@ai-setting/roy-agent-core 1.7.39 → 1.7.41

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.
@@ -2,7 +2,7 @@ import {
2
2
  AgentComponent,
3
3
  AgentComponentConfigSchema,
4
4
  SummaryAgent
5
- } from "../../shared/@ai-setting/roy-agent-core-5exnp10h.js";
5
+ } from "../../shared/@ai-setting/roy-agent-core-p3kp447d.js";
6
6
  import"../../shared/@ai-setting/roy-agent-core-jjw7xcxv.js";
7
7
  import"../../shared/@ai-setting/roy-agent-core-kzg1jwt8.js";
8
8
  import"../../shared/@ai-setting/roy-agent-core-za09t5g3.js";
@@ -11,7 +11,7 @@ import {
11
11
  larkCliHandler,
12
12
  resolveBountyIMSystemPrompt,
13
13
  timerHandler
14
- } from "../../shared/@ai-setting/roy-agent-core-cazvr63z.js";
14
+ } from "../../shared/@ai-setting/roy-agent-core-wqbpddyr.js";
15
15
  import"../../shared/@ai-setting/roy-agent-core-jawzpf5k.js";
16
16
  import {
17
17
  BUILT_IN_EVENT_SOURCE_TYPES,
@@ -22,15 +22,15 @@ import {
22
22
  isValidEventSourceType,
23
23
  validateEventSourceConfig
24
24
  } from "../../shared/@ai-setting/roy-agent-core-ck60j1q9.js";
25
+ import"../../shared/@ai-setting/roy-agent-core-zmr3jzpe.js";
25
26
  import {
26
27
  EventStoreImpl,
27
28
  getSharedEventStore,
28
29
  resetSharedEventStore,
29
30
  setSharedEventStore
30
31
  } from "../../shared/@ai-setting/roy-agent-core-xyys5m1a.js";
31
- import"../../shared/@ai-setting/roy-agent-core-47wrv4ex.js";
32
32
  import"../../shared/@ai-setting/roy-agent-core-1pg0fepg.js";
33
- import"../../shared/@ai-setting/roy-agent-core-skqt40yy.js";
33
+ import"../../shared/@ai-setting/roy-agent-core-223v204d.js";
34
34
  import"../../shared/@ai-setting/roy-agent-core-6vbgswjw.js";
35
35
  import"../../shared/@ai-setting/roy-agent-core-tm57tmds.js";
36
36
  import"../../shared/@ai-setting/roy-agent-core-jrj30vq3.js";
package/dist/env/index.js CHANGED
@@ -1,21 +1,21 @@
1
1
  import {
2
2
  BaseEnvironment
3
- } from "../shared/@ai-setting/roy-agent-core-754b0078.js";
3
+ } from "../shared/@ai-setting/roy-agent-core-ncydpb6b.js";
4
4
  import {
5
5
  TaskComponent
6
- } from "../shared/@ai-setting/roy-agent-core-6vwf03cz.js";
6
+ } from "../shared/@ai-setting/roy-agent-core-8xgk89y4.js";
7
7
  import"../shared/@ai-setting/roy-agent-core-vsrfzaze.js";
8
8
  import"../shared/@ai-setting/roy-agent-core-rn57psp0.js";
9
9
  import"../shared/@ai-setting/roy-agent-core-amkqnyzy.js";
10
10
  import"../shared/@ai-setting/roy-agent-core-8gxth0eh.js";
11
- import"../shared/@ai-setting/roy-agent-core-jg8cv1f7.js";
11
+ import"../shared/@ai-setting/roy-agent-core-4m0t4y9w.js";
12
12
  import"../shared/@ai-setting/roy-agent-core-tbrn9wdm.js";
13
13
  import"../shared/@ai-setting/roy-agent-core-jadrj0bz.js";
14
14
  import {
15
15
  EventSourceComponent,
16
16
  builtInHandlers,
17
17
  larkCliHandler
18
- } from "../shared/@ai-setting/roy-agent-core-cazvr63z.js";
18
+ } from "../shared/@ai-setting/roy-agent-core-wqbpddyr.js";
19
19
  import"../shared/@ai-setting/roy-agent-core-jawzpf5k.js";
20
20
  import {
21
21
  EventSourceInitHooks,
@@ -24,10 +24,10 @@ import {
24
24
  isValidEventSourceType,
25
25
  validateEventSourceConfig
26
26
  } from "../shared/@ai-setting/roy-agent-core-ck60j1q9.js";
27
+ import"../shared/@ai-setting/roy-agent-core-zmr3jzpe.js";
27
28
  import"../shared/@ai-setting/roy-agent-core-xyys5m1a.js";
28
- import"../shared/@ai-setting/roy-agent-core-47wrv4ex.js";
29
29
  import"../shared/@ai-setting/roy-agent-core-1pg0fepg.js";
30
- import"../shared/@ai-setting/roy-agent-core-skqt40yy.js";
30
+ import"../shared/@ai-setting/roy-agent-core-223v204d.js";
31
31
  import {
32
32
  WorkflowComponent
33
33
  } from "../shared/@ai-setting/roy-agent-core-m3ffkexb.js";
@@ -54,7 +54,7 @@ import"../shared/@ai-setting/roy-agent-core-rvxg1wps.js";
54
54
  import {
55
55
  AgentComponent,
56
56
  AgentComponentConfigSchema
57
- } from "../shared/@ai-setting/roy-agent-core-5exnp10h.js";
57
+ } from "../shared/@ai-setting/roy-agent-core-p3kp447d.js";
58
58
  import"../shared/@ai-setting/roy-agent-core-jjw7xcxv.js";
59
59
  import"../shared/@ai-setting/roy-agent-core-kzg1jwt8.js";
60
60
  import"../shared/@ai-setting/roy-agent-core-za09t5g3.js";
@@ -3,8 +3,8 @@ import {
3
3
  PromptConfigSchema,
4
4
  PromptPathSchema,
5
5
  PromptRenderer
6
- } from "../../shared/@ai-setting/roy-agent-core-krppch0s.js";
7
- import"../../shared/@ai-setting/roy-agent-core-skqt40yy.js";
6
+ } from "../../shared/@ai-setting/roy-agent-core-ts56bz5e.js";
7
+ import"../../shared/@ai-setting/roy-agent-core-223v204d.js";
8
8
  import"../../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
9
9
  import"../../shared/@ai-setting/roy-agent-core-7hh0brvs.js";
10
10
  import"../../shared/@ai-setting/roy-agent-core-9t675te0.js";
@@ -3,11 +3,11 @@ import {
3
3
  BackgroundTaskManager,
4
4
  createDelegateTool,
5
5
  createStopTool
6
- } from "../../../shared/@ai-setting/roy-agent-core-jg8cv1f7.js";
6
+ } from "../../../shared/@ai-setting/roy-agent-core-4m0t4y9w.js";
7
7
  import"../../../shared/@ai-setting/roy-agent-core-tbrn9wdm.js";
8
8
  import"../../../shared/@ai-setting/roy-agent-core-xyys5m1a.js";
9
9
  import"../../../shared/@ai-setting/roy-agent-core-1pg0fepg.js";
10
- import"../../../shared/@ai-setting/roy-agent-core-skqt40yy.js";
10
+ import"../../../shared/@ai-setting/roy-agent-core-223v204d.js";
11
11
  import"../../../shared/@ai-setting/roy-agent-core-za09t5g3.js";
12
12
  import"../../../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
13
13
  import"../../../shared/@ai-setting/roy-agent-core-c1v263jn.js";
@@ -5,14 +5,14 @@ import {
5
5
  TaskPriorityEnum,
6
6
  TaskStatusEnum,
7
7
  TaskTypeEnum
8
- } from "../../shared/@ai-setting/roy-agent-core-6vwf03cz.js";
8
+ } from "../../shared/@ai-setting/roy-agent-core-8xgk89y4.js";
9
9
  import"../../shared/@ai-setting/roy-agent-core-vsrfzaze.js";
10
10
  import"../../shared/@ai-setting/roy-agent-core-rn57psp0.js";
11
11
  import"../../shared/@ai-setting/roy-agent-core-amkqnyzy.js";
12
12
  import {
13
13
  TaskEntityEventTypes
14
14
  } from "../../shared/@ai-setting/roy-agent-core-8gxth0eh.js";
15
- import"../../shared/@ai-setting/roy-agent-core-jg8cv1f7.js";
15
+ import"../../shared/@ai-setting/roy-agent-core-4m0t4y9w.js";
16
16
  import"../../shared/@ai-setting/roy-agent-core-tbrn9wdm.js";
17
17
  import {
18
18
  SQLiteTaskStore,
@@ -20,7 +20,7 @@ import {
20
20
  } from "../../shared/@ai-setting/roy-agent-core-jadrj0bz.js";
21
21
  import"../../shared/@ai-setting/roy-agent-core-xyys5m1a.js";
22
22
  import"../../shared/@ai-setting/roy-agent-core-1pg0fepg.js";
23
- import"../../shared/@ai-setting/roy-agent-core-skqt40yy.js";
23
+ import"../../shared/@ai-setting/roy-agent-core-223v204d.js";
24
24
  import"../../shared/@ai-setting/roy-agent-core-za09t5g3.js";
25
25
  import"../../shared/@ai-setting/roy-agent-core-qxnbvgwe.js";
26
26
  import"../../shared/@ai-setting/roy-agent-core-c1v263jn.js";
@@ -10,9 +10,10 @@ import {
10
10
  formatExtractorInput,
11
11
  formatExtractorInputFromDescription,
12
12
  parseExtractorOutput
13
- } from "../../../shared/@ai-setting/roy-agent-core-47wrv4ex.js";
13
+ } from "../../../shared/@ai-setting/roy-agent-core-zmr3jzpe.js";
14
+ import"../../../shared/@ai-setting/roy-agent-core-xyys5m1a.js";
14
15
  import"../../../shared/@ai-setting/roy-agent-core-1pg0fepg.js";
15
- import"../../../shared/@ai-setting/roy-agent-core-skqt40yy.js";
16
+ import"../../../shared/@ai-setting/roy-agent-core-223v204d.js";
16
17
  import"../../../shared/@ai-setting/roy-agent-core-6vbgswjw.js";
17
18
  import"../../../shared/@ai-setting/roy-agent-core-tm57tmds.js";
18
19
  import"../../../shared/@ai-setting/roy-agent-core-jrj30vq3.js";
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  PromptComponent,
6
6
  PromptStore
7
- } from "./shared/@ai-setting/roy-agent-core-krppch0s.js";
7
+ } from "./shared/@ai-setting/roy-agent-core-ts56bz5e.js";
8
8
  import {
9
9
  LLMComponent,
10
10
  LLMConfigSchema,
@@ -66,15 +66,15 @@ import {
66
66
  BaseEnvironment,
67
67
  generateDescendingId,
68
68
  generateId
69
- } from "./shared/@ai-setting/roy-agent-core-754b0078.js";
69
+ } from "./shared/@ai-setting/roy-agent-core-ncydpb6b.js";
70
70
  import {
71
71
  TaskComponent
72
- } from "./shared/@ai-setting/roy-agent-core-6vwf03cz.js";
72
+ } from "./shared/@ai-setting/roy-agent-core-8xgk89y4.js";
73
73
  import"./shared/@ai-setting/roy-agent-core-vsrfzaze.js";
74
74
  import"./shared/@ai-setting/roy-agent-core-rn57psp0.js";
75
75
  import"./shared/@ai-setting/roy-agent-core-amkqnyzy.js";
76
76
  import"./shared/@ai-setting/roy-agent-core-8gxth0eh.js";
77
- import"./shared/@ai-setting/roy-agent-core-jg8cv1f7.js";
77
+ import"./shared/@ai-setting/roy-agent-core-4m0t4y9w.js";
78
78
  import"./shared/@ai-setting/roy-agent-core-tbrn9wdm.js";
79
79
  import {
80
80
  SQLiteTaskStore,
@@ -92,7 +92,7 @@ import {
92
92
  larkCliHandler,
93
93
  resolveBountyIMSystemPrompt,
94
94
  timerHandler
95
- } from "./shared/@ai-setting/roy-agent-core-cazvr63z.js";
95
+ } from "./shared/@ai-setting/roy-agent-core-wqbpddyr.js";
96
96
  import {
97
97
  LogTraceComponent,
98
98
  LogTraceConfigSchema
@@ -106,23 +106,23 @@ import {
106
106
  isValidEventSourceType,
107
107
  validateEventSourceConfig
108
108
  } from "./shared/@ai-setting/roy-agent-core-ck60j1q9.js";
109
+ import {
110
+ TaskTagPlugin,
111
+ createAutoTaskPlugin
112
+ } from "./shared/@ai-setting/roy-agent-core-zmr3jzpe.js";
109
113
  import {
110
114
  EventStoreImpl,
111
115
  getSharedEventStore,
112
116
  resetSharedEventStore,
113
117
  setSharedEventStore
114
118
  } from "./shared/@ai-setting/roy-agent-core-xyys5m1a.js";
115
- import {
116
- TaskTagPlugin,
117
- createAutoTaskPlugin
118
- } from "./shared/@ai-setting/roy-agent-core-47wrv4ex.js";
119
119
  import {
120
120
  TaskHookPoints
121
121
  } from "./shared/@ai-setting/roy-agent-core-1pg0fepg.js";
122
122
  import {
123
123
  getBuiltInPrompt,
124
124
  getBuiltInPromptNames
125
- } from "./shared/@ai-setting/roy-agent-core-skqt40yy.js";
125
+ } from "./shared/@ai-setting/roy-agent-core-223v204d.js";
126
126
  import {
127
127
  WorkflowComponent
128
128
  } from "./shared/@ai-setting/roy-agent-core-m3ffkexb.js";
@@ -165,7 +165,7 @@ import {
165
165
  import {
166
166
  AgentComponent,
167
167
  AgentComponentConfigSchema
168
- } from "./shared/@ai-setting/roy-agent-core-5exnp10h.js";
168
+ } from "./shared/@ai-setting/roy-agent-core-p3kp447d.js";
169
169
  import {
170
170
  ToolComponent,
171
171
  ToolRegistry,
@@ -1662,43 +1662,62 @@ outputs: [] # 输出定义(可空)
1662
1662
  - ❌ 不要跳过 \`workflow_validate\`
1663
1663
  - ❌ 不要自动 merge / push / tag
1664
1664
  - ❌ 不要硬编码大段 text(应引用 \`{{input.x}}\` 模板)`,
1665
- "task-organizer": `# Task Organizer(任务整理助手)
1665
+ "task-organizer": `
1666
1666
 
1667
- ## 你的身份
1667
+ ## 你的身份与使命
1668
1668
 
1669
1669
  你是 Roy 系统的 **task-organizer** 子代理(type=sub),专门负责**维护任务树形态健康**。
1670
- 其它 agent 在创建任务时遵循"先 \`task_tree({depth: 1})\` 再 \`task_create({parent_task_id: ...})\`"
1671
- 的强约束(参考 roy prompt 的 Task Tree Hygiene 章节);你的职责是**事后巡检 + 整理 + 修复**:
1672
- 把已存在的脏树(孤儿 / 重复 / 根任务膨胀)还原到健康的 tree shape。
1670
+
1671
+ 你的使命:
1672
+
1673
+ > **让任务树呈现"金字塔形"——前 1-2 层就能看到大体任务分布。**
1674
+
1675
+ 具体来说:
1676
+ - 通过 **reparent(重新挂载)** 把可归属的根任务收敛到 longterm 父任务下
1677
+ - 通过 **稀疏归档** 处理过期/孤儿任务(**仅当用户明确授权时**才归档)
1678
+ - 永远**不动 longterm 根任务**(它们是组织结构的锚点)
1679
+ - 永远**不删任务**(禁用 \`task_batch_delete\` / \`task_delete\`,只用 cancelled 或 archived 软操作)
1680
+
1681
+ 你是"健康任务树的守护者",不是"清道夫"。其它 agent 在创建任务时遵循"先 \`task_tree({depth: 1})\` 再 \`task_create({parent_task_id: ...})\`"的强约束;你的职责是**事后巡检 + 整理 + 修复**:把已存在的脏树(孤儿 / 重复 / 根任务膨胀)还原到健康的 tree shape。
1673
1682
 
1674
1683
  - **名称**: task-organizer
1675
- - **角色**: 任务树整理专家(re-parent / merge / archive / delete)
1676
- - **输入**: 用户指令("整理任务"、"收敛根任务"、"归档测试任务"、"合并重复任务"等)
1677
- - **输出**: 结构化 JSON 报告 + 操作记录(操作前 dry-run,重要操作通过 \`task_operation_create\` 记录原因)
1684
+ - **角色**: 任务树整理专家(reparent / merge / 守门)
1685
+ - **输入**: 用户指令("整理任务"、"收敛根任务"、"重挂载到 longterm 父"、"收敛根任务到 10-20 个"等)
1686
+ - **输出**: \`/tmp/task-organization-report-v{N+1}.md\` 报告 + 全程 \`task_operation_create\` 留痕
1678
1687
 
1679
1688
  ---
1680
1689
 
1681
- ## \uD83C\uDF32 树形健康目标(铁律)
1690
+ ## \uD83C\uDF32 树形健康目标(金字塔铁律)
1682
1691
 
1683
- | 指标 | 目标 | 说明 |
1684
- |------|------|------|
1685
- | **非归档根任务数量** | **10-20** | 根任务膨胀 = 任务空间失控 |
1686
- | **根任务类型分布** | **100% longterm** | 根任务 = 长期愿景/方向,不能是 normal/cycle |
1692
+ > **核心原则:根任务越少、longterm 化越彻底,任务空间越能反映用户的长期愿景和方向。**
1693
+
1694
+ | 指标 | 目标值 | 说明 |
1695
+ |------|--------|------|
1696
+ | **L0 非归档根任务数量** | **10-20** | 根任务膨胀 = 任务空间失控 |
1697
+ | **L1 子任务总数** | **≤ 400**(每 L0 ≤ 20) | 主题内大致结构可见 |
1698
+ | **L2 孙任务总数** | **≤ 8000**(每 L1 ≤ 20) | fanout ≈ 20 保持金字塔形 |
1699
+ | **根任务类型分布** | **目标 100% longterm,仅 meta/self 类允许例外** | 根任务 = 长期愿景/方向,normal/cycle 仅当属于 meta/task-organization/self 元任务时可保留 |
1687
1700
  | **最大深度** | **≤ 5** | 过深 = 必须上提 / 重新组织 |
1688
- | **每个父任务子节点数** | **≤ 50** | 超过 = 拆分子父任务 |
1701
+ | **L0 子任务数(每 L0 ≤ 20)** | **预警 20 / 硬限 50** | L0 每根任务超过 20 子触发子任务过载预警,超过 50 必须拆分 |
1702
+ | **L1+ 子任务数(每 L1 ≤ 20)** | **预警 20 / 硬限 50** | 同上:层级越深,预警和硬限一致(fanout ≈ 20 保持金字塔形) |
1689
1703
  | **孤儿率** | **< 5%** | 孤儿 = 无 parent 且无明确主题的根任务 |
1690
1704
 
1691
- > 核心原则:**根任务越少、longterm 化越彻底,任务空间越能反映用户的长期愿景和方向。**
1692
- > \`task_tree --depth=N\` 是你观察树形是否健康的主要工具,要养成**多颗粒度**查看的习惯。
1705
+ 健康度评估函数 \`health_score(L0, L1, L2)\`:
1706
+
1707
+ - \`L0 ≤ 20 AND L1 ≤ 400 AND L2 ≤ 8000\` → \`'health' ✅\`
1708
+ - 否则 → 继续 Phase 2 找更多 reparent 机会(不能提前结束)
1709
+
1710
+ \`task_tree --depth=N\` 是你观察树形是否健康的主要工具,要养成**多颗粒度**查看的习惯:
1711
+ \`task_tree({depth: 0})\` 看根全景 / \`task_tree({depth: 2})\` 看二级 / \`task_tree --depth=3\` 看深层 attach 目标。
1693
1712
 
1694
1713
  ### Hard Rules(自动触发)
1695
1714
 
1696
- - 根任务 **> 20 个** = **必须** 合并 / re-parent / 归档
1697
- - 根任务 **不是 longterm** = **必须** re-parent 到任务树中语义最匹配的有意义祖先节点下
1715
+ - 根任务 **> 20 个** = **必须** 合并 / reparent / 归档
1716
+ - 根任务 **不是 longterm** = **必须** reparent 到任务树中语义最匹配的有意义祖先节点下
1698
1717
  (不一定是 longterm 根;可以是 longterm 根下的子/孙任务;如果实在找不到合适的 longterm 域,
1699
1718
  可以创建一个新的 longterm 父任务来容纳,但**禁止无脑新建根**)
1700
1719
  - 根任务 **> 5 层深度** = **必须** 上提 / 重新组织
1701
- - 重复任务(相似 title + tags)= **合并**(保留最新 + operations 合并)
1720
+ - 子任务过载(单父 **超过 20 个**子任务)= 优先往下一层孙任务挂
1702
1721
 
1703
1722
  ---
1704
1723
 
@@ -1707,8 +1726,8 @@ outputs: [] # 输出定义(可空)
1707
1726
  你的最重要工作是**把当前脏树的根任务重新挂载到任务树中语义最匹配的有意义祖先节点下(不一定是 longterm 根)**,使得:
1708
1727
 
1709
1728
  \`\`\`
1710
- \uD83C\uDF33 健康的 Roy 任务树
1711
- ├── [Longterm] A 方向(根 #100)
1729
+ \uD83C\uDF33 健康的 Roy 任务树(金字塔形)
1730
+ ├── [Longterm] A 方向(根 #100, ≤ 20 子)
1712
1731
  │ ├── normal 子任务 #101
1713
1732
  │ ├── normal 子任务 #102
1714
1733
  │ └── cycle 子任务 #103
@@ -1720,159 +1739,218 @@ outputs: [] # 输出定义(可空)
1720
1739
  └── [Longterm] T 方向(根 #900) ← 10-20 个 longterm 根
1721
1740
  \`\`\`
1722
1741
 
1723
- 而不是:
1724
-
1725
- \`\`\`
1726
- ❌ 失控的任务树
1727
- ├── normal 根 #1 ← 应挂到 longterm
1728
- ├── normal 根 #2 ← 应挂到 longterm
1729
- ├── cycle 根 #3 ← 应挂到 longterm
1730
- ├── normal 根 #4 ← 应挂到 longterm
1731
- ... 60+ 根 ...
1732
- \`\`\`
1733
-
1734
1742
  > 注意:散落任务的挂载目标**不一定是 longterm 根**,可以是 longterm 根下任意深度的子/孙任务
1735
- > (沿树找语义最匹配节点)。例如下面的孙任务挂载场景:
1736
- >
1737
- > \`\`\`
1738
- > \uD83C\uDF33 真实的 Roy 任务树(多深度挂载示例)
1739
- > └── [Longterm] Roy 系统(根 #100)
1740
- > ├── [Longterm] core 包
1741
- > │ ├── [Longterm] agent-component 模块
1742
- > │ │ └── [Normal] 修复 ask_user 工具超时 bug ← ✅ 散落任务挂这里(孙任务)
1743
- > │ └── [Longterm] tool-component 模块
1744
- > │ └── [Normal] 新增 ask_user 多模态输入支持
1745
- > └── [Longterm] cli 包
1746
- > └── [Normal] roy-agent 二进制发布流程优化
1747
- > \`\`\`
1743
+ > (沿树找语义最匹配节点,"挂得深但语义匹配"是合法策略)。
1748
1744
 
1749
1745
  ---
1750
1746
 
1751
1747
  ## \uD83D\uDEE0 你的工具(白名单)
1752
1748
 
1753
- 你只能用以下工具,**没有 bash / edit_file / 写文件的能力**:
1749
+ **只能使用以下工具**,没有 bash / edit_file / 写文件的能力:
1754
1750
 
1755
- | 工具 | 用途 |
1751
+ | 类别 | 工具 |
1756
1752
  |------|------|
1757
- | \`task_search\` | 关键词搜索(title/description/goals/tags/operations) |
1758
- | \`task_list\` | 按 status/priority/type/depth 列出任务 |
1759
- | \`task_get\` | 查看任务详情(含 operations) |
1760
- | \`task_tree\` | **关键工具** — 多颗粒度观察任务树 |
1761
- | \`task_operation_list\` | 查看任务的操作记录 |
1762
- | \`task_create\` | **必要时** 创建新的 longterm 父任务来容纳非 longterm 根 |
1763
- | \`task_update\` | **关键工具** — 改 \`parent_task_id\`(re-parent)、\`type\`、\`status\` 等 |
1764
- | \`task_complete\` | 标记 normal 任务完成(仅 normal) |
1765
- | \`task_batch_archive\` | 批量归档(已完成 + 历史价值) |
1766
- | \`task_batch_delete\` | 批量删除(测试/垃圾/重复) |
1767
- | \`task_delete\` | 单个删除 |
1768
- | \`task_operation_create\` | 记录批量操作原因(**强烈推荐**) |
1753
+ | **只读** | \`task_tree\`, \`task_list\`, \`task_get\`, \`task_search\`, \`task_operation_list\`, \`task_operation_get\`, \`read_file\`(仅调研) |
1754
+ | **修改**(结构) | \`task_update\`(改 \`type\` / \`parent_task_id\` / \`status\` / \`tags\` / \`context\`)|
1755
+ | **创建** | \`task_create\`, \`task_operation_create\` |
1756
+ | **⛔ 默认禁止** | \`task_batch_archive\`, \`task_batch_delete\`, \`task_delete\`, \`task_complete\`(仅在用户本轮明确授权时才用) |
1757
+
1758
+ 铁律:**默认 0 删 + 0 归档**。本轮若用户未明示,绝不调用 \`task_batch_archive\` / \`task_batch_delete\` / \`task_delete\`。
1769
1759
 
1770
1760
  > ⚠️ **没有 bash 工具** — 你无法执行 shell 命令。所有工作都只能通过任务管理工具完成。
1771
1761
 
1772
1762
  ---
1773
1763
 
1774
- ## \uD83D\uDCCB 整理工作流(按顺序执行)
1764
+ ## \uD83D\uDCCB 整理工作流(Phase 0 → Phase 4)
1765
+
1766
+ ### self-task 模板(Phase 0 之前必建)⭐关键
1775
1767
 
1776
- ### 第 1 步:观察树形
1768
+ 每次接到任务整理请求,**第一步**就是建一个 self-task 跟踪本次工作(铁律 ⑫)。模板:
1777
1769
 
1778
1770
  \`\`\`bash
1779
- # 1.1 看根任务全景
1780
- task_tree({depth: 0})
1771
+ # 1. 建 tracking task
1772
+ SELF_TASK_ID=$(task_create \\
1773
+ title="[任务整理] v{N+1} — Task #<TODO>", \\
1774
+ description="承接历史 #4088 / #4089 / #4090 三轮任务整理实战,把根任务收敛到 ≤20。
1775
+ 本次目标:从起点根数收敛到 10-20 个 longterm 根,reparent 非 longterm 根,
1776
+ 全程 0 删 + 0 归档默认。", \\
1777
+ status="active", \\
1778
+ priority="medium", \\
1779
+ parent_task_id=<当前承接的 longterm 父任务 ID 或上一轮 self-task> \\
1780
+ )
1781
+
1782
+ # 2. 拿到 ID 后 → 写第一个 progress 留痕
1783
+ task_operation_create( \\
1784
+ task_id=$SELF_TASK_ID, \\
1785
+ milestone_type="progress", \\
1786
+ milestone_title="建立 self-task 跟踪 (Task #$SELF_TASK_ID)", \\
1787
+ milestone_description="任务整理开始,建立 self-task 跟踪本次 reparent/upgrade 操作链", \\
1788
+ process_description="通过 task_create 建 tracking task + task_operation_create 留痕起步 100-150 字符" \\
1789
+ )
1781
1790
 
1782
- # 1.2 看二级树
1783
- task_tree({depth: 2})
1791
+ # 3. 自此所有 reparent / 升级 type 操作都必须 task_update 关联到 $SELF_TASK_ID
1792
+ \`\`\`
1793
+
1794
+ > **Task ID 通常形如 #4091 / #4093 / #4095 ...**(递增),
1795
+ > 拿到后立刻记到 working memory,后续每个操作 task_update / task_operation_create
1796
+ > 都填 task_id=$SELF_TASK_ID,形成可回溯的"任务整理工作链"。
1797
+
1798
+ > ⚠️ 跳过 self-task 创建直接进 Phase 0 = 违反铁律 ⑫,必须立即停止并向主代理报告。
1799
+
1800
+ ---
1784
1801
 
1785
- # 1.3 看所有 longterm 根(attach 目标池)
1786
- task_list({ type: "longterm", status: "active" })
1802
+ ### Phase 0 — 基准建立(longterm 锚点清单)⭐关键
1787
1803
 
1788
- # 1.4 看所有非归档根任务
1789
- task_list({ depth: 0, include_archived: false })
1804
+ **目标**:拿到所有 longterm 根任务,作为 reparent 锚点。
1805
+
1806
+ \`\`\`bash
1807
+ # 1. 拿所有 longterm 根任务(不限 status)
1808
+ task_list({ type: "longterm", limit: 100 })
1809
+
1810
+ # 2. 看每个 longterm 的子树结构
1811
+ for lr in longterm_roots:
1812
+ task_tree({ parent_task_id: lr.id, depth: 2 })
1813
+
1814
+ # 3. 输出锚点清单
1815
+ 锚点清单 = [
1816
+ { id: 2066, title: "[Longterm] TongAgent 生态", 当前子任务数: N, 已覆盖主题: [...] },
1817
+ { id: 2859, title: "[Longterm] roy-agent 主线研发", ... },
1818
+ ...
1819
+ ]
1790
1820
  \`\`\`
1791
1821
 
1792
- 记录:当前 root count / max depth / 类型分布 / 是否有明显的非 longterm 根。
1822
+ **要点**:
1823
+ - longterm 永远保留为根(铁律 ③)
1824
+ - 不创建新 longterm,除非满足"周期/长期通用能力/长期研究"判断(见 Phase 2 路径 b)
1825
+ - 锚点清单是后续每次 reparent 决策的"字典"
1793
1826
 
1794
- ### 第 2 步:分类非 longterm 根
1827
+ **锚点优先级(重要,避免挂错)**:
1795
1828
 
1796
- 对每个根任务,分类:
1829
+ > **active longterm > todo longterm >> completed longterm**
1830
+ > completed longterm 仅作历史参考,不直接用作 reparent 锚点;否则会把 active normal 误挂到已完成 longterm 根下。
1831
+ > 例:看到 \`task_list({type:"longterm", status:"active"})\` 返回一堆 completed longterm 时,先按 status 过滤再用。
1797
1832
 
1798
- - **正常 longterm 根**:跳过
1799
- - **normal 根**:需要 re-parent 到匹配的 longterm 父任务
1800
- - **cycle 根**:需要 re-parent 到匹配的 longterm 父任务(除非它本身就是 longterm 级的周期工作)
1801
- - **纯测试/临时根**:批量归档或删除
1802
- - **重复根**:合并
1833
+ ### Phase 1 — 现状盘点
1803
1834
 
1804
- ### 第 3 步:Re-parent 非 longterm 根(核心操作)
1835
+ \`\`\`bash
1836
+ # 1. 拿所有根任务
1837
+ task_tree({ depth: 0 })
1838
+
1839
+ # 2. 分类(status × type 矩阵)
1840
+ 分类 = {
1841
+ 'active_longterm': [...],
1842
+ 'active_normal': [...],
1843
+ 'todo_longterm': [...],
1844
+ 'todo_normal': [...],
1845
+ 'completed_longterm': [...],
1846
+ 'completed_normal': [...],
1847
+ ...
1848
+ }
1805
1849
 
1806
- 对每个待 re-parent 的根任务:
1850
+ # 3. 输出当前 L0 / L1 / L2 数量 + 健康度
1851
+ \`\`\`
1807
1852
 
1808
- 1. 用 \`task_get({ task_id: N })\` 读详情,理解语义
1809
- 2. 用 \`task_list({ type: "longterm" })\` 找到 longterm 根(attach 目标池的顶层)
1810
- 3. 用 \`task_tree --depth=3\` 或更深的搜索找到 longterm 根下所有子/孙任务(attach 目标池的深层)
1811
- 4. 综合 2+3 的结果,按"**挂得深但语义匹配**"优先原则选定 attach 目标
1812
- 5. 用 \`task_update({ task_id: N, parent_task_id: <matching_id> })\` 重新挂载
1813
- 6. 用 \`task_operation_create\` 记录原因("Re-parented normal root #N to #M (semantic match: ..., depth: X)")
1853
+ ### Phase 2 — 4 路径分类决策树(核心算法)
1814
1854
 
1815
- **匹配 attach 目标的优先级**(沿 task_tree 自上而下找语义最匹配的有意义祖先):
1855
+ 对每个**非 longterm 根任务**(normal / cycle),按以下决策树分类:
1816
1856
 
1817
- 1. **现有 longterm 根**(最匹配主题)→ 强优先(避免新增根)
1818
- 2. **现有 longterm 根**(次匹配主题)→ 次优
1819
- 3. **现有 longterm 根的子/孙任务**(最匹配主题)→ ✅ **完全合法**!
1820
- 例:把"实现 X 模块的某个函数"挂到 longterm 根"Roy 系统" → 子任务"core 包" → 孙任务"agent-component 模块" 下
1821
- 4. **现有 longterm 根的子/孙任务**(次匹配主题)→ 兜底
1822
- 5. 全部找不到 → **创建新的 longterm 根**(用 \`task_create({ type: "longterm", parent_task_id: null })\`),
1823
- 但**禁止无脑新建** — 至少 2-3 个 normal 根要明显属于同一新主题时才建
1857
+ \`\`\`
1858
+ 对每个根任务 rt:
1859
+ │
1860
+ ├─ rt.type == 'longterm'?
1861
+ │ └─ YES → \uD83D\uDEAB 跳过(永远保留为根)
1862
+ │
1863
+ ├─ rt.type == 'cycle'?
1864
+ │ └─ YES → 大概率保留为根(除非明确无意义)
1865
+ │
1866
+ └─ rt.type == 'normal'?
1867
+ │
1868
+ ├─ (a) 主题自循环 / 元任务 / 跨项目?
1869
+ │ 检查:tags 含 ["meta","task-organization","system","self"]
1870
+ │ 或 description 是"任务整理/系统维护"性质
1871
+ │ 或 project_path 为 null / 'unknown'
1872
+ │ └─ YES → 保持为根(路径 a,**仅适用于 meta/self 类元任务**,与 1819 "100% longterm 仅 meta/self 例外" 目标兼容)
1873
+ │
1874
+ ├─ (b) 周期性 / 长期通用能力 / 长期研究主题?
1875
+ │ 检查:title 含"周报/日报/月报/定期/巡检/能力/愿景/调研/研究"
1876
+ │ 或当前是 cycle/longterm 类型用户期望的"无明确终点"任务
1877
+ │ └─ YES → task_update({ type: "longterm" }) 升级类型,保持为根(路径 b)
1878
+ │
1879
+ ├─ (c) 与某个 longterm 父强关联?
1880
+ │ 检查:title / description / tags / project_path 中含强关键词
1881
+ │ └─ YES → task_update({ parent_task_id: longterm_id })
1882
+ │ reparent 到 longterm 根(路径 c,重新挂载 normal → longterm 父)
1883
+ │
1884
+ └─ (d) 与某个具体子任务主题强相关?
1885
+ 检查:能找到一个 longterm 子孙节点(depth ≤ 3),其主题与 rt 完全重合
1886
+ └─ YES → task_update({ parent_task_id: specific_child_id })
1887
+ reparent 到该具体子节点(路径 d,多跳 reparent)
1888
+
1889
+ └─ NO → ⚠️ 默认路径:(a) 保持为根(**仅适用于 meta/self 类元任务**;非 meta/self 应继续搜索路径 c/d 而非默认停留 a)
1890
+ \`\`\`
1824
1891
 
1825
- **关键原则**:挂载目标**不一定是 longterm 根**,可以是 longterm 根下任意深度的子/孙任务,
1826
- 关键是**沿 task_tree 找语义最匹配的有意义节点**。**挂得"深"比挂得"错"好**。
1892
+ **决策依据强度**:
1827
1893
 
1828
- **禁止**:
1829
- - ❌ 不要把不同 longterm 域的孤儿 attach 到错误根
1830
- - ❌ 不要把 normal 根硬塞给不相干的 longterm 父任务
1831
- - ❌ 不要 re-parent 已 completed 的历史任务(破坏历史语义)
1894
+ - \uD83D\uDFE2 **强**:title **明示** longterm 关键词 / project_path **等于** longterm 的 project 路径
1895
+ - \uD83D\uDFE1 **中**:tags 含 longterm 主题词 / description 提及"参考 #XXXX longterm 父"
1896
+ - \uD83D\uDD34 **弱**:描述有相关关键词但不是明示
1832
1897
 
1833
- **避免子任务过载**:
1834
- 挂载前先看 attach 目标已有多少子任务:**超过 20 个时优先往下一层孙任务挂**,避免单父过载。
1835
- 如果整个分支都过载,再考虑**新建一个同主题子任务**作为中间层(而不是直接挂到根)。
1898
+ **规则**:\uD83D\uDFE2 强 → 直接 reparent(路径 c)/ \uD83D\uDFE1 中 + 跨 2 项 → 可 reparent(路径 c/d),\`task_operation_create\` 必须详细 / \uD83D\uDD34 弱 → 保持为根(找不到合适父宁可不 reparent)。
1836
1899
 
1837
- ### 第 4 步:合并重复 / 批量清理
1900
+ ### Phase 3 — 健康度评估
1838
1901
 
1839
- **合并重复**:
1840
- - 保留最新 + 最完善的一条
1841
- - 用 \`task_batch_delete\` 删除副本(reason: "merged into #N")
1902
+ 执行完所有 reparent 后,重新评估 L0 / L1 / L2 与 \`health_score\`。若 \`new_health != 'health'\`:
1903
+ - 继续 Phase 2 找更多 reparent 机会(**更激进但仍保守**)
1904
+ - 直到 \`health == 'health'\` 或耗尽所有 \uD83D\uDFE2/\uD83D\uDFE1 决策
1842
1905
 
1843
- **批量清理**:
1844
- - 测试任务(标题含 test/测试/demo/mock/sample/试验)→ \`task_batch_delete\`
1845
- - 已完成 + 历史价值(调研/检索/旧 fix)→ \`task_batch_archive\`
1846
- - 长期未更新(> 30 天 status=active 但无 progress)→ 标记 paused 或 archive
1906
+ ### Phase 4 — 执行 + 留痕
1847
1907
 
1848
- ### 第 5 步:报告
1908
+ 每次 reparent / 升级 type 时,必须配套:
1849
1909
 
1850
- 输出 JSON 报告:
1910
+ \`\`\`bash
1911
+ task_update({ task_id: X, parent_task_id: Y }) # 或 task_update({ task_id: X, type: "longterm" })
1851
1912
 
1852
- \`\`\`json
1853
- {
1854
- "before": { "root_count": 28, "non_longterm_root_count": 15, "max_depth": 7 },
1855
- "after": { "root_count": 12, "non_longterm_root_count": 0, "max_depth": 4 },
1856
- "reparent": [
1857
- { "task_id": 1234, "from": null, "to": 2068, "type": "normal", "reason": "matched [Longterm] roy-agent 开源" }
1858
- ],
1859
- "merge": [{ "kept": 100, "deleted": [101, 102], "reason": "duplicate" }],
1860
- "archive": [{ "task_ids": [8001, 8002], "reason": "completed > 30d" }],
1861
- "delete": [{ "task_ids": [9001, 9002], "reason": "test tasks" }],
1862
- "next_steps": ["建议保留 #N 作为 [Longterm] X 方向的根"]
1863
- }
1913
+ task_operation_create({
1914
+ task_id: X, # 被 reparent 的任务
1915
+ milestone_type: "decision",
1916
+ milestone_title: "Reparent #X → #Y (reason: ...)"
1917
+ })
1864
1918
  \`\`\`
1865
1919
 
1920
+ **报告输出**:写到 \`/tmp/task-organization-report-v{N+1}.md\`,含 8 节:
1921
+ 1. 起点分析(Phase 1)/ 2. 锚点清单(Phase 0)/ 3. 4 路径分类(Phase 2)/ 4. 整理后终态 / 5. 操作清单(Phase 4)/ 6. 健康度评估(Phase 3)/ 7. 累计历史对比 / 8. 留痕
1922
+
1923
+ ---
1924
+
1925
+ ## \uD83D\uDEA8 铁律(不可违反)
1926
+
1927
+ | # | 铁律 |
1928
+ |---|------|
1929
+ | ① | **0 删任务**(不调用 \`task_batch_delete\` / \`task_delete\`)|
1930
+ | ② | **0 归档默认**(不调用 \`task_batch_archive\`,除非用户本轮明确授权)|
1931
+ | ③ | **longterm 永远保留为根**(不修改 longterm 语义,不 reparent longterm)|
1932
+ | ④ | **active 只改 parent 不改 status**(可 reparent,但 status 永远保留 active)|
1933
+ | ⑤ | **0 碰 paused / cancelled 任务**(除非用户明确指示)|
1934
+ | ⑥ | **找不到合适父宁可不 reparent**(保守 > 激进)|
1935
+ | ⑦ | **每个 reparent 都要 \`task_operation_create\` 留痕** |
1936
+ | ⑧ | **不创建新 longterm 除非主题真正长期** |
1937
+ | ⑨ | **本轮不返工**(上一轮已 reparent 的,本轮不动)|
1938
+ | ⑩ | **不写代码到 roy-agent 仓库**(task-organizer 是 prompt agent)|
1939
+ | ⑪ | **每个决策 100% 可解释** |
1940
+ | ⑫ | **Phase 0 之前先建立 self-task 跟踪**(见下方 self-task 模板) |
1941
+
1942
+ > ⚠️ 触发任何一条 → 立即停止并向主代理报告。
1943
+
1866
1944
  ---
1867
1945
 
1868
1946
  ## \uD83D\uDEA8 禁止操作
1869
1947
 
1870
1948
  - ❌ **不要**无脑新建根任务(必须确认至少 2-3 个非 longterm 根明显同主题才建)
1871
- - ❌ **不要**修改 longterm 根任务的语义(title / description / goals)
1949
+ - ❌ **不要**修改 longterm 根任务的语义(title / description / goals / type)
1872
1950
  - ❌ **不要**把不同 longterm 域的根 attach 到错误根
1873
- - ❌ **不要**re-parent 已 completed 的历史任务
1874
1951
  - ❌ **不要**批量操作前不 dry-run
1875
1952
  - ❌ **不要**在没有 \`task_operation_create\` 记录的情况下做批量动作
1953
+ - ❌ **不要**默认调用 \`task_batch_archive\`(铁律 ②)
1876
1954
 
1877
1955
  ---
1878
1956
 
@@ -1888,26 +1966,27 @@ task_list({ depth: 0, include_archived: false })
1888
1966
 
1889
1967
  ---
1890
1968
 
1891
- ## 关键双维度记录(批量操作必填)
1969
+ ## 关键双维度记录(每次 reparent 必填)
1892
1970
 
1893
- 每次批量操作都必须用 \`task_operation_create\` 留下双维度记录:
1971
+ 每次 reparent / 升级 type 必须用 \`task_operation_create\` 留下双维度记录:
1894
1972
 
1895
- - **milestone_type**: \`milestone\`("我做了什么")或 \`progress\`("我推进到 X 状态")
1896
- - **milestone_title**: 一句话标题(如 "Re-parented 5 non-longterm roots to [Longterm] roy-agent")
1897
- - **milestone_description**: 详细描述(操作范围、影响)
1973
+ - **milestone_type**: \`decision\`("为什么挂这里")或 \`milestone\`("达成了什么")
1974
+ - **milestone_title**: 一句话标题(如 "Reparent #X → #Y(longterm 锚点)")
1975
+ - **milestone_description**: 详细描述(决策依据、强度、项目路径)
1898
1976
  - **process_description**: 100-150 字符简要过程
1899
1977
 
1900
1978
  ---
1901
1979
 
1902
1980
  ## 终止与报告
1903
1981
 
1904
- 整理完成后必须输出最终 JSON 报告,然后一句话总结:
1982
+ 整理完成后输出报告到 \`/tmp/task-organization-report-v{N+1}.md\`,然后一句话总结:
1905
1983
 
1906
- > ✅ 任务树整理完成。根任务从 N 收敛到 M(目标 10-20),其中 longterm 占比从 X% 提升到 100%,re-parent/merge/archive/delete 共 K 项。详见 operations。
1984
+ > ✅ 任务树整理完成。根任务从 N 收敛到 M(目标 10-20),其中 longterm 占比从 X% 提升到 100%,reparent/merge 共 K 项(0 删 + 0 归档默认)。详见 operations。
1907
1985
 
1908
1986
  如果没有任何改动:
1909
1987
 
1910
- > ✅ 任务树形态良好(root=N, depth=X, non_longterm_root=0)。无需操作。`
1988
+ > ✅ 任务树形态良好(root=N, depth=X, non_longterm_root=0, health_score=health)。无需操作。
1989
+ `
1911
1990
  };
1912
1991
  var WORKFLOW_EXTRACT_PROMPT = builtInPrompts["workflow-extract"];
1913
1992
  function getBuiltInPromptNames() {
@@ -10,7 +10,7 @@ import {
10
10
  } from "./roy-agent-core-1pg0fepg.js";
11
11
  import {
12
12
  builtInPrompts
13
- } from "./roy-agent-core-skqt40yy.js";
13
+ } from "./roy-agent-core-223v204d.js";
14
14
  import {
15
15
  DEFAULT_SUBAGENT_PROMPT
16
16
  } from "./roy-agent-core-za09t5g3.js";
@@ -27,7 +27,7 @@ import {
27
27
  BackgroundTaskManager,
28
28
  createDelegateTool,
29
29
  createStopTool
30
- } from "./roy-agent-core-jg8cv1f7.js";
30
+ } from "./roy-agent-core-4m0t4y9w.js";
31
31
  import {
32
32
  SQLiteTaskStore,
33
33
  getDefaultTaskDbPath
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createAutoTaskPlugin
3
- } from "./roy-agent-core-47wrv4ex.js";
3
+ } from "./roy-agent-core-zmr3jzpe.js";
4
4
  import {
5
5
  ContextError,
6
6
  ErrorCodes
@@ -357,6 +357,29 @@ function filterToolsByAgent(tools, agent) {
357
357
  return allowedList.includes(agent.name);
358
358
  });
359
359
  }
360
+ function buildRunEnvContext(inputs) {
361
+ const { effectiveContext, parentEnvContext, envBoundParentTaskId } = inputs;
362
+ const effectiveEnvEvent = effectiveContext.envEvent;
363
+ return {
364
+ ...parentEnvContext,
365
+ agentContext: parentEnvContext?.agentContext ?? {},
366
+ traceId: effectiveContext.metadata?.traceId,
367
+ sessionId: effectiveContext.sessionId,
368
+ userId: parentEnvContext?.userId ?? (effectiveContext.metadata?.userId ?? ""),
369
+ messageId: parentEnvContext?.messageId ?? effectiveContext.metadata?.messageId,
370
+ pluginEnabled: {
371
+ ...parentEnvContext?.pluginEnabled ?? {},
372
+ ...effectiveContext.pluginEnabled ?? {}
373
+ },
374
+ plugins: effectiveContext.plugins,
375
+ envEvent: effectiveContext.envEvent ?? parentEnvContext?.envEvent,
376
+ replyChannel: effectiveEnvEvent?.metadata?.replyChannel ?? parentEnvContext?.replyChannel,
377
+ sourceId: parentEnvContext?.sourceId ?? effectiveContext.envEvent?.metadata?.sourceId,
378
+ sourceType: parentEnvContext?.sourceType ?? effectiveContext.envEvent?.metadata?.sourceType,
379
+ parentTaskId: envBoundParentTaskId,
380
+ metadata: { ...effectiveContext.metadata }
381
+ };
382
+ }
360
383
 
361
384
  class AgentComponent extends BaseComponent {
362
385
  name = "agent";
@@ -868,22 +891,11 @@ class AgentComponent extends BaseComponent {
868
891
  }
869
892
  const parentEnvContext = getEnvContext();
870
893
  const envBoundParentTaskId = resolveEnvParentTaskId(effectiveContext.envEvent, parentEnvContext);
871
- const envContext = {
872
- ...parentEnvContext,
873
- agentContext: parentEnvContext?.agentContext ?? {},
874
- traceId: effectiveContext.metadata?.traceId,
875
- sessionId: effectiveContext.sessionId,
876
- userId: parentEnvContext?.userId ?? (effectiveContext.metadata?.userId ?? ""),
877
- messageId: parentEnvContext?.messageId ?? effectiveContext.metadata?.messageId,
878
- pluginEnabled: { ...parentEnvContext?.pluginEnabled ?? {}, ...effectiveContext.pluginEnabled ?? {} },
879
- plugins: effectiveContext.plugins,
880
- envEvent: effectiveContext.envEvent ?? parentEnvContext?.envEvent,
881
- replyChannel: parentEnvContext?.replyChannel ?? effectiveContext.envEvent?.metadata?.replyChannel,
882
- sourceId: parentEnvContext?.sourceId ?? effectiveContext.envEvent?.metadata?.sourceId,
883
- sourceType: parentEnvContext?.sourceType ?? effectiveContext.envEvent?.metadata?.sourceType,
884
- parentTaskId: envBoundParentTaskId,
885
- metadata: { ...effectiveContext.metadata }
886
- };
894
+ const envContext = buildRunEnvContext({
895
+ effectiveContext,
896
+ parentEnvContext,
897
+ envBoundParentTaskId
898
+ });
887
899
  return await runWithEnvContextAsync(envContext, async () => {
888
900
  this.pushEnvEvent({
889
901
  type: "agent.start",
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  builtInPrompts
3
- } from "./roy-agent-core-skqt40yy.js";
3
+ } from "./roy-agent-core-223v204d.js";
4
4
  import {
5
5
  getXDGPath
6
6
  } from "./roy-agent-core-qxnbvgwe.js";
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  defaultLarkCliRunner
3
3
  } from "./roy-agent-core-ck60j1q9.js";
4
- import {
5
- getSharedEventStore
6
- } from "./roy-agent-core-xyys5m1a.js";
7
4
  import {
8
5
  TaskTagPlugin,
9
6
  createLarkCliTaskNotifyHook,
10
7
  createPerTaskGroupChatPlugin
11
- } from "./roy-agent-core-47wrv4ex.js";
8
+ } from "./roy-agent-core-zmr3jzpe.js";
9
+ import {
10
+ getSharedEventStore
11
+ } from "./roy-agent-core-xyys5m1a.js";
12
12
  import {
13
13
  normalizeLarkAtMentions
14
14
  } from "./roy-agent-core-rmn29nrh.js";
@@ -1621,6 +1621,33 @@ __legacyDecorateClassTS([
1621
1621
  __legacyDecorateClassTS([
1622
1622
  TracedAs("lark-cli.handleEvent", { recordParams: true, log: true })
1623
1623
  ], LarkCliInstance.prototype, "handleEvent", null);
1624
+ var NOTIFY_TERMINAL_TYPES = new Set([
1625
+ "task.background.completed",
1626
+ "task.background.failed",
1627
+ "task.background.timeout",
1628
+ "task.background.stopped"
1629
+ ]);
1630
+ function describeNotifyEvent(type, taskId, desc) {
1631
+ const actionable = NOTIFY_TERMINAL_TYPES.has(type);
1632
+ switch (type) {
1633
+ case "task.background.completed":
1634
+ return { headline: `Sub-agent 完成了 Task #${taskId}「${desc}」。`, actionable };
1635
+ case "task.background.failed":
1636
+ return { headline: `Sub-agent 执行 Task #${taskId}「${desc}」失败。`, actionable };
1637
+ case "task.background.timeout":
1638
+ return { headline: `Sub-agent 执行 Task #${taskId}「${desc}」超时。`, actionable };
1639
+ case "task.background.stopped":
1640
+ return { headline: `Sub-agent 已停止 Task #${taskId}「${desc}」。`, actionable };
1641
+ case "task.background.ask_user":
1642
+ return { headline: `Sub-agent 在 Task #${taskId}「${desc}」中请求用户输入。`, actionable };
1643
+ case "task.background.started":
1644
+ return { headline: `Sub-agent 已启动 Task #${taskId}「${desc}」(后台运行中)。`, actionable };
1645
+ case "task.background.progress":
1646
+ return { headline: `Sub-agent 仍在执行 Task #${taskId}「${desc}」(进行中)。`, actionable };
1647
+ default:
1648
+ return { headline: `Sub-agent 更新了 Task #${taskId}「${desc}」。`, actionable };
1649
+ }
1650
+ }
1624
1651
  var larkCliHandler = {
1625
1652
  type: "lark-cli",
1626
1653
  validateConfig(config) {
@@ -1686,10 +1713,13 @@ var larkCliHandler = {
1686
1713
  const profileFlag = ctx.profile ? `--profile ${ctx.profile} ` : "";
1687
1714
  const desc = input.notifyEvent.description ?? "(未命名任务)";
1688
1715
  const result = input.subAgentResult.summary ?? input.notifyEvent.result ?? "";
1689
- const promptText = `
1690
- ## Notify Event: ${input.notifyEvent.type}
1716
+ const notifyType = input.notifyEvent.type;
1717
+ const taskId = input.notifyEvent.taskId ?? "?";
1718
+ const { headline, actionable } = describeNotifyEvent(notifyType, taskId, desc);
1719
+ const promptText = actionable ? `
1720
+ ## Notify Event: ${notifyType}
1691
1721
 
1692
- Sub-agent 完成了 Task #${input.notifyEvent.taskId ?? "?"}「${desc}」。
1722
+ ${headline}
1693
1723
 
1694
1724
  ### Trigger event(原始飞书消息,来自 EventStore 反查)
1695
1725
  - ES: lark-cli
@@ -1707,8 +1737,20 @@ ${result}
1707
1737
 
1708
1738
  ⚠️ 不要 fallback 到 lastReplyChannel 或 metadata.replyChannel — 那个 chatId
1709
1739
  可能跟用户原始消息的 chatId 不一致(参见 #4035/#4038/#4039 bug)。
1740
+ ` : `
1741
+ ## Notify Event: ${notifyType}
1742
+
1743
+ ${headline}
1744
+
1745
+ ### Trigger event
1746
+ - ES: lark-cli
1747
+ - chatId: ${ctx.chatId}
1748
+ - messageId: ${ctx.messageId}
1749
+
1750
+ (这是中间态通知:仅作状态同步,**不要**回复用户,也不要调用 lark-cli 发消息。
1751
+ 等收到 task.background.completed / failed / timeout / stopped 终态通知后再回复。)
1710
1752
  `;
1711
- const systemHint = `回复必须用 lark-cli im +messages-reply(${profileFlag.trim() ? `带 ${profileFlag.trim()};` : ""}` + `chatId=${ctx.chatId} / messageId=${ctx.messageId} 来自 trigger event,不要 fallback。`;
1753
+ const systemHint = actionable ? `回复必须用 lark-cli im +messages-reply(${profileFlag.trim() ? `带 ${profileFlag.trim()};` : ""}` + `chatId=${ctx.chatId} / messageId=${ctx.messageId} 来自 trigger event,不要 fallback。` : `这是 ${notifyType} 中间态通知,不要回复用户;仅等待终态通知。`;
1712
1754
  return { promptText, systemHint };
1713
1755
  },
1714
1756
  setRunner(runner) {
@@ -1,9 +1,12 @@
1
+ import {
2
+ getSharedEventStore
3
+ } from "./roy-agent-core-xyys5m1a.js";
1
4
  import {
2
5
  TaskHookPoints
3
6
  } from "./roy-agent-core-1pg0fepg.js";
4
7
  import {
5
8
  WORKFLOW_EXTRACT_PROMPT
6
- } from "./roy-agent-core-skqt40yy.js";
9
+ } from "./roy-agent-core-223v204d.js";
7
10
  import {
8
11
  validateWorkflowDefinition
9
12
  } from "./roy-agent-core-6vbgswjw.js";
@@ -378,6 +381,30 @@ var logger3 = createLogger("lark-cli:task-notify");
378
381
  function isTaskNotifyDebugEnabled() {
379
382
  return process.env.ROY_TASK_NOTIFY_DEBUG === "1" || process.env.ROY_TRACE_DEBUG === "1";
380
383
  }
384
+ var CTX_FIELD_CHAT_ID = "larkPerTaskChatId";
385
+ var CTX_FIELD_CHAT_PROFILE = "larkPerTaskChatProfile";
386
+ function parseLarkPerTaskChatId(ctxStr) {
387
+ if (!ctxStr)
388
+ return;
389
+ try {
390
+ const obj = JSON.parse(ctxStr);
391
+ const id = obj[CTX_FIELD_CHAT_ID];
392
+ return typeof id === "string" ? id : undefined;
393
+ } catch {
394
+ return;
395
+ }
396
+ }
397
+ function parseLarkPerTaskChatProfile(ctxStr) {
398
+ if (!ctxStr)
399
+ return;
400
+ try {
401
+ const obj = JSON.parse(ctxStr);
402
+ const profile = obj[CTX_FIELD_CHAT_PROFILE];
403
+ return typeof profile === "string" ? profile : undefined;
404
+ } catch {
405
+ return;
406
+ }
407
+ }
381
408
  function extractLarkFields(env) {
382
409
  const event = getEventFromEnvContext(env);
383
410
  if (!isLarkEvent(event)) {
@@ -407,6 +434,7 @@ class LarkCliTaskNotifyHook {
407
434
  pluginName;
408
435
  sourceId;
409
436
  config;
437
+ eventStore;
410
438
  lastNotifyTimestamps = new Map;
411
439
  constructor(config = {}) {
412
440
  this.name = config.pluginName || "LarkCliTaskNotifyHook";
@@ -515,14 +543,41 @@ class LarkCliTaskNotifyHook {
515
543
  async sendNotify(options) {
516
544
  const { type, title, content, _hookContext } = options;
517
545
  const env = getEnvContextOrEmpty();
518
- let replyChannel = env.replyChannel;
546
+ const taskFromCtx = _hookContext?.data?.task ?? env.metadata?.task;
547
+ const taskContext = taskFromCtx?.context;
548
+ const taskChatId = taskContext ? parseLarkPerTaskChatId(taskContext) : undefined;
549
+ const taskChatProfile = taskContext ? parseLarkPerTaskChatProfile(taskContext) : undefined;
550
+ let replyChannel = taskChatId ? {
551
+ chatId: taskChatId,
552
+ messageId: undefined,
553
+ profile: taskChatProfile,
554
+ type: "lark-cli"
555
+ } : env.replyChannel;
519
556
  const envContextFromMetadata = env.metadata?.envContext;
520
- if (!replyChannel && envContextFromMetadata) {
557
+ if (!replyChannel?.chatId && envContextFromMetadata?.replyChannel) {
521
558
  replyChannel = envContextFromMetadata.replyChannel;
522
559
  }
523
- if (!replyChannel && _hookContext?.metadata?.envContext) {
560
+ if (!replyChannel?.chatId && _hookContext?.metadata?.envContext?.replyChannel) {
524
561
  replyChannel = _hookContext.metadata.envContext.replyChannel;
525
562
  }
563
+ const triggerEventId = env.envEvent?.metadata?.triggerEventId ?? env.envEvent?.payload?.triggerEventId ?? env.event?.metadata?.triggerEventId;
564
+ const fallbackStore = this.eventStore ?? getSharedEventStore() ?? undefined;
565
+ if (!replyChannel?.chatId && fallbackStore && triggerEventId) {
566
+ try {
567
+ const triggerEvent = await fallbackStore.getEventById(triggerEventId);
568
+ const triggerChatId = triggerEvent?.metadata?.chatId ?? triggerEvent?.metadata?.replyChannel?.chatId;
569
+ if (triggerChatId) {
570
+ replyChannel = {
571
+ chatId: triggerChatId,
572
+ messageId: undefined,
573
+ profile: triggerEvent?.metadata?.profile ?? triggerEvent?.metadata?.replyChannel?.profile,
574
+ type: "lark-cli"
575
+ };
576
+ }
577
+ } catch (err) {
578
+ logger3.debug(`EventStore fallback failed: ${err.message}`);
579
+ }
580
+ }
526
581
  const larkFields = extractLarkFields(env);
527
582
  if (!larkFields.isLark && env.event) {
528
583
  logger3.debug(`Skipping notification for non-lark event source: ${larkFields.source}`);
@@ -797,8 +852,12 @@ __legacyDecorateClassTS([
797
852
  __legacyDecorateClassTS([
798
853
  TracedAs("lark-cli-task-notify.sendLarkMessage")
799
854
  ], LarkCliTaskNotifyHook.prototype, "sendLarkMessage", null);
800
- function createLarkCliTaskNotifyHook(config = {}) {
801
- return new LarkCliTaskNotifyHook(config);
855
+ function createLarkCliTaskNotifyHook(config = {}, options = {}) {
856
+ const hook = new LarkCliTaskNotifyHook(config);
857
+ if (options.eventStore) {
858
+ hook.eventStore = options.eventStore;
859
+ }
860
+ return hook;
802
861
  }
803
862
  // src/env/task/plugins/per-task-group-chat-plugin.ts
804
863
  init_decorator();
@@ -809,8 +868,8 @@ var logger4 = createLogger("lark-cli:per-task-group");
809
868
  function isPluginDebugEnabled() {
810
869
  return process.env.ROY_TASK_NOTIFY_DEBUG === "1" || process.env.ROY_TRACE_DEBUG === "1";
811
870
  }
812
- var CTX_FIELD_CHAT_ID = "larkPerTaskChatId";
813
- var CTX_FIELD_CHAT_PROFILE = "larkPerTaskChatProfile";
871
+ var CTX_FIELD_CHAT_ID2 = "larkPerTaskChatId";
872
+ var CTX_FIELD_CHAT_PROFILE2 = "larkPerTaskChatProfile";
814
873
  var CTX_FIELD_CHAT_CREATED_AT = "larkPerTaskChatCreatedAt";
815
874
  var CTX_FIELD_CHAT_TASK_ID = "larkPerTaskChatTaskId";
816
875
 
@@ -840,7 +899,8 @@ class PerTaskGroupChatPlugin {
840
899
  disableSubTaskSkip: config.disableSubTaskSkip ?? false,
841
900
  requireReplyChannel: config.requireReplyChannel ?? true,
842
901
  fallbackProfile: config.fallbackProfile ?? "",
843
- sendWelcomeMessage: config.sendWelcomeMessage ?? true
902
+ sendWelcomeMessage: config.sendWelcomeMessage ?? true,
903
+ resolveToTriggerChatFallback: config.resolveToTriggerChatFallback ?? false
844
904
  };
845
905
  this.name = this.config.pluginName;
846
906
  this.priority = this.config.priority;
@@ -1155,8 +1215,8 @@ class PerTaskGroupChatPlugin {
1155
1215
  } catch {
1156
1216
  parsed = {};
1157
1217
  }
1158
- parsed[CTX_FIELD_CHAT_ID] = chatId;
1159
- parsed[CTX_FIELD_CHAT_PROFILE] = profile;
1218
+ parsed[CTX_FIELD_CHAT_ID2] = chatId;
1219
+ parsed[CTX_FIELD_CHAT_PROFILE2] = profile;
1160
1220
  parsed[CTX_FIELD_CHAT_CREATED_AT] = new Date().toISOString();
1161
1221
  parsed[CTX_FIELD_CHAT_TASK_ID] = task.id;
1162
1222
  const newContext = JSON.stringify(parsed);
@@ -1268,7 +1328,7 @@ ${opts.content}`);
1268
1328
  return;
1269
1329
  try {
1270
1330
  const obj = JSON.parse(ctxStr);
1271
- const id = obj[CTX_FIELD_CHAT_ID];
1331
+ const id = obj[CTX_FIELD_CHAT_ID2];
1272
1332
  return typeof id === "string" ? id : undefined;
1273
1333
  } catch {
1274
1334
  return;
@@ -1279,7 +1339,7 @@ ${opts.content}`);
1279
1339
  return;
1280
1340
  try {
1281
1341
  const obj = JSON.parse(ctxStr);
1282
- const profile = obj[CTX_FIELD_CHAT_PROFILE];
1342
+ const profile = obj[CTX_FIELD_CHAT_PROFILE2];
1283
1343
  return typeof profile === "string" ? profile : undefined;
1284
1344
  } catch {
1285
1345
  return;
@@ -1316,6 +1376,22 @@ ${opts.content}`);
1316
1376
  }
1317
1377
  id = parent.parent_task_id ?? undefined;
1318
1378
  }
1379
+ if (this.config.resolveToTriggerChatFallback) {
1380
+ const store = getSharedEventStore();
1381
+ const triggerEventId = getEnvContextOrEmpty()?.envEvent?.metadata?.triggerEventId;
1382
+ if (store && typeof triggerEventId === "string" && triggerEventId.length > 0) {
1383
+ try {
1384
+ const triggerEvent = await store.getEventById(triggerEventId);
1385
+ const fallbackChatId = triggerEvent?.metadata?.chatId ?? triggerEvent?.metadata?.replyChannel?.chatId;
1386
+ if (fallbackChatId) {
1387
+ return {
1388
+ chatId: fallbackChatId,
1389
+ profile: triggerEvent?.metadata?.profile ?? triggerEvent?.metadata?.replyChannel?.profile
1390
+ };
1391
+ }
1392
+ } catch {}
1393
+ }
1394
+ }
1319
1395
  return {};
1320
1396
  }
1321
1397
  resolveBotAppIds(replyChannel) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-setting/roy-agent-core",
3
- "version": "1.7.39",
3
+ "version": "1.7.41",
4
4
  "type": "module",
5
5
  "description": "Core SDK for roy-agent - Environment, Components, Tools, Sessions, Tasks",
6
6
  "main": "./dist/index.js",