@marimo-team/islands 0.15.2 → 0.15.4
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/dist/{ConnectedDataExplorerComponent-C39nQwtD.js → ConnectedDataExplorerComponent-B68gXlbY.js} +323 -328
- package/dist/{ImageComparisonComponent-BhkiyswP.js → ImageComparisonComponent-Cw1oA8Tn.js} +13 -13
- package/dist/{_baseUniq-DdHL34FO.js → _baseUniq-CQrhBg_9.js} +67 -67
- package/dist/any-language-editor-pzUl6lxp.js +27 -0
- package/dist/{arc-BXrety1g.js → arc-BOhn-m2C.js} +1 -1
- package/dist/{architectureDiagram-KFL7JDKH-BMy6ywCF.js → architectureDiagram-W76B3OCA-DdYf2VnU.js} +144 -144
- package/dist/assets/{worker-COGufAQn.js → worker-BcG8m3h5.js} +33 -29
- package/dist/asterisk-DS281yxp.js +271 -0
- package/dist/{blockDiagram-ZYB65J3Q-DYT2-nlI.js → blockDiagram-QIGZ2CNN-DmmYotkP.js} +10 -10
- package/dist/{c4Diagram-AAMF2YG6-ZiQzioe6.js → c4Diagram-FPNF74CW-Dyz4zMHJ.js} +8 -8
- package/dist/{channel-CeuXqUAU.js → channel-CCL8jXAe.js} +1 -1
- package/dist/{chunk-ANTBXLJU-BvYnIrdq.js → chunk-4BX2VUAB-BfKwWLfJ.js} +1 -1
- package/dist/{chunk-WVR4S24B-DXj8yaUk.js → chunk-55IACEB6-CFQU7zSp.js} +1 -1
- package/dist/{chunk-GLLZNHP4-CyFsosAe.js → chunk-FMBD7UC4-DDjZzUcl.js} +1 -1
- package/dist/{chunk-JBRWN2VN-DA_EEhy2.js → chunk-K7UQS3LO-nBRjBU1H.js} +117 -117
- package/dist/{chunk-NRVI72HA-BYx2jMlI.js → chunk-QN33PNHL-B-g8sJzl.js} +1 -1
- package/dist/{chunk-FHKO5MBM-DfCztBk8.js → chunk-QZHKN3VN-B7QSJS3J.js} +1 -1
- package/dist/{chunk-LXBSTHXV-Se7vdY6J.js → chunk-TVAH2DTR-pGXll4d1.js} +7 -7
- package/dist/{chunk-OMD6QJNC-CqgcPMgL.js → chunk-TZMSLE5B-Dx9h-1mv.js} +1 -1
- package/dist/{classDiagram-v2-QTMF73CY-B19A3G1l.js → classDiagram-KNZD7YFC-BXryI7DY.js} +2 -2
- package/dist/{classDiagram-3BZAVTQC-B19A3G1l.js → classDiagram-v2-RKCZMP56-BXryI7DY.js} +2 -2
- package/dist/{clone-78au0tn1.js → clone-DqwV7ges.js} +1 -1
- package/dist/cose-bilkent-S5V4N54A-Di6FNMXz.js +2609 -0
- package/dist/{cytoscape.esm-BYnVVhJX.js → cytoscape.esm-DfdJODL8.js} +34 -34
- package/dist/{dagre-2BBEFEWP-BfEn3ZUV.js → dagre-5GWH7T2D-BTZPMTey.js} +6 -6
- package/dist/{data-grid-overlay-editor-CH_qLkV2.js → data-grid-overlay-editor-ryatXXby.js} +11 -11
- package/dist/{diagram-4IRLE6MV-CL8xidnG.js → diagram-N5W7TBWH-D79_zdOu.js} +59 -60
- package/dist/{diagram-RP2FKANI-B1BPcUew.js → diagram-QEK2KX5R-DX2A_SD0.js} +15 -15
- package/dist/{diagram-GUPCWM2R-CZ5cfqlq.js → diagram-S2PKOQOG-DM6VMTrJ.js} +10 -10
- package/dist/dockerfile-BoowzQlp.js +194 -0
- package/dist/ebnf-DUPDuY4r.js +78 -0
- package/dist/{erDiagram-HZWUO2LU-BEAIww50.js → erDiagram-AWTI2OKA-BBirxtlI.js} +8 -8
- package/dist/fcl-CPC2WYrI.js +103 -0
- package/dist/{flowDiagram-THRYKUMA-Czs2UAI2.js → flowDiagram-PVAE7QVJ-DyVweEMs.js} +9 -9
- package/dist/{ganttDiagram-WV7ZQ7D5-ByYIAVFO.js → ganttDiagram-OWAHRB6G-DTB7FX7r.js} +34 -34
- package/dist/{gitGraphDiagram-OJR772UL-BcpDsiyB.js → gitGraphDiagram-NY62KEGX-BrbIb5pD.js} +4 -4
- package/dist/{glide-data-editor-CmN6FVyi.js → glide-data-editor-DhMX4nmM.js} +33 -33
- package/dist/{graph-77W6heli.js → graph-CuLSrclI.js} +3 -3
- package/dist/http-D9LttvKF.js +44 -0
- package/dist/{index-BOojn38D.js → index-BNgdUQ2e.js} +7711 -7711
- package/dist/index-DIy6LHLJ.js +98 -0
- package/dist/{index-CmozKMxx.js → index-Df2dsx1t.js} +6 -6
- package/dist/{index-pBmAzQJl.js → index-MCx5v1x0.js} +2 -2
- package/dist/{index-Bfk9dnyS.js → index-cz_xaKvT.js} +33090 -32892
- package/dist/{infoDiagram-6WOFNB3A-CfzLHHVP.js → infoDiagram-STP46IZ2-CCBHc7-K.js} +2 -2
- package/dist/{journeyDiagram-FFXJYRFH-ndAcpkGn.js → journeyDiagram-BIP6EPQ6-LhGSj54j.js} +24 -26
- package/dist/{kanban-definition-KOZQBZVT-DcQYzNvc.js → kanban-definition-6OIFK2YF-aegTMFS6.js} +14 -14
- package/dist/{layout-XySVHJgD.js → layout-BEARWMhl.js} +81 -81
- package/dist/{linear-PbooOqg7.js → linear-fbJq6cdO.js} +35 -35
- package/dist/{main-B5yML0bw.js → main-HerZgEhd.js} +76533 -69945
- package/dist/main.js +1 -1
- package/dist/{mermaid-Cg5IX6Nv.js → mermaid-DxPYK0KX.js} +6160 -7493
- package/dist/min-DBJkhObB.js +80 -0
- package/dist/mindmap-definition-Q6HEUPPD-A3Fh5XDZ.js +785 -0
- package/dist/nginx-zDPm3Z74.js +89 -0
- package/dist/{number-overlay-editor-DUhfZqtP.js → number-overlay-editor-USMrY6k3.js} +19 -19
- package/dist/{pieDiagram-DBDJKBY4-DTOlNsja.js → pieDiagram-ADFJNKIX-Q9uFlCV0.js} +17 -17
- package/dist/{quadrantDiagram-YPSRARAO-BX2d8VS-.js → quadrantDiagram-LMRXKWRM-BuPh-qpK.js} +6 -6
- package/dist/{react-plotly-Dcyw-3Sa.js → react-plotly-HSqJPRfa.js} +3577 -3577
- package/dist/{requirementDiagram-EGVEC5DT-D1T5u-wG.js → requirementDiagram-4UW4RH46-CHROYNU_.js} +7 -7
- package/dist/{sankeyDiagram-HRAUVNP4-G6xDfnp-.js → sankeyDiagram-GR3RE2ED-DkUqHP2d.js} +5 -5
- package/dist/sequenceDiagram-C3RYC4MD-YoPTMplP.js +2519 -0
- package/dist/{slides-component-BJLlPJSr.js → slides-component-D7CHSR00.js} +66 -66
- package/dist/solr-BNlsLglM.js +41 -0
- package/dist/spreadsheet-C-cy4P5N.js +49 -0
- package/dist/{stateDiagram-UUKSUZ4H-CYXbjaom.js → stateDiagram-KXAO66HF-DEN00mVU.js} +5 -5
- package/dist/{stateDiagram-v2-EYPG3UTE-Br1HYKT6.js → stateDiagram-v2-UMBNRL4Z-DlQqSUAa.js} +2 -2
- package/dist/style.css +1 -1
- package/dist/tiddlywiki-5wqsXtSk.js +155 -0
- package/dist/tiki-__Kn3CeS.js +181 -0
- package/dist/{time-B9SZnSen.js → time-BtVcKqeD.js} +58 -58
- package/dist/{timeline-definition-3HZDQTIS-DeK_ZRD0.js → timeline-definition-XQNQX7LJ-DEteLt8D.js} +10 -12
- package/dist/{timer-BYwnU4DF.js → timer-B0-z63CM.js} +16 -16
- package/dist/{treemap-75Q7IDZK-CKP4vV_0.js → treemap-75Q7IDZK-8S6podme.js} +14 -14
- package/dist/{vega-component-CpgdqX2d.js → vega-component-D35L45kI.js} +30 -30
- package/dist/{xychartDiagram-FDP5SA34-AMEPsx_R.js → xychartDiagram-6GGTOJPD-DKwGThyy.js} +7 -7
- package/package.json +44 -41
- package/src/__mocks__/notebook.ts +3 -0
- package/src/__mocks__/requests.ts +3 -0
- package/src/__tests__/__snapshots__/CellStatus.test.tsx.snap +12 -12
- package/src/__tests__/chat-utils.test.ts +26 -211
- package/src/components/ai/ai-model-dropdown.tsx +25 -9
- package/src/components/ai/ai-provider-icon.tsx +5 -1
- package/src/components/app-config/ai-config.tsx +7 -0
- package/src/components/chat/acp/__tests__/__snapshots__/prompt.test.ts.snap +304 -0
- package/src/components/chat/acp/__tests__/atoms.test.ts +56 -0
- package/src/components/chat/acp/__tests__/prompt.test.ts +12 -0
- package/src/components/chat/acp/__tests__/state.test.ts +621 -0
- package/src/components/chat/acp/agent-docs.tsx +78 -0
- package/src/components/chat/acp/agent-panel.css +23 -0
- package/src/components/chat/acp/agent-panel.tsx +715 -0
- package/src/components/chat/acp/agent-selector.tsx +138 -0
- package/src/components/chat/acp/blocks.tsx +664 -0
- package/src/components/chat/acp/common.tsx +198 -0
- package/src/components/chat/acp/prompt.ts +284 -0
- package/src/components/chat/acp/scroll-to-bottom-button.tsx +50 -0
- package/src/components/chat/acp/session-tabs.tsx +138 -0
- package/src/components/chat/acp/state.ts +263 -0
- package/src/components/chat/acp/thread.tsx +121 -0
- package/src/components/chat/acp/types.ts +63 -0
- package/src/components/chat/acp/utils.ts +45 -0
- package/src/components/chat/chat-components.tsx +71 -0
- package/src/components/chat/chat-panel.tsx +481 -291
- package/src/components/chat/chat-utils.ts +50 -0
- package/src/components/chat/markdown-renderer.tsx +3 -7
- package/src/components/chat/tool-call-accordion.tsx +6 -6
- package/src/components/datasources/__tests__/utils.test.ts +6 -0
- package/src/components/datasources/column-preview.tsx +1 -3
- package/src/components/editor/actions/useNotebookActions.tsx +1 -1
- package/src/components/editor/ai/add-cell-with-ai.tsx +20 -15
- package/src/components/editor/ai/ai-completion-editor.tsx +22 -3
- package/src/components/editor/ai/completion-handlers.tsx +2 -4
- package/src/components/editor/ai/completion-utils.ts +85 -11
- package/src/components/editor/alerts/startup-logs-alert.tsx +72 -0
- package/src/components/editor/chrome/panels/datasources-panel.tsx +3 -1
- package/src/components/editor/chrome/panels/dependency-graph-panel.tsx +3 -1
- package/src/components/editor/chrome/panels/documentation-panel.tsx +3 -1
- package/src/components/editor/chrome/panels/error-panel.tsx +3 -1
- package/src/components/editor/chrome/panels/file-explorer-panel.tsx +3 -1
- package/src/components/editor/chrome/panels/logs-panel.tsx +3 -1
- package/src/components/editor/chrome/panels/outline-panel.tsx +3 -1
- package/src/components/editor/chrome/panels/packages-panel.tsx +4 -2
- package/src/components/editor/chrome/panels/scratchpad-panel.tsx +3 -1
- package/src/components/editor/chrome/panels/secrets-panel.tsx +3 -1
- package/src/components/editor/chrome/panels/snippets-panel.tsx +3 -1
- package/src/components/editor/chrome/panels/tracing-panel.tsx +3 -1
- package/src/components/editor/chrome/panels/variable-panel.tsx +3 -1
- package/src/components/editor/chrome/types.ts +10 -0
- package/src/components/editor/chrome/wrapper/app-chrome.tsx +55 -31
- package/src/components/editor/controls/command-palette-button.tsx +1 -1
- package/src/components/editor/controls/command-palette.tsx +5 -4
- package/src/components/editor/controls/state.ts +4 -0
- package/src/components/editor/package-alert.tsx +108 -58
- package/src/components/editor/renderers/CellArray.tsx +2 -0
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +0 -1
- package/src/components/pages/edit-page.tsx +7 -3
- package/src/core/ai/chat-utils.ts +26 -43
- package/src/core/ai/config.ts +1 -1
- package/src/core/ai/context/__tests__/registry.test.ts +277 -3
- package/src/core/ai/context/context.ts +11 -1
- package/src/core/ai/context/providers/__tests__/cell-output.test.ts +378 -0
- package/src/core/ai/context/providers/__tests__/error.test.ts +3 -2
- package/src/core/ai/context/providers/__tests__/file.test.ts +119 -0
- package/src/core/ai/context/providers/cell-output.ts +349 -0
- package/src/core/ai/context/providers/common.ts +5 -1
- package/src/core/ai/context/providers/file.ts +287 -0
- package/src/core/ai/context/registry.ts +79 -0
- package/src/core/ai/state.ts +22 -5
- package/src/core/alerts/state.ts +71 -3
- package/src/core/cells/cell.ts +2 -2
- package/src/core/cells/cells.ts +1 -1
- package/src/core/cells/logs.ts +1 -1
- package/src/core/cells/runs.ts +6 -5
- package/src/core/codemirror/ai/resources.ts +47 -5
- package/src/core/codemirror/ai/state.ts +12 -0
- package/src/core/codemirror/language/__tests__/sql.test.ts +45 -0
- package/src/core/codemirror/markdown/__tests__/commands.test.ts +1 -0
- package/src/core/codemirror/theme/dark.ts +1 -1
- package/src/core/config/capabilities.ts +1 -1
- package/src/core/config/feature-flag.tsx +2 -0
- package/src/core/datasets/__tests__/data-source.test.ts +24 -0
- package/src/core/errors/__tests__/errors.test.ts +2 -0
- package/src/core/islands/bridge.ts +1 -0
- package/src/core/islands/main.ts +1 -0
- package/src/core/kernel/messages.ts +12 -6
- package/src/core/layout/layout.ts +3 -3
- package/src/core/network/requests-network.ts +8 -0
- package/src/core/network/requests-static.ts +1 -0
- package/src/core/network/requests-toasting.ts +1 -0
- package/src/core/network/types.ts +4 -1
- package/src/core/wasm/bridge.ts +18 -2
- package/src/core/wasm/worker/bootstrap.ts +3 -1
- package/src/core/wasm/worker/getMarimoWheel.ts +3 -8
- package/src/core/wasm/worker/types.ts +3 -0
- package/src/core/websocket/useMarimoWebSocket.tsx +7 -1
- package/src/css/app/Cell.css +42 -21
- package/src/css/app/codemirror.css +5 -1
- package/src/css/globals.css +3 -0
- package/src/css/md.css +1 -1
- package/src/plugins/impl/MicrophonePlugin.tsx +2 -2
- package/src/plugins/impl/chat/ChatPlugin.tsx +2 -9
- package/src/plugins/impl/chat/chat-ui.tsx +129 -110
- package/src/plugins/impl/chat/types.ts +5 -8
- package/src/plugins/impl/code/__tests__/language.test.ts +15 -0
- package/src/plugins/impl/code/any-language-editor.tsx +11 -8
- package/src/plugins/impl/vega/vega.css +121 -0
- package/src/plugins/layout/MimeRenderPlugin.tsx +3 -6
- package/src/stories/cell.stories.tsx +6 -0
- package/src/stories/layout/vertical/one-column.stories.tsx +215 -0
- package/src/theme/useTheme.ts +11 -6
- package/src/utils/Logger.ts +5 -6
- package/src/utils/__tests__/blob.test.ts +37 -0
- package/src/utils/arrays.ts +13 -0
- package/src/utils/fileToBase64.ts +21 -6
- package/src/utils/json/base64.ts +5 -2
- package/src/utils/numbers.ts +9 -7
- package/dist/any-language-editor-DC5170DQ.js +0 -45
- package/dist/asn1-jKiBa2Ya.js +0 -95
- package/dist/clojure-CCKyeQKf.js +0 -800
- package/dist/css-BkF-NPzE.js +0 -1553
- package/dist/index-5ZH_qS8j.js +0 -288
- package/dist/index-U4yn89qO.js +0 -341
- package/dist/javascript-C2yteZeJ.js +0 -691
- package/dist/min-DS5Jz-hg.js +0 -80
- package/dist/mindmap-definition-LNHGMQRG-0aOVaMR8.js +0 -3234
- package/dist/mllike-BSnXJBGA.js +0 -272
- package/dist/pug-CwAQJzGR.js +0 -248
- package/dist/python-BkR3uSy8.js +0 -313
- package/dist/rpm-IznJm2Xc.js +0 -57
- package/dist/sequenceDiagram-WFGC7UMF-DMhHzllb.js +0 -2284
- package/dist/ttcn-cfg-Bac_acMi.js +0 -88
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import { useChat } from "@ai-sdk/react";
|
|
3
|
+
import { type UIMessage, useChat } from "@ai-sdk/react";
|
|
4
4
|
import { ChatBubbleIcon } from "@radix-ui/react-icons";
|
|
5
5
|
import { PopoverAnchor } from "@radix-ui/react-popover";
|
|
6
6
|
import type { ReactCodeMirrorRef } from "@uiw/react-codemirror";
|
|
7
|
-
import type
|
|
7
|
+
import { DefaultChatTransport, type FileUIPart } from "ai";
|
|
8
8
|
import { startCase } from "lodash-es";
|
|
9
9
|
import {
|
|
10
10
|
BotMessageSquareIcon,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
X,
|
|
19
19
|
} from "lucide-react";
|
|
20
20
|
import React, { useEffect, useRef, useState } from "react";
|
|
21
|
+
import { convertToFileUIPart } from "@/components/chat/chat-utils";
|
|
21
22
|
import {
|
|
22
23
|
type AdditionalCompletions,
|
|
23
24
|
PromptInput,
|
|
@@ -49,12 +50,7 @@ import { Logger } from "@/utils/Logger";
|
|
|
49
50
|
import { Objects } from "@/utils/objects";
|
|
50
51
|
import { ErrorBanner } from "../common/error-banner";
|
|
51
52
|
import type { PluginFunctions } from "./ChatPlugin";
|
|
52
|
-
import type {
|
|
53
|
-
ChatAttachment,
|
|
54
|
-
ChatConfig,
|
|
55
|
-
ChatMessage,
|
|
56
|
-
ChatRole,
|
|
57
|
-
} from "./types";
|
|
53
|
+
import type { ChatConfig, ChatMessage } from "./types";
|
|
58
54
|
|
|
59
55
|
interface Props extends PluginFunctions {
|
|
60
56
|
prompts: string[];
|
|
@@ -67,8 +63,9 @@ interface Props extends PluginFunctions {
|
|
|
67
63
|
}
|
|
68
64
|
|
|
69
65
|
export const Chatbot: React.FC<Props> = (props) => {
|
|
66
|
+
const [input, setInput] = useState("");
|
|
70
67
|
const [config, setConfig] = useState<ChatConfig>(props.config);
|
|
71
|
-
const [files, setFiles] = useState<
|
|
68
|
+
const [files, setFiles] = useState<File[] | undefined>(undefined);
|
|
72
69
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
73
70
|
const formRef = useRef<HTMLFormElement>(null);
|
|
74
71
|
const codeMirrorInputRef = useRef<ReactCodeMirrorRef>(null);
|
|
@@ -76,75 +73,86 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
76
73
|
|
|
77
74
|
const { data: initialMessages } = useAsyncData(async () => {
|
|
78
75
|
const chatMessages = await props.get_chat_history({});
|
|
79
|
-
const messages:
|
|
76
|
+
const messages: UIMessage[] = chatMessages.messages.map((message, idx) => ({
|
|
80
77
|
id: idx.toString(),
|
|
81
78
|
role: message.role,
|
|
82
|
-
|
|
83
|
-
experimental_attachments: message.attachments,
|
|
79
|
+
parts: message.parts ?? [],
|
|
84
80
|
}));
|
|
85
81
|
return messages;
|
|
86
82
|
}, []);
|
|
87
83
|
|
|
88
84
|
const {
|
|
89
85
|
messages,
|
|
86
|
+
sendMessage,
|
|
90
87
|
setMessages,
|
|
91
|
-
input,
|
|
92
|
-
setInput,
|
|
93
|
-
handleSubmit,
|
|
94
88
|
status,
|
|
95
89
|
stop,
|
|
96
90
|
error,
|
|
97
|
-
|
|
91
|
+
regenerate,
|
|
98
92
|
} = useChat({
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
93
|
+
transport: new DefaultChatTransport({
|
|
94
|
+
fetch: async (
|
|
95
|
+
request: RequestInfo | URL,
|
|
96
|
+
init: RequestInit | undefined,
|
|
97
|
+
) => {
|
|
98
|
+
if (init === undefined) {
|
|
99
|
+
return fetch(request);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const body = JSON.parse(init.body as unknown as string) as {
|
|
103
|
+
messages: UIMessage[];
|
|
104
|
+
};
|
|
105
|
+
try {
|
|
106
|
+
const messages = body.messages.map((m) => ({
|
|
107
|
+
role: m.role,
|
|
108
|
+
content: m.parts
|
|
109
|
+
?.map((p) => ("text" in p ? p.text : ""))
|
|
110
|
+
.join("\n"),
|
|
111
|
+
parts: m.parts,
|
|
112
|
+
}));
|
|
113
|
+
const response = await props.send_prompt({
|
|
114
|
+
messages: messages,
|
|
115
|
+
config: {
|
|
116
|
+
max_tokens: config.max_tokens,
|
|
117
|
+
temperature: config.temperature,
|
|
118
|
+
top_p: config.top_p,
|
|
119
|
+
top_k: config.top_k,
|
|
120
|
+
frequency_penalty: config.frequency_penalty,
|
|
121
|
+
presence_penalty: config.presence_penalty,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
// Update local state with AI response
|
|
125
|
+
setMessages((prev) => [
|
|
126
|
+
...prev,
|
|
127
|
+
{
|
|
128
|
+
id: Date.now().toString(),
|
|
129
|
+
role: "assistant",
|
|
130
|
+
parts: [{ type: "text", text: response }],
|
|
131
|
+
},
|
|
132
|
+
]);
|
|
133
|
+
return new Response(response);
|
|
134
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
135
|
+
} catch (error: any) {
|
|
136
|
+
// HACK: strip the error message to clean up the response
|
|
137
|
+
const strippedError = error.message
|
|
138
|
+
.split("failed with exception ")
|
|
139
|
+
.pop();
|
|
140
|
+
return new Response(strippedError, { status: 400 });
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
}),
|
|
144
|
+
messages: initialMessages,
|
|
145
|
+
onFinish: (message) => {
|
|
133
146
|
setFiles(undefined);
|
|
134
147
|
|
|
135
148
|
if (fileInputRef.current) {
|
|
136
149
|
fileInputRef.current.value = "";
|
|
137
150
|
}
|
|
138
151
|
Logger.debug("Finished streaming message:", message);
|
|
139
|
-
Logger.debug("Token usage:", usage);
|
|
140
|
-
Logger.debug("Finish reason:", finishReason);
|
|
141
152
|
},
|
|
142
153
|
onError: (error) => {
|
|
143
154
|
Logger.error("An error occurred:", error);
|
|
144
155
|
},
|
|
145
|
-
onResponse: (response) => {
|
|
146
|
-
Logger.debug("Received HTTP response from server:", response);
|
|
147
|
-
},
|
|
148
156
|
});
|
|
149
157
|
|
|
150
158
|
const isLoading = status === "submitted" || status === "streaming";
|
|
@@ -157,12 +165,12 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
157
165
|
}
|
|
158
166
|
};
|
|
159
167
|
|
|
160
|
-
const renderAttachment = (attachment:
|
|
161
|
-
if (attachment.
|
|
168
|
+
const renderAttachment = (attachment: FileUIPart) => {
|
|
169
|
+
if (attachment.mediaType?.startsWith("image")) {
|
|
162
170
|
return (
|
|
163
171
|
<img
|
|
164
172
|
src={attachment.url}
|
|
165
|
-
alt={attachment.
|
|
173
|
+
alt={attachment.filename || "Attachment"}
|
|
166
174
|
className="object-contain rounded-sm"
|
|
167
175
|
width={100}
|
|
168
176
|
height={100}
|
|
@@ -177,18 +185,20 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
177
185
|
rel="noopener noreferrer"
|
|
178
186
|
className="text-background hover:underline"
|
|
179
187
|
>
|
|
180
|
-
{attachment.
|
|
188
|
+
{attachment.filename || "Attachment"}
|
|
181
189
|
</a>
|
|
182
190
|
);
|
|
183
191
|
};
|
|
184
192
|
|
|
185
|
-
const renderMessage = (message:
|
|
193
|
+
const renderMessage = (message: UIMessage) => {
|
|
194
|
+
const textParts = message.parts?.filter((p) => p.type === "text");
|
|
195
|
+
const textContent = textParts?.map((p) => p.text).join("\n");
|
|
186
196
|
const content =
|
|
187
197
|
message.role === "assistant"
|
|
188
|
-
? renderHTML({ html:
|
|
189
|
-
:
|
|
198
|
+
? renderHTML({ html: textContent })
|
|
199
|
+
: textContent;
|
|
190
200
|
|
|
191
|
-
const attachments = message.
|
|
201
|
+
const attachments = message.parts?.filter((p) => p.type === "file");
|
|
192
202
|
|
|
193
203
|
return (
|
|
194
204
|
<>
|
|
@@ -204,7 +214,7 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
204
214
|
size: "icon",
|
|
205
215
|
})}
|
|
206
216
|
href={attachment.url}
|
|
207
|
-
download={attachment.
|
|
217
|
+
download={attachment.filename}
|
|
208
218
|
>
|
|
209
219
|
<DownloadIcon className="size-3" />
|
|
210
220
|
</a>
|
|
@@ -274,50 +284,53 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
274
284
|
</p>
|
|
275
285
|
</div>
|
|
276
286
|
)}
|
|
277
|
-
{messages.map((message) =>
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
>
|
|
287
|
+
{messages.map((message) => {
|
|
288
|
+
const textContent = message.parts
|
|
289
|
+
?.filter((p) => p.type === "text")
|
|
290
|
+
.map((p) => p.text)
|
|
291
|
+
.join("\n");
|
|
292
|
+
|
|
293
|
+
return (
|
|
285
294
|
<div
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
295
|
+
key={message.id}
|
|
296
|
+
className={cn(
|
|
297
|
+
"flex flex-col group gap-2",
|
|
298
|
+
message.role === "user" ? "items-end" : "items-start",
|
|
299
|
+
)}
|
|
291
300
|
>
|
|
292
|
-
<
|
|
293
|
-
className={
|
|
301
|
+
<div
|
|
302
|
+
className={`max-w-[80%] p-3 rounded-lg ${
|
|
303
|
+
message.role === "user"
|
|
304
|
+
? "bg-(--sky-11) text-(--slate-1) whitespace-pre-wrap"
|
|
305
|
+
: "bg-(--slate-4) text-(--slate-12)"
|
|
306
|
+
}`}
|
|
294
307
|
>
|
|
295
308
|
{renderMessage(message)}
|
|
296
|
-
</
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
</
|
|
309
|
+
</div>
|
|
310
|
+
<div className="flex justify-end text-xs gap-2 invisible group-hover:visible">
|
|
311
|
+
<button
|
|
312
|
+
type="button"
|
|
313
|
+
onClick={async () => {
|
|
314
|
+
await copyToClipboard(textContent);
|
|
315
|
+
toast({
|
|
316
|
+
title: "Copied to clipboard",
|
|
317
|
+
});
|
|
318
|
+
}}
|
|
319
|
+
className="text-xs text-(--slate-9) hover:text-(--slate-11)"
|
|
320
|
+
>
|
|
321
|
+
<ClipboardIcon className="h-3 w-3" />
|
|
322
|
+
</button>
|
|
323
|
+
<button
|
|
324
|
+
type="button"
|
|
325
|
+
onClick={() => handleDelete(message.id)}
|
|
326
|
+
className="text-xs text-(--slate-9) hover:text-(--slate-11)"
|
|
327
|
+
>
|
|
328
|
+
<Trash2Icon className="h-3 w-3 text-(--red-9)" />
|
|
329
|
+
</button>
|
|
330
|
+
</div>
|
|
318
331
|
</div>
|
|
319
|
-
|
|
320
|
-
)
|
|
332
|
+
);
|
|
333
|
+
})}
|
|
321
334
|
|
|
322
335
|
{isLoading && (
|
|
323
336
|
<div className="flex items-center justify-center space-x-2 mb-4">
|
|
@@ -336,17 +349,23 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
336
349
|
{error && (
|
|
337
350
|
<div className="flex items-center justify-center space-x-2 mb-4">
|
|
338
351
|
<ErrorBanner error={error} />
|
|
339
|
-
<Button variant="outline" size="sm" onClick={() =>
|
|
352
|
+
<Button variant="outline" size="sm" onClick={() => regenerate()}>
|
|
340
353
|
Retry
|
|
341
354
|
</Button>
|
|
342
355
|
</div>
|
|
343
356
|
)}
|
|
344
357
|
</div>
|
|
345
|
-
|
|
346
358
|
<form
|
|
347
|
-
onSubmit={(evt) => {
|
|
348
|
-
|
|
349
|
-
|
|
359
|
+
onSubmit={async (evt) => {
|
|
360
|
+
evt.preventDefault();
|
|
361
|
+
|
|
362
|
+
const fileParts = files
|
|
363
|
+
? await convertToFileUIPart(files)
|
|
364
|
+
: undefined;
|
|
365
|
+
|
|
366
|
+
sendMessage({
|
|
367
|
+
role: "user",
|
|
368
|
+
parts: [{ type: "text", text: input }, ...(fileParts ?? [])],
|
|
350
369
|
});
|
|
351
370
|
}}
|
|
352
371
|
ref={formRef}
|
|
@@ -388,7 +407,7 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
388
407
|
{files && files.length === 1 && (
|
|
389
408
|
<span
|
|
390
409
|
title={files[0].name}
|
|
391
|
-
className="text-sm text-(--slate-11) truncate shrink-0 w-24"
|
|
410
|
+
className="text-sm text-(--slate-11) truncate shrink-0 w-fit max-w-24"
|
|
392
411
|
>
|
|
393
412
|
{files[0].name}
|
|
394
413
|
</span>
|
|
@@ -439,7 +458,7 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
439
458
|
}
|
|
440
459
|
onChange={(event) => {
|
|
441
460
|
if (event.target.files) {
|
|
442
|
-
setFiles(event.target.files);
|
|
461
|
+
setFiles([...event.target.files]);
|
|
443
462
|
}
|
|
444
463
|
}}
|
|
445
464
|
/>
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import type { UIMessage } from "ai";
|
|
4
|
+
|
|
2
5
|
export type ChatRole = "system" | "user" | "assistant";
|
|
3
6
|
|
|
4
7
|
export interface ChatMessage {
|
|
5
8
|
role: ChatRole;
|
|
6
|
-
content: string;
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface ChatAttachment {
|
|
11
|
-
name?: string;
|
|
12
|
-
contentType?: string;
|
|
13
|
-
url: string;
|
|
9
|
+
content: string; // TODO: Deprecate content
|
|
10
|
+
parts: UIMessage["parts"];
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
export interface SendMessageRequest {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { langs } from "@uiw/codemirror-extensions-langs";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { LANGUAGE_MAP } from "../any-language-editor";
|
|
6
|
+
|
|
7
|
+
describe("Codemirror Languages", () => {
|
|
8
|
+
const codemirrorLanguages = Object.keys(langs);
|
|
9
|
+
|
|
10
|
+
it("LANGUAGE_MAP should have all the languages in CodeMirror", () => {
|
|
11
|
+
for (const language of Object.values(LANGUAGE_MAP)) {
|
|
12
|
+
expect(codemirrorLanguages).toContain(language);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
type LanguageName,
|
|
5
|
-
langs,
|
|
6
|
-
loadLanguage,
|
|
7
|
-
} from "@uiw/codemirror-extensions-langs";
|
|
3
|
+
import { langs, loadLanguage } from "@uiw/codemirror-extensions-langs";
|
|
8
4
|
import ReactCodeMirror, {
|
|
9
5
|
type Extension,
|
|
10
6
|
type ReactCodeMirrorProps,
|
|
@@ -15,6 +11,12 @@ import type { ResolvedTheme } from "@/theme/useTheme";
|
|
|
15
11
|
import { Logger } from "@/utils/Logger";
|
|
16
12
|
import { ErrorBanner } from "../common/error-banner";
|
|
17
13
|
|
|
14
|
+
export const LANGUAGE_MAP: Record<string, string> = {
|
|
15
|
+
python: "py",
|
|
16
|
+
javascript: "js",
|
|
17
|
+
typescript: "ts",
|
|
18
|
+
};
|
|
19
|
+
|
|
18
20
|
/**
|
|
19
21
|
* A code editor that supports any language.
|
|
20
22
|
*
|
|
@@ -28,6 +30,9 @@ const AnyLanguageCodeMirror: React.FC<
|
|
|
28
30
|
showCopyButton?: boolean;
|
|
29
31
|
}
|
|
30
32
|
> = ({ language, showCopyButton, extensions = [], ...props }) => {
|
|
33
|
+
// Maybe normalize the language to the extension
|
|
34
|
+
language = LANGUAGE_MAP[language || ""] || language;
|
|
35
|
+
|
|
31
36
|
const isNotSupported = language && !(language in langs);
|
|
32
37
|
if (isNotSupported) {
|
|
33
38
|
Logger.warn(`Language ${language} not found in CodeMirror.`);
|
|
@@ -37,9 +42,7 @@ const AnyLanguageCodeMirror: React.FC<
|
|
|
37
42
|
if (!language) {
|
|
38
43
|
return extensions;
|
|
39
44
|
}
|
|
40
|
-
return [loadLanguage(language
|
|
41
|
-
Boolean,
|
|
42
|
-
);
|
|
45
|
+
return [loadLanguage(language), ...extensions].filter(Boolean);
|
|
43
46
|
}, [language, extensions]);
|
|
44
47
|
|
|
45
48
|
return (
|
|
@@ -29,3 +29,124 @@
|
|
|
29
29
|
right: 2px;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Due to a bug when defining our own VegaPlugin where these styles are not applied,
|
|
35
|
+
* we provide the default styles for vega-actions.
|
|
36
|
+
* https://github.com/vega/vega-embed/blob/8f4ec8e136951a7e34b358e4e9b6037582a6ccdd/vega-embed.scss
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
.vega-embed.has-actions {
|
|
40
|
+
padding-right: 38px;
|
|
41
|
+
}
|
|
42
|
+
.vega-embed details:not([open]) > :not(summary) {
|
|
43
|
+
display: none !important;
|
|
44
|
+
}
|
|
45
|
+
.vega-embed summary {
|
|
46
|
+
list-style: none;
|
|
47
|
+
position: absolute;
|
|
48
|
+
top: 0;
|
|
49
|
+
right: 0;
|
|
50
|
+
padding: 6px;
|
|
51
|
+
z-index: 1000;
|
|
52
|
+
background: white;
|
|
53
|
+
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
|
|
54
|
+
color: #1b1e23;
|
|
55
|
+
border: 1px solid #aaa;
|
|
56
|
+
border-radius: 999px;
|
|
57
|
+
opacity: 0.2;
|
|
58
|
+
transition: opacity 0.4s ease-in;
|
|
59
|
+
cursor: pointer;
|
|
60
|
+
line-height: 0px;
|
|
61
|
+
}
|
|
62
|
+
.vega-embed summary::-webkit-details-marker {
|
|
63
|
+
display: none;
|
|
64
|
+
}
|
|
65
|
+
.vega-embed summary:active {
|
|
66
|
+
box-shadow: #aaa 0px 0px 0px 1px inset;
|
|
67
|
+
}
|
|
68
|
+
.vega-embed summary svg {
|
|
69
|
+
width: 14px;
|
|
70
|
+
height: 14px;
|
|
71
|
+
}
|
|
72
|
+
.vega-embed details[open] summary {
|
|
73
|
+
opacity: 0.7;
|
|
74
|
+
}
|
|
75
|
+
.vega-embed:hover summary,
|
|
76
|
+
.vega-embed:focus-within summary {
|
|
77
|
+
opacity: 1 !important;
|
|
78
|
+
transition: opacity 0.2s ease;
|
|
79
|
+
}
|
|
80
|
+
.vega-embed .vega-actions {
|
|
81
|
+
position: absolute;
|
|
82
|
+
z-index: 1001;
|
|
83
|
+
top: 35px;
|
|
84
|
+
/* right: -9px; Remove right for our own styles */
|
|
85
|
+
display: flex;
|
|
86
|
+
flex-direction: column;
|
|
87
|
+
padding-bottom: 8px;
|
|
88
|
+
padding-top: 8px;
|
|
89
|
+
border-radius: 4px;
|
|
90
|
+
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.2);
|
|
91
|
+
border: 1px solid #d9d9d9;
|
|
92
|
+
background: white;
|
|
93
|
+
animation-duration: 0.15s;
|
|
94
|
+
animation-name: scale-in;
|
|
95
|
+
animation-timing-function: cubic-bezier(0.2, 0, 0.13, 1.5);
|
|
96
|
+
text-align: left;
|
|
97
|
+
}
|
|
98
|
+
.vega-embed .vega-actions a {
|
|
99
|
+
padding: 8px 16px;
|
|
100
|
+
font-family: sans-serif;
|
|
101
|
+
font-size: 14px;
|
|
102
|
+
font-weight: 600;
|
|
103
|
+
white-space: nowrap;
|
|
104
|
+
color: #434a56;
|
|
105
|
+
text-decoration: none;
|
|
106
|
+
}
|
|
107
|
+
.vega-embed .vega-actions a:hover,
|
|
108
|
+
.vega-embed .vega-actions a:focus {
|
|
109
|
+
background-color: #f7f7f9;
|
|
110
|
+
color: black;
|
|
111
|
+
}
|
|
112
|
+
.vega-embed .vega-actions::before,
|
|
113
|
+
.vega-embed .vega-actions::after {
|
|
114
|
+
content: "";
|
|
115
|
+
display: inline-block;
|
|
116
|
+
position: absolute;
|
|
117
|
+
}
|
|
118
|
+
.vega-embed .vega-actions::before {
|
|
119
|
+
left: auto;
|
|
120
|
+
/* right: 14px; */
|
|
121
|
+
top: -16px;
|
|
122
|
+
border: 8px solid #000 0;
|
|
123
|
+
border-bottom-color: #d9d9d9;
|
|
124
|
+
}
|
|
125
|
+
.vega-embed .vega-actions::after {
|
|
126
|
+
left: auto;
|
|
127
|
+
/* right: 15px; */
|
|
128
|
+
top: -14px;
|
|
129
|
+
border: 7px solid #000 0;
|
|
130
|
+
border-bottom-color: #fff;
|
|
131
|
+
}
|
|
132
|
+
.vega-embed .chart-wrapper.fit-x {
|
|
133
|
+
width: 100%;
|
|
134
|
+
}
|
|
135
|
+
.vega-embed .chart-wrapper.fit-y {
|
|
136
|
+
height: 100%;
|
|
137
|
+
}
|
|
138
|
+
.vega-embed-wrapper {
|
|
139
|
+
max-width: 100%;
|
|
140
|
+
overflow: auto;
|
|
141
|
+
padding-right: 14px;
|
|
142
|
+
}
|
|
143
|
+
@keyframes scale-in {
|
|
144
|
+
from {
|
|
145
|
+
opacity: 0;
|
|
146
|
+
transform: scale(0.6);
|
|
147
|
+
}
|
|
148
|
+
to {
|
|
149
|
+
opacity: 1;
|
|
150
|
+
transform: scale(1);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -19,12 +19,9 @@ export class MimeRendererPlugin implements IStatelessPlugin<Data> {
|
|
|
19
19
|
|
|
20
20
|
validator = z.object({
|
|
21
21
|
mime: z.string().transform((val) => val as OutputMessage["mimetype"]),
|
|
22
|
-
data: z
|
|
23
|
-
z.string(),
|
|
24
|
-
|
|
25
|
-
z.record(z.unknown()),
|
|
26
|
-
z.array(z.any()),
|
|
27
|
-
]),
|
|
22
|
+
data: z
|
|
23
|
+
.union([z.string(), z.null(), z.record(z.unknown()), z.array(z.any())])
|
|
24
|
+
.transform((val) => val as OutputMessage["data"]),
|
|
28
25
|
});
|
|
29
26
|
|
|
30
27
|
render({ data }: IStatelessPluginProps<Data>): JSX.Element {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
+
|
|
2
3
|
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
3
4
|
import { createStore, Provider } from "jotai";
|
|
4
5
|
import { createRef } from "react";
|
|
@@ -9,6 +10,8 @@ import {
|
|
|
9
10
|
} from "@/core/cells/types";
|
|
10
11
|
import { defaultUserConfig } from "@/core/config/config-schema";
|
|
11
12
|
import { connectionAtom } from "@/core/network/connection";
|
|
13
|
+
import { requestClientAtom } from "@/core/network/requests";
|
|
14
|
+
import { resolveRequestClient } from "@/core/network/resolve.ts";
|
|
12
15
|
import type { CellConfig } from "@/core/network/types";
|
|
13
16
|
import { WebSocketState } from "@/core/websocket/types";
|
|
14
17
|
import { MultiColumn } from "@/utils/id-tree";
|
|
@@ -78,6 +81,7 @@ const Cell: React.FC<{
|
|
|
78
81
|
const store = createStore();
|
|
79
82
|
store.set(notebookAtom, notebook);
|
|
80
83
|
store.set(connectionAtom, { state: WebSocketState.OPEN });
|
|
84
|
+
store.set(requestClientAtom, resolveRequestClient());
|
|
81
85
|
return (
|
|
82
86
|
<Provider store={store}>
|
|
83
87
|
<TooltipProvider>
|
|
@@ -219,6 +223,7 @@ export const Disabled: Story = {
|
|
|
219
223
|
config: {
|
|
220
224
|
disabled: true,
|
|
221
225
|
hide_code: false,
|
|
226
|
+
column: null,
|
|
222
227
|
},
|
|
223
228
|
output: {
|
|
224
229
|
channel: "output",
|
|
@@ -299,6 +304,7 @@ export const DisabledAndStaleStatus: Story = {
|
|
|
299
304
|
overrides={{
|
|
300
305
|
runElapsedTimeMs: 20 as Milliseconds,
|
|
301
306
|
config: {
|
|
307
|
+
column: null,
|
|
302
308
|
disabled: true,
|
|
303
309
|
hide_code: false,
|
|
304
310
|
},
|