@synergenius/flowweaver-pack-weaver 0.3.1 → 0.5.0
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/bot/dashboard.d.ts +3 -0
- package/dist/bot/dashboard.d.ts.map +1 -1
- package/dist/bot/dashboard.js +141 -0
- package/dist/bot/dashboard.js.map +1 -1
- package/dist/bot/index.d.ts +8 -1
- package/dist/bot/index.d.ts.map +1 -1
- package/dist/bot/index.js +5 -0
- package/dist/bot/index.js.map +1 -1
- package/dist/bot/notifications.d.ts.map +1 -1
- package/dist/bot/notifications.js +18 -0
- package/dist/bot/notifications.js.map +1 -1
- package/dist/bot/session-state.d.ts +19 -0
- package/dist/bot/session-state.d.ts.map +1 -0
- package/dist/bot/session-state.js +56 -0
- package/dist/bot/session-state.js.map +1 -0
- package/dist/bot/steering.d.ts +13 -0
- package/dist/bot/steering.d.ts.map +1 -0
- package/dist/bot/steering.js +35 -0
- package/dist/bot/steering.js.map +1 -0
- package/dist/bot/system-prompt.d.ts +1 -0
- package/dist/bot/system-prompt.d.ts.map +1 -1
- package/dist/bot/system-prompt.js +55 -0
- package/dist/bot/system-prompt.js.map +1 -1
- package/dist/bot/task-queue.d.ts +26 -0
- package/dist/bot/task-queue.d.ts.map +1 -0
- package/dist/bot/task-queue.js +87 -0
- package/dist/bot/task-queue.js.map +1 -0
- package/dist/bot/types.d.ts +37 -1
- package/dist/bot/types.d.ts.map +1 -1
- package/dist/cli-bridge.d.ts +2 -0
- package/dist/cli-bridge.d.ts.map +1 -0
- package/dist/cli-bridge.js +31 -0
- package/dist/cli-bridge.js.map +1 -0
- package/dist/cli-handlers.d.ts +50 -0
- package/dist/cli-handlers.d.ts.map +1 -0
- package/dist/{cli.js → cli-handlers.js} +413 -181
- package/dist/cli-handlers.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-tools.d.ts +13 -0
- package/dist/mcp-tools.d.ts.map +1 -0
- package/dist/mcp-tools.js +175 -0
- package/dist/mcp-tools.js.map +1 -0
- package/dist/node-types/abort-task.d.ts +22 -0
- package/dist/node-types/abort-task.d.ts.map +1 -0
- package/dist/node-types/abort-task.js +33 -0
- package/dist/node-types/abort-task.js.map +1 -0
- package/dist/node-types/approval-gate.d.ts +35 -0
- package/dist/node-types/approval-gate.d.ts.map +1 -0
- package/dist/node-types/approval-gate.js +62 -0
- package/dist/node-types/approval-gate.js.map +1 -0
- package/dist/node-types/bot-report.d.ts +22 -0
- package/dist/node-types/bot-report.d.ts.map +1 -0
- package/dist/node-types/bot-report.js +63 -0
- package/dist/node-types/bot-report.js.map +1 -0
- package/dist/node-types/build-context.d.ts +29 -0
- package/dist/node-types/build-context.d.ts.map +1 -0
- package/dist/node-types/build-context.js +73 -0
- package/dist/node-types/build-context.js.map +1 -0
- package/dist/node-types/detect-provider.d.ts +20 -0
- package/dist/node-types/detect-provider.d.ts.map +1 -0
- package/dist/node-types/detect-provider.js +72 -0
- package/dist/node-types/detect-provider.js.map +1 -0
- package/dist/node-types/exec-validate-retry.d.ts +38 -0
- package/dist/node-types/exec-validate-retry.d.ts.map +1 -0
- package/dist/node-types/exec-validate-retry.js +250 -0
- package/dist/node-types/exec-validate-retry.js.map +1 -0
- package/dist/node-types/execute-plan.d.ts +34 -0
- package/dist/node-types/execute-plan.d.ts.map +1 -0
- package/dist/node-types/execute-plan.js +175 -0
- package/dist/node-types/execute-plan.js.map +1 -0
- package/dist/node-types/execute-target.d.ts +26 -0
- package/dist/node-types/execute-target.d.ts.map +1 -0
- package/dist/node-types/execute-target.js +312 -0
- package/dist/node-types/execute-target.js.map +1 -0
- package/dist/node-types/fix-errors.d.ts +32 -0
- package/dist/node-types/fix-errors.d.ts.map +1 -0
- package/dist/node-types/fix-errors.js +106 -0
- package/dist/node-types/fix-errors.js.map +1 -0
- package/dist/node-types/git-ops.d.ts +18 -0
- package/dist/node-types/git-ops.d.ts.map +1 -0
- package/dist/node-types/git-ops.js +65 -0
- package/dist/node-types/git-ops.js.map +1 -0
- package/dist/node-types/index.d.ts +20 -0
- package/dist/node-types/index.d.ts.map +1 -0
- package/dist/node-types/index.js +20 -0
- package/dist/node-types/index.js.map +1 -0
- package/dist/node-types/load-config.d.ts +15 -0
- package/dist/node-types/load-config.d.ts.map +1 -0
- package/dist/node-types/load-config.js +26 -0
- package/dist/node-types/load-config.js.map +1 -0
- package/dist/node-types/plan-task.d.ts +32 -0
- package/dist/node-types/plan-task.d.ts.map +1 -0
- package/dist/node-types/plan-task.js +122 -0
- package/dist/node-types/plan-task.js.map +1 -0
- package/dist/node-types/read-workflow.d.ts +30 -0
- package/dist/node-types/read-workflow.d.ts.map +1 -0
- package/dist/node-types/read-workflow.js +72 -0
- package/dist/node-types/read-workflow.js.map +1 -0
- package/dist/node-types/receive-task.d.ts +31 -0
- package/dist/node-types/receive-task.d.ts.map +1 -0
- package/dist/node-types/receive-task.js +72 -0
- package/dist/node-types/receive-task.js.map +1 -0
- package/dist/node-types/report.d.ts +15 -0
- package/dist/node-types/report.d.ts.map +1 -0
- package/dist/node-types/report.js +25 -0
- package/dist/node-types/report.js.map +1 -0
- package/dist/node-types/resolve-target.d.ts +24 -0
- package/dist/node-types/resolve-target.d.ts.map +1 -0
- package/dist/node-types/resolve-target.js +67 -0
- package/dist/node-types/resolve-target.js.map +1 -0
- package/dist/node-types/route-task.d.ts +26 -0
- package/dist/node-types/route-task.d.ts.map +1 -0
- package/dist/node-types/route-task.js +29 -0
- package/dist/node-types/route-task.js.map +1 -0
- package/dist/node-types/send-notify.d.ts +20 -0
- package/dist/node-types/send-notify.d.ts.map +1 -0
- package/dist/node-types/send-notify.js +75 -0
- package/dist/node-types/send-notify.js.map +1 -0
- package/dist/node-types/validate-result.d.ts +32 -0
- package/dist/node-types/validate-result.d.ts.map +1 -0
- package/dist/node-types/validate-result.js +53 -0
- package/dist/node-types/validate-result.js.map +1 -0
- package/dist/templates/index.d.ts +2 -0
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +3 -1
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/weaver-bot-template.d.ts +3 -0
- package/dist/templates/weaver-bot-template.d.ts.map +1 -0
- package/dist/templates/weaver-bot-template.js +99 -0
- package/dist/templates/weaver-bot-template.js.map +1 -0
- package/dist/templates/weaver-template.d.ts.map +1 -1
- package/dist/templates/weaver-template.js +15 -653
- package/dist/templates/weaver-template.js.map +1 -1
- package/dist/workflows/index.d.ts +5 -0
- package/dist/workflows/index.d.ts.map +1 -0
- package/dist/workflows/index.js +5 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/weaver-bot-batch.d.ts +57 -0
- package/dist/workflows/weaver-bot-batch.d.ts.map +1 -0
- package/dist/workflows/weaver-bot-batch.js +60 -0
- package/dist/workflows/weaver-bot-batch.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-bot.d.ts +72 -0
- package/dist/workflows/weaver-bot.d.ts.map +1 -0
- package/dist/workflows/weaver-bot.js +75 -0
- package/dist/workflows/weaver-bot.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 +1004 -3
- package/package.json +23 -5
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
import * as path from 'node:path';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
3
4
|
import { runWorkflow } from './bot/runner.js';
|
|
4
5
|
import { RunStore } from './bot/run-store.js';
|
|
5
6
|
import { CostStore } from './bot/cost-store.js';
|
|
@@ -8,64 +9,7 @@ import { WatchDaemon } from './bot/watch-daemon.js';
|
|
|
8
9
|
import { PipelineRunner } from './bot/pipeline-runner.js';
|
|
9
10
|
import { DashboardServer } from './bot/dashboard.js';
|
|
10
11
|
import { openBrowser } from './bot/utils.js';
|
|
11
|
-
|
|
12
|
-
weaver - Autonomous workflow runner for Flow Weaver
|
|
13
|
-
|
|
14
|
-
Usage:
|
|
15
|
-
weaver <file> Run a workflow file
|
|
16
|
-
weaver run <file> Same as above
|
|
17
|
-
weaver history List recent runs
|
|
18
|
-
weaver history <id> Show details of a specific run
|
|
19
|
-
weaver costs Show cost summary
|
|
20
|
-
weaver watch <file> Watch file, re-run on change
|
|
21
|
-
weaver cron "<schedule>" <file> Run on cron schedule
|
|
22
|
-
weaver pipeline <config.json> Run multi-stage pipeline
|
|
23
|
-
weaver dashboard [file] Start live dashboard (optionally run file)
|
|
24
|
-
weaver providers List available providers
|
|
25
|
-
weaver --help Show this help
|
|
26
|
-
|
|
27
|
-
Options:
|
|
28
|
-
-v, --verbose Show detailed execution info
|
|
29
|
-
-n, --dry-run Preview without executing
|
|
30
|
-
-p, --params <json> Input parameters as JSON
|
|
31
|
-
-c, --config <path> Path to .weaver.json config
|
|
32
|
-
--quiet Suppress progress output
|
|
33
|
-
--version Show version
|
|
34
|
-
--dashboard Enable live dashboard for run
|
|
35
|
-
--port <number> Dashboard port (default 4242)
|
|
36
|
-
--open Auto-open browser
|
|
37
|
-
--approval <mode> Override approval mode
|
|
38
|
-
|
|
39
|
-
Watch/Cron options:
|
|
40
|
-
--cron "<schedule>" Add cron trigger to watch mode
|
|
41
|
-
--debounce <ms> File watch debounce (default 500)
|
|
42
|
-
--log <path> Write output to log file
|
|
43
|
-
|
|
44
|
-
Pipeline options:
|
|
45
|
-
--stage <id> Run single stage + its dependencies
|
|
46
|
-
|
|
47
|
-
History options:
|
|
48
|
-
--limit <n> Number of entries (default: 20)
|
|
49
|
-
--outcome <type> Filter: completed|failed|error|skipped
|
|
50
|
-
--workflow <path> Filter by workflow file
|
|
51
|
-
--since <date> Show runs after date (ISO-8601)
|
|
52
|
-
--json JSON output
|
|
53
|
-
--prune Prune old entries (keep 500, 90 days)
|
|
54
|
-
--clear Delete all history
|
|
55
|
-
|
|
56
|
-
Cost options:
|
|
57
|
-
--since <duration|date> Filter: 7d, 30d, or ISO-8601 date
|
|
58
|
-
--model <name> Filter by model
|
|
59
|
-
|
|
60
|
-
Examples:
|
|
61
|
-
weaver my-workflow.ts
|
|
62
|
-
weaver run pipeline.ts --verbose --params '{"env":"prod"}'
|
|
63
|
-
weaver watch my-workflow.ts --cron "*/5 * * * *"
|
|
64
|
-
weaver pipeline deploy.json --stage test
|
|
65
|
-
weaver history --outcome failed --limit 10
|
|
66
|
-
weaver costs --since 7d
|
|
67
|
-
`.trim();
|
|
68
|
-
function parseArgs(argv) {
|
|
12
|
+
export function parseArgs(argv) {
|
|
69
13
|
const result = {
|
|
70
14
|
command: 'run',
|
|
71
15
|
file: undefined,
|
|
@@ -84,6 +28,7 @@ function parseArgs(argv) {
|
|
|
84
28
|
dashboard: false,
|
|
85
29
|
dashboardPort: 4242,
|
|
86
30
|
dashboardOpen: false,
|
|
31
|
+
autoApprove: false,
|
|
87
32
|
};
|
|
88
33
|
const args = argv.slice(2);
|
|
89
34
|
let i = 0;
|
|
@@ -161,6 +106,9 @@ function parseArgs(argv) {
|
|
|
161
106
|
else if (arg === 'providers') {
|
|
162
107
|
result.command = 'providers';
|
|
163
108
|
}
|
|
109
|
+
else if (arg === 'eject') {
|
|
110
|
+
result.command = 'eject';
|
|
111
|
+
}
|
|
164
112
|
else if (arg === 'watch') {
|
|
165
113
|
result.command = 'watch';
|
|
166
114
|
}
|
|
@@ -209,6 +157,62 @@ function parseArgs(argv) {
|
|
|
209
157
|
result.command = 'dashboard';
|
|
210
158
|
result.dashboard = true;
|
|
211
159
|
}
|
|
160
|
+
else if (arg === 'bot') {
|
|
161
|
+
result.command = 'bot';
|
|
162
|
+
// Next non-flag arg is the task string
|
|
163
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
164
|
+
i++;
|
|
165
|
+
result.botTask = args[i];
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else if (arg === 'session') {
|
|
169
|
+
result.command = 'session';
|
|
170
|
+
}
|
|
171
|
+
else if (arg === 'steer') {
|
|
172
|
+
result.command = 'steer';
|
|
173
|
+
// Next arg is the subcommand
|
|
174
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
175
|
+
i++;
|
|
176
|
+
result.botTask = args[i];
|
|
177
|
+
// Next arg after redirect/queue is payload
|
|
178
|
+
if ((args[i] === 'redirect' || args[i] === 'queue') && i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
179
|
+
i++;
|
|
180
|
+
result.botFile = args[i];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
else if (arg === 'queue') {
|
|
185
|
+
result.command = 'queue';
|
|
186
|
+
// Next arg is action (add/list/clear/remove)
|
|
187
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
188
|
+
i++;
|
|
189
|
+
result.botTask = args[i];
|
|
190
|
+
// Next arg is task/id
|
|
191
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
192
|
+
i++;
|
|
193
|
+
result.botFile = args[i];
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else if (arg === '--file' && i + 1 < args.length) {
|
|
198
|
+
i++;
|
|
199
|
+
result.botFile = args[i];
|
|
200
|
+
}
|
|
201
|
+
else if (arg === '--template' && i + 1 < args.length) {
|
|
202
|
+
i++;
|
|
203
|
+
result.botTemplate = args[i];
|
|
204
|
+
}
|
|
205
|
+
else if (arg === '--batch' && i + 1 < args.length) {
|
|
206
|
+
i++;
|
|
207
|
+
result.botBatch = parseInt(args[i], 10) || undefined;
|
|
208
|
+
}
|
|
209
|
+
else if (arg === '--auto-approve') {
|
|
210
|
+
result.autoApprove = true;
|
|
211
|
+
}
|
|
212
|
+
else if (arg === '--project-dir' && i + 1 < args.length) {
|
|
213
|
+
i++;
|
|
214
|
+
result.file = args[i];
|
|
215
|
+
}
|
|
212
216
|
else if (arg === 'run') {
|
|
213
217
|
// skip, next arg is the file
|
|
214
218
|
}
|
|
@@ -222,14 +226,15 @@ function parseArgs(argv) {
|
|
|
222
226
|
}
|
|
223
227
|
else {
|
|
224
228
|
console.error(`[weaver] Unknown option: ${arg}`);
|
|
225
|
-
console.error('Run "weaver --help" for usage');
|
|
229
|
+
console.error('Run "flow-weaver weaver --help" for usage');
|
|
226
230
|
process.exit(1);
|
|
227
231
|
}
|
|
228
232
|
i++;
|
|
229
233
|
}
|
|
230
234
|
return result;
|
|
231
235
|
}
|
|
232
|
-
|
|
236
|
+
// --- Formatting helpers ---
|
|
237
|
+
export function formatDuration(ms) {
|
|
233
238
|
if (ms < 1000)
|
|
234
239
|
return `${ms}ms`;
|
|
235
240
|
return `${(ms / 1000).toFixed(1)}s`;
|
|
@@ -246,7 +251,13 @@ const OUTCOME_COLORS = {
|
|
|
246
251
|
skipped: '\x1b[33m',
|
|
247
252
|
};
|
|
248
253
|
const RESET = '\x1b[0m';
|
|
249
|
-
|
|
254
|
+
const STAGE_ICONS = {
|
|
255
|
+
running: '\x1b[36m>\x1b[0m',
|
|
256
|
+
completed: '\x1b[32m+\x1b[0m',
|
|
257
|
+
failed: '\x1b[31mx\x1b[0m',
|
|
258
|
+
skipped: '\x1b[33m-\x1b[0m',
|
|
259
|
+
cancelled: '\x1b[33m~\x1b[0m',
|
|
260
|
+
};
|
|
250
261
|
function printRunTable(records) {
|
|
251
262
|
console.log('ID'.padEnd(10) +
|
|
252
263
|
'OUTCOME'.padEnd(12) +
|
|
@@ -289,7 +300,57 @@ function printRunDetail(r) {
|
|
|
289
300
|
}
|
|
290
301
|
console.log('');
|
|
291
302
|
}
|
|
292
|
-
|
|
303
|
+
function parseSince(spec) {
|
|
304
|
+
if (!spec)
|
|
305
|
+
return undefined;
|
|
306
|
+
const match = spec.match(/^(\d+)([dhm])$/);
|
|
307
|
+
if (match) {
|
|
308
|
+
const n = parseInt(match[1], 10);
|
|
309
|
+
const unit = match[2];
|
|
310
|
+
const ms = unit === 'd' ? n * 86_400_000 : unit === 'h' ? n * 3_600_000 : n * 60_000;
|
|
311
|
+
return Date.now() - ms;
|
|
312
|
+
}
|
|
313
|
+
const ts = new Date(spec).getTime();
|
|
314
|
+
return isNaN(ts) ? undefined : ts;
|
|
315
|
+
}
|
|
316
|
+
function formatCostTable(summary) {
|
|
317
|
+
const lines = [];
|
|
318
|
+
lines.push(`Weaver Cost Summary (${summary.totalRuns} runs)`);
|
|
319
|
+
lines.push(`Total: ~$${summary.totalCost.toFixed(4)}`);
|
|
320
|
+
lines.push(`Tokens: ${summary.totalInputTokens.toLocaleString()} in / ${summary.totalOutputTokens.toLocaleString()} out`);
|
|
321
|
+
const models = Object.entries(summary.byModel);
|
|
322
|
+
if (models.length > 0) {
|
|
323
|
+
lines.push('');
|
|
324
|
+
lines.push('By model:');
|
|
325
|
+
for (const [model, data] of models) {
|
|
326
|
+
lines.push(` ${model}: ${data.runs} runs, ~$${data.cost.toFixed(4)}, ${data.inputTokens.toLocaleString()} in / ${data.outputTokens.toLocaleString()} out`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return lines.join('\n');
|
|
330
|
+
}
|
|
331
|
+
function formatRunCost(cost) {
|
|
332
|
+
const inp = cost.totalInputTokens.toLocaleString();
|
|
333
|
+
const out = cost.totalOutputTokens.toLocaleString();
|
|
334
|
+
const usd = cost.totalCost < 0.01
|
|
335
|
+
? `$${cost.totalCost.toFixed(4)}`
|
|
336
|
+
: `$${cost.totalCost.toFixed(2)}`;
|
|
337
|
+
return `tokens: ${inp} in / ${out} out | cost: ~${usd} (${cost.model})`;
|
|
338
|
+
}
|
|
339
|
+
async function loadConfig(configPath) {
|
|
340
|
+
if (!configPath)
|
|
341
|
+
return undefined;
|
|
342
|
+
try {
|
|
343
|
+
const { readFileSync } = await import('node:fs');
|
|
344
|
+
return JSON.parse(readFileSync(path.resolve(configPath), 'utf-8'));
|
|
345
|
+
}
|
|
346
|
+
catch (err) {
|
|
347
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
348
|
+
console.error(`[weaver] Failed to read config: ${msg}`);
|
|
349
|
+
process.exit(1);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
// --- Handlers ---
|
|
353
|
+
export async function handleHistory(opts) {
|
|
293
354
|
const store = new RunStore();
|
|
294
355
|
if (opts.historyClear) {
|
|
295
356
|
const deleted = store.clear();
|
|
@@ -332,44 +393,7 @@ async function handleHistory(opts) {
|
|
|
332
393
|
printRunTable(records);
|
|
333
394
|
}
|
|
334
395
|
}
|
|
335
|
-
|
|
336
|
-
function parseSince(spec) {
|
|
337
|
-
if (!spec)
|
|
338
|
-
return undefined;
|
|
339
|
-
const match = spec.match(/^(\d+)([dhm])$/);
|
|
340
|
-
if (match) {
|
|
341
|
-
const n = parseInt(match[1], 10);
|
|
342
|
-
const unit = match[2];
|
|
343
|
-
const ms = unit === 'd' ? n * 86_400_000 : unit === 'h' ? n * 3_600_000 : n * 60_000;
|
|
344
|
-
return Date.now() - ms;
|
|
345
|
-
}
|
|
346
|
-
const ts = new Date(spec).getTime();
|
|
347
|
-
return isNaN(ts) ? undefined : ts;
|
|
348
|
-
}
|
|
349
|
-
function formatCostTable(summary) {
|
|
350
|
-
const lines = [];
|
|
351
|
-
lines.push(`Weaver Cost Summary (${summary.totalRuns} runs)`);
|
|
352
|
-
lines.push(`Total: ~$${summary.totalCost.toFixed(4)}`);
|
|
353
|
-
lines.push(`Tokens: ${summary.totalInputTokens.toLocaleString()} in / ${summary.totalOutputTokens.toLocaleString()} out`);
|
|
354
|
-
const models = Object.entries(summary.byModel);
|
|
355
|
-
if (models.length > 0) {
|
|
356
|
-
lines.push('');
|
|
357
|
-
lines.push('By model:');
|
|
358
|
-
for (const [model, data] of models) {
|
|
359
|
-
lines.push(` ${model}: ${data.runs} runs, ~$${data.cost.toFixed(4)}, ${data.inputTokens.toLocaleString()} in / ${data.outputTokens.toLocaleString()} out`);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return lines.join('\n');
|
|
363
|
-
}
|
|
364
|
-
function formatRunCost(cost) {
|
|
365
|
-
const inp = cost.totalInputTokens.toLocaleString();
|
|
366
|
-
const out = cost.totalOutputTokens.toLocaleString();
|
|
367
|
-
const usd = cost.totalCost < 0.01
|
|
368
|
-
? `$${cost.totalCost.toFixed(4)}`
|
|
369
|
-
: `$${cost.totalCost.toFixed(2)}`;
|
|
370
|
-
return `tokens: ${inp} in / ${out} out | cost: ~${usd} (${cost.model})`;
|
|
371
|
-
}
|
|
372
|
-
async function handleCosts(opts) {
|
|
396
|
+
export async function handleCosts(opts) {
|
|
373
397
|
const store = new CostStore();
|
|
374
398
|
const sinceTs = parseSince(opts.costsSince);
|
|
375
399
|
const summary = store.summarize({ since: sinceTs, model: opts.costsModel });
|
|
@@ -379,21 +403,7 @@ async function handleCosts(opts) {
|
|
|
379
403
|
}
|
|
380
404
|
console.log(formatCostTable(summary));
|
|
381
405
|
}
|
|
382
|
-
async function
|
|
383
|
-
if (!configPath)
|
|
384
|
-
return undefined;
|
|
385
|
-
try {
|
|
386
|
-
const { readFileSync } = await import('node:fs');
|
|
387
|
-
return JSON.parse(readFileSync(path.resolve(configPath), 'utf-8'));
|
|
388
|
-
}
|
|
389
|
-
catch (err) {
|
|
390
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
391
|
-
console.error(`[weaver] Failed to read config: ${msg}`);
|
|
392
|
-
process.exit(1);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
// --- Watch/Cron ---
|
|
396
|
-
async function handleWatch(opts) {
|
|
406
|
+
export async function handleWatch(opts) {
|
|
397
407
|
if (!opts.file) {
|
|
398
408
|
console.error('[weaver] No workflow file specified for watch');
|
|
399
409
|
process.exit(1);
|
|
@@ -412,10 +422,10 @@ async function handleWatch(opts) {
|
|
|
412
422
|
});
|
|
413
423
|
await daemon.start();
|
|
414
424
|
}
|
|
415
|
-
async function handleCron(opts) {
|
|
425
|
+
export async function handleCron(opts) {
|
|
416
426
|
if (!opts.cronSchedule) {
|
|
417
427
|
console.error('[weaver] No cron schedule specified');
|
|
418
|
-
console.error('Usage: weaver cron "*/5 * * * *" <file>');
|
|
428
|
+
console.error('Usage: flow-weaver weaver cron "*/5 * * * *" <file>');
|
|
419
429
|
process.exit(1);
|
|
420
430
|
}
|
|
421
431
|
if (!opts.file) {
|
|
@@ -436,18 +446,10 @@ async function handleCron(opts) {
|
|
|
436
446
|
});
|
|
437
447
|
await daemon.start();
|
|
438
448
|
}
|
|
439
|
-
|
|
440
|
-
const STAGE_ICONS = {
|
|
441
|
-
running: '\x1b[36m>\x1b[0m',
|
|
442
|
-
completed: '\x1b[32m+\x1b[0m',
|
|
443
|
-
failed: '\x1b[31mx\x1b[0m',
|
|
444
|
-
skipped: '\x1b[33m-\x1b[0m',
|
|
445
|
-
cancelled: '\x1b[33m~\x1b[0m',
|
|
446
|
-
};
|
|
447
|
-
async function handlePipeline(opts) {
|
|
449
|
+
export async function handlePipeline(opts) {
|
|
448
450
|
if (!opts.file) {
|
|
449
451
|
console.error('[weaver] No pipeline config specified');
|
|
450
|
-
console.error('Usage: weaver pipeline <config.json>');
|
|
452
|
+
console.error('Usage: flow-weaver weaver pipeline <config.json>');
|
|
451
453
|
process.exit(1);
|
|
452
454
|
}
|
|
453
455
|
let config;
|
|
@@ -508,8 +510,7 @@ async function handlePipeline(opts) {
|
|
|
508
510
|
process.exit(1);
|
|
509
511
|
}
|
|
510
512
|
}
|
|
511
|
-
|
|
512
|
-
async function handleDashboard(opts) {
|
|
513
|
+
export async function handleDashboard(opts) {
|
|
513
514
|
const dashboard = new DashboardServer({ port: opts.dashboardPort });
|
|
514
515
|
const port = await dashboard.start();
|
|
515
516
|
const url = dashboard.getUrl();
|
|
@@ -596,8 +597,7 @@ async function handleDashboard(opts) {
|
|
|
596
597
|
process.exit(1);
|
|
597
598
|
}
|
|
598
599
|
}
|
|
599
|
-
|
|
600
|
-
async function handleProviders() {
|
|
600
|
+
export async function handleProviders() {
|
|
601
601
|
await discoverProviders(defaultRegistry);
|
|
602
602
|
const providers = defaultRegistry.list();
|
|
603
603
|
if (providers.length === 0) {
|
|
@@ -622,64 +622,94 @@ async function handleProviders() {
|
|
|
622
622
|
console.log('');
|
|
623
623
|
}
|
|
624
624
|
}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
const
|
|
628
|
-
|
|
625
|
+
export async function handleEject() {
|
|
626
|
+
// Resolve the pack's own workflows/weaver.ts relative to this file
|
|
627
|
+
const packRoot = new URL('..', import.meta.url);
|
|
628
|
+
const srcPath = new URL('src/workflows/weaver.ts', packRoot);
|
|
629
|
+
let source;
|
|
629
630
|
try {
|
|
630
|
-
|
|
631
|
-
const orphans = store.checkOrphans();
|
|
632
|
-
for (const orphan of orphans) {
|
|
633
|
-
console.error(`[weaver] Recovered orphaned run ${orphan.id.slice(0, 8)} (${orphan.workflowFile}) killed at PID ${orphan.pid}`);
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
catch { /* non-fatal */ }
|
|
637
|
-
if (opts.showHelp) {
|
|
638
|
-
console.log(HELP);
|
|
639
|
-
process.exit(0);
|
|
631
|
+
source = fs.readFileSync(srcPath, 'utf-8');
|
|
640
632
|
}
|
|
641
|
-
|
|
633
|
+
catch {
|
|
634
|
+
// Fallback: try dist location (when running from compiled output)
|
|
635
|
+
const distPath = new URL('dist/workflows/weaver.ts', packRoot);
|
|
642
636
|
try {
|
|
643
|
-
|
|
644
|
-
const { default: pkg } = await import(pkgPath.href, { with: { type: 'json' } });
|
|
645
|
-
console.log(`weaver v${pkg.version}`);
|
|
637
|
+
source = fs.readFileSync(distPath, 'utf-8');
|
|
646
638
|
}
|
|
647
639
|
catch {
|
|
648
|
-
|
|
640
|
+
// Last resort: read the .js and note it
|
|
641
|
+
const jsPath = new URL('dist/workflows/weaver.js', packRoot);
|
|
642
|
+
try {
|
|
643
|
+
source = fs.readFileSync(jsPath, 'utf-8');
|
|
644
|
+
}
|
|
645
|
+
catch (err) {
|
|
646
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
647
|
+
console.error(`[weaver] Could not find managed workflow source: ${msg}`);
|
|
648
|
+
process.exit(1);
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
649
651
|
}
|
|
650
|
-
process.exit(0);
|
|
651
652
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
653
|
+
// Replace pack-relative imports with package imports
|
|
654
|
+
const rewritten = source
|
|
655
|
+
.replace(/from\s+['"]\.\.\/node-types\/load-config\.js['"]/g, "from '@synergenius/flowweaver-pack-weaver/node-types'")
|
|
656
|
+
.replace(/from\s+['"]\.\.\/node-types\/detect-provider\.js['"]/g, "from '@synergenius/flowweaver-pack-weaver/node-types'")
|
|
657
|
+
.replace(/from\s+['"]\.\.\/node-types\/resolve-target\.js['"]/g, "from '@synergenius/flowweaver-pack-weaver/node-types'")
|
|
658
|
+
.replace(/from\s+['"]\.\.\/node-types\/execute-target\.js['"]/g, "from '@synergenius/flowweaver-pack-weaver/node-types'")
|
|
659
|
+
.replace(/from\s+['"]\.\.\/node-types\/send-notify\.js['"]/g, "from '@synergenius/flowweaver-pack-weaver/node-types'")
|
|
660
|
+
.replace(/from\s+['"]\.\.\/node-types\/report\.js['"]/g, "from '@synergenius/flowweaver-pack-weaver/node-types'");
|
|
661
|
+
// Deduplicate import lines: collapse multiple imports from the same module
|
|
662
|
+
const lines = rewritten.split('\n');
|
|
663
|
+
const importMap = new Map();
|
|
664
|
+
const nonImportLines = [];
|
|
665
|
+
let pastImports = false;
|
|
666
|
+
for (const line of lines) {
|
|
667
|
+
const importMatch = line.match(/^import\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]\s*;?\s*$/);
|
|
668
|
+
if (importMatch && !pastImports) {
|
|
669
|
+
const names = importMatch[1].split(',').map((s) => s.trim()).filter(Boolean);
|
|
670
|
+
const mod = importMatch[2];
|
|
671
|
+
if (!importMap.has(mod))
|
|
672
|
+
importMap.set(mod, new Set());
|
|
673
|
+
for (const n of names)
|
|
674
|
+
importMap.get(mod).add(n);
|
|
675
|
+
}
|
|
676
|
+
else {
|
|
677
|
+
if (line.trim() !== '' && !line.match(/^import\s/))
|
|
678
|
+
pastImports = true;
|
|
679
|
+
nonImportLines.push(line);
|
|
680
|
+
}
|
|
675
681
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
682
|
+
const dedupedImports = [];
|
|
683
|
+
for (const [mod, names] of importMap) {
|
|
684
|
+
dedupedImports.push(`import { ${[...names].join(', ')} } from '${mod}';`);
|
|
679
685
|
}
|
|
686
|
+
const finalSource = [...dedupedImports, ...nonImportLines].join('\n');
|
|
687
|
+
const destPath = path.resolve(process.cwd(), 'weaver.ts');
|
|
688
|
+
fs.writeFileSync(destPath, finalSource, 'utf-8');
|
|
689
|
+
// Read pack version
|
|
690
|
+
let packVersion = 'unknown';
|
|
691
|
+
try {
|
|
692
|
+
const pkgPath = new URL('package.json', packRoot);
|
|
693
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
694
|
+
packVersion = pkg.version;
|
|
695
|
+
}
|
|
696
|
+
catch { /* ignore */ }
|
|
697
|
+
// Write/update .weaver-meta.json
|
|
698
|
+
const metaPath = path.resolve(process.cwd(), '.weaver-meta.json');
|
|
699
|
+
const meta = {
|
|
700
|
+
ejected: true,
|
|
701
|
+
packVersion,
|
|
702
|
+
workflowFile: 'weaver.ts',
|
|
703
|
+
};
|
|
704
|
+
fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2) + '\n', 'utf-8');
|
|
705
|
+
console.log(`[weaver] Ejected managed workflow to ${destPath}`);
|
|
706
|
+
console.log(`[weaver] Metadata written to ${metaPath}`);
|
|
707
|
+
console.log('[weaver] You can now customize weaver.ts freely.');
|
|
708
|
+
}
|
|
709
|
+
export async function handleRun(opts) {
|
|
680
710
|
if (!opts.file) {
|
|
681
711
|
console.error('[weaver] No workflow file specified');
|
|
682
|
-
console.error('Run "weaver --help" for usage');
|
|
712
|
+
console.error('Run "flow-weaver weaver --help" for usage');
|
|
683
713
|
process.exit(1);
|
|
684
714
|
}
|
|
685
715
|
const filePath = path.resolve(opts.file);
|
|
@@ -745,5 +775,207 @@ async function main() {
|
|
|
745
775
|
process.exit(1);
|
|
746
776
|
}
|
|
747
777
|
}
|
|
748
|
-
|
|
749
|
-
|
|
778
|
+
export async function handleBot(opts) {
|
|
779
|
+
if (!opts.botTask) {
|
|
780
|
+
console.error('[weaver] No task specified');
|
|
781
|
+
console.error('Usage: flow-weaver weaver bot "Create a workflow that..."');
|
|
782
|
+
process.exit(1);
|
|
783
|
+
}
|
|
784
|
+
const task = {
|
|
785
|
+
instruction: opts.botTask,
|
|
786
|
+
mode: opts.botFile ? 'modify' : 'create',
|
|
787
|
+
targets: opts.botFile ? [opts.botFile] : undefined,
|
|
788
|
+
options: {
|
|
789
|
+
template: opts.botTemplate,
|
|
790
|
+
batchCount: opts.botBatch,
|
|
791
|
+
dryRun: opts.dryRun,
|
|
792
|
+
autoApprove: opts.autoApprove,
|
|
793
|
+
},
|
|
794
|
+
};
|
|
795
|
+
// Use the batch workflow if --batch specified
|
|
796
|
+
const workflowName = opts.botBatch ? 'weaver-bot-batch' : 'weaver-bot';
|
|
797
|
+
// Find the workflow file in the pack
|
|
798
|
+
const packRoot = new URL('..', import.meta.url);
|
|
799
|
+
let workflowPath;
|
|
800
|
+
try {
|
|
801
|
+
workflowPath = fileURLToPath(new URL(`src/workflows/${workflowName}.ts`, packRoot));
|
|
802
|
+
const { existsSync } = await import('node:fs');
|
|
803
|
+
if (!existsSync(workflowPath)) {
|
|
804
|
+
workflowPath = fileURLToPath(new URL(`dist/workflows/${workflowName}.js`, packRoot));
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
catch {
|
|
808
|
+
workflowPath = fileURLToPath(new URL(`dist/workflows/${workflowName}.js`, packRoot));
|
|
809
|
+
}
|
|
810
|
+
const config = await loadConfig(opts.configPath);
|
|
811
|
+
const nodeTimings = new Map();
|
|
812
|
+
// Start dashboard if requested
|
|
813
|
+
let dashboard = null;
|
|
814
|
+
if (opts.dashboard) {
|
|
815
|
+
dashboard = new DashboardServer({ port: opts.dashboardPort ?? 4242 });
|
|
816
|
+
const port = await dashboard.start();
|
|
817
|
+
console.log(`[weaver] Dashboard: http://127.0.0.1:${port}`);
|
|
818
|
+
openBrowser(`http://127.0.0.1:${port}`);
|
|
819
|
+
dashboard.broadcastWorkflowStart(workflowPath);
|
|
820
|
+
}
|
|
821
|
+
const onEvent = opts.quiet
|
|
822
|
+
? undefined
|
|
823
|
+
: (event) => {
|
|
824
|
+
const icon = STATUS_ICONS[event.type] ?? ' ';
|
|
825
|
+
const label = event.nodeType ? `${event.nodeId} (${event.nodeType})` : event.nodeId;
|
|
826
|
+
if (dashboard)
|
|
827
|
+
dashboard.broadcastExecution(event);
|
|
828
|
+
if (event.type === 'node-start') {
|
|
829
|
+
nodeTimings.set(event.nodeId, event.timestamp);
|
|
830
|
+
if (opts.verbose)
|
|
831
|
+
console.log(` ${icon} ${label}`);
|
|
832
|
+
}
|
|
833
|
+
else if (event.type === 'node-complete') {
|
|
834
|
+
const start = nodeTimings.get(event.nodeId);
|
|
835
|
+
const dur = start ? ` ${formatDuration(event.timestamp - start)}` : '';
|
|
836
|
+
console.log(` ${icon} ${label}${dur}`);
|
|
837
|
+
}
|
|
838
|
+
else if (event.type === 'node-error') {
|
|
839
|
+
console.log(` ${icon} ${label}: ${event.error ?? 'unknown error'}`);
|
|
840
|
+
}
|
|
841
|
+
};
|
|
842
|
+
const startTime = Date.now();
|
|
843
|
+
if (!opts.quiet) {
|
|
844
|
+
console.log(`[weaver] Bot: ${opts.botTask.slice(0, 80)}`);
|
|
845
|
+
}
|
|
846
|
+
try {
|
|
847
|
+
const result = await runWorkflow(workflowPath, {
|
|
848
|
+
params: { taskJson: JSON.stringify(task), projectDir: opts.file ?? process.cwd() },
|
|
849
|
+
verbose: opts.verbose,
|
|
850
|
+
dryRun: opts.dryRun,
|
|
851
|
+
config,
|
|
852
|
+
onEvent,
|
|
853
|
+
onNotificationError: (channel, _event, error) => {
|
|
854
|
+
console.error(`[weaver] Notification error (${channel}): ${error}`);
|
|
855
|
+
},
|
|
856
|
+
});
|
|
857
|
+
const elapsed = formatDuration(Date.now() - startTime);
|
|
858
|
+
if (!opts.quiet) {
|
|
859
|
+
const color = result.success ? '\x1b[32m' : '\x1b[31m';
|
|
860
|
+
console.log(`\n${color}Bot: ${result.outcome}\x1b[0m (${elapsed})`);
|
|
861
|
+
console.log(` ${result.summary}`);
|
|
862
|
+
}
|
|
863
|
+
if (dashboard) {
|
|
864
|
+
dashboard.broadcastWorkflowComplete(result.summary ?? '', result.success);
|
|
865
|
+
await dashboard.stop();
|
|
866
|
+
}
|
|
867
|
+
process.exit(result.success ? 0 : 1);
|
|
868
|
+
}
|
|
869
|
+
catch (err) {
|
|
870
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
871
|
+
console.error(`\x1b[31m[weaver] Fatal: ${msg}\x1b[0m`);
|
|
872
|
+
if (dashboard) {
|
|
873
|
+
dashboard.broadcastWorkflowError(msg);
|
|
874
|
+
await dashboard.stop();
|
|
875
|
+
}
|
|
876
|
+
process.exit(1);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
export async function handleSession(opts) {
|
|
880
|
+
const packRoot = new URL('..', import.meta.url);
|
|
881
|
+
let workflowPath;
|
|
882
|
+
try {
|
|
883
|
+
workflowPath = fileURLToPath(new URL('src/workflows/weaver-bot-session.ts', packRoot));
|
|
884
|
+
const { existsSync } = await import('node:fs');
|
|
885
|
+
if (!existsSync(workflowPath)) {
|
|
886
|
+
workflowPath = fileURLToPath(new URL('dist/workflows/weaver-bot-session.js', packRoot));
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
catch {
|
|
890
|
+
workflowPath = fileURLToPath(new URL('dist/workflows/weaver-bot-session.js', packRoot));
|
|
891
|
+
}
|
|
892
|
+
const config = await loadConfig(opts.configPath);
|
|
893
|
+
if (!opts.quiet) {
|
|
894
|
+
console.log('[weaver] Starting bot session (Ctrl+C to stop)');
|
|
895
|
+
console.log('[weaver] Add tasks with: flow-weaver weaver queue add "task"');
|
|
896
|
+
}
|
|
897
|
+
try {
|
|
898
|
+
const result = await runWorkflow(workflowPath, {
|
|
899
|
+
params: { projectDir: opts.file ?? process.cwd() },
|
|
900
|
+
verbose: opts.verbose,
|
|
901
|
+
dryRun: opts.dryRun,
|
|
902
|
+
config,
|
|
903
|
+
});
|
|
904
|
+
if (!opts.quiet) {
|
|
905
|
+
const color = result.success ? '\x1b[32m' : '\x1b[31m';
|
|
906
|
+
console.log(`${color}Session: ${result.outcome}\x1b[0m`);
|
|
907
|
+
}
|
|
908
|
+
process.exit(result.success ? 0 : 1);
|
|
909
|
+
}
|
|
910
|
+
catch (err) {
|
|
911
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
912
|
+
console.error(`\x1b[31m[weaver] Fatal: ${msg}\x1b[0m`);
|
|
913
|
+
process.exit(1);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
export async function handleSteer(opts) {
|
|
917
|
+
const { SteeringController } = await import('./bot/steering.js');
|
|
918
|
+
const controller = new SteeringController();
|
|
919
|
+
const subcommand = opts.botTask;
|
|
920
|
+
if (!subcommand || !['pause', 'resume', 'cancel', 'redirect', 'queue'].includes(subcommand)) {
|
|
921
|
+
console.error('[weaver] Usage: flow-weaver weaver steer <pause|resume|cancel|redirect|queue> [payload]');
|
|
922
|
+
process.exit(1);
|
|
923
|
+
}
|
|
924
|
+
const command = {
|
|
925
|
+
command: subcommand,
|
|
926
|
+
payload: opts.botFile,
|
|
927
|
+
timestamp: Date.now(),
|
|
928
|
+
};
|
|
929
|
+
controller.write(command);
|
|
930
|
+
console.log(`[weaver] Steering command sent: ${subcommand}${opts.botFile ? ' "' + opts.botFile + '"' : ''}`);
|
|
931
|
+
}
|
|
932
|
+
export async function handleQueue(opts) {
|
|
933
|
+
const { TaskQueue } = await import('./bot/task-queue.js');
|
|
934
|
+
const queue = new TaskQueue();
|
|
935
|
+
const action = opts.botTask;
|
|
936
|
+
if (!action || !['add', 'list', 'clear', 'remove'].includes(action)) {
|
|
937
|
+
console.error('[weaver] Usage: flow-weaver weaver queue <add|list|clear|remove> [task|id]');
|
|
938
|
+
process.exit(1);
|
|
939
|
+
}
|
|
940
|
+
switch (action) {
|
|
941
|
+
case 'add': {
|
|
942
|
+
const instruction = opts.botFile;
|
|
943
|
+
if (!instruction) {
|
|
944
|
+
console.error('[weaver] Usage: flow-weaver weaver queue add "task instruction"');
|
|
945
|
+
process.exit(1);
|
|
946
|
+
}
|
|
947
|
+
const id = queue.add({ instruction, priority: 0 });
|
|
948
|
+
console.log(`[weaver] Task added: ${id}`);
|
|
949
|
+
break;
|
|
950
|
+
}
|
|
951
|
+
case 'list': {
|
|
952
|
+
const tasks = queue.list();
|
|
953
|
+
if (tasks.length === 0) {
|
|
954
|
+
console.log('No tasks in queue.');
|
|
955
|
+
}
|
|
956
|
+
else {
|
|
957
|
+
console.log('ID'.padEnd(10) + 'STATUS'.padEnd(12) + 'INSTRUCTION');
|
|
958
|
+
for (const t of tasks) {
|
|
959
|
+
console.log(t.id.padEnd(10) + t.status.padEnd(12) + t.instruction.slice(0, 60));
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
case 'clear': {
|
|
965
|
+
const count = queue.clear();
|
|
966
|
+
console.log(`Cleared ${count} task(s).`);
|
|
967
|
+
break;
|
|
968
|
+
}
|
|
969
|
+
case 'remove': {
|
|
970
|
+
const id = opts.botFile;
|
|
971
|
+
if (!id) {
|
|
972
|
+
console.error('[weaver] Usage: flow-weaver weaver queue remove <id>');
|
|
973
|
+
process.exit(1);
|
|
974
|
+
}
|
|
975
|
+
const removed = queue.remove(id);
|
|
976
|
+
console.log(removed ? `Removed task ${id}.` : `No task found with id "${id}".`);
|
|
977
|
+
break;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
//# sourceMappingURL=cli-handlers.js.map
|