Skip to content

Commit 464530f

Browse files
committed
frontend/jupyter/llm: add Assistant dialog to markdown cells
1 parent 177f37a commit 464530f

File tree

6 files changed

+719
-119
lines changed

6 files changed

+719
-119
lines changed

src/packages/frontend/account/i18n-selector.tsx

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,20 @@
44
*/
55

66
/*
7-
Basically a drop-down to change the langauge (i18n localization)
7+
Basically a drop-down to change the language (i18n localization)
88
*/
99

1010
import { DownOutlined } from "@ant-design/icons";
11-
import { Button, Dropdown, MenuProps, Modal, Space, Tooltip } from "antd";
11+
import {
12+
Button,
13+
Dropdown,
14+
MenuProps,
15+
Modal,
16+
Select,
17+
SelectProps,
18+
Space,
19+
Tooltip,
20+
} from "antd";
1221
import { SizeType } from "antd/es/config-provider/SizeContext";
1322
import { useState } from "react";
1423
import { defineMessage, useIntl } from "react-intl";
@@ -54,6 +63,50 @@ Thank you for your patience and understanding as we work to make our application
5463
description: "Content of translation information modal",
5564
});
5665

66+
interface LanguageSelectorProps
67+
extends Omit<SelectProps, "options" | "onChange"> {
68+
value?: string;
69+
onChange?: (language: string) => void;
70+
}
71+
72+
/**
73+
* A reusable language selector component for translation purposes.
74+
*/
75+
export function LanguageSelector({
76+
value,
77+
onChange,
78+
...props
79+
}: LanguageSelectorProps) {
80+
const intl = useIntl();
81+
82+
let availableLocales = Object.keys(LOCALIZATIONS) as Locale[];
83+
84+
const options = availableLocales.map((locale) => {
85+
const localization = LOCALIZATIONS[locale];
86+
const other =
87+
locale === value
88+
? localization.name
89+
: intl.formatMessage(localization.trans);
90+
return {
91+
value: locale,
92+
label: `${localization.flag} ${localization.native} (${other})`,
93+
};
94+
});
95+
96+
return (
97+
<Select
98+
value={value}
99+
onChange={onChange}
100+
options={options}
101+
placeholder="Select a language..."
102+
showSearch
103+
optionFilterProp="label"
104+
popupMatchSelectWidth={false}
105+
{...props}
106+
/>
107+
);
108+
}
109+
57110
export function I18NSelector(props: Readonly<Props>) {
58111
const { isWide = true, size, confirm = false } = props;
59112

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// number of characters we send to an LLM for context
2-
export const CUTOFF = 3000;
2+
export const CUTOFF = 5000;
33

44
// this came from ./create-chat, but for all frame types
55
export const AI_ASSIST_TAG = "code-editor";

src/packages/frontend/jupyter/cell-buttonbar.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,8 @@ export const CellButtonBar: React.FC<Props> = React.memo(
192192
}
193193

194194
function renderCodeBarLLMButtons() {
195-
if (!isCodeCell || !llmTools || !haveLLMCellTools || is_readonly) return;
196-
return <LLMCellTool id={id} actions={actions} llmTools={llmTools} />;
195+
if (!llmTools || !haveLLMCellTools || is_readonly) return;
196+
return <LLMCellTool id={id} actions={actions} llmTools={llmTools} cellType={isCodeCell ? "code" : "markdown"} />;
197197
}
198198

199199
function renderCodeBarFormatButton() {
@@ -204,7 +204,7 @@ export const CellButtonBar: React.FC<Props> = React.memo(
204204
return (
205205
<Tooltip
206206
title={intl.formatMessage({
207-
id: "jupyter.cell-buttonbr.format-button.tooltip",
207+
id: "jupyter.cell-buttonbar.format-button.tooltip",
208208
defaultMessage: "Format this code to look nice",
209209
description: "Code cell in a Jupyter Notebook",
210210
})}
@@ -230,7 +230,7 @@ export const CellButtonBar: React.FC<Props> = React.memo(
230230
>
231231
<Icon name={formatting ? "spinner" : "sitemap"} spin={formatting} />{" "}
232232
<FormattedMessage
233-
id="jupyter.cell-buttonbr.format-button.label"
233+
id="jupyter.cell-buttonbar.format-button.label"
234234
defaultMessage={"Format"}
235235
description={"Code cell in a Jupyter Notebook"}
236236
/>

src/packages/frontend/jupyter/insert-cell/ai-cell-generator.tsx

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,13 @@ import {
3333
import AIAvatar from "@cocalc/frontend/components/ai-avatar";
3434
import { Icon } from "@cocalc/frontend/components/icon";
3535
import { NotebookFrameActions } from "@cocalc/frontend/frame-editors/jupyter-editor/cell-notebook/actions";
36-
import { CUTOFF } from "@cocalc/frontend/frame-editors/llm/consts";
3736
import { LLMQueryDropdownButton } from "@cocalc/frontend/frame-editors/llm/llm-query-dropdown";
3837
import LLMSelector, {
3938
modelToName,
4039
} from "@cocalc/frontend/frame-editors/llm/llm-selector";
4140
import { labels } from "@cocalc/frontend/i18n";
4241
import { JupyterActions } from "@cocalc/frontend/jupyter/browser-actions";
4342
import { splitCells } from "@cocalc/frontend/jupyter/llm/split-cells";
44-
import { backtickSequence } from "@cocalc/frontend/markdown/util";
4543
import { LLMCostEstimation } from "@cocalc/frontend/misc/llm-cost-estimation";
4644
import { useProjectContext } from "@cocalc/frontend/project/context";
4745
import { LLMEvent } from "@cocalc/frontend/project/history/types";
@@ -62,6 +60,7 @@ import {
6260
} from "@cocalc/util/misc";
6361
import { COLORS } from "@cocalc/util/theme";
6462
import NBViewer from "../nbviewer/nbviewer";
63+
import { getPreviousNonemptyCellContents } from "../util/cell-content";
6564
import { Position } from "./types";
6665
import { insertCell } from "./util";
6766

@@ -713,7 +712,7 @@ export function AIGenerateCodeCell({
713712
open={open}
714713
content={renderContent}
715714
trigger={[]}
716-
destroyTooltipOnHide
715+
destroyOnHidden
717716
>
718717
{children}
719718
</Popover>
@@ -772,46 +771,3 @@ function getInput({
772771
system: `Create one or more code cells in a Jupyter Notebook.\n\nKernel: "${kernel_name}".\n\nProgramming language: "${lang}".\n\nEach code cell must be wrapped in triple backticks. Do not say what the output will be. Be brief.`,
773772
};
774773
}
775-
776-
function getPreviousNonemptyCellContents(
777-
actions: NotebookFrameActions | undefined,
778-
id: string,
779-
position,
780-
prevCells: PrevCells,
781-
cellTypes: "all" | "code" | "markdown" = "code",
782-
lang,
783-
): string {
784-
if (actions == null) return "";
785-
if (prevCells === "none") return "";
786-
const jupyterActionsStore = actions?.jupyter_actions.store;
787-
const start = position === "below" ? 0 : -1;
788-
let delta: number = start;
789-
const cells: string[] = [];
790-
let length = 0;
791-
792-
while (true) {
793-
const prevId = jupyterActionsStore.get_cell_id(delta, id);
794-
if (!prevId) break;
795-
const prevCell = actions.get_cell_by_id(prevId);
796-
if (!prevCell) break;
797-
const code = actions.get_cell_input(prevId)?.trim();
798-
const cellType = prevCell.get("cell_type", "code");
799-
if (code && (cellTypes === "all" || cellType === cellTypes)) {
800-
// we found a cell of given type
801-
length += code.length;
802-
if (length > CUTOFF) break;
803-
const delim = backtickSequence(code);
804-
cells.unshift(
805-
cellTypes === "all" && cellType === "code"
806-
? `${delim}${lang}\n${code}\n${delim}`
807-
: code,
808-
);
809-
if (typeof prevCells === "number") {
810-
prevCells -= 1;
811-
if (prevCells <= 0) break;
812-
}
813-
}
814-
delta -= 1;
815-
}
816-
return cells.join("\n\n");
817-
}

0 commit comments

Comments
 (0)