@homeflare/alchemy 0.43.0 → 0.44.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.
- package/README.md +10 -1
- package/dist/caddy/index.js +35 -1
- package/dist/caddy/index.js.map +3 -3
- package/dist/launchd/index.js +35 -1
- package/dist/launchd/index.js.map +3 -3
- package/dist/linux/index.js +35 -1
- package/dist/linux/index.js.map +3 -3
- package/dist/litellm/access-group-form.d.ts +26 -0
- package/dist/litellm/access-group-form.d.ts.map +1 -0
- package/dist/litellm/access-group-operations.d.ts +37 -0
- package/dist/litellm/access-group-operations.d.ts.map +1 -0
- package/dist/litellm/access-group-types.d.ts +49 -0
- package/dist/litellm/access-group-types.d.ts.map +1 -0
- package/dist/litellm/access-group.d.ts +55 -0
- package/dist/litellm/access-group.d.ts.map +1 -0
- package/dist/litellm/credential-errors.d.ts +131 -0
- package/dist/litellm/credential-errors.d.ts.map +1 -0
- package/dist/litellm/credential-form.d.ts +79 -0
- package/dist/litellm/credential-form.d.ts.map +1 -0
- package/dist/litellm/credential-operations.d.ts +84 -0
- package/dist/litellm/credential-operations.d.ts.map +1 -0
- package/dist/litellm/credential-rewrite.d.ts +6 -0
- package/dist/litellm/credential-rewrite.d.ts.map +1 -0
- package/dist/litellm/credential-types.d.ts +87 -0
- package/dist/litellm/credential-types.d.ts.map +1 -0
- package/dist/litellm/credential-values.d.ts +53 -0
- package/dist/litellm/credential-values.d.ts.map +1 -0
- package/dist/litellm/credential.d.ts +83 -0
- package/dist/litellm/credential.d.ts.map +1 -0
- package/dist/litellm/fake-access-group-litellm.d.ts +34 -0
- package/dist/litellm/fake-access-group-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-credential-litellm.d.ts +54 -0
- package/dist/litellm/fake-credential-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-keys.d.ts +53 -0
- package/dist/litellm/fake-keys.d.ts.map +1 -0
- package/dist/litellm/fake-litellm.d.ts +4 -1
- package/dist/litellm/fake-litellm.d.ts.map +1 -1
- package/dist/litellm/fake-mcp-litellm.d.ts +67 -0
- package/dist/litellm/fake-mcp-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-model-litellm-post-update.d.ts +49 -0
- package/dist/litellm/fake-model-litellm-post-update.d.ts.map +1 -0
- package/dist/litellm/fake-model-litellm.d.ts +48 -0
- package/dist/litellm/fake-model-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-policy-attachment-litellm.d.ts +33 -0
- package/dist/litellm/fake-policy-attachment-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-policy-litellm.d.ts +32 -0
- package/dist/litellm/fake-policy-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-registry-base.d.ts +42 -0
- package/dist/litellm/fake-registry-base.d.ts.map +1 -0
- package/dist/litellm/fake-stack.d.ts +8 -1
- package/dist/litellm/fake-stack.d.ts.map +1 -1
- package/dist/litellm/fake-team-litellm.d.ts +47 -0
- package/dist/litellm/fake-team-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-tool-litellm.d.ts +28 -0
- package/dist/litellm/fake-tool-litellm.d.ts.map +1 -0
- package/dist/litellm/fake-toolset-litellm.d.ts +29 -0
- package/dist/litellm/fake-toolset-litellm.d.ts.map +1 -0
- package/dist/litellm/index.d.ts +18 -0
- package/dist/litellm/index.d.ts.map +1 -1
- package/dist/litellm/index.js +3078 -2
- package/dist/litellm/index.js.map +65 -4
- package/dist/litellm/key-errors.d.ts +169 -0
- package/dist/litellm/key-errors.d.ts.map +1 -0
- package/dist/litellm/key-form.d.ts +119 -0
- package/dist/litellm/key-form.d.ts.map +1 -0
- package/dist/litellm/key-harness.d.ts +41 -0
- package/dist/litellm/key-harness.d.ts.map +1 -0
- package/dist/litellm/key-metadata-errors.d.ts +30 -0
- package/dist/litellm/key-metadata-errors.d.ts.map +1 -0
- package/dist/litellm/key-metadata.d.ts +22 -0
- package/dist/litellm/key-metadata.d.ts.map +1 -0
- package/dist/litellm/key-operations.d.ts +63 -0
- package/dist/litellm/key-operations.d.ts.map +1 -0
- package/dist/litellm/key-secret.d.ts +33 -0
- package/dist/litellm/key-secret.d.ts.map +1 -0
- package/dist/litellm/key.d.ts +78 -0
- package/dist/litellm/key.d.ts.map +1 -0
- package/dist/litellm/mcp-server-credential.d.ts +50 -0
- package/dist/litellm/mcp-server-credential.d.ts.map +1 -0
- package/dist/litellm/mcp-server-errors.d.ts +101 -0
- package/dist/litellm/mcp-server-errors.d.ts.map +1 -0
- package/dist/litellm/mcp-server-form.d.ts +56 -0
- package/dist/litellm/mcp-server-form.d.ts.map +1 -0
- package/dist/litellm/mcp-server-locate.d.ts +26 -0
- package/dist/litellm/mcp-server-locate.d.ts.map +1 -0
- package/dist/litellm/mcp-server-operations.d.ts +63 -0
- package/dist/litellm/mcp-server-operations.d.ts.map +1 -0
- package/dist/litellm/mcp-server-shadow.d.ts +24 -0
- package/dist/litellm/mcp-server-shadow.d.ts.map +1 -0
- package/dist/litellm/mcp-server-types.d.ts +118 -0
- package/dist/litellm/mcp-server-types.d.ts.map +1 -0
- package/dist/litellm/mcp-server-url.d.ts +11 -0
- package/dist/litellm/mcp-server-url.d.ts.map +1 -0
- package/dist/litellm/mcp-server.d.ts +95 -0
- package/dist/litellm/mcp-server.d.ts.map +1 -0
- package/dist/litellm/model-claim.d.ts +24 -0
- package/dist/litellm/model-claim.d.ts.map +1 -0
- package/dist/litellm/model-credential.d.ts +12 -0
- package/dist/litellm/model-credential.d.ts.map +1 -0
- package/dist/litellm/model-errors.d.ts +119 -0
- package/dist/litellm/model-errors.d.ts.map +1 -0
- package/dist/litellm/model-form.d.ts +78 -0
- package/dist/litellm/model-form.d.ts.map +1 -0
- package/dist/litellm/model-locate.d.ts +13 -0
- package/dist/litellm/model-locate.d.ts.map +1 -0
- package/dist/litellm/model-operations.d.ts +59 -0
- package/dist/litellm/model-operations.d.ts.map +1 -0
- package/dist/litellm/model-types.d.ts +91 -0
- package/dist/litellm/model-types.d.ts.map +1 -0
- package/dist/litellm/model.d.ts +88 -0
- package/dist/litellm/model.d.ts.map +1 -0
- package/dist/litellm/policy-attachment-form.d.ts +19 -0
- package/dist/litellm/policy-attachment-form.d.ts.map +1 -0
- package/dist/litellm/policy-attachment-operations.d.ts +31 -0
- package/dist/litellm/policy-attachment-operations.d.ts.map +1 -0
- package/dist/litellm/policy-attachment-types.d.ts +48 -0
- package/dist/litellm/policy-attachment-types.d.ts.map +1 -0
- package/dist/litellm/policy-attachment.d.ts +61 -0
- package/dist/litellm/policy-attachment.d.ts.map +1 -0
- package/dist/litellm/policy-form.d.ts +22 -0
- package/dist/litellm/policy-form.d.ts.map +1 -0
- package/dist/litellm/policy-operations.d.ts +42 -0
- package/dist/litellm/policy-operations.d.ts.map +1 -0
- package/dist/litellm/policy-types.d.ts +57 -0
- package/dist/litellm/policy-types.d.ts.map +1 -0
- package/dist/litellm/policy.d.ts +65 -0
- package/dist/litellm/policy.d.ts.map +1 -0
- package/dist/litellm/providers.d.ts +1 -1
- package/dist/litellm/providers.d.ts.map +1 -1
- package/dist/litellm/registry-errors.d.ts +62 -0
- package/dist/litellm/registry-errors.d.ts.map +1 -0
- package/dist/litellm/registry-support.d.ts +42 -0
- package/dist/litellm/registry-support.d.ts.map +1 -0
- package/dist/litellm/team-form.d.ts +26 -0
- package/dist/litellm/team-form.d.ts.map +1 -0
- package/dist/litellm/team-members.d.ts +10 -0
- package/dist/litellm/team-members.d.ts.map +1 -0
- package/dist/litellm/team-operations.d.ts +38 -0
- package/dist/litellm/team-operations.d.ts.map +1 -0
- package/dist/litellm/team-permission.d.ts +35 -0
- package/dist/litellm/team-permission.d.ts.map +1 -0
- package/dist/litellm/team-types.d.ts +101 -0
- package/dist/litellm/team-types.d.ts.map +1 -0
- package/dist/litellm/team.d.ts +67 -0
- package/dist/litellm/team.d.ts.map +1 -0
- package/dist/litellm/tool-policy-form.d.ts +21 -0
- package/dist/litellm/tool-policy-form.d.ts.map +1 -0
- package/dist/litellm/tool-policy-operations.d.ts +30 -0
- package/dist/litellm/tool-policy-operations.d.ts.map +1 -0
- package/dist/litellm/tool-policy-types.d.ts +46 -0
- package/dist/litellm/tool-policy-types.d.ts.map +1 -0
- package/dist/litellm/tool-policy.d.ts +62 -0
- package/dist/litellm/tool-policy.d.ts.map +1 -0
- package/dist/litellm/toolset-form.d.ts +20 -0
- package/dist/litellm/toolset-form.d.ts.map +1 -0
- package/dist/litellm/toolset-operations.d.ts +39 -0
- package/dist/litellm/toolset-operations.d.ts.map +1 -0
- package/dist/litellm/toolset-types.d.ts +46 -0
- package/dist/litellm/toolset-types.d.ts.map +1 -0
- package/dist/litellm/toolset.d.ts +55 -0
- package/dist/litellm/toolset.d.ts.map +1 -0
- package/dist/openbao/index.js +35 -1
- package/dist/openbao/index.js.map +3 -3
- package/dist/ownership/rows.d.ts +11 -0
- package/dist/ownership/rows.d.ts.map +1 -1
- package/dist/postgres/connection.d.ts +14 -2
- package/dist/postgres/connection.d.ts.map +1 -1
- package/dist/postgres/database-sql.d.ts +27 -8
- package/dist/postgres/database-sql.d.ts.map +1 -1
- package/dist/postgres/fake-grants-parse.d.ts +37 -0
- package/dist/postgres/fake-grants-parse.d.ts.map +1 -0
- package/dist/postgres/fake-grants-read.d.ts +61 -0
- package/dist/postgres/fake-grants-read.d.ts.map +1 -0
- package/dist/postgres/fake-grants-sql.d.ts +46 -0
- package/dist/postgres/fake-grants-sql.d.ts.map +1 -0
- package/dist/postgres/fake-grants-write.d.ts +29 -0
- package/dist/postgres/fake-grants-write.d.ts.map +1 -0
- package/dist/postgres/fake-role-sql.d.ts +40 -0
- package/dist/postgres/fake-role-sql.d.ts.map +1 -0
- package/dist/postgres/fake-schema-sql.d.ts +42 -0
- package/dist/postgres/fake-schema-sql.d.ts.map +1 -0
- package/dist/postgres/fake-sql-parse.d.ts +23 -0
- package/dist/postgres/fake-sql-parse.d.ts.map +1 -0
- package/dist/postgres/fake-sql-quote.d.ts +12 -0
- package/dist/postgres/fake-sql-quote.d.ts.map +1 -0
- package/dist/postgres/fake-sql.d.ts +42 -0
- package/dist/postgres/fake-sql.d.ts.map +1 -1
- package/dist/postgres/grants-attrs.d.ts +115 -0
- package/dist/postgres/grants-attrs.d.ts.map +1 -0
- package/dist/postgres/grants-declare.d.ts +88 -0
- package/dist/postgres/grants-declare.d.ts.map +1 -0
- package/dist/postgres/grants-diff.d.ts +25 -0
- package/dist/postgres/grants-diff.d.ts.map +1 -0
- package/dist/postgres/grants-errors.d.ts +137 -0
- package/dist/postgres/grants-errors.d.ts.map +1 -0
- package/dist/postgres/grants-existence.d.ts +14 -0
- package/dist/postgres/grants-existence.d.ts.map +1 -0
- package/dist/postgres/grants-ops.d.ts +65 -0
- package/dist/postgres/grants-ops.d.ts.map +1 -0
- package/dist/postgres/grants-ownership.d.ts +18 -0
- package/dist/postgres/grants-ownership.d.ts.map +1 -0
- package/dist/postgres/grants-plan-restore.d.ts +22 -0
- package/dist/postgres/grants-plan-restore.d.ts.map +1 -0
- package/dist/postgres/grants-plan.d.ts +65 -0
- package/dist/postgres/grants-plan.d.ts.map +1 -0
- package/dist/postgres/grants-read-defaults.d.ts +17 -0
- package/dist/postgres/grants-read-defaults.d.ts.map +1 -0
- package/dist/postgres/grants-read.d.ts +77 -0
- package/dist/postgres/grants-read.d.ts.map +1 -0
- package/dist/postgres/grants-refuse.d.ts +25 -0
- package/dist/postgres/grants-refuse.d.ts.map +1 -0
- package/dist/postgres/grants-sql.d.ts +42 -0
- package/dist/postgres/grants-sql.d.ts.map +1 -0
- package/dist/postgres/grants-words.d.ts +29 -0
- package/dist/postgres/grants-words.d.ts.map +1 -0
- package/dist/postgres/grants.d.ts +37 -0
- package/dist/postgres/grants.d.ts.map +1 -0
- package/dist/postgres/index.d.ts +31 -6
- package/dist/postgres/index.d.ts.map +1 -1
- package/dist/postgres/index.js +1975 -37
- package/dist/postgres/index.js.map +46 -7
- package/dist/postgres/installed-classifier.d.ts +13 -0
- package/dist/postgres/installed-classifier.d.ts.map +1 -0
- package/dist/postgres/providers.d.ts +16 -8
- package/dist/postgres/providers.d.ts.map +1 -1
- package/dist/postgres/psql-executor.d.ts +4 -0
- package/dist/postgres/psql-executor.d.ts.map +1 -1
- package/dist/postgres/role-attrs.d.ts +109 -0
- package/dist/postgres/role-attrs.d.ts.map +1 -0
- package/dist/postgres/role-diff.d.ts +22 -0
- package/dist/postgres/role-diff.d.ts.map +1 -0
- package/dist/postgres/role-errors.d.ts +126 -0
- package/dist/postgres/role-errors.d.ts.map +1 -0
- package/dist/postgres/role-membership-sql.d.ts +75 -0
- package/dist/postgres/role-membership-sql.d.ts.map +1 -0
- package/dist/postgres/role-provider.d.ts +11 -0
- package/dist/postgres/role-provider.d.ts.map +1 -0
- package/dist/postgres/role-scram.d.ts +6 -0
- package/dist/postgres/role-scram.d.ts.map +1 -0
- package/dist/postgres/role-secrets.d.ts +30 -0
- package/dist/postgres/role-secrets.d.ts.map +1 -0
- package/dist/postgres/role-sql.d.ts +68 -0
- package/dist/postgres/role-sql.d.ts.map +1 -0
- package/dist/postgres/role.d.ts +57 -0
- package/dist/postgres/role.d.ts.map +1 -0
- package/dist/postgres/schema-assert.d.ts +50 -0
- package/dist/postgres/schema-assert.d.ts.map +1 -0
- package/dist/postgres/schema-attrs.d.ts +51 -0
- package/dist/postgres/schema-attrs.d.ts.map +1 -0
- package/dist/postgres/schema-delete.d.ts +28 -0
- package/dist/postgres/schema-delete.d.ts.map +1 -0
- package/dist/postgres/schema-diff.d.ts +14 -0
- package/dist/postgres/schema-diff.d.ts.map +1 -0
- package/dist/postgres/schema-errors.d.ts +139 -0
- package/dist/postgres/schema-errors.d.ts.map +1 -0
- package/dist/postgres/schema-identity.d.ts +8 -0
- package/dist/postgres/schema-identity.d.ts.map +1 -0
- package/dist/postgres/schema-reconcile.d.ts +12 -0
- package/dist/postgres/schema-reconcile.d.ts.map +1 -0
- package/dist/postgres/schema-sql.d.ts +45 -0
- package/dist/postgres/schema-sql.d.ts.map +1 -0
- package/dist/postgres/schema-test-kit.d.ts +67 -0
- package/dist/postgres/schema-test-kit.d.ts.map +1 -0
- package/dist/postgres/schema.d.ts +54 -0
- package/dist/postgres/schema.d.ts.map +1 -0
- package/dist/proxmox/index.js +35 -1
- package/dist/proxmox/index.js.map +3 -3
- package/dist/release/fake-engine.d.ts +10 -0
- package/dist/release/fake-engine.d.ts.map +1 -1
- package/dist/release/index.js +35 -1
- package/dist/release/index.js.map +3 -3
- package/dist/valkey/acl-attrs.d.ts +94 -0
- package/dist/valkey/acl-attrs.d.ts.map +1 -0
- package/dist/valkey/acl-compare.d.ts +28 -0
- package/dist/valkey/acl-compare.d.ts.map +1 -0
- package/dist/valkey/acl-connection.d.ts +6 -0
- package/dist/valkey/acl-connection.d.ts.map +1 -0
- package/dist/valkey/acl-form.d.ts +62 -0
- package/dist/valkey/acl-form.d.ts.map +1 -0
- package/dist/valkey/acl-managed.d.ts +4 -0
- package/dist/valkey/acl-managed.d.ts.map +1 -0
- package/dist/valkey/acl-ops.d.ts +37 -0
- package/dist/valkey/acl-ops.d.ts.map +1 -0
- package/dist/valkey/acl-profiles.d.ts +53 -0
- package/dist/valkey/acl-profiles.d.ts.map +1 -0
- package/dist/valkey/acl-reconcile.d.ts +26 -0
- package/dist/valkey/acl-reconcile.d.ts.map +1 -0
- package/dist/valkey/acl.d.ts +24 -0
- package/dist/valkey/acl.d.ts.map +1 -0
- package/dist/valkey/connection-service.d.ts +22 -0
- package/dist/valkey/connection-service.d.ts.map +1 -0
- package/dist/valkey/connection.d.ts +59 -0
- package/dist/valkey/connection.d.ts.map +1 -0
- package/dist/valkey/errors.d.ts +165 -0
- package/dist/valkey/errors.d.ts.map +1 -0
- package/dist/valkey/fake-acl.d.ts +29 -0
- package/dist/valkey/fake-acl.d.ts.map +1 -0
- package/dist/valkey/fake-valkey.d.ts +35 -0
- package/dist/valkey/fake-valkey.d.ts.map +1 -0
- package/dist/valkey/handler-test-fixture.d.ts +20 -0
- package/dist/valkey/handler-test-fixture.d.ts.map +1 -0
- package/dist/valkey/index.d.ts +18 -0
- package/dist/valkey/index.d.ts.map +1 -0
- package/dist/valkey/index.js +964 -0
- package/dist/valkey/index.js.map +27 -0
- package/dist/valkey/instance-attrs.d.ts +46 -0
- package/dist/valkey/instance-attrs.d.ts.map +1 -0
- package/dist/valkey/instance-form.d.ts +22 -0
- package/dist/valkey/instance-form.d.ts.map +1 -0
- package/dist/valkey/instance.d.ts +48 -0
- package/dist/valkey/instance.d.ts.map +1 -0
- package/dist/valkey/provider-socket-fixture.d.ts +8 -0
- package/dist/valkey/provider-socket-fixture.d.ts.map +1 -0
- package/dist/valkey/providers.d.ts +16 -0
- package/dist/valkey/providers.d.ts.map +1 -0
- package/dist/valkey/resp.d.ts +38 -0
- package/dist/valkey/resp.d.ts.map +1 -0
- package/dist/valkey/transport-error.d.ts +36 -0
- package/dist/valkey/transport-error.d.ts.map +1 -0
- package/dist/valkey/transport.d.ts +50 -0
- package/dist/valkey/transport.d.ts.map +1 -0
- package/docs/litellm-access-group.md +105 -0
- package/docs/litellm-credential.md +60 -0
- package/docs/litellm-key-metadata.md +56 -0
- package/docs/litellm-key.md +194 -0
- package/docs/litellm-mcp.md +187 -0
- package/docs/litellm-model.md +111 -0
- package/docs/litellm-policy-attachment.md +86 -0
- package/docs/litellm-policy.md +103 -0
- package/docs/litellm-team.md +117 -0
- package/docs/litellm-tool-policy.md +90 -0
- package/docs/litellm-toolset.md +92 -0
- package/docs/litellm.md +16 -9
- package/docs/peers.md +15 -6
- package/docs/postgres-grants-example.md +55 -0
- package/docs/postgres-grants.md +157 -0
- package/docs/postgres-role.md +114 -0
- package/docs/postgres-schema.md +139 -0
- package/docs/postgres.md +20 -3
- package/docs/valkey-transport.md +29 -0
- package/docs/valkey.md +187 -0
- package/package.json +6 -2
- package/src/litellm/access-group-form.ts +105 -0
- package/src/litellm/access-group-operations.ts +92 -0
- package/src/litellm/access-group-types.ts +49 -0
- package/src/litellm/access-group.test.ts +197 -0
- package/src/litellm/access-group.ts +151 -0
- package/src/litellm/credential-errors.ts +183 -0
- package/src/litellm/credential-form.test.ts +151 -0
- package/src/litellm/credential-form.ts +211 -0
- package/src/litellm/credential-guards.test.ts +241 -0
- package/src/litellm/credential-operations.ts +208 -0
- package/src/litellm/credential-recovery.test.ts +93 -0
- package/src/litellm/credential-rewrite.test.ts +164 -0
- package/src/litellm/credential-rewrite.ts +50 -0
- package/src/litellm/credential-types.ts +117 -0
- package/src/litellm/credential-values.ts +94 -0
- package/src/litellm/credential.test.ts +218 -0
- package/src/litellm/credential.ts +227 -0
- package/src/litellm/fake-access-group-litellm.ts +127 -0
- package/src/litellm/fake-credential-litellm.ts +216 -0
- package/src/litellm/fake-keys.ts +190 -0
- package/src/litellm/fake-litellm.ts +19 -9
- package/src/litellm/fake-mcp-litellm.ts +214 -0
- package/src/litellm/fake-model-litellm-post-update.ts +103 -0
- package/src/litellm/fake-model-litellm.ts +233 -0
- package/src/litellm/fake-policy-attachment-litellm.ts +97 -0
- package/src/litellm/fake-policy-litellm.ts +186 -0
- package/src/litellm/fake-registry-base.ts +69 -0
- package/src/litellm/fake-stack.ts +17 -1
- package/src/litellm/fake-team-litellm.ts +229 -0
- package/src/litellm/fake-tool-litellm.ts +88 -0
- package/src/litellm/fake-toolset-litellm.ts +110 -0
- package/src/litellm/index.ts +140 -0
- package/src/litellm/key-delete.test.ts +212 -0
- package/src/litellm/key-errors.ts +241 -0
- package/src/litellm/key-form.ts +200 -0
- package/src/litellm/key-harness.ts +121 -0
- package/src/litellm/key-metadata-errors.ts +49 -0
- package/src/litellm/key-metadata.test.ts +156 -0
- package/src/litellm/key-metadata.ts +74 -0
- package/src/litellm/key-operations.ts +184 -0
- package/src/litellm/key-rotation.test.ts +110 -0
- package/src/litellm/key-scope.test.ts +135 -0
- package/src/litellm/key-secret.test.ts +248 -0
- package/src/litellm/key-secret.ts +137 -0
- package/src/litellm/key-transport.test.ts +166 -0
- package/src/litellm/key.test.ts +231 -0
- package/src/litellm/key.ts +213 -0
- package/src/litellm/mcp-server-adopt.test.ts +86 -0
- package/src/litellm/mcp-server-alias.test.ts +184 -0
- package/src/litellm/mcp-server-credential.ts +85 -0
- package/src/litellm/mcp-server-errors.ts +141 -0
- package/src/litellm/mcp-server-exports.test.ts +15 -0
- package/src/litellm/mcp-server-form.test.ts +241 -0
- package/src/litellm/mcp-server-form.ts +233 -0
- package/src/litellm/mcp-server-handlers.test.ts +150 -0
- package/src/litellm/mcp-server-locate.ts +66 -0
- package/src/litellm/mcp-server-operations.ts +111 -0
- package/src/litellm/mcp-server-registry.test.ts +146 -0
- package/src/litellm/mcp-server-retype.test.ts +114 -0
- package/src/litellm/mcp-server-shadow.test.ts +91 -0
- package/src/litellm/mcp-server-shadow.ts +45 -0
- package/src/litellm/mcp-server-tools.test.ts +85 -0
- package/src/litellm/mcp-server-types.ts +143 -0
- package/src/litellm/mcp-server-url.ts +66 -0
- package/src/litellm/mcp-server.test.ts +213 -0
- package/src/litellm/mcp-server.ts +225 -0
- package/src/litellm/model-claim.ts +69 -0
- package/src/litellm/model-credential.ts +45 -0
- package/src/litellm/model-errors.ts +168 -0
- package/src/litellm/model-foreign-row.test.ts +173 -0
- package/src/litellm/model-form.test.ts +228 -0
- package/src/litellm/model-form.ts +223 -0
- package/src/litellm/model-locate.test.ts +128 -0
- package/src/litellm/model-locate.ts +67 -0
- package/src/litellm/model-operations.test.ts +93 -0
- package/src/litellm/model-operations.ts +146 -0
- package/src/litellm/model-params-preserve.test.ts +119 -0
- package/src/litellm/model-recovery.test.ts +57 -0
- package/src/litellm/model-types.ts +112 -0
- package/src/litellm/model.test.ts +222 -0
- package/src/litellm/model.ts +237 -0
- package/src/litellm/policy-attachment-form.ts +103 -0
- package/src/litellm/policy-attachment-operations.ts +74 -0
- package/src/litellm/policy-attachment-types.ts +48 -0
- package/src/litellm/policy-attachment.test.ts +198 -0
- package/src/litellm/policy-attachment.ts +178 -0
- package/src/litellm/policy-form.ts +122 -0
- package/src/litellm/policy-operations.ts +112 -0
- package/src/litellm/policy-types.ts +58 -0
- package/src/litellm/policy.test.ts +214 -0
- package/src/litellm/policy.ts +146 -0
- package/src/litellm/providers.ts +24 -3
- package/src/litellm/registry-errors.ts +88 -0
- package/src/litellm/registry-exports.test.ts +66 -0
- package/src/litellm/registry-support.ts +109 -0
- package/src/litellm/team-form.ts +140 -0
- package/src/litellm/team-members.test.ts +150 -0
- package/src/litellm/team-members.ts +58 -0
- package/src/litellm/team-operations.ts +90 -0
- package/src/litellm/team-permission.ts +159 -0
- package/src/litellm/team-read.test.ts +89 -0
- package/src/litellm/team-types.ts +106 -0
- package/src/litellm/team.test.ts +206 -0
- package/src/litellm/team.ts +159 -0
- package/src/litellm/tool-policy-form.ts +94 -0
- package/src/litellm/tool-policy-operations.ts +58 -0
- package/src/litellm/tool-policy-types.ts +48 -0
- package/src/litellm/tool-policy.test.ts +172 -0
- package/src/litellm/tool-policy.ts +125 -0
- package/src/litellm/toolset-form.ts +104 -0
- package/src/litellm/toolset-operations.ts +90 -0
- package/src/litellm/toolset-types.ts +47 -0
- package/src/litellm/toolset.test.ts +198 -0
- package/src/litellm/toolset.ts +151 -0
- package/src/ownership/ownership.test.ts +33 -1
- package/src/ownership/rows.ts +53 -0
- package/src/postgres/connection.ts +42 -7
- package/src/postgres/database-bigint-serialization.test.ts +1 -0
- package/src/postgres/database-refusals.test.ts +2 -2
- package/src/postgres/database-sql.ts +36 -9
- package/src/postgres/fake-grants-parse.ts +189 -0
- package/src/postgres/fake-grants-read.ts +250 -0
- package/src/postgres/fake-grants-sql.ts +207 -0
- package/src/postgres/fake-grants-write.ts +90 -0
- package/src/postgres/fake-role-sql.ts +220 -0
- package/src/postgres/fake-schema-semantics.test.ts +36 -0
- package/src/postgres/fake-schema-sql.ts +146 -0
- package/src/postgres/fake-sql-parse.ts +86 -0
- package/src/postgres/fake-sql-quote.ts +36 -0
- package/src/postgres/fake-sql.ts +161 -46
- package/src/postgres/fixtures/pg-REL_18_6-acl.h.txt +147 -0
- package/src/postgres/fixtures/pg-REL_18_6-aclexplode-func.txt +31 -0
- package/src/postgres/fixtures/pg-REL_18_6-alter-default-privileges-synopsis.txt +82 -0
- package/src/postgres/fixtures/pg-REL_18_6-alter_role.sgml.txt +44 -0
- package/src/postgres/fixtures/pg-REL_18_6-create_role.sgml.txt +26 -0
- package/src/postgres/fixtures/pg-REL_18_6-grant-synopsis.txt +95 -0
- package/src/postgres/fixtures/pg-REL_18_6-pg_attribute.h.txt +24 -0
- package/src/postgres/fixtures/pg-REL_18_6-pg_auth_members.h.txt +62 -0
- package/src/postgres/fixtures/pg-REL_18_6-pg_authid.h.txt +70 -0
- package/src/postgres/fixtures/pg-REL_18_6-pg_class.h.txt +33 -0
- package/src/postgres/fixtures/pg-REL_18_6-pg_default_acl.h.txt +81 -0
- package/src/postgres/fixtures/pg-REL_18_6-pg_namespace.h.txt +28 -0
- package/src/postgres/fixtures/pg-REL_18_6-revoke-synopsis.txt +124 -0
- package/src/postgres/grants-acl.test.ts +61 -0
- package/src/postgres/grants-attrs.ts +185 -0
- package/src/postgres/grants-database.test.ts +158 -0
- package/src/postgres/grants-declare.ts +172 -0
- package/src/postgres/grants-delete-proof.test.ts +154 -0
- package/src/postgres/grants-diff.ts +101 -0
- package/src/postgres/grants-errors.ts +215 -0
- package/src/postgres/grants-existence-guards.test.ts +113 -0
- package/src/postgres/grants-existence.ts +101 -0
- package/src/postgres/grants-lifecycle-guards.test.ts +208 -0
- package/src/postgres/grants-lifecycle-repair.test.ts +208 -0
- package/src/postgres/grants-lifecycle.test.ts +181 -0
- package/src/postgres/grants-ops.ts +229 -0
- package/src/postgres/grants-owner-revoke.test.ts +121 -0
- package/src/postgres/grants-ownership.ts +49 -0
- package/src/postgres/grants-plan-collateral.test.ts +202 -0
- package/src/postgres/grants-plan-diff.test.ts +204 -0
- package/src/postgres/grants-plan-restore.ts +43 -0
- package/src/postgres/grants-plan-revocations.test.ts +69 -0
- package/src/postgres/grants-plan.test.ts +148 -0
- package/src/postgres/grants-plan.ts +245 -0
- package/src/postgres/grants-provenance.test.ts +134 -0
- package/src/postgres/grants-psql-lifecycle.test.ts +105 -0
- package/src/postgres/grants-read-absent.test.ts +91 -0
- package/src/postgres/grants-read-defaults.ts +51 -0
- package/src/postgres/grants-read.ts +250 -0
- package/src/postgres/grants-refusals.test.ts +136 -0
- package/src/postgres/grants-refuse.ts +119 -0
- package/src/postgres/grants-relkind-wire.test.ts +111 -0
- package/src/postgres/grants-repair-plan.test.ts +201 -0
- package/src/postgres/grants-sql.test.ts +128 -0
- package/src/postgres/grants-sql.ts +144 -0
- package/src/postgres/grants-words.ts +34 -0
- package/src/postgres/grants.ts +110 -0
- package/src/postgres/index.ts +128 -5
- package/src/postgres/installed-classifier.ts +36 -0
- package/src/postgres/providers.ts +33 -9
- package/src/postgres/psql-executor-escaping.test.ts +67 -0
- package/src/postgres/psql-executor.test.ts +63 -2
- package/src/postgres/psql-executor.ts +74 -34
- package/src/postgres/role-adopt.test.ts +98 -0
- package/src/postgres/role-attrs.ts +134 -0
- package/src/postgres/role-diff.ts +89 -0
- package/src/postgres/role-errors.ts +198 -0
- package/src/postgres/role-guard.test.ts +60 -0
- package/src/postgres/role-identity.test.ts +185 -0
- package/src/postgres/role-lifecycle.test.ts +228 -0
- package/src/postgres/role-membership-sql.ts +198 -0
- package/src/postgres/role-password.test.ts +158 -0
- package/src/postgres/role-privilege.test.ts +80 -0
- package/src/postgres/role-provenance.test.ts +200 -0
- package/src/postgres/role-provider.ts +104 -0
- package/src/postgres/role-refusals.test.ts +250 -0
- package/src/postgres/role-scram.test.ts +38 -0
- package/src/postgres/role-scram.ts +38 -0
- package/src/postgres/role-secrets.ts +46 -0
- package/src/postgres/role-sql.ts +211 -0
- package/src/postgres/role-valid-until.test.ts +68 -0
- package/src/postgres/role.ts +218 -0
- package/src/postgres/schema-assert.ts +139 -0
- package/src/postgres/schema-attrs.ts +71 -0
- package/src/postgres/schema-delete-proofs.test.ts +192 -0
- package/src/postgres/schema-delete.ts +96 -0
- package/src/postgres/schema-diff.ts +44 -0
- package/src/postgres/schema-drop-2bp01.test.ts +146 -0
- package/src/postgres/schema-errors.ts +209 -0
- package/src/postgres/schema-handlers.test.ts +193 -0
- package/src/postgres/schema-identity.ts +39 -0
- package/src/postgres/schema-lifecycle.test.ts +246 -0
- package/src/postgres/schema-race.test.ts +70 -0
- package/src/postgres/schema-reconcile.ts +100 -0
- package/src/postgres/schema-refusals.test.ts +144 -0
- package/src/postgres/schema-socket.test.ts +161 -0
- package/src/postgres/schema-sql.ts +130 -0
- package/src/postgres/schema-takeover.test.ts +149 -0
- package/src/postgres/schema-test-kit.ts +85 -0
- package/src/postgres/schema.ts +130 -0
- package/src/release/binary-alias.test.ts +3 -3
- package/src/release/binary-claims.test.ts +3 -3
- package/src/release/binary-directory-umask.test.ts +65 -0
- package/src/release/fake-engine.ts +15 -0
- package/src/valkey/acl-attrs.ts +98 -0
- package/src/valkey/acl-compare.ts +57 -0
- package/src/valkey/acl-connection.ts +13 -0
- package/src/valkey/acl-delete.test.ts +127 -0
- package/src/valkey/acl-form.ts +239 -0
- package/src/valkey/acl-managed.ts +13 -0
- package/src/valkey/acl-ops.ts +122 -0
- package/src/valkey/acl-ownership.test.ts +118 -0
- package/src/valkey/acl-prefix.test.ts +38 -0
- package/src/valkey/acl-profiles.ts +81 -0
- package/src/valkey/acl-reconcile.ts +180 -0
- package/src/valkey/acl-reserved.test.ts +69 -0
- package/src/valkey/acl-revocation.test.ts +94 -0
- package/src/valkey/acl-seat-prefix.test.ts +111 -0
- package/src/valkey/acl-validation.test.ts +54 -0
- package/src/valkey/acl.test.ts +215 -0
- package/src/valkey/acl.ts +169 -0
- package/src/valkey/connection-service.ts +46 -0
- package/src/valkey/connection.ts +180 -0
- package/src/valkey/errors.ts +239 -0
- package/src/valkey/fake-acl.ts +128 -0
- package/src/valkey/fake-valkey.ts +224 -0
- package/src/valkey/handler-test-fixture.ts +43 -0
- package/src/valkey/handlers.test.ts +205 -0
- package/src/valkey/index.ts +54 -0
- package/src/valkey/instance-attrs.ts +48 -0
- package/src/valkey/instance-form.ts +104 -0
- package/src/valkey/instance.test.ts +108 -0
- package/src/valkey/instance.ts +160 -0
- package/src/valkey/provider-socket-fixture.ts +71 -0
- package/src/valkey/providers.test.ts +129 -0
- package/src/valkey/providers.ts +21 -0
- package/src/valkey/resp.ts +212 -0
- package/src/valkey/transport-bounds.test.ts +150 -0
- package/src/valkey/transport-error.ts +37 -0
- package/src/valkey/transport.test.ts +158 -0
- package/src/valkey/transport.ts +109 -0
- package/src/valkey/upstream-bounds.test.ts +14 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a `LiteLLM.AccessGroup` declares (props) and what is remembered about it (attributes).
|
|
3
|
+
*
|
|
4
|
+
* ★ THIS IS THE UNIFIED ACCESS GROUP, `LiteLLM_AccessGroupTable` (`/v1/unified_access_group`), not
|
|
5
|
+
* the two other things LiteLLM calls an "access group": a MODEL access group (`access_groups` in a
|
|
6
|
+
* model's `model_info`) and an MCP access group (a bare name on an MCP server row, referenced by
|
|
7
|
+
* `object_permission.mcp_access_groups`). A unified group bundles models, MCP servers and agents
|
|
8
|
+
* under one name and attaches to teams and keys (docs.litellm.ai/docs/proxy/access_groups).
|
|
9
|
+
* ⚠️ TOOLSETS ARE NOT IN IT. `AccessGroupCreateRequest` (`litellm/types/access_group.py`, 1.103.0)
|
|
10
|
+
* has `access_model_names`, `access_mcp_server_ids`, `access_agent_ids`, `assigned_team_ids` and
|
|
11
|
+
* `assigned_key_ids` and no toolset field. A toolset is granted through `object_permission.mcp_toolsets`
|
|
12
|
+
* on a team or key (`LiteLLM.Team`), not through a group.
|
|
13
|
+
* ★ MODELS ARE MODEL NAMES, MCP SERVERS ARE SERVER IDS. `access_model_names` holds the `model_name`
|
|
14
|
+
* a caller sends (`cf-code`), and `access_mcp_server_ids` holds `server_id`s. Declare a server's id
|
|
15
|
+
* with `server.serverId` (a `LiteLLM.MCPServer`) so the dependency edge exists.
|
|
16
|
+
* ⚠️ NOT MODELLED, on purpose: `assigned_team_ids`, `assigned_key_ids` and `access_agent_ids`. A
|
|
17
|
+
* team's group membership is declared on the TEAM (`accessGroupIds`), and LiteLLM mirrors it into
|
|
18
|
+
* `assigned_team_ids` in the same transaction; two resources writing one edge would fight. Agents
|
|
19
|
+
* are not managed here. None of the three is ever sent, and the update is a partial one, so an
|
|
20
|
+
* adopted group keeps whatever it has there.
|
|
21
|
+
*/
|
|
22
|
+
export interface AccessGroupProps {
|
|
23
|
+
/**
|
|
24
|
+
* The group's name, and the way an existing row is ADOPTED: `access_group_name` is UNIQUE in the
|
|
25
|
+
* table (`access_group_endpoints.py` finds it with `find_unique`), so the match is exact. Changing
|
|
26
|
+
* it is an update of the same row, never a replace: the id does not change.
|
|
27
|
+
*/
|
|
28
|
+
readonly accessGroupName: string;
|
|
29
|
+
/** Compared only when declared: adopting a row never clears text a person wrote. Blank is refused. */
|
|
30
|
+
readonly description?: string;
|
|
31
|
+
/**
|
|
32
|
+
* `model_name`s the group grants, compared as a SET and ALWAYS compared (default `[]`): it is an
|
|
33
|
+
* access grant, so an adopted group that grants more than declared is corrected, never left open.
|
|
34
|
+
* ⚠️ LiteLLM prunes a name itself when its last deployment is deleted
|
|
35
|
+
* (`management_helpers/access_group_model_sync.py`), so a plan can show an update for a model that
|
|
36
|
+
* was removed elsewhere.
|
|
37
|
+
*/
|
|
38
|
+
readonly modelNames?: readonly string[];
|
|
39
|
+
/** MCP `server_id`s the group grants, compared as a set and always compared (default `[]`). */
|
|
40
|
+
readonly mcpServerIds?: readonly string[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface AccessGroupAttributes {
|
|
44
|
+
readonly accessGroupId: string;
|
|
45
|
+
readonly accessGroupName: string;
|
|
46
|
+
readonly description: string | null;
|
|
47
|
+
readonly modelNames: readonly string[];
|
|
48
|
+
readonly mcpServerIds: readonly string[];
|
|
49
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `LiteLLM.AccessGroup` through Alchemy's real Plan and Apply over the fake proxy
|
|
3
|
+
* (`fake-access-group-litellm.ts`): create, no-op, adopt, update, rename, drift and delete.
|
|
4
|
+
*
|
|
5
|
+
* ★ EVERY VALUE IS `FAKE-*`.
|
|
6
|
+
* ⚠️ WHAT THE FAKE MODELS IS READ FROM THE 1.103.0 SOURCE, NOT MEASURED ON A LIVE PROXY (its header).
|
|
7
|
+
*/
|
|
8
|
+
import { expect, test } from 'bun:test';
|
|
9
|
+
import { credentials } from '@distilled.cloud/litellm/Credentials';
|
|
10
|
+
import * as Effect from 'effect/Effect';
|
|
11
|
+
import * as Layer from 'effect/Layer';
|
|
12
|
+
import * as FetchHttpClient from 'effect/unstable/http/FetchHttpClient';
|
|
13
|
+
import { LiteLLMAccessGroup } from './access-group.ts';
|
|
14
|
+
import { deleteAccessGroup } from './access-group-operations.ts';
|
|
15
|
+
import type { AccessGroupProps } from './access-group-types.ts';
|
|
16
|
+
import { FAKE_BASE } from './fake-litellm.ts';
|
|
17
|
+
import {
|
|
18
|
+
type FakeAccessGroupLitellm,
|
|
19
|
+
groupRow,
|
|
20
|
+
startFakeAccessGroupLitellm,
|
|
21
|
+
} from './fake-access-group-litellm.ts';
|
|
22
|
+
import { FAKE_KEY } from './fake-registry-base.ts';
|
|
23
|
+
import { fakeStack, writesOf } from './fake-stack.ts';
|
|
24
|
+
|
|
25
|
+
const stack = (fake: FakeAccessGroupLitellm) =>
|
|
26
|
+
fakeStack({ apiKey: FAKE_KEY, baseUrl: FAKE_BASE }, fake.fetch);
|
|
27
|
+
const declare = (props: AccessGroupProps, name = 'Estate') =>
|
|
28
|
+
Effect.gen(function* () {
|
|
29
|
+
yield* LiteLLMAccessGroup(name, props);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const estate: AccessGroupProps = {
|
|
33
|
+
accessGroupName: 'FAKE-estate',
|
|
34
|
+
description: 'FAKE estate group',
|
|
35
|
+
mcpServerIds: ['FAKE-server-a'],
|
|
36
|
+
modelNames: ['fake-code', 'fake-flash'],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
test('creates a group with both grant lists, then a second deploy writes nothing', async () => {
|
|
40
|
+
const fake = startFakeAccessGroupLitellm();
|
|
41
|
+
const same = stack(fake);
|
|
42
|
+
expect(await same.deploy(declare(estate))).toEqual({ Estate: 'create' });
|
|
43
|
+
expect(fake.groups()[0]).toMatchObject({
|
|
44
|
+
access_group_name: 'FAKE-estate',
|
|
45
|
+
access_mcp_server_ids: ['FAKE-server-a'],
|
|
46
|
+
access_model_names: ['fake-code', 'fake-flash'],
|
|
47
|
+
description: 'FAKE estate group',
|
|
48
|
+
});
|
|
49
|
+
// ★ the id is the proxy's, and it is what the state remembers
|
|
50
|
+
expect(String(fake.groups()[0]?.['access_group_id'])).toStartWith('FAKE-group-');
|
|
51
|
+
const before = fake.requests().length;
|
|
52
|
+
expect(await same.deploy(declare(estate))).toEqual({ Estate: 'noop' });
|
|
53
|
+
expect(writesOf(fake.requests().slice(before))).toEqual([]);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('an undeclared grant list means "grants nothing": it is sent as an empty list on create', async () => {
|
|
57
|
+
const fake = startFakeAccessGroupLitellm();
|
|
58
|
+
await stack(fake).deploy(declare({ accessGroupName: 'FAKE-empty' }));
|
|
59
|
+
expect(fake.bodies()[0]).toMatchObject({ access_mcp_server_ids: [], access_model_names: [] });
|
|
60
|
+
expect(fake.bodies()[0]).not.toHaveProperty('description');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('a changed model set is an update that sends ONLY the field that changed', async () => {
|
|
64
|
+
const fake = startFakeAccessGroupLitellm();
|
|
65
|
+
const same = stack(fake);
|
|
66
|
+
await same.deploy(declare(estate));
|
|
67
|
+
const planned = await same.deploy(declare({ ...estate, modelNames: ['fake-code'] }));
|
|
68
|
+
expect(planned).toEqual({ Estate: 'update' });
|
|
69
|
+
expect(fake.bodies().at(-1)).toEqual({ access_model_names: ['fake-code'] });
|
|
70
|
+
expect(fake.groups()[0]?.['access_mcp_server_ids']).toEqual(['FAKE-server-a']);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('a rename is an update of the SAME row: the id does not change', async () => {
|
|
74
|
+
const fake = startFakeAccessGroupLitellm();
|
|
75
|
+
const same = stack(fake);
|
|
76
|
+
await same.deploy(declare(estate));
|
|
77
|
+
const id = fake.groups()[0]?.['access_group_id'];
|
|
78
|
+
expect(await same.deploy(declare({ ...estate, accessGroupName: 'FAKE-renamed' }))).toEqual({
|
|
79
|
+
Estate: 'update',
|
|
80
|
+
});
|
|
81
|
+
expect(fake.groups()).toHaveLength(1);
|
|
82
|
+
expect(fake.groups()[0]).toMatchObject({
|
|
83
|
+
access_group_id: id,
|
|
84
|
+
access_group_name: 'FAKE-renamed',
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('a live row is Unowned: refused without --adopt, taken by name with it, and a matching row writes nothing', async () => {
|
|
89
|
+
const live = groupRow({
|
|
90
|
+
access_group_id: 'FAKE-live-1',
|
|
91
|
+
access_group_name: 'FAKE-estate',
|
|
92
|
+
access_mcp_server_ids: ['FAKE-server-a'],
|
|
93
|
+
access_model_names: ['fake-code', 'fake-flash'],
|
|
94
|
+
description: 'FAKE estate group',
|
|
95
|
+
});
|
|
96
|
+
const fake = startFakeAccessGroupLitellm({ seed: [live] });
|
|
97
|
+
const engine = stack(fake);
|
|
98
|
+
await expect(engine.deploy(declare(estate))).rejects.toThrow();
|
|
99
|
+
expect(writesOf(fake.requests())).toEqual([]);
|
|
100
|
+
expect(Object.values(await engine.deploy(declare(estate), { adopt: true }))).toEqual(['adopted']);
|
|
101
|
+
expect(writesOf(fake.requests())).toEqual([]);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('adopting a group that grants MORE than declared corrects it, and leaves undeclared text and teams alone', async () => {
|
|
105
|
+
const wide = groupRow({
|
|
106
|
+
access_group_id: 'FAKE-live-2',
|
|
107
|
+
access_group_name: 'FAKE-estate',
|
|
108
|
+
access_mcp_server_ids: ['FAKE-server-a', 'FAKE-server-extra'],
|
|
109
|
+
access_model_names: ['fake-code', 'fake-flash', 'fake-extra'],
|
|
110
|
+
assigned_team_ids: ['FAKE-team-1'],
|
|
111
|
+
description: 'written by a person',
|
|
112
|
+
});
|
|
113
|
+
const fake = startFakeAccessGroupLitellm({ seed: [wide] });
|
|
114
|
+
const { description: _kept, ...withoutDescription } = estate;
|
|
115
|
+
await stack(fake).deploy(declare(withoutDescription), { adopt: true });
|
|
116
|
+
expect(fake.groups()[0]).toMatchObject({
|
|
117
|
+
access_mcp_server_ids: ['FAKE-server-a'],
|
|
118
|
+
access_model_names: ['fake-code', 'fake-flash'],
|
|
119
|
+
assigned_team_ids: ['FAKE-team-1'],
|
|
120
|
+
description: 'written by a person',
|
|
121
|
+
});
|
|
122
|
+
// ★ a partial update: the team edge is not in the body at all
|
|
123
|
+
expect(fake.bodies()[0]).not.toHaveProperty('assigned_team_ids');
|
|
124
|
+
expect(fake.bodies()[0]).not.toHaveProperty('description');
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('reconcile compares the LIVE row: after LiteLLM prunes a model name itself, the next update puts it back', async () => {
|
|
128
|
+
const fake = startFakeAccessGroupLitellm();
|
|
129
|
+
const same = stack(fake);
|
|
130
|
+
await same.deploy(declare(estate));
|
|
131
|
+
fake.dropModel('fake-flash'); // ⚠️ access_group_model_sync.py: a deleted last deployment
|
|
132
|
+
// ★ Alchemy plans from state, so an unchanged declaration is a no-op even now (beta.79 reads live
|
|
133
|
+
// state only to adopt); a declaration that changes anything reaches reconcile, which reads live
|
|
134
|
+
expect(await same.deploy(declare(estate))).toEqual({ Estate: 'noop' });
|
|
135
|
+
expect(await same.deploy(declare({ ...estate, description: 'FAKE changed' }))).toEqual({
|
|
136
|
+
Estate: 'update',
|
|
137
|
+
});
|
|
138
|
+
expect(fake.bodies().at(-1)).toEqual({
|
|
139
|
+
access_model_names: ['fake-code', 'fake-flash'],
|
|
140
|
+
description: 'FAKE changed',
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('a proxy that drops an empty-list edit fails the deploy instead of claiming success', async () => {
|
|
145
|
+
// ⚠️ the fake's own model of a truthiness check on the edit route — unmeasured at 1.103.0
|
|
146
|
+
const fake = startFakeAccessGroupLitellm({ editIgnoresEmpty: true });
|
|
147
|
+
const same = stack(fake);
|
|
148
|
+
await same.deploy(declare(estate));
|
|
149
|
+
await expect(same.deploy(declare({ ...estate, mcpServerIds: [] }))).rejects.toThrow();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test('a refused declaration fails the plan before a single request', async () => {
|
|
153
|
+
for (const props of [
|
|
154
|
+
{ ...estate, accessGroupName: ' ' },
|
|
155
|
+
{ ...estate, accessGroupName: ' padded' },
|
|
156
|
+
{ ...estate, description: ' ' },
|
|
157
|
+
{ ...estate, modelNames: ['fake-code', 'fake-code'] },
|
|
158
|
+
{ ...estate, mcpServerIds: ['FAKE-server-a', ''] },
|
|
159
|
+
]) {
|
|
160
|
+
const fake = startFakeAccessGroupLitellm();
|
|
161
|
+
await expect(stack(fake).deploy(declare(props))).rejects.toThrow();
|
|
162
|
+
expect(fake.requests()).toEqual([]);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test('removing the declaration RETAINS the row: nothing deletes a group unless the stack opts in', async () => {
|
|
167
|
+
const fake = startFakeAccessGroupLitellm();
|
|
168
|
+
const same = stack(fake);
|
|
169
|
+
await same.deploy(declare(estate));
|
|
170
|
+
await same.deploy(Effect.void);
|
|
171
|
+
expect(fake.groups()).toHaveLength(1);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const run = <A, E>(fetchFn: typeof globalThis.fetch, effect: Effect.Effect<A, E, unknown>) =>
|
|
175
|
+
Effect.runPromise(
|
|
176
|
+
effect.pipe(
|
|
177
|
+
Effect.provide(FetchHttpClient.layer),
|
|
178
|
+
Effect.provide(Layer.succeed(FetchHttpClient.Fetch, fetchFn)),
|
|
179
|
+
Effect.provide(credentials({ apiKey: FAKE_KEY, baseUrl: FAKE_BASE })),
|
|
180
|
+
) as Effect.Effect<A, E, never>,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
test('delete answers 204 with no body, and a missing id is swallowed only because a real read says so', async () => {
|
|
184
|
+
const live = groupRow({ access_group_id: 'FAKE-live-3', access_group_name: 'FAKE-estate' });
|
|
185
|
+
const fake = startFakeAccessGroupLitellm({ seed: [live] });
|
|
186
|
+
await run(fake.fetch, deleteAccessGroup('FAKE-live-3'));
|
|
187
|
+
expect(fake.groups()).toEqual([]);
|
|
188
|
+
// already gone: the DELETE 404s, the re-list confirms absence, so it is success
|
|
189
|
+
await run(fake.fetch, deleteAccessGroup('FAKE-live-3'));
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test('a delete refused for lack of rights re-raises the ORIGINAL error and the row stays', async () => {
|
|
193
|
+
const live = groupRow({ access_group_id: 'FAKE-live-4', access_group_name: 'FAKE-estate' });
|
|
194
|
+
const fake = startFakeAccessGroupLitellm({ forbidWrites: true, seed: [live] });
|
|
195
|
+
await expect(run(fake.fetch, deleteAccessGroup('FAKE-live-4'))).rejects.toThrow();
|
|
196
|
+
expect(fake.groups()).toHaveLength(1);
|
|
197
|
+
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `LiteLLM.AccessGroup` — one row of LiteLLM's unified access group table
|
|
3
|
+
* (`LiteLLM_AccessGroupTable`, `/v1/unified_access_group`): a named bundle of models and MCP servers
|
|
4
|
+
* that teams and keys are attached to. Types and what is left out: access-group-types.ts.
|
|
5
|
+
*
|
|
6
|
+
* ★ ADOPT BY NAME. `access_group_name` is unique in the table, so `accessGroupName` finds the one
|
|
7
|
+
* live row that carries it. A live row with no state is `Unowned`, so it needs `--adopt`.
|
|
8
|
+
* ★ `defaultRemovalPolicy: 'retain'` — deleting a group detaches it from every team and key that
|
|
9
|
+
* holds it (`delete_access_group` rewrites their `access_group_ids`), and those callers lose the
|
|
10
|
+
* models and servers it granted. Opt in with `.pipe(RemovalPolicy.destroy())`.
|
|
11
|
+
* ★ THE GRANTS ARE THE DECLARATION. `modelNames` and `mcpServerIds` are always compared (an
|
|
12
|
+
* undeclared list means "grants nothing"), so an adopted group that grants more is corrected.
|
|
13
|
+
* ⚠️ NO LICENCE GATE ON THESE ROUTES: `access_group_endpoints.py` has no `premium_user` check
|
|
14
|
+
* (grep, 1.103.0), and docs.litellm.ai/docs/proxy/access_groups makes no Enterprise statement.
|
|
15
|
+
* ⛔ NO LITELLM CREDENTIAL IS A PROP; `litellmProviders`' layer supplies `Credentials`.
|
|
16
|
+
*/
|
|
17
|
+
import { Resource } from 'alchemy';
|
|
18
|
+
import { Unowned } from 'alchemy/AdoptPolicy';
|
|
19
|
+
import { isResolved } from 'alchemy/Diff';
|
|
20
|
+
import type { Input } from 'alchemy/Input';
|
|
21
|
+
import * as Provider from 'alchemy/Provider';
|
|
22
|
+
import * as Effect from 'effect/Effect';
|
|
23
|
+
import * as Predicate from 'effect/Predicate';
|
|
24
|
+
import { createBody, differing, firstProblem, updateBody } from './access-group-form.ts';
|
|
25
|
+
import {
|
|
26
|
+
createAccessGroup,
|
|
27
|
+
deleteAccessGroup,
|
|
28
|
+
listAccessGroups,
|
|
29
|
+
updateAccessGroup,
|
|
30
|
+
} from './access-group-operations.ts';
|
|
31
|
+
import type { AccessGroupAttributes, AccessGroupProps } from './access-group-types.ts';
|
|
32
|
+
import {
|
|
33
|
+
LitellmRegistryAbsentAfterWriteError,
|
|
34
|
+
LitellmRegistryNotConvergedError,
|
|
35
|
+
} from './registry-errors.ts';
|
|
36
|
+
import { dieIfInvalid, failIfInvalid } from './registry-support.ts';
|
|
37
|
+
|
|
38
|
+
export type { AccessGroupAttributes, AccessGroupProps };
|
|
39
|
+
export type { RegistryError as AccessGroupError } from './registry-errors.ts';
|
|
40
|
+
|
|
41
|
+
const RESOURCE = 'LiteLLM.AccessGroup';
|
|
42
|
+
|
|
43
|
+
export interface LiteLLMAccessGroup extends Resource<
|
|
44
|
+
'LiteLLM.AccessGroup',
|
|
45
|
+
AccessGroupProps,
|
|
46
|
+
AccessGroupAttributes
|
|
47
|
+
> {}
|
|
48
|
+
|
|
49
|
+
export const LiteLLMAccessGroup = Resource<LiteLLMAccessGroup>('LiteLLM.AccessGroup', {
|
|
50
|
+
defaultRemovalPolicy: 'retain',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export const isLiteLLMAccessGroup = (value: unknown): value is LiteLLMAccessGroup =>
|
|
54
|
+
Predicate.hasProperty(value, 'Type') && value.Type === 'LiteLLM.AccessGroup';
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The live row this declaration means. A RECORDED id wins and is matched by id alone: a row that
|
|
58
|
+
* vanished and was recreated by hand under the same name is not silently taken over (the create
|
|
59
|
+
* would then fail on the unique name, loudly). With no state, the name decides.
|
|
60
|
+
*/
|
|
61
|
+
const locate = (
|
|
62
|
+
rows: readonly AccessGroupAttributes[],
|
|
63
|
+
props: AccessGroupProps,
|
|
64
|
+
output: AccessGroupAttributes | undefined,
|
|
65
|
+
) =>
|
|
66
|
+
output !== undefined
|
|
67
|
+
? rows.find((row) => row.accessGroupId === output.accessGroupId)
|
|
68
|
+
: rows.find((row) => row.accessGroupName === props.accessGroupName);
|
|
69
|
+
|
|
70
|
+
/** ⛔ TEST-ONLY EXPORT. Not on index.ts's barrel. */
|
|
71
|
+
export const accessGroupHandlers = {
|
|
72
|
+
/** ⛔ With no `output` this is the adoption probe, so the refusals run here too (registry-support.ts). */
|
|
73
|
+
read: ({ olds, output }: { olds: AccessGroupProps; output: AccessGroupAttributes | undefined }) =>
|
|
74
|
+
Effect.gen(function* () {
|
|
75
|
+
if (output === undefined) {
|
|
76
|
+
yield* dieIfInvalid(RESOURCE, String(olds.accessGroupName), firstProblem(olds));
|
|
77
|
+
}
|
|
78
|
+
const live = locate(yield* listAccessGroups(), olds, output);
|
|
79
|
+
if (live === undefined) return undefined;
|
|
80
|
+
return output === undefined ? Unowned(live) : live;
|
|
81
|
+
}),
|
|
82
|
+
|
|
83
|
+
diff: ({
|
|
84
|
+
news,
|
|
85
|
+
output,
|
|
86
|
+
}: {
|
|
87
|
+
news: Input<AccessGroupProps>;
|
|
88
|
+
output: AccessGroupAttributes | undefined;
|
|
89
|
+
}) =>
|
|
90
|
+
Effect.gen(function* () {
|
|
91
|
+
if (!isResolved(news)) return undefined;
|
|
92
|
+
yield* failIfInvalid(RESOURCE, String(news.accessGroupName), firstProblem(news));
|
|
93
|
+
if (output === undefined) return undefined;
|
|
94
|
+
return differing(output, news).length === 0
|
|
95
|
+
? ({ action: 'noop' } as const)
|
|
96
|
+
: ({ action: 'update' } as const);
|
|
97
|
+
}),
|
|
98
|
+
|
|
99
|
+
reconcile: ({
|
|
100
|
+
news,
|
|
101
|
+
output,
|
|
102
|
+
}: {
|
|
103
|
+
news: AccessGroupProps;
|
|
104
|
+
output: AccessGroupAttributes | undefined;
|
|
105
|
+
}) =>
|
|
106
|
+
Effect.gen(function* () {
|
|
107
|
+
yield* failIfInvalid(RESOURCE, String(news.accessGroupName), firstProblem(news));
|
|
108
|
+
const before = locate(yield* listAccessGroups(), news, output);
|
|
109
|
+
if (before === undefined) yield* createAccessGroup(createBody(news));
|
|
110
|
+
else if (differing(before, news).length > 0) {
|
|
111
|
+
yield* updateAccessGroup(before.accessGroupId, updateBody(news, before));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const rows = yield* listAccessGroups();
|
|
115
|
+
const after =
|
|
116
|
+
before === undefined
|
|
117
|
+
? rows.find((row) => row.accessGroupName === news.accessGroupName)
|
|
118
|
+
: rows.find((row) => row.accessGroupId === before.accessGroupId);
|
|
119
|
+
if (after === undefined) {
|
|
120
|
+
return yield* Effect.fail(
|
|
121
|
+
new LitellmRegistryAbsentAfterWriteError({
|
|
122
|
+
name: news.accessGroupName,
|
|
123
|
+
resource: RESOURCE,
|
|
124
|
+
}),
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
const left = differing(after, news);
|
|
128
|
+
if (left.length > 0) {
|
|
129
|
+
return yield* Effect.fail(
|
|
130
|
+
new LitellmRegistryNotConvergedError({
|
|
131
|
+
fields: left,
|
|
132
|
+
name: news.accessGroupName,
|
|
133
|
+
resource: RESOURCE,
|
|
134
|
+
}),
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
return after;
|
|
138
|
+
}),
|
|
139
|
+
|
|
140
|
+
delete: ({ output }: { output: AccessGroupAttributes }) =>
|
|
141
|
+
deleteAccessGroup(output.accessGroupId),
|
|
142
|
+
|
|
143
|
+
/** ⛔ EMPTY: adoption is an explicit act (`--adopt`), and no ownership mark exists to filter by. */
|
|
144
|
+
list: () => Effect.succeed([]),
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export const LiteLLMAccessGroupProvider = () =>
|
|
148
|
+
Provider.effect(
|
|
149
|
+
LiteLLMAccessGroup,
|
|
150
|
+
Effect.succeed(LiteLLMAccessGroup.Provider.of(accessGroupHandlers)),
|
|
151
|
+
);
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The typed refusals `LiteLLM.Credential` raises on top of `@distilled.cloud/litellm`'s own SDK
|
|
3
|
+
* errors.
|
|
4
|
+
*
|
|
5
|
+
* ⛔ NO MESSAGE HERE MAY CARRY A CREDENTIAL VALUE: only the credential's NAME, field names, the
|
|
6
|
+
* NAMES of environment variables, and SDK error text — exactly like mcp-server-errors.ts.
|
|
7
|
+
* ⚠️ THE SDK'S TYPED UNION IS NARROW ON PURPOSE, and the runtime is wider: the credential routes
|
|
8
|
+
* declare only `UnprocessableEntity` (422) in `credential_management.ts`, so a create on an
|
|
9
|
+
* existing name — which the live 1.103.0 container answers `409` (`endpoints.py`'s
|
|
10
|
+
* `_credential_exists_detail`) — decodes at run time as the core `Conflict` class (`Errors.ts`
|
|
11
|
+
* re-exports it, but it is not in the operation's TS union) and PROPAGATES as such, never
|
|
12
|
+
* silently swallowed (S21). The read's and delete's `404` is TYPED as the SDK's
|
|
13
|
+
* `CredentialNotFound` (a distilled patch matched on the vendor's "Credential not found"
|
|
14
|
+
* message, `endpoints.py`), so credential-operations.ts `catchTag`s it instead of `instanceof`
|
|
15
|
+
* `NotFound`: a 404 from a front proxy, Access, or a wrong base path stays a `NotFound` and is
|
|
16
|
+
* never read as absence. `CredentialError` carries the typed members of the four operations the
|
|
17
|
+
* resource calls (create, by-name read, PATCH, delete), plus the refusals below.
|
|
18
|
+
*/
|
|
19
|
+
import type * as credentials from '@distilled.cloud/litellm/credential_management';
|
|
20
|
+
import * as Data from 'effect/Data';
|
|
21
|
+
import type { HttpClientErrorReason } from 'effect/unstable/http/HttpClientError';
|
|
22
|
+
|
|
23
|
+
/** A declaration the resource refuses before any request: a combination nobody meant. */
|
|
24
|
+
export class LitellmCredentialInvalidError extends Data.TaggedError(
|
|
25
|
+
'LitellmCredentialInvalidError',
|
|
26
|
+
)<{
|
|
27
|
+
readonly credentialName: string;
|
|
28
|
+
readonly problem: string;
|
|
29
|
+
}> {
|
|
30
|
+
override get message(): string {
|
|
31
|
+
return `LiteLLM.Credential "${this.credentialName}": ${this.problem}.`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A create's `POST /credentials` or an update's `PATCH /credentials/{name}` failed on the wire (or
|
|
37
|
+
* its answer could not be read), so nobody knows whether the credential is what was asked for.
|
|
38
|
+
*
|
|
39
|
+
* ⛔ THIS IS WHAT STANDS IN FOR AN `HttpClientError`, WHICH CARRIES ITS REQUEST, AND THE REQUEST
|
|
40
|
+
* BODY OF A CREATE OR UPDATE IS `{"credential_name": …, "credential_values": {"api_key": "…"}}`.
|
|
41
|
+
* Measured 2026-09-30: on a dropped connection `JSON.stringify(error)`, `Bun.inspect(error)` and
|
|
42
|
+
* Effect's JSON logger all printed the value, as did a failed deploy over it — the same leak
|
|
43
|
+
* key-operations.ts's `LitellmKeyTransportError` closes. A defect reading a broken answer
|
|
44
|
+
* (`protocol-rest.ts` reads it `Effect.orDie`) carries the same request. So `reason` keeps the
|
|
45
|
+
* `HttpClientError` reason's TAG (a string) and nothing else: no request, no cause, no
|
|
46
|
+
* description. The credential NAME stays — it is not secret.
|
|
47
|
+
*/
|
|
48
|
+
export class LitellmCredentialTransportError extends Data.TaggedError(
|
|
49
|
+
'LitellmCredentialTransportError',
|
|
50
|
+
)<{
|
|
51
|
+
readonly credentialName: string;
|
|
52
|
+
readonly reason: HttpClientErrorReason['_tag'] | 'Defect';
|
|
53
|
+
}> {
|
|
54
|
+
override get message(): string {
|
|
55
|
+
return (
|
|
56
|
+
`LiteLLM.Credential "${this.credentialName}": a /credentials write failed ` +
|
|
57
|
+
`(${this.reason}) before an answer could be read, so the credential MAY have been written. ` +
|
|
58
|
+
'This error keeps neither the request nor its cause: the request body holds the credential ' +
|
|
59
|
+
'values. Look the name up in LiteLLM. A row that landed is taken over by the next deploy ' +
|
|
60
|
+
'with --adopt; one that did not is created by it.'
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The SDK prints request and response bodies to stderr while `DISTILLED_DEBUG_HTTP` is set, and a
|
|
67
|
+
* `POST /credentials` carries the values in its body — refused before any request, exactly like
|
|
68
|
+
* `key-secret.ts`'s `refuseDebugLogging` for `/key/generate`.
|
|
69
|
+
*/
|
|
70
|
+
export class LitellmCredentialDebugLoggingError extends Data.TaggedError(
|
|
71
|
+
'LitellmCredentialDebugLoggingError',
|
|
72
|
+
)<{
|
|
73
|
+
readonly credentialName: string;
|
|
74
|
+
}> {
|
|
75
|
+
override get message(): string {
|
|
76
|
+
return (
|
|
77
|
+
`LiteLLM.Credential "${this.credentialName}": DISTILLED_DEBUG_HTTP is set, so the SDK ` +
|
|
78
|
+
"would print the credential values to stderr in /credentials' request and response. Unset " +
|
|
79
|
+
'it and run again. Nothing was written.'
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* A write had to send the credential values and the deploying process does not hold one or more
|
|
86
|
+
* of the declared variables. The names are listed, never a value.
|
|
87
|
+
*/
|
|
88
|
+
export class LitellmCredentialEnvUnsetError extends Data.TaggedError(
|
|
89
|
+
'LitellmCredentialEnvUnsetError',
|
|
90
|
+
)<{
|
|
91
|
+
readonly credentialName: string;
|
|
92
|
+
readonly variables: readonly string[];
|
|
93
|
+
}> {
|
|
94
|
+
override get message(): string {
|
|
95
|
+
return (
|
|
96
|
+
`LiteLLM.Credential "${this.credentialName}": ` +
|
|
97
|
+
`the deploying process does not set ${this.variables.join(', ')}.`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* A credentials read answered something that is not a row of the credential table (or named a
|
|
104
|
+
* different row), so adopt-by-name cannot trust it. The by-name read is this resource's only
|
|
105
|
+
* read, so a row it cannot recognise is refused rather than guessed at.
|
|
106
|
+
*/
|
|
107
|
+
export class LitellmCredentialUnreadableError extends Data.TaggedError(
|
|
108
|
+
'LitellmCredentialUnreadableError',
|
|
109
|
+
)<{
|
|
110
|
+
readonly reason: string;
|
|
111
|
+
}> {
|
|
112
|
+
override get message(): string {
|
|
113
|
+
return `LiteLLM.Credential: a credentials read is unreadable (${this.reason}).`;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* A create or update returned no error, yet the by-name read does not answer the credential — the
|
|
119
|
+
* proxy failed to record it in memory or in the DB. Refused instead of reported as done.
|
|
120
|
+
*/
|
|
121
|
+
export class LitellmCredentialAbsentAfterWriteError extends Data.TaggedError(
|
|
122
|
+
'LitellmCredentialAbsentAfterWriteError',
|
|
123
|
+
)<{
|
|
124
|
+
readonly credentialName: string;
|
|
125
|
+
}> {
|
|
126
|
+
override get message(): string {
|
|
127
|
+
return (
|
|
128
|
+
`LiteLLM.Credential "${this.credentialName}": the write returned no error but the ` +
|
|
129
|
+
'credential is absent from the by-name read.'
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The write returned no error but the credential still differs from the declaration. The update
|
|
136
|
+
* path this resource uses is a PATCH merge (credential.ts, credential-operations.ts) — or a
|
|
137
|
+
* whole-row rewrite to drop a key — so a residual difference is refused here instead of being
|
|
138
|
+
* reported as converged.
|
|
139
|
+
*/
|
|
140
|
+
export class LitellmCredentialNotConvergedError extends Data.TaggedError(
|
|
141
|
+
'LitellmCredentialNotConvergedError',
|
|
142
|
+
)<{
|
|
143
|
+
readonly credentialName: string;
|
|
144
|
+
readonly fields: readonly string[];
|
|
145
|
+
}> {
|
|
146
|
+
override get message(): string {
|
|
147
|
+
return (
|
|
148
|
+
`LiteLLM.Credential "${this.credentialName}": after the write it still differs from the ` +
|
|
149
|
+
`declaration in ${this.fields.join(', ')}.`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** A rewrite deleted the old row before its POST failed. Keep only the failure tag. */
|
|
155
|
+
export class LitellmCredentialRewriteError extends Data.TaggedError(
|
|
156
|
+
'LitellmCredentialRewriteError',
|
|
157
|
+
)<{
|
|
158
|
+
readonly credentialName: string;
|
|
159
|
+
readonly reason: string;
|
|
160
|
+
}> {
|
|
161
|
+
override get message(): string {
|
|
162
|
+
return (
|
|
163
|
+
`LiteLLM.Credential "${this.credentialName}": DELETE already ran, but the replacement ` +
|
|
164
|
+
`POST failed (${this.reason}). The next deploy recreates the row if absent; keep all ` +
|
|
165
|
+
'declared credential variables set. If the POST landed despite the failure, the next ' +
|
|
166
|
+
'deploy reads and reconciles that row.'
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export type CredentialError =
|
|
172
|
+
| credentials.CreateCredentialCredentialsPostError
|
|
173
|
+
| credentials.GetCredentialByNameCredentialsByNameCredentialNameGetError
|
|
174
|
+
| credentials.UpdateCredentialCredentialsCredentialNamePatchError
|
|
175
|
+
| credentials.DeleteCredentialCredentialsCredentialNameDeleteError
|
|
176
|
+
| LitellmCredentialInvalidError
|
|
177
|
+
| LitellmCredentialTransportError
|
|
178
|
+
| LitellmCredentialRewriteError
|
|
179
|
+
| LitellmCredentialDebugLoggingError
|
|
180
|
+
| LitellmCredentialEnvUnsetError
|
|
181
|
+
| LitellmCredentialUnreadableError
|
|
182
|
+
| LitellmCredentialAbsentAfterWriteError
|
|
183
|
+
| LitellmCredentialNotConvergedError;
|