@marimo-team/islands 0.19.8-dev5 → 0.19.8-dev50
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/{Combination-Bg-xN8JV.js → Combination-BTMrlhzT.js} +11 -10
- package/dist/{ConnectedDataExplorerComponent-DewsKLl2.js → ConnectedDataExplorerComponent-BAeQ8DWw.js} +11 -11
- package/dist/{ImageComparisonComponent-Bijp8beW.js → ImageComparisonComponent-DkEXPki_.js} +2 -2
- package/dist/{any-language-editor-DZc6NCTp.js → any-language-editor-D0UQItkS.js} +6 -6
- package/dist/{architectureDiagram-VXUJARFQ--NkyBn9Y.js → architectureDiagram-VXUJARFQ-DPPYVq8H.js} +4 -4
- package/dist/assets/__vite-browser-external-WSlCcXn_.js +1 -0
- package/dist/assets/worker-DUYMdbtA.js +73 -0
- package/dist/{blockDiagram-VD42YOAC-DEZZaTW0.js → blockDiagram-VD42YOAC-BA5N05Y9.js} +4 -4
- package/dist/{button-BWvsJ2Wr.js → button-Cy0ElmIm.js} +2 -2
- package/dist/{c4Diagram-YG6GDRKO-Bj7hwWCO.js → c4Diagram-YG6GDRKO-DJLzuGJJ.js} +3 -3
- package/dist/{channel-B_QrFrGg.js → channel-Dob5kWXR.js} +1 -1
- package/dist/{check-CM_kewwn.js → check-DkNR52Mm.js} +1 -1
- package/dist/{chunk-5FQGJX7Z-D5VFKHmt.js → chunk-5FQGJX7Z-BEb20Lzt.js} +3 -3
- package/dist/{chunk-ABZYJK2D-SZPYmRzN.js → chunk-ABZYJK2D-BXTC53mt.js} +1 -1
- package/dist/{chunk-ATLVNIR6-BI_WwH1o.js → chunk-ATLVNIR6-BJDjUR_c.js} +1 -1
- package/dist/{chunk-B4BG7PRW-BlI9Gm1l.js → chunk-B4BG7PRW-DzmUUpfH.js} +4 -4
- package/dist/{chunk-DI55MBZ5-BXxemMn5.js → chunk-DI55MBZ5-gTd3J8Tu.js} +4 -4
- package/dist/{chunk-EXTU4WIE-CzWtDV99.js → chunk-EXTU4WIE-DyoOs5QX.js} +1 -1
- package/dist/{chunk-JA3XYJ7Z-DQ-2ARfa.js → chunk-JA3XYJ7Z-BGnAIbOP.js} +2 -2
- package/dist/{chunk-JZLCHNYA-CVfjf2vv.js → chunk-JZLCHNYA-CIRgweVQ.js} +4 -4
- package/dist/{chunk-N4CR4FBY-BCZvQ7Jq.js → chunk-N4CR4FBY-DKSvXAIS.js} +5 -5
- package/dist/{chunk-QN33PNHL-DY_2Q2zl.js → chunk-QN33PNHL-B6zC8BTi.js} +1 -1
- package/dist/{chunk-QXUST7PY-BMCjAVR_.js → chunk-QXUST7PY-C7750n_u.js} +5 -5
- package/dist/{chunk-S3R3BYOJ-Ddu0H4Qa.js → chunk-S3R3BYOJ-CBkH6JZZ.js} +1 -1
- package/dist/{chunk-TZMSLE5B-C2wVlbMl.js → chunk-TZMSLE5B-DObGL7xi.js} +1 -1
- package/dist/{classDiagram-2ON5EDUG-D-g7zbyO.js → classDiagram-2ON5EDUG-B9pkKjjc.js} +9 -9
- package/dist/{classDiagram-v2-WZHVMYZB-C7v5zNRD.js → classDiagram-v2-WZHVMYZB-CRhhA0tV.js} +9 -9
- package/dist/{click-outside-container-BCN5BtVO.js → click-outside-container-DNfggvIW.js} +1 -1
- package/dist/{code-block-37QAKDTI-eUgXqGNG.js → code-block-37QAKDTI-u5kgjqmr.js} +2 -2
- package/dist/{compiler-runtime-DHFVbq0b.js → compiler-runtime-B_OLMU9S.js} +1 -1
- package/dist/{copy-B59Bw3-w.js → copy-DRaXIb_a.js} +3 -3
- package/dist/{dagre-6UL2VRFP-DKIPL74O.js → dagre-6UL2VRFP-C2C2XxsB.js} +6 -6
- package/dist/{data-grid-overlay-editor-COyFwFmE.js → data-grid-overlay-editor-BXqtz1ia.js} +4 -4
- package/dist/{diagram-PSM6KHXK-CVTrAZaP.js → diagram-PSM6KHXK-DHBY-94p.js} +5 -5
- package/dist/{diagram-QEK2KX5R-BqHBzu3x.js → diagram-QEK2KX5R-CgMshOwn.js} +3 -3
- package/dist/{diagram-S2PKOQOG-CJD6owcg.js → diagram-S2PKOQOG-F1KPva3Y.js} +3 -3
- package/dist/{dist-Co5PD8Fb.js → dist-BBYTEAvO.js} +1 -1
- package/dist/{erDiagram-Q2GNP2WA-CqOceSf9.js → erDiagram-Q2GNP2WA-18gGng8V.js} +9 -9
- package/dist/{error-banner-C7KLpECd.js → error-banner-D2zjeN_a.js} +5 -5
- package/dist/{esm-D4WO8J3G.js → esm-CgRNPmz8.js} +6 -6
- package/dist/{flowDiagram-NV44I4VS-K7-DUifo.js → flowDiagram-NV44I4VS-iHFiHYe0.js} +9 -9
- package/dist/{ganttDiagram-JELNMOA3-BwUFY9Nu.js → ganttDiagram-JELNMOA3-D7GixxiF.js} +2 -2
- package/dist/{gitGraphDiagram-NY62KEGX-CjGRtLb1.js → gitGraphDiagram-NY62KEGX-CJFHytRK.js} +2 -2
- package/dist/{glide-data-editor-C3T7HsLi.js → glide-data-editor-BYwb17Bf.js} +13 -13
- package/dist/{infoDiagram-WHAUD3N6-DNhmDn-6.js → infoDiagram-WHAUD3N6-B5Lkh3A9.js} +2 -2
- package/dist/{journeyDiagram-XKPGCS4Q-BOdK47P8.js → journeyDiagram-XKPGCS4Q-CV_9R9iP.js} +2 -2
- package/dist/{kanban-definition-3W4ZIXB7-A0JC9d0g.js → kanban-definition-3W4ZIXB7-Dp21D5Ym.js} +6 -6
- package/dist/{katex-DJyOeQ91.js → katex-CX2BKujk.js} +1 -1
- package/dist/{katex-Dm9nZf6A.js → katex-Db0k5oV_.js} +1 -1
- package/dist/{label-C4PtQcza.js → label-CxU5JNBW.js} +6 -6
- package/dist/main.js +2000 -1887
- package/dist/mermaid-4DMBBIKO-BhDCqnO1.js +6 -0
- package/dist/{mermaid-Bqp2Xw99.js → mermaid-B__BZSXU.js} +39 -39
- package/dist/{mhchem-BqdXeZVX.js → mhchem-w1tkUnWr.js} +1 -1
- package/dist/{mindmap-definition-VGOIOE7T-CS6nKN_L.js → mindmap-definition-VGOIOE7T-B_5mfdYp.js} +8 -8
- package/dist/{number-overlay-editor-Bz_bDJQb.js → number-overlay-editor-D-4WQAGX.js} +2 -2
- package/dist/{pieDiagram-ADFJNKIX-DSa60Grk.js → pieDiagram-ADFJNKIX-B-DGEopK.js} +3 -3
- package/dist/{quadrantDiagram-AYHSOK5B-CFnMbP2J.js → quadrantDiagram-AYHSOK5B-M_yRSIZn.js} +1 -1
- package/dist/{react-DdA8EBol.js → react-Bs6Z0kvn.js} +1 -1
- package/dist/{react-dom-DJW8xUDg.js → react-dom-CqtLRVZP.js} +2 -2
- package/dist/{react-plotly-jVjTu07w.js → react-plotly-BuRa9xtI.js} +1 -1
- package/dist/{react-vega-DgHpnZ04.js → react-vega-3WcLHYC7.js} +2 -2
- package/dist/{react-vega-CjiPWyw0.js → react-vega-DLFvGrpJ.js} +1 -1
- package/dist/{requirementDiagram-UZGBJVZJ-ytLQrFTk.js → requirementDiagram-UZGBJVZJ-9Wt82hOZ.js} +8 -8
- package/dist/{sankeyDiagram-TZEHDZUN-KQqXDoky.js → sankeyDiagram-TZEHDZUN-x_aTXZeN.js} +1 -1
- package/dist/{sequenceDiagram-WL72ISMW-ByLI04T5.js → sequenceDiagram-WL72ISMW-CXXmJqiQ.js} +3 -3
- package/dist/{slides-component-BVjvNo92.js → slides-component-Dp-y50K9.js} +4 -4
- package/dist/{spec-Dmb1KfK3.js → spec-HoYHAQo2.js} +6 -6
- package/dist/{stateDiagram-FKZM4ZOC-Dfz8vBbP.js → stateDiagram-FKZM4ZOC-CiSKS_Mx.js} +9 -9
- package/dist/{stateDiagram-v2-4FDKWEC3-DRYoLdT5.js → stateDiagram-v2-4FDKWEC3-A43Itnjp.js} +9 -9
- package/dist/style.css +1 -1
- package/dist/{timeline-definition-IT6M3QCI-CO48XU1B.js → timeline-definition-IT6M3QCI-DR26eWb4.js} +1 -1
- package/dist/{types-CzEZ3EWT.js → types-Bb-6p8hv.js} +8 -8
- package/dist/{useAsyncData-BjNwqCfS.js → useAsyncData-Dyq3DyOF.js} +3 -3
- package/dist/{useDeepCompareMemoize-CfoxVor3.js → useDeepCompareMemoize-BhZZsis0.js} +12 -8
- package/dist/{useIframeCapabilities-BBO_R0ww.js → useIframeCapabilities-DurI5SJh.js} +2 -2
- package/dist/{useTheme-BYG2SH8J.js → useTheme-SlKl8MlS.js} +5 -6
- package/dist/{vega-component-rDX7xwxH.js → vega-component-DCxUyPnb.js} +10 -10
- package/dist/{xychartDiagram-PRI3JC2R-CUIfjNVD.js → xychartDiagram-PRI3JC2R-BcVxCRox.js} +4 -4
- package/dist/{zod-DITCj31F.js → zod-bjADtMKr.js} +3 -3
- package/package.json +18 -18
- package/src/components/app-config/ai-config.tsx +11 -2
- package/src/components/app-config/optional-features.tsx +1 -1
- package/src/components/app-config/user-config-form.tsx +0 -54
- package/src/components/chat/__tests__/useFileState.test.tsx +93 -0
- package/src/components/chat/acp/__tests__/state.test.ts +69 -0
- package/src/components/chat/acp/agent-panel.tsx +26 -77
- package/src/components/chat/acp/state.ts +6 -6
- package/src/components/chat/chat-components.tsx +114 -1
- package/src/components/chat/chat-panel.tsx +79 -134
- package/src/components/chat/chat-utils.ts +42 -0
- package/src/components/data-table/__tests__/data-table.test.tsx +94 -2
- package/src/components/editor/actions/useCellActionButton.tsx +14 -1
- package/src/components/editor/ai/add-cell-with-ai.tsx +85 -53
- package/src/components/editor/ai/ai-completion-editor.tsx +15 -38
- package/src/components/editor/cell/CreateCellButton.tsx +2 -1
- package/src/components/editor/cell/code/cell-editor.tsx +12 -0
- package/src/components/editor/chrome/panels/packages-panel.tsx +12 -9
- package/src/components/editor/database/__tests__/__snapshots__/as-code.test.ts.snap +15 -0
- package/src/components/editor/database/__tests__/as-code.test.ts +8 -0
- package/src/components/editor/database/as-code.ts +3 -0
- package/src/components/editor/database/schemas.ts +9 -0
- package/src/components/editor/renderers/cell-array.tsx +2 -1
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +12 -0
- package/src/components/pages/gallery-page.tsx +37 -6
- package/src/core/MarimoApp.tsx +12 -8
- package/src/core/ai/context/providers/file.ts +1 -1
- package/src/core/cells/__tests__/cells.test.ts +120 -0
- package/src/core/cells/__tests__/session.test.ts +37 -1
- package/src/core/cells/cells.ts +14 -0
- package/src/core/cells/session.ts +20 -8
- package/src/core/codemirror/language/languages/markdown.ts +7 -0
- package/src/core/config/feature-flag.tsx +0 -4
- package/src/core/dom/uiregistry.ts +4 -1
- package/src/core/islands/__tests__/bridge.test.ts +7 -2
- package/src/core/islands/bridge.ts +1 -1
- package/src/core/islands/main.ts +7 -0
- package/src/core/network/types.ts +2 -2
- package/src/core/run-app.tsx +11 -4
- package/src/core/static/__tests__/files.test.ts +195 -1
- package/src/core/static/files.ts +39 -9
- package/src/core/wasm/bridge.ts +1 -1
- package/src/core/websocket/useMarimoKernelConnection.tsx +5 -15
- package/src/plugins/core/registerReactComponent.tsx +9 -1
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +164 -0
- package/src/plugins/impl/anywidget/AnyWidgetPlugin.tsx +93 -168
- package/src/plugins/impl/anywidget/__tests__/AnyWidgetPlugin.test.tsx +37 -123
- package/src/plugins/impl/anywidget/__tests__/model.test.ts +128 -122
- package/src/{utils/__tests__/data-views.test.ts → plugins/impl/anywidget/__tests__/serialization.test.ts} +42 -96
- package/src/plugins/impl/anywidget/model.ts +348 -223
- package/src/plugins/impl/anywidget/schemas.ts +32 -0
- package/src/{utils/data-views.ts → plugins/impl/anywidget/serialization.ts} +13 -36
- package/src/plugins/impl/anywidget/types.ts +27 -0
- package/src/plugins/impl/chat/chat-ui.tsx +22 -20
- package/src/utils/Deferred.ts +21 -0
- package/src/utils/__tests__/blob.test.ts +3 -3
- package/src/utils/__tests__/id-tree.test.ts +22 -7
- package/src/utils/__tests__/mime-types.test.ts +8 -10
- package/src/utils/__tests__/url-parser.test.ts +22 -0
- package/src/utils/blob.ts +14 -27
- package/src/utils/id-tree.tsx +11 -19
- package/src/utils/json/base64.ts +38 -8
- package/src/utils/mime-types.ts +5 -5
- package/src/utils/url-parser.ts +1 -1
- package/dist/assets/__vite-browser-external-DRa9CT_O.js +0 -1
- package/dist/assets/worker-SqntmiwV.js +0 -73
- package/dist/mermaid-4DMBBIKO-o3xNphpD.js +0 -6
|
@@ -3,12 +3,8 @@
|
|
|
3
3
|
import { useAtom, useAtomValue } from "jotai";
|
|
4
4
|
import { capitalize } from "lodash-es";
|
|
5
5
|
import {
|
|
6
|
-
AtSignIcon,
|
|
7
6
|
BotMessageSquareIcon,
|
|
8
|
-
PaperclipIcon,
|
|
9
7
|
RefreshCwIcon,
|
|
10
|
-
SendIcon,
|
|
11
|
-
SquareIcon,
|
|
12
8
|
StopCircleIcon,
|
|
13
9
|
} from "lucide-react";
|
|
14
10
|
import React, { memo, useEffect, useMemo, useRef, useState } from "react";
|
|
@@ -25,8 +21,7 @@ import {
|
|
|
25
21
|
import { PanelEmptyState } from "@/components/editor/chrome/panels/empty-state";
|
|
26
22
|
import { Spinner } from "@/components/icons/spinner";
|
|
27
23
|
import { Button } from "@/components/ui/button";
|
|
28
|
-
import {
|
|
29
|
-
import { Tooltip, TooltipProvider } from "@/components/ui/tooltip";
|
|
24
|
+
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
30
25
|
import { cn } from "@/utils/cn";
|
|
31
26
|
import { Logger } from "@/utils/Logger";
|
|
32
27
|
import { AgentDocs } from "./agent-docs";
|
|
@@ -70,7 +65,13 @@ import { store } from "@/core/state/jotai";
|
|
|
70
65
|
import { ErrorBanner } from "@/plugins/impl/common/error-banner";
|
|
71
66
|
import { Functions } from "@/utils/functions";
|
|
72
67
|
import { Paths } from "@/utils/paths";
|
|
73
|
-
import {
|
|
68
|
+
import {
|
|
69
|
+
AddContextButton,
|
|
70
|
+
AttachFileButton,
|
|
71
|
+
FileAttachmentPill,
|
|
72
|
+
SendButton,
|
|
73
|
+
} from "../chat-components";
|
|
74
|
+
import { useFileState } from "../chat-utils";
|
|
74
75
|
import { ReadyToChatBlock } from "./blocks";
|
|
75
76
|
import {
|
|
76
77
|
convertFilesToResourceLinks,
|
|
@@ -89,9 +90,6 @@ import type {
|
|
|
89
90
|
|
|
90
91
|
const logger = Logger.get("agents");
|
|
91
92
|
|
|
92
|
-
// File attachment constants
|
|
93
|
-
const SUPPORTED_ATTACHMENT_TYPES = ["image/*", "text/*"];
|
|
94
|
-
|
|
95
93
|
interface AgentTitleProps {
|
|
96
94
|
currentAgentId?: ExternalAgentId;
|
|
97
95
|
}
|
|
@@ -392,55 +390,21 @@ const PromptArea = memo<PromptAreaProps>(
|
|
|
392
390
|
)}
|
|
393
391
|
</div>
|
|
394
392
|
<div className="flex flex-row">
|
|
395
|
-
<
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
className="cursor-pointer"
|
|
410
|
-
onClick={() => fileInputRef.current?.click()}
|
|
411
|
-
title="Attach a file"
|
|
412
|
-
disabled={isLoading}
|
|
413
|
-
>
|
|
414
|
-
<PaperclipIcon className="h-3.5 w-3.5" />
|
|
415
|
-
</Button>
|
|
416
|
-
</Tooltip>
|
|
417
|
-
<Input
|
|
418
|
-
ref={fileInputRef}
|
|
419
|
-
type="file"
|
|
420
|
-
multiple={true}
|
|
421
|
-
hidden={true}
|
|
422
|
-
onChange={(event) => {
|
|
423
|
-
if (event.target.files) {
|
|
424
|
-
onAddFiles([...event.target.files]);
|
|
425
|
-
}
|
|
426
|
-
}}
|
|
427
|
-
accept={SUPPORTED_ATTACHMENT_TYPES.join(",")}
|
|
393
|
+
<AddContextButton
|
|
394
|
+
handleAddContext={handleAddContext}
|
|
395
|
+
isLoading={isLoading}
|
|
396
|
+
/>
|
|
397
|
+
<AttachFileButton
|
|
398
|
+
fileInputRef={fileInputRef}
|
|
399
|
+
isLoading={isLoading}
|
|
400
|
+
onAddFiles={onAddFiles}
|
|
401
|
+
/>
|
|
402
|
+
<SendButton
|
|
403
|
+
isLoading={isLoading}
|
|
404
|
+
onStop={onStop}
|
|
405
|
+
onSendClick={handleSendClick}
|
|
406
|
+
isEmpty={!promptValue.trim()}
|
|
428
407
|
/>
|
|
429
|
-
<Tooltip content={isLoading ? "Stop" : "Submit"}>
|
|
430
|
-
<Button
|
|
431
|
-
variant="text"
|
|
432
|
-
size="sm"
|
|
433
|
-
className="h-6 w-6 p-0 hover:bg-muted/30 cursor-pointer"
|
|
434
|
-
onClick={isLoading ? onStop : handleSendClick}
|
|
435
|
-
disabled={isLoading ? false : !promptValue.trim()}
|
|
436
|
-
>
|
|
437
|
-
{isLoading ? (
|
|
438
|
-
<SquareIcon className="h-3 w-3 fill-current" />
|
|
439
|
-
) : (
|
|
440
|
-
<SendIcon className="h-3 w-3" />
|
|
441
|
-
)}
|
|
442
|
-
</Button>
|
|
443
|
-
</Tooltip>
|
|
444
408
|
</div>
|
|
445
409
|
</div>
|
|
446
410
|
</TooltipProvider>
|
|
@@ -664,7 +628,7 @@ const AgentPanel: React.FC = () => {
|
|
|
664
628
|
const [isLoading, setIsLoading] = useState(false);
|
|
665
629
|
const [error, setError] = useState<Error | string | null>(null);
|
|
666
630
|
const [promptValue, setPromptValue] = useState("");
|
|
667
|
-
const
|
|
631
|
+
const { files, addFiles, clearFiles, removeFile } = useFileState();
|
|
668
632
|
const [sessionModels, setSessionModels] = useState<SessionModelState | null>(
|
|
669
633
|
null,
|
|
670
634
|
);
|
|
@@ -891,7 +855,7 @@ const AgentPanel: React.FC = () => {
|
|
|
891
855
|
});
|
|
892
856
|
setIsLoading(true);
|
|
893
857
|
setPromptValue("");
|
|
894
|
-
|
|
858
|
+
clearFiles();
|
|
895
859
|
|
|
896
860
|
// Update session title with first message if it's still the default
|
|
897
861
|
if (selectedTab?.title.startsWith("New ")) {
|
|
@@ -967,21 +931,6 @@ const AgentPanel: React.FC = () => {
|
|
|
967
931
|
setIsLoading(false);
|
|
968
932
|
});
|
|
969
933
|
|
|
970
|
-
// Handler for adding files
|
|
971
|
-
const handleAddFiles = useEvent((newFiles: File[]) => {
|
|
972
|
-
if (newFiles.length === 0) {
|
|
973
|
-
return;
|
|
974
|
-
}
|
|
975
|
-
setFiles((prev) => [...(prev ?? []), ...newFiles]);
|
|
976
|
-
});
|
|
977
|
-
|
|
978
|
-
// Handler for removing files
|
|
979
|
-
const handleRemoveFile = useEvent((fileToRemove: File) => {
|
|
980
|
-
if (files) {
|
|
981
|
-
setFiles(files.filter((f) => f !== fileToRemove));
|
|
982
|
-
}
|
|
983
|
-
});
|
|
984
|
-
|
|
985
934
|
// Handler for manual connect
|
|
986
935
|
const handleManualConnect = useEvent(() => {
|
|
987
936
|
logger.debug("Manual connect requested", {
|
|
@@ -1148,7 +1097,7 @@ const AgentPanel: React.FC = () => {
|
|
|
1148
1097
|
<FileAttachmentPill
|
|
1149
1098
|
file={file}
|
|
1150
1099
|
key={file.name}
|
|
1151
|
-
onRemove={() =>
|
|
1100
|
+
onRemove={() => removeFile(file)}
|
|
1152
1101
|
/>
|
|
1153
1102
|
))}
|
|
1154
1103
|
</div>
|
|
@@ -1160,7 +1109,7 @@ const AgentPanel: React.FC = () => {
|
|
|
1160
1109
|
promptValue={promptValue}
|
|
1161
1110
|
onPromptValueChange={setPromptValue}
|
|
1162
1111
|
onPromptSubmit={handlePromptSubmit}
|
|
1163
|
-
onAddFiles={
|
|
1112
|
+
onAddFiles={addFiles}
|
|
1164
1113
|
onStop={handleStop}
|
|
1165
1114
|
fileInputRef={fileInputRef}
|
|
1166
1115
|
commands={availableCommands}
|
|
@@ -233,13 +233,17 @@ export function getAgentDisplayName(agentId: ExternalAgentId): string {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
export function getAgentWebSocketUrl(agentId: ExternalAgentId): string {
|
|
236
|
-
|
|
236
|
+
const port = AGENT_CONFIG[agentId].port;
|
|
237
|
+
// Use the current page's hostname so the agent is reachable when
|
|
238
|
+
// marimo is accessed remotely (e.g. via direct IP or reverse proxy).
|
|
239
|
+
const hostname = window.location.hostname;
|
|
240
|
+
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
|
241
|
+
return `${protocol}//${hostname}:${port}/message` as const;
|
|
237
242
|
}
|
|
238
243
|
|
|
239
244
|
interface AgentConfig {
|
|
240
245
|
port: number;
|
|
241
246
|
command: string;
|
|
242
|
-
webSocketUrl: string;
|
|
243
247
|
sessionSupport: SessionSupportType;
|
|
244
248
|
}
|
|
245
249
|
|
|
@@ -247,25 +251,21 @@ const AGENT_CONFIG: Record<ExternalAgentId, AgentConfig> = {
|
|
|
247
251
|
claude: {
|
|
248
252
|
port: 3017,
|
|
249
253
|
command: "npx @zed-industries/claude-code-acp",
|
|
250
|
-
webSocketUrl: "ws://localhost:3017/message",
|
|
251
254
|
sessionSupport: "single",
|
|
252
255
|
},
|
|
253
256
|
gemini: {
|
|
254
257
|
port: 3019,
|
|
255
258
|
command: "npx @google/gemini-cli --experimental-acp",
|
|
256
|
-
webSocketUrl: "ws://localhost:3019/message",
|
|
257
259
|
sessionSupport: "single",
|
|
258
260
|
},
|
|
259
261
|
codex: {
|
|
260
262
|
port: 3021,
|
|
261
263
|
command: "npx @zed-industries/codex-acp",
|
|
262
|
-
webSocketUrl: "ws://localhost:3021/message",
|
|
263
264
|
sessionSupport: "single",
|
|
264
265
|
},
|
|
265
266
|
opencode: {
|
|
266
267
|
port: 3023,
|
|
267
268
|
command: "npx opencode-ai acp",
|
|
268
|
-
webSocketUrl: "ws://localhost:3023/message",
|
|
269
269
|
sessionSupport: "single",
|
|
270
270
|
},
|
|
271
271
|
};
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import type { FileUIPart } from "ai";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
AtSignIcon,
|
|
6
|
+
FileIcon,
|
|
7
|
+
FileTextIcon,
|
|
8
|
+
ImageIcon,
|
|
9
|
+
PaperclipIcon,
|
|
10
|
+
SendHorizontalIcon,
|
|
11
|
+
StopCircleIcon,
|
|
12
|
+
XIcon,
|
|
13
|
+
} from "lucide-react";
|
|
5
14
|
import { useState } from "react";
|
|
6
15
|
import { cn } from "@/utils/cn";
|
|
16
|
+
import { Spinner } from "../icons/spinner";
|
|
17
|
+
import { Button } from "../ui/button";
|
|
18
|
+
import { Input } from "../ui/input";
|
|
19
|
+
import { Tooltip } from "../ui/tooltip";
|
|
20
|
+
import { SUPPORTED_ATTACHMENT_TYPES } from "./chat-utils";
|
|
7
21
|
|
|
8
22
|
export const AttachmentRenderer = ({
|
|
9
23
|
attachment,
|
|
@@ -58,6 +72,105 @@ export const FileAttachmentPill = ({
|
|
|
58
72
|
);
|
|
59
73
|
};
|
|
60
74
|
|
|
75
|
+
export const SendButton = ({
|
|
76
|
+
isLoading,
|
|
77
|
+
onStop,
|
|
78
|
+
onSendClick,
|
|
79
|
+
isEmpty,
|
|
80
|
+
showStopLabel = false, // Show a stop label and spinner instead of just the stop icon when loading
|
|
81
|
+
}: {
|
|
82
|
+
isLoading: boolean;
|
|
83
|
+
onStop: () => void;
|
|
84
|
+
onSendClick: () => void;
|
|
85
|
+
isEmpty: boolean;
|
|
86
|
+
showStopLabel?: boolean;
|
|
87
|
+
}) => {
|
|
88
|
+
const loadingContent = showStopLabel ? (
|
|
89
|
+
<div className="flex flex-row items-center gap-1 px-1.5">
|
|
90
|
+
<span className="text-xs text-error">Stop</span>
|
|
91
|
+
<Spinner size="small" />
|
|
92
|
+
</div>
|
|
93
|
+
) : (
|
|
94
|
+
<StopCircleIcon className="size-4 text-error" />
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<Tooltip content={isLoading ? "Stop" : "Submit"}>
|
|
99
|
+
<Button
|
|
100
|
+
variant="text"
|
|
101
|
+
size="sm"
|
|
102
|
+
className="h-6 min-w-6 p-0 hover:bg-muted/30 cursor-pointer"
|
|
103
|
+
onClick={isLoading ? onStop : onSendClick}
|
|
104
|
+
disabled={isLoading ? false : isEmpty}
|
|
105
|
+
>
|
|
106
|
+
{isLoading ? (
|
|
107
|
+
loadingContent
|
|
108
|
+
) : (
|
|
109
|
+
<SendHorizontalIcon className="h-3.5 w-3.5" />
|
|
110
|
+
)}
|
|
111
|
+
</Button>
|
|
112
|
+
</Tooltip>
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export const AddContextButton = ({
|
|
117
|
+
handleAddContext,
|
|
118
|
+
isLoading,
|
|
119
|
+
}: {
|
|
120
|
+
handleAddContext: () => void;
|
|
121
|
+
isLoading: boolean;
|
|
122
|
+
}) => {
|
|
123
|
+
return (
|
|
124
|
+
<Tooltip content="Add context">
|
|
125
|
+
<Button
|
|
126
|
+
variant="text"
|
|
127
|
+
size="icon"
|
|
128
|
+
onClick={handleAddContext}
|
|
129
|
+
disabled={isLoading}
|
|
130
|
+
>
|
|
131
|
+
<AtSignIcon className="h-3.5 w-3.5" />
|
|
132
|
+
</Button>
|
|
133
|
+
</Tooltip>
|
|
134
|
+
);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export const AttachFileButton = ({
|
|
138
|
+
fileInputRef,
|
|
139
|
+
isLoading,
|
|
140
|
+
onAddFiles,
|
|
141
|
+
}: {
|
|
142
|
+
fileInputRef: React.RefObject<HTMLInputElement | null>;
|
|
143
|
+
isLoading: boolean;
|
|
144
|
+
onAddFiles: (files: File[]) => void;
|
|
145
|
+
}) => {
|
|
146
|
+
return (
|
|
147
|
+
<>
|
|
148
|
+
<Tooltip content="Attach a file">
|
|
149
|
+
<Button
|
|
150
|
+
variant="text"
|
|
151
|
+
size="icon"
|
|
152
|
+
onClick={() => fileInputRef.current?.click()}
|
|
153
|
+
disabled={isLoading}
|
|
154
|
+
>
|
|
155
|
+
<PaperclipIcon className="h-3.5 w-3.5" />
|
|
156
|
+
</Button>
|
|
157
|
+
</Tooltip>
|
|
158
|
+
<Input
|
|
159
|
+
ref={fileInputRef}
|
|
160
|
+
type="file"
|
|
161
|
+
multiple={true}
|
|
162
|
+
hidden={true}
|
|
163
|
+
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
164
|
+
if (event.target.files) {
|
|
165
|
+
onAddFiles([...event.target.files]);
|
|
166
|
+
}
|
|
167
|
+
}}
|
|
168
|
+
accept={SUPPORTED_ATTACHMENT_TYPES.join(",")}
|
|
169
|
+
/>
|
|
170
|
+
</>
|
|
171
|
+
);
|
|
172
|
+
};
|
|
173
|
+
|
|
61
174
|
function renderFileIcon(file: File): React.ReactNode {
|
|
62
175
|
const classNames = "h-3 w-3 mt-0.5";
|
|
63
176
|
|