@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,537 @@
|
|
|
1
|
+
import { AIProvider, AIMessage, AIToolCall } from './base.js';
|
|
2
|
+
import { ClaudeProvider } from './claude.js';
|
|
3
|
+
import { OpenAIProvider } from './openai.js';
|
|
4
|
+
import { GeminiProvider } from './gemini.js';
|
|
5
|
+
import { OllamaProvider } from './ollama.js';
|
|
6
|
+
import { OpenRouterProvider } from './openrouter.js';
|
|
7
|
+
import { MaestroProvider } from './maestro.js';
|
|
8
|
+
import { Conductor } from '../core/conductor.js';
|
|
9
|
+
import { Keychain } from '../security/keychain.js';
|
|
10
|
+
|
|
11
|
+
export interface AgentResponse {
|
|
12
|
+
text: string;
|
|
13
|
+
approvalRequired?: {
|
|
14
|
+
toolCallId: string;
|
|
15
|
+
toolName: string;
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
arguments: Record<string, any>;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class AIManager {
|
|
22
|
+
private conductor: Conductor;
|
|
23
|
+
private keychain: Keychain;
|
|
24
|
+
private currentProvider: AIProvider | null = null;
|
|
25
|
+
|
|
26
|
+
constructor(conductor: Conductor) {
|
|
27
|
+
this.conductor = conductor;
|
|
28
|
+
this.keychain = new Keychain(conductor.getConfig().getConfigDir());
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Get (or lazily initialize) the current AI provider. */
|
|
32
|
+
async getCurrentProvider(): Promise<AIProvider | null> {
|
|
33
|
+
if (this.currentProvider) return this.currentProvider;
|
|
34
|
+
|
|
35
|
+
const provider = this.conductor.getConfig().get<string>('ai.provider');
|
|
36
|
+
if (!provider) return null;
|
|
37
|
+
|
|
38
|
+
await this.loadProvider(provider);
|
|
39
|
+
return this.currentProvider;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Load and initialize a provider by name. */
|
|
43
|
+
async loadProvider(providerName: string): Promise<AIProvider> {
|
|
44
|
+
switch (providerName.toLowerCase()) {
|
|
45
|
+
case 'claude':
|
|
46
|
+
case 'anthropic': {
|
|
47
|
+
const apiKey =
|
|
48
|
+
(await this.keychain.get('anthropic', 'api_key')) || (await this.keychain.get('claude', 'api_key'));
|
|
49
|
+
if (!apiKey) throw new Error('Claude API key not found');
|
|
50
|
+
|
|
51
|
+
const provider = new ClaudeProvider({
|
|
52
|
+
model: this.conductor.getConfig().get<string>('ai.model'),
|
|
53
|
+
});
|
|
54
|
+
await provider.initialize(apiKey);
|
|
55
|
+
this.currentProvider = provider;
|
|
56
|
+
return provider;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
case 'openai': {
|
|
60
|
+
const apiKey = await this.keychain.get('openai', 'api_key');
|
|
61
|
+
if (!apiKey) throw new Error('OpenAI API key not found');
|
|
62
|
+
|
|
63
|
+
const provider = new OpenAIProvider({
|
|
64
|
+
model: this.conductor.getConfig().get<string>('ai.model'),
|
|
65
|
+
});
|
|
66
|
+
await provider.initialize(apiKey);
|
|
67
|
+
this.currentProvider = provider;
|
|
68
|
+
return provider;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
case 'gemini': {
|
|
72
|
+
const googleTokens = await this.keychain.get('google', 'access_token');
|
|
73
|
+
if (googleTokens) {
|
|
74
|
+
const provider = new GeminiProvider({
|
|
75
|
+
model: this.conductor.getConfig().get<string>('ai.model'),
|
|
76
|
+
});
|
|
77
|
+
await provider.initialize(googleTokens);
|
|
78
|
+
this.currentProvider = provider;
|
|
79
|
+
return provider;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const apiKey = await this.keychain.get('gemini', 'api_key');
|
|
83
|
+
if (apiKey) {
|
|
84
|
+
const provider = new GeminiProvider({
|
|
85
|
+
model: this.conductor.getConfig().get<string>('ai.model'),
|
|
86
|
+
});
|
|
87
|
+
await provider.initialize(apiKey);
|
|
88
|
+
this.currentProvider = provider;
|
|
89
|
+
return provider;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const accessToken = await this.keychain.get('gemini', 'access_token');
|
|
93
|
+
if (accessToken) {
|
|
94
|
+
const provider = new GeminiProvider({
|
|
95
|
+
model: this.conductor.getConfig().get<string>('ai.model'),
|
|
96
|
+
});
|
|
97
|
+
await provider.initialize(accessToken);
|
|
98
|
+
this.currentProvider = provider;
|
|
99
|
+
return provider;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
throw new Error('Gemini not configured. Run: conductor auth google');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
case 'openrouter': {
|
|
106
|
+
const apiKey = await this.keychain.get('openrouter', 'api_key');
|
|
107
|
+
if (!apiKey) throw new Error('OpenRouter API key not found');
|
|
108
|
+
|
|
109
|
+
const provider = new OpenRouterProvider({
|
|
110
|
+
model: this.conductor.getConfig().get<string>('ai.model'),
|
|
111
|
+
});
|
|
112
|
+
await provider.initialize(apiKey);
|
|
113
|
+
this.currentProvider = provider;
|
|
114
|
+
return provider;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
case 'ollama': {
|
|
118
|
+
const endpoint = this.conductor.getConfig().get<string>('ai.local_config.endpoint') || 'http://localhost:11434';
|
|
119
|
+
const model = this.conductor.getConfig().get<string>('ai.model') || 'llama3.2';
|
|
120
|
+
const provider = new OllamaProvider({ endpoint, model });
|
|
121
|
+
await provider.initialize();
|
|
122
|
+
this.currentProvider = provider;
|
|
123
|
+
return provider;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
case 'maestro': {
|
|
127
|
+
const endpoint = this.conductor.getConfig().get<string>('ai.local_config.endpoint') || 'http://localhost:11434';
|
|
128
|
+
const model = this.conductor.getConfig().get<string>('ai.model') || 'maestro';
|
|
129
|
+
const provider = new MaestroProvider({ endpoint, model });
|
|
130
|
+
await provider.initialize();
|
|
131
|
+
this.currentProvider = provider;
|
|
132
|
+
return provider;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
default:
|
|
136
|
+
throw new Error(`Unknown provider: ${providerName}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Setup Claude with API key. */
|
|
141
|
+
async setupClaude(apiKey: string, model?: string): Promise<void> {
|
|
142
|
+
await this.keychain.set('anthropic', 'api_key', apiKey);
|
|
143
|
+
await this.conductor.getConfig().set('ai.provider', 'claude');
|
|
144
|
+
if (model) {
|
|
145
|
+
await this.conductor.getConfig().set('ai.model', model);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const provider = new ClaudeProvider({ model });
|
|
149
|
+
await provider.initialize(apiKey);
|
|
150
|
+
const works = await provider.test();
|
|
151
|
+
if (!works) throw new Error('Claude API key is invalid');
|
|
152
|
+
|
|
153
|
+
this.currentProvider = provider;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Setup OpenAI with API key. */
|
|
157
|
+
async setupOpenAI(apiKey: string, model?: string): Promise<void> {
|
|
158
|
+
await this.keychain.set('openai', 'api_key', apiKey);
|
|
159
|
+
await this.conductor.getConfig().set('ai.provider', 'openai');
|
|
160
|
+
if (model) {
|
|
161
|
+
await this.conductor.getConfig().set('ai.model', model);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const provider = new OpenAIProvider({ model });
|
|
165
|
+
await provider.initialize(apiKey);
|
|
166
|
+
const works = await provider.test();
|
|
167
|
+
if (!works) throw new Error('OpenAI API key is invalid');
|
|
168
|
+
|
|
169
|
+
this.currentProvider = provider;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Setup OpenRouter with API key. */
|
|
173
|
+
async setupOpenRouter(apiKey: string, model?: string): Promise<void> {
|
|
174
|
+
await this.keychain.set('openrouter', 'api_key', apiKey);
|
|
175
|
+
await this.conductor.getConfig().set('ai.provider', 'openrouter');
|
|
176
|
+
if (model) {
|
|
177
|
+
await this.conductor.getConfig().set('ai.model', model);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const provider = new OpenRouterProvider({ model });
|
|
181
|
+
await provider.initialize(apiKey);
|
|
182
|
+
const works = await provider.test();
|
|
183
|
+
if (!works) throw new Error('OpenRouter API key is invalid');
|
|
184
|
+
|
|
185
|
+
this.currentProvider = provider;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** Setup Gemini with OAuth (easiest — uses built-in OAuth app). */
|
|
189
|
+
async setupGeminiOAuthEasy(): Promise<void> {
|
|
190
|
+
const { getOAuthCredentials } = await import('../config/oauth.js');
|
|
191
|
+
const { clientId, clientSecret, redirectUri } = getOAuthCredentials(this.conductor, 'google');
|
|
192
|
+
|
|
193
|
+
const provider = new GeminiProvider({});
|
|
194
|
+
|
|
195
|
+
const authUrl = await provider.initializeWithOAuth(clientId, clientSecret, redirectUri);
|
|
196
|
+
|
|
197
|
+
const open = (await import('open')).default;
|
|
198
|
+
await open(authUrl);
|
|
199
|
+
|
|
200
|
+
await provider.loginWithBrowser();
|
|
201
|
+
|
|
202
|
+
await this.conductor.getConfig().set('ai.provider', 'gemini');
|
|
203
|
+
await this.conductor.getConfig().set('ai.mode', 'oauth');
|
|
204
|
+
|
|
205
|
+
this.currentProvider = provider;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** Setup Gemini with API key. */
|
|
209
|
+
async setupGemini(apiKey: string): Promise<void> {
|
|
210
|
+
await this.keychain.set('gemini', 'api_key', apiKey);
|
|
211
|
+
await this.conductor.getConfig().set('ai.provider', 'gemini');
|
|
212
|
+
|
|
213
|
+
const provider = new GeminiProvider({});
|
|
214
|
+
await provider.initialize(apiKey);
|
|
215
|
+
const works = await provider.test();
|
|
216
|
+
if (!works) throw new Error('Gemini API key is invalid');
|
|
217
|
+
|
|
218
|
+
this.currentProvider = provider;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Setup Ollama (local). */
|
|
222
|
+
async setupOllama(model: string = 'llama3.2', endpoint: string = 'http://localhost:11434'): Promise<void> {
|
|
223
|
+
await this.conductor.getConfig().set('ai.provider', 'ollama');
|
|
224
|
+
await this.conductor.getConfig().set('ai.model', model);
|
|
225
|
+
await this.conductor.getConfig().set('ai.local_config.endpoint', endpoint);
|
|
226
|
+
|
|
227
|
+
const provider = new OllamaProvider({ endpoint, model });
|
|
228
|
+
const works = await provider.test();
|
|
229
|
+
if (!works) {
|
|
230
|
+
throw new Error('Ollama is not running. Start it with: ollama serve');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
this.currentProvider = provider;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Setup Maestro (local, via Ollama). */
|
|
237
|
+
async setupMaestro(model: string = 'maestro', endpoint: string = 'http://localhost:11434'): Promise<void> {
|
|
238
|
+
await this.conductor.getConfig().set('ai.provider', 'maestro');
|
|
239
|
+
await this.conductor.getConfig().set('ai.model', model);
|
|
240
|
+
await this.conductor.getConfig().set('ai.local_config.endpoint', endpoint);
|
|
241
|
+
|
|
242
|
+
const provider = new MaestroProvider({ endpoint, model });
|
|
243
|
+
const works = await provider.test();
|
|
244
|
+
if (!works) {
|
|
245
|
+
throw new Error(
|
|
246
|
+
'Maestro not found. Make sure Ollama is running and pull the model:\n' + 'ollama pull thealxlabs/maestro',
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
this.currentProvider = provider;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** Parse user intent using the current AI provider. */
|
|
254
|
+
async parseIntent(userMessage: string): Promise<any> {
|
|
255
|
+
const provider = await this.getCurrentProvider();
|
|
256
|
+
if (!provider) {
|
|
257
|
+
throw new Error('No AI provider configured. Run: conductor ai');
|
|
258
|
+
}
|
|
259
|
+
return await provider.parseIntent(userMessage);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** Router Agent: Determines the best persona for the request */
|
|
263
|
+
private async determinePersona(userId: string, text: string): Promise<string> {
|
|
264
|
+
const provider = await this.getCurrentProvider();
|
|
265
|
+
if (!provider) return 'general';
|
|
266
|
+
|
|
267
|
+
const prompt = `You are the Conductor Router Agent. Analyze the user's request and categorize it into the most appropriate persona.
|
|
268
|
+
|
|
269
|
+
Options:
|
|
270
|
+
- "coder": The user is asking to write code, debug, use git, bash, or manage files.
|
|
271
|
+
- "social": The user is asking to post tweets, check Slack/Telegram, or manage messages.
|
|
272
|
+
- "researcher": The user wants you to search the web, read pages, or summarize information.
|
|
273
|
+
- "general": Anything else, like checking the weather, calendar, emails, or small talk.
|
|
274
|
+
|
|
275
|
+
User Request: "${text}"
|
|
276
|
+
|
|
277
|
+
Respond with ONLY the exact literal string "coder", "social", "researcher", or "general". No punctuation. Always respond in English.`;
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
const response = await provider.complete(
|
|
281
|
+
[
|
|
282
|
+
{ role: 'system', content: 'You are a strict routing classifier. Always respond in English.' },
|
|
283
|
+
{ role: 'user', content: prompt },
|
|
284
|
+
],
|
|
285
|
+
[],
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
const choice = response.content?.toLowerCase().trim();
|
|
289
|
+
if (['coder', 'social', 'researcher', 'general'].includes(choice!)) {
|
|
290
|
+
return choice!;
|
|
291
|
+
}
|
|
292
|
+
} catch {
|
|
293
|
+
// Silently fallback to general
|
|
294
|
+
}
|
|
295
|
+
return 'general';
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** Helper to process tool calls non-interactively or halt for approval */
|
|
299
|
+
private async processToolCalls(
|
|
300
|
+
userId: string,
|
|
301
|
+
messages: AIMessage[],
|
|
302
|
+
tools: any[],
|
|
303
|
+
): Promise<{ approvalRequired?: any; newMessages: AIMessage[] }> {
|
|
304
|
+
const db = this.conductor.getDatabase();
|
|
305
|
+
|
|
306
|
+
const lastAssistantMessageIndex = [...messages].reverse().findIndex((m) => m.role === 'assistant' && m.tool_calls);
|
|
307
|
+
if (lastAssistantMessageIndex === -1) return { newMessages: [] };
|
|
308
|
+
|
|
309
|
+
const assistantMsg = messages[messages.length - 1 - lastAssistantMessageIndex];
|
|
310
|
+
if (!assistantMsg.tool_calls) return { newMessages: [] };
|
|
311
|
+
|
|
312
|
+
const subsequentMessages = messages.slice(messages.length - lastAssistantMessageIndex);
|
|
313
|
+
const completedToolCallIds = subsequentMessages.filter((m) => m.role === 'tool').map((m) => m.tool_call_id);
|
|
314
|
+
|
|
315
|
+
const pendingToolCalls = assistantMsg.tool_calls.filter((tc: AIToolCall) => !completedToolCallIds.includes(tc.id));
|
|
316
|
+
|
|
317
|
+
const newMessages: AIMessage[] = [];
|
|
318
|
+
|
|
319
|
+
for (const tc of pendingToolCalls) {
|
|
320
|
+
const tool = tools.find((t) => t.name === tc.name);
|
|
321
|
+
if (tool?.requiresApproval) {
|
|
322
|
+
return {
|
|
323
|
+
approvalRequired: { toolCallId: tc.id, toolName: tc.name, arguments: tc.arguments },
|
|
324
|
+
newMessages,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
let resultStr = '';
|
|
329
|
+
if (tool) {
|
|
330
|
+
try {
|
|
331
|
+
process.stderr.write(`\n Executing Tool ➔ ${tc.name}\n`);
|
|
332
|
+
const out = await tool.handler(tc.arguments);
|
|
333
|
+
resultStr = typeof out === 'string' ? out : JSON.stringify(out);
|
|
334
|
+
await db.logActivity(userId, 'tool_execution', tc.name, JSON.stringify(tc.arguments), true);
|
|
335
|
+
} catch (e: any) {
|
|
336
|
+
resultStr = `Error executing ${tc.name}: ${e.message}`;
|
|
337
|
+
await db.logActivity(userId, 'tool_execution', tc.name, e.message, false);
|
|
338
|
+
}
|
|
339
|
+
} else {
|
|
340
|
+
resultStr = `Tool ${tc.name} is not available.`;
|
|
341
|
+
await db.logActivity(userId, 'tool_execution', tc.name, resultStr, false);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const toolMsg: AIMessage = {
|
|
345
|
+
role: 'tool',
|
|
346
|
+
content: resultStr,
|
|
347
|
+
tool_call_id: tc.id,
|
|
348
|
+
name: tc.name,
|
|
349
|
+
};
|
|
350
|
+
await db.addMessage(userId, toolMsg);
|
|
351
|
+
newMessages.push(toolMsg);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return { newMessages };
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/** Execute an interactive conversation loop with the current provider */
|
|
358
|
+
async handleConversation(userId: string, text?: string): Promise<AgentResponse> {
|
|
359
|
+
const provider = await this.getCurrentProvider();
|
|
360
|
+
if (!provider) {
|
|
361
|
+
throw new Error('No AI provider configured. Run: conductor ai setup');
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const db = this.conductor.getDatabase();
|
|
365
|
+
|
|
366
|
+
// Propagate userId to the memory plugin so search_past_conversations is scoped correctly
|
|
367
|
+
try {
|
|
368
|
+
const memPlugin = await this.conductor.getPluginsManager().getPlugin('memory');
|
|
369
|
+
if (memPlugin && typeof (memPlugin as any).setUserId === 'function') {
|
|
370
|
+
(memPlugin as any).setUserId(userId);
|
|
371
|
+
}
|
|
372
|
+
} catch {
|
|
373
|
+
/* memory plugin may not be enabled */
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const tools = await this.conductor.getPluginsManager().getEnabledTools();
|
|
377
|
+
|
|
378
|
+
if (text) {
|
|
379
|
+
const userMsg: AIMessage = { role: 'user', content: text };
|
|
380
|
+
await db.addMessage(userId, userMsg);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
let history = await db.getHistory(userId, 30);
|
|
384
|
+
|
|
385
|
+
let userIntentText = text;
|
|
386
|
+
if (!userIntentText && history.length > 0) {
|
|
387
|
+
const lastUser = [...history].reverse().find((m) => m.role === 'user');
|
|
388
|
+
if (lastUser) userIntentText = lastUser.content;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
let persona = 'general';
|
|
392
|
+
if (userIntentText) {
|
|
393
|
+
persona = await this.determinePersona(userId, userIntentText);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
let systemContent =
|
|
397
|
+
"You are Conductor, an autonomous integration hub agent. You are helpful, concise, and capable of executing tools on behalf of the user. Only use tools when necessary. Always respond in English, regardless of the language of the user's message or your training data.";
|
|
398
|
+
|
|
399
|
+
if (persona === 'coder') {
|
|
400
|
+
systemContent =
|
|
401
|
+
"You are Conductor [Persona: The Coder]. You are an expert software engineer. You write excellent, clean, well-documented code. You prefer using shell and file tools to accomplish programming tasks. Always respond in English, regardless of the language of the user's message or your training data.";
|
|
402
|
+
} else if (persona === 'social') {
|
|
403
|
+
systemContent =
|
|
404
|
+
"You are Conductor [Persona: The Social Manager]. You manage communications, social media, X/Twitter, Slack, and Telegram. You write engaging, professional, and concise updates. Always respond in English, regardless of the language of the user's message or your training data.";
|
|
405
|
+
} else if (persona === 'researcher') {
|
|
406
|
+
systemContent =
|
|
407
|
+
"You are Conductor [Persona: The Researcher]. You are a meticulous investigator. You use web search and browser tools to thoroughly research and summarize factual information. Always respond in English, regardless of the language of the user's message or your training data.";
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const systemPrompt: AIMessage = {
|
|
411
|
+
role: 'system',
|
|
412
|
+
content: systemContent,
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
let messages = [systemPrompt, ...history];
|
|
416
|
+
let loopCount = 0;
|
|
417
|
+
const maxLoops = 15;
|
|
418
|
+
|
|
419
|
+
const pendingProcess = await this.processToolCalls(userId, messages, tools);
|
|
420
|
+
if (pendingProcess.newMessages.length > 0) messages.push(...pendingProcess.newMessages);
|
|
421
|
+
if (pendingProcess.approvalRequired) {
|
|
422
|
+
return { text: 'Action still requires approval.', approvalRequired: pendingProcess.approvalRequired };
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const lastMsg = messages[messages.length - 1];
|
|
426
|
+
if (lastMsg.role === 'assistant' && !lastMsg.tool_calls) {
|
|
427
|
+
return { text: lastMsg.content };
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
while (loopCount < maxLoops) {
|
|
431
|
+
loopCount++;
|
|
432
|
+
|
|
433
|
+
const response = await provider.complete(messages, tools);
|
|
434
|
+
const assistantMsg: AIMessage = {
|
|
435
|
+
role: 'assistant',
|
|
436
|
+
content: response.content || '',
|
|
437
|
+
...(response.tool_calls ? { tool_calls: response.tool_calls } : {}),
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
await db.addMessage(userId, assistantMsg);
|
|
441
|
+
messages.push(assistantMsg);
|
|
442
|
+
|
|
443
|
+
if (!response.tool_calls || response.tool_calls.length === 0) {
|
|
444
|
+
return { text: response.content || 'I completed the task but have nothing to say.' };
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const processObj = await this.processToolCalls(userId, messages, tools);
|
|
448
|
+
if (processObj.newMessages.length > 0) messages.push(...processObj.newMessages);
|
|
449
|
+
if (processObj.approvalRequired) {
|
|
450
|
+
return {
|
|
451
|
+
text: response.content || `I need your permission to use ${processObj.approvalRequired.toolName}.`,
|
|
452
|
+
approvalRequired: processObj.approvalRequired,
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return { text: 'Agent loop cap reached. Task aborted to prevent runaway execution.' };
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/** Execute a tool that was manually approved by the user */
|
|
461
|
+
async executeApprovedTool(userId: string, toolCallId: string): Promise<AgentResponse> {
|
|
462
|
+
const db = this.conductor.getDatabase();
|
|
463
|
+
const tools = await this.conductor.getPluginsManager().getEnabledTools();
|
|
464
|
+
const history = await db.getHistory(userId, 30);
|
|
465
|
+
|
|
466
|
+
let foundTc: AIToolCall | null = null;
|
|
467
|
+
for (const msg of history) {
|
|
468
|
+
if (msg.role === 'assistant' && msg.tool_calls) {
|
|
469
|
+
const tc = msg.tool_calls.find((t: AIToolCall) => t.id === toolCallId);
|
|
470
|
+
if (tc) {
|
|
471
|
+
foundTc = tc;
|
|
472
|
+
break;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (!foundTc) {
|
|
477
|
+
return { text: 'Tool call not found or already executed.' };
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const tool = tools.find((t) => t.name === foundTc!.name);
|
|
481
|
+
let resultStr = '';
|
|
482
|
+
if (tool) {
|
|
483
|
+
try {
|
|
484
|
+
process.stderr.write(`\n Executing Approved Tool ➔ ${foundTc.name}\n`);
|
|
485
|
+
const out = await tool.handler(foundTc.arguments);
|
|
486
|
+
resultStr = typeof out === 'string' ? out : JSON.stringify(out);
|
|
487
|
+
await db.logActivity(userId, 'tool_execution', foundTc.name, JSON.stringify(foundTc.arguments), true);
|
|
488
|
+
} catch (e: any) {
|
|
489
|
+
resultStr = `Error: ${e.message}`;
|
|
490
|
+
await db.logActivity(userId, 'tool_execution', foundTc.name, e.message, false);
|
|
491
|
+
}
|
|
492
|
+
} else {
|
|
493
|
+
resultStr = `Tool ${foundTc.name} unavailable.`;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const toolMsg: AIMessage = {
|
|
497
|
+
role: 'tool',
|
|
498
|
+
content: resultStr,
|
|
499
|
+
tool_call_id: toolCallId,
|
|
500
|
+
name: foundTc.name,
|
|
501
|
+
};
|
|
502
|
+
await db.addMessage(userId, toolMsg);
|
|
503
|
+
|
|
504
|
+
return this.handleConversation(userId);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/** Record a denial for a tool and resume generation */
|
|
508
|
+
async denyTool(userId: string, toolCallId: string): Promise<AgentResponse> {
|
|
509
|
+
const db = this.conductor.getDatabase();
|
|
510
|
+
const history = await db.getHistory(userId, 30);
|
|
511
|
+
|
|
512
|
+
let foundTc: AIToolCall | null = null;
|
|
513
|
+
for (const msg of history) {
|
|
514
|
+
if (msg.role === 'assistant' && msg.tool_calls) {
|
|
515
|
+
const tc = msg.tool_calls.find((t: AIToolCall) => t.id === toolCallId);
|
|
516
|
+
if (tc) {
|
|
517
|
+
foundTc = tc;
|
|
518
|
+
break;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
if (!foundTc) {
|
|
524
|
+
return { text: 'Tool call not found.' };
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
const toolMsg: AIMessage = {
|
|
528
|
+
role: 'tool',
|
|
529
|
+
content: 'User denied the execution of this action.',
|
|
530
|
+
tool_call_id: toolCallId,
|
|
531
|
+
name: foundTc.name,
|
|
532
|
+
};
|
|
533
|
+
await db.addMessage(userId, toolMsg);
|
|
534
|
+
|
|
535
|
+
return this.handleConversation(userId);
|
|
536
|
+
}
|
|
537
|
+
}
|