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
57 changes: 55 additions & 2 deletions refact-agent/gui/generated/documents.ts

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions refact-agent/gui/generated/graphql/gql.ts

Large diffs are not rendered by default.

47 changes: 45 additions & 2 deletions refact-agent/gui/generated/graphql/graphql.ts

Large diffs are not rendered by default.

27 changes: 26 additions & 1 deletion refact-agent/gui/generated/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,28 @@ input FPersonaPatch {
persona_setup: String = null
}

type FPersonaScheduleListOutput {
scheds: [FPersonaScheduleOutput!]!
ws_timezone: String!
}

type FPersonaScheduleOutput {
sched_first_question: String!
sched_id: String!
sched_last_run_ts: Float!
sched_persona_id: String!
sched_rrule: String!
sched_start_ts: Float!
}

input FPersonaScheduleUpsertInput {
sched_first_question: String!
sched_id: String = null
sched_persona_id: String!
sched_rrule: String!
sched_start_ts: Float!
}

type FPersonaSubs {
news_action: String!
news_payload: FPersonaOutput
Expand Down Expand Up @@ -606,6 +628,8 @@ type Mutation {
persona_create(input: FPersonaInput!): FPersonaOutput!
persona_delete(id: String!): Boolean!
persona_patch(id: String!, patch: FPersonaPatch!): FPersonaOutput!
persona_schedule_delete(sched_id: String!): FPersonaScheduleOutput!
persona_schedule_upsert(input: FPersonaScheduleUpsertInput!): FPersonaScheduleOutput!
reset_password_execute(new_password: String!, token: String!): Boolean!
reset_password_start(username: String!): Boolean!
session_open(password: String!, username: String!): String!
Expand All @@ -617,7 +641,7 @@ type Mutation {
thread_delete(id: String!): Boolean!
thread_lock(ft_id: String!, worker_name: String!): Boolean!
thread_mass_group_patch(dst_group_id: String!, src_group_id: String!): Int!
thread_messages_create_multiple(delete_negative: [Int!] = null, input: FThreadMultipleMessagesInput!): Int!
thread_messages_create_multiple(delete_negative: [Int!] = null, input: FThreadMultipleMessagesInput!, mission_accomplished_adv_worker: String = null): Int!
thread_patch(id: String!, patch: FThreadPatch!): FThreadOutput!
thread_reset_error(ft_error: String!, ft_id: String!): Boolean!
thread_reset_title(ft_id: String!, ft_title: String!): Boolean!
Expand Down Expand Up @@ -662,6 +686,7 @@ type Query {
persona_get(id: String!): FPersonaOutput!
persona_list(limit: Int!, located_fgroup_id: String!, skip: Int!, sort_by: String! = ""): [FPersonaOutput!]!
persona_opened_in_ui(persona_id: String!): FPersonaOutput!
persona_schedule_list(persona_id: String!): FPersonaScheduleListOutput!
query_basic_stuff(want_invitations: Boolean! = false): BasicStuffResult!
reset_password_token_info(token: String!): PasswordResetTokenInfo!
stats_query(breakdown_fexp_name: [String!]!, breakdown_fuser_id: [String!]!, breakdown_model: [String!]!, fgroup_id: String! = "", filter_fexp_id: [String!]! = [], filter_fuser_id: [String!]! = [], filter_model: [String!]! = [], filter_thing: [String!]! = [], st_chart: Int!, st_span: String!, timekey_from: String!, timekey_to: String!, ws_id: String! = ""): [FStatsOutput!]!
Expand Down
1 change: 1 addition & 0 deletions refact-agent/gui/src/components/Chat/Chat.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const Template: React.FC<{
endAlt: 0,
endPrevAlt: 0,
thread: null,
loading: false,
messages: messages.reduce((acc, message) => {
return {
...acc,
Expand Down
78 changes: 45 additions & 33 deletions refact-agent/gui/src/components/Chat/Chat.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
import React, { useCallback, useMemo, useState } from "react";
import React, {
useCallback,
// useMemo,
useState,
} from "react";
import { ChatForm, ChatFormProps } from "../ChatForm";
import { ChatContent } from "../ChatContent";
import { Flex } from "@radix-ui/themes";
import { useAppDispatch, useAppSelector, useSendMessages } from "../../hooks";
import { selectConfig, type Config } from "../../features/Config/configSlice";
import {
// useAppDispatch,
useAppSelector,
useSendMessages,
} from "../../hooks";
import {
// selectConfig,
type Config,
} from "../../features/Config/configSlice";

import { DropzoneProvider } from "../Dropzone";
import { useCheckpoints } from "../../hooks/useCheckpoints";
import { Checkpoints } from "../../features/Checkpoints";

import { useMessageSubscription } from "./useMessageSubscription";
import {
selectIsStreaming,
selectIsWaiting,
// selectIsStreaming,
// selectIsWaiting,
selectThreadId,
selectTotalMessagesInThread,
// selectTotalMessagesInThread,
} from "../../features/ThreadMessages";
import { ThreadHistoryButton } from "../Buttons";
import { push } from "../../features/Pages/pagesSlice";
// import { ThreadHistoryButton } from "../Buttons";
// import { push } from "../../features/Pages/pagesSlice";

export type ChatProps = {
host: Config["host"];
Expand All @@ -29,31 +40,31 @@ export type ChatProps = {
};

export const Chat: React.FC<ChatProps> = ({ style, maybeSendToSidebar }) => {
const dispatch = useAppDispatch();
// const dispatch = useAppDispatch();
// const unCalledTools = useAppSelector(selectBranchHasUncalledTools);

const [isViewingRawJSON, setIsViewingRawJSON] = useState(false);
const isStreaming = useAppSelector(selectIsStreaming);
const isWaiting = useAppSelector(selectIsWaiting);
// const isStreaming = useAppSelector(selectIsStreaming);
// const isWaiting = useAppSelector(selectIsWaiting);
useMessageSubscription();
const { sendMessage } = useSendMessages();
const totalMessages = useAppSelector(selectTotalMessagesInThread, {
devModeChecks: { stabilityCheck: "never" },
});

const config = useAppSelector(selectConfig);

const canShowDebugButton = useMemo(() => {
if (config.host === "web") return true;
if (config.features?.connections) return true;
return !isWaiting && !isStreaming && totalMessages > 0;
}, [
config.features?.connections,
config.host,
isStreaming,
isWaiting,
totalMessages,
]);
// const totalMessages = useAppSelector(selectTotalMessagesInThread, {
// devModeChecks: { stabilityCheck: "never" },
// });

// const config = useAppSelector(selectConfig);

// const canShowDebugButton = useMemo(() => {
// if (config.host === "web") return true;
// if (!config.features?.connections) return false;
// return !isWaiting && !isStreaming && totalMessages > 0;
// }, [
// config.features?.connections,
// config.host,
// isStreaming,
// isWaiting,
// totalMessages,
// ]);

const chatId = useAppSelector(selectThreadId);

Expand All @@ -71,9 +82,9 @@ export const Chat: React.FC<ChatProps> = ({ style, maybeSendToSidebar }) => {
);

// TODO: this
const handleThreadHistoryPage = useCallback(() => {
dispatch(push({ name: "thread history page", chatId: chatId ?? "" }));
}, [chatId, dispatch]);
// const handleThreadHistoryPage = useCallback(() => {
// dispatch(push({ name: "thread history page", chatId: chatId ?? "" }));
// }, [chatId, dispatch]);

return (
<DropzoneProvider asChild>
Expand All @@ -98,15 +109,16 @@ export const Chat: React.FC<ChatProps> = ({ style, maybeSendToSidebar }) => {

<Flex justify="between" pl="1" pr="1" pt="1">
{/* Two flexboxes are left for the future UI element on the right side */}
{canShowDebugButton && (
{/* TODO: move this */}
{/* {canShowDebugButton && (
<Flex align="center" justify="end" width="100%">
<ThreadHistoryButton
title="View history of current thread"
size="1"
onClick={handleThreadHistoryPage}
/>
</Flex>
)}
)} */}
</Flex>
</Flex>
</DropzoneProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
const TEXT_DOC_UPDATE = {
waitingBranches: [],
streamingBranches: [],
loading: false,
messages: {
"J7CJxOiP5F:100:1:100": {
ft_app_specific: null,
Expand Down Expand Up @@ -805,6 +806,7 @@ const MockedStore: React.FC<{
endAlt: 0,
endPrevAlt: 0,
thread: null,
loading: false,
messages: messages
? messages.reduce((acc, cur) => {
return { ...acc, [cur.ftm_call_id]: cur };
Expand Down
2 changes: 0 additions & 2 deletions refact-agent/gui/src/components/ChatContent/ChatContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@ export const ChatContent: React.FC = () => {
direction="column"
className={styles.content}
data-element="ChatContent"
p="2"
gap="1"
>
{isEmptyNode(threadMessageTrie) ? (
<Container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ChatContextFile } from "../../services/refact/types";
import {
selectIsStreaming,
selectIsWaiting,
selectLoading,
selectMessagesFromEndNode,
} from "../../features/ThreadMessages";
import { formatMessagesForLsp } from "../../services/refact/links";
Expand Down Expand Up @@ -81,6 +82,7 @@ function useGetCommandPreviewQuery(
const messagesToSend = formatMessagesForLsp(messages);
const isWaiting = useAppSelector(selectIsWaiting);
const isStreaming = useAppSelector(selectIsStreaming);
const isLoading = useAppSelector(selectLoading);

// TODO: attach images
const { data } = commandsApi.useGetCommandPreviewQuery(
Expand All @@ -91,7 +93,7 @@ function useGetCommandPreviewQuery(
],
},
{
skip: isWaiting || isStreaming,
skip: isLoading || isWaiting || isStreaming || query.trim().length === 0,
},
);
if (!data) return [];
Expand Down
56 changes: 6 additions & 50 deletions refact-agent/gui/src/components/MessageNode/MessageNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ import { GroupedDiffs } from "../ChatContent/DiffContent";

import { FTMMessageNode as FTMessageNode } from "../../features/ThreadMessages/makeMessageTrie";
import {
selectIsStreaming,
selectIsWaiting,
selectLoading,
selectMessageIsLastOfType,
selectThreadMessageTopAltNumber,
setThreadEnd,
Expand Down Expand Up @@ -81,8 +80,8 @@ export const MessageNode: React.FC<MessageNodeProps> = ({
const isLastOfRole = useAppSelector((state) =>
selectMessageIsLastOfType(state, children.value),
);
const isWaiting = useAppSelector(selectIsWaiting);
const isStreaming = useAppSelector(selectIsStreaming);

const isLoading = useAppSelector(selectLoading);

useEffect(() => {
if (children.children.length === 0) {
Expand All @@ -104,58 +103,15 @@ export const MessageNode: React.FC<MessageNodeProps> = ({
return (
<>
{/**TODO: this could be put at the end of the assistant message */}
{!isWaiting &&
!isStreaming &&
children.value.ftm_role === "user" &&
isLastOfRole && <ScrollAreaWithAnchor.ScrollAnchor />}
{!isLoading && children.value.ftm_role === "user" && isLastOfRole && (
<ScrollAreaWithAnchor.ScrollAnchor behavior="smooth" block="start" />
)}
<ElementForNodeMessage branch={branch} message={children.value} />
<MessageNodeChildren>{children.children}</MessageNodeChildren>
</>
);
};

// type NodeSelectButtonsProps = {
// onForward: () => void;
// onBackward: () => void;
// currentNode: number;
// totalNodes: number;
// };

// const NodeSelectButtons: React.FC<NodeSelectButtonsProps> = ({
// onForward,
// onBackward,
// currentNode,
// totalNodes,
// }) => {
// return (
// <Container my="2">
// <Flex gap="2" justify="start">
// <IconButton
// variant="ghost"
// size="1"
// disabled={currentNode === 0}
// radius="large"
// onClick={onBackward}
// >
// <ArrowLeftIcon />
// </IconButton>
// <Text size="1">
// {currentNode + 1} / {totalNodes}
// </Text>
// <IconButton
// variant="ghost"
// size="1"
// disabled={currentNode === totalNodes}
// onClick={onForward}
// radius="large"
// >
// <ArrowRightIcon />
// </IconButton>
// </Flex>
// </Container>
// );
// };

function makeDummyNode(
ft_id?: string,
lastMessageNumber?: number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const MockedStore: React.FC<{
lspPort: 8001,
},
threadMessages: {
loading: false,
thread: {
ft_id: "foo",
ft_need_user: -1,
Expand Down
8 changes: 4 additions & 4 deletions refact-agent/gui/src/features/ThreadList/ThreadList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
selectThreadList,
selectThreadListError,
selectThreadListLoading,
ThreadListItem,
type ThreadListItem,
} from "./threadListSlice";
import {
graphqlQueriesAndMutations,
Expand Down Expand Up @@ -79,7 +79,7 @@ export const ThreadList: React.FC = () => {
gap="1"
>
{threads.map((thread) => (
<ThreadLustItem
<ThreadListItem
key={thread.ft_id}
thread={thread}
onOpen={onOpen}
Expand Down Expand Up @@ -113,12 +113,12 @@ type ThreadItemProps = {
onOpen: (id: string) => void;
};

const ThreadLustItem: React.FC<ThreadItemProps> = ({ thread, onOpen }) => {
const ThreadListItem: React.FC<ThreadItemProps> = ({ thread, onOpen }) => {
// TODO: handel updating state
// TODO: handle read state
// TODO: change this to created at

const dateCreated = new Date(thread.ft_created_ts);
const dateCreated = new Date(thread.ft_created_ts * 1000);
const dateTimeString = dateCreated.toLocaleString();
const [deleteThread, deleteThreadRequest] =
graphqlQueriesAndMutations.useDeleteThreadMutation();
Expand Down
Loading