@shipfox/client-agent 14.0.1 → 16.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +21 -0
  3. package/dist/components/add-custom-provider-card.js +3 -3
  4. package/dist/components/add-custom-provider-card.js.map +1 -1
  5. package/dist/components/available-provider-card.js +3 -3
  6. package/dist/components/available-provider-card.js.map +1 -1
  7. package/dist/components/available-providers-grid.d.ts +1 -1
  8. package/dist/components/available-providers-grid.d.ts.map +1 -1
  9. package/dist/components/available-providers-grid.js +2 -2
  10. package/dist/components/available-providers-grid.js.map +1 -1
  11. package/dist/components/change-default-model-form.js +3 -3
  12. package/dist/components/change-default-model-form.js.map +1 -1
  13. package/dist/components/custom-model-provider-form.js +18 -19
  14. package/dist/components/custom-model-provider-form.js.map +1 -1
  15. package/dist/components/custom-model-provider-form.stories.d.ts.map +1 -1
  16. package/dist/components/default-model-field.js +1 -1
  17. package/dist/components/default-model-field.js.map +1 -1
  18. package/dist/components/harnesses-section.js +7 -7
  19. package/dist/components/harnesses-section.js.map +1 -1
  20. package/dist/components/harnesses-section.stories.d.ts.map +1 -1
  21. package/dist/components/model-provider-usage-modal.js +8 -8
  22. package/dist/components/model-provider-usage-modal.js.map +1 -1
  23. package/dist/components/model-provider-usage-modal.stories.d.ts.map +1 -1
  24. package/dist/components/model-providers-section.js +20 -20
  25. package/dist/components/model-providers-section.js.map +1 -1
  26. package/dist/components/model-providers-section.stories.d.ts.map +1 -1
  27. package/dist/components/test-and-save-form.js +3 -3
  28. package/dist/components/test-and-save-form.js.map +1 -1
  29. package/dist/feature.d.ts +8 -8
  30. package/dist/feature.d.ts.map +1 -1
  31. package/dist/hooks/api/model-providers.d.ts +1 -1
  32. package/dist/hooks/api/model-providers.d.ts.map +1 -1
  33. package/dist/pages/model-provider-onboarding-page.d.ts.map +1 -1
  34. package/dist/pages/model-provider-onboarding-page.js +51 -43
  35. package/dist/pages/model-provider-onboarding-page.js.map +1 -1
  36. package/dist/pages/model-provider-onboarding-page.stories.d.ts.map +1 -1
  37. package/dist/routes/agents-settings.d.ts.map +1 -1
  38. package/dist/routes/agents-settings.js +1 -1
  39. package/dist/routes/agents-settings.js.map +1 -1
  40. package/dist/routes/model-provider.d.ts.map +1 -1
  41. package/dist/tsconfig.test.tsbuildinfo +1 -1
  42. package/package.json +5 -5
  43. package/src/components/add-custom-provider-card.tsx +3 -3
  44. package/src/components/available-provider-card.tsx +3 -3
  45. package/src/components/available-providers-grid.tsx +2 -2
  46. package/src/components/change-default-model-form.tsx +3 -3
  47. package/src/components/custom-model-provider-form.tsx +23 -20
  48. package/src/components/default-model-field.tsx +1 -1
  49. package/src/components/harnesses-section.tsx +7 -7
  50. package/src/components/model-provider-usage-modal.tsx +8 -8
  51. package/src/components/model-providers-section.tsx +20 -20
  52. package/src/components/test-and-save-form.tsx +3 -3
  53. package/src/pages/model-provider-onboarding-page.tsx +38 -34
  54. package/src/routes/agents-settings.tsx +1 -1
  55. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1,2 +1,2 @@
1
1
  $ shipfox-swc
2
- Successfully compiled: 37 files with swc (529.05ms)
2
+ Successfully compiled: 37 files with swc (353.72ms)
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @shipfox/client-agent
2
2
 
3
+ ## 16.0.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [80cde6b]
8
+ - @shipfox/react-ui@1.1.0
9
+ - @shipfox/client-ui@16.0.0
10
+ - @shipfox/client-shell@16.0.0
11
+ - @shipfox/api-agent-dto@12.2.0
12
+
13
+ ## 15.0.0
14
+
15
+ ### Patch Changes
16
+
17
+ - bca115c: Migrates the agent client surfaces to semantic spacing roles.
18
+ - @shipfox/api-agent-dto@12.0.0
19
+ - @shipfox/client-api@6.0.1
20
+ - @shipfox/client-shell@14.0.1
21
+ - @shipfox/client-ui@14.0.1
22
+ - @shipfox/react-ui@1.0.0
23
+
3
24
  ## 14.0.1
4
25
 
5
26
  ### Patch Changes
@@ -7,11 +7,11 @@ export function AddCustomProviderCard({ onConfigure }) {
7
7
  return /*#__PURE__*/ _jsx("li", {
8
8
  children: /*#__PURE__*/ _jsx("button", {
9
9
  type: "button",
10
- className: cn('group block h-full w-full cursor-pointer p-16 text-left outline-none transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus', SURFACE_CLASS),
10
+ className: cn('group block h-full w-full cursor-pointer p-panel-compact text-left outline-none transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus', SURFACE_CLASS),
11
11
  "aria-label": "Configure custom provider",
12
12
  onClick: onConfigure,
13
13
  children: /*#__PURE__*/ _jsxs("div", {
14
- className: "flex min-w-0 items-center justify-between gap-12",
14
+ className: "flex min-w-0 items-center justify-between gap-cluster",
15
15
  children: [
16
16
  /*#__PURE__*/ _jsx(Text, {
17
17
  size: "md",
@@ -20,7 +20,7 @@ export function AddCustomProviderCard({ onConfigure }) {
20
20
  children: "Custom"
21
21
  }),
22
22
  /*#__PURE__*/ _jsxs("div", {
23
- className: "flex shrink-0 items-center gap-4 text-foreground-neutral-muted transition-colors group-hover:text-foreground-highlight-interactive",
23
+ className: "flex shrink-0 items-center gap-tight text-foreground-neutral-muted transition-colors group-hover:text-foreground-highlight-interactive",
24
24
  children: [
25
25
  /*#__PURE__*/ _jsx(Text, {
26
26
  size: "sm",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/add-custom-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';\n\nconst SURFACE_CLASS =\n 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';\n\nexport function AddCustomProviderCard({onConfigure}: {onConfigure: () => void}) {\n return (\n <li>\n <button\n type=\"button\"\n className={cn(\n 'group block h-full 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 custom provider\"\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 Custom\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","AddCustomProviderCard","onConfigure","li","button","type","className","aria-label","onClick","div","size","bold","name"],"mappings":";AAAA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,EAAE,QAAO,0BAA0B;AAE3C,MAAMC,gBACJ;AAEF,OAAO,SAASC,sBAAsB,EAACC,WAAW,EAA4B;IAC5E,qBACE,KAACC;kBACC,cAAA,KAACC;YACCC,MAAK;YACLC,WAAWP,GACT,yKACAC;YAEFO,cAAW;YACXC,SAASN;sBAET,cAAA,MAACO;gBAAIH,WAAU;;kCACb,KAACR;wBAAKY,MAAK;wBAAKC,IAAI;wBAACL,WAAU;kCAAmB;;kCAGlD,MAACG;wBAAIH,WAAU;;0CACb,KAACR;gCAAKY,MAAK;0CAAK;;0CAChB,KAACb;gCAAKe,MAAK;gCAAeN,WAAU;;;;;;;;AAMhD"}
1
+ {"version":3,"sources":["../../src/components/add-custom-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';\n\nconst SURFACE_CLASS =\n 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';\n\nexport function AddCustomProviderCard({onConfigure}: {onConfigure: () => void}) {\n return (\n <li>\n <button\n type=\"button\"\n className={cn(\n 'group block h-full w-full cursor-pointer p-panel-compact 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 custom provider\"\n onClick={onConfigure}\n >\n <div className=\"flex min-w-0 items-center justify-between gap-cluster\">\n <Text size=\"md\" bold className=\"min-w-0 truncate\">\n Custom\n </Text>\n <div className=\"flex shrink-0 items-center gap-tight 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","AddCustomProviderCard","onConfigure","li","button","type","className","aria-label","onClick","div","size","bold","name"],"mappings":";AAAA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,EAAE,QAAO,0BAA0B;AAE3C,MAAMC,gBACJ;AAEF,OAAO,SAASC,sBAAsB,EAACC,WAAW,EAA4B;IAC5E,qBACE,KAACC;kBACC,cAAA,KAACC;YACCC,MAAK;YACLC,WAAWP,GACT,oLACAC;YAEFO,cAAW;YACXC,SAASN;sBAET,cAAA,MAACO;gBAAIH,WAAU;;kCACb,KAACR;wBAAKY,MAAK;wBAAKC,IAAI;wBAACL,WAAU;kCAAmB;;kCAGlD,MAACG;wBAAIH,WAAU;;0CACb,KAACR;gCAAKY,MAAK;0CAAK;;0CAChB,KAACb;gCAAKe,MAAK;gCAAeN,WAAU;;;;;;;;AAMhD"}
@@ -7,11 +7,11 @@ export function AvailableProviderCard({ entry, onConfigure }) {
7
7
  return /*#__PURE__*/ _jsx("li", {
8
8
  children: /*#__PURE__*/ _jsx("button", {
9
9
  type: "button",
10
- className: cn('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', SURFACE_CLASS),
10
+ className: cn('group block w-full cursor-pointer p-panel-compact text-left outline-none transition-colors hover:bg-background-components-hover focus-visible:shadow-button-neutral-focus', SURFACE_CLASS),
11
11
  "aria-label": `Configure ${entry.label}`,
12
12
  onClick: onConfigure,
13
13
  children: /*#__PURE__*/ _jsxs("div", {
14
- className: "flex min-w-0 items-center justify-between gap-12",
14
+ className: "flex min-w-0 items-center justify-between gap-cluster",
15
15
  children: [
16
16
  /*#__PURE__*/ _jsx(Text, {
17
17
  size: "md",
@@ -20,7 +20,7 @@ export function AvailableProviderCard({ entry, onConfigure }) {
20
20
  children: entry.label
21
21
  }),
22
22
  /*#__PURE__*/ _jsxs("div", {
23
- className: "flex shrink-0 items-center gap-4 text-foreground-neutral-muted transition-colors group-hover:text-foreground-highlight-interactive",
23
+ className: "flex shrink-0 items-center gap-tight text-foreground-neutral-muted transition-colors group-hover:text-foreground-highlight-interactive",
24
24
  children: [
25
25
  /*#__PURE__*/ _jsx(Text, {
26
26
  size: "sm",
@@ -1 +1 @@
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
+ {"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-panel-compact 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-cluster\">\n <Text size=\"md\" bold className=\"min-w-0 truncate\">\n {entry.label}\n </Text>\n <div className=\"flex shrink-0 items-center gap-tight 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,6KACAC;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,6 +1,6 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { SupportedProvider } from '#core/models.js';
3
- export declare const PROVIDER_GRID_CLASS = "grid grid-cols-2 gap-12 max-[760px]:grid-cols-1";
3
+ export declare const PROVIDER_GRID_CLASS = "grid grid-cols-2 gap-cluster max-[760px]:grid-cols-1";
4
4
  export declare function AvailableProvidersGrid<TEntry extends SupportedProvider>({ entries, onSelect, trailingCard, trailingCardMatchesSearch, }: {
5
5
  entries: TEntry[];
6
6
  onSelect: (entry: TEntry) => void;
@@ -1 +1 @@
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"}
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,yDAAyD,CAAC;AAK1F,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"}
@@ -6,7 +6,7 @@ import { Input } from '@shipfox/react-ui/input';
6
6
  import { useMemo, useRef, useState } from 'react';
7
7
  import { providerMatchesSearch } from '#core/provider-policy.js';
8
8
  import { AvailableProviderCard } from './available-provider-card.js';
9
- export const PROVIDER_GRID_CLASS = 'grid grid-cols-2 gap-12 max-[760px]:grid-cols-1';
9
+ export const PROVIDER_GRID_CLASS = 'grid grid-cols-2 gap-cluster max-[760px]:grid-cols-1';
10
10
  const SEARCH_VISIBILITY_THRESHOLD = 8;
11
11
  const MAX_ECHOED_QUERY_LENGTH = 40;
12
12
  export function AvailableProvidersGrid({ entries, onSelect, trailingCard, trailingCardMatchesSearch = ()=>true }) {
@@ -27,7 +27,7 @@ export function AvailableProvidersGrid({ entries, onSelect, trailingCard, traili
27
27
  inputRef.current?.focus();
28
28
  }
29
29
  return /*#__PURE__*/ _jsxs("div", {
30
- className: "flex flex-col gap-12",
30
+ className: "flex flex-col gap-cluster",
31
31
  children: [
32
32
  showSearch ? /*#__PURE__*/ _jsx(Input, {
33
33
  ref: inputRef,
@@ -1 +1 @@
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
+ {"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-cluster 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-cluster\">\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,uDAAuD;AAE1F,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"}
@@ -35,11 +35,11 @@ export function ChangeDefaultModelForm({ workspaceId, entry, config, onSaved })
35
35
  return /*#__PURE__*/ _jsxs(_Fragment, {
36
36
  children: [
37
37
  /*#__PURE__*/ _jsxs(ModalBody, {
38
- className: "gap-16",
38
+ className: "gap-group",
39
39
  children: [
40
40
  /*#__PURE__*/ _jsx("form", {
41
41
  id: CHANGE_DEFAULT_MODEL_FORM_ID,
42
- className: "flex w-full flex-col gap-14",
42
+ className: "flex w-full flex-col gap-cluster",
43
43
  noValidate: true,
44
44
  onSubmit: (event)=>{
45
45
  event.preventDefault();
@@ -65,7 +65,7 @@ export function ChangeDefaultModelForm({ workspaceId, entry, config, onSaved })
65
65
  role: "alert",
66
66
  type: "error",
67
67
  children: /*#__PURE__*/ _jsxs("div", {
68
- className: "flex flex-col gap-8",
68
+ className: "flex flex-col gap-inline",
69
69
  children: [
70
70
  /*#__PURE__*/ _jsx(Text, {
71
71
  size: "sm",
@@ -1 +1 @@
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
+ {"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-group\">\n <form\n id={CHANGE_DEFAULT_MODEL_FORM_ID}\n className=\"flex w-full flex-col gap-cluster\"\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-inline\">\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"}
@@ -106,11 +106,11 @@ export function CustomModelProviderForm({ workspaceId, existingConfig, onSaved }
106
106
  return /*#__PURE__*/ _jsxs(_Fragment, {
107
107
  children: [
108
108
  /*#__PURE__*/ _jsxs(ModalBody, {
109
- className: "min-h-0 flex-1 gap-0 overflow-y-auto overflow-x-clip scrollbar",
109
+ className: "min-h-0 flex-1 gap-group overflow-y-auto overflow-x-clip scrollbar",
110
110
  children: [
111
111
  /*#__PURE__*/ _jsx("form", {
112
112
  id: CUSTOM_MODEL_PROVIDER_FORM_ID,
113
- className: "flex w-full flex-col gap-24",
113
+ className: "flex w-full flex-col gap-section",
114
114
  noValidate: true,
115
115
  onSubmit: (event)=>{
116
116
  event.preventDefault();
@@ -125,7 +125,7 @@ export function CustomModelProviderForm({ workspaceId, existingConfig, onSaved }
125
125
  title: "Provider",
126
126
  children: [
127
127
  /*#__PURE__*/ _jsxs("div", {
128
- className: "grid grid-cols-2 gap-12 max-[640px]:grid-cols-1",
128
+ className: "grid grid-cols-2 gap-cluster max-[640px]:grid-cols-1",
129
129
  children: [
130
130
  /*#__PURE__*/ _jsx(form.Field, {
131
131
  name: "display_name",
@@ -176,7 +176,7 @@ export function CustomModelProviderForm({ workspaceId, existingConfig, onSaved }
176
176
  ]
177
177
  }),
178
178
  /*#__PURE__*/ _jsxs("div", {
179
- className: "grid grid-cols-2 gap-12 max-[640px]:grid-cols-1",
179
+ className: "grid grid-cols-2 gap-cluster max-[640px]:grid-cols-1",
180
180
  children: [
181
181
  /*#__PURE__*/ _jsx(form.Field, {
182
182
  name: "api",
@@ -246,7 +246,7 @@ export function CustomModelProviderForm({ workspaceId, existingConfig, onSaved }
246
246
  title: "Models",
247
247
  children: [
248
248
  /*#__PURE__*/ _jsxs("div", {
249
- className: "flex flex-wrap items-center justify-between gap-8",
249
+ className: "flex flex-wrap items-center justify-between gap-inline",
250
250
  children: [
251
251
  /*#__PURE__*/ _jsx(Button, {
252
252
  type: "button",
@@ -340,9 +340,8 @@ export function CustomModelProviderForm({ workspaceId, existingConfig, onSaved }
340
340
  formError ? /*#__PURE__*/ _jsx(Callout, {
341
341
  role: "alert",
342
342
  type: "error",
343
- className: "mt-16",
344
343
  children: /*#__PURE__*/ _jsxs("div", {
345
- className: "flex flex-col gap-8",
344
+ className: "flex flex-col gap-inline",
346
345
  children: [
347
346
  /*#__PURE__*/ _jsx(Text, {
348
347
  size: "sm",
@@ -378,7 +377,7 @@ export function CustomModelProviderForm({ workspaceId, existingConfig, onSaved }
378
377
  }
379
378
  function FormGroup({ title, children }) {
380
379
  return /*#__PURE__*/ _jsxs("section", {
381
- className: "flex flex-col gap-16 border-t border-border-neutral-base pt-16 first:border-t-0 first:pt-0",
380
+ className: "flex flex-col gap-group border-t border-border-neutral-base pt-[16px] first:border-t-0 first:pt-0",
382
381
  children: [
383
382
  /*#__PURE__*/ _jsx(Text, {
384
383
  size: "xs",
@@ -392,10 +391,10 @@ function FormGroup({ title, children }) {
392
391
  function HeaderRows({ rows, onChange }) {
393
392
  const addButtonRef = useRef(null);
394
393
  return /*#__PURE__*/ _jsxs("div", {
395
- className: "flex flex-col gap-10",
394
+ className: "flex flex-col gap-inline",
396
395
  children: [
397
396
  rows.map((row, index)=>/*#__PURE__*/ _jsxs("div", {
398
- className: "grid grid-cols-[1fr_1fr_auto_auto] items-end gap-x-8 gap-y-4 max-[760px]:grid-cols-1",
397
+ className: "grid grid-cols-[1fr_1fr_auto_auto] items-end gap-x-inline gap-y-tight max-[760px]:grid-cols-1",
399
398
  children: [
400
399
  /*#__PURE__*/ _jsx(FormField, {
401
400
  label: "Name",
@@ -423,7 +422,7 @@ function HeaderRows({ rows, onChange }) {
423
422
  })
424
423
  }),
425
424
  /*#__PURE__*/ _jsxs("div", {
426
- className: "flex h-32 items-center gap-8 text-sm text-foreground-neutral-muted",
425
+ className: "flex h-32 items-center gap-inline text-sm text-foreground-neutral-muted",
427
426
  children: [
428
427
  /*#__PURE__*/ _jsx(Switch, {
429
428
  size: "sm",
@@ -479,13 +478,13 @@ function HeaderRows({ rows, onChange }) {
479
478
  function ModelRows({ rows, defaultModel, onChange, onDefaultChange, onDefaultRemoved }) {
480
479
  const addButtonRef = useRef(null);
481
480
  return /*#__PURE__*/ _jsxs("div", {
482
- className: "flex flex-col gap-10",
481
+ className: "flex flex-col gap-inline",
483
482
  children: [
484
483
  rows.map((row, index)=>/*#__PURE__*/ _jsxs("div", {
485
- className: "rounded-8 border border-border-neutral-base p-12",
484
+ className: "flex flex-col gap-inline rounded-8 border border-border-neutral-base p-panel-compact",
486
485
  children: [
487
486
  /*#__PURE__*/ _jsxs("div", {
488
- className: "grid grid-cols-[1fr_1fr_auto] items-end gap-8 max-[760px]:grid-cols-1",
487
+ className: "grid grid-cols-[1fr_1fr_auto] items-end gap-inline max-[760px]:grid-cols-1",
489
488
  children: [
490
489
  /*#__PURE__*/ _jsx(FormField, {
491
490
  label: "Model id",
@@ -511,7 +510,7 @@ function ModelRows({ rows, defaultModel, onChange, onDefaultChange, onDefaultRem
511
510
  })
512
511
  }),
513
512
  /*#__PURE__*/ _jsxs("div", {
514
- className: "flex items-center gap-8",
513
+ className: "flex items-center gap-inline",
515
514
  children: [
516
515
  defaultModel && row.id === defaultModel ? /*#__PURE__*/ _jsx(Badge, {
517
516
  variant: "neutral",
@@ -538,6 +537,7 @@ function ModelRows({ rows, defaultModel, onChange, onDefaultChange, onDefaultRem
538
537
  ]
539
538
  }),
540
539
  /*#__PURE__*/ _jsxs(Collapsible, {
540
+ className: "flex flex-col",
541
541
  children: [
542
542
  /*#__PURE__*/ _jsx(CollapsibleTrigger, {
543
543
  asChild: true,
@@ -545,13 +545,12 @@ function ModelRows({ rows, defaultModel, onChange, onDefaultChange, onDefaultRem
545
545
  type: "button",
546
546
  size: "sm",
547
547
  variant: "transparentMuted",
548
- className: "mt-8",
549
548
  children: "Defaults: 128k context, 16k output, text-only"
550
549
  })
551
550
  }),
552
551
  /*#__PURE__*/ _jsx(CollapsibleContent, {
553
552
  children: /*#__PURE__*/ _jsxs("div", {
554
- className: "mt-8 grid grid-cols-2 gap-8 max-[640px]:grid-cols-1",
553
+ className: "grid grid-cols-2 gap-inline pt-[8px] max-[640px]:grid-cols-1",
555
554
  children: [
556
555
  /*#__PURE__*/ _jsx(FormField, {
557
556
  label: "Context window",
@@ -582,7 +581,7 @@ function ModelRows({ rows, defaultModel, onChange, onDefaultChange, onDefaultRem
582
581
  })
583
582
  }),
584
583
  /*#__PURE__*/ _jsxs("div", {
585
- className: "flex h-32 items-center gap-8 text-sm text-foreground-neutral-muted",
584
+ className: "flex h-32 items-center gap-inline text-sm text-foreground-neutral-muted",
586
585
  children: [
587
586
  /*#__PURE__*/ _jsx(Switch, {
588
587
  size: "sm",
@@ -597,7 +596,7 @@ function ModelRows({ rows, defaultModel, onChange, onDefaultChange, onDefaultRem
597
596
  ]
598
597
  }),
599
598
  /*#__PURE__*/ _jsxs("div", {
600
- className: "flex h-32 items-center gap-8 text-sm text-foreground-neutral-muted",
599
+ className: "flex h-32 items-center gap-inline text-sm text-foreground-neutral-muted",
601
600
  children: [
602
601
  /*#__PURE__*/ _jsx(Switch, {
603
602
  size: "sm",