Merge pull request #937 from abeperl/feat/fn-024-add-dependencies-to-task-update
feat: Add optional dependencies parameter to fn_task_update tool
This commit is contained in:
5
.changeset/fn-024-add-dependencies-parameter.md
Normal file
5
.changeset/fn-024-add-dependencies-parameter.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@fusion/engine": minor
|
||||
---
|
||||
|
||||
Add optional dependencies parameter to fn_task_update tool. Executors can now programmatically modify task dependency arrays during execution with `fn_task_update({ id: "FN-XXX", dependencies: ["FN-001", "FN-002"] })`. The parameter is optional and backward-compatible; omitting it preserves existing dependencies. Includes validation for self-dependency and non-existent task IDs. Eliminates the need for direct task.json editing workarounds.
|
||||
@@ -637,6 +637,9 @@ const taskUpdateParams = Type.Object({
|
||||
STEP_STATUSES.map((s) => Type.Literal(s)),
|
||||
{ description: "New status: pending, in-progress, done, or skipped" },
|
||||
),
|
||||
dependencies: Type.Optional(Type.Array(Type.String(), {
|
||||
description: "Optional task dependency array. Replaces existing dependencies. Pass ['FN-001', 'FN-002'] to set dependencies. Pass [] to clear all dependencies. Omit parameter to preserve existing dependencies.",
|
||||
})),
|
||||
});
|
||||
|
||||
// taskLogParams and taskCreateParams are imported from agent-tools.ts
|
||||
@@ -5487,10 +5490,11 @@ export class TaskExecutor {
|
||||
description:
|
||||
"Update a step's status. Call before starting a step (in-progress), " +
|
||||
"after completing it (done), or to skip it (skipped). " +
|
||||
"Optionally update task dependencies by passing a dependencies array. " +
|
||||
"The board updates in real-time.",
|
||||
parameters: taskUpdateParams,
|
||||
execute: async (_id: string, params: Static<typeof taskUpdateParams>) => {
|
||||
const { step, status } = params;
|
||||
const { step, status, dependencies } = params;
|
||||
|
||||
// Record step progress for stuck task detection.
|
||||
// Step transitions (in-progress, done, skipped) indicate real progress
|
||||
@@ -5545,6 +5549,43 @@ export class TaskExecutor {
|
||||
};
|
||||
}
|
||||
|
||||
// Handle dependencies parameter if provided
|
||||
if (dependencies !== undefined) {
|
||||
// Validate: prevent self-dependency
|
||||
if (dependencies.includes(taskId)) {
|
||||
return {
|
||||
content: [{
|
||||
type: "text" as const,
|
||||
text: `Cannot add self-dependency: ${taskId} cannot depend on itself.`,
|
||||
}],
|
||||
details: {},
|
||||
};
|
||||
}
|
||||
|
||||
// Validate: all dependency task IDs must exist
|
||||
const invalidIds: string[] = [];
|
||||
for (const depId of dependencies) {
|
||||
try {
|
||||
await store.getTask(depId);
|
||||
} catch {
|
||||
invalidIds.push(depId);
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidIds.length > 0) {
|
||||
return {
|
||||
content: [{
|
||||
type: "text" as const,
|
||||
text: `Cannot set dependencies — the following task(s) do not exist: ${invalidIds.join(", ")}`,
|
||||
}],
|
||||
details: {},
|
||||
};
|
||||
}
|
||||
|
||||
// Update dependencies
|
||||
await store.updateTask(taskId, { dependencies });
|
||||
}
|
||||
|
||||
const task = await store.updateStep(taskId, stepIndex, status as StepStatus);
|
||||
const stepInfo = task.steps[stepIndex];
|
||||
if (!stepInfo) {
|
||||
|
||||
Reference in New Issue
Block a user