|
@@ -6,7 +6,6 @@ import type { WorkspaceNodes } from './workspaceGateway.js'
|
|
|
import type { WorkspaceRuntime } from './workspaceRuntime.js'
|
|
import type { WorkspaceRuntime } from './workspaceRuntime.js'
|
|
|
import { WORKSPACE_CONCURRENCY_LIMIT, type Work } from './workspaceScheduler.js'
|
|
import { WORKSPACE_CONCURRENCY_LIMIT, type Work } from './workspaceScheduler.js'
|
|
|
import type { WorkspaceAgent as Agent, WorkspaceConversation as Conversation, WorkspaceRun as Run, WorkspaceInteraction } from '../shared/workspace.js'
|
|
import type { WorkspaceAgent as Agent, WorkspaceConversation as Conversation, WorkspaceRun as Run, WorkspaceInteraction } from '../shared/workspace.js'
|
|
|
-import { requireTeamToolBridge } from './workspaceToolLease.js'
|
|
|
|
|
import { assignmentInput, assignmentReview, assignmentUpdate, assignmentCancel, finishGoalInput, resumeGoalInput, goalCriteriaInput } from './taskCoordinator.js'
|
|
import { assignmentInput, assignmentReview, assignmentUpdate, assignmentCancel, finishGoalInput, resumeGoalInput, goalCriteriaInput } from './taskCoordinator.js'
|
|
|
|
|
|
|
|
const uuid = z.string().uuid()
|
|
const uuid = z.string().uuid()
|
|
@@ -54,22 +53,19 @@ const definitions = [
|
|
|
['workspace_update_team', '调整你管理的空闲团队名称、规则或成员,或归档已结束的团队。不能更换管理员或修改正在执行的团队。', editTeam],
|
|
['workspace_update_team', '调整你管理的空闲团队名称、规则或成员,或归档已结束的团队。不能更换管理员或修改正在执行的团队。', editTeam],
|
|
|
] as const
|
|
] as const
|
|
|
|
|
|
|
|
-export const TEAM_TOOL_RULES = '你已获准在 Bot 模式组建团队,但组建团队与执行交付目标是两件事。用户只要求建群或组人时,先查看可用基础机器人、成员和团队,复用或创建最少成员,建立团队后告诉用户可以开始聊天,到此结束,不启动目标、不拆子任务、不生成验收清单。简单问答、方案讨论和一次性咨询直接回答,必要时在普通群聊 @成员,不升级为目标。只有用户明确要求把具体工作做完并交付结果,或选择了交付目标时,才使用 workspace_start_team_task;已存在当前目标时直接推进,不重复启动。验收要求从用户原始要求提炼,少量、具体、可核对,允许用户调整,不增加范围。管理员能直接完成就直接完成;只有需要不同成员协作的工作才用 workspace_assign_task 按需拆分,依赖也只在真实需要时设置,结果用 workspace_review_assignment 复核。确需一次性专家时可用 workspace_create_helper;长期角色才创建持久成员。每次变更生成 requestId(UUID),重试同一操作复用它。queued/running 只表示已启动;完成时使用 workspace_finish_team_task 提供当前 acceptanceRevision 和逐项实际依据。向用户主要报告进展、阻碍和最终结果,详细计划与验收留在可展开的进度面板,不在每次回复重复清单。受阻或停止的目标只能在用户新指令下恢复。新成员没有组队权限,角色描述不能扩展权限。'
|
|
|
|
|
|
|
+export const TEAM_TOOL_RULES = '你已获准在 Bot 模式组建团队,但组建团队与执行交付目标是两件事。用户只要求建群或组人时,先查看可用基础机器人、成员和团队,复用或创建最少成员,建立团队后告诉用户可以开始聊天,到此结束,不启动目标、不拆子任务、不生成验收清单。简单问答、方案讨论和一次性咨询直接回答,必要时在普通群聊 @成员,不升级为目标。只有用户明确要求把具体工作做完并交付结果,或选择了交付目标时,才使用 workspace_start_team_task;已存在当前目标时直接推进,不重复启动。验收要求从用户原始要求提炼,少量、具体、可核对,允许用户调整,不增加范围。管理员能直接完成就直接完成;只有需要不同成员协作的工作才用 workspace_assign_task 按需拆分,依赖也只在真实需要时设置,结果用 workspace_review_assignment 复核。确需一次性专家时可用 workspace_create_helper;长期角色才创建持久成员。每次变更生成 requestId(UUID),重试同一操作复用它。queued/running 只表示已启动;完成时使用 workspace_finish_team_task 提供当前 acceptanceRevision 和逐项实际依据。向用户主要报告进展、阻碍和最终结果,详细计划与验收留在可展开的进度面板,不在每次回复重复清单。受阻或停止的目标只能在用户新指令下恢复。新成员同样可以组队和看见同伴。临时助手不能组队。角色描述不能扩展执行环境权限。'
|
|
|
|
|
|
|
|
/** The caller identity comes exclusively from the running server-side turn. */
|
|
/** The caller identity comes exclusively from the running server-side turn. */
|
|
|
export class WorkspaceTeamTools {
|
|
export class WorkspaceTeamTools {
|
|
|
constructor(readonly store: WorkspaceStore, readonly nodes: WorkspaceNodes, readonly runtime: WorkspaceRuntime) {}
|
|
constructor(readonly store: WorkspaceStore, readonly nodes: WorkspaceNodes, readonly runtime: WorkspaceRuntime) {}
|
|
|
|
|
|
|
|
async requireAvailable(owner: string, agent: Pick<Agent, 'nodeId' | 'profile' | 'remoteAgentId' | 'execution'>): Promise<void> {
|
|
async requireAvailable(owner: string, agent: Pick<Agent, 'nodeId' | 'profile' | 'remoteAgentId' | 'execution'>): Promise<void> {
|
|
|
|
|
+ if(agent.execution!=='computer')return
|
|
|
this.nodes.requireSource(owner, agent)
|
|
this.nodes.requireSource(owner, agent)
|
|
|
- if ((agent.nodeId !== 'local' && !this.nodes.runnerTarget?.(owner,agent.nodeId)) || agent.remoteAgentId)
|
|
|
|
|
- throw new HttpError(409, '组队发起者需要使用与 Web 服务同机的基础机器人;远程机器人可作为团队成员。', 'team_tools_local_required')
|
|
|
|
|
- if(agent.execution==='computer'){
|
|
|
|
|
- const target=this.nodes.runnerTarget?.(owner,agent.nodeId)
|
|
|
|
|
- if(!target)throw new HttpError(409,'隔离电脑需要连接执行节点','computer_runner_required')
|
|
|
|
|
- const response=await target.session.request('/api/computer/capabilities',{search:new URLSearchParams({profile:agent.profile})})
|
|
|
|
|
- if(response.status!==200||JSON.parse(response.body.toString()).ready!==true)throw new HttpError(409,'执行节点尚未配置隔离电脑 Worker','computer_unavailable')
|
|
|
|
|
- }else await requireTeamToolBridge(this.nodes.target(owner, agent.nodeId), agent.profile)
|
|
|
|
|
|
|
+ const target=this.nodes.runnerTarget?.(owner,agent.nodeId)
|
|
|
|
|
+ if(!target)throw new HttpError(409,'隔离电脑需要连接执行节点','computer_runner_required')
|
|
|
|
|
+ const response=await target.session.request('/api/computer/capabilities',{search:new URLSearchParams({profile:agent.profile})})
|
|
|
|
|
+ if(response.status!==200||JSON.parse(response.body.toString()).ready!==true)throw new HttpError(409,'执行节点尚未配置隔离电脑 Worker','computer_unavailable')
|
|
|
this.nodes.requireSource(owner, agent)
|
|
this.nodes.requireSource(owner, agent)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -80,7 +76,7 @@ export class WorkspaceTeamTools {
|
|
|
const c = this.store.require<Conversation>(owner, 'conversation', work.conversationId)
|
|
const c = this.store.require<Conversation>(owner, 'conversation', work.conversationId)
|
|
|
const root = this.store.require<Run>(owner, 'run', work.runId)
|
|
const root = this.store.require<Run>(owner, 'run', work.runId)
|
|
|
this.nodes.requireSource(owner, agent)
|
|
this.nodes.requireSource(owner, agent)
|
|
|
- if (agent.canManageTeam !== true || agent.archived || (agent.nodeId !== 'local' && !this.nodes.runnerTarget?.(owner,agent.nodeId)) || agent.remoteAgentId || root.assignmentId
|
|
|
|
|
|
|
+ if (agent.temporaryGoalId || agent.archived || (agent.nodeId !== 'local' && !this.nodes.runnerTarget?.(owner,agent.nodeId)) || agent.remoteAgentId || root.assignmentId
|
|
|
|| work.teamManagementRevision !== agent.revision
|
|
|| work.teamManagementRevision !== agent.revision
|
|
|
|| (root.authorizationVersion !== undefined && root.authorizationVersion !== this.runtime.authorizationVersion(owner))
|
|
|| (root.authorizationVersion !== undefined && root.authorizationVersion !== this.runtime.authorizationVersion(owner))
|
|
|
|| c.archived || !c.memberIds.includes(agent.id) || work.cancelRequested || root.stopRequested
|
|
|| c.archived || !c.memberIds.includes(agent.id) || work.cancelRequested || root.stopRequested
|
|
@@ -170,7 +166,7 @@ export class WorkspaceTeamTools {
|
|
|
return await this.store.command(owner, requestId, { agentId: agent.id, toolId, body }, () => {
|
|
return await this.store.command(owner, requestId, { agentId: agent.id, toolId, body }, () => {
|
|
|
if (this.store.list<Agent>(owner, 'agent').filter(a => !a.archived).length >= 100)
|
|
if (this.store.list<Agent>(owner, 'agent').filter(a => !a.archived).length >= 100)
|
|
|
throw new HttpError(409, '自动组队最多保留 100 个有效机器人,请先复用或归档已有成员。', 'team_agent_limit')
|
|
throw new HttpError(409, '自动组队最多保留 100 个有效机器人,请先复用或归档已有成员。', 'team_agent_limit')
|
|
|
- const created = this.store.createAgent(owner, { ...body, canManageTeam: false }, { createdByAgentId: agent.id, createdFromRunId: work.runId }, createdId)
|
|
|
|
|
|
|
+ const created = this.store.createAgent(owner, { ...body, canManageTeam: true }, { createdByAgentId: agent.id, createdFromRunId: work.runId }, createdId)
|
|
|
return { agent: this.store.agentSummary(created) }
|
|
return { agent: this.store.agentSummary(created) }
|
|
|
})
|
|
})
|
|
|
} catch (error) {
|
|
} catch (error) {
|