@shipfox/client-agent 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/main.ts +1 -0
- package/.storybook/preview.css +4 -0
- package/.storybook/preview.tsx +56 -0
- package/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +93 -0
- package/LICENSE +21 -0
- package/dist/components/add-custom-provider-card.d.ts +4 -0
- package/dist/components/add-custom-provider-card.d.ts.map +1 -0
- package/dist/components/add-custom-provider-card.js +41 -0
- package/dist/components/add-custom-provider-card.js.map +1 -0
- package/dist/components/agent-workflow-example.d.ts +11 -0
- package/dist/components/agent-workflow-example.d.ts.map +1 -0
- package/dist/components/agent-workflow-example.js +38 -0
- package/dist/components/agent-workflow-example.js.map +1 -0
- package/dist/components/available-provider-card.d.ts +6 -0
- package/dist/components/available-provider-card.d.ts.map +1 -0
- package/dist/components/available-provider-card.js +41 -0
- package/dist/components/available-provider-card.js.map +1 -0
- package/dist/components/available-providers-grid.d.ts +10 -0
- package/dist/components/available-providers-grid.d.ts.map +1 -0
- package/dist/components/available-providers-grid.js +89 -0
- package/dist/components/available-providers-grid.js.map +1 -0
- package/dist/components/change-default-model-form.d.ts +9 -0
- package/dist/components/change-default-model-form.d.ts.map +1 -0
- package/dist/components/change-default-model-form.js +98 -0
- package/dist/components/change-default-model-form.js.map +1 -0
- package/dist/components/custom-model-provider-api-options.d.ts +7 -0
- package/dist/components/custom-model-provider-api-options.d.ts.map +1 -0
- package/dist/components/custom-model-provider-api-options.js +23 -0
- package/dist/components/custom-model-provider-api-options.js.map +1 -0
- package/dist/components/custom-model-provider-form.d.ts +8 -0
- package/dist/components/custom-model-provider-form.d.ts.map +1 -0
- package/dist/components/custom-model-provider-form.js +667 -0
- package/dist/components/custom-model-provider-form.js.map +1 -0
- package/dist/components/custom-model-provider-form.stories.d.ts +20 -0
- package/dist/components/custom-model-provider-form.stories.d.ts.map +1 -0
- package/dist/components/custom-model-provider-form.stories.js +104 -0
- package/dist/components/custom-model-provider-form.stories.js.map +1 -0
- package/dist/components/custom-model-provider-payload.d.ts +39 -0
- package/dist/components/custom-model-provider-payload.d.ts.map +1 -0
- package/dist/components/custom-model-provider-payload.js +203 -0
- package/dist/components/custom-model-provider-payload.js.map +1 -0
- package/dist/components/custom-model-provider-slug.d.ts +3 -0
- package/dist/components/custom-model-provider-slug.d.ts.map +1 -0
- package/dist/components/custom-model-provider-slug.js +14 -0
- package/dist/components/custom-model-provider-slug.js.map +1 -0
- package/dist/components/default-model-field.d.ts +16 -0
- package/dist/components/default-model-field.d.ts.map +1 -0
- package/dist/components/default-model-field.js +60 -0
- package/dist/components/default-model-field.js.map +1 -0
- package/dist/components/form-errors.d.ts +11 -0
- package/dist/components/form-errors.d.ts.map +1 -0
- package/dist/components/form-errors.js +101 -0
- package/dist/components/form-errors.js.map +1 -0
- package/dist/components/harness-availability.d.ts +8 -0
- package/dist/components/harness-availability.d.ts.map +1 -0
- package/dist/components/harness-availability.js +16 -0
- package/dist/components/harness-availability.js.map +1 -0
- package/dist/components/harnesses-section.d.ts +4 -0
- package/dist/components/harnesses-section.d.ts.map +1 -0
- package/dist/components/harnesses-section.js +249 -0
- package/dist/components/harnesses-section.js.map +1 -0
- package/dist/components/harnesses-section.stories.d.ts +25 -0
- package/dist/components/harnesses-section.stories.d.ts.map +1 -0
- package/dist/components/harnesses-section.stories.js +138 -0
- package/dist/components/harnesses-section.stories.js.map +1 -0
- package/dist/components/model-provider-usage-modal.d.ts +11 -0
- package/dist/components/model-provider-usage-modal.d.ts.map +1 -0
- package/dist/components/model-provider-usage-modal.js +349 -0
- package/dist/components/model-provider-usage-modal.js.map +1 -0
- package/dist/components/model-provider-usage-modal.stories.d.ts +21 -0
- package/dist/components/model-provider-usage-modal.stories.d.ts.map +1 -0
- package/dist/components/model-provider-usage-modal.stories.js +115 -0
- package/dist/components/model-provider-usage-modal.stories.js.map +1 -0
- package/dist/components/model-provider-usage-target.d.ts +14 -0
- package/dist/components/model-provider-usage-target.d.ts.map +1 -0
- package/dist/components/model-provider-usage-target.js +20 -0
- package/dist/components/model-provider-usage-target.js.map +1 -0
- package/dist/components/model-providers-section.d.ts +4 -0
- package/dist/components/model-providers-section.d.ts.map +1 -0
- package/dist/components/model-providers-section.js +668 -0
- package/dist/components/model-providers-section.js.map +1 -0
- package/dist/components/model-providers-section.stories.d.ts +32 -0
- package/dist/components/model-providers-section.stories.d.ts.map +1 -0
- package/dist/components/model-providers-section.stories.js +442 -0
- package/dist/components/model-providers-section.stories.js.map +1 -0
- package/dist/components/provider-search.d.ts +4 -0
- package/dist/components/provider-search.d.ts.map +1 -0
- package/dist/components/provider-search.js +13 -0
- package/dist/components/provider-search.js.map +1 -0
- package/dist/components/supported-model-provider-catalog-entry.d.ts +8 -0
- package/dist/components/supported-model-provider-catalog-entry.d.ts.map +1 -0
- package/dist/components/supported-model-provider-catalog-entry.js +9 -0
- package/dist/components/supported-model-provider-catalog-entry.js.map +1 -0
- package/dist/components/test-and-save-form.d.ts +10 -0
- package/dist/components/test-and-save-form.d.ts.map +1 -0
- package/dist/components/test-and-save-form.js +138 -0
- package/dist/components/test-and-save-form.js.map +1 -0
- package/dist/feature.d.ts +9 -0
- package/dist/feature.d.ts.map +1 -0
- package/dist/feature.js +13 -0
- package/dist/feature.js.map +1 -0
- package/dist/hooks/api/model-providers.d.ts +334 -0
- package/dist/hooks/api/model-providers.d.ts.map +1 -0
- package/dist/hooks/api/model-providers.js +190 -0
- package/dist/hooks/api/model-providers.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/pages/model-provider-onboarding-page.d.ts +6 -0
- package/dist/pages/model-provider-onboarding-page.d.ts.map +1 -0
- package/dist/pages/model-provider-onboarding-page.js +295 -0
- package/dist/pages/model-provider-onboarding-page.js.map +1 -0
- package/dist/pages/model-provider-onboarding-page.stories.d.ts +27 -0
- package/dist/pages/model-provider-onboarding-page.stories.d.ts.map +1 -0
- package/dist/pages/model-provider-onboarding-page.stories.js +368 -0
- package/dist/pages/model-provider-onboarding-page.stories.js.map +1 -0
- package/dist/routes/model-provider.d.ts +5 -0
- package/dist/routes/model-provider.d.ts.map +1 -0
- package/dist/routes/model-provider.js +28 -0
- package/dist/routes/model-provider.js.map +1 -0
- package/dist/state/model-provider-onboarding.d.ts +3 -0
- package/dist/state/model-provider-onboarding.d.ts.map +1 -0
- package/dist/state/model-provider-onboarding.js +28 -0
- package/dist/state/model-provider-onboarding.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/package.json +114 -0
- package/src/components/add-custom-provider-card.tsx +32 -0
- package/src/components/agent-workflow-example.test.ts +74 -0
- package/src/components/agent-workflow-example.ts +55 -0
- package/src/components/available-provider-card.tsx +39 -0
- package/src/components/available-providers-grid.test.tsx +55 -0
- package/src/components/available-providers-grid.tsx +106 -0
- package/src/components/change-default-model-form.tsx +104 -0
- package/src/components/custom-model-provider-api-options.test.ts +18 -0
- package/src/components/custom-model-provider-api-options.ts +12 -0
- package/src/components/custom-model-provider-form.stories.tsx +91 -0
- package/src/components/custom-model-provider-form.tsx +710 -0
- package/src/components/custom-model-provider-payload.test.ts +170 -0
- package/src/components/custom-model-provider-payload.ts +264 -0
- package/src/components/custom-model-provider-slug.test.ts +40 -0
- package/src/components/custom-model-provider-slug.ts +23 -0
- package/src/components/default-model-field.tsx +85 -0
- package/src/components/form-errors.test.ts +159 -0
- package/src/components/form-errors.ts +102 -0
- package/src/components/harness-availability.test.ts +45 -0
- package/src/components/harness-availability.ts +35 -0
- package/src/components/harnesses-section.stories.tsx +129 -0
- package/src/components/harnesses-section.test.tsx +188 -0
- package/src/components/harnesses-section.tsx +245 -0
- package/src/components/model-provider-usage-modal.stories.tsx +106 -0
- package/src/components/model-provider-usage-modal.test.tsx +210 -0
- package/src/components/model-provider-usage-modal.tsx +326 -0
- package/src/components/model-provider-usage-target.ts +36 -0
- package/src/components/model-providers-section.stories.tsx +345 -0
- package/src/components/model-providers-section.test.tsx +831 -0
- package/src/components/model-providers-section.tsx +645 -0
- package/src/components/provider-search.test.ts +45 -0
- package/src/components/provider-search.ts +18 -0
- package/src/components/supported-model-provider-catalog-entry.ts +19 -0
- package/src/components/test-and-save-form.tsx +166 -0
- package/src/feature.ts +12 -0
- package/src/hooks/api/model-providers.test.ts +167 -0
- package/src/hooks/api/model-providers.ts +281 -0
- package/src/index.ts +8 -0
- package/src/pages/model-provider-onboarding-page.stories.tsx +284 -0
- package/src/pages/model-provider-onboarding-page.test.tsx +368 -0
- package/src/pages/model-provider-onboarding-page.tsx +290 -0
- package/src/routes/model-provider.tsx +20 -0
- package/src/state/model-provider-onboarding.test.ts +55 -0
- package/src/state/model-provider-onboarding.ts +34 -0
- package/test/fixtures/model-providers.ts +111 -0
- package/test/setup.ts +3 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/tsconfig.test.json +8 -0
- package/vercel.json +8 -0
- package/vitest.config.ts +72 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { configureApiClient } from '@shipfox/client-api';
|
|
3
|
+
import { Toaster } from '@shipfox/react-ui/toast';
|
|
4
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
5
|
+
import { useMemo } from 'react';
|
|
6
|
+
import { WorkspaceHarnessesSection } from './harnesses-section.js';
|
|
7
|
+
const WORKSPACE_ID = '11111111-1111-4111-8111-111111111111';
|
|
8
|
+
function HarnessesStory({ scenario }) {
|
|
9
|
+
configureApiClient({
|
|
10
|
+
baseUrl: 'https://api.example.test',
|
|
11
|
+
fetchImpl: fetchForScenario(scenario)
|
|
12
|
+
});
|
|
13
|
+
const queryClient = useMemo(()=>new QueryClient({
|
|
14
|
+
defaultOptions: {
|
|
15
|
+
queries: {
|
|
16
|
+
retry: false
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}), []);
|
|
20
|
+
return /*#__PURE__*/ _jsxs(QueryClientProvider, {
|
|
21
|
+
client: queryClient,
|
|
22
|
+
children: [
|
|
23
|
+
/*#__PURE__*/ _jsx("div", {
|
|
24
|
+
className: "mx-auto w-full max-w-[760px] bg-background-neutral-background p-24",
|
|
25
|
+
children: /*#__PURE__*/ _jsx(WorkspaceHarnessesSection, {
|
|
26
|
+
workspaceId: WORKSPACE_ID
|
|
27
|
+
})
|
|
28
|
+
}),
|
|
29
|
+
/*#__PURE__*/ _jsx(Toaster, {})
|
|
30
|
+
]
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
const meta = {
|
|
34
|
+
title: 'Agent/HarnessSettings',
|
|
35
|
+
component: HarnessesStory,
|
|
36
|
+
parameters: {
|
|
37
|
+
layout: 'fullscreen'
|
|
38
|
+
},
|
|
39
|
+
args: {
|
|
40
|
+
scenario: 'default-pi'
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
export default meta;
|
|
44
|
+
export const Playground = {};
|
|
45
|
+
export const DefaultClaude = {
|
|
46
|
+
args: {
|
|
47
|
+
scenario: 'default-claude'
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
export const ClaudeUnavailable = {
|
|
51
|
+
args: {
|
|
52
|
+
scenario: 'claude-unavailable'
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
export const DefaultClaudeUnavailable = {
|
|
56
|
+
args: {
|
|
57
|
+
scenario: 'default-claude-unavailable'
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
export const Loading = {
|
|
61
|
+
args: {
|
|
62
|
+
scenario: 'loading'
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
export const ErrorState = {
|
|
66
|
+
args: {
|
|
67
|
+
scenario: 'error'
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
function fetchForScenario(scenario) {
|
|
71
|
+
return ()=>{
|
|
72
|
+
if (scenario === 'loading') return new Promise(()=>undefined);
|
|
73
|
+
if (scenario === 'error') return Promise.resolve(errorResponse());
|
|
74
|
+
return Promise.resolve(jsonResponse(configsForScenario(scenario)));
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function configsForScenario(scenario) {
|
|
78
|
+
if (scenario === 'claude-unavailable') {
|
|
79
|
+
return {
|
|
80
|
+
configs: [
|
|
81
|
+
providerConfig({
|
|
82
|
+
provider_id: 'openai'
|
|
83
|
+
})
|
|
84
|
+
],
|
|
85
|
+
default_provider_id: 'openai',
|
|
86
|
+
default_harness_id: null
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (scenario === 'default-claude-unavailable') {
|
|
90
|
+
return {
|
|
91
|
+
configs: [
|
|
92
|
+
providerConfig({
|
|
93
|
+
provider_id: 'openai'
|
|
94
|
+
})
|
|
95
|
+
],
|
|
96
|
+
default_provider_id: 'openai',
|
|
97
|
+
default_harness_id: 'claude'
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
configs: [
|
|
102
|
+
providerConfig({
|
|
103
|
+
provider_id: 'anthropic'
|
|
104
|
+
})
|
|
105
|
+
],
|
|
106
|
+
default_provider_id: 'anthropic',
|
|
107
|
+
default_harness_id: scenario === 'default-claude' ? 'claude' : null
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function providerConfig(overrides = {}) {
|
|
111
|
+
return {
|
|
112
|
+
kind: 'builtin',
|
|
113
|
+
provider_id: 'anthropic',
|
|
114
|
+
default_model: null,
|
|
115
|
+
created_at: '2026-05-08T00:00:00.000Z',
|
|
116
|
+
updated_at: '2026-05-08T00:00:00.000Z',
|
|
117
|
+
...overrides
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function jsonResponse(body, init = {}) {
|
|
121
|
+
return new Response(JSON.stringify(body), {
|
|
122
|
+
status: 200,
|
|
123
|
+
headers: {
|
|
124
|
+
'content-type': 'application/json'
|
|
125
|
+
},
|
|
126
|
+
...init
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function errorResponse() {
|
|
130
|
+
return jsonResponse({
|
|
131
|
+
code: 'server-error'
|
|
132
|
+
}, {
|
|
133
|
+
status: 500,
|
|
134
|
+
statusText: 'Server error'
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
//# sourceMappingURL=harnesses-section.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/harnesses-section.stories.tsx"],"sourcesContent":["import type {ModelProviderConfigDto} from '@shipfox/api-agent-dto';\nimport {configureApiClient} from '@shipfox/client-api';\nimport {Toaster} from '@shipfox/react-ui/toast';\nimport type {Meta, StoryObj} from '@storybook/react';\nimport {QueryClient, QueryClientProvider} from '@tanstack/react-query';\nimport {useMemo} from 'react';\nimport {WorkspaceHarnessesSection} from './harnesses-section.js';\n\nconst WORKSPACE_ID = '11111111-1111-4111-8111-111111111111';\n\ntype Scenario =\n | 'default-pi'\n | 'default-claude'\n | 'claude-unavailable'\n | 'default-claude-unavailable'\n | 'loading'\n | 'error';\n\ninterface HarnessesStoryProps {\n scenario: Scenario;\n}\n\nfunction HarnessesStory({scenario}: HarnessesStoryProps) {\n configureApiClient({\n baseUrl: 'https://api.example.test',\n fetchImpl: fetchForScenario(scenario),\n });\n\n const queryClient = useMemo(\n () => new QueryClient({defaultOptions: {queries: {retry: false}}}),\n [],\n );\n\n return (\n <QueryClientProvider client={queryClient}>\n <div className=\"mx-auto w-full max-w-[760px] bg-background-neutral-background p-24\">\n <WorkspaceHarnessesSection workspaceId={WORKSPACE_ID} />\n </div>\n <Toaster />\n </QueryClientProvider>\n );\n}\n\nconst meta = {\n title: 'Agent/HarnessSettings',\n component: HarnessesStory,\n parameters: {layout: 'fullscreen'},\n args: {scenario: 'default-pi'},\n} satisfies Meta<typeof HarnessesStory>;\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Playground: Story = {};\n\nexport const DefaultClaude: Story = {\n args: {scenario: 'default-claude'},\n};\n\nexport const ClaudeUnavailable: Story = {\n args: {scenario: 'claude-unavailable'},\n};\n\nexport const DefaultClaudeUnavailable: Story = {\n args: {scenario: 'default-claude-unavailable'},\n};\n\nexport const Loading: Story = {\n args: {scenario: 'loading'},\n};\n\nexport const ErrorState: Story = {\n args: {scenario: 'error'},\n};\n\nfunction fetchForScenario(scenario: Scenario): typeof fetch {\n return () => {\n if (scenario === 'loading') return new Promise<Response>(() => undefined);\n if (scenario === 'error') return Promise.resolve(errorResponse());\n return Promise.resolve(jsonResponse(configsForScenario(scenario)));\n };\n}\n\nfunction configsForScenario(scenario: Scenario) {\n if (scenario === 'claude-unavailable') {\n return {\n configs: [providerConfig({provider_id: 'openai'})],\n default_provider_id: 'openai',\n default_harness_id: null,\n };\n }\n if (scenario === 'default-claude-unavailable') {\n return {\n configs: [providerConfig({provider_id: 'openai'})],\n default_provider_id: 'openai',\n default_harness_id: 'claude',\n };\n }\n return {\n configs: [providerConfig({provider_id: 'anthropic'})],\n default_provider_id: 'anthropic',\n default_harness_id: scenario === 'default-claude' ? 'claude' : null,\n };\n}\n\nfunction providerConfig(\n overrides: Partial<Omit<ModelProviderConfigDto, 'kind'>> = {},\n): ModelProviderConfigDto {\n return {\n kind: 'builtin',\n provider_id: 'anthropic',\n default_model: null,\n created_at: '2026-05-08T00:00:00.000Z',\n updated_at: '2026-05-08T00:00:00.000Z',\n ...overrides,\n };\n}\n\nfunction jsonResponse(body: unknown, init: ResponseInit = {}) {\n return new Response(JSON.stringify(body), {\n status: 200,\n headers: {'content-type': 'application/json'},\n ...init,\n });\n}\n\nfunction errorResponse() {\n return jsonResponse({code: 'server-error'}, {status: 500, statusText: 'Server error'});\n}\n"],"names":["configureApiClient","Toaster","QueryClient","QueryClientProvider","useMemo","WorkspaceHarnessesSection","WORKSPACE_ID","HarnessesStory","scenario","baseUrl","fetchImpl","fetchForScenario","queryClient","defaultOptions","queries","retry","client","div","className","workspaceId","meta","title","component","parameters","layout","args","Playground","DefaultClaude","ClaudeUnavailable","DefaultClaudeUnavailable","Loading","ErrorState","Promise","undefined","resolve","errorResponse","jsonResponse","configsForScenario","configs","providerConfig","provider_id","default_provider_id","default_harness_id","overrides","kind","default_model","created_at","updated_at","body","init","Response","JSON","stringify","status","headers","code","statusText"],"mappings":";AACA,SAAQA,kBAAkB,QAAO,sBAAsB;AACvD,SAAQC,OAAO,QAAO,0BAA0B;AAEhD,SAAQC,WAAW,EAAEC,mBAAmB,QAAO,wBAAwB;AACvE,SAAQC,OAAO,QAAO,QAAQ;AAC9B,SAAQC,yBAAyB,QAAO,yBAAyB;AAEjE,MAAMC,eAAe;AAcrB,SAASC,eAAe,EAACC,QAAQ,EAAsB;IACrDR,mBAAmB;QACjBS,SAAS;QACTC,WAAWC,iBAAiBH;IAC9B;IAEA,MAAMI,cAAcR,QAClB,IAAM,IAAIF,YAAY;YAACW,gBAAgB;gBAACC,SAAS;oBAACC,OAAO;gBAAK;YAAC;QAAC,IAChE,EAAE;IAGJ,qBACE,MAACZ;QAAoBa,QAAQJ;;0BAC3B,KAACK;gBAAIC,WAAU;0BACb,cAAA,KAACb;oBAA0Bc,aAAab;;;0BAE1C,KAACL;;;AAGP;AAEA,MAAMmB,OAAO;IACXC,OAAO;IACPC,WAAWf;IACXgB,YAAY;QAACC,QAAQ;IAAY;IACjCC,MAAM;QAACjB,UAAU;IAAY;AAC/B;AAEA,eAAeY,KAAK;AAGpB,OAAO,MAAMM,aAAoB,CAAC,EAAE;AAEpC,OAAO,MAAMC,gBAAuB;IAClCF,MAAM;QAACjB,UAAU;IAAgB;AACnC,EAAE;AAEF,OAAO,MAAMoB,oBAA2B;IACtCH,MAAM;QAACjB,UAAU;IAAoB;AACvC,EAAE;AAEF,OAAO,MAAMqB,2BAAkC;IAC7CJ,MAAM;QAACjB,UAAU;IAA4B;AAC/C,EAAE;AAEF,OAAO,MAAMsB,UAAiB;IAC5BL,MAAM;QAACjB,UAAU;IAAS;AAC5B,EAAE;AAEF,OAAO,MAAMuB,aAAoB;IAC/BN,MAAM;QAACjB,UAAU;IAAO;AAC1B,EAAE;AAEF,SAASG,iBAAiBH,QAAkB;IAC1C,OAAO;QACL,IAAIA,aAAa,WAAW,OAAO,IAAIwB,QAAkB,IAAMC;QAC/D,IAAIzB,aAAa,SAAS,OAAOwB,QAAQE,OAAO,CAACC;QACjD,OAAOH,QAAQE,OAAO,CAACE,aAAaC,mBAAmB7B;IACzD;AACF;AAEA,SAAS6B,mBAAmB7B,QAAkB;IAC5C,IAAIA,aAAa,sBAAsB;QACrC,OAAO;YACL8B,SAAS;gBAACC,eAAe;oBAACC,aAAa;gBAAQ;aAAG;YAClDC,qBAAqB;YACrBC,oBAAoB;QACtB;IACF;IACA,IAAIlC,aAAa,8BAA8B;QAC7C,OAAO;YACL8B,SAAS;gBAACC,eAAe;oBAACC,aAAa;gBAAQ;aAAG;YAClDC,qBAAqB;YACrBC,oBAAoB;QACtB;IACF;IACA,OAAO;QACLJ,SAAS;YAACC,eAAe;gBAACC,aAAa;YAAW;SAAG;QACrDC,qBAAqB;QACrBC,oBAAoBlC,aAAa,mBAAmB,WAAW;IACjE;AACF;AAEA,SAAS+B,eACPI,YAA2D,CAAC,CAAC;IAE7D,OAAO;QACLC,MAAM;QACNJ,aAAa;QACbK,eAAe;QACfC,YAAY;QACZC,YAAY;QACZ,GAAGJ,SAAS;IACd;AACF;AAEA,SAASP,aAAaY,IAAa,EAAEC,OAAqB,CAAC,CAAC;IAC1D,OAAO,IAAIC,SAASC,KAAKC,SAAS,CAACJ,OAAO;QACxCK,QAAQ;QACRC,SAAS;YAAC,gBAAgB;QAAkB;QAC5C,GAAGL,IAAI;IACT;AACF;AAEA,SAASd;IACP,OAAOC,aAAa;QAACmB,MAAM;IAAc,GAAG;QAACF,QAAQ;QAAKG,YAAY;IAAc;AACtF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Harness } from '@shipfox/api-agent-dto';
|
|
2
|
+
import type { ModelProviderUsageTarget } from './model-provider-usage-target.js';
|
|
3
|
+
export declare function ModelProviderUsageModal({ target, initialModel, open, onOpenChange, closeFocusTarget, workspaceDefaultHarnessId, }: {
|
|
4
|
+
target: ModelProviderUsageTarget | null;
|
|
5
|
+
initialModel?: string | null | undefined;
|
|
6
|
+
open: boolean;
|
|
7
|
+
onOpenChange: (open: boolean) => void;
|
|
8
|
+
closeFocusTarget?: HTMLElement | null | undefined;
|
|
9
|
+
workspaceDefaultHarnessId?: Harness | null | undefined;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=model-provider-usage-modal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-provider-usage-modal.d.ts","sourceRoot":"","sources":["../../src/components/model-provider-usage-modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,OAAO,EAEb,MAAM,wBAAwB,CAAC;AA2BhC,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,kCAAkC,CAAC;AAM/E,wBAAgB,uBAAuB,CAAC,EACtC,MAAM,EACN,YAAY,EACZ,IAAI,EACJ,YAAY,EACZ,gBAAgB,EAChB,yBAAyB,GAC1B,EAAE;IACD,MAAM,EAAE,wBAAwB,GAAG,IAAI,CAAC;IACxC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,gBAAgB,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IAClD,yBAAyB,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;CACxD,+BA0LA"}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { DEFAULT_HARNESS, getHarnessDescriptor, listHarnessDescriptors } from '@shipfox/api-agent-dto';
|
|
3
|
+
import { Button } from '@shipfox/react-ui/button';
|
|
4
|
+
import { CodeBlock, CodeBlockBody, CodeBlockContent, CodeBlockCopyButton, CodeBlockFilename, CodeBlockFiles, CodeBlockHeader, CodeBlockItem } from '@shipfox/react-ui/code-block';
|
|
5
|
+
import { Combobox } from '@shipfox/react-ui/combobox';
|
|
6
|
+
import { useCopyToClipboard } from '@shipfox/react-ui/hooks';
|
|
7
|
+
import { Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, ModalTitle } from '@shipfox/react-ui/modal';
|
|
8
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from '@shipfox/react-ui/tooltip';
|
|
9
|
+
import { Code, Text } from '@shipfox/react-ui/typography';
|
|
10
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
11
|
+
import { buildAgentWorkflowExample } from './agent-workflow-example.js';
|
|
12
|
+
import { compatibleHarnessIds } from './harness-availability.js';
|
|
13
|
+
const WORKFLOW_EXAMPLE_FILENAME = '.shipfox/workflows/agent.yml';
|
|
14
|
+
export function ModelProviderUsageModal({ target, initialModel, open, onOpenChange, closeFocusTarget, workspaceDefaultHarnessId }) {
|
|
15
|
+
const [selectedModel, setSelectedModel] = useState('');
|
|
16
|
+
const [selectedHarness, setSelectedHarness] = useState(DEFAULT_HARNESS);
|
|
17
|
+
useEffect(()=>{
|
|
18
|
+
if (!target) return;
|
|
19
|
+
setSelectedModel(initialModel ?? target.default_model ?? target.models[0]?.id ?? '');
|
|
20
|
+
}, [
|
|
21
|
+
target,
|
|
22
|
+
initialModel
|
|
23
|
+
]);
|
|
24
|
+
useEffect(()=>{
|
|
25
|
+
if (!target) return;
|
|
26
|
+
const nextCompatibleHarnessIds = compatibleHarnessIds({
|
|
27
|
+
isCustom: target.isCustom,
|
|
28
|
+
providerId: target.id
|
|
29
|
+
});
|
|
30
|
+
setSelectedHarness(selectInitialHarness(nextCompatibleHarnessIds, workspaceDefaultHarnessId));
|
|
31
|
+
}, [
|
|
32
|
+
target,
|
|
33
|
+
workspaceDefaultHarnessId
|
|
34
|
+
]);
|
|
35
|
+
const compatibleIds = useMemo(()=>target ? compatibleHarnessIds({
|
|
36
|
+
isCustom: target.isCustom,
|
|
37
|
+
providerId: target.id
|
|
38
|
+
}) : [], [
|
|
39
|
+
target
|
|
40
|
+
]);
|
|
41
|
+
const harnessOptions = useMemo(()=>compatibleIds.map((harnessId)=>({
|
|
42
|
+
value: harnessId,
|
|
43
|
+
label: getHarnessDescriptor(harnessId).label
|
|
44
|
+
})), [
|
|
45
|
+
compatibleIds
|
|
46
|
+
]);
|
|
47
|
+
const modelOptions = useMemo(()=>target?.models.map((model)=>({
|
|
48
|
+
value: model.id,
|
|
49
|
+
label: model.label
|
|
50
|
+
})) ?? [], [
|
|
51
|
+
target
|
|
52
|
+
]);
|
|
53
|
+
const example = target ? buildAgentWorkflowExample({
|
|
54
|
+
harness: selectedHarness,
|
|
55
|
+
providerId: target.id,
|
|
56
|
+
model: selectedModel
|
|
57
|
+
}) : null;
|
|
58
|
+
const data = example === null ? [] : [
|
|
59
|
+
{
|
|
60
|
+
language: 'yaml',
|
|
61
|
+
filename: WORKFLOW_EXAMPLE_FILENAME,
|
|
62
|
+
code: example.code
|
|
63
|
+
}
|
|
64
|
+
];
|
|
65
|
+
function handleOpenChange(nextOpen) {
|
|
66
|
+
onOpenChange(nextOpen);
|
|
67
|
+
if (!nextOpen && closeFocusTarget) {
|
|
68
|
+
window.setTimeout(()=>closeFocusTarget.focus(), 0);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return /*#__PURE__*/ _jsx(Modal, {
|
|
72
|
+
open: open && target !== null,
|
|
73
|
+
onOpenChange: handleOpenChange,
|
|
74
|
+
children: /*#__PURE__*/ _jsxs(ModalContent, {
|
|
75
|
+
"aria-describedby": undefined,
|
|
76
|
+
className: "max-h-[calc(100vh-32px)] max-w-[640px]",
|
|
77
|
+
children: [
|
|
78
|
+
/*#__PURE__*/ _jsx(ModalTitle, {
|
|
79
|
+
className: "sr-only",
|
|
80
|
+
children: target ? `Use ${target.label} in a workflow` : 'Use provider in a workflow'
|
|
81
|
+
}),
|
|
82
|
+
/*#__PURE__*/ _jsx(ModalHeader, {
|
|
83
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
84
|
+
className: "flex min-w-0 flex-col gap-2",
|
|
85
|
+
children: [
|
|
86
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
87
|
+
size: "lg",
|
|
88
|
+
"aria-hidden": "true",
|
|
89
|
+
className: "truncate",
|
|
90
|
+
children: target ? `Use ${target.label} in a workflow` : 'Use provider in a workflow'
|
|
91
|
+
}),
|
|
92
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
93
|
+
size: "sm",
|
|
94
|
+
className: "text-foreground-neutral-muted",
|
|
95
|
+
children: "Reference this provider from a workflow agent step."
|
|
96
|
+
})
|
|
97
|
+
]
|
|
98
|
+
})
|
|
99
|
+
}),
|
|
100
|
+
target && example ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
101
|
+
children: [
|
|
102
|
+
/*#__PURE__*/ _jsx(ModalBody, {
|
|
103
|
+
className: "min-h-0 flex-1 gap-0 overflow-y-auto overflow-x-clip scrollbar",
|
|
104
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
105
|
+
className: "flex w-full flex-col gap-20",
|
|
106
|
+
children: [
|
|
107
|
+
compatibleIds.length === 1 ? /*#__PURE__*/ _jsxs("div", {
|
|
108
|
+
className: "flex flex-col gap-12",
|
|
109
|
+
children: [
|
|
110
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
111
|
+
className: "flex min-h-40 items-center justify-between gap-12 rounded-8 border border-border-neutral-base px-12 py-8",
|
|
112
|
+
children: [
|
|
113
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
114
|
+
size: "sm",
|
|
115
|
+
className: "text-foreground-neutral-muted",
|
|
116
|
+
children: "Harness"
|
|
117
|
+
}),
|
|
118
|
+
/*#__PURE__*/ _jsx(Code, {
|
|
119
|
+
as: "span",
|
|
120
|
+
variant: "label",
|
|
121
|
+
children: compatibleIds[0]
|
|
122
|
+
})
|
|
123
|
+
]
|
|
124
|
+
}),
|
|
125
|
+
/*#__PURE__*/ _jsx(Combobox, {
|
|
126
|
+
"aria-label": "Model",
|
|
127
|
+
options: modelOptions,
|
|
128
|
+
value: selectedModel,
|
|
129
|
+
onValueChange: (value)=>{
|
|
130
|
+
if (value) setSelectedModel(value);
|
|
131
|
+
},
|
|
132
|
+
placeholder: "Select model...",
|
|
133
|
+
searchPlaceholder: "Search models...",
|
|
134
|
+
emptyState: "No model found.",
|
|
135
|
+
className: "w-full"
|
|
136
|
+
})
|
|
137
|
+
]
|
|
138
|
+
}) : /*#__PURE__*/ _jsxs("div", {
|
|
139
|
+
className: "flex flex-col gap-12 sm:flex-row sm:gap-12",
|
|
140
|
+
children: [
|
|
141
|
+
/*#__PURE__*/ _jsx(Combobox, {
|
|
142
|
+
"aria-label": "Harness",
|
|
143
|
+
options: harnessOptions,
|
|
144
|
+
value: selectedHarness,
|
|
145
|
+
onValueChange: (value)=>{
|
|
146
|
+
if (isHarness(value)) setSelectedHarness(value);
|
|
147
|
+
},
|
|
148
|
+
placeholder: "Select harness...",
|
|
149
|
+
searchPlaceholder: "Search harnesses...",
|
|
150
|
+
emptyState: "No harness found.",
|
|
151
|
+
className: "w-full sm:flex-1"
|
|
152
|
+
}),
|
|
153
|
+
/*#__PURE__*/ _jsx(Combobox, {
|
|
154
|
+
"aria-label": "Model",
|
|
155
|
+
options: modelOptions,
|
|
156
|
+
value: selectedModel,
|
|
157
|
+
onValueChange: (value)=>{
|
|
158
|
+
if (value) setSelectedModel(value);
|
|
159
|
+
},
|
|
160
|
+
placeholder: "Select model...",
|
|
161
|
+
searchPlaceholder: "Search models...",
|
|
162
|
+
emptyState: "No model found.",
|
|
163
|
+
className: "w-full sm:flex-1"
|
|
164
|
+
})
|
|
165
|
+
]
|
|
166
|
+
}),
|
|
167
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
168
|
+
className: "flex flex-col gap-8",
|
|
169
|
+
children: [
|
|
170
|
+
/*#__PURE__*/ _jsxs(CodeBlock, {
|
|
171
|
+
data: data,
|
|
172
|
+
className: "h-auto min-h-0 rounded-8",
|
|
173
|
+
children: [
|
|
174
|
+
/*#__PURE__*/ _jsxs(CodeBlockHeader, {
|
|
175
|
+
children: [
|
|
176
|
+
/*#__PURE__*/ _jsx(CodeBlockFiles, {
|
|
177
|
+
children: (item)=>/*#__PURE__*/ _jsx(CodeBlockFilename, {
|
|
178
|
+
value: item.filename,
|
|
179
|
+
children: item.filename
|
|
180
|
+
})
|
|
181
|
+
}),
|
|
182
|
+
/*#__PURE__*/ _jsx(CodeBlockCopyButton, {})
|
|
183
|
+
]
|
|
184
|
+
}),
|
|
185
|
+
/*#__PURE__*/ _jsx(CodeBlockBody, {
|
|
186
|
+
children: (item)=>/*#__PURE__*/ _jsx(CodeBlockItem, {
|
|
187
|
+
value: item.filename,
|
|
188
|
+
children: /*#__PURE__*/ _jsx(CodeBlockContent, {
|
|
189
|
+
language: "yaml",
|
|
190
|
+
syntaxHighlighting: true,
|
|
191
|
+
highlightedLineRange: example.highlightedLineRange,
|
|
192
|
+
children: item.code
|
|
193
|
+
})
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
]
|
|
197
|
+
}),
|
|
198
|
+
/*#__PURE__*/ _jsxs(Text, {
|
|
199
|
+
size: "sm",
|
|
200
|
+
className: "text-foreground-neutral-muted",
|
|
201
|
+
children: [
|
|
202
|
+
"Add this to a workflow file under",
|
|
203
|
+
' ',
|
|
204
|
+
/*#__PURE__*/ _jsx(Code, {
|
|
205
|
+
as: "span",
|
|
206
|
+
variant: "label",
|
|
207
|
+
children: ".shipfox/workflows/"
|
|
208
|
+
}),
|
|
209
|
+
' ',
|
|
210
|
+
"in your repository to run it."
|
|
211
|
+
]
|
|
212
|
+
})
|
|
213
|
+
]
|
|
214
|
+
}),
|
|
215
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
216
|
+
className: "flex flex-col gap-8",
|
|
217
|
+
children: [
|
|
218
|
+
/*#__PURE__*/ _jsxs(Text, {
|
|
219
|
+
size: "sm",
|
|
220
|
+
bold: true,
|
|
221
|
+
children: [
|
|
222
|
+
"Available models (",
|
|
223
|
+
target.models.length,
|
|
224
|
+
")"
|
|
225
|
+
]
|
|
226
|
+
}),
|
|
227
|
+
/*#__PURE__*/ _jsx("ul", {
|
|
228
|
+
className: "rounded-8 border border-border-neutral-base",
|
|
229
|
+
children: target.models.map((model)=>/*#__PURE__*/ _jsx(ModelProviderModelRow, {
|
|
230
|
+
label: model.label,
|
|
231
|
+
id: model.id
|
|
232
|
+
}, model.id))
|
|
233
|
+
})
|
|
234
|
+
]
|
|
235
|
+
})
|
|
236
|
+
]
|
|
237
|
+
})
|
|
238
|
+
}),
|
|
239
|
+
/*#__PURE__*/ _jsx(ModalFooter, {
|
|
240
|
+
children: /*#__PURE__*/ _jsx(Button, {
|
|
241
|
+
type: "button",
|
|
242
|
+
onClick: ()=>handleOpenChange(false),
|
|
243
|
+
children: "Done"
|
|
244
|
+
})
|
|
245
|
+
})
|
|
246
|
+
]
|
|
247
|
+
}) : null
|
|
248
|
+
]
|
|
249
|
+
})
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
function selectInitialHarness(compatibleIds, workspaceDefaultHarnessId) {
|
|
253
|
+
if (workspaceDefaultHarnessId && compatibleIds.includes(workspaceDefaultHarnessId)) {
|
|
254
|
+
return workspaceDefaultHarnessId;
|
|
255
|
+
}
|
|
256
|
+
if (compatibleIds.includes(DEFAULT_HARNESS)) return DEFAULT_HARNESS;
|
|
257
|
+
return compatibleIds[0] ?? DEFAULT_HARNESS;
|
|
258
|
+
}
|
|
259
|
+
function isHarness(value) {
|
|
260
|
+
return listHarnessDescriptors().some((descriptor)=>descriptor.id === value);
|
|
261
|
+
}
|
|
262
|
+
function ModelProviderModelRow({ label, id }) {
|
|
263
|
+
const [copyState, setCopyState] = useState('idle');
|
|
264
|
+
const timeoutRef = useRef(undefined);
|
|
265
|
+
const { copy } = useCopyToClipboard({
|
|
266
|
+
text: id,
|
|
267
|
+
onCopy: ()=>{
|
|
268
|
+
setTemporaryCopyState('copied');
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
useEffect(()=>{
|
|
272
|
+
return ()=>{
|
|
273
|
+
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
274
|
+
};
|
|
275
|
+
}, []);
|
|
276
|
+
function setTemporaryCopyState(state) {
|
|
277
|
+
setCopyState(state);
|
|
278
|
+
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
279
|
+
timeoutRef.current = setTimeout(()=>setCopyState('idle'), 2500);
|
|
280
|
+
}
|
|
281
|
+
async function handleCopy() {
|
|
282
|
+
try {
|
|
283
|
+
await copy();
|
|
284
|
+
} catch {
|
|
285
|
+
setTemporaryCopyState('failed');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return /*#__PURE__*/ _jsxs("li", {
|
|
289
|
+
className: "border-b border-border-neutral-base last:border-b-0",
|
|
290
|
+
children: [
|
|
291
|
+
/*#__PURE__*/ _jsxs(Tooltip, {
|
|
292
|
+
open: copyState === 'copied',
|
|
293
|
+
children: [
|
|
294
|
+
/*#__PURE__*/ _jsx(TooltipTrigger, {
|
|
295
|
+
asChild: true,
|
|
296
|
+
children: /*#__PURE__*/ _jsxs("button", {
|
|
297
|
+
type: "button",
|
|
298
|
+
"aria-label": `Copy ${label} model id ${id}`,
|
|
299
|
+
className: "flex min-h-40 w-full min-w-0 flex-col items-start gap-2 px-12 py-8 text-left transition-colors hover:bg-background-components-hover focus-visible:shadow-border-interactive-with-active focus-visible:outline-none sm:flex-row sm:items-center sm:gap-8",
|
|
300
|
+
onClick: ()=>{
|
|
301
|
+
void handleCopy();
|
|
302
|
+
},
|
|
303
|
+
children: [
|
|
304
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
305
|
+
as: "span",
|
|
306
|
+
size: "sm",
|
|
307
|
+
bold: true,
|
|
308
|
+
className: "max-w-full shrink-0 truncate sm:max-w-[48%]",
|
|
309
|
+
children: label
|
|
310
|
+
}),
|
|
311
|
+
/*#__PURE__*/ _jsx(Code, {
|
|
312
|
+
as: "span",
|
|
313
|
+
variant: "label",
|
|
314
|
+
className: "min-w-0 max-w-full truncate text-left text-foreground-neutral-muted sm:flex-1 sm:text-right",
|
|
315
|
+
children: id
|
|
316
|
+
})
|
|
317
|
+
]
|
|
318
|
+
})
|
|
319
|
+
}),
|
|
320
|
+
/*#__PURE__*/ _jsx(TooltipContent, {
|
|
321
|
+
side: "top",
|
|
322
|
+
align: "center",
|
|
323
|
+
children: "Copied"
|
|
324
|
+
})
|
|
325
|
+
]
|
|
326
|
+
}),
|
|
327
|
+
copyState === 'copied' ? /*#__PURE__*/ _jsxs("span", {
|
|
328
|
+
className: "sr-only",
|
|
329
|
+
role: "status",
|
|
330
|
+
children: [
|
|
331
|
+
"Copied ",
|
|
332
|
+
label,
|
|
333
|
+
" id"
|
|
334
|
+
]
|
|
335
|
+
}) : null,
|
|
336
|
+
copyState === 'failed' ? /*#__PURE__*/ _jsxs("span", {
|
|
337
|
+
className: "sr-only",
|
|
338
|
+
role: "status",
|
|
339
|
+
children: [
|
|
340
|
+
"Could not copy ",
|
|
341
|
+
label,
|
|
342
|
+
" id"
|
|
343
|
+
]
|
|
344
|
+
}) : null
|
|
345
|
+
]
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
//# sourceMappingURL=model-provider-usage-modal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/model-provider-usage-modal.tsx"],"sourcesContent":["import {\n DEFAULT_HARNESS,\n getHarnessDescriptor,\n type Harness,\n listHarnessDescriptors,\n} from '@shipfox/api-agent-dto';\nimport {Button} from '@shipfox/react-ui/button';\nimport {\n CodeBlock,\n CodeBlockBody,\n CodeBlockContent,\n CodeBlockCopyButton,\n CodeBlockFilename,\n CodeBlockFiles,\n CodeBlockHeader,\n CodeBlockItem,\n} from '@shipfox/react-ui/code-block';\nimport {Combobox} from '@shipfox/react-ui/combobox';\nimport {useCopyToClipboard} from '@shipfox/react-ui/hooks';\nimport {\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n ModalTitle,\n} from '@shipfox/react-ui/modal';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Code, Text} from '@shipfox/react-ui/typography';\nimport {useEffect, useMemo, useRef, useState} from 'react';\nimport {buildAgentWorkflowExample} from './agent-workflow-example.js';\nimport {compatibleHarnessIds} from './harness-availability.js';\nimport type {ModelProviderUsageTarget} from './model-provider-usage-target.js';\n\ntype CopyState = 'idle' | 'copied' | 'failed';\n\nconst WORKFLOW_EXAMPLE_FILENAME = '.shipfox/workflows/agent.yml';\n\nexport function ModelProviderUsageModal({\n target,\n initialModel,\n open,\n onOpenChange,\n closeFocusTarget,\n workspaceDefaultHarnessId,\n}: {\n target: ModelProviderUsageTarget | null;\n initialModel?: string | null | undefined;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n closeFocusTarget?: HTMLElement | null | undefined;\n workspaceDefaultHarnessId?: Harness | null | undefined;\n}) {\n const [selectedModel, setSelectedModel] = useState('');\n const [selectedHarness, setSelectedHarness] = useState<Harness>(DEFAULT_HARNESS);\n\n useEffect(() => {\n if (!target) return;\n setSelectedModel(initialModel ?? target.default_model ?? target.models[0]?.id ?? '');\n }, [target, initialModel]);\n\n useEffect(() => {\n if (!target) return;\n const nextCompatibleHarnessIds = compatibleHarnessIds({\n isCustom: target.isCustom,\n providerId: target.id,\n });\n setSelectedHarness(selectInitialHarness(nextCompatibleHarnessIds, workspaceDefaultHarnessId));\n }, [target, workspaceDefaultHarnessId]);\n\n const compatibleIds = useMemo(\n () =>\n target\n ? compatibleHarnessIds({isCustom: target.isCustom, providerId: target.id})\n : ([] as Harness[]),\n [target],\n );\n const harnessOptions = useMemo(\n () =>\n compatibleIds.map((harnessId) => ({\n value: harnessId,\n label: getHarnessDescriptor(harnessId).label,\n })),\n [compatibleIds],\n );\n const modelOptions = useMemo(\n () => target?.models.map((model) => ({value: model.id, label: model.label})) ?? [],\n [target],\n );\n const example = target\n ? buildAgentWorkflowExample({\n harness: selectedHarness,\n providerId: target.id,\n model: selectedModel,\n })\n : null;\n const data =\n example === null\n ? []\n : [{language: 'yaml', filename: WORKFLOW_EXAMPLE_FILENAME, code: example.code}];\n\n function handleOpenChange(nextOpen: boolean) {\n onOpenChange(nextOpen);\n if (!nextOpen && closeFocusTarget) {\n window.setTimeout(() => closeFocusTarget.focus(), 0);\n }\n }\n\n return (\n <Modal open={open && target !== null} onOpenChange={handleOpenChange}>\n <ModalContent aria-describedby={undefined} className=\"max-h-[calc(100vh-32px)] max-w-[640px]\">\n <ModalTitle className=\"sr-only\">\n {target ? `Use ${target.label} in a workflow` : 'Use provider in a workflow'}\n </ModalTitle>\n <ModalHeader>\n <div className=\"flex min-w-0 flex-col gap-2\">\n <Text size=\"lg\" aria-hidden=\"true\" className=\"truncate\">\n {target ? `Use ${target.label} in a workflow` : 'Use provider in a workflow'}\n </Text>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Reference this provider from a workflow agent step.\n </Text>\n </div>\n </ModalHeader>\n {target && example ? (\n <>\n <ModalBody className=\"min-h-0 flex-1 gap-0 overflow-y-auto overflow-x-clip scrollbar\">\n <div className=\"flex w-full flex-col gap-20\">\n {compatibleIds.length === 1 ? (\n <div className=\"flex flex-col gap-12\">\n <div className=\"flex min-h-40 items-center justify-between gap-12 rounded-8 border border-border-neutral-base px-12 py-8\">\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Harness\n </Text>\n <Code as=\"span\" variant=\"label\">\n {compatibleIds[0]}\n </Code>\n </div>\n <Combobox\n aria-label=\"Model\"\n options={modelOptions}\n value={selectedModel}\n onValueChange={(value) => {\n if (value) setSelectedModel(value);\n }}\n placeholder=\"Select model...\"\n searchPlaceholder=\"Search models...\"\n emptyState=\"No model found.\"\n className=\"w-full\"\n />\n </div>\n ) : (\n <div className=\"flex flex-col gap-12 sm:flex-row sm:gap-12\">\n <Combobox\n aria-label=\"Harness\"\n options={harnessOptions}\n value={selectedHarness}\n onValueChange={(value) => {\n if (isHarness(value)) setSelectedHarness(value);\n }}\n placeholder=\"Select harness...\"\n searchPlaceholder=\"Search harnesses...\"\n emptyState=\"No harness found.\"\n className=\"w-full sm:flex-1\"\n />\n <Combobox\n aria-label=\"Model\"\n options={modelOptions}\n value={selectedModel}\n onValueChange={(value) => {\n if (value) setSelectedModel(value);\n }}\n placeholder=\"Select model...\"\n searchPlaceholder=\"Search models...\"\n emptyState=\"No model found.\"\n className=\"w-full sm:flex-1\"\n />\n </div>\n )}\n\n <div className=\"flex flex-col gap-8\">\n <CodeBlock data={data} className=\"h-auto min-h-0 rounded-8\">\n <CodeBlockHeader>\n <CodeBlockFiles>\n {(item) => (\n <CodeBlockFilename value={item.filename}>\n {item.filename}\n </CodeBlockFilename>\n )}\n </CodeBlockFiles>\n <CodeBlockCopyButton />\n </CodeBlockHeader>\n <CodeBlockBody>\n {(item) => (\n <CodeBlockItem value={item.filename}>\n <CodeBlockContent\n language=\"yaml\"\n syntaxHighlighting\n highlightedLineRange={example.highlightedLineRange}\n >\n {item.code}\n </CodeBlockContent>\n </CodeBlockItem>\n )}\n </CodeBlockBody>\n </CodeBlock>\n\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Add this to a workflow file under{' '}\n <Code as=\"span\" variant=\"label\">\n .shipfox/workflows/\n </Code>{' '}\n in your repository to run it.\n </Text>\n </div>\n\n <div className=\"flex flex-col gap-8\">\n <Text size=\"sm\" bold>\n Available models ({target.models.length})\n </Text>\n <ul className=\"rounded-8 border border-border-neutral-base\">\n {target.models.map((model) => (\n <ModelProviderModelRow key={model.id} label={model.label} id={model.id} />\n ))}\n </ul>\n </div>\n </div>\n </ModalBody>\n <ModalFooter>\n <Button type=\"button\" onClick={() => handleOpenChange(false)}>\n Done\n </Button>\n </ModalFooter>\n </>\n ) : null}\n </ModalContent>\n </Modal>\n );\n}\n\nfunction selectInitialHarness(\n compatibleIds: Harness[],\n workspaceDefaultHarnessId: Harness | null | undefined,\n): Harness {\n if (workspaceDefaultHarnessId && compatibleIds.includes(workspaceDefaultHarnessId)) {\n return workspaceDefaultHarnessId;\n }\n if (compatibleIds.includes(DEFAULT_HARNESS)) return DEFAULT_HARNESS;\n return compatibleIds[0] ?? DEFAULT_HARNESS;\n}\n\nfunction isHarness(value: string): value is Harness {\n return listHarnessDescriptors().some((descriptor) => descriptor.id === value);\n}\n\nfunction ModelProviderModelRow({label, id}: {label: string; id: string}) {\n const [copyState, setCopyState] = useState<CopyState>('idle');\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const {copy} = useCopyToClipboard({\n text: id,\n onCopy: () => {\n setTemporaryCopyState('copied');\n },\n });\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, []);\n\n function setTemporaryCopyState(state: Exclude<CopyState, 'idle'>) {\n setCopyState(state);\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n timeoutRef.current = setTimeout(() => setCopyState('idle'), 2500);\n }\n\n async function handleCopy() {\n try {\n await copy();\n } catch {\n setTemporaryCopyState('failed');\n }\n }\n\n return (\n <li className=\"border-b border-border-neutral-base last:border-b-0\">\n <Tooltip open={copyState === 'copied'}>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n aria-label={`Copy ${label} model id ${id}`}\n className=\"flex min-h-40 w-full min-w-0 flex-col items-start gap-2 px-12 py-8 text-left transition-colors hover:bg-background-components-hover focus-visible:shadow-border-interactive-with-active focus-visible:outline-none sm:flex-row sm:items-center sm:gap-8\"\n onClick={() => {\n void handleCopy();\n }}\n >\n <Text as=\"span\" size=\"sm\" bold className=\"max-w-full shrink-0 truncate sm:max-w-[48%]\">\n {label}\n </Text>\n <Code\n as=\"span\"\n variant=\"label\"\n className=\"min-w-0 max-w-full truncate text-left text-foreground-neutral-muted sm:flex-1 sm:text-right\"\n >\n {id}\n </Code>\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"top\" align=\"center\">\n Copied\n </TooltipContent>\n </Tooltip>\n {copyState === 'copied' ? (\n <span className=\"sr-only\" role=\"status\">\n Copied {label} id\n </span>\n ) : null}\n {copyState === 'failed' ? (\n <span className=\"sr-only\" role=\"status\">\n Could not copy {label} id\n </span>\n ) : null}\n </li>\n );\n}\n"],"names":["DEFAULT_HARNESS","getHarnessDescriptor","listHarnessDescriptors","Button","CodeBlock","CodeBlockBody","CodeBlockContent","CodeBlockCopyButton","CodeBlockFilename","CodeBlockFiles","CodeBlockHeader","CodeBlockItem","Combobox","useCopyToClipboard","Modal","ModalBody","ModalContent","ModalFooter","ModalHeader","ModalTitle","Tooltip","TooltipContent","TooltipTrigger","Code","Text","useEffect","useMemo","useRef","useState","buildAgentWorkflowExample","compatibleHarnessIds","WORKFLOW_EXAMPLE_FILENAME","ModelProviderUsageModal","target","initialModel","open","onOpenChange","closeFocusTarget","workspaceDefaultHarnessId","selectedModel","setSelectedModel","selectedHarness","setSelectedHarness","default_model","models","id","nextCompatibleHarnessIds","isCustom","providerId","selectInitialHarness","compatibleIds","harnessOptions","map","harnessId","value","label","modelOptions","model","example","harness","data","language","filename","code","handleOpenChange","nextOpen","window","setTimeout","focus","aria-describedby","undefined","className","div","size","aria-hidden","length","as","variant","aria-label","options","onValueChange","placeholder","searchPlaceholder","emptyState","isHarness","item","syntaxHighlighting","highlightedLineRange","bold","ul","ModelProviderModelRow","type","onClick","includes","some","descriptor","copyState","setCopyState","timeoutRef","copy","text","onCopy","setTemporaryCopyState","current","clearTimeout","state","handleCopy","li","asChild","button","side","align","span","role"],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { StoryObj } from '@storybook/react';
|
|
2
|
+
interface ModelProviderUsageModalStoryProps {
|
|
3
|
+
variant: 'anthropic' | 'custom' | 'long-list';
|
|
4
|
+
}
|
|
5
|
+
declare function ModelProviderUsageModalStory({ variant }: ModelProviderUsageModalStoryProps): import("react").JSX.Element;
|
|
6
|
+
declare const meta: {
|
|
7
|
+
title: string;
|
|
8
|
+
component: typeof ModelProviderUsageModalStory;
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: string;
|
|
11
|
+
};
|
|
12
|
+
args: {
|
|
13
|
+
variant: "anthropic";
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export default meta;
|
|
17
|
+
type Story = StoryObj<typeof meta>;
|
|
18
|
+
export declare const Playground: Story;
|
|
19
|
+
export declare const LongModelList: Story;
|
|
20
|
+
export declare const CustomProvider: Story;
|
|
21
|
+
//# sourceMappingURL=model-provider-usage-modal.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-provider-usage-modal.stories.d.ts","sourceRoot":"","sources":["../../src/components/model-provider-usage-modal.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAO,QAAQ,EAAC,MAAM,kBAAkB,CAAC;AAQrD,UAAU,iCAAiC;IACzC,OAAO,EAAE,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;CAC/C;AAED,iBAAS,4BAA4B,CAAC,EAAC,OAAO,EAAC,EAAE,iCAAiC,+BAmBjF;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,aAAa,EAAE,KAE3B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAC"}
|