@code-yeongyu/senpi 2026.8.30 → 2026.9.2-3

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 (430) hide show
  1. package/CHANGELOG.md +234 -4
  2. package/README.md +3 -0
  3. package/dist/core/agent-session.d.ts +29 -0
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +168 -18
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/compaction/compaction-execution.d.ts +14 -0
  8. package/dist/core/compaction/compaction-execution.d.ts.map +1 -0
  9. package/dist/core/compaction/compaction-execution.js +121 -0
  10. package/dist/core/compaction/compaction-execution.js.map +1 -0
  11. package/dist/core/compaction/compaction-settings.d.ts +17 -0
  12. package/dist/core/compaction/compaction-settings.d.ts.map +1 -0
  13. package/dist/core/compaction/compaction-settings.js +17 -0
  14. package/dist/core/compaction/compaction-settings.js.map +1 -0
  15. package/dist/core/compaction/compaction.d.ts +13 -26
  16. package/dist/core/compaction/compaction.d.ts.map +1 -1
  17. package/dist/core/compaction/compaction.js +7 -136
  18. package/dist/core/compaction/compaction.js.map +1 -1
  19. package/dist/core/compaction/ideal-compaction-settings.d.ts +9 -0
  20. package/dist/core/compaction/ideal-compaction-settings.d.ts.map +1 -0
  21. package/dist/core/compaction/ideal-compaction-settings.js +7 -0
  22. package/dist/core/compaction/ideal-compaction-settings.js.map +1 -0
  23. package/dist/core/compaction-settings-access.d.ts +19 -0
  24. package/dist/core/compaction-settings-access.d.ts.map +1 -0
  25. package/dist/core/compaction-settings-access.js +10 -0
  26. package/dist/core/compaction-settings-access.js.map +1 -0
  27. package/dist/core/compaction-settings-resolver.d.ts +22 -0
  28. package/dist/core/compaction-settings-resolver.d.ts.map +1 -0
  29. package/dist/core/compaction-settings-resolver.js +46 -0
  30. package/dist/core/compaction-settings-resolver.js.map +1 -0
  31. package/dist/core/extensions/builtin/claude-sdk-oauth/options.d.ts.map +1 -1
  32. package/dist/core/extensions/builtin/claude-sdk-oauth/options.js +6 -2
  33. package/dist/core/extensions/builtin/claude-sdk-oauth/options.js.map +1 -1
  34. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts +9 -1
  35. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts.map +1 -1
  36. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js +10 -3
  37. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js.map +1 -1
  38. package/dist/core/extensions/builtin/claude-sdk-oauth/stream.d.ts.map +1 -1
  39. package/dist/core/extensions/builtin/claude-sdk-oauth/stream.js +2 -1
  40. package/dist/core/extensions/builtin/claude-sdk-oauth/stream.js.map +1 -1
  41. package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts +24 -0
  42. package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts.map +1 -0
  43. package/dist/core/extensions/builtin/compaction/context-pipeline.js +43 -0
  44. package/dist/core/extensions/builtin/compaction/context-pipeline.js.map +1 -0
  45. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +1 -1
  46. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
  47. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +8 -2
  48. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
  49. package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts +17 -0
  50. package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts.map +1 -0
  51. package/dist/core/extensions/builtin/compaction/emergency-prune.js +64 -0
  52. package/dist/core/extensions/builtin/compaction/emergency-prune.js.map +1 -0
  53. package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts +27 -0
  54. package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts.map +1 -0
  55. package/dist/core/extensions/builtin/compaction/extension-wiring.js +84 -0
  56. package/dist/core/extensions/builtin/compaction/extension-wiring.js.map +1 -0
  57. package/dist/core/extensions/builtin/compaction/idle-retry.d.ts +1 -1
  58. package/dist/core/extensions/builtin/compaction/idle-retry.d.ts.map +1 -1
  59. package/dist/core/extensions/builtin/compaction/idle-retry.js +1 -1
  60. package/dist/core/extensions/builtin/compaction/idle-retry.js.map +1 -1
  61. package/dist/core/extensions/builtin/compaction/idle.d.ts +1 -0
  62. package/dist/core/extensions/builtin/compaction/idle.d.ts.map +1 -1
  63. package/dist/core/extensions/builtin/compaction/idle.js +13 -2
  64. package/dist/core/extensions/builtin/compaction/idle.js.map +1 -1
  65. package/dist/core/extensions/builtin/compaction/index.d.ts +1 -1
  66. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  67. package/dist/core/extensions/builtin/compaction/index.js +152 -154
  68. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  69. package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
  70. package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
  71. package/dist/core/extensions/builtin/compaction/log.js +2 -0
  72. package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
  73. package/dist/core/extensions/builtin/compaction/model-selection.d.ts +14 -0
  74. package/dist/core/extensions/builtin/compaction/model-selection.d.ts.map +1 -0
  75. package/dist/core/extensions/builtin/compaction/model-selection.js +37 -0
  76. package/dist/core/extensions/builtin/compaction/model-selection.js.map +1 -0
  77. package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts +30 -0
  78. package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts.map +1 -0
  79. package/dist/core/extensions/builtin/compaction/model-usability-budget.js +74 -0
  80. package/dist/core/extensions/builtin/compaction/model-usability-budget.js.map +1 -0
  81. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts +9 -0
  82. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts.map +1 -0
  83. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js +2 -0
  84. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js.map +1 -0
  85. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +3 -6
  86. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -1
  87. package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -1
  88. package/dist/core/extensions/builtin/compaction/orchestration.d.ts +46 -0
  89. package/dist/core/extensions/builtin/compaction/orchestration.d.ts.map +1 -0
  90. package/dist/core/extensions/builtin/compaction/orchestration.js +103 -0
  91. package/dist/core/extensions/builtin/compaction/orchestration.js.map +1 -0
  92. package/dist/core/extensions/builtin/compaction/policy.d.ts +12 -2
  93. package/dist/core/extensions/builtin/compaction/policy.d.ts.map +1 -1
  94. package/dist/core/extensions/builtin/compaction/policy.js +52 -26
  95. package/dist/core/extensions/builtin/compaction/policy.js.map +1 -1
  96. package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts +8 -0
  97. package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts.map +1 -0
  98. package/dist/core/extensions/builtin/compaction/speculation-lead.js +17 -0
  99. package/dist/core/extensions/builtin/compaction/speculation-lead.js.map +1 -0
  100. package/dist/core/extensions/builtin/compaction/speculative-job.d.ts +22 -0
  101. package/dist/core/extensions/builtin/compaction/speculative-job.d.ts.map +1 -0
  102. package/dist/core/extensions/builtin/compaction/speculative-job.js +16 -0
  103. package/dist/core/extensions/builtin/compaction/speculative-job.js.map +1 -0
  104. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts +23 -0
  105. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -0
  106. package/dist/core/extensions/builtin/compaction/speculative-summary.js +132 -0
  107. package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -0
  108. package/dist/core/extensions/builtin/compaction/speculative.d.ts +8 -13
  109. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  110. package/dist/core/extensions/builtin/compaction/speculative.js +21 -197
  111. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  112. package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts +24 -0
  113. package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts.map +1 -0
  114. package/dist/core/extensions/builtin/compaction/token-budget-reminder.js +25 -0
  115. package/dist/core/extensions/builtin/compaction/token-budget-reminder.js.map +1 -0
  116. package/dist/core/extensions/builtin/compaction/tool-admission.d.ts +27 -0
  117. package/dist/core/extensions/builtin/compaction/tool-admission.d.ts.map +1 -0
  118. package/dist/core/extensions/builtin/compaction/tool-admission.js +56 -0
  119. package/dist/core/extensions/builtin/compaction/tool-admission.js.map +1 -0
  120. package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts +5 -0
  121. package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts.map +1 -0
  122. package/dist/core/extensions/builtin/hooks/trust-state-json.js +76 -0
  123. package/dist/core/extensions/builtin/hooks/trust-state-json.js.map +1 -0
  124. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts +7 -1
  125. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts.map +1 -1
  126. package/dist/core/extensions/builtin/hooks/trust-storage.js +60 -8
  127. package/dist/core/extensions/builtin/hooks/trust-storage.js.map +1 -1
  128. package/dist/core/extensions/builtin/hooks/trust.d.ts +1 -2
  129. package/dist/core/extensions/builtin/hooks/trust.d.ts.map +1 -1
  130. package/dist/core/extensions/builtin/hooks/trust.js +1 -72
  131. package/dist/core/extensions/builtin/hooks/trust.js.map +1 -1
  132. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts +3 -0
  133. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts.map +1 -0
  134. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +110 -0
  135. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js.map +1 -0
  136. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.d.ts.map +1 -1
  137. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +2 -1
  138. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js.map +1 -1
  139. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.d.ts.map +1 -1
  140. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.js +7 -1
  141. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.js.map +1 -1
  142. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.d.ts.map +1 -1
  143. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.js +7 -1
  144. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.js.map +1 -1
  145. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.d.ts.map +1 -1
  146. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.js +7 -1
  147. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.js.map +1 -1
  148. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.d.ts.map +1 -1
  149. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.js +7 -1
  150. package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.js.map +1 -1
  151. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.d.ts.map +1 -1
  152. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js +2 -1
  153. package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js.map +1 -1
  154. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.d.ts +50 -0
  155. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.d.ts.map +1 -0
  156. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.js +66 -0
  157. package/dist/core/extensions/builtin/prompt-preset/execution-tooling.js.map +1 -0
  158. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts +5 -1
  159. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
  160. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +6 -1
  161. package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
  162. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-6.d.ts.map +1 -1
  163. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-6.js +11 -1
  164. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-6.js.map +1 -1
  165. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.d.ts.map +1 -1
  166. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.js +11 -1
  167. package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.js.map +1 -1
  168. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.d.ts.map +1 -1
  169. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +2 -1
  170. package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js.map +1 -1
  171. package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
  172. package/dist/core/extensions/builtin/prompt-preset/presets.js +18 -1
  173. package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
  174. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
  175. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
  176. package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
  177. package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
  178. package/dist/core/extensions/builtin/recommended-models/index.d.ts +1 -1
  179. package/dist/core/extensions/builtin/recommended-models/index.d.ts.map +1 -1
  180. package/dist/core/extensions/builtin/recommended-models/index.js +1 -1
  181. package/dist/core/extensions/builtin/recommended-models/index.js.map +1 -1
  182. package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +11 -0
  183. package/dist/core/extensions/builtin/terminal/runtime-session.d.ts.map +1 -1
  184. package/dist/core/extensions/builtin/terminal/runtime-session.js +18 -2
  185. package/dist/core/extensions/builtin/terminal/runtime-session.js.map +1 -1
  186. package/dist/core/extensions/builtin/ttsr/index.d.ts.map +1 -1
  187. package/dist/core/extensions/builtin/ttsr/index.js +4 -0
  188. package/dist/core/extensions/builtin/ttsr/index.js.map +1 -1
  189. package/dist/core/extensions/builtin/ttsr/manager.d.ts +2 -0
  190. package/dist/core/extensions/builtin/ttsr/manager.d.ts.map +1 -1
  191. package/dist/core/extensions/builtin/ttsr/manager.js +28 -1
  192. package/dist/core/extensions/builtin/ttsr/manager.js.map +1 -1
  193. package/dist/core/extensions/runner.d.ts +5 -0
  194. package/dist/core/extensions/runner.d.ts.map +1 -1
  195. package/dist/core/extensions/runner.js +7 -0
  196. package/dist/core/extensions/runner.js.map +1 -1
  197. package/dist/core/provider-composer.d.ts.map +1 -1
  198. package/dist/core/provider-composer.js +17 -8
  199. package/dist/core/provider-composer.js.map +1 -1
  200. package/dist/core/retry-fallback/controller.d.ts +14 -0
  201. package/dist/core/retry-fallback/controller.d.ts.map +1 -1
  202. package/dist/core/retry-fallback/controller.js +33 -3
  203. package/dist/core/retry-fallback/controller.js.map +1 -1
  204. package/dist/core/retry-fallback/log.js +1 -1
  205. package/dist/core/retry-fallback/log.js.map +1 -1
  206. package/dist/core/retry-fallback/settings.d.ts.map +1 -1
  207. package/dist/core/retry-fallback/settings.js +1 -0
  208. package/dist/core/retry-fallback/settings.js.map +1 -1
  209. package/dist/core/sdk.d.ts.map +1 -1
  210. package/dist/core/sdk.js +5 -0
  211. package/dist/core/sdk.js.map +1 -1
  212. package/dist/core/session-activity.d.ts +47 -0
  213. package/dist/core/session-activity.d.ts.map +1 -0
  214. package/dist/core/session-activity.js +58 -0
  215. package/dist/core/session-activity.js.map +1 -0
  216. package/dist/core/session-manager.d.ts +8 -12
  217. package/dist/core/session-manager.d.ts.map +1 -1
  218. package/dist/core/session-manager.js +118 -7
  219. package/dist/core/session-manager.js.map +1 -1
  220. package/dist/core/session-resident-store.d.ts +8 -1
  221. package/dist/core/session-resident-store.d.ts.map +1 -1
  222. package/dist/core/session-resident-store.js +12 -5
  223. package/dist/core/session-resident-store.js.map +1 -1
  224. package/dist/core/settings-manager.d.ts +10 -87
  225. package/dist/core/settings-manager.d.ts.map +1 -1
  226. package/dist/core/settings-manager.js +14 -20
  227. package/dist/core/settings-manager.js.map +1 -1
  228. package/dist/core/settings-public-types.d.ts +11 -0
  229. package/dist/core/settings-public-types.d.ts.map +1 -0
  230. package/dist/core/settings-public-types.js +2 -0
  231. package/dist/core/settings-public-types.js.map +1 -0
  232. package/dist/core/settings-shapes.d.ts +36 -0
  233. package/dist/core/settings-shapes.d.ts.map +1 -0
  234. package/dist/core/settings-shapes.js +2 -0
  235. package/dist/core/settings-shapes.js.map +1 -0
  236. package/dist/core/shared-host-policy.d.ts +6 -0
  237. package/dist/core/shared-host-policy.d.ts.map +1 -0
  238. package/dist/core/shared-host-policy.js +7 -0
  239. package/dist/core/shared-host-policy.js.map +1 -0
  240. package/dist/core/terminal-settings.d.ts +22 -0
  241. package/dist/core/terminal-settings.d.ts.map +1 -0
  242. package/dist/core/terminal-settings.js +2 -0
  243. package/dist/core/terminal-settings.js.map +1 -0
  244. package/dist/index.d.ts +1 -1
  245. package/dist/index.d.ts.map +1 -1
  246. package/dist/index.js +1 -1
  247. package/dist/index.js.map +1 -1
  248. package/dist/main.d.ts +4 -4
  249. package/dist/main.d.ts.map +1 -1
  250. package/dist/main.js +27 -11
  251. package/dist/main.js.map +1 -1
  252. package/dist/modes/app-server/daemon/process.d.ts +13 -2
  253. package/dist/modes/app-server/daemon/process.d.ts.map +1 -1
  254. package/dist/modes/app-server/daemon/process.js +58 -12
  255. package/dist/modes/app-server/daemon/process.js.map +1 -1
  256. package/dist/modes/app-server/daemon.js +65 -7
  257. package/dist/modes/app-server/daemon.js.map +1 -1
  258. package/dist/modes/index.d.ts +1 -1
  259. package/dist/modes/index.d.ts.map +1 -1
  260. package/dist/modes/index.js +1 -1
  261. package/dist/modes/index.js.map +1 -1
  262. package/dist/modes/interactive/interactive-host-runtime.d.ts +84 -1
  263. package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
  264. package/dist/modes/interactive/interactive-host-runtime.js +435 -112
  265. package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
  266. package/dist/modes/interactive/interactive-mode.d.ts +11 -1
  267. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  268. package/dist/modes/interactive/interactive-mode.js +59 -6
  269. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  270. package/dist/modes/interactive/tips/catalog/ethos-tips.js +1 -1
  271. package/dist/modes/interactive/tips/catalog/ethos-tips.js.map +1 -1
  272. package/dist/modes/rpc/connection-handler.d.ts +12 -5
  273. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  274. package/dist/modes/rpc/connection-handler.js +180 -25
  275. package/dist/modes/rpc/connection-handler.js.map +1 -1
  276. package/dist/modes/rpc/custom-capability.d.ts +2 -0
  277. package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
  278. package/dist/modes/rpc/custom-capability.js +2 -0
  279. package/dist/modes/rpc/custom-capability.js.map +1 -1
  280. package/dist/modes/rpc/host-ensure.d.ts +17 -0
  281. package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
  282. package/dist/modes/rpc/host-ensure.js +150 -23
  283. package/dist/modes/rpc/host-ensure.js.map +1 -1
  284. package/dist/modes/rpc/host-lifecycle.d.ts +54 -0
  285. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  286. package/dist/modes/rpc/host-lifecycle.js +259 -69
  287. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  288. package/dist/modes/rpc/host-watchdog.d.ts +2 -2
  289. package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
  290. package/dist/modes/rpc/host-watchdog.js +89 -21
  291. package/dist/modes/rpc/host-watchdog.js.map +1 -1
  292. package/dist/modes/rpc/multi-session-host.d.ts +38 -0
  293. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  294. package/dist/modes/rpc/multi-session-host.js +149 -61
  295. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  296. package/dist/modes/rpc/ownership-safe-lock.d.ts +14 -0
  297. package/dist/modes/rpc/ownership-safe-lock.d.ts.map +1 -0
  298. package/dist/modes/rpc/ownership-safe-lock.js +87 -0
  299. package/dist/modes/rpc/ownership-safe-lock.js.map +1 -0
  300. package/dist/modes/rpc/rpc-client.d.ts +13 -2
  301. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  302. package/dist/modes/rpc/rpc-client.js +46 -12
  303. package/dist/modes/rpc/rpc-client.js.map +1 -1
  304. package/dist/modes/rpc/rpc-types.d.ts +21 -3
  305. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  306. package/dist/modes/rpc/rpc-types.js +1 -0
  307. package/dist/modes/rpc/rpc-types.js.map +1 -1
  308. package/dist/modes/rpc/session-binding.d.ts +2 -1
  309. package/dist/modes/rpc/session-binding.d.ts.map +1 -1
  310. package/dist/modes/rpc/session-binding.js +1 -0
  311. package/dist/modes/rpc/session-binding.js.map +1 -1
  312. package/dist/modes/rpc/session-command-router.d.ts +54 -1
  313. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  314. package/dist/modes/rpc/session-command-router.js +180 -3
  315. package/dist/modes/rpc/session-command-router.js.map +1 -1
  316. package/dist/modes/rpc/session-event-writer.d.ts +18 -0
  317. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  318. package/dist/modes/rpc/session-event-writer.js +88 -8
  319. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  320. package/dist/modes/rpc/session-registry.d.ts +11 -1
  321. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  322. package/dist/modes/rpc/session-registry.js +25 -0
  323. package/dist/modes/rpc/session-registry.js.map +1 -1
  324. package/dist/modes/rpc/socket-transport.d.ts +13 -0
  325. package/dist/modes/rpc/socket-transport.d.ts.map +1 -0
  326. package/dist/modes/rpc/socket-transport.js +92 -0
  327. package/dist/modes/rpc/socket-transport.js.map +1 -0
  328. package/dist/modes/rpc/widget-line-renderer.d.ts +17 -0
  329. package/dist/modes/rpc/widget-line-renderer.d.ts.map +1 -0
  330. package/dist/modes/rpc/widget-line-renderer.js +73 -0
  331. package/dist/modes/rpc/widget-line-renderer.js.map +1 -0
  332. package/dist/utils/fs-watch.d.ts.map +1 -1
  333. package/dist/utils/fs-watch.js +11 -2
  334. package/dist/utils/fs-watch.js.map +1 -1
  335. package/docs/app-server.md +2 -2
  336. package/docs/containerization.md +2 -2
  337. package/docs/development.md +7 -7
  338. package/docs/extensions.md +5 -5
  339. package/docs/grok-neo.md +1 -1
  340. package/docs/index.md +1 -1
  341. package/docs/packages.md +2 -2
  342. package/docs/quickstart.md +4 -4
  343. package/docs/release-guide.md +21 -21
  344. package/docs/rpc.md +83 -6
  345. package/docs/sdk.md +1 -1
  346. package/docs/settings.md +8 -8
  347. package/docs/skills.md +2 -2
  348. package/docs/terminal-tools.md +1 -1
  349. package/docs/termux.md +1 -1
  350. package/docs/tui.md +1 -1
  351. package/examples/AGENTS.md +1 -1
  352. package/examples/sdk/README.md +1 -1
  353. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +85 -0
  354. package/node_modules/@code-yeongyu/senpi-codemode/README.md +6 -4
  355. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  356. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/skill-contribution.ts +105 -0
  357. package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +6 -1
  358. package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +10 -1
  359. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/SKILL.md +44 -0
  360. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/breaking-changes.md +75 -0
  361. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/build.md +114 -0
  362. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/dev-tooling.md +34 -0
  363. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/http-networking.md +113 -0
  364. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/install.md +93 -0
  365. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/node-compat-platforms.md +36 -0
  366. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/performance.md +33 -0
  367. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/runtime-apis.md +156 -0
  368. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/security.md +52 -0
  369. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/test.md +103 -0
  370. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool-options.ts +3 -1
  371. package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +2 -0
  372. package/node_modules/@earendil-works/pi-agent-core/README.md +3 -0
  373. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts +3 -0
  374. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  375. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +2 -2
  376. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  377. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  378. package/node_modules/@earendil-works/pi-ai/README.md +6 -3
  379. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  380. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +24 -7
  381. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  382. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +7 -0
  383. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
  384. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +316 -2
  385. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
  386. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts +4 -0
  387. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts.map +1 -1
  388. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js +23 -0
  389. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js.map +1 -1
  390. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts +24 -0
  391. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  392. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +20 -2
  393. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  394. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  395. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  396. package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -1
  397. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  398. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -1
  399. package/node_modules/@earendil-works/pi-ai/dist/providers/data/groq.json +1 -1
  400. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  401. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
  402. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  403. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  404. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  405. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.d.ts.map +1 -1
  406. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.js +3 -1
  407. package/node_modules/@earendil-works/pi-ai/dist/utils/retry-profile/profiles.js.map +1 -1
  408. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +1 -1
  409. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  410. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  411. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts +42 -0
  412. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts.map +1 -0
  413. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js +34 -0
  414. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js.map +1 -0
  415. package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts +8 -0
  416. package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts.map +1 -0
  417. package/node_modules/@earendil-works/pi-pty/dist/screen-text.js +51 -0
  418. package/node_modules/@earendil-works/pi-pty/dist/screen-text.js.map +1 -0
  419. package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts +45 -0
  420. package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts.map +1 -1
  421. package/node_modules/@earendil-works/pi-pty/dist/screen.js +178 -55
  422. package/node_modules/@earendil-works/pi-pty/dist/screen.js.map +1 -1
  423. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  424. package/node_modules/@earendil-works/pi-telemetry/README.md +6 -3
  425. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  426. package/node_modules/@earendil-works/pi-tui/README.md +5 -4
  427. package/node_modules/@earendil-works/pi-tui/native/darwin/README.md +2 -2
  428. package/node_modules/@earendil-works/pi-tui/native/win32/README.md +2 -2
  429. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  430. package/package.json +7 -7
@@ -85,7 +85,7 @@ function modelFromJson(providerId, definition, providerConfig, defaults) {
85
85
  compat: mergeCompat(providerConfig.compat, definition.compat),
86
86
  };
87
87
  }
88
- function applyModelsJson(providerId, baseModels, config) {
88
+ function applyModelsJson(providerId, baseModels, config, extension) {
89
89
  if (!config)
90
90
  return [...baseModels];
91
91
  const hasOverrides = config.modelOverrides && Object.keys(config.modelOverrides).length > 0;
@@ -111,7 +111,11 @@ function applyModelsJson(providerId, baseModels, config) {
111
111
  for (const definition of config.models ?? []) {
112
112
  const existingIndex = models.findIndex((model) => model.id === definition.id);
113
113
  const defaults = existingIndex >= 0 ? models[existingIndex] : models[0];
114
- const model = modelFromJson(providerId, definition, config, defaults);
114
+ const model = modelFromJson(providerId, definition, config, {
115
+ ...defaults,
116
+ api: extension?.api ?? defaults?.api,
117
+ baseUrl: extension?.baseUrl ?? defaults?.baseUrl,
118
+ });
115
119
  if (existingIndex >= 0)
116
120
  models[existingIndex] = model;
117
121
  else
@@ -121,13 +125,14 @@ function applyModelsJson(providerId, baseModels, config) {
121
125
  const blacklist = config.blacklist ? new Set(config.blacklist) : undefined;
122
126
  return models.filter((model) => (whitelist === undefined || whitelist.has(model.id)) && (blacklist === undefined || !blacklist.has(model.id)));
123
127
  }
124
- function applyExtension(providerId, models, config) {
128
+ function applyExtension(providerId, models, config, customModelIds) {
125
129
  if (!config)
126
130
  return [...models];
127
131
  if (!config.models) {
128
132
  return config.baseUrl ? models.map((model) => ({ ...model, baseUrl: config.baseUrl })) : [...models];
129
133
  }
130
- return config.models.map((definition) => {
134
+ const declaredModels = config.models;
135
+ const extensionModels = declaredModels.map((definition) => {
131
136
  const defaults = models.find((model) => model.id === definition.id) ?? models[0];
132
137
  const api = definition.api ?? config.api ?? defaults?.api;
133
138
  if (!api) {
@@ -144,6 +149,10 @@ function applyExtension(providerId, models, config) {
144
149
  headers: undefined,
145
150
  };
146
151
  });
152
+ return [
153
+ ...extensionModels,
154
+ ...models.filter((model) => customModelIds.has(model.id) && !declaredModels.some((definition) => definition.id === model.id)),
155
+ ];
147
156
  }
148
157
  function adaptOAuth(config) {
149
158
  return {
@@ -206,7 +215,7 @@ export function validateExtensionProvider(providerId, base, modelsConfig, extens
206
215
  if (extension.streamSimple && !extension.api) {
207
216
  throw new Error(`Provider ${providerId}: "api" is required when registering streamSimple.`);
208
217
  }
209
- applyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], modelsConfig), extension);
218
+ applyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], modelsConfig, extension), extension, new Set((modelsConfig?.models ?? []).map((definition) => definition.id)));
210
219
  }
211
220
  /** Compose built-in, models.json, and extension layers without reading credentials. */
212
221
  export function composeModelProvider(providerId, base, modelConfig, extension) {
@@ -217,7 +226,7 @@ export function composeModelProvider(providerId, base, modelConfig, extension) {
217
226
  // models.json modelOverrides are the topmost user-config layer: they apply once,
218
227
  // after custom-model upserts, extension model replacement, and legacy OAuth projection.
219
228
  const getModels = () => {
220
- let models = applyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], config), currentExtension());
229
+ let models = applyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], config, currentExtension()), currentExtension(), new Set((config?.models ?? []).map((definition) => definition.id)));
221
230
  if (extensionOAuthCredential && extension?.oauth?.modifyModels) {
222
231
  models = extension.oauth.modifyModels(models, extensionOAuthCredential);
223
232
  }
@@ -282,10 +291,10 @@ export function composeModelProvider(providerId, base, modelConfig, extension) {
282
291
  update: () => {
283
292
  if (refreshed) {
284
293
  // Validate before publishing the new synchronous list.
285
- applyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], config), {
294
+ applyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], config, extension), {
286
295
  ...extension,
287
296
  models: refreshed,
288
- });
297
+ }, new Set((config?.models ?? []).map((definition) => definition.id)));
289
298
  refreshedExtensionModels = refreshed;
290
299
  }
291
300
  extensionOAuthCredential = oauthCredential;
@@ -1 +1 @@
1
- {"version":3,"file":"provider-composer.js","sourceRoot":"","sources":["../../src/core/provider-composer.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Api,\n\ttype AssistantMessageEventStream,\n\ttype AuthCheck,\n\ttype AuthContext,\n\ttype AuthResult,\n\ttype Context,\n\ttype Credential,\n\tgetApiProvider,\n\tgetProtocol,\n\tgetToolCallFormat,\n\tlazyStream,\n\ttype Model,\n\ttype OAuthAuth,\n\ttype OAuthCredential,\n\ttype OAuthCredentials,\n\ttype OAuthLoginCallbacks,\n\ttype Provider,\n\ttype ProviderHeaders,\n\ttype RefreshModelsContext,\n\ttype SimpleStreamOptions,\n\ttype StreamOptions,\n\ttransformContext,\n\twrapStreamWithToolCallMiddleware,\n} from \"@earendil-works/pi-ai\";\nimport type { RetryPolicyProfile } from \"@earendil-works/pi-ai/utils/retry-profile/types\";\nimport type { ModelConfig, ModelsJsonModel, ModelsJsonModelOverride, ModelsJsonProvider } from \"./model-config.ts\";\nimport { composeApiKeyAuth, configuredApiKey, configuredHeaders, withConfiguredAuth } from \"./provider-api-key-auth.ts\";\nimport { configuredHeaderAuthStatus, type HeaderAuthStatusSource } from \"./provider-header-auth.ts\";\nimport {\n\tclearConfigValueCache,\n\tgetConfigValueEnvVarNames,\n\tisCommandConfigValue,\n\tisConfigValueConfigured,\n\tresolveHeadersOrThrow,\n} from \"./resolve-config-value.ts\";\n\nexport interface ExtensionOAuthConfig {\n\tname: string;\n\t/** Whether access through this auth method is backed by a provider subscription. */\n\tisSubscription?: boolean;\n\t/** @deprecated Retained for extension source compatibility; ignored by canonical auth flows. */\n\tusesCallbackServer?: boolean;\n\tcheck?(input: { ctx: AuthContext; credential?: OAuthCredential }): Promise<AuthCheck | undefined>;\n\t/**\n\t * Request auth for providers whose credentials live outside auth.json —\n\t * an environment token, or a CLI the provider shells out to. Supplying this\n\t * gives the provider api-key auth it would otherwise be denied for having\n\t * `oauth`, so ambient users resolve instead of hitting\n\t * \"Provider is not configured\". Never consulted once a credential is stored.\n\t */\n\tresolveAmbient?(input: { ctx: AuthContext; signal?: AbortSignal }): Promise<AuthResult | undefined>;\n\tlogin(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;\n\trefreshToken(credentials: OAuthCredentials, signal: AbortSignal): Promise<OAuthCredentials>;\n\tgetApiKey(credentials: OAuthCredentials): string;\n\tmodifyModels?(models: Model<Api>[], credentials: OAuthCredentials): Model<Api>[];\n}\n\n/** Input type for the extension registerProvider API. */\nexport interface ProviderConfigInput {\n\tname?: string;\n\tbaseUrl?: string;\n\tapiKey?: string;\n\tapi?: Api;\n\tstreamSimple?: (model: Model<Api>, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStream;\n\theaders?: Record<string, string>;\n\textraBody?: Record<string, unknown>;\n\tauthHeader?: boolean;\n\toauth?: ExtensionOAuthConfig;\n\tretryPolicy?: RetryPolicyProfile;\n\tmodels?: Array<{\n\t\tid: string;\n\t\tname: string;\n\t\tupstreamModelId?: string;\n\t\tserviceTier?: \"auto\" | \"flex\" | \"priority\";\n\t\tpromptPreset?: string;\n\t\trecoverTextToolCalls?: boolean;\n\t\tapi?: Api;\n\t\tbaseUrl?: string;\n\t\treasoning: boolean;\n\t\tthinkingLevelMap?: Model<Api>[\"thinkingLevelMap\"];\n\t\tinput: (\"text\" | \"image\" | \"video\")[];\n\t\tcost: Model<Api>[\"cost\"];\n\t\tcontextWindow: number;\n\t\tmaxTokens: number;\n\t\tsamplingParams?: Record<string, unknown>;\n\t\theaders?: Record<string, string>;\n\t\textraBody?: Record<string, unknown>;\n\t\tcacheRetention?: Model<Api>[\"cacheRetention\"];\n\t\tcompat?: Model<Api>[\"compat\"];\n\t}>;\n\trefreshModels?(context: RefreshModelsContext): Promise<NonNullable<ProviderConfigInput[\"models\"]>>;\n\t/**\n\t * Deterministic usability gate for implicit fallback expansion. Return `false`\n\t * while this lane is guaranteed to refuse unattended execution (for example an\n\t * unacknowledged approval gate); the provider stays registered and explicitly\n\t * selectable, but bare-family fallback expansion skips it. Re-evaluated on\n\t * every expansion, so a settings change takes effect without re-registration.\n\t */\n\tfallbackEligible?(): boolean;\n}\n\nexport type AuthStatus = {\n\tconfigured: boolean;\n\tsource?:\n\t\t| \"stored\"\n\t\t| \"runtime\"\n\t\t| \"environment\"\n\t\t| \"fallback\"\n\t\t| \"models_json_key\"\n\t\t| \"models_json_command\"\n\t\t| HeaderAuthStatusSource;\n\tlabel?: string;\n};\n\nexport const clearApiKeyCache = clearConfigValueCache;\n\ntype ModelWithConfigMetadata = Model<Api> & {\n\tpromptPreset?: string;\n};\n\nfunction mergeCompat(\n\tbase: Model<Api>[\"compat\"],\n\toverride: Model<Api>[\"compat\"] | ModelsJsonModelOverride[\"compat\"],\n): Model<Api>[\"compat\"] {\n\tif (!override) return base;\n\tconst merged = { ...base, ...override } as NonNullable<Model<Api>[\"compat\"]>;\n\tconst baseNested = base as Record<string, unknown> | undefined;\n\tconst overrideNested = override as Record<string, unknown>;\n\tconst mergedNested = merged as Record<string, unknown>;\n\tfor (const key of [\"openRouterRouting\", \"vercelGatewayRouting\", \"chatTemplateKwargs\", \"chatTemplateArgs\"] as const) {\n\t\tconst baseValue = baseNested?.[key];\n\t\tconst overrideValue = overrideNested[key];\n\t\tif (\n\t\t\t(typeof baseValue === \"object\" && baseValue !== null) ||\n\t\t\t(typeof overrideValue === \"object\" && overrideValue !== null)\n\t\t) {\n\t\t\tmergedNested[key] = { ...(baseValue as object | undefined), ...(overrideValue as object | undefined) };\n\t\t}\n\t}\n\treturn merged;\n}\n\nfunction applyModelOverride(model: Model<Api>, override: ModelsJsonModelOverride): ModelWithConfigMetadata {\n\treturn {\n\t\t...model,\n\t\tname: override.name ?? model.name,\n\t\tpromptPreset: override.promptPreset ?? (model as Model<Api> & { promptPreset?: string }).promptPreset,\n\t\trecoverTextToolCalls: override.recoverTextToolCalls ?? model.recoverTextToolCalls,\n\t\treasoning: override.reasoning ?? model.reasoning,\n\t\tthinkingLevelMap: override.thinkingLevelMap\n\t\t\t? override.thinkingLevelMapMode === \"replace\"\n\t\t\t\t? override.thinkingLevelMap\n\t\t\t\t: { ...model.thinkingLevelMap, ...override.thinkingLevelMap }\n\t\t\t: model.thinkingLevelMap,\n\t\tinput: (override.input as (\"text\" | \"image\" | \"video\")[] | undefined) ?? model.input,\n\t\tcost: override.cost\n\t\t\t? {\n\t\t\t\t\tinput: override.cost.input ?? model.cost.input,\n\t\t\t\t\toutput: override.cost.output ?? model.cost.output,\n\t\t\t\t\tcacheRead: override.cost.cacheRead ?? model.cost.cacheRead,\n\t\t\t\t\tcacheWrite: override.cost.cacheWrite ?? model.cost.cacheWrite,\n\t\t\t\t\ttiers: override.cost.tiers ?? model.cost.tiers,\n\t\t\t\t}\n\t\t\t: model.cost,\n\t\tcontextWindow: override.contextWindow ?? model.contextWindow,\n\t\tmaxTokens: override.maxTokens ?? model.maxTokens,\n\t\tcacheRetention: override.cacheRetention ?? model.cacheRetention,\n\t\tsamplingParams: override.samplingParams\n\t\t\t? { ...model.samplingParams, ...override.samplingParams }\n\t\t\t: model.samplingParams,\n\t\tcompat: mergeCompat(model.compat, override.compat),\n\t};\n}\n\nfunction modelFromJson(\n\tproviderId: string,\n\tdefinition: ModelsJsonModel,\n\tproviderConfig: ModelsJsonProvider,\n\tdefaults: Model<Api> | undefined,\n): ModelWithConfigMetadata {\n\tconst api = definition.api ?? providerConfig.api ?? defaults?.api;\n\tif (!api) {\n\t\tthrow new Error(\n\t\t\t`Provider ${providerId}, model ${definition.id}: no \"api\" specified. Set at provider or model level.`,\n\t\t);\n\t}\n\tconst baseUrl = definition.baseUrl ?? providerConfig.baseUrl ?? defaults?.baseUrl;\n\tif (!baseUrl) throw new Error(`Provider ${providerId}: \"baseUrl\" is required when defining custom models.`);\n\tif (definition.contextWindow !== undefined && definition.contextWindow <= 0) {\n\t\tthrow new Error(`Provider ${providerId}, model ${definition.id}: invalid contextWindow`);\n\t}\n\tif (definition.maxTokens !== undefined && definition.maxTokens <= 0) {\n\t\tthrow new Error(`Provider ${providerId}, model ${definition.id}: invalid maxTokens`);\n\t}\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name ?? definition.id,\n\t\tpromptPreset: definition.promptPreset,\n\t\trecoverTextToolCalls: definition.recoverTextToolCalls,\n\t\tapi: api as Api,\n\t\tprovider: providerId,\n\t\tbaseUrl,\n\t\treasoning: definition.reasoning ?? false,\n\t\tthinkingLevelMap: definition.thinkingLevelMap,\n\t\tinput: (definition.input ?? [\"text\"]) as (\"text\" | \"image\" | \"video\")[],\n\t\tcost: definition.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: definition.contextWindow ?? 128000,\n\t\tmaxTokens: definition.maxTokens ?? 16384,\n\t\tsamplingParams: definition.samplingParams,\n\t\theaders: undefined,\n\t\tcacheRetention: definition.cacheRetention ?? providerConfig.cacheRetention,\n\t\tcompat: mergeCompat(providerConfig.compat, definition.compat),\n\t};\n}\n\nfunction applyModelsJson(\n\tproviderId: string,\n\tbaseModels: readonly Model<Api>[],\n\tconfig: ModelsJsonProvider | undefined,\n): Model<Api>[] {\n\tif (!config) return [...baseModels];\n\tconst hasOverrides = config.modelOverrides && Object.keys(config.modelOverrides).length > 0;\n\tif (\n\t\t!config.models?.length &&\n\t\t!config.baseUrl &&\n\t\t!config.headers &&\n\t\t!config.extraBody &&\n\t\t!config.compat &&\n\t\t!hasOverrides &&\n\t\t!config.whitelist &&\n\t\t!config.blacklist &&\n\t\t!config.apiKey &&\n\t\tconfig.authHeader === undefined\n\t) {\n\t\tthrow new Error(\n\t\t\t`Provider ${providerId}: must specify \"baseUrl\", \"headers\", \"extraBody\", \"compat\", \"modelOverrides\", or \"models\".`,\n\t\t);\n\t}\n\n\t// An explicit local Ollama catalog replaces Cloud discovery instead of rebinding its dynamic tags to localhost.\n\tconst configuredBaseModels = providerId === \"ollama\" && config.models?.length ? [] : baseModels;\n\tconst models: Model<Api>[] = configuredBaseModels.map((model) => ({\n\t\t...model,\n\t\tbaseUrl: config.baseUrl ?? model.baseUrl,\n\t\tcompat: mergeCompat(model.compat, config.compat),\n\t}));\n\tfor (const definition of config.models ?? []) {\n\t\tconst existingIndex = models.findIndex((model) => model.id === definition.id);\n\t\tconst defaults = existingIndex >= 0 ? models[existingIndex] : models[0];\n\t\tconst model = modelFromJson(providerId, definition, config, defaults);\n\t\tif (existingIndex >= 0) models[existingIndex] = model;\n\t\telse models.push(model);\n\t}\n\tconst whitelist = config.whitelist ? new Set(config.whitelist) : undefined;\n\tconst blacklist = config.blacklist ? new Set(config.blacklist) : undefined;\n\treturn models.filter(\n\t\t(model) =>\n\t\t\t(whitelist === undefined || whitelist.has(model.id)) && (blacklist === undefined || !blacklist.has(model.id)),\n\t);\n}\n\nfunction applyExtension(\n\tproviderId: string,\n\tmodels: readonly Model<Api>[],\n\tconfig: ProviderConfigInput | undefined,\n): Model<Api>[] {\n\tif (!config) return [...models];\n\tif (!config.models) {\n\t\treturn config.baseUrl ? models.map((model) => ({ ...model, baseUrl: config.baseUrl! })) : [...models];\n\t}\n\treturn config.models.map((definition) => {\n\t\tconst defaults = models.find((model) => model.id === definition.id) ?? models[0];\n\t\tconst api = definition.api ?? config.api ?? defaults?.api;\n\t\tif (!api) {\n\t\t\tthrow new Error(\n\t\t\t\t`Provider ${providerId}, model ${definition.id}: no \"api\" specified. Set at provider or model level.`,\n\t\t\t);\n\t\t}\n\t\tconst baseUrl = definition.baseUrl ?? config.baseUrl ?? defaults?.baseUrl;\n\t\tif (!baseUrl) throw new Error(`Provider ${providerId}: \"baseUrl\" is required when defining custom models.`);\n\t\treturn {\n\t\t\t...definition,\n\t\t\tapi,\n\t\t\tprovider: providerId,\n\t\t\tbaseUrl,\n\t\t\theaders: undefined,\n\t\t};\n\t});\n}\n\nfunction adaptOAuth(config: ExtensionOAuthConfig): OAuthAuth {\n\treturn {\n\t\tname: config.name,\n\t\tisSubscription: config.isSubscription,\n\t\tlogin: async (callbacks) => {\n\t\t\tconst credential = await config.login({\n\t\t\t\tonAuth: (info) => callbacks.notify({ type: \"auth_url\", ...info }),\n\t\t\t\tonDeviceCode: (info) => callbacks.notify({ type: \"device_code\", ...info }),\n\t\t\t\tonPrompt: (prompt) => callbacks.prompt({ type: \"text\", ...prompt }),\n\t\t\t\tonProgress: (message) => callbacks.notify({ type: \"progress\", message }),\n\t\t\t\tonManualCodeInput: () => callbacks.prompt({ type: \"manual_code\", message: \"Paste the authorization code\" }),\n\t\t\t\tonSelect: (prompt) => callbacks.prompt({ type: \"select\", ...prompt }),\n\t\t\t\tsignal: callbacks.signal,\n\t\t\t});\n\t\t\treturn { ...credential, type: \"oauth\" };\n\t\t},\n\t\trefresh: async (credential, signal) => ({ ...(await config.refreshToken(credential, signal)), type: \"oauth\" }),\n\t\ttoAuth: async (credential) => ({ apiKey: config.getApiKey(credential) }),\n\t\t...(config.check ? { check: config.check } : {}),\n\t};\n}\n\nfunction composeOAuthAuth(\n\tproviderId: string,\n\tbase: Provider | undefined,\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n): OAuthAuth | undefined {\n\tconst oauth = extension?.oauth ? adaptOAuth(extension.oauth) : base?.auth.oauth;\n\tif (!oauth) return undefined;\n\tconst rawHeaders = configuredHeaders(config, extension);\n\tconst authHeader = extension?.authHeader ?? config?.authHeader ?? false;\n\treturn {\n\t\t...oauth,\n\t\ttoAuth: async (credential) => {\n\t\t\tconst auth = await oauth.toAuth(credential);\n\t\t\tconst env = credential.env;\n\t\t\tconst headers = resolveHeadersOrThrow(\n\t\t\t\trawHeaders,\n\t\t\t\t`provider \"${providerId}\"`,\n\t\t\t\ttypeof env === \"object\" && env !== null ? (env as Record<string, string>) : undefined,\n\t\t\t);\n\t\t\treturn withConfiguredAuth(auth, headers, authHeader);\n\t\t},\n\t};\n}\n\nfunction rawModelHeaders(\n\tmodel: Model<Api>,\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n): Record<string, string> | undefined {\n\tconst definition = config?.models?.find((entry) => entry.id === model.id);\n\tconst extensionModel = extension?.models?.find((entry) => entry.id === model.id);\n\tconst headers = {\n\t\t...config?.modelOverrides?.[model.id]?.headers,\n\t\t...definition?.headers,\n\t\t...extensionModel?.headers,\n\t};\n\treturn Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nfunction rawModelExtraBody(\n\tmodel: Model<Api>,\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n): Record<string, unknown> | undefined {\n\tconst definition = config?.models?.find((entry) => entry.id === model.id);\n\tconst extensionModel = extension?.models?.find((entry) => entry.id === model.id);\n\tconst extraBody = {\n\t\t...config?.modelOverrides?.[model.id]?.extraBody,\n\t\t...definition?.extraBody,\n\t\t...extensionModel?.extraBody,\n\t};\n\treturn Object.keys(extraBody).length > 0 ? extraBody : undefined;\n}\n\nexport function validateExtensionProvider(\n\tproviderId: string,\n\tbase: Provider | undefined,\n\tmodelsConfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput,\n): void {\n\tif (extension.streamSimple && !extension.api) {\n\t\tthrow new Error(`Provider ${providerId}: \"api\" is required when registering streamSimple.`);\n\t}\n\tapplyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], modelsConfig), extension);\n}\n\n/** Compose built-in, models.json, and extension layers without reading credentials. */\nexport function composeModelProvider(\n\tproviderId: string,\n\tbase: Provider | undefined,\n\tmodelConfig: ModelConfig,\n\textension: ProviderConfigInput | undefined,\n): Provider {\n\tconst config = modelConfig.getProvider(providerId);\n\tlet extensionOAuthCredential: OAuthCredentials | undefined;\n\tlet refreshedExtensionModels: ProviderConfigInput[\"models\"];\n\tconst currentExtension = (): ProviderConfigInput | undefined =>\n\t\textension && refreshedExtensionModels ? { ...extension, models: refreshedExtensionModels } : extension;\n\t// models.json modelOverrides are the topmost user-config layer: they apply once,\n\t// after custom-model upserts, extension model replacement, and legacy OAuth projection.\n\tconst getModels = () => {\n\t\tlet models = applyExtension(\n\t\t\tproviderId,\n\t\t\tapplyModelsJson(providerId, base?.getModels() ?? [], config),\n\t\t\tcurrentExtension(),\n\t\t);\n\t\tif (extensionOAuthCredential && extension?.oauth?.modifyModels) {\n\t\t\tmodels = extension.oauth.modifyModels(models, extensionOAuthCredential);\n\t\t}\n\t\treturn models.map((model) => {\n\t\t\tconst override = config?.modelOverrides?.[model.id];\n\t\t\treturn override ? applyModelOverride(model, override) : model;\n\t\t});\n\t};\n\t// Validate eagerly so registration/reload reports structural errors immediately.\n\tgetModels();\n\tconst apiKey = composeApiKeyAuth(providerId, base, config, extension);\n\tconst oauth = composeOAuthAuth(providerId, base, config, extension);\n\tif (!apiKey && !oauth) throw new Error(`Provider ${providerId}: no authentication method configured.`);\n\t// The documented local `ollama` models.json catalog must not invoke the Cloud builtin's refresh with its\n\tconst refreshBase = providerId === \"ollama\" && config?.models?.length ? undefined : base?.refreshModels?.bind(base);\n\n\tconst supportsBaseApi = (model: Model<Api>) => base?.getModels().some((entry) => entry.api === model.api) ?? false;\n\tconst streamWith = (\n\t\tmodel: Model<Api>,\n\t\tcontext: Context,\n\t\toptions: StreamOptions | undefined,\n\t\tsimple: boolean,\n\t): AssistantMessageEventStream =>\n\t\tlazyStream(model, async () => {\n\t\t\tconst format = getToolCallFormat(model);\n\t\t\tif (format && context.tools && context.tools.length > 0) {\n\t\t\t\tconst protocol = getProtocol(format);\n\t\t\t\tconst transformedContext = transformContext(context, protocol);\n\t\t\t\tconst innerStream = streamWith(model, transformedContext, options, simple);\n\t\t\t\treturn wrapStreamWithToolCallMiddleware(innerStream, protocol, context.tools);\n\t\t\t}\n\t\t\tif (extension?.streamSimple && model.api === extension.api) {\n\t\t\t\treturn extension.streamSimple(model, context, options as SimpleStreamOptions);\n\t\t\t}\n\t\t\tif (base && supportsBaseApi(model)) {\n\t\t\t\treturn simple\n\t\t\t\t\t? base.streamSimple(model, context, options as SimpleStreamOptions)\n\t\t\t\t\t: base.stream(model, context, options);\n\t\t\t}\n\t\t\tconst api = getApiProvider(model.api);\n\t\t\tif (!api) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No API provider registered for api: ${model.api} (model \"${model.provider}/${model.id}\"). ` +\n\t\t\t\t\t\t`Load the extension that implements this api, or fix the \"api\" value for provider \"${providerId}\" in models.json.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn simple\n\t\t\t\t? api.streamSimple(model, context, options as SimpleStreamOptions)\n\t\t\t\t: api.stream(model, context, options);\n\t\t});\n\n\tconst provider: Provider = {\n\t\tid: providerId,\n\t\tname: extension?.name ?? config?.name ?? base?.name ?? extension?.oauth?.name ?? providerId,\n\t\tbaseUrl: extension?.baseUrl ?? config?.baseUrl ?? base?.baseUrl,\n\t\theaders: base?.headers,\n\t\t// Composed providers must not silently drop provider-declared retry profiles.\n\t\tretryPolicy: extension?.retryPolicy ?? base?.retryPolicy,\n\t\tauth: { ...(apiKey ? { apiKey } : {}), ...(oauth ? { oauth } : {}) },\n\t\tgetModels,\n\t\trefreshModels:\n\t\t\trefreshBase || extension?.refreshModels || extension?.oauth?.modifyModels\n\t\t\t\t? async (context) => {\n\t\t\t\t\t\tawait refreshBase?.(context);\n\t\t\t\t\t\tlet refreshed: NonNullable<ProviderConfigInput[\"models\"]> | undefined;\n\t\t\t\t\t\tif (extension?.refreshModels) refreshed = await extension.refreshModels(context);\n\t\t\t\t\t\tif (context.signal.aborted) return;\n\t\t\t\t\t\tconst oauthCredential = context.credential?.type === \"oauth\" ? context.credential : undefined;\n\t\t\t\t\t\tawait context.publish({\n\t\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\t\tif (refreshed) {\n\t\t\t\t\t\t\t\t\t// Validate before publishing the new synchronous list.\n\t\t\t\t\t\t\t\t\tapplyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], config), {\n\t\t\t\t\t\t\t\t\t\t...extension,\n\t\t\t\t\t\t\t\t\t\tmodels: refreshed,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\trefreshedExtensionModels = refreshed;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\textensionOAuthCredential = oauthCredential;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\tfilterModels: base?.filterModels\n\t\t\t? (models, credential: Credential | undefined) => base.filterModels!(models, credential)\n\t\t\t: undefined,\n\t\tstream: (model, context, options) => streamWith(model, context, options, false),\n\t\tstreamSimple: (model, context, options) => streamWith(model, context, options, true),\n\t};\n\n\tconst fetchDeferred = base?.fetchDeferred;\n\tif (fetchDeferred) {\n\t\tprovider.fetchDeferred = (model, handle, options) => fetchDeferred(model, handle, options);\n\t}\n\tconst cancelDeferred = base?.cancelDeferred;\n\tif (cancelDeferred) {\n\t\tprovider.cancelDeferred = (model, handle, options) => cancelDeferred(model, handle, options);\n\t}\n\n\treturn provider;\n}\n\nexport function resolveConfiguredModelHeaders(\n\tmodel: Model<Api>,\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n\tenv?: Record<string, string>,\n): Record<string, string> | undefined {\n\treturn resolveHeadersOrThrow(\n\t\trawModelHeaders(model, config, extension),\n\t\t`model \"${model.provider}/${model.id}\"`,\n\t\tenv,\n\t);\n}\n\nexport interface CompatibilityRequestConfig {\n\theaders?: ProviderHeaders;\n\textraBody?: Record<string, unknown>;\n\tupstreamModelId?: string;\n\tserviceTier?: \"auto\" | \"flex\" | \"priority\";\n\tauthHeader: boolean;\n}\n\nexport function resolveCompatibilityRequestConfig(\n\tmodel: Model<Api>,\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n\tenv?: Record<string, string>,\n): CompatibilityRequestConfig {\n\tconst configured = resolveHeadersOrThrow(\n\t\t{ ...configuredHeaders(config, extension), ...rawModelHeaders(model, config, extension) },\n\t\t`model \"${model.provider}/${model.id}\"`,\n\t\tenv,\n\t);\n\tconst modelDefinition = config?.models?.find((entry) => entry.id === model.id);\n\tconst extensionModel = extension?.models?.find((entry) => entry.id === model.id);\n\tconst configuredExtraBody = {\n\t\t...config?.extraBody,\n\t\t...extension?.extraBody,\n\t\t...rawModelExtraBody(model, config, extension),\n\t};\n\treturn {\n\t\theaders: model.headers || configured ? { ...model.headers, ...configured } : undefined,\n\t\textraBody: Object.keys(configuredExtraBody).length > 0 ? configuredExtraBody : undefined,\n\t\tupstreamModelId: extensionModel?.upstreamModelId ?? modelDefinition?.upstreamModelId ?? model.upstreamModelId,\n\t\tserviceTier: extensionModel?.serviceTier ?? modelDefinition?.serviceTier ?? model.serviceTier,\n\t\tauthHeader: extension?.authHeader ?? config?.authHeader ?? false,\n\t};\n}\n\nexport function configuredRequestAuthStatus(\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n): AuthStatus | undefined {\n\tconst value = configuredApiKey(config, extension);\n\tif (value === undefined) {\n\t\treturn configuredHeaderAuthStatus(config?.headers, extension?.headers);\n\t}\n\tif (isCommandConfigValue(value)) return { configured: true, source: \"models_json_command\" };\n\tconst names = getConfigValueEnvVarNames(value);\n\tif (names.length > 0) {\n\t\treturn isConfigValueConfigured(value)\n\t\t\t? { configured: true, source: \"environment\", label: names.join(\", \") }\n\t\t\t: { configured: false };\n\t}\n\treturn { configured: true, source: extension?.apiKey !== undefined ? \"fallback\" : \"models_json_key\" };\n}\n"]}
1
+ {"version":3,"file":"provider-composer.js","sourceRoot":"","sources":["../../src/core/provider-composer.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Api,\n\ttype AssistantMessageEventStream,\n\ttype AuthCheck,\n\ttype AuthContext,\n\ttype AuthResult,\n\ttype Context,\n\ttype Credential,\n\tgetApiProvider,\n\tgetProtocol,\n\tgetToolCallFormat,\n\tlazyStream,\n\ttype Model,\n\ttype OAuthAuth,\n\ttype OAuthCredential,\n\ttype OAuthCredentials,\n\ttype OAuthLoginCallbacks,\n\ttype Provider,\n\ttype ProviderHeaders,\n\ttype RefreshModelsContext,\n\ttype SimpleStreamOptions,\n\ttype StreamOptions,\n\ttransformContext,\n\twrapStreamWithToolCallMiddleware,\n} from \"@earendil-works/pi-ai\";\nimport type { RetryPolicyProfile } from \"@earendil-works/pi-ai/utils/retry-profile/types\";\nimport type { ModelConfig, ModelsJsonModel, ModelsJsonModelOverride, ModelsJsonProvider } from \"./model-config.ts\";\nimport { composeApiKeyAuth, configuredApiKey, configuredHeaders, withConfiguredAuth } from \"./provider-api-key-auth.ts\";\nimport { configuredHeaderAuthStatus, type HeaderAuthStatusSource } from \"./provider-header-auth.ts\";\nimport {\n\tclearConfigValueCache,\n\tgetConfigValueEnvVarNames,\n\tisCommandConfigValue,\n\tisConfigValueConfigured,\n\tresolveHeadersOrThrow,\n} from \"./resolve-config-value.ts\";\n\nexport interface ExtensionOAuthConfig {\n\tname: string;\n\t/** Whether access through this auth method is backed by a provider subscription. */\n\tisSubscription?: boolean;\n\t/** @deprecated Retained for extension source compatibility; ignored by canonical auth flows. */\n\tusesCallbackServer?: boolean;\n\tcheck?(input: { ctx: AuthContext; credential?: OAuthCredential }): Promise<AuthCheck | undefined>;\n\t/**\n\t * Request auth for providers whose credentials live outside auth.json —\n\t * an environment token, or a CLI the provider shells out to. Supplying this\n\t * gives the provider api-key auth it would otherwise be denied for having\n\t * `oauth`, so ambient users resolve instead of hitting\n\t * \"Provider is not configured\". Never consulted once a credential is stored.\n\t */\n\tresolveAmbient?(input: { ctx: AuthContext; signal?: AbortSignal }): Promise<AuthResult | undefined>;\n\tlogin(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials>;\n\trefreshToken(credentials: OAuthCredentials, signal: AbortSignal): Promise<OAuthCredentials>;\n\tgetApiKey(credentials: OAuthCredentials): string;\n\tmodifyModels?(models: Model<Api>[], credentials: OAuthCredentials): Model<Api>[];\n}\n\n/** Input type for the extension registerProvider API. */\nexport interface ProviderConfigInput {\n\tname?: string;\n\tbaseUrl?: string;\n\tapiKey?: string;\n\tapi?: Api;\n\tstreamSimple?: (model: Model<Api>, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStream;\n\theaders?: Record<string, string>;\n\textraBody?: Record<string, unknown>;\n\tauthHeader?: boolean;\n\toauth?: ExtensionOAuthConfig;\n\tretryPolicy?: RetryPolicyProfile;\n\tmodels?: Array<{\n\t\tid: string;\n\t\tname: string;\n\t\tupstreamModelId?: string;\n\t\tserviceTier?: \"auto\" | \"flex\" | \"priority\";\n\t\tpromptPreset?: string;\n\t\trecoverTextToolCalls?: boolean;\n\t\tapi?: Api;\n\t\tbaseUrl?: string;\n\t\treasoning: boolean;\n\t\tthinkingLevelMap?: Model<Api>[\"thinkingLevelMap\"];\n\t\tinput: (\"text\" | \"image\" | \"video\")[];\n\t\tcost: Model<Api>[\"cost\"];\n\t\tcontextWindow: number;\n\t\tmaxTokens: number;\n\t\tsamplingParams?: Record<string, unknown>;\n\t\theaders?: Record<string, string>;\n\t\textraBody?: Record<string, unknown>;\n\t\tcacheRetention?: Model<Api>[\"cacheRetention\"];\n\t\tcompat?: Model<Api>[\"compat\"];\n\t}>;\n\trefreshModels?(context: RefreshModelsContext): Promise<NonNullable<ProviderConfigInput[\"models\"]>>;\n\t/**\n\t * Deterministic usability gate for implicit fallback expansion. Return `false`\n\t * while this lane is guaranteed to refuse unattended execution (for example an\n\t * unacknowledged approval gate); the provider stays registered and explicitly\n\t * selectable, but bare-family fallback expansion skips it. Re-evaluated on\n\t * every expansion, so a settings change takes effect without re-registration.\n\t */\n\tfallbackEligible?(): boolean;\n}\n\nexport type AuthStatus = {\n\tconfigured: boolean;\n\tsource?:\n\t\t| \"stored\"\n\t\t| \"runtime\"\n\t\t| \"environment\"\n\t\t| \"fallback\"\n\t\t| \"models_json_key\"\n\t\t| \"models_json_command\"\n\t\t| HeaderAuthStatusSource;\n\tlabel?: string;\n};\n\nexport const clearApiKeyCache = clearConfigValueCache;\n\ntype ModelWithConfigMetadata = Model<Api> & {\n\tpromptPreset?: string;\n};\n\nfunction mergeCompat(\n\tbase: Model<Api>[\"compat\"],\n\toverride: Model<Api>[\"compat\"] | ModelsJsonModelOverride[\"compat\"],\n): Model<Api>[\"compat\"] {\n\tif (!override) return base;\n\tconst merged = { ...base, ...override } as NonNullable<Model<Api>[\"compat\"]>;\n\tconst baseNested = base as Record<string, unknown> | undefined;\n\tconst overrideNested = override as Record<string, unknown>;\n\tconst mergedNested = merged as Record<string, unknown>;\n\tfor (const key of [\"openRouterRouting\", \"vercelGatewayRouting\", \"chatTemplateKwargs\", \"chatTemplateArgs\"] as const) {\n\t\tconst baseValue = baseNested?.[key];\n\t\tconst overrideValue = overrideNested[key];\n\t\tif (\n\t\t\t(typeof baseValue === \"object\" && baseValue !== null) ||\n\t\t\t(typeof overrideValue === \"object\" && overrideValue !== null)\n\t\t) {\n\t\t\tmergedNested[key] = { ...(baseValue as object | undefined), ...(overrideValue as object | undefined) };\n\t\t}\n\t}\n\treturn merged;\n}\n\nfunction applyModelOverride(model: Model<Api>, override: ModelsJsonModelOverride): ModelWithConfigMetadata {\n\treturn {\n\t\t...model,\n\t\tname: override.name ?? model.name,\n\t\tpromptPreset: override.promptPreset ?? (model as Model<Api> & { promptPreset?: string }).promptPreset,\n\t\trecoverTextToolCalls: override.recoverTextToolCalls ?? model.recoverTextToolCalls,\n\t\treasoning: override.reasoning ?? model.reasoning,\n\t\tthinkingLevelMap: override.thinkingLevelMap\n\t\t\t? override.thinkingLevelMapMode === \"replace\"\n\t\t\t\t? override.thinkingLevelMap\n\t\t\t\t: { ...model.thinkingLevelMap, ...override.thinkingLevelMap }\n\t\t\t: model.thinkingLevelMap,\n\t\tinput: (override.input as (\"text\" | \"image\" | \"video\")[] | undefined) ?? model.input,\n\t\tcost: override.cost\n\t\t\t? {\n\t\t\t\t\tinput: override.cost.input ?? model.cost.input,\n\t\t\t\t\toutput: override.cost.output ?? model.cost.output,\n\t\t\t\t\tcacheRead: override.cost.cacheRead ?? model.cost.cacheRead,\n\t\t\t\t\tcacheWrite: override.cost.cacheWrite ?? model.cost.cacheWrite,\n\t\t\t\t\ttiers: override.cost.tiers ?? model.cost.tiers,\n\t\t\t\t}\n\t\t\t: model.cost,\n\t\tcontextWindow: override.contextWindow ?? model.contextWindow,\n\t\tmaxTokens: override.maxTokens ?? model.maxTokens,\n\t\tcacheRetention: override.cacheRetention ?? model.cacheRetention,\n\t\tsamplingParams: override.samplingParams\n\t\t\t? { ...model.samplingParams, ...override.samplingParams }\n\t\t\t: model.samplingParams,\n\t\tcompat: mergeCompat(model.compat, override.compat),\n\t};\n}\n\nfunction modelFromJson(\n\tproviderId: string,\n\tdefinition: ModelsJsonModel,\n\tproviderConfig: ModelsJsonProvider,\n\tdefaults: Model<Api> | undefined,\n): ModelWithConfigMetadata {\n\tconst api = definition.api ?? providerConfig.api ?? defaults?.api;\n\tif (!api) {\n\t\tthrow new Error(\n\t\t\t`Provider ${providerId}, model ${definition.id}: no \"api\" specified. Set at provider or model level.`,\n\t\t);\n\t}\n\tconst baseUrl = definition.baseUrl ?? providerConfig.baseUrl ?? defaults?.baseUrl;\n\tif (!baseUrl) throw new Error(`Provider ${providerId}: \"baseUrl\" is required when defining custom models.`);\n\tif (definition.contextWindow !== undefined && definition.contextWindow <= 0) {\n\t\tthrow new Error(`Provider ${providerId}, model ${definition.id}: invalid contextWindow`);\n\t}\n\tif (definition.maxTokens !== undefined && definition.maxTokens <= 0) {\n\t\tthrow new Error(`Provider ${providerId}, model ${definition.id}: invalid maxTokens`);\n\t}\n\treturn {\n\t\tid: definition.id,\n\t\tname: definition.name ?? definition.id,\n\t\tpromptPreset: definition.promptPreset,\n\t\trecoverTextToolCalls: definition.recoverTextToolCalls,\n\t\tapi: api as Api,\n\t\tprovider: providerId,\n\t\tbaseUrl,\n\t\treasoning: definition.reasoning ?? false,\n\t\tthinkingLevelMap: definition.thinkingLevelMap,\n\t\tinput: (definition.input ?? [\"text\"]) as (\"text\" | \"image\" | \"video\")[],\n\t\tcost: definition.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow: definition.contextWindow ?? 128000,\n\t\tmaxTokens: definition.maxTokens ?? 16384,\n\t\tsamplingParams: definition.samplingParams,\n\t\theaders: undefined,\n\t\tcacheRetention: definition.cacheRetention ?? providerConfig.cacheRetention,\n\t\tcompat: mergeCompat(providerConfig.compat, definition.compat),\n\t};\n}\n\nfunction applyModelsJson(\n\tproviderId: string,\n\tbaseModels: readonly Model<Api>[],\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n): Model<Api>[] {\n\tif (!config) return [...baseModels];\n\tconst hasOverrides = config.modelOverrides && Object.keys(config.modelOverrides).length > 0;\n\tif (\n\t\t!config.models?.length &&\n\t\t!config.baseUrl &&\n\t\t!config.headers &&\n\t\t!config.extraBody &&\n\t\t!config.compat &&\n\t\t!hasOverrides &&\n\t\t!config.whitelist &&\n\t\t!config.blacklist &&\n\t\t!config.apiKey &&\n\t\tconfig.authHeader === undefined\n\t) {\n\t\tthrow new Error(\n\t\t\t`Provider ${providerId}: must specify \"baseUrl\", \"headers\", \"extraBody\", \"compat\", \"modelOverrides\", or \"models\".`,\n\t\t);\n\t}\n\n\t// An explicit local Ollama catalog replaces Cloud discovery instead of rebinding its dynamic tags to localhost.\n\tconst configuredBaseModels = providerId === \"ollama\" && config.models?.length ? [] : baseModels;\n\tconst models: Model<Api>[] = configuredBaseModels.map((model) => ({\n\t\t...model,\n\t\tbaseUrl: config.baseUrl ?? model.baseUrl,\n\t\tcompat: mergeCompat(model.compat, config.compat),\n\t}));\n\tfor (const definition of config.models ?? []) {\n\t\tconst existingIndex = models.findIndex((model) => model.id === definition.id);\n\t\tconst defaults = existingIndex >= 0 ? models[existingIndex] : models[0];\n\t\tconst model = modelFromJson(providerId, definition, config, {\n\t\t\t...defaults,\n\t\t\tapi: extension?.api ?? defaults?.api,\n\t\t\tbaseUrl: extension?.baseUrl ?? defaults?.baseUrl,\n\t\t});\n\t\tif (existingIndex >= 0) models[existingIndex] = model;\n\t\telse models.push(model);\n\t}\n\tconst whitelist = config.whitelist ? new Set(config.whitelist) : undefined;\n\tconst blacklist = config.blacklist ? new Set(config.blacklist) : undefined;\n\treturn models.filter(\n\t\t(model) =>\n\t\t\t(whitelist === undefined || whitelist.has(model.id)) && (blacklist === undefined || !blacklist.has(model.id)),\n\t);\n}\n\nfunction applyExtension(\n\tproviderId: string,\n\tmodels: readonly Model<Api>[],\n\tconfig: ProviderConfigInput | undefined,\n\tcustomModelIds: ReadonlySet<string>,\n): Model<Api>[] {\n\tif (!config) return [...models];\n\tif (!config.models) {\n\t\treturn config.baseUrl ? models.map((model) => ({ ...model, baseUrl: config.baseUrl! })) : [...models];\n\t}\n\tconst declaredModels = config.models;\n\tconst extensionModels = declaredModels.map((definition) => {\n\t\tconst defaults = models.find((model) => model.id === definition.id) ?? models[0];\n\t\tconst api = definition.api ?? config.api ?? defaults?.api;\n\t\tif (!api) {\n\t\t\tthrow new Error(\n\t\t\t\t`Provider ${providerId}, model ${definition.id}: no \"api\" specified. Set at provider or model level.`,\n\t\t\t);\n\t\t}\n\t\tconst baseUrl = definition.baseUrl ?? config.baseUrl ?? defaults?.baseUrl;\n\t\tif (!baseUrl) throw new Error(`Provider ${providerId}: \"baseUrl\" is required when defining custom models.`);\n\t\treturn {\n\t\t\t...definition,\n\t\t\tapi,\n\t\t\tprovider: providerId,\n\t\t\tbaseUrl,\n\t\t\theaders: undefined,\n\t\t};\n\t});\n\treturn [\n\t\t...extensionModels,\n\t\t...models.filter(\n\t\t\t(model) => customModelIds.has(model.id) && !declaredModels.some((definition) => definition.id === model.id),\n\t\t),\n\t];\n}\n\nfunction adaptOAuth(config: ExtensionOAuthConfig): OAuthAuth {\n\treturn {\n\t\tname: config.name,\n\t\tisSubscription: config.isSubscription,\n\t\tlogin: async (callbacks) => {\n\t\t\tconst credential = await config.login({\n\t\t\t\tonAuth: (info) => callbacks.notify({ type: \"auth_url\", ...info }),\n\t\t\t\tonDeviceCode: (info) => callbacks.notify({ type: \"device_code\", ...info }),\n\t\t\t\tonPrompt: (prompt) => callbacks.prompt({ type: \"text\", ...prompt }),\n\t\t\t\tonProgress: (message) => callbacks.notify({ type: \"progress\", message }),\n\t\t\t\tonManualCodeInput: () => callbacks.prompt({ type: \"manual_code\", message: \"Paste the authorization code\" }),\n\t\t\t\tonSelect: (prompt) => callbacks.prompt({ type: \"select\", ...prompt }),\n\t\t\t\tsignal: callbacks.signal,\n\t\t\t});\n\t\t\treturn { ...credential, type: \"oauth\" };\n\t\t},\n\t\trefresh: async (credential, signal) => ({ ...(await config.refreshToken(credential, signal)), type: \"oauth\" }),\n\t\ttoAuth: async (credential) => ({ apiKey: config.getApiKey(credential) }),\n\t\t...(config.check ? { check: config.check } : {}),\n\t};\n}\n\nfunction composeOAuthAuth(\n\tproviderId: string,\n\tbase: Provider | undefined,\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n): OAuthAuth | undefined {\n\tconst oauth = extension?.oauth ? adaptOAuth(extension.oauth) : base?.auth.oauth;\n\tif (!oauth) return undefined;\n\tconst rawHeaders = configuredHeaders(config, extension);\n\tconst authHeader = extension?.authHeader ?? config?.authHeader ?? false;\n\treturn {\n\t\t...oauth,\n\t\ttoAuth: async (credential) => {\n\t\t\tconst auth = await oauth.toAuth(credential);\n\t\t\tconst env = credential.env;\n\t\t\tconst headers = resolveHeadersOrThrow(\n\t\t\t\trawHeaders,\n\t\t\t\t`provider \"${providerId}\"`,\n\t\t\t\ttypeof env === \"object\" && env !== null ? (env as Record<string, string>) : undefined,\n\t\t\t);\n\t\t\treturn withConfiguredAuth(auth, headers, authHeader);\n\t\t},\n\t};\n}\n\nfunction rawModelHeaders(\n\tmodel: Model<Api>,\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n): Record<string, string> | undefined {\n\tconst definition = config?.models?.find((entry) => entry.id === model.id);\n\tconst extensionModel = extension?.models?.find((entry) => entry.id === model.id);\n\tconst headers = {\n\t\t...config?.modelOverrides?.[model.id]?.headers,\n\t\t...definition?.headers,\n\t\t...extensionModel?.headers,\n\t};\n\treturn Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nfunction rawModelExtraBody(\n\tmodel: Model<Api>,\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n): Record<string, unknown> | undefined {\n\tconst definition = config?.models?.find((entry) => entry.id === model.id);\n\tconst extensionModel = extension?.models?.find((entry) => entry.id === model.id);\n\tconst extraBody = {\n\t\t...config?.modelOverrides?.[model.id]?.extraBody,\n\t\t...definition?.extraBody,\n\t\t...extensionModel?.extraBody,\n\t};\n\treturn Object.keys(extraBody).length > 0 ? extraBody : undefined;\n}\n\nexport function validateExtensionProvider(\n\tproviderId: string,\n\tbase: Provider | undefined,\n\tmodelsConfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput,\n): void {\n\tif (extension.streamSimple && !extension.api) {\n\t\tthrow new Error(`Provider ${providerId}: \"api\" is required when registering streamSimple.`);\n\t}\n\tapplyExtension(\n\t\tproviderId,\n\t\tapplyModelsJson(providerId, base?.getModels() ?? [], modelsConfig, extension),\n\t\textension,\n\t\tnew Set((modelsConfig?.models ?? []).map((definition) => definition.id)),\n\t);\n}\n\n/** Compose built-in, models.json, and extension layers without reading credentials. */\nexport function composeModelProvider(\n\tproviderId: string,\n\tbase: Provider | undefined,\n\tmodelConfig: ModelConfig,\n\textension: ProviderConfigInput | undefined,\n): Provider {\n\tconst config = modelConfig.getProvider(providerId);\n\tlet extensionOAuthCredential: OAuthCredentials | undefined;\n\tlet refreshedExtensionModels: ProviderConfigInput[\"models\"];\n\tconst currentExtension = (): ProviderConfigInput | undefined =>\n\t\textension && refreshedExtensionModels ? { ...extension, models: refreshedExtensionModels } : extension;\n\t// models.json modelOverrides are the topmost user-config layer: they apply once,\n\t// after custom-model upserts, extension model replacement, and legacy OAuth projection.\n\tconst getModels = () => {\n\t\tlet models = applyExtension(\n\t\t\tproviderId,\n\t\t\tapplyModelsJson(providerId, base?.getModels() ?? [], config, currentExtension()),\n\t\t\tcurrentExtension(),\n\t\t\tnew Set((config?.models ?? []).map((definition) => definition.id)),\n\t\t);\n\t\tif (extensionOAuthCredential && extension?.oauth?.modifyModels) {\n\t\t\tmodels = extension.oauth.modifyModels(models, extensionOAuthCredential);\n\t\t}\n\t\treturn models.map((model) => {\n\t\t\tconst override = config?.modelOverrides?.[model.id];\n\t\t\treturn override ? applyModelOverride(model, override) : model;\n\t\t});\n\t};\n\t// Validate eagerly so registration/reload reports structural errors immediately.\n\tgetModels();\n\tconst apiKey = composeApiKeyAuth(providerId, base, config, extension);\n\tconst oauth = composeOAuthAuth(providerId, base, config, extension);\n\tif (!apiKey && !oauth) throw new Error(`Provider ${providerId}: no authentication method configured.`);\n\t// The documented local `ollama` models.json catalog must not invoke the Cloud builtin's refresh with its\n\tconst refreshBase = providerId === \"ollama\" && config?.models?.length ? undefined : base?.refreshModels?.bind(base);\n\n\tconst supportsBaseApi = (model: Model<Api>) => base?.getModels().some((entry) => entry.api === model.api) ?? false;\n\tconst streamWith = (\n\t\tmodel: Model<Api>,\n\t\tcontext: Context,\n\t\toptions: StreamOptions | undefined,\n\t\tsimple: boolean,\n\t): AssistantMessageEventStream =>\n\t\tlazyStream(model, async () => {\n\t\t\tconst format = getToolCallFormat(model);\n\t\t\tif (format && context.tools && context.tools.length > 0) {\n\t\t\t\tconst protocol = getProtocol(format);\n\t\t\t\tconst transformedContext = transformContext(context, protocol);\n\t\t\t\tconst innerStream = streamWith(model, transformedContext, options, simple);\n\t\t\t\treturn wrapStreamWithToolCallMiddleware(innerStream, protocol, context.tools);\n\t\t\t}\n\t\t\tif (extension?.streamSimple && model.api === extension.api) {\n\t\t\t\treturn extension.streamSimple(model, context, options as SimpleStreamOptions);\n\t\t\t}\n\t\t\tif (base && supportsBaseApi(model)) {\n\t\t\t\treturn simple\n\t\t\t\t\t? base.streamSimple(model, context, options as SimpleStreamOptions)\n\t\t\t\t\t: base.stream(model, context, options);\n\t\t\t}\n\t\t\tconst api = getApiProvider(model.api);\n\t\t\tif (!api) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No API provider registered for api: ${model.api} (model \"${model.provider}/${model.id}\"). ` +\n\t\t\t\t\t\t`Load the extension that implements this api, or fix the \"api\" value for provider \"${providerId}\" in models.json.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn simple\n\t\t\t\t? api.streamSimple(model, context, options as SimpleStreamOptions)\n\t\t\t\t: api.stream(model, context, options);\n\t\t});\n\n\tconst provider: Provider = {\n\t\tid: providerId,\n\t\tname: extension?.name ?? config?.name ?? base?.name ?? extension?.oauth?.name ?? providerId,\n\t\tbaseUrl: extension?.baseUrl ?? config?.baseUrl ?? base?.baseUrl,\n\t\theaders: base?.headers,\n\t\t// Composed providers must not silently drop provider-declared retry profiles.\n\t\tretryPolicy: extension?.retryPolicy ?? base?.retryPolicy,\n\t\tauth: { ...(apiKey ? { apiKey } : {}), ...(oauth ? { oauth } : {}) },\n\t\tgetModels,\n\t\trefreshModels:\n\t\t\trefreshBase || extension?.refreshModels || extension?.oauth?.modifyModels\n\t\t\t\t? async (context) => {\n\t\t\t\t\t\tawait refreshBase?.(context);\n\t\t\t\t\t\tlet refreshed: NonNullable<ProviderConfigInput[\"models\"]> | undefined;\n\t\t\t\t\t\tif (extension?.refreshModels) refreshed = await extension.refreshModels(context);\n\t\t\t\t\t\tif (context.signal.aborted) return;\n\t\t\t\t\t\tconst oauthCredential = context.credential?.type === \"oauth\" ? context.credential : undefined;\n\t\t\t\t\t\tawait context.publish({\n\t\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\t\tif (refreshed) {\n\t\t\t\t\t\t\t\t\t// Validate before publishing the new synchronous list.\n\t\t\t\t\t\t\t\t\tapplyExtension(\n\t\t\t\t\t\t\t\t\t\tproviderId,\n\t\t\t\t\t\t\t\t\t\tapplyModelsJson(providerId, base?.getModels() ?? [], config, extension),\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t...extension,\n\t\t\t\t\t\t\t\t\t\t\tmodels: refreshed,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tnew Set((config?.models ?? []).map((definition) => definition.id)),\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\trefreshedExtensionModels = refreshed;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\textensionOAuthCredential = oauthCredential;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\tfilterModels: base?.filterModels\n\t\t\t? (models, credential: Credential | undefined) => base.filterModels!(models, credential)\n\t\t\t: undefined,\n\t\tstream: (model, context, options) => streamWith(model, context, options, false),\n\t\tstreamSimple: (model, context, options) => streamWith(model, context, options, true),\n\t};\n\n\tconst fetchDeferred = base?.fetchDeferred;\n\tif (fetchDeferred) {\n\t\tprovider.fetchDeferred = (model, handle, options) => fetchDeferred(model, handle, options);\n\t}\n\tconst cancelDeferred = base?.cancelDeferred;\n\tif (cancelDeferred) {\n\t\tprovider.cancelDeferred = (model, handle, options) => cancelDeferred(model, handle, options);\n\t}\n\n\treturn provider;\n}\n\nexport function resolveConfiguredModelHeaders(\n\tmodel: Model<Api>,\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n\tenv?: Record<string, string>,\n): Record<string, string> | undefined {\n\treturn resolveHeadersOrThrow(\n\t\trawModelHeaders(model, config, extension),\n\t\t`model \"${model.provider}/${model.id}\"`,\n\t\tenv,\n\t);\n}\n\nexport interface CompatibilityRequestConfig {\n\theaders?: ProviderHeaders;\n\textraBody?: Record<string, unknown>;\n\tupstreamModelId?: string;\n\tserviceTier?: \"auto\" | \"flex\" | \"priority\";\n\tauthHeader: boolean;\n}\n\nexport function resolveCompatibilityRequestConfig(\n\tmodel: Model<Api>,\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n\tenv?: Record<string, string>,\n): CompatibilityRequestConfig {\n\tconst configured = resolveHeadersOrThrow(\n\t\t{ ...configuredHeaders(config, extension), ...rawModelHeaders(model, config, extension) },\n\t\t`model \"${model.provider}/${model.id}\"`,\n\t\tenv,\n\t);\n\tconst modelDefinition = config?.models?.find((entry) => entry.id === model.id);\n\tconst extensionModel = extension?.models?.find((entry) => entry.id === model.id);\n\tconst configuredExtraBody = {\n\t\t...config?.extraBody,\n\t\t...extension?.extraBody,\n\t\t...rawModelExtraBody(model, config, extension),\n\t};\n\treturn {\n\t\theaders: model.headers || configured ? { ...model.headers, ...configured } : undefined,\n\t\textraBody: Object.keys(configuredExtraBody).length > 0 ? configuredExtraBody : undefined,\n\t\tupstreamModelId: extensionModel?.upstreamModelId ?? modelDefinition?.upstreamModelId ?? model.upstreamModelId,\n\t\tserviceTier: extensionModel?.serviceTier ?? modelDefinition?.serviceTier ?? model.serviceTier,\n\t\tauthHeader: extension?.authHeader ?? config?.authHeader ?? false,\n\t};\n}\n\nexport function configuredRequestAuthStatus(\n\tconfig: ModelsJsonProvider | undefined,\n\textension: ProviderConfigInput | undefined,\n): AuthStatus | undefined {\n\tconst value = configuredApiKey(config, extension);\n\tif (value === undefined) {\n\t\treturn configuredHeaderAuthStatus(config?.headers, extension?.headers);\n\t}\n\tif (isCommandConfigValue(value)) return { configured: true, source: \"models_json_command\" };\n\tconst names = getConfigValueEnvVarNames(value);\n\tif (names.length > 0) {\n\t\treturn isConfigValueConfigured(value)\n\t\t\t? { configured: true, source: \"environment\", label: names.join(\", \") }\n\t\t\t: { configured: false };\n\t}\n\treturn { configured: true, source: extension?.apiKey !== undefined ? \"fallback\" : \"models_json_key\" };\n}\n"]}
@@ -7,6 +7,10 @@ export interface ActiveFallbackState {
7
7
  originalSelector: string;
8
8
  originalThinkingLevel?: ThinkingLevel;
9
9
  lastAppliedThinkingLevel?: ThinkingLevel;
10
+ /** Pin provenance: refusal contributions release on compaction, billing never. */
11
+ pinnedByRefusal: boolean;
12
+ pinnedByBilling: boolean;
13
+ /** Derived OR of the two provenance flags - the only field consumers read. */
10
14
  pinned: boolean;
11
15
  }
12
16
  type FallbackReason = "transient" | "refusal" | "hard-error" | "billing";
@@ -76,6 +80,16 @@ export declare class RetryFallbackController {
76
80
  * so the revert restore-rule must no longer treat it as fallback-applied.
77
81
  */
78
82
  noteManualThinkingLevel(): void;
83
+ /**
84
+ * A senpi-owned compaction successfully rewrote the conversation context, the
85
+ * one safe moment to re-attempt a refusal-pinned fallback's original model:
86
+ * the refusal assumption ("the same context refuses again") no longer holds.
87
+ * Refusal contributions clear; billing contributions never release - retrying
88
+ * the same account never recovers it. Returns true only when the overall pin
89
+ * transitioned true -> false, i.e. the caller may now restore the primary via
90
+ * the existing maybeRestorePrimary gate.
91
+ */
92
+ notifyCompactionApplied(): boolean;
79
93
  /** A user-driven model change abandons the fallback window entirely. */
80
94
  clearForManualModelChange(model: Model<Api>): void;
81
95
  tryFallback(reason: FallbackReason, failure: {
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/core/retry-fallback/controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/core/retry-fallback/controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,KAAK,GAAG,EAAsB,KAAK,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAYjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,mBAAmB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,qBAAqB,CAAC,EAAE,aAAa,CAAC;IACtC,wBAAwB,CAAC,EAAE,aAAa,CAAC;IACzC,kFAAkF;IAClF,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,8EAA8E;IAC9E,MAAM,EAAE,OAAO,CAAC;CAChB;AAED,KAAK,cAAc,GAAG,WAAW,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;AAEzE,UAAU,gBAAgB;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,2BAA2B;IAC3C,WAAW,IAAI,gBAAgB,CAAC;IAChC,QAAQ,EAAE;QACT,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,4EAA4E;QAC5E,YAAY,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;QAC1C,gHAAgH;QAChH,kBAAkB,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;KAChD,CAAC;IACF,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,cAAc,CAAC;IACvB,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,GAAG,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/G,IAAI,CACH,KAAK,EACF;QACA,IAAI,EAAE,wBAAwB,CAAC;QAC/B,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,cAAc,CAAC;KACtB,GACD;QAAE,IAAI,EAAE,yBAAyB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAC9D,IAAI,CAAC;IACR,kBAAkB,IAAI;QAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAAC,aAAa,CAAC,EAAE,aAAa,CAAA;KAAE,GAAG,SAAS,CAAC;IACvF,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3C;AAED,qBAAa,uBAAuB;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA8B;IACnD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,qBAAqB,CAAqB;IAQlD,OAAO,CAAC,cAAc,CAAsD;gBAEhE,IAAI,EAAE,2BAA2B;IAI7C,IAAI,WAAW,IAAI,QAAQ,CAAC,mBAAmB,CAAC,GAAG,SAAS,CAE3D;IAED,IAAI,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAE1C;IAED,SAAS,IAAI,IAAI;IAKjB,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,eAAe;IASvB,cAAc,IAAI,OAAO;IAIzB;;;;;OAKG;IACH,kBAAkB,IAAI,OAAO;IAO7B;;;;;OAKG;IACG,mBAAmB,CAAC,YAAY,EAAE,iBAAiB,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAwBtF;;;OAGG;IACH,uBAAuB,IAAI,IAAI;IAI/B;;;;;;;;OAQG;IACH,uBAAuB,IAAI,OAAO;IAelC,wEAAwE;IACxE,yBAAyB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI;IAQ5C,WAAW,CAChB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GACvD,OAAO,CAAC,OAAO,CAAC;IA+BnB,OAAO,CAAC,aAAa;IAyDrB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,IAAI;CAGZ"}
@@ -85,6 +85,31 @@ export class RetryFallbackController {
85
85
  if (this.state)
86
86
  this.state.lastAppliedThinkingLevel = undefined;
87
87
  }
88
+ /**
89
+ * A senpi-owned compaction successfully rewrote the conversation context, the
90
+ * one safe moment to re-attempt a refusal-pinned fallback's original model:
91
+ * the refusal assumption ("the same context refuses again") no longer holds.
92
+ * Refusal contributions clear; billing contributions never release - retrying
93
+ * the same account never recovers it. Returns true only when the overall pin
94
+ * transitioned true -> false, i.e. the caller may now restore the primary via
95
+ * the existing maybeRestorePrimary gate.
96
+ */
97
+ notifyCompactionApplied() {
98
+ const state = this.state;
99
+ if (!state)
100
+ return false;
101
+ state.pinnedByRefusal = false;
102
+ const wasPinned = state.pinned;
103
+ state.pinned = state.pinnedByBilling;
104
+ if (!wasPinned || state.pinned)
105
+ return false;
106
+ this.deps.logger.info("refusal_pin_released", {
107
+ chainKey: state.chainKey,
108
+ originalSelector: state.originalSelector,
109
+ trigger: "compaction",
110
+ });
111
+ return true;
112
+ }
88
113
  /** A user-driven model change abandons the fallback window entirely. */
89
114
  clearForManualModelChange(model) {
90
115
  if (this.state) {
@@ -107,12 +132,17 @@ export class RetryFallbackController {
107
132
  await this.deps.switchModel(candidate.model, thinking, "fallback");
108
133
  const from = formatSelector(current.model);
109
134
  const to = formatSelector(candidate.model);
135
+ const prior = this.state;
136
+ const pinnedByRefusal = prior?.pinnedByRefusal === true || reason === "refusal";
137
+ const pinnedByBilling = prior?.pinnedByBilling === true || reason === "billing";
110
138
  this.state = {
111
139
  chainKey: candidate.chainKey,
112
- originalSelector: this.state?.originalSelector ?? from,
113
- originalThinkingLevel: this.state?.originalThinkingLevel ?? current.thinkingLevel,
140
+ originalSelector: prior?.originalSelector ?? from,
141
+ originalThinkingLevel: prior?.originalThinkingLevel ?? current.thinkingLevel,
114
142
  lastAppliedThinkingLevel: thinking,
115
- pinned: this.state?.pinned === true || reason === "refusal" || reason === "billing",
143
+ pinnedByRefusal,
144
+ pinnedByBilling,
145
+ pinned: pinnedByRefusal || pinnedByBilling,
116
146
  };
117
147
  this.deps.logger.info("fallback_applied", { from, to, chainKey: candidate.chainKey, reason });
118
148
  this.deps.emit({ type: "retry_fallback_applied", from, to, chainKey: candidate.chainKey, reason });
@@ -1 +1 @@
1
- {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../../src/core/retry-fallback/controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { type Api, clampThinkingLevel, type Model } from \"@earendil-works/pi-ai\";\nimport {\n\tbaseSelector,\n\tcandidatesAfter,\n\tcanonicalizeFallbackChains,\n\ttype FallbackChains,\n\ttype FallbackSelector,\n\tformatSelector,\n\thasExplicitFallbackOptOut,\n\tparseFallbackSelector,\n\tresolveChainKey,\n} from \"./chains.ts\";\nimport type { SelectorCooldowns } from \"./cooldown.ts\";\nimport type { FallbackLogger } from \"./log.ts\";\n\nexport interface ActiveFallbackState {\n\tchainKey: string;\n\toriginalSelector: string;\n\toriginalThinkingLevel?: ThinkingLevel;\n\tlastAppliedThinkingLevel?: ThinkingLevel;\n\tpinned: boolean;\n}\n\ntype FallbackReason = \"transient\" | \"refusal\" | \"hard-error\" | \"billing\";\n\ninterface FallbackSettings {\n\tmodelFallback: boolean;\n\tchains: Readonly<Record<string, readonly string[]>>;\n}\n\nexport interface RetryFallbackControllerDeps {\n\tgetSettings(): FallbackSettings;\n\tregistry: {\n\t\tfind(provider: string, id: string): Model<Api> | undefined;\n\t\tgetAll(): Model<Api>[];\n\t\t/** Ranks bare-selector expansion: OAuth-credential providers come first. */\n\t\tisUsingOAuth?(model: Model<Api>): boolean;\n\t\t/** Filters bare-selector expansion: a definitive `false` keeps a lane that can never serve out of the chain. */\n\t\tisFallbackEligible?(model: Model<Api>): boolean;\n\t};\n\tcooldowns: SelectorCooldowns;\n\tlogger: FallbackLogger;\n\tswitchModel(model: Model<Api>, thinking: ThinkingLevel, reason: \"fallback\" | \"fallback-revert\"): Promise<void>;\n\temit(\n\t\tevent:\n\t\t\t| {\n\t\t\t\t\ttype: \"retry_fallback_applied\";\n\t\t\t\t\tfrom: string;\n\t\t\t\t\tto: string;\n\t\t\t\t\tchainKey: string;\n\t\t\t\t\treason: FallbackReason;\n\t\t\t }\n\t\t\t| { type: \"retry_fallback_reverted\"; from: string; to: string },\n\t): void;\n\tgetCurrentSelector(): { model: Model<Api>; thinkingLevel?: ThinkingLevel } | undefined;\n\tisAuthAvailable(provider: string): boolean;\n}\n\nexport class RetryFallbackController {\n\tprivate readonly deps: RetryFallbackControllerDeps;\n\tprivate readonly triedSelectors = new Set<string>();\n\tprivate state: ActiveFallbackState | undefined;\n\tprivate lastExhaustedChainKey: string | undefined;\n\t// Content-keyed memo of canonicalizeFallbackChains. Provider-error handling calls\n\t// canTryFallback/nextCandidate several times per error; without this each call\n\t// re-expands bare selectors and re-probes registry eligibility over the full\n\t// model set. Keying on the serialized chains content means an unchanged config\n\t// reuses the canonical result, while a chains edit invalidates immediately.\n\t// Registry mutations without a chains change are not tracked here; they are rare\n\t// and in practice coincide with a settings reload that replaces the chains object.\n\tprivate canonicalCache: { key: string; chains: FallbackChains } | undefined;\n\n\tconstructor(deps: RetryFallbackControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tget activeState(): Readonly<ActiveFallbackState> | undefined {\n\t\treturn this.state;\n\t}\n\n\tget exhaustedChainKey(): string | undefined {\n\t\treturn this.lastExhaustedChainKey;\n\t}\n\n\tresetTurn(): void {\n\t\tthis.triedSelectors.clear();\n\t\tthis.lastExhaustedChainKey = undefined;\n\t}\n\n\tclear(): void {\n\t\tthis.state = undefined;\n\t\tthis.canonicalCache = undefined;\n\t\tthis.resetTurn();\n\t}\n\n\tprivate canonicalChains(): FallbackChains {\n\t\tconst chains = this.deps.getSettings().chains;\n\t\tconst key = JSON.stringify(chains);\n\t\tif (this.canonicalCache?.key === key) return this.canonicalCache.chains;\n\t\tconst canonical = canonicalizeFallbackChains(chains, this.deps.registry);\n\t\tthis.canonicalCache = { key, chains: canonical };\n\t\treturn canonical;\n\t}\n\n\tcanTryFallback(): boolean {\n\t\treturn this.nextCandidate(false) !== undefined;\n\t}\n\n\t/**\n\t * Whether a chain exists for the current model at all, regardless of whether\n\t * a candidate is usable right now. `canTryFallback()` answers the latter and\n\t * goes false on cooldown or exhaustion, so it cannot tell a UI \"you never\n\t * configured a chain\" apart from \"the chain is spent\".\n\t */\n\thasConfiguredChain(): boolean {\n\t\tconst current = this.deps.getCurrentSelector();\n\t\tif (!current) return false;\n\t\tconst chains = this.canonicalChains();\n\t\treturn resolveChainKey(current.model, current.thinkingLevel, chains) !== undefined;\n\t}\n\n\t/**\n\t * Revert to the chain's original model at a turn boundary. Only fires for\n\t * unpinned state under the cooldown-expiry policy once the original selector\n\t * is no longer suppressed and is still usable; pinned (refusal) state and the\n\t * \"never\" policy always hold the fallback model.\n\t */\n\tasync maybeRestorePrimary(revertPolicy: \"cooldown-expiry\" | \"never\"): Promise<boolean> {\n\t\tconst state = this.state;\n\t\tif (!state || state.pinned || revertPolicy !== \"cooldown-expiry\") return false;\n\t\tif (this.deps.cooldowns.isSuppressed(state.originalSelector)) return false;\n\t\tconst selector = parseFallbackSelector(state.originalSelector, this.deps.registry);\n\t\tif (!selector || !this.deps.isAuthAvailable(selector.provider)) return false;\n\t\tconst model = this.deps.registry.find(selector.provider, selector.id);\n\t\tconst current = this.deps.getCurrentSelector();\n\t\tif (!model || !current) return false;\n\t\t// User override wins: only restore the original thinking level when the\n\t\t// current level still equals the level the fallback switch applied. A manual\n\t\t// setThinkingLevel clears lastAppliedThinkingLevel (see noteManualThinkingLevel).\n\t\tconst thinking =\n\t\t\tcurrent.thinkingLevel === state.lastAppliedThinkingLevel\n\t\t\t\t? (state.originalThinkingLevel ?? current.thinkingLevel ?? \"off\")\n\t\t\t\t: (current.thinkingLevel ?? \"off\");\n\t\tawait this.deps.switchModel(model, thinking, \"fallback-revert\");\n\t\tconst from = formatSelector(current.model);\n\t\tthis.state = undefined;\n\t\tthis.deps.logger.info(\"fallback_reverted\", { from, to: state.originalSelector });\n\t\tthis.deps.emit({ type: \"retry_fallback_reverted\", from, to: state.originalSelector });\n\t\treturn true;\n\t}\n\n\t/**\n\t * A user-driven setThinkingLevel makes the current level a deliberate choice,\n\t * so the revert restore-rule must no longer treat it as fallback-applied.\n\t */\n\tnoteManualThinkingLevel(): void {\n\t\tif (this.state) this.state.lastAppliedThinkingLevel = undefined;\n\t}\n\n\t/** A user-driven model change abandons the fallback window entirely. */\n\tclearForManualModelChange(model: Model<Api>): void {\n\t\tif (this.state) {\n\t\t\tthis.deps.logger.info(\"fallback_cleared_manual\", { selector: formatSelector(model) });\n\t\t}\n\t\tthis.state = undefined;\n\t\tthis.deps.cooldowns.clear(formatSelector(model));\n\t}\n\n\tasync tryFallback(\n\t\treason: FallbackReason,\n\t\tfailure: { errorMessage?: string; retryAfterMs?: number },\n\t): Promise<boolean> {\n\t\tconst current = this.deps.getCurrentSelector();\n\t\tconst candidate = this.nextCandidate();\n\t\tif (!current || !candidate) return false;\n\t\tconst currentBase = formatSelector(current.model);\n\t\tif (reason === \"transient\" || reason === \"hard-error\" || reason === \"billing\") {\n\t\t\tthis.deps.cooldowns.note(currentBase, failure);\n\t\t\tthis.deps.logger.info(\"cooldown_noted\", { selector: currentBase, errorMessage: failure.errorMessage });\n\t\t}\n\n\t\tconst thinking = this.selectThinking(candidate.selector, candidate.model, current.thinkingLevel);\n\t\tawait this.deps.switchModel(candidate.model, thinking, \"fallback\");\n\t\tconst from = formatSelector(current.model);\n\t\tconst to = formatSelector(candidate.model);\n\t\tthis.state = {\n\t\t\tchainKey: candidate.chainKey,\n\t\t\toriginalSelector: this.state?.originalSelector ?? from,\n\t\t\toriginalThinkingLevel: this.state?.originalThinkingLevel ?? current.thinkingLevel,\n\t\t\tlastAppliedThinkingLevel: thinking,\n\t\t\tpinned: this.state?.pinned === true || reason === \"refusal\" || reason === \"billing\",\n\t\t};\n\t\tthis.deps.logger.info(\"fallback_applied\", { from, to, chainKey: candidate.chainKey, reason });\n\t\tthis.deps.emit({ type: \"retry_fallback_applied\", from, to, chainKey: candidate.chainKey, reason });\n\t\treturn true;\n\t}\n\n\tprivate nextCandidate(\n\t\treserve = true,\n\t): { chainKey: string; selector: FallbackSelector; model: Model<Api> } | undefined {\n\t\tconst settings = this.deps.getSettings();\n\t\tconst current = this.deps.getCurrentSelector();\n\t\tif (!settings.modelFallback || !current) return undefined;\n\t\tconst chains = this.canonicalChains();\n\t\t// Order matters: a model's own chain wins, then the active episode keeps\n\t\t// owning its walk (its last rung usually has no key of its own), and only\n\t\t// a session with neither falls back to the wildcard lane.\n\t\tconst chainKey =\n\t\t\tresolveChainKey(current.model, current.thinkingLevel, chains) ??\n\t\t\tthis.state?.chainKey ??\n\t\t\t(hasExplicitFallbackOptOut(settings.chains, current.model, current.thinkingLevel)\n\t\t\t\t? undefined\n\t\t\t\t: resolveChainKey(current.model, current.thinkingLevel, chains, { allowWildcard: true }));\n\t\tconst entries = chainKey ? chains[chainKey] : undefined;\n\t\tif (!chainKey || !entries) {\n\t\t\tif (reserve) this.deps.logger.debug(\"no_chain\", { selector: formatSelector(current.model) });\n\t\t\treturn undefined;\n\t\t}\n\t\tfor (const raw of candidatesAfter(entries, formatSelector(current.model, current.thinkingLevel))) {\n\t\t\tconst selector = parseFallbackSelector(raw, this.deps.registry);\n\t\t\tif (!selector) {\n\t\t\t\tthis.skip(raw, \"unknown\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (selector.provider === current.model.provider && selector.id === current.model.id) {\n\t\t\t\tthis.skip(raw, \"self\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst base = baseSelector(selector);\n\t\t\tif (this.triedSelectors.has(base)) {\n\t\t\t\tthis.skip(raw, \"tried\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (this.deps.cooldowns.isSuppressed(base)) {\n\t\t\t\tthis.skip(raw, \"suppressed\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!this.deps.isAuthAvailable(selector.provider)) {\n\t\t\t\tthis.skip(raw, \"unauthenticated\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst model = this.deps.registry.find(selector.provider, selector.id);\n\t\t\tif (!model) {\n\t\t\t\tthis.skip(raw, \"unknown\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (reserve) this.triedSelectors.add(base);\n\t\t\treturn { chainKey, selector, model };\n\t\t}\n\t\tthis.lastExhaustedChainKey = chainKey;\n\t\tif (reserve) this.deps.logger.info(\"candidates_exhausted\", { chainKey });\n\t\treturn undefined;\n\t}\n\n\tprivate selectThinking(\n\t\tselector: FallbackSelector,\n\t\tmodel: Model<Api>,\n\t\tinherited: ThinkingLevel | undefined,\n\t): ThinkingLevel {\n\t\tconst requested = selector.thinkingLevel ?? inherited ?? \"off\";\n\t\t// Canonical clamp walks to the NEAREST supported level. Picking the highest\n\t\t// supported level instead would escalate an \"off\" request to max reasoning on\n\t\t// always-on fallback models.\n\t\treturn clampThinkingLevel(model, requested);\n\t}\n\n\tprivate skip(candidate: string, skipReason: string): void {\n\t\tthis.deps.logger.debug(\"candidate_skipped\", { candidate, skipReason });\n\t}\n}\n"]}
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../../src/core/retry-fallback/controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport { type Api, clampThinkingLevel, type Model } from \"@earendil-works/pi-ai\";\nimport {\n\tbaseSelector,\n\tcandidatesAfter,\n\tcanonicalizeFallbackChains,\n\ttype FallbackChains,\n\ttype FallbackSelector,\n\tformatSelector,\n\thasExplicitFallbackOptOut,\n\tparseFallbackSelector,\n\tresolveChainKey,\n} from \"./chains.ts\";\nimport type { SelectorCooldowns } from \"./cooldown.ts\";\nimport type { FallbackLogger } from \"./log.ts\";\n\nexport interface ActiveFallbackState {\n\tchainKey: string;\n\toriginalSelector: string;\n\toriginalThinkingLevel?: ThinkingLevel;\n\tlastAppliedThinkingLevel?: ThinkingLevel;\n\t/** Pin provenance: refusal contributions release on compaction, billing never. */\n\tpinnedByRefusal: boolean;\n\tpinnedByBilling: boolean;\n\t/** Derived OR of the two provenance flags - the only field consumers read. */\n\tpinned: boolean;\n}\n\ntype FallbackReason = \"transient\" | \"refusal\" | \"hard-error\" | \"billing\";\n\ninterface FallbackSettings {\n\tmodelFallback: boolean;\n\tchains: Readonly<Record<string, readonly string[]>>;\n}\n\nexport interface RetryFallbackControllerDeps {\n\tgetSettings(): FallbackSettings;\n\tregistry: {\n\t\tfind(provider: string, id: string): Model<Api> | undefined;\n\t\tgetAll(): Model<Api>[];\n\t\t/** Ranks bare-selector expansion: OAuth-credential providers come first. */\n\t\tisUsingOAuth?(model: Model<Api>): boolean;\n\t\t/** Filters bare-selector expansion: a definitive `false` keeps a lane that can never serve out of the chain. */\n\t\tisFallbackEligible?(model: Model<Api>): boolean;\n\t};\n\tcooldowns: SelectorCooldowns;\n\tlogger: FallbackLogger;\n\tswitchModel(model: Model<Api>, thinking: ThinkingLevel, reason: \"fallback\" | \"fallback-revert\"): Promise<void>;\n\temit(\n\t\tevent:\n\t\t\t| {\n\t\t\t\t\ttype: \"retry_fallback_applied\";\n\t\t\t\t\tfrom: string;\n\t\t\t\t\tto: string;\n\t\t\t\t\tchainKey: string;\n\t\t\t\t\treason: FallbackReason;\n\t\t\t }\n\t\t\t| { type: \"retry_fallback_reverted\"; from: string; to: string },\n\t): void;\n\tgetCurrentSelector(): { model: Model<Api>; thinkingLevel?: ThinkingLevel } | undefined;\n\tisAuthAvailable(provider: string): boolean;\n}\n\nexport class RetryFallbackController {\n\tprivate readonly deps: RetryFallbackControllerDeps;\n\tprivate readonly triedSelectors = new Set<string>();\n\tprivate state: ActiveFallbackState | undefined;\n\tprivate lastExhaustedChainKey: string | undefined;\n\t// Content-keyed memo of canonicalizeFallbackChains. Provider-error handling calls\n\t// canTryFallback/nextCandidate several times per error; without this each call\n\t// re-expands bare selectors and re-probes registry eligibility over the full\n\t// model set. Keying on the serialized chains content means an unchanged config\n\t// reuses the canonical result, while a chains edit invalidates immediately.\n\t// Registry mutations without a chains change are not tracked here; they are rare\n\t// and in practice coincide with a settings reload that replaces the chains object.\n\tprivate canonicalCache: { key: string; chains: FallbackChains } | undefined;\n\n\tconstructor(deps: RetryFallbackControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tget activeState(): Readonly<ActiveFallbackState> | undefined {\n\t\treturn this.state;\n\t}\n\n\tget exhaustedChainKey(): string | undefined {\n\t\treturn this.lastExhaustedChainKey;\n\t}\n\n\tresetTurn(): void {\n\t\tthis.triedSelectors.clear();\n\t\tthis.lastExhaustedChainKey = undefined;\n\t}\n\n\tclear(): void {\n\t\tthis.state = undefined;\n\t\tthis.canonicalCache = undefined;\n\t\tthis.resetTurn();\n\t}\n\n\tprivate canonicalChains(): FallbackChains {\n\t\tconst chains = this.deps.getSettings().chains;\n\t\tconst key = JSON.stringify(chains);\n\t\tif (this.canonicalCache?.key === key) return this.canonicalCache.chains;\n\t\tconst canonical = canonicalizeFallbackChains(chains, this.deps.registry);\n\t\tthis.canonicalCache = { key, chains: canonical };\n\t\treturn canonical;\n\t}\n\n\tcanTryFallback(): boolean {\n\t\treturn this.nextCandidate(false) !== undefined;\n\t}\n\n\t/**\n\t * Whether a chain exists for the current model at all, regardless of whether\n\t * a candidate is usable right now. `canTryFallback()` answers the latter and\n\t * goes false on cooldown or exhaustion, so it cannot tell a UI \"you never\n\t * configured a chain\" apart from \"the chain is spent\".\n\t */\n\thasConfiguredChain(): boolean {\n\t\tconst current = this.deps.getCurrentSelector();\n\t\tif (!current) return false;\n\t\tconst chains = this.canonicalChains();\n\t\treturn resolveChainKey(current.model, current.thinkingLevel, chains) !== undefined;\n\t}\n\n\t/**\n\t * Revert to the chain's original model at a turn boundary. Only fires for\n\t * unpinned state under the cooldown-expiry policy once the original selector\n\t * is no longer suppressed and is still usable; pinned (refusal) state and the\n\t * \"never\" policy always hold the fallback model.\n\t */\n\tasync maybeRestorePrimary(revertPolicy: \"cooldown-expiry\" | \"never\"): Promise<boolean> {\n\t\tconst state = this.state;\n\t\tif (!state || state.pinned || revertPolicy !== \"cooldown-expiry\") return false;\n\t\tif (this.deps.cooldowns.isSuppressed(state.originalSelector)) return false;\n\t\tconst selector = parseFallbackSelector(state.originalSelector, this.deps.registry);\n\t\tif (!selector || !this.deps.isAuthAvailable(selector.provider)) return false;\n\t\tconst model = this.deps.registry.find(selector.provider, selector.id);\n\t\tconst current = this.deps.getCurrentSelector();\n\t\tif (!model || !current) return false;\n\t\t// User override wins: only restore the original thinking level when the\n\t\t// current level still equals the level the fallback switch applied. A manual\n\t\t// setThinkingLevel clears lastAppliedThinkingLevel (see noteManualThinkingLevel).\n\t\tconst thinking =\n\t\t\tcurrent.thinkingLevel === state.lastAppliedThinkingLevel\n\t\t\t\t? (state.originalThinkingLevel ?? current.thinkingLevel ?? \"off\")\n\t\t\t\t: (current.thinkingLevel ?? \"off\");\n\t\tawait this.deps.switchModel(model, thinking, \"fallback-revert\");\n\t\tconst from = formatSelector(current.model);\n\t\tthis.state = undefined;\n\t\tthis.deps.logger.info(\"fallback_reverted\", { from, to: state.originalSelector });\n\t\tthis.deps.emit({ type: \"retry_fallback_reverted\", from, to: state.originalSelector });\n\t\treturn true;\n\t}\n\n\t/**\n\t * A user-driven setThinkingLevel makes the current level a deliberate choice,\n\t * so the revert restore-rule must no longer treat it as fallback-applied.\n\t */\n\tnoteManualThinkingLevel(): void {\n\t\tif (this.state) this.state.lastAppliedThinkingLevel = undefined;\n\t}\n\n\t/**\n\t * A senpi-owned compaction successfully rewrote the conversation context, the\n\t * one safe moment to re-attempt a refusal-pinned fallback's original model:\n\t * the refusal assumption (\"the same context refuses again\") no longer holds.\n\t * Refusal contributions clear; billing contributions never release - retrying\n\t * the same account never recovers it. Returns true only when the overall pin\n\t * transitioned true -> false, i.e. the caller may now restore the primary via\n\t * the existing maybeRestorePrimary gate.\n\t */\n\tnotifyCompactionApplied(): boolean {\n\t\tconst state = this.state;\n\t\tif (!state) return false;\n\t\tstate.pinnedByRefusal = false;\n\t\tconst wasPinned = state.pinned;\n\t\tstate.pinned = state.pinnedByBilling;\n\t\tif (!wasPinned || state.pinned) return false;\n\t\tthis.deps.logger.info(\"refusal_pin_released\", {\n\t\t\tchainKey: state.chainKey,\n\t\t\toriginalSelector: state.originalSelector,\n\t\t\ttrigger: \"compaction\",\n\t\t});\n\t\treturn true;\n\t}\n\n\t/** A user-driven model change abandons the fallback window entirely. */\n\tclearForManualModelChange(model: Model<Api>): void {\n\t\tif (this.state) {\n\t\t\tthis.deps.logger.info(\"fallback_cleared_manual\", { selector: formatSelector(model) });\n\t\t}\n\t\tthis.state = undefined;\n\t\tthis.deps.cooldowns.clear(formatSelector(model));\n\t}\n\n\tasync tryFallback(\n\t\treason: FallbackReason,\n\t\tfailure: { errorMessage?: string; retryAfterMs?: number },\n\t): Promise<boolean> {\n\t\tconst current = this.deps.getCurrentSelector();\n\t\tconst candidate = this.nextCandidate();\n\t\tif (!current || !candidate) return false;\n\t\tconst currentBase = formatSelector(current.model);\n\t\tif (reason === \"transient\" || reason === \"hard-error\" || reason === \"billing\") {\n\t\t\tthis.deps.cooldowns.note(currentBase, failure);\n\t\t\tthis.deps.logger.info(\"cooldown_noted\", { selector: currentBase, errorMessage: failure.errorMessage });\n\t\t}\n\n\t\tconst thinking = this.selectThinking(candidate.selector, candidate.model, current.thinkingLevel);\n\t\tawait this.deps.switchModel(candidate.model, thinking, \"fallback\");\n\t\tconst from = formatSelector(current.model);\n\t\tconst to = formatSelector(candidate.model);\n\t\tconst prior = this.state;\n\t\tconst pinnedByRefusal = prior?.pinnedByRefusal === true || reason === \"refusal\";\n\t\tconst pinnedByBilling = prior?.pinnedByBilling === true || reason === \"billing\";\n\t\tthis.state = {\n\t\t\tchainKey: candidate.chainKey,\n\t\t\toriginalSelector: prior?.originalSelector ?? from,\n\t\t\toriginalThinkingLevel: prior?.originalThinkingLevel ?? current.thinkingLevel,\n\t\t\tlastAppliedThinkingLevel: thinking,\n\t\t\tpinnedByRefusal,\n\t\t\tpinnedByBilling,\n\t\t\tpinned: pinnedByRefusal || pinnedByBilling,\n\t\t};\n\t\tthis.deps.logger.info(\"fallback_applied\", { from, to, chainKey: candidate.chainKey, reason });\n\t\tthis.deps.emit({ type: \"retry_fallback_applied\", from, to, chainKey: candidate.chainKey, reason });\n\t\treturn true;\n\t}\n\n\tprivate nextCandidate(\n\t\treserve = true,\n\t): { chainKey: string; selector: FallbackSelector; model: Model<Api> } | undefined {\n\t\tconst settings = this.deps.getSettings();\n\t\tconst current = this.deps.getCurrentSelector();\n\t\tif (!settings.modelFallback || !current) return undefined;\n\t\tconst chains = this.canonicalChains();\n\t\t// Order matters: a model's own chain wins, then the active episode keeps\n\t\t// owning its walk (its last rung usually has no key of its own), and only\n\t\t// a session with neither falls back to the wildcard lane.\n\t\tconst chainKey =\n\t\t\tresolveChainKey(current.model, current.thinkingLevel, chains) ??\n\t\t\tthis.state?.chainKey ??\n\t\t\t(hasExplicitFallbackOptOut(settings.chains, current.model, current.thinkingLevel)\n\t\t\t\t? undefined\n\t\t\t\t: resolveChainKey(current.model, current.thinkingLevel, chains, { allowWildcard: true }));\n\t\tconst entries = chainKey ? chains[chainKey] : undefined;\n\t\tif (!chainKey || !entries) {\n\t\t\tif (reserve) this.deps.logger.debug(\"no_chain\", { selector: formatSelector(current.model) });\n\t\t\treturn undefined;\n\t\t}\n\t\tfor (const raw of candidatesAfter(entries, formatSelector(current.model, current.thinkingLevel))) {\n\t\t\tconst selector = parseFallbackSelector(raw, this.deps.registry);\n\t\t\tif (!selector) {\n\t\t\t\tthis.skip(raw, \"unknown\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (selector.provider === current.model.provider && selector.id === current.model.id) {\n\t\t\t\tthis.skip(raw, \"self\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst base = baseSelector(selector);\n\t\t\tif (this.triedSelectors.has(base)) {\n\t\t\t\tthis.skip(raw, \"tried\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (this.deps.cooldowns.isSuppressed(base)) {\n\t\t\t\tthis.skip(raw, \"suppressed\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!this.deps.isAuthAvailable(selector.provider)) {\n\t\t\t\tthis.skip(raw, \"unauthenticated\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst model = this.deps.registry.find(selector.provider, selector.id);\n\t\t\tif (!model) {\n\t\t\t\tthis.skip(raw, \"unknown\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (reserve) this.triedSelectors.add(base);\n\t\t\treturn { chainKey, selector, model };\n\t\t}\n\t\tthis.lastExhaustedChainKey = chainKey;\n\t\tif (reserve) this.deps.logger.info(\"candidates_exhausted\", { chainKey });\n\t\treturn undefined;\n\t}\n\n\tprivate selectThinking(\n\t\tselector: FallbackSelector,\n\t\tmodel: Model<Api>,\n\t\tinherited: ThinkingLevel | undefined,\n\t): ThinkingLevel {\n\t\tconst requested = selector.thinkingLevel ?? inherited ?? \"off\";\n\t\t// Canonical clamp walks to the NEAREST supported level. Picking the highest\n\t\t// supported level instead would escalate an \"off\" request to max reasoning on\n\t\t// always-on fallback models.\n\t\treturn clampThinkingLevel(model, requested);\n\t}\n\n\tprivate skip(candidate: string, skipReason: string): void {\n\t\tthis.deps.logger.debug(\"candidate_skipped\", { candidate, skipReason });\n\t}\n}\n"]}
@@ -3,7 +3,7 @@ import { dirname, join } from "node:path";
3
3
  const DEFAULT_MAX_BYTES = 5 * 1024 * 1024;
4
4
  const MAX_STRING_LENGTH = 200;
5
5
  const BLOCKED_KEY = /^(?:__proto__|constructor|prototype|headers?|env(?:ironment)?|authorization|credential(?:s)?|password|secret|token|api_?key|client_?secret)$/i;
6
- const ALLOWED_DATA_KEY = /^(?:selector|candidate|currentSelector|originalSelector|from|to|model|chainKey|reason|skipReason|classification|thinkingLevel|durationMs|retryAfterMs|error|errorMessage|warning)$/;
6
+ const ALLOWED_DATA_KEY = /^(?:selector|candidate|currentSelector|originalSelector|from|to|model|chainKey|reason|skipReason|classification|thinkingLevel|durationMs|retryAfterMs|error|errorMessage|warning|trigger)$/;
7
7
  const SENSITIVE_TEXT = /((?:authorization\s*[:=]\s*(?:bearer|basic)\s+)|(?:bearer\s+)|(?:[?&](?:api[_-]?key|token|secret|password|auth(?:orization)?)=))[^\s&,"'}\]]+/gi;
8
8
  export function createFallbackLogger(agentDir, options = {}) {
9
9
  const filePath = join(agentDir, "logs", "fallback.log");
@@ -1 +1 @@
1
- {"version":3,"file":"log.js","sourceRoot":"","sources":["../../../src/core/retry-fallback/log.ts"],"names":[],"mappings":"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","sourcesContent":["import { chmodSync, closeSync, mkdirSync, openSync, renameSync, rmSync, statSync, writeSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nconst DEFAULT_MAX_BYTES = 5 * 1024 * 1024;\nconst MAX_STRING_LENGTH = 200;\nconst BLOCKED_KEY =\n\t/^(?:__proto__|constructor|prototype|headers?|env(?:ironment)?|authorization|credential(?:s)?|password|secret|token|api_?key|client_?secret)$/i;\nconst ALLOWED_DATA_KEY =\n\t/^(?:selector|candidate|currentSelector|originalSelector|from|to|model|chainKey|reason|skipReason|classification|thinkingLevel|durationMs|retryAfterMs|error|errorMessage|warning)$/;\nconst SENSITIVE_TEXT =\n\t/((?:authorization\\s*[:=]\\s*(?:bearer|basic)\\s+)|(?:bearer\\s+)|(?:[?&](?:api[_-]?key|token|secret|password|auth(?:orization)?)=))[^\\s&,\"'}\\]]+/gi;\n\nexport interface FallbackLogger {\n\tdebug(event: string, data?: Record<string, unknown>): void;\n\tinfo(event: string, data?: Record<string, unknown>): void;\n\twarn(event: string, data?: Record<string, unknown>): void;\n}\n\nexport interface FallbackLoggerOptions {\n\tmaxBytes?: number;\n}\n\nexport function createFallbackLogger(agentDir: string, options: FallbackLoggerOptions = {}): FallbackLogger {\n\tconst filePath = join(agentDir, \"logs\", \"fallback.log\");\n\tconst maxBytes = validMaxBytes(options.maxBytes);\n\tlet reportedWriteFailure = false;\n\n\tfunction log(level: \"debug\" | \"info\" | \"warn\", event: string, data?: Record<string, unknown>): void {\n\t\ttry {\n\t\t\tconst line = formatLine(level, event, data);\n\t\t\twriteLine(filePath, line, maxBytes);\n\t\t} catch (error) {\n\t\t\tif (!reportedWriteFailure) {\n\t\t\t\treportedWriteFailure = true;\n\t\t\t\tconsole.error(\"Unable to write retry fallback debug log\", error);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tdebug: (event, data) => log(\"debug\", event, data),\n\t\tinfo: (event, data) => log(\"info\", event, data),\n\t\twarn: (event, data) => log(\"warn\", event, data),\n\t};\n}\n\nfunction validMaxBytes(value: number | undefined): number {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value > 0 ? Math.floor(value) : DEFAULT_MAX_BYTES;\n}\n\nfunction formatLine(\n\tlevel: \"debug\" | \"info\" | \"warn\",\n\tevent: string,\n\tdata: Record<string, unknown> | undefined,\n): string {\n\tconst entry: Record<string, unknown> = {\n\t\tts: new Date().toISOString(),\n\t\tlevel,\n\t\tevent: safeText(event),\n\t};\n\tif (data !== undefined) {\n\t\tfor (const [key, value] of safeEntries(data)) {\n\t\t\tif (ALLOWED_DATA_KEY.test(key) && !BLOCKED_KEY.test(key)) {\n\t\t\t\tconst safeValue = serializeValue(value, new WeakSet<object>());\n\t\t\t\tif (safeValue !== undefined) entry[key] = safeValue;\n\t\t\t}\n\t\t}\n\t}\n\treturn JSON.stringify(entry);\n}\n\nfunction writeLine(filePath: string, line: string, maxBytes: number): void {\n\tmkdirSync(dirname(filePath), { recursive: true, mode: 0o700 });\n\tconst text = `${line}\\n`;\n\tif (fileExceedsCap(filePath, Buffer.byteLength(text), maxBytes)) {\n\t\trmSync(`${filePath}.1`, { force: true });\n\t\trenameSync(filePath, `${filePath}.1`);\n\t\tchmodSync(`${filePath}.1`, 0o600);\n\t}\n\tconst descriptor = openSync(filePath, \"a\", 0o600);\n\ttry {\n\t\twriteSync(descriptor, text);\n\t} finally {\n\t\tcloseSync(descriptor);\n\t}\n\tchmodSync(filePath, 0o600);\n}\n\nfunction fileExceedsCap(filePath: string, incomingBytes: number, maxBytes: number): boolean {\n\ttry {\n\t\treturn statSync(filePath).size + incomingBytes > maxBytes;\n\t} catch (error) {\n\t\tif (isMissingFileError(error)) return false;\n\t\tthrow error;\n\t}\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n\nfunction serializeValue(value: unknown, seen: WeakSet<object>): unknown {\n\tif (typeof value === \"string\") return safeText(value);\n\tif (typeof value === \"bigint\") return value.toString();\n\tif (typeof value === \"number\" || typeof value === \"boolean\" || value === null) return value;\n\tif (typeof value === \"undefined\") return undefined;\n\tif (typeof value === \"function\" || typeof value === \"symbol\") return String(value);\n\tif (seen.has(value)) return \"[Circular]\";\n\tseen.add(value);\n\tif (Array.isArray(value)) return value.map((item) => serializeValue(item, seen) ?? null);\n\tconst result: Record<string, unknown> = {};\n\tfor (const [key, item] of safeEntries(value)) {\n\t\tif (!BLOCKED_KEY.test(key)) {\n\t\t\tconst safeValue = serializeValue(item, seen);\n\t\t\tif (safeValue !== undefined) result[key] = safeValue;\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction safeEntries(value: object): Array<[string, unknown]> {\n\ttry {\n\t\tconst entries: Array<[string, unknown]> = [];\n\t\tfor (const key of Object.keys(value)) {\n\t\t\ttry {\n\t\t\t\tconst item: unknown = Reflect.get(value, key);\n\t\t\t\tentries.push([key, item]);\n\t\t\t} catch {\n\t\t\t\tentries.push([key, \"[Unreadable]\"]);\n\t\t\t}\n\t\t}\n\t\treturn entries;\n\t} catch {\n\t\treturn [[\"unserializable\", \"[Unreadable]\"]];\n\t}\n}\n\nfunction safeText(value: string): string {\n\tconst redacted = value.replace(SENSITIVE_TEXT, \"$1[redacted]\");\n\treturn redacted.length <= MAX_STRING_LENGTH ? redacted : `${redacted.slice(0, MAX_STRING_LENGTH - 3)}...`;\n}\n"]}
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../../src/core/retry-fallback/log.ts"],"names":[],"mappings":"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","sourcesContent":["import { chmodSync, closeSync, mkdirSync, openSync, renameSync, rmSync, statSync, writeSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nconst DEFAULT_MAX_BYTES = 5 * 1024 * 1024;\nconst MAX_STRING_LENGTH = 200;\nconst BLOCKED_KEY =\n\t/^(?:__proto__|constructor|prototype|headers?|env(?:ironment)?|authorization|credential(?:s)?|password|secret|token|api_?key|client_?secret)$/i;\nconst ALLOWED_DATA_KEY =\n\t/^(?:selector|candidate|currentSelector|originalSelector|from|to|model|chainKey|reason|skipReason|classification|thinkingLevel|durationMs|retryAfterMs|error|errorMessage|warning|trigger)$/;\nconst SENSITIVE_TEXT =\n\t/((?:authorization\\s*[:=]\\s*(?:bearer|basic)\\s+)|(?:bearer\\s+)|(?:[?&](?:api[_-]?key|token|secret|password|auth(?:orization)?)=))[^\\s&,\"'}\\]]+/gi;\n\nexport interface FallbackLogger {\n\tdebug(event: string, data?: Record<string, unknown>): void;\n\tinfo(event: string, data?: Record<string, unknown>): void;\n\twarn(event: string, data?: Record<string, unknown>): void;\n}\n\nexport interface FallbackLoggerOptions {\n\tmaxBytes?: number;\n}\n\nexport function createFallbackLogger(agentDir: string, options: FallbackLoggerOptions = {}): FallbackLogger {\n\tconst filePath = join(agentDir, \"logs\", \"fallback.log\");\n\tconst maxBytes = validMaxBytes(options.maxBytes);\n\tlet reportedWriteFailure = false;\n\n\tfunction log(level: \"debug\" | \"info\" | \"warn\", event: string, data?: Record<string, unknown>): void {\n\t\ttry {\n\t\t\tconst line = formatLine(level, event, data);\n\t\t\twriteLine(filePath, line, maxBytes);\n\t\t} catch (error) {\n\t\t\tif (!reportedWriteFailure) {\n\t\t\t\treportedWriteFailure = true;\n\t\t\t\tconsole.error(\"Unable to write retry fallback debug log\", error);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tdebug: (event, data) => log(\"debug\", event, data),\n\t\tinfo: (event, data) => log(\"info\", event, data),\n\t\twarn: (event, data) => log(\"warn\", event, data),\n\t};\n}\n\nfunction validMaxBytes(value: number | undefined): number {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value > 0 ? Math.floor(value) : DEFAULT_MAX_BYTES;\n}\n\nfunction formatLine(\n\tlevel: \"debug\" | \"info\" | \"warn\",\n\tevent: string,\n\tdata: Record<string, unknown> | undefined,\n): string {\n\tconst entry: Record<string, unknown> = {\n\t\tts: new Date().toISOString(),\n\t\tlevel,\n\t\tevent: safeText(event),\n\t};\n\tif (data !== undefined) {\n\t\tfor (const [key, value] of safeEntries(data)) {\n\t\t\tif (ALLOWED_DATA_KEY.test(key) && !BLOCKED_KEY.test(key)) {\n\t\t\t\tconst safeValue = serializeValue(value, new WeakSet<object>());\n\t\t\t\tif (safeValue !== undefined) entry[key] = safeValue;\n\t\t\t}\n\t\t}\n\t}\n\treturn JSON.stringify(entry);\n}\n\nfunction writeLine(filePath: string, line: string, maxBytes: number): void {\n\tmkdirSync(dirname(filePath), { recursive: true, mode: 0o700 });\n\tconst text = `${line}\\n`;\n\tif (fileExceedsCap(filePath, Buffer.byteLength(text), maxBytes)) {\n\t\trmSync(`${filePath}.1`, { force: true });\n\t\trenameSync(filePath, `${filePath}.1`);\n\t\tchmodSync(`${filePath}.1`, 0o600);\n\t}\n\tconst descriptor = openSync(filePath, \"a\", 0o600);\n\ttry {\n\t\twriteSync(descriptor, text);\n\t} finally {\n\t\tcloseSync(descriptor);\n\t}\n\tchmodSync(filePath, 0o600);\n}\n\nfunction fileExceedsCap(filePath: string, incomingBytes: number, maxBytes: number): boolean {\n\ttry {\n\t\treturn statSync(filePath).size + incomingBytes > maxBytes;\n\t} catch (error) {\n\t\tif (isMissingFileError(error)) return false;\n\t\tthrow error;\n\t}\n}\n\nfunction isMissingFileError(error: unknown): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n\nfunction serializeValue(value: unknown, seen: WeakSet<object>): unknown {\n\tif (typeof value === \"string\") return safeText(value);\n\tif (typeof value === \"bigint\") return value.toString();\n\tif (typeof value === \"number\" || typeof value === \"boolean\" || value === null) return value;\n\tif (typeof value === \"undefined\") return undefined;\n\tif (typeof value === \"function\" || typeof value === \"symbol\") return String(value);\n\tif (seen.has(value)) return \"[Circular]\";\n\tseen.add(value);\n\tif (Array.isArray(value)) return value.map((item) => serializeValue(item, seen) ?? null);\n\tconst result: Record<string, unknown> = {};\n\tfor (const [key, item] of safeEntries(value)) {\n\t\tif (!BLOCKED_KEY.test(key)) {\n\t\t\tconst safeValue = serializeValue(item, seen);\n\t\t\tif (safeValue !== undefined) result[key] = safeValue;\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction safeEntries(value: object): Array<[string, unknown]> {\n\ttry {\n\t\tconst entries: Array<[string, unknown]> = [];\n\t\tfor (const key of Object.keys(value)) {\n\t\t\ttry {\n\t\t\t\tconst item: unknown = Reflect.get(value, key);\n\t\t\t\tentries.push([key, item]);\n\t\t\t} catch {\n\t\t\t\tentries.push([key, \"[Unreadable]\"]);\n\t\t\t}\n\t\t}\n\t\treturn entries;\n\t} catch {\n\t\treturn [[\"unserializable\", \"[Unreadable]\"]];\n\t}\n}\n\nfunction safeText(value: string): string {\n\tconst redacted = value.replace(SENSITIVE_TEXT, \"$1[redacted]\");\n\treturn redacted.length <= MAX_STRING_LENGTH ? redacted : `${redacted.slice(0, MAX_STRING_LENGTH - 3)}...`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/core/retry-fallback/settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,qBAAqB;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,uBAAuB,EAAE,mBAAmB,CAAC,CAAC;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1C,oBAAoB,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC;IACnD,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,6BAA6B;IAC7C,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,YAAY,EAAE,iBAAiB,GAAG,OAAO,CAAC;CAC1C;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,cAcrC,CAAC;AA6CF,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,aAAa,GAAG,SAAS,GAAG,6BAA6B,CAM/G;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAE3F;AAED,eAAO,MAAM,0BAA0B,SAAU,CAAC;AAClD,eAAO,MAAM,yBAAyB,UAAY,CAAC;AAEnD,MAAM,WAAW,0BAA0B;IAC1C,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,aAAa,GAAG,SAAS,GAAG,0BAA0B,CAezG"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/core/retry-fallback/settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,qBAAqB;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,uBAAuB,EAAE,mBAAmB,CAAC,CAAC;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1C,oBAAoB,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC;IACnD,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,6BAA6B;IAC7C,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,YAAY,EAAE,iBAAiB,GAAG,OAAO,CAAC;CAC1C;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,cAerC,CAAC;AA6CF,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,aAAa,GAAG,SAAS,GAAG,6BAA6B,CAM/G;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAE3F;AAED,eAAO,MAAM,0BAA0B,SAAU,CAAC;AAClD,eAAO,MAAM,yBAAyB,UAAY,CAAC;AAEnD,MAAM,WAAW,0BAA0B;IAC1C,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,aAAa,GAAG,SAAS,GAAG,0BAA0B,CAezG"}
@@ -8,6 +8,7 @@ export const DEFAULT_FALLBACK_CHAINS = {
8
8
  // `kimi-k3:max` is an alias entry for providers that expose Kimi K3 under the
9
9
  // vendor-prefixed id `kimi-k3` (e.g. OpenCode Go), which the conservative `k3`
10
10
  // family matcher intentionally cannot capture (issue #793).
11
+ "claude-fable-5-1": ["k3:max", "kimi-k3:max", "claude-opus-5:xhigh", "claude-opus-4-8:xhigh"],
11
12
  "claude-fable-5": ["k3:max", "kimi-k3:max", "claude-opus-5:xhigh", "claude-opus-4-8:xhigh"],
12
13
  // Last-resort lane for models with no chain of their own. resolveChainKey
13
14
  // falls through exact -> base -> "*", so any current model whose upstream