@coool/opencode-adaptive 1.0.0 → 1.0.1

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 (380) hide show
  1. package/README.md +8 -7
  2. package/dist/adapters/codex-capacity/index.d.ts +0 -1
  3. package/dist/adapters/codex-capacity/index.js.map +1 -1
  4. package/dist/adapters/codex-capacity/parse.d.ts +2 -2
  5. package/dist/adapters/codex-capacity/parse.js +19 -3
  6. package/dist/adapters/codex-capacity/parse.js.map +1 -1
  7. package/dist/adapters/codex-capacity/reading.d.ts +0 -1
  8. package/dist/adapters/codex-capacity/reading.js.map +1 -1
  9. package/dist/adapters/codex-capacity/sensor.d.ts +0 -1
  10. package/dist/adapters/codex-capacity/sensor.js.map +1 -1
  11. package/dist/adapters/codex-capacity/types.d.ts +0 -4
  12. package/dist/adapters/codex-capacity/types.js +14 -0
  13. package/dist/adapters/codex-capacity/types.js.map +1 -1
  14. package/dist/adapters/opencode/escalation-tool.d.ts +0 -1
  15. package/dist/adapters/opencode/escalation-tool.js +5 -3
  16. package/dist/adapters/opencode/escalation-tool.js.map +1 -1
  17. package/dist/adapters/opencode/events.d.ts +0 -1
  18. package/dist/adapters/opencode/events.js.map +1 -1
  19. package/dist/adapters/opencode/hooks.d.ts +0 -1
  20. package/dist/adapters/opencode/hooks.js +24 -7
  21. package/dist/adapters/opencode/hooks.js.map +1 -1
  22. package/dist/adapters/opencode/index.d.ts +0 -1
  23. package/dist/adapters/opencode/index.js.map +1 -1
  24. package/dist/adapters/opencode/inventory.d.ts +0 -1
  25. package/dist/adapters/opencode/inventory.js.map +1 -1
  26. package/dist/adapters/opencode/report.d.ts +0 -1
  27. package/dist/adapters/opencode/report.js.map +1 -1
  28. package/dist/adapters/opencode/session-ops.d.ts +0 -1
  29. package/dist/adapters/opencode/session-ops.js.map +1 -1
  30. package/dist/adapters/opencode/storage.d.ts +0 -1
  31. package/dist/adapters/opencode/storage.js.map +1 -1
  32. package/dist/adapters/opencode/tier-tool.d.ts +0 -1
  33. package/dist/adapters/opencode/tier-tool.js.map +1 -1
  34. package/dist/adapters/opencode/types.d.ts +0 -1
  35. package/dist/adapters/opencode/types.js.map +1 -1
  36. package/dist/core/compatibility/gate.d.ts +0 -3
  37. package/dist/core/compatibility/gate.js +0 -4
  38. package/dist/core/compatibility/gate.js.map +1 -1
  39. package/dist/core/compatibility/index.d.ts +0 -1
  40. package/dist/core/compatibility/index.js.map +1 -1
  41. package/dist/core/compatibility/types.d.ts +0 -1
  42. package/dist/core/compatibility/types.js.map +1 -1
  43. package/dist/core/scheduler/admit.d.ts +0 -1
  44. package/dist/core/scheduler/admit.js +22 -21
  45. package/dist/core/scheduler/admit.js.map +1 -1
  46. package/dist/core/scheduler/escalate.d.ts +0 -1
  47. package/dist/core/scheduler/escalate.js +6 -17
  48. package/dist/core/scheduler/escalate.js.map +1 -1
  49. package/dist/core/scheduler/index.d.ts +0 -1
  50. package/dist/core/scheduler/index.js.map +1 -1
  51. package/dist/core/scheduler/mode.d.ts +0 -1
  52. package/dist/core/scheduler/mode.js.map +1 -1
  53. package/dist/core/scheduler/types.d.ts +2 -9
  54. package/dist/core/scheduler/types.js +2 -1
  55. package/dist/core/scheduler/types.js.map +1 -1
  56. package/dist/core/tier-policy/index.d.ts +0 -1
  57. package/dist/core/tier-policy/index.js.map +1 -1
  58. package/dist/core/tier-policy/resolve.d.ts +0 -1
  59. package/dist/core/tier-policy/resolve.js.map +1 -1
  60. package/dist/core/tier-policy/tier-list.d.ts +0 -1
  61. package/dist/core/tier-policy/tier-list.js.map +1 -1
  62. package/dist/core/tier-policy/types.d.ts +2 -1
  63. package/dist/core/tier-policy/types.js +4 -0
  64. package/dist/core/tier-policy/types.js.map +1 -1
  65. package/dist/core/work-unit/index.d.ts +0 -1
  66. package/dist/core/work-unit/index.js.map +1 -1
  67. package/dist/core/work-unit/interruption.d.ts +0 -1
  68. package/dist/core/work-unit/interruption.js.map +1 -1
  69. package/dist/core/work-unit/tracker.d.ts +11 -4
  70. package/dist/core/work-unit/tracker.js +26 -6
  71. package/dist/core/work-unit/tracker.js.map +1 -1
  72. package/dist/core/work-unit/types.d.ts +6 -1
  73. package/dist/core/work-unit/types.js.map +1 -1
  74. package/dist/execution/continuation/execute.d.ts +0 -1
  75. package/dist/execution/continuation/execute.js.map +1 -1
  76. package/dist/execution/continuation/index.d.ts +0 -2
  77. package/dist/execution/continuation/index.js +0 -1
  78. package/dist/execution/continuation/index.js.map +1 -1
  79. package/dist/execution/continuation/plan.d.ts +0 -1
  80. package/dist/execution/continuation/plan.js +1 -3
  81. package/dist/execution/continuation/plan.js.map +1 -1
  82. package/dist/execution/continuation/prompts.d.ts +0 -1
  83. package/dist/execution/continuation/prompts.js.map +1 -1
  84. package/dist/execution/continuation/types.d.ts +0 -2
  85. package/dist/execution/continuation/types.js.map +1 -1
  86. package/dist/execution/escalation/index.d.ts +0 -1
  87. package/dist/execution/escalation/index.js.map +1 -1
  88. package/dist/execution/escalation/types.d.ts +0 -1
  89. package/dist/execution/escalation/types.js.map +1 -1
  90. package/dist/execution/index.d.ts +0 -1
  91. package/dist/execution/index.js.map +1 -1
  92. package/dist/execution/parking/index.d.ts +0 -1
  93. package/dist/execution/parking/index.js.map +1 -1
  94. package/dist/execution/parking/plan.d.ts +0 -1
  95. package/dist/execution/parking/plan.js.map +1 -1
  96. package/dist/execution/retry/decide.d.ts +0 -1
  97. package/dist/execution/retry/decide.js +1 -2
  98. package/dist/execution/retry/decide.js.map +1 -1
  99. package/dist/execution/retry/index.d.ts +0 -1
  100. package/dist/execution/retry/index.js.map +1 -1
  101. package/dist/execution/retry/types.d.ts +0 -2
  102. package/dist/execution/retry/types.js.map +1 -1
  103. package/dist/gui-experimental.cjs +1 -1
  104. package/dist/gui.d.ts +0 -1
  105. package/dist/gui.js +6 -3
  106. package/dist/gui.js.map +1 -1
  107. package/dist/health/capacity/index.d.ts +0 -1
  108. package/dist/health/capacity/index.js.map +1 -1
  109. package/dist/health/capacity/merge.d.ts +0 -1
  110. package/dist/health/capacity/merge.js.map +1 -1
  111. package/dist/health/capacity/registry.d.ts +0 -1
  112. package/dist/health/capacity/registry.js.map +1 -1
  113. package/dist/health/capacity/types.d.ts +0 -1
  114. package/dist/health/capacity/types.js.map +1 -1
  115. package/dist/health/circuit-breaker/breaker.d.ts +8 -1
  116. package/dist/health/circuit-breaker/breaker.js +18 -0
  117. package/dist/health/circuit-breaker/breaker.js.map +1 -1
  118. package/dist/health/circuit-breaker/index.d.ts +0 -1
  119. package/dist/health/circuit-breaker/index.js.map +1 -1
  120. package/dist/health/circuit-breaker/types.d.ts +0 -1
  121. package/dist/health/circuit-breaker/types.js.map +1 -1
  122. package/dist/health/classifier/classify.d.ts +0 -1
  123. package/dist/health/classifier/classify.js.map +1 -1
  124. package/dist/health/classifier/index.d.ts +0 -1
  125. package/dist/health/classifier/index.js.map +1 -1
  126. package/dist/health/classifier/types.d.ts +0 -1
  127. package/dist/health/classifier/types.js.map +1 -1
  128. package/dist/health/index.d.ts +0 -1
  129. package/dist/health/index.js.map +1 -1
  130. package/dist/health/resource-health/index.d.ts +0 -1
  131. package/dist/health/resource-health/index.js.map +1 -1
  132. package/dist/health/resource-health/key.d.ts +0 -1
  133. package/dist/health/resource-health/key.js.map +1 -1
  134. package/dist/health/resource-health/registry.d.ts +6 -1
  135. package/dist/health/resource-health/registry.js +19 -1
  136. package/dist/health/resource-health/registry.js.map +1 -1
  137. package/dist/health/resource-health/transitions.d.ts +2 -4
  138. package/dist/health/resource-health/transitions.js +10 -18
  139. package/dist/health/resource-health/transitions.js.map +1 -1
  140. package/dist/health/resource-health/types.d.ts +7 -1
  141. package/dist/health/resource-health/types.js +1 -0
  142. package/dist/health/resource-health/types.js.map +1 -1
  143. package/dist/index.d.ts +0 -6
  144. package/dist/index.js +44 -19
  145. package/dist/index.js.map +1 -1
  146. package/dist/plugin-id.d.ts +0 -1
  147. package/dist/plugin-id.js.map +1 -1
  148. package/dist/rpc/definition.d.ts +24 -1
  149. package/dist/rpc/definition.js +28 -2
  150. package/dist/rpc/definition.js.map +1 -1
  151. package/dist/rpc/handlers.d.ts +12 -24
  152. package/dist/rpc/handlers.js +22 -8
  153. package/dist/rpc/handlers.js.map +1 -1
  154. package/dist/rpc/status.d.ts +0 -1
  155. package/dist/rpc/status.js.map +1 -1
  156. package/dist/rpc.d.ts +0 -1
  157. package/dist/rpc.js.map +1 -1
  158. package/dist/state/capacity/index.d.ts +0 -1
  159. package/dist/state/capacity/index.js.map +1 -1
  160. package/dist/state/capacity/parse.d.ts +0 -1
  161. package/dist/state/capacity/parse.js +14 -2
  162. package/dist/state/capacity/parse.js.map +1 -1
  163. package/dist/state/capacity/store.d.ts +0 -1
  164. package/dist/state/capacity/store.js +16 -2
  165. package/dist/state/capacity/store.js.map +1 -1
  166. package/dist/state/capacity/types.d.ts +0 -1
  167. package/dist/state/capacity/types.js.map +1 -1
  168. package/dist/state/health/index.d.ts +0 -1
  169. package/dist/state/health/index.js.map +1 -1
  170. package/dist/state/health/parse.d.ts +0 -1
  171. package/dist/state/health/parse.js +20 -4
  172. package/dist/state/health/parse.js.map +1 -1
  173. package/dist/state/health/store.d.ts +0 -1
  174. package/dist/state/health/store.js +16 -2
  175. package/dist/state/health/store.js.map +1 -1
  176. package/dist/state/health/types.d.ts +0 -1
  177. package/dist/state/health/types.js.map +1 -1
  178. package/dist/state/parked-work/index.d.ts +0 -1
  179. package/dist/state/parked-work/index.js.map +1 -1
  180. package/dist/state/parked-work/parse.d.ts +0 -1
  181. package/dist/state/parked-work/parse.js.map +1 -1
  182. package/dist/state/parked-work/store.d.ts +0 -1
  183. package/dist/state/parked-work/store.js +20 -3
  184. package/dist/state/parked-work/store.js.map +1 -1
  185. package/dist/state/parked-work/types.d.ts +0 -1
  186. package/dist/state/parked-work/types.js.map +1 -1
  187. package/dist/state/receipts/bound.d.ts +0 -1
  188. package/dist/state/receipts/bound.js.map +1 -1
  189. package/dist/state/receipts/index.d.ts +0 -1
  190. package/dist/state/receipts/index.js.map +1 -1
  191. package/dist/state/receipts/parse.d.ts +0 -1
  192. package/dist/state/receipts/parse.js.map +1 -1
  193. package/dist/state/receipts/store.d.ts +0 -1
  194. package/dist/state/receipts/store.js +24 -4
  195. package/dist/state/receipts/store.js.map +1 -1
  196. package/dist/state/receipts/types.d.ts +0 -1
  197. package/dist/state/receipts/types.js.map +1 -1
  198. package/dist/state/session-modes/index.d.ts +0 -1
  199. package/dist/state/session-modes/index.js.map +1 -1
  200. package/dist/state/session-modes/parse.d.ts +0 -1
  201. package/dist/state/session-modes/parse.js.map +1 -1
  202. package/dist/state/session-modes/store.d.ts +0 -1
  203. package/dist/state/session-modes/store.js +15 -1
  204. package/dist/state/session-modes/store.js.map +1 -1
  205. package/dist/state/session-modes/types.d.ts +0 -1
  206. package/dist/state/session-modes/types.js.map +1 -1
  207. package/dist/state/settings/index.d.ts +0 -1
  208. package/dist/state/settings/index.js.map +1 -1
  209. package/dist/state/settings/parse.d.ts +0 -1
  210. package/dist/state/settings/parse.js.map +1 -1
  211. package/dist/state/settings/store.d.ts +0 -1
  212. package/dist/state/settings/store.js +9 -1
  213. package/dist/state/settings/store.js.map +1 -1
  214. package/dist/state/settings/types.d.ts +0 -1
  215. package/dist/state/settings/types.js.map +1 -1
  216. package/dist/state/tier-requests/index.d.ts +4 -0
  217. package/dist/state/tier-requests/index.js +4 -0
  218. package/dist/state/tier-requests/index.js.map +1 -0
  219. package/dist/state/tier-requests/parse.d.ts +3 -0
  220. package/dist/state/tier-requests/parse.js +53 -0
  221. package/dist/state/tier-requests/parse.js.map +1 -0
  222. package/dist/state/tier-requests/store.d.ts +27 -0
  223. package/dist/state/tier-requests/store.js +96 -0
  224. package/dist/state/tier-requests/store.js.map +1 -0
  225. package/dist/state/tier-requests/types.d.ts +30 -0
  226. package/dist/state/tier-requests/types.js +7 -0
  227. package/dist/state/tier-requests/types.js.map +1 -0
  228. package/dist/supervisor/index.d.ts +0 -1
  229. package/dist/supervisor/index.js.map +1 -1
  230. package/dist/supervisor/log.d.ts +0 -1
  231. package/dist/supervisor/log.js.map +1 -1
  232. package/dist/supervisor/supervisor.d.ts +23 -6
  233. package/dist/supervisor/supervisor.js +397 -111
  234. package/dist/supervisor/supervisor.js.map +1 -1
  235. package/dist/supervisor/types.d.ts +0 -1
  236. package/dist/supervisor/types.js.map +1 -1
  237. package/dist/supervisor/view.d.ts +0 -1
  238. package/dist/supervisor/view.js.map +1 -1
  239. package/dist/tui.d.ts +0 -1
  240. package/dist/tui.js +14 -10
  241. package/dist/tui.js.map +1 -1
  242. package/dist/ui/gui/api.d.ts +0 -1
  243. package/dist/ui/gui/api.js.map +1 -1
  244. package/dist/ui/gui/view.d.ts +0 -1
  245. package/dist/ui/gui/view.js.map +1 -1
  246. package/dist/ui/tui/controller.d.ts +0 -1
  247. package/dist/ui/tui/controller.js +28 -12
  248. package/dist/ui/tui/controller.js.map +1 -1
  249. package/dist/ui/tui/menu.d.ts +1 -2
  250. package/dist/ui/tui/menu.js +2 -2
  251. package/dist/ui/tui/menu.js.map +1 -1
  252. package/dist/ui/tui/options.d.ts +0 -1
  253. package/dist/ui/tui/options.js.map +1 -1
  254. package/dist/ui/tui/receipts.d.ts +0 -1
  255. package/dist/ui/tui/receipts.js +4 -1
  256. package/dist/ui/tui/receipts.js.map +1 -1
  257. package/dist/ui/tui/status.d.ts +1 -2
  258. package/dist/ui/tui/status.js +4 -2
  259. package/dist/ui/tui/status.js.map +1 -1
  260. package/dist/ui/tui/tiers.d.ts +0 -1
  261. package/dist/ui/tui/tiers.js.map +1 -1
  262. package/package.json +2 -2
  263. package/dist/adapters/codex-capacity/index.d.ts.map +0 -1
  264. package/dist/adapters/codex-capacity/parse.d.ts.map +0 -1
  265. package/dist/adapters/codex-capacity/reading.d.ts.map +0 -1
  266. package/dist/adapters/codex-capacity/sensor.d.ts.map +0 -1
  267. package/dist/adapters/codex-capacity/types.d.ts.map +0 -1
  268. package/dist/adapters/opencode/escalation-tool.d.ts.map +0 -1
  269. package/dist/adapters/opencode/events.d.ts.map +0 -1
  270. package/dist/adapters/opencode/hooks.d.ts.map +0 -1
  271. package/dist/adapters/opencode/index.d.ts.map +0 -1
  272. package/dist/adapters/opencode/inventory.d.ts.map +0 -1
  273. package/dist/adapters/opencode/report.d.ts.map +0 -1
  274. package/dist/adapters/opencode/session-ops.d.ts.map +0 -1
  275. package/dist/adapters/opencode/storage.d.ts.map +0 -1
  276. package/dist/adapters/opencode/tier-tool.d.ts.map +0 -1
  277. package/dist/adapters/opencode/types.d.ts.map +0 -1
  278. package/dist/core/compatibility/gate.d.ts.map +0 -1
  279. package/dist/core/compatibility/index.d.ts.map +0 -1
  280. package/dist/core/compatibility/types.d.ts.map +0 -1
  281. package/dist/core/scheduler/admit.d.ts.map +0 -1
  282. package/dist/core/scheduler/escalate.d.ts.map +0 -1
  283. package/dist/core/scheduler/index.d.ts.map +0 -1
  284. package/dist/core/scheduler/mode.d.ts.map +0 -1
  285. package/dist/core/scheduler/types.d.ts.map +0 -1
  286. package/dist/core/tier-policy/index.d.ts.map +0 -1
  287. package/dist/core/tier-policy/resolve.d.ts.map +0 -1
  288. package/dist/core/tier-policy/tier-list.d.ts.map +0 -1
  289. package/dist/core/tier-policy/types.d.ts.map +0 -1
  290. package/dist/core/work-unit/index.d.ts.map +0 -1
  291. package/dist/core/work-unit/interruption.d.ts.map +0 -1
  292. package/dist/core/work-unit/tracker.d.ts.map +0 -1
  293. package/dist/core/work-unit/types.d.ts.map +0 -1
  294. package/dist/execution/continuation/execute.d.ts.map +0 -1
  295. package/dist/execution/continuation/index.d.ts.map +0 -1
  296. package/dist/execution/continuation/ledger.d.ts +0 -20
  297. package/dist/execution/continuation/ledger.d.ts.map +0 -1
  298. package/dist/execution/continuation/ledger.js +0 -31
  299. package/dist/execution/continuation/ledger.js.map +0 -1
  300. package/dist/execution/continuation/plan.d.ts.map +0 -1
  301. package/dist/execution/continuation/prompts.d.ts.map +0 -1
  302. package/dist/execution/continuation/types.d.ts.map +0 -1
  303. package/dist/execution/escalation/index.d.ts.map +0 -1
  304. package/dist/execution/escalation/types.d.ts.map +0 -1
  305. package/dist/execution/index.d.ts.map +0 -1
  306. package/dist/execution/parking/index.d.ts.map +0 -1
  307. package/dist/execution/parking/plan.d.ts.map +0 -1
  308. package/dist/execution/recovery/gate.d.ts +0 -20
  309. package/dist/execution/recovery/gate.d.ts.map +0 -1
  310. package/dist/execution/recovery/gate.js +0 -23
  311. package/dist/execution/recovery/gate.js.map +0 -1
  312. package/dist/execution/recovery/index.d.ts +0 -3
  313. package/dist/execution/recovery/index.d.ts.map +0 -1
  314. package/dist/execution/recovery/index.js +0 -2
  315. package/dist/execution/recovery/index.js.map +0 -1
  316. package/dist/execution/retry/decide.d.ts.map +0 -1
  317. package/dist/execution/retry/index.d.ts.map +0 -1
  318. package/dist/execution/retry/types.d.ts.map +0 -1
  319. package/dist/gui.d.ts.map +0 -1
  320. package/dist/health/capacity/index.d.ts.map +0 -1
  321. package/dist/health/capacity/merge.d.ts.map +0 -1
  322. package/dist/health/capacity/registry.d.ts.map +0 -1
  323. package/dist/health/capacity/types.d.ts.map +0 -1
  324. package/dist/health/circuit-breaker/breaker.d.ts.map +0 -1
  325. package/dist/health/circuit-breaker/index.d.ts.map +0 -1
  326. package/dist/health/circuit-breaker/types.d.ts.map +0 -1
  327. package/dist/health/classifier/classify.d.ts.map +0 -1
  328. package/dist/health/classifier/index.d.ts.map +0 -1
  329. package/dist/health/classifier/types.d.ts.map +0 -1
  330. package/dist/health/index.d.ts.map +0 -1
  331. package/dist/health/resource-health/index.d.ts.map +0 -1
  332. package/dist/health/resource-health/key.d.ts.map +0 -1
  333. package/dist/health/resource-health/registry.d.ts.map +0 -1
  334. package/dist/health/resource-health/transitions.d.ts.map +0 -1
  335. package/dist/health/resource-health/types.d.ts.map +0 -1
  336. package/dist/index.d.ts.map +0 -1
  337. package/dist/plugin-id.d.ts.map +0 -1
  338. package/dist/rpc/definition.d.ts.map +0 -1
  339. package/dist/rpc/handlers.d.ts.map +0 -1
  340. package/dist/rpc/status.d.ts.map +0 -1
  341. package/dist/rpc.d.ts.map +0 -1
  342. package/dist/state/capacity/index.d.ts.map +0 -1
  343. package/dist/state/capacity/parse.d.ts.map +0 -1
  344. package/dist/state/capacity/store.d.ts.map +0 -1
  345. package/dist/state/capacity/types.d.ts.map +0 -1
  346. package/dist/state/health/index.d.ts.map +0 -1
  347. package/dist/state/health/parse.d.ts.map +0 -1
  348. package/dist/state/health/store.d.ts.map +0 -1
  349. package/dist/state/health/types.d.ts.map +0 -1
  350. package/dist/state/parked-work/index.d.ts.map +0 -1
  351. package/dist/state/parked-work/parse.d.ts.map +0 -1
  352. package/dist/state/parked-work/store.d.ts.map +0 -1
  353. package/dist/state/parked-work/types.d.ts.map +0 -1
  354. package/dist/state/receipts/bound.d.ts.map +0 -1
  355. package/dist/state/receipts/index.d.ts.map +0 -1
  356. package/dist/state/receipts/parse.d.ts.map +0 -1
  357. package/dist/state/receipts/store.d.ts.map +0 -1
  358. package/dist/state/receipts/types.d.ts.map +0 -1
  359. package/dist/state/session-modes/index.d.ts.map +0 -1
  360. package/dist/state/session-modes/parse.d.ts.map +0 -1
  361. package/dist/state/session-modes/store.d.ts.map +0 -1
  362. package/dist/state/session-modes/types.d.ts.map +0 -1
  363. package/dist/state/settings/index.d.ts.map +0 -1
  364. package/dist/state/settings/parse.d.ts.map +0 -1
  365. package/dist/state/settings/store.d.ts.map +0 -1
  366. package/dist/state/settings/types.d.ts.map +0 -1
  367. package/dist/supervisor/index.d.ts.map +0 -1
  368. package/dist/supervisor/log.d.ts.map +0 -1
  369. package/dist/supervisor/supervisor.d.ts.map +0 -1
  370. package/dist/supervisor/types.d.ts.map +0 -1
  371. package/dist/supervisor/view.d.ts.map +0 -1
  372. package/dist/tui.d.ts.map +0 -1
  373. package/dist/ui/gui/api.d.ts.map +0 -1
  374. package/dist/ui/gui/view.d.ts.map +0 -1
  375. package/dist/ui/tui/controller.d.ts.map +0 -1
  376. package/dist/ui/tui/menu.d.ts.map +0 -1
  377. package/dist/ui/tui/options.d.ts.map +0 -1
  378. package/dist/ui/tui/receipts.d.ts.map +0 -1
  379. package/dist/ui/tui/status.d.ts.map +0 -1
  380. package/dist/ui/tui/tiers.d.ts.map +0 -1
@@ -73,6 +73,14 @@ export declare function recordProbeSuccess(record: BreakerRecord): BreakerRecord
73
73
  * the registry's assessment sweep — there are no timers.
74
74
  */
75
75
  export declare function expireProbe(record: BreakerRecord, now: number, config: BreakerConfig): BreakerRecord;
76
+ /**
77
+ * Returns an admitted probe that was never dispatched (the admission picked
78
+ * another resource, only observed, or failed to switch). No request ran, so
79
+ * this is no evidence at all: the breaker goes back to open with the window
80
+ * it was admitted under — still due — instead of restarting the backoff,
81
+ * which would push a passed-over resource back on every admission.
82
+ */
83
+ export declare function releaseProbe(record: BreakerRecord): BreakerRecord;
76
84
  /**
77
85
  * Records a failed probe. A non-exempt failure reopens the breaker with a
78
86
  * doubled backoff. An exempt failure (the probe was rate limited or quota
@@ -81,4 +89,3 @@ export declare function expireProbe(record: BreakerRecord, now: number, config:
81
89
  * overstate the failure.
82
90
  */
83
91
  export declare function recordProbeFailure(record: BreakerRecord, category: FailureCategory, now: number, config: BreakerConfig): BreakerRecord;
84
- //# sourceMappingURL=breaker.d.ts.map
@@ -113,6 +113,24 @@ export function expireProbe(record, now, config) {
113
113
  }
114
114
  return openBreaker(record, record.openCount, now, config);
115
115
  }
116
+ /**
117
+ * Returns an admitted probe that was never dispatched (the admission picked
118
+ * another resource, only observed, or failed to switch). No request ran, so
119
+ * this is no evidence at all: the breaker goes back to open with the window
120
+ * it was admitted under — still due — instead of restarting the backoff,
121
+ * which would push a passed-over resource back on every admission.
122
+ */
123
+ export function releaseProbe(record) {
124
+ if (record.state !== "half_open") {
125
+ return record;
126
+ }
127
+ return {
128
+ state: "open",
129
+ failures: record.failures,
130
+ openCount: record.openCount,
131
+ ...(record.probeAt !== undefined ? { reopenAt: record.probeAt } : {}),
132
+ };
133
+ }
116
134
  /**
117
135
  * Records a failed probe. A non-exempt failure reopens the breaker with a
118
136
  * doubled backoff. An exempt failure (the probe was rate limited or quota
@@ -1 +1 @@
1
- {"version":3,"file":"breaker.js","sourceRoot":"","sources":["../../../src/health/circuit-breaker/breaker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"breaker.js","sourceRoot":"","sources":["../../../src/health/circuit-breaker/breaker.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure circuit breaker state machine (ADP-019).\n *\n * All functions are total, synchronous, and clock-free: `now` is always an\n * injected parameter. The single-probe guarantee comes from the admission\n * protocol: `admitProbe` synchronously transitions an open (and due) breaker\n * to half-open, so the second concurrent caller observes `half_open` and is\n * blocked — there is never an await between the state check and the\n * transition. Callers must persist the returned record immediately.\n */\nimport type { FailureCategory } from \"../classifier/types.js\"\nimport { BREAKER_EXEMPT_CATEGORIES, type BreakerConfig, type BreakerRecord } from \"./types.js\"\n\nexport function initialBreaker(): BreakerRecord {\n return { state: \"closed\", failures: 0, openCount: 0 }\n}\n\n/**\n * Backoff window for the `openCount`-th opening: doubling, capped at\n * `maxBackoffMs` so a persistently failing resource never waits longer than\n * the configured ceiling.\n */\nfunction backoffMs(openCount: number, config: BreakerConfig): number {\n return Math.min(config.baseOpenMs * 2 ** (openCount - 1), config.maxBackoffMs)\n}\n\nfunction openBreaker(\n record: BreakerRecord,\n openCount: number,\n now: number,\n config: BreakerConfig,\n): BreakerRecord {\n return {\n state: \"open\",\n failures: record.failures,\n openCount,\n reopenAt: now + backoffMs(openCount, config),\n }\n}\n\nexport interface BreakerFailureResult {\n readonly record: BreakerRecord\n /** True exactly when this failure tripped the breaker from closed to open. */\n readonly opened: boolean\n}\n\n/**\n * Records a countable failure. Callers route only infrastructure failures\n * here (the resource-health transitions layer sends outage, overload, and\n * timeout); the breaker additionally exempts rate limiting and quota\n * exhaustion, which own their windowed resource states. Failures observed\n * while the breaker is not closed cannot happen through the admission\n * protocol (non-probe callers are blocked) and are ignored defensively.\n */\nexport function recordBreakerFailure(\n record: BreakerRecord,\n category: FailureCategory,\n now: number,\n config: BreakerConfig,\n): BreakerFailureResult {\n if (BREAKER_EXEMPT_CATEGORIES.includes(category) || record.state !== \"closed\") {\n return { record, opened: false }\n }\n const failures = record.failures + 1\n if (failures < config.failureThreshold) {\n return { record: { ...record, failures }, opened: false }\n }\n return {\n record: openBreaker({ ...record, failures }, record.openCount + 1, now, config),\n opened: true,\n }\n}\n\n/**\n * Observed success closes the breaker and resets the failure/backoff state.\n * Evidence beats inference: a success is proof the resource works, from any\n * prior breaker state.\n */\nexport function recordBreakerSuccess(): BreakerRecord {\n return { state: \"closed\", failures: 0, openCount: 0 }\n}\n\nexport type ProbeAdmission =\n | { kind: \"closed\"; record: BreakerRecord }\n | { kind: \"waiting\"; record: BreakerRecord; retryAtMs: number }\n | { kind: \"in-flight\"; record: BreakerRecord }\n | { kind: \"admitted\"; record: BreakerRecord }\n\n/**\n * Attempts to admit the single half-open probe. Callers must persist the\n * returned record synchronously; the returned record carries no probeId — the\n * registry stamps its own ticket id on the persisted copy.\n */\n/**\n * Non-mutating wait computation for an open breaker, admission view: the\n * remaining backoff in ms, or `undefined` when the window has elapsed (or the\n * record is not open). Used to decide whether a probe may be admitted.\n */\nexport function breakerWait(record: BreakerRecord, now: number): number | undefined {\n if (record.state !== \"open\") return undefined\n const reopenAt = record.reopenAt\n if (reopenAt !== undefined && now < reopenAt) return reopenAt - now\n return undefined\n}\n\n/**\n * Non-mutating block computation for an open breaker, observer view: an open\n * breaker blocks regardless of elapsed backoff — recovery counts only once a\n * probe proved it — so an elapsed (or, unreachable through the state machine,\n * missing) stamp simply means zero remaining wait.\n */\nexport function breakerBlockWait(record: BreakerRecord, now: number): number | undefined {\n if (record.state !== \"open\") return undefined\n return Math.max(0, (record.reopenAt ?? 0) - now)\n}\n\nexport function admitProbe(record: BreakerRecord, now: number): ProbeAdmission {\n if (record.state === \"closed\") {\n return { kind: \"closed\", record }\n }\n if (record.state === \"half_open\") {\n return { kind: \"in-flight\", record }\n }\n const wait = breakerWait(record, now)\n if (wait !== undefined) {\n return { kind: \"waiting\", record, retryAtMs: wait }\n }\n return {\n kind: \"admitted\",\n record: { state: \"half_open\", failures: record.failures, openCount: record.openCount },\n }\n}\n\n/** Closes the breaker when a probe report confirms recovery. */\nexport function recordProbeSuccess(record: BreakerRecord): BreakerRecord {\n if (record.state !== \"half_open\") {\n return record\n }\n return { state: \"closed\", failures: 0, openCount: 0 }\n}\n\n/**\n * Expires a probe whose episode never reported an outcome. A lost probe is\n * no health evidence: the breaker re-arms the SAME backoff window (no\n * doubling) so a fresh probe can be admitted after it. Evaluated lazily by\n * the registry's assessment sweep — there are no timers.\n */\nexport function expireProbe(\n record: BreakerRecord,\n now: number,\n config: BreakerConfig,\n): BreakerRecord {\n if (\n record.state !== \"half_open\" ||\n record.probeAt === undefined ||\n now - record.probeAt < config.probeTimeoutMs\n ) {\n return record\n }\n return openBreaker(record, record.openCount, now, config)\n}\n\n/**\n * Returns an admitted probe that was never dispatched (the admission picked\n * another resource, only observed, or failed to switch). No request ran, so\n * this is no evidence at all: the breaker goes back to open with the window\n * it was admitted under — still due — instead of restarting the backoff,\n * which would push a passed-over resource back on every admission.\n */\nexport function releaseProbe(record: BreakerRecord): BreakerRecord {\n if (record.state !== \"half_open\") {\n return record\n }\n return {\n state: \"open\",\n failures: record.failures,\n openCount: record.openCount,\n ...(record.probeAt !== undefined ? { reopenAt: record.probeAt } : {}),\n }\n}\n\n/**\n * Records a failed probe. A non-exempt failure reopens the breaker with a\n * doubled backoff. An exempt failure (the probe was rate limited or quota\n * blocked) re-arms the same backoff window without escalation: the resource\n * was rejected for demand reasons, not degraded health, so doubling would\n * overstate the failure.\n */\nexport function recordProbeFailure(\n record: BreakerRecord,\n category: FailureCategory,\n now: number,\n config: BreakerConfig,\n): BreakerRecord {\n if (record.state !== \"half_open\") {\n return record\n }\n if (BREAKER_EXEMPT_CATEGORIES.includes(category)) {\n return openBreaker(record, record.openCount, now, config)\n }\n return openBreaker(record, record.openCount + 1, now, config)\n}\n"]}
@@ -1,3 +1,2 @@
1
1
  export * from "./breaker.js";
2
2
  export * from "./types.js";
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/health/circuit-breaker/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/health/circuit-breaker/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA","sourcesContent":["export * from \"./breaker.js\"\nexport * from \"./types.js\"\n"]}
@@ -50,4 +50,3 @@ export interface BreakerRecord {
50
50
  readonly probeId?: string | undefined;
51
51
  readonly probeAt?: number | undefined;
52
52
  }
53
- //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/health/circuit-breaker/types.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAsC,CAAA;AAoBlG,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,gBAAgB,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM;IAClB,YAAY,EAAE,SAAS;IACvB,cAAc,EAAE,OAAO;CACxB,CAAA;AAED,MAAM,CAAC,MAAM,yBAAyB,GAA+B;IACnE,cAAc;IACd,iBAAiB;IACjB,gBAAgB;CACjB,CAAA"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/health/circuit-breaker/types.ts"],"names":[],"mappings":"AAaA,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAsC,CAAA;AAoBlG,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,gBAAgB,EAAE,CAAC;IACnB,UAAU,EAAE,MAAM;IAClB,YAAY,EAAE,SAAS;IACvB,cAAc,EAAE,OAAO;CACxB,CAAA;AAED,MAAM,CAAC,MAAM,yBAAyB,GAA+B;IACnE,cAAc;IACd,iBAAiB;IACjB,gBAAgB;CACjB,CAAA","sourcesContent":["/**\n * Circuit breaker types (ADP-019).\n *\n * The breaker is the quarantine mechanism for transient infrastructure\n * failures (outage, overload, timeout): repeated failures open the resource\n * for a backoff window, after which exactly one probe request is admitted\n * (half-open state). Rate limiting and quota exhaustion are deliberately\n * exempt from breaker counting because they already have their own windowed\n * resource states; counting them here would double-punish a resource that is\n * already known to need a cooldown.\n */\nimport type { FailureCategory } from \"../classifier/types.js\"\n\nexport const BREAKER_STATES = [\"closed\", \"open\", \"half_open\"] as const satisfies readonly string[]\n\nexport type BreakerState = (typeof BREAKER_STATES)[number]\n\nexport interface BreakerConfig {\n /** Consecutive countable failures in the closed state that trip the breaker. */\n readonly failureThreshold: number\n /** Backoff for the first opening; doubles on each reopening, capped below. */\n readonly baseOpenMs: number\n /** Upper bound for the backoff window. */\n readonly maxBackoffMs: number\n /**\n * How long a half-open probe may stay unreported before assessment treats\n * it as lost. Generous by design: a probe episode is a real work unit and\n * may run for minutes; the deadline only exists so a probe whose terminal\n * event never arrives cannot wedge the resource in half_open forever.\n */\n readonly probeTimeoutMs: number\n}\n\nexport const DEFAULT_BREAKER_CONFIG: BreakerConfig = {\n failureThreshold: 5,\n baseOpenMs: 30_000,\n maxBackoffMs: 1_800_000,\n probeTimeoutMs: 600_000,\n}\n\nexport const BREAKER_EXEMPT_CATEGORIES: readonly FailureCategory[] = [\n \"rate_limited\",\n \"quota_exhausted\",\n \"user_cancelled\",\n]\n\n/**\n * Persistent breaker record for one resource. `openCount` drives the doubling\n * backoff and resets only when the breaker closes (a probe or an observed\n * success). Rate limiting, quota exhaustion and user cancellation are\n * deliberately exempt from breaker counting: the first two own their own\n * windowed resource states (counting them would double-punish a resource\n * already known to need a cooldown), and a user-interrupted probe says\n * nothing about resource health, so an interrupted probe re-arms the same\n * window rather than doubling it. `probeId` identifies the single admitted\n * probe while half-open so stale or forged probe reports can be rejected;\n * `probeAt` records when it was admitted so a probe whose outcome report is\n * lost can expire instead of wedging the resource half-open forever.\n */\nexport interface BreakerRecord {\n readonly state: BreakerState\n readonly failures: number\n readonly openCount: number\n readonly reopenAt?: number | undefined\n readonly probeId?: string | undefined\n readonly probeAt?: number | undefined\n}\n"]}
@@ -6,4 +6,3 @@ import type { ErrorEvidence, FailureClassification } from "./types.js";
6
6
  * native failure handling (ADP-009, ADP-012).
7
7
  */
8
8
  export declare function classifyFailure(evidence: ErrorEvidence): FailureClassification;
9
- //# sourceMappingURL=classify.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"classify.js","sourceRoot":"","sources":["../../../src/health/classifier/classify.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"classify.js","sourceRoot":"","sources":["../../../src/health/classifier/classify.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ErrorEvidence, FailureCategory, FailureClassification, RetryAdvice } from \"./types.js\"\n\n/**\n * Text fed to the textual last-resort layer is truncated to this bound before\n * matching, so adversarial or enormous error bodies cannot dominate\n * classification cost or smuggle patterns in late bytes (ADP-008).\n */\nconst TEXT_BOUND = 512\n\n/**\n * Retry/failover policy per category (ADP-010, ADP-011).\n *\n * - Infrastructure failures (rate limiting, quota, outage, overload, timeout)\n * are failover-eligible: horizontal recovery within the tier is exactly\n * their remedy.\n * - Permanent configuration failures (auth, invalid model, content policy)\n * and context overflow never retry and never failover: retrying the same\n * request cannot help and switching resources would reproduce the failure.\n * - User cancellation is final: no retry, no failover (ADP-010).\n * - Unknown failures defer to OpenCode's native handling.\n */\nconst CATEGORY_POLICY: Readonly<\n Record<FailureCategory, { retryable: boolean; failoverEligible: boolean }>\n> = {\n rate_limited: { retryable: true, failoverEligible: true },\n quota_exhausted: { retryable: false, failoverEligible: true },\n outage: { retryable: true, failoverEligible: true },\n overload: { retryable: true, failoverEligible: true },\n timeout: { retryable: true, failoverEligible: true },\n auth_failure: { retryable: false, failoverEligible: false },\n invalid_model: { retryable: false, failoverEligible: false },\n context_overflow: { retryable: false, failoverEligible: false },\n content_policy: { retryable: false, failoverEligible: false },\n user_cancelled: { retryable: false, failoverEligible: false },\n unknown: { retryable: false, failoverEligible: false },\n}\n\n/**\n * Error tags from the documented @opencode/protocol vocabulary that map\n * directly to a failure category. Tags absent here (`ProviderRequestError`,\n * `UnknownError`, anything unrecognized) are structured but not\n * category-specific: they never guess, and classification falls through to\n * the refining layers.\n */\nconst STRUCTURED_TYPES = new Map<string, FailureCategory>([\n [\"UnauthorizedError\", \"auth_failure\"],\n [\"ForbiddenError\", \"auth_failure\"],\n [\"ModelNotFoundError\", \"invalid_model\"],\n [\"UnsupportedModelError\", \"invalid_model\"],\n [\"ServiceUnavailableError\", \"outage\"],\n])\n\n/**\n * Bounded textual patterns, last resort only (ADP-008). Ordered most\n * specific first; the first match wins. These encode provider error-message\n * conventions documented by the research phase, not a general-purpose\n * keyword classifier.\n */\nconst TEXTUAL_PATTERNS: readonly {\n readonly category: FailureCategory\n readonly pattern: RegExp\n}[] = [\n {\n category: \"context_overflow\",\n pattern:\n /context (length|window)|maximum context|input length exceeds|prompt is too long|too many (input )?tokens|exceeds the maximum/i,\n },\n { category: \"quota_exhausted\", pattern: /\\bquota\\b|credit balance/i },\n { category: \"rate_limited\", pattern: /rate ?limit/i },\n { category: \"timeout\", pattern: /\\btimeout\\b|timed? ?out|deadline exceeded|etimedout/i },\n {\n category: \"auth_failure\",\n pattern:\n /unauthorized|invalid (api|access) key|api key (expired|invalid)|authentication|permission denied/i,\n },\n {\n category: \"invalid_model\",\n pattern: /model.{0,30}(does not exist|not found)|invalid model|unknown model|no such model/i,\n },\n {\n category: \"content_policy\",\n pattern:\n /content (management )?(policy|filter)|safety system|violates?.{0,32}policy|flagged as/i,\n },\n { category: \"overload\", pattern: /overloaded|over capacity|high demand/i },\n { category: \"user_cancelled\", pattern: /cancel+(l)?ed|aborted by (the )?user|user abort/i },\n]\n\nfunction isHttpStatus(status: number | undefined): status is number {\n return typeof status === \"number\" && Number.isInteger(status) && status >= 100 && status <= 599\n}\n\n/**\n * Upper bound on a provider-claimed retry delay. `Retry-After` and structured\n * retry metadata are untrusted provider data: a hostile or misconfigured\n * value (\"999999999\" seconds) must not convert one response into a\n * near-permanent resource blacklist. The host's own retry scheduling waits\n * out the raw header verbatim — this bound only concerns the health window\n * the supervisor derives from the classification (ADP-011 boundedness).\n */\nconst MAX_RETRY_AFTER_MS = 24 * 60 * 60 * 1000\n\nfunction boundedRetryAfterMs(retryAfterMs: number | undefined): number | undefined {\n if (retryAfterMs === undefined) {\n return undefined\n }\n return Math.min(retryAfterMs, MAX_RETRY_AFTER_MS)\n}\n\nfunction isNonNegativeInteger(value: number | undefined): value is number {\n return typeof value === \"number\" && Number.isInteger(value) && value >= 0\n}\n\nfunction lowercasedHeaders(\n headers: Readonly<Record<string, string>> | undefined,\n): ReadonlyMap<string, string> {\n const lowered = new Map<string, string>()\n if (headers === undefined) {\n return lowered\n }\n for (const [name, value] of Object.entries(headers)) {\n lowered.set(name.toLowerCase(), value)\n }\n return lowered\n}\n\n/**\n * Parses a `Retry-After` header into milliseconds. Only the integer-seconds\n * form is accepted: the HTTP-date form requires a clock, which the classifier\n * deliberately does not have (reset-time handling belongs to the capacity\n * boundary, T-05/T-15).\n */\nfunction retryAfterHeaderMs(headers: ReadonlyMap<string, string>): number | undefined {\n const raw = headers.get(\"retry-after\")\n if (raw === undefined || !/^\\d+$/.test(raw)) {\n return undefined\n }\n return Number(raw) * 1000\n}\n\n/**\n * Standard rate-limit headers (case-insensitive `x-ratelimit-remaining*`).\n * All-zero remaining capacity indicates a fixed-window quota exhaustion\n * rather than a short burst limit.\n */\nfunction fixedWindowExhausted(headers: ReadonlyMap<string, string>): boolean {\n let sawRemaining = false\n for (const [name, value] of headers) {\n if (name.startsWith(\"x-ratelimit-remaining\")) {\n sawRemaining = true\n if (value !== \"0\") {\n return false\n }\n }\n }\n return sawRemaining\n}\n\nfunction retryAdvice(category: FailureCategory, retryAfterMs: number | undefined): RetryAdvice {\n const policy = CATEGORY_POLICY[category]\n const bounded = boundedRetryAfterMs(retryAfterMs)\n if (bounded === undefined) {\n return { retryable: policy.retryable }\n }\n return { retryable: policy.retryable, retryAfterMs: bounded }\n}\n\nfunction classification(\n category: FailureCategory,\n layer: FailureClassification[\"layer\"],\n definitive: boolean,\n retryAfterMs: number | undefined,\n): FailureClassification {\n const policy = CATEGORY_POLICY[category]\n return {\n category,\n layer,\n definitive,\n retry: retryAdvice(category, retryAfterMs),\n failoverEligible: policy.failoverEligible,\n }\n}\n\n/**\n * Classifies an HTTP status. 429 consults the standard rate-limit headers in\n * the same step: status plus documented standard headers are one HTTP\n * semantics layer, and the quota refinement is more specific evidence than a\n * bare 429, so it cannot weaken the ADP-008 precedence.\n */\nfunction classifyStatus(\n status: number,\n headers: ReadonlyMap<string, string>,\n): FailureCategory | undefined {\n if (status === 429) {\n return fixedWindowExhausted(headers) ? \"quota_exhausted\" : \"rate_limited\"\n }\n if (status === 401 || status === 403) {\n return \"auth_failure\"\n }\n if (status === 408) {\n return \"timeout\"\n }\n if (status === 413) {\n return \"context_overflow\"\n }\n if (status === 502 || status === 503 || status === 504) {\n return \"outage\"\n }\n return undefined\n}\n\nfunction classifyText(text: string): FailureCategory | undefined {\n const bounded = text.length > TEXT_BOUND ? text.slice(0, TEXT_BOUND) : text\n for (const { category, pattern } of TEXTUAL_PATTERNS) {\n if (pattern.test(bounded)) {\n return category\n }\n }\n return undefined\n}\n\n/**\n * Total classification of layered failure evidence. Never throws and always\n * returns a category: any evidence shape outside the documented vocabularies\n * classifies as `unknown` via the `none` layer, deferring to OpenCode's\n * native failure handling (ADP-009, ADP-012).\n */\nexport function classifyFailure(evidence: ErrorEvidence): FailureClassification {\n // Layer 0: interruption evidence. Interruptions are host decisions, not\n // provider failures; a user cancellation is final (ADP-010).\n if (evidence.interrupted === \"user\") {\n return classification(\"user_cancelled\", \"interruption\", true, undefined)\n }\n if (evidence.interrupted !== undefined) {\n return classification(\"unknown\", \"interruption\", true, undefined)\n }\n\n // Layer 1: structured OpenCode metadata.\n const structured = evidence.structured\n const structuredRetryAfterMs = isNonNegativeInteger(structured?.retryAfterMs)\n ? structured.retryAfterMs\n : undefined\n if (structured !== undefined) {\n const mapped = STRUCTURED_TYPES.get(structured.type)\n if (mapped !== undefined) {\n return classification(mapped, \"structured\", true, structuredRetryAfterMs)\n }\n // Unmapped tag: fall through so HTTP semantics can refine the category.\n }\n\n // Layer 2: HTTP status (+ standard headers for the 429 refinement).\n const headers = lowercasedHeaders(evidence.headers)\n if (isHttpStatus(evidence.status)) {\n const category = classifyStatus(evidence.status, headers)\n if (category !== undefined) {\n return classification(\n category,\n \"status\",\n true,\n structuredRetryAfterMs ?? retryAfterHeaderMs(headers),\n )\n }\n }\n\n // Layer 3: standard headers alone (Retry-After without a decisive status).\n const headerRetryAfterMs = retryAfterHeaderMs(headers)\n if (headerRetryAfterMs !== undefined) {\n return classification(\"rate_limited\", \"headers\", false, headerRetryAfterMs)\n }\n\n // Layer 4: documented provider-specific metadata, normalized by our own\n // adapters after validation (T-15).\n if (evidence.providerMetadata?.quotaExhausted === true) {\n return classification(\"quota_exhausted\", \"provider-metadata\", true, undefined)\n }\n if (evidence.providerMetadata?.overloaded === true) {\n return classification(\"overload\", \"provider-metadata\", true, structuredRetryAfterMs)\n }\n\n // Layer 5: bounded textual classification, always non-definitive.\n const text = evidence.text\n if (text !== undefined) {\n const category = classifyText(text)\n if (category !== undefined) {\n return classification(category, \"textual\", false, structuredRetryAfterMs)\n }\n }\n\n return classification(\"unknown\", \"none\", false, undefined)\n}\n"]}
@@ -1,3 +1,2 @@
1
1
  export * from "./types.js";
2
2
  export * from "./classify.js";
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/health/classifier/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/health/classifier/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA","sourcesContent":["export * from \"./types.js\"\nexport * from \"./classify.js\"\n"]}
@@ -69,4 +69,3 @@ export interface FailureClassification {
69
69
  /** Horizontal recovery (switch resource within the tier) is allowed. */
70
70
  readonly failoverEligible: boolean;
71
71
  }
72
- //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/health/classifier/types.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,cAAc;IACd,iBAAiB;IACjB,QAAQ;IACR,UAAU;IACV,SAAS;IACT,cAAc;IACd,eAAe;IACf,kBAAkB;IAClB,gBAAgB;IAChB,gBAAgB;IAChB,SAAS;CAC2B,CAAA;AAItC;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,cAAc;IACd,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,mBAAmB;IACnB,SAAS;IACT,MAAM;CAC8B,CAAA"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/health/classifier/types.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,cAAc;IACd,iBAAiB;IACjB,QAAQ;IACR,UAAU;IACV,SAAS;IACT,cAAc;IACd,eAAe;IACf,kBAAkB;IAClB,gBAAgB;IAChB,gBAAgB;IAChB,SAAS;CAC2B,CAAA;AAItC;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,cAAc;IACd,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,mBAAmB;IACnB,SAAS;IACT,MAAM;CAC8B,CAAA","sourcesContent":["/**\n * Failure classification types (ADP-008, ADP-009).\n *\n * The classifier consumes a layered evidence record assembled by the OpenCode\n * adapter. Evidence layers exist so classification can honor the ADP-008\n * precedence chain: structured metadata beats HTTP status beats standard\n * headers beats documented provider-specific metadata beats bounded text.\n */\nimport type { InterruptReason } from \"../../core/work-unit/interruption.js\"\n\nexport const FAILURE_CATEGORIES = [\n \"rate_limited\",\n \"quota_exhausted\",\n \"outage\",\n \"overload\",\n \"timeout\",\n \"auth_failure\",\n \"invalid_model\",\n \"context_overflow\",\n \"content_policy\",\n \"user_cancelled\",\n \"unknown\",\n] as const satisfies readonly string[]\n\nexport type FailureCategory = (typeof FAILURE_CATEGORIES)[number]\n\n/**\n * Where the winning classification came from. Exposed so receipts can show\n * why a decision was made and so tests can pin the precedence chain.\n */\nexport const EVIDENCE_LAYERS = [\n \"interruption\",\n \"structured\",\n \"status\",\n \"headers\",\n \"provider-metadata\",\n \"textual\",\n \"none\",\n] as const satisfies readonly string[]\n\nexport type EvidenceLayer = (typeof EVIDENCE_LAYERS)[number]\n\n/**\n * Structured OpenCode evidence (`Session.StructuredError`): a server-assigned\n * error tag plus, when the provider sent it, a retry delay OpenCode already\n * parsed from `Retry-After`. `type` is a free-form string on the wire, so the\n * classifier only interprets types from the documented @opencode/protocol\n * vocabulary and falls through to lower layers for anything unmapped instead\n * of guessing.\n */\nexport interface StructuredSignal {\n readonly type: string\n readonly retryAfterMs?: number | undefined\n}\n\n/**\n * Documented provider-specific metadata, already normalized by our own\n * adapters (e.g. the Codex capacity sensor validates `x-codex-*` headers\n * before producing these). The classifier never reads raw provider headers\n * itself.\n */\nexport interface ProviderMetadata {\n readonly quotaExhausted?: boolean | undefined\n readonly overloaded?: boolean | undefined\n}\n\n/**\n * Layered failure evidence. `status` is the merged HTTP status (the adapter\n * prefers the wire status seen by `http.response` over any status echoed in\n * structured metadata). `text` is the bounded concatenation of error message\n * and response body, bounded again defensively inside the classifier.\n */\nexport interface ErrorEvidence {\n readonly interrupted?: InterruptReason | undefined\n readonly structured?: StructuredSignal | undefined\n readonly status?: number | undefined\n readonly headers?: Readonly<Record<string, string>> | undefined\n readonly providerMetadata?: ProviderMetadata | undefined\n readonly text?: string | undefined\n}\n\n/** Advisory retry semantics; the retry policy (T-12) makes final decisions. */\nexport interface RetryAdvice {\n readonly retryable: boolean\n readonly retryAfterMs?: number\n}\n\nexport interface FailureClassification {\n readonly category: FailureCategory\n readonly layer: EvidenceLayer\n /**\n * True when the evidence conclusively identifies the failure. Textual\n * classifications are always non-definitive; scheduling treats\n * non-definitive evidence more conservatively (ADP-012).\n */\n readonly definitive: boolean\n readonly retry: RetryAdvice\n /** Horizontal recovery (switch resource within the tier) is allowed. */\n readonly failoverEligible: boolean\n}\n"]}
@@ -2,4 +2,3 @@ export * from "./circuit-breaker/index.js";
2
2
  export * from "./capacity/index.js";
3
3
  export * from "./classifier/index.js";
4
4
  export * from "./resource-health/index.js";
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/health/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAA;AAC1C,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,4BAA4B,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/health/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAA;AAC1C,cAAc,qBAAqB,CAAA;AACnC,cAAc,uBAAuB,CAAA;AACrC,cAAc,4BAA4B,CAAA","sourcesContent":["export * from \"./circuit-breaker/index.js\"\nexport * from \"./capacity/index.js\"\nexport * from \"./classifier/index.js\"\nexport * from \"./resource-health/index.js\"\n"]}
@@ -2,4 +2,3 @@ export * from "./key.js";
2
2
  export * from "./registry.js";
3
3
  export * from "./transitions.js";
4
4
  export * from "./types.js";
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/health/resource-health/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/health/resource-health/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA","sourcesContent":["export * from \"./key.js\"\nexport * from \"./registry.js\"\nexport * from \"./transitions.js\"\nexport * from \"./types.js\"\n"]}
@@ -16,4 +16,3 @@ export declare function resourceKeyID(key: ResourceKey): string;
16
16
  * contributes no level of its own.
17
17
  */
18
18
  export declare function resourceChain(key: ResourceKey): ResourceKey[];
19
- //# sourceMappingURL=key.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"key.js","sourceRoot":"","sources":["../../../src/health/resource-health/key.ts"],"names":[],"mappings":"AAKA,yEAAyE;AACzE,MAAM,UAAU,aAAa,CAAC,GAAgB;IAC5C,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAA;IAChB,CAAC;IACD,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,aAAa,CAAC,GAAgB;IAC5C,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,GAAG,CAAC,UAAU;QACd,GAAG,CAAC,SAAS,IAAI,IAAI;QACrB,GAAG,CAAC,OAAO,IAAI,IAAI;QACnB,GAAG,CAAC,SAAS,IAAI,IAAI;KACtB,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,GAAgB;IAC5C,MAAM,KAAK,GAAkB,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAA;IAC7D,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAA;IACtE,CAAC;IACD,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CACR,GAAG,CAAC,SAAS,KAAK,SAAS;YACzB,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE;YACtD,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CACnF,CAAA;IACH,CAAC;IACD,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAC7D,KAAK,CAAC,IAAI,CACR,GAAG,CAAC,SAAS,KAAK,SAAS;YACzB,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE;YAChF,CAAC,CAAC;gBACE,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,SAAS,EAAE,GAAG,CAAC,SAAS;aACzB,CACN,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
1
+ {"version":3,"file":"key.js","sourceRoot":"","sources":["../../../src/health/resource-health/key.ts"],"names":[],"mappings":"AAKA,yEAAyE;AACzE,MAAM,UAAU,aAAa,CAAC,GAAgB;IAC5C,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAA;IAChB,CAAC;IACD,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,aAAa,CAAC,GAAgB;IAC5C,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,GAAG,CAAC,UAAU;QACd,GAAG,CAAC,SAAS,IAAI,IAAI;QACrB,GAAG,CAAC,OAAO,IAAI,IAAI;QACnB,GAAG,CAAC,SAAS,IAAI,IAAI;KACtB,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,GAAgB;IAC5C,MAAM,KAAK,GAAkB,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAA;IAC7D,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAA;IACtE,CAAC;IACD,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CACR,GAAG,CAAC,SAAS,KAAK,SAAS;YACzB,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE;YACtD,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CACnF,CAAA;IACH,CAAC;IACD,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAC7D,KAAK,CAAC,IAAI,CACR,GAAG,CAAC,SAAS,KAAK,SAAS;YACzB,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE;YAChF,CAAC,CAAC;gBACE,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,SAAS,EAAE,GAAG,CAAC,SAAS;aACzB,CACN,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["/**\n * Resource key helpers: scope derivation and canonical identity.\n */\nimport type { ResourceKey, ResourceScope } from \"./types.js\"\n\n/** The scope a key is attributed at: the most specific present field. */\nexport function resourceScope(key: ResourceKey): ResourceScope {\n if (key.variantID !== undefined) {\n return \"variant\"\n }\n if (key.modelID !== undefined) {\n return \"model\"\n }\n if (key.accountID !== undefined) {\n return \"account\"\n }\n return \"provider\"\n}\n\n/** Canonical string identity for map keys and receipts. */\nexport function resourceKeyID(key: ResourceKey): string {\n return JSON.stringify([\n key.providerID,\n key.accountID ?? null,\n key.modelID ?? null,\n key.variantID ?? null,\n ])\n}\n\n/**\n * The chain of scopes implied by `key`, ordered widest → narrowest. Each level\n * keeps the narrower fields that are present, so a key without an account\n * (OpenCode model references carry only provider and model) still yields a\n * model-level entry. Health assessment walks this chain because a blocked\n * ancestor blocks every descendant (e.g. a provider-wide rate limit skips all\n * of its models). A variant field without a model field is degenerate and\n * contributes no level of its own.\n */\nexport function resourceChain(key: ResourceKey): ResourceKey[] {\n const chain: ResourceKey[] = [{ providerID: key.providerID }]\n if (key.accountID !== undefined) {\n chain.push({ providerID: key.providerID, accountID: key.accountID })\n }\n if (key.modelID !== undefined) {\n chain.push(\n key.accountID === undefined\n ? { providerID: key.providerID, modelID: key.modelID }\n : { providerID: key.providerID, accountID: key.accountID, modelID: key.modelID },\n )\n }\n if (key.modelID !== undefined && key.variantID !== undefined) {\n chain.push(\n key.accountID === undefined\n ? { providerID: key.providerID, modelID: key.modelID, variantID: key.variantID }\n : {\n providerID: key.providerID,\n accountID: key.accountID,\n modelID: key.modelID,\n variantID: key.variantID,\n },\n )\n }\n return chain\n}\n"]}
@@ -33,9 +33,14 @@ export declare class ResourceHealthRegistry {
33
33
  * resolved, record reset, or unknown key) are rejected.
34
34
  */
35
35
  reportProbe(ticket: ProbeTicket, outcome: ProbeOutcome): boolean;
36
+ /**
37
+ * Returns an admitted-but-never-dispatched probe ticket: the breaker
38
+ * reopens still due, so the next admission can issue a fresh probe. Same
39
+ * stale-ticket rule as `reportProbe`.
40
+ */
41
+ releaseProbe(ticket: ProbeTicket): boolean;
36
42
  /** Current (swept) record for one key, if the registry tracks it. */
37
43
  recordFor(key: ResourceKey): ResourceRecord | undefined;
38
44
  /** All tracked records, swept against the clock. */
39
45
  snapshot(): ResourceRecord[];
40
46
  }
41
- //# sourceMappingURL=registry.d.ts.map
@@ -11,7 +11,7 @@
11
11
  * flips a due open breaker to half-open and issues the probe ticket, so
12
12
  * concurrent assessors can never observe two admissions.
13
13
  */
14
- import { admitProbe, breakerBlockWait, expireProbe, recordProbeFailure, recordProbeSuccess, } from "../circuit-breaker/breaker.js";
14
+ import { admitProbe, breakerBlockWait, expireProbe, recordProbeFailure, recordProbeSuccess, releaseProbe, } from "../circuit-breaker/breaker.js";
15
15
  import { resourceChain, resourceKeyID } from "./key.js";
16
16
  import { applyHealthEvent, initialRecord, sweepRecord } from "./transitions.js";
17
17
  import { DEFAULT_HEALTH_CONFIG, } from "./types.js";
@@ -245,6 +245,24 @@ export class ResourceHealthRegistry {
245
245
  this.#records.set(id, { ...record, breaker: next, updatedAt: now });
246
246
  return true;
247
247
  }
248
+ /**
249
+ * Returns an admitted-but-never-dispatched probe ticket: the breaker
250
+ * reopens still due, so the next admission can issue a fresh probe. Same
251
+ * stale-ticket rule as `reportProbe`.
252
+ */
253
+ releaseProbe(ticket) {
254
+ const id = resourceKeyID(ticket.key);
255
+ const record = this.#records.get(id);
256
+ if (record?.breaker.state !== "half_open" || record.breaker.probeId !== ticket.id) {
257
+ return false;
258
+ }
259
+ this.#records.set(id, {
260
+ ...record,
261
+ breaker: releaseProbe(record.breaker),
262
+ updatedAt: this.#clock(),
263
+ });
264
+ return true;
265
+ }
248
266
  /** Current (swept) record for one key, if the registry tracks it. */
249
267
  recordFor(key) {
250
268
  return this.#sweptRecord(key, this.#clock());
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/health/resource-health/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/health/resource-health/registry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Resource health registry (ADP-007, ADP-019, ADP-021).\n *\n * Stateful façade over the pure transition layer: one record per resource\n * key, an injected clock, and assessment that composes the record's chain of\n * ancestor scopes. Time only advances through the injected clock — there are\n * no timers; windows and breaker backoffs are evaluated (swept) lazily on\n * every observation, assessment, and snapshot.\n *\n * The single-probe guarantee (ADP-019) lives here: `assess` synchronously\n * flips a due open breaker to half-open and issues the probe ticket, so\n * concurrent assessors can never observe two admissions.\n */\nimport {\n admitProbe,\n breakerBlockWait,\n expireProbe,\n recordProbeFailure,\n recordProbeSuccess,\n releaseProbe,\n} from \"../circuit-breaker/breaker.js\"\nimport { resourceChain, resourceKeyID } from \"./key.js\"\nimport { applyHealthEvent, initialRecord, sweepRecord } from \"./transitions.js\"\nimport {\n DEFAULT_HEALTH_CONFIG,\n type Assessment,\n type Clock,\n type HealthEvent,\n type ProbeOutcome,\n type ProbeTicket,\n type ResourceHealthConfig,\n type ResourceKey,\n type ResourceRecord,\n} from \"./types.js\"\n\n/**\n * Severity of the three hard resource states. Used only to choose which\n * blocker a report names when several scopes in a chain are blocked at once;\n * every candidate still blocks regardless of which wins the report.\n */\nconst HARD_BLOCK_SEVERITY = {\n unavailable: 3,\n \"quota-exhausted\": 2,\n \"rate-limited\": 1,\n} as const\n\ntype HardBlockReason = keyof typeof HARD_BLOCK_SEVERITY\n\ninterface HardBlock {\n readonly reason: HardBlockReason\n readonly key: ResourceKey\n readonly retryAtMs: number | undefined\n readonly severity: number\n}\n\nfunction blocked(\n reason: HardBlockReason,\n key: ResourceKey,\n retryAtMs: number | undefined,\n): Assessment\nfunction blocked(reason: \"breaker-open\", key: ResourceKey, retryAtMs: number): Assessment\nfunction blocked(\n reason: \"probe-in-flight\" | \"draining\",\n key: ResourceKey,\n retryAtMs: undefined,\n): Assessment\nfunction blocked(\n reason: HardBlockReason | \"breaker-open\" | \"probe-in-flight\" | \"draining\",\n key: ResourceKey,\n retryAtMs: number | undefined,\n): Assessment {\n if (retryAtMs === undefined) {\n return { kind: \"blocked\", reason, key }\n }\n return { kind: \"blocked\", reason, key, retryAtMs }\n}\n\nfunction hardBlocker(record: ResourceRecord, now: number): HardBlock | undefined {\n const retryAtMs = record.window === undefined ? undefined : record.window.until - now\n switch (record.health) {\n case \"unavailable\":\n return {\n reason: \"unavailable\",\n key: record.key,\n retryAtMs: undefined,\n severity: HARD_BLOCK_SEVERITY.unavailable,\n }\n case \"quota_exhausted\":\n return {\n reason: \"quota-exhausted\",\n key: record.key,\n retryAtMs,\n severity: HARD_BLOCK_SEVERITY[\"quota-exhausted\"],\n }\n case \"rate_limited\":\n return {\n reason: \"rate-limited\",\n key: record.key,\n retryAtMs,\n severity: HARD_BLOCK_SEVERITY[\"rate-limited\"],\n }\n default:\n return undefined\n }\n}\n\n/** Most severe hard block across a chain; narrowest scope wins ties. */\nfunction hardest(\n records: readonly (ResourceRecord | undefined)[],\n now: number,\n): HardBlock | undefined {\n let hard: HardBlock | undefined\n for (const record of records) {\n if (record === undefined) {\n continue\n }\n const candidate = hardBlocker(record, now)\n if (candidate === undefined) {\n continue\n }\n if (hard === undefined || candidate.severity >= hard.severity) {\n hard = candidate\n }\n }\n return hard\n}\n\nexport class ResourceHealthRegistry {\n readonly #records = new Map<string, ResourceRecord>()\n readonly #clock: Clock\n readonly #config: ResourceHealthConfig\n #probeCounter = 0\n\n constructor(clock: Clock, config: ResourceHealthConfig = DEFAULT_HEALTH_CONFIG) {\n this.#clock = clock\n this.#config = config\n }\n\n /**\n * Seeds the registry from persisted records (restart / cross-instance\n * reload). Records are swept against the current clock and inserted\n * without persisting — hydration must not write back what it just read.\n * A hydrated half_open record cannot keep its probe (the ticket lived in\n * the previous instance's memory), so it re-opens due immediately — its\n * backoff window had already elapsed when it went half-open, and the next\n * assessment admits exactly one probe as usual.\n */\n hydrate(records: readonly ResourceRecord[]): void {\n const now = this.#clock()\n for (const record of records) {\n const swept = sweepRecord(record, now)\n const breaker =\n swept.breaker.state === \"half_open\"\n ? {\n state: \"open\" as const,\n failures: swept.breaker.failures,\n openCount: swept.breaker.openCount,\n reopenAt: now,\n }\n : swept.breaker\n this.#records.set(resourceKeyID(swept.key), { ...swept, breaker, updatedAt: now })\n }\n }\n\n observe(event: HealthEvent): ResourceRecord {\n const now = this.#clock()\n const id = resourceKeyID(event.key)\n const existing = this.#records.get(id)\n const swept =\n existing === undefined ? initialRecord(event.key, now) : sweepRecord(existing, now)\n const updated = applyHealthEvent(swept, event, now, this.#config)\n this.#records.set(id, updated)\n return updated\n }\n\n #sweptRecord(key: ResourceKey, now: number): ResourceRecord | undefined {\n const id = resourceKeyID(key)\n const record = this.#records.get(id)\n if (record === undefined) {\n return undefined\n }\n const swept = sweepRecord(record, now)\n if (swept !== record) {\n this.#records.set(id, swept)\n }\n return swept\n }\n\n /**\n * Assesses whether the resource may take new work right now, composing the\n * full ancestor chain. Precedence: the most severe hard resource state\n * wins (narrowest scope on ties), then the breaker scan (widest scope\n * first — a due wide breaker is probed before a narrow one), then draining,\n * then available.\n */\n assess(key: ResourceKey): Assessment {\n const now = this.#clock()\n const records = resourceChain(key).map((chainKey) => this.#sweptRecord(chainKey, now))\n\n const hard = hardest(records, now)\n if (hard !== undefined) {\n return blocked(hard.reason, hard.key, hard.retryAtMs)\n }\n\n for (const record of records) {\n if (record === undefined) {\n continue\n }\n // A probe whose outcome report never arrived must not wedge the\n // resource in half_open: expire it (same backoff window, no doubling)\n // before attempting admission.\n const expired = expireProbe(record.breaker, now, this.#config.breaker)\n const current =\n expired === record.breaker ? record : { ...record, breaker: expired, updatedAt: now }\n if (current !== record) {\n this.#records.set(resourceKeyID(record.key), current)\n }\n const admission = admitProbe(current.breaker, now)\n if (admission.kind === \"closed\") {\n continue\n }\n if (admission.kind === \"waiting\") {\n return blocked(\"breaker-open\", record.key, admission.retryAtMs)\n }\n if (admission.kind === \"in-flight\") {\n return blocked(\"probe-in-flight\", record.key, undefined)\n }\n const probeId = String(++this.#probeCounter)\n this.#records.set(resourceKeyID(record.key), {\n ...record,\n breaker: { ...admission.record, probeId, probeAt: now },\n updatedAt: now,\n })\n return { kind: \"probe\", ticket: { id: probeId, key: record.key } }\n }\n\n // Draining is the softest blocker; report the narrowest draining scope.\n let draining: ResourceRecord | undefined\n for (const record of records) {\n if (record?.health === \"draining\") {\n draining = record\n }\n }\n if (draining !== undefined) {\n return blocked(\"draining\", draining.key, undefined)\n }\n\n return { kind: \"available\" }\n }\n\n /**\n * Non-mutating assessment for decisions that must not admit a probe\n * (escalation-target gating): identical hard-state and draining walk, but\n * an open or half-open breaker blocks without being flipped or ticketed.\n */\n evaluate(key: ResourceKey): Assessment {\n const now = this.#clock()\n const records = resourceChain(key).map((chainKey) => this.#sweptRecord(chainKey, now))\n const hard = hardest(records, now)\n if (hard !== undefined) {\n return blocked(hard.reason, hard.key, hard.retryAtMs)\n }\n for (const record of records) {\n if (record === undefined) continue\n // Observer view (non-mutating): an open breaker blocks even when its\n // backoff elapsed — assess is what flips it to half_open and issues\n // the probe ticket.\n const wait = breakerBlockWait(record.breaker, now)\n if (wait !== undefined) {\n return blocked(\"breaker-open\", record.key, wait)\n }\n if (record.breaker.state === \"half_open\") {\n return blocked(\"probe-in-flight\", record.key, undefined)\n }\n }\n let draining: ResourceRecord | undefined\n for (const record of records) {\n if (record?.health === \"draining\") {\n draining = record\n }\n }\n if (draining !== undefined) {\n return blocked(\"draining\", draining.key, undefined)\n }\n return { kind: \"available\" }\n }\n\n /**\n * Reports the outcome of an admitted probe. Only the ticket issued for the\n * current half-open record is honored; stale tickets (probe already\n * resolved, record reset, or unknown key) are rejected.\n */\n reportProbe(ticket: ProbeTicket, outcome: ProbeOutcome): boolean {\n const now = this.#clock()\n const id = resourceKeyID(ticket.key)\n const record = this.#records.get(id)\n if (record === undefined) {\n return false\n }\n const breaker = record.breaker\n if (breaker.state !== \"half_open\" || breaker.probeId !== ticket.id) {\n return false\n }\n const next = outcome.success\n ? recordProbeSuccess(breaker)\n : recordProbeFailure(breaker, outcome.category, now, this.#config.breaker)\n this.#records.set(id, { ...record, breaker: next, updatedAt: now })\n return true\n }\n\n /**\n * Returns an admitted-but-never-dispatched probe ticket: the breaker\n * reopens still due, so the next admission can issue a fresh probe. Same\n * stale-ticket rule as `reportProbe`.\n */\n releaseProbe(ticket: ProbeTicket): boolean {\n const id = resourceKeyID(ticket.key)\n const record = this.#records.get(id)\n if (record?.breaker.state !== \"half_open\" || record.breaker.probeId !== ticket.id) {\n return false\n }\n this.#records.set(id, {\n ...record,\n breaker: releaseProbe(record.breaker),\n updatedAt: this.#clock(),\n })\n return true\n }\n\n /** Current (swept) record for one key, if the registry tracks it. */\n recordFor(key: ResourceKey): ResourceRecord | undefined {\n return this.#sweptRecord(key, this.#clock())\n }\n\n /** All tracked records, swept against the clock. */\n snapshot(): ResourceRecord[] {\n const now = this.#clock()\n return [...this.#records.values()].map((record) => sweepRecord(record, now))\n }\n}\n"]}
@@ -2,10 +2,8 @@ import type { HealthEvent, ResourceHealthConfig, ResourceKey, ResourceRecord } f
2
2
  export declare function initialRecord(key: ResourceKey, now: number): ResourceRecord;
3
3
  /**
4
4
  * Elapses time-bounded windows: once a window's `until` passes, the windowed
5
- * state (rate limited, quota exhausted with a known reset) lifts back to
6
- * healthy. Records without a window, or with one still in the future, pass
7
- * through unchanged.
5
+ * state (rate limited, quota exhausted) lifts back to healthy. Records
6
+ * without a window, or with one still in the future, pass through unchanged.
8
7
  */
9
8
  export declare function sweepRecord(record: ResourceRecord, now: number): ResourceRecord;
10
9
  export declare function applyHealthEvent(record: ResourceRecord, event: HealthEvent, now: number, config: ResourceHealthConfig): ResourceRecord;
11
- //# sourceMappingURL=transitions.d.ts.map
@@ -5,7 +5,8 @@
5
5
  * resource record: total, synchronous, and clock-free (`now` is injected).
6
6
  *
7
7
  * Policy notes:
8
- * - Rate limiting and quota exhaustion set their own windowed states;
8
+ * - Rate limiting and quota exhaustion set their own windowed states, always
9
+ * bounded (a default window when the evidence names no reset);
9
10
  * a windowed state is never downgraded by weaker evidence (a 429 while
10
11
  * quota-exhausted does not erase the quota signal).
11
12
  * - Outage, overload, and timeout count toward the circuit breaker and mark
@@ -34,9 +35,8 @@ export function initialRecord(key, now) {
34
35
  }
35
36
  /**
36
37
  * Elapses time-bounded windows: once a window's `until` passes, the windowed
37
- * state (rate limited, quota exhausted with a known reset) lifts back to
38
- * healthy. Records without a window, or with one still in the future, pass
39
- * through unchanged.
38
+ * state (rate limited, quota exhausted) lifts back to healthy. Records
39
+ * without a window, or with one still in the future, pass through unchanged.
40
40
  */
41
41
  export function sweepRecord(record, now) {
42
42
  const window = record.window;
@@ -56,6 +56,10 @@ function touched(record, now) {
56
56
  function validRetryAfterMs(value) {
57
57
  return value !== undefined && Number.isInteger(value) && value >= 0 ? value : undefined;
58
58
  }
59
+ function quotaExhausted(record, retryAfterMs, now, config) {
60
+ const until = now + (validRetryAfterMs(retryAfterMs) ?? config.defaultQuotaWindowMs);
61
+ return { ...record, health: "quota_exhausted", window: { kind: "quota", until }, updatedAt: now };
62
+ }
59
63
  function failureEvent(record, event, now, config) {
60
64
  switch (event.category) {
61
65
  case "rate_limited": {
@@ -75,13 +79,7 @@ function failureEvent(record, event, now, config) {
75
79
  if (record.health === "unavailable") {
76
80
  return touched(record, now);
77
81
  }
78
- const retryAfterMs = validRetryAfterMs(event.retryAfterMs);
79
- return {
80
- ...record,
81
- health: "quota_exhausted",
82
- window: retryAfterMs === undefined ? undefined : { kind: "quota", until: now + retryAfterMs },
83
- updatedAt: now,
84
- };
82
+ return quotaExhausted(record, event.retryAfterMs, now, config);
85
83
  }
86
84
  case "outage":
87
85
  case "overload":
@@ -142,13 +140,7 @@ export function applyHealthEvent(record, event, now, config) {
142
140
  if (record.health === "unavailable") {
143
141
  return touched(record, now);
144
142
  }
145
- const retryAfterMs = validRetryAfterMs(event.retryAfterMs);
146
- return {
147
- ...record,
148
- health: "quota_exhausted",
149
- window: retryAfterMs === undefined ? undefined : { kind: "quota", until: now + retryAfterMs },
150
- updatedAt: now,
151
- };
143
+ return quotaExhausted(record, event.retryAfterMs, now, config);
152
144
  }
153
145
  const health = record.health === "quota_exhausted" ? "healthy" : record.health;
154
146
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"transitions.js","sourceRoot":"","sources":["../../../src/health/resource-health/transitions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transitions.js","sourceRoot":"","sources":["../../../src/health/resource-health/transitions.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure resource health transitions (ADP-007, ADP-012, ADP-019, ADP-021).\n *\n * `applyHealthEvent` is the single authority for how evidence changes a\n * resource record: total, synchronous, and clock-free (`now` is injected).\n *\n * Policy notes:\n * - Rate limiting and quota exhaustion set their own windowed states, always\n * bounded (a default window when the evidence names no reset);\n * a windowed state is never downgraded by weaker evidence (a 429 while\n * quota-exhausted does not erase the quota signal).\n * - Outage, overload, and timeout count toward the circuit breaker and mark\n * the resource degraded. They never hard-quarantine on their own: a single\n * definitive outage signal can be a blip, so the breaker owns transient\n * failure quarantine with backoff windows and probe recovery.\n * - Definitive configuration failures (auth, invalid model) hard-quarantine\n * the resource: the evidence proves the resource cannot work. Non-definitive\n * evidence of the same categories (the textual last resort, ADP-008) is\n * transient and breaker-owned instead — one fuzzy substring in an error\n * body must never permanently blacklist a resource with no recovery path\n * (ADP-012).\n * - The `definitive` flag otherwise guides scheduling deference, not health:\n * both definitive and non-definitive infra failures leave the resource\n * degraded.\n * - Ambiguous or request-level failures (context overflow, content policy,\n * user cancellation, unknown) never change health: they say nothing about\n * the resource.\n * - Draining is a policy request (ADP-021), not degraded health: it applies\n * on top of healthy/degraded and never masks a harder state.\n */\nimport {\n recordBreakerFailure,\n recordBreakerSuccess,\n initialBreaker,\n} from \"../circuit-breaker/breaker.js\"\nimport type { BreakerRecord } from \"../circuit-breaker/types.js\"\nimport { resourceScope } from \"./key.js\"\nimport type { HealthEvent, ResourceHealthConfig, ResourceKey, ResourceRecord } from \"./types.js\"\n\nexport function initialRecord(key: ResourceKey, now: number): ResourceRecord {\n return { key, health: \"healthy\", breaker: initialBreaker(), updatedAt: now }\n}\n\n/**\n * Elapses time-bounded windows: once a window's `until` passes, the windowed\n * state (rate limited, quota exhausted) lifts back to healthy. Records\n * without a window, or with one still in the future, pass through unchanged.\n */\nexport function sweepRecord(record: ResourceRecord, now: number): ResourceRecord {\n const window = record.window\n if (window === undefined || now < window.until) {\n return record\n }\n return { key: record.key, health: \"healthy\", breaker: record.breaker, updatedAt: now }\n}\n\nfunction touched(record: ResourceRecord, now: number): ResourceRecord {\n return { ...record, updatedAt: now }\n}\n\n/**\n * Defensive re-validation of a parsed retry delay: the classifier already\n * rejects malformed values, but the health layer never trusts a negative or\n * fractional delay to compute a window.\n */\nfunction validRetryAfterMs(value: number | undefined): number | undefined {\n return value !== undefined && Number.isInteger(value) && value >= 0 ? value : undefined\n}\n\nfunction quotaExhausted(\n record: ResourceRecord,\n retryAfterMs: number | undefined,\n now: number,\n config: ResourceHealthConfig,\n): ResourceRecord {\n const until = now + (validRetryAfterMs(retryAfterMs) ?? config.defaultQuotaWindowMs)\n return { ...record, health: \"quota_exhausted\", window: { kind: \"quota\", until }, updatedAt: now }\n}\n\nfunction failureEvent(\n record: ResourceRecord,\n event: Extract<HealthEvent, { kind: \"failure\" }>,\n now: number,\n config: ResourceHealthConfig,\n): ResourceRecord {\n switch (event.category) {\n case \"rate_limited\": {\n if (record.health === \"quota_exhausted\" || record.health === \"unavailable\") {\n return touched(record, now)\n }\n const retryAfterMs = validRetryAfterMs(event.retryAfterMs)\n const until = now + (retryAfterMs ?? config.defaultRateLimitWindowMs)\n return {\n ...record,\n health: \"rate_limited\",\n window: { kind: \"rate-limit\", until },\n updatedAt: now,\n }\n }\n case \"quota_exhausted\": {\n if (record.health === \"unavailable\") {\n return touched(record, now)\n }\n return quotaExhausted(record, event.retryAfterMs, now, config)\n }\n case \"outage\":\n case \"overload\":\n case \"timeout\": {\n const breaker = recordBreakerFailure(record.breaker, event.category, now, config.breaker)\n const health =\n record.health === \"healthy\" || record.health === \"draining\" ? \"degraded\" : record.health\n return { ...record, health, breaker: breaker.record, updatedAt: now }\n }\n case \"auth_failure\":\n case \"invalid_model\": {\n // An invalid model says nothing about the provider or account; only\n // model-scoped and variant-scoped keys may be quarantined by it.\n if (event.category === \"invalid_model\") {\n const scope = resourceScope(record.key)\n if (scope !== \"model\" && scope !== \"variant\") {\n return touched(record, now)\n }\n }\n if (!event.definitive) {\n // Non-definitive evidence (bounded-textual last resort) is not proof\n // the resource cannot work: quarantine through the breaker's bounded\n // failure counting instead of a windowless, unrecoverable state.\n const breaker = recordBreakerFailure(record.breaker, event.category, now, config.breaker)\n const health =\n record.health === \"healthy\" || record.health === \"draining\" ? \"degraded\" : record.health\n return { ...record, health, breaker: breaker.record, updatedAt: now }\n }\n return { ...record, health: \"unavailable\", updatedAt: now }\n }\n default:\n // context_overflow, content_policy, user_cancelled, unknown:\n // request-level evidence, not resource health.\n return touched(record, now)\n }\n}\n\nexport function applyHealthEvent(\n record: ResourceRecord,\n event: HealthEvent,\n now: number,\n config: ResourceHealthConfig,\n): ResourceRecord {\n switch (event.kind) {\n case \"failure\":\n return failureEvent(record, event, now, config)\n case \"success\": {\n const breaker: BreakerRecord = recordBreakerSuccess()\n const health =\n record.health === \"draining\" || record.health === \"quota_exhausted\"\n ? record.health\n : \"healthy\"\n return {\n ...record,\n health,\n breaker,\n window: health === record.health ? record.window : undefined,\n updatedAt: now,\n }\n }\n case \"drain\": {\n const health =\n record.health === \"healthy\" || record.health === \"degraded\" ? \"draining\" : record.health\n return { ...record, health, updatedAt: now }\n }\n case \"capacity\": {\n if (event.exhausted) {\n if (record.health === \"unavailable\") {\n return touched(record, now)\n }\n return quotaExhausted(record, event.retryAfterMs, now, config)\n }\n const health = record.health === \"quota_exhausted\" ? \"healthy\" : record.health\n return {\n ...record,\n health,\n window: health === record.health ? record.window : undefined,\n updatedAt: now,\n }\n }\n case \"reset\":\n return { key: record.key, health: \"healthy\", breaker: initialBreaker(), updatedAt: now }\n }\n}\n"]}
@@ -74,6 +74,13 @@ export interface ResourceHealthConfig {
74
74
  readonly breaker: BreakerConfig;
75
75
  /** Window applied to rate-limited evidence that carries no Retry-After. */
76
76
  readonly defaultRateLimitWindowMs: number;
77
+ /**
78
+ * Window applied to quota exhaustion that carries no reset delay. Without
79
+ * one the state would be permanent (it is persisted and rehydrated), so an
80
+ * unknown reset re-admits the resource after this window and lets fresh
81
+ * evidence re-mark it (ADP-012).
82
+ */
83
+ readonly defaultQuotaWindowMs: number;
77
84
  }
78
85
  export declare const DEFAULT_HEALTH_CONFIG: ResourceHealthConfig;
79
86
  /** Injected monotonic clock, milliseconds. */
@@ -113,4 +120,3 @@ export type Assessment = {
113
120
  readonly key: ResourceKey;
114
121
  readonly retryAtMs?: number;
115
122
  };
116
- //# sourceMappingURL=types.d.ts.map
@@ -25,6 +25,7 @@ export const HEALTH_STATES = [
25
25
  export const DEFAULT_HEALTH_CONFIG = {
26
26
  breaker: DEFAULT_BREAKER_CONFIG,
27
27
  defaultRateLimitWindowMs: 30_000,
28
+ defaultQuotaWindowMs: 15 * 60_000,
28
29
  };
29
30
  /**
30
31
  * Why an assessment blocks new work. Ordered from hardest to softest fact:
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/health/resource-health/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EACL,sBAAsB,GAGvB,MAAM,6BAA6B,CAAA;AAGpC,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,UAAU;IACV,SAAS;IACT,OAAO;IACP,SAAS;CAC2B,CAAA;AAiBtC,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,SAAS;IACT,UAAU;IACV,UAAU;IACV,cAAc;IACd,iBAAiB;IACjB,aAAa;CACuB,CAAA;AAsDtC,MAAM,CAAC,MAAM,qBAAqB,GAAyB;IACzD,OAAO,EAAE,sBAAsB;IAC/B,wBAAwB,EAAE,MAAM;CACjC,CAAA;AAKD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,aAAa;IACb,iBAAiB;IACjB,cAAc;IACd,cAAc;IACd,iBAAiB;IACjB,UAAU;CAC0B,CAAA"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/health/resource-health/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EACL,sBAAsB,GAGvB,MAAM,6BAA6B,CAAA;AAGpC,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,UAAU;IACV,SAAS;IACT,OAAO;IACP,SAAS;CAC2B,CAAA;AAiBtC,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,SAAS;IACT,UAAU;IACV,UAAU;IACV,cAAc;IACd,iBAAiB;IACjB,aAAa;CACuB,CAAA;AA6DtC,MAAM,CAAC,MAAM,qBAAqB,GAAyB;IACzD,OAAO,EAAE,sBAAsB;IAC/B,wBAAwB,EAAE,MAAM;IAChC,oBAAoB,EAAE,EAAE,GAAG,MAAM;CAClC,CAAA;AAKD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,aAAa;IACb,iBAAiB;IACjB,cAAc;IACd,cAAc;IACd,iBAAiB;IACjB,UAAU;CAC0B,CAAA","sourcesContent":["/**\n * Resource health types (ADP-007, ADP-012, ADP-021).\n *\n * A resource is identified at the narrowest scope the evidence supports:\n * provider → account → model → variant. Health states are a closed set and\n * every transition between them is defined by the pure transition layer; the\n * registry never invents states. The circuit breaker (ADP-019) is an\n * orthogonal axis stored per resource record.\n */\nimport {\n DEFAULT_BREAKER_CONFIG,\n type BreakerConfig,\n type BreakerRecord,\n} from \"../circuit-breaker/types.js\"\nimport type { FailureCategory } from \"../classifier/types.js\"\n\nexport const RESOURCE_SCOPES = [\n \"provider\",\n \"account\",\n \"model\",\n \"variant\",\n] as const satisfies readonly string[]\n\nexport type ResourceScope = (typeof RESOURCE_SCOPES)[number]\n\n/**\n * Hierarchical resource identity. The scope is derived from the most specific\n * field present, so callers attribute evidence at exactly the level they can\n * prove (e.g. a provider-wide outage without a model id stays at provider\n * scope; a per-variant failure quarantines only that variant).\n */\nexport interface ResourceKey {\n readonly providerID: string\n readonly accountID?: string | undefined\n readonly modelID?: string | undefined\n readonly variantID?: string | undefined\n}\n\nexport const HEALTH_STATES = [\n \"healthy\",\n \"draining\",\n \"degraded\",\n \"rate_limited\",\n \"quota_exhausted\",\n \"unavailable\",\n] as const satisfies readonly string[]\n\nexport type HealthState = (typeof HEALTH_STATES)[number]\n\n/**\n * A time-bounded window during which the current state is known to hold\n * (e.g. until a Retry-After delay or a quota reset elapses). Absent when no\n * reset time is known — recovery then relies on probes, observed successes,\n * or explicit resets.\n */\nexport interface ResourceWindow {\n readonly kind: \"rate-limit\" | \"quota\"\n readonly until: number\n}\n\nexport interface ResourceRecord {\n readonly key: ResourceKey\n readonly health: HealthState\n readonly breaker: BreakerRecord\n readonly window?: ResourceWindow | undefined\n readonly updatedAt: number\n}\n\n/**\n * Health evidence events. `failure` carries an already-classified category\n * (from the error classifier, ADP-009) plus the classification's\n * definitiveness and parsed retry delay. `capacity` carries a CapacitySensor\n * reading (ADP-020) — `exhausted: false` is positive evidence of capacity.\n * `reset` is the manual Control-mode recovery op.\n */\nexport type HealthEvent =\n | {\n readonly kind: \"failure\"\n readonly key: ResourceKey\n readonly category: FailureCategory\n readonly definitive: boolean\n readonly retryAfterMs?: number | undefined\n }\n | { readonly kind: \"success\"; readonly key: ResourceKey }\n | { readonly kind: \"drain\"; readonly key: ResourceKey }\n | {\n readonly kind: \"capacity\"\n readonly key: ResourceKey\n readonly exhausted: boolean\n readonly retryAfterMs?: number | undefined\n }\n | { readonly kind: \"reset\"; readonly key: ResourceKey }\n\nexport interface ResourceHealthConfig {\n readonly breaker: BreakerConfig\n /** Window applied to rate-limited evidence that carries no Retry-After. */\n readonly defaultRateLimitWindowMs: number\n /**\n * Window applied to quota exhaustion that carries no reset delay. Without\n * one the state would be permanent (it is persisted and rehydrated), so an\n * unknown reset re-admits the resource after this window and lets fresh\n * evidence re-mark it (ADP-012).\n */\n readonly defaultQuotaWindowMs: number\n}\n\nexport const DEFAULT_HEALTH_CONFIG: ResourceHealthConfig = {\n breaker: DEFAULT_BREAKER_CONFIG,\n defaultRateLimitWindowMs: 30_000,\n defaultQuotaWindowMs: 15 * 60_000,\n}\n\n/** Injected monotonic clock, milliseconds. */\nexport type Clock = () => number\n\n/**\n * Why an assessment blocks new work. Ordered from hardest to softest fact:\n * hard resource states (unavailable, quota, rate limit) are direct evidence;\n * breaker reasons are inferred from failure counts; draining is a policy\n * request, not a health fact.\n */\nexport const BLOCKED_REASONS = [\n \"unavailable\",\n \"quota-exhausted\",\n \"rate-limited\",\n \"breaker-open\",\n \"probe-in-flight\",\n \"draining\",\n] as const satisfies readonly string[]\n\nexport type BlockedReason = (typeof BLOCKED_REASONS)[number]\n\n/** Opaque single-probe admission token; validated on report. */\nexport interface ProbeTicket {\n readonly id: string\n readonly key: ResourceKey\n}\n\nexport type ProbeOutcome =\n { readonly success: true } | { readonly success: false; readonly category: FailureCategory }\n\n/**\n * Result of assessing whether a resource may take new work right now. The\n * `blocked` variant reports the winning blocker's key (which may be a wider\n * scope than the assessed key) and, when known, when the block can lift.\n */\nexport type Assessment =\n | { readonly kind: \"available\" }\n | { readonly kind: \"probe\"; readonly ticket: ProbeTicket }\n | {\n readonly kind: \"blocked\"\n readonly reason: BlockedReason\n readonly key: ResourceKey\n readonly retryAtMs?: number\n }\n"]}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,5 @@
1
1
  import { Plugin } from "@opencode/plugin";
2
2
  export { PLUGIN_ID } from "./plugin-id.js";
3
- /**
4
- * Plugin id as required by GOAL.md: must not collide with the `opencode.*`
5
- * namespace and must stay stable across releases (referenced by settings
6
- * storage keys and receipts).
7
- */
8
3
  /**
9
4
  * Entry point wired into OpenCode via `opencode.json(c)`. Setup glues the
10
5
  * adapter touchpoints (session hooks, event subscription, storage) to the
@@ -14,4 +9,3 @@ export { PLUGIN_ID } from "./plugin-id.js";
14
9
  */
15
10
  declare const _default: Plugin.Plugin;
16
11
  export default _default;
17
- //# sourceMappingURL=index.d.ts.map