@homeflare/alchemy 0.43.0 → 0.45.0

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 (612) hide show
  1. package/README.md +10 -1
  2. package/dist/caddy/index.js +35 -1
  3. package/dist/caddy/index.js.map +3 -3
  4. package/dist/launchd/index.js +35 -1
  5. package/dist/launchd/index.js.map +3 -3
  6. package/dist/linux/index.js +35 -1
  7. package/dist/linux/index.js.map +3 -3
  8. package/dist/litellm/access-group-form.d.ts +26 -0
  9. package/dist/litellm/access-group-form.d.ts.map +1 -0
  10. package/dist/litellm/access-group-operations.d.ts +37 -0
  11. package/dist/litellm/access-group-operations.d.ts.map +1 -0
  12. package/dist/litellm/access-group-types.d.ts +49 -0
  13. package/dist/litellm/access-group-types.d.ts.map +1 -0
  14. package/dist/litellm/access-group.d.ts +55 -0
  15. package/dist/litellm/access-group.d.ts.map +1 -0
  16. package/dist/litellm/credential-errors.d.ts +131 -0
  17. package/dist/litellm/credential-errors.d.ts.map +1 -0
  18. package/dist/litellm/credential-form.d.ts +79 -0
  19. package/dist/litellm/credential-form.d.ts.map +1 -0
  20. package/dist/litellm/credential-operations.d.ts +84 -0
  21. package/dist/litellm/credential-operations.d.ts.map +1 -0
  22. package/dist/litellm/credential-rewrite.d.ts +6 -0
  23. package/dist/litellm/credential-rewrite.d.ts.map +1 -0
  24. package/dist/litellm/credential-types.d.ts +87 -0
  25. package/dist/litellm/credential-types.d.ts.map +1 -0
  26. package/dist/litellm/credential-values.d.ts +53 -0
  27. package/dist/litellm/credential-values.d.ts.map +1 -0
  28. package/dist/litellm/credential.d.ts +83 -0
  29. package/dist/litellm/credential.d.ts.map +1 -0
  30. package/dist/litellm/fake-access-group-litellm.d.ts +34 -0
  31. package/dist/litellm/fake-access-group-litellm.d.ts.map +1 -0
  32. package/dist/litellm/fake-credential-litellm.d.ts +54 -0
  33. package/dist/litellm/fake-credential-litellm.d.ts.map +1 -0
  34. package/dist/litellm/fake-keys.d.ts +53 -0
  35. package/dist/litellm/fake-keys.d.ts.map +1 -0
  36. package/dist/litellm/fake-litellm.d.ts +4 -1
  37. package/dist/litellm/fake-litellm.d.ts.map +1 -1
  38. package/dist/litellm/fake-mcp-litellm.d.ts +67 -0
  39. package/dist/litellm/fake-mcp-litellm.d.ts.map +1 -0
  40. package/dist/litellm/fake-model-litellm-post-update.d.ts +49 -0
  41. package/dist/litellm/fake-model-litellm-post-update.d.ts.map +1 -0
  42. package/dist/litellm/fake-model-litellm.d.ts +48 -0
  43. package/dist/litellm/fake-model-litellm.d.ts.map +1 -0
  44. package/dist/litellm/fake-policy-attachment-litellm.d.ts +33 -0
  45. package/dist/litellm/fake-policy-attachment-litellm.d.ts.map +1 -0
  46. package/dist/litellm/fake-policy-litellm.d.ts +32 -0
  47. package/dist/litellm/fake-policy-litellm.d.ts.map +1 -0
  48. package/dist/litellm/fake-registry-base.d.ts +42 -0
  49. package/dist/litellm/fake-registry-base.d.ts.map +1 -0
  50. package/dist/litellm/fake-stack.d.ts +8 -1
  51. package/dist/litellm/fake-stack.d.ts.map +1 -1
  52. package/dist/litellm/fake-team-litellm.d.ts +47 -0
  53. package/dist/litellm/fake-team-litellm.d.ts.map +1 -0
  54. package/dist/litellm/fake-tool-litellm.d.ts +28 -0
  55. package/dist/litellm/fake-tool-litellm.d.ts.map +1 -0
  56. package/dist/litellm/fake-toolset-litellm.d.ts +29 -0
  57. package/dist/litellm/fake-toolset-litellm.d.ts.map +1 -0
  58. package/dist/litellm/index.d.ts +18 -0
  59. package/dist/litellm/index.d.ts.map +1 -1
  60. package/dist/litellm/index.js +3078 -2
  61. package/dist/litellm/index.js.map +65 -4
  62. package/dist/litellm/key-errors.d.ts +169 -0
  63. package/dist/litellm/key-errors.d.ts.map +1 -0
  64. package/dist/litellm/key-form.d.ts +119 -0
  65. package/dist/litellm/key-form.d.ts.map +1 -0
  66. package/dist/litellm/key-harness.d.ts +41 -0
  67. package/dist/litellm/key-harness.d.ts.map +1 -0
  68. package/dist/litellm/key-metadata-errors.d.ts +30 -0
  69. package/dist/litellm/key-metadata-errors.d.ts.map +1 -0
  70. package/dist/litellm/key-metadata.d.ts +22 -0
  71. package/dist/litellm/key-metadata.d.ts.map +1 -0
  72. package/dist/litellm/key-operations.d.ts +63 -0
  73. package/dist/litellm/key-operations.d.ts.map +1 -0
  74. package/dist/litellm/key-secret.d.ts +33 -0
  75. package/dist/litellm/key-secret.d.ts.map +1 -0
  76. package/dist/litellm/key.d.ts +78 -0
  77. package/dist/litellm/key.d.ts.map +1 -0
  78. package/dist/litellm/mcp-server-credential.d.ts +50 -0
  79. package/dist/litellm/mcp-server-credential.d.ts.map +1 -0
  80. package/dist/litellm/mcp-server-errors.d.ts +101 -0
  81. package/dist/litellm/mcp-server-errors.d.ts.map +1 -0
  82. package/dist/litellm/mcp-server-form.d.ts +56 -0
  83. package/dist/litellm/mcp-server-form.d.ts.map +1 -0
  84. package/dist/litellm/mcp-server-locate.d.ts +26 -0
  85. package/dist/litellm/mcp-server-locate.d.ts.map +1 -0
  86. package/dist/litellm/mcp-server-operations.d.ts +63 -0
  87. package/dist/litellm/mcp-server-operations.d.ts.map +1 -0
  88. package/dist/litellm/mcp-server-shadow.d.ts +24 -0
  89. package/dist/litellm/mcp-server-shadow.d.ts.map +1 -0
  90. package/dist/litellm/mcp-server-types.d.ts +118 -0
  91. package/dist/litellm/mcp-server-types.d.ts.map +1 -0
  92. package/dist/litellm/mcp-server-url.d.ts +11 -0
  93. package/dist/litellm/mcp-server-url.d.ts.map +1 -0
  94. package/dist/litellm/mcp-server.d.ts +95 -0
  95. package/dist/litellm/mcp-server.d.ts.map +1 -0
  96. package/dist/litellm/model-claim.d.ts +24 -0
  97. package/dist/litellm/model-claim.d.ts.map +1 -0
  98. package/dist/litellm/model-credential.d.ts +12 -0
  99. package/dist/litellm/model-credential.d.ts.map +1 -0
  100. package/dist/litellm/model-errors.d.ts +119 -0
  101. package/dist/litellm/model-errors.d.ts.map +1 -0
  102. package/dist/litellm/model-form.d.ts +78 -0
  103. package/dist/litellm/model-form.d.ts.map +1 -0
  104. package/dist/litellm/model-locate.d.ts +13 -0
  105. package/dist/litellm/model-locate.d.ts.map +1 -0
  106. package/dist/litellm/model-operations.d.ts +59 -0
  107. package/dist/litellm/model-operations.d.ts.map +1 -0
  108. package/dist/litellm/model-types.d.ts +91 -0
  109. package/dist/litellm/model-types.d.ts.map +1 -0
  110. package/dist/litellm/model.d.ts +88 -0
  111. package/dist/litellm/model.d.ts.map +1 -0
  112. package/dist/litellm/policy-attachment-form.d.ts +19 -0
  113. package/dist/litellm/policy-attachment-form.d.ts.map +1 -0
  114. package/dist/litellm/policy-attachment-operations.d.ts +31 -0
  115. package/dist/litellm/policy-attachment-operations.d.ts.map +1 -0
  116. package/dist/litellm/policy-attachment-types.d.ts +48 -0
  117. package/dist/litellm/policy-attachment-types.d.ts.map +1 -0
  118. package/dist/litellm/policy-attachment.d.ts +61 -0
  119. package/dist/litellm/policy-attachment.d.ts.map +1 -0
  120. package/dist/litellm/policy-form.d.ts +22 -0
  121. package/dist/litellm/policy-form.d.ts.map +1 -0
  122. package/dist/litellm/policy-operations.d.ts +42 -0
  123. package/dist/litellm/policy-operations.d.ts.map +1 -0
  124. package/dist/litellm/policy-types.d.ts +57 -0
  125. package/dist/litellm/policy-types.d.ts.map +1 -0
  126. package/dist/litellm/policy.d.ts +65 -0
  127. package/dist/litellm/policy.d.ts.map +1 -0
  128. package/dist/litellm/providers.d.ts +1 -1
  129. package/dist/litellm/providers.d.ts.map +1 -1
  130. package/dist/litellm/registry-errors.d.ts +62 -0
  131. package/dist/litellm/registry-errors.d.ts.map +1 -0
  132. package/dist/litellm/registry-support.d.ts +42 -0
  133. package/dist/litellm/registry-support.d.ts.map +1 -0
  134. package/dist/litellm/team-form.d.ts +26 -0
  135. package/dist/litellm/team-form.d.ts.map +1 -0
  136. package/dist/litellm/team-members.d.ts +10 -0
  137. package/dist/litellm/team-members.d.ts.map +1 -0
  138. package/dist/litellm/team-operations.d.ts +38 -0
  139. package/dist/litellm/team-operations.d.ts.map +1 -0
  140. package/dist/litellm/team-permission.d.ts +35 -0
  141. package/dist/litellm/team-permission.d.ts.map +1 -0
  142. package/dist/litellm/team-types.d.ts +101 -0
  143. package/dist/litellm/team-types.d.ts.map +1 -0
  144. package/dist/litellm/team.d.ts +67 -0
  145. package/dist/litellm/team.d.ts.map +1 -0
  146. package/dist/litellm/tool-policy-form.d.ts +21 -0
  147. package/dist/litellm/tool-policy-form.d.ts.map +1 -0
  148. package/dist/litellm/tool-policy-operations.d.ts +30 -0
  149. package/dist/litellm/tool-policy-operations.d.ts.map +1 -0
  150. package/dist/litellm/tool-policy-types.d.ts +46 -0
  151. package/dist/litellm/tool-policy-types.d.ts.map +1 -0
  152. package/dist/litellm/tool-policy.d.ts +62 -0
  153. package/dist/litellm/tool-policy.d.ts.map +1 -0
  154. package/dist/litellm/toolset-form.d.ts +20 -0
  155. package/dist/litellm/toolset-form.d.ts.map +1 -0
  156. package/dist/litellm/toolset-operations.d.ts +39 -0
  157. package/dist/litellm/toolset-operations.d.ts.map +1 -0
  158. package/dist/litellm/toolset-types.d.ts +46 -0
  159. package/dist/litellm/toolset-types.d.ts.map +1 -0
  160. package/dist/litellm/toolset.d.ts +55 -0
  161. package/dist/litellm/toolset.d.ts.map +1 -0
  162. package/dist/openbao/index.js +35 -1
  163. package/dist/openbao/index.js.map +3 -3
  164. package/dist/ownership/rows.d.ts +11 -0
  165. package/dist/ownership/rows.d.ts.map +1 -1
  166. package/dist/postgres/connection.d.ts +14 -2
  167. package/dist/postgres/connection.d.ts.map +1 -1
  168. package/dist/postgres/database-sql.d.ts +27 -8
  169. package/dist/postgres/database-sql.d.ts.map +1 -1
  170. package/dist/postgres/fake-grants-parse.d.ts +37 -0
  171. package/dist/postgres/fake-grants-parse.d.ts.map +1 -0
  172. package/dist/postgres/fake-grants-read.d.ts +61 -0
  173. package/dist/postgres/fake-grants-read.d.ts.map +1 -0
  174. package/dist/postgres/fake-grants-sql.d.ts +46 -0
  175. package/dist/postgres/fake-grants-sql.d.ts.map +1 -0
  176. package/dist/postgres/fake-grants-write.d.ts +29 -0
  177. package/dist/postgres/fake-grants-write.d.ts.map +1 -0
  178. package/dist/postgres/fake-role-sql.d.ts +41 -0
  179. package/dist/postgres/fake-role-sql.d.ts.map +1 -0
  180. package/dist/postgres/fake-schema-sql.d.ts +42 -0
  181. package/dist/postgres/fake-schema-sql.d.ts.map +1 -0
  182. package/dist/postgres/fake-sql-parse.d.ts +23 -0
  183. package/dist/postgres/fake-sql-parse.d.ts.map +1 -0
  184. package/dist/postgres/fake-sql-quote.d.ts +12 -0
  185. package/dist/postgres/fake-sql-quote.d.ts.map +1 -0
  186. package/dist/postgres/fake-sql.d.ts +42 -0
  187. package/dist/postgres/fake-sql.d.ts.map +1 -1
  188. package/dist/postgres/grants-attrs.d.ts +115 -0
  189. package/dist/postgres/grants-attrs.d.ts.map +1 -0
  190. package/dist/postgres/grants-declare.d.ts +88 -0
  191. package/dist/postgres/grants-declare.d.ts.map +1 -0
  192. package/dist/postgres/grants-diff.d.ts +25 -0
  193. package/dist/postgres/grants-diff.d.ts.map +1 -0
  194. package/dist/postgres/grants-errors.d.ts +137 -0
  195. package/dist/postgres/grants-errors.d.ts.map +1 -0
  196. package/dist/postgres/grants-existence.d.ts +14 -0
  197. package/dist/postgres/grants-existence.d.ts.map +1 -0
  198. package/dist/postgres/grants-ops.d.ts +65 -0
  199. package/dist/postgres/grants-ops.d.ts.map +1 -0
  200. package/dist/postgres/grants-ownership.d.ts +18 -0
  201. package/dist/postgres/grants-ownership.d.ts.map +1 -0
  202. package/dist/postgres/grants-plan-restore.d.ts +22 -0
  203. package/dist/postgres/grants-plan-restore.d.ts.map +1 -0
  204. package/dist/postgres/grants-plan.d.ts +65 -0
  205. package/dist/postgres/grants-plan.d.ts.map +1 -0
  206. package/dist/postgres/grants-read-defaults.d.ts +17 -0
  207. package/dist/postgres/grants-read-defaults.d.ts.map +1 -0
  208. package/dist/postgres/grants-read.d.ts +77 -0
  209. package/dist/postgres/grants-read.d.ts.map +1 -0
  210. package/dist/postgres/grants-refuse.d.ts +25 -0
  211. package/dist/postgres/grants-refuse.d.ts.map +1 -0
  212. package/dist/postgres/grants-sql.d.ts +42 -0
  213. package/dist/postgres/grants-sql.d.ts.map +1 -0
  214. package/dist/postgres/grants-words.d.ts +29 -0
  215. package/dist/postgres/grants-words.d.ts.map +1 -0
  216. package/dist/postgres/grants.d.ts +37 -0
  217. package/dist/postgres/grants.d.ts.map +1 -0
  218. package/dist/postgres/index.d.ts +31 -6
  219. package/dist/postgres/index.d.ts.map +1 -1
  220. package/dist/postgres/index.js +1998 -37
  221. package/dist/postgres/index.js.map +46 -7
  222. package/dist/postgres/installed-classifier.d.ts +13 -0
  223. package/dist/postgres/installed-classifier.d.ts.map +1 -0
  224. package/dist/postgres/providers.d.ts +16 -8
  225. package/dist/postgres/providers.d.ts.map +1 -1
  226. package/dist/postgres/psql-executor.d.ts +4 -0
  227. package/dist/postgres/psql-executor.d.ts.map +1 -1
  228. package/dist/postgres/role-attrs.d.ts +112 -0
  229. package/dist/postgres/role-attrs.d.ts.map +1 -0
  230. package/dist/postgres/role-diff.d.ts +22 -0
  231. package/dist/postgres/role-diff.d.ts.map +1 -0
  232. package/dist/postgres/role-errors.d.ts +132 -0
  233. package/dist/postgres/role-errors.d.ts.map +1 -0
  234. package/dist/postgres/role-membership-sql.d.ts +78 -0
  235. package/dist/postgres/role-membership-sql.d.ts.map +1 -0
  236. package/dist/postgres/role-provider.d.ts +11 -0
  237. package/dist/postgres/role-provider.d.ts.map +1 -0
  238. package/dist/postgres/role-scram.d.ts +8 -0
  239. package/dist/postgres/role-scram.d.ts.map +1 -0
  240. package/dist/postgres/role-secrets.d.ts +38 -0
  241. package/dist/postgres/role-secrets.d.ts.map +1 -0
  242. package/dist/postgres/role-sql.d.ts +68 -0
  243. package/dist/postgres/role-sql.d.ts.map +1 -0
  244. package/dist/postgres/role.d.ts +57 -0
  245. package/dist/postgres/role.d.ts.map +1 -0
  246. package/dist/postgres/schema-assert.d.ts +50 -0
  247. package/dist/postgres/schema-assert.d.ts.map +1 -0
  248. package/dist/postgres/schema-attrs.d.ts +51 -0
  249. package/dist/postgres/schema-attrs.d.ts.map +1 -0
  250. package/dist/postgres/schema-delete.d.ts +28 -0
  251. package/dist/postgres/schema-delete.d.ts.map +1 -0
  252. package/dist/postgres/schema-diff.d.ts +14 -0
  253. package/dist/postgres/schema-diff.d.ts.map +1 -0
  254. package/dist/postgres/schema-errors.d.ts +139 -0
  255. package/dist/postgres/schema-errors.d.ts.map +1 -0
  256. package/dist/postgres/schema-identity.d.ts +8 -0
  257. package/dist/postgres/schema-identity.d.ts.map +1 -0
  258. package/dist/postgres/schema-reconcile.d.ts +12 -0
  259. package/dist/postgres/schema-reconcile.d.ts.map +1 -0
  260. package/dist/postgres/schema-sql.d.ts +45 -0
  261. package/dist/postgres/schema-sql.d.ts.map +1 -0
  262. package/dist/postgres/schema-test-kit.d.ts +67 -0
  263. package/dist/postgres/schema-test-kit.d.ts.map +1 -0
  264. package/dist/postgres/schema.d.ts +54 -0
  265. package/dist/postgres/schema.d.ts.map +1 -0
  266. package/dist/proxmox/index.js +35 -1
  267. package/dist/proxmox/index.js.map +3 -3
  268. package/dist/release/fake-engine.d.ts +10 -0
  269. package/dist/release/fake-engine.d.ts.map +1 -1
  270. package/dist/release/index.js +35 -1
  271. package/dist/release/index.js.map +3 -3
  272. package/dist/valkey/acl-attrs.d.ts +94 -0
  273. package/dist/valkey/acl-attrs.d.ts.map +1 -0
  274. package/dist/valkey/acl-compare.d.ts +28 -0
  275. package/dist/valkey/acl-compare.d.ts.map +1 -0
  276. package/dist/valkey/acl-connection.d.ts +6 -0
  277. package/dist/valkey/acl-connection.d.ts.map +1 -0
  278. package/dist/valkey/acl-form.d.ts +62 -0
  279. package/dist/valkey/acl-form.d.ts.map +1 -0
  280. package/dist/valkey/acl-managed.d.ts +4 -0
  281. package/dist/valkey/acl-managed.d.ts.map +1 -0
  282. package/dist/valkey/acl-ops.d.ts +37 -0
  283. package/dist/valkey/acl-ops.d.ts.map +1 -0
  284. package/dist/valkey/acl-profiles.d.ts +53 -0
  285. package/dist/valkey/acl-profiles.d.ts.map +1 -0
  286. package/dist/valkey/acl-reconcile.d.ts +26 -0
  287. package/dist/valkey/acl-reconcile.d.ts.map +1 -0
  288. package/dist/valkey/acl.d.ts +24 -0
  289. package/dist/valkey/acl.d.ts.map +1 -0
  290. package/dist/valkey/connection-service.d.ts +22 -0
  291. package/dist/valkey/connection-service.d.ts.map +1 -0
  292. package/dist/valkey/connection.d.ts +59 -0
  293. package/dist/valkey/connection.d.ts.map +1 -0
  294. package/dist/valkey/errors.d.ts +165 -0
  295. package/dist/valkey/errors.d.ts.map +1 -0
  296. package/dist/valkey/fake-acl.d.ts +29 -0
  297. package/dist/valkey/fake-acl.d.ts.map +1 -0
  298. package/dist/valkey/fake-valkey.d.ts +35 -0
  299. package/dist/valkey/fake-valkey.d.ts.map +1 -0
  300. package/dist/valkey/handler-test-fixture.d.ts +20 -0
  301. package/dist/valkey/handler-test-fixture.d.ts.map +1 -0
  302. package/dist/valkey/index.d.ts +18 -0
  303. package/dist/valkey/index.d.ts.map +1 -0
  304. package/dist/valkey/index.js +964 -0
  305. package/dist/valkey/index.js.map +27 -0
  306. package/dist/valkey/instance-attrs.d.ts +46 -0
  307. package/dist/valkey/instance-attrs.d.ts.map +1 -0
  308. package/dist/valkey/instance-form.d.ts +22 -0
  309. package/dist/valkey/instance-form.d.ts.map +1 -0
  310. package/dist/valkey/instance.d.ts +48 -0
  311. package/dist/valkey/instance.d.ts.map +1 -0
  312. package/dist/valkey/provider-socket-fixture.d.ts +8 -0
  313. package/dist/valkey/provider-socket-fixture.d.ts.map +1 -0
  314. package/dist/valkey/providers.d.ts +16 -0
  315. package/dist/valkey/providers.d.ts.map +1 -0
  316. package/dist/valkey/resp.d.ts +38 -0
  317. package/dist/valkey/resp.d.ts.map +1 -0
  318. package/dist/valkey/transport-error.d.ts +36 -0
  319. package/dist/valkey/transport-error.d.ts.map +1 -0
  320. package/dist/valkey/transport.d.ts +50 -0
  321. package/dist/valkey/transport.d.ts.map +1 -0
  322. package/docs/litellm-access-group.md +105 -0
  323. package/docs/litellm-credential.md +60 -0
  324. package/docs/litellm-key-metadata.md +56 -0
  325. package/docs/litellm-key.md +194 -0
  326. package/docs/litellm-mcp.md +187 -0
  327. package/docs/litellm-model.md +111 -0
  328. package/docs/litellm-policy-attachment.md +86 -0
  329. package/docs/litellm-policy.md +103 -0
  330. package/docs/litellm-team.md +117 -0
  331. package/docs/litellm-tool-policy.md +90 -0
  332. package/docs/litellm-toolset.md +92 -0
  333. package/docs/litellm.md +16 -9
  334. package/docs/peers.md +15 -6
  335. package/docs/postgres-grants-example.md +55 -0
  336. package/docs/postgres-grants.md +157 -0
  337. package/docs/postgres-role.md +126 -0
  338. package/docs/postgres-schema.md +139 -0
  339. package/docs/postgres.md +20 -3
  340. package/docs/valkey-transport.md +29 -0
  341. package/docs/valkey.md +187 -0
  342. package/package.json +6 -2
  343. package/src/ceph/ceph-argv.test.ts +1 -1
  344. package/src/launchd/sudo-allowlist.test.ts +2 -2
  345. package/src/linux/sudo-allowlist.test.ts +3 -3
  346. package/src/linux/sudo-runner.test.ts +2 -2
  347. package/src/litellm/access-group-form.ts +105 -0
  348. package/src/litellm/access-group-operations.ts +92 -0
  349. package/src/litellm/access-group-types.ts +49 -0
  350. package/src/litellm/access-group.test.ts +197 -0
  351. package/src/litellm/access-group.ts +151 -0
  352. package/src/litellm/credential-errors.ts +183 -0
  353. package/src/litellm/credential-form.test.ts +151 -0
  354. package/src/litellm/credential-form.ts +211 -0
  355. package/src/litellm/credential-guards.test.ts +241 -0
  356. package/src/litellm/credential-operations.ts +208 -0
  357. package/src/litellm/credential-recovery.test.ts +93 -0
  358. package/src/litellm/credential-rewrite.test.ts +164 -0
  359. package/src/litellm/credential-rewrite.ts +50 -0
  360. package/src/litellm/credential-types.ts +117 -0
  361. package/src/litellm/credential-values.ts +94 -0
  362. package/src/litellm/credential.test.ts +218 -0
  363. package/src/litellm/credential.ts +227 -0
  364. package/src/litellm/fake-access-group-litellm.ts +127 -0
  365. package/src/litellm/fake-credential-litellm.ts +216 -0
  366. package/src/litellm/fake-keys.ts +190 -0
  367. package/src/litellm/fake-litellm.ts +19 -9
  368. package/src/litellm/fake-mcp-litellm.ts +214 -0
  369. package/src/litellm/fake-model-litellm-post-update.ts +103 -0
  370. package/src/litellm/fake-model-litellm.ts +233 -0
  371. package/src/litellm/fake-policy-attachment-litellm.ts +97 -0
  372. package/src/litellm/fake-policy-litellm.ts +186 -0
  373. package/src/litellm/fake-registry-base.ts +69 -0
  374. package/src/litellm/fake-stack.ts +17 -1
  375. package/src/litellm/fake-team-litellm.ts +229 -0
  376. package/src/litellm/fake-tool-litellm.ts +88 -0
  377. package/src/litellm/fake-toolset-litellm.ts +110 -0
  378. package/src/litellm/index.ts +140 -0
  379. package/src/litellm/key-delete.test.ts +212 -0
  380. package/src/litellm/key-errors.ts +241 -0
  381. package/src/litellm/key-form.ts +200 -0
  382. package/src/litellm/key-harness.ts +121 -0
  383. package/src/litellm/key-metadata-errors.ts +49 -0
  384. package/src/litellm/key-metadata.test.ts +156 -0
  385. package/src/litellm/key-metadata.ts +74 -0
  386. package/src/litellm/key-operations.ts +184 -0
  387. package/src/litellm/key-rotation.test.ts +110 -0
  388. package/src/litellm/key-scope.test.ts +135 -0
  389. package/src/litellm/key-secret.test.ts +248 -0
  390. package/src/litellm/key-secret.ts +137 -0
  391. package/src/litellm/key-transport.test.ts +166 -0
  392. package/src/litellm/key.test.ts +231 -0
  393. package/src/litellm/key.ts +213 -0
  394. package/src/litellm/mcp-server-adopt.test.ts +86 -0
  395. package/src/litellm/mcp-server-alias.test.ts +184 -0
  396. package/src/litellm/mcp-server-credential.ts +85 -0
  397. package/src/litellm/mcp-server-errors.ts +141 -0
  398. package/src/litellm/mcp-server-exports.test.ts +15 -0
  399. package/src/litellm/mcp-server-form.test.ts +241 -0
  400. package/src/litellm/mcp-server-form.ts +233 -0
  401. package/src/litellm/mcp-server-handlers.test.ts +150 -0
  402. package/src/litellm/mcp-server-locate.ts +66 -0
  403. package/src/litellm/mcp-server-operations.ts +111 -0
  404. package/src/litellm/mcp-server-registry.test.ts +146 -0
  405. package/src/litellm/mcp-server-retype.test.ts +114 -0
  406. package/src/litellm/mcp-server-shadow.test.ts +91 -0
  407. package/src/litellm/mcp-server-shadow.ts +45 -0
  408. package/src/litellm/mcp-server-tools.test.ts +85 -0
  409. package/src/litellm/mcp-server-types.ts +143 -0
  410. package/src/litellm/mcp-server-url.ts +66 -0
  411. package/src/litellm/mcp-server.test.ts +213 -0
  412. package/src/litellm/mcp-server.ts +225 -0
  413. package/src/litellm/model-claim.ts +69 -0
  414. package/src/litellm/model-credential.ts +45 -0
  415. package/src/litellm/model-errors.ts +168 -0
  416. package/src/litellm/model-foreign-row.test.ts +173 -0
  417. package/src/litellm/model-form.test.ts +228 -0
  418. package/src/litellm/model-form.ts +223 -0
  419. package/src/litellm/model-locate.test.ts +128 -0
  420. package/src/litellm/model-locate.ts +67 -0
  421. package/src/litellm/model-operations.test.ts +93 -0
  422. package/src/litellm/model-operations.ts +146 -0
  423. package/src/litellm/model-params-preserve.test.ts +119 -0
  424. package/src/litellm/model-recovery.test.ts +57 -0
  425. package/src/litellm/model-types.ts +112 -0
  426. package/src/litellm/model.test.ts +222 -0
  427. package/src/litellm/model.ts +237 -0
  428. package/src/litellm/policy-attachment-form.ts +103 -0
  429. package/src/litellm/policy-attachment-operations.ts +74 -0
  430. package/src/litellm/policy-attachment-types.ts +48 -0
  431. package/src/litellm/policy-attachment.test.ts +198 -0
  432. package/src/litellm/policy-attachment.ts +178 -0
  433. package/src/litellm/policy-form.ts +122 -0
  434. package/src/litellm/policy-operations.ts +112 -0
  435. package/src/litellm/policy-types.ts +58 -0
  436. package/src/litellm/policy.test.ts +214 -0
  437. package/src/litellm/policy.ts +146 -0
  438. package/src/litellm/providers.ts +24 -3
  439. package/src/litellm/registry-errors.ts +88 -0
  440. package/src/litellm/registry-exports.test.ts +66 -0
  441. package/src/litellm/registry-support.ts +109 -0
  442. package/src/litellm/team-form.ts +140 -0
  443. package/src/litellm/team-members.test.ts +150 -0
  444. package/src/litellm/team-members.ts +58 -0
  445. package/src/litellm/team-operations.ts +90 -0
  446. package/src/litellm/team-permission.ts +159 -0
  447. package/src/litellm/team-read.test.ts +89 -0
  448. package/src/litellm/team-types.ts +106 -0
  449. package/src/litellm/team.test.ts +206 -0
  450. package/src/litellm/team.ts +159 -0
  451. package/src/litellm/tool-policy-form.ts +94 -0
  452. package/src/litellm/tool-policy-operations.ts +58 -0
  453. package/src/litellm/tool-policy-types.ts +48 -0
  454. package/src/litellm/tool-policy.test.ts +172 -0
  455. package/src/litellm/tool-policy.ts +125 -0
  456. package/src/litellm/toolset-form.ts +104 -0
  457. package/src/litellm/toolset-operations.ts +90 -0
  458. package/src/litellm/toolset-types.ts +47 -0
  459. package/src/litellm/toolset.test.ts +198 -0
  460. package/src/litellm/toolset.ts +151 -0
  461. package/src/ownership/ownership.test.ts +33 -1
  462. package/src/ownership/rows.ts +53 -0
  463. package/src/postgres/connection.ts +42 -7
  464. package/src/postgres/database-bigint-serialization.test.ts +1 -0
  465. package/src/postgres/database-refusals.test.ts +2 -2
  466. package/src/postgres/database-sql.ts +36 -9
  467. package/src/postgres/fake-grants-parse.ts +189 -0
  468. package/src/postgres/fake-grants-read.ts +250 -0
  469. package/src/postgres/fake-grants-sql.ts +207 -0
  470. package/src/postgres/fake-grants-write.ts +90 -0
  471. package/src/postgres/fake-role-sql.ts +240 -0
  472. package/src/postgres/fake-schema-semantics.test.ts +36 -0
  473. package/src/postgres/fake-schema-sql.ts +146 -0
  474. package/src/postgres/fake-sql-parse.ts +86 -0
  475. package/src/postgres/fake-sql-quote.ts +36 -0
  476. package/src/postgres/fake-sql.ts +166 -46
  477. package/src/postgres/fixtures/pg-REL_18_6-acl.h.txt +147 -0
  478. package/src/postgres/fixtures/pg-REL_18_6-aclexplode-func.txt +31 -0
  479. package/src/postgres/fixtures/pg-REL_18_6-alter-default-privileges-synopsis.txt +82 -0
  480. package/src/postgres/fixtures/pg-REL_18_6-alter_role.sgml.txt +44 -0
  481. package/src/postgres/fixtures/pg-REL_18_6-create_role.sgml.txt +26 -0
  482. package/src/postgres/fixtures/pg-REL_18_6-grant-synopsis.txt +95 -0
  483. package/src/postgres/fixtures/pg-REL_18_6-pg_attribute.h.txt +24 -0
  484. package/src/postgres/fixtures/pg-REL_18_6-pg_auth_members.h.txt +62 -0
  485. package/src/postgres/fixtures/pg-REL_18_6-pg_authid.h.txt +70 -0
  486. package/src/postgres/fixtures/pg-REL_18_6-pg_class.h.txt +33 -0
  487. package/src/postgres/fixtures/pg-REL_18_6-pg_default_acl.h.txt +81 -0
  488. package/src/postgres/fixtures/pg-REL_18_6-pg_namespace.h.txt +28 -0
  489. package/src/postgres/fixtures/pg-REL_18_6-revoke-synopsis.txt +124 -0
  490. package/src/postgres/grants-acl.test.ts +61 -0
  491. package/src/postgres/grants-attrs.ts +185 -0
  492. package/src/postgres/grants-database.test.ts +158 -0
  493. package/src/postgres/grants-declare.ts +172 -0
  494. package/src/postgres/grants-delete-proof.test.ts +154 -0
  495. package/src/postgres/grants-diff.ts +101 -0
  496. package/src/postgres/grants-errors.ts +215 -0
  497. package/src/postgres/grants-existence-guards.test.ts +113 -0
  498. package/src/postgres/grants-existence.ts +101 -0
  499. package/src/postgres/grants-lifecycle-guards.test.ts +208 -0
  500. package/src/postgres/grants-lifecycle-repair.test.ts +208 -0
  501. package/src/postgres/grants-lifecycle.test.ts +181 -0
  502. package/src/postgres/grants-ops.ts +229 -0
  503. package/src/postgres/grants-owner-revoke.test.ts +121 -0
  504. package/src/postgres/grants-ownership.ts +49 -0
  505. package/src/postgres/grants-plan-collateral.test.ts +202 -0
  506. package/src/postgres/grants-plan-diff.test.ts +204 -0
  507. package/src/postgres/grants-plan-restore.ts +43 -0
  508. package/src/postgres/grants-plan-revocations.test.ts +69 -0
  509. package/src/postgres/grants-plan.test.ts +148 -0
  510. package/src/postgres/grants-plan.ts +245 -0
  511. package/src/postgres/grants-provenance.test.ts +134 -0
  512. package/src/postgres/grants-psql-lifecycle.test.ts +105 -0
  513. package/src/postgres/grants-read-absent.test.ts +91 -0
  514. package/src/postgres/grants-read-defaults.ts +51 -0
  515. package/src/postgres/grants-read.ts +250 -0
  516. package/src/postgres/grants-refusals.test.ts +136 -0
  517. package/src/postgres/grants-refuse.ts +119 -0
  518. package/src/postgres/grants-relkind-wire.test.ts +111 -0
  519. package/src/postgres/grants-repair-plan.test.ts +201 -0
  520. package/src/postgres/grants-sql.test.ts +128 -0
  521. package/src/postgres/grants-sql.ts +144 -0
  522. package/src/postgres/grants-words.ts +34 -0
  523. package/src/postgres/grants.ts +110 -0
  524. package/src/postgres/index.ts +129 -5
  525. package/src/postgres/installed-classifier.ts +36 -0
  526. package/src/postgres/providers.ts +33 -9
  527. package/src/postgres/psql-executor-escaping.test.ts +67 -0
  528. package/src/postgres/psql-executor.test.ts +63 -2
  529. package/src/postgres/psql-executor.ts +74 -34
  530. package/src/postgres/role-adopt.test.ts +98 -0
  531. package/src/postgres/role-attrs.ts +137 -0
  532. package/src/postgres/role-diff.ts +93 -0
  533. package/src/postgres/role-errors.ts +206 -0
  534. package/src/postgres/role-guard.test.ts +60 -0
  535. package/src/postgres/role-identity.test.ts +197 -0
  536. package/src/postgres/role-lifecycle.test.ts +228 -0
  537. package/src/postgres/role-membership-options.test.ts +73 -0
  538. package/src/postgres/role-membership-repair.test.ts +153 -0
  539. package/src/postgres/role-membership-sql.ts +223 -0
  540. package/src/postgres/role-password-ascii.test.ts +53 -0
  541. package/src/postgres/role-password-transports.test.ts +123 -0
  542. package/src/postgres/role-password.test.ts +158 -0
  543. package/src/postgres/role-privilege.test.ts +107 -0
  544. package/src/postgres/role-provenance.test.ts +200 -0
  545. package/src/postgres/role-provider.ts +105 -0
  546. package/src/postgres/role-refusals.test.ts +225 -0
  547. package/src/postgres/role-scram.test.ts +38 -0
  548. package/src/postgres/role-scram.ts +40 -0
  549. package/src/postgres/role-secrets.ts +61 -0
  550. package/src/postgres/role-sql.ts +213 -0
  551. package/src/postgres/role-valid-until.test.ts +68 -0
  552. package/src/postgres/role.ts +226 -0
  553. package/src/postgres/schema-assert.ts +139 -0
  554. package/src/postgres/schema-attrs.ts +71 -0
  555. package/src/postgres/schema-delete-proofs.test.ts +192 -0
  556. package/src/postgres/schema-delete.ts +96 -0
  557. package/src/postgres/schema-diff.ts +44 -0
  558. package/src/postgres/schema-drop-2bp01.test.ts +146 -0
  559. package/src/postgres/schema-errors.ts +209 -0
  560. package/src/postgres/schema-handlers.test.ts +193 -0
  561. package/src/postgres/schema-identity.ts +39 -0
  562. package/src/postgres/schema-lifecycle.test.ts +246 -0
  563. package/src/postgres/schema-race.test.ts +70 -0
  564. package/src/postgres/schema-reconcile.ts +100 -0
  565. package/src/postgres/schema-refusals.test.ts +144 -0
  566. package/src/postgres/schema-socket.test.ts +162 -0
  567. package/src/postgres/schema-sql.ts +130 -0
  568. package/src/postgres/schema-takeover.test.ts +149 -0
  569. package/src/postgres/schema-test-kit.ts +85 -0
  570. package/src/postgres/schema.ts +130 -0
  571. package/src/release/binary-alias.test.ts +3 -3
  572. package/src/release/binary-claims.test.ts +3 -3
  573. package/src/release/binary-directory-umask.test.ts +65 -0
  574. package/src/release/fake-engine.ts +15 -0
  575. package/src/valkey/acl-attrs.ts +98 -0
  576. package/src/valkey/acl-compare.ts +57 -0
  577. package/src/valkey/acl-connection.ts +13 -0
  578. package/src/valkey/acl-delete.test.ts +127 -0
  579. package/src/valkey/acl-form.ts +239 -0
  580. package/src/valkey/acl-managed.ts +13 -0
  581. package/src/valkey/acl-ops.ts +122 -0
  582. package/src/valkey/acl-ownership.test.ts +118 -0
  583. package/src/valkey/acl-prefix.test.ts +38 -0
  584. package/src/valkey/acl-profiles.ts +81 -0
  585. package/src/valkey/acl-reconcile.ts +180 -0
  586. package/src/valkey/acl-reserved.test.ts +69 -0
  587. package/src/valkey/acl-revocation.test.ts +94 -0
  588. package/src/valkey/acl-seat-prefix.test.ts +111 -0
  589. package/src/valkey/acl-validation.test.ts +54 -0
  590. package/src/valkey/acl.test.ts +215 -0
  591. package/src/valkey/acl.ts +169 -0
  592. package/src/valkey/connection-service.ts +46 -0
  593. package/src/valkey/connection.ts +180 -0
  594. package/src/valkey/errors.ts +239 -0
  595. package/src/valkey/fake-acl.ts +128 -0
  596. package/src/valkey/fake-valkey.ts +224 -0
  597. package/src/valkey/handler-test-fixture.ts +43 -0
  598. package/src/valkey/handlers.test.ts +205 -0
  599. package/src/valkey/index.ts +54 -0
  600. package/src/valkey/instance-attrs.ts +48 -0
  601. package/src/valkey/instance-form.ts +104 -0
  602. package/src/valkey/instance.test.ts +108 -0
  603. package/src/valkey/instance.ts +160 -0
  604. package/src/valkey/provider-socket-fixture.ts +71 -0
  605. package/src/valkey/providers.test.ts +129 -0
  606. package/src/valkey/providers.ts +21 -0
  607. package/src/valkey/resp.ts +212 -0
  608. package/src/valkey/transport-bounds.test.ts +150 -0
  609. package/src/valkey/transport-error.ts +37 -0
  610. package/src/valkey/transport.test.ts +158 -0
  611. package/src/valkey/transport.ts +109 -0
  612. package/src/valkey/upstream-bounds.test.ts +14 -0
@@ -0,0 +1,168 @@
1
+ /**
2
+ * The typed refusals `LiteLLM.Model` raises on top of `@distilled.cloud/litellm`'s own SDK errors.
3
+ *
4
+ * ⛔ NO MESSAGE HERE MAY CARRY A CREDENTIAL: only names, ids, field names and the NAME of an
5
+ * environment variable, exactly like mcp-server-errors.ts.
6
+ */
7
+ import type { BadRequest, NotFound } from '@distilled.cloud/litellm/Errors';
8
+ import type * as models from '@distilled.cloud/litellm/model_management';
9
+ import * as Data from 'effect/Data';
10
+
11
+ /** A declaration the resource refuses before any request: a combination nobody meant. */
12
+ export class LitellmModelInvalidError extends Data.TaggedError('LitellmModelInvalidError')<{
13
+ readonly modelName: string;
14
+ readonly problem: string;
15
+ }> {
16
+ override get message(): string {
17
+ return `LiteLLM.Model "${this.modelName}": ${this.problem}.`;
18
+ }
19
+ }
20
+
21
+ /**
22
+ * More than one live deployment carries the declared `model_name`, so adopt-by-name cannot say
23
+ * which one is meant — LiteLLM runs several deployments under one group name on purpose. Declare
24
+ * `id` to pick one; nothing is adopted, updated or deleted on a guess.
25
+ */
26
+ export class LitellmModelAmbiguousNameError extends Data.TaggedError(
27
+ 'LitellmModelAmbiguousNameError',
28
+ )<{
29
+ readonly modelName: string;
30
+ readonly ids: readonly string[];
31
+ }> {
32
+ override get message(): string {
33
+ return (
34
+ `LiteLLM.Model "${this.modelName}": ${this.ids.length} live deployments carry that name ` +
35
+ `(${this.ids.join(', ')}). Declare \`id\` to choose one.`
36
+ );
37
+ }
38
+ }
39
+
40
+ /** `GET /model/info` answered something that is not a list of deployments. */
41
+ export class LitellmModelUnreadableError extends Data.TaggedError('LitellmModelUnreadableError')<{
42
+ readonly reason: string;
43
+ }> {
44
+ override get message(): string {
45
+ return `LiteLLM.Model: the deployment list is unreadable (${this.reason}).`;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * A create or update returned no error, yet no read answers a deployment with the id it was written
51
+ * under: not in the list, and not by the id it would carry.
52
+ */
53
+ export class LitellmModelAbsentAfterWriteError extends Data.TaggedError(
54
+ 'LitellmModelAbsentAfterWriteError',
55
+ )<{
56
+ readonly modelName: string;
57
+ readonly id: string;
58
+ }> {
59
+ override get message(): string {
60
+ return (
61
+ `LiteLLM.Model "${this.modelName}": the write of ${this.id} returned no error but the ` +
62
+ 'deployment is absent from the list and from the by-id read.'
63
+ );
64
+ }
65
+ }
66
+
67
+ /**
68
+ * The write returned no error but the deployment still differs from the declaration. The PATCH
69
+ * merge writes the keys it was sent (`update_db_model` at v1.103.0); a field the read-back still
70
+ * shows different is refused here instead of being reported as converged.
71
+ */
72
+ export class LitellmModelNotConvergedError extends Data.TaggedError(
73
+ 'LitellmModelNotConvergedError',
74
+ )<{
75
+ readonly modelName: string;
76
+ readonly id: string;
77
+ readonly fields: readonly string[];
78
+ }> {
79
+ override get message(): string {
80
+ return (
81
+ `LiteLLM.Model "${this.modelName}": after the write, ${this.id} still differs from the ` +
82
+ `declaration in ${this.fields.join(', ')}.`
83
+ );
84
+ }
85
+ }
86
+
87
+ /**
88
+ * A reconcile with no state found a live row under the declared name whose id is not the one this
89
+ * declaration would create, and nothing vouchsafes it: writing over it would take over another
90
+ * owner's deployment. `replace` says whether this generation is a replace's new identity (a changed
91
+ * declared id), which `--adopt` does not cover — the object must be removed first.
92
+ */
93
+ export class LitellmModelForeignRowError extends Data.TaggedError('LitellmModelForeignRowError')<{
94
+ readonly modelName: string;
95
+ readonly id: string;
96
+ readonly replace: boolean;
97
+ }> {
98
+ override get message(): string {
99
+ const remedy = this.replace
100
+ ? 'It is the new identity of a replace, which --adopt does not cover: remove it first.'
101
+ : 'Deploy with --adopt to take it over, or remove it first.';
102
+ return (
103
+ `LiteLLM.Model "${this.modelName}": the live row ${this.id} already exists and this stack ` +
104
+ `holds no state for it. Nothing was written. ${remedy}`
105
+ );
106
+ }
107
+ }
108
+
109
+ /**
110
+ * The row a reconcile found is served from the proxy's config file (`model_info.db_model: false`),
111
+ * not from the database, so the DB API cannot manage it. Remove it from the config file first.
112
+ */
113
+ /**
114
+ * The live row a stateless reconcile found is an OLDER generation of this FQN's own state chain
115
+ * (`attr.id` walked through `old`). It is still the serving deployment: the replacement that
116
+ * followed it never committed. Taking the row over would store that id on the new generation, and
117
+ * `destroy()` then deletes the old generation by the same id.
118
+ * ⛔ THE RECOVERY IS STATE, NOT THE ROW. `alchemy state rm` deletes the state record and leaves the
119
+ * deployment; deleting the live row takes the serving model out of its group.
120
+ */
121
+ export class LitellmModelPriorGenerationError extends Data.TaggedError(
122
+ 'LitellmModelPriorGenerationError',
123
+ )<{
124
+ readonly modelName: string;
125
+ readonly id: string;
126
+ readonly fqn: string;
127
+ }> {
128
+ override get message(): string {
129
+ return (
130
+ `LiteLLM.Model "${this.modelName}": the live row ${this.id} is an older generation still ` +
131
+ `recorded on ${this.fqn}. Nothing was written. Taking it over would store that id on the ` +
132
+ 'in-flight replacement, and destroy() then deletes the old generation by the same id. ' +
133
+ "Drop this resource's state row (alchemy state rm, which leaves the deployment) and " +
134
+ 'deploy again with --adopt. Do not delete the live row.'
135
+ );
136
+ }
137
+ }
138
+
139
+ export class LitellmModelConfigFileRowError extends Data.TaggedError(
140
+ 'LitellmModelConfigFileRowError',
141
+ )<{
142
+ readonly modelName: string;
143
+ readonly id: string;
144
+ }> {
145
+ override get message(): string {
146
+ return (
147
+ `LiteLLM.Model "${this.modelName}": the live row ${this.id} is served from the proxy's ` +
148
+ 'config file (db_model: false), not from the database, so the DB API cannot manage it. ' +
149
+ 'Remove it from the config file first.'
150
+ );
151
+ }
152
+ }
153
+
154
+ export type ModelError =
155
+ | models.AddNewModelModelNewPostError
156
+ | models.DeleteModelModelDeletePostError
157
+ | models.GetModelInfoV1ModelInfoError
158
+ | models.PatchModelModelModelIdUpdatePatchError
159
+ | BadRequest
160
+ | NotFound
161
+ | LitellmModelInvalidError
162
+ | LitellmModelAmbiguousNameError
163
+ | LitellmModelUnreadableError
164
+ | LitellmModelAbsentAfterWriteError
165
+ | LitellmModelNotConvergedError
166
+ | LitellmModelForeignRowError
167
+ | LitellmModelPriorGenerationError
168
+ | LitellmModelConfigFileRowError;
@@ -0,0 +1,173 @@
1
+ /**
2
+ * A replace (an unpinned rename, or a changed declared id) reaches `reconcile` with `output`
3
+ * undefined and a live row under the name or id it is moving onto — and that row may belong to
4
+ * another owner. The old gate let it take the row over (measured live on a throwaway 1.103.0
5
+ * proxy through Alchemy's real Plan and Apply: the foreign row's model was overwritten, its
6
+ * access group cleared, its `extra_headers` dropped, and state recorded the foreign id, so a
7
+ * later destroy deleted another owner's deployment). The gate in model.ts now counts only a row
8
+ * whose id is the deterministic one this declaration would create (`ours`); anything else is
9
+ * refused (`LitellmModelForeignRowError`), and a declared id that points at an existing row goes
10
+ * through the `Unowned`/`--adopt` gate like any adoption.
11
+ *
12
+ * ★ EVERY VALUE IS `FAKE-*`, through Alchemy's real Plan and Apply over the fake proxy.
13
+ */
14
+ import { expect, test } from 'bun:test';
15
+ import * as Effect from 'effect/Effect';
16
+ import { type FakeModelLitellm, modelRow, startFakeModelLitellm } from './fake-model-litellm.ts';
17
+ import { fakeStack, writesOf } from './fake-stack.ts';
18
+ import { LiteLLMModel } from './model.ts';
19
+ import type { ModelProps } from './model-types.ts';
20
+
21
+ type Row = Record<string, unknown>;
22
+
23
+ const KEY = 'sk-test-master';
24
+ const stack = (fake: FakeModelLitellm) =>
25
+ fakeStack({ apiKey: KEY, baseUrl: 'https://litellm.example.com' }, fake.fetch);
26
+ const declare = (props: ModelProps, name = 'Grok') =>
27
+ Effect.gen(function* () {
28
+ yield* LiteLLMModel(name, props);
29
+ });
30
+
31
+ const grok: ModelProps = {
32
+ apiKey: { fromEnv: 'FAKE_XAI_KEY' },
33
+ model: 'xai/grok-4.7',
34
+ modelName: 'grok',
35
+ };
36
+
37
+ /** A one-deployment group a foreign owner runs: a gateway auth header, a weight, a group. */
38
+ const foreign = modelRow({
39
+ litellm_params: {
40
+ extra_headers: { 'X-Gateway-Auth': 'FAKE-gateway-credential' },
41
+ model: 'xai/grok-4.6',
42
+ weight: 2,
43
+ },
44
+ model_info: { access_groups: ['FAKE-team'], id: 'FAKE-foreign-id' },
45
+ model_name: 'grok',
46
+ });
47
+
48
+ const rowAt = (fake: FakeModelLitellm, id: string): Row =>
49
+ (fake.models().find((each) => ((each['model_info'] as Row)['id'] as string) === id) ?? {}) as Row;
50
+
51
+ test('an unpinned rename onto a foreign row is refused and the row is untouched', async () => {
52
+ const fake = startFakeModelLitellm({ masterKey: KEY, seed: [foreign] });
53
+ const engine = stack(fake);
54
+ // The stack first owns a row under another name, so the next declaration is a REPLACE.
55
+ expect(await engine.deploy(declare({ ...grok, modelName: 'old-name' }))).toEqual({
56
+ Grok: 'create',
57
+ });
58
+ const before = fake.requests().length;
59
+ await expect(engine.deploy(declare(grok))).rejects.toThrow(/--adopt does not cover/);
60
+ expect(writesOf(fake.requests().slice(before))).toEqual([]);
61
+ // 🔴 the measured takeover wrote the model, cleared the group and dropped extra_headers here.
62
+ expect(rowAt(fake, 'FAKE-foreign-id')).toMatchObject({
63
+ litellm_params: {
64
+ extra_headers: { 'X-Gateway-Auth': 'FAKE-gateway-credential' },
65
+ model: 'xai/grok-4.6',
66
+ weight: 2,
67
+ },
68
+ model_info: { access_groups: ['FAKE-team'] },
69
+ model_name: 'grok',
70
+ });
71
+ // The rename refused, the stack's own row is neither deleted nor renamed either.
72
+ expect(writesOf(fake.requests())).toEqual(['POST /model/new']);
73
+ });
74
+
75
+ test('an unpinned rename onto a foreign row is refused even with --adopt', async () => {
76
+ const fake = startFakeModelLitellm({ masterKey: KEY, seed: [foreign] });
77
+ const engine = stack(fake);
78
+ await engine.deploy(declare({ ...grok, modelName: 'old-name' }));
79
+ const before = fake.requests().length;
80
+ // 🔴 A replace's new identity is never probed and never offered adoption: Apply commits it as
81
+ // `replacing`, so `--adopt` cannot speak for it (ownership/adopt.ts). Refused, not adopted.
82
+ await expect(engine.deploy(declare(grok), { adopt: true })).rejects.toThrow(
83
+ /--adopt does not cover/,
84
+ );
85
+ expect(writesOf(fake.requests().slice(before))).toEqual([]);
86
+ });
87
+
88
+ test('reverting an unpinned rename that hit a foreign row names a state recovery', async () => {
89
+ const fake = startFakeModelLitellm({ masterKey: KEY, seed: [foreign] });
90
+ const engine = stack(fake);
91
+ expect(await engine.deploy(declare({ ...grok, modelName: 'old-name' }))).toEqual({
92
+ Grok: 'create',
93
+ });
94
+ // The refusal is right, and Apply has already committed the `replacing` row.
95
+ await expect(engine.deploy(declare(grok))).rejects.toThrow(/--adopt does not cover/);
96
+ const before = fake.requests().length;
97
+ // The engine resumes that same replacement. Reconcile finds the stack's own serving row by
98
+ // the old name. Its id is the previous generation's, not this instance's physical name.
99
+ await expect(engine.deploy(declare({ ...grok, modelName: 'old-name' }))).rejects.toThrow(
100
+ /older generation/,
101
+ );
102
+ await expect(
103
+ engine.deploy(declare({ ...grok, modelName: 'old-name' }), { adopt: true }),
104
+ ).rejects.toThrow(/alchemy state rm/);
105
+ expect(writesOf(fake.requests().slice(before))).toEqual([]);
106
+ expect(rowAt(fake, 'FAKE-foreign-id')).toMatchObject({
107
+ litellm_params: { model: 'xai/grok-4.6' },
108
+ model_name: 'grok',
109
+ });
110
+ const serving = fake.models().find((row) => row['model_name'] === 'old-name');
111
+ if (serving === undefined) throw new Error("the stack's own row is gone");
112
+ expect((serving['model_info'] as Row)['id']).not.toBe('FAKE-foreign-id');
113
+ });
114
+
115
+ test('a changed declared id pointing at a foreign row is refused, the row untouched', async () => {
116
+ const fake = startFakeModelLitellm({ masterKey: KEY, seed: [foreign] });
117
+ const engine = stack(fake);
118
+ expect(
119
+ await engine.deploy(declare({ ...grok, id: 'FAKE-ours-id', modelName: 'old-name' })),
120
+ ).toEqual({ Grok: 'create' });
121
+ const before = fake.requests().length;
122
+ // The id is identity: declaring the foreign row's id is a replace onto it — refused, whether
123
+ // it is `--adopt` or not, because the probe never asked whose row the replacement would move to.
124
+ await expect(
125
+ engine.deploy(declare({ ...grok, id: 'FAKE-foreign-id', modelName: 'old-name' }), {
126
+ adopt: true,
127
+ }),
128
+ ).rejects.toThrow(/FAKE-foreign-id/);
129
+ expect(writesOf(fake.requests().slice(before))).toEqual([]);
130
+ expect(rowAt(fake, 'FAKE-foreign-id')).toMatchObject({
131
+ model_info: { access_groups: ['FAKE-team'] },
132
+ });
133
+ // The stack's own row survives the failed replace (`retain`), and the foreign row is intact.
134
+ expect(rowAt(fake, 'FAKE-ours-id')).toMatchObject({ model_name: 'old-name' });
135
+ });
136
+
137
+ test('a declared id on a foreign row goes through the Unowned gate: refused, then adopted', async () => {
138
+ const fake = startFakeModelLitellm({ masterKey: KEY, seed: [foreign] });
139
+ const engine = stack(fake);
140
+ // No state at all: the plan's probe answers Unowned, so the deploy refuses without --adopt.
141
+ await expect(engine.deploy(declare({ ...grok, id: 'FAKE-foreign-id' }))).rejects.toThrow();
142
+ expect(writesOf(fake.requests())).toEqual([]);
143
+ // With --adopt it is an explicit adoption: the drift (a different model) PATCHes with the
144
+ // row's own id in model_info, and the second deploy is a no-op on it.
145
+ expect(await engine.deploy(declare({ ...grok, id: 'FAKE-foreign-id' }), { adopt: true })).toEqual(
146
+ { Grok: 'adopted' },
147
+ );
148
+ expect(writesOf(fake.requests())).toEqual(['PATCH /model/FAKE-foreign-id/update']);
149
+ const adopted = rowAt(fake, 'FAKE-foreign-id');
150
+ expect(adopted['litellm_params']).toMatchObject({ model: 'xai/grok-4.7' });
151
+ expect(adopted['model_info']).toMatchObject({ access_groups: [] });
152
+ expect(await engine.deploy(declare({ ...grok, id: 'FAKE-foreign-id' }), { adopt: true })).toEqual(
153
+ { Grok: 'noop' },
154
+ );
155
+ });
156
+
157
+ test('a config-file row is refused at adopt, even with --adopt', async () => {
158
+ const config = modelRow({
159
+ litellm_params: { model: 'xai/grok-4.6' },
160
+ model_info: { access_groups: ['FAKE-team'], db_model: false, id: 'FAKE-config-id' },
161
+ model_name: 'grok',
162
+ });
163
+ const fake = startFakeModelLitellm({ masterKey: KEY, seed: [config] });
164
+ const engine = stack(fake);
165
+ // The DB API cannot manage what the proxy serves from its config file, so --adopt must not
166
+ // take it over either: the gate refuses before a single write.
167
+ await expect(engine.deploy(declare(grok), { adopt: true })).rejects.toThrow(/config file/);
168
+ expect(writesOf(fake.requests())).toEqual([]);
169
+ expect(rowAt(fake, 'FAKE-config-id')).toMatchObject({
170
+ model_info: { access_groups: ['FAKE-team'], db_model: false },
171
+ model_name: 'grok',
172
+ });
173
+ });
@@ -0,0 +1,228 @@
1
+ /**
2
+ * `LiteLLM.Model`'s pure form, with no server and no environment: the plan-time refusals, the wire
3
+ * bodies, the read shape under encryption, and the comparison. The credential is a reference, so
4
+ * nothing here reads (or could read) a value.
5
+ */
6
+ import { describe, expect, test } from 'bun:test';
7
+ import { declaredValues, sealFromValues, sealState } from './model-credential.ts';
8
+ import {
9
+ createBody,
10
+ declaredDigest,
11
+ differing,
12
+ firstProblem,
13
+ patchBody,
14
+ toAttributes,
15
+ } from './model-form.ts';
16
+ import type { ModelProps } from './model-types.ts';
17
+
18
+ type Row = Record<string, unknown>;
19
+
20
+ const props: ModelProps = {
21
+ apiKey: { fromEnv: 'FAKE_XAI_KEY' },
22
+ model: 'xai/grok-4.7',
23
+ modelName: 'grok',
24
+ };
25
+
26
+ describe('firstProblem refuses', () => {
27
+ test('a blank or padded model name', () => {
28
+ expect(firstProblem({ ...props, modelName: '' })).toContain('modelName');
29
+ expect(firstProblem({ ...props, modelName: ' grok' })).toContain('modelName');
30
+ });
31
+
32
+ test('a blank id', () => {
33
+ expect(firstProblem({ ...props, id: ' ' })).toContain('id');
34
+ });
35
+
36
+ test('a model without a provider prefix', () => {
37
+ expect(firstProblem({ ...props, model: 'grok-4.7' })).toContain('provider prefix');
38
+ });
39
+
40
+ test('the openai/ prefix on a grok-named group: Grok is xAI', () => {
41
+ expect(firstProblem({ ...props, model: 'openai/grok-4.7' })).toContain('xAI');
42
+ });
43
+
44
+ test('an api_base that carries a secret, a userinfo or a fragment', () => {
45
+ expect(firstProblem({ ...props, apiBase: 'https://api.xai.example.com?token=FAKE' })).toContain(
46
+ 'credential',
47
+ );
48
+ expect(firstProblem({ ...props, apiBase: 'https://user:FAKE@api.xai.example.com' })).toContain(
49
+ 'userinfo',
50
+ );
51
+ expect(firstProblem({ ...props, apiBase: 'https://api.xai.example.com#frag' })).toContain(
52
+ 'fragment',
53
+ );
54
+ });
55
+
56
+ test('an apiKey value instead of a reference', () => {
57
+ expect(firstProblem({ ...props, apiKey: 'FAKE-literal-value' as never })).toContain(
58
+ 'never a value',
59
+ );
60
+ expect(firstProblem({ ...props, apiKey: { fromEnv: '' } })).toContain('environment variable');
61
+ });
62
+
63
+ test('nothing else: a well-formed declaration passes', () => {
64
+ expect(firstProblem(props)).toBeUndefined();
65
+ expect(
66
+ firstProblem({
67
+ apiBase: 'https://api.xai.example.com',
68
+ baseModel: 'grok-4',
69
+ id: 'FAKE-id',
70
+ mode: 'chat',
71
+ model: 'cloudflare/@cf/meta/llama-3.1-8b-instruct',
72
+ modelName: 'llama',
73
+ }),
74
+ ).toBeUndefined();
75
+ });
76
+ });
77
+
78
+ describe('the wire bodies', () => {
79
+ test('a create sends the group, the id it asks for, and the reference credential', () => {
80
+ // `as Row`: the SDK's 1.103.0 request type does not declare `access_groups` (model-form.ts)
81
+ expect(createBody(props, 'FAKE-wanted') as unknown as Row).toEqual({
82
+ litellm_params: { api_key: 'os.environ/FAKE_XAI_KEY', model: 'xai/grok-4.7' },
83
+ model_info: { access_groups: [], id: 'FAKE-wanted' },
84
+ model_name: 'grok',
85
+ });
86
+ });
87
+
88
+ test('a declared api_base, mode, base model and groups are sent', () => {
89
+ const declared: ModelProps = {
90
+ accessGroups: ['FAKE-team'],
91
+ apiBase: 'https://api.xai.example.com',
92
+ baseModel: 'grok-4',
93
+ mode: 'chat',
94
+ model: 'xai/grok-4.7',
95
+ modelName: 'grok',
96
+ };
97
+ expect(createBody(declared, 'FAKE-wanted')).toMatchObject({
98
+ litellm_params: { api_base: 'https://api.xai.example.com' },
99
+ model_info: {
100
+ access_groups: ['FAKE-team'],
101
+ base_model: 'grok-4',
102
+ mode: 'chat',
103
+ },
104
+ });
105
+ });
106
+
107
+ test('a patch re-sends the managed set, the row id, and the group name only when it changed', () => {
108
+ const live = toAttributes({
109
+ litellm_params: { model: 'xai/grok-4.7' },
110
+ model_info: { id: 'FAKE-live-id' },
111
+ model_name: 'grok',
112
+ });
113
+ const sameName = patchBody(props, live) as Row;
114
+ expect(sameName['litellm_params']).toEqual({
115
+ allow_client_keepalive_override: null,
116
+ api_key: 'os.environ/FAKE_XAI_KEY',
117
+ merge_reasoning_content_in_choices: null,
118
+ model: 'xai/grok-4.7',
119
+ use_in_pass_through: null,
120
+ use_litellm_proxy: null,
121
+ use_xai_oauth: null,
122
+ });
123
+ expect('model_name' in sameName).toBe(false);
124
+ // ★ The row's own id rides the body: an adopt-by-id re-affirms the row it pinned.
125
+ expect(sameName['model_info']).toEqual({ access_groups: [], id: 'FAKE-live-id' });
126
+ expect(sameName['model_id']).toBe('FAKE-live-id');
127
+
128
+ const renamed = patchBody({ ...props, modelName: 'grok-fast' }, live) as Row;
129
+ expect(renamed['model_name']).toBe('grok-fast');
130
+ });
131
+
132
+ test('an undeclared mode, base model and credential are never sent, so the row keeps its own', () => {
133
+ const live = toAttributes({
134
+ litellm_params: { model: 'xai/grok-4.7' },
135
+ model_info: { id: 'FAKE-live-id' },
136
+ model_name: 'grok',
137
+ });
138
+ const bare: ModelProps = { model: 'xai/grok-4.7', modelName: 'grok' };
139
+ const body = patchBody(bare, live) as Row;
140
+ expect(body['litellm_params']).toMatchObject({
141
+ model: 'xai/grok-4.7',
142
+ use_in_pass_through: null,
143
+ use_xai_oauth: null,
144
+ });
145
+ expect(body['model_info']).toEqual({ access_groups: [], id: 'FAKE-live-id' });
146
+ expect((patchBody({ ...bare, mode: 'chat' }, live) as Row)['model_info']).toEqual({
147
+ access_groups: [],
148
+ id: 'FAKE-live-id',
149
+ mode: 'chat',
150
+ });
151
+ });
152
+ });
153
+
154
+ describe('the declared seal', () => {
155
+ test('matches what a write stamps, and round-trips', () => {
156
+ const sealed = sealFromValues(declaredValues(props));
157
+ expect(sealed).not.toBe('');
158
+ expect(sealState(props, sealed)).toBe('match');
159
+ });
160
+
161
+ test('an adopted row without a seal is stale, so the next reconcile records it locally', () => {
162
+ expect(sealState(props, '')).toBe('stale');
163
+ });
164
+
165
+ test('a change of model, api_base or reference NAME moves the seal (the value never does)', () => {
166
+ const sealed = declaredDigest(props);
167
+ expect(sealState({ ...props, model: 'xai/grok-4.6' }, sealed)).toBe('stale');
168
+ expect(sealState({ ...props, apiBase: 'https://api.xai.example.com' }, sealed)).toBe('stale');
169
+ expect(sealState({ ...props, apiKey: { fromEnv: 'FAKE_XAI_KEY_TWO' } }, sealed)).toBe('stale');
170
+ expect(sealState(props, 'garbage')).toBe('stale');
171
+ });
172
+ });
173
+
174
+ describe('toAttributes and differing', () => {
175
+ test('reads the id from wherever the proxy carried it', () => {
176
+ expect(toAttributes({ model_info: { id: 'i' }, model_name: 'grok' }).id).toBe('i');
177
+ expect(toAttributes({ id: 'top', model_name: 'grok' }).id).toBe('top');
178
+ });
179
+
180
+ test('a ciphertext params field hides the model; an object one carries it as it is', () => {
181
+ const encrypted = toAttributes({
182
+ litellm_params: '<encrypted>',
183
+ model_name: 'grok',
184
+ });
185
+ expect(encrypted.model).toBeNull();
186
+ expect(differing(encrypted, props)).toEqual([]);
187
+ const visible = toAttributes({
188
+ litellm_params: { model: 'xai/grok-4.7' },
189
+ model_name: 'grok',
190
+ });
191
+ expect(visible.model).toBe('xai/grok-4.7');
192
+ });
193
+
194
+ test('never copies api_base or api_key, and no row supplies a digest', () => {
195
+ const live = toAttributes({
196
+ litellm_params: {
197
+ api_base: 'https://api.xai.example.com',
198
+ api_key: 'os.environ/FAKE_XAI_KEY',
199
+ model: 'xai/grok-4.7',
200
+ },
201
+ model_info: { id: 'i' },
202
+ model_name: 'grok',
203
+ });
204
+ expect(JSON.stringify(live)).not.toContain('FAKE_XAI_KEY');
205
+ expect(live.paramsSeal).toBe('');
206
+ });
207
+
208
+ test('names exactly the fields where the row and the declaration disagree', () => {
209
+ const live = toAttributes({
210
+ litellm_params: { model: 'xai/grok-4.7' },
211
+ model_info: { access_groups: ['FAKE-team'], id: 'i', mode: 'chat' },
212
+ model_name: 'grok',
213
+ });
214
+ expect(differing(live, props)).toEqual(['access_groups']);
215
+ expect(differing(live, { ...props, mode: 'chat' })).toEqual(['access_groups']);
216
+ expect(differing(live, { ...props, accessGroups: ['FAKE-team'], mode: 'chat' })).toEqual([]);
217
+ expect(differing(live, { ...props, modelName: 'grok-fast' })).toEqual([
218
+ 'model_name',
219
+ 'access_groups',
220
+ ]);
221
+ // ★ access groups compare as a set, order-free
222
+ const shuffled = toAttributes({
223
+ model_info: { access_groups: ['b', 'a'], id: 'i' },
224
+ model_name: 'grok',
225
+ });
226
+ expect(differing(shuffled, { ...props, accessGroups: ['a', 'b'] })).toEqual([]);
227
+ });
228
+ });