agentworkshop 0.5.6 → 0.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.AgentWorkShop/prompts/host-tools.json +31 -0
- package/.output/.AgentWorkShop/prompts/host-tools.json +31 -0
- package/.output/nitro.json +1 -1
- package/.output/public/_nuxt/builds/latest.json +1 -1
- package/.output/public/_nuxt/builds/meta/998b4cce-8563-44e5-b0ef-ff3d71a8480f.json +1 -0
- package/.output/server/chunks/_/nitro.mjs +835 -668
- package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +5 -2
- package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs.map +1 -1
- package/.output/server/package.json +1 -1
- package/package.json +1 -1
- package/scripts/_dbg-cross-team-visibility-e2e.mjs +129 -0
- package/scripts/_dbg-overview-probe.sh +31 -0
- package/server/api/workshop/agent-tools/invoke.post.ts +8 -1
- package/server/data/daqs.json +91 -91
- package/server/data/dcw-lines.json +7 -0
- package/server/data/dcw-products.json +7 -0
- package/server/data/dcw-rollback.json +114 -1
- package/server/data/dcw-runs.json +27 -18
- package/server/data/dcw-writes.json +48 -0
- package/server/data/dcws.json +21 -0
- package/server/data/line-runs.json +23 -23
- package/server/services/workshop/agents/agent-interface.ts +20 -0
- package/server/services/workshop/agents/omp-agent.ts +28 -0
- package/server/services/workshop/db/memory.repo.ts +26 -0
- package/server/services/workshop/runtime/manager.ts +127 -0
- package/.output/public/_nuxt/builds/meta/d50c6ec2-801c-4ba2-97d8-a4db401b702c.json +0 -1
|
@@ -978,6 +978,8 @@ export class AgentChannelManager {
|
|
|
978
978
|
reassignTask: (taskId, toAgentId) => this.reassignTask(channelId, agent.id, taskId, toAgentId),
|
|
979
979
|
sendMessage: input => this.sendA2A(channelId, agent.id, input),
|
|
980
980
|
sendCrossChannelMessage: input => this.sendCrossChannelMessage(channelId, agent.id, input),
|
|
981
|
+
listOtherTeams: () => this.listOtherTeamsOverview(channelId, agent.id),
|
|
982
|
+
searchOtherTeamsMemory: input => this.recallOtherTeamsMemory(channelId, agent.id, input),
|
|
981
983
|
refuseTask: (taskId, reason) => this.refuseTask(channelId, agent.id, taskId, reason),
|
|
982
984
|
pollMailbox: limit => this.pollMailbox(channelId, agent.id, limit),
|
|
983
985
|
waitMailbox: (limit, waitMs) => this.waitMailbox(channelId, agent.id, limit ?? 10, waitMs ?? 0),
|
|
@@ -2538,6 +2540,131 @@ export class AgentChannelManager {
|
|
|
2538
2540
|
}
|
|
2539
2541
|
}
|
|
2540
2542
|
|
|
2543
|
+
/**
|
|
2544
|
+
* 跨团队可见性(仅 lead):其他 channel 的场景任务概览(同主、启用)。
|
|
2545
|
+
* 协同工作流的第一步——先看别的团队在做什么/做过什么,再决定是否发信请求协作。
|
|
2546
|
+
*/
|
|
2547
|
+
listOtherTeamsOverview(channelId: string, agentId: string): Array<{
|
|
2548
|
+
channelId: string, name: string, description: string, leadName: string | null,
|
|
2549
|
+
activeTasks: Array<{ id: string, title: string, state: string }>,
|
|
2550
|
+
recentCompleted: Array<{ title: string }>,
|
|
2551
|
+
}> {
|
|
2552
|
+
this.requireMember(channelId, agentId)
|
|
2553
|
+
const sender = this.deps.repos.channelAgents.findByChannelAgent(channelId, agentId)
|
|
2554
|
+
if (!sender || sender.role !== 'lead') {
|
|
2555
|
+
throw new AppError(403, 'ROLE_FORBIDDEN', `团队任务概览仅限 Leader(${sender?.name ?? agentId} 是 ${sender?.role ?? '非成员'})`)
|
|
2556
|
+
}
|
|
2557
|
+
const terminal = new Set(['COMPLETED', 'FAILED', 'CANCELED'])
|
|
2558
|
+
return this.otherSameOwnerChannels(channelId).map((c) => {
|
|
2559
|
+
const tasks = this.deps.repos.tasks.listByChannel(c.id)
|
|
2560
|
+
const leadRow = c.leadAgentId ? this.deps.repos.channelAgents.findById(c.leadAgentId) : undefined
|
|
2561
|
+
return {
|
|
2562
|
+
channelId: c.id,
|
|
2563
|
+
name: c.name,
|
|
2564
|
+
description: c.description ?? '',
|
|
2565
|
+
leadName: leadRow?.name ?? null,
|
|
2566
|
+
/** 团队共享域知识量:>0 说明该队有可检索的作业结论(search_other_teams_memory) */
|
|
2567
|
+
sharedMemories: this.deps.repos.memories.countTeamShared(c.id),
|
|
2568
|
+
activeTasks: tasks
|
|
2569
|
+
.filter(t => !terminal.has(t.state))
|
|
2570
|
+
.map(t => ({ id: t.id, title: t.title, state: t.state })),
|
|
2571
|
+
recentCompleted: tasks
|
|
2572
|
+
.filter(t => t.state === 'COMPLETED')
|
|
2573
|
+
.slice(0, 3)
|
|
2574
|
+
.map(t => ({ title: t.title })),
|
|
2575
|
+
}
|
|
2576
|
+
})
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2579
|
+
/**
|
|
2580
|
+
* 跨团队共享记忆检索(lead/worker 皆可,只读):其他 channel 的 __team__ 公共域。
|
|
2581
|
+
* 全员可见——worker 由此知道别的团队做过什么;发现相关经验/结论可直接复用,
|
|
2582
|
+
* 无需跨 channel 发信;查无所得而有协作必要时,再由 lead 发起跨 channel 通信。
|
|
2583
|
+
*/
|
|
2584
|
+
recallOtherTeamsMemory(channelId: string, agentId: string, input: { query: string, limit?: number }): Array<{
|
|
2585
|
+
channelId: string, channelName: string, title: string, content: string, importance: number, createdAt: string,
|
|
2586
|
+
}> {
|
|
2587
|
+
this.requireMember(channelId, agentId)
|
|
2588
|
+
const q = input.query.trim()
|
|
2589
|
+
if (!q) return []
|
|
2590
|
+
const others = this.otherSameOwnerChannels(channelId)
|
|
2591
|
+
if (others.length === 0) return []
|
|
2592
|
+
const matchQuery = segmentCJK(q).split(/\s+/).filter(Boolean).join(' OR ')
|
|
2593
|
+
const rows = this.deps.repos.memories.searchTeamSharedAcross(
|
|
2594
|
+
matchQuery,
|
|
2595
|
+
others.map(c => c.id),
|
|
2596
|
+
Math.min(Math.max(input.limit ?? 5, 1), 20),
|
|
2597
|
+
)
|
|
2598
|
+
// 触摸命中行(access_count/last_accessed_at):与 recallRows 同信号,强化后续召回排序
|
|
2599
|
+
for (const r of rows) this.deps.repos.memories.touch(r.id)
|
|
2600
|
+
return rows.map(r => ({
|
|
2601
|
+
channelId: r.channelId,
|
|
2602
|
+
channelName: others.find(c => c.id === r.channelId)?.name ?? r.channelId,
|
|
2603
|
+
title: r.title,
|
|
2604
|
+
content: unsegmentCJK(r.content).slice(0, 400),
|
|
2605
|
+
importance: r.importance,
|
|
2606
|
+
createdAt: r.createdAt,
|
|
2607
|
+
}))
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2610
|
+
/** 同主且启用的其他 channel 列表(跨团队可见性的作用域) */
|
|
2611
|
+
private otherSameOwnerChannels(channelId: string): ChannelRow[] {
|
|
2612
|
+
const self = this.deps.repos.channels.findById(channelId)
|
|
2613
|
+
return this.deps.repos.channels.list().filter(c =>
|
|
2614
|
+
c.id !== channelId
|
|
2615
|
+
&& c.enabled === 1
|
|
2616
|
+
&& (self?.ownerUserId == null || c.ownerUserId == null || c.ownerUserId === self.ownerUserId))
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2619
|
+
/**
|
|
2620
|
+
* 工具桥(协作工具族):按 agentId 定位 channel 并调用其 workspace 方法。
|
|
2621
|
+
* 与工业工具桥同一服务层,供 REST 直调(测试/运维/控制台)。
|
|
2622
|
+
*/
|
|
2623
|
+
invokeAgentWorkspaceTool(agentId: string, tool: string, args: Record<string, unknown> = {}): { text: string, isError?: boolean } {
|
|
2624
|
+
const row = this.deps.repos.channelAgents.findById(agentId)
|
|
2625
|
+
if (!row || row.enabled !== 1) throw new AppError(404, 'NOT_FOUND', `agent 不存在或已停用: ${agentId}`)
|
|
2626
|
+
const ws = this.ensureAgentRuntime(row.channelId, agentId)?.workspace
|
|
2627
|
+
if (!ws) throw new AppError(400, 'AGENT_NOT_READY', `agent 运行时未装配: ${agentId}`)
|
|
2628
|
+
switch (tool) {
|
|
2629
|
+
case 'list_other_teams': {
|
|
2630
|
+
const teams = ws.listOtherTeams()
|
|
2631
|
+
if (teams.length === 0) return { text: '当前没有其他团队(或均未启用)。' }
|
|
2632
|
+
const text = teams.map((t) => {
|
|
2633
|
+
const active = t.activeTasks.length > 0
|
|
2634
|
+
? t.activeTasks.map(x => `「${x.title}」(${x.state})`).join('、')
|
|
2635
|
+
: '无进行中任务'
|
|
2636
|
+
const done = t.recentCompleted.length > 0
|
|
2637
|
+
? t.recentCompleted.map(x => `「${x.title}」`).join('、')
|
|
2638
|
+
: '无'
|
|
2639
|
+
const mem = t.sharedMemories > 0 ? `共享记忆 ${t.sharedMemories} 条(可检索)` : '暂无共享记忆'
|
|
2640
|
+
return `- ${t.name}${t.description ? `(${t.description})` : ''} · lead=${t.leadName ?? '?'} · ${mem}\n 进行中: ${active}\n 近期完成: ${done}\n channel_id: ${t.channelId}`
|
|
2641
|
+
}).join('\n')
|
|
2642
|
+
return { text: `其他团队概览:\n${text}\n(需要协作时用 send_cross_channel_message 向对应团队 Leader 发信;查具体知识用 search_other_teams_memory)` }
|
|
2643
|
+
}
|
|
2644
|
+
case 'search_other_teams_memory': {
|
|
2645
|
+
const query = String(args.query ?? '')
|
|
2646
|
+
if (!query) return { text: '缺少 query', isError: true }
|
|
2647
|
+
const rows = ws.searchOtherTeamsMemory({ query, limit: Number(args.limit ?? 5) })
|
|
2648
|
+
if (rows.length === 0) return { text: `其他团队的共享记忆中没有命中「${query}」的内容。` }
|
|
2649
|
+
const text = rows.map(r =>
|
|
2650
|
+
`- [${r.channelName}] 「${r.title}」(${r.createdAt.slice(0, 10)}): ${r.content}`).join('\n')
|
|
2651
|
+
return { text: `其他团队共享记忆命中 ${rows.length} 条:\n${text}` }
|
|
2652
|
+
}
|
|
2653
|
+
case 'send_cross_channel_message': {
|
|
2654
|
+
if (!args.to_channel_id || !args.message) return { text: '缺少 to_channel_id 或 message', isError: true }
|
|
2655
|
+
const r = ws.sendCrossChannelMessage({
|
|
2656
|
+
toChannelId: String(args.to_channel_id),
|
|
2657
|
+
parts: [{ text: String(args.message) }],
|
|
2658
|
+
requireReply: args.require_reply === true,
|
|
2659
|
+
inReplyTo: typeof args.in_reply_to === 'string' ? args.in_reply_to : undefined,
|
|
2660
|
+
})
|
|
2661
|
+
return { text: `跨 Channel 消息已送达「${r.toChannelName}」的 Leader(channel=${r.toChannelId}, lead=${r.toLeadAgentId.slice(0, 8)}),消息 id=${r.messageId.slice(0, 8)}。` }
|
|
2662
|
+
}
|
|
2663
|
+
default:
|
|
2664
|
+
throw new AppError(400, 'BAD_REQUEST', `工具桥不支持该协作工具: ${tool}`)
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2541
2668
|
/** 阻塞长轮询(poll_messages):到信即时唤醒,250ms 兜底重查 */
|
|
2542
2669
|
async waitMailbox(channelId: string, callerAgentId: string, limit: number, waitMs: number): Promise<A2AMessage[]> {
|
|
2543
2670
|
this.requireMember(channelId, callerAgentId)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"id":"d50c6ec2-801c-4ba2-97d8-a4db401b702c","timestamp":1788350746387,"prerendered":[]}
|