mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-11-03 22:32:27 +08:00
feat(api-tools): implement progressive disclosure meta tools for workspace assistant
LANG-225 Co-authored-by: multica-agent <[email protected]>
This commit is contained in:
co-authored by
multica-agent
parent
d41959effd
commit
eed6c2f744
@@ -1,6 +1,13 @@
|
||||
import { useEffect, useRef, useState, useId, type ReactNode } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Plus, Send, ChevronDown, LoaderCircle, Square } from 'lucide-react';
|
||||
import {
|
||||
Plus,
|
||||
Send,
|
||||
ChevronDown,
|
||||
LoaderCircle,
|
||||
Square,
|
||||
CircleAlert,
|
||||
} from 'lucide-react';
|
||||
import {
|
||||
RiSparkling2Line,
|
||||
RiArrowUpSLine,
|
||||
@@ -39,12 +46,23 @@ import { DynamicFormItemType } from '@/app/infra/entities/form/dynamic';
|
||||
import AssistantToolResult, { AssistantTool } from './AssistantToolResult';
|
||||
import { LANGBOT_MODELS_PROVIDER_REQUESTER } from './models-dialog/types';
|
||||
|
||||
type PendingCall = {
|
||||
name: string;
|
||||
arguments: Record<string, unknown>;
|
||||
operation?: {
|
||||
id: string;
|
||||
label?: Record<string, string>;
|
||||
risk?: 'read' | 'write' | 'dangerous';
|
||||
summary?: string;
|
||||
};
|
||||
};
|
||||
|
||||
type Conversation = {
|
||||
uuid: string;
|
||||
revision: number;
|
||||
status: 'ready' | 'running' | 'approval' | 'failed';
|
||||
messages: { role: string; content: string; tool?: AssistantTool }[];
|
||||
pending: { name: string; arguments: Record<string, unknown> }[];
|
||||
pending: PendingCall[];
|
||||
error: string | null;
|
||||
model_name: string | null;
|
||||
model_uuid: string | null;
|
||||
@@ -1043,14 +1061,86 @@ function AssistantPanel({
|
||||
{conversation?.status === 'approval' && (
|
||||
<div className="space-y-3 rounded-xl border border-primary/30 p-3">
|
||||
<p className="text-sm font-medium">{t('assistant.review')}</p>
|
||||
{conversation.pending.map((call, index) => (
|
||||
<div key={index}>
|
||||
<p className="text-sm font-medium">{call.name}</p>
|
||||
<pre className="max-h-48 overflow-auto whitespace-pre-wrap break-all text-xs">
|
||||
{JSON.stringify(call.arguments, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
))}
|
||||
{conversation.pending.map((call, index) => {
|
||||
const isWorkspaceCall = call.name === 'workspace_call';
|
||||
const operation = call.operation;
|
||||
const opId = isWorkspaceCall
|
||||
? operation?.id ||
|
||||
(call.arguments?.operation_id as string)
|
||||
: null;
|
||||
const opArgs = isWorkspaceCall
|
||||
? (call.arguments?.arguments ?? call.arguments)
|
||||
: call.arguments;
|
||||
const opLabel =
|
||||
operation?.label?.zh_Hans ||
|
||||
operation?.label?.['zh-Hans'] ||
|
||||
operation?.label?.en_US ||
|
||||
opId;
|
||||
const risk = operation?.risk;
|
||||
const isDangerous = risk === 'dangerous';
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className={`space-y-2 rounded-lg border p-3 ${
|
||||
isDangerous
|
||||
? 'border-destructive/40 bg-destructive/5'
|
||||
: 'bg-muted/30'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="min-w-0">
|
||||
{isWorkspaceCall && opLabel ? (
|
||||
<div className="flex items-center gap-1.5 flex-wrap">
|
||||
<span className="text-sm font-semibold">
|
||||
{opLabel}
|
||||
</span>
|
||||
<span className="text-xs text-muted-foreground font-mono">
|
||||
({opId})
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm font-medium">{call.name}</p>
|
||||
)}
|
||||
</div>
|
||||
{risk && (
|
||||
<span
|
||||
className={`shrink-0 rounded px-1.5 py-0.5 text-xs font-medium ${
|
||||
isDangerous
|
||||
? 'bg-destructive/15 text-destructive font-bold ring-1 ring-destructive/30'
|
||||
: 'bg-amber-500/15 text-amber-700 dark:text-amber-400'
|
||||
}`}
|
||||
>
|
||||
{t(`agents.apiToolRisk.${risk}`, {
|
||||
defaultValue: isDangerous ? '敏感' : '操作',
|
||||
})}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{isDangerous && (
|
||||
<div className="flex items-center gap-1.5 rounded bg-destructive/10 px-2 py-1.5 text-xs text-destructive font-medium border border-destructive/20">
|
||||
<CircleAlert className="size-4 shrink-0" />
|
||||
<span>
|
||||
{t('assistant.dangerousWarning', {
|
||||
defaultValue:
|
||||
'敏感操作提示:该操作具有较高风险,执行后可能不可逆,请核对参数后确认。',
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<p className="text-xs text-muted-foreground mb-1">
|
||||
{t('assistant.parameters', {
|
||||
defaultValue: '参数:',
|
||||
})}
|
||||
</p>
|
||||
<pre className="max-h-48 overflow-auto whitespace-pre-wrap break-all rounded bg-background p-2 text-xs font-mono border">
|
||||
{JSON.stringify(opArgs, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
size="sm"
|
||||
|
||||
@@ -195,6 +195,9 @@ const enUS = {
|
||||
get_pipeline: 'Read Pipeline',
|
||||
get_knowledge_schema: 'Read knowledge engine schema',
|
||||
list_operation_logs: 'Read operation logs',
|
||||
workspace_search: 'Search workspace capabilities',
|
||||
workspace_describe: 'Inspect operation definition',
|
||||
workspace_call: 'Execute workspace operation',
|
||||
},
|
||||
resources: {
|
||||
models: 'Find chat models',
|
||||
@@ -213,6 +216,9 @@ const enUS = {
|
||||
build: 'Help me create a knowledge-base question-answering application.',
|
||||
toolResult: 'Operation result',
|
||||
review: 'Review the exact operations before executing',
|
||||
dangerousWarning:
|
||||
'Sensitive Operation: This operation carries high risk and may be irreversible. Please verify arguments carefully before confirming.',
|
||||
parameters: 'Parameters:',
|
||||
confirm: 'Confirm and execute',
|
||||
decline: 'Decline',
|
||||
working: 'Working…',
|
||||
|
||||
@@ -184,6 +184,9 @@ const zhHans = {
|
||||
get_pipeline: '查看 流水线',
|
||||
get_knowledge_schema: '查看知识引擎配置',
|
||||
list_operation_logs: '查询操作日志',
|
||||
workspace_search: '搜索操作能力',
|
||||
workspace_describe: '查看操作定义',
|
||||
workspace_call: '执行工作区操作',
|
||||
},
|
||||
resources: {
|
||||
models: '查询聊天模型',
|
||||
@@ -202,6 +205,9 @@ const zhHans = {
|
||||
build: '帮我创建一个知识库问答应用。',
|
||||
toolResult: '操作结果',
|
||||
review: '请检查具体操作及参数,确认后执行',
|
||||
dangerousWarning:
|
||||
'敏感操作提示:该操作具有较高风险,执行后可能不可逆,请核对参数后确认。',
|
||||
parameters: '参数:',
|
||||
confirm: '确认执行',
|
||||
decline: '拒绝',
|
||||
working: '正在处理…',
|
||||
|
||||
Reference in New Issue
Block a user