Skip to content

Commit

Permalink
Merge pull request #341 from refly-ai/fix/selection-context-issues
Browse files Browse the repository at this point in the history
Fix/selection context issues
  • Loading branch information
mrcfps authored Jan 7, 2025
2 parents 6f7daa8 + f7e1d09 commit cf4306b
Show file tree
Hide file tree
Showing 32 changed files with 268 additions and 197 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { useCanvasContext } from '@refly-packages/ai-workspace-common/context/ca
import { useSyncSelectedNodesToContext } from '@refly-packages/ai-workspace-common/hooks/canvas/use-sync-selected-nodes-to-context';
import { PiMagicWand } from 'react-icons/pi';
import { useAddNode } from '@refly-packages/ai-workspace-common/hooks/canvas/use-add-node';
import { convertContextItemsToNodeFilters } from '@refly-packages/ai-workspace-common/utils/map-context-items';

export const ChatPanel = () => {
const { t } = useTranslation();
Expand Down Expand Up @@ -114,6 +115,7 @@ export const ChatPanel = () => {

// Reset selected skill after sending message
skillStore.setSelectedSkill(null);
setContextItems([]);

invokeAction(
{
Expand Down Expand Up @@ -142,10 +144,7 @@ export const ChatPanel = () => {
},
},
},
contextItems.map((item) => ({
type: item.type,
entityId: item.entityId,
})),
convertContextItemsToNodeFilters(contextItems),
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ import { Command } from 'cmdk';
import { Home } from './home';
import { RenderItem } from './type';
import { getContextItemIcon } from '../../utils/icon';

import { CanvasNodeType } from '@refly/openapi-schema';
import { IconRefresh } from '@arco-design/web-react/icon';
import { IContextItem, useContextPanelStoreShallow } from '@refly-packages/ai-workspace-common/stores/context-panel';
import { CanvasNode } from '@refly-packages/ai-workspace-common/components/canvas/nodes';
import { useCanvasData } from '@refly-packages/ai-workspace-common/hooks/canvas/use-canvas-data';

import './index.scss';
Expand Down Expand Up @@ -97,8 +96,8 @@ export const BaseMarkContextSelector = (props: BaseMarkContextSelectorProps) =>
const sortedRenderData = useMemo(() => {
return processedNodes.map((item) => ({
data: item,
type: item?.type,
icon: getContextItemIcon(item, { width: 12, height: 12 }),
type: item?.type as CanvasNodeType,
icon: getContextItemIcon(item.type, { width: 12, height: 12 }),
isSelected: selectedItems?.some((selected) => selected?.entityId === item?.entityId),
onItemClick: (item: IContextItem) => {
onSelect?.(item);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const ChatHistoryItem = ({ node }: { node: CanvasNode<ResponseNodeMeta> }) => {
);
};

export const ChatHistory: React.FC<ChatHistoryProps> = ({ item }) => {
export const ChatHistoryPreview: React.FC<ChatHistoryProps> = ({ item }) => {
const { t } = useTranslation();

const findThreadHistory = useFindThreadHistory();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { useCallback } from 'react';
import { useReactFlow } from '@xyflow/react';
import { useTranslation } from 'react-i18next';
import { IContextItem } from '@refly-packages/ai-workspace-common/stores/context-panel';
import { IconQuote } from '@refly-packages/ai-workspace-common/components/common/icon';
import { getContextItemIcon } from '@refly-packages/ai-workspace-common/components/canvas/launchpad/context-manager/utils/icon';
import { LuChevronRight } from 'react-icons/lu';
import { useNodePosition } from '@refly-packages/ai-workspace-common/hooks/canvas/use-node-position';
import { useNodeSelection } from '@refly-packages/ai-workspace-common/hooks/canvas/use-node-selection';
import { CanvasNode } from '@refly-packages/ai-workspace-common/components/canvas/nodes';

interface SelectionPreviewProps {
item: IContextItem;
}

export const SelectionPreview: React.FC<SelectionPreviewProps> = ({ item }) => {
const { t } = useTranslation();
const { selection } = item;
const { getNodes } = useReactFlow();
const { setNodeCenter } = useNodePosition();
const { setSelectedNode } = useNodeSelection();

const handleSourceClick = useCallback(async () => {
const node = getNodes().find((node) => node.data?.entityId === selection?.sourceEntityId);

if (!node) {
return;
}

setNodeCenter(node.id);
setSelectedNode(node as CanvasNode<any>);
}, [selection, setNodeCenter, setSelectedNode]);

return (
<div className="w-64 p-3 rounded-lg max-h-[400px] overflow-y-auto flex flex-col gap-3">
<div className="flex items-center gap-2">
<div className="w-6 h-6 rounded bg-gray-700 shadow-lg flex items-center justify-center flex-shrink-0">
<IconQuote className="w-4 h-4 text-white" />
</div>
<span className="text-sm font-medium leading-normal truncate">{t('copilot.contextItem.quote')}</span>
</div>
<div
className="
px-2
py-1
text-xs
text-gray-500
border
border-solid
border-gray-200
rounded-lg
flex
justify-between
items-center
gap-2
cursor-pointer
hover:bg-gray-50
"
onClick={(e) => {
e.stopPropagation();
handleSourceClick();
}}
>
<div className="flex items-center gap-2">
{getContextItemIcon(selection?.sourceEntityType)}
<span className="text-gray-500">{selection?.sourceTitle}</span>
</div>
<LuChevronRight className="w-4 h-4 text-gray-300" />
</div>
<div className="text-xs">{selection?.content}</div>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export const ContextItem = ({
onRemove?: (item: IContextItem) => void;
}) => {
const { t } = useTranslation();
const { title, entityId, type, metadata, isCurrentContext } = item ?? {};
const icon = getContextItemIcon(item);
const { title, entityId, type, selection, metadata, isCurrentContext } = item ?? {};
const icon = getContextItemIcon(item.type, null, { withHistory: metadata?.withHistory });
const { setSelectedNode } = useNodeSelection();
const { nodes } = useCanvasData();
const { getNodes } = useReactFlow();
Expand All @@ -45,11 +45,9 @@ export const ContextItem = ({

setNodeCenter(node.id);

const isSelectionNode = metadata?.sourceType?.includes('Selection');

if (isSelectionNode) {
const sourceEntityId = metadata?.sourceEntityId;
const sourceEntityType = metadata?.sourceEntityType;
if (selection) {
const sourceEntityId = selection.sourceEntityId;
const sourceEntityType = selection.sourceEntityType;

if (!sourceEntityId || !sourceEntityType) {
console.warn('Missing source entity information for selection node');
Expand All @@ -69,7 +67,7 @@ export const ContextItem = ({
} else {
setSelectedNode(node as CanvasNode<any>);
}
}, [entityId, setSelectedNode, t]);
}, [entityId, selection, setSelectedNode, t]);

const content = <ContextPreview item={item} />;

Expand Down Expand Up @@ -118,7 +116,6 @@ export const ContextItem = ({
'text-red-500': isLimit,
},
)}
title={title ?? ''}
>
{title}
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
import { DocumentNode, ResourceNode, MemoNode } from '@refly-packages/ai-workspace-common/components/canvas/nodes';
import { useCanvasData } from '@refly-packages/ai-workspace-common/hooks/canvas/use-canvas-data';
import { IContextItem } from '@refly-packages/ai-workspace-common/stores/context-panel';
import { ChatHistory } from '@refly-packages/ai-workspace-common/components/canvas/launchpad/chat-history';
import { ChatHistoryPreview } from './components/chat-history-preview';
import { SelectionPreview } from '@refly-packages/ai-workspace-common/components/canvas/launchpad/context-manager/components/selection-preview';

export const ContextPreview = memo(
({ item }: { item: IContextItem }) => {
Expand All @@ -20,7 +21,11 @@ export const ContextPreview = memo(
isPreview: true,
hideActions: true,
hideHandles: true,
data: node?.data,
data: {
...node?.data,
// Overwrite contentPreview if this is a selection
...(item.selection ? { contentPreview: item.selection.content } : {}),
},
selected: false,
id: node?.id,
};
Expand All @@ -32,11 +37,15 @@ export const ContextPreview = memo(
return <ResourceNode {...(commonProps as ResourceNodeProps)} />;
case 'skillResponse':
if (item.metadata?.withHistory) {
return <ChatHistory item={item} />;
return <ChatHistoryPreview item={item} />;
}
return <SkillResponseNode {...(commonProps as SkillResponseNodeProps)} />;
case 'memo':
return <MemoNode {...(commonProps as MemoNodeProps)} />;
case 'resourceSelection':
case 'documentSelection':
case 'skillResponseSelection':
return <SelectionPreview item={item} />;
default:
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
import {
IconMemo,
IconThreadHistory,
IconResponseFilled,
IconResourceFilled,
IconDocumentFilled,
IconThreadHistoryFilled,
IconQuote,
} from '@refly-packages/ai-workspace-common/components/common/icon';
import { NODE_COLORS } from '@refly-packages/ai-workspace-common/components/canvas/nodes/shared/colors';
import { IContextItem } from '@refly-packages/ai-workspace-common/stores/context-panel';
import { CanvasNodeType, SelectionKey } from '@refly/openapi-schema';

export const getContextItemIcon = (item: IContextItem, style?: React.CSSProperties) => {
const color = NODE_COLORS[item.type];
export const getContextItemIcon = (
type: CanvasNodeType | SelectionKey,
style?: React.CSSProperties,
options?: { withHistory?: boolean },
) => {
const color = NODE_COLORS[type];

switch (item.type) {
switch (type) {
case 'resource':
return <IconResourceFilled style={{ color, ...style }} />;
case 'document':
return <IconDocumentFilled style={{ color, ...style }} />;
case 'memo':
return <IconMemo style={{ color, ...style }} />;
case 'skillResponse':
return item.metadata?.withHistory ? (
return options?.withHistory ? (
<IconThreadHistoryFilled style={{ color: NODE_COLORS['threadHistory'], ...style }} />
) : (
<IconResponseFilled style={{ color, ...style }} />
);
case 'resourceSelection':
case 'documentSelection':
case 'skillResponseSelection':
return <IconQuote style={{ color, ...style }} />;
default:
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const skillItemTitleClasses = 'inline-block max-w-[calc(100% - 8px)] overflow-hi

const skillItemClasses =
'h-7 px-1.5 rounded-md border border-solid border-gray-200 text-gray-500 bg-white flex items-center justify-center ' +
'text-xs font-medium transition-all duration-200 ease-in-out hover:bg-gray-100 hover:text-black cursor-pointer';
'text-xs font-medium transition-all duration-200 ease-in-out hover:bg-gray-100 hover:text-green-600 cursor-pointer';

export const SkillDisplay = () => {
const { t } = useTranslation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useDeleteNode } from '@refly-packages/ai-workspace-common/hooks/canvas/
import { useInvokeAction } from '@refly-packages/ai-workspace-common/hooks/canvas/use-invoke-action';
import { CanvasNodeData } from '@refly-packages/ai-workspace-common/components/canvas/nodes/shared/types';
import { IContextItem } from '@refly-packages/ai-workspace-common/stores/context-panel';
import { convertContextItemsToNodeFilters } from '@refly-packages/ai-workspace-common/utils/map-context-items';
import { useNodeCluster } from '@refly-packages/ai-workspace-common/hooks/canvas/use-node-cluster';

interface MenuItem {
Expand Down Expand Up @@ -168,10 +169,7 @@ export const SelectionActionMenu: FC<SelectionActionMenuProps> = ({ onClose }) =
},
position: node.position,
},
contextItems.map((item) => ({
type: item.type,
entityId: item.entityId,
})),
convertContextItemsToNodeFilters(contextItems),
);

// Delete the skill node after invoking
Expand Down
Loading

0 comments on commit cf4306b

Please sign in to comment.