diff --git a/.gitignore b/.gitignore index 020d34e3..4aebc103 100644 --- a/.gitignore +++ b/.gitignore @@ -98,3 +98,6 @@ docs/aidev-docs docs/backups # Frontend skills components must be tracked (excluded from the broad skills/ ignore above) !frontend-web/src/components/workspace/skills/ + +# uv lockfile (not tracked per project preference) +offline-backend-20260512/backend/uv.lock diff --git a/frontend-web/.env.development b/frontend-web/.env.development index 6228c720..e66a65da 100644 --- a/frontend-web/.env.development +++ b/frontend-web/.env.development @@ -25,8 +25,13 @@ VITE_AIPI_KNOWLEDGE_IFRAME_API_URL=https://ch1.b.uat.4.cn/knowes/api/iframeKnowl VITE_AIPI_KNOWLEDGE_IFRAME_SKIN=red VITE_AIPI_MOPECHAT_URL=https://ch1.b.uat.4.cn/likun_b1_mope VITE_AIPI_BACKENP_URL=https://knowledgetoolserver.b.uat.4.cn +# 我的笔记前端 +VITE_AIPI_FRONTEND_URL= xxx VITE_AIPI_CONSUMER_URL=https://ch1.b.uat.4.cn/consumer VITE_AIPI_PGLINKTO_URL=https://pg.b.uat.4.cn VITE_AIPI_XKLINKTO_URL=https://kz.b.uat.4.cn # 可选:Canvas 独立 LangGraph 地址(不设则回退到 VITE_LANGGRAPH_BASE_URL) # VITE_CANVAS_LANGGRAPH_BASE_URL= + +# 我的笔记是否显示,侧边栏 +VITE_STUDIO_ENABLED=false diff --git a/frontend-web/src/components/ai-elements/artifact.tsx b/frontend-web/src/components/ai-elements/artifact.tsx index b5e89bd7..3acfc5c1 100644 --- a/frontend-web/src/components/ai-elements/artifact.tsx +++ b/frontend-web/src/components/ai-elements/artifact.tsx @@ -16,7 +16,7 @@ export type ArtifactProps = HTMLAttributes; export const Artifact = ({ className, ...props }: ArtifactProps) => (
(
(
)} + {canEdit && (
-
+
{isSkillsLoading ? (

技能加载中...

) : enabledSkills.length === 0 ? ( @@ -543,13 +592,13 @@ export function AgentCard({ agent }: AgentCardProps) { 当前没有可用技能

) : ( -
+
{enabledSkills.map((skill) => { const checked = selectedSkills.includes(skill.name); return (
diff --git a/frontend-web/src/components/workspace/chats/chat-box.tsx b/frontend-web/src/components/workspace/chats/chat-box.tsx index 282d2584..0fe678a2 100644 --- a/frontend-web/src/components/workspace/chats/chat-box.tsx +++ b/frontend-web/src/components/workspace/chats/chat-box.tsx @@ -384,14 +384,14 @@ const ChatBox: React.FC<{ />
diff --git a/frontend-web/src/components/workspace/input-box.tsx b/frontend-web/src/components/workspace/input-box.tsx index f1739d53..da17a139 100644 --- a/frontend-web/src/components/workspace/input-box.tsx +++ b/frontend-web/src/components/workspace/input-box.tsx @@ -583,7 +583,7 @@ export function InputBox({ // 对话态:常规白卡 + 中性边框 + 轻阴影 isNewThread ? "rounded-3xl bg-transparent border-0 shadow-none ring-0" - : "rounded-3xl bg-background border border-border shadow-sm dark:bg-slate-800 dark:border-slate-700", + : "rounded-3xl bg-background border border-border shadow-sm transition-shadow hover:shadow-md focus-within:border-ring/40 focus-within:shadow-md focus-within:ring-1 focus-within:ring-ring/20 dark:bg-slate-800 dark:border-slate-700", className, )} disabled={disabled} diff --git a/frontend-web/src/components/workspace/messages/message-list-item.tsx b/frontend-web/src/components/workspace/messages/message-list-item.tsx index 082b4607..2deec268 100644 --- a/frontend-web/src/components/workspace/messages/message-list-item.tsx +++ b/frontend-web/src/components/workspace/messages/message-list-item.tsx @@ -1,9 +1,10 @@ import type { Message } from '@langchain/langgraph-sdk'; -import { ClockIcon, FileIcon, Loader2Icon } from 'lucide-react'; +import { ClockIcon, FileIcon, Loader2Icon, PencilIcon } from 'lucide-react'; import { memo, useCallback, useContext, + useEffect, useMemo, useState, type AnchorHTMLAttributes, @@ -25,6 +26,8 @@ import { } from '@/components/ai-elements/reasoning'; import { Task, TaskTrigger } from '@/components/ai-elements/task'; import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { Textarea } from '@/components/ui/textarea'; import { UploadedFilePreviewDialog, useAuthedObjectUrl, @@ -51,6 +54,7 @@ import { cn } from '@/lib/utils'; import { CitationLink } from '../citations/citation-link'; import { CopyButton } from '../copy-button'; +import { Tooltip } from '../tooltip'; import { SkillDisplayBlock } from '../skill-display-block'; import { ThreadContext } from './context'; import { DownloadWordButton } from './download-word-button'; @@ -130,6 +134,7 @@ export function MessageListItem({ tokenUsageEnabled = false, displaySources = [], extraRehypePlugins, + onEditResubmit, }: { className?: string; fitRowToContent?: boolean; @@ -139,6 +144,7 @@ export function MessageListItem({ tokenUsageEnabled?: boolean; displaySources?: RuntimeDisplaySource[]; extraRehypePlugins?: ReturnType; + onEditResubmit?: (text: string) => void; }) { const isHuman = message.type === 'human'; const messageMarkdown = @@ -163,17 +169,23 @@ export function MessageListItem({ tokenUsageEnabled={tokenUsageEnabled} displaySources={displaySources} extraRehypePlugins={extraRehypePlugins} + onEditResubmit={onEditResubmit} /> - {!isLoading && ( + {/* + Human messages carry their own inline copy/edit toolbar inside + MessageContent (above the timestamp). Only assistant answers use the + floating bottom toolbar here. + */} + {!isLoading && !isHuman && (
- {!isHuman && messageMarkdown && ( + {messageMarkdown && ( void; +}) { + const { t } = useI18n(); + const [editing, setEditing] = useState(false); + const [draft, setDraft] = useState(text); + + useEffect(() => { + if (!editing) { + setDraft(text); + } + }, [text, editing]); + + const confirmEdit = useCallback(() => { + const value = draft.trim(); + if (!value) { + return; + } + onEditResubmit?.(value); + setEditing(false); + }, [draft, onEditResubmit]); + + if (editing) { + return ( +
+ {filesList} +