@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,146 @@
1
+ /**
2
+ * `LiteLLM.Policy` — the PRODUCTION version of one named policy in LiteLLM's policy engine
3
+ * (`LiteLLM_PolicyTable`, `/policies`): a set of guardrails to add and remove, with an optional model
4
+ * condition. Props, the versioning and what is left out: policy-types.ts.
5
+ *
6
+ * ★ A CHANGE IS A NEW VERSION, PROMOTED. Only a draft is editable and only production is enforced, so
7
+ * an update clones production to a draft, edits it, publishes it and promotes it; the old production
8
+ * stays as a `published` version. A run that stops midway leaves a draft or a published copy, both
9
+ * inert; the next run starts from production again and never touches a version it did not make.
10
+ * ★ ADOPT BY NAME. A live production version with no state is `Unowned`, so it needs `--adopt`.
11
+ * ⛔ A POLICY THAT EXISTS ONLY IN config.yaml IS NEVER SHADOWED BY ACCIDENT: a create refuses when the
12
+ * name belongs to a config policy, because a production DB policy would override it at runtime.
13
+ * ⛔ NO PRODUCTION VERSION IS NEVER GUESSED AT: a name whose versions are all `draft` or `published`
14
+ * (someone demoted it) is refused with the count, not promoted.
15
+ * ★ `defaultRemovalPolicy: 'retain'` — deleting removes EVERY version (the history) and stops the
16
+ * guardrails applying wherever an attachment pointed at it. Opt in with `RemovalPolicy.destroy()`.
17
+ * ⚠️ NO LICENCE GATE ON THESE ROUTES: `policy_endpoints.py` and `policy_engine/*.py` have no
18
+ * `premium_user` check (grep, 1.103.0). The docs page says team/key-based attachment needs Enterprise
19
+ * (docs.litellm.ai/docs/proxy/guardrails/guardrail_policies); whether a CE proxy enforces one is
20
+ * UNVERIFIED. The `policies` metadata of a team or key IS gated (`_premium_user_check`).
21
+ * ⛔ NO LITELLM CREDENTIAL IS A PROP; `litellmProviders`' layer supplies `Credentials`.
22
+ */
23
+ import { Resource } from 'alchemy';
24
+ import { Unowned } from 'alchemy/AdoptPolicy';
25
+ import { isResolved } from 'alchemy/Diff';
26
+ import type { Input } from 'alchemy/Input';
27
+ import * as Provider from 'alchemy/Provider';
28
+ import * as Effect from 'effect/Effect';
29
+ import * as Predicate from 'effect/Predicate';
30
+ import { createBody, differing, firstProblem, toAttributes, updateBody } from './policy-form.ts';
31
+ import {
32
+ configPolicyNames,
33
+ createDraft,
34
+ createPolicy,
35
+ deleteAllVersions,
36
+ editDraft,
37
+ listPolicyVersions,
38
+ setVersionStatus,
39
+ } from './policy-operations.ts';
40
+ import type { PolicyAttributes, PolicyProps, PolicyVersion } from './policy-types.ts';
41
+ import {
42
+ LitellmRegistryAbsentAfterWriteError,
43
+ LitellmRegistryInvalidError,
44
+ LitellmRegistryNotConvergedError,
45
+ } from './registry-errors.ts';
46
+ import { dieIfInvalid, failIfInvalid } from './registry-support.ts';
47
+
48
+ export type { PolicyAttributes, PolicyProps };
49
+ export type { RegistryError as PolicyError } from './registry-errors.ts';
50
+
51
+ const RESOURCE = 'LiteLLM.Policy';
52
+
53
+ export interface LiteLLMPolicy extends Resource<'LiteLLM.Policy', PolicyProps, PolicyAttributes> {}
54
+
55
+ export const LiteLLMPolicy = Resource<LiteLLMPolicy>('LiteLLM.Policy', {
56
+ defaultRemovalPolicy: 'retain',
57
+ });
58
+
59
+ export const isLiteLLMPolicy = (value: unknown): value is LiteLLMPolicy =>
60
+ Predicate.hasProperty(value, 'Type') && value.Type === 'LiteLLM.Policy';
61
+
62
+ const production = (versions: readonly PolicyVersion[]) =>
63
+ versions.find((version) => version.versionStatus === 'production');
64
+
65
+ const invalid = (name: string, problem: string) =>
66
+ Effect.fail(new LitellmRegistryInvalidError({ name, problem, resource: RESOURCE }));
67
+
68
+ /** ⛔ TEST-ONLY EXPORT. Not on index.ts's barrel. */
69
+ export const policyHandlers = {
70
+ /** ⛔ With no `output` this is the adoption probe, so the refusals run here too (registry-support.ts). */
71
+ read: ({ olds, output }: { olds: PolicyProps; output: PolicyAttributes | undefined }) =>
72
+ Effect.gen(function* () {
73
+ if (output === undefined) {
74
+ yield* dieIfInvalid(RESOURCE, String(olds.policyName), firstProblem(olds));
75
+ }
76
+ const live = production(yield* listPolicyVersions(output?.policyName ?? olds.policyName));
77
+ if (live === undefined) return undefined;
78
+ return output === undefined ? Unowned(toAttributes(live)) : toAttributes(live);
79
+ }),
80
+
81
+ diff: ({ news, output }: { news: Input<PolicyProps>; output: PolicyAttributes | undefined }) =>
82
+ Effect.gen(function* () {
83
+ if (!isResolved(news)) return undefined;
84
+ yield* failIfInvalid(RESOURCE, String(news.policyName), firstProblem(news));
85
+ if (output === undefined) return undefined;
86
+ // The name is identity: a different name is a different policy.
87
+ if (news.policyName !== output.policyName) {
88
+ return { action: 'replace', deleteFirst: false } as const;
89
+ }
90
+ return differing(output, news).length === 0
91
+ ? ({ action: 'noop' } as const)
92
+ : ({ action: 'update' } as const);
93
+ }),
94
+
95
+ reconcile: ({ news }: { news: PolicyProps }) =>
96
+ Effect.gen(function* () {
97
+ yield* failIfInvalid(RESOURCE, String(news.policyName), firstProblem(news));
98
+ const versions = yield* listPolicyVersions(news.policyName);
99
+ const live = production(versions);
100
+ if (versions.length === 0) {
101
+ if ((yield* configPolicyNames()).includes(news.policyName)) {
102
+ return yield* invalid(
103
+ news.policyName,
104
+ 'a policy of this name is defined in config.yaml, and a production DB policy would override it at runtime; rename this one or remove the config policy first',
105
+ );
106
+ }
107
+ yield* createPolicy(createBody(news));
108
+ } else if (live === undefined) {
109
+ return yield* invalid(
110
+ news.policyName,
111
+ `${versions.length} version(s) exist and none is production, so the policy is inactive; promote one in LiteLLM (or delete its versions) instead of letting this guess`,
112
+ );
113
+ } else if (differing(live, news).length > 0) {
114
+ const draft = yield* createDraft(news.policyName);
115
+ yield* editDraft(draft.policyId, updateBody(news, live));
116
+ yield* setVersionStatus(draft.policyId, 'published');
117
+ yield* setVersionStatus(draft.policyId, 'production');
118
+ }
119
+
120
+ const after = production(yield* listPolicyVersions(news.policyName));
121
+ if (after === undefined) {
122
+ return yield* Effect.fail(
123
+ new LitellmRegistryAbsentAfterWriteError({ name: news.policyName, resource: RESOURCE }),
124
+ );
125
+ }
126
+ const left = differing(after, news);
127
+ if (left.length > 0) {
128
+ return yield* Effect.fail(
129
+ new LitellmRegistryNotConvergedError({
130
+ fields: left,
131
+ name: news.policyName,
132
+ resource: RESOURCE,
133
+ }),
134
+ );
135
+ }
136
+ return toAttributes(after);
137
+ }),
138
+
139
+ delete: ({ output }: { output: PolicyAttributes }) => deleteAllVersions(output.policyName),
140
+
141
+ /** ⛔ EMPTY: adoption is an explicit act (`--adopt`), and no ownership mark exists to filter by. */
142
+ list: () => Effect.succeed([]),
143
+ };
144
+
145
+ export const LiteLLMPolicyProvider = () =>
146
+ Provider.effect(LiteLLMPolicy, Effect.succeed(LiteLLMPolicy.Provider.of(policyHandlers)));
@@ -20,10 +20,31 @@
20
20
  */
21
21
  import { type Credentials, CredentialsFromEnv } from '@distilled.cloud/litellm/Credentials';
22
22
  import * as Layer from 'effect/Layer';
23
+ import { LiteLLMAccessGroupProvider } from './access-group.ts';
23
24
  import { LiteLLMBudgetProvider } from './budget.ts';
25
+ import { LiteLLMCredentialProvider } from './credential.ts';
26
+ import { LiteLLMMCPServerProvider } from './mcp-server.ts';
27
+ import { LiteLLMKeyProvider } from './key.ts';
28
+ import { LiteLLMModelProvider } from './model.ts';
24
29
  import { LiteLLMPassThroughEndpointProvider } from './pass-through-endpoint.ts';
30
+ import { LiteLLMPolicyAttachmentProvider } from './policy-attachment.ts';
31
+ import { LiteLLMPolicyProvider } from './policy.ts';
32
+ import { LiteLLMTeamProvider } from './team.ts';
33
+ import { LiteLLMToolPolicyProvider } from './tool-policy.ts';
34
+ import { LiteLLMToolsetProvider } from './toolset.ts';
25
35
 
26
36
  export const litellmProviders = (creds: Layer.Layer<Credentials> = CredentialsFromEnv) =>
27
- Layer.mergeAll(LiteLLMPassThroughEndpointProvider(), LiteLLMBudgetProvider()).pipe(
28
- Layer.provideMerge(creds),
29
- );
37
+ Layer.mergeAll(
38
+ LiteLLMPassThroughEndpointProvider(),
39
+ LiteLLMBudgetProvider(),
40
+ LiteLLMCredentialProvider(),
41
+ LiteLLMMCPServerProvider(),
42
+ LiteLLMAccessGroupProvider(),
43
+ LiteLLMToolsetProvider(),
44
+ LiteLLMToolPolicyProvider(),
45
+ LiteLLMPolicyProvider(),
46
+ LiteLLMPolicyAttachmentProvider(),
47
+ LiteLLMTeamProvider(),
48
+ LiteLLMKeyProvider(),
49
+ LiteLLMModelProvider(),
50
+ ).pipe(Layer.provideMerge(creds));
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The typed refusals the LiteLLM registry resources (`LiteLLM.Team`, `AccessGroup`, `Toolset`,
3
+ * `Policy`, `PolicyAttachment`, `ToolPolicy`) raise on top of `@distilled.cloud/litellm`'s own SDK
4
+ * errors. One small set, tagged with the resource it came from, so a stack's error handling does not
5
+ * grow six near-identical classes.
6
+ *
7
+ * ⛔ NO MESSAGE HERE MAY CARRY A CREDENTIAL. What is named: the resource type, the declared name or
8
+ * id, ids the proxy already lists, and field names. Never a description (free text a person wrote)
9
+ * and never a request body.
10
+ */
11
+ import * as Data from 'effect/Data';
12
+
13
+ /** A declaration the resource refuses before any request: a combination nobody meant. */
14
+ export class LitellmRegistryInvalidError extends Data.TaggedError('LitellmRegistryInvalidError')<{
15
+ readonly resource: string;
16
+ readonly name: string;
17
+ readonly problem: string;
18
+ }> {
19
+ override get message(): string {
20
+ return `${this.resource} "${this.name}": ${this.problem}.`;
21
+ }
22
+ }
23
+
24
+ /** A list or read answered something that is not the rows this resource expects. */
25
+ export class LitellmRegistryUnreadableError extends Data.TaggedError(
26
+ 'LitellmRegistryUnreadableError',
27
+ )<{
28
+ readonly resource: string;
29
+ readonly reason: string;
30
+ }> {
31
+ override get message(): string {
32
+ return `${this.resource}: the proxy's answer is unreadable (${this.reason}).`;
33
+ }
34
+ }
35
+
36
+ /**
37
+ * More than one live row could be the declared one, so adopting by name cannot say which. Nothing is
38
+ * adopted, updated or deleted on a guess: declare the id to choose one.
39
+ */
40
+ export class LitellmRegistryAmbiguousError extends Data.TaggedError(
41
+ 'LitellmRegistryAmbiguousError',
42
+ )<{
43
+ readonly resource: string;
44
+ readonly name: string;
45
+ readonly ids: readonly string[];
46
+ }> {
47
+ override get message(): string {
48
+ return (
49
+ `${this.resource} "${this.name}": ${this.ids.length} live rows match (${this.ids.join(', ')}). ` +
50
+ 'Declare the id to choose one.'
51
+ );
52
+ }
53
+ }
54
+
55
+ /** A write returned no error, yet the row is not there on the read back. */
56
+ export class LitellmRegistryAbsentAfterWriteError extends Data.TaggedError(
57
+ 'LitellmRegistryAbsentAfterWriteError',
58
+ )<{
59
+ readonly resource: string;
60
+ readonly name: string;
61
+ }> {
62
+ override get message(): string {
63
+ return `${this.resource} "${this.name}": the write returned no error but the row is absent on the read back.`;
64
+ }
65
+ }
66
+
67
+ /**
68
+ * A write returned no error, yet the row still differs from the declaration. The route may merge with
69
+ * `exclude_none` or a truthiness check; the read back says so instead of reporting a converged row.
70
+ */
71
+ export class LitellmRegistryNotConvergedError extends Data.TaggedError(
72
+ 'LitellmRegistryNotConvergedError',
73
+ )<{
74
+ readonly resource: string;
75
+ readonly name: string;
76
+ readonly fields: readonly string[];
77
+ }> {
78
+ override get message(): string {
79
+ return `${this.resource} "${this.name}": after the write, the row still differs in ${this.fields.join(', ')}.`;
80
+ }
81
+ }
82
+
83
+ export type RegistryError =
84
+ | LitellmRegistryInvalidError
85
+ | LitellmRegistryUnreadableError
86
+ | LitellmRegistryAmbiguousError
87
+ | LitellmRegistryAbsentAfterWriteError
88
+ | LitellmRegistryNotConvergedError;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * The public barrel re-exports the six registry resources, their providers and guards, and the shared
3
+ * typed refusals. A missing name here is a runtime import failure for a consumer, and nothing else in
4
+ * the tests goes through `index.ts`.
5
+ */
6
+ import { expect, test } from 'bun:test';
7
+ import * as barrel from './index.ts';
8
+
9
+ const RESOURCES = [
10
+ ['LiteLLMTeam', 'isLiteLLMTeam', 'LiteLLM.Team', 'LiteLLMTeamProvider'],
11
+ [
12
+ 'LiteLLMAccessGroup',
13
+ 'isLiteLLMAccessGroup',
14
+ 'LiteLLM.AccessGroup',
15
+ 'LiteLLMAccessGroupProvider',
16
+ ],
17
+ ['LiteLLMToolset', 'isLiteLLMToolset', 'LiteLLM.Toolset', 'LiteLLMToolsetProvider'],
18
+ ['LiteLLMPolicy', 'isLiteLLMPolicy', 'LiteLLM.Policy', 'LiteLLMPolicyProvider'],
19
+ [
20
+ 'LiteLLMPolicyAttachment',
21
+ 'isLiteLLMPolicyAttachment',
22
+ 'LiteLLM.PolicyAttachment',
23
+ 'LiteLLMPolicyAttachmentProvider',
24
+ ],
25
+ ['LiteLLMToolPolicy', 'isLiteLLMToolPolicy', 'LiteLLM.ToolPolicy', 'LiteLLMToolPolicyProvider'],
26
+ ] as const;
27
+
28
+ test('every registry resource, guard and provider is on the barrel, and the guard tells its own type', () => {
29
+ const exported = barrel as unknown as Record<string, unknown>;
30
+ for (const [resource, guard, type, provider] of RESOURCES) {
31
+ expect(exported[resource]).toBeDefined();
32
+ expect(typeof exported[provider]).toBe('function');
33
+ const isType = exported[guard] as (value: unknown) => boolean;
34
+ expect(isType({ Type: type })).toBe(true);
35
+ expect(isType({ Type: 'LiteLLM.Budget' })).toBe(false);
36
+ expect(isType(undefined)).toBe(false);
37
+ }
38
+ });
39
+
40
+ test('the shared typed refusals are on the barrel and name their resource and subject', () => {
41
+ const invalid = new barrel.LitellmRegistryInvalidError({
42
+ name: 'FAKE-name',
43
+ problem: 'a problem',
44
+ resource: 'LiteLLM.Team',
45
+ });
46
+ expect(invalid._tag).toBe('LitellmRegistryInvalidError');
47
+ expect(invalid.message).toBe('LiteLLM.Team "FAKE-name": a problem.');
48
+ expect(
49
+ new barrel.LitellmRegistryNotConvergedError({
50
+ fields: ['models'],
51
+ name: 'FAKE-name',
52
+ resource: 'LiteLLM.Team',
53
+ }).message,
54
+ ).toContain('models');
55
+ for (const each of [
56
+ barrel.LitellmRegistryAbsentAfterWriteError,
57
+ barrel.LitellmRegistryAmbiguousError,
58
+ barrel.LitellmRegistryUnreadableError,
59
+ ]) {
60
+ expect(typeof each).toBe('function');
61
+ }
62
+ });
63
+
64
+ test('litellmProviders() builds a layer with every provider merged in', () => {
65
+ expect(barrel.litellmProviders()).toBeDefined();
66
+ });
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Small pure helpers the LiteLLM registry resources share (`LiteLLM.Team`, `AccessGroup`,
3
+ * `Toolset`, `Policy`, `PolicyAttachment`, `ToolPolicy`). Nothing here talks to a proxy.
4
+ *
5
+ * ★ WHY ONE FILE AND NOT ONE COPY PER RESOURCE: every one of these answers the same three
6
+ * questions about a `body: unknown` reply — "what is the payload", "is this list a set of rows",
7
+ * "is this failure a missing row" — and they must answer them the same way, or two resources
8
+ * disagree about what absence looks like.
9
+ * ⛔ NO MESSAGE OR STATUS SNIFFING (S21). `isNotFound` is a CLASS test against the SDK's own
10
+ * `NotFound`, never a `.status` or message match. These routes do not DECLARE 404 (only the
11
+ * `team_management` create/update/delete routes do, by distilled patch), but core's shared status
12
+ * map still decodes a 404 to that class at run time, invisible to the type checker
13
+ * (`mcp-server-operations.ts` says the same about its own by-id read). The typed fix is a distilled
14
+ * patch for each tag, which belongs in the distilled clone — never a catch by text here.
15
+ * ⚠️ WHICH CLASS A 404 DECODES TO DEPENDS ON THE TAG. Where the SDK DECLARES the status (a distilled
16
+ * patch: the `team_management` create, update and delete routes), the runtime error is that service
17
+ * module's OWN `NotFound`, a different class from the core one exported by `Errors`, and only
18
+ * `Effect.catchTag('NotFound')` sees it (`deleteTeam`). Where it is undeclared (`/team/info`,
19
+ * toolset and tool reads) it is core's, and this `instanceof` sees it. A later patch that declares
20
+ * 404 for one of those tags would move it to the other class and fail the tests here, which run every
21
+ * call through the real SDK decode, rather than silently reading "not found" as a failure.
22
+ */
23
+ import { NotFound } from '@distilled.cloud/litellm/Errors';
24
+ import * as Effect from 'effect/Effect';
25
+ import { LitellmRegistryInvalidError } from './registry-errors.ts';
26
+
27
+ /** Whether a failure is the SDK's `NotFound` class. A 401, a 500 or a dead network is never absence. */
28
+ export const isNotFound = (error: unknown): boolean => error instanceof NotFound;
29
+
30
+ /**
31
+ * ⚠️ The SDK types most of these answers `{ body: unknown }`, but hands a JSON array or object back as
32
+ * it came (measured through the fakes, as for `/budget/list`). Accept both shapes.
33
+ */
34
+ export const bodyOf = (response: unknown): unknown =>
35
+ typeof response === 'object' &&
36
+ response !== null &&
37
+ !Array.isArray(response) &&
38
+ 'body' in response
39
+ ? (response as { readonly body: unknown }).body
40
+ : response;
41
+
42
+ export type Row = Readonly<Record<string, unknown>>;
43
+
44
+ /** The value as a plain object, else `undefined`. An array is not a row. */
45
+ export const asRow = (value: unknown): Row | undefined =>
46
+ typeof value === 'object' && value !== null && !Array.isArray(value) ? (value as Row) : undefined;
47
+
48
+ /** The strings of a live list, in order. Anything else (`null`, a number) is skipped, never trusted. */
49
+ export const stringsOf = (value: unknown): readonly string[] =>
50
+ Array.isArray(value) ? value.filter((each): each is string => typeof each === 'string') : [];
51
+
52
+ /** `null` for anything that is not a string: a live column can hold `null`, and so can a proxy's JSON. */
53
+ export const stringOrNull = (value: unknown): string | null =>
54
+ typeof value === 'string' ? value : null;
55
+
56
+ /** `null` for anything that is not a finite number. Numeric strings (Prisma BigInt) are converted. */
57
+ export const numberOrNull = (value: unknown): number | null => {
58
+ if (value === null || value === undefined || value === '') return null;
59
+ const parsed = typeof value === 'number' ? value : Number(value);
60
+ return Number.isFinite(parsed) ? parsed : null;
61
+ };
62
+
63
+ /** Sorted, de-duplicated. Every list a resource compares is a SET, so this is its canonical form. */
64
+ export const canonical = (values: readonly string[]): readonly string[] =>
65
+ [...new Set(values)].sort();
66
+
67
+ export const sameSet = (left: readonly string[], right: readonly string[]): boolean => {
68
+ const a = canonical(left);
69
+ const b = canonical(right);
70
+ return a.length === b.length && a.every((each, index) => each === b[index]);
71
+ };
72
+
73
+ /** Whether a value is not a string with something in it. Takes `unknown`: a declaration can say anything. */
74
+ export const isBlank = (value: unknown): boolean =>
75
+ typeof value !== 'string' || value.trim() === '';
76
+
77
+ /** The first blank or padded entry of a declared list, or `undefined`. Padding is refused too: it is a typo. */
78
+ export const firstBadEntry = (values: readonly unknown[]): string | undefined => {
79
+ for (const each of values) {
80
+ if (isBlank(each) || (each as string) !== (each as string).trim()) return String(each);
81
+ }
82
+ return undefined;
83
+ };
84
+
85
+ /** A list that names one entry twice. Refused rather than silently collapsed: the twin is a typo. */
86
+ export const firstDuplicate = (values: readonly string[]): string | undefined =>
87
+ values.find((each, index) => values.indexOf(each) !== index);
88
+
89
+ /**
90
+ * A refusal as a TYPED FAILURE. Used in `diff` and `reconcile`, where a failure blocks that one
91
+ * resource with a message.
92
+ */
93
+ export const failIfInvalid = (resource: string, name: string, problem: string | undefined) =>
94
+ problem === undefined
95
+ ? Effect.void
96
+ : Effect.fail(new LitellmRegistryInvalidError({ name, problem, resource }));
97
+
98
+ /**
99
+ * The same refusal as a DEFECT, for `read` with no `output` — Alchemy's adoption probe and the ONLY
100
+ * plan-time hook a brand-new declaration gets (`mcp-server.ts` measured this on beta.79, `Plan.ts`
101
+ * lines 1303-1316). ★ A defect and not a typed failure because the same call shape is Alchemy's
102
+ * recovery read of an interrupted create with the STORED props, where only a defect is caught
103
+ * (`Effect.catchDefect`); a typed failure would wedge a stage on props a later, stricter release now
104
+ * refuses. The cold-start probe has no such catch, so there the defect fails the plan, as intended.
105
+ */
106
+ export const dieIfInvalid = (resource: string, name: string, problem: string | undefined) =>
107
+ problem === undefined
108
+ ? Effect.void
109
+ : Effect.die(new LitellmRegistryInvalidError({ name, problem, resource }));
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Wire bodies, comparison and refusals for `LiteLLM.Team`, testable without a server. The object
3
+ * permission is team-permission.ts, the roster team-members.ts.
4
+ *
5
+ * ★ THE UPDATE IS A PARTIAL ONE (`/team/update` builds its write from `data.json(exclude_unset=True)`,
6
+ * `team_endpoints.py` line 2418, 1.103.0), so it sends the team id and ONLY what differs. Nothing
7
+ * here sends `metadata`, a budget, a limit or any Enterprise field.
8
+ * ★ THE READ IS `/team/info`, and it returns the team's OWN columns: access-group grants are resolved
9
+ * into separate `access_group_*` fields (`_resolve_team_access_group_resources`), never merged into
10
+ * `models` or `object_permission`, so a group cannot make a team look as if it declared a model.
11
+ */
12
+ import type * as team from '@distilled.cloud/litellm/team_management';
13
+ import {
14
+ asRow,
15
+ canonical,
16
+ firstBadEntry,
17
+ firstDuplicate,
18
+ isBlank,
19
+ sameSet,
20
+ stringsOf,
21
+ } from './registry-support.ts';
22
+ import { rosterPending, toMemberAttributes } from './team-members.ts';
23
+ import {
24
+ permissionBody,
25
+ permissionDiffers,
26
+ permissionProblem,
27
+ toPermissionAttributes,
28
+ } from './team-permission.ts';
29
+ import type { TeamAttributes, TeamProps } from './team-types.ts';
30
+
31
+ /** The first reason a declaration is refused, or `undefined`. Runs before any request. */
32
+ export const firstProblem = (props: TeamProps): string | undefined => {
33
+ if (isBlank(props.teamAlias) || props.teamAlias !== props.teamAlias.trim()) {
34
+ return '`teamAlias` must be a non-blank name with no leading or trailing space';
35
+ }
36
+ if (
37
+ props.teamId !== undefined &&
38
+ (isBlank(props.teamId) || props.teamId !== props.teamId.trim())
39
+ ) {
40
+ return '`teamId` must be a non-blank id with no leading or trailing space';
41
+ }
42
+ for (const [field, values] of [
43
+ ['models', props.models ?? []],
44
+ ['accessGroupIds', props.accessGroupIds ?? []],
45
+ ] as const) {
46
+ const bad = firstBadEntry(values);
47
+ if (bad !== undefined)
48
+ return `\`${field}\` has a blank or padded entry (${JSON.stringify(bad)})`;
49
+ const twice = firstDuplicate(values);
50
+ if (twice !== undefined) return `\`${field}\` lists ${JSON.stringify(twice)} twice`;
51
+ }
52
+ const ids = (props.members ?? []).map((member) => member.userId);
53
+ const badId = firstBadEntry(ids);
54
+ if (badId !== undefined)
55
+ return `\`members\` has a blank or padded userId (${JSON.stringify(badId)})`;
56
+ const twiceId = firstDuplicate(ids);
57
+ if (twiceId !== undefined) return `\`members\` lists ${JSON.stringify(twiceId)} twice`;
58
+ for (const member of props.members ?? []) {
59
+ if (member.role !== undefined && member.role !== 'user' && member.role !== 'admin') {
60
+ return `member ${member.userId} has a role other than user or admin`;
61
+ }
62
+ }
63
+ return permissionProblem(props.objectPermission);
64
+ };
65
+
66
+ /** One `team_info` row. `undefined` is "not a team": the caller refuses the whole answer. */
67
+ export const toAttributes = (value: unknown): TeamAttributes | undefined => {
68
+ const row = asRow(asRow(value)?.['team_info']);
69
+ if (row === undefined) return undefined;
70
+ const teamId = row['team_id'];
71
+ if (typeof teamId !== 'string') return undefined;
72
+ return {
73
+ accessGroupIds: canonical(stringsOf(row['access_group_ids'])),
74
+ blocked: row['blocked'] === true,
75
+ members: toMemberAttributes(row['members_with_roles']),
76
+ models: canonical(stringsOf(row['models'])),
77
+ objectPermission: toPermissionAttributes(row['object_permission']),
78
+ teamAlias: typeof row['team_alias'] === 'string' ? row['team_alias'] : '',
79
+ teamId,
80
+ };
81
+ };
82
+
83
+ /** The team's own fields (never the roster) where live and declared disagree, by wire name. */
84
+ export const teamFieldsDiffering = (live: TeamAttributes, props: TeamProps): readonly string[] => {
85
+ const fields: string[] = [];
86
+ if (live.teamAlias !== props.teamAlias) fields.push('team_alias');
87
+ if (props.models !== undefined && !sameSet(live.models, props.models)) fields.push('models');
88
+ if (props.blocked !== undefined && live.blocked !== props.blocked) fields.push('blocked');
89
+ if (props.accessGroupIds !== undefined && !sameSet(live.accessGroupIds, props.accessGroupIds)) {
90
+ fields.push('access_group_ids');
91
+ }
92
+ for (const wire of permissionDiffers(live.objectPermission, props.objectPermission)) {
93
+ fields.push(`object_permission.${wire}`);
94
+ }
95
+ return fields;
96
+ };
97
+
98
+ /** Everything that differs, the roster included. Empty means converged. */
99
+ export const differing = (live: TeamAttributes, props: TeamProps): readonly string[] => [
100
+ ...teamFieldsDiffering(live, props),
101
+ ...(rosterPending(live.members, props.members) ? ['members'] : []),
102
+ ];
103
+
104
+ /** Create body: every declared team field. The roster is added afterwards, through `member_add`. */
105
+ export const createBody = (props: TeamProps, teamId: string): team.PostNewTeamTeamNewRequest => ({
106
+ team_alias: props.teamAlias,
107
+ team_id: teamId,
108
+ ...(props.models === undefined ? {} : { models: [...props.models] }),
109
+ ...(props.blocked === undefined ? {} : { blocked: props.blocked }),
110
+ ...(props.accessGroupIds === undefined ? {} : { access_group_ids: [...props.accessGroupIds] }),
111
+ ...(props.objectPermission === undefined
112
+ ? {}
113
+ : { object_permission: permissionBody(props.objectPermission) }),
114
+ });
115
+
116
+ /** Update body: the team id and only the fields that differ. `undefined` when nothing but the roster does. */
117
+ export const updateBody = (
118
+ props: TeamProps,
119
+ live: TeamAttributes,
120
+ ): team.UpdateTeamTeamUpdatePostRequest | undefined => {
121
+ const changed = new Set(teamFieldsDiffering(live, props));
122
+ if (changed.size === 0) return undefined;
123
+ const permission = new Set(
124
+ [...changed]
125
+ .filter((field) => field.startsWith('object_permission.'))
126
+ .map((field) => field.slice(18)),
127
+ );
128
+ return {
129
+ team_id: live.teamId,
130
+ ...(changed.has('team_alias') ? { team_alias: props.teamAlias } : {}),
131
+ ...(changed.has('models') ? { models: [...(props.models ?? [])] } : {}),
132
+ ...(changed.has('blocked') ? { blocked: props.blocked ?? false } : {}),
133
+ ...(changed.has('access_group_ids')
134
+ ? { access_group_ids: [...(props.accessGroupIds ?? [])] }
135
+ : {}),
136
+ ...(props.objectPermission !== undefined && permission.size > 0
137
+ ? { object_permission: permissionBody(props.objectPermission, permission) }
138
+ : {}),
139
+ };
140
+ };