@prmichaelsen/acp-visualizer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/README.md +68 -0
  2. package/agent/commands/acp.clarification-address.md +417 -0
  3. package/agent/commands/acp.clarification-capture.md +386 -0
  4. package/agent/commands/acp.clarification-create.md +437 -0
  5. package/agent/commands/acp.clarifications-research.md +326 -0
  6. package/agent/commands/acp.command-create.md +432 -0
  7. package/agent/commands/acp.design-create.md +286 -0
  8. package/agent/commands/acp.design-reference.md +355 -0
  9. package/agent/commands/acp.handoff.md +270 -0
  10. package/agent/commands/acp.index.md +423 -0
  11. package/agent/commands/acp.init.md +546 -0
  12. package/agent/commands/acp.package-create.md +895 -0
  13. package/agent/commands/acp.package-info.md +212 -0
  14. package/agent/commands/acp.package-install.md +539 -0
  15. package/agent/commands/acp.package-list.md +280 -0
  16. package/agent/commands/acp.package-publish.md +541 -0
  17. package/agent/commands/acp.package-remove.md +293 -0
  18. package/agent/commands/acp.package-search.md +307 -0
  19. package/agent/commands/acp.package-update.md +361 -0
  20. package/agent/commands/acp.package-validate.md +540 -0
  21. package/agent/commands/acp.pattern-create.md +386 -0
  22. package/agent/commands/acp.plan.md +587 -0
  23. package/agent/commands/acp.proceed.md +882 -0
  24. package/agent/commands/acp.project-create.md +675 -0
  25. package/agent/commands/acp.project-info.md +312 -0
  26. package/agent/commands/acp.project-list.md +226 -0
  27. package/agent/commands/acp.project-remove.md +379 -0
  28. package/agent/commands/acp.project-set.md +227 -0
  29. package/agent/commands/acp.project-update.md +307 -0
  30. package/agent/commands/acp.projects-restore.md +228 -0
  31. package/agent/commands/acp.projects-sync.md +347 -0
  32. package/agent/commands/acp.report.md +407 -0
  33. package/agent/commands/acp.resume.md +239 -0
  34. package/agent/commands/acp.sessions.md +301 -0
  35. package/agent/commands/acp.status.md +293 -0
  36. package/agent/commands/acp.sync.md +364 -0
  37. package/agent/commands/acp.task-create.md +500 -0
  38. package/agent/commands/acp.update.md +302 -0
  39. package/agent/commands/acp.validate.md +466 -0
  40. package/agent/commands/acp.version-check-for-updates.md +276 -0
  41. package/agent/commands/acp.version-check.md +191 -0
  42. package/agent/commands/acp.version-update.md +289 -0
  43. package/agent/commands/command.template.md +339 -0
  44. package/agent/commands/git.commit.md +526 -0
  45. package/agent/commands/git.init.md +514 -0
  46. package/agent/commands/tanstack-cloudflare.deploy.md +272 -0
  47. package/agent/commands/tanstack-cloudflare.tail.md +275 -0
  48. package/agent/design/.gitkeep +0 -0
  49. package/agent/design/design.template.md +154 -0
  50. package/agent/design/local.dashboard-layout-routing.md +288 -0
  51. package/agent/design/local.data-model-yaml-parsing.md +310 -0
  52. package/agent/design/local.search-filtering.md +331 -0
  53. package/agent/design/local.server-api-auto-refresh.md +235 -0
  54. package/agent/design/local.table-tree-views.md +299 -0
  55. package/agent/design/local.visualizer-requirements.md +349 -0
  56. package/agent/design/requirements.template.md +387 -0
  57. package/agent/index/.gitkeep +0 -0
  58. package/agent/index/acp.core.yaml +137 -0
  59. package/agent/index/local.main.template.yaml +37 -0
  60. package/agent/manifest.template.yaml +13 -0
  61. package/agent/manifest.yaml +302 -0
  62. package/agent/milestones/.gitkeep +0 -0
  63. package/agent/milestones/milestone-1-project-scaffold-data-pipeline.md +67 -0
  64. package/agent/milestones/milestone-1-{title}.template.md +206 -0
  65. package/agent/milestones/milestone-2-dashboard-views-interaction.md +79 -0
  66. package/agent/package.template.yaml +86 -0
  67. package/agent/patterns/.gitkeep +0 -0
  68. package/agent/patterns/bootstrap.template.md +1237 -0
  69. package/agent/patterns/pattern.template.md +382 -0
  70. package/agent/patterns/tanstack-cloudflare.acl-permissions.md +332 -0
  71. package/agent/patterns/tanstack-cloudflare.action-bar-item.md +416 -0
  72. package/agent/patterns/tanstack-cloudflare.api-route-handlers.md +401 -0
  73. package/agent/patterns/tanstack-cloudflare.auth-session-management.md +387 -0
  74. package/agent/patterns/tanstack-cloudflare.card-and-list.md +271 -0
  75. package/agent/patterns/tanstack-cloudflare.chat-engine.md +353 -0
  76. package/agent/patterns/tanstack-cloudflare.confirmation-tokens.md +346 -0
  77. package/agent/patterns/tanstack-cloudflare.durable-objects-websocket.md +516 -0
  78. package/agent/patterns/tanstack-cloudflare.email-service.md +431 -0
  79. package/agent/patterns/tanstack-cloudflare.expander.md +98 -0
  80. package/agent/patterns/tanstack-cloudflare.fcm-push.md +115 -0
  81. package/agent/patterns/tanstack-cloudflare.firebase-anonymous-sessions.md +441 -0
  82. package/agent/patterns/tanstack-cloudflare.firebase-auth.md +348 -0
  83. package/agent/patterns/tanstack-cloudflare.firebase-firestore.md +550 -0
  84. package/agent/patterns/tanstack-cloudflare.firebase-storage.md +369 -0
  85. package/agent/patterns/tanstack-cloudflare.form-controls.md +145 -0
  86. package/agent/patterns/tanstack-cloudflare.global-search-context.md +93 -0
  87. package/agent/patterns/tanstack-cloudflare.image-carousel.md +126 -0
  88. package/agent/patterns/tanstack-cloudflare.library-services.md +553 -0
  89. package/agent/patterns/tanstack-cloudflare.lightbox.md +169 -0
  90. package/agent/patterns/tanstack-cloudflare.markdown-content.md +115 -0
  91. package/agent/patterns/tanstack-cloudflare.mention-suggestions.md +98 -0
  92. package/agent/patterns/tanstack-cloudflare.modal.md +156 -0
  93. package/agent/patterns/tanstack-cloudflare.nextjs-to-tanstack-routing.md +461 -0
  94. package/agent/patterns/tanstack-cloudflare.notifications-engine.md +151 -0
  95. package/agent/patterns/tanstack-cloudflare.oauth-token-refresh.md +90 -0
  96. package/agent/patterns/tanstack-cloudflare.og-metadata.md +296 -0
  97. package/agent/patterns/tanstack-cloudflare.pagination.md +442 -0
  98. package/agent/patterns/tanstack-cloudflare.pill-input.md +220 -0
  99. package/agent/patterns/tanstack-cloudflare.provider-adapter.md +401 -0
  100. package/agent/patterns/tanstack-cloudflare.rate-limiting.md +323 -0
  101. package/agent/patterns/tanstack-cloudflare.scheduled-tasks.md +338 -0
  102. package/agent/patterns/tanstack-cloudflare.searchable-settings.md +375 -0
  103. package/agent/patterns/tanstack-cloudflare.slide-over.md +129 -0
  104. package/agent/patterns/tanstack-cloudflare.ssr-preload.md +571 -0
  105. package/agent/patterns/tanstack-cloudflare.third-party-api-integration.md +508 -0
  106. package/agent/patterns/tanstack-cloudflare.toast-system.md +142 -0
  107. package/agent/patterns/tanstack-cloudflare.unified-header.md +280 -0
  108. package/agent/patterns/tanstack-cloudflare.user-scoped-collections.md +628 -0
  109. package/agent/patterns/tanstack-cloudflare.websocket-manager.md +237 -0
  110. package/agent/patterns/tanstack-cloudflare.wrangler-configuration.md +358 -0
  111. package/agent/patterns/tanstack-cloudflare.zod-schema-validation.md +336 -0
  112. package/agent/progress.template.yaml +161 -0
  113. package/agent/progress.yaml +145 -0
  114. package/agent/schemas/package.schema.yaml +276 -0
  115. package/agent/scripts/acp.common.sh +1781 -0
  116. package/agent/scripts/acp.install.sh +333 -0
  117. package/agent/scripts/acp.package-create.sh +924 -0
  118. package/agent/scripts/acp.package-info.sh +288 -0
  119. package/agent/scripts/acp.package-install.sh +893 -0
  120. package/agent/scripts/acp.package-list.sh +311 -0
  121. package/agent/scripts/acp.package-publish.sh +420 -0
  122. package/agent/scripts/acp.package-remove.sh +348 -0
  123. package/agent/scripts/acp.package-search.sh +156 -0
  124. package/agent/scripts/acp.package-update.sh +517 -0
  125. package/agent/scripts/acp.package-validate.sh +1018 -0
  126. package/agent/scripts/acp.uninstall.sh +85 -0
  127. package/agent/scripts/acp.version-check-for-updates.sh +98 -0
  128. package/agent/scripts/acp.version-check.sh +47 -0
  129. package/agent/scripts/acp.version-update.sh +176 -0
  130. package/agent/scripts/acp.yaml-parser.sh +985 -0
  131. package/agent/scripts/acp.yaml-validate.sh +205 -0
  132. package/agent/tasks/.gitkeep +0 -0
  133. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-1-initialize-tanstack-start-project.md +210 -0
  134. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-2-implement-data-model-yaml-parser.md +294 -0
  135. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-3-build-server-api-data-loading.md +193 -0
  136. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-4-add-auto-refresh-sse.md +262 -0
  137. package/agent/tasks/milestone-2-dashboard-views-interaction/task-10-polish-integration-testing.md +156 -0
  138. package/agent/tasks/milestone-2-dashboard-views-interaction/task-5-build-dashboard-layout-routing.md +178 -0
  139. package/agent/tasks/milestone-2-dashboard-views-interaction/task-6-build-overview-page.md +141 -0
  140. package/agent/tasks/milestone-2-dashboard-views-interaction/task-7-implement-milestone-table-view.md +153 -0
  141. package/agent/tasks/milestone-2-dashboard-views-interaction/task-8-implement-milestone-tree-view.md +174 -0
  142. package/agent/tasks/milestone-2-dashboard-views-interaction/task-9-implement-search-filtering.md +233 -0
  143. package/agent/tasks/task-1-{title}.template.md +244 -0
  144. package/bin/visualize.mjs +84 -0
  145. package/package.json +48 -0
  146. package/src/components/ExtraFieldsBadge.tsx +15 -0
  147. package/src/components/FilterBar.tsx +33 -0
  148. package/src/components/Header.tsx +23 -0
  149. package/src/components/MilestoneTable.tsx +167 -0
  150. package/src/components/MilestoneTree.tsx +84 -0
  151. package/src/components/ProgressBar.tsx +20 -0
  152. package/src/components/SearchInput.tsx +22 -0
  153. package/src/components/Sidebar.tsx +54 -0
  154. package/src/components/StatusBadge.tsx +23 -0
  155. package/src/components/StatusDot.tsx +12 -0
  156. package/src/components/TaskList.tsx +36 -0
  157. package/src/components/ViewToggle.tsx +31 -0
  158. package/src/lib/config.ts +8 -0
  159. package/src/lib/file-watcher.ts +43 -0
  160. package/src/lib/search.ts +48 -0
  161. package/src/lib/types.ts +73 -0
  162. package/src/lib/useAutoRefresh.ts +31 -0
  163. package/src/lib/useCollapse.ts +31 -0
  164. package/src/lib/useFilteredData.ts +55 -0
  165. package/src/lib/yaml-loader-real.spec.ts +47 -0
  166. package/src/lib/yaml-loader.spec.ts +201 -0
  167. package/src/lib/yaml-loader.ts +265 -0
  168. package/src/routeTree.gen.ts +140 -0
  169. package/src/router.tsx +10 -0
  170. package/src/routes/__root.tsx +75 -0
  171. package/src/routes/api/watch.ts +29 -0
  172. package/src/routes/index.tsx +115 -0
  173. package/src/routes/milestones.tsx +50 -0
  174. package/src/routes/search.tsx +84 -0
  175. package/src/routes/tasks.tsx +63 -0
  176. package/src/services/progress-database.service.ts +46 -0
  177. package/src/styles.css +25 -0
  178. package/tsconfig.json +24 -0
  179. package/vite.config.ts +16 -0
  180. package/vitest.config.ts +27 -0
@@ -0,0 +1,517 @@
1
+ #!/bin/bash
2
+
3
+ # Agent Context Protocol (ACP) Package Update Script
4
+ # Updates installed ACP packages to their latest versions
5
+
6
+ set -e
7
+
8
+ # Source common utilities
9
+ SCRIPT_DIR="$(dirname "$0")"
10
+ . "${SCRIPT_DIR}/acp.common.sh"
11
+
12
+ # Initialize colors
13
+ init_colors
14
+
15
+ # Parse arguments
16
+ PACKAGE_NAME=""
17
+ CHECK_ONLY=false
18
+ SKIP_MODIFIED=false
19
+ FORCE=false
20
+ AUTO_CONFIRM=false
21
+ GLOBAL_MODE=false
22
+
23
+ while [[ $# -gt 0 ]]; do
24
+ case $1 in
25
+ --global|-g)
26
+ GLOBAL_MODE=true
27
+ shift
28
+ ;;
29
+ --check)
30
+ CHECK_ONLY=true
31
+ shift
32
+ ;;
33
+ --skip-modified)
34
+ SKIP_MODIFIED=true
35
+ shift
36
+ ;;
37
+ --force)
38
+ FORCE=true
39
+ shift
40
+ ;;
41
+ -y|--yes)
42
+ AUTO_CONFIRM=true
43
+ shift
44
+ ;;
45
+ *)
46
+ PACKAGE_NAME="$1"
47
+ shift
48
+ ;;
49
+ esac
50
+ done
51
+
52
+ # Check if experimental feature is already installed
53
+ is_experimental_installed() {
54
+ local file_name="$1"
55
+ local file_type="$2"
56
+ local package_name="$3"
57
+
58
+ # Check manifest to see if this file is already installed
59
+ local installed=$(awk -v pkg="$package_name" -v type="$file_type" -v fname="$file_name" '
60
+ BEGIN { in_pkg=0; in_type=0 }
61
+ $0 ~ "^ " pkg ":" { in_pkg=1; next }
62
+ in_pkg && /^ [a-z]/ { in_pkg=0 }
63
+ in_pkg && $0 ~ "^ " type ":" { in_type=1; next }
64
+ in_type && /^ [a-z]/ { in_type=0 }
65
+ in_type && /^ - name:/ && $3 == fname { print "found"; exit }
66
+ ' "$MANIFEST_FILE")
67
+
68
+ if [ -n "$installed" ]; then
69
+ return 0 # Already installed
70
+ fi
71
+
72
+ return 1 # Not installed
73
+ }
74
+
75
+ # Check if feature graduated from experimental to stable
76
+ check_graduation() {
77
+ local file_name="$1"
78
+ local file_type="$2"
79
+ local package_name="$3"
80
+ local package_yaml_path="$4"
81
+
82
+ # Check if was experimental in manifest
83
+ local was_experimental=$(awk -v pkg="$package_name" -v type="$file_type" -v fname="$file_name" '
84
+ BEGIN { in_pkg=0; in_type=0; in_file=0 }
85
+ $0 ~ "^ " pkg ":" { in_pkg=1; next }
86
+ in_pkg && /^ [a-z]/ { in_pkg=0 }
87
+ in_pkg && $0 ~ "^ " type ":" { in_type=1; next }
88
+ in_type && /^ [a-z]/ { in_type=0 }
89
+ in_type && /^ - name:/ && $3 == fname { in_file=1; next }
90
+ in_file && /^ - name:/ { in_file=0 }
91
+ in_file && /^ experimental:/ { print $2; exit }
92
+ ' "$MANIFEST_FILE")
93
+
94
+ # Check if is experimental in new package.yaml
95
+ local is_experimental=$(grep -A 1000 "^ ${file_type}:" "$package_yaml_path" 2>/dev/null | grep -A 2 "name: ${file_name}" | grep "^ *experimental: true" | grep -v "^[[:space:]]*#" | head -1)
96
+
97
+ if [ "$was_experimental" = "true" ] && [ -z "$is_experimental" ]; then
98
+ return 0 # Graduated
99
+ fi
100
+
101
+ return 1 # Not graduated
102
+ }
103
+
104
+ # Check for updates for a package
105
+ # Usage: check_package_for_updates "package_name"
106
+ # Returns: 0 if updates available, 1 if up to date
107
+ check_package_for_updates() {
108
+ local package_name="$1"
109
+
110
+ # Get current version and source from manifest
111
+ local current_version
112
+ current_version=$(awk -v pkg="$package_name" '
113
+ $0 ~ "^ " pkg ":" { in_pkg=1; next }
114
+ in_pkg && /^ [a-z]/ { in_pkg=0 }
115
+ in_pkg && /^ package_version:/ { print $2; exit }
116
+ ' "$MANIFEST_FILE")
117
+
118
+ local source_url
119
+ source_url=$(awk -v pkg="$package_name" '
120
+ $0 ~ "^ " pkg ":" { in_pkg=1; next }
121
+ in_pkg && /^ [a-z]/ { in_pkg=0 }
122
+ in_pkg && /^ source:/ { print $2; exit }
123
+ ' "$MANIFEST_FILE")
124
+
125
+ if [ -z "$current_version" ] || [ -z "$source_url" ]; then
126
+ warn "Could not read package metadata for $package_name"
127
+ return 1
128
+ fi
129
+
130
+ info "Checking $package_name ($current_version)..."
131
+
132
+ # Clone repository to temp location
133
+ local temp_dir
134
+ temp_dir=$(mktemp -d)
135
+ trap "rm -rf $temp_dir" RETURN
136
+
137
+ if ! git clone --depth 1 "$source_url" "$temp_dir" &>/dev/null; then
138
+ warn "Failed to clone repository for $package_name"
139
+ return 1
140
+ fi
141
+
142
+ # Get remote version
143
+ local remote_version
144
+ if [ -f "$temp_dir/package.yaml" ]; then
145
+ remote_version=$(awk '/^version:/ {print $2; exit}' "$temp_dir/package.yaml")
146
+ else
147
+ warn "No package.yaml found in repository"
148
+ return 1
149
+ fi
150
+
151
+ # Compare versions
152
+ local comparison
153
+ comparison=$(compare_versions "$current_version" "$remote_version")
154
+
155
+ if [ "$comparison" = "newer" ]; then
156
+ echo " ${GREEN}✓${NC} Update available: $current_version → $remote_version"
157
+ return 0
158
+ else
159
+ echo " ${GREEN}✓${NC} Up to date: $current_version"
160
+ return 1
161
+ fi
162
+ }
163
+
164
+ # Update a package
165
+ # Usage: update_package "package_name"
166
+ update_package() {
167
+ local package_name="$1"
168
+
169
+ echo "${BLUE}Updating $package_name...${NC}"
170
+
171
+ # Get package info from manifest
172
+ local source_url
173
+ source_url=$(awk -v pkg="$package_name" '
174
+ $0 ~ "^ " pkg ":" { in_pkg=1; next }
175
+ in_pkg && /^ [a-z]/ { in_pkg=0 }
176
+ in_pkg && /^ source:/ { print $2; exit }
177
+ ' "$MANIFEST_FILE")
178
+
179
+ # Clone latest version
180
+ local temp_dir
181
+ temp_dir=$(mktemp -d)
182
+ trap "rm -rf $temp_dir" RETURN
183
+
184
+ if ! git clone --depth 1 "$source_url" "$temp_dir" &>/dev/null; then
185
+ die "Failed to clone repository"
186
+ fi
187
+
188
+ # Parse new package metadata
189
+ parse_package_metadata "$temp_dir"
190
+ local new_commit
191
+ new_commit=$(get_commit_hash "$temp_dir")
192
+
193
+ # Get list of installed files from manifest
194
+ local updated_count=0
195
+ local skipped_count=0
196
+ local modified_files=()
197
+
198
+ # Check for modified files first
199
+ for file_type in patterns commands design indices; do
200
+ local files
201
+ files=$(awk -v pkg="$package_name" -v type="$file_type" '
202
+ BEGIN { in_pkg=0; in_type=0 }
203
+ $0 ~ "^ " pkg ":" { in_pkg=1; next }
204
+ in_pkg && /^ [a-z]/ { in_pkg=0 }
205
+ in_pkg && $0 ~ "^ " type ":" { in_type=1; next }
206
+ in_type && /^ [a-z]/ { in_type=0 }
207
+ in_type && /^ - name:/ { print $3 }
208
+ ' "$MANIFEST_FILE")
209
+
210
+ for file_name in $files; do
211
+ if is_file_modified "$package_name" "$file_type" "$file_name"; then
212
+ modified_files+=("$file_type/$file_name")
213
+ fi
214
+ done
215
+ done
216
+
217
+ # Check template files for modifications
218
+ local _tmpl_entries
219
+ _tmpl_entries=$(awk -v pkg="$package_name" '
220
+ BEGIN { in_pkg=0; in_files=0; name="" }
221
+ $0 ~ "^ " pkg ":" { in_pkg=1; next }
222
+ in_pkg && /^ [a-z]/ { in_pkg=0 }
223
+ in_pkg && /^ files:$/ { in_files=1; next }
224
+ in_files && /^ [a-z]/ { in_files=0 }
225
+ in_files && /^ - name:/ { name=$3 }
226
+ in_files && /^ target:/ { $1=""; gsub(/^ +/, ""); print name "|" $0 }
227
+ ' "$MANIFEST_FILE")
228
+ while IFS='|' read -r _fname _ftarget; do
229
+ [ -z "$_fname" ] && continue
230
+ if [ -n "$_ftarget" ] && is_template_file_modified "$package_name" "$_fname" "$_ftarget"; then
231
+ modified_files+=("files/$_fname → $_ftarget")
232
+ fi
233
+ done <<< "$_tmpl_entries"
234
+
235
+ # Handle modified files
236
+ if [ ${#modified_files[@]} -gt 0 ] && [ "$FORCE" = false ]; then
237
+ echo ""
238
+ echo "${YELLOW}⚠️ Modified files detected:${NC}"
239
+ for file in "${modified_files[@]}"; do
240
+ echo " - $file"
241
+ done
242
+ echo ""
243
+
244
+ if [ "$SKIP_MODIFIED" = true ]; then
245
+ echo "Will skip modified files (--skip-modified)"
246
+ elif [ "$AUTO_CONFIRM" = false ]; then
247
+ read -p "Overwrite modified files? (y/N) " -n 1 -r
248
+ echo
249
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
250
+ SKIP_MODIFIED=true
251
+ echo "Skipping modified files"
252
+ fi
253
+ fi
254
+ echo ""
255
+ fi
256
+
257
+ # Mapping from manifest type to directory name
258
+ local _dir_for_type
259
+ _type_to_dir() {
260
+ case "$1" in
261
+ indices) echo "index" ;;
262
+ *) echo "$1" ;;
263
+ esac
264
+ }
265
+
266
+ # Update files
267
+ for file_type in patterns commands design indices; do
268
+ local files
269
+ files=$(awk -v pkg="$package_name" -v type="$file_type" '
270
+ BEGIN { in_pkg=0; in_type=0 }
271
+ $0 ~ "^ " pkg ":" { in_pkg=1; next }
272
+ in_pkg && /^ [a-z]/ { in_pkg=0 }
273
+ in_pkg && $0 ~ "^ " type ":" { in_type=1; next }
274
+ in_type && /^ [a-z]/ { in_type=0 }
275
+ in_type && /^ - name:/ { print $3 }
276
+ ' "$MANIFEST_FILE")
277
+
278
+ for file_name in $files; do
279
+ # Check if file should be skipped due to local modifications
280
+ if [ "$SKIP_MODIFIED" = true ]; then
281
+ if printf '%s\n' "${modified_files[@]}" | grep -q "^${file_type}/${file_name}$"; then
282
+ echo " ${YELLOW}⊘${NC} Skipped $file_type/$file_name (modified locally)"
283
+ ((skipped_count++))
284
+ continue
285
+ fi
286
+ fi
287
+
288
+ # Map manifest type to directory name
289
+ local _file_dir=$(_type_to_dir "$file_type")
290
+
291
+ # Check if file exists in new version
292
+ if [ ! -f "$temp_dir/agent/$_file_dir/$file_name" ]; then
293
+ warn "File no longer exists in package: $_file_dir/$file_name"
294
+ ((skipped_count++))
295
+ continue
296
+ fi
297
+
298
+ # Check if this is a new experimental feature
299
+ local is_experimental=$(grep -A 1000 "^ ${file_type}:" "$temp_dir/package.yaml" 2>/dev/null | grep -A 2 "name: ${file_name}" | grep "^ *experimental: true" | grep -v "^[[:space:]]*#" | head -1)
300
+
301
+ if [ -n "$is_experimental" ]; then
302
+ # This is an experimental feature
303
+ if ! is_experimental_installed "$file_name" "$file_type" "$package_name"; then
304
+ # Not installed, skip it
305
+ echo " ${DIM}⊘${NC} Skipping new experimental: $file_type/$file_name (use --experimental with install to add)"
306
+ ((skipped_count++))
307
+ continue
308
+ fi
309
+ # Already installed, update it
310
+ echo " ${YELLOW}↻${NC} Updating experimental: $file_type/$file_name"
311
+ else
312
+ # Check if graduated from experimental to stable
313
+ if check_graduation "$file_name" "$file_type" "$package_name" "$temp_dir/package.yaml"; then
314
+ echo " ${GREEN}🎓${NC} Graduated to stable: $file_type/$file_name"
315
+ fi
316
+ echo " ${BLUE}↻${NC} Updating: $file_type/$file_name"
317
+ fi
318
+
319
+ # Copy file
320
+ mkdir -p "agent/$_file_dir"
321
+ cp "$temp_dir/agent/$_file_dir/$file_name" "agent/$_file_dir/"
322
+
323
+ # Get new version and checksum
324
+ local new_version
325
+ new_version=$(get_file_version "$temp_dir/package.yaml" "$file_type" "$file_name")
326
+ local new_checksum
327
+ new_checksum=$(calculate_checksum "agent/$_file_dir/$file_name")
328
+
329
+ # Update manifest (including experimental status)
330
+ update_file_in_manifest "$package_name" "$file_type" "$file_name" "$new_version" "$new_checksum"
331
+
332
+ # Update experimental flag in manifest if needed
333
+ if [ -n "$is_experimental" ]; then
334
+ # Still experimental, ensure flag is set
335
+ _sed_i "/packages:/{:a;N;/name: ${file_name}/!ba;s/\(name: ${file_name}\)/\1\n experimental: true/;}" "$MANIFEST_FILE" 2>/dev/null || true
336
+ elif check_graduation "$file_name" "$file_type" "$package_name" "$temp_dir/package.yaml"; then
337
+ # Graduated, remove experimental flag
338
+ _sed_i "/name: ${file_name}/{N;s/\n *experimental: true//;}" "$MANIFEST_FILE" 2>/dev/null || true
339
+ fi
340
+
341
+ echo " ${GREEN}✓${NC} Updated $file_type/$file_name (v$new_version)"
342
+ ((updated_count++))
343
+ done
344
+ done
345
+
346
+ # Update template files (installed at target paths)
347
+ while IFS='|' read -r _fname _ftarget; do
348
+ [ -z "$_fname" ] && continue
349
+
350
+ # Check if modified and should skip
351
+ if [ "$SKIP_MODIFIED" = true ]; then
352
+ if printf '%s\n' "${modified_files[@]}" | grep -q "^files/$_fname"; then
353
+ echo " ${YELLOW}⊘${NC} Skipped files/$_fname (modified locally)"
354
+ ((skipped_count++))
355
+ continue
356
+ fi
357
+ fi
358
+
359
+ # Check if source file exists in new version
360
+ local _src_file="$temp_dir/agent/files/$_fname"
361
+ if [ ! -f "$_src_file" ]; then
362
+ warn "File no longer exists in package: files/$_fname"
363
+ ((skipped_count++))
364
+ continue
365
+ fi
366
+
367
+ # Copy to target path
368
+ mkdir -p "$(dirname "$_ftarget")"
369
+ cp "$_src_file" "$_ftarget"
370
+
371
+ # Re-apply variable substitution if stored
372
+ local _stored_vars
373
+ _stored_vars=$(get_template_file_variables "$package_name" "$_fname")
374
+ if [ -n "$_stored_vars" ]; then
375
+ while IFS='=' read -r _vname _vval; do
376
+ [ -z "$_vname" ] && continue
377
+ local _escaped
378
+ _escaped=$(printf '%s\n' "$_vval" | sed 's/[&/\]/\\&/g')
379
+ _sed_i "s|{{${_vname}}}|${_escaped}|g" "$_ftarget"
380
+ done <<< "$_stored_vars"
381
+ fi
382
+
383
+ # Update manifest
384
+ local _new_checksum
385
+ _new_checksum=$(calculate_checksum "$_ftarget")
386
+ local _new_version
387
+ _new_version=$(get_file_version "$temp_dir/package.yaml" "files" "$_fname")
388
+ update_template_file_in_manifest "$package_name" "$_fname" "$_new_version" "$_new_checksum"
389
+
390
+ echo " ${GREEN}✓${NC} Updated files/$_fname → $_ftarget"
391
+ ((updated_count++))
392
+ done <<< "$_tmpl_entries"
393
+
394
+ # Update package metadata in manifest
395
+ local timestamp
396
+ timestamp=$(get_timestamp)
397
+
398
+ # Update using awk
399
+ local temp_file
400
+ temp_file=$(mktemp)
401
+
402
+ awk -v pkg="$package_name" -v ver="$PACKAGE_VERSION" -v commit="$new_commit" -v ts="$timestamp" '
403
+ BEGIN { in_pkg=0 }
404
+ $0 ~ "^ " pkg ":" { in_pkg=1; print; next }
405
+ in_pkg && /^ [a-z]/ { in_pkg=0; print; next }
406
+ in_pkg && /^ package_version:/ { print " package_version: " ver; next }
407
+ in_pkg && /^ commit:/ { print " commit: " commit; next }
408
+ in_pkg && /^ updated_at:/ { print " updated_at: " ts; next }
409
+ { print }
410
+ ' "$MANIFEST_FILE" > "$temp_file"
411
+
412
+ mv "$temp_file" "$MANIFEST_FILE"
413
+
414
+ # Update manifest timestamp
415
+ update_manifest_timestamp
416
+
417
+ echo ""
418
+ success "Updated $package_name: $updated_count file(s)"
419
+ if [ $skipped_count -gt 0 ]; then
420
+ echo " Skipped: $skipped_count file(s)"
421
+ fi
422
+ }
423
+
424
+ # Main script execution
425
+ echo "${BLUE}📦 ACP Package Updater${NC}"
426
+ echo "========================================"
427
+ echo ""
428
+
429
+ # Determine manifest file based on mode
430
+ if [ "$GLOBAL_MODE" = true ]; then
431
+ MANIFEST_FILE="$HOME/.acp/manifest.yaml"
432
+ echo "${BLUE}Updating global packages...${NC}"
433
+ echo ""
434
+ else
435
+ MANIFEST_FILE="./agent/manifest.yaml"
436
+ echo "${BLUE}Updating packages...${NC}"
437
+ echo ""
438
+ fi
439
+
440
+ # Check if manifest exists
441
+ if [ ! -f "$MANIFEST_FILE" ]; then
442
+ if [ "$GLOBAL_MODE" = true ]; then
443
+ die "No global manifest found. No global packages installed."
444
+ else
445
+ die "No manifest found. No packages installed."
446
+ fi
447
+ fi
448
+
449
+ # Source YAML parser
450
+ source_yaml_parser
451
+
452
+ # Get list of installed packages
453
+ INSTALLED_PACKAGES=$(awk '/^ [a-z]/ && !/^ / && /:$/ {gsub(/:/, ""); print $1}' "$MANIFEST_FILE")
454
+
455
+ if [ -z "$INSTALLED_PACKAGES" ]; then
456
+ echo "${YELLOW}No packages installed${NC}"
457
+ exit 0
458
+ fi
459
+
460
+ # If no package specified, update all
461
+ if [ -z "$PACKAGE_NAME" ]; then
462
+ echo "Checking all packages for updates..."
463
+ echo ""
464
+
465
+ UPDATES_AVAILABLE=false
466
+ for pkg in $INSTALLED_PACKAGES; do
467
+ if check_package_for_updates "$pkg"; then
468
+ UPDATES_AVAILABLE=true
469
+ fi
470
+ done
471
+
472
+ if [ "$UPDATES_AVAILABLE" = false ]; then
473
+ echo "${GREEN}✓${NC} All packages are up to date"
474
+ exit 0
475
+ fi
476
+
477
+ if [ "$CHECK_ONLY" = true ]; then
478
+ echo ""
479
+ echo "To update all packages: $0"
480
+ echo "To update specific package: $0 <package-name>"
481
+ exit 0
482
+ fi
483
+
484
+ # Update all packages
485
+ echo ""
486
+ if [ "$AUTO_CONFIRM" = false ]; then
487
+ read -p "Update all packages? (y/N) " -n 1 -r
488
+ echo
489
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
490
+ echo "Update cancelled"
491
+ exit 0
492
+ fi
493
+ fi
494
+
495
+ echo ""
496
+ for pkg in $INSTALLED_PACKAGES; do
497
+ update_package "$pkg"
498
+ echo ""
499
+ done
500
+ else
501
+ # Update specific package
502
+ if ! echo "$INSTALLED_PACKAGES" | grep -q "^${PACKAGE_NAME}$"; then
503
+ die "Package not installed: $PACKAGE_NAME"
504
+ fi
505
+
506
+ if check_package_for_updates "$PACKAGE_NAME"; then
507
+ if [ "$CHECK_ONLY" = false ]; then
508
+ echo ""
509
+ update_package "$PACKAGE_NAME"
510
+ fi
511
+ else
512
+ echo "${GREEN}✓${NC} Package is up to date"
513
+ fi
514
+ fi
515
+
516
+ echo ""
517
+ echo "${GREEN}✅ Update complete!${NC}"