botmux 2.46.1 → 2.47.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/README.en.md +5 -10
- package/README.md +5 -10
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +0 -11
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +9 -36
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/adapters/cli/coco.d.ts.map +1 -1
- package/dist/adapters/cli/coco.js +1 -26
- package/dist/adapters/cli/coco.js.map +1 -1
- package/dist/adapters/cli/codex.d.ts.map +1 -1
- package/dist/adapters/cli/codex.js +1 -6
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/cursor.d.ts.map +1 -1
- package/dist/adapters/cli/cursor.js +12 -58
- package/dist/adapters/cli/cursor.js.map +1 -1
- package/dist/adapters/cli/gemini.d.ts.map +1 -1
- package/dist/adapters/cli/gemini.js +1 -5
- package/dist/adapters/cli/gemini.js.map +1 -1
- package/dist/adapters/cli/opencode.d.ts.map +1 -1
- package/dist/adapters/cli/opencode.js +1 -19
- package/dist/adapters/cli/opencode.js.map +1 -1
- package/dist/adapters/cli/registry.d.ts +1 -5
- package/dist/adapters/cli/registry.d.ts.map +1 -1
- package/dist/adapters/cli/registry.js +2 -22
- package/dist/adapters/cli/registry.js.map +1 -1
- package/dist/adapters/cli/shared-hints.d.ts +1 -1
- package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
- package/dist/adapters/cli/shared-hints.js +1 -2
- package/dist/adapters/cli/shared-hints.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +2 -35
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/bot-registry.d.ts +0 -59
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +0 -67
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/bots-list-output.d.ts +0 -8
- package/dist/cli/bots-list-output.d.ts.map +1 -1
- package/dist/cli/bots-list-output.js +0 -9
- package/dist/cli/bots-list-output.js.map +1 -1
- package/dist/cli.d.ts +1 -15
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +106 -603
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +2 -11
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +4 -17
- package/dist/config.js.map +1 -1
- package/dist/core/command-handler.d.ts +0 -20
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +313 -762
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts +0 -2
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +2 -222
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/role-resolver.d.ts +1 -17
- package/dist/core/role-resolver.d.ts.map +1 -1
- package/dist/core/role-resolver.js +10 -64
- package/dist/core/role-resolver.js.map +1 -1
- package/dist/core/session-discovery.d.ts.map +1 -1
- package/dist/core/session-discovery.js +5 -19
- package/dist/core/session-discovery.js.map +1 -1
- package/dist/core/session-manager.d.ts +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +20 -37
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/types.d.ts +0 -5
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts +0 -141
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +24 -543
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +58 -213
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/auth.d.ts +1 -6
- package/dist/dashboard/auth.d.ts.map +1 -1
- package/dist/dashboard/auth.js +1 -9
- package/dist/dashboard/auth.js.map +1 -1
- package/dist/dashboard/web/app.js +0 -8
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js +21 -205
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +5 -43
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +0 -4
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/workflows.js +3 -3
- package/dist/dashboard/web/workflows.js.map +1 -1
- package/dist/dashboard/workflow-api.d.ts +1 -8
- package/dist/dashboard/workflow-api.d.ts.map +1 -1
- package/dist/dashboard/workflow-api.js +4 -19
- package/dist/dashboard/workflow-api.js.map +1 -1
- package/dist/dashboard-web/app.js +375 -539
- package/dist/dashboard-web/index.html +1 -3
- package/dist/dashboard-web/style.css +0 -22
- package/dist/dashboard.js +2 -199
- package/dist/dashboard.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +11 -104
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +11 -104
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts +3 -108
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +50 -480
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +18 -241
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +0 -83
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +70 -286
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +4 -29
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/grant-command.d.ts +1 -2
- package/dist/im/lark/grant-command.d.ts.map +1 -1
- package/dist/im/lark/grant-command.js +2 -3
- package/dist/im/lark/grant-command.js.map +1 -1
- package/dist/im/lark/identity-cache.d.ts.map +1 -1
- package/dist/im/lark/identity-cache.js +3 -3
- package/dist/im/lark/identity-cache.js.map +1 -1
- package/dist/im/lark/md-card.d.ts +2 -20
- package/dist/im/lark/md-card.d.ts.map +1 -1
- package/dist/im/lark/md-card.js +17 -49
- package/dist/im/lark/md-card.js.map +1 -1
- package/dist/im/lark/message-parser.d.ts.map +1 -1
- package/dist/im/lark/message-parser.js +31 -87
- package/dist/im/lark/message-parser.js.map +1 -1
- package/dist/im/lark/workflow-card-handler.d.ts +2 -2
- package/dist/im/lark/workflow-card-handler.d.ts.map +1 -1
- package/dist/im/lark/workflow-card-handler.js +1 -12
- package/dist/im/lark/workflow-card-handler.js.map +1 -1
- package/dist/im/lark/workflow-progress-card.d.ts.map +1 -1
- package/dist/im/lark/workflow-progress-card.js +0 -53
- package/dist/im/lark/workflow-progress-card.js.map +1 -1
- package/dist/services/codex-bridge-queue.d.ts +0 -1
- package/dist/services/codex-bridge-queue.d.ts.map +1 -1
- package/dist/services/codex-bridge-queue.js +0 -23
- package/dist/services/codex-bridge-queue.js.map +1 -1
- package/dist/services/codex-transcript.d.ts +0 -1
- package/dist/services/codex-transcript.d.ts.map +1 -1
- package/dist/services/codex-transcript.js.map +1 -1
- package/dist/services/feishu-task-client.d.ts +28 -0
- package/dist/services/feishu-task-client.d.ts.map +1 -0
- package/dist/services/feishu-task-client.js +123 -0
- package/dist/services/feishu-task-client.js.map +1 -0
- package/dist/services/grant-store.d.ts +2 -12
- package/dist/services/grant-store.d.ts.map +1 -1
- package/dist/services/grant-store.js +4 -51
- package/dist/services/grant-store.js.map +1 -1
- package/dist/services/group-creator.d.ts +0 -10
- package/dist/services/group-creator.d.ts.map +1 -1
- package/dist/services/group-creator.js +1 -26
- package/dist/services/group-creator.js.map +1 -1
- package/dist/services/groups-store.d.ts +0 -30
- package/dist/services/groups-store.d.ts.map +1 -1
- package/dist/services/groups-store.js +12 -85
- package/dist/services/groups-store.js.map +1 -1
- package/dist/services/project-scanner.d.ts +0 -10
- package/dist/services/project-scanner.d.ts.map +1 -1
- package/dist/services/project-scanner.js +0 -11
- package/dist/services/project-scanner.js.map +1 -1
- package/dist/services/session-store.js +1 -1
- package/dist/services/session-store.js.map +1 -1
- package/dist/services/task-store.d.ts +37 -0
- package/dist/services/task-store.d.ts.map +1 -0
- package/dist/services/task-store.js +115 -0
- package/dist/services/task-store.js.map +1 -0
- package/dist/setup/bot-config-editor.d.ts +1 -8
- package/dist/setup/bot-config-editor.d.ts.map +1 -1
- package/dist/setup/bot-config-editor.js +2 -20
- package/dist/setup/bot-config-editor.js.map +1 -1
- package/dist/setup/ensure-tmux.d.ts +22 -0
- package/dist/setup/ensure-tmux.d.ts.map +1 -1
- package/dist/setup/ensure-tmux.js +1 -25
- package/dist/setup/ensure-tmux.js.map +1 -1
- package/dist/setup/verify-permissions.d.ts.map +1 -1
- package/dist/setup/verify-permissions.js +1 -15
- package/dist/setup/verify-permissions.js.map +1 -1
- package/dist/skills/definitions.d.ts +0 -2
- package/dist/skills/definitions.d.ts.map +1 -1
- package/dist/skills/definitions.js +12 -178
- package/dist/skills/definitions.js.map +1 -1
- package/dist/skills/installer.d.ts +0 -34
- package/dist/skills/installer.d.ts.map +1 -1
- package/dist/skills/installer.js +2 -119
- package/dist/skills/installer.js.map +1 -1
- package/dist/types.d.ts +0 -25
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/bot-routing.d.ts +0 -50
- package/dist/utils/bot-routing.d.ts.map +1 -1
- package/dist/utils/bot-routing.js +0 -83
- package/dist/utils/bot-routing.js.map +1 -1
- package/dist/utils/user-token.d.ts.map +1 -1
- package/dist/utils/user-token.js +2 -0
- package/dist/utils/user-token.js.map +1 -1
- package/dist/worker.js +27 -198
- package/dist/worker.js.map +1 -1
- package/dist/workflows/attempt-resume.d.ts.map +1 -1
- package/dist/workflows/attempt-resume.js +2 -2
- package/dist/workflows/attempt-resume.js.map +1 -1
- package/dist/workflows/definition.d.ts +9 -412
- package/dist/workflows/definition.d.ts.map +1 -1
- package/dist/workflows/definition.js +3 -238
- package/dist/workflows/definition.js.map +1 -1
- package/dist/workflows/events/payloads.d.ts +11 -114
- package/dist/workflows/events/payloads.d.ts.map +1 -1
- package/dist/workflows/events/payloads.js +0 -46
- package/dist/workflows/events/payloads.js.map +1 -1
- package/dist/workflows/events/replay.d.ts +0 -21
- package/dist/workflows/events/replay.d.ts.map +1 -1
- package/dist/workflows/events/replay.js +0 -103
- package/dist/workflows/events/replay.js.map +1 -1
- package/dist/workflows/events/schema.d.ts +1017 -1712
- package/dist/workflows/events/schema.d.ts.map +1 -1
- package/dist/workflows/events/schema.js +1 -37
- package/dist/workflows/events/schema.js.map +1 -1
- package/dist/workflows/events/types.d.ts +1 -5
- package/dist/workflows/events/types.d.ts.map +1 -1
- package/dist/workflows/loader.d.ts +0 -14
- package/dist/workflows/loader.d.ts.map +1 -1
- package/dist/workflows/loader.js +0 -27
- package/dist/workflows/loader.js.map +1 -1
- package/dist/workflows/loop.js +0 -58
- package/dist/workflows/loop.js.map +1 -1
- package/dist/workflows/ops-projection.d.ts +0 -58
- package/dist/workflows/ops-projection.d.ts.map +1 -1
- package/dist/workflows/ops-projection.js +0 -74
- package/dist/workflows/ops-projection.js.map +1 -1
- package/dist/workflows/orchestrator.d.ts +1 -65
- package/dist/workflows/orchestrator.d.ts.map +1 -1
- package/dist/workflows/orchestrator.js +74 -486
- package/dist/workflows/orchestrator.js.map +1 -1
- package/dist/workflows/output-binding.d.ts +1 -8
- package/dist/workflows/output-binding.d.ts.map +1 -1
- package/dist/workflows/output-binding.js +11 -75
- package/dist/workflows/output-binding.js.map +1 -1
- package/dist/workflows/runtime.d.ts +1 -1
- package/dist/workflows/runtime.d.ts.map +1 -1
- package/dist/workflows/runtime.js +4 -39
- package/dist/workflows/runtime.js.map +1 -1
- package/dist/workflows/wait.d.ts +2 -23
- package/dist/workflows/wait.d.ts.map +1 -1
- package/dist/workflows/wait.js +17 -39
- package/dist/workflows/wait.js.map +1 -1
- package/package.json +1 -1
- package/dist/adapters/adopt-route.d.ts +0 -63
- package/dist/adapters/adopt-route.d.ts.map +0 -1
- package/dist/adapters/adopt-route.js +0 -195
- package/dist/adapters/adopt-route.js.map +0 -1
- package/dist/adapters/cli/codex-app.d.ts +0 -4
- package/dist/adapters/cli/codex-app.d.ts.map +0 -1
- package/dist/adapters/cli/codex-app.js +0 -72
- package/dist/adapters/cli/codex-app.js.map +0 -1
- package/dist/adapters/cli/hermes.d.ts +0 -4
- package/dist/adapters/cli/hermes.d.ts.map +0 -1
- package/dist/adapters/cli/hermes.js +0 -40
- package/dist/adapters/cli/hermes.js.map +0 -1
- package/dist/adapters/cli/mira.d.ts +0 -4
- package/dist/adapters/cli/mira.d.ts.map +0 -1
- package/dist/adapters/cli/mira.js +0 -67
- package/dist/adapters/cli/mira.js.map +0 -1
- package/dist/adapters/cli/mtr.d.ts +0 -5
- package/dist/adapters/cli/mtr.d.ts.map +0 -1
- package/dist/adapters/cli/mtr.js +0 -62
- package/dist/adapters/cli/mtr.js.map +0 -1
- package/dist/adapters/hook-command.d.ts +0 -18
- package/dist/adapters/hook-command.d.ts.map +0 -1
- package/dist/adapters/hook-command.js +0 -38
- package/dist/adapters/hook-command.js.map +0 -1
- package/dist/adapters/hook-installer.d.ts +0 -14
- package/dist/adapters/hook-installer.d.ts.map +0 -1
- package/dist/adapters/hook-installer.js +0 -192
- package/dist/adapters/hook-installer.js.map +0 -1
- package/dist/codex-app-runner.d.ts +0 -3
- package/dist/codex-app-runner.d.ts.map +0 -1
- package/dist/codex-app-runner.js +0 -512
- package/dist/codex-app-runner.js.map +0 -1
- package/dist/core/ask-api.d.ts +0 -47
- package/dist/core/ask-api.d.ts.map +0 -1
- package/dist/core/ask-api.js +0 -139
- package/dist/core/ask-api.js.map +0 -1
- package/dist/core/ask-args.d.ts +0 -53
- package/dist/core/ask-args.d.ts.map +0 -1
- package/dist/core/ask-args.js +0 -122
- package/dist/core/ask-args.js.map +0 -1
- package/dist/core/ask-broker.d.ts +0 -98
- package/dist/core/ask-broker.d.ts.map +0 -1
- package/dist/core/ask-broker.js +0 -329
- package/dist/core/ask-broker.js.map +0 -1
- package/dist/core/ask-hook/claude-code.d.ts +0 -50
- package/dist/core/ask-hook/claude-code.d.ts.map +0 -1
- package/dist/core/ask-hook/claude-code.js +0 -145
- package/dist/core/ask-hook/claude-code.js.map +0 -1
- package/dist/core/ask-hook/codex.d.ts +0 -43
- package/dist/core/ask-hook/codex.d.ts.map +0 -1
- package/dist/core/ask-hook/codex.js +0 -69
- package/dist/core/ask-hook/codex.js.map +0 -1
- package/dist/core/ask-hook/opencode.d.ts +0 -41
- package/dist/core/ask-hook/opencode.d.ts.map +0 -1
- package/dist/core/ask-hook/opencode.js +0 -108
- package/dist/core/ask-hook/opencode.js.map +0 -1
- package/dist/core/ask-hook/registry.d.ts +0 -3
- package/dist/core/ask-hook/registry.d.ts.map +0 -1
- package/dist/core/ask-hook/registry.js +0 -12
- package/dist/core/ask-hook/registry.js.map +0 -1
- package/dist/core/ask-hook/types.d.ts +0 -26
- package/dist/core/ask-hook/types.d.ts.map +0 -1
- package/dist/core/ask-hook/types.js +0 -2
- package/dist/core/ask-hook/types.js.map +0 -1
- package/dist/core/ask-types.d.ts +0 -146
- package/dist/core/ask-types.d.ts.map +0 -1
- package/dist/core/ask-types.js +0 -18
- package/dist/core/ask-types.js.map +0 -1
- package/dist/core/trigger-session.d.ts +0 -9
- package/dist/core/trigger-session.d.ts.map +0 -1
- package/dist/core/trigger-session.js +0 -158
- package/dist/core/trigger-session.js.map +0 -1
- package/dist/dashboard/connector-api.d.ts +0 -3
- package/dist/dashboard/connector-api.d.ts.map +0 -1
- package/dist/dashboard/connector-api.js +0 -351
- package/dist/dashboard/connector-api.js.map +0 -1
- package/dist/dashboard/federated-group-core.d.ts +0 -54
- package/dist/dashboard/federated-group-core.d.ts.map +0 -1
- package/dist/dashboard/federated-group-core.js +0 -165
- package/dist/dashboard/federated-group-core.js.map +0 -1
- package/dist/dashboard/federation-api.d.ts +0 -42
- package/dist/dashboard/federation-api.d.ts.map +0 -1
- package/dist/dashboard/federation-api.js +0 -408
- package/dist/dashboard/federation-api.js.map +0 -1
- package/dist/dashboard/federation-spoke-api.d.ts +0 -76
- package/dist/dashboard/federation-spoke-api.d.ts.map +0 -1
- package/dist/dashboard/federation-spoke-api.js +0 -618
- package/dist/dashboard/federation-spoke-api.js.map +0 -1
- package/dist/dashboard/team-group.d.ts +0 -18
- package/dist/dashboard/team-group.d.ts.map +0 -1
- package/dist/dashboard/team-group.js +0 -7
- package/dist/dashboard/team-group.js.map +0 -1
- package/dist/dashboard/trigger-api.d.ts +0 -13
- package/dist/dashboard/trigger-api.d.ts.map +0 -1
- package/dist/dashboard/trigger-api.js +0 -77
- package/dist/dashboard/trigger-api.js.map +0 -1
- package/dist/dashboard/web/connectors.d.ts +0 -2
- package/dist/dashboard/web/connectors.d.ts.map +0 -1
- package/dist/dashboard/web/connectors.js +0 -187
- package/dist/dashboard/web/connectors.js.map +0 -1
- package/dist/dashboard/web/team-federation.d.ts +0 -3
- package/dist/dashboard/web/team-federation.d.ts.map +0 -1
- package/dist/dashboard/web/team-federation.js +0 -487
- package/dist/dashboard/web/team-federation.js.map +0 -1
- package/dist/dashboard/webhook-routes.d.ts +0 -19
- package/dist/dashboard/webhook-routes.d.ts.map +0 -1
- package/dist/dashboard/webhook-routes.js +0 -321
- package/dist/dashboard/webhook-routes.js.map +0 -1
- package/dist/im/lark/ask-card.d.ts +0 -55
- package/dist/im/lark/ask-card.d.ts.map +0 -1
- package/dist/im/lark/ask-card.js +0 -328
- package/dist/im/lark/ask-card.js.map +0 -1
- package/dist/mira-output.d.ts +0 -3
- package/dist/mira-output.d.ts.map +0 -1
- package/dist/mira-output.js +0 -136
- package/dist/mira-output.js.map +0 -1
- package/dist/mira-runner.d.ts +0 -3
- package/dist/mira-runner.d.ts.map +0 -1
- package/dist/mira-runner.js +0 -534
- package/dist/mira-runner.js.map +0 -1
- package/dist/services/bot-owner-store.d.ts +0 -28
- package/dist/services/bot-owner-store.d.ts.map +0 -1
- package/dist/services/bot-owner-store.js +0 -82
- package/dist/services/bot-owner-store.js.map +0 -1
- package/dist/services/bot-profile-store.d.ts +0 -16
- package/dist/services/bot-profile-store.d.ts.map +0 -1
- package/dist/services/bot-profile-store.js +0 -98
- package/dist/services/bot-profile-store.js.map +0 -1
- package/dist/services/brand-store.d.ts +0 -15
- package/dist/services/brand-store.d.ts.map +0 -1
- package/dist/services/brand-store.js +0 -47
- package/dist/services/brand-store.js.map +0 -1
- package/dist/services/card-prefs-store.d.ts +0 -20
- package/dist/services/card-prefs-store.d.ts.map +0 -1
- package/dist/services/card-prefs-store.js +0 -82
- package/dist/services/card-prefs-store.js.map +0 -1
- package/dist/services/connector-store.d.ts +0 -58
- package/dist/services/connector-store.d.ts.map +0 -1
- package/dist/services/connector-store.js +0 -79
- package/dist/services/connector-store.js.map +0 -1
- package/dist/services/deployment-identity.d.ts +0 -22
- package/dist/services/deployment-identity.d.ts.map +0 -1
- package/dist/services/deployment-identity.js +0 -67
- package/dist/services/deployment-identity.js.map +0 -1
- package/dist/services/federation-membership-store.d.ts +0 -23
- package/dist/services/federation-membership-store.d.ts.map +0 -1
- package/dist/services/federation-membership-store.js +0 -66
- package/dist/services/federation-membership-store.js.map +0 -1
- package/dist/services/federation-roster.d.ts +0 -54
- package/dist/services/federation-roster.d.ts.map +0 -1
- package/dist/services/federation-roster.js +0 -51
- package/dist/services/federation-roster.js.map +0 -1
- package/dist/services/federation-store.d.ts +0 -76
- package/dist/services/federation-store.d.ts.map +0 -1
- package/dist/services/federation-store.js +0 -133
- package/dist/services/federation-store.js.map +0 -1
- package/dist/services/hermes-transcript.d.ts +0 -7
- package/dist/services/hermes-transcript.d.ts.map +0 -1
- package/dist/services/hermes-transcript.js +0 -117
- package/dist/services/hermes-transcript.js.map +0 -1
- package/dist/services/invite-store.d.ts +0 -28
- package/dist/services/invite-store.d.ts.map +0 -1
- package/dist/services/invite-store.js +0 -85
- package/dist/services/invite-store.js.map +0 -1
- package/dist/services/pairing-store.d.ts +0 -47
- package/dist/services/pairing-store.d.ts.map +0 -1
- package/dist/services/pairing-store.js +0 -132
- package/dist/services/pairing-store.js.map +0 -1
- package/dist/services/relay-picker.d.ts +0 -22
- package/dist/services/relay-picker.d.ts.map +0 -1
- package/dist/services/relay-picker.js +0 -62
- package/dist/services/relay-picker.js.map +0 -1
- package/dist/services/send-policy.d.ts +0 -55
- package/dist/services/send-policy.d.ts.map +0 -1
- package/dist/services/send-policy.js +0 -47
- package/dist/services/send-policy.js.map +0 -1
- package/dist/services/team-roster.d.ts +0 -38
- package/dist/services/team-roster.d.ts.map +0 -1
- package/dist/services/team-roster.js +0 -82
- package/dist/services/team-roster.js.map +0 -1
- package/dist/services/team-store.d.ts +0 -54
- package/dist/services/team-store.d.ts.map +0 -1
- package/dist/services/team-store.js +0 -156
- package/dist/services/team-store.js.map +0 -1
- package/dist/services/trigger-log-store.d.ts +0 -46
- package/dist/services/trigger-log-store.d.ts.map +0 -1
- package/dist/services/trigger-log-store.js +0 -132
- package/dist/services/trigger-log-store.js.map +0 -1
- package/dist/services/trigger-types.d.ts +0 -57
- package/dist/services/trigger-types.d.ts.map +0 -1
- package/dist/services/trigger-types.js +0 -28
- package/dist/services/trigger-types.js.map +0 -1
- package/dist/services/webhook-key.d.ts +0 -16
- package/dist/services/webhook-key.d.ts.map +0 -1
- package/dist/services/webhook-key.js +0 -123
- package/dist/services/webhook-key.js.map +0 -1
- package/dist/services/webhook-lifecycle-extractors.d.ts +0 -15
- package/dist/services/webhook-lifecycle-extractors.d.ts.map +0 -1
- package/dist/services/webhook-lifecycle-extractors.js +0 -59
- package/dist/services/webhook-lifecycle-extractors.js.map +0 -1
- package/dist/services/webhook-lifecycle-store.d.ts +0 -45
- package/dist/services/webhook-lifecycle-store.d.ts.map +0 -1
- package/dist/services/webhook-lifecycle-store.js +0 -159
- package/dist/services/webhook-lifecycle-store.js.map +0 -1
- package/dist/utils/daemon-discovery.d.ts +0 -11
- package/dist/utils/daemon-discovery.d.ts.map +0 -1
- package/dist/utils/daemon-discovery.js +0 -59
- package/dist/utils/daemon-discovery.js.map +0 -1
- package/dist/workflows/trigger-from-envelope.d.ts +0 -13
- package/dist/workflows/trigger-from-envelope.d.ts.map +0 -1
- package/dist/workflows/trigger-from-envelope.js +0 -67
- package/dist/workflows/trigger-from-envelope.js.map +0 -1
|
@@ -4,14 +4,10 @@ const cliDisplayNames = {
|
|
|
4
4
|
'aiden': 'Aiden',
|
|
5
5
|
'coco': 'CoCo',
|
|
6
6
|
'codex': 'Codex',
|
|
7
|
-
'codex-app': 'Codex App',
|
|
8
7
|
'cursor': 'Cursor',
|
|
9
8
|
'gemini': 'Gemini',
|
|
10
9
|
'opencode': 'OpenCode',
|
|
11
10
|
'antigravity': 'Antigravity',
|
|
12
|
-
'mtr': 'MTR',
|
|
13
|
-
'hermes': 'Hermes',
|
|
14
|
-
'mira': 'Mira',
|
|
15
11
|
};
|
|
16
12
|
export function getCliDisplayName(cliId) {
|
|
17
13
|
return cliDisplayNames[cliId] ?? cliId;
|
|
@@ -133,70 +129,14 @@ export function buildSessionClosedCard(sessionId, rootId, title, cliId, workingD
|
|
|
133
129
|
};
|
|
134
130
|
return JSON.stringify(card);
|
|
135
131
|
}
|
|
136
|
-
/**
|
|
137
|
-
* Build a frozen-snapshot card to PATCH onto the source-chat streaming card
|
|
138
|
-
* after `/relay` moves the session elsewhere.
|
|
139
|
-
*
|
|
140
|
-
* Why this exists: a live streaming card carries action buttons (close /
|
|
141
|
-
* toggle display / get write link). Those buttons identify their session by
|
|
142
|
-
* `session_id` in the value payload, so clicking them after relay still
|
|
143
|
-
* reaches the now-relocated session — closing it, toggling its display
|
|
144
|
-
* mode, etc. — but the visible feedback all lands on the NEW card in the
|
|
145
|
-
* target chat, not this one. The source-chat card then looks like a "live
|
|
146
|
-
* console" while actually being a footgun. PATCH it to an inert snapshot
|
|
147
|
-
* so the user sees clearly it's historical.
|
|
148
|
-
*
|
|
149
|
-
* Last-frame rendering:
|
|
150
|
-
* - imageKey present (session was in 'screenshot' / expanded mode at
|
|
151
|
-
* relay time) → embed the same img element the live card had.
|
|
152
|
-
* img_key is a Lark server resource independent of the card it lived
|
|
153
|
-
* on, so the PATCHed card can still reference it.
|
|
154
|
-
* - imageKey absent (hidden / collapsed mode) → render nothing extra.
|
|
155
|
-
* The header + body notice already convey the state; raw tmux pane
|
|
156
|
-
* text as a code-block is too long and noisy (王皓 caught this in
|
|
157
|
-
* testing).
|
|
158
|
-
*
|
|
159
|
-
* No action buttons are rendered in either case.
|
|
160
|
-
*/
|
|
161
|
-
export function buildRelayedFrozenCard(title, cliId, imageKey, locale) {
|
|
162
|
-
const cliName = getCliDisplayName(cliId ?? 'claude-code');
|
|
163
|
-
const body = `**${escapeMd(title || cliName)}**\n` +
|
|
164
|
-
`${t('card.body.relay_frozen', undefined, locale)}`;
|
|
165
|
-
const elements = [
|
|
166
|
-
{ tag: 'markdown', content: body },
|
|
167
|
-
];
|
|
168
|
-
if (imageKey) {
|
|
169
|
-
elements.push({
|
|
170
|
-
tag: 'img',
|
|
171
|
-
img_key: imageKey,
|
|
172
|
-
alt: { tag: 'plain_text', content: '' },
|
|
173
|
-
mode: 'fit_horizontal',
|
|
174
|
-
preview: true,
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
const card = {
|
|
178
|
-
config: { wide_screen_mode: true },
|
|
179
|
-
header: {
|
|
180
|
-
title: { tag: 'plain_text', content: t('card.status.relay_frozen', undefined, locale) },
|
|
181
|
-
template: 'grey',
|
|
182
|
-
},
|
|
183
|
-
elements,
|
|
184
|
-
};
|
|
185
|
-
return JSON.stringify(card);
|
|
186
|
-
}
|
|
187
132
|
/**
|
|
188
133
|
* Feishu card API rejects payloads exceeding ~109 KB (error 230025).
|
|
189
134
|
* Cap markdown content byte size with headroom for card JSON overhead.
|
|
190
135
|
*/
|
|
191
136
|
const MAX_CONTENT_BYTES = 100_000;
|
|
192
|
-
/**
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
* in additional card JSON (e.g. the private snapshot's code fence) pass a
|
|
196
|
-
* tighter budget so the whole card stays under Feishu's ~109 KB hard limit.
|
|
197
|
-
*/
|
|
198
|
-
export function truncateContent(content, locale, maxBytes = MAX_CONTENT_BYTES) {
|
|
199
|
-
if (Buffer.byteLength(content, 'utf-8') <= maxBytes)
|
|
137
|
+
/** Truncate content to fit within MAX_CONTENT_BYTES, keeping the tail (most recent output). */
|
|
138
|
+
export function truncateContent(content, locale) {
|
|
139
|
+
if (Buffer.byteLength(content, 'utf-8') <= MAX_CONTENT_BYTES)
|
|
200
140
|
return content;
|
|
201
141
|
// Binary search for the longest suffix that fits
|
|
202
142
|
const lines = content.split('\n');
|
|
@@ -205,7 +145,7 @@ export function truncateContent(content, locale, maxBytes = MAX_CONTENT_BYTES) {
|
|
|
205
145
|
while (lo < hi) {
|
|
206
146
|
const mid = Math.floor((lo + hi) / 2);
|
|
207
147
|
const candidate = lines.slice(mid).join('\n');
|
|
208
|
-
if (Buffer.byteLength(candidate, 'utf-8') <=
|
|
148
|
+
if (Buffer.byteLength(candidate, 'utf-8') <= MAX_CONTENT_BYTES - 30) {
|
|
209
149
|
hi = mid;
|
|
210
150
|
}
|
|
211
151
|
else {
|
|
@@ -214,29 +154,36 @@ export function truncateContent(content, locale, maxBytes = MAX_CONTENT_BYTES) {
|
|
|
214
154
|
}
|
|
215
155
|
return `${t('card.status.truncated_prefix', undefined, locale)}\n${lines.slice(lo).join('\n')}`;
|
|
216
156
|
}
|
|
217
|
-
/**
|
|
218
|
-
*
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
*
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Build a Feishu streaming card that shows live terminal output + controls.
|
|
159
|
+
* This card is PATCHed in-place as the CLI works.
|
|
160
|
+
*
|
|
161
|
+
* displayMode:
|
|
162
|
+
* - 'hidden' — body collapsed; only header + main controls visible.
|
|
163
|
+
* - 'screenshot' — img element (rendered server-side, uploaded for img_key).
|
|
164
|
+
*
|
|
165
|
+
* Quick-action buttons (Esc, ^C, Tab, Space, Enter, ←↑↓→, ½屏 ↑/↓) appear
|
|
166
|
+
* whenever displayMode !== 'hidden'.
|
|
167
|
+
*/
|
|
168
|
+
export function buildStreamingCard(sessionId, rootId, terminalUrl, title, screenContent, status, cliId, displayMode = 'hidden', cardNonce, imageKey, adoptMode, showTakeover, locale, usageLimit) {
|
|
169
|
+
const effectiveCliId = cliId ?? 'claude-code';
|
|
170
|
+
const cliName = getCliDisplayName(effectiveCliId);
|
|
171
|
+
const actionBase = { root_id: rootId, session_id: sessionId, cli_id: effectiveCliId, ...(cardNonce ? { card_nonce: cardNonce } : {}) };
|
|
172
|
+
const displayStatus = status === 'limited' && usageLimit?.retryReady ? 'retry_ready' : status;
|
|
173
|
+
const templateMap = { starting: 'yellow', working: 'blue', idle: 'green', analyzing: 'purple', limited: 'red', retry_ready: 'green' };
|
|
174
|
+
const statusLabel = (s) => {
|
|
175
|
+
switch (s) {
|
|
176
|
+
case 'starting': return t('card.status.starting', undefined, locale);
|
|
177
|
+
case 'working': return t('card.status.working', undefined, locale);
|
|
178
|
+
case 'idle': return t('card.status.idle', undefined, locale);
|
|
179
|
+
case 'analyzing': return t('card.status.analyzing', undefined, locale);
|
|
180
|
+
case 'limited': return usageLimit?.retryReady
|
|
181
|
+
? t('card.status.retry_ready', undefined, locale)
|
|
182
|
+
: t('card.status.limited', undefined, locale);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
const elements = [];
|
|
186
|
+
// ── Output body ─────────────────────────────────────────────────────────
|
|
240
187
|
if (status === 'limited' && usageLimit) {
|
|
241
188
|
elements.push({
|
|
242
189
|
tag: 'markdown',
|
|
@@ -248,33 +195,19 @@ function pushStreamBody(elements, opts) {
|
|
|
248
195
|
}
|
|
249
196
|
if (displayMode === 'screenshot') {
|
|
250
197
|
if (imageKey) {
|
|
251
|
-
elements.push({
|
|
198
|
+
elements.push({
|
|
199
|
+
tag: 'img',
|
|
200
|
+
img_key: imageKey,
|
|
201
|
+
alt: { tag: 'plain_text', content: '' },
|
|
202
|
+
mode: 'fit_horizontal',
|
|
203
|
+
preview: true,
|
|
204
|
+
});
|
|
252
205
|
}
|
|
253
206
|
else {
|
|
254
207
|
elements.push({ tag: 'markdown', content: t('card.status.waiting_screenshot', undefined, locale) });
|
|
255
208
|
}
|
|
256
209
|
elements.push({ tag: 'hr' });
|
|
257
210
|
}
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Build a Feishu streaming card that shows live terminal output + controls.
|
|
261
|
-
* This card is PATCHed in-place as the CLI works.
|
|
262
|
-
*
|
|
263
|
-
* displayMode:
|
|
264
|
-
* - 'hidden' — body collapsed; only header + main controls visible.
|
|
265
|
-
* - 'screenshot' — img element (rendered server-side, uploaded for img_key).
|
|
266
|
-
*
|
|
267
|
-
* Quick-action buttons (Esc, ^C, Tab, Space, Enter, ←↑↓→, ½屏 ↑/↓) appear
|
|
268
|
-
* whenever displayMode !== 'hidden'.
|
|
269
|
-
*/
|
|
270
|
-
export function buildStreamingCard(sessionId, rootId, terminalUrl, title, screenContent, status, cliId, displayMode = 'hidden', cardNonce, imageKey, adoptMode, showTakeover, locale, usageLimit, writableTerminalUrl) {
|
|
271
|
-
const effectiveCliId = cliId ?? 'claude-code';
|
|
272
|
-
const cliName = getCliDisplayName(effectiveCliId);
|
|
273
|
-
const actionBase = { root_id: rootId, session_id: sessionId, cli_id: effectiveCliId, ...(cardNonce ? { card_nonce: cardNonce } : {}) };
|
|
274
|
-
const displayStatus = status === 'limited' && usageLimit?.retryReady ? 'retry_ready' : status;
|
|
275
|
-
const elements = [];
|
|
276
|
-
// ── Output body (shared with the private snapshot card) ──────────────────
|
|
277
|
-
pushStreamBody(elements, { status, usageLimit, displayMode, imageKey, cliName, locale });
|
|
278
211
|
// ── Main control row: display toggle, mode toggle, terminal, manage ─────
|
|
279
212
|
const headerActions = [];
|
|
280
213
|
headerActions.push({
|
|
@@ -344,16 +277,6 @@ export function buildStreamingCard(sessionId, rootId, terminalUrl, title, screen
|
|
|
344
277
|
});
|
|
345
278
|
}
|
|
346
279
|
elements.push({ tag: 'action', actions: headerActions });
|
|
347
|
-
// ── Writable terminal link (opt-in) ─────────────────────────────────────
|
|
348
|
-
// When the bot enables `writableTerminalLinkInCard`, embed the token-bearing
|
|
349
|
-
// link right in the card so anyone here can open a writable terminal without
|
|
350
|
-
// the get-write-link → DM round-trip. The link is intentionally group-visible.
|
|
351
|
-
if (writableTerminalUrl) {
|
|
352
|
-
elements.push({
|
|
353
|
-
tag: 'markdown',
|
|
354
|
-
content: t('card.writable_terminal_link', { url: writableTerminalUrl }, locale),
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
280
|
// ── Quick-action keys (only when the screenshot is visible — in text mode
|
|
358
281
|
// there's no visible cursor/input, so these keys would fire blindly) ──
|
|
359
282
|
if (displayMode === 'screenshot') {
|
|
@@ -388,94 +311,8 @@ export function buildStreamingCard(sessionId, rootId, terminalUrl, title, screen
|
|
|
388
311
|
const card = {
|
|
389
312
|
config: { wide_screen_mode: true },
|
|
390
313
|
header: {
|
|
391
|
-
title: { tag: 'plain_text', content: `🖥️ ${cliName} · ${escapeMd(title)} — ${
|
|
392
|
-
template:
|
|
393
|
-
},
|
|
394
|
-
elements,
|
|
395
|
-
};
|
|
396
|
-
return JSON.stringify(card);
|
|
397
|
-
}
|
|
398
|
-
/**
|
|
399
|
-
* Build a static "private snapshot" card for `/card` in private mode — sent via
|
|
400
|
-
* the ephemeral API to one user at a time. Unlike {@link buildStreamingCard} it
|
|
401
|
-
* is **never PATCH-updated** (ephemeral cards can't be), so it carries only a
|
|
402
|
-
* one-shot snapshot of the terminal screenshot plus three buttons:
|
|
403
|
-
* • read-only "open terminal" link (a plain URL button — no callback);
|
|
404
|
-
* • "get write link", whose callback DMs the writable link to the clicker;
|
|
405
|
-
* • "close session", whose callback kills the session and (in private mode)
|
|
406
|
-
* sends the "closed" card ephemeral to the owner audience too — so the
|
|
407
|
-
* session title / CLI name / workingDir on it don't leak to the group.
|
|
408
|
-
* The last two have callbacks but neither patches THIS card (one DMs, the other
|
|
409
|
-
* sends a fresh card), so both work fine on an ephemeral card. Both are
|
|
410
|
-
* `canOperate`-gated in the handler — talk-only viewers who tap them are denied.
|
|
411
|
-
* The patch-driven controls (toggle/refresh/export/term keys) and the inline
|
|
412
|
-
* writable link are still omitted: those need to update this card, which
|
|
413
|
-
* ephemeral cards can't do.
|
|
414
|
-
*/
|
|
415
|
-
export function buildPrivateSnapshotCard(terminalUrl, title, status, cliId, imageKey, screenContent, sessionId, rootId, locale, usageLimit) {
|
|
416
|
-
const effectiveCliId = cliId ?? 'claude-code';
|
|
417
|
-
const cliName = getCliDisplayName(effectiveCliId);
|
|
418
|
-
const displayStatus = status === 'limited' && usageLimit?.retryReady ? 'retry_ready' : status;
|
|
419
|
-
// `visibility: 'private'` pins this card's privacy intent onto the action
|
|
420
|
-
// itself, so a later callback (notably `close`) keeps sending ephemeral even
|
|
421
|
-
// if the bot's `privateCard` config is toggled off after the card was sent —
|
|
422
|
-
// otherwise the closed card (session title / workingDir / resume command)
|
|
423
|
-
// could leak to the group. See the `close` handler in card-handler.ts.
|
|
424
|
-
const actionBase = { root_id: rootId, session_id: sessionId, cli_id: effectiveCliId, visibility: 'private' };
|
|
425
|
-
const elements = [];
|
|
426
|
-
// Show the terminal once: prefer the rendered screenshot when present;
|
|
427
|
-
// otherwise fall back to a code-block of the latest screen text so the
|
|
428
|
-
// snapshot isn't empty (common when the bot has the streaming card disabled
|
|
429
|
-
// or display mode never flipped to screenshot — `lastScreenContent` is still
|
|
430
|
-
// kept up to date regardless). pushStreamBody also emits the usage-limit
|
|
431
|
-
// notice, which applies in either case.
|
|
432
|
-
pushStreamBody(elements, {
|
|
433
|
-
status, usageLimit, displayMode: imageKey ? 'screenshot' : 'hidden', imageKey, cliName, locale,
|
|
434
|
-
});
|
|
435
|
-
if (!imageKey) {
|
|
436
|
-
const text = (screenContent ?? '').replace(/[ \t\r\n]+$/, '');
|
|
437
|
-
if (text) {
|
|
438
|
-
const body = truncateContent(text, locale, PRIVATE_SNAPSHOT_TEXT_MAX);
|
|
439
|
-
// Fence must be longer than the longest backtick run in the body, else
|
|
440
|
-
// terminal output containing ``` would break out of the code block.
|
|
441
|
-
const maxRun = (body.match(/`+/g) ?? []).reduce((m, r) => Math.max(m, r.length), 0);
|
|
442
|
-
const fence = '`'.repeat(Math.max(3, maxRun + 1));
|
|
443
|
-
elements.push({ tag: 'markdown', content: `${fence}\n${body}\n${fence}` });
|
|
444
|
-
elements.push({ tag: 'hr' });
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
elements.push({
|
|
448
|
-
tag: 'action',
|
|
449
|
-
actions: [
|
|
450
|
-
{
|
|
451
|
-
tag: 'button',
|
|
452
|
-
text: { tag: 'plain_text', content: t('card.btn.open_terminal', undefined, locale) },
|
|
453
|
-
type: 'primary',
|
|
454
|
-
multi_url: { url: terminalUrl, pc_url: terminalUrl, android_url: terminalUrl, ios_url: terminalUrl },
|
|
455
|
-
},
|
|
456
|
-
{
|
|
457
|
-
tag: 'button',
|
|
458
|
-
text: { tag: 'plain_text', content: t('card.btn.get_write_link', undefined, locale) },
|
|
459
|
-
type: 'default',
|
|
460
|
-
value: { action: 'get_write_link', ...actionBase },
|
|
461
|
-
},
|
|
462
|
-
{
|
|
463
|
-
tag: 'button',
|
|
464
|
-
text: { tag: 'plain_text', content: t('card.btn.close_session', undefined, locale) },
|
|
465
|
-
type: 'danger',
|
|
466
|
-
value: { action: 'close', ...actionBase },
|
|
467
|
-
},
|
|
468
|
-
],
|
|
469
|
-
});
|
|
470
|
-
elements.push({
|
|
471
|
-
tag: 'note',
|
|
472
|
-
elements: [{ tag: 'lark_md', content: t('card.private.snapshot_note', undefined, locale) }],
|
|
473
|
-
});
|
|
474
|
-
const card = {
|
|
475
|
-
config: { wide_screen_mode: true },
|
|
476
|
-
header: {
|
|
477
|
-
title: { tag: 'plain_text', content: `🔒 ${cliName} · ${escapeMd(title)} — ${streamStatusLabel(status, usageLimit, locale)}` },
|
|
478
|
-
template: STREAM_TEMPLATE_MAP[displayStatus],
|
|
314
|
+
title: { tag: 'plain_text', content: `🖥️ ${cliName} · ${escapeMd(title)} — ${statusLabel(status)}` },
|
|
315
|
+
template: templateMap[displayStatus],
|
|
479
316
|
},
|
|
480
317
|
elements,
|
|
481
318
|
};
|
|
@@ -548,22 +385,19 @@ export function buildGrantCard(o, locale) {
|
|
|
548
385
|
? t('card.grant.body_request', { name: escapeMd(o.requesterName), owner: o.ownerOpenId }, locale)
|
|
549
386
|
: t('card.grant.body_owner', { name: escapeMd(o.requesterName), owner: o.ownerOpenId }, locale);
|
|
550
387
|
const v = { target_open_id: o.requesterOpenId, chat_id: o.chatId, nonce: o.nonce };
|
|
551
|
-
// 「全局授权对话」只在 owner 主动发卡时出现:owner 一眼明确要给全局;request 模式(成员
|
|
552
|
-
// 自助申请)只提供「本群」,避免成员把自己申请到全局。两个授权按钮都是 talk-only。
|
|
553
|
-
const grantButtons = [
|
|
554
|
-
{ tag: 'button', type: 'primary', text: { tag: 'plain_text', content: t('card.grant.btn_chat', undefined, locale) }, value: { action: 'grant_chat', ...v } },
|
|
555
|
-
];
|
|
556
|
-
if (o.mode === 'owner') {
|
|
557
|
-
grantButtons.push({ tag: 'button', type: 'default', text: { tag: 'plain_text', content: t('card.grant.btn_global', undefined, locale) }, value: { action: 'grant_global', ...v } });
|
|
558
|
-
}
|
|
559
|
-
grantButtons.push({ tag: 'button', type: 'danger', text: { tag: 'plain_text', content: t('card.grant.btn_deny', undefined, locale) }, value: { action: 'grant_deny', ...v } });
|
|
560
388
|
const card = {
|
|
561
389
|
config: { wide_screen_mode: true },
|
|
562
390
|
header: { template: 'orange', title: { tag: 'plain_text', content: t('card.grant.title', undefined, locale) } },
|
|
563
391
|
elements: [
|
|
564
392
|
{ tag: 'div', text: { tag: 'lark_md', content: body } },
|
|
565
393
|
{ tag: 'hr' },
|
|
566
|
-
{
|
|
394
|
+
{
|
|
395
|
+
tag: 'action',
|
|
396
|
+
actions: [
|
|
397
|
+
{ tag: 'button', type: 'primary', text: { tag: 'plain_text', content: t('card.grant.btn_chat', undefined, locale) }, value: { action: 'grant_chat', ...v } },
|
|
398
|
+
{ tag: 'button', type: 'danger', text: { tag: 'plain_text', content: t('card.grant.btn_deny', undefined, locale) }, value: { action: 'grant_deny', ...v } },
|
|
399
|
+
],
|
|
400
|
+
},
|
|
567
401
|
{ tag: 'note', elements: [{ tag: 'lark_md', content: t('card.grant.note', undefined, locale) }] },
|
|
568
402
|
],
|
|
569
403
|
};
|
|
@@ -736,270 +570,6 @@ function formatDuration(ms) {
|
|
|
736
570
|
const d = Math.floor(h / 24);
|
|
737
571
|
return `${d}d${h % 24}h`;
|
|
738
572
|
}
|
|
739
|
-
function relayPickerTypeTag(mode, locale) {
|
|
740
|
-
switch (mode) {
|
|
741
|
-
case 'p2p': return t('card.relay.type_p2p', undefined, locale);
|
|
742
|
-
case 'topic': return t('card.relay.type_topic', undefined, locale);
|
|
743
|
-
default: return t('card.relay.type_group', undefined, locale); // 'group' or undefined
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
const RELAY_PICKER_PAGE_SIZE = 5;
|
|
747
|
-
const RELAY_SEARCH_FIELD = 'search';
|
|
748
|
-
/**
|
|
749
|
-
* Match against title / chatLabel / workingDir / cliId. Case-insensitive
|
|
750
|
-
* substring. Empty / whitespace query matches everything.
|
|
751
|
-
*/
|
|
752
|
-
function relayPickerFilter(entries, query) {
|
|
753
|
-
const q = (query ?? '').trim().toLowerCase();
|
|
754
|
-
if (!q)
|
|
755
|
-
return entries;
|
|
756
|
-
return entries.filter((e) => {
|
|
757
|
-
const haystack = [e.title, e.chatLabel, e.workingDir, e.cliId]
|
|
758
|
-
.filter(Boolean)
|
|
759
|
-
.join(' ')
|
|
760
|
-
.toLowerCase();
|
|
761
|
-
return haystack.includes(q);
|
|
762
|
-
});
|
|
763
|
-
}
|
|
764
|
-
/**
|
|
765
|
-
* Card listing the operator's relayable sessions, paginated 5 per page with
|
|
766
|
-
* a search box at the top and a confirm button at the bottom. Layout:
|
|
767
|
-
*
|
|
768
|
-
* ┌──────────────────────────────────────┐
|
|
769
|
-
* │ 📋 选择要接力的会话 │ header
|
|
770
|
-
* ├──────────────────────────────────────┤
|
|
771
|
-
* │ 🔍 [______________] [搜索] │ form: input + submit button
|
|
772
|
-
* ├──────────────────────────────────────┤
|
|
773
|
-
* │ [interactive_container 1] │ current page (≤5 cards),
|
|
774
|
-
* │ [interactive_container 2] │ each clickable for selection
|
|
775
|
-
* │ ... │
|
|
776
|
-
* ├──────────────────────────────────────┤
|
|
777
|
-
* │ [← 上一页] 1 / 4 [下一页 →] │ paginator row
|
|
778
|
-
* ├──────────────────────────────────────┤
|
|
779
|
-
* │ [确认接力到本群] │ primary button (only when
|
|
780
|
-
* │ │ a selected session is on
|
|
781
|
-
* │ │ the current filtered set)
|
|
782
|
-
* └──────────────────────────────────────┘
|
|
783
|
-
*
|
|
784
|
-
* State (search / page / selected) is propagated entirely via the value
|
|
785
|
-
* objects on each button and container — Lark cards are stateless, so any
|
|
786
|
-
* server-side re-render must reconstruct from what the click sent us.
|
|
787
|
-
* That's why every interactive value here carries `search`, `page`,
|
|
788
|
-
* `target_chat_id`, `root_id`.
|
|
789
|
-
*
|
|
790
|
-
* Note: typing into the search box without clicking 搜索 does NOT update
|
|
791
|
-
* the in-callback state — container/paginator clicks use whatever search
|
|
792
|
-
* was applied at card-render time. To apply a new filter, click 搜索.
|
|
793
|
-
*/
|
|
794
|
-
export function buildRelayPickerCard(entries, targetChatId, targetRootMessageId, invokerOpenId, locale, state) {
|
|
795
|
-
const searchQuery = state?.searchQuery ?? '';
|
|
796
|
-
const requestedPage = state?.page ?? 0;
|
|
797
|
-
const selectedSessionId = state?.selectedSessionId;
|
|
798
|
-
const elements = [];
|
|
799
|
-
// ─── Filter & paginate ───────────────────────────────────────────────
|
|
800
|
-
const filtered = relayPickerFilter(entries, searchQuery);
|
|
801
|
-
const totalPages = Math.max(1, Math.ceil(filtered.length / RELAY_PICKER_PAGE_SIZE));
|
|
802
|
-
const page = Math.min(Math.max(0, requestedPage), totalPages - 1);
|
|
803
|
-
const start = page * RELAY_PICKER_PAGE_SIZE;
|
|
804
|
-
const visible = filtered.slice(start, start + RELAY_PICKER_PAGE_SIZE);
|
|
805
|
-
// Common state object carried by every interactive value so re-renders
|
|
806
|
-
// can reconstruct what the user was looking at. `invoker_open_id` pins the
|
|
807
|
-
// card to the user who originally summoned it — card-handler refuses
|
|
808
|
-
// re-render / confirm clicks from anyone else, so the menu doesn't get
|
|
809
|
-
// silently swapped to a passer-by's session list.
|
|
810
|
-
const stateValue = {
|
|
811
|
-
target_chat_id: targetChatId,
|
|
812
|
-
root_id: targetRootMessageId,
|
|
813
|
-
invoker_open_id: invokerOpenId,
|
|
814
|
-
search: searchQuery,
|
|
815
|
-
page,
|
|
816
|
-
selected: selectedSessionId ?? '',
|
|
817
|
-
};
|
|
818
|
-
// ─── Search box ─────────────────────────────────────────────────────
|
|
819
|
-
// v2 input supports `behaviors` natively — pressing Enter or clicking
|
|
820
|
-
// the built-in submit icon inside the input fires the callback. No
|
|
821
|
-
// separate 搜索 button needed (王皓 reported that button rendered as
|
|
822
|
-
// "..." due to cramped column width; the auto-submit input avoids the
|
|
823
|
-
// problem entirely AND removes the manual click).
|
|
824
|
-
//
|
|
825
|
-
// On submit the callback delivers `action.input_value` (the typed
|
|
826
|
-
// string) and `action.value` (our state object). card-handler reads
|
|
827
|
-
// input_value to update search, resets page to 0 and clears selection.
|
|
828
|
-
elements.push({
|
|
829
|
-
tag: 'input',
|
|
830
|
-
name: RELAY_SEARCH_FIELD,
|
|
831
|
-
placeholder: { tag: 'plain_text', content: t('card.relay.search_placeholder', undefined, locale) },
|
|
832
|
-
default_value: searchQuery,
|
|
833
|
-
width: 'fill',
|
|
834
|
-
behaviors: [
|
|
835
|
-
{
|
|
836
|
-
type: 'callback',
|
|
837
|
-
value: { action: 'relay_search', ...stateValue, selected: '' /* new search → reset selection */ },
|
|
838
|
-
},
|
|
839
|
-
],
|
|
840
|
-
});
|
|
841
|
-
elements.push({ tag: 'hr' });
|
|
842
|
-
// ─── Empty / no-match notice ────────────────────────────────────────
|
|
843
|
-
if (entries.length === 0) {
|
|
844
|
-
elements.push({ tag: 'markdown', content: t('card.relay.empty', undefined, locale) });
|
|
845
|
-
return JSON.stringify(wrapCard(elements, locale));
|
|
846
|
-
}
|
|
847
|
-
if (filtered.length === 0) {
|
|
848
|
-
elements.push({
|
|
849
|
-
tag: 'markdown',
|
|
850
|
-
content: t('card.relay.empty_filtered', { query: searchQuery }, locale),
|
|
851
|
-
});
|
|
852
|
-
return JSON.stringify(wrapCard(elements, locale));
|
|
853
|
-
}
|
|
854
|
-
// ─── Session cards (current page) ───────────────────────────────────
|
|
855
|
-
const p2pLocationLabel = t('card.relay.type_p2p', undefined, locale);
|
|
856
|
-
const labelType = t('card.relay.field_type', undefined, locale);
|
|
857
|
-
const labelLocation = t('card.relay.field_location', undefined, locale);
|
|
858
|
-
const labelTime = t('card.relay.field_time', undefined, locale);
|
|
859
|
-
const selectedTag = t('card.relay.selected_tag', undefined, locale);
|
|
860
|
-
const hasValidSelection = !!selectedSessionId && filtered.some(e => e.sessionId === selectedSessionId);
|
|
861
|
-
visible.forEach((e) => {
|
|
862
|
-
const isSelected = e.sessionId === selectedSessionId;
|
|
863
|
-
const typeTag = relayPickerTypeTag(e.chatMode, locale);
|
|
864
|
-
const locationLine = e.chatMode === 'p2p' ? p2pLocationLabel : e.chatLabel;
|
|
865
|
-
const titleLine = isSelected
|
|
866
|
-
? `**✅ ${escapeMd(e.title)}** \`${selectedTag}\``
|
|
867
|
-
: `**${escapeMd(e.title)}**`;
|
|
868
|
-
const lines = [
|
|
869
|
-
titleLine,
|
|
870
|
-
`${labelType}: ${typeTag}`,
|
|
871
|
-
`${labelLocation}: ${escapeMd(locationLine)}`,
|
|
872
|
-
];
|
|
873
|
-
if (e.lastMessageAt) {
|
|
874
|
-
lines.push(`${labelTime}: ${formatDuration(Date.now() - e.lastMessageAt)}`);
|
|
875
|
-
}
|
|
876
|
-
elements.push({
|
|
877
|
-
tag: 'interactive_container',
|
|
878
|
-
width: 'fill',
|
|
879
|
-
padding: '8px 12px',
|
|
880
|
-
background_style: isSelected ? 'laser' : 'default',
|
|
881
|
-
has_border: true,
|
|
882
|
-
border_color: isSelected ? 'blue-500' : 'grey-200',
|
|
883
|
-
corner_radius: '8px',
|
|
884
|
-
behaviors: [
|
|
885
|
-
{
|
|
886
|
-
type: 'callback',
|
|
887
|
-
value: { action: 'relay_select', session_id: e.sessionId, ...stateValue },
|
|
888
|
-
},
|
|
889
|
-
],
|
|
890
|
-
elements: [{ tag: 'markdown', content: lines.join('\n') }],
|
|
891
|
-
});
|
|
892
|
-
});
|
|
893
|
-
// ─── Paginator (only when more than one page) ───────────────────────
|
|
894
|
-
if (totalPages > 1) {
|
|
895
|
-
elements.push({
|
|
896
|
-
tag: 'column_set',
|
|
897
|
-
flex_mode: 'none',
|
|
898
|
-
horizontal_spacing: 'default',
|
|
899
|
-
columns: [
|
|
900
|
-
{
|
|
901
|
-
tag: 'column',
|
|
902
|
-
width: 'weighted',
|
|
903
|
-
weight: 1,
|
|
904
|
-
vertical_align: 'center',
|
|
905
|
-
elements: [
|
|
906
|
-
{
|
|
907
|
-
tag: 'button',
|
|
908
|
-
text: { tag: 'plain_text', content: t('card.relay.btn_prev_page', undefined, locale) },
|
|
909
|
-
type: 'default',
|
|
910
|
-
disabled: page === 0,
|
|
911
|
-
behaviors: [
|
|
912
|
-
{
|
|
913
|
-
type: 'callback',
|
|
914
|
-
value: { action: 'relay_page', ...stateValue, page: Math.max(0, page - 1) },
|
|
915
|
-
},
|
|
916
|
-
],
|
|
917
|
-
},
|
|
918
|
-
],
|
|
919
|
-
},
|
|
920
|
-
{
|
|
921
|
-
tag: 'column',
|
|
922
|
-
width: 'weighted',
|
|
923
|
-
weight: 2,
|
|
924
|
-
vertical_align: 'center',
|
|
925
|
-
elements: [
|
|
926
|
-
{
|
|
927
|
-
tag: 'markdown',
|
|
928
|
-
text_align: 'center',
|
|
929
|
-
content: t('card.relay.page_indicator', { current: page + 1, total: totalPages }, locale),
|
|
930
|
-
},
|
|
931
|
-
],
|
|
932
|
-
},
|
|
933
|
-
{
|
|
934
|
-
tag: 'column',
|
|
935
|
-
width: 'weighted',
|
|
936
|
-
weight: 1,
|
|
937
|
-
vertical_align: 'center',
|
|
938
|
-
elements: [
|
|
939
|
-
{
|
|
940
|
-
tag: 'button',
|
|
941
|
-
text: { tag: 'plain_text', content: t('card.relay.btn_next_page', undefined, locale) },
|
|
942
|
-
type: 'default',
|
|
943
|
-
disabled: page === totalPages - 1,
|
|
944
|
-
behaviors: [
|
|
945
|
-
{
|
|
946
|
-
type: 'callback',
|
|
947
|
-
value: { action: 'relay_page', ...stateValue, page: Math.min(totalPages - 1, page + 1) },
|
|
948
|
-
},
|
|
949
|
-
],
|
|
950
|
-
},
|
|
951
|
-
],
|
|
952
|
-
},
|
|
953
|
-
],
|
|
954
|
-
});
|
|
955
|
-
}
|
|
956
|
-
// ─── Confirm button or hint ─────────────────────────────────────────
|
|
957
|
-
elements.push({ tag: 'hr' });
|
|
958
|
-
if (hasValidSelection) {
|
|
959
|
-
elements.push({
|
|
960
|
-
tag: 'column_set',
|
|
961
|
-
flex_mode: 'none',
|
|
962
|
-
columns: [
|
|
963
|
-
{
|
|
964
|
-
tag: 'column',
|
|
965
|
-
width: 'weighted',
|
|
966
|
-
weight: 1,
|
|
967
|
-
elements: [
|
|
968
|
-
{
|
|
969
|
-
tag: 'button',
|
|
970
|
-
text: { tag: 'plain_text', content: t('card.relay.btn_confirm', undefined, locale) },
|
|
971
|
-
type: 'primary',
|
|
972
|
-
behaviors: [
|
|
973
|
-
{
|
|
974
|
-
type: 'callback',
|
|
975
|
-
value: { action: 'relay_confirm', session_id: selectedSessionId, ...stateValue },
|
|
976
|
-
},
|
|
977
|
-
],
|
|
978
|
-
},
|
|
979
|
-
],
|
|
980
|
-
},
|
|
981
|
-
],
|
|
982
|
-
});
|
|
983
|
-
}
|
|
984
|
-
else {
|
|
985
|
-
elements.push({
|
|
986
|
-
tag: 'markdown',
|
|
987
|
-
content: `<font color='grey'>${t('card.relay.hint_pick_first', undefined, locale)}</font>`,
|
|
988
|
-
});
|
|
989
|
-
}
|
|
990
|
-
return JSON.stringify(wrapCard(elements, locale));
|
|
991
|
-
}
|
|
992
|
-
function wrapCard(elements, locale) {
|
|
993
|
-
return {
|
|
994
|
-
schema: '2.0',
|
|
995
|
-
config: { update_multi: true },
|
|
996
|
-
header: {
|
|
997
|
-
title: { tag: 'plain_text', content: t('card.relay.title', undefined, locale) },
|
|
998
|
-
template: 'blue',
|
|
999
|
-
},
|
|
1000
|
-
body: { direction: 'vertical', elements },
|
|
1001
|
-
};
|
|
1002
|
-
}
|
|
1003
573
|
export function buildAdoptSelectCard(sessions, rootMessageId, locale) {
|
|
1004
574
|
const unknownUptime = t('card.adopt.uptime_unknown', undefined, locale);
|
|
1005
575
|
const options = sessions.map((s) => {
|