@marimo-team/islands 0.15.1 → 0.15.3
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-DIy_POzQ.js → ConnectedDataExplorerComponent-DfvW3rBn.js} +323 -328
- package/dist/{ImageComparisonComponent-4ehfWTqN.js → ImageComparisonComponent-XaJshw7d.js} +13 -13
- package/dist/{_baseUniq-Duh9chhg.js → _baseUniq-dN9WKF9m.js} +67 -67
- package/dist/any-language-editor-CpFniVi-.js +27 -0
- package/dist/{arc-BXrety1g.js → arc-BOhn-m2C.js} +1 -1
- package/dist/{architectureDiagram-KFL7JDKH-3xVup6Z2.js → architectureDiagram-W76B3OCA-Bpg85ZKv.js} +144 -144
- package/dist/assets/{worker-COGufAQn.js → worker-Y-Q4G-N2.js} +30 -26
- package/dist/asterisk-DS281yxp.js +271 -0
- package/dist/{blockDiagram-ZYB65J3Q-eEZ6LTIH.js → blockDiagram-QIGZ2CNN-DS1kOHlW.js} +10 -10
- package/dist/{c4Diagram-AAMF2YG6-BqjOo55d.js → c4Diagram-FPNF74CW-CyRVKssw.js} +8 -8
- package/dist/{channel-BkhHQVue.js → channel-BilGXox7.js} +1 -1
- package/dist/{chunk-ANTBXLJU-BkLYh6ot.js → chunk-4BX2VUAB-CZR39zCO.js} +1 -1
- package/dist/{chunk-WVR4S24B-DpdvazVp.js → chunk-55IACEB6-BIH-MYov.js} +1 -1
- package/dist/{chunk-GLLZNHP4-BGaltx6Q.js → chunk-FMBD7UC4-4PZXFZE8.js} +1 -1
- package/dist/{chunk-JBRWN2VN-BZ3JgjiU.js → chunk-K7UQS3LO-CEvWKznk.js} +117 -117
- package/dist/{chunk-NRVI72HA-XO3jKXGr.js → chunk-QN33PNHL-D5LO5Jq_.js} +1 -1
- package/dist/{chunk-FHKO5MBM-BqvR49qe.js → chunk-QZHKN3VN-6gwUonWI.js} +1 -1
- package/dist/{chunk-LXBSTHXV-CJgOmuuc.js → chunk-TVAH2DTR-3gm06QdU.js} +7 -7
- package/dist/{chunk-OMD6QJNC-1rwXYaVn.js → chunk-TZMSLE5B-Cm8Iy9bO.js} +1 -1
- package/dist/{classDiagram-v2-QTMF73CY-_BeLc0pY.js → classDiagram-KNZD7YFC-DC529O_z.js} +2 -2
- package/dist/{classDiagram-3BZAVTQC-_BeLc0pY.js → classDiagram-v2-RKCZMP56-DC529O_z.js} +2 -2
- package/dist/{clone-DhXjmfNH.js → clone-CLoRX3j6.js} +1 -1
- package/dist/cose-bilkent-S5V4N54A-qf5DlS6Y.js +2609 -0
- package/dist/{cytoscape.esm-BYnVVhJX.js → cytoscape.esm-DfdJODL8.js} +34 -34
- package/dist/{dagre-2BBEFEWP-DoebA2zc.js → dagre-5GWH7T2D-Ceocls0m.js} +6 -6
- package/dist/{data-grid-overlay-editor-DYmc5v9I.js → data-grid-overlay-editor-AqDS_UKe.js} +11 -11
- package/dist/{diagram-4IRLE6MV-CxnJ439S.js → diagram-N5W7TBWH-CP66oSiv.js} +59 -60
- package/dist/{diagram-RP2FKANI-C-v51IXB.js → diagram-QEK2KX5R-_YD4kxxi.js} +15 -15
- package/dist/{diagram-GUPCWM2R-B7MLfHE7.js → diagram-S2PKOQOG-Cnj8T-OP.js} +10 -10
- package/dist/dockerfile-Cm8cRYCN.js +194 -0
- package/dist/ebnf-DUPDuY4r.js +78 -0
- package/dist/{erDiagram-HZWUO2LU-Cv1Slpwd.js → erDiagram-AWTI2OKA-CGnvoHx6.js} +8 -8
- package/dist/fcl-CPC2WYrI.js +103 -0
- package/dist/{flowDiagram-THRYKUMA-CnjAkcKg.js → flowDiagram-PVAE7QVJ-DG-pr9R9.js} +9 -9
- package/dist/{ganttDiagram-WV7ZQ7D5-CRQQ5cqP.js → ganttDiagram-OWAHRB6G-JmChtxvn.js} +34 -34
- package/dist/{gitGraphDiagram-OJR772UL-a7Wl_pP8.js → gitGraphDiagram-NY62KEGX-D8wLfOPd.js} +4 -4
- package/dist/{glide-data-editor-DrSTYUHP.js → glide-data-editor-9nC3iCIZ.js} +33 -33
- package/dist/{graph-Dq4lx1WI.js → graph-CoRe7vAN.js} +3 -3
- package/dist/http-D9LttvKF.js +44 -0
- package/dist/{index-B_t2cVfJ.js → index-6qYeHHjQ.js} +33090 -32892
- package/dist/{index-BhnWrXVh.js → index-BpzLh4Qe.js} +7711 -7711
- package/dist/{index-DSAnCCyV.js → index-BthgsgYX.js} +6 -6
- package/dist/{index-pBmAzQJl.js → index-MCx5v1x0.js} +2 -2
- package/dist/index-jkm77Jrz.js +98 -0
- package/dist/{infoDiagram-6WOFNB3A-B4pr_cke.js → infoDiagram-STP46IZ2-BlXxvOrR.js} +2 -2
- package/dist/{journeyDiagram-FFXJYRFH-CF8H9tcV.js → journeyDiagram-BIP6EPQ6-CNRYs_Fc.js} +24 -26
- package/dist/{kanban-definition-KOZQBZVT-BYfBCo4W.js → kanban-definition-6OIFK2YF-B9HeMAuP.js} +14 -14
- package/dist/{layout-D8_YOjKz.js → layout-m2vOUiW1.js} +81 -81
- package/dist/{linear-Be5SurQB.js → linear-DU6Q5CX3.js} +35 -35
- package/dist/{main-8IC_V2L6.js → main-BD2KGFpU.js} +74594 -68034
- package/dist/main.js +1 -1
- package/dist/{mermaid-B4v-qVXz.js → mermaid-HVCtvbyx.js} +6160 -7493
- package/dist/min-DcGMA4e_.js +80 -0
- package/dist/mindmap-definition-Q6HEUPPD-BW8UmIDQ.js +785 -0
- package/dist/nginx-zDPm3Z74.js +89 -0
- package/dist/{number-overlay-editor-XASk1ikZ.js → number-overlay-editor-D8Hl0Syo.js} +19 -19
- package/dist/{pieDiagram-DBDJKBY4-DhPX65dy.js → pieDiagram-ADFJNKIX-Bg-3zg5U.js} +17 -17
- package/dist/{quadrantDiagram-YPSRARAO-BjPa8bg5.js → quadrantDiagram-LMRXKWRM-BO4IG6Yz.js} +6 -6
- package/dist/{react-plotly-C_6SNkG9.js → react-plotly-dkvHVuRb.js} +3577 -3577
- package/dist/{requirementDiagram-EGVEC5DT-CtN_U9bI.js → requirementDiagram-4UW4RH46-5sdTguSM.js} +7 -7
- package/dist/{sankeyDiagram-HRAUVNP4-DVi73SZP.js → sankeyDiagram-GR3RE2ED-Buhlv9OI.js} +5 -5
- package/dist/sequenceDiagram-C3RYC4MD-C3qsM2UP.js +2519 -0
- package/dist/{slides-component-ML7vxRcD.js → slides-component-D209A0-s.js} +66 -66
- package/dist/solr-BNlsLglM.js +41 -0
- package/dist/spreadsheet-C-cy4P5N.js +49 -0
- package/dist/{stateDiagram-UUKSUZ4H-qZ62tNIz.js → stateDiagram-KXAO66HF-CopJ7G6P.js} +5 -5
- package/dist/{stateDiagram-v2-EYPG3UTE-BZEyTMgl.js → stateDiagram-v2-UMBNRL4Z-CejL8AKf.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-CZ2vTSO2.js → time-BwSBitlN.js} +58 -58
- package/dist/{timeline-definition-3HZDQTIS-DbWMwd1x.js → timeline-definition-XQNQX7LJ-DzMNTX-C.js} +10 -12
- package/dist/{timer-BYwnU4DF.js → timer-B0-z63CM.js} +16 -16
- package/dist/{treemap-75Q7IDZK-CocR-oAZ.js → treemap-75Q7IDZK-zeJG07dk.js} +14 -14
- package/dist/{vega-component-BrYek_kz.js → vega-component-CUkiTayd.js} +30 -30
- package/dist/{xychartDiagram-FDP5SA34-CYiUdiy5.js → xychartDiagram-6GGTOJPD-DiENNXMS.js} +7 -7
- package/package.json +39 -39
- 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/app-config/ai-config.tsx +7 -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 +5 -5
- 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/wrapper/app-chrome.tsx +38 -28
- 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/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/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/__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-Cvakxnzg.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-CfrpOVe5.js +0 -341
- package/dist/index-DIFrY2JV.js +0 -288
- package/dist/javascript-C2yteZeJ.js +0 -691
- package/dist/min-Q4QXsXWR.js +0 -80
- package/dist/mindmap-definition-LNHGMQRG-CebaDS3t.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-C8jImRwI.js +0 -2284
- package/dist/ttcn-cfg-Bac_acMi.js +0 -88
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import type { FileUIPart, UIMessage } from "ai";
|
|
4
|
+
import { blobToString } from "@/utils/fileToBase64";
|
|
5
|
+
|
|
6
|
+
export function generateChatTitle(message: string): string {
|
|
7
|
+
return message.length > 50 ? `${message.slice(0, 50)}...` : message;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function convertToFileUIPart(
|
|
11
|
+
files: File[],
|
|
12
|
+
): Promise<FileUIPart[]> {
|
|
13
|
+
const fileUIParts = await Promise.all(
|
|
14
|
+
files.map(async (file) => {
|
|
15
|
+
const part: FileUIPart = {
|
|
16
|
+
type: "file" as const,
|
|
17
|
+
mediaType: file.type,
|
|
18
|
+
filename: file.name,
|
|
19
|
+
url: await blobToString(file, "dataUrl"),
|
|
20
|
+
};
|
|
21
|
+
return part;
|
|
22
|
+
}),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
return fileUIParts;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function isLastMessageReasoning(messages: UIMessage[]): boolean {
|
|
29
|
+
if (messages.length === 0) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const lastMessage = messages.at(-1);
|
|
34
|
+
if (!lastMessage) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (lastMessage.role !== "assistant" || !lastMessage.parts) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const parts = lastMessage.parts;
|
|
43
|
+
if (parts.length === 0) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Check if the last part is reasoning
|
|
48
|
+
const lastPart = parts[parts.length - 1];
|
|
49
|
+
return lastPart.type === "reasoning";
|
|
50
|
+
}
|
|
@@ -172,21 +172,17 @@ const CopyButton: React.FC<ButtonProps> = ({ onClick, ...props }) => {
|
|
|
172
172
|
};
|
|
173
173
|
|
|
174
174
|
const COMPONENTS: Components = {
|
|
175
|
-
code: ({ children, className
|
|
175
|
+
code: ({ children, className }) => {
|
|
176
176
|
const language = className?.replace("language-", "");
|
|
177
177
|
if (language && typeof children === "string") {
|
|
178
178
|
return (
|
|
179
|
-
<div
|
|
179
|
+
<div>
|
|
180
180
|
<div className="text-xs text-muted-foreground pl-1">{language}</div>
|
|
181
181
|
<CodeBlock code={children.trim()} language={language} />
|
|
182
182
|
</div>
|
|
183
183
|
);
|
|
184
184
|
}
|
|
185
|
-
return
|
|
186
|
-
<code key={key} className={className}>
|
|
187
|
-
{children}
|
|
188
|
-
</code>
|
|
189
|
-
);
|
|
185
|
+
return <code className={className}>{children}</code>;
|
|
190
186
|
},
|
|
191
187
|
};
|
|
192
188
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
+
import type { ToolUIPart } from "ai";
|
|
3
4
|
import {
|
|
4
5
|
CheckCircleIcon,
|
|
5
6
|
Loader2,
|
|
@@ -17,10 +18,10 @@ import { cn } from "@/utils/cn";
|
|
|
17
18
|
|
|
18
19
|
interface ToolCallAccordionProps {
|
|
19
20
|
toolName: string;
|
|
20
|
-
result
|
|
21
|
+
result: unknown;
|
|
21
22
|
error?: string;
|
|
22
23
|
index?: number;
|
|
23
|
-
state?: "
|
|
24
|
+
state?: ToolUIPart["state"];
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export const ToolCallAccordion: React.FC<ToolCallAccordionProps> = ({
|
|
@@ -30,7 +31,7 @@ export const ToolCallAccordion: React.FC<ToolCallAccordionProps> = ({
|
|
|
30
31
|
index = 0,
|
|
31
32
|
state,
|
|
32
33
|
}) => {
|
|
33
|
-
const hasResult = state === "
|
|
34
|
+
const hasResult = state === "output-available" && (result || error);
|
|
34
35
|
const status = error ? "error" : hasResult ? "success" : "loading";
|
|
35
36
|
|
|
36
37
|
const getStatusIcon = () => {
|
|
@@ -84,8 +85,7 @@ export const ToolCallAccordion: React.FC<ToolCallAccordionProps> = ({
|
|
|
84
85
|
{/* Only show content when tool is complete */}
|
|
85
86
|
{hasResult && (
|
|
86
87
|
<div className="space-y-3">
|
|
87
|
-
{
|
|
88
|
-
{result && (
|
|
88
|
+
{result !== undefined && result !== null && (
|
|
89
89
|
<div>
|
|
90
90
|
<div className="text-xs font-medium text-muted-foreground mt-2 mb-1">
|
|
91
91
|
Result:
|
|
@@ -13,6 +13,12 @@ describe("sqlCode", () => {
|
|
|
13
13
|
source: "local",
|
|
14
14
|
source_type: "local",
|
|
15
15
|
type: "table",
|
|
16
|
+
engine: null,
|
|
17
|
+
indexes: null,
|
|
18
|
+
num_columns: null,
|
|
19
|
+
num_rows: null,
|
|
20
|
+
variable_name: null,
|
|
21
|
+
primary_keys: null,
|
|
16
22
|
};
|
|
17
23
|
const mockColumn = {
|
|
18
24
|
name: "email" as const,
|
|
@@ -173,9 +173,7 @@ export function renderPreviewError({
|
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
export function renderStats(
|
|
176
|
-
stats: Partial<
|
|
177
|
-
Record<ColumnHeaderStatsKey, string | number | boolean | null | undefined>
|
|
178
|
-
>,
|
|
176
|
+
stats: Partial<Record<ColumnHeaderStatsKey, unknown>>,
|
|
179
177
|
dataType: DataType,
|
|
180
178
|
) {
|
|
181
179
|
return (
|
|
@@ -73,8 +73,8 @@ import { newNotebookURL } from "@/utils/urls";
|
|
|
73
73
|
import { useRunAllCells } from "../cell/useRunCells";
|
|
74
74
|
import { useChromeActions, useChromeState } from "../chrome/state";
|
|
75
75
|
import { PANELS } from "../chrome/types";
|
|
76
|
-
import { commandPaletteAtom } from "../controls/command-palette";
|
|
77
76
|
import { keyboardShortcutsAtom } from "../controls/keyboard-shortcuts";
|
|
77
|
+
import { commandPaletteAtom } from "../controls/state";
|
|
78
78
|
import { AddDatabaseDialogContent } from "../database/add-database-form";
|
|
79
79
|
import { displayLayoutName, getLayoutIcon } from "../renderers/layout-select";
|
|
80
80
|
import { LAYOUT_TYPES } from "../renderers/types";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
+
import { useCompletion } from "@ai-sdk/react";
|
|
3
4
|
import {
|
|
4
5
|
autocompletion,
|
|
5
6
|
type Completion,
|
|
@@ -16,8 +17,7 @@ import ReactCodeMirror, {
|
|
|
16
17
|
minimalSetup,
|
|
17
18
|
type ReactCodeMirrorRef,
|
|
18
19
|
} from "@uiw/react-codemirror";
|
|
19
|
-
import {
|
|
20
|
-
import { useAtom, useAtomValue, useStore } from "jotai";
|
|
20
|
+
import { useAtom, useStore } from "jotai";
|
|
21
21
|
import { atomWithStorage } from "jotai/utils";
|
|
22
22
|
import {
|
|
23
23
|
ChevronsUpDown,
|
|
@@ -40,12 +40,9 @@ import {
|
|
|
40
40
|
DropdownMenuTrigger,
|
|
41
41
|
} from "@/components/ui/dropdown-menu";
|
|
42
42
|
import { toast } from "@/components/ui/use-toast";
|
|
43
|
-
import { useModelChange } from "@/core/ai/config";
|
|
44
43
|
import { resourceExtension } from "@/core/codemirror/ai/resources";
|
|
45
44
|
import { customPythonLanguageSupport } from "@/core/codemirror/language/languages/python";
|
|
46
45
|
import { SQLLanguageAdapter } from "@/core/codemirror/language/languages/sql/sql";
|
|
47
|
-
import { aiAtom } from "@/core/config/config";
|
|
48
|
-
import { DEFAULT_AI_MODEL } from "@/core/config/config-schema";
|
|
49
46
|
import { useRuntimeManager } from "@/core/runtime/config";
|
|
50
47
|
import { useTheme } from "@/theme/useTheme";
|
|
51
48
|
import { cn } from "@/utils/cn";
|
|
@@ -58,6 +55,7 @@ import {
|
|
|
58
55
|
createAiCompletionOnKeydown,
|
|
59
56
|
} from "./completion-handlers";
|
|
60
57
|
import {
|
|
58
|
+
CONTEXT_TRIGGER,
|
|
61
59
|
getAICompletionBody,
|
|
62
60
|
mentionsCompletionSource,
|
|
63
61
|
} from "./completion-utils";
|
|
@@ -90,9 +88,6 @@ export const AddCellWithAI: React.FC<{
|
|
|
90
88
|
const { theme } = useTheme();
|
|
91
89
|
const runtimeManager = useRuntimeManager();
|
|
92
90
|
|
|
93
|
-
const ai = useAtomValue(aiAtom);
|
|
94
|
-
const editModel = ai?.models?.edit_model || DEFAULT_AI_MODEL;
|
|
95
|
-
const { saveModelChange } = useModelChange();
|
|
96
91
|
const inputRef = useRef<ReactCodeMirrorRef>(null);
|
|
97
92
|
|
|
98
93
|
const {
|
|
@@ -261,10 +256,6 @@ export const AddCellWithAI: React.FC<{
|
|
|
261
256
|
<div className="ml-auto flex items-center gap-1">
|
|
262
257
|
{languageDropdown}
|
|
263
258
|
<AIModelDropdown
|
|
264
|
-
value={editModel}
|
|
265
|
-
onSelect={(model) => {
|
|
266
|
-
saveModelChange(model, "edit");
|
|
267
|
-
}}
|
|
268
259
|
triggerClassName="h-7 text-xs max-w-64"
|
|
269
260
|
iconSize="small"
|
|
270
261
|
forRole="edit"
|
|
@@ -301,6 +292,7 @@ interface PromptInputProps {
|
|
|
301
292
|
onSubmit: (e: KeyboardEvent | undefined, value: string) => void;
|
|
302
293
|
additionalCompletions?: AdditionalCompletions;
|
|
303
294
|
maxHeight?: string;
|
|
295
|
+
onAddFiles?: (files: File[]) => void;
|
|
304
296
|
}
|
|
305
297
|
|
|
306
298
|
/**
|
|
@@ -318,6 +310,7 @@ export const PromptInput = ({
|
|
|
318
310
|
onSubmit,
|
|
319
311
|
onKeyDown,
|
|
320
312
|
onClose,
|
|
313
|
+
onAddFiles,
|
|
321
314
|
additionalCompletions,
|
|
322
315
|
maxHeight,
|
|
323
316
|
}: PromptInputProps) => {
|
|
@@ -346,7 +339,11 @@ export const PromptInput = ({
|
|
|
346
339
|
return [
|
|
347
340
|
autocompletion({}),
|
|
348
341
|
markdownLanguage,
|
|
349
|
-
resourceExtension(
|
|
342
|
+
resourceExtension({
|
|
343
|
+
language: markdownLanguage.language,
|
|
344
|
+
store,
|
|
345
|
+
onAddFiles,
|
|
346
|
+
}),
|
|
350
347
|
markdownLanguage.language.data.of({
|
|
351
348
|
autocomplete: additionalCompletionsSource,
|
|
352
349
|
}),
|
|
@@ -411,7 +408,13 @@ export const PromptInput = ({
|
|
|
411
408
|
},
|
|
412
409
|
]),
|
|
413
410
|
];
|
|
414
|
-
}, [
|
|
411
|
+
}, [
|
|
412
|
+
store,
|
|
413
|
+
onAddFiles,
|
|
414
|
+
additionalCompletionsSource,
|
|
415
|
+
handleSubmit,
|
|
416
|
+
handleEscape,
|
|
417
|
+
]);
|
|
415
418
|
|
|
416
419
|
return (
|
|
417
420
|
<ReactCodeMirror
|
|
@@ -425,7 +428,9 @@ export const PromptInput = ({
|
|
|
425
428
|
onChange={onChange}
|
|
426
429
|
onKeyDown={onKeyDown}
|
|
427
430
|
theme={theme === "dark" ? "dark" : "light"}
|
|
428
|
-
placeholder={
|
|
431
|
+
placeholder={
|
|
432
|
+
placeholder || `Generate with AI, ${CONTEXT_TRIGGER} to include context`
|
|
433
|
+
}
|
|
429
434
|
/>
|
|
430
435
|
);
|
|
431
436
|
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useCompletion } from "@ai-sdk/react";
|
|
4
4
|
import { EditorView } from "@codemirror/view";
|
|
5
|
-
import { Loader2Icon, SparklesIcon, XIcon } from "lucide-react";
|
|
5
|
+
import { AtSignIcon, Loader2Icon, SparklesIcon, XIcon } from "lucide-react";
|
|
6
6
|
import React, { useEffect, useId, useState } from "react";
|
|
7
7
|
import CodeMirrorMerge from "react-codemirror-merge";
|
|
8
8
|
import { Button } from "@/components/ui/button";
|
|
@@ -12,6 +12,7 @@ import "./merge-editor.css";
|
|
|
12
12
|
import { storePrompt } from "@marimo-team/codemirror-ai";
|
|
13
13
|
import type { ReactCodeMirrorRef } from "@uiw/react-codemirror";
|
|
14
14
|
import { useAtom } from "jotai";
|
|
15
|
+
import { AIModelDropdown } from "@/components/ai/ai-model-dropdown";
|
|
15
16
|
import { Checkbox } from "@/components/ui/checkbox";
|
|
16
17
|
import { Label } from "@/components/ui/label";
|
|
17
18
|
import { Tooltip } from "@/components/ui/tooltip";
|
|
@@ -30,7 +31,7 @@ import {
|
|
|
30
31
|
CompletionActions,
|
|
31
32
|
createAiCompletionOnKeydown,
|
|
32
33
|
} from "./completion-handlers";
|
|
33
|
-
import { getAICompletionBody } from "./completion-utils";
|
|
34
|
+
import { addContextCompletion, getAICompletionBody } from "./completion-utils";
|
|
34
35
|
|
|
35
36
|
const Original = CodeMirrorMerge.Original;
|
|
36
37
|
const Modified = CodeMirrorMerge.Modified;
|
|
@@ -164,7 +165,7 @@ export const AiCompletionEditor: React.FC<Props> = ({
|
|
|
164
165
|
<SparklesIcon className="text-(--blue-10) shrink-0" size={16} />
|
|
165
166
|
<PromptInput
|
|
166
167
|
inputRef={inputRef}
|
|
167
|
-
className="h-full my-0 py-
|
|
168
|
+
className="h-full my-0 py-2"
|
|
168
169
|
onClose={() => {
|
|
169
170
|
declineChange();
|
|
170
171
|
setCompletion("");
|
|
@@ -209,6 +210,24 @@ export const AiCompletionEditor: React.FC<Props> = ({
|
|
|
209
210
|
size="xs"
|
|
210
211
|
/>
|
|
211
212
|
)}
|
|
213
|
+
<div className="flex flex-row items-center gap-0.5 -ml-1.5 -mr-2">
|
|
214
|
+
<Tooltip content="Add context">
|
|
215
|
+
<Button
|
|
216
|
+
variant="text"
|
|
217
|
+
size="icon"
|
|
218
|
+
onClick={() => addContextCompletion(inputRef)}
|
|
219
|
+
>
|
|
220
|
+
<AtSignIcon className="h-3 w-3" />
|
|
221
|
+
</Button>
|
|
222
|
+
</Tooltip>
|
|
223
|
+
<AIModelDropdown
|
|
224
|
+
triggerClassName="h-7"
|
|
225
|
+
iconSize="small"
|
|
226
|
+
displayIconOnly={true}
|
|
227
|
+
forRole="edit"
|
|
228
|
+
/>
|
|
229
|
+
</div>
|
|
230
|
+
|
|
212
231
|
<div className="h-full w-px bg-border mx-2" />
|
|
213
232
|
<Tooltip content="Include code from other cells">
|
|
214
233
|
<div className="flex flex-row items-start gap-1 overflow-hidden">
|
|
@@ -25,10 +25,8 @@ export const createAiCompletionOnKeydown = (opts: {
|
|
|
25
25
|
const metaKey = isPlatformMac() ? e.metaKey : e.ctrlKey;
|
|
26
26
|
|
|
27
27
|
// Mod+Enter should accept the completion, if there is one
|
|
28
|
-
if (metaKey && e.key === "Enter") {
|
|
29
|
-
|
|
30
|
-
handleAcceptCompletion();
|
|
31
|
-
}
|
|
28
|
+
if (metaKey && e.key === "Enter" && !isLoading && completion) {
|
|
29
|
+
handleAcceptCompletion();
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
// Mod+Shift+Delete should decline the completion
|
|
@@ -1,28 +1,41 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
Completion,
|
|
5
|
-
CompletionContext,
|
|
6
|
-
CompletionSource,
|
|
3
|
+
import {
|
|
4
|
+
type Completion,
|
|
5
|
+
type CompletionContext,
|
|
6
|
+
type CompletionSource,
|
|
7
|
+
startCompletion,
|
|
7
8
|
} from "@codemirror/autocomplete";
|
|
9
|
+
import type { ReactCodeMirrorRef } from "@uiw/react-codemirror";
|
|
10
|
+
import type { FileUIPart } from "ai";
|
|
8
11
|
import { getAIContextRegistry } from "@/core/ai/context/context";
|
|
9
12
|
import { getCodes } from "@/core/codemirror/copilot/getCodes";
|
|
10
13
|
import type { AiCompletionRequest } from "@/core/network/types";
|
|
11
14
|
import { store } from "@/core/state/jotai";
|
|
12
15
|
import { Logger } from "@/utils/Logger";
|
|
13
16
|
|
|
17
|
+
export const CONTEXT_TRIGGER = "@";
|
|
18
|
+
|
|
19
|
+
interface Opts {
|
|
20
|
+
input: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface AICompletionBodyWithAttachments {
|
|
24
|
+
body: Omit<AiCompletionRequest, "language" | "prompt" | "code">;
|
|
25
|
+
attachments: FileUIPart[];
|
|
26
|
+
}
|
|
27
|
+
|
|
14
28
|
/**
|
|
15
29
|
* Gets the request body for the AI completion API.
|
|
16
30
|
*/
|
|
17
31
|
export function getAICompletionBody({
|
|
18
32
|
input,
|
|
19
|
-
}: {
|
|
20
|
-
input: string;
|
|
21
|
-
}): Omit<AiCompletionRequest, "language" | "prompt" | "code"> {
|
|
33
|
+
}: Opts): Omit<AiCompletionRequest, "language" | "prompt" | "code"> {
|
|
22
34
|
let contextString = "";
|
|
35
|
+
|
|
23
36
|
// Skip if no '@' in the input
|
|
24
37
|
if (input.includes("@")) {
|
|
25
|
-
contextString =
|
|
38
|
+
contextString = extractTaggedContext(input);
|
|
26
39
|
Logger.debug("Included context", contextString);
|
|
27
40
|
}
|
|
28
41
|
|
|
@@ -37,11 +50,49 @@ export function getAICompletionBody({
|
|
|
37
50
|
}
|
|
38
51
|
|
|
39
52
|
/**
|
|
40
|
-
*
|
|
53
|
+
* Gets the request body and attachments for the AI completion API.
|
|
54
|
+
*/
|
|
55
|
+
export async function getAICompletionBodyWithAttachments({
|
|
56
|
+
input,
|
|
57
|
+
}: Opts): Promise<AICompletionBodyWithAttachments> {
|
|
58
|
+
let contextString = "";
|
|
59
|
+
let attachments: FileUIPart[] = [];
|
|
60
|
+
|
|
61
|
+
// Skip if no '@' in the input
|
|
62
|
+
if (input.includes("@")) {
|
|
63
|
+
const registry = getAIContextRegistry(store);
|
|
64
|
+
const contextIds = registry.parseAllContextIds(input);
|
|
65
|
+
|
|
66
|
+
// Get context string
|
|
67
|
+
contextString = registry.formatContextForAI(contextIds);
|
|
68
|
+
|
|
69
|
+
// Get attachments
|
|
70
|
+
try {
|
|
71
|
+
attachments = await registry.getAttachmentsForContext(contextIds);
|
|
72
|
+
Logger.debug("Included attachments", attachments.length);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
Logger.error("Error getting attachments:", error);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
body: {
|
|
80
|
+
includeOtherCode: getCodes(""),
|
|
81
|
+
context: {
|
|
82
|
+
plainText: contextString,
|
|
83
|
+
schema: [],
|
|
84
|
+
variables: [],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
attachments,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Extracts datasets, variables and other context from the input.
|
|
41
93
|
* References are with @<name> in the input.
|
|
42
|
-
* Prioritizes datasets over variables if there's a name conflict.
|
|
43
94
|
*/
|
|
44
|
-
function
|
|
95
|
+
function extractTaggedContext(input: string): string {
|
|
45
96
|
const registry = getAIContextRegistry(store);
|
|
46
97
|
const contextIds = registry.parseAllContextIds(input);
|
|
47
98
|
return registry.formatContextForAI(contextIds);
|
|
@@ -71,3 +122,26 @@ export function mentionsCompletionSource(
|
|
|
71
122
|
};
|
|
72
123
|
};
|
|
73
124
|
}
|
|
125
|
+
|
|
126
|
+
export function addContextCompletion(
|
|
127
|
+
inputRef: React.RefObject<ReactCodeMirrorRef | null>,
|
|
128
|
+
) {
|
|
129
|
+
if (inputRef.current?.view) {
|
|
130
|
+
const pos = inputRef.current.view.state.selection.main.from;
|
|
131
|
+
// Insert @ at the cursor position
|
|
132
|
+
inputRef.current.view.dispatch({
|
|
133
|
+
changes: {
|
|
134
|
+
from: pos,
|
|
135
|
+
to: pos,
|
|
136
|
+
insert: CONTEXT_TRIGGER,
|
|
137
|
+
},
|
|
138
|
+
selection: {
|
|
139
|
+
anchor: pos + 1,
|
|
140
|
+
head: pos + 1,
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
inputRef.current.view.focus();
|
|
144
|
+
// Trigger completion
|
|
145
|
+
startCompletion(inputRef.current.view);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
+
import { BoxIcon, XIcon } from "lucide-react";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { useEvent } from "react-use-event-hook";
|
|
5
|
+
import { useAlertActions, useAlerts } from "@/core/alerts/state";
|
|
6
|
+
import { Banner } from "@/plugins/impl/common/error-banner";
|
|
7
|
+
import { Button } from "../../ui/button";
|
|
8
|
+
|
|
9
|
+
export const StartupLogsAlert: React.FC = () => {
|
|
10
|
+
const { startupLogsAlert } = useAlerts();
|
|
11
|
+
const { clearStartupLogsAlert } = useAlertActions();
|
|
12
|
+
const [hasCleared, setHasCleared] = useState(false);
|
|
13
|
+
const status = startupLogsAlert?.status;
|
|
14
|
+
|
|
15
|
+
const handleClear = useEvent(() => {
|
|
16
|
+
clearStartupLogsAlert();
|
|
17
|
+
setHasCleared(true);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const isDone = status === "done";
|
|
21
|
+
const isRunning = status === "start" || status === "append";
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
let timeout: number | undefined;
|
|
25
|
+
|
|
26
|
+
if (isDone) {
|
|
27
|
+
// Dismiss after 5 seconds
|
|
28
|
+
timeout = window.setTimeout(() => handleClear(), 5000);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return () => {
|
|
32
|
+
if (timeout) {
|
|
33
|
+
window.clearTimeout(timeout);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}, [isDone]);
|
|
37
|
+
|
|
38
|
+
if (startupLogsAlert === null || hasCleared) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className="flex flex-col gap-4 mb-5 fixed top-5 left-12 min-w-[400px] max-w-[600px] z-200 opacity-95">
|
|
44
|
+
<Banner
|
|
45
|
+
kind="info"
|
|
46
|
+
className="flex flex-col rounded py-3 px-5 animate-in slide-in-from-left"
|
|
47
|
+
>
|
|
48
|
+
<div className="flex justify-between">
|
|
49
|
+
<span className="font-bold text-lg flex items-center mb-2">
|
|
50
|
+
<BoxIcon className="w-5 h-5 inline-block mr-2" />
|
|
51
|
+
{isRunning ? "Initializing..." : "Initialized"}
|
|
52
|
+
</span>
|
|
53
|
+
<Button
|
|
54
|
+
variant="text"
|
|
55
|
+
data-testid="remove-startup-logs-button"
|
|
56
|
+
size="icon"
|
|
57
|
+
onClick={handleClear}
|
|
58
|
+
>
|
|
59
|
+
<XIcon className="w-5 h-5" />
|
|
60
|
+
</Button>
|
|
61
|
+
</div>
|
|
62
|
+
<div className="flex flex-col gap-4 justify-between items-start text-muted-foreground text-base">
|
|
63
|
+
<div className="w-full">
|
|
64
|
+
<pre className="bg-muted p-3 rounded text-sm font-mono overflow-auto max-h-64 whitespace-pre-wrap">
|
|
65
|
+
{startupLogsAlert.content || "Starting startup script..."}
|
|
66
|
+
</pre>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</Banner>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
import { DataSources } from "@/components/datasources/datasources";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
const DataSourcesPanel: React.FC = () => {
|
|
5
5
|
return <DataSources />;
|
|
6
6
|
};
|
|
7
|
+
|
|
8
|
+
export default DataSourcesPanel;
|
|
@@ -6,7 +6,7 @@ import { useVariables } from "@/core/variables/state";
|
|
|
6
6
|
import { cn } from "@/utils/cn";
|
|
7
7
|
import { DependencyGraph } from "../../../dependency-graph/dependency-graph";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const DependencyGraphPanel: React.FC = () => {
|
|
10
10
|
const variables = useVariables();
|
|
11
11
|
const cellIds = useCellIds();
|
|
12
12
|
const [cells] = useCellDataAtoms();
|
|
@@ -21,3 +21,5 @@ export const DependencyGraphPanel: React.FC = () => {
|
|
|
21
21
|
</div>
|
|
22
22
|
);
|
|
23
23
|
};
|
|
24
|
+
|
|
25
|
+
export default DependencyGraphPanel;
|
|
@@ -8,7 +8,7 @@ import "../../documentation.css";
|
|
|
8
8
|
import { TextSearchIcon } from "lucide-react";
|
|
9
9
|
import { PanelEmptyState } from "./empty-state";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const DocumentationPanel: React.FC = () => {
|
|
12
12
|
const { documentation } = useAtomValue(documentationAtom);
|
|
13
13
|
|
|
14
14
|
if (!documentation) {
|
|
@@ -27,3 +27,5 @@ export const DocumentationPanel: React.FC = () => {
|
|
|
27
27
|
</div>
|
|
28
28
|
);
|
|
29
29
|
};
|
|
30
|
+
|
|
31
|
+
export default DocumentationPanel;
|
|
@@ -7,7 +7,7 @@ import { useCellErrors } from "../../../../core/cells/cells";
|
|
|
7
7
|
import { MarimoErrorOutput } from "../../output/MarimoErrorOutput";
|
|
8
8
|
import { PanelEmptyState } from "./empty-state";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
const ErrorsPanel: React.FC = () => {
|
|
11
11
|
const errors = useCellErrors();
|
|
12
12
|
|
|
13
13
|
if (errors.length === 0) {
|
|
@@ -33,3 +33,5 @@ export const ErrorsPanel: React.FC = () => {
|
|
|
33
33
|
</div>
|
|
34
34
|
);
|
|
35
35
|
};
|
|
36
|
+
|
|
37
|
+
export default ErrorsPanel;
|
|
@@ -6,7 +6,7 @@ import { cn } from "@/utils/cn";
|
|
|
6
6
|
import { FileExplorer } from "../../file-tree/file-explorer";
|
|
7
7
|
import { useFileExplorerUpload } from "../../file-tree/upload";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const FileExplorerPanel: React.FC = () => {
|
|
10
10
|
const { ref, height = 1 } = useResizeObserver<HTMLDivElement>();
|
|
11
11
|
const { getRootProps, getInputProps, isDragActive } = useFileExplorerUpload({
|
|
12
12
|
noClick: true,
|
|
@@ -31,3 +31,5 @@ export const FileExplorerPanel: React.FC = () => {
|
|
|
31
31
|
</div>
|
|
32
32
|
);
|
|
33
33
|
};
|
|
34
|
+
|
|
35
|
+
export default FileExplorerPanel;
|
|
@@ -14,7 +14,7 @@ interface Props {
|
|
|
14
14
|
logs: CellLog[];
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
const LogsPanel: React.FC = () => {
|
|
18
18
|
const logs = useCellLogs();
|
|
19
19
|
const { clearLogs } = useCellActions();
|
|
20
20
|
|
|
@@ -46,6 +46,8 @@ export const LogsPanel: React.FC = () => {
|
|
|
46
46
|
);
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
+
export default LogsPanel;
|
|
50
|
+
|
|
49
51
|
export const LogViewer: React.FC<Props> = ({ logs, className }) => {
|
|
50
52
|
const hover = "opacity-70 group-hover:bg-(--gray-3) group-hover:opacity-100";
|
|
51
53
|
return (
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
useActiveOutline,
|
|
14
14
|
} from "./outline/useActiveOutline";
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
const OutlinePanel: React.FC = () => {
|
|
17
17
|
const { items } = useAtomValue(notebookOutline);
|
|
18
18
|
const headerElements = useMemo(() => findOutlineElements(items), [items]);
|
|
19
19
|
const { activeHeaderId, activeOccurrences } =
|
|
@@ -37,3 +37,5 @@ export const OutlinePanel: React.FC = () => {
|
|
|
37
37
|
/>
|
|
38
38
|
);
|
|
39
39
|
};
|
|
40
|
+
|
|
41
|
+
export default OutlinePanel;
|
|
@@ -65,7 +65,7 @@ const PackageActionButton: React.FC<{
|
|
|
65
65
|
);
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
const PackagesPanel: React.FC = () => {
|
|
69
69
|
const [config] = useResolvedMarimoConfig();
|
|
70
70
|
const packageManager = config.package_management.manager;
|
|
71
71
|
const { getDependencyTree, getPackageList } = useRequestClient();
|
|
@@ -162,6 +162,8 @@ export const PackagesPanel: React.FC = () => {
|
|
|
162
162
|
);
|
|
163
163
|
};
|
|
164
164
|
|
|
165
|
+
export default PackagesPanel;
|
|
166
|
+
|
|
165
167
|
const InstallPackageForm: React.FC<{
|
|
166
168
|
packageManager: string;
|
|
167
169
|
onSuccess: () => void;
|
|
@@ -411,7 +413,7 @@ const RemoveButton: React.FC<{
|
|
|
411
413
|
};
|
|
412
414
|
|
|
413
415
|
const DependencyTree: React.FC<{
|
|
414
|
-
tree
|
|
416
|
+
tree: DependencyTreeNode | null;
|
|
415
417
|
error?: Error | null;
|
|
416
418
|
onSuccess: () => void;
|
|
417
419
|
}> = ({ tree, error, onSuccess }) => {
|