Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions src/packages/frontend/chat/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,7 @@ export class ChatActions extends Actions<ChatState> {
};

toggleFoldThread = (reply_to: Date, messageIndex?: number) => {
if (this.syncdb == null) {
return;
}
if (this.syncdb == null) return;
const account_id = this.redux.getStore("account").get_account_id();
const cur = this.syncdb.get_one({ event: "chat", date: reply_to });
const folding = cur?.get("folding") ?? List([]);
Expand All @@ -113,6 +111,29 @@ export class ChatActions extends Actions<ChatState> {
}
};

foldAllThreads = (onlyLLM = true) => {
if (this.syncdb == null || this.store == null) return;
const messages = this.store.get("messages");
if (messages == null) return;
const account_id = this.redux.getStore("account").get_account_id();
for (const [_timestamp, message] of messages) {
// ignore replies
if (message.get("reply_to") != null) continue;
const date = message.get("date");
if (!(date instanceof Date)) continue;
const isLLMThread = this.isLanguageModelThread(date) !== false;
if (onlyLLM && !isLLMThread) continue;
const folding = message?.get("folding") ?? List([]);
const folded = folding.includes(account_id);
if (!folded) {
this.syncdb.set({
folding: folding.push(account_id),
date,
});
}
}
};

feedback = (message: ChatMessageTyped, feedback: Feedback | null) => {
if (this.syncdb == null) return;
const date = message.get("date");
Expand Down Expand Up @@ -479,6 +500,7 @@ export class ChatActions extends Actions<ChatState> {
scrollToDate: null,
});
};

scrollToIndex = (index: number = -1) => {
if (this.syncdb == null) return;
// we first clear, then set it, since scroll to needs to
Expand Down
49 changes: 29 additions & 20 deletions src/packages/frontend/chat/chat-log.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@
Render all the messages in the chat.
*/

// cSpell:ignore: timespan

import { Alert, Button } from "antd";
import { Set as immutableSet } from "immutable";
import { MutableRefObject, useEffect, useMemo, useRef } from "react";
import { Virtuoso, VirtuosoHandle } from "react-virtuoso";

import { chatBotName, isChatBot } from "@cocalc/frontend/account/chatbot";
import { useRedux, useTypedRedux } from "@cocalc/frontend/app-framework";
import { Icon } from "@cocalc/frontend/components";
import useVirtuosoScrollHook from "@cocalc/frontend/components/virtuoso-scroll-hook";
import { HashtagBar } from "@cocalc/frontend/editors/task-editor/hashtag-bar";
import { DivTempHeight } from "@cocalc/frontend/jupyter/cell-list";
import {
cmp,
hoursToTimeIntervalHuman,
Expand All @@ -24,12 +28,21 @@ import {
} from "@cocalc/util/misc";
import type { ChatActions } from "./actions";
import Composing from "./composing";
import Message from "./message";
import type { ChatMessageTyped, ChatMessages, Mode } from "./types";
import { getSelectedHashtagsSearch, newest_content } from "./utils";
import { getRootMessage, getThreadRootDate } from "./utils";
import { DivTempHeight } from "@cocalc/frontend/jupyter/cell-list";
import { filterMessages } from "./filter-messages";
import Message from "./message";
import type {
ChatMessageTyped,
ChatMessages,
CostEstimate,
Mode,
NumChildren,
} from "./types";
import {
getRootMessage,
getSelectedHashtagsSearch,
getThreadRootDate,
newest_content,
} from "./utils";

interface Props {
project_id: string; // used to render links more effectively
Expand Down Expand Up @@ -83,7 +96,7 @@ export function ChatLog({
} = useMemo<{
dates: string[];
numFolded: number;
numChildren;
numChildren: NumChildren;
}>(() => {
const { dates, numFolded, numChildren } = getSortedDates(
messages,
Expand Down Expand Up @@ -288,10 +301,7 @@ function isPrevMessageSender(
);
}

function isThread(
message: ChatMessageTyped,
numChildren: { [date: number]: number },
) {
function isThread(message: ChatMessageTyped, numChildren: NumChildren) {
if (message.get("reply_to") != null) {
return true;
}
Expand Down Expand Up @@ -324,7 +334,7 @@ export function getSortedDates(
): {
dates: string[];
numFolded: number;
numChildren: { [date: number]: number };
numChildren: NumChildren;
} {
let numFolded = 0;
let m = messages;
Expand All @@ -342,7 +352,7 @@ export function getSortedDates(

// Do a linear pass through all messages to divide into threads, so that
// getSortedDates is O(n) instead of O(n^2) !
const numChildren: { [date: number]: number } = {};
const numChildren: NumChildren = {};
for (const [_, message] of m) {
const parent = message.get("reply_to");
if (parent != null) {
Expand Down Expand Up @@ -486,22 +496,21 @@ export function MessageList({
selectedDate,
numChildren,
}: {
messages;
account_id;
messages: ChatMessages;
account_id: string;
user_map;
mode;
sortedDates;
virtuosoRef?;
search?;
project_id?;
path?;
fontSize?;
project_id?: string;
path?: string;
fontSize?: number;
selectedHashtags?;
actions?;
costEstimate?;
costEstimate?: CostEstimate;
manualScrollRef?;
selectedDate?: string;
numChildren?;
numChildren?: NumChildren;
}) {
const virtuosoHeightsRef = useRef<{ [index: number]: number }>({});
const virtuosoScroll = useVirtuosoScrollHook({
Expand Down
17 changes: 10 additions & 7 deletions src/packages/frontend/chat/chatroom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import { Button, Divider, Input, Select, Space, Tooltip } from "antd";
import { debounce } from "lodash";
import { FormattedMessage } from "react-intl";

import { ButtonGroup, Col, Row, Well } from "@cocalc/frontend/antd-bootstrap";
import {
React,
Expand All @@ -18,16 +20,16 @@ import { Icon, Loading } from "@cocalc/frontend/components";
import StaticMarkdown from "@cocalc/frontend/editors/slate/static-markdown";
import { FrameContext } from "@cocalc/frontend/frame-editors/frame-tree/frame-context";
import { hoursToTimeIntervalHuman } from "@cocalc/util/misc";
import { FormattedMessage } from "react-intl";
import type { ChatActions } from "./actions";
import type { ChatState } from "./store";
import { ChatLog } from "./chat-log";
import Filter from "./filter";
import { FoldAllThreads } from "./fold-threads";
import ChatInput from "./input";
import { LLMCostEstimationChat } from "./llm-cost-estimation";
import type { ChatState } from "./store";
import { SubmitMentionsFn } from "./types";
import { INPUT_HEIGHT, markChatAsReadIfUnseen } from "./utils";
import VideoChatButton from "./video/launch-button";
import Filter from "./filter";

const FILTER_RECENT_NONE = {
value: 0,
Expand Down Expand Up @@ -68,7 +70,7 @@ interface Props {
project_id: string;
path: string;
is_visible?: boolean;
font_size: number;
fontSize: number;
desc?;
}

Expand All @@ -77,7 +79,7 @@ export function ChatRoom({
project_id,
path,
is_visible,
font_size,
fontSize,
desc,
}: Props) {
const useEditor = useEditorRedux<ChatState>({ project_id, path });
Expand Down Expand Up @@ -261,6 +263,7 @@ export function ChatRoom({
<ButtonGroup style={{ marginLeft: "5px" }}>
{render_video_chat_button()}
</ButtonGroup>
<FoldAllThreads actions={actions} shortLabel={false} />
</Space>
);
}
Expand All @@ -285,7 +288,7 @@ export function ChatRoom({
path={path}
scrollToBottomRef={scrollToBottomRef}
mode={"standalone"}
fontSize={font_size}
fontSize={fontSize}
search={search}
filterRecentH={filterRecentH}
selectedHashtags={selectedHashtags}
Expand All @@ -304,7 +307,7 @@ export function ChatRoom({
}}
>
<ChatInput
fontSize={font_size}
fontSize={fontSize}
autoFocus
cacheId={`${path}${project_id}-new`}
input={input}
Expand Down
7 changes: 4 additions & 3 deletions src/packages/frontend/chat/filter-messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ NOTE: chat uses every imaginable way to store a timestamp at once,
which is the may source of weirdness in the code below... Beware.
*/

import type { ChatMessages, ChatMessageTyped, MessageHistory } from "./types";
import { search_match, search_split } from "@cocalc/util/misc";
import { List } from "immutable";
import LRU from "lru-cache";

import type { TypedMap } from "@cocalc/frontend/app-framework";
import { redux } from "@cocalc/frontend/app-framework";
import { webapp_client } from "@cocalc/frontend/webapp-client";
import LRU from "lru-cache";
import { search_match, search_split } from "@cocalc/util/misc";
import type { ChatMessages, ChatMessageTyped, MessageHistory } from "./types";

export function filterMessages({
messages,
Expand Down
25 changes: 25 additions & 0 deletions src/packages/frontend/chat/fold-threads.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Button } from "antd";

import { ChatActions } from "@cocalc/frontend/chat/actions";
import { Icon, Tip } from "@cocalc/frontend/components";

export function FoldAllThreads({
actions,
shortLabel,
}: {
actions: ChatActions;
shortLabel: boolean;
}) {
return (
<Tip placement="top" title="Fold all language model threads">
<Button
onClick={() => {
actions.foldAllThreads(true);
}}
>
<Icon name="to-top-outlined" />{" "}
{shortLabel ? "LLM" : "Fold LLM threads"}
</Button>
</Tip>
);
}
3 changes: 2 additions & 1 deletion src/packages/frontend/chat/llm-cost-estimation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import {
ESTIMATION_HELP_TEXT,
MODEL_FREE_TO_USE,
} from "@cocalc/frontend/misc/llm-cost-estimation";
import type { CostEstimate } from "./types";

export function LLMCostEstimationChat({
costEstimate,
compact,
style,
}: {
costEstimate?: { min: number; max: number } | null;
costEstimate?: CostEstimate;
compact: boolean; // only mean is shown
style?: CSS;
}) {
Expand Down
13 changes: 9 additions & 4 deletions src/packages/frontend/chat/llm-msg-summarize.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Button, Collapse, Switch } from "antd";

import { useLanguageModelSetting } from "@cocalc/frontend/account/useLanguageModelSetting";
import { useAsyncEffect, useState } from "@cocalc/frontend/app-framework";
import { Icon, Paragraph, RawPrompt } from "@cocalc/frontend/components";
import { Icon, Paragraph, RawPrompt, Tip } from "@cocalc/frontend/components";
import AIAvatar from "@cocalc/frontend/components/ai-avatar";
import PopconfirmKeyboard from "@cocalc/frontend/components/popconfirm-keyboard";
import LLMSelector, {
Expand Down Expand Up @@ -111,9 +111,14 @@ export function SummarizeThread({
onConfirm={() => actions?.summarizeThread({ model, reply_to, short })}
okText="Summarize"
>
<Button type="text" style={{ color: COLORS.GRAY_M }}>
<Icon name="vertical-align-middle" /> Summarize…
</Button>
<Tip
placement={"bottom"}
title={"Summarize this thread using a language model."}
>
<Button type="text" style={{ color: COLORS.GRAY_M }}>
<Icon name="vertical-align-middle" /> Summarize…
</Button>
</Tip>
</PopconfirmKeyboard>
);
}
Loading