@ai-setting/roy-agent-core 1.7.72 → 1.7.76

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.
Files changed (91) hide show
  1. package/dist/env/agent/agent-component.js +6 -6
  2. package/dist/env/agent/agent-registry.d.ts +4 -1
  3. package/dist/env/agent/index.js +6 -6
  4. package/dist/env/error-reply.d.ts +46 -0
  5. package/dist/env/error-reply.js +3 -1
  6. package/dist/env/event-source/event-source-handlers.js +13 -12
  7. package/dist/env/event-source/index.js +14 -13
  8. package/dist/env/index.js +31 -30
  9. package/dist/env/llm/index.js +2 -2
  10. package/dist/env/llm/orphan-toolcall.d.ts +107 -0
  11. package/dist/env/plugin/index.js +3 -3
  12. package/dist/env/prompt/index.js +4 -3
  13. package/dist/env/prompt/prompts-index.d.ts +27 -3
  14. package/dist/env/session/index.js +4 -4
  15. package/dist/env/session/storage/index.js +3 -3
  16. package/dist/env/task/backend/index.js +9 -1
  17. package/dist/env/task/delegate/delegate-tool.d.ts +8 -0
  18. package/dist/env/task/delegate/delegate-tool.js +5 -4
  19. package/dist/env/task/delegate/index.js +5 -4
  20. package/dist/env/task/hooks/contexts.d.ts +12 -1
  21. package/dist/env/task/hooks/task-hook-points.d.ts +8 -3
  22. package/dist/env/task/index.d.ts +1 -0
  23. package/dist/env/task/index.js +17 -7
  24. package/dist/env/task/mcp/index.js +3 -2
  25. package/dist/env/task/plugins/index.d.ts +3 -0
  26. package/dist/env/task/plugins/index.js +33 -9
  27. package/dist/env/task/plugins/lark-card-patch-notifier.d.ts +61 -0
  28. package/dist/env/task/plugins/lark-card-patch-notifier.js +6 -2
  29. package/dist/env/task/plugins/lark-cli-task-notify-plugin.d.ts +42 -0
  30. package/dist/env/task/prompt/index.js +2 -1
  31. package/dist/env/task/prompt/task-discipline.d.ts +9 -3
  32. package/dist/env/task/task-component.d.ts +79 -0
  33. package/dist/env/task/tools/cancel-tool.d.ts +36 -0
  34. package/dist/env/task/tools/completion-copy.d.ts +92 -0
  35. package/dist/env/task/tools/index.d.ts +2 -0
  36. package/dist/env/task/tools/index.js +7 -2
  37. package/dist/env/task/tools/pre-complete-tool.d.ts +32 -0
  38. package/dist/env/task/tools/task-types.d.ts +71 -17
  39. package/dist/env/task/types.d.ts +13 -1
  40. package/dist/env/tool/built-in/compact-session-tool.d.ts +120 -0
  41. package/dist/env/tool/built-in/index.d.ts +2 -0
  42. package/dist/env/tool/built-in/index.js +6 -2
  43. package/dist/env/tool/index.js +4 -4
  44. package/dist/env/workflow/engine/index.js +6 -6
  45. package/dist/env/workflow/index.js +15 -13
  46. package/dist/env/workflow/plugins/index.js +2 -2
  47. package/dist/env/workflow/tools/ask-user-tool.d.ts +88 -0
  48. package/dist/env/workflow/tools/index.js +11 -9
  49. package/dist/env/workflow/tools/run-workflow.d.ts +2 -2
  50. package/dist/env/workflow/types/index.js +2 -2
  51. package/dist/env/workflow/types/workflow-hil.d.ts +25 -1
  52. package/dist/env/workflow/utils/index.js +5 -5
  53. package/dist/index.d.ts +1 -1
  54. package/dist/index.js +43 -33
  55. package/dist/shared/@ai-setting/{roy-agent-core-sm0sf6sb.js → roy-agent-core-0qyrk5k0.js} +2 -2
  56. package/dist/shared/@ai-setting/{roy-agent-core-kmbct9yg.js → roy-agent-core-0snm5hc5.js} +1 -1
  57. package/dist/shared/@ai-setting/{roy-agent-core-yr1mryb8.js → roy-agent-core-1v4g0d4x.js} +1 -1
  58. package/dist/shared/@ai-setting/{roy-agent-core-rxb00gjm.js → roy-agent-core-264qexac.js} +1 -1
  59. package/dist/shared/@ai-setting/roy-agent-core-2akfd64z.js +374 -0
  60. package/dist/shared/@ai-setting/{roy-agent-core-skyc30qx.js → roy-agent-core-3fh1f7s7.js} +2 -2
  61. package/dist/shared/@ai-setting/roy-agent-core-4rtg69cn.js +26 -0
  62. package/dist/shared/@ai-setting/{roy-agent-core-add1zqsh.js → roy-agent-core-6cy43nss.js} +22 -1
  63. package/dist/shared/@ai-setting/{roy-agent-core-vah6g5yx.js → roy-agent-core-6rh8k6ba.js} +5 -5
  64. package/dist/shared/@ai-setting/{roy-agent-core-kpg25s2q.js → roy-agent-core-8ez6mccb.js} +4 -2
  65. package/dist/shared/@ai-setting/{roy-agent-core-yhwxpj12.js → roy-agent-core-9vxh6f8h.js} +233 -16
  66. package/dist/shared/@ai-setting/{roy-agent-core-7qvw65jt.js → roy-agent-core-aa2j7bk9.js} +11 -8
  67. package/dist/shared/@ai-setting/{roy-agent-core-sjr1kmfz.js → roy-agent-core-acj8ag08.js} +1 -1
  68. package/dist/shared/@ai-setting/{roy-agent-core-mds8tqd0.js → roy-agent-core-cgtq6427.js} +1 -1
  69. package/dist/shared/@ai-setting/{roy-agent-core-34jz9mgh.js → roy-agent-core-cmprygrp.js} +1 -1
  70. package/dist/shared/@ai-setting/{roy-agent-core-wr7mv7k3.js → roy-agent-core-cxy143m4.js} +1 -1
  71. package/dist/shared/@ai-setting/{roy-agent-core-pakhchy7.js → roy-agent-core-ddyk1rc0.js} +1 -1
  72. package/dist/shared/@ai-setting/{roy-agent-core-attpry6g.js → roy-agent-core-dqxec05w.js} +4 -3
  73. package/dist/shared/@ai-setting/{roy-agent-core-vm8h5zyj.js → roy-agent-core-ed233k5z.js} +1 -1
  74. package/dist/shared/@ai-setting/{roy-agent-core-jrj30vq3.js → roy-agent-core-er070zjq.js} +1 -1
  75. package/dist/shared/@ai-setting/{roy-agent-core-40rv283c.js → roy-agent-core-fghc2m8z.js} +152 -2
  76. package/dist/shared/@ai-setting/{roy-agent-core-5gw0qa8m.js → roy-agent-core-ghnagzrh.js} +557 -92
  77. package/dist/shared/@ai-setting/{roy-agent-core-4jjwewvw.js → roy-agent-core-m46fe3x4.js} +41 -30
  78. package/dist/shared/@ai-setting/{roy-agent-core-e25xkv53.js → roy-agent-core-mkc3zshb.js} +3 -1
  79. package/dist/shared/@ai-setting/{roy-agent-core-hfyfavp3.js → roy-agent-core-mww0mnd9.js} +231 -27
  80. package/dist/shared/@ai-setting/{roy-agent-core-46rv4d7d.js → roy-agent-core-nmx9934r.js} +92 -2
  81. package/dist/shared/@ai-setting/{roy-agent-core-1w9y7mxj.js → roy-agent-core-p3zv1mx5.js} +1 -1
  82. package/dist/shared/@ai-setting/{roy-agent-core-jgb3bb42.js → roy-agent-core-q5r75vev.js} +17 -8
  83. package/dist/shared/@ai-setting/{roy-agent-core-y12kyxwa.js → roy-agent-core-t3rrb959.js} +33 -9
  84. package/dist/shared/@ai-setting/{roy-agent-core-dt104qa1.js → roy-agent-core-v85n42ve.js} +1 -1
  85. package/dist/shared/@ai-setting/{roy-agent-core-gr48c89p.js → roy-agent-core-v87njmq7.js} +3 -3
  86. package/dist/shared/@ai-setting/{roy-agent-core-7sj9xs9c.js → roy-agent-core-vffccgf6.js} +252 -25
  87. package/dist/shared/@ai-setting/{roy-agent-core-2gzt2q8c.js → roy-agent-core-z43aj03k.js} +134 -29
  88. package/dist/shared/@ai-setting/roy-agent-core-zycadbpx.js +662 -0
  89. package/package.json +1 -1
  90. package/dist/shared/@ai-setting/roy-agent-core-1p6syv85.js +0 -1083
  91. package/dist/shared/@ai-setting/roy-agent-core-58804s3j.js +0 -155
@@ -1,7 +1,8 @@
1
- // src/env/task/tools/completion-copy.ts
2
- var TASK_COMPLETE_ITEM_BY_ITEM = "按子项逐条验收";
3
- var TASK_COMPLETION_HINT_ANCHOR = "TASK_COMPLETION_HINT";
4
- var TASK_COMPLETE_VERIFY_DUTY = "核实义务";
1
+ import {
2
+ TASK_COMPLETE_ITEM_BY_ITEM,
3
+ TASK_COMPLETE_VERIFY_DUTY,
4
+ TASK_COMPLETION_HINT_ANCHOR
5
+ } from "./roy-agent-core-4rtg69cn.js";
5
6
 
6
7
  // src/env/task/prompt/task-discipline.ts
7
8
  var TASK_DISCIPLINE_LIFECYCLE = `### Task Lifecycle (7 steps, 0-6)
@@ -52,13 +53,21 @@ var TASK_DISCIPLINE_LIFECYCLE = `### Task Lifecycle (7 steps, 0-6)
52
53
 
53
54
  4. TRACK
54
55
  - Update progress (0-100%) as the work advances
55
- - Update status: todo → active → completed
56
+ - Update status: todo → active
56
57
  - Record \`current_status\` with human-readable progress
58
+ - ⚠️ **不要**把 status 直接置为 \`completed\` 或 \`to_validate\` ——
59
+ 终态由验收方落、待验证由 \`task_pre_complete\` 提交(见步骤 6)
57
60
 
58
61
  5. RECORD — operation records (see Operation Discipline below)
59
62
 
60
- 6. COMPLETE — \`task_complete\` after item-by-item verification
61
- (see Complete Discipline below)`;
63
+ 6. COMPLETE — 收尾分两种角色(Task #5007/#5073,验收权分离)
64
+ - **执行方(roy sub-agent)**:进度达到你判断的 100% ⇒
65
+ \`task_pre_complete\` **提交待验证**(\`deliverable_storage_path\`
66
+ 传交付物地址;status → to_validate,并触发一次 goal 检查自查)
67
+ + 最后一条 \`task_operation_create\` ⇒ **结束并返回结果**。
68
+ ❌ **不要调用 \`task_complete\`**(你无此权限)。
69
+ - **验收方(default agent / 接待员)**:\`task_complete\` after item-by-item verification
70
+ (see Complete Discipline below)`.trim();
62
71
  var TASK_DISCIPLINE_OPERATION = `### Operation Record — 双维度分工规范
63
72
 
64
73
  **Record milestones as you work** — call \`task_operation_create\` the moment a
@@ -124,7 +133,11 @@ Reference the four atomic assertion forms (Task #4768
124
133
  - 进程断言 (process assertion): command exit code / stdout match
125
134
  - 测试断言 (test assertion): pass/fail counts, no NEW fail
126
135
  - 状态断言 (state assertion): version number / HTTP 200 / status field`;
127
- var TASK_DISCIPLINE_COMPLETE = `### Task Complete — 核实义务
136
+ var TASK_DISCIPLINE_COMPLETE = `### Task Complete — 核实义务(**仅验收方适用**)
137
+
138
+ > ⚠️ **角色作用域(Task #5007)**:本节是**验收方**(default agent / 接待员)的动作。
139
+ > 若你是**执行方**(roy sub-agent),你没有 \`task_complete\` 权限 ——
140
+ > 你的收尾动作是「进度推到 100% + 记完操作记录 + 结束返回」,验收由主智能体负责。
128
141
 
129
142
  Before calling \`task_complete\`, you MUST:
130
143
 
@@ -142,34 +155,32 @@ Before calling \`task_complete\`, you MUST:
142
155
  \`[${TASK_COMPLETION_HINT_ANCHOR}]\`.
143
156
  - **If you receive a [${TASK_COMPLETION_HINT_ANCHOR}]**, you MUST verify it
144
157
  (${TASK_COMPLETE_VERIFY_DUTY}): re-read the task via \`task_get\`, then do exactly one of:
145
- (a) 确认未完成 → \`task_update(task_id=<id>, status=todo)\` to **reopen**
146
- the task and continue the work; or
147
- (b) 确认已完成 → \`task_operation_create\` (milestone_type=decision,
148
- milestone_title=<一行结论>) **state why** the sub-items are actually
149
- met (说明理由).
158
+ (a) 确认未完成 → **重新委托**(用你的委托工具 + 同一 sub-session 续跑,
159
+ 在指令里写明"目标尚未达成,需要补 X/Y/Z"),由 sub-agent 用
160
+ \`task_update(status=active)\` 重开并继续推进;若你**自己就是执行方**
161
+ (有 \`task_update\` 权限),则直接 \`task_update(status=todo)\` 重开;或
162
+ (b) 确认已完成 → **用你手上有权限的写工具**落一条 \`decision\` 类操作记录
163
+ (\`task_operation_create\`,milestone_type=decision,milestone_title=<一行结论>)
164
+ 说明子项实际已达成(说明理由)。若你没有该工具的权限(验收方场景),
165
+ 就通过你的**委托工具**让 sub-agent 代写这条记录,或在最终汇报里
166
+ 明确写出核实结论与证据。
150
167
  Never ignore it (不允许无视).
168
+ ⚠️ **核实义务的两条路径都依赖写权限**(\`task_update\` / \`task_operation_create\`)。
169
+ 若这些工具对你**不可用**(如验收方不持有执行类工具),必须**改用委托**把动作
170
+ 交回给有权限的 sub-agent 执行 —— 不要试图调用不可用的工具(会被拦掉并浪费一轮迭代)。
151
171
  - If the goal and delivery mismatch **without** a hint, either:
152
172
  (a) extend the task via \`task_update\`, or
153
173
  (b) record the discrepancy via \`task_operation_create\`
154
174
  (milestone_type=decision) — the reason **must** land in the
155
175
  operation record (必须落到操作记录里), not merely a line in
156
176
  your final report (不能只在报告里带一句).
157
- 3. **Provide \`deliverable_storage_path\`** parameter with the deliverable's address.
158
- It may name **multiple paths** (multiple deliverables), space-separated
159
- (\`/tmp/report.md /tmp/diff.patch\`) — the judge splits on whitespace as
160
- well as \`,\` \`;\` \`、\` and \` + \`. A local path may also be written in its
161
- \`file://\` form (\`file:///tmp/report.md\`) — the scheme is stripped and the
162
- path kept. Declare **every** artefact you produced: a path left out reads
163
- as "not produced".
164
- - Feishu doc URL (e.g., https://my.feishu.cn/docx/abc)
165
- - Local file path (e.g., /tmp/report.md)
166
- - Git branch or worktree path (e.g., feature/my-feature)
167
- - GitHub commit URL or PR URL
168
- - Cloud drive URL (e.g., https://my.feishu.cn/file/abc)
169
- - Or any other locator that points to where the work product lives
170
-
171
- The \`deliverable_storage_path\` will be persisted to the task's
172
- \`context.deliverable_storage_path\` for future reference and traceability.`;
177
+ 3. Deliverables were submitted by the executor via \`task_pre_complete\`
178
+ (Task #5073 two-phase acceptance): they live in
179
+ \`context.deliverable_storage_path\` and the operation trail
180
+ (\`Deliverable: <path>\` lines). Cross-check them in step 2.
181
+ \`task_complete\` takes **no** deliverable parameter — if the
182
+ deliverables are missing from the record, re-delegate instead of
183
+ asking for a path here.`;
173
184
  var TASK_DISCIPLINE_PROMPT = [
174
185
  TASK_DISCIPLINE_LIFECYCLE,
175
186
  TASK_DISCIPLINE_OPERATION,
@@ -179,4 +190,4 @@ var TASK_DISCIPLINE_PROMPT = [
179
190
 
180
191
  `);
181
192
 
182
- export { TASK_COMPLETE_ITEM_BY_ITEM, TASK_COMPLETION_HINT_ANCHOR, TASK_COMPLETE_VERIFY_DUTY, TASK_DISCIPLINE_LIFECYCLE, TASK_DISCIPLINE_OPERATION, TASK_DISCIPLINE_GOALS, TASK_DISCIPLINE_COMPLETE, TASK_DISCIPLINE_PROMPT };
193
+ export { TASK_DISCIPLINE_LIFECYCLE, TASK_DISCIPLINE_OPERATION, TASK_DISCIPLINE_GOALS, TASK_DISCIPLINE_COMPLETE, TASK_DISCIPLINE_PROMPT };
@@ -35,9 +35,10 @@ var init_workflow_hil = __esm(() => {
35
35
  query;
36
36
  agentSessionId;
37
37
  timestamp;
38
+ delivered;
38
39
  type = "ask-user";
39
40
  name = "AskUserError";
40
- constructor(runId, sessionId, nodeId, nodeType, query, agentSessionId, timestamp = Date.now()) {
41
+ constructor(runId, sessionId, nodeId, nodeType, query, agentSessionId, timestamp = Date.now(), delivered = false) {
41
42
  super(`[${nodeType}:${nodeId}] Ask user: ${query}`);
42
43
  this.runId = runId;
43
44
  this.sessionId = sessionId;
@@ -46,6 +47,7 @@ var init_workflow_hil = __esm(() => {
46
47
  this.query = query;
47
48
  this.agentSessionId = agentSessionId;
48
49
  this.timestamp = timestamp;
50
+ this.delivered = delivered;
49
51
  }
50
52
  toEvent() {
51
53
  return {
@@ -1,20 +1,29 @@
1
1
  import {
2
2
  isValidSessionId
3
- } from "./roy-agent-core-pakhchy7.js";
3
+ } from "./roy-agent-core-ddyk1rc0.js";
4
4
  import {
5
5
  TAG_MAX_COUNT,
6
6
  TAG_MIN_COUNT
7
7
  } from "./roy-agent-core-12n08pg5.js";
8
+ import {
9
+ deliverAskUserMessage
10
+ } from "./roy-agent-core-6cy43nss.js";
8
11
  import {
9
12
  validateWorkflowDefinition
10
- } from "./roy-agent-core-yr1mryb8.js";
13
+ } from "./roy-agent-core-1v4g0d4x.js";
11
14
  import {
12
15
  getCurrentBgTaskId
13
16
  } from "./roy-agent-core-c1v263jn.js";
14
17
  import {
15
18
  AskUserError,
16
19
  init_workflow_hil
17
- } from "./roy-agent-core-e25xkv53.js";
20
+ } from "./roy-agent-core-mkc3zshb.js";
21
+ import {
22
+ init_context
23
+ } from "./roy-agent-core-qqaak24r.js";
24
+ import {
25
+ getEnvContext
26
+ } from "./roy-agent-core-7cbpmk4q.js";
18
27
  import {
19
28
  TracedAs,
20
29
  init_decorator
@@ -30,12 +39,185 @@ import {
30
39
 
31
40
  // src/env/workflow/tools/ask-user-tool.ts
32
41
  init_workflow_hil();
42
+ init_context();
43
+ init_logger();
33
44
  import { z } from "zod";
45
+ var logger = createLogger("AskUserTool");
34
46
  var AskUserInputSchema = z.object({
35
47
  query: z.string().describe("The question or request to ask the user"),
36
48
  options: z.array(z.string()).optional().describe("Optional choices for the user"),
37
49
  required_confirm: z.boolean().optional().describe("If true, user must explicitly confirm")
38
50
  });
51
+ function isProcessingAskUserEvent(envContext) {
52
+ const type = envContext?.envEvent?.type;
53
+ return type === "task.background.ask_user";
54
+ }
55
+ function getEnvContextSafe() {
56
+ try {
57
+ return getEnvContext();
58
+ } catch {
59
+ return;
60
+ }
61
+ }
62
+ function resolveDeliveryTarget(context) {
63
+ if (context.metadata?.askUserDelivery === "off") {
64
+ return { skipReason: "off" };
65
+ }
66
+ let envContext;
67
+ try {
68
+ envContext = getEnvContext();
69
+ } catch {
70
+ envContext = undefined;
71
+ }
72
+ if (!envContext)
73
+ return {};
74
+ if (isProcessingAskUserEvent(envContext)) {
75
+ const payloadDelivered = envContext.envEvent?.payload?.delivered;
76
+ if (payloadDelivered === true) {
77
+ return { skipReason: "guarded-turn" };
78
+ }
79
+ const fallback = resolveDeliveryTargetFromContext(context, envContext);
80
+ return { ...fallback, skipReason: "delivery-failed" };
81
+ }
82
+ return resolveDeliveryTargetFromContext(context, envContext);
83
+ }
84
+ function resolveDeliveryTargetFromContext(_context, envContext) {
85
+ const replyChannel = envContext.replyChannel;
86
+ if (replyChannel) {
87
+ const hasSender = typeof replyChannel.sendMarkdown === "function" || typeof replyChannel.sendText === "function" || typeof replyChannel.reply === "function";
88
+ if (!replyChannel.chatId && !replyChannel.messageId) {
89
+ return {};
90
+ }
91
+ return {
92
+ target: {
93
+ chatId: replyChannel.chatId,
94
+ messageId: replyChannel.messageId,
95
+ profile: replyChannel.profile,
96
+ ...hasSender ? { channel: replyChannel } : {}
97
+ }
98
+ };
99
+ }
100
+ const metaChannel = envContext.envEvent?.metadata?.replyChannel;
101
+ if (metaChannel?.chatId || metaChannel?.messageId) {
102
+ return {
103
+ target: {
104
+ chatId: metaChannel.chatId,
105
+ messageId: metaChannel.messageId,
106
+ profile: metaChannel.profile
107
+ }
108
+ };
109
+ }
110
+ return {};
111
+ }
112
+ function buildAskUserDeliveryText(args) {
113
+ const lines = [];
114
+ lines.push("❓ **需要您确认**");
115
+ lines.push("");
116
+ lines.push(args.query.trim());
117
+ if (args.options && args.options.length > 0) {
118
+ lines.push("");
119
+ lines.push("**可选方案:**");
120
+ args.options.forEach((opt, i) => {
121
+ lines.push(`${i + 1}. ${opt}`);
122
+ });
123
+ }
124
+ if (args.requiredConfirm) {
125
+ lines.push("");
126
+ lines.push("(需要您明确确认后才会继续)");
127
+ }
128
+ lines.push("");
129
+ lines.push("\uD83D\uDC49 直接在本会话回复文字或序号即可(例如「1」)。");
130
+ return lines.join(`
131
+ `);
132
+ }
133
+ var DELIVERY_TIMEOUT_MS = 15000;
134
+ function withDeliveryTimeout(p, ms) {
135
+ return new Promise((resolve) => {
136
+ let settled = false;
137
+ const timer = setTimeout(() => {
138
+ if (settled)
139
+ return;
140
+ settled = true;
141
+ resolve(null);
142
+ }, ms);
143
+ timer.unref?.();
144
+ p.then((v) => {
145
+ if (settled)
146
+ return;
147
+ settled = true;
148
+ clearTimeout(timer);
149
+ resolve(v);
150
+ }, () => {
151
+ if (settled)
152
+ return;
153
+ settled = true;
154
+ clearTimeout(timer);
155
+ resolve(null);
156
+ });
157
+ });
158
+ }
159
+ async function deliverAskUserToChannel(target, text) {
160
+ const channel = target.channel;
161
+ if (channel) {
162
+ try {
163
+ if (typeof channel.sendMarkdown === "function") {
164
+ const r = await withDeliveryTimeout(Promise.resolve(channel.sendMarkdown(text)), DELIVERY_TIMEOUT_MS);
165
+ if (r === null) {
166
+ logger.warn("[ask_user] Channel delivery timed out (ignored)", {
167
+ chatId: target.chatId,
168
+ timeoutMs: DELIVERY_TIMEOUT_MS
169
+ });
170
+ return false;
171
+ }
172
+ return true;
173
+ }
174
+ if (typeof channel.sendText === "function") {
175
+ const r = await withDeliveryTimeout(Promise.resolve(channel.sendText(text)), DELIVERY_TIMEOUT_MS);
176
+ if (r === null) {
177
+ logger.warn("[ask_user] Channel delivery timed out (ignored)", {
178
+ chatId: target.chatId,
179
+ timeoutMs: DELIVERY_TIMEOUT_MS
180
+ });
181
+ return false;
182
+ }
183
+ return true;
184
+ }
185
+ if (typeof channel.reply === "function" && target.messageId) {
186
+ const r = await withDeliveryTimeout(Promise.resolve(channel.reply(text)), DELIVERY_TIMEOUT_MS);
187
+ if (r === null) {
188
+ logger.warn("[ask_user] Channel delivery timed out (ignored)", {
189
+ chatId: target.chatId,
190
+ timeoutMs: DELIVERY_TIMEOUT_MS
191
+ });
192
+ return false;
193
+ }
194
+ return true;
195
+ }
196
+ return false;
197
+ } catch (err) {
198
+ logger.warn("[ask_user] Failed to deliver question to channel (ignored)", {
199
+ error: err instanceof Error ? err.message : String(err),
200
+ chatId: target.chatId
201
+ });
202
+ return false;
203
+ }
204
+ }
205
+ if (!target.chatId && !target.messageId)
206
+ return false;
207
+ const result = await deliverAskUserMessage({
208
+ chatId: target.chatId,
209
+ messageId: target.messageId,
210
+ profile: target.profile,
211
+ content: text
212
+ });
213
+ if (!result.sent) {
214
+ logger.warn("[ask_user] Failed to deliver question via lark-cli (ignored)", {
215
+ error: result.error,
216
+ chatId: target.chatId
217
+ });
218
+ }
219
+ return result.sent;
220
+ }
39
221
  var askUserTool = {
40
222
  name: "ask_user",
41
223
  description: "Ask user for input or confirmation. Use this tool when you need user input or validation to continue the workflow.",
@@ -48,7 +230,29 @@ var askUserTool = {
48
230
  if (args.options && args.options.length > 0) {
49
231
  fullQuery = `${args.query} (选项: ${args.options.join(", ")})`;
50
232
  }
51
- throw new AskUserError(runId, sessionId, nodeId, "agent", fullQuery);
233
+ const resolved = resolveDeliveryTarget(context);
234
+ const target = resolved.target;
235
+ let delivered = false;
236
+ if (resolved.skipReason === "guarded-turn") {
237
+ delivered = true;
238
+ logger.info("[ask_user] Guarded turn — question already delivered by sub-agent, skip (delivered=true)", {
239
+ envEventType: getEnvContextSafe()?.envEvent?.type
240
+ });
241
+ } else if (target) {
242
+ const text = buildAskUserDeliveryText({
243
+ query: args.query,
244
+ options: args.options,
245
+ requiredConfirm: args.required_confirm
246
+ });
247
+ delivered = await deliverAskUserToChannel(target, text);
248
+ logger.info("[ask_user] Question delivered to channel", {
249
+ chatId: target.chatId,
250
+ delivered,
251
+ skipReason: resolved.skipReason,
252
+ hasOptions: Boolean(args.options && args.options.length > 0)
253
+ });
254
+ }
255
+ throw new AskUserError(runId, sessionId, nodeId, "agent", fullQuery, undefined, undefined, delivered);
52
256
  },
53
257
  metadata: {
54
258
  category: "workflow",
@@ -61,7 +265,7 @@ var askUserToolInstance = askUserTool;
61
265
  // src/env/workflow/tools/workflow-get-tool.ts
62
266
  init_logger();
63
267
  import { z as z2 } from "zod";
64
- var logger = createLogger("workflow-get-tool");
268
+ var logger2 = createLogger("workflow-get-tool");
65
269
  var WorkflowGetInputSchema = z2.object({
66
270
  name: z2.string().optional().describe("Workflow name to get definition details"),
67
271
  run_id: z2.string().optional().describe("Run/session ID to get run status")
@@ -137,7 +341,7 @@ function createWorkflowGetTool(workflowService) {
137
341
  metadata: { execution_time_ms: 0 }
138
342
  };
139
343
  } catch (error) {
140
- logger.error("Failed to get workflow info", { error });
344
+ logger2.error("Failed to get workflow info", { error });
141
345
  return {
142
346
  success: false,
143
347
  output: "",
@@ -152,7 +356,7 @@ function createWorkflowGetTool(workflowService) {
152
356
  // src/env/workflow/tools/workflow-list-tool.ts
153
357
  init_logger();
154
358
  import { z as z3 } from "zod";
155
- var logger2 = createLogger("workflow-list-tool");
359
+ var logger3 = createLogger("workflow-list-tool");
156
360
  var WorkflowListInputSchema = z3.object({
157
361
  tag: z3.string().optional().describe("Filter by single tag (legacy single-tag filter)"),
158
362
  tags: z3.array(z3.string()).optional().describe("Filter by multiple tags (AND)"),
@@ -237,7 +441,7 @@ function createWorkflowListTool(workflowService) {
237
441
  metadata: { execution_time_ms: 0 }
238
442
  };
239
443
  } catch (error) {
240
- logger2.error("Failed to list workflows", { error });
444
+ logger3.error("Failed to list workflows", { error });
241
445
  return {
242
446
  success: false,
243
447
  output: "",
@@ -253,7 +457,7 @@ function createWorkflowListTool(workflowService) {
253
457
  init_logger();
254
458
  init_decorator();
255
459
  import { z as z4 } from "zod";
256
- var logger3 = createLogger("workflow-tag-list-tool");
460
+ var logger4 = createLogger("workflow-tag-list-tool");
257
461
  var WorkflowTagListInputSchema = z4.object({
258
462
  sort_by: z4.enum(["usage_count", "name", "created_at"]).default("usage_count").describe("Sort field: usage_count (default), name, or created_at"),
259
463
  order: z4.enum(["asc", "desc"]).default("desc").describe("Sort order: desc (default) or asc"),
@@ -304,7 +508,7 @@ function createWorkflowTagListTool(workflowService) {
304
508
  metadata: { execution_time_ms: 0 }
305
509
  };
306
510
  } catch (error) {
307
- logger3.error("Failed to list workflow tags", { error });
511
+ logger4.error("Failed to list workflow tags", { error });
308
512
  return {
309
513
  success: false,
310
514
  output: "",
@@ -320,7 +524,7 @@ function createWorkflowTagListTool(workflowService) {
320
524
  import { z as z5 } from "zod";
321
525
  init_logger();
322
526
  import yaml from "yaml";
323
- var logger4 = createLogger("workflow-add-tool");
527
+ var logger5 = createLogger("workflow-add-tool");
324
528
  var WorkflowAddInputSchema = z5.object({
325
529
  definition: z5.any().optional().describe("Workflow definition object (alternative to definition_yaml)"),
326
530
  definition_yaml: z5.string().optional().describe("Workflow definition as YAML or JSON string"),
@@ -461,7 +665,7 @@ function createWorkflowAddTool(workflowService) {
461
665
  metadata: { execution_time_ms: 0 }
462
666
  };
463
667
  }
464
- logger4.error("Failed to add workflow", { error });
668
+ logger5.error("Failed to add workflow", { error });
465
669
  return {
466
670
  success: false,
467
671
  output: "",
@@ -477,7 +681,7 @@ function createWorkflowAddTool(workflowService) {
477
681
  init_logger();
478
682
  import { z as z6 } from "zod";
479
683
  import yaml2 from "yaml";
480
- var logger5 = createLogger("workflow-validate-tool");
684
+ var logger6 = createLogger("workflow-validate-tool");
481
685
  var WorkflowValidateInputSchema = z6.object({
482
686
  definition: z6.any().optional().describe("Workflow definition object (alternative to definition_yaml)"),
483
687
  definition_yaml: z6.string().optional().describe("Workflow definition as YAML or JSON string"),
@@ -611,7 +815,7 @@ Advisory warnings (${warnings.length}) — evaluate and fix where sensible:
611
815
  metadata: { execution_time_ms: 0 }
612
816
  };
613
817
  } catch (error) {
614
- logger5.error("[workflow_validate] failed", { error });
818
+ logger6.error("[workflow_validate] failed", { error });
615
819
  return {
616
820
  success: false,
617
821
  output: "",
@@ -626,7 +830,7 @@ Advisory warnings (${warnings.length}) — evaluate and fix where sensible:
626
830
  // src/env/workflow/tools/workflow-search-tool.ts
627
831
  init_logger();
628
832
  import { z as z7 } from "zod";
629
- var logger6 = createLogger("workflow-search-tool");
833
+ var logger7 = createLogger("workflow-search-tool");
630
834
  var WorkflowSearchInputSchema = z7.object({
631
835
  keyword: z7.string().optional().describe("Search keyword in name and description (case-insensitive substring)"),
632
836
  tags: z7.array(z7.string()).optional().describe("Filter by tags (ALL must match - AND filter)"),
@@ -677,7 +881,7 @@ function createWorkflowSearchTool(workflowService) {
677
881
  metadata: { execution_time_ms: 0 }
678
882
  };
679
883
  } catch (error) {
680
- logger6.error("Failed to search workflows", { error });
884
+ logger7.error("Failed to search workflows", { error });
681
885
  return {
682
886
  success: false,
683
887
  output: "",
@@ -693,7 +897,7 @@ function createWorkflowSearchTool(workflowService) {
693
897
  init_logger();
694
898
  init_decorator();
695
899
  import { z as z8 } from "zod";
696
- var logger7 = createLogger("run-workflow-tool");
900
+ var logger8 = createLogger("run-workflow-tool");
697
901
  function synthFallbackRunId(now = Date.now()) {
698
902
  return `workflow_${now}_fallback_${Math.random().toString(36).slice(2, 8)}`;
699
903
  }
@@ -701,7 +905,7 @@ function attemptStopOnTimeout(workflowService, runId, reason) {
701
905
  if (typeof workflowService.stopRun !== "function")
702
906
  return;
703
907
  workflowService.stopRun(runId, reason).catch((stopErr) => {
704
- logger7.warn(`Failed to stop workflow ${runId} after timeout: ${stopErr instanceof Error ? stopErr.message : String(stopErr)}`);
908
+ logger8.warn(`Failed to stop workflow ${runId} after timeout: ${stopErr instanceof Error ? stopErr.message : String(stopErr)}`);
705
909
  });
706
910
  }
707
911
  function buildErrorReturn(args) {
@@ -922,7 +1126,7 @@ function resolveEffectiveTimeout(workflowService, workflowName, explicitTimeout)
922
1126
  return declared;
923
1127
  }
924
1128
  } catch (err) {
925
- logger7.warn(`workflow_run: could not resolve definition for ${workflowName}; ` + `falling back to the default run budget`, { error: err instanceof Error ? err.message : String(err) });
1129
+ logger8.warn(`workflow_run: could not resolve definition for ${workflowName}; ` + `falling back to the default run budget`, { error: err instanceof Error ? err.message : String(err) });
926
1130
  }
927
1131
  }
928
1132
  return DEFAULT_WORKFLOW_RUN_TIMEOUT_MS;
@@ -951,7 +1155,7 @@ function createRunWorkflowTool(workflowService, hooks) {
951
1155
  const startTime = Date.now();
952
1156
  const { workflow_name, input, session, timeout, node_config } = args;
953
1157
  const effectiveTimeout = resolveEffectiveTimeout(workflowService, workflow_name, timeout);
954
- logger7.info(`Running workflow: ${workflow_name}`, {
1158
+ logger8.info(`Running workflow: ${workflow_name}`, {
955
1159
  input,
956
1160
  timeout: effectiveTimeout,
957
1161
  timeoutSource: timeout ? "caller" : "definition-or-default",
@@ -960,7 +1164,7 @@ function createRunWorkflowTool(workflowService, hooks) {
960
1164
  const ctxSessionId = typeof ctx?.session_id === "string" && isValidSessionId(ctx.session_id) ? ctx.session_id : undefined;
961
1165
  const envSessionId = typeof process.env.ROY_PARENT_SESSION_ID === "string" && isValidSessionId(process.env.ROY_PARENT_SESSION_ID) ? process.env.ROY_PARENT_SESSION_ID : undefined;
962
1166
  if (process.env.ROY_PARENT_SESSION_ID && !envSessionId) {
963
- logger7.warn(`Ignoring malformed ROY_PARENT_SESSION_ID env value (must match /^[A-Za-z0-9_-]{8,128}$/); received length=${process.env.ROY_PARENT_SESSION_ID.length}`);
1167
+ logger8.warn(`Ignoring malformed ROY_PARENT_SESSION_ID env value (must match /^[A-Za-z0-9_-]{8,128}$/); received length=${process.env.ROY_PARENT_SESSION_ID.length}`);
964
1168
  }
965
1169
  const parentSessionId = ctxSessionId ?? envSessionId;
966
1170
  let timeoutHandle;
@@ -1102,8 +1306,8 @@ function createRunWorkflowTool(workflowService, hooks) {
1102
1306
  durationMs
1103
1307
  });
1104
1308
  }
1105
- if (logger7?.error) {
1106
- logger7.error(`Failed to run workflow: ${workflow_name}`, {
1309
+ if (logger8?.error) {
1310
+ logger8.error(`Failed to run workflow: ${workflow_name}`, {
1107
1311
  error: rawErrorMessage,
1108
1312
  errorClassification
1109
1313
  });
@@ -1156,7 +1360,7 @@ function createLegacyRunWorkflowTool(workflowService) {
1156
1360
  // src/env/workflow/tools/workflow-run-status-tool.ts
1157
1361
  init_logger();
1158
1362
  import { z as z9 } from "zod";
1159
- var logger8 = createLogger("workflow-run-status-tool");
1363
+ var logger9 = createLogger("workflow-run-status-tool");
1160
1364
  var WorkflowRunStatusInputSchema = z9.object({
1161
1365
  run_id: z9.string().describe("Run/session ID to query status")
1162
1366
  });
@@ -1198,7 +1402,7 @@ function createWorkflowRunStatusTool(workflowService) {
1198
1402
  metadata: { execution_time_ms: 0 }
1199
1403
  };
1200
1404
  } catch (error) {
1201
- logger8.error("Failed to get run status", { error });
1405
+ logger9.error("Failed to get run status", { error });
1202
1406
  return {
1203
1407
  success: false,
1204
1408
  output: "",
@@ -1213,7 +1417,7 @@ function createWorkflowRunStatusTool(workflowService) {
1213
1417
  // src/env/workflow/tools/workflow-run-stop-tool.ts
1214
1418
  init_logger();
1215
1419
  import { z as z10 } from "zod";
1216
- var logger9 = createLogger("workflow-run-stop-tool");
1420
+ var logger10 = createLogger("workflow-run-stop-tool");
1217
1421
  var WorkflowRunStopInputSchema = z10.object({
1218
1422
  run_id: z10.string().describe("Run/session ID to stop"),
1219
1423
  reason: z10.string().optional().describe("Optional reason for stopping the workflow")
@@ -1238,7 +1442,7 @@ function createWorkflowRunStopTool(workflowService) {
1238
1442
  metadata: { execution_time_ms: 0 }
1239
1443
  };
1240
1444
  } catch (error) {
1241
- logger9.error("Failed to stop workflow run", { error });
1445
+ logger10.error("Failed to stop workflow run", { error });
1242
1446
  return {
1243
1447
  success: false,
1244
1448
  output: "",