@seanyao/roll 2026.424.3 → 2026.424.4

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 (2) hide show
  1. package/bin/roll +74 -4
  2. package/package.json +1 -1
package/bin/roll CHANGED
@@ -4,7 +4,7 @@ set -euo pipefail
4
4
  # Roll — AI Agent Convention Manager
5
5
  # Single source of truth for how all AI coding agents behave.
6
6
 
7
- VERSION="2026.424.3"
7
+ VERSION="2026.424.4"
8
8
  ROLL_HOME="${ROLL_HOME:-${HOME}/.roll}"
9
9
  ROLL_CONFIG="${ROLL_HOME}/config.yaml"
10
10
  ROLL_GLOBAL="${ROLL_HOME}/conventions/global"
@@ -64,6 +64,24 @@ lower_name() {
64
64
  echo "$1" | tr '[:upper:]' '[:lower:]'
65
65
  }
66
66
 
67
+ # Check if an AI tool is actually installed.
68
+ # Most tools create their own config dir; Trae on macOS uses Library/Application Support
69
+ # and expects roll to manage ~/.trae/ — so we detect via the app directory instead.
70
+ _is_ai_installed() {
71
+ local ai_dir="$1"
72
+ [[ -d "$ai_dir" ]] && return 0
73
+ local bn
74
+ bn="$(basename "$ai_dir" | sed 's/^\.//')"
75
+ case "$bn" in
76
+ trae)
77
+ [[ -d "$HOME/Library/Application Support/Trae" ]] ||
78
+ [[ -d "$HOME/.config/Trae" ]]
79
+ return
80
+ ;;
81
+ esac
82
+ return 1
83
+ }
84
+
67
85
  # ─── Helper: read config value ───────────────────────────────────────────────
68
86
  config_get() {
69
87
  local key="$1"
@@ -87,6 +105,53 @@ _get_ai_tools() {
87
105
  done
88
106
  }
89
107
 
108
+ # Add any ai_* keys from the default set that are missing from the user's config.
109
+ # Non-destructive: never removes or modifies existing entries.
110
+ _ensure_config_entries() {
111
+ [[ -f "$ROLL_CONFIG" ]] || return
112
+
113
+ local -a default_keys=(
114
+ "ai_claude:~/.claude|CLAUDE.md|CLAUDE.md"
115
+ "ai_gemini:~/.gemini|GEMINI.md|GEMINI.md"
116
+ "ai_kimi:~/.kimi|AGENTS.md|AGENTS.md"
117
+ "ai_codex:~/.codex|AGENTS.md|AGENTS.md"
118
+ "ai_cursor:~/.cursor|.cursor-rules|.cursor-rules"
119
+ "ai_trae:~/.trae|user_rules.md|project_rules.md"
120
+ "ai_openclaw:~/.openclaw/workspace|AGENTS.md|AGENTS.md"
121
+ )
122
+
123
+ local added=0
124
+ local tmp
125
+ tmp="$(mktemp)"
126
+ cp "$ROLL_CONFIG" "$tmp"
127
+
128
+ for entry in "${default_keys[@]}"; do
129
+ local key="${entry%%:*}"
130
+ local val="${entry#*:}"
131
+ if ! grep -qE "^${key}:" "$ROLL_CONFIG" 2>/dev/null; then
132
+ if grep -q "^# User preferences" "$tmp" 2>/dev/null; then
133
+ local new_tmp
134
+ new_tmp="$(mktemp)"
135
+ while IFS= read -r line; do
136
+ [[ "$line" == "# User preferences" ]] && echo "${key}: ${val}" >> "$new_tmp"
137
+ echo "$line" >> "$new_tmp"
138
+ done < "$tmp"
139
+ mv "$new_tmp" "$tmp"
140
+ else
141
+ echo "${key}: ${val}" >> "$tmp"
142
+ fi
143
+ added=$((added + 1))
144
+ warn "Added missing config entry: ${key} 已添加缺失配置项: ${key}"
145
+ fi
146
+ done
147
+
148
+ if [[ $added -gt 0 ]]; then
149
+ cp "$tmp" "$ROLL_CONFIG"
150
+ ok "Config updated with $added new entries 配置已更新,新增 $added 条目"
151
+ fi
152
+ rm -f "$tmp"
153
+ }
154
+
90
155
  # Extract fields from a "<dir>|<config>|<src>" entry
91
156
  _ai_dir() { echo "$1" | cut -d'|' -f1; }
92
157
  _ai_config() { echo "$1" | cut -d'|' -f2; }
@@ -246,6 +311,9 @@ YAML
246
311
  ok "Created: ~/.roll/config.yaml 已创建: ~/.roll/config.yaml"
247
312
  fi
248
313
 
314
+ # Ensure all expected ai_* keys exist (handles upgrades where new tools were added)
315
+ _ensure_config_entries
316
+
249
317
  }
250
318
 
251
319
  # ─── Internal: create or repair per-skill symlinks (non-destructive) ─────────
@@ -258,7 +326,8 @@ _link_skills() {
258
326
  while IFS= read -r entry; do
259
327
  local ai_dir
260
328
  ai_dir="$(_ai_dir "$entry")"
261
- [[ -d "$ai_dir" ]] || continue
329
+ _is_ai_installed "$ai_dir" || continue
330
+ mkdir -p "$ai_dir"
262
331
 
263
332
  local ai_name ai_dir_real skills_dir
264
333
  ai_name="$(ai_tool_name "$ai_dir")"
@@ -355,8 +424,8 @@ _sync_convention_for_tool() {
355
424
  local dst_dir
356
425
  dst_dir="$(dirname "$main_dst")"
357
426
 
358
- # Only proceed if the AI tool directory already exists (except Claude, always create)
359
- if [[ "$dst_dir" != "$HOME/.claude" ]] && [[ ! -d "$dst_dir" ]]; then
427
+ # Only proceed if Claude (always) or the tool is installed
428
+ if [[ "$dst_dir" != "$HOME/.claude" ]] && ! _is_ai_installed "$dst_dir"; then
360
429
  return
361
430
  fi
362
431
  mkdir -p "$dst_dir"
@@ -467,6 +536,7 @@ cmd_sync() {
467
536
  info "Syncing from repo to AI tools... 正在从仓库同步到 AI 工具..."
468
537
  echo ""
469
538
  _pull_conventions "$force"
539
+ _ensure_config_entries
470
540
  echo ""
471
541
  _sync_conventions "$force"
472
542
  echo ""
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seanyao/roll",
3
- "version": "2026.424.3",
3
+ "version": "2026.424.4",
4
4
  "description": "Roll — Roll out features with AI agents",
5
5
  "scripts": {
6
6
  "test": "find tests/unit tests/integration -name '*.bats' | sort | xargs ./tests/helpers/bats-core/bin/bats"