1- import type { Part , AssistantMessage , ReasoningPart , TextPart , ToolPart } from "@opencode-ai/sdk"
1+ import type { Part , AssistantMessage , ReasoningPart , TextPart , ToolPart , Message } from "@opencode-ai/sdk"
22import { children , Component , createMemo , For , Match , Show , Switch , type JSX } from "solid-js"
33import { Dynamic } from "solid-js/web"
44import { Markdown } from "./markdown"
@@ -17,74 +17,65 @@ import type { WriteTool } from "opencode/tool/write"
1717import type { TodoWriteTool } from "opencode/tool/todo"
1818import { DiffChanges } from "./diff-changes"
1919
20- export function AssistantMessage ( props : { message : AssistantMessage ; parts : Part [ ] ; lastToolOnly ?: boolean } ) {
20+ export function AssistantMessage ( props : { message : AssistantMessage ; parts : Part [ ] } ) {
2121 const filteredParts = createMemo ( ( ) => {
22- let tool = false
2322 return props . parts ?. filter ( ( x ) => {
24- if ( x . type === "tool" && props . lastToolOnly && tool ) return false
25- if ( x . type === "tool" ) tool = true
23+ if ( x . type === "reasoning" ) return false
2624 return x . type !== "tool" || x . tool !== "todoread"
2725 } )
2826 } )
2927 return (
3028 < div class = "w-full flex flex-col items-start gap-4" >
31- < For each = { filteredParts ( ) } >
32- { ( part ) => {
33- const component = createMemo ( ( ) => PART_MAPPING [ part . type as keyof typeof PART_MAPPING ] )
34- return (
35- < Show when = { component ( ) } >
36- < Dynamic component = { component ( ) } part = { part as any } message = { props . message } />
37- </ Show >
38- )
39- } }
40- </ For >
29+ < For each = { filteredParts ( ) } > { ( part ) => < Part part = { part } message = { props . message } /> } </ For >
4130 </ div >
4231 )
4332}
4433
34+ export function Part ( props : { part : Part ; message : Message ; readonly ?: boolean } ) {
35+ const component = createMemo ( ( ) => PART_MAPPING [ props . part . type as keyof typeof PART_MAPPING ] )
36+ return (
37+ < Show when = { component ( ) } >
38+ < Dynamic component = { component ( ) } part = { props . part as any } message = { props . message } readonly = { props . readonly } />
39+ </ Show >
40+ )
41+ }
42+
4543const PART_MAPPING = {
4644 text : TextPart ,
4745 tool : ToolPart ,
4846 reasoning : ReasoningPart ,
4947}
5048
51- function ReasoningPart ( props : { part : ReasoningPart ; message : AssistantMessage } ) {
52- return null
53- // return (
54- // <Show when={props.part.text.trim()}>
55- // <div>{props.part.text}</div>
56- // </Show>
57- // )
49+ function ReasoningPart ( props : { part : ReasoningPart ; message : Message } ) {
50+ return (
51+ < Show when = { props . part . text . trim ( ) } >
52+ < Markdown text = { props . part . text . trim ( ) } />
53+ </ Show >
54+ )
5855}
5956
60- function TextPart ( props : { part : TextPart ; message : AssistantMessage } ) {
57+ function TextPart ( props : { part : TextPart ; message : Message } ) {
6158 return (
6259 < Show when = { props . part . text . trim ( ) } >
6360 < Markdown text = { props . part . text . trim ( ) } />
6461 </ Show >
6562 )
6663}
6764
68- function ToolPart ( props : { part : ToolPart ; message : AssistantMessage } ) {
69- // const sync = useSync()
70-
65+ function ToolPart ( props : { part : ToolPart ; message : Message ; readonly ?: boolean } ) {
7166 const component = createMemo ( ( ) => {
7267 const render = ToolRegistry . render ( props . part . tool ) ?? GenericTool
73-
7468 const metadata = props . part . state . status === "pending" ? { } : ( props . part . state . metadata ?? { } )
7569 const input = props . part . state . status === "completed" ? props . part . state . input : { }
76- // const permissions = sync.data.permission[props.message.sessionID] ?? []
77- // const permissionIndex = permissions.findIndex((x) => x.callID === props.part.callID)
78- // const permission = permissions[permissionIndex]
7970
8071 return (
8172 < Dynamic
8273 component = { render }
8374 input = { input }
8475 tool = { props . part . tool }
8576 metadata = { metadata }
86- // permission={permission?.metadata ?? {}}
8777 output = { props . part . state . status === "completed" ? props . part . state . output : undefined }
78+ readonly = { props . readonly }
8879 />
8980 )
9081 } )
@@ -106,7 +97,12 @@ const isTriggerTitle = (val: any): val is TriggerTitle => {
10697 return typeof val === "object" && val !== null && "title" in val && ! ( val instanceof Node )
10798}
10899
109- function BasicTool ( props : { icon : IconProps [ "name" ] ; trigger : TriggerTitle | JSX . Element ; children ?: JSX . Element } ) {
100+ function BasicTool ( props : {
101+ icon : IconProps [ "name" ]
102+ trigger : TriggerTitle | JSX . Element
103+ children ?: JSX . Element
104+ readonly ?: boolean
105+ } ) {
110106 const resolved = children ( ( ) => props . children )
111107 return (
112108 < Collapsible >
@@ -161,13 +157,13 @@ function BasicTool(props: { icon: IconProps["name"]; trigger: TriggerTitle | JSX
161157 </ Switch >
162158 </ div >
163159 </ div >
164- < Show when = { resolved ( ) } >
160+ < Show when = { resolved ( ) && ! props . readonly } >
165161 < Collapsible . Arrow />
166162 </ Show >
167163 </ div >
168164 </ Collapsible . Trigger >
169- < Show when = { props . children } >
170- < Collapsible . Content > { props . children } </ Collapsible . Content >
165+ < Show when = { resolved ( ) && ! props . readonly } >
166+ < Collapsible . Content > { resolved ( ) } </ Collapsible . Content >
171167 </ Show >
172168 </ Collapsible >
173169 // <>
@@ -177,15 +173,15 @@ function BasicTool(props: { icon: IconProps["name"]; trigger: TriggerTitle | JSX
177173}
178174
179175function GenericTool ( props : ToolProps < any > ) {
180- return < BasicTool icon = "mcp" trigger = { { title : props . tool } } />
176+ return < BasicTool icon = "mcp" trigger = { { title : props . tool } } readonly = { props . readonly } />
181177}
182178
183179type ToolProps < T extends Tool . Info > = {
184180 input : Partial < Tool . InferParameters < T > >
185181 metadata : Partial < Tool . InferMetadata < T > >
186- // permission: Record<string, any>
187182 tool : string
188183 output ?: string
184+ readonly ?: boolean
189185}
190186
191187const ToolRegistry = ( ( ) => {
0 commit comments