@kendoo.agentdesk/agentdesk 0.10.5 → 0.11.1
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/bin/agentdesk.mjs +20 -6
- package/cli/orchestrator.mjs +2 -2
- package/cli/prompt.mjs +55 -1
- package/cli/team.mjs +4 -0
- package/package.json +1 -1
package/bin/agentdesk.mjs
CHANGED
|
@@ -71,6 +71,7 @@ if (!command || command === "help" || command === "--help") {
|
|
|
71
71
|
Options:
|
|
72
72
|
--description, -d Task description or requirements
|
|
73
73
|
--cwd Working directory (defaults to current)
|
|
74
|
+
--child-strategy How to handle child tasks: "inline" (default) or "branch"
|
|
74
75
|
|
|
75
76
|
|
|
76
77
|
How it works:
|
|
@@ -101,6 +102,7 @@ if (AGENT_NAMES.includes(command?.toLowerCase())) {
|
|
|
101
102
|
let description = "";
|
|
102
103
|
let cwd = process.cwd();
|
|
103
104
|
let taskId = null;
|
|
105
|
+
let childStrategy = null;
|
|
104
106
|
const remaining = args.slice(1);
|
|
105
107
|
|
|
106
108
|
for (let i = 0; i < remaining.length; i++) {
|
|
@@ -108,6 +110,8 @@ if (AGENT_NAMES.includes(command?.toLowerCase())) {
|
|
|
108
110
|
description = remaining[++i];
|
|
109
111
|
} else if (remaining[i] === "--cwd" && remaining[i + 1]) {
|
|
110
112
|
cwd = remaining[++i];
|
|
113
|
+
} else if (remaining[i] === "--child-strategy" && remaining[i + 1]) {
|
|
114
|
+
childStrategy = remaining[++i];
|
|
111
115
|
} else if (!taskId && !remaining[i].startsWith("-")) {
|
|
112
116
|
taskId = remaining[i];
|
|
113
117
|
}
|
|
@@ -120,7 +124,7 @@ if (AGENT_NAMES.includes(command?.toLowerCase())) {
|
|
|
120
124
|
}
|
|
121
125
|
|
|
122
126
|
const { runTeam } = await import("../cli/team.mjs");
|
|
123
|
-
const code = await runTeam(taskId, { description, cwd, soloAgent: command.charAt(0).toUpperCase() + command.slice(1).toLowerCase() });
|
|
127
|
+
const code = await runTeam(taskId, { description, cwd, soloAgent: command.charAt(0).toUpperCase() + command.slice(1).toLowerCase(), childStrategy });
|
|
124
128
|
process.exit(code);
|
|
125
129
|
}
|
|
126
130
|
|
|
@@ -140,10 +144,11 @@ else if (command === "init") {
|
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
else if (command === "team") {
|
|
143
|
-
// Parse options first to find -d, --cwd, --
|
|
147
|
+
// Parse options first to find -d, --cwd, --child-strategy
|
|
144
148
|
let description = "";
|
|
145
149
|
let cwd = process.cwd();
|
|
146
150
|
let taskId = null;
|
|
151
|
+
let childStrategy = null;
|
|
147
152
|
const remaining = args.slice(1);
|
|
148
153
|
|
|
149
154
|
for (let i = 0; i < remaining.length; i++) {
|
|
@@ -151,6 +156,8 @@ else if (command === "team") {
|
|
|
151
156
|
description = remaining[++i];
|
|
152
157
|
} else if (remaining[i] === "--cwd" && remaining[i + 1]) {
|
|
153
158
|
cwd = remaining[++i];
|
|
159
|
+
} else if (remaining[i] === "--child-strategy" && remaining[i + 1]) {
|
|
160
|
+
childStrategy = remaining[++i];
|
|
154
161
|
} else if (!taskId && !remaining[i].startsWith("-")) {
|
|
155
162
|
taskId = remaining[i];
|
|
156
163
|
}
|
|
@@ -163,7 +170,7 @@ else if (command === "team") {
|
|
|
163
170
|
}
|
|
164
171
|
|
|
165
172
|
const { runTeam } = await import("../cli/team.mjs");
|
|
166
|
-
const code = await runTeam(taskId, { description, cwd });
|
|
173
|
+
const code = await runTeam(taskId, { description, cwd, childStrategy });
|
|
167
174
|
process.exit(code);
|
|
168
175
|
}
|
|
169
176
|
|
|
@@ -174,10 +181,17 @@ else if (command === "daemon") {
|
|
|
174
181
|
|
|
175
182
|
else if (command === "update") {
|
|
176
183
|
const { execSync } = await import("child_process");
|
|
177
|
-
|
|
184
|
+
const currentVersion = pkg.version;
|
|
185
|
+
console.log(`\n Current version: ${currentVersion}`);
|
|
178
186
|
try {
|
|
179
|
-
execSync(`npm
|
|
180
|
-
|
|
187
|
+
const latest = execSync(`npm view ${pkg.name} version`, { encoding: "utf-8" }).trim();
|
|
188
|
+
if (latest === currentVersion) {
|
|
189
|
+
console.log(` Already up to date.\n`);
|
|
190
|
+
} else {
|
|
191
|
+
console.log(` Updating to ${latest}...\n`);
|
|
192
|
+
execSync(`npm i -g ${pkg.name}@latest`, { stdio: "inherit" });
|
|
193
|
+
console.log(`\n Updated: ${currentVersion} → ${latest}\n`);
|
|
194
|
+
}
|
|
181
195
|
} catch {
|
|
182
196
|
console.error(`\n Update failed. Try manually: npm i -g ${pkg.name}@latest\n`);
|
|
183
197
|
process.exit(1);
|
package/cli/orchestrator.mjs
CHANGED
|
@@ -47,7 +47,7 @@ function timestamp() {
|
|
|
47
47
|
export async function runOrchestrator({
|
|
48
48
|
taskId, taskLink, description, createTask, tracker, config,
|
|
49
49
|
project, team, teamSections, inboxUrl, sessionUrl, cwd,
|
|
50
|
-
onEvent, apiKey, serverUrl, soloAgent,
|
|
50
|
+
onEvent, apiKey, serverUrl, soloAgent, childStrategy,
|
|
51
51
|
}) {
|
|
52
52
|
const trackerCreds = await fetchTrackerCredentials(project?.name, apiKey, serverUrl);
|
|
53
53
|
const env = { ...process.env, ...loadDotEnv(cwd), ...trackerCreds };
|
|
@@ -64,7 +64,7 @@ export async function runOrchestrator({
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
const fullPrompt = soloAgent
|
|
67
|
-
? buildSoloPrompt({ agentName: soloAgent, taskId, description, tracker, config, project, sessionUrl })
|
|
67
|
+
? buildSoloPrompt({ agentName: soloAgent, taskId, description, tracker, config, project, sessionUrl, childStrategy })
|
|
68
68
|
: buildPrompt({ taskId, taskLink, description, createTask, tracker, config, project, teamSections, inboxUrl, sessionUrl });
|
|
69
69
|
|
|
70
70
|
emit({
|
package/cli/prompt.mjs
CHANGED
|
@@ -102,7 +102,7 @@ export function buildPrompt({ taskId, taskLink, description, createTask, tracker
|
|
|
102
102
|
return `${prompt}\n\n---\n\n## PROJECT CONTEXT\n\n${context}\n\n${timeInfo}`;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
export function buildSoloPrompt({ agentName, taskId, description, tracker, config, project, sessionUrl }) {
|
|
105
|
+
export function buildSoloPrompt({ agentName, taskId, description, tracker, config, project, sessionUrl, childStrategy }) {
|
|
106
106
|
const agent = BUILT_IN_AGENTS[agentName];
|
|
107
107
|
if (!agent) throw new Error(`Unknown agent: ${agentName}`);
|
|
108
108
|
|
|
@@ -244,6 +244,60 @@ export function buildSoloPrompt({ agentName, taskId, description, tracker, confi
|
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
+
// Child task handling — when the task has subtasks/child items
|
|
248
|
+
if (tracker) {
|
|
249
|
+
const strategy = childStrategy || "inline";
|
|
250
|
+
lines.push(
|
|
251
|
+
`## Handling parent tasks with child items`,
|
|
252
|
+
``,
|
|
253
|
+
`After fetching the task, check if it has child items / subtasks. If it does, work on all child items that are marked "To Do" (or equivalent open status).`,
|
|
254
|
+
``,
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
if (strategy === "branch") {
|
|
258
|
+
lines.push(
|
|
259
|
+
`**Strategy: one branch per child item**`,
|
|
260
|
+
``,
|
|
261
|
+
`1. Create a parent feature branch from main: \`feat/<parent-task-id>\``,
|
|
262
|
+
`2. For each child item marked "To Do" (sequentially):`,
|
|
263
|
+
` a. Pull/rebase the parent branch to include any prior child merges`,
|
|
264
|
+
` b. Create a child branch from the parent: \`feat/<parent-task-id>/<child-task-id>\``,
|
|
265
|
+
` c. Do the work, commit`,
|
|
266
|
+
` d. Push the child branch and open a PR **targeting the parent branch** (not main)`,
|
|
267
|
+
` e. Post the PR link as a comment on the child task`,
|
|
268
|
+
` f. Update the child task status to "In Review"`,
|
|
269
|
+
` g. Switch back to the parent branch before starting the next child`,
|
|
270
|
+
`3. After all children are done, post a summary on the parent task listing all child PRs`,
|
|
271
|
+
``,
|
|
272
|
+
`Each child PR can be reviewed and merged to the parent branch independently.`,
|
|
273
|
+
`When all children are merged, the parent branch can be merged to main.`,
|
|
274
|
+
``,
|
|
275
|
+
);
|
|
276
|
+
} else {
|
|
277
|
+
lines.push(
|
|
278
|
+
`**Strategy: all changes on parent branch (inline)**`,
|
|
279
|
+
``,
|
|
280
|
+
`1. Create a feature branch from main: \`feat/<parent-task-id>\``,
|
|
281
|
+
`2. For each child item marked "To Do" (sequentially):`,
|
|
282
|
+
` a. Do the work on the parent branch`,
|
|
283
|
+
` b. Commit with a message referencing the child task ID`,
|
|
284
|
+
` c. Post a comment on the child task describing what was done`,
|
|
285
|
+
` d. Update the child task status to "Done"`,
|
|
286
|
+
`3. Push the branch and open a single PR targeting main`,
|
|
287
|
+
`4. Post the PR link on the parent task`,
|
|
288
|
+
`5. Post a summary on the parent task listing all completed children`,
|
|
289
|
+
``,
|
|
290
|
+
`This keeps everything in one branch — no conflicts, one PR to review.`,
|
|
291
|
+
``,
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
lines.push(
|
|
296
|
+
`If the task has no child items, just work on it normally as a single task.`,
|
|
297
|
+
``,
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
247
301
|
// Add custom instructions
|
|
248
302
|
if (config?.instructions) {
|
|
249
303
|
lines.push(`## Additional Instructions`, ``, config.instructions, ``);
|
package/cli/team.mjs
CHANGED
|
@@ -90,6 +90,9 @@ export async function runTeam(taskId, opts = {}) {
|
|
|
90
90
|
if (opts.soloAgent) {
|
|
91
91
|
console.log(`Agent: ${opts.soloAgent} (solo mode)`);
|
|
92
92
|
}
|
|
93
|
+
if (opts.childStrategy) {
|
|
94
|
+
console.log(`Child strategy: ${opts.childStrategy}`);
|
|
95
|
+
}
|
|
93
96
|
|
|
94
97
|
// Resolve team and generate dynamic prompt sections
|
|
95
98
|
const team = resolveTeam(config);
|
|
@@ -211,6 +214,7 @@ export async function runTeam(taskId, opts = {}) {
|
|
|
211
214
|
apiKey,
|
|
212
215
|
serverUrl: agentdeskServer,
|
|
213
216
|
soloAgent: opts.soloAgent || null,
|
|
217
|
+
childStrategy: opts.childStrategy || null,
|
|
214
218
|
});
|
|
215
219
|
|
|
216
220
|
clearInterval(heartbeatInterval);
|