@ai-setting/roy-agent-core 1.7.65 → 1.7.67
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.d.ts +56 -3
- package/dist/env/agent/agent-component.js +2 -2
- package/dist/env/agent/index.js +2 -2
- package/dist/env/agent/types.d.ts +28 -0
- package/dist/env/environment.d.ts +13 -0
- package/dist/env/event-source/command-card-action.d.ts +105 -0
- package/dist/env/event-source/command-cards.d.ts +72 -0
- package/dist/env/event-source/command-registry.d.ts +181 -0
- package/dist/env/event-source/command-types.d.ts +8 -0
- package/dist/env/event-source/event-source-handlers.d.ts +66 -0
- package/dist/env/event-source/event-source-handlers.js +7 -4
- package/dist/env/event-source/fallback-model-command.d.ts +80 -0
- package/dist/env/event-source/index.d.ts +7 -0
- package/dist/env/event-source/index.js +48 -7
- package/dist/env/event-source/timer-handler.d.ts +93 -1
- package/dist/env/index.js +15 -14
- package/dist/env/llm/index.js +1 -1
- package/dist/env/prompt/index.js +3 -2
- package/dist/env/prompt/prompts-index.d.ts +3 -8
- package/dist/env/task/delegate/delegate-tool.d.ts +58 -2
- package/dist/env/task/delegate/delegate-tool.js +5 -2
- package/dist/env/task/delegate/index.js +3 -2
- package/dist/env/task/index.js +9 -8
- package/dist/env/task/mcp/index.js +3 -2
- package/dist/env/task/plugins/__e2e__/laya-completion-e2e.d.ts +16 -0
- package/dist/env/task/plugins/index.js +4 -3
- package/dist/env/task/plugins/laya-completion-plugin.d.ts +133 -0
- package/dist/env/task/plugins/laya-port.d.ts +23 -0
- package/dist/env/task/storage/index.js +2 -2
- package/dist/env/task/storage/migrations/003_add_process_description.d.ts +1 -1
- package/dist/env/task/storage/migrations/log-migration.d.ts +49 -3
- package/dist/env/task/task-component.d.ts +43 -0
- package/dist/env/task/tools/completion-copy.d.ts +27 -0
- package/dist/env/task/tools/index.js +2 -1
- package/dist/env/task/tools/operation/create-tool.d.ts +1 -1
- package/dist/env/task/tools/operation/index.js +1 -1
- package/dist/env/task/tools/operation/operation-types.d.ts +10 -8
- package/dist/env/task/types.d.ts +3 -3
- package/dist/env/tool/built-in/index.js +2 -2
- package/dist/env/tool/built-in/query-background-process-tool.d.ts +10 -0
- package/dist/env/tool/index.js +3 -3
- package/dist/env/tool/types.d.ts +6 -0
- package/dist/index.js +60 -19
- package/dist/shared/@ai-setting/{roy-agent-core-rjzdj0xb.js → roy-agent-core-02j24hrg.js} +2 -0
- package/dist/shared/@ai-setting/{roy-agent-core-hmdcz3g9.js → roy-agent-core-1k83dq3a.js} +16 -6
- package/dist/shared/@ai-setting/{roy-agent-core-e42v9bcq.js → roy-agent-core-1kxf910n.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-amkqnyzy.js → roy-agent-core-58804s3j.js} +10 -0
- package/dist/shared/@ai-setting/roy-agent-core-6m4bw8jy.js +6 -0
- package/dist/shared/@ai-setting/roy-agent-core-8zas6w5q.js +1083 -0
- package/dist/shared/@ai-setting/{roy-agent-core-9bs6xrav.js → roy-agent-core-abqhkbn3.js} +6 -3
- package/dist/shared/@ai-setting/{roy-agent-core-f6c0nadn.js → roy-agent-core-b7jbqfsy.js} +25 -11
- package/dist/shared/@ai-setting/{roy-agent-core-hjejpcg5.js → roy-agent-core-dnjm17sa.js} +51 -9
- package/dist/shared/@ai-setting/{roy-agent-core-t0ktaevq.js → roy-agent-core-h5vmff8w.js} +60 -4
- package/dist/shared/@ai-setting/{roy-agent-core-xhrrgfdy.js → roy-agent-core-hfr6bzts.js} +168 -52
- package/dist/shared/@ai-setting/{roy-agent-core-18am1h07.js → roy-agent-core-k4ps1hxp.js} +1085 -46
- package/dist/shared/@ai-setting/{roy-agent-core-jz8dsypm.js → roy-agent-core-kpg25s2q.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-6masakz4.js → roy-agent-core-ma35jyd9.js} +19 -8
- package/dist/shared/@ai-setting/{roy-agent-core-gxzxq1sf.js → roy-agent-core-ntq0gz7q.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-rn57psp0.js → roy-agent-core-p5cz9m8v.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-w07ymg29.js → roy-agent-core-wksgtqf9.js} +1 -1
- package/package.json +1 -1
- package/dist/shared/@ai-setting/roy-agent-core-6z412atw.js +0 -654
- /package/dist/shared/@ai-setting/{roy-agent-core-5enxfga2.js → roy-agent-core-b4x6x4k2.js} +0 -0
- /package/dist/shared/@ai-setting/{roy-agent-core-es467wsz.js → roy-agent-core-dt104qa1.js} +0 -0
|
@@ -16,10 +16,13 @@ import {
|
|
|
16
16
|
|
|
17
17
|
// src/env/task/storage/migrations/log-migration.ts
|
|
18
18
|
function logMigration(message) {
|
|
19
|
-
|
|
20
|
-
`);
|
|
19
|
+
migrationLogger.warn(message);
|
|
21
20
|
}
|
|
22
|
-
var
|
|
21
|
+
var migrationLogger;
|
|
22
|
+
var init_log_migration = __esm(() => {
|
|
23
|
+
init_logger();
|
|
24
|
+
migrationLogger = createLogger("task:migration");
|
|
25
|
+
});
|
|
23
26
|
|
|
24
27
|
// src/env/task/storage/migrations/001_add_project_path_context.ts
|
|
25
28
|
var exports_001_add_project_path_context = {};
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
createCompatibleDatabase,
|
|
6
6
|
init_sqlite_task_store
|
|
7
|
-
} from "./roy-agent-core-
|
|
7
|
+
} from "./roy-agent-core-abqhkbn3.js";
|
|
8
8
|
import {
|
|
9
9
|
TaskHookPoints
|
|
10
10
|
} from "./roy-agent-core-1pg0fepg.js";
|
|
11
11
|
import {
|
|
12
12
|
WORKFLOW_EXTRACT_PROMPT
|
|
13
|
-
} from "./roy-agent-core-
|
|
13
|
+
} from "./roy-agent-core-ma35jyd9.js";
|
|
14
14
|
import {
|
|
15
15
|
assertNoLeakage,
|
|
16
16
|
buildHintText,
|
|
@@ -929,6 +929,7 @@ function truncateSnippet(text) {
|
|
|
929
929
|
var DEFAULT_TIMEOUT_MS = 2000;
|
|
930
930
|
var DEFAULT_MAX_STRIKES = 3;
|
|
931
931
|
var DEFAULT_MODEL = "task-decision";
|
|
932
|
+
var DEFAULT_GOAL_MODEL = "task-completion";
|
|
932
933
|
var SYSTEMONE_PATH = "/v1/systemone";
|
|
933
934
|
|
|
934
935
|
class LayaDecisionPort {
|
|
@@ -1058,19 +1059,32 @@ function isTimeoutError(err) {
|
|
|
1058
1059
|
}
|
|
1059
1060
|
return false;
|
|
1060
1061
|
}
|
|
1062
|
+
var LAYA_DECISION_PROVIDER = "laya-decision";
|
|
1063
|
+
var LAYA_GOAL_DECISION_PROVIDER = "laya-goal-decision";
|
|
1064
|
+
function providerNameForPurpose(purpose) {
|
|
1065
|
+
return purpose === "goal" ? LAYA_GOAL_DECISION_PROVIDER : LAYA_DECISION_PROVIDER;
|
|
1066
|
+
}
|
|
1061
1067
|
async function loadLayaAuth(authPath = `${process.env.HOME ?? "~"}/.roy-agent/auth.json`) {
|
|
1068
|
+
return loadLayaAuthForPurpose(authPath, "create");
|
|
1069
|
+
}
|
|
1070
|
+
async function loadLayaAuthForPurpose(authPath = `${process.env.HOME ?? "~"}/.roy-agent/auth.json`, purpose = "create") {
|
|
1062
1071
|
try {
|
|
1063
1072
|
const fs = await import("fs/promises");
|
|
1064
1073
|
const raw = await fs.readFile(authPath, "utf-8");
|
|
1065
1074
|
const parsed = JSON.parse(raw);
|
|
1066
|
-
const
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
baseURL
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1075
|
+
const primary = providerNameForPurpose(purpose);
|
|
1076
|
+
const candidates = purpose === "goal" ? [primary, LAYA_DECISION_PROVIDER] : [primary];
|
|
1077
|
+
for (const name of candidates) {
|
|
1078
|
+
const p = parsed.providers?.[name];
|
|
1079
|
+
if (p?.baseURL && p?.apiKey) {
|
|
1080
|
+
return {
|
|
1081
|
+
baseURL: p.baseURL,
|
|
1082
|
+
apiKey: p.apiKey,
|
|
1083
|
+
model: p.model ?? (name === LAYA_GOAL_DECISION_PROVIDER ? DEFAULT_GOAL_MODEL : DEFAULT_MODEL)
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
return null;
|
|
1074
1088
|
} catch {
|
|
1075
1089
|
return null;
|
|
1076
1090
|
}
|
|
@@ -2937,4 +2951,4 @@ __legacyDecorateClassTS([
|
|
|
2937
2951
|
function createPerTaskGroupChatPlugin(config = {}) {
|
|
2938
2952
|
return new PerTaskGroupChatPlugin(config);
|
|
2939
2953
|
}
|
|
2940
|
-
export { createAutoTaskPlugin, LAYA_REUSE_THRESHOLD, LayaDecisionPlugin, createLayaDecisionPlugin, WORKFLOW_EXTRACTOR_PROMPT, formatExtractorInput, formatExtractorInputFromDescription, parseExtractorOutput, TaskTagPlugin, extractPerTaskChatId, extractPerTaskChatName, NotifyType, LarkCliTaskNotifyHook, createLarkCliTaskNotifyHook, PerTaskGroupChatPlugin, createPerTaskGroupChatPlugin };
|
|
2954
|
+
export { createAutoTaskPlugin, pickGateConfidence, LayaDecisionPort, loadLayaAuthForPurpose, LAYA_REUSE_THRESHOLD, LayaDecisionPlugin, createLayaDecisionPlugin, WORKFLOW_EXTRACTOR_PROMPT, formatExtractorInput, formatExtractorInputFromDescription, parseExtractorOutput, TaskTagPlugin, extractPerTaskChatId, extractPerTaskChatName, NotifyType, LarkCliTaskNotifyHook, createLarkCliTaskNotifyHook, PerTaskGroupChatPlugin, createPerTaskGroupChatPlugin };
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "./roy-agent-core-1pg0fepg.js";
|
|
11
11
|
import {
|
|
12
12
|
builtInPrompts
|
|
13
|
-
} from "./roy-agent-core-
|
|
13
|
+
} from "./roy-agent-core-ma35jyd9.js";
|
|
14
14
|
import {
|
|
15
15
|
DEFAULT_SUBAGENT_PROMPT
|
|
16
16
|
} from "./roy-agent-core-07fvy74y.js";
|
|
@@ -897,7 +897,7 @@ var WORKFLOW_COMPAT_ALIASES = new Set([
|
|
|
897
897
|
"test-workflow-agent"
|
|
898
898
|
]);
|
|
899
899
|
var DEFAULT_TIMEOUT = 1800000;
|
|
900
|
-
var PROGRESS_INTERVAL =
|
|
900
|
+
var PROGRESS_INTERVAL = 600000;
|
|
901
901
|
|
|
902
902
|
class BackgroundTaskManager {
|
|
903
903
|
env;
|
|
@@ -1113,7 +1113,7 @@ class BackgroundTaskManager {
|
|
|
1113
1113
|
return null;
|
|
1114
1114
|
}
|
|
1115
1115
|
async createTask(options) {
|
|
1116
|
-
const { parentSessionId, description, prompt, subagentType, timeout, similarTaskIds, existingSubSessionId, triggerEventId, model, fallbackModel } = options;
|
|
1116
|
+
const { parentSessionId, description, prompt, subagentType, timeout, similarTaskIds, existingSubSessionId, triggerEventId, model, fallbackModel, fallbackModels } = options;
|
|
1117
1117
|
const taskIdGen = `process_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
|
1118
1118
|
const sessionComponent = this.getSessionComponent();
|
|
1119
1119
|
if (!sessionComponent) {
|
|
@@ -1213,6 +1213,7 @@ class BackgroundTaskManager {
|
|
|
1213
1213
|
triggerEventId,
|
|
1214
1214
|
model,
|
|
1215
1215
|
fallbackModel,
|
|
1216
|
+
fallbackModels,
|
|
1216
1217
|
replyChannel: replyChannelSnapshot
|
|
1217
1218
|
};
|
|
1218
1219
|
this.tasks.set(taskIdGen, task);
|
|
@@ -1627,6 +1628,7 @@ ${reuseSection.markdown}`;
|
|
|
1627
1628
|
const invokeHandleQuery = () => {
|
|
1628
1629
|
const inheritedModel = task?.model;
|
|
1629
1630
|
const inheritedFallbackModel = task?.fallbackModel;
|
|
1631
|
+
const inheritedFallbackModels = task?.fallbackModels;
|
|
1630
1632
|
return this.env.handle_query?.(delegateQuery, {
|
|
1631
1633
|
sessionId,
|
|
1632
1634
|
deniedTools: deniedTools.length > 0 ? deniedTools : undefined,
|
|
@@ -1634,7 +1636,8 @@ ${reuseSection.markdown}`;
|
|
|
1634
1636
|
abort: signal,
|
|
1635
1637
|
runId: capturedRunId,
|
|
1636
1638
|
...inheritedModel ? { model: inheritedModel } : {},
|
|
1637
|
-
...inheritedFallbackModel ? { fallbackModel: inheritedFallbackModel } : {}
|
|
1639
|
+
...inheritedFallbackModel ? { fallbackModel: inheritedFallbackModel } : {},
|
|
1640
|
+
...Array.isArray(inheritedFallbackModels) ? { fallbackModels: inheritedFallbackModels } : {}
|
|
1638
1641
|
});
|
|
1639
1642
|
};
|
|
1640
1643
|
const wrappedPromise = processRegistry ? runWithProcessRegistryAsync(processRegistry, () => runWithBgTaskIdAsync(bgTaskId, () => invokeHandleQuery())) : runWithBgTaskIdAsync(bgTaskId, () => invokeHandleQuery());
|
|
@@ -1725,6 +1728,25 @@ ${reuseSection.markdown}`;
|
|
|
1725
1728
|
getTask(taskId) {
|
|
1726
1729
|
return this.tasks.get(taskId) ?? this.terminalTasks.get(taskId);
|
|
1727
1730
|
}
|
|
1731
|
+
async getSubSessionActivity(bgProcessId) {
|
|
1732
|
+
const task = this.getTask(bgProcessId);
|
|
1733
|
+
if (!task)
|
|
1734
|
+
return;
|
|
1735
|
+
const sessionComponent = this.getSessionComponent();
|
|
1736
|
+
if (!sessionComponent?.get)
|
|
1737
|
+
return;
|
|
1738
|
+
try {
|
|
1739
|
+
const session = await sessionComponent.get(task.subSessionId);
|
|
1740
|
+
if (!session)
|
|
1741
|
+
return;
|
|
1742
|
+
return {
|
|
1743
|
+
messageCount: session.messageCount ?? 0,
|
|
1744
|
+
updatedAt: session.updatedAt ?? task.lastUpdatedAt ?? task.createdAt
|
|
1745
|
+
};
|
|
1746
|
+
} catch {
|
|
1747
|
+
return;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1728
1750
|
listTasks() {
|
|
1729
1751
|
return Array.from(this.tasks.values()).concat(Array.from(this.terminalTasks.values()));
|
|
1730
1752
|
}
|
|
@@ -1810,14 +1832,33 @@ ${reuseSection.markdown}`;
|
|
|
1810
1832
|
async forceStopAll() {
|
|
1811
1833
|
return this.forceStopAllAcrossParents();
|
|
1812
1834
|
}
|
|
1813
|
-
async dispose() {
|
|
1835
|
+
async dispose(options) {
|
|
1814
1836
|
for (const [, timer] of this.progressTimers) {
|
|
1815
1837
|
try {
|
|
1816
1838
|
clearInterval(timer);
|
|
1817
1839
|
} catch {}
|
|
1818
1840
|
}
|
|
1819
1841
|
this.progressTimers.clear();
|
|
1842
|
+
const skipAbortRunningTasks = options?.skipAbortRunningTasks === true;
|
|
1843
|
+
const waitForRunningTasks = options?.waitForRunningTasks === true;
|
|
1844
|
+
if (waitForRunningTasks && skipAbortRunningTasks) {
|
|
1845
|
+
const waitStart = Date.now();
|
|
1846
|
+
const WAIT_TIMEOUT_MS = 10 * 60 * 1000;
|
|
1847
|
+
while (Date.now() - waitStart < WAIT_TIMEOUT_MS) {
|
|
1848
|
+
let running = 0;
|
|
1849
|
+
for (const [, t] of this.tasks) {
|
|
1850
|
+
if (t.status === "running" || t.status === "pending")
|
|
1851
|
+
running++;
|
|
1852
|
+
}
|
|
1853
|
+
if (running === 0)
|
|
1854
|
+
break;
|
|
1855
|
+
logger3.info(`[BackgroundTaskManager] dispose waiting for ${running} running task(s)`);
|
|
1856
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1820
1859
|
for (const [, controller] of this.abortControllers) {
|
|
1860
|
+
if (skipAbortRunningTasks)
|
|
1861
|
+
break;
|
|
1821
1862
|
try {
|
|
1822
1863
|
controller.abort();
|
|
1823
1864
|
} catch {}
|
|
@@ -2012,7 +2053,7 @@ No need to poll — just wait for the notification and use \`task_get\` with the
|
|
|
2012
2053
|
};
|
|
2013
2054
|
await globalHookManager.execute(TaskHookPoints.DELEGATE_BEFORE, delegateCtx, { sessionId: parentSessionId });
|
|
2014
2055
|
promptWithTaskInfo = delegateCtx.prompt;
|
|
2015
|
-
return await handleBackgroundTask(backgroundTaskManager, parentSessionId, description, promptWithTaskInfo, delegateCtx.subagentType, delegateCtx.timeout, similar_task_ids, params.sub_session_id, resolvedTriggerEventId, ctx.model, ctx.fallbackModel);
|
|
2056
|
+
return await handleBackgroundTask(backgroundTaskManager, parentSessionId, description, promptWithTaskInfo, delegateCtx.subagentType, delegateCtx.timeout, similar_task_ids, params.sub_session_id, resolvedTriggerEventId, ctx.model, ctx.fallbackModel, ctx.fallbackModels);
|
|
2016
2057
|
}
|
|
2017
2058
|
};
|
|
2018
2059
|
tool.execute = wrapFunction(tool.execute, "delegate.execute", {
|
|
@@ -2056,7 +2097,7 @@ function _captureReplyChannelSnapshot() {
|
|
|
2056
2097
|
};
|
|
2057
2098
|
}
|
|
2058
2099
|
var captureReplyChannelSnapshot = wrapFunction(_captureReplyChannelSnapshot, "delegate.captureReplyChannel", { recordParams: false, recordResult: true, recordError: true });
|
|
2059
|
-
async function handleBackgroundTask(backgroundTaskManager, parentSessionId, description, prompt, subagentType, timeout, similarTaskIds, existingSubSessionId, triggerEventId, model, fallbackModel) {
|
|
2100
|
+
async function handleBackgroundTask(backgroundTaskManager, parentSessionId, description, prompt, subagentType, timeout, similarTaskIds, existingSubSessionId, triggerEventId, model, fallbackModel, fallbackModels) {
|
|
2060
2101
|
const startTime = Date.now();
|
|
2061
2102
|
try {
|
|
2062
2103
|
let actualSubagentType = subagentType;
|
|
@@ -2084,7 +2125,8 @@ async function handleBackgroundTask(backgroundTaskManager, parentSessionId, desc
|
|
|
2084
2125
|
existingSubSessionId,
|
|
2085
2126
|
triggerEventId,
|
|
2086
2127
|
model,
|
|
2087
|
-
fallbackModel
|
|
2128
|
+
fallbackModel,
|
|
2129
|
+
fallbackModels
|
|
2088
2130
|
});
|
|
2089
2131
|
const output = [
|
|
2090
2132
|
`✅ Background task accepted`,
|
|
@@ -2117,4 +2159,4 @@ async function handleBackgroundTask(backgroundTaskManager, parentSessionId, desc
|
|
|
2117
2159
|
};
|
|
2118
2160
|
}
|
|
2119
2161
|
}
|
|
2120
|
-
export { BackgroundTaskEventTypes, builtInSubAgents, getSubAgentSpec, DelegateToolParameters, buildEntryAgentPrompt, WORKFLOW_COMPAT_ALIASES, DEFAULT_TIMEOUT, BackgroundTaskManager, createDelegateTool, deriveTriggerEventIdFromEnvContext, captureReplyChannelSnapshot, handleBackgroundTask };
|
|
2162
|
+
export { BackgroundTaskEventTypes, builtInSubAgents, getSubAgentSpec, DelegateToolParameters, buildEntryAgentPrompt, WORKFLOW_COMPAT_ALIASES, DEFAULT_TIMEOUT, PROGRESS_INTERVAL, BackgroundTaskManager, createDelegateTool, deriveTriggerEventIdFromEnvContext, captureReplyChannelSnapshot, handleBackgroundTask };
|
|
@@ -2,6 +2,11 @@ import {
|
|
|
2
2
|
NEW_TASK_ID_HASH_PLACEHOLDER,
|
|
3
3
|
NEW_TASK_ID_PLACEHOLDER
|
|
4
4
|
} from "./roy-agent-core-tr3ep81v.js";
|
|
5
|
+
import {
|
|
6
|
+
TASK_COMPLETE_ITEM_BY_ITEM,
|
|
7
|
+
TASK_COMPLETE_VERIFY_DUTY,
|
|
8
|
+
TASK_COMPLETION_HINT_ANCHOR
|
|
9
|
+
} from "./roy-agent-core-6m4bw8jy.js";
|
|
5
10
|
import {
|
|
6
11
|
getEnvContextOrEmpty,
|
|
7
12
|
init_env_context,
|
|
@@ -38,7 +43,7 @@ var CreateTaskToolSchema = z.object({
|
|
|
38
43
|
description: z.string().optional().describe("Task description"),
|
|
39
44
|
priority: z.enum(["low", "medium", "high"]).optional().describe("Task priority"),
|
|
40
45
|
type: z.enum(["normal", "cycle", "longterm"]).optional().default("normal").describe("Task type. normal: 常规任务,需要跟踪完成. cycle: 周期任务(如每周发周报),无需 complete,定期执行. longterm: 长期任务/愿景目标(如提升公司影响力),难以一次性完成,持续跟进"),
|
|
41
|
-
goals_and_expected_deliverables: z.string().optional().describe("Goals and expected deliverables"),
|
|
46
|
+
goals_and_expected_deliverables: z.string().optional().describe("Goals and expected deliverables. " + "⚠️ 写成可逐条验收的编号子项(1. … 2. … 3. …),每条是一个可判定的交付/动作" + "(文件断言:文件存在/大小/内容;进程断言:命令 exit code/stdout;" + "测试断言:pass/fail 计数;状态断言:版本号/HTTP 200/状态字段)。" + "避免一句话模糊目标(如「做好 X」「完成调研」)——" + "任务完成时 completion hook 会按这些子项逐条对照操作记录验收。"),
|
|
42
47
|
due_date: z.string().optional().describe("Due date (ISO format)"),
|
|
43
48
|
tags: z.array(z.string()).optional().describe("Task tags (for search, stored in task.tags JSON field)"),
|
|
44
49
|
project_path: z.string().default("unknown").describe("Project root path for task positioning. " + "Used to locate the project space for this task. " + "Use 'unknown' if unknown. (Defaults to 'unknown'.)"),
|
|
@@ -84,7 +89,7 @@ var UpdateTaskToolSchema = withLegacyTaskId({
|
|
|
84
89
|
type: z.enum(["normal", "cycle", "longterm"]).optional().describe("Task type"),
|
|
85
90
|
progress: z.number().min(0).max(100).optional(),
|
|
86
91
|
current_status: z.string().optional(),
|
|
87
|
-
goals_and_expected_deliverables: z.string().optional(),
|
|
92
|
+
goals_and_expected_deliverables: z.string().optional().describe("Goals and expected deliverables. " + "⚠️ 追加/修改时同样写成可逐条验收的编号子项(1. … 2. … 3. …)," + "每条是一个可判定的交付/动作(文件断言:文件存在/大小/内容;" + "进程断言:命令 exit code/stdout;测试断言:pass/fail 计数;" + "状态断言:版本号/HTTP 200/状态字段)。" + "避免一句话模糊目标(如「做好 X」「完成调研」)——" + "任务完成时 completion hook 会按这些子项逐条对照操作记录验收。" + "(Task #4833 — 与 task_create 的 goals 规则同源)"),
|
|
88
93
|
due_date: z.string().optional(),
|
|
89
94
|
tags: z.array(z.string()).optional(),
|
|
90
95
|
project_path: z.string().optional().describe("Project path, identifies which project this task belongs to"),
|
|
@@ -316,6 +321,37 @@ function createTaskTool(taskComponent) {
|
|
|
316
321
|
- Same-theme tasks cluster under one parent
|
|
317
322
|
- Long-tail/stranded tasks should be archived or merged
|
|
318
323
|
|
|
324
|
+
## ⚠️ Goals 子项拆分规则 (Task #4791)
|
|
325
|
+
|
|
326
|
+
\`goals_and_expected_deliverables\` **MUST** be written as
|
|
327
|
+
**numbered sub-items** (编号子项) that can each be verified
|
|
328
|
+
one by one (逐条验收) — for \`type=normal\` tasks:
|
|
329
|
+
|
|
330
|
+
1. 实现 X(含文件路径)
|
|
331
|
+
2. 测试 Y 覆盖 Z 场景(pass/fail 计数)
|
|
332
|
+
3. 文档 W 落盘到 <path>
|
|
333
|
+
|
|
334
|
+
⚠️ For \`type=longterm\` / \`type=cycle\` tasks there is no
|
|
335
|
+
per-item completion acceptance(不走逐条 complete 验收), so the
|
|
336
|
+
MUST above does not apply; for those, it is **strongly recommended**
|
|
337
|
+
(建议) to split goals into staged, individually checkable sub-items
|
|
338
|
+
(阶段性可判子项) instead of one vague sentence.
|
|
339
|
+
|
|
340
|
+
Why: when the task is completed, the completion hook
|
|
341
|
+
(task:after.complete) judges the whole goal against the
|
|
342
|
+
operation-record chain, using each sub-item as fine-grained
|
|
343
|
+
evidence (逐条对照的依据). Vague one-line goals (一句话模糊目标,
|
|
344
|
+
如「做好 X」「完成调研」) give the judge nothing to check and
|
|
345
|
+
make a completion hint much more likely.
|
|
346
|
+
|
|
347
|
+
Reference the four atomic assertion forms (Task #4768
|
|
348
|
+
四原子形态) when writing each sub-item:
|
|
349
|
+
|
|
350
|
+
- 文件断言 (file assertion): file exists / size / content grep
|
|
351
|
+
- 进程断言 (process assertion): command exit code / stdout match
|
|
352
|
+
- 测试断言 (test assertion): pass/fail counts, no NEW fail
|
|
353
|
+
- 状态断言 (state assertion): version number / HTTP 200 / status field
|
|
354
|
+
|
|
319
355
|
## ⚠️ Spatial + Temporal Context (Task #2325)
|
|
320
356
|
|
|
321
357
|
A task MUST carry spatio-temporal context so it survives task-handoff
|
|
@@ -917,8 +953,28 @@ Mark a task as completed (progress=100, status=completed). Creates an operation
|
|
|
917
953
|
|
|
918
954
|
1. Read the task's \`goal\` (description) and \`delivery\` (goals_and_expected_deliverables) fields.
|
|
919
955
|
- Use \`task_get(task_id=<id>)\` to fetch the full task record.
|
|
920
|
-
2. **Validate
|
|
921
|
-
-
|
|
956
|
+
2. **Validate whether each goal sub-item was achieved** (${TASK_COMPLETE_ITEM_BY_ITEM}).
|
|
957
|
+
- Goals should be numbered sub-items (编号子项, see task_create rules). Check
|
|
958
|
+
each sub-item against the operation-record chain (操作记录链) and the
|
|
959
|
+
deliverable evidence (context.deliverable_storage_path).
|
|
960
|
+
- The completion hook (task:after.complete) judges the whole goal vs.
|
|
961
|
+
deliverables; numbered sub-items give it finer-grained evidence to
|
|
962
|
+
reason with (逐条对照的证据粒度). If it detects that the goal or
|
|
963
|
+
deliverables appear unmet, the task context will carry a
|
|
964
|
+
\`[${TASK_COMPLETION_HINT_ANCHOR}]\`.
|
|
965
|
+
- **If you receive a [${TASK_COMPLETION_HINT_ANCHOR}]**, you MUST verify it
|
|
966
|
+
(${TASK_COMPLETE_VERIFY_DUTY}): re-read the task via \`task_get\`, then do exactly one of:
|
|
967
|
+
(a) 确认未完成 → \`task_update(task_id=<id>, status=todo)\` reopen and continue; or
|
|
968
|
+
(b) 确认已完成 → \`task_operation_create\` (milestone_type=decision,
|
|
969
|
+
milestone_title=<一行结论>) state why the sub-items are actually
|
|
970
|
+
met (说明理由).
|
|
971
|
+
Never ignore it (不允许无视).
|
|
972
|
+
- If the goal and delivery mismatch **without** a hint, either:
|
|
973
|
+
(a) extend the task via \`task_update\`, or
|
|
974
|
+
(b) record the discrepancy via \`task_operation_create\`
|
|
975
|
+
(milestone_type=decision) — the reason **must** land in the
|
|
976
|
+
operation record (必须落到操作记录里), not merely a line in
|
|
977
|
+
your final report (不能只在报告里带一句).
|
|
922
978
|
3. **Provide \`deliverable_storage_path\`** parameter with the deliverable's address:
|
|
923
979
|
- Feishu doc URL (e.g., https://my.feishu.cn/docx/abc)
|
|
924
980
|
- Local file path (e.g., /tmp/report.md)
|