@synergenius/flow-weaver-pack-weaver 0.9.62 → 0.9.78
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 +12 -0
- package/dist/ai-chat-provider.d.ts.map +1 -1
- package/dist/ai-chat-provider.js +173 -19
- package/dist/ai-chat-provider.js.map +1 -1
- package/dist/bot/agent-loop.d.ts +20 -0
- package/dist/bot/agent-loop.d.ts.map +1 -0
- package/dist/bot/agent-loop.js +331 -0
- package/dist/bot/agent-loop.js.map +1 -0
- package/dist/bot/ai-router.d.ts +19 -0
- package/dist/bot/ai-router.d.ts.map +1 -0
- package/dist/bot/ai-router.js +104 -0
- package/dist/bot/ai-router.js.map +1 -0
- package/dist/bot/bot-registry.js +2 -2
- package/dist/bot/bot-registry.js.map +1 -1
- package/dist/bot/conversation-store.d.ts +1 -0
- package/dist/bot/conversation-store.d.ts.map +1 -1
- package/dist/bot/conversation-store.js.map +1 -1
- package/dist/bot/improve-loop.js.map +1 -1
- package/dist/bot/instance-manager.d.ts +31 -0
- package/dist/bot/instance-manager.d.ts.map +1 -0
- package/dist/bot/instance-manager.js +115 -0
- package/dist/bot/instance-manager.js.map +1 -0
- package/dist/bot/orchestrator.d.ts +36 -0
- package/dist/bot/orchestrator.d.ts.map +1 -0
- package/dist/bot/orchestrator.js +176 -0
- package/dist/bot/orchestrator.js.map +1 -0
- package/dist/bot/profile-store.d.ts +36 -0
- package/dist/bot/profile-store.d.ts.map +1 -0
- package/dist/bot/profile-store.js +208 -0
- package/dist/bot/profile-store.js.map +1 -0
- package/dist/bot/profile-types.d.ts +126 -0
- package/dist/bot/profile-types.d.ts.map +1 -0
- package/dist/bot/profile-types.js +7 -0
- package/dist/bot/profile-types.js.map +1 -0
- package/dist/bot/session-state.d.ts +25 -0
- package/dist/bot/session-state.d.ts.map +1 -0
- package/dist/bot/session-state.js +110 -0
- package/dist/bot/session-state.js.map +1 -0
- package/dist/bot/swarm-controller.d.ts +37 -21
- package/dist/bot/swarm-controller.d.ts.map +1 -1
- package/dist/bot/swarm-controller.js +344 -163
- package/dist/bot/swarm-controller.js.map +1 -1
- package/dist/bot/task-prompt-builder.d.ts +2 -1
- package/dist/bot/task-prompt-builder.d.ts.map +1 -1
- package/dist/bot/task-prompt-builder.js +33 -10
- package/dist/bot/task-prompt-builder.js.map +1 -1
- package/dist/bot/task-queue.d.ts +46 -0
- package/dist/bot/task-queue.d.ts.map +1 -0
- package/dist/bot/task-queue.js +237 -0
- package/dist/bot/task-queue.js.map +1 -0
- package/dist/bot/task-store.d.ts +1 -6
- package/dist/bot/task-store.d.ts.map +1 -1
- package/dist/bot/task-store.js +27 -78
- package/dist/bot/task-store.js.map +1 -1
- package/dist/bot/task-types.d.ts +8 -4
- package/dist/bot/task-types.d.ts.map +1 -1
- package/dist/cli-handlers.d.ts.map +1 -1
- package/dist/cli-handlers.js +2 -3
- package/dist/cli-handlers.js.map +1 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +749 -0
- package/dist/cli.js.map +1 -0
- package/dist/docs/docs/weaver-bot-usage.md +35 -18
- package/dist/docs/docs/weaver-config.md +20 -0
- package/dist/docs/docs/weaver-task-queue.md +31 -19
- package/dist/docs/weaver-config.md +15 -9
- package/dist/mcp-tools.d.ts +17 -0
- package/dist/mcp-tools.d.ts.map +1 -1
- package/dist/mcp-tools.js +98 -232
- package/dist/mcp-tools.js.map +1 -1
- package/dist/node-types/orchestrator-dispatch.d.ts +17 -0
- package/dist/node-types/orchestrator-dispatch.d.ts.map +1 -0
- package/dist/node-types/orchestrator-dispatch.js +63 -0
- package/dist/node-types/orchestrator-dispatch.js.map +1 -0
- package/dist/node-types/orchestrator-load-state.d.ts +16 -0
- package/dist/node-types/orchestrator-load-state.d.ts.map +1 -0
- package/dist/node-types/orchestrator-load-state.js +60 -0
- package/dist/node-types/orchestrator-load-state.js.map +1 -0
- package/dist/node-types/orchestrator-route.d.ts +16 -0
- package/dist/node-types/orchestrator-route.d.ts.map +1 -0
- package/dist/node-types/orchestrator-route.js +28 -0
- package/dist/node-types/orchestrator-route.js.map +1 -0
- package/dist/node-types/receive-task.d.ts +2 -3
- package/dist/node-types/receive-task.d.ts.map +1 -1
- package/dist/node-types/receive-task.js +3 -28
- package/dist/node-types/receive-task.js.map +1 -1
- package/dist/templates/weaver-template.d.ts +11 -0
- package/dist/templates/weaver-template.d.ts.map +1 -0
- package/dist/templates/weaver-template.js +53 -0
- package/dist/templates/weaver-template.js.map +1 -0
- package/dist/ui/bot-constants.d.ts +14 -0
- package/dist/ui/bot-constants.d.ts.map +1 -0
- package/dist/ui/bot-constants.js +189 -0
- package/dist/ui/bot-constants.js.map +1 -0
- package/dist/ui/bot-panel.js +51 -90
- package/dist/ui/bot-slot-card.js +87 -122
- package/dist/ui/budget-bar.js +5 -3
- package/dist/ui/chat-task-result.js +4 -7
- package/dist/ui/decision-log.js +136 -0
- package/dist/ui/profile-card.js +158 -0
- package/dist/ui/profile-editor.js +597 -0
- package/dist/ui/swarm-controls.js +36 -27
- package/dist/ui/swarm-dashboard.js +2034 -736
- package/dist/ui/task-create-form.js +39 -116
- package/dist/ui/task-detail-view.js +490 -239
- package/dist/ui/task-pool-list.js +69 -94
- package/dist/workflows/orchestrator.d.ts +21 -0
- package/dist/workflows/orchestrator.d.ts.map +1 -0
- package/dist/workflows/orchestrator.js +281 -0
- package/dist/workflows/orchestrator.js.map +1 -0
- package/dist/workflows/weaver-bot-session.d.ts +65 -0
- package/dist/workflows/weaver-bot-session.d.ts.map +1 -0
- package/dist/workflows/weaver-bot-session.js +68 -0
- package/dist/workflows/weaver-bot-session.js.map +1 -0
- package/dist/workflows/weaver.d.ts +24 -0
- package/dist/workflows/weaver.d.ts.map +1 -0
- package/dist/workflows/weaver.js +28 -0
- package/dist/workflows/weaver.js.map +1 -0
- package/flowweaver.manifest.json +253 -66
- package/package.json +1 -1
- package/src/ai-chat-provider.ts +184 -18
- package/src/bot/ai-router.ts +132 -0
- package/src/bot/bot-registry.ts +2 -2
- package/src/bot/conversation-store.ts +2 -1
- package/src/bot/improve-loop.ts +6 -6
- package/src/bot/instance-manager.ts +128 -0
- package/src/bot/orchestrator.ts +244 -0
- package/src/bot/profile-store.ts +225 -0
- package/src/bot/profile-types.ts +141 -0
- package/src/bot/swarm-controller.ts +385 -186
- package/src/bot/task-prompt-builder.ts +37 -6
- package/src/bot/task-store.ts +28 -89
- package/src/bot/task-types.ts +10 -4
- package/src/cli-handlers.ts +2 -3
- package/src/docs/weaver-bot-usage.md +35 -18
- package/src/docs/weaver-config.md +20 -0
- package/src/docs/weaver-task-queue.md +31 -19
- package/src/mcp-tools.ts +129 -320
- package/src/node-types/orchestrator-dispatch.ts +71 -0
- package/src/node-types/orchestrator-load-state.ts +66 -0
- package/src/node-types/orchestrator-route.ts +33 -0
- package/src/node-types/receive-task.ts +3 -26
- package/src/ui/bot-constants.ts +192 -0
- package/src/ui/bot-panel.tsx +55 -79
- package/src/ui/bot-slot-card.tsx +69 -117
- package/src/ui/budget-bar.tsx +5 -3
- package/src/ui/chat-task-result.tsx +6 -9
- package/src/ui/decision-log.tsx +148 -0
- package/src/ui/profile-card.tsx +157 -0
- package/src/ui/profile-editor.tsx +384 -0
- package/src/ui/swarm-controls.tsx +35 -31
- package/src/ui/swarm-dashboard.tsx +409 -80
- package/src/ui/task-create-form.tsx +29 -119
- package/src/ui/task-detail-view.tsx +461 -215
- package/src/ui/task-pool-list.tsx +74 -95
- package/src/workflows/orchestrator.ts +302 -0
- package/dist/docs/weaver-bot-usage.md +0 -34
- package/dist/docs/weaver-genesis.md +0 -32
- package/dist/docs/weaver-task-queue.md +0 -34
- package/src/bot/error-guide.ts +0 -4
- package/src/bot/retry-utils.ts +0 -4
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* Each row shows status icon, title (clickable), assigned bot tags, and priority badge.
|
|
7
7
|
*/
|
|
8
8
|
const React = require('react');
|
|
9
|
-
const {
|
|
10
|
-
const {
|
|
9
|
+
const { useState } = React;
|
|
10
|
+
const { Flex, Typography, Icon, StatusIcon, Tag, ScrollArea, Badge, EmptyState } = require('@fw/plugin-ui-kit');
|
|
11
11
|
|
|
12
12
|
// --- Types ---
|
|
13
13
|
|
|
@@ -20,7 +20,7 @@ interface Task {
|
|
|
20
20
|
priority: number;
|
|
21
21
|
isParent: boolean;
|
|
22
22
|
parentId?: string;
|
|
23
|
-
|
|
23
|
+
assignedProfile?: string;
|
|
24
24
|
createdAt: string;
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -40,57 +40,18 @@ const statusToIcon: Record<TaskStatus, string> = {
|
|
|
40
40
|
'cancelled': 'failed',
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
'pending': 'color-text-subtle',
|
|
45
|
-
'in-progress': 'color-status-info',
|
|
46
|
-
'done': 'color-status-positive',
|
|
47
|
-
'failed': 'color-status-negative',
|
|
48
|
-
'blocked': 'color-status-caution',
|
|
49
|
-
'cancelled': 'color-text-subtle',
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// --- Styled components ---
|
|
43
|
+
// --- Row styles ---
|
|
53
44
|
|
|
54
|
-
const
|
|
55
|
-
display: 'flex',
|
|
56
|
-
flexDirection: 'column',
|
|
57
|
-
height: '100%',
|
|
58
|
-
overflow: 'hidden',
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
const TaskRow = styled.div({
|
|
62
|
-
display: 'flex',
|
|
63
|
-
alignItems: 'center',
|
|
64
|
-
gap: '8px',
|
|
45
|
+
const rowBaseStyle: React.CSSProperties = {
|
|
65
46
|
padding: '8px 12px',
|
|
66
47
|
cursor: 'pointer',
|
|
67
|
-
borderBottom: '1px solid
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
textOverflow: 'ellipsis',
|
|
75
|
-
whiteSpace: 'nowrap',
|
|
76
|
-
minWidth: 0,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const BotTags = styled.div({
|
|
80
|
-
display: 'flex',
|
|
81
|
-
gap: '4px',
|
|
82
|
-
flexShrink: 0,
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
const EmptyState = styled.div({
|
|
86
|
-
display: 'flex',
|
|
87
|
-
flexDirection: 'column',
|
|
88
|
-
alignItems: 'center',
|
|
89
|
-
justifyContent: 'center',
|
|
90
|
-
gap: '8px',
|
|
91
|
-
padding: '24px 16px',
|
|
92
|
-
flex: 1,
|
|
93
|
-
});
|
|
48
|
+
borderBottom: '1px solid var(--color-border-default)',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const indentedRowStyle: React.CSSProperties = {
|
|
52
|
+
...rowBaseStyle,
|
|
53
|
+
paddingLeft: '32px',
|
|
54
|
+
};
|
|
94
55
|
|
|
95
56
|
// --- Sorting ---
|
|
96
57
|
|
|
@@ -142,62 +103,80 @@ function buildHierarchy(tasks: Task[]): Array<{ task: Task; indent: boolean }> {
|
|
|
142
103
|
return result;
|
|
143
104
|
}
|
|
144
105
|
|
|
106
|
+
// --- Task Row component with hover ---
|
|
107
|
+
|
|
108
|
+
function TaskRowItem({ task, indent, onClick }: { task: Task; indent: boolean; onClick: () => void }) {
|
|
109
|
+
const [hovered, setHovered] = useState(false);
|
|
110
|
+
const style: React.CSSProperties = {
|
|
111
|
+
...(indent ? indentedRowStyle : rowBaseStyle),
|
|
112
|
+
...(hovered ? { backgroundColor: 'var(--color-surface-elevated)' } : undefined),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
return React.createElement(Flex, {
|
|
116
|
+
variant: 'row-center-start-nowrap-8',
|
|
117
|
+
style,
|
|
118
|
+
onClick,
|
|
119
|
+
onMouseEnter: () => setHovered(true),
|
|
120
|
+
onMouseLeave: () => setHovered(false),
|
|
121
|
+
},
|
|
122
|
+
// Status icon
|
|
123
|
+
React.createElement(StatusIcon, {
|
|
124
|
+
status: statusToIcon[task.status] || 'pending',
|
|
125
|
+
size: 'sm',
|
|
126
|
+
}),
|
|
127
|
+
|
|
128
|
+
// Title
|
|
129
|
+
React.createElement(Flex, {
|
|
130
|
+
variant: 'row-center-start-nowrap-0',
|
|
131
|
+
style: { flex: 1, minWidth: 0 },
|
|
132
|
+
},
|
|
133
|
+
React.createElement(Typography, {
|
|
134
|
+
variant: 'caption-regular',
|
|
135
|
+
color: task.status === 'cancelled'
|
|
136
|
+
? 'color-text-subtle'
|
|
137
|
+
: 'color-text-high',
|
|
138
|
+
truncate: true,
|
|
139
|
+
style: task.status === 'cancelled' ? { textDecoration: 'line-through', opacity: 0.6 } : undefined,
|
|
140
|
+
}, task.title),
|
|
141
|
+
),
|
|
142
|
+
|
|
143
|
+
// Assigned profile as Tag
|
|
144
|
+
task.assignedProfile && React.createElement(Tag, {
|
|
145
|
+
size: 'small',
|
|
146
|
+
color: 'info',
|
|
147
|
+
}, task.assignedProfile),
|
|
148
|
+
|
|
149
|
+
// Priority badge (only if > 0)
|
|
150
|
+
task.priority > 0 && React.createElement(Badge, {
|
|
151
|
+
variant: task.priority >= 3 ? 'warning' : 'info',
|
|
152
|
+
}, `P${task.priority}`),
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
145
156
|
// --- Component ---
|
|
146
157
|
|
|
147
158
|
function TaskPoolList({ tasks, onTaskClick }: TaskPoolListProps) {
|
|
148
159
|
if (!tasks || tasks.length === 0) {
|
|
149
|
-
return React.createElement(EmptyState,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
color: 'color-text-subtle',
|
|
154
|
-
}, 'No tasks in the pool.'),
|
|
155
|
-
);
|
|
160
|
+
return React.createElement(EmptyState, {
|
|
161
|
+
icon: 'inbox',
|
|
162
|
+
message: 'No tasks in the pool.',
|
|
163
|
+
});
|
|
156
164
|
}
|
|
157
165
|
|
|
158
166
|
const rows = buildHierarchy(tasks);
|
|
159
167
|
|
|
160
|
-
return React.createElement(
|
|
168
|
+
return React.createElement(Flex, {
|
|
169
|
+
variant: 'column-stretch-start-nowrap-0',
|
|
170
|
+
style: { height: '100%', overflow: 'hidden' },
|
|
171
|
+
},
|
|
161
172
|
React.createElement(ScrollArea, { style: { flex: 1 } },
|
|
162
173
|
rows.map(({ task, indent }) =>
|
|
163
|
-
React.createElement(
|
|
174
|
+
React.createElement(TaskRowItem, {
|
|
164
175
|
key: task.id,
|
|
165
|
-
|
|
176
|
+
task,
|
|
177
|
+
indent,
|
|
166
178
|
onClick: () => onTaskClick(task.id),
|
|
167
|
-
},
|
|
168
|
-
// Status icon
|
|
169
|
-
React.createElement(StatusIcon, {
|
|
170
|
-
status: statusToIcon[task.status] || 'pending',
|
|
171
|
-
size: 'sm',
|
|
172
|
-
}),
|
|
173
|
-
|
|
174
|
-
// Title
|
|
175
|
-
React.createElement(TitleText, null,
|
|
176
|
-
React.createElement(Typography, {
|
|
177
|
-
variant: 'caption-regular',
|
|
178
|
-
color: statusToColor[task.status] === 'color-text-subtle' && task.status === 'cancelled'
|
|
179
|
-
? 'color-text-subtle'
|
|
180
|
-
: 'color-text-high',
|
|
181
|
-
style: task.status === 'cancelled' ? { textDecoration: 'line-through', opacity: 0.6 } : undefined,
|
|
182
|
-
}, task.title),
|
|
183
|
-
),
|
|
184
|
-
|
|
185
|
-
// Assigned bots as Tags
|
|
186
|
-
task.assignedBots.length > 0 && React.createElement(BotTags, null,
|
|
187
|
-
task.assignedBots.map((botId: string) =>
|
|
188
|
-
React.createElement(Tag, {
|
|
189
|
-
key: botId,
|
|
190
|
-
size: 'small',
|
|
191
|
-
color: 'info',
|
|
192
|
-
}, botId),
|
|
193
|
-
),
|
|
194
|
-
),
|
|
195
|
-
|
|
196
|
-
// Priority badge (only if > 0)
|
|
197
|
-
task.priority > 0 && React.createElement(Badge, {
|
|
198
|
-
variant: task.priority >= 3 ? 'warning' : 'info',
|
|
199
|
-
}, `P${task.priority}`),
|
|
200
|
-
),
|
|
179
|
+
}),
|
|
201
180
|
),
|
|
202
181
|
),
|
|
203
182
|
);
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { orchestratorLoadState } from '../node-types/orchestrator-load-state.js';
|
|
2
|
+
import { orchestratorRoute } from '../node-types/orchestrator-route.js';
|
|
3
|
+
import { orchestratorDispatch } from '../node-types/orchestrator-dispatch.js';
|
|
4
|
+
|
|
5
|
+
// @flow-weaver-runtime-start
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// DO NOT EDIT - This section is auto-generated by Flow Weaver
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
import { GeneratedExecutionContext, CancellationError } from '@synergenius/flow-weaver/runtime';
|
|
11
|
+
import type { TDebugger, TDebugController } from '@synergenius/flow-weaver/runtime';
|
|
12
|
+
declare const __flowWeaverDebugger__: TDebugger | undefined;
|
|
13
|
+
// @flow-weaver-runtime-end
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @flowWeaver workflow
|
|
17
|
+
* @node load orchestratorLoadState [position: 200 300]
|
|
18
|
+
* @node route orchestratorRoute [position: 450 300]
|
|
19
|
+
* @node dispatch orchestratorDispatch [position: 700 300]
|
|
20
|
+
* @path Start -> load -> route -> dispatch -> Exit
|
|
21
|
+
* @position Start 0 0
|
|
22
|
+
* @position Exit 1080 0
|
|
23
|
+
* @connect dispatch.results -> Exit.results
|
|
24
|
+
* @param execute [order:-1] - Execute
|
|
25
|
+
* @param projectDir [order:0] - ProjectDir
|
|
26
|
+
* @returns onSuccess [order:-1] - On Success
|
|
27
|
+
* @returns results [order:0] - Results
|
|
28
|
+
*/
|
|
29
|
+
export async function orchestratorWorkflow(
|
|
30
|
+
execute: boolean,
|
|
31
|
+
params: { projectDir: string },
|
|
32
|
+
__abortSignal__?: AbortSignal,
|
|
33
|
+
): Promise<{ onSuccess: boolean; results: string | null }> {
|
|
34
|
+
// @flow-weaver-body-start
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// DO NOT EDIT - This section is auto-generated by Flow Weaver
|
|
37
|
+
// Edit the @flowWeaver annotations above to modify workflow behavior
|
|
38
|
+
// ============================================================================
|
|
39
|
+
|
|
40
|
+
const __effectiveDebugger__ = typeof __flowWeaverDebugger__ !== 'undefined' ? __flowWeaverDebugger__ : undefined;
|
|
41
|
+
|
|
42
|
+
// Recursion depth protection
|
|
43
|
+
const __rd__ = (params as { __rd__?: number }).__rd__ ?? 0;
|
|
44
|
+
if (__rd__ >= 1000) {
|
|
45
|
+
throw new Error('Max recursion depth exceeded (1000) in workflow "orchestratorWorkflow"');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const ctx = new GeneratedExecutionContext(true, __effectiveDebugger__, __abortSignal__);
|
|
49
|
+
|
|
50
|
+
// Debug controller for step-through debugging and checkpoint/resume
|
|
51
|
+
const __ctrl__: TDebugController = (
|
|
52
|
+
typeof globalThis !== 'undefined' && (globalThis as unknown as { __fw_debug_controller__?: TDebugController }).__fw_debug_controller__
|
|
53
|
+
? (globalThis as unknown as { __fw_debug_controller__?: TDebugController }).__fw_debug_controller__
|
|
54
|
+
: { beforeNode: () => true, afterNode: () => {} }
|
|
55
|
+
)!;
|
|
56
|
+
|
|
57
|
+
const startIdx = ctx.addExecution('Start');
|
|
58
|
+
await ctx.setVariable({ id: 'Start', portName: 'execute', executionIndex: startIdx, nodeTypeName: 'Start' }, execute);
|
|
59
|
+
await ctx.setVariable({ id: 'Start', portName: 'projectDir', executionIndex: startIdx, nodeTypeName: 'Start' }, params.projectDir);
|
|
60
|
+
await ctx.sendStatusChangedEvent({
|
|
61
|
+
nodeTypeName: 'Start',
|
|
62
|
+
id: 'Start',
|
|
63
|
+
executionIndex: startIdx,
|
|
64
|
+
status: 'SUCCEEDED',
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
let loadIdx: number | undefined;
|
|
68
|
+
let routeIdx: number | undefined;
|
|
69
|
+
let dispatchIdx: number | undefined;
|
|
70
|
+
|
|
71
|
+
let load_success = false;
|
|
72
|
+
let route_success = false;
|
|
73
|
+
|
|
74
|
+
if (await __ctrl__.beforeNode('load', ctx)) {
|
|
75
|
+
|
|
76
|
+
// ── load (orchestratorLoadState) ──
|
|
77
|
+
ctx.checkAborted('load');
|
|
78
|
+
loadIdx = ctx.addExecution('load');
|
|
79
|
+
if (typeof globalThis !== 'undefined') (globalThis as unknown as { __fw_current_node_id__?: string }).__fw_current_node_id__ = 'load';
|
|
80
|
+
await ctx.sendStatusChangedEvent({
|
|
81
|
+
nodeTypeName: 'orchestratorLoadState',
|
|
82
|
+
id: 'load',
|
|
83
|
+
executionIndex: loadIdx,
|
|
84
|
+
status: 'RUNNING',
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
load_success = false;
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const load_execute = await ctx.getVariable({ id: 'Start', portName: 'execute', executionIndex: startIdx }) as boolean;
|
|
91
|
+
await ctx.setVariable({ id: 'load', portName: 'execute', executionIndex: loadIdx, nodeTypeName: 'orchestratorLoadState' }, load_execute);
|
|
92
|
+
const load_projectDir = await ctx.getVariable({ id: 'Start', portName: 'projectDir', executionIndex: startIdx }) as string;
|
|
93
|
+
await ctx.setVariable({ id: 'load', portName: 'projectDir', executionIndex: loadIdx, nodeTypeName: 'orchestratorLoadState' }, load_projectDir);
|
|
94
|
+
const loadResult = await orchestratorLoadState(load_execute, load_projectDir);
|
|
95
|
+
await ctx.setVariable({ id: 'load', portName: 'state', executionIndex: loadIdx, nodeTypeName: 'orchestratorLoadState' }, loadResult.state);
|
|
96
|
+
await ctx.setVariable({ id: 'load', portName: 'onSuccess', executionIndex: loadIdx, nodeTypeName: 'orchestratorLoadState' }, loadResult.onSuccess);
|
|
97
|
+
await ctx.setVariable({ id: 'load', portName: 'onFailure', executionIndex: loadIdx, nodeTypeName: 'orchestratorLoadState' }, loadResult.onFailure);
|
|
98
|
+
await ctx.sendStatusChangedEvent({
|
|
99
|
+
nodeTypeName: 'orchestratorLoadState',
|
|
100
|
+
id: 'load',
|
|
101
|
+
executionIndex: loadIdx,
|
|
102
|
+
status: 'SUCCEEDED',
|
|
103
|
+
});
|
|
104
|
+
await __ctrl__.afterNode('load', ctx);
|
|
105
|
+
load_success = loadResult.onSuccess;
|
|
106
|
+
} catch (error: unknown) {
|
|
107
|
+
const isCancellation = CancellationError.isCancellationError(error);
|
|
108
|
+
await ctx.sendStatusChangedEvent({
|
|
109
|
+
nodeTypeName: 'orchestratorLoadState',
|
|
110
|
+
id: 'load',
|
|
111
|
+
executionIndex: loadIdx,
|
|
112
|
+
status: isCancellation ? 'CANCELLED' : 'FAILED',
|
|
113
|
+
});
|
|
114
|
+
if (!isCancellation) {
|
|
115
|
+
ctx.sendLogErrorEvent({
|
|
116
|
+
nodeTypeName: 'orchestratorLoadState',
|
|
117
|
+
id: 'load',
|
|
118
|
+
executionIndex: loadIdx,
|
|
119
|
+
error: error instanceof Error ? error.message : String(error),
|
|
120
|
+
});
|
|
121
|
+
await ctx.setVariable({ id: 'load', portName: 'onSuccess', executionIndex: loadIdx, nodeTypeName: 'orchestratorLoadState' }, false);
|
|
122
|
+
await ctx.setVariable({ id: 'load', portName: 'onFailure', executionIndex: loadIdx, nodeTypeName: 'orchestratorLoadState' }, true);
|
|
123
|
+
load_success = false;
|
|
124
|
+
}
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
loadIdx = ctx.addExecution('load');
|
|
129
|
+
load_success = true;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (load_success) {
|
|
133
|
+
if (await __ctrl__.beforeNode('route', ctx)) {
|
|
134
|
+
|
|
135
|
+
// ── route (orchestratorRoute) ──
|
|
136
|
+
ctx.checkAborted('route');
|
|
137
|
+
routeIdx = ctx.addExecution('route');
|
|
138
|
+
if (typeof globalThis !== 'undefined') (globalThis as unknown as { __fw_current_node_id__?: string }).__fw_current_node_id__ = 'route';
|
|
139
|
+
await ctx.sendStatusChangedEvent({
|
|
140
|
+
nodeTypeName: 'orchestratorRoute',
|
|
141
|
+
id: 'route',
|
|
142
|
+
executionIndex: routeIdx,
|
|
143
|
+
status: 'RUNNING',
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
route_success = false;
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
const route_execute = loadIdx !== undefined ? await ctx.getVariable({ id: 'load', portName: 'onSuccess', executionIndex: loadIdx }) as boolean : false;
|
|
150
|
+
await ctx.setVariable({ id: 'route', portName: 'execute', executionIndex: routeIdx, nodeTypeName: 'orchestratorRoute' }, route_execute);
|
|
151
|
+
const route_state = await ctx.getVariable({ id: 'load', portName: 'state', executionIndex: loadIdx! }) as string;
|
|
152
|
+
await ctx.setVariable({ id: 'route', portName: 'state', executionIndex: routeIdx, nodeTypeName: 'orchestratorRoute' }, route_state);
|
|
153
|
+
const routeResult = await orchestratorRoute(route_execute, route_state);
|
|
154
|
+
await ctx.setVariable({ id: 'route', portName: 'decisions', executionIndex: routeIdx, nodeTypeName: 'orchestratorRoute' }, routeResult.decisions);
|
|
155
|
+
await ctx.setVariable({ id: 'route', portName: 'onSuccess', executionIndex: routeIdx, nodeTypeName: 'orchestratorRoute' }, routeResult.onSuccess);
|
|
156
|
+
await ctx.setVariable({ id: 'route', portName: 'onFailure', executionIndex: routeIdx, nodeTypeName: 'orchestratorRoute' }, routeResult.onFailure);
|
|
157
|
+
await ctx.sendStatusChangedEvent({
|
|
158
|
+
nodeTypeName: 'orchestratorRoute',
|
|
159
|
+
id: 'route',
|
|
160
|
+
executionIndex: routeIdx,
|
|
161
|
+
status: 'SUCCEEDED',
|
|
162
|
+
});
|
|
163
|
+
await __ctrl__.afterNode('route', ctx);
|
|
164
|
+
route_success = routeResult.onSuccess;
|
|
165
|
+
} catch (error: unknown) {
|
|
166
|
+
const isCancellation = CancellationError.isCancellationError(error);
|
|
167
|
+
await ctx.sendStatusChangedEvent({
|
|
168
|
+
nodeTypeName: 'orchestratorRoute',
|
|
169
|
+
id: 'route',
|
|
170
|
+
executionIndex: routeIdx,
|
|
171
|
+
status: isCancellation ? 'CANCELLED' : 'FAILED',
|
|
172
|
+
});
|
|
173
|
+
if (!isCancellation) {
|
|
174
|
+
ctx.sendLogErrorEvent({
|
|
175
|
+
nodeTypeName: 'orchestratorRoute',
|
|
176
|
+
id: 'route',
|
|
177
|
+
executionIndex: routeIdx,
|
|
178
|
+
error: error instanceof Error ? error.message : String(error),
|
|
179
|
+
});
|
|
180
|
+
await ctx.setVariable({ id: 'route', portName: 'onSuccess', executionIndex: routeIdx, nodeTypeName: 'orchestratorRoute' }, false);
|
|
181
|
+
await ctx.setVariable({ id: 'route', portName: 'onFailure', executionIndex: routeIdx, nodeTypeName: 'orchestratorRoute' }, true);
|
|
182
|
+
route_success = false;
|
|
183
|
+
}
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
routeIdx = ctx.addExecution('route');
|
|
188
|
+
route_success = true;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
} else {
|
|
192
|
+
const routeIdx = ctx.addExecution('route');
|
|
193
|
+
await ctx.setVariable({ id: 'route', portName: 'onSuccess', executionIndex: routeIdx, nodeTypeName: 'orchestratorRoute' }, false);
|
|
194
|
+
await ctx.setVariable({ id: 'route', portName: 'onFailure', executionIndex: routeIdx, nodeTypeName: 'orchestratorRoute' }, false);
|
|
195
|
+
await ctx.sendStatusChangedEvent({
|
|
196
|
+
nodeTypeName: 'orchestratorRoute',
|
|
197
|
+
id: 'route',
|
|
198
|
+
executionIndex: routeIdx,
|
|
199
|
+
status: 'CANCELLED',
|
|
200
|
+
});
|
|
201
|
+
const dispatchIdx = ctx.addExecution('dispatch');
|
|
202
|
+
await ctx.setVariable({ id: 'dispatch', portName: 'onSuccess', executionIndex: dispatchIdx, nodeTypeName: 'orchestratorDispatch' }, false);
|
|
203
|
+
await ctx.setVariable({ id: 'dispatch', portName: 'onFailure', executionIndex: dispatchIdx, nodeTypeName: 'orchestratorDispatch' }, false);
|
|
204
|
+
await ctx.sendStatusChangedEvent({
|
|
205
|
+
nodeTypeName: 'orchestratorDispatch',
|
|
206
|
+
id: 'dispatch',
|
|
207
|
+
executionIndex: dispatchIdx,
|
|
208
|
+
status: 'CANCELLED',
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
if (load_success && route_success) {
|
|
212
|
+
if (await __ctrl__.beforeNode('dispatch', ctx)) {
|
|
213
|
+
|
|
214
|
+
// ── dispatch (orchestratorDispatch) ──
|
|
215
|
+
ctx.checkAborted('dispatch');
|
|
216
|
+
dispatchIdx = ctx.addExecution('dispatch');
|
|
217
|
+
if (typeof globalThis !== 'undefined') (globalThis as unknown as { __fw_current_node_id__?: string }).__fw_current_node_id__ = 'dispatch';
|
|
218
|
+
await ctx.sendStatusChangedEvent({
|
|
219
|
+
nodeTypeName: 'orchestratorDispatch',
|
|
220
|
+
id: 'dispatch',
|
|
221
|
+
executionIndex: dispatchIdx,
|
|
222
|
+
status: 'RUNNING',
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
const dispatch_execute = routeIdx !== undefined ? await ctx.getVariable({ id: 'route', portName: 'onSuccess', executionIndex: routeIdx }) as boolean : false;
|
|
227
|
+
await ctx.setVariable({ id: 'dispatch', portName: 'execute', executionIndex: dispatchIdx, nodeTypeName: 'orchestratorDispatch' }, dispatch_execute);
|
|
228
|
+
const dispatch_decisions = await ctx.getVariable({ id: 'route', portName: 'decisions', executionIndex: routeIdx! }) as string;
|
|
229
|
+
await ctx.setVariable({ id: 'dispatch', portName: 'decisions', executionIndex: dispatchIdx, nodeTypeName: 'orchestratorDispatch' }, dispatch_decisions);
|
|
230
|
+
const dispatch_projectDir = await ctx.getVariable({ id: 'Start', portName: 'projectDir', executionIndex: startIdx }) as string;
|
|
231
|
+
await ctx.setVariable({ id: 'dispatch', portName: 'projectDir', executionIndex: dispatchIdx, nodeTypeName: 'orchestratorDispatch' }, dispatch_projectDir);
|
|
232
|
+
const dispatchResult = await orchestratorDispatch(dispatch_execute, dispatch_decisions, dispatch_projectDir);
|
|
233
|
+
await ctx.setVariable({ id: 'dispatch', portName: 'results', executionIndex: dispatchIdx, nodeTypeName: 'orchestratorDispatch' }, dispatchResult.results);
|
|
234
|
+
await ctx.setVariable({ id: 'dispatch', portName: 'onSuccess', executionIndex: dispatchIdx, nodeTypeName: 'orchestratorDispatch' }, dispatchResult.onSuccess);
|
|
235
|
+
await ctx.setVariable({ id: 'dispatch', portName: 'onFailure', executionIndex: dispatchIdx, nodeTypeName: 'orchestratorDispatch' }, dispatchResult.onFailure);
|
|
236
|
+
await ctx.sendStatusChangedEvent({
|
|
237
|
+
nodeTypeName: 'orchestratorDispatch',
|
|
238
|
+
id: 'dispatch',
|
|
239
|
+
executionIndex: dispatchIdx,
|
|
240
|
+
status: 'SUCCEEDED',
|
|
241
|
+
});
|
|
242
|
+
await __ctrl__.afterNode('dispatch', ctx);
|
|
243
|
+
} catch (error: unknown) {
|
|
244
|
+
const isCancellation = CancellationError.isCancellationError(error);
|
|
245
|
+
await ctx.sendStatusChangedEvent({
|
|
246
|
+
nodeTypeName: 'orchestratorDispatch',
|
|
247
|
+
id: 'dispatch',
|
|
248
|
+
executionIndex: dispatchIdx,
|
|
249
|
+
status: isCancellation ? 'CANCELLED' : 'FAILED',
|
|
250
|
+
});
|
|
251
|
+
if (!isCancellation) {
|
|
252
|
+
ctx.sendLogErrorEvent({
|
|
253
|
+
nodeTypeName: 'orchestratorDispatch',
|
|
254
|
+
id: 'dispatch',
|
|
255
|
+
executionIndex: dispatchIdx,
|
|
256
|
+
error: error instanceof Error ? error.message : String(error),
|
|
257
|
+
});
|
|
258
|
+
await ctx.setVariable({ id: 'dispatch', portName: 'onSuccess', executionIndex: dispatchIdx, nodeTypeName: 'orchestratorDispatch' }, false);
|
|
259
|
+
await ctx.setVariable({ id: 'dispatch', portName: 'onFailure', executionIndex: dispatchIdx, nodeTypeName: 'orchestratorDispatch' }, true);
|
|
260
|
+
}
|
|
261
|
+
throw error;
|
|
262
|
+
}
|
|
263
|
+
} else {
|
|
264
|
+
dispatchIdx = ctx.addExecution('dispatch');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
} else {
|
|
268
|
+
const dispatchIdx = ctx.addExecution('dispatch');
|
|
269
|
+
await ctx.setVariable({ id: 'dispatch', portName: 'onSuccess', executionIndex: dispatchIdx, nodeTypeName: 'orchestratorDispatch' }, false);
|
|
270
|
+
await ctx.setVariable({ id: 'dispatch', portName: 'onFailure', executionIndex: dispatchIdx, nodeTypeName: 'orchestratorDispatch' }, false);
|
|
271
|
+
await ctx.sendStatusChangedEvent({
|
|
272
|
+
nodeTypeName: 'orchestratorDispatch',
|
|
273
|
+
id: 'dispatch',
|
|
274
|
+
executionIndex: dispatchIdx,
|
|
275
|
+
status: 'CANCELLED',
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
const exitIdx = ctx.addExecution('Exit');
|
|
279
|
+
const exit_results = dispatchIdx !== undefined ? await ctx.getVariable({ id: 'dispatch', portName: 'results', executionIndex: dispatchIdx }) : undefined;
|
|
280
|
+
await ctx.setVariable({ id: 'Exit', portName: 'results', executionIndex: exitIdx, nodeTypeName: 'Exit' }, exit_results);
|
|
281
|
+
const exit_onSuccess = dispatchIdx !== undefined ? await ctx.getVariable({ id: 'dispatch', portName: 'onSuccess', executionIndex: dispatchIdx }) : false;
|
|
282
|
+
await ctx.setVariable({ id: 'Exit', portName: 'onSuccess', executionIndex: exitIdx, nodeTypeName: 'Exit' }, exit_onSuccess);
|
|
283
|
+
|
|
284
|
+
await ctx.setVariable({ id: 'Exit', portName: 'onFailure', executionIndex: exitIdx, nodeTypeName: 'Exit' }, false);
|
|
285
|
+
const finalResult = { onFailure: false, results: exit_results as string, onSuccess: exit_onSuccess as boolean };
|
|
286
|
+
|
|
287
|
+
await ctx.sendStatusChangedEvent({
|
|
288
|
+
nodeTypeName: 'Exit',
|
|
289
|
+
id: 'Exit',
|
|
290
|
+
executionIndex: exitIdx,
|
|
291
|
+
status: 'SUCCEEDED',
|
|
292
|
+
});
|
|
293
|
+
ctx.sendWorkflowCompletedEvent({
|
|
294
|
+
executionIndex: exitIdx,
|
|
295
|
+
status: 'SUCCEEDED',
|
|
296
|
+
result: finalResult,
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
return finalResult;
|
|
300
|
+
// @flow-weaver-body-end
|
|
301
|
+
return { onSuccess: false, results: null };
|
|
302
|
+
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
## Weaver Bot
|
|
2
|
-
|
|
3
|
-
The Weaver bot is an autonomous AI agent that creates and modifies Flow Weaver workflows from natural language instructions.
|
|
4
|
-
|
|
5
|
-
### Running the bot
|
|
6
|
-
|
|
7
|
-
Use `fw_weaver_bot` with a task description:
|
|
8
|
-
- `task`: Natural language instruction (required)
|
|
9
|
-
- `mode`: `create` (new workflow), `modify` (edit existing), `read` (analyze), `batch` (multiple tasks)
|
|
10
|
-
- `targets`: File paths for modify/read mode
|
|
11
|
-
- `autoApprove`: Skip the approval gate (default: true in studio)
|
|
12
|
-
|
|
13
|
-
### Execution flow
|
|
14
|
-
|
|
15
|
-
1. **Receive task** — parses instruction and determines mode
|
|
16
|
-
2. **Build context** — gathers project state, templates, and relevant files
|
|
17
|
-
3. **Plan** — AI generates a step-by-step execution plan
|
|
18
|
-
4. **Approval gate** — plan shown for review (skipped if autoApprove)
|
|
19
|
-
5. **Execute + validate + retry** — runs steps, validates output, retries on errors (up to 3 attempts)
|
|
20
|
-
6. **Git ops** — commits changes if successful
|
|
21
|
-
7. **Report** — returns summary with outcome
|
|
22
|
-
|
|
23
|
-
### Steering a running bot
|
|
24
|
-
|
|
25
|
-
Use `fw_weaver_steer` to control execution:
|
|
26
|
-
- `pause` — pause at next safe point
|
|
27
|
-
- `resume` — continue after pause
|
|
28
|
-
- `cancel` — abort execution
|
|
29
|
-
- `redirect` — change task mid-execution
|
|
30
|
-
- `queue` — add a follow-up task
|
|
31
|
-
|
|
32
|
-
### Checking status
|
|
33
|
-
|
|
34
|
-
Use `fw_weaver_status` to see the current bot session state, active task, and completion count.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
## Genesis Self-Evolution
|
|
2
|
-
|
|
3
|
-
Genesis is Weaver's self-evolution protocol. It autonomously observes, proposes, applies, and validates changes to workflows.
|
|
4
|
-
|
|
5
|
-
### Running a Genesis cycle
|
|
6
|
-
|
|
7
|
-
Use `fw_weaver_genesis` to trigger a single cycle:
|
|
8
|
-
- `projectDir`: Project directory (defaults to workspace)
|
|
9
|
-
- `dryRun`: Preview changes without applying
|
|
10
|
-
|
|
11
|
-
### How it works
|
|
12
|
-
|
|
13
|
-
1. **Observe** — scans project for workflows and their health
|
|
14
|
-
2. **Fingerprint** — detects if workflows changed since last cycle (avoids duplicate proposals)
|
|
15
|
-
3. **Stabilize check** — prevents rapid churn (cooldown between cycles)
|
|
16
|
-
4. **Propose** — AI analyzes project state and proposes modifications within a budget
|
|
17
|
-
5. **Validate proposal** — checks proposed changes are safe
|
|
18
|
-
6. **Snapshot** — creates backup before applying
|
|
19
|
-
7. **Apply** — executes proposed operations via `flow-weaver modify`
|
|
20
|
-
8. **Validate result** — compiles and validates the modified workflow
|
|
21
|
-
9. **Threshold check** — decides if changes meet the quality bar
|
|
22
|
-
10. **Approve** — human approval gate (configurable)
|
|
23
|
-
11. **Commit** — git commit with rollback capability
|
|
24
|
-
12. **Escrow** — data safety pipeline for recovery
|
|
25
|
-
|
|
26
|
-
### Safety features
|
|
27
|
-
|
|
28
|
-
- Pre-apply snapshots for rollback
|
|
29
|
-
- Escrow recovery from previous cycles
|
|
30
|
-
- Fingerprinting prevents duplicate proposals
|
|
31
|
-
- Threshold checking before committing
|
|
32
|
-
- Budget limits on proposed changes
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
## Task Queue & Steering
|
|
2
|
-
|
|
3
|
-
Weaver supports queuing tasks for background processing and steering running bots in real-time.
|
|
4
|
-
|
|
5
|
-
### Task queue
|
|
6
|
-
|
|
7
|
-
Use `fw_weaver_queue` to manage tasks:
|
|
8
|
-
- `add` — add a task to the queue (requires `task` instruction)
|
|
9
|
-
- `list` — show all queued tasks
|
|
10
|
-
- `clear` — remove all pending tasks
|
|
11
|
-
- `remove` — remove a specific task by ID
|
|
12
|
-
|
|
13
|
-
Tasks are stored in NDJSON format and processed sequentially by the bot session.
|
|
14
|
-
|
|
15
|
-
### Steering commands
|
|
16
|
-
|
|
17
|
-
Use `fw_weaver_steer` to control a running bot:
|
|
18
|
-
- `pause` — pause execution at the next safe point
|
|
19
|
-
- `resume` — continue after a pause
|
|
20
|
-
- `cancel` — abort the current task
|
|
21
|
-
- `redirect` — change the task instruction mid-execution (requires `payload` with new instruction)
|
|
22
|
-
- `queue` — add a follow-up task without interrupting the current one
|
|
23
|
-
|
|
24
|
-
### Batch mode
|
|
25
|
-
|
|
26
|
-
For multiple related tasks, use `fw_weaver_bot` with `mode: "batch"` to process them in sequence through the same bot session, sharing context between tasks.
|
|
27
|
-
|
|
28
|
-
### Monitoring
|
|
29
|
-
|
|
30
|
-
Use `fw_weaver_status` to check the current session state:
|
|
31
|
-
- Session phase (idle, planning, executing, validating)
|
|
32
|
-
- Current task instruction
|
|
33
|
-
- Completed task count
|
|
34
|
-
- Error state if any
|
package/src/bot/error-guide.ts
DELETED
package/src/bot/retry-utils.ts
DELETED