agentstudio 0.1.18 → 0.1.21
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/README.md +26 -505
- package/bin/agentstudio.js +305 -0
- package/bin/agentstudio.js.map +1 -0
- package/bin/serviceManager.d.ts +16 -0
- package/bin/serviceManager.d.ts.map +1 -0
- package/bin/serviceManager.js +434 -0
- package/bin/serviceManager.js.map +1 -0
- package/config/index.d.ts +74 -0
- package/config/index.d.ts.map +1 -0
- package/config/index.js +166 -0
- package/config/index.js.map +1 -0
- package/config/paths.d.ts +81 -0
- package/config/paths.d.ts.map +1 -0
- package/config/paths.js +98 -0
- package/config/paths.js.map +1 -0
- package/index.d.ts +4 -0
- package/index.d.ts.map +1 -0
- package/index.js +369 -0
- package/index.js.map +1 -0
- package/jobs/taskTimeoutMonitor.d.ts +25 -0
- package/jobs/taskTimeoutMonitor.d.ts.map +1 -0
- package/jobs/taskTimeoutMonitor.js +94 -0
- package/jobs/taskTimeoutMonitor.js.map +1 -0
- package/middleware/a2aAuth.d.ts +38 -0
- package/middleware/a2aAuth.d.ts.map +1 -0
- package/middleware/a2aAuth.js +134 -0
- package/middleware/a2aAuth.js.map +1 -0
- package/{backend/dist/middleware → middleware}/auth.d.ts +3 -1
- package/middleware/auth.d.ts.map +1 -0
- package/middleware/auth.js +35 -0
- package/middleware/auth.js.map +1 -0
- package/middleware/httpsOnly.d.ts +38 -0
- package/middleware/httpsOnly.d.ts.map +1 -0
- package/middleware/httpsOnly.js +105 -0
- package/middleware/httpsOnly.js.map +1 -0
- package/middleware/rateLimiting.d.ts +37 -0
- package/middleware/rateLimiting.d.ts.map +1 -0
- package/middleware/rateLimiting.js +118 -0
- package/middleware/rateLimiting.js.map +1 -0
- package/package.json +43 -38
- package/public/assets/AgentsPage-Nvg2xu6K.js +10 -0
- package/public/assets/Button-Co56C389.js +1 -0
- package/public/assets/ChatPage-D6sol0ad.js +442 -0
- package/public/assets/CommandForm-Bk7F_HU8.js +7 -0
- package/public/assets/CommandsPage-DZHyOdKd.js +1 -0
- package/public/assets/DashboardPage-29qC7Ev1.js +15 -0
- package/public/assets/FileBrowser-BYweUPH4.js +6 -0
- package/public/assets/FileExplorer-DNYj6Tsx.js +1 -0
- package/public/assets/GeneralSettingsPage-D9Xa7Nd8.js +1 -0
- package/public/assets/LandingPage-CjnT-cvO.js +1 -0
- package/public/assets/LoginPage-DcaGNCXH.js +16 -0
- package/public/assets/McpAdminSettingsPage-DgR3E2Bd.js +7 -0
- package/public/assets/McpPage-CtWf1CoL.js +40 -0
- package/public/assets/MemorySettingsPage-JTry4Ccp.js +1 -0
- package/public/assets/PluginsPage-D-BHjQ3P.js +1 -0
- package/public/assets/ProjectSelector-DSXOjMQC.js +1 -0
- package/public/assets/ProjectsPage-lLUk4-Xa.js +21 -0
- package/public/assets/ScheduledTasksPage-5hPbd9Vs.js +1 -0
- package/public/assets/SettingsLayout-DGJspXLp.js +1 -0
- package/public/assets/SkillsPage-DBw0m7D2.js +18 -0
- package/{backend/dist/frontend/assets/SubagentForm-DXtTTIKg.js → public/assets/SubagentForm-BdUK1U4y.js} +2 -2
- package/public/assets/SubagentsPage-Dnq70IFd.js +1 -0
- package/{backend/dist/frontend/assets/ToastTestPage-DT4wuN5C.js → public/assets/ToastTestPage-BfJQRFIm.js} +1 -1
- package/public/assets/ToolsList-Dl5F2fWk.js +1 -0
- package/public/assets/UnifiedToolSelector-CNbPsiuq.js +1 -0
- package/public/assets/VersionSettingsPage-BfoCcham.js +5 -0
- package/public/assets/_basePickBy-7C_e0Xv1.js +1 -0
- package/public/assets/_baseUniq-eGJNLBzx.js +1 -0
- package/public/assets/agents-ChrA1R0y.js +1 -0
- package/public/assets/arc-CuA752eE.js +1 -0
- package/public/assets/architectureDiagram-VXUJARFQ-BnPYh1OW.js +36 -0
- package/public/assets/blockDiagram-VD42YOAC-72nsMt_i.js +122 -0
- package/public/assets/c4Diagram-YG6GDRKO-BNJSAXcg.js +10 -0
- package/public/assets/channel-CIunGC5m.js +1 -0
- package/public/assets/chunk-4BX2VUAB-RPxkCWhH.js +1 -0
- package/public/assets/chunk-55IACEB6-3ePDt0kp.js +1 -0
- package/public/assets/chunk-B4BG7PRW-CBg_BBfl.js +165 -0
- package/public/assets/chunk-DI55MBZ5-DIh69TUJ.js +220 -0
- package/public/assets/chunk-FMBD7UC4-BbjwhyTe.js +15 -0
- package/public/assets/chunk-QN33PNHL-BpH-o_YR.js +1 -0
- package/public/assets/chunk-QZHKN3VN-DYB7rh5Q.js +1 -0
- package/public/assets/chunk-TZMSLE5B-DPCYEVb3.js +1 -0
- package/public/assets/classDiagram-2ON5EDUG-aUQHFsTA.js +1 -0
- package/public/assets/classDiagram-v2-WZHVMYZB-aUQHFsTA.js +1 -0
- package/public/assets/clone-Ckf7tA1V.js +1 -0
- package/public/assets/cose-bilkent-S5V4N54A-CnpfmL-Y.js +1 -0
- package/public/assets/cytoscape.esm-DtBltrT8.js +331 -0
- package/public/assets/dagre-6UL2VRFP-DR9x77Xf.js +4 -0
- package/{backend/dist/frontend/assets/data-structures-DLJedtzx.js → public/assets/data-structures-C0h9Oap1.js} +1 -1
- package/public/assets/defaultLocale-C4B-KCzX.js +1 -0
- package/public/assets/diagram-PSM6KHXK-SONPsQNx.js +24 -0
- package/public/assets/diagram-QEK2KX5R-BKYFSfC1.js +43 -0
- package/public/assets/diagram-S2PKOQOG-CkM0APZj.js +24 -0
- package/public/assets/erDiagram-Q2GNP2WA-BX1DpOGx.js +60 -0
- package/public/assets/flowDiagram-NV44I4VS-HAAlzNbq.js +162 -0
- package/public/assets/ganttDiagram-LVOFAZNH-BqzWexqa.js +267 -0
- package/public/assets/gitGraphDiagram-NY62KEGX-CIPmSp43.js +65 -0
- package/public/assets/graph-m515btDj.js +1 -0
- package/public/assets/index-Bn3v3S9-.js +293 -0
- package/public/assets/index-DWieeYj4.css +1 -0
- package/public/assets/infoDiagram-F6ZHWCRC-Pn4yNWrF.js +2 -0
- package/public/assets/init-Gi6I4Gst.js +1 -0
- package/public/assets/journeyDiagram-XKPGCS4Q-BfzTomS0.js +139 -0
- package/public/assets/kanban-definition-3W4ZIXB7-Cgju7b-L.js +89 -0
- package/public/assets/katex-qrhCpa0F.js +261 -0
- package/public/assets/layout-BKQfQSxJ.js +1 -0
- package/public/assets/linear-DigtLz3B.js +1 -0
- package/public/assets/mindmap-definition-VGOIOE7T-qopraVFy.js +68 -0
- package/public/assets/monaco-editor-DHKm5-VF.js +19 -0
- package/public/assets/ordinal-Cboi1Yqb.js +1 -0
- package/public/assets/pieDiagram-ADFJNKIX-BcoaAI-L.js +30 -0
- package/public/assets/quadrantDiagram-AYHSOK5B-D-DwcoSd.js +7 -0
- package/public/assets/requirementDiagram-UZGBJVZJ-DbQCpx77.js +64 -0
- package/public/assets/sankeyDiagram-TZEHDZUN-BVk8387S.js +10 -0
- package/public/assets/sequenceDiagram-WL72ISMW-BdzICjxO.js +145 -0
- package/public/assets/stateDiagram-FKZM4ZOC-CYY-uUvJ.js +1 -0
- package/public/assets/stateDiagram-v2-4FDKWEC3-Dh2Kvomq.js +1 -0
- package/{backend/dist/frontend/assets/syntax-highlighting-YWvMU4Hm.js → public/assets/syntax-highlighting-CnREyncB.js} +5 -5
- package/public/assets/tabManager-B2LQO_Ll.js +30 -0
- package/{backend/dist/frontend/assets/table-D6q1rytw.js → public/assets/table-D0L2RL5i.js} +1 -1
- package/public/assets/timeline-definition-IT6M3QCI-BAvjPYvX.js +61 -0
- package/public/assets/tools-IcPNZlPj.js +1 -0
- package/public/assets/treemap-KMMF4GRG-DtkpVA56.js +128 -0
- package/{backend/dist/frontend/assets/ui-components-Cw21Epuw.js → public/assets/ui-components-D1St49qC.js} +231 -96
- package/public/assets/useAgents-BnDTkOG8.js +2 -0
- package/public/assets/useClaudeVersions-CD59tFWM.js +1 -0
- package/public/assets/useCommands-mvMu3mMD.js +1 -0
- package/public/assets/useProjects-YXOjaOwL.js +1 -0
- package/public/assets/xychartDiagram-PRI3JC2R-ByBTDWE2.js +7 -0
- package/{backend/dist/frontend → public}/index.html +8 -8
- package/routes/__tests__/a2a.integration.test.d.ts +11 -0
- package/routes/__tests__/a2a.integration.test.d.ts.map +1 -0
- package/routes/__tests__/a2a.integration.test.js +314 -0
- package/routes/__tests__/a2a.integration.test.js.map +1 -0
- package/routes/__tests__/a2a.test.d.ts +6 -0
- package/routes/__tests__/a2a.test.d.ts.map +1 -0
- package/routes/__tests__/a2a.test.js +622 -0
- package/routes/__tests__/a2a.test.js.map +1 -0
- package/routes/__tests__/agents.test.d.ts +6 -0
- package/routes/__tests__/agents.test.d.ts.map +1 -0
- package/routes/__tests__/agents.test.js +315 -0
- package/routes/__tests__/agents.test.js.map +1 -0
- package/routes/__tests__/sessions.test.d.ts +7 -0
- package/routes/__tests__/sessions.test.d.ts.map +1 -0
- package/routes/__tests__/sessions.test.js +330 -0
- package/routes/__tests__/sessions.test.js.map +1 -0
- package/routes/a2a.d.ts +18 -0
- package/routes/a2a.d.ts.map +1 -0
- package/routes/a2a.js +649 -0
- package/routes/a2a.js.map +1 -0
- package/routes/a2a.streaming.test.d.ts +2 -0
- package/routes/a2a.streaming.test.d.ts.map +1 -0
- package/routes/a2a.streaming.test.js +167 -0
- package/routes/a2a.streaming.test.js.map +1 -0
- package/routes/a2aManagement.d.ts +21 -0
- package/routes/a2aManagement.d.ts.map +1 -0
- package/routes/a2aManagement.js +466 -0
- package/routes/a2aManagement.js.map +1 -0
- package/{backend/dist/routes → routes}/agents.d.ts.map +1 -1
- package/routes/agents.js +997 -0
- package/routes/agents.js.map +1 -0
- package/{backend/dist/routes → routes}/auth.d.ts.map +1 -1
- package/routes/auth.js +135 -0
- package/routes/auth.js.map +1 -0
- package/{backend/dist/routes → routes}/commands.d.ts.map +1 -1
- package/{backend/dist/routes → routes}/commands.js +115 -31
- package/routes/commands.js.map +1 -0
- package/routes/config.d.ts +4 -0
- package/routes/config.d.ts.map +1 -0
- package/routes/config.js +211 -0
- package/routes/config.js.map +1 -0
- package/{backend/dist/routes → routes}/files.d.ts.map +1 -1
- package/{backend/dist/routes → routes}/files.js +103 -43
- package/routes/files.js.map +1 -0
- package/routes/mcp.d.ts +27 -0
- package/routes/mcp.d.ts.map +1 -0
- package/{backend/dist/routes → routes}/mcp.js +195 -105
- package/routes/mcp.js.map +1 -0
- package/routes/mcpAdmin.d.ts +16 -0
- package/routes/mcpAdmin.d.ts.map +1 -0
- package/routes/mcpAdmin.js +308 -0
- package/routes/mcpAdmin.js.map +1 -0
- package/routes/mcpAdminManagement.d.ts +17 -0
- package/routes/mcpAdminManagement.d.ts.map +1 -0
- package/routes/mcpAdminManagement.js +345 -0
- package/routes/mcpAdminManagement.js.map +1 -0
- package/routes/media.d.ts.map +1 -0
- package/{backend/dist/routes → routes}/media.js +52 -42
- package/routes/media.js.map +1 -0
- package/routes/mediaAuth.d.ts +8 -0
- package/routes/mediaAuth.d.ts.map +1 -0
- package/routes/mediaAuth.js +136 -0
- package/routes/mediaAuth.js.map +1 -0
- package/routes/plugins.d.ts +4 -0
- package/routes/plugins.d.ts.map +1 -0
- package/routes/plugins.js +339 -0
- package/routes/plugins.js.map +1 -0
- package/{backend/dist/routes → routes}/projects.d.ts.map +1 -1
- package/routes/projects.js +884 -0
- package/routes/projects.js.map +1 -0
- package/routes/scheduledTasks.d.ts +9 -0
- package/routes/scheduledTasks.d.ts.map +1 -0
- package/routes/scheduledTasks.js +320 -0
- package/routes/scheduledTasks.js.map +1 -0
- package/{backend/dist/routes → routes}/sessions.d.ts.map +1 -1
- package/{backend/dist/routes → routes}/sessions.js +258 -39
- package/routes/sessions.js.map +1 -0
- package/{backend/dist/routes → routes}/settings.d.ts.map +1 -1
- package/{backend/dist/routes → routes}/settings.js +82 -241
- package/routes/settings.js.map +1 -0
- package/{backend/dist/routes/mcp.d.ts → routes/skills.d.ts} +1 -1
- package/routes/skills.d.ts.map +1 -0
- package/routes/skills.js +272 -0
- package/routes/skills.js.map +1 -0
- package/routes/slack.d.ts +10 -0
- package/routes/slack.d.ts.map +1 -0
- package/routes/slack.js +189 -0
- package/routes/slack.js.map +1 -0
- package/{backend/dist/routes → routes}/slides.d.ts.map +1 -1
- package/{backend/dist/routes → routes}/slides.js +29 -27
- package/routes/slides.js.map +1 -0
- package/{backend/dist/routes → routes}/subagents.js +27 -22
- package/routes/subagents.js.map +1 -0
- package/schemas/a2a.d.ts +858 -0
- package/schemas/a2a.d.ts.map +1 -0
- package/schemas/a2a.js +300 -0
- package/schemas/a2a.js.map +1 -0
- package/scripts/postinstall.js +10 -0
- package/services/__tests__/pluginInstaller.test.d.ts +5 -0
- package/services/__tests__/pluginInstaller.test.d.ts.map +1 -0
- package/services/__tests__/pluginInstaller.test.js +290 -0
- package/services/__tests__/pluginInstaller.test.js.map +1 -0
- package/services/__tests__/pluginParser.test.d.ts +5 -0
- package/services/__tests__/pluginParser.test.d.ts.map +1 -0
- package/services/__tests__/pluginParser.test.js +272 -0
- package/services/__tests__/pluginParser.test.js.map +1 -0
- package/services/__tests__/pluginPaths.test.d.ts +5 -0
- package/services/__tests__/pluginPaths.test.d.ts.map +1 -0
- package/services/__tests__/pluginPaths.test.js +221 -0
- package/services/__tests__/pluginPaths.test.js.map +1 -0
- package/services/__tests__/pluginScanner.test.d.ts +5 -0
- package/services/__tests__/pluginScanner.test.d.ts.map +1 -0
- package/services/__tests__/pluginScanner.test.js +272 -0
- package/services/__tests__/pluginScanner.test.js.map +1 -0
- package/services/__tests__/pluginSymlink.test.d.ts +5 -0
- package/services/__tests__/pluginSymlink.test.d.ts.map +1 -0
- package/services/__tests__/pluginSymlink.test.js +318 -0
- package/services/__tests__/pluginSymlink.test.js.map +1 -0
- package/services/__tests__/slackAIService.test.d.ts +5 -0
- package/services/__tests__/slackAIService.test.d.ts.map +1 -0
- package/services/__tests__/slackAIService.test.js +477 -0
- package/services/__tests__/slackAIService.test.js.map +1 -0
- package/services/__tests__/slackThreadMapper.test.d.ts +5 -0
- package/services/__tests__/slackThreadMapper.test.d.ts.map +1 -0
- package/services/__tests__/slackThreadMapper.test.js +194 -0
- package/services/__tests__/slackThreadMapper.test.js.map +1 -0
- package/services/a2a/__tests__/a2aClientTool.integration.test.d.ts +6 -0
- package/services/a2a/__tests__/a2aClientTool.integration.test.d.ts.map +1 -0
- package/services/a2a/__tests__/a2aClientTool.integration.test.js +264 -0
- package/services/a2a/__tests__/a2aClientTool.integration.test.js.map +1 -0
- package/services/a2a/__tests__/a2aClientTool.test.d.ts +6 -0
- package/services/a2a/__tests__/a2aClientTool.test.d.ts.map +1 -0
- package/services/a2a/__tests__/a2aClientTool.test.js +418 -0
- package/services/a2a/__tests__/a2aClientTool.test.js.map +1 -0
- package/services/a2a/__tests__/a2aConfigService.test.d.ts +6 -0
- package/services/a2a/__tests__/a2aConfigService.test.d.ts.map +1 -0
- package/services/a2a/__tests__/a2aConfigService.test.js +431 -0
- package/services/a2a/__tests__/a2aConfigService.test.js.map +1 -0
- package/services/a2a/__tests__/a2aConfigServicePath.test.d.ts +2 -0
- package/services/a2a/__tests__/a2aConfigServicePath.test.d.ts.map +1 -0
- package/services/a2a/__tests__/a2aConfigServicePath.test.js +49 -0
- package/services/a2a/__tests__/a2aConfigServicePath.test.js.map +1 -0
- package/services/a2a/__tests__/a2aSdkMcp.test.d.ts +10 -0
- package/services/a2a/__tests__/a2aSdkMcp.test.d.ts.map +1 -0
- package/services/a2a/__tests__/a2aSdkMcp.test.js +239 -0
- package/services/a2a/__tests__/a2aSdkMcp.test.js.map +1 -0
- package/services/a2a/__tests__/agentCardService.test.d.ts +6 -0
- package/services/a2a/__tests__/agentCardService.test.d.ts.map +1 -0
- package/services/a2a/__tests__/agentCardService.test.js +292 -0
- package/services/a2a/__tests__/agentCardService.test.js.map +1 -0
- package/services/a2a/__tests__/apiKeyService.test.d.ts +6 -0
- package/services/a2a/__tests__/apiKeyService.test.d.ts.map +1 -0
- package/services/a2a/__tests__/apiKeyService.test.js +284 -0
- package/services/a2a/__tests__/apiKeyService.test.js.map +1 -0
- package/services/a2a/__tests__/buildQueryOptionsIntegration.test.d.ts +2 -0
- package/services/a2a/__tests__/buildQueryOptionsIntegration.test.d.ts.map +1 -0
- package/services/a2a/__tests__/buildQueryOptionsIntegration.test.js +70 -0
- package/services/a2a/__tests__/buildQueryOptionsIntegration.test.js.map +1 -0
- package/services/a2a/__tests__/dynamic_config_verification.test.d.ts +2 -0
- package/services/a2a/__tests__/dynamic_config_verification.test.d.ts.map +1 -0
- package/services/a2a/__tests__/dynamic_config_verification.test.js +67 -0
- package/services/a2a/__tests__/dynamic_config_verification.test.js.map +1 -0
- package/services/a2a/__tests__/integrateA2AMcpServer.test.d.ts +2 -0
- package/services/a2a/__tests__/integrateA2AMcpServer.test.d.ts.map +1 -0
- package/services/a2a/__tests__/integrateA2AMcpServer.test.js +112 -0
- package/services/a2a/__tests__/integrateA2AMcpServer.test.js.map +1 -0
- package/services/a2a/__tests__/taskManager.integration.test.d.ts +7 -0
- package/services/a2a/__tests__/taskManager.integration.test.d.ts.map +1 -0
- package/services/a2a/__tests__/taskManager.integration.test.js +346 -0
- package/services/a2a/__tests__/taskManager.integration.test.js.map +1 -0
- package/services/a2a/__tests__/taskManager.test.d.ts +7 -0
- package/services/a2a/__tests__/taskManager.test.d.ts.map +1 -0
- package/services/a2a/__tests__/taskManager.test.js +423 -0
- package/services/a2a/__tests__/taskManager.test.js.map +1 -0
- package/services/a2a/a2aClientTool.d.ts +73 -0
- package/services/a2a/a2aClientTool.d.ts.map +1 -0
- package/services/a2a/a2aClientTool.js +572 -0
- package/services/a2a/a2aClientTool.js.map +1 -0
- package/services/a2a/a2aConfigService.d.ts +50 -0
- package/services/a2a/a2aConfigService.d.ts.map +1 -0
- package/services/a2a/a2aConfigService.js +186 -0
- package/services/a2a/a2aConfigService.js.map +1 -0
- package/services/a2a/a2aHistoryService.d.ts +32 -0
- package/services/a2a/a2aHistoryService.d.ts.map +1 -0
- package/services/a2a/a2aHistoryService.js +108 -0
- package/services/a2a/a2aHistoryService.js.map +1 -0
- package/services/a2a/a2aIntegration.d.ts +9 -0
- package/services/a2a/a2aIntegration.d.ts.map +1 -0
- package/services/a2a/a2aIntegration.js +41 -0
- package/services/a2a/a2aIntegration.js.map +1 -0
- package/services/a2a/a2aQueryService.d.ts +71 -0
- package/services/a2a/a2aQueryService.d.ts.map +1 -0
- package/services/a2a/a2aQueryService.js +166 -0
- package/services/a2a/a2aQueryService.js.map +1 -0
- package/services/a2a/a2aSdkMcp.d.ts +51 -0
- package/services/a2a/a2aSdkMcp.d.ts.map +1 -0
- package/services/a2a/a2aSdkMcp.js +185 -0
- package/services/a2a/a2aSdkMcp.js.map +1 -0
- package/services/a2a/a2aStreamEvents.d.ts +94 -0
- package/services/a2a/a2aStreamEvents.d.ts.map +1 -0
- package/services/a2a/a2aStreamEvents.js +92 -0
- package/services/a2a/a2aStreamEvents.js.map +1 -0
- package/services/a2a/agentCardService.d.ts +34 -0
- package/services/a2a/agentCardService.d.ts.map +1 -0
- package/services/a2a/agentCardService.js +228 -0
- package/services/a2a/agentCardService.js.map +1 -0
- package/services/a2a/agentMappingService.d.ts +53 -0
- package/services/a2a/agentMappingService.d.ts.map +1 -0
- package/services/a2a/agentMappingService.js +185 -0
- package/services/a2a/agentMappingService.js.map +1 -0
- package/services/a2a/apiKeyService.d.ts +101 -0
- package/services/a2a/apiKeyService.d.ts.map +1 -0
- package/services/a2a/apiKeyService.js +314 -0
- package/services/a2a/apiKeyService.js.map +1 -0
- package/services/a2a/taskCleanup.d.ts +30 -0
- package/services/a2a/taskCleanup.d.ts.map +1 -0
- package/services/a2a/taskCleanup.js +184 -0
- package/services/a2a/taskCleanup.js.map +1 -0
- package/services/a2a/taskManager.d.ts +86 -0
- package/services/a2a/taskManager.d.ts.map +1 -0
- package/services/a2a/taskManager.js +263 -0
- package/services/a2a/taskManager.js.map +1 -0
- package/services/agentStorage.d.ts +27 -0
- package/services/agentStorage.d.ts.map +1 -0
- package/services/agentStorage.js +487 -0
- package/services/agentStorage.js.map +1 -0
- package/services/askUserQuestion/askUserQuestionIntegration.d.ts +24 -0
- package/services/askUserQuestion/askUserQuestionIntegration.d.ts.map +1 -0
- package/services/askUserQuestion/askUserQuestionIntegration.js +52 -0
- package/services/askUserQuestion/askUserQuestionIntegration.js.map +1 -0
- package/services/askUserQuestion/askUserQuestionMcp.d.ts +103 -0
- package/services/askUserQuestion/askUserQuestionMcp.d.ts.map +1 -0
- package/services/askUserQuestion/askUserQuestionMcp.js +129 -0
- package/services/askUserQuestion/askUserQuestionMcp.js.map +1 -0
- package/services/askUserQuestion/index.d.ts +13 -0
- package/services/askUserQuestion/index.d.ts.map +1 -0
- package/services/askUserQuestion/index.js +35 -0
- package/services/askUserQuestion/index.js.map +1 -0
- package/services/askUserQuestion/init.d.ts +17 -0
- package/services/askUserQuestion/init.d.ts.map +1 -0
- package/services/askUserQuestion/init.js +47 -0
- package/services/askUserQuestion/init.js.map +1 -0
- package/services/askUserQuestion/notificationChannel.d.ts +97 -0
- package/services/askUserQuestion/notificationChannel.d.ts.map +1 -0
- package/services/askUserQuestion/notificationChannel.js +147 -0
- package/services/askUserQuestion/notificationChannel.js.map +1 -0
- package/services/askUserQuestion/slackNotificationChannel.d.ts +35 -0
- package/services/askUserQuestion/slackNotificationChannel.d.ts.map +1 -0
- package/services/askUserQuestion/slackNotificationChannel.js +129 -0
- package/services/askUserQuestion/slackNotificationChannel.js.map +1 -0
- package/services/askUserQuestion/sseNotificationChannel.d.ts +36 -0
- package/services/askUserQuestion/sseNotificationChannel.d.ts.map +1 -0
- package/services/askUserQuestion/sseNotificationChannel.js +88 -0
- package/services/askUserQuestion/sseNotificationChannel.js.map +1 -0
- package/services/askUserQuestion/userInputRegistry.d.ts +107 -0
- package/services/askUserQuestion/userInputRegistry.d.ts.map +1 -0
- package/services/askUserQuestion/userInputRegistry.js +253 -0
- package/services/askUserQuestion/userInputRegistry.js.map +1 -0
- package/{backend/dist/services → services}/claudeSession.d.ts +20 -5
- package/services/claudeSession.d.ts.map +1 -0
- package/{backend/dist/services → services}/claudeSession.js +123 -41
- package/services/claudeSession.js.map +1 -0
- package/services/claudeVersionStorage.d.ts +20 -0
- package/services/claudeVersionStorage.d.ts.map +1 -0
- package/services/claudeVersionStorage.js +331 -0
- package/services/claudeVersionStorage.js.map +1 -0
- package/services/mcpAdmin/__tests__/adminApiKeyService.test.d.ts +5 -0
- package/services/mcpAdmin/__tests__/adminApiKeyService.test.d.ts.map +1 -0
- package/services/mcpAdmin/__tests__/adminApiKeyService.test.js +289 -0
- package/services/mcpAdmin/__tests__/adminApiKeyService.test.js.map +1 -0
- package/services/mcpAdmin/__tests__/mcpAdminRoutes.test.d.ts +5 -0
- package/services/mcpAdmin/__tests__/mcpAdminRoutes.test.d.ts.map +1 -0
- package/services/mcpAdmin/__tests__/mcpAdminRoutes.test.js +345 -0
- package/services/mcpAdmin/__tests__/mcpAdminRoutes.test.js.map +1 -0
- package/services/mcpAdmin/__tests__/mcpAdminServer.test.d.ts +5 -0
- package/services/mcpAdmin/__tests__/mcpAdminServer.test.d.ts.map +1 -0
- package/services/mcpAdmin/__tests__/mcpAdminServer.test.js +453 -0
- package/services/mcpAdmin/__tests__/mcpAdminServer.test.js.map +1 -0
- package/services/mcpAdmin/__tests__/tools.test.d.ts +5 -0
- package/services/mcpAdmin/__tests__/tools.test.d.ts.map +1 -0
- package/services/mcpAdmin/__tests__/tools.test.js +371 -0
- package/services/mcpAdmin/__tests__/tools.test.js.map +1 -0
- package/services/mcpAdmin/adminApiKeyService.d.ts +61 -0
- package/services/mcpAdmin/adminApiKeyService.d.ts.map +1 -0
- package/services/mcpAdmin/adminApiKeyService.js +270 -0
- package/services/mcpAdmin/adminApiKeyService.js.map +1 -0
- package/services/mcpAdmin/index.d.ts +10 -0
- package/services/mcpAdmin/index.d.ts.map +1 -0
- package/services/mcpAdmin/index.js +43 -0
- package/services/mcpAdmin/index.js.map +1 -0
- package/services/mcpAdmin/mcpAdminServer.d.ts +76 -0
- package/services/mcpAdmin/mcpAdminServer.d.ts.map +1 -0
- package/services/mcpAdmin/mcpAdminServer.js +243 -0
- package/services/mcpAdmin/mcpAdminServer.js.map +1 -0
- package/services/mcpAdmin/tools/agentTools.d.ts +27 -0
- package/services/mcpAdmin/tools/agentTools.d.ts.map +1 -0
- package/services/mcpAdmin/tools/agentTools.js +359 -0
- package/services/mcpAdmin/tools/agentTools.js.map +1 -0
- package/services/mcpAdmin/tools/index.d.ts +15 -0
- package/services/mcpAdmin/tools/index.d.ts.map +1 -0
- package/services/mcpAdmin/tools/index.js +30 -0
- package/services/mcpAdmin/tools/index.js.map +1 -0
- package/services/mcpAdmin/tools/mcpServerTools.d.ts +27 -0
- package/services/mcpAdmin/tools/mcpServerTools.d.ts.map +1 -0
- package/services/mcpAdmin/tools/mcpServerTools.js +334 -0
- package/services/mcpAdmin/tools/mcpServerTools.js.map +1 -0
- package/services/mcpAdmin/tools/projectTools.d.ts +27 -0
- package/services/mcpAdmin/tools/projectTools.d.ts.map +1 -0
- package/services/mcpAdmin/tools/projectTools.js +353 -0
- package/services/mcpAdmin/tools/projectTools.js.map +1 -0
- package/services/mcpAdmin/tools/systemTools.d.ts +23 -0
- package/services/mcpAdmin/tools/systemTools.d.ts.map +1 -0
- package/services/mcpAdmin/tools/systemTools.js +241 -0
- package/services/mcpAdmin/tools/systemTools.js.map +1 -0
- package/services/mcpAdmin/types.d.ts +124 -0
- package/services/mcpAdmin/types.d.ts.map +1 -0
- package/services/mcpAdmin/types.js +18 -0
- package/services/mcpAdmin/types.js.map +1 -0
- package/{backend/dist/services → services}/messageQueue.d.ts.map +1 -1
- package/{backend/dist/services → services}/messageQueue.js +16 -3
- package/services/messageQueue.js.map +1 -0
- package/services/pluginInstaller.d.ts +58 -0
- package/services/pluginInstaller.d.ts.map +1 -0
- package/services/pluginInstaller.js +321 -0
- package/services/pluginInstaller.js.map +1 -0
- package/services/pluginParser.d.ts +45 -0
- package/services/pluginParser.d.ts.map +1 -0
- package/services/pluginParser.js +437 -0
- package/services/pluginParser.js.map +1 -0
- package/services/pluginPaths.d.ts +80 -0
- package/services/pluginPaths.d.ts.map +1 -0
- package/services/pluginPaths.js +274 -0
- package/services/pluginPaths.js.map +1 -0
- package/services/pluginScanner.d.ts +36 -0
- package/services/pluginScanner.d.ts.map +1 -0
- package/services/pluginScanner.js +251 -0
- package/services/pluginScanner.js.map +1 -0
- package/services/pluginSymlink.d.ts +54 -0
- package/services/pluginSymlink.d.ts.map +1 -0
- package/services/pluginSymlink.js +223 -0
- package/services/pluginSymlink.js.map +1 -0
- package/services/projectMetadataStorage.d.ts +114 -0
- package/services/projectMetadataStorage.d.ts.map +1 -0
- package/services/projectMetadataStorage.js +711 -0
- package/services/projectMetadataStorage.js.map +1 -0
- package/services/scheduledTaskStorage.d.ts +52 -0
- package/services/scheduledTaskStorage.d.ts.map +1 -0
- package/services/scheduledTaskStorage.js +285 -0
- package/services/scheduledTaskStorage.js.map +1 -0
- package/services/schedulerService.d.ts +81 -0
- package/services/schedulerService.d.ts.map +1 -0
- package/services/schedulerService.js +743 -0
- package/services/schedulerService.js.map +1 -0
- package/{backend/dist/services → services}/sessionManager.d.ts +6 -4
- package/services/sessionManager.d.ts.map +1 -0
- package/{backend/dist/services → services}/sessionManager.js +77 -16
- package/services/sessionManager.js.map +1 -0
- package/services/skillStorage.d.ts +60 -0
- package/services/skillStorage.d.ts.map +1 -0
- package/services/skillStorage.js +398 -0
- package/services/skillStorage.js.map +1 -0
- package/services/slackAIService.d.ts +81 -0
- package/services/slackAIService.d.ts.map +1 -0
- package/services/slackAIService.js +1091 -0
- package/services/slackAIService.js.map +1 -0
- package/services/slackClient.d.ts +46 -0
- package/services/slackClient.d.ts.map +1 -0
- package/services/slackClient.js +85 -0
- package/services/slackClient.js.map +1 -0
- package/services/slackSessionLock.d.ts +79 -0
- package/services/slackSessionLock.d.ts.map +1 -0
- package/services/slackSessionLock.js +353 -0
- package/services/slackSessionLock.js.map +1 -0
- package/services/slackThreadMapper.d.ts +57 -0
- package/services/slackThreadMapper.d.ts.map +1 -0
- package/services/slackThreadMapper.js +140 -0
- package/services/slackThreadMapper.js.map +1 -0
- package/types/a2a.d.ts +275 -0
- package/types/a2a.d.ts.map +1 -0
- package/types/a2a.js +23 -0
- package/types/a2a.js.map +1 -0
- package/types/agents.d.ts +95 -0
- package/types/agents.d.ts.map +1 -0
- package/types/agents.js +46 -0
- package/types/agents.js.map +1 -0
- package/types/claude-history.d.ts +62 -0
- package/types/claude-history.d.ts.map +1 -0
- package/types/claude-history.js +4 -0
- package/types/claude-history.js.map +1 -0
- package/types/claude-versions.d.ts +36 -0
- package/types/claude-versions.d.ts.map +1 -0
- package/types/claude-versions.js +3 -0
- package/types/claude-versions.js.map +1 -0
- package/types/commands.d.ts +50 -0
- package/types/commands.d.ts.map +1 -0
- package/types/commands.js +23 -0
- package/types/commands.js.map +1 -0
- package/types/plugins.d.ts +144 -0
- package/types/plugins.d.ts.map +1 -0
- package/types/plugins.js +8 -0
- package/types/plugins.js.map +1 -0
- package/types/projects.d.ts +42 -0
- package/types/projects.d.ts.map +1 -0
- package/types/projects.js +4 -0
- package/types/projects.js.map +1 -0
- package/types/scheduledTasks.d.ts +164 -0
- package/types/scheduledTasks.d.ts.map +1 -0
- package/types/scheduledTasks.js +17 -0
- package/types/scheduledTasks.js.map +1 -0
- package/types/skills.d.ts +91 -0
- package/types/skills.d.ts.map +1 -0
- package/types/skills.js +6 -0
- package/types/skills.js.map +1 -0
- package/types/slack.d.ts +97 -0
- package/types/slack.d.ts.map +1 -0
- package/types/slack.js +8 -0
- package/types/slack.js.map +1 -0
- package/types/streaming.d.ts +12 -0
- package/types/streaming.d.ts.map +1 -0
- package/types/streaming.js +8 -0
- package/types/streaming.js.map +1 -0
- package/types/subagents.d.ts +26 -0
- package/types/subagents.d.ts.map +1 -0
- package/types/subagents.js +3 -0
- package/types/subagents.js.map +1 -0
- package/utils/__tests__/claudeUtils.test.d.ts +5 -0
- package/utils/__tests__/claudeUtils.test.d.ts.map +1 -0
- package/utils/__tests__/claudeUtils.test.js +282 -0
- package/utils/__tests__/claudeUtils.test.js.map +1 -0
- package/utils/__tests__/sessionUtils.test.d.ts +5 -0
- package/utils/__tests__/sessionUtils.test.d.ts.map +1 -0
- package/utils/__tests__/sessionUtils.test.js +295 -0
- package/utils/__tests__/sessionUtils.test.js.map +1 -0
- package/utils/agentCardCache.d.ts +93 -0
- package/utils/agentCardCache.d.ts.map +1 -0
- package/utils/agentCardCache.js +212 -0
- package/utils/agentCardCache.js.map +1 -0
- package/utils/claudeUtils.d.ts +54 -0
- package/utils/claudeUtils.d.ts.map +1 -0
- package/utils/claudeUtils.js +387 -0
- package/utils/claudeUtils.js.map +1 -0
- package/utils/fileUtils.d.ts +2 -0
- package/utils/fileUtils.d.ts.map +1 -0
- package/utils/fileUtils.js +11 -0
- package/utils/fileUtils.js.map +1 -0
- package/utils/jwt.d.ts +30 -0
- package/utils/jwt.d.ts.map +1 -0
- package/utils/jwt.js +95 -0
- package/utils/jwt.js.map +1 -0
- package/utils/sessionUtils.d.ts +64 -0
- package/utils/sessionUtils.d.ts.map +1 -0
- package/utils/sessionUtils.js +266 -0
- package/utils/sessionUtils.js.map +1 -0
- package/README.zh-CN.md +0 -525
- package/backend/dist/bin/agentstudio.js +0 -120
- package/backend/dist/bin/agentstudio.js.map +0 -1
- package/backend/dist/frontend/assets/AgentsPage-Dqb_aqAA.js +0 -1
- package/backend/dist/frontend/assets/ChatPage-L8Paywyc.js +0 -91
- package/backend/dist/frontend/assets/CommandForm-DLl7EIMS.js +0 -7
- package/backend/dist/frontend/assets/CommandsPage-Bzavq0Ec.js +0 -1
- package/backend/dist/frontend/assets/DashboardPage-B3o4AYFT.js +0 -15
- package/backend/dist/frontend/assets/FileBrowser-DL3ayaqb.js +0 -1
- package/backend/dist/frontend/assets/GeneralSettingsPage-CBN_de-V.js +0 -1
- package/backend/dist/frontend/assets/LandingPage-Dl4ioKos.js +0 -1
- package/backend/dist/frontend/assets/LoginPage-4QqRdiSi.js +0 -12
- package/backend/dist/frontend/assets/McpPage-CY3tYiqj.js +0 -39
- package/backend/dist/frontend/assets/MemorySettingsPage-DGxrok5K.js +0 -1
- package/backend/dist/frontend/assets/ProjectSelector-hgmGYVFh.js +0 -1
- package/backend/dist/frontend/assets/ProjectsPage-D399IM0c.js +0 -14
- package/backend/dist/frontend/assets/SettingsLayout-CL_K-lzJ.js +0 -1
- package/backend/dist/frontend/assets/SubagentsPage-Chbhj8p2.js +0 -1
- package/backend/dist/frontend/assets/UnifiedToolSelector-CsM9qBvs.js +0 -1
- package/backend/dist/frontend/assets/VersionSettingsPage-74Q-LVgA.js +0 -5
- package/backend/dist/frontend/assets/agents-ClAzIJTw.js +0 -1
- package/backend/dist/frontend/assets/authFetch-BATQyPG5.js +0 -1
- package/backend/dist/frontend/assets/index-B9YHa7XT.css +0 -1
- package/backend/dist/frontend/assets/index-B_CTNvca.js +0 -268
- package/backend/dist/frontend/assets/monaco-editor-C7Z4sOhS.js +0 -19
- package/backend/dist/frontend/assets/tabManager-DV8urRBM.js +0 -30
- package/backend/dist/frontend/assets/tools-C4EPanYi.js +0 -1
- package/backend/dist/frontend/assets/useAgents-DwnOE1_k.js +0 -2
- package/backend/dist/frontend/assets/useClaudeVersions-CQdGnCqv.js +0 -1
- package/backend/dist/frontend/assets/useCommands-CCVaurbt.js +0 -1
- package/backend/dist/index.d.ts +0 -3
- package/backend/dist/index.d.ts.map +0 -1
- package/backend/dist/index.js +0 -157
- package/backend/dist/index.js.map +0 -1
- package/backend/dist/middleware/auth.d.ts.map +0 -1
- package/backend/dist/middleware/auth.js +0 -21
- package/backend/dist/middleware/auth.js.map +0 -1
- package/backend/dist/routes/agents.js +0 -803
- package/backend/dist/routes/agents.js.map +0 -1
- package/backend/dist/routes/auth.js +0 -60
- package/backend/dist/routes/auth.js.map +0 -1
- package/backend/dist/routes/commands.js.map +0 -1
- package/backend/dist/routes/files.js.map +0 -1
- package/backend/dist/routes/mcp.d.ts.map +0 -1
- package/backend/dist/routes/mcp.js.map +0 -1
- package/backend/dist/routes/media.d.ts.map +0 -1
- package/backend/dist/routes/media.js.map +0 -1
- package/backend/dist/routes/projects.js +0 -528
- package/backend/dist/routes/projects.js.map +0 -1
- package/backend/dist/routes/sessions.js.map +0 -1
- package/backend/dist/routes/settings.js.map +0 -1
- package/backend/dist/routes/slides.js.map +0 -1
- package/backend/dist/routes/subagents.js.map +0 -1
- package/backend/dist/services/claudeSession.d.ts.map +0 -1
- package/backend/dist/services/claudeSession.js.map +0 -1
- package/backend/dist/services/messageQueue.js.map +0 -1
- package/backend/dist/services/sessionManager.d.ts.map +0 -1
- package/backend/dist/services/sessionManager.js.map +0 -1
- package/backend/dist/utils/jwt.d.ts +0 -15
- package/backend/dist/utils/jwt.d.ts.map +0 -1
- package/backend/dist/utils/jwt.js +0 -28
- package/backend/dist/utils/jwt.js.map +0 -1
- /package/{backend/dist/bin → bin}/agentstudio.d.ts +0 -0
- /package/{backend/dist/bin → bin}/agentstudio.d.ts.map +0 -0
- /package/{backend/dist/frontend → public}/assets/ChatPage-BvQmXfcP.css +0 -0
- /package/{backend/dist/frontend → public}/assets/agents-DwCY2K8p.css +0 -0
- /package/{backend/dist/frontend → public}/assets/dateFormat-CXa8VnEC.js +0 -0
- /package/{backend/dist/frontend → public}/cc-studio.png +0 -0
- /package/{backend/dist/frontend → public}/vite.svg +0 -0
- /package/{backend/dist/routes → routes}/agents.d.ts +0 -0
- /package/{backend/dist/routes → routes}/auth.d.ts +0 -0
- /package/{backend/dist/routes → routes}/commands.d.ts +0 -0
- /package/{backend/dist/routes → routes}/files.d.ts +0 -0
- /package/{backend/dist/routes → routes}/media.d.ts +0 -0
- /package/{backend/dist/routes → routes}/projects.d.ts +0 -0
- /package/{backend/dist/routes → routes}/sessions.d.ts +0 -0
- /package/{backend/dist/routes → routes}/settings.d.ts +0 -0
- /package/{backend/dist/routes → routes}/slides.d.ts +0 -0
- /package/{backend/dist/routes → routes}/subagents.d.ts +0 -0
- /package/{backend/dist/routes → routes}/subagents.d.ts.map +0 -0
- /package/{backend/dist/services → services}/messageQueue.d.ts +0 -0
|
@@ -0,0 +1,1091 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Slack AI Service
|
|
4
|
+
*
|
|
5
|
+
* Adapts AgentStudio's AI architecture for Slack
|
|
6
|
+
* Reuses sessionManager, AgentStorage, and Claude Code SDK
|
|
7
|
+
* WITHOUT modifying existing SSE implementation
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.SlackAIService = void 0;
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const sessionManager_js_1 = require("./sessionManager.js");
|
|
47
|
+
const agentStorage_js_1 = require("./agentStorage.js");
|
|
48
|
+
const slackThreadMapper_js_1 = require("./slackThreadMapper.js");
|
|
49
|
+
const slackSessionLock_js_1 = require("./slackSessionLock.js");
|
|
50
|
+
const slackClient_js_1 = require("./slackClient.js");
|
|
51
|
+
const projectMetadataStorage_js_1 = require("./projectMetadataStorage.js");
|
|
52
|
+
const index_js_1 = require("../config/index.js");
|
|
53
|
+
const claudeUtils_js_1 = require("../utils/claudeUtils.js");
|
|
54
|
+
const claudeVersionStorage_js_1 = require("./claudeVersionStorage.js");
|
|
55
|
+
const sessionUtils_js_1 = require("../utils/sessionUtils.js");
|
|
56
|
+
/**
|
|
57
|
+
* Parse agent from message text
|
|
58
|
+
* Supports agent mention, agent name, or agent ID
|
|
59
|
+
*/
|
|
60
|
+
function parseAgentFromMessage(text, allAgents) {
|
|
61
|
+
// Remove the bot mention if present
|
|
62
|
+
const cleanText = text.replace(/<@[A-Z0-9]+>/g, '').trim();
|
|
63
|
+
// Check for agent mention format: @agent-name or agent-name
|
|
64
|
+
const agentMentionMatch = cleanText.match(/^@?([a-zA-Z0-9\-_]+)\s+(.+)/);
|
|
65
|
+
if (agentMentionMatch) {
|
|
66
|
+
const potentialAgentId = agentMentionMatch[1];
|
|
67
|
+
const remainingText = agentMentionMatch[2].trim();
|
|
68
|
+
// First try exact match with agent ID
|
|
69
|
+
let agent = allAgents.find(a => a.id.toLowerCase() === potentialAgentId.toLowerCase());
|
|
70
|
+
// Then try name match
|
|
71
|
+
if (!agent) {
|
|
72
|
+
agent = allAgents.find(a => a.name.toLowerCase().includes(potentialAgentId.toLowerCase()) ||
|
|
73
|
+
potentialAgentId.toLowerCase().includes(a.name.toLowerCase()));
|
|
74
|
+
}
|
|
75
|
+
// Finally try to match with common aliases
|
|
76
|
+
if (!agent) {
|
|
77
|
+
const aliases = {
|
|
78
|
+
'ppt': 'ppt-editor',
|
|
79
|
+
'slides': 'ppt-editor',
|
|
80
|
+
'presentation': 'ppt-editor',
|
|
81
|
+
'powerpoint': 'ppt-editor',
|
|
82
|
+
'code': 'code-assistant',
|
|
83
|
+
'coding': 'code-assistant',
|
|
84
|
+
'developer': 'code-assistant',
|
|
85
|
+
'programmer': 'code-assistant',
|
|
86
|
+
'document': 'document-writer',
|
|
87
|
+
'docs': 'document-writer',
|
|
88
|
+
'writing': 'document-writer',
|
|
89
|
+
'writer': 'document-writer',
|
|
90
|
+
'general': 'general-chat',
|
|
91
|
+
'chat': 'general-chat',
|
|
92
|
+
'assistant': 'general-chat',
|
|
93
|
+
'help': 'general-chat'
|
|
94
|
+
};
|
|
95
|
+
const aliasId = aliases[potentialAgentId.toLowerCase()];
|
|
96
|
+
if (aliasId) {
|
|
97
|
+
agent = allAgents.find(a => a.id === aliasId);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (agent && agent.enabled) {
|
|
101
|
+
return { agentId: agent.id, cleanText: remainingText };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Parse project specification from message text
|
|
108
|
+
* Supports proj:project-name format
|
|
109
|
+
*/
|
|
110
|
+
function parseProjectFromMessage(text) {
|
|
111
|
+
// Check for project specification format: proj:project-name
|
|
112
|
+
// The pattern can appear anywhere in the text
|
|
113
|
+
const projectMatch = text.match(/proj:([^\s]+)/i);
|
|
114
|
+
if (projectMatch) {
|
|
115
|
+
const projectIdentifier = projectMatch[1];
|
|
116
|
+
// Remove the project specification from the text
|
|
117
|
+
const cleanText = text.replace(/proj:[^\s]+/gi, '').trim();
|
|
118
|
+
return { projectIdentifier, cleanText };
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Match project identifier against available projects
|
|
124
|
+
* Priority order: exact path match -> exact directory name match (prefer home paths) -> basename match -> partial match
|
|
125
|
+
*/
|
|
126
|
+
function matchProject(identifier, allProjects) {
|
|
127
|
+
const identifierLower = identifier.toLowerCase();
|
|
128
|
+
// Priority 1: Exact path match (full path or real path)
|
|
129
|
+
const exactPathMatches = allProjects.filter(project => project.path.toLowerCase() === identifierLower ||
|
|
130
|
+
project.realPath?.toLowerCase() === identifierLower);
|
|
131
|
+
if (exactPathMatches.length > 0) {
|
|
132
|
+
return { matches: exactPathMatches, isExactMatch: true };
|
|
133
|
+
}
|
|
134
|
+
// Priority 2: Exact directory name match
|
|
135
|
+
const exactDirMatches = allProjects.filter(project => project.dirName.toLowerCase() === identifierLower);
|
|
136
|
+
if (exactDirMatches.length > 0) {
|
|
137
|
+
// If multiple exact directory matches, prioritize by:
|
|
138
|
+
// 1. Home directory paths (containing /home/ or ~)
|
|
139
|
+
// 2. More recently accessed
|
|
140
|
+
const prioritizedMatches = exactDirMatches.sort((a, b) => {
|
|
141
|
+
const aIsHome = a.path.includes('/home/') || a.path.includes('~');
|
|
142
|
+
const bIsHome = b.path.includes('/home/') || b.path.includes('~');
|
|
143
|
+
if (aIsHome && !bIsHome)
|
|
144
|
+
return -1;
|
|
145
|
+
if (!aIsHome && bIsHome)
|
|
146
|
+
return 1;
|
|
147
|
+
// If both have same home priority, sort by last accessed
|
|
148
|
+
return new Date(b.lastAccessed).getTime() - new Date(a.lastAccessed).getTime();
|
|
149
|
+
});
|
|
150
|
+
return { matches: prioritizedMatches, isExactMatch: true };
|
|
151
|
+
}
|
|
152
|
+
// Priority 3: Basename match (match against the last component of paths)
|
|
153
|
+
const basenameMatches = allProjects.filter(project => {
|
|
154
|
+
const pathBasename = path.basename(project.path).toLowerCase();
|
|
155
|
+
const realPathBasename = project.realPath ? path.basename(project.realPath).toLowerCase() : '';
|
|
156
|
+
return pathBasename === identifierLower || realPathBasename === identifierLower;
|
|
157
|
+
});
|
|
158
|
+
if (basenameMatches.length > 0) {
|
|
159
|
+
// Prioritize basename matches the same way
|
|
160
|
+
const prioritizedMatches = basenameMatches.sort((a, b) => {
|
|
161
|
+
const aIsHome = a.path.includes('/home/') || a.path.includes('~');
|
|
162
|
+
const bIsHome = b.path.includes('/home/') || b.path.includes('~');
|
|
163
|
+
if (aIsHome && !bIsHome)
|
|
164
|
+
return -1;
|
|
165
|
+
if (!aIsHome && bIsHome)
|
|
166
|
+
return 1;
|
|
167
|
+
return new Date(b.lastAccessed).getTime() - new Date(a.lastAccessed).getTime();
|
|
168
|
+
});
|
|
169
|
+
return { matches: prioritizedMatches, isExactMatch: true };
|
|
170
|
+
}
|
|
171
|
+
// Priority 4: Partial matches (only if no exact matches found)
|
|
172
|
+
// This matches identifier as a substring of directory names
|
|
173
|
+
const partialDirMatches = allProjects.filter(project => project.dirName.toLowerCase().includes(identifierLower) ||
|
|
174
|
+
identifierLower.includes(project.dirName.toLowerCase()));
|
|
175
|
+
// Priority 5: Partial basename matches
|
|
176
|
+
const partialBasenameMatches = allProjects.filter(project => {
|
|
177
|
+
const pathBasename = path.basename(project.path).toLowerCase();
|
|
178
|
+
const realPathBasename = project.realPath ? path.basename(project.realPath).toLowerCase() : '';
|
|
179
|
+
return pathBasename.includes(identifierLower) ||
|
|
180
|
+
identifierLower.includes(pathBasename) ||
|
|
181
|
+
realPathBasename.includes(identifierLower) ||
|
|
182
|
+
identifierLower.includes(realPathBasename);
|
|
183
|
+
});
|
|
184
|
+
// Combine all partial matches and remove duplicates, then prioritize
|
|
185
|
+
const allPartialMatches = [...new Set([...partialDirMatches, ...partialBasenameMatches])];
|
|
186
|
+
const prioritizedPartialMatches = allPartialMatches.sort((a, b) => {
|
|
187
|
+
const aIsHome = a.path.includes('/home/') || a.path.includes('~');
|
|
188
|
+
const bIsHome = b.path.includes('/home/') || b.path.includes('~');
|
|
189
|
+
if (aIsHome && !bIsHome)
|
|
190
|
+
return -1;
|
|
191
|
+
if (!aIsHome && bIsHome)
|
|
192
|
+
return 1;
|
|
193
|
+
return new Date(b.lastAccessed).getTime() - new Date(a.lastAccessed).getTime();
|
|
194
|
+
});
|
|
195
|
+
return { matches: prioritizedPartialMatches, isExactMatch: false };
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Create project selection message for multiple matches
|
|
199
|
+
*/
|
|
200
|
+
function createProjectSelectionMessage(matches) {
|
|
201
|
+
const projectList = matches.map((project, index) => {
|
|
202
|
+
const pathInfo = project.realPath ? ` (${project.realPath})` : '';
|
|
203
|
+
return `${index + 1}. **${project.name}** (\`${project.dirName}\`${pathInfo})`;
|
|
204
|
+
}).join('\n');
|
|
205
|
+
return `🎯 **找到多个匹配的项目,请选择:**\n\n${projectList}\n\n📝 **使用方法:**\n• 指定目录名:\`proj:目录名\`\n• 或指定完整路径:\`proj:/完整/路径\``;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Create project not found message
|
|
209
|
+
*/
|
|
210
|
+
function createProjectNotFoundMessage(identifier, availableProjects) {
|
|
211
|
+
const sampleProjects = availableProjects.slice(0, 5).map(project => `• \`${project.dirName}\` - ${project.name}`).join('\n');
|
|
212
|
+
return `❌ **未找到项目 "${identifier}"**\n\n📂 **可用项目:**\n${sampleProjects}${availableProjects.length > 5 ? `\n... 还有 ${availableProjects.length - 5} 个项目` : ''}\n\n💡 **提示:** 使用项目目录名或完整路径来指定项目`;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Get available agents list for Slack response
|
|
216
|
+
*/
|
|
217
|
+
function getAvailableAgentsList(allAgents) {
|
|
218
|
+
const enabledAgents = allAgents.filter(a => a.enabled);
|
|
219
|
+
return enabledAgents.map(agent => `• **${agent.name}** (\`${agent.id}\`) - ${agent.description}`).join('\n');
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Slack AI Service - Main adapter class
|
|
223
|
+
*/
|
|
224
|
+
class SlackAIService {
|
|
225
|
+
slackClient;
|
|
226
|
+
agentStorage;
|
|
227
|
+
projectStorage;
|
|
228
|
+
defaultAgentId;
|
|
229
|
+
defaultProjectPath = null;
|
|
230
|
+
constructor(botToken, defaultAgentId = 'general-chat') {
|
|
231
|
+
this.slackClient = new slackClient_js_1.SlackClient(botToken);
|
|
232
|
+
this.agentStorage = new agentStorage_js_1.AgentStorage();
|
|
233
|
+
this.projectStorage = new projectMetadataStorage_js_1.ProjectMetadataStorage();
|
|
234
|
+
this.defaultAgentId = defaultAgentId;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Get or create default project for Slack
|
|
238
|
+
*/
|
|
239
|
+
async getDefaultProject() {
|
|
240
|
+
// Check if already cached
|
|
241
|
+
if (this.defaultProjectPath) {
|
|
242
|
+
const allProjects = this.projectStorage.getAllProjects();
|
|
243
|
+
const cachedProject = allProjects.find(p => p.realPath === this.defaultProjectPath || p.path === this.defaultProjectPath);
|
|
244
|
+
if (cachedProject) {
|
|
245
|
+
return cachedProject;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// Priority 1: Check configuration (from env or config.json)
|
|
249
|
+
const { defaultProject: envProjectPath } = await (0, index_js_1.getSlackConfig)();
|
|
250
|
+
if (envProjectPath) {
|
|
251
|
+
console.log(`📂 Found SLACK_DEFAULT_PROJECT config: ${envProjectPath}`);
|
|
252
|
+
// Check if this path exists in projects
|
|
253
|
+
const allProjects = this.projectStorage.getAllProjects();
|
|
254
|
+
const envProject = allProjects.find(p => p.realPath === envProjectPath || p.path === envProjectPath);
|
|
255
|
+
if (envProject) {
|
|
256
|
+
this.defaultProjectPath = envProject.realPath || envProject.path;
|
|
257
|
+
console.log(`✅ Using default project from config: ${envProject.name}`);
|
|
258
|
+
return envProject;
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
console.warn(`⚠️ SLACK_DEFAULT_PROJECT path not found in projects: ${envProjectPath}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Priority 2: Use or create slack-app project in claude-code-projects
|
|
265
|
+
const homeDir = require('os').homedir();
|
|
266
|
+
const projectsDir = path.join(homeDir, 'claude-code-projects');
|
|
267
|
+
const slackAppPath = path.join(projectsDir, 'slack-app');
|
|
268
|
+
// Ensure claude-code-projects directory exists
|
|
269
|
+
if (!fs.existsSync(projectsDir)) {
|
|
270
|
+
console.log(`📁 Creating claude-code-projects directory: ${projectsDir}`);
|
|
271
|
+
fs.mkdirSync(projectsDir, { recursive: true });
|
|
272
|
+
}
|
|
273
|
+
// Ensure slack-app directory exists
|
|
274
|
+
if (!fs.existsSync(slackAppPath)) {
|
|
275
|
+
console.log(`📁 Creating default Slack project: ${slackAppPath}`);
|
|
276
|
+
fs.mkdirSync(slackAppPath, { recursive: true });
|
|
277
|
+
// Create a README.md to explain this directory
|
|
278
|
+
const readmePath = path.join(slackAppPath, 'README.md');
|
|
279
|
+
const readmeContent = `# Slack App Default Project
|
|
280
|
+
|
|
281
|
+
This is the default project directory for Slack App interactions.
|
|
282
|
+
|
|
283
|
+
When you chat with the AI in Slack without specifying a project (using \`proj:\`),
|
|
284
|
+
this directory will be used as the working directory.
|
|
285
|
+
|
|
286
|
+
## Customizing the Default Project
|
|
287
|
+
|
|
288
|
+
You can change the default project by:
|
|
289
|
+
|
|
290
|
+
1. **Environment Variable**: Set \`SLACK_DEFAULT_PROJECT\` to your desired project path
|
|
291
|
+
\`\`\`bash
|
|
292
|
+
export SLACK_DEFAULT_PROJECT=/path/to/your/project
|
|
293
|
+
\`\`\`
|
|
294
|
+
|
|
295
|
+
2. **Specify in Message**: Use \`proj:project-name\` in your Slack message
|
|
296
|
+
\`\`\`
|
|
297
|
+
@bot proj:my-project help me with this code
|
|
298
|
+
\`\`\`
|
|
299
|
+
|
|
300
|
+
## Project Structure
|
|
301
|
+
|
|
302
|
+
Feel free to organize your files here as needed. This directory is managed by AgentStudio.
|
|
303
|
+
`;
|
|
304
|
+
fs.writeFileSync(readmePath, readmeContent, 'utf-8');
|
|
305
|
+
console.log(`📝 Created README.md in ${slackAppPath}`);
|
|
306
|
+
}
|
|
307
|
+
// Check if slack-app exists in projects metadata
|
|
308
|
+
const allProjects = this.projectStorage.getAllProjects();
|
|
309
|
+
let slackAppProject = allProjects.find(p => p.realPath === slackAppPath || p.path === slackAppPath || p.dirName === 'slack-app');
|
|
310
|
+
if (!slackAppProject) {
|
|
311
|
+
// Project directory exists but not in metadata, it will be picked up on next scan
|
|
312
|
+
// For now, create a minimal project info
|
|
313
|
+
console.log(`🔄 Slack-app directory exists but not in metadata, will be picked up on next scan`);
|
|
314
|
+
// Try to get it from storage (in case it was just added)
|
|
315
|
+
const metadata = this.projectStorage.getProjectMetadata(slackAppPath);
|
|
316
|
+
if (metadata) {
|
|
317
|
+
// Construct a minimal project info
|
|
318
|
+
slackAppProject = {
|
|
319
|
+
id: metadata.id,
|
|
320
|
+
name: metadata.name || 'Slack App',
|
|
321
|
+
description: metadata.description || 'Default project for Slack interactions',
|
|
322
|
+
path: slackAppPath,
|
|
323
|
+
realPath: slackAppPath,
|
|
324
|
+
dirName: 'slack-app',
|
|
325
|
+
createdAt: metadata.createdAt,
|
|
326
|
+
lastAccessed: metadata.lastAccessed,
|
|
327
|
+
agents: [],
|
|
328
|
+
defaultAgent: metadata.defaultAgent || '',
|
|
329
|
+
defaultAgentName: '',
|
|
330
|
+
defaultAgentIcon: '',
|
|
331
|
+
tags: metadata.tags || [],
|
|
332
|
+
metadata: metadata.metadata || {}
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (!slackAppProject) {
|
|
337
|
+
console.error(`❌ Failed to create or find slack-app project`);
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
this.defaultProjectPath = slackAppProject.realPath || slackAppProject.path;
|
|
341
|
+
console.log(`✅ Using default Slack project: ${slackAppProject.name} at ${this.defaultProjectPath}`);
|
|
342
|
+
return slackAppProject;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Parse and validate message context
|
|
346
|
+
*/
|
|
347
|
+
async parseMessageContext(event) {
|
|
348
|
+
const threadTs = event.thread_ts || event.ts;
|
|
349
|
+
const isNewThread = !event.thread_ts;
|
|
350
|
+
// Get all available agents and projects
|
|
351
|
+
const allAgents = this.agentStorage.getAllAgents();
|
|
352
|
+
const enabledAgents = allAgents.filter((agent) => agent.enabled);
|
|
353
|
+
const allProjects = this.projectStorage.getAllProjects();
|
|
354
|
+
// Parse agent from message
|
|
355
|
+
const agentSelection = parseAgentFromMessage(event.text, enabledAgents);
|
|
356
|
+
// Start with the cleaned text from agent parsing (if available)
|
|
357
|
+
let cleanText = agentSelection ? agentSelection.cleanText : event.text;
|
|
358
|
+
// Check if this thread already has a session with project info
|
|
359
|
+
const existingSessionId = slackThreadMapper_js_1.slackThreadMapper.getSessionId(threadTs, event.channel);
|
|
360
|
+
const existingMapping = existingSessionId
|
|
361
|
+
? slackThreadMapper_js_1.slackThreadMapper.getThreadForSession(existingSessionId)
|
|
362
|
+
: null;
|
|
363
|
+
const hasExistingProject = existingMapping && existingMapping.projectPath;
|
|
364
|
+
// Parse project from message
|
|
365
|
+
// Parse for: new threads OR threads without existing project
|
|
366
|
+
let selectedProject = null;
|
|
367
|
+
if (isNewThread || !hasExistingProject) {
|
|
368
|
+
// Parse project from the already-cleaned text
|
|
369
|
+
const projectSelection = parseProjectFromMessage(cleanText);
|
|
370
|
+
if (projectSelection) {
|
|
371
|
+
console.log(`🎯 Found project specification: ${projectSelection.projectIdentifier}`);
|
|
372
|
+
// Match project against available projects
|
|
373
|
+
const projectMatch = matchProject(projectSelection.projectIdentifier, allProjects);
|
|
374
|
+
if (projectMatch.matches.length === 0) {
|
|
375
|
+
// No projects found
|
|
376
|
+
const errorMessage = createProjectNotFoundMessage(projectSelection.projectIdentifier, allProjects);
|
|
377
|
+
await this.slackClient.postMessage({
|
|
378
|
+
channel: event.channel,
|
|
379
|
+
text: errorMessage,
|
|
380
|
+
thread_ts: threadTs
|
|
381
|
+
});
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
384
|
+
else if (projectMatch.matches.length > 1 && !projectMatch.isExactMatch) {
|
|
385
|
+
// Multiple partial matches found - ask user to be more specific
|
|
386
|
+
const selectionMessage = createProjectSelectionMessage(projectMatch.matches);
|
|
387
|
+
await this.slackClient.postMessage({
|
|
388
|
+
channel: event.channel,
|
|
389
|
+
text: selectionMessage,
|
|
390
|
+
thread_ts: threadTs
|
|
391
|
+
});
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
// Single match found, or multiple exact matches (already prioritized)
|
|
396
|
+
selectedProject = projectMatch.matches[0];
|
|
397
|
+
console.log(`✅ Selected project: ${selectedProject.name} (${selectedProject.dirName}) - Path: ${selectedProject.realPath || selectedProject.path}`);
|
|
398
|
+
// If there were multiple exact matches, log this for debugging
|
|
399
|
+
if (projectMatch.matches.length > 1) {
|
|
400
|
+
console.log(`📝 Note: Found ${projectMatch.matches.length} exact matches, selected the highest priority one`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
// Update cleanText with project specification removed
|
|
404
|
+
cleanText = projectSelection.cleanText;
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
// No project specified, use default project
|
|
408
|
+
console.log(`📂 No project specified, using default project`);
|
|
409
|
+
selectedProject = await this.getDefaultProject();
|
|
410
|
+
if (selectedProject) {
|
|
411
|
+
console.log(`✅ Using default project: ${selectedProject.name} at ${selectedProject.realPath || selectedProject.path}`);
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
console.warn(`⚠️ Failed to get default project`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
// Thread already has a project, use it from existing mapping
|
|
420
|
+
if (existingMapping && existingMapping.projectPath) {
|
|
421
|
+
console.log(`♻️ Reusing project from existing thread: ${existingMapping.projectPath}`);
|
|
422
|
+
// Find the project in allProjects
|
|
423
|
+
const existingProject = allProjects.find(p => p.realPath === existingMapping.projectPath ||
|
|
424
|
+
p.path === existingMapping.projectPath);
|
|
425
|
+
if (existingProject) {
|
|
426
|
+
selectedProject = existingProject;
|
|
427
|
+
console.log(`✅ Found existing project: ${existingProject.name} (${existingProject.dirName})`);
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
console.warn(`⚠️ Existing project path not found in projects list: ${existingMapping.projectPath}`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// Determine agent to use
|
|
435
|
+
let agentId;
|
|
436
|
+
if (agentSelection) {
|
|
437
|
+
agentId = agentSelection.agentId;
|
|
438
|
+
console.log(`🎯 Selected agent: ${agentId} from message`);
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
// Try to get agent from existing session
|
|
442
|
+
const sessionId = slackThreadMapper_js_1.slackThreadMapper.getSessionId(threadTs, event.channel);
|
|
443
|
+
if (sessionId) {
|
|
444
|
+
const existingSession = sessionManager_js_1.sessionManager.getSession(sessionId);
|
|
445
|
+
if (existingSession) {
|
|
446
|
+
agentId = existingSession.getAgentId();
|
|
447
|
+
console.log(`♻️ Reusing agent from existing session: ${agentId}`);
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
agentId = this.defaultAgentId;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
agentId = this.defaultAgentId;
|
|
455
|
+
}
|
|
456
|
+
// Validate default agent
|
|
457
|
+
const defaultAgent = this.agentStorage.getAgent(agentId);
|
|
458
|
+
if (!defaultAgent || !defaultAgent.enabled) {
|
|
459
|
+
// Show available agents list
|
|
460
|
+
const agentsList = getAvailableAgentsList(allAgents);
|
|
461
|
+
await this.slackClient.postMessage({
|
|
462
|
+
channel: event.channel,
|
|
463
|
+
text: `🤖 **请选择你想要使用的AI助手:**\n\n${agentsList}\n\n📝 **使用方法:**\n• 直接提及:\`@机器人 ppt-editor 请帮我创建幻灯片\`\n• 或使用别名:\`@机器人 ppt 请帮我创建幻灯片\`\n• 通用对话:\`@机器人 general 随便聊聊\``,
|
|
464
|
+
thread_ts: threadTs
|
|
465
|
+
});
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
console.log(`🔧 Using default agent: ${agentId}`);
|
|
469
|
+
}
|
|
470
|
+
// Get and validate agent
|
|
471
|
+
const agent = this.agentStorage.getAgent(agentId);
|
|
472
|
+
if (!agent) {
|
|
473
|
+
await this.slackClient.postMessage({
|
|
474
|
+
channel: event.channel,
|
|
475
|
+
text: `❌ Agent **${agentId}** not found.`,
|
|
476
|
+
thread_ts: threadTs
|
|
477
|
+
});
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
if (!agent.enabled) {
|
|
481
|
+
await this.slackClient.postMessage({
|
|
482
|
+
channel: event.channel,
|
|
483
|
+
text: `⚠️ Agent **${agent.name}** is currently disabled.`,
|
|
484
|
+
thread_ts: threadTs
|
|
485
|
+
});
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
488
|
+
return {
|
|
489
|
+
threadTs,
|
|
490
|
+
isNewThread,
|
|
491
|
+
agentId,
|
|
492
|
+
agent,
|
|
493
|
+
selectedProject,
|
|
494
|
+
cleanText
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Process Slack files and convert to image format for Claude
|
|
499
|
+
*/
|
|
500
|
+
async processSlackFiles(files) {
|
|
501
|
+
const images = [];
|
|
502
|
+
// Filter for image files only
|
|
503
|
+
const imageFiles = files.filter(file => file.mimetype.startsWith('image/'));
|
|
504
|
+
if (imageFiles.length === 0) {
|
|
505
|
+
return images;
|
|
506
|
+
}
|
|
507
|
+
console.log(`📷 Processing ${imageFiles.length} image(s) from Slack`);
|
|
508
|
+
for (const file of imageFiles) {
|
|
509
|
+
try {
|
|
510
|
+
console.log(`📥 Downloading image: ${file.name} (${file.mimetype}, ${file.size} bytes)`);
|
|
511
|
+
// Download file from Slack
|
|
512
|
+
const fileData = await this.slackClient.downloadFile(file.url_private_download);
|
|
513
|
+
// Convert to base64
|
|
514
|
+
const base64Data = fileData.toString('base64');
|
|
515
|
+
images.push({
|
|
516
|
+
id: file.id,
|
|
517
|
+
mediaType: file.mimetype,
|
|
518
|
+
filename: file.name,
|
|
519
|
+
data: base64Data
|
|
520
|
+
});
|
|
521
|
+
console.log(`✅ Successfully processed image: ${file.name}`);
|
|
522
|
+
}
|
|
523
|
+
catch (error) {
|
|
524
|
+
console.error(`❌ Failed to process image ${file.name}:`, error);
|
|
525
|
+
// Continue processing other images
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return images;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Get default Claude version configuration
|
|
532
|
+
*/
|
|
533
|
+
async getClaudeVersionConfig() {
|
|
534
|
+
try {
|
|
535
|
+
const defaultVersionId = await (0, claudeVersionStorage_js_1.getDefaultVersionId)();
|
|
536
|
+
if (defaultVersionId) {
|
|
537
|
+
const defaultVersion = await (0, claudeVersionStorage_js_1.getVersionByIdInternal)(defaultVersionId);
|
|
538
|
+
if (defaultVersion) {
|
|
539
|
+
const model = defaultVersion.models && defaultVersion.models.length > 0
|
|
540
|
+
? defaultVersion.models[0].id
|
|
541
|
+
: undefined;
|
|
542
|
+
console.log(`🎯 Using default Claude version: ${defaultVersion.alias}${model ? ` with model: ${model}` : ''}`);
|
|
543
|
+
return {
|
|
544
|
+
versionId: defaultVersion.id,
|
|
545
|
+
model,
|
|
546
|
+
env: defaultVersion.environmentVariables || null
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
catch (error) {
|
|
552
|
+
console.error('Failed to get default Claude version:', error);
|
|
553
|
+
}
|
|
554
|
+
return { env: null };
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Acquire session lock or send busy message
|
|
558
|
+
*/
|
|
559
|
+
async acquireSessionLock(sessionId, event, threadTs, agentId, placeholderTs, agentDisplayName) {
|
|
560
|
+
const lockStatus = slackSessionLock_js_1.slackSessionLock.isSessionLocked(sessionId, true);
|
|
561
|
+
if (lockStatus.locked) {
|
|
562
|
+
console.log(`⚠️ Session ${sessionId} is locked (${lockStatus.reason}), returning busy message`);
|
|
563
|
+
await this.slackClient.updateMessage({
|
|
564
|
+
channel: event.channel,
|
|
565
|
+
ts: placeholderTs,
|
|
566
|
+
text: `🚦 ${agentDisplayName} 正在处理其他消息,请稍后再试...`
|
|
567
|
+
});
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
const lockAcquired = slackSessionLock_js_1.slackSessionLock.tryAcquireLock(sessionId, {
|
|
571
|
+
sessionId,
|
|
572
|
+
threadTs,
|
|
573
|
+
channel: event.channel,
|
|
574
|
+
agentId
|
|
575
|
+
});
|
|
576
|
+
if (!lockAcquired) {
|
|
577
|
+
console.log(`⚠️ Failed to acquire lock for session ${sessionId}, returning busy message`);
|
|
578
|
+
await this.slackClient.updateMessage({
|
|
579
|
+
channel: event.channel,
|
|
580
|
+
ts: placeholderTs,
|
|
581
|
+
text: `🚦 ${agentDisplayName} 正在处理其他消息,请稍后再试...`
|
|
582
|
+
});
|
|
583
|
+
return false;
|
|
584
|
+
}
|
|
585
|
+
console.log(`🔒 Acquired lock for session ${sessionId}`);
|
|
586
|
+
return true;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Format tool call for display
|
|
590
|
+
*/
|
|
591
|
+
formatToolCall(toolName, input) {
|
|
592
|
+
if (!input || typeof input !== 'object') {
|
|
593
|
+
return `🔧 ${toolName}()`;
|
|
594
|
+
}
|
|
595
|
+
// Define large content parameters that should always be hidden
|
|
596
|
+
const largeContentParams = {
|
|
597
|
+
'Write': ['content', 'contents'],
|
|
598
|
+
'write': ['content', 'contents'],
|
|
599
|
+
'search_replace': ['old_string', 'new_string']
|
|
600
|
+
};
|
|
601
|
+
// Determine threshold for "large" content
|
|
602
|
+
const largeContentThreshold = 50; // chars
|
|
603
|
+
// Extract key parameters (limit to avoid too long output)
|
|
604
|
+
const params = [];
|
|
605
|
+
const keys = Object.keys(input);
|
|
606
|
+
// Check if this tool has large content parameters
|
|
607
|
+
const largeParams = largeContentParams[toolName] || [];
|
|
608
|
+
// Filter out large content params if they exceed threshold
|
|
609
|
+
const displayKeys = [];
|
|
610
|
+
for (const key of keys) {
|
|
611
|
+
if (largeParams.includes(key)) {
|
|
612
|
+
// Check if this parameter is large
|
|
613
|
+
const value = input[key];
|
|
614
|
+
if (typeof value === 'string') {
|
|
615
|
+
// If content is large (multi-line or long), skip it from display
|
|
616
|
+
if (value.length > largeContentThreshold || value.includes('\n')) {
|
|
617
|
+
continue; // Skip this parameter, will show in summary
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
displayKeys.push(key);
|
|
622
|
+
if (displayKeys.length >= 3)
|
|
623
|
+
break; // Limit to 3 displayed params
|
|
624
|
+
}
|
|
625
|
+
// Format the displayed parameters
|
|
626
|
+
for (const key of displayKeys) {
|
|
627
|
+
let value = input[key];
|
|
628
|
+
// Simplify long values
|
|
629
|
+
if (typeof value === 'string') {
|
|
630
|
+
if (value.length > 50) {
|
|
631
|
+
value = value.substring(0, 47) + '...';
|
|
632
|
+
}
|
|
633
|
+
value = `"${value}"`;
|
|
634
|
+
}
|
|
635
|
+
else if (typeof value === 'object') {
|
|
636
|
+
const jsonStr = JSON.stringify(value);
|
|
637
|
+
if (jsonStr.length > 50) {
|
|
638
|
+
value = jsonStr.substring(0, 47) + '...';
|
|
639
|
+
}
|
|
640
|
+
else {
|
|
641
|
+
value = jsonStr;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
params.push(`${key}=${value}`);
|
|
645
|
+
}
|
|
646
|
+
// Add summary for hidden large params
|
|
647
|
+
const hiddenLargeParams = [];
|
|
648
|
+
if (toolName === 'Write' || toolName === 'write') {
|
|
649
|
+
if (input.content && displayKeys.indexOf('content') === -1) {
|
|
650
|
+
hiddenLargeParams.push(`content: ${input.content.length} chars`);
|
|
651
|
+
}
|
|
652
|
+
if (input.contents && displayKeys.indexOf('contents') === -1) {
|
|
653
|
+
hiddenLargeParams.push(`contents: ${input.contents.length} chars`);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
if (toolName === 'search_replace') {
|
|
657
|
+
if (input.old_string && displayKeys.indexOf('old_string') === -1) {
|
|
658
|
+
hiddenLargeParams.push(`old: ${input.old_string.length} chars`);
|
|
659
|
+
}
|
|
660
|
+
if (input.new_string && displayKeys.indexOf('new_string') === -1) {
|
|
661
|
+
hiddenLargeParams.push(`new: ${input.new_string.length} chars`);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
const moreParamsInfo = hiddenLargeParams.length > 0
|
|
665
|
+
? `, ${hiddenLargeParams.join(', ')}`
|
|
666
|
+
: (Object.keys(input).length > displayKeys.length ? ', ...' : '');
|
|
667
|
+
return `🔧 ${toolName}(${params.join(', ')}${moreParamsInfo})`;
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Build status message from current state
|
|
671
|
+
*/
|
|
672
|
+
buildStatusMessage(thinkingContent, fullResponse) {
|
|
673
|
+
let statusText = '';
|
|
674
|
+
// Add thinking content if exists
|
|
675
|
+
if (thinkingContent) {
|
|
676
|
+
statusText += `💭 **思考中...**\n${thinkingContent}\n\n`;
|
|
677
|
+
}
|
|
678
|
+
// Add response text (which now includes tool calls in order)
|
|
679
|
+
if (fullResponse) {
|
|
680
|
+
statusText += fullResponse;
|
|
681
|
+
}
|
|
682
|
+
// If nothing to show yet, keep the thinking message
|
|
683
|
+
if (!statusText.trim()) {
|
|
684
|
+
statusText = '🤔 正在思考...';
|
|
685
|
+
}
|
|
686
|
+
// Debug log
|
|
687
|
+
console.log('📄 Building status message:', {
|
|
688
|
+
hasThinking: !!thinkingContent,
|
|
689
|
+
hasResponse: !!fullResponse,
|
|
690
|
+
statusTextLength: statusText.length
|
|
691
|
+
});
|
|
692
|
+
return statusText;
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Create Slack message updater with throttling
|
|
696
|
+
*/
|
|
697
|
+
createSlackMessageUpdater(event, placeholderTs, stateRef, updateThrottleMs = 1000) {
|
|
698
|
+
return async (force = false) => {
|
|
699
|
+
const now = Date.now();
|
|
700
|
+
// Throttle updates unless forced
|
|
701
|
+
if (!force && now - stateRef.lastUpdateTime < updateThrottleMs) {
|
|
702
|
+
stateRef.pendingUpdate = true;
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
stateRef.pendingUpdate = false;
|
|
706
|
+
stateRef.lastUpdateTime = now;
|
|
707
|
+
const statusText = this.buildStatusMessage(stateRef.thinkingContent, stateRef.fullResponse);
|
|
708
|
+
try {
|
|
709
|
+
await this.slackClient.updateMessage({
|
|
710
|
+
channel: event.channel,
|
|
711
|
+
ts: placeholderTs,
|
|
712
|
+
text: statusText
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
catch (error) {
|
|
716
|
+
console.error('❌ Failed to update Slack message:', error);
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Handle Claude init message
|
|
722
|
+
*/
|
|
723
|
+
handleInitMessage(sdkMessage, claudeSession, event, threadTs, agentId, selectedProject) {
|
|
724
|
+
if (sdkMessage.type === 'system' && sdkMessage.subtype === 'init' && sdkMessage.session_id) {
|
|
725
|
+
const newSessionId = sdkMessage.session_id;
|
|
726
|
+
claudeSession.setClaudeSessionId(newSessionId);
|
|
727
|
+
sessionManager_js_1.sessionManager.confirmSessionId(claudeSession, newSessionId);
|
|
728
|
+
// Update mapping with project information
|
|
729
|
+
slackThreadMapper_js_1.slackThreadMapper.setMapping({
|
|
730
|
+
threadTs,
|
|
731
|
+
channel: event.channel,
|
|
732
|
+
sessionId: newSessionId,
|
|
733
|
+
agentId,
|
|
734
|
+
projectId: selectedProject?.dirName,
|
|
735
|
+
projectPath: selectedProject?.realPath || selectedProject?.path
|
|
736
|
+
});
|
|
737
|
+
console.log(`✅ Session confirmed: ${newSessionId} for thread: ${threadTs}`);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Handle Claude thinking message
|
|
742
|
+
*/
|
|
743
|
+
handleThinkingMessage(sdkMessage, stateRef) {
|
|
744
|
+
if (sdkMessage.type === 'assistant' && sdkMessage.subtype === 'thinking') {
|
|
745
|
+
if (sdkMessage.thinking || sdkMessage.text) {
|
|
746
|
+
const thinkingText = sdkMessage.thinking || sdkMessage.text;
|
|
747
|
+
stateRef.thinkingContent = thinkingText;
|
|
748
|
+
console.log(`💭 Thinking: ${thinkingText.substring(0, 100)}...`);
|
|
749
|
+
return true; // Trigger update
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Extract text from assistant message
|
|
756
|
+
*/
|
|
757
|
+
extractTextFromAssistantMessage(sdkMessage) {
|
|
758
|
+
let newText = '';
|
|
759
|
+
// Extract text from message.content array (standard Claude SDK format)
|
|
760
|
+
if (sdkMessage.message?.content && Array.isArray(sdkMessage.message.content)) {
|
|
761
|
+
for (const block of sdkMessage.message.content) {
|
|
762
|
+
if (block.type === 'text' && block.text) {
|
|
763
|
+
newText += block.text;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
// Fallback: Try other formats
|
|
768
|
+
else if (sdkMessage.subtype === 'text' && sdkMessage.text) {
|
|
769
|
+
newText = sdkMessage.text;
|
|
770
|
+
}
|
|
771
|
+
else if (sdkMessage.message && typeof sdkMessage.message === 'string') {
|
|
772
|
+
newText = sdkMessage.message;
|
|
773
|
+
}
|
|
774
|
+
else if (sdkMessage.content) {
|
|
775
|
+
if (Array.isArray(sdkMessage.content)) {
|
|
776
|
+
for (const block of sdkMessage.content) {
|
|
777
|
+
if (block.type === 'text' && block.text) {
|
|
778
|
+
newText += block.text;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
else if (typeof sdkMessage.content === 'string') {
|
|
783
|
+
newText = sdkMessage.content;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
return newText;
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Handle Claude assistant message
|
|
790
|
+
*/
|
|
791
|
+
handleAssistantMessage(sdkMessage, stateRef) {
|
|
792
|
+
if (sdkMessage.type === 'assistant' && sdkMessage.subtype !== 'thinking') {
|
|
793
|
+
console.log('🔍 Assistant message details:', JSON.stringify({
|
|
794
|
+
type: sdkMessage.type,
|
|
795
|
+
subtype: sdkMessage.subtype,
|
|
796
|
+
hasContent: !!(sdkMessage.content || sdkMessage.message?.content),
|
|
797
|
+
contentLength: sdkMessage.content?.length || sdkMessage.message?.content?.length || 0
|
|
798
|
+
}, null, 2));
|
|
799
|
+
const newText = this.extractTextFromAssistantMessage(sdkMessage);
|
|
800
|
+
if (newText) {
|
|
801
|
+
stateRef.fullResponse += newText;
|
|
802
|
+
// Clear thinking when actual response starts
|
|
803
|
+
if (stateRef.thinkingContent) {
|
|
804
|
+
stateRef.thinkingContent = '';
|
|
805
|
+
}
|
|
806
|
+
return true; // Trigger update
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
return false;
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Handle Claude tool use message
|
|
813
|
+
* Appends tool calls to fullResponse in chronological order
|
|
814
|
+
*/
|
|
815
|
+
handleToolUseMessage(sdkMessage, stateRef) {
|
|
816
|
+
// Log full message for debugging
|
|
817
|
+
console.log('🔍 Checking for tool_use message:', JSON.stringify({
|
|
818
|
+
type: sdkMessage.type,
|
|
819
|
+
subtype: sdkMessage.subtype,
|
|
820
|
+
hasToolUse: !!sdkMessage.tool_use,
|
|
821
|
+
hasToolName: !!sdkMessage.tool_use?.name,
|
|
822
|
+
fullMessage: sdkMessage
|
|
823
|
+
}, null, 2));
|
|
824
|
+
if (sdkMessage.type === 'tool_use' && sdkMessage.subtype === 'start') {
|
|
825
|
+
const toolName = sdkMessage.tool_use?.name || 'unknown';
|
|
826
|
+
const toolInput = sdkMessage.tool_use?.input || {};
|
|
827
|
+
const formattedTool = this.formatToolCall(toolName, toolInput);
|
|
828
|
+
// Append to fullResponse to maintain chronological order
|
|
829
|
+
stateRef.fullResponse += `${stateRef.fullResponse ? '\n' : ''}${formattedTool}\n`;
|
|
830
|
+
// Clear thinking when tool starts
|
|
831
|
+
if (stateRef.thinkingContent) {
|
|
832
|
+
stateRef.thinkingContent = '';
|
|
833
|
+
}
|
|
834
|
+
console.log(`🔧 Tool started: ${toolName}, formatted: ${formattedTool}`);
|
|
835
|
+
console.log(`📝 Current fullResponse: ${stateRef.fullResponse}`);
|
|
836
|
+
return true; // Trigger update
|
|
837
|
+
}
|
|
838
|
+
// Also check for assistant message with tool_use content
|
|
839
|
+
if (sdkMessage.type === 'assistant' && sdkMessage.message?.content) {
|
|
840
|
+
const content = sdkMessage.message.content;
|
|
841
|
+
if (Array.isArray(content)) {
|
|
842
|
+
for (const block of content) {
|
|
843
|
+
if (block.type === 'tool_use') {
|
|
844
|
+
const toolName = block.name || 'unknown';
|
|
845
|
+
const toolInput = block.input || {};
|
|
846
|
+
const formattedTool = this.formatToolCall(toolName, toolInput);
|
|
847
|
+
// Append to fullResponse to maintain chronological order
|
|
848
|
+
stateRef.fullResponse += `${stateRef.fullResponse ? '\n' : ''}${formattedTool}\n`;
|
|
849
|
+
// Clear thinking when tool starts
|
|
850
|
+
if (stateRef.thinkingContent) {
|
|
851
|
+
stateRef.thinkingContent = '';
|
|
852
|
+
}
|
|
853
|
+
console.log(`🔧 Tool found in assistant content: ${toolName}, formatted: ${formattedTool}`);
|
|
854
|
+
console.log(`📝 Current fullResponse: ${stateRef.fullResponse}`);
|
|
855
|
+
return true; // Trigger update
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
return false;
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Process Claude response and collect text with real-time updates
|
|
864
|
+
*/
|
|
865
|
+
async processClaudeResponse(claudeSession, userMessage, event, threadTs, agentId, selectedProject, placeholderTs) {
|
|
866
|
+
const stateRef = {
|
|
867
|
+
fullResponse: '',
|
|
868
|
+
thinkingContent: '',
|
|
869
|
+
lastUpdateTime: 0,
|
|
870
|
+
pendingUpdate: false
|
|
871
|
+
};
|
|
872
|
+
let hasError = false;
|
|
873
|
+
let isResponseComplete = false;
|
|
874
|
+
const updateThrottleMs = 1000;
|
|
875
|
+
// Create update handler
|
|
876
|
+
const updateSlackMessage = this.createSlackMessageUpdater(event, placeholderTs, stateRef, updateThrottleMs);
|
|
877
|
+
return new Promise((resolve) => {
|
|
878
|
+
let timeoutId;
|
|
879
|
+
let updateIntervalId;
|
|
880
|
+
// Set up periodic update check for pending updates
|
|
881
|
+
updateIntervalId = setInterval(() => {
|
|
882
|
+
if (stateRef.pendingUpdate && !isResponseComplete) {
|
|
883
|
+
updateSlackMessage(false);
|
|
884
|
+
}
|
|
885
|
+
}, updateThrottleMs);
|
|
886
|
+
claudeSession.sendMessage(userMessage, async (sdkMessage) => {
|
|
887
|
+
console.log(`📦 Received SDK message type: ${sdkMessage.type}, subtype: ${sdkMessage.subtype}`);
|
|
888
|
+
// Clear any existing timeout
|
|
889
|
+
if (timeoutId) {
|
|
890
|
+
clearTimeout(timeoutId);
|
|
891
|
+
}
|
|
892
|
+
// Set a new timeout in case we don't get a result event
|
|
893
|
+
timeoutId = setTimeout(() => {
|
|
894
|
+
if (!isResponseComplete) {
|
|
895
|
+
console.log('⏰ Response timeout, treating as complete');
|
|
896
|
+
isResponseComplete = true;
|
|
897
|
+
clearInterval(updateIntervalId);
|
|
898
|
+
resolve({
|
|
899
|
+
fullResponse: stateRef.fullResponse,
|
|
900
|
+
toolUsageInfo: '', // No longer used, kept for interface compatibility
|
|
901
|
+
hasError
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
}, 30000); // 30 second timeout
|
|
905
|
+
// Handle init message
|
|
906
|
+
this.handleInitMessage(sdkMessage, claudeSession, event, threadTs, agentId, selectedProject);
|
|
907
|
+
// Handle thinking and trigger update if needed
|
|
908
|
+
if (this.handleThinkingMessage(sdkMessage, stateRef)) {
|
|
909
|
+
await updateSlackMessage(false);
|
|
910
|
+
}
|
|
911
|
+
// Handle assistant message and trigger update if needed
|
|
912
|
+
if (this.handleAssistantMessage(sdkMessage, stateRef)) {
|
|
913
|
+
await updateSlackMessage(false);
|
|
914
|
+
}
|
|
915
|
+
// Handle tool use and trigger update if needed
|
|
916
|
+
if (this.handleToolUseMessage(sdkMessage, stateRef)) {
|
|
917
|
+
await updateSlackMessage(false);
|
|
918
|
+
}
|
|
919
|
+
// Handle errors
|
|
920
|
+
if (sdkMessage.type === 'error') {
|
|
921
|
+
hasError = true;
|
|
922
|
+
console.error('❌ Claude error:', sdkMessage.error || sdkMessage.message);
|
|
923
|
+
isResponseComplete = true;
|
|
924
|
+
clearTimeout(timeoutId);
|
|
925
|
+
clearInterval(updateIntervalId);
|
|
926
|
+
// Final update with error
|
|
927
|
+
await updateSlackMessage(true);
|
|
928
|
+
resolve({
|
|
929
|
+
fullResponse: stateRef.fullResponse,
|
|
930
|
+
toolUsageInfo: '', // No longer used, kept for interface compatibility
|
|
931
|
+
hasError
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
// Check for completion
|
|
935
|
+
if (sdkMessage.type === 'result') {
|
|
936
|
+
console.log('✅ AI response completed');
|
|
937
|
+
isResponseComplete = true;
|
|
938
|
+
clearTimeout(timeoutId);
|
|
939
|
+
clearInterval(updateIntervalId);
|
|
940
|
+
// Final update
|
|
941
|
+
await updateSlackMessage(true);
|
|
942
|
+
resolve({
|
|
943
|
+
fullResponse: stateRef.fullResponse,
|
|
944
|
+
toolUsageInfo: '', // No longer used, kept for interface compatibility
|
|
945
|
+
hasError
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
}).catch((error) => {
|
|
949
|
+
console.error('❌ Error in sendMessage:', error);
|
|
950
|
+
hasError = true;
|
|
951
|
+
isResponseComplete = true;
|
|
952
|
+
if (timeoutId) {
|
|
953
|
+
clearTimeout(timeoutId);
|
|
954
|
+
}
|
|
955
|
+
if (updateIntervalId) {
|
|
956
|
+
clearInterval(updateIntervalId);
|
|
957
|
+
}
|
|
958
|
+
resolve({
|
|
959
|
+
fullResponse: stateRef.fullResponse,
|
|
960
|
+
toolUsageInfo: '', // No longer used, kept for interface compatibility
|
|
961
|
+
hasError: true
|
|
962
|
+
});
|
|
963
|
+
});
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Handle incoming Slack message
|
|
968
|
+
*/
|
|
969
|
+
async handleMessage(event) {
|
|
970
|
+
try {
|
|
971
|
+
console.log('📨 Received Slack message:', {
|
|
972
|
+
channel: event.channel,
|
|
973
|
+
user: event.user,
|
|
974
|
+
text: event.text.substring(0, 50),
|
|
975
|
+
thread_ts: event.thread_ts || event.ts
|
|
976
|
+
});
|
|
977
|
+
// Step 1: Parse and validate message context (agent, project, etc.)
|
|
978
|
+
const context = await this.parseMessageContext(event);
|
|
979
|
+
if (!context) {
|
|
980
|
+
return; // Early exit if parsing failed (error message already sent)
|
|
981
|
+
}
|
|
982
|
+
const { threadTs, agentId, agent, selectedProject, cleanText } = context;
|
|
983
|
+
// Step 2: Send "thinking" placeholder message
|
|
984
|
+
const agentDisplayName = agent.ui.icon ? `${agent.ui.icon} ${agent.name}` : agent.name;
|
|
985
|
+
const projectInfo = selectedProject ? ` 在项目 ${selectedProject.name} 中` : '';
|
|
986
|
+
const placeholderMsg = await this.slackClient.postMessage({
|
|
987
|
+
channel: event.channel,
|
|
988
|
+
text: `🤔 ${agentDisplayName}${projectInfo} 正在思考...`,
|
|
989
|
+
thread_ts: threadTs
|
|
990
|
+
});
|
|
991
|
+
console.log(`📍 Posted placeholder message: ${placeholderMsg.ts}`);
|
|
992
|
+
if (selectedProject) {
|
|
993
|
+
console.log(`📂 Working in project: ${selectedProject.name} (${selectedProject.dirName}) - Path: ${selectedProject.realPath || selectedProject.path}`);
|
|
994
|
+
}
|
|
995
|
+
// Step 3: Get Claude version configuration
|
|
996
|
+
const claudeConfig = await this.getClaudeVersionConfig();
|
|
997
|
+
// Step 4: Build query options with all necessary configurations
|
|
998
|
+
const projectPath = selectedProject ? (selectedProject.realPath || selectedProject.path) : undefined;
|
|
999
|
+
const { queryOptions } = await (0, claudeUtils_js_1.buildQueryOptions)(agent, selectedProject?.realPath || selectedProject?.path, undefined, // mcpTools
|
|
1000
|
+
undefined, // permissionMode
|
|
1001
|
+
claudeConfig.model, claudeConfig.versionId, claudeConfig.env || undefined // defaultEnv
|
|
1002
|
+
);
|
|
1003
|
+
// Slack uses block-based streaming (no partial messages)
|
|
1004
|
+
queryOptions.includePartialMessages = false;
|
|
1005
|
+
// Step 5: Get or create Claude session
|
|
1006
|
+
const sessionId = slackThreadMapper_js_1.slackThreadMapper.getSessionId(threadTs, event.channel);
|
|
1007
|
+
let claudeSession = sessionId ? sessionManager_js_1.sessionManager.getSession(sessionId) : null;
|
|
1008
|
+
if (!claudeSession) {
|
|
1009
|
+
claudeSession = sessionManager_js_1.sessionManager.createNewSession(agentId, queryOptions);
|
|
1010
|
+
console.log(`🆕 Created new Claude session for Slack thread: ${threadTs}`);
|
|
1011
|
+
}
|
|
1012
|
+
else {
|
|
1013
|
+
console.log(`♻️ Reusing existing Claude session: ${sessionId}`);
|
|
1014
|
+
}
|
|
1015
|
+
// Step 6: Acquire session lock
|
|
1016
|
+
const finalSessionId = claudeSession.getClaudeSessionId() || sessionId;
|
|
1017
|
+
let lockAcquired = false;
|
|
1018
|
+
if (finalSessionId) {
|
|
1019
|
+
lockAcquired = await this.acquireSessionLock(finalSessionId, event, threadTs, agentId, placeholderMsg.ts, agentDisplayName);
|
|
1020
|
+
if (!lockAcquired) {
|
|
1021
|
+
return; // Lock acquisition failed, busy message already sent
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
try {
|
|
1025
|
+
// Step 7: Process images if present
|
|
1026
|
+
let images = [];
|
|
1027
|
+
if (event.files && event.files.length > 0) {
|
|
1028
|
+
images = await this.processSlackFiles(event.files);
|
|
1029
|
+
if (images.length > 0) {
|
|
1030
|
+
console.log(`📸 Processed ${images.length} image(s) for Claude`);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
// Step 8: Build user message with images support
|
|
1034
|
+
const userMessage = await (0, sessionUtils_js_1.buildUserMessageContent)(cleanText, images.length > 0 ? images : undefined, claudeConfig.model, projectPath, claudeConfig.versionId);
|
|
1035
|
+
// Step 9: Process Claude response with real-time updates
|
|
1036
|
+
const { fullResponse, toolUsageInfo, hasError } = await this.processClaudeResponse(claudeSession, userMessage, event, threadTs, agentId, selectedProject, placeholderMsg.ts // Pass placeholder message timestamp for real-time updates
|
|
1037
|
+
);
|
|
1038
|
+
// Step 10: Update Slack message with final response
|
|
1039
|
+
let finalText = fullResponse || '✅ 完成';
|
|
1040
|
+
if (toolUsageInfo) {
|
|
1041
|
+
finalText += `\n\n${toolUsageInfo}`;
|
|
1042
|
+
}
|
|
1043
|
+
if (hasError) {
|
|
1044
|
+
finalText = '❌ 处理请求时发生错误,请稍后重试';
|
|
1045
|
+
}
|
|
1046
|
+
await this.slackClient.updateMessage({
|
|
1047
|
+
channel: event.channel,
|
|
1048
|
+
ts: placeholderMsg.ts,
|
|
1049
|
+
text: finalText
|
|
1050
|
+
});
|
|
1051
|
+
console.log(`✅ Updated Slack message with AI response (${fullResponse.length} chars)`);
|
|
1052
|
+
}
|
|
1053
|
+
catch (error) {
|
|
1054
|
+
console.error('❌ Error during Claude processing:', error);
|
|
1055
|
+
await this.slackClient.updateMessage({
|
|
1056
|
+
channel: event.channel,
|
|
1057
|
+
ts: placeholderMsg.ts,
|
|
1058
|
+
text: `❌ 错误: ${error instanceof Error ? error.message : '未知错误'}`
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
finally {
|
|
1062
|
+
// Step 11: Release session lock
|
|
1063
|
+
if (finalSessionId && lockAcquired) {
|
|
1064
|
+
const released = slackSessionLock_js_1.slackSessionLock.releaseLock(finalSessionId);
|
|
1065
|
+
if (released) {
|
|
1066
|
+
console.log(`🔓 Released lock for session ${finalSessionId}`);
|
|
1067
|
+
}
|
|
1068
|
+
else {
|
|
1069
|
+
console.log(`⚠️ Failed to release lock for session ${finalSessionId}`);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
catch (error) {
|
|
1075
|
+
console.error('❌ Error handling Slack message:', error);
|
|
1076
|
+
// Try to send error message to Slack
|
|
1077
|
+
try {
|
|
1078
|
+
await this.slackClient.postMessage({
|
|
1079
|
+
channel: event.channel,
|
|
1080
|
+
text: `❌ 处理消息时发生错误: ${error instanceof Error ? error.message : '未知错误'}`,
|
|
1081
|
+
thread_ts: event.thread_ts || event.ts
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
catch (sendError) {
|
|
1085
|
+
console.error('❌ Failed to send error message to Slack:', sendError);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
exports.SlackAIService = SlackAIService;
|
|
1091
|
+
//# sourceMappingURL=slackAIService.js.map
|