@oni.bot/core 0.8.0 → 1.0.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/CHANGELOG.md +15 -0
- package/README.md +59 -373
- package/dist/checkpointers/sqlite.d.ts.map +1 -1
- package/dist/checkpointers/sqlite.js +23 -8
- package/dist/checkpointers/sqlite.js.map +1 -1
- package/dist/cli/build.d.ts +11 -0
- package/dist/cli/build.d.ts.map +1 -0
- package/dist/cli/build.js +61 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/dev.d.ts +5 -0
- package/dist/cli/dev.d.ts.map +1 -0
- package/dist/cli/dev.js +54 -0
- package/dist/cli/dev.js.map +1 -0
- package/dist/cli/index.js +16 -27
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +18 -1
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/inspect.d.ts +5 -0
- package/dist/cli/inspect.d.ts.map +1 -0
- package/dist/cli/inspect.js +85 -0
- package/dist/cli/inspect.js.map +1 -0
- package/dist/cli/router.d.ts +14 -0
- package/dist/cli/router.d.ts.map +1 -0
- package/dist/cli/router.js +107 -0
- package/dist/cli/router.js.map +1 -0
- package/dist/cli/run.d.ts +5 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +53 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/templates.d.ts +1 -0
- package/dist/cli/templates.d.ts.map +1 -1
- package/dist/cli/templates.js +106 -66
- package/dist/cli/templates.js.map +1 -1
- package/dist/cli/test.d.ts +3 -0
- package/dist/cli/test.d.ts.map +1 -0
- package/dist/cli/test.js +29 -0
- package/dist/cli/test.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +37 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +180 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/types.d.ts +74 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +5 -0
- package/dist/config/types.js.map +1 -0
- package/dist/coordination/pubsub.d.ts +4 -0
- package/dist/coordination/pubsub.d.ts.map +1 -1
- package/dist/coordination/pubsub.js +8 -0
- package/dist/coordination/pubsub.js.map +1 -1
- package/dist/coordination/request-reply.d.ts +3 -1
- package/dist/coordination/request-reply.d.ts.map +1 -1
- package/dist/coordination/request-reply.js +11 -2
- package/dist/coordination/request-reply.js.map +1 -1
- package/dist/errors.d.ts +7 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +18 -3
- package/dist/errors.js.map +1 -1
- package/dist/events/bridge.d.ts +17 -0
- package/dist/events/bridge.d.ts.map +1 -0
- package/dist/events/bridge.js +67 -0
- package/dist/events/bridge.js.map +1 -0
- package/dist/events/bus.d.ts +9 -0
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/events/bus.js +39 -4
- package/dist/events/bus.js.map +1 -1
- package/dist/events/index.d.ts +2 -1
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +2 -0
- package/dist/events/index.js.map +1 -1
- package/dist/events/types.d.ts +123 -1
- package/dist/events/types.d.ts.map +1 -1
- package/dist/graph.d.ts.map +1 -1
- package/dist/graph.js +16 -8
- package/dist/graph.js.map +1 -1
- package/dist/guardrails/types.d.ts +1 -1
- package/dist/guardrails/types.d.ts.map +1 -1
- package/dist/harness/agent-loop.d.ts.map +1 -1
- package/dist/harness/agent-loop.js +226 -29
- package/dist/harness/agent-loop.js.map +1 -1
- package/dist/harness/context-compactor.d.ts +21 -2
- package/dist/harness/context-compactor.d.ts.map +1 -1
- package/dist/harness/context-compactor.js +45 -6
- package/dist/harness/context-compactor.js.map +1 -1
- package/dist/harness/hooks-engine.d.ts +7 -1
- package/dist/harness/hooks-engine.d.ts.map +1 -1
- package/dist/harness/hooks-engine.js.map +1 -1
- package/dist/harness/index.d.ts +3 -2
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +2 -0
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/skill-loader.d.ts +14 -1
- package/dist/harness/skill-loader.d.ts.map +1 -1
- package/dist/harness/skill-loader.js +33 -3
- package/dist/harness/skill-loader.js.map +1 -1
- package/dist/harness/types.d.ts +24 -2
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/validate-args.d.ts +16 -0
- package/dist/harness/validate-args.d.ts.map +1 -0
- package/dist/harness/validate-args.js +132 -0
- package/dist/harness/validate-args.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/internal/timeout.d.ts +2 -0
- package/dist/internal/timeout.d.ts.map +1 -0
- package/dist/internal/timeout.js +16 -0
- package/dist/internal/timeout.js.map +1 -0
- package/dist/lsp/client.d.ts +70 -0
- package/dist/lsp/client.d.ts.map +1 -0
- package/dist/lsp/client.js +421 -0
- package/dist/lsp/client.js.map +1 -0
- package/dist/lsp/index.d.ts +77 -0
- package/dist/lsp/index.d.ts.map +1 -0
- package/dist/lsp/index.js +183 -0
- package/dist/lsp/index.js.map +1 -0
- package/dist/lsp/servers.d.ts +48 -0
- package/dist/lsp/servers.d.ts.map +1 -0
- package/dist/lsp/servers.js +108 -0
- package/dist/lsp/servers.js.map +1 -0
- package/dist/lsp/types.d.ts +142 -0
- package/dist/lsp/types.d.ts.map +1 -0
- package/dist/lsp/types.js +16 -0
- package/dist/lsp/types.js.map +1 -0
- package/dist/mcp/client.d.ts +56 -0
- package/dist/mcp/client.d.ts.map +1 -0
- package/dist/mcp/client.js +170 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/convert.d.ts +26 -0
- package/dist/mcp/convert.d.ts.map +1 -0
- package/dist/mcp/convert.js +56 -0
- package/dist/mcp/convert.js.map +1 -0
- package/dist/mcp/index.d.ts +21 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +19 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/transport.d.ts +56 -0
- package/dist/mcp/transport.d.ts.map +1 -0
- package/dist/mcp/transport.js +204 -0
- package/dist/mcp/transport.js.map +1 -0
- package/dist/mcp/types.d.ts +96 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +11 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/models/anthropic.d.ts.map +1 -1
- package/dist/models/anthropic.js +78 -41
- package/dist/models/anthropic.js.map +1 -1
- package/dist/models/google.d.ts.map +1 -1
- package/dist/models/google.js +47 -46
- package/dist/models/google.js.map +1 -1
- package/dist/models/http-error.d.ts +16 -0
- package/dist/models/http-error.d.ts.map +1 -0
- package/dist/models/http-error.js +67 -0
- package/dist/models/http-error.js.map +1 -0
- package/dist/models/index.d.ts +3 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +2 -0
- package/dist/models/index.js.map +1 -1
- package/dist/models/ollama.d.ts.map +1 -1
- package/dist/models/ollama.js +4 -3
- package/dist/models/ollama.js.map +1 -1
- package/dist/models/openai.d.ts.map +1 -1
- package/dist/models/openai.js +36 -44
- package/dist/models/openai.js.map +1 -1
- package/dist/models/openrouter.d.ts +13 -0
- package/dist/models/openrouter.d.ts.map +1 -1
- package/dist/models/openrouter.js +86 -47
- package/dist/models/openrouter.js.map +1 -1
- package/dist/models/sse.d.ts +9 -0
- package/dist/models/sse.d.ts.map +1 -0
- package/dist/models/sse.js +45 -0
- package/dist/models/sse.js.map +1 -0
- package/dist/models/types.d.ts +10 -0
- package/dist/models/types.d.ts.map +1 -1
- package/dist/oni-code/agent-registry.d.ts +73 -0
- package/dist/oni-code/agent-registry.d.ts.map +1 -0
- package/dist/oni-code/agent-registry.js +151 -0
- package/dist/oni-code/agent-registry.js.map +1 -0
- package/dist/oni-code/bin.d.ts +18 -0
- package/dist/oni-code/bin.d.ts.map +1 -0
- package/dist/oni-code/bin.js +78 -0
- package/dist/oni-code/bin.js.map +1 -0
- package/dist/oni-code/change-tracking.d.ts +28 -0
- package/dist/oni-code/change-tracking.d.ts.map +1 -0
- package/dist/oni-code/change-tracking.js +77 -0
- package/dist/oni-code/change-tracking.js.map +1 -0
- package/dist/oni-code/cli.d.ts +6 -0
- package/dist/oni-code/cli.d.ts.map +1 -0
- package/dist/oni-code/cli.js +30 -0
- package/dist/oni-code/cli.js.map +1 -0
- package/dist/oni-code/conductor.d.ts +203 -0
- package/dist/oni-code/conductor.d.ts.map +1 -0
- package/dist/oni-code/conductor.js +1547 -0
- package/dist/oni-code/conductor.js.map +1 -0
- package/dist/oni-code/config.d.ts +130 -0
- package/dist/oni-code/config.d.ts.map +1 -0
- package/dist/oni-code/config.js +264 -0
- package/dist/oni-code/config.js.map +1 -0
- package/dist/oni-code/context-files.d.ts +22 -0
- package/dist/oni-code/context-files.d.ts.map +1 -0
- package/dist/oni-code/context-files.js +156 -0
- package/dist/oni-code/context-files.js.map +1 -0
- package/dist/oni-code/cron/humanize.d.ts +26 -0
- package/dist/oni-code/cron/humanize.d.ts.map +1 -0
- package/dist/oni-code/cron/humanize.js +83 -0
- package/dist/oni-code/cron/humanize.js.map +1 -0
- package/dist/oni-code/cron/index.d.ts +10 -0
- package/dist/oni-code/cron/index.d.ts.map +1 -0
- package/dist/oni-code/cron/index.js +7 -0
- package/dist/oni-code/cron/index.js.map +1 -0
- package/dist/oni-code/cron/matcher.d.ts +29 -0
- package/dist/oni-code/cron/matcher.d.ts.map +1 -0
- package/dist/oni-code/cron/matcher.js +73 -0
- package/dist/oni-code/cron/matcher.js.map +1 -0
- package/dist/oni-code/cron/parser.d.ts +27 -0
- package/dist/oni-code/cron/parser.d.ts.map +1 -0
- package/dist/oni-code/cron/parser.js +149 -0
- package/dist/oni-code/cron/parser.js.map +1 -0
- package/dist/oni-code/cron/persistence.d.ts +21 -0
- package/dist/oni-code/cron/persistence.d.ts.map +1 -0
- package/dist/oni-code/cron/persistence.js +58 -0
- package/dist/oni-code/cron/persistence.js.map +1 -0
- package/dist/oni-code/cron/scheduler.d.ts +64 -0
- package/dist/oni-code/cron/scheduler.d.ts.map +1 -0
- package/dist/oni-code/cron/scheduler.js +188 -0
- package/dist/oni-code/cron/scheduler.js.map +1 -0
- package/dist/oni-code/cron/store.d.ts +46 -0
- package/dist/oni-code/cron/store.d.ts.map +1 -0
- package/dist/oni-code/cron/store.js +68 -0
- package/dist/oni-code/cron/store.js.map +1 -0
- package/dist/oni-code/env.d.ts +17 -0
- package/dist/oni-code/env.d.ts.map +1 -0
- package/dist/oni-code/env.js +51 -0
- package/dist/oni-code/env.js.map +1 -0
- package/dist/oni-code/file-reader.d.ts +28 -0
- package/dist/oni-code/file-reader.d.ts.map +1 -0
- package/dist/oni-code/file-reader.js +368 -0
- package/dist/oni-code/file-reader.js.map +1 -0
- package/dist/oni-code/file-watcher.d.ts +66 -0
- package/dist/oni-code/file-watcher.d.ts.map +1 -0
- package/dist/oni-code/file-watcher.js +167 -0
- package/dist/oni-code/file-watcher.js.map +1 -0
- package/dist/oni-code/loop-detector.d.ts +64 -0
- package/dist/oni-code/loop-detector.d.ts.map +1 -0
- package/dist/oni-code/loop-detector.js +163 -0
- package/dist/oni-code/loop-detector.js.map +1 -0
- package/dist/oni-code/permissions.d.ts +43 -0
- package/dist/oni-code/permissions.d.ts.map +1 -0
- package/dist/oni-code/permissions.js +98 -0
- package/dist/oni-code/permissions.js.map +1 -0
- package/dist/oni-code/planner.d.ts +26 -0
- package/dist/oni-code/planner.d.ts.map +1 -0
- package/dist/oni-code/planner.js +86 -0
- package/dist/oni-code/planner.js.map +1 -0
- package/dist/oni-code/plugin-loader.d.ts +103 -0
- package/dist/oni-code/plugin-loader.d.ts.map +1 -0
- package/dist/oni-code/plugin-loader.js +171 -0
- package/dist/oni-code/plugin-loader.js.map +1 -0
- package/dist/oni-code/process-tree.d.ts +44 -0
- package/dist/oni-code/process-tree.d.ts.map +1 -0
- package/dist/oni-code/process-tree.js +107 -0
- package/dist/oni-code/process-tree.js.map +1 -0
- package/dist/oni-code/progress-tracker.d.ts +40 -0
- package/dist/oni-code/progress-tracker.d.ts.map +1 -0
- package/dist/oni-code/progress-tracker.js +375 -0
- package/dist/oni-code/progress-tracker.js.map +1 -0
- package/dist/oni-code/scheduler.d.ts +56 -0
- package/dist/oni-code/scheduler.d.ts.map +1 -0
- package/dist/oni-code/scheduler.js +105 -0
- package/dist/oni-code/scheduler.js.map +1 -0
- package/dist/oni-code/session-fork.d.ts +146 -0
- package/dist/oni-code/session-fork.d.ts.map +1 -0
- package/dist/oni-code/session-fork.js +238 -0
- package/dist/oni-code/session-fork.js.map +1 -0
- package/dist/oni-code/session-stats.d.ts +72 -0
- package/dist/oni-code/session-stats.d.ts.map +1 -0
- package/dist/oni-code/session-stats.js +141 -0
- package/dist/oni-code/session-stats.js.map +1 -0
- package/dist/oni-code/session-title.d.ts +25 -0
- package/dist/oni-code/session-title.d.ts.map +1 -0
- package/dist/oni-code/session-title.js +67 -0
- package/dist/oni-code/session-title.js.map +1 -0
- package/dist/oni-code/shell-parser.d.ts +112 -0
- package/dist/oni-code/shell-parser.d.ts.map +1 -0
- package/dist/oni-code/shell-parser.js +657 -0
- package/dist/oni-code/shell-parser.js.map +1 -0
- package/dist/oni-code/summarizer.d.ts +27 -0
- package/dist/oni-code/summarizer.d.ts.map +1 -0
- package/dist/oni-code/summarizer.js +70 -0
- package/dist/oni-code/summarizer.js.map +1 -0
- package/dist/oni-code/swarm-checkpoint.d.ts +52 -0
- package/dist/oni-code/swarm-checkpoint.d.ts.map +1 -0
- package/dist/oni-code/swarm-checkpoint.js +71 -0
- package/dist/oni-code/swarm-checkpoint.js.map +1 -0
- package/dist/oni-code/swarm-runner.d.ts +173 -0
- package/dist/oni-code/swarm-runner.d.ts.map +1 -0
- package/dist/oni-code/swarm-runner.js +873 -0
- package/dist/oni-code/swarm-runner.js.map +1 -0
- package/dist/oni-code/system-prompt.d.ts +13 -0
- package/dist/oni-code/system-prompt.d.ts.map +1 -0
- package/dist/oni-code/system-prompt.js +64 -0
- package/dist/oni-code/system-prompt.js.map +1 -0
- package/dist/oni-code/task-evaluator.d.ts +73 -0
- package/dist/oni-code/task-evaluator.d.ts.map +1 -0
- package/dist/oni-code/task-evaluator.js +172 -0
- package/dist/oni-code/task-evaluator.js.map +1 -0
- package/dist/oni-code/tools/batch.d.ts +12 -0
- package/dist/oni-code/tools/batch.d.ts.map +1 -0
- package/dist/oni-code/tools/batch.js +116 -0
- package/dist/oni-code/tools/batch.js.map +1 -0
- package/dist/oni-code/tools/coding.d.ts +10 -0
- package/dist/oni-code/tools/coding.d.ts.map +1 -0
- package/dist/oni-code/tools/coding.js +557 -0
- package/dist/oni-code/tools/coding.js.map +1 -0
- package/dist/oni-code/tools/cron.d.ts +4 -0
- package/dist/oni-code/tools/cron.d.ts.map +1 -0
- package/dist/oni-code/tools/cron.js +120 -0
- package/dist/oni-code/tools/cron.js.map +1 -0
- package/dist/oni-code/tools/custom.d.ts +43 -0
- package/dist/oni-code/tools/custom.d.ts.map +1 -0
- package/dist/oni-code/tools/custom.js +115 -0
- package/dist/oni-code/tools/custom.js.map +1 -0
- package/dist/oni-code/tools/patch.d.ts +58 -0
- package/dist/oni-code/tools/patch.d.ts.map +1 -0
- package/dist/oni-code/tools/patch.js +247 -0
- package/dist/oni-code/tools/patch.js.map +1 -0
- package/dist/oni-code/tools/plan.d.ts +17 -0
- package/dist/oni-code/tools/plan.d.ts.map +1 -0
- package/dist/oni-code/tools/plan.js +48 -0
- package/dist/oni-code/tools/plan.js.map +1 -0
- package/dist/oni-code/tools/question.d.ts +17 -0
- package/dist/oni-code/tools/question.d.ts.map +1 -0
- package/dist/oni-code/tools/question.js +46 -0
- package/dist/oni-code/tools/question.js.map +1 -0
- package/dist/oni-code/tools/skill.d.ts +36 -0
- package/dist/oni-code/tools/skill.d.ts.map +1 -0
- package/dist/oni-code/tools/skill.js +132 -0
- package/dist/oni-code/tools/skill.js.map +1 -0
- package/dist/oni-code/tools/spawn-agents.d.ts +37 -0
- package/dist/oni-code/tools/spawn-agents.d.ts.map +1 -0
- package/dist/oni-code/tools/spawn-agents.js +91 -0
- package/dist/oni-code/tools/spawn-agents.js.map +1 -0
- package/dist/oni-code/tools/spawn-swarm.d.ts +70 -0
- package/dist/oni-code/tools/spawn-swarm.d.ts.map +1 -0
- package/dist/oni-code/tools/spawn-swarm.js +129 -0
- package/dist/oni-code/tools/spawn-swarm.js.map +1 -0
- package/dist/oni-code/tools/web.d.ts +11 -0
- package/dist/oni-code/tools/web.d.ts.map +1 -0
- package/dist/oni-code/tools/web.js +375 -0
- package/dist/oni-code/tools/web.js.map +1 -0
- package/dist/oni-code/topology-agent-builder.d.ts +22 -0
- package/dist/oni-code/topology-agent-builder.d.ts.map +1 -0
- package/dist/oni-code/topology-agent-builder.js +220 -0
- package/dist/oni-code/topology-agent-builder.js.map +1 -0
- package/dist/oni-code/topology-selector.d.ts +85 -0
- package/dist/oni-code/topology-selector.d.ts.map +1 -0
- package/dist/oni-code/topology-selector.js +338 -0
- package/dist/oni-code/topology-selector.js.map +1 -0
- package/dist/oni-code/ui/App.d.ts +10 -0
- package/dist/oni-code/ui/App.d.ts.map +1 -0
- package/dist/oni-code/ui/App.js +395 -0
- package/dist/oni-code/ui/App.js.map +1 -0
- package/dist/oni-code/ui/FooterPanel.d.ts +16 -0
- package/dist/oni-code/ui/FooterPanel.d.ts.map +1 -0
- package/dist/oni-code/ui/FooterPanel.js +56 -0
- package/dist/oni-code/ui/FooterPanel.js.map +1 -0
- package/dist/oni-code/ui/Header.d.ts +21 -0
- package/dist/oni-code/ui/Header.d.ts.map +1 -0
- package/dist/oni-code/ui/Header.js +105 -0
- package/dist/oni-code/ui/Header.js.map +1 -0
- package/dist/oni-code/ui/InputArea.d.ts +11 -0
- package/dist/oni-code/ui/InputArea.d.ts.map +1 -0
- package/dist/oni-code/ui/InputArea.js +82 -0
- package/dist/oni-code/ui/InputArea.js.map +1 -0
- package/dist/oni-code/ui/MessageBlock.d.ts +11 -0
- package/dist/oni-code/ui/MessageBlock.d.ts.map +1 -0
- package/dist/oni-code/ui/MessageBlock.js +103 -0
- package/dist/oni-code/ui/MessageBlock.js.map +1 -0
- package/dist/oni-code/ui/OutputPane.d.ts +12 -0
- package/dist/oni-code/ui/OutputPane.d.ts.map +1 -0
- package/dist/oni-code/ui/OutputPane.js +8 -0
- package/dist/oni-code/ui/OutputPane.js.map +1 -0
- package/dist/oni-code/ui/PermissionPrompt.d.ts +11 -0
- package/dist/oni-code/ui/PermissionPrompt.d.ts.map +1 -0
- package/dist/oni-code/ui/PermissionPrompt.js +48 -0
- package/dist/oni-code/ui/PermissionPrompt.js.map +1 -0
- package/dist/oni-code/ui/QuestionPrompt.d.ts +8 -0
- package/dist/oni-code/ui/QuestionPrompt.d.ts.map +1 -0
- package/dist/oni-code/ui/QuestionPrompt.js +9 -0
- package/dist/oni-code/ui/QuestionPrompt.js.map +1 -0
- package/dist/oni-code/ui/StatusLine.d.ts +14 -0
- package/dist/oni-code/ui/StatusLine.d.ts.map +1 -0
- package/dist/oni-code/ui/StatusLine.js +23 -0
- package/dist/oni-code/ui/StatusLine.js.map +1 -0
- package/dist/oni-code/ui/SwarmPanel.d.ts +9 -0
- package/dist/oni-code/ui/SwarmPanel.d.ts.map +1 -0
- package/dist/oni-code/ui/SwarmPanel.js +52 -0
- package/dist/oni-code/ui/SwarmPanel.js.map +1 -0
- package/dist/oni-code/ui/ToolCallBlock.d.ts +10 -0
- package/dist/oni-code/ui/ToolCallBlock.d.ts.map +1 -0
- package/dist/oni-code/ui/ToolCallBlock.js +21 -0
- package/dist/oni-code/ui/ToolCallBlock.js.map +1 -0
- package/dist/oni-code/ui/Toolbar.d.ts +8 -0
- package/dist/oni-code/ui/Toolbar.d.ts.map +1 -0
- package/dist/oni-code/ui/Toolbar.js +11 -0
- package/dist/oni-code/ui/Toolbar.js.map +1 -0
- package/dist/oni-code/ui/WelcomeBanner.d.ts +12 -0
- package/dist/oni-code/ui/WelcomeBanner.d.ts.map +1 -0
- package/dist/oni-code/ui/WelcomeBanner.js +24 -0
- package/dist/oni-code/ui/WelcomeBanner.js.map +1 -0
- package/dist/oni-code/ui/activity.d.ts +15 -0
- package/dist/oni-code/ui/activity.d.ts.map +1 -0
- package/dist/oni-code/ui/activity.js +252 -0
- package/dist/oni-code/ui/activity.js.map +1 -0
- package/dist/oni-code/ui/banner.d.ts +16 -0
- package/dist/oni-code/ui/banner.d.ts.map +1 -0
- package/dist/oni-code/ui/banner.js +132 -0
- package/dist/oni-code/ui/banner.js.map +1 -0
- package/dist/oni-code/ui/command-menu.d.ts +7 -0
- package/dist/oni-code/ui/command-menu.d.ts.map +1 -0
- package/dist/oni-code/ui/command-menu.js +20 -0
- package/dist/oni-code/ui/command-menu.js.map +1 -0
- package/dist/oni-code/ui/diff.d.ts +17 -0
- package/dist/oni-code/ui/diff.d.ts.map +1 -0
- package/dist/oni-code/ui/diff.js +37 -0
- package/dist/oni-code/ui/diff.js.map +1 -0
- package/dist/oni-code/ui/format.d.ts +41 -0
- package/dist/oni-code/ui/format.d.ts.map +1 -0
- package/dist/oni-code/ui/format.js +223 -0
- package/dist/oni-code/ui/format.js.map +1 -0
- package/dist/oni-code/ui/input.d.ts +28 -0
- package/dist/oni-code/ui/input.d.ts.map +1 -0
- package/dist/oni-code/ui/input.js +216 -0
- package/dist/oni-code/ui/input.js.map +1 -0
- package/dist/oni-code/ui/insights.d.ts +39 -0
- package/dist/oni-code/ui/insights.d.ts.map +1 -0
- package/dist/oni-code/ui/insights.js +193 -0
- package/dist/oni-code/ui/insights.js.map +1 -0
- package/dist/oni-code/ui/markdown.d.ts +9 -0
- package/dist/oni-code/ui/markdown.d.ts.map +1 -0
- package/dist/oni-code/ui/markdown.js +44 -0
- package/dist/oni-code/ui/markdown.js.map +1 -0
- package/dist/oni-code/ui/panels.d.ts +39 -0
- package/dist/oni-code/ui/panels.d.ts.map +1 -0
- package/dist/oni-code/ui/panels.js +209 -0
- package/dist/oni-code/ui/panels.js.map +1 -0
- package/dist/oni-code/ui/paste.d.ts +17 -0
- package/dist/oni-code/ui/paste.d.ts.map +1 -0
- package/dist/oni-code/ui/paste.js +45 -0
- package/dist/oni-code/ui/paste.js.map +1 -0
- package/dist/oni-code/ui/raw-spinner.d.ts +37 -0
- package/dist/oni-code/ui/raw-spinner.d.ts.map +1 -0
- package/dist/oni-code/ui/raw-spinner.js +121 -0
- package/dist/oni-code/ui/raw-spinner.js.map +1 -0
- package/dist/oni-code/ui/session.d.ts +44 -0
- package/dist/oni-code/ui/session.d.ts.map +1 -0
- package/dist/oni-code/ui/session.js +93 -0
- package/dist/oni-code/ui/session.js.map +1 -0
- package/dist/oni-code/ui/spinner.d.ts +7 -0
- package/dist/oni-code/ui/spinner.d.ts.map +1 -0
- package/dist/oni-code/ui/spinner.js +20 -0
- package/dist/oni-code/ui/spinner.js.map +1 -0
- package/dist/oni-code/ui/swarm-activity.d.ts +50 -0
- package/dist/oni-code/ui/swarm-activity.d.ts.map +1 -0
- package/dist/oni-code/ui/swarm-activity.js +233 -0
- package/dist/oni-code/ui/swarm-activity.js.map +1 -0
- package/dist/oni-code/ui/terminal-size.d.ts +18 -0
- package/dist/oni-code/ui/terminal-size.d.ts.map +1 -0
- package/dist/oni-code/ui/terminal-size.js +45 -0
- package/dist/oni-code/ui/terminal-size.js.map +1 -0
- package/dist/oni-code/ui/theme.d.ts +82 -0
- package/dist/oni-code/ui/theme.d.ts.map +1 -0
- package/dist/oni-code/ui/theme.js +101 -0
- package/dist/oni-code/ui/theme.js.map +1 -0
- package/dist/oni-code/ui/tool-utils.d.ts +10 -0
- package/dist/oni-code/ui/tool-utils.d.ts.map +1 -0
- package/dist/oni-code/ui/tool-utils.js +82 -0
- package/dist/oni-code/ui/tool-utils.js.map +1 -0
- package/dist/oni-code/ui/useTerminalSize.d.ts +3 -0
- package/dist/oni-code/ui/useTerminalSize.d.ts.map +1 -0
- package/dist/oni-code/ui/useTerminalSize.js +16 -0
- package/dist/oni-code/ui/useTerminalSize.js.map +1 -0
- package/dist/oni-code/workspace/change-tracker.d.ts +18 -0
- package/dist/oni-code/workspace/change-tracker.d.ts.map +1 -0
- package/dist/oni-code/workspace/change-tracker.js +67 -0
- package/dist/oni-code/workspace/change-tracker.js.map +1 -0
- package/dist/oni-code/workspace/conflict-detector.d.ts +12 -0
- package/dist/oni-code/workspace/conflict-detector.d.ts.map +1 -0
- package/dist/oni-code/workspace/conflict-detector.js +24 -0
- package/dist/oni-code/workspace/conflict-detector.js.map +1 -0
- package/dist/oni-code/workspace/file-snapshots.d.ts +39 -0
- package/dist/oni-code/workspace/file-snapshots.d.ts.map +1 -0
- package/dist/oni-code/workspace/file-snapshots.js +77 -0
- package/dist/oni-code/workspace/file-snapshots.js.map +1 -0
- package/dist/oni-code/workspace/index.d.ts +5 -0
- package/dist/oni-code/workspace/index.d.ts.map +1 -0
- package/dist/oni-code/workspace/index.js +5 -0
- package/dist/oni-code/workspace/index.js.map +1 -0
- package/dist/oni-code/workspace/project-map.d.ts +14 -0
- package/dist/oni-code/workspace/project-map.d.ts.map +1 -0
- package/dist/oni-code/workspace/project-map.js +91 -0
- package/dist/oni-code/workspace/project-map.js.map +1 -0
- package/dist/pregel.d.ts +4 -0
- package/dist/pregel.d.ts.map +1 -1
- package/dist/pregel.js +121 -54
- package/dist/pregel.js.map +1 -1
- package/dist/retry.d.ts.map +1 -1
- package/dist/retry.js +10 -3
- package/dist/retry.js.map +1 -1
- package/dist/sentinel/config/index.d.ts +2 -0
- package/dist/sentinel/config/index.d.ts.map +1 -0
- package/dist/sentinel/config/index.js +2 -0
- package/dist/sentinel/config/index.js.map +1 -0
- package/dist/sentinel/config/schema.d.ts +4 -0
- package/dist/sentinel/config/schema.d.ts.map +1 -0
- package/dist/sentinel/config/schema.js +42 -0
- package/dist/sentinel/config/schema.js.map +1 -0
- package/dist/sentinel/debate/index.d.ts +6 -0
- package/dist/sentinel/debate/index.d.ts.map +1 -0
- package/dist/sentinel/debate/index.js +64 -0
- package/dist/sentinel/debate/index.js.map +1 -0
- package/dist/sentinel/debate/prompts.d.ts +4 -0
- package/dist/sentinel/debate/prompts.d.ts.map +1 -0
- package/dist/sentinel/debate/prompts.js +13 -0
- package/dist/sentinel/debate/prompts.js.map +1 -0
- package/dist/sentinel/fix/index.d.ts +6 -0
- package/dist/sentinel/fix/index.d.ts.map +1 -0
- package/dist/sentinel/fix/index.js +27 -0
- package/dist/sentinel/fix/index.js.map +1 -0
- package/dist/sentinel/fix/strategies.d.ts +9 -0
- package/dist/sentinel/fix/strategies.d.ts.map +1 -0
- package/dist/sentinel/fix/strategies.js +40 -0
- package/dist/sentinel/fix/strategies.js.map +1 -0
- package/dist/sentinel/index.d.ts +14 -0
- package/dist/sentinel/index.d.ts.map +1 -0
- package/dist/sentinel/index.js +22 -0
- package/dist/sentinel/index.js.map +1 -0
- package/dist/sentinel/integrations/cli.d.ts +10 -0
- package/dist/sentinel/integrations/cli.d.ts.map +1 -0
- package/dist/sentinel/integrations/cli.js +24 -0
- package/dist/sentinel/integrations/cli.js.map +1 -0
- package/dist/sentinel/integrations/index.d.ts +2 -0
- package/dist/sentinel/integrations/index.d.ts.map +1 -0
- package/dist/sentinel/integrations/index.js +2 -0
- package/dist/sentinel/integrations/index.js.map +1 -0
- package/dist/sentinel/memory/index.d.ts +16 -0
- package/dist/sentinel/memory/index.d.ts.map +1 -0
- package/dist/sentinel/memory/index.js +60 -0
- package/dist/sentinel/memory/index.js.map +1 -0
- package/dist/sentinel/report/console.d.ts +3 -0
- package/dist/sentinel/report/console.d.ts.map +1 -0
- package/dist/sentinel/report/console.js +27 -0
- package/dist/sentinel/report/console.js.map +1 -0
- package/dist/sentinel/report/github.d.ts +3 -0
- package/dist/sentinel/report/github.d.ts.map +1 -0
- package/dist/sentinel/report/github.js +36 -0
- package/dist/sentinel/report/github.js.map +1 -0
- package/dist/sentinel/report/index.d.ts +6 -0
- package/dist/sentinel/report/index.d.ts.map +1 -0
- package/dist/sentinel/report/index.js +15 -0
- package/dist/sentinel/report/index.js.map +1 -0
- package/dist/sentinel/report/sarif.d.ts +3 -0
- package/dist/sentinel/report/sarif.d.ts.map +1 -0
- package/dist/sentinel/report/sarif.js +29 -0
- package/dist/sentinel/report/sarif.js.map +1 -0
- package/dist/sentinel/sentinel.d.ts +17 -0
- package/dist/sentinel/sentinel.d.ts.map +1 -0
- package/dist/sentinel/sentinel.js +111 -0
- package/dist/sentinel/sentinel.js.map +1 -0
- package/dist/sentinel/swarm/agents.d.ts +6 -0
- package/dist/sentinel/swarm/agents.d.ts.map +1 -0
- package/dist/sentinel/swarm/agents.js +36 -0
- package/dist/sentinel/swarm/agents.js.map +1 -0
- package/dist/sentinel/swarm/index.d.ts +8 -0
- package/dist/sentinel/swarm/index.d.ts.map +1 -0
- package/dist/sentinel/swarm/index.js +74 -0
- package/dist/sentinel/swarm/index.js.map +1 -0
- package/dist/sentinel/swarm/prompts.d.ts +2 -0
- package/dist/sentinel/swarm/prompts.d.ts.map +1 -0
- package/dist/sentinel/swarm/prompts.js +24 -0
- package/dist/sentinel/swarm/prompts.js.map +1 -0
- package/dist/sentinel/swarm/topology.d.ts +10 -0
- package/dist/sentinel/swarm/topology.d.ts.map +1 -0
- package/dist/sentinel/swarm/topology.js +38 -0
- package/dist/sentinel/swarm/topology.js.map +1 -0
- package/dist/sentinel/triage/analyzers/complexity-analyzer.d.ts +7 -0
- package/dist/sentinel/triage/analyzers/complexity-analyzer.d.ts.map +1 -0
- package/dist/sentinel/triage/analyzers/complexity-analyzer.js +94 -0
- package/dist/sentinel/triage/analyzers/complexity-analyzer.js.map +1 -0
- package/dist/sentinel/triage/analyzers/custom-analyzer.d.ts +19 -0
- package/dist/sentinel/triage/analyzers/custom-analyzer.d.ts.map +1 -0
- package/dist/sentinel/triage/analyzers/custom-analyzer.js +268 -0
- package/dist/sentinel/triage/analyzers/custom-analyzer.js.map +1 -0
- package/dist/sentinel/triage/analyzers/dependency-analyzer.d.ts +26 -0
- package/dist/sentinel/triage/analyzers/dependency-analyzer.d.ts.map +1 -0
- package/dist/sentinel/triage/analyzers/dependency-analyzer.js +220 -0
- package/dist/sentinel/triage/analyzers/dependency-analyzer.js.map +1 -0
- package/dist/sentinel/triage/analyzers/diff-analyzer.d.ts +12 -0
- package/dist/sentinel/triage/analyzers/diff-analyzer.d.ts.map +1 -0
- package/dist/sentinel/triage/analyzers/diff-analyzer.js +19 -0
- package/dist/sentinel/triage/analyzers/diff-analyzer.js.map +1 -0
- package/dist/sentinel/triage/analyzers/index.d.ts +14 -0
- package/dist/sentinel/triage/analyzers/index.d.ts.map +1 -0
- package/dist/sentinel/triage/analyzers/index.js +25 -0
- package/dist/sentinel/triage/analyzers/index.js.map +1 -0
- package/dist/sentinel/triage/analyzers/pattern-analyzer.d.ts +7 -0
- package/dist/sentinel/triage/analyzers/pattern-analyzer.d.ts.map +1 -0
- package/dist/sentinel/triage/analyzers/pattern-analyzer.js +180 -0
- package/dist/sentinel/triage/analyzers/pattern-analyzer.js.map +1 -0
- package/dist/sentinel/triage/analyzers/security-analyzer.d.ts +7 -0
- package/dist/sentinel/triage/analyzers/security-analyzer.d.ts.map +1 -0
- package/dist/sentinel/triage/analyzers/security-analyzer.js +96 -0
- package/dist/sentinel/triage/analyzers/security-analyzer.js.map +1 -0
- package/dist/sentinel/triage/analyzers/ts-parser.d.ts +71 -0
- package/dist/sentinel/triage/analyzers/ts-parser.d.ts.map +1 -0
- package/dist/sentinel/triage/analyzers/ts-parser.js +323 -0
- package/dist/sentinel/triage/analyzers/ts-parser.js.map +1 -0
- package/dist/sentinel/triage/analyzers/typescript-analyzer.d.ts +7 -0
- package/dist/sentinel/triage/analyzers/typescript-analyzer.d.ts.map +1 -0
- package/dist/sentinel/triage/analyzers/typescript-analyzer.js +68 -0
- package/dist/sentinel/triage/analyzers/typescript-analyzer.js.map +1 -0
- package/dist/sentinel/triage/index.d.ts +10 -0
- package/dist/sentinel/triage/index.d.ts.map +1 -0
- package/dist/sentinel/triage/index.js +39 -0
- package/dist/sentinel/triage/index.js.map +1 -0
- package/dist/sentinel/triage/scorer.d.ts +9 -0
- package/dist/sentinel/triage/scorer.d.ts.map +1 -0
- package/dist/sentinel/triage/scorer.js +28 -0
- package/dist/sentinel/triage/scorer.js.map +1 -0
- package/dist/sentinel/types.d.ts +125 -0
- package/dist/sentinel/types.d.ts.map +1 -0
- package/dist/sentinel/types.js +6 -0
- package/dist/sentinel/types.js.map +1 -0
- package/dist/store/index.d.ts +3 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +17 -0
- package/dist/store/index.js.map +1 -1
- package/dist/streaming.d.ts +4 -1
- package/dist/streaming.d.ts.map +1 -1
- package/dist/streaming.js +21 -7
- package/dist/streaming.js.map +1 -1
- package/dist/swarm/graph.d.ts +81 -2
- package/dist/swarm/graph.d.ts.map +1 -1
- package/dist/swarm/graph.js +517 -32
- package/dist/swarm/graph.js.map +1 -1
- package/dist/swarm/index.d.ts +10 -2
- package/dist/swarm/index.d.ts.map +1 -1
- package/dist/swarm/index.js +6 -1
- package/dist/swarm/index.js.map +1 -1
- package/dist/swarm/mermaid.d.ts +10 -0
- package/dist/swarm/mermaid.d.ts.map +1 -0
- package/dist/swarm/mermaid.js +64 -0
- package/dist/swarm/mermaid.js.map +1 -0
- package/dist/swarm/pool.d.ts +9 -1
- package/dist/swarm/pool.d.ts.map +1 -1
- package/dist/swarm/pool.js +58 -10
- package/dist/swarm/pool.js.map +1 -1
- package/dist/swarm/registry.d.ts +11 -1
- package/dist/swarm/registry.d.ts.map +1 -1
- package/dist/swarm/registry.js +17 -3
- package/dist/swarm/registry.js.map +1 -1
- package/dist/swarm/scaling.d.ts +95 -0
- package/dist/swarm/scaling.d.ts.map +1 -0
- package/dist/swarm/scaling.js +214 -0
- package/dist/swarm/scaling.js.map +1 -0
- package/dist/swarm/snapshot.d.ts +51 -0
- package/dist/swarm/snapshot.d.ts.map +1 -0
- package/dist/swarm/snapshot.js +115 -0
- package/dist/swarm/snapshot.js.map +1 -0
- package/dist/swarm/supervisor.d.ts.map +1 -1
- package/dist/swarm/supervisor.js +82 -0
- package/dist/swarm/supervisor.js.map +1 -1
- package/dist/swarm/tracer.d.ts +57 -0
- package/dist/swarm/tracer.d.ts.map +1 -0
- package/dist/swarm/tracer.js +138 -0
- package/dist/swarm/tracer.js.map +1 -0
- package/dist/swarm/types.d.ts +23 -1
- package/dist/swarm/types.d.ts.map +1 -1
- package/dist/swarm/types.js.map +1 -1
- package/dist/tools/types.d.ts +2 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/package.json +160 -141
|
@@ -0,0 +1,873 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DefaultSwarmRunner — bridges the oni-code Conductor to ONI swarm primitives.
|
|
3
|
+
*
|
|
4
|
+
* Replaces NOOP_SWARM_RUNNER to make spawn_swarm actually dispatch real
|
|
5
|
+
* multi-agent work. Uses SwarmGraph topology factories, ONIHarness for
|
|
6
|
+
* agent creation, and returns summarized results to the conductor.
|
|
7
|
+
*/
|
|
8
|
+
import { StateGraph } from "../graph.js";
|
|
9
|
+
import { START, END } from "../types.js";
|
|
10
|
+
import { ONIHarness } from "../harness/harness.js";
|
|
11
|
+
import { SwarmGraph, baseSwarmChannels, } from "../swarm/graph.js";
|
|
12
|
+
import { makeCodingTools } from "./tools/coding.js";
|
|
13
|
+
import { makeWebTools } from "./tools/web.js";
|
|
14
|
+
import { makeSpawnSwarmTool } from "./tools/spawn-swarm.js";
|
|
15
|
+
import { ChangeTracker } from "./workspace/change-tracker.js";
|
|
16
|
+
import { ConflictDetector } from "./workspace/conflict-detector.js";
|
|
17
|
+
import { extractFileChange } from "./change-tracking.js";
|
|
18
|
+
import { generateCheckpointId, } from "./swarm-checkpoint.js";
|
|
19
|
+
// ── Config ───────────────────────────────────────────────────
|
|
20
|
+
/** Default total token budget for an entire swarm (16K per agent is reasonable) */
|
|
21
|
+
const DEFAULT_SWARM_MAX_TOKENS = 65536;
|
|
22
|
+
// ── Supported topologies ─────────────────────────────────────
|
|
23
|
+
const SUPPORTED_TOPOLOGIES = new Set([
|
|
24
|
+
"debate",
|
|
25
|
+
"fanOut",
|
|
26
|
+
"pipeline",
|
|
27
|
+
"hierarchical",
|
|
28
|
+
"mapReduce",
|
|
29
|
+
]);
|
|
30
|
+
// ── DefaultSwarmRunner ───────────────────────────────────────
|
|
31
|
+
// ── Tool tracking ────────────────────────────────────────────
|
|
32
|
+
/**
|
|
33
|
+
* Wraps an array of tools so that mutating tool calls (edit_file, write_file)
|
|
34
|
+
* automatically record changes to a ChangeTracker.
|
|
35
|
+
*/
|
|
36
|
+
function wrapToolsWithTracking(tools, tracker) {
|
|
37
|
+
return tools.map((tool) => ({
|
|
38
|
+
...tool,
|
|
39
|
+
execute: async (input, ctx) => {
|
|
40
|
+
const result = await tool.execute(input, ctx);
|
|
41
|
+
const change = extractFileChange(tool.name, input, result);
|
|
42
|
+
if (change) {
|
|
43
|
+
tracker.recordChange(change.file, change.type);
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
46
|
+
},
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Single-pass dual tracking — wraps tools so file changes are recorded
|
|
51
|
+
* in BOTH the per-agent tracker and the shared (swarm-wide) tracker
|
|
52
|
+
* with a single async wrapper instead of two nested wrappers.
|
|
53
|
+
*/
|
|
54
|
+
function wrapToolsWithDualTracking(tools, agentTracker, sharedTracker) {
|
|
55
|
+
return tools.map((tool) => ({
|
|
56
|
+
...tool,
|
|
57
|
+
execute: async (input, ctx) => {
|
|
58
|
+
const result = await tool.execute(input, ctx);
|
|
59
|
+
const change = extractFileChange(tool.name, input, result);
|
|
60
|
+
if (change) {
|
|
61
|
+
agentTracker.recordChange(change.file, change.type);
|
|
62
|
+
sharedTracker.recordChange(change.file, change.type);
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
},
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Filter tools to only those whose names appear in the allowed list.
|
|
70
|
+
* If the allowed list is empty, returns all tools (no restriction).
|
|
71
|
+
*/
|
|
72
|
+
function filterToolsByName(tools, allowedNames) {
|
|
73
|
+
if (allowedNames.length === 0)
|
|
74
|
+
return tools;
|
|
75
|
+
const nameSet = new Set(allowedNames);
|
|
76
|
+
return tools.filter((t) => nameSet.has(t.name));
|
|
77
|
+
}
|
|
78
|
+
export class DefaultSwarmRunner {
|
|
79
|
+
model;
|
|
80
|
+
fastModel;
|
|
81
|
+
rootDir;
|
|
82
|
+
conductorTracker;
|
|
83
|
+
maxTokens;
|
|
84
|
+
onProgress;
|
|
85
|
+
cacheTtlMs;
|
|
86
|
+
maxDepth;
|
|
87
|
+
currentDepth;
|
|
88
|
+
cache = new Map();
|
|
89
|
+
checkpointStore;
|
|
90
|
+
perAgentMaxTurns;
|
|
91
|
+
agentTimeout;
|
|
92
|
+
maxConcurrency;
|
|
93
|
+
eventBus;
|
|
94
|
+
/** Cached base tools — built once in constructor, reused across all run() calls */
|
|
95
|
+
baseTools;
|
|
96
|
+
swarmIdCounter = 0;
|
|
97
|
+
constructor(config) {
|
|
98
|
+
this.model = config.model;
|
|
99
|
+
this.fastModel = config.fastModel;
|
|
100
|
+
this.rootDir = config.rootDir;
|
|
101
|
+
this.conductorTracker = config.changeTracker;
|
|
102
|
+
this.maxTokens = config.maxTokens ?? DEFAULT_SWARM_MAX_TOKENS;
|
|
103
|
+
this.onProgress = config.onProgress;
|
|
104
|
+
this.cacheTtlMs = config.cacheTtlMs ?? 0;
|
|
105
|
+
this.maxDepth = config.maxDepth ?? 1;
|
|
106
|
+
this.currentDepth = config.currentDepth ?? 0;
|
|
107
|
+
this.checkpointStore = config.checkpointStore;
|
|
108
|
+
this.perAgentMaxTurns = config.perAgentMaxTurns ?? 5;
|
|
109
|
+
this.agentTimeout = config.agentTimeout ?? 300_000;
|
|
110
|
+
this.maxConcurrency = config.maxConcurrency;
|
|
111
|
+
this.eventBus = config.eventBus;
|
|
112
|
+
// Build base tools once — rootDir is immutable, factories are pure
|
|
113
|
+
this.baseTools = [...makeCodingTools(this.rootDir), ...makeWebTools()];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Returns the tool names that agents in this runner would receive.
|
|
117
|
+
* Useful for testing nesting configuration.
|
|
118
|
+
* @param _index — reserved for future per-agent scoping (currently unused)
|
|
119
|
+
*/
|
|
120
|
+
getAgentToolNames(_index) {
|
|
121
|
+
const names = this.baseTools.map((t) => t.name);
|
|
122
|
+
if (this.currentDepth + 1 < this.maxDepth) {
|
|
123
|
+
names.push("spawn_swarm");
|
|
124
|
+
}
|
|
125
|
+
return names;
|
|
126
|
+
}
|
|
127
|
+
/** Emit a progress event if a listener is registered, and bridge to EventBus */
|
|
128
|
+
emit(event) {
|
|
129
|
+
if (this.onProgress) {
|
|
130
|
+
this.onProgress(event);
|
|
131
|
+
}
|
|
132
|
+
// Bridge SwarmProgressEvent → EventBus lifecycle events
|
|
133
|
+
if (this.eventBus) {
|
|
134
|
+
const swarmId = event.swarmId ?? `swarm_${this.swarmIdCounter}`;
|
|
135
|
+
switch (event.type) {
|
|
136
|
+
case "swarm:start":
|
|
137
|
+
this.eventBus.emit({
|
|
138
|
+
type: "swarm.started",
|
|
139
|
+
swarmId,
|
|
140
|
+
topology: event.topology,
|
|
141
|
+
agentCount: event.agentCount,
|
|
142
|
+
timestamp: event.timestamp,
|
|
143
|
+
});
|
|
144
|
+
break;
|
|
145
|
+
case "swarm:complete":
|
|
146
|
+
this.eventBus.emit({
|
|
147
|
+
type: "swarm.completed",
|
|
148
|
+
swarmId,
|
|
149
|
+
topology: event.topology,
|
|
150
|
+
agentCount: event.agentCount,
|
|
151
|
+
duration: event.duration,
|
|
152
|
+
durationMs: (event.duration ?? 0) * 1000,
|
|
153
|
+
outcome: event.detail,
|
|
154
|
+
timestamp: event.timestamp,
|
|
155
|
+
});
|
|
156
|
+
break;
|
|
157
|
+
case "swarm:error":
|
|
158
|
+
this.eventBus.emit({
|
|
159
|
+
type: "swarm.completed",
|
|
160
|
+
swarmId,
|
|
161
|
+
topology: event.topology,
|
|
162
|
+
agentCount: event.agentCount,
|
|
163
|
+
duration: event.duration,
|
|
164
|
+
durationMs: (event.duration ?? 0) * 1000,
|
|
165
|
+
outcome: event.detail ? `ERROR: ${event.detail}` : "ERROR: swarm failed",
|
|
166
|
+
agentResults: event.detail ? { error: event.detail } : { error: "Swarm failed" },
|
|
167
|
+
timestamp: event.timestamp,
|
|
168
|
+
});
|
|
169
|
+
break;
|
|
170
|
+
case "agent:start":
|
|
171
|
+
this.eventBus.emit({
|
|
172
|
+
type: "swarm.agent.started",
|
|
173
|
+
swarmId,
|
|
174
|
+
agentName: event.agentId ?? "unknown",
|
|
175
|
+
agentRole: event.agentRole,
|
|
176
|
+
timestamp: event.timestamp,
|
|
177
|
+
});
|
|
178
|
+
break;
|
|
179
|
+
case "agent:complete":
|
|
180
|
+
this.eventBus.emit({
|
|
181
|
+
type: "swarm.agent.completed",
|
|
182
|
+
swarmId,
|
|
183
|
+
agentName: event.agentId ?? "unknown",
|
|
184
|
+
agentRole: event.agentRole,
|
|
185
|
+
durationMs: (event.duration ?? 0) * 1000,
|
|
186
|
+
timestamp: event.timestamp,
|
|
187
|
+
});
|
|
188
|
+
break;
|
|
189
|
+
case "agent:error":
|
|
190
|
+
this.eventBus.emit({
|
|
191
|
+
type: "swarm.agent.failed",
|
|
192
|
+
swarmId,
|
|
193
|
+
agentName: event.agentId ?? "unknown",
|
|
194
|
+
agentRole: event.agentRole,
|
|
195
|
+
error: event.detail ?? "Unknown error",
|
|
196
|
+
timestamp: event.timestamp,
|
|
197
|
+
});
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/** Build a deterministic cache key from topology + task + agent IDs */
|
|
203
|
+
cacheKey(config) {
|
|
204
|
+
const agentKey = config.agents.map((a) => a.id).sort().join(",");
|
|
205
|
+
return `${config.topology}::${config.task}::${agentKey}`;
|
|
206
|
+
}
|
|
207
|
+
/** Look up a cached result. Returns undefined on miss or expiry. */
|
|
208
|
+
getCached(key) {
|
|
209
|
+
const entry = this.cache.get(key);
|
|
210
|
+
if (!entry)
|
|
211
|
+
return undefined;
|
|
212
|
+
if (Date.now() > entry.expiresAt) {
|
|
213
|
+
this.cache.delete(key);
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
return entry.result;
|
|
217
|
+
}
|
|
218
|
+
async run(config, perCallProgress, opts) {
|
|
219
|
+
// Save original onProgress to restore after this call
|
|
220
|
+
const originalOnProgress = this.onProgress;
|
|
221
|
+
if (perCallProgress) {
|
|
222
|
+
// Per-call callback takes priority; chain with constructor callback
|
|
223
|
+
this.onProgress = (event) => {
|
|
224
|
+
perCallProgress(event);
|
|
225
|
+
if (originalOnProgress)
|
|
226
|
+
originalOnProgress(event);
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
try {
|
|
230
|
+
return await this._runImpl(config, opts?.signal);
|
|
231
|
+
}
|
|
232
|
+
finally {
|
|
233
|
+
this.onProgress = originalOnProgress;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async _runImpl(config, signal) {
|
|
237
|
+
this.swarmIdCounter++;
|
|
238
|
+
const startTime = Date.now();
|
|
239
|
+
const swarmId = `swarm_${startTime.toString(36)}_${this.swarmIdCounter.toString(36)}`;
|
|
240
|
+
// ── Early abort check ────────────────────────────────────
|
|
241
|
+
if (signal?.aborted) {
|
|
242
|
+
return {
|
|
243
|
+
outcome: "Swarm aborted before start.",
|
|
244
|
+
agentSummaries: [],
|
|
245
|
+
filesModified: [],
|
|
246
|
+
duration: (Date.now() - startTime) / 1000,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
// ── Cache lookup ──────────────────────────────────────────
|
|
250
|
+
if (this.cacheTtlMs > 0) {
|
|
251
|
+
const cached = this.getCached(this.cacheKey(config));
|
|
252
|
+
if (cached)
|
|
253
|
+
return cached;
|
|
254
|
+
}
|
|
255
|
+
const agentIds = config.agents.map((a) => a.id);
|
|
256
|
+
this.emit({
|
|
257
|
+
type: "swarm:start",
|
|
258
|
+
timestamp: Date.now(),
|
|
259
|
+
swarmId,
|
|
260
|
+
topology: config.topology,
|
|
261
|
+
agentCount: config.agents.length,
|
|
262
|
+
agentIds,
|
|
263
|
+
});
|
|
264
|
+
try {
|
|
265
|
+
if (!SUPPORTED_TOPOLOGIES.has(config.topology)) {
|
|
266
|
+
this.emit({
|
|
267
|
+
type: "swarm:complete",
|
|
268
|
+
timestamp: Date.now(),
|
|
269
|
+
swarmId,
|
|
270
|
+
duration: (Date.now() - startTime) / 1000,
|
|
271
|
+
topology: config.topology,
|
|
272
|
+
agentCount: config.agents.length,
|
|
273
|
+
detail: `Unsupported topology: ${config.topology}`,
|
|
274
|
+
});
|
|
275
|
+
return {
|
|
276
|
+
outcome: `Topology "${config.topology}" requires manual configuration (handoffs/teams) that cannot be auto-generated. Supported auto-topologies: ${[...SUPPORTED_TOPOLOGIES].join(", ")}`,
|
|
277
|
+
agentSummaries: [],
|
|
278
|
+
filesModified: [],
|
|
279
|
+
duration: (Date.now() - startTime) / 1000,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
this.emit({
|
|
283
|
+
type: "swarm:topology-resolved",
|
|
284
|
+
timestamp: Date.now(),
|
|
285
|
+
swarmId,
|
|
286
|
+
topology: config.topology,
|
|
287
|
+
});
|
|
288
|
+
// Compute per-agent token budget
|
|
289
|
+
const agentCount = config.agents.length;
|
|
290
|
+
const perAgentTokens = Math.floor(this.maxTokens / Math.max(agentCount, 1));
|
|
291
|
+
// Build per-agent change trackers for file modification tracking
|
|
292
|
+
const perAgentTrackers = new Map();
|
|
293
|
+
const sharedTracker = new ChangeTracker();
|
|
294
|
+
// Use cached base tools — spread to allow per-run additions (e.g. spawn_swarm)
|
|
295
|
+
const allTools = [...this.baseTools];
|
|
296
|
+
// If nesting is allowed, add spawn_swarm backed by a child runner
|
|
297
|
+
if (this.currentDepth + 1 < this.maxDepth) {
|
|
298
|
+
const childRunner = new DefaultSwarmRunner({
|
|
299
|
+
model: this.model,
|
|
300
|
+
fastModel: this.fastModel,
|
|
301
|
+
rootDir: this.rootDir,
|
|
302
|
+
changeTracker: this.conductorTracker,
|
|
303
|
+
maxTokens: Math.floor(this.maxTokens / 2), // child gets half the budget
|
|
304
|
+
maxDepth: this.maxDepth,
|
|
305
|
+
currentDepth: this.currentDepth + 1,
|
|
306
|
+
perAgentMaxTurns: this.perAgentMaxTurns,
|
|
307
|
+
agentTimeout: this.agentTimeout,
|
|
308
|
+
maxConcurrency: this.maxConcurrency,
|
|
309
|
+
eventBus: this.eventBus,
|
|
310
|
+
});
|
|
311
|
+
allTools.push(makeSpawnSwarmTool(childRunner));
|
|
312
|
+
}
|
|
313
|
+
const agentDefs = config.agents.map((input) => {
|
|
314
|
+
const agentTracker = new ChangeTracker();
|
|
315
|
+
perAgentTrackers.set(input.id, agentTracker);
|
|
316
|
+
// Per-agent tool scoping: use agent-level tools if set, else swarm-level
|
|
317
|
+
const allowedNames = input.tools ?? config.tools;
|
|
318
|
+
const scopedTools = filterToolsByName(allTools, allowedNames);
|
|
319
|
+
// Single-pass wrapper: records file changes in both per-agent and shared trackers
|
|
320
|
+
const trackedTools = wrapToolsWithDualTracking(scopedTools, agentTracker, sharedTracker);
|
|
321
|
+
return this.buildAgentDef(input, trackedTools, config.maxTurns, perAgentTokens, swarmId);
|
|
322
|
+
});
|
|
323
|
+
this.emit({
|
|
324
|
+
type: "swarm:agents-built",
|
|
325
|
+
timestamp: Date.now(),
|
|
326
|
+
swarmId,
|
|
327
|
+
topology: config.topology,
|
|
328
|
+
agentCount: agentDefs.length,
|
|
329
|
+
agentIds: agentDefs.map((a) => a.id),
|
|
330
|
+
});
|
|
331
|
+
// ── Abort check before graph compilation ──────────────────
|
|
332
|
+
if (signal?.aborted) {
|
|
333
|
+
return {
|
|
334
|
+
outcome: "Swarm aborted before graph compilation.",
|
|
335
|
+
agentSummaries: [],
|
|
336
|
+
filesModified: [],
|
|
337
|
+
duration: (Date.now() - startTime) / 1000,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
// Build and compile the swarm graph
|
|
341
|
+
const swarmGraph = this.buildTopology(config, agentDefs);
|
|
342
|
+
const skeleton = swarmGraph.compile();
|
|
343
|
+
// Invoke with initial state, enforcing agentTimeout + abort signal as deadline
|
|
344
|
+
const invokePromise = skeleton.invoke({
|
|
345
|
+
task: config.task,
|
|
346
|
+
context: {},
|
|
347
|
+
agentResults: {},
|
|
348
|
+
messages: [],
|
|
349
|
+
swarmMessages: [],
|
|
350
|
+
supervisorRound: 0,
|
|
351
|
+
currentAgent: null,
|
|
352
|
+
done: false,
|
|
353
|
+
handoffHistory: [],
|
|
354
|
+
});
|
|
355
|
+
// Build race competitors: invoke vs timeout vs abort signal
|
|
356
|
+
const raceCompetitors = [invokePromise];
|
|
357
|
+
if (this.agentTimeout > 0) {
|
|
358
|
+
raceCompetitors.push(new Promise((_, reject) => {
|
|
359
|
+
const timer = setTimeout(() => reject(new Error(`Swarm timed out after ${this.agentTimeout}ms`)), this.agentTimeout);
|
|
360
|
+
if (typeof timer === "object" && "unref" in timer)
|
|
361
|
+
timer.unref();
|
|
362
|
+
}));
|
|
363
|
+
}
|
|
364
|
+
if (signal && !signal.aborted) {
|
|
365
|
+
raceCompetitors.push(new Promise((_, reject) => {
|
|
366
|
+
signal.addEventListener("abort", () => {
|
|
367
|
+
reject(new Error("Swarm aborted by user"));
|
|
368
|
+
}, { once: true });
|
|
369
|
+
}));
|
|
370
|
+
}
|
|
371
|
+
const finalState = await Promise.race(raceCompetitors);
|
|
372
|
+
const duration = (Date.now() - startTime) / 1000;
|
|
373
|
+
// Detect conflicts: multiple agents modifying the same file
|
|
374
|
+
const conflicts = this.detectConflicts(perAgentTrackers);
|
|
375
|
+
// Merge tracked changes into conductor's tracker
|
|
376
|
+
this.mergeIntoConductorTracker(sharedTracker);
|
|
377
|
+
const result = this.extractResults(finalState, config, duration, sharedTracker.getChangedFiles(), conflicts);
|
|
378
|
+
this.emit({
|
|
379
|
+
type: "swarm:complete",
|
|
380
|
+
timestamp: Date.now(),
|
|
381
|
+
swarmId,
|
|
382
|
+
duration,
|
|
383
|
+
topology: config.topology,
|
|
384
|
+
agentCount: config.agents.length,
|
|
385
|
+
});
|
|
386
|
+
// ── Cache store (clean successes only) ───────────────────
|
|
387
|
+
// Don't cache results with error indicators — retries may succeed
|
|
388
|
+
const hasErrors = this.resultHasErrors(result);
|
|
389
|
+
if (this.cacheTtlMs > 0 && !hasErrors) {
|
|
390
|
+
this.cache.set(this.cacheKey(config), {
|
|
391
|
+
result,
|
|
392
|
+
expiresAt: Date.now() + this.cacheTtlMs,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
// ── Checkpoint degraded results ───────────────────────────
|
|
396
|
+
// If the swarm "completed" but all agents produced empty/error output,
|
|
397
|
+
// store a checkpoint so the conductor can offer to resume.
|
|
398
|
+
if (hasErrors && this.checkpointStore) {
|
|
399
|
+
const checkpointId = generateCheckpointId();
|
|
400
|
+
const checkpoint = {
|
|
401
|
+
id: checkpointId,
|
|
402
|
+
topology: config.topology,
|
|
403
|
+
task: config.task,
|
|
404
|
+
completedResults: this.extractCompletedResults(result),
|
|
405
|
+
pendingAgents: this.extractPendingAgents(config, result),
|
|
406
|
+
timestamp: Date.now(),
|
|
407
|
+
config,
|
|
408
|
+
};
|
|
409
|
+
this.checkpointStore.save(checkpoint);
|
|
410
|
+
this.emit({
|
|
411
|
+
type: "swarm:checkpoint-created",
|
|
412
|
+
timestamp: Date.now(),
|
|
413
|
+
swarmId,
|
|
414
|
+
detail: checkpointId,
|
|
415
|
+
topology: config.topology,
|
|
416
|
+
});
|
|
417
|
+
return { ...result, checkpointId };
|
|
418
|
+
}
|
|
419
|
+
return result;
|
|
420
|
+
}
|
|
421
|
+
catch (err) {
|
|
422
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
423
|
+
const duration = (Date.now() - startTime) / 1000;
|
|
424
|
+
this.emit({
|
|
425
|
+
type: "swarm:error",
|
|
426
|
+
timestamp: Date.now(),
|
|
427
|
+
swarmId,
|
|
428
|
+
duration,
|
|
429
|
+
topology: config.topology,
|
|
430
|
+
agentCount: config.agents.length,
|
|
431
|
+
detail: message,
|
|
432
|
+
});
|
|
433
|
+
// Create checkpoint for resumption if a store is configured
|
|
434
|
+
let checkpointId;
|
|
435
|
+
if (this.checkpointStore) {
|
|
436
|
+
checkpointId = generateCheckpointId();
|
|
437
|
+
const checkpoint = {
|
|
438
|
+
id: checkpointId,
|
|
439
|
+
topology: config.topology,
|
|
440
|
+
task: config.task,
|
|
441
|
+
completedResults: {},
|
|
442
|
+
pendingAgents: config.agents,
|
|
443
|
+
timestamp: Date.now(),
|
|
444
|
+
config,
|
|
445
|
+
};
|
|
446
|
+
this.checkpointStore.save(checkpoint);
|
|
447
|
+
this.emit({
|
|
448
|
+
type: "swarm:checkpoint-created",
|
|
449
|
+
timestamp: Date.now(),
|
|
450
|
+
swarmId,
|
|
451
|
+
detail: checkpointId,
|
|
452
|
+
topology: config.topology,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
return {
|
|
456
|
+
outcome: `ERROR: Swarm execution failed: ${message}`,
|
|
457
|
+
agentSummaries: [],
|
|
458
|
+
filesModified: [],
|
|
459
|
+
duration,
|
|
460
|
+
checkpointId,
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
// ── Resume from checkpoint ──────────────────────────────────
|
|
465
|
+
/**
|
|
466
|
+
* Resume a previously failed swarm from its checkpoint.
|
|
467
|
+
* Re-runs the swarm using the stored config. On success, the checkpoint
|
|
468
|
+
* is deleted. On failure, a new checkpoint is stored (or the existing
|
|
469
|
+
* one is preserved).
|
|
470
|
+
*
|
|
471
|
+
* @param checkpointId — the ID returned in the failed run's result
|
|
472
|
+
* @throws if no checkpoint store is configured or the checkpoint is not found
|
|
473
|
+
*/
|
|
474
|
+
async resume(checkpointId) {
|
|
475
|
+
if (!this.checkpointStore) {
|
|
476
|
+
throw new Error("Checkpoint store not configured — cannot resume swarm. " +
|
|
477
|
+
"Pass a SwarmCheckpointStore in the runner config.");
|
|
478
|
+
}
|
|
479
|
+
const checkpoint = this.checkpointStore.get(checkpointId);
|
|
480
|
+
if (!checkpoint) {
|
|
481
|
+
throw new Error(`Checkpoint "${checkpointId}" not found (it may have expired or been deleted).`);
|
|
482
|
+
}
|
|
483
|
+
// Delete the old checkpoint — run() will create a new one if it fails again
|
|
484
|
+
this.checkpointStore.delete(checkpointId);
|
|
485
|
+
// Re-run the swarm with the stored config
|
|
486
|
+
return this.run(checkpoint.config);
|
|
487
|
+
}
|
|
488
|
+
// ── Build a SwarmAgentDef from SwarmAgentInput ──────────────
|
|
489
|
+
buildAgentDef(input, tools, maxTurns, maxTokens, swarmId) {
|
|
490
|
+
const harness = ONIHarness.create({
|
|
491
|
+
model: this.model,
|
|
492
|
+
fastModel: this.fastModel,
|
|
493
|
+
sharedTools: tools,
|
|
494
|
+
maxTokens,
|
|
495
|
+
});
|
|
496
|
+
// asNode returns (state) => Promise<Partial<state>> that reads state.task
|
|
497
|
+
// and writes to state.agentResults[agentName]
|
|
498
|
+
const nodeFunc = harness.asNode({
|
|
499
|
+
name: input.id,
|
|
500
|
+
soul: input.systemPrompt,
|
|
501
|
+
maxTurns: Math.min(maxTurns, this.perAgentMaxTurns),
|
|
502
|
+
});
|
|
503
|
+
// Wrap in a single-node graph to produce a skeleton
|
|
504
|
+
const g = new StateGraph({
|
|
505
|
+
channels: baseSwarmChannels,
|
|
506
|
+
});
|
|
507
|
+
g.addNode("work", nodeFunc);
|
|
508
|
+
g.addEdge(START, "work");
|
|
509
|
+
g.addEdge("work", END);
|
|
510
|
+
// Build lifecycle hooks that emit agent-level progress events
|
|
511
|
+
const hooks = this.buildAgentHooks(input.id, input.role, swarmId);
|
|
512
|
+
return {
|
|
513
|
+
id: input.id,
|
|
514
|
+
role: input.role,
|
|
515
|
+
capabilities: [{ name: "work", description: input.systemPrompt }],
|
|
516
|
+
skeleton: g.compile(),
|
|
517
|
+
hooks,
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
// ── Agent lifecycle hooks for observability ────────────────
|
|
521
|
+
/**
|
|
522
|
+
* Create AgentLifecycleHooks that emit agent-level progress events
|
|
523
|
+
* (agent:start, agent:complete, agent:error) through the onProgress callback.
|
|
524
|
+
*/
|
|
525
|
+
buildAgentHooks(agentId, agentRole, swarmId) {
|
|
526
|
+
// Capture the start timestamp per agent to compute duration on complete
|
|
527
|
+
let startTime = 0;
|
|
528
|
+
return {
|
|
529
|
+
onStart: (_id) => {
|
|
530
|
+
startTime = Date.now();
|
|
531
|
+
this.emit({
|
|
532
|
+
type: "agent:start",
|
|
533
|
+
timestamp: Date.now(),
|
|
534
|
+
swarmId,
|
|
535
|
+
agentId,
|
|
536
|
+
agentRole,
|
|
537
|
+
});
|
|
538
|
+
},
|
|
539
|
+
onComplete: (_id, result) => {
|
|
540
|
+
const duration = startTime > 0
|
|
541
|
+
? (Date.now() - startTime) / 1000
|
|
542
|
+
: 0;
|
|
543
|
+
// Detect if the harness returned an empty/error result
|
|
544
|
+
// (model errors are caught internally by the harness and produce empty output)
|
|
545
|
+
const isEmptyResult = this.isAgentResultEmpty(agentId, result);
|
|
546
|
+
if (isEmptyResult) {
|
|
547
|
+
this.emit({
|
|
548
|
+
type: "agent:error",
|
|
549
|
+
timestamp: Date.now(),
|
|
550
|
+
swarmId,
|
|
551
|
+
agentId,
|
|
552
|
+
agentRole,
|
|
553
|
+
duration,
|
|
554
|
+
detail: "Agent produced empty result (model may have failed)",
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
this.emit({
|
|
559
|
+
type: "agent:complete",
|
|
560
|
+
timestamp: Date.now(),
|
|
561
|
+
swarmId,
|
|
562
|
+
agentId,
|
|
563
|
+
agentRole,
|
|
564
|
+
duration,
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
onError: (_id, error) => {
|
|
569
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
570
|
+
this.emit({
|
|
571
|
+
type: "agent:error",
|
|
572
|
+
timestamp: Date.now(),
|
|
573
|
+
swarmId,
|
|
574
|
+
agentId,
|
|
575
|
+
agentRole,
|
|
576
|
+
detail: message,
|
|
577
|
+
});
|
|
578
|
+
},
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Check if an agent result is empty/error.
|
|
583
|
+
* The harness catches model errors internally and returns an empty string
|
|
584
|
+
* as the agent result, so we detect that condition here.
|
|
585
|
+
*/
|
|
586
|
+
isAgentResultEmpty(agentId, result) {
|
|
587
|
+
if (result == null)
|
|
588
|
+
return true;
|
|
589
|
+
if (typeof result !== "object")
|
|
590
|
+
return false;
|
|
591
|
+
const obj = result;
|
|
592
|
+
const agentResults = obj.agentResults;
|
|
593
|
+
if (!agentResults)
|
|
594
|
+
return false;
|
|
595
|
+
const agentOutput = agentResults[agentId];
|
|
596
|
+
if (agentOutput == null)
|
|
597
|
+
return true;
|
|
598
|
+
if (typeof agentOutput === "string" && agentOutput.trim() === "")
|
|
599
|
+
return true;
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
// ── Topology selection ─────────────────────────────────────
|
|
603
|
+
buildTopology(config, agents) {
|
|
604
|
+
switch (config.topology) {
|
|
605
|
+
case "debate":
|
|
606
|
+
return this.buildDebate(config, agents);
|
|
607
|
+
case "fanOut":
|
|
608
|
+
return this.buildFanOut(agents, this.maxConcurrency);
|
|
609
|
+
case "pipeline":
|
|
610
|
+
return this.buildPipeline(agents);
|
|
611
|
+
case "hierarchical":
|
|
612
|
+
return this.buildHierarchical(config, agents);
|
|
613
|
+
case "mapReduce":
|
|
614
|
+
return this.buildMapReduce(config, agents);
|
|
615
|
+
default:
|
|
616
|
+
throw new Error(`Unsupported topology: ${config.topology}`);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
// ── Debate ─────────────────────────────────────────────────
|
|
620
|
+
buildDebate(config, agents) {
|
|
621
|
+
const judgeModel = this.fastModel ?? this.model;
|
|
622
|
+
const maxRounds = config.judge?.maxRounds ?? 3;
|
|
623
|
+
const consensusKeyword = config.judge?.consensusKeyword ?? "CONSENSUS";
|
|
624
|
+
return SwarmGraph.debate({
|
|
625
|
+
debaters: agents,
|
|
626
|
+
judge: {
|
|
627
|
+
model: judgeModel,
|
|
628
|
+
maxRounds,
|
|
629
|
+
consensusKeyword,
|
|
630
|
+
systemPrompt: "You are a debate judge. Evaluate the arguments and determine if consensus has been reached.",
|
|
631
|
+
},
|
|
632
|
+
topic: "task",
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
// ── FanOut ─────────────────────────────────────────────────
|
|
636
|
+
buildFanOut(agents, maxConcurrency) {
|
|
637
|
+
return SwarmGraph.fanOut({
|
|
638
|
+
agents,
|
|
639
|
+
maxConcurrency,
|
|
640
|
+
reducer: (agentResults) => {
|
|
641
|
+
// Default reducer: merge all results into a combined outcome
|
|
642
|
+
const summaries = Object.entries(agentResults)
|
|
643
|
+
.map(([id, result]) => {
|
|
644
|
+
const text = typeof result === "string" ? result : this.extractAgentText(result, id);
|
|
645
|
+
return `[${id}]: ${text}`;
|
|
646
|
+
})
|
|
647
|
+
.join("\n\n");
|
|
648
|
+
return {
|
|
649
|
+
context: { combinedResults: summaries },
|
|
650
|
+
};
|
|
651
|
+
},
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
// ── Pipeline ───────────────────────────────────────────────
|
|
655
|
+
buildPipeline(agents) {
|
|
656
|
+
return SwarmGraph.pipeline({
|
|
657
|
+
stages: agents,
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
// ── Hierarchical ───────────────────────────────────────────
|
|
661
|
+
buildHierarchical(config, agents) {
|
|
662
|
+
const supervisorModel = this.fastModel ?? this.model;
|
|
663
|
+
return SwarmGraph.hierarchical({
|
|
664
|
+
supervisor: {
|
|
665
|
+
model: supervisorModel,
|
|
666
|
+
strategy: "llm",
|
|
667
|
+
maxRounds: config.maxTurns,
|
|
668
|
+
systemPrompt: "You are a supervisor coordinating worker agents. Route tasks to the most appropriate agent based on their capabilities. Respond with just the agent ID, or DONE when the task is complete.",
|
|
669
|
+
},
|
|
670
|
+
agents,
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
// ── MapReduce ──────────────────────────────────────────────
|
|
674
|
+
buildMapReduce(config, agents) {
|
|
675
|
+
// Use first agent as the mapper template, pool across all agents
|
|
676
|
+
const mapper = agents[0];
|
|
677
|
+
return SwarmGraph.mapReduce({
|
|
678
|
+
mapper,
|
|
679
|
+
poolSize: agents.length,
|
|
680
|
+
inputField: "task",
|
|
681
|
+
reducer: (agentResults) => {
|
|
682
|
+
const combined = Object.entries(agentResults)
|
|
683
|
+
.map(([id, result]) => {
|
|
684
|
+
const text = typeof result === "string" ? result : this.extractAgentText(result, id);
|
|
685
|
+
return `[${id}]: ${text}`;
|
|
686
|
+
})
|
|
687
|
+
.join("\n\n");
|
|
688
|
+
return {
|
|
689
|
+
context: { reducedResult: combined },
|
|
690
|
+
};
|
|
691
|
+
},
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
// ── Conflict detection ──────────────────────────────────────
|
|
695
|
+
detectConflicts(perAgentTrackers) {
|
|
696
|
+
const detector = new ConflictDetector();
|
|
697
|
+
const estimates = [...perAgentTrackers.entries()].map(([agentId, tracker]) => ({
|
|
698
|
+
id: agentId,
|
|
699
|
+
estimatedFiles: tracker.getChangedFiles(),
|
|
700
|
+
}));
|
|
701
|
+
return detector.findConflicts(estimates);
|
|
702
|
+
}
|
|
703
|
+
// ── Merge into conductor tracker ───────────────────────────
|
|
704
|
+
mergeIntoConductorTracker(swarmTracker) {
|
|
705
|
+
if (!this.conductorTracker)
|
|
706
|
+
return;
|
|
707
|
+
for (const file of swarmTracker.getChangedFiles()) {
|
|
708
|
+
const type = swarmTracker.getChangeType(file);
|
|
709
|
+
if (type) {
|
|
710
|
+
this.conductorTracker.recordChange(file, type);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
// ── Result extraction ──────────────────────────────────────
|
|
715
|
+
/**
|
|
716
|
+
* Extract meaningful text from an agent result.
|
|
717
|
+
* Agent results can be strings (simple), or full BaseSwarmState objects
|
|
718
|
+
* (pipeline/hierarchical), which contain nested agentResults, messages, etc.
|
|
719
|
+
* We dig through the layers to find actual text content.
|
|
720
|
+
*/
|
|
721
|
+
extractAgentText(result, agentId) {
|
|
722
|
+
if (typeof result === "string")
|
|
723
|
+
return result;
|
|
724
|
+
if (result == null)
|
|
725
|
+
return "";
|
|
726
|
+
const obj = result;
|
|
727
|
+
// 0. Error marker objects: { _error: true, error: "..." }
|
|
728
|
+
if (obj._error) {
|
|
729
|
+
return typeof obj.error === "string" ? obj.error : JSON.stringify(result);
|
|
730
|
+
}
|
|
731
|
+
// 1. Check nested agentResults for the agent's own text output
|
|
732
|
+
if (obj.agentResults && typeof obj.agentResults === "object") {
|
|
733
|
+
const nested = obj.agentResults;
|
|
734
|
+
// Try the agent's own ID first
|
|
735
|
+
if (agentId && nested[agentId] != null) {
|
|
736
|
+
const inner = this.extractAgentText(nested[agentId], agentId);
|
|
737
|
+
if (inner)
|
|
738
|
+
return inner;
|
|
739
|
+
}
|
|
740
|
+
// Otherwise, collect all agent result texts
|
|
741
|
+
const texts = Object.entries(nested)
|
|
742
|
+
.map(([id, val]) => {
|
|
743
|
+
const text = this.extractAgentText(val, id);
|
|
744
|
+
return text ? `[${id}]: ${text}` : null;
|
|
745
|
+
})
|
|
746
|
+
.filter(Boolean);
|
|
747
|
+
if (texts.length > 0)
|
|
748
|
+
return texts.join("\n\n");
|
|
749
|
+
}
|
|
750
|
+
// 2. Check messages for the last assistant message
|
|
751
|
+
if (Array.isArray(obj.messages) && obj.messages.length > 0) {
|
|
752
|
+
const lastAssistant = [...obj.messages]
|
|
753
|
+
.reverse()
|
|
754
|
+
.find((m) => m.role === "assistant");
|
|
755
|
+
if (lastAssistant && typeof lastAssistant.content === "string") {
|
|
756
|
+
const content = lastAssistant.content;
|
|
757
|
+
if (content.trim())
|
|
758
|
+
return content;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
// 3. Check context for combined/reduced results
|
|
762
|
+
if (obj.context && typeof obj.context === "object") {
|
|
763
|
+
const ctx = obj.context;
|
|
764
|
+
if (typeof ctx.combinedResults === "string")
|
|
765
|
+
return ctx.combinedResults;
|
|
766
|
+
if (typeof ctx.reducedResult === "string")
|
|
767
|
+
return ctx.reducedResult;
|
|
768
|
+
}
|
|
769
|
+
// 4. If this looks like a swarm state (has task, done, agentResults fields)
|
|
770
|
+
// but no meaningful content was found above, return empty
|
|
771
|
+
if ("task" in obj && "done" in obj)
|
|
772
|
+
return "";
|
|
773
|
+
// 5. Last resort: stringify the object
|
|
774
|
+
return JSON.stringify(result);
|
|
775
|
+
}
|
|
776
|
+
extractResults(finalState, config, duration, filesModified = [], conflicts = []) {
|
|
777
|
+
// Extract outcome from final state
|
|
778
|
+
const agentResults = finalState.agentResults ?? {};
|
|
779
|
+
const messages = finalState.messages ?? [];
|
|
780
|
+
// Build outcome: prefer judge verdict (debate) or combined results
|
|
781
|
+
let outcome;
|
|
782
|
+
const lastJudgeMessage = [...messages]
|
|
783
|
+
.reverse()
|
|
784
|
+
.find((m) => m.role === "system" &&
|
|
785
|
+
(m.content.includes("[Judge") || m.content.includes("VERDICT")));
|
|
786
|
+
if (lastJudgeMessage) {
|
|
787
|
+
outcome = lastJudgeMessage.content;
|
|
788
|
+
}
|
|
789
|
+
else if (Object.keys(agentResults).length > 0) {
|
|
790
|
+
outcome = Object.entries(agentResults)
|
|
791
|
+
.map(([id, result]) => {
|
|
792
|
+
const text = this.extractAgentText(result, id);
|
|
793
|
+
return `[${id}]: ${text}`;
|
|
794
|
+
})
|
|
795
|
+
.join("\n\n");
|
|
796
|
+
}
|
|
797
|
+
else {
|
|
798
|
+
outcome = "Swarm completed with no agent results.";
|
|
799
|
+
}
|
|
800
|
+
// Append conflict warnings to outcome
|
|
801
|
+
if (conflicts.length > 0) {
|
|
802
|
+
const conflictLines = conflicts.map((c) => ` ⚠ ${c.file} — modified by: ${c.tasks.join(", ")}`);
|
|
803
|
+
outcome +=
|
|
804
|
+
"\n\nFILE CONFLICTS DETECTED:\n" + conflictLines.join("\n");
|
|
805
|
+
}
|
|
806
|
+
// Truncate outcome to prevent context blowout
|
|
807
|
+
if (outcome.length > 2000) {
|
|
808
|
+
outcome = outcome.slice(0, 1997) + "...";
|
|
809
|
+
}
|
|
810
|
+
// Build per-agent summaries
|
|
811
|
+
const agentSummaries = config.agents.map((agent) => {
|
|
812
|
+
const result = agentResults[agent.id];
|
|
813
|
+
const text = this.extractAgentText(result, agent.id);
|
|
814
|
+
const summary = text ? text.slice(0, 200) : "No output";
|
|
815
|
+
return { id: agent.id, summary };
|
|
816
|
+
});
|
|
817
|
+
return {
|
|
818
|
+
outcome,
|
|
819
|
+
agentSummaries,
|
|
820
|
+
filesModified,
|
|
821
|
+
duration,
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
// ── Error detection ────────────────────────────────────────
|
|
825
|
+
/**
|
|
826
|
+
* Detect whether a run result contains error indicators.
|
|
827
|
+
* Used to decide whether to cache (no) and whether to checkpoint (yes).
|
|
828
|
+
*/
|
|
829
|
+
resultHasErrors(result) {
|
|
830
|
+
// Explicit error markers in outcome (case-insensitive for robustness)
|
|
831
|
+
const outcomeLower = result.outcome.toLowerCase();
|
|
832
|
+
if (outcomeLower.includes("error") ||
|
|
833
|
+
outcomeLower.includes("execution failed") ||
|
|
834
|
+
outcomeLower.includes("swarm execution failed") ||
|
|
835
|
+
outcomeLower.includes("_error")) {
|
|
836
|
+
return true;
|
|
837
|
+
}
|
|
838
|
+
// All agents produced empty/no output — likely a total failure
|
|
839
|
+
if (result.agentSummaries.length > 0 &&
|
|
840
|
+
result.agentSummaries.every((s) => s.summary === "No output" || s.summary.trim() === "")) {
|
|
841
|
+
return true;
|
|
842
|
+
}
|
|
843
|
+
return false;
|
|
844
|
+
}
|
|
845
|
+
// ── Checkpoint helpers ─────────────────────────────────────
|
|
846
|
+
/**
|
|
847
|
+
* Extract completed agent results from a (possibly partial) swarm result.
|
|
848
|
+
* Agents with non-trivial summaries are considered "completed".
|
|
849
|
+
*/
|
|
850
|
+
extractCompletedResults(result) {
|
|
851
|
+
const completed = {};
|
|
852
|
+
for (const agent of result.agentSummaries) {
|
|
853
|
+
if (agent.summary !== "No output" && agent.summary.trim() !== "") {
|
|
854
|
+
completed[agent.id] = agent.summary;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
return completed;
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Determine which agents still need to run based on their result summaries.
|
|
861
|
+
* Agents with "No output" or empty summaries are considered pending.
|
|
862
|
+
*/
|
|
863
|
+
extractPendingAgents(config, result) {
|
|
864
|
+
const completedIds = new Set();
|
|
865
|
+
for (const agent of result.agentSummaries) {
|
|
866
|
+
if (agent.summary !== "No output" && agent.summary.trim() !== "") {
|
|
867
|
+
completedIds.add(agent.id);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
return config.agents.filter((a) => !completedIds.has(a.id));
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
//# sourceMappingURL=swarm-runner.js.map
|