aidevops 2.52.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/AGENTS.md +614 -0
- package/.agent/accounts.md +65 -0
- package/.agent/aidevops/add-new-mcp-to-aidevops.md +456 -0
- package/.agent/aidevops/api-integrations.md +335 -0
- package/.agent/aidevops/architecture.md +510 -0
- package/.agent/aidevops/configs.md +274 -0
- package/.agent/aidevops/docs.md +244 -0
- package/.agent/aidevops/extension.md +311 -0
- package/.agent/aidevops/mcp-integrations.md +340 -0
- package/.agent/aidevops/mcp-troubleshooting.md +162 -0
- package/.agent/aidevops/memory-patterns.md +172 -0
- package/.agent/aidevops/providers.md +217 -0
- package/.agent/aidevops/recommendations.md +321 -0
- package/.agent/aidevops/requirements.md +301 -0
- package/.agent/aidevops/resources.md +214 -0
- package/.agent/aidevops/security-requirements.md +174 -0
- package/.agent/aidevops/security.md +350 -0
- package/.agent/aidevops/service-links.md +400 -0
- package/.agent/aidevops/services.md +357 -0
- package/.agent/aidevops/setup.md +153 -0
- package/.agent/aidevops/troubleshooting.md +389 -0
- package/.agent/aidevops.md +124 -0
- package/.agent/build-plus.md +244 -0
- package/.agent/content/guidelines.md +109 -0
- package/.agent/content.md +87 -0
- package/.agent/health.md +59 -0
- package/.agent/legal.md +59 -0
- package/.agent/loop-state/full-loop.local.md +16 -0
- package/.agent/loop-state/ralph-loop.local.md +10 -0
- package/.agent/marketing.md +440 -0
- package/.agent/memory/README.md +260 -0
- package/.agent/onboarding.md +796 -0
- package/.agent/plan-plus.md +245 -0
- package/.agent/research.md +100 -0
- package/.agent/sales.md +333 -0
- package/.agent/scripts/101domains-helper.sh +701 -0
- package/.agent/scripts/add-missing-returns.sh +140 -0
- package/.agent/scripts/agent-browser-helper.sh +311 -0
- package/.agent/scripts/agno-setup.sh +712 -0
- package/.agent/scripts/ahrefs-mcp-wrapper.js +168 -0
- package/.agent/scripts/aidevops-update-check.sh +71 -0
- package/.agent/scripts/ampcode-cli.sh +522 -0
- package/.agent/scripts/auto-version-bump.sh +156 -0
- package/.agent/scripts/autogen-helper.sh +512 -0
- package/.agent/scripts/beads-sync-helper.sh +596 -0
- package/.agent/scripts/closte-helper.sh +5 -0
- package/.agent/scripts/cloudron-helper.sh +321 -0
- package/.agent/scripts/codacy-cli-chunked.sh +581 -0
- package/.agent/scripts/codacy-cli.sh +442 -0
- package/.agent/scripts/code-audit-helper.sh +5 -0
- package/.agent/scripts/coderabbit-cli.sh +417 -0
- package/.agent/scripts/coderabbit-pro-analysis.sh +238 -0
- package/.agent/scripts/commands/code-simplifier.md +86 -0
- package/.agent/scripts/commands/full-loop.md +246 -0
- package/.agent/scripts/commands/postflight-loop.md +103 -0
- package/.agent/scripts/commands/recall.md +182 -0
- package/.agent/scripts/commands/remember.md +132 -0
- package/.agent/scripts/commands/save-todo.md +175 -0
- package/.agent/scripts/commands/session-review.md +154 -0
- package/.agent/scripts/comprehensive-quality-fix.sh +106 -0
- package/.agent/scripts/context-builder-helper.sh +522 -0
- package/.agent/scripts/coolify-cli-helper.sh +674 -0
- package/.agent/scripts/coolify-helper.sh +380 -0
- package/.agent/scripts/crawl4ai-examples.sh +401 -0
- package/.agent/scripts/crawl4ai-helper.sh +1078 -0
- package/.agent/scripts/crewai-helper.sh +681 -0
- package/.agent/scripts/dev-browser-helper.sh +513 -0
- package/.agent/scripts/dns-helper.sh +396 -0
- package/.agent/scripts/domain-research-helper.sh +917 -0
- package/.agent/scripts/dspy-helper.sh +285 -0
- package/.agent/scripts/dspyground-helper.sh +291 -0
- package/.agent/scripts/eeat-score-helper.sh +1242 -0
- package/.agent/scripts/efficient-return-fix.sh +92 -0
- package/.agent/scripts/extract-opencode-prompts.sh +128 -0
- package/.agent/scripts/find-missing-returns.sh +113 -0
- package/.agent/scripts/fix-auth-headers.sh +104 -0
- package/.agent/scripts/fix-common-strings.sh +254 -0
- package/.agent/scripts/fix-content-type.sh +100 -0
- package/.agent/scripts/fix-error-messages.sh +130 -0
- package/.agent/scripts/fix-misplaced-returns.sh +74 -0
- package/.agent/scripts/fix-remaining-literals.sh +152 -0
- package/.agent/scripts/fix-return-statements.sh +41 -0
- package/.agent/scripts/fix-s131-default-cases.sh +249 -0
- package/.agent/scripts/fix-sc2155-simple.sh +102 -0
- package/.agent/scripts/fix-shellcheck-critical.sh +187 -0
- package/.agent/scripts/fix-string-literals.sh +273 -0
- package/.agent/scripts/full-loop-helper.sh +773 -0
- package/.agent/scripts/generate-opencode-agents.sh +497 -0
- package/.agent/scripts/generate-opencode-commands.sh +1629 -0
- package/.agent/scripts/generate-skills.sh +366 -0
- package/.agent/scripts/git-platforms-helper.sh +640 -0
- package/.agent/scripts/gitea-cli-helper.sh +743 -0
- package/.agent/scripts/github-cli-helper.sh +702 -0
- package/.agent/scripts/gitlab-cli-helper.sh +682 -0
- package/.agent/scripts/gsc-add-user-helper.sh +325 -0
- package/.agent/scripts/gsc-sitemap-helper.sh +678 -0
- package/.agent/scripts/hetzner-helper.sh +485 -0
- package/.agent/scripts/hostinger-helper.sh +229 -0
- package/.agent/scripts/keyword-research-helper.sh +1815 -0
- package/.agent/scripts/langflow-helper.sh +544 -0
- package/.agent/scripts/linkedin-automation.py +241 -0
- package/.agent/scripts/linter-manager.sh +599 -0
- package/.agent/scripts/linters-local.sh +434 -0
- package/.agent/scripts/list-keys-helper.sh +488 -0
- package/.agent/scripts/local-browser-automation.py +339 -0
- package/.agent/scripts/localhost-helper.sh +744 -0
- package/.agent/scripts/loop-common.sh +806 -0
- package/.agent/scripts/mainwp-helper.sh +728 -0
- package/.agent/scripts/markdown-formatter.sh +338 -0
- package/.agent/scripts/markdown-lint-fix.sh +311 -0
- package/.agent/scripts/mass-fix-returns.sh +58 -0
- package/.agent/scripts/mcp-diagnose.sh +167 -0
- package/.agent/scripts/mcp-inspector-helper.sh +449 -0
- package/.agent/scripts/memory-helper.sh +650 -0
- package/.agent/scripts/monitor-code-review.sh +255 -0
- package/.agent/scripts/onboarding-helper.sh +706 -0
- package/.agent/scripts/opencode-github-setup-helper.sh +797 -0
- package/.agent/scripts/opencode-test-helper.sh +213 -0
- package/.agent/scripts/pagespeed-helper.sh +464 -0
- package/.agent/scripts/pandoc-helper.sh +362 -0
- package/.agent/scripts/postflight-check.sh +555 -0
- package/.agent/scripts/pre-commit-hook.sh +259 -0
- package/.agent/scripts/pre-edit-check.sh +169 -0
- package/.agent/scripts/qlty-cli.sh +356 -0
- package/.agent/scripts/quality-cli-manager.sh +525 -0
- package/.agent/scripts/quality-feedback-helper.sh +462 -0
- package/.agent/scripts/quality-fix.sh +263 -0
- package/.agent/scripts/quality-loop-helper.sh +1108 -0
- package/.agent/scripts/ralph-loop-helper.sh +836 -0
- package/.agent/scripts/ralph-upstream-check.sh +341 -0
- package/.agent/scripts/secretlint-helper.sh +847 -0
- package/.agent/scripts/servers-helper.sh +241 -0
- package/.agent/scripts/ses-helper.sh +619 -0
- package/.agent/scripts/session-review-helper.sh +404 -0
- package/.agent/scripts/setup-linters-wizard.sh +379 -0
- package/.agent/scripts/setup-local-api-keys.sh +330 -0
- package/.agent/scripts/setup-mcp-integrations.sh +472 -0
- package/.agent/scripts/shared-constants.sh +246 -0
- package/.agent/scripts/site-crawler-helper.sh +1487 -0
- package/.agent/scripts/snyk-helper.sh +940 -0
- package/.agent/scripts/sonarcloud-autofix.sh +193 -0
- package/.agent/scripts/sonarcloud-cli.sh +191 -0
- package/.agent/scripts/sonarscanner-cli.sh +455 -0
- package/.agent/scripts/spaceship-helper.sh +747 -0
- package/.agent/scripts/stagehand-helper.sh +321 -0
- package/.agent/scripts/stagehand-python-helper.sh +321 -0
- package/.agent/scripts/stagehand-python-setup.sh +441 -0
- package/.agent/scripts/stagehand-setup.sh +439 -0
- package/.agent/scripts/system-cleanup.sh +340 -0
- package/.agent/scripts/terminal-title-helper.sh +388 -0
- package/.agent/scripts/terminal-title-setup.sh +549 -0
- package/.agent/scripts/test-stagehand-both-integration.sh +317 -0
- package/.agent/scripts/test-stagehand-integration.sh +309 -0
- package/.agent/scripts/test-stagehand-python-integration.sh +341 -0
- package/.agent/scripts/todo-ready.sh +263 -0
- package/.agent/scripts/tool-version-check.sh +362 -0
- package/.agent/scripts/toon-helper.sh +469 -0
- package/.agent/scripts/twilio-helper.sh +917 -0
- package/.agent/scripts/updown-helper.sh +279 -0
- package/.agent/scripts/validate-mcp-integrations.sh +250 -0
- package/.agent/scripts/validate-version-consistency.sh +131 -0
- package/.agent/scripts/vaultwarden-helper.sh +597 -0
- package/.agent/scripts/vercel-cli-helper.sh +816 -0
- package/.agent/scripts/verify-mirrors.sh +169 -0
- package/.agent/scripts/version-manager.sh +831 -0
- package/.agent/scripts/webhosting-helper.sh +471 -0
- package/.agent/scripts/webhosting-verify.sh +238 -0
- package/.agent/scripts/wordpress-mcp-helper.sh +508 -0
- package/.agent/scripts/worktree-helper.sh +595 -0
- package/.agent/scripts/worktree-sessions.sh +577 -0
- package/.agent/seo/dataforseo.md +215 -0
- package/.agent/seo/domain-research.md +532 -0
- package/.agent/seo/eeat-score.md +659 -0
- package/.agent/seo/google-search-console.md +366 -0
- package/.agent/seo/gsc-sitemaps.md +282 -0
- package/.agent/seo/keyword-research.md +521 -0
- package/.agent/seo/serper.md +278 -0
- package/.agent/seo/site-crawler.md +387 -0
- package/.agent/seo.md +236 -0
- package/.agent/services/accounting/quickfile.md +159 -0
- package/.agent/services/communications/telfon.md +470 -0
- package/.agent/services/communications/twilio.md +569 -0
- package/.agent/services/crm/fluentcrm.md +449 -0
- package/.agent/services/email/ses.md +399 -0
- package/.agent/services/hosting/101domains.md +378 -0
- package/.agent/services/hosting/closte.md +177 -0
- package/.agent/services/hosting/cloudflare.md +251 -0
- package/.agent/services/hosting/cloudron.md +478 -0
- package/.agent/services/hosting/dns-providers.md +335 -0
- package/.agent/services/hosting/domain-purchasing.md +344 -0
- package/.agent/services/hosting/hetzner.md +327 -0
- package/.agent/services/hosting/hostinger.md +287 -0
- package/.agent/services/hosting/localhost.md +419 -0
- package/.agent/services/hosting/spaceship.md +353 -0
- package/.agent/services/hosting/webhosting.md +330 -0
- package/.agent/social-media.md +69 -0
- package/.agent/templates/plans-template.md +114 -0
- package/.agent/templates/prd-template.md +129 -0
- package/.agent/templates/tasks-template.md +108 -0
- package/.agent/templates/todo-template.md +89 -0
- package/.agent/tools/ai-assistants/agno.md +471 -0
- package/.agent/tools/ai-assistants/capsolver.md +326 -0
- package/.agent/tools/ai-assistants/configuration.md +221 -0
- package/.agent/tools/ai-assistants/overview.md +209 -0
- package/.agent/tools/ai-assistants/status.md +171 -0
- package/.agent/tools/ai-assistants/windsurf.md +193 -0
- package/.agent/tools/ai-orchestration/autogen.md +406 -0
- package/.agent/tools/ai-orchestration/crewai.md +445 -0
- package/.agent/tools/ai-orchestration/langflow.md +405 -0
- package/.agent/tools/ai-orchestration/openprose.md +487 -0
- package/.agent/tools/ai-orchestration/overview.md +362 -0
- package/.agent/tools/ai-orchestration/packaging.md +647 -0
- package/.agent/tools/browser/agent-browser.md +464 -0
- package/.agent/tools/browser/browser-automation.md +400 -0
- package/.agent/tools/browser/chrome-devtools.md +282 -0
- package/.agent/tools/browser/crawl4ai-integration.md +422 -0
- package/.agent/tools/browser/crawl4ai-resources.md +277 -0
- package/.agent/tools/browser/crawl4ai-usage.md +416 -0
- package/.agent/tools/browser/crawl4ai.md +585 -0
- package/.agent/tools/browser/dev-browser.md +341 -0
- package/.agent/tools/browser/pagespeed.md +260 -0
- package/.agent/tools/browser/playwright.md +266 -0
- package/.agent/tools/browser/playwriter.md +310 -0
- package/.agent/tools/browser/stagehand-examples.md +456 -0
- package/.agent/tools/browser/stagehand-python.md +483 -0
- package/.agent/tools/browser/stagehand.md +421 -0
- package/.agent/tools/build-agent/agent-review.md +224 -0
- package/.agent/tools/build-agent/build-agent.md +784 -0
- package/.agent/tools/build-mcp/aidevops-plugin.md +476 -0
- package/.agent/tools/build-mcp/api-wrapper.md +445 -0
- package/.agent/tools/build-mcp/build-mcp.md +240 -0
- package/.agent/tools/build-mcp/deployment.md +401 -0
- package/.agent/tools/build-mcp/server-patterns.md +632 -0
- package/.agent/tools/build-mcp/transports.md +366 -0
- package/.agent/tools/code-review/auditing.md +383 -0
- package/.agent/tools/code-review/automation.md +219 -0
- package/.agent/tools/code-review/best-practices.md +203 -0
- package/.agent/tools/code-review/codacy.md +151 -0
- package/.agent/tools/code-review/code-simplifier.md +174 -0
- package/.agent/tools/code-review/code-standards.md +309 -0
- package/.agent/tools/code-review/coderabbit.md +101 -0
- package/.agent/tools/code-review/management.md +155 -0
- package/.agent/tools/code-review/qlty.md +248 -0
- package/.agent/tools/code-review/secretlint.md +565 -0
- package/.agent/tools/code-review/setup.md +250 -0
- package/.agent/tools/code-review/snyk.md +563 -0
- package/.agent/tools/code-review/tools.md +230 -0
- package/.agent/tools/content/summarize.md +353 -0
- package/.agent/tools/context/augment-context-engine.md +468 -0
- package/.agent/tools/context/context-builder-agent.md +76 -0
- package/.agent/tools/context/context-builder.md +375 -0
- package/.agent/tools/context/context7.md +371 -0
- package/.agent/tools/context/dspy.md +302 -0
- package/.agent/tools/context/dspyground.md +374 -0
- package/.agent/tools/context/llm-tldr.md +219 -0
- package/.agent/tools/context/osgrep.md +488 -0
- package/.agent/tools/context/prompt-optimization.md +338 -0
- package/.agent/tools/context/toon.md +292 -0
- package/.agent/tools/conversion/pandoc.md +304 -0
- package/.agent/tools/credentials/api-key-management.md +154 -0
- package/.agent/tools/credentials/api-key-setup.md +224 -0
- package/.agent/tools/credentials/environment-variables.md +180 -0
- package/.agent/tools/credentials/vaultwarden.md +382 -0
- package/.agent/tools/data-extraction/outscraper.md +974 -0
- package/.agent/tools/deployment/coolify-cli.md +388 -0
- package/.agent/tools/deployment/coolify-setup.md +353 -0
- package/.agent/tools/deployment/coolify.md +345 -0
- package/.agent/tools/deployment/vercel.md +390 -0
- package/.agent/tools/git/authentication.md +132 -0
- package/.agent/tools/git/gitea-cli.md +193 -0
- package/.agent/tools/git/github-actions.md +207 -0
- package/.agent/tools/git/github-cli.md +223 -0
- package/.agent/tools/git/gitlab-cli.md +190 -0
- package/.agent/tools/git/opencode-github-security.md +350 -0
- package/.agent/tools/git/opencode-github.md +328 -0
- package/.agent/tools/git/opencode-gitlab.md +252 -0
- package/.agent/tools/git/security.md +196 -0
- package/.agent/tools/git.md +207 -0
- package/.agent/tools/opencode/oh-my-opencode.md +375 -0
- package/.agent/tools/opencode/opencode-anthropic-auth.md +446 -0
- package/.agent/tools/opencode/opencode.md +651 -0
- package/.agent/tools/social-media/bird.md +437 -0
- package/.agent/tools/task-management/beads.md +336 -0
- package/.agent/tools/terminal/terminal-title.md +251 -0
- package/.agent/tools/ui/shadcn.md +196 -0
- package/.agent/tools/ui/ui-skills.md +115 -0
- package/.agent/tools/wordpress/localwp.md +311 -0
- package/.agent/tools/wordpress/mainwp.md +391 -0
- package/.agent/tools/wordpress/scf.md +527 -0
- package/.agent/tools/wordpress/wp-admin.md +729 -0
- package/.agent/tools/wordpress/wp-dev.md +940 -0
- package/.agent/tools/wordpress/wp-preferred.md +398 -0
- package/.agent/tools/wordpress.md +95 -0
- package/.agent/workflows/branch/bugfix.md +63 -0
- package/.agent/workflows/branch/chore.md +95 -0
- package/.agent/workflows/branch/experiment.md +115 -0
- package/.agent/workflows/branch/feature.md +59 -0
- package/.agent/workflows/branch/hotfix.md +98 -0
- package/.agent/workflows/branch/refactor.md +92 -0
- package/.agent/workflows/branch/release.md +96 -0
- package/.agent/workflows/branch.md +347 -0
- package/.agent/workflows/bug-fixing.md +267 -0
- package/.agent/workflows/changelog.md +129 -0
- package/.agent/workflows/code-audit-remote.md +279 -0
- package/.agent/workflows/conversation-starter.md +69 -0
- package/.agent/workflows/error-feedback.md +578 -0
- package/.agent/workflows/feature-development.md +355 -0
- package/.agent/workflows/git-workflow.md +702 -0
- package/.agent/workflows/multi-repo-workspace.md +268 -0
- package/.agent/workflows/plans.md +709 -0
- package/.agent/workflows/postflight.md +604 -0
- package/.agent/workflows/pr.md +571 -0
- package/.agent/workflows/preflight.md +278 -0
- package/.agent/workflows/ralph-loop.md +773 -0
- package/.agent/workflows/release.md +498 -0
- package/.agent/workflows/session-manager.md +254 -0
- package/.agent/workflows/session-review.md +311 -0
- package/.agent/workflows/sql-migrations.md +631 -0
- package/.agent/workflows/version-bump.md +283 -0
- package/.agent/workflows/wiki-update.md +333 -0
- package/.agent/workflows/worktree.md +477 -0
- package/LICENSE +21 -0
- package/README.md +1446 -0
- package/VERSION +1 -0
- package/aidevops.sh +1746 -0
- package/bin/aidevops +21 -0
- package/package.json +75 -0
- package/scripts/npm-postinstall.js +60 -0
- package/setup.sh +2366 -0
package/setup.sh
ADDED
|
@@ -0,0 +1,2366 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# AI Assistant Server Access Framework Setup Script
|
|
4
|
+
# Helps developers set up the framework for their infrastructure
|
|
5
|
+
#
|
|
6
|
+
# Version: 2.52.1
|
|
7
|
+
#
|
|
8
|
+
# Quick Install (one-liner):
|
|
9
|
+
# bash <(curl -fsSL https://aidevops.dev/install)
|
|
10
|
+
# OR: bash <(curl -fsSL https://raw.githubusercontent.com/marcusquinn/aidevops/main/setup.sh)
|
|
11
|
+
|
|
12
|
+
# Colors for output
|
|
13
|
+
GREEN='\033[0;32m'
|
|
14
|
+
BLUE='\033[0;34m'
|
|
15
|
+
YELLOW='\033[1;33m'
|
|
16
|
+
RED='\033[0;31m'
|
|
17
|
+
NC='\033[0m' # No Color
|
|
18
|
+
|
|
19
|
+
# Global flags
|
|
20
|
+
CLEAN_MODE=false
|
|
21
|
+
INTERACTIVE_MODE=false
|
|
22
|
+
UPDATE_TOOLS_MODE=false
|
|
23
|
+
REPO_URL="https://github.com/marcusquinn/aidevops.git"
|
|
24
|
+
INSTALL_DIR="$HOME/Git/aidevops"
|
|
25
|
+
|
|
26
|
+
print_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
27
|
+
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
|
28
|
+
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
|
29
|
+
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
30
|
+
|
|
31
|
+
# Confirm step in interactive mode
|
|
32
|
+
# Usage: confirm_step "Step description" && function_to_run
|
|
33
|
+
# Returns: 0 if confirmed or not interactive, 1 if skipped
|
|
34
|
+
confirm_step() {
|
|
35
|
+
local step_name="$1"
|
|
36
|
+
|
|
37
|
+
# Skip confirmation in non-interactive mode
|
|
38
|
+
if [[ "$INTERACTIVE_MODE" != "true" ]]; then
|
|
39
|
+
return 0
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
echo ""
|
|
43
|
+
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
44
|
+
echo -e "${BLUE}Step:${NC} $step_name"
|
|
45
|
+
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
46
|
+
|
|
47
|
+
while true; do
|
|
48
|
+
echo -n -e "${GREEN}Run this step? [Y]es / [n]o / [q]uit: ${NC}"
|
|
49
|
+
read -r response
|
|
50
|
+
# Convert to lowercase (bash 3.2 compatible)
|
|
51
|
+
response=$(echo "$response" | tr '[:upper:]' '[:lower:]')
|
|
52
|
+
case "$response" in
|
|
53
|
+
y|yes|"")
|
|
54
|
+
return 0
|
|
55
|
+
;;
|
|
56
|
+
n|no|s|skip)
|
|
57
|
+
print_warning "Skipped: $step_name"
|
|
58
|
+
return 1
|
|
59
|
+
;;
|
|
60
|
+
q|quit|exit)
|
|
61
|
+
echo ""
|
|
62
|
+
print_info "Setup cancelled by user"
|
|
63
|
+
exit 0
|
|
64
|
+
;;
|
|
65
|
+
*)
|
|
66
|
+
echo "Please answer: y (yes), n (no), or q (quit)"
|
|
67
|
+
;;
|
|
68
|
+
esac
|
|
69
|
+
done
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# Backup rotation settings
|
|
73
|
+
BACKUP_KEEP_COUNT=10
|
|
74
|
+
|
|
75
|
+
# Create a backup with rotation (keeps last N backups)
|
|
76
|
+
# Usage: create_backup_with_rotation <source_path> <backup_name>
|
|
77
|
+
# Example: create_backup_with_rotation "$target_dir" "agents"
|
|
78
|
+
# Creates: ~/.aidevops/agents-backups/20251221_123456/
|
|
79
|
+
create_backup_with_rotation() {
|
|
80
|
+
local source_path="$1"
|
|
81
|
+
local backup_name="$2"
|
|
82
|
+
local backup_base="$HOME/.aidevops/${backup_name}-backups"
|
|
83
|
+
local backup_dir
|
|
84
|
+
backup_dir="$backup_base/$(date +%Y%m%d_%H%M%S)"
|
|
85
|
+
|
|
86
|
+
# Create backup directory
|
|
87
|
+
mkdir -p "$backup_dir"
|
|
88
|
+
|
|
89
|
+
# Copy source to backup
|
|
90
|
+
if [[ -d "$source_path" ]]; then
|
|
91
|
+
cp -R "$source_path" "$backup_dir/"
|
|
92
|
+
elif [[ -f "$source_path" ]]; then
|
|
93
|
+
cp "$source_path" "$backup_dir/"
|
|
94
|
+
else
|
|
95
|
+
print_warning "Source path does not exist: $source_path"
|
|
96
|
+
return 1
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
print_info "Backed up to $backup_dir"
|
|
100
|
+
|
|
101
|
+
# Rotate old backups (keep last N)
|
|
102
|
+
local backup_count
|
|
103
|
+
backup_count=$(find "$backup_base" -maxdepth 1 -type d -name "20*" 2>/dev/null | wc -l | tr -d ' ')
|
|
104
|
+
|
|
105
|
+
if [[ $backup_count -gt $BACKUP_KEEP_COUNT ]]; then
|
|
106
|
+
local to_delete=$((backup_count - BACKUP_KEEP_COUNT))
|
|
107
|
+
print_info "Rotating backups: removing $to_delete old backup(s), keeping last $BACKUP_KEEP_COUNT"
|
|
108
|
+
|
|
109
|
+
# Delete oldest backups (sorted by name = sorted by date)
|
|
110
|
+
find "$backup_base" -maxdepth 1 -type d -name "20*" 2>/dev/null | sort | head -n "$to_delete" | while read -r old_backup; do
|
|
111
|
+
rm -rf "$old_backup"
|
|
112
|
+
done
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
return 0
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# Remove deprecated agent paths that have been moved
|
|
119
|
+
# This ensures clean upgrades when agents are reorganized
|
|
120
|
+
cleanup_deprecated_paths() {
|
|
121
|
+
local agents_dir="$HOME/.aidevops/agents"
|
|
122
|
+
local cleaned=0
|
|
123
|
+
|
|
124
|
+
# List of deprecated paths (add new ones here when reorganizing)
|
|
125
|
+
local deprecated_paths=(
|
|
126
|
+
# v2.40.7: wordpress moved from root to tools/wordpress
|
|
127
|
+
"$agents_dir/wordpress.md"
|
|
128
|
+
"$agents_dir/wordpress"
|
|
129
|
+
# v2.41.0: build-agent and build-mcp moved from root to tools/
|
|
130
|
+
"$agents_dir/build-agent.md"
|
|
131
|
+
"$agents_dir/build-agent"
|
|
132
|
+
"$agents_dir/build-mcp.md"
|
|
133
|
+
"$agents_dir/build-mcp"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
for path in "${deprecated_paths[@]}"; do
|
|
137
|
+
if [[ -e "$path" ]]; then
|
|
138
|
+
rm -rf "$path"
|
|
139
|
+
((cleaned++))
|
|
140
|
+
fi
|
|
141
|
+
done
|
|
142
|
+
|
|
143
|
+
if [[ $cleaned -gt 0 ]]; then
|
|
144
|
+
print_info "Cleaned up $cleaned deprecated agent path(s)"
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
return 0
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
# Migrate old config-backups to new per-type backup structure
|
|
151
|
+
# This runs once to clean up the legacy backup directory
|
|
152
|
+
migrate_old_backups() {
|
|
153
|
+
local old_backup_dir="$HOME/.aidevops/config-backups"
|
|
154
|
+
|
|
155
|
+
# Skip if old directory doesn't exist
|
|
156
|
+
if [[ ! -d "$old_backup_dir" ]]; then
|
|
157
|
+
return 0
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
# Count old backups
|
|
161
|
+
local old_count
|
|
162
|
+
old_count=$(find "$old_backup_dir" -maxdepth 1 -type d -name "20*" 2>/dev/null | wc -l | tr -d ' ')
|
|
163
|
+
|
|
164
|
+
if [[ $old_count -eq 0 ]]; then
|
|
165
|
+
# Empty directory, just remove it
|
|
166
|
+
rm -rf "$old_backup_dir"
|
|
167
|
+
return 0
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
print_info "Migrating $old_count old backups to new structure..."
|
|
171
|
+
|
|
172
|
+
# Create new backup directories
|
|
173
|
+
mkdir -p "$HOME/.aidevops/agents-backups"
|
|
174
|
+
mkdir -p "$HOME/.aidevops/opencode-backups"
|
|
175
|
+
|
|
176
|
+
# Move the most recent backups (up to BACKUP_KEEP_COUNT) to new locations
|
|
177
|
+
# Old backups contained mixed content, so we'll just keep the newest ones as agents backups
|
|
178
|
+
local migrated=0
|
|
179
|
+
for backup in $(find "$old_backup_dir" -maxdepth 1 -type d -name "20*" 2>/dev/null | sort -r | head -n "$BACKUP_KEEP_COUNT"); do
|
|
180
|
+
local backup_name
|
|
181
|
+
backup_name=$(basename "$backup")
|
|
182
|
+
|
|
183
|
+
# Check if it contains agents folder (most common)
|
|
184
|
+
if [[ -d "$backup/agents" ]]; then
|
|
185
|
+
mv "$backup" "$HOME/.aidevops/agents-backups/$backup_name"
|
|
186
|
+
((migrated++))
|
|
187
|
+
# Check if it contains opencode.json
|
|
188
|
+
elif [[ -f "$backup/opencode.json" ]]; then
|
|
189
|
+
mv "$backup" "$HOME/.aidevops/opencode-backups/$backup_name"
|
|
190
|
+
((migrated++))
|
|
191
|
+
fi
|
|
192
|
+
done
|
|
193
|
+
|
|
194
|
+
# Remove remaining old backups and the old directory
|
|
195
|
+
rm -rf "$old_backup_dir"
|
|
196
|
+
|
|
197
|
+
if [[ $migrated -gt 0 ]]; then
|
|
198
|
+
print_success "Migrated $migrated recent backups, removed $((old_count - migrated)) old backups"
|
|
199
|
+
else
|
|
200
|
+
print_info "Cleaned up $old_count old backups"
|
|
201
|
+
fi
|
|
202
|
+
|
|
203
|
+
return 0
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
# Migrate loop state from .claude/ to .agent/loop-state/ in user projects
|
|
207
|
+
# This handles the breaking change from v2.51.0 where loop state directory moved
|
|
208
|
+
# The migration is non-destructive: moves files, doesn't delete originals until confirmed
|
|
209
|
+
migrate_loop_state_directories() {
|
|
210
|
+
print_info "Checking for legacy loop state directories..."
|
|
211
|
+
|
|
212
|
+
local migrated=0
|
|
213
|
+
local git_dirs=()
|
|
214
|
+
|
|
215
|
+
# Find Git repositories in common locations
|
|
216
|
+
# Check ~/Git/ and current directory's parent
|
|
217
|
+
for search_dir in "$HOME/Git" "$(dirname "$(pwd)")"; do
|
|
218
|
+
if [[ -d "$search_dir" ]]; then
|
|
219
|
+
while IFS= read -r -d '' git_dir; do
|
|
220
|
+
git_dirs+=("$(dirname "$git_dir")")
|
|
221
|
+
done < <(find "$search_dir" -maxdepth 3 -type d -name ".git" -print0 2>/dev/null)
|
|
222
|
+
fi
|
|
223
|
+
done
|
|
224
|
+
|
|
225
|
+
for repo_dir in "${git_dirs[@]}"; do
|
|
226
|
+
local old_state_dir="$repo_dir/.claude"
|
|
227
|
+
local new_state_dir="$repo_dir/.agent/loop-state"
|
|
228
|
+
|
|
229
|
+
# Skip if no old state directory
|
|
230
|
+
[[ ! -d "$old_state_dir" ]] && continue
|
|
231
|
+
|
|
232
|
+
# Check for loop state files in old location
|
|
233
|
+
local has_loop_state=false
|
|
234
|
+
if [[ -f "$old_state_dir/ralph-loop.local.md" ]] || \
|
|
235
|
+
[[ -f "$old_state_dir/loop-state.json" ]] || \
|
|
236
|
+
[[ -d "$old_state_dir/receipts" ]]; then
|
|
237
|
+
has_loop_state=true
|
|
238
|
+
fi
|
|
239
|
+
|
|
240
|
+
[[ "$has_loop_state" != "true" ]] && continue
|
|
241
|
+
|
|
242
|
+
print_info "Found legacy loop state in: $repo_dir/.claude/"
|
|
243
|
+
|
|
244
|
+
# Create new directory
|
|
245
|
+
mkdir -p "$new_state_dir"
|
|
246
|
+
|
|
247
|
+
# Move loop-related files
|
|
248
|
+
for file in ralph-loop.local.md loop-state.json re-anchor.md guardrails.md; do
|
|
249
|
+
if [[ -f "$old_state_dir/$file" ]]; then
|
|
250
|
+
mv "$old_state_dir/$file" "$new_state_dir/"
|
|
251
|
+
print_info " Moved $file"
|
|
252
|
+
fi
|
|
253
|
+
done
|
|
254
|
+
|
|
255
|
+
# Move receipts directory
|
|
256
|
+
if [[ -d "$old_state_dir/receipts" ]]; then
|
|
257
|
+
mv "$old_state_dir/receipts" "$new_state_dir/"
|
|
258
|
+
print_info " Moved receipts/"
|
|
259
|
+
fi
|
|
260
|
+
|
|
261
|
+
# Check if .claude/ is now empty (only has hidden files or nothing)
|
|
262
|
+
local remaining
|
|
263
|
+
remaining=$(find "$old_state_dir" -mindepth 1 -maxdepth 1 2>/dev/null | wc -l | tr -d ' ')
|
|
264
|
+
|
|
265
|
+
if [[ "$remaining" -eq 0 ]]; then
|
|
266
|
+
rmdir "$old_state_dir" 2>/dev/null && print_info " Removed empty .claude/"
|
|
267
|
+
else
|
|
268
|
+
print_warning " .claude/ has other files, not removing"
|
|
269
|
+
fi
|
|
270
|
+
|
|
271
|
+
# Update .gitignore if needed
|
|
272
|
+
local gitignore="$repo_dir/.gitignore"
|
|
273
|
+
if [[ -f "$gitignore" ]]; then
|
|
274
|
+
if ! grep -q "^\.agent/loop-state/" "$gitignore" 2>/dev/null; then
|
|
275
|
+
echo ".agent/loop-state/" >> "$gitignore"
|
|
276
|
+
print_info " Added .agent/loop-state/ to .gitignore"
|
|
277
|
+
fi
|
|
278
|
+
fi
|
|
279
|
+
|
|
280
|
+
((migrated++))
|
|
281
|
+
done
|
|
282
|
+
|
|
283
|
+
if [[ $migrated -gt 0 ]]; then
|
|
284
|
+
print_success "Migrated loop state in $migrated repositories"
|
|
285
|
+
else
|
|
286
|
+
print_info "No legacy loop state directories found"
|
|
287
|
+
fi
|
|
288
|
+
|
|
289
|
+
return 0
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
# Bootstrap: Clone or update repo if running remotely (via curl)
|
|
293
|
+
bootstrap_repo() {
|
|
294
|
+
# Detect if running from curl (no script directory context)
|
|
295
|
+
local script_path="${BASH_SOURCE[0]}"
|
|
296
|
+
|
|
297
|
+
# If script_path is empty or stdin, we're running from curl
|
|
298
|
+
if [[ -z "$script_path" || "$script_path" == "/dev/stdin" || "$script_path" == "bash" ]]; then
|
|
299
|
+
print_info "Remote install detected - bootstrapping repository..."
|
|
300
|
+
|
|
301
|
+
# Check for git
|
|
302
|
+
if ! command -v git >/dev/null 2>&1; then
|
|
303
|
+
print_error "git is required but not installed"
|
|
304
|
+
echo "Install git first: brew install git (macOS) or sudo apt install git (Linux)"
|
|
305
|
+
exit 1
|
|
306
|
+
fi
|
|
307
|
+
|
|
308
|
+
# Create parent directory
|
|
309
|
+
mkdir -p "$(dirname "$INSTALL_DIR")"
|
|
310
|
+
|
|
311
|
+
if [[ -d "$INSTALL_DIR/.git" ]]; then
|
|
312
|
+
print_info "Existing installation found - updating..."
|
|
313
|
+
cd "$INSTALL_DIR" || exit 1
|
|
314
|
+
git pull --ff-only
|
|
315
|
+
if [[ $? -ne 0 ]]; then
|
|
316
|
+
print_warning "Git pull failed - trying reset to origin/main"
|
|
317
|
+
git fetch origin
|
|
318
|
+
git reset --hard origin/main
|
|
319
|
+
fi
|
|
320
|
+
else
|
|
321
|
+
print_info "Cloning aidevops to $INSTALL_DIR..."
|
|
322
|
+
if [[ -d "$INSTALL_DIR" ]]; then
|
|
323
|
+
print_warning "Directory exists but is not a git repo - backing up"
|
|
324
|
+
mv "$INSTALL_DIR" "$INSTALL_DIR.backup.$(date +%Y%m%d_%H%M%S)"
|
|
325
|
+
fi
|
|
326
|
+
git clone "$REPO_URL" "$INSTALL_DIR"
|
|
327
|
+
if [[ $? -ne 0 ]]; then
|
|
328
|
+
print_error "Failed to clone repository"
|
|
329
|
+
exit 1
|
|
330
|
+
fi
|
|
331
|
+
fi
|
|
332
|
+
|
|
333
|
+
print_success "Repository ready at $INSTALL_DIR"
|
|
334
|
+
|
|
335
|
+
# Re-execute the local script
|
|
336
|
+
cd "$INSTALL_DIR" || exit 1
|
|
337
|
+
exec bash "./setup.sh" "$@"
|
|
338
|
+
fi
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
# Detect package manager
|
|
342
|
+
detect_package_manager() {
|
|
343
|
+
if command -v brew >/dev/null 2>&1; then
|
|
344
|
+
echo "brew"
|
|
345
|
+
elif command -v apt-get >/dev/null 2>&1; then
|
|
346
|
+
echo "apt"
|
|
347
|
+
elif command -v dnf >/dev/null 2>&1; then
|
|
348
|
+
echo "dnf"
|
|
349
|
+
elif command -v yum >/dev/null 2>&1; then
|
|
350
|
+
echo "yum"
|
|
351
|
+
elif command -v pacman >/dev/null 2>&1; then
|
|
352
|
+
echo "pacman"
|
|
353
|
+
elif command -v apk >/dev/null 2>&1; then
|
|
354
|
+
echo "apk"
|
|
355
|
+
else
|
|
356
|
+
echo "unknown"
|
|
357
|
+
fi
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
# Install packages using detected package manager
|
|
361
|
+
install_packages() {
|
|
362
|
+
local pkg_manager="$1"
|
|
363
|
+
shift
|
|
364
|
+
local packages=("$@")
|
|
365
|
+
|
|
366
|
+
case "$pkg_manager" in
|
|
367
|
+
brew)
|
|
368
|
+
brew install "${packages[@]}"
|
|
369
|
+
;;
|
|
370
|
+
apt)
|
|
371
|
+
sudo apt-get update && sudo apt-get install -y "${packages[@]}"
|
|
372
|
+
;;
|
|
373
|
+
dnf)
|
|
374
|
+
sudo dnf install -y "${packages[@]}"
|
|
375
|
+
;;
|
|
376
|
+
yum)
|
|
377
|
+
sudo yum install -y "${packages[@]}"
|
|
378
|
+
;;
|
|
379
|
+
pacman)
|
|
380
|
+
sudo pacman -S --noconfirm "${packages[@]}"
|
|
381
|
+
;;
|
|
382
|
+
apk)
|
|
383
|
+
sudo apk add "${packages[@]}"
|
|
384
|
+
;;
|
|
385
|
+
*)
|
|
386
|
+
return 1
|
|
387
|
+
;;
|
|
388
|
+
esac
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
# Check system requirements
|
|
392
|
+
check_requirements() {
|
|
393
|
+
print_info "Checking system requirements..."
|
|
394
|
+
|
|
395
|
+
local missing_deps=()
|
|
396
|
+
|
|
397
|
+
# Check for required commands
|
|
398
|
+
command -v jq >/dev/null 2>&1 || missing_deps+=("jq")
|
|
399
|
+
command -v curl >/dev/null 2>&1 || missing_deps+=("curl")
|
|
400
|
+
command -v ssh >/dev/null 2>&1 || missing_deps+=("ssh")
|
|
401
|
+
|
|
402
|
+
if [[ ${#missing_deps[@]} -gt 0 ]]; then
|
|
403
|
+
print_warning "Missing required dependencies: ${missing_deps[*]}"
|
|
404
|
+
|
|
405
|
+
local pkg_manager
|
|
406
|
+
pkg_manager=$(detect_package_manager)
|
|
407
|
+
|
|
408
|
+
if [[ "$pkg_manager" == "unknown" ]]; then
|
|
409
|
+
print_error "Could not detect package manager"
|
|
410
|
+
echo ""
|
|
411
|
+
echo "Please install manually:"
|
|
412
|
+
echo " macOS: brew install ${missing_deps[*]}"
|
|
413
|
+
echo " Ubuntu/Debian: sudo apt-get install ${missing_deps[*]}"
|
|
414
|
+
echo " Fedora: sudo dnf install ${missing_deps[*]}"
|
|
415
|
+
echo " CentOS/RHEL: sudo yum install ${missing_deps[*]}"
|
|
416
|
+
echo " Arch: sudo pacman -S ${missing_deps[*]}"
|
|
417
|
+
echo " Alpine: sudo apk add ${missing_deps[*]}"
|
|
418
|
+
exit 1
|
|
419
|
+
fi
|
|
420
|
+
|
|
421
|
+
echo ""
|
|
422
|
+
read -r -p "Install missing dependencies using $pkg_manager? (y/n): " install_deps
|
|
423
|
+
|
|
424
|
+
if [[ "$install_deps" == "y" ]]; then
|
|
425
|
+
print_info "Installing ${missing_deps[*]}..."
|
|
426
|
+
if install_packages "$pkg_manager" "${missing_deps[@]}"; then
|
|
427
|
+
print_success "Dependencies installed successfully"
|
|
428
|
+
else
|
|
429
|
+
print_error "Failed to install dependencies"
|
|
430
|
+
exit 1
|
|
431
|
+
fi
|
|
432
|
+
else
|
|
433
|
+
print_error "Cannot continue without required dependencies"
|
|
434
|
+
exit 1
|
|
435
|
+
fi
|
|
436
|
+
fi
|
|
437
|
+
|
|
438
|
+
print_success "All required dependencies found"
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
# Check for optional dependencies
|
|
442
|
+
check_optional_deps() {
|
|
443
|
+
print_info "Checking optional dependencies..."
|
|
444
|
+
|
|
445
|
+
local missing_optional=()
|
|
446
|
+
|
|
447
|
+
if ! command -v sshpass >/dev/null 2>&1; then
|
|
448
|
+
missing_optional+=("sshpass")
|
|
449
|
+
else
|
|
450
|
+
print_success "sshpass found"
|
|
451
|
+
fi
|
|
452
|
+
|
|
453
|
+
if [[ ${#missing_optional[@]} -gt 0 ]]; then
|
|
454
|
+
print_warning "Missing optional dependencies: ${missing_optional[*]}"
|
|
455
|
+
echo " sshpass - needed for password-based SSH (like Hostinger)"
|
|
456
|
+
|
|
457
|
+
local pkg_manager
|
|
458
|
+
pkg_manager=$(detect_package_manager)
|
|
459
|
+
|
|
460
|
+
if [[ "$pkg_manager" != "unknown" ]]; then
|
|
461
|
+
read -r -p "Install optional dependencies using $pkg_manager? (y/n): " install_optional
|
|
462
|
+
|
|
463
|
+
if [[ "$install_optional" == "y" ]]; then
|
|
464
|
+
print_info "Installing ${missing_optional[*]}..."
|
|
465
|
+
if install_packages "$pkg_manager" "${missing_optional[@]}"; then
|
|
466
|
+
print_success "Optional dependencies installed"
|
|
467
|
+
else
|
|
468
|
+
print_warning "Failed to install optional dependencies (non-critical)"
|
|
469
|
+
fi
|
|
470
|
+
else
|
|
471
|
+
print_info "Skipped optional dependencies"
|
|
472
|
+
fi
|
|
473
|
+
fi
|
|
474
|
+
fi
|
|
475
|
+
return 0
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
# Setup Git CLI tools
|
|
479
|
+
setup_git_clis() {
|
|
480
|
+
print_info "Setting up Git CLI tools..."
|
|
481
|
+
|
|
482
|
+
local cli_tools=()
|
|
483
|
+
local missing_packages=()
|
|
484
|
+
local missing_names=()
|
|
485
|
+
|
|
486
|
+
# Check for GitHub CLI
|
|
487
|
+
if ! command -v gh >/dev/null 2>&1; then
|
|
488
|
+
missing_packages+=("gh")
|
|
489
|
+
missing_names+=("GitHub CLI")
|
|
490
|
+
else
|
|
491
|
+
cli_tools+=("GitHub CLI")
|
|
492
|
+
fi
|
|
493
|
+
|
|
494
|
+
# Check for GitLab CLI
|
|
495
|
+
if ! command -v glab >/dev/null 2>&1; then
|
|
496
|
+
missing_packages+=("glab")
|
|
497
|
+
missing_names+=("GitLab CLI")
|
|
498
|
+
else
|
|
499
|
+
cli_tools+=("GitLab CLI")
|
|
500
|
+
fi
|
|
501
|
+
|
|
502
|
+
# Report found tools
|
|
503
|
+
if [[ ${#cli_tools[@]} -gt 0 ]]; then
|
|
504
|
+
print_success "Found Git CLI tools: ${cli_tools[*]}"
|
|
505
|
+
fi
|
|
506
|
+
|
|
507
|
+
# Offer to install missing tools
|
|
508
|
+
if [[ ${#missing_packages[@]} -gt 0 ]]; then
|
|
509
|
+
print_warning "Missing Git CLI tools: ${missing_names[*]}"
|
|
510
|
+
echo " These provide enhanced Git platform integration (repos, PRs, issues)"
|
|
511
|
+
|
|
512
|
+
local pkg_manager
|
|
513
|
+
pkg_manager=$(detect_package_manager)
|
|
514
|
+
|
|
515
|
+
if [[ "$pkg_manager" != "unknown" ]]; then
|
|
516
|
+
echo ""
|
|
517
|
+
read -r -p "Install Git CLI tools (${missing_packages[*]}) using $pkg_manager? (y/n): " install_git_clis
|
|
518
|
+
|
|
519
|
+
if [[ "$install_git_clis" == "y" ]]; then
|
|
520
|
+
print_info "Installing ${missing_packages[*]}..."
|
|
521
|
+
if install_packages "$pkg_manager" "${missing_packages[@]}"; then
|
|
522
|
+
print_success "Git CLI tools installed"
|
|
523
|
+
echo ""
|
|
524
|
+
echo "📋 Next steps - authenticate each CLI:"
|
|
525
|
+
for pkg in "${missing_packages[@]}"; do
|
|
526
|
+
case "$pkg" in
|
|
527
|
+
gh) echo " • gh auth login" ;;
|
|
528
|
+
glab) echo " • glab auth login" ;;
|
|
529
|
+
esac
|
|
530
|
+
done
|
|
531
|
+
else
|
|
532
|
+
print_warning "Failed to install some Git CLI tools (non-critical)"
|
|
533
|
+
fi
|
|
534
|
+
else
|
|
535
|
+
print_info "Skipped Git CLI tools installation"
|
|
536
|
+
echo ""
|
|
537
|
+
echo "📋 Manual installation:"
|
|
538
|
+
echo " macOS: brew install ${missing_packages[*]}"
|
|
539
|
+
echo " Ubuntu: sudo apt install ${missing_packages[*]}"
|
|
540
|
+
echo " Fedora: sudo dnf install ${missing_packages[*]}"
|
|
541
|
+
fi
|
|
542
|
+
else
|
|
543
|
+
echo ""
|
|
544
|
+
echo "📋 Manual installation:"
|
|
545
|
+
echo " macOS: brew install ${missing_packages[*]}"
|
|
546
|
+
echo " Ubuntu: sudo apt install ${missing_packages[*]}"
|
|
547
|
+
echo " Fedora: sudo dnf install ${missing_packages[*]}"
|
|
548
|
+
fi
|
|
549
|
+
else
|
|
550
|
+
print_success "All Git CLI tools installed and ready!"
|
|
551
|
+
fi
|
|
552
|
+
|
|
553
|
+
# Check for Gitea CLI separately (not in standard package managers)
|
|
554
|
+
if ! command -v tea >/dev/null 2>&1; then
|
|
555
|
+
print_info "Gitea CLI (tea) not found - install manually if needed:"
|
|
556
|
+
echo " go install code.gitea.io/tea/cmd/tea@latest"
|
|
557
|
+
echo " Or download from: https://dl.gitea.io/tea/"
|
|
558
|
+
else
|
|
559
|
+
print_success "Gitea CLI (tea) found"
|
|
560
|
+
fi
|
|
561
|
+
|
|
562
|
+
return 0
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
# Setup recommended tools (Tabby terminal, Zed editor)
|
|
566
|
+
setup_recommended_tools() {
|
|
567
|
+
print_info "Checking recommended development tools..."
|
|
568
|
+
|
|
569
|
+
local missing_tools=()
|
|
570
|
+
local missing_names=()
|
|
571
|
+
|
|
572
|
+
# Check for Tabby terminal
|
|
573
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
574
|
+
# macOS - check Applications folder
|
|
575
|
+
if [[ ! -d "/Applications/Tabby.app" ]]; then
|
|
576
|
+
missing_tools+=("tabby")
|
|
577
|
+
missing_names+=("Tabby (modern terminal)")
|
|
578
|
+
else
|
|
579
|
+
print_success "Tabby terminal found"
|
|
580
|
+
fi
|
|
581
|
+
elif [[ "$(uname)" == "Linux" ]]; then
|
|
582
|
+
# Linux - check if tabby command exists
|
|
583
|
+
if ! command -v tabby >/dev/null 2>&1; then
|
|
584
|
+
missing_tools+=("tabby")
|
|
585
|
+
missing_names+=("Tabby (modern terminal)")
|
|
586
|
+
else
|
|
587
|
+
print_success "Tabby terminal found"
|
|
588
|
+
fi
|
|
589
|
+
fi
|
|
590
|
+
|
|
591
|
+
# Check for Zed editor
|
|
592
|
+
local zed_exists=false
|
|
593
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
594
|
+
# macOS - check Applications folder
|
|
595
|
+
if [[ ! -d "/Applications/Zed.app" ]]; then
|
|
596
|
+
missing_tools+=("zed")
|
|
597
|
+
missing_names+=("Zed (AI-native editor)")
|
|
598
|
+
else
|
|
599
|
+
print_success "Zed editor found"
|
|
600
|
+
zed_exists=true
|
|
601
|
+
fi
|
|
602
|
+
elif [[ "$(uname)" == "Linux" ]]; then
|
|
603
|
+
# Linux - check if zed command exists
|
|
604
|
+
if ! command -v zed >/dev/null 2>&1; then
|
|
605
|
+
missing_tools+=("zed")
|
|
606
|
+
missing_names+=("Zed (AI-native editor)")
|
|
607
|
+
else
|
|
608
|
+
print_success "Zed editor found"
|
|
609
|
+
zed_exists=true
|
|
610
|
+
fi
|
|
611
|
+
fi
|
|
612
|
+
|
|
613
|
+
# Check for OpenCode extension in existing Zed installation
|
|
614
|
+
if [[ "$zed_exists" == "true" ]]; then
|
|
615
|
+
local zed_extensions_dir=""
|
|
616
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
617
|
+
zed_extensions_dir="$HOME/Library/Application Support/Zed/extensions/installed"
|
|
618
|
+
elif [[ "$(uname)" == "Linux" ]]; then
|
|
619
|
+
zed_extensions_dir="$HOME/.local/share/zed/extensions/installed"
|
|
620
|
+
fi
|
|
621
|
+
|
|
622
|
+
if [[ -d "$zed_extensions_dir" ]]; then
|
|
623
|
+
if [[ ! -d "$zed_extensions_dir/opencode" ]]; then
|
|
624
|
+
read -r -p "Install OpenCode extension for Zed? (y/n): " install_opencode_ext
|
|
625
|
+
if [[ "$install_opencode_ext" == "y" ]]; then
|
|
626
|
+
print_info "Installing OpenCode extension..."
|
|
627
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
628
|
+
open "zed://extension/opencode" 2>/dev/null
|
|
629
|
+
print_success "OpenCode extension install triggered"
|
|
630
|
+
print_info "Zed will open and prompt to install the extension"
|
|
631
|
+
elif [[ "$(uname)" == "Linux" ]]; then
|
|
632
|
+
xdg-open "zed://extension/opencode" 2>/dev/null || \
|
|
633
|
+
print_info "Open Zed and install 'opencode' from Extensions"
|
|
634
|
+
fi
|
|
635
|
+
fi
|
|
636
|
+
else
|
|
637
|
+
print_success "OpenCode extension already installed in Zed"
|
|
638
|
+
fi
|
|
639
|
+
fi
|
|
640
|
+
fi
|
|
641
|
+
|
|
642
|
+
# Offer to install missing tools
|
|
643
|
+
if [[ ${#missing_tools[@]} -gt 0 ]]; then
|
|
644
|
+
print_warning "Missing recommended tools: ${missing_names[*]}"
|
|
645
|
+
echo " Tabby - Modern terminal with profiles, SSH manager, split panes"
|
|
646
|
+
echo " Zed - High-performance AI-native code editor"
|
|
647
|
+
echo ""
|
|
648
|
+
|
|
649
|
+
# Install Tabby if missing
|
|
650
|
+
if [[ " ${missing_tools[*]} " =~ " tabby " ]]; then
|
|
651
|
+
read -r -p "Install Tabby terminal? (y/n): " install_tabby
|
|
652
|
+
|
|
653
|
+
if [[ "$install_tabby" == "y" ]]; then
|
|
654
|
+
print_info "Installing Tabby..."
|
|
655
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
656
|
+
if command -v brew >/dev/null 2>&1; then
|
|
657
|
+
brew install --cask tabby
|
|
658
|
+
if [[ $? -eq 0 ]]; then
|
|
659
|
+
print_success "Tabby installed successfully"
|
|
660
|
+
else
|
|
661
|
+
print_warning "Failed to install Tabby via Homebrew"
|
|
662
|
+
echo " Download manually: https://github.com/Eugeny/tabby/releases/latest"
|
|
663
|
+
fi
|
|
664
|
+
else
|
|
665
|
+
print_warning "Homebrew not found"
|
|
666
|
+
echo " Download manually: https://github.com/Eugeny/tabby/releases/latest"
|
|
667
|
+
fi
|
|
668
|
+
elif [[ "$(uname)" == "Linux" ]]; then
|
|
669
|
+
local pkg_manager
|
|
670
|
+
pkg_manager=$(detect_package_manager)
|
|
671
|
+
case "$pkg_manager" in
|
|
672
|
+
apt)
|
|
673
|
+
# Add packagecloud repo for Tabby
|
|
674
|
+
print_info "Adding Tabby repository..."
|
|
675
|
+
curl -s https://packagecloud.io/install/repositories/eugeny/tabby/script.deb.sh | sudo bash
|
|
676
|
+
sudo apt-get install -y tabby-terminal
|
|
677
|
+
;;
|
|
678
|
+
dnf|yum)
|
|
679
|
+
print_info "Adding Tabby repository..."
|
|
680
|
+
curl -s https://packagecloud.io/install/repositories/eugeny/tabby/script.rpm.sh | sudo bash
|
|
681
|
+
sudo "$pkg_manager" install -y tabby-terminal
|
|
682
|
+
;;
|
|
683
|
+
pacman)
|
|
684
|
+
# AUR package
|
|
685
|
+
print_info "Tabby available in AUR as 'tabby-bin'"
|
|
686
|
+
echo " Install with: yay -S tabby-bin"
|
|
687
|
+
;;
|
|
688
|
+
*)
|
|
689
|
+
echo " Download manually: https://github.com/Eugeny/tabby/releases/latest"
|
|
690
|
+
;;
|
|
691
|
+
esac
|
|
692
|
+
fi
|
|
693
|
+
else
|
|
694
|
+
print_info "Skipped Tabby installation"
|
|
695
|
+
fi
|
|
696
|
+
fi
|
|
697
|
+
|
|
698
|
+
# Install Zed if missing
|
|
699
|
+
if [[ " ${missing_tools[*]} " =~ " zed " ]]; then
|
|
700
|
+
read -r -p "Install Zed editor? (y/n): " install_zed
|
|
701
|
+
|
|
702
|
+
if [[ "$install_zed" == "y" ]]; then
|
|
703
|
+
print_info "Installing Zed..."
|
|
704
|
+
local zed_installed=false
|
|
705
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
706
|
+
if command -v brew >/dev/null 2>&1; then
|
|
707
|
+
brew install --cask zed
|
|
708
|
+
if [[ $? -eq 0 ]]; then
|
|
709
|
+
print_success "Zed installed successfully"
|
|
710
|
+
zed_installed=true
|
|
711
|
+
else
|
|
712
|
+
print_warning "Failed to install Zed via Homebrew"
|
|
713
|
+
echo " Download manually: https://zed.dev/download"
|
|
714
|
+
fi
|
|
715
|
+
else
|
|
716
|
+
print_warning "Homebrew not found"
|
|
717
|
+
echo " Download manually: https://zed.dev/download"
|
|
718
|
+
fi
|
|
719
|
+
elif [[ "$(uname)" == "Linux" ]]; then
|
|
720
|
+
# Zed provides an install script for Linux
|
|
721
|
+
print_info "Running Zed install script..."
|
|
722
|
+
curl -f https://zed.dev/install.sh | sh
|
|
723
|
+
if [[ $? -eq 0 ]]; then
|
|
724
|
+
print_success "Zed installed successfully"
|
|
725
|
+
zed_installed=true
|
|
726
|
+
else
|
|
727
|
+
print_warning "Failed to install Zed"
|
|
728
|
+
echo " See: https://zed.dev/docs/linux"
|
|
729
|
+
fi
|
|
730
|
+
fi
|
|
731
|
+
|
|
732
|
+
# Install OpenCode extension for Zed
|
|
733
|
+
if [[ "$zed_installed" == "true" ]]; then
|
|
734
|
+
read -r -p "Install OpenCode extension for Zed? (y/n): " install_opencode_ext
|
|
735
|
+
if [[ "$install_opencode_ext" == "y" ]]; then
|
|
736
|
+
print_info "Installing OpenCode extension..."
|
|
737
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
738
|
+
open "zed://extension/opencode" 2>/dev/null
|
|
739
|
+
print_success "OpenCode extension install triggered"
|
|
740
|
+
print_info "Zed will open and prompt to install the extension"
|
|
741
|
+
elif [[ "$(uname)" == "Linux" ]]; then
|
|
742
|
+
xdg-open "zed://extension/opencode" 2>/dev/null || \
|
|
743
|
+
print_info "Open Zed and install 'opencode' from Extensions (Cmd+Shift+X)"
|
|
744
|
+
fi
|
|
745
|
+
fi
|
|
746
|
+
fi
|
|
747
|
+
else
|
|
748
|
+
print_info "Skipped Zed installation"
|
|
749
|
+
fi
|
|
750
|
+
fi
|
|
751
|
+
else
|
|
752
|
+
print_success "All recommended tools installed!"
|
|
753
|
+
fi
|
|
754
|
+
|
|
755
|
+
return 0
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
# Setup SSH key if needed
|
|
759
|
+
setup_ssh_key() {
|
|
760
|
+
print_info "Checking SSH key setup..."
|
|
761
|
+
|
|
762
|
+
if [[ ! -f ~/.ssh/id_ed25519 ]]; then
|
|
763
|
+
print_warning "Ed25519 SSH key not found"
|
|
764
|
+
read -r -p "Generate new Ed25519 SSH key? (y/n): " generate_key
|
|
765
|
+
|
|
766
|
+
if [[ "$generate_key" == "y" ]]; then
|
|
767
|
+
read -r -p "Enter your email address: " email
|
|
768
|
+
ssh-keygen -t ed25519 -C "$email"
|
|
769
|
+
print_success "SSH key generated"
|
|
770
|
+
else
|
|
771
|
+
print_info "Skipping SSH key generation"
|
|
772
|
+
fi
|
|
773
|
+
else
|
|
774
|
+
print_success "Ed25519 SSH key found"
|
|
775
|
+
fi
|
|
776
|
+
return 0
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
# Setup configuration files
|
|
780
|
+
setup_configs() {
|
|
781
|
+
print_info "Setting up configuration files..."
|
|
782
|
+
|
|
783
|
+
# Create configs directory if it doesn't exist
|
|
784
|
+
mkdir -p configs
|
|
785
|
+
|
|
786
|
+
# Copy template configs if they don't exist
|
|
787
|
+
for template in configs/*.txt; do
|
|
788
|
+
if [[ -f "$template" ]]; then
|
|
789
|
+
config_file="${template%.txt}"
|
|
790
|
+
if [[ ! -f "$config_file" ]]; then
|
|
791
|
+
cp "$template" "$config_file"
|
|
792
|
+
print_success "Created $(basename "$config_file")"
|
|
793
|
+
print_warning "Please edit $(basename "$config_file") with your actual credentials"
|
|
794
|
+
else
|
|
795
|
+
print_info "Found existing config: $(basename "$config_file") - Skipping"
|
|
796
|
+
fi
|
|
797
|
+
fi
|
|
798
|
+
done
|
|
799
|
+
|
|
800
|
+
return 0
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
# Set proper permissions
|
|
804
|
+
set_permissions() {
|
|
805
|
+
print_info "Setting proper file permissions..."
|
|
806
|
+
|
|
807
|
+
# Make scripts executable
|
|
808
|
+
chmod +x ./*.sh
|
|
809
|
+
chmod +x .agent/scripts/*.sh
|
|
810
|
+
chmod +x ssh/*.sh
|
|
811
|
+
|
|
812
|
+
# Secure configuration files
|
|
813
|
+
chmod 600 configs/*.json 2>/dev/null || true
|
|
814
|
+
|
|
815
|
+
print_success "File permissions set"
|
|
816
|
+
return 0
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
# Add ~/.local/bin to PATH in shell config
|
|
820
|
+
add_local_bin_to_path() {
|
|
821
|
+
local shell_rc=""
|
|
822
|
+
local path_line='export PATH="$HOME/.local/bin:$PATH"'
|
|
823
|
+
|
|
824
|
+
# Detect shell config file
|
|
825
|
+
if [[ "$SHELL" == *"zsh"* ]] || [[ -n "$ZSH_VERSION" ]]; then
|
|
826
|
+
shell_rc="$HOME/.zshrc"
|
|
827
|
+
elif [[ "$SHELL" == *"bash"* ]] || [[ -n "$BASH_VERSION" ]]; then
|
|
828
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
829
|
+
shell_rc="$HOME/.bash_profile"
|
|
830
|
+
else
|
|
831
|
+
shell_rc="$HOME/.bashrc"
|
|
832
|
+
fi
|
|
833
|
+
elif [[ -f "$HOME/.zshrc" ]]; then
|
|
834
|
+
shell_rc="$HOME/.zshrc"
|
|
835
|
+
elif [[ -f "$HOME/.bashrc" ]]; then
|
|
836
|
+
shell_rc="$HOME/.bashrc"
|
|
837
|
+
elif [[ -f "$HOME/.bash_profile" ]]; then
|
|
838
|
+
shell_rc="$HOME/.bash_profile"
|
|
839
|
+
fi
|
|
840
|
+
|
|
841
|
+
if [[ -z "$shell_rc" ]]; then
|
|
842
|
+
print_warning "Could not detect shell config file"
|
|
843
|
+
print_info "Add this to your shell config: $path_line"
|
|
844
|
+
return 0
|
|
845
|
+
fi
|
|
846
|
+
|
|
847
|
+
# Create the rc file if it doesn't exist
|
|
848
|
+
if [[ ! -f "$shell_rc" ]]; then
|
|
849
|
+
touch "$shell_rc"
|
|
850
|
+
fi
|
|
851
|
+
|
|
852
|
+
# Check if already added
|
|
853
|
+
if grep -q '\.local/bin' "$shell_rc" 2>/dev/null; then
|
|
854
|
+
print_info "~/.local/bin already in PATH (found in $shell_rc)"
|
|
855
|
+
return 0
|
|
856
|
+
fi
|
|
857
|
+
|
|
858
|
+
# Add to shell config
|
|
859
|
+
echo "" >> "$shell_rc"
|
|
860
|
+
echo "# Added by aidevops setup" >> "$shell_rc"
|
|
861
|
+
echo "$path_line" >> "$shell_rc"
|
|
862
|
+
|
|
863
|
+
print_success "Added ~/.local/bin to PATH in $shell_rc"
|
|
864
|
+
print_info "Run 'source $shell_rc' or restart your terminal to use 'aidevops' command"
|
|
865
|
+
|
|
866
|
+
# Also export for current session
|
|
867
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
868
|
+
|
|
869
|
+
return 0
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
# Install aidevops CLI command
|
|
873
|
+
install_aidevops_cli() {
|
|
874
|
+
print_info "Installing aidevops CLI command..."
|
|
875
|
+
|
|
876
|
+
local script_dir
|
|
877
|
+
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
878
|
+
local cli_source="$script_dir/aidevops.sh"
|
|
879
|
+
local cli_target="/usr/local/bin/aidevops"
|
|
880
|
+
|
|
881
|
+
if [[ ! -f "$cli_source" ]]; then
|
|
882
|
+
print_warning "aidevops.sh not found - skipping CLI installation"
|
|
883
|
+
return 0
|
|
884
|
+
fi
|
|
885
|
+
|
|
886
|
+
# Check if we can write to /usr/local/bin
|
|
887
|
+
if [[ -w "/usr/local/bin" ]]; then
|
|
888
|
+
# Direct symlink
|
|
889
|
+
ln -sf "$cli_source" "$cli_target"
|
|
890
|
+
print_success "Installed aidevops command to $cli_target"
|
|
891
|
+
elif [[ -w "$HOME/.local/bin" ]] || mkdir -p "$HOME/.local/bin" 2>/dev/null; then
|
|
892
|
+
# Use ~/.local/bin instead
|
|
893
|
+
cli_target="$HOME/.local/bin/aidevops"
|
|
894
|
+
ln -sf "$cli_source" "$cli_target"
|
|
895
|
+
print_success "Installed aidevops command to $cli_target"
|
|
896
|
+
|
|
897
|
+
# Check if ~/.local/bin is in PATH and add it if not
|
|
898
|
+
if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
|
|
899
|
+
add_local_bin_to_path
|
|
900
|
+
fi
|
|
901
|
+
else
|
|
902
|
+
# Need sudo
|
|
903
|
+
print_info "Installing aidevops command requires sudo..."
|
|
904
|
+
if sudo ln -sf "$cli_source" "$cli_target"; then
|
|
905
|
+
print_success "Installed aidevops command to $cli_target"
|
|
906
|
+
else
|
|
907
|
+
print_warning "Could not install aidevops command globally"
|
|
908
|
+
print_info "You can run it directly: $cli_source"
|
|
909
|
+
fi
|
|
910
|
+
fi
|
|
911
|
+
|
|
912
|
+
return 0
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
# Setup shell aliases
|
|
916
|
+
setup_aliases() {
|
|
917
|
+
print_info "Setting up shell aliases..."
|
|
918
|
+
|
|
919
|
+
local shell_rc=""
|
|
920
|
+
local shell_name=""
|
|
921
|
+
|
|
922
|
+
# Detect shell - check $SHELL first, then try to detect from process
|
|
923
|
+
if [[ "$SHELL" == *"zsh"* ]]; then
|
|
924
|
+
shell_rc="$HOME/.zshrc"
|
|
925
|
+
shell_name="zsh"
|
|
926
|
+
elif [[ "$SHELL" == *"bash"* ]]; then
|
|
927
|
+
# macOS: use .bash_profile (login shell), Linux: use .bashrc
|
|
928
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
929
|
+
shell_rc="$HOME/.bash_profile"
|
|
930
|
+
else
|
|
931
|
+
shell_rc="$HOME/.bashrc"
|
|
932
|
+
fi
|
|
933
|
+
shell_name="bash"
|
|
934
|
+
elif [[ "$SHELL" == *"fish"* ]]; then
|
|
935
|
+
shell_rc="$HOME/.config/fish/config.fish"
|
|
936
|
+
shell_name="fish"
|
|
937
|
+
elif [[ "$SHELL" == *"ksh"* ]]; then
|
|
938
|
+
shell_rc="$HOME/.kshrc"
|
|
939
|
+
shell_name="ksh"
|
|
940
|
+
elif [[ -n "$ZSH_VERSION" ]]; then
|
|
941
|
+
shell_rc="$HOME/.zshrc"
|
|
942
|
+
shell_name="zsh"
|
|
943
|
+
elif [[ -n "$BASH_VERSION" ]]; then
|
|
944
|
+
if [[ "$(uname)" == "Darwin" ]]; then
|
|
945
|
+
shell_rc="$HOME/.bash_profile"
|
|
946
|
+
else
|
|
947
|
+
shell_rc="$HOME/.bashrc"
|
|
948
|
+
fi
|
|
949
|
+
shell_name="bash"
|
|
950
|
+
else
|
|
951
|
+
# Fallback: check common rc files
|
|
952
|
+
if [[ -f "$HOME/.zshrc" ]]; then
|
|
953
|
+
shell_rc="$HOME/.zshrc"
|
|
954
|
+
shell_name="zsh"
|
|
955
|
+
elif [[ -f "$HOME/.bashrc" ]]; then
|
|
956
|
+
shell_rc="$HOME/.bashrc"
|
|
957
|
+
shell_name="bash"
|
|
958
|
+
elif [[ -f "$HOME/.bash_profile" ]]; then
|
|
959
|
+
shell_rc="$HOME/.bash_profile"
|
|
960
|
+
shell_name="bash"
|
|
961
|
+
else
|
|
962
|
+
print_warning "Could not detect shell configuration file"
|
|
963
|
+
print_info "Supported shells: bash, zsh, fish, ksh"
|
|
964
|
+
print_info "You can manually add aliases to your shell config"
|
|
965
|
+
return 0
|
|
966
|
+
fi
|
|
967
|
+
fi
|
|
968
|
+
|
|
969
|
+
# Create the rc file if it doesn't exist (common on fresh systems)
|
|
970
|
+
if [[ ! -f "$shell_rc" ]]; then
|
|
971
|
+
print_info "Creating $shell_rc (file did not exist)"
|
|
972
|
+
touch "$shell_rc"
|
|
973
|
+
fi
|
|
974
|
+
|
|
975
|
+
# Check if aliases already exist
|
|
976
|
+
if grep -q "# AI Assistant Server Access" "$shell_rc" 2>/dev/null; then
|
|
977
|
+
print_info "Server Access aliases already configured in $shell_rc - Skipping"
|
|
978
|
+
return 0
|
|
979
|
+
fi
|
|
980
|
+
|
|
981
|
+
print_info "Detected shell: $shell_name"
|
|
982
|
+
read -r -p "Add shell aliases to $shell_rc? (y/n): " add_aliases
|
|
983
|
+
|
|
984
|
+
if [[ "$add_aliases" == "y" ]]; then
|
|
985
|
+
# Fish shell uses different syntax
|
|
986
|
+
if [[ "$shell_name" == "fish" ]]; then
|
|
987
|
+
mkdir -p "$HOME/.config/fish"
|
|
988
|
+
cat >> "$shell_rc" << 'EOF'
|
|
989
|
+
|
|
990
|
+
# AI Assistant Server Access Framework
|
|
991
|
+
alias servers './.agent/scripts/servers-helper.sh'
|
|
992
|
+
alias servers-list './.agent/scripts/servers-helper.sh list'
|
|
993
|
+
alias hostinger './.agent/scripts/hostinger-helper.sh'
|
|
994
|
+
alias hetzner './.agent/scripts/hetzner-helper.sh'
|
|
995
|
+
alias aws-helper './.agent/scripts/aws-helper.sh'
|
|
996
|
+
EOF
|
|
997
|
+
else
|
|
998
|
+
# Bash, zsh, ksh use same syntax
|
|
999
|
+
cat >> "$shell_rc" << 'EOF'
|
|
1000
|
+
|
|
1001
|
+
# AI Assistant Server Access Framework
|
|
1002
|
+
alias servers='./.agent/scripts/servers-helper.sh'
|
|
1003
|
+
alias servers-list='./.agent/scripts/servers-helper.sh list'
|
|
1004
|
+
alias hostinger='./.agent/scripts/hostinger-helper.sh'
|
|
1005
|
+
alias hetzner='./.agent/scripts/hetzner-helper.sh'
|
|
1006
|
+
alias aws-helper='./.agent/scripts/aws-helper.sh'
|
|
1007
|
+
EOF
|
|
1008
|
+
fi
|
|
1009
|
+
print_success "Aliases added to $shell_rc"
|
|
1010
|
+
print_info "Run 'source $shell_rc' or restart your terminal to use aliases"
|
|
1011
|
+
else
|
|
1012
|
+
print_info "Skipped alias setup by user request"
|
|
1013
|
+
fi
|
|
1014
|
+
return 0
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
# Setup terminal title integration (syncs tab title with git repo/branch)
|
|
1018
|
+
setup_terminal_title() {
|
|
1019
|
+
print_info "Setting up terminal title integration..."
|
|
1020
|
+
|
|
1021
|
+
local setup_script=".agent/scripts/terminal-title-setup.sh"
|
|
1022
|
+
|
|
1023
|
+
if [[ ! -f "$setup_script" ]]; then
|
|
1024
|
+
print_warning "Terminal title setup script not found - skipping"
|
|
1025
|
+
return 0
|
|
1026
|
+
fi
|
|
1027
|
+
|
|
1028
|
+
# Check if already installed
|
|
1029
|
+
local shell_name
|
|
1030
|
+
shell_name=$(basename "${SHELL:-/bin/bash}")
|
|
1031
|
+
local rc_file=""
|
|
1032
|
+
|
|
1033
|
+
case "$shell_name" in
|
|
1034
|
+
zsh) rc_file="$HOME/.zshrc" ;;
|
|
1035
|
+
bash) rc_file="$HOME/.bashrc" ;;
|
|
1036
|
+
fish) rc_file="$HOME/.config/fish/config.fish" ;;
|
|
1037
|
+
esac
|
|
1038
|
+
|
|
1039
|
+
if [[ -n "$rc_file" ]] && [[ -f "$rc_file" ]] && grep -q "aidevops terminal-title" "$rc_file" 2>/dev/null; then
|
|
1040
|
+
print_info "Terminal title integration already configured in $rc_file - Skipping"
|
|
1041
|
+
return 0
|
|
1042
|
+
fi
|
|
1043
|
+
|
|
1044
|
+
# Show current status before asking
|
|
1045
|
+
echo ""
|
|
1046
|
+
print_info "Terminal title integration syncs your terminal tab with git repo/branch"
|
|
1047
|
+
print_info "Example: Tab shows 'aidevops/feature/xyz' when in that branch"
|
|
1048
|
+
echo ""
|
|
1049
|
+
echo "Current status:"
|
|
1050
|
+
|
|
1051
|
+
# Shell info
|
|
1052
|
+
local shell_info="$shell_name"
|
|
1053
|
+
if [[ "$shell_name" == "zsh" ]] && [[ -d "$HOME/.oh-my-zsh" ]]; then
|
|
1054
|
+
shell_info="$shell_name (Oh-My-Zsh)"
|
|
1055
|
+
fi
|
|
1056
|
+
echo " Shell: $shell_info"
|
|
1057
|
+
|
|
1058
|
+
# Tabby info
|
|
1059
|
+
local tabby_config="$HOME/Library/Application Support/tabby/config.yaml"
|
|
1060
|
+
if [[ -f "$tabby_config" ]]; then
|
|
1061
|
+
local disabled_count
|
|
1062
|
+
disabled_count=$(grep -c "disableDynamicTitle: true" "$tabby_config" 2>/dev/null || echo "0")
|
|
1063
|
+
if [[ "$disabled_count" -gt 0 ]]; then
|
|
1064
|
+
echo " Tabby: detected, dynamic titles disabled in $disabled_count profile(s) (will fix)"
|
|
1065
|
+
else
|
|
1066
|
+
echo " Tabby: detected, dynamic titles enabled"
|
|
1067
|
+
fi
|
|
1068
|
+
fi
|
|
1069
|
+
|
|
1070
|
+
echo ""
|
|
1071
|
+
read -r -p "Install terminal title integration? (y/n): " install_title
|
|
1072
|
+
|
|
1073
|
+
if [[ "$install_title" == "y" ]]; then
|
|
1074
|
+
if bash "$setup_script" install; then
|
|
1075
|
+
print_success "Terminal title integration installed"
|
|
1076
|
+
else
|
|
1077
|
+
print_warning "Terminal title setup encountered issues (non-critical)"
|
|
1078
|
+
fi
|
|
1079
|
+
else
|
|
1080
|
+
print_info "Skipped terminal title setup by user request"
|
|
1081
|
+
print_info "You can install later with: ~/.aidevops/agents/scripts/terminal-title-setup.sh install"
|
|
1082
|
+
fi
|
|
1083
|
+
|
|
1084
|
+
return 0
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
# Deploy AI assistant templates
|
|
1088
|
+
deploy_ai_templates() {
|
|
1089
|
+
print_info "Deploying AI assistant templates..."
|
|
1090
|
+
|
|
1091
|
+
if [[ -f "templates/deploy-templates.sh" ]]; then
|
|
1092
|
+
print_info "Running template deployment script..."
|
|
1093
|
+
bash templates/deploy-templates.sh
|
|
1094
|
+
|
|
1095
|
+
if [[ $? -eq 0 ]]; then
|
|
1096
|
+
print_success "AI assistant templates deployed successfully"
|
|
1097
|
+
else
|
|
1098
|
+
print_warning "Template deployment encountered issues (non-critical)"
|
|
1099
|
+
fi
|
|
1100
|
+
else
|
|
1101
|
+
print_warning "Template deployment script not found - skipping"
|
|
1102
|
+
fi
|
|
1103
|
+
return 0
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
# Extract OpenCode prompts from binary (for Plan+ system-reminder)
|
|
1107
|
+
# Must run before deploy_aidevops_agents so the cache exists for injection
|
|
1108
|
+
extract_opencode_prompts() {
|
|
1109
|
+
local extract_script=".agent/scripts/extract-opencode-prompts.sh"
|
|
1110
|
+
if [[ -f "$extract_script" ]]; then
|
|
1111
|
+
if bash "$extract_script"; then
|
|
1112
|
+
print_success "OpenCode prompts extracted"
|
|
1113
|
+
else
|
|
1114
|
+
print_warning "OpenCode prompt extraction encountered issues (non-critical)"
|
|
1115
|
+
fi
|
|
1116
|
+
fi
|
|
1117
|
+
return 0
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
# Deploy aidevops agents to user location
|
|
1121
|
+
deploy_aidevops_agents() {
|
|
1122
|
+
print_info "Deploying aidevops agents to ~/.aidevops/agents/..."
|
|
1123
|
+
|
|
1124
|
+
local script_dir
|
|
1125
|
+
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
1126
|
+
local source_dir="$script_dir/.agent"
|
|
1127
|
+
local target_dir="$HOME/.aidevops/agents"
|
|
1128
|
+
|
|
1129
|
+
# Create backup if target exists (with rotation)
|
|
1130
|
+
if [[ -d "$target_dir" ]]; then
|
|
1131
|
+
create_backup_with_rotation "$target_dir" "agents"
|
|
1132
|
+
fi
|
|
1133
|
+
|
|
1134
|
+
# Create target directory and copy agents
|
|
1135
|
+
mkdir -p "$target_dir"
|
|
1136
|
+
|
|
1137
|
+
# If clean mode, remove stale files first
|
|
1138
|
+
if [[ "$CLEAN_MODE" == "true" ]]; then
|
|
1139
|
+
print_info "Clean mode: removing stale files from $target_dir"
|
|
1140
|
+
rm -rf "${target_dir:?}"/*
|
|
1141
|
+
fi
|
|
1142
|
+
|
|
1143
|
+
# Copy all agent files and folders (excluding scripts which are large)
|
|
1144
|
+
# We copy scripts separately to maintain structure
|
|
1145
|
+
cp -R "$source_dir"/* "$target_dir/"
|
|
1146
|
+
|
|
1147
|
+
if [[ $? -eq 0 ]]; then
|
|
1148
|
+
print_success "Deployed agents to $target_dir"
|
|
1149
|
+
|
|
1150
|
+
# Set permissions on scripts
|
|
1151
|
+
chmod +x "$target_dir/scripts/"*.sh 2>/dev/null || true
|
|
1152
|
+
|
|
1153
|
+
# Count what was deployed
|
|
1154
|
+
local agent_count
|
|
1155
|
+
agent_count=$(find "$target_dir" -name "*.md" -type f | wc -l | tr -d ' ')
|
|
1156
|
+
local script_count
|
|
1157
|
+
script_count=$(find "$target_dir/scripts" -name "*.sh" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
1158
|
+
|
|
1159
|
+
print_info "Deployed $agent_count agent files and $script_count scripts"
|
|
1160
|
+
|
|
1161
|
+
# Copy VERSION file from repo root to deployed agents
|
|
1162
|
+
if [[ -f "$script_dir/VERSION" ]]; then
|
|
1163
|
+
if cp "$script_dir/VERSION" "$target_dir/VERSION"; then
|
|
1164
|
+
print_info "Copied VERSION file to deployed agents"
|
|
1165
|
+
else
|
|
1166
|
+
print_warning "Failed to copy VERSION file (Plan+ may not read version correctly)"
|
|
1167
|
+
fi
|
|
1168
|
+
else
|
|
1169
|
+
print_warning "VERSION file not found in repo root"
|
|
1170
|
+
fi
|
|
1171
|
+
|
|
1172
|
+
# Inject extracted OpenCode plan-reminder into Plan+ if available
|
|
1173
|
+
local plan_reminder="$HOME/.aidevops/cache/opencode-prompts/plan-reminder.txt"
|
|
1174
|
+
local plan_plus="$target_dir/plan-plus.md"
|
|
1175
|
+
if [[ -f "$plan_reminder" && -f "$plan_plus" ]]; then
|
|
1176
|
+
# Check if plan-plus.md has the placeholder marker
|
|
1177
|
+
if grep -q "OPENCODE-PLAN-REMINDER-INJECT" "$plan_plus"; then
|
|
1178
|
+
# Replace placeholder with extracted content
|
|
1179
|
+
local reminder_content
|
|
1180
|
+
reminder_content=$(cat "$plan_reminder")
|
|
1181
|
+
# Use awk to replace the placeholder section
|
|
1182
|
+
awk -v content="$reminder_content" '
|
|
1183
|
+
/<!-- OPENCODE-PLAN-REMINDER-INJECT-START -->/ { print; print content; skip=1; next }
|
|
1184
|
+
/<!-- OPENCODE-PLAN-REMINDER-INJECT-END -->/ { skip=0 }
|
|
1185
|
+
!skip { print }
|
|
1186
|
+
' "$plan_plus" > "$plan_plus.tmp" && mv "$plan_plus.tmp" "$plan_plus"
|
|
1187
|
+
print_info "Injected OpenCode plan-reminder into Plan+"
|
|
1188
|
+
fi
|
|
1189
|
+
fi
|
|
1190
|
+
else
|
|
1191
|
+
print_error "Failed to deploy agents"
|
|
1192
|
+
return 1
|
|
1193
|
+
fi
|
|
1194
|
+
|
|
1195
|
+
return 0
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
# Generate Agent Skills SKILL.md files for cross-tool compatibility
|
|
1199
|
+
generate_agent_skills() {
|
|
1200
|
+
print_info "Generating Agent Skills SKILL.md files..."
|
|
1201
|
+
|
|
1202
|
+
local skills_script="$HOME/.aidevops/agents/scripts/generate-skills.sh"
|
|
1203
|
+
|
|
1204
|
+
if [[ -f "$skills_script" ]]; then
|
|
1205
|
+
if bash "$skills_script" 2>/dev/null; then
|
|
1206
|
+
print_success "Agent Skills SKILL.md files generated"
|
|
1207
|
+
print_info "Skills compatible with: Cursor, Claude Code, VS Code, GitHub Copilot"
|
|
1208
|
+
else
|
|
1209
|
+
print_warning "Agent Skills generation encountered issues (non-critical)"
|
|
1210
|
+
fi
|
|
1211
|
+
else
|
|
1212
|
+
print_warning "Agent Skills generator not found at $skills_script"
|
|
1213
|
+
fi
|
|
1214
|
+
|
|
1215
|
+
return 0
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
# Inject aidevops reference into AI assistant AGENTS.md files
|
|
1219
|
+
inject_agents_reference() {
|
|
1220
|
+
print_info "Adding aidevops reference to AI assistant configurations..."
|
|
1221
|
+
|
|
1222
|
+
local reference_line='Add ~/.aidevops/agents/AGENTS.md to context for AI DevOps capabilities.'
|
|
1223
|
+
|
|
1224
|
+
# AI assistant agent directories - these get cleaned and receive AGENTS.md reference
|
|
1225
|
+
# Format: "config_dir:agents_subdir" where agents_subdir is the folder containing agent files
|
|
1226
|
+
local ai_agent_dirs=(
|
|
1227
|
+
"$HOME/.config/opencode:agent"
|
|
1228
|
+
"$HOME/.cursor:rules"
|
|
1229
|
+
"$HOME/.claude:commands"
|
|
1230
|
+
"$HOME/.continue:."
|
|
1231
|
+
"$HOME/.cody:."
|
|
1232
|
+
"$HOME/.opencode:."
|
|
1233
|
+
)
|
|
1234
|
+
|
|
1235
|
+
local updated_count=0
|
|
1236
|
+
|
|
1237
|
+
for entry in "${ai_agent_dirs[@]}"; do
|
|
1238
|
+
local config_dir="${entry%%:*}"
|
|
1239
|
+
local agents_subdir="${entry##*:}"
|
|
1240
|
+
local agents_dir="$config_dir/$agents_subdir"
|
|
1241
|
+
local agents_file="$agents_dir/AGENTS.md"
|
|
1242
|
+
|
|
1243
|
+
# Only process if the config directory exists (tool is installed)
|
|
1244
|
+
if [[ -d "$config_dir" ]]; then
|
|
1245
|
+
# Create agents subdirectory if needed
|
|
1246
|
+
mkdir -p "$agents_dir"
|
|
1247
|
+
|
|
1248
|
+
# Check if AGENTS.md exists and has our reference
|
|
1249
|
+
if [[ -f "$agents_file" ]]; then
|
|
1250
|
+
# Check first line for our reference
|
|
1251
|
+
local first_line
|
|
1252
|
+
first_line=$(head -1 "$agents_file" 2>/dev/null || echo "")
|
|
1253
|
+
if [[ "$first_line" != *"~/.aidevops/agents/AGENTS.md"* ]]; then
|
|
1254
|
+
# Prepend reference to existing file
|
|
1255
|
+
local temp_file
|
|
1256
|
+
temp_file=$(mktemp)
|
|
1257
|
+
echo "$reference_line" > "$temp_file"
|
|
1258
|
+
echo "" >> "$temp_file"
|
|
1259
|
+
cat "$agents_file" >> "$temp_file"
|
|
1260
|
+
mv "$temp_file" "$agents_file"
|
|
1261
|
+
print_success "Added reference to $agents_file"
|
|
1262
|
+
((updated_count++))
|
|
1263
|
+
else
|
|
1264
|
+
print_info "Reference already exists in $agents_file"
|
|
1265
|
+
fi
|
|
1266
|
+
else
|
|
1267
|
+
# Create new file with just the reference
|
|
1268
|
+
echo "$reference_line" > "$agents_file"
|
|
1269
|
+
print_success "Created $agents_file with aidevops reference"
|
|
1270
|
+
((updated_count++))
|
|
1271
|
+
fi
|
|
1272
|
+
fi
|
|
1273
|
+
done
|
|
1274
|
+
|
|
1275
|
+
if [[ $updated_count -eq 0 ]]; then
|
|
1276
|
+
print_info "No AI assistant configs found to update (tools may not be installed yet)"
|
|
1277
|
+
else
|
|
1278
|
+
print_success "Updated $updated_count AI assistant configuration(s)"
|
|
1279
|
+
fi
|
|
1280
|
+
|
|
1281
|
+
return 0
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
# Update OpenCode configuration
|
|
1285
|
+
update_opencode_config() {
|
|
1286
|
+
print_info "Updating OpenCode configuration..."
|
|
1287
|
+
|
|
1288
|
+
local opencode_config="$HOME/.config/opencode/opencode.json"
|
|
1289
|
+
|
|
1290
|
+
if [[ ! -f "$opencode_config" ]]; then
|
|
1291
|
+
print_info "OpenCode config not found at $opencode_config - skipping"
|
|
1292
|
+
return 0
|
|
1293
|
+
fi
|
|
1294
|
+
|
|
1295
|
+
# Create backup (with rotation)
|
|
1296
|
+
create_backup_with_rotation "$opencode_config" "opencode"
|
|
1297
|
+
|
|
1298
|
+
# Generate OpenCode agent configuration
|
|
1299
|
+
# - Primary agents: Added to opencode.json (for Tab order & MCP control)
|
|
1300
|
+
# - Subagents: Generated as markdown in ~/.config/opencode/agent/
|
|
1301
|
+
local generator_script=".agent/scripts/generate-opencode-agents.sh"
|
|
1302
|
+
if [[ -f "$generator_script" ]]; then
|
|
1303
|
+
print_info "Generating OpenCode agent configuration..."
|
|
1304
|
+
if bash "$generator_script"; then
|
|
1305
|
+
print_success "OpenCode agents configured (11 primary in JSON, subagents as markdown)"
|
|
1306
|
+
else
|
|
1307
|
+
print_warning "OpenCode agent generation encountered issues"
|
|
1308
|
+
fi
|
|
1309
|
+
else
|
|
1310
|
+
print_warning "OpenCode agent generator not found at $generator_script"
|
|
1311
|
+
fi
|
|
1312
|
+
|
|
1313
|
+
# Generate OpenCode commands
|
|
1314
|
+
# - Commands from workflows and agents -> /command-name
|
|
1315
|
+
local commands_script=".agent/scripts/generate-opencode-commands.sh"
|
|
1316
|
+
if [[ -f "$commands_script" ]]; then
|
|
1317
|
+
print_info "Generating OpenCode commands..."
|
|
1318
|
+
if bash "$commands_script"; then
|
|
1319
|
+
print_success "OpenCode commands configured"
|
|
1320
|
+
else
|
|
1321
|
+
print_warning "OpenCode command generation encountered issues"
|
|
1322
|
+
fi
|
|
1323
|
+
else
|
|
1324
|
+
print_warning "OpenCode command generator not found at $commands_script"
|
|
1325
|
+
fi
|
|
1326
|
+
|
|
1327
|
+
return 0
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
# Verify repository location
|
|
1331
|
+
verify_location() {
|
|
1332
|
+
local current_dir
|
|
1333
|
+
current_dir="$(pwd)"
|
|
1334
|
+
local expected_location="$HOME/Git/aidevops"
|
|
1335
|
+
|
|
1336
|
+
if [[ "$current_dir" != "$expected_location" ]]; then
|
|
1337
|
+
print_warning "Repository is not in the recommended location"
|
|
1338
|
+
print_info "Current location: $current_dir"
|
|
1339
|
+
print_info "Recommended location: $expected_location"
|
|
1340
|
+
echo ""
|
|
1341
|
+
echo "For optimal AI assistant integration, consider moving this repository to:"
|
|
1342
|
+
echo " mkdir -p ~/git"
|
|
1343
|
+
echo " mv '$current_dir' '$expected_location'"
|
|
1344
|
+
echo ""
|
|
1345
|
+
else
|
|
1346
|
+
print_success "Repository is in the recommended location: $expected_location"
|
|
1347
|
+
fi
|
|
1348
|
+
return 0
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
|
|
1352
|
+
|
|
1353
|
+
# Setup Python environment for DSPy
|
|
1354
|
+
setup_python_env() {
|
|
1355
|
+
print_info "Setting up Python environment for DSPy..."
|
|
1356
|
+
|
|
1357
|
+
# Check if Python 3 is available
|
|
1358
|
+
if ! command -v python3 &> /dev/null; then
|
|
1359
|
+
print_warning "Python 3 not found - DSPy setup skipped"
|
|
1360
|
+
print_info "Install Python 3.8+ to enable DSPy integration"
|
|
1361
|
+
return
|
|
1362
|
+
fi
|
|
1363
|
+
|
|
1364
|
+
local python_version=$(python3 --version | cut -d' ' -f2 | cut -d'.' -f1-2)
|
|
1365
|
+
local version_check=$(python3 -c "import sys; print(1 if sys.version_info >= (3, 8) else 0)")
|
|
1366
|
+
|
|
1367
|
+
if [[ "$version_check" != "1" ]]; then
|
|
1368
|
+
print_warning "Python 3.8+ required for DSPy, found $python_version - DSPy setup skipped"
|
|
1369
|
+
return
|
|
1370
|
+
fi
|
|
1371
|
+
|
|
1372
|
+
# Create Python virtual environment
|
|
1373
|
+
if [[ ! -d "python-env/dspy-env" ]]; then
|
|
1374
|
+
print_info "Creating Python virtual environment for DSPy..."
|
|
1375
|
+
mkdir -p python-env
|
|
1376
|
+
python3 -m venv python-env/dspy-env
|
|
1377
|
+
|
|
1378
|
+
if [[ $? -eq 0 ]]; then
|
|
1379
|
+
print_success "Python virtual environment created"
|
|
1380
|
+
else
|
|
1381
|
+
print_warning "Failed to create Python virtual environment - DSPy setup skipped"
|
|
1382
|
+
return
|
|
1383
|
+
fi
|
|
1384
|
+
else
|
|
1385
|
+
print_info "Python virtual environment already exists"
|
|
1386
|
+
fi
|
|
1387
|
+
|
|
1388
|
+
# Install DSPy dependencies
|
|
1389
|
+
print_info "Installing DSPy dependencies..."
|
|
1390
|
+
source python-env/dspy-env/bin/activate
|
|
1391
|
+
pip install --upgrade pip > /dev/null 2>&1
|
|
1392
|
+
pip install -r requirements.txt > /dev/null 2>&1
|
|
1393
|
+
|
|
1394
|
+
if [[ $? -eq 0 ]]; then
|
|
1395
|
+
print_success "DSPy dependencies installed successfully"
|
|
1396
|
+
else
|
|
1397
|
+
print_warning "Failed to install DSPy dependencies - check requirements.txt"
|
|
1398
|
+
fi
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
# Setup Node.js environment for DSPyGround
|
|
1402
|
+
setup_nodejs_env() {
|
|
1403
|
+
print_info "Setting up Node.js environment for DSPyGround..."
|
|
1404
|
+
|
|
1405
|
+
# Check if Node.js is available
|
|
1406
|
+
if ! command -v node &> /dev/null; then
|
|
1407
|
+
print_warning "Node.js not found - DSPyGround setup skipped"
|
|
1408
|
+
print_info "Install Node.js 18+ to enable DSPyGround integration"
|
|
1409
|
+
return
|
|
1410
|
+
fi
|
|
1411
|
+
|
|
1412
|
+
local node_version=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
|
|
1413
|
+
if [[ $node_version -lt 18 ]]; then
|
|
1414
|
+
print_warning "Node.js 18+ required for DSPyGround, found v$node_version - DSPyGround setup skipped"
|
|
1415
|
+
return
|
|
1416
|
+
fi
|
|
1417
|
+
|
|
1418
|
+
# Check if npm is available
|
|
1419
|
+
if ! command -v npm &> /dev/null; then
|
|
1420
|
+
print_warning "npm not found - DSPyGround setup skipped"
|
|
1421
|
+
return
|
|
1422
|
+
fi
|
|
1423
|
+
|
|
1424
|
+
# Install DSPyGround globally if not already installed
|
|
1425
|
+
if ! command -v dspyground &> /dev/null; then
|
|
1426
|
+
print_info "Installing DSPyGround globally..."
|
|
1427
|
+
npm install -g dspyground > /dev/null 2>&1
|
|
1428
|
+
|
|
1429
|
+
if [[ $? -eq 0 ]]; then
|
|
1430
|
+
print_success "DSPyGround installed successfully"
|
|
1431
|
+
else
|
|
1432
|
+
print_warning "Failed to install DSPyGround globally"
|
|
1433
|
+
fi
|
|
1434
|
+
else
|
|
1435
|
+
print_success "DSPyGround already installed"
|
|
1436
|
+
fi
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
# Setup LocalWP MCP server for AI database access
|
|
1440
|
+
setup_localwp_mcp() {
|
|
1441
|
+
print_info "Setting up LocalWP MCP server..."
|
|
1442
|
+
|
|
1443
|
+
# Check if LocalWP is installed
|
|
1444
|
+
local localwp_found=false
|
|
1445
|
+
if [[ -d "/Applications/Local.app" ]] || [[ -d "$HOME/Applications/Local.app" ]]; then
|
|
1446
|
+
localwp_found=true
|
|
1447
|
+
fi
|
|
1448
|
+
|
|
1449
|
+
if [[ "$localwp_found" != "true" ]]; then
|
|
1450
|
+
print_info "LocalWP not found - skipping MCP server setup"
|
|
1451
|
+
print_info "Install LocalWP from: https://localwp.com/"
|
|
1452
|
+
return 0
|
|
1453
|
+
fi
|
|
1454
|
+
|
|
1455
|
+
print_success "LocalWP found"
|
|
1456
|
+
|
|
1457
|
+
# Check if npm is available
|
|
1458
|
+
if ! command -v npm &> /dev/null; then
|
|
1459
|
+
print_warning "npm not found - cannot install LocalWP MCP server"
|
|
1460
|
+
print_info "Install Node.js and npm first"
|
|
1461
|
+
return 0
|
|
1462
|
+
fi
|
|
1463
|
+
|
|
1464
|
+
# Check if mcp-local-wp is already installed
|
|
1465
|
+
if command -v mcp-local-wp &> /dev/null; then
|
|
1466
|
+
print_success "LocalWP MCP server already installed"
|
|
1467
|
+
return 0
|
|
1468
|
+
fi
|
|
1469
|
+
|
|
1470
|
+
# Offer to install mcp-local-wp
|
|
1471
|
+
print_info "LocalWP MCP server enables AI assistants to query WordPress databases"
|
|
1472
|
+
read -r -p "Install LocalWP MCP server (@verygoodplugins/mcp-local-wp)? (y/n): " install_mcp
|
|
1473
|
+
|
|
1474
|
+
if [[ "$install_mcp" == "y" ]]; then
|
|
1475
|
+
print_info "Installing LocalWP MCP server..."
|
|
1476
|
+
if npm install -g @verygoodplugins/mcp-local-wp > /dev/null 2>&1; then
|
|
1477
|
+
print_success "LocalWP MCP server installed successfully"
|
|
1478
|
+
print_info "Start with: ~/.aidevops/agents/scripts/localhost-helper.sh start-mcp"
|
|
1479
|
+
print_info "Or configure in OpenCode MCP settings for auto-start"
|
|
1480
|
+
else
|
|
1481
|
+
print_warning "Failed to install LocalWP MCP server"
|
|
1482
|
+
print_info "Try manually: npm install -g @verygoodplugins/mcp-local-wp"
|
|
1483
|
+
fi
|
|
1484
|
+
else
|
|
1485
|
+
print_info "Skipped LocalWP MCP server installation"
|
|
1486
|
+
print_info "Install later: npm install -g @verygoodplugins/mcp-local-wp"
|
|
1487
|
+
fi
|
|
1488
|
+
|
|
1489
|
+
return 0
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
# Setup Augment Context Engine MCP
|
|
1493
|
+
setup_augment_context_engine() {
|
|
1494
|
+
print_info "Setting up Augment Context Engine MCP..."
|
|
1495
|
+
|
|
1496
|
+
# Check Node.js version (requires 22+)
|
|
1497
|
+
if ! command -v node &> /dev/null; then
|
|
1498
|
+
print_warning "Node.js not found - Augment Context Engine setup skipped"
|
|
1499
|
+
print_info "Install Node.js 22+ to enable Augment Context Engine"
|
|
1500
|
+
return
|
|
1501
|
+
fi
|
|
1502
|
+
|
|
1503
|
+
local node_version=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
|
|
1504
|
+
if [[ $node_version -lt 22 ]]; then
|
|
1505
|
+
print_warning "Node.js 22+ required for Augment Context Engine, found v$node_version"
|
|
1506
|
+
print_info "Install: brew install node@22 (macOS) or nvm install 22"
|
|
1507
|
+
return
|
|
1508
|
+
fi
|
|
1509
|
+
|
|
1510
|
+
# Check if auggie is installed
|
|
1511
|
+
if ! command -v auggie &> /dev/null; then
|
|
1512
|
+
print_warning "Auggie CLI not found"
|
|
1513
|
+
print_info "Install with: npm install -g @augmentcode/auggie@prerelease"
|
|
1514
|
+
print_info "Then run: auggie login"
|
|
1515
|
+
return
|
|
1516
|
+
fi
|
|
1517
|
+
|
|
1518
|
+
# Check if logged in
|
|
1519
|
+
if [[ ! -f "$HOME/.augment/session.json" ]]; then
|
|
1520
|
+
print_warning "Auggie not logged in"
|
|
1521
|
+
print_info "Run: auggie login"
|
|
1522
|
+
return
|
|
1523
|
+
fi
|
|
1524
|
+
|
|
1525
|
+
print_success "Auggie CLI found and authenticated"
|
|
1526
|
+
|
|
1527
|
+
# MCP configuration is handled by generate-opencode-agents.sh for OpenCode
|
|
1528
|
+
# Other tools (Cursor, Claude Code, etc.) discover skills via SKILL.md files
|
|
1529
|
+
|
|
1530
|
+
print_info "Augment Context Engine available for tools supporting Agent Skills"
|
|
1531
|
+
print_info "Supported tools: OpenCode, Cursor, Claude Code, VS Code, GitHub Copilot"
|
|
1532
|
+
print_info "Verification: 'What is this project? Please use codebase retrieval tool.'"
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
# Setup osgrep - Local Semantic Search
|
|
1536
|
+
setup_osgrep() {
|
|
1537
|
+
print_info "Setting up osgrep (local semantic search)..."
|
|
1538
|
+
|
|
1539
|
+
# Check Node.js version (requires 18+)
|
|
1540
|
+
if ! command -v node &> /dev/null; then
|
|
1541
|
+
print_warning "Node.js not found - osgrep setup skipped"
|
|
1542
|
+
print_info "Install Node.js 18+ to enable osgrep"
|
|
1543
|
+
return
|
|
1544
|
+
fi
|
|
1545
|
+
|
|
1546
|
+
local node_version
|
|
1547
|
+
node_version=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
|
|
1548
|
+
if [[ $node_version -lt 18 ]]; then
|
|
1549
|
+
print_warning "Node.js 18+ required for osgrep, found v$node_version"
|
|
1550
|
+
print_info "Install: brew install node@18 (macOS) or nvm install 18"
|
|
1551
|
+
return
|
|
1552
|
+
fi
|
|
1553
|
+
|
|
1554
|
+
# Check if osgrep is installed
|
|
1555
|
+
if ! command -v osgrep &> /dev/null; then
|
|
1556
|
+
print_warning "osgrep CLI not found"
|
|
1557
|
+
print_info "Install with: npm install -g osgrep"
|
|
1558
|
+
print_info "Then run: osgrep setup (downloads ~150MB embedding models)"
|
|
1559
|
+
return
|
|
1560
|
+
fi
|
|
1561
|
+
|
|
1562
|
+
# Check if models are downloaded
|
|
1563
|
+
if [[ ! -d "$HOME/.osgrep" ]]; then
|
|
1564
|
+
print_warning "osgrep models not yet downloaded"
|
|
1565
|
+
print_info "Run: osgrep setup"
|
|
1566
|
+
print_info "This downloads ~150MB of embedding models for local semantic search"
|
|
1567
|
+
else
|
|
1568
|
+
print_success "osgrep CLI found and configured"
|
|
1569
|
+
fi
|
|
1570
|
+
|
|
1571
|
+
# Note about Claude Code integration
|
|
1572
|
+
print_info "osgrep provides 100% local semantic search (no cloud, no auth)"
|
|
1573
|
+
print_info "For Claude Code: osgrep install-claude-code"
|
|
1574
|
+
print_info "Supported tools: OpenCode, Cursor, Gemini CLI, Claude Code, Zed"
|
|
1575
|
+
print_info "Verification: 'Search for authentication handling in this codebase'"
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
# Setup Beads - Task Graph Visualization
|
|
1579
|
+
setup_beads() {
|
|
1580
|
+
print_info "Setting up Beads (task graph visualization)..."
|
|
1581
|
+
|
|
1582
|
+
# Check if Beads CLI (bd) is already installed
|
|
1583
|
+
if command -v bd &> /dev/null; then
|
|
1584
|
+
local bd_version
|
|
1585
|
+
bd_version=$(bd --version 2>/dev/null | head -1 || echo "unknown")
|
|
1586
|
+
print_success "Beads CLI (bd) already installed: $bd_version"
|
|
1587
|
+
else
|
|
1588
|
+
# Try to install via Homebrew first (macOS/Linux with Homebrew)
|
|
1589
|
+
if command -v brew &> /dev/null; then
|
|
1590
|
+
print_info "Installing Beads via Homebrew..."
|
|
1591
|
+
if brew install steveyegge/beads/bd 2>/dev/null; then
|
|
1592
|
+
print_success "Beads CLI installed via Homebrew"
|
|
1593
|
+
else
|
|
1594
|
+
print_warning "Homebrew tap installation failed, trying alternative..."
|
|
1595
|
+
# Try Go install if Go is available
|
|
1596
|
+
if command -v go &> /dev/null; then
|
|
1597
|
+
print_info "Installing Beads via Go..."
|
|
1598
|
+
if go install github.com/steveyegge/beads/cmd/bd@latest 2>/dev/null; then
|
|
1599
|
+
print_success "Beads CLI installed via Go"
|
|
1600
|
+
print_info "Ensure \$GOPATH/bin is in your PATH"
|
|
1601
|
+
else
|
|
1602
|
+
print_warning "Go installation failed"
|
|
1603
|
+
fi
|
|
1604
|
+
fi
|
|
1605
|
+
fi
|
|
1606
|
+
elif command -v go &> /dev/null; then
|
|
1607
|
+
print_info "Installing Beads via Go..."
|
|
1608
|
+
if go install github.com/steveyegge/beads/cmd/bd@latest 2>/dev/null; then
|
|
1609
|
+
print_success "Beads CLI installed via Go"
|
|
1610
|
+
print_info "Ensure \$GOPATH/bin is in your PATH"
|
|
1611
|
+
else
|
|
1612
|
+
print_warning "Go installation failed"
|
|
1613
|
+
fi
|
|
1614
|
+
else
|
|
1615
|
+
# Provide manual installation instructions
|
|
1616
|
+
print_warning "Beads CLI (bd) not installed"
|
|
1617
|
+
echo ""
|
|
1618
|
+
echo " Install options:"
|
|
1619
|
+
echo " macOS/Linux (Homebrew): brew install steveyegge/beads/bd"
|
|
1620
|
+
echo " Go: go install github.com/steveyegge/beads/cmd/bd@latest"
|
|
1621
|
+
echo " Manual: https://github.com/steveyegge/beads/releases"
|
|
1622
|
+
echo ""
|
|
1623
|
+
fi
|
|
1624
|
+
fi
|
|
1625
|
+
|
|
1626
|
+
print_info "Beads provides task graph visualization for TODO.md and PLANS.md"
|
|
1627
|
+
print_info "After installation, run: aidevops init beads"
|
|
1628
|
+
|
|
1629
|
+
# Offer to install optional Beads UI tools
|
|
1630
|
+
setup_beads_ui
|
|
1631
|
+
|
|
1632
|
+
return 0
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
# Setup Beads UI Tools (optional visualization tools)
|
|
1636
|
+
setup_beads_ui() {
|
|
1637
|
+
echo ""
|
|
1638
|
+
print_info "Beads UI tools provide enhanced visualization:"
|
|
1639
|
+
echo " • beads_viewer (Python) - PageRank, critical path, graph analytics"
|
|
1640
|
+
echo " • beads-ui (Node.js) - Web dashboard with live updates"
|
|
1641
|
+
echo " • bdui (Node.js) - React/Ink terminal UI"
|
|
1642
|
+
echo " • perles (Rust) - BQL query language TUI"
|
|
1643
|
+
echo ""
|
|
1644
|
+
|
|
1645
|
+
read -r -p "Install optional Beads UI tools? (y/n): " install_beads_ui
|
|
1646
|
+
|
|
1647
|
+
if [[ "$install_beads_ui" != "y" ]]; then
|
|
1648
|
+
print_info "Skipped Beads UI tools (can install later from beads.md docs)"
|
|
1649
|
+
return 0
|
|
1650
|
+
fi
|
|
1651
|
+
|
|
1652
|
+
local installed_count=0
|
|
1653
|
+
|
|
1654
|
+
# beads_viewer (Python)
|
|
1655
|
+
if command -v pip3 &> /dev/null || command -v pip &> /dev/null; then
|
|
1656
|
+
read -r -p " Install beads_viewer (Python TUI with graph analytics)? (y/n): " install_viewer
|
|
1657
|
+
if [[ "$install_viewer" == "y" ]]; then
|
|
1658
|
+
print_info "Installing beads_viewer..."
|
|
1659
|
+
if pip3 install beads-viewer 2>/dev/null || pip install beads-viewer 2>/dev/null; then
|
|
1660
|
+
print_success "beads_viewer installed"
|
|
1661
|
+
((installed_count++))
|
|
1662
|
+
else
|
|
1663
|
+
print_warning "Failed to install beads_viewer"
|
|
1664
|
+
fi
|
|
1665
|
+
fi
|
|
1666
|
+
fi
|
|
1667
|
+
|
|
1668
|
+
# beads-ui (Node.js)
|
|
1669
|
+
if command -v npm &> /dev/null; then
|
|
1670
|
+
read -r -p " Install beads-ui (Web dashboard)? (y/n): " install_web
|
|
1671
|
+
if [[ "$install_web" == "y" ]]; then
|
|
1672
|
+
print_info "Installing beads-ui..."
|
|
1673
|
+
if npm install -g beads-ui 2>/dev/null; then
|
|
1674
|
+
print_success "beads-ui installed (run: beads-ui)"
|
|
1675
|
+
((installed_count++))
|
|
1676
|
+
else
|
|
1677
|
+
print_warning "Failed to install beads-ui"
|
|
1678
|
+
fi
|
|
1679
|
+
fi
|
|
1680
|
+
|
|
1681
|
+
read -r -p " Install bdui (React/Ink TUI)? (y/n): " install_bdui
|
|
1682
|
+
if [[ "$install_bdui" == "y" ]]; then
|
|
1683
|
+
print_info "Installing bdui..."
|
|
1684
|
+
if npm install -g bdui 2>/dev/null; then
|
|
1685
|
+
print_success "bdui installed (run: bdui)"
|
|
1686
|
+
((installed_count++))
|
|
1687
|
+
else
|
|
1688
|
+
print_warning "Failed to install bdui"
|
|
1689
|
+
fi
|
|
1690
|
+
fi
|
|
1691
|
+
fi
|
|
1692
|
+
|
|
1693
|
+
# perles (Rust)
|
|
1694
|
+
if command -v cargo &> /dev/null; then
|
|
1695
|
+
read -r -p " Install perles (BQL query language TUI)? (y/n): " install_perles
|
|
1696
|
+
if [[ "$install_perles" == "y" ]]; then
|
|
1697
|
+
print_info "Installing perles (this may take a few minutes)..."
|
|
1698
|
+
if cargo install perles 2>/dev/null; then
|
|
1699
|
+
print_success "perles installed (run: perles)"
|
|
1700
|
+
((installed_count++))
|
|
1701
|
+
else
|
|
1702
|
+
print_warning "Failed to install perles"
|
|
1703
|
+
fi
|
|
1704
|
+
fi
|
|
1705
|
+
fi
|
|
1706
|
+
|
|
1707
|
+
if [[ $installed_count -gt 0 ]]; then
|
|
1708
|
+
print_success "Installed $installed_count Beads UI tool(s)"
|
|
1709
|
+
else
|
|
1710
|
+
print_info "No Beads UI tools installed"
|
|
1711
|
+
fi
|
|
1712
|
+
|
|
1713
|
+
echo ""
|
|
1714
|
+
print_info "Beads UI documentation: ~/.aidevops/agents/tools/task-management/beads.md"
|
|
1715
|
+
|
|
1716
|
+
return 0
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
# Setup Browser Automation Tools (Bun, dev-browser, Playwriter)
|
|
1720
|
+
setup_browser_tools() {
|
|
1721
|
+
print_info "Setting up browser automation tools..."
|
|
1722
|
+
|
|
1723
|
+
local has_bun=false
|
|
1724
|
+
local has_node=false
|
|
1725
|
+
|
|
1726
|
+
# Check Bun
|
|
1727
|
+
if command -v bun &> /dev/null; then
|
|
1728
|
+
has_bun=true
|
|
1729
|
+
print_success "Bun $(bun --version) found"
|
|
1730
|
+
fi
|
|
1731
|
+
|
|
1732
|
+
# Check Node.js (for Playwriter)
|
|
1733
|
+
if command -v node &> /dev/null; then
|
|
1734
|
+
has_node=true
|
|
1735
|
+
fi
|
|
1736
|
+
|
|
1737
|
+
# Install Bun if not present (required for dev-browser)
|
|
1738
|
+
if [[ "$has_bun" == "false" ]]; then
|
|
1739
|
+
print_info "Installing Bun (required for dev-browser)..."
|
|
1740
|
+
if curl -fsSL https://bun.sh/install | bash 2>/dev/null; then
|
|
1741
|
+
# Source the updated PATH
|
|
1742
|
+
export BUN_INSTALL="$HOME/.bun"
|
|
1743
|
+
export PATH="$BUN_INSTALL/bin:$PATH"
|
|
1744
|
+
if command -v bun &> /dev/null; then
|
|
1745
|
+
has_bun=true
|
|
1746
|
+
print_success "Bun installed: $(bun --version)"
|
|
1747
|
+
fi
|
|
1748
|
+
else
|
|
1749
|
+
print_warning "Bun installation failed - dev-browser will need manual setup"
|
|
1750
|
+
fi
|
|
1751
|
+
fi
|
|
1752
|
+
|
|
1753
|
+
# Setup dev-browser if Bun is available
|
|
1754
|
+
if [[ "$has_bun" == "true" ]]; then
|
|
1755
|
+
local dev_browser_dir="$HOME/.aidevops/dev-browser"
|
|
1756
|
+
|
|
1757
|
+
if [[ -d "${dev_browser_dir}/skills/dev-browser" ]]; then
|
|
1758
|
+
print_success "dev-browser already installed"
|
|
1759
|
+
else
|
|
1760
|
+
print_info "Installing dev-browser (stateful browser automation)..."
|
|
1761
|
+
if bash "$AGENTS_DIR/scripts/dev-browser-helper.sh" setup 2>/dev/null; then
|
|
1762
|
+
print_success "dev-browser installed"
|
|
1763
|
+
print_info "Start server with: bash ~/.aidevops/agents/scripts/dev-browser-helper.sh start"
|
|
1764
|
+
else
|
|
1765
|
+
print_warning "dev-browser setup failed - run manually:"
|
|
1766
|
+
print_info " bash ~/.aidevops/agents/scripts/dev-browser-helper.sh setup"
|
|
1767
|
+
fi
|
|
1768
|
+
fi
|
|
1769
|
+
fi
|
|
1770
|
+
|
|
1771
|
+
# Playwriter MCP (Node.js based, runs via npx)
|
|
1772
|
+
if [[ "$has_node" == "true" ]]; then
|
|
1773
|
+
print_success "Playwriter MCP available (runs via npx playwriter@latest)"
|
|
1774
|
+
print_info "Install Chrome extension: https://chromewebstore.google.com/detail/playwriter-mcp/jfeammnjpkecdekppnclgkkffahnhfhe"
|
|
1775
|
+
else
|
|
1776
|
+
print_warning "Node.js not found - Playwriter MCP unavailable"
|
|
1777
|
+
fi
|
|
1778
|
+
|
|
1779
|
+
print_info "Browser tools: dev-browser (stateful), Playwriter (extension), Stagehand (AI)"
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
# Setup AI Orchestration Frameworks (Langflow, CrewAI, AutoGen)
|
|
1783
|
+
setup_ai_orchestration() {
|
|
1784
|
+
print_info "Setting up AI orchestration frameworks..."
|
|
1785
|
+
|
|
1786
|
+
local has_python=false
|
|
1787
|
+
|
|
1788
|
+
# Check Python
|
|
1789
|
+
if command -v python3 &> /dev/null; then
|
|
1790
|
+
local python_version
|
|
1791
|
+
python_version=$(python3 --version 2>&1 | cut -d' ' -f2)
|
|
1792
|
+
local major minor
|
|
1793
|
+
major=$(echo "$python_version" | cut -d. -f1)
|
|
1794
|
+
minor=$(echo "$python_version" | cut -d. -f2)
|
|
1795
|
+
|
|
1796
|
+
if [[ $major -ge 3 ]] && [[ $minor -ge 10 ]]; then
|
|
1797
|
+
has_python=true
|
|
1798
|
+
print_success "Python $python_version found (3.10+ required)"
|
|
1799
|
+
else
|
|
1800
|
+
print_warning "Python 3.10+ required for AI orchestration, found $python_version"
|
|
1801
|
+
fi
|
|
1802
|
+
else
|
|
1803
|
+
print_warning "Python 3 not found - AI orchestration frameworks unavailable"
|
|
1804
|
+
return 0
|
|
1805
|
+
fi
|
|
1806
|
+
|
|
1807
|
+
if [[ "$has_python" == "false" ]]; then
|
|
1808
|
+
return 0
|
|
1809
|
+
fi
|
|
1810
|
+
|
|
1811
|
+
# Create orchestration directory
|
|
1812
|
+
mkdir -p "$HOME/.aidevops/orchestration"
|
|
1813
|
+
|
|
1814
|
+
# Info about available frameworks
|
|
1815
|
+
print_info "AI Orchestration Frameworks available:"
|
|
1816
|
+
echo " - Langflow: Visual flow builder (localhost:7860)"
|
|
1817
|
+
echo " - CrewAI: Multi-agent teams (localhost:8501)"
|
|
1818
|
+
echo " - AutoGen: Microsoft agentic AI (localhost:8081)"
|
|
1819
|
+
echo ""
|
|
1820
|
+
print_info "Setup individual frameworks with:"
|
|
1821
|
+
echo " bash .agent/scripts/langflow-helper.sh setup"
|
|
1822
|
+
echo " bash .agent/scripts/crewai-helper.sh setup"
|
|
1823
|
+
echo " bash .agent/scripts/autogen-helper.sh setup"
|
|
1824
|
+
echo ""
|
|
1825
|
+
print_info "See .agent/tools/ai-orchestration/overview.md for comparison"
|
|
1826
|
+
|
|
1827
|
+
return 0
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
# Setup OpenCode Plugins (Antigravity OAuth)
|
|
1831
|
+
# Helper function to add/update a single plugin in OpenCode config
|
|
1832
|
+
add_opencode_plugin() {
|
|
1833
|
+
local plugin_name="$1"
|
|
1834
|
+
local plugin_spec="$2"
|
|
1835
|
+
local opencode_config="$3"
|
|
1836
|
+
|
|
1837
|
+
# Check if plugin array exists and if plugin is already configured
|
|
1838
|
+
local has_plugin_array
|
|
1839
|
+
has_plugin_array=$(jq -e '.plugin' "$opencode_config" 2>/dev/null && echo "true" || echo "false")
|
|
1840
|
+
|
|
1841
|
+
if [[ "$has_plugin_array" == "true" ]]; then
|
|
1842
|
+
# Check if plugin is already in the array
|
|
1843
|
+
local plugin_exists
|
|
1844
|
+
plugin_exists=$(jq -e --arg p "$plugin_name" '.plugin | map(select(startswith($p))) | length > 0' "$opencode_config" 2>/dev/null && echo "true" || echo "false")
|
|
1845
|
+
|
|
1846
|
+
if [[ "$plugin_exists" == "true" ]]; then
|
|
1847
|
+
# Update existing plugin to latest version
|
|
1848
|
+
local temp_file
|
|
1849
|
+
temp_file=$(mktemp)
|
|
1850
|
+
jq --arg old "$plugin_name" --arg new "$plugin_spec" \
|
|
1851
|
+
'.plugin = [.plugin[] | if startswith($old) then $new else . end]' \
|
|
1852
|
+
"$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
|
|
1853
|
+
print_success "Updated $plugin_name to latest version"
|
|
1854
|
+
else
|
|
1855
|
+
# Add plugin to existing array
|
|
1856
|
+
local temp_file
|
|
1857
|
+
temp_file=$(mktemp)
|
|
1858
|
+
jq --arg p "$plugin_spec" '.plugin += [$p]' "$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
|
|
1859
|
+
print_success "Added $plugin_name plugin to OpenCode config"
|
|
1860
|
+
fi
|
|
1861
|
+
else
|
|
1862
|
+
# Create plugin array with the plugin
|
|
1863
|
+
local temp_file
|
|
1864
|
+
temp_file=$(mktemp)
|
|
1865
|
+
jq --arg p "$plugin_spec" '. + {plugin: [$p]}' "$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
|
|
1866
|
+
print_success "Created plugin array with $plugin_name"
|
|
1867
|
+
fi
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
setup_opencode_plugins() {
|
|
1871
|
+
print_info "Setting up OpenCode plugins..."
|
|
1872
|
+
|
|
1873
|
+
local opencode_config="$HOME/.config/opencode/opencode.json"
|
|
1874
|
+
|
|
1875
|
+
# Check if OpenCode is installed
|
|
1876
|
+
if ! command -v opencode &> /dev/null; then
|
|
1877
|
+
print_warning "OpenCode not found - plugin setup skipped"
|
|
1878
|
+
print_info "Install OpenCode first: https://opencode.ai"
|
|
1879
|
+
return 0
|
|
1880
|
+
fi
|
|
1881
|
+
|
|
1882
|
+
# Check if config exists
|
|
1883
|
+
if [[ ! -f "$opencode_config" ]]; then
|
|
1884
|
+
print_warning "OpenCode config not found at $opencode_config - plugin setup skipped"
|
|
1885
|
+
return 0
|
|
1886
|
+
fi
|
|
1887
|
+
|
|
1888
|
+
# Check if jq is available
|
|
1889
|
+
if ! command -v jq &> /dev/null; then
|
|
1890
|
+
print_warning "jq not found - cannot update OpenCode config"
|
|
1891
|
+
return 0
|
|
1892
|
+
fi
|
|
1893
|
+
|
|
1894
|
+
# Setup Antigravity OAuth plugin (Google OAuth)
|
|
1895
|
+
print_info "Setting up Antigravity OAuth plugin..."
|
|
1896
|
+
add_opencode_plugin "opencode-antigravity-auth" "opencode-antigravity-auth@latest" "$opencode_config"
|
|
1897
|
+
|
|
1898
|
+
print_info "Antigravity OAuth plugin enables Google OAuth for OpenCode"
|
|
1899
|
+
print_info "Models available: gemini-3-pro-high, claude-opus-4-5-thinking, etc."
|
|
1900
|
+
print_info "See: https://github.com/NoeFabris/opencode-antigravity-auth"
|
|
1901
|
+
echo ""
|
|
1902
|
+
|
|
1903
|
+
# Setup Anthropic OAuth plugin (Claude OAuth)
|
|
1904
|
+
print_info "Setting up Anthropic OAuth plugin..."
|
|
1905
|
+
add_opencode_plugin "opencode-anthropic-auth" "opencode-anthropic-auth@latest" "$opencode_config"
|
|
1906
|
+
|
|
1907
|
+
print_info "Anthropic OAuth plugin enables Claude Pro/Max authentication"
|
|
1908
|
+
print_info "Zero cost for Claude subscribers, auto token refresh, beta features"
|
|
1909
|
+
print_info "See: https://github.com/anomalyco/opencode-anthropic-auth"
|
|
1910
|
+
echo ""
|
|
1911
|
+
|
|
1912
|
+
print_info "After setup, authenticate with: opencode auth login"
|
|
1913
|
+
print_info " • For Google OAuth: Select 'Google' → 'OAuth with Google (Antigravity)'"
|
|
1914
|
+
print_info " • For Claude OAuth: Select 'Anthropic' → 'Claude Pro/Max'"
|
|
1915
|
+
|
|
1916
|
+
return 0
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
# Setup Oh-My-OpenCode Plugin (coding productivity features)
|
|
1920
|
+
setup_oh_my_opencode() {
|
|
1921
|
+
print_info "Setting up Oh-My-OpenCode plugin..."
|
|
1922
|
+
|
|
1923
|
+
local opencode_config="$HOME/.config/opencode/opencode.json"
|
|
1924
|
+
|
|
1925
|
+
# Check if OpenCode is installed
|
|
1926
|
+
if ! command -v opencode &> /dev/null; then
|
|
1927
|
+
print_warning "OpenCode not found - Oh-My-OpenCode setup skipped"
|
|
1928
|
+
return 0
|
|
1929
|
+
fi
|
|
1930
|
+
|
|
1931
|
+
# Check if config exists
|
|
1932
|
+
if [[ ! -f "$opencode_config" ]]; then
|
|
1933
|
+
print_warning "OpenCode config not found - Oh-My-OpenCode setup skipped"
|
|
1934
|
+
return 0
|
|
1935
|
+
fi
|
|
1936
|
+
|
|
1937
|
+
# Check if jq is available
|
|
1938
|
+
if ! command -v jq &> /dev/null; then
|
|
1939
|
+
print_warning "jq not found - cannot update OpenCode config"
|
|
1940
|
+
return 0
|
|
1941
|
+
fi
|
|
1942
|
+
|
|
1943
|
+
echo ""
|
|
1944
|
+
print_info "Oh-My-OpenCode adds coding productivity features:"
|
|
1945
|
+
echo " • Async background agents (parallel task execution)"
|
|
1946
|
+
echo " • LSP tools (11 tools: hover, goto, references, rename, etc.)"
|
|
1947
|
+
echo " • AST-Grep (semantic code search/replace)"
|
|
1948
|
+
echo " • Curated agents (OmO, Oracle, Librarian, Explore, Frontend)"
|
|
1949
|
+
echo " • Claude Code compatibility (hooks, commands, skills)"
|
|
1950
|
+
echo " • Context window monitoring and session recovery"
|
|
1951
|
+
echo ""
|
|
1952
|
+
echo " Note: aidevops provides DevOps infrastructure (hosting, DNS, WordPress, SEO)"
|
|
1953
|
+
echo " Oh-My-OpenCode provides coding productivity (LSP, AST, background agents)"
|
|
1954
|
+
echo " They are complementary and work well together."
|
|
1955
|
+
echo ""
|
|
1956
|
+
|
|
1957
|
+
read -r -p "Install Oh-My-OpenCode plugin? (y/n): " install_omo
|
|
1958
|
+
|
|
1959
|
+
if [[ "$install_omo" != "y" ]]; then
|
|
1960
|
+
print_info "Skipped Oh-My-OpenCode installation"
|
|
1961
|
+
return 0
|
|
1962
|
+
fi
|
|
1963
|
+
|
|
1964
|
+
local plugin_name="oh-my-opencode"
|
|
1965
|
+
|
|
1966
|
+
# Check if plugin array exists
|
|
1967
|
+
local has_plugin_array
|
|
1968
|
+
has_plugin_array=$(jq -e '.plugin' "$opencode_config" 2>/dev/null && echo "true" || echo "false")
|
|
1969
|
+
|
|
1970
|
+
if [[ "$has_plugin_array" == "true" ]]; then
|
|
1971
|
+
# Check if plugin is already in the array
|
|
1972
|
+
local plugin_exists
|
|
1973
|
+
plugin_exists=$(jq -e --arg p "$plugin_name" '.plugin | map(select(. == $p or startswith($p + "@"))) | length > 0' "$opencode_config" 2>/dev/null && echo "true" || echo "false")
|
|
1974
|
+
|
|
1975
|
+
if [[ "$plugin_exists" == "true" ]]; then
|
|
1976
|
+
print_info "Oh-My-OpenCode already configured"
|
|
1977
|
+
else
|
|
1978
|
+
# Add plugin to existing array
|
|
1979
|
+
local temp_file
|
|
1980
|
+
temp_file=$(mktemp)
|
|
1981
|
+
jq --arg p "$plugin_name" '.plugin += [$p]' "$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
|
|
1982
|
+
print_success "Added Oh-My-OpenCode plugin to OpenCode config"
|
|
1983
|
+
fi
|
|
1984
|
+
else
|
|
1985
|
+
# Create plugin array with the plugin
|
|
1986
|
+
local temp_file
|
|
1987
|
+
temp_file=$(mktemp)
|
|
1988
|
+
jq --arg p "$plugin_name" '. + {plugin: [$p]}' "$opencode_config" > "$temp_file" && mv "$temp_file" "$opencode_config"
|
|
1989
|
+
print_success "Created plugin array with Oh-My-OpenCode"
|
|
1990
|
+
fi
|
|
1991
|
+
|
|
1992
|
+
# Create oh-my-opencode config if it doesn't exist
|
|
1993
|
+
local omo_config="$HOME/.config/opencode/oh-my-opencode.json"
|
|
1994
|
+
if [[ ! -f "$omo_config" ]]; then
|
|
1995
|
+
print_info "Creating Oh-My-OpenCode configuration..."
|
|
1996
|
+
cat > "$omo_config" << 'EOF'
|
|
1997
|
+
{
|
|
1998
|
+
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json",
|
|
1999
|
+
"google_auth": false,
|
|
2000
|
+
"disabled_mcps": ["context7"],
|
|
2001
|
+
"agents": {}
|
|
2002
|
+
}
|
|
2003
|
+
EOF
|
|
2004
|
+
print_success "Created $omo_config"
|
|
2005
|
+
print_info "Note: context7 MCP disabled in OmO (aidevops configures it separately)"
|
|
2006
|
+
fi
|
|
2007
|
+
|
|
2008
|
+
print_success "Oh-My-OpenCode plugin configured"
|
|
2009
|
+
echo ""
|
|
2010
|
+
print_info "Oh-My-OpenCode features now available:"
|
|
2011
|
+
echo " • Type 'ultrawork' or 'ulw' for maximum performance mode"
|
|
2012
|
+
echo " • Background agents run in parallel"
|
|
2013
|
+
echo " • LSP tools: lsp_hover, lsp_goto_definition, lsp_rename, etc."
|
|
2014
|
+
echo " • AST-Grep: ast_grep_search, ast_grep_replace"
|
|
2015
|
+
echo ""
|
|
2016
|
+
print_info "Curated agents (use @agent-name):"
|
|
2017
|
+
echo " • @oracle - Architecture, code review (GPT 5.2)"
|
|
2018
|
+
echo " • @librarian - Docs lookup, GitHub examples (Sonnet 4.5)"
|
|
2019
|
+
echo " • @explore - Fast codebase exploration (Grok)"
|
|
2020
|
+
echo " • @frontend-ui-ux-engineer - UI development (Gemini 3 Pro)"
|
|
2021
|
+
echo ""
|
|
2022
|
+
print_info "Documentation: https://github.com/code-yeongyu/oh-my-opencode"
|
|
2023
|
+
|
|
2024
|
+
return 0
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
setup_seo_mcps() {
|
|
2028
|
+
print_info "Setting up SEO MCP servers..."
|
|
2029
|
+
|
|
2030
|
+
local has_node=false
|
|
2031
|
+
local has_python=false
|
|
2032
|
+
local has_uv=false
|
|
2033
|
+
|
|
2034
|
+
# Check Node.js
|
|
2035
|
+
if command -v node &> /dev/null; then
|
|
2036
|
+
has_node=true
|
|
2037
|
+
fi
|
|
2038
|
+
|
|
2039
|
+
# Check Python
|
|
2040
|
+
if command -v python3 &> /dev/null; then
|
|
2041
|
+
has_python=true
|
|
2042
|
+
fi
|
|
2043
|
+
|
|
2044
|
+
# Check uv (Python package manager)
|
|
2045
|
+
if command -v uv &> /dev/null; then
|
|
2046
|
+
has_uv=true
|
|
2047
|
+
elif command -v uvx &> /dev/null; then
|
|
2048
|
+
has_uv=true
|
|
2049
|
+
fi
|
|
2050
|
+
|
|
2051
|
+
# DataForSEO MCP (Node.js based)
|
|
2052
|
+
if [[ "$has_node" == "true" ]]; then
|
|
2053
|
+
print_info "DataForSEO MCP available via: npx dataforseo-mcp-server"
|
|
2054
|
+
print_info "Configure credentials in ~/.config/aidevops/mcp-env.sh:"
|
|
2055
|
+
print_info " DATAFORSEO_USERNAME and DATAFORSEO_PASSWORD"
|
|
2056
|
+
else
|
|
2057
|
+
print_warning "Node.js not found - DataForSEO MCP requires Node.js"
|
|
2058
|
+
fi
|
|
2059
|
+
|
|
2060
|
+
# Serper MCP (Python based, uses uv/uvx)
|
|
2061
|
+
if [[ "$has_uv" == "true" ]]; then
|
|
2062
|
+
print_info "Serper MCP available via: uvx serper-mcp-server"
|
|
2063
|
+
print_info "Configure credentials in ~/.config/aidevops/mcp-env.sh:"
|
|
2064
|
+
print_info " SERPER_API_KEY"
|
|
2065
|
+
elif [[ "$has_python" == "true" ]]; then
|
|
2066
|
+
print_info "Serper MCP available via: pip install serper-mcp-server"
|
|
2067
|
+
print_info "Then run: python3 -m serper_mcp_server"
|
|
2068
|
+
print_info "Configure credentials in ~/.config/aidevops/mcp-env.sh:"
|
|
2069
|
+
print_info " SERPER_API_KEY"
|
|
2070
|
+
|
|
2071
|
+
# Offer to install uv for better experience
|
|
2072
|
+
read -r -p "Install uv (recommended Python package manager)? (y/n): " install_uv
|
|
2073
|
+
if [[ "$install_uv" == "y" ]]; then
|
|
2074
|
+
print_info "Installing uv..."
|
|
2075
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
2076
|
+
if [[ $? -eq 0 ]]; then
|
|
2077
|
+
print_success "uv installed successfully"
|
|
2078
|
+
print_info "Restart your terminal or run: source ~/.bashrc (or ~/.zshrc)"
|
|
2079
|
+
else
|
|
2080
|
+
print_warning "Failed to install uv"
|
|
2081
|
+
fi
|
|
2082
|
+
fi
|
|
2083
|
+
else
|
|
2084
|
+
print_warning "Python not found - Serper MCP requires Python 3.11+"
|
|
2085
|
+
fi
|
|
2086
|
+
|
|
2087
|
+
# Check if credentials are configured
|
|
2088
|
+
if [[ -f "$HOME/.config/aidevops/mcp-env.sh" ]]; then
|
|
2089
|
+
# shellcheck source=/dev/null
|
|
2090
|
+
source "$HOME/.config/aidevops/mcp-env.sh"
|
|
2091
|
+
|
|
2092
|
+
if [[ -n "$DATAFORSEO_USERNAME" && -n "$DATAFORSEO_PASSWORD" ]]; then
|
|
2093
|
+
print_success "DataForSEO credentials configured"
|
|
2094
|
+
else
|
|
2095
|
+
print_info "DataForSEO: Set credentials with:"
|
|
2096
|
+
print_info " bash ~/.aidevops/agents/scripts/setup-local-api-keys.sh set DATAFORSEO_USERNAME your_username"
|
|
2097
|
+
print_info " bash ~/.aidevops/agents/scripts/setup-local-api-keys.sh set DATAFORSEO_PASSWORD your_password"
|
|
2098
|
+
fi
|
|
2099
|
+
|
|
2100
|
+
if [[ -n "$SERPER_API_KEY" ]]; then
|
|
2101
|
+
print_success "Serper API key configured"
|
|
2102
|
+
else
|
|
2103
|
+
print_info "Serper: Set API key with:"
|
|
2104
|
+
print_info " bash ~/.aidevops/agents/scripts/setup-local-api-keys.sh set SERPER_API_KEY your_key"
|
|
2105
|
+
fi
|
|
2106
|
+
else
|
|
2107
|
+
print_info "Configure SEO API credentials:"
|
|
2108
|
+
print_info " bash ~/.aidevops/agents/scripts/setup-local-api-keys.sh setup"
|
|
2109
|
+
fi
|
|
2110
|
+
|
|
2111
|
+
print_info "SEO MCP documentation: ~/.aidevops/agents/seo/"
|
|
2112
|
+
return 0
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
# Check for tool updates after setup
|
|
2116
|
+
check_tool_updates() {
|
|
2117
|
+
print_info "Checking for tool updates..."
|
|
2118
|
+
|
|
2119
|
+
local tool_check_script="$HOME/.aidevops/agents/scripts/tool-version-check.sh"
|
|
2120
|
+
|
|
2121
|
+
if [[ ! -f "$tool_check_script" ]]; then
|
|
2122
|
+
# Try local script if deployed version not available yet
|
|
2123
|
+
tool_check_script=".agent/scripts/tool-version-check.sh"
|
|
2124
|
+
fi
|
|
2125
|
+
|
|
2126
|
+
if [[ ! -f "$tool_check_script" ]]; then
|
|
2127
|
+
print_warning "Tool version check script not found - skipping update check"
|
|
2128
|
+
return 0
|
|
2129
|
+
fi
|
|
2130
|
+
|
|
2131
|
+
# Run the check in quiet mode first to see if there are updates
|
|
2132
|
+
# Capture both output and exit code
|
|
2133
|
+
local outdated_output
|
|
2134
|
+
local check_exit_code
|
|
2135
|
+
outdated_output=$(bash "$tool_check_script" --quiet 2>&1) || check_exit_code=$?
|
|
2136
|
+
check_exit_code=${check_exit_code:-0}
|
|
2137
|
+
|
|
2138
|
+
# If the script failed, warn and continue
|
|
2139
|
+
if [[ $check_exit_code -ne 0 ]]; then
|
|
2140
|
+
print_warning "Tool version check encountered an error (exit code: $check_exit_code)"
|
|
2141
|
+
print_info "Run 'aidevops update-tools' manually to check for updates"
|
|
2142
|
+
return 0
|
|
2143
|
+
fi
|
|
2144
|
+
|
|
2145
|
+
if [[ -z "$outdated_output" ]]; then
|
|
2146
|
+
print_success "All tools are up to date!"
|
|
2147
|
+
return 0
|
|
2148
|
+
fi
|
|
2149
|
+
|
|
2150
|
+
# Show what's outdated
|
|
2151
|
+
echo ""
|
|
2152
|
+
print_warning "Some tools have updates available:"
|
|
2153
|
+
echo ""
|
|
2154
|
+
bash "$tool_check_script" --quiet
|
|
2155
|
+
echo ""
|
|
2156
|
+
|
|
2157
|
+
read -r -p "Update all outdated tools now? (y/n): " do_update
|
|
2158
|
+
|
|
2159
|
+
if [[ "$do_update" == "y" || "$do_update" == "Y" ]]; then
|
|
2160
|
+
print_info "Updating tools..."
|
|
2161
|
+
bash "$tool_check_script" --update
|
|
2162
|
+
print_success "Tool updates complete!"
|
|
2163
|
+
else
|
|
2164
|
+
print_info "Skipped tool updates"
|
|
2165
|
+
print_info "Run 'aidevops update-tools' anytime to update tools"
|
|
2166
|
+
fi
|
|
2167
|
+
|
|
2168
|
+
return 0
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
# Parse command line arguments
|
|
2172
|
+
parse_args() {
|
|
2173
|
+
while [[ $# -gt 0 ]]; do
|
|
2174
|
+
case "$1" in
|
|
2175
|
+
--clean)
|
|
2176
|
+
CLEAN_MODE=true
|
|
2177
|
+
shift
|
|
2178
|
+
;;
|
|
2179
|
+
--interactive|-i)
|
|
2180
|
+
INTERACTIVE_MODE=true
|
|
2181
|
+
shift
|
|
2182
|
+
;;
|
|
2183
|
+
--update|-u)
|
|
2184
|
+
UPDATE_TOOLS_MODE=true
|
|
2185
|
+
shift
|
|
2186
|
+
;;
|
|
2187
|
+
--help|-h)
|
|
2188
|
+
echo "Usage: ./setup.sh [OPTIONS]"
|
|
2189
|
+
echo ""
|
|
2190
|
+
echo "Options:"
|
|
2191
|
+
echo " --clean Remove stale files before deploying (cleans ~/.aidevops/agents/)"
|
|
2192
|
+
echo " --interactive Ask confirmation before each step"
|
|
2193
|
+
echo " -i Short for --interactive"
|
|
2194
|
+
echo " --update Check for and offer to update outdated tools after setup"
|
|
2195
|
+
echo " -u Short for --update"
|
|
2196
|
+
echo " --help Show this help message"
|
|
2197
|
+
echo ""
|
|
2198
|
+
echo "Default behavior adds/overwrites files without removing deleted agents."
|
|
2199
|
+
echo "Use --clean after removing or renaming agents to sync deletions."
|
|
2200
|
+
echo "Use --interactive to control each step individually."
|
|
2201
|
+
echo "Use --update to check for tool updates after setup completes."
|
|
2202
|
+
exit 0
|
|
2203
|
+
;;
|
|
2204
|
+
*)
|
|
2205
|
+
print_error "Unknown option: $1"
|
|
2206
|
+
echo "Use --help for usage information"
|
|
2207
|
+
exit 1
|
|
2208
|
+
;;
|
|
2209
|
+
esac
|
|
2210
|
+
done
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
# Main setup function
|
|
2214
|
+
main() {
|
|
2215
|
+
# Bootstrap first (handles curl install)
|
|
2216
|
+
bootstrap_repo "$@"
|
|
2217
|
+
|
|
2218
|
+
parse_args "$@"
|
|
2219
|
+
|
|
2220
|
+
echo "🤖 AI DevOps Framework Setup"
|
|
2221
|
+
echo "============================="
|
|
2222
|
+
if [[ "$CLEAN_MODE" == "true" ]]; then
|
|
2223
|
+
echo "Mode: Clean (removing stale files)"
|
|
2224
|
+
fi
|
|
2225
|
+
if [[ "$INTERACTIVE_MODE" == "true" ]]; then
|
|
2226
|
+
echo "Mode: Interactive (confirm each step)"
|
|
2227
|
+
echo ""
|
|
2228
|
+
echo "Controls: [Y]es (default) / [n]o skip / [q]uit"
|
|
2229
|
+
fi
|
|
2230
|
+
if [[ "$UPDATE_TOOLS_MODE" == "true" ]]; then
|
|
2231
|
+
echo "Mode: Update (will check for tool updates after setup)"
|
|
2232
|
+
fi
|
|
2233
|
+
echo ""
|
|
2234
|
+
|
|
2235
|
+
# Required steps (always run)
|
|
2236
|
+
verify_location
|
|
2237
|
+
check_requirements
|
|
2238
|
+
|
|
2239
|
+
# Optional steps with confirmation in interactive mode
|
|
2240
|
+
confirm_step "Check optional dependencies (bun, node, python)" && check_optional_deps
|
|
2241
|
+
confirm_step "Setup recommended tools (Tabby, Zed, etc.)" && setup_recommended_tools
|
|
2242
|
+
confirm_step "Setup Git CLIs (gh, glab, tea)" && setup_git_clis
|
|
2243
|
+
confirm_step "Setup SSH key" && setup_ssh_key
|
|
2244
|
+
confirm_step "Setup configuration files" && setup_configs
|
|
2245
|
+
confirm_step "Set secure permissions on config files" && set_permissions
|
|
2246
|
+
confirm_step "Install aidevops CLI command" && install_aidevops_cli
|
|
2247
|
+
confirm_step "Setup shell aliases" && setup_aliases
|
|
2248
|
+
confirm_step "Setup terminal title integration" && setup_terminal_title
|
|
2249
|
+
confirm_step "Deploy AI templates to home directories" && deploy_ai_templates
|
|
2250
|
+
confirm_step "Migrate old backups to new structure" && migrate_old_backups
|
|
2251
|
+
confirm_step "Migrate loop state from .claude/ to .agent/loop-state/" && migrate_loop_state_directories
|
|
2252
|
+
confirm_step "Cleanup deprecated agent paths" && cleanup_deprecated_paths
|
|
2253
|
+
confirm_step "Extract OpenCode prompts" && extract_opencode_prompts
|
|
2254
|
+
confirm_step "Deploy aidevops agents to ~/.aidevops/agents/" && deploy_aidevops_agents
|
|
2255
|
+
confirm_step "Generate agent skills (SKILL.md files)" && generate_agent_skills
|
|
2256
|
+
confirm_step "Inject agents reference into AI configs" && inject_agents_reference
|
|
2257
|
+
confirm_step "Update OpenCode configuration" && update_opencode_config
|
|
2258
|
+
confirm_step "Setup Python environment (DSPy, crawl4ai)" && setup_python_env
|
|
2259
|
+
confirm_step "Setup Node.js environment" && setup_nodejs_env
|
|
2260
|
+
confirm_step "Setup LocalWP MCP server" && setup_localwp_mcp
|
|
2261
|
+
confirm_step "Setup Augment Context Engine MCP" && setup_augment_context_engine
|
|
2262
|
+
confirm_step "Setup osgrep (local semantic search)" && setup_osgrep
|
|
2263
|
+
confirm_step "Setup Beads task management" && setup_beads
|
|
2264
|
+
confirm_step "Setup SEO MCP servers (DataForSEO, Serper)" && setup_seo_mcps
|
|
2265
|
+
confirm_step "Setup browser automation tools" && setup_browser_tools
|
|
2266
|
+
confirm_step "Setup AI orchestration frameworks info" && setup_ai_orchestration
|
|
2267
|
+
confirm_step "Setup OpenCode plugins" && setup_opencode_plugins
|
|
2268
|
+
confirm_step "Setup Oh-My-OpenCode" && setup_oh_my_opencode
|
|
2269
|
+
|
|
2270
|
+
echo ""
|
|
2271
|
+
print_success "🎉 Setup complete!"
|
|
2272
|
+
echo ""
|
|
2273
|
+
echo "CLI Command:"
|
|
2274
|
+
echo " aidevops init - Initialize aidevops in a project"
|
|
2275
|
+
echo " aidevops features - List available features"
|
|
2276
|
+
echo " aidevops status - Check installation status"
|
|
2277
|
+
echo " aidevops update - Update to latest version"
|
|
2278
|
+
echo " aidevops update-tools - Check for and update installed tools"
|
|
2279
|
+
echo " aidevops uninstall - Remove aidevops"
|
|
2280
|
+
echo ""
|
|
2281
|
+
echo "Deployed to:"
|
|
2282
|
+
echo " ~/.aidevops/agents/ - Agent files (main agents, subagents, scripts)"
|
|
2283
|
+
echo " ~/.aidevops/*-backups/ - Backups with rotation (keeps last $BACKUP_KEEP_COUNT)"
|
|
2284
|
+
echo ""
|
|
2285
|
+
echo "Next steps:"
|
|
2286
|
+
echo "1. Edit configuration files in configs/ with your actual credentials"
|
|
2287
|
+
echo "2. Setup Git CLI tools and authentication (shown during setup)"
|
|
2288
|
+
echo "3. Setup API keys: bash .agent/scripts/setup-local-api-keys.sh setup"
|
|
2289
|
+
echo "4. Test access: ./.agent/scripts/servers-helper.sh list"
|
|
2290
|
+
echo "5. Read documentation: ~/.aidevops/agents/AGENTS.md"
|
|
2291
|
+
echo ""
|
|
2292
|
+
echo "For development on aidevops framework itself:"
|
|
2293
|
+
echo " See ~/Git/aidevops/AGENTS.md"
|
|
2294
|
+
echo ""
|
|
2295
|
+
echo "OpenCode Primary Agents (12 total, Tab to switch):"
|
|
2296
|
+
echo "• Plan+ - Enhanced planning with context tools (read-only)"
|
|
2297
|
+
echo "• Build+ - Enhanced build with context tools (full access)"
|
|
2298
|
+
echo "• Accounts, AI-DevOps, Content, Health, Legal, Marketing,"
|
|
2299
|
+
echo " Research, Sales, SEO, WordPress"
|
|
2300
|
+
echo ""
|
|
2301
|
+
echo "Agent Skills (SKILL.md) - Cross-tool compatibility:"
|
|
2302
|
+
echo "• Cursor, Claude Code, VS Code, GitHub Copilot auto-discover skills"
|
|
2303
|
+
echo "• 21 SKILL.md files generated in ~/.aidevops/agents/"
|
|
2304
|
+
echo "• Skills include: wordpress, seo, aidevops, build-mcp, and more"
|
|
2305
|
+
echo ""
|
|
2306
|
+
echo "MCP Integrations (OpenCode):"
|
|
2307
|
+
echo "• Augment Context Engine - Cloud semantic codebase retrieval"
|
|
2308
|
+
echo "• Context7 - Real-time library documentation"
|
|
2309
|
+
echo "• osgrep - Local semantic search (100% private)"
|
|
2310
|
+
echo "• DataForSEO - Comprehensive SEO data APIs"
|
|
2311
|
+
echo "• Serper - Google Search API"
|
|
2312
|
+
echo ""
|
|
2313
|
+
echo "DSPy & DSPyGround Integration:"
|
|
2314
|
+
echo "• ./.agent/scripts/dspy-helper.sh - DSPy prompt optimization toolkit"
|
|
2315
|
+
echo "• ./.agent/scripts/dspyground-helper.sh - DSPyGround playground interface"
|
|
2316
|
+
echo "• python-env/dspy-env/ - Python virtual environment for DSPy"
|
|
2317
|
+
echo "• data/dspy/ - DSPy projects and datasets"
|
|
2318
|
+
echo "• data/dspyground/ - DSPyGround projects and configurations"
|
|
2319
|
+
echo ""
|
|
2320
|
+
echo "Task Management:"
|
|
2321
|
+
echo "• Beads CLI (bd) - Task graph visualization"
|
|
2322
|
+
echo "• beads-sync-helper.sh - Sync TODO.md/PLANS.md with Beads"
|
|
2323
|
+
echo "• todo-ready.sh - Show tasks with no open blockers"
|
|
2324
|
+
echo "• Run: aidevops init beads - Initialize Beads in a project"
|
|
2325
|
+
echo ""
|
|
2326
|
+
echo "Security reminders:"
|
|
2327
|
+
echo "- Never commit configuration files with real credentials"
|
|
2328
|
+
echo "- Use strong passwords and enable MFA on all accounts"
|
|
2329
|
+
echo "- Regularly rotate API tokens and SSH keys"
|
|
2330
|
+
echo ""
|
|
2331
|
+
echo "Happy server managing! 🚀"
|
|
2332
|
+
echo ""
|
|
2333
|
+
|
|
2334
|
+
# Check for tool updates if --update flag was passed
|
|
2335
|
+
if [[ "$UPDATE_TOOLS_MODE" == "true" ]]; then
|
|
2336
|
+
echo ""
|
|
2337
|
+
check_tool_updates
|
|
2338
|
+
fi
|
|
2339
|
+
|
|
2340
|
+
# Offer to launch onboarding for new users (only if not running inside OpenCode)
|
|
2341
|
+
if [[ -z "${OPENCODE_SESSION:-}" ]] && command -v opencode &>/dev/null; then
|
|
2342
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
2343
|
+
echo ""
|
|
2344
|
+
echo "🎯 Ready to configure your services?"
|
|
2345
|
+
echo ""
|
|
2346
|
+
echo "Launch OpenCode with the onboarding wizard to:"
|
|
2347
|
+
echo " • See which services are already configured"
|
|
2348
|
+
echo " • Get personalized recommendations based on your work"
|
|
2349
|
+
echo " • Set up API keys and credentials interactively"
|
|
2350
|
+
echo ""
|
|
2351
|
+
read -r -p "Launch OpenCode with /onboarding now? (y/n): " launch_onboarding
|
|
2352
|
+
if [[ "$launch_onboarding" == "y" || "$launch_onboarding" == "Y" ]]; then
|
|
2353
|
+
echo ""
|
|
2354
|
+
echo "Starting OpenCode..."
|
|
2355
|
+
opencode --prompt "/onboarding"
|
|
2356
|
+
else
|
|
2357
|
+
echo ""
|
|
2358
|
+
echo "You can run /onboarding anytime in OpenCode to configure services."
|
|
2359
|
+
fi
|
|
2360
|
+
fi
|
|
2361
|
+
|
|
2362
|
+
return 0
|
|
2363
|
+
}
|
|
2364
|
+
|
|
2365
|
+
# Run setup
|
|
2366
|
+
main "$@"
|