pi-ccswitch-auto-switch 0.1.6 → 0.1.7

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 (3) hide show
  1. package/classify.ts +3 -1
  2. package/index.ts +10 -2
  3. package/package.json +1 -1
package/classify.ts CHANGED
@@ -17,7 +17,9 @@ export function classifyFailure(observation: FailureObservation): Classification
17
17
  const status = observation.status
18
18
  if (observation.aborted && !observation.watchdog) return { kind: 'unknown', roundOnly: true }
19
19
  if (observation.watchdog) return { kind: 'timeout', scope: 'endpoint', roundOnly: false }
20
- if (content.test(text)) return { kind: 'content_policy', roundOnly: true }
20
+ // 内容审查/敏感拦截属于该模型的失败:按 model 级记录并与冷却(2min×2ⁿ 上限 30min),
21
+ // chooseCandidate 会排除后自动切换到其他模型,而不是同一内容原样重试到本轮上限。
22
+ if (content.test(text)) return { kind: 'content_policy', scope: 'model', roundOnly: false }
21
23
  if (context.test(text)) return { kind: 'context_overflow', roundOnly: true }
22
24
  if (status === 429) return { kind: 'rate_limit', scope: 'provider', roundOnly: false, retryAfterMs: observation.retryAfterMs }
23
25
  if (status === 401 || status === 403) return { kind: 'auth', scope: 'provider', roundOnly: false }
package/index.ts CHANGED
@@ -32,6 +32,8 @@ interface Round {
32
32
  observation?: FailureObservation
33
33
  model?: ModelRef
34
34
  endpointFails?: EndpointFailTracker
35
+ /** 本轮内最后一次成功切换的时间;用于刷新 ROUND_LIMIT 窗口,避免供应商内部重试耗时导致误判“达到上限” */
36
+ lastSwitchAt?: number
35
37
  }
36
38
 
37
39
  function key(model: ModelRef | undefined): string | undefined { return model && modelKey(model) }
@@ -69,9 +71,11 @@ export default function (pi: ExtensionAPI) {
69
71
  const activeModel = round?.model ?? ctx.model
70
72
  // 恒显完整状态:健康/总数 · 冷却 · 禁用 · 本session切换 · 当前模型(均为 0 时也显示,便于确认扩展在监控中)
71
73
  const plain = round?.phase === 'switching' ? `CCS ↻${round.attempts}/${MAX_ATTEMPTS} ${modelTag(round.model)}` :
74
+ round?.phase === 'exhausted' ? `CCS ⏸切换停止 ${modelTag(round.model ?? ctx.model)}` :
72
75
  `CCS ✓${counts.healthy}/${counts.total} · ⏳${counts.cooling} · ⛔${counts.disabled}${switchSuffix()} · ${modelTag(activeModel)}`
73
76
  const theme = ctx.ui.theme
74
- ctx.ui.setStatus('ccswitch-ha', theme ? theme.fg(counts.cooling || counts.disabled ? 'warning' : 'success', plain) : plain)
77
+ const tone = round?.phase === 'exhausted' ? 'error' : counts.cooling || counts.disabled ? 'warning' : 'success'
78
+ ctx.ui.setStatus('ccswitch-ha', theme ? theme.fg(tone, plain) : plain)
75
79
  }
76
80
  // 本次 session 成功切换计数:始终显示 🔄N(N=0 也显示,用于确认扩展在监控中);累计切换数在面板/自检中可见
77
81
  const switchSuffix = () => ` · 🔄${sessionSwitches}`
@@ -140,7 +144,9 @@ export default function (pi: ExtensionAPI) {
140
144
  }
141
145
  const failover = async (ctx: ExtensionContext) => {
142
146
  if (!round || !round.observation || !round.model || !canRetry(ctx)) return
143
- if (round.attempts >= MAX_ATTEMPTS || Date.now() - round.startedAt >= ROUND_LIMIT) return exhaust(ctx, '达到本轮切换上限')
147
+ // 窗口从上一次成功切换(或本轮开始)起算:供应商内部重试耗时不应消耗整轮限额
148
+ const windowStart = Math.max(round.startedAt, round.lastSwitchAt ?? 0)
149
+ if (round.attempts >= MAX_ATTEMPTS || Date.now() - windowStart >= ROUND_LIMIT) return exhaust(ctx, '达到本轮切换上限')
144
150
  const classification = classifyFailure(round.observation)
145
151
  if (round.observation.aborted && !round.observation.watchdog) { round.phase = 'idle'; clearWatchdog(); status(ctx); return }
146
152
  round.phase = 'switching'
@@ -173,6 +179,8 @@ export default function (pi: ExtensionAPI) {
173
179
  }
174
180
  round.model = next
175
181
  round.phase = 'redispatching'
182
+ // 刷新本轮切换时间窗:成功切换后重新起算 ROUND_LIMIT,避免长重试轮被误判为“达到上限”
183
+ round.lastSwitchAt = Date.now()
176
184
  // 本次 session 成功切换计数 + 持久化累计/日志(衡量扩展有效程度)
177
185
  sessionSwitches += 1
178
186
  const fromKey = key(round.model ?? ctx.model)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ccswitch-auto-switch",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Provider-first automatic model failover extension for Pi and CC Switch",
5
5
  "license": "MIT",
6
6
  "keywords": [