Skip to content

Commit 6f1882d

Browse files
author
薛華慶, james.hsueh
committed
feat: exract a core docs to replace place holder in template files
1 parent fc656af commit 6f1882d

File tree

9 files changed

+1042
-9
lines changed

9 files changed

+1042
-9
lines changed

gsi_installer.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
uvx --from gsi-protocol-installer gsi-install
88
# or
99
pipx run gsi-protocol-installer
10+
11+
# 本地同步模式(用於開發):
12+
python gsi_installer.py --sync
1013
"""
1114

1215
import os
@@ -16,6 +19,7 @@
1619
import shutil
1720
import tempfile
1821
import subprocess
22+
import argparse
1923

2024

2125
class Colors:
@@ -146,14 +150,17 @@ def download_commands(repo_url: str = "https://github.com/CodeMachine0121/GSI-Pr
146150

147151
def transform_template_for_claude(content: str) -> str:
148152
"""Transform template for Claude Code format."""
149-
# Claude Code 使用 {{prompt}},不需要轉換
150-
return content
153+
# 替換佔位符為 Claude Code 格式
154+
result = content.replace('__PROMPT__', '{{prompt}}')
155+
result = result.replace('__CMD_PREFIX__', '/')
156+
return result
151157

152158

153159
def transform_template_for_codex(content: str, filename: str) -> str:
154160
"""Transform template for Codex format."""
155-
# Codex 使用 $1 並需要 argument-hint
156-
result = content.replace('{{prompt}}', '$1')
161+
# 替換佔位符為 Codex 格式
162+
result = content.replace('__PROMPT__', '$1')
163+
result = result.replace('__CMD_PREFIX__', '/')
157164

158165
# 在 frontmatter 中加入 argument-hint
159166
if content.startswith('---\n'):
@@ -178,11 +185,9 @@ def transform_template_for_codex(content: str, filename: str) -> str:
178185

179186
def transform_template_for_github(content: str) -> str:
180187
"""Transform template for GitHub Copilot format."""
181-
# GitHub prompts 使用 {{ARG}} 和 @workspace 前綴
182-
result = content.replace('{{prompt}}', '{{ARG}}')
183-
184-
# 替換命令引用為 @workspace 格式
185-
result = result.replace('`/sdd-', '`@workspace /sdd-')
188+
# 替換佔位符為 GitHub Copilot 格式
189+
result = content.replace('__PROMPT__', '{{ARG}}')
190+
result = result.replace('__CMD_PREFIX__', '@workspace /')
186191

187192
return result
188193

scripts/README.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# GSI-Protocol 開發工作流程
2+
3+
## 問題
4+
修改 GSI command 內容時,需要同時維護三個位置:
5+
- `.claude/commands/` (Claude Code)
6+
- `.codex/prompts/` (Codex)
7+
- `.github/prompts/` (GitHub Copilot)
8+
9+
## 解決方案
10+
使用單一來源 + 自動同步腳本
11+
12+
## 目錄結構
13+
```
14+
scripts/
15+
├── templates/ # 📝 唯一需要維護的模板來源
16+
│ ├── sdd-spec.md
17+
│ ├── sdd-arch.md
18+
│ ├── sdd-impl.md
19+
│ ├── sdd-verify.md
20+
│ ├── sdd-integration-test.md
21+
│ └── sdd-auto.md
22+
├── sync_commands.py # 🔄 同步腳本
23+
└── README.md # 📖 本文件
24+
```
25+
26+
## 開發工作流程
27+
28+
### 1. 修改模板
29+
只需要修改 `scripts/templates/` 中的檔案,使用通用佔位符:
30+
31+
```markdown
32+
## 使用者需求
33+
34+
__PROMPT__
35+
36+
## 下一步
37+
- 使用指令:`__CMD_PREFIX__sdd-arch features/xxx.feature`
38+
```
39+
40+
**佔位符說明:**
41+
- `__PROMPT__` - 用戶輸入的參數
42+
- `__CMD_PREFIX__` - 命令前綴(會根據平台自動轉換)
43+
44+
### 2. 同步到三個平台
45+
運行同步腳本:
46+
47+
```bash
48+
python3 scripts/sync_commands.py
49+
```
50+
51+
這會自動轉換佔位符並同步:
52+
- 轉換並同步到 `.claude/commands/``__PROMPT__``{{prompt}}``__CMD_PREFIX__``/`
53+
- 轉換並同步到 `.codex/prompts/``__PROMPT__``$1``__CMD_PREFIX__``/`
54+
- 轉換並同步到 `.github/prompts/``__PROMPT__``{{ARG}}``__CMD_PREFIX__``@workspace /`
55+
56+
### 3. 測試
57+
在本地測試各平台的命令是否正常運作
58+
59+
### 4. 提交
60+
提交所有變更到 Git
61+
62+
## 用戶安裝流程
63+
64+
當用戶執行:
65+
```bash
66+
uvx --from gsi-protocol-installer gsi-install
67+
```
68+
69+
`gsi_installer.py` 會:
70+
1. 從 GitHub 下載 repo
71+
2. 讀取 `scripts/templates/` 中的模板
72+
3. 根據用戶選擇的平台自動轉換並安裝
73+
74+
## 佔位符轉換對照表
75+
76+
| 平台 | `__PROMPT__` 轉換為 | `__CMD_PREFIX__` 轉換為 | 檔案副檔名 |
77+
|------|-------------------|----------------------|-----------|
78+
| 模板 | `__PROMPT__` | `__CMD_PREFIX__` | `.md` |
79+
| Claude Code | `{{prompt}}` | `/` | `.md` |
80+
| Codex | `$1` | `/` | `.md` |
81+
| GitHub Copilot | `{{ARG}}` | `@workspace /` | `.prompt.md` |
82+
83+
## 優點
84+
85+
✅ 只需維護一個地方 (`scripts/templates/`)
86+
✅ 自動處理平台差異
87+
✅ 降低維護成本
88+
✅ 減少人為錯誤

scripts/sync_commands.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#!/usr/bin/env python3
2+
"""
3+
同步腳本 - 將 scripts/templates/ 中的模板同步到三個目標位置
4+
用法:python scripts/sync_commands.py
5+
"""
6+
7+
import os
8+
from pathlib import Path
9+
import shutil
10+
11+
12+
def transform_template_for_claude(content: str) -> str:
13+
"""轉換為 Claude Code 格式"""
14+
# 替換佔位符為 Claude Code 格式
15+
result = content.replace('__PROMPT__', '{{prompt}}')
16+
result = result.replace('__CMD_PREFIX__', '/')
17+
return result
18+
19+
20+
def transform_template_for_codex(content: str, filename: str) -> str:
21+
"""轉換為 Codex 格式"""
22+
# 替換佔位符為 Codex 格式
23+
result = content.replace('__PROMPT__', '$1')
24+
result = result.replace('__CMD_PREFIX__', '/')
25+
26+
# 在 frontmatter 中加入 argument-hint
27+
if content.startswith('---\n'):
28+
parts = result.split('---\n')
29+
if len(parts) >= 3:
30+
# 根據不同的指令設置不同的 argument-hint
31+
hint = ''
32+
if 'arch' in filename:
33+
hint = 'argument-hint: <feature_file_path>\n'
34+
elif 'impl' in filename:
35+
hint = 'argument-hint: <feature_file_path>\n'
36+
elif 'verify' in filename:
37+
hint = 'argument-hint: <feature_file_path>\n'
38+
elif 'integration-test' in filename:
39+
hint = 'argument-hint: <feature_file_path>\n'
40+
41+
parts[1] = hint + parts[1]
42+
result = '---\n'.join(parts)
43+
44+
return result
45+
46+
47+
def transform_template_for_github(content: str) -> str:
48+
"""轉換為 GitHub Copilot 格式"""
49+
# 替換佔位符為 GitHub Copilot 格式
50+
result = content.replace('__PROMPT__', '{{ARG}}')
51+
result = result.replace('__CMD_PREFIX__', '@workspace /')
52+
53+
return result
54+
55+
56+
def sync_commands():
57+
"""同步模板到三個目標位置"""
58+
# 獲取專案根目錄
59+
root_dir = Path(__file__).parent.parent
60+
templates_dir = root_dir / "scripts" / "templates"
61+
62+
if not templates_dir.exists():
63+
print(f"❌ 模板目錄不存在: {templates_dir}")
64+
print("請先創建 scripts/templates/ 目錄並放入模板文件")
65+
return
66+
67+
# 定義三個目標位置
68+
targets = {
69+
"Claude Code": {
70+
"dir": root_dir / ".claude" / "commands",
71+
"transform": transform_template_for_claude,
72+
"extension": ".md"
73+
},
74+
"Codex": {
75+
"dir": root_dir / ".codex" / "prompts",
76+
"transform": transform_template_for_codex,
77+
"extension": ".md"
78+
},
79+
"GitHub Copilot": {
80+
"dir": root_dir / ".github" / "prompts",
81+
"transform": transform_template_for_github,
82+
"extension": ".prompt.md"
83+
}
84+
}
85+
86+
print("🔄 開始同步命令模板...\n")
87+
88+
# 處理每個目標
89+
for name, config in targets.items():
90+
target_dir = config["dir"]
91+
transform_func = config["transform"]
92+
extension = config["extension"]
93+
94+
# 創建目標目錄
95+
target_dir.mkdir(parents=True, exist_ok=True)
96+
97+
# 清空目標目錄中的舊文件
98+
for old_file in target_dir.glob("sdd-*"):
99+
old_file.unlink()
100+
101+
# 複製並轉換模板
102+
count = 0
103+
for template_file in templates_dir.glob("sdd-*.md"):
104+
content = template_file.read_text(encoding='utf-8')
105+
106+
# 應用轉換
107+
if name == "Codex":
108+
transformed = transform_func(content, template_file.name)
109+
else:
110+
transformed = transform_func(content)
111+
112+
# 確定輸出文件名
113+
if extension == ".prompt.md":
114+
output_filename = template_file.stem + extension
115+
else:
116+
output_filename = template_file.name
117+
118+
output_file = target_dir / output_filename
119+
output_file.write_text(transformed, encoding='utf-8')
120+
count += 1
121+
122+
print(f"✅ {name}: 已同步 {count} 個文件到 {target_dir}")
123+
124+
print("\n✨ 同步完成!")
125+
print("\n💡 提示:")
126+
print(" - 模板來源: scripts/templates/")
127+
print(" - 修改模板後運行此腳本即可同步到三個位置")
128+
print(" - Claude Code: .claude/commands/")
129+
print(" - Codex: .codex/prompts/")
130+
print(" - GitHub Copilot: .github/prompts/")
131+
132+
133+
if __name__ == "__main__":
134+
sync_commands()

0 commit comments

Comments
 (0)