@ai-setting/roy-agent-core 1.6.4 → 1.6.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/dist/env/agent/index.js +3 -3
- package/dist/env/event-source/index.js +3 -3
- package/dist/env/index.js +15 -15
- package/dist/env/llm/index.js +2 -2
- package/dist/env/plugin/index.js +1 -1
- package/dist/env/prompt/index.js +2 -2
- package/dist/env/task/delegate/index.js +2 -2
- package/dist/env/task/index.js +3 -3
- package/dist/env/task/plugins/index.js +2 -2
- package/dist/env/tool/built-in/index.js +1 -1
- package/dist/env/tool/index.js +2 -2
- package/dist/env/workflow/engine/index.js +3 -3
- package/dist/env/workflow/index.js +5 -5
- package/dist/env/workflow/nodes/index.js +6 -2
- package/dist/env/workflow/tools/index.js +1 -1
- package/dist/index.js +18 -18
- package/dist/shared/@ai-setting/{roy-agent-core-ba6243hr.js → roy-agent-core-0tfv18rf.js} +175 -1
- package/dist/shared/@ai-setting/{roy-agent-core-hd5xrr2q.js → roy-agent-core-12ttd2w1.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-z7dxedn6.js → roy-agent-core-2r1rc0fe.js} +12 -2
- package/dist/shared/@ai-setting/{roy-agent-core-xxfkvqqh.js → roy-agent-core-34xt19yg.js} +8 -7
- package/dist/shared/@ai-setting/{roy-agent-core-z9m38ytb.js → roy-agent-core-4extx33r.js} +2 -3
- package/dist/shared/@ai-setting/{roy-agent-core-kf3mw79k.js → roy-agent-core-4y3hdqw2.js} +20 -8
- package/dist/shared/@ai-setting/{roy-agent-core-y1m7c2v7.js → roy-agent-core-8jmkghjc.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-g7hfkszj.js → roy-agent-core-971gwby7.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-tyqzn10b.js → roy-agent-core-a5rde2ky.js} +3 -2
- package/dist/shared/@ai-setting/{roy-agent-core-2xpstxhz.js → roy-agent-core-b9bnm4mj.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-7afcdb2m.js → roy-agent-core-c94yan0b.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-65qs21kf.js → roy-agent-core-dcd1s7ct.js} +4 -1
- package/dist/shared/@ai-setting/{roy-agent-core-r3209bcd.js → roy-agent-core-gw43m8yd.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-aa0tdfb2.js → roy-agent-core-jayzyg7h.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-bferdaw6.js → roy-agent-core-mzhsk0jb.js} +58 -26
- package/dist/shared/@ai-setting/{roy-agent-core-155408xq.js → roy-agent-core-r08qk37k.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-xnga0ksx.js → roy-agent-core-smmr6wr3.js} +43 -40
- package/dist/shared/@ai-setting/{roy-agent-core-vf72n6qn.js → roy-agent-core-w7mhnc4c.js} +22 -4
- package/package.json +1 -1
- /package/dist/shared/@ai-setting/{roy-agent-core-6kygfd9x.js → roy-agent-core-02n40zbs.js} +0 -0
|
@@ -234,6 +234,9 @@ class PluginComponent extends BaseComponent {
|
|
|
234
234
|
return this.registry.has(name);
|
|
235
235
|
}
|
|
236
236
|
getConfig(name) {
|
|
237
|
+
if (name === undefined) {
|
|
238
|
+
return super.getConfig();
|
|
239
|
+
}
|
|
237
240
|
return this.configComponent?.get(`plugin.${name}`);
|
|
238
241
|
}
|
|
239
242
|
async registerAll(plugins) {
|
|
@@ -299,7 +302,12 @@ class PluginComponent extends BaseComponent {
|
|
|
299
302
|
registerTool(tool) {
|
|
300
303
|
const toolComponent = self.env?.getComponent("tool");
|
|
301
304
|
if (toolComponent) {
|
|
302
|
-
toolComponent.register(
|
|
305
|
+
toolComponent.register({
|
|
306
|
+
name: tool.name,
|
|
307
|
+
description: tool.description,
|
|
308
|
+
parameters: tool.parameters,
|
|
309
|
+
execute: async (args) => tool.handler(args)
|
|
310
|
+
});
|
|
303
311
|
self.logger.debug(`Registered tool: ${tool.name} (for plugin: ${plugin.name})`);
|
|
304
312
|
} else {
|
|
305
313
|
self.logger.warn(`Cannot register tool ${tool.name}: ToolComponent not available`);
|
|
@@ -309,7 +317,9 @@ class PluginComponent extends BaseComponent {
|
|
|
309
317
|
globalHookManager.register(hook.point, {
|
|
310
318
|
name: `${plugin.name}:${hook.point}`,
|
|
311
319
|
priority: hook.priority ?? plugin.priority,
|
|
312
|
-
execute:
|
|
320
|
+
execute: async (ctx) => {
|
|
321
|
+
await hook.handler(ctx);
|
|
322
|
+
}
|
|
313
323
|
});
|
|
314
324
|
self.logger.debug(`Registered hook: ${hook.point} (for plugin: ${plugin.name})`);
|
|
315
325
|
},
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
withTimeout
|
|
3
|
-
} from "./roy-agent-core-
|
|
3
|
+
} from "./roy-agent-core-dcd1s7ct.js";
|
|
4
4
|
import {
|
|
5
5
|
truncateOutputInline
|
|
6
|
-
} from "./roy-agent-core-
|
|
6
|
+
} from "./roy-agent-core-02n40zbs.js";
|
|
7
7
|
import {
|
|
8
8
|
AskUserError,
|
|
9
9
|
init_workflow_hil
|
|
@@ -672,7 +672,7 @@ class AgentComponent extends BaseComponent {
|
|
|
672
672
|
agentType: agent.config.type,
|
|
673
673
|
model: context?.model ?? agent.config.model,
|
|
674
674
|
traceId: context?.metadata?.traceId ?? context?.traceId,
|
|
675
|
-
abort: abortController.signal
|
|
675
|
+
abort: context?.abort ? AbortSignal.any([abortController.signal, context.abort]) : abortController.signal
|
|
676
676
|
};
|
|
677
677
|
const result = {
|
|
678
678
|
iterations: 0,
|
|
@@ -1405,13 +1405,14 @@ ${additionInfo}`
|
|
|
1405
1405
|
if (!sessionId) {
|
|
1406
1406
|
return;
|
|
1407
1407
|
}
|
|
1408
|
+
let filtered;
|
|
1408
1409
|
try {
|
|
1409
1410
|
const sessionComponent = this.env.getComponent("session");
|
|
1410
1411
|
if (!sessionComponent) {
|
|
1411
1412
|
logger.warn("SessionComponent not found, skipping session recording");
|
|
1412
1413
|
return;
|
|
1413
1414
|
}
|
|
1414
|
-
|
|
1415
|
+
filtered = [];
|
|
1415
1416
|
for (const msg of allMessages) {
|
|
1416
1417
|
if (msg.role === "system") {
|
|
1417
1418
|
continue;
|
|
@@ -1424,12 +1425,12 @@ ${additionInfo}`
|
|
|
1424
1425
|
continue;
|
|
1425
1426
|
}
|
|
1426
1427
|
}
|
|
1427
|
-
|
|
1428
|
+
filtered.push(this.messageConverter.fromModelMessage(msg, { sessionID: sessionId }));
|
|
1428
1429
|
}
|
|
1429
|
-
if (
|
|
1430
|
+
if (filtered.length === 0) {
|
|
1430
1431
|
return;
|
|
1431
1432
|
}
|
|
1432
|
-
await sessionComponent.addMessages(sessionId,
|
|
1433
|
+
await sessionComponent.addMessages(sessionId, filtered);
|
|
1433
1434
|
} catch (err) {
|
|
1434
1435
|
const kind = err && typeof err === "object" && "kind" in err ? err.kind : undefined;
|
|
1435
1436
|
if (kind === "lock_exhausted") {
|
|
@@ -530,7 +530,7 @@ roy-agent workflow list|add|search|get|tag|validate|update|remove|run|pause|resu
|
|
|
530
530
|
| \`workflow get <name>\` | Get workflow definition details. |
|
|
531
531
|
| \`workflow tag list [--sort-by name/usage_count/created_at] [--order desc/asc]\` | List all available tags with usage_count. \`\`\` |
|
|
532
532
|
| \`workflow validate --file <path>\` | Validate a workflow YAML/JSON before adding. Always run this BEFORE \`workflow add\`. |
|
|
533
|
-
| \`workflow run <name> [--input JSON]
|
|
533
|
+
| \`workflow run <name> [--input JSON]\` | Run a workflow. |
|
|
534
534
|
| \`workflow status <run-id>\` | Check workflow run status. |
|
|
535
535
|
| \`workflow pause/resume/stop <run-id>\` | Control workflow execution. |
|
|
536
536
|
| \`workflow update <id> [--tags] [--description]\` | Update workflow metadata. |
|
|
@@ -1022,7 +1022,7 @@ When reusing an existing task, you MUST follow these rules:
|
|
|
1022
1022
|
- 返回值:workflow 定义(名称、版本、描述、入参 inputs schema、节点列表),或 run 的状态
|
|
1023
1023
|
|
|
1024
1024
|
3. **\`workflow_run\`** — 运行 workflow
|
|
1025
|
-
- 参数:\`workflow_name\`(必填),\`input\`(可选 JSON),\`
|
|
1025
|
+
- 参数:\`workflow_name\`(必填),\`input\`(可选 JSON),\`timeout\`(可选),\`session\`(resume 用,传 runId 即可),\`node_config\`(per-node 覆盖,Task #1974,JSON 对象 { "<nodeId>": { timeout: 5000 } })
|
|
1026
1026
|
- 返回值:run_id, status, output, error, duration_ms
|
|
1027
1027
|
|
|
1028
1028
|
4. **\`workflow_run_status\`** — 查询 run 状态
|
|
@@ -1170,7 +1170,6 @@ plan/execute/verify 三阶段已完成的会跳过,未完成的会接上。
|
|
|
1170
1170
|
| \`workflow_run\` 返回 \`status="failed"\` + error 含 "timeout" | stop → resume(同 session) |
|
|
1171
1171
|
| \`workflow_run\` 返回 \`status="failed"\` + error 是业务错误(如校验失败) | **不** resume,原样返回给上游 |
|
|
1172
1172
|
| \`workflow_run\` 返回 \`status="paused"\`(ask_user 中断) | 用 \`session\` resume + 用户 response |
|
|
1173
|
-
| \`workflow_run\` 返回 \`status="running"\` 但实际卡死很久 | 先 \`workflow_run_status\` 确认;仍是 running 则 stop → resume |
|
|
1174
1173
|
| \`workflow_run\` 抛异常(非 status=failed,是 throw) | stop → resume;resume 仍失败则开新 run |
|
|
1175
1174
|
|
|
1176
1175
|
记住:**stop + resume 是默认动作**,不是例外。
|
|
@@ -7,19 +7,21 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
AgentComponentAdapter,
|
|
9
9
|
init_agent_component_adapter
|
|
10
|
-
} from "./roy-agent-core-
|
|
10
|
+
} from "./roy-agent-core-w7mhnc4c.js";
|
|
11
11
|
import {
|
|
12
12
|
TemplateResolver,
|
|
13
13
|
init_template_resolver
|
|
14
14
|
} from "./roy-agent-core-q88vxmx5.js";
|
|
15
15
|
import {
|
|
16
|
+
PythonCallNode,
|
|
16
17
|
SkillNode,
|
|
17
18
|
ToolNode,
|
|
18
19
|
WorkflowNode,
|
|
20
|
+
init_python_call_node,
|
|
19
21
|
init_skill_node,
|
|
20
22
|
init_tool_node,
|
|
21
23
|
init_workflow_node
|
|
22
|
-
} from "./roy-agent-core-
|
|
24
|
+
} from "./roy-agent-core-0tfv18rf.js";
|
|
23
25
|
import {
|
|
24
26
|
WorkflowError,
|
|
25
27
|
createWorkflowEvent,
|
|
@@ -1297,6 +1299,9 @@ class NodeRegistry {
|
|
|
1297
1299
|
this.factories.set("ask_user", (definition) => {
|
|
1298
1300
|
return new AskUserNode(definition);
|
|
1299
1301
|
});
|
|
1302
|
+
this.factories.set("python_call", (definition) => {
|
|
1303
|
+
return new PythonCallNode(definition);
|
|
1304
|
+
});
|
|
1300
1305
|
}
|
|
1301
1306
|
register(type, factory) {
|
|
1302
1307
|
this.factories.set(type, factory);
|
|
@@ -1323,6 +1328,7 @@ var init_node_registry = __esm(() => {
|
|
|
1323
1328
|
init_agent_component_adapter();
|
|
1324
1329
|
init_workflow_node();
|
|
1325
1330
|
init_ask_user_node();
|
|
1331
|
+
init_python_call_node();
|
|
1326
1332
|
});
|
|
1327
1333
|
|
|
1328
1334
|
// src/env/workflow/utils/agent-session-metadata.ts
|
|
@@ -1395,7 +1401,16 @@ var init_engine = __esm(() => {
|
|
|
1395
1401
|
const definition = "definition" in workflow ? workflow.definition : workflow;
|
|
1396
1402
|
const workflowId = "id" in workflow ? workflow.id : `inline_${definition.name}`;
|
|
1397
1403
|
const workflowName = definition.name;
|
|
1398
|
-
|
|
1404
|
+
let runId;
|
|
1405
|
+
if (options?.runId) {
|
|
1406
|
+
const reserved = options.runId;
|
|
1407
|
+
if (typeof reserved !== "string" || !reserved.startsWith("workflow_")) {
|
|
1408
|
+
throw new Error(`[WorkflowEngine.createSession] reserved runId must start with 'workflow_'; got ${JSON.stringify(reserved)}`);
|
|
1409
|
+
}
|
|
1410
|
+
runId = reserved;
|
|
1411
|
+
} else {
|
|
1412
|
+
runId = this.generateRunId();
|
|
1413
|
+
}
|
|
1399
1414
|
const sessionId = this.getSessionId(runId);
|
|
1400
1415
|
const metadata = {
|
|
1401
1416
|
type: "workflow",
|
|
@@ -1642,11 +1657,8 @@ var init_engine = __esm(() => {
|
|
|
1642
1657
|
logger3.error(`Workflow ${sessionId} scheduling error:`, error);
|
|
1643
1658
|
this.failWorkflow(sessionState, error);
|
|
1644
1659
|
});
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
return this.waitForCompletion(sessionId, wfTimeout);
|
|
1648
|
-
}
|
|
1649
|
-
return { runId, status: "running" };
|
|
1660
|
+
const wfTimeout = options?.timeout ?? sessionState.config.timeout ?? undefined;
|
|
1661
|
+
return this.waitForCompletion(sessionId, wfTimeout);
|
|
1650
1662
|
}
|
|
1651
1663
|
async runWorkflow(workflow, options) {
|
|
1652
1664
|
const definition = "definition" in workflow ? workflow.definition : workflow;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AgentComponentAdapter,
|
|
3
3
|
init_agent_component_adapter
|
|
4
|
-
} from "./roy-agent-core-
|
|
4
|
+
} from "./roy-agent-core-w7mhnc4c.js";
|
|
5
5
|
import"./roy-agent-core-1db4vpc6.js";
|
|
6
6
|
import"./roy-agent-core-e25xkv53.js";
|
|
7
7
|
import"./roy-agent-core-gp872e7m.js";
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
BackgroundTaskManager,
|
|
9
9
|
createDelegateTool,
|
|
10
10
|
createStopTool
|
|
11
|
-
} from "./roy-agent-core-
|
|
11
|
+
} from "./roy-agent-core-c94yan0b.js";
|
|
12
12
|
import {
|
|
13
13
|
SQLiteTaskStore,
|
|
14
14
|
getDefaultTaskDbPath
|
|
@@ -148,7 +148,8 @@ class DefaultTagService {
|
|
|
148
148
|
return this.store.searchTasks(query, limit);
|
|
149
149
|
}
|
|
150
150
|
async searchTasksByKeywords(keywords, options) {
|
|
151
|
-
|
|
151
|
+
const result = await this.store.searchTasksByKeywords(keywords, options);
|
|
152
|
+
return result.tasks;
|
|
152
153
|
}
|
|
153
154
|
async findSimilarTasksByKeywords(keywords, options) {
|
|
154
155
|
return this.store.findSimilarTasksByKeywords(keywords, options);
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
WorkflowEngine,
|
|
7
7
|
exports_engine,
|
|
8
8
|
init_engine
|
|
9
|
-
} from "./roy-agent-core-
|
|
9
|
+
} from "./roy-agent-core-4y3hdqw2.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-
|
|
21
|
+
} from "./roy-agent-core-smmr6wr3.js";
|
|
22
22
|
import {
|
|
23
23
|
WorkflowService
|
|
24
24
|
} from "./roy-agent-core-b75jtybq.js";
|
|
@@ -141,7 +141,7 @@ class WorkflowComponent extends BaseComponent {
|
|
|
141
141
|
if (!agentRunner && this._workflowEnv) {
|
|
142
142
|
const agentComponent = this._workflowEnv.getComponent("agent");
|
|
143
143
|
if (agentComponent) {
|
|
144
|
-
const { AgentComponentAdapter } = await import("./roy-agent-core-
|
|
144
|
+
const { AgentComponentAdapter } = await import("./roy-agent-core-8jmkghjc.js");
|
|
145
145
|
agentRunner = new AgentComponentAdapter(agentComponent, {}, this.sessionComponent);
|
|
146
146
|
}
|
|
147
147
|
}
|
|
@@ -432,7 +432,10 @@ function processThinkingStream(textDelta, config, state) {
|
|
|
432
432
|
async function invoke(config, options, ctx) {
|
|
433
433
|
try {
|
|
434
434
|
const emitToEnv = createEnvEventEmitter(options.env, options.context);
|
|
435
|
-
logger.info("[invoke] Created event emitter
|
|
435
|
+
logger.info("[invoke] Created event emitter", {
|
|
436
|
+
envAvailable: !!options.env,
|
|
437
|
+
hasContext: options.context !== undefined
|
|
438
|
+
});
|
|
436
439
|
const { providerId, modelId } = parseModelString(options.model || config.model);
|
|
437
440
|
const provider = createProviderInstance(providerId, config.apiKey, config.baseURL);
|
|
438
441
|
if (!provider) {
|
|
@@ -73,7 +73,7 @@ var killTree = (proc, signal = "SIGKILL") => {
|
|
|
73
73
|
var makeBashSpawner = () => {
|
|
74
74
|
return {
|
|
75
75
|
run: (command, options) => {
|
|
76
|
-
return Effect.gen(function* () {
|
|
76
|
+
return Effect.scoped(Effect.gen(function* () {
|
|
77
77
|
const cwd = options?.cwd;
|
|
78
78
|
const timeout = options?.timeout ?? 60000;
|
|
79
79
|
const env = options?.env ?? {};
|
|
@@ -175,7 +175,7 @@ var makeBashSpawner = () => {
|
|
|
175
175
|
success: !timedOut && exitCode === 0,
|
|
176
176
|
timedOut
|
|
177
177
|
};
|
|
178
|
-
});
|
|
178
|
+
}));
|
|
179
179
|
}
|
|
180
180
|
};
|
|
181
181
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TaskTagPlugin,
|
|
3
3
|
createLarkCliTaskNotifyHook
|
|
4
|
-
} from "./roy-agent-core-
|
|
4
|
+
} from "./roy-agent-core-jayzyg7h.js";
|
|
5
5
|
import {
|
|
6
6
|
envKeyToConfigKey
|
|
7
7
|
} from "./roy-agent-core-qxhq8ven.js";
|
|
@@ -196,11 +196,14 @@ var timerHandler = {
|
|
|
196
196
|
function readBountyIMConfig(config) {
|
|
197
197
|
const topLevelAddress = config.address;
|
|
198
198
|
const topLevelUrl = config.imServerUrl;
|
|
199
|
+
const topLevelEmail = config.email;
|
|
199
200
|
const optionsAddress = config.options?.address;
|
|
200
201
|
const optionsUrl = config.options?.imServerUrl;
|
|
202
|
+
const optionsEmail = config.options?.email;
|
|
201
203
|
return {
|
|
202
204
|
address: topLevelAddress || optionsAddress,
|
|
203
|
-
imServerUrl: topLevelUrl || optionsUrl
|
|
205
|
+
imServerUrl: topLevelUrl || optionsUrl,
|
|
206
|
+
email: topLevelEmail || optionsEmail
|
|
204
207
|
};
|
|
205
208
|
}
|
|
206
209
|
function readBountyIMTlsSkipVerify(config) {
|
|
@@ -213,20 +216,25 @@ function buildDefaultBountyIMSystemPrompt(input) {
|
|
|
213
216
|
const server = input.imServerUrl || "ws://localhost:4005/ws";
|
|
214
217
|
const httpScheme = server.startsWith("wss://") ? "https://" : "http://";
|
|
215
218
|
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 "..."`;
|
|
216
224
|
return [
|
|
217
225
|
"你正在通过 Bounty IM 与其他 agent 通信。",
|
|
218
226
|
"",
|
|
219
|
-
`你的 IM
|
|
227
|
+
`你的 IM 身份:${identity}`,
|
|
220
228
|
`IM Server:${endpoint} (k8s remote server)`,
|
|
221
229
|
"",
|
|
222
|
-
"回复收到的消息时,**必须**使用以下命令格式(注意 --endpoint 不可省略,省略会默认连 localhost:4000 而失败):",
|
|
230
|
+
"回复收到的消息时,**必须**使用以下命令格式(注意 --server-url / --endpoint 不可省略,省略会默认连 localhost:4000 而失败):",
|
|
223
231
|
"",
|
|
224
|
-
`
|
|
232
|
+
` ${command}`,
|
|
225
233
|
"",
|
|
226
234
|
"如果遇到 TLS 错误(自签名证书),加 -k:",
|
|
227
|
-
|
|
235
|
+
tlsCommand,
|
|
228
236
|
"",
|
|
229
|
-
|
|
237
|
+
rule
|
|
230
238
|
].join(`
|
|
231
239
|
`);
|
|
232
240
|
}
|
|
@@ -247,15 +255,20 @@ class BountyIMInstance {
|
|
|
247
255
|
constructor(config) {
|
|
248
256
|
this.config = config;
|
|
249
257
|
}
|
|
258
|
+
getCurrentIdentity() {
|
|
259
|
+
const { email, address } = readBountyIMConfig(this.config);
|
|
260
|
+
return { email, address };
|
|
261
|
+
}
|
|
250
262
|
getCurrentAddress() {
|
|
251
|
-
const { address } = readBountyIMConfig(this.config);
|
|
252
|
-
return address || "unknown";
|
|
263
|
+
const { email, address } = readBountyIMConfig(this.config);
|
|
264
|
+
return address || email || "unknown";
|
|
253
265
|
}
|
|
254
266
|
getCurrentSystemPrompt() {
|
|
255
|
-
const imServerUrl = readBountyIMConfig(this.config)
|
|
267
|
+
const { email, address, imServerUrl } = readBountyIMConfig(this.config);
|
|
256
268
|
return resolveBountyIMSystemPrompt({
|
|
257
269
|
configSystemPrompt: this.config.systemPrompt,
|
|
258
|
-
currentAddress:
|
|
270
|
+
currentAddress: address,
|
|
271
|
+
currentEmail: email,
|
|
259
272
|
imServerUrl
|
|
260
273
|
});
|
|
261
274
|
}
|
|
@@ -266,12 +279,14 @@ class BountyIMInstance {
|
|
|
266
279
|
if (this.status === "running")
|
|
267
280
|
return;
|
|
268
281
|
this.setStatus("starting");
|
|
269
|
-
const { address, imServerUrl } = readBountyIMConfig(this.config);
|
|
282
|
+
const { email, address, imServerUrl } = readBountyIMConfig(this.config);
|
|
270
283
|
if (!imServerUrl) {
|
|
271
284
|
throw new Error("imServerUrl is required for bounty-im event source");
|
|
272
285
|
}
|
|
273
286
|
const wsUrl = new URL(imServerUrl);
|
|
274
|
-
if (
|
|
287
|
+
if (email) {
|
|
288
|
+
wsUrl.searchParams.set("email", email);
|
|
289
|
+
} else if (address) {
|
|
275
290
|
wsUrl.searchParams.set("address", address);
|
|
276
291
|
}
|
|
277
292
|
console.log(`[BountyIM] Connecting to ${wsUrl.toString()}...`);
|
|
@@ -352,13 +367,16 @@ class BountyIMInstance {
|
|
|
352
367
|
const eventType = `bounty-im.${evt.event || "message"}`;
|
|
353
368
|
const fromAddress = msg.from || "unknown";
|
|
354
369
|
const currentAddress = this.getCurrentAddress();
|
|
370
|
+
const currentIdentity = this.getCurrentIdentity();
|
|
371
|
+
const currentEmail = currentIdentity.email;
|
|
355
372
|
const toAddress = msg.to || currentAddress;
|
|
356
|
-
|
|
357
|
-
|
|
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})`);
|
|
358
376
|
}
|
|
359
377
|
const msgContent = msg.content;
|
|
360
378
|
const content = msgContent?.type === "text" ? String(msgContent.body || "") : "";
|
|
361
|
-
const { imServerUrl } = readBountyIMConfig(this.config);
|
|
379
|
+
const { imServerUrl, email } = readBountyIMConfig(this.config);
|
|
362
380
|
const agent = this.config.handleRule?.agent;
|
|
363
381
|
const metadata = {
|
|
364
382
|
eventType,
|
|
@@ -366,10 +384,12 @@ class BountyIMInstance {
|
|
|
366
384
|
chatId: toAddress,
|
|
367
385
|
agent
|
|
368
386
|
};
|
|
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 "回复内容"`;
|
|
369
389
|
let recommendedAction;
|
|
370
390
|
if (evt.event === "message") {
|
|
371
391
|
recommendedAction = {
|
|
372
|
-
action: `处理消息并通过 bounty com send
|
|
392
|
+
action: `处理消息并通过 bounty com send 回复发件人。使用格式:${replyCommandHint}`,
|
|
373
393
|
replyTo: {
|
|
374
394
|
chatId: fromAddress
|
|
375
395
|
}
|
|
@@ -379,14 +399,14 @@ class BountyIMInstance {
|
|
|
379
399
|
type: "bounty-im",
|
|
380
400
|
chatId: fromAddress,
|
|
381
401
|
params: {
|
|
382
|
-
from: toAddress,
|
|
402
|
+
from: email || toAddress,
|
|
383
403
|
to: fromAddress,
|
|
384
404
|
imServerUrl
|
|
385
405
|
}
|
|
386
406
|
};
|
|
387
407
|
const displayMessage = content ? `[From ${fromAddress}] ${content}
|
|
388
408
|
|
|
389
|
-
\uD83D\uDCA1 回复:
|
|
409
|
+
\uD83D\uDCA1 回复: ${inlineReplyHint}` : this.formatMessage(rawEvent);
|
|
390
410
|
const event = {
|
|
391
411
|
id: `es-${this.config.id}-${Date.now()}`,
|
|
392
412
|
type: "event-source.event.bounty-im",
|
|
@@ -451,11 +471,19 @@ var bountyIMHandler = {
|
|
|
451
471
|
errors.push("EventSource ID is required");
|
|
452
472
|
if (!config.name)
|
|
453
473
|
errors.push("EventSource name is required");
|
|
454
|
-
const { address, imServerUrl } = readBountyIMConfig(config);
|
|
455
|
-
if (!address) {
|
|
456
|
-
errors.push("Bounty IM address is required (top-level address or options.address)");
|
|
457
|
-
}
|
|
458
|
-
|
|
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)");
|
|
477
|
+
}
|
|
478
|
+
if (email !== undefined && email !== "") {
|
|
479
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
|
480
|
+
errors.push("Bounty IM email format invalid (expected: user@domain.tld)");
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (address !== undefined && address !== "") {
|
|
484
|
+
if (!/^[\w-]+@[\w.-]+$/.test(address)) {
|
|
485
|
+
errors.push("Bounty IM address format invalid (expected: agent-id@host)");
|
|
486
|
+
}
|
|
459
487
|
}
|
|
460
488
|
if (!imServerUrl) {
|
|
461
489
|
errors.push("Bounty IM imServerUrl is required (top-level imServerUrl or options.imServerUrl)");
|
|
@@ -808,8 +836,9 @@ class LarkCliInstance {
|
|
|
808
836
|
}
|
|
809
837
|
const event = rawEvent;
|
|
810
838
|
let eventType;
|
|
811
|
-
|
|
812
|
-
|
|
839
|
+
const eventHeader = event.header;
|
|
840
|
+
if (eventHeader?.event_type) {
|
|
841
|
+
eventType = eventHeader.event_type;
|
|
813
842
|
} else if (event.schema) {
|
|
814
843
|
eventType = `lark.${event.schema}`;
|
|
815
844
|
} else if (event.type) {
|
|
@@ -1310,6 +1339,9 @@ class EventSourceComponent extends BaseComponent {
|
|
|
1310
1339
|
return Array.from(this.sources.values());
|
|
1311
1340
|
}
|
|
1312
1341
|
getStatus(id) {
|
|
1342
|
+
if (id === undefined) {
|
|
1343
|
+
return this._status;
|
|
1344
|
+
}
|
|
1313
1345
|
return this.statuses.get(id);
|
|
1314
1346
|
}
|
|
1315
1347
|
getEventSourceStatus(id) {
|
|
@@ -615,14 +615,23 @@ function createWorkflowSearchTool(workflowService) {
|
|
|
615
615
|
init_logger();
|
|
616
616
|
import { z as z8 } from "zod";
|
|
617
617
|
var logger7 = createLogger("run-workflow-tool");
|
|
618
|
+
function synthFallbackRunId(now = Date.now()) {
|
|
619
|
+
return `workflow_${now}_fallback_${Math.random().toString(36).slice(2, 8)}`;
|
|
620
|
+
}
|
|
621
|
+
function attemptStopOnTimeout(workflowService, runId, reason) {
|
|
622
|
+
if (typeof workflowService.stopRun !== "function")
|
|
623
|
+
return;
|
|
624
|
+
workflowService.stopRun(runId, reason).catch((stopErr) => {
|
|
625
|
+
logger7.warn(`Failed to stop workflow ${runId} after timeout: ${stopErr instanceof Error ? stopErr.message : String(stopErr)}`);
|
|
626
|
+
});
|
|
627
|
+
}
|
|
618
628
|
var RunWorkflowInputSchema = z8.object({
|
|
619
629
|
workflow_name: z8.string().describe("Name of the workflow to run"),
|
|
620
630
|
input: z8.record(z8.any()).optional().describe("Input to pass to the workflow"),
|
|
621
|
-
sync: z8.boolean().default(true).describe("Wait for completion (default: true)"),
|
|
622
631
|
timeout: z8.number().positive().optional().describe("Timeout in milliseconds (default: 1800000 = 30 min)"),
|
|
623
632
|
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."),
|
|
624
633
|
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.")
|
|
625
|
-
});
|
|
634
|
+
}).strict();
|
|
626
635
|
function createRunWorkflowTool(workflowService) {
|
|
627
636
|
return {
|
|
628
637
|
name: "workflow_run",
|
|
@@ -642,10 +651,9 @@ function createRunWorkflowTool(workflowService) {
|
|
|
642
651
|
},
|
|
643
652
|
execute: async (args, ctx) => {
|
|
644
653
|
const startTime = Date.now();
|
|
645
|
-
const { workflow_name, input, session,
|
|
654
|
+
const { workflow_name, input, session, timeout = 1800000, node_config } = args;
|
|
646
655
|
logger7.info(`Running workflow: ${workflow_name}`, {
|
|
647
656
|
input,
|
|
648
|
-
sync,
|
|
649
657
|
timeout,
|
|
650
658
|
...session ? { resumeSession: session } : {}
|
|
651
659
|
});
|
|
@@ -657,15 +665,23 @@ function createRunWorkflowTool(workflowService) {
|
|
|
657
665
|
const parentSessionId = ctxSessionId ?? envSessionId;
|
|
658
666
|
let timeoutHandle;
|
|
659
667
|
let durationMs;
|
|
660
|
-
|
|
668
|
+
const reservedRunId = synthFallbackRunId();
|
|
669
|
+
let timedOut = false;
|
|
670
|
+
let capturedByCallback = false;
|
|
671
|
+
let capturedRunId = session ? session : reservedRunId;
|
|
661
672
|
const onSessionCreated = (sid) => {
|
|
662
673
|
capturedRunId = sid;
|
|
674
|
+
capturedByCallback = true;
|
|
675
|
+
if (timedOut) {
|
|
676
|
+
attemptStopOnTimeout(workflowService, sid, "timed out");
|
|
677
|
+
}
|
|
663
678
|
};
|
|
664
679
|
try {
|
|
665
680
|
let result;
|
|
681
|
+
const fallbackRunId = reservedRunId;
|
|
666
682
|
const baseOptions = {
|
|
667
|
-
sync,
|
|
668
683
|
...parentSessionId ? { parentSessionId } : {},
|
|
684
|
+
...session ? {} : { runId: reservedRunId },
|
|
669
685
|
onSessionCreated,
|
|
670
686
|
...node_config ? { nodeConfig: node_config } : {}
|
|
671
687
|
};
|
|
@@ -683,6 +699,8 @@ function createRunWorkflowTool(workflowService) {
|
|
|
683
699
|
executeCall(),
|
|
684
700
|
new Promise((_, reject) => {
|
|
685
701
|
timeoutHandle = setTimeout(() => {
|
|
702
|
+
timedOut = true;
|
|
703
|
+
attemptStopOnTimeout(workflowService, capturedRunId ?? reservedRunId, "timed out");
|
|
686
704
|
reject(new Error("Workflow execution timed out"));
|
|
687
705
|
}, timeout);
|
|
688
706
|
})
|
|
@@ -694,46 +712,31 @@ function createRunWorkflowTool(workflowService) {
|
|
|
694
712
|
clearTimeout(timeoutHandle);
|
|
695
713
|
}
|
|
696
714
|
durationMs = Date.now() - startTime;
|
|
697
|
-
const finalRunId = capturedRunId
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
};
|
|
716
|
-
} else {
|
|
717
|
-
return {
|
|
718
|
-
success: true,
|
|
719
|
-
output: {
|
|
720
|
-
run_id: finalRunId,
|
|
721
|
-
status: result.status,
|
|
722
|
-
duration_ms: durationMs
|
|
723
|
-
},
|
|
724
|
-
metadata: {
|
|
725
|
-
execution_time_ms: durationMs,
|
|
726
|
-
run_id: finalRunId
|
|
727
|
-
}
|
|
728
|
-
};
|
|
729
|
-
}
|
|
715
|
+
const finalRunId = capturedByCallback ? capturedRunId : result.runId ?? "";
|
|
716
|
+
return {
|
|
717
|
+
success: result.status === "completed" || result.status === "paused",
|
|
718
|
+
output: {
|
|
719
|
+
run_id: finalRunId,
|
|
720
|
+
status: result.status,
|
|
721
|
+
output: result.output,
|
|
722
|
+
error: result.error,
|
|
723
|
+
duration_ms: result.durationMs || durationMs,
|
|
724
|
+
...result.pendingNodeId ? { pending_node_id: result.pendingNodeId } : {},
|
|
725
|
+
...result.query ? { query: result.query } : {},
|
|
726
|
+
...result.agentSessionId ? { agent_session_id: result.agentSessionId } : {}
|
|
727
|
+
},
|
|
728
|
+
metadata: {
|
|
729
|
+
execution_time_ms: durationMs,
|
|
730
|
+
run_id: finalRunId
|
|
731
|
+
}
|
|
732
|
+
};
|
|
730
733
|
} catch (error) {
|
|
731
734
|
if (timeoutHandle) {
|
|
732
735
|
clearTimeout(timeoutHandle);
|
|
733
736
|
}
|
|
734
737
|
durationMs = Date.now() - startTime;
|
|
735
738
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
736
|
-
const errorRunId = capturedRunId ??
|
|
739
|
+
const errorRunId = capturedRunId ?? reservedRunId;
|
|
737
740
|
if (errorMessage.includes("Workflow not found")) {
|
|
738
741
|
return {
|
|
739
742
|
success: false,
|