@@ -136,6 +136,20 @@ S7::method(contents_shinychat, ellmer::ContentText) <- function(content) {
136
136
content@text
137
137
}
138
138
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
+
139
153
new_tool_card <- function(type, request_id, tool_name, ...) {
140
154
type <- arg_match(type, c("request", "result"))
141
155
@@ -316,18 +330,22 @@ tool_result_display <- function(content, display = NULL) {
316
330
use_basic_display <- opt_shinychat_tool_display() == "basic"
317
331
318
332
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))
320
334
}
321
335
322
336
if (is.list(display)) {
323
337
has_type <- intersect(c("html", "markdown", "text"), names(display))
324
338
if (length(has_type) > 0) {
325
339
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))
327
341
}
328
342
}
329
343
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)
331
349
}
332
350
333
351
# Copied from
@@ -336,21 +354,33 @@ tool_errored <- function(x) !is.null(x@error)
336
354
tool_error_string <- function(x) {
337
355
if (inherits(x@error, "condition")) conditionMessage(x@error) else x@error
338
356
}
339
- tool_string <- function(x) {
357
+ tool_default_display <- function(x) {
340
358
if (tool_errored(x)) {
341
359
# 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")
349
373
} 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
+ )
351
377
}
352
378
}
353
379
380
+ is_content_extra <- function(x) {
381
+ S7::S7_inherits(x, ellmer::ContentImage) ||
382
+ S7::S7_inherits(x, ellmer::ContentPDF)
383
+ }
354
384
355
385
S7::method(contents_shinychat, ellmer::Turn) <- function(content) {
356
386
# 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(
427
457
428
458
compact(messages)
429
459
}
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