@synergenius/flow-weaver-pack-weaver 0.9.159 → 0.9.164
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/ai-chat-provider.d.ts.map +1 -1
- package/dist/ai-chat-provider.js +17 -11
- package/dist/ai-chat-provider.js.map +1 -1
- package/dist/bot/ai-router.js +5 -5
- package/dist/bot/ai-router.js.map +1 -1
- package/dist/bot/assistant-tools.d.ts.map +1 -1
- package/dist/bot/assistant-tools.js +6 -7
- package/dist/bot/assistant-tools.js.map +1 -1
- package/dist/bot/capability-registry.d.ts.map +1 -1
- package/dist/bot/capability-registry.js +37 -14
- package/dist/bot/capability-registry.js.map +1 -1
- package/dist/bot/dashboard.js +1 -1
- package/dist/bot/dashboard.js.map +1 -1
- package/dist/bot/index.d.ts +1 -1
- package/dist/bot/index.d.ts.map +1 -1
- package/dist/bot/index.js.map +1 -1
- package/dist/bot/instance-manager.js +3 -3
- package/dist/bot/instance-manager.js.map +1 -1
- package/dist/bot/profile-store.d.ts.map +1 -1
- package/dist/bot/profile-store.js +11 -9
- package/dist/bot/profile-store.js.map +1 -1
- package/dist/bot/profile-types.d.ts +2 -2
- package/dist/bot/profile-types.d.ts.map +1 -1
- package/dist/bot/runner.d.ts +1 -0
- package/dist/bot/runner.d.ts.map +1 -1
- package/dist/bot/runner.js +6 -2
- package/dist/bot/runner.js.map +1 -1
- package/dist/bot/step-executor.d.ts.map +1 -1
- package/dist/bot/step-executor.js +10 -0
- package/dist/bot/step-executor.js.map +1 -1
- package/dist/bot/swarm-controller.d.ts +3 -5
- package/dist/bot/swarm-controller.d.ts.map +1 -1
- package/dist/bot/swarm-controller.js +157 -74
- package/dist/bot/swarm-controller.js.map +1 -1
- package/dist/bot/task-prompt-builder.d.ts +2 -3
- package/dist/bot/task-prompt-builder.d.ts.map +1 -1
- package/dist/bot/task-prompt-builder.js +81 -67
- package/dist/bot/task-prompt-builder.js.map +1 -1
- package/dist/bot/task-store.d.ts +3 -3
- package/dist/bot/task-store.d.ts.map +1 -1
- package/dist/bot/task-store.js +89 -75
- package/dist/bot/task-store.js.map +1 -1
- package/dist/bot/task-types.d.ts +54 -26
- package/dist/bot/task-types.d.ts.map +1 -1
- package/dist/bot/task-types.js +6 -2
- package/dist/bot/task-types.js.map +1 -1
- package/dist/bot/types.d.ts +2 -0
- package/dist/bot/types.d.ts.map +1 -1
- package/dist/bot/weaver-tools.d.ts.map +1 -1
- package/dist/bot/weaver-tools.js +10 -0
- package/dist/bot/weaver-tools.js.map +1 -1
- package/dist/cli-handlers.d.ts +0 -1
- package/dist/cli-handlers.d.ts.map +1 -1
- package/dist/cli-handlers.js +5 -9
- package/dist/cli-handlers.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/node-types/agent-execute.d.ts.map +1 -1
- package/dist/node-types/agent-execute.js +95 -63
- package/dist/node-types/agent-execute.js.map +1 -1
- package/dist/node-types/plan-task.js +8 -8
- package/dist/node-types/plan-task.js.map +1 -1
- package/dist/ui/bot-panel.js +1 -1
- package/dist/ui/capability-editor.js +37 -14
- package/dist/ui/chat-task-result.js +1 -7
- package/dist/ui/profile-editor.js +37 -14
- package/dist/ui/swarm-controls.js +2 -2
- package/dist/ui/swarm-dashboard.js +72 -109
- package/dist/ui/task-detail-view.js +21 -42
- package/dist/ui/task-editor.js +13 -50
- package/dist/ui/task-pool-list.js +0 -2
- package/flowweaver.manifest.json +1 -1
- package/package.json +1 -1
- package/src/ai-chat-provider.ts +15 -11
- package/src/bot/ai-router.ts +5 -5
- package/src/bot/assistant-tools.ts +6 -7
- package/src/bot/capability-registry.ts +37 -14
- package/src/bot/dashboard.ts +1 -1
- package/src/bot/index.ts +5 -1
- package/src/bot/instance-manager.ts +3 -3
- package/src/bot/profile-store.ts +12 -10
- package/src/bot/profile-types.ts +2 -2
- package/src/bot/runner.ts +6 -2
- package/src/bot/step-executor.ts +11 -0
- package/src/bot/swarm-controller.ts +164 -78
- package/src/bot/task-prompt-builder.ts +86 -71
- package/src/bot/task-store.ts +101 -78
- package/src/bot/task-types.ts +81 -36
- package/src/bot/types.ts +2 -0
- package/src/bot/weaver-tools.ts +11 -0
- package/src/cli-handlers.ts +5 -9
- package/src/index.ts +6 -0
- package/src/node-types/agent-execute.ts +99 -62
- package/src/node-types/plan-task.ts +8 -8
- package/src/ui/bot-panel.tsx +3 -3
- package/src/ui/chat-task-result.tsx +5 -14
- package/src/ui/swarm-controls.tsx +3 -3
- package/src/ui/swarm-dashboard.tsx +3 -3
- package/src/ui/task-detail-view.tsx +29 -52
- package/src/ui/task-editor.tsx +14 -51
- package/src/ui/task-pool-list.tsx +1 -3
|
@@ -206,10 +206,10 @@ function SwarmControls({ swarmStatus, onRefresh }) {
|
|
|
206
206
|
variant: "caption-regular",
|
|
207
207
|
color: "color-text-subtle"
|
|
208
208
|
}, `${swarmStatus.tasksCompleted} done`),
|
|
209
|
-
swarmStatus && swarmStatus.
|
|
209
|
+
swarmStatus && swarmStatus.runsIncomplete > 0 && React.createElement(Typography, {
|
|
210
210
|
variant: "caption-regular",
|
|
211
211
|
color: "color-status-negative"
|
|
212
|
-
}, `${swarmStatus.
|
|
212
|
+
}, `${swarmStatus.runsIncomplete} incomplete`)
|
|
213
213
|
),
|
|
214
214
|
// Right: action buttons
|
|
215
215
|
React.createElement(
|
|
@@ -404,10 +404,8 @@ var { useState: useState2 } = React4;
|
|
|
404
404
|
var { Flex: Flex4, Typography: Typography4, Icon: Icon2, StatusIcon: StatusIcon2, Chip, ScrollArea, Badge, EmptyState } = require("@fw/plugin-ui-kit");
|
|
405
405
|
var statusToIcon = {
|
|
406
406
|
"open": "pending",
|
|
407
|
-
"pending": "pending",
|
|
408
407
|
"in-progress": "running",
|
|
409
408
|
"done": "completed",
|
|
410
|
-
"blocked": "pending",
|
|
411
409
|
"cancelled": "failed"
|
|
412
410
|
};
|
|
413
411
|
var rowBaseStyle = {
|
|
@@ -855,18 +853,14 @@ var {
|
|
|
855
853
|
} = require("@fw/plugin-ui-kit");
|
|
856
854
|
var statusToIcon2 = {
|
|
857
855
|
"open": "pending",
|
|
858
|
-
"pending": "pending",
|
|
859
856
|
"in-progress": "running",
|
|
860
857
|
"done": "completed",
|
|
861
|
-
"blocked": "pending",
|
|
862
858
|
"cancelled": "failed"
|
|
863
859
|
};
|
|
864
860
|
var statusToLabel2 = {
|
|
865
861
|
"open": "Open",
|
|
866
|
-
"pending": "Queued",
|
|
867
862
|
"in-progress": "Running",
|
|
868
863
|
"done": "Done",
|
|
869
|
-
"blocked": "Blocked",
|
|
870
864
|
"cancelled": "Cancelled"
|
|
871
865
|
};
|
|
872
866
|
var headerStyle = {
|
|
@@ -921,11 +915,7 @@ function SubtaskRowItem({ sub, onBack }) {
|
|
|
921
915
|
label: sub.assignedProfile,
|
|
922
916
|
size: "small",
|
|
923
917
|
color: "color-status-info"
|
|
924
|
-
})
|
|
925
|
-
React6.createElement(Typography5, {
|
|
926
|
-
variant: "caption-regular",
|
|
927
|
-
color: "color-text-subtle"
|
|
928
|
-
}, `#${sub.attempt}`)
|
|
918
|
+
})
|
|
929
919
|
);
|
|
930
920
|
}
|
|
931
921
|
function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
@@ -944,7 +934,7 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
944
934
|
const t = data.task ?? data;
|
|
945
935
|
setTask(t);
|
|
946
936
|
const rs = t.context;
|
|
947
|
-
const summaries = rs?.
|
|
937
|
+
const summaries = rs?.runHistory;
|
|
948
938
|
if (summaries?.length) {
|
|
949
939
|
setHistory((prev) => {
|
|
950
940
|
if (prev.length > 0) return prev;
|
|
@@ -1013,13 +1003,13 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
1013
1003
|
awaitingApproval,
|
|
1014
1004
|
report: liveReport
|
|
1015
1005
|
} = useStreamTimeline(stream.events, stream.isDone);
|
|
1016
|
-
const
|
|
1017
|
-
const isLive = task?.status === "in-progress" && !!
|
|
1006
|
+
const activeRunId = task?.activeRunId;
|
|
1007
|
+
const isLive = task?.status === "in-progress" && !!activeRunId;
|
|
1018
1008
|
useEffect2(() => {
|
|
1019
|
-
if (!isLive || !
|
|
1020
|
-
stream.start(packId, "fw_weaver_events",
|
|
1009
|
+
if (!isLive || !activeRunId) return;
|
|
1010
|
+
stream.start(packId, "fw_weaver_events", activeRunId);
|
|
1021
1011
|
return () => stream.stop();
|
|
1022
|
-
}, [isLive,
|
|
1012
|
+
}, [isLive, activeRunId, packId]);
|
|
1023
1013
|
const [detailTab, setDetailTab] = useState4("runs");
|
|
1024
1014
|
const [actionLoading, setActionLoading] = useState4(null);
|
|
1025
1015
|
const [availableProfiles, setAvailableProfiles] = useState4([]);
|
|
@@ -1274,7 +1264,7 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
1274
1264
|
React6.createElement(Chip2, {
|
|
1275
1265
|
label: statusToLabel2[task.status] || task.status || "open",
|
|
1276
1266
|
size: "small",
|
|
1277
|
-
color: task.status === "done" ? "color-status-positive" : task.status === "cancelled" ? "color-status-negative" : task.status === "in-progress" ? "color-status-info" :
|
|
1267
|
+
color: task.status === "done" ? "color-status-positive" : task.status === "cancelled" ? "color-status-negative" : task.status === "in-progress" ? "color-status-info" : "color-brand-alt"
|
|
1278
1268
|
}),
|
|
1279
1269
|
task.assignedProfile && React6.createElement(Chip2, { key: `profile-${task.assignedProfile}`, label: task.assignedProfile, size: "small", color: "color-status-info" }),
|
|
1280
1270
|
task.priority > 0 && React6.createElement(Chip2, {
|
|
@@ -1282,10 +1272,10 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
1282
1272
|
size: "small",
|
|
1283
1273
|
color: task.priority >= 3 ? "color-status-caution" : "color-status-info"
|
|
1284
1274
|
}),
|
|
1285
|
-
task.
|
|
1275
|
+
(task.context?.runHistory?.length ?? 0) > 0 && React6.createElement(Typography5, {
|
|
1286
1276
|
variant: "smallCaption-regular",
|
|
1287
1277
|
color: "color-text-subtle"
|
|
1288
|
-
}, `${task.
|
|
1278
|
+
}, `${task.context.runHistory.length} run${task.context.runHistory.length !== 1 ? "s" : ""}`)
|
|
1289
1279
|
),
|
|
1290
1280
|
// Description
|
|
1291
1281
|
task.description && React6.createElement(Typography5, {
|
|
@@ -1327,7 +1317,7 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
1327
1317
|
Flex5,
|
|
1328
1318
|
{ variant: "column-stretch-start-nowrap-8", style: { padding: "12px 16px" } },
|
|
1329
1319
|
// ── Runs tab ──
|
|
1330
|
-
detailTab === "runs" && (hasRuns || (task.
|
|
1320
|
+
detailTab === "runs" && (hasRuns || (task.context?.runHistory?.length ?? 0) > 0) ? React6.createElement(
|
|
1331
1321
|
Flex5,
|
|
1332
1322
|
{ variant: "column-stretch-start-nowrap-8" },
|
|
1333
1323
|
...runItems.map(({ run, runTimeline }) => {
|
|
@@ -1400,7 +1390,7 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
1400
1390
|
React6.createElement(
|
|
1401
1391
|
Flex5,
|
|
1402
1392
|
{ variant: "row-center-start-nowrap-6" },
|
|
1403
|
-
task.status === "open" && (task.
|
|
1393
|
+
task.status === "open" && (task.context?.runHistory?.length ?? 0) > 0 && React6.createElement(Button2, {
|
|
1404
1394
|
size: "xs",
|
|
1405
1395
|
variant: "fill",
|
|
1406
1396
|
color: "primary",
|
|
@@ -1408,7 +1398,7 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
1408
1398
|
loading: actionLoading === "retry",
|
|
1409
1399
|
disabled: !!actionLoading
|
|
1410
1400
|
}, "Retry Task"),
|
|
1411
|
-
(task.status === "open" || task.status === "
|
|
1401
|
+
(task.status === "open" || task.status === "in-progress") && React6.createElement(Button2, {
|
|
1412
1402
|
size: "xs",
|
|
1413
1403
|
variant: "outlined",
|
|
1414
1404
|
color: "danger",
|
|
@@ -1547,27 +1537,14 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
1547
1537
|
style: { whiteSpace: "pre-wrap" }
|
|
1548
1538
|
}, task.context.notes)
|
|
1549
1539
|
),
|
|
1550
|
-
//
|
|
1551
|
-
task.context?.
|
|
1552
|
-
Flex5,
|
|
1553
|
-
{
|
|
1554
|
-
variant: "column-stretch-start-nowrap-4"
|
|
1555
|
-
},
|
|
1556
|
-
React6.createElement(Typography5, { variant: "caption-thick", color: "color-status-negative" }, "Last Error"),
|
|
1557
|
-
React6.createElement(Typography5, {
|
|
1558
|
-
variant: "smallCaption-regular",
|
|
1559
|
-
color: "color-text-high",
|
|
1560
|
-
style: { fontFamily: "var(--font-mono, monospace)", whiteSpace: "pre-wrap" }
|
|
1561
|
-
}, task.context.lastError)
|
|
1562
|
-
),
|
|
1563
|
-
// Run summaries (accumulated context)
|
|
1564
|
-
(task.context?.runSummaries?.length ?? 0) > 0 && React6.createElement(
|
|
1540
|
+
// Run history (accumulated context)
|
|
1541
|
+
(task.context?.runHistory?.length ?? 0) > 0 && React6.createElement(
|
|
1565
1542
|
Flex5,
|
|
1566
1543
|
{
|
|
1567
1544
|
variant: "column-stretch-start-nowrap-6"
|
|
1568
1545
|
},
|
|
1569
|
-
React6.createElement(Typography5, { variant: "caption-thick", color: "color-text-medium" }, "Run
|
|
1570
|
-
...(task.context?.
|
|
1546
|
+
React6.createElement(Typography5, { variant: "caption-thick", color: "color-text-medium" }, "Run History"),
|
|
1547
|
+
...(task.context?.runHistory ?? []).map(
|
|
1571
1548
|
(rs, i) => React6.createElement(
|
|
1572
1549
|
Card,
|
|
1573
1550
|
{
|
|
@@ -1597,10 +1574,10 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
1597
1574
|
color: "color-text-subtle",
|
|
1598
1575
|
style: { fontFamily: "var(--font-mono, monospace)" }
|
|
1599
1576
|
}, `Files: ${rs.filesModified.join(", ")}`),
|
|
1600
|
-
rs.
|
|
1577
|
+
rs.remainingWork && React6.createElement(Typography5, {
|
|
1601
1578
|
variant: "smallCaption-regular",
|
|
1602
|
-
color: "color-status-
|
|
1603
|
-
}, `
|
|
1579
|
+
color: "color-status-caution"
|
|
1580
|
+
}, `Remaining: ${rs.remainingWork}`)
|
|
1604
1581
|
)
|
|
1605
1582
|
)
|
|
1606
1583
|
),
|
|
@@ -1617,7 +1594,7 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
1617
1594
|
React6.createElement(
|
|
1618
1595
|
Typography5,
|
|
1619
1596
|
{ variant: "smallCaption-regular", color: "color-text-high" },
|
|
1620
|
-
`Tokens: ${task.tokensUsed?.toLocaleString() ?? 0}
|
|
1597
|
+
`Tokens: ${task.tokensUsed?.toLocaleString() ?? 0}`
|
|
1621
1598
|
),
|
|
1622
1599
|
React6.createElement(
|
|
1623
1600
|
Typography5,
|
|
@@ -1664,9 +1641,7 @@ var COMPLEXITY_OPTIONS = [
|
|
|
1664
1641
|
];
|
|
1665
1642
|
var STATUS_COLOR = {
|
|
1666
1643
|
"open": "color-brand-alt",
|
|
1667
|
-
"pending": "color-brand-alt",
|
|
1668
1644
|
"in-progress": "color-status-info",
|
|
1669
|
-
"blocked": "color-status-caution",
|
|
1670
1645
|
"done": "color-status-positive",
|
|
1671
1646
|
"cancelled": "color-status-negative"
|
|
1672
1647
|
};
|
|
@@ -1678,8 +1653,6 @@ function TaskEditor({ mode, taskId, onSave, onCancel, onDelete }) {
|
|
|
1678
1653
|
const [priority, setPriority] = useState5("0");
|
|
1679
1654
|
const [complexity, setComplexity] = useState5("");
|
|
1680
1655
|
const [assignedProfile, setAssignedProfile] = useState5("");
|
|
1681
|
-
const [maxAttempts, setMaxAttempts] = useState5("3");
|
|
1682
|
-
const [budgetTokens, setBudgetTokens] = useState5("");
|
|
1683
1656
|
const [budgetCost, setBudgetCost] = useState5("");
|
|
1684
1657
|
const [notes, setNotes] = useState5("");
|
|
1685
1658
|
const [files, setFiles] = useState5([]);
|
|
@@ -1736,8 +1709,6 @@ function TaskEditor({ mode, taskId, onSave, onCancel, onDelete }) {
|
|
|
1736
1709
|
setPriority(String(t.priority ?? 0));
|
|
1737
1710
|
setComplexity(t.complexity || "");
|
|
1738
1711
|
setAssignedProfile(t.assignedProfile || "");
|
|
1739
|
-
setMaxAttempts(String(t.maxAttempts ?? 3));
|
|
1740
|
-
setBudgetTokens(t.budgetTokens != null ? String(t.budgetTokens) : "");
|
|
1741
1712
|
setBudgetCost(t.budgetCost != null ? String(t.budgetCost) : "");
|
|
1742
1713
|
setNotes(t.context?.notes || "");
|
|
1743
1714
|
setFiles(t.context?.files || []);
|
|
@@ -1755,11 +1726,11 @@ function TaskEditor({ mode, taskId, onSave, onCancel, onDelete }) {
|
|
|
1755
1726
|
}, [mode, taskId, callTool]);
|
|
1756
1727
|
const isDirty = useCallback3(() => {
|
|
1757
1728
|
if (mode === "create") {
|
|
1758
|
-
return !!(title.trim() || description.trim() || notes.trim() || files.length > 0 || dependsOn.length > 0 || priority !== "0" || complexity || assignedProfile ||
|
|
1729
|
+
return !!(title.trim() || description.trim() || notes.trim() || files.length > 0 || dependsOn.length > 0 || priority !== "0" || complexity || assignedProfile || budgetCost);
|
|
1759
1730
|
}
|
|
1760
1731
|
if (!taskData) return false;
|
|
1761
|
-
return title.trim() !== (taskData.title || "") || description.trim() !== (taskData.description || "") || notes.trim() !== (taskData.context?.notes || "") || JSON.stringify(files) !== JSON.stringify(taskData.context?.files || []) || priority !== String(taskData.priority ?? 0) || complexity !== (taskData.complexity || "") || assignedProfile !== (taskData.assignedProfile || "") ||
|
|
1762
|
-
}, [mode, title, description, notes, files, dependsOn, priority, complexity, assignedProfile,
|
|
1732
|
+
return title.trim() !== (taskData.title || "") || description.trim() !== (taskData.description || "") || notes.trim() !== (taskData.context?.notes || "") || JSON.stringify(files) !== JSON.stringify(taskData.context?.files || []) || priority !== String(taskData.priority ?? 0) || complexity !== (taskData.complexity || "") || assignedProfile !== (taskData.assignedProfile || "") || budgetCost !== (taskData.budgetCost != null ? String(taskData.budgetCost) : "");
|
|
1733
|
+
}, [mode, title, description, notes, files, dependsOn, priority, complexity, assignedProfile, budgetCost, taskData]);
|
|
1763
1734
|
const handleBack = useCallback3(async () => {
|
|
1764
1735
|
if (isDirty()) {
|
|
1765
1736
|
const ok = await ctx.confirm("Discard unsaved changes?", {
|
|
@@ -1798,12 +1769,10 @@ function TaskEditor({ mode, taskId, onSave, onCancel, onDelete }) {
|
|
|
1798
1769
|
const args = {
|
|
1799
1770
|
title: title.trim(),
|
|
1800
1771
|
description: description.trim(),
|
|
1801
|
-
priority: parseInt(priority, 10) || 0
|
|
1802
|
-
maxAttempts: parseInt(maxAttempts, 10) || 3
|
|
1772
|
+
priority: parseInt(priority, 10) || 0
|
|
1803
1773
|
};
|
|
1804
1774
|
if (complexity) args.complexity = complexity;
|
|
1805
1775
|
if (assignedProfile) args.assignedProfile = assignedProfile;
|
|
1806
|
-
if (budgetTokens) args.budgetTokens = parseInt(budgetTokens, 10);
|
|
1807
1776
|
if (budgetCost) args.budgetCost = parseFloat(budgetCost);
|
|
1808
1777
|
if (dependsOn.length > 0) args.dependsOn = dependsOn;
|
|
1809
1778
|
const result = await callTool("fw_weaver_task_create", args);
|
|
@@ -1815,7 +1784,8 @@ function TaskEditor({ mode, taskId, onSave, onCancel, onDelete }) {
|
|
|
1815
1784
|
context: {
|
|
1816
1785
|
notes: notes.trim(),
|
|
1817
1786
|
files,
|
|
1818
|
-
|
|
1787
|
+
runHistory: [],
|
|
1788
|
+
stagnationCount: 0
|
|
1819
1789
|
}
|
|
1820
1790
|
});
|
|
1821
1791
|
}
|
|
@@ -1826,15 +1796,9 @@ function TaskEditor({ mode, taskId, onSave, onCancel, onDelete }) {
|
|
|
1826
1796
|
title: title.trim(),
|
|
1827
1797
|
description: description.trim(),
|
|
1828
1798
|
priority: parseInt(priority, 10) || 0,
|
|
1829
|
-
maxAttempts: parseInt(maxAttempts, 10) || 3,
|
|
1830
1799
|
complexity: complexity || void 0,
|
|
1831
1800
|
assignedProfile: assignedProfile || null
|
|
1832
1801
|
};
|
|
1833
|
-
if (budgetTokens) {
|
|
1834
|
-
patch.budgetTokens = parseInt(budgetTokens, 10);
|
|
1835
|
-
} else {
|
|
1836
|
-
patch.budgetTokens = void 0;
|
|
1837
|
-
}
|
|
1838
1802
|
if (budgetCost) {
|
|
1839
1803
|
patch.budgetCost = parseFloat(budgetCost);
|
|
1840
1804
|
} else {
|
|
@@ -1843,8 +1807,8 @@ function TaskEditor({ mode, taskId, onSave, onCancel, onDelete }) {
|
|
|
1843
1807
|
patch.context = {
|
|
1844
1808
|
files,
|
|
1845
1809
|
notes: notes.trim(),
|
|
1846
|
-
|
|
1847
|
-
|
|
1810
|
+
runHistory: taskData?.context?.runHistory || [],
|
|
1811
|
+
stagnationCount: taskData?.context?.stagnationCount ?? 0
|
|
1848
1812
|
};
|
|
1849
1813
|
await callTool("fw_weaver_task_update", patch);
|
|
1850
1814
|
toast3("Task updated", { type: "success" });
|
|
@@ -1853,7 +1817,7 @@ function TaskEditor({ mode, taskId, onSave, onCancel, onDelete }) {
|
|
|
1853
1817
|
} catch (err) {
|
|
1854
1818
|
toast3(err instanceof Error ? err.message : `Failed to ${mode} task`, { type: "error" });
|
|
1855
1819
|
}
|
|
1856
|
-
}, [mode, taskId, title, description, priority, complexity, assignedProfile,
|
|
1820
|
+
}, [mode, taskId, title, description, priority, complexity, assignedProfile, budgetCost, notes, files, dependsOn, taskData, callTool, onSave]);
|
|
1857
1821
|
const handleDelete = useCallback3(async () => {
|
|
1858
1822
|
if (!taskId) return;
|
|
1859
1823
|
const ok = await ctx.confirm("Are you sure you want to cancel this task?", {
|
|
@@ -2007,30 +1971,6 @@ function TaskEditor({ mode, taskId, onSave, onCancel, onDelete }) {
|
|
|
2007
1971
|
defaultBoxStyle: { flex: 1, minWidth: 0 }
|
|
2008
1972
|
})
|
|
2009
1973
|
),
|
|
2010
|
-
// -- Max Attempts --
|
|
2011
|
-
React7.createElement(
|
|
2012
|
-
Field,
|
|
2013
|
-
{ label: "Max Attempts" },
|
|
2014
|
-
React7.createElement(Input, {
|
|
2015
|
-
type: "number",
|
|
2016
|
-
size: "small",
|
|
2017
|
-
placeholder: "3",
|
|
2018
|
-
value: maxAttempts,
|
|
2019
|
-
onChange: (v) => setMaxAttempts(v)
|
|
2020
|
-
})
|
|
2021
|
-
),
|
|
2022
|
-
// -- Budget Tokens --
|
|
2023
|
-
React7.createElement(
|
|
2024
|
-
Field,
|
|
2025
|
-
{ label: "Budget Tokens" },
|
|
2026
|
-
React7.createElement(Input, {
|
|
2027
|
-
type: "number",
|
|
2028
|
-
size: "small",
|
|
2029
|
-
placeholder: "Optional token limit",
|
|
2030
|
-
value: budgetTokens,
|
|
2031
|
-
onChange: (v) => setBudgetTokens(v)
|
|
2032
|
-
})
|
|
2033
|
-
),
|
|
2034
1974
|
// -- Budget Cost --
|
|
2035
1975
|
React7.createElement(
|
|
2036
1976
|
Field,
|
|
@@ -2228,14 +2168,14 @@ function TaskEditor({ mode, taskId, onSave, onCancel, onDelete }) {
|
|
|
2228
2168
|
`$${(taskData.costUsed ?? 0).toFixed(3)}`
|
|
2229
2169
|
)
|
|
2230
2170
|
),
|
|
2231
|
-
taskData.context?.
|
|
2171
|
+
taskData.context?.runHistory?.slice(-1)?.[0]?.remainingWork && React7.createElement(
|
|
2232
2172
|
Field,
|
|
2233
|
-
{ label: "
|
|
2173
|
+
{ label: "Remaining work", align: "start" },
|
|
2234
2174
|
React7.createElement(Typography6, {
|
|
2235
2175
|
variant: "smallCaption-regular",
|
|
2236
|
-
color: "color-status-
|
|
2176
|
+
color: "color-status-caution",
|
|
2237
2177
|
style: { fontFamily: "var(--font-mono, monospace)", whiteSpace: "pre-wrap" }
|
|
2238
|
-
}, taskData.context.
|
|
2178
|
+
}, taskData.context.runHistory.slice(-1)[0]?.remainingWork)
|
|
2239
2179
|
)
|
|
2240
2180
|
)
|
|
2241
2181
|
),
|
|
@@ -2798,23 +2738,46 @@ Each subtask: focused (one concern), self-contained, properly routed, ordered by
|
|
|
2798
2738
|
After implementation tasks, create a verification task (ops profile) that runs \`tsc --noEmit\`.
|
|
2799
2739
|
This catches compilation errors before tests run, saving time and token spend.
|
|
2800
2740
|
|
|
2801
|
-
###
|
|
2802
|
-
Your LAST subtask MUST be a "
|
|
2741
|
+
### Review & Steer (Convergence Loop)
|
|
2742
|
+
Your LAST subtask MUST be a "Review & Steer" task assigned to yourself (orchestrator):
|
|
2803
2743
|
- dependsOn: ALL other subtasks
|
|
2804
|
-
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2744
|
+
- acceptance: include the objective's acceptance criteria
|
|
2745
|
+
|
|
2746
|
+
When this task runs, you are in STEERING MODE. Read your context carefully:
|
|
2747
|
+
- Sibling tasks show their status, acceptance check results, and stagnation counts
|
|
2748
|
+
- Your job is to decide: are we done, or do we need more work?
|
|
2749
|
+
|
|
2750
|
+
STEERING DECISIONS:
|
|
2751
|
+
1. ALL DONE: Every subtask has passing acceptance checks \u2192 call done
|
|
2752
|
+
2. PROGRESS: Tasks are open with recent changes \u2192 create another "Review & Steer" depending on open tasks, call done
|
|
2753
|
+
3. STAGNANT (stagnationCount >= 3): A task keeps failing the same way \u2192 INTERVENE:
|
|
2754
|
+
- REASSIGN: Change the task description to suggest a different profile ("This might need ops help")
|
|
2755
|
+
- REDEFINE: Create a new task with smaller scope or different approach, cancel the stuck one
|
|
2756
|
+
- DROP: Cancel a non-essential task that's blocking progress
|
|
2757
|
+
4. FIX: Acceptance checks failing with specific errors \u2192 create targeted fix tasks
|
|
2758
|
+
|
|
2759
|
+
After creating fix tasks, ALWAYS create another "Review & Steer" task depending on those fixes.
|
|
2760
|
+
This creates the convergence loop: decompose \u2192 execute \u2192 review \u2192 fix \u2192 review \u2192 done.
|
|
2761
|
+
|
|
2762
|
+
### Existing Subtasks (Retries)
|
|
2763
|
+
If your context shows "Parent Context" with existing sibling tasks, those are subtasks from a previous run. Do NOT create duplicates. Check what exists and only create MISSING tasks. If all subtasks already exist and look correct, just call done.
|
|
2764
|
+
|
|
2765
|
+
### Acceptance Criteria (Shell Scripts)
|
|
2766
|
+
Every task MUST have acceptance.checks \u2014 an array of shell commands that verify "done".
|
|
2767
|
+
Each command must exit 0 to pass. The system runs them AUTOMATICALLY after each completed run.
|
|
2768
|
+
If any check fails, the task stays open for another run.
|
|
2808
2769
|
|
|
2809
|
-
|
|
2810
|
-
|
|
2770
|
+
Write commands relative to the workspace root. Examples:
|
|
2771
|
+
- File exists: test -f url-shortener/src/server.ts
|
|
2772
|
+
- Compiles: cd url-shortener && npx tsc --noEmit
|
|
2773
|
+
- Tests pass: cd url-shortener && npx vitest run
|
|
2774
|
+
- Export exists: grep -r "export.*startServer" url-shortener/src/
|
|
2775
|
+
- No console.log: ! grep -r "console.log" url-shortener/src/
|
|
2811
2776
|
|
|
2812
2777
|
### Example
|
|
2813
|
-
{ operation: "task_create", args: { title: "Design: Create project contract", parentId: "@self", assignedProfile: "developer",
|
|
2814
|
-
{ operation: "task_create", args: { title: "
|
|
2815
|
-
{ operation: "task_create", args: { title: "
|
|
2816
|
-
{ operation: "task_create", args: { title: "Implement HTTP server", parentId: "@self", assignedProfile: "developer", dependsOn: ["Implement storage module"], description: "You may ONLY create: src/server.ts" } }
|
|
2817
|
-
{ operation: "task_create", args: { title: "Verify & Iterate", parentId: "@self", assignedProfile: "orchestrator", dependsOn: ["Implement HTTP server"], description: "Review all task results. If issues found, create fix tasks. If all good, signal done." } }`
|
|
2778
|
+
{ operation: "task_create", args: { title: "Design: Create project contract", parentId: "@self", assignedProfile: "developer", description: "Create .design.md", acceptance: { checks: [{ name: "design exists", command: "test -f url-shortener/.design.md" }] }, dependsOn: [] } }
|
|
2779
|
+
{ operation: "task_create", args: { title: "Implement storage", parentId: "@self", assignedProfile: "developer", dependsOn: ["Design: Create project contract"], description: "You may ONLY create: src/types.ts, src/storage.ts", acceptance: { checks: [{ name: "files exist", command: "test -f url-shortener/src/types.ts && test -f url-shortener/src/storage.ts" }, { name: "compiles", command: "cd url-shortener && npx tsc --noEmit" }] } } }
|
|
2780
|
+
{ operation: "task_create", args: { title: "Review & Steer", parentId: "@self", assignedProfile: "orchestrator", dependsOn: ["Implement storage"], description: "Review subtask results. If all acceptance checks pass, signal done. If issues, create fix tasks + another Review & Steer." } }`
|
|
2818
2781
|
};
|
|
2819
2782
|
var CAP_ROLE_DEVELOPER = {
|
|
2820
2783
|
name: "role-developer",
|
|
@@ -349,18 +349,14 @@ var {
|
|
|
349
349
|
} = require("@fw/plugin-ui-kit");
|
|
350
350
|
var statusToIcon = {
|
|
351
351
|
"open": "pending",
|
|
352
|
-
"pending": "pending",
|
|
353
352
|
"in-progress": "running",
|
|
354
353
|
"done": "completed",
|
|
355
|
-
"blocked": "pending",
|
|
356
354
|
"cancelled": "failed"
|
|
357
355
|
};
|
|
358
356
|
var statusToLabel = {
|
|
359
357
|
"open": "Open",
|
|
360
|
-
"pending": "Queued",
|
|
361
358
|
"in-progress": "Running",
|
|
362
359
|
"done": "Done",
|
|
363
|
-
"blocked": "Blocked",
|
|
364
360
|
"cancelled": "Cancelled"
|
|
365
361
|
};
|
|
366
362
|
var headerStyle = {
|
|
@@ -415,11 +411,7 @@ function SubtaskRowItem({ sub, onBack }) {
|
|
|
415
411
|
label: sub.assignedProfile,
|
|
416
412
|
size: "small",
|
|
417
413
|
color: "color-status-info"
|
|
418
|
-
})
|
|
419
|
-
React2.createElement(Typography, {
|
|
420
|
-
variant: "caption-regular",
|
|
421
|
-
color: "color-text-subtle"
|
|
422
|
-
}, `#${sub.attempt}`)
|
|
414
|
+
})
|
|
423
415
|
);
|
|
424
416
|
}
|
|
425
417
|
function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
@@ -438,7 +430,7 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
438
430
|
const t = data.task ?? data;
|
|
439
431
|
setTask(t);
|
|
440
432
|
const rs = t.context;
|
|
441
|
-
const summaries = rs?.
|
|
433
|
+
const summaries = rs?.runHistory;
|
|
442
434
|
if (summaries?.length) {
|
|
443
435
|
setHistory((prev) => {
|
|
444
436
|
if (prev.length > 0) return prev;
|
|
@@ -507,13 +499,13 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
507
499
|
awaitingApproval,
|
|
508
500
|
report: liveReport
|
|
509
501
|
} = useStreamTimeline(stream.events, stream.isDone);
|
|
510
|
-
const
|
|
511
|
-
const isLive = task?.status === "in-progress" && !!
|
|
502
|
+
const activeRunId = task?.activeRunId;
|
|
503
|
+
const isLive = task?.status === "in-progress" && !!activeRunId;
|
|
512
504
|
useEffect2(() => {
|
|
513
|
-
if (!isLive || !
|
|
514
|
-
stream.start(packId, "fw_weaver_events",
|
|
505
|
+
if (!isLive || !activeRunId) return;
|
|
506
|
+
stream.start(packId, "fw_weaver_events", activeRunId);
|
|
515
507
|
return () => stream.stop();
|
|
516
|
-
}, [isLive,
|
|
508
|
+
}, [isLive, activeRunId, packId]);
|
|
517
509
|
const [detailTab, setDetailTab] = useState2("runs");
|
|
518
510
|
const [actionLoading, setActionLoading] = useState2(null);
|
|
519
511
|
const [availableProfiles, setAvailableProfiles] = useState2([]);
|
|
@@ -768,7 +760,7 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
768
760
|
React2.createElement(Chip, {
|
|
769
761
|
label: statusToLabel[task.status] || task.status || "open",
|
|
770
762
|
size: "small",
|
|
771
|
-
color: task.status === "done" ? "color-status-positive" : task.status === "cancelled" ? "color-status-negative" : task.status === "in-progress" ? "color-status-info" :
|
|
763
|
+
color: task.status === "done" ? "color-status-positive" : task.status === "cancelled" ? "color-status-negative" : task.status === "in-progress" ? "color-status-info" : "color-brand-alt"
|
|
772
764
|
}),
|
|
773
765
|
task.assignedProfile && React2.createElement(Chip, { key: `profile-${task.assignedProfile}`, label: task.assignedProfile, size: "small", color: "color-status-info" }),
|
|
774
766
|
task.priority > 0 && React2.createElement(Chip, {
|
|
@@ -776,10 +768,10 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
776
768
|
size: "small",
|
|
777
769
|
color: task.priority >= 3 ? "color-status-caution" : "color-status-info"
|
|
778
770
|
}),
|
|
779
|
-
task.
|
|
771
|
+
(task.context?.runHistory?.length ?? 0) > 0 && React2.createElement(Typography, {
|
|
780
772
|
variant: "smallCaption-regular",
|
|
781
773
|
color: "color-text-subtle"
|
|
782
|
-
}, `${task.
|
|
774
|
+
}, `${task.context.runHistory.length} run${task.context.runHistory.length !== 1 ? "s" : ""}`)
|
|
783
775
|
),
|
|
784
776
|
// Description
|
|
785
777
|
task.description && React2.createElement(Typography, {
|
|
@@ -821,7 +813,7 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
821
813
|
Flex,
|
|
822
814
|
{ variant: "column-stretch-start-nowrap-8", style: { padding: "12px 16px" } },
|
|
823
815
|
// ── Runs tab ──
|
|
824
|
-
detailTab === "runs" && (hasRuns || (task.
|
|
816
|
+
detailTab === "runs" && (hasRuns || (task.context?.runHistory?.length ?? 0) > 0) ? React2.createElement(
|
|
825
817
|
Flex,
|
|
826
818
|
{ variant: "column-stretch-start-nowrap-8" },
|
|
827
819
|
...runItems.map(({ run, runTimeline }) => {
|
|
@@ -894,7 +886,7 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
894
886
|
React2.createElement(
|
|
895
887
|
Flex,
|
|
896
888
|
{ variant: "row-center-start-nowrap-6" },
|
|
897
|
-
task.status === "open" && (task.
|
|
889
|
+
task.status === "open" && (task.context?.runHistory?.length ?? 0) > 0 && React2.createElement(Button, {
|
|
898
890
|
size: "xs",
|
|
899
891
|
variant: "fill",
|
|
900
892
|
color: "primary",
|
|
@@ -902,7 +894,7 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
902
894
|
loading: actionLoading === "retry",
|
|
903
895
|
disabled: !!actionLoading
|
|
904
896
|
}, "Retry Task"),
|
|
905
|
-
(task.status === "open" || task.status === "
|
|
897
|
+
(task.status === "open" || task.status === "in-progress") && React2.createElement(Button, {
|
|
906
898
|
size: "xs",
|
|
907
899
|
variant: "outlined",
|
|
908
900
|
color: "danger",
|
|
@@ -1041,27 +1033,14 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
1041
1033
|
style: { whiteSpace: "pre-wrap" }
|
|
1042
1034
|
}, task.context.notes)
|
|
1043
1035
|
),
|
|
1044
|
-
//
|
|
1045
|
-
task.context?.
|
|
1046
|
-
Flex,
|
|
1047
|
-
{
|
|
1048
|
-
variant: "column-stretch-start-nowrap-4"
|
|
1049
|
-
},
|
|
1050
|
-
React2.createElement(Typography, { variant: "caption-thick", color: "color-status-negative" }, "Last Error"),
|
|
1051
|
-
React2.createElement(Typography, {
|
|
1052
|
-
variant: "smallCaption-regular",
|
|
1053
|
-
color: "color-text-high",
|
|
1054
|
-
style: { fontFamily: "var(--font-mono, monospace)", whiteSpace: "pre-wrap" }
|
|
1055
|
-
}, task.context.lastError)
|
|
1056
|
-
),
|
|
1057
|
-
// Run summaries (accumulated context)
|
|
1058
|
-
(task.context?.runSummaries?.length ?? 0) > 0 && React2.createElement(
|
|
1036
|
+
// Run history (accumulated context)
|
|
1037
|
+
(task.context?.runHistory?.length ?? 0) > 0 && React2.createElement(
|
|
1059
1038
|
Flex,
|
|
1060
1039
|
{
|
|
1061
1040
|
variant: "column-stretch-start-nowrap-6"
|
|
1062
1041
|
},
|
|
1063
|
-
React2.createElement(Typography, { variant: "caption-thick", color: "color-text-medium" }, "Run
|
|
1064
|
-
...(task.context?.
|
|
1042
|
+
React2.createElement(Typography, { variant: "caption-thick", color: "color-text-medium" }, "Run History"),
|
|
1043
|
+
...(task.context?.runHistory ?? []).map(
|
|
1065
1044
|
(rs, i) => React2.createElement(
|
|
1066
1045
|
Card,
|
|
1067
1046
|
{
|
|
@@ -1091,10 +1070,10 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
1091
1070
|
color: "color-text-subtle",
|
|
1092
1071
|
style: { fontFamily: "var(--font-mono, monospace)" }
|
|
1093
1072
|
}, `Files: ${rs.filesModified.join(", ")}`),
|
|
1094
|
-
rs.
|
|
1073
|
+
rs.remainingWork && React2.createElement(Typography, {
|
|
1095
1074
|
variant: "smallCaption-regular",
|
|
1096
|
-
color: "color-status-
|
|
1097
|
-
}, `
|
|
1075
|
+
color: "color-status-caution"
|
|
1076
|
+
}, `Remaining: ${rs.remainingWork}`)
|
|
1098
1077
|
)
|
|
1099
1078
|
)
|
|
1100
1079
|
),
|
|
@@ -1111,7 +1090,7 @@ function TaskDetailView({ taskId, onBack, onEdit }) {
|
|
|
1111
1090
|
React2.createElement(
|
|
1112
1091
|
Typography,
|
|
1113
1092
|
{ variant: "smallCaption-regular", color: "color-text-high" },
|
|
1114
|
-
`Tokens: ${task.tokensUsed?.toLocaleString() ?? 0}
|
|
1093
|
+
`Tokens: ${task.tokensUsed?.toLocaleString() ?? 0}`
|
|
1115
1094
|
),
|
|
1116
1095
|
React2.createElement(
|
|
1117
1096
|
Typography,
|