@wingman-ai/gateway 0.1.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/.wingman/agents/README.md +161 -0
- package/.wingman/agents/coding/agent.md +147 -0
- package/.wingman/agents/coding/implementor.md +56 -0
- package/.wingman/agents/main/agent.md +19 -0
- package/.wingman/agents/researcher/agent.md +62 -0
- package/.wingman/agents/stock-trader/agent.md +223 -0
- package/.wingman/agents/stock-trader/chain-curator.md +24 -0
- package/.wingman/agents/stock-trader/goal-translator.md +42 -0
- package/.wingman/agents/stock-trader/guardrails-veto.md +11 -0
- package/.wingman/agents/stock-trader/path-planner.md +23 -0
- package/.wingman/agents/stock-trader/regime-analyst.md +15 -0
- package/.wingman/agents/stock-trader/risk.md +20 -0
- package/.wingman/agents/stock-trader/selection.md +22 -0
- package/.wingman/agents/stock-trader/strategy-composer.md +38 -0
- package/.wingman/agents/wingman/agent.json +12 -0
- package/bin/wingman +7 -0
- package/dist/agent/config/agentConfig.cjs +95 -0
- package/dist/agent/config/agentConfig.d.ts +187 -0
- package/dist/agent/config/agentConfig.js +52 -0
- package/dist/agent/config/agentLoader.cjs +242 -0
- package/dist/agent/config/agentLoader.d.ts +42 -0
- package/dist/agent/config/agentLoader.js +208 -0
- package/dist/agent/config/mcpClientManager.cjs +168 -0
- package/dist/agent/config/mcpClientManager.d.ts +41 -0
- package/dist/agent/config/mcpClientManager.js +134 -0
- package/dist/agent/config/modelFactory.cjs +175 -0
- package/dist/agent/config/modelFactory.d.ts +33 -0
- package/dist/agent/config/modelFactory.js +141 -0
- package/dist/agent/config/toolRegistry.cjs +111 -0
- package/dist/agent/config/toolRegistry.d.ts +25 -0
- package/dist/agent/config/toolRegistry.js +71 -0
- package/dist/agent/middleware/additional-messages.cjs +60 -0
- package/dist/agent/middleware/additional-messages.d.ts +7 -0
- package/dist/agent/middleware/additional-messages.js +26 -0
- package/dist/agent/middleware/hooks/executor.cjs +137 -0
- package/dist/agent/middleware/hooks/executor.d.ts +52 -0
- package/dist/agent/middleware/hooks/executor.js +103 -0
- package/dist/agent/middleware/hooks/input-builder.cjs +55 -0
- package/dist/agent/middleware/hooks/input-builder.d.ts +15 -0
- package/dist/agent/middleware/hooks/input-builder.js +21 -0
- package/dist/agent/middleware/hooks/matcher.cjs +59 -0
- package/dist/agent/middleware/hooks/matcher.d.ts +27 -0
- package/dist/agent/middleware/hooks/matcher.js +22 -0
- package/dist/agent/middleware/hooks/merger.cjs +54 -0
- package/dist/agent/middleware/hooks/merger.d.ts +18 -0
- package/dist/agent/middleware/hooks/merger.js +20 -0
- package/dist/agent/middleware/hooks/types.cjs +62 -0
- package/dist/agent/middleware/hooks/types.d.ts +82 -0
- package/dist/agent/middleware/hooks/types.js +19 -0
- package/dist/agent/middleware/hooks.cjs +79 -0
- package/dist/agent/middleware/hooks.d.ts +19 -0
- package/dist/agent/middleware/hooks.js +45 -0
- package/dist/agent/middleware/media-compat.cjs +80 -0
- package/dist/agent/middleware/media-compat.d.ts +7 -0
- package/dist/agent/middleware/media-compat.js +46 -0
- package/dist/agent/tests/agentConfig.test.cjs +132 -0
- package/dist/agent/tests/agentConfig.test.d.ts +1 -0
- package/dist/agent/tests/agentConfig.test.js +126 -0
- package/dist/agent/tests/agentLoader.test.cjs +235 -0
- package/dist/agent/tests/agentLoader.test.d.ts +1 -0
- package/dist/agent/tests/agentLoader.test.js +229 -0
- package/dist/agent/tests/modelFactory.test.cjs +114 -0
- package/dist/agent/tests/modelFactory.test.d.ts +1 -0
- package/dist/agent/tests/modelFactory.test.js +108 -0
- package/dist/agent/tests/test-agent-loader.cjs +33 -0
- package/dist/agent/tests/test-agent-loader.d.ts +1 -0
- package/dist/agent/tests/test-agent-loader.js +27 -0
- package/dist/agent/tests/test-subagent-loading.cjs +99 -0
- package/dist/agent/tests/test-subagent-loading.d.ts +1 -0
- package/dist/agent/tests/test-subagent-loading.js +93 -0
- package/dist/agent/tests/toolRegistry.test.cjs +109 -0
- package/dist/agent/tests/toolRegistry.test.d.ts +1 -0
- package/dist/agent/tests/toolRegistry.test.js +103 -0
- package/dist/agent/tools/code_search.cjs +108 -0
- package/dist/agent/tools/code_search.d.ts +24 -0
- package/dist/agent/tools/code_search.js +74 -0
- package/dist/agent/tools/command_execute.cjs +136 -0
- package/dist/agent/tools/command_execute.d.ts +12 -0
- package/dist/agent/tools/command_execute.js +99 -0
- package/dist/agent/tools/git_status.cjs +126 -0
- package/dist/agent/tools/git_status.d.ts +15 -0
- package/dist/agent/tools/git_status.js +92 -0
- package/dist/agent/tools/internet_search.cjs +93 -0
- package/dist/agent/tools/internet_search.d.ts +25 -0
- package/dist/agent/tools/internet_search.js +56 -0
- package/dist/agent/tools/think.cjs +53 -0
- package/dist/agent/tools/think.d.ts +26 -0
- package/dist/agent/tools/think.js +16 -0
- package/dist/agent/tools/web_crawler.cjs +180 -0
- package/dist/agent/tools/web_crawler.d.ts +31 -0
- package/dist/agent/tools/web_crawler.js +143 -0
- package/dist/agent/utils.cjs +54 -0
- package/dist/agent/utils.d.ts +1 -0
- package/dist/agent/utils.js +10 -0
- package/dist/cli/commands/agent.cjs +169 -0
- package/dist/cli/commands/agent.d.ts +15 -0
- package/dist/cli/commands/agent.js +125 -0
- package/dist/cli/commands/gateway.cjs +601 -0
- package/dist/cli/commands/gateway.d.ts +12 -0
- package/dist/cli/commands/gateway.js +567 -0
- package/dist/cli/commands/init.cjs +681 -0
- package/dist/cli/commands/init.d.ts +10 -0
- package/dist/cli/commands/init.js +634 -0
- package/dist/cli/commands/provider.cjs +208 -0
- package/dist/cli/commands/provider.d.ts +5 -0
- package/dist/cli/commands/provider.js +174 -0
- package/dist/cli/commands/skill.cjs +145 -0
- package/dist/cli/commands/skill.d.ts +10 -0
- package/dist/cli/commands/skill.js +111 -0
- package/dist/cli/config/loader.cjs +143 -0
- package/dist/cli/config/loader.d.ts +14 -0
- package/dist/cli/config/loader.js +109 -0
- package/dist/cli/config/schema.cjs +262 -0
- package/dist/cli/config/schema.d.ts +268 -0
- package/dist/cli/config/schema.js +213 -0
- package/dist/cli/core/agentInvoker.cjs +284 -0
- package/dist/cli/core/agentInvoker.d.ts +77 -0
- package/dist/cli/core/agentInvoker.js +247 -0
- package/dist/cli/core/commandHandler.cjs +257 -0
- package/dist/cli/core/commandHandler.d.ts +62 -0
- package/dist/cli/core/commandHandler.js +223 -0
- package/dist/cli/core/database/bunSqliteAdapter.cjs +87 -0
- package/dist/cli/core/database/bunSqliteAdapter.d.ts +34 -0
- package/dist/cli/core/database/bunSqliteAdapter.js +53 -0
- package/dist/cli/core/loggerBridge.cjs +42 -0
- package/dist/cli/core/loggerBridge.d.ts +8 -0
- package/dist/cli/core/loggerBridge.js +8 -0
- package/dist/cli/core/outputManager.cjs +106 -0
- package/dist/cli/core/outputManager.d.ts +43 -0
- package/dist/cli/core/outputManager.js +72 -0
- package/dist/cli/core/sessionManager.cjs +535 -0
- package/dist/cli/core/sessionManager.d.ts +111 -0
- package/dist/cli/core/sessionManager.js +486 -0
- package/dist/cli/core/streamParser.cjs +328 -0
- package/dist/cli/core/streamParser.d.ts +42 -0
- package/dist/cli/core/streamParser.js +288 -0
- package/dist/cli/index.cjs +211 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +205 -0
- package/dist/cli/services/skillRepository.cjs +178 -0
- package/dist/cli/services/skillRepository.d.ts +35 -0
- package/dist/cli/services/skillRepository.js +144 -0
- package/dist/cli/services/skillService.cjs +336 -0
- package/dist/cli/services/skillService.d.ts +48 -0
- package/dist/cli/services/skillService.js +302 -0
- package/dist/cli/types/gateway.cjs +18 -0
- package/dist/cli/types/gateway.d.ts +18 -0
- package/dist/cli/types/gateway.js +0 -0
- package/dist/cli/types/init.cjs +18 -0
- package/dist/cli/types/init.d.ts +13 -0
- package/dist/cli/types/init.js +0 -0
- package/dist/cli/types/provider.cjs +18 -0
- package/dist/cli/types/provider.d.ts +9 -0
- package/dist/cli/types/provider.js +0 -0
- package/dist/cli/types/skill.cjs +18 -0
- package/dist/cli/types/skill.d.ts +71 -0
- package/dist/cli/types/skill.js +0 -0
- package/dist/cli/types.cjs +18 -0
- package/dist/cli/types.d.ts +175 -0
- package/dist/cli/types.js +0 -0
- package/dist/cli/ui/AgentOutput.cjs +82 -0
- package/dist/cli/ui/AgentOutput.d.ts +8 -0
- package/dist/cli/ui/AgentOutput.js +38 -0
- package/dist/cli/ui/App.cjs +285 -0
- package/dist/cli/ui/App.d.ts +6 -0
- package/dist/cli/ui/App.js +241 -0
- package/dist/cli/ui/ErrorDisplay.cjs +65 -0
- package/dist/cli/ui/ErrorDisplay.d.ts +8 -0
- package/dist/cli/ui/ErrorDisplay.js +21 -0
- package/dist/cli/ui/LogDisplay.cjs +74 -0
- package/dist/cli/ui/LogDisplay.d.ts +13 -0
- package/dist/cli/ui/LogDisplay.js +30 -0
- package/dist/cli/ui/SessionListDisplay.cjs +135 -0
- package/dist/cli/ui/SessionListDisplay.d.ts +9 -0
- package/dist/cli/ui/SessionListDisplay.js +91 -0
- package/dist/cli/ui/blockHelpers.cjs +80 -0
- package/dist/cli/ui/blockHelpers.d.ts +21 -0
- package/dist/cli/ui/blockHelpers.js +40 -0
- package/dist/cli/ui/components/ToolCallDisplay.cjs +207 -0
- package/dist/cli/ui/components/ToolCallDisplay.d.ts +7 -0
- package/dist/cli/ui/components/ToolCallDisplay.js +162 -0
- package/dist/cli/ui/components/ToolResultDisplay.cjs +86 -0
- package/dist/cli/ui/components/ToolResultDisplay.d.ts +8 -0
- package/dist/cli/ui/components/ToolResultDisplay.js +42 -0
- package/dist/cli/ui/toolDisplayHelpers.cjs +112 -0
- package/dist/cli/ui/toolDisplayHelpers.d.ts +3 -0
- package/dist/cli/ui/toolDisplayHelpers.js +72 -0
- package/dist/gateway/adapters/discord.cjs +298 -0
- package/dist/gateway/adapters/discord.d.ts +42 -0
- package/dist/gateway/adapters/discord.js +246 -0
- package/dist/gateway/auth.cjs +94 -0
- package/dist/gateway/auth.d.ts +36 -0
- package/dist/gateway/auth.js +60 -0
- package/dist/gateway/broadcast.cjs +131 -0
- package/dist/gateway/broadcast.d.ts +76 -0
- package/dist/gateway/broadcast.js +97 -0
- package/dist/gateway/client.cjs +282 -0
- package/dist/gateway/client.d.ts +141 -0
- package/dist/gateway/client.js +248 -0
- package/dist/gateway/daemon.cjs +195 -0
- package/dist/gateway/daemon.d.ts +67 -0
- package/dist/gateway/daemon.js +161 -0
- package/dist/gateway/discovery/index.cjs +72 -0
- package/dist/gateway/discovery/index.d.ts +3 -0
- package/dist/gateway/discovery/index.js +3 -0
- package/dist/gateway/discovery/mdns.cjs +221 -0
- package/dist/gateway/discovery/mdns.d.ts +37 -0
- package/dist/gateway/discovery/mdns.js +177 -0
- package/dist/gateway/discovery/tailscale.cjs +140 -0
- package/dist/gateway/discovery/tailscale.d.ts +31 -0
- package/dist/gateway/discovery/tailscale.js +106 -0
- package/dist/gateway/discovery/types.cjs +18 -0
- package/dist/gateway/discovery/types.d.ts +41 -0
- package/dist/gateway/discovery/types.js +0 -0
- package/dist/gateway/env.cjs +45 -0
- package/dist/gateway/env.d.ts +2 -0
- package/dist/gateway/env.js +8 -0
- package/dist/gateway/hooks/loader.cjs +137 -0
- package/dist/gateway/hooks/loader.d.ts +10 -0
- package/dist/gateway/hooks/loader.js +103 -0
- package/dist/gateway/hooks/registry.cjs +128 -0
- package/dist/gateway/hooks/registry.d.ts +13 -0
- package/dist/gateway/hooks/registry.js +94 -0
- package/dist/gateway/hooks/types.cjs +58 -0
- package/dist/gateway/hooks/types.d.ts +50 -0
- package/dist/gateway/hooks/types.js +18 -0
- package/dist/gateway/http/agents.cjs +280 -0
- package/dist/gateway/http/agents.d.ts +2 -0
- package/dist/gateway/http/agents.js +246 -0
- package/dist/gateway/http/fs.cjs +81 -0
- package/dist/gateway/http/fs.d.ts +2 -0
- package/dist/gateway/http/fs.js +47 -0
- package/dist/gateway/http/providers.cjs +120 -0
- package/dist/gateway/http/providers.d.ts +2 -0
- package/dist/gateway/http/providers.js +86 -0
- package/dist/gateway/http/routines.cjs +196 -0
- package/dist/gateway/http/routines.d.ts +20 -0
- package/dist/gateway/http/routines.js +159 -0
- package/dist/gateway/http/sessions.cjs +241 -0
- package/dist/gateway/http/sessions.d.ts +2 -0
- package/dist/gateway/http/sessions.js +207 -0
- package/dist/gateway/http/types.cjs +18 -0
- package/dist/gateway/http/types.d.ts +25 -0
- package/dist/gateway/http/types.js +0 -0
- package/dist/gateway/http/voice.cjs +167 -0
- package/dist/gateway/http/voice.d.ts +2 -0
- package/dist/gateway/http/voice.js +133 -0
- package/dist/gateway/http/webhooks.cjs +353 -0
- package/dist/gateway/http/webhooks.d.ts +22 -0
- package/dist/gateway/http/webhooks.js +313 -0
- package/dist/gateway/index.cjs +119 -0
- package/dist/gateway/index.d.ts +8 -0
- package/dist/gateway/index.js +9 -0
- package/dist/gateway/node.cjs +218 -0
- package/dist/gateway/node.d.ts +112 -0
- package/dist/gateway/node.js +184 -0
- package/dist/gateway/router.cjs +85 -0
- package/dist/gateway/router.d.ts +9 -0
- package/dist/gateway/router.js +51 -0
- package/dist/gateway/rpcClient.cjs +152 -0
- package/dist/gateway/rpcClient.d.ts +24 -0
- package/dist/gateway/rpcClient.js +118 -0
- package/dist/gateway/server.cjs +1175 -0
- package/dist/gateway/server.d.ts +185 -0
- package/dist/gateway/server.js +1138 -0
- package/dist/gateway/transport/http.cjs +153 -0
- package/dist/gateway/transport/http.d.ts +25 -0
- package/dist/gateway/transport/http.js +119 -0
- package/dist/gateway/transport/index.cjs +40 -0
- package/dist/gateway/transport/index.d.ts +3 -0
- package/dist/gateway/transport/index.js +3 -0
- package/dist/gateway/transport/types.cjs +18 -0
- package/dist/gateway/transport/types.d.ts +59 -0
- package/dist/gateway/transport/types.js +0 -0
- package/dist/gateway/transport/websocket.cjs +132 -0
- package/dist/gateway/transport/websocket.d.ts +21 -0
- package/dist/gateway/transport/websocket.js +98 -0
- package/dist/gateway/types.cjs +18 -0
- package/dist/gateway/types.d.ts +215 -0
- package/dist/gateway/types.js +0 -0
- package/dist/gateway/validation.cjs +225 -0
- package/dist/gateway/validation.d.ts +157 -0
- package/dist/gateway/validation.js +158 -0
- package/dist/index.cjs +95 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/logger.cjs +270 -0
- package/dist/logger.d.ts +54 -0
- package/dist/logger.js +215 -0
- package/dist/providers/copilot.cjs +148 -0
- package/dist/providers/copilot.d.ts +3 -0
- package/dist/providers/copilot.js +114 -0
- package/dist/providers/credentials.cjs +154 -0
- package/dist/providers/credentials.d.ts +26 -0
- package/dist/providers/credentials.js +99 -0
- package/dist/providers/oauth.cjs +279 -0
- package/dist/providers/oauth.d.ts +13 -0
- package/dist/providers/oauth.js +245 -0
- package/dist/providers/registry.cjs +138 -0
- package/dist/providers/registry.d.ts +32 -0
- package/dist/providers/registry.js +98 -0
- package/dist/tests/additionalMessageMiddleware.test.cjs +45 -0
- package/dist/tests/additionalMessageMiddleware.test.d.ts +1 -0
- package/dist/tests/additionalMessageMiddleware.test.js +39 -0
- package/dist/tests/agent-config-voice.test.cjs +25 -0
- package/dist/tests/agent-config-voice.test.d.ts +1 -0
- package/dist/tests/agent-config-voice.test.js +19 -0
- package/dist/tests/agentInvokerAttachments.test.cjs +67 -0
- package/dist/tests/agentInvokerAttachments.test.d.ts +1 -0
- package/dist/tests/agentInvokerAttachments.test.js +61 -0
- package/dist/tests/attachments-utils.test.cjs +46 -0
- package/dist/tests/attachments-utils.test.d.ts +1 -0
- package/dist/tests/attachments-utils.test.js +40 -0
- package/dist/tests/bunSqliteAdapter.test.cjs +265 -0
- package/dist/tests/bunSqliteAdapter.test.d.ts +1 -0
- package/dist/tests/bunSqliteAdapter.test.js +259 -0
- package/dist/tests/candleRange.test.cjs +48 -0
- package/dist/tests/candleRange.test.d.ts +1 -0
- package/dist/tests/candleRange.test.js +42 -0
- package/dist/tests/cli-config-loader.test.cjs +364 -0
- package/dist/tests/cli-config-loader.test.d.ts +1 -0
- package/dist/tests/cli-config-loader.test.js +358 -0
- package/dist/tests/cli-init.test.cjs +82 -0
- package/dist/tests/cli-init.test.d.ts +1 -0
- package/dist/tests/cli-init.test.js +76 -0
- package/dist/tests/discord-adapter.test.cjs +55 -0
- package/dist/tests/discord-adapter.test.d.ts +1 -0
- package/dist/tests/discord-adapter.test.js +49 -0
- package/dist/tests/gateway.test.cjs +319 -0
- package/dist/tests/gateway.test.d.ts +1 -0
- package/dist/tests/gateway.test.js +313 -0
- package/dist/tests/hooks-matcher.test.cjs +309 -0
- package/dist/tests/hooks-matcher.test.d.ts +1 -0
- package/dist/tests/hooks-matcher.test.js +303 -0
- package/dist/tests/hooks-merger.test.cjs +528 -0
- package/dist/tests/hooks-merger.test.d.ts +1 -0
- package/dist/tests/hooks-merger.test.js +522 -0
- package/dist/tests/integration/agent-invocation.integration.test.cjs +264 -0
- package/dist/tests/integration/agent-invocation.integration.test.d.ts +1 -0
- package/dist/tests/integration/agent-invocation.integration.test.js +258 -0
- package/dist/tests/integration/finnhub-candles.integration.test.cjs +98 -0
- package/dist/tests/integration/finnhub-candles.integration.test.d.ts +1 -0
- package/dist/tests/integration/finnhub-candles.integration.test.js +92 -0
- package/dist/tests/logger.test.cjs +353 -0
- package/dist/tests/logger.test.d.ts +1 -0
- package/dist/tests/logger.test.js +347 -0
- package/dist/tests/mediaCompatibilityMiddleware.test.cjs +106 -0
- package/dist/tests/mediaCompatibilityMiddleware.test.d.ts +1 -0
- package/dist/tests/mediaCompatibilityMiddleware.test.js +100 -0
- package/dist/tests/routines-api.test.cjs +107 -0
- package/dist/tests/routines-api.test.d.ts +1 -0
- package/dist/tests/routines-api.test.js +101 -0
- package/dist/tests/sessionMessageAttachments.test.cjs +108 -0
- package/dist/tests/sessionMessageAttachments.test.d.ts +1 -0
- package/dist/tests/sessionMessageAttachments.test.js +102 -0
- package/dist/tests/sessionMessageRole.test.cjs +44 -0
- package/dist/tests/sessionMessageRole.test.d.ts +1 -0
- package/dist/tests/sessionMessageRole.test.js +38 -0
- package/dist/tests/sessionStateMessages.test.cjs +72 -0
- package/dist/tests/sessionStateMessages.test.d.ts +1 -0
- package/dist/tests/sessionStateMessages.test.js +66 -0
- package/dist/tests/sessions-api.test.cjs +68 -0
- package/dist/tests/sessions-api.test.d.ts +1 -0
- package/dist/tests/sessions-api.test.js +62 -0
- package/dist/tests/technicalIndicators.test.cjs +82 -0
- package/dist/tests/technicalIndicators.test.d.ts +1 -0
- package/dist/tests/technicalIndicators.test.js +76 -0
- package/dist/tests/toolDisplayHelpers.test.cjs +43 -0
- package/dist/tests/toolDisplayHelpers.test.d.ts +1 -0
- package/dist/tests/toolDisplayHelpers.test.js +37 -0
- package/dist/tests/voice-config.test.cjs +35 -0
- package/dist/tests/voice-config.test.d.ts +1 -0
- package/dist/tests/voice-config.test.js +29 -0
- package/dist/tests/yahooCandles.test.cjs +111 -0
- package/dist/tests/yahooCandles.test.d.ts +1 -0
- package/dist/tests/yahooCandles.test.js +105 -0
- package/dist/tools/finance/candleRange.cjs +71 -0
- package/dist/tools/finance/candleRange.d.ts +21 -0
- package/dist/tools/finance/candleRange.js +28 -0
- package/dist/tools/finance/optionsAnalytics.cjs +222 -0
- package/dist/tools/finance/optionsAnalytics.d.ts +44 -0
- package/dist/tools/finance/optionsAnalytics.js +188 -0
- package/dist/tools/finance/optionsAnalytics.test.cjs +128 -0
- package/dist/tools/finance/optionsAnalytics.test.d.ts +1 -0
- package/dist/tools/finance/optionsAnalytics.test.js +122 -0
- package/dist/tools/finance/technicalIndicators.cjs +111 -0
- package/dist/tools/finance/technicalIndicators.d.ts +15 -0
- package/dist/tools/finance/technicalIndicators.js +68 -0
- package/dist/tools/finance/yahooCandles.cjs +125 -0
- package/dist/tools/finance/yahooCandles.d.ts +41 -0
- package/dist/tools/finance/yahooCandles.js +85 -0
- package/dist/tools/mcp-finance.cjs +649 -0
- package/dist/tools/mcp-finance.d.ts +1 -0
- package/dist/tools/mcp-finance.js +631 -0
- package/dist/types/agents.cjs +18 -0
- package/dist/types/agents.d.ts +11 -0
- package/dist/types/agents.js +0 -0
- package/dist/types/hooks.cjs +18 -0
- package/dist/types/hooks.d.ts +82 -0
- package/dist/types/hooks.js +0 -0
- package/dist/types/mcp.cjs +86 -0
- package/dist/types/mcp.d.ts +107 -0
- package/dist/types/mcp.js +40 -0
- package/dist/types/voice.cjs +103 -0
- package/dist/types/voice.d.ts +117 -0
- package/dist/types/voice.js +51 -0
- package/dist/utils/attachments.cjs +46 -0
- package/dist/utils/attachments.d.ts +7 -0
- package/dist/utils/attachments.js +12 -0
- package/dist/voice/config.cjs +52 -0
- package/dist/voice/config.d.ts +8 -0
- package/dist/voice/config.js +18 -0
- package/dist/webui/assets/index-BA0HaStz.css +1 -0
- package/dist/webui/assets/index-NHgTZsWN.js +112 -0
- package/dist/webui/assets/wingman_icon-DOy91UEF.webp +0 -0
- package/dist/webui/assets/wingman_logo-Cogyt3qm.webp +0 -0
- package/dist/webui/index.html +19 -0
- package/package.json +130 -0
|
@@ -0,0 +1,1175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const __rslib_import_meta_url__ = /*#__PURE__*/ function() {
|
|
3
|
+
return "u" < typeof document ? new (require('url'.replace('', ''))).URL('file:' + __filename).href : document.currentScript && document.currentScript.src || new URL('main.js', document.baseURI).href;
|
|
4
|
+
}();
|
|
5
|
+
var __webpack_require__ = {};
|
|
6
|
+
(()=>{
|
|
7
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
8
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: definition[key]
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
16
|
+
})();
|
|
17
|
+
(()=>{
|
|
18
|
+
__webpack_require__.r = (exports1)=>{
|
|
19
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
20
|
+
value: 'Module'
|
|
21
|
+
});
|
|
22
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
23
|
+
value: true
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
})();
|
|
27
|
+
var __webpack_exports__ = {};
|
|
28
|
+
__webpack_require__.r(__webpack_exports__);
|
|
29
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
30
|
+
GatewayServer: ()=>GatewayServer
|
|
31
|
+
});
|
|
32
|
+
const external_node_cjs_namespaceObject = require("./node.cjs");
|
|
33
|
+
const external_broadcast_cjs_namespaceObject = require("./broadcast.cjs");
|
|
34
|
+
const external_auth_cjs_namespaceObject = require("./auth.cjs");
|
|
35
|
+
const external_validation_cjs_namespaceObject = require("./validation.cjs");
|
|
36
|
+
const external_env_cjs_namespaceObject = require("./env.cjs");
|
|
37
|
+
const index_cjs_namespaceObject = require("./discovery/index.cjs");
|
|
38
|
+
const external_logger_cjs_namespaceObject = require("../logger.cjs");
|
|
39
|
+
const loader_cjs_namespaceObject = require("../cli/config/loader.cjs");
|
|
40
|
+
const external_router_cjs_namespaceObject = require("./router.cjs");
|
|
41
|
+
const outputManager_cjs_namespaceObject = require("../cli/core/outputManager.cjs");
|
|
42
|
+
const agentInvoker_cjs_namespaceObject = require("../cli/core/agentInvoker.cjs");
|
|
43
|
+
const sessionManager_cjs_namespaceObject = require("../cli/core/sessionManager.cjs");
|
|
44
|
+
const agents_cjs_namespaceObject = require("./http/agents.cjs");
|
|
45
|
+
const fs_cjs_namespaceObject = require("./http/fs.cjs");
|
|
46
|
+
const providers_cjs_namespaceObject = require("./http/providers.cjs");
|
|
47
|
+
const voice_cjs_namespaceObject = require("./http/voice.cjs");
|
|
48
|
+
const sessions_cjs_namespaceObject = require("./http/sessions.cjs");
|
|
49
|
+
const webhooks_cjs_namespaceObject = require("./http/webhooks.cjs");
|
|
50
|
+
const routines_cjs_namespaceObject = require("./http/routines.cjs");
|
|
51
|
+
const discord_cjs_namespaceObject = require("./adapters/discord.cjs");
|
|
52
|
+
const registry_cjs_namespaceObject = require("./hooks/registry.cjs");
|
|
53
|
+
const external_node_os_namespaceObject = require("node:os");
|
|
54
|
+
const external_node_path_namespaceObject = require("node:path");
|
|
55
|
+
const external_node_fs_namespaceObject = require("node:fs");
|
|
56
|
+
const external_node_url_namespaceObject = require("node:url");
|
|
57
|
+
function _define_property(obj, key, value) {
|
|
58
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
59
|
+
value: value,
|
|
60
|
+
enumerable: true,
|
|
61
|
+
configurable: true,
|
|
62
|
+
writable: true
|
|
63
|
+
});
|
|
64
|
+
else obj[key] = value;
|
|
65
|
+
return obj;
|
|
66
|
+
}
|
|
67
|
+
class GatewayServer {
|
|
68
|
+
async start() {
|
|
69
|
+
if (void 0 === globalThis.Bun) throw new Error("Gateway server requires Bun runtime. Start with `bun ./bin/wingman gateway start`.");
|
|
70
|
+
this.startedAt = Date.now();
|
|
71
|
+
this.internalHooks = new registry_cjs_namespaceObject.InternalHookRegistry(this.getHttpContext(), this.wingmanConfig.hooks);
|
|
72
|
+
await this.internalHooks.load();
|
|
73
|
+
this.server = Bun.serve({
|
|
74
|
+
port: this.config.port,
|
|
75
|
+
hostname: this.config.host,
|
|
76
|
+
fetch: async (req, server)=>{
|
|
77
|
+
const url = new URL(req.url);
|
|
78
|
+
if ("/health" === url.pathname) return this.handleHealthCheck();
|
|
79
|
+
if ("/stats" === url.pathname) return this.handleStats();
|
|
80
|
+
if ("/bridge/send" === url.pathname) return this.handleBridgeSend(req);
|
|
81
|
+
if ("/bridge/poll" === url.pathname) return this.handleBridgePoll(req);
|
|
82
|
+
if ("/ws" === url.pathname) {
|
|
83
|
+
const tailscaleUser = req.headers.get("tailscale-user-login") || req.headers.get("ts-user-login") || void 0;
|
|
84
|
+
const upgraded = server.upgrade(req, {
|
|
85
|
+
data: {
|
|
86
|
+
nodeId: "",
|
|
87
|
+
tailscaleUser
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
if (!upgraded) return new Response("WebSocket upgrade failed", {
|
|
91
|
+
status: 400
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const webhookResponse = await (0, webhooks_cjs_namespaceObject.handleWebhookInvoke)(this.getHttpContext(), this.webhookStore, req, url);
|
|
96
|
+
if (webhookResponse) return webhookResponse;
|
|
97
|
+
if (this.controlUiSamePort) return this.handleUiRequest(req);
|
|
98
|
+
return new Response("Not Found", {
|
|
99
|
+
status: 404
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
websocket: {
|
|
103
|
+
open: (ws)=>this.handleOpen(ws),
|
|
104
|
+
message: (ws, message)=>this.handleMessage(ws, message),
|
|
105
|
+
close: (ws)=>this.handleClose(ws),
|
|
106
|
+
drain: (ws)=>this.handleDrain(ws)
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
this.startPingInterval();
|
|
110
|
+
if (this.controlUiEnabled && !this.controlUiSamePort) {
|
|
111
|
+
if (!this.uiDistDir) this.log("warn", "Control UI is enabled but build assets were not found. Run `bun run webui:build`.");
|
|
112
|
+
this.uiServer = Bun.serve({
|
|
113
|
+
port: this.controlUiPort,
|
|
114
|
+
hostname: this.config.host,
|
|
115
|
+
fetch: (req)=>this.handleUiRequest(req)
|
|
116
|
+
});
|
|
117
|
+
this.log("info", `Control UI started on ${this.config.host}:${this.controlUiPort}`);
|
|
118
|
+
} else if (this.controlUiEnabled) {
|
|
119
|
+
if (!this.uiDistDir) this.log("warn", "Control UI is enabled but build assets were not found. Run `bun run webui:build`.");
|
|
120
|
+
this.log("info", `Control UI available on ${this.config.host}:${this.config.port}`);
|
|
121
|
+
}
|
|
122
|
+
if (this.config.discovery?.enabled) await this.startDiscovery();
|
|
123
|
+
await this.startAdapters();
|
|
124
|
+
this.log("info", `Gateway started on ${this.config.host}:${this.config.port}`);
|
|
125
|
+
this.internalHooks?.emit({
|
|
126
|
+
type: "gateway",
|
|
127
|
+
action: "startup",
|
|
128
|
+
timestamp: new Date()
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async stop() {
|
|
132
|
+
await this.stopAdapters();
|
|
133
|
+
if (this.discoveryService) {
|
|
134
|
+
await this.discoveryService.stopAnnouncing();
|
|
135
|
+
this.discoveryService = null;
|
|
136
|
+
}
|
|
137
|
+
if (this.pingInterval) {
|
|
138
|
+
clearInterval(this.pingInterval);
|
|
139
|
+
this.pingInterval = null;
|
|
140
|
+
}
|
|
141
|
+
if (this.server) {
|
|
142
|
+
this.server.stop();
|
|
143
|
+
this.server = null;
|
|
144
|
+
}
|
|
145
|
+
if (this.uiServer) {
|
|
146
|
+
this.uiServer.stop();
|
|
147
|
+
this.uiServer = null;
|
|
148
|
+
}
|
|
149
|
+
this.log("info", "Gateway stopped");
|
|
150
|
+
}
|
|
151
|
+
async startAdapters() {
|
|
152
|
+
const discordConfig = this.wingmanConfig.gateway?.adapters?.discord;
|
|
153
|
+
if (discordConfig?.enabled) {
|
|
154
|
+
const resolvedHost = "0.0.0.0" === this.config.host || "::" === this.config.host ? "127.0.0.1" : this.config.host;
|
|
155
|
+
const url = discordConfig.gatewayUrl || `ws://${resolvedHost}:${this.config.port}/ws`;
|
|
156
|
+
const token = discordConfig.gatewayToken || (this.config.auth?.mode === "token" ? this.config.authToken : void 0);
|
|
157
|
+
const password = discordConfig.gatewayPassword || (this.config.auth?.mode === "password" ? this.config.auth?.password : void 0);
|
|
158
|
+
this.discordAdapter = new discord_cjs_namespaceObject.DiscordGatewayAdapter({
|
|
159
|
+
enabled: discordConfig.enabled,
|
|
160
|
+
token: discordConfig.token,
|
|
161
|
+
mentionOnly: discordConfig.mentionOnly ?? true,
|
|
162
|
+
allowBots: discordConfig.allowBots ?? false,
|
|
163
|
+
allowedGuilds: discordConfig.allowedGuilds ?? [],
|
|
164
|
+
allowedChannels: discordConfig.allowedChannels ?? [],
|
|
165
|
+
channelSessions: discordConfig.channelSessions ?? {},
|
|
166
|
+
sessionCommand: discordConfig.sessionCommand || "!session",
|
|
167
|
+
gatewayUrl: discordConfig.gatewayUrl,
|
|
168
|
+
gatewayToken: discordConfig.gatewayToken,
|
|
169
|
+
gatewayPassword: discordConfig.gatewayPassword,
|
|
170
|
+
responseChunkSize: discordConfig.responseChunkSize || 1900
|
|
171
|
+
}, {
|
|
172
|
+
url,
|
|
173
|
+
token,
|
|
174
|
+
password
|
|
175
|
+
}, this.logger);
|
|
176
|
+
try {
|
|
177
|
+
await this.discordAdapter.start();
|
|
178
|
+
this.log("info", "Discord adapter started");
|
|
179
|
+
} catch (error) {
|
|
180
|
+
this.log("error", "Failed to start Discord adapter", error);
|
|
181
|
+
this.discordAdapter = null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async stopAdapters() {
|
|
186
|
+
if (this.discordAdapter) {
|
|
187
|
+
await this.discordAdapter.stop();
|
|
188
|
+
this.discordAdapter = null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async startDiscovery() {
|
|
192
|
+
const discovery = this.config.discovery;
|
|
193
|
+
if (!discovery) return;
|
|
194
|
+
const discoveryConfig = {
|
|
195
|
+
name: discovery.name,
|
|
196
|
+
port: this.config.port,
|
|
197
|
+
requireAuth: this.auth.isAuthRequired(),
|
|
198
|
+
capabilities: [
|
|
199
|
+
"broadcast",
|
|
200
|
+
"direct",
|
|
201
|
+
"groups"
|
|
202
|
+
],
|
|
203
|
+
version: "1.0.0",
|
|
204
|
+
transport: "0.0.0.0" === this.config.host ? "ws" : "wss"
|
|
205
|
+
};
|
|
206
|
+
if ("mdns" === discovery.method) {
|
|
207
|
+
this.discoveryService = new index_cjs_namespaceObject.MDNSDiscoveryService();
|
|
208
|
+
await this.discoveryService.announce(discoveryConfig);
|
|
209
|
+
this.log("info", `mDNS discovery started: ${discovery.name}`);
|
|
210
|
+
} else if ("tailscale" === discovery.method) {
|
|
211
|
+
this.discoveryService = new index_cjs_namespaceObject.TailscaleDiscoveryService();
|
|
212
|
+
await this.discoveryService.announce(discoveryConfig);
|
|
213
|
+
this.log("info", `Tailscale discovery started: ${discovery.name}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
handleOpen(ws) {
|
|
217
|
+
this.log("debug", "New WebSocket connection");
|
|
218
|
+
}
|
|
219
|
+
handleMessage(ws, message) {
|
|
220
|
+
try {
|
|
221
|
+
const parsed = JSON.parse(message.toString());
|
|
222
|
+
const validation = (0, external_validation_cjs_namespaceObject.validateGatewayMessage)(parsed);
|
|
223
|
+
if (!validation.success) {
|
|
224
|
+
this.log("warn", "Invalid message format", validation.error);
|
|
225
|
+
this.sendError(ws, "INVALID_MESSAGE", validation.error);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const msg = validation.data;
|
|
229
|
+
const nodeId = ws.data.nodeId;
|
|
230
|
+
if ("connect" === msg.type) return void this.handleConnect(ws, msg);
|
|
231
|
+
if ("req:agent" === msg.type) return void this.handleAgentRequest(ws, msg);
|
|
232
|
+
if (nodeId && "register" !== msg.type && "ping" !== msg.type && "pong" !== msg.type) {
|
|
233
|
+
if (this.nodeManager.isRateLimited(nodeId)) return void this.sendError(ws, "RATE_LIMITED", "Too many messages. Please slow down.");
|
|
234
|
+
this.nodeManager.recordMessage(nodeId);
|
|
235
|
+
}
|
|
236
|
+
this.messagesProcessed++;
|
|
237
|
+
this.log("debug", `Received message: ${msg.type}`, msg);
|
|
238
|
+
switch(msg.type){
|
|
239
|
+
case "register":
|
|
240
|
+
this.handleRegister(ws, msg);
|
|
241
|
+
break;
|
|
242
|
+
case "session_subscribe":
|
|
243
|
+
this.handleSessionSubscribe(ws, msg);
|
|
244
|
+
break;
|
|
245
|
+
case "session_unsubscribe":
|
|
246
|
+
this.handleSessionUnsubscribe(ws, msg);
|
|
247
|
+
break;
|
|
248
|
+
case "unregister":
|
|
249
|
+
this.handleUnregister(ws, msg);
|
|
250
|
+
break;
|
|
251
|
+
case "join_group":
|
|
252
|
+
this.handleJoinGroup(ws, msg);
|
|
253
|
+
break;
|
|
254
|
+
case "leave_group":
|
|
255
|
+
this.handleLeaveGroup(ws, msg);
|
|
256
|
+
break;
|
|
257
|
+
case "broadcast":
|
|
258
|
+
this.handleBroadcast(ws, msg);
|
|
259
|
+
break;
|
|
260
|
+
case "direct":
|
|
261
|
+
this.handleDirect(ws, msg);
|
|
262
|
+
break;
|
|
263
|
+
case "ping":
|
|
264
|
+
this.handlePing(ws, msg);
|
|
265
|
+
break;
|
|
266
|
+
case "pong":
|
|
267
|
+
this.handlePong(ws, msg);
|
|
268
|
+
break;
|
|
269
|
+
default:
|
|
270
|
+
this.sendError(ws, "UNKNOWN_MESSAGE_TYPE", "Unknown message type");
|
|
271
|
+
}
|
|
272
|
+
} catch (error) {
|
|
273
|
+
this.log("error", "Failed to process message", error);
|
|
274
|
+
this.sendError(ws, "INVALID_MESSAGE", "Invalid message format");
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
handleClose(ws) {
|
|
278
|
+
const nodeId = ws.data.nodeId;
|
|
279
|
+
if (nodeId) {
|
|
280
|
+
this.groupManager.removeNodeFromAllGroups(nodeId);
|
|
281
|
+
this.nodeManager.unregisterNode(nodeId);
|
|
282
|
+
this.log("info", `Node disconnected: ${nodeId}`);
|
|
283
|
+
}
|
|
284
|
+
this.connectedClients.delete(ws);
|
|
285
|
+
this.clearSessionSubscriptions(ws);
|
|
286
|
+
}
|
|
287
|
+
handleDrain(ws) {
|
|
288
|
+
this.log("debug", "WebSocket drained");
|
|
289
|
+
}
|
|
290
|
+
handleConnect(ws, msg) {
|
|
291
|
+
if (!msg.id) return void this.sendError(ws, "INVALID_CONNECT", "Missing connect request id");
|
|
292
|
+
if (!msg.client) return void this.sendMessage(ws, {
|
|
293
|
+
type: "res",
|
|
294
|
+
id: msg.id,
|
|
295
|
+
ok: false,
|
|
296
|
+
payload: "missing client info",
|
|
297
|
+
timestamp: Date.now()
|
|
298
|
+
});
|
|
299
|
+
const allowed = this.auth.validate(msg.auth, ws.data.tailscaleUser);
|
|
300
|
+
if (!allowed) {
|
|
301
|
+
this.sendMessage(ws, {
|
|
302
|
+
type: "res",
|
|
303
|
+
id: msg.id,
|
|
304
|
+
ok: false,
|
|
305
|
+
payload: "authentication failed",
|
|
306
|
+
timestamp: Date.now()
|
|
307
|
+
});
|
|
308
|
+
ws.close();
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
ws.data.clientId = msg.client.instanceId;
|
|
312
|
+
ws.data.clientType = msg.client.clientType;
|
|
313
|
+
ws.data.authenticated = true;
|
|
314
|
+
this.connectedClients.add(ws);
|
|
315
|
+
this.sendMessage(ws, {
|
|
316
|
+
type: "res",
|
|
317
|
+
id: msg.id,
|
|
318
|
+
ok: true,
|
|
319
|
+
payload: "gateway-ready",
|
|
320
|
+
timestamp: Date.now()
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
async handleAgentRequest(ws, msg) {
|
|
324
|
+
if (!msg.id) return void this.sendError(ws, "INVALID_REQUEST", "Missing request id");
|
|
325
|
+
if (!ws.data.authenticated) return void this.sendAgentError(ws, msg.id, "Client is not authenticated");
|
|
326
|
+
const payload = msg.payload;
|
|
327
|
+
const content = "string" == typeof payload?.content ? payload.content : "";
|
|
328
|
+
const attachments = Array.isArray(payload?.attachments) ? payload.attachments : [];
|
|
329
|
+
const hasContent = content.trim().length > 0;
|
|
330
|
+
const hasAttachments = attachments.length > 0;
|
|
331
|
+
if (!hasContent && !hasAttachments) return void this.sendAgentError(ws, msg.id, "Missing agent content");
|
|
332
|
+
const agentId = this.router.selectAgent(payload.agentId, payload.routing);
|
|
333
|
+
if (!agentId) return void this.sendAgentError(ws, msg.id, "No agent matched the request");
|
|
334
|
+
const sessionKey = payload.sessionKey || this.router.buildSessionKey(agentId, payload.routing);
|
|
335
|
+
const sessionManager = await this.getSessionManager(agentId);
|
|
336
|
+
const existingSession = sessionManager.getSession(sessionKey);
|
|
337
|
+
const session = existingSession || sessionManager.getOrCreateSession(sessionKey, agentId);
|
|
338
|
+
const workdir = session.metadata?.workdir ?? null;
|
|
339
|
+
const defaultOutputDir = this.resolveDefaultOutputDir(agentId);
|
|
340
|
+
const preview = hasContent ? content.trim() : buildAttachmentPreview(attachments);
|
|
341
|
+
sessionManager.updateSession(session.id, {
|
|
342
|
+
lastMessagePreview: preview.substring(0, 200)
|
|
343
|
+
});
|
|
344
|
+
if (!existingSession) this.internalHooks?.emit({
|
|
345
|
+
type: "session",
|
|
346
|
+
action: "start",
|
|
347
|
+
timestamp: new Date(),
|
|
348
|
+
agentId,
|
|
349
|
+
sessionKey,
|
|
350
|
+
routing: payload.routing
|
|
351
|
+
});
|
|
352
|
+
this.internalHooks?.emit({
|
|
353
|
+
type: "message",
|
|
354
|
+
action: "received",
|
|
355
|
+
timestamp: new Date(),
|
|
356
|
+
agentId,
|
|
357
|
+
sessionKey,
|
|
358
|
+
routing: payload.routing,
|
|
359
|
+
payload: {
|
|
360
|
+
content,
|
|
361
|
+
attachments
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
const sessionMessage = {
|
|
365
|
+
type: "event:agent",
|
|
366
|
+
id: msg.id,
|
|
367
|
+
payload: this.attachSessionContext({
|
|
368
|
+
type: "session-message",
|
|
369
|
+
role: "user",
|
|
370
|
+
content,
|
|
371
|
+
attachments,
|
|
372
|
+
routing: payload.routing
|
|
373
|
+
}, sessionKey, agentId),
|
|
374
|
+
timestamp: Date.now()
|
|
375
|
+
};
|
|
376
|
+
this.broadcastSessionEvent(sessionKey, sessionMessage, ws);
|
|
377
|
+
this.broadcastToClients(sessionMessage, {
|
|
378
|
+
exclude: ws,
|
|
379
|
+
clientType: "webui",
|
|
380
|
+
skipSessionId: sessionKey
|
|
381
|
+
});
|
|
382
|
+
const outputManager = new outputManager_cjs_namespaceObject.OutputManager("interactive");
|
|
383
|
+
const outputHandler = (event)=>{
|
|
384
|
+
const payloadWithSession = this.attachSessionContext(event, sessionKey, agentId);
|
|
385
|
+
const baseMessage = {
|
|
386
|
+
type: "event:agent",
|
|
387
|
+
id: msg.id,
|
|
388
|
+
payload: payloadWithSession,
|
|
389
|
+
timestamp: Date.now()
|
|
390
|
+
};
|
|
391
|
+
this.sendMessage(ws, {
|
|
392
|
+
...baseMessage,
|
|
393
|
+
clientId: ws.data.clientId
|
|
394
|
+
});
|
|
395
|
+
this.broadcastSessionEvent(sessionKey, baseMessage, ws);
|
|
396
|
+
};
|
|
397
|
+
outputManager.on("output-event", outputHandler);
|
|
398
|
+
const workspace = this.resolveAgentWorkspace(agentId);
|
|
399
|
+
const invoker = new agentInvoker_cjs_namespaceObject.AgentInvoker({
|
|
400
|
+
workspace,
|
|
401
|
+
configDir: this.configDir,
|
|
402
|
+
outputManager,
|
|
403
|
+
logger: this.logger,
|
|
404
|
+
sessionManager,
|
|
405
|
+
workdir,
|
|
406
|
+
defaultOutputDir
|
|
407
|
+
});
|
|
408
|
+
try {
|
|
409
|
+
await invoker.invokeAgent(agentId, content, sessionKey, attachments);
|
|
410
|
+
const updated = sessionManager.getSession(sessionKey);
|
|
411
|
+
if (updated) sessionManager.updateSession(sessionKey, {
|
|
412
|
+
messageCount: updated.messageCount + 1
|
|
413
|
+
});
|
|
414
|
+
} catch (error) {
|
|
415
|
+
this.logger.error("Agent invocation failed", error);
|
|
416
|
+
} finally{
|
|
417
|
+
outputManager.off("output-event", outputHandler);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
handleRegister(ws, msg) {
|
|
421
|
+
const payload = msg.payload;
|
|
422
|
+
if (!this.auth.validate({
|
|
423
|
+
token: payload.token
|
|
424
|
+
}, ws.data.tailscaleUser)) {
|
|
425
|
+
this.sendError(ws, "AUTH_FAILED", "Authentication failed");
|
|
426
|
+
ws.close();
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const node = this.nodeManager.registerNode(ws, payload.name, payload.capabilities, payload.sessionId, payload.agentName);
|
|
430
|
+
if (!node) {
|
|
431
|
+
this.sendError(ws, "MAX_NODES_REACHED", "Maximum nodes reached");
|
|
432
|
+
ws.close();
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
this.sendMessage(ws, {
|
|
436
|
+
type: "ack",
|
|
437
|
+
nodeId: node.id,
|
|
438
|
+
payload: {
|
|
439
|
+
nodeId: node.id,
|
|
440
|
+
name: node.name,
|
|
441
|
+
sessionId: node.sessionId,
|
|
442
|
+
agentName: node.agentName
|
|
443
|
+
},
|
|
444
|
+
timestamp: Date.now()
|
|
445
|
+
});
|
|
446
|
+
const sessionInfo = node.sessionId ? ` (session: ${node.sessionId})` : "";
|
|
447
|
+
this.log("info", `Node registered: ${node.id} (${node.name})${sessionInfo}`);
|
|
448
|
+
}
|
|
449
|
+
handleSessionSubscribe(ws, msg) {
|
|
450
|
+
if (!ws.data.authenticated) return void this.sendError(ws, "AUTH_REQUIRED", "Client is not authenticated");
|
|
451
|
+
const payload = msg.payload;
|
|
452
|
+
const sessionId = "string" == typeof payload?.sessionId ? payload.sessionId.trim() : "";
|
|
453
|
+
if (!sessionId) return void this.sendError(ws, "INVALID_REQUEST", "Missing sessionId");
|
|
454
|
+
this.addSessionSubscription(ws, sessionId);
|
|
455
|
+
this.sendMessage(ws, {
|
|
456
|
+
type: "ack",
|
|
457
|
+
payload: {
|
|
458
|
+
action: "session_subscribe",
|
|
459
|
+
sessionId
|
|
460
|
+
},
|
|
461
|
+
timestamp: Date.now()
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
handleSessionUnsubscribe(ws, msg) {
|
|
465
|
+
if (!ws.data.authenticated) return void this.sendError(ws, "AUTH_REQUIRED", "Client is not authenticated");
|
|
466
|
+
const payload = msg.payload;
|
|
467
|
+
const sessionId = "string" == typeof payload?.sessionId ? payload.sessionId.trim() : "";
|
|
468
|
+
if (!sessionId) return void this.sendError(ws, "INVALID_REQUEST", "Missing sessionId");
|
|
469
|
+
this.removeSessionSubscription(ws, sessionId);
|
|
470
|
+
this.sendMessage(ws, {
|
|
471
|
+
type: "ack",
|
|
472
|
+
payload: {
|
|
473
|
+
action: "session_unsubscribe",
|
|
474
|
+
sessionId
|
|
475
|
+
},
|
|
476
|
+
timestamp: Date.now()
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
handleUnregister(ws, msg) {
|
|
480
|
+
const nodeId = ws.data.nodeId;
|
|
481
|
+
if (nodeId) {
|
|
482
|
+
this.groupManager.removeNodeFromAllGroups(nodeId);
|
|
483
|
+
this.nodeManager.unregisterNode(nodeId);
|
|
484
|
+
this.log("info", `Node unregistered: ${nodeId}`);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
handleJoinGroup(ws, msg) {
|
|
488
|
+
const nodeId = ws.data.nodeId;
|
|
489
|
+
if (!nodeId) return void this.sendError(ws, "NOT_REGISTERED", "Node not registered");
|
|
490
|
+
const payload = msg.payload;
|
|
491
|
+
let group;
|
|
492
|
+
if (payload.groupId) group = this.groupManager.getGroup(payload.groupId);
|
|
493
|
+
else if (payload.groupName) group = payload.createIfNotExists ? this.groupManager.getOrCreateGroup(payload.groupName, nodeId, payload.description) : this.groupManager.getGroupByName(payload.groupName);
|
|
494
|
+
if (!group) return void this.sendError(ws, "GROUP_NOT_FOUND", "Group not found");
|
|
495
|
+
this.groupManager.addNodeToGroup(group.id, nodeId);
|
|
496
|
+
this.nodeManager.addNodeToGroup(nodeId, group.id);
|
|
497
|
+
this.sendMessage(ws, {
|
|
498
|
+
type: "ack",
|
|
499
|
+
nodeId,
|
|
500
|
+
groupId: group.id,
|
|
501
|
+
payload: {
|
|
502
|
+
groupId: group.id,
|
|
503
|
+
groupName: group.name
|
|
504
|
+
},
|
|
505
|
+
timestamp: Date.now()
|
|
506
|
+
});
|
|
507
|
+
this.log("info", `Node ${nodeId} joined group ${group.name}`);
|
|
508
|
+
}
|
|
509
|
+
handleLeaveGroup(ws, msg) {
|
|
510
|
+
const nodeId = ws.data.nodeId;
|
|
511
|
+
if (!nodeId || !msg.groupId) return void this.sendError(ws, "INVALID_REQUEST", "Invalid leave group request");
|
|
512
|
+
this.groupManager.removeNodeFromGroup(msg.groupId, nodeId);
|
|
513
|
+
this.nodeManager.removeNodeFromGroup(nodeId, msg.groupId);
|
|
514
|
+
this.sendMessage(ws, {
|
|
515
|
+
type: "ack",
|
|
516
|
+
nodeId,
|
|
517
|
+
groupId: msg.groupId,
|
|
518
|
+
timestamp: Date.now()
|
|
519
|
+
});
|
|
520
|
+
this.log("info", `Node ${nodeId} left group ${msg.groupId}`);
|
|
521
|
+
}
|
|
522
|
+
handleBroadcast(ws, msg) {
|
|
523
|
+
const nodeId = ws.data.nodeId;
|
|
524
|
+
if (!nodeId) return void this.sendError(ws, "NOT_REGISTERED", "Node not registered");
|
|
525
|
+
const payload = msg.payload;
|
|
526
|
+
const members = this.groupManager.getGroupMembers(payload.groupId);
|
|
527
|
+
const recipients = members.filter((id)=>id !== nodeId);
|
|
528
|
+
const broadcastMsg = {
|
|
529
|
+
type: "broadcast",
|
|
530
|
+
nodeId,
|
|
531
|
+
groupId: payload.groupId,
|
|
532
|
+
payload: payload.message,
|
|
533
|
+
timestamp: Date.now()
|
|
534
|
+
};
|
|
535
|
+
const sent = this.nodeManager.broadcastToNodes(recipients, broadcastMsg);
|
|
536
|
+
this.log("debug", `Broadcast to ${sent}/${recipients.length} nodes in group ${payload.groupId}`);
|
|
537
|
+
}
|
|
538
|
+
handleDirect(ws, msg) {
|
|
539
|
+
const nodeId = ws.data.nodeId;
|
|
540
|
+
if (!nodeId) return void this.sendError(ws, "NOT_REGISTERED", "Node not registered");
|
|
541
|
+
const payload = msg.payload;
|
|
542
|
+
const directMsg = {
|
|
543
|
+
type: "direct",
|
|
544
|
+
nodeId,
|
|
545
|
+
targetNodeId: payload.targetNodeId,
|
|
546
|
+
payload: payload.message,
|
|
547
|
+
timestamp: Date.now()
|
|
548
|
+
};
|
|
549
|
+
const sent = this.nodeManager.sendToNode(payload.targetNodeId, directMsg);
|
|
550
|
+
if (!sent) this.sendError(ws, "NODE_NOT_FOUND", "Target node not found");
|
|
551
|
+
}
|
|
552
|
+
handlePing(ws, msg) {
|
|
553
|
+
const nodeId = ws.data.nodeId;
|
|
554
|
+
if (nodeId) this.nodeManager.updatePing(nodeId);
|
|
555
|
+
this.sendMessage(ws, {
|
|
556
|
+
type: "pong",
|
|
557
|
+
timestamp: Date.now()
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
handlePong(ws, msg) {
|
|
561
|
+
const nodeId = ws.data.nodeId;
|
|
562
|
+
if (nodeId) this.nodeManager.updatePing(nodeId);
|
|
563
|
+
}
|
|
564
|
+
sendMessage(ws, message) {
|
|
565
|
+
try {
|
|
566
|
+
ws.send(JSON.stringify(message));
|
|
567
|
+
} catch (error) {
|
|
568
|
+
this.log("error", "Failed to send message", error);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
sendError(ws, code, message) {
|
|
572
|
+
const errorPayload = {
|
|
573
|
+
code,
|
|
574
|
+
message
|
|
575
|
+
};
|
|
576
|
+
this.sendMessage(ws, {
|
|
577
|
+
type: "error",
|
|
578
|
+
payload: errorPayload,
|
|
579
|
+
timestamp: Date.now()
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
sendAgentError(ws, requestId, message) {
|
|
583
|
+
this.sendMessage(ws, {
|
|
584
|
+
type: "event:agent",
|
|
585
|
+
id: requestId,
|
|
586
|
+
payload: {
|
|
587
|
+
type: "agent-error",
|
|
588
|
+
error: message,
|
|
589
|
+
timestamp: new Date().toISOString()
|
|
590
|
+
},
|
|
591
|
+
timestamp: Date.now()
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
attachSessionContext(event, sessionId, agentId) {
|
|
595
|
+
if (event && "object" == typeof event && !Array.isArray(event)) return {
|
|
596
|
+
...event,
|
|
597
|
+
sessionId,
|
|
598
|
+
agentId
|
|
599
|
+
};
|
|
600
|
+
return {
|
|
601
|
+
type: "agent-event",
|
|
602
|
+
data: event,
|
|
603
|
+
sessionId,
|
|
604
|
+
agentId
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
broadcastSessionEvent(sessionId, message, exclude) {
|
|
608
|
+
const subscribers = this.sessionSubscriptions.get(sessionId);
|
|
609
|
+
if (!subscribers || 0 === subscribers.size) return 0;
|
|
610
|
+
let sent = 0;
|
|
611
|
+
for (const ws of subscribers)if (!exclude || ws !== exclude) {
|
|
612
|
+
this.sendMessage(ws, message);
|
|
613
|
+
sent++;
|
|
614
|
+
}
|
|
615
|
+
return sent;
|
|
616
|
+
}
|
|
617
|
+
broadcastToClients(message, options) {
|
|
618
|
+
let sent = 0;
|
|
619
|
+
for (const ws of this.connectedClients)if (!options?.exclude || ws !== options.exclude) {
|
|
620
|
+
if (!options?.clientType || ws.data.clientType === options.clientType) {
|
|
621
|
+
if (options?.skipSessionId) {
|
|
622
|
+
const subscribers = this.sessionSubscriptions.get(options.skipSessionId);
|
|
623
|
+
if (subscribers?.has(ws)) continue;
|
|
624
|
+
}
|
|
625
|
+
this.sendMessage(ws, message);
|
|
626
|
+
sent++;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return sent;
|
|
630
|
+
}
|
|
631
|
+
addSessionSubscription(ws, sessionId) {
|
|
632
|
+
let subscribers = this.sessionSubscriptions.get(sessionId);
|
|
633
|
+
if (!subscribers) {
|
|
634
|
+
subscribers = new Set();
|
|
635
|
+
this.sessionSubscriptions.set(sessionId, subscribers);
|
|
636
|
+
}
|
|
637
|
+
subscribers.add(ws);
|
|
638
|
+
let socketSessions = this.socketSubscriptions.get(ws);
|
|
639
|
+
if (!socketSessions) {
|
|
640
|
+
socketSessions = new Set();
|
|
641
|
+
this.socketSubscriptions.set(ws, socketSessions);
|
|
642
|
+
}
|
|
643
|
+
socketSessions.add(sessionId);
|
|
644
|
+
}
|
|
645
|
+
removeSessionSubscription(ws, sessionId) {
|
|
646
|
+
const subscribers = this.sessionSubscriptions.get(sessionId);
|
|
647
|
+
if (subscribers) {
|
|
648
|
+
subscribers.delete(ws);
|
|
649
|
+
if (0 === subscribers.size) this.sessionSubscriptions.delete(sessionId);
|
|
650
|
+
}
|
|
651
|
+
const socketSessions = this.socketSubscriptions.get(ws);
|
|
652
|
+
if (socketSessions) {
|
|
653
|
+
socketSessions.delete(sessionId);
|
|
654
|
+
if (0 === socketSessions.size) this.socketSubscriptions.delete(ws);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
clearSessionSubscriptions(ws) {
|
|
658
|
+
const sessions = this.socketSubscriptions.get(ws);
|
|
659
|
+
if (!sessions) return;
|
|
660
|
+
for (const sessionId of sessions){
|
|
661
|
+
const subscribers = this.sessionSubscriptions.get(sessionId);
|
|
662
|
+
if (subscribers) {
|
|
663
|
+
subscribers.delete(ws);
|
|
664
|
+
if (0 === subscribers.size) this.sessionSubscriptions.delete(sessionId);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
this.socketSubscriptions.delete(ws);
|
|
668
|
+
}
|
|
669
|
+
resolveStateDir() {
|
|
670
|
+
const configured = this.config.stateDir || this.wingmanConfig.gateway?.stateDir;
|
|
671
|
+
const fallback = (0, external_node_path_namespaceObject.join)((0, external_node_os_namespaceObject.homedir)(), ".wingman");
|
|
672
|
+
const raw = configured || fallback;
|
|
673
|
+
if (raw.startsWith("~/")) return (0, external_node_path_namespaceObject.join)((0, external_node_os_namespaceObject.homedir)(), raw.slice(2));
|
|
674
|
+
if ((0, external_node_path_namespaceObject.isAbsolute)(raw)) return raw;
|
|
675
|
+
return (0, external_node_path_namespaceObject.join)(this.workspace, raw);
|
|
676
|
+
}
|
|
677
|
+
resolveAgentWorkspace(agentId) {
|
|
678
|
+
const agents = this.wingmanConfig.agents?.list || [];
|
|
679
|
+
const match = agents.find((agent)=>agent.id === agentId);
|
|
680
|
+
return match?.workspace || this.workspace;
|
|
681
|
+
}
|
|
682
|
+
resolveConfigDirPath() {
|
|
683
|
+
return (0, external_node_path_namespaceObject.isAbsolute)(this.configDir) ? this.configDir : (0, external_node_path_namespaceObject.join)(this.workspace, this.configDir);
|
|
684
|
+
}
|
|
685
|
+
getHttpContext() {
|
|
686
|
+
return {
|
|
687
|
+
workspace: this.workspace,
|
|
688
|
+
configDir: this.configDir,
|
|
689
|
+
getWingmanConfig: ()=>this.wingmanConfig,
|
|
690
|
+
setWingmanConfig: (config)=>{
|
|
691
|
+
this.wingmanConfig = config;
|
|
692
|
+
},
|
|
693
|
+
persistWingmanConfig: ()=>this.persistWingmanConfig(),
|
|
694
|
+
router: this.router,
|
|
695
|
+
setRouter: (router)=>{
|
|
696
|
+
this.router = router;
|
|
697
|
+
},
|
|
698
|
+
auth: this.auth,
|
|
699
|
+
logger: this.logger,
|
|
700
|
+
getSessionManager: (agentId)=>this.getSessionManager(agentId),
|
|
701
|
+
resolveConfigDirPath: ()=>this.resolveConfigDirPath(),
|
|
702
|
+
resolveOutputRoot: ()=>this.resolveOutputRoot(),
|
|
703
|
+
resolveDefaultOutputDir: (agentId)=>this.resolveDefaultOutputDir(agentId),
|
|
704
|
+
resolveAgentWorkspace: (agentId)=>this.resolveAgentWorkspace(agentId),
|
|
705
|
+
resolveFsRoots: ()=>this.resolveFsRoots(),
|
|
706
|
+
resolveFsPath: (path)=>this.resolveFsPath(path),
|
|
707
|
+
isPathWithinRoots: (path, roots)=>this.isPathWithinRoots(path, roots),
|
|
708
|
+
getBuiltInTools: ()=>this.getBuiltInTools()
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
persistWingmanConfig() {
|
|
712
|
+
const configDir = this.resolveConfigDirPath();
|
|
713
|
+
(0, external_node_fs_namespaceObject.mkdirSync)(configDir, {
|
|
714
|
+
recursive: true
|
|
715
|
+
});
|
|
716
|
+
const configPath = (0, external_node_path_namespaceObject.join)(configDir, "wingman.config.json");
|
|
717
|
+
(0, external_node_fs_namespaceObject.writeFileSync)(configPath, JSON.stringify(this.wingmanConfig, null, 2));
|
|
718
|
+
}
|
|
719
|
+
getBuiltInTools() {
|
|
720
|
+
return [
|
|
721
|
+
"ls",
|
|
722
|
+
"read_file",
|
|
723
|
+
"write_file",
|
|
724
|
+
"edit_file",
|
|
725
|
+
"glob",
|
|
726
|
+
"grep"
|
|
727
|
+
];
|
|
728
|
+
}
|
|
729
|
+
resolveOutputRoot() {
|
|
730
|
+
const root = (0, external_node_path_namespaceObject.join)(this.resolveStateDir(), "outputs");
|
|
731
|
+
(0, external_node_fs_namespaceObject.mkdirSync)(root, {
|
|
732
|
+
recursive: true
|
|
733
|
+
});
|
|
734
|
+
return root;
|
|
735
|
+
}
|
|
736
|
+
resolveDefaultOutputDir(agentId) {
|
|
737
|
+
const root = this.resolveOutputRoot();
|
|
738
|
+
const dir = (0, external_node_path_namespaceObject.join)(root, agentId);
|
|
739
|
+
(0, external_node_fs_namespaceObject.mkdirSync)(dir, {
|
|
740
|
+
recursive: true
|
|
741
|
+
});
|
|
742
|
+
return dir;
|
|
743
|
+
}
|
|
744
|
+
resolveFsRoots() {
|
|
745
|
+
const configured = this.wingmanConfig.gateway?.fsRoots || [];
|
|
746
|
+
const candidates = configured.length > 0 ? configured : [
|
|
747
|
+
this.resolveOutputRoot()
|
|
748
|
+
];
|
|
749
|
+
const resolved = candidates.map((entry)=>this.resolveFsPath(entry)).filter((entry)=>{
|
|
750
|
+
try {
|
|
751
|
+
return (0, external_node_fs_namespaceObject.existsSync)(entry) && (0, external_node_fs_namespaceObject.statSync)(entry).isDirectory();
|
|
752
|
+
} catch {
|
|
753
|
+
return false;
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
return Array.from(new Set(resolved));
|
|
757
|
+
}
|
|
758
|
+
resolveFsPath(raw) {
|
|
759
|
+
if ("~" === raw) return (0, external_node_path_namespaceObject.normalize)((0, external_node_os_namespaceObject.homedir)());
|
|
760
|
+
if (raw.startsWith("~/")) return (0, external_node_path_namespaceObject.normalize)((0, external_node_path_namespaceObject.join)((0, external_node_os_namespaceObject.homedir)(), raw.slice(2)));
|
|
761
|
+
if ((0, external_node_path_namespaceObject.isAbsolute)(raw)) return (0, external_node_path_namespaceObject.normalize)(raw);
|
|
762
|
+
return (0, external_node_path_namespaceObject.normalize)((0, external_node_path_namespaceObject.join)(this.workspace, raw));
|
|
763
|
+
}
|
|
764
|
+
isPathWithinRoots(pathname, roots) {
|
|
765
|
+
const normalized = (0, external_node_path_namespaceObject.normalize)(pathname);
|
|
766
|
+
return roots.some((root)=>{
|
|
767
|
+
const normalizedRoot = (0, external_node_path_namespaceObject.normalize)(root);
|
|
768
|
+
return normalized === normalizedRoot || normalized.startsWith(normalizedRoot + external_node_path_namespaceObject.sep);
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
resolveControlUiDir() {
|
|
772
|
+
const moduleDir = (0, external_node_path_namespaceObject.dirname)((0, external_node_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__));
|
|
773
|
+
const candidates = [
|
|
774
|
+
(0, external_node_path_namespaceObject.join)(this.workspace, "dist", "webui"),
|
|
775
|
+
(0, external_node_path_namespaceObject.join)(moduleDir, "..", "webui"),
|
|
776
|
+
(0, external_node_path_namespaceObject.join)(moduleDir, "..", "..", "dist", "webui")
|
|
777
|
+
];
|
|
778
|
+
for (const candidate of candidates)try {
|
|
779
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(candidate) && (0, external_node_fs_namespaceObject.statSync)(candidate).isDirectory() && (0, external_node_fs_namespaceObject.existsSync)((0, external_node_path_namespaceObject.join)(candidate, "index.html"))) return candidate;
|
|
780
|
+
} catch {
|
|
781
|
+
continue;
|
|
782
|
+
}
|
|
783
|
+
return null;
|
|
784
|
+
}
|
|
785
|
+
async getSessionManager(agentId) {
|
|
786
|
+
const existing = this.sessionManagers.get(agentId);
|
|
787
|
+
if (existing) return existing;
|
|
788
|
+
const stateDir = this.resolveStateDir();
|
|
789
|
+
const sessionsDir = (0, external_node_path_namespaceObject.join)(stateDir, "agents", agentId, "sessions");
|
|
790
|
+
(0, external_node_fs_namespaceObject.mkdirSync)(sessionsDir, {
|
|
791
|
+
recursive: true
|
|
792
|
+
});
|
|
793
|
+
const dbPath = (0, external_node_path_namespaceObject.join)(sessionsDir, "wingman.db");
|
|
794
|
+
const manager = new sessionManager_cjs_namespaceObject.SessionManager(dbPath);
|
|
795
|
+
await manager.initialize();
|
|
796
|
+
this.sessionManagers.set(agentId, manager);
|
|
797
|
+
return manager;
|
|
798
|
+
}
|
|
799
|
+
handleHealthCheck() {
|
|
800
|
+
const stats = this.getStats();
|
|
801
|
+
const health = {
|
|
802
|
+
status: "healthy",
|
|
803
|
+
version: "1.0.0",
|
|
804
|
+
stats,
|
|
805
|
+
timestamp: Date.now()
|
|
806
|
+
};
|
|
807
|
+
return new Response(JSON.stringify(health, null, 2), {
|
|
808
|
+
headers: {
|
|
809
|
+
"Content-Type": "application/json"
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
handleStats() {
|
|
814
|
+
const stats = {
|
|
815
|
+
gateway: this.getStats(),
|
|
816
|
+
nodes: this.nodeManager.getStats(),
|
|
817
|
+
groups: this.groupManager.getStats()
|
|
818
|
+
};
|
|
819
|
+
return new Response(JSON.stringify(stats, null, 2), {
|
|
820
|
+
headers: {
|
|
821
|
+
"Content-Type": "application/json"
|
|
822
|
+
}
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
getStats() {
|
|
826
|
+
const nodeStats = this.nodeManager.getStats();
|
|
827
|
+
return {
|
|
828
|
+
uptime: Date.now() - this.startedAt,
|
|
829
|
+
totalNodes: nodeStats.totalNodes,
|
|
830
|
+
totalGroups: this.groupManager.getStats().totalGroups,
|
|
831
|
+
messagesProcessed: this.messagesProcessed,
|
|
832
|
+
startedAt: this.startedAt,
|
|
833
|
+
activeSessions: nodeStats.activeSessions,
|
|
834
|
+
sessionNodes: nodeStats.sessionNodes
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
startPingInterval() {
|
|
838
|
+
if (this.pingInterval) clearInterval(this.pingInterval);
|
|
839
|
+
this.pingInterval = setInterval(()=>{
|
|
840
|
+
const nodes = this.nodeManager.getAllNodes();
|
|
841
|
+
for (const node of nodes)this.sendMessage(node.ws, {
|
|
842
|
+
type: "ping",
|
|
843
|
+
timestamp: Date.now()
|
|
844
|
+
});
|
|
845
|
+
const removed = this.nodeManager.removeStaleNodes(this.config.pingTimeout);
|
|
846
|
+
if (removed > 0) this.log("info", `Removed ${removed} stale nodes`);
|
|
847
|
+
}, this.config.pingInterval);
|
|
848
|
+
}
|
|
849
|
+
log(level, message, data) {
|
|
850
|
+
if ("silent" === level) return;
|
|
851
|
+
const args = void 0 === data ? [] : [
|
|
852
|
+
data
|
|
853
|
+
];
|
|
854
|
+
switch(level){
|
|
855
|
+
case "debug":
|
|
856
|
+
this.logger.debug(message, ...args);
|
|
857
|
+
break;
|
|
858
|
+
case "info":
|
|
859
|
+
this.logger.info(message, ...args);
|
|
860
|
+
break;
|
|
861
|
+
case "warn":
|
|
862
|
+
this.logger.warn(message, ...args);
|
|
863
|
+
break;
|
|
864
|
+
case "error":
|
|
865
|
+
this.logger.error(message, ...args);
|
|
866
|
+
break;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
async handleUiRequest(req) {
|
|
870
|
+
const url = new URL(req.url);
|
|
871
|
+
const ctx = this.getHttpContext();
|
|
872
|
+
const webhookResponse = await (0, webhooks_cjs_namespaceObject.handleWebhookInvoke)(ctx, this.webhookStore, req, url);
|
|
873
|
+
if (webhookResponse) return webhookResponse;
|
|
874
|
+
if (url.pathname.startsWith("/api/")) {
|
|
875
|
+
if ("/api/config" === url.pathname) {
|
|
876
|
+
const agents = this.wingmanConfig.agents?.list?.map((agent)=>({
|
|
877
|
+
id: agent.id,
|
|
878
|
+
name: agent.name,
|
|
879
|
+
default: agent.default
|
|
880
|
+
})) || [];
|
|
881
|
+
const defaultAgentId = this.router.selectAgent();
|
|
882
|
+
return new Response(JSON.stringify({
|
|
883
|
+
gatewayHost: this.config.host,
|
|
884
|
+
gatewayPort: this.config.port,
|
|
885
|
+
requireAuth: this.auth.isAuthRequired(),
|
|
886
|
+
defaultAgentId,
|
|
887
|
+
outputRoot: this.resolveOutputRoot(),
|
|
888
|
+
voice: this.wingmanConfig.voice,
|
|
889
|
+
agents
|
|
890
|
+
}, null, 2), {
|
|
891
|
+
headers: {
|
|
892
|
+
"Content-Type": "application/json"
|
|
893
|
+
}
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
const apiResponse = await (0, webhooks_cjs_namespaceObject.handleWebhooksApi)(ctx, this.webhookStore, req, url) || await (0, routines_cjs_namespaceObject.handleRoutinesApi)(ctx, this.routineStore, req, url) || await (0, agents_cjs_namespaceObject.handleAgentsApi)(ctx, req, url) || await (0, providers_cjs_namespaceObject.handleProvidersApi)(ctx, req, url) || await (0, voice_cjs_namespaceObject.handleVoiceApi)(ctx, req, url) || await (0, fs_cjs_namespaceObject.handleFsApi)(ctx, req, url) || await (0, sessions_cjs_namespaceObject.handleSessionsApi)(ctx, req, url);
|
|
897
|
+
if (apiResponse) return apiResponse;
|
|
898
|
+
if ("/api/health" === url.pathname) return this.handleHealthCheck();
|
|
899
|
+
if ("/api/stats" === url.pathname) return this.handleStats();
|
|
900
|
+
return new Response("Not Found", {
|
|
901
|
+
status: 404
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
if ("GET" !== req.method) return new Response("Method Not Allowed", {
|
|
905
|
+
status: 405
|
|
906
|
+
});
|
|
907
|
+
if ("/ui" === url.pathname || "/ui/" === url.pathname) return new Response(null, {
|
|
908
|
+
status: 302,
|
|
909
|
+
headers: {
|
|
910
|
+
Location: "/"
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
if (!this.uiDistDir) return new Response("Control UI build not found", {
|
|
914
|
+
status: 404
|
|
915
|
+
});
|
|
916
|
+
const relativePath = "/" === url.pathname || "/index.html" === url.pathname ? "index.html" : url.pathname.replace(/^\/+/, "");
|
|
917
|
+
const candidate = (0, external_node_path_namespaceObject.normalize)((0, external_node_path_namespaceObject.join)(this.uiDistDir, relativePath));
|
|
918
|
+
if (!candidate.startsWith(this.uiDistDir)) return new Response("Invalid path", {
|
|
919
|
+
status: 400
|
|
920
|
+
});
|
|
921
|
+
if (!(0, external_node_fs_namespaceObject.existsSync)(candidate) || !(0, external_node_fs_namespaceObject.statSync)(candidate).isFile()) {
|
|
922
|
+
const isAssetRequest = relativePath.startsWith("assets/") || relativePath.includes(".");
|
|
923
|
+
if (!isAssetRequest) {
|
|
924
|
+
const indexPath = (0, external_node_path_namespaceObject.normalize)((0, external_node_path_namespaceObject.join)(this.uiDistDir, "index.html"));
|
|
925
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(indexPath) && (0, external_node_fs_namespaceObject.statSync)(indexPath).isFile()) return new Response(Bun.file(indexPath), {
|
|
926
|
+
headers: {
|
|
927
|
+
"Cache-Control": "no-store",
|
|
928
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
929
|
+
}
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
return new Response("Not Found", {
|
|
933
|
+
status: 404
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
const file = Bun.file(candidate);
|
|
937
|
+
const headers = {
|
|
938
|
+
"Cache-Control": "no-store"
|
|
939
|
+
};
|
|
940
|
+
if ("index.html" === relativePath) headers["Content-Type"] = "text/html; charset=utf-8";
|
|
941
|
+
return new Response(file, {
|
|
942
|
+
headers
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
getAuth() {
|
|
946
|
+
return this.auth;
|
|
947
|
+
}
|
|
948
|
+
getConfig() {
|
|
949
|
+
return this.config;
|
|
950
|
+
}
|
|
951
|
+
async handleBridgeSend(req) {
|
|
952
|
+
try {
|
|
953
|
+
const message = await req.json();
|
|
954
|
+
const validation = (0, external_validation_cjs_namespaceObject.validateGatewayMessage)(message);
|
|
955
|
+
if (!validation.success) return new Response(JSON.stringify({
|
|
956
|
+
error: validation.error
|
|
957
|
+
}), {
|
|
958
|
+
status: 400,
|
|
959
|
+
headers: {
|
|
960
|
+
"Content-Type": "application/json"
|
|
961
|
+
}
|
|
962
|
+
});
|
|
963
|
+
const validatedMessage = validation.data;
|
|
964
|
+
if ("register" === validatedMessage.type) {
|
|
965
|
+
const payload = validatedMessage.payload;
|
|
966
|
+
const nodeId = this.generateNodeId();
|
|
967
|
+
this.bridgeQueues.set(nodeId, []);
|
|
968
|
+
const response = {
|
|
969
|
+
type: "registered",
|
|
970
|
+
nodeId,
|
|
971
|
+
timestamp: Date.now()
|
|
972
|
+
};
|
|
973
|
+
this.log("info", `HTTP bridge node registered: ${payload.name}`);
|
|
974
|
+
return new Response(JSON.stringify(response), {
|
|
975
|
+
status: 200,
|
|
976
|
+
headers: {
|
|
977
|
+
"Content-Type": "application/json"
|
|
978
|
+
}
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
const nodeId = validatedMessage.nodeId;
|
|
982
|
+
if (!nodeId) return new Response(JSON.stringify({
|
|
983
|
+
error: "nodeId required"
|
|
984
|
+
}), {
|
|
985
|
+
status: 400,
|
|
986
|
+
headers: {
|
|
987
|
+
"Content-Type": "application/json"
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
this.messagesProcessed++;
|
|
991
|
+
return new Response(JSON.stringify({
|
|
992
|
+
success: true
|
|
993
|
+
}), {
|
|
994
|
+
status: 200,
|
|
995
|
+
headers: {
|
|
996
|
+
"Content-Type": "application/json"
|
|
997
|
+
}
|
|
998
|
+
});
|
|
999
|
+
} catch (error) {
|
|
1000
|
+
return new Response(JSON.stringify({
|
|
1001
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1002
|
+
}), {
|
|
1003
|
+
status: 500,
|
|
1004
|
+
headers: {
|
|
1005
|
+
"Content-Type": "application/json"
|
|
1006
|
+
}
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
async handleBridgePoll(req) {
|
|
1011
|
+
try {
|
|
1012
|
+
const nodeId = req.headers.get("X-Node-ID");
|
|
1013
|
+
if (!nodeId) return new Response(JSON.stringify({
|
|
1014
|
+
error: "X-Node-ID header required"
|
|
1015
|
+
}), {
|
|
1016
|
+
status: 400,
|
|
1017
|
+
headers: {
|
|
1018
|
+
"Content-Type": "application/json"
|
|
1019
|
+
}
|
|
1020
|
+
});
|
|
1021
|
+
const queue = this.bridgeQueues.get(nodeId);
|
|
1022
|
+
if (!queue) return new Response(JSON.stringify({
|
|
1023
|
+
error: "Node not registered"
|
|
1024
|
+
}), {
|
|
1025
|
+
status: 404,
|
|
1026
|
+
headers: {
|
|
1027
|
+
"Content-Type": "application/json"
|
|
1028
|
+
}
|
|
1029
|
+
});
|
|
1030
|
+
if (queue.length > 0) {
|
|
1031
|
+
const messages = [
|
|
1032
|
+
...queue
|
|
1033
|
+
];
|
|
1034
|
+
queue.length = 0;
|
|
1035
|
+
return new Response(JSON.stringify(messages), {
|
|
1036
|
+
status: 200,
|
|
1037
|
+
headers: {
|
|
1038
|
+
"Content-Type": "application/json"
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
1042
|
+
const messages = await new Promise((resolve)=>{
|
|
1043
|
+
const timeout = setTimeout(()=>{
|
|
1044
|
+
this.bridgePollWaiters.delete(nodeId);
|
|
1045
|
+
resolve([]);
|
|
1046
|
+
}, 30000);
|
|
1047
|
+
this.bridgePollWaiters.set(nodeId, (msgs)=>{
|
|
1048
|
+
clearTimeout(timeout);
|
|
1049
|
+
resolve(msgs);
|
|
1050
|
+
});
|
|
1051
|
+
});
|
|
1052
|
+
return new Response(JSON.stringify(messages), {
|
|
1053
|
+
status: 200,
|
|
1054
|
+
headers: {
|
|
1055
|
+
"Content-Type": "application/json"
|
|
1056
|
+
}
|
|
1057
|
+
});
|
|
1058
|
+
} catch (error) {
|
|
1059
|
+
return new Response(JSON.stringify({
|
|
1060
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1061
|
+
}), {
|
|
1062
|
+
status: 500,
|
|
1063
|
+
headers: {
|
|
1064
|
+
"Content-Type": "application/json"
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
generateNodeId() {
|
|
1070
|
+
return `node-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
1071
|
+
}
|
|
1072
|
+
constructor(config = {}){
|
|
1073
|
+
_define_property(this, "config", void 0);
|
|
1074
|
+
_define_property(this, "nodeManager", void 0);
|
|
1075
|
+
_define_property(this, "groupManager", void 0);
|
|
1076
|
+
_define_property(this, "auth", void 0);
|
|
1077
|
+
_define_property(this, "server", null);
|
|
1078
|
+
_define_property(this, "startedAt", 0);
|
|
1079
|
+
_define_property(this, "messagesProcessed", 0);
|
|
1080
|
+
_define_property(this, "pingInterval", null);
|
|
1081
|
+
_define_property(this, "discoveryService", null);
|
|
1082
|
+
_define_property(this, "logger", void 0);
|
|
1083
|
+
_define_property(this, "wingmanConfig", void 0);
|
|
1084
|
+
_define_property(this, "router", void 0);
|
|
1085
|
+
_define_property(this, "sessionManagers", new Map());
|
|
1086
|
+
_define_property(this, "workspace", void 0);
|
|
1087
|
+
_define_property(this, "configDir", void 0);
|
|
1088
|
+
_define_property(this, "uiServer", null);
|
|
1089
|
+
_define_property(this, "controlUiEnabled", false);
|
|
1090
|
+
_define_property(this, "controlUiPort", 18790);
|
|
1091
|
+
_define_property(this, "controlUiSamePort", false);
|
|
1092
|
+
_define_property(this, "uiDistDir", null);
|
|
1093
|
+
_define_property(this, "webhookStore", void 0);
|
|
1094
|
+
_define_property(this, "routineStore", void 0);
|
|
1095
|
+
_define_property(this, "internalHooks", null);
|
|
1096
|
+
_define_property(this, "discordAdapter", null);
|
|
1097
|
+
_define_property(this, "sessionSubscriptions", new Map());
|
|
1098
|
+
_define_property(this, "socketSubscriptions", new Map());
|
|
1099
|
+
_define_property(this, "connectedClients", new Set());
|
|
1100
|
+
_define_property(this, "bridgeQueues", new Map());
|
|
1101
|
+
_define_property(this, "bridgePollWaiters", new Map());
|
|
1102
|
+
this.workspace = config.workspace || process.cwd();
|
|
1103
|
+
this.configDir = config.configDir || ".wingman";
|
|
1104
|
+
const configLoader = new loader_cjs_namespaceObject.WingmanConfigLoader(this.configDir, this.workspace);
|
|
1105
|
+
this.wingmanConfig = configLoader.loadConfig();
|
|
1106
|
+
this.router = new external_router_cjs_namespaceObject.GatewayRouter(this.wingmanConfig);
|
|
1107
|
+
this.webhookStore = (0, webhooks_cjs_namespaceObject.createWebhookStore)(()=>this.resolveConfigDirPath());
|
|
1108
|
+
this.routineStore = (0, routines_cjs_namespaceObject.createRoutineStore)(()=>this.resolveConfigDirPath());
|
|
1109
|
+
const gatewayDefaults = this.wingmanConfig.gateway;
|
|
1110
|
+
const envToken = (0, external_env_cjs_namespaceObject.getGatewayTokenFromEnv)();
|
|
1111
|
+
const authFromConfig = config.auth?.mode === "token" ? {
|
|
1112
|
+
...config.auth,
|
|
1113
|
+
token: config.auth.token ?? envToken
|
|
1114
|
+
} : config.auth;
|
|
1115
|
+
const legacyToken = config.authToken ?? envToken;
|
|
1116
|
+
const authConfig = authFromConfig ? authFromConfig : config.requireAuth || config.authToken ? {
|
|
1117
|
+
mode: "token",
|
|
1118
|
+
token: legacyToken
|
|
1119
|
+
} : gatewayDefaults.auth;
|
|
1120
|
+
const resolvedAuthToken = authConfig?.mode === "token" ? authConfig.token ?? legacyToken : void 0;
|
|
1121
|
+
this.config = {
|
|
1122
|
+
port: config.port ?? gatewayDefaults.port ?? 18789,
|
|
1123
|
+
host: config.host || gatewayDefaults.host || "127.0.0.1",
|
|
1124
|
+
authToken: resolvedAuthToken,
|
|
1125
|
+
requireAuth: config.requireAuth ?? false,
|
|
1126
|
+
auth: authConfig,
|
|
1127
|
+
stateDir: config.stateDir || gatewayDefaults.stateDir,
|
|
1128
|
+
workspace: this.workspace,
|
|
1129
|
+
configDir: this.configDir,
|
|
1130
|
+
maxNodes: config.maxNodes || 1000,
|
|
1131
|
+
pingInterval: config.pingInterval || 30000,
|
|
1132
|
+
pingTimeout: config.pingTimeout || 60000,
|
|
1133
|
+
logLevel: config.logLevel || "info",
|
|
1134
|
+
discovery: config.discovery
|
|
1135
|
+
};
|
|
1136
|
+
this.nodeManager = new external_node_cjs_namespaceObject.NodeManager(this.config.maxNodes);
|
|
1137
|
+
this.groupManager = new external_broadcast_cjs_namespaceObject.BroadcastGroupManager();
|
|
1138
|
+
this.logger = (0, external_logger_cjs_namespaceObject.createLogger)(this.config.logLevel);
|
|
1139
|
+
const initialTokens = this.config.authToken ? [
|
|
1140
|
+
this.config.authToken
|
|
1141
|
+
] : [];
|
|
1142
|
+
this.auth = new external_auth_cjs_namespaceObject.GatewayAuth(this.config.auth || {
|
|
1143
|
+
mode: "none"
|
|
1144
|
+
}, initialTokens);
|
|
1145
|
+
const controlUi = this.wingmanConfig.gateway?.controlUi;
|
|
1146
|
+
this.controlUiEnabled = controlUi?.enabled ?? false;
|
|
1147
|
+
this.controlUiPort = controlUi?.port || 18790;
|
|
1148
|
+
this.controlUiSamePort = this.controlUiEnabled && this.controlUiPort === this.config.port;
|
|
1149
|
+
this.uiDistDir = this.controlUiEnabled ? this.resolveControlUiDir() : null;
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
function buildAttachmentPreview(attachments) {
|
|
1153
|
+
if (!attachments || 0 === attachments.length) return "Attachment";
|
|
1154
|
+
let hasAudio = false;
|
|
1155
|
+
let hasImage = false;
|
|
1156
|
+
for (const attachment of attachments)if (isAudioAttachment(attachment)) hasAudio = true;
|
|
1157
|
+
else hasImage = true;
|
|
1158
|
+
const count = attachments.length;
|
|
1159
|
+
if (hasAudio && hasImage) return count > 1 ? "Media attachments" : "Media attachment";
|
|
1160
|
+
if (hasAudio) return count > 1 ? "Audio attachments" : "Audio attachment";
|
|
1161
|
+
return count > 1 ? "Image attachments" : "Image attachment";
|
|
1162
|
+
}
|
|
1163
|
+
function isAudioAttachment(attachment) {
|
|
1164
|
+
if ("audio" === attachment.kind) return true;
|
|
1165
|
+
if (attachment.mimeType?.startsWith("audio/")) return true;
|
|
1166
|
+
if (attachment.dataUrl?.startsWith("data:audio/")) return true;
|
|
1167
|
+
return false;
|
|
1168
|
+
}
|
|
1169
|
+
exports.GatewayServer = __webpack_exports__.GatewayServer;
|
|
1170
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
1171
|
+
"GatewayServer"
|
|
1172
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
1173
|
+
Object.defineProperty(exports, '__esModule', {
|
|
1174
|
+
value: true
|
|
1175
|
+
});
|