@synergenius/flow-weaver-pack-weaver 0.8.1
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/LICENSE +204 -0
- package/README.md +167 -0
- package/dist/bot/agent-provider.d.ts +34 -0
- package/dist/bot/agent-provider.d.ts.map +1 -0
- package/dist/bot/agent-provider.js +218 -0
- package/dist/bot/agent-provider.js.map +1 -0
- package/dist/bot/ai-client.d.ts +15 -0
- package/dist/bot/ai-client.d.ts.map +1 -0
- package/dist/bot/ai-client.js +128 -0
- package/dist/bot/ai-client.js.map +1 -0
- package/dist/bot/approvals.d.ts +22 -0
- package/dist/bot/approvals.d.ts.map +1 -0
- package/dist/bot/approvals.js +187 -0
- package/dist/bot/approvals.js.map +1 -0
- package/dist/bot/audit-logger.d.ts +5 -0
- package/dist/bot/audit-logger.d.ts.map +1 -0
- package/dist/bot/audit-logger.js +42 -0
- package/dist/bot/audit-logger.js.map +1 -0
- package/dist/bot/audit-store.d.ts +13 -0
- package/dist/bot/audit-store.d.ts.map +1 -0
- package/dist/bot/audit-store.js +59 -0
- package/dist/bot/audit-store.js.map +1 -0
- package/dist/bot/bot-agent-channel.d.ts +46 -0
- package/dist/bot/bot-agent-channel.d.ts.map +1 -0
- package/dist/bot/bot-agent-channel.js +58 -0
- package/dist/bot/bot-agent-channel.js.map +1 -0
- package/dist/bot/cli-provider.d.ts +29 -0
- package/dist/bot/cli-provider.d.ts.map +1 -0
- package/dist/bot/cli-provider.js +132 -0
- package/dist/bot/cli-provider.js.map +1 -0
- package/dist/bot/cli-stream-parser.d.ts +11 -0
- package/dist/bot/cli-stream-parser.d.ts.map +1 -0
- package/dist/bot/cli-stream-parser.js +53 -0
- package/dist/bot/cli-stream-parser.js.map +1 -0
- package/dist/bot/cost-store.d.ts +18 -0
- package/dist/bot/cost-store.d.ts.map +1 -0
- package/dist/bot/cost-store.js +81 -0
- package/dist/bot/cost-store.js.map +1 -0
- package/dist/bot/cost-tracker.d.ts +18 -0
- package/dist/bot/cost-tracker.d.ts.map +1 -0
- package/dist/bot/cost-tracker.js +60 -0
- package/dist/bot/cost-tracker.js.map +1 -0
- package/dist/bot/cron-parser.d.ts +5 -0
- package/dist/bot/cron-parser.d.ts.map +1 -0
- package/dist/bot/cron-parser.js +141 -0
- package/dist/bot/cron-parser.js.map +1 -0
- package/dist/bot/cron-scheduler.d.ts +12 -0
- package/dist/bot/cron-scheduler.d.ts.map +1 -0
- package/dist/bot/cron-scheduler.js +43 -0
- package/dist/bot/cron-scheduler.js.map +1 -0
- package/dist/bot/dashboard.d.ts +34 -0
- package/dist/bot/dashboard.d.ts.map +1 -0
- package/dist/bot/dashboard.js +602 -0
- package/dist/bot/dashboard.js.map +1 -0
- package/dist/bot/design-checker.d.ts +24 -0
- package/dist/bot/design-checker.d.ts.map +1 -0
- package/dist/bot/design-checker.js +269 -0
- package/dist/bot/design-checker.js.map +1 -0
- package/dist/bot/file-lock.d.ts +7 -0
- package/dist/bot/file-lock.d.ts.map +1 -0
- package/dist/bot/file-lock.js +64 -0
- package/dist/bot/file-lock.js.map +1 -0
- package/dist/bot/file-validator.d.ts +10 -0
- package/dist/bot/file-validator.d.ts.map +1 -0
- package/dist/bot/file-validator.js +27 -0
- package/dist/bot/file-validator.js.map +1 -0
- package/dist/bot/file-watcher.d.ts +24 -0
- package/dist/bot/file-watcher.d.ts.map +1 -0
- package/dist/bot/file-watcher.js +98 -0
- package/dist/bot/file-watcher.js.map +1 -0
- package/dist/bot/fw-api.d.ts +8 -0
- package/dist/bot/fw-api.d.ts.map +1 -0
- package/dist/bot/fw-api.js +12 -0
- package/dist/bot/fw-api.js.map +1 -0
- package/dist/bot/genesis-prompt-context.d.ts +31 -0
- package/dist/bot/genesis-prompt-context.d.ts.map +1 -0
- package/dist/bot/genesis-prompt-context.js +121 -0
- package/dist/bot/genesis-prompt-context.js.map +1 -0
- package/dist/bot/genesis-store.d.ts +28 -0
- package/dist/bot/genesis-store.d.ts.map +1 -0
- package/dist/bot/genesis-store.js +154 -0
- package/dist/bot/genesis-store.js.map +1 -0
- package/dist/bot/index.d.ts +38 -0
- package/dist/bot/index.d.ts.map +1 -0
- package/dist/bot/index.js +37 -0
- package/dist/bot/index.js.map +1 -0
- package/dist/bot/notifications.d.ts +20 -0
- package/dist/bot/notifications.d.ts.map +1 -0
- package/dist/bot/notifications.js +215 -0
- package/dist/bot/notifications.js.map +1 -0
- package/dist/bot/pipeline-runner.d.ts +22 -0
- package/dist/bot/pipeline-runner.d.ts.map +1 -0
- package/dist/bot/pipeline-runner.js +263 -0
- package/dist/bot/pipeline-runner.js.map +1 -0
- package/dist/bot/provider-registry.d.ts +26 -0
- package/dist/bot/provider-registry.d.ts.map +1 -0
- package/dist/bot/provider-registry.js +175 -0
- package/dist/bot/provider-registry.js.map +1 -0
- package/dist/bot/run-store.d.ts +25 -0
- package/dist/bot/run-store.d.ts.map +1 -0
- package/dist/bot/run-store.js +156 -0
- package/dist/bot/run-store.js.map +1 -0
- package/dist/bot/runner.d.ts +13 -0
- package/dist/bot/runner.d.ts.map +1 -0
- package/dist/bot/runner.js +244 -0
- package/dist/bot/runner.js.map +1 -0
- 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 +65 -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 +40 -0
- package/dist/bot/steering.js.map +1 -0
- package/dist/bot/step-executor.d.ts +10 -0
- package/dist/bot/step-executor.d.ts.map +1 -0
- package/dist/bot/step-executor.js +30 -0
- package/dist/bot/step-executor.js.map +1 -0
- package/dist/bot/system-prompt.d.ts +19 -0
- package/dist/bot/system-prompt.d.ts.map +1 -0
- package/dist/bot/system-prompt.js +222 -0
- package/dist/bot/system-prompt.js.map +1 -0
- 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 +98 -0
- package/dist/bot/task-queue.js.map +1 -0
- package/dist/bot/types.d.ts +478 -0
- package/dist/bot/types.d.ts.map +1 -0
- package/dist/bot/types.js +2 -0
- package/dist/bot/types.js.map +1 -0
- package/dist/bot/utils.d.ts +2 -0
- package/dist/bot/utils.d.ts.map +1 -0
- package/dist/bot/utils.js +20 -0
- package/dist/bot/utils.js.map +1 -0
- package/dist/bot/watch-daemon.d.ts +19 -0
- package/dist/bot/watch-daemon.d.ts.map +1 -0
- package/dist/bot/watch-daemon.js +178 -0
- package/dist/bot/watch-daemon.js.map +1 -0
- package/dist/bot/web-approval.d.ts +19 -0
- package/dist/bot/web-approval.d.ts.map +1 -0
- package/dist/bot/web-approval.js +207 -0
- package/dist/bot/web-approval.js.map +1 -0
- package/dist/cli-bridge.d.ts +2 -0
- package/dist/cli-bridge.d.ts.map +1 -0
- package/dist/cli-bridge.js +30 -0
- package/dist/cli-bridge.js.map +1 -0
- package/dist/cli-handlers.d.ts +79 -0
- package/dist/cli-handlers.d.ts.map +1 -0
- package/dist/cli-handlers.js +1335 -0
- package/dist/cli-handlers.js.map +1 -0
- 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-config.md +135 -0
- package/dist/docs/weaver-config.md +141 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-tools.d.ts +13 -0
- package/dist/mcp-tools.d.ts.map +1 -0
- package/dist/mcp-tools.js +197 -0
- package/dist/mcp-tools.js.map +1 -0
- package/dist/node-types/abort-task.d.ts +15 -0
- package/dist/node-types/abort-task.d.ts.map +1 -0
- package/dist/node-types/abort-task.js +28 -0
- package/dist/node-types/abort-task.js.map +1 -0
- package/dist/node-types/approval-gate.d.ts +18 -0
- package/dist/node-types/approval-gate.d.ts.map +1 -0
- package/dist/node-types/approval-gate.js +80 -0
- package/dist/node-types/approval-gate.js.map +1 -0
- package/dist/node-types/bot-report.d.ts +20 -0
- package/dist/node-types/bot-report.d.ts.map +1 -0
- package/dist/node-types/bot-report.js +67 -0
- package/dist/node-types/bot-report.js.map +1 -0
- package/dist/node-types/build-context.d.ts +16 -0
- package/dist/node-types/build-context.d.ts.map +1 -0
- package/dist/node-types/build-context.js +64 -0
- package/dist/node-types/build-context.js.map +1 -0
- package/dist/node-types/detect-provider.d.ts +17 -0
- package/dist/node-types/detect-provider.d.ts.map +1 -0
- package/dist/node-types/detect-provider.js +71 -0
- package/dist/node-types/detect-provider.js.map +1 -0
- package/dist/node-types/exec-validate-retry.d.ts +17 -0
- package/dist/node-types/exec-validate-retry.d.ts.map +1 -0
- package/dist/node-types/exec-validate-retry.js +147 -0
- package/dist/node-types/exec-validate-retry.js.map +1 -0
- package/dist/node-types/execute-plan.d.ts +26 -0
- package/dist/node-types/execute-plan.d.ts.map +1 -0
- package/dist/node-types/execute-plan.js +120 -0
- package/dist/node-types/execute-plan.js.map +1 -0
- package/dist/node-types/execute-target.d.ts +16 -0
- package/dist/node-types/execute-target.d.ts.map +1 -0
- package/dist/node-types/execute-target.js +238 -0
- package/dist/node-types/execute-target.js.map +1 -0
- package/dist/node-types/fix-errors.d.ts +24 -0
- package/dist/node-types/fix-errors.d.ts.map +1 -0
- package/dist/node-types/fix-errors.js +49 -0
- package/dist/node-types/fix-errors.js.map +1 -0
- package/dist/node-types/genesis-apply-retry.d.ts +27 -0
- package/dist/node-types/genesis-apply-retry.d.ts.map +1 -0
- package/dist/node-types/genesis-apply-retry.js +97 -0
- package/dist/node-types/genesis-apply-retry.js.map +1 -0
- package/dist/node-types/genesis-apply.d.ts +29 -0
- package/dist/node-types/genesis-apply.d.ts.map +1 -0
- package/dist/node-types/genesis-apply.js +76 -0
- package/dist/node-types/genesis-apply.js.map +1 -0
- package/dist/node-types/genesis-approve.d.ts +19 -0
- package/dist/node-types/genesis-approve.d.ts.map +1 -0
- package/dist/node-types/genesis-approve.js +59 -0
- package/dist/node-types/genesis-approve.js.map +1 -0
- package/dist/node-types/genesis-check-stabilize.d.ts +16 -0
- package/dist/node-types/genesis-check-stabilize.d.ts.map +1 -0
- package/dist/node-types/genesis-check-stabilize.js +32 -0
- package/dist/node-types/genesis-check-stabilize.js.map +1 -0
- package/dist/node-types/genesis-check-threshold.d.ts +15 -0
- package/dist/node-types/genesis-check-threshold.d.ts.map +1 -0
- package/dist/node-types/genesis-check-threshold.js +29 -0
- package/dist/node-types/genesis-check-threshold.js.map +1 -0
- package/dist/node-types/genesis-commit.d.ts +17 -0
- package/dist/node-types/genesis-commit.d.ts.map +1 -0
- package/dist/node-types/genesis-commit.js +59 -0
- package/dist/node-types/genesis-commit.js.map +1 -0
- package/dist/node-types/genesis-compile-validate.d.ts +26 -0
- package/dist/node-types/genesis-compile-validate.d.ts.map +1 -0
- package/dist/node-types/genesis-compile-validate.js +60 -0
- package/dist/node-types/genesis-compile-validate.js.map +1 -0
- package/dist/node-types/genesis-diff-fingerprint.d.ts +15 -0
- package/dist/node-types/genesis-diff-fingerprint.d.ts.map +1 -0
- package/dist/node-types/genesis-diff-fingerprint.js +59 -0
- package/dist/node-types/genesis-diff-fingerprint.js.map +1 -0
- package/dist/node-types/genesis-diff-workflow.d.ts +15 -0
- package/dist/node-types/genesis-diff-workflow.d.ts.map +1 -0
- package/dist/node-types/genesis-diff-workflow.js +67 -0
- package/dist/node-types/genesis-diff-workflow.js.map +1 -0
- package/dist/node-types/genesis-escrow-grace.d.ts +15 -0
- package/dist/node-types/genesis-escrow-grace.d.ts.map +1 -0
- package/dist/node-types/genesis-escrow-grace.js +52 -0
- package/dist/node-types/genesis-escrow-grace.js.map +1 -0
- package/dist/node-types/genesis-escrow-migrate.d.ts +21 -0
- package/dist/node-types/genesis-escrow-migrate.d.ts.map +1 -0
- package/dist/node-types/genesis-escrow-migrate.js +116 -0
- package/dist/node-types/genesis-escrow-migrate.js.map +1 -0
- package/dist/node-types/genesis-escrow-recover.d.ts +15 -0
- package/dist/node-types/genesis-escrow-recover.d.ts.map +1 -0
- package/dist/node-types/genesis-escrow-recover.js +90 -0
- package/dist/node-types/genesis-escrow-recover.js.map +1 -0
- package/dist/node-types/genesis-escrow-stage.d.ts +17 -0
- package/dist/node-types/genesis-escrow-stage.d.ts.map +1 -0
- package/dist/node-types/genesis-escrow-stage.js +86 -0
- package/dist/node-types/genesis-escrow-stage.js.map +1 -0
- package/dist/node-types/genesis-escrow-validate.d.ts +17 -0
- package/dist/node-types/genesis-escrow-validate.d.ts.map +1 -0
- package/dist/node-types/genesis-escrow-validate.js +110 -0
- package/dist/node-types/genesis-escrow-validate.js.map +1 -0
- package/dist/node-types/genesis-load-config.d.ts +17 -0
- package/dist/node-types/genesis-load-config.d.ts.map +1 -0
- package/dist/node-types/genesis-load-config.js +36 -0
- package/dist/node-types/genesis-load-config.js.map +1 -0
- package/dist/node-types/genesis-observe.d.ts +18 -0
- package/dist/node-types/genesis-observe.d.ts.map +1 -0
- package/dist/node-types/genesis-observe.js +103 -0
- package/dist/node-types/genesis-observe.js.map +1 -0
- package/dist/node-types/genesis-propose.d.ts +17 -0
- package/dist/node-types/genesis-propose.d.ts.map +1 -0
- package/dist/node-types/genesis-propose.js +69 -0
- package/dist/node-types/genesis-propose.js.map +1 -0
- package/dist/node-types/genesis-report.d.ts +20 -0
- package/dist/node-types/genesis-report.d.ts.map +1 -0
- package/dist/node-types/genesis-report.js +87 -0
- package/dist/node-types/genesis-report.js.map +1 -0
- package/dist/node-types/genesis-snapshot.d.ts +15 -0
- package/dist/node-types/genesis-snapshot.d.ts.map +1 -0
- package/dist/node-types/genesis-snapshot.js +26 -0
- package/dist/node-types/genesis-snapshot.js.map +1 -0
- package/dist/node-types/genesis-try-apply.d.ts +18 -0
- package/dist/node-types/genesis-try-apply.d.ts.map +1 -0
- package/dist/node-types/genesis-try-apply.js +142 -0
- package/dist/node-types/genesis-try-apply.js.map +1 -0
- package/dist/node-types/genesis-update-history.d.ts +15 -0
- package/dist/node-types/genesis-update-history.d.ts.map +1 -0
- package/dist/node-types/genesis-update-history.js +70 -0
- package/dist/node-types/genesis-update-history.js.map +1 -0
- package/dist/node-types/genesis-validate-proposal.d.ts +16 -0
- package/dist/node-types/genesis-validate-proposal.d.ts.map +1 -0
- package/dist/node-types/genesis-validate-proposal.js +109 -0
- package/dist/node-types/genesis-validate-proposal.js.map +1 -0
- package/dist/node-types/git-ops.d.ts +15 -0
- package/dist/node-types/git-ops.d.ts.map +1 -0
- package/dist/node-types/git-ops.js +69 -0
- package/dist/node-types/git-ops.js.map +1 -0
- package/dist/node-types/index.d.ts +37 -0
- package/dist/node-types/index.d.ts.map +1 -0
- package/dist/node-types/index.js +37 -0
- package/dist/node-types/index.js.map +1 -0
- package/dist/node-types/load-config.d.ts +17 -0
- package/dist/node-types/load-config.d.ts.map +1 -0
- package/dist/node-types/load-config.js +27 -0
- package/dist/node-types/load-config.js.map +1 -0
- package/dist/node-types/plan-task.d.ts +17 -0
- package/dist/node-types/plan-task.d.ts.map +1 -0
- package/dist/node-types/plan-task.js +55 -0
- package/dist/node-types/plan-task.js.map +1 -0
- package/dist/node-types/read-workflow.d.ts +15 -0
- package/dist/node-types/read-workflow.d.ts.map +1 -0
- package/dist/node-types/read-workflow.js +60 -0
- package/dist/node-types/read-workflow.js.map +1 -0
- package/dist/node-types/receive-task.d.ts +20 -0
- package/dist/node-types/receive-task.d.ts.map +1 -0
- package/dist/node-types/receive-task.js +69 -0
- package/dist/node-types/receive-task.js.map +1 -0
- package/dist/node-types/report.d.ts +14 -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 +16 -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 +14 -0
- package/dist/node-types/route-task.d.ts.map +1 -0
- package/dist/node-types/route-task.js +22 -0
- package/dist/node-types/route-task.js.map +1 -0
- package/dist/node-types/send-notify.d.ts +14 -0
- package/dist/node-types/send-notify.d.ts.map +1 -0
- package/dist/node-types/send-notify.js +71 -0
- package/dist/node-types/send-notify.js.map +1 -0
- package/dist/node-types/validate-result.d.ts +24 -0
- package/dist/node-types/validate-result.d.ts.map +1 -0
- package/dist/node-types/validate-result.js +38 -0
- package/dist/node-types/validate-result.js.map +1 -0
- package/dist/templates/index.d.ts +5 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +4 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/weaver-bot-template.d.ts +11 -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 +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/workflows/genesis-task.d.ts +62 -0
- package/dist/workflows/genesis-task.d.ts.map +1 -0
- package/dist/workflows/genesis-task.js +64 -0
- package/dist/workflows/genesis-task.js.map +1 -0
- package/dist/workflows/index.d.ts +4 -0
- package/dist/workflows/index.d.ts.map +1 -0
- package/dist/workflows/index.js +4 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/weaver-bot-batch.d.ts +49 -0
- package/dist/workflows/weaver-bot-batch.d.ts.map +1 -0
- package/dist/workflows/weaver-bot-batch.js +49 -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 +61 -0
- package/dist/workflows/weaver-bot.d.ts.map +1 -0
- package/dist/workflows/weaver-bot.js +61 -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 +1001 -0
- package/package.json +78 -0
- package/src/bot/agent-provider.ts +273 -0
- package/src/bot/ai-client.ts +153 -0
- package/src/bot/approvals.ts +273 -0
- package/src/bot/audit-logger.ts +45 -0
- package/src/bot/audit-store.ts +69 -0
- package/src/bot/bot-agent-channel.ts +99 -0
- package/src/bot/cli-provider.ts +169 -0
- package/src/bot/cli-stream-parser.ts +59 -0
- package/src/bot/cost-store.ts +92 -0
- package/src/bot/cost-tracker.ts +72 -0
- package/src/bot/cron-parser.ts +153 -0
- package/src/bot/cron-scheduler.ts +48 -0
- package/src/bot/dashboard.ts +658 -0
- package/src/bot/design-checker.ts +327 -0
- package/src/bot/file-lock.ts +73 -0
- package/src/bot/file-validator.ts +41 -0
- package/src/bot/file-watcher.ts +103 -0
- package/src/bot/fw-api.ts +18 -0
- package/src/bot/genesis-prompt-context.ts +135 -0
- package/src/bot/genesis-store.ts +180 -0
- package/src/bot/index.ts +127 -0
- package/src/bot/notifications.ts +263 -0
- package/src/bot/pipeline-runner.ts +324 -0
- package/src/bot/provider-registry.ts +236 -0
- package/src/bot/run-store.ts +169 -0
- package/src/bot/runner.ts +311 -0
- package/src/bot/session-state.ts +73 -0
- package/src/bot/steering.ts +44 -0
- package/src/bot/step-executor.ts +34 -0
- package/src/bot/system-prompt.ts +280 -0
- package/src/bot/task-queue.ts +111 -0
- package/src/bot/types.ts +571 -0
- package/src/bot/utils.ts +17 -0
- package/src/bot/watch-daemon.ts +203 -0
- package/src/bot/web-approval.ts +240 -0
- package/src/cli-bridge.ts +41 -0
- package/src/cli-handlers.ts +1445 -0
- package/src/docs/weaver-config.md +135 -0
- package/src/index.ts +177 -0
- package/src/mcp-tools.ts +274 -0
- package/src/node-types/abort-task.ts +31 -0
- package/src/node-types/approval-gate.ts +95 -0
- package/src/node-types/bot-report.ts +82 -0
- package/src/node-types/build-context.ts +65 -0
- package/src/node-types/detect-provider.ts +77 -0
- package/src/node-types/exec-validate-retry.ts +170 -0
- package/src/node-types/execute-plan.ts +130 -0
- package/src/node-types/execute-target.ts +256 -0
- package/src/node-types/fix-errors.ts +63 -0
- package/src/node-types/genesis-apply-retry.ts +133 -0
- package/src/node-types/genesis-apply.ts +96 -0
- package/src/node-types/genesis-approve.ts +73 -0
- package/src/node-types/genesis-check-stabilize.ts +37 -0
- package/src/node-types/genesis-check-threshold.ts +34 -0
- package/src/node-types/genesis-commit.ts +71 -0
- package/src/node-types/genesis-compile-validate.ts +77 -0
- package/src/node-types/genesis-diff-fingerprint.ts +67 -0
- package/src/node-types/genesis-diff-workflow.ts +71 -0
- package/src/node-types/genesis-escrow-grace.ts +62 -0
- package/src/node-types/genesis-escrow-migrate.ts +138 -0
- package/src/node-types/genesis-escrow-recover.ts +99 -0
- package/src/node-types/genesis-escrow-stage.ts +104 -0
- package/src/node-types/genesis-escrow-validate.ts +120 -0
- package/src/node-types/genesis-load-config.ts +44 -0
- package/src/node-types/genesis-observe.ts +119 -0
- package/src/node-types/genesis-propose.ts +86 -0
- package/src/node-types/genesis-report.ts +95 -0
- package/src/node-types/genesis-snapshot.ts +30 -0
- package/src/node-types/genesis-try-apply.ts +165 -0
- package/src/node-types/genesis-update-history.ts +72 -0
- package/src/node-types/genesis-validate-proposal.ts +124 -0
- package/src/node-types/git-ops.ts +72 -0
- package/src/node-types/index.ts +36 -0
- package/src/node-types/load-config.ts +27 -0
- package/src/node-types/plan-task.ts +66 -0
- package/src/node-types/read-workflow.ts +68 -0
- package/src/node-types/receive-task.ts +92 -0
- package/src/node-types/report.ts +25 -0
- package/src/node-types/resolve-target.ts +64 -0
- package/src/node-types/route-task.ts +25 -0
- package/src/node-types/send-notify.ts +75 -0
- package/src/node-types/validate-result.ts +49 -0
- package/src/templates/index.ts +5 -0
- package/src/templates/weaver-bot-template.ts +106 -0
- package/src/workflows/genesis-task.ts +91 -0
- package/src/workflows/index.ts +3 -0
- package/src/workflows/weaver-bot-batch.ts +65 -0
- package/src/workflows/weaver-bot.ts +79 -0
- package/templates.js +1 -0
|
@@ -0,0 +1,1335 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { runWorkflow } from './bot/runner.js';
|
|
5
|
+
import { RunStore } from './bot/run-store.js';
|
|
6
|
+
import { CostStore } from './bot/cost-store.js';
|
|
7
|
+
import { defaultRegistry, discoverProviders } from './bot/provider-registry.js';
|
|
8
|
+
import { WatchDaemon } from './bot/watch-daemon.js';
|
|
9
|
+
import { PipelineRunner } from './bot/pipeline-runner.js';
|
|
10
|
+
import { DashboardServer } from './bot/dashboard.js';
|
|
11
|
+
import { openBrowser } from './bot/utils.js';
|
|
12
|
+
import { AuditStore } from './bot/audit-store.js';
|
|
13
|
+
export function parseArgs(argv) {
|
|
14
|
+
const result = {
|
|
15
|
+
command: 'run',
|
|
16
|
+
file: undefined,
|
|
17
|
+
verbose: false,
|
|
18
|
+
dryRun: false,
|
|
19
|
+
quiet: false,
|
|
20
|
+
params: undefined,
|
|
21
|
+
configPath: undefined,
|
|
22
|
+
showHelp: false,
|
|
23
|
+
showVersion: false,
|
|
24
|
+
historyLimit: 20,
|
|
25
|
+
historyJson: false,
|
|
26
|
+
historyPrune: false,
|
|
27
|
+
historyClear: false,
|
|
28
|
+
debounceMs: 500,
|
|
29
|
+
dashboard: false,
|
|
30
|
+
dashboardPort: 4242,
|
|
31
|
+
dashboardOpen: false,
|
|
32
|
+
autoApprove: false,
|
|
33
|
+
genesisInit: false,
|
|
34
|
+
genesisWatch: false,
|
|
35
|
+
};
|
|
36
|
+
const args = argv.slice(2);
|
|
37
|
+
let i = 0;
|
|
38
|
+
while (i < args.length) {
|
|
39
|
+
const arg = args[i];
|
|
40
|
+
if (arg === '--help' || arg === '-h') {
|
|
41
|
+
result.showHelp = true;
|
|
42
|
+
}
|
|
43
|
+
else if (arg === '--version') {
|
|
44
|
+
result.showVersion = true;
|
|
45
|
+
}
|
|
46
|
+
else if (arg === '--verbose' || arg === '-v') {
|
|
47
|
+
result.verbose = true;
|
|
48
|
+
}
|
|
49
|
+
else if (arg === '--dry-run' || arg === '-n') {
|
|
50
|
+
result.dryRun = true;
|
|
51
|
+
}
|
|
52
|
+
else if (arg === '--quiet') {
|
|
53
|
+
result.quiet = true;
|
|
54
|
+
}
|
|
55
|
+
else if ((arg === '--params' || arg === '-p') && i + 1 < args.length) {
|
|
56
|
+
i++;
|
|
57
|
+
try {
|
|
58
|
+
result.params = JSON.parse(args[i]);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
console.error(`[weaver] Invalid JSON for --params: ${args[i]}`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else if ((arg === '--config' || arg === '-c') && i + 1 < args.length) {
|
|
66
|
+
i++;
|
|
67
|
+
result.configPath = args[i];
|
|
68
|
+
}
|
|
69
|
+
else if (arg === '--limit' && i + 1 < args.length) {
|
|
70
|
+
i++;
|
|
71
|
+
result.historyLimit = parseInt(args[i], 10) || 20;
|
|
72
|
+
}
|
|
73
|
+
else if (arg === '--outcome' && i + 1 < args.length) {
|
|
74
|
+
i++;
|
|
75
|
+
result.historyOutcome = args[i];
|
|
76
|
+
}
|
|
77
|
+
else if (arg === '--workflow' && i + 1 < args.length) {
|
|
78
|
+
i++;
|
|
79
|
+
if (result.command === 'eject') {
|
|
80
|
+
result.ejectWorkflow = args[i];
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
result.historyWorkflow = args[i];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else if (arg === '--since' && i + 1 < args.length) {
|
|
87
|
+
i++;
|
|
88
|
+
if (result.command === 'costs') {
|
|
89
|
+
result.costsSince = args[i];
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
result.historySince = args[i];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else if (arg === '--model' && i + 1 < args.length) {
|
|
96
|
+
i++;
|
|
97
|
+
result.costsModel = args[i];
|
|
98
|
+
}
|
|
99
|
+
else if (arg === '--json') {
|
|
100
|
+
result.historyJson = true;
|
|
101
|
+
}
|
|
102
|
+
else if (arg === '--prune') {
|
|
103
|
+
result.historyPrune = true;
|
|
104
|
+
}
|
|
105
|
+
else if (arg === '--clear') {
|
|
106
|
+
result.historyClear = true;
|
|
107
|
+
}
|
|
108
|
+
else if (arg === 'history') {
|
|
109
|
+
result.command = 'history';
|
|
110
|
+
}
|
|
111
|
+
else if (arg === 'costs') {
|
|
112
|
+
result.command = 'costs';
|
|
113
|
+
}
|
|
114
|
+
else if (arg === 'providers') {
|
|
115
|
+
result.command = 'providers';
|
|
116
|
+
}
|
|
117
|
+
else if (arg === 'eject') {
|
|
118
|
+
result.command = 'eject';
|
|
119
|
+
}
|
|
120
|
+
else if (arg === 'watch') {
|
|
121
|
+
result.command = 'watch';
|
|
122
|
+
}
|
|
123
|
+
else if (arg === 'cron') {
|
|
124
|
+
result.command = 'cron';
|
|
125
|
+
// Next arg is the schedule
|
|
126
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
127
|
+
i++;
|
|
128
|
+
result.cronSchedule = args[i];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else if (arg === 'pipeline') {
|
|
132
|
+
result.command = 'pipeline';
|
|
133
|
+
}
|
|
134
|
+
else if (arg === '--cron' && i + 1 < args.length) {
|
|
135
|
+
i++;
|
|
136
|
+
result.cronSchedule = args[i];
|
|
137
|
+
}
|
|
138
|
+
else if (arg === '--debounce' && i + 1 < args.length) {
|
|
139
|
+
i++;
|
|
140
|
+
result.debounceMs = parseInt(args[i], 10) || 500;
|
|
141
|
+
}
|
|
142
|
+
else if (arg === '--log' && i + 1 < args.length) {
|
|
143
|
+
i++;
|
|
144
|
+
result.logFile = args[i];
|
|
145
|
+
}
|
|
146
|
+
else if (arg === '--stage' && i + 1 < args.length) {
|
|
147
|
+
i++;
|
|
148
|
+
result.pipelineStage = args[i];
|
|
149
|
+
}
|
|
150
|
+
else if (arg === '--dashboard') {
|
|
151
|
+
result.dashboard = true;
|
|
152
|
+
}
|
|
153
|
+
else if (arg === '--port' && i + 1 < args.length) {
|
|
154
|
+
i++;
|
|
155
|
+
result.dashboardPort = parseInt(args[i], 10) || 4242;
|
|
156
|
+
}
|
|
157
|
+
else if (arg === '--open') {
|
|
158
|
+
result.dashboardOpen = true;
|
|
159
|
+
}
|
|
160
|
+
else if (arg === '--approval' && i + 1 < args.length) {
|
|
161
|
+
i++;
|
|
162
|
+
result.approvalMode = args[i];
|
|
163
|
+
}
|
|
164
|
+
else if (arg === 'dashboard') {
|
|
165
|
+
result.command = 'dashboard';
|
|
166
|
+
result.dashboard = true;
|
|
167
|
+
}
|
|
168
|
+
else if (arg === 'bot') {
|
|
169
|
+
result.command = 'bot';
|
|
170
|
+
// Next non-flag arg is the task string
|
|
171
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
172
|
+
i++;
|
|
173
|
+
result.botTask = args[i];
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else if (arg === 'session') {
|
|
177
|
+
result.command = 'session';
|
|
178
|
+
}
|
|
179
|
+
else if (arg === 'steer') {
|
|
180
|
+
result.command = 'steer';
|
|
181
|
+
// Next arg is the subcommand
|
|
182
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
183
|
+
i++;
|
|
184
|
+
result.botTask = args[i];
|
|
185
|
+
// Next arg after redirect/queue is payload
|
|
186
|
+
if ((args[i] === 'redirect' || args[i] === 'queue') && i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
187
|
+
i++;
|
|
188
|
+
result.botFile = args[i];
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else if (arg === 'queue') {
|
|
193
|
+
result.command = 'queue';
|
|
194
|
+
// Next arg is action (add/list/clear/remove)
|
|
195
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
196
|
+
i++;
|
|
197
|
+
result.botTask = args[i];
|
|
198
|
+
// Next arg is task/id
|
|
199
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
200
|
+
i++;
|
|
201
|
+
result.botFile = args[i];
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else if (arg === '--file' && i + 1 < args.length) {
|
|
206
|
+
i++;
|
|
207
|
+
result.botFile = args[i];
|
|
208
|
+
}
|
|
209
|
+
else if (arg === '--template' && i + 1 < args.length) {
|
|
210
|
+
i++;
|
|
211
|
+
result.botTemplate = args[i];
|
|
212
|
+
}
|
|
213
|
+
else if (arg === '--batch' && i + 1 < args.length) {
|
|
214
|
+
i++;
|
|
215
|
+
result.botBatch = parseInt(args[i], 10) || undefined;
|
|
216
|
+
}
|
|
217
|
+
else if (arg === '--auto-approve') {
|
|
218
|
+
result.autoApprove = true;
|
|
219
|
+
}
|
|
220
|
+
else if (arg === 'audit') {
|
|
221
|
+
result.command = 'audit';
|
|
222
|
+
// Next non-flag arg is the runId
|
|
223
|
+
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
224
|
+
i++;
|
|
225
|
+
result.historyId = args[i];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else if (arg === 'genesis') {
|
|
229
|
+
result.command = 'genesis';
|
|
230
|
+
}
|
|
231
|
+
else if (arg === '--init') {
|
|
232
|
+
result.genesisInit = true;
|
|
233
|
+
}
|
|
234
|
+
else if (arg === '--watch') {
|
|
235
|
+
result.genesisWatch = true;
|
|
236
|
+
}
|
|
237
|
+
else if (arg === '--project-dir' && i + 1 < args.length) {
|
|
238
|
+
i++;
|
|
239
|
+
result.file = args[i];
|
|
240
|
+
}
|
|
241
|
+
else if (arg === 'run') {
|
|
242
|
+
// skip, next arg is the file
|
|
243
|
+
}
|
|
244
|
+
else if (!arg.startsWith('-')) {
|
|
245
|
+
if (result.command === 'history' && !result.file) {
|
|
246
|
+
result.historyId = arg;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
result.file = arg;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
console.error(`[weaver] Unknown option: ${arg}`);
|
|
254
|
+
console.error('Run "flow-weaver weaver --help" for usage');
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
i++;
|
|
258
|
+
}
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
// --- Formatting helpers ---
|
|
262
|
+
export function formatDuration(ms) {
|
|
263
|
+
if (ms < 1000)
|
|
264
|
+
return `${ms}ms`;
|
|
265
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
266
|
+
}
|
|
267
|
+
const STATUS_ICONS = {
|
|
268
|
+
'node-start': '\x1b[36m>\x1b[0m',
|
|
269
|
+
'node-complete': '\x1b[32m+\x1b[0m',
|
|
270
|
+
'node-error': '\x1b[31mx\x1b[0m',
|
|
271
|
+
};
|
|
272
|
+
const OUTCOME_COLORS = {
|
|
273
|
+
completed: '\x1b[32m',
|
|
274
|
+
failed: '\x1b[31m',
|
|
275
|
+
error: '\x1b[31m',
|
|
276
|
+
skipped: '\x1b[33m',
|
|
277
|
+
};
|
|
278
|
+
const RESET = '\x1b[0m';
|
|
279
|
+
const STAGE_ICONS = {
|
|
280
|
+
running: '\x1b[36m>\x1b[0m',
|
|
281
|
+
completed: '\x1b[32m+\x1b[0m',
|
|
282
|
+
failed: '\x1b[31mx\x1b[0m',
|
|
283
|
+
skipped: '\x1b[33m-\x1b[0m',
|
|
284
|
+
cancelled: '\x1b[33m~\x1b[0m',
|
|
285
|
+
};
|
|
286
|
+
function printRunTable(records) {
|
|
287
|
+
console.log('ID'.padEnd(10) +
|
|
288
|
+
'OUTCOME'.padEnd(12) +
|
|
289
|
+
'DURATION'.padEnd(10) +
|
|
290
|
+
'WORKFLOW'.padEnd(24) +
|
|
291
|
+
'STARTED');
|
|
292
|
+
for (const r of records) {
|
|
293
|
+
const id = r.id.slice(0, 8);
|
|
294
|
+
const color = OUTCOME_COLORS[r.outcome] ?? '';
|
|
295
|
+
const outcome = `${color}${r.outcome}${RESET}`;
|
|
296
|
+
const duration = formatDuration(r.durationMs);
|
|
297
|
+
const workflow = path.basename(r.workflowFile);
|
|
298
|
+
const started = r.startedAt.replace('T', ' ').slice(0, 16);
|
|
299
|
+
console.log(id.padEnd(10) +
|
|
300
|
+
outcome.padEnd(12 + color.length + RESET.length) +
|
|
301
|
+
duration.padEnd(10) +
|
|
302
|
+
(workflow.length > 22 ? workflow.slice(0, 21) + '~' : workflow).padEnd(24) +
|
|
303
|
+
started);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function printRunDetail(r) {
|
|
307
|
+
const outcomeColor = r.success ? '\x1b[32m' : '\x1b[31m';
|
|
308
|
+
console.log(`\nRun ${r.id}\n`);
|
|
309
|
+
console.log(` Workflow: ${r.workflowFile}`);
|
|
310
|
+
if (r.functionName)
|
|
311
|
+
console.log(` Function: ${r.functionName}`);
|
|
312
|
+
console.log(` Outcome: ${outcomeColor}${r.outcome}${RESET} (${r.success ? 'success' : 'failure'})`);
|
|
313
|
+
console.log(` Started: ${r.startedAt}`);
|
|
314
|
+
console.log(` Finished: ${r.finishedAt}`);
|
|
315
|
+
console.log(` Duration: ${formatDuration(r.durationMs)}`);
|
|
316
|
+
if (r.executionTime !== undefined) {
|
|
317
|
+
console.log(` Execution time: ${formatDuration(r.executionTime)}`);
|
|
318
|
+
}
|
|
319
|
+
if (r.provider)
|
|
320
|
+
console.log(` Provider: ${r.provider}`);
|
|
321
|
+
console.log(` Dry run: ${r.dryRun ? 'yes' : 'no'}`);
|
|
322
|
+
console.log(` Summary: ${r.summary}`);
|
|
323
|
+
if (r.params) {
|
|
324
|
+
console.log(` Params: ${JSON.stringify(r.params)}`);
|
|
325
|
+
}
|
|
326
|
+
console.log('');
|
|
327
|
+
}
|
|
328
|
+
function parseSince(spec) {
|
|
329
|
+
if (!spec)
|
|
330
|
+
return undefined;
|
|
331
|
+
const match = spec.match(/^(\d+)([dhm])$/);
|
|
332
|
+
if (match) {
|
|
333
|
+
const n = parseInt(match[1], 10);
|
|
334
|
+
const unit = match[2];
|
|
335
|
+
const ms = unit === 'd' ? n * 86_400_000 : unit === 'h' ? n * 3_600_000 : n * 60_000;
|
|
336
|
+
return Date.now() - ms;
|
|
337
|
+
}
|
|
338
|
+
const ts = new Date(spec).getTime();
|
|
339
|
+
return isNaN(ts) ? undefined : ts;
|
|
340
|
+
}
|
|
341
|
+
function formatCostTable(summary) {
|
|
342
|
+
const lines = [];
|
|
343
|
+
lines.push(`Weaver Cost Summary (${summary.totalRuns} runs)`);
|
|
344
|
+
lines.push(`Total: ~$${summary.totalCost.toFixed(4)}`);
|
|
345
|
+
lines.push(`Tokens: ${summary.totalInputTokens.toLocaleString()} in / ${summary.totalOutputTokens.toLocaleString()} out`);
|
|
346
|
+
const models = Object.entries(summary.byModel);
|
|
347
|
+
if (models.length > 0) {
|
|
348
|
+
lines.push('');
|
|
349
|
+
lines.push('By model:');
|
|
350
|
+
for (const [model, data] of models) {
|
|
351
|
+
lines.push(` ${model}: ${data.runs} runs, ~$${data.cost.toFixed(4)}, ${data.inputTokens.toLocaleString()} in / ${data.outputTokens.toLocaleString()} out`);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return lines.join('\n');
|
|
355
|
+
}
|
|
356
|
+
function formatRunCost(cost) {
|
|
357
|
+
const inp = cost.totalInputTokens.toLocaleString();
|
|
358
|
+
const out = cost.totalOutputTokens.toLocaleString();
|
|
359
|
+
const usd = cost.totalCost < 0.01
|
|
360
|
+
? `$${cost.totalCost.toFixed(4)}`
|
|
361
|
+
: `$${cost.totalCost.toFixed(2)}`;
|
|
362
|
+
return `tokens: ${inp} in / ${out} out | cost: ~${usd} (${cost.model})`;
|
|
363
|
+
}
|
|
364
|
+
async function loadConfig(configPath) {
|
|
365
|
+
if (!configPath)
|
|
366
|
+
return undefined;
|
|
367
|
+
try {
|
|
368
|
+
const { readFileSync } = await import('node:fs');
|
|
369
|
+
return JSON.parse(readFileSync(path.resolve(configPath), 'utf-8'));
|
|
370
|
+
}
|
|
371
|
+
catch (err) {
|
|
372
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
373
|
+
console.error(`[weaver] Failed to read config: ${msg}`);
|
|
374
|
+
process.exit(1);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
// --- Handlers ---
|
|
378
|
+
export async function handleHistory(opts) {
|
|
379
|
+
const store = new RunStore();
|
|
380
|
+
if (opts.historyClear) {
|
|
381
|
+
const deleted = store.clear();
|
|
382
|
+
console.log(deleted ? 'History cleared.' : 'No history to clear.');
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
if (opts.historyPrune) {
|
|
386
|
+
const pruned = store.prune({ maxRecords: 500, maxAgeDays: 90 });
|
|
387
|
+
console.log(`Pruned ${pruned} record(s).`);
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
if (opts.historyId) {
|
|
391
|
+
const record = store.get(opts.historyId);
|
|
392
|
+
if (!record) {
|
|
393
|
+
console.error(`[weaver] No run found matching "${opts.historyId}"`);
|
|
394
|
+
process.exit(1);
|
|
395
|
+
}
|
|
396
|
+
if (opts.historyJson) {
|
|
397
|
+
console.log(JSON.stringify(record, null, 2));
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
printRunDetail(record);
|
|
401
|
+
}
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
const records = store.list({
|
|
405
|
+
outcome: opts.historyOutcome,
|
|
406
|
+
workflowFile: opts.historyWorkflow ? path.resolve(opts.historyWorkflow) : undefined,
|
|
407
|
+
since: opts.historySince,
|
|
408
|
+
limit: opts.historyLimit,
|
|
409
|
+
});
|
|
410
|
+
if (records.length === 0) {
|
|
411
|
+
console.log('No runs recorded yet.');
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
if (opts.historyJson) {
|
|
415
|
+
console.log(JSON.stringify(records, null, 2));
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
printRunTable(records);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
export async function handleCosts(opts) {
|
|
422
|
+
const store = new CostStore();
|
|
423
|
+
const sinceTs = parseSince(opts.costsSince);
|
|
424
|
+
const summary = store.summarize({ since: sinceTs, model: opts.costsModel });
|
|
425
|
+
if (summary.totalRuns === 0) {
|
|
426
|
+
console.log('No cost data found.');
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
console.log(formatCostTable(summary));
|
|
430
|
+
}
|
|
431
|
+
export async function handleWatch(opts) {
|
|
432
|
+
if (!opts.file) {
|
|
433
|
+
console.error('[weaver] No workflow file specified for watch');
|
|
434
|
+
process.exit(1);
|
|
435
|
+
}
|
|
436
|
+
const config = await loadConfig(opts.configPath);
|
|
437
|
+
const daemon = new WatchDaemon({
|
|
438
|
+
filePath: path.resolve(opts.file),
|
|
439
|
+
watchFile: true,
|
|
440
|
+
cron: opts.cronSchedule,
|
|
441
|
+
debounceMs: opts.debounceMs,
|
|
442
|
+
logFile: opts.logFile,
|
|
443
|
+
verbose: opts.verbose,
|
|
444
|
+
params: opts.params,
|
|
445
|
+
config,
|
|
446
|
+
quiet: opts.quiet,
|
|
447
|
+
});
|
|
448
|
+
await daemon.start();
|
|
449
|
+
}
|
|
450
|
+
export async function handleCron(opts) {
|
|
451
|
+
if (!opts.cronSchedule) {
|
|
452
|
+
console.error('[weaver] No cron schedule specified');
|
|
453
|
+
console.error('Usage: flow-weaver weaver cron "*/5 * * * *" <file>');
|
|
454
|
+
process.exit(1);
|
|
455
|
+
}
|
|
456
|
+
if (!opts.file) {
|
|
457
|
+
console.error('[weaver] No workflow file specified for cron');
|
|
458
|
+
process.exit(1);
|
|
459
|
+
}
|
|
460
|
+
const config = await loadConfig(opts.configPath);
|
|
461
|
+
const daemon = new WatchDaemon({
|
|
462
|
+
filePath: path.resolve(opts.file),
|
|
463
|
+
watchFile: false,
|
|
464
|
+
cron: opts.cronSchedule,
|
|
465
|
+
debounceMs: opts.debounceMs,
|
|
466
|
+
logFile: opts.logFile,
|
|
467
|
+
verbose: opts.verbose,
|
|
468
|
+
params: opts.params,
|
|
469
|
+
config,
|
|
470
|
+
quiet: opts.quiet,
|
|
471
|
+
});
|
|
472
|
+
await daemon.start();
|
|
473
|
+
}
|
|
474
|
+
export async function handlePipeline(opts) {
|
|
475
|
+
if (!opts.file) {
|
|
476
|
+
console.error('[weaver] No pipeline config specified');
|
|
477
|
+
console.error('Usage: flow-weaver weaver pipeline <config.json>');
|
|
478
|
+
process.exit(1);
|
|
479
|
+
}
|
|
480
|
+
let config;
|
|
481
|
+
try {
|
|
482
|
+
config = PipelineRunner.load(opts.file);
|
|
483
|
+
}
|
|
484
|
+
catch (err) {
|
|
485
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
486
|
+
console.error(`\x1b[31m[weaver] Pipeline config error: ${msg}\x1b[0m`);
|
|
487
|
+
process.exit(1);
|
|
488
|
+
}
|
|
489
|
+
const runner = new PipelineRunner();
|
|
490
|
+
if (!opts.quiet) {
|
|
491
|
+
console.log(`Pipeline: ${config.name}`);
|
|
492
|
+
console.log(` ${config.stages.length} stages\n`);
|
|
493
|
+
}
|
|
494
|
+
const stageTimings = new Map();
|
|
495
|
+
const onStageEvent = opts.quiet
|
|
496
|
+
? undefined
|
|
497
|
+
: (stageId, status, result) => {
|
|
498
|
+
const icon = STAGE_ICONS[status] ?? ' ';
|
|
499
|
+
const stage = config.stages.find((s) => s.id === stageId);
|
|
500
|
+
const label = stage?.label ?? stageId;
|
|
501
|
+
if (status === 'running') {
|
|
502
|
+
stageTimings.set(stageId, Date.now());
|
|
503
|
+
if (opts.verbose) {
|
|
504
|
+
console.log(` ${icon} ${label}`);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
const start = stageTimings.get(stageId);
|
|
509
|
+
const dur = start ? ` (${formatDuration(Date.now() - start)})` : '';
|
|
510
|
+
console.log(` ${icon} ${label}${dur}`);
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
const weaverConfig = await loadConfig(opts.configPath);
|
|
514
|
+
try {
|
|
515
|
+
const pipelineResult = await runner.run(config, {
|
|
516
|
+
verbose: opts.verbose,
|
|
517
|
+
dryRun: opts.dryRun,
|
|
518
|
+
config: weaverConfig,
|
|
519
|
+
stage: opts.pipelineStage,
|
|
520
|
+
onStageEvent,
|
|
521
|
+
onNotificationError: (channel, _event, error) => {
|
|
522
|
+
console.error(`[weaver] Notification error (${channel}): ${error}`);
|
|
523
|
+
},
|
|
524
|
+
});
|
|
525
|
+
if (!opts.quiet) {
|
|
526
|
+
const elapsed = formatDuration(pipelineResult.durationMs);
|
|
527
|
+
const color = pipelineResult.success ? '\x1b[32m' : '\x1b[31m';
|
|
528
|
+
console.log(`\n${color}Pipeline: ${pipelineResult.outcome}\x1b[0m (${elapsed})`);
|
|
529
|
+
}
|
|
530
|
+
process.exit(pipelineResult.success ? 0 : 1);
|
|
531
|
+
}
|
|
532
|
+
catch (err) {
|
|
533
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
534
|
+
console.error(`\x1b[31m[weaver] Pipeline error: ${msg}\x1b[0m`);
|
|
535
|
+
process.exit(1);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
export async function handleDashboard(opts) {
|
|
539
|
+
const dashboard = new DashboardServer({ port: opts.dashboardPort });
|
|
540
|
+
const port = await dashboard.start();
|
|
541
|
+
const url = dashboard.getUrl();
|
|
542
|
+
console.log(`[weaver] Dashboard: ${url}`);
|
|
543
|
+
if (opts.dashboardOpen)
|
|
544
|
+
openBrowser(url);
|
|
545
|
+
if (!opts.file) {
|
|
546
|
+
// Dashboard-only mode: view history, wait for SIGINT
|
|
547
|
+
console.log('[weaver] Dashboard running (Ctrl+C to stop)');
|
|
548
|
+
await new Promise((resolve) => {
|
|
549
|
+
process.on('SIGINT', () => { dashboard.stop().then(resolve); });
|
|
550
|
+
process.on('SIGTERM', () => { dashboard.stop().then(resolve); });
|
|
551
|
+
});
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
// Run workflow with live dashboard
|
|
555
|
+
const config = await loadConfig(opts.configPath);
|
|
556
|
+
if (opts.approvalMode) {
|
|
557
|
+
const cfg = config ?? { provider: 'auto' };
|
|
558
|
+
cfg.approval = { mode: opts.approvalMode, webOpen: opts.dashboardOpen };
|
|
559
|
+
}
|
|
560
|
+
dashboard.broadcastWorkflowStart(path.resolve(opts.file));
|
|
561
|
+
const nodeTimings = new Map();
|
|
562
|
+
const onEvent = (event) => {
|
|
563
|
+
dashboard.broadcastExecution(event);
|
|
564
|
+
if (opts.quiet)
|
|
565
|
+
return;
|
|
566
|
+
const icon = STATUS_ICONS[event.type] ?? ' ';
|
|
567
|
+
const label = event.nodeType ? `${event.nodeId} (${event.nodeType})` : event.nodeId;
|
|
568
|
+
if (event.type === 'node-start') {
|
|
569
|
+
nodeTimings.set(event.nodeId, event.timestamp);
|
|
570
|
+
if (opts.verbose)
|
|
571
|
+
console.log(` ${icon} ${label}`);
|
|
572
|
+
}
|
|
573
|
+
else if (event.type === 'node-complete') {
|
|
574
|
+
const start = nodeTimings.get(event.nodeId);
|
|
575
|
+
const dur = start ? ` ${formatDuration(event.timestamp - start)}` : '';
|
|
576
|
+
console.log(` ${icon} ${label}${dur}`);
|
|
577
|
+
}
|
|
578
|
+
else if (event.type === 'node-error') {
|
|
579
|
+
console.log(` ${icon} ${label}: ${event.error ?? 'unknown error'}`);
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
const startTime = Date.now();
|
|
583
|
+
try {
|
|
584
|
+
const result = await runWorkflow(path.resolve(opts.file), {
|
|
585
|
+
params: opts.params,
|
|
586
|
+
verbose: opts.verbose,
|
|
587
|
+
dryRun: opts.dryRun,
|
|
588
|
+
config,
|
|
589
|
+
onEvent,
|
|
590
|
+
dashboardServer: dashboard,
|
|
591
|
+
onNotificationError: (channel, _event, error) => {
|
|
592
|
+
console.error(`[weaver] Notification error (${channel}): ${error}`);
|
|
593
|
+
},
|
|
594
|
+
});
|
|
595
|
+
dashboard.broadcastWorkflowComplete(result.summary, result.success);
|
|
596
|
+
const elapsed = formatDuration(Date.now() - startTime);
|
|
597
|
+
if (!opts.quiet) {
|
|
598
|
+
console.log('');
|
|
599
|
+
const color = result.success ? '\x1b[32m' : '\x1b[31m';
|
|
600
|
+
console.log(`${color}Weaver: ${result.outcome}\x1b[0m (${elapsed})`);
|
|
601
|
+
console.log(` ${result.summary}`);
|
|
602
|
+
if (result.cost && result.cost.totalInputTokens > 0) {
|
|
603
|
+
console.log(` ${formatRunCost(result.cost)}`);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
// Keep alive for 5 minutes after completion
|
|
607
|
+
console.log(`[weaver] Dashboard at ${url} (5min keep-alive, Ctrl+C to stop)`);
|
|
608
|
+
await new Promise((resolve) => {
|
|
609
|
+
const timer = setTimeout(() => resolve(), 300_000);
|
|
610
|
+
const handler = () => { clearTimeout(timer); resolve(); };
|
|
611
|
+
process.on('SIGINT', handler);
|
|
612
|
+
process.on('SIGTERM', handler);
|
|
613
|
+
});
|
|
614
|
+
await dashboard.stop();
|
|
615
|
+
process.exit(result.success ? 0 : 1);
|
|
616
|
+
}
|
|
617
|
+
catch (err) {
|
|
618
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
619
|
+
dashboard.broadcastWorkflowError(msg);
|
|
620
|
+
console.error(`\x1b[31m[weaver] Fatal: ${msg}\x1b[0m`);
|
|
621
|
+
await dashboard.stop();
|
|
622
|
+
process.exit(1);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
export async function handleProviders() {
|
|
626
|
+
await discoverProviders(defaultRegistry);
|
|
627
|
+
const providers = defaultRegistry.list();
|
|
628
|
+
if (providers.length === 0) {
|
|
629
|
+
console.log('No providers found.');
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
console.log('Available providers:\n');
|
|
633
|
+
for (const { name, metadata } of providers) {
|
|
634
|
+
const tag = `[${metadata.source}]`;
|
|
635
|
+
console.log(` ${name} ${tag}`);
|
|
636
|
+
if (metadata.description) {
|
|
637
|
+
console.log(` ${metadata.description}`);
|
|
638
|
+
}
|
|
639
|
+
if (metadata.requiredEnvVars && metadata.requiredEnvVars.length > 0) {
|
|
640
|
+
const present = metadata.requiredEnvVars.every((v) => process.env[v]);
|
|
641
|
+
const status = present ? '\x1b[32mset\x1b[0m' : '\x1b[33mnot set\x1b[0m';
|
|
642
|
+
console.log(` env: ${metadata.requiredEnvVars.join(', ')} (${status})`);
|
|
643
|
+
}
|
|
644
|
+
if (metadata.detectCliCommand) {
|
|
645
|
+
console.log(` cli: ${metadata.detectCliCommand}`);
|
|
646
|
+
}
|
|
647
|
+
console.log('');
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
// --- Workflow map for eject and resolution ---
|
|
651
|
+
const MANAGED_WORKFLOWS = {
|
|
652
|
+
bot: 'weaver-bot',
|
|
653
|
+
batch: 'weaver-bot-batch',
|
|
654
|
+
genesis: 'genesis-task',
|
|
655
|
+
};
|
|
656
|
+
/** Deduplicate import lines: collapse multiple imports from the same module. */
|
|
657
|
+
function deduplicateImports(source) {
|
|
658
|
+
const lines = source.split('\n');
|
|
659
|
+
const importMap = new Map();
|
|
660
|
+
const nonImportLines = [];
|
|
661
|
+
let pastImports = false;
|
|
662
|
+
for (const line of lines) {
|
|
663
|
+
const importMatch = line.match(/^import\s+(?:type\s+)?\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]\s*;?\s*$/);
|
|
664
|
+
if (importMatch && !pastImports) {
|
|
665
|
+
const isType = line.trimStart().startsWith('import type');
|
|
666
|
+
const names = importMatch[1].split(',').map((s) => s.trim()).filter(Boolean);
|
|
667
|
+
const mod = importMatch[2];
|
|
668
|
+
const key = isType ? `type:${mod}` : mod;
|
|
669
|
+
if (!importMap.has(key))
|
|
670
|
+
importMap.set(key, new Set());
|
|
671
|
+
for (const n of names)
|
|
672
|
+
importMap.get(key).add(n);
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
if (line.trim() !== '' && !line.match(/^import\s/))
|
|
676
|
+
pastImports = true;
|
|
677
|
+
nonImportLines.push(line);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
const dedupedImports = [];
|
|
681
|
+
for (const [key, names] of importMap) {
|
|
682
|
+
const isType = key.startsWith('type:');
|
|
683
|
+
const mod = isType ? key.slice(5) : key;
|
|
684
|
+
const keyword = isType ? 'import type' : 'import';
|
|
685
|
+
dedupedImports.push(`${keyword} { ${[...names].join(', ')} } from '${mod}';`);
|
|
686
|
+
}
|
|
687
|
+
return [...dedupedImports, ...nonImportLines].join('\n');
|
|
688
|
+
}
|
|
689
|
+
/** Rewrite node-type source: ../bot/*.js → package barrel, deduplicate. */
|
|
690
|
+
function rewriteNodeTypeImports(source) {
|
|
691
|
+
const rewritten = source
|
|
692
|
+
.replace(/from\s+['"]\.\.\/bot\/[^'"]+['"]/g, "from '@synergenius/flow-weaver-pack-weaver/bot'");
|
|
693
|
+
return deduplicateImports(rewritten);
|
|
694
|
+
}
|
|
695
|
+
/** Rewrite workflow source: ../node-types/ → ./node-types/ (local ejected), ../bot/ → package barrel. */
|
|
696
|
+
function rewriteWorkflowImports(source) {
|
|
697
|
+
const rewritten = source
|
|
698
|
+
.replace(/from\s+['"]\.\.\/node-types\//g, "from './node-types/")
|
|
699
|
+
.replace(/from\s+['"]\.\.\/bot\/[^'"]+['"]/g, "from '@synergenius/flow-weaver-pack-weaver/bot'");
|
|
700
|
+
return deduplicateImports(rewritten);
|
|
701
|
+
}
|
|
702
|
+
/** Read a managed workflow source from the pack. */
|
|
703
|
+
function readPackWorkflowSource(packRoot, workflowBaseName) {
|
|
704
|
+
const candidates = [
|
|
705
|
+
new URL(`src/workflows/${workflowBaseName}.ts`, packRoot),
|
|
706
|
+
new URL(`dist/workflows/${workflowBaseName}.ts`, packRoot),
|
|
707
|
+
new URL(`dist/workflows/${workflowBaseName}.js`, packRoot),
|
|
708
|
+
];
|
|
709
|
+
for (const candidate of candidates) {
|
|
710
|
+
try {
|
|
711
|
+
return fs.readFileSync(candidate, 'utf-8');
|
|
712
|
+
}
|
|
713
|
+
catch { /* try next */ }
|
|
714
|
+
}
|
|
715
|
+
throw new Error(`Could not find managed workflow: ${workflowBaseName}`);
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Read a pack source file, trying src/ then dist/.
|
|
719
|
+
*/
|
|
720
|
+
function readPackFile(packRoot, relativePath) {
|
|
721
|
+
const srcCandidate = new URL(`src/${relativePath}`, packRoot);
|
|
722
|
+
const distCandidate = new URL(`dist/${relativePath}`, packRoot);
|
|
723
|
+
try {
|
|
724
|
+
return fs.readFileSync(srcCandidate, 'utf-8');
|
|
725
|
+
}
|
|
726
|
+
catch {
|
|
727
|
+
return fs.readFileSync(distCandidate, 'utf-8');
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Collect bot utility files transitively imported by node-type files.
|
|
732
|
+
* Traces `from '../bot/<file>.js'` and `from './<file>.js'` within bot/.
|
|
733
|
+
*/
|
|
734
|
+
function collectBotDeps(packRoot, ntFiles) {
|
|
735
|
+
const visited = new Set();
|
|
736
|
+
const queue = [];
|
|
737
|
+
// Seed from node-type files: look for ../bot/ imports
|
|
738
|
+
for (const ntFile of ntFiles) {
|
|
739
|
+
let ntSource;
|
|
740
|
+
try {
|
|
741
|
+
ntSource = readPackFile(packRoot, `node-types/${ntFile}`);
|
|
742
|
+
}
|
|
743
|
+
catch {
|
|
744
|
+
continue;
|
|
745
|
+
}
|
|
746
|
+
const botImportRegex = /from\s+['"]\.\.\/bot\/([^'"]+)['"]/g;
|
|
747
|
+
let m;
|
|
748
|
+
while ((m = botImportRegex.exec(ntSource)) !== null) {
|
|
749
|
+
const botFile = m[1].replace(/\.js$/, '.ts');
|
|
750
|
+
if (!visited.has(botFile)) {
|
|
751
|
+
visited.add(botFile);
|
|
752
|
+
queue.push(botFile);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
// Always include types.ts
|
|
757
|
+
if (!visited.has('types.ts')) {
|
|
758
|
+
visited.add('types.ts');
|
|
759
|
+
queue.push('types.ts');
|
|
760
|
+
}
|
|
761
|
+
// Trace transitive deps within bot/
|
|
762
|
+
while (queue.length > 0) {
|
|
763
|
+
const botFile = queue.shift();
|
|
764
|
+
let botSource;
|
|
765
|
+
try {
|
|
766
|
+
botSource = readPackFile(packRoot, `bot/${botFile}`);
|
|
767
|
+
}
|
|
768
|
+
catch {
|
|
769
|
+
continue;
|
|
770
|
+
}
|
|
771
|
+
const localImportRegex = /from\s+['"]\.\/([^'"]+)['"]/g;
|
|
772
|
+
let m;
|
|
773
|
+
while ((m = localImportRegex.exec(botSource)) !== null) {
|
|
774
|
+
const dep = m[1].replace(/\.js$/, '.ts');
|
|
775
|
+
if (!visited.has(dep)) {
|
|
776
|
+
visited.add(dep);
|
|
777
|
+
queue.push(dep);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
return [...visited];
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* Eject workflow + node-type files into a destination directory.
|
|
785
|
+
*
|
|
786
|
+
* When `standalone` is true, bot utility files are also ejected so the
|
|
787
|
+
* workflows run without the pack installed. Import paths in workflows
|
|
788
|
+
* are rewritten from `../node-types/` to `./node-types/`, and `../bot/`
|
|
789
|
+
* imports in node-type files remain as-is (pointing to the local `bot/`
|
|
790
|
+
* directory).
|
|
791
|
+
*
|
|
792
|
+
* When `standalone` is false (default), bot imports are rewritten to
|
|
793
|
+
* the package barrel (`@synergenius/flow-weaver-pack-weaver/bot`).
|
|
794
|
+
*/
|
|
795
|
+
export function ejectWorkflows(opts) {
|
|
796
|
+
const packRoot = new URL('..', import.meta.url);
|
|
797
|
+
const workflowKeys = opts.workflows ?? Object.keys(MANAGED_WORKFLOWS);
|
|
798
|
+
const standalone = opts.standalone === true;
|
|
799
|
+
const results = [];
|
|
800
|
+
const allNtFiles = [];
|
|
801
|
+
for (const key of workflowKeys) {
|
|
802
|
+
const baseName = MANAGED_WORKFLOWS[key];
|
|
803
|
+
if (!baseName)
|
|
804
|
+
continue;
|
|
805
|
+
const source = readPackWorkflowSource(packRoot, baseName);
|
|
806
|
+
// In standalone mode, only rewrite ../node-types/ to ./node-types/
|
|
807
|
+
// and keep ../bot/ as-is (local bot/ dir). Otherwise use package barrel.
|
|
808
|
+
let rewritten;
|
|
809
|
+
if (standalone) {
|
|
810
|
+
rewritten = source.replace(/from\s+['"]\.\.\/node-types\//g, "from './node-types/");
|
|
811
|
+
}
|
|
812
|
+
else {
|
|
813
|
+
rewritten = rewriteWorkflowImports(source);
|
|
814
|
+
}
|
|
815
|
+
const wfFile = `${baseName}.ts`;
|
|
816
|
+
const wfPath = path.join(opts.destDir, wfFile);
|
|
817
|
+
// Collect node-type files referenced by the workflow
|
|
818
|
+
const ntImportRegex = /from\s+['"]\.\.\/node-types\/([^'"]+)['"]/g;
|
|
819
|
+
const ntFiles = [];
|
|
820
|
+
let ntMatch;
|
|
821
|
+
while ((ntMatch = ntImportRegex.exec(source)) !== null) {
|
|
822
|
+
const ntFile = ntMatch[1].replace(/\.js$/, '.ts');
|
|
823
|
+
if (!ntFiles.includes(ntFile))
|
|
824
|
+
ntFiles.push(ntFile);
|
|
825
|
+
if (!allNtFiles.includes(ntFile))
|
|
826
|
+
allNtFiles.push(ntFile);
|
|
827
|
+
}
|
|
828
|
+
// Write workflow (skip if exists and not forced)
|
|
829
|
+
let exists = false;
|
|
830
|
+
try {
|
|
831
|
+
fs.statSync(wfPath);
|
|
832
|
+
exists = true;
|
|
833
|
+
}
|
|
834
|
+
catch { }
|
|
835
|
+
if (!exists || opts.force) {
|
|
836
|
+
fs.mkdirSync(path.join(opts.destDir, 'node-types'), { recursive: true });
|
|
837
|
+
fs.writeFileSync(wfPath, rewritten, 'utf-8');
|
|
838
|
+
// Eject each referenced node-type file
|
|
839
|
+
for (const ntFile of ntFiles) {
|
|
840
|
+
const ntSrcCandidates = [
|
|
841
|
+
new URL(`src/node-types/${ntFile}`, packRoot),
|
|
842
|
+
new URL(`dist/node-types/${ntFile}`, packRoot),
|
|
843
|
+
];
|
|
844
|
+
for (const candidate of ntSrcCandidates) {
|
|
845
|
+
try {
|
|
846
|
+
const ntSource = fs.readFileSync(candidate, 'utf-8');
|
|
847
|
+
// In standalone mode, keep ../bot/ as-is (local). Otherwise rewrite to barrel.
|
|
848
|
+
const ntRewritten = standalone ? ntSource : rewriteNodeTypeImports(ntSource);
|
|
849
|
+
fs.writeFileSync(path.join(opts.destDir, 'node-types', ntFile), ntRewritten, 'utf-8');
|
|
850
|
+
break;
|
|
851
|
+
}
|
|
852
|
+
catch { /* try next */ }
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
results.push({ workflow: key, file: wfFile, nodeTypes: ntFiles });
|
|
857
|
+
}
|
|
858
|
+
// In standalone mode, eject bot utility files
|
|
859
|
+
if (standalone) {
|
|
860
|
+
const botFiles = collectBotDeps(packRoot, allNtFiles);
|
|
861
|
+
fs.mkdirSync(path.join(opts.destDir, 'bot'), { recursive: true });
|
|
862
|
+
for (const botFile of botFiles) {
|
|
863
|
+
const destPath = path.join(opts.destDir, 'bot', botFile);
|
|
864
|
+
let exists = false;
|
|
865
|
+
try {
|
|
866
|
+
fs.statSync(destPath);
|
|
867
|
+
exists = true;
|
|
868
|
+
}
|
|
869
|
+
catch { }
|
|
870
|
+
if (!exists || opts.force) {
|
|
871
|
+
try {
|
|
872
|
+
const botSource = readPackFile(packRoot, `bot/${botFile}`);
|
|
873
|
+
fs.writeFileSync(destPath, botSource, 'utf-8');
|
|
874
|
+
}
|
|
875
|
+
catch {
|
|
876
|
+
// File not found in pack, skip
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
// Attach bot files to results
|
|
881
|
+
for (const r of results) {
|
|
882
|
+
r.botFiles = botFiles;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
return results;
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Resolve a managed workflow path. Checks for a local ejected override first,
|
|
889
|
+
* then falls back to the pack's own source or dist.
|
|
890
|
+
*/
|
|
891
|
+
function resolveWorkflowPath(workflowKey, cwd) {
|
|
892
|
+
const baseName = MANAGED_WORKFLOWS[workflowKey];
|
|
893
|
+
if (!baseName)
|
|
894
|
+
throw new Error(`Unknown workflow: ${workflowKey}`);
|
|
895
|
+
// Check for ejected override
|
|
896
|
+
const metaPath = path.join(cwd, '.weaver-meta.json');
|
|
897
|
+
if (fs.existsSync(metaPath)) {
|
|
898
|
+
try {
|
|
899
|
+
const meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
|
|
900
|
+
if (meta.ejected && meta.workflowFiles?.[workflowKey]) {
|
|
901
|
+
const localPath = path.resolve(cwd, meta.workflowFiles[workflowKey]);
|
|
902
|
+
if (fs.existsSync(localPath)) {
|
|
903
|
+
return localPath;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
catch { /* fall through to pack */ }
|
|
908
|
+
}
|
|
909
|
+
// Fall back to pack's managed workflow
|
|
910
|
+
const packRoot = new URL('..', import.meta.url);
|
|
911
|
+
try {
|
|
912
|
+
const srcPath = fileURLToPath(new URL(`src/workflows/${baseName}.ts`, packRoot));
|
|
913
|
+
if (fs.existsSync(srcPath))
|
|
914
|
+
return srcPath;
|
|
915
|
+
}
|
|
916
|
+
catch { /* ignore */ }
|
|
917
|
+
return fileURLToPath(new URL(`dist/workflows/${baseName}.js`, packRoot));
|
|
918
|
+
}
|
|
919
|
+
export async function handleEject(opts) {
|
|
920
|
+
if (opts.ejectWorkflow && !MANAGED_WORKFLOWS[opts.ejectWorkflow]) {
|
|
921
|
+
console.error(`[weaver] Unknown workflow: ${opts.ejectWorkflow}`);
|
|
922
|
+
console.error(`[weaver] Available: ${Object.keys(MANAGED_WORKFLOWS).join(', ')}`);
|
|
923
|
+
process.exit(1);
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
const destDir = process.cwd();
|
|
927
|
+
const workflows = opts.ejectWorkflow ? [opts.ejectWorkflow] : undefined;
|
|
928
|
+
let results;
|
|
929
|
+
try {
|
|
930
|
+
results = ejectWorkflows({ destDir, workflows, force: true, standalone: true });
|
|
931
|
+
}
|
|
932
|
+
catch (err) {
|
|
933
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
934
|
+
console.error(`[weaver] ${msg}`);
|
|
935
|
+
process.exit(1);
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
for (const r of results) {
|
|
939
|
+
console.log(`[weaver] Ejected ${r.workflow} → ${path.resolve(destDir, r.file)} (${r.nodeTypes.length} node types)`);
|
|
940
|
+
}
|
|
941
|
+
// Read pack version
|
|
942
|
+
const packRoot = new URL('..', import.meta.url);
|
|
943
|
+
let packVersion = 'unknown';
|
|
944
|
+
try {
|
|
945
|
+
const pkgPath = new URL('package.json', packRoot);
|
|
946
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
947
|
+
packVersion = pkg.version;
|
|
948
|
+
}
|
|
949
|
+
catch { /* ignore */ }
|
|
950
|
+
// Write/update .weaver-meta.json (merge with existing if present)
|
|
951
|
+
const metaPath = path.resolve(destDir, '.weaver-meta.json');
|
|
952
|
+
let existingMeta = {};
|
|
953
|
+
try {
|
|
954
|
+
existingMeta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
|
|
955
|
+
}
|
|
956
|
+
catch { /* start fresh */ }
|
|
957
|
+
const existingWorkflows = existingMeta.workflowFiles ?? {};
|
|
958
|
+
const ejectedFiles = {};
|
|
959
|
+
for (const r of results)
|
|
960
|
+
ejectedFiles[r.workflow] = r.file;
|
|
961
|
+
const meta = {
|
|
962
|
+
ejected: true,
|
|
963
|
+
packVersion,
|
|
964
|
+
workflowFiles: { ...existingWorkflows, ...ejectedFiles },
|
|
965
|
+
};
|
|
966
|
+
fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2) + '\n', 'utf-8');
|
|
967
|
+
console.log(`[weaver] Metadata written to ${metaPath}`);
|
|
968
|
+
console.log('[weaver] You can now customize the ejected workflow(s) freely.');
|
|
969
|
+
console.log('[weaver] The bot will use local files when available.');
|
|
970
|
+
}
|
|
971
|
+
export async function handleRun(opts) {
|
|
972
|
+
if (!opts.file) {
|
|
973
|
+
console.error('[weaver] No workflow file specified');
|
|
974
|
+
console.error('Run "flow-weaver weaver --help" for usage');
|
|
975
|
+
process.exit(1);
|
|
976
|
+
}
|
|
977
|
+
const filePath = path.resolve(opts.file);
|
|
978
|
+
const config = await loadConfig(opts.configPath);
|
|
979
|
+
// Apply --approval override
|
|
980
|
+
if (opts.approvalMode && config) {
|
|
981
|
+
config.approval = { mode: opts.approvalMode };
|
|
982
|
+
}
|
|
983
|
+
const nodeTimings = new Map();
|
|
984
|
+
const onEvent = opts.quiet
|
|
985
|
+
? undefined
|
|
986
|
+
: (event) => {
|
|
987
|
+
const icon = STATUS_ICONS[event.type] ?? ' ';
|
|
988
|
+
const label = event.nodeType
|
|
989
|
+
? `${event.nodeId} (${event.nodeType})`
|
|
990
|
+
: event.nodeId;
|
|
991
|
+
if (event.type === 'node-start') {
|
|
992
|
+
nodeTimings.set(event.nodeId, event.timestamp);
|
|
993
|
+
if (opts.verbose) {
|
|
994
|
+
console.log(` ${icon} ${label}`);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
else if (event.type === 'node-complete') {
|
|
998
|
+
const start = nodeTimings.get(event.nodeId);
|
|
999
|
+
const dur = start ? ` ${formatDuration(event.timestamp - start)}` : '';
|
|
1000
|
+
console.log(` ${icon} ${label}${dur}`);
|
|
1001
|
+
}
|
|
1002
|
+
else if (event.type === 'node-error') {
|
|
1003
|
+
console.log(` ${icon} ${label}: ${event.error ?? 'unknown error'}`);
|
|
1004
|
+
}
|
|
1005
|
+
};
|
|
1006
|
+
const startTime = Date.now();
|
|
1007
|
+
try {
|
|
1008
|
+
const result = await runWorkflow(filePath, {
|
|
1009
|
+
params: opts.params,
|
|
1010
|
+
verbose: opts.verbose,
|
|
1011
|
+
dryRun: opts.dryRun,
|
|
1012
|
+
config,
|
|
1013
|
+
onEvent,
|
|
1014
|
+
onNotificationError: (channel, _event, error) => {
|
|
1015
|
+
console.error(`[weaver] Notification error (${channel}): ${error}`);
|
|
1016
|
+
},
|
|
1017
|
+
});
|
|
1018
|
+
const elapsed = formatDuration(Date.now() - startTime);
|
|
1019
|
+
if (!opts.quiet) {
|
|
1020
|
+
console.log('');
|
|
1021
|
+
if (result.success) {
|
|
1022
|
+
console.log(`\x1b[32mBot: ${result.outcome}\x1b[0m (${elapsed})`);
|
|
1023
|
+
}
|
|
1024
|
+
else {
|
|
1025
|
+
console.log(`\x1b[31mBot: ${result.outcome}\x1b[0m (${elapsed})`);
|
|
1026
|
+
}
|
|
1027
|
+
console.log(` ${result.summary}`);
|
|
1028
|
+
if (result.cost && result.cost.totalInputTokens > 0) {
|
|
1029
|
+
console.log(` ${formatRunCost(result.cost)}`);
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
process.exit(result.success ? 0 : 1);
|
|
1033
|
+
}
|
|
1034
|
+
catch (err) {
|
|
1035
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1036
|
+
console.error(`\x1b[31m[weaver] Fatal: ${msg}\x1b[0m`);
|
|
1037
|
+
process.exit(1);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
export async function handleBot(opts) {
|
|
1041
|
+
if (!opts.botTask) {
|
|
1042
|
+
console.error('[weaver] No task specified');
|
|
1043
|
+
console.error('Usage: flow-weaver weaver bot "Create a workflow that..."');
|
|
1044
|
+
process.exit(1);
|
|
1045
|
+
}
|
|
1046
|
+
const task = {
|
|
1047
|
+
instruction: opts.botTask,
|
|
1048
|
+
mode: opts.botFile ? 'modify' : 'create',
|
|
1049
|
+
targets: opts.botFile ? [opts.botFile] : undefined,
|
|
1050
|
+
options: {
|
|
1051
|
+
template: opts.botTemplate,
|
|
1052
|
+
batchCount: opts.botBatch,
|
|
1053
|
+
dryRun: opts.dryRun,
|
|
1054
|
+
autoApprove: opts.autoApprove,
|
|
1055
|
+
},
|
|
1056
|
+
};
|
|
1057
|
+
// Use the batch workflow if --batch specified
|
|
1058
|
+
const workflowKey = opts.botBatch ? 'batch' : 'bot';
|
|
1059
|
+
const workflowPath = resolveWorkflowPath(workflowKey, opts.file ?? process.cwd());
|
|
1060
|
+
const config = await loadConfig(opts.configPath);
|
|
1061
|
+
const nodeTimings = new Map();
|
|
1062
|
+
// Start dashboard if requested
|
|
1063
|
+
let dashboard = null;
|
|
1064
|
+
if (opts.dashboard) {
|
|
1065
|
+
dashboard = new DashboardServer({ port: opts.dashboardPort ?? 4242 });
|
|
1066
|
+
const port = await dashboard.start();
|
|
1067
|
+
console.log(`[weaver] Dashboard: http://127.0.0.1:${port}`);
|
|
1068
|
+
openBrowser(`http://127.0.0.1:${port}`);
|
|
1069
|
+
dashboard.broadcastWorkflowStart(workflowPath);
|
|
1070
|
+
}
|
|
1071
|
+
const onEvent = opts.quiet
|
|
1072
|
+
? undefined
|
|
1073
|
+
: (event) => {
|
|
1074
|
+
const icon = STATUS_ICONS[event.type] ?? ' ';
|
|
1075
|
+
const label = event.nodeType ? `${event.nodeId} (${event.nodeType})` : event.nodeId;
|
|
1076
|
+
if (dashboard)
|
|
1077
|
+
dashboard.broadcastExecution(event);
|
|
1078
|
+
if (event.type === 'node-start') {
|
|
1079
|
+
nodeTimings.set(event.nodeId, event.timestamp);
|
|
1080
|
+
if (opts.verbose)
|
|
1081
|
+
console.log(` ${icon} ${label}`);
|
|
1082
|
+
}
|
|
1083
|
+
else if (event.type === 'node-complete') {
|
|
1084
|
+
const start = nodeTimings.get(event.nodeId);
|
|
1085
|
+
const dur = start ? ` ${formatDuration(event.timestamp - start)}` : '';
|
|
1086
|
+
console.log(` ${icon} ${label}${dur}`);
|
|
1087
|
+
}
|
|
1088
|
+
else if (event.type === 'node-error') {
|
|
1089
|
+
console.log(` ${icon} ${label}: ${event.error ?? 'unknown error'}`);
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
const startTime = Date.now();
|
|
1093
|
+
if (!opts.quiet) {
|
|
1094
|
+
console.log(`[weaver] Bot: ${opts.botTask.slice(0, 80)}`);
|
|
1095
|
+
}
|
|
1096
|
+
try {
|
|
1097
|
+
const result = await runWorkflow(workflowPath, {
|
|
1098
|
+
params: { taskJson: JSON.stringify(task), projectDir: opts.file ?? process.cwd() },
|
|
1099
|
+
verbose: opts.verbose,
|
|
1100
|
+
dryRun: opts.dryRun,
|
|
1101
|
+
config,
|
|
1102
|
+
onEvent,
|
|
1103
|
+
onNotificationError: (channel, _event, error) => {
|
|
1104
|
+
console.error(`[weaver] Notification error (${channel}): ${error}`);
|
|
1105
|
+
},
|
|
1106
|
+
});
|
|
1107
|
+
const elapsed = formatDuration(Date.now() - startTime);
|
|
1108
|
+
if (!opts.quiet) {
|
|
1109
|
+
const color = result.success ? '\x1b[32m' : '\x1b[31m';
|
|
1110
|
+
console.log(`\n${color}Bot: ${result.outcome}\x1b[0m (${elapsed})`);
|
|
1111
|
+
console.log(` ${result.summary}`);
|
|
1112
|
+
}
|
|
1113
|
+
if (dashboard) {
|
|
1114
|
+
dashboard.broadcastWorkflowComplete(result.summary ?? '', result.success);
|
|
1115
|
+
await dashboard.stop();
|
|
1116
|
+
}
|
|
1117
|
+
process.exit(result.success ? 0 : 1);
|
|
1118
|
+
}
|
|
1119
|
+
catch (err) {
|
|
1120
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1121
|
+
console.error(`\x1b[31m[weaver] Fatal: ${msg}\x1b[0m`);
|
|
1122
|
+
if (dashboard) {
|
|
1123
|
+
dashboard.broadcastWorkflowError(msg);
|
|
1124
|
+
await dashboard.stop();
|
|
1125
|
+
}
|
|
1126
|
+
process.exit(1);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
export async function handleSession(opts) {
|
|
1130
|
+
const workflowPath = resolveWorkflowPath('bot', opts.file ?? process.cwd());
|
|
1131
|
+
const config = await loadConfig(opts.configPath);
|
|
1132
|
+
if (!opts.quiet) {
|
|
1133
|
+
console.log('[weaver] Starting bot session (Ctrl+C to stop)');
|
|
1134
|
+
console.log('[weaver] Add tasks with: flow-weaver weaver queue add "task"');
|
|
1135
|
+
}
|
|
1136
|
+
try {
|
|
1137
|
+
const result = await runWorkflow(workflowPath, {
|
|
1138
|
+
params: { projectDir: opts.file ?? process.cwd() },
|
|
1139
|
+
verbose: opts.verbose,
|
|
1140
|
+
dryRun: opts.dryRun,
|
|
1141
|
+
config,
|
|
1142
|
+
});
|
|
1143
|
+
if (!opts.quiet) {
|
|
1144
|
+
const color = result.success ? '\x1b[32m' : '\x1b[31m';
|
|
1145
|
+
console.log(`${color}Session: ${result.outcome}\x1b[0m`);
|
|
1146
|
+
}
|
|
1147
|
+
process.exit(result.success ? 0 : 1);
|
|
1148
|
+
}
|
|
1149
|
+
catch (err) {
|
|
1150
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1151
|
+
console.error(`\x1b[31m[weaver] Fatal: ${msg}\x1b[0m`);
|
|
1152
|
+
process.exit(1);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
export async function handleSteer(opts) {
|
|
1156
|
+
const { SteeringController } = await import('./bot/steering.js');
|
|
1157
|
+
const controller = new SteeringController();
|
|
1158
|
+
const subcommand = opts.botTask;
|
|
1159
|
+
if (!subcommand || !['pause', 'resume', 'cancel', 'redirect', 'queue'].includes(subcommand)) {
|
|
1160
|
+
console.error('[weaver] Usage: flow-weaver weaver steer <pause|resume|cancel|redirect|queue> [payload]');
|
|
1161
|
+
process.exit(1);
|
|
1162
|
+
}
|
|
1163
|
+
const command = {
|
|
1164
|
+
command: subcommand,
|
|
1165
|
+
payload: opts.botFile,
|
|
1166
|
+
timestamp: Date.now(),
|
|
1167
|
+
};
|
|
1168
|
+
await controller.write(command);
|
|
1169
|
+
console.log(`[weaver] Steering command sent: ${subcommand}${opts.botFile ? ' "' + opts.botFile + '"' : ''}`);
|
|
1170
|
+
}
|
|
1171
|
+
export async function handleQueue(opts) {
|
|
1172
|
+
const { TaskQueue } = await import('./bot/task-queue.js');
|
|
1173
|
+
const queue = new TaskQueue();
|
|
1174
|
+
const action = opts.botTask;
|
|
1175
|
+
if (!action || !['add', 'list', 'clear', 'remove'].includes(action)) {
|
|
1176
|
+
console.error('[weaver] Usage: flow-weaver weaver queue <add|list|clear|remove> [task|id]');
|
|
1177
|
+
process.exit(1);
|
|
1178
|
+
}
|
|
1179
|
+
switch (action) {
|
|
1180
|
+
case 'add': {
|
|
1181
|
+
const instruction = opts.botFile;
|
|
1182
|
+
if (!instruction) {
|
|
1183
|
+
console.error('[weaver] Usage: flow-weaver weaver queue add "task instruction"');
|
|
1184
|
+
process.exit(1);
|
|
1185
|
+
}
|
|
1186
|
+
const id = await queue.add({ instruction, priority: 0 });
|
|
1187
|
+
console.log(`[weaver] Task added: ${id}`);
|
|
1188
|
+
break;
|
|
1189
|
+
}
|
|
1190
|
+
case 'list': {
|
|
1191
|
+
const tasks = await queue.list();
|
|
1192
|
+
if (tasks.length === 0) {
|
|
1193
|
+
console.log('No tasks in queue.');
|
|
1194
|
+
}
|
|
1195
|
+
else {
|
|
1196
|
+
console.log('ID'.padEnd(10) + 'STATUS'.padEnd(12) + 'INSTRUCTION');
|
|
1197
|
+
for (const t of tasks) {
|
|
1198
|
+
console.log(t.id.padEnd(10) + t.status.padEnd(12) + t.instruction.slice(0, 60));
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
break;
|
|
1202
|
+
}
|
|
1203
|
+
case 'clear': {
|
|
1204
|
+
const count = await queue.clear();
|
|
1205
|
+
console.log(`Cleared ${count} task(s).`);
|
|
1206
|
+
break;
|
|
1207
|
+
}
|
|
1208
|
+
case 'remove': {
|
|
1209
|
+
const id = opts.botFile;
|
|
1210
|
+
if (!id) {
|
|
1211
|
+
console.error('[weaver] Usage: flow-weaver weaver queue remove <id>');
|
|
1212
|
+
process.exit(1);
|
|
1213
|
+
}
|
|
1214
|
+
const removed = await queue.remove(id);
|
|
1215
|
+
console.log(removed ? `Removed task ${id}.` : `No task found with id "${id}".`);
|
|
1216
|
+
break;
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
export async function handleGenesis(opts) {
|
|
1221
|
+
const projectDir = opts.file ?? process.cwd();
|
|
1222
|
+
if (opts.genesisInit) {
|
|
1223
|
+
const { GenesisStore } = await import('./bot/genesis-store.js');
|
|
1224
|
+
const store = new GenesisStore(projectDir);
|
|
1225
|
+
store.ensureDirs();
|
|
1226
|
+
const config = store.loadConfig();
|
|
1227
|
+
console.log('[weaver] Created .genesis/config.json');
|
|
1228
|
+
console.log('[weaver] Set "targetWorkflow" to the workflow you want Genesis to evolve');
|
|
1229
|
+
console.log(JSON.stringify(config, null, 2));
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1232
|
+
const workflowPath = resolveWorkflowPath('genesis', projectDir);
|
|
1233
|
+
const config = await loadConfig(opts.configPath);
|
|
1234
|
+
if (opts.genesisWatch) {
|
|
1235
|
+
const { GenesisStore } = await import('./bot/genesis-store.js');
|
|
1236
|
+
const store = new GenesisStore(projectDir);
|
|
1237
|
+
const gConfig = store.loadConfig();
|
|
1238
|
+
const maxCycles = gConfig.maxCyclesPerRun;
|
|
1239
|
+
if (!opts.quiet)
|
|
1240
|
+
console.log(`[weaver] Bot genesis watch: up to ${maxCycles} cycles`);
|
|
1241
|
+
for (let i = 0; i < maxCycles; i++) {
|
|
1242
|
+
if (!opts.quiet)
|
|
1243
|
+
console.log(`\n[weaver] Bot genesis cycle ${i + 1}/${maxCycles}`);
|
|
1244
|
+
const result = await runWorkflow(workflowPath, {
|
|
1245
|
+
params: { projectDir },
|
|
1246
|
+
verbose: opts.verbose,
|
|
1247
|
+
dryRun: opts.dryRun,
|
|
1248
|
+
config,
|
|
1249
|
+
});
|
|
1250
|
+
if (!result.success) {
|
|
1251
|
+
if (!opts.quiet)
|
|
1252
|
+
console.log(`\x1b[33m[weaver] Cycle ${i + 1} ended: ${result.summary}\x1b[0m`);
|
|
1253
|
+
}
|
|
1254
|
+
if (i < maxCycles - 1) {
|
|
1255
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
// Single cycle
|
|
1261
|
+
if (!opts.quiet)
|
|
1262
|
+
console.log('[weaver] Bot genesis: running cycle');
|
|
1263
|
+
const result = await runWorkflow(workflowPath, {
|
|
1264
|
+
params: { projectDir },
|
|
1265
|
+
verbose: opts.verbose,
|
|
1266
|
+
dryRun: opts.dryRun,
|
|
1267
|
+
config,
|
|
1268
|
+
});
|
|
1269
|
+
if (!opts.quiet) {
|
|
1270
|
+
const color = result.success ? '\x1b[32m' : '\x1b[33m';
|
|
1271
|
+
console.log(`${color}Bot genesis: ${result.summary}\x1b[0m`);
|
|
1272
|
+
}
|
|
1273
|
+
process.exit(result.success ? 0 : 1);
|
|
1274
|
+
}
|
|
1275
|
+
export async function handleAudit(opts) {
|
|
1276
|
+
const store = new AuditStore();
|
|
1277
|
+
if (opts.historyClear) {
|
|
1278
|
+
const deleted = store.clear();
|
|
1279
|
+
console.log(deleted ? 'Audit log cleared.' : 'No audit log to clear.');
|
|
1280
|
+
return;
|
|
1281
|
+
}
|
|
1282
|
+
if (opts.historyId) {
|
|
1283
|
+
const events = store.queryByRun(opts.historyId);
|
|
1284
|
+
if (events.length === 0) {
|
|
1285
|
+
// Try prefix match
|
|
1286
|
+
const recent = store.queryRecent(1000);
|
|
1287
|
+
const matched = recent.filter((e) => e.runId.startsWith(opts.historyId));
|
|
1288
|
+
if (matched.length === 0) {
|
|
1289
|
+
console.error(`[weaver] No audit events found for "${opts.historyId}"`);
|
|
1290
|
+
process.exit(1);
|
|
1291
|
+
}
|
|
1292
|
+
printAuditEvents(matched, opts.historyJson);
|
|
1293
|
+
return;
|
|
1294
|
+
}
|
|
1295
|
+
printAuditEvents(events, opts.historyJson);
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1298
|
+
const events = store.queryRecent(opts.historyLimit);
|
|
1299
|
+
if (events.length === 0) {
|
|
1300
|
+
console.log('No audit events recorded yet.');
|
|
1301
|
+
return;
|
|
1302
|
+
}
|
|
1303
|
+
if (opts.historyJson) {
|
|
1304
|
+
console.log(JSON.stringify(events, null, 2));
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1307
|
+
// Group by runId
|
|
1308
|
+
const byRun = new Map();
|
|
1309
|
+
for (const e of events) {
|
|
1310
|
+
if (!byRun.has(e.runId))
|
|
1311
|
+
byRun.set(e.runId, []);
|
|
1312
|
+
byRun.get(e.runId).push(e);
|
|
1313
|
+
}
|
|
1314
|
+
for (const [runId, runEvents] of byRun) {
|
|
1315
|
+
console.log(`\n\x1b[1mRun ${runId.slice(0, 8)}\x1b[0m`);
|
|
1316
|
+
for (const e of runEvents) {
|
|
1317
|
+
const time = e.timestamp.replace('T', ' ').slice(11, 19);
|
|
1318
|
+
const dataStr = e.data ? ' ' + JSON.stringify(e.data) : '';
|
|
1319
|
+
console.log(` ${time} ${e.type}${dataStr}`);
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
console.log('');
|
|
1323
|
+
}
|
|
1324
|
+
function printAuditEvents(events, json) {
|
|
1325
|
+
if (json) {
|
|
1326
|
+
console.log(JSON.stringify(events, null, 2));
|
|
1327
|
+
return;
|
|
1328
|
+
}
|
|
1329
|
+
for (const e of events) {
|
|
1330
|
+
const time = e.timestamp.replace('T', ' ').slice(0, 19);
|
|
1331
|
+
const dataStr = e.data ? ' ' + JSON.stringify(e.data) : '';
|
|
1332
|
+
console.log(`${time} [${e.type}]${dataStr}`);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
//# sourceMappingURL=cli-handlers.js.map
|