@ai-setting/roy-agent-core 1.6.6 → 1.6.7

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.
@@ -10,7 +10,7 @@ import {
10
10
  larkCliHandler,
11
11
  resolveBountyIMSystemPrompt,
12
12
  timerHandler
13
- } from "../../shared/@ai-setting/roy-agent-core-mzhsk0jb.js";
13
+ } from "../../shared/@ai-setting/roy-agent-core-jzza6c2r.js";
14
14
  import {
15
15
  BUILT_IN_EVENT_SOURCE_TYPES,
16
16
  BUILT_IN_EVENT_SOURCE_TYPE_LIST,
package/dist/env/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  EventSourceComponent,
6
6
  builtInHandlers,
7
7
  larkCliHandler
8
- } from "../shared/@ai-setting/roy-agent-core-mzhsk0jb.js";
8
+ } from "../shared/@ai-setting/roy-agent-core-jzza6c2r.js";
9
9
  import {
10
10
  EventSourceInitHooks,
11
11
  getDefaultConfigForType,
@@ -21,9 +21,9 @@ import"../shared/@ai-setting/roy-agent-core-jayzyg7h.js";
21
21
  import"../shared/@ai-setting/roy-agent-core-az13yzmc.js";
22
22
  import {
23
23
  WorkflowComponent
24
- } from "../shared/@ai-setting/roy-agent-core-b9bnm4mj.js";
24
+ } from "../shared/@ai-setting/roy-agent-core-kenhsgnf.js";
25
25
  import"../shared/@ai-setting/roy-agent-core-xgnpr28w.js";
26
- import"../shared/@ai-setting/roy-agent-core-4y3hdqw2.js";
26
+ import"../shared/@ai-setting/roy-agent-core-39rvx3fw.js";
27
27
  import"../shared/@ai-setting/roy-agent-core-6atd905e.js";
28
28
  import"../shared/@ai-setting/roy-agent-core-w7mhnc4c.js";
29
29
  import"../shared/@ai-setting/roy-agent-core-q88vxmx5.js";
@@ -31,7 +31,7 @@ import"../shared/@ai-setting/roy-agent-core-ddwa0n6h.js";
31
31
  import"../shared/@ai-setting/roy-agent-core-hhrg314p.js";
32
32
  import"../shared/@ai-setting/roy-agent-core-0tfv18rf.js";
33
33
  import"../shared/@ai-setting/roy-agent-core-qnrf2aw6.js";
34
- import"../shared/@ai-setting/roy-agent-core-smmr6wr3.js";
34
+ import"../shared/@ai-setting/roy-agent-core-ka4b12eg.js";
35
35
  import"../shared/@ai-setting/roy-agent-core-1db4vpc6.js";
36
36
  import"../shared/@ai-setting/roy-agent-core-b75jtybq.js";
37
37
  import"../shared/@ai-setting/roy-agent-core-8wd3qwx5.js";
@@ -48,7 +48,7 @@ import"../shared/@ai-setting/roy-agent-core-5h49ct1a.js";
48
48
  import"../shared/@ai-setting/roy-agent-core-e25xkv53.js";
49
49
  import {
50
50
  TaskComponent
51
- } from "../shared/@ai-setting/roy-agent-core-a5rde2ky.js";
51
+ } from "../shared/@ai-setting/roy-agent-core-gdkq55yg.js";
52
52
  import"../shared/@ai-setting/roy-agent-core-amkqnyzy.js";
53
53
  import"../shared/@ai-setting/roy-agent-core-8gxth0eh.js";
54
54
  import"../shared/@ai-setting/roy-agent-core-c94yan0b.js";
@@ -61,7 +61,7 @@ import {
61
61
  getXDGPath,
62
62
  getXDGPaths
63
63
  } from "../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
64
- import"../shared/@ai-setting/roy-agent-core-ktbkp661.js";
64
+ import"../shared/@ai-setting/roy-agent-core-sxqy40cs.js";
65
65
  import"../shared/@ai-setting/roy-agent-core-t94ktchq.js";
66
66
  import"../shared/@ai-setting/roy-agent-core-1pg0fepg.js";
67
67
  import {
@@ -5,7 +5,7 @@ import {
5
5
  TaskPriorityEnum,
6
6
  TaskStatusEnum,
7
7
  TaskTypeEnum
8
- } from "../../shared/@ai-setting/roy-agent-core-a5rde2ky.js";
8
+ } from "../../shared/@ai-setting/roy-agent-core-gdkq55yg.js";
9
9
  import"../../shared/@ai-setting/roy-agent-core-amkqnyzy.js";
10
10
  import {
11
11
  TaskEntityEventTypes
@@ -19,7 +19,7 @@ import {
19
19
  import"../../shared/@ai-setting/roy-agent-core-4extx33r.js";
20
20
  import"../../shared/@ai-setting/roy-agent-core-as3phr7n.js";
21
21
  import"../../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
22
- import"../../shared/@ai-setting/roy-agent-core-ktbkp661.js";
22
+ import"../../shared/@ai-setting/roy-agent-core-sxqy40cs.js";
23
23
  import"../../shared/@ai-setting/roy-agent-core-t94ktchq.js";
24
24
  import"../../shared/@ai-setting/roy-agent-core-1pg0fepg.js";
25
25
  import"../../shared/@ai-setting/roy-agent-core-qxhq8ven.js";
@@ -9,7 +9,7 @@ import {
9
9
  searchTasksTool,
10
10
  treeTasksTool,
11
11
  updateTaskTool
12
- } from "../../../shared/@ai-setting/roy-agent-core-ktbkp661.js";
12
+ } from "../../../shared/@ai-setting/roy-agent-core-sxqy40cs.js";
13
13
  import"../../../shared/@ai-setting/roy-agent-core-scp0afxg.js";
14
14
  import"../../../shared/@ai-setting/roy-agent-core-cg146hmg.js";
15
15
  import"../../../shared/@ai-setting/roy-agent-core-vyygk314.js";
@@ -5,7 +5,7 @@ import {
5
5
  Scheduler,
6
6
  WorkflowEngine,
7
7
  init_engine
8
- } from "../../../shared/@ai-setting/roy-agent-core-4y3hdqw2.js";
8
+ } from "../../../shared/@ai-setting/roy-agent-core-39rvx3fw.js";
9
9
  import"../../../shared/@ai-setting/roy-agent-core-6atd905e.js";
10
10
  import"../../../shared/@ai-setting/roy-agent-core-w7mhnc4c.js";
11
11
  import"../../../shared/@ai-setting/roy-agent-core-q88vxmx5.js";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  WorkflowComponent
3
- } from "../../shared/@ai-setting/roy-agent-core-b9bnm4mj.js";
3
+ } from "../../shared/@ai-setting/roy-agent-core-kenhsgnf.js";
4
4
  import"../../shared/@ai-setting/roy-agent-core-xgnpr28w.js";
5
- import"../../shared/@ai-setting/roy-agent-core-4y3hdqw2.js";
5
+ import"../../shared/@ai-setting/roy-agent-core-39rvx3fw.js";
6
6
  import"../../shared/@ai-setting/roy-agent-core-6atd905e.js";
7
7
  import"../../shared/@ai-setting/roy-agent-core-w7mhnc4c.js";
8
8
  import"../../shared/@ai-setting/roy-agent-core-q88vxmx5.js";
@@ -60,7 +60,7 @@ import {
60
60
  pathNotFound,
61
61
  unresolvedVariable
62
62
  } from "../../shared/@ai-setting/roy-agent-core-qnrf2aw6.js";
63
- import"../../shared/@ai-setting/roy-agent-core-smmr6wr3.js";
63
+ import"../../shared/@ai-setting/roy-agent-core-ka4b12eg.js";
64
64
  import"../../shared/@ai-setting/roy-agent-core-1db4vpc6.js";
65
65
  import"../../shared/@ai-setting/roy-agent-core-b75jtybq.js";
66
66
  import"../../shared/@ai-setting/roy-agent-core-8wd3qwx5.js";
@@ -24,7 +24,7 @@ import {
24
24
  getRunWorkflowTool,
25
25
  initRunWorkflowTool,
26
26
  resetRunWorkflowTool
27
- } from "../../../shared/@ai-setting/roy-agent-core-smmr6wr3.js";
27
+ } from "../../../shared/@ai-setting/roy-agent-core-ka4b12eg.js";
28
28
  import {
29
29
  WORKFLOW_SUBMIT_OUTPUT_TOOL_NAME,
30
30
  WorkflowJsonOutputMarker,
package/dist/index.js CHANGED
@@ -74,7 +74,7 @@ import {
74
74
  larkCliHandler,
75
75
  resolveBountyIMSystemPrompt,
76
76
  timerHandler
77
- } from "./shared/@ai-setting/roy-agent-core-mzhsk0jb.js";
77
+ } from "./shared/@ai-setting/roy-agent-core-jzza6c2r.js";
78
78
  import {
79
79
  BUILT_IN_EVENT_SOURCE_TYPES,
80
80
  BUILT_IN_EVENT_SOURCE_TYPE_LIST,
@@ -100,12 +100,12 @@ import {
100
100
  } from "./shared/@ai-setting/roy-agent-core-az13yzmc.js";
101
101
  import {
102
102
  WorkflowComponent
103
- } from "./shared/@ai-setting/roy-agent-core-b9bnm4mj.js";
103
+ } from "./shared/@ai-setting/roy-agent-core-kenhsgnf.js";
104
104
  import {
105
105
  init_node_registry_helper,
106
106
  registerDecoratorNodeType
107
107
  } from "./shared/@ai-setting/roy-agent-core-xgnpr28w.js";
108
- import"./shared/@ai-setting/roy-agent-core-4y3hdqw2.js";
108
+ import"./shared/@ai-setting/roy-agent-core-39rvx3fw.js";
109
109
  import"./shared/@ai-setting/roy-agent-core-6atd905e.js";
110
110
  import"./shared/@ai-setting/roy-agent-core-w7mhnc4c.js";
111
111
  import"./shared/@ai-setting/roy-agent-core-q88vxmx5.js";
@@ -113,7 +113,7 @@ import"./shared/@ai-setting/roy-agent-core-ddwa0n6h.js";
113
113
  import"./shared/@ai-setting/roy-agent-core-hhrg314p.js";
114
114
  import"./shared/@ai-setting/roy-agent-core-0tfv18rf.js";
115
115
  import"./shared/@ai-setting/roy-agent-core-qnrf2aw6.js";
116
- import"./shared/@ai-setting/roy-agent-core-smmr6wr3.js";
116
+ import"./shared/@ai-setting/roy-agent-core-ka4b12eg.js";
117
117
  import"./shared/@ai-setting/roy-agent-core-1db4vpc6.js";
118
118
  import"./shared/@ai-setting/roy-agent-core-b75jtybq.js";
119
119
  import"./shared/@ai-setting/roy-agent-core-8wd3qwx5.js";
@@ -148,7 +148,7 @@ import {
148
148
  } from "./shared/@ai-setting/roy-agent-core-e25xkv53.js";
149
149
  import {
150
150
  TaskComponent
151
- } from "./shared/@ai-setting/roy-agent-core-a5rde2ky.js";
151
+ } from "./shared/@ai-setting/roy-agent-core-gdkq55yg.js";
152
152
  import"./shared/@ai-setting/roy-agent-core-amkqnyzy.js";
153
153
  import"./shared/@ai-setting/roy-agent-core-8gxth0eh.js";
154
154
  import"./shared/@ai-setting/roy-agent-core-c94yan0b.js";
@@ -169,7 +169,7 @@ import {
169
169
  getXDGPath,
170
170
  getXDGPaths
171
171
  } from "./shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
172
- import"./shared/@ai-setting/roy-agent-core-ktbkp661.js";
172
+ import"./shared/@ai-setting/roy-agent-core-sxqy40cs.js";
173
173
  import"./shared/@ai-setting/roy-agent-core-t94ktchq.js";
174
174
  import {
175
175
  TaskHookPoints
@@ -1027,6 +1027,7 @@ var init_agent_node = __esm(() => {
1027
1027
  const promptTemplate = config.prompt || "";
1028
1028
  resolvedPrompt = context.templateResolver?.resolveValue(promptTemplate) ?? promptTemplate;
1029
1029
  }
1030
+ resolvedPrompt = this.applyPromptInjection(resolvedPrompt, context.workflowInput?.prompt_injection);
1030
1031
  let resolvedAgentType = agentType;
1031
1032
  let inheritedModel;
1032
1033
  let inheritedAllowedTools;
@@ -1137,6 +1138,16 @@ var init_agent_node = __esm(() => {
1137
1138
  };
1138
1139
  }
1139
1140
  }
1141
+ applyPromptInjection(basePrompt, promptInjection) {
1142
+ if (typeof promptInjection !== "string" || promptInjection.length === 0) {
1143
+ return basePrompt;
1144
+ }
1145
+ return `${basePrompt}
1146
+
1147
+ ---
1148
+ [Caller Injection]
1149
+ ${promptInjection}`;
1150
+ }
1140
1151
  async resolveAgentSessionIdFromWorkflow(context) {
1141
1152
  const sessionComponent = context.sessionComponent;
1142
1153
  if (!sessionComponent) {
@@ -1199,6 +1210,9 @@ var init_agent_node = __esm(() => {
1199
1210
  __legacyDecorateClassTS([
1200
1211
  TracedAs("workflow.agent.execute")
1201
1212
  ], AgentNode.prototype, "execute", null);
1213
+ __legacyDecorateClassTS([
1214
+ TracedAs("workflow.agent.applyPromptInjection", { recordParams: true, recordResult: false })
1215
+ ], AgentNode.prototype, "applyPromptInjection", null);
1202
1216
  __legacyDecorateClassTS([
1203
1217
  TracedAs("agent.node.createAgentSubSession", { recordParams: true, recordResult: true, log: true })
1204
1218
  ], AgentNode.prototype, "createAgentSubSession", null);
@@ -2184,6 +2198,9 @@ var init_engine = __esm(() => {
2184
2198
  let timer;
2185
2199
  const timeoutPromise = new Promise((_, reject) => {
2186
2200
  timer = setTimeout(() => {
2201
+ this.stop(sessionId, "execution timeout").catch((stopError) => {
2202
+ logger3.warn(`[WorkflowEngine.waitForCompletion] Failed to stop ${sessionId} after execution timeout: ${stopError instanceof Error ? stopError.message : String(stopError)}`);
2203
+ });
2187
2204
  reject(new Error(`Workflow execution timeout: ${timeoutMs}ms`));
2188
2205
  }, timeoutMs);
2189
2206
  });
@@ -2266,6 +2283,12 @@ var init_engine = __esm(() => {
2266
2283
  __legacyDecorateClassTS([
2267
2284
  TracedAs("workflow.engine.failWorkflow", { recordParams: true, recordResult: true })
2268
2285
  ], WorkflowEngine.prototype, "failWorkflow", null);
2286
+ __legacyDecorateClassTS([
2287
+ TracedAs("workflow.engine.waitForCompletion", {
2288
+ recordParams: true,
2289
+ recordResult: true
2290
+ })
2291
+ ], WorkflowEngine.prototype, "waitForCompletion", null);
2269
2292
  });
2270
2293
 
2271
2294
  // src/env/workflow/engine/index.ts
@@ -24,7 +24,7 @@ import {
24
24
  searchTasksTool,
25
25
  treeTasksTool,
26
26
  updateTaskTool
27
- } from "./roy-agent-core-ktbkp661.js";
27
+ } from "./roy-agent-core-sxqy40cs.js";
28
28
  import {
29
29
  createOperationTool,
30
30
  deleteOperationTool,
@@ -194,18 +194,23 @@ var timerHandler = {
194
194
 
195
195
  // src/env/event-source/bounty-im-handler.ts
196
196
  function readBountyIMConfig(config) {
197
- const topLevelAddress = config.address;
198
197
  const topLevelUrl = config.imServerUrl;
199
198
  const topLevelEmail = config.email;
200
- const optionsAddress = config.options?.address;
201
199
  const optionsUrl = config.options?.imServerUrl;
202
200
  const optionsEmail = config.options?.email;
203
201
  return {
204
- address: topLevelAddress || optionsAddress,
205
- imServerUrl: topLevelUrl || optionsUrl,
206
- email: topLevelEmail || optionsEmail
202
+ email: topLevelEmail || optionsEmail,
203
+ imServerUrl: topLevelUrl || optionsUrl
207
204
  };
208
205
  }
206
+ function assertNoLegacyAddressField(config) {
207
+ const legacyTopLevel = config.address;
208
+ const legacyInOptions = config.options?.address;
209
+ const legacyValue = typeof legacyTopLevel === "string" && legacyTopLevel.trim() !== "" && legacyTopLevel || typeof legacyInOptions === "string" && legacyInOptions.trim() !== "" && legacyInOptions;
210
+ if (legacyValue) {
211
+ throw new Error(`[BountyIM] v0.14 strict email-only: legacy 'address' field is no longer supported. ` + `Found: address="${legacyValue}". ` + `Migration: remove the 'address' field and add 'email' (your registered bounty email) ` + `to event-sources.json. Example: { "id": "<source-id>", "type": "bounty-im", ` + `"email": "<you@bounty.example.com>", "imServerUrl": "<ws-url>" }`);
212
+ }
213
+ }
209
214
  function readBountyIMTlsSkipVerify(config) {
210
215
  const topLevel = config.tlsSkipVerify;
211
216
  const fromOptions = config.options?.tlsSkipVerify;
@@ -216,18 +221,17 @@ function buildDefaultBountyIMSystemPrompt(input) {
216
221
  const server = input.imServerUrl || "ws://localhost:4005/ws";
217
222
  const httpScheme = server.startsWith("wss://") ? "https://" : "http://";
218
223
  const endpoint = server.replace(/^wss?:\/\//, httpScheme).replace(/\/ws$/, "");
219
- const hasEmail = !!input.currentEmail;
220
- const identity = input.currentEmail || input.currentAddress || "unknown";
221
- const command = hasEmail ? `bounty com send --server-url ${endpoint} --from-email ${input.currentEmail} --to-email <recipient-email> --body "..."` : `bounty com send --endpoint ${endpoint} -f ${input.currentAddress} -t <to-address> -b "..."`;
222
- const rule = hasEmail ? `规则:from-email 永远固定为 ${input.currentEmail}; to-email 是收到消息的 from 字段。` : `规则:to-address 总是收到的消息的 from 字段;from-address 永远固定为 ${input.currentAddress}。`;
223
- const tlsCommand = hasEmail ? ` bounty com send --server-url ${endpoint} --from-email ${input.currentEmail} --to-email <recipient-email> --body "..."` : ` bounty com send --endpoint ${endpoint} -k -f ${input.currentAddress} -t <to-address> -b "..."`;
224
+ const email = input.currentEmail || "<your-registered-email>";
225
+ const command = `bounty com send --server-url ${endpoint} --from-email ${email} --to-email <recipient-email> --body "..."`;
226
+ const tlsCommand = ` bounty com send --server-url ${endpoint} --from-email ${email} --to-email <recipient-email> --body "..."`;
227
+ const rule = `规则:from-email 永远固定为 ${email}; to-email 是收到消息的 from 字段。`;
224
228
  return [
225
229
  "你正在通过 Bounty IM 与其他 agent 通信。",
226
230
  "",
227
- `你的 IM 身份:${identity}`,
231
+ `你的 IM 身份(v0.14 strict email-only):${email}`,
228
232
  `IM Server:${endpoint} (k8s remote server)`,
229
233
  "",
230
- "回复收到的消息时,**必须**使用以下命令格式(注意 --server-url / --endpoint 不可省略,省略会默认连 localhost:4000 而失败):",
234
+ "回复收到的消息时,**必须**使用以下命令格式(注意 --server-url 不可省略,省略会默认连 localhost:4000 而失败):",
231
235
  "",
232
236
  ` ${command}`,
233
237
  "",
@@ -238,9 +242,80 @@ function buildDefaultBountyIMSystemPrompt(input) {
238
242
  ].join(`
239
243
  `);
240
244
  }
245
+ function translateImServerUrlToHttpApi(imServerUrl) {
246
+ const httpScheme = imServerUrl.startsWith("wss://") ? "https://" : "http://";
247
+ return imServerUrl.replace(/^wss?:\/\//, httpScheme).replace(/\/ws$/, "");
248
+ }
249
+ function resolveCanonicalToEmail(canonical, profileEmail) {
250
+ if (!canonical)
251
+ return null;
252
+ const trimmed = canonical.trim();
253
+ if (!trimmed)
254
+ return null;
255
+ const UUID_HOST = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}@(.+)$/i;
256
+ const match = trimmed.match(UUID_HOST);
257
+ if (match) {
258
+ const host = match[1];
259
+ if (host === "authenticated") {
260
+ return profileEmail?.trim() || null;
261
+ }
262
+ return null;
263
+ }
264
+ if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmed)) {
265
+ return trimmed;
266
+ }
267
+ return null;
268
+ }
241
269
  function resolveBountyIMSystemPrompt(input) {
242
270
  return input.configSystemPrompt || buildDefaultBountyIMSystemPrompt(input);
243
271
  }
272
+ function isSelfEcho(msg, currentEmail) {
273
+ if (!msg || typeof msg !== "object")
274
+ return false;
275
+ const m = msg;
276
+ const fromEmailRaw = typeof m.fromEmail === "string" ? m.fromEmail.trim() : "";
277
+ const currentTrim = typeof currentEmail === "string" ? currentEmail.trim() : "";
278
+ if (fromEmailRaw && currentTrim) {
279
+ return fromEmailRaw.toLowerCase() === currentTrim.toLowerCase();
280
+ }
281
+ const fromAddr = typeof m.from === "string" ? m.from : undefined;
282
+ const toAddr = typeof m.to === "string" ? m.to : undefined;
283
+ if (fromAddr && toAddr) {
284
+ const fromLocal = fromAddr.split("@")[0]?.trim();
285
+ const toLocal = toAddr.split("@")[0]?.trim();
286
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
287
+ if (fromLocal && toLocal && UUID_RE.test(fromLocal) && UUID_RE.test(toLocal)) {
288
+ return fromLocal.toLowerCase() === toLocal.toLowerCase();
289
+ }
290
+ }
291
+ return false;
292
+ }
293
+ function isWrongAddress(msg, currentEmail) {
294
+ if (!msg || typeof msg !== "object")
295
+ return false;
296
+ const m = msg;
297
+ const toAddr = typeof m.to === "string" ? m.to.trim() : "";
298
+ if (!toAddr)
299
+ return false;
300
+ const currentTrim = typeof currentEmail === "string" ? currentEmail.trim() : "";
301
+ if (!currentTrim)
302
+ return false;
303
+ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
304
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
305
+ const toLocal = toAddr.split("@")[0] ?? "";
306
+ const currentLocal = currentTrim.split("@")[0] ?? "";
307
+ const toIsEmail = EMAIL_RE.test(toAddr) && !UUID_RE.test(toLocal);
308
+ const currentIsEmail = EMAIL_RE.test(currentTrim) && !UUID_RE.test(currentLocal);
309
+ const toIsUuid = UUID_RE.test(toLocal);
310
+ const currentIsUuid = UUID_RE.test(currentLocal);
311
+ if (toIsEmail && currentIsEmail) {
312
+ return toAddr.toLowerCase() !== currentTrim.toLowerCase();
313
+ }
314
+ if (toIsUuid && currentIsUuid) {
315
+ return toLocal.toLowerCase() !== currentLocal.toLowerCase();
316
+ }
317
+ return false;
318
+ }
244
319
  function shouldWriteBunTlsSkipEnv(tlsSkipVerify, isBunRuntimeOverride) {
245
320
  const isBun = isBunRuntimeOverride ?? typeof Bun !== "undefined";
246
321
  return tlsSkipVerify === true && isBun;
@@ -256,18 +331,17 @@ class BountyIMInstance {
256
331
  this.config = config;
257
332
  }
258
333
  getCurrentIdentity() {
259
- const { email, address } = readBountyIMConfig(this.config);
260
- return { email, address };
334
+ const { email } = readBountyIMConfig(this.config);
335
+ return { email };
261
336
  }
262
337
  getCurrentAddress() {
263
- const { email, address } = readBountyIMConfig(this.config);
264
- return address || email || "unknown";
338
+ const { email } = readBountyIMConfig(this.config);
339
+ return email || "unknown";
265
340
  }
266
341
  getCurrentSystemPrompt() {
267
- const { email, address, imServerUrl } = readBountyIMConfig(this.config);
342
+ const { email, imServerUrl } = readBountyIMConfig(this.config);
268
343
  return resolveBountyIMSystemPrompt({
269
344
  configSystemPrompt: this.config.systemPrompt,
270
- currentAddress: address,
271
345
  currentEmail: email,
272
346
  imServerUrl
273
347
  });
@@ -279,15 +353,14 @@ class BountyIMInstance {
279
353
  if (this.status === "running")
280
354
  return;
281
355
  this.setStatus("starting");
282
- const { email, address, imServerUrl } = readBountyIMConfig(this.config);
356
+ assertNoLegacyAddressField(this.config);
357
+ const { email, imServerUrl } = readBountyIMConfig(this.config);
283
358
  if (!imServerUrl) {
284
359
  throw new Error("imServerUrl is required for bounty-im event source");
285
360
  }
286
361
  const wsUrl = new URL(imServerUrl);
287
362
  if (email) {
288
363
  wsUrl.searchParams.set("email", email);
289
- } else if (address) {
290
- wsUrl.searchParams.set("address", address);
291
364
  }
292
365
  console.log(`[BountyIM] Connecting to ${wsUrl.toString()}...`);
293
366
  try {
@@ -302,7 +375,7 @@ class BountyIMInstance {
302
375
  rejectUnauthorized: !tlsSkipVerify
303
376
  });
304
377
  this.ws.on("open", () => {
305
- console.log(`[BountyIM] Connected${address ? ` as ${address}` : ""}`);
378
+ console.log(`[BountyIM] Connected${email ? ` as ${email}` : ""}`);
306
379
  this.setStatus("running");
307
380
  });
308
381
  this.ws.on("message", (data) => {
@@ -340,6 +413,15 @@ class BountyIMInstance {
340
413
  setStatus(status) {
341
414
  this.status = status;
342
415
  }
416
+ sendAck(messageId) {
417
+ if (!messageId || !this.ws)
418
+ return;
419
+ try {
420
+ this.ws.send(JSON.stringify({ event: "ack", data: { messageIds: [messageId] } }));
421
+ } catch (ackErr) {
422
+ console.error(`[BountyIM] 发送 ACK 失败:`, ackErr);
423
+ }
424
+ }
343
425
  handleMessage(data) {
344
426
  this.buffer += data;
345
427
  try {
@@ -366,28 +448,42 @@ class BountyIMInstance {
366
448
  }
367
449
  const eventType = `bounty-im.${evt.event || "message"}`;
368
450
  const fromAddress = msg.from || "unknown";
369
- const currentAddress = this.getCurrentAddress();
370
- const currentIdentity = this.getCurrentIdentity();
371
- const currentEmail = currentIdentity.email;
372
- const toAddress = msg.to || currentAddress;
373
- const identityMatches = currentEmail ? msg.to === currentEmail || msg.to === currentAddress : msg.to === currentAddress;
374
- if (msg.to && !identityMatches) {
375
- console.warn(`[BountyIM] Warning: message.to (${msg.to}) !== current identity (${currentEmail || currentAddress})`);
451
+ const currentEmail = this.getCurrentIdentity().email || "unknown";
452
+ const toAddress = msg.to || currentEmail;
453
+ if (isSelfEcho(msg, currentEmail)) {
454
+ console.log(`[BountyIM] Skipped self-echo: from=${msg.from ?? "?"} to=${msg.to ?? "?"}`);
455
+ this.sendAck(msg.id);
456
+ return;
457
+ }
458
+ if (isWrongAddress(msg, currentEmail)) {
459
+ console.warn(`[BountyIM] Skipped wrong-address event: to=${msg.to ?? "?"} currentEmail=${currentEmail}`);
460
+ this.sendAck(msg.id);
461
+ return;
462
+ }
463
+ if (msg.to && msg.to !== currentEmail) {
464
+ console.warn(`[BountyIM] Warning: message.to (${msg.to}) !== current email (${currentEmail})`);
376
465
  }
377
466
  const msgContent = msg.content;
378
467
  const content = msgContent?.type === "text" ? String(msgContent.body || "") : "";
379
468
  const { imServerUrl, email } = readBountyIMConfig(this.config);
380
469
  const agent = this.config.handleRule?.agent;
470
+ const fromEmailRaw = msg.fromEmail;
471
+ const fromEmailResolved = resolveCanonicalToEmail(fromAddress, email);
472
+ const senderEmail = typeof fromEmailRaw === "string" && fromEmailRaw.trim() !== "" && fromEmailRaw.trim() || fromEmailResolved || fromAddress;
381
473
  const metadata = {
382
474
  eventType,
383
475
  senderId: fromAddress,
476
+ senderEmail,
384
477
  chatId: toAddress,
385
478
  agent
386
479
  };
387
- const replyCommandHint = email ? `bounty com send --server-url ${imServerUrl} --from-email ${email} --to-email <recipient-email> --body "..."` : `bounty com send -f ${toAddress} -t ${fromAddress} -b "回复内容"`;
388
- const inlineReplyHint = email ? `bounty com send --server-url ${imServerUrl} --from-email ${email} --to-email ${fromAddress} --body "回复内容"` : `bounty com send -f ${toAddress} -t ${fromAddress} -b "回复内容"`;
480
+ const httpApiUrl = imServerUrl ? translateImServerUrlToHttpApi(imServerUrl) : "<your-server-url>";
481
+ const fromEmailForCmd = email || "<your-registered-email>";
482
+ const toEmailForCmd = senderEmail !== fromAddress ? senderEmail : "<recipient-registered-email>";
483
+ const replyCommandHint = `bounty com send --server-url ${httpApiUrl} --from-email ${fromEmailForCmd} --to-email ${toEmailForCmd} --body "..."`;
484
+ const inlineReplyHint = `bounty com send --server-url ${httpApiUrl} --from-email ${fromEmailForCmd} --to-email ${toEmailForCmd} --body "回复内容"`;
389
485
  let recommendedAction;
390
- if (evt.event === "message") {
486
+ if (evt.event === "message" && fromAddress !== toAddress) {
391
487
  recommendedAction = {
392
488
  action: `处理消息并通过 bounty com send 回复发件人。使用格式:${replyCommandHint}`,
393
489
  replyTo: {
@@ -404,7 +500,8 @@ class BountyIMInstance {
404
500
  imServerUrl
405
501
  }
406
502
  };
407
- const displayMessage = content ? `[From ${fromAddress}] ${content}
503
+ const displayFrom = senderEmail;
504
+ const displayMessage = content ? `[From ${displayFrom}] ${content}
408
505
 
409
506
  \uD83D\uDCA1 回复: ${inlineReplyHint}` : this.formatMessage(rawEvent);
410
507
  const event = {
@@ -430,18 +527,10 @@ class BountyIMInstance {
430
527
  }
431
528
  };
432
529
  this.eventHandler?.(event);
433
- if (msg.id && this.ws) {
434
- try {
435
- const ackPayload = JSON.stringify({
436
- event: "ack",
437
- data: { messageIds: [msg.id] }
438
- });
439
- this.ws.send(ackPayload);
440
- console.log(`[BountyIM] 已发送 ACK for message: ${msg.id}`);
441
- } catch (ackErr) {
442
- console.error(`[BountyIM] 发送 ACK 失败:`, ackErr);
443
- }
530
+ if (msg.id) {
531
+ console.log(`[BountyIM] 已发送 ACK for message: ${msg.id}`);
444
532
  }
533
+ this.sendAck(msg.id);
445
534
  } catch (err) {
446
535
  console.error(`[BountyIM] Error processing message:`, err);
447
536
  }
@@ -471,20 +560,20 @@ var bountyIMHandler = {
471
560
  errors.push("EventSource ID is required");
472
561
  if (!config.name)
473
562
  errors.push("EventSource name is required");
474
- const { address, imServerUrl, email } = readBountyIMConfig(config);
475
- if (!email && !address) {
476
- errors.push("Bounty IM email or address is required (top-level email/address or options.email/address)");
563
+ try {
564
+ assertNoLegacyAddressField(config);
565
+ } catch (err) {
566
+ errors.push(err instanceof Error ? err.message : String(err));
567
+ }
568
+ const { imServerUrl, email } = readBountyIMConfig(config);
569
+ if (!email) {
570
+ errors.push("Bounty IM email is required (v0.14 strict email-only; top-level email or options.email)");
477
571
  }
478
572
  if (email !== undefined && email !== "") {
479
573
  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
480
574
  errors.push("Bounty IM email format invalid (expected: user@domain.tld)");
481
575
  }
482
576
  }
483
- if (address !== undefined && address !== "") {
484
- if (!/^[\w-]+@[\w.-]+$/.test(address)) {
485
- errors.push("Bounty IM address format invalid (expected: agent-id@host)");
486
- }
487
- }
488
577
  if (!imServerUrl) {
489
578
  errors.push("Bounty IM imServerUrl is required (top-level imServerUrl or options.imServerUrl)");
490
579
  } else if (!imServerUrl.startsWith("ws://") && !imServerUrl.startsWith("wss://")) {
@@ -568,7 +657,7 @@ function extractMetadata(rawEvent, eventType) {
568
657
  const profileFlag = profile2 ? `--profile ${profile2} ` : "";
569
658
  const profileHint = profile2 ? `(⚠️ 必须使用 profile="${profile2}" 调用 lark-cli,否则会因 openId 跨 app 失败)` : "";
570
659
  recommendedAction = {
571
- action: `处理飞书消息并以机器人身份回复${profileHint},例如:lark-cli ${profileFlag}im +messages-reply --message-id "xxxxid" --as bot --text "回复内容"`,
660
+ action: `处理飞书消息并以机器人身份回复${profileHint},例如:lark-cli ${profileFlag}im +messages-reply --message-id "xxxxid" --as bot --markdown "Markdown 格式回复内容"`,
572
661
  replyTo: {
573
662
  appId: metadata.appId,
574
663
  profile: profile2,
@@ -613,6 +613,7 @@ function createWorkflowSearchTool(workflowService) {
613
613
 
614
614
  // src/env/workflow/tools/run-workflow.ts
615
615
  init_logger();
616
+ init_decorator();
616
617
  import { z as z8 } from "zod";
617
618
  var logger7 = createLogger("run-workflow-tool");
618
619
  function synthFallbackRunId(now = Date.now()) {
@@ -625,6 +626,24 @@ function attemptStopOnTimeout(workflowService, runId, reason) {
625
626
  logger7.warn(`Failed to stop workflow ${runId} after timeout: ${stopErr instanceof Error ? stopErr.message : String(stopErr)}`);
626
627
  });
627
628
  }
629
+ function buildErrorReturn(args) {
630
+ const { errorRunId, status, errorMessage, durationMs } = args;
631
+ const errorWithRunId = `${errorMessage} (runId: ${errorRunId})`;
632
+ return {
633
+ success: false,
634
+ output: {
635
+ run_id: errorRunId,
636
+ status,
637
+ error: errorWithRunId,
638
+ duration_ms: durationMs
639
+ },
640
+ error: errorWithRunId,
641
+ metadata: {
642
+ execution_time_ms: durationMs,
643
+ run_id: errorRunId
644
+ }
645
+ };
646
+ }
628
647
  var RunWorkflowInputSchema = z8.object({
629
648
  workflow_name: z8.string().describe("Name of the workflow to run"),
630
649
  input: z8.record(z8.any()).optional().describe("Input to pass to the workflow"),
@@ -632,8 +651,24 @@ var RunWorkflowInputSchema = z8.object({
632
651
  node_config: z8.record(z8.string(), z8.record(z8.string(), z8.any())).optional().describe("Per-node runtime config overrides keyed by node id (Task #1974). " + "Shallow-merged into each node's effective config; input wins over nodeDef.config."),
633
652
  session: z8.string().regex(/^workflow_/, { message: "session must start with 'workflow_'" }).optional().describe("Existing session ID (workflow_xxx) to resume from. Mutually exclusive with fresh `input` runs.")
634
653
  }).strict();
654
+
655
+ class RunWorkflowToolRunner {
656
+ executeImpl;
657
+ constructor(executeImpl) {
658
+ this.executeImpl = executeImpl;
659
+ }
660
+ async execute(args, ctx) {
661
+ return this.executeImpl(args, ctx);
662
+ }
663
+ }
664
+ __legacyDecorateClassTS([
665
+ TracedAs("workflow.run-workflow-tool.execute", {
666
+ recordParams: true,
667
+ recordResult: true
668
+ })
669
+ ], RunWorkflowToolRunner.prototype, "execute", null);
635
670
  function createRunWorkflowTool(workflowService) {
636
- return {
671
+ const tool = {
637
672
  name: "workflow_run",
638
673
  description: "Run a workflow by name with optional input, OR resume an existing workflow run via the `session` field (the runId itself acts as session ID, both have `workflow_` prefix natively — pass the workflow run's runId directly). Returns run_id (== session_id, ALWAYS populated — even on timeout/abort/error paths), status, output, error, and duration_ms. Default timeout: 30 minutes.",
639
674
  parameters: RunWorkflowInputSchema,
@@ -738,57 +773,42 @@ function createRunWorkflowTool(workflowService) {
738
773
  const errorMessage = error instanceof Error ? error.message : String(error);
739
774
  const errorRunId = capturedRunId ?? reservedRunId;
740
775
  if (errorMessage.includes("Workflow not found")) {
741
- return {
742
- success: false,
743
- output: {
744
- run_id: errorRunId,
745
- status: "failed",
746
- error: `Workflow not found: ${workflow_name}`,
747
- duration_ms: durationMs
748
- },
749
- error: `Workflow not found: ${workflow_name}`,
750
- metadata: {
751
- execution_time_ms: durationMs,
752
- run_id: errorRunId
753
- }
754
- };
776
+ return buildErrorReturn({
777
+ errorRunId,
778
+ status: "failed",
779
+ errorMessage: `Workflow not found: ${workflow_name}`,
780
+ durationMs
781
+ });
755
782
  }
756
- if (errorMessage.includes("abort") || errorMessage.includes("timed out")) {
757
- return {
758
- success: false,
759
- output: {
760
- run_id: errorRunId,
761
- status: "timeout",
762
- error: `Workflow execution timed out or was aborted: ${workflow_name}`,
763
- duration_ms: durationMs
764
- },
765
- error: `Workflow execution timed out or was aborted: ${workflow_name}`,
766
- metadata: {
767
- execution_time_ms: durationMs,
768
- run_id: errorRunId
769
- }
770
- };
783
+ const isTimeoutLike = errorMessage.includes("abort") || errorMessage.includes("timed out") || errorMessage.includes("execution timeout:");
784
+ if (isTimeoutLike) {
785
+ if (!timedOut) {
786
+ attemptStopOnTimeout(workflowService, errorRunId, "timed out");
787
+ }
788
+ return buildErrorReturn({
789
+ errorRunId,
790
+ status: "timeout",
791
+ errorMessage: `Workflow execution timed out or was aborted: ${workflow_name}`,
792
+ durationMs
793
+ });
771
794
  }
772
795
  if (logger7?.error) {
773
796
  logger7.error(`Failed to run workflow: ${workflow_name}`, { error: errorMessage });
774
797
  }
775
- return {
776
- success: false,
777
- output: {
778
- run_id: errorRunId,
779
- status: "failed",
780
- error: `Failed to run workflow ${workflow_name}: ${errorMessage}`,
781
- duration_ms: durationMs
782
- },
783
- error: `Failed to run workflow ${workflow_name}: ${errorMessage}`,
784
- metadata: {
785
- execution_time_ms: durationMs,
786
- run_id: errorRunId
787
- }
788
- };
798
+ return buildErrorReturn({
799
+ errorRunId,
800
+ status: "failed",
801
+ errorMessage: `Failed to run workflow ${workflow_name}: ${errorMessage}`,
802
+ durationMs
803
+ });
789
804
  }
790
805
  }
791
806
  };
807
+ const runner = new RunWorkflowToolRunner(tool.execute);
808
+ return {
809
+ ...tool,
810
+ execute: runner.execute.bind(runner)
811
+ };
792
812
  }
793
813
  var _runWorkflowTool = null;
794
814
  var _workflowService = null;
@@ -6,7 +6,7 @@ import {
6
6
  WorkflowEngine,
7
7
  exports_engine,
8
8
  init_engine
9
- } from "./roy-agent-core-4y3hdqw2.js";
9
+ } from "./roy-agent-core-39rvx3fw.js";
10
10
  import {
11
11
  askUserTool,
12
12
  createRunWorkflowTool,
@@ -18,7 +18,7 @@ import {
18
18
  createWorkflowSearchTool,
19
19
  createWorkflowTagListTool,
20
20
  createWorkflowValidateTool
21
- } from "./roy-agent-core-smmr6wr3.js";
21
+ } from "./roy-agent-core-ka4b12eg.js";
22
22
  import {
23
23
  WorkflowService
24
24
  } from "./roy-agent-core-b75jtybq.js";
@@ -98,10 +98,10 @@ function createTaskTool(taskComponent) {
98
98
  description: `
99
99
  Create a new task for tracking work.
100
100
 
101
- ## ⚠️ CALL task_tree(depth=2) BEFORE THIS TOOL
101
+ ## ⚠️ CALL task_tree(depth=1) BEFORE THIS TOOL
102
102
 
103
103
  Before calling \`task_create\`, you **MUST** first call
104
- \`task_tree(depth=2)\` to inspect the existing task hierarchy.
104
+ \`task_tree(depth=1)\` to inspect the existing task hierarchy.
105
105
  This is critical because:
106
106
 
107
107
  1. Avoid duplicating root tasks (root tasks should stay ≤ 10).
@@ -109,7 +109,7 @@ function createTaskTool(taskComponent) {
109
109
  3. Avoid creating stranded/orphan tasks.
110
110
 
111
111
  Workflow:
112
- step 1: task_tree({depth: 2})
112
+ step 1: task_tree({depth: 1})
113
113
  step 2: read the tree, then decide per "Decision Tree" below
114
114
  step 3: task_create({...})
115
115
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-setting/roy-agent-core",
3
- "version": "1.6.6",
3
+ "version": "1.6.7",
4
4
  "type": "module",
5
5
  "description": "Core SDK for roy-agent - Environment, Components, Tools, Sessions, Tasks",
6
6
  "main": "./dist/index.js",