Browse Source

Refactor code structure for improved readability and maintainability

feat/agent-independence
npmrun 2 months ago
parent
commit
a10c0eb2e5
  1. 64
      app/components/agent/AgentDocumentDrawer.vue
  2. 42
      app/pages/agent-documents/[id].vue
  3. 11
      app/pages/agent-documents/index.vue
  4. BIN
      packages/drizzle-pkg/db.sqlite
  5. 1
      packages/drizzle-pkg/lib/schema/agent-document.ts
  6. 1
      packages/drizzle-pkg/migrations/0005_chunky_rick_jones.sql
  7. 2798
      packages/drizzle-pkg/migrations/meta/0005_snapshot.json
  8. 7
      packages/drizzle-pkg/migrations/meta/_journal.json
  9. 2
      server/api/agent-documents/[id].patch.ts
  10. 6
      server/service/agent-document/index.ts

64
app/components/agent/AgentDocumentDrawer.vue

@ -18,6 +18,7 @@ interface AgentDocumentItem {
type: 'memory' | 'document'
summary: string | null
tags: string[]
disabled: boolean
createdAt: string
updatedAt: string
}
@ -38,6 +39,7 @@ interface DocDetail {
summary: string | null
tags: string[]
agentId: number | null
disabled: boolean
createdAt: string
updatedAt: string
}
@ -57,6 +59,25 @@ const searchQuery = ref('')
const scope = ref<'agent' | 'all'>('agent')
const agents = ref<AgentItem[]>([])
const scopeSaving = ref(false)
const toggling = ref(false)
async function toggleDisabled() {
if (!selectedDoc.value) return
toggling.value = true
try {
await request(`/api/agent-documents/${selectedDoc.value.id}`, {
method: 'PATCH',
body: { disabled: !selectedDoc.value.disabled },
})
$toast.success(selectedDoc.value.disabled ? '已启用' : '已禁用')
await openDetail(selectedDoc.value.id)
await fetchDocuments()
} catch (e: any) {
$toast.error(e?.data?.message || e?.message || '操作失败')
} finally {
toggling.value = false
}
}
async function fetchAgents() {
try {
@ -267,6 +288,7 @@ watch(() => props.show, (val) => {
<span class="type-badge" :class="item.type">
{{ item.type === 'document' ? '文档' : '记忆' }}
</span>
<span v-if="item.type === 'memory' && item.disabled" class="disabled-badge">已禁用</span>
<span class="card-date">{{ new Date(item.updatedAt).toLocaleDateString('zh-CN') }}</span>
<button
class="card-delete-btn"
@ -298,6 +320,14 @@ watch(() => props.show, (val) => {
<Icon name="lucide:trash-2" />
<span>{{ deleting ? '删除中…' : '删除' }}</span>
</button>
<button
v-if="selectedDoc.type === 'memory'"
class="toggle-btn"
:disabled="toggling"
@click="toggleDisabled"
>
{{ toggling ? '处理中…' : (selectedDoc.disabled ? '启用' : '禁用') }}
</button>
<button class="close-btn" @click="emit('close')">
<Icon name="lucide:x" />
</button>
@ -310,6 +340,7 @@ watch(() => props.show, (val) => {
<span class="type-badge" :class="selectedDoc.type">
{{ selectedDoc.type === 'document' ? '文档' : '记忆' }}
</span>
<span v-if="selectedDoc.type === 'memory' && selectedDoc.disabled" class="disabled-badge">已禁用</span>
<span class="detail-date">
{{ new Date(selectedDoc.updatedAt).toLocaleString('zh-CN') }}
</span>
@ -629,6 +660,39 @@ watch(() => props.show, (val) => {
color: #1a5276;
}
.disabled-badge {
font-size: 10px;
padding: 2px 6px;
border-radius: 4px;
font-weight: 500;
background: #fde8e8;
color: #c0392b;
}
.toggle-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;
}
.toggle-btn:hover:not(:disabled) {
background: var(--color-surface-soft, #efe9de);
color: var(--color-ink, #141413);
}
.toggle-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.card-date {
font-size: 11px;
color: var(--color-muted, #b8b2a6);

42
app/pages/agent-documents/[id].vue

@ -17,6 +17,7 @@ interface AgentDocumentDetail {
tags: string[]
sessionId: string | null
agentId: number | null
disabled: boolean
createdAt: string
updatedAt: string
}
@ -44,6 +45,24 @@ const confirmShow = ref(false)
const agents = ref<AgentItem[]>([])
const scopeSaving = ref(false)
const toggling = ref(false)
async function toggleDisabled() {
if (!doc.value) return
toggling.value = true
try {
await request(`/api/agent-documents/${route.params.id}`, {
method: 'PATCH',
body: { disabled: !doc.value.disabled },
})
$toast.success(doc.value.disabled ? '已启用' : '已禁用')
await fetchDocument()
} catch (e: any) {
$toast.error(e?.data?.message || e?.message || '操作失败')
} finally {
toggling.value = false
}
}
async function fetchAgents() {
try {
@ -180,6 +199,14 @@ onMounted(() => {
<div class="detail-header">
<NuxtLink to="/agent-documents" class="back-link">← 返回列表</NuxtLink>
<div v-if="loggedIn" class="header-actions">
<button
v-if="doc.type === 'memory'"
class="action-btn"
:disabled="toggling"
@click="toggleDisabled"
>
{{ toggling ? '处理中…' : (doc.disabled ? '启用' : '禁用') }}
</button>
<button class="action-btn" @click="openEdit">编辑</button>
<button class="action-btn danger" @click="confirmShow = true">删除</button>
</div>
@ -189,6 +216,7 @@ onMounted(() => {
<span class="type-badge" :class="doc.type">
{{ doc.type === 'document' ? '文档' : '记忆' }}
</span>
<span v-if="doc.type === 'memory' && doc.disabled" class="disabled-badge">已禁用</span>
<span class="meta-date">
创建于 {{ new Date(doc.createdAt).toLocaleString('zh-CN') }}
</span>
@ -349,11 +377,25 @@ onMounted(() => {
color: #cc785c;
}
.action-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.action-btn.danger:hover {
border-color: #c64545;
color: #c64545;
}
.disabled-badge {
font-size: 11px;
padding: 2px 8px;
border-radius: 4px;
font-weight: 500;
background: #fde8e8;
color: #c0392b;
}
.detail-meta {
display: flex;
align-items: center;

11
app/pages/agent-documents/index.vue

@ -13,6 +13,7 @@ interface AgentDocumentItem {
type: 'memory' | 'document'
summary: string | null
tags: string[]
disabled: boolean
createdAt: string
updatedAt: string
}
@ -150,6 +151,7 @@ onMounted(() => {
<span class="type-badge" :class="item.type">
{{ item.type === 'document' ? '文档' : '记忆' }}
</span>
<span v-if="item.type === 'memory' && item.disabled" class="disabled-badge">已禁用</span>
<span class="card-date">{{ new Date(item.updatedAt).toLocaleDateString('zh-CN') }}</span>
<span v-if="item.tags && item.tags.length > 0" class="card-tags">
<span v-for="tag in item.tags" :key="tag" class="tag-chip">{{ tag }}</span>
@ -340,6 +342,15 @@ onMounted(() => {
color: #1a5276;
}
.disabled-badge {
font-size: 11px;
padding: 2px 8px;
border-radius: 4px;
font-weight: 500;
background: #fde8e8;
color: #c0392b;
}
.card-date {
font-size: 12px;
color: #b8b2a6;

BIN
packages/drizzle-pkg/db.sqlite

Binary file not shown.

1
packages/drizzle-pkg/lib/schema/agent-document.ts

@ -17,6 +17,7 @@ export const agentDocuments = sqliteTable(
content: text("content").notNull(),
summary: text("summary"),
tags: text("tags"),
disabled: integer("disabled", { mode: "boolean" }).notNull().default(false),
createdAt: integer("created_at", { mode: "timestamp_ms" })
.defaultNow()
.notNull(),

1
packages/drizzle-pkg/migrations/0005_chunky_rick_jones.sql

@ -0,0 +1 @@
ALTER TABLE `agent_documents` ADD `disabled` integer DEFAULT false NOT NULL;

2798
packages/drizzle-pkg/migrations/meta/0005_snapshot.json

File diff suppressed because it is too large

7
packages/drizzle-pkg/migrations/meta/_journal.json

@ -36,6 +36,13 @@
"when": 1786459321606,
"tag": "0004_public_dracula",
"breakpoints": true
},
{
"idx": 5,
"version": "6",
"when": 1786773570565,
"tag": "0005_chunky_rick_jones",
"breakpoints": true
}
]
}

2
server/api/agent-documents/[id].patch.ts

@ -9,6 +9,7 @@ const updateSchema = z.object({
content: z.string().max(50000).optional(),
tags: z.array(z.string()).optional(),
agentSlug: z.string().nullable().optional(),
disabled: z.boolean().optional(),
});
export default defineWrappedResponseHandler(async (event) => {
@ -36,6 +37,7 @@ export default defineWrappedResponseHandler(async (event) => {
content: body.content,
tags: body.tags,
agentId,
disabled: body.disabled,
});
if (!updated) return R.throwError(404, "文档不存在或无权访问", null);

6
server/service/agent-document/index.ts

@ -25,6 +25,7 @@ export interface UpdateDocumentInput {
content?: string;
tags?: string[] | null;
agentId?: number | null;
disabled?: boolean;
}
export interface ListDocumentsOptions {
@ -152,6 +153,7 @@ export async function listDocuments(
title: agentDocuments.title,
summary: agentDocuments.summary,
tags: agentDocuments.tags,
disabled: agentDocuments.disabled,
createdAt: agentDocuments.createdAt,
updatedAt: agentDocuments.updatedAt,
})
@ -198,6 +200,9 @@ export async function updateDocument(
if (input.agentId !== undefined) {
updateData.agentId = input.agentId;
}
if (input.disabled !== undefined) {
updateData.disabled = input.disabled;
}
if (Object.keys(updateData).length === 0) {
return existing;
@ -233,6 +238,7 @@ export async function getMemoryContext(
const conditions = [
eq(agentDocuments.userId, userId),
eq(agentDocuments.type, "memory"),
eq(agentDocuments.disabled, false),
];
if (agentId !== undefined && agentId !== null) {

Loading…
Cancel
Save