@x-otto/orchestrator 0.0.1-alpha.0

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/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # @x-otto/orchestrator
2
+
3
+ ## 模块定位
4
+
5
+ 管理多 Agent 任务的创建、调度、重试与生命周期。提供 TaskStore + TaskExecutor + CircuitBreaker 组合。
6
+
7
+ ## 核心功能
8
+
9
+ | 模块 | 功能 |
10
+ | ----------------- | -------------------------------------------------------------- |
11
+ | TaskStore | 任务 CRUD + 状态追踪(pending/running/completed/failed) |
12
+ | TaskExecutor | 同步/后台混合调度 + 并发限制 |
13
+ | RetryPolicy | 指数退避 + 抖动重试策略 |
14
+ | CircuitBreaker | 断路器(CLOSED/OPEN/HALF_OPEN) |
15
+ | Orchestrator | 业务级 API(dispatchTask/callAgent/getTask/updateTask) |
16
+ | BackgroundManager | 后台异步任务生命周期 |
17
+
18
+ ## 安装
19
+
20
+ ```bash
21
+ pnpm add @x-otto/orchestrator
22
+ ```
23
+
24
+ ## 快速开始
25
+
26
+ ```ts
27
+ import { Orchestrator, createTaskStore } from '@x-otto/orchestrator'
28
+
29
+ const store = createTaskStore({ kind: 'in-memory' })
30
+ const orchestrator = new Orchestrator({ store, maxConcurrency: 5 })
31
+
32
+ const taskId = await orchestrator.dispatchTask({
33
+ agent: 'explore',
34
+ prompt: 'Search for all unused imports in src/',
35
+ })
36
+
37
+ // 后台模式
38
+ await orchestrator.dispatchTask({ ...opts, mode: 'background' })
39
+ const result = await orchestrator.waitFor(taskId)
40
+ ```
41
+
42
+ ## 目录概览
43
+
44
+ ```
45
+ src/
46
+ types.ts # 核心类型
47
+ task-store.ts # 任务存储
48
+ task-executor.ts # 执行引擎
49
+ retry-policy.ts # 重试策略
50
+ circuit-breaker.ts # 断路器
51
+ orchestrator.ts # 顶层协调器
52
+ background-manager.ts # 后台管理
53
+ index.ts
54
+ tests/ # 7 个测试文件
55
+ ```
56
+
57
+ ## 开发命令
58
+
59
+ ```bash
60
+ pnpm --filter @x-otto/orchestrator build
61
+ pnpm --filter @x-otto/orchestrator typecheck
62
+ pnpm --filter @x-otto/orchestrator clean
63
+ ```
64
+
65
+ ## 关联包
66
+
67
+ `@x-otto/agent`、`@x-otto/shared`、`@x-otto/env`
@@ -0,0 +1,752 @@
1
+ import { CallAgent, CancelBackground, GetBackgroundOutput, GetTask, ListTasks, ModelSlotName, SessionMode, TaskDispatch, TaskMode, TaskStatus, TaskStatus as TaskStatus$1, UpdateTask, WorkflowOptions, WorkflowOptions as WorkflowOptions$1 } from "@x-otto/orchestration-contracts";
2
+ import { AgentError } from "@x-otto/shared";
3
+ import * as _$_x_otto_hooks0 from "@x-otto/hooks";
4
+ import { HookRegistry } from "@x-otto/hooks";
5
+ import { Model, ThinkingLevel } from "@x-otto/ai";
6
+ import { AgentMessage } from "@x-otto/hook-contracts";
7
+ import { AgentTool } from "@x-otto/interchange";
8
+
9
+ //#region src/retry.d.ts
10
+ interface RetryConfig {
11
+ enabled: boolean;
12
+ maxAttempts: number;
13
+ backoffMs: number;
14
+ backoffMultiplier: number;
15
+ }
16
+ declare class RetryPolicy {
17
+ private readonly config;
18
+ constructor(config?: Partial<RetryConfig>);
19
+ shouldRetry(attempt: number): boolean;
20
+ getBackoff(attempt: number): number;
21
+ static fromWorkflowOptions(wf?: WorkflowOptions$1): RetryPolicy;
22
+ }
23
+ interface CircuitBreakerConfig {
24
+ enabled: boolean;
25
+ failureThreshold: number;
26
+ resetTimeoutMs: number;
27
+ }
28
+ declare class CircuitBreaker {
29
+ private readonly enabled;
30
+ private readonly failureThreshold;
31
+ private readonly resetTimeoutMs;
32
+ private consecutiveFailures;
33
+ private openedAt;
34
+ constructor(config?: Partial<CircuitBreakerConfig>);
35
+ isOpen(): boolean;
36
+ success(): void;
37
+ failure(): void;
38
+ reset(): void;
39
+ }
40
+ //#endregion
41
+ //#region src/task-store.d.ts
42
+ declare class TaskStore {
43
+ private readonly tasks;
44
+ private nextId;
45
+ /**
46
+ * 容量上限(默认 1000)。store 只收 task_delegate 落库的真任务,但终态任务只增不减——
47
+ * 故加「终态优先 LRU 驱逐」兜底治裸 Map 无界增长(确定性、无时钟依赖,区别于 TTL)。
48
+ */
49
+ private readonly maxStoredTasks;
50
+ constructor(maxStoredTasks?: number);
51
+ private generateId;
52
+ create(input: TaskInput): Promise<Task>;
53
+ /**
54
+ * 容量回收:新建前若已达上限,按「终态优先 + 最旧先弃」驱逐至腾出一席。
55
+ * 驱逐优先级:仅终态(completed/failed/cancelled),按 completedAt ?? createdAt 升序(最旧先弃)。
56
+ * pending/running 在飞任务绝不驱逐——若只剩在飞仍超上限,则越界保活 + warn(绝不丢在飞的活儿)。
57
+ */
58
+ private evictForCapacity;
59
+ get(id: string): Promise<Task | undefined>;
60
+ list(filter?: {
61
+ status?: TaskStatus;
62
+ }): Promise<Task[]>;
63
+ update(id: string, patch: Partial<Pick<Task, 'status' | 'output' | 'error' | 'attempts' | 'completedAt' | 'sessionId'>>): Promise<void>;
64
+ delete(id: string): Promise<boolean>;
65
+ }
66
+ //#endregion
67
+ //#region src/executor.d.ts
68
+ interface RunSessionOptions {
69
+ prompt: string;
70
+ sessionId?: string;
71
+ sessionMode: 'ephemeral' | 'sticky';
72
+ agentName?: string;
73
+ slot?: TaskInput['slot'];
74
+ /** 显式模型 id(subagent 按能力选型)——优先于 slot。 */
75
+ model?: string;
76
+ /** 任务类别(task_delegate.category)——委派子会话据此走 category→slot 智能默认。 */
77
+ category?: string;
78
+ /** 子会话承接的委托深度——使其 toolCtx.depth = 该深度,递归闭合护栏。 */
79
+ depth?: number;
80
+ /**
81
+ * 任务锚点:宿主据此登记 taskId→活动会话,使 cancel(updateTask/
82
+ * background cancel → abortTask 回调)能中断正在执行的子会话。callAgent 等
83
+ * 非任务路径不携带。
84
+ */
85
+ taskId?: string;
86
+ /** 父会话 AbortSignal(旁路,不进 TaskInput/store)——串联中断 in-flight 子会话。 */
87
+ signal?: AbortSignal;
88
+ /**
89
+ * Phase 0(task_delegate/job 统一):只读委托——宿主据此从子会话工具集剔除文件改动工具
90
+ * (edit/write/lsp_rename/bash)。background 委托脱离父对话且无审计边界,禁其改主 worktree;
91
+ * 改动型后台活走 /job(worktree 隔离 + diff 审计)。详见 docs/design/task-delegate-job-unification.md。
92
+ */
93
+ readOnly?: boolean;
94
+ promptContext?: {
95
+ taskTitle?: string;
96
+ taskDescription?: string;
97
+ taskFiles?: string[];
98
+ };
99
+ systemPrompt?: string;
100
+ tools?: AgentToolDef[];
101
+ extraTools?: AgentToolDef[];
102
+ thinkingLevel?: ThinkingLevel$1;
103
+ maxTokens?: number;
104
+ temperature?: number;
105
+ maxToolTurns?: number;
106
+ }
107
+ interface RunSessionResult {
108
+ text: string;
109
+ sessionId: string;
110
+ tokenUsage?: {
111
+ input: number;
112
+ output: number;
113
+ cacheRead: number;
114
+ };
115
+ durationMs: number;
116
+ /** swarm member turn: 完整消息历史(handoff 策略需要检查 tool_calls)。 */
117
+ messages?: unknown[];
118
+ /** swarm member turn: leaf 捕获的 handoff intent(RFC-332 M1 纯数据回传)。 */
119
+ handoff?: {
120
+ from: string;
121
+ to: string;
122
+ reason: string;
123
+ };
124
+ }
125
+ //#endregion
126
+ //#region src/types.d.ts
127
+ /** 工具定义(本地 minimal type,避免 orchestrator 核心依赖 @x-otto/interchange)。 */
128
+ interface AgentToolDef {
129
+ name: string;
130
+ description: string;
131
+ parameters: Record<string, unknown>;
132
+ }
133
+ /** handoff 目标的纯数据信息(RFC-332 M1:跨边界只传可序列化数据)。 */
134
+ interface HandoffTargetInfo {
135
+ id: string;
136
+ name: string;
137
+ description: string;
138
+ }
139
+ /**
140
+ * RFC-332 M1:swarm core 工具的纯数据描述符。
141
+ *
142
+ * `extraTools`(AgentToolDef 元数据投影)无法承载 core 工具的执行闭包——旧路径在 leaf
143
+ * 被补成 throw stub(模型可见但必坏)。本描述符替代之:orchestrator 策略只声明
144
+ * 「请 leaf 暴露哪个已注册 core 能力 + 可序列化上下文」,coding leaf 的受限 core
145
+ * resolver 据此构造真实 `AgentTool`。描述符不得含 execute/函数/闭包。
146
+ *
147
+ * 当前唯一注册名是 `handoff_to_agent`;新增 core 工具须同步扩展 leaf resolver 白名单。
148
+ */
149
+ interface CoreToolDescriptor {
150
+ source: 'core';
151
+ name: 'handoff_to_agent';
152
+ context: {
153
+ /** 发起方 member id——leaf 校验其与当前 turn 的 agentId 一致(origin 校验)。 */from: string; /** 策略计算后的目标白名单;leaf 只能收窄不能放宽。空数组 = 不暴露工具。 */
154
+ allowedTargets: readonly HandoffTargetInfo[];
155
+ };
156
+ }
157
+ /** 思考深度(本地 minimal type,避免 orchestrator 核心依赖 @x-otto/ai)。 */
158
+ type ThinkingLevel$1 = 'low' | 'medium' | 'high';
159
+ /** swarm member turn 入参(B+ 门禁①:经 TaskExecutor 治理)。 */
160
+ interface AgentTurnInput {
161
+ agentId: string;
162
+ prompt: string;
163
+ systemPrompt?: string;
164
+ tools?: AgentToolDef[];
165
+ /**
166
+ * @deprecated RFC-332:额外工具的元数据投影无法承载执行闭包(leaf 曾以 throw stub 补洞)。
167
+ * core 工具(handoff)改走 `coreTools` 描述符 + leaf 受限 resolver;本字段在 M2 策略
168
+ * 切换后删除。leaf 对该字段 fail closed(忽略并诊断),不再生成 stub。
169
+ */
170
+ extraTools?: AgentToolDef[];
171
+ /** RFC-332 M1:core 工具纯数据描述符——leaf 的受限 core resolver 据此构造真实工具。 */
172
+ coreTools?: CoreToolDescriptor[];
173
+ model?: string;
174
+ maxToolTurns?: number;
175
+ thinkingLevel?: ThinkingLevel$1;
176
+ maxTokens?: number;
177
+ temperature?: number;
178
+ signal?: AbortSignal;
179
+ /** swarm 执行标识(用于权限/审计归属,映射到 toolHookExecutor.sessionId)。 */
180
+ sessionId?: string;
181
+ /** 委托深度(递归护栏,映射到 Agent 构造器)。 */
182
+ depth?: number;
183
+ }
184
+ /** swarm member turn 结果(B+ 门禁①)。 */
185
+ interface AgentTurnResult {
186
+ agentId: string;
187
+ text: string;
188
+ /** 完整消息历史(handoff/hierarchical 策略需要)。 */
189
+ messages?: unknown[];
190
+ /** handoff 请求(handoff 策略需要)。 */
191
+ handoff?: {
192
+ from: string;
193
+ to: string;
194
+ reason: string;
195
+ };
196
+ tokenUsage?: {
197
+ input: number;
198
+ output: number;
199
+ cacheRead: number;
200
+ };
201
+ durationMs: number;
202
+ }
203
+ interface TaskInput {
204
+ /** 任务类别判别字段:'task' 走标准 Session 创建,'swarm_member' 走轻量 Agent 创建。
205
+ * 缺省等价于 'task'(向后兼容 task_delegate/agent_call 路径)。 */
206
+ kind?: 'task' | 'swarm_member';
207
+ /** 发给 subagent 的提示 */
208
+ prompt: string;
209
+ /** 指定 agent 名称 — 对齐 task_delegate.subagent / agent_call.agent */
210
+ subagent?: string;
211
+ /** 任务类别 — 对齐 task_delegate.category */
212
+ category?: string;
213
+ /** 复用的 session ID */
214
+ sessionId?: string;
215
+ /** session 策略 — 对齐 task_delegate.sessionMode */
216
+ sessionMode?: SessionMode;
217
+ /** 执行模式 — 对齐 task_delegate.mode */
218
+ mode?: TaskMode;
219
+ /** 模型槽位 — 对齐 task_delegate.slot / agent_call.slot */
220
+ slot?: ModelSlotName;
221
+ /** 显式模型 id(subagent 按能力选型)——优先于 slot。 */
222
+ model?: string;
223
+ /** 该任务所处委托深度(root 派发的任务 depth=1)。 */
224
+ depth?: number;
225
+ /** swarm 成员自定义 system prompt(覆盖默认)。 */
226
+ systemPrompt?: string;
227
+ tools?: AgentToolDef[];
228
+ /** 本轮额外工具(如 handoff 工具)。@deprecated RFC-332:见 AgentTurnInput.extraTools。 */
229
+ extraTools?: AgentToolDef[];
230
+ /** RFC-332 M1:core 工具纯数据描述符(swarm_member 专用)。 */
231
+ coreTools?: CoreToolDescriptor[];
232
+ thinkingLevel?: ThinkingLevel$1;
233
+ maxTokens?: number;
234
+ temperature?: number;
235
+ maxToolTurns?: number;
236
+ }
237
+ interface TaskOutput {
238
+ text: string;
239
+ summary?: string;
240
+ tokenUsage?: {
241
+ input: number;
242
+ output: number;
243
+ cacheRead: number;
244
+ };
245
+ durationMs?: number;
246
+ /** 完整消息历史(handoff/hierarchical 策略消费;非 swarm 任务恒缺省)。 */
247
+ messages?: unknown[];
248
+ /** leaf 捕获的 handoff intent(orchestrator 策略二次验证后才切换)。 */
249
+ handoff?: {
250
+ from: string;
251
+ to: string;
252
+ reason: string;
253
+ };
254
+ }
255
+ interface TaskError {
256
+ code: string;
257
+ message: string;
258
+ retriable: boolean;
259
+ }
260
+ interface Task {
261
+ id: string;
262
+ status: TaskStatus$1;
263
+ sessionPolicy: SessionMode;
264
+ sessionId?: string;
265
+ attempts: number;
266
+ maxAttempts: number;
267
+ input: TaskInput;
268
+ output?: TaskOutput;
269
+ error?: TaskError;
270
+ createdAt: number;
271
+ completedAt?: number;
272
+ }
273
+ interface TaskUnit {
274
+ input: TaskInput;
275
+ }
276
+ interface TaskResult {
277
+ taskId: string;
278
+ status: TaskStatus$1;
279
+ output?: TaskOutput;
280
+ error?: TaskError;
281
+ }
282
+ declare class TaskRejectedError extends Error {
283
+ readonly reason: 'circuit_open';
284
+ constructor(message: string, reason: 'circuit_open');
285
+ }
286
+ interface OrchestratorOptions {
287
+ hookRegistry: HookRegistry;
288
+ /** 由 App 注入:创建子 session → prompt → 提取输出文本(task_delegate/agent_call 路径)。 */
289
+ runSession: (options: RunSessionOptions) => Promise<RunSessionResult>;
290
+ /** B+ 门禁①:swarm member turn 执行回调(经 TaskExecutor 获得治理,但用轻量 Agent 创建)。
291
+ * 未提供时 runAgentTurn 回退到 runSession(兼容旧路径)。 */
292
+ runAgentTurn?: (input: AgentTurnInput) => Promise<AgentTurnResult>;
293
+ /** 可选:外部 abort 回调 */
294
+ abortTask?: (taskId: string) => void;
295
+ workflowConfig?: WorkflowOptions$1;
296
+ maxActiveTasks?: number;
297
+ /**
298
+ * TaskStore 容量上限(默认 1000)。store 满时按「终态优先 + 最旧先弃」LRU
299
+ * 驱逐已完成/失败/取消的任务档;pending/running 在飞任务绝不驱逐。治裸 Map 无界增长,
300
+ * 确定性、无时钟依赖(区别于 TTL)。透传 `new TaskStore(maxStoredTasks)`。
301
+ */
302
+ maxStoredTasks?: number;
303
+ /** 委托深度上限(默认 1)。root(0)→child1 放行;depth1→child2>1 拒。swarm 深层可经此放宽。 */
304
+ maxDelegationDepth?: number;
305
+ }
306
+ //#endregion
307
+ //#region src/orchestrator.d.ts
308
+ declare class Orchestrator {
309
+ readonly taskStore: TaskStore;
310
+ private readonly executor;
311
+ private readonly backgroundManager;
312
+ private readonly hookRegistry;
313
+ private readonly circuitBreakers;
314
+ private readonly delegationGate;
315
+ private readonly runSession;
316
+ private readonly maxDelegationDepth;
317
+ constructor(options: OrchestratorOptions);
318
+ dispatchTask: TaskDispatch;
319
+ /**
320
+ * agent 直调——**旁路任务内核**:不建档、不进 store、不重试,
321
+ * 直连宿主 runSession 的轻量探询语义(agent_call)。**但仍受治理**:
322
+ * 共享同一并发闸 delegationGate + per-target 熔断(与 task_delegate 同一 CircuitBreakerRegistry)
323
+ * + 委托深度护栏——agent_call 不是无治理通道,只是不走任务建档/重试。
324
+ */
325
+ callAgent: CallAgent;
326
+ /**
327
+ * swarm member turn — 经 TaskExecutor 执行(B+ 门禁①:成员 turn Task 化)。
328
+ * TaskExecutor 检测 swarm 字段时走 runAgentTurn 轻量回调,否则走 runSession。
329
+ */
330
+ runAgentTurn(input: AgentTurnInput): Promise<AgentTurnResult>;
331
+ getTask: GetTask;
332
+ listTasks: ListTasks;
333
+ updateTask: UpdateTask;
334
+ getBackgroundOutput: GetBackgroundOutput;
335
+ cancelBackground: CancelBackground;
336
+ dispose(): void;
337
+ }
338
+ //#endregion
339
+ //#region src/swarm/types.d.ts
340
+ type SwarmAgentId = string;
341
+ interface SwarmMemberCommon {
342
+ /** 唯一标识 */
343
+ id: SwarmAgentId;
344
+ /** 显示名 */
345
+ name: string;
346
+ /** 角色描述(用于路由决策) */
347
+ description: string;
348
+ /** 成员元数据(业务自定义) */
349
+ metadata?: Record<string, unknown>;
350
+ }
351
+ interface SwarmAgentMember extends SwarmMemberCommon {
352
+ kind: 'agent';
353
+ systemPrompt: string;
354
+ /** 模型配置(缺省时继承 Swarm 默认模型) */
355
+ model?: Model;
356
+ /**
357
+ * 成员声明的工具**元数据**(RFC-332 M3:从 `AgentTool[]` 收窄为纯数据 `AgentToolDef[]`)。
358
+ *
359
+ * orchestrator 全包不再持有可执行 `AgentTool`/`execute`——它只调度「请 leaf 暴露哪些能力」
360
+ * 的声明。真实工具由 coding leaf(`swarm-runtime.ts` 的 `resolveMemberTools`)按名从真实
361
+ * 工具目录 ∩ profile allowlist 重新解析。宿主解析层负责在构造 `SwarmAgentDef` 时投影
362
+ * (`description` 若为函数需先求值为字符串)。
363
+ */
364
+ tools?: AgentToolDef[];
365
+ /** 允许 handoff 到的目标 Agent ID 列表(空 = 无限制) */
366
+ handoffTargets?: SwarmAgentId[];
367
+ maxToolTurns?: number;
368
+ thinkingLevel?: ThinkingLevel;
369
+ temperature?: number;
370
+ maxTokens?: number;
371
+ }
372
+ /**
373
+ * 子团队成员 — 执行 = 递归运行整个子 swarm(team 嵌套)。
374
+ * 宿主解析层(coding/swarm-runtime)注入 `runNested` 闭包;**无 agent 执行字段**
375
+ * (systemPrompt/tools 等)——旧 `runNested?` 可选字段把 team 当 agent 伪造
376
+ * `systemPrompt:''`,本判别联合让 team 不再背 agent 假字段。swarm 核心不 import createSwarm,避免成环。
377
+ */
378
+ interface SwarmTeamMember extends SwarmMemberCommon {
379
+ kind: 'team';
380
+ runNested: (input: string, signal: AbortSignal) => Promise<SwarmTurnResult>;
381
+ }
382
+ type SwarmAgentDef = SwarmAgentMember | SwarmTeamMember;
383
+ interface HandoffRequest {
384
+ /** 发起方 Agent ID */
385
+ from: SwarmAgentId;
386
+ /** 目标 Agent ID */
387
+ to: SwarmAgentId;
388
+ /** Handoff 原因(注入目标 Agent 上下文) */
389
+ reason: string;
390
+ }
391
+ type RoutingStrategy = 'llm' | 'rule' | 'round-robin' | 'random';
392
+ interface RoutingDecision {
393
+ /** 选中的 Agent ID */
394
+ agentId: SwarmAgentId;
395
+ /** 路由理由 */
396
+ reason: string;
397
+ /** 置信度 (0-1) */
398
+ confidence: number;
399
+ }
400
+ interface RouteRule {
401
+ /** 匹配模式(正则或关键词数组) */
402
+ match: RegExp | string[];
403
+ /** 命中时路由到的 Agent ID */
404
+ agentId: SwarmAgentId;
405
+ /** 优先级(高优先) */
406
+ priority?: number;
407
+ }
408
+ interface RouterConfig {
409
+ strategy: RoutingStrategy;
410
+ /** LLM 路由时使用的模型 */
411
+ routerModel?: Model;
412
+ /** 规则路由 */
413
+ rules?: RouteRule[];
414
+ /** 自定义路由函数 */
415
+ customRouter?: (input: string, agents: SwarmAgentDef[]) => Promise<RoutingDecision>;
416
+ /** 默认 fallback Agent ID */
417
+ fallbackAgentId?: SwarmAgentId;
418
+ /** 确定性随机数端口。缺省=Math.random(行为不变)。 */
419
+ random?: {
420
+ random(): number;
421
+ };
422
+ }
423
+ type OrchestrationPattern = 'handoff' | 'sequential' | 'parallel' | 'hierarchical' | 'router';
424
+ interface HierarchicalTask {
425
+ description: string;
426
+ assignedTo?: SwarmAgentId;
427
+ }
428
+ interface SwarmTurnResult {
429
+ agentId: SwarmAgentId;
430
+ messages: AgentMessage[];
431
+ text: string;
432
+ /** 是否请求 handoff */
433
+ handoff?: HandoffRequest;
434
+ /** 使用的 token 量 */
435
+ tokenUsage: {
436
+ input: number;
437
+ output: number;
438
+ cacheRead: number;
439
+ };
440
+ /** 执行时长 */
441
+ durationMs: number;
442
+ }
443
+ interface SwarmConfig {
444
+ name: string;
445
+ /** 参与的 Agent 定义列表 */
446
+ agents: SwarmAgentDef[];
447
+ /** 默认 LLM 模型 */
448
+ defaultModel: Model;
449
+ /** 编排模式 */
450
+ pattern: OrchestrationPattern;
451
+ /** Swarm 成员所处的委托深度;传 Agent 构造器闭合递归护栏。 */
452
+ depth?: number;
453
+ /** 路由器配置(pattern='router' 或 'handoff' 时使用) */
454
+ router?: RouterConfig;
455
+ /** 流水线顺序(pattern='sequential' 时使用) */
456
+ pipeline?: SwarmAgentId[];
457
+ /** 层级根 Agent(pattern='hierarchical' 时使用) */
458
+ supervisorId?: SwarmAgentId;
459
+ /** 最大 handoff 深度(防无限循环) */
460
+ maxHandoffDepth?: number;
461
+ /** 最大并行 Agent 数 */
462
+ maxConcurrency?: number;
463
+ /** 初始入口 Agent ID */
464
+ entryAgentId?: SwarmAgentId;
465
+ /** Agent 执行器——完全封装 Agent 创建与执行,返回 SwarmTurnResult。
466
+ * **M-B2 B+ 门禁①**:由 Orchestrator.runAgentTurn 提供(经 TaskExecutor 获得重试/熔断/并发闸/深度护栏)。
467
+ * 宿主(coding/swarm-runtime)注入 orchestrator 方法;swarm 自身不持有 Agent 构造逻辑。 */
468
+ runAgentTurn: (input: AgentTurnInput) => Promise<AgentTurnResult>;
469
+ /** swarm 运行标识(用于权限/审计归属,透传至 AgentTurnInput.sessionId)。 */
470
+ runId?: string;
471
+ /**
472
+ * M-B3: swarm 事件回调(取代 TypedEventEmitter.on)。
473
+ * 调用方(coding/swarm-runtime)可桥接到 hookRegistry 注册 observer。
474
+ * 未设置时事件静默丢弃(当前零外部订阅者,无行为变化)。
475
+ *
476
+ * RFC-107 D1 / M-N6:保留此私有回调(向后兼容),新增 hookRegistry 桥接为并行通道。
477
+ */
478
+ onSwarmEvent?: SwarmEventHandler;
479
+ /**
480
+ * Hook 注册表(RFC-107 D1 / M-N6)。Swarm 内部 emit 事件时,
481
+ * 同时经此桥接至既有 task.* HookTiming 家族(携带 SwarmEventPayload 上下文)。
482
+ * 未设置时仅走 onSwarmEvent 私有回调(行为不变)。
483
+ */
484
+ hookRegistry?: _$_x_otto_hooks0.HookRegistry;
485
+ }
486
+ type SwarmEvent = {
487
+ type: 'swarm.start';
488
+ pattern: OrchestrationPattern;
489
+ agentCount: number;
490
+ } | {
491
+ type: 'swarm.end';
492
+ totalDurationMs: number;
493
+ } | {
494
+ type: 'agent.start';
495
+ agentId: SwarmAgentId;
496
+ } | {
497
+ type: 'agent.end';
498
+ agentId: SwarmAgentId;
499
+ durationMs: number;
500
+ } | {
501
+ type: 'handoff';
502
+ from: SwarmAgentId;
503
+ to: SwarmAgentId;
504
+ reason: string;
505
+ } | {
506
+ type: 'routing.decision';
507
+ decision: RoutingDecision;
508
+ } | {
509
+ type: 'parallel.fanOut';
510
+ agentIds: SwarmAgentId[];
511
+ } | {
512
+ type: 'parallel.fanIn';
513
+ completedCount: number;
514
+ totalCount: number;
515
+ } | {
516
+ type: 'pipeline.step';
517
+ step: number;
518
+ agentId: SwarmAgentId;
519
+ } | {
520
+ type: 'hierarchy.delegate';
521
+ supervisor: SwarmAgentId;
522
+ worker: SwarmAgentId;
523
+ task: string;
524
+ } | {
525
+ type: 'error';
526
+ agentId: SwarmAgentId;
527
+ error: Error;
528
+ };
529
+ type SwarmEventHandler = (event: SwarmEvent) => void;
530
+ //#endregion
531
+ //#region src/swarm/strategy.d.ts
532
+ interface StepResult {
533
+ agentId: string;
534
+ output: SwarmTurnResult;
535
+ durationMs: number;
536
+ }
537
+ interface StrategyContext {
538
+ /**
539
+ * 轻量 step 执行器——经 createStepRunner 派发。
540
+ * team 成员的 runNested 由策略自行分派(agentDef.kind === 'team')。
541
+ * 并发由策略直接 import `runConcurrent`(intra-team 扇出原语)组织——非经 ctx 字段。
542
+ */
543
+ createStepRunner: (agentDef: SwarmAgentDef, input: string, options?: {
544
+ signal?: AbortSignal;
545
+ coreTools?: CoreToolDescriptor[];
546
+ }) => Promise<SwarmTurnResult>;
547
+ /** 事件总线。 */
548
+ emit: SwarmEventHandler;
549
+ /** 可选路由器(handoff/router pattern 用)。 */
550
+ router?: Router;
551
+ /** AbortSignal。 */
552
+ signal: AbortSignal;
553
+ /** 配置快照。 */
554
+ config: StrategyConfig;
555
+ }
556
+ interface StrategyConfig {
557
+ name: string;
558
+ agents: Map<string, SwarmAgentDef>;
559
+ entryAgentId?: string;
560
+ pipeline?: string[];
561
+ supervisorId?: string;
562
+ maxHandoffDepth?: number;
563
+ maxConcurrency?: number;
564
+ }
565
+ interface OrchestrationStrategy {
566
+ /** 策略名(注册表 key)。 */
567
+ readonly name: string;
568
+ /**
569
+ * 执行编排。ctx 由 Swarm.run() 从 config + runtime 构造。
570
+ * 策略内经 ctx.createStepRunner 派单步、直接 import runConcurrent 组织 intra-team 并发。
571
+ */
572
+ execute(input: string, ctx: StrategyContext): Promise<StrategyResult>;
573
+ }
574
+ interface StrategyResult {
575
+ /** 所有 step 的执行记录。 */
576
+ steps: StepResult[];
577
+ /** 最终输出文本。 */
578
+ output: string;
579
+ }
580
+ declare class StrategyRegistry {
581
+ private readonly strategies;
582
+ register(strategy: OrchestrationStrategy): void;
583
+ get(name: string): OrchestrationStrategy | undefined;
584
+ has(name: string): boolean;
585
+ names(): string[];
586
+ }
587
+ interface Router {
588
+ route(input: string, agents: SwarmAgentDef[]): Promise<{
589
+ agentId: string;
590
+ reason: string;
591
+ confidence: number;
592
+ }>;
593
+ }
594
+ //#endregion
595
+ //#region src/swarm/swarm.d.ts
596
+ /**
597
+ * Swarm — 多 Agent 协作框架(策略引擎化)。
598
+ *
599
+ * OrchestrationStrategy 取代封闭枚举+switch——新模式 = 实现接口 + registry.register(),
600
+ * 不碰 Swarm.run()、不碰核心结果类型。
601
+ */
602
+ declare class Swarm {
603
+ private readonly config;
604
+ private readonly agents;
605
+ private readonly router;
606
+ private readonly registry;
607
+ constructor(config: SwarmConfig);
608
+ getAgents(): SwarmAgentDef[];
609
+ getAgent(id: SwarmAgentId): SwarmAgentDef | undefined;
610
+ /** 注册/替换策略(§4-12:host 可追加新模式,不碰核心)。 */
611
+ registerStrategy(strategy: OrchestrationStrategy): void;
612
+ /** 获取已注册策略名列表。 */
613
+ getStrategyNames(): string[];
614
+ private emitEvent;
615
+ /** 构建 StrategyContext——每次 run() 全新构造(context/signal 属单次运行)。 */
616
+ private buildStrategyContext;
617
+ /**
618
+ * 运行 Swarm — 从注册表取策略并执行。
619
+ */
620
+ run(input: string, options?: {
621
+ signal?: AbortSignal;
622
+ }): Promise<SwarmRunResult>;
623
+ /**
624
+ * 执行单个 swarm 成员的 agent turn(B+ 门禁①:经 TaskExecutor 执行)。
625
+ * team 成员走 runNested(递归子 swarm)。
626
+ */
627
+ private executeMemberTurn;
628
+ private validateConfig;
629
+ }
630
+ interface SwarmRunResult {
631
+ /** 模式名(保留判别字段,service/CLI 据此消费)。 */
632
+ pattern: string;
633
+ /** 所有 step 的执行记录。 */
634
+ steps: StepResult[];
635
+ /** 最终输出文本。 */
636
+ output: string;
637
+ durationMs: number;
638
+ }
639
+ declare function createSwarm(config: SwarmConfig): Swarm;
640
+ //#endregion
641
+ //#region src/swarm/concurrent.d.ts
642
+ interface ConcurrentOptions<T> {
643
+ /** 并发上限。 */
644
+ cap: number;
645
+ /**
646
+ * 单步执行器。第三参 `signal` 在「兄弟失败」或「外部 signal abort」时触发——执行器可据此取消
647
+ * 在途工作(不取消也无妨:仍不会启动新任务、且失败会上抛)。
648
+ */
649
+ executor: (step: T, index: number, signal: AbortSignal) => Promise<void>;
650
+ /** 可选外部 AbortSignal——阻止新任务启动;经内部控制器转发给执行器(可中断在途)。 */
651
+ signal?: AbortSignal;
652
+ /**
653
+ * 可选进度回调:每次一个任务完成(或出错)时调用。
654
+ * 调用方可在此 emit fan-in 事件(如 `{type:'parallel.fanIn',completedCount,totalCount}`)。
655
+ */
656
+ onProgress?: (completedCount: number, totalCount: number) => void;
657
+ }
658
+ /**
659
+ * 全仓唯一并发池原语(M24-02)。
660
+ *
661
+ * endgame review 修复(弃跑兄弟):旧实现 `await Promise.race(running)` 在某成员 reject 时直接外抛,
662
+ * 其余在途任务变成**无 await 的孤儿** → 后续 reject 触发 unhandledRejection、且谁也不取消它们。
663
+ * 现在:① 每个任务包成**永不 reject** 的 wrapper(race 不再因兄弟失败而抛,所有任务都被排空);
664
+ * ② 首个失败记录 firstError 并 abort 内部控制器(转发给执行器取消在途)+ 清空 pending(不再启动新任务);
665
+ * ③ finally 里 allSettled 排空残余,确保无孤儿;④ 全部结束后再上抛 firstError。
666
+ * 顺带修了旧实现的一个潜伏 bug:外部 signal abort 且仍有 pending 时,旧循环会空转(running 排空后
667
+ * pending 非空、canStart=false、无 await → CPU busy loop)——现在 abort/fail 都清 pending、干净退出。
668
+ */
669
+ declare function runConcurrent<T>(steps: readonly T[], options: ConcurrentOptions<T>): Promise<void>;
670
+ //#endregion
671
+ //#region src/swarm/strategies/handoff.d.ts
672
+ declare const HANDOFF_STRATEGY: OrchestrationStrategy;
673
+ //#endregion
674
+ //#region src/swarm/strategies/sequential.d.ts
675
+ declare const SEQUENTIAL_STRATEGY: OrchestrationStrategy;
676
+ //#endregion
677
+ //#region src/swarm/strategies/parallel.d.ts
678
+ declare const PARALLEL_STRATEGY: OrchestrationStrategy;
679
+ //#endregion
680
+ //#region src/swarm/strategies/hierarchical.d.ts
681
+ declare const HIERARCHICAL_STRATEGY: OrchestrationStrategy;
682
+ //#endregion
683
+ //#region src/swarm/strategies/router.d.ts
684
+ declare const ROUTER_STRATEGY: OrchestrationStrategy;
685
+ //#endregion
686
+ //#region src/swarm/strategies/index.d.ts
687
+ declare function createDefaultStrategyRegistry(): StrategyRegistry;
688
+ //#endregion
689
+ //#region src/swarm/router.d.ts
690
+ declare class SwarmRouter {
691
+ private readonly config;
692
+ private roundRobinIndex;
693
+ constructor(config: RouterConfig);
694
+ route(input: string, agents: SwarmAgentDef[]): Promise<RoutingDecision>;
695
+ /** 基于规则路由 */
696
+ private routeByRule;
697
+ /** 轮转路由 */
698
+ private routeRoundRobin;
699
+ /** 随机路由 */
700
+ private routeRandom;
701
+ /**
702
+ * LLM 路由 —— 委托宿主注入的 customRouter(真实 LLM 调用)。
703
+ * 旧 'custom' 枚举值已坍缩归入此路径(两者语义相同:host-injected 函数)。
704
+ */
705
+ private routeByLlm;
706
+ /** Fallback 到默认 Agent */
707
+ private fallback;
708
+ /** 匹配单条规则 */
709
+ private matchRule;
710
+ }
711
+ //#endregion
712
+ //#region src/swarm/handoff.d.ts
713
+ /**
714
+ * 创建 handoff 工具 — 注入到每个 SwarmAgent 的工具列表中,
715
+ * 允许 Agent 通过工具调用发起 handoff。
716
+ *
717
+ * 灵感来自 OpenAI Swarm 的 handoff 模式:
718
+ * Agent 在对话过程中自行决定何时、向谁交接控制权。
719
+ *
720
+ * RFC-332 M1:参数从 `SwarmAgentDef[]` 收窄为最小纯数据结构(本函数只消费
721
+ * id/name/description)——使 coding leaf 的 core resolver 能用可序列化的
722
+ * `HandoffTargetInfo[]`(经 `CoreToolDescriptor` 跨边界传输)直接构造真实工具。
723
+ */
724
+ declare function createHandoffTool(currentAgentId: SwarmAgentId, availableTargets: readonly {
725
+ id: SwarmAgentId;
726
+ name: string;
727
+ description: string;
728
+ }[], onHandoff: (request: HandoffRequest) => void): AgentTool;
729
+ declare function validateHandoff(request: HandoffRequest, agents: Map<string, SwarmAgentDef>): {
730
+ valid: boolean;
731
+ error?: string;
732
+ };
733
+ //#endregion
734
+ //#region src/swarm/errors.d.ts
735
+ declare class HandoffDepthError extends AgentError {
736
+ readonly depth: number;
737
+ readonly maxDepth: number;
738
+ constructor(depth: number, maxDepth: number);
739
+ }
740
+ declare class RoutingError extends AgentError {
741
+ constructor(message: string);
742
+ }
743
+ declare class AgentNotFoundError extends AgentError {
744
+ readonly agentId: string;
745
+ constructor(agentId: string);
746
+ }
747
+ declare class SwarmConfigError extends AgentError {
748
+ constructor(message: string);
749
+ }
750
+ //#endregion
751
+ export { AgentNotFoundError, type AgentToolDef, type AgentTurnInput, type AgentTurnResult, CircuitBreaker, type CircuitBreakerConfig, type ConcurrentOptions, type CoreToolDescriptor, HANDOFF_STRATEGY, HIERARCHICAL_STRATEGY, HandoffDepthError, type HandoffRequest, type HandoffTargetInfo, type HierarchicalTask, type OrchestrationPattern, type OrchestrationStrategy, Orchestrator, type OrchestratorOptions, PARALLEL_STRATEGY, ROUTER_STRATEGY, type RetryConfig, RetryPolicy, type RouteRule, type RouterConfig, type RoutingDecision, RoutingError, type RoutingStrategy, type RunSessionOptions, type RunSessionResult, SEQUENTIAL_STRATEGY, type StepResult, type StrategyConfig, type StrategyContext, StrategyRegistry, type StrategyResult, Swarm, type SwarmAgentDef, type SwarmAgentId, type SwarmAgentMember, type SwarmConfig, SwarmConfigError, type SwarmEvent, type SwarmEventHandler, SwarmRouter, type SwarmRunResult, type SwarmTeamMember, type SwarmTurnResult, type Task, type TaskError, type TaskInput, type TaskOutput, TaskRejectedError, type TaskResult, type TaskStatus, TaskStore, type TaskUnit, type WorkflowOptions, createDefaultStrategyRegistry, createHandoffTool, createSwarm, runConcurrent, validateHandoff };
752
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/retry.ts","../src/task-store.ts","../src/executor.ts","../src/types.ts","../src/orchestrator.ts","../src/swarm/types.ts","../src/swarm/strategy.ts","../src/swarm/swarm.ts","../src/swarm/concurrent.ts","../src/swarm/strategies/handoff.ts","../src/swarm/strategies/sequential.ts","../src/swarm/strategies/parallel.ts","../src/swarm/strategies/hierarchical.ts","../src/swarm/strategies/router.ts","../src/swarm/strategies/index.ts","../src/swarm/router.ts","../src/swarm/handoff.ts","../src/swarm/errors.ts"],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import{checkDelegationDepth as e}from"@x-otto/orchestration-contracts";import{AgentError as t,createLogger as n}from"@x-otto/shared";import{z as r}from"zod";var i=class extends Error{constructor(e,t){super(e),this.reason=t,this.name=`TaskRejectedError`}};const a=new Set([`completed`,`failed`,`cancelled`]);var o=class{tasks=new Map;nextId=1;maxStoredTasks;constructor(e=1e3){this.maxStoredTasks=Math.max(1,e)}generateId(){return`task_${Date.now()}_${this.nextId++}`}async create(e){this.evictForCapacity();let t={id:this.generateId(),status:`pending`,sessionPolicy:e.sessionMode??`ephemeral`,attempts:0,maxAttempts:3,input:e,createdAt:Date.now()};return this.tasks.set(t.id,t),t}evictForCapacity(){let e=this.tasks.size-this.maxStoredTasks+1;if(e<=0)return;let t=[...this.tasks.values()].filter(e=>a.has(e.status)).sort((e,t)=>(e.completedAt??e.createdAt)-(t.completedAt??t.createdAt));for(let n of t){if(e<=0)break;this.tasks.delete(n.id),e--}e>0&&console.warn(`[TaskStore] capacity ${this.maxStoredTasks} exceeded by ${e} in-flight task(s); no terminal tasks left to evict — keeping in-flight tasks (will exceed cap).`)}async get(e){return this.tasks.get(e)}async list(e){let t=[...this.tasks.values()];return e?.status&&(t=t.filter(t=>t.status===e.status)),t}async update(e,t){let n=this.tasks.get(e);if(!n)throw Error(`Task not found: ${e}`);Object.assign(n,t)}async delete(e){return this.tasks.delete(e)}};const s={enabled:!0,maxAttempts:3,backoffMs:1e3,backoffMultiplier:2};var c=class e{config;constructor(e){this.config={...s,...e}}shouldRetry(e){return this.config.enabled&&e<this.config.maxAttempts}getBackoff(e){return this.config.backoffMs*this.config.backoffMultiplier**(e-1)}static fromWorkflowOptions(t){let n=t?.retry;return new e({enabled:n?.enabled??!0,maxAttempts:n?.maxAttempts??3})}};const l={enabled:!0,failureThreshold:5,resetTimeoutMs:6e4};var u=class{enabled;failureThreshold;resetTimeoutMs;consecutiveFailures=0;openedAt=null;constructor(e){let t={...l,...e};this.enabled=t.enabled,this.failureThreshold=t.failureThreshold,this.resetTimeoutMs=t.resetTimeoutMs}isOpen(){return!this.enabled||this.openedAt===null?!1:Date.now()-this.openedAt>=this.resetTimeoutMs?(this.openedAt=null,this.consecutiveFailures=0,!1):!0}success(){this.consecutiveFailures=0,this.openedAt=null}failure(){this.consecutiveFailures++,this.consecutiveFailures>=this.failureThreshold&&(this.openedAt=Date.now())}reset(){this.consecutiveFailures=0,this.openedAt=null}},d=class e{breakers=new Map;constructor(e){this.factory=e}forTarget(e){let t=this.breakers.get(e);return t||(t=this.factory(),this.breakers.set(e,t)),t}resetAll(){for(let e of this.breakers.values())e.reset()}static perTarget(t){return new e(()=>new u(t))}static single(t){return new e(()=>t)}static fromWorkflowOptions(t){let n=t?.circuitBreaker;return e.perTarget({enabled:n?.enabled??!0,failureThreshold:n?.failureThreshold??5,resetTimeoutMs:n?.timeoutMs??6e4})}};function f(){let e=Error(`Semaphore acquire aborted`);return e.name=`AbortError`,e}var p=class{active=0;waiters=[];constructor(e){this.max=e}async acquire(e){if(e?.aborted)throw f();if(this.active<this.max){this.active+=1;return}await new Promise((t,n)=>{let r=()=>{a(),t()},i=()=>{let e=this.waiters.indexOf(r);e>=0&&this.waiters.splice(e,1),a(),n(f())},a=()=>e?.removeEventListener(`abort`,i);this.waiters.push(r),e?.addEventListener(`abort`,i,{once:!0})})}release(){let e=this.waiters.shift();e?e():--this.active}async run(e,t){await this.acquire(t);try{return await e()}finally{this.release()}}get activeCount(){return this.active}get pendingCount(){return this.waiters.length}get capacity(){return this.max}},m=class{constructor(e,t,n,r,i,a,o){this.taskStore=e,this.hookRegistry=t,this.retryPolicy=n,this.circuitBreakers=r,this.runSession=i,this.semaphore=a,this.runAgentTurn=o}breakerFor(e){return this.circuitBreakers.forTarget(e??`default`)}async runTask(e,t){this.assertCircuit(e.input.subagent);let n=await this.register(e);return this.runScheduled(n.id,t)}assertCircuit(e){if(this.breakerFor(e).isOpen())throw new i(`Circuit breaker is open due to repeated failures. Try again later.`,`circuit_open`)}async runScheduled(e,t){return this.semaphore.run(()=>this.executeToCompletion(e,t),t)}async isCancelled(e){return(await this.taskStore.get(e))?.status===`cancelled`}async register(e){let t=await this.taskStore.create(e.input);return this.hookRegistry.emit(`task.created`,{task:t}),t}async startTask(e){this.assertCircuit(e.input.subagent);let t=await this.register(e);return this.runScheduled(t.id).catch(async e=>{await this.taskStore.update(t.id,{status:`failed`,error:{code:`EXECUTION_FAILED`,message:e instanceof Error?e.message:String(e),retriable:!1},completedAt:Date.now()}).catch(()=>{})}),{id:t.id}}async executeToCompletion(e,t){let n=await this.taskStore.get(e);if(!n)return{taskId:e,status:`failed`,error:{code:`TASK_NOT_FOUND`,message:`Task not found: ${e}`,retriable:!1}};let r=n.attempts+1;try{await this.taskStore.update(e,{status:`running`,attempts:r}),this.hookRegistry.emit(`task.started`,{task:{...n,status:`running`},agent:n.input.subagent??`default`});let i=n.input.kind===`swarm_member`,a;if(i&&this.runAgentTurn){let e=await this.runAgentTurn({agentId:n.input.subagent??`agent`,prompt:n.input.prompt,systemPrompt:n.input.systemPrompt,tools:n.input.tools,extraTools:n.input.extraTools,coreTools:n.input.coreTools,model:n.input.model,maxToolTurns:n.input.maxToolTurns,thinkingLevel:n.input.thinkingLevel,maxTokens:n.input.maxTokens,temperature:n.input.temperature,sessionId:n.input.sessionId,depth:n.input.depth,signal:t});a={text:e.text,sessionId:n.input.sessionId??``,tokenUsage:e.tokenUsage,durationMs:e.durationMs,messages:e.messages,handoff:e.handoff}}else a=await this.runSession({prompt:n.input.prompt,sessionId:n.input.sessionId,sessionMode:n.sessionPolicy,agentName:n.input.subagent,slot:n.input.slot,model:n.input.model,category:n.input.category,depth:n.input.depth,taskId:e,signal:t,readOnly:n.input.mode===`background`,systemPrompt:n.input.systemPrompt,tools:n.input.tools,extraTools:n.input.extraTools,thinkingLevel:n.input.thinkingLevel,maxTokens:n.input.maxTokens,temperature:n.input.temperature,maxToolTurns:n.input.maxToolTurns});if(await this.isCancelled(e))return{taskId:e,status:`cancelled`};let o={text:a.text,tokenUsage:a.tokenUsage,durationMs:a.durationMs,...a.messages?{messages:a.messages}:{},...a.handoff?{handoff:a.handoff}:{}};return await this.taskStore.update(e,{status:`completed`,output:o,sessionId:a.sessionId,completedAt:Date.now()}),this.breakerFor(n.input.subagent).success(),this.hookRegistry.emit(`task.completed`,{task:{...n,status:`completed`,output:o},result:o}),{taskId:e,status:`completed`,output:o}}catch(r){let i=r instanceof Error?r.message:String(r);if(await this.isCancelled(e))return{taskId:e,status:`cancelled`};if(this.retryPolicy.shouldRetry(n.attempts)&&!t?.aborted&&(await h(this.retryPolicy.getBackoff(n.attempts),t),!t?.aborted))return this.executeToCompletion(e,t);this.breakerFor(n.input.subagent).failure();let a={code:`EXECUTION_FAILED`,message:i,retriable:!1};return await this.taskStore.update(e,{status:`failed`,error:a,completedAt:Date.now()}),this.hookRegistry.emit(`task.failed`,{task:{...n,status:`failed`},error:a}),{taskId:e,status:`failed`,error:a}}}};function h(e,t){return t?.aborted?Promise.resolve():new Promise(n=>{let r,i=()=>{clearTimeout(r),n()};r=setTimeout(()=>{t?.removeEventListener(`abort`,i),n()},e),t?.addEventListener(`abort`,i,{once:!0})})}var g=class{constructor(e,t){this.taskStore=e,this.abortTask=t}async getOutput(e){let t=await this.taskStore.get(e);return t?t.status===`completed`?{ok:!0,value:{status:`completed`,output:t.output?.text}}:t.status===`failed`?{ok:!1,error:t.error?.message??`Task failed`}:{ok:!0,value:{status:t.status}}:{ok:!1,error:`Task not found id: ${e}`}}async cancel(e){let t=await this.taskStore.get(e);return t?t.status===`completed`||t.status===`failed`||t.status===`cancelled`?{ok:!1,error:`Task already in terminal state: ${t.status}, id: ${e}`}:(await this.taskStore.update(e,{status:`cancelled`,completedAt:Date.now()}),this.abortTask&&this.abortTask(e),{ok:!0,value:void 0}):{ok:!1,error:`Task not found id: ${e}`}}},_=class{taskStore;executor;backgroundManager;hookRegistry;circuitBreakers;delegationGate;runSession;maxDelegationDepth;constructor(e){let{hookRegistry:t,runSession:n,runAgentTurn:r,abortTask:i,workflowConfig:a,maxActiveTasks:s=10,maxStoredTasks:l,maxDelegationDepth:u=1}=e;this.hookRegistry=t,this.runSession=n,this.maxDelegationDepth=u,this.taskStore=new o(l);let f=c.fromWorkflowOptions(a);this.circuitBreakers=d.fromWorkflowOptions(a),this.delegationGate=new p(s),this.executor=new m(this.taskStore,t,f,this.circuitBreakers,n,this.delegationGate,r),this.backgroundManager=new g(this.taskStore,i)}dispatchTask=async t=>{let{childDepth:n,exceeded:r}=e(t.depth,this.maxDelegationDepth);if(r)return y(`Delegation depth limit (${this.maxDelegationDepth}) reached — complete this subtask yourself instead of delegating further.`);let i={input:{prompt:t.prompt,subagent:t.subagent,category:t.category,sessionId:t.sessionId,sessionMode:t.sessionMode??`ephemeral`,mode:t.mode,slot:t.slot,model:t.model,depth:n}};if(t.mode===`background`)return b(async()=>{let{id:e}=await this.executor.startTask(i);return{id:e,status:`pending`,output:`Background task created: ${e}`}});try{let e=await this.executor.runTask(i,t.signal);return e.status===`completed`?v({id:e.taskId,status:e.status,output:e.output?.text}):y(e.error?.message??`Unknown error`)}catch(e){return y(e)}};callAgent=async(t,n,r)=>{let{childDepth:i,exceeded:a}=e(r?.depth,this.maxDelegationDepth);if(a)return y(`Delegation depth limit (${this.maxDelegationDepth}) reached — complete this subtask yourself instead of delegating further.`);let o=this.circuitBreakers.forTarget(t);return o.isOpen()?y(`Circuit breaker is open due to repeated failures. Try again later.`):this.delegationGate.run(async()=>{try{let e=await this.runSession({prompt:n,sessionMode:`ephemeral`,agentName:t,slot:r?.slot,model:r?.model,depth:i,signal:r?.signal});return o.success(),v(e.text)}catch(e){return o.failure(),y(e)}},r?.signal)};async runAgentTurn(e){let t={input:{kind:`swarm_member`,prompt:e.prompt,subagent:e.agentId,systemPrompt:e.systemPrompt,tools:e.tools,extraTools:e.extraTools,coreTools:e.coreTools,model:e.model,maxToolTurns:e.maxToolTurns,thinkingLevel:e.thinkingLevel,maxTokens:e.maxTokens,temperature:e.temperature,sessionMode:`ephemeral`,sessionId:e.sessionId,depth:e.depth}},n=await this.executor.runTask(t,e.signal);if(n.status===`completed`)return{agentId:e.agentId,text:n.output?.text??``,messages:n.output?.messages,handoff:n.output?.handoff,tokenUsage:n.output?.tokenUsage,durationMs:n.output?.durationMs??0};throw Error(n.error?.message??`Swarm member turn failed: ${n.status}`)}getTask=async e=>{let t=await this.taskStore.get(e);return t?v({id:t.id,status:t.status,prompt:t.input.prompt,output:t.output?.text,error:t.error?.message}):y(`Task not found: ${e}`)};listTasks=async e=>{let t=e&&e!==`all`?{status:e}:void 0;return v((await this.taskStore.list(t)).map(e=>({id:e.id,prompt:e.input.prompt,status:e.status})))};updateTask=async(e,t)=>{let n=await this.taskStore.get(e);if(!n)return y(`Task not found: ${e}`);if(t===`cancel`){let t=await this.backgroundManager.cancel(e);return t.ok?(await this.hookRegistry.emit(`task.cancelled`,{taskId:e}),v(`Task ${e} cancelled`)):y(t.error)}if(t===`retry`){if(n.status!==`failed`)return y(`Can only retry failed tasks. Current status: ${n.status}`);let e=await this.dispatchTask({prompt:n.input.prompt,subagent:n.input.subagent,category:n.input.category,mode:n.input.mode??`sync`,sessionId:n.input.sessionId,sessionMode:n.input.sessionMode,slot:n.input.slot,model:n.input.model});return e.ok?v(e.value.output??`Retry completed`):y(e.error)}return y(`Unknown action: ${t}`)};getBackgroundOutput=async e=>this.backgroundManager.getOutput(e);cancelBackground=async e=>this.backgroundManager.cancel(e);dispose(){this.circuitBreakers.resetAll()}};function v(e){return{ok:!0,value:e}}function y(e){return{ok:!1,error:x(e)}}async function b(e){try{return v(await e())}catch(e){return y(e)}}function x(e){return e instanceof Error?e.message:String(e)}var S=class extends t{depth;maxDepth;constructor(e,t){super(`Handoff depth ${e} exceeds max ${t}`,{code:`SWARM_HANDOFF_DEPTH_EXCEEDED`}),this.name=`HandoffDepthError`,this.depth=e,this.maxDepth=t}},C=class extends t{constructor(e){super(e,{code:`SWARM_ROUTING_ERROR`}),this.name=`RoutingError`}},w=class extends t{agentId;constructor(e){super(`Agent "${e}" not found in swarm`,{code:`SWARM_AGENT_NOT_FOUND`}),this.name=`AgentNotFoundError`,this.agentId=e}},T=class extends t{constructor(e){super(e,{code:`SWARM_CONFIG_ERROR`}),this.name=`SwarmConfigError`}},E=class{config;roundRobinIndex=0;constructor(e){if(e.strategy===`llm`&&!e.customRouter)throw new C(`Routing strategy 'llm' requires a customRouter (inject the real LLM routing call).`);this.config=e}async route(e,t){let{strategy:n}=this.config;switch(n){case`rule`:return this.routeByRule(e,t);case`round-robin`:return this.routeRoundRobin(t);case`random`:return this.routeRandom(t);case`llm`:return this.routeByLlm(e,t);default:throw new C(`Unknown routing strategy: ${n}`)}}routeByRule(e,t){let n=this.config.rules??[],r=e.toLowerCase(),i=[...n].sort((e,t)=>(t.priority??0)-(e.priority??0));for(let e of i)if(this.matchRule(e,r)){let n=t.find(t=>t.id===e.agentId);if(n)return{agentId:e.agentId,reason:`Matched rule for "${n.name}"`,confidence:1}}return this.fallback(t,`No rule matched`)}routeRoundRobin(e){let t=e[this.roundRobinIndex%e.length];return this.roundRobinIndex++,{agentId:t.id,reason:`Round-robin selection (index ${this.roundRobinIndex-1})`,confidence:1}}routeRandom(e){let t=this.config.random?.random??Math.random;return{agentId:e[Math.floor(t()*e.length)].id,reason:`Random selection`,confidence:1/e.length}}async routeByLlm(e,t){let{customRouter:n}=this.config;if(!n)throw new C(`Routing strategy 'llm' requires a customRouter.`);return n(e,t)}fallback(e,t){let n=this.config.fallbackAgentId??e[0]?.id;if(!n)throw new C(`${t} and no fallback agent configured`);return{agentId:n,reason:`${t} — using fallback agent`,confidence:0}}matchRule(e,t){return e.match instanceof RegExp?e.match.test(t):e.match.some(e=>t.includes(e.toLowerCase()))}},D=class{strategies=new Map;register(e){if(this.strategies.has(e.name))throw Error(`Orchestration strategy "${e.name}" is already registered`);this.strategies.set(e.name,e)}get(e){return this.strategies.get(e)}has(e){return this.strategies.has(e)}names(){return[...this.strategies.keys()]}};function O(e,t,n){let i=t.map(e=>`- "${e.id}": ${e.name} — ${e.description}`).join(`
2
+ `),a=t.map(e=>e.id);return{name:`handoff_to_agent`,description:`Transfer control to another agent in the swarm. Available targets:\n${i}`,parameters:r.object({target_agent_id:r.string().describe(`The ID of the agent to hand off to. Must be one of: ${a.join(`, `)}`),reason:r.string().describe(`Why you are transferring to this agent — will be provided as context.`),summary:r.string().optional().describe(`Optional summary of work done so far to provide context to the target agent.`)}),readonly:!0,execute:async t=>{let{target_agent_id:r,reason:i,summary:o}=t.params;return a.includes(r)?(n({from:e,to:r,reason:o?`${i}\n\nContext: ${o}`:i}),{content:[{type:`text`,text:`Handoff initiated to "${r}". Reason: ${i}`}]}):{content:[{type:`text`,text:`Invalid target agent "${r}". Available targets: ${a.join(`, `)}`}],isError:!0}}}}function k(e,t){let n=t.get(e.from),r=t.get(e.to);return n?r?n.kind===`agent`&&n.handoffTargets&&n.handoffTargets.length>0&&!n.handoffTargets.includes(e.to)?{valid:!1,error:`Agent "${e.from}" is not allowed to handoff to "${e.to}". Allowed: [${n.handoffTargets.join(`, `)}]`}:{valid:!0}:{valid:!1,error:`Target agent "${e.to}" not found`}:{valid:!1,error:`Source agent "${e.from}" not found`}}const A={name:`handoff`,async execute(e,t){let n=[...t.config.agents.values()],r=t.config.entryAgentId??n[0]?.id;if(!r)return{steps:[],output:``};let i=t.config.maxHandoffDepth??10,a=r,o=e,s=[];for(let e=0;e<i&&!t.signal.aborted;e++){let e=t.config.agents.get(a);if(!e)throw new w(a);let r=n.filter(e=>e.id!==a);if(e.kind===`agent`&&e.handoffTargets&&e.handoffTargets.length>0){let t=e.handoffTargets;r=r.filter(e=>t.includes(e.id))}let i=r.length>0?{source:`core`,name:`handoff_to_agent`,context:{from:a,allowedTargets:r.map(e=>({id:e.id,name:e.name,description:e.description}))}}:null;t.emit({type:`agent.start`,agentId:a});let c=Date.now(),l=await t.createStepRunner(e,o,{signal:t.signal,coreTools:i?[i]:void 0}),u=Date.now()-c;t.emit({type:`agent.end`,agentId:a,durationMs:u}),s.push({agentId:a,output:l,durationMs:u});let d=l.handoff;if(d){let e=d;if(!k(e,new Map(n.map(e=>[e.id,e]))).valid)return{steps:s,output:l.text};t.emit({type:`handoff`,from:e.from,to:e.to,reason:e.reason}),a=e.to,o=e.reason;continue}return{steps:s,output:l.text}}throw new S(i,i)}},j={name:`sequential`,async execute(e,t){let n=t.config.pipeline??[...t.config.agents.values()].map(e=>e.id),r=[],i=e;for(let e of n){if(t.signal.aborted)break;let n=t.config.agents.get(e);if(!n)continue;t.emit({type:`agent.start`,agentId:e});let a=Date.now(),o=await t.createStepRunner(n,i,{signal:t.signal}),s=Date.now()-a;t.emit({type:`agent.end`,agentId:e,durationMs:s}),r.push({agentId:e,output:o,durationMs:s}),i=o.text,t.emit({type:`pipeline.step`,step:r.length-1,agentId:e})}let a=r[r.length-1];return a?{steps:r,output:a.output.text}:{steps:[],output:``}}};async function M(e,t){let{cap:n,executor:r,signal:i,onProgress:a}=t;if(e.length===0)return;let o=Number.isFinite(n)&&n>=1?Math.floor(n):1,s=e.length,c=[...e],l=new Set,u=0,d=0,f,p=!1,m=new AbortController,h=()=>m.abort();i&&(i.aborted?m.abort():i.addEventListener(`abort`,h,{once:!0}));try{for(;c.length>0||l.size>0;){for((m.signal.aborted||p)&&(c.length=0);l.size<o&&c.length>0;){let e=c.shift(),t=d++,n;n=(async()=>{try{await r(e,t,m.signal)}catch(e){p||=(f=e,!0),m.abort()}finally{l.delete(n),u++,a?.(u,s)}})(),l.add(n)}l.size>0&&await Promise.race(l)}}finally{l.size>0&&await Promise.allSettled(l),i&&i.removeEventListener(`abort`,h)}if(p)throw f}const N={name:`parallel`,async execute(e,t){let n=[...t.config.agents.values()],r=t.config.maxConcurrency??n.length,i=n.map(t=>({agentId:t.id,input:e})),a=Array(i.length);t.emit({type:`parallel.fanOut`,agentIds:n.map(e=>e.id)}),await M(i,{cap:r,executor:async(e,n)=>{try{let r=t.config.agents.get(e.agentId);if(!r)return;t.emit({type:`agent.start`,agentId:e.agentId});let i=Date.now(),o=await t.createStepRunner(r,e.input,{signal:t.signal}),s=Date.now()-i;t.emit({type:`agent.end`,agentId:e.agentId,durationMs:s}),a[n]={agentId:e.agentId,output:o,durationMs:s}}catch(n){t.emit({type:`error`,agentId:e.agentId,error:n instanceof Error?n:Error(String(n))})}},signal:t.signal,onProgress:(e,n)=>{t.emit({type:`parallel.fanIn`,completedCount:e,totalCount:n})}});let o=a.filter(e=>e!==void 0);return{steps:o,output:o.map(e=>`## ${e.agentId}\n${e.output.text}`).join(`
3
+
4
+ `)}}},P=n(`otto:orchestrator:strategies:hierarchical`),F=r.object({description:r.string(),assignedTo:r.string().optional()});function I(e){if(!Array.isArray(e))return[];let t=[];for(let n of e){let e=F.safeParse(n);e.success&&t.push(e.data)}return t}function L(e){try{let t=I(JSON.parse(e.trim()));if(t.length>0)return t}catch{}let t=e.match(/\[[\s\S]*\]/);if(t)try{let e=I(JSON.parse(t[0]));if(e.length>0)return e}catch{}return P.warn({textPreview:e.slice(0,200)},`hierarchical supervisor plan parse failed, degrading to single task`),[]}const R={name:`hierarchical`,async execute(e,t){let n=t.config.supervisorId??[...t.config.agents.values()][0]?.id??``;if(!n)return{steps:[],output:``};let r=t.config.agents.get(n);if(!r||r.kind!==`agent`)return{steps:[],output:``};t.emit({type:`agent.start`,agentId:n}),t.emit({type:`hierarchy.delegate`,supervisor:n,worker:``,task:`planning`});let i=Date.now(),a=await t.createStepRunner(r,`You are the supervisor. Break down this task into subtasks:\n\n${e}\n\nFor each subtask, specify:\n1. A clear description\n2. Which agent should execute it (choose from: ${[...t.config.agents.values()].map(e=>e.id).join(`, `)})\n\nRespond with a JSON array of {description, assignedTo}. Output only the JSON array, no other text.`,{signal:t.signal}),o=Date.now()-i;t.emit({type:`agent.end`,agentId:n,durationMs:o});let s=[{agentId:n,output:a,durationMs:o}],c=L(a.text);c.length===0&&(c=[{description:e,assignedTo:void 0}]);let l=[],u=[...t.config.agents.values()].find(e=>e.id!==n)?.id??n,d=c.map(e=>({...e,agentId:e.assignedTo??u}));await M(d,{cap:t.config.maxConcurrency??d.length,executor:async e=>{try{let r=t.config.agents.get(e.agentId);if(!r)return;t.emit({type:`agent.start`,agentId:e.agentId}),t.emit({type:`hierarchy.delegate`,supervisor:n,worker:e.agentId,task:e.description});let i=Date.now(),a=await t.createStepRunner(r,e.description,{signal:t.signal}),o=Date.now()-i;t.emit({type:`agent.end`,agentId:e.agentId,durationMs:o}),l.push({task:e,agentId:e.agentId,output:a,durationMs:o})}catch(n){t.emit({type:`error`,agentId:e.agentId,error:n instanceof Error?n:Error(String(n))})}},signal:t.signal});for(let e of l)s.push({agentId:e.agentId,output:e.output,durationMs:e.durationMs});let f=l.map(e=>`## ${e.task.description} (by ${e.agentId})\n${e.output.text}`),p=[`The subtasks have been completed. Here are the results:`,``,...f,``,`Synthesize these results into a final coherent response for the original task:`,e].join(`
5
+ `);if(t.signal.aborted)return{steps:s,output:f.join(`
6
+
7
+ `)};t.emit({type:`agent.start`,agentId:n});let m=Date.now(),h=await t.createStepRunner(r,p,{signal:t.signal}),g=Date.now()-m;return t.emit({type:`agent.end`,agentId:n,durationMs:g}),s.push({agentId:n,output:h,durationMs:g}),{steps:s,output:h.text}}},z={name:`router`,async execute(e,t){if(!t.router)throw new T(`Router not configured`);let n=[...t.config.agents.values()],r=await t.router.route(e,n),i=t.config.agents.get(r.agentId);if(!i)throw new w(r.agentId);t.emit({type:`routing.decision`,decision:r}),t.emit({type:`agent.start`,agentId:r.agentId});let a=Date.now(),o=await t.createStepRunner(i,e,{signal:t.signal}),s=Date.now()-a;return t.emit({type:`agent.end`,agentId:r.agentId,durationMs:s}),{steps:[{agentId:r.agentId,output:o,durationMs:s}],output:o.text}}};function B(){let e=new D;return e.register(A),e.register(j),e.register(N),e.register(R),e.register(z),e}var V=class{config;agents;router;registry;constructor(e){this.validateConfig(e),this.config=e,this.agents=new Map;for(let t of e.agents)this.agents.set(t.id,t);this.router=e.router?new E(e.router):null,this.registry=B()}getAgents(){return[...this.agents.values()]}getAgent(e){return this.agents.get(e)}registerStrategy(e){this.registry.register(e)}getStrategyNames(){return this.registry.names()}emitEvent(e){if(this.config.onSwarmEvent?.(e),this.config.hookRegistry){let t={id:`swarm:${this.config.runId??this.config.name}`,status:`running`,attempts:0,maxAttempts:1,createdAt:Date.now(),swarmEvent:e};this.config.hookRegistry.emit(`task.started`,{task:t,agent:`swarm:${this.config.name}`})}}buildStrategyContext(e){return{createStepRunner:(t,n,r)=>this.executeMemberTurn(t,n,r?.signal??e,r?.coreTools),emit:e=>this.emitEvent(e),router:this.router,signal:e,config:{name:this.config.name,agents:this.agents,entryAgentId:this.config.entryAgentId,pipeline:this.config.pipeline,supervisorId:this.config.supervisorId,maxHandoffDepth:this.config.maxHandoffDepth,maxConcurrency:this.config.maxConcurrency}}}async run(e,t){let n=t?.signal??new AbortController().signal,r=Date.now(),i=e=>this.emitEvent(e);i({type:`swarm.start`,pattern:this.config.pattern,agentCount:this.agents.size});let a=this.registry.get(this.config.pattern);if(!a)throw new T(`Unknown pattern: "${this.config.pattern}". Registered strategies: ${this.registry.names().join(`, `)}`);try{let t=this.buildStrategyContext(n),o=await a.execute(e,t);return i({type:`swarm.end`,totalDurationMs:Date.now()-r}),{pattern:this.config.pattern,steps:o.steps,output:o.output,durationMs:Date.now()-r}}catch(e){throw i({type:`swarm.end`,totalDurationMs:Date.now()-r}),e}}async executeMemberTurn(e,t,n,r){if(e.kind===`team`)return r?.length&&this.config.onSwarmEvent?.({type:`error`,agentId:e.id,error:Error(`Nested team "${e.id}" does not support core tools (${r.map(e=>e.name).join(`, `)}); descriptors dropped`)}),e.runNested(t,n);let i=e,a=await this.config.runAgentTurn({agentId:i.id,prompt:t,systemPrompt:i.systemPrompt,tools:i.tools,coreTools:r,model:i.model?.id,maxToolTurns:i.maxToolTurns,thinkingLevel:i.thinkingLevel,maxTokens:i.maxTokens,temperature:i.temperature,sessionId:this.config.runId,depth:this.config.depth,signal:n});return{agentId:a.agentId,messages:a.messages??[],text:a.text,handoff:a.handoff,tokenUsage:a.tokenUsage??{input:0,output:0,cacheRead:0},durationMs:a.durationMs}}validateConfig(e){if(!e.name)throw new T(`Swarm name is required`);if(!e.agents||e.agents.length===0)throw new T(`At least one agent is required`);if(!e.runAgentTurn)throw new T(`runAgentTurn factory is required`);let t=new Set;for(let n of e.agents){if(t.has(n.id))throw new T(`Duplicate agent ID: "${n.id}"`);t.add(n.id)}for(let n of e.agents)if(n.kind===`agent`&&n.handoffTargets){for(let e of n.handoffTargets)if(!t.has(e))throw new T(`Agent "${n.id}" references unknown handoff target "${e}"`)}}};function H(e){return new V(e)}export{w as AgentNotFoundError,u as CircuitBreaker,A as HANDOFF_STRATEGY,R as HIERARCHICAL_STRATEGY,S as HandoffDepthError,_ as Orchestrator,N as PARALLEL_STRATEGY,z as ROUTER_STRATEGY,c as RetryPolicy,C as RoutingError,j as SEQUENTIAL_STRATEGY,D as StrategyRegistry,V as Swarm,T as SwarmConfigError,E as SwarmRouter,i as TaskRejectedError,o as TaskStore,B as createDefaultStrategyRegistry,O as createHandoffTool,H as createSwarm,M as runConcurrent,k as validateHandoff};
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/types.ts","../src/task-store.ts","../src/retry.ts","../src/semaphore.ts","../src/executor.ts","../src/background-manager.ts","../src/orchestrator.ts","../src/swarm/errors.ts","../src/swarm/router.ts","../src/swarm/strategy.ts","../src/swarm/handoff.ts","../src/swarm/strategies/handoff.ts","../src/swarm/strategies/sequential.ts","../src/swarm/concurrent.ts","../src/swarm/strategies/parallel.ts","../src/swarm/strategies/hierarchical.ts","../src/swarm/strategies/router.ts","../src/swarm/strategies/index.ts","../src/swarm/swarm.ts"],"sourcesContent":["import type { HookRegistry } from '@x-otto/hooks'\nimport type {\n ModelSlotName,\n SessionMode,\n TaskMode,\n TaskStatus,\n WorkflowOptions,\n} from '@x-otto/orchestration-contracts'\nimport type { RunSessionOptions, RunSessionResult } from './executor'\n\nexport type { TaskStatus } from '@x-otto/orchestration-contracts'\nexport type { WorkflowOptions } from '@x-otto/orchestration-contracts'\n\n/** 工具定义(本地 minimal type,避免 orchestrator 核心依赖 @x-otto/interchange)。 */\nexport interface AgentToolDef {\n name: string\n description: string\n parameters: Record<string, unknown>\n}\n\n/** handoff 目标的纯数据信息(RFC-332 M1:跨边界只传可序列化数据)。 */\nexport interface HandoffTargetInfo {\n id: string\n name: string\n description: string\n}\n\n/**\n * RFC-332 M1:swarm core 工具的纯数据描述符。\n *\n * `extraTools`(AgentToolDef 元数据投影)无法承载 core 工具的执行闭包——旧路径在 leaf\n * 被补成 throw stub(模型可见但必坏)。本描述符替代之:orchestrator 策略只声明\n * 「请 leaf 暴露哪个已注册 core 能力 + 可序列化上下文」,coding leaf 的受限 core\n * resolver 据此构造真实 `AgentTool`。描述符不得含 execute/函数/闭包。\n *\n * 当前唯一注册名是 `handoff_to_agent`;新增 core 工具须同步扩展 leaf resolver 白名单。\n */\nexport interface CoreToolDescriptor {\n source: 'core'\n name: 'handoff_to_agent'\n context: {\n /** 发起方 member id——leaf 校验其与当前 turn 的 agentId 一致(origin 校验)。 */\n from: string\n /** 策略计算后的目标白名单;leaf 只能收窄不能放宽。空数组 = 不暴露工具。 */\n allowedTargets: readonly HandoffTargetInfo[]\n }\n}\n\n/** 思考深度(本地 minimal type,避免 orchestrator 核心依赖 @x-otto/ai)。 */\nexport type ThinkingLevel = 'low' | 'medium' | 'high'\n\n/** swarm member turn 入参(B+ 门禁①:经 TaskExecutor 治理)。 */\nexport interface AgentTurnInput {\n agentId: string\n prompt: string\n systemPrompt?: string\n tools?: AgentToolDef[]\n /**\n * @deprecated RFC-332:额外工具的元数据投影无法承载执行闭包(leaf 曾以 throw stub 补洞)。\n * core 工具(handoff)改走 `coreTools` 描述符 + leaf 受限 resolver;本字段在 M2 策略\n * 切换后删除。leaf 对该字段 fail closed(忽略并诊断),不再生成 stub。\n */\n extraTools?: AgentToolDef[]\n /** RFC-332 M1:core 工具纯数据描述符——leaf 的受限 core resolver 据此构造真实工具。 */\n coreTools?: CoreToolDescriptor[]\n model?: string\n maxToolTurns?: number\n thinkingLevel?: ThinkingLevel\n maxTokens?: number\n temperature?: number\n signal?: AbortSignal\n /** swarm 执行标识(用于权限/审计归属,映射到 toolHookExecutor.sessionId)。 */\n sessionId?: string\n /** 委托深度(递归护栏,映射到 Agent 构造器)。 */\n depth?: number\n}\n\n/** swarm member turn 结果(B+ 门禁①)。 */\nexport interface AgentTurnResult {\n agentId: string\n text: string\n /** 完整消息历史(handoff/hierarchical 策略需要)。 */\n messages?: unknown[]\n /** handoff 请求(handoff 策略需要)。 */\n handoff?: { from: string; to: string; reason: string }\n tokenUsage?: { input: number; output: number; cacheRead: number }\n durationMs: number\n}\n\nexport interface TaskInput {\n /** 任务类别判别字段:'task' 走标准 Session 创建,'swarm_member' 走轻量 Agent 创建。\n * 缺省等价于 'task'(向后兼容 task_delegate/agent_call 路径)。 */\n kind?: 'task' | 'swarm_member'\n /** 发给 subagent 的提示 */\n prompt: string\n /** 指定 agent 名称 — 对齐 task_delegate.subagent / agent_call.agent */\n subagent?: string\n /** 任务类别 — 对齐 task_delegate.category */\n category?: string\n /** 复用的 session ID */\n sessionId?: string\n /** session 策略 — 对齐 task_delegate.sessionMode */\n sessionMode?: SessionMode\n /** 执行模式 — 对齐 task_delegate.mode */\n mode?: TaskMode\n /** 模型槽位 — 对齐 task_delegate.slot / agent_call.slot */\n slot?: ModelSlotName\n /** 显式模型 id(subagent 按能力选型)——优先于 slot。 */\n model?: string\n /** 该任务所处委托深度(root 派发的任务 depth=1)。 */\n depth?: number\n // ── swarm member turn 扩展字段(全部可选,向后兼容 task_delegate/agent_call) ──\n /** swarm 成员自定义 system prompt(覆盖默认)。 */\n systemPrompt?: string\n tools?: AgentToolDef[]\n /** 本轮额外工具(如 handoff 工具)。@deprecated RFC-332:见 AgentTurnInput.extraTools。 */\n extraTools?: AgentToolDef[]\n /** RFC-332 M1:core 工具纯数据描述符(swarm_member 专用)。 */\n coreTools?: CoreToolDescriptor[]\n thinkingLevel?: ThinkingLevel\n maxTokens?: number\n temperature?: number\n maxToolTurns?: number\n}\n\nexport interface TaskOutput {\n text: string\n summary?: string\n tokenUsage?: { input: number; output: number; cacheRead: number }\n durationMs?: number\n // ── swarm member turn 专用(RFC-332 M1:handoff 结果是纯数据,经 Task 链路回传) ──\n /** 完整消息历史(handoff/hierarchical 策略消费;非 swarm 任务恒缺省)。 */\n messages?: unknown[]\n /** leaf 捕获的 handoff intent(orchestrator 策略二次验证后才切换)。 */\n handoff?: { from: string; to: string; reason: string }\n}\n\nexport interface TaskError {\n code: string\n message: string\n retriable: boolean\n}\n\nexport interface Task {\n id: string\n status: TaskStatus\n sessionPolicy: SessionMode\n sessionId?: string\n attempts: number\n maxAttempts: number\n input: TaskInput\n output?: TaskOutput\n error?: TaskError\n createdAt: number\n completedAt?: number\n}\n\nexport interface TaskUnit {\n input: TaskInput\n}\n\nexport interface TaskResult {\n taskId: string\n status: TaskStatus\n output?: TaskOutput\n error?: TaskError\n}\n\nexport class TaskRejectedError extends Error {\n constructor(\n message: string,\n readonly reason: 'circuit_open',\n ) {\n super(message)\n this.name = 'TaskRejectedError'\n }\n}\n\nexport interface OrchestratorOptions {\n hookRegistry: HookRegistry\n /** 由 App 注入:创建子 session → prompt → 提取输出文本(task_delegate/agent_call 路径)。 */\n runSession: (options: RunSessionOptions) => Promise<RunSessionResult>\n /** B+ 门禁①:swarm member turn 执行回调(经 TaskExecutor 获得治理,但用轻量 Agent 创建)。\n * 未提供时 runAgentTurn 回退到 runSession(兼容旧路径)。 */\n runAgentTurn?: (input: AgentTurnInput) => Promise<AgentTurnResult>\n /** 可选:外部 abort 回调 */\n abortTask?: (taskId: string) => void\n workflowConfig?: WorkflowOptions\n maxActiveTasks?: number\n /**\n * TaskStore 容量上限(默认 1000)。store 满时按「终态优先 + 最旧先弃」LRU\n * 驱逐已完成/失败/取消的任务档;pending/running 在飞任务绝不驱逐。治裸 Map 无界增长,\n * 确定性、无时钟依赖(区别于 TTL)。透传 `new TaskStore(maxStoredTasks)`。\n */\n maxStoredTasks?: number\n /** 委托深度上限(默认 1)。root(0)→child1 放行;depth1→child2>1 拒。swarm 深层可经此放宽。 */\n maxDelegationDepth?: number\n}\n","import type { Task, TaskInput, TaskStatus } from './types'\n\n/**\n * 内存任务档案:**单线程内存语义**——API 形态 async 是为未来\n * 换异步后端预留,但读-改-写(get → update merge → set)非原子。在 Node 单线程\n * 事件循环 + 纯内存 Map 下安全(无 await 横跨读写间隙);若替换为真实异步后端\n * (文件/网络),update 必须先加 CAS/版本号,否则 cancel 与终态写入会竞态覆写。\n */\nconst TERMINAL_STATUSES: ReadonlySet<TaskStatus> = new Set<TaskStatus>([\n 'completed',\n 'failed',\n 'cancelled',\n])\n\nexport class TaskStore {\n private readonly tasks = new Map<string, Task>()\n private nextId = 1\n\n /**\n * 容量上限(默认 1000)。store 只收 task_delegate 落库的真任务,但终态任务只增不减——\n * 故加「终态优先 LRU 驱逐」兜底治裸 Map 无界增长(确定性、无时钟依赖,区别于 TTL)。\n */\n private readonly maxStoredTasks: number\n\n constructor(maxStoredTasks = 1000) {\n this.maxStoredTasks = Math.max(1, maxStoredTasks)\n }\n\n private generateId(): string {\n return `task_${Date.now()}_${this.nextId++}`\n }\n\n async create(input: TaskInput): Promise<Task> {\n this.evictForCapacity()\n\n const task: Task = {\n id: this.generateId(),\n status: 'pending',\n sessionPolicy: input.sessionMode ?? 'ephemeral',\n attempts: 0,\n maxAttempts: 3,\n input,\n createdAt: Date.now(),\n }\n\n this.tasks.set(task.id, task)\n return task\n }\n\n /**\n * 容量回收:新建前若已达上限,按「终态优先 + 最旧先弃」驱逐至腾出一席。\n * 驱逐优先级:仅终态(completed/failed/cancelled),按 completedAt ?? createdAt 升序(最旧先弃)。\n * pending/running 在飞任务绝不驱逐——若只剩在飞仍超上限,则越界保活 + warn(绝不丢在飞的活儿)。\n */\n private evictForCapacity(): void {\n let overflow = this.tasks.size - this.maxStoredTasks + 1\n if (overflow <= 0) {\n return\n }\n\n const terminalOldestFirst = [...this.tasks.values()]\n .filter((t) => TERMINAL_STATUSES.has(t.status))\n .sort((a, b) => (a.completedAt ?? a.createdAt) - (b.completedAt ?? b.createdAt))\n\n for (const task of terminalOldestFirst) {\n if (overflow <= 0) {\n break\n }\n this.tasks.delete(task.id)\n overflow--\n }\n\n if (overflow > 0) {\n console.warn(\n `[TaskStore] capacity ${this.maxStoredTasks} exceeded by ${overflow} in-flight task(s); ` +\n `no terminal tasks left to evict — keeping in-flight tasks (will exceed cap).`,\n )\n }\n }\n\n async get(id: string): Promise<Task | undefined> {\n return this.tasks.get(id)\n }\n\n async list(filter?: { status?: TaskStatus }): Promise<Task[]> {\n let result = [...this.tasks.values()]\n if (filter?.status) {\n result = result.filter((t) => t.status === filter.status)\n }\n return result\n }\n\n async update(\n id: string,\n patch: Partial<\n Pick<Task, 'status' | 'output' | 'error' | 'attempts' | 'completedAt' | 'sessionId'>\n >,\n ): Promise<void> {\n const task = this.tasks.get(id)\n if (!task) {\n throw new Error(`Task not found: ${id}`)\n }\n\n Object.assign(task, patch)\n }\n\n async delete(id: string): Promise<boolean> {\n return this.tasks.delete(id)\n }\n}\n","import type { WorkflowOptions } from '@x-otto/orchestration-contracts'\n\nexport interface RetryConfig {\n enabled: boolean\n maxAttempts: number\n backoffMs: number\n backoffMultiplier: number\n}\n\nconst DEFAULT_RETRY: RetryConfig = {\n enabled: true,\n maxAttempts: 3,\n backoffMs: 1000,\n backoffMultiplier: 2,\n}\n\nexport class RetryPolicy {\n private readonly config: RetryConfig\n\n constructor(config?: Partial<RetryConfig>) {\n this.config = { ...DEFAULT_RETRY, ...config }\n }\n\n shouldRetry(attempt: number): boolean {\n return this.config.enabled && attempt < this.config.maxAttempts\n }\n\n getBackoff(attempt: number): number {\n return this.config.backoffMs * this.config.backoffMultiplier ** (attempt - 1)\n }\n\n static fromWorkflowOptions(wf?: WorkflowOptions): RetryPolicy {\n const retry = wf?.retry\n\n return new RetryPolicy({\n enabled: retry?.enabled ?? true,\n maxAttempts: retry?.maxAttempts ?? 3,\n })\n }\n}\n\nexport interface CircuitBreakerConfig {\n enabled: boolean\n failureThreshold: number\n resetTimeoutMs: number\n}\n\nconst DEFAULT_CIRCUIT_BREAKER: CircuitBreakerConfig = {\n enabled: true,\n failureThreshold: 5,\n resetTimeoutMs: 60_000,\n}\n\nexport class CircuitBreaker {\n private readonly enabled: boolean\n private readonly failureThreshold: number\n private readonly resetTimeoutMs: number\n private consecutiveFailures = 0\n private openedAt: number | null = null\n\n constructor(config?: Partial<CircuitBreakerConfig>) {\n const resolvedConfig = { ...DEFAULT_CIRCUIT_BREAKER, ...config }\n\n this.enabled = resolvedConfig.enabled\n this.failureThreshold = resolvedConfig.failureThreshold\n this.resetTimeoutMs = resolvedConfig.resetTimeoutMs\n }\n\n isOpen(): boolean {\n if (!this.enabled) {\n return false\n }\n if (this.openedAt === null) {\n return false\n }\n\n if (Date.now() - this.openedAt >= this.resetTimeoutMs) {\n this.openedAt = null\n this.consecutiveFailures = 0\n return false\n }\n\n return true\n }\n\n success(): void {\n this.consecutiveFailures = 0\n this.openedAt = null\n }\n\n failure(): void {\n this.consecutiveFailures++\n if (this.consecutiveFailures >= this.failureThreshold) {\n this.openedAt = Date.now()\n }\n }\n\n reset(): void {\n this.consecutiveFailures = 0\n this.openedAt = null\n }\n}\n\n/**\n * H5/RFC-016 步骤1:按 target(子代理名)分桶的熔断器。单例全局熔断器在并行委托下会把\n * 不相关 target 的失败计进同一个 consecutiveFailures——一个 flaky 子代理就能熔断全部委托。\n * 按 target 分桶后,各 target 独立计数/熔断,互不污染。\n */\nexport class CircuitBreakerRegistry {\n private readonly breakers = new Map<string, CircuitBreaker>()\n\n constructor(private readonly factory: () => CircuitBreaker) {}\n\n forTarget(target: string): CircuitBreaker {\n let breaker = this.breakers.get(target)\n if (!breaker) {\n breaker = this.factory()\n this.breakers.set(target, breaker)\n }\n return breaker\n }\n\n resetAll(): void {\n for (const breaker of this.breakers.values()) {\n breaker.reset()\n }\n }\n\n /** 每个 target 一个独立熔断器(生产路径)。 */\n static perTarget(config?: Partial<CircuitBreakerConfig>): CircuitBreakerRegistry {\n return new CircuitBreakerRegistry(() => new CircuitBreaker(config))\n }\n\n /** 所有 target 共用同一个熔断器实例——保留旧的全局语义(测试/向后兼容用)。 */\n static single(breaker: CircuitBreaker): CircuitBreakerRegistry {\n return new CircuitBreakerRegistry(() => breaker)\n }\n\n static fromWorkflowOptions(wf?: WorkflowOptions): CircuitBreakerRegistry {\n const circuit = wf?.circuitBreaker\n return CircuitBreakerRegistry.perTarget({\n enabled: circuit?.enabled ?? true,\n failureThreshold: circuit?.failureThreshold ?? 5,\n resetTimeoutMs: circuit?.timeoutMs ?? 60_000,\n })\n }\n}\n","/**\n * H5/RFC-016 步骤1:并发闸(信号量)。把委托并发上限做成可共享的单一对象——\n * callAgent 与 TaskExecutor 注入同一个实例,使 agent_call + task_delegate 走**同一个**全局\n * 上限(之前 callAgent 旁路 executor 的内部计数,无任何闸)。\n *\n * 计数同步、交接式释放(有等待者直接转交槽位,active 不减),无 TOCTOU。\n */\nfunction abortError(): Error {\n const err = new Error('Semaphore acquire aborted')\n err.name = 'AbortError'\n return err\n}\n\nexport class Semaphore {\n private active = 0\n private readonly waiters: Array<() => void> = []\n\n constructor(private readonly max: number) {}\n\n /**\n * 获取一个槽位:满则排队,空出后被 release 直接交接。\n *\n * 可选 `signal`:排队等待期间若 signal abort,则把该等待者从队列摘除并 reject(AbortError)——否则\n * 一个卡死的持票者永不 release 时,被 abort 的排队委托会**永久停在这里唤不醒**(RFC:委托信号量\n * 票泄漏冻全局)。abort 只作用于「尚在排队」阶段;已拿到槽位后的中断由调用方(run 的 finally)负责。\n */\n async acquire(signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n throw abortError()\n }\n if (this.active < this.max) {\n this.active += 1\n return\n }\n await new Promise<void>((resolve, reject) => {\n const waiter = (): void => {\n cleanup()\n resolve()\n }\n const onAbort = (): void => {\n const idx = this.waiters.indexOf(waiter)\n if (idx >= 0) {\n this.waiters.splice(idx, 1)\n }\n cleanup()\n reject(abortError())\n }\n const cleanup = (): void => signal?.removeEventListener('abort', onAbort)\n this.waiters.push(waiter)\n signal?.addEventListener('abort', onAbort, { once: true })\n })\n }\n\n /** 释放一个槽位:有等待者则把槽位交接给它(active 不变),否则 active--。 */\n release(): void {\n const next = this.waiters.shift()\n if (next) {\n next()\n } else {\n this.active -= 1\n }\n }\n\n /**\n * 在一个槽位内执行(含排队等待),完成/抛错后释放。\n * 传 `signal` 时,排队阶段被 abort 会抛 AbortError 且**不**进入 fn、**不**释放(从未获得槽位)。\n */\n async run<T>(fn: () => Promise<T>, signal?: AbortSignal): Promise<T> {\n await this.acquire(signal)\n try {\n return await fn()\n } finally {\n this.release()\n }\n }\n\n /** 当前占用的槽位数(含已交接给等待者的),用于观测/测试。 */\n get activeCount(): number {\n return this.active\n }\n\n /** 排队等待中的数量。 */\n get pendingCount(): number {\n return this.waiters.length\n }\n\n get capacity(): number {\n return this.max\n }\n}\n","import { TaskRejectedError } from './types'\nimport { CircuitBreaker, CircuitBreakerRegistry } from './retry'\nimport { Semaphore } from './semaphore'\n\nimport type { HookRegistry } from '@x-otto/hooks'\nimport type { TaskInput, TaskOutput, TaskResult, TaskUnit } from './types'\nimport type { TaskStore } from './task-store'\nimport type { RetryPolicy } from './retry'\n\nexport interface RunSessionOptions {\n prompt: string\n sessionId?: string\n sessionMode: 'ephemeral' | 'sticky'\n agentName?: string\n slot?: TaskInput['slot']\n /** 显式模型 id(subagent 按能力选型)——优先于 slot。 */\n model?: string\n /** 任务类别(task_delegate.category)——委派子会话据此走 category→slot 智能默认。 */\n category?: string\n /** 子会话承接的委托深度——使其 toolCtx.depth = 该深度,递归闭合护栏。 */\n depth?: number\n /**\n * 任务锚点:宿主据此登记 taskId→活动会话,使 cancel(updateTask/\n * background cancel → abortTask 回调)能中断正在执行的子会话。callAgent 等\n * 非任务路径不携带。\n */\n taskId?: string\n /** 父会话 AbortSignal(旁路,不进 TaskInput/store)——串联中断 in-flight 子会话。 */\n signal?: AbortSignal\n /**\n * Phase 0(task_delegate/job 统一):只读委托——宿主据此从子会话工具集剔除文件改动工具\n * (edit/write/lsp_rename/bash)。background 委托脱离父对话且无审计边界,禁其改主 worktree;\n * 改动型后台活走 /job(worktree 隔离 + diff 审计)。详见 docs/design/task-delegate-job-unification.md。\n */\n readOnly?: boolean\n promptContext?: {\n taskTitle?: string\n taskDescription?: string\n taskFiles?: string[]\n }\n // ── swarm member turn 扩展字段(全部可选) ──\n systemPrompt?: string\n tools?: import('./types').AgentToolDef[]\n extraTools?: import('./types').AgentToolDef[]\n thinkingLevel?: import('./types').ThinkingLevel\n maxTokens?: number\n temperature?: number\n maxToolTurns?: number\n}\n\nexport interface RunSessionResult {\n text: string\n sessionId: string\n tokenUsage?: { input: number; output: number; cacheRead: number }\n durationMs: number\n /** swarm member turn: 完整消息历史(handoff 策略需要检查 tool_calls)。 */\n messages?: unknown[]\n /** swarm member turn: leaf 捕获的 handoff intent(RFC-332 M1 纯数据回传)。 */\n handoff?: { from: string; to: string; reason: string }\n}\n\n/**\n * 纯执行单元内核:只说 TaskUnit/TaskResult/异常三种语言——\n * runTask(同步跑到终态)与 startTask(建档即返、异步跑到终态)。\n * 工具回调形态({success, output, error} 软错误字典)的适配归 Orchestrator。\n */\nexport class TaskExecutor {\n constructor(\n private readonly taskStore: TaskStore,\n private readonly hookRegistry: HookRegistry,\n private readonly retryPolicy: RetryPolicy,\n private readonly circuitBreakers: CircuitBreakerRegistry,\n private readonly runSession: (options: RunSessionOptions) => Promise<RunSessionResult>,\n private readonly semaphore: Semaphore,\n /** B+ 门禁①:swarm member turn 的轻量执行器(有 swarm 字段时优先此而非 runSession)。 */\n private readonly runAgentTurn?: (input: import('./types').AgentTurnInput) => Promise<import('./types').AgentTurnResult>,\n ) {}\n\n private breakerFor(subagent?: string): CircuitBreaker {\n return this.circuitBreakers.forTarget(subagent ?? 'default')\n }\n\n /**\n * 执行单元:封装并发闸/熔断准入 + 建档 + 重试 + store + 事件,\n * 经注入的 runSession 触达引擎 pipeline,跑到终态后返回 TaskResult。\n * orchestrator.dispatchTask 的 sync 路径走此(background 走 startTask)。\n */\n async runTask(unit: TaskUnit, signal?: AbortSignal): Promise<TaskResult> {\n this.assertCircuit(unit.input.subagent)\n const task = await this.register(unit)\n return this.runScheduled(task.id, signal)\n }\n\n /**\n * 熔断准入(快速失败,不排队):该 target 的熔断打开时抛 TaskRejectedError。\n * 并发上限不在此拒绝——交由 Semaphore 排队(槽位排队)。\n */\n private assertCircuit(subagent?: string): void {\n if (this.breakerFor(subagent).isOpen()) {\n throw new TaskRejectedError(\n 'Circuit breaker is open due to repeated failures. Try again later.',\n 'circuit_open',\n )\n }\n }\n\n /** 占用一个并发槽位执行到终态,终态后释放(含排队等待) */\n private async runScheduled(taskId: string, signal?: AbortSignal): Promise<TaskResult> {\n // B8:signal 必须传给 semaphore.run——否则父 abort 时仍在**排队**的任务不会被摘除,\n // 槽位被挂死的子会话占满 → 排队的 sync task_delegate 永不唤醒(无槽位释放)→ 全局冻死。\n // callAgent 走 delegationGate.run(fn, signal) 已是此契约;此处对齐。\n return this.semaphore.run(() => this.executeToCompletion(taskId, signal), signal)\n }\n\n /** 终态写入前的 cancel 检查(updateTask/background cancel 置 cancelled 后不可覆写)。 */\n private async isCancelled(taskId: string): Promise<boolean> {\n const current = await this.taskStore.get(taskId)\n return current?.status === 'cancelled'\n }\n\n /**\n * 建立 Task 记录并广播 task.created。\n * RFC-143 M0:emit 改为 fire-and-forget——task 记录已落盘,调用方只需要 task id 立即返回,\n * 不应被挂起的插件 hook 拖慢任务创建路径。HookRegistry.emit() 自身已有超时兜底(5s)。\n */\n private async register(unit: TaskUnit): Promise<{ id: string }> {\n const task = await this.taskStore.create(unit.input)\n void this.hookRegistry.emit('task.created', { task })\n return task\n }\n\n /**\n * 后台执行单元:建档后立即返回 id,\n * 执行在并发槽位内异步跑到终态。准入同 runTask(熔断打开抛 TaskRejectedError)。\n *\n * executeToCompletion 已把一切异常转终态(不 reject);此 .catch 是防御性外网——\n * 若未来在 try 边界外再引入抛错路径(如 executeToCompletion 首行 store.get),最后一搏\n * 写 failed 终态而非静默僵死 pending + unhandled rejection。\n */\n async startTask(unit: TaskUnit): Promise<{ id: string }> {\n this.assertCircuit(unit.input.subagent)\n const task = await this.register(unit)\n void this.runScheduled(task.id).catch(async (error) => {\n await this.taskStore\n .update(task.id, {\n status: 'failed',\n error: {\n code: 'EXECUTION_FAILED',\n message: error instanceof Error ? error.message : String(error),\n retriable: false,\n },\n completedAt: Date.now(),\n })\n .catch(() => {})\n })\n return { id: task.id }\n }\n\n /** 执行单元内核:跑到终态(含重试循环),返回终态 TaskResult */\n private async executeToCompletion(taskId: string, signal?: AbortSignal): Promise<TaskResult> {\n const task = await this.taskStore.get(taskId)\n if (!task) {\n return {\n taskId,\n status: 'failed',\n error: { code: 'TASK_NOT_FOUND', message: `Task not found: ${taskId}`, retriable: false },\n }\n }\n\n const attempt = task.attempts + 1\n\n try {\n await this.taskStore.update(taskId, { status: 'running', attempts: attempt })\n // RFC-143 M0:fire-and-forget——task 执行链路(下方 runSession/runAgentTurn)不应被\n // 挂起的插件 hook 阻塞在 running 状态判定之前。\n void this.hookRegistry.emit('task.started', {\n task: { ...task, status: 'running' },\n agent: task.input.subagent ?? 'default',\n })\n\n // B+ 门禁①:swarm member turn 走轻量 Agent 创建(非 session 创建)。\n // kind 判别替换旧字段嗅探 heuristic(RFC-107 D1 / M-N6)。\n const isSwarmTurn = task.input.kind === 'swarm_member'\n\n let result: RunSessionResult\n if (isSwarmTurn && this.runAgentTurn) {\n const agentResult = await this.runAgentTurn({\n agentId: task.input.subagent ?? 'agent',\n prompt: task.input.prompt,\n systemPrompt: task.input.systemPrompt,\n tools: task.input.tools,\n extraTools: task.input.extraTools,\n coreTools: task.input.coreTools,\n model: task.input.model,\n maxToolTurns: task.input.maxToolTurns,\n thinkingLevel: task.input.thinkingLevel,\n maxTokens: task.input.maxTokens,\n temperature: task.input.temperature,\n sessionId: task.input.sessionId,\n depth: task.input.depth,\n signal,\n })\n result = {\n text: agentResult.text,\n sessionId: task.input.sessionId ?? '',\n tokenUsage: agentResult.tokenUsage,\n durationMs: agentResult.durationMs,\n messages: agentResult.messages,\n handoff: agentResult.handoff,\n }\n } else {\n result = await this.runSession({\n prompt: task.input.prompt,\n sessionId: task.input.sessionId,\n sessionMode: task.sessionPolicy,\n agentName: task.input.subagent,\n slot: task.input.slot,\n model: task.input.model,\n category: task.input.category,\n depth: task.input.depth,\n taskId,\n signal,\n readOnly: task.input.mode === 'background',\n systemPrompt: task.input.systemPrompt,\n tools: task.input.tools,\n extraTools: task.input.extraTools,\n thinkingLevel: task.input.thinkingLevel,\n maxTokens: task.input.maxTokens,\n temperature: task.input.temperature,\n maxToolTurns: task.input.maxToolTurns,\n })\n }\n\n if (await this.isCancelled(taskId)) {\n return { taskId, status: 'cancelled' }\n }\n\n const output: TaskOutput = {\n text: result.text,\n tokenUsage: result.tokenUsage,\n durationMs: result.durationMs,\n ...(result.messages ? { messages: result.messages } : {}),\n ...(result.handoff ? { handoff: result.handoff } : {}),\n }\n\n await this.taskStore.update(taskId, {\n status: 'completed',\n output,\n sessionId: result.sessionId,\n completedAt: Date.now(),\n })\n\n this.breakerFor(task.input.subagent).success()\n\n // RFC-143 M0:fire-and-forget——task 已到达 completed 终态(taskStore.update 已写入),\n // 调用方(startTask/runTask)不应被挂起的插件 hook 阻塞在终态返回之前。\n void this.hookRegistry.emit('task.completed', {\n task: { ...task, status: 'completed', output },\n result: output,\n })\n\n return {\n taskId,\n status: 'completed',\n output,\n }\n } catch (error) {\n const errMsg = error instanceof Error ? error.message : String(error)\n\n if (await this.isCancelled(taskId)) {\n return { taskId, status: 'cancelled' }\n }\n\n // 重试须保持 abort 感知:父 signal 贯穿递归 + 退避可被 abort 打断,\n // 否则被中断的 sync 任务会占着信号量槽位把 maxAttempts 次重试跑完、无视父 abort。\n const canRetry = this.retryPolicy.shouldRetry(task.attempts) && !signal?.aborted\n if (canRetry) {\n const backoff = this.retryPolicy.getBackoff(task.attempts)\n await sleep(backoff, signal)\n if (!signal?.aborted) {\n return this.executeToCompletion(taskId, signal)\n }\n }\n\n this.breakerFor(task.input.subagent).failure()\n\n const taskError = {\n code: 'EXECUTION_FAILED',\n message: errMsg,\n retriable: false,\n }\n\n await this.taskStore.update(taskId, {\n status: 'failed',\n error: taskError,\n completedAt: Date.now(),\n })\n\n // RFC-143 M0:fire-and-forget——task 已到达 failed 终态,catch 块中若 emit 挂起会让\n // executeToCompletion 卡在错误路径里,永远到不了下面的 return,比正常路径更需要不阻塞。\n void this.hookRegistry.emit('task.failed', {\n task: { ...task, status: 'failed' },\n error: taskError,\n })\n\n return {\n taskId,\n status: 'failed',\n error: taskError,\n }\n }\n }\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) return Promise.resolve()\n return new Promise((resolve) => {\n let timer: ReturnType<typeof setTimeout>\n const onAbort = (): void => {\n clearTimeout(timer)\n resolve()\n }\n timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n signal?.addEventListener('abort', onAbort, { once: true })\n })\n}\n","import type { BackgroundOutput, Result } from '@x-otto/orchestration-contracts'\nimport type { TaskStore } from './task-store'\n\nexport class BackgroundManager {\n constructor(\n private readonly taskStore: TaskStore,\n private readonly abortTask?: (taskId: string) => void,\n ) {}\n\n async getOutput(id: string): Promise<Result<BackgroundOutput>> {\n const task = await this.taskStore.get(id)\n if (!task) {\n return { ok: false, error: `Task not found id: ${id}` }\n }\n\n if (task.status === 'completed') {\n return { ok: true, value: { status: 'completed', output: task.output?.text } }\n }\n\n if (task.status === 'failed') {\n return { ok: false, error: task.error?.message ?? 'Task failed' }\n }\n\n return { ok: true, value: { status: task.status } }\n }\n\n async cancel(id: string): Promise<Result<void>> {\n const task = await this.taskStore.get(id)\n\n if (!task) {\n return { ok: false, error: `Task not found id: ${id}` }\n }\n\n if (task.status === 'completed' || task.status === 'failed' || task.status === 'cancelled') {\n return { ok: false, error: `Task already in terminal state: ${task.status}, id: ${id}` }\n }\n\n await this.taskStore.update(id, {\n status: 'cancelled',\n completedAt: Date.now(),\n })\n\n if (this.abortTask) {\n this.abortTask(id)\n }\n\n return { ok: true, value: undefined }\n }\n}\n","import type { HookRegistry } from '@x-otto/hooks'\nimport type {\n GetTask,\n ListTasks,\n UpdateTask,\n TaskDispatch,\n CallAgent,\n GetBackgroundOutput,\n CancelBackground,\n Result,\n} from '@x-otto/orchestration-contracts'\nimport { checkDelegationDepth } from '@x-otto/orchestration-contracts'\nimport type { OrchestratorOptions, TaskUnit, AgentTurnInput, AgentTurnResult } from './types'\nimport type { RunSessionOptions, RunSessionResult } from './executor'\n\nimport { TaskStore } from './task-store'\nimport { TaskExecutor } from './executor'\nimport { BackgroundManager } from './background-manager'\nimport { RetryPolicy, CircuitBreakerRegistry } from './retry'\nimport { Semaphore } from './semaphore'\n\nexport class Orchestrator {\n readonly taskStore: TaskStore\n private readonly executor: TaskExecutor\n private readonly backgroundManager: BackgroundManager\n private readonly hookRegistry: HookRegistry\n private readonly circuitBreakers: CircuitBreakerRegistry\n private readonly delegationGate: Semaphore\n private readonly runSession: (options: RunSessionOptions) => Promise<RunSessionResult>\n private readonly maxDelegationDepth: number\n\n constructor(options: OrchestratorOptions) {\n const {\n hookRegistry,\n runSession,\n runAgentTurn,\n abortTask,\n workflowConfig,\n maxActiveTasks = 10,\n maxStoredTasks,\n maxDelegationDepth = 1,\n } = options\n\n this.hookRegistry = hookRegistry\n this.runSession = runSession\n this.maxDelegationDepth = maxDelegationDepth\n this.taskStore = new TaskStore(maxStoredTasks)\n const retryPolicy = RetryPolicy.fromWorkflowOptions(workflowConfig)\n this.circuitBreakers = CircuitBreakerRegistry.fromWorkflowOptions(workflowConfig)\n this.delegationGate = new Semaphore(maxActiveTasks)\n\n this.executor = new TaskExecutor(\n this.taskStore,\n hookRegistry,\n retryPolicy,\n this.circuitBreakers,\n runSession,\n this.delegationGate,\n runAgentTurn,\n )\n\n this.backgroundManager = new BackgroundManager(this.taskStore, abortTask)\n }\n\n dispatchTask: TaskDispatch = async (args) => {\n const { childDepth, exceeded } = checkDelegationDepth(args.depth, this.maxDelegationDepth)\n if (exceeded) {\n return fail(\n `Delegation depth limit (${this.maxDelegationDepth}) reached — complete this subtask yourself instead of delegating further.`,\n )\n }\n\n const unit: TaskUnit = {\n input: {\n prompt: args.prompt,\n subagent: args.subagent,\n category: args.category,\n sessionId: args.sessionId,\n sessionMode: args.sessionMode ?? 'ephemeral',\n mode: args.mode,\n slot: args.slot,\n model: args.model,\n depth: childDepth,\n },\n }\n\n if (args.mode === 'background') {\n return attempt(async () => {\n const { id } = await this.executor.startTask(unit)\n return { id, status: 'pending' as const, output: `Background task created: ${id}` }\n })\n }\n\n try {\n const result = await this.executor.runTask(unit, args.signal)\n return result.status === 'completed'\n ? ok({ id: result.taskId, status: result.status, output: result.output?.text })\n : fail(result.error?.message ?? 'Unknown error')\n } catch (error) {\n return fail(error)\n }\n }\n\n /**\n * agent 直调——**旁路任务内核**:不建档、不进 store、不重试,\n * 直连宿主 runSession 的轻量探询语义(agent_call)。**但仍受治理**:\n * 共享同一并发闸 delegationGate + per-target 熔断(与 task_delegate 同一 CircuitBreakerRegistry)\n * + 委托深度护栏——agent_call 不是无治理通道,只是不走任务建档/重试。\n */\n callAgent: CallAgent = async (agent, prompt, options) => {\n const { childDepth, exceeded } = checkDelegationDepth(options?.depth, this.maxDelegationDepth)\n if (exceeded) {\n return fail(\n `Delegation depth limit (${this.maxDelegationDepth}) reached — complete this subtask yourself instead of delegating further.`,\n )\n }\n\n const breaker = this.circuitBreakers.forTarget(agent)\n if (breaker.isOpen()) {\n return fail('Circuit breaker is open due to repeated failures. Try again later.')\n }\n\n return this.delegationGate.run(async () => {\n try {\n const result = await this.runSession({\n prompt,\n sessionMode: 'ephemeral',\n agentName: agent,\n slot: options?.slot,\n model: options?.model,\n depth: childDepth,\n signal: options?.signal,\n })\n breaker.success()\n return ok(result.text)\n } catch (error) {\n breaker.failure()\n return fail(error)\n }\n }, options?.signal)\n }\n\n /**\n * swarm member turn — 经 TaskExecutor 执行(B+ 门禁①:成员 turn Task 化)。\n * TaskExecutor 检测 swarm 字段时走 runAgentTurn 轻量回调,否则走 runSession。\n */\n async runAgentTurn(input: AgentTurnInput): Promise<AgentTurnResult> {\n const unit = {\n input: {\n kind: 'swarm_member' as const,\n prompt: input.prompt,\n subagent: input.agentId,\n systemPrompt: input.systemPrompt,\n tools: input.tools,\n extraTools: input.extraTools,\n coreTools: input.coreTools,\n model: input.model,\n maxToolTurns: input.maxToolTurns,\n thinkingLevel: input.thinkingLevel,\n maxTokens: input.maxTokens,\n temperature: input.temperature,\n sessionMode: 'ephemeral' as const,\n sessionId: input.sessionId,\n depth: input.depth,\n },\n }\n\n const result = await this.executor.runTask(unit, input.signal)\n\n if (result.status === 'completed') {\n return {\n agentId: input.agentId,\n text: result.output?.text ?? '',\n messages: result.output?.messages,\n handoff: result.output?.handoff,\n tokenUsage: result.output?.tokenUsage,\n durationMs: result.output?.durationMs ?? 0,\n }\n }\n\n throw new Error(\n result.error?.message ?? `Swarm member turn failed: ${result.status}`,\n )\n }\n\n getTask: GetTask = async (id) => {\n const task = await this.taskStore.get(id)\n if (!task) {\n return fail(`Task not found: ${id}`)\n }\n\n return ok({\n id: task.id,\n status: task.status,\n prompt: task.input.prompt,\n output: task.output?.text,\n error: task.error?.message,\n })\n }\n\n listTasks: ListTasks = async (status) => {\n const filter = status && status !== 'all' ? { status } : undefined\n\n const tasks = await this.taskStore.list(filter)\n\n return ok(\n tasks.map((t) => ({\n id: t.id,\n prompt: t.input.prompt,\n status: t.status,\n })),\n )\n }\n\n updateTask: UpdateTask = async (id, action) => {\n const task = await this.taskStore.get(id)\n if (!task) {\n return fail(`Task not found: ${id}`)\n }\n\n if (action === 'cancel') {\n // cancel 机制(终态护栏 + 置 cancelled + abortTask)单源在 BackgroundManager;\n // updateTask 仅在其上叠加 task.cancelled 钩子与可读返回。\n const cancelled = await this.backgroundManager.cancel(id)\n if (!cancelled.ok) {\n return fail(cancelled.error)\n }\n await this.hookRegistry.emit('task.cancelled', { taskId: id })\n return ok(`Task ${id} cancelled`)\n }\n\n if (action === 'retry') {\n if (task.status !== 'failed') {\n return fail(`Can only retry failed tasks. Current status: ${task.status}`)\n }\n const result = await this.dispatchTask({\n prompt: task.input.prompt,\n subagent: task.input.subagent,\n category: task.input.category,\n mode: task.input.mode ?? 'sync',\n sessionId: task.input.sessionId,\n sessionMode: task.input.sessionMode,\n slot: task.input.slot,\n model: task.input.model,\n })\n return result.ok ? ok(result.value.output ?? 'Retry completed') : fail(result.error)\n }\n\n return fail(`Unknown action: ${action}`)\n }\n\n getBackgroundOutput: GetBackgroundOutput = async (id) => {\n return this.backgroundManager.getOutput(id)\n }\n\n cancelBackground: CancelBackground = async (id) => {\n return this.backgroundManager.cancel(id)\n }\n\n dispose(): void {\n this.circuitBreakers.resetAll()\n }\n}\n\nfunction ok<T>(value: T): Result<T> {\n return { ok: true, value }\n}\n\nfunction fail(error: unknown): { ok: false; error: string } {\n return { ok: false, error: errorMessage(error) }\n}\n\nasync function attempt<T>(fn: () => Promise<T>): Promise<Result<T>> {\n try {\n return ok(await fn())\n } catch (error) {\n return fail(error)\n }\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n","import { AgentError } from '@x-otto/shared'\n\nexport class HandoffDepthError extends AgentError {\n readonly depth: number\n readonly maxDepth: number\n\n constructor(depth: number, maxDepth: number) {\n super(`Handoff depth ${depth} exceeds max ${maxDepth}`, {\n code: 'SWARM_HANDOFF_DEPTH_EXCEEDED',\n })\n this.name = 'HandoffDepthError'\n this.depth = depth\n this.maxDepth = maxDepth\n }\n}\n\nexport class RoutingError extends AgentError {\n constructor(message: string) {\n super(message, { code: 'SWARM_ROUTING_ERROR' })\n this.name = 'RoutingError'\n }\n}\n\nexport class AgentNotFoundError extends AgentError {\n readonly agentId: string\n\n constructor(agentId: string) {\n super(`Agent \"${agentId}\" not found in swarm`, {\n code: 'SWARM_AGENT_NOT_FOUND',\n })\n this.name = 'AgentNotFoundError'\n this.agentId = agentId\n }\n}\n\nexport class SwarmConfigError extends AgentError {\n constructor(message: string) {\n super(message, { code: 'SWARM_CONFIG_ERROR' })\n this.name = 'SwarmConfigError'\n }\n}\n","import type { RouterConfig, RoutingDecision, RouteRule, SwarmAgentDef } from './types'\nimport { RoutingError } from './errors'\n\nexport class SwarmRouter {\n private readonly config: RouterConfig\n private roundRobinIndex = 0\n\n constructor(config: RouterConfig) {\n if (config.strategy === 'llm' && !config.customRouter) {\n throw new RoutingError(\n \"Routing strategy 'llm' requires a customRouter (inject the real LLM routing call).\",\n )\n }\n this.config = config\n }\n\n async route(input: string, agents: SwarmAgentDef[]): Promise<RoutingDecision> {\n const { strategy } = this.config\n\n switch (strategy) {\n case 'rule':\n return this.routeByRule(input, agents)\n case 'round-robin':\n return this.routeRoundRobin(agents)\n case 'random':\n return this.routeRandom(agents)\n case 'llm':\n return this.routeByLlm(input, agents)\n default:\n throw new RoutingError(`Unknown routing strategy: ${strategy as string}`)\n }\n }\n\n /** 基于规则路由 */\n private routeByRule(input: string, agents: SwarmAgentDef[]): RoutingDecision {\n const rules = this.config.rules ?? []\n const lowerInput = input.toLowerCase()\n\n const sorted = [...rules].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0))\n\n for (const rule of sorted) {\n if (this.matchRule(rule, lowerInput)) {\n const agent = agents.find((a) => a.id === rule.agentId)\n if (agent) {\n return {\n agentId: rule.agentId,\n reason: `Matched rule for \"${agent.name}\"`,\n confidence: 1.0,\n }\n }\n }\n }\n\n return this.fallback(agents, 'No rule matched')\n }\n\n /** 轮转路由 */\n private routeRoundRobin(agents: SwarmAgentDef[]): RoutingDecision {\n const agent = agents[this.roundRobinIndex % agents.length]!\n this.roundRobinIndex++\n\n return {\n agentId: agent.id,\n reason: `Round-robin selection (index ${this.roundRobinIndex - 1})`,\n confidence: 1.0,\n }\n }\n\n /** 随机路由 */\n private routeRandom(agents: SwarmAgentDef[]): RoutingDecision {\n const rand = this.config.random?.random ?? Math.random\n const index = Math.floor(rand() * agents.length)\n const agent = agents[index]!\n\n return {\n agentId: agent.id,\n reason: 'Random selection',\n confidence: 1.0 / agents.length,\n }\n }\n\n /**\n * LLM 路由 —— 委托宿主注入的 customRouter(真实 LLM 调用)。\n * 旧 'custom' 枚举值已坍缩归入此路径(两者语义相同:host-injected 函数)。\n */\n private async routeByLlm(input: string, agents: SwarmAgentDef[]): Promise<RoutingDecision> {\n const { customRouter } = this.config\n if (!customRouter) {\n throw new RoutingError(\"Routing strategy 'llm' requires a customRouter.\")\n }\n return customRouter(input, agents)\n }\n\n /** Fallback 到默认 Agent */\n private fallback(agents: SwarmAgentDef[], reason: string): RoutingDecision {\n const fallbackId = this.config.fallbackAgentId ?? agents[0]?.id\n if (!fallbackId) {\n throw new RoutingError(`${reason} and no fallback agent configured`)\n }\n\n return {\n agentId: fallbackId,\n reason: `${reason} — using fallback agent`,\n confidence: 0,\n }\n }\n\n /** 匹配单条规则 */\n private matchRule(rule: RouteRule, input: string): boolean {\n if (rule.match instanceof RegExp) {\n return rule.match.test(input)\n }\n\n return rule.match.some((keyword) => input.includes(keyword.toLowerCase()))\n }\n}\n","import type { SwarmAgentDef, SwarmEventHandler, SwarmTurnResult } from './types'\n\nexport interface StepResult {\n agentId: string\n output: SwarmTurnResult\n durationMs: number\n}\n\nexport interface StrategyContext {\n /**\n * 轻量 step 执行器——经 createStepRunner 派发。\n * team 成员的 runNested 由策略自行分派(agentDef.kind === 'team')。\n * 并发由策略直接 import `runConcurrent`(intra-team 扇出原语)组织——非经 ctx 字段。\n */\n createStepRunner: (\n agentDef: import('./types').SwarmAgentDef,\n input: string,\n options?: { signal?: AbortSignal; coreTools?: import('../types').CoreToolDescriptor[] },\n ) => Promise<import('./types').SwarmTurnResult>\n /** 事件总线。 */\n emit: SwarmEventHandler\n /** 可选路由器(handoff/router pattern 用)。 */\n router?: Router\n /** AbortSignal。 */\n signal: AbortSignal\n /** 配置快照。 */\n config: StrategyConfig\n}\n\nexport interface StrategyConfig {\n name: string\n agents: Map<string, SwarmAgentDef>\n entryAgentId?: string\n pipeline?: string[]\n supervisorId?: string\n maxHandoffDepth?: number\n maxConcurrency?: number\n}\n\n\nexport interface OrchestrationStrategy {\n /** 策略名(注册表 key)。 */\n readonly name: string\n /**\n * 执行编排。ctx 由 Swarm.run() 从 config + runtime 构造。\n * 策略内经 ctx.createStepRunner 派单步、直接 import runConcurrent 组织 intra-team 并发。\n */\n execute(input: string, ctx: StrategyContext): Promise<StrategyResult>\n}\n\nexport interface StrategyResult {\n /** 所有 step 的执行记录。 */\n steps: StepResult[]\n /** 最终输出文本。 */\n output: string\n}\n\nexport class StrategyRegistry {\n private readonly strategies = new Map<string, OrchestrationStrategy>()\n\n register(strategy: OrchestrationStrategy): void {\n if (this.strategies.has(strategy.name)) {\n throw new Error(`Orchestration strategy \"${strategy.name}\" is already registered`)\n }\n this.strategies.set(strategy.name, strategy)\n }\n\n get(name: string): OrchestrationStrategy | undefined {\n return this.strategies.get(name)\n }\n\n has(name: string): boolean {\n return this.strategies.has(name)\n }\n\n names(): string[] {\n return [...this.strategies.keys()]\n }\n}\n\nexport interface Router {\n route(\n input: string,\n agents: SwarmAgentDef[],\n ): Promise<{ agentId: string; reason: string; confidence: number }>\n}\n","import type { AgentTool, ToolResult } from '@x-otto/interchange'\nimport type { ZodType } from '@x-otto/ai'\nimport { z } from 'zod'\nimport type { HandoffRequest, SwarmAgentDef, SwarmAgentId } from './types'\n\n/**\n * 创建 handoff 工具 — 注入到每个 SwarmAgent 的工具列表中,\n * 允许 Agent 通过工具调用发起 handoff。\n *\n * 灵感来自 OpenAI Swarm 的 handoff 模式:\n * Agent 在对话过程中自行决定何时、向谁交接控制权。\n *\n * RFC-332 M1:参数从 `SwarmAgentDef[]` 收窄为最小纯数据结构(本函数只消费\n * id/name/description)——使 coding leaf 的 core resolver 能用可序列化的\n * `HandoffTargetInfo[]`(经 `CoreToolDescriptor` 跨边界传输)直接构造真实工具。\n */\nexport function createHandoffTool(\n currentAgentId: SwarmAgentId,\n availableTargets: readonly { id: SwarmAgentId; name: string; description: string }[],\n onHandoff: (request: HandoffRequest) => void,\n): AgentTool {\n const targetDescriptions = availableTargets\n .map((t) => `- \"${t.id}\": ${t.name} — ${t.description}`)\n .join('\\n')\n\n const targetIds = availableTargets.map((t) => t.id)\n\n return {\n name: 'handoff_to_agent',\n description: `Transfer control to another agent in the swarm. Available targets:\\n${targetDescriptions}`,\n parameters: z.object({\n target_agent_id: z\n .string()\n .describe(`The ID of the agent to hand off to. Must be one of: ${targetIds.join(', ')}`),\n reason: z\n .string()\n .describe('Why you are transferring to this agent — will be provided as context.'),\n summary: z\n .string()\n .optional()\n .describe('Optional summary of work done so far to provide context to the target agent.'),\n }) as ZodType,\n readonly: true,\n execute: async (ctx): Promise<ToolResult> => {\n const { target_agent_id, reason, summary } = ctx.params as {\n target_agent_id: string\n reason: string\n summary?: string\n }\n\n if (!targetIds.includes(target_agent_id)) {\n return {\n content: [\n {\n type: 'text',\n text: `Invalid target agent \"${target_agent_id}\". Available targets: ${targetIds.join(', ')}`,\n },\n ],\n isError: true,\n }\n }\n\n const request: HandoffRequest = {\n from: currentAgentId,\n to: target_agent_id,\n reason: summary ? `${reason}\\n\\nContext: ${summary}` : reason,\n }\n\n onHandoff(request)\n\n return {\n content: [\n {\n type: 'text',\n text: `Handoff initiated to \"${target_agent_id}\". Reason: ${reason}`,\n },\n ],\n }\n },\n }\n}\n\nexport function validateHandoff(\n request: HandoffRequest,\n agents: Map<string, SwarmAgentDef>,\n): { valid: boolean; error?: string } {\n const fromAgent = agents.get(request.from)\n const toAgent = agents.get(request.to)\n\n if (!fromAgent) {\n return { valid: false, error: `Source agent \"${request.from}\" not found` }\n }\n\n if (!toAgent) {\n return { valid: false, error: `Target agent \"${request.to}\" not found` }\n }\n\n if (\n fromAgent.kind === 'agent' &&\n fromAgent.handoffTargets &&\n fromAgent.handoffTargets.length > 0 &&\n !fromAgent.handoffTargets.includes(request.to)\n ) {\n return {\n valid: false,\n error: `Agent \"${request.from}\" is not allowed to handoff to \"${request.to}\". Allowed: [${fromAgent.handoffTargets.join(', ')}]`,\n }\n }\n\n return { valid: true }\n}\n","import { validateHandoff } from '../handoff'\nimport { AgentNotFoundError, HandoffDepthError } from '../errors'\n\nimport type { OrchestrationStrategy, StrategyContext, StrategyResult } from '../strategy'\nimport type { HandoffRequest } from '../types'\nimport type { CoreToolDescriptor } from '../../types'\n\nexport const HANDOFF_STRATEGY: OrchestrationStrategy = {\n name: 'handoff',\n\n async execute(input: string, ctx: StrategyContext): Promise<StrategyResult> {\n const agents = [...ctx.config.agents.values()]\n const entryId = ctx.config.entryAgentId ?? agents[0]?.id\n if (!entryId) {\n return { steps: [], output: '' }\n }\n\n const maxDepth = ctx.config.maxHandoffDepth ?? 10\n let currentAgentId = entryId\n let currentInput = input\n const steps: StrategyResult['steps'] = []\n\n for (let depth = 0; depth < maxDepth; depth++) {\n if (ctx.signal.aborted) break\n\n const agentDef = ctx.config.agents.get(currentAgentId)\n if (!agentDef) throw new AgentNotFoundError(currentAgentId)\n\n let handoffTargets = agents.filter((a) => a.id !== currentAgentId)\n if (\n agentDef.kind === 'agent' &&\n agentDef.handoffTargets &&\n agentDef.handoffTargets.length > 0\n ) {\n const allowed = agentDef.handoffTargets\n handoffTargets = handoffTargets.filter((a) => allowed.includes(a.id))\n }\n\n // RFC-332 M1:策略只声明纯数据 descriptor(不再创建 AgentTool 闭包穿越边界)。\n // leaf 的 core resolver 据此构造真实 handoff 工具;intent 经 result.handoff 纯数据回传。\n const handoffDescriptor: CoreToolDescriptor | null =\n handoffTargets.length > 0\n ? {\n source: 'core',\n name: 'handoff_to_agent',\n context: {\n from: currentAgentId,\n allowedTargets: handoffTargets.map((t) => ({\n id: t.id,\n name: t.name,\n description: t.description,\n })),\n },\n }\n : null\n\n ctx.emit({ type: 'agent.start', agentId: currentAgentId })\n const start = Date.now()\n\n // team 与 member 的分派统一经 createStepRunner→executeMemberTurn(team→runNested,\n // 不支持 core 工具并诊断)单源;handoff descriptor 仅对 member 有意义。\n const output = await ctx.createStepRunner(agentDef, currentInput, {\n signal: ctx.signal,\n coreTools: handoffDescriptor ? [handoffDescriptor] : undefined,\n })\n\n const dur = Date.now() - start\n ctx.emit({ type: 'agent.end', agentId: currentAgentId, durationMs: dur })\n steps.push({ agentId: currentAgentId, output, durationMs: dur })\n\n // RFC-332 M1:handoff intent 从 result 纯数据读取(leaf 已按 descriptor 白名单校验,\n // 此处 orchestrator 二次验证——leaf 校验不能替代策略终审)。\n const pendingHandoff = output.handoff\n if (pendingHandoff) {\n const handoff: HandoffRequest = pendingHandoff\n const validation = validateHandoff(handoff, new Map(agents.map((a) => [a.id, a])))\n if (!validation.valid) {\n return { steps, output: output.text }\n }\n\n ctx.emit({\n type: 'handoff',\n from: handoff.from,\n to: handoff.to,\n reason: handoff.reason,\n })\n\n currentAgentId = handoff.to\n currentInput = handoff.reason\n continue\n }\n\n return { steps, output: output.text }\n }\n\n throw new HandoffDepthError(maxDepth, maxDepth)\n },\n}\n","import type { OrchestrationStrategy, StrategyContext, StrategyResult } from '../strategy'\n\nexport const SEQUENTIAL_STRATEGY: OrchestrationStrategy = {\n name: 'sequential',\n\n async execute(input: string, ctx: StrategyContext): Promise<StrategyResult> {\n const pipeline = ctx.config.pipeline ?? [...ctx.config.agents.values()].map((a) => a.id)\n const steps: StrategyResult['steps'] = []\n let currentInput = input\n\n for (const agentId of pipeline) {\n if (ctx.signal.aborted) break\n\n const agentDef = ctx.config.agents.get(agentId)\n if (!agentDef) continue\n\n ctx.emit({ type: 'agent.start', agentId })\n const startTime = Date.now()\n\n const output = await ctx.createStepRunner(agentDef, currentInput, { signal: ctx.signal })\n\n const durationMs = Date.now() - startTime\n ctx.emit({ type: 'agent.end', agentId, durationMs })\n\n steps.push({ agentId, output, durationMs })\n\n currentInput = output.text\n ctx.emit({ type: 'pipeline.step', step: steps.length - 1, agentId })\n }\n\n const finalStep = steps[steps.length - 1]\n if (!finalStep) {\n return { steps: [], output: '' }\n }\n\n return { steps, output: finalStep.output.text }\n },\n}\n","export interface ConcurrentOptions<T> {\n /** 并发上限。 */\n cap: number\n /**\n * 单步执行器。第三参 `signal` 在「兄弟失败」或「外部 signal abort」时触发——执行器可据此取消\n * 在途工作(不取消也无妨:仍不会启动新任务、且失败会上抛)。\n */\n executor: (step: T, index: number, signal: AbortSignal) => Promise<void>\n /** 可选外部 AbortSignal——阻止新任务启动;经内部控制器转发给执行器(可中断在途)。 */\n signal?: AbortSignal\n /**\n * 可选进度回调:每次一个任务完成(或出错)时调用。\n * 调用方可在此 emit fan-in 事件(如 `{type:'parallel.fanIn',completedCount,totalCount}`)。\n */\n onProgress?: (completedCount: number, totalCount: number) => void\n}\n\n/**\n * 全仓唯一并发池原语(M24-02)。\n *\n * endgame review 修复(弃跑兄弟):旧实现 `await Promise.race(running)` 在某成员 reject 时直接外抛,\n * 其余在途任务变成**无 await 的孤儿** → 后续 reject 触发 unhandledRejection、且谁也不取消它们。\n * 现在:① 每个任务包成**永不 reject** 的 wrapper(race 不再因兄弟失败而抛,所有任务都被排空);\n * ② 首个失败记录 firstError 并 abort 内部控制器(转发给执行器取消在途)+ 清空 pending(不再启动新任务);\n * ③ finally 里 allSettled 排空残余,确保无孤儿;④ 全部结束后再上抛 firstError。\n * 顺带修了旧实现的一个潜伏 bug:外部 signal abort 且仍有 pending 时,旧循环会空转(running 排空后\n * pending 非空、canStart=false、无 await → CPU busy loop)——现在 abort/fail 都清 pending、干净退出。\n */\nexport async function runConcurrent<T>(\n steps: readonly T[],\n options: ConcurrentOptions<T>,\n): Promise<void> {\n const { cap, executor, signal, onProgress } = options\n if (steps.length === 0) return\n\n const safeCap = Number.isFinite(cap) && cap >= 1 ? Math.floor(cap) : 1\n\n const total = steps.length\n const pending = [...steps]\n const running = new Set<Promise<void>>()\n let completed = 0\n let i = 0\n let firstError: unknown\n let failed = false\n\n const internal = new AbortController()\n const onExternalAbort = (): void => internal.abort()\n if (signal) {\n if (signal.aborted) internal.abort()\n else signal.addEventListener('abort', onExternalAbort, { once: true })\n }\n\n try {\n while (pending.length > 0 || running.size > 0) {\n if (internal.signal.aborted || failed) {\n pending.length = 0\n }\n\n while (running.size < safeCap && pending.length > 0) {\n const step = pending.shift()!\n const idx = i++\n let p!: Promise<void>\n p = (async () => {\n try {\n await executor(step, idx, internal.signal)\n } catch (err) {\n if (!failed) {\n firstError = err\n failed = true\n }\n internal.abort()\n } finally {\n running.delete(p)\n completed++\n onProgress?.(completed, total)\n }\n })()\n running.add(p)\n }\n\n if (running.size > 0) {\n await Promise.race(running)\n }\n }\n } finally {\n if (running.size > 0) await Promise.allSettled(running)\n if (signal) signal.removeEventListener('abort', onExternalAbort)\n }\n\n if (failed) {\n throw firstError\n }\n}\n","import { runConcurrent } from '../concurrent'\n\nimport type { OrchestrationStrategy, StrategyContext, StrategyResult } from '../strategy'\n\nexport const PARALLEL_STRATEGY: OrchestrationStrategy = {\n name: 'parallel',\n\n async execute(input: string, ctx: StrategyContext): Promise<StrategyResult> {\n const agents = [...ctx.config.agents.values()]\n const cap = ctx.config.maxConcurrency ?? agents.length\n const tasks = agents.map((a) => ({ agentId: a.id, input }))\n const slots: Array<StrategyResult['steps'][number] | undefined> = new Array(tasks.length)\n\n ctx.emit({ type: 'parallel.fanOut', agentIds: agents.map((a) => a.id) })\n\n await runConcurrent(tasks, {\n cap,\n executor: async (task, index) => {\n try {\n const agentDef = ctx.config.agents.get(task.agentId)\n if (!agentDef) return\n\n ctx.emit({ type: 'agent.start', agentId: task.agentId })\n const start = Date.now()\n\n // team 与 member 的分派统一经 createStepRunner→executeMemberTurn(team→runNested)单源。\n const output = await ctx.createStepRunner(agentDef, task.input, { signal: ctx.signal })\n\n const dur = Date.now() - start\n ctx.emit({ type: 'agent.end', agentId: task.agentId, durationMs: dur })\n slots[index] = { agentId: task.agentId, output, durationMs: dur }\n } catch (err) {\n ctx.emit({\n type: 'error',\n agentId: task.agentId,\n error: err instanceof Error ? err : new Error(String(err)),\n })\n }\n },\n signal: ctx.signal,\n onProgress: (completed, total) => {\n ctx.emit({ type: 'parallel.fanIn', completedCount: completed, totalCount: total })\n },\n })\n\n const results = slots.filter(\n (s): s is StrategyResult['steps'][number] => s !== undefined,\n )\n const combined = results.map((r) => `## ${r.agentId}\\n${r.output.text}`).join('\\n\\n')\n return { steps: results, output: combined }\n },\n}\n","import { createLogger } from '@x-otto/shared'\nimport { z } from 'zod'\n\nimport { runConcurrent } from '../concurrent'\n\nimport type { OrchestrationStrategy, StrategyContext, StrategyResult } from '../strategy'\nimport type { HierarchicalTask, SwarmTurnResult } from '../types'\n\nconst logger = createLogger('otto:orchestrator:strategies:hierarchical')\n\nconst taskSchema = z.object({\n description: z.string(),\n assignedTo: z.string().optional(),\n})\n\n/**\n * 对未知值做逐元素 zod 校验过滤,而非整数组校验(整数组校验会因单个坏元素全盘拒绝)。\n */\nfunction parseAndFilterTasks(raw: unknown): HierarchicalTask[] {\n if (!Array.isArray(raw)) return []\n const tasks: HierarchicalTask[] = []\n for (const item of raw) {\n const result = taskSchema.safeParse(item)\n if (result.success) {\n tasks.push(result.data)\n }\n }\n return tasks\n}\n\nexport function parsePlanOutput(text: string): HierarchicalTask[] {\n // 优先:整体 JSON.parse\n try {\n const parsed = JSON.parse(text.trim())\n const direct = parseAndFilterTasks(parsed)\n if (direct.length > 0) {\n return direct\n }\n } catch {\n // 继续降级\n }\n\n // 兜底:正则匹配 + zod 逐元素校验\n const jsonMatch = text.match(/\\[[\\s\\S]*\\]/)\n if (jsonMatch) {\n try {\n const parsed = JSON.parse(jsonMatch[0])\n const fallback = parseAndFilterTasks(parsed)\n if (fallback.length > 0) {\n return fallback\n }\n } catch {\n // 继续降级\n }\n }\n\n // 最终兜底:warn + 空数组(调用方 tasks.length === 0 分支走既有单任务兜底)\n logger.warn(\n { textPreview: text.slice(0, 200) },\n 'hierarchical supervisor plan parse failed, degrading to single task',\n )\n return []\n}\n\nexport const HIERARCHICAL_STRATEGY: OrchestrationStrategy = {\n name: 'hierarchical',\n\n async execute(input: string, ctx: StrategyContext): Promise<StrategyResult> {\n const supervisorId: string =\n ctx.config.supervisorId ?? [...ctx.config.agents.values()][0]?.id ?? ''\n if (!supervisorId) {\n return { steps: [], output: '' }\n }\n\n const supervisorDef = ctx.config.agents.get(supervisorId)\n if (!supervisorDef || supervisorDef.kind !== 'agent') {\n return { steps: [], output: '' }\n }\n\n ctx.emit({ type: 'agent.start', agentId: supervisorId })\n ctx.emit({ type: 'hierarchy.delegate', supervisor: supervisorId, worker: '', task: 'planning' })\n const planStart = Date.now()\n\n const planOutput = await ctx.createStepRunner(\n supervisorDef,\n `You are the supervisor. Break down this task into subtasks:\\n\\n${input}\\n\\nFor each subtask, specify:\\n1. A clear description\\n2. Which agent should execute it (choose from: ${[...ctx.config.agents.values()].map((a) => a.id).join(', ')})\\n\\nRespond with a JSON array of {description, assignedTo}. Output only the JSON array, no other text.`,\n { signal: ctx.signal },\n )\n\n const planDur = Date.now() - planStart\n ctx.emit({ type: 'agent.end', agentId: supervisorId, durationMs: planDur })\n const steps: StrategyResult['steps'] = [\n { agentId: supervisorId, output: planOutput, durationMs: planDur },\n ]\n\n let tasks = parsePlanOutput(planOutput.text)\n\n if (tasks.length === 0) {\n tasks = [{ description: input, assignedTo: undefined }]\n }\n\n const taskResults: Array<{\n task: HierarchicalTask\n agentId: string\n output: SwarmTurnResult\n durationMs: number\n }> = []\n\n const fallbackWorker =\n [...ctx.config.agents.values()].find((a) => a.id !== supervisorId)?.id ?? supervisorId\n const assignedTasks = tasks.map((t) => ({\n ...t,\n agentId: t.assignedTo ?? fallbackWorker,\n }))\n\n const cap = ctx.config.maxConcurrency ?? assignedTasks.length\n\n await runConcurrent(assignedTasks, {\n cap,\n executor: async (task) => {\n try {\n const workerDef = ctx.config.agents.get(task.agentId)\n if (!workerDef) return\n\n ctx.emit({ type: 'agent.start', agentId: task.agentId })\n ctx.emit({\n type: 'hierarchy.delegate',\n supervisor: supervisorId,\n worker: task.agentId,\n task: task.description,\n })\n const start = Date.now()\n\n const output = await ctx.createStepRunner(workerDef, task.description, {\n signal: ctx.signal,\n })\n\n const dur = Date.now() - start\n ctx.emit({ type: 'agent.end', agentId: task.agentId, durationMs: dur })\n taskResults.push({ task, agentId: task.agentId, output, durationMs: dur })\n } catch (err) {\n ctx.emit({\n type: 'error',\n agentId: task.agentId,\n error: err instanceof Error ? err : new Error(String(err)),\n })\n }\n },\n signal: ctx.signal,\n })\n\n for (const tr of taskResults) {\n steps.push({ agentId: tr.agentId, output: tr.output, durationMs: tr.durationMs })\n }\n\n const summaryParts = taskResults.map(\n (r) => `## ${r.task.description} (by ${r.agentId})\\n${r.output.text}`,\n )\n const synthesis = [\n 'The subtasks have been completed. Here are the results:',\n '',\n ...summaryParts,\n '',\n 'Synthesize these results into a final coherent response for the original task:',\n input,\n ].join('\\n')\n\n if (ctx.signal.aborted) {\n return { steps, output: summaryParts.join('\\n\\n') }\n }\n\n ctx.emit({ type: 'agent.start', agentId: supervisorId })\n const synStart = Date.now()\n\n const synOutput = await ctx.createStepRunner(supervisorDef, synthesis, { signal: ctx.signal })\n\n const synDur = Date.now() - synStart\n ctx.emit({ type: 'agent.end', agentId: supervisorId, durationMs: synDur })\n steps.push({ agentId: supervisorId, output: synOutput, durationMs: synDur })\n\n return { steps, output: synOutput.text }\n },\n}\n","import { AgentNotFoundError, SwarmConfigError } from '../errors'\n\nimport type { OrchestrationStrategy, StrategyContext, StrategyResult } from '../strategy'\n\nexport const ROUTER_STRATEGY: OrchestrationStrategy = {\n name: 'router',\n\n async execute(input: string, ctx: StrategyContext): Promise<StrategyResult> {\n if (!ctx.router) {\n throw new SwarmConfigError('Router not configured')\n }\n\n const agents = [...ctx.config.agents.values()]\n const decision = await ctx.router.route(input, agents)\n\n const agentDef = ctx.config.agents.get(decision.agentId)\n if (!agentDef) {\n throw new AgentNotFoundError(decision.agentId)\n }\n\n ctx.emit({ type: 'routing.decision', decision })\n\n ctx.emit({ type: 'agent.start', agentId: decision.agentId })\n const start = Date.now()\n\n // team 与 member 的分派统一经 createStepRunner→executeMemberTurn(team→runNested)单源。\n const output = await ctx.createStepRunner(agentDef, input, { signal: ctx.signal })\n\n const dur = Date.now() - start\n ctx.emit({ type: 'agent.end', agentId: decision.agentId, durationMs: dur })\n\n return {\n steps: [{ agentId: decision.agentId, output, durationMs: dur }],\n output: output.text,\n }\n },\n}\n","import { StrategyRegistry } from '../strategy'\nimport { HANDOFF_STRATEGY } from './handoff'\nimport { SEQUENTIAL_STRATEGY } from './sequential'\nimport { PARALLEL_STRATEGY } from './parallel'\nimport { HIERARCHICAL_STRATEGY } from './hierarchical'\nimport { ROUTER_STRATEGY } from './router'\n\nexport function createDefaultStrategyRegistry(): StrategyRegistry {\n const registry = new StrategyRegistry()\n registry.register(HANDOFF_STRATEGY)\n registry.register(SEQUENTIAL_STRATEGY)\n registry.register(PARALLEL_STRATEGY)\n registry.register(HIERARCHICAL_STRATEGY)\n registry.register(ROUTER_STRATEGY)\n return registry\n}\n\nexport { HANDOFF_STRATEGY } from './handoff'\nexport { SEQUENTIAL_STRATEGY } from './sequential'\nexport { PARALLEL_STRATEGY } from './parallel'\nexport { HIERARCHICAL_STRATEGY } from './hierarchical'\nexport { ROUTER_STRATEGY } from './router'\n","import { SwarmRouter } from './router'\nimport { createDefaultStrategyRegistry } from './strategies'\nimport { SwarmConfigError } from './errors'\n\nimport type {\n SwarmAgentDef,\n SwarmAgentId,\n SwarmAgentMember,\n SwarmConfig,\n SwarmEvent,\n SwarmEventHandler,\n SwarmTurnResult,\n} from './types'\nimport type { AgentTurnInput, CoreToolDescriptor } from '../types'\nimport type { TaskHookInfo } from '@x-otto/hook-contracts'\nimport type {\n OrchestrationStrategy,\n StrategyContext,\n StrategyResult,\n Router,\n StepResult,\n} from './strategy'\nimport type { StrategyRegistry } from './strategy'\n\n/**\n * Swarm — 多 Agent 协作框架(策略引擎化)。\n *\n * OrchestrationStrategy 取代封闭枚举+switch——新模式 = 实现接口 + registry.register(),\n * 不碰 Swarm.run()、不碰核心结果类型。\n */\nexport class Swarm {\n private readonly config: SwarmConfig\n private readonly agents: Map<string, SwarmAgentDef>\n private readonly router: SwarmRouter | null\n private readonly registry: StrategyRegistry\n\n constructor(config: SwarmConfig) {\n this.validateConfig(config)\n\n this.config = config\n this.agents = new Map()\n\n for (const agent of config.agents) {\n this.agents.set(agent.id, agent)\n }\n\n this.router = config.router ? new SwarmRouter(config.router) : null\n\n this.registry = createDefaultStrategyRegistry()\n }\n\n getAgents(): SwarmAgentDef[] {\n return [...this.agents.values()]\n }\n\n getAgent(id: SwarmAgentId): SwarmAgentDef | undefined {\n return this.agents.get(id)\n }\n\n /** 注册/替换策略(§4-12:host 可追加新模式,不碰核心)。 */\n registerStrategy(strategy: OrchestrationStrategy): void {\n this.registry.register(strategy)\n }\n\n /** 获取已注册策略名列表。 */\n getStrategyNames(): string[] {\n return this.registry.names()\n }\n\n private emitEvent(event: SwarmEvent): void {\n // 私有回调(向后兼容,RFC-107 D1 / M-N6 保留)\n this.config.onSwarmEvent?.(event)\n // hookRegistry 桥接(RFC-107 D1 / M-N6):swarm 事件映射至既有 task.* HookTiming。\n // 构造合成 TaskHookInfo 承载 SwarmEventPayload;不新建 swarm.* timing 家族。\n if (this.config.hookRegistry) {\n const taskInfo: TaskHookInfo = {\n id: `swarm:${this.config.runId ?? this.config.name}`,\n status: 'running',\n attempts: 0,\n maxAttempts: 1,\n createdAt: Date.now(),\n swarmEvent: event as TaskHookInfo['swarmEvent'],\n }\n // task.started 是 task.* 家族中最合适的挂接点:swarm 成员 turn 本已经过\n // TaskExecutor 产生 task.created→task.started→task.completed,swarm 级\n // 编排事件在此之上叠 swarmEvent 上下文,下游 hook 据此区分普通 task 与\n // swarm 编排事件并消费路由/编组元数据。\n void this.config.hookRegistry.emit('task.started', {\n task: taskInfo,\n agent: `swarm:${this.config.name}`,\n })\n }\n }\n\n /** 构建 StrategyContext——每次 run() 全新构造(context/signal 属单次运行)。 */\n private buildStrategyContext(signal: AbortSignal): StrategyContext {\n const emit: SwarmEventHandler = (event) => this.emitEvent(event)\n\n const createStepRunner: StrategyContext['createStepRunner'] = (agentDef, input, opts) =>\n this.executeMemberTurn(agentDef, input, opts?.signal ?? signal, opts?.coreTools)\n\n const ctx: StrategyContext = {\n createStepRunner,\n emit,\n router: this.router as Router,\n signal,\n config: {\n name: this.config.name,\n agents: this.agents,\n entryAgentId: this.config.entryAgentId,\n pipeline: this.config.pipeline,\n supervisorId: this.config.supervisorId,\n maxHandoffDepth: this.config.maxHandoffDepth,\n maxConcurrency: this.config.maxConcurrency,\n },\n }\n\n return ctx\n }\n\n /**\n * 运行 Swarm — 从注册表取策略并执行。\n */\n async run(input: string, options?: { signal?: AbortSignal }): Promise<SwarmRunResult> {\n const signal = options?.signal ?? new AbortController().signal\n const startTime = Date.now()\n const emit: SwarmEventHandler = (event) => this.emitEvent(event)\n\n emit({\n type: 'swarm.start',\n pattern: this.config.pattern,\n agentCount: this.agents.size,\n })\n\n const strategy = this.registry.get(this.config.pattern)\n if (!strategy) {\n throw new SwarmConfigError(\n `Unknown pattern: \"${this.config.pattern}\". Registered strategies: ${this.registry.names().join(', ')}`,\n )\n }\n\n try {\n const ctx = this.buildStrategyContext(signal)\n const result: StrategyResult = await strategy.execute(input, ctx)\n\n emit({ type: 'swarm.end', totalDurationMs: Date.now() - startTime })\n\n return {\n pattern: this.config.pattern,\n steps: result.steps,\n output: result.output,\n durationMs: Date.now() - startTime,\n }\n } catch (error) {\n emit({ type: 'swarm.end', totalDurationMs: Date.now() - startTime })\n throw error\n }\n }\n\n /**\n * 执行单个 swarm 成员的 agent turn(B+ 门禁①:经 TaskExecutor 执行)。\n * team 成员走 runNested(递归子 swarm)。\n */\n private async executeMemberTurn(\n agentDef: SwarmAgentDef,\n input: string,\n signal: AbortSignal,\n coreTools?: CoreToolDescriptor[],\n ): Promise<SwarmTurnResult> {\n if (agentDef.kind === 'team') {\n // RFC-332 M1:nested team 语义显式化——core 工具(handoff)对子团队整体无意义\n // (子 swarm 有自己的策略状态机),descriptor 不透传,记录诊断而非静默丢弃。\n if (coreTools?.length) {\n this.config.onSwarmEvent?.({\n type: 'error',\n agentId: agentDef.id,\n error: new Error(\n `Nested team \"${agentDef.id}\" does not support core tools (${coreTools.map((d) => d.name).join(', ')}); descriptors dropped`,\n ),\n })\n }\n return agentDef.runNested(input, signal)\n }\n\n const member = agentDef as SwarmAgentMember\n // M-B2: 类型安全调用——config.runAgentTurn 已是 AgentTurnInput → AgentTurnResult,\n // 经 Orchestrator.runAgentTurn → TaskExecutor 获得重试/熔断/并发闸/深度护栏。\n // RFC-332 M3:member.tools 已是纯数据 AgentToolDef[],无需再做 execute 剥离投影\n // (剥离发生在宿主解析层构造 SwarmAgentDef 时,orchestrator 全程不见 AgentTool)。\n const result = await this.config.runAgentTurn({\n agentId: member.id,\n prompt: input,\n systemPrompt: member.systemPrompt,\n tools: member.tools,\n coreTools,\n model: member.model?.id,\n maxToolTurns: member.maxToolTurns,\n thinkingLevel: member.thinkingLevel as AgentTurnInput['thinkingLevel'],\n maxTokens: member.maxTokens,\n temperature: member.temperature,\n sessionId: this.config.runId,\n depth: this.config.depth,\n signal,\n })\n\n return {\n agentId: result.agentId,\n messages: (result.messages ?? []) as SwarmTurnResult['messages'],\n text: result.text,\n handoff: result.handoff,\n tokenUsage: result.tokenUsage ?? { input: 0, output: 0, cacheRead: 0 },\n durationMs: result.durationMs,\n }\n }\n\n private validateConfig(config: SwarmConfig): void {\n if (!config.name) {\n throw new SwarmConfigError('Swarm name is required')\n }\n\n if (!config.agents || config.agents.length === 0) {\n throw new SwarmConfigError('At least one agent is required')\n }\n\n if (!config.runAgentTurn) {\n throw new SwarmConfigError('runAgentTurn factory is required')\n }\n\n const ids = new Set<string>()\n for (const agent of config.agents) {\n if (ids.has(agent.id)) {\n throw new SwarmConfigError(`Duplicate agent ID: \"${agent.id}\"`)\n }\n ids.add(agent.id)\n }\n\n for (const agent of config.agents) {\n if (agent.kind === 'agent' && agent.handoffTargets) {\n for (const targetId of agent.handoffTargets) {\n if (!ids.has(targetId)) {\n throw new SwarmConfigError(\n `Agent \"${agent.id}\" references unknown handoff target \"${targetId}\"`,\n )\n }\n }\n }\n }\n }\n}\n\nexport interface SwarmRunResult {\n /** 模式名(保留判别字段,service/CLI 据此消费)。 */\n pattern: string\n /** 所有 step 的执行记录。 */\n steps: StepResult[]\n /** 最终输出文本。 */\n output: string\n durationMs: number\n}\n\nexport function createSwarm(config: SwarmConfig): Swarm {\n return new Swarm(config)\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@x-otto/orchestrator",
3
+ "version": "0.0.1-alpha.0",
4
+ "files": [
5
+ "dist"
6
+ ],
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js"
14
+ }
15
+ },
16
+ "publishConfig": {
17
+ "access": "public",
18
+ "registry": "https://registry.npmjs.org",
19
+ "tag": "alpha"
20
+ },
21
+ "dependencies": {
22
+ "@x-otto/ai": "0.0.1-alpha.0",
23
+ "@x-otto/hook-contracts": "0.0.1-alpha.0",
24
+ "@x-otto/hooks": "0.0.1-alpha.0",
25
+ "@x-otto/orchestration-contracts": "0.0.1-alpha.0",
26
+ "@x-otto/interchange": "0.1.0-alpha.1",
27
+ "@x-otto/shared": "0.1.0-alpha.1",
28
+ "zod": "^3.24.4"
29
+ },
30
+ "scripts": {
31
+ "build": "tsdown",
32
+ "typecheck:project": "tsc -p tsconfig.json --noEmit",
33
+ "typecheck:file": "tsc src/index.ts --noEmit --target ES2024 --module ESNext --moduleResolution bundler --esModuleInterop --skipLibCheck",
34
+ "typecheck": "tsc --noEmit",
35
+ "clean": "rm -rf dist"
36
+ }
37
+ }