@@ -136,6 +136,20 @@ S7::method(contents_shinychat, ellmer::ContentText) <- function(content) {
136136 content @ text
137137}
138138
139+ S7 :: method(contents_shinychat , ellmer :: ContentPDF ) <- function (content ) {
140+ htmltools :: div(
141+ class = " shinychat-pdf badge fs-6 text-bg-secondary" ,
142+ htmltools :: span(
143+ class = " shinychat-pdf__icon me-1" ,
144+ htmltools :: HTML(ICON_FILE_PDF_FILL )
145+ ),
146+ htmltools :: span(
147+ class = " shinychat-pdf__filename font-monospace"
148+ content @ filename
149+ )
150+ )
151+ }
152+
139153new_tool_card <- function (type , request_id , tool_name , ... ) {
140154 type <- arg_match(type , c(" request" , " result" ))
141155
@@ -316,18 +330,22 @@ tool_result_display <- function(content, display = NULL) {
316330 use_basic_display <- opt_shinychat_tool_display() == " basic"
317331
318332 if (tool_errored(content ) || use_basic_display || ! has_display ) {
319- return (list ( value = tool_string( content ), value_type = " code " ))
333+ return (tool_default_display( content ))
320334 }
321335
322336 if (is.list(display )) {
323337 has_type <- intersect(c(" html" , " markdown" , " text" ), names(display ))
324338 if (length(has_type ) > 0 ) {
325339 value_type <- has_type [1 ]
326- return (list ( value = display [[value_type ]], value_type = value_type ))
340+ return (as_tool_display( display [[value_type ]], value_type ))
327341 }
328342 }
329343
330- list (value = tool_string(content ), value_type = " code" )
344+ tool_default_display(content )
345+ }
346+
347+ as_tool_display <- function (value , type = " code" ) {
348+ list (value = value , value_type = type )
331349}
332350
333351# Copied from
@@ -336,21 +354,33 @@ tool_errored <- function(x) !is.null(x@error)
336354tool_error_string <- function (x ) {
337355 if (inherits(x @ error , " condition" )) conditionMessage(x @ error ) else x @ error
338356}
339- tool_string <- function (x ) {
357+ tool_default_display <- function (x ) {
340358 if (tool_errored(x )) {
341359 # Changed from original: if tool errored, just return the error message
342- strip_ansi(tool_error_string(x ))
343- } else if (inherits(x @ value , " AsIs" )) {
344- x @ value
345- } else if (inherits(x @ value , " json" )) {
346- x @ value
347- } else if (is.character(x @ value )) {
348- paste(x @ value , collapse = " \n " )
360+ as_tool_display(strip_ansi(tool_error_string(x )))
361+ }
362+ value <- x @ value
363+ if (inherits(value , " AsIs" )) {
364+ as_tool_display(value )
365+ } else if (inherits(value , " json" )) {
366+ as_tool_display(value )
367+ } else if (is.character(value )) {
368+ as_tool_display(paste(value , collapse = " \n " ))
369+ } else if (is_content_extra(value )) {
370+ as_tool_display(htmltools :: div(contents_shinychat(value )), " html" )
371+ } else if (is.list(value ) && every(value , is_content_extra )) {
372+ as_tool_display(htmltools :: div(map(value , contents_shinychat )), " html" )
349373 } else {
350- jsonlite :: toJSON(x @ value , auto_unbox = TRUE , pretty = 2 , force = TRUE )
374+ as_tool_display(
375+ jsonlite :: toJSON(value , auto_unbox = TRUE , pretty = 2 , force = TRUE )
376+ )
351377 }
352378}
353379
380+ is_content_extra <- function (x ) {
381+ S7 :: S7_inherits(x , ellmer :: ContentImage ) ||
382+ S7 :: S7_inherits(x , ellmer :: ContentPDF )
383+ }
354384
355385S7 :: method(contents_shinychat , ellmer :: Turn ) <- function (content ) {
356386 # Process all contents in the turn, filtering out empty results
@@ -427,3 +457,5 @@ S7::method(contents_shinychat, S7::new_S3_class(c("Chat", "R6"))) <- function(
427457
428458 compact(messages )
429459}
460+
461+ ICON_FILE_PDF_FILL <- "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" class=\"bi bi-file-pdf-fill \" style=\"height:1em;width:1em;fill:currentColor;vertical-align:-0.125em;\" aria-hidden=\"true\" role=\"img\" ><path d=\"M5.523 10.424c.14-.082.293-.162.459-.238a7.878 7.878 0 0 1-.45.606c-.28.337-.498.516-.635.572a.266.266 0 0 1-.035.012.282.282 0 0 1-.026-.044c-.056-.11-.054-.216.04-.36.106-.165.319-.354.647-.548zm2.455-1.647c-.119.025-.237.05-.356.078a21.035 21.035 0 0 0 .5-1.05 11.96 11.96 0 0 0 .51.858c-.217.032-.436.07-.654.114zm2.525.939a3.888 3.888 0 0 1-.435-.41c.228.005.434.022.612.054.317.057.466.147.518.209a.095.095 0 0 1 .026.064.436.436 0 0 1-.06.2.307.307 0 0 1-.094.124.107.107 0 0 1-.069.015c-.09-.003-.258-.066-.498-.256zM8.278 4.97c-.04.244-.108.524-.2.829a4.86 4.86 0 0 1-.089-.346c-.076-.353-.087-.63-.046-.822.038-.177.11-.248.196-.283a.517.517 0 0 1 .145-.04c.013.03.028.092.032.198.005.122-.007.277-.038.465z\"></path>\n<path fill-rule=\"evenodd\" d=\"M4 0h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm.165 11.668c.09.18.23.343.438.419.207.075.412.04.58-.03.318-.13.635-.436.926-.786.333-.401.683-.927 1.021-1.51a11.64 11.64 0 0 1 1.997-.406c.3.383.61.713.91.95.28.22.603.403.934.417a.856.856 0 0 0 .51-.138c.155-.101.27-.247.354-.416.09-.181.145-.37.138-.563a.844.844 0 0 0-.2-.518c-.226-.27-.596-.4-.96-.465a5.76 5.76 0 0 0-1.335-.05 10.954 10.954 0 0 1-.98-1.686c.25-.66.437-1.284.52-1.794.036-.218.055-.426.048-.614a1.238 1.238 0 0 0-.127-.538.7.7 0 0 0-.477-.365c-.202-.043-.41 0-.601.077-.377.15-.576.47-.651.823-.073.34-.04.736.046 1.136.088.406.238.848.43 1.295a19.707 19.707 0 0 1-1.062 2.227 7.662 7.662 0 0 0-1.482.645c-.37.22-.699.48-.897.787-.21.326-.275.714-.08 1.103z\"></path></svg>"
0 commit comments