diff --git a/ui/web/src/i18n/locales/en/agents.json b/ui/web/src/i18n/locales/en/agents.json
index 5d7f0bbe..8ef6dcc6 100644
--- a/ui/web/src/i18n/locales/en/agents.json
+++ b/ui/web/src/i18n/locales/en/agents.json
@@ -724,7 +724,10 @@
"retrying": "Retrying...",
"done": "done",
"fileLabelSOUL": "Soul & Personality",
- "fileLabelIDENTITY": "Identity Card"
+ "fileLabelIDENTITY": "Identity Card",
+ "takingTooLong": "Taking too long?",
+ "cancel": "Cancel",
+ "cancelling": "Cancelling..."
},
"configGroups": {
"core": "Core",
diff --git a/ui/web/src/i18n/locales/vi/agents.json b/ui/web/src/i18n/locales/vi/agents.json
index cec9d42a..34ecd77b 100644
--- a/ui/web/src/i18n/locales/vi/agents.json
+++ b/ui/web/src/i18n/locales/vi/agents.json
@@ -709,7 +709,10 @@
"retrying": "Đang thử lại...",
"done": "xong",
"fileLabelSOUL": "Linh hồn & Tính cách",
- "fileLabelIDENTITY": "Thẻ danh tính"
+ "fileLabelIDENTITY": "Thẻ danh tính",
+ "takingTooLong": "Mất quá nhiều thời gian?",
+ "cancel": "Huỷ",
+ "cancelling": "Đang huỷ..."
},
"configGroups": {
"core": "Cốt lõi",
diff --git a/ui/web/src/i18n/locales/zh/agents.json b/ui/web/src/i18n/locales/zh/agents.json
index cb1470d8..59e4e86f 100644
--- a/ui/web/src/i18n/locales/zh/agents.json
+++ b/ui/web/src/i18n/locales/zh/agents.json
@@ -709,7 +709,10 @@
"retrying": "重试中...",
"done": "完成",
"fileLabelSOUL": "灵魂与个性",
- "fileLabelIDENTITY": "身份卡"
+ "fileLabelIDENTITY": "身份卡",
+ "takingTooLong": "耗时过长?",
+ "cancel": "取消",
+ "cancelling": "正在取消..."
},
"configGroups": {
"core": "核心",
diff --git a/ui/web/src/pages/agents/agent-detail/agent-detail-page.tsx b/ui/web/src/pages/agents/agent-detail/agent-detail-page.tsx
index dd2fd350..6692a235 100644
--- a/ui/web/src/pages/agents/agent-detail/agent-detail-page.tsx
+++ b/ui/web/src/pages/agents/agent-detail/agent-detail-page.tsx
@@ -35,7 +35,7 @@ export function AgentDetailPage({ agentId, onBack }: AgentDetailPageProps) {
const navigate = useNavigate();
const { agent, files, loading, updateAgent, getFile, setFile, regenerateAgent, resummonAgent, refresh } =
useAgentDetail(agentId);
- const { deleteAgent: deleteAgentById } = useAgents();
+ const { deleteAgent: deleteAgentById, cancelSummonAgent } = useAgents();
const hb = useAgentHeartbeat(agentId);
const [summoningOpen, setSummoningOpen] = useState(false);
const [activeTab, setActiveTab] = useState("agent");
@@ -161,6 +161,7 @@ export function AgentDetailPage({ agentId, onBack }: AgentDetailPageProps) {
agentName={title}
onCompleted={() => {}}
onResummon={async () => { await resummonAgent(); }}
+ onCancel={cancelSummonAgent}
/>
{heartbeatOpen && (
diff --git a/ui/web/src/pages/agents/agents-page.tsx b/ui/web/src/pages/agents/agents-page.tsx
index 6f9ce2c7..700130ba 100644
--- a/ui/web/src/pages/agents/agents-page.tsx
+++ b/ui/web/src/pages/agents/agents-page.tsx
@@ -31,7 +31,7 @@ export function AgentsPage() {
const { t } = useTranslation("agents");
const { id: detailId } = useParams<{ id: string }>();
const navigate = useNavigate();
- const { agents, loading, createAgent, deleteAgent, refresh, resummonAgent } = useAgents();
+ const { agents, loading, createAgent, deleteAgent, refresh, resummonAgent, cancelSummonAgent } = useAgents();
const showSkeleton = useDeferredLoading(loading && agents.length === 0);
const [search, setSearch] = useState("");
@@ -288,6 +288,7 @@ export function AgentsPage() {
agentName={summoningAgent.name}
onCompleted={refresh}
onResummon={resummonAgent}
+ onCancel={cancelSummonAgent}
/>
)}
diff --git a/ui/web/src/pages/agents/hooks/use-agents.ts b/ui/web/src/pages/agents/hooks/use-agents.ts
index a96660f7..7fc0f474 100644
--- a/ui/web/src/pages/agents/hooks/use-agents.ts
+++ b/ui/web/src/pages/agents/hooks/use-agents.ts
@@ -113,5 +113,12 @@ export function useAgents() {
[http],
);
- return { agents, loading, error, refresh: invalidate, createAgent, updateAgent, deleteAgent, resummonAgent };
+ const cancelSummonAgent = useCallback(
+ async (id: string) => {
+ await http.post(`/v1/agents/${id}/cancel-summon`);
+ },
+ [http],
+ );
+
+ return { agents, loading, error, refresh: invalidate, createAgent, updateAgent, deleteAgent, resummonAgent, cancelSummonAgent };
}
diff --git a/ui/web/src/pages/agents/summoning-modal.tsx b/ui/web/src/pages/agents/summoning-modal.tsx
index a76883a3..2f853895 100644
--- a/ui/web/src/pages/agents/summoning-modal.tsx
+++ b/ui/web/src/pages/agents/summoning-modal.tsx
@@ -17,10 +17,13 @@ interface SummoningModalProps {
agentName: string;
onCompleted: () => void;
onResummon: (agentId: string) => Promise
{t("summoning.takingTooLong")}
+ +