@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
package/test.mjs
ADDED
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Conductor Test Suite
|
|
4
|
+
* Tests all 29 plugins and 146 tools.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node test.mjs # Run all tests
|
|
8
|
+
* node test.mjs --plugin notes # Test one plugin
|
|
9
|
+
* node test.mjs --skip-auth # Skip plugins needing API keys/tokens
|
|
10
|
+
* node test.mjs --write # Also run write tests (sends real data)
|
|
11
|
+
* node test.mjs --verbose # Show full tool output
|
|
12
|
+
*
|
|
13
|
+
* Categories:
|
|
14
|
+
* [FREE] Zero config, always testable
|
|
15
|
+
* [AUTH] Requires API key / OAuth token (skipped if not configured)
|
|
16
|
+
* [WRITE] Makes real changes — email, tweets, calendar events (needs --write)
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { mkdirSync } from 'fs';
|
|
20
|
+
import { homedir } from 'os';
|
|
21
|
+
import { join } from 'path';
|
|
22
|
+
import { parseArgs } from 'util';
|
|
23
|
+
|
|
24
|
+
// ── CLI args ─────────────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
const { values: args } = parseArgs({
|
|
27
|
+
options: {
|
|
28
|
+
plugin: { type: 'string', short: 'p' },
|
|
29
|
+
'skip-auth': { type: 'boolean', default: false },
|
|
30
|
+
write: { type: 'boolean', default: false },
|
|
31
|
+
verbose: { type: 'boolean', short: 'v', default: false },
|
|
32
|
+
help: { type: 'boolean', short: 'h', default: false },
|
|
33
|
+
},
|
|
34
|
+
allowPositionals: true,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
if (args.help) {
|
|
38
|
+
console.log(`
|
|
39
|
+
Conductor Test Suite
|
|
40
|
+
|
|
41
|
+
node test.mjs Run all tests
|
|
42
|
+
node test.mjs --plugin notes Test one plugin
|
|
43
|
+
node test.mjs --skip-auth Skip tests needing API tokens
|
|
44
|
+
node test.mjs --write Run write tests (send email, post tweet, etc.)
|
|
45
|
+
node test.mjs --verbose Print full tool output
|
|
46
|
+
`);
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ── Colours ───────────────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
const c = {
|
|
53
|
+
reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
|
|
54
|
+
green: '\x1b[32m', red: '\x1b[31m', yellow: '\x1b[33m',
|
|
55
|
+
cyan: '\x1b[36m', blue: '\x1b[34m', gray: '\x1b[90m',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// ── Result tracking ───────────────────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
const results = { passed: 0, failed: 0, skipped: 0, errors: [] };
|
|
61
|
+
let currentPlugin = '';
|
|
62
|
+
|
|
63
|
+
function pluginHeader(name, category) {
|
|
64
|
+
const badge =
|
|
65
|
+
category === 'FREE' ? `${c.green}[FREE]${c.reset}` :
|
|
66
|
+
category === 'AUTH' ? `${c.yellow}[AUTH]${c.reset}` :
|
|
67
|
+
category === 'WRITE' ? `${c.red}[WRITE]${c.reset}` : '';
|
|
68
|
+
console.log(`\n${c.bold}${c.cyan}▶ ${name}${c.reset} ${badge}`);
|
|
69
|
+
currentPlugin = name;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function pass(name, detail) {
|
|
73
|
+
results.passed++;
|
|
74
|
+
const det = detail && args.verbose
|
|
75
|
+
? ` ${c.gray}${JSON.stringify(detail).slice(0, 120)}${c.reset}` : '';
|
|
76
|
+
console.log(` ${c.green}✓${c.reset} ${name}${det}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function fail(name, err) {
|
|
80
|
+
results.failed++;
|
|
81
|
+
const msg = err?.message ?? String(err);
|
|
82
|
+
results.errors.push({ plugin: currentPlugin, tool: name, error: msg });
|
|
83
|
+
console.log(` ${c.red}✗${c.reset} ${name} ${c.red}${msg}${c.reset}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function skip(name, reason) {
|
|
87
|
+
results.skipped++;
|
|
88
|
+
console.log(` ${c.dim}○ ${name} — ${reason}${c.reset}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function run(name, fn, { write = false, auth = false } = {}) {
|
|
92
|
+
if (write && !args.write) return skip(name, 'use --write to enable');
|
|
93
|
+
if (auth && args['skip-auth']) return skip(name, '--skip-auth');
|
|
94
|
+
try {
|
|
95
|
+
const result = await fn();
|
|
96
|
+
if (result?.error) fail(name, { message: result.error });
|
|
97
|
+
else pass(name, result);
|
|
98
|
+
} catch (err) {
|
|
99
|
+
const msg = err?.message ?? String(err);
|
|
100
|
+
const isUnconfigured =
|
|
101
|
+
/not configured|not authenticated|token|api key|bearer|keychain/i.test(msg);
|
|
102
|
+
if (isUnconfigured) skip(name, 'not configured');
|
|
103
|
+
else fail(name, err);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ── Fake conductor for plugin.initialize() ────────────────────────────────────
|
|
108
|
+
|
|
109
|
+
const CONDUCTOR_DIR = join(homedir(), '.conductor');
|
|
110
|
+
mkdirSync(join(CONDUCTOR_DIR, 'keychain'), { recursive: true });
|
|
111
|
+
mkdirSync(join(CONDUCTOR_DIR, 'notes'), { recursive: true });
|
|
112
|
+
|
|
113
|
+
const fakeConductor = {
|
|
114
|
+
getConfig: () => ({
|
|
115
|
+
getConfigDir: () => CONDUCTOR_DIR,
|
|
116
|
+
get: () => null,
|
|
117
|
+
}),
|
|
118
|
+
getDatabase: () => ({
|
|
119
|
+
addCoreMemory: async () => { },
|
|
120
|
+
searchCoreMemory: async () => [],
|
|
121
|
+
deleteCoreMemory: async () => true,
|
|
122
|
+
listCoreMemory: async () => [],
|
|
123
|
+
searchMessages: async () => []
|
|
124
|
+
})
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
async function loadPlugin(file) {
|
|
128
|
+
const mod = await import(`./dist/plugins/builtin/${file}.js`);
|
|
129
|
+
const Cls = Object.values(mod).find(v =>
|
|
130
|
+
typeof v === 'function' && v.prototype && typeof v.prototype.getTools === 'function'
|
|
131
|
+
);
|
|
132
|
+
if (!Cls) throw new Error(`No plugin class in ${file}.js`);
|
|
133
|
+
const plugin = new Cls();
|
|
134
|
+
await plugin.initialize(fakeConductor);
|
|
135
|
+
return Object.fromEntries(plugin.getTools().map(t => [t.name, t.handler]));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
139
|
+
// TESTS
|
|
140
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
141
|
+
|
|
142
|
+
// ── Loader integrity ──────────────────────────────────────────────────────────
|
|
143
|
+
|
|
144
|
+
async function testLoader() {
|
|
145
|
+
if (args.plugin) return;
|
|
146
|
+
console.log(`\n${c.bold}${c.blue}▶ Plugin Loader Integrity${c.reset}`);
|
|
147
|
+
|
|
148
|
+
const { getAllBuiltinPlugins } = await import('./dist/plugins/builtin/index.js');
|
|
149
|
+
const plugins = getAllBuiltinPlugins();
|
|
150
|
+
|
|
151
|
+
await run('29 plugins loaded', () => {
|
|
152
|
+
if (plugins.length !== 29) throw new Error(`Expected 29, got ${plugins.length}`);
|
|
153
|
+
return { count: plugins.length };
|
|
154
|
+
});
|
|
155
|
+
await run('all have name', () => {
|
|
156
|
+
const bad = plugins.filter(p => !p.name);
|
|
157
|
+
if (bad.length) throw new Error(`${bad.length} plugins missing name`);
|
|
158
|
+
return { ok: true };
|
|
159
|
+
});
|
|
160
|
+
await run('all have tools', () => {
|
|
161
|
+
const bad = plugins.filter(p => !p.getTools?.().length);
|
|
162
|
+
if (bad.length) throw new Error(`Empty: ${bad.map(p => p.name).join(', ')}`);
|
|
163
|
+
return { ok: true };
|
|
164
|
+
});
|
|
165
|
+
await run('total tools ≥ 146', () => {
|
|
166
|
+
const total = plugins.reduce((n, p) => n + p.getTools().length, 0);
|
|
167
|
+
if (total < 146) throw new Error(`Got ${total}`);
|
|
168
|
+
return { total };
|
|
169
|
+
});
|
|
170
|
+
await run('no duplicate tool names', () => {
|
|
171
|
+
const names = plugins.flatMap(p => p.getTools().map(t => t.name));
|
|
172
|
+
const dupes = names.filter((n, i) => names.indexOf(n) !== i);
|
|
173
|
+
if (dupes.length) throw new Error(`Dupes: ${dupes.join(', ')}`);
|
|
174
|
+
return { ok: true };
|
|
175
|
+
});
|
|
176
|
+
await run('all tools have inputSchema', () => {
|
|
177
|
+
const bad = plugins.flatMap(p =>
|
|
178
|
+
p.getTools().filter(t => !t.inputSchema).map(t => `${p.name}/${t.name}`)
|
|
179
|
+
);
|
|
180
|
+
if (bad.length) throw new Error(bad.join(', '));
|
|
181
|
+
return { ok: true };
|
|
182
|
+
});
|
|
183
|
+
await run('all tools have handlers', () => {
|
|
184
|
+
const bad = plugins.flatMap(p =>
|
|
185
|
+
p.getTools().filter(t => typeof t.handler !== 'function').map(t => `${p.name}/${t.name}`)
|
|
186
|
+
);
|
|
187
|
+
if (bad.length) throw new Error(bad.join(', '));
|
|
188
|
+
return { ok: true };
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ── calculator ────────────────────────────────────────────────────────────────
|
|
193
|
+
|
|
194
|
+
async function testCalculator() {
|
|
195
|
+
if (args.plugin && args.plugin !== 'calculator') return;
|
|
196
|
+
pluginHeader('calculator', 'FREE');
|
|
197
|
+
const t = await loadPlugin('calculator');
|
|
198
|
+
|
|
199
|
+
await run('calc_math basic', () => t.calc_math({ expression: '2 + 2 * 10' }));
|
|
200
|
+
await run('calc_math sqrt', () => t.calc_math({ expression: 'sqrt(144) + 2 ** 3' }));
|
|
201
|
+
await run('calc_convert km→mi', () => t.calc_convert({ value: 100, from: 'km', to: 'mi' }));
|
|
202
|
+
await run('calc_convert C→F', () => t.calc_convert({ value: 100, from: 'C', to: 'F' }));
|
|
203
|
+
await run('calc_convert kg→lb', () => t.calc_convert({ value: 70, from: 'kg', to: 'lb' }));
|
|
204
|
+
await run('calc_date add', () => t.calc_date({ operation: 'add', date: '2024-01-01', amount: 30, unit: 'days' }));
|
|
205
|
+
await run('calc_date diff', () => t.calc_date({ operation: 'diff', date: '2024-01-01', date2: '2024-12-31' }));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ── colors ────────────────────────────────────────────────────────────────────
|
|
209
|
+
|
|
210
|
+
async function testColors() {
|
|
211
|
+
if (args.plugin && args.plugin !== 'colors') return;
|
|
212
|
+
pluginHeader('colors', 'FREE');
|
|
213
|
+
const t = await loadPlugin('colors');
|
|
214
|
+
|
|
215
|
+
await run('color_convert hex→rgb', () => t.color_convert({ color: '#FF6B6B', to: 'rgb' }));
|
|
216
|
+
await run('color_convert hex→hsl', () => t.color_convert({ color: '#3B82F6', to: 'hsl' }));
|
|
217
|
+
// color_contrast expects { foreground, background } not { color1, color2 }
|
|
218
|
+
await run('color_contrast', () => t.color_contrast({ foreground: '#000000', background: '#FFFFFF' }));
|
|
219
|
+
// color_palette expects { base } not { color }
|
|
220
|
+
await run('color_palette analogous', () => t.color_palette({ base: '#3B82F6', type: 'analogous' }));
|
|
221
|
+
await run('color_palette triadic', () => t.color_palette({ base: '#FF6B6B', type: 'triadic' }));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// ── crypto ────────────────────────────────────────────────────────────────────
|
|
225
|
+
|
|
226
|
+
async function testCrypto() {
|
|
227
|
+
if (args.plugin && args.plugin !== 'crypto') return;
|
|
228
|
+
pluginHeader('crypto', 'FREE');
|
|
229
|
+
const t = await loadPlugin('crypto');
|
|
230
|
+
|
|
231
|
+
await run('crypto_price BTC', () => t.crypto_price({ coin: 'bitcoin' }));
|
|
232
|
+
await run('crypto_price ETH', () => t.crypto_price({ coin: 'ethereum' }));
|
|
233
|
+
await run('crypto_trending', () => t.crypto_trending({}));
|
|
234
|
+
await run('crypto_search', () => t.crypto_search({ query: 'solana' }));
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ── fun ───────────────────────────────────────────────────────────────────────
|
|
238
|
+
|
|
239
|
+
async function testFun() {
|
|
240
|
+
if (args.plugin && args.plugin !== 'fun') return;
|
|
241
|
+
pluginHeader('fun', 'FREE');
|
|
242
|
+
const t = await loadPlugin('fun');
|
|
243
|
+
|
|
244
|
+
await run('fun_joke', () => t.fun_joke({}));
|
|
245
|
+
await run('fun_cat_fact', () => t.fun_cat_fact({}));
|
|
246
|
+
await run('fun_trivia', () => t.fun_trivia({}));
|
|
247
|
+
await run('fun_random_number', () => t.fun_random_number({ min: 1, max: 100 }));
|
|
248
|
+
await run('fun_quote', () => t.fun_quote({}));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// ── hash ──────────────────────────────────────────────────────────────────────
|
|
252
|
+
|
|
253
|
+
async function testHash() {
|
|
254
|
+
if (args.plugin && args.plugin !== 'hash') return;
|
|
255
|
+
pluginHeader('hash', 'FREE');
|
|
256
|
+
const t = await loadPlugin('hash');
|
|
257
|
+
|
|
258
|
+
await run('hash_text sha256', () => t.hash_text({ text: 'conductor', algorithm: 'sha256' }));
|
|
259
|
+
await run('hash_text md5', () => t.hash_text({ text: 'conductor', algorithm: 'md5' }));
|
|
260
|
+
await run('base64_encode', () => t.base64_encode({ text: 'Conductor by TheAlxLabs' }));
|
|
261
|
+
// base64_decode expects { text } not { encoded }
|
|
262
|
+
await run('base64_decode', () => t.base64_decode({ text: 'Q29uZHVjdG9yIGJ5IFRoZUFseExhYnM=' }));
|
|
263
|
+
await run('generate_uuid', () => t.generate_uuid({}));
|
|
264
|
+
await run('generate_password', () => t.generate_password({ length: 24, includeSymbols: true }));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ── network ───────────────────────────────────────────────────────────────────
|
|
268
|
+
|
|
269
|
+
async function testNetwork() {
|
|
270
|
+
if (args.plugin && args.plugin !== 'network') return;
|
|
271
|
+
pluginHeader('network', 'FREE');
|
|
272
|
+
const t = await loadPlugin('network');
|
|
273
|
+
|
|
274
|
+
await run('dns_lookup', () => t.dns_lookup({ domain: 'github.com' }));
|
|
275
|
+
await run('ip_info', () => t.ip_info({ ip: '8.8.8.8' }));
|
|
276
|
+
await run('reverse_dns', () => t.reverse_dns({ ip: '8.8.8.8' }));
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// ── system ────────────────────────────────────────────────────────────────────
|
|
280
|
+
|
|
281
|
+
async function testSystem() {
|
|
282
|
+
if (args.plugin && args.plugin !== 'system') return;
|
|
283
|
+
pluginHeader('system', 'FREE');
|
|
284
|
+
const t = await loadPlugin('system');
|
|
285
|
+
|
|
286
|
+
await run('system_info', () => t.system_info({}));
|
|
287
|
+
await run('system_processes', () => t.system_processes({ limit: 5 }));
|
|
288
|
+
await run('system_network', () => t.system_network({}));
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// ── text-tools ────────────────────────────────────────────────────────────────
|
|
292
|
+
|
|
293
|
+
async function testTextTools() {
|
|
294
|
+
if (args.plugin && args.plugin !== 'text-tools') return;
|
|
295
|
+
pluginHeader('text-tools', 'FREE');
|
|
296
|
+
const t = await loadPlugin('text-tools');
|
|
297
|
+
|
|
298
|
+
await run('json_format', () => t.json_format({ json: '{"name":"conductor","plugins":25}' }));
|
|
299
|
+
await run('text_stats', () => t.text_stats({ text: 'Conductor by TheAlxLabs. 29 plugins. 146 tools.' }));
|
|
300
|
+
// regex_test needs the 'g' flag for matchAll
|
|
301
|
+
await run('regex_test', () => t.regex_test({ pattern: '[a-z]+', flags: 'gi', text: 'Conductor' }));
|
|
302
|
+
// text_transform valid values: uppercase, lowercase, title, camel, snake, slug, reverse
|
|
303
|
+
await run('text_transform title', () => t.text_transform({ text: 'hello world from conductor', transform: 'title' }));
|
|
304
|
+
await run('text_transform camel', () => t.text_transform({ text: 'hello world from conductor', transform: 'camel' }));
|
|
305
|
+
await run('text_transform slug', () => t.text_transform({ text: 'Hello World From Conductor', transform: 'slug' }));
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ── timezone ──────────────────────────────────────────────────────────────────
|
|
309
|
+
|
|
310
|
+
async function testTimezone() {
|
|
311
|
+
if (args.plugin && args.plugin !== 'timezone') return;
|
|
312
|
+
pluginHeader('timezone', 'FREE');
|
|
313
|
+
const t = await loadPlugin('timezone');
|
|
314
|
+
|
|
315
|
+
// time_now expects { cities: string[] } not { timezone: string }
|
|
316
|
+
await run('time_now', () => t.time_now({ cities: ['Toronto', 'Tokyo', 'London'] }));
|
|
317
|
+
await run('time_convert', () => t.time_convert({ time: '09:00', from: 'America/Toronto', to: 'Europe/London' }));
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// ── translate ─────────────────────────────────────────────────────────────────
|
|
321
|
+
|
|
322
|
+
async function testTranslate() {
|
|
323
|
+
if (args.plugin && args.plugin !== 'translate') return;
|
|
324
|
+
pluginHeader('translate', 'FREE');
|
|
325
|
+
const t = await loadPlugin('translate');
|
|
326
|
+
|
|
327
|
+
await run('translate en→fr', () => t.translate_text({ text: 'Hello from Conductor', from: 'en', to: 'fr' }));
|
|
328
|
+
await run('translate en→es', () => t.translate_text({ text: 'Good morning', from: 'en', to: 'es' }));
|
|
329
|
+
await run('translate en→ja', () => t.translate_text({ text: 'Hello', from: 'en', to: 'ja' }));
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// ── url-tools ─────────────────────────────────────────────────────────────────
|
|
333
|
+
|
|
334
|
+
async function testUrlTools() {
|
|
335
|
+
if (args.plugin && args.plugin !== 'url-tools') return;
|
|
336
|
+
pluginHeader('url-tools', 'FREE');
|
|
337
|
+
const t = await loadPlugin('url-tools');
|
|
338
|
+
|
|
339
|
+
await run('url_status', () => t.url_status({ url: 'https://github.com' }));
|
|
340
|
+
await run('url_headers', () => t.url_headers({ url: 'https://github.com' }));
|
|
341
|
+
await run('url_expand', () => t.url_expand({ url: 'https://bit.ly/3NvL2Ge' }));
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// ── weather ───────────────────────────────────────────────────────────────────
|
|
345
|
+
|
|
346
|
+
async function testWeather() {
|
|
347
|
+
if (args.plugin && args.plugin !== 'weather') return;
|
|
348
|
+
pluginHeader('weather', 'FREE');
|
|
349
|
+
const t = await loadPlugin('weather');
|
|
350
|
+
|
|
351
|
+
await run('weather_current', () => t.weather_current({ city: 'Toronto' }));
|
|
352
|
+
await run('weather_forecast', () => t.weather_forecast({ city: 'Toronto', days: 3 }));
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// ── github (public) ───────────────────────────────────────────────────────────
|
|
356
|
+
|
|
357
|
+
async function testGitHub() {
|
|
358
|
+
if (args.plugin && args.plugin !== 'github') return;
|
|
359
|
+
pluginHeader('github', 'FREE');
|
|
360
|
+
const t = await loadPlugin('github');
|
|
361
|
+
|
|
362
|
+
await run('github_user', () => t.github_user({ username: 'thealxlabs' }));
|
|
363
|
+
await run('github_repo', () => t.github_repo({ owner: 'thealxlabs', repo: 'conductor' }));
|
|
364
|
+
await run('github_repos', () => t.github_repos({ username: 'thealxlabs' }));
|
|
365
|
+
await run('github_trending', () => t.github_trending({ query: 'typescript ai' }));
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// ── memory ────────────────────────────────────────────────────────────────────
|
|
369
|
+
|
|
370
|
+
async function testMemory() {
|
|
371
|
+
if (args.plugin && args.plugin !== 'memory') return;
|
|
372
|
+
pluginHeader('memory', 'FREE');
|
|
373
|
+
const t = await loadPlugin('memory');
|
|
374
|
+
|
|
375
|
+
let memId;
|
|
376
|
+
// memory_store expects { text } not { content }
|
|
377
|
+
await run('memory_store', async () => {
|
|
378
|
+
const r = await t.memory_store({ text: 'Conductor has 29 plugins and 146 tools', category: 'fact' });
|
|
379
|
+
memId = r.id;
|
|
380
|
+
return r;
|
|
381
|
+
});
|
|
382
|
+
await run('memory_list', () => t.memory_list({}));
|
|
383
|
+
await run('memory_recall', () => t.memory_recall({ query: 'plugins' }));
|
|
384
|
+
await run('memory_forget', async () => {
|
|
385
|
+
if (!memId) return { skipped: 'no memory stored' };
|
|
386
|
+
return t.memory_forget({ memoryId: memId });
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// ── notes ─────────────────────────────────────────────────────────────────────
|
|
391
|
+
|
|
392
|
+
async function testNotes() {
|
|
393
|
+
if (args.plugin && args.plugin !== 'notes') return;
|
|
394
|
+
pluginHeader('notes', 'FREE');
|
|
395
|
+
const t = await loadPlugin('notes');
|
|
396
|
+
|
|
397
|
+
let noteId;
|
|
398
|
+
await run('notes_create blank', async () => {
|
|
399
|
+
const r = await t.notes_create({ title: 'Conductor Test Note', content: '# Test\n\nTesting notes plugin.\n\n#testing #conductor' });
|
|
400
|
+
noteId = r.id;
|
|
401
|
+
return r;
|
|
402
|
+
});
|
|
403
|
+
await run('notes_create template', () => t.notes_create({ title: 'Test Meeting', template: 'meeting' }));
|
|
404
|
+
await run('notes_daily', () => t.notes_daily({}));
|
|
405
|
+
await run('notes_daily append', () => t.notes_daily({ append: 'Test entry added by test suite' }));
|
|
406
|
+
await run('notes_list', () => t.notes_list({}));
|
|
407
|
+
await run('notes_search', () => t.notes_search({ query: 'conductor' }));
|
|
408
|
+
await run('notes_stats', () => t.notes_stats({}));
|
|
409
|
+
await run('notes_read', () => noteId ? t.notes_read({ id: noteId }) : Promise.resolve({ skipped: true }));
|
|
410
|
+
await run('notes_update', () => noteId ? t.notes_update({ id: noteId, append: '\nUpdated by test suite.' }) : Promise.resolve({ skipped: true }));
|
|
411
|
+
await run('notes_delete', () => noteId ? t.notes_delete({ id: noteId }) : Promise.resolve({ skipped: true }));
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// ── cron ──────────────────────────────────────────────────────────────────────
|
|
415
|
+
|
|
416
|
+
async function testCron() {
|
|
417
|
+
if (args.plugin && args.plugin !== 'cron') return;
|
|
418
|
+
pluginHeader('cron', 'FREE');
|
|
419
|
+
const t = await loadPlugin('cron');
|
|
420
|
+
|
|
421
|
+
let taskId;
|
|
422
|
+
await run('cron_schedule once', async () => {
|
|
423
|
+
const r = await t.cron_schedule({ name: 'Test once', when: 'in 30 minutes', action: 'log', message: 'Test' });
|
|
424
|
+
taskId = r.id;
|
|
425
|
+
return r;
|
|
426
|
+
});
|
|
427
|
+
await run('cron_schedule daily', () => t.cron_schedule({ name: 'Daily test', when: 'every day at 9am', action: 'log' }));
|
|
428
|
+
await run('cron_schedule weekly', () => t.cron_schedule({ name: 'Weekly test', when: 'every Monday at 8am', action: 'log' }));
|
|
429
|
+
await run('cron_list', () => t.cron_list({}));
|
|
430
|
+
await run('cron_pause', () => taskId ? t.cron_pause({ id: taskId, paused: true }) : Promise.resolve({ skipped: true }));
|
|
431
|
+
await run('cron_history', () => taskId ? t.cron_history({ id: taskId }) : Promise.resolve({ skipped: true }));
|
|
432
|
+
await run('cron_cancel', () => taskId ? t.cron_cancel({ id: taskId }) : Promise.resolve({ skipped: true }));
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// ── gmail ─────────────────────────────────────────────────────────────────────
|
|
436
|
+
|
|
437
|
+
async function testGmail() {
|
|
438
|
+
if (args.plugin && args.plugin !== 'gmail') return;
|
|
439
|
+
pluginHeader('gmail', 'AUTH');
|
|
440
|
+
const t = await loadPlugin('gmail');
|
|
441
|
+
|
|
442
|
+
await run('gmail_list', () => t.gmail_list({ maxResults: 5 }), { auth: true });
|
|
443
|
+
await run('gmail_search', () => t.gmail_search({ query: 'is:unread', maxResults: 3 }), { auth: true });
|
|
444
|
+
await run('gmail_list inbox', () => t.gmail_list({ labelIds: ['INBOX'], maxResults: 3 }), { auth: true });
|
|
445
|
+
await run('gmail_send', () => Promise.resolve('skipped — use --write'), { write: true, auth: true });
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// ── gcal ──────────────────────────────────────────────────────────────────────
|
|
449
|
+
|
|
450
|
+
async function testGcal() {
|
|
451
|
+
if (args.plugin && args.plugin !== 'gcal') return;
|
|
452
|
+
pluginHeader('gcal', 'AUTH');
|
|
453
|
+
const t = await loadPlugin('gcal');
|
|
454
|
+
|
|
455
|
+
await run('gcal_list_calendars', () => t.gcal_list_calendars({}), { auth: true });
|
|
456
|
+
await run('gcal_list_events', () => t.gcal_list_events({ maxResults: 5 }), { auth: true });
|
|
457
|
+
await run('gcal_create_event', () => t.gcal_create_event({
|
|
458
|
+
summary: 'Conductor Test Event',
|
|
459
|
+
start: new Date(Date.now() + 86400000).toISOString(),
|
|
460
|
+
end: new Date(Date.now() + 90000000).toISOString(),
|
|
461
|
+
}), { write: true, auth: true });
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// ── gdrive ────────────────────────────────────────────────────────────────────
|
|
465
|
+
|
|
466
|
+
async function testGdrive() {
|
|
467
|
+
if (args.plugin && args.plugin !== 'gdrive') return;
|
|
468
|
+
pluginHeader('gdrive', 'AUTH');
|
|
469
|
+
const t = await loadPlugin('gdrive');
|
|
470
|
+
|
|
471
|
+
await run('gdrive_list', () => t.gdrive_list({ maxResults: 5 }), { auth: true });
|
|
472
|
+
await run('gdrive_search', () => t.gdrive_search({ query: 'README', maxResults: 3 }), { auth: true });
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// ── github_actions ────────────────────────────────────────────────────────────
|
|
476
|
+
|
|
477
|
+
async function testGitHubActions() {
|
|
478
|
+
if (args.plugin && args.plugin !== 'github_actions') return;
|
|
479
|
+
pluginHeader('github_actions', 'AUTH');
|
|
480
|
+
const t = await loadPlugin('github-actions');
|
|
481
|
+
|
|
482
|
+
await run('gh_my_repos', () => t.gh_my_repos({ limit: 10 }), { auth: true });
|
|
483
|
+
await run('gh_workflow_runs', () => t.gh_workflow_runs({ owner: 'thealxlabs', repo: 'conductor', limit: 5 }), { auth: true });
|
|
484
|
+
await run('gh_list_prs', () => t.gh_list_prs({ owner: 'thealxlabs', repo: 'conductor' }), { auth: true });
|
|
485
|
+
await run('gh_list_issues', () => t.gh_list_issues({ owner: 'thealxlabs', repo: 'conductor' }), { auth: true });
|
|
486
|
+
await run('gh_notifications', () => t.gh_notifications({ limit: 10 }), { auth: true });
|
|
487
|
+
await run('gh_releases', () => t.gh_releases({ owner: 'thealxlabs', repo: 'conductor' }), { auth: true });
|
|
488
|
+
await run('gh_code_search', () => t.gh_code_search({ query: 'Plugin repo:thealxlabs/conductor' }), { auth: true });
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// ── vercel ────────────────────────────────────────────────────────────────────
|
|
492
|
+
|
|
493
|
+
async function testVercel() {
|
|
494
|
+
if (args.plugin && args.plugin !== 'vercel') return;
|
|
495
|
+
pluginHeader('vercel', 'AUTH');
|
|
496
|
+
const t = await loadPlugin('vercel');
|
|
497
|
+
|
|
498
|
+
await run('vercel_projects', () => t.vercel_projects({ limit: 10 }), { auth: true });
|
|
499
|
+
await run('vercel_deployments', () => t.vercel_deployments({ limit: 5 }), { auth: true });
|
|
500
|
+
await run('vercel_domains', () => t.vercel_domains({}), { auth: true });
|
|
501
|
+
await run('vercel_team_info', () => t.vercel_team_info({}), { auth: true });
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// ── n8n ───────────────────────────────────────────────────────────────────────
|
|
505
|
+
|
|
506
|
+
async function testN8n() {
|
|
507
|
+
if (args.plugin && args.plugin !== 'n8n') return;
|
|
508
|
+
pluginHeader('n8n', 'AUTH');
|
|
509
|
+
const t = await loadPlugin('n8n');
|
|
510
|
+
|
|
511
|
+
await run('n8n_health', () => t.n8n_health({}), { auth: true });
|
|
512
|
+
await run('n8n_workflows', () => t.n8n_workflows({}), { auth: true });
|
|
513
|
+
await run('n8n_tags', () => t.n8n_tags({}), { auth: true });
|
|
514
|
+
await run('n8n_credentials', () => t.n8n_credentials({}), { auth: true });
|
|
515
|
+
await run('n8n_executions', () => t.n8n_executions({ limit: 5 }), { auth: true });
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// ── notion ────────────────────────────────────────────────────────────────────
|
|
519
|
+
|
|
520
|
+
async function testNotion() {
|
|
521
|
+
if (args.plugin && args.plugin !== 'notion') return;
|
|
522
|
+
pluginHeader('notion', 'AUTH');
|
|
523
|
+
const t = await loadPlugin('notion');
|
|
524
|
+
|
|
525
|
+
await run('notion_search', () => t.notion_search({ query: 'test', maxResults: 5 }), { auth: true });
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// ── x ─────────────────────────────────────────────────────────────────────────
|
|
529
|
+
|
|
530
|
+
async function testX() {
|
|
531
|
+
if (args.plugin && args.plugin !== 'x') return;
|
|
532
|
+
pluginHeader('x', 'AUTH');
|
|
533
|
+
const t = await loadPlugin('x');
|
|
534
|
+
|
|
535
|
+
await run('x_search', () => t.x_search({ query: 'TypeScript', maxResults: 5 }), { auth: true });
|
|
536
|
+
await run('x_get_user', () => t.x_get_user({ username: 'thealxlabs' }), { auth: true });
|
|
537
|
+
await run('x_get_timeline', () => t.x_get_timeline({ username: 'thealxlabs', maxResults: 5 }), { auth: true });
|
|
538
|
+
await run('x_post_tweet', () => t.x_post_tweet({ text: 'Test from Conductor 🚀 #conductor' }), { write: true, auth: true });
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// ── spotify ───────────────────────────────────────────────────────────────────
|
|
542
|
+
|
|
543
|
+
async function testSpotify() {
|
|
544
|
+
if (args.plugin && args.plugin !== 'spotify') return;
|
|
545
|
+
pluginHeader('spotify', 'AUTH');
|
|
546
|
+
const t = await loadPlugin('spotify');
|
|
547
|
+
|
|
548
|
+
await run('spotify_now_playing', () => t.spotify_now_playing({}), { auth: true });
|
|
549
|
+
await run('spotify_search track', () => t.spotify_search({ query: 'Radiohead', type: 'track', limit: 3 }), { auth: true });
|
|
550
|
+
await run('spotify_search artist', () => t.spotify_search({ query: 'Radiohead', type: 'artist', limit: 3 }), { auth: true });
|
|
551
|
+
await run('spotify_search playlist', () => t.spotify_search({ query: 'chill', type: 'playlist', limit: 3 }), { auth: true });
|
|
552
|
+
await run('spotify_devices', () => t.spotify_devices({}), { auth: true });
|
|
553
|
+
await run('spotify_playlists', () => t.spotify_playlists({ limit: 5 }), { auth: true });
|
|
554
|
+
await run('spotify_top_tracks', () => t.spotify_top_tracks({ type: 'tracks', timeRange: 'medium_term', limit: 5 }), { auth: true });
|
|
555
|
+
await run('spotify_top_artists', () => t.spotify_top_tracks({ type: 'artists', timeRange: 'short_term', limit: 5 }), { auth: true });
|
|
556
|
+
await run('spotify_recently_played', () => t.spotify_recently_played({ limit: 5 }), { auth: true });
|
|
557
|
+
await run('spotify_recommendations', () => t.spotify_recommendations({ seedGenres: ['indie', 'alternative'], limit: 5 }), { auth: true });
|
|
558
|
+
await run('spotify_play', () => t.spotify_play({ query: 'Creep Radiohead' }), { write: true, auth: true });
|
|
559
|
+
await run('spotify_pause', () => t.spotify_pause({}), { write: true, auth: true });
|
|
560
|
+
await run('spotify_shuffle on', () => t.spotify_shuffle({ state: true }), { write: true, auth: true });
|
|
561
|
+
await run('spotify_volume', () => t.spotify_volume({ volume: 50 }), { write: true, auth: true });
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// ── Main ──────────────────────────────────────────────────────────────────────
|
|
565
|
+
|
|
566
|
+
async function main() {
|
|
567
|
+
console.log(`\n${c.bold}${c.cyan}╔══════════════════════════════════════════╗${c.reset}`);
|
|
568
|
+
console.log(`${c.bold}${c.cyan}║ Conductor Test Suite ║${c.reset}`);
|
|
569
|
+
console.log(`${c.bold}${c.cyan}║ 29 plugins ║${c.reset}`);
|
|
570
|
+
console.log(`${c.bold}${c.cyan}╚══════════════════════════════════════════╝${c.reset}`);
|
|
571
|
+
|
|
572
|
+
if (args['skip-auth']) console.log(`\n${c.yellow} ⚠ --skip-auth: skipping all auth plugins${c.reset}`);
|
|
573
|
+
if (!args.write) console.log(`${c.dim} --write not set: skipping destructive operations${c.reset}`);
|
|
574
|
+
if (args.plugin) console.log(`${c.dim} --plugin: testing ${args.plugin} only${c.reset}`);
|
|
575
|
+
|
|
576
|
+
const start = Date.now();
|
|
577
|
+
|
|
578
|
+
await testLoader();
|
|
579
|
+
|
|
580
|
+
// FREE
|
|
581
|
+
await testCalculator();
|
|
582
|
+
await testColors();
|
|
583
|
+
await testCrypto();
|
|
584
|
+
await testFun();
|
|
585
|
+
await testHash();
|
|
586
|
+
await testNetwork();
|
|
587
|
+
await testSystem();
|
|
588
|
+
await testTextTools();
|
|
589
|
+
await testTimezone();
|
|
590
|
+
await testTranslate();
|
|
591
|
+
await testUrlTools();
|
|
592
|
+
await testWeather();
|
|
593
|
+
await testGitHub();
|
|
594
|
+
await testMemory();
|
|
595
|
+
await testNotes();
|
|
596
|
+
await testCron();
|
|
597
|
+
|
|
598
|
+
// AUTH
|
|
599
|
+
await testGmail();
|
|
600
|
+
await testGcal();
|
|
601
|
+
await testGdrive();
|
|
602
|
+
await testGitHubActions();
|
|
603
|
+
await testVercel();
|
|
604
|
+
await testN8n();
|
|
605
|
+
await testNotion();
|
|
606
|
+
await testX();
|
|
607
|
+
await testSpotify();
|
|
608
|
+
|
|
609
|
+
const elapsed = ((Date.now() - start) / 1000).toFixed(1);
|
|
610
|
+
const total = results.passed + results.failed + results.skipped;
|
|
611
|
+
|
|
612
|
+
console.log(`\n${c.bold}${'─'.repeat(50)}${c.reset}`);
|
|
613
|
+
console.log(`${c.bold}Results${c.reset} ${elapsed}s · ${total} tests`);
|
|
614
|
+
console.log(` ${c.green}✓ ${results.passed} passed${c.reset}`);
|
|
615
|
+
if (results.skipped) console.log(` ${c.dim}○ ${results.skipped} skipped (network / not configured)${c.reset}`);
|
|
616
|
+
if (results.failed) console.log(` ${c.red}✗ ${results.failed} failed${c.reset}`);
|
|
617
|
+
|
|
618
|
+
if (results.errors.length > 0) {
|
|
619
|
+
console.log(`\n${c.bold}${c.red}Failures:${c.reset}`);
|
|
620
|
+
for (const e of results.errors) {
|
|
621
|
+
console.log(` ${c.red}✗${c.reset} ${c.bold}${e.plugin}/${e.tool}${c.reset}`);
|
|
622
|
+
console.log(` ${c.dim}${e.error}${c.reset}`);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
console.log('');
|
|
627
|
+
process.exit(results.failed > 0 ? 1 : 0);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
main().catch(err => {
|
|
631
|
+
console.error(`\n${c.red}Fatal:${c.reset}`, err);
|
|
632
|
+
process.exit(1);
|
|
633
|
+
});
|
package/tests/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# tests
|
|
2
|
+
|
|
3
|
+
Test suite for Conductor. Uses Vitest as the test runner.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- `calculator.test.ts` - Calculator plugin tests
|
|
8
|
+
- `docker.test.ts` - Docker plugin tests
|
|
9
|
+
- `mcp.test.ts` - MCP server tests
|
|
10
|
+
- `shell.test.ts` - Shell plugin tests
|
|
11
|
+
|
|
12
|
+
## Architecture
|
|
13
|
+
|
|
14
|
+
Tests match `**/*.test.ts` and are run via `npx vitest run`. Use `npm run test:watch` for watch mode and `npm run test:coverage` for coverage reports. Add new test files alongside the modules they test, following the existing naming convention.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx vitest run tests/calculator.test.ts # Run a single test file
|
|
18
|
+
npm test # Run all tests
|
|
19
|
+
```
|