@ai-setting/roy-agent-core 1.7.72 → 1.7.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/env/agent/agent-component.js +6 -6
- package/dist/env/agent/agent-registry.d.ts +4 -1
- package/dist/env/agent/index.js +6 -6
- package/dist/env/error-reply.d.ts +46 -0
- package/dist/env/error-reply.js +3 -1
- package/dist/env/event-source/event-source-handlers.js +13 -12
- package/dist/env/event-source/index.js +14 -13
- package/dist/env/index.js +31 -30
- package/dist/env/llm/index.js +2 -2
- package/dist/env/llm/orphan-toolcall.d.ts +107 -0
- package/dist/env/plugin/index.js +3 -3
- package/dist/env/prompt/index.js +4 -3
- package/dist/env/prompt/prompts-index.d.ts +27 -3
- package/dist/env/session/index.js +4 -4
- package/dist/env/session/storage/index.js +3 -3
- package/dist/env/task/backend/index.js +9 -1
- package/dist/env/task/delegate/delegate-tool.d.ts +8 -0
- package/dist/env/task/delegate/delegate-tool.js +5 -4
- package/dist/env/task/delegate/index.js +5 -4
- package/dist/env/task/hooks/contexts.d.ts +12 -1
- package/dist/env/task/hooks/task-hook-points.d.ts +8 -3
- package/dist/env/task/index.d.ts +1 -0
- package/dist/env/task/index.js +17 -7
- package/dist/env/task/mcp/index.js +3 -2
- package/dist/env/task/plugins/index.d.ts +3 -0
- package/dist/env/task/plugins/index.js +33 -9
- package/dist/env/task/plugins/lark-card-patch-notifier.d.ts +61 -0
- package/dist/env/task/plugins/lark-card-patch-notifier.js +6 -2
- package/dist/env/task/plugins/lark-cli-task-notify-plugin.d.ts +42 -0
- package/dist/env/task/prompt/index.js +2 -1
- package/dist/env/task/prompt/task-discipline.d.ts +9 -3
- package/dist/env/task/task-component.d.ts +79 -0
- package/dist/env/task/tools/cancel-tool.d.ts +36 -0
- package/dist/env/task/tools/completion-copy.d.ts +92 -0
- package/dist/env/task/tools/index.d.ts +2 -0
- package/dist/env/task/tools/index.js +7 -2
- package/dist/env/task/tools/pre-complete-tool.d.ts +32 -0
- package/dist/env/task/tools/task-types.d.ts +71 -17
- package/dist/env/task/types.d.ts +13 -1
- package/dist/env/tool/built-in/compact-session-tool.d.ts +120 -0
- package/dist/env/tool/built-in/index.d.ts +2 -0
- package/dist/env/tool/built-in/index.js +6 -2
- package/dist/env/tool/index.js +4 -4
- package/dist/env/workflow/engine/index.js +6 -6
- package/dist/env/workflow/index.js +15 -13
- package/dist/env/workflow/plugins/index.js +2 -2
- package/dist/env/workflow/tools/ask-user-tool.d.ts +88 -0
- package/dist/env/workflow/tools/index.js +11 -9
- package/dist/env/workflow/tools/run-workflow.d.ts +2 -2
- package/dist/env/workflow/types/index.js +2 -2
- package/dist/env/workflow/types/workflow-hil.d.ts +25 -1
- package/dist/env/workflow/utils/index.js +5 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +43 -33
- package/dist/shared/@ai-setting/{roy-agent-core-sm0sf6sb.js → roy-agent-core-0qyrk5k0.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-kmbct9yg.js → roy-agent-core-0snm5hc5.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-yr1mryb8.js → roy-agent-core-1v4g0d4x.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-rxb00gjm.js → roy-agent-core-264qexac.js} +1 -1
- package/dist/shared/@ai-setting/roy-agent-core-2akfd64z.js +374 -0
- package/dist/shared/@ai-setting/{roy-agent-core-skyc30qx.js → roy-agent-core-3fh1f7s7.js} +2 -2
- package/dist/shared/@ai-setting/roy-agent-core-4rtg69cn.js +26 -0
- package/dist/shared/@ai-setting/{roy-agent-core-add1zqsh.js → roy-agent-core-6cy43nss.js} +22 -1
- package/dist/shared/@ai-setting/{roy-agent-core-vah6g5yx.js → roy-agent-core-6rh8k6ba.js} +5 -5
- package/dist/shared/@ai-setting/{roy-agent-core-kpg25s2q.js → roy-agent-core-8ez6mccb.js} +4 -2
- package/dist/shared/@ai-setting/{roy-agent-core-yhwxpj12.js → roy-agent-core-9vxh6f8h.js} +233 -16
- package/dist/shared/@ai-setting/{roy-agent-core-7qvw65jt.js → roy-agent-core-aa2j7bk9.js} +11 -8
- package/dist/shared/@ai-setting/{roy-agent-core-sjr1kmfz.js → roy-agent-core-acj8ag08.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-mds8tqd0.js → roy-agent-core-cgtq6427.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-34jz9mgh.js → roy-agent-core-cmprygrp.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-wr7mv7k3.js → roy-agent-core-cxy143m4.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-pakhchy7.js → roy-agent-core-ddyk1rc0.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-attpry6g.js → roy-agent-core-dqxec05w.js} +4 -3
- package/dist/shared/@ai-setting/{roy-agent-core-vm8h5zyj.js → roy-agent-core-ed233k5z.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-jrj30vq3.js → roy-agent-core-er070zjq.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-40rv283c.js → roy-agent-core-fghc2m8z.js} +152 -2
- package/dist/shared/@ai-setting/{roy-agent-core-5gw0qa8m.js → roy-agent-core-ghnagzrh.js} +557 -92
- package/dist/shared/@ai-setting/{roy-agent-core-4jjwewvw.js → roy-agent-core-m46fe3x4.js} +41 -30
- package/dist/shared/@ai-setting/{roy-agent-core-e25xkv53.js → roy-agent-core-mkc3zshb.js} +3 -1
- package/dist/shared/@ai-setting/{roy-agent-core-hfyfavp3.js → roy-agent-core-mww0mnd9.js} +231 -27
- package/dist/shared/@ai-setting/{roy-agent-core-46rv4d7d.js → roy-agent-core-nmx9934r.js} +92 -2
- package/dist/shared/@ai-setting/{roy-agent-core-1w9y7mxj.js → roy-agent-core-p3zv1mx5.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-jgb3bb42.js → roy-agent-core-q5r75vev.js} +17 -8
- package/dist/shared/@ai-setting/{roy-agent-core-y12kyxwa.js → roy-agent-core-t3rrb959.js} +33 -9
- package/dist/shared/@ai-setting/{roy-agent-core-dt104qa1.js → roy-agent-core-v85n42ve.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-gr48c89p.js → roy-agent-core-v87njmq7.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-7sj9xs9c.js → roy-agent-core-vffccgf6.js} +252 -25
- package/dist/shared/@ai-setting/{roy-agent-core-2gzt2q8c.js → roy-agent-core-z43aj03k.js} +134 -29
- package/dist/shared/@ai-setting/roy-agent-core-zycadbpx.js +662 -0
- package/package.json +1 -1
- package/dist/shared/@ai-setting/roy-agent-core-1p6syv85.js +0 -1083
- package/dist/shared/@ai-setting/roy-agent-core-58804s3j.js +0 -155
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
+
LAYA_COMPLETION_THRESHOLD,
|
|
2
3
|
LAYA_REUSE_THRESHOLD,
|
|
3
4
|
LarkCliTaskNotifyHook,
|
|
5
|
+
LayaCompletionPlugin,
|
|
4
6
|
LayaDecisionPlugin,
|
|
5
7
|
MemoryLarkCardStateStore,
|
|
6
8
|
NotifyType,
|
|
@@ -8,22 +10,33 @@ import {
|
|
|
8
10
|
SqliteLarkCardStateStore,
|
|
9
11
|
TaskTagPlugin,
|
|
10
12
|
WORKFLOW_EXTRACTOR_PROMPT,
|
|
13
|
+
buildCompletionHint,
|
|
14
|
+
buildCompletionQuestion,
|
|
11
15
|
createAutoTaskPlugin,
|
|
12
16
|
createLarkCardStateStore,
|
|
13
17
|
createLarkCliTaskNotifyHook,
|
|
18
|
+
createLayaCompletionPlugin,
|
|
14
19
|
createLayaDecisionPlugin,
|
|
15
20
|
createPerTaskGroupChatPlugin,
|
|
16
21
|
formatExtractorInput,
|
|
17
22
|
formatExtractorInputFromDescription,
|
|
18
23
|
getDefaultLarkCardDbPath,
|
|
19
|
-
parseExtractorOutput
|
|
20
|
-
|
|
24
|
+
parseExtractorOutput,
|
|
25
|
+
registerLayaCompletionTaskHook,
|
|
26
|
+
renderCompletionState
|
|
27
|
+
} from "../../../shared/@ai-setting/roy-agent-core-ghnagzrh.js";
|
|
21
28
|
import"../../../shared/@ai-setting/roy-agent-core-na18zwj0.js";
|
|
22
|
-
import"../../../shared/@ai-setting/roy-agent-core-
|
|
29
|
+
import"../../../shared/@ai-setting/roy-agent-core-9vxh6f8h.js";
|
|
23
30
|
import"../../../shared/@ai-setting/roy-agent-core-abqhkbn3.js";
|
|
24
31
|
import"../../../shared/@ai-setting/roy-agent-core-1pg0fepg.js";
|
|
25
32
|
import"../../../shared/@ai-setting/roy-agent-core-tr3ep81v.js";
|
|
26
|
-
import"../../../shared/@ai-setting/roy-agent-core-
|
|
33
|
+
import"../../../shared/@ai-setting/roy-agent-core-m46fe3x4.js";
|
|
34
|
+
import {
|
|
35
|
+
TASK_COMPLETE_ACCEPTANCE,
|
|
36
|
+
TASK_COMPLETE_ITEM_BY_ITEM,
|
|
37
|
+
TASK_COMPLETE_VERIFY_DUTY,
|
|
38
|
+
TASK_COMPLETION_HINT_ANCHOR
|
|
39
|
+
} from "../../../shared/@ai-setting/roy-agent-core-4rtg69cn.js";
|
|
27
40
|
import {
|
|
28
41
|
DEFAULT_APP_LINK_BASE,
|
|
29
42
|
LarkCardPatchNotifier,
|
|
@@ -42,12 +55,12 @@ import {
|
|
|
42
55
|
renderWorkflowInfoLines,
|
|
43
56
|
resolveTaskTitleForDisplay,
|
|
44
57
|
sanitizeInlineText
|
|
45
|
-
} from "../../../shared/@ai-setting/roy-agent-core-
|
|
46
|
-
import"../../../shared/@ai-setting/roy-agent-core-
|
|
47
|
-
import"../../../shared/@ai-setting/roy-agent-core-
|
|
48
|
-
import"../../../shared/@ai-setting/roy-agent-core-
|
|
58
|
+
} from "../../../shared/@ai-setting/roy-agent-core-nmx9934r.js";
|
|
59
|
+
import"../../../shared/@ai-setting/roy-agent-core-1v4g0d4x.js";
|
|
60
|
+
import"../../../shared/@ai-setting/roy-agent-core-cgtq6427.js";
|
|
61
|
+
import"../../../shared/@ai-setting/roy-agent-core-er070zjq.js";
|
|
49
62
|
import"../../../shared/@ai-setting/roy-agent-core-f77k3gqt.js";
|
|
50
|
-
import"../../../shared/@ai-setting/roy-agent-core-
|
|
63
|
+
import"../../../shared/@ai-setting/roy-agent-core-mkc3zshb.js";
|
|
51
64
|
import"../../../shared/@ai-setting/roy-agent-core-az13yzmc.js";
|
|
52
65
|
import"../../../shared/@ai-setting/roy-agent-core-qqaak24r.js";
|
|
53
66
|
import"../../../shared/@ai-setting/roy-agent-core-7cbpmk4q.js";
|
|
@@ -64,6 +77,8 @@ export {
|
|
|
64
77
|
renderProcessSteps,
|
|
65
78
|
renderMilestones,
|
|
66
79
|
renderContextAsLines,
|
|
80
|
+
renderCompletionState,
|
|
81
|
+
registerLayaCompletionTaskHook,
|
|
67
82
|
parseExtractorOutput,
|
|
68
83
|
humanizeValue,
|
|
69
84
|
getDefaultLarkCardDbPath,
|
|
@@ -74,21 +89,30 @@ export {
|
|
|
74
89
|
formatDateTimeForDisplay,
|
|
75
90
|
createPerTaskGroupChatPlugin,
|
|
76
91
|
createLayaDecisionPlugin,
|
|
92
|
+
createLayaCompletionPlugin,
|
|
77
93
|
createLarkCliTaskNotifyHook,
|
|
78
94
|
createLarkCardStateStore,
|
|
79
95
|
createAutoTaskPlugin,
|
|
80
96
|
buildWorkflowCard,
|
|
81
97
|
buildTaskCard,
|
|
98
|
+
buildCompletionQuestion,
|
|
99
|
+
buildCompletionHint,
|
|
82
100
|
buildChatAppLink,
|
|
83
101
|
WORKFLOW_EXTRACTOR_PROMPT,
|
|
84
102
|
TaskTagPlugin,
|
|
103
|
+
TASK_COMPLETION_HINT_ANCHOR,
|
|
104
|
+
TASK_COMPLETE_VERIFY_DUTY,
|
|
105
|
+
TASK_COMPLETE_ITEM_BY_ITEM,
|
|
106
|
+
TASK_COMPLETE_ACCEPTANCE,
|
|
85
107
|
SqliteLarkCardStateStore,
|
|
86
108
|
PerTaskGroupChatPlugin,
|
|
87
109
|
NotifyType,
|
|
88
110
|
MemoryLarkCardStateStore,
|
|
89
111
|
LayaDecisionPlugin,
|
|
112
|
+
LayaCompletionPlugin,
|
|
90
113
|
LarkCliTaskNotifyHook,
|
|
91
114
|
LarkCardPatchNotifier,
|
|
92
115
|
LAYA_REUSE_THRESHOLD,
|
|
116
|
+
LAYA_COMPLETION_THRESHOLD,
|
|
93
117
|
DEFAULT_APP_LINK_BASE
|
|
94
118
|
};
|
|
@@ -379,6 +379,27 @@ export declare function formatTimestampForDisplay(iso: string | undefined): stri
|
|
|
379
379
|
* 路径 / 命令 / 中文正文不受影响。
|
|
380
380
|
*/
|
|
381
381
|
export declare function sanitizeInlineText(text: string, maxLen?: number): string;
|
|
382
|
+
/**
|
|
383
|
+
* 卡片 head 标题的**视觉宽度预算**(Task #4984)
|
|
384
|
+
*
|
|
385
|
+
* 飞书卡片 header.title 是单行 plain_text,超长会被截断/挤压布局。
|
|
386
|
+
* 这里用「视觉宽度」而非字符数做预算:CJK 占 2 列、ASCII 占 1 列。
|
|
387
|
+
*/
|
|
388
|
+
export declare const HEAD_TITLE_MAX_WIDTH = 40;
|
|
389
|
+
/**
|
|
390
|
+
* 截断卡片 head 用的任务名称(Task #4984)
|
|
391
|
+
*
|
|
392
|
+
* 策略(按用户诉求「head 要有任务名称,但别撑破布局」):
|
|
393
|
+
* 1. 先把多行压成单行(head 是单行 plain_text)
|
|
394
|
+
* 2. **视觉宽度**预算:CJK 记 2 列、ASCII 记 1 列
|
|
395
|
+
* 3. 不切半个 emoji —— 按 code point 遍历,代理对整体保留
|
|
396
|
+
* 4. 不切半个英文单词 —— 尽量在空格/分隔符处断开
|
|
397
|
+
* 5. 超长时补 "…" 后缀
|
|
398
|
+
*
|
|
399
|
+
* @param text 原始标题
|
|
400
|
+
* @param maxWidth 视觉宽度预算(默认 {@link HEAD_TITLE_MAX_WIDTH})
|
|
401
|
+
*/
|
|
402
|
+
export declare function truncateHeadTitle(text: string | undefined | null, maxWidth?: number): string;
|
|
382
403
|
/** ISO 8601 时间串 → 北京时间 "YYYY-MM-DD HH:mm"(非 ISO 时原样返回) */
|
|
383
404
|
export declare function formatDateTimeForDisplay(value: string): string;
|
|
384
405
|
/**
|
|
@@ -677,6 +698,28 @@ export declare class LarkCardPatchNotifier {
|
|
|
677
698
|
* ★ 幂等:已有 state 时不覆盖(内存里的比持久化的更新)。
|
|
678
699
|
*/
|
|
679
700
|
hydrateState(messageId: string, snapshot: CardStateSnapshot): void;
|
|
701
|
+
/**
|
|
702
|
+
* ★ Task #5020 —— 把时间线条目**并入内存态**,但**不发** lark-cli patch。
|
|
703
|
+
*
|
|
704
|
+
* ## 为什么需要
|
|
705
|
+
*
|
|
706
|
+
* `task:operation:after.create` 的 patch 频率受 `operationThrottleMs`
|
|
707
|
+
* 约束(默认 5s),目的是别刷屏飞书。但**节流不该丢数据**:
|
|
708
|
+
* 被节流的那条 operation 如果直接丢掉,它的里程碑既不上卡也不落库。
|
|
709
|
+
*
|
|
710
|
+
* 这个方法让「节流」与「数据完整性」解耦:
|
|
711
|
+
* - 被节流的 operation → `mergeTimelineState`(只进内存态,不 patch)
|
|
712
|
+
* - 下一次允许 patch → `updateTask` 把**累积后的**整条时间线 patch 出去
|
|
713
|
+
* - 任何时刻的 `exportState` 都能看到**全部**里程碑 → ledger 落库完整
|
|
714
|
+
*
|
|
715
|
+
* ## 与 `updateTask` 的区别
|
|
716
|
+
*
|
|
717
|
+
* `updateTask` 会**渲染并发送**卡片(一次 lark-cli 调用);本方法**不碰飞书**,
|
|
718
|
+
* 只动内存态。调用方负责决定何时真正 patch。
|
|
719
|
+
*
|
|
720
|
+
* @returns 是否真的并入了(state 不存在时返回 false —— 那张卡不是本 notifier 的)
|
|
721
|
+
*/
|
|
722
|
+
mergeTimelineState(messageId: string, milestones?: Milestone[], processSteps?: ProcessStep[]): boolean;
|
|
680
723
|
/**
|
|
681
724
|
* 暂停卡片(Task #4536:stop / archived)+ unpin,**保留**卡片状态与时间线
|
|
682
725
|
*
|
|
@@ -744,6 +787,24 @@ export declare class LarkCardPatchNotifier {
|
|
|
744
787
|
updateMetaAndBuildCard(messageId: string, meta: TaskMeta, opts?: {
|
|
745
788
|
clearPerTaskChat?: boolean;
|
|
746
789
|
}): CardPayload | undefined;
|
|
790
|
+
/**
|
|
791
|
+
* ★ Task #5020 —— 已经走到**真终态**的卡片(review round-4 MAJOR)。
|
|
792
|
+
*
|
|
793
|
+
* ## 为什么需要(结构性地堵住竞态,而不是靠时序检查)
|
|
794
|
+
*
|
|
795
|
+
* `finishTask` 结束后会 `states.delete(messageId)`。此时若有**另一个**
|
|
796
|
+
* 已经通过前置检查、正在等 mutex 的 `updateTask` 排队进来,它会因为
|
|
797
|
+
* 「state 不存在」而用空默认 state 重建卡片 → 把「已完成」刷回「进行中」
|
|
798
|
+
* 且清空里程碑。
|
|
799
|
+
*
|
|
800
|
+
* 前置检查(`cardMessageIds` / ledger status)只能挡住**还没开始**的补发;
|
|
801
|
+
* 已经进入 `mutexFor(messageId)` 队列的那一个挡不住。所以必须在
|
|
802
|
+
* notifier 内部——也就是唯一串行化那一步——做终态守卫。
|
|
803
|
+
*
|
|
804
|
+
* 记 messageId 而不是 taskId:reopen 场景会发一张**新卡**(新 messageId),
|
|
805
|
+
* 不会被旧 messageId 的终态记录误伤。
|
|
806
|
+
*/
|
|
807
|
+
private finalisedCards;
|
|
747
808
|
/** 诊断:当前跟踪中的卡片数(测试/自检用) */
|
|
748
809
|
trackedCardCount(): number;
|
|
749
810
|
/** 诊断:当前跟踪中的 workflow 卡片数(测试/自检用) */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_APP_LINK_BASE,
|
|
3
|
+
HEAD_TITLE_MAX_WIDTH,
|
|
3
4
|
LarkCardPatchNotifier,
|
|
4
5
|
buildChatAppLink,
|
|
5
6
|
buildCollapsiblePanel,
|
|
@@ -19,13 +20,15 @@ import {
|
|
|
19
20
|
renderTaskInfoLines,
|
|
20
21
|
renderWorkflowInfoLines,
|
|
21
22
|
resolveTaskTitleForDisplay,
|
|
22
|
-
sanitizeInlineText
|
|
23
|
-
|
|
23
|
+
sanitizeInlineText,
|
|
24
|
+
truncateHeadTitle
|
|
25
|
+
} from "../../../shared/@ai-setting/roy-agent-core-nmx9934r.js";
|
|
24
26
|
import"../../../shared/@ai-setting/roy-agent-core-qq96p0tj.js";
|
|
25
27
|
import"../../../shared/@ai-setting/roy-agent-core-7f7t9wwp.js";
|
|
26
28
|
import"../../../shared/@ai-setting/roy-agent-core-85xyctnb.js";
|
|
27
29
|
import"../../../shared/@ai-setting/roy-agent-core-fs0mn2jk.js";
|
|
28
30
|
export {
|
|
31
|
+
truncateHeadTitle,
|
|
29
32
|
sanitizeInlineText,
|
|
30
33
|
resolveTaskTitleForDisplay,
|
|
31
34
|
renderWorkflowInfoLines,
|
|
@@ -46,5 +49,6 @@ export {
|
|
|
46
49
|
buildCollapsiblePanel,
|
|
47
50
|
buildChatAppLink,
|
|
48
51
|
LarkCardPatchNotifier,
|
|
52
|
+
HEAD_TITLE_MAX_WIDTH,
|
|
49
53
|
DEFAULT_APP_LINK_BASE
|
|
50
54
|
};
|
|
@@ -149,6 +149,13 @@ export declare class LarkCliTaskNotifyHook implements Hook {
|
|
|
149
149
|
* key: `op:${taskId}`,value: 上次 patch 时间戳
|
|
150
150
|
*/
|
|
151
151
|
private lastNotifyTimestamps;
|
|
152
|
+
/**
|
|
153
|
+
* ★ Task #5020 —— 尾沿补发定时器(key: taskId)。
|
|
154
|
+
*
|
|
155
|
+
* 被节流的 operation 只登记一个待补发标记;窗口结束时补发**一次**
|
|
156
|
+
* patch,渲染累积后的完整时间线。见 {@link scheduleTrailingPatch}。
|
|
157
|
+
*/
|
|
158
|
+
private trailingPatchTimers;
|
|
152
159
|
/** 卡片路由端口(由 EventSource handler 注入) */
|
|
153
160
|
private cardRoutingPorts?;
|
|
154
161
|
/**
|
|
@@ -236,6 +243,37 @@ export declare class LarkCliTaskNotifyHook implements Hook {
|
|
|
236
243
|
* 旧实现会 fallback `startTask`(凭空多发一张卡)——已删除。
|
|
237
244
|
*/
|
|
238
245
|
private onAfterOperationCreate;
|
|
246
|
+
/**
|
|
247
|
+
* ★ Task #5020 —— 立即 patch 一次 operation 时间线。
|
|
248
|
+
*
|
|
249
|
+
* 失败只记日志:**不能**因为飞书侧失败就丢掉已经落进 ledger 的数据
|
|
250
|
+
* (ledger 落库在调用方、且早于本方法)。
|
|
251
|
+
*/
|
|
252
|
+
private patchOperationTimeline;
|
|
253
|
+
/**
|
|
254
|
+
* ★ Task #5020 —— 尾沿补发:窗口结束时把累积的时间线 patch 一次。
|
|
255
|
+
*
|
|
256
|
+
* ## 为什么需要(review round-2 MAJOR)
|
|
257
|
+
*
|
|
258
|
+
* 若「被节流就不 patch」,那条里程碑可能永远不上卡(等不到下一个事件);
|
|
259
|
+
* 若「被节流也立刻 patch」,节流就完全没有减少 patch 次数,形同虚设。
|
|
260
|
+
*
|
|
261
|
+
* 尾沿补发是两者的正解:窗口内的 N 条只排队、**不发**;窗口一结束补发
|
|
262
|
+
* **一次**,渲染当时**累积后的完整时间线**(`updateTask` 传空数组即用
|
|
263
|
+
* state 里的全部里程碑)。于是「可见性」与「限频」同时满足。
|
|
264
|
+
*
|
|
265
|
+
* - 同一 task 同时只挂一个定时器(重入只刷新,不叠加)
|
|
266
|
+
* - 定时器 `unref()`,不阻止进程退出
|
|
267
|
+
* - 补发失败只 warn(数据已在 ledger,跨进程回填仍有保障)
|
|
268
|
+
*/
|
|
269
|
+
private scheduleTrailingPatch;
|
|
270
|
+
/**
|
|
271
|
+
* ★ Task #5020 —— 取消该 task 待补发的尾沿 patch(终态 / 暂停时调用)。
|
|
272
|
+
*
|
|
273
|
+
* 与 {@link scheduleTrailingPatch} 里的二次校验互为双保险:
|
|
274
|
+
* 这里主动取消,避免即使校验通过也多发一次无意义的 patch。
|
|
275
|
+
*/
|
|
276
|
+
private cancelTrailingPatch;
|
|
239
277
|
/**
|
|
240
278
|
* 从持久层回填内存 messageId(一次性/幂等)
|
|
241
279
|
*
|
|
@@ -375,6 +413,10 @@ export declare class LarkCliTaskNotifyHook implements Hook {
|
|
|
375
413
|
*
|
|
376
414
|
* 同一 Task 在 operationThrottleMs(默认 5s)窗口内只 patch 一次,
|
|
377
415
|
* 避免 agent 每次 tool call 都刷屏 patch 卡片。
|
|
416
|
+
*
|
|
417
|
+
* ★ Task #5020 —— 返回 true **不代表丢弃**:被节流的 operation 仍会
|
|
418
|
+
* 并进 notifier 的内存态(`mergeTimelineState`)并落进共享 ledger,
|
|
419
|
+
* 只是**不立刻 patch 飞书**。节流只限制**频率**,不丢**数据**。
|
|
378
420
|
*/
|
|
379
421
|
private shouldThrottleOperation;
|
|
380
422
|
/** 检查是否应该发送通知 */
|
|
@@ -5,7 +5,8 @@ import {
|
|
|
5
5
|
TASK_DISCIPLINE_LIFECYCLE,
|
|
6
6
|
TASK_DISCIPLINE_OPERATION,
|
|
7
7
|
TASK_DISCIPLINE_PROMPT
|
|
8
|
-
} from "../../../shared/@ai-setting/roy-agent-core-
|
|
8
|
+
} from "../../../shared/@ai-setting/roy-agent-core-m46fe3x4.js";
|
|
9
|
+
import"../../../shared/@ai-setting/roy-agent-core-4rtg69cn.js";
|
|
9
10
|
import"../../../shared/@ai-setting/roy-agent-core-fs0mn2jk.js";
|
|
10
11
|
export {
|
|
11
12
|
TASK_DISCIPLINE_PROMPT,
|
|
@@ -21,12 +21,18 @@
|
|
|
21
21
|
* prompts-index(超大模板串)与外部 npm 消费方安全引用。
|
|
22
22
|
*/
|
|
23
23
|
/** 分片 1:生命周期契约(M1/M2/M13/M14/M15) */
|
|
24
|
-
export declare const TASK_DISCIPLINE_LIFECYCLE
|
|
24
|
+
export declare const TASK_DISCIPLINE_LIFECYCLE: string;
|
|
25
25
|
/** 分片 2:操作记录双维度规范(M3/M4/M5/M6/M16) */
|
|
26
26
|
export declare const TASK_DISCIPLINE_OPERATION = "### Operation Record \u2014 \u53CC\u7EF4\u5EA6\u5206\u5DE5\u89C4\u8303\n\n**Record milestones as you work** \u2014 call `task_operation_create` the moment a\nstage is reached, **not after the fact** (not in a batch at the end).\n\n**\u64CD\u4F5C\u8BB0\u5F55\u5FC5\u987B\u4E25\u683C\u533A\u5206\u4E24\u4E2A\u7EF4\u5EA6\uFF0C\u4E8C\u8005\u914D\u5957\u8BB0\u5F55\u3001\u5404\u53F8\u5176\u804C**\uFF1A\n\n#### \u7EF4\u5EA6 1\uFF1A\u72B6\u6001/\u91CC\u7A0B\u7891\uFF08\"\u8FBE\u5230\u4EC0\u4E48\"\uFF09\u2014 \u5FC5\u586B\u7EF4\u5EA6\n\u4F7F\u7528 `task_operation_create` \u7684 milestone_* \u4E3B\u5B57\u6BB5\uFF1A\n- **milestone_type**\uFF1A\u91CC\u7A0B\u7891\u7C7B\u578B\uFF08create / progress / milestone / problem / solution / decision / review / completed / workflow_extracted\uFF09\n- **milestone_title**\uFF1A\u91CC\u7A0B\u7891\u6807\u9898\uFF08\u4E00\u884C\uFF09\n- **milestone_description**\uFF1A\u8FBE\u6210\u7684\u72B6\u6001/\u7ED3\u679C\u63CF\u8FF0\uFF08\u53EF\u957F\u53EF\u77ED\uFF09\n\n#### \u7EF4\u5EA6 2\uFF1A\u8FC7\u7A0B\uFF08\"\u5982\u4F55\u8FBE\u5230\"\uFF09\u2014 \u53EF\u9009\u4F46\u63A8\u8350\u7EF4\u5EA6\n\u4F7F\u7528 `task_operation_create` \u7684 `process_description` \u5B57\u6BB5\uFF1A\n- \u5B57\u7B26\u8303\u56F4\u786C\u7EA6\u675F 100-500 \u5B57\u7B26 (100\u2013500 characters)\n- \u5185\u5BB9\uFF1A\u91C7\u53D6\u7684\u7B56\u7565 + \u5DE5\u5177\u6B65\u9AA4\u6982\u8981\n- \u5B8C\u6574\u8FC7\u7A0B\u901A\u8FC7 sessionId \u56DE\u67E5 session\n\n#### \u53CC\u7EF4\u5EA6\u914D\u5408\u94C1\u5F8B\n- \u274C **\u4E0D\u8981\u628A action \u5F53\u72B6\u6001**\uFF1A\u65E7 `action_*` \u547D\u540D\u504F\u52A8\u4F5C/\u884C\u4E3A\u5C42\uFF0C\u4E0D\u80FD\u8868\u8FBE\"\u6B64\u523B\u8FBE\u5230\u4EC0\u4E48\"\uFF1B\u73B0\u5728\u7EDF\u4E00\u6539\u7528 `milestone_*`\u3002\n- \u274C **\u4E0D\u8981\u8BA9 process_description \u4E0E milestone_description \u91CD\u590D**\uFF1Aprocess \u662F\"\u5982\u4F55\u8FBE\u5230\"\uFF0Cmilestone \u662F\"\u8FBE\u5230\u4EC0\u4E48\u72B6\u6001\"\u3002\n- \u2705 **\u914D\u5957\u8BB0\u5F55**\uFF1A\u6BCF\u4E2A\u6709\u610F\u4E49\u7684 operation \u90FD\u5E94\u540C\u65F6\u5305\u542B\u4E24\u8005\uFF1B\u4E0D\u5199 process \u65F6\uFF0Cdetail \u5E94\u901A\u8FC7 sessionId \u56DE\u67E5\u3002\n- \u26A0\uFE0F **\u517C\u5BB9\u7A97\u53E3\u671F**\uFF1A\u65E7 `action_type` / `action_title` / `action_description` \u4ECD\u88AB tool \u63A5\u53D7\uFF08\u6807\u8BB0 @deprecated\uFF09\uFF0C\u4F1A\u81EA\u52A8\u6620\u5C04\u5230 milestone_* \u5E76\u8FD4\u56DE deprecation warning\u3002\n\n#### \u8303\u4F8B\uFF08\u53CC\u7EF4\u5EA6\u9F50\u5168\u7684 operation \u8BB0\u5F55\uFF09\n```json\n{\n \"task_id\": 123,\n \"milestone_type\": \"milestone\",\n \"milestone_title\": \"GREEN \u901A\u8FC7\uFF1Amilestone_* schema/storage/tool \u5168\u94FE\u8DEF\",\n \"milestone_description\": \"21/21 \u6D4B\u8BD5\u901A\u8FC7\uFF0C\u5305\u542B 4 \u4E2A action_* alias \u517C\u5BB9\u6D4B\u8BD5\",\n \"process_description\": \"TDD RED \u5199 4 \u4E2A\u5931\u8D25\u6D4B\u8BD5\u8986\u76D6 storage/tool\uFF1B\u8FC1\u79FB 004 rename \u5217\uFF1BrowToOperation \u540C\u65F6\u8F93\u51FA\u53CC\u5B57\u6BB5\u517C\u5BB9\uFF1Btool zod preprocess \u81EA\u52A8\u6620\u5C04 action_*\"\n}\n```";
|
|
27
27
|
/** 分片 3:goals 编号子项规则(M7/M8/M9) */
|
|
28
28
|
export declare const TASK_DISCIPLINE_GOALS = "### Goals \u5B50\u9879\u62C6\u5206\u89C4\u5219\n\n`goals_and_expected_deliverables` **MUST** be written as\n**numbered sub-items** (\u7F16\u53F7\u5B50\u9879) that can each be verified\none by one (\u9010\u6761\u9A8C\u6536) \u2014 for `type=normal` tasks:\n\n1. \u5B9E\u73B0 X\uFF08\u542B\u6587\u4EF6\u8DEF\u5F84\uFF09\n2. \u6D4B\u8BD5 Y \u8986\u76D6 Z \u573A\u666F\uFF08pass/fail \u8BA1\u6570\uFF09\n3. \u6587\u6863 W \u843D\u76D8\u5230 <path>\n\n\u26A0\uFE0F For `type=longterm` / `type=cycle` tasks there is no\nper-item completion acceptance\uFF08\u4E0D\u8D70\u9010\u6761 complete \u9A8C\u6536\uFF09, so the\nMUST above does not apply; for those, it is **strongly recommended**\n(\u5EFA\u8BAE) to split goals into staged, individually checkable sub-items\n(\u9636\u6BB5\u6027\u53EF\u5224\u5B50\u9879) instead of one vague sentence.\n\nWhy: when the task is completed, the completion hook\n(task:after.complete) judges the whole goal against the\noperation-record chain, using each sub-item as fine-grained\nevidence (\u9010\u6761\u5BF9\u7167\u7684\u4F9D\u636E). Vague one-line goals (\u4E00\u53E5\u8BDD\u6A21\u7CCA\u76EE\u6807\uFF0C\n\u5982\u300C\u505A\u597D X\u300D\u300C\u5B8C\u6210\u8C03\u7814\u300D) give the judge nothing to check\nand make a completion hint much more likely.\n\nReference the four atomic assertion forms (Task #4768\n\u56DB\u539F\u5B50\u5F62\u6001) when writing each sub-item:\n\n- \u6587\u4EF6\u65AD\u8A00 (file assertion): file exists / size / content grep\n- \u8FDB\u7A0B\u65AD\u8A00 (process assertion): command exit code / stdout match\n- \u6D4B\u8BD5\u65AD\u8A00 (test assertion): pass/fail counts, no NEW fail\n- \u72B6\u6001\u65AD\u8A00 (state assertion): version number / HTTP 200 / status field";
|
|
29
|
-
/** 分片 4:complete 逐条验收 + HINT 核实义务(M10/M11/M12)
|
|
30
|
-
|
|
29
|
+
/** 分片 4:complete 逐条验收 + HINT 核实义务(M10/M11/M12)
|
|
30
|
+
*
|
|
31
|
+
* ★ Task #5007 —— 角色作用域说明:
|
|
32
|
+
* 本分片描述的是**验收方**(default agent / 接待员)的动作。
|
|
33
|
+
* 执行方(roy sub-agent)**没有** `task_complete` 权限,不适用本分片。
|
|
34
|
+
* 为避免执行方误读,段落开头显式声明「仅验收方适用」。
|
|
35
|
+
*/
|
|
36
|
+
export declare const TASK_DISCIPLINE_COMPLETE = "### Task Complete \u2014 \u6838\u5B9E\u4E49\u52A1\uFF08**\u4EC5\u9A8C\u6536\u65B9\u9002\u7528**\uFF09\n\n> \u26A0\uFE0F **\u89D2\u8272\u4F5C\u7528\u57DF\uFF08Task #5007\uFF09**\uFF1A\u672C\u8282\u662F**\u9A8C\u6536\u65B9**\uFF08default agent / \u63A5\u5F85\u5458\uFF09\u7684\u52A8\u4F5C\u3002\n> \u82E5\u4F60\u662F**\u6267\u884C\u65B9**\uFF08roy sub-agent\uFF09\uFF0C\u4F60\u6CA1\u6709 `task_complete` \u6743\u9650 \u2014\u2014\n> \u4F60\u7684\u6536\u5C3E\u52A8\u4F5C\u662F\u300C\u8FDB\u5EA6\u63A8\u5230 100% + \u8BB0\u5B8C\u64CD\u4F5C\u8BB0\u5F55 + \u7ED3\u675F\u8FD4\u56DE\u300D\uFF0C\u9A8C\u6536\u7531\u4E3B\u667A\u80FD\u4F53\u8D1F\u8D23\u3002\n\nBefore calling `task_complete`, you MUST:\n\n1. Read the task's `goal` (description) and `delivery` (goals_and_expected_deliverables) fields.\n - Use `task_get(task_id=<id>)` to fetch the full task record.\n2. **Validate whether each goal sub-item was achieved** \u2014 accept the goal\n **item-by-item** (\u6309\u5B50\u9879\u9010\u6761\u9A8C\u6536).\n - Goals should be numbered sub-items (\u7F16\u53F7\u5B50\u9879). Check\n each sub-item against the operation-record chain (\u64CD\u4F5C\u8BB0\u5F55\u94FE) and the\n deliverable evidence (context.deliverable_storage_path).\n - The completion hook (task:after.complete) judges the whole goal vs.\n deliverables; numbered sub-items give it finer-grained evidence to\n reason with (\u9010\u6761\u5BF9\u7167\u7684\u8BC1\u636E\u7C92\u5EA6). If it detects that the goal or\n deliverables appear unmet, the task context will carry a\n `[TASK_COMPLETION_HINT]`.\n - **If you receive a [TASK_COMPLETION_HINT]**, you MUST verify it\n (\u6838\u5B9E\u4E49\u52A1): re-read the task via `task_get`, then do exactly one of:\n (a) \u786E\u8BA4\u672A\u5B8C\u6210 \u2192 **\u91CD\u65B0\u59D4\u6258**\uFF08\u7528\u4F60\u7684\u59D4\u6258\u5DE5\u5177 + \u540C\u4E00 sub-session \u7EED\u8DD1\uFF0C\n \u5728\u6307\u4EE4\u91CC\u5199\u660E\"\u76EE\u6807\u5C1A\u672A\u8FBE\u6210\uFF0C\u9700\u8981\u8865 X/Y/Z\"\uFF09\uFF0C\u7531 sub-agent \u7528\n `task_update(status=active)` \u91CD\u5F00\u5E76\u7EE7\u7EED\u63A8\u8FDB\uFF1B\u82E5\u4F60**\u81EA\u5DF1\u5C31\u662F\u6267\u884C\u65B9**\n \uFF08\u6709 `task_update` \u6743\u9650\uFF09\uFF0C\u5219\u76F4\u63A5 `task_update(status=todo)` \u91CD\u5F00\uFF1B\u6216\n (b) \u786E\u8BA4\u5DF2\u5B8C\u6210 \u2192 **\u7528\u4F60\u624B\u4E0A\u6709\u6743\u9650\u7684\u5199\u5DE5\u5177**\u843D\u4E00\u6761 `decision` \u7C7B\u64CD\u4F5C\u8BB0\u5F55\n \uFF08`task_operation_create`\uFF0Cmilestone_type=decision\uFF0Cmilestone_title=<\u4E00\u884C\u7ED3\u8BBA>\uFF09\n \u8BF4\u660E\u5B50\u9879\u5B9E\u9645\u5DF2\u8FBE\u6210\uFF08\u8BF4\u660E\u7406\u7531\uFF09\u3002\u82E5\u4F60\u6CA1\u6709\u8BE5\u5DE5\u5177\u7684\u6743\u9650\uFF08\u9A8C\u6536\u65B9\u573A\u666F\uFF09\uFF0C\n \u5C31\u901A\u8FC7\u4F60\u7684**\u59D4\u6258\u5DE5\u5177**\u8BA9 sub-agent \u4EE3\u5199\u8FD9\u6761\u8BB0\u5F55\uFF0C\u6216\u5728\u6700\u7EC8\u6C47\u62A5\u91CC\n \u660E\u786E\u5199\u51FA\u6838\u5B9E\u7ED3\u8BBA\u4E0E\u8BC1\u636E\u3002\n Never ignore it (\u4E0D\u5141\u8BB8\u65E0\u89C6).\n \u26A0\uFE0F **\u6838\u5B9E\u4E49\u52A1\u7684\u4E24\u6761\u8DEF\u5F84\u90FD\u4F9D\u8D56\u5199\u6743\u9650**\uFF08`task_update` / `task_operation_create`\uFF09\u3002\n \u82E5\u8FD9\u4E9B\u5DE5\u5177\u5BF9\u4F60**\u4E0D\u53EF\u7528**\uFF08\u5982\u9A8C\u6536\u65B9\u4E0D\u6301\u6709\u6267\u884C\u7C7B\u5DE5\u5177\uFF09\uFF0C\u5FC5\u987B**\u6539\u7528\u59D4\u6258**\u628A\u52A8\u4F5C\n \u4EA4\u56DE\u7ED9\u6709\u6743\u9650\u7684 sub-agent \u6267\u884C \u2014\u2014 \u4E0D\u8981\u8BD5\u56FE\u8C03\u7528\u4E0D\u53EF\u7528\u7684\u5DE5\u5177\uFF08\u4F1A\u88AB\u62E6\u6389\u5E76\u6D6A\u8D39\u4E00\u8F6E\u8FED\u4EE3\uFF09\u3002\n - If the goal and delivery mismatch **without** a hint, either:\n (a) extend the task via `task_update`, or\n (b) record the discrepancy via `task_operation_create`\n (milestone_type=decision) \u2014 the reason **must** land in the\n operation record (\u5FC5\u987B\u843D\u5230\u64CD\u4F5C\u8BB0\u5F55\u91CC), not merely a line in\n your final report (\u4E0D\u80FD\u53EA\u5728\u62A5\u544A\u91CC\u5E26\u4E00\u53E5).\n3. Deliverables were submitted by the executor via `task_pre_complete`\n (Task #5073 two-phase acceptance): they live in\n `context.deliverable_storage_path` and the operation trail\n (`Deliverable: <path>` lines). Cross-check them in step 2.\n `task_complete` takes **no** deliverable parameter \u2014 if the\n deliverables are missing from the record, re-delegate instead of\n asking for a path here.";
|
|
31
37
|
/** 完整纪律正文(主出口):4 分片拼装 */
|
|
32
38
|
export declare const TASK_DISCIPLINE_PROMPT: string;
|
|
@@ -213,6 +213,54 @@ export declare class TaskComponent extends BaseComponent {
|
|
|
213
213
|
operations: TaskOperation[];
|
|
214
214
|
task: Task;
|
|
215
215
|
}) | undefined>;
|
|
216
|
+
/**
|
|
217
|
+
* ★ Task #5063 — 终态 current_status 收口辅助(**唯一**措辞/规则来源)
|
|
218
|
+
*
|
|
219
|
+
* 规则(测试锁死,勿改):
|
|
220
|
+
* 1. **只在 status 迁移到终态时**补 current_status
|
|
221
|
+
* —— 非终态(todo/active/paused)原样返回,不碰 current_status。
|
|
222
|
+
* (否则会破坏 `task_update(current_status="推进中")` 这类合法用法。)
|
|
223
|
+
* 2. **调用方显式传了 current_status 就尊重调用方**,不覆盖
|
|
224
|
+
* —— completeTask / cancelTaskTool 已在自己的调用里写好了带
|
|
225
|
+
* deliverable / reason 的终态文案,不能被这里冲掉。
|
|
226
|
+
* 3. 只认**本次更新要落**的 status —— `status` 缺省时一律不动。
|
|
227
|
+
*
|
|
228
|
+
* 终态集合与措辞:
|
|
229
|
+
* - completed → TASK_COMPLETED_STATUS_WORD(但 completeTask 自己写了带
|
|
230
|
+
* deliverable 的版本,走的是规则 2「尊重调用方」,不受这里影响)
|
|
231
|
+
* - cancelled → TASK_CANCELLED_STATUS_WORD
|
|
232
|
+
* - archived → TASK_ARCHIVED_STATUS_WORD
|
|
233
|
+
*
|
|
234
|
+
* ⚠️ 与 TASK_COMPLETE_TERMINAL_STATUSES(hooks/contexts.ts)**故意不同**:
|
|
235
|
+
* 那个集合决定「要不要 fire AFTER_COMPLETE 钩子」(archived 不 fire);
|
|
236
|
+
* 这个集合决定「要不要刷新 current_status」(archived 要刷)。
|
|
237
|
+
* 两者语义正交,别合并。
|
|
238
|
+
*
|
|
239
|
+
* ★ Task #5067 — 新增**反向**收口(reopen:终态 → 非终态)
|
|
240
|
+
*
|
|
241
|
+
* #5063 只管「迁入终态」。反向路径没管 ⇒ 任务从终态被 reopen 回
|
|
242
|
+
* active/todo 时,current_status 仍停在终态文案("已归档"/"已取消"/"已完成"),
|
|
243
|
+
* 出现「status: active 但 current_status: 已归档」的自相矛盾状态。
|
|
244
|
+
*
|
|
245
|
+
* 规则 4(新增,测试锁死):
|
|
246
|
+
* **从终态迁出到非终态,且当前 current_status 是系统写的终态文案时,
|
|
247
|
+
* 把 current_status 换成 reopen 措辞。**
|
|
248
|
+
*
|
|
249
|
+
* 为什么这不违反规则 1:
|
|
250
|
+
* 规则 1 说的「非终态迁移不碰 current_status」指的是**普通进度更新**
|
|
251
|
+
* (如 `task_update(current_status="推进中")`)—— 那必须保留调用方
|
|
252
|
+
* 显式传的值。而 reopen 时 current_status 里留着的是**系统自己写的
|
|
253
|
+
* 终态文案**,不是调用方的意图 ⇒ 这种情况**应该**被刷新。
|
|
254
|
+
*
|
|
255
|
+
* 判定用「值比对 + 前态 status」双条件(修法 A 增强版):
|
|
256
|
+
* - 值比对:current_status 以某个终态锚点**开头**(TASK_TERMINAL_STATUS_WORDS)
|
|
257
|
+
* - 前态 status:任务**当前**确实处于终态(archived/cancelled/completed)
|
|
258
|
+
* 两个条件同时成立才替换。为什么要加「前态」条件:
|
|
259
|
+
* 只看值的话,active 任务上手写的「已完成的部分:A/B/C」会被误判
|
|
260
|
+
* 成陈旧终态文案而被冲掉。加上前态判定后,只有**真的从终态迁出**
|
|
261
|
+
* 时才动 —— 把误伤面压到极窄。
|
|
262
|
+
*/
|
|
263
|
+
private withTerminalCurrentStatus;
|
|
216
264
|
/**
|
|
217
265
|
* Update task
|
|
218
266
|
*/
|
|
@@ -278,6 +326,37 @@ export declare class TaskComponent extends BaseComponent {
|
|
|
278
326
|
* @returns 更新后的 Task,任务不存在时返回 undefined
|
|
279
327
|
*/
|
|
280
328
|
updateTaskContext(id: number, context: string): Promise<Task | undefined>;
|
|
329
|
+
/**
|
|
330
|
+
* ★ Task #5073 — 提交待验证(两阶段验收的第一阶段)
|
|
331
|
+
*
|
|
332
|
+
* 需求(用户 2026-11-06 飞书):sub-agent 觉得可以完成了,
|
|
333
|
+
* 传交付物等参数调 task_pre_complete → task 状态变为 to_validate;
|
|
334
|
+
* default agent 调 task_complete 校验之后状态正式 completed。
|
|
335
|
+
*
|
|
336
|
+
* 语义要点:
|
|
337
|
+
* - to_validate **不是终态**:
|
|
338
|
+
* - 不加入 isTerminalTaskStatus(reopen 反向收口不管它)
|
|
339
|
+
* - 卡片(lark 插件)保持 running 更新态(cardStatusOf 不识别
|
|
340
|
+
* to_validate → 走 sendCardUpdate 普通 patch,不 unpin)
|
|
341
|
+
* - ★ 设计调整②(38603):preCompleteTask 在 updateTask 后**显式
|
|
342
|
+
* fire 一次 AFTER_COMPLETE**(goal 检查自查关,terminalStatus=
|
|
343
|
+
* to_validate);updateTask 本体已**不再**触发 AFTER_COMPLETE
|
|
344
|
+
* (见 updateTask 注释),本钩子的触发点唯一 = preCompleteTask。
|
|
345
|
+
* - current_status 同步(#5060 收口模式):措辞同源锚点
|
|
346
|
+
* TASK_TO_VALIDATE_STATUS_WORD =「待验证」,调用方传了
|
|
347
|
+
* progressSummary 就带上(「待验证:<summary>」)
|
|
348
|
+
* - 交付物双写(#2778 v2 同模式):context.deliverable_storage_path
|
|
349
|
+
* + operation 的 Deliverable 行
|
|
350
|
+
* - 幂等:重复提交安全(后一次覆盖前一次的 current_status /
|
|
351
|
+
* deliverable,operation 各自留痕)
|
|
352
|
+
*
|
|
353
|
+
* @param id 任务 ID
|
|
354
|
+
* @param sessionId 当前 session ID
|
|
355
|
+
* @param deliverableStoragePath 可选,交付物寻址地址
|
|
356
|
+
* @param progressSummary 可选,本次交付的进展摘要(拼进 current_status)
|
|
357
|
+
* @returns 更新后的 Task 或 undefined
|
|
358
|
+
*/
|
|
359
|
+
preCompleteTask(id: number, sessionId: string, deliverableStoragePath?: string, progressSummary?: string): Promise<Task | undefined>;
|
|
281
360
|
/**
|
|
282
361
|
* Create operation record
|
|
283
362
|
*/
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Task Cancel Tool (Task #5007)
|
|
3
|
+
*
|
|
4
|
+
* 架构背景 —— 验收权从 roy sub-agent 移交 default agent(接待员):
|
|
5
|
+
*
|
|
6
|
+
* 原本「验收」与「执行」都在 roy sub-agent 手里(裁判和运动员同一人),
|
|
7
|
+
* 且 sub-agent 超时 / 未更新状态时任务状态会长期不同步。
|
|
8
|
+
* 调整后 default agent 承担验收:
|
|
9
|
+
* - task_complete —— 核对产出后判定完成(触发 goal 检查 decision model)
|
|
10
|
+
* - task_cancel —— **仅在用户明令取消时**取消任务
|
|
11
|
+
*
|
|
12
|
+
* 语义边界(Task #5055,用户明令):
|
|
13
|
+
* task_cancel 是**用户明令**才能调的 —— 用户说"取消 / 停掉这个任务"。
|
|
14
|
+
* 失败 / 超时 ≠ 取消:正确的出路是找根因 → 提修复方案 → 重新委托
|
|
15
|
+
* (可用 sub_session_id 续跑)→ 实在推不动就如实告知用户、等用户决定,
|
|
16
|
+
* **不自行 cancel**。
|
|
17
|
+
*
|
|
18
|
+
* 本工具的职责边界:
|
|
19
|
+
* - **取消 Task 本身**(task.status = "cancelled")
|
|
20
|
+
* - **不是**停后台进程 —— 那是 `stop_task` 的职责(stop_task 停 bg process,
|
|
21
|
+
* task_cancel 停 Task 记录)。两者正交,default agent 可能需要连用:
|
|
22
|
+
* 先 stop_task 掐掉还在跑的 sub-agent,再 task_cancel 取消任务记录。
|
|
23
|
+
*
|
|
24
|
+
* 终态 hook:`cancelled` 属于 TASK_COMPLETE_TERMINAL_STATUSES。
|
|
25
|
+
* ⚠️ Task #5073 设计调整②:updateTask **不再** fire
|
|
26
|
+
* AFTER_COMPLETE —— 终态通知走 task:after.update
|
|
27
|
+
* (lark-card 状态机 cardStatusOf 覆盖 completed/cancelled/
|
|
28
|
+
* archived 等),本工具无需额外接线。
|
|
29
|
+
*/
|
|
30
|
+
import type { Tool } from "../../tool/types";
|
|
31
|
+
import type { TaskComponent } from "../task-component";
|
|
32
|
+
/**
|
|
33
|
+
* task_cancel 工具描述(导出便于单测和未来 reuse)
|
|
34
|
+
*/
|
|
35
|
+
export declare const TASK_CANCEL_DESCRIPTION: string;
|
|
36
|
+
export declare function cancelTaskTool(taskComponent: TaskComponent): Tool;
|
|
@@ -25,3 +25,95 @@ export declare const TASK_COMPLETE_ACCEPTANCE: {
|
|
|
25
25
|
readonly hintAnchor: "TASK_COMPLETION_HINT";
|
|
26
26
|
readonly verifyDuty: "核实义务";
|
|
27
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* Task #5060 — 终态 current_status 文案同源锚点
|
|
30
|
+
*
|
|
31
|
+
* 背景:`task_complete` / `task_cancel` 原来只改 status/progress,
|
|
32
|
+
* **完全不碰 current_status** ⇒ 任务落终态后 current_status 仍留着
|
|
33
|
+
* 完成前的旧文案(如「按用户方案 X 决定暂停:未 commit」),出现
|
|
34
|
+
* 「status=completed 但描述说没做完」的自相矛盾状态。
|
|
35
|
+
*
|
|
36
|
+
* 修复:终态工具在同一次 updateTask 里把 current_status 一起写成终态语义。
|
|
37
|
+
* 下面的短语是「终态 current_status」的**唯一措辞来源** ——
|
|
38
|
+
* task-component(完成)/ cancel-tool(取消)都引用它,避免两处漂移。
|
|
39
|
+
*/
|
|
40
|
+
/** 完成态 current_status 的核心语义词 */
|
|
41
|
+
export declare const TASK_COMPLETED_STATUS_WORD = "\u5DF2\u5B8C\u6210";
|
|
42
|
+
/** 取消态 current_status 的核心语义词 */
|
|
43
|
+
export declare const TASK_CANCELLED_STATUS_WORD = "\u5DF2\u53D6\u6D88";
|
|
44
|
+
/** 交付物已记录的前缀(跟在终态词之后) */
|
|
45
|
+
export declare const TASK_DELIVERABLE_RECORDED = "\u4EA4\u4ED8\u7269\u5DF2\u8BB0\u5F55";
|
|
46
|
+
/**
|
|
47
|
+
* Task #5063 — 归档态 current_status 的核心语义词
|
|
48
|
+
*
|
|
49
|
+
* 背景(Task #5060 的 follow-up,DS review 留档 MINOR m2):
|
|
50
|
+
* `archived` 是「终态 current_status 不刷新」这个 bug 的**第四个出口**。
|
|
51
|
+
* #5060 只修了 completed / cancelled 两条路径,导致走归档路径
|
|
52
|
+
* (`tasks complete --archive`、批量归档工具、通用 task_update)
|
|
53
|
+
* 的任务完成后 current_status 仍留着归档前的旧文案。
|
|
54
|
+
*
|
|
55
|
+
* 本锚点与 TASK_COMPLETED_STATUS_WORD / TASK_CANCELLED_STATUS_WORD 并列,
|
|
56
|
+
* 是「归档态 current_status」的**唯一措辞来源**。
|
|
57
|
+
*/
|
|
58
|
+
export declare const TASK_ARCHIVED_STATUS_WORD = "\u5DF2\u5F52\u6863";
|
|
59
|
+
/**
|
|
60
|
+
* Task #5067 — reopen(终态 → 非终态)后 current_status 的核心语义词
|
|
61
|
+
*
|
|
62
|
+
* 背景(Task #5063 DS review 留档 MINOR m1):
|
|
63
|
+
* #5063 只收口了「**迁入**终态时刷新 current_status」,**反向**路径没管:
|
|
64
|
+
* 任务从终态被 reopen 回 active/todo 时,current_status 仍停在终态文案
|
|
65
|
+
* ("已归档" / "已取消" / "已完成")⇒ 出现
|
|
66
|
+
* status: active / current_status: "已归档" ← 说反了
|
|
67
|
+
*
|
|
68
|
+
* 为什么措辞是「已重新打开」而不是清空:
|
|
69
|
+
* 卡片渲染(lark-card-patch-notifier.ts)与 CLI(tasks get / tasks search)
|
|
70
|
+
* 都用 `if (current_status)` 守卫 —— **空串会让整行消失**,用户看到的是
|
|
71
|
+
* 一张没有「📶 当前状态」行的卡片,而不是「已重新打开」。
|
|
72
|
+
* 「已重新打开」非空、可渲染、语义明确(区别于「已完成」这类终态词)。
|
|
73
|
+
*/
|
|
74
|
+
export declare const TASK_REOPENED_STATUS_WORD = "\u5DF2\u91CD\u65B0\u6253\u5F00";
|
|
75
|
+
/**
|
|
76
|
+
* Task #5073 — 待验证(to_validate)current_status 的核心语义词
|
|
77
|
+
*
|
|
78
|
+
* 两阶段验收(#5007 的机制化落地):
|
|
79
|
+
* sub-agent 干完 → `task_pre_complete` → status=to_validate,
|
|
80
|
+
* current_status 刷成「待验证」;default agent `task_complete`
|
|
81
|
+
* 校验通过后才落 completed(措辞 TASK_COMPLETED_STATUS_WORD)。
|
|
82
|
+
*
|
|
83
|
+
* 与终态措辞(TASK_COMPLETED_STATUS_WORD 等)并列但**不入**
|
|
84
|
+
* TASK_TERMINAL_STATUS_WORDS —— to_validate 是**非终态**
|
|
85
|
+
* (reopen 反向收口管不着它:从 to_validate 迁出时 current_status
|
|
86
|
+
* 本来就该带「待验证」语义,由 withTerminalCurrentStatus 的
|
|
87
|
+
* 非终态分支按调用方意图处理)。
|
|
88
|
+
*/
|
|
89
|
+
export declare const TASK_TO_VALIDATE_STATUS_WORD = "\u5F85\u9A8C\u8BC1";
|
|
90
|
+
/**
|
|
91
|
+
* Task #5067 — 终态 current_status 措辞锚点集合(reopen 判定的**唯一**依据)
|
|
92
|
+
*
|
|
93
|
+
* 用途:`withTerminalCurrentStatus` 在「迁出终态」时,需要判断当前
|
|
94
|
+
* current_status 是不是**系统写的终态文案**(而不是调用方自己写的)。
|
|
95
|
+
* 判定方式 = current_status 以本集合中任一锚点**开头**。
|
|
96
|
+
*
|
|
97
|
+
* ⚠️ 为什么用 startsWith 而不是 includes:
|
|
98
|
+
* 终态文案可能带后缀(如「已归档:批量整理」「已完成(交付物已记录:/x.md)」),
|
|
99
|
+
* 但**开头**的锚点才是系统写的语义主体。反过来,包含判断会误伤
|
|
100
|
+
* 调用方自己写的「已完成的部分:A/B/C」这类正常文案。
|
|
101
|
+
*
|
|
102
|
+
* ⚠️ 边界取舍(已知且接受):
|
|
103
|
+
* 若调用方**恰好手动写了**以「已完成」/「已取消」/「已归档」开头的文案,
|
|
104
|
+
* 且任务当时正处于终态,reopen 时该文案会被系统措辞替换。
|
|
105
|
+
* 这是「值比对」方案的固有代价 —— 用「前态 status 是终态」这一额外条件
|
|
106
|
+
* 把它压到极窄(只在真的从终态迁出、且文案形状与系统措辞完全一致时触发)。
|
|
107
|
+
*/
|
|
108
|
+
export declare const TASK_TERMINAL_STATUS_WORDS: readonly ["已完成", "已取消", "已归档"];
|
|
109
|
+
/**
|
|
110
|
+
* ★ Task #5073(DS review r4 MINOR-3)— 终态护栏集合的同源锚点:
|
|
111
|
+
* 已终态(cancelled / archived)任务**不可**被「验收通过」翻转成
|
|
112
|
+
* completed。消费点:TaskComponent.completeTask(组件层护栏,
|
|
113
|
+
* 兜底 CLI / 直连通道)+ complete-tool.ts(tool 层友好报错)。
|
|
114
|
+
*
|
|
115
|
+
* ⚠️ to_validate / active / todo / paused **不在**集合里 ——
|
|
116
|
+
* 规范路径 to_validate → completed 与兜底路径 active →
|
|
117
|
+
* completed(#5054 补验收)都必须放行。
|
|
118
|
+
*/
|
|
119
|
+
export declare const TERMINAL_NON_ACCEPTABLE_STATUSES: readonly ["cancelled", "archived"];
|
|
@@ -10,4 +10,6 @@ export { batchDeleteTaskTool } from "./batch-delete-tool";
|
|
|
10
10
|
export { updateTaskTool } from "./update-tool";
|
|
11
11
|
export { deleteTaskTool } from "./delete-tool";
|
|
12
12
|
export { completeTaskTool } from "./complete-tool";
|
|
13
|
+
export { cancelTaskTool } from "./cancel-tool";
|
|
14
|
+
export { preCompleteTaskTool } from "./pre-complete-tool";
|
|
13
15
|
export { treeTasksTool } from "./task-tree-tool";
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
batchArchiveTaskTool,
|
|
3
3
|
batchDeleteTaskTool,
|
|
4
|
+
cancelTaskTool,
|
|
4
5
|
completeTaskTool,
|
|
5
6
|
createTaskTool,
|
|
6
7
|
deleteTaskTool,
|
|
7
8
|
getTaskTool,
|
|
8
9
|
listTasksTool,
|
|
10
|
+
preCompleteTaskTool,
|
|
9
11
|
searchTasksTool,
|
|
10
12
|
treeTasksTool,
|
|
11
13
|
updateTaskTool
|
|
12
|
-
} from "../../../shared/@ai-setting/roy-agent-core-
|
|
14
|
+
} from "../../../shared/@ai-setting/roy-agent-core-vffccgf6.js";
|
|
13
15
|
import"../../../shared/@ai-setting/roy-agent-core-tr3ep81v.js";
|
|
14
|
-
import"../../../shared/@ai-setting/roy-agent-core-
|
|
16
|
+
import"../../../shared/@ai-setting/roy-agent-core-m46fe3x4.js";
|
|
17
|
+
import"../../../shared/@ai-setting/roy-agent-core-4rtg69cn.js";
|
|
15
18
|
import"../../../shared/@ai-setting/roy-agent-core-7cbpmk4q.js";
|
|
16
19
|
import"../../../shared/@ai-setting/roy-agent-core-qq96p0tj.js";
|
|
17
20
|
import"../../../shared/@ai-setting/roy-agent-core-7f7t9wwp.js";
|
|
@@ -21,11 +24,13 @@ export {
|
|
|
21
24
|
updateTaskTool,
|
|
22
25
|
treeTasksTool,
|
|
23
26
|
searchTasksTool,
|
|
27
|
+
preCompleteTaskTool,
|
|
24
28
|
listTasksTool,
|
|
25
29
|
getTaskTool,
|
|
26
30
|
deleteTaskTool,
|
|
27
31
|
createTaskTool,
|
|
28
32
|
completeTaskTool,
|
|
33
|
+
cancelTaskTool,
|
|
29
34
|
batchDeleteTaskTool,
|
|
30
35
|
batchArchiveTaskTool
|
|
31
36
|
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Task Pre-Complete Tool (Task #5073 — 两阶段验收)
|
|
3
|
+
*
|
|
4
|
+
* 需求(用户 2026-11-06 飞书原话):
|
|
5
|
+
* 「给 subagent 添加一个跟 task_complete 类似的工具,比如
|
|
6
|
+
* task_pre_complete,sub agent 觉得可以完成了就传入交付物等参数,
|
|
7
|
+
* task 状态变为待验证(to_validate),default agent 调用
|
|
8
|
+
* task_complete 校验之后状态正式完成。」
|
|
9
|
+
*
|
|
10
|
+
* 职责边界(沿用 #5007「执行与验收分离」架构):
|
|
11
|
+
* - **执行方(roy sub-agent)**:干完活 → task_pre_complete 提交待验证
|
|
12
|
+
* (status → to_validate + 交付物落 context/operation)
|
|
13
|
+
* - **验收方(default agent)**:task_complete 逐条验收 → completed
|
|
14
|
+
*
|
|
15
|
+
* 与 task_complete 的关系:
|
|
16
|
+
* - 参数同构(deliverable_storage_path),调用体验一致
|
|
17
|
+
* - 语义不同:这里只是「提交待验证」,不是终态 —— 会 fire 一次
|
|
18
|
+
* AFTER_COMPLETE(terminalStatus="to_validate")作为 goal 检查
|
|
19
|
+
* 自查关(design v2 #38603),卡片保持 running 更新态
|
|
20
|
+
*
|
|
21
|
+
* current_status 同步:走 TaskComponent.preCompleteTask →
|
|
22
|
+
* updateTask(withTerminalCurrentStatus 收口模式之外的本层显式文案,
|
|
23
|
+
* 措辞同源锚点 TASK_TO_VALIDATE_STATUS_WORD = 「待验证」,
|
|
24
|
+
* 见 tools/completion-copy.ts —— 与 #5060 的 completed/cancelled 同模式)。
|
|
25
|
+
*/
|
|
26
|
+
import type { Tool } from "../../tool/types";
|
|
27
|
+
import type { TaskComponent } from "../task-component";
|
|
28
|
+
/**
|
|
29
|
+
* task_pre_complete 工具描述(导出便于单测和 reuse)
|
|
30
|
+
*/
|
|
31
|
+
export declare const TASK_PRE_COMPLETE_DESCRIPTION: string;
|
|
32
|
+
export declare function preCompleteTaskTool(taskComponent: TaskComponent): Tool;
|