@coool/opencode-adaptive 0.0.0-stage → 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 (334) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +99 -2
  3. package/dist/adapters/codex-capacity/index.d.ts +4 -0
  4. package/dist/adapters/codex-capacity/index.js +5 -0
  5. package/dist/adapters/codex-capacity/index.js.map +1 -0
  6. package/dist/adapters/codex-capacity/parse.d.ts +28 -0
  7. package/dist/adapters/codex-capacity/parse.js +146 -0
  8. package/dist/adapters/codex-capacity/parse.js.map +1 -0
  9. package/dist/adapters/codex-capacity/reading.d.ts +9 -0
  10. package/dist/adapters/codex-capacity/reading.js +45 -0
  11. package/dist/adapters/codex-capacity/reading.js.map +1 -0
  12. package/dist/adapters/codex-capacity/sensor.d.ts +23 -0
  13. package/dist/adapters/codex-capacity/sensor.js +30 -0
  14. package/dist/adapters/codex-capacity/sensor.js.map +1 -0
  15. package/dist/adapters/codex-capacity/types.d.ts +31 -0
  16. package/dist/adapters/codex-capacity/types.js +18 -0
  17. package/dist/adapters/codex-capacity/types.js.map +1 -0
  18. package/dist/adapters/opencode/escalation-tool.d.ts +51 -0
  19. package/dist/adapters/opencode/escalation-tool.js +61 -0
  20. package/dist/adapters/opencode/escalation-tool.js.map +1 -0
  21. package/dist/adapters/opencode/events.d.ts +23 -0
  22. package/dist/adapters/opencode/events.js +68 -0
  23. package/dist/adapters/opencode/events.js.map +1 -0
  24. package/dist/adapters/opencode/hooks.d.ts +34 -0
  25. package/dist/adapters/opencode/hooks.js +29 -0
  26. package/dist/adapters/opencode/hooks.js.map +1 -0
  27. package/dist/adapters/opencode/index.d.ts +16 -0
  28. package/dist/adapters/opencode/index.js +9 -0
  29. package/dist/adapters/opencode/index.js.map +1 -0
  30. package/dist/adapters/opencode/inventory.d.ts +30 -0
  31. package/dist/adapters/opencode/inventory.js +53 -0
  32. package/dist/adapters/opencode/inventory.js.map +1 -0
  33. package/dist/adapters/opencode/report.d.ts +91 -0
  34. package/dist/adapters/opencode/report.js +145 -0
  35. package/dist/adapters/opencode/report.js.map +1 -0
  36. package/dist/adapters/opencode/session-ops.d.ts +39 -0
  37. package/dist/adapters/opencode/session-ops.js +32 -0
  38. package/dist/adapters/opencode/session-ops.js.map +1 -0
  39. package/dist/adapters/opencode/storage.d.ts +15 -0
  40. package/dist/adapters/opencode/storage.js +8 -0
  41. package/dist/adapters/opencode/storage.js.map +1 -0
  42. package/dist/adapters/opencode/tier-tool.d.ts +37 -0
  43. package/dist/adapters/opencode/tier-tool.js +72 -0
  44. package/dist/adapters/opencode/tier-tool.js.map +1 -0
  45. package/dist/adapters/opencode/types.d.ts +101 -0
  46. package/dist/adapters/opencode/types.js +2 -0
  47. package/dist/adapters/opencode/types.js.map +1 -0
  48. package/dist/core/compatibility/gate.d.ts +7 -0
  49. package/dist/core/compatibility/gate.js +51 -0
  50. package/dist/core/compatibility/gate.js.map +1 -0
  51. package/dist/core/compatibility/index.d.ts +2 -0
  52. package/dist/core/compatibility/index.js +3 -0
  53. package/dist/core/compatibility/index.js.map +1 -0
  54. package/dist/core/compatibility/types.d.ts +53 -0
  55. package/dist/core/compatibility/types.js +27 -0
  56. package/dist/core/compatibility/types.js.map +1 -0
  57. package/dist/core/scheduler/admit.d.ts +6 -0
  58. package/dist/core/scheduler/admit.js +154 -0
  59. package/dist/core/scheduler/admit.js.map +1 -0
  60. package/dist/core/scheduler/escalate.d.ts +6 -0
  61. package/dist/core/scheduler/escalate.js +45 -0
  62. package/dist/core/scheduler/escalate.js.map +1 -0
  63. package/dist/core/scheduler/index.d.ts +4 -0
  64. package/dist/core/scheduler/index.js +5 -0
  65. package/dist/core/scheduler/index.js.map +1 -0
  66. package/dist/core/scheduler/mode.d.ts +8 -0
  67. package/dist/core/scheduler/mode.js +10 -0
  68. package/dist/core/scheduler/mode.js.map +1 -0
  69. package/dist/core/scheduler/types.d.ts +136 -0
  70. package/dist/core/scheduler/types.js +75 -0
  71. package/dist/core/scheduler/types.js.map +1 -0
  72. package/dist/core/tier-policy/index.d.ts +3 -0
  73. package/dist/core/tier-policy/index.js +4 -0
  74. package/dist/core/tier-policy/index.js.map +1 -0
  75. package/dist/core/tier-policy/resolve.d.ts +18 -0
  76. package/dist/core/tier-policy/resolve.js +52 -0
  77. package/dist/core/tier-policy/resolve.js.map +1 -0
  78. package/dist/core/tier-policy/tier-list.d.ts +10 -0
  79. package/dist/core/tier-policy/tier-list.js +23 -0
  80. package/dist/core/tier-policy/tier-list.js.map +1 -0
  81. package/dist/core/tier-policy/types.d.ts +86 -0
  82. package/dist/core/tier-policy/types.js +49 -0
  83. package/dist/core/tier-policy/types.js.map +1 -0
  84. package/dist/core/work-unit/index.d.ts +3 -0
  85. package/dist/core/work-unit/index.js +4 -0
  86. package/dist/core/work-unit/index.js.map +1 -0
  87. package/dist/core/work-unit/interruption.d.ts +7 -0
  88. package/dist/core/work-unit/interruption.js +12 -0
  89. package/dist/core/work-unit/interruption.js.map +1 -0
  90. package/dist/core/work-unit/tracker.d.ts +53 -0
  91. package/dist/core/work-unit/tracker.js +156 -0
  92. package/dist/core/work-unit/tracker.js.map +1 -0
  93. package/dist/core/work-unit/types.d.ts +151 -0
  94. package/dist/core/work-unit/types.js +23 -0
  95. package/dist/core/work-unit/types.js.map +1 -0
  96. package/dist/execution/continuation/execute.d.ts +18 -0
  97. package/dist/execution/continuation/execute.js +31 -0
  98. package/dist/execution/continuation/execute.js.map +1 -0
  99. package/dist/execution/continuation/index.d.ts +4 -0
  100. package/dist/execution/continuation/index.js +4 -0
  101. package/dist/execution/continuation/index.js.map +1 -0
  102. package/dist/execution/continuation/plan.d.ts +12 -0
  103. package/dist/execution/continuation/plan.js +18 -0
  104. package/dist/execution/continuation/plan.js.map +1 -0
  105. package/dist/execution/continuation/prompts.d.ts +7 -0
  106. package/dist/execution/continuation/prompts.js +8 -0
  107. package/dist/execution/continuation/prompts.js.map +1 -0
  108. package/dist/execution/continuation/types.d.ts +68 -0
  109. package/dist/execution/continuation/types.js +15 -0
  110. package/dist/execution/continuation/types.js.map +1 -0
  111. package/dist/execution/escalation/index.d.ts +1 -0
  112. package/dist/execution/escalation/index.js +2 -0
  113. package/dist/execution/escalation/index.js.map +1 -0
  114. package/dist/execution/escalation/types.d.ts +30 -0
  115. package/dist/execution/escalation/types.js +49 -0
  116. package/dist/execution/escalation/types.js.map +1 -0
  117. package/dist/execution/index.d.ts +4 -0
  118. package/dist/execution/index.js +5 -0
  119. package/dist/execution/index.js.map +1 -0
  120. package/dist/execution/parking/index.d.ts +2 -0
  121. package/dist/execution/parking/index.js +2 -0
  122. package/dist/execution/parking/index.js.map +1 -0
  123. package/dist/execution/parking/plan.d.ts +39 -0
  124. package/dist/execution/parking/plan.js +34 -0
  125. package/dist/execution/parking/plan.js.map +1 -0
  126. package/dist/execution/retry/decide.d.ts +29 -0
  127. package/dist/execution/retry/decide.js +75 -0
  128. package/dist/execution/retry/decide.js.map +1 -0
  129. package/dist/execution/retry/index.d.ts +2 -0
  130. package/dist/execution/retry/index.js +3 -0
  131. package/dist/execution/retry/index.js.map +1 -0
  132. package/dist/execution/retry/types.d.ts +64 -0
  133. package/dist/execution/retry/types.js +9 -0
  134. package/dist/execution/retry/types.js.map +1 -0
  135. package/dist/gui-experimental.cjs +1 -0
  136. package/dist/gui.d.ts +16 -0
  137. package/dist/gui.js +73 -0
  138. package/dist/gui.js.map +1 -0
  139. package/dist/health/capacity/index.d.ts +3 -0
  140. package/dist/health/capacity/index.js +4 -0
  141. package/dist/health/capacity/index.js.map +1 -0
  142. package/dist/health/capacity/merge.d.ts +57 -0
  143. package/dist/health/capacity/merge.js +154 -0
  144. package/dist/health/capacity/merge.js.map +1 -0
  145. package/dist/health/capacity/registry.d.ts +40 -0
  146. package/dist/health/capacity/registry.js +106 -0
  147. package/dist/health/capacity/registry.js.map +1 -0
  148. package/dist/health/capacity/types.d.ts +73 -0
  149. package/dist/health/capacity/types.js +6 -0
  150. package/dist/health/capacity/types.js.map +1 -0
  151. package/dist/health/circuit-breaker/breaker.d.ts +91 -0
  152. package/dist/health/circuit-breaker/breaker.js +150 -0
  153. package/dist/health/circuit-breaker/breaker.js.map +1 -0
  154. package/dist/health/circuit-breaker/index.d.ts +2 -0
  155. package/dist/health/circuit-breaker/index.js +3 -0
  156. package/dist/health/circuit-breaker/index.js.map +1 -0
  157. package/dist/health/circuit-breaker/types.d.ts +52 -0
  158. package/dist/health/circuit-breaker/types.js +13 -0
  159. package/dist/health/circuit-breaker/types.js.map +1 -0
  160. package/dist/health/classifier/classify.d.ts +8 -0
  161. package/dist/health/classifier/classify.js +245 -0
  162. package/dist/health/classifier/classify.js.map +1 -0
  163. package/dist/health/classifier/index.d.ts +2 -0
  164. package/dist/health/classifier/index.js +3 -0
  165. package/dist/health/classifier/index.js.map +1 -0
  166. package/dist/health/classifier/types.d.ts +71 -0
  167. package/dist/health/classifier/types.js +27 -0
  168. package/dist/health/classifier/types.js.map +1 -0
  169. package/dist/health/index.d.ts +4 -0
  170. package/dist/health/index.js +5 -0
  171. package/dist/health/index.js.map +1 -0
  172. package/dist/health/resource-health/index.d.ts +4 -0
  173. package/dist/health/resource-health/index.js +5 -0
  174. package/dist/health/resource-health/index.js.map +1 -0
  175. package/dist/health/resource-health/key.d.ts +18 -0
  176. package/dist/health/resource-health/key.js +54 -0
  177. package/dist/health/resource-health/key.js.map +1 -0
  178. package/dist/health/resource-health/registry.d.ts +46 -0
  179. package/dist/health/resource-health/registry.js +276 -0
  180. package/dist/health/resource-health/registry.js.map +1 -0
  181. package/dist/health/resource-health/transitions.d.ts +9 -0
  182. package/dist/health/resource-health/transitions.js +157 -0
  183. package/dist/health/resource-health/transitions.js.map +1 -0
  184. package/dist/health/resource-health/types.d.ts +122 -0
  185. package/dist/health/resource-health/types.js +44 -0
  186. package/dist/health/resource-health/types.js.map +1 -0
  187. package/dist/index.d.ts +11 -0
  188. package/dist/index.js +105 -0
  189. package/dist/index.js.map +1 -0
  190. package/dist/plugin-id.d.ts +2 -0
  191. package/dist/plugin-id.js +3 -0
  192. package/dist/plugin-id.js.map +1 -0
  193. package/dist/rpc/definition.d.ts +123 -0
  194. package/dist/rpc/definition.js +130 -0
  195. package/dist/rpc/definition.js.map +1 -0
  196. package/dist/rpc/handlers.d.ts +53 -0
  197. package/dist/rpc/handlers.js +125 -0
  198. package/dist/rpc/handlers.js.map +1 -0
  199. package/dist/rpc/status.d.ts +42 -0
  200. package/dist/rpc/status.js +45 -0
  201. package/dist/rpc/status.js.map +1 -0
  202. package/dist/rpc.d.ts +10 -0
  203. package/dist/rpc.js +8 -0
  204. package/dist/rpc.js.map +1 -0
  205. package/dist/state/capacity/index.d.ts +3 -0
  206. package/dist/state/capacity/index.js +4 -0
  207. package/dist/state/capacity/index.js.map +1 -0
  208. package/dist/state/capacity/parse.d.ts +2 -0
  209. package/dist/state/capacity/parse.js +122 -0
  210. package/dist/state/capacity/parse.js.map +1 -0
  211. package/dist/state/capacity/store.d.ts +18 -0
  212. package/dist/state/capacity/store.js +78 -0
  213. package/dist/state/capacity/store.js.map +1 -0
  214. package/dist/state/capacity/types.d.ts +37 -0
  215. package/dist/state/capacity/types.js +11 -0
  216. package/dist/state/capacity/types.js.map +1 -0
  217. package/dist/state/health/index.d.ts +4 -0
  218. package/dist/state/health/index.js +4 -0
  219. package/dist/state/health/index.js.map +1 -0
  220. package/dist/state/health/parse.d.ts +2 -0
  221. package/dist/state/health/parse.js +137 -0
  222. package/dist/state/health/parse.js.map +1 -0
  223. package/dist/state/health/store.d.ts +17 -0
  224. package/dist/state/health/store.js +69 -0
  225. package/dist/state/health/store.js.map +1 -0
  226. package/dist/state/health/types.d.ts +23 -0
  227. package/dist/state/health/types.js +5 -0
  228. package/dist/state/health/types.js.map +1 -0
  229. package/dist/state/parked-work/index.d.ts +4 -0
  230. package/dist/state/parked-work/index.js +4 -0
  231. package/dist/state/parked-work/index.js.map +1 -0
  232. package/dist/state/parked-work/parse.d.ts +6 -0
  233. package/dist/state/parked-work/parse.js +83 -0
  234. package/dist/state/parked-work/parse.js.map +1 -0
  235. package/dist/state/parked-work/store.d.ts +17 -0
  236. package/dist/state/parked-work/store.js +98 -0
  237. package/dist/state/parked-work/store.js.map +1 -0
  238. package/dist/state/parked-work/types.d.ts +41 -0
  239. package/dist/state/parked-work/types.js +7 -0
  240. package/dist/state/parked-work/types.js.map +1 -0
  241. package/dist/state/receipts/bound.d.ts +14 -0
  242. package/dist/state/receipts/bound.js +77 -0
  243. package/dist/state/receipts/bound.js.map +1 -0
  244. package/dist/state/receipts/index.d.ts +6 -0
  245. package/dist/state/receipts/index.js +5 -0
  246. package/dist/state/receipts/index.js.map +1 -0
  247. package/dist/state/receipts/parse.d.ts +6 -0
  248. package/dist/state/receipts/parse.js +226 -0
  249. package/dist/state/receipts/parse.js.map +1 -0
  250. package/dist/state/receipts/store.d.ts +34 -0
  251. package/dist/state/receipts/store.js +148 -0
  252. package/dist/state/receipts/store.js.map +1 -0
  253. package/dist/state/receipts/types.d.ts +61 -0
  254. package/dist/state/receipts/types.js +12 -0
  255. package/dist/state/receipts/types.js.map +1 -0
  256. package/dist/state/session-modes/index.d.ts +4 -0
  257. package/dist/state/session-modes/index.js +4 -0
  258. package/dist/state/session-modes/index.js.map +1 -0
  259. package/dist/state/session-modes/parse.d.ts +8 -0
  260. package/dist/state/session-modes/parse.js +62 -0
  261. package/dist/state/session-modes/parse.js.map +1 -0
  262. package/dist/state/session-modes/store.d.ts +20 -0
  263. package/dist/state/session-modes/store.js +87 -0
  264. package/dist/state/session-modes/store.js.map +1 -0
  265. package/dist/state/session-modes/types.d.ts +41 -0
  266. package/dist/state/session-modes/types.js +7 -0
  267. package/dist/state/session-modes/types.js.map +1 -0
  268. package/dist/state/settings/index.d.ts +4 -0
  269. package/dist/state/settings/index.js +4 -0
  270. package/dist/state/settings/index.js.map +1 -0
  271. package/dist/state/settings/parse.d.ts +33 -0
  272. package/dist/state/settings/parse.js +261 -0
  273. package/dist/state/settings/parse.js.map +1 -0
  274. package/dist/state/settings/store.d.ts +21 -0
  275. package/dist/state/settings/store.js +65 -0
  276. package/dist/state/settings/store.js.map +1 -0
  277. package/dist/state/settings/types.d.ts +62 -0
  278. package/dist/state/settings/types.js +12 -0
  279. package/dist/state/settings/types.js.map +1 -0
  280. package/dist/state/tier-requests/index.d.ts +4 -0
  281. package/dist/state/tier-requests/index.js +4 -0
  282. package/dist/state/tier-requests/index.js.map +1 -0
  283. package/dist/state/tier-requests/parse.d.ts +3 -0
  284. package/dist/state/tier-requests/parse.js +53 -0
  285. package/dist/state/tier-requests/parse.js.map +1 -0
  286. package/dist/state/tier-requests/store.d.ts +27 -0
  287. package/dist/state/tier-requests/store.js +96 -0
  288. package/dist/state/tier-requests/store.js.map +1 -0
  289. package/dist/state/tier-requests/types.d.ts +30 -0
  290. package/dist/state/tier-requests/types.js +7 -0
  291. package/dist/state/tier-requests/types.js.map +1 -0
  292. package/dist/supervisor/index.d.ts +4 -0
  293. package/dist/supervisor/index.js +4 -0
  294. package/dist/supervisor/index.js.map +1 -0
  295. package/dist/supervisor/log.d.ts +10 -0
  296. package/dist/supervisor/log.js +14 -0
  297. package/dist/supervisor/log.js.map +1 -0
  298. package/dist/supervisor/supervisor.d.ts +86 -0
  299. package/dist/supervisor/supervisor.js +1629 -0
  300. package/dist/supervisor/supervisor.js.map +1 -0
  301. package/dist/supervisor/types.d.ts +49 -0
  302. package/dist/supervisor/types.js +3 -0
  303. package/dist/supervisor/types.js.map +1 -0
  304. package/dist/supervisor/view.d.ts +3 -0
  305. package/dist/supervisor/view.js +4 -0
  306. package/dist/supervisor/view.js.map +1 -0
  307. package/dist/tui.d.ts +15 -0
  308. package/dist/tui.js +256 -0
  309. package/dist/tui.js.map +1 -0
  310. package/dist/ui/gui/api.d.ts +17 -0
  311. package/dist/ui/gui/api.js +21 -0
  312. package/dist/ui/gui/api.js.map +1 -0
  313. package/dist/ui/gui/view.d.ts +26 -0
  314. package/dist/ui/gui/view.js +49 -0
  315. package/dist/ui/gui/view.js.map +1 -0
  316. package/dist/ui/tui/controller.d.ts +97 -0
  317. package/dist/ui/tui/controller.js +415 -0
  318. package/dist/ui/tui/controller.js.map +1 -0
  319. package/dist/ui/tui/menu.d.ts +55 -0
  320. package/dist/ui/tui/menu.js +176 -0
  321. package/dist/ui/tui/menu.js.map +1 -0
  322. package/dist/ui/tui/options.d.ts +19 -0
  323. package/dist/ui/tui/options.js +17 -0
  324. package/dist/ui/tui/options.js.map +1 -0
  325. package/dist/ui/tui/receipts.d.ts +21 -0
  326. package/dist/ui/tui/receipts.js +112 -0
  327. package/dist/ui/tui/receipts.js.map +1 -0
  328. package/dist/ui/tui/status.d.ts +22 -0
  329. package/dist/ui/tui/status.js +92 -0
  330. package/dist/ui/tui/status.js.map +1 -0
  331. package/dist/ui/tui/tiers.d.ts +51 -0
  332. package/dist/ui/tui/tiers.js +108 -0
  333. package/dist/ui/tui/tiers.js.map +1 -0
  334. package/package.json +85 -4
@@ -0,0 +1,32 @@
1
+ /** Build the supervisor's continuation ops on top of the host session domain. */
2
+ export function sessionOps(session, hooks) {
3
+ return {
4
+ settle: (sessionID) => session.wait({ sessionID }),
5
+ switchModel: (sessionID, model) => {
6
+ hooks?.beforeSwitch?.(sessionID, model);
7
+ return session.switchModel({
8
+ sessionID,
9
+ model: {
10
+ providerID: model.providerID,
11
+ id: model.id,
12
+ ...(model.variant !== undefined ? { variant: model.variant } : {}),
13
+ },
14
+ });
15
+ },
16
+ prompt: async (sessionID, text) => {
17
+ hooks?.beforePrompt?.(sessionID);
18
+ let delivered = false;
19
+ try {
20
+ await session.prompt({ sessionID, text });
21
+ delivered = true;
22
+ }
23
+ finally {
24
+ // The ownership mark is consumed by the prompt hook; if the prompt
25
+ // never reaches the hook (session gone, host error), the mark must
26
+ // not outlive the attempt and swallow a later user prompt.
27
+ hooks?.afterPrompt?.(sessionID, delivered);
28
+ }
29
+ },
30
+ };
31
+ }
32
+ //# sourceMappingURL=session-ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-ops.js","sourceRoot":"","sources":["../../../src/adapters/opencode/session-ops.ts"],"names":[],"mappings":"AAwCA,iFAAiF;AACjF,MAAM,UAAU,UAAU,CAAC,OAAyB,EAAE,KAAuB;IAC3E,OAAO;QACL,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC;QAClD,WAAW,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE;YAChC,KAAK,EAAE,YAAY,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;YACvC,OAAO,OAAO,CAAC,WAAW,CAAC;gBACzB,SAAS;gBACT,KAAK,EAAE;oBACL,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,EAAE,EAAE,KAAK,CAAC,EAAE;oBACZ,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACnE;aACF,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE;YAChC,KAAK,EAAE,YAAY,EAAE,CAAC,SAAS,CAAC,CAAA;YAChC,IAAI,SAAS,GAAG,KAAK,CAAA;YACrB,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;gBACzC,SAAS,GAAG,IAAI,CAAA;YAClB,CAAC;oBAAS,CAAC;gBACT,mEAAmE;gBACnE,mEAAmE;gBACnE,2DAA2D;gBAC3D,KAAK,EAAE,WAAW,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;YAC5C,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC","sourcesContent":["/**\n * Session operations seam (ADP-013/ADP-014/ADP-023/ADP-028). Implements the\n * supervisor's `ContinuationOps` on the host session domain: settle on the\n * host's experimental wait, switch model, deliver a prompt. Never replays a\n * failed request — prompting after a failure starts a NEW execution that\n * continues from session state (prompt strategy chosen by the supervisor).\n *\n * Switch self-tagging (verified limitation: `session.model.selected` fires for\n * manual AND plugin switches): `beforeSwitch` is invoked BEFORE the host\n * switch so the supervisor can record its own pending attribution note; the\n * resulting selection event is then attributed to Adaptive, never to the user.\n */\nimport type { SessionDomain } from \"@opencode/plugin/promise/session\"\n\n/** The session surface the ops actually use (structural — fixture-friendly). */\nexport type SessionOpsSource = Pick<SessionDomain, \"wait\" | \"switchModel\" | \"prompt\">\nimport type { ContinuationOps } from \"../../execution/continuation/types.js\"\nimport type { ModelRef } from \"../../core/work-unit/types.js\"\n\nexport interface SessionOpsHooks {\n /**\n * Called before every host `switchModel` this adapter performs, so wiring\n * can tag the switch as Adaptive's own (`noteOwnSwitch`).\n */\n readonly beforeSwitch?: (sessionID: string, model: ModelRef) => void\n /**\n * Called before the adapter prompts a continuation, so wiring can mark the\n * upcoming prompt-hook admission as owned (the continuation belongs to the\n * active unit and must not re-admit).\n */\n readonly beforePrompt?: (sessionID: string) => void\n /**\n * Called when the prompted call settles (success or failure), whether or\n * not the prompt hook fired — the counterpart that bounds the ownership\n * mark's lifetime. `delivered` is false exactly when the host prompt\n * rejected, so the hook can never fire for it.\n */\n readonly afterPrompt?: (sessionID: string, delivered: boolean) => void\n}\n\n/** Build the supervisor's continuation ops on top of the host session domain. */\nexport function sessionOps(session: SessionOpsSource, hooks?: SessionOpsHooks): ContinuationOps {\n return {\n settle: (sessionID) => session.wait({ sessionID }),\n switchModel: (sessionID, model) => {\n hooks?.beforeSwitch?.(sessionID, model)\n return session.switchModel({\n sessionID,\n model: {\n providerID: model.providerID,\n id: model.id,\n ...(model.variant !== undefined ? { variant: model.variant } : {}),\n },\n })\n },\n prompt: async (sessionID, text) => {\n hooks?.beforePrompt?.(sessionID)\n let delivered = false\n try {\n await session.prompt({ sessionID, text })\n delivered = true\n } finally {\n // The ownership mark is consumed by the prompt hook; if the prompt\n // never reaches the hook (session gone, host error), the mark must\n // not outlive the attempt and swallow a later user prompt.\n hooks?.afterPrompt?.(sessionID, delivered)\n }\n },\n }\n}\n"]}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Storage seam binding (ADP-030/ADP-031). The supervisor's state stores depend
3
+ * on a minimal `{ read, write }` seam; this module binds that seam to the
4
+ * host's `ctx.storage` under the fixed `coool.adaptive/...` keys. Values are
5
+ * JSON-serializable state payloads (settings/receipts/parked work).
6
+ */
7
+ import type { StorageDomain } from "@opencode/plugin/promise/storage";
8
+ /** The storage surface the seam actually uses (structural — fixture-friendly). */
9
+ export type StorageSource = Pick<StorageDomain, "get" | "set">;
10
+ export interface JsonSeam {
11
+ read(): Promise<unknown>;
12
+ write(value: unknown): Promise<void>;
13
+ }
14
+ /** Bind a storage key to the supervisor seam shape. */
15
+ export declare function storageSeam(key: string, storage: StorageSource): JsonSeam;
@@ -0,0 +1,8 @@
1
+ /** Bind a storage key to the supervisor seam shape. */
2
+ export function storageSeam(key, storage) {
3
+ return {
4
+ read: () => storage.get(key),
5
+ write: (value) => storage.set(key, value),
6
+ };
7
+ }
8
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/adapters/opencode/storage.ts"],"names":[],"mappings":"AAgBA,uDAAuD;AACvD,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,OAAsB;IAC7D,OAAO;QACL,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;QAC5B,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAA0C,CAAC;KAC/E,CAAA;AACH,CAAC","sourcesContent":["/**\n * Storage seam binding (ADP-030/ADP-031). The supervisor's state stores depend\n * on a minimal `{ read, write }` seam; this module binds that seam to the\n * host's `ctx.storage` under the fixed `coool.adaptive/...` keys. Values are\n * JSON-serializable state payloads (settings/receipts/parked work).\n */\nimport type { StorageDomain } from \"@opencode/plugin/promise/storage\"\n\n/** The storage surface the seam actually uses (structural — fixture-friendly). */\nexport type StorageSource = Pick<StorageDomain, \"get\" | \"set\">\n\nexport interface JsonSeam {\n read(): Promise<unknown>\n write(value: unknown): Promise<void>\n}\n\n/** Bind a storage key to the supervisor seam shape. */\nexport function storageSeam(key: string, storage: StorageSource): JsonSeam {\n return {\n read: () => storage.get(key),\n write: (value) => storage.set(key, value as Parameters<typeof storage.set>[1]),\n }\n}\n"]}
@@ -0,0 +1,37 @@
1
+ import type { TierName } from "../../core/tier-policy/types.js";
2
+ /** Records the agent's tier declaration; false = not accepted. */
3
+ export type TierRequestRecorder = (sessionID: string, tier: TierName) => boolean;
4
+ /**
5
+ * The agent-declared tier tool: a typed sibling of adaptive_escalate. The
6
+ * agent declares the tier of the task it is starting ("this task is quick")
7
+ * and the declaration steers the session's next admissions until cleared —
8
+ * one tier per task, not per unit. Plain JSON Schema: the host converts it,
9
+ * and a Standard Schema vendor is silently dropped on 2.2.5.
10
+ */
11
+ export declare function tierTool(record: TierRequestRecorder): {
12
+ name: string;
13
+ description: string;
14
+ input: {
15
+ readonly $schema: "https://json-schema.org/draft/2020-12/schema";
16
+ readonly type: "object";
17
+ readonly properties: {
18
+ readonly tier: {
19
+ readonly description: "The tier the current task needs.";
20
+ readonly enum: readonly ["quick", "standard", "advanced"];
21
+ };
22
+ };
23
+ readonly required: readonly ["tier"];
24
+ readonly additionalProperties: false;
25
+ };
26
+ options: {
27
+ readonly codemode: false;
28
+ };
29
+ execute: (input: unknown, context: {
30
+ sessionID: string;
31
+ }) => Promise<{
32
+ content: {
33
+ type: "text";
34
+ text: string;
35
+ }[];
36
+ }>;
37
+ };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * The agent-declared tier tool: a typed sibling of adaptive_escalate. The
3
+ * agent declares the tier of the task it is starting ("this task is quick")
4
+ * and the declaration steers the session's next admissions until cleared —
5
+ * one tier per task, not per unit. Plain JSON Schema: the host converts it,
6
+ * and a Standard Schema vendor is silently dropped on 2.2.5.
7
+ */
8
+ export function tierTool(record) {
9
+ return {
10
+ name: "adaptive_tier",
11
+ description: "Declare the capability tier of the task you are starting: quick " +
12
+ "(routine edits, mechanical steps), standard (the default), or " +
13
+ "advanced (multi-step design, broad refactors, hard debugging). " +
14
+ "The declaration stays in force for this session until you declare " +
15
+ "a different tier. Only declare when the task's tier differs from " +
16
+ "the default; never use this to work around unavailability.",
17
+ input: {
18
+ $schema: "https://json-schema.org/draft/2020-12/schema",
19
+ type: "object",
20
+ properties: {
21
+ tier: {
22
+ description: "The tier the current task needs.",
23
+ enum: ["quick", "standard", "advanced"],
24
+ },
25
+ },
26
+ required: ["tier"],
27
+ additionalProperties: false,
28
+ },
29
+ options: { codemode: false },
30
+ execute: (input, context) => {
31
+ const tier = readTier(input);
32
+ if (tier === null) {
33
+ return Promise.resolve({
34
+ content: [
35
+ {
36
+ type: "text",
37
+ text: "adaptive_tier rejected: tier must be quick, standard, or advanced.",
38
+ },
39
+ ],
40
+ });
41
+ }
42
+ const accepted = record(context.sessionID, tier);
43
+ if (!accepted) {
44
+ return Promise.resolve({
45
+ content: [
46
+ {
47
+ type: "text",
48
+ text: "adaptive_tier rejected: the tier request was not accepted.",
49
+ },
50
+ ],
51
+ });
52
+ }
53
+ return Promise.resolve({
54
+ content: [
55
+ {
56
+ type: "text",
57
+ text: `Tier request recorded: ${tier}. It steers this session's next admissions until cleared.`,
58
+ },
59
+ ],
60
+ });
61
+ },
62
+ };
63
+ }
64
+ function readTier(input) {
65
+ if (typeof input !== "object" || input === null)
66
+ return null;
67
+ const tier = input.tier;
68
+ if (tier !== "quick" && tier !== "standard" && tier !== "advanced")
69
+ return null;
70
+ return tier;
71
+ }
72
+ //# sourceMappingURL=tier-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier-tool.js","sourceRoot":"","sources":["../../../src/adapters/opencode/tier-tool.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,MAA2B;IAClD,OAAO;QACL,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,kEAAkE;YAClE,gEAAgE;YAChE,iEAAiE;YACjE,oEAAoE;YACpE,mEAAmE;YACnE,4DAA4D;QAC9D,KAAK,EAAE;YACL,OAAO,EAAE,8CAA8C;YACvD,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,WAAW,EAAE,kCAAkC;oBAC/C,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,CAAC;iBACxC;aACF;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;YAClB,oBAAoB,EAAE,KAAK;SACnB;QACV,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAW;QACrC,OAAO,EAAE,CACP,KAAc,EACd,OAA8B,EAC0B,EAAE;YAC1D,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;YAC5B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClB,OAAO,OAAO,CAAC,OAAO,CAAC;oBACrB,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,oEAAoE;yBAC3E;qBACF;iBACF,CAAC,CAAA;YACJ,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;YAChD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,OAAO,CAAC,OAAO,CAAC;oBACrB,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,4DAA4D;yBACnE;qBACF;iBACF,CAAC,CAAA;YACJ,CAAC;YACD,OAAO,OAAO,CAAC,OAAO,CAAC;gBACrB,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,0BAA0B,IAAI,2DAA2D;qBAChG;iBACF;aACF,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAC5D,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAA;IAC/C,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,UAAU;QAAE,OAAO,IAAI,CAAA;IAC/E,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["import type { TierName } from \"../../core/tier-policy/types.js\"\n\n/** Records the agent's tier declaration; false = not accepted. */\nexport type TierRequestRecorder = (sessionID: string, tier: TierName) => boolean\n\n/**\n * The agent-declared tier tool: a typed sibling of adaptive_escalate. The\n * agent declares the tier of the task it is starting (\"this task is quick\")\n * and the declaration steers the session's next admissions until cleared —\n * one tier per task, not per unit. Plain JSON Schema: the host converts it,\n * and a Standard Schema vendor is silently dropped on 2.2.5.\n */\nexport function tierTool(record: TierRequestRecorder) {\n return {\n name: \"adaptive_tier\",\n description:\n \"Declare the capability tier of the task you are starting: quick \" +\n \"(routine edits, mechanical steps), standard (the default), or \" +\n \"advanced (multi-step design, broad refactors, hard debugging). \" +\n \"The declaration stays in force for this session until you declare \" +\n \"a different tier. Only declare when the task's tier differs from \" +\n \"the default; never use this to work around unavailability.\",\n input: {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n type: \"object\",\n properties: {\n tier: {\n description: \"The tier the current task needs.\",\n enum: [\"quick\", \"standard\", \"advanced\"],\n },\n },\n required: [\"tier\"],\n additionalProperties: false,\n } as const,\n options: { codemode: false } as const,\n execute: (\n input: unknown,\n context: { sessionID: string },\n ): Promise<{ content: { type: \"text\"; text: string }[] }> => {\n const tier = readTier(input)\n if (tier === null) {\n return Promise.resolve({\n content: [\n {\n type: \"text\" as const,\n text: \"adaptive_tier rejected: tier must be quick, standard, or advanced.\",\n },\n ],\n })\n }\n const accepted = record(context.sessionID, tier)\n if (!accepted) {\n return Promise.resolve({\n content: [\n {\n type: \"text\" as const,\n text: \"adaptive_tier rejected: the tier request was not accepted.\",\n },\n ],\n })\n }\n return Promise.resolve({\n content: [\n {\n type: \"text\" as const,\n text: `Tier request recorded: ${tier}. It steers this session's next admissions until cleared.`,\n },\n ],\n })\n },\n }\n}\n\nfunction readTier(input: unknown): TierName | null {\n if (typeof input !== \"object\" || input === null) return null\n const tier = (input as { tier?: unknown }).tier\n if (tier !== \"quick\" && tier !== \"standard\" && tier !== \"advanced\") return null\n return tier\n}\n"]}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Adapter report types (ADP-025..ADP-031). The OpenCode adapter's only job is
3
+ * to observe host events and hooks and forward them as plain reports; every
4
+ * policy decision lives in the supervisor wiring. Report shapes mirror the
5
+ * verified `@opencode/plugin@2.2.5` surfaces structurally, so the adapter
6
+ * stays testable against typed fixtures without importing host internals
7
+ * beyond types.
8
+ */
9
+ import type { ModelRef } from "../../core/work-unit/types.js";
10
+ import type { RequestKind } from "../../core/tier-policy/types.js";
11
+ /**
12
+ * Structural mirror of the wire `Session.StructuredError` (also the classifier
13
+ * evidence source). Declared locally because `SessionError.Error` is not
14
+ * re-exported by `@opencode/plugin` — the host payloads are assignable to
15
+ * this shape.
16
+ */
17
+ export interface AdapterStructuredError {
18
+ readonly type: string;
19
+ readonly message: string;
20
+ readonly status?: number | undefined;
21
+ readonly response?: {
22
+ readonly body: string;
23
+ } | undefined;
24
+ readonly retryAfterMs?: number | undefined;
25
+ }
26
+ /** Work-unit lifecycle reports forwarded from `session.execution.*` events. */
27
+ export type ExecutionReport = {
28
+ kind: "execution-started";
29
+ sessionID: string;
30
+ at: number;
31
+ } | {
32
+ kind: "execution-succeeded";
33
+ sessionID: string;
34
+ at: number;
35
+ } | {
36
+ kind: "execution-failed";
37
+ sessionID: string;
38
+ at: number;
39
+ error: AdapterStructuredError;
40
+ } | {
41
+ kind: "execution-interrupted";
42
+ sessionID: string;
43
+ at: number;
44
+ reason: string;
45
+ } | {
46
+ kind: "model-selected";
47
+ sessionID: string;
48
+ at: number;
49
+ model: ModelRef;
50
+ };
51
+ /**
52
+ * Model request reports from the `context` hook (the agent loop, always
53
+ * `primary`) and the `model.request` hook (which carries the request kind for
54
+ * auxiliary requests — ADP-027).
55
+ */
56
+ export interface ModelRequestReport {
57
+ kind: "model-request";
58
+ sessionID: string;
59
+ model: ModelRef;
60
+ requestKind: RequestKind;
61
+ /** The agent the request runs under (ADP-002 role-hint routing evidence). */
62
+ agent?: string;
63
+ }
64
+ /**
65
+ * HTTP response evidence from the `http.response` hook. The response body is
66
+ * cloned exactly once and only a bounded excerpt is kept — the original body
67
+ * stays untouched for the host. WebSocket-backed providers bypass this hook
68
+ * entirely (verified limitation), so this evidence is never load-bearing.
69
+ */
70
+ export interface HttpResponseReport {
71
+ kind: "http-response";
72
+ sessionID: string;
73
+ status: number;
74
+ /** Raw `Retry-After` header value; the supervisor parses it, not the adapter. */
75
+ retryAfterHeader?: string | undefined;
76
+ bodyExcerpt?: string | undefined;
77
+ /**
78
+ * Captured quota-telemetry headers selected by the wiring-supplied capture
79
+ * predicate (an allowlist — no other header ever leaves the response, so
80
+ * credentials and cookies cannot leak). Bounded in count and value length.
81
+ */
82
+ capturedHeaders?: Readonly<Record<string, string>> | undefined;
83
+ }
84
+ /** Idle-boundary report from the `experimental.idle` hook (safe boundary). */
85
+ export interface IdleReport {
86
+ kind: "idle";
87
+ sessionID: string;
88
+ }
89
+ /**
90
+ * User-prompt report from the `session.hook("prompt")` hook. The hook is
91
+ * awaited BEFORE the turn's model resolution, so admission performed here
92
+ * lands on the very turn that triggered it — the event pump's
93
+ * execution-started report is asynchronous and races the turn (empirically
94
+ * verified on opencode 2.2.5).
95
+ */
96
+ export interface PromptReport {
97
+ kind: "prompt";
98
+ sessionID: string;
99
+ }
100
+ /** Everything the adapter forwards to the supervisor. */
101
+ export type EventReport = ExecutionReport | ModelRequestReport | HttpResponseReport | IdleReport | PromptReport;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/adapters/opencode/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Adapter report types (ADP-025..ADP-031). The OpenCode adapter's only job is\n * to observe host events and hooks and forward them as plain reports; every\n * policy decision lives in the supervisor wiring. Report shapes mirror the\n * verified `@opencode/plugin@2.2.5` surfaces structurally, so the adapter\n * stays testable against typed fixtures without importing host internals\n * beyond types.\n */\nimport type { ModelRef } from \"../../core/work-unit/types.js\"\nimport type { RequestKind } from \"../../core/tier-policy/types.js\"\n\n/**\n * Structural mirror of the wire `Session.StructuredError` (also the classifier\n * evidence source). Declared locally because `SessionError.Error` is not\n * re-exported by `@opencode/plugin` — the host payloads are assignable to\n * this shape.\n */\nexport interface AdapterStructuredError {\n readonly type: string\n readonly message: string\n readonly status?: number | undefined\n readonly response?: { readonly body: string } | undefined\n readonly retryAfterMs?: number | undefined\n}\n\n/** Work-unit lifecycle reports forwarded from `session.execution.*` events. */\nexport type ExecutionReport =\n | { kind: \"execution-started\"; sessionID: string; at: number }\n | { kind: \"execution-succeeded\"; sessionID: string; at: number }\n | { kind: \"execution-failed\"; sessionID: string; at: number; error: AdapterStructuredError }\n | { kind: \"execution-interrupted\"; sessionID: string; at: number; reason: string }\n | { kind: \"model-selected\"; sessionID: string; at: number; model: ModelRef }\n\n/**\n * Model request reports from the `context` hook (the agent loop, always\n * `primary`) and the `model.request` hook (which carries the request kind for\n * auxiliary requests — ADP-027).\n */\nexport interface ModelRequestReport {\n kind: \"model-request\"\n sessionID: string\n model: ModelRef\n requestKind: RequestKind\n /** The agent the request runs under (ADP-002 role-hint routing evidence). */\n agent?: string\n}\n\n/**\n * HTTP response evidence from the `http.response` hook. The response body is\n * cloned exactly once and only a bounded excerpt is kept — the original body\n * stays untouched for the host. WebSocket-backed providers bypass this hook\n * entirely (verified limitation), so this evidence is never load-bearing.\n */\nexport interface HttpResponseReport {\n kind: \"http-response\"\n sessionID: string\n status: number\n /** Raw `Retry-After` header value; the supervisor parses it, not the adapter. */\n retryAfterHeader?: string | undefined\n bodyExcerpt?: string | undefined\n /**\n * Captured quota-telemetry headers selected by the wiring-supplied capture\n * predicate (an allowlist — no other header ever leaves the response, so\n * credentials and cookies cannot leak). Bounded in count and value length.\n */\n capturedHeaders?: Readonly<Record<string, string>> | undefined\n}\n\n/** Idle-boundary report from the `experimental.idle` hook (safe boundary). */\nexport interface IdleReport {\n kind: \"idle\"\n sessionID: string\n}\n\n/**\n * User-prompt report from the `session.hook(\"prompt\")` hook. The hook is\n * awaited BEFORE the turn's model resolution, so admission performed here\n * lands on the very turn that triggered it — the event pump's\n * execution-started report is asynchronous and races the turn (empirically\n * verified on opencode 2.2.5).\n */\nexport interface PromptReport {\n kind: \"prompt\"\n sessionID: string\n}\n\n/** Everything the adapter forwards to the supervisor. */\nexport type EventReport =\n ExecutionReport | ModelRequestReport | HttpResponseReport | IdleReport | PromptReport\n"]}
@@ -0,0 +1,7 @@
1
+ import type { CandidateModel, Demand, Verdict } from "./types.js";
2
+ /**
3
+ * Run every check and accumulate reasons in fixed order. A candidate is
4
+ * compatible only when no reason applies; unknown candidate metadata never
5
+ * satisfies a stated requirement.
6
+ */
7
+ export declare function checkCompatibility(candidate: CandidateModel, demand: Demand): Verdict;
@@ -0,0 +1,51 @@
1
+ /** A finite, non-negative token count is assessable; anything else is unknown demand. */
2
+ function assessableTokens(value) {
3
+ return value !== undefined && Number.isFinite(value) && value >= 0;
4
+ }
5
+ function supportsModalities(supported, demanded) {
6
+ if (supported === undefined) {
7
+ return false;
8
+ }
9
+ return demanded.every((modality) => supported.includes(modality));
10
+ }
11
+ /**
12
+ * Run every check and accumulate reasons in fixed order. A candidate is
13
+ * compatible only when no reason applies; unknown candidate metadata never
14
+ * satisfies a stated requirement.
15
+ */
16
+ export function checkCompatibility(candidate, demand) {
17
+ const reasons = [];
18
+ if (candidate.providerEnabled !== true) {
19
+ reasons.push("provider-unavailable");
20
+ }
21
+ if (candidate.enabled !== true) {
22
+ reasons.push("model-unavailable");
23
+ }
24
+ if (candidate.variant !== undefined && candidate.variantAvailable !== true) {
25
+ reasons.push("variant-unavailable");
26
+ }
27
+ if (demand.tools === true && candidate.capabilities?.tools !== true) {
28
+ reasons.push("tool-use-unsupported");
29
+ }
30
+ if (demand.input !== undefined &&
31
+ demand.input.length > 0 &&
32
+ !supportsModalities(candidate.capabilities?.input, demand.input)) {
33
+ reasons.push("input-modality-unsupported");
34
+ }
35
+ if (demand.output !== undefined &&
36
+ demand.output.length > 0 &&
37
+ !supportsModalities(candidate.capabilities?.output, demand.output)) {
38
+ reasons.push("output-modality-unsupported");
39
+ }
40
+ if (assessableTokens(demand.contextTokens)) {
41
+ const contextLimit = candidate.limit?.context;
42
+ if (!assessableTokens(contextLimit)) {
43
+ reasons.push("context-capacity-unknown");
44
+ }
45
+ else if (contextLimit < demand.contextTokens) {
46
+ reasons.push("context-capacity-insufficient");
47
+ }
48
+ }
49
+ return { compatible: reasons.length === 0, reasons };
50
+ }
51
+ //# sourceMappingURL=gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.js","sourceRoot":"","sources":["../../../src/core/compatibility/gate.ts"],"names":[],"mappings":"AAEA,yFAAyF;AACzF,SAAS,gBAAgB,CAAC,KAAyB;IACjD,OAAO,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;AACpE,CAAC;AAED,SAAS,kBAAkB,CACzB,SAAwC,EACxC,QAA2B;IAE3B,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAA;IACd,CAAC;IACD,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAyB,EAAE,MAAc;IAC1E,MAAM,OAAO,GAA4B,EAAE,CAAA;IAE3C,IAAI,SAAS,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;IACtC,CAAC;IACD,IAAI,SAAS,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;IACnC,CAAC;IACD,IAAI,SAAS,CAAC,OAAO,KAAK,SAAS,IAAI,SAAS,CAAC,gBAAgB,KAAK,IAAI,EAAE,CAAC;QAC3E,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;IACrC,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,SAAS,CAAC,YAAY,EAAE,KAAK,KAAK,IAAI,EAAE,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;IACtC,CAAC;IACD,IACE,MAAM,CAAC,KAAK,KAAK,SAAS;QAC1B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QACvB,CAAC,kBAAkB,CAAC,SAAS,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAChE,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAA;IAC5C,CAAC;IACD,IACE,MAAM,CAAC,MAAM,KAAK,SAAS;QAC3B,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QACxB,CAAC,kBAAkB,CAAC,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAClE,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAA;IAC7C,CAAC;IAED,IAAI,gBAAgB,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,EAAE,OAAO,CAAA;QAC7C,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAA;QAC1C,CAAC;aAAM,IAAI,YAAY,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;YAC/C,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAA;QAC/C,CAAC;IACH,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,EAAE,CAAA;AACtD,CAAC","sourcesContent":["import type { CandidateModel, Demand, IncompatibilityReason, Verdict } from \"./types.js\"\n\n/** A finite, non-negative token count is assessable; anything else is unknown demand. */\nfunction assessableTokens(value: number | undefined): value is number {\n return value !== undefined && Number.isFinite(value) && value >= 0\n}\n\nfunction supportsModalities(\n supported: readonly string[] | undefined,\n demanded: readonly string[],\n): boolean {\n if (supported === undefined) {\n return false\n }\n return demanded.every((modality) => supported.includes(modality))\n}\n\n/**\n * Run every check and accumulate reasons in fixed order. A candidate is\n * compatible only when no reason applies; unknown candidate metadata never\n * satisfies a stated requirement.\n */\nexport function checkCompatibility(candidate: CandidateModel, demand: Demand): Verdict {\n const reasons: IncompatibilityReason[] = []\n\n if (candidate.providerEnabled !== true) {\n reasons.push(\"provider-unavailable\")\n }\n if (candidate.enabled !== true) {\n reasons.push(\"model-unavailable\")\n }\n if (candidate.variant !== undefined && candidate.variantAvailable !== true) {\n reasons.push(\"variant-unavailable\")\n }\n\n if (demand.tools === true && candidate.capabilities?.tools !== true) {\n reasons.push(\"tool-use-unsupported\")\n }\n if (\n demand.input !== undefined &&\n demand.input.length > 0 &&\n !supportsModalities(candidate.capabilities?.input, demand.input)\n ) {\n reasons.push(\"input-modality-unsupported\")\n }\n if (\n demand.output !== undefined &&\n demand.output.length > 0 &&\n !supportsModalities(candidate.capabilities?.output, demand.output)\n ) {\n reasons.push(\"output-modality-unsupported\")\n }\n\n if (assessableTokens(demand.contextTokens)) {\n const contextLimit = candidate.limit?.context\n if (!assessableTokens(contextLimit)) {\n reasons.push(\"context-capacity-unknown\")\n } else if (contextLimit < demand.contextTokens) {\n reasons.push(\"context-capacity-insufficient\")\n }\n }\n\n return { compatible: reasons.length === 0, reasons }\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export * from "./types.js";
2
+ export * from "./gate.js";
@@ -0,0 +1,3 @@
1
+ export * from "./types.js";
2
+ export * from "./gate.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/compatibility/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA","sourcesContent":["export * from \"./types.js\"\nexport * from \"./gate.js\"\n"]}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Compatibility gate (ADP-017): filters candidates on context capacity,
3
+ * tool use, modalities, and model/variant/provider availability BEFORE
4
+ * health/preference ranking. Pure — adapters map OpenCode `Model.Info` /
5
+ * `Provider.Info` into `CandidateModel`, this module never touches
6
+ * `@opencode/plugin` types.
7
+ *
8
+ * Conservative rule: metadata the gate needs but cannot see is treated as
9
+ * NOT satisfying the requirement (e.g. unknown `enabled`, unknown tool
10
+ * support, unknown context limit). Only demand-side quantities that are
11
+ * themselves unknown are skipped — there is nothing to check against.
12
+ */
13
+ /** What the executing work needs from a resource. All demand fields are optional. */
14
+ export interface Demand {
15
+ /** The unit needs tool use. `undefined`/`false` imposes no tool requirement. */
16
+ readonly tools?: boolean | undefined;
17
+ /** Input modalities the unit carries (e.g. `"text"`, `"image"`). */
18
+ readonly input?: readonly string[] | undefined;
19
+ /** Output modalities the unit must produce. */
20
+ readonly output?: readonly string[] | undefined;
21
+ /** Known or estimated context need in tokens; `undefined` skips the capacity check. */
22
+ readonly contextTokens?: number | undefined;
23
+ }
24
+ /** Adapter-normalized view of one candidate resource. */
25
+ export interface CandidateModel {
26
+ readonly providerID: string;
27
+ readonly modelID: string;
28
+ readonly variant?: string | undefined;
29
+ /** Model is enabled in the host inventory. Unknown ⇒ conservative reject. */
30
+ readonly enabled?: boolean | undefined;
31
+ /** Provider is available in the host inventory. Unknown ⇒ conservative reject. */
32
+ readonly providerEnabled?: boolean | undefined;
33
+ /** The requested variant exists for this model. Unknown ⇒ conservative reject. */
34
+ readonly variantAvailable?: boolean | undefined;
35
+ readonly capabilities?: {
36
+ readonly tools?: boolean | undefined;
37
+ readonly input?: readonly string[] | undefined;
38
+ readonly output?: readonly string[] | undefined;
39
+ } | undefined;
40
+ readonly limit?: {
41
+ readonly context?: number | undefined;
42
+ } | undefined;
43
+ }
44
+ /**
45
+ * Why a candidate failed the gate, in the fixed order the checks run:
46
+ * availability → tools → input modalities → output modalities → context.
47
+ */
48
+ export declare const INCOMPATIBILITY_REASONS: readonly ["provider-unavailable", "model-unavailable", "variant-unavailable", "tool-use-unsupported", "input-modality-unsupported", "output-modality-unsupported", "context-capacity-insufficient", "context-capacity-unknown"];
49
+ export type IncompatibilityReason = (typeof INCOMPATIBILITY_REASONS)[number];
50
+ export interface Verdict {
51
+ readonly compatible: boolean;
52
+ readonly reasons: readonly IncompatibilityReason[];
53
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Compatibility gate (ADP-017): filters candidates on context capacity,
3
+ * tool use, modalities, and model/variant/provider availability BEFORE
4
+ * health/preference ranking. Pure — adapters map OpenCode `Model.Info` /
5
+ * `Provider.Info` into `CandidateModel`, this module never touches
6
+ * `@opencode/plugin` types.
7
+ *
8
+ * Conservative rule: metadata the gate needs but cannot see is treated as
9
+ * NOT satisfying the requirement (e.g. unknown `enabled`, unknown tool
10
+ * support, unknown context limit). Only demand-side quantities that are
11
+ * themselves unknown are skipped — there is nothing to check against.
12
+ */
13
+ /**
14
+ * Why a candidate failed the gate, in the fixed order the checks run:
15
+ * availability → tools → input modalities → output modalities → context.
16
+ */
17
+ export const INCOMPATIBILITY_REASONS = [
18
+ "provider-unavailable",
19
+ "model-unavailable",
20
+ "variant-unavailable",
21
+ "tool-use-unsupported",
22
+ "input-modality-unsupported",
23
+ "output-modality-unsupported",
24
+ "context-capacity-insufficient",
25
+ "context-capacity-unknown",
26
+ ];
27
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/compatibility/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAmCH;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,sBAAsB;IACtB,mBAAmB;IACnB,qBAAqB;IACrB,sBAAsB;IACtB,4BAA4B;IAC5B,6BAA6B;IAC7B,+BAA+B;IAC/B,0BAA0B;CACU,CAAA","sourcesContent":["/**\n * Compatibility gate (ADP-017): filters candidates on context capacity,\n * tool use, modalities, and model/variant/provider availability BEFORE\n * health/preference ranking. Pure — adapters map OpenCode `Model.Info` /\n * `Provider.Info` into `CandidateModel`, this module never touches\n * `@opencode/plugin` types.\n *\n * Conservative rule: metadata the gate needs but cannot see is treated as\n * NOT satisfying the requirement (e.g. unknown `enabled`, unknown tool\n * support, unknown context limit). Only demand-side quantities that are\n * themselves unknown are skipped — there is nothing to check against.\n */\n\n/** What the executing work needs from a resource. All demand fields are optional. */\nexport interface Demand {\n /** The unit needs tool use. `undefined`/`false` imposes no tool requirement. */\n readonly tools?: boolean | undefined\n /** Input modalities the unit carries (e.g. `\"text\"`, `\"image\"`). */\n readonly input?: readonly string[] | undefined\n /** Output modalities the unit must produce. */\n readonly output?: readonly string[] | undefined\n /** Known or estimated context need in tokens; `undefined` skips the capacity check. */\n readonly contextTokens?: number | undefined\n}\n\n/** Adapter-normalized view of one candidate resource. */\nexport interface CandidateModel {\n readonly providerID: string\n readonly modelID: string\n readonly variant?: string | undefined\n /** Model is enabled in the host inventory. Unknown ⇒ conservative reject. */\n readonly enabled?: boolean | undefined\n /** Provider is available in the host inventory. Unknown ⇒ conservative reject. */\n readonly providerEnabled?: boolean | undefined\n /** The requested variant exists for this model. Unknown ⇒ conservative reject. */\n readonly variantAvailable?: boolean | undefined\n readonly capabilities?:\n | {\n readonly tools?: boolean | undefined\n readonly input?: readonly string[] | undefined\n readonly output?: readonly string[] | undefined\n }\n | undefined\n readonly limit?: { readonly context?: number | undefined } | undefined\n}\n\n/**\n * Why a candidate failed the gate, in the fixed order the checks run:\n * availability → tools → input modalities → output modalities → context.\n */\nexport const INCOMPATIBILITY_REASONS = [\n \"provider-unavailable\",\n \"model-unavailable\",\n \"variant-unavailable\",\n \"tool-use-unsupported\",\n \"input-modality-unsupported\",\n \"output-modality-unsupported\",\n \"context-capacity-insufficient\",\n \"context-capacity-unknown\",\n] as const satisfies readonly string[]\n\nexport type IncompatibilityReason = (typeof INCOMPATIBILITY_REASONS)[number]\n\nexport interface Verdict {\n readonly compatible: boolean\n readonly reasons: readonly IncompatibilityReason[]\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import type { AdmissionDecision, SchedulerInput } from "./types.js";
2
+ /**
3
+ * Decide the model for a fresh work unit. Total and deterministic: the same
4
+ * input always yields the same decision, and the function has no effects.
5
+ */
6
+ export declare function admit(input: SchedulerInput): AdmissionDecision;