diff --git a/app/components/agent/AgentDocumentDrawer.vue b/app/components/agent/AgentDocumentDrawer.vue
index 80bdd4d..05cb2e9 100644
--- a/app/components/agent/AgentDocumentDrawer.vue
+++ b/app/components/agent/AgentDocumentDrawer.vue
@@ -86,6 +86,27 @@ function closeDetail() {
selectedDoc.value = null
}
+const deleting = ref(false)
+
+async function deleteDocument(doc: AgentDocumentItem | DocDetail) {
+ if (!confirm(`确定删除「${doc.title}」吗?`)) return
+ deleting.value = true
+ try {
+ await request<{ code: number }>(`/api/agent-documents/${doc.id}`, {
+ method: 'DELETE',
+ })
+ $toast.success('已删除')
+ documents.value = documents.value.filter((d) => d.id !== doc.id)
+ if (selectedDoc.value?.id === doc.id) {
+ selectedDoc.value = null
+ }
+ } catch {
+ $toast.error('删除失败')
+ } finally {
+ deleting.value = false
+ }
+}
+
function onFilterChange(type: 'memory' | 'document' | '') {
typeFilter.value = type
fetchDocuments()
@@ -100,7 +121,7 @@ function onSearchInput() {
}
watch(() => props.show, (val) => {
- if (val && documents.value.length === 0) {
+ if (val) {
fetchDocuments()
}
})
@@ -177,6 +198,13 @@ watch(() => props.show, (val) => {
{{ item.type === 'document' ? '文档' : '记忆' }}
{{ new Date(item.updatedAt).toLocaleDateString('zh-CN') }}
+
{{ item.title }}
{{ item.summary }}
@@ -192,6 +220,14 @@ watch(() => props.show, (val) => {
返回
+
@@ -304,6 +340,57 @@ watch(() => props.show, (val) => {
color: var(--color-ink, #141413);
}
+.delete-btn {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ padding: 6px 10px;
+ border: none;
+ background: none;
+ border-radius: 8px;
+ cursor: pointer;
+ color: var(--color-muted, #6c6a64);
+ font-size: 13px;
+ transition: all 0.15s;
+ margin-left: auto;
+}
+
+.delete-btn:hover:not(:disabled) {
+ background: #fde8e8;
+ color: #c0392b;
+}
+
+.delete-btn:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.card-delete-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 24px;
+ height: 24px;
+ border: none;
+ background: none;
+ border-radius: 6px;
+ cursor: pointer;
+ color: var(--color-muted, #b8b2a6);
+ font-size: 14px;
+ transition: all 0.15s;
+ margin-left: auto;
+}
+
+.card-delete-btn:hover:not(:disabled) {
+ background: #fde8e8;
+ color: #c0392b;
+}
+
+.card-delete-btn:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
.drawer-filters {
display: flex;
align-items: center;
diff --git a/server/service/agent-document/index.ts b/server/service/agent-document/index.ts
index 77ad11a..83119a3 100644
--- a/server/service/agent-document/index.ts
+++ b/server/service/agent-document/index.ts
@@ -207,5 +207,33 @@ export async function deleteDocument(
return result.length > 0;
}
+// ============ Memory Context ============
+
+export async function getMemoryContext(
+ userId: number,
+): Promise {
+ const rows = await dbGlobal
+ .select({
+ title: agentDocuments.title,
+ content: agentDocuments.content,
+ })
+ .from(agentDocuments)
+ .where(
+ and(
+ eq(agentDocuments.userId, userId),
+ eq(agentDocuments.type, "memory"),
+ ),
+ )
+ .orderBy(desc(agentDocuments.updatedAt));
+
+ if (rows.length === 0) return null;
+
+ const parts = rows.map(
+ (r) => `## ${r.title}\n${r.content}`,
+ );
+
+ return `\n${parts.join("\n\n")}\n`;
+}
+
// ============ Tags Helper ============
export { deserializeTags, serializeTags };
diff --git a/server/service/agent/chat-engine.ts b/server/service/agent/chat-engine.ts
index b67c1d7..8297fb2 100644
--- a/server/service/agent/chat-engine.ts
+++ b/server/service/agent/chat-engine.ts
@@ -14,6 +14,7 @@ import {
updateSession,
} from "#server/service/agent/session";
import { getAgentToolsForChatByAgentId, getAgentToolsBySlugs, executeAgentTool } from "#server/service/agent-tool";
+import { getMemoryContext } from "#server/service/agent-document";
import { checkRateLimit, incrementRateLimit } from "#server/service/agent/rate-limit";
import { resolveModelForUser, resolveModelAny, toLanguageModel } from "#server/service/llm/model-resolver";
import { generateSessionTitle } from "./title";
@@ -102,6 +103,12 @@ function buildModelMessages(
});
} else {
assistantContent.push({
+ type: "tool-call",
+ toolCallId: p.toolCallId,
+ toolName: p.toolName,
+ input: p.args ?? {},
+ });
+ assistantContent.push({
type: "tool-approval-request",
approvalId: p.approvalId,
toolCallId: p.toolCallId,
@@ -238,7 +245,17 @@ export async function executeChat(params: ChatEngineParams): Promise