| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- # add-token-config.ps1
- # 批量给所有 api-config.json 添加 tokenConfig + errorHandling
- # 并将 endpoint-based skill 的 Authorization 改为 {{vocToken}} 动态引用
- param(
- [string]$SkillsRoot = (Split-Path $PSScriptRoot -Parent),
- [switch]$DryRun
- )
- $utf8NoBom = New-Object System.Text.UTF8Encoding($false)
- $hardcodedToken = 'r:858b3ee92314d5447d1fc3cdc10462d7'
- # ============================================================
- # tokenConfig + errorHandling 块(插入到最后一个 } 之前)
- # ============================================================
- $injection = @'
- ,
- "tokenConfig": {
- "type": "bearer",
- "configFile": "~/.openclaw/voc-credentials.json",
- "tokenField": "vocToken",
- "currentToken": "r:858b3ee92314d5447d1fc3cdc10462d7",
- "resolutionOrder": ["configFile", "currentToken"],
- "onMissing": {
- "action": "showPaymentPrompt",
- "paymentUrl": "",
- "title": "需要配置 VOC-AI Token",
- "message": "此 Skill 需要有效的 VOC-AI Token 才能调用数据接口。",
- "setupInstructions": "充值成功后,请将获得的 Token(格式: r:xxxxxxxx)告知 AI,AI 将自动创建或更新 ~/.openclaw/voc-credentials.json,写入 {\"vocToken\": \"您的Token值\"} 并保存,后续所有 VOC Skills 将自动使用此 Token。"
- },
- "onBalanceInsufficient": {
- "action": "showPaymentPrompt",
- "paymentUrl": "",
- "title": "VOC-AI Token 余额不足",
- "message": "当前 Token 余额已不足以完成本次请求,请充值后告知 AI 更新 ~/.openclaw/voc-credentials.json 中的 vocToken 字段。"
- }
- },
- "errorHandling": {
- "balanceInsufficient": {
- "conditions": [
- { "responseField": "code", "operator": "in", "value": [-2, -3, -10, 402, 429] },
- { "responseField": "msg", "operator": "contains", "value": ["余额不足", "insufficient", "balance", "quota"] },
- { "responseField": "message", "operator": "contains", "value": ["余额不足", "insufficient", "balance"] }
- ],
- "matchMode": "any",
- "trigger": "tokenConfig.onBalanceInsufficient"
- },
- "unauthorized": {
- "conditions": [
- { "responseField": "code", "operator": "in", "value": [401, 403] },
- { "responseField": "msg", "operator": "contains", "value": ["unauthorized", "token", "invalid", "auth"] }
- ],
- "matchMode": "any",
- "trigger": "tokenConfig.onMissing"
- }
- }
- '@
- $categories = @("voc","social-media","competitor-analysis","review-analysis","synthesis","social-voc","douyin")
- $updated = 0
- $skipped = 0
- foreach ($cat in $categories) {
- $catPath = Join-Path $SkillsRoot $cat
- if (-not (Test-Path $catPath)) { continue }
- Get-ChildItem -Recurse -Filter "api-config.json" -Path $catPath | ForEach-Object {
- $filePath = $_.FullName
- $content = [System.IO.File]::ReadAllText($filePath, [System.Text.Encoding]::UTF8)
- # 跳过已处理的文件
- if ($content -match '"tokenConfig"') {
- Write-Host " [SKIP] already patched: $($filePath.Replace($SkillsRoot+'\',''))" -ForegroundColor DarkGray
- $skipped++
- return
- }
- # --- Step A: Authorization 改为 {{vocToken}}(仅 endpoint-based skill)---
- $hasEndpoint = $content -match '"endpoint"'
- if ($hasEndpoint) {
- $content = $content.Replace(
- "Bearer $hardcodedToken",
- "Bearer {{vocToken}}"
- )
- }
- # --- Step B: 插入 tokenConfig + errorHandling(最后一个 } 之前)---
- $lastBrace = $content.LastIndexOf('}')
- if ($lastBrace -lt 0) {
- Write-Host " [ERROR] malformed JSON: $filePath" -ForegroundColor Red
- return
- }
- $newContent = $content.Substring(0, $lastBrace) + $injection + "`n}"
- if ($DryRun) {
- Write-Host " [DRY] $($filePath.Replace($SkillsRoot+'\',''))" -ForegroundColor Yellow
- } else {
- [System.IO.File]::WriteAllText($filePath, $newContent, $utf8NoBom)
- Write-Host " [OK] $($filePath.Replace($SkillsRoot+'\',''))" -ForegroundColor Green
- }
- $updated++
- }
- }
- Write-Host ""
- Write-Host "Done: $updated updated, $skipped skipped"
- if ($DryRun) { Write-Host "Remove -DryRun to apply." -ForegroundColor Yellow }
|