@jungjaehoon/mama-os 0.28.6 → 0.29.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/dist/agent/agent-loop.d.ts +0 -4
- package/dist/agent/agent-loop.d.ts.map +1 -1
- package/dist/agent/agent-loop.js +33 -10
- package/dist/agent/agent-loop.js.map +1 -1
- package/dist/agent/code-act/host-bridge.d.ts.map +1 -1
- package/dist/agent/code-act/host-bridge.js +53 -3
- package/dist/agent/code-act/host-bridge.js.map +1 -1
- package/dist/agent/code-act/tool-policy.d.ts.map +1 -1
- package/dist/agent/code-act/tool-policy.js +5 -0
- package/dist/agent/code-act/tool-policy.js.map +1 -1
- package/dist/agent/codex-auth.d.ts +0 -1
- package/dist/agent/codex-auth.d.ts.map +1 -1
- package/dist/agent/codex-auth.js +0 -4
- package/dist/agent/codex-auth.js.map +1 -1
- package/dist/agent/codex-home.d.ts +0 -2
- package/dist/agent/codex-home.d.ts.map +1 -1
- package/dist/agent/codex-home.js +0 -66
- package/dist/agent/codex-home.js.map +1 -1
- package/dist/agent/context-compile-service.d.ts +9 -0
- package/dist/agent/context-compile-service.d.ts.map +1 -1
- package/dist/agent/context-compile-service.js +6 -0
- package/dist/agent/context-compile-service.js.map +1 -1
- package/dist/agent/context-prompt-builder.d.ts +0 -6
- package/dist/agent/context-prompt-builder.d.ts.map +1 -1
- package/dist/agent/context-prompt-builder.js +0 -131
- package/dist/agent/context-prompt-builder.js.map +1 -1
- package/dist/agent/contract-extractor.d.ts +0 -4
- package/dist/agent/contract-extractor.d.ts.map +1 -1
- package/dist/agent/contract-extractor.js +0 -68
- package/dist/agent/contract-extractor.js.map +1 -1
- package/dist/agent/gateway-tool-executor.d.ts +20 -15
- package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
- package/dist/agent/gateway-tool-executor.js +236 -90
- package/dist/agent/gateway-tool-executor.js.map +1 -1
- package/dist/agent/gateway-tools.md +7 -4
- package/dist/agent/skill-loader.d.ts +0 -7
- package/dist/agent/skill-loader.d.ts.map +1 -1
- package/dist/agent/skill-loader.js +0 -86
- package/dist/agent/skill-loader.js.map +1 -1
- package/dist/agent/token-estimator.d.ts +0 -8
- package/dist/agent/token-estimator.d.ts.map +1 -1
- package/dist/agent/token-estimator.js +0 -14
- package/dist/agent/token-estimator.js.map +1 -1
- package/dist/agent/tool-registry.d.ts.map +1 -1
- package/dist/agent/tool-registry.js +23 -5
- package/dist/agent/tool-registry.js.map +1 -1
- package/dist/agent/types.d.ts +27 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/api/agent-graph-handler.d.ts +9 -0
- package/dist/api/agent-graph-handler.d.ts.map +1 -1
- package/dist/api/agent-graph-handler.js +27 -1
- package/dist/api/agent-graph-handler.js.map +1 -1
- package/dist/api/entity-audit-handler.d.ts +1 -2
- package/dist/api/entity-audit-handler.d.ts.map +1 -1
- package/dist/api/entity-audit-handler.js +0 -5
- package/dist/api/entity-audit-handler.js.map +1 -1
- package/dist/api/index.d.ts +1 -9
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +4 -17
- package/dist/api/index.js.map +1 -1
- package/dist/api/intelligence-handler.d.ts +0 -5
- package/dist/api/intelligence-handler.d.ts.map +1 -1
- package/dist/api/intelligence-handler.js +0 -15
- package/dist/api/intelligence-handler.js.map +1 -1
- package/dist/api/types.d.ts +1 -5
- package/dist/api/types.d.ts.map +1 -1
- package/dist/api/types.js +0 -14
- package/dist/api/types.js.map +1 -1
- package/dist/cli/commands/start.d.ts +117 -3
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +223 -62
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/config/config-manager.d.ts +0 -5
- package/dist/cli/config/config-manager.d.ts.map +1 -1
- package/dist/cli/config/config-manager.js +0 -29
- package/dist/cli/config/config-manager.js.map +1 -1
- package/dist/cli/config/types.d.ts.map +1 -1
- package/dist/cli/config/types.js +3 -0
- package/dist/cli/config/types.js.map +1 -1
- package/dist/cli/runtime/api-routes-init.d.ts.map +1 -1
- package/dist/cli/runtime/api-routes-init.js +32 -5
- package/dist/cli/runtime/api-routes-init.js.map +1 -1
- package/dist/cli/runtime/api-server-init.d.ts.map +1 -1
- package/dist/cli/runtime/api-server-init.js +2 -0
- package/dist/cli/runtime/api-server-init.js.map +1 -1
- package/dist/cli/runtime/gateway-init.d.ts +1 -1
- package/dist/cli/runtime/gateway-init.d.ts.map +1 -1
- package/dist/cli/runtime/gateway-init.js +11 -38
- package/dist/cli/runtime/gateway-init.js.map +1 -1
- package/dist/cli/runtime/gateway-wiring.d.ts.map +1 -1
- package/dist/cli/runtime/gateway-wiring.js +6 -120
- package/dist/cli/runtime/gateway-wiring.js.map +1 -1
- package/dist/cli/utils/pid-manager.d.ts +0 -10
- package/dist/cli/utils/pid-manager.d.ts.map +1 -1
- package/dist/cli/utils/pid-manager.js +0 -26
- package/dist/cli/utils/pid-manager.js.map +1 -1
- package/dist/connectors/framework/polling-scheduler.d.ts +33 -1
- package/dist/connectors/framework/polling-scheduler.d.ts.map +1 -1
- package/dist/connectors/framework/polling-scheduler.js +46 -40
- package/dist/connectors/framework/polling-scheduler.js.map +1 -1
- package/dist/connectors/trello/query-tools.d.ts +32 -5
- package/dist/connectors/trello/query-tools.d.ts.map +1 -1
- package/dist/connectors/trello/query-tools.js +56 -17
- package/dist/connectors/trello/query-tools.js.map +1 -1
- package/dist/db/agent-store.d.ts +0 -4
- package/dist/db/agent-store.d.ts.map +1 -1
- package/dist/db/agent-store.js +0 -65
- package/dist/db/agent-store.js.map +1 -1
- package/dist/envelope/enforcer.d.ts.map +1 -1
- package/dist/envelope/enforcer.js +10 -1
- package/dist/envelope/enforcer.js.map +1 -1
- package/dist/envelope/index.d.ts +0 -1
- package/dist/envelope/index.d.ts.map +1 -1
- package/dist/envelope/index.js +0 -1
- package/dist/envelope/index.js.map +1 -1
- package/dist/envelope/signature.d.ts +0 -1
- package/dist/envelope/signature.d.ts.map +1 -1
- package/dist/envelope/signature.js +0 -7
- package/dist/envelope/signature.js.map +1 -1
- package/dist/envelope/tool-connector-scope.d.ts +35 -0
- package/dist/envelope/tool-connector-scope.d.ts.map +1 -0
- package/dist/envelope/tool-connector-scope.js +57 -0
- package/dist/envelope/tool-connector-scope.js.map +1 -0
- package/dist/evidence/effects.d.ts +107 -0
- package/dist/evidence/effects.d.ts.map +1 -0
- package/dist/evidence/effects.js +281 -0
- package/dist/evidence/effects.js.map +1 -0
- package/dist/evidence/read.d.ts +75 -0
- package/dist/evidence/read.d.ts.map +1 -0
- package/dist/evidence/read.js +105 -0
- package/dist/evidence/read.js.map +1 -0
- package/dist/gateways/base-gateway.d.ts +23 -3
- package/dist/gateways/base-gateway.d.ts.map +1 -1
- package/dist/gateways/base-gateway.js +15 -2
- package/dist/gateways/base-gateway.js.map +1 -1
- package/dist/gateways/discord.d.ts +4 -16
- package/dist/gateways/discord.d.ts.map +1 -1
- package/dist/gateways/discord.js +22 -189
- package/dist/gateways/discord.js.map +1 -1
- package/dist/gateways/index.d.ts +2 -1
- package/dist/gateways/index.d.ts.map +1 -1
- package/dist/gateways/message-router.d.ts +13 -20
- package/dist/gateways/message-router.d.ts.map +1 -1
- package/dist/gateways/message-router.js +32 -3
- package/dist/gateways/message-router.js.map +1 -1
- package/dist/gateways/slack.d.ts +2 -12
- package/dist/gateways/slack.d.ts.map +1 -1
- package/dist/gateways/slack.js +6 -220
- package/dist/gateways/slack.js.map +1 -1
- package/dist/gateways/telegram.d.ts +2 -2
- package/dist/gateways/telegram.d.ts.map +1 -1
- package/dist/gateways/telegram.js +3 -2
- package/dist/gateways/telegram.js.map +1 -1
- package/dist/gateways/turn-contract.d.ts +104 -0
- package/dist/gateways/turn-contract.d.ts.map +1 -0
- package/dist/{memory/consult-contract.js → gateways/turn-contract.js} +1 -1
- package/dist/gateways/turn-contract.js.map +1 -0
- package/dist/memory/provenance-live.d.ts +111 -0
- package/dist/memory/provenance-live.d.ts.map +1 -0
- package/dist/memory/provenance-live.js +381 -0
- package/dist/memory/provenance-live.js.map +1 -0
- package/dist/memory/provenance-resolver.d.ts +184 -0
- package/dist/memory/provenance-resolver.d.ts.map +1 -0
- package/dist/memory/provenance-resolver.js +152 -0
- package/dist/memory/provenance-resolver.js.map +1 -0
- package/dist/multi-agent/agent-event-bus.d.ts +1 -0
- package/dist/multi-agent/agent-event-bus.d.ts.map +1 -1
- package/dist/multi-agent/bmad-templates.d.ts +0 -18
- package/dist/multi-agent/bmad-templates.d.ts.map +1 -1
- package/dist/multi-agent/bmad-templates.js +0 -127
- package/dist/multi-agent/bmad-templates.js.map +1 -1
- package/dist/multi-agent/dashboard-agent-persona.js +3 -3
- package/dist/operator/board-reconcile.d.ts +2 -3
- package/dist/operator/board-reconcile.d.ts.map +1 -1
- package/dist/operator/board-reconcile.js +18 -32
- package/dist/operator/board-reconcile.js.map +1 -1
- package/dist/operator/changes-projection.d.ts +70 -0
- package/dist/operator/changes-projection.d.ts.map +1 -0
- package/dist/operator/changes-projection.js +109 -0
- package/dist/operator/changes-projection.js.map +1 -0
- package/dist/operator/external-correlation.d.ts +94 -0
- package/dist/operator/external-correlation.d.ts.map +1 -0
- package/dist/operator/external-correlation.js +177 -0
- package/dist/operator/external-correlation.js.map +1 -0
- package/dist/operator/operator-trigger-loop.d.ts +9 -1
- package/dist/operator/operator-trigger-loop.d.ts.map +1 -1
- package/dist/operator/operator-trigger-loop.js +8 -4
- package/dist/operator/operator-trigger-loop.js.map +1 -1
- package/dist/operator/provenance-lookup.d.ts +18 -0
- package/dist/operator/provenance-lookup.d.ts.map +1 -0
- package/dist/operator/provenance-lookup.js +54 -0
- package/dist/operator/provenance-lookup.js.map +1 -0
- package/dist/operator/report-carry.d.ts +18 -1
- package/dist/operator/report-carry.d.ts.map +1 -1
- package/dist/operator/report-carry.js +22 -3
- package/dist/operator/report-carry.js.map +1 -1
- package/dist/operator/report-run.d.ts +31 -0
- package/dist/operator/report-run.d.ts.map +1 -1
- package/dist/operator/report-run.js +140 -22
- package/dist/operator/report-run.js.map +1 -1
- package/dist/operator/task-ledger.d.ts +84 -2
- package/dist/operator/task-ledger.d.ts.map +1 -1
- package/dist/operator/task-ledger.js +274 -31
- package/dist/operator/task-ledger.js.map +1 -1
- package/dist/operator/trigger-author.d.ts +7 -0
- package/dist/operator/trigger-author.d.ts.map +1 -1
- package/dist/operator/trigger-author.js +78 -7
- package/dist/operator/trigger-author.js.map +1 -1
- package/dist/operator/worker-run.js +1 -1
- package/dist/operator/worker-run.js.map +1 -1
- package/dist/operator/workorder-hooks.d.ts +79 -4
- package/dist/operator/workorder-hooks.d.ts.map +1 -1
- package/dist/operator/workorder-hooks.js +152 -20
- package/dist/operator/workorder-hooks.js.map +1 -1
- package/dist/operator/workorder-publishers.d.ts +2 -0
- package/dist/operator/workorder-publishers.d.ts.map +1 -1
- package/dist/operator/workorder-publishers.js +8 -1
- package/dist/operator/workorder-publishers.js.map +1 -1
- package/dist/utils/untrusted-content.d.ts +11 -0
- package/dist/utils/untrusted-content.d.ts.map +1 -1
- package/dist/utils/untrusted-content.js +20 -0
- package/dist/utils/untrusted-content.js.map +1 -1
- package/package.json +4 -3
- package/scripts/backfill-channel-keys.ts +451 -0
- package/dist/agent/auto-recall.d.ts +0 -48
- package/dist/agent/auto-recall.d.ts.map +0 -1
- package/dist/agent/auto-recall.js +0 -192
- package/dist/agent/auto-recall.js.map +0 -1
- package/dist/agent/claude-client.d.ts +0 -50
- package/dist/agent/claude-client.d.ts.map +0 -1
- package/dist/agent/claude-client.js +0 -219
- package/dist/agent/claude-client.js.map +0 -1
- package/dist/agent/delegation-executor.d.ts +0 -49
- package/dist/agent/delegation-executor.d.ts.map +0 -1
- package/dist/agent/delegation-executor.js +0 -692
- package/dist/agent/delegation-executor.js.map +0 -1
- package/dist/agent/mcp-executor.d.ts +0 -60
- package/dist/agent/mcp-executor.d.ts.map +0 -1
- package/dist/agent/mcp-executor.js +0 -190
- package/dist/agent/mcp-executor.js.map +0 -1
- package/dist/agent/process-tree.d.ts +0 -6
- package/dist/agent/process-tree.d.ts.map +0 -1
- package/dist/agent/process-tree.js +0 -21
- package/dist/agent/process-tree.js.map +0 -1
- package/dist/agent/streaming-callback-manager.d.ts +0 -85
- package/dist/agent/streaming-callback-manager.d.ts.map +0 -1
- package/dist/agent/streaming-callback-manager.js +0 -103
- package/dist/agent/streaming-callback-manager.js.map +0 -1
- package/dist/agent/token-budget.d.ts +0 -49
- package/dist/agent/token-budget.d.ts.map +0 -1
- package/dist/agent/token-budget.js +0 -92
- package/dist/agent/token-budget.js.map +0 -1
- package/dist/connectors/kagemusha/history-compiler.d.ts +0 -18
- package/dist/connectors/kagemusha/history-compiler.d.ts.map +0 -1
- package/dist/connectors/kagemusha/history-compiler.js +0 -35
- package/dist/connectors/kagemusha/history-compiler.js.map +0 -1
- package/dist/db/migrations/wiki-artifacts.d.ts +0 -3
- package/dist/db/migrations/wiki-artifacts.d.ts.map +0 -1
- package/dist/db/migrations/wiki-artifacts.js +0 -24
- package/dist/db/migrations/wiki-artifacts.js.map +0 -1
- package/dist/envelope/subset.d.ts +0 -9
- package/dist/envelope/subset.d.ts.map +0 -1
- package/dist/envelope/subset.js +0 -67
- package/dist/envelope/subset.js.map +0 -1
- package/dist/memory/consult-contract.d.ts +0 -8
- package/dist/memory/consult-contract.d.ts.map +0 -1
- package/dist/memory/consult-contract.js.map +0 -1
- package/dist/multi-agent/agent-message-queue.d.ts +0 -104
- package/dist/multi-agent/agent-message-queue.d.ts.map +0 -1
- package/dist/multi-agent/agent-message-queue.js +0 -227
- package/dist/multi-agent/agent-message-queue.js.map +0 -1
- package/dist/multi-agent/background-task-manager.d.ts +0 -248
- package/dist/multi-agent/background-task-manager.d.ts.map +0 -1
- package/dist/multi-agent/background-task-manager.js +0 -415
- package/dist/multi-agent/background-task-manager.js.map +0 -1
- package/dist/multi-agent/category-router.d.ts +0 -56
- package/dist/multi-agent/category-router.d.ts.map +0 -1
- package/dist/multi-agent/category-router.js +0 -99
- package/dist/multi-agent/category-router.js.map +0 -1
- package/dist/multi-agent/council-engine.d.ts +0 -60
- package/dist/multi-agent/council-engine.d.ts.map +0 -1
- package/dist/multi-agent/council-engine.js +0 -284
- package/dist/multi-agent/council-engine.js.map +0 -1
- package/dist/multi-agent/delegation-format-validator.d.ts +0 -22
- package/dist/multi-agent/delegation-format-validator.d.ts.map +0 -1
- package/dist/multi-agent/delegation-format-validator.js +0 -31
- package/dist/multi-agent/delegation-format-validator.js.map +0 -1
- package/dist/multi-agent/delegation-manager.d.ts +0 -128
- package/dist/multi-agent/delegation-manager.d.ts.map +0 -1
- package/dist/multi-agent/delegation-manager.js +0 -276
- package/dist/multi-agent/delegation-manager.js.map +0 -1
- package/dist/multi-agent/i18n-messages.d.ts +0 -35
- package/dist/multi-agent/i18n-messages.d.ts.map +0 -1
- package/dist/multi-agent/i18n-messages.js +0 -54
- package/dist/multi-agent/i18n-messages.js.map +0 -1
- package/dist/multi-agent/index.d.ts +0 -31
- package/dist/multi-agent/index.d.ts.map +0 -1
- package/dist/multi-agent/index.js +0 -46
- package/dist/multi-agent/index.js.map +0 -1
- package/dist/multi-agent/multi-agent-base.d.ts +0 -223
- package/dist/multi-agent/multi-agent-base.d.ts.map +0 -1
- package/dist/multi-agent/multi-agent-base.js +0 -592
- package/dist/multi-agent/multi-agent-base.js.map +0 -1
- package/dist/multi-agent/multi-agent-discord.d.ts +0 -142
- package/dist/multi-agent/multi-agent-discord.d.ts.map +0 -1
- package/dist/multi-agent/multi-agent-discord.js +0 -1235
- package/dist/multi-agent/multi-agent-discord.js.map +0 -1
- package/dist/multi-agent/multi-agent-slack.d.ts +0 -146
- package/dist/multi-agent/multi-agent-slack.d.ts.map +0 -1
- package/dist/multi-agent/multi-agent-slack.js +0 -953
- package/dist/multi-agent/multi-agent-slack.js.map +0 -1
- package/dist/multi-agent/multi-bot-manager.d.ts +0 -119
- package/dist/multi-agent/multi-bot-manager.d.ts.map +0 -1
- package/dist/multi-agent/multi-bot-manager.js +0 -449
- package/dist/multi-agent/multi-bot-manager.js.map +0 -1
- package/dist/multi-agent/orchestrator.d.ts +0 -110
- package/dist/multi-agent/orchestrator.d.ts.map +0 -1
- package/dist/multi-agent/orchestrator.js +0 -436
- package/dist/multi-agent/orchestrator.js.map +0 -1
- package/dist/multi-agent/rate-limiter.d.ts +0 -76
- package/dist/multi-agent/rate-limiter.d.ts.map +0 -1
- package/dist/multi-agent/rate-limiter.js +0 -128
- package/dist/multi-agent/rate-limiter.js.map +0 -1
- package/dist/multi-agent/shared-context.d.ts +0 -127
- package/dist/multi-agent/shared-context.d.ts.map +0 -1
- package/dist/multi-agent/shared-context.js +0 -239
- package/dist/multi-agent/shared-context.js.map +0 -1
- package/dist/multi-agent/slack-config-validator.d.ts +0 -42
- package/dist/multi-agent/slack-config-validator.d.ts.map +0 -1
- package/dist/multi-agent/slack-config-validator.js +0 -194
- package/dist/multi-agent/slack-config-validator.js.map +0 -1
- package/dist/multi-agent/slack-multi-bot-manager.d.ts +0 -143
- package/dist/multi-agent/slack-multi-bot-manager.d.ts.map +0 -1
- package/dist/multi-agent/slack-multi-bot-manager.js +0 -413
- package/dist/multi-agent/slack-multi-bot-manager.js.map +0 -1
- package/dist/multi-agent/swarm/swarm-anti-pattern-detector.d.ts +0 -98
- package/dist/multi-agent/swarm/swarm-anti-pattern-detector.d.ts.map +0 -1
- package/dist/multi-agent/swarm/swarm-anti-pattern-detector.js +0 -225
- package/dist/multi-agent/swarm/swarm-anti-pattern-detector.js.map +0 -1
- package/dist/multi-agent/swarm/swarm-db.d.ts +0 -175
- package/dist/multi-agent/swarm/swarm-db.d.ts.map +0 -1
- package/dist/multi-agent/swarm/swarm-db.js +0 -313
- package/dist/multi-agent/swarm/swarm-db.js.map +0 -1
- package/dist/multi-agent/swarm/swarm-event-reporter.d.ts +0 -116
- package/dist/multi-agent/swarm/swarm-event-reporter.d.ts.map +0 -1
- package/dist/multi-agent/swarm/swarm-event-reporter.js +0 -243
- package/dist/multi-agent/swarm/swarm-event-reporter.js.map +0 -1
- package/dist/multi-agent/swarm/swarm-mama-adapter.d.ts +0 -57
- package/dist/multi-agent/swarm/swarm-mama-adapter.d.ts.map +0 -1
- package/dist/multi-agent/swarm/swarm-mama-adapter.js +0 -87
- package/dist/multi-agent/swarm/swarm-mama-adapter.js.map +0 -1
- package/dist/multi-agent/swarm/swarm-manager.d.ts +0 -122
- package/dist/multi-agent/swarm/swarm-manager.d.ts.map +0 -1
- package/dist/multi-agent/swarm/swarm-manager.js +0 -199
- package/dist/multi-agent/swarm/swarm-manager.js.map +0 -1
- package/dist/multi-agent/swarm/swarm-task-learner.d.ts +0 -104
- package/dist/multi-agent/swarm/swarm-task-learner.d.ts.map +0 -1
- package/dist/multi-agent/swarm/swarm-task-learner.js +0 -211
- package/dist/multi-agent/swarm/swarm-task-learner.js.map +0 -1
- package/dist/multi-agent/swarm/swarm-task-runner.d.ts +0 -155
- package/dist/multi-agent/swarm/swarm-task-runner.d.ts.map +0 -1
- package/dist/multi-agent/swarm/swarm-task-runner.js +0 -615
- package/dist/multi-agent/swarm/swarm-task-runner.js.map +0 -1
- package/dist/multi-agent/swarm/wave-engine.d.ts +0 -96
- package/dist/multi-agent/swarm/wave-engine.d.ts.map +0 -1
- package/dist/multi-agent/swarm/wave-engine.js +0 -123
- package/dist/multi-agent/swarm/wave-engine.js.map +0 -1
- package/dist/multi-agent/system-reminder.d.ts +0 -206
- package/dist/multi-agent/system-reminder.d.ts.map +0 -1
- package/dist/multi-agent/system-reminder.js +0 -455
- package/dist/multi-agent/system-reminder.js.map +0 -1
- package/dist/multi-agent/task-continuation.d.ts +0 -74
- package/dist/multi-agent/task-continuation.d.ts.map +0 -1
- package/dist/multi-agent/task-continuation.js +0 -172
- package/dist/multi-agent/task-continuation.js.map +0 -1
- package/dist/multi-agent/ultrawork-state.d.ts +0 -57
- package/dist/multi-agent/ultrawork-state.d.ts.map +0 -1
- package/dist/multi-agent/ultrawork-state.js +0 -191
- package/dist/multi-agent/ultrawork-state.js.map +0 -1
- package/dist/multi-agent/ultrawork.d.ts +0 -152
- package/dist/multi-agent/ultrawork.d.ts.map +0 -1
- package/dist/multi-agent/ultrawork.js +0 -879
- package/dist/multi-agent/ultrawork.js.map +0 -1
- package/dist/multi-agent/work-tracker.d.ts +0 -22
- package/dist/multi-agent/work-tracker.d.ts.map +0 -1
- package/dist/multi-agent/work-tracker.js +0 -45
- package/dist/multi-agent/work-tracker.js.map +0 -1
- package/dist/multi-agent/workflow-engine.d.ts +0 -87
- package/dist/multi-agent/workflow-engine.d.ts.map +0 -1
- package/dist/multi-agent/workflow-engine.js +0 -604
- package/dist/multi-agent/workflow-engine.js.map +0 -1
- package/dist/onboarding/all-tools.d.ts +0 -18
- package/dist/onboarding/all-tools.d.ts.map +0 -1
- package/dist/onboarding/all-tools.js +0 -149
- package/dist/onboarding/all-tools.js.map +0 -1
- package/dist/onboarding/autonomous-discovery-tools.d.ts +0 -23
- package/dist/onboarding/autonomous-discovery-tools.d.ts.map +0 -1
- package/dist/onboarding/autonomous-discovery-tools.js +0 -268
- package/dist/onboarding/autonomous-discovery-tools.js.map +0 -1
- package/dist/onboarding/onboarding-state.d.ts +0 -70
- package/dist/onboarding/onboarding-state.d.ts.map +0 -1
- package/dist/onboarding/onboarding-state.js +0 -183
- package/dist/onboarding/onboarding-state.js.map +0 -1
- package/dist/onboarding/personality-quiz.d.ts +0 -35
- package/dist/onboarding/personality-quiz.d.ts.map +0 -1
- package/dist/onboarding/personality-quiz.js +0 -219
- package/dist/onboarding/personality-quiz.js.map +0 -1
- package/dist/onboarding/phase-5-summary.d.ts +0 -26
- package/dist/onboarding/phase-5-summary.d.ts.map +0 -1
- package/dist/onboarding/phase-5-summary.js +0 -153
- package/dist/onboarding/phase-5-summary.js.map +0 -1
- package/dist/onboarding/phase-6-security.d.ts +0 -33
- package/dist/onboarding/phase-6-security.d.ts.map +0 -1
- package/dist/onboarding/phase-6-security.js +0 -473
- package/dist/onboarding/phase-6-security.js.map +0 -1
- package/dist/onboarding/phase-7-integrations.d.ts +0 -91
- package/dist/onboarding/phase-7-integrations.d.ts.map +0 -1
- package/dist/onboarding/phase-7-integrations.js +0 -725
- package/dist/onboarding/phase-7-integrations.js.map +0 -1
- package/dist/onboarding/phase-8-demo.d.ts +0 -43
- package/dist/onboarding/phase-8-demo.d.ts.map +0 -1
- package/dist/onboarding/phase-8-demo.js +0 -346
- package/dist/onboarding/phase-8-demo.js.map +0 -1
- package/dist/onboarding/phase-9-finalization.d.ts +0 -27
- package/dist/onboarding/phase-9-finalization.d.ts.map +0 -1
- package/dist/onboarding/phase-9-finalization.js +0 -417
- package/dist/onboarding/phase-9-finalization.js.map +0 -1
- package/dist/onboarding/ritual-prompt.d.ts +0 -2
- package/dist/onboarding/ritual-prompt.d.ts.map +0 -1
- package/dist/onboarding/ritual-prompt.js +0 -285
- package/dist/onboarding/ritual-prompt.js.map +0 -1
- package/dist/onboarding/ritual-tools.d.ts +0 -17
- package/dist/onboarding/ritual-tools.d.ts.map +0 -1
- package/dist/onboarding/ritual-tools.js +0 -93
- package/dist/onboarding/ritual-tools.js.map +0 -1
- package/dist/setup/setup-tools.d.ts +0 -13
- package/dist/setup/setup-tools.d.ts.map +0 -1
- package/dist/setup/setup-tools.js +0 -106
- package/dist/setup/setup-tools.js.map +0 -1
- package/dist/utils/slack-input-validator.d.ts +0 -74
- package/dist/utils/slack-input-validator.d.ts.map +0 -1
- package/dist/utils/slack-input-validator.js +0 -275
- package/dist/utils/slack-input-validator.js.map +0 -1
- package/dist/utils/slack-rate-limiter.d.ts +0 -139
- package/dist/utils/slack-rate-limiter.d.ts.map +0 -1
- package/dist/utils/slack-rate-limiter.js +0 -324
- package/dist/utils/slack-rate-limiter.js.map +0 -1
- package/dist/wiki/wiki-compiler.d.ts +0 -13
- package/dist/wiki/wiki-compiler.d.ts.map +0 -1
- package/dist/wiki/wiki-compiler.js +0 -82
- package/dist/wiki/wiki-compiler.js.map +0 -1
|
@@ -1,1235 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Multi-Agent Discord Integration
|
|
4
|
-
*
|
|
5
|
-
* Extends the Discord gateway with multi-agent support.
|
|
6
|
-
* Enables multiple AI personas to interact in Discord channels.
|
|
7
|
-
*/
|
|
8
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
-
if (k2 === undefined) k2 = k;
|
|
10
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
-
}
|
|
14
|
-
Object.defineProperty(o, k2, desc);
|
|
15
|
-
}) : (function(o, m, k, k2) {
|
|
16
|
-
if (k2 === undefined) k2 = k;
|
|
17
|
-
o[k2] = m[k];
|
|
18
|
-
}));
|
|
19
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
-
}) : function(o, v) {
|
|
22
|
-
o["default"] = v;
|
|
23
|
-
});
|
|
24
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
-
var ownKeys = function(o) {
|
|
26
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
-
var ar = [];
|
|
28
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
-
return ar;
|
|
30
|
-
};
|
|
31
|
-
return ownKeys(o);
|
|
32
|
-
};
|
|
33
|
-
return function (mod) {
|
|
34
|
-
if (mod && mod.__esModule) return mod;
|
|
35
|
-
var result = {};
|
|
36
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
-
__setModuleDefault(result, mod);
|
|
38
|
-
return result;
|
|
39
|
-
};
|
|
40
|
-
})();
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.MultiAgentDiscordHandler = void 0;
|
|
43
|
-
const multi_bot_manager_js_1 = require("./multi-bot-manager.js");
|
|
44
|
-
const message_splitter_js_1 = require("../gateways/message-splitter.js");
|
|
45
|
-
const channel_history_js_1 = require("../gateways/channel-history.js");
|
|
46
|
-
const prompt_enhancer_js_1 = require("../agent/prompt-enhancer.js");
|
|
47
|
-
const tool_status_tracker_js_1 = require("../gateways/tool-status-tracker.js");
|
|
48
|
-
const child_process_1 = require("child_process");
|
|
49
|
-
const util_1 = require("util");
|
|
50
|
-
const debugLogger = __importStar(require("@jungjaehoon/mama-core/debug-logger"));
|
|
51
|
-
const config_manager_js_1 = require("../cli/config/config-manager.js");
|
|
52
|
-
const multi_agent_base_js_1 = require("./multi-agent-base.js");
|
|
53
|
-
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
54
|
-
const { DebugLogger } = debugLogger;
|
|
55
|
-
const logger = new DebugLogger('MultiAgentDiscord');
|
|
56
|
-
/** Delay before showing progress message (ms) -- fast requests never show it */
|
|
57
|
-
const PROGRESS_DELAY_MS = 5_000;
|
|
58
|
-
/** Minimum interval between progress message edits (ms) -- Discord rate limit safety */
|
|
59
|
-
const PROGRESS_EDIT_INTERVAL_MS = 3_000;
|
|
60
|
-
/** Phase emoji progression */
|
|
61
|
-
const _PHASE_EMOJIS = ['👀', '🔍', '💻', '🔧', '📝', '✅'];
|
|
62
|
-
/** Max characters allowed for dynamic context blocks to avoid prompt bloat */
|
|
63
|
-
const MAX_DYNAMIC_CONTEXT_CHARS = () => (0, config_manager_js_1.getConfig)().io?.max_dynamic_context_chars ?? 4_000;
|
|
64
|
-
/** Map tool names to phase emojis */
|
|
65
|
-
function toolToPhaseEmoji(toolName) {
|
|
66
|
-
switch (toolName) {
|
|
67
|
-
case 'Task':
|
|
68
|
-
case 'Read':
|
|
69
|
-
case 'Grep':
|
|
70
|
-
case 'Glob':
|
|
71
|
-
case 'WebFetch':
|
|
72
|
-
case 'WebSearch':
|
|
73
|
-
return '🔍'; // analysis
|
|
74
|
-
case 'Bash':
|
|
75
|
-
return '💻'; // terminal commands
|
|
76
|
-
case 'Edit':
|
|
77
|
-
case 'Write':
|
|
78
|
-
case 'NotebookEdit':
|
|
79
|
-
return '🔧'; // implementation (file mutations only)
|
|
80
|
-
default:
|
|
81
|
-
return null; // no change
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Multi-Agent Discord Handler
|
|
86
|
-
*
|
|
87
|
-
* Integrates with the Discord gateway to provide multi-agent support.
|
|
88
|
-
* Should be instantiated and called from the Discord gateway when
|
|
89
|
-
* multi-agent mode is enabled.
|
|
90
|
-
*/
|
|
91
|
-
class MultiAgentDiscordHandler extends multi_agent_base_js_1.MultiAgentHandlerBase {
|
|
92
|
-
multiBotManager;
|
|
93
|
-
promptEnhancer;
|
|
94
|
-
/** Discord client reference for main bot channel sends */
|
|
95
|
-
discordClient = null;
|
|
96
|
-
/** Tracks which agent:channel combos have received history injection (new session only) */
|
|
97
|
-
historyInjected = new Set();
|
|
98
|
-
constructor(config, processOptions = {}, runtimeOptions = {}) {
|
|
99
|
-
super(config, processOptions, runtimeOptions);
|
|
100
|
-
this.multiBotManager = new multi_bot_manager_js_1.MultiBotManager(config);
|
|
101
|
-
this.promptEnhancer = new prompt_enhancer_js_1.PromptEnhancer();
|
|
102
|
-
// Setup idle event listeners for all agents (F7)
|
|
103
|
-
this.setupIdleListeners();
|
|
104
|
-
}
|
|
105
|
-
getPlatformName() {
|
|
106
|
-
return 'discord';
|
|
107
|
-
}
|
|
108
|
-
formatBold(text) {
|
|
109
|
-
return `**${text}**`;
|
|
110
|
-
}
|
|
111
|
-
async sendChannelNotification(channelId, message) {
|
|
112
|
-
try {
|
|
113
|
-
if (this.discordClient) {
|
|
114
|
-
const channel = await this.discordClient.channels.fetch(channelId);
|
|
115
|
-
if (channel && 'send' in channel) {
|
|
116
|
-
await channel.send({
|
|
117
|
-
content: message,
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
catch (err) {
|
|
123
|
-
console.error(`[MultiAgent] Failed to send channel notification:`, err);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Extract agent IDs from <@USER_ID> mentions in message content.
|
|
128
|
-
*/
|
|
129
|
-
extractMentionedAgentIds(content) {
|
|
130
|
-
const agentIds = [];
|
|
131
|
-
// Discord native mentions: <@USER_ID> or <@!USER_ID>
|
|
132
|
-
const mentionPattern = /<@!?(\d+)>/g;
|
|
133
|
-
let match;
|
|
134
|
-
while ((match = mentionPattern.exec(content)) !== null) {
|
|
135
|
-
const userId = match[1];
|
|
136
|
-
const agentId = this.multiBotManager.resolveAgentIdFromUserId(userId);
|
|
137
|
-
if (agentId && agentId !== 'main') {
|
|
138
|
-
agentIds.push(agentId);
|
|
139
|
-
}
|
|
140
|
-
else if (agentId === 'main' && this.config.default_agent) {
|
|
141
|
-
// Main bot userId maps to the default agent (LEAD)
|
|
142
|
-
agentIds.push(this.config.default_agent);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return agentIds;
|
|
146
|
-
}
|
|
147
|
-
async platformCleanup() {
|
|
148
|
-
await this.multiBotManager.stopAll();
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Initialize multi-bot support (call after Discord connects)
|
|
152
|
-
*/
|
|
153
|
-
async initializeMultiBots() {
|
|
154
|
-
if (this.multiBotInitialized)
|
|
155
|
-
return;
|
|
156
|
-
// Register mention callback so agent bots forward mentions to handler
|
|
157
|
-
this.multiBotManager.onMention(async (agentId, message) => {
|
|
158
|
-
// Dedup: skip if already processed via routeResponseMentions
|
|
159
|
-
const dedupKey = `${agentId}:${message.id}`;
|
|
160
|
-
if (this.processedMentions.has(dedupKey))
|
|
161
|
-
return;
|
|
162
|
-
this.processedMentions.set(dedupKey, Date.now());
|
|
163
|
-
const cleanContent = message.content.replace(/<@!?\d+>/g, '').trim();
|
|
164
|
-
if (!cleanContent)
|
|
165
|
-
return;
|
|
166
|
-
// Determine if sender is an agent bot (for mention_delegation chains)
|
|
167
|
-
const isFromAgent = message.author.bot;
|
|
168
|
-
const senderAgentId = isFromAgent
|
|
169
|
-
? (this.multiBotManager.isFromAgentBot(message) ?? undefined)
|
|
170
|
-
: undefined;
|
|
171
|
-
// Chain depth check for mention_delegation
|
|
172
|
-
if (isFromAgent && senderAgentId && senderAgentId !== 'main') {
|
|
173
|
-
const chainState = this.orchestrator.getChainState(message.channel.id);
|
|
174
|
-
const maxDepth = this.getEffectiveMaxMentionDepth();
|
|
175
|
-
if (chainState.blocked) {
|
|
176
|
-
logger.info(`[MultiAgent] Mention chain blocked in channel ${message.channel.id}, ignoring`);
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
if (chainState.length >= maxDepth) {
|
|
180
|
-
logger.info(`[MultiAgent] Mention chain depth ${chainState.length} >= max ${maxDepth}, ignoring`);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
logger.info(`[MultiAgent] Mention-triggered: agent=${agentId}, from=${senderAgentId ?? message.author.tag}, content="${cleanContent.substring(0, 50)}"`);
|
|
185
|
-
// Extract mentioned agent IDs from the original content
|
|
186
|
-
const mentionedAgentIds = this.extractMentionedAgentIds(message.content);
|
|
187
|
-
// Add eyes emoji to indicate processing
|
|
188
|
-
try {
|
|
189
|
-
await message.react('👀');
|
|
190
|
-
}
|
|
191
|
-
catch {
|
|
192
|
-
/* ignore */
|
|
193
|
-
}
|
|
194
|
-
// Force this specific agent to respond
|
|
195
|
-
const mentionDescription = cleanContent.substring(0, 200);
|
|
196
|
-
let mentionResponse = null;
|
|
197
|
-
try {
|
|
198
|
-
this.systemReminder.notify({
|
|
199
|
-
type: 'delegation-started',
|
|
200
|
-
taskId: '',
|
|
201
|
-
description: mentionDescription,
|
|
202
|
-
agentId,
|
|
203
|
-
requestedBy: senderAgentId ?? message.author.tag,
|
|
204
|
-
channelId: message.channel.id,
|
|
205
|
-
source: 'discord',
|
|
206
|
-
timestamp: Date.now(),
|
|
207
|
-
});
|
|
208
|
-
mentionResponse = await this.processAgentResponse(agentId, {
|
|
209
|
-
channelId: message.channel.id,
|
|
210
|
-
userId: message.author.id,
|
|
211
|
-
content: cleanContent,
|
|
212
|
-
isBot: isFromAgent,
|
|
213
|
-
senderAgentId: senderAgentId && senderAgentId !== 'main' ? senderAgentId : undefined,
|
|
214
|
-
mentionedAgentIds,
|
|
215
|
-
messageId: message.id,
|
|
216
|
-
timestamp: message.createdTimestamp,
|
|
217
|
-
}, cleanContent, message);
|
|
218
|
-
if (mentionResponse) {
|
|
219
|
-
this.systemReminder.notify({
|
|
220
|
-
type: 'delegation-completed',
|
|
221
|
-
taskId: '',
|
|
222
|
-
description: mentionDescription,
|
|
223
|
-
agentId,
|
|
224
|
-
requestedBy: senderAgentId ?? message.author.tag,
|
|
225
|
-
channelId: message.channel.id,
|
|
226
|
-
source: 'discord',
|
|
227
|
-
duration: mentionResponse.duration,
|
|
228
|
-
timestamp: Date.now(),
|
|
229
|
-
});
|
|
230
|
-
await this.sendAgentResponses(message, [mentionResponse]);
|
|
231
|
-
this.orchestrator.recordAgentResponse(agentId, message.channel.id, mentionResponse.messageId);
|
|
232
|
-
// Route delegation mentions from this agent's response
|
|
233
|
-
if (this.isMentionDelegationEnabled()) {
|
|
234
|
-
await this.routeResponseMentions(message, [mentionResponse]);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
catch (err) {
|
|
239
|
-
console.error(`[MultiAgent] Mention handler error:`, err);
|
|
240
|
-
}
|
|
241
|
-
finally {
|
|
242
|
-
// Only add checkmark if agent responded (null = busy/queued)
|
|
243
|
-
if (mentionResponse) {
|
|
244
|
-
try {
|
|
245
|
-
await message.react('✅');
|
|
246
|
-
}
|
|
247
|
-
catch {
|
|
248
|
-
/* ignore */
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
await this.multiBotManager.initialize();
|
|
254
|
-
this.multiBotInitialized = true;
|
|
255
|
-
const connectedAgents = this.multiBotManager.getConnectedAgents();
|
|
256
|
-
if (connectedAgents.length > 0) {
|
|
257
|
-
logger.info(`[MultiAgent] Multi-bot mode active for: ${connectedAgents.join(', ')}`);
|
|
258
|
-
}
|
|
259
|
-
// Pass bot ID map to process manager for mention-based delegation prompts
|
|
260
|
-
if (this.config.mention_delegation) {
|
|
261
|
-
const botUserIdMap = this.multiBotManager.getBotUserIdMap();
|
|
262
|
-
// Include LEAD (default agent) which uses the main bot token
|
|
263
|
-
// Without this, @Conductor in other agents' personas won't resolve to <@userId>
|
|
264
|
-
const defaultAgentId = this.config.default_agent;
|
|
265
|
-
if (defaultAgentId && !botUserIdMap.has(defaultAgentId)) {
|
|
266
|
-
const mainBotUserId = this.multiBotManager.getMainBotUserId();
|
|
267
|
-
if (mainBotUserId) {
|
|
268
|
-
botUserIdMap.set(defaultAgentId, mainBotUserId);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
this.processManager.setBotUserIdMap(botUserIdMap);
|
|
272
|
-
this.processManager.setMentionDelegation(true);
|
|
273
|
-
logger.info(`[MultiAgent] Mention delegation enabled with ${botUserIdMap.size} bot IDs`);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Set bot's own user ID (call when Discord connects)
|
|
278
|
-
* Also wires the PR Review Poller message sender via Discord client.
|
|
279
|
-
*/
|
|
280
|
-
setBotUserId(userId) {
|
|
281
|
-
this.multiBotManager.setMainBotUserId(userId);
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Set Discord client for PR Review Poller message delivery.
|
|
285
|
-
* Call after Discord client is ready.
|
|
286
|
-
* The sender posts the message to the channel AND injects it into the
|
|
287
|
-
* multi-agent flow so LEAD processes the review comments.
|
|
288
|
-
*/
|
|
289
|
-
setDiscordClient(client) {
|
|
290
|
-
// Guard against setting different client when already configured
|
|
291
|
-
if (this.discordClient && this.discordClient !== client) {
|
|
292
|
-
console.warn('[MultiAgent] Attempted to set different Discord client - ignoring');
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
this.discordClient = client;
|
|
296
|
-
this.systemReminder.registerCallback(async (channelId, message) => {
|
|
297
|
-
const ch = await client.channels.fetch(channelId);
|
|
298
|
-
if (ch && 'send' in ch) {
|
|
299
|
-
const chunks = (0, message_splitter_js_1.splitForDiscord)(message);
|
|
300
|
-
for (const chunk of chunks) {
|
|
301
|
-
await ch.send({
|
|
302
|
-
content: chunk,
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}, 'discord');
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* Set main bot token (to avoid duplicate logins in MultiBotManager)
|
|
310
|
-
*/
|
|
311
|
-
setMainBotToken(token) {
|
|
312
|
-
this.multiBotManager.setMainBotToken(token);
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Update configuration (for hot reload)
|
|
316
|
-
*/
|
|
317
|
-
updateConfig(config) {
|
|
318
|
-
this.config = config;
|
|
319
|
-
this.orchestrator.updateConfig(config);
|
|
320
|
-
this.processManager.updateConfig(config);
|
|
321
|
-
this.multiBotManager.updateConfig(config);
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* Handle a Discord message with multi-agent logic
|
|
325
|
-
*
|
|
326
|
-
* @returns Object with selected agents and their responses, or null if no agents respond
|
|
327
|
-
*/
|
|
328
|
-
async handleMessage(message, cleanContent) {
|
|
329
|
-
// Intercept !stop command before any agent routing
|
|
330
|
-
if (cleanContent.startsWith('!stop')) {
|
|
331
|
-
await this.handleStopCommand(message, cleanContent);
|
|
332
|
-
return null;
|
|
333
|
-
}
|
|
334
|
-
// Build message context
|
|
335
|
-
const context = this.buildMessageContext(message, cleanContent);
|
|
336
|
-
// Record human message to shared context
|
|
337
|
-
if (!context.isBot) {
|
|
338
|
-
this.sharedContext.recordHumanMessage(context.channelId, message.author.username, cleanContent, message.id);
|
|
339
|
-
}
|
|
340
|
-
// Select responding agents
|
|
341
|
-
const selection = this.orchestrator.selectRespondingAgents(context);
|
|
342
|
-
logger.info(`[MultiAgent] Selection result: agents=${selection.selectedAgents.join(',')}, reason=${selection.reason}, blocked=${selection.blocked}`);
|
|
343
|
-
if (selection.blocked) {
|
|
344
|
-
logger.info(`[MultiAgent] Blocked: ${selection.blockReason}`);
|
|
345
|
-
return null;
|
|
346
|
-
}
|
|
347
|
-
if (selection.selectedAgents.length === 0) {
|
|
348
|
-
return null;
|
|
349
|
-
}
|
|
350
|
-
// Process all selected agents in parallel
|
|
351
|
-
const results = await Promise.allSettled(selection.selectedAgents.map((agentId) => this.processAgentResponse(agentId, context, cleanContent, message)));
|
|
352
|
-
const responses = [];
|
|
353
|
-
for (let i = 0; i < results.length; i++) {
|
|
354
|
-
const result = results[i];
|
|
355
|
-
const agentId = selection.selectedAgents[i];
|
|
356
|
-
if (result.status === 'fulfilled' && result.value) {
|
|
357
|
-
const response = result.value;
|
|
358
|
-
responses.push(response);
|
|
359
|
-
// Record agent response to orchestrator and shared context
|
|
360
|
-
this.orchestrator.recordAgentResponse(agentId, context.channelId, response.messageId);
|
|
361
|
-
const agent = this.orchestrator.getAgent(agentId);
|
|
362
|
-
if (agent) {
|
|
363
|
-
this.sharedContext.recordAgentMessage(context.channelId, agent, response.content, response.messageId);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
else if (result.status === 'rejected') {
|
|
367
|
-
console.error(`[MultiAgent] Error processing agent ${agentId}:`, result.reason);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
if (responses.length === 0) {
|
|
371
|
-
return null;
|
|
372
|
-
}
|
|
373
|
-
return {
|
|
374
|
-
selectedAgents: selection.selectedAgents,
|
|
375
|
-
reason: selection.reason,
|
|
376
|
-
responses,
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
async handleStopCommand(message, cleanContent) {
|
|
380
|
-
const channelId = message.channel.id;
|
|
381
|
-
const args = cleanContent.slice('!stop'.length).trim();
|
|
382
|
-
if (args) {
|
|
383
|
-
const agentId = args;
|
|
384
|
-
const agent = this.orchestrator.getAgent(agentId);
|
|
385
|
-
if (!agent) {
|
|
386
|
-
await message.reply({ content: `⏹️ Unknown agent: \`${agentId}\`` });
|
|
387
|
-
return;
|
|
388
|
-
}
|
|
389
|
-
const hasActive = this.processManager.hasActiveProcess('discord', channelId, agentId);
|
|
390
|
-
if (hasActive) {
|
|
391
|
-
this.processManager.stopProcess('discord', channelId, agentId);
|
|
392
|
-
this.orchestrator.resetChain(channelId);
|
|
393
|
-
const displayName = agent.display_name || agentId;
|
|
394
|
-
await message.reply({ content: `⏹️ Stopped ${displayName}` });
|
|
395
|
-
}
|
|
396
|
-
else {
|
|
397
|
-
await message.reply({ content: `⏹️ No running agents to stop` });
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
else {
|
|
401
|
-
const activeAgents = this.processManager.getActiveAgentsInChannel('discord', channelId);
|
|
402
|
-
if (activeAgents.length > 0) {
|
|
403
|
-
this.processManager.stopChannelProcesses('discord', channelId);
|
|
404
|
-
this.orchestrator.resetChain(channelId);
|
|
405
|
-
await message.reply({ content: `⏹️ Stopped all agents in this channel` });
|
|
406
|
-
}
|
|
407
|
-
else {
|
|
408
|
-
await message.reply({ content: `⏹️ No running agents to stop` });
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
logger.info(`[MultiAgent] !stop command: channel=${channelId}, target=${args || 'all'}`);
|
|
412
|
-
}
|
|
413
|
-
/**
|
|
414
|
-
* Process a single agent's response
|
|
415
|
-
* @param discordMessage - Optional Discord message for emoji progression
|
|
416
|
-
*/
|
|
417
|
-
async processAgentResponse(agentId, context, userMessage, discordMessage) {
|
|
418
|
-
const agent = this.orchestrator.getAgent(agentId);
|
|
419
|
-
if (!agent) {
|
|
420
|
-
console.error(`[MultiAgent] Unknown agent: ${agentId}`);
|
|
421
|
-
return null;
|
|
422
|
-
}
|
|
423
|
-
// Strip trigger prefix from message if present
|
|
424
|
-
const cleanMessage = this.orchestrator.stripTriggerPrefix(userMessage, agentId);
|
|
425
|
-
// Build context for this agent.
|
|
426
|
-
// In delegation chains (senderAgentId set), include own messages so the agent
|
|
427
|
-
// can see what it already said and reason about whether to repeat.
|
|
428
|
-
// In normal triggers, exclude own messages to avoid self-reference confusion.
|
|
429
|
-
let agentContext;
|
|
430
|
-
if (context.senderAgentId) {
|
|
431
|
-
const messages = this.sharedContext.getRecentMessages(context.channelId, 10);
|
|
432
|
-
if (messages.length > 0) {
|
|
433
|
-
const lines = messages.map((msg) => {
|
|
434
|
-
const isSelf = msg.agentId === agentId;
|
|
435
|
-
const prefix = msg.isHuman ? '👤' : isSelf ? '📌 (you)' : '🤖';
|
|
436
|
-
const content = msg.content.length > 600 ? msg.content.slice(0, 600) + '...' : msg.content;
|
|
437
|
-
return `${prefix} **${msg.displayName}**: ${content}`;
|
|
438
|
-
});
|
|
439
|
-
agentContext = `## Delegation Chain Context\n${lines.join('\n')}`;
|
|
440
|
-
}
|
|
441
|
-
else {
|
|
442
|
-
agentContext = '';
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
else {
|
|
446
|
-
agentContext = this.sharedContext.buildContextForAgent(context.channelId, agentId, 5);
|
|
447
|
-
}
|
|
448
|
-
// Build full prompt with context.
|
|
449
|
-
// - agentContext: other agents' recent messages (inter-agent awareness)
|
|
450
|
-
// - historyContext: human-only channel history (LEAD agent only)
|
|
451
|
-
// DevBot/Reviewer are sub-agent-like -- they get tasks via delegation, not channel history.
|
|
452
|
-
// Only LEAD needs channel context to understand the conversation flow.
|
|
453
|
-
let fullPrompt = cleanMessage;
|
|
454
|
-
// Inject channel history for all agents on new sessions only.
|
|
455
|
-
// - Keeps human messages + this agent's own messages, excludes other bots.
|
|
456
|
-
// - Only on first message per session (subsequent messages are in session memory).
|
|
457
|
-
const sessionKey = `${agentId}:${context.channelId}`;
|
|
458
|
-
if (!this.historyInjected.has(sessionKey)) {
|
|
459
|
-
const channelHistory = (0, channel_history_js_1.getChannelHistory)();
|
|
460
|
-
const displayName = agent.display_name || agentId;
|
|
461
|
-
const historyContext = channelHistory.formatForContext(context.channelId, context.messageId, displayName // keep human + this agent's own messages, exclude other bots
|
|
462
|
-
);
|
|
463
|
-
if (historyContext) {
|
|
464
|
-
fullPrompt = `${historyContext}\n\n${fullPrompt}`;
|
|
465
|
-
}
|
|
466
|
-
this.historyInjected.add(sessionKey);
|
|
467
|
-
}
|
|
468
|
-
if (agentContext) {
|
|
469
|
-
fullPrompt = `${agentContext}\n\n${fullPrompt}`;
|
|
470
|
-
}
|
|
471
|
-
// Inject agent availability status, active work, and channel context (Phase 2 + 3)
|
|
472
|
-
const agentStatus = this.buildAgentStatusSection(agentId);
|
|
473
|
-
const workSection = this.workTracker.buildWorkSection(agentId);
|
|
474
|
-
const channelInfo = `## Current Channel\nPlatform: Discord\nchannel_id: ${context.channelId}\nUse **discord_send** to send messages/files to this channel.`;
|
|
475
|
-
const dynamicContextRaw = [agentStatus, workSection, channelInfo].filter(Boolean).join('\n');
|
|
476
|
-
const dynamicContext = dynamicContextRaw.length > MAX_DYNAMIC_CONTEXT_CHARS()
|
|
477
|
-
? `${dynamicContextRaw.slice(0, MAX_DYNAMIC_CONTEXT_CHARS())}\n...`
|
|
478
|
-
: dynamicContextRaw;
|
|
479
|
-
if (dynamicContext) {
|
|
480
|
-
fullPrompt = `${dynamicContext}\n\n${fullPrompt}`;
|
|
481
|
-
}
|
|
482
|
-
// Enhance prompt with keyword detection (ultrawork/search/analyze modes)
|
|
483
|
-
const workspacePath = globalThis.process.env.MAMA_WORKSPACE || '';
|
|
484
|
-
const ruleContext = {
|
|
485
|
-
agentId,
|
|
486
|
-
tier: agent.tier,
|
|
487
|
-
channelId: context.channelId,
|
|
488
|
-
};
|
|
489
|
-
const enhanced = await this.promptEnhancer.enhance(cleanMessage, workspacePath, ruleContext);
|
|
490
|
-
if (enhanced.skillContent) {
|
|
491
|
-
const safeSkillContent = enhanced.skillContent.replace(/<\/system-reminder>/gi, '</system\u2011reminder>');
|
|
492
|
-
fullPrompt = `<system-reminder>\n${safeSkillContent}\n</system-reminder>\n\n${fullPrompt}`;
|
|
493
|
-
logger.info(`[SkillMatch] Injecting skill into Discord agent ${agentId}: ${enhanced.skillContent.length} chars`);
|
|
494
|
-
}
|
|
495
|
-
if (enhanced.keywordInstructions) {
|
|
496
|
-
fullPrompt = `${enhanced.keywordInstructions}\n\n${fullPrompt}`;
|
|
497
|
-
logger.info(`[PromptEnhancer] Keyword detected for agent ${agentId}: ${enhanced.keywordInstructions.length} chars injected`);
|
|
498
|
-
}
|
|
499
|
-
if (enhanced.rulesContent) {
|
|
500
|
-
fullPrompt = `## Project Rules\n${enhanced.rulesContent}\n\n${fullPrompt}`;
|
|
501
|
-
logger.info(`[PromptEnhancer] Rules injected for agent ${agentId}: ${enhanced.rulesContent.length} chars`);
|
|
502
|
-
}
|
|
503
|
-
logger.info(`[MultiAgent] Processing agent ${agentId}, prompt length: ${fullPrompt.length}`);
|
|
504
|
-
// Track work start (completed in finally block)
|
|
505
|
-
this.workTracker.startWork(agentId, context.channelId, cleanMessage);
|
|
506
|
-
let agentProcess = null;
|
|
507
|
-
try {
|
|
508
|
-
// Get or create process for this agent in this channel
|
|
509
|
-
agentProcess = await this.processManager.getProcess('discord', context.channelId, agentId);
|
|
510
|
-
// Build onToolUse callback for emoji progression (accumulate, don't replace)
|
|
511
|
-
const addedEmojis = new Set();
|
|
512
|
-
const hasOwnBot = this.multiBotManager.hasAgentBot(agentId);
|
|
513
|
-
// Create tool status tracker for progress messages
|
|
514
|
-
let tracker = null;
|
|
515
|
-
if (discordMessage) {
|
|
516
|
-
const channelId = discordMessage.channel.id;
|
|
517
|
-
let placeholderMsg = null;
|
|
518
|
-
const discordAdapter = {
|
|
519
|
-
postPlaceholder: async (content) => {
|
|
520
|
-
if (hasOwnBot) {
|
|
521
|
-
placeholderMsg = await this.multiBotManager.sendAsAgent(agentId, channelId, content);
|
|
522
|
-
}
|
|
523
|
-
else if ('send' in discordMessage.channel) {
|
|
524
|
-
placeholderMsg = await discordMessage.channel.send(content);
|
|
525
|
-
}
|
|
526
|
-
return placeholderMsg?.id ?? null;
|
|
527
|
-
},
|
|
528
|
-
editPlaceholder: async (_handle, content) => {
|
|
529
|
-
if (placeholderMsg) {
|
|
530
|
-
await placeholderMsg.edit(content);
|
|
531
|
-
}
|
|
532
|
-
},
|
|
533
|
-
deletePlaceholder: async (_handle) => {
|
|
534
|
-
if (placeholderMsg) {
|
|
535
|
-
await placeholderMsg.delete();
|
|
536
|
-
placeholderMsg = null;
|
|
537
|
-
}
|
|
538
|
-
},
|
|
539
|
-
};
|
|
540
|
-
tracker = new tool_status_tracker_js_1.ToolStatusTracker(discordAdapter, {
|
|
541
|
-
throttleMs: PROGRESS_EDIT_INTERVAL_MS,
|
|
542
|
-
initialDelayMs: PROGRESS_DELAY_MS,
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
|
-
const onToolUse = discordMessage
|
|
546
|
-
? (name, input) => {
|
|
547
|
-
// Emoji reaction behavior
|
|
548
|
-
const emoji = toolToPhaseEmoji(name);
|
|
549
|
-
if (emoji && !addedEmojis.has(emoji)) {
|
|
550
|
-
addedEmojis.add(emoji);
|
|
551
|
-
if (hasOwnBot) {
|
|
552
|
-
this.multiBotManager
|
|
553
|
-
.reactAsAgent(agentId, discordMessage.channel.id, discordMessage.id, emoji)
|
|
554
|
-
.catch(() => {
|
|
555
|
-
/* ignore */
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
else {
|
|
559
|
-
discordMessage.react(emoji).catch(() => {
|
|
560
|
-
/* ignore */
|
|
561
|
-
});
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
// Tool status tracker
|
|
565
|
-
tracker?.onToolUse(name, input);
|
|
566
|
-
}
|
|
567
|
-
: undefined;
|
|
568
|
-
// Send message and get response (with timeout, properly cleaned up)
|
|
569
|
-
// agent_ms=0 means unlimited (no timeout race)
|
|
570
|
-
let timeoutHandle;
|
|
571
|
-
let result;
|
|
572
|
-
try {
|
|
573
|
-
const agentTimeout = (0, multi_agent_base_js_1.AGENT_TIMEOUT_MS)();
|
|
574
|
-
const sendPromise = agentProcess.sendMessage(fullPrompt, onToolUse ? { onToolUse } : undefined);
|
|
575
|
-
if (agentTimeout > 0) {
|
|
576
|
-
result = await Promise.race([
|
|
577
|
-
sendPromise,
|
|
578
|
-
new Promise((_, reject) => {
|
|
579
|
-
timeoutHandle = setTimeout(() => reject(new Error(`Agent ${agentId} timed out after ${agentTimeout / 1000}s`)), agentTimeout);
|
|
580
|
-
}),
|
|
581
|
-
]);
|
|
582
|
-
}
|
|
583
|
-
else {
|
|
584
|
-
result = await sendPromise;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
finally {
|
|
588
|
-
if (timeoutHandle)
|
|
589
|
-
clearTimeout(timeoutHandle);
|
|
590
|
-
await tracker?.cleanup();
|
|
591
|
-
}
|
|
592
|
-
// Execute text-based gateway tool calls (```tool_call blocks in response)
|
|
593
|
-
// Claude CLI handles built-in tools (Read, Bash, Glob) internally via native tool_use.
|
|
594
|
-
// Gateway tools (discord_send, mama_*) are requested via text-based tool_call blocks.
|
|
595
|
-
// discord_send is routed through the agent's own bot (not the main LEAD bot).
|
|
596
|
-
// Check for workflow plan BEFORE executing tool calls (priority)
|
|
597
|
-
const workflowStart = Date.now();
|
|
598
|
-
const workflowResult = await this.tryExecuteWorkflow(result.response, context.channelId, 'discord', (event) => {
|
|
599
|
-
if (!this.discordClient) {
|
|
600
|
-
return;
|
|
601
|
-
}
|
|
602
|
-
let msg = '';
|
|
603
|
-
const modelTag = event.agentModel ? ` [${event.agentModel}]` : '';
|
|
604
|
-
const progress = event.totalSteps && event.completedSteps !== undefined
|
|
605
|
-
? ` [${event.completedSteps}/${event.totalSteps}]`
|
|
606
|
-
: '';
|
|
607
|
-
if (event.type === 'step-started') {
|
|
608
|
-
msg = ` ${event.agentDisplayName}${modelTag}${progress} starting...`;
|
|
609
|
-
}
|
|
610
|
-
else if (event.type === 'step-completed') {
|
|
611
|
-
const sec = event.duration_ms ? Math.round(event.duration_ms / 1000) : 0;
|
|
612
|
-
const pct = event.totalSteps && event.completedSteps !== undefined
|
|
613
|
-
? ` (${Math.round((event.completedSteps / event.totalSteps) * 100)}%)`
|
|
614
|
-
: '';
|
|
615
|
-
msg = `${event.agentDisplayName}${modelTag} (${sec}s)${pct} completed`;
|
|
616
|
-
}
|
|
617
|
-
else if (event.type === 'step-failed') {
|
|
618
|
-
msg = `${event.agentDisplayName}${modelTag}${progress} ❌ failed: ${event.error?.substring(0, 100)}`;
|
|
619
|
-
}
|
|
620
|
-
if (msg) {
|
|
621
|
-
this.sendChannelNotification(context.channelId, msg).catch(() => { });
|
|
622
|
-
}
|
|
623
|
-
});
|
|
624
|
-
if (workflowResult) {
|
|
625
|
-
if (workflowResult.failed) {
|
|
626
|
-
this.logger.warn(`[MultiAgentDiscord] Workflow failed: ${workflowResult.failed}, sending feedback to conductor`);
|
|
627
|
-
const feedback = `[SYSTEM] Your workflow_plan failed to execute.\nReason: ${workflowResult.failed}\nPlease adjust and retry, or respond without a workflow_plan.`;
|
|
628
|
-
const retryResult = await agentProcess.sendMessage(feedback);
|
|
629
|
-
const cleanedRetry = await this.executeAgentToolCalls(agentId, retryResult.response);
|
|
630
|
-
const formattedResponse = this.formatAgentResponse(agent, cleanedRetry);
|
|
631
|
-
return {
|
|
632
|
-
agentId,
|
|
633
|
-
agent,
|
|
634
|
-
content: formattedResponse,
|
|
635
|
-
rawContent: cleanedRetry,
|
|
636
|
-
duration: Date.now() - workflowStart + (result.duration_ms ?? 0),
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
const display = workflowResult.directMessage
|
|
640
|
-
? `${workflowResult.directMessage}\n\n${workflowResult.result}`
|
|
641
|
-
: workflowResult.result;
|
|
642
|
-
const formattedResponse = this.formatAgentResponse(agent, display);
|
|
643
|
-
const totalDuration = Date.now() - workflowStart + (result.duration_ms ?? 0);
|
|
644
|
-
return {
|
|
645
|
-
agentId,
|
|
646
|
-
agent,
|
|
647
|
-
content: formattedResponse,
|
|
648
|
-
rawContent: display,
|
|
649
|
-
duration: totalDuration,
|
|
650
|
-
};
|
|
651
|
-
}
|
|
652
|
-
// Check for council plan (after workflow, before tool calls)
|
|
653
|
-
const councilResult = await this.tryExecuteCouncil(result.response, context.channelId, 'discord', (event) => {
|
|
654
|
-
if (!this.discordClient)
|
|
655
|
-
return;
|
|
656
|
-
let msg = '';
|
|
657
|
-
if (event.type === 'council-round-started') {
|
|
658
|
-
msg = `🗣️ ${event.agentDisplayName} Round ${event.round} starting...`;
|
|
659
|
-
}
|
|
660
|
-
else if (event.type === 'council-round-completed') {
|
|
661
|
-
const sec = event.duration_ms ? Math.round(event.duration_ms / 1000) : 0;
|
|
662
|
-
msg = `🗣️ ${event.agentDisplayName} Round ${event.round} (${sec}s) completed`;
|
|
663
|
-
}
|
|
664
|
-
else if (event.type === 'council-round-failed') {
|
|
665
|
-
msg = `🗣️ ${event.agentDisplayName} Round ${event.round} ❌ failed: ${event.error?.substring(0, 100)}`;
|
|
666
|
-
}
|
|
667
|
-
if (msg) {
|
|
668
|
-
this.sendChannelNotification(context.channelId, msg).catch(() => { });
|
|
669
|
-
}
|
|
670
|
-
});
|
|
671
|
-
if (councilResult) {
|
|
672
|
-
const display = councilResult.directMessage
|
|
673
|
-
? `${councilResult.directMessage}\n\n${councilResult.result}`
|
|
674
|
-
: councilResult.result;
|
|
675
|
-
const formattedResponse = this.formatAgentResponse(agent, display);
|
|
676
|
-
return {
|
|
677
|
-
agentId,
|
|
678
|
-
agent,
|
|
679
|
-
content: formattedResponse,
|
|
680
|
-
rawContent: display,
|
|
681
|
-
duration: Date.now() - workflowStart + (result.duration_ms ?? 0),
|
|
682
|
-
};
|
|
683
|
-
}
|
|
684
|
-
// Strip any workflow/council plan JSON that wasn't executed
|
|
685
|
-
let responseForProcessing = result.response;
|
|
686
|
-
if (this.workflowEngine?.isEnabled()) {
|
|
687
|
-
responseForProcessing = this.workflowEngine.extractNonPlanContent(responseForProcessing);
|
|
688
|
-
}
|
|
689
|
-
if (this.councilEngine) {
|
|
690
|
-
responseForProcessing = this.councilEngine.extractNonPlanContent(responseForProcessing);
|
|
691
|
-
}
|
|
692
|
-
const cleanedResponse = await this.executeAgentToolCalls(agentId, responseForProcessing);
|
|
693
|
-
// Detect API error responses — skip mention resolution to prevent error loops
|
|
694
|
-
const isErrorResponse = /API Error:\s*\d{3}\b/.test(cleanedResponse);
|
|
695
|
-
const resolvedResponse = isErrorResponse
|
|
696
|
-
? cleanedResponse
|
|
697
|
-
: this.resolveResponseMentions(cleanedResponse);
|
|
698
|
-
const formattedResponse = this.formatAgentResponse(agent, resolvedResponse);
|
|
699
|
-
return {
|
|
700
|
-
agentId,
|
|
701
|
-
agent,
|
|
702
|
-
content: formattedResponse,
|
|
703
|
-
rawContent: resolvedResponse,
|
|
704
|
-
duration: result.duration_ms,
|
|
705
|
-
};
|
|
706
|
-
}
|
|
707
|
-
catch (error) {
|
|
708
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
709
|
-
console.error(`[MultiAgent] Failed to get response from ${agentId}:`, error);
|
|
710
|
-
if (errMsg.includes('busy')) {
|
|
711
|
-
logger.info(`[MultiAgent] Agent ${agentId} busy, enqueuing message`);
|
|
712
|
-
const queuedMessage = {
|
|
713
|
-
prompt: fullPrompt,
|
|
714
|
-
channelId: context.channelId,
|
|
715
|
-
threadTs: context.messageId,
|
|
716
|
-
source: 'discord',
|
|
717
|
-
enqueuedAt: Date.now(),
|
|
718
|
-
context,
|
|
719
|
-
discordMessageId: discordMessage?.id,
|
|
720
|
-
};
|
|
721
|
-
this.messageQueue.enqueue(agentId, queuedMessage);
|
|
722
|
-
// Trigger immediate drain if process is idle or reaped
|
|
723
|
-
this.tryDrainNow(agentId, 'discord', context.channelId).catch(() => { });
|
|
724
|
-
if (discordMessage) {
|
|
725
|
-
try {
|
|
726
|
-
await discordMessage.react('⏳');
|
|
727
|
-
}
|
|
728
|
-
catch {
|
|
729
|
-
/* ignore */
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
return null;
|
|
734
|
-
}
|
|
735
|
-
finally {
|
|
736
|
-
this.workTracker.completeWork(agentId, context.channelId);
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
/**
|
|
740
|
-
* Build message context from Discord message
|
|
741
|
-
*/
|
|
742
|
-
buildMessageContext(message, cleanContent) {
|
|
743
|
-
const isBot = message.author.bot;
|
|
744
|
-
let senderAgentId;
|
|
745
|
-
if (isBot) {
|
|
746
|
-
// Check if message is from one of our agent bots
|
|
747
|
-
const agentBotId = this.multiBotManager.isFromAgentBot(message);
|
|
748
|
-
if (agentBotId && agentBotId !== 'main') {
|
|
749
|
-
senderAgentId = agentBotId;
|
|
750
|
-
}
|
|
751
|
-
else {
|
|
752
|
-
// Try to extract agent ID from message display name (main bot)
|
|
753
|
-
const extracted = this.orchestrator.extractAgentIdFromMessage(message.content);
|
|
754
|
-
senderAgentId = extracted ?? undefined;
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
// Extract mentioned agent IDs from Discord mentions
|
|
758
|
-
const mentionedAgentIds = isBot ? undefined : this.extractMentionedAgentIds(message.content);
|
|
759
|
-
return {
|
|
760
|
-
channelId: message.channel.id,
|
|
761
|
-
userId: message.author.id,
|
|
762
|
-
content: cleanContent,
|
|
763
|
-
isBot,
|
|
764
|
-
senderAgentId,
|
|
765
|
-
mentionedAgentIds: mentionedAgentIds?.length ? mentionedAgentIds : undefined,
|
|
766
|
-
messageId: message.id,
|
|
767
|
-
timestamp: message.createdTimestamp,
|
|
768
|
-
};
|
|
769
|
-
}
|
|
770
|
-
/**
|
|
771
|
-
* Send queued response to Discord (F7: message queue drain callback)
|
|
772
|
-
*/
|
|
773
|
-
async sendQueuedResponse(agentId, message, response) {
|
|
774
|
-
const agent = this.orchestrator.getAgent(agentId);
|
|
775
|
-
if (!agent) {
|
|
776
|
-
console.error(`[MultiAgent] Unknown agent in queue: ${agentId}`);
|
|
777
|
-
return;
|
|
778
|
-
}
|
|
779
|
-
// Try executing workflow if this is a conductor response with a workflow_plan
|
|
780
|
-
let cleanedResponse;
|
|
781
|
-
const workflowResult = await this.tryExecuteWorkflow(response, message.channelId, 'discord');
|
|
782
|
-
if (workflowResult && !workflowResult.failed) {
|
|
783
|
-
cleanedResponse = workflowResult.directMessage
|
|
784
|
-
? `${workflowResult.directMessage}\n\n${workflowResult.result}`
|
|
785
|
-
: workflowResult.result;
|
|
786
|
-
}
|
|
787
|
-
else {
|
|
788
|
-
// Strip workflow/council plan JSON that wasn't executed
|
|
789
|
-
let strippedResponse = response;
|
|
790
|
-
if (this.workflowEngine?.isEnabled()) {
|
|
791
|
-
strippedResponse = this.workflowEngine.extractNonPlanContent(strippedResponse);
|
|
792
|
-
}
|
|
793
|
-
if (this.councilEngine) {
|
|
794
|
-
strippedResponse = this.councilEngine.extractNonPlanContent(strippedResponse);
|
|
795
|
-
}
|
|
796
|
-
// Execute gateway tool calls from response
|
|
797
|
-
cleanedResponse = await this.executeAgentToolCalls(agentId, strippedResponse);
|
|
798
|
-
}
|
|
799
|
-
const displayResponse = cleanedResponse;
|
|
800
|
-
// Format response with agent prefix
|
|
801
|
-
const formattedResponse = this.formatAgentResponse(agent, displayResponse);
|
|
802
|
-
const chunks = (0, message_splitter_js_1.splitForDiscord)(formattedResponse);
|
|
803
|
-
const hasOwnBot = this.multiBotManager.hasAgentBot(agentId);
|
|
804
|
-
for (const chunk of chunks) {
|
|
805
|
-
try {
|
|
806
|
-
if (hasOwnBot) {
|
|
807
|
-
// Use agent's dedicated bot - send to channel
|
|
808
|
-
await this.multiBotManager.sendAsAgent(agentId, message.channelId, chunk);
|
|
809
|
-
}
|
|
810
|
-
else if (this.discordClient) {
|
|
811
|
-
// Use main bot via stored Discord client
|
|
812
|
-
const channel = await this.discordClient.channels.fetch(message.channelId);
|
|
813
|
-
if (channel && 'send' in channel) {
|
|
814
|
-
await channel.send(chunk);
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
else {
|
|
818
|
-
console.warn(`[MultiAgent] Cannot send queued message for ${agentId}: no agent bot or Discord client`);
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
catch (err) {
|
|
822
|
-
console.error(`[MultiAgent] Failed to send queued response for ${agentId}:`, err);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
// Record to shared context
|
|
826
|
-
this.sharedContext.recordAgentMessage(message.channelId, agent, response, '');
|
|
827
|
-
// Mark original Discord message as completed
|
|
828
|
-
if (message.discordMessageId && this.discordClient) {
|
|
829
|
-
try {
|
|
830
|
-
const channel = await this.discordClient.channels.fetch(message.channelId);
|
|
831
|
-
if (channel && 'messages' in channel) {
|
|
832
|
-
const originalMsg = await channel.messages.fetch(message.discordMessageId);
|
|
833
|
-
if (originalMsg) {
|
|
834
|
-
await originalMsg.react('✅');
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
catch {
|
|
839
|
-
/* ignore -- message may have been deleted */
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
logger.info(`[MultiAgent] Queued message delivered for ${agentId} in ${message.channelId}`);
|
|
843
|
-
}
|
|
844
|
-
/**
|
|
845
|
-
* Send formatted response to Discord (handles message splitting)
|
|
846
|
-
* Uses agent's dedicated bot if available, otherwise main bot
|
|
847
|
-
*/
|
|
848
|
-
async sendAgentResponses(originalMessage, responses) {
|
|
849
|
-
const sentMessages = [];
|
|
850
|
-
for (const response of responses) {
|
|
851
|
-
try {
|
|
852
|
-
const chunks = (0, message_splitter_js_1.splitForDiscord)(response.content);
|
|
853
|
-
const hasOwnBot = this.multiBotManager.hasAgentBot(response.agentId);
|
|
854
|
-
for (let i = 0; i < chunks.length; i++) {
|
|
855
|
-
let sentMessage = null;
|
|
856
|
-
try {
|
|
857
|
-
if (hasOwnBot) {
|
|
858
|
-
// Use agent's dedicated bot
|
|
859
|
-
if (i === 0) {
|
|
860
|
-
// First chunk: reply to original message
|
|
861
|
-
sentMessage = await this.multiBotManager.replyAsAgent(response.agentId, originalMessage, chunks[i]);
|
|
862
|
-
}
|
|
863
|
-
else {
|
|
864
|
-
// Subsequent chunks: send as new message
|
|
865
|
-
sentMessage = await this.multiBotManager.sendAsAgent(response.agentId, originalMessage.channel.id, chunks[i]);
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
else {
|
|
869
|
-
// Use main bot
|
|
870
|
-
if (sentMessages.length === 0 && i === 0) {
|
|
871
|
-
// First message: reply to original
|
|
872
|
-
sentMessage = await originalMessage.reply({ content: chunks[i] });
|
|
873
|
-
}
|
|
874
|
-
else {
|
|
875
|
-
// Subsequent messages: send as new message
|
|
876
|
-
if ('send' in originalMessage.channel) {
|
|
877
|
-
sentMessage = await originalMessage.channel.send({ content: chunks[i] });
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
if (sentMessage) {
|
|
882
|
-
sentMessages.push(sentMessage);
|
|
883
|
-
// Update response with message ID (for chain tracking)
|
|
884
|
-
if (i === 0) {
|
|
885
|
-
response.messageId = sentMessage.id;
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
|
-
catch (chunkErr) {
|
|
890
|
-
// Per-chunk error handling: don't let one chunk failure drop remaining chunks
|
|
891
|
-
console.error(`[MultiAgent] Failed to send chunk ${i + 1}/${chunks.length} for agent ${response.agentId}:`, chunkErr);
|
|
892
|
-
// Continue with next chunk
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
catch (err) {
|
|
897
|
-
// Per-response error handling: don't let one agent's failure drop other agents' responses
|
|
898
|
-
console.error(`[MultiAgent] Failed to send response for agent ${response.agentId}:`, err);
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
// Post-send: Auto-review trigger for default agent (Armed Conductor) self-implementations
|
|
902
|
-
const defaultAgentId = this.config.default_agent;
|
|
903
|
-
if (defaultAgentId) {
|
|
904
|
-
const selfImplemented = responses.find((r) => r.agentId === defaultAgentId && this.detectSelfImplementation(r.rawContent));
|
|
905
|
-
if (selfImplemented && sentMessages.length > 0) {
|
|
906
|
-
this.triggerAutoReviewIfNeeded(originalMessage.channel.id, defaultAgentId).catch((err) => console.error('[AutoReview] Failed to check diff size:', err));
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
return sentMessages;
|
|
910
|
-
}
|
|
911
|
-
/**
|
|
912
|
-
* Detect if the default agent (Conductor) performed direct code edits.
|
|
913
|
-
* Checks for Claude CLI tool-use markers that indicate Edit/Write operations.
|
|
914
|
-
*/
|
|
915
|
-
detectSelfImplementation(rawContent) {
|
|
916
|
-
// Claude CLI responses contain tool use results -- look for Edit/Write indicators
|
|
917
|
-
const editIndicators = [
|
|
918
|
-
/\bedit\b.*\bapplied\b/i,
|
|
919
|
-
/\bwrote\b.*\bfile\b/i,
|
|
920
|
-
/\bmodified\b.*\bfile/i,
|
|
921
|
-
/\bEdit\b.*\bsuccess/i,
|
|
922
|
-
/\bWrite\b.*\bsuccess/i,
|
|
923
|
-
/파일.*수정/, // Korean: "file...modified" — detects Korean user input
|
|
924
|
-
/수정.*완료/, // Korean: "modification...completed" — detects Korean user input
|
|
925
|
-
/\[SOLO\]/i,
|
|
926
|
-
/\[PAIR\]/i,
|
|
927
|
-
];
|
|
928
|
-
return editIndicators.some((pattern) => pattern.test(rawContent));
|
|
929
|
-
}
|
|
930
|
-
/**
|
|
931
|
-
* Check git diff size after Conductor self-implementation.
|
|
932
|
-
* If diff exceeds thresholds, auto-trigger Reviewer for quality gate.
|
|
933
|
-
*
|
|
934
|
-
* Thresholds (PAIR mode auto-escalation):
|
|
935
|
-
* - >3 files changed -> auto-mention Reviewer
|
|
936
|
-
* - >200 lines changed -> auto-mention Reviewer
|
|
937
|
-
*/
|
|
938
|
-
async triggerAutoReviewIfNeeded(channelId, defaultAgentId) {
|
|
939
|
-
const MAX_FILES = 3;
|
|
940
|
-
const MAX_LINES = 200;
|
|
941
|
-
try {
|
|
942
|
-
// Get diff stats from git
|
|
943
|
-
const { stdout: diffStat } = await execFileAsync('git', ['diff', '--stat', '--cached'], {
|
|
944
|
-
cwd: process.cwd(),
|
|
945
|
-
timeout: 5000,
|
|
946
|
-
});
|
|
947
|
-
// Also check unstaged changes (increased timeout for large repos)
|
|
948
|
-
const { stdout: diffUnstaged } = await execFileAsync('git', ['diff', '--stat'], {
|
|
949
|
-
cwd: process.cwd(),
|
|
950
|
-
timeout: 10000,
|
|
951
|
-
});
|
|
952
|
-
const combinedDiff = diffStat + '\n' + diffUnstaged;
|
|
953
|
-
const fileLines = combinedDiff
|
|
954
|
-
.split('\n')
|
|
955
|
-
.filter((l) => l.includes('|'))
|
|
956
|
-
.map((l) => l.trim())
|
|
957
|
-
.filter((l) => l.length > 0);
|
|
958
|
-
const filesChanged = fileLines.length;
|
|
959
|
-
// Parse total insertions/deletions from summary line
|
|
960
|
-
const summaryMatch = combinedDiff.match(/(\d+)\s+insertion|(\d+)\s+deletion/g);
|
|
961
|
-
let totalLines = 0;
|
|
962
|
-
if (summaryMatch) {
|
|
963
|
-
for (const m of summaryMatch) {
|
|
964
|
-
const num = m.match(/(\d+)/);
|
|
965
|
-
if (num) {
|
|
966
|
-
totalLines += parseInt(num[1], 10);
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
if (filesChanged > MAX_FILES || totalLines > MAX_LINES) {
|
|
971
|
-
logger.info(`[AutoReview] Conductor self-implementation exceeded thresholds: ${filesChanged} files, ${totalLines} lines -> auto-triggering Reviewer`);
|
|
972
|
-
// Find reviewer agent using shared helper
|
|
973
|
-
const reviewerEntry = this.findReviewerAgent();
|
|
974
|
-
const reviewerAgentId = reviewerEntry?.[0];
|
|
975
|
-
if (reviewerAgentId && this.multiBotManager.hasAgentBot(reviewerAgentId)) {
|
|
976
|
-
const reviewMsg = `⬆️ **Auto-Review Triggered** -- ${defaultAgentId} self-implemented but diff exceeded thresholds (${filesChanged} files, ${totalLines} lines). Requesting @Reviewer auto-review.`;
|
|
977
|
-
await this.multiBotManager.sendAsAgent(reviewerAgentId, channelId, reviewMsg);
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
else {
|
|
981
|
-
logger.info(`[AutoReview] Conductor self-implementation within thresholds: ${filesChanged} files, ${totalLines} lines -- no auto-review needed`);
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
catch {
|
|
985
|
-
// Git not available or not in a repo -- skip silently
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
/**
|
|
989
|
-
* Get multi-bot manager
|
|
990
|
-
*/
|
|
991
|
-
getMultiBotManager() {
|
|
992
|
-
return this.multiBotManager;
|
|
993
|
-
}
|
|
994
|
-
/**
|
|
995
|
-
* Get status of all agent bots
|
|
996
|
-
*/
|
|
997
|
-
getBotStatus() {
|
|
998
|
-
return this.multiBotManager.getStatus();
|
|
999
|
-
}
|
|
1000
|
-
/**
|
|
1001
|
-
* After sending agent responses, check for mentions to other agents and route them.
|
|
1002
|
-
* Discord equivalent of Slack's routeResponseMentions -- necessary because Discord
|
|
1003
|
-
* bots don't receive their own messages as events.
|
|
1004
|
-
*/
|
|
1005
|
-
async routeResponseMentions(originalMessage, responses) {
|
|
1006
|
-
for (const response of responses) {
|
|
1007
|
-
// Filter out self-mentions only. All agents can route to any other agent
|
|
1008
|
-
// including LEAD -- the receiving LLM agent can reason about whether to
|
|
1009
|
-
// respond with new information or acknowledge without repeating.
|
|
1010
|
-
const mentionedAgentIds = this.extractMentionedAgentIds(response.rawContent).filter((id) => id !== response.agentId // no self-mention
|
|
1011
|
-
);
|
|
1012
|
-
if (mentionedAgentIds.length === 0)
|
|
1013
|
-
continue;
|
|
1014
|
-
logger.info(`[MultiAgent] Auto-routing mentions from ${response.agentId}: -> ${mentionedAgentIds.join(', ')}`);
|
|
1015
|
-
// Route to all mentioned agents in parallel
|
|
1016
|
-
await Promise.all(mentionedAgentIds.map((targetAgentId) => this.handleDelegatedMention(targetAgentId, originalMessage, response)));
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
/**
|
|
1020
|
-
* Handle a delegated mention: process target agent response and recursively route.
|
|
1021
|
-
*/
|
|
1022
|
-
async handleDelegatedMention(targetAgentId, originalMessage, sourceResponse) {
|
|
1023
|
-
// Dedup: prevent double processing
|
|
1024
|
-
const dedupKey = `${targetAgentId}:${sourceResponse.messageId || originalMessage.id}`;
|
|
1025
|
-
if (this.processedMentions.has(dedupKey))
|
|
1026
|
-
return;
|
|
1027
|
-
this.processedMentions.set(dedupKey, Date.now());
|
|
1028
|
-
// Chain depth check
|
|
1029
|
-
const chainState = this.orchestrator.getChainState(originalMessage.channel.id);
|
|
1030
|
-
const maxDepth = this.config.max_mention_depth ?? 3;
|
|
1031
|
-
if (chainState.blocked || chainState.length >= maxDepth) {
|
|
1032
|
-
logger.info(`[MultiAgent] Delegation chain blocked/maxed in ${originalMessage.channel.id}`);
|
|
1033
|
-
return;
|
|
1034
|
-
}
|
|
1035
|
-
// Delegation rule validation (Phase 4)
|
|
1036
|
-
if (this.config.delegation_rules) {
|
|
1037
|
-
const rule = this.config.delegation_rules.find((r) => r.from === sourceResponse.agentId && r.to.includes(targetAgentId));
|
|
1038
|
-
if (!rule) {
|
|
1039
|
-
logger.info(`[MultiAgent] Delegation blocked by rule: ${sourceResponse.agentId} → ${targetAgentId}`);
|
|
1040
|
-
return;
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
logger.info(`[MultiAgent] Delegated mention: ${sourceResponse.agentId} -> ${targetAgentId}`);
|
|
1044
|
-
// React on the delegation message (source agent's response), not the user's original message
|
|
1045
|
-
const hasOwnBot = this.multiBotManager.hasAgentBot(targetAgentId);
|
|
1046
|
-
const delegationMsgId = sourceResponse.messageId || originalMessage.id;
|
|
1047
|
-
const channelId = originalMessage.channel.id;
|
|
1048
|
-
try {
|
|
1049
|
-
if (hasOwnBot) {
|
|
1050
|
-
await this.multiBotManager.reactAsAgent(targetAgentId, channelId, delegationMsgId, '👀');
|
|
1051
|
-
}
|
|
1052
|
-
else {
|
|
1053
|
-
await originalMessage.react('👀');
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
catch {
|
|
1057
|
-
/* ignore */
|
|
1058
|
-
}
|
|
1059
|
-
const truncatedDescription = sourceResponse.rawContent
|
|
1060
|
-
.replace(/<@!?\d+>/g, '')
|
|
1061
|
-
.trim()
|
|
1062
|
-
.substring(0, 200);
|
|
1063
|
-
this.systemReminder.notify({
|
|
1064
|
-
type: 'delegation-started',
|
|
1065
|
-
taskId: '',
|
|
1066
|
-
description: truncatedDescription,
|
|
1067
|
-
agentId: targetAgentId,
|
|
1068
|
-
requestedBy: sourceResponse.agentId,
|
|
1069
|
-
channelId,
|
|
1070
|
-
source: 'discord',
|
|
1071
|
-
timestamp: Date.now(),
|
|
1072
|
-
});
|
|
1073
|
-
const delegationContent = sourceResponse.rawContent.replace(/<@!?\d+>/g, '').trim();
|
|
1074
|
-
try {
|
|
1075
|
-
const response = await this.processAgentResponse(targetAgentId, {
|
|
1076
|
-
channelId,
|
|
1077
|
-
userId: originalMessage.author.id,
|
|
1078
|
-
content: delegationContent,
|
|
1079
|
-
isBot: true,
|
|
1080
|
-
senderAgentId: sourceResponse.agentId,
|
|
1081
|
-
mentionedAgentIds: [targetAgentId],
|
|
1082
|
-
messageId: originalMessage.id,
|
|
1083
|
-
timestamp: originalMessage.createdTimestamp,
|
|
1084
|
-
}, delegationContent, undefined // Don't pass discordMessage -- emojis handled here via delegation messageId
|
|
1085
|
-
);
|
|
1086
|
-
if (response) {
|
|
1087
|
-
this.systemReminder.notify({
|
|
1088
|
-
type: 'delegation-completed',
|
|
1089
|
-
taskId: '',
|
|
1090
|
-
description: truncatedDescription,
|
|
1091
|
-
agentId: targetAgentId,
|
|
1092
|
-
requestedBy: sourceResponse.agentId,
|
|
1093
|
-
channelId,
|
|
1094
|
-
source: 'discord',
|
|
1095
|
-
duration: response.duration,
|
|
1096
|
-
timestamp: Date.now(),
|
|
1097
|
-
});
|
|
1098
|
-
await this.sendAgentResponses(originalMessage, [response]);
|
|
1099
|
-
this.orchestrator.recordAgentResponse(targetAgentId, originalMessage.channel.id, response.messageId);
|
|
1100
|
-
// Recursively route mentions in this agent's response
|
|
1101
|
-
await this.routeResponseMentions(originalMessage, [response]);
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
catch (err) {
|
|
1105
|
-
const isBusy = err instanceof Error && err.message.includes('Process is busy');
|
|
1106
|
-
if (isBusy) {
|
|
1107
|
-
logger.info(`[MultiAgent] ${targetAgentId} busy, enqueuing delegation from ${sourceResponse.agentId}`);
|
|
1108
|
-
this.messageQueue.enqueue(targetAgentId, {
|
|
1109
|
-
prompt: delegationContent,
|
|
1110
|
-
channelId,
|
|
1111
|
-
source: 'discord',
|
|
1112
|
-
enqueuedAt: Date.now(),
|
|
1113
|
-
context: { channelId, userId: originalMessage.author.id },
|
|
1114
|
-
});
|
|
1115
|
-
this.tryDrainNow(targetAgentId, 'discord', channelId).catch(() => { });
|
|
1116
|
-
}
|
|
1117
|
-
else {
|
|
1118
|
-
console.error(`[MultiAgent] Delegated mention error (${targetAgentId}):`, err);
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
finally {
|
|
1122
|
-
// Add checkmark on the delegation message (source agent's response)
|
|
1123
|
-
try {
|
|
1124
|
-
if (hasOwnBot) {
|
|
1125
|
-
await this.multiBotManager.reactAsAgent(targetAgentId, channelId, delegationMsgId, '✅');
|
|
1126
|
-
}
|
|
1127
|
-
else {
|
|
1128
|
-
// Fix: React to the delegation message, not the original user message
|
|
1129
|
-
const delegationMsg = await originalMessage.channel.messages.fetch(delegationMsgId);
|
|
1130
|
-
await delegationMsg.react('✅');
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
catch {
|
|
1134
|
-
/* ignore */
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
/**
|
|
1139
|
-
* Execute text-based tool calls, routing discord_send through the agent's own bot.
|
|
1140
|
-
* Non-discord tools fall through to the base executeTextToolCalls.
|
|
1141
|
-
*/
|
|
1142
|
-
async executeAgentToolCalls(agentId, responseText) {
|
|
1143
|
-
const toolCalls = this.parseToolCallsFromText(responseText);
|
|
1144
|
-
if (toolCalls.length === 0)
|
|
1145
|
-
return responseText;
|
|
1146
|
-
const hasOwnBot = this.multiBotManager.hasAgentBot(agentId);
|
|
1147
|
-
for (const toolCall of toolCalls) {
|
|
1148
|
-
try {
|
|
1149
|
-
if (toolCall.name === 'discord_send' && hasOwnBot) {
|
|
1150
|
-
if (typeof toolCall.input !== 'object' || toolCall.input === null) {
|
|
1151
|
-
console.warn(`[MultiAgent] Tool ${toolCall.name}: invalid input (not an object)`);
|
|
1152
|
-
continue;
|
|
1153
|
-
}
|
|
1154
|
-
const input = toolCall.input;
|
|
1155
|
-
const channelId = typeof input.channel_id === 'string' ? input.channel_id : undefined;
|
|
1156
|
-
const filePath = typeof input.file_path === 'string'
|
|
1157
|
-
? input.file_path
|
|
1158
|
-
: typeof input.image_path === 'string'
|
|
1159
|
-
? input.image_path
|
|
1160
|
-
: undefined;
|
|
1161
|
-
const message = typeof input.message === 'string' ? input.message : undefined;
|
|
1162
|
-
if (!channelId || (!filePath && !message)) {
|
|
1163
|
-
console.warn(`[MultiAgent] Tool ${toolCall.name}: missing channel_id or payload`);
|
|
1164
|
-
continue;
|
|
1165
|
-
}
|
|
1166
|
-
if (channelId && filePath) {
|
|
1167
|
-
await this.multiBotManager.sendFileAsAgent(agentId, channelId, filePath, message);
|
|
1168
|
-
}
|
|
1169
|
-
else if (channelId && message) {
|
|
1170
|
-
await this.multiBotManager.sendAsAgent(agentId, channelId, message);
|
|
1171
|
-
}
|
|
1172
|
-
logger.info(`[MultiAgent] discord_send routed through agent bot: ${agentId}`);
|
|
1173
|
-
}
|
|
1174
|
-
else if (this.gatewayToolExecutor) {
|
|
1175
|
-
const result = await this.gatewayToolExecutor.execute(toolCall.name, toolCall.input);
|
|
1176
|
-
logger.info(`[MultiAgent] Tool ${toolCall.name} succeeded:`, JSON.stringify(result).substring(0, 200));
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
catch (error) {
|
|
1180
|
-
console.error(`[MultiAgent] Tool ${toolCall.name} failed:`, error instanceof Error ? error.message : error);
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
return this.removeToolCallBlocks(responseText);
|
|
1184
|
-
}
|
|
1185
|
-
/**
|
|
1186
|
-
* Resolve @Name mentions in LLM response text to <@userId> Discord format.
|
|
1187
|
-
* LLMs generate plain text like "@LEAD", "@Conductor", "@DevBot" which won't
|
|
1188
|
-
* trigger Discord mentions or routeResponseMentions detection.
|
|
1189
|
-
*/
|
|
1190
|
-
resolveResponseMentions(text) {
|
|
1191
|
-
if (!this.config.mention_delegation)
|
|
1192
|
-
return text;
|
|
1193
|
-
const botUserIdMap = this.multiBotManager.getBotUserIdMap();
|
|
1194
|
-
const mainBotUserId = this.multiBotManager.getMainBotUserId();
|
|
1195
|
-
const defaultAgentId = this.config.default_agent;
|
|
1196
|
-
// Build pattern -> <@userId> lookup
|
|
1197
|
-
const patterns = new Map();
|
|
1198
|
-
for (const [agentId, agentConfig] of Object.entries(this.config.agents)) {
|
|
1199
|
-
let userId = botUserIdMap.get(agentId);
|
|
1200
|
-
if (!userId && agentId === defaultAgentId && mainBotUserId) {
|
|
1201
|
-
userId = mainBotUserId;
|
|
1202
|
-
}
|
|
1203
|
-
if (!userId)
|
|
1204
|
-
continue;
|
|
1205
|
-
const mention = `<@${userId}>`;
|
|
1206
|
-
if (agentConfig.name)
|
|
1207
|
-
patterns.set(agentConfig.name.toLowerCase(), { mention, agentId });
|
|
1208
|
-
if (agentConfig.display_name)
|
|
1209
|
-
patterns.set(agentConfig.display_name.toLowerCase(), { mention, agentId });
|
|
1210
|
-
patterns.set(agentId.toLowerCase(), { mention, agentId });
|
|
1211
|
-
}
|
|
1212
|
-
// Also match "LEAD" for the default agent
|
|
1213
|
-
if (defaultAgentId && mainBotUserId) {
|
|
1214
|
-
patterns.set('lead', { mention: `<@${mainBotUserId}>`, agentId: defaultAgentId });
|
|
1215
|
-
}
|
|
1216
|
-
let resolved = text;
|
|
1217
|
-
for (const [pattern, { mention }] of patterns) {
|
|
1218
|
-
// Match @pattern but NOT already-resolved <@pattern
|
|
1219
|
-
const regex = new RegExp(`(?<!<)@${pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'gi');
|
|
1220
|
-
resolved = resolved.replace(regex, mention);
|
|
1221
|
-
}
|
|
1222
|
-
return resolved;
|
|
1223
|
-
}
|
|
1224
|
-
getEffectiveMaxMentionDepth() {
|
|
1225
|
-
return this.config.max_mention_depth ?? 3;
|
|
1226
|
-
}
|
|
1227
|
-
/**
|
|
1228
|
-
* Find the reviewer agent entry from config
|
|
1229
|
-
*/
|
|
1230
|
-
findReviewerAgent() {
|
|
1231
|
-
return Object.entries(this.config.agents).find(([aid, cfg]) => aid.toLowerCase().includes('review') || cfg.name?.toLowerCase().includes('review'));
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
exports.MultiAgentDiscordHandler = MultiAgentDiscordHandler;
|
|
1235
|
-
//# sourceMappingURL=multi-agent-discord.js.map
|