taiwan-invoice-skill 2.0.0 → 2.2.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 (30) hide show
  1. package/README.md +131 -0
  2. package/assets/taiwan-invoice/SKILL.md +452 -0
  3. package/assets/taiwan-invoice/data/error-codes.csv +41 -0
  4. package/assets/taiwan-invoice/data/field-mappings.csv +27 -0
  5. package/assets/taiwan-invoice/data/operations.csv +11 -0
  6. package/assets/taiwan-invoice/data/providers.csv +4 -0
  7. package/assets/taiwan-invoice/data/tax-rules.csv +9 -0
  8. package/assets/taiwan-invoice/data/troubleshooting.csv +17 -0
  9. package/assets/taiwan-invoice/scripts/__pycache__/core.cpython-312.pyc +0 -0
  10. package/assets/taiwan-invoice/scripts/core.py +304 -0
  11. package/assets/taiwan-invoice/scripts/generate-invoice-service.py +642 -128
  12. package/assets/taiwan-invoice/scripts/recommend.py +340 -0
  13. package/assets/taiwan-invoice/scripts/search.py +201 -0
  14. package/assets/templates/base/quick-reference.md +85 -0
  15. package/assets/templates/platforms/{antigravity.json → agent.json} +6 -3
  16. package/assets/templates/platforms/claude.json +5 -2
  17. package/assets/templates/platforms/codebuddy.json +5 -2
  18. package/assets/templates/platforms/codex.json +5 -2
  19. package/assets/templates/platforms/continue.json +5 -2
  20. package/assets/templates/platforms/copilot.json +5 -2
  21. package/assets/templates/platforms/cursor.json +5 -2
  22. package/assets/templates/platforms/gemini.json +5 -2
  23. package/assets/templates/platforms/kiro.json +5 -2
  24. package/assets/templates/platforms/opencode.json +5 -2
  25. package/assets/templates/platforms/qoder.json +5 -2
  26. package/assets/templates/platforms/roocode.json +5 -2
  27. package/assets/templates/platforms/trae.json +5 -2
  28. package/assets/templates/platforms/windsurf.json +5 -2
  29. package/dist/index.js +265 -60
  30. package/package.json +3 -2
@@ -0,0 +1,340 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Taiwan Invoice Skill - 加值中心推薦系統
4
+ 基於使用者需求推薦最適合的電子發票加值中心
5
+
6
+ 無外部依賴,純 Python 實現
7
+ """
8
+
9
+ import csv
10
+ import os
11
+ import sys
12
+ import argparse
13
+ from typing import List, Dict, Any, Optional, Tuple
14
+
15
+ # 取得 data 目錄路徑
16
+ SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
17
+ DATA_DIR = os.path.join(os.path.dirname(SCRIPT_DIR), 'data')
18
+
19
+ # 推薦規則定義
20
+ RECOMMENDATION_RULES = {
21
+ # 關鍵字 → (provider, weight, reason)
22
+ '穩定': [('ECPay', 3, '市佔率最高,系統穩定性佳')],
23
+ '市佔': [('ECPay', 3, '台灣電子發票市佔率領先')],
24
+ '文檔': [('ECPay', 2, '提供完整 API 文檔與 SDK')],
25
+ 'sdk': [('ECPay', 2, '官方 SDK 支援多種語言')],
26
+ '高交易量': [('ECPay', 3, '適合高交易量電商')],
27
+ '電商': [('ECPay', 2, '電商整合經驗豐富')],
28
+
29
+ '簡單': [('SmilePay', 3, '整合流程最簡單')],
30
+ '快速': [('SmilePay', 3, '最快速完成整合')],
31
+ '小型': [('SmilePay', 2, '適合小型專案')],
32
+ '測試': [('SmilePay', 2, '測試環境設定簡單')],
33
+ '無加密': [('SmilePay', 3, '無需複雜加密流程')],
34
+ '便宜': [('SmilePay', 2, '費用較低')],
35
+
36
+ 'api': [('Amego', 3, 'MIG 4.0 最新 API 標準')],
37
+ '設計': [('Amego', 2, 'API 設計優良')],
38
+ '新': [('Amego', 2, '採用最新技術標準')],
39
+ 'mig': [('Amego', 3, '完整支援 MIG 4.0 規範')],
40
+ '標準': [('Amego', 2, 'API 設計符合業界標準')],
41
+
42
+ # B2B/B2C 相關
43
+ 'b2b': [('ECPay', 1, 'B2B 發票功能完整'), ('Amego', 1, 'B2B 計算清晰')],
44
+ 'b2c': [('ECPay', 1, 'B2C 市佔最高'), ('SmilePay', 1, 'B2C 整合簡單')],
45
+ '統編': [('ECPay', 1, 'B2B 統編發票經驗豐富')],
46
+
47
+ # 功能相關
48
+ '列印': [('ECPay', 2, '列印功能完整'), ('SmilePay', 1, '支援列印')],
49
+ '作廢': [('ECPay', 1, '作廢流程完整')],
50
+ '折讓': [('ECPay', 1, '折讓功能完整')],
51
+ '載具': [('ECPay', 1, '載具支援完整'), ('SmilePay', 1, '載具整合簡單')],
52
+ '捐贈': [('ECPay', 1, '捐贈功能完整')],
53
+ }
54
+
55
+ # 反模式警告
56
+ ANTI_PATTERNS = {
57
+ 'ECPay': [
58
+ ('無技術資源', '加密流程較複雜,需要一定技術能力'),
59
+ ('極簡整合', '如果只需最簡單整合,SmilePay 可能更適合'),
60
+ ],
61
+ 'SmilePay': [
62
+ ('高交易量', '大型電商建議使用 ECPay 以確保穩定性'),
63
+ ('複雜需求', 'API 功能相對基本,複雜需求可能受限'),
64
+ ('b2b', 'B2B 發票功能較少文檔'),
65
+ ],
66
+ 'Amego': [
67
+ ('市佔', '市佔率相對較低'),
68
+ ('社群', '社群支援與範例相對較少'),
69
+ ('穩定', '如果穩定性是首要考量,ECPay 更保險'),
70
+ ],
71
+ }
72
+
73
+
74
+ def load_providers() -> List[Dict[str, str]]:
75
+ """載入加值中心資料"""
76
+ filepath = os.path.join(DATA_DIR, 'providers.csv')
77
+ if not os.path.exists(filepath):
78
+ return []
79
+
80
+ with open(filepath, 'r', encoding='utf-8') as f:
81
+ reader = csv.DictReader(f)
82
+ return list(reader)
83
+
84
+
85
+ def analyze_requirements(query: str) -> Dict[str, Tuple[int, List[str]]]:
86
+ """
87
+ 分析使用者需求,計算各加值中心分數
88
+
89
+ Returns:
90
+ Dict[provider, (score, reasons)]
91
+ """
92
+ query_lower = query.lower()
93
+
94
+ scores = {
95
+ 'ECPay': (0, []),
96
+ 'SmilePay': (0, []),
97
+ 'Amego': (0, []),
98
+ }
99
+
100
+ # 根據關鍵字累計分數
101
+ for keyword, rules in RECOMMENDATION_RULES.items():
102
+ if keyword.lower() in query_lower:
103
+ for provider, weight, reason in rules:
104
+ current_score, reasons = scores[provider]
105
+ if reason not in reasons:
106
+ scores[provider] = (current_score + weight, reasons + [reason])
107
+
108
+ return scores
109
+
110
+
111
+ def get_anti_pattern_warnings(query: str, recommended: str) -> List[str]:
112
+ """取得反模式警告"""
113
+ query_lower = query.lower()
114
+ warnings = []
115
+
116
+ if recommended in ANTI_PATTERNS:
117
+ for keyword, warning in ANTI_PATTERNS[recommended]:
118
+ if keyword.lower() in query_lower:
119
+ warnings.append(warning)
120
+
121
+ return warnings
122
+
123
+
124
+ def recommend(query: str, verbose: bool = False) -> Dict[str, Any]:
125
+ """
126
+ 推薦加值中心
127
+
128
+ Args:
129
+ query: 使用者需求描述
130
+ verbose: 是否輸出詳細資訊
131
+
132
+ Returns:
133
+ 推薦結果
134
+ """
135
+ providers = load_providers()
136
+ scores = analyze_requirements(query)
137
+
138
+ # 排序取得推薦順序
139
+ sorted_providers = sorted(
140
+ scores.items(),
141
+ key=lambda x: x[1][0],
142
+ reverse=True
143
+ )
144
+
145
+ # 建立結果
146
+ recommended = sorted_providers[0][0]
147
+ recommended_score, recommended_reasons = sorted_providers[0]
148
+
149
+ # 如果沒有匹配任何關鍵字,給預設推薦
150
+ if recommended_score == 0:
151
+ recommended = 'ECPay'
152
+ recommended_reasons = ['市佔率最高,適合大多數場景', '文檔完整,社群支援豐富']
153
+ recommended_score = 1
154
+
155
+ # 取得加值中心詳細資訊
156
+ provider_info = None
157
+ for p in providers:
158
+ if p.get('provider') == recommended:
159
+ provider_info = p
160
+ break
161
+
162
+ # 取得警告
163
+ warnings = get_anti_pattern_warnings(query, recommended)
164
+
165
+ result = {
166
+ 'query': query,
167
+ 'recommended': recommended,
168
+ 'score': recommended_score,
169
+ 'reasons': recommended_reasons,
170
+ 'warnings': warnings,
171
+ 'alternatives': [],
172
+ 'provider_info': provider_info,
173
+ }
174
+
175
+ # 加入替代方案
176
+ for provider, (score, reasons) in sorted_providers[1:]:
177
+ if score > 0:
178
+ result['alternatives'].append({
179
+ 'provider': provider,
180
+ 'score': score,
181
+ 'reasons': reasons,
182
+ })
183
+
184
+ return result
185
+
186
+
187
+ def format_ascii_box(result: Dict[str, Any]) -> str:
188
+ """格式化為 ASCII Box 輸出"""
189
+ width = 70
190
+ lines = []
191
+
192
+ # 頂部邊框
193
+ lines.append('╔' + '═' * (width - 2) + '╗')
194
+ lines.append('║' + ' 🎯 加值中心推薦結果 '.center(width - 2) + '║')
195
+ lines.append('╠' + '═' * (width - 2) + '╣')
196
+
197
+ # 查詢內容
198
+ query_line = f' 需求: {result["query"]}'
199
+ if len(query_line) > width - 4:
200
+ query_line = query_line[:width - 7] + '...'
201
+ lines.append('║' + query_line.ljust(width - 2) + '║')
202
+ lines.append('╠' + '─' * (width - 2) + '╣')
203
+
204
+ # 推薦結果
205
+ recommended = result['recommended']
206
+ score = result['score']
207
+ lines.append('║' + f' ⭐ 推薦: {recommended} (信心分數: {score})'.ljust(width - 2) + '║')
208
+ lines.append('║' + ' '.ljust(width - 2) + '║')
209
+
210
+ # 推薦原因
211
+ lines.append('║' + ' 📋 推薦原因:'.ljust(width - 2) + '║')
212
+ for reason in result['reasons']:
213
+ reason_line = f' • {reason}'
214
+ if len(reason_line) > width - 4:
215
+ reason_line = reason_line[:width - 7] + '...'
216
+ lines.append('║' + reason_line.ljust(width - 2) + '║')
217
+
218
+ # 警告
219
+ if result['warnings']:
220
+ lines.append('║' + ' '.ljust(width - 2) + '║')
221
+ lines.append('║' + ' ⚠️ 注意事項:'.ljust(width - 2) + '║')
222
+ for warning in result['warnings']:
223
+ warning_line = f' • {warning}'
224
+ if len(warning_line) > width - 4:
225
+ warning_line = warning_line[:width - 7] + '...'
226
+ lines.append('║' + warning_line.ljust(width - 2) + '║')
227
+
228
+ # 替代方案
229
+ if result['alternatives']:
230
+ lines.append('║' + ' '.ljust(width - 2) + '║')
231
+ lines.append('╠' + '─' * (width - 2) + '╣')
232
+ lines.append('║' + ' 🔄 替代方案:'.ljust(width - 2) + '║')
233
+ for alt in result['alternatives']:
234
+ alt_line = f' • {alt["provider"]} (分數: {alt["score"]})'
235
+ lines.append('║' + alt_line.ljust(width - 2) + '║')
236
+ for reason in alt['reasons'][:2]: # 只顯示前 2 個原因
237
+ reason_line = f' - {reason}'
238
+ if len(reason_line) > width - 4:
239
+ reason_line = reason_line[:width - 7] + '...'
240
+ lines.append('║' + reason_line.ljust(width - 2) + '║')
241
+
242
+ # 加值中心資訊
243
+ if result['provider_info']:
244
+ info = result['provider_info']
245
+ lines.append('║' + ' '.ljust(width - 2) + '║')
246
+ lines.append('╠' + '─' * (width - 2) + '╣')
247
+ lines.append('║' + f' 📦 {info.get("display_name", recommended)} 資訊:'.ljust(width - 2) + '║')
248
+ lines.append('║' + f' 認證方式: {info.get("auth_method", "N/A")}'.ljust(width - 2) + '║')
249
+ lines.append('║' + f' 測試網址: {info.get("test_url", "N/A")}'.ljust(width - 2) + '║')
250
+ features = info.get('features', '')
251
+ if features:
252
+ feat_line = f' 特色: {features}'
253
+ if len(feat_line) > width - 4:
254
+ feat_line = feat_line[:width - 7] + '...'
255
+ lines.append('║' + feat_line.ljust(width - 2) + '║')
256
+
257
+ # 底部邊框
258
+ lines.append('╚' + '═' * (width - 2) + '╝')
259
+
260
+ return '\n'.join(lines)
261
+
262
+
263
+ def format_json(result: Dict[str, Any]) -> str:
264
+ """格式化為 JSON 輸出"""
265
+ import json
266
+ return json.dumps(result, ensure_ascii=False, indent=2)
267
+
268
+
269
+ def format_simple(result: Dict[str, Any]) -> str:
270
+ """格式化為簡單文字輸出"""
271
+ lines = []
272
+ lines.append(f"推薦加值中心: {result['recommended']}")
273
+ lines.append(f"信心分數: {result['score']}")
274
+ lines.append("")
275
+ lines.append("推薦原因:")
276
+ for reason in result['reasons']:
277
+ lines.append(f" - {reason}")
278
+
279
+ if result['warnings']:
280
+ lines.append("")
281
+ lines.append("注意事項:")
282
+ for warning in result['warnings']:
283
+ lines.append(f" - {warning}")
284
+
285
+ if result['alternatives']:
286
+ lines.append("")
287
+ lines.append("替代方案:")
288
+ for alt in result['alternatives']:
289
+ lines.append(f" - {alt['provider']} (分數: {alt['score']})")
290
+
291
+ return '\n'.join(lines)
292
+
293
+
294
+ def main():
295
+ parser = argparse.ArgumentParser(
296
+ description='Taiwan Invoice 加值中心推薦系統',
297
+ formatter_class=argparse.RawDescriptionHelpFormatter,
298
+ epilog="""
299
+ 範例:
300
+ python recommend.py "電商 高交易量 穩定"
301
+ python recommend.py "簡單整合 快速上線" --format json
302
+ python recommend.py "API設計優先 MIG標準" --format simple
303
+
304
+ 關鍵字範例:
305
+ 穩定性: 穩定, 市佔, 高交易量, 電商
306
+ 簡易性: 簡單, 快速, 小型, 測試
307
+ API品質: api, 設計, 新, mig, 標準
308
+ 功能: b2b, b2c, 列印, 作廢, 折讓, 載具, 捐贈
309
+ """
310
+ )
311
+
312
+ parser.add_argument('query', help='需求描述 (關鍵字以空格分隔)')
313
+ parser.add_argument(
314
+ '-f', '--format',
315
+ choices=['ascii', 'json', 'simple'],
316
+ default='ascii',
317
+ help='輸出格式 (預設: ascii)'
318
+ )
319
+ parser.add_argument(
320
+ '-v', '--verbose',
321
+ action='store_true',
322
+ help='顯示詳細資訊'
323
+ )
324
+
325
+ args = parser.parse_args()
326
+
327
+ # 執行推薦
328
+ result = recommend(args.query, args.verbose)
329
+
330
+ # 輸出結果
331
+ if args.format == 'json':
332
+ print(format_json(result))
333
+ elif args.format == 'simple':
334
+ print(format_simple(result))
335
+ else:
336
+ print(format_ascii_box(result))
337
+
338
+
339
+ if __name__ == '__main__':
340
+ main()
@@ -0,0 +1,201 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Taiwan Invoice Skill - Search CLI
4
+ 電子發票智能搜索命令行工具
5
+
6
+ 用法:
7
+ python search.py "ecpay B2C" --domain operation
8
+ python search.py "1999 error" --domain error
9
+ python search.py "稅額計算" --domain tax
10
+ python search.py "綠界" --all
11
+ """
12
+
13
+ import argparse
14
+ import sys
15
+ from typing import Dict, List, Any
16
+
17
+ from core import (
18
+ search,
19
+ search_all,
20
+ detect_domain,
21
+ get_available_domains,
22
+ get_domain_info
23
+ )
24
+
25
+
26
+ def format_ascii_box(title: str, content: List[str], width: int = 80) -> str:
27
+ """
28
+ 格式化 ASCII Box 輸出
29
+ """
30
+ lines = []
31
+ lines.append('┌' + '─' * (width - 2) + '┐')
32
+ lines.append('│' + f' {title}'.ljust(width - 2) + '│')
33
+ lines.append('├' + '─' * (width - 2) + '┤')
34
+
35
+ for line in content:
36
+ # 處理過長的行
37
+ if len(line) > width - 4:
38
+ line = line[:width - 7] + '...'
39
+ lines.append('│ ' + line.ljust(width - 4) + ' │')
40
+
41
+ lines.append('└' + '─' * (width - 2) + '┘')
42
+ return '\n'.join(lines)
43
+
44
+
45
+ def format_result(result: Dict[str, Any], domain: str) -> List[str]:
46
+ """
47
+ 格式化單個搜索結果
48
+ """
49
+ lines = []
50
+ score = result.get('_score', 0)
51
+ lines.append(f'Score: {score}')
52
+ lines.append('')
53
+
54
+ for key, value in result.items():
55
+ if key == '_score' or not value:
56
+ continue
57
+
58
+ # 截斷過長的值
59
+ value_str = str(value)
60
+ if len(value_str) > 60:
61
+ value_str = value_str[:57] + '...'
62
+
63
+ lines.append(f'{key}: {value_str}')
64
+
65
+ return lines
66
+
67
+
68
+ def format_domain_results(results: List[Dict[str, Any]], domain: str, query: str) -> str:
69
+ """
70
+ 格式化整個域的搜索結果
71
+ """
72
+ if not results:
73
+ return f"No results found in '{domain}' for query: {query}"
74
+
75
+ output = []
76
+ output.append(f"\n{'='*60}")
77
+ output.append(f"Domain: {domain.upper()} | Query: {query} | Results: {len(results)}")
78
+ output.append('='*60)
79
+
80
+ for i, result in enumerate(results, 1):
81
+ lines = format_result(result, domain)
82
+ box = format_ascii_box(f'Result {i}', lines, width=60)
83
+ output.append(box)
84
+ output.append('')
85
+
86
+ return '\n'.join(output)
87
+
88
+
89
+ def format_all_results(results: Dict[str, List[Dict[str, Any]]], query: str) -> str:
90
+ """
91
+ 格式化所有域的搜索結果
92
+ """
93
+ if not results:
94
+ return f"No results found for query: {query}"
95
+
96
+ output = []
97
+ output.append(f"\n{'#'*60}")
98
+ output.append(f"# SEARCH ALL DOMAINS: {query}")
99
+ output.append('#'*60)
100
+
101
+ for domain, domain_results in results.items():
102
+ output.append(format_domain_results(domain_results, domain, query))
103
+
104
+ return '\n'.join(output)
105
+
106
+
107
+ def list_domains():
108
+ """
109
+ 列出所有可用的搜索域
110
+ """
111
+ print("\n可用的搜索域 (Available Domains):")
112
+ print("="*50)
113
+
114
+ for domain in get_available_domains():
115
+ info = get_domain_info(domain)
116
+ if info:
117
+ print(f"\n {domain}")
118
+ print(f" 檔案: {info['file']}")
119
+ print(f" 記錄數: {info['total_records']}")
120
+ print(f" 搜索欄位: {', '.join(info['search_cols'])}")
121
+
122
+ print()
123
+
124
+
125
+ def main():
126
+ parser = argparse.ArgumentParser(
127
+ description='Taiwan Invoice Skill - BM25 Search Engine',
128
+ formatter_class=argparse.RawDescriptionHelpFormatter,
129
+ epilog="""
130
+ Examples:
131
+ python search.py "ecpay B2C" # Auto-detect domain
132
+ python search.py "開立發票" --domain operation # Search operations
133
+ python search.py "10000016" --domain error # Search error codes
134
+ python search.py "統編" --domain field # Search field mappings
135
+ python search.py "B2B 稅額" --domain tax # Search tax rules
136
+ python search.py "列印空白" --domain troubleshoot # Search troubleshooting
137
+ python search.py "ECPay" --all # Search all domains
138
+ python search.py --list # List available domains
139
+ """
140
+ )
141
+
142
+ parser.add_argument('query', nargs='?', help='Search query')
143
+ parser.add_argument('-d', '--domain', choices=get_available_domains(),
144
+ help='Search domain (auto-detect if not specified)')
145
+ parser.add_argument('-n', '--max-results', type=int, default=5,
146
+ help='Maximum results per domain (default: 5)')
147
+ parser.add_argument('-a', '--all', action='store_true',
148
+ help='Search all domains')
149
+ parser.add_argument('-l', '--list', action='store_true',
150
+ help='List available domains')
151
+ parser.add_argument('-f', '--format', choices=['ascii', 'simple', 'json'],
152
+ default='ascii', help='Output format (default: ascii)')
153
+
154
+ args = parser.parse_args()
155
+
156
+ # 列出域
157
+ if args.list:
158
+ list_domains()
159
+ return
160
+
161
+ # 檢查查詢
162
+ if not args.query:
163
+ parser.print_help()
164
+ return
165
+
166
+ query = args.query
167
+
168
+ # 搜索所有域
169
+ if args.all:
170
+ results = search_all(query, args.max_results)
171
+
172
+ if args.format == 'json':
173
+ import json
174
+ print(json.dumps(results, ensure_ascii=False, indent=2))
175
+ else:
176
+ print(format_all_results(results, query))
177
+ return
178
+
179
+ # 單域搜索
180
+ domain = args.domain
181
+ if not domain:
182
+ domain = detect_domain(query)
183
+ print(f"[Auto-detected domain: {domain}]")
184
+
185
+ results = search(query, domain, args.max_results)
186
+
187
+ if args.format == 'json':
188
+ import json
189
+ print(json.dumps(results, ensure_ascii=False, indent=2))
190
+ elif args.format == 'simple':
191
+ for i, result in enumerate(results, 1):
192
+ print(f"\n[{i}] Score: {result.get('_score', 0)}")
193
+ for key, value in result.items():
194
+ if key != '_score' and value:
195
+ print(f" {key}: {value}")
196
+ else:
197
+ print(format_domain_results(results, domain, query))
198
+
199
+
200
+ if __name__ == '__main__':
201
+ main()
@@ -0,0 +1,85 @@
1
+ ## When to Apply
2
+
3
+ Reference these guidelines when:
4
+ - Developing Taiwan E-Invoice issuance functionality
5
+ - Integrating ECPay, SmilePay, or Amego APIs
6
+ - Implementing B2C or B2B invoice logic
7
+ - Handling invoice printing, void, and allowance
8
+ - Troubleshooting invoice API integration issues
9
+
10
+ ## Provider Quick Reference
11
+
12
+ | Priority | Task | Impact | Provider |
13
+ |----------|------|--------|----------|
14
+ | 1 | Amount Calculation | CRITICAL | All |
15
+ | 2 | Encryption/Signature | CRITICAL | All |
16
+ | 3 | B2B vs B2C Logic | HIGH | All |
17
+ | 4 | Print Response Handling | HIGH | All |
18
+ | 5 | Provider Binding | MEDIUM | All |
19
+ | 6 | Error Handling | MEDIUM | All |
20
+ | 7 | Carrier/Donation | LOW | B2C only |
21
+
22
+ ## Quick Reference
23
+
24
+ ### 1. Amount Calculation (CRITICAL)
25
+
26
+ - `b2c-tax-inclusive` - B2C uses tax-inclusive total
27
+ - `b2b-split-tax` - B2B requires pre-tax + tax split
28
+ - `round-tax` - Round tax: `Math.round(total - (total / 1.05))`
29
+ - `salesamount` - ECPay/Amego: Use SalesAmount for pre-tax
30
+
31
+ ### 2. Encryption/Signature (CRITICAL)
32
+
33
+ - `ecpay-aes` - ECPay: AES-128-CBC with HashKey/HashIV
34
+ - `smilepay-verify` - SmilePay: Grvc + Verify_key params
35
+ - `amego-md5` - Amego: MD5(data + time + appKey)
36
+ - `url-encode` - Always URL encode before encryption
37
+
38
+ ### 3. B2B vs B2C Logic (HIGH)
39
+
40
+ - `buyer-id-b2c` - B2C: BuyerIdentifier = "0000000000"
41
+ - `buyer-id-b2b` - B2B: BuyerIdentifier = actual 8-digit tax ID
42
+ - `no-carrier-b2b` - B2B: Cannot use carrier or donation
43
+ - `validate-taxid` - Validate 8-digit tax ID format
44
+
45
+ ### 4. Print Response Handling (HIGH)
46
+
47
+ - `ecpay-html` - ECPay: Returns HTML, use window.document.write
48
+ - `smilepay-redirect` - SmilePay: Returns URL, use window.open
49
+ - `amego-pdf` - Amego: Returns PDF URL, use window.open
50
+ - `form-submit` - Some APIs require form POST submission
51
+
52
+ ### 5. Provider Binding (MEDIUM)
53
+
54
+ - `save-provider` - Save invoiceProvider when issuing
55
+ - `save-random` - Save invoiceRandomNum for printing
56
+ - `match-provider` - Use issuing provider for print/void
57
+
58
+ ### 6. Error Handling (MEDIUM)
59
+
60
+ - `log-raw-response` - Log complete raw response for debugging
61
+ - `ecpay-codes` - ECPay: Check RtnCode and RtnMsg
62
+ - `smilepay-codes` - SmilePay: Check Status field
63
+ - `amego-codes` - Amego: Check Code and Message
64
+
65
+ ### 7. Carrier/Donation (B2C only)
66
+
67
+ - `carrier-mobile` - Mobile barcode: /XXXXXXX format
68
+ - `carrier-npc` - Natural person certificate
69
+ - `donation-code` - Donation: 3-7 digit love code
70
+ - `mutual-exclusive` - Carrier and donation are mutually exclusive
71
+
72
+ ## Test Credentials
73
+
74
+ | Provider | Key Info |
75
+ |----------|----------|
76
+ | ECPay | MerchantID: 2000132, Stage URL |
77
+ | SmilePay | Grvc: SEI1000034, Test Tax ID: 80129529 |
78
+ | Amego | Tax ID: 12345678, test@amego.tw |
79
+
80
+ ## How to Use
81
+
82
+ See the full skill documentation for detailed API references and code examples.
83
+
84
+ ---
85
+
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "platform": "antigravity",
3
- "displayName": "Google Antigravity",
3
+ "displayName": "Antigravity / Generic Agent",
4
4
  "installType": "full",
5
5
  "folderStructure": {
6
6
  "root": ".agent",
7
7
  "skillPath": "skills/taiwan-invoice",
8
8
  "filename": "SKILL.md"
9
9
  },
10
+ "scriptPath": "skills/taiwan-invoice/scripts",
10
11
  "frontmatter": {
11
12
  "name": "taiwan-invoice",
12
13
  "description": "Taiwan E-Invoice API integration specialist for ECPay, SmilePay, and Amego. Provides B2C/B2B invoice issuance, void, allowance, query, and print functionality."
@@ -14,8 +15,10 @@
14
15
  "sections": {
15
16
  "examples": true,
16
17
  "references": true,
17
- "scripts": true
18
+ "scripts": true,
19
+ "quickReference": false
18
20
  },
19
21
  "title": "Taiwan E-Invoice Skill",
20
- "description": "Comprehensive guide for Taiwan E-Invoice API integration. Supports ECPay, SmilePay, and Amego providers with B2C/B2B invoice operations."
22
+ "description": "Comprehensive guide for Taiwan E-Invoice API integration. Supports ECPay, SmilePay, and Amego providers with B2C/B2B invoice operations.",
23
+ "skillOrWorkflow": "Skill"
21
24
  }
@@ -7,6 +7,7 @@
7
7
  "skillPath": "skills/taiwan-invoice",
8
8
  "filename": "SKILL.md"
9
9
  },
10
+ "scriptPath": "skills/taiwan-invoice/scripts",
10
11
  "frontmatter": {
11
12
  "name": "taiwan-invoice",
12
13
  "description": "Taiwan E-Invoice API integration specialist for ECPay, SmilePay, and Amego. Provides B2C/B2B invoice issuance, void, allowance, query, and print functionality. Includes encryption implementations (AES-128-CBC, MD5), tax calculations, and complete API specifications.",
@@ -15,8 +16,10 @@
15
16
  "sections": {
16
17
  "examples": true,
17
18
  "references": true,
18
- "scripts": true
19
+ "scripts": true,
20
+ "quickReference": true
19
21
  },
20
22
  "title": "Taiwan E-Invoice Skill",
21
- "description": "Comprehensive guide for Taiwan E-Invoice API integration. Supports ECPay, SmilePay, and Amego providers with B2C/B2B invoice operations."
23
+ "description": "Comprehensive guide for Taiwan E-Invoice API integration. Supports ECPay, SmilePay, and Amego providers with B2C/B2B invoice operations.",
24
+ "skillOrWorkflow": "Skill"
22
25
  }
@@ -7,12 +7,15 @@
7
7
  "skillPath": "skills/taiwan-invoice",
8
8
  "filename": "SKILL.md"
9
9
  },
10
+ "scriptPath": "skills/taiwan-invoice/scripts",
10
11
  "frontmatter": null,
11
12
  "sections": {
12
13
  "examples": true,
13
14
  "references": true,
14
- "scripts": true
15
+ "scripts": true,
16
+ "quickReference": false
15
17
  },
16
18
  "title": "Taiwan E-Invoice Skill",
17
- "description": "Comprehensive guide for Taiwan E-Invoice API integration. Supports ECPay, SmilePay, and Amego providers with B2C/B2B invoice operations."
19
+ "description": "Comprehensive guide for Taiwan E-Invoice API integration. Supports ECPay, SmilePay, and Amego providers with B2C/B2B invoice operations.",
20
+ "skillOrWorkflow": "Skill"
18
21
  }