lua-cli 3.5.0-alpha.2 ā 3.5.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -689
- package/dist/api/agent.api.service.d.ts +1 -8
- package/dist/api/agent.api.service.js +1 -11
- package/dist/api/agent.api.service.js.map +1 -1
- package/dist/api/auth.api.service.d.ts +1 -1
- package/dist/api/auth.api.service.js +1 -1
- package/dist/api/auth.api.service.js.map +1 -1
- package/dist/api/backup.api.service.d.ts +80 -0
- package/dist/api/backup.api.service.js +101 -0
- package/dist/api/backup.api.service.js.map +1 -0
- package/dist/api/basket.api.service.d.ts +4 -5
- package/dist/api/basket.api.service.js +13 -18
- package/dist/api/basket.api.service.js.map +1 -1
- package/dist/api/cdn.api.service.d.ts +2 -0
- package/dist/api/cdn.api.service.js +2 -0
- package/dist/api/cdn.api.service.js.map +1 -1
- package/dist/api/chat.api.service.d.ts +10 -2
- package/dist/api/chat.api.service.js +21 -2
- package/dist/api/chat.api.service.js.map +1 -1
- package/dist/api/credentials.js +5 -8
- package/dist/api/credentials.js.map +1 -1
- package/dist/api/custom.data.api.service.d.ts +3 -3
- package/dist/api/custom.data.api.service.js +9 -10
- package/dist/api/custom.data.api.service.js.map +1 -1
- package/dist/api/developer.api.service.d.ts +1 -1
- package/dist/api/developer.api.service.js +1 -1
- package/dist/api/developer.api.service.js.map +1 -1
- package/dist/api/http.client.js.map +1 -0
- package/dist/api/job.api.service.d.ts +2 -2
- package/dist/api/job.api.service.js +2 -2
- package/dist/api/job.api.service.js.map +1 -1
- package/dist/api/logs.api.service.d.ts +1 -1
- package/dist/api/logs.api.service.js +1 -1
- package/dist/api/logs.api.service.js.map +1 -1
- package/dist/api/marketplace.api.service.d.ts +6 -6
- package/dist/api/marketplace.api.service.js.map +1 -1
- package/dist/api/order.api.service.d.ts +3 -4
- package/dist/api/order.api.service.js +8 -10
- package/dist/api/order.api.service.js.map +1 -1
- package/dist/api/persona.api.service.d.ts +1 -1
- package/dist/api/persona.api.service.js +1 -1
- package/dist/api/persona.api.service.js.map +1 -1
- package/dist/api/postprocessor.api.service.d.ts +1 -1
- package/dist/api/postprocessor.api.service.js +1 -1
- package/dist/api/postprocessor.api.service.js.map +1 -1
- package/dist/api/preprocessor.api.service.d.ts +1 -1
- package/dist/api/preprocessor.api.service.js +1 -1
- package/dist/api/preprocessor.api.service.js.map +1 -1
- package/dist/api/products.api.service.d.ts +4 -4
- package/dist/api/products.api.service.js +6 -6
- package/dist/api/products.api.service.js.map +1 -1
- package/dist/api/resource.api.service.d.ts +76 -0
- package/dist/api/resource.api.service.js +74 -0
- package/dist/api/resource.api.service.js.map +1 -0
- package/dist/api/skills.api.service.d.ts +7 -15
- package/dist/api/skills.api.service.js +1 -1
- package/dist/api/skills.api.service.js.map +1 -1
- package/dist/api/tool.api.service.d.ts +1 -1
- package/dist/api/tool.api.service.js +1 -1
- package/dist/api/tool.api.service.js.map +1 -1
- package/dist/api/unifiedto.api.service.d.ts +7 -1
- package/dist/api/unifiedto.api.service.js +9 -1
- package/dist/api/unifiedto.api.service.js.map +1 -1
- package/dist/api/user.data.api.service.d.ts +7 -8
- package/dist/api/user.data.api.service.js +2 -3
- package/dist/api/user.data.api.service.js.map +1 -1
- package/dist/api/webhook.api.service.d.ts +1 -1
- package/dist/api/webhook.api.service.js +2 -2
- package/dist/api/webhook.api.service.js.map +1 -1
- package/dist/api/whatsapp-templates.api.service.d.ts +1 -1
- package/dist/api/whatsapp-templates.api.service.js +1 -1
- package/dist/api/whatsapp-templates.api.service.js.map +1 -1
- package/dist/api-exports.d.ts +14 -12
- package/dist/api-exports.js +8 -8
- package/dist/api-exports.js.map +1 -1
- package/dist/cli/command-definitions.js +63 -39
- package/dist/cli/command-definitions.js.map +1 -1
- package/dist/commands/admin.js +3 -24
- package/dist/commands/admin.js.map +1 -1
- package/dist/commands/agents.d.ts +8 -7
- package/dist/commands/agents.js +63 -21
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/channels.js +11 -23
- package/dist/commands/channels.js.map +1 -1
- package/dist/commands/chat.js +33 -47
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/chatClear.js +11 -41
- package/dist/commands/chatClear.js.map +1 -1
- package/dist/commands/compile.d.ts +26 -23
- package/dist/commands/compile.js +98 -403
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/completion.js +1 -1
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/deploy.js +55 -25
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.js +29 -45
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/env.js +12 -25
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/evals.js +3 -20
- package/dist/commands/evals.js.map +1 -1
- package/dist/commands/features.js +10 -23
- package/dist/commands/features.js.map +1 -1
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.js +1 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +135 -19
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/integrations.d.ts +2 -2
- package/dist/commands/integrations.js +761 -158
- package/dist/commands/integrations.js.map +1 -1
- package/dist/commands/jobs.js +32 -56
- package/dist/commands/jobs.js.map +1 -1
- package/dist/commands/logs.js +9 -20
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/marketplace.js +34 -52
- package/dist/commands/marketplace.js.map +1 -1
- package/dist/commands/mcp.js +10 -23
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/persona.js +43 -74
- package/dist/commands/persona.js.map +1 -1
- package/dist/commands/postprocessors.js +15 -28
- package/dist/commands/postprocessors.js.map +1 -1
- package/dist/commands/preprocessors.js +15 -28
- package/dist/commands/preprocessors.js.map +1 -1
- package/dist/commands/production.js +30 -63
- package/dist/commands/production.js.map +1 -1
- package/dist/commands/push.js +350 -1308
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/pushBackup.d.ts +22 -0
- package/dist/commands/pushBackup.js +133 -0
- package/dist/commands/pushBackup.js.map +1 -0
- package/dist/commands/resources.js +29 -72
- package/dist/commands/resources.js.map +1 -1
- package/dist/commands/skills.d.ts +1 -1
- package/dist/commands/skills.js +58 -70
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/sync.d.ts +1 -3
- package/dist/commands/sync.js +12 -24
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/test.js +135 -104
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/webhooks.js +15 -28
- package/dist/commands/webhooks.js.map +1 -1
- package/dist/compiler/agent-traverser.d.ts +104 -0
- package/dist/compiler/agent-traverser.js +311 -0
- package/dist/compiler/agent-traverser.js.map +1 -0
- package/dist/compiler/bundler.d.ts +42 -0
- package/dist/compiler/bundler.js +187 -0
- package/dist/compiler/bundler.js.map +1 -0
- package/dist/compiler/compiler.d.ts +177 -0
- package/dist/compiler/compiler.js +580 -0
- package/dist/compiler/compiler.js.map +1 -0
- package/dist/compiler/index.d.ts +36 -0
- package/dist/compiler/index.js +42 -0
- package/dist/compiler/index.js.map +1 -0
- package/dist/compiler/plugins/base.d.ts +264 -0
- package/dist/compiler/plugins/base.js +307 -0
- package/dist/compiler/plugins/base.js.map +1 -0
- package/dist/compiler/plugins/job.plugin.d.ts +33 -0
- package/dist/compiler/plugins/job.plugin.js +143 -0
- package/dist/compiler/plugins/job.plugin.js.map +1 -0
- package/dist/compiler/plugins/mcp-server.plugin.d.ts +50 -0
- package/dist/compiler/plugins/mcp-server.plugin.js +186 -0
- package/dist/compiler/plugins/mcp-server.plugin.js.map +1 -0
- package/dist/compiler/plugins/postprocessor.plugin.d.ts +20 -0
- package/dist/compiler/plugins/postprocessor.plugin.js +39 -0
- package/dist/compiler/plugins/postprocessor.plugin.js.map +1 -0
- package/dist/compiler/plugins/preprocessor.plugin.d.ts +20 -0
- package/dist/compiler/plugins/preprocessor.plugin.js +48 -0
- package/dist/compiler/plugins/preprocessor.plugin.js.map +1 -0
- package/dist/compiler/plugins/processor-base.d.ts +16 -0
- package/dist/compiler/plugins/processor-base.js +34 -0
- package/dist/compiler/plugins/processor-base.js.map +1 -0
- package/dist/compiler/plugins/registry.d.ts +61 -0
- package/dist/compiler/plugins/registry.js +107 -0
- package/dist/compiler/plugins/registry.js.map +1 -0
- package/dist/compiler/plugins/skill.plugin.d.ts +71 -0
- package/dist/compiler/plugins/skill.plugin.js +243 -0
- package/dist/compiler/plugins/skill.plugin.js.map +1 -0
- package/dist/compiler/plugins/tool.plugin.d.ts +67 -0
- package/dist/compiler/plugins/tool.plugin.js +279 -0
- package/dist/compiler/plugins/tool.plugin.js.map +1 -0
- package/dist/compiler/plugins/webhook.plugin.d.ts +37 -0
- package/dist/compiler/plugins/webhook.plugin.js +127 -0
- package/dist/compiler/plugins/webhook.plugin.js.map +1 -0
- package/dist/compiler/source-writer.d.ts +98 -0
- package/dist/compiler/source-writer.js +223 -0
- package/dist/compiler/source-writer.js.map +1 -0
- package/dist/compiler/types.d.ts +289 -0
- package/dist/compiler/types.js +20 -0
- package/dist/compiler/types.js.map +1 -0
- package/dist/compiler/utils/ast-helpers.d.ts +57 -0
- package/dist/compiler/utils/ast-helpers.js +164 -0
- package/dist/compiler/utils/ast-helpers.js.map +1 -0
- package/dist/compiler/utils/common.d.ts +23 -0
- package/dist/compiler/utils/common.js +66 -0
- package/dist/compiler/utils/common.js.map +1 -0
- package/dist/compiler/utils/file-discovery.d.ts +34 -0
- package/dist/compiler/utils/file-discovery.js +68 -0
- package/dist/compiler/utils/file-discovery.js.map +1 -0
- package/dist/compiler/utils/path-resolver.d.ts +25 -0
- package/dist/compiler/utils/path-resolver.js +66 -0
- package/dist/compiler/utils/path-resolver.js.map +1 -0
- package/dist/compiler/utils/schema-converter.d.ts +26 -0
- package/dist/compiler/utils/schema-converter.js +94 -0
- package/dist/compiler/utils/schema-converter.js.map +1 -0
- package/dist/config/compile.constants.d.ts +2 -22
- package/dist/config/compile.constants.js +2 -49
- package/dist/config/compile.constants.js.map +1 -1
- package/dist/config/constants.d.ts +18 -2
- package/dist/config/constants.js +28 -8
- package/dist/config/constants.js.map +1 -1
- package/dist/config/dev.constants.d.ts +0 -10
- package/dist/config/dev.constants.js +0 -10
- package/dist/config/dev.constants.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/instances/basket.instance.js.map +1 -0
- package/dist/instances/data.entry.instance.js.map +1 -0
- package/dist/instances/job.instance.js.map +1 -0
- package/dist/instances/order.instance.js.map +1 -0
- package/dist/instances/product.instance.js.map +1 -0
- package/dist/instances/product.pagination.instance.js.map +1 -0
- package/dist/instances/product.search.instance.js.map +1 -0
- package/dist/instances/user.instance.js.map +1 -0
- package/dist/interfaces/admin.d.ts +0 -38
- package/dist/interfaces/backup.d.ts +125 -0
- package/dist/interfaces/backup.js +8 -0
- package/dist/interfaces/backup.js.map +1 -0
- package/dist/interfaces/baskets.d.ts +0 -56
- package/dist/interfaces/common.d.ts +1 -0
- package/dist/interfaces/deploy.d.ts +0 -15
- package/dist/interfaces/index.d.ts +1 -1
- package/dist/interfaces/marketplace.d.ts +51 -0
- package/dist/interfaces/marketplace.js +1 -1
- package/dist/interfaces/marketplace.js.map +1 -1
- package/dist/interfaces/message.d.ts +0 -3
- package/dist/interfaces/orders.d.ts +0 -24
- package/dist/interfaces/postprocessors.d.ts +0 -18
- package/dist/interfaces/preprocessors.d.ts +0 -18
- package/dist/interfaces/skills.d.ts +61 -0
- package/dist/interfaces/unifiedto.d.ts +4 -0
- package/dist/interfaces/user.d.ts +25 -0
- package/dist/interfaces/webhooks.d.ts +0 -9
- package/dist/primitives/base.handler.d.ts +106 -0
- package/dist/primitives/base.handler.js +370 -0
- package/dist/primitives/base.handler.js.map +1 -0
- package/dist/primitives/index.d.ts +47 -0
- package/dist/primitives/index.js +78 -0
- package/dist/primitives/index.js.map +1 -0
- package/dist/primitives/job.handler.d.ts +52 -0
- package/dist/primitives/job.handler.js +118 -0
- package/dist/primitives/job.handler.js.map +1 -0
- package/dist/primitives/mcp-server.handler.d.ts +54 -0
- package/dist/primitives/mcp-server.handler.js +91 -0
- package/dist/primitives/mcp-server.handler.js.map +1 -0
- package/dist/primitives/postprocessor.handler.d.ts +49 -0
- package/dist/primitives/postprocessor.handler.js +81 -0
- package/dist/primitives/postprocessor.handler.js.map +1 -0
- package/dist/primitives/preprocessor.handler.d.ts +54 -0
- package/dist/primitives/preprocessor.handler.js +95 -0
- package/dist/primitives/preprocessor.handler.js.map +1 -0
- package/dist/primitives/skill.handler.d.ts +44 -0
- package/dist/primitives/skill.handler.js +192 -0
- package/dist/primitives/skill.handler.js.map +1 -0
- package/dist/primitives/types.d.ts +72 -0
- package/dist/primitives/types.js +17 -0
- package/dist/primitives/types.js.map +1 -0
- package/dist/primitives/webhook.handler.d.ts +50 -0
- package/dist/primitives/webhook.handler.js +96 -0
- package/dist/primitives/webhook.handler.js.map +1 -0
- package/dist/services/auth.js +1 -2
- package/dist/services/auth.js.map +1 -1
- package/dist/services/sandbox.service.d.ts +103 -0
- package/dist/services/sandbox.service.js +479 -0
- package/dist/services/sandbox.service.js.map +1 -0
- package/dist/types/api-contracts.d.ts +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/skill.d.ts +8 -2
- package/dist/types/skill.js +8 -0
- package/dist/types/skill.js.map +1 -1
- package/dist/types/yaml.types.d.ts +69 -0
- package/dist/types/yaml.types.js +6 -0
- package/dist/types/yaml.types.js.map +1 -0
- package/dist/utils/artifact-loader.d.ts +108 -0
- package/dist/utils/artifact-loader.js +188 -0
- package/dist/utils/artifact-loader.js.map +1 -0
- package/dist/utils/backup-helpers.d.ts +122 -0
- package/dist/utils/backup-helpers.js +274 -0
- package/dist/utils/backup-helpers.js.map +1 -0
- package/dist/utils/cli.d.ts +8 -0
- package/dist/utils/cli.js +19 -2
- package/dist/utils/cli.js.map +1 -1
- package/dist/utils/command-utils.d.ts +42 -0
- package/dist/utils/command-utils.js +83 -0
- package/dist/utils/command-utils.js.map +1 -0
- package/dist/utils/deploy-helpers.d.ts +0 -29
- package/dist/utils/deploy-helpers.js +0 -70
- package/dist/utils/deploy-helpers.js.map +1 -1
- package/dist/utils/dev-api.d.ts +3 -99
- package/dist/utils/dev-api.js +3 -430
- package/dist/utils/dev-api.js.map +1 -1
- package/dist/utils/dev-server.d.ts +3 -1
- package/dist/utils/dev-server.js +69 -145
- package/dist/utils/dev-server.js.map +1 -1
- package/dist/utils/dev-watcher.d.ts +0 -1
- package/dist/utils/dev-watcher.js +23 -8
- package/dist/utils/dev-watcher.js.map +1 -1
- package/dist/utils/env-loader.utils.d.ts +10 -1
- package/dist/utils/env-loader.utils.js +39 -31
- package/dist/utils/env-loader.utils.js.map +1 -1
- package/dist/utils/files.d.ts +47 -3
- package/dist/utils/files.js +98 -40
- package/dist/utils/files.js.map +1 -1
- package/dist/utils/init-agent.js +1 -2
- package/dist/utils/init-agent.js.map +1 -1
- package/dist/utils/init-helpers.d.ts +2 -10
- package/dist/utils/init-helpers.js +9 -17
- package/dist/utils/init-helpers.js.map +1 -1
- package/dist/utils/init-prompts.d.ts +0 -8
- package/dist/utils/init-prompts.js +0 -22
- package/dist/utils/init-prompts.js.map +1 -1
- package/dist/utils/prompt-handler.d.ts +3 -0
- package/dist/utils/prompt-handler.js +13 -0
- package/dist/utils/prompt-handler.js.map +1 -1
- package/dist/utils/sandbox-storage.d.ts +6 -5
- package/dist/utils/sandbox-storage.js +12 -12
- package/dist/utils/sandbox-storage.js.map +1 -1
- package/dist/utils/sandbox.d.ts +7 -30
- package/dist/utils/sandbox.js +247 -223
- package/dist/utils/sandbox.js.map +1 -1
- package/dist/utils/semver.d.ts +12 -0
- package/dist/utils/semver.js +23 -0
- package/dist/utils/semver.js.map +1 -1
- package/dist/utils/sync-display.d.ts +9 -0
- package/dist/utils/sync-display.js +67 -0
- package/dist/utils/sync-display.js.map +1 -0
- package/dist/utils/sync-fetch.d.ts +23 -0
- package/dist/utils/sync-fetch.js +64 -0
- package/dist/utils/sync-fetch.js.map +1 -0
- package/dist/utils/sync-helpers.d.ts +4 -59
- package/dist/utils/sync-helpers.js +4 -206
- package/dist/utils/sync-helpers.js.map +1 -1
- package/dist/web/app.css +912 -186
- package/dist/web/app.js +46 -46
- package/docs/API_INDEX.md +100 -0
- package/docs/API_REFERENCE.md +773 -0
- package/docs/CLI_REFERENCE.md +924 -0
- package/docs/GETTING_STARTED.md +862 -0
- package/docs/README.md +270 -0
- package/docs/api/AI.md +882 -0
- package/docs/api/Baskets.md +511 -0
- package/docs/api/CDN.md +524 -0
- package/docs/api/Data.md +446 -0
- package/docs/api/Jobs.md +524 -0
- package/docs/api/LuaAgent.md +454 -0
- package/docs/api/LuaJob.md +604 -0
- package/docs/api/LuaSkill.md +396 -0
- package/docs/api/LuaTool.md +521 -0
- package/docs/api/LuaWebhook.md +601 -0
- package/docs/api/Orders.md +514 -0
- package/docs/api/PostProcessor.md +565 -0
- package/docs/api/PreProcessor.md +630 -0
- package/docs/api/Products.md +507 -0
- package/docs/api/Templates.md +662 -0
- package/docs/api/User.md +567 -0
- package/docs/archive/DEVELOPMENT_GUIDE_V1.md +1294 -0
- package/docs/compiler-v2/ASSESSMENT.md +205 -0
- package/docs/compiler-v2/TEST_PLAN.md +306 -0
- package/package.json +3 -7
- package/template/package.json +1 -1
- package/template/tsconfig.json +1 -1
- package/dist/common/basket.instance.js.map +0 -1
- package/dist/common/data.entry.instance.js.map +0 -1
- package/dist/common/http.client.js.map +0 -1
- package/dist/common/job.instance.js.map +0 -1
- package/dist/common/order.instance.js.map +0 -1
- package/dist/common/product.instance.js.map +0 -1
- package/dist/common/product.pagination.instance.js.map +0 -1
- package/dist/common/product.search.instance.js.map +0 -1
- package/dist/common/user.instance.js.map +0 -1
- package/dist/config/auth.constants.d.ts +0 -11
- package/dist/config/auth.constants.js +0 -12
- package/dist/config/auth.constants.js.map +0 -1
- package/dist/config/init.constants.d.ts +0 -15
- package/dist/config/init.constants.js +0 -20
- package/dist/config/init.constants.js.map +0 -1
- package/dist/interfaces/compile.d.ts +0 -12
- package/dist/interfaces/compile.js +0 -5
- package/dist/interfaces/compile.js.map +0 -1
- package/dist/types/compile.types.d.ts +0 -131
- package/dist/types/compile.types.js +0 -6
- package/dist/types/compile.types.js.map +0 -1
- package/dist/utils/agent-code-utils.d.ts +0 -25
- package/dist/utils/agent-code-utils.js +0 -107
- package/dist/utils/agent-code-utils.js.map +0 -1
- package/dist/utils/bundling.d.ts +0 -89
- package/dist/utils/bundling.js +0 -1068
- package/dist/utils/bundling.js.map +0 -1
- package/dist/utils/compile.d.ts +0 -116
- package/dist/utils/compile.js +0 -1062
- package/dist/utils/compile.js.map +0 -1
- package/dist/utils/deploy-api.d.ts +0 -26
- package/dist/utils/deploy-api.js +0 -54
- package/dist/utils/deploy-api.js.map +0 -1
- package/dist/utils/deployment.d.ts +0 -26
- package/dist/utils/deployment.js +0 -218
- package/dist/utils/deployment.js.map +0 -1
- package/dist/utils/dev-helpers.d.ts +0 -47
- package/dist/utils/dev-helpers.js +0 -82
- package/dist/utils/dev-helpers.js.map +0 -1
- package/dist/utils/job-management.d.ts +0 -27
- package/dist/utils/job-management.js +0 -248
- package/dist/utils/job-management.js.map +0 -1
- package/dist/utils/mcp-server-management.d.ts +0 -26
- package/dist/utils/mcp-server-management.js +0 -197
- package/dist/utils/mcp-server-management.js.map +0 -1
- package/dist/utils/postprocessor-management.d.ts +0 -9
- package/dist/utils/postprocessor-management.js +0 -117
- package/dist/utils/postprocessor-management.js.map +0 -1
- package/dist/utils/pre-bundle-jobs.d.ts +0 -27
- package/dist/utils/pre-bundle-jobs.js +0 -189
- package/dist/utils/pre-bundle-jobs.js.map +0 -1
- package/dist/utils/preprocessor-management.d.ts +0 -9
- package/dist/utils/preprocessor-management.js +0 -117
- package/dist/utils/preprocessor-management.js.map +0 -1
- package/dist/utils/push-api.d.ts +0 -15
- package/dist/utils/push-api.js +0 -49
- package/dist/utils/push-api.js.map +0 -1
- package/dist/utils/push-helpers.d.ts +0 -82
- package/dist/utils/push-helpers.js +0 -246
- package/dist/utils/push-helpers.js.map +0 -1
- package/dist/utils/skill-management.d.ts +0 -39
- package/dist/utils/skill-management.js +0 -299
- package/dist/utils/skill-management.js.map +0 -1
- package/dist/utils/test-helpers.d.ts +0 -33
- package/dist/utils/test-helpers.js +0 -84
- package/dist/utils/test-helpers.js.map +0 -1
- package/dist/utils/test-prompts.d.ts +0 -23
- package/dist/utils/test-prompts.js +0 -187
- package/dist/utils/test-prompts.js.map +0 -1
- package/dist/utils/tool-detection.d.ts +0 -19
- package/dist/utils/tool-detection.js +0 -125
- package/dist/utils/tool-detection.js.map +0 -1
- package/dist/utils/webhook-management.d.ts +0 -27
- package/dist/utils/webhook-management.js +0 -241
- package/dist/utils/webhook-management.js.map +0 -1
- /package/dist/{common ā api}/http.client.d.ts +0 -0
- /package/dist/{common ā api}/http.client.js +0 -0
- /package/dist/{common ā instances}/basket.instance.d.ts +0 -0
- /package/dist/{common ā instances}/basket.instance.js +0 -0
- /package/dist/{common ā instances}/data.entry.instance.d.ts +0 -0
- /package/dist/{common ā instances}/data.entry.instance.js +0 -0
- /package/dist/{common ā instances}/job.instance.d.ts +0 -0
- /package/dist/{common ā instances}/job.instance.js +0 -0
- /package/dist/{common ā instances}/order.instance.d.ts +0 -0
- /package/dist/{common ā instances}/order.instance.js +0 -0
- /package/dist/{common ā instances}/product.instance.d.ts +0 -0
- /package/dist/{common ā instances}/product.instance.js +0 -0
- /package/dist/{common ā instances}/product.pagination.instance.d.ts +0 -0
- /package/dist/{common ā instances}/product.pagination.instance.js +0 -0
- /package/dist/{common ā instances}/product.search.instance.d.ts +0 -0
- /package/dist/{common ā instances}/product.search.instance.js +0 -0
- /package/dist/{common ā instances}/user.instance.d.ts +0 -0
- /package/dist/{common ā instances}/user.instance.js +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Integrations Command
|
|
3
|
-
* Manages third-party
|
|
3
|
+
* Manages third-party integrations via Unified.to
|
|
4
4
|
*
|
|
5
5
|
* Core concepts:
|
|
6
6
|
* - Integration: A supported third-party service (e.g., Linear, Google Calendar)
|
|
7
|
-
* - Connection: An authenticated link between your agent and a specific
|
|
7
|
+
* - Connection: An authenticated link between your agent and a specific integration
|
|
8
8
|
* - MCP Server: Technical implementation that exposes connection tools to the agent (auto-managed)
|
|
9
9
|
*
|
|
10
10
|
* Flow:
|
|
@@ -17,21 +17,22 @@
|
|
|
17
17
|
import http from 'http';
|
|
18
18
|
import { URL } from 'url';
|
|
19
19
|
import open from 'open';
|
|
20
|
-
import { loadApiKey, checkApiKey } from '../services/auth.js';
|
|
21
|
-
import { readSkillConfig } from '../utils/files.js';
|
|
22
20
|
import { withErrorHandling, writeProgress, writeSuccess, writeInfo, writeError } from '../utils/cli.js';
|
|
23
21
|
import { BASE_URLS } from '../config/constants.js';
|
|
24
22
|
import { safePrompt } from '../utils/prompt-handler.js';
|
|
25
|
-
import {
|
|
23
|
+
import { initializeCommand } from '../utils/command-utils.js';
|
|
26
24
|
import DeveloperApi from '../api/developer.api.service.js';
|
|
27
25
|
import UnifiedToApi from '../api/unifiedto.api.service.js';
|
|
28
|
-
import { fetchServersCore, activateServerCore, deactivateServerCore } from './mcp.js';
|
|
26
|
+
import { fetchServersCore, activateServerCore, deactivateServerCore, } from './mcp.js';
|
|
29
27
|
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
30
28
|
// Configuration
|
|
31
29
|
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
32
30
|
const UNIFIED_MCP_BASE_URL = 'https://mcp-api.unified.to/mcp';
|
|
33
31
|
const CALLBACK_PORT = 19837; // Random high port for OAuth callback
|
|
34
32
|
const CALLBACK_URL = `http://localhost:${CALLBACK_PORT}/callback`;
|
|
33
|
+
// Webhook trigger configuration
|
|
34
|
+
const AGENT_WEBHOOK_URL = `${BASE_URLS.API}/webhook/unifiedto/data`;
|
|
35
|
+
const DEFAULT_VIRTUAL_WEBHOOK_INTERVAL = 60; // minutes
|
|
35
36
|
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
36
37
|
// Integration API Functions (via Lua API)
|
|
37
38
|
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
@@ -98,7 +99,7 @@ function startCallbackServer(timeoutMs = 300000) {
|
|
|
98
99
|
<body style="font-family: system-ui; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #1a1a2e;">
|
|
99
100
|
<div style="text-align: center; color: white;">
|
|
100
101
|
<h1 style="color: #4ade80;">ā
Connection Successful!</h1>
|
|
101
|
-
<p style="color: #ccc;">Your
|
|
102
|
+
<p style="color: #ccc;">Your integration has been connected.</p>
|
|
102
103
|
<p style="color: #888;">You can close this window and return to the terminal.</p>
|
|
103
104
|
</div>
|
|
104
105
|
</body>
|
|
@@ -135,21 +136,12 @@ function startCallbackServer(timeoutMs = 300000) {
|
|
|
135
136
|
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
136
137
|
export async function integrationsCommand(action, subaction, cmdObj) {
|
|
137
138
|
return withErrorHandling(async () => {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const agentId = config.agent.agentId;
|
|
142
|
-
const apiKey = await loadApiKey();
|
|
143
|
-
if (!apiKey) {
|
|
144
|
-
console.error("ā No API key found. Please run 'lua auth configure' to set up your API key.");
|
|
145
|
-
process.exit(1);
|
|
146
|
-
}
|
|
147
|
-
const userData = await checkApiKey(apiKey);
|
|
148
|
-
writeProgress("ā
Authenticated with Lua");
|
|
149
|
-
const userId = userData.admin?.userId;
|
|
139
|
+
// Initialize command (validates config + auth)
|
|
140
|
+
const { agentId, apiKey, userData } = await initializeCommand({ showProgress: false });
|
|
141
|
+
const userId = userData?.admin?.userId;
|
|
150
142
|
if (!userId) {
|
|
151
143
|
console.error("ā Failed to get user ID from authentication.");
|
|
152
|
-
|
|
144
|
+
throw new Error("Failed to get user ID from authentication.");
|
|
153
145
|
}
|
|
154
146
|
const developerApi = new DeveloperApi(BASE_URLS.API, apiKey, agentId);
|
|
155
147
|
const unifiedToApi = new UnifiedToApi(BASE_URLS.API, apiKey);
|
|
@@ -182,7 +174,13 @@ async function executeNonInteractive(context, action, cmdOptions) {
|
|
|
182
174
|
authMethod: cmdOptions?.authMethod,
|
|
183
175
|
scopes: cmdOptions?.scopes,
|
|
184
176
|
hideSensitive: cmdOptions?.hideSensitive !== 'false', // Default true, only false if explicitly set
|
|
177
|
+
// Trigger options
|
|
178
|
+
triggers: cmdOptions?.triggers,
|
|
179
|
+
customWebhook: cmdOptions?.customWebhook === true,
|
|
180
|
+
hookUrl: cmdOptions?.hookUrl,
|
|
185
181
|
};
|
|
182
|
+
// Check for JSON output flag
|
|
183
|
+
const jsonOutput = cmdOptions?.json === true;
|
|
186
184
|
switch (normalizedAction) {
|
|
187
185
|
case 'connect':
|
|
188
186
|
await connectIntegrationFlow(context, options);
|
|
@@ -191,7 +189,7 @@ async function executeNonInteractive(context, action, cmdOptions) {
|
|
|
191
189
|
if (!options.integration) {
|
|
192
190
|
console.error("ā --integration is required for update");
|
|
193
191
|
console.log("\nš” Run 'lua integrations list' to see connected integrations");
|
|
194
|
-
|
|
192
|
+
throw new Error("--integration is required for update");
|
|
195
193
|
}
|
|
196
194
|
await updateConnectionFlow(context, options);
|
|
197
195
|
break;
|
|
@@ -201,11 +199,23 @@ async function executeNonInteractive(context, action, cmdOptions) {
|
|
|
201
199
|
case 'available':
|
|
202
200
|
await listAvailableIntegrations(context);
|
|
203
201
|
break;
|
|
202
|
+
case 'info':
|
|
203
|
+
// New command: Show detailed info about an integration type
|
|
204
|
+
// Integration type can be passed as positional arg (info <type>) or as --integration flag
|
|
205
|
+
const infoIntegrationType = options.integration || cmdOptions?._?.[0];
|
|
206
|
+
if (!infoIntegrationType) {
|
|
207
|
+
console.error("ā Integration type is required");
|
|
208
|
+
console.log("\nUsage: lua integrations info <type>");
|
|
209
|
+
console.log(" lua integrations info <type> --json");
|
|
210
|
+
throw new Error("Integration type is required");
|
|
211
|
+
}
|
|
212
|
+
await showIntegrationInfo(context, infoIntegrationType, jsonOutput);
|
|
213
|
+
break;
|
|
204
214
|
case 'disconnect':
|
|
205
215
|
if (!options.connectionId) {
|
|
206
216
|
console.error("ā --connection-id is required for disconnect");
|
|
207
217
|
console.log("\nš” Run 'lua integrations list' to see connection IDs");
|
|
208
|
-
|
|
218
|
+
throw new Error("--connection-id is required for disconnect");
|
|
209
219
|
}
|
|
210
220
|
await disconnectIntegration(context, options.connectionId);
|
|
211
221
|
break;
|
|
@@ -218,7 +228,7 @@ async function executeNonInteractive(context, action, cmdOptions) {
|
|
|
218
228
|
default:
|
|
219
229
|
console.error(`ā Invalid action: "${action}"`);
|
|
220
230
|
showUsage();
|
|
221
|
-
|
|
231
|
+
throw new Error("Invalid action:");
|
|
222
232
|
}
|
|
223
233
|
}
|
|
224
234
|
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
@@ -228,7 +238,7 @@ async function interactiveIntegrationsManagement(context) {
|
|
|
228
238
|
let continueManaging = true;
|
|
229
239
|
while (continueManaging) {
|
|
230
240
|
console.log("\n" + "=".repeat(60));
|
|
231
|
-
console.log("š
|
|
241
|
+
console.log("š Integrations");
|
|
232
242
|
console.log("=".repeat(60) + "\n");
|
|
233
243
|
const actionAnswer = await safePrompt([
|
|
234
244
|
{
|
|
@@ -236,13 +246,13 @@ async function interactiveIntegrationsManagement(context) {
|
|
|
236
246
|
name: 'action',
|
|
237
247
|
message: 'What would you like to do?',
|
|
238
248
|
choices: [
|
|
239
|
-
{ name: 'ā Connect a new
|
|
249
|
+
{ name: 'ā Connect a new integration', value: 'connect' },
|
|
240
250
|
{ name: 'š Update connection scopes', value: 'update' },
|
|
241
|
-
{ name: 'š List connected
|
|
251
|
+
{ name: 'š List connected integrations', value: 'list' },
|
|
242
252
|
{ name: 'š View available integrations', value: 'available' },
|
|
243
|
-
{ name: 'š Manage
|
|
253
|
+
{ name: 'š Manage triggers', value: 'webhooks' },
|
|
244
254
|
{ name: 'š Manage MCP servers', value: 'mcp' },
|
|
245
|
-
{ name: 'šļø Disconnect an
|
|
255
|
+
{ name: 'šļø Disconnect an integration', value: 'disconnect' },
|
|
246
256
|
{ name: 'ā Exit', value: 'exit' }
|
|
247
257
|
]
|
|
248
258
|
}
|
|
@@ -319,6 +329,130 @@ async function listAvailableIntegrations(context) {
|
|
|
319
329
|
}
|
|
320
330
|
}
|
|
321
331
|
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
332
|
+
// Integration Info (Non-Interactive Discovery)
|
|
333
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
334
|
+
/**
|
|
335
|
+
* Show detailed information about an integration type
|
|
336
|
+
* Used for non-interactive discovery of OAuth scopes and webhook events
|
|
337
|
+
*/
|
|
338
|
+
async function showIntegrationInfo(context, integrationType, jsonOutput = false) {
|
|
339
|
+
try {
|
|
340
|
+
// Fetch integration details
|
|
341
|
+
const integrations = await fetchAvailableIntegrations(context.unifiedToApi);
|
|
342
|
+
const integration = integrations.find(i => i.value === integrationType);
|
|
343
|
+
if (!integration) {
|
|
344
|
+
if (jsonOutput) {
|
|
345
|
+
console.log(JSON.stringify({ error: `Integration not found: ${integrationType}` }));
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
console.error(`ā Integration not found: ${integrationType}`);
|
|
349
|
+
console.log('\nAvailable integrations:');
|
|
350
|
+
integrations.forEach(i => console.log(` - ${i.value} (${i.name})`));
|
|
351
|
+
}
|
|
352
|
+
throw new Error("Operation failed");
|
|
353
|
+
}
|
|
354
|
+
// Fetch available webhook events for this integration
|
|
355
|
+
let webhookEvents = [];
|
|
356
|
+
try {
|
|
357
|
+
const eventsResult = await context.unifiedToApi.getAvailableWebhookEventsByType(integrationType);
|
|
358
|
+
if (eventsResult.success && eventsResult.data) {
|
|
359
|
+
webhookEvents = eventsResult.data;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
catch {
|
|
363
|
+
// Silently ignore if webhook events can't be fetched
|
|
364
|
+
}
|
|
365
|
+
if (jsonOutput) {
|
|
366
|
+
// Output as JSON for scripting
|
|
367
|
+
const output = {
|
|
368
|
+
type: integration.value,
|
|
369
|
+
name: integration.name,
|
|
370
|
+
categories: integration.categories,
|
|
371
|
+
authSupport: integration.authSupport,
|
|
372
|
+
oauthConfigured: integration.oauthConfigured,
|
|
373
|
+
oauthScopes: integration.oauthScopes || [],
|
|
374
|
+
tokenFields: integration.tokenFields || [],
|
|
375
|
+
webhookEvents: webhookEvents.map(e => ({
|
|
376
|
+
trigger: `${e.objectType}.${e.event}`,
|
|
377
|
+
objectType: e.objectType,
|
|
378
|
+
event: e.event,
|
|
379
|
+
webhookType: e.webhookType,
|
|
380
|
+
friendlyLabel: e.friendlyLabel,
|
|
381
|
+
friendlyDescription: e.friendlyDescription,
|
|
382
|
+
availableFilters: e.availableFilters,
|
|
383
|
+
})),
|
|
384
|
+
webhookDefaults: {
|
|
385
|
+
agentWebhookUrl: AGENT_WEBHOOK_URL,
|
|
386
|
+
defaultVirtualInterval: DEFAULT_VIRTUAL_WEBHOOK_INTERVAL,
|
|
387
|
+
},
|
|
388
|
+
};
|
|
389
|
+
console.log(JSON.stringify(output, null, 2));
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
// Human-readable output
|
|
393
|
+
console.log("\n" + "=".repeat(60));
|
|
394
|
+
console.log(`š Integration: ${integration.name}`);
|
|
395
|
+
console.log("=".repeat(60));
|
|
396
|
+
console.log(`\n Type: ${integration.value}`);
|
|
397
|
+
console.log(` Categories: ${integration.categories.join(', ')}`);
|
|
398
|
+
console.log(` Auth Support: ${integration.authSupport}`);
|
|
399
|
+
console.log(` OAuth Configured: ${integration.oauthConfigured ? 'Yes' : 'No'}`);
|
|
400
|
+
// OAuth Scopes
|
|
401
|
+
if (integration.oauthScopes && integration.oauthScopes.length > 0) {
|
|
402
|
+
console.log('\n OAuth Scopes:');
|
|
403
|
+
integration.oauthScopes.forEach(s => {
|
|
404
|
+
if (s.friendlyLabel) {
|
|
405
|
+
console.log(` - ${s.friendlyLabel} (${s.unifiedScope})`);
|
|
406
|
+
if (s.friendlyDescription) {
|
|
407
|
+
console.log(` ${s.friendlyDescription}`);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
console.log(` - ${s.unifiedScope} ā [${s.originalScopes.join(', ')}]`);
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
// Token Fields
|
|
416
|
+
if (integration.tokenFields && integration.tokenFields.length > 0) {
|
|
417
|
+
console.log('\n Token Fields:');
|
|
418
|
+
integration.tokenFields.forEach(f => {
|
|
419
|
+
console.log(` - ${f.name}`);
|
|
420
|
+
if (f.instructions) {
|
|
421
|
+
console.log(` š” ${f.instructions}`);
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
// Webhook Events/Triggers
|
|
426
|
+
if (webhookEvents.length > 0) {
|
|
427
|
+
console.log('\n Available Triggers:');
|
|
428
|
+
webhookEvents.forEach(e => {
|
|
429
|
+
console.log(` - ${e.objectType}.${e.event} [${e.webhookType}] - ${e.friendlyDescription}`);
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
console.log('\n Available Triggers: None');
|
|
434
|
+
}
|
|
435
|
+
console.log("\n" + "=".repeat(60));
|
|
436
|
+
console.log("\nš” Use with non-interactive commands:");
|
|
437
|
+
console.log(` lua integrations connect --integration ${integrationType} --auth-method oauth --scopes all`);
|
|
438
|
+
if (webhookEvents.length > 0) {
|
|
439
|
+
const exampleTrigger = `${webhookEvents[0].objectType}.${webhookEvents[0].event}`;
|
|
440
|
+
console.log(` lua integrations connect --integration ${integrationType} --triggers ${exampleTrigger}`);
|
|
441
|
+
}
|
|
442
|
+
console.log();
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
catch (error) {
|
|
446
|
+
if (jsonOutput) {
|
|
447
|
+
console.log(JSON.stringify({ error: error.message }));
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
writeError(`ā Failed to get integration info: ${error.message}`);
|
|
451
|
+
}
|
|
452
|
+
throw new Error("Operation failed");
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
322
456
|
// Connect Flow
|
|
323
457
|
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
324
458
|
async function connectIntegrationFlow(context, options = {}) {
|
|
@@ -359,14 +493,14 @@ async function connectIntegrationFlow(context, options = {}) {
|
|
|
359
493
|
if (connectedTypes.has(options.integration)) {
|
|
360
494
|
console.error(`ā Integration "${options.integration}" is already connected.`);
|
|
361
495
|
console.log("š” Use 'lua integrations update --integration " + options.integration + "' to change scopes.\n");
|
|
362
|
-
|
|
496
|
+
throw new Error("Integration");
|
|
363
497
|
}
|
|
364
498
|
selectedIntegration = availableIntegrations.find(i => i.value === options.integration);
|
|
365
499
|
if (!selectedIntegration) {
|
|
366
500
|
console.error(`ā Integration "${options.integration}" not found or not available.`);
|
|
367
501
|
console.log('\nAvailable integrations to connect:');
|
|
368
502
|
availableIntegrations.forEach(i => console.log(` - ${i.value} (${i.name})`));
|
|
369
|
-
|
|
503
|
+
throw new Error("Integration");
|
|
370
504
|
}
|
|
371
505
|
}
|
|
372
506
|
else {
|
|
@@ -448,21 +582,21 @@ async function connectIntegrationFlow(context, options = {}) {
|
|
|
448
582
|
if (options.authMethod) {
|
|
449
583
|
if (!['oauth', 'token'].includes(options.authMethod)) {
|
|
450
584
|
console.error(`ā Invalid --auth-method: "${options.authMethod}". Use 'oauth' or 'token'`);
|
|
451
|
-
|
|
585
|
+
throw new Error("Invalid --auth-method:");
|
|
452
586
|
}
|
|
453
587
|
if (options.authMethod === 'oauth' && !canUseOAuth) {
|
|
454
588
|
console.error(`ā OAuth is not available for ${selectedIntegration.name}.`);
|
|
455
589
|
if (canUseToken) {
|
|
456
590
|
console.log(`š” Use --auth-method token instead.`);
|
|
457
591
|
}
|
|
458
|
-
|
|
592
|
+
throw new Error("Operation failed");
|
|
459
593
|
}
|
|
460
594
|
if (options.authMethod === 'token' && !canUseToken) {
|
|
461
595
|
console.error(`ā Token authentication is not available for ${selectedIntegration.name}.`);
|
|
462
596
|
if (canUseOAuth) {
|
|
463
597
|
console.log(`š” Use --auth-method oauth instead.`);
|
|
464
598
|
}
|
|
465
|
-
|
|
599
|
+
throw new Error("Operation failed");
|
|
466
600
|
}
|
|
467
601
|
authMethod = options.authMethod;
|
|
468
602
|
writeInfo(`Using ${authMethod === 'oauth' ? 'OAuth 2.0' : 'API Token'} authentication`);
|
|
@@ -513,7 +647,7 @@ async function connectIntegrationFlow(context, options = {}) {
|
|
|
513
647
|
console.error(`ā Invalid scopes: ${invalidScopes.join(', ')}`);
|
|
514
648
|
console.log(`\nAvailable scopes for ${selectedIntegration.name}:`);
|
|
515
649
|
availableScopes.forEach(s => console.log(` - ${s}`));
|
|
516
|
-
|
|
650
|
+
throw new Error("Invalid scopes: ${invalidScopes.join(");
|
|
517
651
|
}
|
|
518
652
|
selectedScopes = requestedScopes;
|
|
519
653
|
writeInfo(`Using ${selectedScopes.length} specified scope(s)`);
|
|
@@ -527,11 +661,18 @@ async function connectIntegrationFlow(context, options = {}) {
|
|
|
527
661
|
message: 'Select OAuth scopes (Space to toggle, Enter to confirm, leave empty for all):',
|
|
528
662
|
pageSize: 15,
|
|
529
663
|
loop: false,
|
|
530
|
-
choices: selectedIntegration.oauthScopes.map(s =>
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
664
|
+
choices: selectedIntegration.oauthScopes.map(s => {
|
|
665
|
+
// Use friendly label if available, otherwise fall back to technical name
|
|
666
|
+
const displayName = s.friendlyLabel || s.unifiedScope;
|
|
667
|
+
const description = s.friendlyDescription
|
|
668
|
+
? ` (${s.friendlyDescription})`
|
|
669
|
+
: ` ā [${s.originalScopes.join(', ')}]`;
|
|
670
|
+
return {
|
|
671
|
+
name: `${displayName}${description}`,
|
|
672
|
+
value: s.unifiedScope,
|
|
673
|
+
checked: false
|
|
674
|
+
};
|
|
675
|
+
})
|
|
535
676
|
}]);
|
|
536
677
|
if (!scopeAnswer)
|
|
537
678
|
return;
|
|
@@ -577,7 +718,132 @@ async function connectIntegrationFlow(context, options = {}) {
|
|
|
577
718
|
hideSensitive = sensitiveAnswer.hide;
|
|
578
719
|
}
|
|
579
720
|
}
|
|
580
|
-
// Step 4:
|
|
721
|
+
// Step 4: Select webhook triggers (agent wake-up events)
|
|
722
|
+
let selectedTriggers = [];
|
|
723
|
+
let webhookUrl = AGENT_WEBHOOK_URL; // Default: agent trigger mode
|
|
724
|
+
let isCustomWebhook = false;
|
|
725
|
+
try {
|
|
726
|
+
const eventsResult = await context.unifiedToApi.getAvailableWebhookEventsByType(selectedIntegration.value);
|
|
727
|
+
if (eventsResult.success && eventsResult.data && eventsResult.data.length > 0) {
|
|
728
|
+
const availableEvents = eventsResult.data;
|
|
729
|
+
// Determine webhook mode
|
|
730
|
+
if (options.customWebhook || options.hookUrl) {
|
|
731
|
+
isCustomWebhook = true;
|
|
732
|
+
if (options.hookUrl) {
|
|
733
|
+
webhookUrl = options.hookUrl;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
if (options.triggers) {
|
|
737
|
+
// Non-interactive: parse comma-separated triggers (e.g., 'task_task.created,task_task.updated')
|
|
738
|
+
const requestedTriggers = options.triggers.split(',').map(t => t.trim());
|
|
739
|
+
for (const trigger of requestedTriggers) {
|
|
740
|
+
const [objectType, event] = trigger.split('.');
|
|
741
|
+
const matchingEvent = availableEvents.find(e => e.objectType === objectType && e.event === event);
|
|
742
|
+
if (!matchingEvent) {
|
|
743
|
+
console.error(`ā Invalid trigger: ${trigger}`);
|
|
744
|
+
console.log(`\nAvailable triggers for ${selectedIntegration.name}:`);
|
|
745
|
+
availableEvents.forEach(e => {
|
|
746
|
+
console.log(` - ${e.objectType}.${e.event} [${e.webhookType}] - ${e.friendlyDescription}`);
|
|
747
|
+
});
|
|
748
|
+
throw new Error("Invalid trigger: ${trigger}");
|
|
749
|
+
}
|
|
750
|
+
selectedTriggers.push(matchingEvent);
|
|
751
|
+
}
|
|
752
|
+
writeInfo(`Selected ${selectedTriggers.length} trigger(s)`);
|
|
753
|
+
// If custom webhook mode, prompt for URL if not provided
|
|
754
|
+
if (isCustomWebhook && !options.hookUrl) {
|
|
755
|
+
const urlAnswer = await safePrompt([{
|
|
756
|
+
type: 'input',
|
|
757
|
+
name: 'url',
|
|
758
|
+
message: 'Enter your webhook URL:',
|
|
759
|
+
validate: (input) => {
|
|
760
|
+
try {
|
|
761
|
+
new URL(input);
|
|
762
|
+
return true;
|
|
763
|
+
}
|
|
764
|
+
catch {
|
|
765
|
+
return 'Please enter a valid URL';
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}]);
|
|
769
|
+
if (!urlAnswer)
|
|
770
|
+
return;
|
|
771
|
+
webhookUrl = urlAnswer.url;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
else {
|
|
775
|
+
// Interactive: show trigger selection
|
|
776
|
+
console.log('\n' + 'ā'.repeat(60));
|
|
777
|
+
console.log('š” Webhook Triggers');
|
|
778
|
+
console.log('ā'.repeat(60));
|
|
779
|
+
console.log('\nSelect events that will wake up your agent:');
|
|
780
|
+
console.log('(Space to toggle, Enter to confirm. All selected by default.)');
|
|
781
|
+
const triggerAnswer = await safePrompt([{
|
|
782
|
+
type: 'checkbox',
|
|
783
|
+
name: 'triggers',
|
|
784
|
+
message: 'Select triggers:',
|
|
785
|
+
pageSize: 15,
|
|
786
|
+
loop: false,
|
|
787
|
+
choices: availableEvents.map(e => ({
|
|
788
|
+
name: `${e.friendlyDescription} [${e.webhookType}]`,
|
|
789
|
+
value: e,
|
|
790
|
+
checked: true // Pre-select all by default
|
|
791
|
+
}))
|
|
792
|
+
}]);
|
|
793
|
+
if (triggerAnswer && triggerAnswer.triggers.length > 0) {
|
|
794
|
+
selectedTriggers = triggerAnswer.triggers;
|
|
795
|
+
// Ask about webhook mode only if triggers are selected
|
|
796
|
+
const modeAnswer = await safePrompt([{
|
|
797
|
+
type: 'list',
|
|
798
|
+
name: 'mode',
|
|
799
|
+
message: 'How should these events be handled?',
|
|
800
|
+
choices: [
|
|
801
|
+
{ name: 'š¤ Agent Trigger (recommended) - Events wake up your agent', value: 'agent' },
|
|
802
|
+
{ name: 'š Custom URL - Send events to your own webhook URL', value: 'custom' }
|
|
803
|
+
]
|
|
804
|
+
}]);
|
|
805
|
+
if (!modeAnswer)
|
|
806
|
+
return;
|
|
807
|
+
if (modeAnswer.mode === 'custom') {
|
|
808
|
+
isCustomWebhook = true;
|
|
809
|
+
const urlAnswer = await safePrompt([{
|
|
810
|
+
type: 'input',
|
|
811
|
+
name: 'url',
|
|
812
|
+
message: 'Enter your webhook URL:',
|
|
813
|
+
validate: (input) => {
|
|
814
|
+
try {
|
|
815
|
+
new URL(input);
|
|
816
|
+
return true;
|
|
817
|
+
}
|
|
818
|
+
catch {
|
|
819
|
+
return 'Please enter a valid URL';
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}]);
|
|
823
|
+
if (!urlAnswer)
|
|
824
|
+
return;
|
|
825
|
+
webhookUrl = urlAnswer.url;
|
|
826
|
+
}
|
|
827
|
+
console.log(`\nā ${selectedTriggers.length} trigger(s) selected`);
|
|
828
|
+
if (isCustomWebhook) {
|
|
829
|
+
console.log(` ā Events will be sent to: ${webhookUrl}`);
|
|
830
|
+
}
|
|
831
|
+
else {
|
|
832
|
+
console.log(` ā Events will wake up your agent`);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
else {
|
|
836
|
+
console.log(`\nāļø No triggers selected - your agent won't be event-driven`);
|
|
837
|
+
console.log(` You can add triggers later with: lua integrations webhooks create`);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
catch (error) {
|
|
843
|
+
// Non-fatal: continue without triggers if we can't fetch events
|
|
844
|
+
writeInfo(`Note: Could not fetch available triggers (${error.message})`);
|
|
845
|
+
}
|
|
846
|
+
// Step 5: Get authorization URL from Lua API
|
|
581
847
|
writeProgress("š Preparing authorization...");
|
|
582
848
|
const state = Buffer.from(JSON.stringify({
|
|
583
849
|
agentId: context.agentId,
|
|
@@ -642,22 +908,24 @@ async function connectIntegrationFlow(context, options = {}) {
|
|
|
642
908
|
const result = await callbackPromise;
|
|
643
909
|
if (result.success && result.connectionId) {
|
|
644
910
|
writeSuccess("\nā
Authorization successful!");
|
|
645
|
-
// Finalize the connection (sets up MCP server internally)
|
|
646
|
-
await finalizeConnection(context, selectedIntegration, result.connectionId, selectedScopes, hideSensitive
|
|
911
|
+
// Finalize the connection (sets up MCP server internally and creates webhooks)
|
|
912
|
+
await finalizeConnection(context, selectedIntegration, result.connectionId, selectedScopes, hideSensitive, {
|
|
913
|
+
triggers: selectedTriggers,
|
|
914
|
+
webhookUrl,
|
|
915
|
+
isCustomWebhook,
|
|
916
|
+
});
|
|
647
917
|
}
|
|
648
918
|
else {
|
|
649
919
|
writeError(`\nā Authorization failed: ${result.error || 'Unknown error'}`);
|
|
650
920
|
console.log("š” Please try again with 'lua integrations connect'\n");
|
|
651
921
|
}
|
|
652
922
|
}
|
|
653
|
-
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
654
|
-
// Connection Management
|
|
655
|
-
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
656
923
|
/**
|
|
657
|
-
* Finalizes a new connection by setting up the MCP server
|
|
924
|
+
* Finalizes a new connection by setting up the MCP server and creating webhooks
|
|
658
925
|
* The MCP server enables the agent to use tools from this connection
|
|
926
|
+
* Webhooks enable the agent to be triggered by events from the connection
|
|
659
927
|
*/
|
|
660
|
-
async function finalizeConnection(context, integration, connectionId, scopes, hideSensitive = true) {
|
|
928
|
+
async function finalizeConnection(context, integration, connectionId, scopes, hideSensitive = true, webhookConfig = { triggers: [], webhookUrl: '', isCustomWebhook: false }) {
|
|
661
929
|
writeProgress(`š Setting up ${integration.name} connection...`);
|
|
662
930
|
// Build MCP URL
|
|
663
931
|
let mcpUrl = `${UNIFIED_MCP_BASE_URL}?connection=${connectionId}`;
|
|
@@ -679,44 +947,154 @@ async function finalizeConnection(context, integration, connectionId, scopes, hi
|
|
|
679
947
|
source: 'unifiedto', // Flag for runtime auth injection
|
|
680
948
|
timeout: 30000,
|
|
681
949
|
};
|
|
950
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
951
|
+
// Step 1: Set up MCP Server (for tools)
|
|
952
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
953
|
+
let mcpSetupSuccess = false;
|
|
954
|
+
let isActive = false;
|
|
955
|
+
let mcpError = null;
|
|
682
956
|
try {
|
|
957
|
+
writeProgress(`š Setting up MCP server...`);
|
|
683
958
|
const result = await context.developerApi.createMCPServer(mcpServerData);
|
|
684
959
|
if (result.success && result.data) {
|
|
685
960
|
// Auto-activate the MCP server so the agent can use the connection immediately
|
|
686
961
|
const activateResult = await context.developerApi.activateMCPServer(result.data.id);
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
962
|
+
isActive = activateResult.success && activateResult.data?.active === true;
|
|
963
|
+
mcpSetupSuccess = true;
|
|
964
|
+
}
|
|
965
|
+
else {
|
|
966
|
+
mcpError = result.error?.message || 'Unknown error';
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
catch (error) {
|
|
970
|
+
mcpError = error.message || 'Unknown error';
|
|
971
|
+
}
|
|
972
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
973
|
+
// Step 2: Set up Webhook Triggers (for event-driven agent wake-up)
|
|
974
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
975
|
+
const createdWebhooks = [];
|
|
976
|
+
const failedWebhooks = [];
|
|
977
|
+
if (webhookConfig.triggers.length > 0) {
|
|
978
|
+
writeProgress(`š Setting up ${webhookConfig.triggers.length} trigger(s)...`);
|
|
979
|
+
for (const trigger of webhookConfig.triggers) {
|
|
980
|
+
try {
|
|
981
|
+
// Use per-trigger hookUrl/interval if available, otherwise fall back to defaults
|
|
982
|
+
const hookUrl = trigger.hookUrl || webhookConfig.webhookUrl || AGENT_WEBHOOK_URL;
|
|
983
|
+
const interval = trigger.interval ?? (trigger.webhookType === 'virtual' ? DEFAULT_VIRTUAL_WEBHOOK_INTERVAL : undefined);
|
|
984
|
+
const webhookResult = await context.unifiedToApi.createWebhookSubscription(context.agentId, {
|
|
985
|
+
connectionId,
|
|
986
|
+
objectType: trigger.objectType,
|
|
987
|
+
event: trigger.event,
|
|
988
|
+
hookUrl,
|
|
989
|
+
interval,
|
|
990
|
+
});
|
|
991
|
+
if (webhookResult.success && webhookResult.data) {
|
|
992
|
+
createdWebhooks.push(webhookResult.data);
|
|
993
|
+
}
|
|
994
|
+
else {
|
|
995
|
+
const errorMsg = webhookResult.error?.message || 'Unknown error';
|
|
996
|
+
failedWebhooks.push(`${trigger.objectType}.${trigger.event}: ${errorMsg}`);
|
|
997
|
+
}
|
|
699
998
|
}
|
|
700
|
-
|
|
701
|
-
|
|
999
|
+
catch (error) {
|
|
1000
|
+
const errorMsg = error?.message || 'Unknown error';
|
|
1001
|
+
failedWebhooks.push(`${trigger.objectType}.${trigger.event}: ${errorMsg}`);
|
|
702
1002
|
}
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
1006
|
+
// Step 3: Display Results
|
|
1007
|
+
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
1008
|
+
console.log("\n" + "ā".repeat(60));
|
|
1009
|
+
console.log("š Connection Established!");
|
|
1010
|
+
console.log("ā".repeat(60));
|
|
1011
|
+
console.log(`\n Integration: ${integration.name}`);
|
|
1012
|
+
console.log(` Connection ID: ${connectionId}`);
|
|
1013
|
+
// MCP Server status
|
|
1014
|
+
console.log(`\n š¦ MCP Server (Tools):`);
|
|
1015
|
+
if (mcpSetupSuccess) {
|
|
1016
|
+
console.log(` Status: ${isActive ? 'š¢ Active' : 'š” Pending activation'}`);
|
|
1017
|
+
console.log(` Name: ${serverName}`);
|
|
1018
|
+
console.log(` Hide Sensitive: ${hideSensitive ? 'ā
Yes' : 'ā No'}`);
|
|
1019
|
+
}
|
|
1020
|
+
else {
|
|
1021
|
+
console.log(` Status: ā Failed`);
|
|
1022
|
+
console.log(` Error: ${mcpError}`);
|
|
1023
|
+
}
|
|
1024
|
+
// Show requested scopes with friendly labels
|
|
1025
|
+
if (scopes.length > 0) {
|
|
1026
|
+
console.log(`\n š Permissions (${scopes.length}):`);
|
|
1027
|
+
scopes.forEach(scopeName => {
|
|
1028
|
+
const scopeInfo = integration.oauthScopes?.find(s => s.unifiedScope === scopeName);
|
|
1029
|
+
if (scopeInfo?.friendlyLabel) {
|
|
1030
|
+
console.log(` ⢠${scopeInfo.friendlyLabel}`);
|
|
707
1031
|
}
|
|
708
1032
|
else {
|
|
709
|
-
console.log(
|
|
1033
|
+
console.log(` ⢠${scopeName}`);
|
|
710
1034
|
}
|
|
711
|
-
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
else {
|
|
1038
|
+
console.log(`\n š Permissions: Default`);
|
|
1039
|
+
}
|
|
1040
|
+
// Webhook/Triggers status
|
|
1041
|
+
if (webhookConfig.triggers.length > 0) {
|
|
1042
|
+
console.log(`\n ā” Triggers (${createdWebhooks.length}/${webhookConfig.triggers.length}):`);
|
|
1043
|
+
// Compute actual URLs being used (per-trigger hookUrl or default)
|
|
1044
|
+
const actualUrls = webhookConfig.triggers.map(t => t.hookUrl || webhookConfig.webhookUrl || AGENT_WEBHOOK_URL);
|
|
1045
|
+
const uniqueUrls = [...new Set(actualUrls)];
|
|
1046
|
+
const allAgentTriggers = uniqueUrls.every(url => url === AGENT_WEBHOOK_URL);
|
|
1047
|
+
if (allAgentTriggers) {
|
|
1048
|
+
console.log(` Mode: Agent wake-up`);
|
|
1049
|
+
}
|
|
1050
|
+
else if (uniqueUrls.length === 1) {
|
|
1051
|
+
console.log(` Mode: Custom webhook`);
|
|
1052
|
+
console.log(` URL: ${uniqueUrls[0]}`);
|
|
1053
|
+
}
|
|
1054
|
+
else {
|
|
1055
|
+
console.log(` Mode: Mixed (per-trigger URLs)`);
|
|
1056
|
+
}
|
|
1057
|
+
if (createdWebhooks.length > 0) {
|
|
1058
|
+
createdWebhooks.forEach(wh => {
|
|
1059
|
+
const trigger = webhookConfig.triggers.find(t => t.objectType === wh.objectType && t.event === wh.event);
|
|
1060
|
+
const desc = trigger?.friendlyDescription || `${wh.objectType}.${wh.event}`;
|
|
1061
|
+
console.log(` ā ${desc}`);
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
if (failedWebhooks.length > 0) {
|
|
1065
|
+
failedWebhooks.forEach(t => console.log(` ā ${t}`));
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
// Summary message
|
|
1069
|
+
console.log("\n" + "ā".repeat(60));
|
|
1070
|
+
const capabilities = [];
|
|
1071
|
+
if (mcpSetupSuccess && isActive) {
|
|
1072
|
+
capabilities.push('tools via MCP');
|
|
1073
|
+
}
|
|
1074
|
+
if (createdWebhooks.length > 0) {
|
|
1075
|
+
// Check if any triggers use custom URLs
|
|
1076
|
+
const hasCustomUrls = webhookConfig.triggers.some(t => {
|
|
1077
|
+
const url = t.hookUrl || webhookConfig.webhookUrl || AGENT_WEBHOOK_URL;
|
|
1078
|
+
return url !== AGENT_WEBHOOK_URL;
|
|
1079
|
+
});
|
|
1080
|
+
if (hasCustomUrls) {
|
|
1081
|
+
capabilities.push('webhooks to custom URL');
|
|
712
1082
|
}
|
|
713
1083
|
else {
|
|
714
|
-
|
|
1084
|
+
capabilities.push('event-driven triggers');
|
|
715
1085
|
}
|
|
716
1086
|
}
|
|
717
|
-
|
|
718
|
-
|
|
1087
|
+
if (capabilities.length > 0) {
|
|
1088
|
+
console.log(`ā
${integration.name} connected! Your agent now has: ${capabilities.join(', ')}`);
|
|
1089
|
+
}
|
|
1090
|
+
else if (mcpSetupSuccess && !isActive) {
|
|
1091
|
+
console.log(`ā ļø Connection created but MCP server pending activation.`);
|
|
1092
|
+
console.log(` Run: lua mcp activate --server-name ${serverName}`);
|
|
719
1093
|
}
|
|
1094
|
+
else {
|
|
1095
|
+
console.log(`ā ļø Connection created but setup incomplete. Check errors above.`);
|
|
1096
|
+
}
|
|
1097
|
+
console.log();
|
|
720
1098
|
}
|
|
721
1099
|
async function listConnections(context) {
|
|
722
1100
|
writeProgress("š Loading connections...");
|
|
@@ -738,11 +1116,11 @@ async function listConnections(context) {
|
|
|
738
1116
|
}
|
|
739
1117
|
}
|
|
740
1118
|
console.log("\n" + "=".repeat(60));
|
|
741
|
-
console.log("š Connected
|
|
1119
|
+
console.log("š Connected Integrations");
|
|
742
1120
|
console.log("=".repeat(60) + "\n");
|
|
743
1121
|
if (connections.length === 0) {
|
|
744
|
-
console.log("ā¹ļø No
|
|
745
|
-
console.log("š” Run 'lua integrations connect' to connect
|
|
1122
|
+
console.log("ā¹ļø No integrations connected yet.");
|
|
1123
|
+
console.log("š” Run 'lua integrations connect' to connect an integration.\n");
|
|
746
1124
|
return;
|
|
747
1125
|
}
|
|
748
1126
|
for (const connection of connections) {
|
|
@@ -765,23 +1143,26 @@ async function listConnections(context) {
|
|
|
765
1143
|
}
|
|
766
1144
|
else if (connection.status === 'active') {
|
|
767
1145
|
statusIcon = 'š”';
|
|
768
|
-
statusText = 'Connected (
|
|
1146
|
+
statusText = 'Connected (MCP pending)';
|
|
769
1147
|
}
|
|
770
1148
|
console.log(`${statusIcon} ${connection.integrationName || connection.integrationType}`);
|
|
771
|
-
console.log(`
|
|
1149
|
+
console.log(` Connection: ${connection.id}`);
|
|
772
1150
|
console.log(` Status: ${statusText}`);
|
|
1151
|
+
if (linkedServer) {
|
|
1152
|
+
console.log(` MCP Server: ${linkedServer.name} (${linkedServer.active ? 'active' : 'inactive'})`);
|
|
1153
|
+
}
|
|
773
1154
|
console.log(` Connected: ${new Date(connection.createdAt).toLocaleDateString()}`);
|
|
774
1155
|
console.log();
|
|
775
1156
|
}
|
|
776
1157
|
console.log("=".repeat(60));
|
|
777
|
-
console.log(`Total: ${connections.length}
|
|
1158
|
+
console.log(`Total: ${connections.length} integration(s)\n`);
|
|
778
1159
|
}
|
|
779
1160
|
catch (error) {
|
|
780
1161
|
writeError(`ā Error loading connections: ${error.message}`);
|
|
781
1162
|
}
|
|
782
1163
|
}
|
|
783
1164
|
async function disconnectIntegration(context, connectionId) {
|
|
784
|
-
writeProgress(`š Disconnecting
|
|
1165
|
+
writeProgress(`š Disconnecting... (please wait, do not close this window)`);
|
|
785
1166
|
try {
|
|
786
1167
|
// Clean up associated MCP server (internal implementation detail)
|
|
787
1168
|
const mcpServers = await context.developerApi.getMCPServers();
|
|
@@ -794,9 +1175,9 @@ async function disconnectIntegration(context, connectionId) {
|
|
|
794
1175
|
// Delete the connection (also deletes webhook subscriptions)
|
|
795
1176
|
const deleteResult = await context.unifiedToApi.deleteConnection(connectionId, context.agentId);
|
|
796
1177
|
if (deleteResult.success) {
|
|
797
|
-
writeSuccess(`ā
|
|
1178
|
+
writeSuccess(`ā
Integration disconnected successfully!`);
|
|
798
1179
|
if (deleteResult.data?.deletedWebhooksCount && deleteResult.data.deletedWebhooksCount > 0) {
|
|
799
|
-
console.log(` ā Deleted ${deleteResult.data.deletedWebhooksCount}
|
|
1180
|
+
console.log(` ā Deleted ${deleteResult.data.deletedWebhooksCount} trigger(s)`);
|
|
800
1181
|
}
|
|
801
1182
|
console.log();
|
|
802
1183
|
}
|
|
@@ -817,14 +1198,14 @@ async function disconnectIntegrationInteractive(context) {
|
|
|
817
1198
|
}
|
|
818
1199
|
const connections = connectionsResult.data || [];
|
|
819
1200
|
if (connections.length === 0) {
|
|
820
|
-
console.log("\nā¹ļø No
|
|
1201
|
+
console.log("\nā¹ļø No integrations to disconnect.\n");
|
|
821
1202
|
return;
|
|
822
1203
|
}
|
|
823
1204
|
const connectionAnswer = await safePrompt([
|
|
824
1205
|
{
|
|
825
1206
|
type: 'list',
|
|
826
1207
|
name: 'connection',
|
|
827
|
-
message: 'Select an
|
|
1208
|
+
message: 'Select an integration to disconnect:',
|
|
828
1209
|
choices: connections.map(c => ({
|
|
829
1210
|
name: `${c.integrationName || c.integrationType} (${c.id.substring(0, 8)}...)`,
|
|
830
1211
|
value: c.id
|
|
@@ -838,7 +1219,7 @@ async function disconnectIntegrationInteractive(context) {
|
|
|
838
1219
|
{
|
|
839
1220
|
type: 'confirm',
|
|
840
1221
|
name: 'confirm',
|
|
841
|
-
message: `Disconnect ${selectedConnection?.integrationName || selectedConnection?.integrationType}? Your agent will lose access to this
|
|
1222
|
+
message: `Disconnect ${selectedConnection?.integrationName || selectedConnection?.integrationType}? Your agent will lose access to this integration.`,
|
|
842
1223
|
default: false
|
|
843
1224
|
}
|
|
844
1225
|
]);
|
|
@@ -873,8 +1254,8 @@ async function updateConnectionFlow(context, options = {}) {
|
|
|
873
1254
|
return;
|
|
874
1255
|
}
|
|
875
1256
|
if (connections.length === 0) {
|
|
876
|
-
writeInfo("No
|
|
877
|
-
console.log("š” Run 'lua integrations connect' to connect
|
|
1257
|
+
writeInfo("No integrations to update.");
|
|
1258
|
+
console.log("š” Run 'lua integrations connect' to connect an integration.\n");
|
|
878
1259
|
return;
|
|
879
1260
|
}
|
|
880
1261
|
// Step 2: Select connection to update
|
|
@@ -887,7 +1268,7 @@ async function updateConnectionFlow(context, options = {}) {
|
|
|
887
1268
|
console.error(`ā No connection found for integration "${options.integration}".`);
|
|
888
1269
|
console.log('\nConnected integrations:');
|
|
889
1270
|
connections.forEach(c => console.log(` - ${c.integrationType} (${c.integrationName || c.integrationType})`));
|
|
890
|
-
|
|
1271
|
+
throw new Error("No connection found for integration");
|
|
891
1272
|
}
|
|
892
1273
|
selectedIntegration = integrations.find(i => i.value === options.integration);
|
|
893
1274
|
}
|
|
@@ -939,7 +1320,7 @@ async function updateConnectionFlow(context, options = {}) {
|
|
|
939
1320
|
console.error(`ā Invalid scopes: ${invalidScopes.join(', ')}`);
|
|
940
1321
|
console.log(`\nAvailable scopes for ${selectedIntegration.name}:`);
|
|
941
1322
|
availableScopes.forEach(s => console.log(` - ${s}`));
|
|
942
|
-
|
|
1323
|
+
throw new Error("Invalid scopes: ${invalidScopes.join(");
|
|
943
1324
|
}
|
|
944
1325
|
selectedScopes = requestedScopes;
|
|
945
1326
|
writeInfo(`Using ${selectedScopes.length} specified scope(s)`);
|
|
@@ -953,11 +1334,18 @@ async function updateConnectionFlow(context, options = {}) {
|
|
|
953
1334
|
message: 'Select new OAuth scopes (Space to toggle, Enter to confirm, leave empty for all):',
|
|
954
1335
|
pageSize: 15,
|
|
955
1336
|
loop: false,
|
|
956
|
-
choices: selectedIntegration.oauthScopes.map(s =>
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
1337
|
+
choices: selectedIntegration.oauthScopes.map(s => {
|
|
1338
|
+
// Use friendly label if available, otherwise fall back to technical name
|
|
1339
|
+
const displayName = s.friendlyLabel || s.unifiedScope;
|
|
1340
|
+
const description = s.friendlyDescription
|
|
1341
|
+
? ` (${s.friendlyDescription})`
|
|
1342
|
+
: ` ā [${s.originalScopes.join(', ')}]`;
|
|
1343
|
+
return {
|
|
1344
|
+
name: `${displayName}${description}`,
|
|
1345
|
+
value: s.unifiedScope,
|
|
1346
|
+
checked: false
|
|
1347
|
+
};
|
|
1348
|
+
})
|
|
961
1349
|
}]);
|
|
962
1350
|
if (!scopeAnswer)
|
|
963
1351
|
return;
|
|
@@ -983,7 +1371,28 @@ async function updateConnectionFlow(context, options = {}) {
|
|
|
983
1371
|
hideSensitive = sensitiveAnswer.hide;
|
|
984
1372
|
}
|
|
985
1373
|
}
|
|
986
|
-
// Step 5:
|
|
1374
|
+
// Step 5: Fetch existing triggers before deletion (so we can re-create them)
|
|
1375
|
+
let existingTriggers = [];
|
|
1376
|
+
try {
|
|
1377
|
+
const webhooksResult = await context.unifiedToApi.getWebhookSubscriptions(context.agentId);
|
|
1378
|
+
if (webhooksResult.success && webhooksResult.data && webhooksResult.data.length > 0) {
|
|
1379
|
+
// Filter webhooks to only those belonging to this connection
|
|
1380
|
+
const connectionWebhooks = webhooksResult.data.filter(w => w.connectionId === selectedConnection.id);
|
|
1381
|
+
existingTriggers = connectionWebhooks.map(w => ({
|
|
1382
|
+
objectType: w.objectType,
|
|
1383
|
+
event: w.event,
|
|
1384
|
+
hookUrl: w.hookUrl,
|
|
1385
|
+
interval: w.interval,
|
|
1386
|
+
}));
|
|
1387
|
+
if (existingTriggers.length > 0) {
|
|
1388
|
+
writeInfo(`Found ${existingTriggers.length} existing trigger(s) - will restore after update`);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
catch (error) {
|
|
1393
|
+
// If we can't fetch existing triggers, continue without them
|
|
1394
|
+
}
|
|
1395
|
+
// Step 6: Confirm the update
|
|
987
1396
|
if (!options.integration) {
|
|
988
1397
|
const confirmAnswer = await safePrompt([
|
|
989
1398
|
{
|
|
@@ -998,7 +1407,7 @@ async function updateConnectionFlow(context, options = {}) {
|
|
|
998
1407
|
return;
|
|
999
1408
|
}
|
|
1000
1409
|
}
|
|
1001
|
-
// Step
|
|
1410
|
+
// Step 7: Delete the old connection (silently)
|
|
1002
1411
|
writeProgress(`š Updating ${selectedIntegration.name}...`);
|
|
1003
1412
|
try {
|
|
1004
1413
|
// Clean up old MCP server
|
|
@@ -1009,14 +1418,14 @@ async function updateConnectionFlow(context, options = {}) {
|
|
|
1009
1418
|
await context.developerApi.deleteMCPServer(associatedServer.id);
|
|
1010
1419
|
}
|
|
1011
1420
|
}
|
|
1012
|
-
// Delete old connection
|
|
1421
|
+
// Delete old connection (this also deletes associated webhooks in Unified.to)
|
|
1013
1422
|
await context.unifiedToApi.deleteConnection(selectedConnection.id, context.agentId);
|
|
1014
1423
|
}
|
|
1015
1424
|
catch (error) {
|
|
1016
1425
|
writeError(`ā Failed to remove old connection: ${error.message}`);
|
|
1017
1426
|
return;
|
|
1018
1427
|
}
|
|
1019
|
-
// Step
|
|
1428
|
+
// Step 8: Create new connection with new scopes
|
|
1020
1429
|
const state = Buffer.from(JSON.stringify({
|
|
1021
1430
|
agentId: context.agentId,
|
|
1022
1431
|
integration: selectedIntegration.value,
|
|
@@ -1057,7 +1466,7 @@ async function updateConnectionFlow(context, options = {}) {
|
|
|
1057
1466
|
catch (error) {
|
|
1058
1467
|
// Use original auth URL if pre-fetch fails
|
|
1059
1468
|
}
|
|
1060
|
-
// Step
|
|
1469
|
+
// Step 9: Open browser and wait for callback
|
|
1061
1470
|
console.log("\n" + "ā".repeat(60));
|
|
1062
1471
|
console.log("š Re-authorizing with new scopes...");
|
|
1063
1472
|
console.log("ā".repeat(60));
|
|
@@ -1075,7 +1484,39 @@ async function updateConnectionFlow(context, options = {}) {
|
|
|
1075
1484
|
const result = await callbackPromise;
|
|
1076
1485
|
if (result.success && result.connectionId) {
|
|
1077
1486
|
writeSuccess("\nā
Authorization successful!");
|
|
1078
|
-
|
|
1487
|
+
// Check if any triggers use custom webhooks
|
|
1488
|
+
const hasCustomWebhook = existingTriggers.some(t => t.hookUrl !== AGENT_WEBHOOK_URL);
|
|
1489
|
+
// Convert existing triggers to TriggerWithSettings format, preserving per-trigger hookUrl and interval
|
|
1490
|
+
let triggersToRestore = [];
|
|
1491
|
+
if (existingTriggers.length > 0) {
|
|
1492
|
+
try {
|
|
1493
|
+
const eventsResult = await context.unifiedToApi.getAvailableWebhookEventsByType(selectedIntegration.value);
|
|
1494
|
+
if (eventsResult.success && eventsResult.data) {
|
|
1495
|
+
for (const trigger of existingTriggers) {
|
|
1496
|
+
const matchingEvent = eventsResult.data.find(e => e.objectType === trigger.objectType && e.event === trigger.event);
|
|
1497
|
+
if (matchingEvent) {
|
|
1498
|
+
// Preserve per-trigger hookUrl and interval from original webhook
|
|
1499
|
+
triggersToRestore.push({
|
|
1500
|
+
...matchingEvent,
|
|
1501
|
+
hookUrl: trigger.hookUrl,
|
|
1502
|
+
interval: trigger.interval,
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
catch (error) {
|
|
1509
|
+
// If we can't match triggers, continue without them
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
await finalizeConnection(context, selectedIntegration, result.connectionId, selectedScopes, hideSensitive, {
|
|
1513
|
+
triggers: triggersToRestore,
|
|
1514
|
+
webhookUrl: AGENT_WEBHOOK_URL, // Default, but per-trigger hookUrl will override if set
|
|
1515
|
+
isCustomWebhook: hasCustomWebhook,
|
|
1516
|
+
});
|
|
1517
|
+
if (triggersToRestore.length > 0) {
|
|
1518
|
+
writeSuccess(`Restored ${triggersToRestore.length} trigger(s) from previous connection`);
|
|
1519
|
+
}
|
|
1079
1520
|
}
|
|
1080
1521
|
else {
|
|
1081
1522
|
writeError(`\nā Authorization failed: ${result.error || 'Unknown error'}`);
|
|
@@ -1095,12 +1536,14 @@ async function webhooksSubcommand(context, cmdOptions) {
|
|
|
1095
1536
|
webhookId: cmdOptions?.webhookId,
|
|
1096
1537
|
objectType: cmdOptions?.object,
|
|
1097
1538
|
event: cmdOptions?.event,
|
|
1098
|
-
|
|
1539
|
+
hookUrl: cmdOptions?.hookUrl,
|
|
1099
1540
|
interval: cmdOptions?.interval ? parseInt(cmdOptions.interval, 10) : undefined,
|
|
1541
|
+
integration: cmdOptions?.integration,
|
|
1100
1542
|
};
|
|
1543
|
+
const jsonOutput = cmdOptions?.json === true;
|
|
1101
1544
|
switch (subAction) {
|
|
1102
1545
|
case 'list':
|
|
1103
|
-
await webhooksListFlow(context);
|
|
1546
|
+
await webhooksListFlow(context, jsonOutput);
|
|
1104
1547
|
break;
|
|
1105
1548
|
case 'create':
|
|
1106
1549
|
await webhooksCreateFlow(context, options);
|
|
@@ -1108,19 +1551,114 @@ async function webhooksSubcommand(context, cmdOptions) {
|
|
|
1108
1551
|
case 'delete':
|
|
1109
1552
|
if (!options.webhookId) {
|
|
1110
1553
|
console.error("ā --webhook-id is required for delete");
|
|
1111
|
-
console.log("\nš” Run 'lua integrations webhooks list' to see
|
|
1112
|
-
|
|
1554
|
+
console.log("\nš” Run 'lua integrations webhooks list' to see trigger IDs");
|
|
1555
|
+
throw new Error("--webhook-id is required for delete");
|
|
1113
1556
|
}
|
|
1114
1557
|
await webhooksDeleteFlow(context, options.webhookId);
|
|
1115
1558
|
break;
|
|
1559
|
+
case 'events':
|
|
1560
|
+
// New: List available webhook events for a connection or integration type
|
|
1561
|
+
await webhooksEventsFlow(context, options, jsonOutput);
|
|
1562
|
+
break;
|
|
1116
1563
|
default:
|
|
1117
1564
|
console.error(`ā Invalid webhooks action: "${subAction || '(none)'}"`);
|
|
1118
1565
|
console.log('\nUsage:');
|
|
1119
|
-
console.log(' lua integrations webhooks list List
|
|
1120
|
-
console.log(' lua integrations webhooks
|
|
1121
|
-
console.log(' lua integrations webhooks
|
|
1122
|
-
console.log(' lua integrations webhooks
|
|
1123
|
-
|
|
1566
|
+
console.log(' lua integrations webhooks list List triggers');
|
|
1567
|
+
console.log(' lua integrations webhooks events --connection <id> List available events for a connection');
|
|
1568
|
+
console.log(' lua integrations webhooks events --integration <type> List available events for an integration');
|
|
1569
|
+
console.log(' lua integrations webhooks create Create trigger (interactive)');
|
|
1570
|
+
console.log(' lua integrations webhooks create --connection <id> --object <type> --event <event> --hook-url <url>');
|
|
1571
|
+
console.log(' lua integrations webhooks delete --webhook-id <id> Delete trigger');
|
|
1572
|
+
throw new Error("Invalid webhooks action:");
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
/**
|
|
1576
|
+
* Show available webhook events for a connection or integration type
|
|
1577
|
+
* Used for non-interactive discovery
|
|
1578
|
+
*/
|
|
1579
|
+
async function webhooksEventsFlow(context, options, jsonOutput = false) {
|
|
1580
|
+
try {
|
|
1581
|
+
let webhookEvents = [];
|
|
1582
|
+
let sourceName = '';
|
|
1583
|
+
if (options.connectionId) {
|
|
1584
|
+
// Get events by connection ID
|
|
1585
|
+
const eventsResult = await context.unifiedToApi.getAvailableWebhookEvents(context.agentId, options.connectionId);
|
|
1586
|
+
if (eventsResult.success && eventsResult.data) {
|
|
1587
|
+
webhookEvents = eventsResult.data;
|
|
1588
|
+
}
|
|
1589
|
+
sourceName = `connection ${options.connectionId}`;
|
|
1590
|
+
}
|
|
1591
|
+
else if (options.integration) {
|
|
1592
|
+
// Get events by integration type
|
|
1593
|
+
const eventsResult = await context.unifiedToApi.getAvailableWebhookEventsByType(options.integration);
|
|
1594
|
+
if (eventsResult.success && eventsResult.data) {
|
|
1595
|
+
webhookEvents = eventsResult.data;
|
|
1596
|
+
}
|
|
1597
|
+
sourceName = `integration ${options.integration}`;
|
|
1598
|
+
}
|
|
1599
|
+
else {
|
|
1600
|
+
if (jsonOutput) {
|
|
1601
|
+
console.log(JSON.stringify({ error: 'Either --connection or --integration is required' }));
|
|
1602
|
+
}
|
|
1603
|
+
else {
|
|
1604
|
+
console.error("ā Either --connection <id> or --integration <type> is required");
|
|
1605
|
+
console.log("\nUsage:");
|
|
1606
|
+
console.log(" lua integrations webhooks events --connection <id>");
|
|
1607
|
+
console.log(" lua integrations webhooks events --integration <type>");
|
|
1608
|
+
}
|
|
1609
|
+
throw new Error("Operation failed");
|
|
1610
|
+
}
|
|
1611
|
+
if (jsonOutput) {
|
|
1612
|
+
const output = {
|
|
1613
|
+
source: sourceName,
|
|
1614
|
+
events: webhookEvents.map(e => ({
|
|
1615
|
+
trigger: `${e.objectType}.${e.event}`,
|
|
1616
|
+
objectType: e.objectType,
|
|
1617
|
+
event: e.event,
|
|
1618
|
+
webhookType: e.webhookType,
|
|
1619
|
+
friendlyLabel: e.friendlyLabel,
|
|
1620
|
+
friendlyDescription: e.friendlyDescription,
|
|
1621
|
+
availableFilters: e.availableFilters,
|
|
1622
|
+
})),
|
|
1623
|
+
defaults: {
|
|
1624
|
+
agentWebhookUrl: AGENT_WEBHOOK_URL,
|
|
1625
|
+
defaultVirtualInterval: DEFAULT_VIRTUAL_WEBHOOK_INTERVAL,
|
|
1626
|
+
},
|
|
1627
|
+
};
|
|
1628
|
+
console.log(JSON.stringify(output, null, 2));
|
|
1629
|
+
}
|
|
1630
|
+
else {
|
|
1631
|
+
console.log("\n" + "=".repeat(60));
|
|
1632
|
+
console.log(`š” Available Trigger Events for ${sourceName}`);
|
|
1633
|
+
console.log("=".repeat(60) + "\n");
|
|
1634
|
+
if (webhookEvents.length === 0) {
|
|
1635
|
+
console.log("ā¹ļø No trigger events available for this integration.\n");
|
|
1636
|
+
}
|
|
1637
|
+
else {
|
|
1638
|
+
webhookEvents.forEach(e => {
|
|
1639
|
+
console.log(` ${e.objectType}.${e.event} [${e.webhookType}]`);
|
|
1640
|
+
console.log(` ${e.friendlyDescription}`);
|
|
1641
|
+
if (e.availableFilters.length > 0) {
|
|
1642
|
+
console.log(` Filters: ${e.availableFilters.join(', ')}`);
|
|
1643
|
+
}
|
|
1644
|
+
console.log();
|
|
1645
|
+
});
|
|
1646
|
+
console.log("ā".repeat(60));
|
|
1647
|
+
console.log(`Total: ${webhookEvents.length} event(s) available`);
|
|
1648
|
+
console.log("\nš” Use with --triggers flag:");
|
|
1649
|
+
const exampleTriggers = webhookEvents.slice(0, 2).map(e => `${e.objectType}.${e.event}`).join(',');
|
|
1650
|
+
console.log(` lua integrations connect --integration <type> --triggers ${exampleTriggers}\n`);
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
catch (error) {
|
|
1655
|
+
if (jsonOutput) {
|
|
1656
|
+
console.log(JSON.stringify({ error: error.message }));
|
|
1657
|
+
}
|
|
1658
|
+
else {
|
|
1659
|
+
writeError(`ā Failed to get trigger events: ${error.message}`);
|
|
1660
|
+
}
|
|
1661
|
+
throw new Error("Operation failed");
|
|
1124
1662
|
}
|
|
1125
1663
|
}
|
|
1126
1664
|
/**
|
|
@@ -1128,7 +1666,7 @@ async function webhooksSubcommand(context, cmdOptions) {
|
|
|
1128
1666
|
*/
|
|
1129
1667
|
async function webhooksInteractiveMenu(context) {
|
|
1130
1668
|
console.log("\n" + "ā".repeat(60));
|
|
1131
|
-
console.log("š
|
|
1669
|
+
console.log("š Triggers");
|
|
1132
1670
|
console.log("ā".repeat(60) + "\n");
|
|
1133
1671
|
const actionAnswer = await safePrompt([
|
|
1134
1672
|
{
|
|
@@ -1136,7 +1674,7 @@ async function webhooksInteractiveMenu(context) {
|
|
|
1136
1674
|
name: 'action',
|
|
1137
1675
|
message: 'What would you like to do?',
|
|
1138
1676
|
choices: [
|
|
1139
|
-
{ name: 'š List
|
|
1677
|
+
{ name: 'š List triggers', value: 'list' },
|
|
1140
1678
|
{ name: 'ā Create new subscription', value: 'create' },
|
|
1141
1679
|
{ name: 'šļø Delete subscription', value: 'delete' },
|
|
1142
1680
|
{ name: 'ā Back', value: 'back' }
|
|
@@ -1160,35 +1698,81 @@ async function webhooksInteractiveMenu(context) {
|
|
|
1160
1698
|
/**
|
|
1161
1699
|
* List all webhook subscriptions
|
|
1162
1700
|
*/
|
|
1163
|
-
async function webhooksListFlow(context) {
|
|
1164
|
-
writeProgress("š Loading
|
|
1701
|
+
async function webhooksListFlow(context, jsonOutput = false) {
|
|
1702
|
+
writeProgress("š Loading triggers...");
|
|
1165
1703
|
try {
|
|
1166
1704
|
const result = await context.unifiedToApi.getWebhookSubscriptions(context.agentId);
|
|
1167
1705
|
if (!result.success) {
|
|
1168
|
-
|
|
1706
|
+
if (jsonOutput) {
|
|
1707
|
+
console.log(JSON.stringify({ error: result.error?.message || 'Failed to load triggers' }));
|
|
1708
|
+
}
|
|
1709
|
+
else {
|
|
1710
|
+
writeError(`ā Failed to load triggers: ${result.error?.message}`);
|
|
1711
|
+
}
|
|
1169
1712
|
return;
|
|
1170
1713
|
}
|
|
1171
1714
|
const webhooks = result.data || [];
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1715
|
+
if (jsonOutput) {
|
|
1716
|
+
// Output as JSON for scripting
|
|
1717
|
+
console.log(JSON.stringify({
|
|
1718
|
+
triggers: webhooks.map(wh => ({
|
|
1719
|
+
id: wh.id,
|
|
1720
|
+
integrationType: wh.integrationType,
|
|
1721
|
+
objectType: wh.objectType,
|
|
1722
|
+
event: wh.event,
|
|
1723
|
+
webhookType: wh.webhookType,
|
|
1724
|
+
hookUrl: wh.hookUrl,
|
|
1725
|
+
status: wh.status,
|
|
1726
|
+
interval: wh.interval,
|
|
1727
|
+
connectionId: wh.connectionId,
|
|
1728
|
+
})),
|
|
1729
|
+
total: webhooks.length,
|
|
1730
|
+
}, null, 2));
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1733
|
+
console.log("\n" + "ā".repeat(60));
|
|
1734
|
+
console.log("ā” Triggers / Webhook Subscriptions");
|
|
1735
|
+
console.log("ā".repeat(60) + "\n");
|
|
1175
1736
|
if (webhooks.length === 0) {
|
|
1176
|
-
console.log("ā¹ļø No
|
|
1177
|
-
console.log("š”
|
|
1737
|
+
console.log("ā¹ļø No triggers configured yet.\n");
|
|
1738
|
+
console.log("š” Add triggers when connecting: lua integrations connect --triggers <events>");
|
|
1739
|
+
console.log(" Or manually: lua integrations webhooks create\n");
|
|
1178
1740
|
return;
|
|
1179
1741
|
}
|
|
1742
|
+
// Group by integration
|
|
1743
|
+
const byIntegration = new Map();
|
|
1180
1744
|
for (const wh of webhooks) {
|
|
1181
|
-
const
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1745
|
+
const key = wh.integrationType;
|
|
1746
|
+
if (!byIntegration.has(key))
|
|
1747
|
+
byIntegration.set(key, []);
|
|
1748
|
+
byIntegration.get(key).push(wh);
|
|
1749
|
+
}
|
|
1750
|
+
for (const [integration, integrationWebhooks] of byIntegration) {
|
|
1751
|
+
console.log(`š¦ ${integration}`);
|
|
1752
|
+
for (const wh of integrationWebhooks) {
|
|
1753
|
+
const statusIcon = wh.status === 'active' ? 'ā
' : 'āŖ';
|
|
1754
|
+
const typeLabel = wh.webhookType === 'native' ? 'push' : 'poll';
|
|
1755
|
+
const isAgentTrigger = wh.hookUrl.includes('webhook/unifiedto');
|
|
1756
|
+
const mode = isAgentTrigger ? 'agent trigger' : 'custom URL';
|
|
1757
|
+
// Show webhook ID for delete operations
|
|
1758
|
+
console.log(` ${statusIcon} ${wh.objectType}.${wh.event} (${typeLabel}, ${mode})`);
|
|
1759
|
+
console.log(` ID: ${wh.id}`);
|
|
1760
|
+
if (!isAgentTrigger) {
|
|
1761
|
+
console.log(` URL: ${wh.hookUrl}`);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
console.log();
|
|
1187
1765
|
}
|
|
1188
|
-
console.log(
|
|
1766
|
+
console.log("ā".repeat(60));
|
|
1767
|
+
console.log(`Total: ${webhooks.length} trigger(s)\n`);
|
|
1189
1768
|
}
|
|
1190
1769
|
catch (error) {
|
|
1191
|
-
|
|
1770
|
+
if (jsonOutput) {
|
|
1771
|
+
console.log(JSON.stringify({ error: error.message }));
|
|
1772
|
+
}
|
|
1773
|
+
else {
|
|
1774
|
+
writeError(`ā Error: ${error.message}`);
|
|
1775
|
+
}
|
|
1192
1776
|
}
|
|
1193
1777
|
}
|
|
1194
1778
|
/**
|
|
@@ -1212,7 +1796,7 @@ async function webhooksCreateFlow(context, options) {
|
|
|
1212
1796
|
}
|
|
1213
1797
|
if (connections.length === 0) {
|
|
1214
1798
|
writeInfo("No connections available.");
|
|
1215
|
-
console.log("š” Run 'lua integrations connect' to connect an
|
|
1799
|
+
console.log("š” Run 'lua integrations connect' to connect an integration first.\n");
|
|
1216
1800
|
return;
|
|
1217
1801
|
}
|
|
1218
1802
|
// Step 2: Select connection
|
|
@@ -1223,7 +1807,7 @@ async function webhooksCreateFlow(context, options) {
|
|
|
1223
1807
|
console.error(`ā Connection "${options.connectionId}" not found.`);
|
|
1224
1808
|
console.log('\nAvailable connections:');
|
|
1225
1809
|
connections.forEach(c => console.log(` - ${c.id} (${c.integrationName || c.integrationType})`));
|
|
1226
|
-
|
|
1810
|
+
throw new Error("Connection");
|
|
1227
1811
|
}
|
|
1228
1812
|
}
|
|
1229
1813
|
else {
|
|
@@ -1258,8 +1842,8 @@ async function webhooksCreateFlow(context, options) {
|
|
|
1258
1842
|
return;
|
|
1259
1843
|
}
|
|
1260
1844
|
if (availableEvents.length === 0) {
|
|
1261
|
-
writeInfo(`No
|
|
1262
|
-
console.log("š” This integration may not support
|
|
1845
|
+
writeInfo(`No trigger events available for ${selectedConnection.integrationName || selectedConnection.integrationType}.`);
|
|
1846
|
+
console.log("š” This integration may not support triggers.\n");
|
|
1263
1847
|
return;
|
|
1264
1848
|
}
|
|
1265
1849
|
// Step 4: Select event
|
|
@@ -1270,11 +1854,11 @@ async function webhooksCreateFlow(context, options) {
|
|
|
1270
1854
|
console.error(`ā Event '${options.objectType}.${options.event}' is not supported.`);
|
|
1271
1855
|
console.log(`\nAvailable events for ${selectedConnection.integrationName || selectedConnection.integrationType}:`);
|
|
1272
1856
|
availableEvents.forEach(e => console.log(` - ${e.objectType}.${e.event} [${e.webhookType}]`));
|
|
1273
|
-
|
|
1857
|
+
throw new Error("Event");
|
|
1274
1858
|
}
|
|
1275
1859
|
}
|
|
1276
1860
|
else {
|
|
1277
|
-
console.log(`\nAvailable
|
|
1861
|
+
console.log(`\nAvailable trigger events for ${selectedConnection.integrationName || selectedConnection.integrationType}:\n`);
|
|
1278
1862
|
const eventAnswer = await safePrompt([
|
|
1279
1863
|
{
|
|
1280
1864
|
type: 'list',
|
|
@@ -1293,8 +1877,8 @@ async function webhooksCreateFlow(context, options) {
|
|
|
1293
1877
|
}
|
|
1294
1878
|
// Step 5: Get webhook URL
|
|
1295
1879
|
let hookUrl;
|
|
1296
|
-
if (options.
|
|
1297
|
-
hookUrl = options.
|
|
1880
|
+
if (options.hookUrl) {
|
|
1881
|
+
hookUrl = options.hookUrl;
|
|
1298
1882
|
}
|
|
1299
1883
|
else {
|
|
1300
1884
|
const webhookAnswer = await safePrompt([
|
|
@@ -1357,7 +1941,7 @@ async function webhooksCreateFlow(context, options) {
|
|
|
1357
1941
|
// Step 7: Confirmation (interactive only)
|
|
1358
1942
|
if (!options.connectionId) {
|
|
1359
1943
|
console.log("\n" + "ā".repeat(60));
|
|
1360
|
-
console.log("š
|
|
1944
|
+
console.log("š Trigger Summary");
|
|
1361
1945
|
console.log("ā".repeat(60));
|
|
1362
1946
|
console.log(` Connection: ${selectedConnection.integrationName || selectedConnection.integrationType}`);
|
|
1363
1947
|
console.log(` Event: ${selectedEvent.objectType}.${selectedEvent.event} [${selectedEvent.webhookType}]`);
|
|
@@ -1369,7 +1953,7 @@ async function webhooksCreateFlow(context, options) {
|
|
|
1369
1953
|
{
|
|
1370
1954
|
type: 'confirm',
|
|
1371
1955
|
name: 'confirm',
|
|
1372
|
-
message: 'Create this
|
|
1956
|
+
message: 'Create this trigger?',
|
|
1373
1957
|
default: true
|
|
1374
1958
|
}
|
|
1375
1959
|
]);
|
|
@@ -1379,7 +1963,7 @@ async function webhooksCreateFlow(context, options) {
|
|
|
1379
1963
|
}
|
|
1380
1964
|
}
|
|
1381
1965
|
// Step 8: Create the webhook
|
|
1382
|
-
writeProgress("š Creating
|
|
1966
|
+
writeProgress("š Creating trigger...");
|
|
1383
1967
|
try {
|
|
1384
1968
|
const createResult = await context.unifiedToApi.createWebhookSubscription(context.agentId, {
|
|
1385
1969
|
connectionId: selectedConnection.id,
|
|
@@ -1389,22 +1973,32 @@ async function webhooksCreateFlow(context, options) {
|
|
|
1389
1973
|
interval,
|
|
1390
1974
|
});
|
|
1391
1975
|
if (!createResult.success || !createResult.data) {
|
|
1392
|
-
writeError(`ā Failed to create
|
|
1976
|
+
writeError(`ā Failed to create trigger: ${createResult.error?.message}`);
|
|
1393
1977
|
return;
|
|
1394
1978
|
}
|
|
1395
1979
|
const webhook = createResult.data;
|
|
1980
|
+
const isAgentTrigger = webhook.hookUrl.includes('webhook/unifiedto');
|
|
1981
|
+
const typeLabel = webhook.webhookType === 'native' ? 'push' : 'polling';
|
|
1396
1982
|
console.log("\n" + "ā".repeat(60));
|
|
1397
|
-
writeSuccess("ā
|
|
1983
|
+
writeSuccess("ā
Trigger created!");
|
|
1398
1984
|
console.log("ā".repeat(60));
|
|
1399
|
-
console.log(` ID: ${webhook.id}`);
|
|
1400
1985
|
console.log(` Integration: ${webhook.integrationType}`);
|
|
1401
|
-
console.log(` Event: ${webhook.objectType}.${webhook.event}
|
|
1402
|
-
console.log(`
|
|
1986
|
+
console.log(` Event: ${webhook.objectType}.${webhook.event}`);
|
|
1987
|
+
console.log(` Type: ${typeLabel}`);
|
|
1988
|
+
console.log(` Mode: ${isAgentTrigger ? 'Agent wake-up' : 'Custom URL'}`);
|
|
1989
|
+
if (!isAgentTrigger) {
|
|
1990
|
+
console.log(` URL: ${webhook.hookUrl}`);
|
|
1991
|
+
}
|
|
1403
1992
|
if (webhook.interval)
|
|
1404
|
-
console.log(`
|
|
1993
|
+
console.log(` Poll interval: ${formatInterval(webhook.interval)}`);
|
|
1405
1994
|
console.log(` Status: ${webhook.status}`);
|
|
1406
1995
|
console.log("ā".repeat(60) + "\n");
|
|
1407
|
-
|
|
1996
|
+
if (isAgentTrigger) {
|
|
1997
|
+
console.log("š” Your agent will now wake up when this event occurs.\n");
|
|
1998
|
+
}
|
|
1999
|
+
else {
|
|
2000
|
+
console.log("š” Ensure your webhook endpoint is ready to receive events.\n");
|
|
2001
|
+
}
|
|
1408
2002
|
}
|
|
1409
2003
|
catch (error) {
|
|
1410
2004
|
writeError(`ā Error: ${error.message}`);
|
|
@@ -1414,23 +2008,23 @@ async function webhooksCreateFlow(context, options) {
|
|
|
1414
2008
|
* Delete a webhook subscription (interactive)
|
|
1415
2009
|
*/
|
|
1416
2010
|
async function webhooksDeleteInteractive(context) {
|
|
1417
|
-
writeProgress("š Loading
|
|
2011
|
+
writeProgress("š Loading triggers...");
|
|
1418
2012
|
try {
|
|
1419
2013
|
const result = await context.unifiedToApi.getWebhookSubscriptions(context.agentId);
|
|
1420
2014
|
if (!result.success) {
|
|
1421
|
-
writeError(`ā Failed to load
|
|
2015
|
+
writeError(`ā Failed to load triggers: ${result.error?.message}`);
|
|
1422
2016
|
return;
|
|
1423
2017
|
}
|
|
1424
2018
|
const webhooks = result.data || [];
|
|
1425
2019
|
if (webhooks.length === 0) {
|
|
1426
|
-
console.log("\nā¹ļø No
|
|
2020
|
+
console.log("\nā¹ļø No triggers to delete.\n");
|
|
1427
2021
|
return;
|
|
1428
2022
|
}
|
|
1429
2023
|
const webhookAnswer = await safePrompt([
|
|
1430
2024
|
{
|
|
1431
2025
|
type: 'list',
|
|
1432
2026
|
name: 'webhook',
|
|
1433
|
-
message: 'Select a
|
|
2027
|
+
message: 'Select a trigger to delete:',
|
|
1434
2028
|
choices: webhooks.map(wh => {
|
|
1435
2029
|
// Show last part of URL for readability
|
|
1436
2030
|
const urlParts = (wh.hookUrl || '').split('/');
|
|
@@ -1449,7 +2043,7 @@ async function webhooksDeleteInteractive(context) {
|
|
|
1449
2043
|
{
|
|
1450
2044
|
type: 'confirm',
|
|
1451
2045
|
name: 'confirm',
|
|
1452
|
-
message: `Delete
|
|
2046
|
+
message: `Delete trigger for ${selectedWebhook?.objectType}.${selectedWebhook?.event}?`,
|
|
1453
2047
|
default: false
|
|
1454
2048
|
}
|
|
1455
2049
|
]);
|
|
@@ -1467,14 +2061,14 @@ async function webhooksDeleteInteractive(context) {
|
|
|
1467
2061
|
* Delete a webhook subscription (non-interactive)
|
|
1468
2062
|
*/
|
|
1469
2063
|
async function webhooksDeleteFlow(context, webhookId) {
|
|
1470
|
-
writeProgress("š Deleting
|
|
2064
|
+
writeProgress("š Deleting trigger...");
|
|
1471
2065
|
try {
|
|
1472
2066
|
const result = await context.unifiedToApi.deleteWebhookSubscription(context.agentId, webhookId);
|
|
1473
2067
|
if (result.success) {
|
|
1474
|
-
writeSuccess(`ā
|
|
2068
|
+
writeSuccess(`ā
Trigger deleted: ${webhookId}\n`);
|
|
1475
2069
|
}
|
|
1476
2070
|
else {
|
|
1477
|
-
writeError(`ā Failed to delete
|
|
2071
|
+
writeError(`ā Failed to delete trigger: ${result.error?.message}`);
|
|
1478
2072
|
}
|
|
1479
2073
|
}
|
|
1480
2074
|
catch (error) {
|
|
@@ -1758,21 +2352,30 @@ async function mcpDeactivateInteractive(context) {
|
|
|
1758
2352
|
function showUsage() {
|
|
1759
2353
|
console.log('\nUsage:');
|
|
1760
2354
|
console.log(' lua integrations Interactive integration management');
|
|
1761
|
-
console.log(' lua integrations connect Connect a new
|
|
2355
|
+
console.log(' lua integrations connect Connect a new integration (interactive)');
|
|
1762
2356
|
console.log(' lua integrations connect --integration <type> Connect a specific integration');
|
|
2357
|
+
console.log(' lua integrations connect --integration <type> --triggers <events> Connect with triggers');
|
|
1763
2358
|
console.log(' lua integrations update Update connection scopes (interactive)');
|
|
1764
2359
|
console.log(' lua integrations update --integration <type> Update scopes for a specific integration');
|
|
1765
|
-
console.log(' lua integrations list List connected
|
|
2360
|
+
console.log(' lua integrations list List connected integrations');
|
|
1766
2361
|
console.log(' lua integrations available List available integrations');
|
|
1767
|
-
console.log(' lua integrations
|
|
1768
|
-
console.log('
|
|
1769
|
-
console.log(' lua integrations
|
|
1770
|
-
console.log('
|
|
1771
|
-
console.log(' lua integrations webhooks
|
|
1772
|
-
console.log(' lua integrations webhooks
|
|
2362
|
+
console.log(' lua integrations info <type> Show integration details (scopes, triggers)');
|
|
2363
|
+
console.log(' lua integrations info <type> --json Output as JSON for scripting');
|
|
2364
|
+
console.log(' lua integrations disconnect --connection-id <id> Disconnect an integration');
|
|
2365
|
+
console.log('\nTriggers:');
|
|
2366
|
+
console.log(' lua integrations webhooks list List all triggers');
|
|
2367
|
+
console.log(' lua integrations webhooks events --connection <id> List available events for a connection');
|
|
2368
|
+
console.log(' lua integrations webhooks events --integration <type> List available events for an integration');
|
|
2369
|
+
console.log(' lua integrations webhooks create Create trigger (interactive)');
|
|
2370
|
+
console.log(' lua integrations webhooks create --connection <id> --object <type> --event <event> --hook-url <url>');
|
|
2371
|
+
console.log(' lua integrations webhooks delete --webhook-id <id> Delete a trigger');
|
|
1773
2372
|
console.log('\nMCP Server Management:');
|
|
1774
2373
|
console.log(' lua integrations mcp list List connections with MCP status');
|
|
1775
2374
|
console.log(' lua integrations mcp activate --connection <id> Activate MCP server');
|
|
1776
2375
|
console.log(' lua integrations mcp deactivate --connection <id> Deactivate MCP server');
|
|
2376
|
+
console.log('\nTrigger Options (use with connect):');
|
|
2377
|
+
console.log(' --triggers <events> Comma-separated triggers (e.g., task_task.created,task_task.updated)');
|
|
2378
|
+
console.log(' --custom-webhook Use custom URL instead of agent trigger');
|
|
2379
|
+
console.log(' --hook-url <url> Custom URL for triggers');
|
|
1777
2380
|
}
|
|
1778
2381
|
//# sourceMappingURL=integrations.js.map
|