pybao-cli 1.5.19 → 1.5.21
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/REPL-64WF5V7K.js +50 -0
- package/dist/{acp-VADDAIVV.js → acp-VH2FWCMR.js} +31 -31
- package/dist/{agentsValidate-VDPY7LYN.js → agentsValidate-4E7AHAMS.js} +7 -7
- package/dist/{ask-4ZMUM73X.js → ask-R3YZ5B44.js} +30 -30
- package/dist/{autoUpdater-RIDDLHLH.js → autoUpdater-DCNAXD4F.js} +3 -3
- package/dist/{chunk-CGFEVSPI.js → chunk-25GZITCX.js} +3 -3
- package/dist/{chunk-2FDZ2PEI.js → chunk-2OOER4FR.js} +3 -3
- package/dist/{chunk-7SWRPT6M.js → chunk-3UWTN6DM.js} +3 -3
- package/dist/{chunk-VB3UZHV6.js → chunk-4ZGZTWMR.js} +4 -4
- package/dist/{chunk-YKSGF3T7.js → chunk-56IL2VXC.js} +1 -1
- package/dist/{chunk-TNOZ27TG.js → chunk-5VO2CFAL.js} +2 -2
- package/dist/{chunk-ZWB3VSTH.js → chunk-6UNYL6XK.js} +245 -50
- package/dist/{chunk-ZWB3VSTH.js.map → chunk-6UNYL6XK.js.map} +3 -3
- package/dist/{chunk-277JOCVZ.js → chunk-BED7SG2Q.js} +1 -1
- package/dist/{chunk-7I4S6UH7.js → chunk-BRSPPFSY.js} +1 -1
- package/dist/{chunk-L6J4MPRE.js → chunk-CPYDPN2J.js} +725 -73
- package/dist/{chunk-L6J4MPRE.js.map → chunk-CPYDPN2J.js.map} +2 -2
- package/dist/{chunk-PHBWXWFD.js → chunk-CSONCQLF.js} +2 -2
- package/dist/{chunk-KP7PMNEW.js → chunk-EP62LHB7.js} +1 -1
- package/dist/{chunk-M6CFQRHR.js → chunk-GIXE5FJ2.js} +1 -1
- package/dist/{chunk-KX7DKI3A.js → chunk-H2ZE5QDY.js} +4 -4
- package/dist/{chunk-M3AEV7WD.js → chunk-HA7FKBZI.js} +2 -2
- package/dist/{chunk-RUMV5QOU.js → chunk-KMCUZUZG.js} +3 -3
- package/dist/{chunk-JKTDFI2S.js → chunk-LRL3MYKR.js} +3 -3
- package/dist/{chunk-3JRH6I43.js → chunk-MMMMRMOG.js} +3 -3
- package/dist/{chunk-PXAQPDGS.js → chunk-N3T2WAYN.js} +1 -1
- package/dist/{chunk-IYGHQUN2.js → chunk-NRQHLVJJ.js} +2 -2
- package/dist/{chunk-CZZKRPE2.js → chunk-P5NTGZ5H.js} +1 -1
- package/dist/{chunk-CZZKRPE2.js.map → chunk-P5NTGZ5H.js.map} +1 -1
- package/dist/{chunk-7AJ4EUUJ.js → chunk-QE7PZPHW.js} +1 -1
- package/dist/{chunk-FYOORPZ4.js → chunk-RQ5X6LFM.js} +4 -4
- package/dist/{chunk-JR5WF5M6.js → chunk-SE7UGQCE.js} +2 -2
- package/dist/{chunk-LXJUYOGP.js → chunk-TBEA6BY3.js} +1 -1
- package/dist/{chunk-MRG76U66.js → chunk-TSAURYF2.js} +1 -1
- package/dist/{chunk-CEHSLEJ3.js → chunk-TXZ5UTGP.js} +1 -1
- package/dist/{chunk-CEHSLEJ3.js.map → chunk-TXZ5UTGP.js.map} +1 -1
- package/dist/{chunk-VSKWAGTO.js → chunk-VP5A6FKG.js} +1 -1
- package/dist/{chunk-PJ2XKKDM.js → chunk-VY5KEHU5.js} +3 -3
- package/dist/{chunk-JTRFDGES.js → chunk-X5LLT4P2.js} +1 -1
- package/dist/{chunk-KRBHZ2NW.js → chunk-XRLMQN3Q.js} +4 -4
- package/dist/{chunk-BPY6R2EU.js → chunk-YQ2RQUQF.js} +1 -1
- package/dist/{chunk-OMCKTGQ5.js → chunk-ZQR3MM2D.js} +17 -2
- package/dist/{chunk-OMCKTGQ5.js.map → chunk-ZQR3MM2D.js.map} +2 -2
- package/dist/{cli-AK6CYCFX.js → cli-RBMZQ5KF.js} +103 -92
- package/dist/cli-RBMZQ5KF.js.map +7 -0
- package/dist/commands-WPHK776A.js +54 -0
- package/dist/{config-FLSTRDUK.js → config-7TO5SQU5.js} +4 -4
- package/dist/{context-JQKLNDEK.js → context-LRA2DKJT.js} +6 -6
- package/dist/{conversationPersistence-RVLIJAVU.js → conversationPersistence-Z4QSI5NB.js} +3 -3
- package/dist/{conversationTracker-5HLVM6IU.js → conversationTracker-B3DMEHMA.js} +4 -4
- package/dist/{customCommands-J2RH24UE.js → customCommands-6JZ2VUO2.js} +4 -4
- package/dist/{env-PWLMV4WE.js → env-37ALKFXU.js} +2 -2
- package/dist/{file-LY2Z6EYX.js → file-7EOMBX72.js} +4 -4
- package/dist/index.js +3 -3
- package/dist/{llm-RRAVQWE3.js → llm-3KQG5NEP.js} +31 -31
- package/dist/{llmLazy-LRW757BZ.js → llmLazy-ENEH3KAB.js} +1 -1
- package/dist/{loader-2LT2GMMI.js → loader-D6V3WFL6.js} +4 -4
- package/dist/{lsp-XVTWUOP7.js → lsp-CTPOMI7O.js} +6 -6
- package/dist/{lspAnchor-WIAD4UCJ.js → lspAnchor-PPPTHRQH.js} +6 -6
- package/dist/{mcp-NNXV4YW5.js → mcp-6M34WBA5.js} +7 -7
- package/dist/{mentionProcessor-YXD3BYZG.js → mentionProcessor-TS4SITI3.js} +5 -5
- package/dist/{messages-JJ6XSPH4.js → messages-BINU6SYX.js} +1 -1
- package/dist/{model-SHEZI5VH.js → model-6IW224UU.js} +5 -5
- package/dist/{openai-MAEDGVOM.js → openai-O6CGVMYK.js} +5 -5
- package/dist/{outputStyles-Y5T4PH3H.js → outputStyles-7PPMLSV6.js} +4 -4
- package/dist/{pluginRuntime-EA5NXHW2.js → pluginRuntime-RU5STQ6F.js} +6 -6
- package/dist/{pluginValidation-AA3RZDZQ.js → pluginValidation-JTJTB3TB.js} +6 -6
- package/dist/prompts-CAPCICF3.js +56 -0
- package/dist/{pybAgentSessionLoad-DKPYB2WI.js → pybAgentSessionLoad-ZXQAHTQS.js} +4 -4
- package/dist/{pybAgentSessionResume-QBNQXHZX.js → pybAgentSessionResume-R73KFN3V.js} +4 -4
- package/dist/{pybAgentStreamJsonSession-5PBYWXYX.js → pybAgentStreamJsonSession-N4SMTC64.js} +1 -1
- package/dist/{pybHooks-66OQ6DF7.js → pybHooks-NGJ5OFAI.js} +4 -4
- package/dist/query-CYTIVMQ6.js +54 -0
- package/dist/{registry-3YQQGXL6.js → registry-FKY6JQ3L.js} +5 -5
- package/dist/{ripgrep-ZHLMP6TJ.js → ripgrep-O7MOW25M.js} +3 -3
- package/dist/{skillMarketplace-TXDXKVDH.js → skillMarketplace-VK3AYR6Q.js} +3 -3
- package/dist/{state-YDKD6B6T.js → state-T57IG35V.js} +2 -2
- package/dist/{theme-WSG2IX32.js → theme-ZEFQIPVH.js} +5 -5
- package/dist/{toolPermissionSettings-26CM7QG5.js → toolPermissionSettings-ERNXVP7A.js} +6 -6
- package/dist/tools-2XLLIKZM.js +55 -0
- package/dist/{userInput-BFWEIUZE.js → userInput-JBAUBHGI.js} +33 -33
- package/package.json +1 -1
- package/dist/REPL-GNHAV3LL.js +0 -50
- package/dist/cli-AK6CYCFX.js.map +0 -7
- package/dist/commands-5WWNVLIZ.js +0 -54
- package/dist/prompts-PMRRQP3L.js +0 -56
- package/dist/query-RHLO6AS2.js +0 -54
- package/dist/tools-4HKXD3DV.js +0 -55
- /package/dist/{REPL-GNHAV3LL.js.map → REPL-64WF5V7K.js.map} +0 -0
- /package/dist/{acp-VADDAIVV.js.map → acp-VH2FWCMR.js.map} +0 -0
- /package/dist/{agentsValidate-VDPY7LYN.js.map → agentsValidate-4E7AHAMS.js.map} +0 -0
- /package/dist/{ask-4ZMUM73X.js.map → ask-R3YZ5B44.js.map} +0 -0
- /package/dist/{autoUpdater-RIDDLHLH.js.map → autoUpdater-DCNAXD4F.js.map} +0 -0
- /package/dist/{chunk-CGFEVSPI.js.map → chunk-25GZITCX.js.map} +0 -0
- /package/dist/{chunk-2FDZ2PEI.js.map → chunk-2OOER4FR.js.map} +0 -0
- /package/dist/{chunk-7SWRPT6M.js.map → chunk-3UWTN6DM.js.map} +0 -0
- /package/dist/{chunk-VB3UZHV6.js.map → chunk-4ZGZTWMR.js.map} +0 -0
- /package/dist/{chunk-YKSGF3T7.js.map → chunk-56IL2VXC.js.map} +0 -0
- /package/dist/{chunk-TNOZ27TG.js.map → chunk-5VO2CFAL.js.map} +0 -0
- /package/dist/{chunk-277JOCVZ.js.map → chunk-BED7SG2Q.js.map} +0 -0
- /package/dist/{chunk-7I4S6UH7.js.map → chunk-BRSPPFSY.js.map} +0 -0
- /package/dist/{chunk-PHBWXWFD.js.map → chunk-CSONCQLF.js.map} +0 -0
- /package/dist/{chunk-KP7PMNEW.js.map → chunk-EP62LHB7.js.map} +0 -0
- /package/dist/{chunk-M6CFQRHR.js.map → chunk-GIXE5FJ2.js.map} +0 -0
- /package/dist/{chunk-KX7DKI3A.js.map → chunk-H2ZE5QDY.js.map} +0 -0
- /package/dist/{chunk-M3AEV7WD.js.map → chunk-HA7FKBZI.js.map} +0 -0
- /package/dist/{chunk-RUMV5QOU.js.map → chunk-KMCUZUZG.js.map} +0 -0
- /package/dist/{chunk-JKTDFI2S.js.map → chunk-LRL3MYKR.js.map} +0 -0
- /package/dist/{chunk-3JRH6I43.js.map → chunk-MMMMRMOG.js.map} +0 -0
- /package/dist/{chunk-PXAQPDGS.js.map → chunk-N3T2WAYN.js.map} +0 -0
- /package/dist/{chunk-IYGHQUN2.js.map → chunk-NRQHLVJJ.js.map} +0 -0
- /package/dist/{chunk-7AJ4EUUJ.js.map → chunk-QE7PZPHW.js.map} +0 -0
- /package/dist/{chunk-FYOORPZ4.js.map → chunk-RQ5X6LFM.js.map} +0 -0
- /package/dist/{chunk-JR5WF5M6.js.map → chunk-SE7UGQCE.js.map} +0 -0
- /package/dist/{chunk-LXJUYOGP.js.map → chunk-TBEA6BY3.js.map} +0 -0
- /package/dist/{chunk-MRG76U66.js.map → chunk-TSAURYF2.js.map} +0 -0
- /package/dist/{chunk-VSKWAGTO.js.map → chunk-VP5A6FKG.js.map} +0 -0
- /package/dist/{chunk-PJ2XKKDM.js.map → chunk-VY5KEHU5.js.map} +0 -0
- /package/dist/{chunk-JTRFDGES.js.map → chunk-X5LLT4P2.js.map} +0 -0
- /package/dist/{chunk-KRBHZ2NW.js.map → chunk-XRLMQN3Q.js.map} +0 -0
- /package/dist/{chunk-BPY6R2EU.js.map → chunk-YQ2RQUQF.js.map} +0 -0
- /package/dist/{commands-5WWNVLIZ.js.map → commands-WPHK776A.js.map} +0 -0
- /package/dist/{config-FLSTRDUK.js.map → config-7TO5SQU5.js.map} +0 -0
- /package/dist/{context-JQKLNDEK.js.map → context-LRA2DKJT.js.map} +0 -0
- /package/dist/{conversationPersistence-RVLIJAVU.js.map → conversationPersistence-Z4QSI5NB.js.map} +0 -0
- /package/dist/{conversationTracker-5HLVM6IU.js.map → conversationTracker-B3DMEHMA.js.map} +0 -0
- /package/dist/{customCommands-J2RH24UE.js.map → customCommands-6JZ2VUO2.js.map} +0 -0
- /package/dist/{env-PWLMV4WE.js.map → env-37ALKFXU.js.map} +0 -0
- /package/dist/{file-LY2Z6EYX.js.map → file-7EOMBX72.js.map} +0 -0
- /package/dist/{llm-RRAVQWE3.js.map → llm-3KQG5NEP.js.map} +0 -0
- /package/dist/{llmLazy-LRW757BZ.js.map → llmLazy-ENEH3KAB.js.map} +0 -0
- /package/dist/{loader-2LT2GMMI.js.map → loader-D6V3WFL6.js.map} +0 -0
- /package/dist/{lsp-XVTWUOP7.js.map → lsp-CTPOMI7O.js.map} +0 -0
- /package/dist/{lspAnchor-WIAD4UCJ.js.map → lspAnchor-PPPTHRQH.js.map} +0 -0
- /package/dist/{mcp-NNXV4YW5.js.map → mcp-6M34WBA5.js.map} +0 -0
- /package/dist/{mentionProcessor-YXD3BYZG.js.map → mentionProcessor-TS4SITI3.js.map} +0 -0
- /package/dist/{messages-JJ6XSPH4.js.map → messages-BINU6SYX.js.map} +0 -0
- /package/dist/{model-SHEZI5VH.js.map → model-6IW224UU.js.map} +0 -0
- /package/dist/{openai-MAEDGVOM.js.map → openai-O6CGVMYK.js.map} +0 -0
- /package/dist/{outputStyles-Y5T4PH3H.js.map → outputStyles-7PPMLSV6.js.map} +0 -0
- /package/dist/{pluginRuntime-EA5NXHW2.js.map → pluginRuntime-RU5STQ6F.js.map} +0 -0
- /package/dist/{pluginValidation-AA3RZDZQ.js.map → pluginValidation-JTJTB3TB.js.map} +0 -0
- /package/dist/{prompts-PMRRQP3L.js.map → prompts-CAPCICF3.js.map} +0 -0
- /package/dist/{pybAgentSessionLoad-DKPYB2WI.js.map → pybAgentSessionLoad-ZXQAHTQS.js.map} +0 -0
- /package/dist/{pybAgentSessionResume-QBNQXHZX.js.map → pybAgentSessionResume-R73KFN3V.js.map} +0 -0
- /package/dist/{pybAgentStreamJsonSession-5PBYWXYX.js.map → pybAgentStreamJsonSession-N4SMTC64.js.map} +0 -0
- /package/dist/{pybHooks-66OQ6DF7.js.map → pybHooks-NGJ5OFAI.js.map} +0 -0
- /package/dist/{query-RHLO6AS2.js.map → query-CYTIVMQ6.js.map} +0 -0
- /package/dist/{registry-3YQQGXL6.js.map → registry-FKY6JQ3L.js.map} +0 -0
- /package/dist/{ripgrep-ZHLMP6TJ.js.map → ripgrep-O7MOW25M.js.map} +0 -0
- /package/dist/{skillMarketplace-TXDXKVDH.js.map → skillMarketplace-VK3AYR6Q.js.map} +0 -0
- /package/dist/{state-YDKD6B6T.js.map → state-T57IG35V.js.map} +0 -0
- /package/dist/{theme-WSG2IX32.js.map → theme-ZEFQIPVH.js.map} +0 -0
- /package/dist/{toolPermissionSettings-26CM7QG5.js.map → toolPermissionSettings-ERNXVP7A.js.map} +0 -0
- /package/dist/{tools-4HKXD3DV.js.map → tools-2XLLIKZM.js.map} +0 -0
- /package/dist/{userInput-BFWEIUZE.js.map → userInput-JBAUBHGI.js.map} +0 -0
|
@@ -41,57 +41,57 @@ import {
|
|
|
41
41
|
runWithTaskListEnv,
|
|
42
42
|
runWithTaskListId,
|
|
43
43
|
updateTask
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-6UNYL6XK.js";
|
|
45
45
|
import {
|
|
46
46
|
getCurrentSessionId
|
|
47
47
|
} from "./chunk-XKYHFZEC.js";
|
|
48
48
|
import {
|
|
49
49
|
queryLLM
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-4ZGZTWMR.js";
|
|
51
51
|
import {
|
|
52
52
|
FallbackToolUseRejectedMessage,
|
|
53
53
|
MCPTool,
|
|
54
54
|
getClients,
|
|
55
55
|
getMCPTools
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-H2ZE5QDY.js";
|
|
57
57
|
import {
|
|
58
58
|
emitReminderEvent
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-ZQR3MM2D.js";
|
|
60
60
|
import {
|
|
61
61
|
getActiveAgents,
|
|
62
62
|
getAgentByType,
|
|
63
63
|
getAvailableAgentTypes
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-NRQHLVJJ.js";
|
|
65
65
|
import {
|
|
66
66
|
INTERRUPT_MESSAGE,
|
|
67
67
|
createAssistantMessage,
|
|
68
68
|
createUserMessageFromBlocks,
|
|
69
69
|
createUserMessageFromText,
|
|
70
70
|
getLastAssistantMessageId
|
|
71
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-YQ2RQUQF.js";
|
|
72
72
|
import {
|
|
73
73
|
formatDuration,
|
|
74
74
|
formatNumber
|
|
75
75
|
} from "./chunk-OUXHGDLH.js";
|
|
76
76
|
import {
|
|
77
77
|
getAbsolutePath
|
|
78
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-HA7FKBZI.js";
|
|
79
79
|
import {
|
|
80
80
|
LspFacade,
|
|
81
81
|
formatDiagnosticsPretty
|
|
82
|
-
} from "./chunk-
|
|
82
|
+
} from "./chunk-XRLMQN3Q.js";
|
|
83
83
|
import {
|
|
84
84
|
getModelManager
|
|
85
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-25GZITCX.js";
|
|
86
86
|
import {
|
|
87
87
|
getContext
|
|
88
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-RQ5X6LFM.js";
|
|
89
89
|
import {
|
|
90
90
|
getTheme
|
|
91
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-56IL2VXC.js";
|
|
92
92
|
import {
|
|
93
93
|
debug
|
|
94
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-TBEA6BY3.js";
|
|
95
95
|
import {
|
|
96
96
|
BunShell,
|
|
97
97
|
MEMORY_DIR,
|
|
@@ -103,7 +103,7 @@ import {
|
|
|
103
103
|
overwriteLog,
|
|
104
104
|
readTaskOutput,
|
|
105
105
|
resolveXdgDataPath
|
|
106
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-VP5A6FKG.js";
|
|
107
107
|
|
|
108
108
|
// src/tools/index.ts
|
|
109
109
|
import { memoize as memoize2 } from "lodash-es";
|
|
@@ -784,7 +784,7 @@ async function analyzeOutputWithLsp(output, exitCode) {
|
|
|
784
784
|
if (exitCode !== 0 || errorCount > 0 || warningCount > 0) {
|
|
785
785
|
try {
|
|
786
786
|
const { isAbsolute: isAbsolute2, resolve: resolve3 } = await import("path");
|
|
787
|
-
const { getSessionRoot: getSessionRoot2 } = await import("./state-
|
|
787
|
+
const { getSessionRoot: getSessionRoot2 } = await import("./state-T57IG35V.js");
|
|
788
788
|
const lines = output.split("\n");
|
|
789
789
|
const uniqueFiles = /* @__PURE__ */ new Set();
|
|
790
790
|
const lspSuggestions = [];
|
|
@@ -1154,7 +1154,7 @@ var DeleteTool = {
|
|
|
1154
1154
|
}
|
|
1155
1155
|
if (!force) {
|
|
1156
1156
|
try {
|
|
1157
|
-
const { LspFacade: LspFacade2 } = await import("./lsp-
|
|
1157
|
+
const { LspFacade: LspFacade2 } = await import("./lsp-CTPOMI7O.js");
|
|
1158
1158
|
const referenceDetail = await LspFacade2.checkFileReferences(fullPath);
|
|
1159
1159
|
if (referenceDetail) {
|
|
1160
1160
|
failedItems.push(
|
|
@@ -2688,12 +2688,20 @@ function mapStatusToOutput(status) {
|
|
|
2688
2688
|
return status;
|
|
2689
2689
|
}
|
|
2690
2690
|
function toTaskListItem(task) {
|
|
2691
|
-
|
|
2691
|
+
const projection = getTaskCollaborationProjection(task);
|
|
2692
|
+
const item = {
|
|
2692
2693
|
id: task.id,
|
|
2693
2694
|
subject: task.subject,
|
|
2694
2695
|
status: mapStatusToOutput(task.status),
|
|
2695
2696
|
blockedBy: task.blockedBy ?? []
|
|
2696
2697
|
};
|
|
2698
|
+
if (projection.owner) item.owner = projection.owner;
|
|
2699
|
+
if (projection.worktree) item.worktree = projection.worktree;
|
|
2700
|
+
if (projection.lane) item.lane = projection.lane;
|
|
2701
|
+
if (projection.agent) item.agent = projection.agent;
|
|
2702
|
+
if (projection.created_at !== void 0) item.created_at = projection.created_at;
|
|
2703
|
+
if (projection.updated_at !== void 0) item.updated_at = projection.updated_at;
|
|
2704
|
+
return item;
|
|
2697
2705
|
}
|
|
2698
2706
|
function toTaskDetail(task) {
|
|
2699
2707
|
return {
|
|
@@ -2708,13 +2716,33 @@ function toTaskDetail(task) {
|
|
|
2708
2716
|
};
|
|
2709
2717
|
}
|
|
2710
2718
|
function toTaskGetDetail(task) {
|
|
2711
|
-
|
|
2719
|
+
const projection = getTaskCollaborationProjection(task);
|
|
2720
|
+
const detail = {
|
|
2712
2721
|
subject: task.subject,
|
|
2713
2722
|
description: task.description,
|
|
2723
|
+
activeForm: task.activeForm,
|
|
2714
2724
|
status: mapStatusToOutput(task.status),
|
|
2725
|
+
metadata: task.metadata,
|
|
2715
2726
|
blocks: task.blocks ?? [],
|
|
2716
2727
|
blockedBy: task.blockedBy ?? []
|
|
2717
2728
|
};
|
|
2729
|
+
if (projection.owner) detail.owner = projection.owner;
|
|
2730
|
+
if (projection.worktree) detail.worktree = projection.worktree;
|
|
2731
|
+
if (projection.lane) detail.lane = projection.lane;
|
|
2732
|
+
if (projection.agent) detail.agent = projection.agent;
|
|
2733
|
+
if (projection.created_at !== void 0) detail.created_at = projection.created_at;
|
|
2734
|
+
if (projection.updated_at !== void 0) detail.updated_at = projection.updated_at;
|
|
2735
|
+
return detail;
|
|
2736
|
+
}
|
|
2737
|
+
function getTaskCollaborationProjection(task) {
|
|
2738
|
+
const metadata = task.metadata ?? {};
|
|
2739
|
+
const owner = typeof metadata.owner === "string" ? metadata.owner : void 0;
|
|
2740
|
+
const worktree = typeof metadata.worktree === "string" ? metadata.worktree : void 0;
|
|
2741
|
+
const lane = typeof metadata.lane === "string" ? metadata.lane : void 0;
|
|
2742
|
+
const agent = typeof metadata.agent === "string" ? metadata.agent : void 0;
|
|
2743
|
+
const created_at = typeof metadata.created_at === "number" || typeof metadata.created_at === "string" ? metadata.created_at : void 0;
|
|
2744
|
+
const updated_at = typeof metadata.updated_at === "number" || typeof metadata.updated_at === "string" ? metadata.updated_at : void 0;
|
|
2745
|
+
return { owner, worktree, lane, agent, created_at, updated_at };
|
|
2718
2746
|
}
|
|
2719
2747
|
function createTaskToolError(params) {
|
|
2720
2748
|
return {
|
|
@@ -2756,15 +2784,24 @@ Skip using this tool only when:
|
|
|
2756
2784
|
- Use TaskCreate when scope changes during execution.
|
|
2757
2785
|
- Use TaskCreate when a milestone is completed and the next concrete work unit begins.
|
|
2758
2786
|
|
|
2787
|
+
## Core Workflow
|
|
2788
|
+
|
|
2789
|
+
**The Two-Phase Pattern (IMPORTANT):**
|
|
2790
|
+
- **Phase 1 - Create**: Create all tasks one by one WITHOUT dependencies (blockedBy=[]).
|
|
2791
|
+
- **Phase 2 - Link**: Use TaskUpdate to add blockedBy AFTER all related tasks exist.
|
|
2792
|
+
|
|
2793
|
+
This pattern ensures clean dependency graph construction and prevents reference errors.
|
|
2794
|
+
|
|
2759
2795
|
## Input Notes
|
|
2760
2796
|
- subject is required.
|
|
2761
2797
|
- listId is optional; omit to use the default list.
|
|
2762
2798
|
- TaskCreate only supports single-task creation; create multiple tasks one by one.
|
|
2763
2799
|
- For multi-step plans, create the structured task list without dependencies and add blockedBy later via TaskUpdate.
|
|
2764
|
-
- activeForm is required
|
|
2800
|
+
- activeForm is required.
|
|
2801
|
+
- metadata is optional and should only include stable coordination fields you want to persist.
|
|
2765
2802
|
- blockedBy is always stored as an array (empty when not used).
|
|
2766
2803
|
- description and blockedBy are kept separate in JSON; any joining is only for terminal rendering.
|
|
2767
|
-
- Task ordering relies on task id;
|
|
2804
|
+
- Task ordering relies on task id;
|
|
2768
2805
|
- Use metadata.planFinalized="true" in TaskUpdate when dependencies are ready to be validated globally.
|
|
2769
2806
|
- Do not mention tool names or tool usage in user-facing messages.
|
|
2770
2807
|
- When uncertain whether to track, prefer tracking.
|
|
@@ -2788,50 +2825,296 @@ Preferred single-task template:
|
|
|
2788
2825
|
## Status Notes
|
|
2789
2826
|
- Use pending when dependencies prevent work and fill blockedBy.
|
|
2790
2827
|
|
|
2828
|
+
## Task Lifecycle Overview
|
|
2829
|
+
|
|
2830
|
+
Tasks flow through these states:
|
|
2831
|
+
|
|
2832
|
+
- pending --(start work)--> in_progress --(complete)--> done
|
|
2833
|
+
- pending --(cancel)--> deleted
|
|
2834
|
+
- in_progress --(cancel)--> deleted
|
|
2835
|
+
|
|
2836
|
+
**State Definitions:**
|
|
2837
|
+
- **pending**: Not started, may be blocked by dependencies
|
|
2838
|
+
- **in_progress**: Currently being worked on (only ONE task at a time)
|
|
2839
|
+
- **done**: Successfully completed (triggers unlock propagation)
|
|
2840
|
+
- **deleted**: Cancelled or no longer needed
|
|
2841
|
+
|
|
2842
|
+
**Ready vs Blocked:**
|
|
2843
|
+
- A task is **ready** when: status=pending AND blockedBy=[] (all dependencies satisfied)
|
|
2844
|
+
- A task is **blocked** when: blockedBy contains task IDs that are not yet done/deleted
|
|
2845
|
+
|
|
2846
|
+
## Dependency Relationships
|
|
2847
|
+
|
|
2848
|
+
Tasks can have dependencies on other tasks:
|
|
2849
|
+
|
|
2850
|
+
- **blockedBy**: List of task IDs that must complete before this task can start
|
|
2851
|
+
- **blocks**: List of task IDs that are waiting for this task (auto-synced, do not set manually)
|
|
2852
|
+
|
|
2853
|
+
**How it works:**
|
|
2854
|
+
|
|
2855
|
+
Task A (blockedBy: [])
|
|
2856
|
+
Task B (blockedBy: ["A"]) \u2190 B waits for A
|
|
2857
|
+
Task C (blockedBy: ["A"]) \u2190 C waits for A
|
|
2858
|
+
|
|
2859
|
+
When Task A completes:
|
|
2860
|
+
- blockedBy is cleared from B and C
|
|
2861
|
+
- Both B and C become ready (can run in parallel)
|
|
2862
|
+
|
|
2863
|
+
**Important:** When you set blockedBy via TaskUpdate, the reverse blocks relationship is automatically synchronized. Never manually set blocks.
|
|
2864
|
+
|
|
2865
|
+
## Handling Natural Language Requests
|
|
2866
|
+
|
|
2867
|
+
When users provide vague or high-level requests (e.g., "build a user auth module"), you must:
|
|
2868
|
+
1. **Decompose** the request into logical subtasks based on software engineering best practices
|
|
2869
|
+
2. **Identify dependencies** between subtasks (what must complete before what can start)
|
|
2870
|
+
3. **Create tasks first** with blockedBy=[] for all tasks
|
|
2871
|
+
4. **Add dependencies second** using TaskUpdate.addBlockedBy
|
|
2872
|
+
|
|
2873
|
+
Common decomposition patterns:
|
|
2874
|
+
- **Database/API pattern**: Schema design \u2192 Table implementation \u2192 API endpoints \u2192 Tests
|
|
2875
|
+
- **Frontend pattern**: Design \u2192 Components \u2192 Integration \u2192 Testing
|
|
2876
|
+
- **Full-stack pattern**: Backend \u2192 API \u2192 Frontend \u2192 Integration tests
|
|
2877
|
+
|
|
2791
2878
|
## Examples of When to Use TaskCreate
|
|
2792
2879
|
|
|
2880
|
+
### Category A: No Explicit Dependencies or Order (Most Common)
|
|
2881
|
+
|
|
2882
|
+
User provides a high-level request without specifying how to break it down or what should be done first.
|
|
2883
|
+
|
|
2793
2884
|
<example>
|
|
2794
|
-
User:
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2885
|
+
User: Build a user authentication module
|
|
2886
|
+
|
|
2887
|
+
Assistant: This is a complex feature that requires multiple components. Let me plan the implementation steps.
|
|
2888
|
+
|
|
2889
|
+
*Creates tasks (Phase 1):*
|
|
2890
|
+
TaskCreate(subject="Design auth database schema", activeForm="Designing auth database schema")
|
|
2891
|
+
TaskCreate(subject="Implement users table", activeForm="Implementing users table")
|
|
2892
|
+
TaskCreate(subject="Implement sessions table", activeForm="Implementing sessions table")
|
|
2893
|
+
TaskCreate(subject="Build auth API endpoints", activeForm="Building auth API endpoints")
|
|
2894
|
+
TaskCreate(subject="Write unit tests", activeForm="Writing unit tests")
|
|
2895
|
+
TaskCreate(subject="Write integration tests", activeForm="Writing integration tests")
|
|
2896
|
+
|
|
2897
|
+
*Adds dependencies (Phase 2):*
|
|
2898
|
+
TaskUpdate(taskId="2", addBlockedBy=["1"])
|
|
2899
|
+
TaskUpdate(taskId="3", addBlockedBy=["1"])
|
|
2900
|
+
TaskUpdate(taskId="4", addBlockedBy=["2", "3"])
|
|
2901
|
+
TaskUpdate(taskId="5", addBlockedBy=["4"])
|
|
2902
|
+
TaskUpdate(taskId="6", addBlockedBy=["4"])
|
|
2903
|
+
|
|
2904
|
+
Auth module planned: 6 tasks with dependency graph established. Starting with database design.
|
|
2905
|
+
|
|
2906
|
+
<reasoning>
|
|
2907
|
+
The assistant used TaskCreate because:
|
|
2908
|
+
1. User provided a high-level feature request without task breakdown
|
|
2909
|
+
2. Authentication module requires multiple components (database, tables, API, tests)
|
|
2910
|
+
3. The assistant inferred dependencies based on software engineering practices: schema before tables, tables before API, API before tests
|
|
2911
|
+
4. Two-phase pattern: create all tasks first, then link dependencies
|
|
2912
|
+
</reasoning>
|
|
2800
2913
|
</example>
|
|
2801
2914
|
|
|
2802
2915
|
<example>
|
|
2803
|
-
User:
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2916
|
+
User: I want to add a dark mode toggle to the application settings. Make sure you run the tests when you're done!
|
|
2917
|
+
|
|
2918
|
+
Assistant: I'll help add a dark mode toggle. Let me plan the implementation steps.
|
|
2919
|
+
|
|
2920
|
+
*Creates tasks (Phase 1):*
|
|
2921
|
+
TaskCreate(subject="Create dark mode toggle component", activeForm="Creating dark mode toggle component")
|
|
2922
|
+
TaskCreate(subject="Add dark mode state management", activeForm="Adding dark mode state management")
|
|
2923
|
+
TaskCreate(subject="Implement dark theme styles", activeForm="Implementing dark theme styles")
|
|
2924
|
+
TaskCreate(subject="Update components for theme switching", activeForm="Updating components for theme switching")
|
|
2925
|
+
TaskCreate(subject="Run tests and fix failures", activeForm="Running tests and fixing failures")
|
|
2926
|
+
|
|
2927
|
+
*Adds dependencies (Phase 2):*
|
|
2928
|
+
TaskUpdate(taskId="3", addBlockedBy=["2"])
|
|
2929
|
+
TaskUpdate(taskId="4", addBlockedBy=["1", "3"])
|
|
2930
|
+
TaskUpdate(taskId="5", addBlockedBy=["4"])
|
|
2931
|
+
|
|
2932
|
+
Dark mode toggle planned: 5 tasks. Starting with the toggle component.
|
|
2933
|
+
|
|
2934
|
+
<reasoning>
|
|
2935
|
+
The assistant used TaskCreate because:
|
|
2936
|
+
1. Adding dark mode is a multi-step feature requiring UI, state management, and styling changes
|
|
2937
|
+
2. User explicitly requested tests be run afterward - this becomes the final task
|
|
2938
|
+
3. Dependencies inferred: styles depend on state management, components depend on toggle and styles, tests run last
|
|
2939
|
+
</reasoning>
|
|
2809
2940
|
</example>
|
|
2810
2941
|
|
|
2811
2942
|
<example>
|
|
2812
|
-
User:
|
|
2813
|
-
|
|
2814
|
-
|
|
2943
|
+
User: Help optimize my React app performance, rendering is slow
|
|
2944
|
+
|
|
2945
|
+
Assistant: Let me first examine the codebase to identify performance bottlenecks.
|
|
2946
|
+
|
|
2947
|
+
*Examines component structure, render patterns, state management*
|
|
2948
|
+
|
|
2949
|
+
After analyzing the codebase, I've identified several performance issues. Let me plan the optimizations.
|
|
2950
|
+
|
|
2951
|
+
*Creates tasks (Phase 1):*
|
|
2952
|
+
TaskCreate(subject="Add memoization to ProductList calculations", activeForm="Adding memoization to ProductList")
|
|
2953
|
+
TaskCreate(subject="Implement virtualization for Dashboard lists", activeForm="Implementing list virtualization")
|
|
2954
|
+
TaskCreate(subject="Optimize image loading in Gallery", activeForm="Optimizing image loading")
|
|
2955
|
+
TaskCreate(subject="Fix state update loops in ShoppingCart", activeForm="Fixing state update loops")
|
|
2956
|
+
|
|
2957
|
+
*Dependencies: These can be done at the same time, no specific order needed*
|
|
2958
|
+
|
|
2959
|
+
React performance optimization planned: 4 tasks. Starting with ProductList memoization.
|
|
2960
|
+
|
|
2961
|
+
<reasoning>
|
|
2962
|
+
The assistant used TaskCreate because:
|
|
2963
|
+
1. First examined the codebase to identify specific performance issues
|
|
2964
|
+
2. Multiple independent optimizations were identified - each becomes a task
|
|
2965
|
+
3. These tasks have NO dependencies - they can run in parallel
|
|
2966
|
+
4. Todo list helps track which optimizations have been addressed
|
|
2967
|
+
</reasoning>
|
|
2968
|
+
</example>
|
|
2969
|
+
|
|
2970
|
+
### Category B: Explicit Order Specified by User
|
|
2971
|
+
|
|
2972
|
+
User clearly indicates what should be done first, second, etc. using words like "first... then... finally..." or numbered lists.
|
|
2973
|
+
|
|
2974
|
+
<example>
|
|
2975
|
+
User: First design the database, then create the users table and sessions table, then write the API, and finally test
|
|
2976
|
+
|
|
2977
|
+
Assistant: User has explicitly specified the order. Let me plan tasks according to this sequence.
|
|
2978
|
+
|
|
2979
|
+
*Creates tasks (Phase 1):*
|
|
2980
|
+
TaskCreate(subject="Design database schema", activeForm="Designing database schema")
|
|
2981
|
+
TaskCreate(subject="Implement users table", activeForm="Implementing users table")
|
|
2982
|
+
TaskCreate(subject="Implement sessions table", activeForm="Implementing sessions table")
|
|
2983
|
+
TaskCreate(subject="Build API endpoints", activeForm="Building API endpoints")
|
|
2984
|
+
TaskCreate(subject="Write tests", activeForm="Writing tests")
|
|
2985
|
+
|
|
2986
|
+
*Adds dependencies based on user's explicit order (Phase 2):*
|
|
2987
|
+
TaskUpdate(taskId="2", addBlockedBy=["1"]) // users table waits for database
|
|
2988
|
+
TaskUpdate(taskId="3", addBlockedBy=["1"]) // sessions table waits for database
|
|
2989
|
+
TaskUpdate(taskId="4", addBlockedBy=["2", "3"]) // API waits for both tables
|
|
2990
|
+
TaskUpdate(taskId="5", addBlockedBy=["4"]) // tests wait for API
|
|
2991
|
+
|
|
2992
|
+
Tasks planned in your specified order: database \u2192 users/sessions tables \u2192 API \u2192 tests
|
|
2993
|
+
|
|
2994
|
+
<reasoning>
|
|
2995
|
+
The assistant used TaskCreate because:
|
|
2996
|
+
1. User explicitly specified the order: database first, then tables, then API, finally tests
|
|
2997
|
+
2. This order translates directly into dependency relationships
|
|
2998
|
+
3. Users table and sessions table can run in parallel after database (both depend only on task 1)
|
|
2999
|
+
4. Two-phase pattern: create all tasks, then add dependencies matching user's specified order
|
|
3000
|
+
</reasoning>
|
|
2815
3001
|
</example>
|
|
2816
3002
|
|
|
2817
3003
|
<example>
|
|
2818
|
-
User:
|
|
2819
|
-
|
|
2820
|
-
|
|
3004
|
+
User: I need to add a character limit to the bio field. First, add the validation logic to the backend, then update the frontend form.
|
|
3005
|
+
|
|
3006
|
+
Assistant: I'll plan this with the order you specified.
|
|
3007
|
+
|
|
3008
|
+
*Creates tasks (Phase 1):*
|
|
3009
|
+
TaskCreate(subject="Add backend validation for bio character limit", activeForm="Adding backend validation")
|
|
3010
|
+
TaskCreate(subject="Update frontend form to enforce character limit", activeForm="Updating frontend form")
|
|
3011
|
+
|
|
3012
|
+
*Adds dependencies (Phase 2):*
|
|
3013
|
+
TaskUpdate(taskId="2", addBlockedBy=["1"]) // frontend waits for backend
|
|
3014
|
+
|
|
3015
|
+
Bio character limit planned: backend validation first, then frontend update.
|
|
3016
|
+
|
|
3017
|
+
<reasoning>
|
|
3018
|
+
The assistant used TaskCreate because:
|
|
3019
|
+
1. User used "First... then..." which explicitly defines the order
|
|
3020
|
+
2. Backend must be done before frontend - this is a dependency relationship
|
|
3021
|
+
3. Two tasks with one dependency
|
|
3022
|
+
</reasoning>
|
|
2821
3023
|
</example>
|
|
2822
3024
|
|
|
2823
3025
|
<example>
|
|
2824
|
-
User:
|
|
2825
|
-
|
|
2826
|
-
|
|
3026
|
+
User: I need to implement user registration, product catalog, shopping cart, and checkout flow
|
|
3027
|
+
|
|
3028
|
+
Assistant: These are core e-commerce features. Let me plan tasks for each module.
|
|
3029
|
+
|
|
3030
|
+
*Creates tasks for each feature (Phase 1):*
|
|
3031
|
+
TaskCreate(subject="Implement user registration", activeForm="Implementing user registration")
|
|
3032
|
+
TaskCreate(subject="Implement product catalog", activeForm="Implementing product catalog")
|
|
3033
|
+
TaskCreate(subject="Implement shopping cart", activeForm="Implementing shopping cart")
|
|
3034
|
+
TaskCreate(subject="Implement checkout flow", activeForm="Implementing checkout flow")
|
|
3035
|
+
|
|
3036
|
+
*Adds dependencies (Phase 2):*
|
|
3037
|
+
TaskUpdate(taskId="3", addBlockedBy=["2"]) // cart depends on product catalog
|
|
3038
|
+
TaskUpdate(taskId="4", addBlockedBy=["1", "3"]) // checkout depends on registration and cart
|
|
3039
|
+
|
|
3040
|
+
E-commerce features planned: user registration and product catalog can start together, cart waits for catalog, checkout waits for registration and cart.
|
|
3041
|
+
|
|
3042
|
+
<reasoning>
|
|
3043
|
+
The assistant used TaskCreate because:
|
|
3044
|
+
1. User provided multiple complex features in a comma-separated list
|
|
3045
|
+
2. These features have natural dependencies: cart needs products, checkout needs user and cart
|
|
3046
|
+
3. Registration and catalog can run in parallel (no dependency between them)
|
|
3047
|
+
4. Todo list helps organize these large features into manageable tasks
|
|
3048
|
+
</reasoning>
|
|
3049
|
+
</example>
|
|
3050
|
+
|
|
3051
|
+
### Category C: Simple or Single Task
|
|
3052
|
+
|
|
3053
|
+
User's request is straightforward and doesn't require complex planning.
|
|
3054
|
+
|
|
3055
|
+
<example>
|
|
3056
|
+
User: Just fix the typo in the documentation
|
|
3057
|
+
|
|
3058
|
+
Assistant: This is a straightforward fix. I'll create a single task to track it.
|
|
3059
|
+
|
|
3060
|
+
*Creates one task:*
|
|
3061
|
+
TaskCreate(subject="Fix typo in documentation", activeForm="Fixing documentation typo")
|
|
3062
|
+
|
|
3063
|
+
<reasoning>
|
|
3064
|
+
The assistant used TaskCreate because:
|
|
3065
|
+
1. This is a single task that can be tracked
|
|
3066
|
+
2. No complex breakdown needed
|
|
3067
|
+
3. Still useful to track for completeness and progress visibility
|
|
3068
|
+
</reasoning>
|
|
3069
|
+
</example>
|
|
3070
|
+
|
|
3071
|
+
<example>
|
|
3072
|
+
User: Add a comment to the calculateTotal function explaining what it does
|
|
3073
|
+
|
|
3074
|
+
Assistant: This is a simple single-step task.
|
|
3075
|
+
|
|
3076
|
+
*Creates one task:*
|
|
3077
|
+
TaskCreate(subject="Add comment to calculateTotal function", activeForm="Adding function comment")
|
|
3078
|
+
|
|
3079
|
+
<reasoning>
|
|
3080
|
+
The assistant used TaskCreate because:
|
|
3081
|
+
1. Single straightforward task in one location
|
|
3082
|
+
2. Creating a task helps track completion
|
|
3083
|
+
</reasoning>
|
|
3084
|
+
</example>
|
|
3085
|
+
|
|
3086
|
+
### Category D: Adding Forgotten Tasks
|
|
3087
|
+
|
|
3088
|
+
User realizes something was missed after the initial plan.
|
|
3089
|
+
|
|
3090
|
+
<example>
|
|
3091
|
+
User: I forgot, we also need logging for the auth module
|
|
3092
|
+
|
|
3093
|
+
Assistant: Let me add the logging task and link it appropriately.
|
|
3094
|
+
|
|
3095
|
+
TaskCreate(subject="Add auth logging", activeForm="Adding auth logging")
|
|
3096
|
+
|
|
3097
|
+
*The logging task depends on API endpoints being ready:*
|
|
3098
|
+
TaskUpdate(taskId="7", addBlockedBy=["4"]) // logging depends on API
|
|
3099
|
+
|
|
3100
|
+
Auth logging added. It will be done after the API endpoints are complete.
|
|
3101
|
+
|
|
3102
|
+
<reasoning>
|
|
3103
|
+
The assistant used TaskCreate because:
|
|
3104
|
+
1. User added a new requirement after initial planning
|
|
3105
|
+
2. New task was created first with TaskCreate
|
|
3106
|
+
3. Then linked to existing tasks via TaskUpdate.addBlockedBy
|
|
3107
|
+
4. Logging logically depends on API endpoints existence
|
|
3108
|
+
</reasoning>
|
|
2827
3109
|
</example>
|
|
2828
3110
|
`.trim();
|
|
2829
3111
|
|
|
2830
3112
|
// src/tools/interaction/TaskCreateTool/TaskCreateTool.tsx
|
|
2831
3113
|
var inputSchema8 = z9.strictObject({
|
|
3114
|
+
listId: z9.string().min(1).optional(),
|
|
2832
3115
|
subject: z9.string().min(1),
|
|
2833
3116
|
description: z9.string().min(1),
|
|
2834
|
-
activeForm: z9.string().min(1)
|
|
3117
|
+
activeForm: z9.string().min(1),
|
|
2835
3118
|
metadata: metadataSchema.optional()
|
|
2836
3119
|
});
|
|
2837
3120
|
var TaskCreateTool = {
|
|
@@ -2876,14 +3159,17 @@ var TaskCreateTool = {
|
|
|
2876
3159
|
description: input.description,
|
|
2877
3160
|
activeForm: input.activeForm,
|
|
2878
3161
|
metadata: input.metadata
|
|
2879
|
-
});
|
|
2880
|
-
const { listId } = getTaskListPaths();
|
|
2881
|
-
|
|
3162
|
+
}, { listId: input.listId });
|
|
3163
|
+
const { listId } = getTaskListPaths(input.listId);
|
|
3164
|
+
const timestamp = Date.now();
|
|
3165
|
+
const payload = {
|
|
2882
3166
|
listId,
|
|
2883
3167
|
taskId: task.id,
|
|
2884
3168
|
task,
|
|
2885
|
-
timestamp
|
|
2886
|
-
}
|
|
3169
|
+
timestamp
|
|
3170
|
+
};
|
|
3171
|
+
emitReminderEvent("task.created", payload);
|
|
3172
|
+
emitReminderEvent("task.created.v1", payload);
|
|
2887
3173
|
yield {
|
|
2888
3174
|
type: "result",
|
|
2889
3175
|
data: {
|
|
@@ -2941,6 +3227,7 @@ Assistant: I'll fetch the task details first.
|
|
|
2941
3227
|
|
|
2942
3228
|
// src/tools/interaction/TaskGetTool/TaskGetTool.tsx
|
|
2943
3229
|
var inputSchema9 = z10.strictObject({
|
|
3230
|
+
listId: z10.string().min(1).optional(),
|
|
2944
3231
|
taskId: z10.string().min(1)
|
|
2945
3232
|
});
|
|
2946
3233
|
var TaskGetTool = {
|
|
@@ -2978,8 +3265,8 @@ var TaskGetTool = {
|
|
|
2978
3265
|
return null;
|
|
2979
3266
|
},
|
|
2980
3267
|
async *call(input) {
|
|
2981
|
-
const { listId } = getTaskListPaths();
|
|
2982
|
-
const task = getTask(input.taskId);
|
|
3268
|
+
const { listId } = getTaskListPaths(input.listId);
|
|
3269
|
+
const task = getTask(input.taskId, { listId: input.listId });
|
|
2983
3270
|
if (!task) {
|
|
2984
3271
|
yield {
|
|
2985
3272
|
type: "result",
|
|
@@ -3026,6 +3313,7 @@ Skip using this tool when:
|
|
|
3026
3313
|
NOTE that TaskList is for summaries and readiness; use TaskGet for details.
|
|
3027
3314
|
|
|
3028
3315
|
## Input Notes
|
|
3316
|
+
- listId is optional; omit to use the default list.
|
|
3029
3317
|
- status filters the returned items; omit to exclude deleted tasks by default.
|
|
3030
3318
|
- blockedBy may be empty early in planning and will appear as dependencies are added.
|
|
3031
3319
|
- Do not mention tool names or tool usage in user-facing messages.
|
|
@@ -3053,6 +3341,7 @@ Assistant: I'll list tasks to show the updated ready/blocked breakdown.
|
|
|
3053
3341
|
|
|
3054
3342
|
// src/tools/interaction/TaskListTool/TaskListTool.tsx
|
|
3055
3343
|
var inputSchema10 = z11.strictObject({
|
|
3344
|
+
listId: z11.string().min(1).optional(),
|
|
3056
3345
|
status: z11.enum(["pending", "in_progress", "completed", "deleted"]).optional()
|
|
3057
3346
|
});
|
|
3058
3347
|
var filterByStatus = (tasks, statuses) => {
|
|
@@ -3069,6 +3358,21 @@ var mapStatusFilterInput = (input) => {
|
|
|
3069
3358
|
if (input === "pending") return ["pending"];
|
|
3070
3359
|
return ["in_progress"];
|
|
3071
3360
|
};
|
|
3361
|
+
var getActiveBlockers = (task, tasksById) => {
|
|
3362
|
+
const blockers = task.blockedBy ?? [];
|
|
3363
|
+
const active = [];
|
|
3364
|
+
for (const blockerId of blockers) {
|
|
3365
|
+
const blocker = tasksById.get(blockerId);
|
|
3366
|
+
if (!blocker) {
|
|
3367
|
+
active.push(blockerId);
|
|
3368
|
+
continue;
|
|
3369
|
+
}
|
|
3370
|
+
if (blocker.status !== "done" && blocker.status !== "deleted") {
|
|
3371
|
+
active.push(blockerId);
|
|
3372
|
+
}
|
|
3373
|
+
}
|
|
3374
|
+
return active;
|
|
3375
|
+
};
|
|
3072
3376
|
var TaskListTool = {
|
|
3073
3377
|
name: "TaskList",
|
|
3074
3378
|
cachedDescription: DESCRIPTION7,
|
|
@@ -3105,10 +3409,19 @@ var TaskListTool = {
|
|
|
3105
3409
|
},
|
|
3106
3410
|
async *call(input) {
|
|
3107
3411
|
try {
|
|
3108
|
-
const { listId } = getTaskListPaths();
|
|
3109
|
-
const tasks = listTasks();
|
|
3412
|
+
const { listId } = getTaskListPaths(input.listId);
|
|
3413
|
+
const tasks = listTasks({ listId: input.listId });
|
|
3110
3414
|
const filtered = filterByStatus(tasks, mapStatusFilterInput(input.status));
|
|
3111
|
-
const
|
|
3415
|
+
const tasksById = new Map(tasks.map((task) => [task.id, task]));
|
|
3416
|
+
const items = filtered.map((task) => {
|
|
3417
|
+
const base = toTaskListItem(task);
|
|
3418
|
+
const activeBlockers = getActiveBlockers(task, tasksById);
|
|
3419
|
+
return {
|
|
3420
|
+
...base,
|
|
3421
|
+
ready: task.status === "pending" && activeBlockers.length === 0,
|
|
3422
|
+
activeBlockers
|
|
3423
|
+
};
|
|
3424
|
+
});
|
|
3112
3425
|
yield {
|
|
3113
3426
|
type: "result",
|
|
3114
3427
|
data: {
|
|
@@ -3157,40 +3470,350 @@ NOTE that TaskUpdate should be used when you need to persist task changes.
|
|
|
3157
3470
|
- listId is optional; omit to use the default list.
|
|
3158
3471
|
- Dependencies are validated for cycles; invalid cycles will be rejected.
|
|
3159
3472
|
- Use TaskUpdate to add blockedBy after tasks are created.
|
|
3473
|
+
- Use addBlocks when the current task should block other tasks; the reverse blockedBy relation is synchronized.
|
|
3160
3474
|
- You can set metadata.planFinalized="true" to trigger a full dependency validation pass.
|
|
3161
|
-
- activeForm
|
|
3475
|
+
- activeForm is optional in updates; when omitted, existing value is preserved.
|
|
3162
3476
|
- blockedBy is always stored as an array (empty when not used).
|
|
3163
3477
|
- description and blockedBy are kept separate in JSON; any joining is only for terminal rendering.
|
|
3164
3478
|
- Task ordering relies on task id; do not use priority fields.
|
|
3165
3479
|
- Do not mention tool names or tool usage in user-facing messages.
|
|
3166
3480
|
|
|
3481
|
+
## The Two Usage Patterns
|
|
3482
|
+
|
|
3483
|
+
### Pattern 1: Dependency Linking (After TaskCreate)
|
|
3484
|
+
Use TaskUpdate to establish dependencies AFTER all tasks are created:
|
|
3485
|
+
- Create tasks with TaskCreate (blockedBy=[])
|
|
3486
|
+
- Link dependencies with TaskUpdate.addBlockedBy or TaskUpdate.addBlocks
|
|
3487
|
+
- This ensures reference validity and clean graph construction
|
|
3488
|
+
|
|
3489
|
+
### Pattern 2: Status Progression
|
|
3490
|
+
Use TaskUpdate to move tasks through the execution lifecycle:
|
|
3491
|
+
- pending \u2192 in_progress: When starting work on a task
|
|
3492
|
+
- in_progress \u2192 completed: When task is done (triggers unlock propagation)
|
|
3493
|
+
- Any \u2192 deleted: When task is obsolete or cancelled
|
|
3494
|
+
|
|
3495
|
+
## Update Patterns
|
|
3496
|
+
- Simple status-only update: update one task status directly (pending \u2192 in_progress \u2192 completed) when no dependency change is needed.
|
|
3497
|
+
- Complex dependency and unlock update: update blockedBy/addBlocks and status together, then consume unlockResult.readyNow immediately.
|
|
3498
|
+
- Cancel or retire path: use deleted when a task is intentionally retired and should no longer appear in default lists.
|
|
3499
|
+
|
|
3167
3500
|
## Field Guidance
|
|
3168
3501
|
- activeForm: short verb phrase describing the in-progress action.
|
|
3169
3502
|
- description: prefer a one-line overview plus bullet points for multi-step tasks; for very simple tasks a short sentence is fine.
|
|
3503
|
+
- collaboration metadata keys:
|
|
3504
|
+
- metadata.owner for task owner identity
|
|
3505
|
+
- metadata.worktree for bound worktree name
|
|
3506
|
+
- metadata.lane for collaboration lane
|
|
3507
|
+
- metadata.agent for agent role or identifier
|
|
3508
|
+
- metadata.created_at for creation timestamp
|
|
3509
|
+
- metadata.updated_at for update timestamp
|
|
3170
3510
|
|
|
3171
3511
|
## Status Notes
|
|
3172
3512
|
- Use in_progress for the task you are actively working on.
|
|
3173
3513
|
- Use pending when dependencies prevent progress and set blockedBy.
|
|
3174
3514
|
- Use completed only when all dependencies are satisfied.
|
|
3515
|
+
- When status becomes completed, consume unlockResult.readyNow immediately.
|
|
3516
|
+
- If readyNow is returned, continue with those tasks without calling TaskList.
|
|
3517
|
+
|
|
3518
|
+
## Task Lifecycle Overview
|
|
3519
|
+
|
|
3520
|
+
Tasks flow through these states:
|
|
3521
|
+
|
|
3522
|
+
- pending --(start work)--> in_progress --(complete)--> done
|
|
3523
|
+
- pending --(cancel)--> deleted
|
|
3524
|
+
- in_progress --(cancel)--> deleted
|
|
3525
|
+
|
|
3526
|
+
**State Definitions:**
|
|
3527
|
+
- **pending**: Not started, may be blocked by dependencies
|
|
3528
|
+
- **in_progress**: Currently being worked on (only ONE task at a time)
|
|
3529
|
+
- **done**: Successfully completed (triggers unlock propagation)
|
|
3530
|
+
- **deleted**: Cancelled or no longer needed
|
|
3531
|
+
|
|
3532
|
+
**Ready vs Blocked:**
|
|
3533
|
+
- A task is **ready** when: status=pending AND blockedBy=[] (all dependencies satisfied)
|
|
3534
|
+
- A task is **blocked** when: blockedBy contains task IDs that are not yet done/deleted
|
|
3535
|
+
|
|
3536
|
+
## Dependency Relationships
|
|
3537
|
+
|
|
3538
|
+
Tasks can have dependencies on other tasks:
|
|
3539
|
+
|
|
3540
|
+
- **blockedBy**: List of task IDs that must complete before this task can start
|
|
3541
|
+
- **blocks**: List of task IDs that are waiting for this task (auto-synced, do not set manually)
|
|
3542
|
+
|
|
3543
|
+
**How it works:**
|
|
3544
|
+
|
|
3545
|
+
Task A (blockedBy: [])
|
|
3546
|
+
Task B (blockedBy: ["A"]) \u2190 B waits for A
|
|
3547
|
+
Task C (blockedBy: ["A"]) \u2190 C waits for A
|
|
3548
|
+
|
|
3549
|
+
When Task A completes:
|
|
3550
|
+
- blockedBy is cleared from B and C
|
|
3551
|
+
- Both B and C become ready (can run in parallel)
|
|
3552
|
+
|
|
3553
|
+
**Important:** When you set blockedBy via TaskUpdate, the reverse blocks relationship is automatically synchronized. Never manually set blocks.
|
|
3554
|
+
|
|
3555
|
+
## Understanding Unlock Propagation
|
|
3556
|
+
|
|
3557
|
+
When a task is marked as completed:
|
|
3558
|
+
1. It is removed from the blockedBy list of all tasks it was blocking
|
|
3559
|
+
2. Any tasks that become unblocked (blockedBy becomes empty) appear in unlockResult.readyNow
|
|
3560
|
+
3. You should immediately continue with those readyNow tasks without calling TaskList
|
|
3561
|
+
|
|
3562
|
+
This enables efficient "chain execution" without redundant status checks.
|
|
3175
3563
|
|
|
3176
3564
|
## Examples of When to Use TaskUpdate
|
|
3177
3565
|
|
|
3566
|
+
### Category A: Status Progression (Moving Tasks Forward)
|
|
3567
|
+
|
|
3178
3568
|
<example>
|
|
3179
|
-
User:
|
|
3180
|
-
|
|
3181
|
-
|
|
3569
|
+
User: The database design is done, let's start on the users table
|
|
3570
|
+
|
|
3571
|
+
Assistant: Database design is complete. Let me update the task status and continue to the next step.
|
|
3572
|
+
|
|
3573
|
+
TaskUpdate(taskId="1", status="completed")
|
|
3574
|
+
*Result shows readyNow: ["2", "3"]*
|
|
3575
|
+
|
|
3576
|
+
Both the users table and sessions table are now ready. I'll start with the users table.
|
|
3577
|
+
|
|
3578
|
+
TaskUpdate(taskId="2", status="in_progress")
|
|
3579
|
+
|
|
3580
|
+
<reasoning>
|
|
3581
|
+
The assistant used TaskUpdate because:
|
|
3582
|
+
1. User indicated the database design is done
|
|
3583
|
+
2. Completing task 1 triggers unlock - tasks 2 and 3 become ready
|
|
3584
|
+
3. User said to start the users table
|
|
3585
|
+
4. The unlockResult.readyNow tells us what tasks are now unblocked
|
|
3586
|
+
</reasoning>
|
|
3587
|
+
</example>
|
|
3588
|
+
|
|
3589
|
+
<example>
|
|
3590
|
+
User: I've finished the API endpoints. What should I work on next?
|
|
3591
|
+
|
|
3592
|
+
Assistant: Let me mark the API task complete and see what's unblocked.
|
|
3593
|
+
|
|
3594
|
+
TaskUpdate(taskId="4", status="completed")
|
|
3595
|
+
*Result shows readyNow: ["5", "6"]*
|
|
3596
|
+
|
|
3597
|
+
The unit tests and integration tests are now ready. Would you like to start with unit tests?
|
|
3598
|
+
|
|
3599
|
+
<reasoning>
|
|
3600
|
+
The assistant used TaskUpdate because:
|
|
3601
|
+
1. User said they finished the API endpoints
|
|
3602
|
+
2. Completing this task triggers unlock propagation
|
|
3603
|
+
3. The readyNow field shows which tasks can now start
|
|
3604
|
+
4. This enables efficient "chain execution" without calling TaskList
|
|
3605
|
+
</reasoning>
|
|
3606
|
+
</example>
|
|
3607
|
+
|
|
3608
|
+
<example>
|
|
3609
|
+
User: Start writing the tests
|
|
3610
|
+
|
|
3611
|
+
Assistant: I'll mark the test task as in progress.
|
|
3612
|
+
|
|
3613
|
+
TaskUpdate(taskId="5", status="in_progress")
|
|
3614
|
+
|
|
3615
|
+
<reasoning>
|
|
3616
|
+
The assistant used TaskUpdate because:
|
|
3617
|
+
1. User wants to start working on tests
|
|
3618
|
+
2. Simple status progression: pending \u2192 in_progress
|
|
3619
|
+
</reasoning>
|
|
3620
|
+
</example>
|
|
3621
|
+
|
|
3622
|
+
### Category B: Task Completion and Chain Execution
|
|
3623
|
+
|
|
3624
|
+
<example>
|
|
3625
|
+
User: The database design is complete
|
|
3626
|
+
|
|
3627
|
+
Assistant: Database design task is complete. Let me check what tasks are now ready.
|
|
3628
|
+
|
|
3629
|
+
TaskUpdate(taskId="1", status="completed")
|
|
3630
|
+
*Result shows unlockResult.readyNow: ["2", "3"]*
|
|
3631
|
+
|
|
3632
|
+
The users table and sessions table can now be done together. I'll continue with the users table.
|
|
3633
|
+
|
|
3634
|
+
TaskUpdate(taskId="2", status="in_progress")
|
|
3635
|
+
*Continuing with unblocked task without calling TaskList*
|
|
3636
|
+
|
|
3637
|
+
<reasoning>
|
|
3638
|
+
The assistant used TaskUpdate because:
|
|
3639
|
+
1. User reported completion of database design
|
|
3640
|
+
2. unlockResult.readyNow shows tasks 2 and 3 are now unblocked and can run in parallel
|
|
3641
|
+
3. Assistant immediately continues with task 2 - efficient chain execution
|
|
3642
|
+
4. No need to call TaskList to check status
|
|
3643
|
+
</reasoning>
|
|
3644
|
+
</example>
|
|
3645
|
+
|
|
3646
|
+
### Category C: Task Obsolescence or Cancellation
|
|
3647
|
+
|
|
3648
|
+
<example>
|
|
3649
|
+
User: This feature is no longer needed, let's skip it for now
|
|
3650
|
+
|
|
3651
|
+
Assistant: I'll mark this task as deleted.
|
|
3652
|
+
|
|
3653
|
+
TaskUpdate(taskId="3", status="deleted")
|
|
3654
|
+
|
|
3655
|
+
<reasoning>
|
|
3656
|
+
The assistant used TaskUpdate because:
|
|
3657
|
+
1. User said the feature is no longer needed
|
|
3658
|
+
2. "deleted" status removes it from active task flow
|
|
3659
|
+
3. This may unblock other tasks that were waiting on this one
|
|
3660
|
+
</reasoning>
|
|
3661
|
+
</example>
|
|
3662
|
+
|
|
3663
|
+
<example>
|
|
3664
|
+
User: Actually, we don't need the session table anymore. We're using JWT instead.
|
|
3665
|
+
|
|
3666
|
+
Assistant: I'll mark the session table task as deleted since we're switching to JWT.
|
|
3667
|
+
|
|
3668
|
+
TaskUpdate(taskId="3", status="deleted")
|
|
3669
|
+
|
|
3670
|
+
*If task 3 was blocking other tasks, they may now be unblocked*
|
|
3671
|
+
|
|
3672
|
+
<reasoning>
|
|
3673
|
+
The assistant used TaskUpdate because:
|
|
3674
|
+
1. User indicated a change in approach (JWT instead of sessions)
|
|
3675
|
+
2. The session table task is now obsolete
|
|
3676
|
+
3. Marking as deleted removes it from active work
|
|
3677
|
+
</reasoning>
|
|
3678
|
+
</example>
|
|
3679
|
+
|
|
3680
|
+
### Category D: Adding New Requirements During Execution
|
|
3681
|
+
|
|
3682
|
+
<example>
|
|
3683
|
+
User: The auth module also needs a password reset feature
|
|
3684
|
+
|
|
3685
|
+
Assistant: Adding password reset functionality. Let me create a new task and add it to the existing plan.
|
|
3686
|
+
|
|
3687
|
+
TaskCreate(subject="Implement password reset", activeForm="Implementing password reset")
|
|
3688
|
+
|
|
3689
|
+
*This new task may need to be linked to existing tasks:*
|
|
3690
|
+
TaskUpdate(taskId="7", addBlockedBy=["4"]) // password reset depends on API endpoints
|
|
3691
|
+
|
|
3692
|
+
Password reset feature added to task list, depends on API endpoints completion.
|
|
3693
|
+
|
|
3694
|
+
<reasoning>
|
|
3695
|
+
The assistant used TaskUpdate because:
|
|
3696
|
+
1. User added a new requirement during execution
|
|
3697
|
+
2. New task was created first
|
|
3698
|
+
3. Then dependency was added using TaskUpdate
|
|
3699
|
+
4. Password reset logically depends on the API endpoints being ready
|
|
3700
|
+
</reasoning>
|
|
3701
|
+
</example>
|
|
3702
|
+
|
|
3703
|
+
<example>
|
|
3704
|
+
User: We need to add rate limiting to the auth endpoints too
|
|
3705
|
+
|
|
3706
|
+
Assistant: I'll add a rate limiting task and link it appropriately.
|
|
3707
|
+
|
|
3708
|
+
TaskCreate(subject="Add rate limiting to auth endpoints", activeForm="Adding rate limiting")
|
|
3709
|
+
TaskUpdate(taskId="8", addBlockedBy=["4"]) // rate limiting depends on API
|
|
3710
|
+
|
|
3711
|
+
Rate limiting task added. It will start after the API endpoints are complete.
|
|
3712
|
+
|
|
3713
|
+
<reasoning>
|
|
3714
|
+
The assistant used TaskUpdate because:
|
|
3715
|
+
1. User added a new requirement
|
|
3716
|
+
2. Create task first, then add dependency
|
|
3717
|
+
3. Rate limiting applies to API endpoints, so it depends on task 4
|
|
3718
|
+
</reasoning>
|
|
3719
|
+
</example>
|
|
3720
|
+
|
|
3721
|
+
### Category E: Dependency Adjustment
|
|
3722
|
+
|
|
3723
|
+
<example>
|
|
3724
|
+
User: The users table doesn't need to wait for database design, we can do it at the same time
|
|
3725
|
+
|
|
3726
|
+
Assistant: I'll remove this dependency.
|
|
3727
|
+
|
|
3728
|
+
TaskUpdate(taskId="2", blockedBy=[])
|
|
3729
|
+
|
|
3730
|
+
The users table can now start immediately, no need to wait for database design.
|
|
3731
|
+
|
|
3732
|
+
<reasoning>
|
|
3733
|
+
The assistant used TaskUpdate because:
|
|
3734
|
+
1. User said the users table no longer needs to wait for database design
|
|
3735
|
+
2. Setting blockedBy=[] removes all blockers
|
|
3736
|
+
3. Task 2 is now ready to start immediately
|
|
3737
|
+
</reasoning>
|
|
3182
3738
|
</example>
|
|
3183
3739
|
|
|
3184
3740
|
<example>
|
|
3185
|
-
User:
|
|
3186
|
-
|
|
3187
|
-
|
|
3741
|
+
User: Tests should wait until all development tasks are complete
|
|
3742
|
+
|
|
3743
|
+
Assistant: I'll set the test task to wait for all development tasks.
|
|
3744
|
+
|
|
3745
|
+
TaskUpdate(taskId="5", addBlockedBy=["1", "2", "3", "4"])
|
|
3746
|
+
|
|
3747
|
+
The test task will now wait for tasks 1-4 to all complete before starting.
|
|
3748
|
+
|
|
3749
|
+
<reasoning>
|
|
3750
|
+
The assistant used TaskUpdate because:
|
|
3751
|
+
1. User specified that tests should wait for all development tasks
|
|
3752
|
+
2. addBlockedBy adds new dependencies without removing existing ones
|
|
3753
|
+
3. Task 5 will only be ready after all four development tasks complete
|
|
3754
|
+
</reasoning>
|
|
3188
3755
|
</example>
|
|
3189
3756
|
|
|
3190
3757
|
<example>
|
|
3191
|
-
User:
|
|
3192
|
-
|
|
3193
|
-
|
|
3758
|
+
User: The API doesn't need to wait for the sessions table anymore, just the users table
|
|
3759
|
+
|
|
3760
|
+
Assistant: I'll adjust the API's dependencies.
|
|
3761
|
+
|
|
3762
|
+
TaskUpdate(taskId="4", blockedBy=["2"]) // only keep users table dependency
|
|
3763
|
+
|
|
3764
|
+
The API now only needs to wait for the users table to complete.
|
|
3765
|
+
|
|
3766
|
+
<reasoning>
|
|
3767
|
+
The assistant used TaskUpdate because:
|
|
3768
|
+
1. User specified a change in dependencies
|
|
3769
|
+
2. Sessions table is no longer a blocker for API
|
|
3770
|
+
3. Setting the full blockedBy list replaces the previous one
|
|
3771
|
+
</reasoning>
|
|
3772
|
+
</example>
|
|
3773
|
+
|
|
3774
|
+
### Category F: Changing Execution Order
|
|
3775
|
+
|
|
3776
|
+
User wants to change the planned execution order.
|
|
3777
|
+
|
|
3778
|
+
<example>
|
|
3779
|
+
User: Wait, let's do the users table first, then the database
|
|
3780
|
+
|
|
3781
|
+
Assistant: I understand you want to change the execution order. Let me adjust the dependencies.
|
|
3782
|
+
|
|
3783
|
+
*Current state: users table (task 2) depends on database (task 1)*
|
|
3784
|
+
|
|
3785
|
+
TaskUpdate(taskId="2", blockedBy=[]) // users table no longer waits for database
|
|
3786
|
+
TaskUpdate(taskId="1", addBlockedBy=["2"]) // database now waits for users table
|
|
3787
|
+
|
|
3788
|
+
Order adjusted: users table first, then database. The users table can start immediately.
|
|
3789
|
+
|
|
3790
|
+
<reasoning>
|
|
3791
|
+
The assistant used TaskUpdate because:
|
|
3792
|
+
1. User requested a reversal of execution order
|
|
3793
|
+
2. First, remove the existing dependency from task 2
|
|
3794
|
+
3. Then, create a reverse dependency where database waits for users table
|
|
3795
|
+
4. Task 2 is now unblocked and ready to start immediately
|
|
3796
|
+
</reasoning>
|
|
3797
|
+
</example>
|
|
3798
|
+
|
|
3799
|
+
<example>
|
|
3800
|
+
User: Actually, let's do the users table and sessions table first, before the database design
|
|
3801
|
+
|
|
3802
|
+
Assistant: I'll reverse the dependency chain so both tables come before database design.
|
|
3803
|
+
|
|
3804
|
+
TaskUpdate(taskId="2", blockedBy=[]) // users table no longer blocked
|
|
3805
|
+
TaskUpdate(taskId="3", blockedBy=[]) // sessions table no longer blocked
|
|
3806
|
+
TaskUpdate(taskId="1", addBlockedBy=["2", "3"]) // database waits for both tables
|
|
3807
|
+
|
|
3808
|
+
Both tables can now start immediately. Database design will wait for both to complete.
|
|
3809
|
+
|
|
3810
|
+
<reasoning>
|
|
3811
|
+
The assistant used TaskUpdate because:
|
|
3812
|
+
1. User wanted to completely reverse the execution order
|
|
3813
|
+
2. Multiple dependencies needed to be cleared first
|
|
3814
|
+
3. Then reverse dependencies were added via addBlockedBy
|
|
3815
|
+
4. Tasks 2 and 3 are now unblocked and can run in parallel
|
|
3816
|
+
</reasoning>
|
|
3194
3817
|
</example>
|
|
3195
3818
|
`.trim();
|
|
3196
3819
|
|
|
@@ -3264,6 +3887,7 @@ var compareTaskId = (left, right) => {
|
|
|
3264
3887
|
return left.id.localeCompare(right.id);
|
|
3265
3888
|
};
|
|
3266
3889
|
var inputSchema11 = z12.strictObject({
|
|
3890
|
+
listId: z12.string().min(1).optional(),
|
|
3267
3891
|
taskId: z12.string().min(1),
|
|
3268
3892
|
subject: z12.string().optional(),
|
|
3269
3893
|
description: z12.string().optional(),
|
|
@@ -3308,8 +3932,8 @@ var TaskUpdateTool = {
|
|
|
3308
3932
|
return null;
|
|
3309
3933
|
},
|
|
3310
3934
|
async *call(input) {
|
|
3311
|
-
const { listId } = getTaskListPaths();
|
|
3312
|
-
const existing = getTask(input.taskId);
|
|
3935
|
+
const { listId } = getTaskListPaths(input.listId);
|
|
3936
|
+
const existing = getTask(input.taskId, { listId: input.listId });
|
|
3313
3937
|
if (!existing) {
|
|
3314
3938
|
yield {
|
|
3315
3939
|
type: "result",
|
|
@@ -3322,7 +3946,7 @@ var TaskUpdateTool = {
|
|
|
3322
3946
|
};
|
|
3323
3947
|
return;
|
|
3324
3948
|
}
|
|
3325
|
-
const tasks = listTasks();
|
|
3949
|
+
const tasks = listTasks({ listId: input.listId });
|
|
3326
3950
|
const subject = input.subject ?? existing.subject;
|
|
3327
3951
|
const mergedBlockedBy = mergeDeps(existing.blockedBy, input.addBlockedBy);
|
|
3328
3952
|
const mappedStatus = mapStatusInput(input.status);
|
|
@@ -3454,7 +4078,7 @@ var TaskUpdateTool = {
|
|
|
3454
4078
|
}
|
|
3455
4079
|
}
|
|
3456
4080
|
if (same) continue;
|
|
3457
|
-
updateTask(task.id, { blockedBy: merged });
|
|
4081
|
+
updateTask(task.id, { blockedBy: merged }, { listId: input.listId });
|
|
3458
4082
|
}
|
|
3459
4083
|
const result = updateTask(
|
|
3460
4084
|
input.taskId,
|
|
@@ -3465,23 +4089,30 @@ var TaskUpdateTool = {
|
|
|
3465
4089
|
status: mappedStatus,
|
|
3466
4090
|
metadata: metadataUpdate,
|
|
3467
4091
|
blockedBy: mergedBlockedBy
|
|
3468
|
-
}
|
|
4092
|
+
},
|
|
4093
|
+
{ listId: input.listId }
|
|
3469
4094
|
);
|
|
3470
4095
|
const didDepsChange = depsChanged(existing, result.task);
|
|
3471
|
-
|
|
4096
|
+
const updatedTimestamp = Date.now();
|
|
4097
|
+
const updatedPayload = {
|
|
3472
4098
|
listId,
|
|
3473
4099
|
taskId: result.task.id,
|
|
3474
4100
|
task: result.task,
|
|
3475
|
-
timestamp:
|
|
3476
|
-
}
|
|
4101
|
+
timestamp: updatedTimestamp
|
|
4102
|
+
};
|
|
4103
|
+
emitReminderEvent("task.updated", updatedPayload);
|
|
4104
|
+
emitReminderEvent("task.updated.v1", updatedPayload);
|
|
3477
4105
|
if (existing.status !== result.task.status) {
|
|
3478
|
-
|
|
4106
|
+
const statusTimestamp = Date.now();
|
|
4107
|
+
const statusPayload = {
|
|
3479
4108
|
listId,
|
|
3480
4109
|
taskId: result.task.id,
|
|
3481
4110
|
previousStatus: existing.status,
|
|
3482
4111
|
status: result.task.status,
|
|
3483
|
-
timestamp:
|
|
3484
|
-
}
|
|
4112
|
+
timestamp: statusTimestamp
|
|
4113
|
+
};
|
|
4114
|
+
emitReminderEvent("task.status_changed", statusPayload);
|
|
4115
|
+
emitReminderEvent("task.status_changed.v1", statusPayload);
|
|
3485
4116
|
}
|
|
3486
4117
|
if (didDepsChange) {
|
|
3487
4118
|
emitReminderEvent("task.deps_changed", {
|
|
@@ -3492,12 +4123,33 @@ var TaskUpdateTool = {
|
|
|
3492
4123
|
timestamp: Date.now()
|
|
3493
4124
|
});
|
|
3494
4125
|
}
|
|
4126
|
+
if (result.unlockResult) {
|
|
4127
|
+
emitReminderEvent("task.unblocked.v1", {
|
|
4128
|
+
listId,
|
|
4129
|
+
taskId: result.task.id,
|
|
4130
|
+
unblocked: result.unlockResult.unblocked.map((task) => task.id),
|
|
4131
|
+
readyNow: result.unlockResult.readyNow.map((task) => task.id),
|
|
4132
|
+
touchedTaskIds: result.unlockResult.unlockSummary.touchedTaskIds,
|
|
4133
|
+
timestamp: Date.now()
|
|
4134
|
+
});
|
|
4135
|
+
}
|
|
3495
4136
|
yield {
|
|
3496
4137
|
type: "result",
|
|
3497
4138
|
data: {
|
|
3498
4139
|
listId,
|
|
3499
4140
|
item: toTaskDetail(result.task),
|
|
3500
|
-
depsChanged: didDepsChange
|
|
4141
|
+
depsChanged: didDepsChange,
|
|
4142
|
+
unlockResult: result.unlockResult ? {
|
|
4143
|
+
unblocked: result.unlockResult.unblocked.map(toTaskDetail),
|
|
4144
|
+
partiallyUnblocked: result.unlockResult.partiallyUnblocked.map(
|
|
4145
|
+
(item) => ({
|
|
4146
|
+
task: toTaskDetail(item.task),
|
|
4147
|
+
remainingBlockers: item.remainingBlockers
|
|
4148
|
+
})
|
|
4149
|
+
),
|
|
4150
|
+
readyNow: result.unlockResult.readyNow.map(toTaskDetail),
|
|
4151
|
+
unlockSummary: result.unlockResult.unlockSummary
|
|
4152
|
+
} : void 0
|
|
3501
4153
|
}
|
|
3502
4154
|
};
|
|
3503
4155
|
} catch (error) {
|