weacpx 0.4.5 → 0.4.6
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 +5 -12
- package/dist/bridge/bridge-main.js +6 -2
- package/dist/cli.js +86 -514
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -169,7 +169,7 @@ weacpx restart
|
|
|
169
169
|
| `weacpx status` | 查看后台状态、PID、配置路径、日志路径 |
|
|
170
170
|
| `weacpx stop` | 停止后台实例 |
|
|
171
171
|
| `weacpx restart` | 重启后台实例,让频道配置变更生效 |
|
|
172
|
-
| `weacpx update [--all
|
|
172
|
+
| `weacpx update [--all\|<name>]` | 检查并更新 weacpx 与已安装插件;安装了插件时会交互式选择更新项 |
|
|
173
173
|
| `weacpx channel list` | 查看已配置的消息频道 |
|
|
174
174
|
| `weacpx plugin known` | 查看官方插件清单(飞书/元宝包名) |
|
|
175
175
|
| `weacpx plugin add @ganglion/weacpx-channel-feishu && weacpx channel add feishu` | 安装并添加飞书频道,会提示输入飞书应用凭据 |
|
|
@@ -351,22 +351,15 @@ README 里只保留用户视角的最常用命令。
|
|
|
351
351
|
| 命令 | 说明 |
|
|
352
352
|
|------|------|
|
|
353
353
|
| `/dg <agent> <task>` | 快速委派一个子任务 |
|
|
354
|
-
| `/group new <title>` | 创建任务组 |
|
|
355
|
-
| `/group add <groupId> <agent> <task>` | 往任务组里加子任务 |
|
|
356
|
-
| `/groups` | 查看任务组列表 |
|
|
357
|
-
| `/group <id>` | 查看单个任务组 |
|
|
358
|
-
| `/group cancel <groupId>` | 取消组内未结束任务 |
|
|
359
354
|
| `/tasks` | 查看当前主线下的任务 |
|
|
360
355
|
| `/task <id>` | 查看单个任务详情 |
|
|
361
356
|
| `/task approve <id>` | 批准 `needs_confirmation` 任务 |
|
|
362
|
-
| `/task cancel <id>` |
|
|
357
|
+
| `/task cancel <id>` | 取消任务;取消一个尚未批准的任务等同于拒绝 |
|
|
363
358
|
|
|
364
359
|
最常见例子:
|
|
365
360
|
|
|
366
361
|
```text
|
|
367
362
|
/dg claude 审查当前方案的 3 个高风险点
|
|
368
|
-
/group new review
|
|
369
|
-
/group add review claude 审查接口设计
|
|
370
363
|
/tasks
|
|
371
364
|
/task approve task_123
|
|
372
365
|
```
|
|
@@ -376,9 +369,9 @@ README 里只保留用户视角的最常用命令。
|
|
|
376
369
|
- 当前会话就是主控会话
|
|
377
370
|
- 被委派出去的是独立子任务会话
|
|
378
371
|
- agent 发起的委派请求默认需要人工确认
|
|
379
|
-
-
|
|
372
|
+
- 如果你在用外部 MCP host(Codex / Claude Code),用 `delegate_batch` 一次派发多个并行子任务:传一个 `tasks` 数组,底层自动建组,全部结果一次性回注,无需手动维护 groupId
|
|
380
373
|
|
|
381
|
-
如果你想先理解什么时候该用 delegate
|
|
374
|
+
如果你想先理解什么时候该用 delegate、什么时候应该并行派出多个子任务,请看:
|
|
382
375
|
|
|
383
376
|
- [docs/weacpx-group-usage-guide.md](./docs/weacpx-group-usage-guide.md)
|
|
384
377
|
|
|
@@ -387,7 +380,7 @@ README 里只保留用户视角的最常用命令。
|
|
|
387
380
|
|
|
388
381
|
如果你想让 Codex、Claude Code 等外部 MCP host 直接使用 weacpx 的多 Agent 编排能力,可以把 `weacpx mcp-stdio` 配成一个 stdio MCP server。
|
|
389
382
|
|
|
390
|
-
`delegate_request` 支持 MCP Tasks:支持该能力的 host 可以让委派请求立即返回原生 task handle,之后通过 `tasks/get` / `tasks/result` / `tasks/cancel` 获取状态、结果或取消任务;worker 输出的 `[PROGRESS] ...` 会显示在 `tasks/get` / `tasks/list` 的 `statusMessage` 里;`input_required` 状态下的 `tasks/result` 会返回下一步操作提示并结束本次 result stream,而不是长时间阻塞;client 按提示调用 `task_get` / `task_approve` / `coordinator_answer_question` 等工具后,再继续 `tasks/get` / `tasks/result` 轮询。不支持 MCP Tasks 的 host 仍可使用兼容工具 `task_get` / `
|
|
383
|
+
`delegate_request` 支持 MCP Tasks:支持该能力的 host 可以让委派请求立即返回原生 task handle,之后通过 `tasks/get` / `tasks/result` / `tasks/cancel` 获取状态、结果或取消任务;worker 输出的 `[PROGRESS] ...` 会显示在 `tasks/get` / `tasks/list` 的 `statusMessage` 里;`input_required` 状态下的 `tasks/result` 会返回下一步操作提示并结束本次 result stream,而不是长时间阻塞;client 按提示调用 `task_get` / `task_approve` / `coordinator_answer_question` 等工具后,再继续 `tasks/get` / `tasks/result` 轮询。不支持 MCP Tasks 的 host 仍可使用兼容工具 `task_get` / `task_list` / `task_watch` / `task_cancel`。
|
|
391
384
|
|
|
392
385
|
先启动 daemon:
|
|
393
386
|
|
|
@@ -162,8 +162,12 @@ function extractJsonRpcErrorMessages(output) {
|
|
|
162
162
|
`).map((line) => line.trim()).filter((line) => line.length > 0).flatMap((line) => {
|
|
163
163
|
try {
|
|
164
164
|
const payload = JSON.parse(line);
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
const err = payload.error;
|
|
166
|
+
const dataMsg = typeof err?.data?.message === "string" && err.data.message.length > 0 ? err.data.message : undefined;
|
|
167
|
+
const baseMsg = typeof err?.message === "string" && err.message.length > 0 ? err.message : undefined;
|
|
168
|
+
const chosen = dataMsg && dataMsg !== baseMsg ? dataMsg : baseMsg;
|
|
169
|
+
if (chosen) {
|
|
170
|
+
return [chosen];
|
|
167
171
|
}
|
|
168
172
|
} catch {
|
|
169
173
|
return [];
|
package/dist/cli.js
CHANGED
|
@@ -9617,11 +9617,9 @@ function readVersion(moduleUrl = import.meta.url) {
|
|
|
9617
9617
|
var PACKAGE_NAME = "weacpx";
|
|
9618
9618
|
var init_version = () => {};
|
|
9619
9619
|
|
|
9620
|
-
// src/orchestration/task-
|
|
9621
|
-
var
|
|
9622
|
-
var
|
|
9623
|
-
DEFAULT_TASK_WAIT_TIMEOUT_MS = 5 * 60000;
|
|
9624
|
-
MAX_TASK_WAIT_TIMEOUT_MS = 20 * 60000;
|
|
9620
|
+
// src/orchestration/task-watch-timeouts.ts
|
|
9621
|
+
var DEFAULT_TASK_WATCH_TIMEOUT_MS = 60000, MAX_TASK_WATCH_TIMEOUT_MS, DEFAULT_TASK_WATCH_POLL_INTERVAL_MS = 1000, MAX_TASK_WATCH_POLL_INTERVAL_MS = 1e4, TASK_WATCH_RPC_TIMEOUT_PADDING_MS = 5000;
|
|
9622
|
+
var init_task_watch_timeouts = __esm(() => {
|
|
9625
9623
|
MAX_TASK_WATCH_TIMEOUT_MS = 20 * 60000;
|
|
9626
9624
|
});
|
|
9627
9625
|
|
|
@@ -14019,7 +14017,7 @@ ${buildFinalHeadsUp({
|
|
|
14019
14017
|
sendWeixinErrorNotice({
|
|
14020
14018
|
to,
|
|
14021
14019
|
contextToken,
|
|
14022
|
-
message: `⚠️
|
|
14020
|
+
message: `⚠️ 执行出错:${err instanceof Error ? err.message : JSON.stringify(err)}`,
|
|
14023
14021
|
baseUrl: deps.baseUrl,
|
|
14024
14022
|
token: deps.token,
|
|
14025
14023
|
errLog: deps.errLog
|
|
@@ -15553,8 +15551,12 @@ function extractJsonRpcErrorMessages(output) {
|
|
|
15553
15551
|
`).map((line) => line.trim()).filter((line) => line.length > 0).flatMap((line) => {
|
|
15554
15552
|
try {
|
|
15555
15553
|
const payload = JSON.parse(line);
|
|
15556
|
-
|
|
15557
|
-
|
|
15554
|
+
const err = payload.error;
|
|
15555
|
+
const dataMsg = typeof err?.data?.message === "string" && err.data.message.length > 0 ? err.data.message : undefined;
|
|
15556
|
+
const baseMsg = typeof err?.message === "string" && err.message.length > 0 ? err.message : undefined;
|
|
15557
|
+
const chosen = dataMsg && dataMsg !== baseMsg ? dataMsg : baseMsg;
|
|
15558
|
+
if (chosen) {
|
|
15559
|
+
return [chosen];
|
|
15558
15560
|
}
|
|
15559
15561
|
} catch {
|
|
15560
15562
|
return [];
|
|
@@ -17243,18 +17245,18 @@ function renderDelegateSuccess2(taskId, workerSession) {
|
|
|
17243
17245
|
return [`已创建委派任务「${taskId}」`, `worker 会话:${workerSession}`].join(`
|
|
17244
17246
|
`);
|
|
17245
17247
|
}
|
|
17246
|
-
function
|
|
17248
|
+
function renderGroupCreated(group) {
|
|
17247
17249
|
return [`已创建任务组「${group.groupId}」`, `- 标题:${group.title}`].join(`
|
|
17248
17250
|
`);
|
|
17249
17251
|
}
|
|
17250
|
-
function
|
|
17252
|
+
function renderGroupList(groups) {
|
|
17251
17253
|
if (groups.length === 0) {
|
|
17252
17254
|
return "当前协调会话下还没有任务组。";
|
|
17253
17255
|
}
|
|
17254
|
-
return ["当前协调会话的任务组:", ...groups.map((group) =>
|
|
17256
|
+
return ["当前协调会话的任务组:", ...groups.map((group) => renderGroupListItem(group))].join(`
|
|
17255
17257
|
`);
|
|
17256
17258
|
}
|
|
17257
|
-
function
|
|
17259
|
+
function renderGroupSummary(summary) {
|
|
17258
17260
|
const { group, tasks } = summary;
|
|
17259
17261
|
const lines = [
|
|
17260
17262
|
`任务组「${group.groupId}」`,
|
|
@@ -17286,7 +17288,7 @@ function renderGroupSummary2(summary) {
|
|
|
17286
17288
|
return lines.join(`
|
|
17287
17289
|
`);
|
|
17288
17290
|
}
|
|
17289
|
-
function
|
|
17291
|
+
function renderGroupCancelSuccess(input) {
|
|
17290
17292
|
return [
|
|
17291
17293
|
`任务组「${input.summary.group.groupId}」已发起取消`,
|
|
17292
17294
|
`- 已请求取消:${input.cancelledTaskIds.length}`,
|
|
@@ -17369,7 +17371,7 @@ function renderTaskApprovalSuccess2(task) {
|
|
|
17369
17371
|
return [`已批准任务「${task.taskId}」。`, `- 当前状态:${task.status}`].join(`
|
|
17370
17372
|
`);
|
|
17371
17373
|
}
|
|
17372
|
-
function
|
|
17374
|
+
function renderTaskRejectSuccess(task) {
|
|
17373
17375
|
return [`已拒绝任务「${task.taskId}」。`, `- 当前状态:${task.status}`].join(`
|
|
17374
17376
|
`);
|
|
17375
17377
|
}
|
|
@@ -17403,7 +17405,7 @@ function renderTaskListItem2(task) {
|
|
|
17403
17405
|
].filter(Boolean).map((item) => `;${item}`).join("");
|
|
17404
17406
|
return `- ${task.taskId} [${task.status}] ${task.targetAgent}${role} -> ${task.workerSession ?? "未分配"}${group}${source}${summary}${reliability}`;
|
|
17405
17407
|
}
|
|
17406
|
-
function
|
|
17408
|
+
function renderGroupListItem(group) {
|
|
17407
17409
|
const reliability = [
|
|
17408
17410
|
group.group.injectionPending ? "注入待重试" : ""
|
|
17409
17411
|
].filter(Boolean).map((item) => `;${item}`).join("");
|
|
@@ -17464,7 +17466,7 @@ async function handleGroupCreate(context, chatKey, title) {
|
|
|
17464
17466
|
coordinatorSession: session.transportSession,
|
|
17465
17467
|
title
|
|
17466
17468
|
});
|
|
17467
|
-
return { text:
|
|
17469
|
+
return { text: renderGroupCreated(group) };
|
|
17468
17470
|
}
|
|
17469
17471
|
async function handleGroupList(context, chatKey, filter) {
|
|
17470
17472
|
const session = await getCurrentSession(context, chatKey);
|
|
@@ -17479,7 +17481,7 @@ async function handleGroupList(context, chatKey, filter) {
|
|
|
17479
17481
|
coordinatorSession: session.transportSession,
|
|
17480
17482
|
...filter ?? {}
|
|
17481
17483
|
});
|
|
17482
|
-
return { text:
|
|
17484
|
+
return { text: renderGroupList(groups) };
|
|
17483
17485
|
}
|
|
17484
17486
|
async function handleGroupGet(context, chatKey, groupId) {
|
|
17485
17487
|
const session = await getCurrentSession(context, chatKey);
|
|
@@ -17497,7 +17499,7 @@ async function handleGroupGet(context, chatKey, groupId) {
|
|
|
17497
17499
|
if (!group) {
|
|
17498
17500
|
return { text: GROUP_NOT_FOUND_TEXT };
|
|
17499
17501
|
}
|
|
17500
|
-
return { text:
|
|
17502
|
+
return { text: renderGroupSummary(group) };
|
|
17501
17503
|
}
|
|
17502
17504
|
async function handleGroupCancel(context, chatKey, groupId) {
|
|
17503
17505
|
const session = await getCurrentSession(context, chatKey);
|
|
@@ -17519,7 +17521,7 @@ async function handleGroupCancel(context, chatKey, groupId) {
|
|
|
17519
17521
|
groupId,
|
|
17520
17522
|
coordinatorSession: session.transportSession
|
|
17521
17523
|
});
|
|
17522
|
-
return { text:
|
|
17524
|
+
return { text: renderGroupCancelSuccess(cancelled) };
|
|
17523
17525
|
}
|
|
17524
17526
|
async function handleGroupDelegate(context, chatKey, groupId, targetAgent, task, role, replyContextToken, accountId) {
|
|
17525
17527
|
const session = await getCurrentSession(context, chatKey);
|
|
@@ -17607,11 +17609,11 @@ async function handleTaskReject(context, chatKey, taskId) {
|
|
|
17607
17609
|
if (task.status !== "needs_confirmation") {
|
|
17608
17610
|
return { text: renderTaskConfirmationUnavailable(task) };
|
|
17609
17611
|
}
|
|
17610
|
-
const rejected = await orchestration.
|
|
17612
|
+
const rejected = await orchestration.cancelTask({
|
|
17611
17613
|
taskId,
|
|
17612
17614
|
coordinatorSession: session.transportSession
|
|
17613
17615
|
});
|
|
17614
|
-
return { text:
|
|
17616
|
+
return { text: renderTaskRejectSuccess(rejected) };
|
|
17615
17617
|
}
|
|
17616
17618
|
async function handleTaskCancel(context, chatKey, taskId) {
|
|
17617
17619
|
const session = await getCurrentSession(context, chatKey);
|
|
@@ -19309,8 +19311,6 @@ class OrchestrationServer {
|
|
|
19309
19311
|
return await this.dispatchTaskGet(params);
|
|
19310
19312
|
case "task.list":
|
|
19311
19313
|
return await this.handlers.listTasks(this.parseTaskListFilter(params));
|
|
19312
|
-
case "task.wait":
|
|
19313
|
-
return await this.handlers.waitTask(this.parseWaitTaskInput(params));
|
|
19314
19314
|
case "task.watch":
|
|
19315
19315
|
return await this.handlers.watchTask(this.parseWatchTaskInput(params));
|
|
19316
19316
|
case "task.approve":
|
|
@@ -19319,12 +19319,6 @@ class OrchestrationServer {
|
|
|
19319
19319
|
taskId: requireString(params, "taskId"),
|
|
19320
19320
|
coordinatorSession: requireString(params, "coordinatorSession")
|
|
19321
19321
|
});
|
|
19322
|
-
case "task.reject":
|
|
19323
|
-
requireOnlyKeys(params, ["taskId", "coordinatorSession"], "params");
|
|
19324
|
-
return await this.handlers.rejectTask({
|
|
19325
|
-
taskId: requireString(params, "taskId"),
|
|
19326
|
-
coordinatorSession: requireString(params, "coordinatorSession")
|
|
19327
|
-
});
|
|
19328
19322
|
case "task.cancel":
|
|
19329
19323
|
return await this.handlers.cancelTask(this.parseCancelTaskInput(params));
|
|
19330
19324
|
case "worker.reply":
|
|
@@ -19357,15 +19351,6 @@ class OrchestrationServer {
|
|
|
19357
19351
|
...expectedActivePackageId !== undefined ? { expectedActivePackageId } : {}
|
|
19358
19352
|
});
|
|
19359
19353
|
}
|
|
19360
|
-
case "coordinator.follow_up_human_package":
|
|
19361
|
-
requireOnlyKeys(params, ["coordinatorSession", "packageId", "priorMessageId", "taskQuestions", "promptText"], "params");
|
|
19362
|
-
return await this.handlers.coordinatorFollowUpHumanPackage({
|
|
19363
|
-
coordinatorSession: requireString(params, "coordinatorSession"),
|
|
19364
|
-
packageId: requireString(params, "packageId"),
|
|
19365
|
-
priorMessageId: requireString(params, "priorMessageId"),
|
|
19366
|
-
taskQuestions: requireTaskQuestions(params, "taskQuestions"),
|
|
19367
|
-
promptText: requireString(params, "promptText")
|
|
19368
|
-
});
|
|
19369
19354
|
case "coordinator.review_contested_result":
|
|
19370
19355
|
requireOnlyKeys(params, ["coordinatorSession", "taskId", "reviewId", "decision"], "params");
|
|
19371
19356
|
return await this.handlers.coordinatorReviewContestedResult({
|
|
@@ -19380,20 +19365,6 @@ class OrchestrationServer {
|
|
|
19380
19365
|
coordinatorSession: requireString(params, "coordinatorSession"),
|
|
19381
19366
|
title: requireString(params, "title")
|
|
19382
19367
|
});
|
|
19383
|
-
case "group.get":
|
|
19384
|
-
requireOnlyKeys(params, ["coordinatorSession", "groupId"], "params");
|
|
19385
|
-
return await this.handlers.getGroupSummary({
|
|
19386
|
-
coordinatorSession: requireString(params, "coordinatorSession"),
|
|
19387
|
-
groupId: requireString(params, "groupId")
|
|
19388
|
-
});
|
|
19389
|
-
case "group.list":
|
|
19390
|
-
return await this.handlers.listGroupSummaries(this.parseGroupListFilter(params));
|
|
19391
|
-
case "group.cancel":
|
|
19392
|
-
requireOnlyKeys(params, ["coordinatorSession", "groupId"], "params");
|
|
19393
|
-
return await this.handlers.cancelGroup({
|
|
19394
|
-
coordinatorSession: requireString(params, "coordinatorSession"),
|
|
19395
|
-
groupId: requireString(params, "groupId")
|
|
19396
|
-
});
|
|
19397
19368
|
default:
|
|
19398
19369
|
throw new OrchestrationInvalidRequestError(`unsupported orchestration method: ${method}`);
|
|
19399
19370
|
}
|
|
@@ -19488,17 +19459,6 @@ class OrchestrationServer {
|
|
|
19488
19459
|
...resultText !== undefined ? { resultText } : {}
|
|
19489
19460
|
};
|
|
19490
19461
|
}
|
|
19491
|
-
parseWaitTaskInput(params) {
|
|
19492
|
-
requireOnlyKeys(params, ["coordinatorSession", "taskId", "timeoutMs", "pollIntervalMs"], "params");
|
|
19493
|
-
const timeoutMs = requireOptionalIntegerInRange(params, "timeoutMs", 0, MAX_TASK_WAIT_TIMEOUT_MS);
|
|
19494
|
-
const pollIntervalMs = requireOptionalIntegerInRange(params, "pollIntervalMs", 1, MAX_TASK_WAIT_POLL_INTERVAL_MS);
|
|
19495
|
-
return {
|
|
19496
|
-
coordinatorSession: requireString(params, "coordinatorSession"),
|
|
19497
|
-
taskId: requireString(params, "taskId"),
|
|
19498
|
-
...timeoutMs !== undefined ? { timeoutMs } : {},
|
|
19499
|
-
...pollIntervalMs !== undefined ? { pollIntervalMs } : {}
|
|
19500
|
-
};
|
|
19501
|
-
}
|
|
19502
19462
|
parseWatchTaskInput(params) {
|
|
19503
19463
|
requireOnlyKeys(params, ["coordinatorSession", "taskId", "afterSeq", "mode", "includeProgress", "timeoutMs", "pollIntervalMs"], "params");
|
|
19504
19464
|
const afterSeq = requireOptionalIntegerInRange(params, "afterSeq", 0, Number.MAX_SAFE_INTEGER);
|
|
@@ -19526,20 +19486,6 @@ class OrchestrationServer {
|
|
|
19526
19486
|
whatIsNeeded: requireString(params, "whatIsNeeded")
|
|
19527
19487
|
};
|
|
19528
19488
|
}
|
|
19529
|
-
parseGroupListFilter(params) {
|
|
19530
|
-
requireOnlyKeys(params, ["coordinatorSession", "status", "stuck", "sort", "order"], "params");
|
|
19531
|
-
const status = requireOptionalEnum(params, "status", ["pending", "running", "terminal"]);
|
|
19532
|
-
const stuck = requireOptionalBoolean(params, "stuck");
|
|
19533
|
-
const sort = requireOptionalEnum(params, "sort", ["updatedAt", "createdAt"]);
|
|
19534
|
-
const order = requireOptionalEnum(params, "order", ["asc", "desc"]);
|
|
19535
|
-
return {
|
|
19536
|
-
coordinatorSession: requireString(params, "coordinatorSession"),
|
|
19537
|
-
...status !== undefined ? { status } : {},
|
|
19538
|
-
...stuck !== undefined ? { stuck } : {},
|
|
19539
|
-
...sort !== undefined ? { sort } : {},
|
|
19540
|
-
...order !== undefined ? { order } : {}
|
|
19541
|
-
};
|
|
19542
|
-
}
|
|
19543
19489
|
async cleanupEndpoint() {
|
|
19544
19490
|
if (this.endpoint.kind !== "unix") {
|
|
19545
19491
|
return;
|
|
@@ -19750,7 +19696,7 @@ function isServerNotRunningError(error2) {
|
|
|
19750
19696
|
var OrchestrationInvalidRequestError, ORCHESTRATION_RPC_METHODS;
|
|
19751
19697
|
var init_orchestration_server = __esm(() => {
|
|
19752
19698
|
init_orchestration_ipc();
|
|
19753
|
-
|
|
19699
|
+
init_task_watch_timeouts();
|
|
19754
19700
|
OrchestrationInvalidRequestError = class OrchestrationInvalidRequestError extends Error {
|
|
19755
19701
|
};
|
|
19756
19702
|
ORCHESTRATION_RPC_METHODS = new Set([
|
|
@@ -19758,22 +19704,16 @@ var init_orchestration_server = __esm(() => {
|
|
|
19758
19704
|
"delegate.request",
|
|
19759
19705
|
"task.get",
|
|
19760
19706
|
"task.list",
|
|
19761
|
-
"task.wait",
|
|
19762
19707
|
"task.watch",
|
|
19763
19708
|
"task.approve",
|
|
19764
|
-
"task.reject",
|
|
19765
19709
|
"task.cancel",
|
|
19766
19710
|
"worker.reply",
|
|
19767
19711
|
"worker.raise_question",
|
|
19768
19712
|
"coordinator.answer_question",
|
|
19769
19713
|
"coordinator.retract_answer",
|
|
19770
19714
|
"coordinator.request_human_input",
|
|
19771
|
-
"coordinator.follow_up_human_package",
|
|
19772
19715
|
"coordinator.review_contested_result",
|
|
19773
|
-
"group.new"
|
|
19774
|
-
"group.get",
|
|
19775
|
-
"group.list",
|
|
19776
|
-
"group.cancel"
|
|
19716
|
+
"group.new"
|
|
19777
19717
|
]);
|
|
19778
19718
|
});
|
|
19779
19719
|
|
|
@@ -19950,15 +19890,6 @@ class OrchestrationService {
|
|
|
19950
19890
|
this.logEvent("orchestration.group.created", "group created", this.groupContext(group));
|
|
19951
19891
|
return group;
|
|
19952
19892
|
}
|
|
19953
|
-
async getGroup(groupId) {
|
|
19954
|
-
const state = await this.deps.loadState();
|
|
19955
|
-
const group = this.ensureGroups(state)[groupId];
|
|
19956
|
-
return group ? { ...group } : null;
|
|
19957
|
-
}
|
|
19958
|
-
async listGroups(coordinatorSession) {
|
|
19959
|
-
const state = await this.deps.loadState();
|
|
19960
|
-
return Object.values(this.ensureGroups(state)).filter((group) => coordinatorSession === undefined || group.coordinatorSession === coordinatorSession).sort((left, right) => left.createdAt.localeCompare(right.createdAt)).map((group) => ({ ...group }));
|
|
19961
|
-
}
|
|
19962
19893
|
async getGroupSummary(input) {
|
|
19963
19894
|
const state = await this.deps.loadState();
|
|
19964
19895
|
const group = this.ensureGroups(state)[input.groupId];
|
|
@@ -20597,30 +20528,6 @@ class OrchestrationService {
|
|
|
20597
20528
|
const task = state.orchestration.tasks[taskId];
|
|
20598
20529
|
return task ? { ...task } : null;
|
|
20599
20530
|
}
|
|
20600
|
-
async waitTask(input) {
|
|
20601
|
-
const timeoutMs = clampWaitTimeout(input.timeoutMs);
|
|
20602
|
-
const pollIntervalMs = clampPollInterval(input.pollIntervalMs);
|
|
20603
|
-
const deadline = Date.now() + timeoutMs;
|
|
20604
|
-
while (true) {
|
|
20605
|
-
const state = await this.deps.loadState();
|
|
20606
|
-
const task = state.orchestration.tasks[input.taskId];
|
|
20607
|
-
if (!task || task.coordinatorSession !== input.coordinatorSession) {
|
|
20608
|
-
return { status: "not_found", task: null };
|
|
20609
|
-
}
|
|
20610
|
-
const snapshot = { ...task };
|
|
20611
|
-
if (isTerminalTaskStatus2(task.status) && task.reviewPending === undefined) {
|
|
20612
|
-
return { status: "terminal", task: snapshot };
|
|
20613
|
-
}
|
|
20614
|
-
if (isAttentionRequiredTask(task)) {
|
|
20615
|
-
return { status: "attention_required", task: snapshot };
|
|
20616
|
-
}
|
|
20617
|
-
const remainingMs = deadline - Date.now();
|
|
20618
|
-
if (remainingMs <= 0) {
|
|
20619
|
-
return { status: "timeout", task: snapshot };
|
|
20620
|
-
}
|
|
20621
|
-
await sleep2(Math.min(pollIntervalMs, remainingMs));
|
|
20622
|
-
}
|
|
20623
|
-
}
|
|
20624
20531
|
async watchTask(input) {
|
|
20625
20532
|
const timeoutMs = clampWatchTimeout(input.timeoutMs);
|
|
20626
20533
|
const pollIntervalMs = clampWatchPollInterval(input.pollIntervalMs);
|
|
@@ -21039,88 +20946,6 @@ class OrchestrationService {
|
|
|
21039
20946
|
queuedTaskIds: prepared.queuedTaskIds
|
|
21040
20947
|
};
|
|
21041
20948
|
}
|
|
21042
|
-
async coordinatorFollowUpHumanPackage(input) {
|
|
21043
|
-
const promptText = input.promptText.trim();
|
|
21044
|
-
if (promptText.length === 0) {
|
|
21045
|
-
throw new Error("promptText must be a non-empty string");
|
|
21046
|
-
}
|
|
21047
|
-
if (input.taskQuestions.length === 0) {
|
|
21048
|
-
throw new Error("taskQuestions must contain at least one question");
|
|
21049
|
-
}
|
|
21050
|
-
const prepared = await this.mutate(async () => {
|
|
21051
|
-
const state = await this.deps.loadState();
|
|
21052
|
-
if (this.isExternalCoordinatorSession(state, input.coordinatorSession)) {
|
|
21053
|
-
throw new Error("human input routing is not configured for external coordinator");
|
|
21054
|
-
}
|
|
21055
|
-
const coordinatorState = this.ensureCoordinatorQuestionState(state, input.coordinatorSession);
|
|
21056
|
-
if (coordinatorState.activePackageId !== input.packageId) {
|
|
21057
|
-
throw new Error(`package "${input.packageId}" is not the active package for coordinator "${input.coordinatorSession}"`);
|
|
21058
|
-
}
|
|
21059
|
-
const packageRecord = this.ensureHumanQuestionPackages(state)[input.packageId];
|
|
21060
|
-
if (!packageRecord || packageRecord.status !== "active") {
|
|
21061
|
-
throw new Error(`package "${input.packageId}" is not active`);
|
|
21062
|
-
}
|
|
21063
|
-
const latestMessage = packageRecord.messages.at(-1);
|
|
21064
|
-
if (!latestMessage || latestMessage.messageId !== input.priorMessageId) {
|
|
21065
|
-
throw new Error(`package "${input.packageId}" latest message is "${latestMessage?.messageId ?? ""}", not "${input.priorMessageId}"`);
|
|
21066
|
-
}
|
|
21067
|
-
if (!latestMessage.deliveredAt) {
|
|
21068
|
-
throw new Error(`package "${input.packageId}" latest message "${latestMessage.messageId}" is not delivered yet`);
|
|
21069
|
-
}
|
|
21070
|
-
const tasks = input.taskQuestions.map(({ taskId, questionId }) => {
|
|
21071
|
-
const task = state.orchestration.tasks[taskId];
|
|
21072
|
-
if (!task) {
|
|
21073
|
-
throw new Error(`task "${taskId}" does not exist`);
|
|
21074
|
-
}
|
|
21075
|
-
this.assertCoordinatorOwnership(task, input.coordinatorSession);
|
|
21076
|
-
if (!packageRecord.openTaskIds.includes(taskId)) {
|
|
21077
|
-
throw new Error(`task "${taskId}" does not belong to active package "${input.packageId}"`);
|
|
21078
|
-
}
|
|
21079
|
-
this.assertCoordinatorQuestionMatch(task, questionId);
|
|
21080
|
-
return task;
|
|
21081
|
-
});
|
|
21082
|
-
const now = this.deps.now().toISOString();
|
|
21083
|
-
const route = this.resolveFrozenPackageMessageRoute(latestMessage);
|
|
21084
|
-
const messageId = this.deps.createId();
|
|
21085
|
-
const message = {
|
|
21086
|
-
messageId,
|
|
21087
|
-
kind: "follow_up",
|
|
21088
|
-
promptText,
|
|
21089
|
-
createdAt: now,
|
|
21090
|
-
taskQuestions: input.taskQuestions.map((entry) => ({ ...entry })),
|
|
21091
|
-
...route ? this.serializeFrozenDeliveryRoute(route) : {}
|
|
21092
|
-
};
|
|
21093
|
-
packageRecord.messages.push(message);
|
|
21094
|
-
packageRecord.awaitingReplyMessageId = undefined;
|
|
21095
|
-
packageRecord.updatedAt = now;
|
|
21096
|
-
for (const task of tasks) {
|
|
21097
|
-
task.status = "waiting_for_human";
|
|
21098
|
-
task.openQuestion = {
|
|
21099
|
-
...task.openQuestion,
|
|
21100
|
-
packageId: input.packageId
|
|
21101
|
-
};
|
|
21102
|
-
task.updatedAt = now;
|
|
21103
|
-
this.appendTaskEvent(task, now, "attention_required", {
|
|
21104
|
-
status: "waiting_for_human",
|
|
21105
|
-
message: task.openQuestion.question
|
|
21106
|
-
});
|
|
21107
|
-
this.bumpGroupUpdated(state, task.groupId, now);
|
|
21108
|
-
}
|
|
21109
|
-
await this.deps.saveState(state);
|
|
21110
|
-
return {
|
|
21111
|
-
coordinatorSession: input.coordinatorSession,
|
|
21112
|
-
packageId: input.packageId,
|
|
21113
|
-
messageId,
|
|
21114
|
-
promptText,
|
|
21115
|
-
route
|
|
21116
|
-
};
|
|
21117
|
-
});
|
|
21118
|
-
await this.deliverHumanQuestionPackageMessage(prepared);
|
|
21119
|
-
return {
|
|
21120
|
-
packageId: prepared.packageId,
|
|
21121
|
-
messageId: prepared.messageId
|
|
21122
|
-
};
|
|
21123
|
-
}
|
|
21124
20949
|
async retryHumanQuestionPackageDelivery(input) {
|
|
21125
20950
|
const prepared = await this.mutate(async () => {
|
|
21126
20951
|
const state = await this.deps.loadState();
|
|
@@ -21760,7 +21585,11 @@ class OrchestrationService {
|
|
|
21760
21585
|
return { task: { ...task }, shouldPropagate, closedPackageId: undefined };
|
|
21761
21586
|
}
|
|
21762
21587
|
const closedPackageId = this.detachTaskFromQuestionFlows(state, task, now);
|
|
21588
|
+
const wasNeedsConfirmation = task.status === "needs_confirmation";
|
|
21763
21589
|
task.status = "cancelled";
|
|
21590
|
+
if (wasNeedsConfirmation && task.summary.trim().length === 0) {
|
|
21591
|
+
task.summary = "rejected";
|
|
21592
|
+
}
|
|
21764
21593
|
task.openQuestion = undefined;
|
|
21765
21594
|
task.cancelRequestedAt = task.cancelRequestedAt ?? now;
|
|
21766
21595
|
task.cancelCompletedAt = now;
|
|
@@ -21980,29 +21809,6 @@ class OrchestrationService {
|
|
|
21980
21809
|
this.logEvent("orchestration.task.approved", "task approved", this.taskContext(prepared.task));
|
|
21981
21810
|
return prepared.task;
|
|
21982
21811
|
}
|
|
21983
|
-
async rejectTask(input) {
|
|
21984
|
-
const task = await this.mutate(async () => {
|
|
21985
|
-
const state = await this.deps.loadState();
|
|
21986
|
-
const task2 = state.orchestration.tasks[input.taskId];
|
|
21987
|
-
if (!task2) {
|
|
21988
|
-
throw new Error(`task "${input.taskId}" does not exist`);
|
|
21989
|
-
}
|
|
21990
|
-
this.assertCoordinatorOwnership(task2, input.coordinatorSession);
|
|
21991
|
-
this.assertNeedsConfirmation(task2);
|
|
21992
|
-
task2.status = "cancelled";
|
|
21993
|
-
task2.summary = "rejected";
|
|
21994
|
-
task2.updatedAt = this.deps.now().toISOString();
|
|
21995
|
-
this.appendTaskEvent(task2, task2.updatedAt, "status_changed", {
|
|
21996
|
-
status: "cancelled",
|
|
21997
|
-
summary: "rejected",
|
|
21998
|
-
message: "Task rejected"
|
|
21999
|
-
});
|
|
22000
|
-
await this.deps.saveState(state);
|
|
22001
|
-
return { ...task2 };
|
|
22002
|
-
});
|
|
22003
|
-
this.logEvent("orchestration.task.rejected", "task rejected", this.taskContext(task));
|
|
22004
|
-
return task;
|
|
22005
|
-
}
|
|
22006
21812
|
async resolveWorkerSession(input) {
|
|
22007
21813
|
const role = this.normalizeRole(input.role);
|
|
22008
21814
|
const reusable = await this.deps.findReusableWorkerSession?.({
|
|
@@ -22946,24 +22752,6 @@ function isTerminalTaskStatus2(status) {
|
|
|
22946
22752
|
function isAttentionRequiredTask(task) {
|
|
22947
22753
|
return task.reviewPending !== undefined || task.status === "needs_confirmation" || task.status === "blocked" || task.status === "waiting_for_human";
|
|
22948
22754
|
}
|
|
22949
|
-
function clampWaitTimeout(timeoutMs) {
|
|
22950
|
-
if (timeoutMs === undefined) {
|
|
22951
|
-
return DEFAULT_TASK_WAIT_TIMEOUT_MS;
|
|
22952
|
-
}
|
|
22953
|
-
if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
|
|
22954
|
-
return 0;
|
|
22955
|
-
}
|
|
22956
|
-
return Math.min(Math.floor(timeoutMs), MAX_TASK_WAIT_TIMEOUT_MS);
|
|
22957
|
-
}
|
|
22958
|
-
function clampPollInterval(pollIntervalMs) {
|
|
22959
|
-
if (pollIntervalMs === undefined) {
|
|
22960
|
-
return DEFAULT_TASK_WAIT_POLL_INTERVAL_MS;
|
|
22961
|
-
}
|
|
22962
|
-
if (!Number.isFinite(pollIntervalMs) || pollIntervalMs <= 0) {
|
|
22963
|
-
return 1;
|
|
22964
|
-
}
|
|
22965
|
-
return Math.min(Math.floor(pollIntervalMs), MAX_TASK_WAIT_POLL_INTERVAL_MS);
|
|
22966
|
-
}
|
|
22967
22755
|
async function sleep2(ms) {
|
|
22968
22756
|
await new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
22969
22757
|
}
|
|
@@ -22973,7 +22761,7 @@ function isRequestDelegateInput(input) {
|
|
|
22973
22761
|
var MAX_TASK_EVENTS_PER_TASK = 200;
|
|
22974
22762
|
var init_orchestration_service = __esm(() => {
|
|
22975
22763
|
init_quota_errors();
|
|
22976
|
-
|
|
22764
|
+
init_task_watch_timeouts();
|
|
22977
22765
|
});
|
|
22978
22766
|
|
|
22979
22767
|
// src/orchestration/worker-prompts.ts
|
|
@@ -39387,9 +39175,8 @@ function requireHome(env) {
|
|
|
39387
39175
|
}
|
|
39388
39176
|
|
|
39389
39177
|
// src/mcp/weacpx-mcp-tools.ts
|
|
39390
|
-
|
|
39178
|
+
init_task_watch_timeouts();
|
|
39391
39179
|
init_quota_errors();
|
|
39392
|
-
var groupStatusSchema = exports_external.enum(["pending", "running", "terminal"]);
|
|
39393
39180
|
var taskStatusSchema = exports_external.enum([
|
|
39394
39181
|
"needs_confirmation",
|
|
39395
39182
|
"running",
|
|
@@ -39412,7 +39199,7 @@ function buildWeacpxMcpToolRegistry(input) {
|
|
|
39412
39199
|
const tools = [
|
|
39413
39200
|
{
|
|
39414
39201
|
name: "delegate_request",
|
|
39415
|
-
description: `Delegate a subtask to another agent under the current coordinator. Pass an absolute workingDirectory for the worker. Supports MCP Tasks when the client requests task execution: the tool can return a native task handle immediately, then clients can use tasks/get, tasks/result, tasks/list, and tasks/cancel
|
|
39202
|
+
description: `Delegate a subtask to another agent under the current coordinator. Pass an absolute workingDirectory for the worker. Supports MCP Tasks when the client requests task execution: the tool can return a native task handle immediately, then clients can use tasks/get, tasks/result, tasks/list, and tasks/cancel.${availableAgents && availableAgents.length > 0 ? ` Available agents: ${availableAgents.join(", ")}.` : ""}`,
|
|
39416
39203
|
execution: { taskSupport: "optional" },
|
|
39417
39204
|
inputSchema: exports_external.object({
|
|
39418
39205
|
targetAgent: exports_external.string().min(1),
|
|
@@ -39432,66 +39219,41 @@ function buildWeacpxMcpToolRegistry(input) {
|
|
|
39432
39219
|
})
|
|
39433
39220
|
},
|
|
39434
39221
|
{
|
|
39435
|
-
name: "
|
|
39436
|
-
description:
|
|
39437
|
-
inputSchema: exports_external.object({
|
|
39438
|
-
title: exports_external.string().min(1)
|
|
39439
|
-
}).strict(),
|
|
39440
|
-
handler: async (args) => await asToolResult(async () => {
|
|
39441
|
-
const group = await transport.createGroup({
|
|
39442
|
-
coordinatorSession,
|
|
39443
|
-
title: args.title
|
|
39444
|
-
});
|
|
39445
|
-
return createSuccessResult(renderGroupCreated(group), group);
|
|
39446
|
-
})
|
|
39447
|
-
},
|
|
39448
|
-
{
|
|
39449
|
-
name: "group_get",
|
|
39450
|
-
description: "Fetch a single task-group summary under the current coordinator. Use to check aggregate progress when waiting on a batch of delegations.",
|
|
39222
|
+
name: "delegate_batch",
|
|
39223
|
+
description: `Delegate several subtasks at once. Pass a "tasks" array; when it holds 2+ tasks they are bound to one auto-created group, so their results are reported back to you together when the whole batch finishes — one handoff instead of one interruption per task. Use this whenever you have multiple parallel delegations. Returns one result per task in input order; a task that fails to start carries an "error" field and does not abort the rest. Legacy-style only: it does not support MCP task execution — use delegate_request for a single native task handle.`,
|
|
39451
39224
|
inputSchema: exports_external.object({
|
|
39452
|
-
|
|
39225
|
+
title: exports_external.string().min(1).optional(),
|
|
39226
|
+
tasks: exports_external.array(exports_external.object({
|
|
39227
|
+
targetAgent: exports_external.string().min(1),
|
|
39228
|
+
task: exports_external.string().min(1),
|
|
39229
|
+
workingDirectory: exports_external.string().min(1).optional(),
|
|
39230
|
+
role: exports_external.string().min(1).optional()
|
|
39231
|
+
}).strict()).min(1)
|
|
39453
39232
|
}).strict(),
|
|
39454
39233
|
handler: async (args) => await asToolResult(async () => {
|
|
39455
|
-
const
|
|
39234
|
+
const { title, tasks } = args;
|
|
39235
|
+
const groupId = tasks.length >= 2 ? (await transport.createGroup({
|
|
39456
39236
|
coordinatorSession,
|
|
39457
|
-
|
|
39458
|
-
});
|
|
39459
|
-
|
|
39460
|
-
|
|
39461
|
-
|
|
39462
|
-
|
|
39463
|
-
|
|
39464
|
-
|
|
39465
|
-
|
|
39466
|
-
|
|
39467
|
-
|
|
39468
|
-
|
|
39469
|
-
|
|
39470
|
-
|
|
39471
|
-
|
|
39472
|
-
|
|
39473
|
-
|
|
39474
|
-
|
|
39475
|
-
|
|
39476
|
-
|
|
39477
|
-
...sort !== undefined ? { sort } : {},
|
|
39478
|
-
...order !== undefined ? { order } : {}
|
|
39479
|
-
});
|
|
39480
|
-
return createSuccessResult(renderGroupList(summaries), { groups: summaries });
|
|
39481
|
-
})
|
|
39482
|
-
},
|
|
39483
|
-
{
|
|
39484
|
-
name: "group_cancel",
|
|
39485
|
-
description: "Cancel all unfinished tasks in a task group under the current coordinator. Use to abort a batch started via group_new + delegate_request.",
|
|
39486
|
-
inputSchema: exports_external.object({
|
|
39487
|
-
groupId: exports_external.string().min(1)
|
|
39488
|
-
}).strict(),
|
|
39489
|
-
handler: async (args) => await asToolResult(async () => {
|
|
39490
|
-
const result = await transport.cancelGroup({
|
|
39491
|
-
coordinatorSession,
|
|
39492
|
-
groupId: args.groupId
|
|
39493
|
-
});
|
|
39494
|
-
return createSuccessResult(renderGroupCancelSuccess(result), result);
|
|
39237
|
+
title: title ?? `Batch delegation (${tasks.length} tasks)`
|
|
39238
|
+
})).groupId : undefined;
|
|
39239
|
+
const results = [];
|
|
39240
|
+
for (const [index, entry] of tasks.entries()) {
|
|
39241
|
+
try {
|
|
39242
|
+
const result = await transport.delegateRequest({
|
|
39243
|
+
coordinatorSession,
|
|
39244
|
+
...sourceHandle ? { sourceHandle } : {},
|
|
39245
|
+
targetAgent: entry.targetAgent,
|
|
39246
|
+
task: entry.task,
|
|
39247
|
+
...entry.workingDirectory ? { workingDirectory: entry.workingDirectory } : {},
|
|
39248
|
+
...entry.role ? { role: entry.role } : {},
|
|
39249
|
+
...groupId ? { groupId } : {}
|
|
39250
|
+
});
|
|
39251
|
+
results.push({ index, taskId: result.taskId, status: result.status });
|
|
39252
|
+
} catch (error2) {
|
|
39253
|
+
results.push({ index, error: formatToolError(error2) });
|
|
39254
|
+
}
|
|
39255
|
+
}
|
|
39256
|
+
return createSuccessResult(renderDelegateBatchSuccess(groupId, results), { ...groupId ? { groupId } : {}, tasks: results });
|
|
39495
39257
|
})
|
|
39496
39258
|
},
|
|
39497
39259
|
{
|
|
@@ -39531,7 +39293,7 @@ function buildWeacpxMcpToolRegistry(input) {
|
|
|
39531
39293
|
},
|
|
39532
39294
|
{
|
|
39533
39295
|
name: "task_approve",
|
|
39534
|
-
description: "Approve a
|
|
39296
|
+
description: "Approve a task that delegate_request returned as needs_confirmation, once the user has authorized it. The task then starts running.",
|
|
39535
39297
|
inputSchema: exports_external.object({
|
|
39536
39298
|
taskId: exports_external.string().min(1)
|
|
39537
39299
|
}).strict(),
|
|
@@ -39543,23 +39305,9 @@ function buildWeacpxMcpToolRegistry(input) {
|
|
|
39543
39305
|
return createSuccessResult(renderTaskApprovalSuccess(task), task);
|
|
39544
39306
|
})
|
|
39545
39307
|
},
|
|
39546
|
-
{
|
|
39547
|
-
name: "task_reject",
|
|
39548
|
-
description: "Reject a pending task under the current coordinator. Use when delegate_request returned status=needs_confirmation and the user declined; no task_wait is needed afterwards.",
|
|
39549
|
-
inputSchema: exports_external.object({
|
|
39550
|
-
taskId: exports_external.string().min(1)
|
|
39551
|
-
}).strict(),
|
|
39552
|
-
handler: async (args) => await asToolResult(async () => {
|
|
39553
|
-
const task = await transport.rejectTask({
|
|
39554
|
-
coordinatorSession,
|
|
39555
|
-
taskId: args.taskId
|
|
39556
|
-
});
|
|
39557
|
-
return createSuccessResult(renderTaskRejectionSuccess(task), task);
|
|
39558
|
-
})
|
|
39559
|
-
},
|
|
39560
39308
|
{
|
|
39561
39309
|
name: "task_cancel",
|
|
39562
|
-
description: "
|
|
39310
|
+
description: "Cancel a task under the current coordinator. Works in any non-terminal state: a running delegation is aborted, and a task still waiting for approval (needs_confirmation) is rejected. The task transitions to a terminal state shortly after.",
|
|
39563
39311
|
inputSchema: exports_external.object({
|
|
39564
39312
|
taskId: exports_external.string().min(1)
|
|
39565
39313
|
}).strict(),
|
|
@@ -39571,25 +39319,9 @@ function buildWeacpxMcpToolRegistry(input) {
|
|
|
39571
39319
|
return createSuccessResult(renderTaskCancelRequest(task), task);
|
|
39572
39320
|
})
|
|
39573
39321
|
},
|
|
39574
|
-
{
|
|
39575
|
-
name: "task_wait",
|
|
39576
|
-
description: `Wait for a task to finish or require attention. This is a blocking legacy compatibility tool; do not call it automatically after delegate_request when the user only asked to start/delegate work. Use task_get/task_list for non-blocking progress snapshots; call task_wait when the user explicitly asks to wait, or when your next step truly depends on completion. Returns status=terminal (done; call task_get for the result), status=attention_required (call task_get first to read the task's current status, then branch: needs_confirmation -> task_approve or task_reject; blocked or waiting_for_human -> coordinator_answer_question; reviewPending set -> coordinator_review_contested_result; after resolving, use task_get/task_list snapshots or task_wait only if intentionally blocking), or status=timeout (still running; use task_get for a snapshot, or task_wait only if intentionally blocking). Defaults: timeout ${DEFAULT_TASK_WAIT_TIMEOUT_MS} ms, poll interval ${DEFAULT_TASK_WAIT_POLL_INTERVAL_MS} ms. Maximums: timeout ${MAX_TASK_WAIT_TIMEOUT_MS} ms, poll interval ${MAX_TASK_WAIT_POLL_INTERVAL_MS} ms.`,
|
|
39577
|
-
inputSchema: exports_external.object({
|
|
39578
|
-
taskId: exports_external.string().min(1),
|
|
39579
|
-
timeoutMs: exports_external.number().int().min(0).max(MAX_TASK_WAIT_TIMEOUT_MS).optional(),
|
|
39580
|
-
pollIntervalMs: exports_external.number().int().min(1).max(MAX_TASK_WAIT_POLL_INTERVAL_MS).optional()
|
|
39581
|
-
}).strict(),
|
|
39582
|
-
handler: async (args) => await asToolResult(async () => {
|
|
39583
|
-
const result = await transport.waitTask({
|
|
39584
|
-
coordinatorSession,
|
|
39585
|
-
...args
|
|
39586
|
-
});
|
|
39587
|
-
return createSuccessResult(renderTaskWaitResult(result), result);
|
|
39588
|
-
})
|
|
39589
|
-
},
|
|
39590
39322
|
{
|
|
39591
39323
|
name: "task_watch",
|
|
39592
|
-
description: `Long-poll a task for the next event, attention-required state, or terminal state.
|
|
39324
|
+
description: `Long-poll a task for the next event, attention-required state, or terminal state. For MCP-task-capable clients, request task execution for this tool to create a background watcher: the call returns a native task handle immediately, and tasks/result returns when the watch condition is met. The native watcher is single-shot: it runs one watch cycle then terminates, so to keep watching start another task_watch with afterSeq set to the returned nextAfterSeq. Defaults: timeout ${DEFAULT_TASK_WATCH_TIMEOUT_MS} ms, poll interval ${DEFAULT_TASK_WATCH_POLL_INTERVAL_MS} ms. Maximums: timeout ${MAX_TASK_WATCH_TIMEOUT_MS} ms, poll interval ${MAX_TASK_WATCH_POLL_INTERVAL_MS} ms.`,
|
|
39593
39325
|
execution: { taskSupport: "optional" },
|
|
39594
39326
|
inputSchema: exports_external.object({
|
|
39595
39327
|
taskId: exports_external.string().min(1),
|
|
@@ -39609,7 +39341,7 @@ function buildWeacpxMcpToolRegistry(input) {
|
|
|
39609
39341
|
},
|
|
39610
39342
|
{
|
|
39611
39343
|
name: "worker_raise_question",
|
|
39612
|
-
description: "Raise a blocker question for the current bound worker session. Worker-side only: call this from inside a delegated task when you are blocked and need the coordinator's input.
|
|
39344
|
+
description: "Raise a blocker question for the current bound worker session. Worker-side only: call this from inside a delegated task when you are blocked and need the coordinator's input.",
|
|
39613
39345
|
inputSchema: exports_external.object({
|
|
39614
39346
|
taskId: exports_external.string().min(1),
|
|
39615
39347
|
question: exports_external.string().min(1),
|
|
@@ -39629,7 +39361,7 @@ function buildWeacpxMcpToolRegistry(input) {
|
|
|
39629
39361
|
},
|
|
39630
39362
|
{
|
|
39631
39363
|
name: "coordinator_answer_question",
|
|
39632
|
-
description: "Answer a blocked worker question under the current coordinator. Use when task_get shows a pending question
|
|
39364
|
+
description: "Answer a blocked worker question under the current coordinator. Use when task_get shows a pending question.",
|
|
39633
39365
|
inputSchema: exports_external.object({
|
|
39634
39366
|
taskId: exports_external.string().min(1),
|
|
39635
39367
|
questionId: exports_external.string().min(1),
|
|
@@ -39659,23 +39391,6 @@ function buildWeacpxMcpToolRegistry(input) {
|
|
|
39659
39391
|
return createSuccessResult(renderCoordinatorRequestHumanInputSuccess(result), result);
|
|
39660
39392
|
})
|
|
39661
39393
|
},
|
|
39662
|
-
{
|
|
39663
|
-
name: "coordinator_follow_up_human_package",
|
|
39664
|
-
description: "Append a follow-up message to the active human question package under the current coordinator. Use to clarify or add context to an in-flight package created via coordinator_request_human_input.",
|
|
39665
|
-
inputSchema: exports_external.object({
|
|
39666
|
-
packageId: exports_external.string().min(1),
|
|
39667
|
-
priorMessageId: exports_external.string().min(1),
|
|
39668
|
-
taskQuestions: exports_external.array(taskQuestionSchema).min(1),
|
|
39669
|
-
promptText: exports_external.string().min(1)
|
|
39670
|
-
}).strict(),
|
|
39671
|
-
handler: async (args) => await asToolResult(async () => {
|
|
39672
|
-
const result = await transport.coordinatorFollowUpHumanPackage({
|
|
39673
|
-
coordinatorSession,
|
|
39674
|
-
...args
|
|
39675
|
-
});
|
|
39676
|
-
return createSuccessResult(renderCoordinatorFollowUpHumanPackageSuccess(result), result);
|
|
39677
|
-
})
|
|
39678
|
-
},
|
|
39679
39394
|
{
|
|
39680
39395
|
name: "coordinator_review_contested_result",
|
|
39681
39396
|
description: "Review a contested result under the current coordinator. Use when a worker's result has been challenged and the coordinator must decide accept or discard.",
|
|
@@ -39697,8 +39412,7 @@ function buildWeacpxMcpToolRegistry(input) {
|
|
|
39697
39412
|
];
|
|
39698
39413
|
if (isExternalCoordinator) {
|
|
39699
39414
|
const externalCoordinatorIncompatibleTools = new Set([
|
|
39700
|
-
"coordinator_request_human_input"
|
|
39701
|
-
"coordinator_follow_up_human_package"
|
|
39415
|
+
"coordinator_request_human_input"
|
|
39702
39416
|
]);
|
|
39703
39417
|
return tools.filter((tool) => !externalCoordinatorIncompatibleTools.has(tool.name));
|
|
39704
39418
|
}
|
|
@@ -39723,37 +39437,6 @@ async function asToolResult(action) {
|
|
|
39723
39437
|
return createErrorResult(formatToolError(error2));
|
|
39724
39438
|
}
|
|
39725
39439
|
}
|
|
39726
|
-
function renderTaskWaitResult(result) {
|
|
39727
|
-
if (result.status === "not_found") {
|
|
39728
|
-
return "Task not found.";
|
|
39729
|
-
}
|
|
39730
|
-
if (!result.task) {
|
|
39731
|
-
return `Task wait ${result.status.replace("_", " ")}; current state is unavailable.`;
|
|
39732
|
-
}
|
|
39733
|
-
if (result.status === "timeout") {
|
|
39734
|
-
return [
|
|
39735
|
-
`Task ${result.task.taskId} wait timed out; current state is ${result.task.status}.`,
|
|
39736
|
-
`Next: call task_get for a snapshot, or call task_wait again only if you intentionally want to keep blocking.`
|
|
39737
|
-
].join(`
|
|
39738
|
-
`);
|
|
39739
|
-
}
|
|
39740
|
-
if (result.status === "attention_required") {
|
|
39741
|
-
return [
|
|
39742
|
-
`Task ${result.task.taskId} requires attention; current state is ${result.task.status}.`,
|
|
39743
|
-
`Next: call task_get to read the task's current status and any reviewPending / openQuestion fields, then branch by what you see:`,
|
|
39744
|
-
` - status=needs_confirmation -> task_approve or task_reject`,
|
|
39745
|
-
` - status=blocked or waiting_for_human -> coordinator_answer_question`,
|
|
39746
|
-
` - reviewPending set -> coordinator_review_contested_result`,
|
|
39747
|
-
`After resolving, use task_get/task_list for snapshots, or call task_wait again only if you intentionally want to keep blocking.`
|
|
39748
|
-
].join(`
|
|
39749
|
-
`);
|
|
39750
|
-
}
|
|
39751
|
-
return [
|
|
39752
|
-
`Task ${result.task.taskId} reached terminal state ${result.task.status}.`,
|
|
39753
|
-
`Next: call task_get to read the worker's final result before reporting back to the user.`
|
|
39754
|
-
].join(`
|
|
39755
|
-
`);
|
|
39756
|
-
}
|
|
39757
39440
|
function renderTaskWatchResult(result) {
|
|
39758
39441
|
if (result.status === "not_found" || !result.task) {
|
|
39759
39442
|
return "Task not found.";
|
|
@@ -39787,72 +39470,16 @@ function createErrorResult(message) {
|
|
|
39787
39470
|
};
|
|
39788
39471
|
}
|
|
39789
39472
|
function renderDelegateSuccess(result) {
|
|
39790
|
-
const next = result.status === "needs_confirmation" ? `Next: this delegation requires user approval
|
|
39473
|
+
const next = result.status === "needs_confirmation" ? `Next: this delegation requires user approval. Tell the user, then call task_approve or task_cancel based on their response.` : `Next: task "${result.taskId}" is running. Return this taskId to the user, call task_get/task_list for non-blocking progress snapshots, or task_watch to long-poll for the next event or terminal state.`;
|
|
39791
39474
|
return [`Delegation task "${result.taskId}" created.`, `- Status: ${result.status}`, next].join(`
|
|
39792
39475
|
`);
|
|
39793
39476
|
}
|
|
39794
|
-
function
|
|
39795
|
-
|
|
39796
|
-
|
|
39797
|
-
}
|
|
39798
|
-
|
|
39799
|
-
|
|
39800
|
-
const lines = [
|
|
39801
|
-
`Task group "${group.groupId}"`,
|
|
39802
|
-
`- Title: ${group.title}`,
|
|
39803
|
-
`- Coordinator session: ${group.coordinatorSession}`,
|
|
39804
|
-
`- Total tasks: ${summary.totalTasks}`,
|
|
39805
|
-
`- Pending approval: ${summary.pendingApprovalTasks}`,
|
|
39806
|
-
`- Running: ${summary.runningTasks}`,
|
|
39807
|
-
`- Completed: ${summary.completedTasks}`,
|
|
39808
|
-
`- Failed: ${summary.failedTasks}`,
|
|
39809
|
-
`- Cancelled: ${summary.cancelledTasks}`,
|
|
39810
|
-
`- Terminal: ${summary.terminal ? "yes" : "no"}`
|
|
39811
|
-
];
|
|
39812
|
-
if (group.injectionPending !== undefined) {
|
|
39813
|
-
lines.push(`- Injection pending: ${group.injectionPending ? "yes" : "no"}`);
|
|
39814
|
-
}
|
|
39815
|
-
if (group.injectionAppliedAt) {
|
|
39816
|
-
lines.push(`- Injection completed at: ${group.injectionAppliedAt}`);
|
|
39817
|
-
}
|
|
39818
|
-
if (group.lastInjectionError) {
|
|
39819
|
-
lines.push(`- Last injection error: ${group.lastInjectionError}`);
|
|
39820
|
-
}
|
|
39821
|
-
if (tasks.length > 0) {
|
|
39822
|
-
lines.push("- Members:");
|
|
39823
|
-
for (const task of tasks) {
|
|
39824
|
-
lines.push(` - ${task.taskId} [${task.status}] ${task.targetAgent}`);
|
|
39825
|
-
}
|
|
39826
|
-
}
|
|
39827
|
-
return lines.join(`
|
|
39828
|
-
`);
|
|
39829
|
-
}
|
|
39830
|
-
function renderGroupList(groups) {
|
|
39831
|
-
if (groups.length === 0) {
|
|
39832
|
-
return "There are no task groups under the current coordinator.";
|
|
39833
|
-
}
|
|
39834
|
-
return ["Task groups for the current coordinator:", ...groups.map((group) => renderGroupListItem(group))].join(`
|
|
39835
|
-
`);
|
|
39836
|
-
}
|
|
39837
|
-
function renderGroupListItem(group) {
|
|
39838
|
-
const reliability = group.group.injectionPending ? " | injection pending" : "";
|
|
39839
|
-
return [
|
|
39840
|
-
`- ${group.group.groupId}`,
|
|
39841
|
-
group.group.title,
|
|
39842
|
-
`total ${group.totalTasks}`,
|
|
39843
|
-
`pending ${group.pendingApprovalTasks}`,
|
|
39844
|
-
`running ${group.runningTasks}`,
|
|
39845
|
-
`completed ${group.completedTasks}`,
|
|
39846
|
-
`failed ${group.failedTasks}`,
|
|
39847
|
-
`cancelled ${group.cancelledTasks}${reliability}`
|
|
39848
|
-
].join(" | ");
|
|
39849
|
-
}
|
|
39850
|
-
function renderGroupCancelSuccess(input) {
|
|
39851
|
-
return [
|
|
39852
|
-
`Task group "${input.summary.group.groupId}" cancellation requested.`,
|
|
39853
|
-
`- Cancel requested: ${input.cancelledTaskIds.length}`,
|
|
39854
|
-
`- Skipped terminal tasks: ${input.skippedTaskIds.length}`
|
|
39855
|
-
].join(`
|
|
39477
|
+
function renderDelegateBatchSuccess(groupId, results) {
|
|
39478
|
+
const lines = results.map((entry) => entry.error ? ` - #${entry.index}: failed to start — ${entry.error}` : ` - #${entry.index}: task "${entry.taskId}" (${entry.status})`);
|
|
39479
|
+
const started = results.filter((entry) => entry.taskId).length;
|
|
39480
|
+
const header = groupId ? `Batch delegation created group "${groupId}" with ${started}/${results.length} tasks started.` : `Delegation: ${started}/${results.length} task started.`;
|
|
39481
|
+
const next = started > 0 ? "Next: track the started tasks with task_get/task_list, or task_watch to long-poll. The group reports all results back together once every task is terminal." : "Next: every task failed to start — fix the errors above and retry.";
|
|
39482
|
+
return [header, "- Tasks:", ...lines, next].join(`
|
|
39856
39483
|
`);
|
|
39857
39484
|
}
|
|
39858
39485
|
function renderTaskList(tasks) {
|
|
@@ -39923,7 +39550,9 @@ function renderTaskSummary(task) {
|
|
|
39923
39550
|
events.push({ at: task.updatedAt, event: "injection failed", detail: task.lastInjectionError });
|
|
39924
39551
|
events.sort((a, b) => a.at.localeCompare(b.at));
|
|
39925
39552
|
const timeline = events.length > 0 ? ["- Timeline:", ...events.map((e) => ` - [${e.at}] ${e.event}${e.detail ? `: ${e.detail}` : ""}`)] : [];
|
|
39926
|
-
|
|
39553
|
+
const isTerminal2 = task.status === "completed" || task.status === "failed" || task.status === "cancelled";
|
|
39554
|
+
const next = isTerminal2 ? ["Next: summarize this result for the user."] : [];
|
|
39555
|
+
return [...header, ...timeline, ...next].join(`
|
|
39927
39556
|
`);
|
|
39928
39557
|
}
|
|
39929
39558
|
function renderTaskCancelRequest(task) {
|
|
@@ -39938,14 +39567,10 @@ function renderTaskApprovalSuccess(task) {
|
|
|
39938
39567
|
return [
|
|
39939
39568
|
`Task "${task.taskId}" approved.`,
|
|
39940
39569
|
`- Current status: ${task.status}`,
|
|
39941
|
-
`Next: use task_get/task_list for non-blocking progress snapshots, or
|
|
39570
|
+
`Next: use task_get/task_list for non-blocking progress snapshots, or task_watch to long-poll until the worker finishes; then task_get to read the final result.`
|
|
39942
39571
|
].join(`
|
|
39943
39572
|
`);
|
|
39944
39573
|
}
|
|
39945
|
-
function renderTaskRejectionSuccess(task) {
|
|
39946
|
-
return [`Task "${task.taskId}" rejected.`, `- Current status: ${task.status}`].join(`
|
|
39947
|
-
`);
|
|
39948
|
-
}
|
|
39949
39574
|
function renderWorkerRaiseQuestionSuccess(task) {
|
|
39950
39575
|
return [`Blocker question submitted for task "${task.taskId}".`, `- questionId: ${task.questionId}`].join(`
|
|
39951
39576
|
`);
|
|
@@ -39959,10 +39584,6 @@ function renderCoordinatorRequestHumanInputSuccess(result) {
|
|
|
39959
39584
|
`) : [`Queued the question in the current human question queue.`, `- Queued tasks: ${result.queuedTaskIds.length}`].join(`
|
|
39960
39585
|
`);
|
|
39961
39586
|
}
|
|
39962
|
-
function renderCoordinatorFollowUpHumanPackageSuccess(result) {
|
|
39963
|
-
return [`Appended follow-up to human package "${result.packageId}".`, `- messageId: ${result.messageId}`].join(`
|
|
39964
|
-
`);
|
|
39965
|
-
}
|
|
39966
39587
|
function renderCoordinatorReviewContestedResultSuccess(task, decision) {
|
|
39967
39588
|
const actionText = decision === "accept" ? "Accepted" : "Discarded";
|
|
39968
39589
|
return [`${actionText} contested result for task "${task.taskId}".`, `- Current status: ${task.status}`].join(`
|
|
@@ -39980,7 +39601,7 @@ function formatToolError(error2) {
|
|
|
39980
39601
|
|
|
39981
39602
|
// src/orchestration/orchestration-client.ts
|
|
39982
39603
|
init_orchestration_ipc();
|
|
39983
|
-
|
|
39604
|
+
init_task_watch_timeouts();
|
|
39984
39605
|
import { randomUUID } from "node:crypto";
|
|
39985
39606
|
import { createConnection } from "node:net";
|
|
39986
39607
|
|
|
@@ -40005,18 +39626,12 @@ class OrchestrationClient {
|
|
|
40005
39626
|
async listTasks(filter) {
|
|
40006
39627
|
return await this.request("task.list", { filter });
|
|
40007
39628
|
}
|
|
40008
|
-
async waitTask(input) {
|
|
40009
|
-
return await this.request("task.wait", input, getWaitRequestTimeoutMs(input.timeoutMs, this.timeoutMs));
|
|
40010
|
-
}
|
|
40011
39629
|
async watchTask(input) {
|
|
40012
39630
|
return await this.request("task.watch", input, getWatchRequestTimeoutMs(input.timeoutMs, this.timeoutMs));
|
|
40013
39631
|
}
|
|
40014
39632
|
async approveTask(input) {
|
|
40015
39633
|
return await this.request("task.approve", input);
|
|
40016
39634
|
}
|
|
40017
|
-
async rejectTask(input) {
|
|
40018
|
-
return await this.request("task.reject", input);
|
|
40019
|
-
}
|
|
40020
39635
|
async cancelTask(input) {
|
|
40021
39636
|
return await this.request("task.cancel", input);
|
|
40022
39637
|
}
|
|
@@ -40038,24 +39653,12 @@ class OrchestrationClient {
|
|
|
40038
39653
|
async coordinatorRequestHumanInput(input) {
|
|
40039
39654
|
return await this.request("coordinator.request_human_input", input);
|
|
40040
39655
|
}
|
|
40041
|
-
async coordinatorFollowUpHumanPackage(input) {
|
|
40042
|
-
return await this.request("coordinator.follow_up_human_package", input);
|
|
40043
|
-
}
|
|
40044
39656
|
async coordinatorReviewContestedResult(input) {
|
|
40045
39657
|
return await this.request("coordinator.review_contested_result", input);
|
|
40046
39658
|
}
|
|
40047
39659
|
async createGroup(input) {
|
|
40048
39660
|
return await this.request("group.new", input);
|
|
40049
39661
|
}
|
|
40050
|
-
async getGroup(input) {
|
|
40051
|
-
return await this.request("group.get", input);
|
|
40052
|
-
}
|
|
40053
|
-
async listGroups(input) {
|
|
40054
|
-
return await this.request("group.list", input);
|
|
40055
|
-
}
|
|
40056
|
-
async cancelGroup(input) {
|
|
40057
|
-
return await this.request("group.cancel", input);
|
|
40058
|
-
}
|
|
40059
39662
|
async request(method, params, timeoutMs = this.timeoutMs) {
|
|
40060
39663
|
const id = this.createId();
|
|
40061
39664
|
return await new Promise((resolve, reject) => {
|
|
@@ -40122,11 +39725,6 @@ class OrchestrationClient {
|
|
|
40122
39725
|
});
|
|
40123
39726
|
}
|
|
40124
39727
|
}
|
|
40125
|
-
function getWaitRequestTimeoutMs(waitTimeoutMs, defaultTimeoutMs) {
|
|
40126
|
-
const requestedWaitTimeoutMs = waitTimeoutMs === undefined ? undefined : Number.isFinite(waitTimeoutMs) ? waitTimeoutMs : 0;
|
|
40127
|
-
const boundedWaitTimeoutMs = Math.min(Math.max(Math.floor(requestedWaitTimeoutMs ?? DEFAULT_TASK_WAIT_TIMEOUT_MS), 0), MAX_TASK_WAIT_TIMEOUT_MS);
|
|
40128
|
-
return Math.max(defaultTimeoutMs, boundedWaitTimeoutMs + TASK_WAIT_RPC_TIMEOUT_PADDING_MS);
|
|
40129
|
-
}
|
|
40130
39728
|
function getWatchRequestTimeoutMs(watchTimeoutMs, defaultTimeoutMs) {
|
|
40131
39729
|
const requestedWatchTimeoutMs = watchTimeoutMs === undefined ? undefined : Number.isFinite(watchTimeoutMs) ? watchTimeoutMs : 0;
|
|
40132
39730
|
const boundedWatchTimeoutMs = Math.min(Math.max(Math.floor(requestedWatchTimeoutMs ?? DEFAULT_TASK_WATCH_TIMEOUT_MS), 0), MAX_TASK_WATCH_TIMEOUT_MS);
|
|
@@ -40146,9 +39744,6 @@ function createOrchestrationTransport(endpoint, deps = {}) {
|
|
|
40146
39744
|
...input.groupId !== undefined ? { groupId: input.groupId } : {}
|
|
40147
39745
|
}),
|
|
40148
39746
|
createGroup: async (input) => await client.createGroup(input),
|
|
40149
|
-
getGroup: async (input) => await client.getGroup(input),
|
|
40150
|
-
listGroups: async (input) => await client.listGroups(input),
|
|
40151
|
-
cancelGroup: async (input) => await client.cancelGroup(input),
|
|
40152
39747
|
getTask: async (input) => await client.getTaskForCoordinator(input),
|
|
40153
39748
|
listTasks: async (input) => await client.listTasks({
|
|
40154
39749
|
coordinatorSession: input.coordinatorSession,
|
|
@@ -40158,9 +39753,7 @@ function createOrchestrationTransport(endpoint, deps = {}) {
|
|
|
40158
39753
|
...input.order !== undefined ? { order: input.order } : {}
|
|
40159
39754
|
}),
|
|
40160
39755
|
approveTask: async (input) => await client.approveTask(input),
|
|
40161
|
-
rejectTask: async (input) => await client.rejectTask(input),
|
|
40162
39756
|
cancelTask: async (input) => await client.cancelTaskForCoordinator(input),
|
|
40163
|
-
waitTask: async (input) => await client.waitTask(input),
|
|
40164
39757
|
watchTask: async (input) => await client.watchTask(input),
|
|
40165
39758
|
workerRaiseQuestion: async (input) => {
|
|
40166
39759
|
const sourceHandle = input.sourceHandle.trim();
|
|
@@ -40177,7 +39770,6 @@ function createOrchestrationTransport(endpoint, deps = {}) {
|
|
|
40177
39770
|
},
|
|
40178
39771
|
coordinatorAnswerQuestion: async (input) => await client.coordinatorAnswerQuestion(input),
|
|
40179
39772
|
coordinatorRequestHumanInput: async (input) => await client.coordinatorRequestHumanInput(input),
|
|
40180
|
-
coordinatorFollowUpHumanPackage: async (input) => await client.coordinatorFollowUpHumanPackage(input),
|
|
40181
39773
|
coordinatorReviewContestedResult: async (input) => await client.coordinatorReviewContestedResult(input)
|
|
40182
39774
|
};
|
|
40183
39775
|
}
|
|
@@ -40189,32 +39781,12 @@ var WATCH_TASKS_CACHE_LIMIT = 256;
|
|
|
40189
39781
|
var WEACPX_MCP_SERVER_INSTRUCTIONS = [
|
|
40190
39782
|
"Use these tools to orchestrate work across other agents under your coordinator session.",
|
|
40191
39783
|
"",
|
|
40192
|
-
"
|
|
40193
|
-
"
|
|
40194
|
-
"1. Call delegate_request with task execution requested. It returns a native MCP task handle immediately.",
|
|
40195
|
-
"2. Use task_watch with MCP task execution to start a background watcher, or use tasks/get / tasks/list to poll status. Use tasks/result after terminal status, or on input_required to receive an actionable next-step package; use tasks/cancel to cancel.",
|
|
40196
|
-
" - When tasks/result returns input_required, that result stream is complete. Call the recommended tool, then resume polling with tasks/get / tasks/result.",
|
|
40197
|
-
"3. Status mapping: working = running, input_required = needs_confirmation / blocked / waiting_for_human / contested review, completed / failed / cancelled are terminal.",
|
|
40198
|
-
"",
|
|
40199
|
-
"Legacy tool lifecycle for clients without MCP Tasks support:",
|
|
40200
|
-
"1. delegate_request → returns { taskId, status }.",
|
|
40201
|
-
" - status=running: the worker has started. Return the taskId to the user, use task_get / task_list for non-blocking snapshots, or task_watch to long-poll for the next event; only go to step 2 when you intentionally want to block waiting.",
|
|
40202
|
-
" - status=needs_confirmation: tell the user, then call task_approve or task_reject based on their response. After task_approve, use task_get/task_list for snapshots or step 2 only if intentionally blocking. Do not call task_wait before approval.",
|
|
40203
|
-
"2. Optional blocking wait: task_wait(taskId) → blocks until the task is done, needs attention, or times out. Do not call it automatically when the user asked to delegate and continue.",
|
|
40204
|
-
" - status=terminal: go to step 3.",
|
|
40205
|
-
" - status=attention_required: the task is in needs_confirmation / blocked / waiting_for_human, or has reviewPending set. Call task_get(taskId) to read the actual status and any openQuestion / reviewPending fields, then branch:",
|
|
40206
|
-
" * needs_confirmation -> task_approve or task_reject (after approval, use snapshots or optional blocking wait only if needed)",
|
|
40207
|
-
" * blocked or waiting_for_human -> coordinator_answer_question (the answer can come from you or be relayed from a human you consulted)",
|
|
40208
|
-
" * reviewPending set -> coordinator_review_contested_result with accept or discard",
|
|
40209
|
-
" After resolving, use task_get / task_list for snapshots, or step 2 only if intentionally blocking.",
|
|
40210
|
-
" - status=timeout: the task is still running. Use task_get for a snapshot, or call task_wait again only if you still intentionally want to block.",
|
|
40211
|
-
"3. The task is terminal. Call task_get(taskId) to read the worker's final result, then summarize it for the user. Do not invent results that did not come from task_get.",
|
|
39784
|
+
"Delegate with delegate_request (one task) or delegate_batch (several at once). Each returns a taskId and a status.",
|
|
39785
|
+
"Then follow the task: clients that support MCP Tasks should request task execution on delegate_request / task_watch and poll with tasks/get / tasks/list / tasks/result; other clients use task_get / task_list for snapshots or task_watch to long-poll.",
|
|
40212
39786
|
"",
|
|
40213
|
-
"
|
|
40214
|
-
"Cancellation: task_cancel aborts a single running task; group_cancel aborts the whole batch.",
|
|
40215
|
-
"Discovery: task_list / group_list recover taskIds and groupIds from earlier in the session.",
|
|
39787
|
+
"Most tool results end with a 'Next:' line telling you the concrete next step — follow it when present. In short: status=needs_confirmation needs task_approve or task_cancel; a task that needs attention (blocked / waiting_for_human / a contested review) is resolved with coordinator_answer_question or coordinator_review_contested_result; a terminal task is read with task_get. Never report a result you did not read from task_get.",
|
|
40216
39788
|
"",
|
|
40217
|
-
"worker_raise_question is worker-side only — call it from inside a delegated task when you are blocked, not from the coordinator
|
|
39789
|
+
"worker_raise_question is worker-side only — call it from inside a delegated task when you are blocked, not from the coordinator waiting on a delegation."
|
|
40218
39790
|
].join(`
|
|
40219
39791
|
`);
|
|
40220
39792
|
function createWeacpxMcpServer(options) {
|
|
@@ -40627,7 +40199,7 @@ function renderInputRequiredTaskResult(task) {
|
|
|
40627
40199
|
function inputRequiredActions(task) {
|
|
40628
40200
|
const actions = [];
|
|
40629
40201
|
if (task.status === "needs_confirmation") {
|
|
40630
|
-
actions.push("task_approve", "
|
|
40202
|
+
actions.push("task_approve", "task_cancel");
|
|
40631
40203
|
}
|
|
40632
40204
|
if (task.status === "blocked" || task.status === "waiting_for_human" || task.openQuestion) {
|
|
40633
40205
|
actions.push("coordinator_answer_question");
|