agor-live 0.21.2 → 0.22.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/dist/cli/commands/branch/env/restart.js +1 -1
- package/dist/cli/commands/branch/env/start.js +1 -1
- package/dist/cli/commands/branch/env/stop.js +1 -1
- package/dist/core/api/index.cjs +5 -1
- package/dist/core/api/index.d.ts +6 -1
- package/dist/core/api/index.d.ts.map +1 -1
- package/dist/core/api/index.js +5 -1
- package/dist/core/claude/index.cjs +162 -14
- package/dist/core/claude/index.js +166 -18
- package/dist/core/client/index.cjs +43 -3
- package/dist/core/client/index.js +37 -3
- package/dist/core/config/browser.cjs +2 -2
- package/dist/core/config/browser.js +2 -2
- package/dist/core/config/config-manager.d.ts.map +1 -1
- package/dist/core/config/constants.d.ts +1 -1
- package/dist/core/config/index.cjs +174 -20
- package/dist/core/config/index.js +178 -24
- package/dist/core/config/types.d.ts +8 -0
- package/dist/core/config/types.d.ts.map +1 -1
- package/dist/core/db/index.cjs +495 -86
- package/dist/core/db/index.js +482 -75
- package/dist/core/db/repositories/artifacts.d.ts.map +1 -1
- package/dist/core/db/repositories/branches.d.ts +13 -1
- package/dist/core/db/repositories/branches.d.ts.map +1 -1
- package/dist/core/db/repositories/gateway-channels.d.ts.map +1 -1
- package/dist/core/db/repositories/index.d.ts +1 -0
- package/dist/core/db/repositories/index.d.ts.map +1 -1
- package/dist/core/db/repositories/session-relationships.d.ts +30 -0
- package/dist/core/db/repositories/session-relationships.d.ts.map +1 -0
- package/dist/core/db/repositories/users.d.ts +11 -0
- package/dist/core/db/repositories/users.d.ts.map +1 -1
- package/dist/core/db/schema.d.ts +421 -4
- package/dist/core/db/schema.d.ts.map +1 -1
- package/dist/core/db/schema.postgres.d.ts +226 -2
- package/dist/core/db/schema.postgres.d.ts.map +1 -1
- package/dist/core/db/schema.sqlite.d.ts +228 -2
- package/dist/core/db/schema.sqlite.d.ts.map +1 -1
- package/dist/core/drizzle/postgres/0050_artifact_source_session.sql +3 -0
- package/dist/core/drizzle/postgres/0051_session_relationships.sql +26 -0
- package/dist/core/drizzle/postgres/meta/_journal.json +14 -0
- package/dist/core/drizzle/sqlite/0059_artifact_source_session.sql +2 -0
- package/dist/core/drizzle/sqlite/0060_session_relationships.sql +23 -0
- package/dist/core/drizzle/sqlite/meta/_journal.json +14 -0
- package/dist/core/gateway/connector-registry.d.ts.map +1 -1
- package/dist/core/gateway/connector.d.ts +22 -0
- package/dist/core/gateway/connector.d.ts.map +1 -1
- package/dist/core/gateway/connectors/slack.d.ts +35 -3
- package/dist/core/gateway/connectors/slack.d.ts.map +1 -1
- package/dist/core/gateway/connectors/teams.d.ts +107 -0
- package/dist/core/gateway/connectors/teams.d.ts.map +1 -0
- package/dist/core/gateway/context.d.ts.map +1 -1
- package/dist/core/gateway/index.cjs +552 -52
- package/dist/core/gateway/index.d.ts +3 -2
- package/dist/core/gateway/index.d.ts.map +1 -1
- package/dist/core/gateway/index.js +544 -52
- package/dist/core/gateway/system-message.d.ts +21 -0
- package/dist/core/gateway/system-message.d.ts.map +1 -1
- package/dist/core/index.cjs +616 -127
- package/dist/core/index.js +597 -116
- package/dist/core/mcp/index.cjs +146 -9
- package/dist/core/mcp/index.js +146 -9
- package/dist/core/mcp/template-resolver.d.ts.map +1 -1
- package/dist/core/seed/index.cjs +375 -59
- package/dist/core/seed/index.js +378 -62
- package/dist/core/sessions/index.cjs +19 -0
- package/dist/core/sessions/index.js +19 -0
- package/dist/core/templates/agor-system-prompt.md +21 -53
- package/dist/core/templates/session-context.cjs +2 -73
- package/dist/core/templates/session-context.d.ts +9 -53
- package/dist/core/templates/session-context.d.ts.map +1 -1
- package/dist/core/templates/session-context.js +2 -72
- package/dist/core/tools/mcp/jwt-auth.cjs +2 -20
- package/dist/core/tools/mcp/jwt-auth.d.ts.map +1 -1
- package/dist/core/tools/mcp/jwt-auth.js +2 -20
- package/dist/core/tools/mcp/oauth-mcp-transport.cjs +2 -15
- package/dist/core/tools/mcp/oauth-mcp-transport.d.ts.map +1 -1
- package/dist/core/tools/mcp/oauth-mcp-transport.js +2 -15
- package/dist/core/tools/mcp/oauth-refresh.cjs +167 -19
- package/dist/core/tools/mcp/oauth-refresh.js +167 -19
- package/dist/core/types/artifact.d.ts +5 -1
- package/dist/core/types/artifact.d.ts.map +1 -1
- package/dist/core/types/branch.d.ts +14 -0
- package/dist/core/types/branch.d.ts.map +1 -1
- package/dist/core/types/gateway.d.ts +1 -1
- package/dist/core/types/gateway.d.ts.map +1 -1
- package/dist/core/types/id.d.ts +1 -0
- package/dist/core/types/id.d.ts.map +1 -1
- package/dist/core/types/index.cjs +36 -0
- package/dist/core/types/index.js +30 -0
- package/dist/core/types/session.d.ts +65 -1
- package/dist/core/types/session.d.ts.map +1 -1
- package/dist/core/types/task.d.ts +9 -0
- package/dist/core/types/task.d.ts.map +1 -1
- package/dist/core/unix/index.cjs +371 -55
- package/dist/core/unix/index.js +374 -58
- package/dist/core/unix/unix-integration-service.d.ts +10 -7
- package/dist/core/unix/unix-integration-service.d.ts.map +1 -1
- package/dist/core/utils/permission-mode-mapper.cjs +19 -0
- package/dist/core/utils/permission-mode-mapper.js +19 -0
- package/dist/daemon/declarations.d.ts +7 -0
- package/dist/daemon/declarations.d.ts.map +1 -1
- package/dist/daemon/hooks/gateway-route.d.ts.map +1 -1
- package/dist/daemon/hooks/gateway-route.js +53 -1
- package/dist/daemon/index.js +3760 -2107
- package/dist/daemon/main.js +3760 -2107
- package/dist/daemon/mcp/server.js +155 -17
- package/dist/daemon/mcp/tools/analytics.js +6 -7
- package/dist/daemon/mcp/tools/artifacts.d.ts.map +1 -1
- package/dist/daemon/mcp/tools/artifacts.js +7 -7
- package/dist/daemon/mcp/tools/boards.js +6 -7
- package/dist/daemon/mcp/tools/branches.js +6 -7
- package/dist/daemon/mcp/tools/card-types.js +6 -7
- package/dist/daemon/mcp/tools/cards.js +6 -7
- package/dist/daemon/mcp/tools/environment.d.ts.map +1 -1
- package/dist/daemon/mcp/tools/environment.js +19 -12
- package/dist/daemon/mcp/tools/knowledge.js +6 -7
- package/dist/daemon/mcp/tools/mcp-servers.js +6 -7
- package/dist/daemon/mcp/tools/messages.js +6 -7
- package/dist/daemon/mcp/tools/proxies.js +6 -7
- package/dist/daemon/mcp/tools/repos.js +6 -7
- package/dist/daemon/mcp/tools/schedules.js +6 -7
- package/dist/daemon/mcp/tools/search.js +6 -7
- package/dist/daemon/mcp/tools/sessions.d.ts.map +1 -1
- package/dist/daemon/mcp/tools/sessions.js +140 -11
- package/dist/daemon/mcp/tools/tasks.js +6 -7
- package/dist/daemon/mcp/tools/users.js +6 -7
- package/dist/daemon/mcp/tools/widgets.js +7 -8
- package/dist/daemon/register-hooks.d.ts +5 -1
- package/dist/daemon/register-hooks.d.ts.map +1 -1
- package/dist/daemon/register-hooks.js +404 -179
- package/dist/daemon/register-routes.d.ts.map +1 -1
- package/dist/daemon/register-routes.js +360 -162
- package/dist/daemon/register-services.d.ts.map +1 -1
- package/dist/daemon/register-services.js +1928 -671
- package/dist/daemon/services/artifacts.d.ts +10 -1
- package/dist/daemon/services/artifacts.d.ts.map +1 -1
- package/dist/daemon/services/artifacts.js +25 -1
- package/dist/daemon/services/branches.d.ts +11 -1
- package/dist/daemon/services/branches.d.ts.map +1 -1
- package/dist/daemon/services/branches.js +470 -184
- package/dist/daemon/services/claude-models.js +879 -339
- package/dist/daemon/services/gateway.d.ts +58 -2
- package/dist/daemon/services/gateway.d.ts.map +1 -1
- package/dist/daemon/services/gateway.js +590 -47
- package/dist/daemon/services/groups.d.ts +2 -0
- package/dist/daemon/services/groups.d.ts.map +1 -1
- package/dist/daemon/services/groups.js +56 -0
- package/dist/daemon/services/mcp-servers.d.ts.map +1 -1
- package/dist/daemon/services/mcp-servers.js +0 -6
- package/dist/daemon/services/scheduler.d.ts.map +1 -1
- package/dist/daemon/services/scheduler.js +6 -2
- package/dist/daemon/services/sessions.d.ts +11 -3
- package/dist/daemon/services/sessions.d.ts.map +1 -1
- package/dist/daemon/services/sessions.js +68 -7
- package/dist/daemon/services/tasks.d.ts +13 -2
- package/dist/daemon/services/tasks.d.ts.map +1 -1
- package/dist/daemon/services/tasks.js +42 -26
- package/dist/daemon/startup.js +6 -2
- package/dist/daemon/utils/session-stop.d.ts +43 -0
- package/dist/daemon/utils/session-stop.d.ts.map +1 -0
- package/dist/daemon/utils/session-stop.js +102 -0
- package/dist/daemon/utils/session-task-state.d.ts +7 -2
- package/dist/daemon/utils/session-task-state.d.ts.map +1 -1
- package/dist/daemon/utils/session-task-state.js +9 -3
- package/dist/daemon/utils/session-tasks.d.ts +4 -4
- package/dist/daemon/utils/session-tasks.d.ts.map +1 -1
- package/dist/daemon/utils/session-tasks.js +4 -8
- package/dist/executor/commands/environment.d.ts +13 -0
- package/dist/executor/commands/environment.d.ts.map +1 -0
- package/dist/executor/commands/environment.js +287 -0
- package/dist/executor/commands/index.d.ts.map +1 -1
- package/dist/executor/commands/index.js +5 -1
- package/dist/executor/commands/unix.d.ts +8 -1
- package/dist/executor/commands/unix.d.ts.map +1 -1
- package/dist/executor/commands/unix.js +157 -2
- package/dist/executor/payload-types.d.ts +201 -5
- package/dist/executor/payload-types.d.ts.map +1 -1
- package/dist/executor/payload-types.js +98 -0
- package/dist/executor/sdk-handlers/base/mcp-scoping.d.ts.map +1 -1
- package/dist/executor/sdk-handlers/base/mcp-scoping.js +14 -0
- package/dist/executor/sdk-handlers/claude/message-processor.d.ts.map +1 -1
- package/dist/executor/sdk-handlers/claude/message-processor.js +0 -1
- package/dist/executor/sdk-handlers/claude/query-builder.d.ts +1 -0
- package/dist/executor/sdk-handlers/claude/query-builder.d.ts.map +1 -1
- package/dist/executor/sdk-handlers/claude/query-builder.js +91 -39
- package/dist/executor/sdk-handlers/codex/prompt-service.d.ts +12 -5
- package/dist/executor/sdk-handlers/codex/prompt-service.d.ts.map +1 -1
- package/dist/executor/sdk-handlers/codex/prompt-service.js +72 -30
- package/dist/executor/sdk-handlers/copilot/prompt-service.d.ts +2 -4
- package/dist/executor/sdk-handlers/copilot/prompt-service.d.ts.map +1 -1
- package/dist/executor/sdk-handlers/copilot/prompt-service.js +4 -13
- package/dist/executor/sdk-handlers/gemini/prompt-service.d.ts +2 -4
- package/dist/executor/sdk-handlers/gemini/prompt-service.d.ts.map +1 -1
- package/dist/executor/sdk-handlers/gemini/prompt-service.js +4 -13
- package/dist/ui/assets/App-DcEY8Ota.js +3 -0
- package/dist/ui/assets/App-DcEY8Ota.js.gz +0 -0
- package/dist/ui/assets/{ArtifactConsentModal-ParNk5kW.js → ArtifactConsentModal-CiCbK9iv.js} +1 -1
- package/dist/ui/assets/ArtifactConsentModal-CiCbK9iv.js.gz +0 -0
- package/dist/ui/assets/ArtifactFullscreenPage-CfsTEGKd.js +9 -0
- package/dist/ui/assets/ArtifactFullscreenPage-CfsTEGKd.js.gz +0 -0
- package/dist/ui/assets/AutocompleteTextarea-BAFFH_5e.js +18 -0
- package/dist/ui/assets/AutocompleteTextarea-BAFFH_5e.js.gz +0 -0
- package/dist/ui/assets/BoardObjectNodes-D-O6bZIG.js +34 -0
- package/dist/ui/assets/BoardObjectNodes-D-O6bZIG.js.gz +0 -0
- package/dist/ui/assets/{CodeEditor.inner-D51Z_CLQ.js → CodeEditor.inner-DBgsP4tn.js} +2 -2
- package/dist/ui/assets/CodeEditor.inner-DBgsP4tn.js.gz +0 -0
- package/dist/ui/assets/ConversationView-CUWR0gR6.js +1 -0
- package/dist/ui/assets/ConversationView-CUWR0gR6.js.gz +0 -0
- package/dist/ui/assets/KnowledgePage-B2bzlXfn.js +24 -0
- package/dist/ui/assets/KnowledgePage-B2bzlXfn.js.gz +0 -0
- package/dist/ui/assets/MarketingScreenshotPage-9Qd7eZsm.css +1 -0
- package/dist/ui/assets/MarketingScreenshotPage-zv5RUCuV.js +143 -0
- package/dist/ui/assets/MarketingScreenshotPage-zv5RUCuV.js.gz +0 -0
- package/dist/ui/assets/MobileApp-VgVnsnsN.js +1 -0
- package/dist/ui/assets/MobileApp-VgVnsnsN.js.gz +0 -0
- package/dist/ui/assets/SessionCanvas-f1-1Gbcw.js +20 -0
- package/dist/ui/assets/SessionCanvas-f1-1Gbcw.js.gz +0 -0
- package/dist/ui/assets/{App-BAdBsEnV.css → SessionCanvas-mEmYGZhC.css} +1 -1
- package/dist/ui/assets/SessionCanvas-mEmYGZhC.css.gz +0 -0
- package/dist/ui/assets/{StreamdownDemoPage-B9wbgp2s.js → StreamdownDemoPage-wzWaqWwr.js} +1 -1
- package/dist/ui/assets/StreamdownDemoPage-wzWaqWwr.js.gz +0 -0
- package/dist/ui/assets/{ThemeSwitcher-ubn6IOz9.js → ThemeSwitcher-Dly2y9pi.js} +1 -1
- package/dist/ui/assets/ThemeSwitcher-Dly2y9pi.js.gz +0 -0
- package/dist/ui/assets/antd-CfbbHJOz.js +401 -0
- package/dist/ui/assets/antd-CfbbHJOz.js.gz +0 -0
- package/dist/ui/assets/architecture-U656AL7Q-CykGFbQU.js +1 -0
- package/dist/ui/assets/{architectureDiagram-VXUJARFQ-ChmZt3zk.js → architectureDiagram-VXUJARFQ-C8HXAenz.js} +1 -1
- package/dist/ui/assets/architectureDiagram-VXUJARFQ-C8HXAenz.js.gz +0 -0
- package/dist/ui/assets/{blockDiagram-VD42YOAC-CzGHAHao.js → blockDiagram-VD42YOAC-BhZaEN19.js} +1 -1
- package/dist/ui/assets/blockDiagram-VD42YOAC-BhZaEN19.js.gz +0 -0
- package/dist/ui/assets/{c4Diagram-YG6GDRKO-DscJyaWN.js → c4Diagram-YG6GDRKO-Dk_UH-sY.js} +1 -1
- package/dist/ui/assets/c4Diagram-YG6GDRKO-Dk_UH-sY.js.gz +0 -0
- package/dist/ui/assets/channel-D6_nUWlW.js +1 -0
- package/dist/ui/assets/{chunk-4BX2VUAB-DoWpTvP8.js → chunk-4BX2VUAB-XprbG2TG.js} +1 -1
- package/dist/ui/assets/chunk-55IACEB6-ByzqIgSb.js +1 -0
- package/dist/ui/assets/{chunk-ABZYJK2D-RzDCrjE6.js → chunk-ABZYJK2D-BJcrryHK.js} +1 -1
- package/dist/ui/assets/chunk-ABZYJK2D-BJcrryHK.js.gz +0 -0
- package/dist/ui/assets/{chunk-AGHRB4JF-jidCS5Of.js → chunk-AGHRB4JF-DvxmfbM0.js} +1 -1
- package/dist/ui/assets/chunk-AGHRB4JF-DvxmfbM0.js.gz +0 -0
- package/dist/ui/assets/{chunk-ATLVNIR6-BEIIfJtC.js → chunk-ATLVNIR6-DbeJ0OrR.js} +1 -1
- package/dist/ui/assets/chunk-ATLVNIR6-DbeJ0OrR.js.gz +0 -0
- package/dist/ui/assets/{chunk-B4BG7PRW-B8b6dQQ2.js → chunk-B4BG7PRW-C53q2ggf.js} +1 -1
- package/dist/ui/assets/chunk-B4BG7PRW-C53q2ggf.js.gz +0 -0
- package/dist/ui/assets/{chunk-CVBHYZKI-D-mQAfrk.js → chunk-CVBHYZKI-B3EBSlb3.js} +1 -1
- package/dist/ui/assets/{chunk-DI55MBZ5-BfATX3V8.js → chunk-DI55MBZ5-vIyNEQN-.js} +1 -1
- package/dist/ui/assets/chunk-DI55MBZ5-vIyNEQN-.js.gz +0 -0
- package/dist/ui/assets/chunk-EXTU4WIE-B3ObkuOm.js +1 -0
- package/dist/ui/assets/{chunk-FMBD7UC4-fqXscNvc.js → chunk-FMBD7UC4-rddmfK-Z.js} +1 -1
- package/dist/ui/assets/{chunk-HN2XXSSU-BCHvD80g.js → chunk-HN2XXSSU-Dttqcg3b.js} +1 -1
- package/dist/ui/assets/chunk-HN2XXSSU-Dttqcg3b.js.gz +0 -0
- package/dist/ui/assets/{chunk-JA3XYJ7Z-Cp6dqHnY.js → chunk-JA3XYJ7Z-DbNDev3D.js} +1 -1
- package/dist/ui/assets/chunk-JA3XYJ7Z-DbNDev3D.js.gz +0 -0
- package/dist/ui/assets/{chunk-JZLCHNYA-cKMooY3y.js → chunk-JZLCHNYA-EUmx2y4H.js} +1 -1
- package/dist/ui/assets/chunk-JZLCHNYA-EUmx2y4H.js.gz +0 -0
- package/dist/ui/assets/{chunk-MI3HLSF2-BlzO5wOE.js → chunk-MI3HLSF2-65n9Mkyc.js} +1 -1
- package/dist/ui/assets/chunk-MI3HLSF2-65n9Mkyc.js.gz +0 -0
- package/dist/ui/assets/chunk-N4CR4FBY-mv5koXqW.js +2 -0
- package/dist/ui/assets/chunk-N4CR4FBY-mv5koXqW.js.gz +0 -0
- package/dist/ui/assets/{chunk-QN33PNHL-DIHGQ_pd.js → chunk-QN33PNHL-DsRKK6NR.js} +1 -1
- package/dist/ui/assets/{chunk-QXUST7PY-C9l0muI0.js → chunk-QXUST7PY-BCYnMiS3.js} +1 -1
- package/dist/ui/assets/chunk-QXUST7PY-BCYnMiS3.js.gz +0 -0
- package/dist/ui/assets/chunk-QZHKN3VN-HucAw4xW.js +1 -0
- package/dist/ui/assets/{chunk-S3R3BYOJ-VJiLzt2o.js → chunk-S3R3BYOJ-CWMEa9Dc.js} +1 -1
- package/dist/ui/assets/chunk-S3R3BYOJ-CWMEa9Dc.js.gz +0 -0
- package/dist/ui/assets/{chunk-TZMSLE5B-DZwI0C_2.js → chunk-TZMSLE5B-BuQUQcTr.js} +1 -1
- package/dist/ui/assets/chunk-TZMSLE5B-BuQUQcTr.js.gz +0 -0
- package/dist/ui/assets/classDiagram-2ON5EDUG-CUT3rPTB.js +1 -0
- package/dist/ui/assets/classDiagram-v2-WZHVMYZB-CUT3rPTB.js +1 -0
- package/dist/ui/assets/{cose-bilkent-S5V4N54A-Ipik-oSD.js → cose-bilkent-S5V4N54A-CnPB3ARO.js} +1 -1
- package/dist/ui/assets/cose-bilkent-S5V4N54A-CnPB3ARO.js.gz +0 -0
- package/dist/ui/assets/cursor-QEb7m-rN.png +0 -0
- package/dist/ui/assets/{dagre-6UL2VRFP-BDpyWQnh.js → dagre-6UL2VRFP-DhS-k_Se.js} +1 -1
- package/dist/ui/assets/dagre-6UL2VRFP-DhS-k_Se.js.gz +0 -0
- package/dist/ui/assets/{dagre-CgA4KhUX.js → dagre-KgLoHEuy.js} +1 -1
- package/dist/ui/assets/dagre-KgLoHEuy.js.gz +0 -0
- package/dist/ui/assets/{diagram-PSM6KHXK-B4GRzxLJ.js → diagram-PSM6KHXK-BZg3MJmb.js} +1 -1
- package/dist/ui/assets/diagram-PSM6KHXK-BZg3MJmb.js.gz +0 -0
- package/dist/ui/assets/{diagram-QEK2KX5R-BWPW28XI.js → diagram-QEK2KX5R-BPCitvbo.js} +1 -1
- package/dist/ui/assets/diagram-QEK2KX5R-BPCitvbo.js.gz +0 -0
- package/dist/ui/assets/{diagram-S2PKOQOG-BIHhcGoV.js → diagram-S2PKOQOG-NW4uK6sx.js} +1 -1
- package/dist/ui/assets/diagram-S2PKOQOG-NW4uK6sx.js.gz +0 -0
- package/dist/ui/assets/{editor-C-HJ7Yw0.js → editor-CzFWIUw2.js} +1 -1
- package/dist/ui/assets/editor-CzFWIUw2.js.gz +0 -0
- package/dist/ui/assets/{emoji-D8F6B62m.js → emoji-Dkz4Zzv_.js} +1 -1
- package/dist/ui/assets/emoji-Dkz4Zzv_.js.gz +0 -0
- package/dist/ui/assets/{erDiagram-Q2GNP2WA-ubTaAFcK.js → erDiagram-Q2GNP2WA-me1fboaf.js} +1 -1
- package/dist/ui/assets/erDiagram-Q2GNP2WA-me1fboaf.js.gz +0 -0
- package/dist/ui/assets/{flowDiagram-NV44I4VS-BHLCTYjI.js → flowDiagram-NV44I4VS-DzE8dGsh.js} +1 -1
- package/dist/ui/assets/flowDiagram-NV44I4VS-DzE8dGsh.js.gz +0 -0
- package/dist/ui/assets/{ganttDiagram-LVOFAZNH-ClC3pay1.js → ganttDiagram-LVOFAZNH-CFQD09Mi.js} +2 -2
- package/dist/ui/assets/ganttDiagram-LVOFAZNH-CFQD09Mi.js.gz +0 -0
- package/dist/ui/assets/{gitGraph-F6HP7TQM-DghoobE6.js → gitGraph-F6HP7TQM-CfFE_uAC.js} +1 -1
- package/dist/ui/assets/{gitGraphDiagram-NY62KEGX-Clqpiswu.js → gitGraphDiagram-NY62KEGX-CaVoxU4C.js} +1 -1
- package/dist/ui/assets/gitGraphDiagram-NY62KEGX-CaVoxU4C.js.gz +0 -0
- package/dist/ui/assets/index-BN5_Qq7R.js +324 -0
- package/dist/ui/assets/index-BN5_Qq7R.js.gz +0 -0
- package/dist/ui/assets/index-DxuPq13l.css +1 -0
- package/dist/ui/assets/index-DxuPq13l.css.gz +0 -0
- package/dist/ui/assets/{info-NVLQJR56-0ZldEXPQ.js → info-NVLQJR56-i_xHYg3f.js} +1 -1
- package/dist/ui/assets/{infoDiagram-ER5ION4S-DMmPX-il.js → infoDiagram-ER5ION4S-2NL93b78.js} +1 -1
- package/dist/ui/assets/{journeyDiagram-XKPGCS4Q-CrVickA2.js → journeyDiagram-XKPGCS4Q-CZF-2DHU.js} +1 -1
- package/dist/ui/assets/journeyDiagram-XKPGCS4Q-CZF-2DHU.js.gz +0 -0
- package/dist/ui/assets/{kanban-definition-3W4ZIXB7-C_BsdHYL.js → kanban-definition-3W4ZIXB7-CfvJIOny.js} +1 -1
- package/dist/ui/assets/kanban-definition-3W4ZIXB7-CfvJIOny.js.gz +0 -0
- package/dist/ui/assets/{line-CfBP7Yic.js → line-DDv8kOJk.js} +1 -1
- package/dist/ui/assets/{linear-BsjageUB.js → linear-Daef-l29.js} +1 -1
- package/dist/ui/assets/linear-Daef-l29.js.gz +0 -0
- package/dist/ui/assets/{mermaid-parser.core-DZdP-NFq.js → mermaid-parser.core-CdK9QgYV.js} +2 -2
- package/dist/ui/assets/mermaid-parser.core-CdK9QgYV.js.gz +0 -0
- package/dist/ui/assets/{mermaid.core-TNrI0pHG.js → mermaid.core-D6GS9mU-.js} +3 -3
- package/dist/ui/assets/mermaid.core-D6GS9mU-.js.gz +0 -0
- package/dist/ui/assets/message-SqLqNYcv.js +36 -0
- package/dist/ui/assets/message-SqLqNYcv.js.gz +0 -0
- package/dist/ui/assets/{mindmap-definition-VGOIOE7T-BbmaUjMY.js → mindmap-definition-VGOIOE7T-Cb3QMflX.js} +1 -1
- package/dist/ui/assets/mindmap-definition-VGOIOE7T-Cb3QMflX.js.gz +0 -0
- package/dist/ui/assets/{packet-BFZMPI3H-D_ZhkXuT.js → packet-BFZMPI3H-Bm2uwz4i.js} +1 -1
- package/dist/ui/assets/{particles-Dv28pjOd.js → particles-DsJFOarW.js} +1 -1
- package/dist/ui/assets/particles-DsJFOarW.js.gz +0 -0
- package/dist/ui/assets/{pie-7BOR55EZ-Dn0Q3qNx.js → pie-7BOR55EZ-5i17tVnF.js} +1 -1
- package/dist/ui/assets/{pieDiagram-ADFJNKIX-BbyjfYu8.js → pieDiagram-ADFJNKIX-BxIwQWvw.js} +1 -1
- package/dist/ui/assets/pieDiagram-ADFJNKIX-BxIwQWvw.js.gz +0 -0
- package/dist/ui/assets/{quadrantDiagram-AYHSOK5B-Bc3GqMKz.js → quadrantDiagram-AYHSOK5B-B5HPe4ga.js} +1 -1
- package/dist/ui/assets/quadrantDiagram-AYHSOK5B-B5HPe4ga.js.gz +0 -0
- package/dist/ui/assets/{radar-NHE76QYJ-BHwoAy1q.js → radar-NHE76QYJ-BTn-tq0k.js} +1 -1
- package/dist/ui/assets/{reactflow-BVYPxNhc.js → reactflow-Bf74ngoo.js} +2 -2
- package/dist/ui/assets/reactflow-Bf74ngoo.js.gz +0 -0
- package/dist/ui/assets/{requirementDiagram-UZGBJVZJ-BQaKKL09.js → requirementDiagram-UZGBJVZJ-YfI6llkX.js} +1 -1
- package/dist/ui/assets/requirementDiagram-UZGBJVZJ-YfI6llkX.js.gz +0 -0
- package/dist/ui/assets/{sandpack-BQW_FQ7G.js → sandpack-D7koO5op.js} +1 -1
- package/dist/ui/assets/sandpack-D7koO5op.js.gz +0 -0
- package/dist/ui/assets/{sankeyDiagram-TZEHDZUN-DiJvDvhb.js → sankeyDiagram-TZEHDZUN-DOk_B10B.js} +1 -1
- package/dist/ui/assets/sankeyDiagram-TZEHDZUN-DOk_B10B.js.gz +0 -0
- package/dist/ui/assets/{sequenceDiagram-WL72ISMW-Dw32824o.js → sequenceDiagram-WL72ISMW-DAe4Um17.js} +1 -1
- package/dist/ui/assets/sequenceDiagram-WL72ISMW-DAe4Um17.js.gz +0 -0
- package/dist/ui/assets/{stateDiagram-FKZM4ZOC-BCOpNdHV.js → stateDiagram-FKZM4ZOC-CCesDu_C.js} +1 -1
- package/dist/ui/assets/stateDiagram-FKZM4ZOC-CCesDu_C.js.gz +0 -0
- package/dist/ui/assets/stateDiagram-v2-4FDKWEC3-CMlIrsoO.js +1 -0
- package/dist/ui/assets/{syntax-VJrU5BEu.js → syntax-C-M-8jOU.js} +1 -1
- package/dist/ui/assets/syntax-C-M-8jOU.js.gz +0 -0
- package/dist/ui/assets/{theme-DZtFA8b4.js → theme-BQZdiqwv.js} +1 -1
- package/dist/ui/assets/{timeline-definition-IT6M3QCI-Jh_WZzXv.js → timeline-definition-IT6M3QCI-D6P5txjT.js} +1 -1
- package/dist/ui/assets/timeline-definition-IT6M3QCI-D6P5txjT.js.gz +0 -0
- package/dist/ui/assets/{treemap-KMMF4GRG-CPYIgjxE.js → treemap-KMMF4GRG-Bitm3gy4.js} +1 -1
- package/dist/ui/assets/{knowledgeRoutes-CivaUqha.js → useUserLocalStorage-Ckb8HsIw.js} +1 -1
- package/dist/ui/assets/useUserLocalStorage-Ckb8HsIw.js.gz +0 -0
- package/dist/ui/assets/{xychartDiagram-PRI3JC2R-CERc7Rdb.js → xychartDiagram-PRI3JC2R-CsybjUbd.js} +1 -1
- package/dist/ui/assets/xychartDiagram-PRI3JC2R-CsybjUbd.js.gz +0 -0
- package/dist/ui/index.html +13 -11
- package/dist/ui/index.html.gz +0 -0
- package/package.json +10 -9
- package/dist/ui/assets/App-9s2WHM6S.js +0 -22
- package/dist/ui/assets/App-9s2WHM6S.js.gz +0 -0
- package/dist/ui/assets/App-BAdBsEnV.css.gz +0 -0
- package/dist/ui/assets/ArtifactConsentModal-ParNk5kW.js.gz +0 -0
- package/dist/ui/assets/ArtifactFullscreenPage-VQxLMCiN.js +0 -9
- package/dist/ui/assets/ArtifactFullscreenPage-VQxLMCiN.js.gz +0 -0
- package/dist/ui/assets/AutocompleteTextarea-3RchrIgk.js +0 -18
- package/dist/ui/assets/AutocompleteTextarea-3RchrIgk.js.gz +0 -0
- package/dist/ui/assets/CodeEditor.inner-D51Z_CLQ.js.gz +0 -0
- package/dist/ui/assets/ConversationView-Dyddw2b1.js +0 -34
- package/dist/ui/assets/ConversationView-Dyddw2b1.js.gz +0 -0
- package/dist/ui/assets/KnowledgePage-CdftslnF.js +0 -24
- package/dist/ui/assets/KnowledgePage-CdftslnF.js.gz +0 -0
- package/dist/ui/assets/MobileApp-BdBMpnJ1.js +0 -1
- package/dist/ui/assets/MobileApp-BdBMpnJ1.js.gz +0 -0
- package/dist/ui/assets/StreamdownDemoPage-B9wbgp2s.js.gz +0 -0
- package/dist/ui/assets/ThemeSwitcher-ubn6IOz9.js.gz +0 -0
- package/dist/ui/assets/antd-C-HfEC4E.js +0 -400
- package/dist/ui/assets/antd-C-HfEC4E.js.gz +0 -0
- package/dist/ui/assets/architecture-U656AL7Q-dkBewUpN.js +0 -1
- package/dist/ui/assets/architectureDiagram-VXUJARFQ-ChmZt3zk.js.gz +0 -0
- package/dist/ui/assets/blockDiagram-VD42YOAC-CzGHAHao.js.gz +0 -0
- package/dist/ui/assets/c4Diagram-YG6GDRKO-DscJyaWN.js.gz +0 -0
- package/dist/ui/assets/channel-DvRQqEqC.js +0 -1
- package/dist/ui/assets/chunk-55IACEB6-DojF2pZN.js +0 -1
- package/dist/ui/assets/chunk-ABZYJK2D-RzDCrjE6.js.gz +0 -0
- package/dist/ui/assets/chunk-AGHRB4JF-jidCS5Of.js.gz +0 -0
- package/dist/ui/assets/chunk-ATLVNIR6-BEIIfJtC.js.gz +0 -0
- package/dist/ui/assets/chunk-B4BG7PRW-B8b6dQQ2.js.gz +0 -0
- package/dist/ui/assets/chunk-DI55MBZ5-BfATX3V8.js.gz +0 -0
- package/dist/ui/assets/chunk-EXTU4WIE-BKt6lPJM.js +0 -1
- package/dist/ui/assets/chunk-HN2XXSSU-BCHvD80g.js.gz +0 -0
- package/dist/ui/assets/chunk-JA3XYJ7Z-Cp6dqHnY.js.gz +0 -0
- package/dist/ui/assets/chunk-JZLCHNYA-cKMooY3y.js.gz +0 -0
- package/dist/ui/assets/chunk-MI3HLSF2-BlzO5wOE.js.gz +0 -0
- package/dist/ui/assets/chunk-N4CR4FBY-pASDorUx.js +0 -2
- package/dist/ui/assets/chunk-N4CR4FBY-pASDorUx.js.gz +0 -0
- package/dist/ui/assets/chunk-QXUST7PY-C9l0muI0.js.gz +0 -0
- package/dist/ui/assets/chunk-QZHKN3VN-CZskCFCf.js +0 -1
- package/dist/ui/assets/chunk-S3R3BYOJ-VJiLzt2o.js.gz +0 -0
- package/dist/ui/assets/chunk-TZMSLE5B-DZwI0C_2.js.gz +0 -0
- package/dist/ui/assets/classDiagram-2ON5EDUG-BFASUbmZ.js +0 -1
- package/dist/ui/assets/classDiagram-v2-WZHVMYZB-BFASUbmZ.js +0 -1
- package/dist/ui/assets/cose-bilkent-S5V4N54A-Ipik-oSD.js.gz +0 -0
- package/dist/ui/assets/dagre-6UL2VRFP-BDpyWQnh.js.gz +0 -0
- package/dist/ui/assets/dagre-CgA4KhUX.js.gz +0 -0
- package/dist/ui/assets/diagram-PSM6KHXK-B4GRzxLJ.js.gz +0 -0
- package/dist/ui/assets/diagram-QEK2KX5R-BWPW28XI.js.gz +0 -0
- package/dist/ui/assets/diagram-S2PKOQOG-BIHhcGoV.js.gz +0 -0
- package/dist/ui/assets/editor-C-HJ7Yw0.js.gz +0 -0
- package/dist/ui/assets/emoji-D8F6B62m.js.gz +0 -0
- package/dist/ui/assets/erDiagram-Q2GNP2WA-ubTaAFcK.js.gz +0 -0
- package/dist/ui/assets/flowDiagram-NV44I4VS-BHLCTYjI.js.gz +0 -0
- package/dist/ui/assets/ganttDiagram-LVOFAZNH-ClC3pay1.js.gz +0 -0
- package/dist/ui/assets/gitGraphDiagram-NY62KEGX-Clqpiswu.js.gz +0 -0
- package/dist/ui/assets/index-D9OElx9A.css +0 -1
- package/dist/ui/assets/index-D9OElx9A.css.gz +0 -0
- package/dist/ui/assets/index-DxPuzG7E.js +0 -350
- package/dist/ui/assets/index-DxPuzG7E.js.gz +0 -0
- package/dist/ui/assets/journeyDiagram-XKPGCS4Q-CrVickA2.js.gz +0 -0
- package/dist/ui/assets/kanban-definition-3W4ZIXB7-C_BsdHYL.js.gz +0 -0
- package/dist/ui/assets/knowledgeRoutes-CivaUqha.js.gz +0 -0
- package/dist/ui/assets/linear-BsjageUB.js.gz +0 -0
- package/dist/ui/assets/mermaid-parser.core-DZdP-NFq.js.gz +0 -0
- package/dist/ui/assets/mermaid.core-TNrI0pHG.js.gz +0 -0
- package/dist/ui/assets/message-BtWWJ9Af.js +0 -36
- package/dist/ui/assets/message-BtWWJ9Af.js.gz +0 -0
- package/dist/ui/assets/mindmap-definition-VGOIOE7T-BbmaUjMY.js.gz +0 -0
- package/dist/ui/assets/particles-Dv28pjOd.js.gz +0 -0
- package/dist/ui/assets/pieDiagram-ADFJNKIX-BbyjfYu8.js.gz +0 -0
- package/dist/ui/assets/quadrantDiagram-AYHSOK5B-Bc3GqMKz.js.gz +0 -0
- package/dist/ui/assets/reactflow-BVYPxNhc.js.gz +0 -0
- package/dist/ui/assets/requirementDiagram-UZGBJVZJ-BQaKKL09.js.gz +0 -0
- package/dist/ui/assets/sandpack-BQW_FQ7G.js.gz +0 -0
- package/dist/ui/assets/sankeyDiagram-TZEHDZUN-DiJvDvhb.js.gz +0 -0
- package/dist/ui/assets/sequenceDiagram-WL72ISMW-Dw32824o.js.gz +0 -0
- package/dist/ui/assets/stateDiagram-FKZM4ZOC-BCOpNdHV.js.gz +0 -0
- package/dist/ui/assets/stateDiagram-v2-4FDKWEC3-Cuqwvgfg.js +0 -1
- package/dist/ui/assets/syntax-VJrU5BEu.js.gz +0 -0
- package/dist/ui/assets/timeline-definition-IT6M3QCI-Jh_WZzXv.js.gz +0 -0
- package/dist/ui/assets/xychartDiagram-PRI3JC2R-CERc7Rdb.js.gz +0 -0
|
@@ -341,12 +341,16 @@ var TABLE_MAX_ROWS = 100;
|
|
|
341
341
|
var TABLE_MAX_COLS = 20;
|
|
342
342
|
var TABLE_MAX_CELL_CHARS = 3e3;
|
|
343
343
|
var SECTION_MAX_CHARS = 3e3;
|
|
344
|
+
var MARKDOWN_BLOCK_MAX_CHARS = 12e3;
|
|
344
345
|
var MAX_TABLES_PER_MESSAGE = 1;
|
|
345
346
|
var MAX_BLOCKS_PER_MESSAGE = 50;
|
|
346
347
|
var BLOCK_PAYLOAD_ERRORS = /* @__PURE__ */ new Set([
|
|
347
348
|
"invalid_blocks",
|
|
348
349
|
"invalid_blocks_format",
|
|
349
|
-
"
|
|
350
|
+
"invalid_block_type",
|
|
351
|
+
"message_blocks_too_long",
|
|
352
|
+
"unknown_block_type",
|
|
353
|
+
"unsupported_block_type"
|
|
350
354
|
]);
|
|
351
355
|
var FENCE_LINE_RE = /^(`{3,}|~{3,})/;
|
|
352
356
|
var PIPE_LINE_RE = /^\s*\|/;
|
|
@@ -519,12 +523,35 @@ ${tableLines.join("\n")}
|
|
|
519
523
|
text: { type: "mrkdwn", text: wrapped }
|
|
520
524
|
};
|
|
521
525
|
}
|
|
526
|
+
function buildMarkdownBlock(markdown) {
|
|
527
|
+
const trimmed = markdown.trim();
|
|
528
|
+
if (trimmed.length === 0 || trimmed.length > MARKDOWN_BLOCK_MAX_CHARS) return null;
|
|
529
|
+
return { type: "markdown", text: markdown };
|
|
530
|
+
}
|
|
531
|
+
function tableHasRichMarkdown(tableLines) {
|
|
532
|
+
return tableLines.some(
|
|
533
|
+
(line) => /(\*\*|__|~~|`|\[[^\]]+\]\([^)]*\)|<br\s*\/?\s*>|_[^_|]+_|(^|\|)\s*[-*+]\s+)/i.test(line)
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
function shouldUseNativeMarkdownBlock(markdown, segments) {
|
|
537
|
+
if (!buildMarkdownBlock(markdown)) return false;
|
|
538
|
+
const tableSegments = segments.filter((segment) => segment.kind === "table");
|
|
539
|
+
if (tableSegments.length > 1) return true;
|
|
540
|
+
return tableSegments.some((segment) => tableHasRichMarkdown(segment.lines));
|
|
541
|
+
}
|
|
522
542
|
function markdownToSlackPayload(markdown) {
|
|
523
543
|
const text = markdownToMrkdwn(markdown);
|
|
524
544
|
const segments = segmentMarkdown(markdown);
|
|
525
|
-
|
|
545
|
+
const hasTable = segments.some((s) => s.kind === "table");
|
|
546
|
+
if (!hasTable) {
|
|
526
547
|
return { text };
|
|
527
548
|
}
|
|
549
|
+
if (shouldUseNativeMarkdownBlock(markdown, segments)) {
|
|
550
|
+
const markdownBlock = buildMarkdownBlock(markdown);
|
|
551
|
+
if (markdownBlock) {
|
|
552
|
+
return { text, blocks: [markdownBlock] };
|
|
553
|
+
}
|
|
554
|
+
}
|
|
528
555
|
const blocks = [];
|
|
529
556
|
let tablesEmitted = 0;
|
|
530
557
|
for (const seg of segments) {
|
|
@@ -562,12 +589,15 @@ var SlackConnector = class _SlackConnector {
|
|
|
562
589
|
botUserId = null;
|
|
563
590
|
/** Cache: Slack user ID → profile (email + display name, or null if unavailable). */
|
|
564
591
|
userProfileCache = /* @__PURE__ */ new Map();
|
|
592
|
+
inboundEventDedup = /* @__PURE__ */ new Map();
|
|
565
593
|
/** Cache: Slack channel ID → channel name */
|
|
566
594
|
channelNameCache = /* @__PURE__ */ new Map();
|
|
567
595
|
static USER_CACHE_TTL_MS = 15 * 60 * 1e3;
|
|
568
596
|
// 15 min for successful lookups
|
|
569
597
|
static USER_CACHE_ERROR_TTL_MS = 60 * 1e3;
|
|
570
598
|
// 1 min for errors (transient recovery)
|
|
599
|
+
static INBOUND_EVENT_DEDUP_TTL_MS = 5 * 60 * 1e3;
|
|
600
|
+
// Slack may send message + app_mention for one user action
|
|
571
601
|
/**
|
|
572
602
|
* Cache: Slack channel ID → channel type string (channel/group/mpim/im).
|
|
573
603
|
*
|
|
@@ -626,11 +656,7 @@ var SlackConnector = class _SlackConnector {
|
|
|
626
656
|
displayName,
|
|
627
657
|
expiresAt: now + _SlackConnector.USER_CACHE_TTL_MS
|
|
628
658
|
});
|
|
629
|
-
if (email) {
|
|
630
|
-
console.log(
|
|
631
|
-
`[slack] Resolved user ${slackUserId} \u2192 ${displayName ?? "(no name)"} <${email}>`
|
|
632
|
-
);
|
|
633
|
-
} else {
|
|
659
|
+
if (!email) {
|
|
634
660
|
console.log(
|
|
635
661
|
`[slack] User ${slackUserId} has no email (missing users:read.email scope or restricted account)`
|
|
636
662
|
);
|
|
@@ -679,6 +705,47 @@ var SlackConnector = class _SlackConnector {
|
|
|
679
705
|
return null;
|
|
680
706
|
}
|
|
681
707
|
}
|
|
708
|
+
async lookupLatestThreadReply(event) {
|
|
709
|
+
const channel = typeof event.channel === "string" ? event.channel : void 0;
|
|
710
|
+
const message = typeof event.message === "object" && event.message !== null ? event.message : void 0;
|
|
711
|
+
const threadTs = (typeof message?.thread_ts === "string" ? message.thread_ts : void 0) ?? (typeof message?.ts === "string" ? message.ts : void 0) ?? (typeof event.thread_ts === "string" ? event.thread_ts : void 0);
|
|
712
|
+
const replies = Array.isArray(message?.replies) ? message.replies.filter((reply) => {
|
|
713
|
+
return typeof reply === "object" && reply !== null;
|
|
714
|
+
}) : [];
|
|
715
|
+
const latestReplyTs = (typeof message?.latest_reply === "string" ? message.latest_reply : void 0) ?? (typeof event.latest_reply === "string" ? event.latest_reply : void 0) ?? [...replies].reverse().map((reply) => typeof reply.ts === "string" ? reply.ts : void 0).find(Boolean);
|
|
716
|
+
if (!channel || !threadTs || !latestReplyTs) return null;
|
|
717
|
+
try {
|
|
718
|
+
const result = await this.web.conversations.replies({
|
|
719
|
+
channel,
|
|
720
|
+
ts: threadTs,
|
|
721
|
+
oldest: latestReplyTs,
|
|
722
|
+
inclusive: true,
|
|
723
|
+
limit: 1
|
|
724
|
+
});
|
|
725
|
+
const reply = result.messages?.find((candidate) => candidate.ts === latestReplyTs) ?? result.messages?.[0] ?? null;
|
|
726
|
+
if (!reply) return null;
|
|
727
|
+
return {
|
|
728
|
+
...reply,
|
|
729
|
+
channel,
|
|
730
|
+
thread_ts: typeof reply.thread_ts === "string" ? reply.thread_ts : threadTs,
|
|
731
|
+
team: event.team
|
|
732
|
+
};
|
|
733
|
+
} catch (error) {
|
|
734
|
+
console.warn("[slack] Failed to fetch latest thread reply for message_replied event:", error);
|
|
735
|
+
return null;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
shouldProcessInboundEventOnce(channel, ts) {
|
|
739
|
+
if (!channel || !ts) return true;
|
|
740
|
+
const now = Date.now();
|
|
741
|
+
for (const [key2, expiresAt] of this.inboundEventDedup) {
|
|
742
|
+
if (expiresAt <= now) this.inboundEventDedup.delete(key2);
|
|
743
|
+
}
|
|
744
|
+
const key = `${channel}:${ts}`;
|
|
745
|
+
if (this.inboundEventDedup.has(key)) return false;
|
|
746
|
+
this.inboundEventDedup.set(key, now + _SlackConnector.INBOUND_EVENT_DEDUP_TTL_MS);
|
|
747
|
+
return true;
|
|
748
|
+
}
|
|
682
749
|
/**
|
|
683
750
|
* Cache a known channel type from a trusted source (e.g. `message` event with explicit `channel_type`).
|
|
684
751
|
*/
|
|
@@ -724,7 +791,6 @@ var SlackConnector = class _SlackConnector {
|
|
|
724
791
|
} else {
|
|
725
792
|
resolvedType = "channel";
|
|
726
793
|
}
|
|
727
|
-
console.log(`[slack] conversations.info resolved channel ${channelId} \u2192 ${resolvedType}`);
|
|
728
794
|
this.cacheChannelType(channelId, resolvedType);
|
|
729
795
|
if (ch.name) {
|
|
730
796
|
this.channelNameCache.set(channelId, {
|
|
@@ -770,22 +836,34 @@ var SlackConnector = class _SlackConnector {
|
|
|
770
836
|
async sendMessage(req) {
|
|
771
837
|
const { channel, thread_ts } = parseThreadId2(req.threadId);
|
|
772
838
|
const blocks = req.blocks && req.blocks.length > 0 ? req.blocks : void 0;
|
|
773
|
-
const
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
839
|
+
const updateTs = typeof req.metadata?.slack_update_ts === "string" ? req.metadata.slack_update_ts : void 0;
|
|
840
|
+
const send = (withBlocks) => {
|
|
841
|
+
const base = {
|
|
842
|
+
channel,
|
|
843
|
+
text: req.text,
|
|
844
|
+
...withBlocks && blocks ? { blocks } : {},
|
|
845
|
+
unfurl_links: false,
|
|
846
|
+
unfurl_media: false
|
|
847
|
+
};
|
|
848
|
+
if (updateTs) {
|
|
849
|
+
return this.web.chat.update({
|
|
850
|
+
...base,
|
|
851
|
+
ts: updateTs
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
return this.web.chat.postMessage({
|
|
855
|
+
...base,
|
|
856
|
+
thread_ts
|
|
857
|
+
});
|
|
858
|
+
};
|
|
781
859
|
let result;
|
|
782
860
|
try {
|
|
783
|
-
result = await
|
|
861
|
+
result = await send(true);
|
|
784
862
|
} catch (err) {
|
|
785
863
|
const code = extractSlackErrorCode(err);
|
|
786
864
|
if (blocks && code && BLOCK_PAYLOAD_ERRORS.has(code)) {
|
|
787
865
|
console.warn(`[slack] Block payload rejected (${code}); retrying as text-only`);
|
|
788
|
-
result = await
|
|
866
|
+
result = await send(false);
|
|
789
867
|
} else {
|
|
790
868
|
throw err;
|
|
791
869
|
}
|
|
@@ -794,7 +872,7 @@ var SlackConnector = class _SlackConnector {
|
|
|
794
872
|
const code = extractSlackErrorCode(result);
|
|
795
873
|
if (blocks && code && BLOCK_PAYLOAD_ERRORS.has(code)) {
|
|
796
874
|
console.warn(`[slack] Block payload rejected (${code}); retrying as text-only`);
|
|
797
|
-
const retry = await
|
|
875
|
+
const retry = await send(false);
|
|
798
876
|
if (!retry.ok || !retry.ts) {
|
|
799
877
|
throw new Error(`Slack API error: ${retry.error ?? "unknown error"}`);
|
|
800
878
|
}
|
|
@@ -805,6 +883,70 @@ var SlackConnector = class _SlackConnector {
|
|
|
805
883
|
}
|
|
806
884
|
return result.ts;
|
|
807
885
|
}
|
|
886
|
+
async startStream(req) {
|
|
887
|
+
const { channel, thread_ts } = parseThreadId2(req.threadId);
|
|
888
|
+
const chat = this.web.chat;
|
|
889
|
+
const result = await chat.startStream({
|
|
890
|
+
channel,
|
|
891
|
+
thread_ts,
|
|
892
|
+
markdown_text: req.text?.trim() ? req.text : " ",
|
|
893
|
+
...req.recipientUserId ? { recipient_user_id: req.recipientUserId } : {},
|
|
894
|
+
...req.recipientTeamId ? { recipient_team_id: req.recipientTeamId } : {}
|
|
895
|
+
});
|
|
896
|
+
if (!result.ok || !result.ts) {
|
|
897
|
+
throw new Error(`Slack stream start error: ${result.error ?? "unknown error"}`);
|
|
898
|
+
}
|
|
899
|
+
return result.ts;
|
|
900
|
+
}
|
|
901
|
+
async appendStream(req) {
|
|
902
|
+
const { channel } = parseThreadId2(req.threadId);
|
|
903
|
+
const chat = this.web.chat;
|
|
904
|
+
const result = await chat.appendStream({
|
|
905
|
+
channel,
|
|
906
|
+
ts: req.ts,
|
|
907
|
+
markdown_text: req.text
|
|
908
|
+
});
|
|
909
|
+
if (!result.ok) {
|
|
910
|
+
throw new Error(`Slack stream append error: ${result.error ?? "unknown error"}`);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
async stopStream(req) {
|
|
914
|
+
const { channel } = parseThreadId2(req.threadId);
|
|
915
|
+
const chat = this.web.chat;
|
|
916
|
+
const result = await chat.stopStream({
|
|
917
|
+
channel,
|
|
918
|
+
ts: req.ts,
|
|
919
|
+
...req.text ? { markdown_text: req.text } : {}
|
|
920
|
+
});
|
|
921
|
+
if (!result.ok) {
|
|
922
|
+
throw new Error(`Slack stream stop error: ${result.error ?? "unknown error"}`);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
async deleteMessage(req) {
|
|
926
|
+
const { channel } = parseThreadId2(req.threadId);
|
|
927
|
+
const result = await this.web.chat.delete({
|
|
928
|
+
channel,
|
|
929
|
+
ts: req.messageId
|
|
930
|
+
});
|
|
931
|
+
if (!result.ok) {
|
|
932
|
+
throw new Error(`Slack delete error: ${result.error ?? "unknown error"}`);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
async setThreadStatus(req) {
|
|
936
|
+
const { channel, thread_ts } = parseThreadId2(req.threadId);
|
|
937
|
+
const web = this.web;
|
|
938
|
+
const args = {
|
|
939
|
+
channel_id: channel,
|
|
940
|
+
thread_ts,
|
|
941
|
+
status: req.status,
|
|
942
|
+
...req.loadingMessages?.length ? { loading_messages: req.loadingMessages } : {},
|
|
943
|
+
...req.iconEmoji ? { icon_emoji: req.iconEmoji } : {}
|
|
944
|
+
};
|
|
945
|
+
const result = web.assistant?.threads?.setStatus ? await web.assistant.threads.setStatus(args) : await web.apiCall?.("assistant.threads.setStatus", args);
|
|
946
|
+
if (!result?.ok) {
|
|
947
|
+
throw new Error(`Slack assistant status error: ${result?.error ?? "unknown error"}`);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
808
950
|
/**
|
|
809
951
|
* Start listening for inbound messages via Socket Mode
|
|
810
952
|
*
|
|
@@ -817,27 +959,20 @@ var SlackConnector = class _SlackConnector {
|
|
|
817
959
|
* - Channel whitelist (if allowed_channel_ids is set)
|
|
818
960
|
*/
|
|
819
961
|
async startListening(callback) {
|
|
820
|
-
console.log("[slack] startListening called");
|
|
821
962
|
if (!this.config.app_token) {
|
|
822
963
|
console.error("[slack] ERROR: app_token is missing from config");
|
|
823
964
|
throw new Error("Slack Socket Mode requires app_token in config");
|
|
824
965
|
}
|
|
825
|
-
console.log("[slack] Creating SocketModeClient...");
|
|
826
966
|
this.socketMode = new SocketModeClient({
|
|
827
967
|
appToken: this.config.app_token
|
|
828
968
|
});
|
|
829
969
|
let botMentionPattern = null;
|
|
830
970
|
let botMentionReplacePattern = null;
|
|
831
971
|
try {
|
|
832
|
-
console.log("[slack] Testing bot token with auth.test()...");
|
|
833
972
|
const authTest = await this.web.auth.test();
|
|
834
973
|
this.botUserId = authTest.user_id;
|
|
835
974
|
botMentionPattern = new RegExp(`<@${this.botUserId}>`);
|
|
836
975
|
botMentionReplacePattern = new RegExp(`<@${this.botUserId}>\\s*`, "g");
|
|
837
|
-
console.log(`[slack] Bot user ID: ${this.botUserId}`);
|
|
838
|
-
console.log(
|
|
839
|
-
`[slack] Bot auth test successful - team: ${authTest.team}, user: ${authTest.user}`
|
|
840
|
-
);
|
|
841
976
|
} catch (error) {
|
|
842
977
|
console.error("[slack] Failed to fetch bot user ID:", error);
|
|
843
978
|
console.error("[slack] This usually means the bot_token is invalid or expired");
|
|
@@ -863,13 +998,6 @@ var SlackConnector = class _SlackConnector {
|
|
|
863
998
|
allowedChannelIds = void 0;
|
|
864
999
|
}
|
|
865
1000
|
}
|
|
866
|
-
console.log("[slack] Message source config:", {
|
|
867
|
-
enableChannels,
|
|
868
|
-
enableGroups,
|
|
869
|
-
enableMpim,
|
|
870
|
-
requireMention,
|
|
871
|
-
allowedChannelIds: allowedChannelIds?.length || 0
|
|
872
|
-
});
|
|
873
1001
|
this.socketMode.on("slack_event", async ({ type, body, ack }) => {
|
|
874
1002
|
if (type !== "events_api") {
|
|
875
1003
|
await ack();
|
|
@@ -881,15 +1009,42 @@ var SlackConnector = class _SlackConnector {
|
|
|
881
1009
|
return;
|
|
882
1010
|
}
|
|
883
1011
|
await ack();
|
|
884
|
-
|
|
1012
|
+
let event = body.event;
|
|
1013
|
+
const slackTeamId = typeof event.team === "string" ? event.team : typeof body.team_id === "string" ? body.team_id : Array.isArray(body.authorizations) && typeof body.authorizations[0]?.team_id === "string" ? body.authorizations[0].team_id : void 0;
|
|
885
1014
|
console.log(
|
|
886
1015
|
`[slack] Processing ${eventType} event - channel: ${event.channel}, channel_type: ${event.channel_type}`
|
|
887
1016
|
);
|
|
888
1017
|
if (event.bot_id || event.subtype === "bot_message") {
|
|
889
|
-
console.log("[slack] Skipping bot message");
|
|
890
1018
|
return;
|
|
891
1019
|
}
|
|
892
1020
|
if (eventType === "message" && event.subtype) {
|
|
1021
|
+
if (event.subtype === "message_replied") {
|
|
1022
|
+
const replyEvent = await this.lookupLatestThreadReply(event);
|
|
1023
|
+
if (!replyEvent) {
|
|
1024
|
+
console.log(
|
|
1025
|
+
`[slack] Skipping message_replied event without fetchable latest reply channel=${event.channel ?? "(none)"} ts=${event.ts ?? "(none)"}`
|
|
1026
|
+
);
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
event = {
|
|
1030
|
+
...replyEvent,
|
|
1031
|
+
type: "message",
|
|
1032
|
+
channel_type: event.channel_type
|
|
1033
|
+
};
|
|
1034
|
+
console.log(
|
|
1035
|
+
`[slack] Resolved message_replied event to latest reply thread_ts=${event.thread_ts ?? "(none)"} ts=${event.ts ?? "(none)"}`
|
|
1036
|
+
);
|
|
1037
|
+
} else {
|
|
1038
|
+
console.debug(
|
|
1039
|
+
`[slack] Skipping message subtype=${event.subtype} user=${event.user ?? "(none)"} thread_ts=${event.thread_ts ?? "(none)"} ts=${event.ts ?? "(none)"}`
|
|
1040
|
+
);
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
if (event.bot_id || event.subtype === "bot_message") {
|
|
1045
|
+
console.debug(
|
|
1046
|
+
`[slack] Skipping resolved bot message subtype=${event.subtype ?? "(none)"} thread_ts=${event.thread_ts ?? "(none)"} ts=${event.ts ?? "(none)"}`
|
|
1047
|
+
);
|
|
893
1048
|
return;
|
|
894
1049
|
}
|
|
895
1050
|
const channelType = event.channel ? await this.resolveChannelType(event.channel, event.channel_type) : void 0;
|
|
@@ -897,23 +1052,14 @@ var SlackConnector = class _SlackConnector {
|
|
|
897
1052
|
const isChannelMessage = channelType === "channel" || channelType === "group";
|
|
898
1053
|
if (isChannelMessage && !botMentionPattern) {
|
|
899
1054
|
if (eventType === "message" && requireMention) {
|
|
900
|
-
console.warn(
|
|
901
|
-
"[slack] Bot ID unavailable, require_mention=true - skipping message event (will use app_mention)"
|
|
902
|
-
);
|
|
903
1055
|
return;
|
|
904
1056
|
}
|
|
905
1057
|
if (eventType === "app_mention" && !requireMention) {
|
|
906
|
-
console.warn(
|
|
907
|
-
"[slack] Bot ID unavailable, require_mention=false - skipping app_mention (will use message)"
|
|
908
|
-
);
|
|
909
1058
|
return;
|
|
910
1059
|
}
|
|
911
1060
|
}
|
|
912
1061
|
if (isChannelMessage && botMentionPattern) {
|
|
913
1062
|
const mentionOutsideCodeBlock = hasActiveMention2(event.text ?? "", botMentionPattern);
|
|
914
|
-
if (eventType === "message" && mentionOutsideCodeBlock) {
|
|
915
|
-
return;
|
|
916
|
-
}
|
|
917
1063
|
if (eventType === "app_mention" && !mentionOutsideCodeBlock) {
|
|
918
1064
|
return;
|
|
919
1065
|
}
|
|
@@ -961,9 +1107,15 @@ var SlackConnector = class _SlackConnector {
|
|
|
961
1107
|
}
|
|
962
1108
|
}
|
|
963
1109
|
}
|
|
1110
|
+
if (!this.shouldProcessInboundEventOnce(event.channel, event.ts)) {
|
|
1111
|
+
console.log(
|
|
1112
|
+
`[slack] Skipping duplicate inbound event type=${eventType} channel=${event.channel} ts=${event.ts}`
|
|
1113
|
+
);
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
964
1116
|
const threadId = event.thread_ts ? `${event.channel}-${event.thread_ts}` : `${event.channel}-${event.ts}`;
|
|
965
1117
|
console.log(
|
|
966
|
-
`[slack]
|
|
1118
|
+
`[slack] Accepted inbound message: thread=${threadId} channel_type=${channelType} user=${event.user}`
|
|
967
1119
|
);
|
|
968
1120
|
let slackUserEmail = null;
|
|
969
1121
|
let slackUserDisplayName = null;
|
|
@@ -984,6 +1136,8 @@ var SlackConnector = class _SlackConnector {
|
|
|
984
1136
|
metadata: {
|
|
985
1137
|
channel: event.channel,
|
|
986
1138
|
channel_type: channelType,
|
|
1139
|
+
...event.user ? { slack_user_id: event.user } : {},
|
|
1140
|
+
...slackTeamId ? { slack_team_id: slackTeamId } : {},
|
|
987
1141
|
requires_mapping_verification: allowedViaThreadReplyException,
|
|
988
1142
|
...slackUserEmail ? { slack_user_email: slackUserEmail } : {},
|
|
989
1143
|
...slackUserDisplayName ? { slack_user_name: slackUserDisplayName } : {},
|
|
@@ -995,9 +1149,7 @@ var SlackConnector = class _SlackConnector {
|
|
|
995
1149
|
}
|
|
996
1150
|
});
|
|
997
1151
|
});
|
|
998
|
-
console.log("[slack] Starting Socket Mode client...");
|
|
999
1152
|
await this.socketMode.start();
|
|
1000
|
-
console.log("[slack] Socket Mode client connected successfully!");
|
|
1001
1153
|
}
|
|
1002
1154
|
/**
|
|
1003
1155
|
* Stop Socket Mode listener
|
|
@@ -1013,18 +1165,310 @@ var SlackConnector = class _SlackConnector {
|
|
|
1013
1165
|
*
|
|
1014
1166
|
* Returns `{ text, blocks? }`. `text` is the mrkdwn fallback used for
|
|
1015
1167
|
* notifications and clients that don't render Block Kit; `blocks` is set
|
|
1016
|
-
* when the message contains
|
|
1017
|
-
*
|
|
1168
|
+
* when the message contains tables that can benefit from Slack's native
|
|
1169
|
+
* markdown/table blocks.
|
|
1018
1170
|
*/
|
|
1019
1171
|
formatMessage(markdown) {
|
|
1020
1172
|
return markdownToSlackPayload(markdown);
|
|
1021
1173
|
}
|
|
1022
1174
|
};
|
|
1023
1175
|
|
|
1176
|
+
// src/gateway/connectors/teams.ts
|
|
1177
|
+
import { createServer } from "http";
|
|
1178
|
+
import { BotFrameworkAdapter, TurnContext } from "botbuilder";
|
|
1179
|
+
function parseThreadId3(threadId) {
|
|
1180
|
+
const lastPipe = threadId.lastIndexOf("|");
|
|
1181
|
+
if (lastPipe === -1) {
|
|
1182
|
+
throw new Error(
|
|
1183
|
+
`Invalid Teams thread ID format: "${threadId}" (expected "{conversationId}|{activityId}")`
|
|
1184
|
+
);
|
|
1185
|
+
}
|
|
1186
|
+
const conversationId = threadId.substring(0, lastPipe);
|
|
1187
|
+
const activityId = threadId.substring(lastPipe + 1);
|
|
1188
|
+
if (!conversationId || !activityId) {
|
|
1189
|
+
throw new Error(
|
|
1190
|
+
`Invalid Teams thread ID format: "${threadId}" (expected "{conversationId}|{activityId}")`
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
return { conversationId, activityId };
|
|
1194
|
+
}
|
|
1195
|
+
function stripMention2(text, botName) {
|
|
1196
|
+
const escaped = botName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1197
|
+
const pattern = new RegExp(`<at>${escaped}</at>\\s*`, "gi");
|
|
1198
|
+
return text.replace(pattern, "").trim();
|
|
1199
|
+
}
|
|
1200
|
+
function hasActiveMention3(text, botName) {
|
|
1201
|
+
const stripped = text.replace(/```[\s\S]*?```/g, "").replace(/`[^`]*`/g, "");
|
|
1202
|
+
const escaped = botName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1203
|
+
const pattern = new RegExp(`<at>${escaped}</at>`, "i");
|
|
1204
|
+
return pattern.test(stripped);
|
|
1205
|
+
}
|
|
1206
|
+
function stripHtmlTags(text) {
|
|
1207
|
+
return text.replace(/<[^>]+>/g, "");
|
|
1208
|
+
}
|
|
1209
|
+
function extractQuotedReplyText(attachments) {
|
|
1210
|
+
if (!attachments) return null;
|
|
1211
|
+
for (const attachment of attachments) {
|
|
1212
|
+
if (attachment.contentType !== "text/html" || !attachment.content) continue;
|
|
1213
|
+
if (!attachment.content.includes("schema.skype.com/Reply")) continue;
|
|
1214
|
+
const afterQuote = attachment.content.split("</blockquote>").pop();
|
|
1215
|
+
if (!afterQuote) continue;
|
|
1216
|
+
const text = stripHtmlTags(afterQuote).trim();
|
|
1217
|
+
if (text) return text;
|
|
1218
|
+
}
|
|
1219
|
+
return null;
|
|
1220
|
+
}
|
|
1221
|
+
function wrapResponse(res) {
|
|
1222
|
+
const wrapped = res;
|
|
1223
|
+
wrapped.status = (code) => {
|
|
1224
|
+
res.statusCode = code;
|
|
1225
|
+
return res;
|
|
1226
|
+
};
|
|
1227
|
+
wrapped.send = (body) => {
|
|
1228
|
+
if (body !== void 0 && body !== null) {
|
|
1229
|
+
const bodyStr = typeof body === "string" ? body : JSON.stringify(body);
|
|
1230
|
+
res.setHeader("Content-Type", "application/json");
|
|
1231
|
+
res.end(bodyStr);
|
|
1232
|
+
} else {
|
|
1233
|
+
res.end();
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1236
|
+
return wrapped;
|
|
1237
|
+
}
|
|
1238
|
+
var TeamsConnector = class {
|
|
1239
|
+
channelType = "teams";
|
|
1240
|
+
adapter;
|
|
1241
|
+
config;
|
|
1242
|
+
server = null;
|
|
1243
|
+
/** Stored ConversationReferences for proactive messaging, keyed by threadId */
|
|
1244
|
+
conversationRefs = /* @__PURE__ */ new Map();
|
|
1245
|
+
constructor(config) {
|
|
1246
|
+
this.config = config;
|
|
1247
|
+
if (!this.config.app_id) {
|
|
1248
|
+
throw new Error("Teams connector requires app_id in config");
|
|
1249
|
+
}
|
|
1250
|
+
if (!this.config.app_password) {
|
|
1251
|
+
throw new Error("Teams connector requires app_password in config");
|
|
1252
|
+
}
|
|
1253
|
+
this.adapter = new BotFrameworkAdapter({
|
|
1254
|
+
appId: this.config.app_id,
|
|
1255
|
+
appPassword: this.config.app_password,
|
|
1256
|
+
...this.config.tenant_id ? { channelAuthTenant: this.config.tenant_id } : {}
|
|
1257
|
+
});
|
|
1258
|
+
}
|
|
1259
|
+
/**
|
|
1260
|
+
* Send a message to a Teams thread using a stored ConversationReference.
|
|
1261
|
+
*
|
|
1262
|
+
* Uses the proactive messaging pattern: look up the stored reference
|
|
1263
|
+
* from the inbound turn, then use adapter.continueConversation() to
|
|
1264
|
+
* send a message outside of a turn.
|
|
1265
|
+
*/
|
|
1266
|
+
async sendMessage(req) {
|
|
1267
|
+
const ref = this.conversationRefs.get(req.threadId);
|
|
1268
|
+
if (!ref) {
|
|
1269
|
+
throw new Error(
|
|
1270
|
+
`No ConversationReference stored for thread ${req.threadId}. Cannot send proactive message before receiving an inbound message.`
|
|
1271
|
+
);
|
|
1272
|
+
}
|
|
1273
|
+
let sentActivityId = "";
|
|
1274
|
+
await this.adapter.continueConversation(ref, async (turnContext) => {
|
|
1275
|
+
const response = await turnContext.sendActivity(req.text);
|
|
1276
|
+
sentActivityId = response?.id ?? "";
|
|
1277
|
+
});
|
|
1278
|
+
return sentActivityId;
|
|
1279
|
+
}
|
|
1280
|
+
/**
|
|
1281
|
+
* Start listening for inbound messages via an HTTP webhook.
|
|
1282
|
+
*
|
|
1283
|
+
* Creates a lightweight HTTP server that receives Bot Framework activities
|
|
1284
|
+
* from Azure Bot Service, processes them, and calls the gateway callback.
|
|
1285
|
+
*/
|
|
1286
|
+
async startListening(callback) {
|
|
1287
|
+
const port = this.config.webhook_port ?? 3978;
|
|
1288
|
+
const path = this.config.webhook_path ?? "/api/messages";
|
|
1289
|
+
const requireMention = this.config.require_mention ?? true;
|
|
1290
|
+
const allowThreadRepliesWithoutMention = this.config.allow_thread_replies_without_mention ?? true;
|
|
1291
|
+
let botName = null;
|
|
1292
|
+
this.server = createServer((req, res) => {
|
|
1293
|
+
if (req.method !== "POST" || req.url !== path) {
|
|
1294
|
+
res.statusCode = 404;
|
|
1295
|
+
res.end();
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1298
|
+
const bodyChunks = [];
|
|
1299
|
+
req.on("data", (chunk) => bodyChunks.push(chunk));
|
|
1300
|
+
req.on("end", () => {
|
|
1301
|
+
const bodyStr = Buffer.concat(bodyChunks).toString("utf-8");
|
|
1302
|
+
let body;
|
|
1303
|
+
try {
|
|
1304
|
+
body = JSON.parse(bodyStr);
|
|
1305
|
+
} catch {
|
|
1306
|
+
res.statusCode = 400;
|
|
1307
|
+
res.end("Invalid JSON");
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
req.body = body;
|
|
1311
|
+
this.adapter.processActivity(
|
|
1312
|
+
req,
|
|
1313
|
+
wrapResponse(res),
|
|
1314
|
+
async (turnContext) => {
|
|
1315
|
+
const activity = turnContext.activity;
|
|
1316
|
+
if (activity.type !== "message") {
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1319
|
+
if (activity.from?.id === this.config.app_id) {
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
const ref = TurnContext.getConversationReference(activity);
|
|
1323
|
+
if (!botName && activity.recipient?.name) {
|
|
1324
|
+
botName = activity.recipient.name;
|
|
1325
|
+
console.log(`[teams] Bot name resolved: "${botName}"`);
|
|
1326
|
+
}
|
|
1327
|
+
const conversationType = activity.conversation?.conversationType;
|
|
1328
|
+
const isPersonal = conversationType === "personal";
|
|
1329
|
+
const isThreadReply = !isPersonal && !!activity.replyToId;
|
|
1330
|
+
const rawConversationId = activity.conversation?.id ?? "";
|
|
1331
|
+
const replyToId = activity.replyToId;
|
|
1332
|
+
let threadId;
|
|
1333
|
+
if (isPersonal) {
|
|
1334
|
+
threadId = rawConversationId;
|
|
1335
|
+
} else {
|
|
1336
|
+
let baseConversationId = rawConversationId;
|
|
1337
|
+
let messageIdFromConv;
|
|
1338
|
+
const msgIdIdx = rawConversationId.indexOf(";messageid=");
|
|
1339
|
+
if (msgIdIdx !== -1) {
|
|
1340
|
+
baseConversationId = rawConversationId.substring(0, msgIdIdx);
|
|
1341
|
+
messageIdFromConv = rawConversationId.substring(msgIdIdx + ";messageid=".length);
|
|
1342
|
+
}
|
|
1343
|
+
const rootId = messageIdFromConv ?? replyToId ?? activity.id ?? "";
|
|
1344
|
+
threadId = `${baseConversationId}|${rootId}`;
|
|
1345
|
+
}
|
|
1346
|
+
this.conversationRefs.set(threadId, ref);
|
|
1347
|
+
const quotedReplyText = extractQuotedReplyText(
|
|
1348
|
+
activity.attachments
|
|
1349
|
+
);
|
|
1350
|
+
let messageText = quotedReplyText ?? activity.text ?? "";
|
|
1351
|
+
let hasMention = false;
|
|
1352
|
+
if (activity.entities) {
|
|
1353
|
+
for (const entity of activity.entities) {
|
|
1354
|
+
if (entity.type !== "mention") continue;
|
|
1355
|
+
const mentioned = entity.mentioned;
|
|
1356
|
+
const mentionedId = mentioned?.id ?? "";
|
|
1357
|
+
const isBotMention = mentionedId === this.config.app_id || mentionedId.includes(this.config.app_id);
|
|
1358
|
+
if (!isBotMention) continue;
|
|
1359
|
+
hasMention = true;
|
|
1360
|
+
const mentionText = entity.text;
|
|
1361
|
+
if (mentionText && messageText.includes(mentionText)) {
|
|
1362
|
+
messageText = messageText.replace(mentionText, "").trim();
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
if (!hasMention) {
|
|
1367
|
+
const allBotNames = /* @__PURE__ */ new Set();
|
|
1368
|
+
if (botName) allBotNames.add(botName);
|
|
1369
|
+
if (activity.recipient?.name) allBotNames.add(activity.recipient.name);
|
|
1370
|
+
for (const name of allBotNames) {
|
|
1371
|
+
if (hasActiveMention3(messageText, name)) {
|
|
1372
|
+
hasMention = true;
|
|
1373
|
+
messageText = stripMention2(messageText, name);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
messageText = stripHtmlTags(messageText).trim();
|
|
1378
|
+
if (!messageText) {
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
if (!isPersonal && requireMention) {
|
|
1382
|
+
if (!hasMention) {
|
|
1383
|
+
if (isThreadReply && allowThreadRepliesWithoutMention) {
|
|
1384
|
+
} else {
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
const userName = activity.from?.name;
|
|
1390
|
+
const userAadObjectId = activity.from?.aadObjectId;
|
|
1391
|
+
const channelData = activity.channelData;
|
|
1392
|
+
const teamName = channelData?.team?.name;
|
|
1393
|
+
const channelName = channelData?.channel?.name;
|
|
1394
|
+
const tenantId = channelData?.tenant?.id;
|
|
1395
|
+
callback({
|
|
1396
|
+
threadId,
|
|
1397
|
+
text: messageText,
|
|
1398
|
+
userId: activity.from?.id ?? "unknown",
|
|
1399
|
+
timestamp: activity.timestamp?.toISOString() ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
1400
|
+
metadata: {
|
|
1401
|
+
teams_conversation_type: conversationType,
|
|
1402
|
+
teams_channel_name: channelName,
|
|
1403
|
+
teams_team_name: teamName,
|
|
1404
|
+
teams_user_name: userName,
|
|
1405
|
+
teams_user_aad_id: userAadObjectId,
|
|
1406
|
+
teams_tenant_id: tenantId,
|
|
1407
|
+
requires_mapping_verification: !hasMention && isThreadReply
|
|
1408
|
+
}
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
);
|
|
1412
|
+
});
|
|
1413
|
+
});
|
|
1414
|
+
return new Promise((resolve, reject) => {
|
|
1415
|
+
if (!this.server) {
|
|
1416
|
+
reject(new Error("Server not created"));
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
this.server.on("error", (err) => {
|
|
1420
|
+
console.error(`[teams] HTTP server error:`, err);
|
|
1421
|
+
reject(err);
|
|
1422
|
+
});
|
|
1423
|
+
this.server.listen(port, () => {
|
|
1424
|
+
console.log(`[teams] Webhook server listening on port ${port} at ${path}`);
|
|
1425
|
+
resolve();
|
|
1426
|
+
});
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
/**
|
|
1430
|
+
* Stop the HTTP webhook server
|
|
1431
|
+
*/
|
|
1432
|
+
async stopListening() {
|
|
1433
|
+
if (this.server) {
|
|
1434
|
+
return new Promise((resolve) => {
|
|
1435
|
+
this.server?.close(() => {
|
|
1436
|
+
console.log("[teams] Webhook server stopped");
|
|
1437
|
+
this.server = null;
|
|
1438
|
+
resolve();
|
|
1439
|
+
});
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
/**
|
|
1444
|
+
* Convert markdown to Teams-compatible format.
|
|
1445
|
+
*
|
|
1446
|
+
* Teams natively supports most markdown (bold, italic, code blocks, links, lists).
|
|
1447
|
+
* Main adjustments:
|
|
1448
|
+
* - Collapse <details>/<summary> blocks (not supported in Teams)
|
|
1449
|
+
* - Strip unsupported HTML tags
|
|
1450
|
+
*/
|
|
1451
|
+
formatMessage(markdown) {
|
|
1452
|
+
let text = markdown;
|
|
1453
|
+
text = text.replace(
|
|
1454
|
+
/<details>\s*<summary>([\s\S]*?)<\/summary>\s*([\s\S]*?)<\/details>/gi,
|
|
1455
|
+
(_match, summary, content) => {
|
|
1456
|
+
const summaryText = summary.trim();
|
|
1457
|
+
const contentText = content.trim();
|
|
1458
|
+
return `**${summaryText}**
|
|
1459
|
+
${contentText}`;
|
|
1460
|
+
}
|
|
1461
|
+
);
|
|
1462
|
+
text = stripHtmlTags(text);
|
|
1463
|
+
return text.trim();
|
|
1464
|
+
}
|
|
1465
|
+
};
|
|
1466
|
+
|
|
1024
1467
|
// src/gateway/connector-registry.ts
|
|
1025
1468
|
var connectors = /* @__PURE__ */ new Map();
|
|
1026
1469
|
connectors.set("slack", (config) => new SlackConnector(config));
|
|
1027
1470
|
connectors.set("github", (config) => new GitHubConnector(config));
|
|
1471
|
+
connectors.set("teams", (config) => new TeamsConnector(config));
|
|
1028
1472
|
function getConnector(channelType, config) {
|
|
1029
1473
|
const factory = connectors.get(channelType);
|
|
1030
1474
|
if (!factory) {
|
|
@@ -1045,7 +1489,8 @@ var PLATFORM_LABELS = {
|
|
|
1045
1489
|
discord: "Discord",
|
|
1046
1490
|
github: "GitHub",
|
|
1047
1491
|
whatsapp: "WhatsApp",
|
|
1048
|
-
telegram: "Telegram"
|
|
1492
|
+
telegram: "Telegram",
|
|
1493
|
+
teams: "Microsoft Teams"
|
|
1049
1494
|
};
|
|
1050
1495
|
function formatGatewayContext(ctx) {
|
|
1051
1496
|
const label = PLATFORM_LABELS[ctx.platform] ?? ctx.platform;
|
|
@@ -1082,23 +1527,70 @@ function formatGatewayContext(ctx) {
|
|
|
1082
1527
|
`;
|
|
1083
1528
|
}
|
|
1084
1529
|
|
|
1530
|
+
// src/types/id.ts
|
|
1531
|
+
var SHORT_ID_LENGTH = 24;
|
|
1532
|
+
function toShortId(id, length = SHORT_ID_LENGTH) {
|
|
1533
|
+
return id.replace(/-/g, "").slice(0, Math.min(length, 32));
|
|
1534
|
+
}
|
|
1535
|
+
function shortId(id) {
|
|
1536
|
+
return toShortId(id, SHORT_ID_LENGTH);
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1085
1539
|
// src/gateway/system-message.ts
|
|
1540
|
+
var GATEWAY_SYSTEM_PREFIX = "Agor:";
|
|
1541
|
+
function formatGatewayMarkdownSessionReference(sessionId, sessionUrl) {
|
|
1542
|
+
return sessionUrl ? `[session](${sessionUrl})` : `session ${shortId(sessionId)}`;
|
|
1543
|
+
}
|
|
1544
|
+
function formatGatewaySessionCreatedMessage(sessionId, sessionUrl) {
|
|
1545
|
+
return sessionUrl ? `Session created: ${sessionUrl}` : `Session ${shortId(sessionId)} created, sending prompt to agent...`;
|
|
1546
|
+
}
|
|
1547
|
+
function formatGatewayFollowUpRoutingMessage(sessionId, sessionUrl) {
|
|
1548
|
+
return `Follow-up received \u2014 routing to ${formatGatewayMarkdownSessionReference(sessionId, sessionUrl)} ...`;
|
|
1549
|
+
}
|
|
1086
1550
|
function formatGatewaySystemMessage(channelType, text) {
|
|
1087
1551
|
const sessionCreatedMatch = text.match(/^Session created: (https?:\/\/\S+)$/);
|
|
1088
1552
|
if (channelType === "slack") {
|
|
1089
|
-
const markdown = sessionCreatedMatch ?
|
|
1553
|
+
const markdown = sessionCreatedMatch ? `${GATEWAY_SYSTEM_PREFIX} Session created: [View session](${sessionCreatedMatch[1]})` : `${GATEWAY_SYSTEM_PREFIX} ${text}`;
|
|
1090
1554
|
return markdownToMrkdwn(markdown);
|
|
1091
1555
|
}
|
|
1092
|
-
return
|
|
1556
|
+
return `${GATEWAY_SYSTEM_PREFIX} ${text}`;
|
|
1557
|
+
}
|
|
1558
|
+
function formatGatewaySystemPayload(channelType, text) {
|
|
1559
|
+
const formatted = formatGatewaySystemMessage(channelType, text);
|
|
1560
|
+
if (channelType !== "slack") {
|
|
1561
|
+
return { text: formatted };
|
|
1562
|
+
}
|
|
1563
|
+
return {
|
|
1564
|
+
text: formatted,
|
|
1565
|
+
blocks: [
|
|
1566
|
+
{
|
|
1567
|
+
type: "context",
|
|
1568
|
+
elements: [
|
|
1569
|
+
{
|
|
1570
|
+
type: "mrkdwn",
|
|
1571
|
+
text: formatted
|
|
1572
|
+
}
|
|
1573
|
+
]
|
|
1574
|
+
}
|
|
1575
|
+
]
|
|
1576
|
+
};
|
|
1093
1577
|
}
|
|
1094
1578
|
export {
|
|
1095
1579
|
GitHubConnector,
|
|
1096
1580
|
SlackConnector,
|
|
1581
|
+
TeamsConnector,
|
|
1582
|
+
extractQuotedReplyText,
|
|
1097
1583
|
formatGatewayContext,
|
|
1584
|
+
formatGatewayFollowUpRoutingMessage,
|
|
1585
|
+
formatGatewayMarkdownSessionReference,
|
|
1586
|
+
formatGatewaySessionCreatedMessage,
|
|
1098
1587
|
formatGatewaySystemMessage,
|
|
1588
|
+
formatGatewaySystemPayload,
|
|
1099
1589
|
getConnector,
|
|
1100
1590
|
hasConnector,
|
|
1591
|
+
markdownToMrkdwn,
|
|
1101
1592
|
normalizeOutbound,
|
|
1102
1593
|
parseThreadId as parseGitHubThreadId,
|
|
1594
|
+
parseThreadId3 as parseTeamsThreadId,
|
|
1103
1595
|
registerConnector
|
|
1104
1596
|
};
|