@pixelbyte-software/pixcode 1.42.1 → 1.42.3
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/assets/{index-C97kIvXz.js → index-BnaWRV1a.js} +182 -182
- package/dist/index.html +1 -1
- package/dist-server/server/modules/orchestration/tasks/orchestration-task.service.js +86 -0
- package/dist-server/server/modules/orchestration/tasks/orchestration-task.service.js.map +1 -1
- package/dist-server/server/modules/orchestration/tasks/task-run-graph.js +158 -0
- package/dist-server/server/modules/orchestration/tasks/task-run-graph.js.map +1 -0
- package/dist-server/server/modules/orchestration/workflows/workflow-fallback-policy.js +114 -0
- package/dist-server/server/modules/orchestration/workflows/workflow-fallback-policy.js.map +1 -0
- package/dist-server/server/modules/orchestration/workflows/workflow-replay.js +177 -0
- package/dist-server/server/modules/orchestration/workflows/workflow-replay.js.map +1 -0
- package/dist-server/server/modules/orchestration/workflows/workflow-runner.js +53 -7
- package/dist-server/server/modules/orchestration/workflows/workflow-runner.js.map +1 -1
- package/dist-server/server/modules/orchestration/workflows/workflow-trace.js +74 -0
- package/dist-server/server/modules/orchestration/workflows/workflow-trace.js.map +1 -1
- package/dist-server/server/modules/orchestration/workflows/workflow.routes.js +88 -0
- package/dist-server/server/modules/orchestration/workflows/workflow.routes.js.map +1 -1
- package/dist-server/server/routes/taskmaster.js +93 -25
- package/dist-server/server/routes/taskmaster.js.map +1 -1
- package/package.json +1 -1
- package/scripts/smoke/taskmaster-run-graph.mjs +55 -0
- package/scripts/smoke/workflow-fallback-replay.mjs +56 -0
- package/server/modules/orchestration/tasks/orchestration-task.service.ts +94 -0
- package/server/modules/orchestration/tasks/orchestration-task.types.ts +10 -0
- package/server/modules/orchestration/tasks/task-run-graph.ts +219 -0
- package/server/modules/orchestration/workflows/workflow-fallback-policy.ts +161 -0
- package/server/modules/orchestration/workflows/workflow-replay.ts +254 -0
- package/server/modules/orchestration/workflows/workflow-runner.ts +112 -7
- package/server/modules/orchestration/workflows/workflow-trace.ts +76 -0
- package/server/modules/orchestration/workflows/workflow.routes.ts +107 -0
- package/server/modules/orchestration/workflows/workflow.types.ts +5 -0
- package/server/routes/taskmaster.js +90 -23
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { WorkflowContextPacket } from '@/modules/orchestration/workflows/context-packet.js';
|
|
2
|
+
import type { WorkflowFallbackTrigger } from '@/modules/orchestration/workflows/workflow-fallback-policy.js';
|
|
2
3
|
import type { WorkflowHandoffArtifact } from '@/modules/orchestration/workflows/handoff-artifact.js';
|
|
3
4
|
|
|
4
5
|
export type WorkflowRunStatus = 'queued' | 'running' | 'completed' | 'failed' | 'canceled';
|
|
@@ -21,6 +22,8 @@ export interface WorkflowNode {
|
|
|
21
22
|
isolation?: 'host' | 'worktree' | 'docker';
|
|
22
23
|
timeoutMs?: number;
|
|
23
24
|
internal?: boolean;
|
|
25
|
+
fallbackTrigger?: WorkflowFallbackTrigger;
|
|
26
|
+
fallbackSourceNodeId?: string;
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
export interface Workflow {
|
|
@@ -44,6 +47,8 @@ export interface WorkflowNodeRun {
|
|
|
44
47
|
timeoutMs?: number;
|
|
45
48
|
stage?: string;
|
|
46
49
|
internal?: boolean;
|
|
50
|
+
fallbackTrigger?: WorkflowFallbackTrigger;
|
|
51
|
+
fallbackSourceNodeId?: string;
|
|
47
52
|
status: WorkflowNodeStatus;
|
|
48
53
|
a2aTaskId?: string;
|
|
49
54
|
startedAt?: number;
|
|
@@ -16,6 +16,9 @@ import express from 'express';
|
|
|
16
16
|
import crossSpawn from 'cross-spawn';
|
|
17
17
|
|
|
18
18
|
import { orchestrationTaskService } from '@/modules/orchestration/tasks/orchestration-task.service.js';
|
|
19
|
+
import { buildTaskRunGraph } from '@/modules/orchestration/tasks/task-run-graph.js';
|
|
20
|
+
import { workflowRunner } from '@/modules/orchestration/workflows/workflow-runner.js';
|
|
21
|
+
import { workflowStore } from '@/modules/orchestration/workflows/workflow-store.js';
|
|
19
22
|
|
|
20
23
|
import { extractProjectDirectory } from '../projects.js';
|
|
21
24
|
import {
|
|
@@ -167,6 +170,21 @@ function taskMasterExecutionDescription(task) {
|
|
|
167
170
|
].filter(Boolean).join('\n\n');
|
|
168
171
|
}
|
|
169
172
|
|
|
173
|
+
function taskGraphForTask(projectId, task) {
|
|
174
|
+
return buildTaskRunGraph({
|
|
175
|
+
projectId,
|
|
176
|
+
taskmasterId: String(task.id),
|
|
177
|
+
taskmasterTask: task,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function attachTaskGraph(projectId, task) {
|
|
182
|
+
return {
|
|
183
|
+
...task,
|
|
184
|
+
taskGraph: taskGraphForTask(projectId, task),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
170
188
|
function buildTaskMasterQueueSummary(projectName, projectPath, tasks) {
|
|
171
189
|
const normalized = tasks.map((task) => ({
|
|
172
190
|
...task,
|
|
@@ -389,22 +407,26 @@ router.delete('/install/:jobId', async (req, res) => {
|
|
|
389
407
|
router.get('/tasks/:projectName', async (req, res) => {
|
|
390
408
|
try {
|
|
391
409
|
const { projectName } = req.params;
|
|
410
|
+
const projectId = typeof req.query.projectId === 'string' && req.query.projectId.trim()
|
|
411
|
+
? req.query.projectId.trim()
|
|
412
|
+
: projectName;
|
|
392
413
|
|
|
393
414
|
const { projectPath, transformedTasks, currentTag } = await readTaskMasterTasks(projectName);
|
|
415
|
+
const tasksWithGraph = transformedTasks.map((task) => attachTaskGraph(projectId, task));
|
|
394
416
|
|
|
395
417
|
res.json({
|
|
396
418
|
projectName,
|
|
397
419
|
projectPath,
|
|
398
|
-
tasks:
|
|
420
|
+
tasks: tasksWithGraph,
|
|
399
421
|
currentTag,
|
|
400
|
-
totalTasks:
|
|
422
|
+
totalTasks: tasksWithGraph.length,
|
|
401
423
|
tasksByStatus: {
|
|
402
|
-
pending:
|
|
403
|
-
'in-progress':
|
|
404
|
-
done:
|
|
405
|
-
review:
|
|
406
|
-
deferred:
|
|
407
|
-
cancelled:
|
|
424
|
+
pending: tasksWithGraph.filter(t => t.status === 'pending').length,
|
|
425
|
+
'in-progress': tasksWithGraph.filter(t => t.status === 'in-progress').length,
|
|
426
|
+
done: tasksWithGraph.filter(t => t.status === 'done').length,
|
|
427
|
+
review: tasksWithGraph.filter(t => t.status === 'review').length,
|
|
428
|
+
deferred: tasksWithGraph.filter(t => t.status === 'deferred').length,
|
|
429
|
+
cancelled: tasksWithGraph.filter(t => t.status === 'cancelled').length
|
|
408
430
|
},
|
|
409
431
|
timestamp: new Date().toISOString()
|
|
410
432
|
});
|
|
@@ -459,6 +481,9 @@ router.get('/queue/:projectName', async (req, res) => {
|
|
|
459
481
|
router.get('/task/:projectName/:taskId', async (req, res) => {
|
|
460
482
|
try {
|
|
461
483
|
const { projectName, taskId } = req.params;
|
|
484
|
+
const projectId = typeof req.query.projectId === 'string' && req.query.projectId.trim()
|
|
485
|
+
? req.query.projectId.trim()
|
|
486
|
+
: projectName;
|
|
462
487
|
const { projectPath, transformedTasks } = await readTaskMasterTasks(projectName);
|
|
463
488
|
const task = transformedTasks.find((candidate) => String(candidate.id) === String(taskId));
|
|
464
489
|
if (!task) {
|
|
@@ -472,7 +497,8 @@ router.get('/task/:projectName/:taskId', async (req, res) => {
|
|
|
472
497
|
success: true,
|
|
473
498
|
projectName,
|
|
474
499
|
projectPath,
|
|
475
|
-
task,
|
|
500
|
+
task: attachTaskGraph(projectId, task),
|
|
501
|
+
taskGraph: taskGraphForTask(projectId, task),
|
|
476
502
|
execution: {
|
|
477
503
|
supportsProvider: true,
|
|
478
504
|
supportsModel: true,
|
|
@@ -505,6 +531,7 @@ router.post('/execute/:projectName/:taskId', async (req, res) => {
|
|
|
505
531
|
: '';
|
|
506
532
|
const model = typeof req.body?.model === 'string' ? req.body.model : undefined;
|
|
507
533
|
const permissionMode = typeof req.body?.permissionMode === 'string' ? req.body.permissionMode : undefined;
|
|
534
|
+
const workflowId = typeof req.body?.workflowId === 'string' ? req.body.workflowId : undefined;
|
|
508
535
|
const fallbackProvider = typeof req.body?.fallbackProvider === 'string' ? req.body.fallbackProvider : undefined;
|
|
509
536
|
const workerSlot = Number.isInteger(req.body?.workerSlot) ? req.body.workerSlot : undefined;
|
|
510
537
|
const isolation = ['host', 'worktree', 'docker'].includes(req.body?.isolation)
|
|
@@ -544,15 +571,49 @@ router.post('/execute/:projectName/:taskId', async (req, res) => {
|
|
|
544
571
|
},
|
|
545
572
|
});
|
|
546
573
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
574
|
+
let dispatchedTask;
|
|
575
|
+
let workflowRun;
|
|
576
|
+
if (workflowId) {
|
|
577
|
+
const workflow = workflowStore.getWorkflow(workflowId);
|
|
578
|
+
if (!workflow) {
|
|
579
|
+
return res.status(404).json({
|
|
580
|
+
success: false,
|
|
581
|
+
error: 'Workflow not found',
|
|
582
|
+
message: `Workflow "${workflowId}" was not found`
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
workflowRun = workflowRunner.start(workflow, taskMasterExecutionDescription(task), {
|
|
586
|
+
projectId,
|
|
587
|
+
projectName,
|
|
588
|
+
projectPath,
|
|
589
|
+
selectedProjectPath: projectPath,
|
|
590
|
+
taskmasterId: String(task.id),
|
|
591
|
+
taskmasterTaskTitle: task.title,
|
|
592
|
+
orchestrationTaskId: orchestrationTask.id,
|
|
593
|
+
workflowName: workflow.name,
|
|
594
|
+
settings: {
|
|
595
|
+
isolation,
|
|
596
|
+
keepWorkspace: true,
|
|
597
|
+
baseRef: 'HEAD',
|
|
598
|
+
},
|
|
599
|
+
taskGraph: {
|
|
600
|
+
taskmasterId: String(task.id),
|
|
601
|
+
orchestrationTaskId: orchestrationTask.id,
|
|
602
|
+
source: 'taskmaster',
|
|
603
|
+
},
|
|
604
|
+
});
|
|
605
|
+
dispatchedTask = orchestrationTaskService.linkWorkflowRun(orchestrationTask.id, workflowRun) ?? orchestrationTask;
|
|
606
|
+
} else {
|
|
607
|
+
dispatchedTask = await orchestrationTaskService.dispatch(orchestrationTask.id, {
|
|
608
|
+
adapterId,
|
|
609
|
+
isolation,
|
|
610
|
+
projectPath,
|
|
611
|
+
model,
|
|
612
|
+
permissionMode,
|
|
613
|
+
fallbackProvider,
|
|
614
|
+
workerSlot,
|
|
615
|
+
});
|
|
616
|
+
}
|
|
556
617
|
|
|
557
618
|
res.json({
|
|
558
619
|
success: true,
|
|
@@ -565,8 +626,11 @@ router.post('/execute/:projectName/:taskId', async (req, res) => {
|
|
|
565
626
|
permissionMode,
|
|
566
627
|
fallbackProvider,
|
|
567
628
|
workerSlot,
|
|
629
|
+
workflowId,
|
|
568
630
|
},
|
|
569
|
-
task: dispatchedTask
|
|
631
|
+
task: dispatchedTask,
|
|
632
|
+
run: workflowRun,
|
|
633
|
+
taskGraph: taskGraphForTask(projectId, task),
|
|
570
634
|
});
|
|
571
635
|
} catch (error) {
|
|
572
636
|
console.error('TaskMaster execute error:', error);
|
|
@@ -591,14 +655,17 @@ router.post('/sync-orchestration/:projectName', async (req, res) => {
|
|
|
591
655
|
? req.body.projectId.trim()
|
|
592
656
|
: projectName;
|
|
593
657
|
|
|
594
|
-
const syncedTasks = transformedTasks.map((task) =>
|
|
595
|
-
|
|
658
|
+
const syncedTasks = transformedTasks.map((task) => {
|
|
659
|
+
const taskGraph = taskGraphForTask(projectId, task);
|
|
660
|
+
return orchestrationTaskService.upsertFromTaskMaster({
|
|
596
661
|
projectId,
|
|
597
662
|
taskmasterId: String(task.id),
|
|
598
663
|
title: task.title,
|
|
599
664
|
description: task.description,
|
|
600
|
-
|
|
601
|
-
|
|
665
|
+
acceptanceCriteria: taskGraph.acceptanceCriteria,
|
|
666
|
+
changedFiles: taskGraph.changedFiles,
|
|
667
|
+
});
|
|
668
|
+
});
|
|
602
669
|
|
|
603
670
|
res.json({
|
|
604
671
|
success: true,
|