@ai-setting/roy-agent-core 1.7.85 → 1.7.89
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/config/index.js +7 -7
- package/dist/env/agent/agent-component.d.ts +1 -1
- package/dist/env/agent/agent-component.js +13 -12
- package/dist/env/agent/index.js +13 -12
- package/dist/env/agent/types.d.ts +14 -0
- package/dist/env/commands/index.js +7 -7
- package/dist/env/context/index.js +3 -3
- package/dist/env/debug/index.js +7 -7
- package/dist/env/error-reply.js +1 -1
- package/dist/env/event-source/event-source-handlers.d.ts +18 -2
- package/dist/env/event-source/event-source-handlers.js +26 -21
- package/dist/env/event-source/event-store.js +2 -2
- package/dist/env/event-source/index.js +25 -22
- package/dist/env/event-source/timer-handler.d.ts +98 -0
- package/dist/env/event-source/types.d.ts +53 -1
- package/dist/env/event-source/wecom-card-action-handler.d.ts +235 -3
- package/dist/env/event-source/wecom-card-builder.d.ts +207 -1
- package/dist/env/event-source/wecom-cli-handler.d.ts +25 -0
- package/dist/{shared/@ai-setting/roy-agent-core-vyr6svt6.js → env/event-source/wecom-respond-registry.js} +8 -6
- package/dist/env/event-source/wecom-session-card-sender.d.ts +135 -0
- package/dist/env/event-source/wecom-session-card-sender.js +153 -0
- package/dist/env/hook/index.js +5 -5
- package/dist/env/index.js +50 -45
- package/dist/env/llm/index.js +9 -8
- package/dist/env/log-trace/index.js +7 -7
- package/dist/env/log-trace/trace-filters.d.ts +6 -1
- package/dist/env/mcp/index.js +7 -7
- package/dist/env/memory/index.js +7 -7
- package/dist/env/plugin/index.js +7 -7
- package/dist/env/prompt/index.js +8 -8
- package/dist/env/prompt/prompts-index.d.ts +1 -1
- package/dist/env/session/group-session-link.d.ts +99 -0
- package/dist/env/session/index.js +11 -10
- package/dist/env/session/session-component.d.ts +89 -0
- package/dist/env/session/storage/index.js +5 -4
- package/dist/env/session/types.d.ts +10 -0
- package/dist/env/skill/index.js +7 -7
- package/dist/env/task/backend/index.d.ts +3 -0
- package/dist/env/task/backend/index.js +151 -3
- package/dist/env/task/backend/remote-task-port.d.ts +85 -0
- package/dist/env/task/backend/types.d.ts +5 -0
- package/dist/env/task/delegate/delegate-channel-hint.d.ts +39 -0
- package/dist/env/task/delegate/delegate-tool.d.ts +71 -6
- package/dist/env/task/delegate/delegate-tool.js +11 -9
- package/dist/env/task/delegate/index.js +8 -8
- package/dist/env/task/index.d.ts +1 -1
- package/dist/env/task/index.js +34 -18
- package/dist/env/task/mcp/index.js +4 -4
- package/dist/env/task/plugins/card-subject.d.ts +117 -0
- package/dist/env/task/plugins/index.js +19 -17
- package/dist/env/task/plugins/lark-card-action-handler.d.ts +261 -6
- package/dist/env/task/plugins/lark-card-patch-notifier.d.ts +501 -0
- package/dist/env/task/plugins/lark-card-patch-notifier.js +12 -2
- package/dist/env/task/plugins/lark-card-state-store.d.ts +60 -0
- package/dist/env/task/plugins/lark-cli-task-notify-plugin.d.ts +45 -0
- package/dist/env/task/plugins/sub-session-activity.d.ts +415 -0
- package/dist/env/task/plugins/wecom-session-card-store.d.ts +134 -0
- package/dist/env/task/plugins/wecom-session-card-store.js +23 -0
- package/dist/env/task/plugins/wecom-task-notify-plugin.d.ts +40 -0
- package/dist/env/task/storage/index.d.ts +1 -0
- package/dist/env/task/storage/index.js +24 -4
- package/dist/env/task/storage/migrations/006_add_task_owner.d.ts +24 -0
- package/dist/env/task/storage/remote-task-store.d.ts +186 -0
- package/dist/env/task/task-component.d.ts +7 -0
- package/dist/env/task/tools/index.js +4 -4
- package/dist/env/task/tools/task-types.d.ts +7 -0
- package/dist/env/task/types.d.ts +17 -0
- package/dist/env/tool/built-in/index.js +6 -4
- package/dist/env/tool/index.js +14 -10
- package/dist/env/tool/types.d.ts +25 -0
- package/dist/env/tool/validator.d.ts +8 -0
- package/dist/env/workflow/engine/index.js +12 -12
- package/dist/env/workflow/hooks/index.js +7 -7
- package/dist/env/workflow/index.js +24 -23
- package/dist/env/workflow/nodes/index.js +2 -2
- package/dist/env/workflow/plugins/index.js +10 -8
- package/dist/env/workflow/service/index.js +2 -2
- package/dist/env/workflow/storage/index.js +3 -3
- package/dist/env/workflow/tools/index.js +16 -15
- package/dist/env/workflow/utils/index.js +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +71 -60
- package/dist/shared/@ai-setting/{roy-agent-core-q813vafd.js → roy-agent-core-05z35shp.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-dc9zq75z.js → roy-agent-core-0crmsc12.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-7dd0s3xb.js → roy-agent-core-0n1wwndq.js} +1027 -14
- package/dist/shared/@ai-setting/{roy-agent-core-cha0jc7n.js → roy-agent-core-0sbmdz8d.js} +137 -16
- package/dist/shared/@ai-setting/{roy-agent-core-87942bw4.js → roy-agent-core-1mhyh4c5.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-v6vr6za7.js → roy-agent-core-1vv4fx15.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-nwbfepba.js → roy-agent-core-3e040tc5.js} +1 -1
- package/dist/shared/@ai-setting/roy-agent-core-418zc9ha.js +288 -0
- package/dist/shared/@ai-setting/{roy-agent-core-qk9hd89p.js → roy-agent-core-49qcpqwg.js} +54 -19
- package/dist/shared/@ai-setting/{roy-agent-core-xf6z96qy.js → roy-agent-core-4b38m749.js} +818 -346
- package/dist/shared/@ai-setting/{roy-agent-core-r5wt1h3c.js → roy-agent-core-4fkxy2gv.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-na18zwj0.js → roy-agent-core-4t3yskp8.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-d1n4jbza.js → roy-agent-core-5dhvfgaw.js} +5 -5
- package/dist/shared/@ai-setting/{roy-agent-core-5pr4zp88.js → roy-agent-core-5kzhaap1.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-qq96p0tj.js → roy-agent-core-5s2t8z00.js} +22 -1
- package/dist/shared/@ai-setting/{roy-agent-core-6rh8k6ba.js → roy-agent-core-6gj1hc5z.js} +7 -7
- package/dist/shared/@ai-setting/{roy-agent-core-g8htfwxj.js → roy-agent-core-7f10p7m2.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-h21gngxf.js → roy-agent-core-7yh5wps0.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-efkjyh69.js → roy-agent-core-9710zwwz.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-rykf7c04.js → roy-agent-core-9c565frx.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-vffccgf6.js → roy-agent-core-9cen1jvg.js} +18 -7
- package/dist/shared/@ai-setting/{roy-agent-core-fghc2m8z.js → roy-agent-core-aa8kv18f.js} +34 -2
- package/dist/shared/@ai-setting/roy-agent-core-age3qseb.js +177 -0
- package/dist/shared/@ai-setting/{roy-agent-core-7bpj859q.js → roy-agent-core-azyz78ky.js} +7 -7
- package/dist/shared/@ai-setting/{roy-agent-core-264qexac.js → roy-agent-core-b7h39vrc.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-dqxec05w.js → roy-agent-core-bjtc9d35.js} +2 -2
- package/dist/shared/@ai-setting/roy-agent-core-c4ec7k0p.js +426 -0
- package/dist/shared/@ai-setting/{roy-agent-core-ddyk1rc0.js → roy-agent-core-cre2y2ct.js} +160 -4
- package/dist/shared/@ai-setting/{roy-agent-core-tr3ep81v.js → roy-agent-core-d6zdbgtc.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-0qyrk5k0.js → roy-agent-core-ds6qzmf8.js} +14 -5
- package/dist/shared/@ai-setting/{roy-agent-core-p6ks90tb.js → roy-agent-core-dvec4nn2.js} +6 -6
- package/dist/shared/@ai-setting/{roy-agent-core-cgtq6427.js → roy-agent-core-e08bvpaq.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-12n08pg5.js → roy-agent-core-e69qxdyy.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-xcp8vwax.js → roy-agent-core-fepm835e.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-6j02sbee.js → roy-agent-core-fhg03v43.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-dvtg4sn0.js → roy-agent-core-g8yr733d.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-m3vjepzz.js → roy-agent-core-h1e1fm9b.js} +38 -202
- package/dist/shared/@ai-setting/{roy-agent-core-c2gbt68e.js → roy-agent-core-h83zdsrq.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-tk98f92b.js → roy-agent-core-k3gcvybs.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-b31v3qpv.js → roy-agent-core-k3h8t4q1.js} +992 -212
- package/dist/shared/@ai-setting/{roy-agent-core-pgvcf91v.js → roy-agent-core-m39v7qpx.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-ezvpreqz.js → roy-agent-core-m66ysky0.js} +54 -6
- package/dist/shared/@ai-setting/{roy-agent-core-begm7ytz.js → roy-agent-core-m7d1t3db.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-tm1mxttk.js → roy-agent-core-mf5p38yf.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-83bewqx8.js → roy-agent-core-mvh0td7p.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-ze5cqpf2.js → roy-agent-core-mx855td4.js} +17 -38
- package/dist/shared/@ai-setting/{roy-agent-core-0dh8npnz.js → roy-agent-core-n197medr.js} +13 -13
- package/dist/shared/@ai-setting/{roy-agent-core-cmprygrp.js → roy-agent-core-nqkfkpf4.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-7cbpmk4q.js → roy-agent-core-p31ftgq9.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-1v4g0d4x.js → roy-agent-core-rm7seqwb.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-ax9e9szb.js → roy-agent-core-smf94h73.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-acj8ag08.js → roy-agent-core-tjnabyvq.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-qqaak24r.js → roy-agent-core-tkpp1ba0.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-dkrvmjsh.js → roy-agent-core-tpm1dd1g.js} +23 -15
- package/dist/shared/@ai-setting/{roy-agent-core-ed233k5z.js → roy-agent-core-v1n0106v.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-zxz5fkwj.js → roy-agent-core-v6yshv0z.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-mcy5apay.js → roy-agent-core-vf9sp6s3.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-xvt7kf7p.js → roy-agent-core-w9ryeg2p.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-es203w7p.js → roy-agent-core-wqs6yypq.js} +1 -1
- package/dist/shared/@ai-setting/roy-agent-core-wxrkcb17.js +56 -0
- package/dist/shared/@ai-setting/{roy-agent-core-0snm5hc5.js → roy-agent-core-y6shd91r.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-9vxh6f8h.js → roy-agent-core-y7fqtzk2.js} +7 -7
- package/dist/shared/@ai-setting/{roy-agent-core-cpcd24n2.js → roy-agent-core-yet36q5k.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-3fh1f7s7.js → roy-agent-core-yfpnkc4z.js} +5 -5
- package/dist/shared/@ai-setting/roy-agent-core-zhwcje5a.js +352 -0
- package/package.json +9 -1
|
@@ -4,35 +4,35 @@ import {
|
|
|
4
4
|
} from "./roy-agent-core-fttgm52a.js";
|
|
5
5
|
import {
|
|
6
6
|
getSharedEventStore
|
|
7
|
-
} from "./roy-agent-core-
|
|
7
|
+
} from "./roy-agent-core-4t3yskp8.js";
|
|
8
8
|
import {
|
|
9
9
|
builtInPrompts
|
|
10
|
-
} from "./roy-agent-core-
|
|
10
|
+
} from "./roy-agent-core-y7fqtzk2.js";
|
|
11
11
|
import {
|
|
12
12
|
TaskHookPoints
|
|
13
13
|
} from "./roy-agent-core-1pg0fepg.js";
|
|
14
14
|
import {
|
|
15
15
|
DEFAULT_SUBAGENT_PROMPT
|
|
16
|
-
} from "./roy-agent-core-
|
|
16
|
+
} from "./roy-agent-core-v1n0106v.js";
|
|
17
17
|
import {
|
|
18
18
|
runWithBgTaskIdAsync
|
|
19
19
|
} from "./roy-agent-core-c1v263jn.js";
|
|
20
20
|
import {
|
|
21
21
|
globalHookManager,
|
|
22
22
|
init_global_hook_manager
|
|
23
|
-
} from "./roy-agent-core-
|
|
23
|
+
} from "./roy-agent-core-yet36q5k.js";
|
|
24
24
|
import {
|
|
25
25
|
init_context
|
|
26
|
-
} from "./roy-agent-core-
|
|
26
|
+
} from "./roy-agent-core-tkpp1ba0.js";
|
|
27
27
|
import {
|
|
28
28
|
getCurrentTaskId,
|
|
29
29
|
getEnvContext
|
|
30
|
-
} from "./roy-agent-core-
|
|
30
|
+
} from "./roy-agent-core-p31ftgq9.js";
|
|
31
31
|
import {
|
|
32
32
|
TracedAs,
|
|
33
33
|
init_decorator,
|
|
34
34
|
wrapFunction
|
|
35
|
-
} from "./roy-agent-core-
|
|
35
|
+
} from "./roy-agent-core-5s2t8z00.js";
|
|
36
36
|
import {
|
|
37
37
|
createLogger,
|
|
38
38
|
init_logger
|
|
@@ -47,6 +47,43 @@ init_decorator();
|
|
|
47
47
|
init_context();
|
|
48
48
|
import { z } from "zod";
|
|
49
49
|
|
|
50
|
+
// src/env/task/delegate/delegate-channel-hint.ts
|
|
51
|
+
var DELEGATE_CHANNEL_HINT_TITLE = "## 渠道交付提示(当前会话来自外部渠道)";
|
|
52
|
+
function buildDelegateChannelHint(channelType) {
|
|
53
|
+
if (!channelType)
|
|
54
|
+
return;
|
|
55
|
+
let channelBody;
|
|
56
|
+
if (channelType === "lark-cli" || channelType.startsWith("lark")) {
|
|
57
|
+
channelBody = [
|
|
58
|
+
`- 触发渠道是**飞书**。文档类产出(调研文档 / 报告 / PPT / doc 等)`,
|
|
59
|
+
` 必须用**飞书云盘**存储:\`lark-cli docs +create --title <标题> --markdown @<本地md>\`,用完即弃。`,
|
|
60
|
+
`- 交付时只给**云盘链接**(https://my.feishu.cn/...),**不落本地路径**交付。`,
|
|
61
|
+
` 本地路径只作中转(生成 md → 上传云盘 → 回复里贴云盘链接),不作为交付物。`
|
|
62
|
+
].join(`
|
|
63
|
+
`);
|
|
64
|
+
} else if (channelType === "wecom-cli" || channelType.startsWith("wecom")) {
|
|
65
|
+
channelBody = [
|
|
66
|
+
`- 触发渠道是**企业微信**。文档类产出(调研文档 / docs / ppt 等)`,
|
|
67
|
+
` 必须上传到**企微文档**,链接作为交付物:`,
|
|
68
|
+
` - 在线文档:\`wecom-cli doc create --doc-name <标题> --doc-type doc --content-type text --file-path <本地md>\``,
|
|
69
|
+
` - 微盘文件:\`wecom-cli disk files upload --file-path <本地文件>\`(默认传到我的空间)`,
|
|
70
|
+
`- 本地路径只作中转(生成 → 上传企微文档 → 回复里贴链接),**不落本地路径**交付。`
|
|
71
|
+
].join(`
|
|
72
|
+
`);
|
|
73
|
+
}
|
|
74
|
+
if (!channelBody)
|
|
75
|
+
return;
|
|
76
|
+
return [
|
|
77
|
+
DELEGATE_CHANNEL_HINT_TITLE,
|
|
78
|
+
``,
|
|
79
|
+
`通用措辞:当前会话来自外部渠道,交付类产出优先用该渠道的原生存储/展示方式,`,
|
|
80
|
+
`不要把本地文件路径当作交付物(渠道用户无法访问本机文件系统)。`,
|
|
81
|
+
``,
|
|
82
|
+
channelBody
|
|
83
|
+
].join(`
|
|
84
|
+
`);
|
|
85
|
+
}
|
|
86
|
+
|
|
50
87
|
// src/env/task/delegate/subagent-resolver.ts
|
|
51
88
|
function isKnownSubagentType(subagentType, registry) {
|
|
52
89
|
if (getSubAgentSpec(subagentType)) {
|
|
@@ -743,7 +780,8 @@ var BackgroundTaskEventTypes = {
|
|
|
743
780
|
FAILED: "task.background.failed",
|
|
744
781
|
TIMEOUT: "task.background.timeout",
|
|
745
782
|
STOPPED: "task.background.stopped",
|
|
746
|
-
ASK_USER: "task.background.ask_user"
|
|
783
|
+
ASK_USER: "task.background.ask_user",
|
|
784
|
+
SESSION_STARTED: "task.background.session_started"
|
|
747
785
|
};
|
|
748
786
|
var builtInSubAgents = [
|
|
749
787
|
{
|
|
@@ -825,6 +863,21 @@ var builtInSubAgents = [
|
|
|
825
863
|
function getSubAgentSpec(id) {
|
|
826
864
|
return builtInSubAgents.find((agent) => agent.id === id);
|
|
827
865
|
}
|
|
866
|
+
function normalizeExtendTools(raw) {
|
|
867
|
+
if (!Array.isArray(raw))
|
|
868
|
+
return;
|
|
869
|
+
const out = [];
|
|
870
|
+
for (const v of raw) {
|
|
871
|
+
if (typeof v !== "string")
|
|
872
|
+
continue;
|
|
873
|
+
const trimmed = v.trim();
|
|
874
|
+
if (trimmed.length === 0)
|
|
875
|
+
continue;
|
|
876
|
+
if (!out.includes(trimmed))
|
|
877
|
+
out.push(trimmed);
|
|
878
|
+
}
|
|
879
|
+
return out.length > 0 ? out : undefined;
|
|
880
|
+
}
|
|
828
881
|
function ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgent, deniedTools) {
|
|
829
882
|
const registry = agentComponent.getRegistry?.();
|
|
830
883
|
if (registry) {
|
|
@@ -858,7 +911,7 @@ var DelegateToolParameters = z.object({
|
|
|
858
911
|
timeout: z.number().describe("Task timeout in milliseconds. Default: 1800000 (30 minutes). If set, task will be terminated after timeout.").optional(),
|
|
859
912
|
reason: z.string().describe("Brief reason for calling this tool (max 30 chars, e.g., 'Delegate refactor task')").optional(),
|
|
860
913
|
similar_task_ids: z.array(z.number()).max(3).describe("Similar task IDs (max 3) to reference for improving task execution. Search for similar tasks before calling this tool."),
|
|
861
|
-
sub_session_id: z.string().describe("
|
|
914
|
+
sub_session_id: z.string().describe("⚠️ 硬约束:同一任务链的续跑必须传此参数(从终态 notify 的「子 session:」行" + "或 delegate 返回的「\uD83D\uDD17 Sub-session:」行复制)。" + "仅当旧 session 上下文已确认不可救(compact_session 后仍超限 / 迭代上限且无可复用断点)时才留空;" + "留空等于丢弃全部上下文,从零开始。").optional(),
|
|
862
915
|
triggerEventId: z.string().describe("EventStore trigger event ID (ESPlugin v2). Pass it when this delegate_task " + "is triggered by an external event source (e.g. Feishu message) so the " + "completion notification can reply to the original chat instead of a " + "fallback channel. Leave empty if not triggered by an event source.").optional()
|
|
863
916
|
});
|
|
864
917
|
function buildEntryAgentPrompt(options) {
|
|
@@ -1116,7 +1169,7 @@ class BackgroundTaskManager {
|
|
|
1116
1169
|
return null;
|
|
1117
1170
|
}
|
|
1118
1171
|
async createTask(options) {
|
|
1119
|
-
const { parentSessionId, description, prompt, subagentType, timeout, similarTaskIds, existingSubSessionId, triggerEventId, model, fallbackModel, fallbackModels, systemPrompt } = options;
|
|
1172
|
+
const { parentSessionId, description, prompt, subagentType, timeout, similarTaskIds, existingSubSessionId, triggerEventId, model, fallbackModel, fallbackModels, systemPrompt, extendTools } = options;
|
|
1120
1173
|
const taskIdGen = `process_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
|
1121
1174
|
const sessionComponent = this.getSessionComponent();
|
|
1122
1175
|
if (!sessionComponent) {
|
|
@@ -1175,6 +1228,10 @@ class BackgroundTaskManager {
|
|
|
1175
1228
|
if (profile) {
|
|
1176
1229
|
metadata.larkProfile = profile;
|
|
1177
1230
|
}
|
|
1231
|
+
const channelType = replyChannel?.type;
|
|
1232
|
+
if (channelType) {
|
|
1233
|
+
metadata.channelType = channelType;
|
|
1234
|
+
}
|
|
1178
1235
|
}
|
|
1179
1236
|
if (triggerEventId) {
|
|
1180
1237
|
metadata.triggerEventId = triggerEventId;
|
|
@@ -1219,6 +1276,7 @@ class BackgroundTaskManager {
|
|
|
1219
1276
|
fallbackModel,
|
|
1220
1277
|
fallbackModels,
|
|
1221
1278
|
systemPrompt,
|
|
1279
|
+
extendTools,
|
|
1222
1280
|
replyChannel: replyChannelSnapshot,
|
|
1223
1281
|
pluginEnabledSnapshot
|
|
1224
1282
|
};
|
|
@@ -1234,6 +1292,16 @@ class BackgroundTaskManager {
|
|
|
1234
1292
|
timeoutMs: timeout || DEFAULT_TIMEOUT
|
|
1235
1293
|
};
|
|
1236
1294
|
this.publishBackgroundEvent(BackgroundTaskEventTypes.STARTED, startedPayload, parentSessionId, triggerEventId, replyChannelSnapshot, task.pluginEnabledSnapshot);
|
|
1295
|
+
this.publishBackgroundEvent(BackgroundTaskEventTypes.SESSION_STARTED, {
|
|
1296
|
+
backgroundTaskId: taskIdGen,
|
|
1297
|
+
subSessionId: subSession.id,
|
|
1298
|
+
parentSessionId,
|
|
1299
|
+
description,
|
|
1300
|
+
subagentType,
|
|
1301
|
+
associatedTaskId: undefined,
|
|
1302
|
+
lifecycle: "running",
|
|
1303
|
+
startedAt: createdAt
|
|
1304
|
+
}, parentSessionId, triggerEventId, replyChannelSnapshot, task.pluginEnabledSnapshot);
|
|
1237
1305
|
this.executeTask(taskIdGen, prompt, timeout, parentSessionId).catch((err) => {
|
|
1238
1306
|
logger3.error(`[BackgroundTaskManager] executeTask unhandled rejection`, {
|
|
1239
1307
|
taskId: taskIdGen,
|
|
@@ -1277,6 +1345,16 @@ class BackgroundTaskManager {
|
|
|
1277
1345
|
if (task.associatedTaskId === undefined) {
|
|
1278
1346
|
task.associatedTaskId = getCurrentTaskId();
|
|
1279
1347
|
}
|
|
1348
|
+
this.publishBackgroundEvent(BackgroundTaskEventTypes.SESSION_STARTED, {
|
|
1349
|
+
backgroundTaskId: task.id,
|
|
1350
|
+
subSessionId: task.subSessionId,
|
|
1351
|
+
parentSessionId: parentSessionId || task.parentSessionId,
|
|
1352
|
+
description: task.description,
|
|
1353
|
+
subagentType: task.subagentType,
|
|
1354
|
+
associatedTaskId: task.associatedTaskId,
|
|
1355
|
+
lifecycle: "completed",
|
|
1356
|
+
executionTimeMs
|
|
1357
|
+
}, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
|
|
1280
1358
|
const completedPayload = {
|
|
1281
1359
|
backgroundTaskId: task.id,
|
|
1282
1360
|
subSessionId: task.subSessionId,
|
|
@@ -1324,7 +1402,7 @@ class BackgroundTaskManager {
|
|
|
1324
1402
|
executionTimeMs,
|
|
1325
1403
|
hints: [
|
|
1326
1404
|
"请把上面的问题原样通过 ask_user tool 展示给用户并等待答复",
|
|
1327
|
-
`得到用户回复后,通过 delegate_task(
|
|
1405
|
+
`得到用户回复后,通过 delegate_task(subagent_type="${task.subagentType}", sub_session_id="${task.subSessionId}", prompt=<基于用户回复>) 复用 sub-session 让 sub-agent 继承之前消息历史继续推进,无需实现 resume function`
|
|
1328
1406
|
],
|
|
1329
1407
|
associatedTaskId: task.associatedTaskId
|
|
1330
1408
|
};
|
|
@@ -1351,6 +1429,16 @@ class BackgroundTaskManager {
|
|
|
1351
1429
|
associatedTaskId: task.associatedTaskId
|
|
1352
1430
|
};
|
|
1353
1431
|
this.publishBackgroundEvent(BackgroundTaskEventTypes.STOPPED, stoppedPayload, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
|
|
1432
|
+
this.publishBackgroundEvent(BackgroundTaskEventTypes.SESSION_STARTED, {
|
|
1433
|
+
backgroundTaskId: task.id,
|
|
1434
|
+
subSessionId: task.subSessionId,
|
|
1435
|
+
parentSessionId: parentSessionId || task.parentSessionId,
|
|
1436
|
+
description: task.description,
|
|
1437
|
+
subagentType: task.subagentType,
|
|
1438
|
+
associatedTaskId: task.associatedTaskId,
|
|
1439
|
+
lifecycle: "stopped",
|
|
1440
|
+
executionTimeMs
|
|
1441
|
+
}, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
|
|
1354
1442
|
} else if (errorMessage.startsWith("Task execution timeout after")) {
|
|
1355
1443
|
task.status = "timeout";
|
|
1356
1444
|
const timeoutPayload = {
|
|
@@ -1364,6 +1452,16 @@ class BackgroundTaskManager {
|
|
|
1364
1452
|
associatedTaskId: task.associatedTaskId
|
|
1365
1453
|
};
|
|
1366
1454
|
this.publishBackgroundEvent(BackgroundTaskEventTypes.TIMEOUT, timeoutPayload, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
|
|
1455
|
+
this.publishBackgroundEvent(BackgroundTaskEventTypes.SESSION_STARTED, {
|
|
1456
|
+
backgroundTaskId: task.id,
|
|
1457
|
+
subSessionId: task.subSessionId,
|
|
1458
|
+
parentSessionId: parentSessionId || task.parentSessionId,
|
|
1459
|
+
description: task.description,
|
|
1460
|
+
subagentType: task.subagentType,
|
|
1461
|
+
associatedTaskId: task.associatedTaskId,
|
|
1462
|
+
lifecycle: "timeout",
|
|
1463
|
+
executionTimeMs
|
|
1464
|
+
}, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
|
|
1367
1465
|
} else {
|
|
1368
1466
|
task.status = "failed";
|
|
1369
1467
|
const failedPayload = {
|
|
@@ -1376,6 +1474,16 @@ class BackgroundTaskManager {
|
|
|
1376
1474
|
associatedTaskId: task.associatedTaskId
|
|
1377
1475
|
};
|
|
1378
1476
|
this.publishBackgroundEvent(BackgroundTaskEventTypes.FAILED, failedPayload, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
|
|
1477
|
+
this.publishBackgroundEvent(BackgroundTaskEventTypes.SESSION_STARTED, {
|
|
1478
|
+
backgroundTaskId: task.id,
|
|
1479
|
+
subSessionId: task.subSessionId,
|
|
1480
|
+
parentSessionId: parentSessionId || task.parentSessionId,
|
|
1481
|
+
description: task.description,
|
|
1482
|
+
subagentType: task.subagentType,
|
|
1483
|
+
associatedTaskId: task.associatedTaskId,
|
|
1484
|
+
lifecycle: "failed",
|
|
1485
|
+
executionTimeMs
|
|
1486
|
+
}, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
|
|
1379
1487
|
}
|
|
1380
1488
|
task.error = errorMessage;
|
|
1381
1489
|
logger3.error(`[BackgroundTaskManager] Task execution error`, {
|
|
@@ -1552,6 +1660,15 @@ ${reuseSection.markdown}`;
|
|
|
1552
1660
|
error: err instanceof Error ? err.message : String(err)
|
|
1553
1661
|
});
|
|
1554
1662
|
}
|
|
1663
|
+
const channelTypeHint = metadata.channelType ?? getEnvContext()?.replyChannel?.type;
|
|
1664
|
+
const channelHint = buildDelegateChannelHint(channelTypeHint);
|
|
1665
|
+
if (channelHint) {
|
|
1666
|
+
fullPrompt += `
|
|
1667
|
+
|
|
1668
|
+
---
|
|
1669
|
+
|
|
1670
|
+
${channelHint}`;
|
|
1671
|
+
}
|
|
1555
1672
|
const subAgentForRegister = subAgent ? { ...subAgent, allowedTools } : allowedTools ? {
|
|
1556
1673
|
id: subagentType,
|
|
1557
1674
|
name: subagentType,
|
|
@@ -1641,7 +1758,8 @@ ${reuseSection.markdown}`;
|
|
|
1641
1758
|
...inheritedModel ? { model: inheritedModel } : {},
|
|
1642
1759
|
...inheritedFallbackModel ? { fallbackModel: inheritedFallbackModel } : {},
|
|
1643
1760
|
...Array.isArray(inheritedFallbackModels) ? { fallbackModels: inheritedFallbackModels } : {},
|
|
1644
|
-
...task?.systemPrompt ? { metadata: { systemPrompt: task.systemPrompt } } : {}
|
|
1761
|
+
...task?.systemPrompt ? { metadata: { systemPrompt: task.systemPrompt } } : {},
|
|
1762
|
+
...task?.extendTools?.length ? { extendTools: task.extendTools } : {}
|
|
1645
1763
|
});
|
|
1646
1764
|
};
|
|
1647
1765
|
const wrappedPromise = processRegistry ? runWithProcessRegistryAsync(processRegistry, () => runWithBgTaskIdAsync(bgTaskId, () => invokeHandleQuery())) : runWithBgTaskIdAsync(bgTaskId, () => invokeHandleQuery());
|
|
@@ -2057,7 +2175,7 @@ No need to poll — just wait for the notification and use \`task_get\` with the
|
|
|
2057
2175
|
};
|
|
2058
2176
|
await globalHookManager.execute(TaskHookPoints.DELEGATE_BEFORE, delegateCtx, { sessionId: parentSessionId });
|
|
2059
2177
|
promptWithTaskInfo = delegateCtx.prompt;
|
|
2060
|
-
return await handleBackgroundTask(backgroundTaskManager, parentSessionId, description, promptWithTaskInfo, delegateCtx.subagentType, delegateCtx.timeout, similar_task_ids, params.sub_session_id, resolvedTriggerEventId, ctx.model, ctx.fallbackModel, ctx.fallbackModels, ctx.metadata?.systemPrompt);
|
|
2178
|
+
return await handleBackgroundTask(backgroundTaskManager, parentSessionId, description, promptWithTaskInfo, delegateCtx.subagentType, delegateCtx.timeout, similar_task_ids, params.sub_session_id, resolvedTriggerEventId, ctx.model, ctx.fallbackModel, ctx.fallbackModels, ctx.metadata?.systemPrompt, normalizeExtendTools(ctx.metadata?.extendTools));
|
|
2061
2179
|
}
|
|
2062
2180
|
};
|
|
2063
2181
|
tool.execute = wrapFunction(tool.execute, "delegate.execute", {
|
|
@@ -2113,7 +2231,7 @@ function _capturePluginEnabledSnapshot() {
|
|
|
2113
2231
|
return { ...pluginEnabled };
|
|
2114
2232
|
}
|
|
2115
2233
|
var capturePluginEnabledSnapshot = wrapFunction(_capturePluginEnabledSnapshot, "delegate.capturePluginEnabled", { recordParams: false, recordResult: true, recordError: true });
|
|
2116
|
-
async function handleBackgroundTask(backgroundTaskManager, parentSessionId, description, prompt, subagentType, timeout, similarTaskIds, existingSubSessionId, triggerEventId, model, fallbackModel, fallbackModels, systemPrompt) {
|
|
2234
|
+
async function handleBackgroundTask(backgroundTaskManager, parentSessionId, description, prompt, subagentType, timeout, similarTaskIds, existingSubSessionId, triggerEventId, model, fallbackModel, fallbackModels, systemPrompt, extendTools) {
|
|
2117
2235
|
const startTime = Date.now();
|
|
2118
2236
|
try {
|
|
2119
2237
|
let actualSubagentType = subagentType;
|
|
@@ -2143,7 +2261,8 @@ async function handleBackgroundTask(backgroundTaskManager, parentSessionId, desc
|
|
|
2143
2261
|
model,
|
|
2144
2262
|
fallbackModel,
|
|
2145
2263
|
fallbackModels,
|
|
2146
|
-
systemPrompt
|
|
2264
|
+
systemPrompt,
|
|
2265
|
+
extendTools
|
|
2147
2266
|
});
|
|
2148
2267
|
const output = [
|
|
2149
2268
|
`✅ Background task accepted`,
|
|
@@ -2153,6 +2272,8 @@ async function handleBackgroundTask(backgroundTaskManager, parentSessionId, desc
|
|
|
2153
2272
|
`\uD83E\uDD16 Sub-agent: ${actualSubagentType}${originalWorkflowName ? ` (workflow: ${originalWorkflowName})` : ""}`,
|
|
2154
2273
|
`⏱️ Timeout: ${(timeout || DEFAULT_TIMEOUT) / 1000}s`,
|
|
2155
2274
|
"",
|
|
2275
|
+
`\uD83D\uDD17 Sub-session: ${subSessionId} (续跑本任务:delegate_task(sub_session_id="${subSessionId}", prompt="..."))`,
|
|
2276
|
+
"",
|
|
2156
2277
|
`Use stop_task with task_id="${bgProcessId}" to cancel this task.`
|
|
2157
2278
|
].join(`
|
|
2158
2279
|
`);
|
|
@@ -2176,4 +2297,4 @@ async function handleBackgroundTask(backgroundTaskManager, parentSessionId, desc
|
|
|
2176
2297
|
};
|
|
2177
2298
|
}
|
|
2178
2299
|
}
|
|
2179
|
-
export { BackgroundTaskEventTypes, builtInSubAgents, getSubAgentSpec, DelegateToolParameters, buildEntryAgentPrompt, WORKFLOW_COMPAT_ALIASES, DEFAULT_TIMEOUT, PROGRESS_INTERVAL, BackgroundTaskManager, createDelegateTool, deriveTriggerEventIdFromEnvContext, captureReplyChannelSnapshot, capturePluginEnabledSnapshot, handleBackgroundTask };
|
|
2300
|
+
export { BackgroundTaskEventTypes, builtInSubAgents, getSubAgentSpec, normalizeExtendTools, DelegateToolParameters, buildEntryAgentPrompt, WORKFLOW_COMPAT_ALIASES, DEFAULT_TIMEOUT, PROGRESS_INTERVAL, BackgroundTaskManager, createDelegateTool, deriveTriggerEventIdFromEnvContext, captureReplyChannelSnapshot, capturePluginEnabledSnapshot, handleBackgroundTask };
|
|
@@ -3,17 +3,17 @@ import {
|
|
|
3
3
|
} from "./roy-agent-core-az13yzmc.js";
|
|
4
4
|
import {
|
|
5
5
|
BaseComponent
|
|
6
|
-
} from "./roy-agent-core-
|
|
6
|
+
} from "./roy-agent-core-m39v7qpx.js";
|
|
7
7
|
import {
|
|
8
8
|
globalHookManager,
|
|
9
9
|
init_global_hook_manager
|
|
10
|
-
} from "./roy-agent-core-
|
|
10
|
+
} from "./roy-agent-core-yet36q5k.js";
|
|
11
11
|
import {
|
|
12
12
|
init_context
|
|
13
|
-
} from "./roy-agent-core-
|
|
13
|
+
} from "./roy-agent-core-tkpp1ba0.js";
|
|
14
14
|
import {
|
|
15
15
|
getEnvContextOrEmpty
|
|
16
|
-
} from "./roy-agent-core-
|
|
16
|
+
} from "./roy-agent-core-p31ftgq9.js";
|
|
17
17
|
import {
|
|
18
18
|
createLogger,
|
|
19
19
|
init_logger
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
// src/env/task/plugins/sub-session-activity.ts
|
|
2
|
+
function flattenInline(text) {
|
|
3
|
+
return text.replace(/\r\n?/g, `
|
|
4
|
+
`).replace(/\n+/g, " · ").replace(/\s{2,}/g, " ").replace(/(?:\s*·\s*){2,}/g, " · ").replace(/^(\s*·\s*)+/, "").replace(/(\s*·\s*)+$/, "").trim();
|
|
5
|
+
}
|
|
6
|
+
var ACTIVITY_ACTIVE_MS = 5 * 60 * 1000;
|
|
7
|
+
var ACTIVITY_SLOW_MS = 20 * 60 * 1000;
|
|
8
|
+
var DEFAULT_ACTIVITY_MESSAGE_MAX = 200;
|
|
9
|
+
function formatAgo(updatedAt, now) {
|
|
10
|
+
if (updatedAt === undefined || !Number.isFinite(updatedAt))
|
|
11
|
+
return;
|
|
12
|
+
const diff = now - updatedAt;
|
|
13
|
+
if (!Number.isFinite(diff) || diff < 60000)
|
|
14
|
+
return "刚刚";
|
|
15
|
+
const minutes = Math.floor(diff / 60000);
|
|
16
|
+
if (minutes < 60)
|
|
17
|
+
return `${minutes} 分钟前`;
|
|
18
|
+
const hours = Math.floor(minutes / 60);
|
|
19
|
+
if (hours < 24)
|
|
20
|
+
return `${hours} 小时前`;
|
|
21
|
+
return `${Math.floor(hours / 24)} 天前`;
|
|
22
|
+
}
|
|
23
|
+
function formatClockTime(ts) {
|
|
24
|
+
if (ts === undefined || !Number.isFinite(ts))
|
|
25
|
+
return;
|
|
26
|
+
const d = new Date(ts);
|
|
27
|
+
if (Number.isNaN(d.getTime()))
|
|
28
|
+
return;
|
|
29
|
+
const pad = (n) => n < 10 ? `0${n}` : String(n);
|
|
30
|
+
return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
|
31
|
+
}
|
|
32
|
+
function resolveActivityLiveness(activity, now, terminal = false) {
|
|
33
|
+
if (!activity) {
|
|
34
|
+
return { level: "unknown", dot: "❔", label: "未知" };
|
|
35
|
+
}
|
|
36
|
+
const agoText = formatAgo(activity.updatedAt, now);
|
|
37
|
+
if (terminal) {
|
|
38
|
+
return { level: "terminal", dot: "⚪", label: "已结束", agoText };
|
|
39
|
+
}
|
|
40
|
+
const updatedAt = activity.updatedAt;
|
|
41
|
+
if (updatedAt === undefined || !Number.isFinite(updatedAt)) {
|
|
42
|
+
return { level: "unknown", dot: "❔", label: "未知", agoText };
|
|
43
|
+
}
|
|
44
|
+
const age = now - updatedAt;
|
|
45
|
+
if (!Number.isFinite(age) || age < ACTIVITY_ACTIVE_MS) {
|
|
46
|
+
return { level: "active", dot: "\uD83D\uDFE2", label: "活跃", agoText };
|
|
47
|
+
}
|
|
48
|
+
if (age < ACTIVITY_SLOW_MS) {
|
|
49
|
+
return { level: "slow", dot: "\uD83D\uDFE1", label: "缓慢", agoText };
|
|
50
|
+
}
|
|
51
|
+
return { level: "stalled", dot: "\uD83D\uDD34", label: "疑似停滞", agoText };
|
|
52
|
+
}
|
|
53
|
+
function truncateActivityMessage(text, max = DEFAULT_ACTIVITY_MESSAGE_MAX) {
|
|
54
|
+
if (!text)
|
|
55
|
+
return "";
|
|
56
|
+
const flat = flattenInline(text);
|
|
57
|
+
if (!flat)
|
|
58
|
+
return "";
|
|
59
|
+
if (flat.length <= max)
|
|
60
|
+
return flat;
|
|
61
|
+
const cut = flat.slice(0, max - 1);
|
|
62
|
+
const lastSpace = cut.lastIndexOf(" ");
|
|
63
|
+
if (lastSpace > max * 0.6)
|
|
64
|
+
return `${cut.slice(0, lastSpace).trimEnd()}…`;
|
|
65
|
+
return `${cut}…`;
|
|
66
|
+
}
|
|
67
|
+
function formatActivityLines(activity, now, terminal = false) {
|
|
68
|
+
const live = resolveActivityLiveness(activity, now, terminal);
|
|
69
|
+
if (!activity) {
|
|
70
|
+
return ["❔ 暂无数据(子会话已归档或未落盘)"];
|
|
71
|
+
}
|
|
72
|
+
const headParts = [];
|
|
73
|
+
const agoPhrase = live.agoText ? `(${live.agoText}有写入)` : "";
|
|
74
|
+
headParts.push(`${live.dot} ${live.label}${agoPhrase}`);
|
|
75
|
+
headParts.push(`消息数 ${activity.messageCount} 条`);
|
|
76
|
+
const lines = [headParts.join(" · ")];
|
|
77
|
+
const clock = formatClockTime(activity.updatedAt);
|
|
78
|
+
if (clock)
|
|
79
|
+
lines.push(`\uD83D\uDD50 最近写入:${clock}`);
|
|
80
|
+
const last = activity.lastMessage;
|
|
81
|
+
if (last && last.content) {
|
|
82
|
+
const role = last.role ? `[${last.role}] ` : "";
|
|
83
|
+
lines.push(`\uD83D\uDCAC 最近消息:${role}${last.content}`);
|
|
84
|
+
} else {
|
|
85
|
+
lines.push("\uD83D\uDCAC 最近消息:(暂无文本消息)");
|
|
86
|
+
}
|
|
87
|
+
return lines;
|
|
88
|
+
}
|
|
89
|
+
function formatActivityQuote(activity, now, terminal = false) {
|
|
90
|
+
const live = resolveActivityLiveness(activity, now, terminal);
|
|
91
|
+
if (!activity) {
|
|
92
|
+
return {
|
|
93
|
+
title: "⚡ 子会话活性",
|
|
94
|
+
text: "❔ 暂无数据(子会话已归档或未落盘)",
|
|
95
|
+
overflow: false
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const agoPhrase = live.agoText ? `(${live.agoText}有写入)` : "";
|
|
99
|
+
const head = `${live.dot} ${live.label}${agoPhrase} · 消息数 ${activity.messageCount} 条`;
|
|
100
|
+
const last = activity.lastMessage;
|
|
101
|
+
const role = last?.role ? `[${last.role}] ` : "";
|
|
102
|
+
const body = last?.content ? `${role}${truncateActivityMessage(last.content, 80)}` : "(暂无文本消息)";
|
|
103
|
+
const text = `${head}
|
|
104
|
+
\uD83D\uDCAC ${body}`;
|
|
105
|
+
const overflow = text.length > 112;
|
|
106
|
+
return { title: "⚡ 子会话活性", text, overflow };
|
|
107
|
+
}
|
|
108
|
+
function findBackgroundTaskByAssociatedTaskId(tasks, taskId) {
|
|
109
|
+
if (!tasks || tasks.length === 0)
|
|
110
|
+
return;
|
|
111
|
+
if (!Number.isFinite(taskId))
|
|
112
|
+
return;
|
|
113
|
+
let found;
|
|
114
|
+
for (const t of tasks) {
|
|
115
|
+
if (!t || typeof t.subSessionId !== "string" || !t.subSessionId)
|
|
116
|
+
continue;
|
|
117
|
+
if (t.associatedTaskId === taskId)
|
|
118
|
+
found = t;
|
|
119
|
+
}
|
|
120
|
+
return found;
|
|
121
|
+
}
|
|
122
|
+
function createSessionActivityProbe(ports) {
|
|
123
|
+
return async (sessionId) => {
|
|
124
|
+
if (!sessionId)
|
|
125
|
+
return { activity: undefined, terminal: false };
|
|
126
|
+
let session;
|
|
127
|
+
try {
|
|
128
|
+
session = await ports.getSession?.(sessionId);
|
|
129
|
+
} catch {
|
|
130
|
+
session = undefined;
|
|
131
|
+
}
|
|
132
|
+
if (!session)
|
|
133
|
+
return { activity: undefined, terminal: false };
|
|
134
|
+
let lastMessage;
|
|
135
|
+
try {
|
|
136
|
+
lastMessage = await ports.getLastMessage?.(sessionId);
|
|
137
|
+
} catch {
|
|
138
|
+
lastMessage = undefined;
|
|
139
|
+
}
|
|
140
|
+
let lifecycle = "running";
|
|
141
|
+
try {
|
|
142
|
+
lifecycle = await ports.getLifecycle?.(sessionId) ?? "running";
|
|
143
|
+
} catch {
|
|
144
|
+
lifecycle = "running";
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
lifecycle,
|
|
148
|
+
terminal: lifecycle !== "running",
|
|
149
|
+
activity: {
|
|
150
|
+
subSessionId: sessionId,
|
|
151
|
+
messageCount: typeof session.messageCount === "number" ? session.messageCount : 0,
|
|
152
|
+
updatedAt: typeof session.updatedAt === "number" ? session.updatedAt : Number.NaN,
|
|
153
|
+
...lastMessage ? { lastMessage } : {}
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function createActivityProbe(ports) {
|
|
159
|
+
return async (taskId) => {
|
|
160
|
+
let terminal = false;
|
|
161
|
+
try {
|
|
162
|
+
terminal = await ports.isTerminalTask?.(taskId) ?? false;
|
|
163
|
+
} catch {
|
|
164
|
+
terminal = false;
|
|
165
|
+
}
|
|
166
|
+
let task;
|
|
167
|
+
try {
|
|
168
|
+
task = findBackgroundTaskByAssociatedTaskId(ports.listBackgroundTasks?.(), taskId);
|
|
169
|
+
} catch {
|
|
170
|
+
task = undefined;
|
|
171
|
+
}
|
|
172
|
+
if (!task)
|
|
173
|
+
return { activity: undefined, terminal };
|
|
174
|
+
let stats;
|
|
175
|
+
try {
|
|
176
|
+
stats = await ports.getSubSessionActivity?.(task.id);
|
|
177
|
+
} catch {
|
|
178
|
+
stats = undefined;
|
|
179
|
+
}
|
|
180
|
+
if (!stats)
|
|
181
|
+
return { activity: undefined, terminal };
|
|
182
|
+
let lastMessage;
|
|
183
|
+
try {
|
|
184
|
+
lastMessage = await ports.getLastMessage?.(task.subSessionId);
|
|
185
|
+
} catch {
|
|
186
|
+
lastMessage = undefined;
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
terminal,
|
|
190
|
+
activity: {
|
|
191
|
+
subSessionId: task.subSessionId,
|
|
192
|
+
messageCount: stats.messageCount ?? 0,
|
|
193
|
+
updatedAt: stats.updatedAt,
|
|
194
|
+
...lastMessage ? { lastMessage } : {}
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function toActivityMessage(msg, max = DEFAULT_ACTIVITY_MESSAGE_MAX) {
|
|
200
|
+
if (!msg)
|
|
201
|
+
return;
|
|
202
|
+
let text = msg.content;
|
|
203
|
+
if (!text || text.length === 0) {
|
|
204
|
+
const textParts = [];
|
|
205
|
+
for (const part of msg.parts ?? []) {
|
|
206
|
+
if (part?.type === "text" && typeof part.content === "string") {
|
|
207
|
+
textParts.push(part.content);
|
|
208
|
+
} else if (part?.type === "tool-result" && typeof part.output === "string") {
|
|
209
|
+
textParts.push(part.output);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (textParts.length > 0)
|
|
213
|
+
text = textParts.join(" ");
|
|
214
|
+
}
|
|
215
|
+
const content = truncateActivityMessage(text, max);
|
|
216
|
+
if (!content) {
|
|
217
|
+
if (max === DEFAULT_ACTIVITY_MESSAGE_MAX)
|
|
218
|
+
return;
|
|
219
|
+
return {
|
|
220
|
+
role: typeof msg.role === "string" ? msg.role : "unknown",
|
|
221
|
+
content: "(无文本内容)",
|
|
222
|
+
...typeof msg.timestamp === "number" ? { timestamp: msg.timestamp } : {}
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
role: typeof msg.role === "string" ? msg.role : "unknown",
|
|
227
|
+
content,
|
|
228
|
+
...typeof msg.timestamp === "number" ? { timestamp: msg.timestamp } : {}
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function mapBgTaskStatusToSessionLifecycle(status) {
|
|
232
|
+
switch (status) {
|
|
233
|
+
case "completed":
|
|
234
|
+
return "completed";
|
|
235
|
+
case "timeout":
|
|
236
|
+
case "timed_out":
|
|
237
|
+
return "timeout";
|
|
238
|
+
case "failed":
|
|
239
|
+
case "error":
|
|
240
|
+
return "failed";
|
|
241
|
+
case "stopped":
|
|
242
|
+
case "cancelled":
|
|
243
|
+
case "canceled":
|
|
244
|
+
case "aborted":
|
|
245
|
+
return "stopped";
|
|
246
|
+
default:
|
|
247
|
+
return "running";
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
var RECENT_MESSAGE_LIMIT = 5;
|
|
251
|
+
var RECENT_MESSAGE_MAX = 100;
|
|
252
|
+
function extractToolCallsFromMessages(messages) {
|
|
253
|
+
const calls = [];
|
|
254
|
+
for (const msg of messages ?? []) {
|
|
255
|
+
for (const part of msg?.parts ?? []) {
|
|
256
|
+
if (part?.type !== "tool-call")
|
|
257
|
+
continue;
|
|
258
|
+
const toolName = typeof part.toolName === "string" ? part.toolName : undefined;
|
|
259
|
+
if (!toolName)
|
|
260
|
+
continue;
|
|
261
|
+
let args;
|
|
262
|
+
if (typeof part.arguments === "string") {
|
|
263
|
+
try {
|
|
264
|
+
const parsed = JSON.parse(part.arguments);
|
|
265
|
+
if (parsed && typeof parsed === "object") {
|
|
266
|
+
args = parsed;
|
|
267
|
+
}
|
|
268
|
+
} catch {}
|
|
269
|
+
} else if (part.arguments && typeof part.arguments === "object") {
|
|
270
|
+
args = part.arguments;
|
|
271
|
+
}
|
|
272
|
+
const reason = typeof args?.reason === "string" && args.reason.trim().length > 0 ? args.reason.trim() : undefined;
|
|
273
|
+
calls.push({ toolName, ...reason ? { reason } : {} });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return calls;
|
|
277
|
+
}
|
|
278
|
+
function formatRecentToolCallLines(calls, max = RECENT_MESSAGE_MAX) {
|
|
279
|
+
if (!calls || calls.length === 0) {
|
|
280
|
+
return ["暂无工具调用"];
|
|
281
|
+
}
|
|
282
|
+
return calls.map((c) => {
|
|
283
|
+
const reason = truncateActivityMessage(c?.reason, max) || "—";
|
|
284
|
+
return `- ${c?.toolName ?? "未知"}:${reason}`;
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export { formatActivityLines, formatActivityQuote, createSessionActivityProbe, createActivityProbe, toActivityMessage, mapBgTaskStatusToSessionLifecycle, RECENT_MESSAGE_LIMIT, extractToolCallsFromMessages, formatRecentToolCallLines };
|