@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,2 +1,2 @@
1
1
  $ shipfox-swc
2
- Successfully compiled: 31 files with swc (457.97ms)
2
+ Successfully compiled: 37 files with swc (221.85ms)
package/CHANGELOG.md CHANGED
@@ -1,5 +1,50 @@
1
1
  # @shipfox/client-agent
2
2
 
3
+ ## 6.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 475ce59: Republishes all public packages after restoring release authorization.
8
+ - 3f8f1cb: Enforces typed route-input and browser-storage boundaries across client features.
9
+ - Updated dependencies [475ce59]
10
+ - Updated dependencies [3f8f1cb]
11
+ - @shipfox/api-agent-dto@9.0.1
12
+ - @shipfox/client-api@6.0.1
13
+ - @shipfox/client-shell@6.0.1
14
+ - @shipfox/client-ui@6.0.1
15
+ - @shipfox/react-ui@0.3.6
16
+
17
+ ## 6.0.0
18
+
19
+ ### Major Changes
20
+
21
+ - e009149: Converges Agent model-provider queries and commands on client domain models.
22
+ - 24be269: Makes checked API adapters the only public business-response boundary and returns package-owned domain models from Agent, Integrations, and Workflows adapters.
23
+
24
+ ### Minor Changes
25
+
26
+ - 401b583: Exposes typed feature-owned navigation and settings contributions and enforces coordinator-owned client composition.
27
+
28
+ ### Patch Changes
29
+
30
+ - d784a07: Enforces checked client API responses and removes stale transport compatibility helpers.
31
+ - fa07be9: Enforces client architecture boundaries with Biome plugins and migrates the Agent presentation DTO import.
32
+ - 46aa52f: Closes remaining API package-boundary exceptions and moves model-provider policy behind the Agent implementation boundary.
33
+ - c097dff: Adds an internal domain-model core (harnesses, providers, onboarding and management-modal state) and a DTO-to-domain mapper for model providers, ahead of converging the package's scattered provider/model shapes onto it.
34
+ - Updated dependencies [401b583]
35
+ - Updated dependencies [82eda45]
36
+ - Updated dependencies [cd90c19]
37
+ - Updated dependencies [24be269]
38
+ - Updated dependencies [c56c124]
39
+ - Updated dependencies [46aa52f]
40
+ - Updated dependencies [4a6d124]
41
+ - Updated dependencies [c02ac42]
42
+ - @shipfox/client-shell@6.0.0
43
+ - @shipfox/client-api@6.0.0
44
+ - @shipfox/api-agent-dto@9.0.0
45
+ - @shipfox/client-ui@6.0.0
46
+ - @shipfox/react-ui@0.3.5
47
+
3
48
  ## 5.0.0
4
49
 
5
50
  ### Minor Changes
@@ -1,6 +1,6 @@
1
- import type { ModelProviderCatalogEntryDto } from '@shipfox/api-agent-dto';
1
+ import type { SupportedProvider } from '#core/models.js';
2
2
  export declare function AvailableProviderCard({ entry, onConfigure, }: {
3
- entry: ModelProviderCatalogEntryDto;
3
+ entry: SupportedProvider;
4
4
  onConfigure: () => void;
5
5
  }): import("react").JSX.Element;
6
6
  //# sourceMappingURL=available-provider-card.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"available-provider-card.d.ts","sourceRoot":"","sources":["../../src/components/available-provider-card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,wBAAwB,CAAC;AAQzE,wBAAgB,qBAAqB,CAAC,EACpC,KAAK,EACL,WAAW,GACZ,EAAE;IACD,KAAK,EAAE,4BAA4B,CAAC;IACpC,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB,+BAwBA"}
1
+ {"version":3,"file":"available-provider-card.d.ts","sourceRoot":"","sources":["../../src/components/available-provider-card.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,iBAAiB,CAAC;AAKvD,wBAAgB,qBAAqB,CAAC,EACpC,KAAK,EACL,WAAW,GACZ,EAAE;IACD,KAAK,EAAE,iBAAiB,CAAC;IACzB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB,+BAwBA"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/available-provider-card.tsx"],"sourcesContent":["import type {ModelProviderCatalogEntryDto} from '@shipfox/api-agent-dto';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\n\nconst SURFACE_CLASS =\n 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';\n\nexport function AvailableProviderCard({\n entry,\n onConfigure,\n}: {\n entry: ModelProviderCatalogEntryDto;\n onConfigure: () => void;\n}) {\n return (\n <li>\n <button\n type=\"button\"\n className={cn(\n 'group block w-full cursor-pointer p-16 text-left outline-none transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus',\n SURFACE_CLASS,\n )}\n aria-label={`Configure ${entry.label}`}\n onClick={onConfigure}\n >\n <div className=\"flex min-w-0 items-center justify-between gap-12\">\n <Text size=\"md\" bold className=\"min-w-0 truncate\">\n {entry.label}\n </Text>\n <div className=\"flex shrink-0 items-center gap-4 text-foreground-neutral-muted transition-colors group-hover:text-foreground-highlight-interactive\">\n <Text size=\"sm\">Configure</Text>\n <Icon name=\"chevronRight\" className=\"size-16\" />\n </div>\n </div>\n </button>\n </li>\n );\n}\n"],"names":["Icon","Text","cn","SURFACE_CLASS","AvailableProviderCard","entry","onConfigure","li","button","type","className","aria-label","label","onClick","div","size","bold","name"],"mappings":";AACA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,EAAE,QAAO,0BAA0B;AAE3C,MAAMC,gBACJ;AAEF,OAAO,SAASC,sBAAsB,EACpCC,KAAK,EACLC,WAAW,EAIZ;IACC,qBACE,KAACC;kBACC,cAAA,KAACC;YACCC,MAAK;YACLC,WAAWR,GACT,kKACAC;YAEFQ,cAAY,CAAC,UAAU,EAAEN,MAAMO,KAAK,EAAE;YACtCC,SAASP;sBAET,cAAA,MAACQ;gBAAIJ,WAAU;;kCACb,KAACT;wBAAKc,MAAK;wBAAKC,IAAI;wBAACN,WAAU;kCAC5BL,MAAMO,KAAK;;kCAEd,MAACE;wBAAIJ,WAAU;;0CACb,KAACT;gCAAKc,MAAK;0CAAK;;0CAChB,KAACf;gCAAKiB,MAAK;gCAAeP,WAAU;;;;;;;;AAMhD"}
1
+ {"version":3,"sources":["../../src/components/available-provider-card.tsx"],"sourcesContent":["import {Icon} from '@shipfox/react-ui/icon';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport type {SupportedProvider} from '#core/models.js';\n\nconst SURFACE_CLASS =\n 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';\n\nexport function AvailableProviderCard({\n entry,\n onConfigure,\n}: {\n entry: SupportedProvider;\n onConfigure: () => void;\n}) {\n return (\n <li>\n <button\n type=\"button\"\n className={cn(\n 'group block w-full cursor-pointer p-16 text-left outline-none transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus',\n SURFACE_CLASS,\n )}\n aria-label={`Configure ${entry.label}`}\n onClick={onConfigure}\n >\n <div className=\"flex min-w-0 items-center justify-between gap-12\">\n <Text size=\"md\" bold className=\"min-w-0 truncate\">\n {entry.label}\n </Text>\n <div className=\"flex shrink-0 items-center gap-4 text-foreground-neutral-muted transition-colors group-hover:text-foreground-highlight-interactive\">\n <Text size=\"sm\">Configure</Text>\n <Icon name=\"chevronRight\" className=\"size-16\" />\n </div>\n </div>\n </button>\n </li>\n );\n}\n"],"names":["Icon","Text","cn","SURFACE_CLASS","AvailableProviderCard","entry","onConfigure","li","button","type","className","aria-label","label","onClick","div","size","bold","name"],"mappings":";AAAA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,EAAE,QAAO,0BAA0B;AAG3C,MAAMC,gBACJ;AAEF,OAAO,SAASC,sBAAsB,EACpCC,KAAK,EACLC,WAAW,EAIZ;IACC,qBACE,KAACC;kBACC,cAAA,KAACC;YACCC,MAAK;YACLC,WAAWR,GACT,kKACAC;YAEFQ,cAAY,CAAC,UAAU,EAAEN,MAAMO,KAAK,EAAE;YACtCC,SAASP;sBAET,cAAA,MAACQ;gBAAIJ,WAAU;;kCACb,KAACT;wBAAKc,MAAK;wBAAKC,IAAI;wBAACN,WAAU;kCAC5BL,MAAMO,KAAK;;kCAEd,MAACE;wBAAIJ,WAAU;;0CACb,KAACT;gCAAKc,MAAK;0CAAK;;0CAChB,KAACf;gCAAKiB,MAAK;gCAAeP,WAAU;;;;;;;;AAMhD"}
@@ -1,7 +1,7 @@
1
- import type { ModelProviderCatalogEntryDto } from '@shipfox/api-agent-dto';
2
1
  import type { ReactNode } from 'react';
2
+ import type { SupportedProvider } from '#core/models.js';
3
3
  export declare const PROVIDER_GRID_CLASS = "grid grid-cols-2 gap-12 max-[760px]:grid-cols-1";
4
- export declare function AvailableProvidersGrid<TEntry extends ModelProviderCatalogEntryDto>({ entries, onSelect, trailingCard, trailingCardMatchesSearch, }: {
4
+ export declare function AvailableProvidersGrid<TEntry extends SupportedProvider>({ entries, onSelect, trailingCard, trailingCardMatchesSearch, }: {
5
5
  entries: TEntry[];
6
6
  onSelect: (entry: TEntry) => void;
7
7
  trailingCard?: ReactNode | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"available-providers-grid.d.ts","sourceRoot":"","sources":["../../src/components/available-providers-grid.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,wBAAwB,CAAC;AAKzE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAKrC,eAAO,MAAM,mBAAmB,oDAAoD,CAAC;AAKrF,wBAAgB,sBAAsB,CAAC,MAAM,SAAS,4BAA4B,EAAE,EAClF,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,yBAAsC,GACvC,EAAE;IACD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,YAAY,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACrC,yBAAyB,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CACtE,+BAuDA"}
1
+ {"version":3,"file":"available-providers-grid.d.ts","sourceRoot":"","sources":["../../src/components/available-providers-grid.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAErC,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,iBAAiB,CAAC;AAIvD,eAAO,MAAM,mBAAmB,oDAAoD,CAAC;AAKrF,wBAAgB,sBAAsB,CAAC,MAAM,SAAS,iBAAiB,EAAE,EACvE,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,yBAAsC,GACvC,EAAE;IACD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,YAAY,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACrC,yBAAyB,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CACtE,+BAuDA"}
@@ -4,8 +4,8 @@ import { EmptyState } from '@shipfox/react-ui/empty-state';
4
4
  import { Icon } from '@shipfox/react-ui/icon';
5
5
  import { Input } from '@shipfox/react-ui/input';
6
6
  import { useMemo, useRef, useState } from 'react';
7
+ import { providerMatchesSearch } from '#core/provider-policy.js';
7
8
  import { AvailableProviderCard } from './available-provider-card.js';
8
- import { providerMatchesSearch } from './provider-search.js';
9
9
  export const PROVIDER_GRID_CLASS = 'grid grid-cols-2 gap-12 max-[760px]:grid-cols-1';
10
10
  const SEARCH_VISIBILITY_THRESHOLD = 8;
11
11
  const MAX_ECHOED_QUERY_LENGTH = 40;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/available-providers-grid.tsx"],"sourcesContent":["import type {ModelProviderCatalogEntryDto} from '@shipfox/api-agent-dto';\nimport {Button} from '@shipfox/react-ui/button';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {Input} from '@shipfox/react-ui/input';\nimport type {ReactNode} from 'react';\nimport {useMemo, useRef, useState} from 'react';\nimport {AvailableProviderCard} from './available-provider-card.js';\nimport {providerMatchesSearch} from './provider-search.js';\n\nexport const PROVIDER_GRID_CLASS = 'grid grid-cols-2 gap-12 max-[760px]:grid-cols-1';\n\nconst SEARCH_VISIBILITY_THRESHOLD = 8;\nconst MAX_ECHOED_QUERY_LENGTH = 40;\n\nexport function AvailableProvidersGrid<TEntry extends ModelProviderCatalogEntryDto>({\n entries,\n onSelect,\n trailingCard,\n trailingCardMatchesSearch = () => true,\n}: {\n entries: TEntry[];\n onSelect: (entry: TEntry) => void;\n trailingCard?: ReactNode | undefined;\n trailingCardMatchesSearch?: ((query: string) => boolean) | undefined;\n}) {\n const [search, setSearch] = useState('');\n const inputRef = useRef<HTMLInputElement | null>(null);\n const trimmedSearch = search.trim();\n const filteredEntries = useMemo(\n () => entries.filter((entry) => providerMatchesSearch(entry, search)),\n [entries, search],\n );\n const trailingCardVisible = trailingCard !== undefined && trailingCardMatchesSearch(search);\n const visibleCount = filteredEntries.length + (trailingCardVisible ? 1 : 0);\n const showSearch = entries.length > SEARCH_VISIBILITY_THRESHOLD || trimmedSearch !== '';\n const providerListLabel =\n trimmedSearch !== '' ? 'Available providers matching search' : 'Available providers';\n const resultCountText =\n trimmedSearch === '' ? '' : providerResultCountText(filteredEntries.length, trimmedSearch);\n\n function clearSearch() {\n setSearch('');\n inputRef.current?.focus();\n }\n\n return (\n <div className=\"flex flex-col gap-12\">\n {showSearch ? (\n <Input\n ref={inputRef}\n type=\"search\"\n aria-label=\"Search providers\"\n placeholder=\"Search providers...\"\n value={search}\n iconLeft={<Icon name=\"searchLine\" className=\"size-16 text-foreground-neutral-muted\" />}\n onChange={(event) => setSearch(event.target.value)}\n />\n ) : null}\n\n {visibleCount > 0 ? (\n <ul className={PROVIDER_GRID_CLASS} aria-label={providerListLabel}>\n {filteredEntries.map((entry) => (\n <AvailableProviderCard\n key={entry.id}\n entry={entry}\n onConfigure={() => onSelect(entry)}\n />\n ))}\n {trailingCardVisible ? trailingCard : null}\n </ul>\n ) : (\n <NoProviderSearchResults search={trimmedSearch} onClear={clearSearch} />\n )}\n\n <p role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {resultCountText}\n </p>\n </div>\n );\n}\n\nfunction NoProviderSearchResults({search, onClear}: {search: string; onClear: () => void}) {\n return (\n <EmptyState\n icon=\"searchLine\"\n title={`No providers match \"${truncateQuery(search)}\"`}\n description=\"Try a different search, or clear it to see all providers.\"\n action={\n <Button size=\"sm\" variant=\"secondary\" onClick={onClear}>\n Clear search\n </Button>\n }\n />\n );\n}\n\nfunction truncateQuery(query: string): string {\n if (query.length <= MAX_ECHOED_QUERY_LENGTH) return query;\n return `${query.slice(0, MAX_ECHOED_QUERY_LENGTH - 3)}...`;\n}\n\nfunction providerResultCountText(count: number, query: string): string {\n if (count === 1) return `1 provider matches \"${query}\"`;\n return `${count} providers match \"${query}\"`;\n}\n"],"names":["Button","EmptyState","Icon","Input","useMemo","useRef","useState","AvailableProviderCard","providerMatchesSearch","PROVIDER_GRID_CLASS","SEARCH_VISIBILITY_THRESHOLD","MAX_ECHOED_QUERY_LENGTH","AvailableProvidersGrid","entries","onSelect","trailingCard","trailingCardMatchesSearch","search","setSearch","inputRef","trimmedSearch","trim","filteredEntries","filter","entry","trailingCardVisible","undefined","visibleCount","length","showSearch","providerListLabel","resultCountText","providerResultCountText","clearSearch","current","focus","div","className","ref","type","aria-label","placeholder","value","iconLeft","name","onChange","event","target","ul","map","onConfigure","id","NoProviderSearchResults","onClear","p","role","aria-live","icon","title","truncateQuery","description","action","size","variant","onClick","query","slice","count"],"mappings":";AACA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SAAQC,UAAU,QAAO,gCAAgC;AACzD,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,KAAK,QAAO,0BAA0B;AAE9C,SAAQC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAO,QAAQ;AAChD,SAAQC,qBAAqB,QAAO,+BAA+B;AACnE,SAAQC,qBAAqB,QAAO,uBAAuB;AAE3D,OAAO,MAAMC,sBAAsB,kDAAkD;AAErF,MAAMC,8BAA8B;AACpC,MAAMC,0BAA0B;AAEhC,OAAO,SAASC,uBAAoE,EAClFC,OAAO,EACPC,QAAQ,EACRC,YAAY,EACZC,4BAA4B,IAAM,IAAI,EAMvC;IACC,MAAM,CAACC,QAAQC,UAAU,GAAGZ,SAAS;IACrC,MAAMa,WAAWd,OAAgC;IACjD,MAAMe,gBAAgBH,OAAOI,IAAI;IACjC,MAAMC,kBAAkBlB,QACtB,IAAMS,QAAQU,MAAM,CAAC,CAACC,QAAUhB,sBAAsBgB,OAAOP,UAC7D;QAACJ;QAASI;KAAO;IAEnB,MAAMQ,sBAAsBV,iBAAiBW,aAAaV,0BAA0BC;IACpF,MAAMU,eAAeL,gBAAgBM,MAAM,GAAIH,CAAAA,sBAAsB,IAAI,CAAA;IACzE,MAAMI,aAAahB,QAAQe,MAAM,GAAGlB,+BAA+BU,kBAAkB;IACrF,MAAMU,oBACJV,kBAAkB,KAAK,wCAAwC;IACjE,MAAMW,kBACJX,kBAAkB,KAAK,KAAKY,wBAAwBV,gBAAgBM,MAAM,EAAER;IAE9E,SAASa;QACPf,UAAU;QACVC,SAASe,OAAO,EAAEC;IACpB;IAEA,qBACE,MAACC;QAAIC,WAAU;;YACZR,2BACC,KAAC1B;gBACCmC,KAAKnB;gBACLoB,MAAK;gBACLC,cAAW;gBACXC,aAAY;gBACZC,OAAOzB;gBACP0B,wBAAU,KAACzC;oBAAK0C,MAAK;oBAAaP,WAAU;;gBAC5CQ,UAAU,CAACC,QAAU5B,UAAU4B,MAAMC,MAAM,CAACL,KAAK;iBAEjD;YAEHf,eAAe,kBACd,MAACqB;gBAAGX,WAAW5B;gBAAqB+B,cAAYV;;oBAC7CR,gBAAgB2B,GAAG,CAAC,CAACzB,sBACpB,KAACjB;4BAECiB,OAAOA;4BACP0B,aAAa,IAAMpC,SAASU;2BAFvBA,MAAM2B,EAAE;oBAKhB1B,sBAAsBV,eAAe;;+BAGxC,KAACqC;gBAAwBnC,QAAQG;gBAAeiC,SAASpB;;0BAG3D,KAACqB;gBAAEC,MAAK;gBAASC,aAAU;gBAASnB,WAAU;0BAC3CN;;;;AAIT;AAEA,SAASqB,wBAAwB,EAACnC,MAAM,EAAEoC,OAAO,EAAwC;IACvF,qBACE,KAACpD;QACCwD,MAAK;QACLC,OAAO,CAAC,oBAAoB,EAAEC,cAAc1C,QAAQ,CAAC,CAAC;QACtD2C,aAAY;QACZC,sBACE,KAAC7D;YAAO8D,MAAK;YAAKC,SAAQ;YAAYC,SAASX;sBAAS;;;AAMhE;AAEA,SAASM,cAAcM,KAAa;IAClC,IAAIA,MAAMrC,MAAM,IAAIjB,yBAAyB,OAAOsD;IACpD,OAAO,GAAGA,MAAMC,KAAK,CAAC,GAAGvD,0BAA0B,GAAG,GAAG,CAAC;AAC5D;AAEA,SAASqB,wBAAwBmC,KAAa,EAAEF,KAAa;IAC3D,IAAIE,UAAU,GAAG,OAAO,CAAC,oBAAoB,EAAEF,MAAM,CAAC,CAAC;IACvD,OAAO,GAAGE,MAAM,kBAAkB,EAAEF,MAAM,CAAC,CAAC;AAC9C"}
1
+ {"version":3,"sources":["../../src/components/available-providers-grid.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {Input} from '@shipfox/react-ui/input';\nimport type {ReactNode} from 'react';\nimport {useMemo, useRef, useState} from 'react';\nimport type {SupportedProvider} from '#core/models.js';\nimport {providerMatchesSearch} from '#core/provider-policy.js';\nimport {AvailableProviderCard} from './available-provider-card.js';\n\nexport const PROVIDER_GRID_CLASS = 'grid grid-cols-2 gap-12 max-[760px]:grid-cols-1';\n\nconst SEARCH_VISIBILITY_THRESHOLD = 8;\nconst MAX_ECHOED_QUERY_LENGTH = 40;\n\nexport function AvailableProvidersGrid<TEntry extends SupportedProvider>({\n entries,\n onSelect,\n trailingCard,\n trailingCardMatchesSearch = () => true,\n}: {\n entries: TEntry[];\n onSelect: (entry: TEntry) => void;\n trailingCard?: ReactNode | undefined;\n trailingCardMatchesSearch?: ((query: string) => boolean) | undefined;\n}) {\n const [search, setSearch] = useState('');\n const inputRef = useRef<HTMLInputElement | null>(null);\n const trimmedSearch = search.trim();\n const filteredEntries = useMemo(\n () => entries.filter((entry) => providerMatchesSearch(entry, search)),\n [entries, search],\n );\n const trailingCardVisible = trailingCard !== undefined && trailingCardMatchesSearch(search);\n const visibleCount = filteredEntries.length + (trailingCardVisible ? 1 : 0);\n const showSearch = entries.length > SEARCH_VISIBILITY_THRESHOLD || trimmedSearch !== '';\n const providerListLabel =\n trimmedSearch !== '' ? 'Available providers matching search' : 'Available providers';\n const resultCountText =\n trimmedSearch === '' ? '' : providerResultCountText(filteredEntries.length, trimmedSearch);\n\n function clearSearch() {\n setSearch('');\n inputRef.current?.focus();\n }\n\n return (\n <div className=\"flex flex-col gap-12\">\n {showSearch ? (\n <Input\n ref={inputRef}\n type=\"search\"\n aria-label=\"Search providers\"\n placeholder=\"Search providers...\"\n value={search}\n iconLeft={<Icon name=\"searchLine\" className=\"size-16 text-foreground-neutral-muted\" />}\n onChange={(event) => setSearch(event.target.value)}\n />\n ) : null}\n\n {visibleCount > 0 ? (\n <ul className={PROVIDER_GRID_CLASS} aria-label={providerListLabel}>\n {filteredEntries.map((entry) => (\n <AvailableProviderCard\n key={entry.id}\n entry={entry}\n onConfigure={() => onSelect(entry)}\n />\n ))}\n {trailingCardVisible ? trailingCard : null}\n </ul>\n ) : (\n <NoProviderSearchResults search={trimmedSearch} onClear={clearSearch} />\n )}\n\n <p role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {resultCountText}\n </p>\n </div>\n );\n}\n\nfunction NoProviderSearchResults({search, onClear}: {search: string; onClear: () => void}) {\n return (\n <EmptyState\n icon=\"searchLine\"\n title={`No providers match \"${truncateQuery(search)}\"`}\n description=\"Try a different search, or clear it to see all providers.\"\n action={\n <Button size=\"sm\" variant=\"secondary\" onClick={onClear}>\n Clear search\n </Button>\n }\n />\n );\n}\n\nfunction truncateQuery(query: string): string {\n if (query.length <= MAX_ECHOED_QUERY_LENGTH) return query;\n return `${query.slice(0, MAX_ECHOED_QUERY_LENGTH - 3)}...`;\n}\n\nfunction providerResultCountText(count: number, query: string): string {\n if (count === 1) return `1 provider matches \"${query}\"`;\n return `${count} providers match \"${query}\"`;\n}\n"],"names":["Button","EmptyState","Icon","Input","useMemo","useRef","useState","providerMatchesSearch","AvailableProviderCard","PROVIDER_GRID_CLASS","SEARCH_VISIBILITY_THRESHOLD","MAX_ECHOED_QUERY_LENGTH","AvailableProvidersGrid","entries","onSelect","trailingCard","trailingCardMatchesSearch","search","setSearch","inputRef","trimmedSearch","trim","filteredEntries","filter","entry","trailingCardVisible","undefined","visibleCount","length","showSearch","providerListLabel","resultCountText","providerResultCountText","clearSearch","current","focus","div","className","ref","type","aria-label","placeholder","value","iconLeft","name","onChange","event","target","ul","map","onConfigure","id","NoProviderSearchResults","onClear","p","role","aria-live","icon","title","truncateQuery","description","action","size","variant","onClick","query","slice","count"],"mappings":";AAAA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SAAQC,UAAU,QAAO,gCAAgC;AACzD,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,KAAK,QAAO,0BAA0B;AAE9C,SAAQC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAO,QAAQ;AAEhD,SAAQC,qBAAqB,QAAO,2BAA2B;AAC/D,SAAQC,qBAAqB,QAAO,+BAA+B;AAEnE,OAAO,MAAMC,sBAAsB,kDAAkD;AAErF,MAAMC,8BAA8B;AACpC,MAAMC,0BAA0B;AAEhC,OAAO,SAASC,uBAAyD,EACvEC,OAAO,EACPC,QAAQ,EACRC,YAAY,EACZC,4BAA4B,IAAM,IAAI,EAMvC;IACC,MAAM,CAACC,QAAQC,UAAU,GAAGZ,SAAS;IACrC,MAAMa,WAAWd,OAAgC;IACjD,MAAMe,gBAAgBH,OAAOI,IAAI;IACjC,MAAMC,kBAAkBlB,QACtB,IAAMS,QAAQU,MAAM,CAAC,CAACC,QAAUjB,sBAAsBiB,OAAOP,UAC7D;QAACJ;QAASI;KAAO;IAEnB,MAAMQ,sBAAsBV,iBAAiBW,aAAaV,0BAA0BC;IACpF,MAAMU,eAAeL,gBAAgBM,MAAM,GAAIH,CAAAA,sBAAsB,IAAI,CAAA;IACzE,MAAMI,aAAahB,QAAQe,MAAM,GAAGlB,+BAA+BU,kBAAkB;IACrF,MAAMU,oBACJV,kBAAkB,KAAK,wCAAwC;IACjE,MAAMW,kBACJX,kBAAkB,KAAK,KAAKY,wBAAwBV,gBAAgBM,MAAM,EAAER;IAE9E,SAASa;QACPf,UAAU;QACVC,SAASe,OAAO,EAAEC;IACpB;IAEA,qBACE,MAACC;QAAIC,WAAU;;YACZR,2BACC,KAAC1B;gBACCmC,KAAKnB;gBACLoB,MAAK;gBACLC,cAAW;gBACXC,aAAY;gBACZC,OAAOzB;gBACP0B,wBAAU,KAACzC;oBAAK0C,MAAK;oBAAaP,WAAU;;gBAC5CQ,UAAU,CAACC,QAAU5B,UAAU4B,MAAMC,MAAM,CAACL,KAAK;iBAEjD;YAEHf,eAAe,kBACd,MAACqB;gBAAGX,WAAW5B;gBAAqB+B,cAAYV;;oBAC7CR,gBAAgB2B,GAAG,CAAC,CAACzB,sBACpB,KAAChB;4BAECgB,OAAOA;4BACP0B,aAAa,IAAMpC,SAASU;2BAFvBA,MAAM2B,EAAE;oBAKhB1B,sBAAsBV,eAAe;;+BAGxC,KAACqC;gBAAwBnC,QAAQG;gBAAeiC,SAASpB;;0BAG3D,KAACqB;gBAAEC,MAAK;gBAASC,aAAU;gBAASnB,WAAU;0BAC3CN;;;;AAIT;AAEA,SAASqB,wBAAwB,EAACnC,MAAM,EAAEoC,OAAO,EAAwC;IACvF,qBACE,KAACpD;QACCwD,MAAK;QACLC,OAAO,CAAC,oBAAoB,EAAEC,cAAc1C,QAAQ,CAAC,CAAC;QACtD2C,aAAY;QACZC,sBACE,KAAC7D;YAAO8D,MAAK;YAAKC,SAAQ;YAAYC,SAASX;sBAAS;;;AAMhE;AAEA,SAASM,cAAcM,KAAa;IAClC,IAAIA,MAAMrC,MAAM,IAAIjB,yBAAyB,OAAOsD;IACpD,OAAO,GAAGA,MAAMC,KAAK,CAAC,GAAGvD,0BAA0B,GAAG,GAAG,CAAC;AAC5D;AAEA,SAASqB,wBAAwBmC,KAAa,EAAEF,KAAa;IAC3D,IAAIE,UAAU,GAAG,OAAO,CAAC,oBAAoB,EAAEF,MAAM,CAAC,CAAC;IACvD,OAAO,GAAGE,MAAM,kBAAkB,EAAEF,MAAM,CAAC,CAAC;AAC9C"}
@@ -1,9 +1,8 @@
1
- import type { ModelProviderConfigDto } from '@shipfox/api-agent-dto';
2
- import type { SupportedModelProviderCatalogEntry } from './supported-model-provider-catalog-entry.js';
1
+ import type { BuiltinProviderConfig, SupportedProvider } from '#core/models.js';
3
2
  export declare function ChangeDefaultModelForm({ workspaceId, entry, config, onSaved, }: {
4
3
  workspaceId: string;
5
- entry: SupportedModelProviderCatalogEntry;
6
- config: ModelProviderConfigDto;
4
+ entry: SupportedProvider;
5
+ config: BuiltinProviderConfig;
7
6
  onSaved: () => void;
8
7
  }): import("react").JSX.Element;
9
8
  //# sourceMappingURL=change-default-model-form.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"change-default-model-form.d.ts","sourceRoot":"","sources":["../../src/components/change-default-model-form.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,wBAAwB,CAAC;AAenE,OAAO,KAAK,EAAC,kCAAkC,EAAC,MAAM,6CAA6C,CAAC;AAIpG,wBAAgB,sBAAsB,CAAC,EACrC,WAAW,EACX,KAAK,EACL,MAAM,EACN,OAAO,GACR,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,kCAAkC,CAAC;IAC1C,MAAM,EAAE,sBAAsB,CAAC;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,+BA0EA"}
1
+ {"version":3,"file":"change-default-model-form.d.ts","sourceRoot":"","sources":["../../src/components/change-default-model-form.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,qBAAqB,EAAE,iBAAiB,EAAC,MAAM,iBAAiB,CAAC;AAW9E,wBAAgB,sBAAsB,CAAC,EACrC,WAAW,EACX,KAAK,EACL,MAAM,EACN,OAAO,GACR,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,iBAAiB,CAAC;IACzB,MAAM,EAAE,qBAAqB,CAAC;IAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,+BA0EA"}
@@ -15,7 +15,7 @@ export function ChangeDefaultModelForm({ workspaceId, entry, config, onSaved })
15
15
  const [formError, setFormError] = useState();
16
16
  const form = useForm({
17
17
  defaultValues: {
18
- default_model: defaultModelFormValue(config.default_model)
18
+ default_model: defaultModelFormValue(config.defaultModel)
19
19
  },
20
20
  onSubmit: async ({ value })=>{
21
21
  setFormError(undefined);
@@ -23,9 +23,7 @@ export function ChangeDefaultModelForm({ workspaceId, entry, config, onSaved })
23
23
  await updateDefaultModel.mutateAsync({
24
24
  workspaceId,
25
25
  providerId: entry.id,
26
- body: {
27
- default_model: selectedModelForModelPayload(value.default_model)
28
- }
26
+ defaultModel: selectedModelForModelPayload(value.default_model)
29
27
  });
30
28
  onSaved();
31
29
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/change-default-model-form.tsx"],"sourcesContent":["import type {ModelProviderConfigDto} from '@shipfox/api-agent-dto';\nimport {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {fieldError} from '@shipfox/react-ui/form-field';\nimport {ModalBody, ModalFooter} from '@shipfox/react-ui/modal';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {useForm} from '@tanstack/react-form';\nimport {useState} from 'react';\nimport {useUpdateModelProviderDefaultModelMutation} from '#hooks/api/model-providers.js';\nimport {\n DefaultModelField,\n defaultModelFormValue,\n selectedModelForModelPayload,\n} from './default-model-field.js';\nimport {modelProviderConfigErrorToFormError} from './form-errors.js';\nimport type {SupportedModelProviderCatalogEntry} from './supported-model-provider-catalog-entry.js';\n\nconst CHANGE_DEFAULT_MODEL_FORM_ID = 'model-provider-change-default-model-form';\n\nexport function ChangeDefaultModelForm({\n workspaceId,\n entry,\n config,\n onSaved,\n}: {\n workspaceId: string;\n entry: SupportedModelProviderCatalogEntry;\n config: ModelProviderConfigDto;\n onSaved: () => void;\n}) {\n const updateDefaultModel = useUpdateModelProviderDefaultModelMutation();\n const [formError, setFormError] = useState<string | undefined>();\n const form = useForm({\n defaultValues: {default_model: defaultModelFormValue(config.default_model)},\n onSubmit: async ({value}) => {\n setFormError(undefined);\n try {\n await updateDefaultModel.mutateAsync({\n workspaceId,\n providerId: entry.id,\n body: {default_model: selectedModelForModelPayload(value.default_model)},\n });\n onSaved();\n } catch (error) {\n const mapped = modelProviderConfigErrorToFormError(error);\n setFormError(mapped.message);\n }\n },\n });\n\n return (\n <>\n <ModalBody className=\"gap-16\">\n <form\n id={CHANGE_DEFAULT_MODEL_FORM_ID}\n className=\"flex w-full flex-col gap-14\"\n noValidate\n onSubmit={(event) => {\n event.preventDefault();\n event.stopPropagation();\n void form.handleSubmit();\n }}\n >\n <form.Field\n name=\"default_model\"\n validators={{\n onBlur: ({value}) => (value.trim() ? undefined : 'Default model is required.'),\n onSubmit: ({value}) => (value.trim() ? undefined : 'Default model is required.'),\n }}\n >\n {(field) => (\n <DefaultModelField\n entry={entry}\n value={field.state.value}\n error={fieldError(field)}\n onChange={(event) => field.handleChange(event.target.value)}\n onBlur={field.handleBlur}\n />\n )}\n </form.Field>\n </form>\n {formError ? (\n <Callout role=\"alert\" type=\"error\">\n <div className=\"flex flex-col gap-8\">\n <Text size=\"sm\" bold>\n Could not save default model\n </Text>\n <Text size=\"sm\">{formError}</Text>\n </div>\n </Callout>\n ) : null}\n </ModalBody>\n <ModalFooter>\n <Button\n type=\"submit\"\n form={CHANGE_DEFAULT_MODEL_FORM_ID}\n isLoading={updateDefaultModel.isPending}\n >\n Save model\n </Button>\n </ModalFooter>\n </>\n );\n}\n"],"names":["Button","Callout","fieldError","ModalBody","ModalFooter","Text","useForm","useState","useUpdateModelProviderDefaultModelMutation","DefaultModelField","defaultModelFormValue","selectedModelForModelPayload","modelProviderConfigErrorToFormError","CHANGE_DEFAULT_MODEL_FORM_ID","ChangeDefaultModelForm","workspaceId","entry","config","onSaved","updateDefaultModel","formError","setFormError","form","defaultValues","default_model","onSubmit","value","undefined","mutateAsync","providerId","id","body","error","mapped","message","className","noValidate","event","preventDefault","stopPropagation","handleSubmit","Field","name","validators","onBlur","trim","field","state","onChange","handleChange","target","handleBlur","role","type","div","size","bold","isLoading","isPending"],"mappings":";AACA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SAAQC,OAAO,QAAO,4BAA4B;AAClD,SAAQC,UAAU,QAAO,+BAA+B;AACxD,SAAQC,SAAS,EAAEC,WAAW,QAAO,0BAA0B;AAC/D,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,OAAO,QAAO,uBAAuB;AAC7C,SAAQC,QAAQ,QAAO,QAAQ;AAC/B,SAAQC,0CAA0C,QAAO,gCAAgC;AACzF,SACEC,iBAAiB,EACjBC,qBAAqB,EACrBC,4BAA4B,QACvB,2BAA2B;AAClC,SAAQC,mCAAmC,QAAO,mBAAmB;AAGrE,MAAMC,+BAA+B;AAErC,OAAO,SAASC,uBAAuB,EACrCC,WAAW,EACXC,KAAK,EACLC,MAAM,EACNC,OAAO,EAMR;IACC,MAAMC,qBAAqBX;IAC3B,MAAM,CAACY,WAAWC,aAAa,GAAGd;IAClC,MAAMe,OAAOhB,QAAQ;QACnBiB,eAAe;YAACC,eAAed,sBAAsBO,OAAOO,aAAa;QAAC;QAC1EC,UAAU,OAAO,EAACC,KAAK,EAAC;YACtBL,aAAaM;YACb,IAAI;gBACF,MAAMR,mBAAmBS,WAAW,CAAC;oBACnCb;oBACAc,YAAYb,MAAMc,EAAE;oBACpBC,MAAM;wBAACP,eAAeb,6BAA6Be,MAAMF,aAAa;oBAAC;gBACzE;gBACAN;YACF,EAAE,OAAOc,OAAO;gBACd,MAAMC,SAASrB,oCAAoCoB;gBACnDX,aAAaY,OAAOC,OAAO;YAC7B;QACF;IACF;IAEA,qBACE;;0BACE,MAAC/B;gBAAUgC,WAAU;;kCACnB,KAACb;wBACCQ,IAAIjB;wBACJsB,WAAU;wBACVC,UAAU;wBACVX,UAAU,CAACY;4BACTA,MAAMC,cAAc;4BACpBD,MAAME,eAAe;4BACrB,KAAKjB,KAAKkB,YAAY;wBACxB;kCAEA,cAAA,KAAClB,KAAKmB,KAAK;4BACTC,MAAK;4BACLC,YAAY;gCACVC,QAAQ,CAAC,EAAClB,KAAK,EAAC,GAAMA,MAAMmB,IAAI,KAAKlB,YAAY;gCACjDF,UAAU,CAAC,EAACC,KAAK,EAAC,GAAMA,MAAMmB,IAAI,KAAKlB,YAAY;4BACrD;sCAEC,CAACmB,sBACA,KAACrC;oCACCO,OAAOA;oCACPU,OAAOoB,MAAMC,KAAK,CAACrB,KAAK;oCACxBM,OAAO9B,WAAW4C;oCAClBE,UAAU,CAACX,QAAUS,MAAMG,YAAY,CAACZ,MAAMa,MAAM,CAACxB,KAAK;oCAC1DkB,QAAQE,MAAMK,UAAU;;;;oBAK/B/B,0BACC,KAACnB;wBAAQmD,MAAK;wBAAQC,MAAK;kCACzB,cAAA,MAACC;4BAAInB,WAAU;;8CACb,KAAC9B;oCAAKkD,MAAK;oCAAKC,IAAI;8CAAC;;8CAGrB,KAACnD;oCAAKkD,MAAK;8CAAMnC;;;;yBAGnB;;;0BAEN,KAAChB;0BACC,cAAA,KAACJ;oBACCqD,MAAK;oBACL/B,MAAMT;oBACN4C,WAAWtC,mBAAmBuC,SAAS;8BACxC;;;;;AAMT"}
1
+ {"version":3,"sources":["../../src/components/change-default-model-form.tsx"],"sourcesContent":["import {Button} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {fieldError} from '@shipfox/react-ui/form-field';\nimport {ModalBody, ModalFooter} from '@shipfox/react-ui/modal';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {useForm} from '@tanstack/react-form';\nimport {useState} from 'react';\nimport type {BuiltinProviderConfig, SupportedProvider} from '#core/models.js';\nimport {useUpdateModelProviderDefaultModelMutation} from '#hooks/api/model-providers.js';\nimport {\n DefaultModelField,\n defaultModelFormValue,\n selectedModelForModelPayload,\n} from './default-model-field.js';\nimport {modelProviderConfigErrorToFormError} from './form-errors.js';\n\nconst CHANGE_DEFAULT_MODEL_FORM_ID = 'model-provider-change-default-model-form';\n\nexport function ChangeDefaultModelForm({\n workspaceId,\n entry,\n config,\n onSaved,\n}: {\n workspaceId: string;\n entry: SupportedProvider;\n config: BuiltinProviderConfig;\n onSaved: () => void;\n}) {\n const updateDefaultModel = useUpdateModelProviderDefaultModelMutation();\n const [formError, setFormError] = useState<string | undefined>();\n const form = useForm({\n defaultValues: {default_model: defaultModelFormValue(config.defaultModel)},\n onSubmit: async ({value}) => {\n setFormError(undefined);\n try {\n await updateDefaultModel.mutateAsync({\n workspaceId,\n providerId: entry.id,\n defaultModel: selectedModelForModelPayload(value.default_model),\n });\n onSaved();\n } catch (error) {\n const mapped = modelProviderConfigErrorToFormError(error);\n setFormError(mapped.message);\n }\n },\n });\n\n return (\n <>\n <ModalBody className=\"gap-16\">\n <form\n id={CHANGE_DEFAULT_MODEL_FORM_ID}\n className=\"flex w-full flex-col gap-14\"\n noValidate\n onSubmit={(event) => {\n event.preventDefault();\n event.stopPropagation();\n void form.handleSubmit();\n }}\n >\n <form.Field\n name=\"default_model\"\n validators={{\n onBlur: ({value}) => (value.trim() ? undefined : 'Default model is required.'),\n onSubmit: ({value}) => (value.trim() ? undefined : 'Default model is required.'),\n }}\n >\n {(field) => (\n <DefaultModelField\n entry={entry}\n value={field.state.value}\n error={fieldError(field)}\n onChange={(event) => field.handleChange(event.target.value)}\n onBlur={field.handleBlur}\n />\n )}\n </form.Field>\n </form>\n {formError ? (\n <Callout role=\"alert\" type=\"error\">\n <div className=\"flex flex-col gap-8\">\n <Text size=\"sm\" bold>\n Could not save default model\n </Text>\n <Text size=\"sm\">{formError}</Text>\n </div>\n </Callout>\n ) : null}\n </ModalBody>\n <ModalFooter>\n <Button\n type=\"submit\"\n form={CHANGE_DEFAULT_MODEL_FORM_ID}\n isLoading={updateDefaultModel.isPending}\n >\n Save model\n </Button>\n </ModalFooter>\n </>\n );\n}\n"],"names":["Button","Callout","fieldError","ModalBody","ModalFooter","Text","useForm","useState","useUpdateModelProviderDefaultModelMutation","DefaultModelField","defaultModelFormValue","selectedModelForModelPayload","modelProviderConfigErrorToFormError","CHANGE_DEFAULT_MODEL_FORM_ID","ChangeDefaultModelForm","workspaceId","entry","config","onSaved","updateDefaultModel","formError","setFormError","form","defaultValues","default_model","defaultModel","onSubmit","value","undefined","mutateAsync","providerId","id","error","mapped","message","className","noValidate","event","preventDefault","stopPropagation","handleSubmit","Field","name","validators","onBlur","trim","field","state","onChange","handleChange","target","handleBlur","role","type","div","size","bold","isLoading","isPending"],"mappings":";AAAA,SAAQA,MAAM,QAAO,2BAA2B;AAChD,SAAQC,OAAO,QAAO,4BAA4B;AAClD,SAAQC,UAAU,QAAO,+BAA+B;AACxD,SAAQC,SAAS,EAAEC,WAAW,QAAO,0BAA0B;AAC/D,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,OAAO,QAAO,uBAAuB;AAC7C,SAAQC,QAAQ,QAAO,QAAQ;AAE/B,SAAQC,0CAA0C,QAAO,gCAAgC;AACzF,SACEC,iBAAiB,EACjBC,qBAAqB,EACrBC,4BAA4B,QACvB,2BAA2B;AAClC,SAAQC,mCAAmC,QAAO,mBAAmB;AAErE,MAAMC,+BAA+B;AAErC,OAAO,SAASC,uBAAuB,EACrCC,WAAW,EACXC,KAAK,EACLC,MAAM,EACNC,OAAO,EAMR;IACC,MAAMC,qBAAqBX;IAC3B,MAAM,CAACY,WAAWC,aAAa,GAAGd;IAClC,MAAMe,OAAOhB,QAAQ;QACnBiB,eAAe;YAACC,eAAed,sBAAsBO,OAAOQ,YAAY;QAAC;QACzEC,UAAU,OAAO,EAACC,KAAK,EAAC;YACtBN,aAAaO;YACb,IAAI;gBACF,MAAMT,mBAAmBU,WAAW,CAAC;oBACnCd;oBACAe,YAAYd,MAAMe,EAAE;oBACpBN,cAAcd,6BAA6BgB,MAAMH,aAAa;gBAChE;gBACAN;YACF,EAAE,OAAOc,OAAO;gBACd,MAAMC,SAASrB,oCAAoCoB;gBACnDX,aAAaY,OAAOC,OAAO;YAC7B;QACF;IACF;IAEA,qBACE;;0BACE,MAAC/B;gBAAUgC,WAAU;;kCACnB,KAACb;wBACCS,IAAIlB;wBACJsB,WAAU;wBACVC,UAAU;wBACVV,UAAU,CAACW;4BACTA,MAAMC,cAAc;4BACpBD,MAAME,eAAe;4BACrB,KAAKjB,KAAKkB,YAAY;wBACxB;kCAEA,cAAA,KAAClB,KAAKmB,KAAK;4BACTC,MAAK;4BACLC,YAAY;gCACVC,QAAQ,CAAC,EAACjB,KAAK,EAAC,GAAMA,MAAMkB,IAAI,KAAKjB,YAAY;gCACjDF,UAAU,CAAC,EAACC,KAAK,EAAC,GAAMA,MAAMkB,IAAI,KAAKjB,YAAY;4BACrD;sCAEC,CAACkB,sBACA,KAACrC;oCACCO,OAAOA;oCACPW,OAAOmB,MAAMC,KAAK,CAACpB,KAAK;oCACxBK,OAAO9B,WAAW4C;oCAClBE,UAAU,CAACX,QAAUS,MAAMG,YAAY,CAACZ,MAAMa,MAAM,CAACvB,KAAK;oCAC1DiB,QAAQE,MAAMK,UAAU;;;;oBAK/B/B,0BACC,KAACnB;wBAAQmD,MAAK;wBAAQC,MAAK;kCACzB,cAAA,MAACC;4BAAInB,WAAU;;8CACb,KAAC9B;oCAAKkD,MAAK;oCAAKC,IAAI;8CAAC;;8CAGrB,KAACnD;oCAAKkD,MAAK;8CAAMnC;;;;yBAGnB;;;0BAEN,KAAChB;0BACC,cAAA,KAACJ;oBACCqD,MAAK;oBACL/B,MAAMT;oBACN4C,WAAWtC,mBAAmBuC,SAAS;8BACxC;;;;;AAMT"}
@@ -1,7 +1,7 @@
1
- import type { ModelProviderApi } from '@shipfox/api-agent-dto';
1
+ import type { ProviderApi } from '#core/models.js';
2
2
  export declare const MODEL_PROVIDER_API_OPTIONS: Array<{
3
- value: ModelProviderApi;
3
+ value: ProviderApi;
4
4
  label: string;
5
5
  }>;
6
- export declare function modelProviderApiLabel(api: ModelProviderApi): string;
6
+ export declare function modelProviderApiLabel(api: ProviderApi): string;
7
7
  //# sourceMappingURL=custom-model-provider-api-options.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-model-provider-api-options.d.ts","sourceRoot":"","sources":["../../src/components/custom-model-provider-api-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,wBAAwB,CAAC;AAE7D,eAAO,MAAM,0BAA0B,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAKtF,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,GAAG,MAAM,CAEnE"}
1
+ {"version":3,"file":"custom-model-provider-api-options.d.ts","sourceRoot":"","sources":["../../src/components/custom-model-provider-api-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,iBAAiB,CAAC;AAEjD,eAAO,MAAM,0BAA0B,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAKjF,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAE9D"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/custom-model-provider-api-options.ts"],"sourcesContent":["import type {ModelProviderApi} from '@shipfox/api-agent-dto';\n\nexport const MODEL_PROVIDER_API_OPTIONS: Array<{value: ModelProviderApi; label: string}> = [\n {value: 'openai-completions', label: 'OpenAI Chat Completions'},\n {value: 'openai-responses', label: 'OpenAI Responses'},\n {value: 'anthropic-messages', label: 'Anthropic Messages'},\n {value: 'google-generative-ai', label: 'Google Generative AI'},\n];\n\nexport function modelProviderApiLabel(api: ModelProviderApi): string {\n return MODEL_PROVIDER_API_OPTIONS.find((option) => option.value === api)?.label ?? api;\n}\n"],"names":["MODEL_PROVIDER_API_OPTIONS","value","label","modelProviderApiLabel","api","find","option"],"mappings":"AAEA,OAAO,MAAMA,6BAA8E;IACzF;QAACC,OAAO;QAAsBC,OAAO;IAAyB;IAC9D;QAACD,OAAO;QAAoBC,OAAO;IAAkB;IACrD;QAACD,OAAO;QAAsBC,OAAO;IAAoB;IACzD;QAACD,OAAO;QAAwBC,OAAO;IAAsB;CAC9D,CAAC;AAEF,OAAO,SAASC,sBAAsBC,GAAqB;IACzD,OAAOJ,2BAA2BK,IAAI,CAAC,CAACC,SAAWA,OAAOL,KAAK,KAAKG,MAAMF,SAASE;AACrF"}
1
+ {"version":3,"sources":["../../src/components/custom-model-provider-api-options.ts"],"sourcesContent":["import type {ProviderApi} from '#core/models.js';\n\nexport const MODEL_PROVIDER_API_OPTIONS: Array<{value: ProviderApi; label: string}> = [\n {value: 'openai-completions', label: 'OpenAI Chat Completions'},\n {value: 'openai-responses', label: 'OpenAI Responses'},\n {value: 'anthropic-messages', label: 'Anthropic Messages'},\n {value: 'google-generative-ai', label: 'Google Generative AI'},\n];\n\nexport function modelProviderApiLabel(api: ProviderApi): string {\n return MODEL_PROVIDER_API_OPTIONS.find((option) => option.value === api)?.label ?? api;\n}\n"],"names":["MODEL_PROVIDER_API_OPTIONS","value","label","modelProviderApiLabel","api","find","option"],"mappings":"AAEA,OAAO,MAAMA,6BAAyE;IACpF;QAACC,OAAO;QAAsBC,OAAO;IAAyB;IAC9D;QAACD,OAAO;QAAoBC,OAAO;IAAkB;IACrD;QAACD,OAAO;QAAsBC,OAAO;IAAoB;IACzD;QAACD,OAAO;QAAwBC,OAAO;IAAsB;CAC9D,CAAC;AAEF,OAAO,SAASC,sBAAsBC,GAAgB;IACpD,OAAOJ,2BAA2BK,IAAI,CAAC,CAACC,SAAWA,OAAOL,KAAK,KAAKG,MAAMF,SAASE;AACrF"}
@@ -1,8 +1,8 @@
1
- import type { CustomModelProviderConfigDto } from '@shipfox/api-agent-dto';
1
+ import type { CustomProviderConfig } from '#core/models.js';
2
2
  export declare const CUSTOM_MODEL_PROVIDER_FORM_ID = "custom-model-provider-form";
3
3
  export declare function CustomModelProviderForm({ workspaceId, existingConfig, onSaved, }: {
4
4
  workspaceId: string;
5
- existingConfig?: CustomModelProviderConfigDto | undefined;
5
+ existingConfig?: CustomProviderConfig | undefined;
6
6
  onSaved: () => void;
7
7
  }): import("react").JSX.Element;
8
8
  //# sourceMappingURL=custom-model-provider-form.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-model-provider-form.d.ts","sourceRoot":"","sources":["../../src/components/custom-model-provider-form.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,4BAA4B,EAAmB,MAAM,wBAAwB,CAAC;AAsC3F,eAAO,MAAM,6BAA6B,+BAA+B,CAAC;AAE1E,wBAAgB,uBAAuB,CAAC,EACtC,WAAW,EACX,cAAc,EACd,OAAO,GACR,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,4BAA4B,GAAG,SAAS,CAAC;IAC1D,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,+BAgYA"}
1
+ {"version":3,"file":"custom-model-provider-form.d.ts","sourceRoot":"","sources":["../../src/components/custom-model-provider-form.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAC,oBAAoB,EAAc,MAAM,iBAAiB,CAAC;AA4BvE,eAAO,MAAM,6BAA6B,+BAA+B,CAAC;AAE1E,wBAAgB,uBAAuB,CAAC,EACtC,WAAW,EACX,cAAc,EACd,OAAO,GACR,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAClD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,+BAsYA"}
@@ -9,7 +9,7 @@ import { Switch } from '@shipfox/react-ui/switch';
9
9
  import { Text } from '@shipfox/react-ui/typography';
10
10
  import { useForm } from '@tanstack/react-form';
11
11
  import { useEffect, useRef, useState } from 'react';
12
- import { useCreateCustomModelProviderMutation, useDiscoverCustomModelProviderModelsBySlugMutation, useDiscoverCustomModelProviderModelsMutation, useUpdateCustomModelProviderMutation } from '#hooks/api/model-providers.js';
12
+ import { useCreateCustomModelProviderMutation, useDiscoverCustomModelProviderModelsBySlugMutation, useDiscoverCustomModelProviderModelsMutation, useModelProviderCatalogQuery, useUpdateCustomModelProviderMutation } from '#hooks/api/model-providers.js';
13
13
  import { MODEL_PROVIDER_API_OPTIONS } from './custom-model-provider-api-options.js';
14
14
  import { buildCreateCustomModelProviderBody, buildDiscoverModelsBody, buildDiscoverModelsBySlugBody, buildUpdateCustomModelProviderBody, createCustomModelProviderFormValues, createFormRowId, editCustomModelProviderFormValues } from './custom-model-provider-payload.js';
15
15
  import { customModelProviderSlugError, deriveCustomModelProviderSlug } from './custom-model-provider-slug.js';
@@ -20,6 +20,8 @@ export function CustomModelProviderForm({ workspaceId, existingConfig, onSaved }
20
20
  const createMutation = useCreateCustomModelProviderMutation();
21
21
  const updateMutation = useUpdateCustomModelProviderMutation();
22
22
  const discoverMutation = useDiscoverCustomModelProviderModelsMutation();
23
+ const catalogQuery = useModelProviderCatalogQuery();
24
+ const reservedProviderIds = catalogQuery.data?.providers.map((provider)=>provider.id) ?? [];
23
25
  const discoverBySlugMutation = useDiscoverCustomModelProviderModelsBySlugMutation();
24
26
  const [slugEdited, setSlugEdited] = useState(existingConfig !== undefined);
25
27
  const [formError, setFormError] = useState();
@@ -34,13 +36,13 @@ export function CustomModelProviderForm({ workspaceId, existingConfig, onSaved }
34
36
  if (existingConfig) {
35
37
  await updateMutation.mutateAsync({
36
38
  workspaceId,
37
- providerId: existingConfig.provider_id,
38
- body: buildUpdateCustomModelProviderBody(existingConfig, value)
39
+ providerId: existingConfig.providerId,
40
+ command: buildUpdateCustomModelProviderBody(existingConfig, value)
39
41
  });
40
42
  } else {
41
43
  await createMutation.mutateAsync({
42
44
  workspaceId,
43
- body: buildCreateCustomModelProviderBody(value)
45
+ command: buildCreateCustomModelProviderBody(value)
44
46
  });
45
47
  }
46
48
  onSaved();
@@ -60,15 +62,15 @@ export function CustomModelProviderForm({ workspaceId, existingConfig, onSaved }
60
62
  try {
61
63
  const response = existingConfig ? await discoverBySlugMutation.mutateAsync({
62
64
  workspaceId,
63
- providerId: existingConfig.provider_id,
64
- body: buildDiscoverModelsBySlugBody(existingConfig, values)
65
+ providerId: existingConfig.providerId,
66
+ command: buildDiscoverModelsBySlugBody(existingConfig, values)
65
67
  }) : await discoverMutation.mutateAsync({
66
68
  workspaceId,
67
- body: buildDiscoverModelsBody(values)
69
+ command: buildDiscoverModelsBody(values)
68
70
  });
69
71
  if (!mountedRef.current) return;
70
72
  const existingIds = new Set(values.models.map((model)=>model.id.trim()).filter(Boolean));
71
- const discovered = response.models.filter((model)=>!existingIds.has(model.id));
73
+ const discovered = response.filter((model)=>!existingIds.has(model.id));
72
74
  form.setFieldValue('models', [
73
75
  ...values.models,
74
76
  ...discovered.map((model)=>({
@@ -151,8 +153,8 @@ export function CustomModelProviderForm({ workspaceId, existingConfig, onSaved }
151
153
  /*#__PURE__*/ _jsx(form.Field, {
152
154
  name: "slug",
153
155
  validators: {
154
- onBlur: ({ value })=>existingConfig ? undefined : customModelProviderSlugError(value),
155
- onSubmit: ({ value })=>existingConfig ? undefined : customModelProviderSlugError(value)
156
+ onBlur: ({ value })=>existingConfig ? undefined : customModelProviderSlugError(value, reservedProviderIds),
157
+ onSubmit: ({ value })=>existingConfig ? undefined : customModelProviderSlugError(value, reservedProviderIds)
156
158
  },
157
159
  children: (field)=>/*#__PURE__*/ _jsx(FormField, {
158
160
  label: "Provider ID",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/custom-model-provider-form.tsx"],"sourcesContent":["import type {CustomModelProviderConfigDto, ModelProviderApi} from '@shipfox/api-agent-dto';\nimport {Badge} from '@shipfox/react-ui/badge';\nimport {Button, IconButton} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {Collapsible, CollapsibleContent, CollapsibleTrigger} from '@shipfox/react-ui/collapsible';\nimport {FormField, FormFieldInput, fieldError} from '@shipfox/react-ui/form-field';\nimport {ModalBody, ModalFooter} from '@shipfox/react-ui/modal';\nimport {Switch} from '@shipfox/react-ui/switch';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {useForm} from '@tanstack/react-form';\nimport type {ReactNode, RefObject} from 'react';\nimport {useEffect, useRef, useState} from 'react';\nimport {\n useCreateCustomModelProviderMutation,\n useDiscoverCustomModelProviderModelsBySlugMutation,\n useDiscoverCustomModelProviderModelsMutation,\n useUpdateCustomModelProviderMutation,\n} from '#hooks/api/model-providers.js';\nimport {MODEL_PROVIDER_API_OPTIONS} from './custom-model-provider-api-options.js';\nimport {\n buildCreateCustomModelProviderBody,\n buildDiscoverModelsBody,\n buildDiscoverModelsBySlugBody,\n buildUpdateCustomModelProviderBody,\n type CustomModelProviderFormValues,\n type CustomModelProviderHeaderFormValue,\n type CustomModelProviderModelFormValue,\n createCustomModelProviderFormValues,\n createFormRowId,\n editCustomModelProviderFormValues,\n} from './custom-model-provider-payload.js';\nimport {\n customModelProviderSlugError,\n deriveCustomModelProviderSlug,\n} from './custom-model-provider-slug.js';\nimport {FormFieldSelect} from './default-model-field.js';\nimport {modelProviderConfigErrorField} from './form-errors.js';\n\nexport const CUSTOM_MODEL_PROVIDER_FORM_ID = 'custom-model-provider-form';\n\nexport function CustomModelProviderForm({\n workspaceId,\n existingConfig,\n onSaved,\n}: {\n workspaceId: string;\n existingConfig?: CustomModelProviderConfigDto | undefined;\n onSaved: () => void;\n}) {\n const createMutation = useCreateCustomModelProviderMutation();\n const updateMutation = useUpdateCustomModelProviderMutation();\n const discoverMutation = useDiscoverCustomModelProviderModelsMutation();\n const discoverBySlugMutation = useDiscoverCustomModelProviderModelsBySlugMutation();\n const [slugEdited, setSlugEdited] = useState(existingConfig !== undefined);\n const [formError, setFormError] = useState<string | undefined>();\n const [discoveryStatus, setDiscoveryStatus] = useState<string | undefined>();\n const [removedDefaultNotice, setRemovedDefaultNotice] = useState(false);\n const mountedRef = useRef(true);\n const form = useForm({\n defaultValues: existingConfig\n ? editCustomModelProviderFormValues(existingConfig)\n : createCustomModelProviderFormValues(),\n onSubmit: async ({value}) => {\n setFormError(undefined);\n\n try {\n if (existingConfig) {\n await updateMutation.mutateAsync({\n workspaceId,\n providerId: existingConfig.provider_id,\n body: buildUpdateCustomModelProviderBody(existingConfig, value),\n });\n } else {\n await createMutation.mutateAsync({\n workspaceId,\n body: buildCreateCustomModelProviderBody(value),\n });\n }\n onSaved();\n } catch (error) {\n applyServerError(error);\n }\n },\n });\n\n const isPending =\n createMutation.isPending ||\n updateMutation.isPending ||\n discoverMutation.isPending ||\n discoverBySlugMutation.isPending;\n\n useEffect(() => {\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n async function handleDiscoverModels(values: CustomModelProviderFormValues) {\n setDiscoveryStatus(undefined);\n try {\n const response = existingConfig\n ? await discoverBySlugMutation.mutateAsync({\n workspaceId,\n providerId: existingConfig.provider_id,\n body: buildDiscoverModelsBySlugBody(existingConfig, values),\n })\n : await discoverMutation.mutateAsync({\n workspaceId,\n body: buildDiscoverModelsBody(values),\n });\n if (!mountedRef.current) return;\n const existingIds = new Set(values.models.map((model) => model.id.trim()).filter(Boolean));\n const discovered = response.models.filter((model) => !existingIds.has(model.id));\n form.setFieldValue('models', [\n ...values.models,\n ...discovered.map((model) => ({\n client_id: createFormRowId(),\n id: model.id,\n label: model.label,\n context_window: '',\n max_output_tokens: '',\n input_image: false,\n reasoning: false,\n })),\n ]);\n setDiscoveryStatus(\n discovered.length > 0\n ? `Discovered ${discovered.length} models.`\n : 'No models found - that is normal for some servers. Add models manually.',\n );\n } catch (error) {\n if (!mountedRef.current) return;\n applyServerError(error);\n }\n }\n\n function applyServerError(error: unknown) {\n const mapped = modelProviderConfigErrorField(error);\n if (mapped.kind === 'field') {\n form.setFieldMeta(mapped.field, (prev) => ({\n ...prev,\n errorMap: {...prev.errorMap, onServer: mapped.message},\n }));\n return;\n }\n setFormError(mapped.message);\n }\n\n return (\n <>\n <ModalBody className=\"min-h-0 flex-1 gap-0 overflow-y-auto overflow-x-clip scrollbar\">\n <form\n id={CUSTOM_MODEL_PROVIDER_FORM_ID}\n className=\"flex w-full flex-col gap-24\"\n noValidate\n onSubmit={(event) => {\n event.preventDefault();\n event.stopPropagation();\n void form.handleSubmit();\n }}\n >\n <form.Subscribe selector={(state) => state.values}>\n {(values) => (\n <>\n <FormGroup title=\"Provider\">\n <div className=\"grid grid-cols-2 gap-12 max-[640px]:grid-cols-1\">\n <form.Field\n name=\"display_name\"\n validators={{\n onBlur: ({value}) =>\n value.trim() ? undefined : 'Display name is required.',\n onSubmit: ({value}) =>\n value.trim() ? undefined : 'Display name is required.',\n }}\n >\n {(field) => (\n <FormField\n label=\"Display name\"\n id=\"custom-provider-display-name\"\n error={fieldError(field)}\n >\n <FormFieldInput\n value={field.state.value}\n onChange={(event) => {\n const displayName = event.target.value;\n field.handleChange(displayName);\n if (!slugEdited && !existingConfig) {\n form.setFieldValue(\n 'slug',\n deriveCustomModelProviderSlug(displayName),\n );\n }\n }}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n <form.Field\n name=\"slug\"\n validators={{\n onBlur: ({value}) =>\n existingConfig ? undefined : customModelProviderSlugError(value),\n onSubmit: ({value}) =>\n existingConfig ? undefined : customModelProviderSlugError(value),\n }}\n >\n {(field) => (\n <FormField\n label=\"Provider ID\"\n id=\"custom-provider-slug\"\n error={fieldError(field)}\n description=\"Use this ID in workflow files.\"\n >\n <FormFieldInput\n className=\"font-code\"\n value={field.state.value}\n disabled={existingConfig !== undefined}\n onChange={(event) => {\n setSlugEdited(event.target.value.trim() !== '');\n field.handleChange(event.target.value);\n }}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n </div>\n\n <div className=\"grid grid-cols-2 gap-12 max-[640px]:grid-cols-1\">\n <form.Field name=\"api\">\n {(field) => (\n <FormField label=\"Protocol\" id=\"custom-provider-api\">\n <FormFieldSelect\n value={field.state.value}\n onChange={(event) =>\n field.handleChange(event.target.value as ModelProviderApi)\n }\n onBlur={field.handleBlur}\n >\n {MODEL_PROVIDER_API_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </FormFieldSelect>\n </FormField>\n )}\n </form.Field>\n <form.Field\n name=\"base_url\"\n validators={{\n onBlur: ({value}) =>\n canParseUrl(value)\n ? undefined\n : 'Enter a full URL, like https://api.openai.com/v1',\n onSubmit: ({value}) =>\n canParseUrl(value)\n ? undefined\n : 'Enter a full URL, like https://api.openai.com/v1',\n }}\n >\n {(field) => (\n <FormField\n label=\"Base URL\"\n id=\"custom-provider-base-url\"\n error={fieldError(field)}\n >\n <FormFieldInput\n className=\"font-code\"\n placeholder=\"https://api.openai.com/v1\"\n value={field.state.value}\n onChange={(event) => field.handleChange(event.target.value)}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n </div>\n\n <form.Field name=\"api_key\">\n {(field) => (\n <FormField\n label=\"API key\"\n id=\"custom-provider-api-key\"\n description={\n existingConfig\n ? 'Leave blank to keep the current key.'\n : 'Leave blank when the endpoint does not require a key.'\n }\n >\n <FormFieldInput\n type=\"password\"\n autoComplete=\"off\"\n value={field.state.value}\n onChange={(event) => field.handleChange(event.target.value)}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n </FormGroup>\n\n <FormGroup title=\"Headers\">\n <form.Field name=\"headers\">\n {(field) => (\n <HeaderRows\n rows={field.state.value}\n onChange={(headers) => field.handleChange(headers)}\n />\n )}\n </form.Field>\n </FormGroup>\n\n <FormGroup title=\"Models\">\n <div className=\"flex flex-wrap items-center justify-between gap-8\">\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n iconLeft=\"downloadLine\"\n disabled={!canParseUrl(values.base_url)}\n isLoading={discoverMutation.isPending || discoverBySlugMutation.isPending}\n onClick={() => {\n void handleDiscoverModels(values);\n }}\n >\n Fetch models\n </Button>\n {discoveryStatus ? (\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\" role=\"status\">\n {discoveryStatus}\n </Text>\n ) : null}\n </div>\n\n <form.Field\n name=\"models\"\n validators={{\n onSubmit: ({value}) =>\n value.some((model) => model.id.trim() && model.label.trim())\n ? undefined\n : 'Add at least one model.',\n }}\n >\n {(field) => (\n <>\n <ModelRows\n rows={field.state.value}\n defaultModel={values.default_model}\n onDefaultRemoved={() => setRemovedDefaultNotice(true)}\n onChange={(models) => field.handleChange(models)}\n onDefaultChange={(defaultModel) => {\n setRemovedDefaultNotice(false);\n form.setFieldValue('default_model', defaultModel);\n }}\n />\n {fieldError(field) ? (\n <Text size=\"sm\" className=\"text-foreground-highlight-error\">\n {fieldError(field)}\n </Text>\n ) : null}\n </>\n )}\n </form.Field>\n\n {removedDefaultNotice ? (\n <Callout role=\"alert\" type=\"warning\">\n <Text size=\"sm\">\n Default model removed - choose a new default or keep none.\n </Text>\n </Callout>\n ) : null}\n <form.Field\n name=\"default_model\"\n validators={{\n onBlur: ({value}) => validateDefaultModel(value, values.models),\n onSubmit: ({value}) => validateDefaultModel(value, values.models),\n }}\n >\n {(field) => (\n <FormField\n label=\"Default model\"\n id=\"custom-provider-default-model\"\n error={fieldError(field)}\n >\n <FormFieldSelect\n value={field.state.value}\n onChange={(event) => {\n setRemovedDefaultNotice(false);\n field.handleChange(event.target.value);\n }}\n onBlur={field.handleBlur}\n >\n <option value=\"\">No default</option>\n {values.models\n .filter((model) => model.id.trim())\n .map((model) => (\n <option key={model.client_id} value={model.id}>\n {model.label.trim() || model.id}\n </option>\n ))}\n </FormFieldSelect>\n </FormField>\n )}\n </form.Field>\n </FormGroup>\n </>\n )}\n </form.Subscribe>\n </form>\n {formError ? (\n <Callout role=\"alert\" type=\"error\" className=\"mt-16\">\n <div className=\"flex flex-col gap-8\">\n <Text size=\"sm\" bold>\n Could not save provider\n </Text>\n <Text size=\"sm\">{formError}</Text>\n </div>\n </Callout>\n ) : null}\n </ModalBody>\n <ModalFooter>\n <Text size=\"sm\" className=\"mr-auto text-foreground-neutral-muted\">\n Saving runs a live test against the endpoint.\n </Text>\n <Button type=\"submit\" form={CUSTOM_MODEL_PROVIDER_FORM_ID} isLoading={isPending}>\n Test & save\n </Button>\n </ModalFooter>\n </>\n );\n}\n\nfunction FormGroup({title, children}: {title: string; children: ReactNode}) {\n return (\n <section className=\"flex flex-col gap-16 border-t border-border-neutral-base pt-16 first:border-t-0 first:pt-0\">\n <Text size=\"xs\" className=\"font-medium uppercase text-foreground-neutral-muted\">\n {title}\n </Text>\n {children}\n </section>\n );\n}\n\nfunction HeaderRows({\n rows,\n onChange,\n}: {\n rows: CustomModelProviderHeaderFormValue[];\n onChange: (rows: CustomModelProviderHeaderFormValue[]) => void;\n}) {\n const addButtonRef = useRef<HTMLButtonElement>(null);\n\n return (\n <div className=\"flex flex-col gap-10\">\n {rows.map((row, index) => (\n <div\n key={row.client_id}\n className=\"grid grid-cols-[1fr_1fr_auto_auto] items-end gap-x-8 gap-y-4 max-[760px]:grid-cols-1\"\n >\n <FormField label=\"Name\" id={`custom-header-name-${row.client_id}`}>\n <FormFieldInput\n className=\"font-code\"\n value={row.name}\n onChange={(event) =>\n updateRow(rows, index, {...row, name: event.target.value}, onChange)\n }\n />\n </FormField>\n <FormField label=\"Value\" id={`custom-header-value-${row.client_id}`}>\n <FormFieldInput\n type={row.secret ? 'password' : 'text'}\n placeholder={row.hasStoredValue ? 'Unchanged' : undefined}\n value={row.value}\n onChange={(event) =>\n updateRow(rows, index, {...row, value: event.target.value}, onChange)\n }\n />\n </FormField>\n <div className=\"flex h-32 items-center gap-8 text-sm text-foreground-neutral-muted\">\n <Switch\n size=\"sm\"\n aria-label={`Mark header ${index + 1} as secret`}\n checked={row.secret}\n onCheckedChange={(checked) =>\n updateRow(rows, index, {...row, secret: checked}, onChange)\n }\n />\n Secret\n </div>\n <IconButton\n type=\"button\"\n size=\"sm\"\n variant=\"transparent\"\n icon=\"deleteBinLine\"\n aria-label=\"Remove header\"\n onClick={() => {\n onChange(rows.filter((_, rowIndex) => rowIndex !== index));\n focusAfterRender(addButtonRef);\n }}\n />\n </div>\n ))}\n <Button\n ref={addButtonRef}\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n iconLeft=\"addLine\"\n onClick={() => {\n const clientId = createFormRowId();\n onChange([\n ...rows,\n {\n client_id: clientId,\n name: '',\n value: '',\n secret: false,\n hasStoredValue: false,\n storedName: '',\n },\n ]);\n focusAfterRender(`custom-header-name-${clientId}`);\n }}\n >\n Add header\n </Button>\n </div>\n );\n}\n\nfunction ModelRows({\n rows,\n defaultModel,\n onChange,\n onDefaultChange,\n onDefaultRemoved,\n}: {\n rows: CustomModelProviderModelFormValue[];\n defaultModel: string;\n onChange: (rows: CustomModelProviderModelFormValue[]) => void;\n onDefaultChange: (value: string) => void;\n onDefaultRemoved: () => void;\n}) {\n const addButtonRef = useRef<HTMLButtonElement>(null);\n\n return (\n <div className=\"flex flex-col gap-10\">\n {rows.map((row, index) => (\n <div key={row.client_id} className=\"rounded-8 border border-border-neutral-base p-12\">\n <div className=\"grid grid-cols-[1fr_1fr_auto] items-end gap-8 max-[760px]:grid-cols-1\">\n <FormField label=\"Model id\" id={`custom-model-id-${row.client_id}`}>\n <FormFieldInput\n className=\"font-code\"\n value={row.id}\n onChange={(event) =>\n updateRow(rows, index, {...row, id: event.target.value}, onChange)\n }\n />\n </FormField>\n <FormField label=\"Label\" id={`custom-model-label-${row.client_id}`}>\n <FormFieldInput\n value={row.label}\n onChange={(event) =>\n updateRow(rows, index, {...row, label: event.target.value}, onChange)\n }\n />\n </FormField>\n <div className=\"flex items-center gap-8\">\n {defaultModel && row.id === defaultModel ? (\n <Badge variant=\"neutral\">Default</Badge>\n ) : null}\n <IconButton\n type=\"button\"\n size=\"sm\"\n variant=\"transparent\"\n icon=\"deleteBinLine\"\n aria-label=\"Remove model\"\n onClick={() => {\n const nextRows = rows.filter((_, rowIndex) => rowIndex !== index);\n onChange(nextRows);\n focusAfterRender(addButtonRef);\n if (row.id === defaultModel) {\n onDefaultChange('');\n onDefaultRemoved();\n }\n }}\n />\n </div>\n </div>\n <Collapsible>\n <CollapsibleTrigger asChild>\n <Button type=\"button\" size=\"sm\" variant=\"transparentMuted\" className=\"mt-8\">\n Defaults: 128k context, 16k output, text-only\n </Button>\n </CollapsibleTrigger>\n <CollapsibleContent>\n <div className=\"mt-8 grid grid-cols-2 gap-8 max-[640px]:grid-cols-1\">\n <FormField label=\"Context window\" id={`custom-model-context-${row.client_id}`}>\n <FormFieldInput\n type=\"number\"\n inputMode=\"numeric\"\n placeholder=\"128000\"\n value={row.context_window}\n onChange={(event) =>\n updateRow(rows, index, {...row, context_window: event.target.value}, onChange)\n }\n />\n </FormField>\n <FormField label=\"Max output tokens\" id={`custom-model-output-${row.client_id}`}>\n <FormFieldInput\n type=\"number\"\n inputMode=\"numeric\"\n placeholder=\"16384\"\n value={row.max_output_tokens}\n onChange={(event) =>\n updateRow(\n rows,\n index,\n {...row, max_output_tokens: event.target.value},\n onChange,\n )\n }\n />\n </FormField>\n <div className=\"flex h-32 items-center gap-8 text-sm text-foreground-neutral-muted\">\n <Switch\n size=\"sm\"\n aria-label={`Enable image input for model ${index + 1}`}\n checked={row.input_image}\n onCheckedChange={(checked) =>\n updateRow(rows, index, {...row, input_image: checked}, onChange)\n }\n />\n Image input\n </div>\n <div className=\"flex h-32 items-center gap-8 text-sm text-foreground-neutral-muted\">\n <Switch\n size=\"sm\"\n aria-label={`Enable reasoning for model ${index + 1}`}\n checked={row.reasoning}\n onCheckedChange={(checked) =>\n updateRow(rows, index, {...row, reasoning: checked}, onChange)\n }\n />\n Reasoning\n </div>\n </div>\n </CollapsibleContent>\n </Collapsible>\n </div>\n ))}\n <Button\n ref={addButtonRef}\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n iconLeft=\"addLine\"\n onClick={() => {\n const clientId = createFormRowId();\n onChange([\n ...rows,\n {\n client_id: clientId,\n id: '',\n label: '',\n context_window: '',\n max_output_tokens: '',\n input_image: false,\n reasoning: false,\n },\n ]);\n focusAfterRender(`custom-model-id-${clientId}`);\n }}\n >\n Add model\n </Button>\n </div>\n );\n}\n\nfunction updateRow<T>(rows: T[], index: number, row: T, onChange: (rows: T[]) => void) {\n onChange(rows.map((candidate, rowIndex) => (rowIndex === index ? row : candidate)));\n}\n\nfunction focusAfterRender(target: string | RefObject<HTMLElement | null>): void {\n requestAnimationFrame(() => {\n const element = typeof target === 'string' ? document.getElementById(target) : target.current;\n element?.focus();\n });\n}\n\nfunction validateDefaultModel(\n value: string,\n models: CustomModelProviderModelFormValue[],\n): string | undefined {\n return value.trim() && !models.some((model) => model.id.trim() === value.trim())\n ? 'Choose a model from the models list.'\n : undefined;\n}\n\nfunction canParseUrl(value: string): boolean {\n try {\n new URL(value);\n return true;\n } catch {\n return false;\n }\n}\n"],"names":["Badge","Button","IconButton","Callout","Collapsible","CollapsibleContent","CollapsibleTrigger","FormField","FormFieldInput","fieldError","ModalBody","ModalFooter","Switch","Text","useForm","useEffect","useRef","useState","useCreateCustomModelProviderMutation","useDiscoverCustomModelProviderModelsBySlugMutation","useDiscoverCustomModelProviderModelsMutation","useUpdateCustomModelProviderMutation","MODEL_PROVIDER_API_OPTIONS","buildCreateCustomModelProviderBody","buildDiscoverModelsBody","buildDiscoverModelsBySlugBody","buildUpdateCustomModelProviderBody","createCustomModelProviderFormValues","createFormRowId","editCustomModelProviderFormValues","customModelProviderSlugError","deriveCustomModelProviderSlug","FormFieldSelect","modelProviderConfigErrorField","CUSTOM_MODEL_PROVIDER_FORM_ID","CustomModelProviderForm","workspaceId","existingConfig","onSaved","createMutation","updateMutation","discoverMutation","discoverBySlugMutation","slugEdited","setSlugEdited","undefined","formError","setFormError","discoveryStatus","setDiscoveryStatus","removedDefaultNotice","setRemovedDefaultNotice","mountedRef","form","defaultValues","onSubmit","value","mutateAsync","providerId","provider_id","body","error","applyServerError","isPending","current","handleDiscoverModels","values","response","existingIds","Set","models","map","model","id","trim","filter","Boolean","discovered","has","setFieldValue","client_id","label","context_window","max_output_tokens","input_image","reasoning","length","mapped","kind","setFieldMeta","field","prev","errorMap","onServer","message","className","noValidate","event","preventDefault","stopPropagation","handleSubmit","Subscribe","selector","state","FormGroup","title","div","Field","name","validators","onBlur","onChange","displayName","target","handleChange","handleBlur","description","disabled","option","canParseUrl","placeholder","type","autoComplete","HeaderRows","rows","headers","size","variant","iconLeft","base_url","isLoading","onClick","role","some","ModelRows","defaultModel","default_model","onDefaultRemoved","onDefaultChange","validateDefaultModel","bold","children","section","addButtonRef","row","index","updateRow","secret","hasStoredValue","aria-label","checked","onCheckedChange","icon","_","rowIndex","focusAfterRender","ref","clientId","storedName","nextRows","asChild","inputMode","candidate","requestAnimationFrame","element","document","getElementById","focus","URL"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/components/custom-model-provider-form.tsx"],"sourcesContent":["import {Badge} from '@shipfox/react-ui/badge';\nimport {Button, IconButton} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {Collapsible, CollapsibleContent, CollapsibleTrigger} from '@shipfox/react-ui/collapsible';\nimport {FormField, FormFieldInput, fieldError} from '@shipfox/react-ui/form-field';\nimport {ModalBody, ModalFooter} from '@shipfox/react-ui/modal';\nimport {Switch} from '@shipfox/react-ui/switch';\nimport {Text} from '@shipfox/react-ui/typography';\nimport {useForm} from '@tanstack/react-form';\nimport type {ReactNode, RefObject} from 'react';\nimport {useEffect, useRef, useState} from 'react';\nimport type {CustomProviderConfig, ProviderApi} from '#core/models.js';\nimport {\n useCreateCustomModelProviderMutation,\n useDiscoverCustomModelProviderModelsBySlugMutation,\n useDiscoverCustomModelProviderModelsMutation,\n useModelProviderCatalogQuery,\n useUpdateCustomModelProviderMutation,\n} from '#hooks/api/model-providers.js';\nimport {MODEL_PROVIDER_API_OPTIONS} from './custom-model-provider-api-options.js';\nimport {\n buildCreateCustomModelProviderBody,\n buildDiscoverModelsBody,\n buildDiscoverModelsBySlugBody,\n buildUpdateCustomModelProviderBody,\n type CustomModelProviderFormValues,\n type CustomModelProviderHeaderFormValue,\n type CustomModelProviderModelFormValue,\n createCustomModelProviderFormValues,\n createFormRowId,\n editCustomModelProviderFormValues,\n} from './custom-model-provider-payload.js';\nimport {\n customModelProviderSlugError,\n deriveCustomModelProviderSlug,\n} from './custom-model-provider-slug.js';\nimport {FormFieldSelect} from './default-model-field.js';\nimport {modelProviderConfigErrorField} from './form-errors.js';\n\nexport const CUSTOM_MODEL_PROVIDER_FORM_ID = 'custom-model-provider-form';\n\nexport function CustomModelProviderForm({\n workspaceId,\n existingConfig,\n onSaved,\n}: {\n workspaceId: string;\n existingConfig?: CustomProviderConfig | undefined;\n onSaved: () => void;\n}) {\n const createMutation = useCreateCustomModelProviderMutation();\n const updateMutation = useUpdateCustomModelProviderMutation();\n const discoverMutation = useDiscoverCustomModelProviderModelsMutation();\n const catalogQuery = useModelProviderCatalogQuery();\n const reservedProviderIds = catalogQuery.data?.providers.map((provider) => provider.id) ?? [];\n const discoverBySlugMutation = useDiscoverCustomModelProviderModelsBySlugMutation();\n const [slugEdited, setSlugEdited] = useState(existingConfig !== undefined);\n const [formError, setFormError] = useState<string | undefined>();\n const [discoveryStatus, setDiscoveryStatus] = useState<string | undefined>();\n const [removedDefaultNotice, setRemovedDefaultNotice] = useState(false);\n const mountedRef = useRef(true);\n const form = useForm({\n defaultValues: existingConfig\n ? editCustomModelProviderFormValues(existingConfig)\n : createCustomModelProviderFormValues(),\n onSubmit: async ({value}) => {\n setFormError(undefined);\n\n try {\n if (existingConfig) {\n await updateMutation.mutateAsync({\n workspaceId,\n providerId: existingConfig.providerId,\n command: buildUpdateCustomModelProviderBody(existingConfig, value),\n });\n } else {\n await createMutation.mutateAsync({\n workspaceId,\n command: buildCreateCustomModelProviderBody(value),\n });\n }\n onSaved();\n } catch (error) {\n applyServerError(error);\n }\n },\n });\n\n const isPending =\n createMutation.isPending ||\n updateMutation.isPending ||\n discoverMutation.isPending ||\n discoverBySlugMutation.isPending;\n\n useEffect(() => {\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n async function handleDiscoverModels(values: CustomModelProviderFormValues) {\n setDiscoveryStatus(undefined);\n try {\n const response = existingConfig\n ? await discoverBySlugMutation.mutateAsync({\n workspaceId,\n providerId: existingConfig.providerId,\n command: buildDiscoverModelsBySlugBody(existingConfig, values),\n })\n : await discoverMutation.mutateAsync({\n workspaceId,\n command: buildDiscoverModelsBody(values),\n });\n if (!mountedRef.current) return;\n const existingIds = new Set(values.models.map((model) => model.id.trim()).filter(Boolean));\n const discovered = response.filter((model) => !existingIds.has(model.id));\n form.setFieldValue('models', [\n ...values.models,\n ...discovered.map((model) => ({\n client_id: createFormRowId(),\n id: model.id,\n label: model.label,\n context_window: '',\n max_output_tokens: '',\n input_image: false,\n reasoning: false,\n })),\n ]);\n setDiscoveryStatus(\n discovered.length > 0\n ? `Discovered ${discovered.length} models.`\n : 'No models found - that is normal for some servers. Add models manually.',\n );\n } catch (error) {\n if (!mountedRef.current) return;\n applyServerError(error);\n }\n }\n\n function applyServerError(error: unknown) {\n const mapped = modelProviderConfigErrorField(error);\n if (mapped.kind === 'field') {\n form.setFieldMeta(mapped.field, (prev) => ({\n ...prev,\n errorMap: {...prev.errorMap, onServer: mapped.message},\n }));\n return;\n }\n setFormError(mapped.message);\n }\n\n return (\n <>\n <ModalBody className=\"min-h-0 flex-1 gap-0 overflow-y-auto overflow-x-clip scrollbar\">\n <form\n id={CUSTOM_MODEL_PROVIDER_FORM_ID}\n className=\"flex w-full flex-col gap-24\"\n noValidate\n onSubmit={(event) => {\n event.preventDefault();\n event.stopPropagation();\n void form.handleSubmit();\n }}\n >\n <form.Subscribe selector={(state) => state.values}>\n {(values) => (\n <>\n <FormGroup title=\"Provider\">\n <div className=\"grid grid-cols-2 gap-12 max-[640px]:grid-cols-1\">\n <form.Field\n name=\"display_name\"\n validators={{\n onBlur: ({value}) =>\n value.trim() ? undefined : 'Display name is required.',\n onSubmit: ({value}) =>\n value.trim() ? undefined : 'Display name is required.',\n }}\n >\n {(field) => (\n <FormField\n label=\"Display name\"\n id=\"custom-provider-display-name\"\n error={fieldError(field)}\n >\n <FormFieldInput\n value={field.state.value}\n onChange={(event) => {\n const displayName = event.target.value;\n field.handleChange(displayName);\n if (!slugEdited && !existingConfig) {\n form.setFieldValue(\n 'slug',\n deriveCustomModelProviderSlug(displayName),\n );\n }\n }}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n <form.Field\n name=\"slug\"\n validators={{\n onBlur: ({value}) =>\n existingConfig\n ? undefined\n : customModelProviderSlugError(value, reservedProviderIds),\n onSubmit: ({value}) =>\n existingConfig\n ? undefined\n : customModelProviderSlugError(value, reservedProviderIds),\n }}\n >\n {(field) => (\n <FormField\n label=\"Provider ID\"\n id=\"custom-provider-slug\"\n error={fieldError(field)}\n description=\"Use this ID in workflow files.\"\n >\n <FormFieldInput\n className=\"font-code\"\n value={field.state.value}\n disabled={existingConfig !== undefined}\n onChange={(event) => {\n setSlugEdited(event.target.value.trim() !== '');\n field.handleChange(event.target.value);\n }}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n </div>\n\n <div className=\"grid grid-cols-2 gap-12 max-[640px]:grid-cols-1\">\n <form.Field name=\"api\">\n {(field) => (\n <FormField label=\"Protocol\" id=\"custom-provider-api\">\n <FormFieldSelect\n value={field.state.value}\n onChange={(event) =>\n field.handleChange(event.target.value as ProviderApi)\n }\n onBlur={field.handleBlur}\n >\n {MODEL_PROVIDER_API_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </FormFieldSelect>\n </FormField>\n )}\n </form.Field>\n <form.Field\n name=\"base_url\"\n validators={{\n onBlur: ({value}) =>\n canParseUrl(value)\n ? undefined\n : 'Enter a full URL, like https://api.openai.com/v1',\n onSubmit: ({value}) =>\n canParseUrl(value)\n ? undefined\n : 'Enter a full URL, like https://api.openai.com/v1',\n }}\n >\n {(field) => (\n <FormField\n label=\"Base URL\"\n id=\"custom-provider-base-url\"\n error={fieldError(field)}\n >\n <FormFieldInput\n className=\"font-code\"\n placeholder=\"https://api.openai.com/v1\"\n value={field.state.value}\n onChange={(event) => field.handleChange(event.target.value)}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n </div>\n\n <form.Field name=\"api_key\">\n {(field) => (\n <FormField\n label=\"API key\"\n id=\"custom-provider-api-key\"\n description={\n existingConfig\n ? 'Leave blank to keep the current key.'\n : 'Leave blank when the endpoint does not require a key.'\n }\n >\n <FormFieldInput\n type=\"password\"\n autoComplete=\"off\"\n value={field.state.value}\n onChange={(event) => field.handleChange(event.target.value)}\n onBlur={field.handleBlur}\n />\n </FormField>\n )}\n </form.Field>\n </FormGroup>\n\n <FormGroup title=\"Headers\">\n <form.Field name=\"headers\">\n {(field) => (\n <HeaderRows\n rows={field.state.value}\n onChange={(headers) => field.handleChange(headers)}\n />\n )}\n </form.Field>\n </FormGroup>\n\n <FormGroup title=\"Models\">\n <div className=\"flex flex-wrap items-center justify-between gap-8\">\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n iconLeft=\"downloadLine\"\n disabled={!canParseUrl(values.base_url)}\n isLoading={discoverMutation.isPending || discoverBySlugMutation.isPending}\n onClick={() => {\n void handleDiscoverModels(values);\n }}\n >\n Fetch models\n </Button>\n {discoveryStatus ? (\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\" role=\"status\">\n {discoveryStatus}\n </Text>\n ) : null}\n </div>\n\n <form.Field\n name=\"models\"\n validators={{\n onSubmit: ({value}) =>\n value.some((model) => model.id.trim() && model.label.trim())\n ? undefined\n : 'Add at least one model.',\n }}\n >\n {(field) => (\n <>\n <ModelRows\n rows={field.state.value}\n defaultModel={values.default_model}\n onDefaultRemoved={() => setRemovedDefaultNotice(true)}\n onChange={(models) => field.handleChange(models)}\n onDefaultChange={(defaultModel) => {\n setRemovedDefaultNotice(false);\n form.setFieldValue('default_model', defaultModel);\n }}\n />\n {fieldError(field) ? (\n <Text size=\"sm\" className=\"text-foreground-highlight-error\">\n {fieldError(field)}\n </Text>\n ) : null}\n </>\n )}\n </form.Field>\n\n {removedDefaultNotice ? (\n <Callout role=\"alert\" type=\"warning\">\n <Text size=\"sm\">\n Default model removed - choose a new default or keep none.\n </Text>\n </Callout>\n ) : null}\n <form.Field\n name=\"default_model\"\n validators={{\n onBlur: ({value}) => validateDefaultModel(value, values.models),\n onSubmit: ({value}) => validateDefaultModel(value, values.models),\n }}\n >\n {(field) => (\n <FormField\n label=\"Default model\"\n id=\"custom-provider-default-model\"\n error={fieldError(field)}\n >\n <FormFieldSelect\n value={field.state.value}\n onChange={(event) => {\n setRemovedDefaultNotice(false);\n field.handleChange(event.target.value);\n }}\n onBlur={field.handleBlur}\n >\n <option value=\"\">No default</option>\n {values.models\n .filter((model) => model.id.trim())\n .map((model) => (\n <option key={model.client_id} value={model.id}>\n {model.label.trim() || model.id}\n </option>\n ))}\n </FormFieldSelect>\n </FormField>\n )}\n </form.Field>\n </FormGroup>\n </>\n )}\n </form.Subscribe>\n </form>\n {formError ? (\n <Callout role=\"alert\" type=\"error\" className=\"mt-16\">\n <div className=\"flex flex-col gap-8\">\n <Text size=\"sm\" bold>\n Could not save provider\n </Text>\n <Text size=\"sm\">{formError}</Text>\n </div>\n </Callout>\n ) : null}\n </ModalBody>\n <ModalFooter>\n <Text size=\"sm\" className=\"mr-auto text-foreground-neutral-muted\">\n Saving runs a live test against the endpoint.\n </Text>\n <Button type=\"submit\" form={CUSTOM_MODEL_PROVIDER_FORM_ID} isLoading={isPending}>\n Test & save\n </Button>\n </ModalFooter>\n </>\n );\n}\n\nfunction FormGroup({title, children}: {title: string; children: ReactNode}) {\n return (\n <section className=\"flex flex-col gap-16 border-t border-border-neutral-base pt-16 first:border-t-0 first:pt-0\">\n <Text size=\"xs\" className=\"font-medium uppercase text-foreground-neutral-muted\">\n {title}\n </Text>\n {children}\n </section>\n );\n}\n\nfunction HeaderRows({\n rows,\n onChange,\n}: {\n rows: CustomModelProviderHeaderFormValue[];\n onChange: (rows: CustomModelProviderHeaderFormValue[]) => void;\n}) {\n const addButtonRef = useRef<HTMLButtonElement>(null);\n\n return (\n <div className=\"flex flex-col gap-10\">\n {rows.map((row, index) => (\n <div\n key={row.client_id}\n className=\"grid grid-cols-[1fr_1fr_auto_auto] items-end gap-x-8 gap-y-4 max-[760px]:grid-cols-1\"\n >\n <FormField label=\"Name\" id={`custom-header-name-${row.client_id}`}>\n <FormFieldInput\n className=\"font-code\"\n value={row.name}\n onChange={(event) =>\n updateRow(rows, index, {...row, name: event.target.value}, onChange)\n }\n />\n </FormField>\n <FormField label=\"Value\" id={`custom-header-value-${row.client_id}`}>\n <FormFieldInput\n type={row.secret ? 'password' : 'text'}\n placeholder={row.hasStoredValue ? 'Unchanged' : undefined}\n value={row.value}\n onChange={(event) =>\n updateRow(rows, index, {...row, value: event.target.value}, onChange)\n }\n />\n </FormField>\n <div className=\"flex h-32 items-center gap-8 text-sm text-foreground-neutral-muted\">\n <Switch\n size=\"sm\"\n aria-label={`Mark header ${index + 1} as secret`}\n checked={row.secret}\n onCheckedChange={(checked) =>\n updateRow(rows, index, {...row, secret: checked}, onChange)\n }\n />\n Secret\n </div>\n <IconButton\n type=\"button\"\n size=\"sm\"\n variant=\"transparent\"\n icon=\"deleteBinLine\"\n aria-label=\"Remove header\"\n onClick={() => {\n onChange(rows.filter((_, rowIndex) => rowIndex !== index));\n focusAfterRender(addButtonRef);\n }}\n />\n </div>\n ))}\n <Button\n ref={addButtonRef}\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n iconLeft=\"addLine\"\n onClick={() => {\n const clientId = createFormRowId();\n onChange([\n ...rows,\n {\n client_id: clientId,\n name: '',\n value: '',\n secret: false,\n hasStoredValue: false,\n storedName: '',\n },\n ]);\n focusAfterRender(`custom-header-name-${clientId}`);\n }}\n >\n Add header\n </Button>\n </div>\n );\n}\n\nfunction ModelRows({\n rows,\n defaultModel,\n onChange,\n onDefaultChange,\n onDefaultRemoved,\n}: {\n rows: CustomModelProviderModelFormValue[];\n defaultModel: string;\n onChange: (rows: CustomModelProviderModelFormValue[]) => void;\n onDefaultChange: (value: string) => void;\n onDefaultRemoved: () => void;\n}) {\n const addButtonRef = useRef<HTMLButtonElement>(null);\n\n return (\n <div className=\"flex flex-col gap-10\">\n {rows.map((row, index) => (\n <div key={row.client_id} className=\"rounded-8 border border-border-neutral-base p-12\">\n <div className=\"grid grid-cols-[1fr_1fr_auto] items-end gap-8 max-[760px]:grid-cols-1\">\n <FormField label=\"Model id\" id={`custom-model-id-${row.client_id}`}>\n <FormFieldInput\n className=\"font-code\"\n value={row.id}\n onChange={(event) =>\n updateRow(rows, index, {...row, id: event.target.value}, onChange)\n }\n />\n </FormField>\n <FormField label=\"Label\" id={`custom-model-label-${row.client_id}`}>\n <FormFieldInput\n value={row.label}\n onChange={(event) =>\n updateRow(rows, index, {...row, label: event.target.value}, onChange)\n }\n />\n </FormField>\n <div className=\"flex items-center gap-8\">\n {defaultModel && row.id === defaultModel ? (\n <Badge variant=\"neutral\">Default</Badge>\n ) : null}\n <IconButton\n type=\"button\"\n size=\"sm\"\n variant=\"transparent\"\n icon=\"deleteBinLine\"\n aria-label=\"Remove model\"\n onClick={() => {\n const nextRows = rows.filter((_, rowIndex) => rowIndex !== index);\n onChange(nextRows);\n focusAfterRender(addButtonRef);\n if (row.id === defaultModel) {\n onDefaultChange('');\n onDefaultRemoved();\n }\n }}\n />\n </div>\n </div>\n <Collapsible>\n <CollapsibleTrigger asChild>\n <Button type=\"button\" size=\"sm\" variant=\"transparentMuted\" className=\"mt-8\">\n Defaults: 128k context, 16k output, text-only\n </Button>\n </CollapsibleTrigger>\n <CollapsibleContent>\n <div className=\"mt-8 grid grid-cols-2 gap-8 max-[640px]:grid-cols-1\">\n <FormField label=\"Context window\" id={`custom-model-context-${row.client_id}`}>\n <FormFieldInput\n type=\"number\"\n inputMode=\"numeric\"\n placeholder=\"128000\"\n value={row.context_window}\n onChange={(event) =>\n updateRow(rows, index, {...row, context_window: event.target.value}, onChange)\n }\n />\n </FormField>\n <FormField label=\"Max output tokens\" id={`custom-model-output-${row.client_id}`}>\n <FormFieldInput\n type=\"number\"\n inputMode=\"numeric\"\n placeholder=\"16384\"\n value={row.max_output_tokens}\n onChange={(event) =>\n updateRow(\n rows,\n index,\n {...row, max_output_tokens: event.target.value},\n onChange,\n )\n }\n />\n </FormField>\n <div className=\"flex h-32 items-center gap-8 text-sm text-foreground-neutral-muted\">\n <Switch\n size=\"sm\"\n aria-label={`Enable image input for model ${index + 1}`}\n checked={row.input_image}\n onCheckedChange={(checked) =>\n updateRow(rows, index, {...row, input_image: checked}, onChange)\n }\n />\n Image input\n </div>\n <div className=\"flex h-32 items-center gap-8 text-sm text-foreground-neutral-muted\">\n <Switch\n size=\"sm\"\n aria-label={`Enable reasoning for model ${index + 1}`}\n checked={row.reasoning}\n onCheckedChange={(checked) =>\n updateRow(rows, index, {...row, reasoning: checked}, onChange)\n }\n />\n Reasoning\n </div>\n </div>\n </CollapsibleContent>\n </Collapsible>\n </div>\n ))}\n <Button\n ref={addButtonRef}\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n iconLeft=\"addLine\"\n onClick={() => {\n const clientId = createFormRowId();\n onChange([\n ...rows,\n {\n client_id: clientId,\n id: '',\n label: '',\n context_window: '',\n max_output_tokens: '',\n input_image: false,\n reasoning: false,\n },\n ]);\n focusAfterRender(`custom-model-id-${clientId}`);\n }}\n >\n Add model\n </Button>\n </div>\n );\n}\n\nfunction updateRow<T>(rows: T[], index: number, row: T, onChange: (rows: T[]) => void) {\n onChange(rows.map((candidate, rowIndex) => (rowIndex === index ? row : candidate)));\n}\n\nfunction focusAfterRender(target: string | RefObject<HTMLElement | null>): void {\n requestAnimationFrame(() => {\n const element = typeof target === 'string' ? document.getElementById(target) : target.current;\n element?.focus();\n });\n}\n\nfunction validateDefaultModel(\n value: string,\n models: CustomModelProviderModelFormValue[],\n): string | undefined {\n return value.trim() && !models.some((model) => model.id.trim() === value.trim())\n ? 'Choose a model from the models list.'\n : undefined;\n}\n\nfunction canParseUrl(value: string): boolean {\n try {\n new URL(value);\n return true;\n } catch {\n return false;\n }\n}\n"],"names":["Badge","Button","IconButton","Callout","Collapsible","CollapsibleContent","CollapsibleTrigger","FormField","FormFieldInput","fieldError","ModalBody","ModalFooter","Switch","Text","useForm","useEffect","useRef","useState","useCreateCustomModelProviderMutation","useDiscoverCustomModelProviderModelsBySlugMutation","useDiscoverCustomModelProviderModelsMutation","useModelProviderCatalogQuery","useUpdateCustomModelProviderMutation","MODEL_PROVIDER_API_OPTIONS","buildCreateCustomModelProviderBody","buildDiscoverModelsBody","buildDiscoverModelsBySlugBody","buildUpdateCustomModelProviderBody","createCustomModelProviderFormValues","createFormRowId","editCustomModelProviderFormValues","customModelProviderSlugError","deriveCustomModelProviderSlug","FormFieldSelect","modelProviderConfigErrorField","CUSTOM_MODEL_PROVIDER_FORM_ID","CustomModelProviderForm","workspaceId","existingConfig","onSaved","createMutation","updateMutation","discoverMutation","catalogQuery","reservedProviderIds","data","providers","map","provider","id","discoverBySlugMutation","slugEdited","setSlugEdited","undefined","formError","setFormError","discoveryStatus","setDiscoveryStatus","removedDefaultNotice","setRemovedDefaultNotice","mountedRef","form","defaultValues","onSubmit","value","mutateAsync","providerId","command","error","applyServerError","isPending","current","handleDiscoverModels","values","response","existingIds","Set","models","model","trim","filter","Boolean","discovered","has","setFieldValue","client_id","label","context_window","max_output_tokens","input_image","reasoning","length","mapped","kind","setFieldMeta","field","prev","errorMap","onServer","message","className","noValidate","event","preventDefault","stopPropagation","handleSubmit","Subscribe","selector","state","FormGroup","title","div","Field","name","validators","onBlur","onChange","displayName","target","handleChange","handleBlur","description","disabled","option","canParseUrl","placeholder","type","autoComplete","HeaderRows","rows","headers","size","variant","iconLeft","base_url","isLoading","onClick","role","some","ModelRows","defaultModel","default_model","onDefaultRemoved","onDefaultChange","validateDefaultModel","bold","children","section","addButtonRef","row","index","updateRow","secret","hasStoredValue","aria-label","checked","onCheckedChange","icon","_","rowIndex","focusAfterRender","ref","clientId","storedName","nextRows","asChild","inputMode","candidate","requestAnimationFrame","element","document","getElementById","focus","URL"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"custom-model-provider-form.stories.d.ts","sourceRoot":"","sources":["../../src/components/custom-model-provider-form.stories.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAO,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAKrD,UAAU,iCAAiC;IACzC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;CACzB;AAED,iBAAS,4BAA4B,CAAC,EAAC,IAAI,EAAC,EAAE,iCAAiC,+BAiC9E;AAED,QAAA,MAAM,IAAI;;;;;;;;;CAK2C,CAAC;AAEtD,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,UAAU,EAAE,KAAU,CAAC;AAEpC,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAC"}
1
+ {"version":3,"file":"custom-model-provider-form.stories.d.ts","sourceRoot":"","sources":["../../src/components/custom-model-provider-form.stories.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAO,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAMrD,UAAU,iCAAiC;IACzC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;CACzB;AAED,iBAAS,4BAA4B,CAAC,EAAC,IAAI,EAAC,EAAE,iCAAiC,+BAiC9E;AAED,QAAA,MAAM,IAAI;;;;;;;;;CAK2C,CAAC;AAEtD,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,UAAU,EAAE,KAAU,CAAC;AAEpC,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAC"}