botmux 3.7.1 → 3.8.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/.runtime-build-id +1 -1
- package/dist/adapters/backend/capabilities.d.ts +17 -0
- package/dist/adapters/backend/capabilities.d.ts.map +1 -0
- package/dist/adapters/backend/capabilities.js +22 -0
- package/dist/adapters/backend/capabilities.js.map +1 -0
- package/dist/adapters/backend/critical-control-key.d.ts +19 -0
- package/dist/adapters/backend/critical-control-key.d.ts.map +1 -0
- package/dist/adapters/backend/critical-control-key.js +34 -0
- package/dist/adapters/backend/critical-control-key.js.map +1 -0
- package/dist/adapters/backend/herdr-backend.d.ts +9 -0
- package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
- package/dist/adapters/backend/herdr-backend.js +23 -4
- package/dist/adapters/backend/herdr-backend.js.map +1 -1
- package/dist/adapters/backend/riff-backend.d.ts.map +1 -1
- package/dist/adapters/backend/riff-backend.js +3 -2
- package/dist/adapters/backend/riff-backend.js.map +1 -1
- package/dist/adapters/backend/session-backend-selector.d.ts +61 -6
- package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -1
- package/dist/adapters/backend/session-backend-selector.js +173 -9
- package/dist/adapters/backend/session-backend-selector.js.map +1 -1
- package/dist/adapters/backend/tmux-backend.d.ts +10 -3
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +25 -8
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.js +3 -2
- package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
- package/dist/adapters/backend/types.d.ts +45 -4
- package/dist/adapters/backend/types.d.ts.map +1 -1
- package/dist/adapters/backend/types.js +11 -0
- package/dist/adapters/backend/types.js.map +1 -1
- package/dist/adapters/backend/zellij-backend.d.ts.map +1 -1
- package/dist/adapters/backend/zellij-backend.js +3 -2
- package/dist/adapters/backend/zellij-backend.js.map +1 -1
- package/dist/adapters/backend/zmx-backend.d.ts +286 -0
- package/dist/adapters/backend/zmx-backend.d.ts.map +1 -0
- package/dist/adapters/backend/zmx-backend.js +2396 -0
- package/dist/adapters/backend/zmx-backend.js.map +1 -0
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +3 -0
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/adapters/cli/codex-app.d.ts.map +1 -1
- package/dist/adapters/cli/codex-app.js +5 -1
- package/dist/adapters/cli/codex-app.js.map +1 -1
- package/dist/adapters/cli/codex.d.ts.map +1 -1
- package/dist/adapters/cli/codex.js +26 -1
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/fs-policy.d.ts +79 -1
- package/dist/adapters/cli/fs-policy.d.ts.map +1 -1
- package/dist/adapters/cli/fs-policy.js +290 -13
- package/dist/adapters/cli/fs-policy.js.map +1 -1
- package/dist/adapters/cli/grok.d.ts.map +1 -1
- package/dist/adapters/cli/grok.js +4 -1
- package/dist/adapters/cli/grok.js.map +1 -1
- package/dist/adapters/cli/oh-my-pi.d.ts.map +1 -1
- package/dist/adapters/cli/oh-my-pi.js +5 -3
- package/dist/adapters/cli/oh-my-pi.js.map +1 -1
- package/dist/adapters/cli/shared-hints.d.ts +7 -4
- package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
- package/dist/adapters/cli/shared-hints.js +52 -35
- package/dist/adapters/cli/shared-hints.js.map +1 -1
- package/dist/adapters/cli/strict-input-handle.d.ts +13 -0
- package/dist/adapters/cli/strict-input-handle.d.ts.map +1 -0
- package/dist/adapters/cli/strict-input-handle.js +39 -0
- package/dist/adapters/cli/strict-input-handle.js.map +1 -0
- package/dist/adapters/cli/traex.d.ts.map +1 -1
- package/dist/adapters/cli/traex.js +6 -4
- package/dist/adapters/cli/traex.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +16 -0
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/bot-registry.d.ts +137 -8
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +298 -12
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/session-list-liveness.d.ts +1 -1
- package/dist/cli/session-list-liveness.js +1 -1
- package/dist/cli/zmx-managed-attach.d.ts +41 -0
- package/dist/cli/zmx-managed-attach.d.ts.map +1 -0
- package/dist/cli/zmx-managed-attach.js +72 -0
- package/dist/cli/zmx-managed-attach.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +780 -131
- package/dist/cli.js.map +1 -1
- package/dist/codex-app-runner.js +90 -2
- package/dist/codex-app-runner.js.map +1 -1
- package/dist/codex-rpc-engine.d.ts.map +1 -1
- package/dist/codex-rpc-engine.js +22 -6
- package/dist/codex-rpc-engine.js.map +1 -1
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +29 -1
- package/dist/config.js.map +1 -1
- package/dist/core/ask-broker.d.ts +22 -1
- package/dist/core/ask-broker.d.ts.map +1 -1
- package/dist/core/ask-broker.js +12 -5
- package/dist/core/ask-broker.js.map +1 -1
- package/dist/core/botmux-wrapper.d.ts +18 -0
- package/dist/core/botmux-wrapper.d.ts.map +1 -1
- package/dist/core/botmux-wrapper.js +25 -1
- package/dist/core/botmux-wrapper.js.map +1 -1
- package/dist/core/chat-rename.d.ts +27 -0
- package/dist/core/chat-rename.d.ts.map +1 -0
- package/dist/core/chat-rename.js +53 -0
- package/dist/core/chat-rename.js.map +1 -0
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +160 -12
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/cost-calculator.d.ts +25 -1
- package/dist/core/cost-calculator.d.ts.map +1 -1
- package/dist/core/cost-calculator.js +102 -4
- package/dist/core/cost-calculator.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts +16 -2
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +611 -62
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dashboard-rows.d.ts +22 -1
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +61 -0
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/core/dashboard-url.d.ts +6 -0
- package/dist/core/dashboard-url.d.ts.map +1 -1
- package/dist/core/dashboard-url.js +11 -1
- package/dist/core/dashboard-url.js.map +1 -1
- package/dist/core/device-isolation-daemon.d.ts +28 -6
- package/dist/core/device-isolation-daemon.d.ts.map +1 -1
- package/dist/core/device-isolation-daemon.js +96 -13
- package/dist/core/device-isolation-daemon.js.map +1 -1
- package/dist/core/host-overload-alert.d.ts +75 -0
- package/dist/core/host-overload-alert.d.ts.map +1 -1
- package/dist/core/host-overload-alert.js +103 -0
- package/dist/core/host-overload-alert.js.map +1 -1
- package/dist/core/idle-worker-sweeper.js +1 -1
- package/dist/core/idle-worker-sweeper.js.map +1 -1
- package/dist/core/inflight-input-tracker.d.ts +3 -0
- package/dist/core/inflight-input-tracker.d.ts.map +1 -1
- package/dist/core/inflight-input-tracker.js +9 -0
- package/dist/core/inflight-input-tracker.js.map +1 -1
- package/dist/core/passthrough-commands.d.ts.map +1 -1
- package/dist/core/passthrough-commands.js +10 -0
- package/dist/core/passthrough-commands.js.map +1 -1
- package/dist/core/persistent-backend.d.ts +32 -4
- package/dist/core/persistent-backend.d.ts.map +1 -1
- package/dist/core/persistent-backend.js +75 -6
- package/dist/core/persistent-backend.js.map +1 -1
- package/dist/core/plugins/mcp/gateway.js +2 -2
- package/dist/core/plugins/mcp/gateway.js.map +1 -1
- package/dist/core/plugins/runtime.d.ts +3 -0
- package/dist/core/plugins/runtime.d.ts.map +1 -1
- package/dist/core/plugins/runtime.js.map +1 -1
- package/dist/core/plugins/service-manager.d.ts +4 -1
- package/dist/core/plugins/service-manager.d.ts.map +1 -1
- package/dist/core/plugins/service-manager.js +11 -6
- package/dist/core/plugins/service-manager.js.map +1 -1
- package/dist/core/role-library.d.ts +48 -1
- package/dist/core/role-library.d.ts.map +1 -1
- package/dist/core/role-library.js +111 -3
- package/dist/core/role-library.js.map +1 -1
- package/dist/core/role-resolver.d.ts +14 -2
- package/dist/core/role-resolver.d.ts.map +1 -1
- package/dist/core/role-resolver.js +47 -4
- package/dist/core/role-resolver.js.map +1 -1
- package/dist/core/session-activity.d.ts +14 -0
- package/dist/core/session-activity.d.ts.map +1 -1
- package/dist/core/session-activity.js +46 -1
- package/dist/core/session-activity.js.map +1 -1
- package/dist/core/session-board.d.ts +5 -2
- package/dist/core/session-board.d.ts.map +1 -1
- package/dist/core/session-board.js +5 -2
- package/dist/core/session-board.js.map +1 -1
- package/dist/core/session-liveness.d.ts +6 -5
- package/dist/core/session-liveness.d.ts.map +1 -1
- package/dist/core/session-liveness.js +34 -13
- package/dist/core/session-liveness.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -2
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +397 -103
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-marker.d.ts +11 -2
- package/dist/core/session-marker.d.ts.map +1 -1
- package/dist/core/session-marker.js +50 -11
- package/dist/core/session-marker.js.map +1 -1
- package/dist/core/session-message-preview.d.ts +20 -0
- package/dist/core/session-message-preview.d.ts.map +1 -0
- package/dist/core/session-message-preview.js +188 -0
- package/dist/core/session-message-preview.js.map +1 -0
- package/dist/core/session-title.d.ts +5 -1
- package/dist/core/session-title.d.ts.map +1 -1
- package/dist/core/session-title.js +20 -3
- package/dist/core/session-title.js.map +1 -1
- package/dist/core/startup-commands.d.ts +1 -1
- package/dist/core/startup-commands.js +1 -1
- package/dist/core/terminal-url.d.ts.map +1 -1
- package/dist/core/terminal-url.js +3 -2
- package/dist/core/terminal-url.js.map +1 -1
- package/dist/core/trigger-session.d.ts.map +1 -1
- package/dist/core/trigger-session.js +75 -12
- package/dist/core/trigger-session.js.map +1 -1
- package/dist/core/types.d.ts +35 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +23 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-ipc.d.ts +11 -0
- package/dist/core/worker-ipc.d.ts.map +1 -0
- package/dist/core/worker-ipc.js +26 -0
- package/dist/core/worker-ipc.js.map +1 -0
- package/dist/core/worker-pool.d.ts +179 -29
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +2118 -331
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts +132 -3
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +1327 -449
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/auth.d.ts +2 -0
- package/dist/dashboard/auth.d.ts.map +1 -1
- package/dist/dashboard/auth.js +9 -0
- package/dist/dashboard/auth.js.map +1 -1
- package/dist/dashboard/bot-payload.d.ts +4 -0
- package/dist/dashboard/bot-payload.d.ts.map +1 -1
- package/dist/dashboard/bot-payload.js +5 -0
- package/dist/dashboard/bot-payload.js.map +1 -1
- package/dist/dashboard/federation-api.d.ts.map +1 -1
- package/dist/dashboard/federation-api.js +4 -0
- package/dist/dashboard/federation-api.js.map +1 -1
- package/dist/dashboard/federation-spoke-api.d.ts.map +1 -1
- package/dist/dashboard/federation-spoke-api.js +32 -5
- package/dist/dashboard/federation-spoke-api.js.map +1 -1
- package/dist/dashboard/public-redact.d.ts +8 -2
- package/dist/dashboard/public-redact.d.ts.map +1 -1
- package/dist/dashboard/public-redact.js +34 -7
- package/dist/dashboard/public-redact.js.map +1 -1
- package/dist/dashboard/session-card-model.d.ts.map +1 -1
- package/dist/dashboard/session-card-model.js +10 -2
- package/dist/dashboard/session-card-model.js.map +1 -1
- package/dist/dashboard/settings-write-applier.d.ts +35 -1
- package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
- package/dist/dashboard/settings-write-applier.js +88 -1
- package/dist/dashboard/settings-write-applier.js.map +1 -1
- package/dist/dashboard/web/app.d.ts.map +1 -1
- package/dist/dashboard/web/app.js +0 -1
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts +15 -0
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.js +212 -58
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts +3 -0
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/bot-onboarding.d.ts +2 -1
- package/dist/dashboard/web/bot-onboarding.d.ts.map +1 -1
- package/dist/dashboard/web/bot-onboarding.js.map +1 -1
- package/dist/dashboard/web/clipboard.d.ts +2 -0
- package/dist/dashboard/web/clipboard.d.ts.map +1 -0
- package/dist/dashboard/web/clipboard.js +42 -0
- package/dist/dashboard/web/clipboard.js.map +1 -0
- package/dist/dashboard/web/connectors-page.d.ts.map +1 -1
- package/dist/dashboard/web/connectors-page.js +12 -8
- package/dist/dashboard/web/connectors-page.js.map +1 -1
- package/dist/dashboard/web/dashboard-components.d.ts +17 -16
- package/dist/dashboard/web/dashboard-components.d.ts.map +1 -1
- package/dist/dashboard/web/dashboard-components.js.map +1 -1
- package/dist/dashboard/web/groups-page.d.ts.map +1 -1
- package/dist/dashboard/web/groups-page.js +7 -3
- package/dist/dashboard/web/groups-page.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +205 -12
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/icon-tooltip.d.ts.map +1 -1
- package/dist/dashboard/web/icon-tooltip.js +16 -1
- package/dist/dashboard/web/icon-tooltip.js.map +1 -1
- package/dist/dashboard/web/listener-filters.d.ts +23 -0
- package/dist/dashboard/web/listener-filters.d.ts.map +1 -0
- package/dist/dashboard/web/listener-filters.js +36 -0
- package/dist/dashboard/web/listener-filters.js.map +1 -0
- package/dist/dashboard/web/overview-page.d.ts.map +1 -1
- package/dist/dashboard/web/overview-page.js.map +1 -1
- package/dist/dashboard/web/plugin-page.d.ts.map +1 -1
- package/dist/dashboard/web/plugin-page.js.map +1 -1
- package/dist/dashboard/web/preview-markdown.d.ts +5 -0
- package/dist/dashboard/web/preview-markdown.d.ts.map +1 -0
- package/dist/dashboard/web/preview-markdown.js +52 -0
- package/dist/dashboard/web/preview-markdown.js.map +1 -0
- package/dist/dashboard/web/roles-page.d.ts.map +1 -1
- package/dist/dashboard/web/roles-page.js +535 -10
- package/dist/dashboard/web/roles-page.js.map +1 -1
- package/dist/dashboard/web/roles.d.ts +77 -0
- package/dist/dashboard/web/roles.d.ts.map +1 -1
- package/dist/dashboard/web/roles.js +98 -0
- package/dist/dashboard/web/roles.js.map +1 -1
- package/dist/dashboard/web/session-terminal.d.ts.map +1 -1
- package/dist/dashboard/web/session-terminal.js +6 -4
- package/dist/dashboard/web/session-terminal.js.map +1 -1
- package/dist/dashboard/web/sessions-kanban.d.ts +4 -1
- package/dist/dashboard/web/sessions-kanban.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-kanban.js +1 -1
- package/dist/dashboard/web/sessions-kanban.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts +3 -2
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-page.js +163 -28
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts +25 -0
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +58 -7
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/settings-page.d.ts +28 -3
- package/dist/dashboard/web/settings-page.d.ts.map +1 -1
- package/dist/dashboard/web/settings-page.js +61 -1
- package/dist/dashboard/web/settings-page.js.map +1 -1
- package/dist/dashboard/web/skills-page.d.ts +6 -5
- package/dist/dashboard/web/skills-page.d.ts.map +1 -1
- package/dist/dashboard/web/skills-page.js +2 -0
- package/dist/dashboard/web/skills-page.js.map +1 -1
- package/dist/dashboard/web/v3-components.d.ts +3 -2
- package/dist/dashboard/web/v3-components.d.ts.map +1 -1
- package/dist/dashboard/web/v3-components.js.map +1 -1
- package/dist/dashboard/web/vc-consumer-profiles-section.d.ts +12 -2
- package/dist/dashboard/web/vc-consumer-profiles-section.d.ts.map +1 -1
- package/dist/dashboard/web/vc-consumer-profiles-section.js +0 -9
- package/dist/dashboard/web/vc-consumer-profiles-section.js.map +1 -1
- package/dist/dashboard/web/webhook-logs-page.d.ts +2 -1
- package/dist/dashboard/web/webhook-logs-page.d.ts.map +1 -1
- package/dist/dashboard/web/webhook-logs-page.js +4 -1
- package/dist/dashboard/web/webhook-logs-page.js.map +1 -1
- package/dist/dashboard-web/app.js +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-FAPIMQV3.js +10 -0
- package/dist/dashboard-web/chunks/{chunk-QFMH6ITB.js → chunk-5CJMHTT4.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-KQB42ML5.js → chunk-DLZK52JU.js} +14 -12
- package/dist/dashboard-web/chunks/chunk-FDZ7WOBW.js +16 -0
- package/dist/dashboard-web/chunks/{chunk-3QAUJXAS.js → chunk-GTAJV5YC.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-FNPGOZMX.js → chunk-IHNG6KE6.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-FLGXZJTD.js → chunk-VA6QWSGQ.js} +1 -1
- package/dist/dashboard-web/chunks/chunk-XJ7BGPJH.js +1 -0
- package/dist/dashboard-web/chunks/chunk-ZJVTGU5X.js +1 -0
- package/dist/dashboard-web/chunks/connectors-page-LKWRT3GS.js +1 -0
- package/dist/dashboard-web/chunks/groups-page-V6654ICQ.js +8 -0
- package/dist/dashboard-web/chunks/insights-page-237RMFQ5.js +7 -0
- package/dist/dashboard-web/chunks/{monitor-room-7IVIS75W.js → monitor-room-OO5Y4FRQ.js} +1 -1
- package/dist/dashboard-web/chunks/{monitoring-page-5SSJRQZF.js → monitoring-page-OUEITM5P.js} +1 -1
- package/dist/dashboard-web/chunks/{office-page-EOND3L5D.js → office-page-4KNAHQ4Q.js} +1 -1
- package/dist/dashboard-web/chunks/{overview-page-NISBVBBJ.js → overview-page-QDP4YK2S.js} +1 -1
- package/dist/dashboard-web/chunks/{plugin-page-JXC5F5YV.js → plugin-page-VEGTCEAS.js} +1 -1
- package/dist/dashboard-web/chunks/roles-page-PGXNZZNP.js +1 -0
- package/dist/dashboard-web/chunks/{schedules-page-AVOOKLUH.js → schedules-page-BJNC5TID.js} +1 -1
- package/dist/dashboard-web/chunks/sessions-page-M2ZYYCMO.js +6 -0
- package/dist/dashboard-web/chunks/settings-page-IJFZKUUW.js +2 -0
- package/dist/dashboard-web/chunks/{skills-page-5MW54PCC.js → skills-page-YRAIRZOQ.js} +3 -3
- package/dist/dashboard-web/chunks/{team-federation-page-2SNIMVXI.js → team-federation-page-DEU27GRU.js} +1 -1
- package/dist/dashboard-web/chunks/{v3-page-W6SBXXQC.js → v3-page-6KHEW2YL.js} +5 -5
- package/dist/dashboard-web/chunks/{whiteboards-page-STC54KTP.js → whiteboards-page-VDECAALH.js} +1 -1
- package/dist/dashboard-web/style.css +12545 -11432
- package/dist/dashboard.js +215 -36
- package/dist/dashboard.js.map +1 -1
- package/dist/global-config.d.ts +41 -2
- package/dist/global-config.d.ts.map +1 -1
- package/dist/global-config.js +47 -0
- package/dist/global-config.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +71 -19
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +71 -19
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/callback-button-marker.d.ts +34 -0
- package/dist/im/lark/callback-button-marker.d.ts.map +1 -0
- package/dist/im/lark/callback-button-marker.js +99 -0
- package/dist/im/lark/callback-button-marker.js.map +1 -0
- package/dist/im/lark/card-builder.d.ts +46 -10
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +299 -78
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts +3 -4
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +380 -148
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +24 -1
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +101 -8
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/doc-comment.d.ts.map +1 -1
- package/dist/im/lark/doc-comment.js +6 -1
- package/dist/im/lark/doc-comment.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +115 -3
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +534 -147
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/grant-command.d.ts +16 -12
- package/dist/im/lark/grant-command.d.ts.map +1 -1
- package/dist/im/lark/grant-command.js +48 -151
- package/dist/im/lark/grant-command.js.map +1 -1
- package/dist/im/lark/grant-pending.d.ts +12 -4
- package/dist/im/lark/grant-pending.d.ts.map +1 -1
- package/dist/im/lark/grant-pending.js +31 -8
- package/dist/im/lark/grant-pending.js.map +1 -1
- package/dist/im/lark/invite-command.d.ts +20 -0
- package/dist/im/lark/invite-command.d.ts.map +1 -0
- package/dist/im/lark/invite-command.js +239 -0
- package/dist/im/lark/invite-command.js.map +1 -0
- package/dist/im/lark/md-card.d.ts +66 -4
- package/dist/im/lark/md-card.d.ts.map +1 -1
- package/dist/im/lark/md-card.js +201 -31
- package/dist/im/lark/md-card.js.map +1 -1
- package/dist/im/lark/mention-targets.d.ts +43 -0
- package/dist/im/lark/mention-targets.d.ts.map +1 -0
- package/dist/im/lark/mention-targets.js +190 -0
- package/dist/im/lark/mention-targets.js.map +1 -0
- package/dist/im/lark/message-parser.d.ts +31 -0
- package/dist/im/lark/message-parser.d.ts.map +1 -1
- package/dist/im/lark/message-parser.js +305 -32
- package/dist/im/lark/message-parser.js.map +1 -1
- package/dist/im/lark/reply-card-footer-signature.d.ts +7 -0
- package/dist/im/lark/reply-card-footer-signature.d.ts.map +1 -0
- package/dist/im/lark/reply-card-footer-signature.js +7 -0
- package/dist/im/lark/reply-card-footer-signature.js.map +1 -0
- package/dist/im/lark/sessions-card.d.ts.map +1 -1
- package/dist/im/lark/sessions-card.js +4 -1
- package/dist/im/lark/sessions-card.js.map +1 -1
- package/dist/im/lark/substitute-command.d.ts.map +1 -1
- package/dist/im/lark/substitute-command.js +8 -0
- package/dist/im/lark/substitute-command.js.map +1 -1
- package/dist/im/lark/topic-root-context.d.ts +35 -0
- package/dist/im/lark/topic-root-context.d.ts.map +1 -0
- package/dist/im/lark/topic-root-context.js +37 -0
- package/dist/im/lark/topic-root-context.js.map +1 -0
- package/dist/im/lark/v3-blocked-card.d.ts.map +1 -1
- package/dist/im/lark/v3-blocked-card.js +2 -1
- package/dist/im/lark/v3-blocked-card.js.map +1 -1
- package/dist/im/lark/v3-gate-card.d.ts.map +1 -1
- package/dist/im/lark/v3-gate-card.js +2 -1
- package/dist/im/lark/v3-gate-card.js.map +1 -1
- package/dist/im/lark/v3-loop-grant-card.d.ts.map +1 -1
- package/dist/im/lark/v3-loop-grant-card.js +2 -1
- package/dist/im/lark/v3-loop-grant-card.js.map +1 -1
- package/dist/im/lark/v3-progress-card.d.ts.map +1 -1
- package/dist/im/lark/v3-progress-card.js +2 -1
- package/dist/im/lark/v3-progress-card.js.map +1 -1
- package/dist/im/lark/v3-revisit-grant-card.d.ts.map +1 -1
- package/dist/im/lark/v3-revisit-grant-card.js +2 -1
- package/dist/im/lark/v3-revisit-grant-card.js.map +1 -1
- package/dist/index-core-only.d.ts +3 -0
- package/dist/index-core-only.d.ts.map +1 -0
- package/dist/index-core-only.js +107 -0
- package/dist/index-core-only.js.map +1 -0
- package/dist/services/async-trigger-state.d.ts +8 -0
- package/dist/services/async-trigger-state.d.ts.map +1 -1
- package/dist/services/async-trigger-state.js +3 -2
- package/dist/services/async-trigger-state.js.map +1 -1
- package/dist/services/async-trigger-store.d.ts +10 -2
- package/dist/services/async-trigger-store.d.ts.map +1 -1
- package/dist/services/async-trigger-store.js +3 -2
- package/dist/services/async-trigger-store.js.map +1 -1
- package/dist/services/backend-availability.d.ts +3 -1
- package/dist/services/backend-availability.d.ts.map +1 -1
- package/dist/services/backend-availability.js +14 -1
- package/dist/services/backend-availability.js.map +1 -1
- package/dist/services/backend-type-store.d.ts.map +1 -1
- package/dist/services/backend-type-store.js +1 -1
- package/dist/services/backend-type-store.js.map +1 -1
- package/dist/services/bot-config-store.d.ts.map +1 -1
- package/dist/services/bot-config-store.js +2 -1
- package/dist/services/bot-config-store.js.map +1 -1
- package/dist/services/bridge-fallback-gate.d.ts +14 -1
- package/dist/services/bridge-fallback-gate.d.ts.map +1 -1
- package/dist/services/bridge-fallback-gate.js +65 -1
- package/dist/services/bridge-fallback-gate.js.map +1 -1
- package/dist/services/card-prefs-store.d.ts +7 -2
- package/dist/services/card-prefs-store.d.ts.map +1 -1
- package/dist/services/card-prefs-store.js +30 -4
- package/dist/services/card-prefs-store.js.map +1 -1
- package/dist/services/codex-app-runner-protocol.d.ts +9 -0
- package/dist/services/codex-app-runner-protocol.d.ts.map +1 -1
- package/dist/services/codex-app-runner-protocol.js +17 -0
- package/dist/services/codex-app-runner-protocol.js.map +1 -1
- package/dist/services/codex-app-token-usage.d.ts +93 -0
- package/dist/services/codex-app-token-usage.d.ts.map +1 -0
- package/dist/services/codex-app-token-usage.js +190 -0
- package/dist/services/codex-app-token-usage.js.map +1 -0
- package/dist/services/codex-transcript.d.ts +6 -1
- package/dist/services/codex-transcript.d.ts.map +1 -1
- package/dist/services/codex-transcript.js +103 -32
- package/dist/services/codex-transcript.js.map +1 -1
- package/dist/services/federation-roster.d.ts +4 -0
- package/dist/services/federation-roster.d.ts.map +1 -1
- package/dist/services/federation-roster.js +3 -0
- package/dist/services/federation-roster.js.map +1 -1
- package/dist/services/federation-store.d.ts +6 -0
- package/dist/services/federation-store.d.ts.map +1 -1
- package/dist/services/federation-store.js.map +1 -1
- package/dist/services/grant-policy.d.ts +13 -0
- package/dist/services/grant-policy.d.ts.map +1 -0
- package/dist/services/grant-policy.js +40 -0
- package/dist/services/grant-policy.js.map +1 -0
- package/dist/services/grant-store.d.ts +24 -3
- package/dist/services/grant-store.d.ts.map +1 -1
- package/dist/services/grant-store.js +196 -12
- package/dist/services/grant-store.js.map +1 -1
- package/dist/services/groups-store.d.ts +36 -0
- package/dist/services/groups-store.d.ts.map +1 -1
- package/dist/services/groups-store.js +123 -1
- package/dist/services/groups-store.js.map +1 -1
- package/dist/services/jsonl-cursor.d.ts.map +1 -1
- package/dist/services/jsonl-cursor.js +8 -2
- package/dist/services/jsonl-cursor.js.map +1 -1
- package/dist/services/local-cli-opener.d.ts.map +1 -1
- package/dist/services/local-cli-opener.js +32 -0
- package/dist/services/local-cli-opener.js.map +1 -1
- package/dist/services/message-listener-run-preview-store.d.ts +43 -0
- package/dist/services/message-listener-run-preview-store.d.ts.map +1 -0
- package/dist/services/message-listener-run-preview-store.js +152 -0
- package/dist/services/message-listener-run-preview-store.js.map +1 -0
- package/dist/services/message-listener-store.d.ts +26 -0
- package/dist/services/message-listener-store.d.ts.map +1 -0
- package/dist/services/message-listener-store.js +138 -0
- package/dist/services/message-listener-store.js.map +1 -0
- package/dist/services/message-listener.d.ts +112 -0
- package/dist/services/message-listener.d.ts.map +1 -0
- package/dist/services/message-listener.js +391 -0
- package/dist/services/message-listener.js.map +1 -0
- package/dist/services/overload-alert-migration.d.ts +15 -0
- package/dist/services/overload-alert-migration.d.ts.map +1 -0
- package/dist/services/overload-alert-migration.js +115 -0
- package/dist/services/overload-alert-migration.js.map +1 -0
- package/dist/services/send-policy.d.ts +38 -0
- package/dist/services/send-policy.d.ts.map +1 -1
- package/dist/services/send-policy.js +34 -0
- package/dist/services/send-policy.js.map +1 -1
- package/dist/services/session-store.d.ts +12 -1
- package/dist/services/session-store.d.ts.map +1 -1
- package/dist/services/session-store.js +44 -2
- package/dist/services/session-store.js.map +1 -1
- package/dist/services/skill-registry-store.d.ts.map +1 -1
- package/dist/services/skill-registry-store.js +87 -12
- package/dist/services/skill-registry-store.js.map +1 -1
- package/dist/services/substitute-mode-normalize.d.ts +3 -0
- package/dist/services/substitute-mode-normalize.d.ts.map +1 -1
- package/dist/services/substitute-mode-normalize.js +8 -0
- package/dist/services/substitute-mode-normalize.js.map +1 -1
- package/dist/services/substitute-mode-store.d.ts.map +1 -1
- package/dist/services/substitute-mode-store.js +8 -1
- package/dist/services/substitute-mode-store.js.map +1 -1
- package/dist/services/transcript-resolver.d.ts +6 -1
- package/dist/services/transcript-resolver.d.ts.map +1 -1
- package/dist/services/transcript-resolver.js +145 -29
- package/dist/services/transcript-resolver.js.map +1 -1
- package/dist/services/trigger-types.d.ts +16 -0
- package/dist/services/trigger-types.d.ts.map +1 -1
- package/dist/services/trigger-types.js +6 -0
- package/dist/services/trigger-types.js.map +1 -1
- package/dist/setup/bot-config-editor.js +2 -2
- package/dist/setup/bot-config-editor.js.map +1 -1
- package/dist/setup/ensure-zmx.d.ts +31 -0
- package/dist/setup/ensure-zmx.d.ts.map +1 -0
- package/dist/setup/ensure-zmx.js +161 -0
- package/dist/setup/ensure-zmx.js.map +1 -0
- package/dist/setup/index.d.ts +1 -1
- package/dist/setup/index.js +1 -1
- package/dist/setup/open-platform-automation.d.ts +9 -0
- package/dist/setup/open-platform-automation.d.ts.map +1 -1
- package/dist/setup/open-platform-automation.js +15 -2
- package/dist/setup/open-platform-automation.js.map +1 -1
- package/dist/setup/setup-args.d.ts +1 -1
- package/dist/setup/setup-args.d.ts.map +1 -1
- package/dist/setup/setup-args.js +1 -1
- package/dist/skills/definitions.d.ts.map +1 -1
- package/dist/skills/definitions.js +32 -0
- package/dist/skills/definitions.js.map +1 -1
- package/dist/skills/injection-mode.d.ts +6 -2
- package/dist/skills/injection-mode.d.ts.map +1 -1
- package/dist/skills/injection-mode.js +10 -5
- package/dist/skills/injection-mode.js.map +1 -1
- package/dist/types.d.ts +79 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/child-env.d.ts +1 -1
- package/dist/utils/child-env.d.ts.map +1 -1
- package/dist/utils/child-env.js +4 -0
- package/dist/utils/child-env.js.map +1 -1
- package/dist/utils/effort-confirm-dialog.d.ts +40 -0
- package/dist/utils/effort-confirm-dialog.d.ts.map +1 -0
- package/dist/utils/effort-confirm-dialog.js +74 -0
- package/dist/utils/effort-confirm-dialog.js.map +1 -0
- package/dist/utils/pending-input-queue.d.ts +56 -0
- package/dist/utils/pending-input-queue.d.ts.map +1 -1
- package/dist/utils/pending-input-queue.js +80 -0
- package/dist/utils/pending-input-queue.js.map +1 -1
- package/dist/utils/render-dimensions.d.ts +8 -0
- package/dist/utils/render-dimensions.d.ts.map +1 -1
- package/dist/utils/render-dimensions.js +10 -0
- package/dist/utils/render-dimensions.js.map +1 -1
- package/dist/utils/stuck-key-guard.d.ts +3 -2
- package/dist/utils/stuck-key-guard.d.ts.map +1 -1
- package/dist/utils/stuck-key-guard.js +3 -3
- package/dist/utils/stuck-key-guard.js.map +1 -1
- package/dist/utils/terminal-renderer.d.ts +6 -0
- package/dist/utils/terminal-renderer.d.ts.map +1 -1
- package/dist/utils/terminal-renderer.js +15 -0
- package/dist/utils/terminal-renderer.js.map +1 -1
- package/dist/utils/tui-input-delivery.d.ts +32 -0
- package/dist/utils/tui-input-delivery.d.ts.map +1 -0
- package/dist/utils/tui-input-delivery.js +53 -0
- package/dist/utils/tui-input-delivery.js.map +1 -0
- package/dist/utils/xml.d.ts +19 -0
- package/dist/utils/xml.d.ts.map +1 -0
- package/dist/utils/xml.js +26 -0
- package/dist/utils/xml.js.map +1 -0
- package/dist/worker.js +1852 -374
- package/dist/worker.js.map +1 -1
- package/dist/workflows/definition.d.ts +8 -8
- package/dist/workflows/events/payloads.d.ts +8 -8
- package/dist/workflows/events/schema.d.ts +160 -160
- package/dist/workflows/v3/session-relay-client.js +1 -1
- package/dist/workflows/v3/session-relay-client.js.map +1 -1
- package/dist/workflows/v3/worker-fence.d.ts.map +1 -1
- package/dist/workflows/v3/worker-fence.js +15 -10
- package/dist/workflows/v3/worker-fence.js.map +1 -1
- package/package.json +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-UKA7K4JV.js +0 -10
- package/dist/dashboard-web/chunks/chunk-DFLNXQNT.js +0 -1
- package/dist/dashboard-web/chunks/connectors-page-A77YAB5Y.js +0 -1
- package/dist/dashboard-web/chunks/groups-page-RUZNVXQB.js +0 -8
- package/dist/dashboard-web/chunks/insights-page-RF7U7RTA.js +0 -22
- package/dist/dashboard-web/chunks/roles-page-BUMKD7Y4.js +0 -1
- package/dist/dashboard-web/chunks/sessions-page-6HLSEAB7.js +0 -2
- package/dist/dashboard-web/chunks/settings-page-MJDZHQ4X.js +0 -2
|
@@ -1,11 +1,94 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
3
3
|
import { DropdownMenu, Html, LoadingState, RefreshIconButton } from './dashboard-components.js';
|
|
4
|
+
import { applyListenerFilterState, filterListenerTargets, listenerTargetStateFor, } from './listener-filters.js';
|
|
4
5
|
import { useT } from './react-hooks.js';
|
|
5
6
|
import { mountReactPage } from './react-mount.js';
|
|
6
7
|
import { hasExplicitChatRole, summarizeGroupProfileMatches, } from './role-profile-match.js';
|
|
7
|
-
import { applyRoleProfile, botInChatCount, botRoleCount, byteLength, deleteProfileEntry, deleteRole, entryForBot, filterRoleGroups, filterRoleProfiles, hashChatId, isValidProfileId, loadGroups, loadProfileEntries, loadProfileEntry, loadProfiles, loadRole, loadRoleProfileContext, MAX_ROLE_BYTES, roleKey, ROLE_WARN_BYTES, saveInjectMode, saveProfileEntry, saveRole, } from './roles.js';
|
|
8
|
+
import { applyRoleProfile, botInChatCount, botRoleCount, byteLength, deleteProfileEntry, deleteMessageListener, deleteRole, entryForBot, filterRoleGroups, filterRoleProfiles, formatListenerPreviewTime, hashChatId, isValidProfileId, loadGroupMemberDisplays, loadGroups, loadMessageListenerRunPreviewStatus, loadMessageListener, loadProfileEntries, loadProfileEntry, loadProfiles, loadRole, loadRoleProfileContext, MAX_MESSAGE_LISTENER_PROMPT_BYTES, MAX_ROLE_BYTES, MESSAGE_LISTENER_WARN_BYTES, DEFAULT_MESSAGE_LISTENER_PREVIEW_LIMIT, MAX_MESSAGE_LISTENER_PREVIEW_LIMIT, roleKey, ROLE_WARN_BYTES, saveInjectMode, saveMessageListener, saveProfileEntry, saveRole, previewMessageListener, runMessageListenerPreview, } from './roles.js';
|
|
8
9
|
import { botAvatarHtml, loadNameMaps } from './ui.js';
|
|
10
|
+
const LISTENER_MESSAGE_TYPES = ['text', 'post', 'image', 'interactive'];
|
|
11
|
+
const DEFAULT_LISTENER = {
|
|
12
|
+
enabled: false,
|
|
13
|
+
prompt: '',
|
|
14
|
+
senderPolicy: {
|
|
15
|
+
mode: 'include_only',
|
|
16
|
+
includeSenderTypes: ['user'],
|
|
17
|
+
excludeSelf: true,
|
|
18
|
+
},
|
|
19
|
+
messagePolicy: {
|
|
20
|
+
includeMsgTypes: [...LISTENER_MESSAGE_TYPES],
|
|
21
|
+
scope: 'top_level',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
function cloneListener(listener) {
|
|
25
|
+
return {
|
|
26
|
+
enabled: listener?.enabled === true,
|
|
27
|
+
name: listener?.name ?? '',
|
|
28
|
+
replyCardTitle: listener?.replyCardTitle ?? '',
|
|
29
|
+
workingDir: listener?.workingDir ?? '',
|
|
30
|
+
prompt: listener?.prompt ?? '',
|
|
31
|
+
senderPolicy: {
|
|
32
|
+
mode: 'include_only',
|
|
33
|
+
includeSenderOpenIds: [...(listener?.senderPolicy?.includeSenderOpenIds ?? [])],
|
|
34
|
+
excludeSenderOpenIds: [],
|
|
35
|
+
includeSenderTypes: [...(listener?.senderPolicy?.includeSenderTypes ?? DEFAULT_LISTENER.senderPolicy?.includeSenderTypes ?? [])],
|
|
36
|
+
excludeSenderTypes: [...(listener?.senderPolicy?.excludeSenderTypes ?? [])],
|
|
37
|
+
excludeSelf: listener?.senderPolicy?.excludeSelf !== false,
|
|
38
|
+
},
|
|
39
|
+
messagePolicy: {
|
|
40
|
+
includeMsgTypes: [...(listener?.messagePolicy?.includeMsgTypes ?? DEFAULT_LISTENER.messagePolicy?.includeMsgTypes ?? [])],
|
|
41
|
+
scope: 'top_level',
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function listenerHasConfig(listener) {
|
|
46
|
+
return listener?.enabled === true && listener.prompt.trim().length > 0;
|
|
47
|
+
}
|
|
48
|
+
function groupHasAnyRoleOrListener(group) {
|
|
49
|
+
return group.memberBots.some(bot => bot.inChat && (bot.hasRole || bot.hasMessageListener));
|
|
50
|
+
}
|
|
51
|
+
function memberDisplayName(member, openId) {
|
|
52
|
+
return member?.name || openId;
|
|
53
|
+
}
|
|
54
|
+
function listenerSenderTypeMatches(member, listener) {
|
|
55
|
+
const includeTypes = new Set(listener.senderPolicy?.includeSenderTypes ?? DEFAULT_LISTENER.senderPolicy?.includeSenderTypes ?? []);
|
|
56
|
+
if (includeTypes.size === 0)
|
|
57
|
+
return true;
|
|
58
|
+
return (member.memberType === 'user' || member.memberType === 'bot') && includeTypes.has(member.memberType);
|
|
59
|
+
}
|
|
60
|
+
function mergeListenerRunPreviewResults(current, next) {
|
|
61
|
+
const merged = new Map();
|
|
62
|
+
for (const result of current ?? [])
|
|
63
|
+
merged.set(result.messageId, result);
|
|
64
|
+
for (const result of next)
|
|
65
|
+
merged.set(result.messageId, { ...merged.get(result.messageId), ...result });
|
|
66
|
+
return [...merged.values()];
|
|
67
|
+
}
|
|
68
|
+
function listenerRunPreviewStateClass(state, ok) {
|
|
69
|
+
if (!ok || state === 'failed')
|
|
70
|
+
return 'error';
|
|
71
|
+
if (state === 'replied')
|
|
72
|
+
return 'ok';
|
|
73
|
+
if (state === 'running')
|
|
74
|
+
return 'running';
|
|
75
|
+
return 'triggered';
|
|
76
|
+
}
|
|
77
|
+
function listenerForEditor(listener, members = []) {
|
|
78
|
+
const next = cloneListener(listener ?? DEFAULT_LISTENER);
|
|
79
|
+
if (listener?.senderPolicy?.mode !== 'all_except_excluded')
|
|
80
|
+
return next;
|
|
81
|
+
const excluded = new Set(listener.senderPolicy.excludeSenderOpenIds ?? []);
|
|
82
|
+
next.senderPolicy = {
|
|
83
|
+
...(next.senderPolicy ?? {}),
|
|
84
|
+
mode: 'include_only',
|
|
85
|
+
includeSenderOpenIds: members
|
|
86
|
+
.filter(member => listenerSenderTypeMatches(member, next) && !excluded.has(member.openId))
|
|
87
|
+
.map(member => member.openId),
|
|
88
|
+
excludeSenderOpenIds: [],
|
|
89
|
+
};
|
|
90
|
+
return next;
|
|
91
|
+
}
|
|
9
92
|
function useAliveRef() {
|
|
10
93
|
const alive = useRef(true);
|
|
11
94
|
useEffect(() => {
|
|
@@ -65,6 +148,19 @@ function RolesPage(props) {
|
|
|
65
148
|
const [injectSaving, setInjectSaving] = useState(false);
|
|
66
149
|
const [roleFlash, setRoleFlash] = useState(null);
|
|
67
150
|
const [injectFlash, setInjectFlash] = useState(null);
|
|
151
|
+
const [groupEditorSection, setGroupEditorSection] = useState('role');
|
|
152
|
+
const [selectedListener, setSelectedListener] = useState(null);
|
|
153
|
+
const [editingListener, setEditingListener] = useState(() => cloneListener(DEFAULT_LISTENER));
|
|
154
|
+
const [listenerMembers, setListenerMembers] = useState([]);
|
|
155
|
+
const [listenerLoading, setListenerLoading] = useState(false);
|
|
156
|
+
const [listenerMembersLoading, setListenerMembersLoading] = useState(false);
|
|
157
|
+
const [listenerSaving, setListenerSaving] = useState(false);
|
|
158
|
+
const [listenerDeleting, setListenerDeleting] = useState(false);
|
|
159
|
+
const [listenerFlash, setListenerFlash] = useState(null);
|
|
160
|
+
const [listenerPreviewLimit, setListenerPreviewLimit] = useState(DEFAULT_MESSAGE_LISTENER_PREVIEW_LIMIT);
|
|
161
|
+
const [listenerPreviewStatus, setListenerPreviewStatus] = useState({ kind: 'idle' });
|
|
162
|
+
const listenerRunPollRef = useRef(null);
|
|
163
|
+
const listenerRunPollToken = useRef(0);
|
|
68
164
|
const [selectedProfileId, setSelectedProfileId] = useState(null);
|
|
69
165
|
const [selectedProfileBotId, setSelectedProfileBotId] = useState(null);
|
|
70
166
|
const [profileEntries, setProfileEntries] = useState([]);
|
|
@@ -97,6 +193,13 @@ function RolesPage(props) {
|
|
|
97
193
|
const filteredProfiles = useMemo(() => filterRoleProfiles(profiles, profileFilter), [profiles, profileFilter]);
|
|
98
194
|
const roleByteLen = byteLength(editingContent);
|
|
99
195
|
const profileByteLen = byteLength(profileEditingContent);
|
|
196
|
+
const listenerPromptByteLen = byteLength(editingListener.prompt);
|
|
197
|
+
const listenerMemberById = useMemo(() => {
|
|
198
|
+
const map = new Map();
|
|
199
|
+
for (const member of listenerMembers)
|
|
200
|
+
map.set(member.openId, member);
|
|
201
|
+
return map;
|
|
202
|
+
}, [listenerMembers]);
|
|
100
203
|
const flash = useCallback((setter, text, isError = false) => {
|
|
101
204
|
const id = Date.now() + Math.random();
|
|
102
205
|
setter({ text, isError, id });
|
|
@@ -134,6 +237,33 @@ function RolesPage(props) {
|
|
|
134
237
|
setProfiles(nextProfiles);
|
|
135
238
|
return nextProfiles;
|
|
136
239
|
}, [alive]);
|
|
240
|
+
const applyLoadedListener = useCallback((listener, members = []) => {
|
|
241
|
+
const next = listenerForEditor(listener ?? DEFAULT_LISTENER, members);
|
|
242
|
+
setSelectedListener(listener);
|
|
243
|
+
setEditingListener(next);
|
|
244
|
+
}, []);
|
|
245
|
+
const loadListenerForSelection = useCallback(async (botId, groupId, serial) => {
|
|
246
|
+
setListenerLoading(true);
|
|
247
|
+
setListenerMembersLoading(true);
|
|
248
|
+
setListenerMembers([]);
|
|
249
|
+
try {
|
|
250
|
+
const [listener, members] = await Promise.all([
|
|
251
|
+
loadMessageListener(botId, groupId).catch(() => cloneListener(DEFAULT_LISTENER)),
|
|
252
|
+
loadGroupMemberDisplays(botId, groupId).catch(() => []),
|
|
253
|
+
]);
|
|
254
|
+
if (!alive.current || serial !== selectSerial.current)
|
|
255
|
+
return;
|
|
256
|
+
applyLoadedListener(listenerHasConfig(listener) ? listener : null, members);
|
|
257
|
+
setListenerMembers(members);
|
|
258
|
+
setListenerFlash(null);
|
|
259
|
+
}
|
|
260
|
+
finally {
|
|
261
|
+
if (alive.current && serial === selectSerial.current) {
|
|
262
|
+
setListenerLoading(false);
|
|
263
|
+
setListenerMembersLoading(false);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}, [alive, applyLoadedListener]);
|
|
137
267
|
const loadInitial = useCallback(async () => {
|
|
138
268
|
setLoadingTree(true);
|
|
139
269
|
setProfileListLoading(true);
|
|
@@ -148,7 +278,7 @@ function RolesPage(props) {
|
|
|
148
278
|
await loadNameMaps();
|
|
149
279
|
if (!alive.current)
|
|
150
280
|
return;
|
|
151
|
-
setExpandedGroups(new Set(snapshot.groups.filter(
|
|
281
|
+
setExpandedGroups(new Set(snapshot.groups.filter(groupHasAnyRoleOrListener).map(group => group.chatId)));
|
|
152
282
|
if (props.tab === 'profiles') {
|
|
153
283
|
const requestedChatId = hashChatId();
|
|
154
284
|
setSelectedApplyGroupId(current => {
|
|
@@ -177,6 +307,10 @@ function RolesPage(props) {
|
|
|
177
307
|
useEffect(() => {
|
|
178
308
|
void loadInitial();
|
|
179
309
|
}, [loadInitial]);
|
|
310
|
+
useEffect(() => () => {
|
|
311
|
+
listenerRunPollToken.current += 1;
|
|
312
|
+
listenerRunPollRef.current = null;
|
|
313
|
+
}, []);
|
|
180
314
|
useEffect(() => {
|
|
181
315
|
if (selectedApplyGroupId || groups.length === 0)
|
|
182
316
|
return;
|
|
@@ -193,14 +327,17 @@ function RolesPage(props) {
|
|
|
193
327
|
const serial = ++selectSerial.current;
|
|
194
328
|
setSelectedGroupId(groupId);
|
|
195
329
|
setSelectedBotId(botId);
|
|
330
|
+
setRoleFlash(null);
|
|
331
|
+
setInjectFlash(null);
|
|
332
|
+
setListenerFlash(null);
|
|
333
|
+
applyLoadedListener(null);
|
|
196
334
|
const role = await loadRole(botId, groupId);
|
|
197
335
|
if (!alive.current || serial !== selectSerial.current)
|
|
198
336
|
return;
|
|
199
337
|
setSelectedRole(role);
|
|
200
338
|
setEditingContent(role.content ?? '');
|
|
201
339
|
setEditingInjectMode(role.injectMode === 'once' ? 'once' : 'every');
|
|
202
|
-
|
|
203
|
-
setInjectFlash(null);
|
|
340
|
+
await loadListenerForSelection(botId, groupId, serial);
|
|
204
341
|
}
|
|
205
342
|
async function handleGroupRefresh() {
|
|
206
343
|
const snapshot = await refreshGroups();
|
|
@@ -208,12 +345,14 @@ function RolesPage(props) {
|
|
|
208
345
|
return;
|
|
209
346
|
void refreshRoleContext(snapshot.groups, profiles);
|
|
210
347
|
if (selectedGroupId && selectedBotId) {
|
|
348
|
+
const serial = ++selectSerial.current;
|
|
211
349
|
const role = await loadRole(selectedBotId, selectedGroupId);
|
|
212
|
-
if (!alive.current)
|
|
350
|
+
if (!alive.current || serial !== selectSerial.current)
|
|
213
351
|
return;
|
|
214
352
|
setSelectedRole(role);
|
|
215
353
|
setEditingContent(role.content ?? '');
|
|
216
354
|
setEditingInjectMode(role.injectMode === 'once' ? 'once' : 'every');
|
|
355
|
+
await loadListenerForSelection(selectedBotId, selectedGroupId, serial);
|
|
217
356
|
}
|
|
218
357
|
}
|
|
219
358
|
async function handleSaveRole() {
|
|
@@ -287,6 +426,273 @@ function RolesPage(props) {
|
|
|
287
426
|
setInjectSaving(false);
|
|
288
427
|
}
|
|
289
428
|
}
|
|
429
|
+
function updateEditingListener(patch) {
|
|
430
|
+
setEditingListener(prev => ({ ...prev, ...patch }));
|
|
431
|
+
}
|
|
432
|
+
function updateListenerSenderPolicy(patch) {
|
|
433
|
+
setEditingListener(prev => ({
|
|
434
|
+
...prev,
|
|
435
|
+
senderPolicy: {
|
|
436
|
+
...(prev.senderPolicy ?? {}),
|
|
437
|
+
...patch,
|
|
438
|
+
},
|
|
439
|
+
}));
|
|
440
|
+
}
|
|
441
|
+
function updateListenerMessagePolicy(patch) {
|
|
442
|
+
setEditingListener(prev => ({
|
|
443
|
+
...prev,
|
|
444
|
+
messagePolicy: {
|
|
445
|
+
...(prev.messagePolicy ?? { scope: 'top_level' }),
|
|
446
|
+
...patch,
|
|
447
|
+
scope: 'top_level',
|
|
448
|
+
},
|
|
449
|
+
}));
|
|
450
|
+
}
|
|
451
|
+
function toggleListenerSenderType(type, checked) {
|
|
452
|
+
setEditingListener(prev => {
|
|
453
|
+
const current = new Set(prev.senderPolicy?.includeSenderTypes ?? []);
|
|
454
|
+
if (checked)
|
|
455
|
+
current.add(type);
|
|
456
|
+
else {
|
|
457
|
+
if (current.size <= 1 && current.has(type))
|
|
458
|
+
return prev;
|
|
459
|
+
current.delete(type);
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
...prev,
|
|
463
|
+
senderPolicy: {
|
|
464
|
+
...(prev.senderPolicy ?? {}),
|
|
465
|
+
includeSenderTypes: [...current],
|
|
466
|
+
},
|
|
467
|
+
};
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
function toggleListenerMsgType(msgType, checked) {
|
|
471
|
+
setEditingListener(prev => {
|
|
472
|
+
const current = new Set(prev.messagePolicy?.includeMsgTypes ?? []);
|
|
473
|
+
if (checked)
|
|
474
|
+
current.add(msgType);
|
|
475
|
+
else {
|
|
476
|
+
if (current.size <= 1 && current.has(msgType))
|
|
477
|
+
return prev;
|
|
478
|
+
current.delete(msgType);
|
|
479
|
+
}
|
|
480
|
+
return {
|
|
481
|
+
...prev,
|
|
482
|
+
messagePolicy: {
|
|
483
|
+
...(prev.messagePolicy ?? { scope: 'top_level' }),
|
|
484
|
+
includeMsgTypes: [...current],
|
|
485
|
+
scope: 'top_level',
|
|
486
|
+
},
|
|
487
|
+
};
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
function setListenerTargetPolicy(openId, listening) {
|
|
491
|
+
setEditingListener(prev => {
|
|
492
|
+
const next = applyListenerFilterState({
|
|
493
|
+
include: prev.senderPolicy?.includeSenderOpenIds ?? [],
|
|
494
|
+
exclude: prev.senderPolicy?.excludeSenderOpenIds ?? [],
|
|
495
|
+
targetIds: [openId],
|
|
496
|
+
listening,
|
|
497
|
+
});
|
|
498
|
+
return {
|
|
499
|
+
...prev,
|
|
500
|
+
senderPolicy: {
|
|
501
|
+
...(prev.senderPolicy ?? {}),
|
|
502
|
+
mode: 'include_only',
|
|
503
|
+
includeSenderOpenIds: next.include,
|
|
504
|
+
excludeSenderOpenIds: next.exclude,
|
|
505
|
+
},
|
|
506
|
+
};
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
function setListenerTargetsPolicy(openIds, listening) {
|
|
510
|
+
setEditingListener(prev => {
|
|
511
|
+
const current = applyListenerFilterState({
|
|
512
|
+
include: prev.senderPolicy?.includeSenderOpenIds ?? [],
|
|
513
|
+
exclude: prev.senderPolicy?.excludeSenderOpenIds ?? [],
|
|
514
|
+
targetIds: openIds,
|
|
515
|
+
listening,
|
|
516
|
+
});
|
|
517
|
+
return {
|
|
518
|
+
...prev,
|
|
519
|
+
senderPolicy: {
|
|
520
|
+
...(prev.senderPolicy ?? {}),
|
|
521
|
+
mode: 'include_only',
|
|
522
|
+
includeSenderOpenIds: current.include,
|
|
523
|
+
excludeSenderOpenIds: current.exclude,
|
|
524
|
+
},
|
|
525
|
+
};
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
function listenerSavePayload() {
|
|
529
|
+
const senderPolicy = editingListener.senderPolicy ?? {};
|
|
530
|
+
const messagePolicy = editingListener.messagePolicy ?? {};
|
|
531
|
+
const includeSenderOpenIds = [...new Set(senderPolicy.includeSenderOpenIds ?? [])].filter(Boolean);
|
|
532
|
+
const includeSenderTypes = [...new Set(senderPolicy.includeSenderTypes ?? [])].filter((type) => type === 'user' || type === 'bot');
|
|
533
|
+
const includeMsgTypes = [...new Set(messagePolicy.includeMsgTypes ?? [])].filter(Boolean);
|
|
534
|
+
return {
|
|
535
|
+
enabled: editingListener.enabled,
|
|
536
|
+
...(editingListener.name?.trim() ? { name: editingListener.name.trim() } : {}),
|
|
537
|
+
...(editingListener.replyCardTitle?.trim() ? { replyCardTitle: editingListener.replyCardTitle.trim() } : {}),
|
|
538
|
+
...(editingListener.workingDir?.trim() ? { workingDir: editingListener.workingDir.trim() } : {}),
|
|
539
|
+
prompt: editingListener.prompt.trim(),
|
|
540
|
+
senderPolicy: {
|
|
541
|
+
...(includeSenderOpenIds.length > 0 ? { includeSenderOpenIds } : {}),
|
|
542
|
+
mode: 'include_only',
|
|
543
|
+
...(includeSenderTypes.length > 0 ? { includeSenderTypes } : {}),
|
|
544
|
+
excludeSelf: senderPolicy.excludeSelf !== false,
|
|
545
|
+
},
|
|
546
|
+
messagePolicy: {
|
|
547
|
+
...(includeMsgTypes.length > 0 ? { includeMsgTypes } : {}),
|
|
548
|
+
scope: 'top_level',
|
|
549
|
+
},
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
function validateListenerForPreview() {
|
|
553
|
+
if (!editingListener.prompt.trim()) {
|
|
554
|
+
flash(setListenerFlash, tr('roles.listenerPromptRequired'), true);
|
|
555
|
+
return null;
|
|
556
|
+
}
|
|
557
|
+
if ((editingListener.senderPolicy?.includeSenderOpenIds?.length ?? 0) === 0) {
|
|
558
|
+
flash(setListenerFlash, tr('roles.listenerSenderRequired'), true);
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
return {
|
|
562
|
+
...listenerSavePayload(),
|
|
563
|
+
enabled: true,
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
async function handleListenerPreview(run) {
|
|
567
|
+
if (!selectedGroupId || !selectedBotId)
|
|
568
|
+
return;
|
|
569
|
+
const payload = validateListenerForPreview();
|
|
570
|
+
if (!payload)
|
|
571
|
+
return;
|
|
572
|
+
const mode = run ? 'run' : 'preview';
|
|
573
|
+
setListenerPreviewStatus({ kind: 'loading', mode });
|
|
574
|
+
try {
|
|
575
|
+
const response = run
|
|
576
|
+
? await runMessageListenerPreview(selectedBotId, selectedGroupId, payload, listenerPreviewLimit)
|
|
577
|
+
: await previewMessageListener(selectedBotId, selectedGroupId, payload, listenerPreviewLimit);
|
|
578
|
+
if (!alive.current)
|
|
579
|
+
return;
|
|
580
|
+
setListenerPreviewStatus(response.ok
|
|
581
|
+
? { kind: 'result', response, mode }
|
|
582
|
+
: { kind: 'error', text: response.error || tr('roles.listenerPreviewFailed') });
|
|
583
|
+
if (response.ok && run && response.runId) {
|
|
584
|
+
startListenerRunPreviewPolling(response.runId);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
catch (err) {
|
|
588
|
+
if (!alive.current)
|
|
589
|
+
return;
|
|
590
|
+
setListenerPreviewStatus({ kind: 'error', text: err instanceof Error ? err.message : tr('roles.listenerPreviewFailed') });
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function startListenerRunPreviewPolling(runId) {
|
|
594
|
+
if (!selectedGroupId || !selectedBotId)
|
|
595
|
+
return;
|
|
596
|
+
const token = ++listenerRunPollToken.current;
|
|
597
|
+
listenerRunPollRef.current = { runId, token };
|
|
598
|
+
const poll = async () => {
|
|
599
|
+
if (!alive.current)
|
|
600
|
+
return;
|
|
601
|
+
const current = listenerRunPollRef.current;
|
|
602
|
+
if (!current || current.runId !== runId || current.token !== token || !selectedGroupId || !selectedBotId)
|
|
603
|
+
return;
|
|
604
|
+
try {
|
|
605
|
+
const status = await loadMessageListenerRunPreviewStatus(selectedBotId, selectedGroupId, runId);
|
|
606
|
+
if (!alive.current)
|
|
607
|
+
return;
|
|
608
|
+
if (status.ok && status.results) {
|
|
609
|
+
const nextResults = status.results;
|
|
610
|
+
setListenerPreviewStatus(previous => {
|
|
611
|
+
if (previous.kind !== 'result' || previous.mode !== 'run' || previous.response.runId !== runId)
|
|
612
|
+
return previous;
|
|
613
|
+
return {
|
|
614
|
+
...previous,
|
|
615
|
+
response: {
|
|
616
|
+
...previous.response,
|
|
617
|
+
results: mergeListenerRunPreviewResults(previous.response.results, nextResults),
|
|
618
|
+
},
|
|
619
|
+
};
|
|
620
|
+
});
|
|
621
|
+
if (nextResults.some(result => result.state === 'triggered' || result.state === 'running')) {
|
|
622
|
+
scheduleTimer(poll, 1500);
|
|
623
|
+
}
|
|
624
|
+
else if (listenerRunPollRef.current?.runId === runId) {
|
|
625
|
+
listenerRunPollRef.current = null;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
catch {
|
|
630
|
+
scheduleTimer(poll, 2500);
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
scheduleTimer(poll, 1500);
|
|
634
|
+
}
|
|
635
|
+
async function handleSaveListener() {
|
|
636
|
+
if (!selectedGroupId || !selectedBotId)
|
|
637
|
+
return;
|
|
638
|
+
if (!editingListener.enabled) {
|
|
639
|
+
await handleDeleteListener(false);
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
if (!editingListener.prompt.trim()) {
|
|
643
|
+
flash(setListenerFlash, tr('roles.listenerPromptRequired'), true);
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
if ((editingListener.senderPolicy?.includeSenderOpenIds?.length ?? 0) === 0) {
|
|
647
|
+
flash(setListenerFlash, tr('roles.listenerSenderRequired'), true);
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
setListenerSaving(true);
|
|
651
|
+
try {
|
|
652
|
+
const ok = await saveMessageListener(selectedBotId, selectedGroupId, listenerSavePayload());
|
|
653
|
+
if (!alive.current)
|
|
654
|
+
return;
|
|
655
|
+
if (ok) {
|
|
656
|
+
const snapshot = await refreshGroups();
|
|
657
|
+
if (!alive.current)
|
|
658
|
+
return;
|
|
659
|
+
const listener = await loadMessageListener(selectedBotId, selectedGroupId);
|
|
660
|
+
if (!alive.current)
|
|
661
|
+
return;
|
|
662
|
+
applyLoadedListener(listenerHasConfig(listener) ? listener : null);
|
|
663
|
+
void refreshRoleContext(snapshot.groups, profiles);
|
|
664
|
+
}
|
|
665
|
+
flash(setListenerFlash, ok ? tr('roles.saved') : tr('roles.saveFailed'), !ok);
|
|
666
|
+
}
|
|
667
|
+
finally {
|
|
668
|
+
if (alive.current)
|
|
669
|
+
setListenerSaving(false);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
async function handleDeleteListener(confirmFirst = true) {
|
|
673
|
+
if (!selectedGroupId || !selectedBotId)
|
|
674
|
+
return;
|
|
675
|
+
if (confirmFirst && !confirm(tr('roles.listenerConfirmDelete')))
|
|
676
|
+
return;
|
|
677
|
+
setListenerDeleting(true);
|
|
678
|
+
try {
|
|
679
|
+
const ok = await deleteMessageListener(selectedBotId, selectedGroupId);
|
|
680
|
+
if (!alive.current)
|
|
681
|
+
return;
|
|
682
|
+
if (ok) {
|
|
683
|
+
const snapshot = await refreshGroups();
|
|
684
|
+
if (!alive.current)
|
|
685
|
+
return;
|
|
686
|
+
applyLoadedListener(null);
|
|
687
|
+
void refreshRoleContext(snapshot.groups, profiles);
|
|
688
|
+
}
|
|
689
|
+
flash(setListenerFlash, ok ? tr('roles.saved') : tr('roles.saveFailed'), !ok);
|
|
690
|
+
}
|
|
691
|
+
finally {
|
|
692
|
+
if (alive.current)
|
|
693
|
+
setListenerDeleting(false);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
290
696
|
async function handleSelectProfile(profileId) {
|
|
291
697
|
const clean = profileId.trim();
|
|
292
698
|
if (!isValidProfileId(clean))
|
|
@@ -439,13 +845,17 @@ function RolesPage(props) {
|
|
|
439
845
|
}
|
|
440
846
|
}
|
|
441
847
|
const roleSaveDisabled = roleSaving || roleByteLen > MAX_ROLE_BYTES || editingContent.trim().length === 0;
|
|
848
|
+
const listenerSaveDisabled = listenerSaving
|
|
849
|
+
|| listenerDeleting
|
|
850
|
+
|| listenerPromptByteLen > MAX_MESSAGE_LISTENER_PROMPT_BYTES
|
|
851
|
+
|| (editingListener.enabled && editingListener.prompt.trim().length === 0);
|
|
442
852
|
const profileSaveDisabled = profileSaving || profileByteLen > MAX_ROLE_BYTES || profileEditingContent.trim().length === 0;
|
|
443
853
|
const isProfiles = props.tab === 'profiles';
|
|
444
854
|
const tabs = (_jsxs("nav", { className: "roles-subnav insight-tabs", role: "tablist", "aria-label": tr('roles.title'), children: [_jsx("a", { href: "#/roles", className: `itab${isProfiles ? '' : ' on'}`, role: "tab", "aria-selected": !isProfiles, children: tr('roles.tabGroups') }), _jsx("a", { href: "#/roles/profile", className: `itab${isProfiles ? ' on' : ''}`, role: "tab", "aria-selected": isProfiles, children: tr('roles.tabProfiles') })] }));
|
|
445
|
-
return (_jsxs("section", { className: "page roles-page", children: [_jsxs("div", { className: "page-heading roles-heading", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: tr('nav.roles') }), _jsx("h1", { children: tr('roles.title') })] }), _jsx("div", { className: "page-heading-actions", children: tabs })] }), _jsxs("div", { id: "roles-by-group-view", className: "roles-layout", hidden: isProfiles, children: [_jsxs("div", { className: "roles-tree-panel", children: [_jsxs("div", { className: "roles-tree-header dashboard-toolbar", children: [_jsx("input", { type: "search", id: "roles-search", placeholder: tr('roles.search'), value: groupsFilter, onChange: ev => setGroupsFilter(ev.target.value) }), _jsx(RefreshIconButton, { id: "roles-refresh", label: tr('roles.refresh'), onClick: () => void handleGroupRefresh() })] }), _jsx("div", { id: "roles-tree", className: "roles-tree", children: loadingTree ? _jsx(LoadingState, { label: tr('common.loading') }) : (_jsx(GroupsTree, { groups: filteredGroups, profiles: profiles, context: roleContext, contextLoaded: roleContextLoaded, expandedGroups: expandedGroups, selectedGroupId: selectedGroupId, selectedBotId: selectedBotId, tr: tr, onToggleGroup: groupId => setExpandedGroups(prev => toggleSet(prev, groupId)), onSelectBot: (groupId, botId) => void handleSelectBot(groupId, botId) })) })] }), _jsx("div", { className: "roles-editor-panel", children: !selectedGroupId || !selectedBotId ? (_jsx("div", { id: "roles-editor-empty", className: "roles-editor-empty", children: tr('roles.selectHint') })) : (_jsxs("div", { id: "roles-editor-form", className: "roles-editor-form", children: [_jsxs("div", { className: "roles-editor-head", children: [_jsxs("div", { children: [_jsxs("div", { className: "roles-editor-breadcrumb", children: [_jsx("span", { id: "roles-editor-group-name", children: selectedGroup?.name ?? selectedGroupId }), _jsx("span", { className: "roles-breadcrumb-sep", children: "\u203A" }), _jsx("span", { id: "roles-editor-bot-name", children: selectedBot?.botName ?? selectedBotId })] }), _jsx("div", { className: "roles-editor-meta", children: _jsxs("span", { id: "roles-editor-chat-id", className: "roles-editor-meta-line", children: [selectedGroupId, " \u00B7 ", selectedBotId] }) })] }),
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
855
|
+
return (_jsxs("section", { className: "page roles-page", children: [_jsxs("div", { className: "page-heading roles-heading", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: tr('nav.roles') }), _jsx("h1", { children: tr('roles.title') })] }), _jsx("div", { className: "page-heading-actions", children: tabs })] }), _jsxs("div", { id: "roles-by-group-view", className: "roles-layout", hidden: isProfiles, children: [_jsxs("div", { className: "roles-tree-panel", children: [_jsxs("div", { className: "roles-tree-header dashboard-toolbar", children: [_jsx("input", { type: "search", id: "roles-search", placeholder: tr('roles.search'), value: groupsFilter, onChange: ev => setGroupsFilter(ev.target.value) }), _jsx(RefreshIconButton, { id: "roles-refresh", label: tr('roles.refresh'), onClick: () => void handleGroupRefresh() })] }), _jsx("div", { id: "roles-tree", className: "roles-tree", children: loadingTree ? _jsx(LoadingState, { label: tr('common.loading') }) : (_jsx(GroupsTree, { groups: filteredGroups, profiles: profiles, context: roleContext, contextLoaded: roleContextLoaded, expandedGroups: expandedGroups, selectedGroupId: selectedGroupId, selectedBotId: selectedBotId, tr: tr, onToggleGroup: groupId => setExpandedGroups(prev => toggleSet(prev, groupId)), onSelectBot: (groupId, botId) => void handleSelectBot(groupId, botId) })) })] }), _jsx("div", { className: "roles-editor-panel", children: !selectedGroupId || !selectedBotId ? (_jsx("div", { id: "roles-editor-empty", className: "roles-editor-empty", children: tr('roles.selectHint') })) : (_jsxs("div", { id: "roles-editor-form", className: "roles-editor-form", children: [_jsxs("div", { className: "roles-editor-head", children: [_jsxs("div", { children: [_jsxs("div", { className: "roles-editor-breadcrumb", children: [_jsx("span", { id: "roles-editor-group-name", children: selectedGroup?.name ?? selectedGroupId }), _jsx("span", { className: "roles-breadcrumb-sep", children: "\u203A" }), _jsx("span", { id: "roles-editor-bot-name", children: selectedBot?.botName ?? selectedBotId })] }), _jsx("div", { className: "roles-editor-meta", children: _jsxs("span", { id: "roles-editor-chat-id", className: "roles-editor-meta-line", children: [selectedGroupId, " \u00B7 ", selectedBotId] }) })] }), _jsx("div", { className: "roles-editor-actions roles-editor-head-actions", children: groupEditorSection === 'role' ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", id: "roles-delete", className: "danger", style: { display: selectedRole?.hasRole ? '' : 'none' }, disabled: roleDeleting, onClick: () => void handleDeleteRole(), children: roleDeleting ? '...' : tr('roles.delete') }), _jsx("button", { type: "button", id: "roles-save", className: "primary", disabled: roleSaveDisabled, onClick: () => void handleSaveRole(), children: roleSaving ? '...' : tr('roles.save') })] })) : (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", id: "roles-listener-delete", className: "danger", style: { display: selectedListener?.enabled ? '' : 'none' }, disabled: listenerDeleting, onClick: () => void handleDeleteListener(), children: listenerDeleting ? '...' : tr('roles.delete') }), _jsx("button", { type: "button", id: "roles-listener-save", className: "primary", disabled: listenerSaveDisabled, onClick: () => void handleSaveListener(), children: listenerSaving ? '...' : tr('roles.save') })] })) })] }), _jsxs("div", { className: "roles-editor-switch segmented", role: "tablist", "aria-label": tr('roles.editorTabs'), children: [_jsx("button", { type: "button", className: groupEditorSection === 'role' ? 'active' : '', "aria-pressed": groupEditorSection === 'role', onClick: () => setGroupEditorSection('role'), children: tr('roles.roleTab') }), _jsx("button", { type: "button", className: groupEditorSection === 'listener' ? 'active' : '', "aria-pressed": groupEditorSection === 'listener', onClick: () => setGroupEditorSection('listener'), children: tr('roles.listenerTab') })] }), groupEditorSection === 'role' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "roles-editor-inject", children: [_jsx("span", { className: "roles-field-label", children: tr('roles.injectModeLabel') }), _jsx(DropdownMenu, { id: "roles-editor-inject-mode", className: "roles-inline-menu", ariaLabel: tr('roles.injectModeLabel'), disabled: injectSaving, label: editingInjectMode === 'once' ? tr('roles.injectModeOnce') : tr('roles.injectModeEvery'), value: editingInjectMode, options: [
|
|
856
|
+
{ value: 'every', label: tr('roles.injectModeEvery') },
|
|
857
|
+
{ value: 'once', label: tr('roles.injectModeOnce') },
|
|
858
|
+
], onChange: mode => void handleInjectModeChange(mode === 'once' ? 'once' : 'every') }), _jsx("span", { className: "roles-editor-inject-hint", children: tr('roles.injectModeHint') }), _jsx(Flash, { flash: injectFlash })] }), _jsx("textarea", { id: "roles-editor-textarea", placeholder: tr('roles.editorPlaceholder'), rows: 14, value: editingContent, onChange: ev => setEditingContent(ev.target.value) }), _jsxs("div", { className: "roles-editor-footer", children: [_jsxs("span", { id: "roles-editor-bytecount", className: byteCountClass(roleByteLen), children: [roleByteLen, " / ", MAX_ROLE_BYTES, " bytes"] }), _jsx(Flash, { flash: roleFlash })] }), _jsx(RolePreview, { content: editingContent, tr: tr, id: "roles-preview" })] })) : (_jsx(MessageListenerEditor, { listener: editingListener, members: listenerMembers, memberById: listenerMemberById, promptByteLen: listenerPromptByteLen, loading: listenerLoading, membersLoading: listenerMembersLoading, flash: listenerFlash, tr: tr, onPatch: updateEditingListener, onSenderPolicyPatch: updateListenerSenderPolicy, onMessagePolicyPatch: updateListenerMessagePolicy, onToggleSenderType: toggleListenerSenderType, onToggleMsgType: toggleListenerMsgType, onSetTargetPolicy: setListenerTargetPolicy, onSetTargetsPolicy: setListenerTargetsPolicy, previewLimit: listenerPreviewLimit, previewStatus: listenerPreviewStatus, onPreviewLimitChange: setListenerPreviewLimit, onPreview: () => void handleListenerPreview(false), onRunPreview: () => void handleListenerPreview(true) }))] })) })] }), _jsxs("div", { id: "roles-profiles-view", className: "roles-layout roles-profiles-layout", hidden: !isProfiles, children: [_jsxs("div", { className: "roles-tree-panel", children: [_jsxs("div", { className: "roles-tree-header roles-profile-create dashboard-toolbar", children: [_jsx("input", { type: "text", id: "roles-profile-id", placeholder: tr('roles.profileIdPlaceholder'), maxLength: 64, ref: profileIdInputRef, onChange: ev => ev.currentTarget.setCustomValidity('') }), _jsx("button", { type: "button", id: "roles-profile-select", onClick: () => void handleOpenProfile(), children: tr('roles.openProfile') })] }), _jsxs("div", { className: "roles-tree-header dashboard-toolbar", children: [_jsx("input", { type: "search", id: "roles-profile-search", placeholder: tr('roles.profileSearch'), value: profileFilter, onChange: ev => setProfileFilter(ev.target.value) }), _jsx(RefreshIconButton, { id: "roles-profile-refresh", label: tr('roles.refresh'), onClick: () => void handleProfileRefresh() })] }), _jsx("div", { id: "roles-profile-list", className: "roles-tree", children: profileListLoading ? _jsx(LoadingState, { label: tr('common.loading') }) : (_jsx(ProfileList, { profiles: filteredProfiles, selectedProfileId: selectedProfileId, tr: tr, onSelect: profileId => void handleSelectProfile(profileId) })) })] }), _jsx("div", { className: "roles-editor-panel", children: !selectedProfileId ? (_jsx("div", { id: "roles-profile-empty", className: "roles-editor-empty", children: tr('roles.profileSelectHint') })) : (_jsxs("div", { id: "roles-profile-detail", className: "roles-editor-form roles-profile-detail", children: [_jsx("div", { className: "roles-profile-title", children: _jsxs("div", { children: [_jsxs("div", { className: "roles-editor-breadcrumb", children: [_jsx("span", { children: selectedProfileId }), selectedProfileBot ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "roles-breadcrumb-sep", children: "\u203A" }), _jsx("span", { children: selectedProfileBot.botName ?? selectedProfileBot.larkAppId })] })) : null] }), _jsx("div", { className: "roles-editor-meta-line", children: tr('roles.profileRuntimeHint') })] }) }), _jsxs("div", { className: "roles-profile-grid", children: [_jsxs("div", { className: "roles-profile-bots", children: [_jsx("div", { className: "roles-profile-section-title", children: tr('roles.profileBots') }), _jsx("div", { className: "roles-profile-bot-list", children: allBots.map(bot => {
|
|
449
859
|
const hasEntry = !!entryForBot(profileEntries, bot.larkAppId);
|
|
450
860
|
const selected = selectedProfileBotId === bot.larkAppId;
|
|
451
861
|
return (_jsxs("div", { className: `roles-bot-row roles-profile-bot-row ${selected ? 'selected' : ''}`, "data-profile-bot-id": bot.larkAppId, onClick: () => void handleSelectProfileBot(bot.larkAppId), children: [_jsx(BotAvatar, { bot: bot }), _jsxs("div", { className: "roles-bot-info", children: [_jsx("div", { className: "roles-bot-name", children: bot.botName ?? bot.larkAppId }), _jsx("div", { className: "roles-bot-id", children: bot.larkAppId })] }), _jsx("span", { className: `roles-badge ${hasEntry ? 'has-role' : 'no-role'}`, children: hasEntry ? tr('roles.configured') : tr('roles.unconfigured') })] }, bot.larkAppId));
|
|
@@ -468,6 +878,9 @@ function toggleSet(prev, value) {
|
|
|
468
878
|
function byteCountClass(len) {
|
|
469
879
|
return `roles-bytecount ${len > ROLE_WARN_BYTES ? 'warn' : ''} ${len > MAX_ROLE_BYTES ? 'over' : ''}`;
|
|
470
880
|
}
|
|
881
|
+
function listenerByteCountClass(len) {
|
|
882
|
+
return `roles-bytecount ${len > MESSAGE_LISTENER_WARN_BYTES ? 'warn' : ''} ${len > MAX_MESSAGE_LISTENER_PROMPT_BYTES ? 'over' : ''}`;
|
|
883
|
+
}
|
|
471
884
|
function Flash(props) {
|
|
472
885
|
if (!props.flash)
|
|
473
886
|
return null;
|
|
@@ -487,7 +900,7 @@ function GroupsTree(props) {
|
|
|
487
900
|
return (_jsxs("div", { className: `roles-bot-row ${selected ? 'selected' : ''}`, "data-group-id": group.chatId, "data-bot-id": bot.larkAppId, onClick: ev => {
|
|
488
901
|
ev.stopPropagation();
|
|
489
902
|
props.onSelectBot(group.chatId, bot.larkAppId);
|
|
490
|
-
}, children: [_jsx("span", { className: "roles-bot-indent" }), _jsx(BotAvatar, { bot: bot }), _jsxs("div", { className: "roles-bot-info", children: [_jsx("div", { className: "roles-bot-name", children: bot.botName }), _jsx("div", { className: "roles-bot-id", children: bot.larkAppId })] }), _jsx("span", { className: `roles-badge ${bot.hasRole ? 'has-role' : 'no-role'}`, children: bot.hasRole ? tr('roles.configured') : tr('roles.unconfigured') })] }, bot.larkAppId));
|
|
903
|
+
}, children: [_jsx("span", { className: "roles-bot-indent" }), _jsx(BotAvatar, { bot: bot }), _jsxs("div", { className: "roles-bot-info", children: [_jsx("div", { className: "roles-bot-name", children: bot.botName }), _jsx("div", { className: "roles-bot-id", children: bot.larkAppId })] }), _jsxs("div", { className: "roles-bot-badges", children: [_jsx("span", { className: `roles-badge ${bot.hasRole ? 'has-role' : 'no-role'}`, children: bot.hasRole ? tr('roles.configured') : tr('roles.unconfigured') }), bot.hasMessageListener ? (_jsx("span", { className: "roles-badge has-listener", children: tr('roles.listenerBadge') })) : null] })] }, bot.larkAppId));
|
|
491
904
|
}) : null })] }, group.chatId));
|
|
492
905
|
}) }));
|
|
493
906
|
}
|
|
@@ -514,9 +927,121 @@ function GroupProfileStatus(props) {
|
|
|
514
927
|
chat: best.chatMatched,
|
|
515
928
|
}) }));
|
|
516
929
|
}
|
|
930
|
+
function MessageListenerEditor(props) {
|
|
931
|
+
const { listener, tr } = props;
|
|
932
|
+
const [targetTab, setTargetTab] = useState('members');
|
|
933
|
+
const [targetQuery, setTargetQuery] = useState('');
|
|
934
|
+
const [selectedTargetIds, setSelectedTargetIds] = useState(() => new Set());
|
|
935
|
+
const senderTypes = new Set(listener.senderPolicy?.includeSenderTypes ?? []);
|
|
936
|
+
const msgTypes = new Set(listener.messagePolicy?.includeMsgTypes ?? []);
|
|
937
|
+
const includeIds = new Set(listener.senderPolicy?.includeSenderOpenIds ?? []);
|
|
938
|
+
const configuredUnknownMembers = [
|
|
939
|
+
...[...includeIds].filter(openId => !props.memberById.has(openId)),
|
|
940
|
+
];
|
|
941
|
+
const members = [
|
|
942
|
+
...props.members.filter(member => member.memberType !== 'bot'),
|
|
943
|
+
...configuredUnknownMembers.map(openId => ({ openId, name: openId, memberType: 'unknown' })),
|
|
944
|
+
];
|
|
945
|
+
const bots = props.members.filter(member => member.memberType === 'bot');
|
|
946
|
+
const activeTargets = targetTab === 'bots' ? bots : members;
|
|
947
|
+
const filteredTargets = filterListenerTargets(activeTargets, targetQuery);
|
|
948
|
+
const filteredTargetIds = filteredTargets.map(target => target.openId);
|
|
949
|
+
const selectedVisibleIds = filteredTargetIds.filter(id => selectedTargetIds.has(id));
|
|
950
|
+
const allVisibleSelected = filteredTargetIds.length > 0 && selectedVisibleIds.length === filteredTargetIds.length;
|
|
951
|
+
const selectedIds = [...selectedTargetIds].filter(id => activeTargets.some(target => target.openId === id));
|
|
952
|
+
const bulkTargetIds = selectedIds.length > 0 ? selectedIds : filteredTargetIds;
|
|
953
|
+
const bulkState = listenerTargetStateFor({
|
|
954
|
+
include: [...includeIds],
|
|
955
|
+
exclude: [],
|
|
956
|
+
targetIds: bulkTargetIds,
|
|
957
|
+
});
|
|
958
|
+
useEffect(() => {
|
|
959
|
+
setTargetQuery('');
|
|
960
|
+
setSelectedTargetIds(new Set());
|
|
961
|
+
}, [targetTab]);
|
|
962
|
+
useEffect(() => {
|
|
963
|
+
const activeIds = new Set(activeTargets.map(target => target.openId));
|
|
964
|
+
setSelectedTargetIds(prev => {
|
|
965
|
+
const next = new Set([...prev].filter(id => activeIds.has(id)));
|
|
966
|
+
return next.size === prev.size ? prev : next;
|
|
967
|
+
});
|
|
968
|
+
}, [activeTargets]);
|
|
969
|
+
const toggleTargetSelection = (openId, checked) => {
|
|
970
|
+
setSelectedTargetIds(prev => {
|
|
971
|
+
const next = new Set(prev);
|
|
972
|
+
if (checked)
|
|
973
|
+
next.add(openId);
|
|
974
|
+
else
|
|
975
|
+
next.delete(openId);
|
|
976
|
+
return next;
|
|
977
|
+
});
|
|
978
|
+
};
|
|
979
|
+
const toggleAllVisible = () => {
|
|
980
|
+
setSelectedTargetIds(prev => {
|
|
981
|
+
const next = new Set(prev);
|
|
982
|
+
if (allVisibleSelected) {
|
|
983
|
+
for (const id of filteredTargetIds)
|
|
984
|
+
next.delete(id);
|
|
985
|
+
}
|
|
986
|
+
else {
|
|
987
|
+
for (const id of filteredTargetIds)
|
|
988
|
+
next.add(id);
|
|
989
|
+
}
|
|
990
|
+
return next;
|
|
991
|
+
});
|
|
992
|
+
};
|
|
993
|
+
const applyBulkState = (listening) => {
|
|
994
|
+
if (bulkTargetIds.length === 0)
|
|
995
|
+
return;
|
|
996
|
+
props.onSetTargetsPolicy(bulkTargetIds, listening);
|
|
997
|
+
};
|
|
998
|
+
return (_jsxs("div", { className: "roles-listener-editor", children: [props.loading ? _jsx(LoadingState, { label: tr('common.loading') }) : null, _jsxs("label", { className: "filter-toggle roles-listener-enabled", children: [_jsx("input", { type: "checkbox", checked: listener.enabled, onChange: ev => props.onPatch({ enabled: ev.currentTarget.checked }) }), _jsx("span", { className: "filter-toggle-switch", "aria-hidden": "true" }), _jsx("span", { className: "filter-toggle-label", children: tr('roles.listenerEnabled') })] }), _jsx("p", { className: "roles-listener-scope-help", children: tr('roles.listenerScopeHelp') }), _jsxs("div", { className: "roles-listener-grid", children: [_jsxs("label", { className: "roles-listener-field", children: [_jsx("span", { className: "roles-field-label", children: tr('roles.listenerName') }), _jsx("input", { type: "text", value: listener.name ?? '', placeholder: tr('roles.listenerNamePlaceholder'), onChange: ev => props.onPatch({ name: ev.currentTarget.value }) })] }), _jsxs("label", { className: "roles-listener-field", children: [_jsx("span", { className: "roles-field-label", children: tr('roles.listenerReplyCardTitle') }), _jsx("input", { type: "text", value: listener.replyCardTitle ?? '', placeholder: tr('roles.listenerReplyCardTitlePlaceholder'), onChange: ev => props.onPatch({ replyCardTitle: ev.currentTarget.value }) })] }), _jsxs("label", { className: "roles-listener-field", children: [_jsx("span", { className: "roles-field-label", children: tr('roles.listenerWorkingDir') }), _jsx("input", { type: "text", value: listener.workingDir ?? '', placeholder: tr('roles.listenerWorkingDirPlaceholder'), onChange: ev => props.onPatch({ workingDir: ev.currentTarget.value }) })] })] }), _jsxs("div", { className: "roles-listener-policy-row", children: [_jsxs("div", { className: "roles-listener-policy", children: [_jsx("div", { className: "roles-field-label", children: tr('roles.listenerSenderTypes') }), _jsxs("label", { className: "roles-listener-chip", children: [_jsx("input", { type: "checkbox", checked: senderTypes.has('user'), onChange: ev => props.onToggleSenderType('user', ev.currentTarget.checked) }), _jsx("span", { children: tr('roles.listenerSenderUser') })] }), _jsxs("label", { className: "roles-listener-chip", children: [_jsx("input", { type: "checkbox", checked: senderTypes.has('bot'), onChange: ev => props.onToggleSenderType('bot', ev.currentTarget.checked) }), _jsx("span", { children: tr('roles.listenerSenderBot') })] })] }), _jsxs("div", { className: "roles-listener-policy", children: [_jsx("div", { className: "roles-field-label", children: tr('roles.listenerMessageTypes') }), LISTENER_MESSAGE_TYPES.map(msgType => (_jsxs("label", { className: "roles-listener-chip", children: [_jsx("input", { type: "checkbox", checked: msgTypes.has(msgType), onChange: ev => props.onToggleMsgType(msgType, ev.currentTarget.checked) }), _jsx("span", { children: msgType })] }, msgType)))] }), _jsxs("label", { className: "roles-listener-checkbox", children: [_jsx("input", { type: "checkbox", checked: listener.senderPolicy?.excludeSelf !== false, onChange: ev => props.onSenderPolicyPatch({ excludeSelf: ev.currentTarget.checked }) }), _jsx("span", { children: tr('roles.listenerExcludeSelf') })] })] }), _jsxs("label", { className: "roles-listener-field", children: [_jsx("span", { className: "roles-field-label", children: tr('roles.listenerPrompt') }), _jsx("textarea", { id: "roles-listener-prompt", placeholder: tr('roles.listenerPromptPlaceholder'), rows: 9, value: listener.prompt, onChange: ev => props.onPatch({ prompt: ev.currentTarget.value }) })] }), _jsxs("div", { className: "roles-editor-footer", children: [_jsxs("span", { id: "roles-listener-bytecount", className: listenerByteCountClass(props.promptByteLen), children: [props.promptByteLen, " / ", MAX_MESSAGE_LISTENER_PROMPT_BYTES, " bytes"] }), _jsx(Flash, { flash: props.flash })] }), _jsxs("div", { className: "roles-listener-preview-panel", children: [_jsxs("div", { className: "roles-listener-preview-head", children: [_jsxs("div", { children: [_jsx("div", { className: "roles-profile-section-title", children: tr('roles.listenerPreviewTitle') }), _jsx("small", { children: tr('roles.listenerPreviewHint') })] }), _jsxs("div", { className: "roles-listener-preview-actions", children: [_jsxs("label", { children: [_jsx("span", { children: tr('roles.listenerPreviewCount') }), _jsx("select", { value: props.previewLimit, onChange: ev => props.onPreviewLimitChange(Number(ev.currentTarget.value)), children: Array.from({ length: MAX_MESSAGE_LISTENER_PREVIEW_LIMIT }, (_, index) => index + 1).map(count => (_jsx("option", { value: count, children: count }, count))) })] }), _jsx("button", { type: "button", onClick: props.onPreview, disabled: props.previewStatus.kind === 'loading', children: props.previewStatus.kind === 'loading' && props.previewStatus.mode === 'preview' ? '...' : tr('roles.listenerPreviewButton') }), _jsx("button", { type: "button", className: "primary", onClick: props.onRunPreview, disabled: props.previewStatus.kind === 'loading', children: props.previewStatus.kind === 'loading' && props.previewStatus.mode === 'run' ? '...' : tr('roles.listenerRunPreviewButton') })] })] }), _jsx(ListenerPreviewResult, { status: props.previewStatus, tr: tr })] }), _jsxs("div", { className: "roles-listener-members", children: [_jsxs("div", { className: "roles-listener-members-head", children: [_jsx("div", { className: "roles-profile-section-title", children: tr('roles.listenerFilters') }), _jsx("small", { children: props.membersLoading ? tr('common.loading') : tr('roles.listenerMembersHint') })] }), _jsxs("div", { className: "roles-listener-target-tabs segmented", role: "tablist", "aria-label": tr('roles.listenerFilters'), children: [_jsx("button", { type: "button", className: targetTab === 'members' ? 'active' : '', "aria-pressed": targetTab === 'members', onClick: () => setTargetTab('members'), children: tr('roles.listenerMembers') }), _jsx("button", { type: "button", className: targetTab === 'bots' ? 'active' : '', "aria-pressed": targetTab === 'bots', onClick: () => setTargetTab('bots'), children: tr('roles.listenerBots') })] }), _jsxs("div", { className: "roles-listener-filter-toolbar", children: [_jsx("input", { type: "search", value: targetQuery, placeholder: tr('roles.listenerSearchPlaceholder'), onChange: ev => setTargetQuery(ev.currentTarget.value) }), targetQuery ? (_jsx("button", { type: "button", className: "roles-listener-clear-search", onClick: () => setTargetQuery(''), "aria-label": tr('roles.listenerClearSearch'), children: "\u00D7" })) : null, _jsx("button", { type: "button", className: "roles-listener-select-all", disabled: filteredTargetIds.length === 0, onClick: toggleAllVisible, children: tr(allVisibleSelected ? 'roles.listenerClearVisible' : 'roles.listenerSelectVisible', { count: filteredTargetIds.length }) })] }), _jsxs("div", { className: "roles-listener-bulkbar", children: [_jsxs("span", { children: [selectedIds.length > 0
|
|
999
|
+
? tr('roles.listenerSelectedCount', { count: selectedIds.length })
|
|
1000
|
+
: tr('roles.listenerFilteredCount', { count: filteredTargetIds.length }), bulkState === 'mixed' ? ` · ${tr('roles.listenerMixedMode')}` : ''] }), _jsxs("div", { className: "roles-listener-member-actions", role: "group", "aria-label": tr('roles.listenerBulkActions'), children: [_jsx("button", { type: "button", className: bulkState === 'listen' ? 'active' : '', "aria-pressed": bulkState === 'listen', disabled: bulkTargetIds.length === 0, onClick: () => applyBulkState(true), children: tr('roles.listenerTargetListen') }), _jsx("button", { type: "button", className: bulkState === 'ignore' ? 'active' : '', "aria-pressed": bulkState === 'ignore', disabled: bulkTargetIds.length === 0, onClick: () => applyBulkState(false), children: tr('roles.listenerTargetIgnore') })] })] }), _jsx("div", { className: "roles-listener-member-list", children: filteredTargets.length === 0 ? (_jsx("div", { className: "roles-empty", children: tr(targetTab === 'bots' ? 'roles.listenerBotsEmpty' : 'roles.listenerMembersEmpty') })) : filteredTargets.map(member => {
|
|
1001
|
+
const targetState = listenerTargetStateFor({
|
|
1002
|
+
include: [...includeIds],
|
|
1003
|
+
exclude: [],
|
|
1004
|
+
targetIds: [member.openId],
|
|
1005
|
+
});
|
|
1006
|
+
return (_jsxs("div", { className: "roles-listener-member", children: [_jsx("label", { className: "roles-listener-member-select", "aria-label": memberDisplayName(member, member.openId), children: _jsx("input", { type: "checkbox", checked: selectedTargetIds.has(member.openId), onChange: ev => toggleTargetSelection(member.openId, ev.currentTarget.checked) }) }), _jsxs("div", { className: "roles-listener-member-main", children: [_jsx("strong", { children: memberDisplayName(member, member.openId) }), _jsx("span", { children: member.openId })] }), _jsxs("div", { className: "roles-listener-member-actions", role: "group", "aria-label": memberDisplayName(member, member.openId), children: [_jsx("button", { type: "button", className: targetState === 'listen' ? 'active' : '', "aria-pressed": targetState === 'listen', onClick: () => props.onSetTargetPolicy(member.openId, true), children: tr('roles.listenerTargetListen') }), _jsx("button", { type: "button", className: targetState === 'ignore' ? 'active' : '', "aria-pressed": targetState === 'ignore', onClick: () => props.onSetTargetPolicy(member.openId, false), children: tr('roles.listenerTargetIgnore') })] })] }, member.openId));
|
|
1007
|
+
}) })] })] }));
|
|
1008
|
+
}
|
|
517
1009
|
function RolePreview(props) {
|
|
518
1010
|
return (_jsx("div", { id: props.id, className: "roles-preview", children: props.content.trim() ? (_jsxs(_Fragment, { children: [_jsx("strong", { children: props.tr('roles.preview') }), _jsx("pre", { children: props.content })] })) : (_jsx("small", { children: props.tr('roles.previewEmpty') })) }));
|
|
519
1011
|
}
|
|
1012
|
+
function ListenerPreviewResult(props) {
|
|
1013
|
+
const { status, tr } = props;
|
|
1014
|
+
if (status.kind === 'idle')
|
|
1015
|
+
return _jsx("div", { className: "roles-listener-preview-empty", children: tr('roles.listenerPreviewEmpty') });
|
|
1016
|
+
if (status.kind === 'loading')
|
|
1017
|
+
return _jsx(LoadingState, { label: tr('common.loading') });
|
|
1018
|
+
if (status.kind === 'error')
|
|
1019
|
+
return _jsx("div", { className: "roles-listener-preview-error", children: status.text });
|
|
1020
|
+
const matches = status.response.matches ?? [];
|
|
1021
|
+
const results = status.response.results ?? [];
|
|
1022
|
+
const stateCounts = results.reduce((acc, result) => {
|
|
1023
|
+
const state = !result.ok ? 'failed' : result.state ?? 'triggered';
|
|
1024
|
+
acc[state] = (acc[state] ?? 0) + 1;
|
|
1025
|
+
return acc;
|
|
1026
|
+
}, {});
|
|
1027
|
+
return (_jsxs("div", { className: "roles-listener-preview-results", children: [_jsx("div", { className: "roles-listener-preview-summary", children: status.mode === 'run'
|
|
1028
|
+
? tr('roles.listenerRunPreviewSummary', {
|
|
1029
|
+
count: matches.length,
|
|
1030
|
+
triggered: stateCounts.triggered ?? 0,
|
|
1031
|
+
running: stateCounts.running ?? 0,
|
|
1032
|
+
replied: stateCounts.replied ?? 0,
|
|
1033
|
+
failed: stateCounts.failed ?? 0,
|
|
1034
|
+
})
|
|
1035
|
+
: tr('roles.listenerPreviewSummary', { count: matches.length }) }), matches.length === 0 ? (_jsx("div", { className: "roles-listener-preview-empty", children: tr('roles.listenerPreviewNoMatches') })) : (_jsx("div", { className: "roles-listener-preview-list", children: matches.map(item => (_jsx(ListenerPreviewItem, { item: item, result: status.response.results?.find(result => result.messageId === item.messageId), tr: tr }, item.messageId))) }))] }));
|
|
1036
|
+
}
|
|
1037
|
+
function ListenerPreviewItem(props) {
|
|
1038
|
+
const text = props.item.messageText.length > 300
|
|
1039
|
+
? `${props.item.messageText.slice(0, 300)}...`
|
|
1040
|
+
: props.item.messageText;
|
|
1041
|
+
const senderLabel = props.item.senderName || props.item.senderOpenId || props.item.senderType;
|
|
1042
|
+
const sentAt = formatListenerPreviewTime(props.item.createTime);
|
|
1043
|
+
return (_jsxs("div", { className: "roles-listener-preview-item", children: [_jsxs("div", { className: "roles-listener-preview-meta", children: [_jsx("span", { children: props.item.msgType }), _jsx("span", { children: props.item.senderType }), props.item.senderOpenId ? _jsx("span", { children: props.item.senderOpenId }) : null, _jsx("span", { children: props.item.messageId }), props.result ? (_jsx("span", { className: listenerRunPreviewStateClass(props.result.state, props.result.ok), children: props.tr(`roles.listenerRunPreviewState.${!props.result.ok ? 'failed' : props.result.state ?? 'triggered'}`) })) : null] }), props.result?.sessionId || props.result?.replyMessageId || props.result?.error ? (_jsxs("div", { className: "roles-listener-preview-run-detail", children: [props.result.sessionId ? _jsx("span", { children: props.result.sessionId }) : null, props.result.replyMessageId ? _jsx("span", { children: props.result.replyMessageId }) : null, props.result.error ? _jsx("strong", { children: props.result.error }) : null] })) : null, _jsxs("div", { className: "roles-listener-preview-sender", children: [_jsx("span", { children: props.tr('roles.listenerPreviewSender') }), _jsx("strong", { children: senderLabel })] }), sentAt ? (_jsxs("div", { className: "roles-listener-preview-time", children: [_jsx("span", { children: props.tr('roles.listenerPreviewTime') }), _jsx("strong", { children: sentAt })] })) : null, props.item.messageTitle ? (_jsxs("div", { className: "roles-listener-preview-title", children: [_jsx("span", { children: props.tr('roles.listenerPreviewMessageTitle') }), _jsx("strong", { children: props.item.messageTitle })] })) : null, _jsx("div", { className: "roles-listener-preview-content-label", children: props.tr('roles.listenerPreviewContent') }), _jsx("pre", { children: text })] }));
|
|
1044
|
+
}
|
|
520
1045
|
function ProfileList(props) {
|
|
521
1046
|
const { tr } = props;
|
|
522
1047
|
if (props.profiles.length === 0)
|