Files
openmaic/OpenMAIC/components/edit/AgentPanel/edit-elements-tool-ui.tsx
2026-08-16 14:58:47 +08:00

98 lines
2.4 KiB
TypeScript

'use client';
/**
* Tool-call UI for `edit_elements` (natural-language per-element edits).
* Minimal non-expandable ToolCard — title + @scene pill + localized status.
*/
import { Move } from 'lucide-react';
import { makeAssistantToolUI } from '@assistant-ui/react';
import { useI18n } from '@/lib/hooks/use-i18n';
import { editElementsOutcome } from '@/lib/agent/client/edit-elements-result';
import { ToolCard, isStoppedResult, type ToolStatus } from './tool-card';
interface EditElementsResult {
content?: { type: string; text?: string }[];
details?: {
sceneId?: string;
intents?: unknown[] | null;
updateCount?: number;
refuseReason?: string;
};
}
function deriveEditElementsFailed(args: {
running: boolean;
stopped: boolean;
isError: boolean;
result?: EditElementsResult | null;
}): boolean {
const { running, stopped, isError, result } = args;
if (running || stopped) return false;
const outcome = editElementsOutcome(result?.details);
if (outcome === 'applied') return false;
return isError || outcome === 'refused';
}
export function EditElementsCard({
running,
stopped,
failed,
sceneId,
}: {
running: boolean;
stopped: boolean;
failed: boolean;
sceneId?: string;
}) {
const { t } = useI18n();
const toolStatus: ToolStatus = running
? 'running'
: stopped
? 'stopped'
: failed
? 'failed'
: 'done';
const baseLabel = running
? t('edit.editElements.editing')
: stopped
? t('edit.agent.stopped')
: failed
? t('edit.editElements.notApplied')
: t('edit.editElements.applied');
return (
<ToolCard
title={t('edit.editElements.title')}
icon={Move}
sceneId={sceneId}
status={toolStatus}
statusLabel={baseLabel}
/>
);
}
export const EditElementsUI = makeAssistantToolUI<
{ sceneId?: string; instruction?: string },
EditElementsResult
>({
toolName: 'edit_elements',
render: ({ args, status, result, isError }) => {
const running = status.type === 'running' || status.type === 'requires-action';
const stopped = !running && isStoppedResult(result);
const failed = deriveEditElementsFailed({
running,
stopped,
isError: !!isError,
result,
});
return (
<EditElementsCard
running={running}
stopped={stopped}
failed={failed}
sceneId={args?.sceneId ?? result?.details?.sceneId}
/>
);
},
});