@useconductor/conductor 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +33 -0
- package/.claude-plugin/plugin.json +23 -0
- package/.eslintrc.json +23 -0
- package/.gitattributes +6 -0
- package/.github/FUNDING.yml +15 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +91 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +63 -0
- package/.github/ISSUE_TEMPLATE/plugin_request.yml +71 -0
- package/.github/README.md +13 -0
- package/.github/workflows/README.md +22 -0
- package/.github/workflows/auto-release.yml +112 -0
- package/.github/workflows/ci.yml +49 -0
- package/.github/workflows/claude-code-review.yml +44 -0
- package/.github/workflows/claude.yml +36 -0
- package/.github/workflows/sync-install.yml +47 -0
- package/.mcp.json +9 -0
- package/.prettierrc.json +7 -0
- package/C.png +0 -0
- package/CHANGELOG.md +74 -0
- package/CLAUDE.md +118 -0
- package/CONTRIBUTING.md +231 -0
- package/LICENSE +201 -0
- package/README.md +179 -0
- package/SECURITY.md +47 -0
- package/commands/conductor-setup.md +11 -0
- package/commands/conductor-status.md +7 -0
- package/dist/ai/base.d.ts +44 -0
- package/dist/ai/base.d.ts.map +1 -0
- package/dist/ai/base.js +47 -0
- package/dist/ai/base.js.map +1 -0
- package/dist/ai/claude.d.ts +11 -0
- package/dist/ai/claude.d.ts.map +1 -0
- package/dist/ai/claude.js +149 -0
- package/dist/ai/claude.js.map +1 -0
- package/dist/ai/gemini.d.ts +15 -0
- package/dist/ai/gemini.d.ts.map +1 -0
- package/dist/ai/gemini.js +156 -0
- package/dist/ai/gemini.js.map +1 -0
- package/dist/ai/maestro.d.ts +22 -0
- package/dist/ai/maestro.d.ts.map +1 -0
- package/dist/ai/maestro.js +142 -0
- package/dist/ai/maestro.js.map +1 -0
- package/dist/ai/manager.d.ts +47 -0
- package/dist/ai/manager.d.ts.map +1 -0
- package/dist/ai/manager.js +450 -0
- package/dist/ai/manager.js.map +1 -0
- package/dist/ai/ollama.d.ts +16 -0
- package/dist/ai/ollama.d.ts.map +1 -0
- package/dist/ai/ollama.js +151 -0
- package/dist/ai/ollama.js.map +1 -0
- package/dist/ai/openai.d.ts +11 -0
- package/dist/ai/openai.d.ts.map +1 -0
- package/dist/ai/openai.js +132 -0
- package/dist/ai/openai.js.map +1 -0
- package/dist/ai/openrouter.d.ts +11 -0
- package/dist/ai/openrouter.d.ts.map +1 -0
- package/dist/ai/openrouter.js +139 -0
- package/dist/ai/openrouter.js.map +1 -0
- package/dist/bot/slack.d.ts +17 -0
- package/dist/bot/slack.d.ts.map +1 -0
- package/dist/bot/slack.js +144 -0
- package/dist/bot/slack.js.map +1 -0
- package/dist/bot/telegram.d.ts +19 -0
- package/dist/bot/telegram.d.ts.map +1 -0
- package/dist/bot/telegram.js +157 -0
- package/dist/bot/telegram.js.map +1 -0
- package/dist/cli/commands/ai.d.ts +4 -0
- package/dist/cli/commands/ai.d.ts.map +1 -0
- package/dist/cli/commands/ai.js +161 -0
- package/dist/cli/commands/ai.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +18 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +213 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.d.ts +15 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +281 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install.d.ts +16 -0
- package/dist/cli/commands/install.d.ts.map +1 -0
- package/dist/cli/commands/install.js +750 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/lifecycle.d.ts +4 -0
- package/dist/cli/commands/lifecycle.d.ts.map +1 -0
- package/dist/cli/commands/lifecycle.js +84 -0
- package/dist/cli/commands/lifecycle.js.map +1 -0
- package/dist/cli/commands/marketplace.d.ts +13 -0
- package/dist/cli/commands/marketplace.d.ts.map +1 -0
- package/dist/cli/commands/marketplace.js +197 -0
- package/dist/cli/commands/marketplace.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +6 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +83 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/onboard.d.ts +10 -0
- package/dist/cli/commands/onboard.d.ts.map +1 -0
- package/dist/cli/commands/onboard.js +207 -0
- package/dist/cli/commands/onboard.js.map +1 -0
- package/dist/cli/commands/plugin-create.d.ts +13 -0
- package/dist/cli/commands/plugin-create.d.ts.map +1 -0
- package/dist/cli/commands/plugin-create.js +122 -0
- package/dist/cli/commands/plugin-create.js.map +1 -0
- package/dist/cli/commands/plugins.d.ts +5 -0
- package/dist/cli/commands/plugins.d.ts.map +1 -0
- package/dist/cli/commands/plugins.js +30 -0
- package/dist/cli/commands/plugins.js.map +1 -0
- package/dist/cli/commands/release.d.ts +13 -0
- package/dist/cli/commands/release.d.ts.map +1 -0
- package/dist/cli/commands/release.js +243 -0
- package/dist/cli/commands/release.js.map +1 -0
- package/dist/cli/commands/telegram.d.ts +3 -0
- package/dist/cli/commands/telegram.d.ts.map +1 -0
- package/dist/cli/commands/telegram.js +20 -0
- package/dist/cli/commands/telegram.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +402 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/oauth.d.ts +8 -0
- package/dist/config/oauth.d.ts.map +1 -0
- package/dist/config/oauth.js +13 -0
- package/dist/config/oauth.js.map +1 -0
- package/dist/core/audit.d.ts +91 -0
- package/dist/core/audit.d.ts.map +1 -0
- package/dist/core/audit.js +233 -0
- package/dist/core/audit.js.map +1 -0
- package/dist/core/circuit-breaker.d.ts +56 -0
- package/dist/core/circuit-breaker.d.ts.map +1 -0
- package/dist/core/circuit-breaker.js +107 -0
- package/dist/core/circuit-breaker.js.map +1 -0
- package/dist/core/conductor.d.ts +44 -0
- package/dist/core/conductor.d.ts.map +1 -0
- package/dist/core/conductor.js +200 -0
- package/dist/core/conductor.js.map +1 -0
- package/dist/core/config.d.ts +66 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +86 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/database.d.ts +59 -0
- package/dist/core/database.d.ts.map +1 -0
- package/dist/core/database.js +342 -0
- package/dist/core/database.js.map +1 -0
- package/dist/core/errors.d.ts +231 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +254 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/health.d.ts +72 -0
- package/dist/core/health.d.ts.map +1 -0
- package/dist/core/health.js +116 -0
- package/dist/core/health.js.map +1 -0
- package/dist/core/interfaces.d.ts +62 -0
- package/dist/core/interfaces.d.ts.map +1 -0
- package/dist/core/interfaces.js +8 -0
- package/dist/core/interfaces.js.map +1 -0
- package/dist/core/logger.d.ts +15 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +30 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/rbac.d.ts +132 -0
- package/dist/core/rbac.d.ts.map +1 -0
- package/dist/core/rbac.js +230 -0
- package/dist/core/rbac.js.map +1 -0
- package/dist/core/retry.d.ts +22 -0
- package/dist/core/retry.d.ts.map +1 -0
- package/dist/core/retry.js +41 -0
- package/dist/core/retry.js.map +1 -0
- package/dist/core/webhooks.d.ts +92 -0
- package/dist/core/webhooks.d.ts.map +1 -0
- package/dist/core/webhooks.js +176 -0
- package/dist/core/webhooks.js.map +1 -0
- package/dist/core/zero-config.d.ts +22 -0
- package/dist/core/zero-config.d.ts.map +1 -0
- package/dist/core/zero-config.js +59 -0
- package/dist/core/zero-config.js.map +1 -0
- package/dist/dashboard/cli.d.ts +6 -0
- package/dist/dashboard/cli.d.ts.map +1 -0
- package/dist/dashboard/cli.js +42 -0
- package/dist/dashboard/cli.js.map +1 -0
- package/dist/dashboard/index.html +3426 -0
- package/dist/dashboard/server.d.ts +7 -0
- package/dist/dashboard/server.d.ts.map +1 -0
- package/dist/dashboard/server.js +1427 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/mcp/server.d.ts +27 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +380 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/misc.d.ts +15 -0
- package/dist/mcp/tools/misc.d.ts.map +1 -0
- package/dist/mcp/tools/misc.js +49 -0
- package/dist/mcp/tools/misc.js.map +1 -0
- package/dist/plugins/builtin/calculator.d.ts +11 -0
- package/dist/plugins/builtin/calculator.d.ts.map +1 -0
- package/dist/plugins/builtin/calculator.js +166 -0
- package/dist/plugins/builtin/calculator.js.map +1 -0
- package/dist/plugins/builtin/colors.d.ts +15 -0
- package/dist/plugins/builtin/colors.d.ts.map +1 -0
- package/dist/plugins/builtin/colors.js +193 -0
- package/dist/plugins/builtin/colors.js.map +1 -0
- package/dist/plugins/builtin/cron.d.ts +40 -0
- package/dist/plugins/builtin/cron.d.ts.map +1 -0
- package/dist/plugins/builtin/cron.js +578 -0
- package/dist/plugins/builtin/cron.js.map +1 -0
- package/dist/plugins/builtin/crypto.d.ts +11 -0
- package/dist/plugins/builtin/crypto.d.ts.map +1 -0
- package/dist/plugins/builtin/crypto.js +83 -0
- package/dist/plugins/builtin/crypto.js.map +1 -0
- package/dist/plugins/builtin/database.d.ts +29 -0
- package/dist/plugins/builtin/database.d.ts.map +1 -0
- package/dist/plugins/builtin/database.js +230 -0
- package/dist/plugins/builtin/database.js.map +1 -0
- package/dist/plugins/builtin/docker.d.ts +12 -0
- package/dist/plugins/builtin/docker.d.ts.map +1 -0
- package/dist/plugins/builtin/docker.js +436 -0
- package/dist/plugins/builtin/docker.js.map +1 -0
- package/dist/plugins/builtin/fun.d.ts +11 -0
- package/dist/plugins/builtin/fun.d.ts.map +1 -0
- package/dist/plugins/builtin/fun.js +114 -0
- package/dist/plugins/builtin/fun.js.map +1 -0
- package/dist/plugins/builtin/gcal.d.ts +38 -0
- package/dist/plugins/builtin/gcal.d.ts.map +1 -0
- package/dist/plugins/builtin/gcal.js +280 -0
- package/dist/plugins/builtin/gcal.js.map +1 -0
- package/dist/plugins/builtin/gdrive.d.ts +26 -0
- package/dist/plugins/builtin/gdrive.d.ts.map +1 -0
- package/dist/plugins/builtin/gdrive.js +295 -0
- package/dist/plugins/builtin/gdrive.js.map +1 -0
- package/dist/plugins/builtin/github-actions.d.ts +38 -0
- package/dist/plugins/builtin/github-actions.d.ts.map +1 -0
- package/dist/plugins/builtin/github-actions.js +629 -0
- package/dist/plugins/builtin/github-actions.js.map +1 -0
- package/dist/plugins/builtin/github.d.ts +26 -0
- package/dist/plugins/builtin/github.d.ts.map +1 -0
- package/dist/plugins/builtin/github.js +800 -0
- package/dist/plugins/builtin/github.js.map +1 -0
- package/dist/plugins/builtin/gmail.d.ts +50 -0
- package/dist/plugins/builtin/gmail.d.ts.map +1 -0
- package/dist/plugins/builtin/gmail.js +445 -0
- package/dist/plugins/builtin/gmail.js.map +1 -0
- package/dist/plugins/builtin/hash.d.ts +11 -0
- package/dist/plugins/builtin/hash.d.ts.map +1 -0
- package/dist/plugins/builtin/hash.js +95 -0
- package/dist/plugins/builtin/hash.js.map +1 -0
- package/dist/plugins/builtin/homekit.d.ts +53 -0
- package/dist/plugins/builtin/homekit.d.ts.map +1 -0
- package/dist/plugins/builtin/homekit.js +341 -0
- package/dist/plugins/builtin/homekit.js.map +1 -0
- package/dist/plugins/builtin/index.d.ts +4 -0
- package/dist/plugins/builtin/index.d.ts.map +1 -0
- package/dist/plugins/builtin/index.js +96 -0
- package/dist/plugins/builtin/index.js.map +1 -0
- package/dist/plugins/builtin/jira.d.ts +50 -0
- package/dist/plugins/builtin/jira.d.ts.map +1 -0
- package/dist/plugins/builtin/jira.js +353 -0
- package/dist/plugins/builtin/jira.js.map +1 -0
- package/dist/plugins/builtin/linear.d.ts +35 -0
- package/dist/plugins/builtin/linear.d.ts.map +1 -0
- package/dist/plugins/builtin/linear.js +397 -0
- package/dist/plugins/builtin/linear.js.map +1 -0
- package/dist/plugins/builtin/lumen.d.ts +21 -0
- package/dist/plugins/builtin/lumen.d.ts.map +1 -0
- package/dist/plugins/builtin/lumen.js +404 -0
- package/dist/plugins/builtin/lumen.js.map +1 -0
- package/dist/plugins/builtin/memory.d.ts +22 -0
- package/dist/plugins/builtin/memory.d.ts.map +1 -0
- package/dist/plugins/builtin/memory.js +184 -0
- package/dist/plugins/builtin/memory.js.map +1 -0
- package/dist/plugins/builtin/n8n.d.ts +60 -0
- package/dist/plugins/builtin/n8n.d.ts.map +1 -0
- package/dist/plugins/builtin/n8n.js +519 -0
- package/dist/plugins/builtin/n8n.js.map +1 -0
- package/dist/plugins/builtin/network.d.ts +11 -0
- package/dist/plugins/builtin/network.d.ts.map +1 -0
- package/dist/plugins/builtin/network.js +88 -0
- package/dist/plugins/builtin/network.js.map +1 -0
- package/dist/plugins/builtin/notes.d.ts +47 -0
- package/dist/plugins/builtin/notes.d.ts.map +1 -0
- package/dist/plugins/builtin/notes.js +641 -0
- package/dist/plugins/builtin/notes.js.map +1 -0
- package/dist/plugins/builtin/notion.d.ts +47 -0
- package/dist/plugins/builtin/notion.d.ts.map +1 -0
- package/dist/plugins/builtin/notion.js +317 -0
- package/dist/plugins/builtin/notion.js.map +1 -0
- package/dist/plugins/builtin/shell.d.ts +12 -0
- package/dist/plugins/builtin/shell.d.ts.map +1 -0
- package/dist/plugins/builtin/shell.js +310 -0
- package/dist/plugins/builtin/shell.js.map +1 -0
- package/dist/plugins/builtin/slack.d.ts +31 -0
- package/dist/plugins/builtin/slack.d.ts.map +1 -0
- package/dist/plugins/builtin/slack.js +295 -0
- package/dist/plugins/builtin/slack.js.map +1 -0
- package/dist/plugins/builtin/spotify.d.ts +55 -0
- package/dist/plugins/builtin/spotify.d.ts.map +1 -0
- package/dist/plugins/builtin/spotify.js +623 -0
- package/dist/plugins/builtin/spotify.js.map +1 -0
- package/dist/plugins/builtin/stripe.d.ts +35 -0
- package/dist/plugins/builtin/stripe.d.ts.map +1 -0
- package/dist/plugins/builtin/stripe.js +376 -0
- package/dist/plugins/builtin/stripe.js.map +1 -0
- package/dist/plugins/builtin/system.d.ts +11 -0
- package/dist/plugins/builtin/system.d.ts.map +1 -0
- package/dist/plugins/builtin/system.js +91 -0
- package/dist/plugins/builtin/system.js.map +1 -0
- package/dist/plugins/builtin/text-tools.d.ts +11 -0
- package/dist/plugins/builtin/text-tools.d.ts.map +1 -0
- package/dist/plugins/builtin/text-tools.js +146 -0
- package/dist/plugins/builtin/text-tools.js.map +1 -0
- package/dist/plugins/builtin/timezone.d.ts +13 -0
- package/dist/plugins/builtin/timezone.d.ts.map +1 -0
- package/dist/plugins/builtin/timezone.js +164 -0
- package/dist/plugins/builtin/timezone.js.map +1 -0
- package/dist/plugins/builtin/todoist.d.ts +49 -0
- package/dist/plugins/builtin/todoist.d.ts.map +1 -0
- package/dist/plugins/builtin/todoist.js +540 -0
- package/dist/plugins/builtin/todoist.js.map +1 -0
- package/dist/plugins/builtin/translate.d.ts +11 -0
- package/dist/plugins/builtin/translate.d.ts.map +1 -0
- package/dist/plugins/builtin/translate.js +42 -0
- package/dist/plugins/builtin/translate.js.map +1 -0
- package/dist/plugins/builtin/url-tools.d.ts +11 -0
- package/dist/plugins/builtin/url-tools.d.ts.map +1 -0
- package/dist/plugins/builtin/url-tools.js +70 -0
- package/dist/plugins/builtin/url-tools.js.map +1 -0
- package/dist/plugins/builtin/vercel.d.ts +55 -0
- package/dist/plugins/builtin/vercel.d.ts.map +1 -0
- package/dist/plugins/builtin/vercel.js +514 -0
- package/dist/plugins/builtin/vercel.js.map +1 -0
- package/dist/plugins/builtin/weather.d.ts +13 -0
- package/dist/plugins/builtin/weather.d.ts.map +1 -0
- package/dist/plugins/builtin/weather.js +103 -0
- package/dist/plugins/builtin/weather.js.map +1 -0
- package/dist/plugins/builtin/x.d.ts +54 -0
- package/dist/plugins/builtin/x.d.ts.map +1 -0
- package/dist/plugins/builtin/x.js +402 -0
- package/dist/plugins/builtin/x.js.map +1 -0
- package/dist/plugins/manager.d.ts +77 -0
- package/dist/plugins/manager.d.ts.map +1 -0
- package/dist/plugins/manager.js +141 -0
- package/dist/plugins/manager.js.map +1 -0
- package/dist/plugins/validation.d.ts +18 -0
- package/dist/plugins/validation.d.ts.map +1 -0
- package/dist/plugins/validation.js +81 -0
- package/dist/plugins/validation.js.map +1 -0
- package/dist/security/auth.d.ts +23 -0
- package/dist/security/auth.d.ts.map +1 -0
- package/dist/security/auth.js +56 -0
- package/dist/security/auth.js.map +1 -0
- package/dist/security/keychain.d.ts +60 -0
- package/dist/security/keychain.d.ts.map +1 -0
- package/dist/security/keychain.js +213 -0
- package/dist/security/keychain.js.map +1 -0
- package/dist/utils/google-auth.d.ts +21 -0
- package/dist/utils/google-auth.d.ts.map +1 -0
- package/dist/utils/google-auth.js +135 -0
- package/dist/utils/google-auth.js.map +1 -0
- package/dist/utils/retry.d.ts +5 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +34 -0
- package/dist/utils/retry.js.map +1 -0
- package/docs/README.md +13 -0
- package/docs/api.md +210 -0
- package/docs/getting-started.md +100 -0
- package/docs/plugins.md +306 -0
- package/docs-site/.vitepress/config.ts +59 -0
- package/docs-site/README.md +12 -0
- package/docs-site/index.md +30 -0
- package/eslint.config.js +29 -0
- package/install.ps1 +334 -0
- package/install.sh +1119 -0
- package/local-install.sh +304 -0
- package/package.json +90 -0
- package/packages/README.md +11 -0
- package/packages/plugin-sdk/README.md +12 -0
- package/packages/plugin-sdk/package.json +22 -0
- package/packages/plugin-sdk/src/README.md +11 -0
- package/packages/plugin-sdk/src/index.ts +191 -0
- package/sdks/README.md +26 -0
- package/sdks/csharp/ConductorClient.cs +65 -0
- package/sdks/csharp/README.md +11 -0
- package/sdks/go/README.md +11 -0
- package/sdks/go/conductor.go +257 -0
- package/sdks/java/ConductorClient.java +27 -0
- package/sdks/java/README.md +11 -0
- package/sdks/php/README.md +11 -0
- package/sdks/php/src/Client.php +72 -0
- package/sdks/python/README.md +12 -0
- package/sdks/python/conductor/__init__.py +227 -0
- package/sdks/python/pyproject.toml +30 -0
- package/sdks/ruby/README.md +11 -0
- package/sdks/ruby/lib/conductor.rb +46 -0
- package/sdks/rust/Cargo.toml +14 -0
- package/sdks/rust/README.md +11 -0
- package/sdks/swift/README.md +11 -0
- package/sdks/swift/Sources/Conductor/ConductorClient.swift +65 -0
- package/skills/conductor-mcp/SKILL.md +38 -0
- package/src/README.md +20 -0
- package/src/ai/README.md +18 -0
- package/src/ai/base.ts +93 -0
- package/src/ai/claude.ts +162 -0
- package/src/ai/gemini.ts +188 -0
- package/src/ai/maestro.ts +168 -0
- package/src/ai/manager.ts +537 -0
- package/src/ai/ollama.ts +186 -0
- package/src/ai/openai.ts +147 -0
- package/src/ai/openrouter.ts +152 -0
- package/src/bot/README.md +12 -0
- package/src/bot/slack.ts +164 -0
- package/src/bot/telegram.ts +185 -0
- package/src/cli/README.md +24 -0
- package/src/cli/commands/README.md +20 -0
- package/src/cli/commands/ai.ts +170 -0
- package/src/cli/commands/doctor.ts +221 -0
- package/src/cli/commands/init.ts +348 -0
- package/src/cli/commands/install.ts +792 -0
- package/src/cli/commands/lifecycle.ts +95 -0
- package/src/cli/commands/marketplace.ts +253 -0
- package/src/cli/commands/mcp.ts +92 -0
- package/src/cli/commands/onboard.ts +248 -0
- package/src/cli/commands/plugin-create.ts +130 -0
- package/src/cli/commands/plugins.ts +36 -0
- package/src/cli/commands/release.ts +251 -0
- package/src/cli/commands/telegram.ts +25 -0
- package/src/cli/index.ts +450 -0
- package/src/config/README.md +11 -0
- package/src/config/oauth.ts +26 -0
- package/src/core/README.md +22 -0
- package/src/core/audit.ts +291 -0
- package/src/core/circuit-breaker.ts +129 -0
- package/src/core/conductor.ts +240 -0
- package/src/core/config.ts +149 -0
- package/src/core/database.ts +411 -0
- package/src/core/errors.ts +275 -0
- package/src/core/health.ts +159 -0
- package/src/core/interfaces.ts +75 -0
- package/src/core/logger.ts +33 -0
- package/src/core/rbac.ts +321 -0
- package/src/core/retry.ts +61 -0
- package/src/core/webhooks.ts +234 -0
- package/src/core/zero-config.ts +72 -0
- package/src/dashboard/README.md +15 -0
- package/src/dashboard/cli.ts +48 -0
- package/src/dashboard/index.html +3426 -0
- package/src/dashboard/server.ts +1544 -0
- package/src/mcp/README.md +20 -0
- package/src/mcp/server.ts +475 -0
- package/src/mcp/tools/README.md +11 -0
- package/src/mcp/tools/misc.ts +61 -0
- package/src/plugins/README.md +28 -0
- package/src/plugins/builtin/README.md +23 -0
- package/src/plugins/builtin/calculator.ts +178 -0
- package/src/plugins/builtin/colors.ts +201 -0
- package/src/plugins/builtin/cron.ts +649 -0
- package/src/plugins/builtin/crypto.ts +85 -0
- package/src/plugins/builtin/database.ts +235 -0
- package/src/plugins/builtin/docker.ts +426 -0
- package/src/plugins/builtin/fun.ts +118 -0
- package/src/plugins/builtin/gcal.ts +305 -0
- package/src/plugins/builtin/gdrive.ts +326 -0
- package/src/plugins/builtin/github-actions.ts +666 -0
- package/src/plugins/builtin/github.ts +912 -0
- package/src/plugins/builtin/gmail.ts +492 -0
- package/src/plugins/builtin/hash.ts +98 -0
- package/src/plugins/builtin/homekit.ts +389 -0
- package/src/plugins/builtin/index.ts +116 -0
- package/src/plugins/builtin/jira.ts +380 -0
- package/src/plugins/builtin/linear.ts +448 -0
- package/src/plugins/builtin/lumen.ts +497 -0
- package/src/plugins/builtin/memory.ts +200 -0
- package/src/plugins/builtin/n8n.ts +565 -0
- package/src/plugins/builtin/network.ts +92 -0
- package/src/plugins/builtin/notes.ts +689 -0
- package/src/plugins/builtin/notion.ts +348 -0
- package/src/plugins/builtin/shell.ts +334 -0
- package/src/plugins/builtin/slack.ts +327 -0
- package/src/plugins/builtin/spotify.ts +665 -0
- package/src/plugins/builtin/stripe.ts +388 -0
- package/src/plugins/builtin/system.ts +93 -0
- package/src/plugins/builtin/text-tools.ts +150 -0
- package/src/plugins/builtin/timezone.ts +173 -0
- package/src/plugins/builtin/todoist.ts +625 -0
- package/src/plugins/builtin/translate.ts +47 -0
- package/src/plugins/builtin/url-tools.ts +73 -0
- package/src/plugins/builtin/vercel.ts +546 -0
- package/src/plugins/builtin/weather.ts +112 -0
- package/src/plugins/builtin/x.ts +440 -0
- package/src/plugins/manager.ts +213 -0
- package/src/plugins/validation.ts +94 -0
- package/src/security/README.md +12 -0
- package/src/security/auth.ts +72 -0
- package/src/security/keychain.ts +226 -0
- package/src/utils/README.md +12 -0
- package/src/utils/google-auth.ts +159 -0
- package/src/utils/retry.ts +41 -0
- package/test-all.mjs +1256 -0
- package/test.mjs +633 -0
- package/tests/README.md +19 -0
- package/tests/calculator.test.ts +54 -0
- package/tests/docker.test.ts +42 -0
- package/tests/load.test.ts +129 -0
- package/tests/mcp.test.ts +14 -0
- package/tests/shell.test.ts +42 -0
- package/tsconfig.json +21 -0
- package/vitest.config.ts +14 -0
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Todoist Plugin — Conductor
|
|
3
|
+
*
|
|
4
|
+
* Manage tasks, projects, and comments in Todoist.
|
|
5
|
+
* Uses the Todoist REST API v2 with a personal API token.
|
|
6
|
+
*
|
|
7
|
+
* Setup:
|
|
8
|
+
* 1. Go to https://app.todoist.com/app/settings/integrations/developer
|
|
9
|
+
* 2. Scroll to "API token" and copy your token
|
|
10
|
+
* 3. Run: conductor plugins config todoist api_token <YOUR_TOKEN>
|
|
11
|
+
* OR set it during install when prompted
|
|
12
|
+
*
|
|
13
|
+
* Keychain entry: todoist / api_token
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { z, ZodError } from 'zod';
|
|
17
|
+
import { Plugin, PluginTool } from '../manager.js';
|
|
18
|
+
import { Conductor } from '../../core/conductor.js';
|
|
19
|
+
import { Keychain } from '../../security/keychain.js';
|
|
20
|
+
|
|
21
|
+
// ── Constants ─────────────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
const TODOIST_BASE = 'https://api.todoist.com/api/v1';
|
|
24
|
+
|
|
25
|
+
// ── Todoist API types ─────────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
interface TodoistTask {
|
|
28
|
+
id: string;
|
|
29
|
+
content: string;
|
|
30
|
+
description: string;
|
|
31
|
+
project_id: string;
|
|
32
|
+
section_id: string | null;
|
|
33
|
+
parent_id: string | null;
|
|
34
|
+
labels: string[];
|
|
35
|
+
priority: number;
|
|
36
|
+
due: {
|
|
37
|
+
date: string;
|
|
38
|
+
string: string;
|
|
39
|
+
datetime?: string;
|
|
40
|
+
is_recurring: boolean;
|
|
41
|
+
} | null;
|
|
42
|
+
url: string;
|
|
43
|
+
comment_count: number;
|
|
44
|
+
created_at: string;
|
|
45
|
+
creator_id: string;
|
|
46
|
+
checked: boolean;
|
|
47
|
+
order: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface TodoistProject {
|
|
51
|
+
id: string;
|
|
52
|
+
name: string;
|
|
53
|
+
color: string;
|
|
54
|
+
parent_id: string | null;
|
|
55
|
+
order: number;
|
|
56
|
+
comment_count: number;
|
|
57
|
+
is_shared: boolean;
|
|
58
|
+
is_favorite: boolean;
|
|
59
|
+
is_inbox_project: boolean;
|
|
60
|
+
is_team_inbox: boolean;
|
|
61
|
+
url: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
interface TodoistComment {
|
|
65
|
+
id: string;
|
|
66
|
+
task_id: string;
|
|
67
|
+
content: string;
|
|
68
|
+
posted_at: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ── Priority helpers ──────────────────────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
const PRIORITY_LABELS: Record<number, string> = {
|
|
74
|
+
1: 'normal',
|
|
75
|
+
2: 'medium',
|
|
76
|
+
3: 'high',
|
|
77
|
+
4: 'urgent',
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
function priorityLabel(p: number): string {
|
|
81
|
+
return PRIORITY_LABELS[p] ?? `p${p}`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function formatDue(due: TodoistTask['due']): string {
|
|
85
|
+
if (!due) return 'no due date';
|
|
86
|
+
return due.string ?? due.date;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ── Plugin class ──────────────────────────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
export class TodoistPlugin implements Plugin {
|
|
92
|
+
name = 'todoist';
|
|
93
|
+
description = 'Manage Todoist tasks, projects, and comments — requires Todoist API token';
|
|
94
|
+
version = '1.0.0';
|
|
95
|
+
|
|
96
|
+
configSchema = {
|
|
97
|
+
fields: [
|
|
98
|
+
{
|
|
99
|
+
key: 'api_token',
|
|
100
|
+
label: 'API Token',
|
|
101
|
+
type: 'password' as const,
|
|
102
|
+
required: true,
|
|
103
|
+
secret: true,
|
|
104
|
+
service: 'todoist',
|
|
105
|
+
description: 'Copy your token from Todoist Settings > Integrations > Developer.',
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
setupInstructions:
|
|
109
|
+
'1. Open Todoist and go to Settings > Integrations > Developer. ' +
|
|
110
|
+
'2. Copy the "API token" shown at the bottom of the page. ' +
|
|
111
|
+
'3. Run: conductor plugins config todoist api_token <YOUR_TOKEN>',
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
private keychain!: Keychain;
|
|
115
|
+
|
|
116
|
+
async initialize(conductor: Conductor): Promise<void> {
|
|
117
|
+
this.keychain = new Keychain(conductor.getConfig().getConfigDir());
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
isConfigured(): boolean {
|
|
121
|
+
return true; // lazily validated on first tool call via getToken()
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async getContext(): Promise<string | null> {
|
|
125
|
+
try {
|
|
126
|
+
const overdue: TodoistTask[] = await this.todoistFetch('/tasks', { params: { filter: 'overdue' } });
|
|
127
|
+
const today: TodoistTask[] = await this.todoistFetch('/tasks', { params: { filter: 'today' } });
|
|
128
|
+
const parts: string[] = [];
|
|
129
|
+
if (overdue.length > 0) parts.push(`${overdue.length} overdue`);
|
|
130
|
+
if (today.length > 0) parts.push(`${today.length} due today`);
|
|
131
|
+
if (parts.length === 0) return null;
|
|
132
|
+
return `[TODOIST] Tasks: ${parts.join(', ')}`;
|
|
133
|
+
} catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ── Internal helpers ──────────────────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
private async getToken(): Promise<string> {
|
|
141
|
+
const token = await this.keychain.get('todoist', 'api_token');
|
|
142
|
+
if (!token) {
|
|
143
|
+
throw new Error(
|
|
144
|
+
'Todoist not configured. Get your API token from ' +
|
|
145
|
+
'https://app.todoist.com/app/settings/integrations/developer\n' +
|
|
146
|
+
'Then run: conductor plugins config todoist api_token <YOUR_TOKEN>',
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return token;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Thin wrapper around the Todoist REST API v2.
|
|
154
|
+
* Handles auth, JSON encoding, and error surfacing.
|
|
155
|
+
*/
|
|
156
|
+
private async todoistFetch(
|
|
157
|
+
path: string,
|
|
158
|
+
options: {
|
|
159
|
+
method?: 'GET' | 'POST' | 'DELETE';
|
|
160
|
+
params?: Record<string, string>;
|
|
161
|
+
body?: Record<string, unknown>;
|
|
162
|
+
} = {},
|
|
163
|
+
): Promise<any> {
|
|
164
|
+
const token = await this.getToken();
|
|
165
|
+
const { method = 'GET', params, body } = options;
|
|
166
|
+
|
|
167
|
+
let url = `${TODOIST_BASE}${path}`;
|
|
168
|
+
if (params) {
|
|
169
|
+
const qs = new URLSearchParams(params).toString();
|
|
170
|
+
if (qs) url += `?${qs}`;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const res = await fetch(url, {
|
|
174
|
+
method,
|
|
175
|
+
headers: {
|
|
176
|
+
Authorization: `Bearer ${token}`,
|
|
177
|
+
'Content-Type': 'application/json',
|
|
178
|
+
},
|
|
179
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
if (res.status === 204) {
|
|
183
|
+
// No content — successful operation with no body (e.g. close, delete)
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (!res.ok) {
|
|
188
|
+
const text = await res.text().catch(() => res.statusText);
|
|
189
|
+
throw new Error(`Todoist API ${res.status}: ${text}`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const data = await res.json();
|
|
193
|
+
// API v1 wraps list responses in { results: [], next_cursor }
|
|
194
|
+
// Single-item responses (create/update) return the object directly
|
|
195
|
+
if (data !== null && typeof data === 'object' && Array.isArray((data as any).results)) {
|
|
196
|
+
return (data as any).results;
|
|
197
|
+
}
|
|
198
|
+
return data;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ── Formatters ────────────────────────────────────────────────────────────
|
|
202
|
+
|
|
203
|
+
/** Format a single task into a clean markdown string. */
|
|
204
|
+
private formatTask(task: TodoistTask): string {
|
|
205
|
+
const priority = task.priority > 1 ? ` [P${5 - task.priority} — ${priorityLabel(task.priority)}]` : '';
|
|
206
|
+
const due = task.due ? ` | Due: ${formatDue(task.due)}` : '';
|
|
207
|
+
const labels = task.labels.length ? ` | Labels: ${task.labels.join(', ')}` : '';
|
|
208
|
+
const desc = task.description ? `\n ${task.description}` : '';
|
|
209
|
+
return `- [${task.id}] **${task.content}**${priority}${due}${labels}${desc}`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** Format a project into a single-line summary. */
|
|
213
|
+
private formatProject(project: TodoistProject): string {
|
|
214
|
+
const inbox = project.is_inbox_project ? ' (Inbox)' : '';
|
|
215
|
+
const fav = project.is_favorite ? ' ★' : '';
|
|
216
|
+
const shared = project.is_shared ? ' (shared)' : '';
|
|
217
|
+
return `- [${project.id}] **${project.name}**${inbox}${fav}${shared}`;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ── Tools ─────────────────────────────────────────────────────────────────
|
|
221
|
+
|
|
222
|
+
getTools(): PluginTool[] {
|
|
223
|
+
return [
|
|
224
|
+
// ── todoist_list_tasks ────────────────────────────────────────────────
|
|
225
|
+
{
|
|
226
|
+
name: 'todoist_list_tasks',
|
|
227
|
+
description:
|
|
228
|
+
'List active Todoist tasks. Optionally filter by project ID, label name, or a ' +
|
|
229
|
+
'Todoist filter string (e.g. "today", "overdue", "p1", "#Work & @urgent").',
|
|
230
|
+
inputSchema: {
|
|
231
|
+
type: 'object',
|
|
232
|
+
properties: {
|
|
233
|
+
project_id: {
|
|
234
|
+
type: 'string',
|
|
235
|
+
description: 'Only return tasks in this project (use todoist_get_projects to find IDs)',
|
|
236
|
+
},
|
|
237
|
+
label: {
|
|
238
|
+
type: 'string',
|
|
239
|
+
description: 'Only return tasks with this label name',
|
|
240
|
+
},
|
|
241
|
+
filter: {
|
|
242
|
+
type: 'string',
|
|
243
|
+
description:
|
|
244
|
+
'Todoist filter string, e.g. "today", "overdue", "p1", "assigned to: me". ' +
|
|
245
|
+
'Cannot be combined with project_id or label.',
|
|
246
|
+
},
|
|
247
|
+
limit: {
|
|
248
|
+
type: 'number',
|
|
249
|
+
description: 'Max number of tasks to return (default: 50)',
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
handler: async (rawInput: Record<string, unknown>) => {
|
|
254
|
+
try {
|
|
255
|
+
const schema = z.object({
|
|
256
|
+
project_id: z.string().optional(),
|
|
257
|
+
label: z.string().optional(),
|
|
258
|
+
filter: z.string().optional(),
|
|
259
|
+
limit: z.number().int().min(1).max(200).optional().default(50),
|
|
260
|
+
});
|
|
261
|
+
const { project_id, label, filter, limit } = schema.parse(rawInput);
|
|
262
|
+
|
|
263
|
+
const params: Record<string, string> = {};
|
|
264
|
+
if (project_id) params.project_id = project_id;
|
|
265
|
+
if (label) params.label = label;
|
|
266
|
+
if (filter) params.filter = filter;
|
|
267
|
+
|
|
268
|
+
const tasks: TodoistTask[] = await this.todoistFetch('/tasks', { params });
|
|
269
|
+
const slice = tasks.slice(0, limit);
|
|
270
|
+
|
|
271
|
+
if (slice.length === 0) {
|
|
272
|
+
return 'No tasks found matching the given criteria.';
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const lines = slice.map((t) => this.formatTask(t));
|
|
276
|
+
const header =
|
|
277
|
+
`Found ${slice.length} task${slice.length !== 1 ? 's' : ''}` +
|
|
278
|
+
(tasks.length > limit ? ` (showing first ${limit} of ${tasks.length})` : '') +
|
|
279
|
+
':';
|
|
280
|
+
|
|
281
|
+
return `${header}\n\n${lines.join('\n')}`;
|
|
282
|
+
} catch (err: unknown) {
|
|
283
|
+
if (err instanceof ZodError)
|
|
284
|
+
return `Validation error: ${err.issues.map((e) => `${e.path.join('.')}: ${(e as any).message}`).join('; ')}`;
|
|
285
|
+
return `Error listing tasks: ${(err as Error).message}`;
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
// ── todoist_create_task ───────────────────────────────────────────────
|
|
291
|
+
{
|
|
292
|
+
name: 'todoist_create_task',
|
|
293
|
+
description:
|
|
294
|
+
'Create a new Todoist task. Supports natural-language due dates like ' +
|
|
295
|
+
'"tomorrow at 3pm", "every Monday", or "in 2 weeks".',
|
|
296
|
+
inputSchema: {
|
|
297
|
+
type: 'object',
|
|
298
|
+
properties: {
|
|
299
|
+
content: {
|
|
300
|
+
type: 'string',
|
|
301
|
+
description: 'Task name / content (required)',
|
|
302
|
+
},
|
|
303
|
+
description: {
|
|
304
|
+
type: 'string',
|
|
305
|
+
description: 'Optional longer description or notes',
|
|
306
|
+
},
|
|
307
|
+
due_string: {
|
|
308
|
+
type: 'string',
|
|
309
|
+
description: 'Natural language due date, e.g. "tomorrow at 3pm", "next Monday", "every week"',
|
|
310
|
+
},
|
|
311
|
+
priority: {
|
|
312
|
+
type: 'number',
|
|
313
|
+
description: 'Priority: 1 = normal, 2 = medium, 3 = high, 4 = urgent (Todoist P4–P1)',
|
|
314
|
+
},
|
|
315
|
+
project_id: {
|
|
316
|
+
type: 'string',
|
|
317
|
+
description: 'Project to add the task to (defaults to Inbox)',
|
|
318
|
+
},
|
|
319
|
+
labels: {
|
|
320
|
+
type: 'array',
|
|
321
|
+
items: { type: 'string' },
|
|
322
|
+
description: 'Label names to attach, e.g. ["work", "urgent"]',
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
required: ['content'],
|
|
326
|
+
},
|
|
327
|
+
handler: async (rawInput: Record<string, unknown>) => {
|
|
328
|
+
try {
|
|
329
|
+
const schema = z.object({
|
|
330
|
+
content: z.string().min(1, 'content is required'),
|
|
331
|
+
description: z.string().optional(),
|
|
332
|
+
due_string: z.string().optional(),
|
|
333
|
+
priority: z.number().int().min(1).max(4).optional(),
|
|
334
|
+
project_id: z.string().optional(),
|
|
335
|
+
labels: z.array(z.string()).optional(),
|
|
336
|
+
});
|
|
337
|
+
const { content, description, due_string, priority, project_id, labels } = schema.parse(rawInput);
|
|
338
|
+
|
|
339
|
+
const body: Record<string, unknown> = { content };
|
|
340
|
+
if (description) body.description = description;
|
|
341
|
+
if (due_string) body.due_string = due_string;
|
|
342
|
+
if (priority !== undefined) body.priority = priority;
|
|
343
|
+
if (project_id) body.project_id = project_id;
|
|
344
|
+
if (labels?.length) body.labels = labels;
|
|
345
|
+
|
|
346
|
+
const task: TodoistTask = await this.todoistFetch('/tasks', {
|
|
347
|
+
method: 'POST',
|
|
348
|
+
body,
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
const lines = [`Task created successfully.`, ``, `**${task.content}** [ID: ${task.id}]`];
|
|
352
|
+
if (task.description) lines.push(`Description: ${task.description}`);
|
|
353
|
+
if (task.due) lines.push(`Due: ${formatDue(task.due)}`);
|
|
354
|
+
if (task.priority > 1) lines.push(`Priority: ${priorityLabel(task.priority)}`);
|
|
355
|
+
if (task.labels.length) lines.push(`Labels: ${task.labels.join(', ')}`);
|
|
356
|
+
lines.push(`URL: ${task.url}`);
|
|
357
|
+
|
|
358
|
+
return lines.join('\n');
|
|
359
|
+
} catch (err: unknown) {
|
|
360
|
+
if (err instanceof ZodError)
|
|
361
|
+
return `Validation error: ${err.issues.map((e) => `${e.path.join('.')}: ${(e as any).message}`).join('; ')}`;
|
|
362
|
+
return `Error creating task: ${(err as Error).message}`;
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
|
|
367
|
+
// ── todoist_complete_task ─────────────────────────────────────────────
|
|
368
|
+
{
|
|
369
|
+
name: 'todoist_complete_task',
|
|
370
|
+
description: 'Mark a Todoist task as completed (closed) by its ID.',
|
|
371
|
+
inputSchema: {
|
|
372
|
+
type: 'object',
|
|
373
|
+
properties: {
|
|
374
|
+
task_id: {
|
|
375
|
+
type: 'string',
|
|
376
|
+
description: 'The task ID to mark as complete',
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
required: ['task_id'],
|
|
380
|
+
},
|
|
381
|
+
handler: async (rawInput: Record<string, unknown>) => {
|
|
382
|
+
try {
|
|
383
|
+
const schema = z.object({ task_id: z.string().min(1, 'task_id is required') });
|
|
384
|
+
const { task_id } = schema.parse(rawInput);
|
|
385
|
+
await this.todoistFetch(`/tasks/${encodeURIComponent(task_id)}/close`, {
|
|
386
|
+
method: 'POST',
|
|
387
|
+
});
|
|
388
|
+
return `Task ${task_id} marked as complete.`;
|
|
389
|
+
} catch (err: unknown) {
|
|
390
|
+
if (err instanceof ZodError)
|
|
391
|
+
return `Validation error: ${err.issues.map((e) => `${e.path.join('.')}: ${(e as any).message}`).join('; ')}`;
|
|
392
|
+
return `Error completing task: ${(err as Error).message}`;
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
|
|
397
|
+
// ── todoist_update_task ───────────────────────────────────────────────
|
|
398
|
+
{
|
|
399
|
+
name: 'todoist_update_task',
|
|
400
|
+
description: 'Update an existing task — change its content, description, due date, or priority.',
|
|
401
|
+
inputSchema: {
|
|
402
|
+
type: 'object',
|
|
403
|
+
properties: {
|
|
404
|
+
task_id: {
|
|
405
|
+
type: 'string',
|
|
406
|
+
description: 'The task ID to update',
|
|
407
|
+
},
|
|
408
|
+
content: {
|
|
409
|
+
type: 'string',
|
|
410
|
+
description: 'New task name / content',
|
|
411
|
+
},
|
|
412
|
+
description: {
|
|
413
|
+
type: 'string',
|
|
414
|
+
description: 'New description / notes',
|
|
415
|
+
},
|
|
416
|
+
due_string: {
|
|
417
|
+
type: 'string',
|
|
418
|
+
description: 'New due date as natural language, e.g. "next Friday at 10am"',
|
|
419
|
+
},
|
|
420
|
+
priority: {
|
|
421
|
+
type: 'number',
|
|
422
|
+
description: 'New priority: 1 = normal, 2 = medium, 3 = high, 4 = urgent',
|
|
423
|
+
},
|
|
424
|
+
labels: {
|
|
425
|
+
type: 'array',
|
|
426
|
+
items: { type: 'string' },
|
|
427
|
+
description: 'Replace all labels with this list',
|
|
428
|
+
},
|
|
429
|
+
},
|
|
430
|
+
required: ['task_id'],
|
|
431
|
+
},
|
|
432
|
+
handler: async (rawInput: Record<string, unknown>) => {
|
|
433
|
+
try {
|
|
434
|
+
const schema = z.object({
|
|
435
|
+
task_id: z.string().min(1, 'task_id is required'),
|
|
436
|
+
content: z.string().optional(),
|
|
437
|
+
description: z.string().optional(),
|
|
438
|
+
due_string: z.string().optional(),
|
|
439
|
+
priority: z.number().int().min(1).max(4).optional(),
|
|
440
|
+
labels: z.array(z.string()).optional(),
|
|
441
|
+
});
|
|
442
|
+
const { task_id, content, description, due_string, priority, labels } = schema.parse(rawInput);
|
|
443
|
+
|
|
444
|
+
const body: Record<string, unknown> = {};
|
|
445
|
+
if (content !== undefined) body.content = content;
|
|
446
|
+
if (description !== undefined) body.description = description;
|
|
447
|
+
if (due_string !== undefined) body.due_string = due_string;
|
|
448
|
+
if (priority !== undefined) body.priority = priority;
|
|
449
|
+
if (labels !== undefined) body.labels = labels;
|
|
450
|
+
|
|
451
|
+
if (Object.keys(body).length === 0) {
|
|
452
|
+
return 'No fields to update were provided.';
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const task: TodoistTask = await this.todoistFetch(`/tasks/${encodeURIComponent(task_id)}`, {
|
|
456
|
+
method: 'POST',
|
|
457
|
+
body,
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
const lines = [`Task updated successfully.`, ``, `**${task.content}** [ID: ${task.id}]`];
|
|
461
|
+
if (task.description) lines.push(`Description: ${task.description}`);
|
|
462
|
+
if (task.due) lines.push(`Due: ${formatDue(task.due)}`);
|
|
463
|
+
if (task.priority > 1) lines.push(`Priority: ${priorityLabel(task.priority)}`);
|
|
464
|
+
if (task.labels.length) lines.push(`Labels: ${task.labels.join(', ')}`);
|
|
465
|
+
|
|
466
|
+
return lines.join('\n');
|
|
467
|
+
} catch (err: unknown) {
|
|
468
|
+
if (err instanceof ZodError)
|
|
469
|
+
return `Validation error: ${err.issues.map((e) => `${e.path.join('.')}: ${(e as any).message}`).join('; ')}`;
|
|
470
|
+
return `Error updating task: ${(err as Error).message}`;
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
|
|
475
|
+
// ── todoist_delete_task ───────────────────────────────────────────────
|
|
476
|
+
{
|
|
477
|
+
name: 'todoist_delete_task',
|
|
478
|
+
description:
|
|
479
|
+
'Permanently delete a task from Todoist. This cannot be undone. ' +
|
|
480
|
+
'Prefer todoist_complete_task unless the task should be fully removed.',
|
|
481
|
+
inputSchema: {
|
|
482
|
+
type: 'object',
|
|
483
|
+
properties: {
|
|
484
|
+
task_id: {
|
|
485
|
+
type: 'string',
|
|
486
|
+
description: 'The task ID to permanently delete',
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
required: ['task_id'],
|
|
490
|
+
},
|
|
491
|
+
requiresApproval: true,
|
|
492
|
+
handler: async (rawInput: Record<string, unknown>) => {
|
|
493
|
+
try {
|
|
494
|
+
const schema = z.object({ task_id: z.string().min(1, 'task_id is required') });
|
|
495
|
+
const { task_id } = schema.parse(rawInput);
|
|
496
|
+
await this.todoistFetch(`/tasks/${encodeURIComponent(task_id)}`, {
|
|
497
|
+
method: 'DELETE',
|
|
498
|
+
});
|
|
499
|
+
return `Task ${task_id} has been permanently deleted.`;
|
|
500
|
+
} catch (err: unknown) {
|
|
501
|
+
if (err instanceof ZodError)
|
|
502
|
+
return `Validation error: ${err.issues.map((e) => `${e.path.join('.')}: ${(e as any).message}`).join('; ')}`;
|
|
503
|
+
return `Error deleting task: ${(err as Error).message}`;
|
|
504
|
+
}
|
|
505
|
+
},
|
|
506
|
+
},
|
|
507
|
+
|
|
508
|
+
// ── todoist_get_projects ──────────────────────────────────────────────
|
|
509
|
+
{
|
|
510
|
+
name: 'todoist_get_projects',
|
|
511
|
+
description: 'List all Todoist projects in the account.',
|
|
512
|
+
inputSchema: {
|
|
513
|
+
type: 'object',
|
|
514
|
+
properties: {},
|
|
515
|
+
},
|
|
516
|
+
handler: async (_rawInput: Record<string, unknown>) => {
|
|
517
|
+
try {
|
|
518
|
+
const projects: TodoistProject[] = await this.todoistFetch('/projects');
|
|
519
|
+
|
|
520
|
+
if (projects.length === 0) {
|
|
521
|
+
return 'No projects found.';
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
const lines = projects.map((p) => this.formatProject(p));
|
|
525
|
+
return `${projects.length} project${projects.length !== 1 ? 's' : ''}:\n\n${lines.join('\n')}`;
|
|
526
|
+
} catch (err: unknown) {
|
|
527
|
+
return `Error fetching projects: ${(err as Error).message}`;
|
|
528
|
+
}
|
|
529
|
+
},
|
|
530
|
+
},
|
|
531
|
+
|
|
532
|
+
// ── todoist_search_tasks ──────────────────────────────────────────────
|
|
533
|
+
{
|
|
534
|
+
name: 'todoist_search_tasks',
|
|
535
|
+
description:
|
|
536
|
+
'Search tasks using Todoist\'s filter syntax. Examples: "today", "overdue", ' +
|
|
537
|
+
'"p1", "#Work", "@label", "assigned to: me", "created before: -7 days".',
|
|
538
|
+
inputSchema: {
|
|
539
|
+
type: 'object',
|
|
540
|
+
properties: {
|
|
541
|
+
filter: {
|
|
542
|
+
type: 'string',
|
|
543
|
+
description: 'Todoist filter expression',
|
|
544
|
+
},
|
|
545
|
+
limit: {
|
|
546
|
+
type: 'number',
|
|
547
|
+
description: 'Max results to return (default: 50)',
|
|
548
|
+
},
|
|
549
|
+
},
|
|
550
|
+
required: ['filter'],
|
|
551
|
+
},
|
|
552
|
+
handler: async (rawInput: Record<string, unknown>) => {
|
|
553
|
+
try {
|
|
554
|
+
const schema = z.object({
|
|
555
|
+
filter: z.string().min(1, 'filter is required'),
|
|
556
|
+
limit: z.number().int().min(1).max(200).optional().default(50),
|
|
557
|
+
});
|
|
558
|
+
const { filter, limit } = schema.parse(rawInput);
|
|
559
|
+
|
|
560
|
+
const tasks: TodoistTask[] = await this.todoistFetch('/tasks', {
|
|
561
|
+
params: { filter },
|
|
562
|
+
});
|
|
563
|
+
const slice = tasks.slice(0, limit);
|
|
564
|
+
|
|
565
|
+
if (slice.length === 0) {
|
|
566
|
+
return `No tasks matched the filter: "${filter}"`;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
const lines = slice.map((t) => this.formatTask(t));
|
|
570
|
+
const header =
|
|
571
|
+
`Found ${slice.length} task${slice.length !== 1 ? 's' : ''} matching "${filter}"` +
|
|
572
|
+
(tasks.length > limit ? ` (showing first ${limit} of ${tasks.length})` : '') +
|
|
573
|
+
':';
|
|
574
|
+
|
|
575
|
+
return `${header}\n\n${lines.join('\n')}`;
|
|
576
|
+
} catch (err: unknown) {
|
|
577
|
+
if (err instanceof ZodError)
|
|
578
|
+
return `Validation error: ${err.issues.map((e) => `${e.path.join('.')}: ${(e as any).message}`).join('; ')}`;
|
|
579
|
+
return `Error searching tasks: ${(err as Error).message}`;
|
|
580
|
+
}
|
|
581
|
+
},
|
|
582
|
+
},
|
|
583
|
+
|
|
584
|
+
// ── todoist_add_comment ───────────────────────────────────────────────
|
|
585
|
+
{
|
|
586
|
+
name: 'todoist_add_comment',
|
|
587
|
+
description: 'Add a comment to a Todoist task.',
|
|
588
|
+
inputSchema: {
|
|
589
|
+
type: 'object',
|
|
590
|
+
properties: {
|
|
591
|
+
task_id: {
|
|
592
|
+
type: 'string',
|
|
593
|
+
description: 'The task ID to comment on',
|
|
594
|
+
},
|
|
595
|
+
content: {
|
|
596
|
+
type: 'string',
|
|
597
|
+
description: 'The comment text',
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
required: ['task_id', 'content'],
|
|
601
|
+
},
|
|
602
|
+
handler: async (rawInput: Record<string, unknown>) => {
|
|
603
|
+
try {
|
|
604
|
+
const schema = z.object({
|
|
605
|
+
task_id: z.string().min(1, 'task_id is required'),
|
|
606
|
+
content: z.string().min(1, 'content is required'),
|
|
607
|
+
});
|
|
608
|
+
const { task_id, content } = schema.parse(rawInput);
|
|
609
|
+
const comment: TodoistComment = await this.todoistFetch('/comments', {
|
|
610
|
+
method: 'POST',
|
|
611
|
+
body: { task_id, content },
|
|
612
|
+
});
|
|
613
|
+
return (
|
|
614
|
+
`Comment added to task ${task_id}.\n` + `Comment ID: ${comment.id}\n` + `Posted at: ${comment.posted_at}`
|
|
615
|
+
);
|
|
616
|
+
} catch (err: unknown) {
|
|
617
|
+
if (err instanceof ZodError)
|
|
618
|
+
return `Validation error: ${err.issues.map((e) => `${e.path.join('.')}: ${(e as any).message}`).join('; ')}`;
|
|
619
|
+
return `Error adding comment: ${(err as Error).message}`;
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
},
|
|
623
|
+
];
|
|
624
|
+
}
|
|
625
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Plugin, PluginTool } from '../manager.js';
|
|
2
|
+
import { Conductor } from '../../core/conductor.js';
|
|
3
|
+
|
|
4
|
+
export class TranslatePlugin implements Plugin {
|
|
5
|
+
name = 'translate';
|
|
6
|
+
description = 'Translate text between languages (free, no API key)';
|
|
7
|
+
version = '1.0.0';
|
|
8
|
+
|
|
9
|
+
async initialize(_conductor: Conductor): Promise<void> {}
|
|
10
|
+
isConfigured(): boolean {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
getTools(): PluginTool[] {
|
|
15
|
+
return [
|
|
16
|
+
{
|
|
17
|
+
name: 'translate_text',
|
|
18
|
+
description: 'Translate text between languages. Use ISO 639-1 codes (en, fr, es, de, ja, zh, ko, ar, etc.)',
|
|
19
|
+
inputSchema: {
|
|
20
|
+
type: 'object',
|
|
21
|
+
properties: {
|
|
22
|
+
text: { type: 'string', description: 'Text to translate' },
|
|
23
|
+
from: { type: 'string', description: 'Source language code (e.g. en)', default: 'auto' },
|
|
24
|
+
to: { type: 'string', description: 'Target language code (e.g. fr)' },
|
|
25
|
+
},
|
|
26
|
+
required: ['text', 'to'],
|
|
27
|
+
},
|
|
28
|
+
handler: async (input: { text: string; from?: string; to: string }) => {
|
|
29
|
+
const from = input.from || 'auto';
|
|
30
|
+
const pair = `${from}|${input.to}`;
|
|
31
|
+
const res = await fetch(
|
|
32
|
+
`https://api.mymemory.translated.net/get?q=${encodeURIComponent(input.text)}&langpair=${encodeURIComponent(pair)}`,
|
|
33
|
+
);
|
|
34
|
+
if (!res.ok) throw new Error(`Translation API error: ${res.statusText}`);
|
|
35
|
+
const data = (await res.json()) as any;
|
|
36
|
+
return {
|
|
37
|
+
original: input.text,
|
|
38
|
+
translated: data.responseData?.translatedText || 'Translation failed',
|
|
39
|
+
from,
|
|
40
|
+
to: input.to,
|
|
41
|
+
confidence: data.responseData?.match,
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
}
|