agim-cli 1.0.1
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/CHANGELOG.md +1234 -0
- package/LICENSE +21 -0
- package/README.md +422 -0
- package/README.zh-CN.md +414 -0
- package/dist/cli-ui/cmd-handlers.d.ts +11 -0
- package/dist/cli-ui/cmd-handlers.d.ts.map +1 -0
- package/dist/cli-ui/cmd-handlers.js +240 -0
- package/dist/cli-ui/cmd-handlers.js.map +1 -0
- package/dist/cli-ui/config-wizard.d.ts +3 -0
- package/dist/cli-ui/config-wizard.d.ts.map +1 -0
- package/dist/cli-ui/config-wizard.js +851 -0
- package/dist/cli-ui/config-wizard.js.map +1 -0
- package/dist/cli-ui/entry-menu.d.ts +28 -0
- package/dist/cli-ui/entry-menu.d.ts.map +1 -0
- package/dist/cli-ui/entry-menu.js +50 -0
- package/dist/cli-ui/entry-menu.js.map +1 -0
- package/dist/cli-ui/env-file.d.ts +35 -0
- package/dist/cli-ui/env-file.d.ts.map +1 -0
- package/dist/cli-ui/env-file.js +163 -0
- package/dist/cli-ui/env-file.js.map +1 -0
- package/dist/cli-ui/i18n.d.ts +204 -0
- package/dist/cli-ui/i18n.d.ts.map +1 -0
- package/dist/cli-ui/i18n.js +455 -0
- package/dist/cli-ui/i18n.js.map +1 -0
- package/dist/cli-ui/lang-picker.d.ts +10 -0
- package/dist/cli-ui/lang-picker.d.ts.map +1 -0
- package/dist/cli-ui/lang-picker.js +33 -0
- package/dist/cli-ui/lang-picker.js.map +1 -0
- package/dist/cli-ui/paths.d.ts +4 -0
- package/dist/cli-ui/paths.d.ts.map +1 -0
- package/dist/cli-ui/paths.js +11 -0
- package/dist/cli-ui/paths.js.map +1 -0
- package/dist/cli-ui/prompts.d.ts +65 -0
- package/dist/cli-ui/prompts.d.ts.map +1 -0
- package/dist/cli-ui/prompts.js +125 -0
- package/dist/cli-ui/prompts.js.map +1 -0
- package/dist/cli-ui/service.d.ts +41 -0
- package/dist/cli-ui/service.d.ts.map +1 -0
- package/dist/cli-ui/service.js +241 -0
- package/dist/cli-ui/service.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1143 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/acp-server.d.ts +8 -0
- package/dist/core/acp-server.d.ts.map +1 -0
- package/dist/core/acp-server.js +266 -0
- package/dist/core/acp-server.js.map +1 -0
- package/dist/core/agent-base.d.ts +94 -0
- package/dist/core/agent-base.d.ts.map +1 -0
- package/dist/core/agent-base.js +373 -0
- package/dist/core/agent-base.js.map +1 -0
- package/dist/core/agent-cwd.d.ts +48 -0
- package/dist/core/agent-cwd.d.ts.map +1 -0
- package/dist/core/agent-cwd.js +181 -0
- package/dist/core/agent-cwd.js.map +1 -0
- package/dist/core/agent-helper.d.ts +65 -0
- package/dist/core/agent-helper.d.ts.map +1 -0
- package/dist/core/agent-helper.js +150 -0
- package/dist/core/agent-helper.js.map +1 -0
- package/dist/core/agim-paths.d.ts +10 -0
- package/dist/core/agim-paths.d.ts.map +1 -0
- package/dist/core/agim-paths.js +64 -0
- package/dist/core/agim-paths.js.map +1 -0
- package/dist/core/approval-bus.d.ts +300 -0
- package/dist/core/approval-bus.d.ts.map +1 -0
- package/dist/core/approval-bus.js +990 -0
- package/dist/core/approval-bus.js.map +1 -0
- package/dist/core/approval-router.d.ts +101 -0
- package/dist/core/approval-router.d.ts.map +1 -0
- package/dist/core/approval-router.js +540 -0
- package/dist/core/approval-router.js.map +1 -0
- package/dist/core/audit-log.d.ts +55 -0
- package/dist/core/audit-log.d.ts.map +1 -0
- package/dist/core/audit-log.js +203 -0
- package/dist/core/audit-log.js.map +1 -0
- package/dist/core/bgjob-reader.d.ts +65 -0
- package/dist/core/bgjob-reader.d.ts.map +1 -0
- package/dist/core/bgjob-reader.js +212 -0
- package/dist/core/bgjob-reader.js.map +1 -0
- package/dist/core/circuit-breaker.d.ts +37 -0
- package/dist/core/circuit-breaker.d.ts.map +1 -0
- package/dist/core/circuit-breaker.js +115 -0
- package/dist/core/circuit-breaker.js.map +1 -0
- package/dist/core/commands/agent.d.ts +4 -0
- package/dist/core/commands/agent.d.ts.map +1 -0
- package/dist/core/commands/agent.js +40 -0
- package/dist/core/commands/agent.js.map +1 -0
- package/dist/core/commands/approval.d.ts +3 -0
- package/dist/core/commands/approval.d.ts.map +1 -0
- package/dist/core/commands/approval.js +85 -0
- package/dist/core/commands/approval.js.map +1 -0
- package/dist/core/commands/audit.d.ts +3 -0
- package/dist/core/commands/audit.d.ts.map +1 -0
- package/dist/core/commands/audit.js +84 -0
- package/dist/core/commands/audit.js.map +1 -0
- package/dist/core/commands/builtin.d.ts +3 -0
- package/dist/core/commands/builtin.d.ts.map +1 -0
- package/dist/core/commands/builtin.js +304 -0
- package/dist/core/commands/builtin.js.map +1 -0
- package/dist/core/commands/cron.d.ts +3 -0
- package/dist/core/commands/cron.d.ts.map +1 -0
- package/dist/core/commands/cron.js +128 -0
- package/dist/core/commands/cron.js.map +1 -0
- package/dist/core/commands/job.d.ts +3 -0
- package/dist/core/commands/job.d.ts.map +1 -0
- package/dist/core/commands/job.js +195 -0
- package/dist/core/commands/job.js.map +1 -0
- package/dist/core/commands/memo.d.ts +3 -0
- package/dist/core/commands/memo.d.ts.map +1 -0
- package/dist/core/commands/memo.js +151 -0
- package/dist/core/commands/memo.js.map +1 -0
- package/dist/core/commands/model.d.ts +9 -0
- package/dist/core/commands/model.d.ts.map +1 -0
- package/dist/core/commands/model.js +183 -0
- package/dist/core/commands/model.js.map +1 -0
- package/dist/core/commands/plan.d.ts +3 -0
- package/dist/core/commands/plan.d.ts.map +1 -0
- package/dist/core/commands/plan.js +75 -0
- package/dist/core/commands/plan.js.map +1 -0
- package/dist/core/commands/remind.d.ts +3 -0
- package/dist/core/commands/remind.d.ts.map +1 -0
- package/dist/core/commands/remind.js +271 -0
- package/dist/core/commands/remind.js.map +1 -0
- package/dist/core/commands/router.d.ts +3 -0
- package/dist/core/commands/router.d.ts.map +1 -0
- package/dist/core/commands/router.js +71 -0
- package/dist/core/commands/router.js.map +1 -0
- package/dist/core/commands/sessions.d.ts +3 -0
- package/dist/core/commands/sessions.d.ts.map +1 -0
- package/dist/core/commands/sessions.js +88 -0
- package/dist/core/commands/sessions.js.map +1 -0
- package/dist/core/commands/stats.d.ts +3 -0
- package/dist/core/commands/stats.d.ts.map +1 -0
- package/dist/core/commands/stats.js +73 -0
- package/dist/core/commands/stats.js.map +1 -0
- package/dist/core/commands/think.d.ts +3 -0
- package/dist/core/commands/think.d.ts.map +1 -0
- package/dist/core/commands/think.js +28 -0
- package/dist/core/commands/think.js.map +1 -0
- package/dist/core/commands/workspaces.d.ts +3 -0
- package/dist/core/commands/workspaces.d.ts.map +1 -0
- package/dist/core/commands/workspaces.js +47 -0
- package/dist/core/commands/workspaces.js.map +1 -0
- package/dist/core/config-schema.d.ts +60 -0
- package/dist/core/config-schema.d.ts.map +1 -0
- package/dist/core/config-schema.js +75 -0
- package/dist/core/config-schema.js.map +1 -0
- package/dist/core/coord-systems.d.ts +65 -0
- package/dist/core/coord-systems.d.ts.map +1 -0
- package/dist/core/coord-systems.js +229 -0
- package/dist/core/coord-systems.js.map +1 -0
- package/dist/core/cron.d.ts +29 -0
- package/dist/core/cron.d.ts.map +1 -0
- package/dist/core/cron.js +184 -0
- package/dist/core/cron.js.map +1 -0
- package/dist/core/event-bus.d.ts +80 -0
- package/dist/core/event-bus.d.ts.map +1 -0
- package/dist/core/event-bus.js +62 -0
- package/dist/core/event-bus.js.map +1 -0
- package/dist/core/intent-llm.d.ts +27 -0
- package/dist/core/intent-llm.d.ts.map +1 -0
- package/dist/core/intent-llm.js +170 -0
- package/dist/core/intent-llm.js.map +1 -0
- package/dist/core/intent.d.ts +12 -0
- package/dist/core/intent.d.ts.map +1 -0
- package/dist/core/intent.js +187 -0
- package/dist/core/intent.js.map +1 -0
- package/dist/core/job-board.d.ts +82 -0
- package/dist/core/job-board.d.ts.map +1 -0
- package/dist/core/job-board.js +379 -0
- package/dist/core/job-board.js.map +1 -0
- package/dist/core/location-context.d.ts +32 -0
- package/dist/core/location-context.d.ts.map +1 -0
- package/dist/core/location-context.js +69 -0
- package/dist/core/location-context.js.map +1 -0
- package/dist/core/location-token.d.ts +57 -0
- package/dist/core/location-token.d.ts.map +1 -0
- package/dist/core/location-token.js +128 -0
- package/dist/core/location-token.js.map +1 -0
- package/dist/core/logger.d.ts +6 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +54 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/memo-rpc.d.ts +13 -0
- package/dist/core/memo-rpc.d.ts.map +1 -0
- package/dist/core/memo-rpc.js +288 -0
- package/dist/core/memo-rpc.js.map +1 -0
- package/dist/core/memos.d.ts +163 -0
- package/dist/core/memos.d.ts.map +1 -0
- package/dist/core/memos.js +502 -0
- package/dist/core/memos.js.map +1 -0
- package/dist/core/metrics.d.ts +55 -0
- package/dist/core/metrics.d.ts.map +1 -0
- package/dist/core/metrics.js +291 -0
- package/dist/core/metrics.js.map +1 -0
- package/dist/core/onboarding.d.ts +99 -0
- package/dist/core/onboarding.d.ts.map +1 -0
- package/dist/core/onboarding.js +426 -0
- package/dist/core/onboarding.js.map +1 -0
- package/dist/core/pending-reminder.d.ts +25 -0
- package/dist/core/pending-reminder.d.ts.map +1 -0
- package/dist/core/pending-reminder.js +53 -0
- package/dist/core/pending-reminder.js.map +1 -0
- package/dist/core/rate-limiter.d.ts +44 -0
- package/dist/core/rate-limiter.d.ts.map +1 -0
- package/dist/core/rate-limiter.js +115 -0
- package/dist/core/rate-limiter.js.map +1 -0
- package/dist/core/registry.d.ts +32 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +126 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/remind-intent.d.ts +25 -0
- package/dist/core/remind-intent.d.ts.map +1 -0
- package/dist/core/remind-intent.js +196 -0
- package/dist/core/remind-intent.js.map +1 -0
- package/dist/core/reminder-rpc.d.ts +17 -0
- package/dist/core/reminder-rpc.d.ts.map +1 -0
- package/dist/core/reminder-rpc.js +169 -0
- package/dist/core/reminder-rpc.js.map +1 -0
- package/dist/core/reminders.d.ts +159 -0
- package/dist/core/reminders.d.ts.map +1 -0
- package/dist/core/reminders.js +977 -0
- package/dist/core/reminders.js.map +1 -0
- package/dist/core/router.d.ts +55 -0
- package/dist/core/router.d.ts.map +1 -0
- package/dist/core/router.js +497 -0
- package/dist/core/router.js.map +1 -0
- package/dist/core/schedule.d.ts +65 -0
- package/dist/core/schedule.d.ts.map +1 -0
- package/dist/core/schedule.js +323 -0
- package/dist/core/schedule.js.map +1 -0
- package/dist/core/session.d.ts +182 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +807 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/sqlite-helper.d.ts +37 -0
- package/dist/core/sqlite-helper.d.ts.map +1 -0
- package/dist/core/sqlite-helper.js +79 -0
- package/dist/core/sqlite-helper.js.map +1 -0
- package/dist/core/transcribe.d.ts +25 -0
- package/dist/core/transcribe.d.ts.map +1 -0
- package/dist/core/transcribe.js +217 -0
- package/dist/core/transcribe.js.map +1 -0
- package/dist/core/types.d.ts +360 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/workspace.d.ts +67 -0
- package/dist/core/workspace.d.ts.map +1 -0
- package/dist/core/workspace.js +113 -0
- package/dist/core/workspace.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/agents/acp/acp-adapter.d.ts +16 -0
- package/dist/plugins/agents/acp/acp-adapter.d.ts.map +1 -0
- package/dist/plugins/agents/acp/acp-adapter.js +49 -0
- package/dist/plugins/agents/acp/acp-adapter.js.map +1 -0
- package/dist/plugins/agents/acp/acp-client.d.ts +32 -0
- package/dist/plugins/agents/acp/acp-client.d.ts.map +1 -0
- package/dist/plugins/agents/acp/acp-client.js +177 -0
- package/dist/plugins/agents/acp/acp-client.js.map +1 -0
- package/dist/plugins/agents/acp/discovery.d.ts +19 -0
- package/dist/plugins/agents/acp/discovery.d.ts.map +1 -0
- package/dist/plugins/agents/acp/discovery.js +111 -0
- package/dist/plugins/agents/acp/discovery.js.map +1 -0
- package/dist/plugins/agents/acp/index.d.ts +4 -0
- package/dist/plugins/agents/acp/index.d.ts.map +1 -0
- package/dist/plugins/agents/acp/index.js +4 -0
- package/dist/plugins/agents/acp/index.js.map +1 -0
- package/dist/plugins/agents/acp/types.d.ts +62 -0
- package/dist/plugins/agents/acp/types.d.ts.map +1 -0
- package/dist/plugins/agents/acp/types.js +5 -0
- package/dist/plugins/agents/acp/types.js.map +1 -0
- package/dist/plugins/agents/claude-code/index.d.ts +25 -0
- package/dist/plugins/agents/claude-code/index.d.ts.map +1 -0
- package/dist/plugins/agents/claude-code/index.js +184 -0
- package/dist/plugins/agents/claude-code/index.js.map +1 -0
- package/dist/plugins/agents/claude-code/mcp-approval-server.d.ts +59 -0
- package/dist/plugins/agents/claude-code/mcp-approval-server.d.ts.map +1 -0
- package/dist/plugins/agents/claude-code/mcp-approval-server.js +645 -0
- package/dist/plugins/agents/claude-code/mcp-approval-server.js.map +1 -0
- package/dist/plugins/agents/codex/build-mcp-cli-args.d.ts +28 -0
- package/dist/plugins/agents/codex/build-mcp-cli-args.d.ts.map +1 -0
- package/dist/plugins/agents/codex/build-mcp-cli-args.js +74 -0
- package/dist/plugins/agents/codex/build-mcp-cli-args.js.map +1 -0
- package/dist/plugins/agents/codex/index.d.ts +53 -0
- package/dist/plugins/agents/codex/index.d.ts.map +1 -0
- package/dist/plugins/agents/codex/index.js +341 -0
- package/dist/plugins/agents/codex/index.js.map +1 -0
- package/dist/plugins/agents/copilot/index.d.ts +35 -0
- package/dist/plugins/agents/copilot/index.d.ts.map +1 -0
- package/dist/plugins/agents/copilot/index.js +182 -0
- package/dist/plugins/agents/copilot/index.js.map +1 -0
- package/dist/plugins/agents/opencode/ensure-mcp-config.d.ts +11 -0
- package/dist/plugins/agents/opencode/ensure-mcp-config.d.ts.map +1 -0
- package/dist/plugins/agents/opencode/ensure-mcp-config.js +100 -0
- package/dist/plugins/agents/opencode/ensure-mcp-config.js.map +1 -0
- package/dist/plugins/agents/opencode/index.d.ts +5 -0
- package/dist/plugins/agents/opencode/index.d.ts.map +1 -0
- package/dist/plugins/agents/opencode/index.js +30 -0
- package/dist/plugins/agents/opencode/index.js.map +1 -0
- package/dist/plugins/agents/opencode/opencode-http-adapter.d.ts +166 -0
- package/dist/plugins/agents/opencode/opencode-http-adapter.d.ts.map +1 -0
- package/dist/plugins/agents/opencode/opencode-http-adapter.js +682 -0
- package/dist/plugins/agents/opencode/opencode-http-adapter.js.map +1 -0
- package/dist/plugins/agents/opencode/opencode-stdio-adapter.d.ts +32 -0
- package/dist/plugins/agents/opencode/opencode-stdio-adapter.d.ts.map +1 -0
- package/dist/plugins/agents/opencode/opencode-stdio-adapter.js +137 -0
- package/dist/plugins/agents/opencode/opencode-stdio-adapter.js.map +1 -0
- package/dist/plugins/agents/opencode/serve-manager.d.ts +27 -0
- package/dist/plugins/agents/opencode/serve-manager.d.ts.map +1 -0
- package/dist/plugins/agents/opencode/serve-manager.js +194 -0
- package/dist/plugins/agents/opencode/serve-manager.js.map +1 -0
- package/dist/plugins/messengers/dingtalk/dingtalk-adapter.d.ts +57 -0
- package/dist/plugins/messengers/dingtalk/dingtalk-adapter.d.ts.map +1 -0
- package/dist/plugins/messengers/dingtalk/dingtalk-adapter.js +409 -0
- package/dist/plugins/messengers/dingtalk/dingtalk-adapter.js.map +1 -0
- package/dist/plugins/messengers/dingtalk/dingtalk-client.d.ts +48 -0
- package/dist/plugins/messengers/dingtalk/dingtalk-client.d.ts.map +1 -0
- package/dist/plugins/messengers/dingtalk/dingtalk-client.js +236 -0
- package/dist/plugins/messengers/dingtalk/dingtalk-client.js.map +1 -0
- package/dist/plugins/messengers/dingtalk/index.d.ts +3 -0
- package/dist/plugins/messengers/dingtalk/index.d.ts.map +1 -0
- package/dist/plugins/messengers/dingtalk/index.js +3 -0
- package/dist/plugins/messengers/dingtalk/index.js.map +1 -0
- package/dist/plugins/messengers/dingtalk/link-coords.d.ts +23 -0
- package/dist/plugins/messengers/dingtalk/link-coords.d.ts.map +1 -0
- package/dist/plugins/messengers/dingtalk/link-coords.js +89 -0
- package/dist/plugins/messengers/dingtalk/link-coords.js.map +1 -0
- package/dist/plugins/messengers/dingtalk/media-store.d.ts +16 -0
- package/dist/plugins/messengers/dingtalk/media-store.d.ts.map +1 -0
- package/dist/plugins/messengers/dingtalk/media-store.js +77 -0
- package/dist/plugins/messengers/dingtalk/media-store.js.map +1 -0
- package/dist/plugins/messengers/dingtalk/types.d.ts +82 -0
- package/dist/plugins/messengers/dingtalk/types.d.ts.map +1 -0
- package/dist/plugins/messengers/dingtalk/types.js +14 -0
- package/dist/plugins/messengers/dingtalk/types.js.map +1 -0
- package/dist/plugins/messengers/discord/discord-adapter.d.ts +21 -0
- package/dist/plugins/messengers/discord/discord-adapter.d.ts.map +1 -0
- package/dist/plugins/messengers/discord/discord-adapter.js +238 -0
- package/dist/plugins/messengers/discord/discord-adapter.js.map +1 -0
- package/dist/plugins/messengers/discord/index.d.ts +4 -0
- package/dist/plugins/messengers/discord/index.d.ts.map +1 -0
- package/dist/plugins/messengers/discord/index.js +4 -0
- package/dist/plugins/messengers/discord/index.js.map +1 -0
- package/dist/plugins/messengers/discord/markdown-to-discord.d.ts +11 -0
- package/dist/plugins/messengers/discord/markdown-to-discord.d.ts.map +1 -0
- package/dist/plugins/messengers/discord/markdown-to-discord.js +59 -0
- package/dist/plugins/messengers/discord/markdown-to-discord.js.map +1 -0
- package/dist/plugins/messengers/discord/types.d.ts +9 -0
- package/dist/plugins/messengers/discord/types.d.ts.map +1 -0
- package/dist/plugins/messengers/discord/types.js +3 -0
- package/dist/plugins/messengers/discord/types.js.map +1 -0
- package/dist/plugins/messengers/email/email-adapter.d.ts +33 -0
- package/dist/plugins/messengers/email/email-adapter.d.ts.map +1 -0
- package/dist/plugins/messengers/email/email-adapter.js +137 -0
- package/dist/plugins/messengers/email/email-adapter.js.map +1 -0
- package/dist/plugins/messengers/feishu/card-builder.d.ts +23 -0
- package/dist/plugins/messengers/feishu/card-builder.d.ts.map +1 -0
- package/dist/plugins/messengers/feishu/card-builder.js +89 -0
- package/dist/plugins/messengers/feishu/card-builder.js.map +1 -0
- package/dist/plugins/messengers/feishu/feishu-adapter.d.ts +23 -0
- package/dist/plugins/messengers/feishu/feishu-adapter.d.ts.map +1 -0
- package/dist/plugins/messengers/feishu/feishu-adapter.js +250 -0
- package/dist/plugins/messengers/feishu/feishu-adapter.js.map +1 -0
- package/dist/plugins/messengers/feishu/feishu-client.d.ts +43 -0
- package/dist/plugins/messengers/feishu/feishu-client.d.ts.map +1 -0
- package/dist/plugins/messengers/feishu/feishu-client.js +118 -0
- package/dist/plugins/messengers/feishu/feishu-client.js.map +1 -0
- package/dist/plugins/messengers/feishu/index.d.ts +4 -0
- package/dist/plugins/messengers/feishu/index.d.ts.map +1 -0
- package/dist/plugins/messengers/feishu/index.js +4 -0
- package/dist/plugins/messengers/feishu/index.js.map +1 -0
- package/dist/plugins/messengers/feishu/types.d.ts +113 -0
- package/dist/plugins/messengers/feishu/types.d.ts.map +1 -0
- package/dist/plugins/messengers/feishu/types.js +4 -0
- package/dist/plugins/messengers/feishu/types.js.map +1 -0
- package/dist/plugins/messengers/telegram/index.d.ts +4 -0
- package/dist/plugins/messengers/telegram/index.d.ts.map +1 -0
- package/dist/plugins/messengers/telegram/index.js +4 -0
- package/dist/plugins/messengers/telegram/index.js.map +1 -0
- package/dist/plugins/messengers/telegram/markdown-to-html.d.ts +5 -0
- package/dist/plugins/messengers/telegram/markdown-to-html.d.ts.map +1 -0
- package/dist/plugins/messengers/telegram/markdown-to-html.js +186 -0
- package/dist/plugins/messengers/telegram/markdown-to-html.js.map +1 -0
- package/dist/plugins/messengers/telegram/media-download.d.ts +59 -0
- package/dist/plugins/messengers/telegram/media-download.d.ts.map +1 -0
- package/dist/plugins/messengers/telegram/media-download.js +228 -0
- package/dist/plugins/messengers/telegram/media-download.js.map +1 -0
- package/dist/plugins/messengers/telegram/telegram-adapter.d.ts +77 -0
- package/dist/plugins/messengers/telegram/telegram-adapter.d.ts.map +1 -0
- package/dist/plugins/messengers/telegram/telegram-adapter.js +880 -0
- package/dist/plugins/messengers/telegram/telegram-adapter.js.map +1 -0
- package/dist/plugins/messengers/telegram/types.d.ts +47 -0
- package/dist/plugins/messengers/telegram/types.d.ts.map +1 -0
- package/dist/plugins/messengers/telegram/types.js +3 -0
- package/dist/plugins/messengers/telegram/types.js.map +1 -0
- package/dist/plugins/messengers/wechat/context-store.d.ts +18 -0
- package/dist/plugins/messengers/wechat/context-store.d.ts.map +1 -0
- package/dist/plugins/messengers/wechat/context-store.js +105 -0
- package/dist/plugins/messengers/wechat/context-store.js.map +1 -0
- package/dist/plugins/messengers/wechat/ilink-adapter.d.ts +71 -0
- package/dist/plugins/messengers/wechat/ilink-adapter.d.ts.map +1 -0
- package/dist/plugins/messengers/wechat/ilink-adapter.js +664 -0
- package/dist/plugins/messengers/wechat/ilink-adapter.js.map +1 -0
- package/dist/plugins/messengers/wechat/ilink-client.d.ts +75 -0
- package/dist/plugins/messengers/wechat/ilink-client.d.ts.map +1 -0
- package/dist/plugins/messengers/wechat/ilink-client.js +331 -0
- package/dist/plugins/messengers/wechat/ilink-client.js.map +1 -0
- package/dist/plugins/messengers/wechat/ilink-types.d.ts +181 -0
- package/dist/plugins/messengers/wechat/ilink-types.d.ts.map +1 -0
- package/dist/plugins/messengers/wechat/ilink-types.js +22 -0
- package/dist/plugins/messengers/wechat/ilink-types.js.map +1 -0
- package/dist/plugins/messengers/wechat/media-download.d.ts +32 -0
- package/dist/plugins/messengers/wechat/media-download.d.ts.map +1 -0
- package/dist/plugins/messengers/wechat/media-download.js +78 -0
- package/dist/plugins/messengers/wechat/media-download.js.map +1 -0
- package/dist/scripts/migrate-gcj02-to-wgs84.d.ts +3 -0
- package/dist/scripts/migrate-gcj02-to-wgs84.d.ts.map +1 -0
- package/dist/scripts/migrate-gcj02-to-wgs84.js +52 -0
- package/dist/scripts/migrate-gcj02-to-wgs84.js.map +1 -0
- package/dist/utils/backoff.d.ts +35 -0
- package/dist/utils/backoff.d.ts.map +1 -0
- package/dist/utils/backoff.js +59 -0
- package/dist/utils/backoff.js.map +1 -0
- package/dist/utils/cross-platform.d.ts +26 -0
- package/dist/utils/cross-platform.d.ts.map +1 -0
- package/dist/utils/cross-platform.js +58 -0
- package/dist/utils/cross-platform.js.map +1 -0
- package/dist/utils/message-split.d.ts +14 -0
- package/dist/utils/message-split.d.ts.map +1 -0
- package/dist/utils/message-split.js +65 -0
- package/dist/utils/message-split.js.map +1 -0
- package/dist/utils/safe-equal.d.ts +2 -0
- package/dist/utils/safe-equal.d.ts.map +1 -0
- package/dist/utils/safe-equal.js +11 -0
- package/dist/utils/safe-equal.js.map +1 -0
- package/dist/web/public/_app.js +196 -0
- package/dist/web/public/index.html +936 -0
- package/dist/web/public/loc.html +305 -0
- package/dist/web/public/login.html +106 -0
- package/dist/web/public/memos.html +271 -0
- package/dist/web/public/reminders.html +234 -0
- package/dist/web/public/settings.html +1355 -0
- package/dist/web/public/tasks.html +1835 -0
- package/dist/web/server.d.ts +12 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +2399 -0
- package/dist/web/server.js.map +1 -0
- package/package.json +92 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
// DingTalk Bot client — wraps the official `dingtalk-stream` SDK for
|
|
2
|
+
// inbound messages (WebSocket Stream mode) and uses DingTalk's REST
|
|
3
|
+
// OpenAPI for outbound messages.
|
|
4
|
+
//
|
|
5
|
+
// Architecture matches the Feishu client:
|
|
6
|
+
// * Inbound goes through TOPIC_ROBOT callback registered with DWClient
|
|
7
|
+
// * Outbound uses access-token-authed POST to api.dingtalk.com
|
|
8
|
+
// * The SDK manages WebSocket reconnect (1s-60s exponential), heartbeat,
|
|
9
|
+
// and access-token refresh — we just call getAccessToken() before
|
|
10
|
+
// each OpenAPI send and the SDK caches/refreshes as needed.
|
|
11
|
+
//
|
|
12
|
+
// Why not sessionWebhook (the temporary 30s URL each inbound message
|
|
13
|
+
// carries)? Because im-hub's primary use case is multi-minute agent
|
|
14
|
+
// runs and the sessionWebhook is always stale by the time the agent
|
|
15
|
+
// finishes. OpenAPI works for any send regardless of elapsed time.
|
|
16
|
+
import { DWClient, TOPIC_ROBOT } from 'dingtalk-stream';
|
|
17
|
+
import { logger as rootLogger } from '../../../core/logger.js';
|
|
18
|
+
const log = rootLogger.child({ component: 'dingtalk-client' });
|
|
19
|
+
const API_BASE = 'https://api.dingtalk.com';
|
|
20
|
+
const URL_1V1 = `${API_BASE}/v1.0/robot/oToMessages/batchSend`;
|
|
21
|
+
const URL_GROUP = `${API_BASE}/v1.0/robot/groupMessages/send`;
|
|
22
|
+
const URL_MEDIA_DL = `${API_BASE}/v1.0/robot/messageFiles/download`;
|
|
23
|
+
/** Hard cap on a single inbound media download. DingTalk caps voice at
|
|
24
|
+
* ~2 MB and images at ~10 MB on the consumer client; 20 MB gives us
|
|
25
|
+
* headroom for files without letting a runaway upload fill the disk. */
|
|
26
|
+
const MAX_MEDIA_BYTES = 20 * 1024 * 1024;
|
|
27
|
+
function parseThreadId(threadId) {
|
|
28
|
+
if (threadId.startsWith('user:')) {
|
|
29
|
+
return { kind: 'user', id: threadId.slice('user:'.length) };
|
|
30
|
+
}
|
|
31
|
+
if (threadId.startsWith('group:')) {
|
|
32
|
+
return { kind: 'group', id: threadId.slice('group:'.length) };
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
export class DingTalkClient {
|
|
37
|
+
dw;
|
|
38
|
+
config;
|
|
39
|
+
messageHandler;
|
|
40
|
+
/** Cached robotCode from the most recent inbound (== clientId for
|
|
41
|
+
* stream-mode internal apps, but we read it from messages so we're
|
|
42
|
+
* tolerant of multi-bot setups in one app). */
|
|
43
|
+
lastSeenRobotCode;
|
|
44
|
+
constructor(config) {
|
|
45
|
+
this.config = config;
|
|
46
|
+
this.lastSeenRobotCode = config.clientId; // sensible default
|
|
47
|
+
this.dw = new DWClient({
|
|
48
|
+
clientId: config.clientId,
|
|
49
|
+
clientSecret: config.clientSecret,
|
|
50
|
+
// DWClient defaults: autoReconnect=true, debug=false, keepAlive=false.
|
|
51
|
+
// Reconnect strategy is 1s → 60s exponential, heartbeat 8s — already
|
|
52
|
+
// matches our needs.
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
onMessage(handler) {
|
|
56
|
+
this.messageHandler = handler;
|
|
57
|
+
}
|
|
58
|
+
async start() {
|
|
59
|
+
this.dw.registerCallbackListener(TOPIC_ROBOT, async (res) => {
|
|
60
|
+
let msg;
|
|
61
|
+
try {
|
|
62
|
+
msg = JSON.parse(res.data);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
log.warn({ err: err instanceof Error ? err.message : String(err), data: res.data?.slice?.(0, 200) }, 'failed to parse TOPIC_ROBOT data');
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (msg.robotCode)
|
|
69
|
+
this.lastSeenRobotCode = msg.robotCode;
|
|
70
|
+
if (this.messageHandler) {
|
|
71
|
+
try {
|
|
72
|
+
await this.messageHandler(msg);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
log.error({ err: err instanceof Error ? err.message : String(err) }, 'message handler threw');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// ack so the gateway doesn't redeliver. We're swallowing the
|
|
79
|
+
// response payload here intentionally — DingTalk gives 60s before
|
|
80
|
+
// it retries; our agent flow may exceed that and that's fine,
|
|
81
|
+
// the user gets the eventual reply via OpenAPI.
|
|
82
|
+
this.dw.socketCallBackResponse(res.headers.messageId, { status: 'SUCCESS' });
|
|
83
|
+
});
|
|
84
|
+
await this.dw.connect();
|
|
85
|
+
log.info({ event: 'dingtalk.client.connected' }, 'WebSocket connected');
|
|
86
|
+
}
|
|
87
|
+
async stop() {
|
|
88
|
+
try {
|
|
89
|
+
this.dw.disconnect();
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
log.warn({ err: err instanceof Error ? err.message : String(err) }, 'error during dingtalk disconnect (ignored)');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Send a plain-text message to a thread we previously received from
|
|
96
|
+
* (encoded as `user:<staffId>` for 1:1, `group:<convId>` for groups).
|
|
97
|
+
* Uses OpenAPI under the bot's access token. */
|
|
98
|
+
async sendMessage(threadId, text) {
|
|
99
|
+
await this.sendTemplated(threadId, 'sampleText', { content: text });
|
|
100
|
+
}
|
|
101
|
+
/** Send a markdown-formatted message. DingTalk's `sampleMarkdown` only
|
|
102
|
+
* takes `title` + `text`; we derive title from the first line so the
|
|
103
|
+
* user sees something meaningful in the notification preview. */
|
|
104
|
+
async sendMarkdown(threadId, text, title) {
|
|
105
|
+
const firstLine = text.split('\n', 1)[0]?.replace(/^[#*\-\s>]+/, '').slice(0, 32) || 'Message';
|
|
106
|
+
await this.sendTemplated(threadId, 'sampleMarkdown', {
|
|
107
|
+
title: title ?? firstLine,
|
|
108
|
+
text,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/** Download an inbound image / voice / file message's binary payload.
|
|
112
|
+
*
|
|
113
|
+
* DingTalk hands the bot a short-lived `downloadCode` in each media
|
|
114
|
+
* inbound; we trade it (plus our robotCode) for a presigned downloadUrl
|
|
115
|
+
* on alibaba CDN, then GET that URL and return the bytes.
|
|
116
|
+
*
|
|
117
|
+
* Returns null on any error (caller surfaces a "[download failed:...]"
|
|
118
|
+
* marker instead of silently dropping the user's message). MAX cap is
|
|
119
|
+
* enforced; oversize payloads throw before allocating the buffer.
|
|
120
|
+
*
|
|
121
|
+
* Reference: POST /v1.0/robot/messageFiles/download
|
|
122
|
+
* { downloadCode, robotCode }
|
|
123
|
+
* header: x-acs-dingtalk-access-token
|
|
124
|
+
* response: { downloadUrl } (sometimes nested under .data)
|
|
125
|
+
*/
|
|
126
|
+
async downloadMessageFile(downloadCode) {
|
|
127
|
+
if (!downloadCode)
|
|
128
|
+
return null;
|
|
129
|
+
let accessToken;
|
|
130
|
+
try {
|
|
131
|
+
accessToken = await this.dw.getAccessToken();
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
log.warn({ err: err instanceof Error ? err.message : String(err) }, 'dingtalk: getAccessToken failed before media download');
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
if (!accessToken)
|
|
138
|
+
return null;
|
|
139
|
+
// Step 1: exchange downloadCode for a CDN URL.
|
|
140
|
+
let downloadUrl = null;
|
|
141
|
+
try {
|
|
142
|
+
const res = await fetch(URL_MEDIA_DL, {
|
|
143
|
+
method: 'POST',
|
|
144
|
+
headers: {
|
|
145
|
+
'Content-Type': 'application/json',
|
|
146
|
+
'x-acs-dingtalk-access-token': String(accessToken),
|
|
147
|
+
},
|
|
148
|
+
body: JSON.stringify({ downloadCode, robotCode: this.lastSeenRobotCode }),
|
|
149
|
+
});
|
|
150
|
+
if (!res.ok) {
|
|
151
|
+
const txt = await res.text().catch(() => '');
|
|
152
|
+
log.warn({
|
|
153
|
+
status: res.status,
|
|
154
|
+
body: txt.slice(0, 200),
|
|
155
|
+
event: 'dingtalk.media.exchange_failed',
|
|
156
|
+
}, 'messageFiles/download API rejected the downloadCode exchange');
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
const payload = await res.json().catch(() => null);
|
|
160
|
+
downloadUrl = payload?.downloadUrl ?? payload?.data?.downloadUrl ?? null;
|
|
161
|
+
if (!downloadUrl) {
|
|
162
|
+
log.warn({ event: 'dingtalk.media.no_url_in_response', payload }, 'exchange succeeded but response had no downloadUrl');
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
log.warn({ err: err instanceof Error ? err.message : String(err) }, 'dingtalk: downloadCode exchange threw');
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
// Step 2: GET the CDN URL. DingTalk's CDN may be on different alibaba
|
|
171
|
+
// hosts depending on the file type / region; no host restriction here.
|
|
172
|
+
try {
|
|
173
|
+
const res = await fetch(downloadUrl);
|
|
174
|
+
if (!res.ok) {
|
|
175
|
+
log.warn({ status: res.status, event: 'dingtalk.media.cdn_get_failed' }, 'CDN refused the download');
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
const contentLength = parseInt(res.headers.get('content-length') ?? '0', 10);
|
|
179
|
+
if (Number.isFinite(contentLength) && contentLength > MAX_MEDIA_BYTES) {
|
|
180
|
+
log.warn({ contentLength, max: MAX_MEDIA_BYTES, event: 'dingtalk.media.too_large' }, 'media exceeds size cap; refusing to download');
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
const arr = await res.arrayBuffer();
|
|
184
|
+
if (arr.byteLength > MAX_MEDIA_BYTES) {
|
|
185
|
+
log.warn({ bytes: arr.byteLength, max: MAX_MEDIA_BYTES, event: 'dingtalk.media.too_large' }, 'media bytes exceed size cap after download');
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
const contentType = res.headers.get('content-type') ?? 'application/octet-stream';
|
|
189
|
+
return { buffer: Buffer.from(arr), contentType };
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
log.warn({ err: err instanceof Error ? err.message : String(err) }, 'dingtalk: CDN GET threw');
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/** Shared POST path. msgKey + msgParam (stringified inner object) is
|
|
197
|
+
* DingTalk's "templated message" convention — covers text, markdown,
|
|
198
|
+
* cards via the same endpoint. */
|
|
199
|
+
async sendTemplated(threadId, msgKey, inner) {
|
|
200
|
+
const target = parseThreadId(threadId);
|
|
201
|
+
if (!target) {
|
|
202
|
+
throw new Error(`dingtalk: unrecognised threadId "${threadId}" (expected user:<id> or group:<id>)`);
|
|
203
|
+
}
|
|
204
|
+
const accessToken = await this.dw.getAccessToken();
|
|
205
|
+
if (!accessToken) {
|
|
206
|
+
throw new Error('dingtalk: getAccessToken() returned empty token');
|
|
207
|
+
}
|
|
208
|
+
const body = target.kind === 'user'
|
|
209
|
+
? {
|
|
210
|
+
robotCode: this.lastSeenRobotCode,
|
|
211
|
+
userIds: [target.id],
|
|
212
|
+
msgKey,
|
|
213
|
+
msgParam: JSON.stringify(inner),
|
|
214
|
+
}
|
|
215
|
+
: {
|
|
216
|
+
robotCode: this.lastSeenRobotCode,
|
|
217
|
+
openConversationId: target.id,
|
|
218
|
+
msgKey,
|
|
219
|
+
msgParam: JSON.stringify(inner),
|
|
220
|
+
};
|
|
221
|
+
const url = target.kind === 'user' ? URL_1V1 : URL_GROUP;
|
|
222
|
+
const res = await fetch(url, {
|
|
223
|
+
method: 'POST',
|
|
224
|
+
headers: {
|
|
225
|
+
'Content-Type': 'application/json',
|
|
226
|
+
'x-acs-dingtalk-access-token': String(accessToken),
|
|
227
|
+
},
|
|
228
|
+
body: JSON.stringify(body),
|
|
229
|
+
});
|
|
230
|
+
if (!res.ok) {
|
|
231
|
+
const txt = await res.text().catch(() => '');
|
|
232
|
+
throw new Error(`dingtalk: ${target.kind} send failed: ${res.status} ${res.statusText} ${txt.slice(0, 200)}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=dingtalk-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dingtalk-client.js","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/dingtalk-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACxE,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** What coord system the URL's host implies. Drives which conversion
|
|
2
|
+
* `normalizeIncomingCoords` applies on the extracted lat/lng. */
|
|
3
|
+
export type MapUrlSource = 'dingtalk-link-amap' | 'dingtalk-link-tencent' | 'dingtalk-link-baidu' | 'dingtalk-link-unknown';
|
|
4
|
+
/** Best-effort lat/lng extraction from common map URLs.
|
|
5
|
+
*
|
|
6
|
+
* Returns null if the URL doesn't look like a map share. On hit, also
|
|
7
|
+
* returns the `source` so the caller can route through
|
|
8
|
+
* `normalizeIncomingCoords()` for the right coord-system conversion:
|
|
9
|
+
* - Amap / Gaode → GCJ-02
|
|
10
|
+
* - Tencent (map.qq) → GCJ-02
|
|
11
|
+
* - Baidu Maps → BD-09
|
|
12
|
+
* - Anything else → pass-through (we don't guess for unknown hosts)
|
|
13
|
+
*
|
|
14
|
+
* Parses these URL shapes:
|
|
15
|
+
* - Amap: `uri.amap.com/marker?position=lng,lat`
|
|
16
|
+
* - Tencent: `apis.map.qq.com/uri/v1/marker?marker=coord:lat,lng`
|
|
17
|
+
* - Generic: `?location=lat,lng`, `?latlng=lat,lng`, `?lat=…&lng=…` */
|
|
18
|
+
export declare function tryExtractLatLng(url: string): {
|
|
19
|
+
lat: number;
|
|
20
|
+
lng: number;
|
|
21
|
+
source: MapUrlSource;
|
|
22
|
+
} | null;
|
|
23
|
+
//# sourceMappingURL=link-coords.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-coords.d.ts","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/link-coords.ts"],"names":[],"mappings":"AASA;kEACkE;AAClE,MAAM,MAAM,YAAY,GACpB,oBAAoB,GACpB,uBAAuB,GACvB,qBAAqB,GACrB,uBAAuB,CAAA;AAmB3B;;;;;;;;;;;;;yEAayE;AACzE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAAG,IAAI,CA+CvG"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Map-URL coordinate extraction for DingTalk `link` msgtype payloads.
|
|
2
|
+
//
|
|
3
|
+
// Kept in a separate file (rather than inline in dingtalk-adapter.ts)
|
|
4
|
+
// because the adapter pulls in heavy modules — `media-store.ts`,
|
|
5
|
+
// `dingtalk-stream`, the transcribe / location-context machinery — that
|
|
6
|
+
// each can have side effects at import time (env-var capture, file
|
|
7
|
+
// handles, etc.). Tests for the URL classifier should not pay that cost
|
|
8
|
+
// or risk pulling in process-wide state.
|
|
9
|
+
function classifyHost(host) {
|
|
10
|
+
const h = host.toLowerCase();
|
|
11
|
+
if (h.endsWith('.amap.com') || h === 'amap.com' || h.endsWith('.gaode.com') || h === 'gaode.com') {
|
|
12
|
+
return 'dingtalk-link-amap';
|
|
13
|
+
}
|
|
14
|
+
if (h.endsWith('.qq.com') || h === 'qq.com') {
|
|
15
|
+
// Tencent's map endpoints: map.qq.com, apis.map.qq.com, lbs.qq.com.
|
|
16
|
+
// Other *.qq.com URLs (chat / mail) shouldn't legitimately carry
|
|
17
|
+
// map coords; if they do, GCJ-02 is the safe assumption.
|
|
18
|
+
return 'dingtalk-link-tencent';
|
|
19
|
+
}
|
|
20
|
+
if (h.endsWith('.baidu.com') || h === 'baidu.com') {
|
|
21
|
+
return 'dingtalk-link-baidu';
|
|
22
|
+
}
|
|
23
|
+
return 'dingtalk-link-unknown';
|
|
24
|
+
}
|
|
25
|
+
/** Best-effort lat/lng extraction from common map URLs.
|
|
26
|
+
*
|
|
27
|
+
* Returns null if the URL doesn't look like a map share. On hit, also
|
|
28
|
+
* returns the `source` so the caller can route through
|
|
29
|
+
* `normalizeIncomingCoords()` for the right coord-system conversion:
|
|
30
|
+
* - Amap / Gaode → GCJ-02
|
|
31
|
+
* - Tencent (map.qq) → GCJ-02
|
|
32
|
+
* - Baidu Maps → BD-09
|
|
33
|
+
* - Anything else → pass-through (we don't guess for unknown hosts)
|
|
34
|
+
*
|
|
35
|
+
* Parses these URL shapes:
|
|
36
|
+
* - Amap: `uri.amap.com/marker?position=lng,lat`
|
|
37
|
+
* - Tencent: `apis.map.qq.com/uri/v1/marker?marker=coord:lat,lng`
|
|
38
|
+
* - Generic: `?location=lat,lng`, `?latlng=lat,lng`, `?lat=…&lng=…` */
|
|
39
|
+
export function tryExtractLatLng(url) {
|
|
40
|
+
if (!url || typeof url !== 'string')
|
|
41
|
+
return null;
|
|
42
|
+
try {
|
|
43
|
+
const u = new URL(url);
|
|
44
|
+
const source = classifyHost(u.hostname);
|
|
45
|
+
const params = u.searchParams;
|
|
46
|
+
// Amap: ?position=lng,lat
|
|
47
|
+
const position = params.get('position');
|
|
48
|
+
if (position) {
|
|
49
|
+
const [lngStr, latStr] = position.split(',');
|
|
50
|
+
const lng = parseFloat(lngStr);
|
|
51
|
+
const lat = parseFloat(latStr);
|
|
52
|
+
if (Number.isFinite(lat) && Number.isFinite(lng))
|
|
53
|
+
return { lat, lng, source };
|
|
54
|
+
}
|
|
55
|
+
// Tencent: ?marker=coord:lat,lng;title:...
|
|
56
|
+
const marker = params.get('marker');
|
|
57
|
+
if (marker?.startsWith('coord:')) {
|
|
58
|
+
const coord = marker.slice('coord:'.length).split(';')[0];
|
|
59
|
+
const [latStr, lngStr] = coord.split(',');
|
|
60
|
+
const lat = parseFloat(latStr);
|
|
61
|
+
const lng = parseFloat(lngStr);
|
|
62
|
+
if (Number.isFinite(lat) && Number.isFinite(lng))
|
|
63
|
+
return { lat, lng, source };
|
|
64
|
+
}
|
|
65
|
+
// Generic ?location=lat,lng OR ?latlng=lat,lng
|
|
66
|
+
const loc = params.get('location') ?? params.get('latlng');
|
|
67
|
+
if (loc) {
|
|
68
|
+
const [latStr, lngStr] = loc.split(',');
|
|
69
|
+
const lat = parseFloat(latStr);
|
|
70
|
+
const lng = parseFloat(lngStr);
|
|
71
|
+
if (Number.isFinite(lat) && Number.isFinite(lng))
|
|
72
|
+
return { lat, lng, source };
|
|
73
|
+
}
|
|
74
|
+
// Separate ?lat=...&lng=... (or &lon=...)
|
|
75
|
+
const latParam = params.get('lat') ?? params.get('latitude');
|
|
76
|
+
const lngParam = params.get('lng') ?? params.get('lon') ?? params.get('longitude');
|
|
77
|
+
if (latParam && lngParam) {
|
|
78
|
+
const lat = parseFloat(latParam);
|
|
79
|
+
const lng = parseFloat(lngParam);
|
|
80
|
+
if (Number.isFinite(lat) && Number.isFinite(lng))
|
|
81
|
+
return { lat, lng, source };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
/* URL didn't parse — not a map share we can read. */
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=link-coords.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-coords.js","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/link-coords.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,sEAAsE;AACtE,iEAAiE;AACjE,wEAAwE;AACxE,mEAAmE;AACnE,wEAAwE;AACxE,yCAAyC;AAUzC,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;IAC5B,IAAI,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,WAAW,EAAE,CAAC;QACjG,OAAO,oBAAoB,CAAA;IAC7B,CAAC;IACD,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC5C,oEAAoE;QACpE,iEAAiE;QACjE,yDAAyD;QACzD,OAAO,uBAAuB,CAAA;IAChC,CAAC;IACD,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,WAAW,EAAE,CAAC;QAClD,OAAO,qBAAqB,CAAA;IAC9B,CAAC;IACD,OAAO,uBAAuB,CAAA;AAChC,CAAC;AAED;;;;;;;;;;;;;yEAayE;AACzE,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAChD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QACtB,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;QACvC,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,CAAA;QAE7B,0BAA0B;QAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QACvC,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;YAC9B,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;YAC9B,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,CAAA;QAC/E,CAAC;QAED,2CAA2C;QAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACnC,IAAI,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;YACzD,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YACzC,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;YAC9B,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;YAC9B,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,CAAA;QAC/E,CAAC;QAED,+CAA+C;QAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC1D,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YACvC,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;YAC9B,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;YAC9B,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,CAAA;QAC/E,CAAC;QAED,0CAA0C;QAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAClF,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;YAChC,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;YAChC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,CAAA;QAC/E,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,qDAAqD;IACvD,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Pick a sensible extension for a buffer based on (in order):
|
|
2
|
+
* 1. content-type header from the CDN response
|
|
3
|
+
* 2. the original filename (for msgtype='file') if it has one
|
|
4
|
+
* 3. fallback 'bin' so the file is always inspectable on disk
|
|
5
|
+
*
|
|
6
|
+
* Same map shape as telegram's pickExtension but DingTalk also delivers
|
|
7
|
+
* voice as audio/amr — distinct from anything telegram sees. */
|
|
8
|
+
export declare function pickDingTalkExtension(contentType: string | undefined, originalFilename: string | undefined): string;
|
|
9
|
+
/** Write `buffer` to `<MEDIA_ROOT>/dingtalk/<subPath>/<filename>` and
|
|
10
|
+
* return the absolute path. Refuses path-traversal in filename / subPath
|
|
11
|
+
* (segments containing `/`, `\`, or `..` are rejected before mkdir).
|
|
12
|
+
*
|
|
13
|
+
* Caller is responsible for the size cap — `dingtalk-client.ts`
|
|
14
|
+
* already enforces MAX_MEDIA_BYTES before handing us the buffer. */
|
|
15
|
+
export declare function saveDingTalkMedia(buffer: Buffer, subPath: string, filename: string): Promise<string>;
|
|
16
|
+
//# sourceMappingURL=media-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-store.d.ts","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/media-store.ts"],"names":[],"mappings":"AAgBA;;;;;;iEAMiE;AACjE,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,MAAM,CA2BR;AAED;;;;;qEAKqE;AACrE,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAiBjB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// DingTalk inbound media → local disk.
|
|
2
|
+
//
|
|
3
|
+
// We piggyback on telegram's MEDIA_ROOT so both adapters land their
|
|
4
|
+
// attachments in the same ~/.im-hub/media/<platform>/<thread>/ tree.
|
|
5
|
+
// That keeps `cleanupOldMedia` (running on the telegram side) covering
|
|
6
|
+
// everything, and matches how claude-code's Read tool already expects
|
|
7
|
+
// to find adjuncts referenced by `[图片附件:…]` markers.
|
|
8
|
+
//
|
|
9
|
+
// Why a separate file from `dingtalk-client.ts`? The client's job is the
|
|
10
|
+
// network round-trip; the on-disk format and path-injection guards live
|
|
11
|
+
// here so they can be unit-tested without spinning up a DWClient.
|
|
12
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
13
|
+
import { resolve } from 'node:path';
|
|
14
|
+
import { MEDIA_ROOT } from '../telegram/media-download.js';
|
|
15
|
+
/** Pick a sensible extension for a buffer based on (in order):
|
|
16
|
+
* 1. content-type header from the CDN response
|
|
17
|
+
* 2. the original filename (for msgtype='file') if it has one
|
|
18
|
+
* 3. fallback 'bin' so the file is always inspectable on disk
|
|
19
|
+
*
|
|
20
|
+
* Same map shape as telegram's pickExtension but DingTalk also delivers
|
|
21
|
+
* voice as audio/amr — distinct from anything telegram sees. */
|
|
22
|
+
export function pickDingTalkExtension(contentType, originalFilename) {
|
|
23
|
+
if (originalFilename) {
|
|
24
|
+
const m = /\.([a-z0-9]+)$/i.exec(originalFilename);
|
|
25
|
+
if (m)
|
|
26
|
+
return m[1].toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
if (contentType) {
|
|
29
|
+
const map = {
|
|
30
|
+
'image/jpeg': 'jpg',
|
|
31
|
+
'image/jpg': 'jpg',
|
|
32
|
+
'image/png': 'png',
|
|
33
|
+
'image/gif': 'gif',
|
|
34
|
+
'image/webp': 'webp',
|
|
35
|
+
'image/heic': 'heic',
|
|
36
|
+
'audio/amr': 'amr',
|
|
37
|
+
'audio/x-amr': 'amr',
|
|
38
|
+
'audio/mpeg': 'mp3',
|
|
39
|
+
'audio/mp4': 'm4a',
|
|
40
|
+
'audio/ogg': 'ogg',
|
|
41
|
+
'audio/wav': 'wav',
|
|
42
|
+
'application/pdf': 'pdf',
|
|
43
|
+
};
|
|
44
|
+
const ct = contentType.toLowerCase().split(';')[0].trim();
|
|
45
|
+
if (map[ct])
|
|
46
|
+
return map[ct];
|
|
47
|
+
const m = /\/([a-z0-9]+)$/i.exec(ct);
|
|
48
|
+
if (m)
|
|
49
|
+
return m[1].toLowerCase();
|
|
50
|
+
}
|
|
51
|
+
return 'bin';
|
|
52
|
+
}
|
|
53
|
+
/** Write `buffer` to `<MEDIA_ROOT>/dingtalk/<subPath>/<filename>` and
|
|
54
|
+
* return the absolute path. Refuses path-traversal in filename / subPath
|
|
55
|
+
* (segments containing `/`, `\`, or `..` are rejected before mkdir).
|
|
56
|
+
*
|
|
57
|
+
* Caller is responsible for the size cap — `dingtalk-client.ts`
|
|
58
|
+
* already enforces MAX_MEDIA_BYTES before handing us the buffer. */
|
|
59
|
+
export async function saveDingTalkMedia(buffer, subPath, filename) {
|
|
60
|
+
for (const piece of [subPath, filename]) {
|
|
61
|
+
if (piece.includes('..') || piece.includes('\\')) {
|
|
62
|
+
throw new Error(`unsafe path piece: ${piece}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (filename.includes('/')) {
|
|
66
|
+
throw new Error(`unsafe filename: ${filename}`);
|
|
67
|
+
}
|
|
68
|
+
const dir = resolve(MEDIA_ROOT, 'dingtalk', subPath);
|
|
69
|
+
const path = resolve(dir, filename);
|
|
70
|
+
if (!path.startsWith(`${MEDIA_ROOT}/`)) {
|
|
71
|
+
throw new Error(`destination escapes MEDIA_ROOT: ${path}`);
|
|
72
|
+
}
|
|
73
|
+
await mkdir(dir, { recursive: true });
|
|
74
|
+
await writeFile(path, buffer);
|
|
75
|
+
return path;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=media-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-store.js","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/media-store.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,EAAE;AACF,oEAAoE;AACpE,qEAAqE;AACrE,uEAAuE;AACvE,sEAAsE;AACtE,qDAAqD;AACrD,EAAE;AACF,yEAAyE;AACzE,wEAAwE;AACxE,kEAAkE;AAElE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAE1D;;;;;;iEAMiE;AACjE,MAAM,UAAU,qBAAqB,CACnC,WAA+B,EAC/B,gBAAoC;IAEpC,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;QAClD,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;IAClC,CAAC;IACD,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,GAAG,GAA2B;YAClC,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,MAAM;YACpB,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,KAAK;YAClB,aAAa,EAAE,KAAK;YACpB,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,KAAK;YAClB,iBAAiB,EAAE,KAAK;SACzB,CAAA;QACD,MAAM,EAAE,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QACzD,IAAI,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,GAAG,CAAC,EAAE,CAAC,CAAA;QAC3B,MAAM,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACpC,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;IAClC,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;qEAKqE;AACrE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAc,EACd,OAAe,EACf,QAAgB;IAEhB,KAAK,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;QACxC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAA;QAChD,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,EAAE,CAAC,CAAA;IACjD,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;IACpD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IACnC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,EAAE,CAAC,CAAA;IAC5D,CAAC;IACD,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACrC,MAAM,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC7B,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export interface DingTalkConfig {
|
|
2
|
+
/** AppKey from the DingTalk developer console (also serves as robotCode). */
|
|
3
|
+
clientId: string;
|
|
4
|
+
/** AppSecret — used by the SDK to obtain access tokens automatically. */
|
|
5
|
+
clientSecret: string;
|
|
6
|
+
/** Optional channel id (forwarded to MessageContext); we don't drive
|
|
7
|
+
* routing on it but a few downstream consumers tag logs by it. */
|
|
8
|
+
channelId?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Inbound message payload from the Stream SDK's TOPIC_ROBOT callback.
|
|
11
|
+
* Empirically observed msgtype values (community docs say `image`/`voice`
|
|
12
|
+
* but DingTalk actually wire-formats them as `picture`/`audio`):
|
|
13
|
+
* 'text' | 'picture' | 'audio' | 'file' | 'link' | 'markdown' | 'action_card'
|
|
14
|
+
* The official Node SDK only types `text`; we keep msgtype as a loose
|
|
15
|
+
* string and snapshot known shapes for the rest. Unknown shapes fall
|
|
16
|
+
* through to a debug-logging path that dumps the full payload — that's
|
|
17
|
+
* how we discovered the `picture`/`audio` naming + the `content` block
|
|
18
|
+
* shape (community docs document those fields under `msg.picture` etc.,
|
|
19
|
+
* but real deliveries put them inside a single `content` object). */
|
|
20
|
+
export interface DingTalkInboundMessage {
|
|
21
|
+
/** Unique message id for dedup. */
|
|
22
|
+
msgId: string;
|
|
23
|
+
/** One of the empirically-confirmed msgtype values, or something else. */
|
|
24
|
+
msgtype: string;
|
|
25
|
+
/** Present on msgtype='text'. */
|
|
26
|
+
text?: {
|
|
27
|
+
content: string;
|
|
28
|
+
};
|
|
29
|
+
/** Present on msgtype='link'. picUrl is the thumbnail; messageUrl is
|
|
30
|
+
* the deep link / URL the user actually shared. Title/text are
|
|
31
|
+
* display preview. */
|
|
32
|
+
link?: {
|
|
33
|
+
title?: string;
|
|
34
|
+
text?: string;
|
|
35
|
+
picUrl?: string;
|
|
36
|
+
messageUrl?: string;
|
|
37
|
+
};
|
|
38
|
+
/** Catch-all `content` block — used by every non-text/non-link msgtype.
|
|
39
|
+
* Different msgtype values use different subsets of the fields below:
|
|
40
|
+
* picture: { pictureDownloadCode (full), downloadCode (thumb) }
|
|
41
|
+
* audio: { downloadCode, recognition (DingTalk's server-side ASR!) }
|
|
42
|
+
* file: { downloadCode, fileName } (best-effort from docs)
|
|
43
|
+
* markdown / action_card: { text, title } (best-effort) */
|
|
44
|
+
content?: {
|
|
45
|
+
pictureDownloadCode?: string;
|
|
46
|
+
downloadCode?: string;
|
|
47
|
+
/** DingTalk's built-in voice-to-text for `audio` messages. Prefer
|
|
48
|
+
* this over running whisper.cpp locally — it's typically more
|
|
49
|
+
* accurate for Mandarin and zero-cost on our side. */
|
|
50
|
+
recognition?: string;
|
|
51
|
+
title?: string;
|
|
52
|
+
text?: string;
|
|
53
|
+
fileName?: string;
|
|
54
|
+
duration?: string | number;
|
|
55
|
+
};
|
|
56
|
+
/** Conversation id in OpenAPI's `openConversationId` shape — usable
|
|
57
|
+
* directly when calling /v1.0/robot/groupMessages/send. */
|
|
58
|
+
conversationId: string;
|
|
59
|
+
/** '1' = single chat (1:1), '2' = group chat. */
|
|
60
|
+
conversationType: '1' | '2' | string;
|
|
61
|
+
/** Internal staff id of the message sender (use in 1:1 send userIds). */
|
|
62
|
+
senderStaffId: string;
|
|
63
|
+
senderNick?: string;
|
|
64
|
+
senderCorpId?: string;
|
|
65
|
+
/** Bot's own ids (chatbotUserId = robot's user id inside the corp). */
|
|
66
|
+
chatbotUserId?: string;
|
|
67
|
+
chatbotCorpId?: string;
|
|
68
|
+
/** The bot's robotCode — same value as the configured AppKey/clientId
|
|
69
|
+
* for stream-mode internal apps, but we read it from the message so
|
|
70
|
+
* we don't have to hard-code the relationship. */
|
|
71
|
+
robotCode: string;
|
|
72
|
+
/** Temporary webhook URL the bot can POST to without an access token,
|
|
73
|
+
* valid until `sessionWebhookExpiredTime` (ms epoch). 30s in practice. */
|
|
74
|
+
sessionWebhook?: string;
|
|
75
|
+
sessionWebhookExpiredTime?: number;
|
|
76
|
+
createAt?: number;
|
|
77
|
+
isAdmin?: boolean;
|
|
78
|
+
/** Catch-all for unknown fields — we never index this in code, but
|
|
79
|
+
* preserving it lets the debug-log path dump the full payload. */
|
|
80
|
+
[extra: string]: unknown;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/types.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,cAAc;IAC7B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAA;IAChB,yEAAyE;IACzE,YAAY,EAAE,MAAM,CAAA;IACpB;uEACmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;sEASsE;AACtE,MAAM,WAAW,sBAAsB;IACrC,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAA;IACf,iCAAiC;IACjC,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1B;;2BAEuB;IACvB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9E;;;;;kEAK8D;IAC9D,OAAO,CAAC,EAAE;QACR,mBAAmB,CAAC,EAAE,MAAM,CAAA;QAC5B,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB;;+DAEuD;QACvD,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAC3B,CAAA;IACD;gEAC4D;IAC5D,cAAc,EAAE,MAAM,CAAA;IACtB,iDAAiD;IACjD,gBAAgB,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,CAAA;IACpC,yEAAyE;IACzE,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;uDAEmD;IACnD,SAAS,EAAE,MAAM,CAAA;IACjB;+EAC2E;IAC3E,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;uEACmE;IACnE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;CACzB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// DingTalk (钉钉) Bot — Stream-mode messenger types
|
|
2
|
+
//
|
|
3
|
+
// Reference:
|
|
4
|
+
// * SDK: https://github.com/open-dingtalk/dingtalk-stream-sdk-nodejs
|
|
5
|
+
// * Stream mode protocol: https://open.dingtalk.com/document/direction/stream-mode-protocol-access-description
|
|
6
|
+
// * 1:1 send: POST /v1.0/robot/oToMessages/batchSend
|
|
7
|
+
// * Group send: POST /v1.0/robot/groupMessages/send
|
|
8
|
+
//
|
|
9
|
+
// Note: the SDK's RobotTextMessage type covers only `msgtype: 'text'`, but
|
|
10
|
+
// inbound payloads carry conversationType / robotCode / sessionWebhook
|
|
11
|
+
// that we need for routing — restate the full shape here so the adapter
|
|
12
|
+
// can switch on conversationType without fighting the SDK union.
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/types.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,EAAE;AACF,aAAa;AACb,uEAAuE;AACvE,iHAAiH;AACjH,uDAAuD;AACvD,sDAAsD;AACtD,EAAE;AACF,2EAA2E;AAC3E,uEAAuE;AACvE,wEAAwE;AACxE,iEAAiE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { MessengerAdapter, MessageContext } from '../../../core/types.js';
|
|
2
|
+
export declare class DiscordAdapter implements MessengerAdapter {
|
|
3
|
+
readonly name = "discord";
|
|
4
|
+
private client;
|
|
5
|
+
private config;
|
|
6
|
+
private messageHandler?;
|
|
7
|
+
private typingIntervals;
|
|
8
|
+
/** L7: companion AbortController per typing thread. Lets the periodic
|
|
9
|
+
* refresh callback bail BEFORE invoking sendTyping when stop() has
|
|
10
|
+
* fired, instead of racing against client.destroy(). */
|
|
11
|
+
private typingAbortControllers;
|
|
12
|
+
start(): Promise<void>;
|
|
13
|
+
stop(): Promise<void>;
|
|
14
|
+
onMessage(handler: (ctx: MessageContext) => Promise<void>): void;
|
|
15
|
+
sendMessage(threadId: string, text: string): Promise<void>;
|
|
16
|
+
sendTyping(threadId: string, isTyping: boolean): Promise<void>;
|
|
17
|
+
private fetchSendableChannel;
|
|
18
|
+
private handleDiscordMessage;
|
|
19
|
+
}
|
|
20
|
+
export declare const discordAdapter: DiscordAdapter;
|
|
21
|
+
//# sourceMappingURL=discord-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discord-adapter.d.ts","sourceRoot":"","sources":["../../../../src/plugins/messengers/discord/discord-adapter.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAW,MAAM,wBAAwB,CAAA;AAWvF,qBAAa,cAAe,YAAW,gBAAgB;IACrD,QAAQ,CAAC,IAAI,aAAY;IACzB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,cAAc,CAAC,CAAwC;IAC/D,OAAO,CAAC,eAAe,CAAoD;IAC3E;;6DAEyD;IACzD,OAAO,CAAC,sBAAsB,CAAqC;IAE7D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA0DtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB3B,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI1D,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB1D,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;YA4DtD,oBAAoB;YAcpB,oBAAoB;CAyDnC;AAGD,eAAO,MAAM,cAAc,gBAAuB,CAAA"}
|