@ai-setting/roy-agent-core 1.7.75 → 1.7.77

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.
Files changed (59) hide show
  1. package/dist/env/agent/agent-component.js +2 -2
  2. package/dist/env/agent/index.js +2 -2
  3. package/dist/env/event-source/event-source-handlers.js +9 -8
  4. package/dist/env/event-source/index.js +10 -9
  5. package/dist/env/index.js +16 -15
  6. package/dist/env/prompt/index.js +4 -3
  7. package/dist/env/prompt/prompts-index.d.ts +11 -9
  8. package/dist/env/task/backend/index.js +45 -1
  9. package/dist/env/task/backend/task-store-backend.d.ts +12 -0
  10. package/dist/env/task/backend/types.d.ts +19 -0
  11. package/dist/env/task/delegate/delegate-tool.js +4 -3
  12. package/dist/env/task/delegate/index.js +4 -3
  13. package/dist/env/task/hooks/contexts.d.ts +12 -1
  14. package/dist/env/task/hooks/task-hook-points.d.ts +8 -3
  15. package/dist/env/task/index.d.ts +1 -0
  16. package/dist/env/task/index.js +17 -7
  17. package/dist/env/task/mcp/index.js +6 -2
  18. package/dist/env/task/mcp/task-mcp-server.d.ts +1 -1
  19. package/dist/env/task/plugins/fake-user-message-helper.d.ts +10 -2
  20. package/dist/env/task/plugins/index.d.ts +1 -0
  21. package/dist/env/task/plugins/index.js +18 -6
  22. package/dist/env/task/plugins/lark-card-patch-notifier.js +1 -1
  23. package/dist/env/task/plugins/task-op-watermark-plugin.d.ts +112 -0
  24. package/dist/env/task/prompt/index.js +2 -1
  25. package/dist/env/task/prompt/task-discipline.d.ts +1 -1
  26. package/dist/env/task/storage/index.js +2 -2
  27. package/dist/env/task/storage/sqlite-task-store.d.ts +54 -0
  28. package/dist/env/task/task-component.d.ts +95 -0
  29. package/dist/env/task/tools/cancel-tool.d.ts +12 -4
  30. package/dist/env/task/tools/completion-copy.d.ts +92 -0
  31. package/dist/env/task/tools/index.d.ts +1 -0
  32. package/dist/env/task/tools/index.js +5 -2
  33. package/dist/env/task/tools/operation/operation-types.d.ts +13 -13
  34. package/dist/env/task/tools/pre-complete-tool.d.ts +32 -0
  35. package/dist/env/task/tools/task-types.d.ts +49 -17
  36. package/dist/env/task/types.d.ts +13 -1
  37. package/dist/env/workflow/plugins/index.js +2 -2
  38. package/dist/env/workflow/types/event.d.ts +4 -4
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.js +26 -16
  41. package/dist/shared/@ai-setting/{roy-agent-core-n9q1encx.js → roy-agent-core-0v27y99n.js} +1 -1
  42. package/dist/shared/@ai-setting/{roy-agent-core-60jbrfye.js → roy-agent-core-3gpygqcx.js} +30 -6
  43. package/dist/shared/@ai-setting/roy-agent-core-4rtg69cn.js +26 -0
  44. package/dist/shared/@ai-setting/{roy-agent-core-djpq6yb0.js → roy-agent-core-9vhq7fvv.js} +6 -2
  45. package/dist/shared/@ai-setting/{roy-agent-core-3e6gg17d.js → roy-agent-core-9vxh6f8h.js} +169 -30
  46. package/dist/shared/@ai-setting/{roy-agent-core-jg65qnwa.js → roy-agent-core-aa2j7bk9.js} +1 -1
  47. package/dist/shared/@ai-setting/{roy-agent-core-29b6hc39.js → roy-agent-core-cmprygrp.js} +1 -1
  48. package/dist/shared/@ai-setting/{roy-agent-core-snvh4s2p.js → roy-agent-core-ew6qb5yx.js} +1 -1
  49. package/dist/shared/@ai-setting/{roy-agent-core-abqhkbn3.js → roy-agent-core-ezvpreqz.js} +23 -0
  50. package/dist/shared/@ai-setting/roy-agent-core-h21gngxf.js +247 -0
  51. package/dist/shared/@ai-setting/{roy-agent-core-p3zv1mx5.js → roy-agent-core-hd3n57zs.js} +1 -1
  52. package/dist/shared/@ai-setting/{roy-agent-core-11shp00p.js → roy-agent-core-m46fe3x4.js} +21 -31
  53. package/dist/shared/@ai-setting/{roy-agent-core-ntq0gz7q.js → roy-agent-core-q813vafd.js} +1 -1
  54. package/dist/shared/@ai-setting/{roy-agent-core-4gr3k7qg.js → roy-agent-core-rhtdspx6.js} +140 -29
  55. package/dist/shared/@ai-setting/{roy-agent-core-y7x2qzwc.js → roy-agent-core-rsn44n9y.js} +10 -6
  56. package/dist/shared/@ai-setting/{roy-agent-core-hnyk1by7.js → roy-agent-core-vffccgf6.js} +152 -33
  57. package/dist/shared/@ai-setting/{roy-agent-core-nmx9934r.js → roy-agent-core-w0qjeq2v.js} +1 -1
  58. package/package.json +1 -1
  59. package/dist/shared/@ai-setting/roy-agent-core-f77k3gqt.js +0 -71
@@ -3,11 +3,11 @@ import {
3
3
  } from "./roy-agent-core-na18zwj0.js";
4
4
  import {
5
5
  WORKFLOW_EXTRACT_PROMPT
6
- } from "./roy-agent-core-3e6gg17d.js";
6
+ } from "./roy-agent-core-9vxh6f8h.js";
7
7
  import {
8
8
  createCompatibleDatabase,
9
9
  init_sqlite_task_store
10
- } from "./roy-agent-core-abqhkbn3.js";
10
+ } from "./roy-agent-core-ezvpreqz.js";
11
11
  import {
12
12
  TaskHookPoints
13
13
  } from "./roy-agent-core-1pg0fepg.js";
@@ -24,13 +24,13 @@ import {
24
24
  import {
25
25
  LarkCardPatchNotifier,
26
26
  humanizeValue
27
- } from "./roy-agent-core-nmx9934r.js";
27
+ } from "./roy-agent-core-w0qjeq2v.js";
28
28
  import {
29
29
  validateWorkflowDefinition
30
30
  } from "./roy-agent-core-1v4g0d4x.js";
31
31
  import {
32
32
  enqueueToAddFakeUserMessage
33
- } from "./roy-agent-core-f77k3gqt.js";
33
+ } from "./roy-agent-core-h21gngxf.js";
34
34
  import {
35
35
  BasePlugin
36
36
  } from "./roy-agent-core-az13yzmc.js";
@@ -1515,8 +1515,8 @@ class LayaCompletionPlugin {
1515
1515
  logger5.warn("[laya-completion] taskComponent not injected — skip");
1516
1516
  return;
1517
1517
  }
1518
- if (ctx.terminalStatus !== "completed") {
1519
- logger5.debug(`[laya-completion] terminalStatus=${ctx.terminalStatus} — skip (only completed)`);
1518
+ if (ctx.terminalStatus !== "completed" && ctx.terminalStatus !== "to_validate") {
1519
+ logger5.debug(`[laya-completion] terminalStatus=${ctx.terminalStatus} — skip (only completed / to_validate)`);
1520
1520
  return;
1521
1521
  }
1522
1522
  const task = ctx.task;
@@ -2116,6 +2116,10 @@ class LarkCliTaskNotifyHook {
2116
2116
  return;
2117
2117
  if (!this.isCardModeEnabled())
2118
2118
  return;
2119
+ const terminalStatus = data.terminalStatus;
2120
+ if (terminalStatus === "to_validate" || task.status === "to_validate") {
2121
+ return;
2122
+ }
2119
2123
  await this.sendCardFinish(task);
2120
2124
  }
2121
2125
  async onAfterDelete(ctx) {
@@ -3,11 +3,16 @@ import {
3
3
  NEW_TASK_ID_PLACEHOLDER
4
4
  } from "./roy-agent-core-tr3ep81v.js";
5
5
  import {
6
+ TASK_DISCIPLINE_GOALS
7
+ } from "./roy-agent-core-m46fe3x4.js";
8
+ import {
9
+ TASK_ARCHIVED_STATUS_WORD,
10
+ TASK_CANCELLED_STATUS_WORD,
6
11
  TASK_COMPLETE_ITEM_BY_ITEM,
7
12
  TASK_COMPLETE_VERIFY_DUTY,
8
13
  TASK_COMPLETION_HINT_ANCHOR,
9
- TASK_DISCIPLINE_GOALS
10
- } from "./roy-agent-core-11shp00p.js";
14
+ TERMINAL_NON_ACCEPTABLE_STATUSES
15
+ } from "./roy-agent-core-4rtg69cn.js";
11
16
  import {
12
17
  getEnvContextOrEmpty,
13
18
  init_env_context,
@@ -63,7 +68,7 @@ var GetTaskToolSchema = withLegacyTaskId({
63
68
  include_operations: z.boolean().optional().default(true).describe("Include operation records (milestones / process log) with the task. " + "Defaults to true — the task's operation history is part of its detail. " + "Pass false for a lean task-only response.")
64
69
  });
65
70
  var ListTasksToolSchema = z.object({
66
- status: z.enum(["todo", "active", "completed", "paused", "cancelled", "archived"]).optional(),
71
+ status: z.enum(["todo", "active", "to_validate", "completed", "paused", "cancelled", "archived"]).optional(),
67
72
  priority: z.enum(["low", "medium", "high"]).optional(),
68
73
  type: z.enum(["normal", "cycle", "longterm"]).optional().describe("Filter by task type"),
69
74
  limit: z.number().optional().default(20),
@@ -75,7 +80,7 @@ var SearchTasksToolSchema = z.object({
75
80
  keywords: z.array(z.string()).describe("关键词列表(AND 逻辑,匹配 title/description/goals/tags/operations)"),
76
81
  limit: z.number().optional().default(20).describe("返回数量"),
77
82
  offset: z.number().optional().default(0).describe("偏移量"),
78
- status: z.enum(["todo", "active", "completed", "paused", "cancelled", "archived"]).optional().describe("按状态筛选"),
83
+ status: z.enum(["todo", "active", "to_validate", "completed", "paused", "cancelled", "archived"]).optional().describe("按状态筛选"),
79
84
  priority: z.enum(["low", "medium", "high"]).optional().describe("按优先级筛选"),
80
85
  type: z.enum(["normal", "cycle", "longterm"]).optional().describe("按类型筛选"),
81
86
  exclude_task_id: z.number().optional().describe("排除的 task ID"),
@@ -85,7 +90,7 @@ var SearchTasksToolSchema = z.object({
85
90
  var UpdateTaskToolSchema = withLegacyTaskId({
86
91
  title: z.string().optional(),
87
92
  description: z.string().optional(),
88
- status: z.enum(["todo", "active", "completed", "paused", "cancelled", "archived"]).optional(),
93
+ status: z.enum(["todo", "active", "to_validate", "completed", "paused", "cancelled", "archived"]).optional(),
89
94
  priority: z.enum(["low", "medium", "high"]).optional(),
90
95
  type: z.enum(["normal", "cycle", "longterm"]).optional().describe("Task type"),
91
96
  progress: z.number().min(0).max(100).optional(),
@@ -100,8 +105,10 @@ var UpdateTaskToolSchema = withLegacyTaskId({
100
105
  var DeleteTaskToolSchema = z.object({
101
106
  task_id: z.number().describe("Task ID")
102
107
  });
103
- var CompleteTaskToolSchema = withLegacyTaskId({
104
- deliverable_storage_path: z.string().optional().describe("交付物的寻址地址(路径 / URL / 分支名等)。" + "调用本工具前,请先读取任务的 goal(description)和 delivery(goals_and_expected_deliverables)栏位," + "建议验证目标和交付物是否符合预期,然后将实际交付物的寻址地址填入此参数。")
108
+ var CompleteTaskToolSchema = withLegacyTaskId({});
109
+ var PreCompleteTaskToolSchema = withLegacyTaskId({
110
+ deliverable_storage_path: z.string().optional().describe("交付物的寻址地址(路径 / URL / 分支名等)。" + "会持久化到 task.context.deliverable_storage_path," + "并写入 operation 记录(Deliverable 行),供验收方 task_complete 时逐条对照。"),
111
+ current_status: z.string().optional().describe("本次交付的进展摘要(可选)。" + "会拼进「待验证:」文案,作为任务当前状态展示给验收方(default agent)。")
105
112
  });
106
113
  var CancelTaskToolSchema = withLegacyTaskId({
107
114
  reason: z.string().optional().describe("取消原因(可选)。会写入该任务的 operation 记录,便于事后追溯验收结论。")
@@ -116,7 +123,7 @@ var BatchDeleteToolSchema = z.object({
116
123
  var TreeTasksToolSchema = z.object({
117
124
  depth: z.number().optional().default(2).describe("树的展开深度。默认 2 (根 + 一层子任务 + 二层孙任务)。" + "0 = 只返回根任务,不展开任何子节点。" + "-1 或负数 = 无限层级(全部展开)。"),
118
125
  parent_task_id: z.number().optional().describe("只看指定父任务的子树。不传则从所有根任务(forest)开始。"),
119
- status: z.enum(["todo", "active", "completed", "paused", "cancelled", "archived"]).optional().describe("按状态过滤(与 task_list 一致)。"),
126
+ status: z.enum(["todo", "active", "to_validate", "completed", "paused", "cancelled", "archived"]).optional().describe("按状态过滤(与 task_list 一致)。"),
120
127
  priority: z.enum(["low", "medium", "high"]).optional().describe("按优先级过滤。"),
121
128
  type: z.enum(["normal", "cycle", "longterm"]).optional().describe("按任务类型过滤。"),
122
129
  include_archived: z.boolean().optional().default(false).describe("是否包含已归档任务(默认 false,与 task_list 一致)。")
@@ -702,7 +709,10 @@ function batchArchiveTaskTool(taskComponent) {
702
709
  let archivedCount = 0;
703
710
  for (const taskId of taskIds) {
704
711
  try {
705
- const task = await taskComponent.updateTask(taskId, { status: "archived" });
712
+ const task = await taskComponent.updateTask(taskId, {
713
+ status: "archived",
714
+ current_status: params.reason ? `${TASK_ARCHIVED_STATUS_WORD}:${params.reason}` : TASK_ARCHIVED_STATUS_WORD
715
+ });
706
716
  if (task) {
707
717
  await taskComponent.createOperation({
708
718
  taskId,
@@ -940,7 +950,11 @@ init_env_context();
940
950
  init_logger();
941
951
  var logger4 = createLogger("task:tools:complete");
942
952
  var TASK_COMPLETE_DESCRIPTION = `
943
- Mark a task as completed (progress=100, status=completed). Creates an operation record.
953
+ Final acceptance of a submitted task: set status=completed, progress=100
954
+ (two-phase acceptance, Task #5073).
955
+
956
+ **Who should call this** — the **acceptance side** (default agent). The
957
+ executor (sub-agent) has NO permission to call it (deniedTools, Task #5007).
944
958
 
945
959
  **Before calling this tool**, you MUST:
946
960
 
@@ -968,21 +982,27 @@ Mark a task as completed (progress=100, status=completed). Creates an operation
968
982
  (milestone_type=decision) — the reason **must** land in the
969
983
  operation record (必须落到操作记录里), not merely a line in
970
984
  your final report (不能只在报告里带一句).
971
- 3. **Provide \`deliverable_storage_path\`** parameter with the deliverable's address:
972
- - Feishu doc URL (e.g., https://my.feishu.cn/docx/abc)
973
- - Local file path (e.g., /tmp/report.md)
974
- - Git branch or worktree path (e.g., feature/my-feature)
975
- - GitHub commit URL or PR URL
976
- - Cloud drive URL (e.g., https://my.feishu.cn/file/abc)
977
- - Or any other locator that points to where the work product lives
978
-
979
- The \`deliverable_storage_path\` will be persisted to the task's \`context.deliverable_storage_path\` for future reference and traceability.
985
+ 3. Deliverables were already submitted by the executor via
986
+ \`task_pre_complete\` (they live in \`context.deliverable_storage_path\`
987
+ and the operation trail — Task #5073 design: task_complete takes **no**
988
+ deliverable parameter). Cross-check them in step 2; do NOT ask the
989
+ executor to resubmit.
980
990
 
981
991
  **Restrictions**:
982
992
  - Cannot complete cycle-type tasks (they are periodic). Use \`task_update\` to reset progress instead.
983
993
  - Marks the task as 100% complete; use \`task_update\` to record partial progress first if needed.
984
994
 
985
- **Backward compatibility**: \`deliverable_storage_path\` is optional. Existing callers that omit it continue to work as before.
995
+ **Side effects**:
996
+ - Sets \`status = "completed"\`, \`progress = 100\` **and refreshes \`current_status\`**
997
+ to the completed wording. You do **NOT** need a follow-up
998
+ \`task_update(current_status=...)\` call — a task must never keep a stale
999
+ pre-completion progress sentence (e.g. "paused, not committed") that would
1000
+ contradict \`status = "completed"\`.
1001
+ - The goal-check decision model does **NOT** run here — it already ran at
1002
+ \`task_pre_complete\` time (Task #5073 design v2). This tool is the final
1003
+ state commit by the acceptance side.
1004
+ - Cannot complete a task that is already in a terminal state (cancelled /
1005
+ archived) — reopen it first via \`task_update(status="active")\`.
986
1006
  `.trim();
987
1007
  function completeTaskTool(taskComponent) {
988
1008
  return {
@@ -1010,7 +1030,18 @@ function completeTaskTool(taskComponent) {
1010
1030
  metadata: { execution_time_ms: 0 }
1011
1031
  };
1012
1032
  }
1013
- const task = await taskComponent.completeTask(params.task_id, sessionId, params.deliverable_storage_path);
1033
+ const TERMINAL_NON_ACCEPTABLE = new Set([
1034
+ ...TERMINAL_NON_ACCEPTABLE_STATUSES
1035
+ ]);
1036
+ if (TERMINAL_NON_ACCEPTABLE.has(currentTask.status)) {
1037
+ return {
1038
+ success: false,
1039
+ output: "",
1040
+ error: `Cannot complete task #${params.task_id}: it is already in terminal status "${currentTask.status}". Reopen it first via task_update(status="active") if acceptance should proceed.`,
1041
+ metadata: { execution_time_ms: 0 }
1042
+ };
1043
+ }
1044
+ const task = await taskComponent.completeTask(params.task_id, sessionId);
1014
1045
  if (!task) {
1015
1046
  return {
1016
1047
  success: false,
@@ -1020,12 +1051,10 @@ function completeTaskTool(taskComponent) {
1020
1051
  };
1021
1052
  }
1022
1053
  setCurrentTaskId(undefined);
1023
- logger4.info(`[completeTask] Trace: Task #${params.task_id} completed, deliverable=${params.deliverable_storage_path || "(none)"}, currentTaskId cleared from EnvContext`);
1054
+ logger4.info(`[completeTask] Trace: Task #${params.task_id} completed (acceptance committed), currentTaskId cleared from EnvContext`);
1024
1055
  return {
1025
1056
  success: true,
1026
- output: params.deliverable_storage_path ? `Task completed: #${task.id} - ${task.title}
1027
- Deliverable (context + operation): ${params.deliverable_storage_path}` : `Task completed: #${task.id} - ${task.title}
1028
- Deliverable: (no path provided)`,
1057
+ output: `Task completed: #${task.id} - ${task.title}`,
1029
1058
  metadata: { execution_time_ms: 0, task }
1030
1059
  };
1031
1060
  } catch (error) {
@@ -1044,13 +1073,17 @@ init_logger();
1044
1073
  var logger5 = createLogger("tool:cancel-task");
1045
1074
  var NON_CANCELLABLE_STATUSES = new Set(["completed", "cancelled", "archived"]);
1046
1075
  var TASK_CANCEL_DESCRIPTION = `
1047
- Cancel a task (task.status = "cancelled"). This is the **acceptance-side** cancel:
1048
- use it when the work is abandoned, the user asked to stop, or acceptance failed.
1076
+ Cancel a task (task.status = "cancelled"). This is the **acceptance-side** cancel.
1049
1077
 
1050
- **When to use**:
1051
- - The user asks to cancel / stop / drop the task
1052
- - Acceptance failed and re-delegation is not worth it
1053
- - The sub-agent timed out or went off-track and the task is no longer relevant
1078
+ **When to use** — ONLY when the user explicitly asks (用户明令):
1079
+ - The user asks to cancel / stop / drop the task (用户明令取消 / 停掉 / 放弃这个任务)
1080
+
1081
+ **When NOT to use**:
1082
+ - ❌ A sub-agent failed / timed out / went off-track — that is NOT a cancellation.
1083
+ Find the root cause, propose a fix, and re-delegate (with \`sub_session_id\` to resume).
1084
+ If it truly cannot be moved forward, report the situation to the user and **wait for
1085
+ the user's decision** — do NOT cancel it on your own.
1086
+ - ❌ Acceptance found gaps but re-delegation is still possible — re-delegate instead.
1054
1087
 
1055
1088
  **What it does NOT do**:
1056
1089
  - It does **NOT** stop a running background process — that is \`stop_task\`
@@ -1060,6 +1093,9 @@ use it when the work is abandoned, the user asked to stop, or acceptance failed.
1060
1093
  **Side effects**:
1061
1094
  - Sets \`status = "cancelled"\` and fires the task terminal-state hooks
1062
1095
  (notifications / card state machine converge to the cancelled state).
1096
+ - Also refreshes \`current_status\` to the cancelled wording (with your \`reason\`
1097
+ appended when given) — the task no longer keeps a stale pre-cancel progress
1098
+ sentence that would contradict \`status = "cancelled"\`.
1063
1099
  - Writes an operation record so the cancellation reason stays auditable.
1064
1100
  - A cancelled task can be reopened later with \`task_update(status="active")\`.
1065
1101
 
@@ -1094,7 +1130,8 @@ function cancelTaskTool(taskComponent) {
1094
1130
  };
1095
1131
  }
1096
1132
  const task = await taskComponent.updateTask(params.task_id, {
1097
- status: "cancelled"
1133
+ status: "cancelled",
1134
+ current_status: params.reason ? `${TASK_CANCELLED_STATUS_WORD}:${params.reason}` : TASK_CANCELLED_STATUS_WORD
1098
1135
  });
1099
1136
  if (!task) {
1100
1137
  return {
@@ -1128,6 +1165,88 @@ function cancelTaskTool(taskComponent) {
1128
1165
  }
1129
1166
  };
1130
1167
  }
1168
+ // src/env/task/tools/pre-complete-tool.ts
1169
+ init_logger();
1170
+ var logger6 = createLogger("task:tools:pre-complete");
1171
+ var TASK_PRE_COMPLETE_DESCRIPTION = `
1172
+ Submit a task for acceptance (two-phase acceptance, Task #5073).
1173
+
1174
+ **Who should call this** — the **executor** (sub-agent) when it believes
1175
+ the work is done and deliverables are ready.
1176
+
1177
+ **What it does**:
1178
+ - Sets \`status = "to_validate"\` (待验证) — the task enters the
1179
+ acceptance queue. This is **NOT** a terminal state.
1180
+ - Persists \`deliverable_storage_path\` to \`task.context.deliverable_storage_path\`
1181
+ and writes a \`Deliverable: <path>\` line into the operation trail.
1182
+ - Refreshes \`current_status\` to the to-validate wording
1183
+ (with your progress summary appended when given).
1184
+ - Creates an operation record so the submission stays auditable.
1185
+
1186
+ **What it does NOT do**:
1187
+ - It does **NOT** mark the task completed — final acceptance
1188
+ (\`task_complete\`) belongs to the **default agent** (验收权分离, Task #5007).
1189
+
1190
+ **Goal self-check (design v2)**:
1191
+ - Submitting **does** fire the completion goal-check hook once
1192
+ (\`terminalStatus="to_validate"\`) as a self-check gate — the
1193
+ decision model reviews your goals/operations at submission time.
1194
+ If it produces a hint, read it and address the gaps **before**
1195
+ ending your turn. The final acceptance (\`task_complete\`) does
1196
+ **not** re-run the goal check.
1197
+
1198
+ **After calling**:
1199
+ - Push progress to 100 via \`task_update(progress=100)\` if not already,
1200
+ then **end your turn and return the result** to the main agent.
1201
+ - The default agent will pick up the notification, verify the goals
1202
+ item-by-item, and call \`task_complete\` (or re-delegate on gaps).
1203
+
1204
+ **Parameters**:
1205
+ - \`task_id\` (required): the task to submit
1206
+ - \`deliverable_storage_path\` (optional): where the work product lives
1207
+ (file path / Feishu doc URL / git branch / PR URL ...)
1208
+ - \`current_status\` (optional): a one-line progress summary shown to the
1209
+ acceptance side (e.g. "实现完成,测试全绿")
1210
+
1211
+ **Restrictions**:
1212
+ - Cannot pre-complete cycle-type tasks (they are periodic).
1213
+ `.trim();
1214
+ function preCompleteTaskTool(taskComponent) {
1215
+ return {
1216
+ name: "task_pre_complete",
1217
+ description: TASK_PRE_COMPLETE_DESCRIPTION,
1218
+ parameters: PreCompleteTaskToolSchema,
1219
+ execute: async (args, ctx) => {
1220
+ const params = PreCompleteTaskToolSchema.parse(args);
1221
+ const sessionId = ctx.session_id || "unknown";
1222
+ try {
1223
+ const task = await taskComponent.preCompleteTask(params.task_id, sessionId, params.deliverable_storage_path, params.current_status);
1224
+ if (!task) {
1225
+ return {
1226
+ success: false,
1227
+ output: "",
1228
+ error: `Task not found: ${params.task_id}`,
1229
+ metadata: { execution_time_ms: 0 }
1230
+ };
1231
+ }
1232
+ return {
1233
+ success: true,
1234
+ output: params.deliverable_storage_path ? `Task submitted for acceptance (to_validate): #${task.id} - ${task.title}
1235
+ Deliverable (context + operation): ${params.deliverable_storage_path}` : `Task submitted for acceptance (to_validate): #${task.id} - ${task.title}
1236
+ Deliverable: (no path provided)`,
1237
+ metadata: { execution_time_ms: 0, task }
1238
+ };
1239
+ } catch (error) {
1240
+ return {
1241
+ success: false,
1242
+ output: "",
1243
+ error: error instanceof Error ? error.message : String(error),
1244
+ metadata: { execution_time_ms: 0 }
1245
+ };
1246
+ }
1247
+ }
1248
+ };
1249
+ }
1131
1250
  // src/env/task/tools/task-tree-tool.ts
1132
1251
  function compareTasksDesc(a, b) {
1133
1252
  if (a.updatedAt < b.updatedAt)
@@ -1266,4 +1385,4 @@ function treeTasksTool(taskComponent) {
1266
1385
  }
1267
1386
  };
1268
1387
  }
1269
- export { createTaskTool, getTaskTool, listTasksTool, searchTasksTool, batchArchiveTaskTool, batchDeleteTaskTool, updateTaskTool, deleteTaskTool, completeTaskTool, cancelTaskTool, treeTasksTool };
1388
+ export { createTaskTool, getTaskTool, listTasksTool, searchTasksTool, batchArchiveTaskTool, batchDeleteTaskTool, updateTaskTool, deleteTaskTool, completeTaskTool, cancelTaskTool, preCompleteTaskTool, treeTasksTool };
@@ -60,7 +60,7 @@ function sanitizeInlineText(text, maxLen = 300) {
60
60
  if (!text)
61
61
  return "";
62
62
  const flat = text.replace(/\r\n?/g, `
63
- `).replace(/^#{1,6}\s+/gm, "").replace(/^\s*[-*+]\s+/gm, "· ").replace(/^\s*\d+\.\s+/gm, "· ").replace(/\*\*/g, "").replace(/`/g, "").replace(/\n+/g, " · ").replace(/\s{2,}/g, " ").replace(/(?:\s*·\s*){2,}/g, " · ").replace(/^(\s*·\s*)+/, "").replace(/(\s*·\s*)+$/, "").trim();
63
+ `).replace(/^#{1,6}\s+/gm, "").replace(/!\[([^\]]*)\]\([^)]*\)/g, (_m, alt) => alt.trim() ? `${alt.trim()}[图片]` : "[图片]").replace(/^\s*[-*+]\s+/gm, "· ").replace(/^\s*\d+\.\s+/gm, "· ").replace(/\*\*/g, "").replace(/`/g, "").replace(/\n+/g, " · ").replace(/\s{2,}/g, " ").replace(/(?:\s*·\s*){2,}/g, " · ").replace(/^(\s*·\s*)+/, "").replace(/(\s*·\s*)+$/, "").trim();
64
64
  return flat.length <= maxLen ? flat : `${flat.slice(0, maxLen)}…`;
65
65
  }
66
66
  var HEAD_TITLE_MAX_WIDTH = 40;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-setting/roy-agent-core",
3
- "version": "1.7.75",
3
+ "version": "1.7.77",
4
4
  "type": "module",
5
5
  "description": "Core SDK for roy-agent - Environment, Components, Tools, Sessions, Tasks",
6
6
  "main": "./dist/index.js",
@@ -1,71 +0,0 @@
1
- import {
2
- init_decorator,
3
- wrapFunction
4
- } from "./roy-agent-core-qq96p0tj.js";
5
-
6
- // src/env/task/plugins/fake-user-message-helper.ts
7
- init_decorator();
8
- var KIND_FIELD = "__fakeUserMessageKind";
9
- function ensureMetadata(toolResult) {
10
- if (!toolResult)
11
- return;
12
- if (!toolResult.result)
13
- toolResult.result = {};
14
- if (!toolResult.result.metadata)
15
- toolResult.result.metadata = {};
16
- return toolResult.result.metadata;
17
- }
18
- function stringContent(msg) {
19
- const c = msg?.content;
20
- return typeof c === "string" ? c : JSON.stringify(c);
21
- }
22
- function enqueueToAddFakeUserMessageImpl(toolResult, newMsg, newKind) {
23
- const meta = ensureMetadata(toolResult);
24
- if (!meta)
25
- return { willMerge: false, finalKind: newKind };
26
- const existing = meta.toAddFakeUserMessage;
27
- const existingKind = meta[KIND_FIELD];
28
- if (!existing) {
29
- meta.toAddFakeUserMessage = newMsg;
30
- meta[KIND_FIELD] = newKind;
31
- return { willMerge: false, finalKind: newKind };
32
- }
33
- let merged;
34
- if (newKind === "max-iter") {
35
- merged = {
36
- role: "user",
37
- content: `${stringContent(existing)}
38
-
39
- ${stringContent(newMsg)}`
40
- };
41
- } else if (newKind === "delegate" && existingKind === "max-iter") {
42
- merged = {
43
- role: "user",
44
- content: `${stringContent(newMsg)}
45
-
46
- ${stringContent(existing)}`
47
- };
48
- } else {
49
- merged = {
50
- role: "user",
51
- content: `${stringContent(existing)}
52
-
53
- ${stringContent(newMsg)}`
54
- };
55
- }
56
- meta.toAddFakeUserMessage = merged;
57
- const finalKind = newKind === "max-iter" || existingKind === "max-iter" ? "max-iter" : newKind;
58
- meta[KIND_FIELD] = finalKind;
59
- return { willMerge: true, finalKind };
60
- }
61
- var enqueueToAddFakeUserMessage = wrapFunction(enqueueToAddFakeUserMessageImpl, "plugin.fake-user-message.enqueue", {
62
- recordParams: false,
63
- recordResult: false,
64
- log: true,
65
- resultFilter: (result) => ({
66
- "fake-user-message.will_merge": result.willMerge,
67
- "fake-user-message.final_kind": result.finalKind
68
- })
69
- });
70
-
71
- export { enqueueToAddFakeUserMessage };