update-agent-context.sh 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. #!/usr/bin/env bash
  2. # Update agent context files with information from plan.md
  3. #
  4. # This script maintains AI agent context files by parsing feature specifications
  5. # and updating agent-specific configuration files with project information.
  6. #
  7. # MAIN FUNCTIONS:
  8. # 1. Environment Validation
  9. # - Verifies git repository structure and branch information
  10. # - Checks for required plan.md files and templates
  11. # - Validates file permissions and accessibility
  12. #
  13. # 2. Plan Data Extraction
  14. # - Parses plan.md files to extract project metadata
  15. # - Identifies language/version, frameworks, databases, and project types
  16. # - Handles missing or incomplete specification data gracefully
  17. #
  18. # 3. Agent File Management
  19. # - Creates new agent context files from templates when needed
  20. # - Updates existing agent files with new project information
  21. # - Preserves manual additions and custom configurations
  22. # - Supports multiple AI agent formats and directory structures
  23. #
  24. # 4. Content Generation
  25. # - Generates language-specific build/test commands
  26. # - Creates appropriate project directory structures
  27. # - Updates technology stacks and recent changes sections
  28. # - Maintains consistent formatting and timestamps
  29. #
  30. # 5. Multi-Agent Support
  31. # - Handles agent-specific file paths and naming conventions
  32. # - Supports: Claude, Gemini, Copilot, Cursor, Qwen, opencode, Codex, Windsurf
  33. # - Can update single agents or all existing agent files
  34. # - Creates default Claude file if no agent files exist
  35. #
  36. # Usage: ./update-agent-context.sh [agent_type]
  37. # Agent types: claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf
  38. # Leave empty to update all existing agent files
  39. set -e
  40. # Enable strict error handling
  41. set -u
  42. set -o pipefail
  43. #==============================================================================
  44. # Configuration and Global Variables
  45. #==============================================================================
  46. # Get script directory and load common functions
  47. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  48. source "$SCRIPT_DIR/common.sh"
  49. # Get all paths and variables from common functions
  50. eval $(get_feature_paths)
  51. NEW_PLAN="$IMPL_PLAN" # Alias for compatibility with existing code
  52. AGENT_TYPE="${1:-}"
  53. # Agent-specific file paths
  54. CLAUDE_FILE="$REPO_ROOT/CLAUDE.md"
  55. GEMINI_FILE="$REPO_ROOT/GEMINI.md"
  56. COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md"
  57. CURSOR_FILE="$REPO_ROOT/.cursor/rules/specify-rules.mdc"
  58. QWEN_FILE="$REPO_ROOT/QWEN.md"
  59. AGENTS_FILE="$REPO_ROOT/AGENTS.md"
  60. WINDSURF_FILE="$REPO_ROOT/.windsurf/rules/specify-rules.md"
  61. KILOCODE_FILE="$REPO_ROOT/.kilocode/rules/specify-rules.md"
  62. AUGGIE_FILE="$REPO_ROOT/.augment/rules/specify-rules.md"
  63. ROO_FILE="$REPO_ROOT/.roo/rules/specify-rules.md"
  64. # Template file
  65. TEMPLATE_FILE="$REPO_ROOT/.specify/templates/agent-file-template.md"
  66. # Global variables for parsed plan data
  67. NEW_LANG=""
  68. NEW_FRAMEWORK=""
  69. NEW_DB=""
  70. NEW_PROJECT_TYPE=""
  71. #==============================================================================
  72. # Utility Functions
  73. #==============================================================================
  74. log_info() {
  75. echo "INFO: $1"
  76. }
  77. log_success() {
  78. echo "✓ $1"
  79. }
  80. log_error() {
  81. echo "ERROR: $1" >&2
  82. }
  83. log_warning() {
  84. echo "WARNING: $1" >&2
  85. }
  86. # Cleanup function for temporary files
  87. cleanup() {
  88. local exit_code=$?
  89. rm -f /tmp/agent_update_*_$$
  90. rm -f /tmp/manual_additions_$$
  91. exit $exit_code
  92. }
  93. # Set up cleanup trap
  94. trap cleanup EXIT INT TERM
  95. #==============================================================================
  96. # Validation Functions
  97. #==============================================================================
  98. validate_environment() {
  99. # Check if we have a current branch/feature (git or non-git)
  100. if [[ -z "$CURRENT_BRANCH" ]]; then
  101. log_error "Unable to determine current feature"
  102. if [[ "$HAS_GIT" == "true" ]]; then
  103. log_info "Make sure you're on a feature branch"
  104. else
  105. log_info "Set SPECIFY_FEATURE environment variable or create a feature first"
  106. fi
  107. exit 1
  108. fi
  109. # Check if plan.md exists
  110. if [[ ! -f "$NEW_PLAN" ]]; then
  111. log_error "No plan.md found at $NEW_PLAN"
  112. log_info "Make sure you're working on a feature with a corresponding spec directory"
  113. if [[ "$HAS_GIT" != "true" ]]; then
  114. log_info "Use: export SPECIFY_FEATURE=your-feature-name or create a new feature first"
  115. fi
  116. exit 1
  117. fi
  118. # Check if template exists (needed for new files)
  119. if [[ ! -f "$TEMPLATE_FILE" ]]; then
  120. log_warning "Template file not found at $TEMPLATE_FILE"
  121. log_warning "Creating new agent files will fail"
  122. fi
  123. }
  124. #==============================================================================
  125. # Plan Parsing Functions
  126. #==============================================================================
  127. extract_plan_field() {
  128. local field_pattern="$1"
  129. local plan_file="$2"
  130. grep "^\*\*${field_pattern}\*\*: " "$plan_file" 2>/dev/null | \
  131. head -1 | \
  132. sed "s|^\*\*${field_pattern}\*\*: ||" | \
  133. sed 's/^[ \t]*//;s/[ \t]*$//' | \
  134. grep -v "NEEDS CLARIFICATION" | \
  135. grep -v "^N/A$" || echo ""
  136. }
  137. parse_plan_data() {
  138. local plan_file="$1"
  139. if [[ ! -f "$plan_file" ]]; then
  140. log_error "Plan file not found: $plan_file"
  141. return 1
  142. fi
  143. if [[ ! -r "$plan_file" ]]; then
  144. log_error "Plan file is not readable: $plan_file"
  145. return 1
  146. fi
  147. log_info "Parsing plan data from $plan_file"
  148. NEW_LANG=$(extract_plan_field "Language/Version" "$plan_file")
  149. NEW_FRAMEWORK=$(extract_plan_field "Primary Dependencies" "$plan_file")
  150. NEW_DB=$(extract_plan_field "Storage" "$plan_file")
  151. NEW_PROJECT_TYPE=$(extract_plan_field "Project Type" "$plan_file")
  152. # Log what we found
  153. if [[ -n "$NEW_LANG" ]]; then
  154. log_info "Found language: $NEW_LANG"
  155. else
  156. log_warning "No language information found in plan"
  157. fi
  158. if [[ -n "$NEW_FRAMEWORK" ]]; then
  159. log_info "Found framework: $NEW_FRAMEWORK"
  160. fi
  161. if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]]; then
  162. log_info "Found database: $NEW_DB"
  163. fi
  164. if [[ -n "$NEW_PROJECT_TYPE" ]]; then
  165. log_info "Found project type: $NEW_PROJECT_TYPE"
  166. fi
  167. }
  168. format_technology_stack() {
  169. local lang="$1"
  170. local framework="$2"
  171. local parts=()
  172. # Add non-empty parts
  173. [[ -n "$lang" && "$lang" != "NEEDS CLARIFICATION" ]] && parts+=("$lang")
  174. [[ -n "$framework" && "$framework" != "NEEDS CLARIFICATION" && "$framework" != "N/A" ]] && parts+=("$framework")
  175. # Join with proper formatting
  176. if [[ ${#parts[@]} -eq 0 ]]; then
  177. echo ""
  178. elif [[ ${#parts[@]} -eq 1 ]]; then
  179. echo "${parts[0]}"
  180. else
  181. # Join multiple parts with " + "
  182. local result="${parts[0]}"
  183. for ((i=1; i<${#parts[@]}; i++)); do
  184. result="$result + ${parts[i]}"
  185. done
  186. echo "$result"
  187. fi
  188. }
  189. #==============================================================================
  190. # Template and Content Generation Functions
  191. #==============================================================================
  192. get_project_structure() {
  193. local project_type="$1"
  194. if [[ "$project_type" == *"web"* ]]; then
  195. echo "backend/\\nfrontend/\\ntests/"
  196. else
  197. echo "src/\\ntests/"
  198. fi
  199. }
  200. get_commands_for_language() {
  201. local lang="$1"
  202. case "$lang" in
  203. *"Python"*)
  204. echo "cd src && pytest && ruff check ."
  205. ;;
  206. *"Rust"*)
  207. echo "cargo test && cargo clippy"
  208. ;;
  209. *"JavaScript"*|*"TypeScript"*)
  210. echo "npm test && npm run lint"
  211. ;;
  212. *)
  213. echo "# Add commands for $lang"
  214. ;;
  215. esac
  216. }
  217. get_language_conventions() {
  218. local lang="$1"
  219. echo "$lang: Follow standard conventions"
  220. }
  221. create_new_agent_file() {
  222. local target_file="$1"
  223. local temp_file="$2"
  224. local project_name="$3"
  225. local current_date="$4"
  226. if [[ ! -f "$TEMPLATE_FILE" ]]; then
  227. log_error "Template not found at $TEMPLATE_FILE"
  228. return 1
  229. fi
  230. if [[ ! -r "$TEMPLATE_FILE" ]]; then
  231. log_error "Template file is not readable: $TEMPLATE_FILE"
  232. return 1
  233. fi
  234. log_info "Creating new agent context file from template..."
  235. if ! cp "$TEMPLATE_FILE" "$temp_file"; then
  236. log_error "Failed to copy template file"
  237. return 1
  238. fi
  239. # Replace template placeholders
  240. local project_structure
  241. project_structure=$(get_project_structure "$NEW_PROJECT_TYPE")
  242. local commands
  243. commands=$(get_commands_for_language "$NEW_LANG")
  244. local language_conventions
  245. language_conventions=$(get_language_conventions "$NEW_LANG")
  246. # Perform substitutions with error checking using safer approach
  247. # Escape special characters for sed by using a different delimiter or escaping
  248. local escaped_lang=$(printf '%s\n' "$NEW_LANG" | sed 's/[\[\.*^$()+{}|]/\\&/g')
  249. local escaped_framework=$(printf '%s\n' "$NEW_FRAMEWORK" | sed 's/[\[\.*^$()+{}|]/\\&/g')
  250. local escaped_branch=$(printf '%s\n' "$CURRENT_BRANCH" | sed 's/[\[\.*^$()+{}|]/\\&/g')
  251. # Build technology stack and recent change strings conditionally
  252. local tech_stack
  253. if [[ -n "$escaped_lang" && -n "$escaped_framework" ]]; then
  254. tech_stack="- $escaped_lang + $escaped_framework ($escaped_branch)"
  255. elif [[ -n "$escaped_lang" ]]; then
  256. tech_stack="- $escaped_lang ($escaped_branch)"
  257. elif [[ -n "$escaped_framework" ]]; then
  258. tech_stack="- $escaped_framework ($escaped_branch)"
  259. else
  260. tech_stack="- ($escaped_branch)"
  261. fi
  262. local recent_change
  263. if [[ -n "$escaped_lang" && -n "$escaped_framework" ]]; then
  264. recent_change="- $escaped_branch: Added $escaped_lang + $escaped_framework"
  265. elif [[ -n "$escaped_lang" ]]; then
  266. recent_change="- $escaped_branch: Added $escaped_lang"
  267. elif [[ -n "$escaped_framework" ]]; then
  268. recent_change="- $escaped_branch: Added $escaped_framework"
  269. else
  270. recent_change="- $escaped_branch: Added"
  271. fi
  272. local substitutions=(
  273. "s|\[PROJECT NAME\]|$project_name|"
  274. "s|\[DATE\]|$current_date|"
  275. "s|\[EXTRACTED FROM ALL PLAN.MD FILES\]|$tech_stack|"
  276. "s|\[ACTUAL STRUCTURE FROM PLANS\]|$project_structure|g"
  277. "s|\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]|$commands|"
  278. "s|\[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]|$language_conventions|"
  279. "s|\[LAST 3 FEATURES AND WHAT THEY ADDED\]|$recent_change|"
  280. )
  281. for substitution in "${substitutions[@]}"; do
  282. if ! sed -i.bak -e "$substitution" "$temp_file"; then
  283. log_error "Failed to perform substitution: $substitution"
  284. rm -f "$temp_file" "$temp_file.bak"
  285. return 1
  286. fi
  287. done
  288. # Convert \n sequences to actual newlines
  289. newline=$(printf '\n')
  290. sed -i.bak2 "s/\\\\n/${newline}/g" "$temp_file"
  291. # Clean up backup files
  292. rm -f "$temp_file.bak" "$temp_file.bak2"
  293. return 0
  294. }
  295. update_existing_agent_file() {
  296. local target_file="$1"
  297. local current_date="$2"
  298. log_info "Updating existing agent context file..."
  299. # Use a single temporary file for atomic update
  300. local temp_file
  301. temp_file=$(mktemp) || {
  302. log_error "Failed to create temporary file"
  303. return 1
  304. }
  305. # Process the file in one pass
  306. local tech_stack=$(format_technology_stack "$NEW_LANG" "$NEW_FRAMEWORK")
  307. local new_tech_entries=()
  308. local new_change_entry=""
  309. # Prepare new technology entries
  310. if [[ -n "$tech_stack" ]] && ! grep -q "$tech_stack" "$target_file"; then
  311. new_tech_entries+=("- $tech_stack ($CURRENT_BRANCH)")
  312. fi
  313. if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]] && [[ "$NEW_DB" != "NEEDS CLARIFICATION" ]] && ! grep -q "$NEW_DB" "$target_file"; then
  314. new_tech_entries+=("- $NEW_DB ($CURRENT_BRANCH)")
  315. fi
  316. # Prepare new change entry
  317. if [[ -n "$tech_stack" ]]; then
  318. new_change_entry="- $CURRENT_BRANCH: Added $tech_stack"
  319. elif [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]] && [[ "$NEW_DB" != "NEEDS CLARIFICATION" ]]; then
  320. new_change_entry="- $CURRENT_BRANCH: Added $NEW_DB"
  321. fi
  322. # Process file line by line
  323. local in_tech_section=false
  324. local in_changes_section=false
  325. local tech_entries_added=false
  326. local changes_entries_added=false
  327. local existing_changes_count=0
  328. while IFS= read -r line || [[ -n "$line" ]]; do
  329. # Handle Active Technologies section
  330. if [[ "$line" == "## Active Technologies" ]]; then
  331. echo "$line" >> "$temp_file"
  332. in_tech_section=true
  333. continue
  334. elif [[ $in_tech_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then
  335. # Add new tech entries before closing the section
  336. if [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
  337. printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
  338. tech_entries_added=true
  339. fi
  340. echo "$line" >> "$temp_file"
  341. in_tech_section=false
  342. continue
  343. elif [[ $in_tech_section == true ]] && [[ -z "$line" ]]; then
  344. # Add new tech entries before empty line in tech section
  345. if [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
  346. printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
  347. tech_entries_added=true
  348. fi
  349. echo "$line" >> "$temp_file"
  350. continue
  351. fi
  352. # Handle Recent Changes section
  353. if [[ "$line" == "## Recent Changes" ]]; then
  354. echo "$line" >> "$temp_file"
  355. # Add new change entry right after the heading
  356. if [[ -n "$new_change_entry" ]]; then
  357. echo "$new_change_entry" >> "$temp_file"
  358. fi
  359. in_changes_section=true
  360. changes_entries_added=true
  361. continue
  362. elif [[ $in_changes_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then
  363. echo "$line" >> "$temp_file"
  364. in_changes_section=false
  365. continue
  366. elif [[ $in_changes_section == true ]] && [[ "$line" == "- "* ]]; then
  367. # Keep only first 2 existing changes
  368. if [[ $existing_changes_count -lt 2 ]]; then
  369. echo "$line" >> "$temp_file"
  370. ((existing_changes_count++))
  371. fi
  372. continue
  373. fi
  374. # Update timestamp
  375. if [[ "$line" =~ \*\*Last\ updated\*\*:.*[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] ]]; then
  376. echo "$line" | sed "s/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/$current_date/" >> "$temp_file"
  377. else
  378. echo "$line" >> "$temp_file"
  379. fi
  380. done < "$target_file"
  381. # Post-loop check: if we're still in the Active Technologies section and haven't added new entries
  382. if [[ $in_tech_section == true ]] && [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
  383. printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
  384. fi
  385. # Move temp file to target atomically
  386. if ! mv "$temp_file" "$target_file"; then
  387. log_error "Failed to update target file"
  388. rm -f "$temp_file"
  389. return 1
  390. fi
  391. return 0
  392. }
  393. #==============================================================================
  394. # Main Agent File Update Function
  395. #==============================================================================
  396. update_agent_file() {
  397. local target_file="$1"
  398. local agent_name="$2"
  399. if [[ -z "$target_file" ]] || [[ -z "$agent_name" ]]; then
  400. log_error "update_agent_file requires target_file and agent_name parameters"
  401. return 1
  402. fi
  403. log_info "Updating $agent_name context file: $target_file"
  404. local project_name
  405. project_name=$(basename "$REPO_ROOT")
  406. local current_date
  407. current_date=$(date +%Y-%m-%d)
  408. # Create directory if it doesn't exist
  409. local target_dir
  410. target_dir=$(dirname "$target_file")
  411. if [[ ! -d "$target_dir" ]]; then
  412. if ! mkdir -p "$target_dir"; then
  413. log_error "Failed to create directory: $target_dir"
  414. return 1
  415. fi
  416. fi
  417. if [[ ! -f "$target_file" ]]; then
  418. # Create new file from template
  419. local temp_file
  420. temp_file=$(mktemp) || {
  421. log_error "Failed to create temporary file"
  422. return 1
  423. }
  424. if create_new_agent_file "$target_file" "$temp_file" "$project_name" "$current_date"; then
  425. if mv "$temp_file" "$target_file"; then
  426. log_success "Created new $agent_name context file"
  427. else
  428. log_error "Failed to move temporary file to $target_file"
  429. rm -f "$temp_file"
  430. return 1
  431. fi
  432. else
  433. log_error "Failed to create new agent file"
  434. rm -f "$temp_file"
  435. return 1
  436. fi
  437. else
  438. # Update existing file
  439. if [[ ! -r "$target_file" ]]; then
  440. log_error "Cannot read existing file: $target_file"
  441. return 1
  442. fi
  443. if [[ ! -w "$target_file" ]]; then
  444. log_error "Cannot write to existing file: $target_file"
  445. return 1
  446. fi
  447. if update_existing_agent_file "$target_file" "$current_date"; then
  448. log_success "Updated existing $agent_name context file"
  449. else
  450. log_error "Failed to update existing agent file"
  451. return 1
  452. fi
  453. fi
  454. return 0
  455. }
  456. #==============================================================================
  457. # Agent Selection and Processing
  458. #==============================================================================
  459. update_specific_agent() {
  460. local agent_type="$1"
  461. case "$agent_type" in
  462. claude)
  463. update_agent_file "$CLAUDE_FILE" "Claude Code"
  464. ;;
  465. gemini)
  466. update_agent_file "$GEMINI_FILE" "Gemini CLI"
  467. ;;
  468. copilot)
  469. update_agent_file "$COPILOT_FILE" "GitHub Copilot"
  470. ;;
  471. cursor)
  472. update_agent_file "$CURSOR_FILE" "Cursor IDE"
  473. ;;
  474. qwen)
  475. update_agent_file "$QWEN_FILE" "Qwen Code"
  476. ;;
  477. opencode)
  478. update_agent_file "$AGENTS_FILE" "opencode"
  479. ;;
  480. codex)
  481. update_agent_file "$AGENTS_FILE" "Codex CLI"
  482. ;;
  483. windsurf)
  484. update_agent_file "$WINDSURF_FILE" "Windsurf"
  485. ;;
  486. kilocode)
  487. update_agent_file "$KILOCODE_FILE" "Kilo Code"
  488. ;;
  489. auggie)
  490. update_agent_file "$AUGGIE_FILE" "Auggie CLI"
  491. ;;
  492. roo)
  493. update_agent_file "$ROO_FILE" "Roo Code"
  494. ;;
  495. *)
  496. log_error "Unknown agent type '$agent_type'"
  497. log_error "Expected: claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|roo"
  498. exit 1
  499. ;;
  500. esac
  501. }
  502. update_all_existing_agents() {
  503. local found_agent=false
  504. # Check each possible agent file and update if it exists
  505. if [[ -f "$CLAUDE_FILE" ]]; then
  506. update_agent_file "$CLAUDE_FILE" "Claude Code"
  507. found_agent=true
  508. fi
  509. if [[ -f "$GEMINI_FILE" ]]; then
  510. update_agent_file "$GEMINI_FILE" "Gemini CLI"
  511. found_agent=true
  512. fi
  513. if [[ -f "$COPILOT_FILE" ]]; then
  514. update_agent_file "$COPILOT_FILE" "GitHub Copilot"
  515. found_agent=true
  516. fi
  517. if [[ -f "$CURSOR_FILE" ]]; then
  518. update_agent_file "$CURSOR_FILE" "Cursor IDE"
  519. found_agent=true
  520. fi
  521. if [[ -f "$QWEN_FILE" ]]; then
  522. update_agent_file "$QWEN_FILE" "Qwen Code"
  523. found_agent=true
  524. fi
  525. if [[ -f "$AGENTS_FILE" ]]; then
  526. update_agent_file "$AGENTS_FILE" "Codex/opencode"
  527. found_agent=true
  528. fi
  529. if [[ -f "$WINDSURF_FILE" ]]; then
  530. update_agent_file "$WINDSURF_FILE" "Windsurf"
  531. found_agent=true
  532. fi
  533. if [[ -f "$KILOCODE_FILE" ]]; then
  534. update_agent_file "$KILOCODE_FILE" "Kilo Code"
  535. found_agent=true
  536. fi
  537. if [[ -f "$AUGGIE_FILE" ]]; then
  538. update_agent_file "$AUGGIE_FILE" "Auggie CLI"
  539. found_agent=true
  540. fi
  541. if [[ -f "$ROO_FILE" ]]; then
  542. update_agent_file "$ROO_FILE" "Roo Code"
  543. found_agent=true
  544. fi
  545. # If no agent files exist, create a default Claude file
  546. if [[ "$found_agent" == false ]]; then
  547. log_info "No existing agent files found, creating default Claude file..."
  548. update_agent_file "$CLAUDE_FILE" "Claude Code"
  549. fi
  550. }
  551. print_summary() {
  552. echo
  553. log_info "Summary of changes:"
  554. if [[ -n "$NEW_LANG" ]]; then
  555. echo " - Added language: $NEW_LANG"
  556. fi
  557. if [[ -n "$NEW_FRAMEWORK" ]]; then
  558. echo " - Added framework: $NEW_FRAMEWORK"
  559. fi
  560. if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]]; then
  561. echo " - Added database: $NEW_DB"
  562. fi
  563. echo
  564. log_info "Usage: $0 [claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|roo]"
  565. }
  566. #==============================================================================
  567. # Main Execution
  568. #==============================================================================
  569. main() {
  570. # Validate environment before proceeding
  571. validate_environment
  572. log_info "=== Updating agent context files for feature $CURRENT_BRANCH ==="
  573. # Parse the plan file to extract project information
  574. if ! parse_plan_data "$NEW_PLAN"; then
  575. log_error "Failed to parse plan data"
  576. exit 1
  577. fi
  578. # Process based on agent type argument
  579. local success=true
  580. if [[ -z "$AGENT_TYPE" ]]; then
  581. # No specific agent provided - update all existing agent files
  582. log_info "No agent specified, updating all existing agent files..."
  583. if ! update_all_existing_agents; then
  584. success=false
  585. fi
  586. else
  587. # Specific agent provided - update only that agent
  588. log_info "Updating specific agent: $AGENT_TYPE"
  589. if ! update_specific_agent "$AGENT_TYPE"; then
  590. success=false
  591. fi
  592. fi
  593. # Print summary
  594. print_summary
  595. if [[ "$success" == true ]]; then
  596. log_success "Agent context update completed successfully"
  597. exit 0
  598. else
  599. log_error "Agent context update completed with errors"
  600. exit 1
  601. fi
  602. }
  603. # Execute main function if script is run directly
  604. if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  605. main "$@"
  606. fi