|
1 | 1 | import { useMemo, useState } from "react"; |
2 | 2 | import { useAtomValue } from "@effect/atom-react"; |
3 | 3 | import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"; |
4 | | -import { toolSchemaAtom, toolTypeScriptAtom } from "../api/atoms"; |
| 4 | +import { toolSchemaAtom } from "../api/atoms"; |
5 | 5 | import { |
6 | 6 | ScopeId, |
7 | 7 | ToolId, |
@@ -109,11 +109,19 @@ export function ToolDetail(props: { |
109 | 109 | const data = useMemo(() => { |
110 | 110 | if (!AsyncResult.isSuccess(toolContract)) return null; |
111 | 111 | const v = toolContract.value; |
| 112 | + const definitions = Object.entries(v.typeScriptDefinitions ?? {}).map(([name, body]) => ({ |
| 113 | + name, |
| 114 | + code: String(body), |
| 115 | + })); |
| 116 | + |
112 | 117 | return { |
113 | 118 | description: v.description, |
114 | 119 | inputSchema: v.inputSchema, |
115 | 120 | outputSchema: v.outputSchema, |
116 | 121 | schemaDefinitions: v.schemaDefinitions, |
| 122 | + inputTypeScript: v.inputTypeScript ? `type Input = ${v.inputTypeScript}` : null, |
| 123 | + outputTypeScript: v.outputTypeScript ? `type Output = ${v.outputTypeScript}` : null, |
| 124 | + definitions, |
117 | 125 | }; |
118 | 126 | }, [toolContract]); |
119 | 127 |
|
@@ -213,68 +221,55 @@ export function ToolDetail(props: { |
213 | 221 | )} |
214 | 222 | </div> |
215 | 223 | ) : ( |
216 | | - <ToolTypeScriptPanel scopeId={props.scopeId} toolId={props.toolId as ToolId} /> |
| 224 | + <ToolTypeScriptPanel |
| 225 | + inputTypeScript={data?.inputTypeScript ?? null} |
| 226 | + outputTypeScript={data?.outputTypeScript ?? null} |
| 227 | + definitions={data?.definitions ?? []} |
| 228 | + /> |
217 | 229 | ), |
218 | 230 | })} |
219 | 231 | </div> |
220 | 232 | </div> |
221 | 233 | ); |
222 | 234 | } |
223 | 235 |
|
224 | | -function ToolTypeScriptPanel(props: { scopeId: ScopeId; toolId: ToolId }) { |
225 | | - const toolContract = useAtomValue(toolTypeScriptAtom(props.scopeId, props.toolId)); |
226 | | - |
227 | | - const data = useMemo(() => { |
228 | | - if (!AsyncResult.isSuccess(toolContract)) return null; |
229 | | - const v = toolContract.value; |
230 | | - const definitions = Object.entries(v.typeScriptDefinitions ?? {}).map(([name, body]) => ({ |
231 | | - name, |
232 | | - code: String(body), |
233 | | - })); |
234 | | - |
235 | | - return { |
236 | | - inputTypeScript: v.inputTypeScript ? `type Input = ${v.inputTypeScript}` : null, |
237 | | - outputTypeScript: v.outputTypeScript ? `type Output = ${v.outputTypeScript}` : null, |
238 | | - definitions, |
239 | | - }; |
240 | | - }, [toolContract]); |
241 | | - |
242 | | - return AsyncResult.match(toolContract, { |
243 | | - onInitial: () => <div className="p-5 text-sm text-muted-foreground">Loading…</div>, |
244 | | - onFailure: () => <div className="p-5 text-sm text-destructive">Something went wrong</div>, |
245 | | - onSuccess: () => ( |
246 | | - <div className="px-5 py-5 space-y-5"> |
247 | | - {data?.inputTypeScript ? ( |
248 | | - <CardStack> |
249 | | - <CardStackHeader>Input</CardStackHeader> |
250 | | - <CardStackContent> |
251 | | - <ExpandableCodeBlock |
252 | | - code={data.inputTypeScript} |
253 | | - definitions={data.definitions} |
254 | | - className="rounded-none border-0" |
255 | | - /> |
256 | | - </CardStackContent> |
257 | | - </CardStack> |
258 | | - ) : ( |
259 | | - <EmptySection title="Input" message="void" /> |
260 | | - )} |
261 | | - {data?.outputTypeScript ? ( |
262 | | - <CardStack> |
263 | | - <CardStackHeader>Output</CardStackHeader> |
264 | | - <CardStackContent> |
265 | | - <ExpandableCodeBlock |
266 | | - code={data.outputTypeScript} |
267 | | - definitions={data.definitions} |
268 | | - className="rounded-none border-0" |
269 | | - /> |
270 | | - </CardStackContent> |
271 | | - </CardStack> |
272 | | - ) : ( |
273 | | - <EmptySection title="Output" message="void" /> |
274 | | - )} |
275 | | - </div> |
276 | | - ), |
277 | | - }); |
| 236 | +function ToolTypeScriptPanel(props: { |
| 237 | + inputTypeScript: string | null; |
| 238 | + outputTypeScript: string | null; |
| 239 | + definitions: ReadonlyArray<{ name: string; code: string }>; |
| 240 | +}) { |
| 241 | + return ( |
| 242 | + <div className="px-5 py-5 space-y-5"> |
| 243 | + {props.inputTypeScript ? ( |
| 244 | + <CardStack> |
| 245 | + <CardStackHeader>Input</CardStackHeader> |
| 246 | + <CardStackContent> |
| 247 | + <ExpandableCodeBlock |
| 248 | + code={props.inputTypeScript} |
| 249 | + definitions={props.definitions} |
| 250 | + className="rounded-none border-0" |
| 251 | + /> |
| 252 | + </CardStackContent> |
| 253 | + </CardStack> |
| 254 | + ) : ( |
| 255 | + <EmptySection title="Input" message="void" /> |
| 256 | + )} |
| 257 | + {props.outputTypeScript ? ( |
| 258 | + <CardStack> |
| 259 | + <CardStackHeader>Output</CardStackHeader> |
| 260 | + <CardStackContent> |
| 261 | + <ExpandableCodeBlock |
| 262 | + code={props.outputTypeScript} |
| 263 | + definitions={props.definitions} |
| 264 | + className="rounded-none border-0" |
| 265 | + /> |
| 266 | + </CardStackContent> |
| 267 | + </CardStack> |
| 268 | + ) : ( |
| 269 | + <EmptySection title="Output" message="void" /> |
| 270 | + )} |
| 271 | + </div> |
| 272 | + ); |
278 | 273 | } |
279 | 274 |
|
280 | 275 | // --------------------------------------------------------------------------- |
|
0 commit comments