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,229 @@
|
|
|
1
|
+
// coord-systems.ts — every coordinate-system conversion + the
|
|
2
|
+
// "normalize an incoming location" policy that adapters route through.
|
|
3
|
+
//
|
|
4
|
+
// Why this module exists (incident background, 2026-05-12):
|
|
5
|
+
// The old behavior was "treat every incoming lat/lng as GCJ-02 if it
|
|
6
|
+
// falls inside the China bbox" — true for iOS Core Location and
|
|
7
|
+
// Apple/Google GMS-with-China-region, FALSE for the WeChat X5
|
|
8
|
+
// webview, raw Android Chrome, Telegram Desktop, and other paths
|
|
9
|
+
// where the JS / IM payload is already WGS-84.
|
|
10
|
+
//
|
|
11
|
+
// The user observed wrong markers in WeChat — `/memo here` H5 capture
|
|
12
|
+
// landed coords ~500m–1km off on both 高德 and 百度 maps. Root cause:
|
|
13
|
+
// X5 webview hands the page genuine WGS-84, but server.ts applied an
|
|
14
|
+
// inverse GCJ→WGS offset on top, so the stored value was *anti-shifted*
|
|
15
|
+
// and every downstream map URL re-shifted it back the wrong way.
|
|
16
|
+
//
|
|
17
|
+
// Per-platform reality (empirically known as of 2026-05):
|
|
18
|
+
//
|
|
19
|
+
// | Source | Coord system |
|
|
20
|
+
// |---------------------------------------|-----------------|
|
|
21
|
+
// | Telegram native location (iOS in China) | GCJ-02 |
|
|
22
|
+
// | Telegram native location (iOS outside China) | WGS-84 |
|
|
23
|
+
// | Telegram native location (Telegram Desktop) | WGS-84 |
|
|
24
|
+
// | Telegram native location (most Android cases) | WGS-84 |
|
|
25
|
+
// | Feishu native location | GCJ-02 (mandated) |
|
|
26
|
+
// | DingTalk native location | n/a (not delivered to bots) |
|
|
27
|
+
// | DingTalk link msgtype → Amap/Tencent URL | GCJ-02 |
|
|
28
|
+
// | DingTalk link msgtype → Baidu Maps URL | BD-09 |
|
|
29
|
+
// | H5 `navigator.geolocation` in iOS Safari (CN) | GCJ-02 |
|
|
30
|
+
// | H5 `navigator.geolocation` in WeChat X5 / Chrome| WGS-84 |
|
|
31
|
+
//
|
|
32
|
+
// There is no reliable server-side way to know which of the two
|
|
33
|
+
// ambiguous paths produced any given coord, so we ship sensible
|
|
34
|
+
// defaults + env-var overrides for the edge cases.
|
|
35
|
+
import { logger as rootLogger } from './logger.js';
|
|
36
|
+
const log = rootLogger.child({ component: 'coord-systems' });
|
|
37
|
+
/**
|
|
38
|
+
* Convert any incoming (lat, lng) to WGS-84 based on what we know about
|
|
39
|
+
* the source. Adapters route every native coord through this. Defaults
|
|
40
|
+
* favor "trust the payload as WGS-84" because that's the safer assumption
|
|
41
|
+
* when the source is ambiguous — applying an inverse GCJ offset to a
|
|
42
|
+
* value that's actually already WGS produces a 500m-1km error, while
|
|
43
|
+
* pass-through on actual GCJ leaves the user with the same ~1km error
|
|
44
|
+
* but in a recoverable direction. Both error modes get the user roughly
|
|
45
|
+
* the right country / city; an `IMHUB_*_COORDS_GCJ02=1` env flag flips
|
|
46
|
+
* the default for any source whose users tell us their device DOES apply
|
|
47
|
+
* the offset (Apple devices in China + Chinese region most often).
|
|
48
|
+
*/
|
|
49
|
+
export function normalizeIncomingCoords(source, lat, lng) {
|
|
50
|
+
if (!Number.isFinite(lat) || !Number.isFinite(lng)) {
|
|
51
|
+
return { lat, lng, applied: 'none', outOfChina: true };
|
|
52
|
+
}
|
|
53
|
+
if (outOfChina(lat, lng)) {
|
|
54
|
+
return { lat, lng, applied: 'none', outOfChina: true };
|
|
55
|
+
}
|
|
56
|
+
// Per-source policy. The flag-overrideable defaults reflect the empirical
|
|
57
|
+
// table at the top of this file. See env table at the bottom.
|
|
58
|
+
const treatAsGcj = (() => {
|
|
59
|
+
switch (source) {
|
|
60
|
+
case 'telegram-native':
|
|
61
|
+
// Default WGS-84 (covers Telegram Desktop + non-Apple in-China +
|
|
62
|
+
// anyone outside China). User can flip with the env flag if their
|
|
63
|
+
// Telegram is on Apple-zh-CN where Core Location applies the offset.
|
|
64
|
+
return process.env.IMHUB_TELEGRAM_COORDS_GCJ02 === '1';
|
|
65
|
+
case 'feishu-native':
|
|
66
|
+
// Feishu is mandated GCJ-02 server-side, no override expected.
|
|
67
|
+
return true;
|
|
68
|
+
case 'dingtalk-link-amap':
|
|
69
|
+
case 'dingtalk-link-tencent':
|
|
70
|
+
return true;
|
|
71
|
+
case 'dingtalk-link-baidu':
|
|
72
|
+
return false; // BD-09, handled below
|
|
73
|
+
case 'dingtalk-link-unknown':
|
|
74
|
+
return false; // pass-through; don't guess
|
|
75
|
+
case 'h5-browser-geolocation':
|
|
76
|
+
// Default WGS-84. THIS IS THE INCIDENT FIX (2026-05-12): WeChat
|
|
77
|
+
// X5 + Android Chrome without GMS hand the page raw WGS-84 and
|
|
78
|
+
// the old "always GCJ" assumption put markers ~1km off in WeChat.
|
|
79
|
+
// iOS Safari users in China can flip the flag to restore the old
|
|
80
|
+
// GCJ→WGS path.
|
|
81
|
+
return process.env.IMHUB_H5_COORDS_GCJ02 === '1';
|
|
82
|
+
case 'web-admin':
|
|
83
|
+
// Developer-facing console; PC browser is overwhelmingly WGS-84.
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
})();
|
|
87
|
+
if (source === 'dingtalk-link-baidu') {
|
|
88
|
+
const wgs = bd09ToWgs84(lat, lng);
|
|
89
|
+
log.debug({
|
|
90
|
+
event: 'coord.normalized',
|
|
91
|
+
source,
|
|
92
|
+
raw_lat: lat, raw_lng: lng,
|
|
93
|
+
wgs_lat: wgs.lat, wgs_lng: wgs.lng,
|
|
94
|
+
applied: 'bd09-to-wgs84',
|
|
95
|
+
});
|
|
96
|
+
return { lat: wgs.lat, lng: wgs.lng, applied: 'bd09-to-wgs84', outOfChina: false };
|
|
97
|
+
}
|
|
98
|
+
if (treatAsGcj) {
|
|
99
|
+
const wgs = gcj02ToWgs84(lat, lng);
|
|
100
|
+
log.debug({
|
|
101
|
+
event: 'coord.normalized',
|
|
102
|
+
source,
|
|
103
|
+
raw_lat: lat, raw_lng: lng,
|
|
104
|
+
wgs_lat: wgs.lat, wgs_lng: wgs.lng,
|
|
105
|
+
applied: 'gcj02-to-wgs84',
|
|
106
|
+
});
|
|
107
|
+
return { lat: wgs.lat, lng: wgs.lng, applied: 'gcj02-to-wgs84', outOfChina: false };
|
|
108
|
+
}
|
|
109
|
+
log.debug({
|
|
110
|
+
event: 'coord.normalized',
|
|
111
|
+
source,
|
|
112
|
+
raw_lat: lat, raw_lng: lng,
|
|
113
|
+
wgs_lat: lat, wgs_lng: lng,
|
|
114
|
+
applied: 'none',
|
|
115
|
+
});
|
|
116
|
+
return { lat, lng, applied: 'none', outOfChina: false };
|
|
117
|
+
}
|
|
118
|
+
// ─── coord-system math ──────────────────────────────────────────────
|
|
119
|
+
// We keep the GCJ pair in this file alongside BD-09 (rather than
|
|
120
|
+
// re-exporting from memos.ts) so all coord math lives in one place.
|
|
121
|
+
// The originals in memos.ts are still exported for backwards-compat;
|
|
122
|
+
// new code should import from here.
|
|
123
|
+
const A = 6378245.0;
|
|
124
|
+
const EE = 0.006693421622965943;
|
|
125
|
+
const PI = Math.PI;
|
|
126
|
+
/** WGS-84 → GCJ-02. */
|
|
127
|
+
export function wgs84ToGcj02(lat, lng) {
|
|
128
|
+
if (outOfChina(lat, lng))
|
|
129
|
+
return { lat, lng };
|
|
130
|
+
let dLat = transformLat(lng - 105.0, lat - 35.0);
|
|
131
|
+
let dLng = transformLng(lng - 105.0, lat - 35.0);
|
|
132
|
+
const radLat = (lat / 180.0) * PI;
|
|
133
|
+
let magic = Math.sin(radLat);
|
|
134
|
+
magic = 1 - EE * magic * magic;
|
|
135
|
+
const sqrtMagic = Math.sqrt(magic);
|
|
136
|
+
dLat = (dLat * 180.0) / (((A * (1 - EE)) / (magic * sqrtMagic)) * PI);
|
|
137
|
+
dLng = (dLng * 180.0) / ((A / sqrtMagic) * Math.cos(radLat) * PI);
|
|
138
|
+
return { lat: lat + dLat, lng: lng + dLng };
|
|
139
|
+
}
|
|
140
|
+
/** GCJ-02 → WGS-84 (Newton iteration; converges to sub-meter in 3 passes). */
|
|
141
|
+
export function gcj02ToWgs84(lat, lng) {
|
|
142
|
+
if (outOfChina(lat, lng))
|
|
143
|
+
return { lat, lng };
|
|
144
|
+
let wgsLat = lat;
|
|
145
|
+
let wgsLng = lng;
|
|
146
|
+
for (let i = 0; i < 3; i++) {
|
|
147
|
+
const forward = wgs84ToGcj02(wgsLat, wgsLng);
|
|
148
|
+
wgsLat = lat - (forward.lat - wgsLat);
|
|
149
|
+
wgsLng = lng - (forward.lng - wgsLng);
|
|
150
|
+
}
|
|
151
|
+
return { lat: wgsLat, lng: wgsLng };
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Baidu BD-09 → GCJ-02. BD-09 is GCJ-02 plus an additional radial offset
|
|
155
|
+
* applied by Baidu. The math is well-known (cf. open-source `coordtransform`
|
|
156
|
+
* libraries); we lift the formula verbatim and add a comment so the next
|
|
157
|
+
* reader doesn't have to derive it.
|
|
158
|
+
*/
|
|
159
|
+
export function bd09ToGcj02(lat, lng) {
|
|
160
|
+
if (outOfChina(lat, lng))
|
|
161
|
+
return { lat, lng };
|
|
162
|
+
const X_PI = (PI * 3000.0) / 180.0;
|
|
163
|
+
const x = lng - 0.0065;
|
|
164
|
+
const y = lat - 0.006;
|
|
165
|
+
const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI);
|
|
166
|
+
const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);
|
|
167
|
+
return { lat: z * Math.sin(theta), lng: z * Math.cos(theta) };
|
|
168
|
+
}
|
|
169
|
+
/** GCJ-02 → Baidu BD-09 (forward; closed form). */
|
|
170
|
+
export function gcj02ToBd09(lat, lng) {
|
|
171
|
+
if (outOfChina(lat, lng))
|
|
172
|
+
return { lat, lng };
|
|
173
|
+
const X_PI = (PI * 3000.0) / 180.0;
|
|
174
|
+
const z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * X_PI);
|
|
175
|
+
const theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * X_PI);
|
|
176
|
+
return { lat: z * Math.sin(theta) + 0.006, lng: z * Math.cos(theta) + 0.0065 };
|
|
177
|
+
}
|
|
178
|
+
/** BD-09 → WGS-84 via GCJ-02 intermediate. */
|
|
179
|
+
export function bd09ToWgs84(lat, lng) {
|
|
180
|
+
if (outOfChina(lat, lng))
|
|
181
|
+
return { lat, lng };
|
|
182
|
+
const gcj = bd09ToGcj02(lat, lng);
|
|
183
|
+
return gcj02ToWgs84(gcj.lat, gcj.lng);
|
|
184
|
+
}
|
|
185
|
+
/** WGS-84 → BD-09 via GCJ-02 intermediate. Useful for building Baidu
|
|
186
|
+
* Maps URLs from our WGS-stored coords. */
|
|
187
|
+
export function wgs84ToBd09(lat, lng) {
|
|
188
|
+
if (outOfChina(lat, lng))
|
|
189
|
+
return { lat, lng };
|
|
190
|
+
const gcj = wgs84ToGcj02(lat, lng);
|
|
191
|
+
return gcj02ToBd09(gcj.lat, gcj.lng);
|
|
192
|
+
}
|
|
193
|
+
// ─── internals ──────────────────────────────────────────────────────
|
|
194
|
+
/** GCJ-02 offset is only defined for mainland China + the bbox below.
|
|
195
|
+
* Outside, every conversion in this module is a no-op pass-through. */
|
|
196
|
+
export function outOfChina(lat, lng) {
|
|
197
|
+
return lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271;
|
|
198
|
+
}
|
|
199
|
+
function transformLat(x, y) {
|
|
200
|
+
let r = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
|
|
201
|
+
r += ((20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0;
|
|
202
|
+
r += ((20.0 * Math.sin(y * PI) + 40.0 * Math.sin((y / 3.0) * PI)) * 2.0) / 3.0;
|
|
203
|
+
r += ((160.0 * Math.sin((y / 12.0) * PI) + 320 * Math.sin((y * PI) / 30.0)) * 2.0) / 3.0;
|
|
204
|
+
return r;
|
|
205
|
+
}
|
|
206
|
+
function transformLng(x, y) {
|
|
207
|
+
let r = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
|
|
208
|
+
r += ((20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0;
|
|
209
|
+
r += ((20.0 * Math.sin(x * PI) + 40.0 * Math.sin((x / 3.0) * PI)) * 2.0) / 3.0;
|
|
210
|
+
r += ((150.0 * Math.sin((x / 12.0) * PI) + 300.0 * Math.sin((x / 30.0) * PI)) * 2.0) / 3.0;
|
|
211
|
+
return r;
|
|
212
|
+
}
|
|
213
|
+
// ─── env vars exposed by this module ────────────────────────────────
|
|
214
|
+
//
|
|
215
|
+
// IMHUB_TELEGRAM_COORDS_GCJ02=1
|
|
216
|
+
// Apply GCJ-02 → WGS-84 to Telegram native location/venue messages.
|
|
217
|
+
// Default off (WGS pass-through). Turn ON if your Telegram clients are
|
|
218
|
+
// Apple devices in China (iOS Core Location applies the offset).
|
|
219
|
+
//
|
|
220
|
+
// IMHUB_H5_COORDS_GCJ02=1
|
|
221
|
+
// Apply GCJ-02 → WGS-84 to coordinates POSTed from the /memo here H5
|
|
222
|
+
// capture page. Default off (WGS pass-through). Turn ON if your users
|
|
223
|
+
// open the H5 link in iOS Safari / iOS WebKit in mainland China —
|
|
224
|
+
// navigator.geolocation respects Apple's GCJ offset there.
|
|
225
|
+
//
|
|
226
|
+
// (Feishu always GCJ→WGS, DingTalk amap/qmap always GCJ→WGS,
|
|
227
|
+
// DingTalk baidu always BD-09→WGS — those are server-mandated and
|
|
228
|
+
// don't need overrides.)
|
|
229
|
+
//# sourceMappingURL=coord-systems.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coord-systems.js","sourceRoot":"","sources":["../../src/core/coord-systems.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
interface FieldSpec {
|
|
2
|
+
raw: string;
|
|
3
|
+
values: Set<number>;
|
|
4
|
+
min: number;
|
|
5
|
+
max: number;
|
|
6
|
+
}
|
|
7
|
+
export interface CronSpec {
|
|
8
|
+
minute: FieldSpec;
|
|
9
|
+
hour: FieldSpec;
|
|
10
|
+
day: FieldSpec;
|
|
11
|
+
month: FieldSpec;
|
|
12
|
+
dow: FieldSpec;
|
|
13
|
+
}
|
|
14
|
+
export declare function parseCron(expr: string): CronSpec;
|
|
15
|
+
/**
|
|
16
|
+
* Next firing strictly after `from`, found by field-level
|
|
17
|
+
* fast-forwarding. For "yearly at midnight Jan 1" (`0 0 1 1 *`) this
|
|
18
|
+
* converges in at most 4-5 jumps, vs ~525_000 minute increments under
|
|
19
|
+
* the previous brute-force loop.
|
|
20
|
+
*
|
|
21
|
+
* The loop walks fields outermost (month) → innermost (minute). On a
|
|
22
|
+
* mismatch we set the field to its ceiling (next valid value) and reset
|
|
23
|
+
* everything inside it. If no ceiling exists in the current scope we
|
|
24
|
+
* step one unit up in the parent field. JavaScript Date handles
|
|
25
|
+
* carries (month=12 → next year, hour=24 → next day) natively.
|
|
26
|
+
*/
|
|
27
|
+
export declare function nextOccurrence(spec: CronSpec, from?: Date): Date | null;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=cron.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/core/cron.ts"],"names":[],"mappings":"AAgBA,UAAU,SAAS;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACnB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;CACZ;AA2DD,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,SAAS,CAAA;IACjB,IAAI,EAAE,SAAS,CAAA;IACf,GAAG,EAAE,SAAS,CAAA;IACd,KAAK,EAAE,SAAS,CAAA;IAChB,GAAG,EAAE,SAAS,CAAA;CACf;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAYhD;AAgCD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAE,IAAiB,GAAG,IAAI,GAAG,IAAI,CA2DnF"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// Minimal POSIX-flavored cron parser (5 fields: minute hour day month dow).
|
|
2
|
+
//
|
|
3
|
+
// Supported syntax per field:
|
|
4
|
+
// * wildcard
|
|
5
|
+
// N single integer
|
|
6
|
+
// N,M,O comma list
|
|
7
|
+
// N-M inclusive range
|
|
8
|
+
// *\/K step (e.g. */5 = every 5 minutes)
|
|
9
|
+
// N-M/K stepped range
|
|
10
|
+
//
|
|
11
|
+
// Day-of-week: 0 or 7 = Sunday, 1 = Monday … 6 = Saturday.
|
|
12
|
+
//
|
|
13
|
+
// nextOccurrence() returns the next Date strictly greater than `from`.
|
|
14
|
+
// Returns null only on bogus expressions; a valid expression always has
|
|
15
|
+
// a future occurrence within ~6 years (the search loop bails after that).
|
|
16
|
+
const FIELD_BOUNDS = [
|
|
17
|
+
{ name: 'minute', min: 0, max: 59 },
|
|
18
|
+
{ name: 'hour', min: 0, max: 23 },
|
|
19
|
+
{ name: 'day', min: 1, max: 31 },
|
|
20
|
+
{ name: 'month', min: 1, max: 12 },
|
|
21
|
+
{ name: 'dow', min: 0, max: 6 }, // 7 normalized to 0
|
|
22
|
+
];
|
|
23
|
+
function parseField(raw, min, max, fieldName) {
|
|
24
|
+
const out = new Set();
|
|
25
|
+
for (const piece of raw.split(',')) {
|
|
26
|
+
const stepMatch = piece.match(/^(.+)\/(\d+)$/);
|
|
27
|
+
let body = piece;
|
|
28
|
+
let step = 1;
|
|
29
|
+
if (stepMatch) {
|
|
30
|
+
body = stepMatch[1];
|
|
31
|
+
step = parseInt(stepMatch[2], 10);
|
|
32
|
+
if (!Number.isFinite(step) || step <= 0) {
|
|
33
|
+
throw new Error(`Invalid step in ${fieldName}: ${piece}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
let lo;
|
|
37
|
+
let hi;
|
|
38
|
+
if (body === '*') {
|
|
39
|
+
lo = min;
|
|
40
|
+
hi = max;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const range = body.match(/^(\d+)-(\d+)$/);
|
|
44
|
+
if (range) {
|
|
45
|
+
lo = parseInt(range[1], 10);
|
|
46
|
+
hi = parseInt(range[2], 10);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const single = parseInt(body, 10);
|
|
50
|
+
if (!Number.isFinite(single)) {
|
|
51
|
+
throw new Error(`Invalid value in ${fieldName}: ${piece}`);
|
|
52
|
+
}
|
|
53
|
+
lo = single;
|
|
54
|
+
hi = single;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (fieldName === 'dow') {
|
|
58
|
+
if (lo === 7)
|
|
59
|
+
lo = 0;
|
|
60
|
+
if (hi === 7)
|
|
61
|
+
hi = 0;
|
|
62
|
+
}
|
|
63
|
+
if (lo < min || hi > max || lo > hi) {
|
|
64
|
+
throw new Error(`Out-of-range value in ${fieldName}: ${piece}`);
|
|
65
|
+
}
|
|
66
|
+
for (let v = lo; v <= hi; v += step)
|
|
67
|
+
out.add(v);
|
|
68
|
+
}
|
|
69
|
+
return { raw, values: out, min, max };
|
|
70
|
+
}
|
|
71
|
+
export function parseCron(expr) {
|
|
72
|
+
const parts = expr.trim().split(/\s+/);
|
|
73
|
+
if (parts.length !== 5) {
|
|
74
|
+
throw new Error(`Expected 5 fields (minute hour day month dow), got ${parts.length}`);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
minute: parseField(parts[0], FIELD_BOUNDS[0].min, FIELD_BOUNDS[0].max, FIELD_BOUNDS[0].name),
|
|
78
|
+
hour: parseField(parts[1], FIELD_BOUNDS[1].min, FIELD_BOUNDS[1].max, FIELD_BOUNDS[1].name),
|
|
79
|
+
day: parseField(parts[2], FIELD_BOUNDS[2].min, FIELD_BOUNDS[2].max, FIELD_BOUNDS[2].name),
|
|
80
|
+
month: parseField(parts[3], FIELD_BOUNDS[3].min, FIELD_BOUNDS[3].max, FIELD_BOUNDS[3].name),
|
|
81
|
+
dow: parseField(parts[4], FIELD_BOUNDS[4].min, FIELD_BOUNDS[4].max, FIELD_BOUNDS[4].name),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Smallest value in `values` that is ≥ target, or null if none.
|
|
86
|
+
* The set is iterated linearly; sizes are tiny (≤ 60) so the cost is
|
|
87
|
+
* negligible vs the surrounding work.
|
|
88
|
+
*/
|
|
89
|
+
function ceilingIn(values, target) {
|
|
90
|
+
let best = null;
|
|
91
|
+
for (const v of values) {
|
|
92
|
+
if (v >= target && (best === null || v < best))
|
|
93
|
+
best = v;
|
|
94
|
+
}
|
|
95
|
+
return best;
|
|
96
|
+
}
|
|
97
|
+
function firstIn(values) {
|
|
98
|
+
let best = Infinity;
|
|
99
|
+
for (const v of values)
|
|
100
|
+
if (v < best)
|
|
101
|
+
best = v;
|
|
102
|
+
return best;
|
|
103
|
+
}
|
|
104
|
+
function dayMatches(spec, d) {
|
|
105
|
+
const dayWild = spec.day.raw === '*';
|
|
106
|
+
const dowWild = spec.dow.raw === '*';
|
|
107
|
+
const dayOk = spec.day.values.has(d.getDate());
|
|
108
|
+
const dowOk = spec.dow.values.has(d.getDay());
|
|
109
|
+
if (dayWild && dowWild)
|
|
110
|
+
return true;
|
|
111
|
+
if (!dayWild && dowWild)
|
|
112
|
+
return dayOk;
|
|
113
|
+
if (dayWild && !dowWild)
|
|
114
|
+
return dowOk;
|
|
115
|
+
return dayOk || dowOk;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Next firing strictly after `from`, found by field-level
|
|
119
|
+
* fast-forwarding. For "yearly at midnight Jan 1" (`0 0 1 1 *`) this
|
|
120
|
+
* converges in at most 4-5 jumps, vs ~525_000 minute increments under
|
|
121
|
+
* the previous brute-force loop.
|
|
122
|
+
*
|
|
123
|
+
* The loop walks fields outermost (month) → innermost (minute). On a
|
|
124
|
+
* mismatch we set the field to its ceiling (next valid value) and reset
|
|
125
|
+
* everything inside it. If no ceiling exists in the current scope we
|
|
126
|
+
* step one unit up in the parent field. JavaScript Date handles
|
|
127
|
+
* carries (month=12 → next year, hour=24 → next day) natively.
|
|
128
|
+
*/
|
|
129
|
+
export function nextOccurrence(spec, from = new Date()) {
|
|
130
|
+
const cur = new Date(from);
|
|
131
|
+
cur.setSeconds(0, 0);
|
|
132
|
+
cur.setMinutes(cur.getMinutes() + 1);
|
|
133
|
+
// Sane upper bound: 1000 field jumps will resolve any 5-field spec —
|
|
134
|
+
// crontab can't repeat itself within that many adjustments.
|
|
135
|
+
for (let i = 0; i < 1000; i++) {
|
|
136
|
+
// 1) Month
|
|
137
|
+
const mthIdx = cur.getMonth() + 1; // 1-indexed
|
|
138
|
+
const mthCeil = ceilingIn(spec.month.values, mthIdx);
|
|
139
|
+
if (mthCeil === null) {
|
|
140
|
+
// No matching month this year — roll to next year's first valid month.
|
|
141
|
+
cur.setFullYear(cur.getFullYear() + 1, firstIn(spec.month.values) - 1, 1);
|
|
142
|
+
cur.setHours(0, 0, 0, 0);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (mthCeil !== mthIdx) {
|
|
146
|
+
cur.setMonth(mthCeil - 1, 1);
|
|
147
|
+
cur.setHours(0, 0, 0, 0);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
// 2) Day (handle the day-OR-dow quirk through dayMatches)
|
|
151
|
+
if (!dayMatches(spec, cur)) {
|
|
152
|
+
cur.setDate(cur.getDate() + 1);
|
|
153
|
+
cur.setHours(0, 0, 0, 0);
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
// 3) Hour
|
|
157
|
+
const hr = cur.getHours();
|
|
158
|
+
const hrCeil = ceilingIn(spec.hour.values, hr);
|
|
159
|
+
if (hrCeil === null) {
|
|
160
|
+
cur.setDate(cur.getDate() + 1);
|
|
161
|
+
cur.setHours(0, 0, 0, 0);
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (hrCeil !== hr) {
|
|
165
|
+
cur.setHours(hrCeil, 0, 0, 0);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
// 4) Minute
|
|
169
|
+
const mn = cur.getMinutes();
|
|
170
|
+
const mnCeil = ceilingIn(spec.minute.values, mn);
|
|
171
|
+
if (mnCeil === null) {
|
|
172
|
+
cur.setHours(cur.getHours() + 1, 0, 0, 0);
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (mnCeil !== mn) {
|
|
176
|
+
cur.setMinutes(mnCeil, 0, 0);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
// All four fields are valid simultaneously — done.
|
|
180
|
+
return new Date(cur);
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=cron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/core/cron.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
/** Fired by audit-log.logInvocation after a successful (or failed) agent
|
|
3
|
+
* invocation has been recorded. Mirrors the shape audit-log already
|
|
4
|
+
* builds, plus a `ts` ISO string for client-side sorting. */
|
|
5
|
+
export interface AuditEvent {
|
|
6
|
+
type: 'audit';
|
|
7
|
+
ts: string;
|
|
8
|
+
agent: string;
|
|
9
|
+
intent: string;
|
|
10
|
+
platform: string;
|
|
11
|
+
durationMs: number;
|
|
12
|
+
cost: number;
|
|
13
|
+
success: boolean;
|
|
14
|
+
traceId: string;
|
|
15
|
+
userId: string;
|
|
16
|
+
}
|
|
17
|
+
/** Fired when approval-bus enqueues a new pending or resolves one. The
|
|
18
|
+
* /api/approvals snapshot is still authoritative; this event lets the
|
|
19
|
+
* UI refresh that tab (and the in-chat card) without waiting on the
|
|
20
|
+
* 3 s poll. */
|
|
21
|
+
export interface ApprovalEvent {
|
|
22
|
+
type: 'approval';
|
|
23
|
+
phase: 'requested' | 'resolved';
|
|
24
|
+
reqId: string;
|
|
25
|
+
threadId: string;
|
|
26
|
+
platform: string;
|
|
27
|
+
toolName: string;
|
|
28
|
+
/** Present on resolved events — 'allow' / 'deny' / 'timeout' from the
|
|
29
|
+
* bus's metrics buckets. Absent on `requested`. */
|
|
30
|
+
outcome?: 'allow' | 'deny' | 'timeout';
|
|
31
|
+
}
|
|
32
|
+
/** Fired on job-board state transitions. The dashboard subscribes to
|
|
33
|
+
* refresh the Jobs tab without polling. */
|
|
34
|
+
export interface JobEvent {
|
|
35
|
+
type: 'job';
|
|
36
|
+
phase: 'created' | 'started' | 'completed' | 'failed' | 'cancelled';
|
|
37
|
+
jobId: number;
|
|
38
|
+
agent: string;
|
|
39
|
+
}
|
|
40
|
+
/** Periodic metrics tick. Different from individual audit events: this
|
|
41
|
+
* is a snapshot of the full per-agent state (counters + latency
|
|
42
|
+
* quantiles) so the Health tab's sparkline doesn't have to derive
|
|
43
|
+
* everything from raw audits. Emitted by an internal interval, not by
|
|
44
|
+
* any specific call site. */
|
|
45
|
+
export interface MetricsEvent {
|
|
46
|
+
type: 'metrics';
|
|
47
|
+
ts: string;
|
|
48
|
+
agents: Array<{
|
|
49
|
+
agent: string;
|
|
50
|
+
total: number;
|
|
51
|
+
success: number;
|
|
52
|
+
failure: number;
|
|
53
|
+
p50Ms: number;
|
|
54
|
+
p95Ms: number;
|
|
55
|
+
p99Ms: number;
|
|
56
|
+
}>;
|
|
57
|
+
}
|
|
58
|
+
export type ImhubEvent = AuditEvent | ApprovalEvent | JobEvent | MetricsEvent;
|
|
59
|
+
declare class ImhubEventBus extends EventEmitter {
|
|
60
|
+
/** Bounded recent-event log so a freshly-connected SSE client can
|
|
61
|
+
* catch up on what happened in the last few seconds without needing
|
|
62
|
+
* a separate REST poll. Cap at 200 entries — enough for the dashboard
|
|
63
|
+
* to show a meaningful "what just happened" feed without bloating
|
|
64
|
+
* process memory. */
|
|
65
|
+
private recent;
|
|
66
|
+
private static readonly RECENT_CAP;
|
|
67
|
+
constructor();
|
|
68
|
+
/**
|
|
69
|
+
* Publish a typed event. Listeners are called synchronously inside
|
|
70
|
+
* EventEmitter.emit; errors thrown from a listener are caught here so
|
|
71
|
+
* a bad subscriber can't break audit-log / approval-bus / job-board.
|
|
72
|
+
*/
|
|
73
|
+
publish(event: ImhubEvent): void;
|
|
74
|
+
/** Snapshot of the recent ring buffer. Used by SSE handler on
|
|
75
|
+
* connection to replay the last N events to a fresh client. */
|
|
76
|
+
getRecent(): ImhubEvent[];
|
|
77
|
+
}
|
|
78
|
+
export declare const eventBus: ImhubEventBus;
|
|
79
|
+
export {};
|
|
80
|
+
//# sourceMappingURL=event-bus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/core/event-bus.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C;;8DAE8D;AAC9D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAA;IACb,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;gBAGgB;AAChB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,EAAE,WAAW,GAAG,UAAU,CAAA;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB;wDACoD;IACpD,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;CACvC;AAED;4CAC4C;AAC5C,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,KAAK,CAAA;IACX,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAA;IACnE,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;8BAI8B;AAC9B,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,KAAK,CAAC;QACZ,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE,MAAM,CAAA;QACf,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;KACd,CAAC,CAAA;CACH;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,aAAa,GAAG,QAAQ,GAAG,YAAY,CAAA;AAE7E,cAAM,aAAc,SAAQ,YAAY;IACtC;;;;0BAIsB;IACtB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAM;;IAUxC;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAUhC;oEACgE;IAChE,SAAS,IAAI,UAAU,EAAE;CAG1B;AAED,eAAO,MAAM,QAAQ,eAAsB,CAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// im-hub event bus — fan-out for cross-cutting state changes that the
|
|
2
|
+
// dashboard / future plugins want to observe in real time.
|
|
3
|
+
//
|
|
4
|
+
// Why a dedicated bus instead of just exposing each module's
|
|
5
|
+
// EventEmitter?
|
|
6
|
+
//
|
|
7
|
+
// 1. Type uniformity. Subscribers want to handle *any* event with one
|
|
8
|
+
// handler shape; otherwise tasks.html ends up wiring six different
|
|
9
|
+
// EventEmitters by hand.
|
|
10
|
+
// 2. Cross-module decoupling. audit-log / approval-bus / job-board
|
|
11
|
+
// should not know that a Web SSE consumer exists. They emit on the
|
|
12
|
+
// bus; whoever wants to listen does.
|
|
13
|
+
// 3. Backpressure / fan-out. The /events SSE endpoint multiplexes a
|
|
14
|
+
// single bus subscription out to N browser clients. If a single
|
|
15
|
+
// client is slow we don't want to drag the entire process; the bus
|
|
16
|
+
// only does fan-out, per-connection write-buffering is the SSE
|
|
17
|
+
// handler's responsibility.
|
|
18
|
+
//
|
|
19
|
+
// IMPORTANT: emit is best-effort. Never throw out of an emit() — the
|
|
20
|
+
// caller (audit-log.logInvocation, approvalBus.handleApproval, etc.) is
|
|
21
|
+
// in a hot path. We swallow listener errors here so a buggy subscriber
|
|
22
|
+
// can't break the originating action.
|
|
23
|
+
import { EventEmitter } from 'node:events';
|
|
24
|
+
class ImhubEventBus extends EventEmitter {
|
|
25
|
+
/** Bounded recent-event log so a freshly-connected SSE client can
|
|
26
|
+
* catch up on what happened in the last few seconds without needing
|
|
27
|
+
* a separate REST poll. Cap at 200 entries — enough for the dashboard
|
|
28
|
+
* to show a meaningful "what just happened" feed without bloating
|
|
29
|
+
* process memory. */
|
|
30
|
+
recent = [];
|
|
31
|
+
static RECENT_CAP = 200;
|
|
32
|
+
constructor() {
|
|
33
|
+
super();
|
|
34
|
+
// EventEmitter defaults to 10 listeners before warning; we expect one
|
|
35
|
+
// handler per SSE connection plus a few internal subscribers, so 100
|
|
36
|
+
// is a comfortable cap that still flags accidental leaks.
|
|
37
|
+
this.setMaxListeners(100);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Publish a typed event. Listeners are called synchronously inside
|
|
41
|
+
* EventEmitter.emit; errors thrown from a listener are caught here so
|
|
42
|
+
* a bad subscriber can't break audit-log / approval-bus / job-board.
|
|
43
|
+
*/
|
|
44
|
+
publish(event) {
|
|
45
|
+
this.recent.push(event);
|
|
46
|
+
while (this.recent.length > ImhubEventBus.RECENT_CAP)
|
|
47
|
+
this.recent.shift();
|
|
48
|
+
try {
|
|
49
|
+
this.emit('event', event);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// EventEmitter normally rethrows — caller is in a hot path so we swallow.
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Snapshot of the recent ring buffer. Used by SSE handler on
|
|
56
|
+
* connection to replay the last N events to a fresh client. */
|
|
57
|
+
getRecent() {
|
|
58
|
+
return this.recent.slice();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export const eventBus = new ImhubEventBus();
|
|
62
|
+
//# sourceMappingURL=event-bus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../src/core/event-bus.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,2DAA2D;AAC3D,EAAE;AACF,6DAA6D;AAC7D,gBAAgB;AAChB,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,8BAA8B;AAC9B,qEAAqE;AACrE,wEAAwE;AACxE,0CAA0C;AAC1C,sEAAsE;AACtE,qEAAqE;AACrE,wEAAwE;AACxE,oEAAoE;AACpE,iCAAiC;AACjC,EAAE;AACF,qEAAqE;AACrE,wEAAwE;AACxE,uEAAuE;AACvE,sCAAsC;AAEtC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAgE1C,MAAM,aAAc,SAAQ,YAAY;IACtC;;;;0BAIsB;IACd,MAAM,GAAiB,EAAE,CAAA;IACzB,MAAM,CAAU,UAAU,GAAG,GAAG,CAAA;IAExC;QACE,KAAK,EAAE,CAAA;QACP,sEAAsE;QACtE,qEAAqE;QACrE,0DAA0D;QAC1D,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAA;IAC3B,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,KAAiB;QACvB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,aAAa,CAAC,UAAU;YAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACzE,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;QAC5E,CAAC;IACH,CAAC;IAED;oEACgE;IAChE,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;IAC5B,CAAC;;AAGH,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AgentAdapter } from './types.js';
|
|
2
|
+
export interface LLMJudgeConfig {
|
|
3
|
+
/** Agent name used as the judge. Must already be registered. */
|
|
4
|
+
agentName: string;
|
|
5
|
+
/** Score threshold below which the LLM is consulted (default 1.0). */
|
|
6
|
+
threshold?: number;
|
|
7
|
+
/** Override the default 5s response timeout. */
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function configureLLMJudge(cfg: LLMJudgeConfig | null): void;
|
|
11
|
+
/** Read the judge configuration. Used by classifyIntent to know whether
|
|
12
|
+
* to attempt a fallback at all. */
|
|
13
|
+
export declare function getLLMJudge(): LLMJudgeConfig | null;
|
|
14
|
+
/**
|
|
15
|
+
* Ask the judge agent which candidate to use. Returns null on any
|
|
16
|
+
* failure path (timeout, judge unavailable, malformed response) so
|
|
17
|
+
* the caller can keep its rule-based decision.
|
|
18
|
+
*/
|
|
19
|
+
export declare function classifyWithLLM(text: string, candidates: string[], resolveAgent: (name: string) => AgentAdapter | undefined): Promise<{
|
|
20
|
+
agent: string;
|
|
21
|
+
reason: string;
|
|
22
|
+
} | null>;
|
|
23
|
+
/** Test-only: clear cache so memoization doesn't leak between cases. */
|
|
24
|
+
export declare function _clearLLMCache(): void;
|
|
25
|
+
/** Test/diagnostic: current cache size. */
|
|
26
|
+
export declare function _cacheSize(): number;
|
|
27
|
+
//# sourceMappingURL=intent-llm.d.ts.map
|