@homeflare/alchemy 0.28.0 → 0.29.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 (210) hide show
  1. package/README.md +2 -0
  2. package/dist/caddy/admin-address.d.ts +27 -0
  3. package/dist/caddy/admin-address.d.ts.map +1 -0
  4. package/dist/caddy/admin-calls.d.ts +25 -28
  5. package/dist/caddy/admin-calls.d.ts.map +1 -1
  6. package/dist/caddy/admin.d.ts +28 -38
  7. package/dist/caddy/admin.d.ts.map +1 -1
  8. package/dist/caddy/caddy-http-client.d.ts +25 -0
  9. package/dist/caddy/caddy-http-client.d.ts.map +1 -0
  10. package/dist/caddy/config-errors.d.ts +24 -0
  11. package/dist/caddy/config-errors.d.ts.map +1 -0
  12. package/dist/caddy/config-lifecycle.d.ts +20 -49
  13. package/dist/caddy/config-lifecycle.d.ts.map +1 -1
  14. package/dist/caddy/config-reconcile.d.ts +45 -0
  15. package/dist/caddy/config-reconcile.d.ts.map +1 -0
  16. package/dist/caddy/config.d.ts +4 -3
  17. package/dist/caddy/config.d.ts.map +1 -1
  18. package/dist/caddy/fake-caddy.d.ts +10 -2
  19. package/dist/caddy/fake-caddy.d.ts.map +1 -1
  20. package/dist/caddy/index.d.ts +3 -3
  21. package/dist/caddy/index.d.ts.map +1 -1
  22. package/dist/caddy/index.js +487 -444
  23. package/dist/caddy/index.js.map +16 -12
  24. package/dist/caddy/local-admin.d.ts +20 -34
  25. package/dist/caddy/local-admin.d.ts.map +1 -1
  26. package/dist/caddy/providers.d.ts +19 -3
  27. package/dist/caddy/providers.d.ts.map +1 -1
  28. package/dist/cloudflare/mesh-node-token.d.ts +1 -1
  29. package/dist/cloudflare/mesh-node-token.d.ts.map +1 -1
  30. package/dist/forgejo/branch-protection.d.ts +4 -4
  31. package/dist/forgejo/org-actions-secrets.d.ts +4 -4
  32. package/dist/forgejo/org-label.d.ts +4 -4
  33. package/dist/forgejo/org-team.d.ts +4 -4
  34. package/dist/forgejo/repo-webhook.d.ts +4 -4
  35. package/dist/forgejo/repository.d.ts +4 -4
  36. package/dist/forgejo/team-member.d.ts +4 -4
  37. package/dist/github/declare-repo-baseline.d.ts +1 -1
  38. package/dist/github/declare-repo-baseline.d.ts.map +1 -1
  39. package/dist/github/index.d.ts +8 -4
  40. package/dist/github/index.d.ts.map +1 -1
  41. package/dist/github/index.js +63 -23
  42. package/dist/github/index.js.map +13 -12
  43. package/dist/github/repo-baseline-data.d.ts +10 -1
  44. package/dist/github/repo-baseline-data.d.ts.map +1 -1
  45. package/dist/github/repo-policy.d.ts +1 -1
  46. package/dist/github/repo-policy.d.ts.map +1 -1
  47. package/dist/github/repository-ruleset-errors.d.ts +3 -2
  48. package/dist/github/repository-ruleset-errors.d.ts.map +1 -1
  49. package/dist/github/repository-ruleset-form.d.ts.map +1 -1
  50. package/dist/github/repository-ruleset-guards.d.ts +3 -2
  51. package/dist/github/repository-ruleset-guards.d.ts.map +1 -1
  52. package/dist/github/repository-ruleset-octokit.d.ts +49 -0
  53. package/dist/github/repository-ruleset-octokit.d.ts.map +1 -1
  54. package/dist/github/repository-ruleset-probe.d.ts +2 -1
  55. package/dist/github/repository-ruleset-probe.d.ts.map +1 -1
  56. package/dist/github/repository-ruleset-props.d.ts +7 -4
  57. package/dist/github/repository-ruleset-props.d.ts.map +1 -1
  58. package/dist/github/repository-ruleset-providers.d.ts +42 -0
  59. package/dist/github/repository-ruleset-providers.d.ts.map +1 -0
  60. package/dist/github/repository-ruleset.d.ts +26 -4
  61. package/dist/github/repository-ruleset.d.ts.map +1 -1
  62. package/dist/litellm/fake-litellm.d.ts +27 -16
  63. package/dist/litellm/fake-litellm.d.ts.map +1 -1
  64. package/dist/litellm/fake-stack.d.ts +9 -4
  65. package/dist/litellm/fake-stack.d.ts.map +1 -1
  66. package/dist/litellm/index.d.ts +7 -5
  67. package/dist/litellm/index.d.ts.map +1 -1
  68. package/dist/litellm/index.js +53 -123
  69. package/dist/litellm/index.js.map +8 -8
  70. package/dist/litellm/operations.d.ts +60 -0
  71. package/dist/litellm/operations.d.ts.map +1 -0
  72. package/dist/litellm/pass-through-endpoint.d.ts +10 -28
  73. package/dist/litellm/pass-through-endpoint.d.ts.map +1 -1
  74. package/dist/litellm/pass-through-errors.d.ts +37 -0
  75. package/dist/litellm/pass-through-errors.d.ts.map +1 -0
  76. package/dist/litellm/pass-through-form.d.ts +11 -4
  77. package/dist/litellm/pass-through-form.d.ts.map +1 -1
  78. package/dist/litellm/providers.d.ts +7 -5
  79. package/dist/litellm/providers.d.ts.map +1 -1
  80. package/dist/netbox/prefix.d.ts +4 -4
  81. package/dist/paperless/custom-field.d.ts +21 -21
  82. package/dist/paperless/custom-field.d.ts.map +1 -1
  83. package/dist/paperless/document-type.d.ts +34 -4
  84. package/dist/paperless/document-type.d.ts.map +1 -1
  85. package/dist/paperless/fake-paperless.d.ts +36 -19
  86. package/dist/paperless/fake-paperless.d.ts.map +1 -1
  87. package/dist/paperless/index.d.ts +7 -2
  88. package/dist/paperless/index.d.ts.map +1 -1
  89. package/dist/paperless/index.js +164 -228
  90. package/dist/paperless/index.js.map +10 -13
  91. package/dist/paperless/matching-locate.d.ts +42 -20
  92. package/dist/paperless/matching-locate.d.ts.map +1 -1
  93. package/dist/paperless/matching-types.d.ts +47 -18
  94. package/dist/paperless/matching-types.d.ts.map +1 -1
  95. package/dist/paperless/matching.d.ts +30 -27
  96. package/dist/paperless/matching.d.ts.map +1 -1
  97. package/dist/paperless/providers.d.ts +13 -7
  98. package/dist/paperless/providers.d.ts.map +1 -1
  99. package/dist/paperless/storage-path.d.ts +34 -4
  100. package/dist/paperless/storage-path.d.ts.map +1 -1
  101. package/dist/paperless/tag.d.ts +43 -8
  102. package/dist/paperless/tag.d.ts.map +1 -1
  103. package/dist/proxmox/acl.d.ts +30 -23
  104. package/dist/proxmox/acl.d.ts.map +1 -1
  105. package/dist/proxmox/distilled-pve.d.ts +89 -0
  106. package/dist/proxmox/distilled-pve.d.ts.map +1 -0
  107. package/dist/proxmox/index.js +663 -609
  108. package/dist/proxmox/index.js.map +12 -11
  109. package/dist/proxmox/members.d.ts +29 -10
  110. package/dist/proxmox/members.d.ts.map +1 -1
  111. package/docs/caddy-admin.md +1 -1
  112. package/docs/caddy.md +3 -2
  113. package/docs/credentials.md +16 -0
  114. package/docs/litellm.md +21 -13
  115. package/docs/paperless.md +12 -0
  116. package/docs/peers.md +5 -0
  117. package/docs/repo-policy.md +16 -1
  118. package/docs/repository-ruleset.md +53 -13
  119. package/docs/upstream-conformance.md +126 -10
  120. package/package.json +5 -2
  121. package/src/caddy/admin-address.ts +71 -0
  122. package/src/caddy/admin-calls.ts +48 -100
  123. package/src/caddy/admin.ts +37 -41
  124. package/src/caddy/adopt-scope.test.ts +1 -1
  125. package/src/caddy/caddy-http-client.ts +229 -0
  126. package/src/caddy/config-adopt-provider.test.ts +139 -0
  127. package/src/caddy/config-adopt.test.ts +60 -126
  128. package/src/caddy/config-errors.ts +47 -0
  129. package/src/caddy/config-lifecycle.test.ts +55 -42
  130. package/src/caddy/config-lifecycle.ts +72 -162
  131. package/src/caddy/config-reconcile.ts +138 -0
  132. package/src/caddy/config.ts +36 -42
  133. package/src/caddy/fake-caddy.ts +20 -2
  134. package/src/caddy/index.ts +3 -8
  135. package/src/caddy/local-admin.test.ts +35 -21
  136. package/src/caddy/local-admin.ts +60 -167
  137. package/src/caddy/providers.test.ts +14 -6
  138. package/src/caddy/providers.ts +20 -4
  139. package/src/github/declare-repo-baseline.ts +6 -6
  140. package/src/github/index.ts +8 -4
  141. package/src/github/repo-baseline-data.test.ts +13 -0
  142. package/src/github/repo-baseline-data.ts +11 -2
  143. package/src/github/repo-policy-stack.test.ts +59 -0
  144. package/src/github/repo-policy.ts +3 -2
  145. package/src/github/repository-ruleset-errors.ts +6 -4
  146. package/src/github/repository-ruleset-exact-adopt-k1.test.ts +109 -0
  147. package/src/github/repository-ruleset-exact-adopt.test.ts +14 -9
  148. package/src/github/repository-ruleset-form.ts +7 -3
  149. package/src/github/repository-ruleset-guards.ts +3 -2
  150. package/src/github/repository-ruleset-octokit.test.ts +141 -0
  151. package/src/github/repository-ruleset-octokit.ts +121 -30
  152. package/src/github/repository-ruleset-probe.ts +2 -1
  153. package/src/github/repository-ruleset-props.ts +7 -4
  154. package/src/github/repository-ruleset-providers.ts +46 -0
  155. package/src/github/repository-ruleset-wire.test.ts +38 -27
  156. package/src/github/repository-ruleset.ts +27 -3
  157. package/src/litellm/fake-litellm.ts +83 -78
  158. package/src/litellm/fake-stack.ts +13 -5
  159. package/src/litellm/index.ts +7 -21
  160. package/src/litellm/operations.ts +149 -0
  161. package/src/litellm/pass-through-endpoint-delete-swallow.test.ts +17 -20
  162. package/src/litellm/pass-through-endpoint-replace.test.ts +3 -4
  163. package/src/litellm/pass-through-endpoint.test.ts +8 -8
  164. package/src/litellm/pass-through-endpoint.ts +21 -31
  165. package/src/litellm/pass-through-errors.ts +37 -0
  166. package/src/litellm/pass-through-form.ts +20 -10
  167. package/src/litellm/providers.ts +8 -7
  168. package/src/paperless/custom-field.test.ts +49 -40
  169. package/src/paperless/custom-field.ts +57 -33
  170. package/src/paperless/document-type.test.ts +48 -0
  171. package/src/paperless/document-type.ts +51 -22
  172. package/src/paperless/fake-paperless.ts +63 -72
  173. package/src/paperless/index.ts +7 -13
  174. package/src/paperless/matching-locate.test.ts +102 -0
  175. package/src/paperless/matching-locate.ts +80 -86
  176. package/src/paperless/matching-types.ts +49 -16
  177. package/src/paperless/matching.ts +77 -90
  178. package/src/paperless/providers.ts +14 -10
  179. package/src/paperless/storage-path.test.ts +56 -0
  180. package/src/paperless/storage-path.ts +53 -24
  181. package/src/paperless/tag-identity.test.ts +127 -0
  182. package/src/paperless/tag.test.ts +100 -0
  183. package/src/paperless/tag.ts +62 -32
  184. package/src/proxmox/acl.test.ts +145 -0
  185. package/src/proxmox/acl.ts +128 -150
  186. package/src/proxmox/distilled-pve.test.ts +231 -0
  187. package/src/proxmox/distilled-pve.ts +147 -0
  188. package/src/proxmox/members-timeout.test.ts +161 -0
  189. package/src/proxmox/members.test.ts +9 -0
  190. package/src/proxmox/members.ts +36 -2
  191. package/dist/litellm/client.d.ts +0 -76
  192. package/dist/litellm/client.d.ts.map +0 -1
  193. package/dist/litellm/credentials.d.ts +0 -48
  194. package/dist/litellm/credentials.d.ts.map +0 -1
  195. package/dist/litellm/generated/pass-through.d.ts +0 -71
  196. package/dist/litellm/generated/pass-through.d.ts.map +0 -1
  197. package/dist/paperless/client.d.ts +0 -37
  198. package/dist/paperless/client.d.ts.map +0 -1
  199. package/dist/paperless/credentials.d.ts +0 -40
  200. package/dist/paperless/credentials.d.ts.map +0 -1
  201. package/dist/paperless/errors.d.ts +0 -49
  202. package/dist/paperless/errors.d.ts.map +0 -1
  203. package/src/litellm/client.ts +0 -195
  204. package/src/litellm/credentials.ts +0 -73
  205. package/src/litellm/generated/pass-through.ts +0 -73
  206. package/src/paperless/client.ts +0 -88
  207. package/src/paperless/credentials.ts +0 -69
  208. package/src/paperless/errors.ts +0 -62
  209. package/src/paperless/matching-identity.test.ts +0 -194
  210. package/src/paperless/matching.test.ts +0 -128
@@ -1,57 +1,19 @@
1
- // src/litellm/credentials.ts
2
- import * as Context from "effect/Context";
3
- import * as Data from "effect/Data";
4
- import * as Effect from "effect/Effect";
5
- import * as Layer from "effect/Layer";
6
- var LITELLM_PROXY_URL_ENV = "LITELLM_PROXY_URL";
7
- var LITELLM_PROXY_API_KEY_ENV = "LITELLM_PROXY_API_KEY";
8
-
9
- class LitellmCredentialsError extends Data.TaggedError("LitellmCredentialsError") {
10
- }
11
- var missing = (name) => new LitellmCredentialsError({
12
- message: `${name} is not set. Export it — the same variable LiteLLM's own \`litellm\` CLI ` + "reads — before running a stack that declares a LiteLLM.PassThroughEndpoint."
13
- });
14
- var resolveCreds = Effect.gen(function* () {
15
- const rawUrl = process.env[LITELLM_PROXY_URL_ENV];
16
- if (rawUrl === undefined || rawUrl.trim() === "")
17
- return yield* Effect.fail(missing(LITELLM_PROXY_URL_ENV));
18
- const rawKey = process.env[LITELLM_PROXY_API_KEY_ENV];
19
- if (rawKey === undefined || rawKey.trim() === "") {
20
- return yield* Effect.fail(missing(LITELLM_PROXY_API_KEY_ENV));
21
- }
22
- return { baseUrl: rawUrl.trim().replace(/\/$/, ""), apiKey: rawKey.trim() };
23
- });
24
-
25
- class LitellmCredentials extends Context.Service()("homeflare/litellm/Credentials") {
26
- }
27
- var litellmCredentialsLayer = Layer.succeed(LitellmCredentials, resolveCreds);
28
- var litellmCredentialsLayerFor = (creds) => Layer.succeed(LitellmCredentials, Effect.succeed(creds));
29
- // src/litellm/client.ts
30
- import * as Data2 from "effect/Data";
1
+ // src/litellm/pass-through-endpoint.ts
2
+ import { Resource } from "alchemy";
3
+ import { Unowned } from "alchemy/AdoptPolicy";
4
+ import { isResolved } from "alchemy/Diff";
5
+ import { createPhysicalName } from "alchemy/PhysicalName";
6
+ import * as Provider from "alchemy/Provider";
31
7
  import * as Effect2 from "effect/Effect";
32
- import * as HttpClient from "effect/unstable/http/HttpClient";
33
- import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
34
- import * as Semaphore from "effect/Semaphore";
35
- var LITELLM_OPERATIONS = {
36
- create: "litellm:POST /config/pass_through_endpoint",
37
- delete: "litellm:DELETE /config/pass_through_endpoint",
38
- list: "litellm:GET /config/pass_through_endpoint",
39
- update: "litellm:POST /config/pass_through_endpoint/{endpoint_id}"
40
- };
41
-
42
- class LitellmUnauthorizedError extends Data2.TaggedError("LitellmUnauthorizedError") {
43
- }
44
-
45
- class LitellmBadRequestError extends Data2.TaggedError("LitellmBadRequestError") {
46
- }
47
-
48
- class LitellmHttpError extends Data2.TaggedError("LitellmHttpError") {
49
- }
8
+ import * as Predicate from "effect/Predicate";
50
9
 
51
- class LitellmTransportError extends Data2.TaggedError("LitellmTransportError") {
52
- }
10
+ // src/litellm/operations.ts
11
+ import * as misc from "@distilled.cloud/litellm/misc";
12
+ import { Credentials } from "@distilled.cloud/litellm/Credentials";
13
+ import * as Effect from "effect/Effect";
14
+ import * as Semaphore from "effect/Semaphore";
53
15
  var semaphores = new Map;
54
- var semaphoreFor = (baseUrl) => Effect2.sync(() => {
16
+ var semaphoreFor = (baseUrl) => Effect.sync(() => {
55
17
  const existing = semaphores.get(baseUrl);
56
18
  if (existing !== undefined)
57
19
  return existing;
@@ -59,49 +21,35 @@ var semaphoreFor = (baseUrl) => Effect2.sync(() => {
59
21
  semaphores.set(baseUrl, created);
60
22
  return created;
61
23
  });
62
- var call = (method, path, body) => Effect2.gen(function* () {
63
- const creds = yield* yield* LitellmCredentials;
64
- const client = yield* HttpClient.HttpClient;
65
- const url = `${creds.baseUrl}${path}`;
66
- const request = HttpClientRequest.make(method)(url).pipe(HttpClientRequest.setHeaders({
67
- Accept: "application/json",
68
- Authorization: `Bearer ${creds.apiKey}`
69
- }), body === undefined ? (self) => self : HttpClientRequest.bodyText(JSON.stringify(body), "application/json"));
70
- const response = yield* client.execute(request).pipe(Effect2.mapError((cause) => new LitellmTransportError({ cause: String(cause), method, path })));
71
- const text = yield* response.text.pipe(Effect2.mapError((cause) => new LitellmTransportError({ cause: String(cause), method, path })));
72
- if (response.status === 401 || response.status === 403) {
73
- return yield* Effect2.fail(new LitellmUnauthorizedError({ method, path, status: response.status }));
74
- }
75
- if (response.status === 400) {
76
- return yield* Effect2.fail(new LitellmBadRequestError({ detail: text.slice(0, 300), method, path }));
77
- }
78
- if (response.status < 200 || response.status >= 300) {
79
- return yield* Effect2.fail(new LitellmHttpError({ detail: text.slice(0, 300), method, path, status: response.status }));
80
- }
81
- return text === "" ? undefined : JSON.parse(text);
82
- });
83
- var listPassThroughEndpoints = () => call("GET", "/config/pass_through_endpoint").pipe(Effect2.map((body) => body.endpoints));
84
- var mutate = (io) => Effect2.gen(function* () {
85
- const creds = yield* yield* LitellmCredentials;
86
- const semaphore = yield* semaphoreFor(creds.baseUrl);
24
+ var mutate = (io) => Effect.gen(function* () {
25
+ const resolve = yield* Credentials;
26
+ const creds = yield* resolve;
27
+ const semaphore = yield* semaphoreFor(creds.apiBaseUrl);
87
28
  return yield* semaphore.withPermits(1)(io);
88
29
  });
89
- var createPassThroughEndpoint = (body) => mutate(call("POST", "/config/pass_through_endpoint", body));
90
- var updatePassThroughEndpoint = (endpointId, body) => mutate(call("POST", `/config/pass_through_endpoint/${encodeURIComponent(endpointId)}`, body));
91
- var deletePassThroughEndpoint = (endpointId) => mutate(call("DELETE", `/config/pass_through_endpoint?endpoint_id=${encodeURIComponent(endpointId)}`).pipe(Effect2.catchTag("LitellmBadRequestError", (original) => Effect2.gen(function* () {
30
+ var listPassThroughEndpoints = () => misc.getPassThroughEndpointsConfigPassThroughEndpointGet({}).pipe(Effect.map((response) => response.endpoints));
31
+ var createPassThroughEndpoint = (body) => mutate(misc.createPassThroughEndpointsConfigPassThroughEndpointPost(body).pipe(Effect.asVoid));
32
+ var updatePassThroughEndpoint = (endpointId, body) => mutate(misc.updatePassThroughEndpointsConfigPassThroughEndpointEndpointIdPost({
33
+ ...body,
34
+ endpoint_id: endpointId
35
+ }).pipe(Effect.asVoid));
36
+ var deletePassThroughEndpoint = (endpointId) => mutate(misc.deletePassThroughEndpointsConfigPassThroughEndpointDelete({ endpoint_id: endpointId }).pipe(Effect.asVoid, Effect.catchTag("BadRequest", (original) => Effect.gen(function* () {
92
37
  const rows = yield* listPassThroughEndpoints();
93
38
  if (rows.some((row) => row.id === endpointId))
94
- return yield* Effect2.fail(original);
95
- })), Effect2.asVoid));
96
- // src/litellm/pass-through-endpoint.ts
97
- import { Resource } from "alchemy";
98
- import { Unowned } from "alchemy/AdoptPolicy";
99
- import { isResolved } from "alchemy/Diff";
100
- import { createPhysicalName } from "alchemy/PhysicalName";
101
- import * as Provider from "alchemy/Provider";
102
- import * as Data3 from "effect/Data";
103
- import * as Effect3 from "effect/Effect";
104
- import * as Predicate from "effect/Predicate";
39
+ return yield* Effect.fail(original);
40
+ }))));
41
+
42
+ // src/litellm/pass-through-errors.ts
43
+ import * as Data from "effect/Data";
44
+
45
+ class LitellmConfigPathConflictError extends Data.TaggedError("LitellmConfigPathConflictError") {
46
+ }
47
+
48
+ class LitellmUnaddressableRowError extends Data.TaggedError("LitellmUnaddressableRowError") {
49
+ }
50
+
51
+ class LitellmLiteralSecretHeaderError extends Data.TaggedError("LitellmLiteralSecretHeaderError") {
52
+ }
105
53
 
106
54
  // src/litellm/pass-through-form.ts
107
55
  import { deepEqual } from "alchemy/Diff";
@@ -141,14 +89,6 @@ var SECRET_HEADER_NAMES = new Set(["authorization", "x-api-key", "cf-aig-authori
141
89
  var literalSecretHeaders = (headers) => Object.entries(headers ?? {}).filter(([name, value]) => SECRET_HEADER_NAMES.has(name.toLowerCase()) && !String(value).includes("os.environ/")).map(([name]) => name);
142
90
 
143
91
  // src/litellm/pass-through-endpoint.ts
144
- class LitellmConfigPathConflictError extends Data3.TaggedError("LitellmConfigPathConflictError") {
145
- }
146
-
147
- class LitellmUnaddressableRowError extends Data3.TaggedError("LitellmUnaddressableRowError") {
148
- }
149
-
150
- class LitellmLiteralSecretHeaderError extends Data3.TaggedError("LitellmLiteralSecretHeaderError") {
151
- }
152
92
  var LiteLLMPassThroughEndpoint = Resource("LiteLLM.PassThroughEndpoint");
153
93
  var isLiteLLMPassThroughEndpoint = (value) => Predicate.hasProperty(value, "Type") && value.Type === "LiteLLM.PassThroughEndpoint";
154
94
  var toAttributes = (row, fallbackId) => ({
@@ -162,10 +102,10 @@ var locate = (rows, objectId, path) => {
162
102
  return { conflict, mine };
163
103
  };
164
104
  var conflictRefusal = (conflict, path) => conflict.is_from_config === true ? new LitellmConfigPathConflictError({ path }) : new LitellmUnaddressableRowError({ path });
165
- var readConflict = (conflict, path) => conflict.is_from_config !== true && conflict.id !== undefined && conflict.id !== null ? Effect3.succeed(Unowned(toAttributes(conflict, conflict.id))) : Effect3.fail(conflictRefusal(conflict, path));
105
+ var readConflict = (conflict, path) => conflict.is_from_config !== true && conflict.id !== undefined && conflict.id !== null ? Effect2.succeed(Unowned(toAttributes(conflict, conflict.id))) : Effect2.fail(conflictRefusal(conflict, path));
166
106
  var refuseLiteralSecrets = (headers) => {
167
107
  const bad = literalSecretHeaders(headers);
168
- return bad.length === 0 ? Effect3.void : Effect3.fail(new LitellmLiteralSecretHeaderError({ headers: bad }));
108
+ return bad.length === 0 ? Effect2.void : Effect2.fail(new LitellmLiteralSecretHeaderError({ headers: bad }));
169
109
  };
170
110
  var passThroughHandlers = {
171
111
  read: ({
@@ -173,7 +113,7 @@ var passThroughHandlers = {
173
113
  instanceId,
174
114
  olds,
175
115
  output
176
- }) => Effect3.gen(function* () {
116
+ }) => Effect2.gen(function* () {
177
117
  const objectId = output?.id ?? (yield* physicalIdOf(id, instanceId));
178
118
  const rows = yield* listPassThroughEndpoints();
179
119
  const { conflict, mine } = locate(rows, objectId, olds.path);
@@ -186,7 +126,7 @@ var passThroughHandlers = {
186
126
  diff: ({
187
127
  news,
188
128
  output
189
- }) => Effect3.gen(function* () {
129
+ }) => Effect2.gen(function* () {
190
130
  if (!isResolved(news))
191
131
  return;
192
132
  yield* refuseLiteralSecrets(news.headers);
@@ -201,17 +141,17 @@ var passThroughHandlers = {
201
141
  instanceId,
202
142
  news,
203
143
  output
204
- }) => Effect3.gen(function* () {
144
+ }) => Effect2.gen(function* () {
205
145
  yield* refuseLiteralSecrets(news.headers);
206
146
  const objectId = output?.id ?? (yield* physicalIdOf(id, instanceId));
207
147
  const rows = yield* listPassThroughEndpoints();
208
148
  const { conflict, mine } = locate(rows, objectId, news.path);
209
149
  if (mine === undefined) {
210
150
  if (conflict !== undefined)
211
- return yield* Effect3.fail(conflictRefusal(conflict, news.path));
151
+ return yield* Effect2.fail(conflictRefusal(conflict, news.path));
212
152
  yield* createPassThroughEndpoint(createBody(news, objectId));
213
153
  } else if (mine.is_from_config === true) {
214
- return yield* Effect3.fail(new LitellmConfigPathConflictError({ path: news.path }));
154
+ return yield* Effect2.fail(new LitellmConfigPathConflictError({ path: news.path }));
215
155
  } else if (needsReplace(toAttributes(mine, objectId), news)) {
216
156
  yield* deletePassThroughEndpoint(objectId);
217
157
  yield* createPassThroughEndpoint(createBody(news, objectId));
@@ -222,7 +162,7 @@ var passThroughHandlers = {
222
162
  }
223
163
  const after = (yield* listPassThroughEndpoints()).find((row) => row.id === objectId);
224
164
  if (after === undefined) {
225
- return yield* Effect3.die(new Error(`LiteLLM.PassThroughEndpoint ${news.path}: the write returned no error but id ` + `${objectId} is still absent from GET /config/pass_through_endpoint — read back ` + "rather than trusting the call that just returned."));
165
+ return yield* Effect2.die(new Error(`LiteLLM.PassThroughEndpoint ${news.path}: the write returned no error but id ` + `${objectId} is still absent from GET /config/pass_through_endpoint — read back ` + "rather than trusting the call that just returned."));
226
166
  }
227
167
  return toAttributes(after, objectId);
228
168
  }),
@@ -231,7 +171,7 @@ var passThroughHandlers = {
231
171
  instanceId,
232
172
  olds,
233
173
  output
234
- }) => Effect3.gen(function* () {
174
+ }) => Effect2.gen(function* () {
235
175
  const objectId = output.id ?? (yield* physicalIdOf(id, instanceId));
236
176
  const rows = yield* listPassThroughEndpoints();
237
177
  const live = rows.find((row) => row.id === objectId);
@@ -239,32 +179,22 @@ var passThroughHandlers = {
239
179
  return;
240
180
  yield* deletePassThroughEndpoint(objectId);
241
181
  }),
242
- list: () => Effect3.succeed([])
182
+ list: () => Effect2.succeed([])
243
183
  };
244
- var LiteLLMPassThroughEndpointProvider = () => Provider.effect(LiteLLMPassThroughEndpoint, Effect3.succeed(LiteLLMPassThroughEndpoint.Provider.of(passThroughHandlers)));
184
+ var LiteLLMPassThroughEndpointProvider = () => Provider.effect(LiteLLMPassThroughEndpoint, Effect2.succeed(LiteLLMPassThroughEndpoint.Provider.of(passThroughHandlers)));
245
185
  // src/litellm/providers.ts
246
- import * as Layer2 from "effect/Layer";
247
- var litellmProviders = (creds = litellmCredentialsLayer) => LiteLLMPassThroughEndpointProvider().pipe(Layer2.provide(creds));
186
+ import { CredentialsFromEnv } from "@distilled.cloud/litellm/Credentials";
187
+ import * as Layer from "effect/Layer";
188
+ var litellmProviders = (creds = CredentialsFromEnv) => LiteLLMPassThroughEndpointProvider().pipe(Layer.provide(creds));
248
189
  export {
249
- LITELLM_OPERATIONS,
250
- LITELLM_PROXY_API_KEY_ENV,
251
- LITELLM_PROXY_URL_ENV,
252
190
  LiteLLMPassThroughEndpoint,
253
191
  LiteLLMPassThroughEndpointProvider,
254
- LitellmBadRequestError,
255
192
  LitellmConfigPathConflictError,
256
- LitellmCredentials,
257
- LitellmCredentialsError,
258
- LitellmHttpError,
259
193
  LitellmLiteralSecretHeaderError,
260
- LitellmTransportError,
261
194
  LitellmUnaddressableRowError,
262
- LitellmUnauthorizedError,
263
195
  isLiteLLMPassThroughEndpoint,
264
- litellmCredentialsLayer,
265
- litellmCredentialsLayerFor,
266
196
  litellmProviders
267
197
  };
268
198
 
269
- //# debugId=9216FE33E5E3721264756E2164756E21
199
+ //# debugId=F883BA858F0CF3AD64756E2164756E21
270
200
  //# sourceMappingURL=index.js.map
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/litellm/credentials.ts", "../src/litellm/client.ts", "../src/litellm/pass-through-endpoint.ts", "../src/litellm/pass-through-form.ts", "../src/litellm/providers.ts"],
3
+ "sources": ["../src/litellm/pass-through-endpoint.ts", "../src/litellm/operations.ts", "../src/litellm/pass-through-errors.ts", "../src/litellm/pass-through-form.ts", "../src/litellm/providers.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * The lazy Auth service every LiteLLM call reads from, and nothing else reads the environment.\n *\n * ★ LITELLM'S OWN VARIABLE NAMES, NOT A HOUSE CHOICE. `LITELLM_PROXY_URL` and\n * `LITELLM_PROXY_API_KEY` are what LiteLLM's own CLI client reads\n * (litellm/proxy/client/cli/main.py:70,78 at tag v1.100.0) — using the vendor's own names means\n * a consumer who already has a `.env` for the `litellm` CLI needs nothing new for this package.\n * ⛔ NO DEFAULT URL. A published package that fell back to a loopback address would let a\n * consumer who forgot the variable watch every call fail against a proxy that is not theirs,\n * instead of being told which variable is missing (S24/S25 — the house rule, not a vendor one).\n * ⛔ THE KEY IS NEVER A PROP. Alchemy persists attributes unencrypted (S25); the master key that\n * `update_config_general_settings` requires (PROXY_ADMIN only, proxy_server.py:16411 at the\n * tag) is read fresh from the environment on every call, never stored in state.\n * ★ LAZY: the service's VALUE is an `Effect` that resolves the credential, not the credential\n * itself — so a layer built once still reads the environment inside each operation\n * (`yield* yield* LitellmCredentials`), the idiom `alchemy/Auth`'s custom-auth-provider guide\n * describes for a credential a layer must not capture at build time.\n */\nimport * as Context from 'effect/Context';\nimport * as Data from 'effect/Data';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\n\nexport const LITELLM_PROXY_URL_ENV = 'LITELLM_PROXY_URL';\nexport const LITELLM_PROXY_API_KEY_ENV = 'LITELLM_PROXY_API_KEY';\n\nexport interface LitellmCreds {\n /** Trailing slash stripped. No default — see the header. */\n readonly baseUrl: string;\n /** LiteLLM's master (or a PROXY_ADMIN) key. Never logged, never an attribute. */\n readonly apiKey: string;\n}\n\nexport class LitellmCredentialsError extends Data.TaggedError('LitellmCredentialsError')<{\n readonly message: string;\n}> {}\n\nconst missing = (name: string): LitellmCredentialsError =>\n new LitellmCredentialsError({\n message:\n `${name} is not set. Export it — the same variable LiteLLM's own \\`litellm\\` CLI ` +\n 'reads — before running a stack that declares a LiteLLM.PassThroughEndpoint.',\n });\n\n/** Read at call time. Exported so a test can call it directly against `process.env`. */\nexport const resolveCreds: Effect.Effect<LitellmCreds, LitellmCredentialsError> = Effect.gen(\n function* () {\n const rawUrl = process.env[LITELLM_PROXY_URL_ENV];\n if (rawUrl === undefined || rawUrl.trim() === '')\n return yield* Effect.fail(missing(LITELLM_PROXY_URL_ENV));\n const rawKey = process.env[LITELLM_PROXY_API_KEY_ENV];\n if (rawKey === undefined || rawKey.trim() === '') {\n return yield* Effect.fail(missing(LITELLM_PROXY_API_KEY_ENV));\n }\n return { baseUrl: rawUrl.trim().replace(/\\/$/, ''), apiKey: rawKey.trim() };\n },\n);\n\n/** The Effect service a LiteLLM operation reads: `yield* yield* LitellmCredentials`. */\nexport class LitellmCredentials extends Context.Service<\n LitellmCredentials,\n Effect.Effect<LitellmCreds, LitellmCredentialsError>\n>()('homeflare/litellm/Credentials') {}\n\n/** The default layer: resolves from the environment, fresh, on every `yield*`. */\nexport const litellmCredentialsLayer: Layer.Layer<LitellmCredentials> = Layer.succeed(\n LitellmCredentials,\n resolveCreds,\n);\n\n/** For a test: a fixed credential, never touching the environment. */\nexport const litellmCredentialsLayerFor = (creds: LitellmCreds): Layer.Layer<LitellmCredentials> =>\n Layer.succeed(LitellmCredentials, Effect.succeed(creds));\n",
6
- "/**\n * The four LiteLLM proxy calls a `LiteLLM.PassThroughEndpoint` needs, and nothing else reaches\n * LiteLLM's `/config/pass_through_endpoint` routes.\n *\n * ⛔ WRAPPED IN A PER-BASE-URL SEMAPHORE. LiteLLM stores every pass-through endpoint in ONE\n * `general_settings.pass_through_endpoints` list (pass_through_endpoints.py at tag v1.100.0),\n * so create/update/delete are each a read-modify-write of the WHOLE list through\n * `update_config_general_settings`. Two of this package's own calls racing each other — two\n * endpoints created in the same deploy — would each read the list, add their own row and write\n * it back, and the second write would silently drop the first row. One permit per proxy\n * serialises this package's own writes; it cannot serialise against the LiteLLM UI or a second\n * deploy process, which is why `reconcile` reads back after writing rather than trusting the\n * call that just returned (docs/litellm.md).\n * ★ `Authorization: Bearer <key>` — LiteLLM's own client uses it (litellm/proxy/client/cli, and\n * every `/config/*` route decorator at the tag takes `user_api_key_dict = Depends(user_api_key_auth)`,\n * which accepts a bearer token). Every mutation additionally requires the caller be\n * PROXY_ADMIN (`update_config_general_settings`, proxy_server.py:16411 at the tag) — an\n * ordinary virtual key gets `LitellmUnauthorizedError`, not a clearer 403 body naming the role.\n * ⛔ NO MESSAGE SNIFFING (S21). Every status this file maps becomes a typed tag; nothing here or\n * above it matches an error body's text. Deleting an id LiteLLM does not have answers 400\n * (measured against the tag's `pass_through_endpoint_delete` — the id is looked up in the list\n * and a miss raises `HTTPException(400)`, not 404) — but so does a genuinely-live row when the\n * caller isn't PROXY_ADMIN, or the DB is disconnected (`update_config_general_settings`,\n * proxy_server.py:16389-16416 at the tag): the SAME status, for a delete that did NOT happen.\n * `deletePassThroughEndpoint` tells them apart by re-listing (a GET, which needs no PROXY_ADMIN —\n * proxy_server.py:3245-3251) rather than by the 400's body text — see its own comment.\n */\nimport * as Data from 'effect/Data';\nimport * as Effect from 'effect/Effect';\nimport * as HttpClient from 'effect/unstable/http/HttpClient';\nimport * as HttpClientRequest from 'effect/unstable/http/HttpClientRequest';\nimport * as Semaphore from 'effect/Semaphore';\nimport { LitellmCredentials, type LitellmCredentialsError } from './credentials.ts';\nimport type {\n PassThroughEndpointResponse,\n PassThroughGenericEndpoint,\n} from './generated/pass-through.ts';\n\nexport type LitellmRequirements = HttpClient.HttpClient | LitellmCredentials;\n\n/**\n * The `litellm:<METHOD> <path>` operations this package writes to and reads from.\n *\n * ★ `codegen/litellm.ts` scans this FILE's text for these exact literals to pick which of\n * LiteLLM 1.100.0's 696 paths to generate types from (codegen/litellm.ts header). Keep each one\n * a literal string on one line; the generator matches text, it does not evaluate the object.\n */\nexport const LITELLM_OPERATIONS = {\n create: 'litellm:POST /config/pass_through_endpoint',\n delete: 'litellm:DELETE /config/pass_through_endpoint',\n list: 'litellm:GET /config/pass_through_endpoint',\n update: 'litellm:POST /config/pass_through_endpoint/{endpoint_id}',\n} as const;\n\nexport class LitellmUnauthorizedError extends Data.TaggedError('LitellmUnauthorizedError')<{\n readonly status: number;\n readonly method: string;\n readonly path: string;\n}> {}\nexport class LitellmBadRequestError extends Data.TaggedError('LitellmBadRequestError')<{\n readonly method: string;\n readonly path: string;\n readonly detail: string;\n}> {}\nexport class LitellmHttpError extends Data.TaggedError('LitellmHttpError')<{\n readonly status: number;\n readonly method: string;\n readonly path: string;\n readonly detail: string;\n}> {}\nexport class LitellmTransportError extends Data.TaggedError('LitellmTransportError')<{\n readonly method: string;\n readonly path: string;\n readonly cause: string;\n}> {}\n\nexport type LitellmError =\n | LitellmUnauthorizedError\n | LitellmBadRequestError\n | LitellmHttpError\n | LitellmTransportError\n | LitellmCredentialsError;\n\nconst semaphores = new Map<string, Semaphore.Semaphore>();\n\n/** One semaphore per base URL, created on first use. Never `Hash.structure` (S18) — a plain Map key. */\nconst semaphoreFor = (baseUrl: string): Effect.Effect<Semaphore.Semaphore> =>\n Effect.sync(() => {\n const existing = semaphores.get(baseUrl);\n if (existing !== undefined) return existing;\n const created = Semaphore.makeUnsafe(1);\n semaphores.set(baseUrl, created);\n return created;\n });\n\nconst call = <T>(method: 'GET' | 'POST' | 'DELETE', path: string, body?: unknown) =>\n Effect.gen(function* () {\n const creds = yield* yield* LitellmCredentials;\n const client = yield* HttpClient.HttpClient;\n const url = `${creds.baseUrl}${path}`;\n const request = HttpClientRequest.make(method)(url).pipe(\n HttpClientRequest.setHeaders({\n Accept: 'application/json',\n Authorization: `Bearer ${creds.apiKey}`,\n }),\n body === undefined\n ? (self) => self\n : HttpClientRequest.bodyText(JSON.stringify(body), 'application/json'),\n );\n const response = yield* client\n .execute(request)\n .pipe(\n Effect.mapError(\n (cause) => new LitellmTransportError({ cause: String(cause), method, path }),\n ),\n );\n const text = yield* response.text.pipe(\n Effect.mapError((cause) => new LitellmTransportError({ cause: String(cause), method, path })),\n );\n if (response.status === 401 || response.status === 403) {\n return yield* Effect.fail(\n new LitellmUnauthorizedError({ method, path, status: response.status }),\n );\n }\n if (response.status === 400) {\n return yield* Effect.fail(\n new LitellmBadRequestError({ detail: text.slice(0, 300), method, path }),\n );\n }\n if (response.status < 200 || response.status >= 300) {\n return yield* Effect.fail(\n new LitellmHttpError({ detail: text.slice(0, 300), method, path, status: response.status }),\n );\n }\n return (text === '' ? undefined : JSON.parse(text)) as T;\n });\n\n/** GET /config/pass_through_endpoint — every row, config-file and DB alike. Not under the semaphore: reads don't race the field. */\nexport const listPassThroughEndpoints = (): Effect.Effect<\n readonly PassThroughGenericEndpoint[],\n LitellmError,\n LitellmRequirements\n> =>\n call<PassThroughEndpointResponse>('GET', '/config/pass_through_endpoint').pipe(\n Effect.map((body) => body.endpoints),\n );\n\nconst mutate = <T>(io: Effect.Effect<T, LitellmError, LitellmRequirements>) =>\n Effect.gen(function* () {\n const creds = yield* yield* LitellmCredentials;\n const semaphore = yield* semaphoreFor(creds.baseUrl);\n return yield* semaphore.withPermits(1)(io);\n });\n\n/** POST /config/pass_through_endpoint. `body` carries `id` — see pass-through-endpoint.ts. */\nexport const createPassThroughEndpoint = (\n body: PassThroughGenericEndpoint,\n): Effect.Effect<void, LitellmError, LitellmRequirements> =>\n mutate(call('POST', '/config/pass_through_endpoint', body));\n\n/** POST /config/pass_through_endpoint/{endpoint_id}. Merges with `exclude_none` — see pass-through-form.ts. */\nexport const updatePassThroughEndpoint = (\n endpointId: string,\n body: Partial<PassThroughGenericEndpoint>,\n): Effect.Effect<void, LitellmError, LitellmRequirements> =>\n mutate(call('POST', `/config/pass_through_endpoint/${encodeURIComponent(endpointId)}`, body));\n\n/**\n * DELETE /config/pass_through_endpoint?endpoint_id=… — idempotent BY THIS FUNCTION, not by the\n * vendor. ⚠️ Measured at v1.100.0: deleting an id the list does not have raises `HTTPException(400)`\n * from `pass_through_endpoint_delete` — but the SAME route also 400s `not_allowed_access` for a\n * non-PROXY_ADMIN caller or a disconnected DB (`update_config_general_settings`,\n * proxy_server.py:16389-16416), on a row that never got deleted. A 400 alone cannot tell the two\n * apart, so THIS FUNCTION DOESN'T GUESS FROM THE STATUS ALONE: on 400 it re-lists (a GET — no\n * PROXY_ADMIN required, proxy_server.py:3245-3251) and only treats the delete as already-done if\n * `endpointId` is genuinely absent; otherwise the delete failed and this re-fails with the ORIGINAL\n * error, not a message match (S21 — a status-and-a-real-read decision, never body text).\n */\nexport const deletePassThroughEndpoint = (\n endpointId: string,\n): Effect.Effect<void, LitellmError, LitellmRequirements> =>\n mutate(\n call(\n 'DELETE',\n `/config/pass_through_endpoint?endpoint_id=${encodeURIComponent(endpointId)}`,\n ).pipe(\n Effect.catchTag('LitellmBadRequestError', (original) =>\n Effect.gen(function* () {\n const rows = yield* listPassThroughEndpoints();\n if (rows.some((row) => row.id === endpointId)) return yield* Effect.fail(original);\n }),\n ),\n Effect.asVoid,\n ),\n );\n",
7
- "/**\n * `LiteLLM.PassThroughEndpoint` — one row in LiteLLM's `general_settings.pass_through_endpoints`.\n *\n * ★ ADOPT-FRIENDLY BY id, NOT BY PATH. `output?.id` is used as the object's live id once the\n * engine has one — from our own prior create (the deterministic physical name) or from an\n * adopted foreign row — and `read` computes a FRESH physical name only for a resource the\n * engine has never resolved before. This is S7/S9's \"output is a cache of stable identifiers,\n * not proof the object exists\" and S13's \"an adopted object keeps its live name as an explicit\n * prop\", applied to an id LiteLLM lets a client choose (`_types.py:2192` at v1.100.0: create\n * takes a caller-supplied `id`, else `uuid4()`).\n *\n * ⛔ A PATH HELD BY AN `is_from_config` ROW IS REFUSED, NOT ADOPTED. A DB row on the same path\n * overrides it at runtime (`pass_through_endpoints.py` merges DB after config, at the tag) — so\n * creating one would silently take over a route the operator declared in `config.yaml`, the\n * exact \"DB row silently overrides the file\" the task names. `is_from_config` rows are also\n * never updated or deleted by this provider, for the same reason.\n * ⛔ A DB ROW WITH NO `id` (path-only, `_types.py`'s \"backwards compatibility\" case) CANNOT BE\n * ADDRESSED by the id-keyed update/delete calls this provider uses, so it is refused rather than\n * silently adopted into an id-based lifecycle it cannot actually manage — see docs/litellm.md.\n * ⛔ NO CREDENTIAL IS A PROP (S25). `LITELLM_PROXY_URL`/`LITELLM_PROXY_API_KEY` are read at call\n * time by credentials.ts.\n */\nimport { Resource } from 'alchemy';\nimport { Unowned } from 'alchemy/AdoptPolicy';\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport { createPhysicalName } from 'alchemy/PhysicalName';\nimport * as Provider from 'alchemy/Provider';\nimport type { Stack } from 'alchemy/Stack';\nimport type { Stage } from 'alchemy/Stage';\nimport * as Data from 'effect/Data';\nimport * as Effect from 'effect/Effect';\nimport * as Predicate from 'effect/Predicate';\nimport {\n type LitellmError,\n type LitellmRequirements,\n createPassThroughEndpoint,\n deletePassThroughEndpoint,\n listPassThroughEndpoints,\n updatePassThroughEndpoint,\n} from './client.ts';\nimport type { PassThroughGenericEndpoint } from './generated/pass-through.ts';\nimport {\n type PassThroughEndpointAttributes,\n type PassThroughEndpointProps,\n createBody,\n literalSecretHeaders,\n matches,\n needsReplace,\n updateBody,\n} from './pass-through-form.ts';\n\nexport type { PassThroughEndpointAttributes, PassThroughEndpointProps };\n\nexport class LitellmConfigPathConflictError extends Data.TaggedError(\n 'LitellmConfigPathConflictError',\n)<{\n readonly path: string;\n}> {}\nexport class LitellmUnaddressableRowError extends Data.TaggedError('LitellmUnaddressableRowError')<{\n readonly path: string;\n}> {}\nexport class LitellmLiteralSecretHeaderError extends Data.TaggedError(\n 'LitellmLiteralSecretHeaderError',\n)<{\n readonly headers: readonly string[];\n}> {}\n\nexport type PassThroughEndpointError =\n | LitellmError\n | LitellmConfigPathConflictError\n | LitellmUnaddressableRowError\n | LitellmLiteralSecretHeaderError;\n\nexport interface LiteLLMPassThroughEndpoint extends Resource<\n 'LiteLLM.PassThroughEndpoint',\n PassThroughEndpointProps,\n PassThroughEndpointAttributes,\n never,\n LitellmRequirements | Stack | Stage\n> {}\n\nexport const LiteLLMPassThroughEndpoint = Resource<LiteLLMPassThroughEndpoint>(\n 'LiteLLM.PassThroughEndpoint',\n);\n\nexport const isLiteLLMPassThroughEndpoint = (value: unknown): value is LiteLLMPassThroughEndpoint =>\n Predicate.hasProperty(value, 'Type') && value.Type === 'LiteLLM.PassThroughEndpoint';\n\nconst toAttributes = (\n row: PassThroughGenericEndpoint,\n fallbackId: string,\n): PassThroughEndpointAttributes => ({\n ...row,\n id: row.id ?? fallbackId,\n});\n\nconst physicalIdOf = (logicalId: string, instanceId: string) =>\n createPhysicalName({ id: logicalId, instanceId, lowercase: true, maxLength: 64 });\n\n/**\n * Find this resource's live row (by id) and, when absent, the row that already holds its `path`\n * (a config-file row to refuse, or a DB row LiteLLM did not give an id — also refused, see the\n * file header — or a genuine foreign DB row to hand back `Unowned`).\n */\nconst locate = (\n rows: readonly PassThroughGenericEndpoint[],\n objectId: string,\n path: string,\n): {\n readonly mine: PassThroughGenericEndpoint | undefined;\n readonly conflict: PassThroughGenericEndpoint | undefined;\n} => {\n const mine = rows.find((row) => row.id === objectId);\n const conflict = mine === undefined ? rows.find((row) => row.path === path) : undefined;\n return { conflict, mine };\n};\n\n/** The typed refusal for a `path` conflict that cannot ever be adopted (config row, or no id). */\nconst conflictRefusal = (conflict: PassThroughGenericEndpoint, path: string) =>\n conflict.is_from_config === true\n ? new LitellmConfigPathConflictError({ path })\n : new LitellmUnaddressableRowError({ path });\n\n/** `read`'s answer for a path conflict: `Unowned` when it is a real, addressable DB row — a typed refusal otherwise. */\nconst readConflict = (conflict: PassThroughGenericEndpoint, path: string) =>\n conflict.is_from_config !== true && conflict.id !== undefined && conflict.id !== null\n ? Effect.succeed(Unowned(toAttributes(conflict, conflict.id)))\n : Effect.fail(conflictRefusal(conflict, path));\n\nconst refuseLiteralSecrets = (headers: Readonly<Record<string, unknown>> | undefined) => {\n const bad = literalSecretHeaders(headers);\n return bad.length === 0\n ? Effect.void\n : Effect.fail(new LitellmLiteralSecretHeaderError({ headers: bad }));\n};\n\n/** ⛔ TEST-ONLY EXPORT. Not on index.ts's barrel — a lifecycle test calls these directly against the fake. */\nexport const passThroughHandlers = {\n read: ({\n id,\n instanceId,\n olds,\n output,\n }: {\n id: string;\n instanceId: string;\n olds: PassThroughEndpointProps;\n output: PassThroughEndpointAttributes | undefined;\n }) =>\n Effect.gen(function* () {\n const objectId = output?.id ?? (yield* physicalIdOf(id, instanceId));\n const rows = yield* listPassThroughEndpoints();\n const { conflict, mine } = locate(rows, objectId, olds.path);\n if (mine !== undefined) return toAttributes(mine, objectId);\n if (conflict === undefined) return undefined;\n return yield* readConflict(conflict, olds.path);\n }),\n\n diff: ({\n news,\n output,\n }: {\n news: Input<PassThroughEndpointProps>;\n output: PassThroughEndpointAttributes | undefined;\n }) =>\n Effect.gen(function* () {\n if (!isResolved(news)) return undefined;\n yield* refuseLiteralSecrets(news.headers);\n if (output === undefined) return undefined;\n // ⛔ deleteFirst: TRUE — a create-first replace mints a new instanceId/id before the old row\n // on `path` is gone, so the new generation's `reconcile` would refuse it as a foreign\n // conflict (Apply.ts). Same fix this kit's other unique-identity providers use.\n if (needsReplace(output, news)) return { action: 'replace', deleteFirst: true } as const;\n return matches(output, news)\n ? ({ action: 'noop' } as const)\n : ({ action: 'update' } as const);\n }),\n\n reconcile: ({\n id,\n instanceId,\n news,\n output,\n }: {\n id: string;\n instanceId: string;\n news: PassThroughEndpointProps;\n output: PassThroughEndpointAttributes | undefined;\n }) =>\n Effect.gen(function* () {\n yield* refuseLiteralSecrets(news.headers);\n const objectId = output?.id ?? (yield* physicalIdOf(id, instanceId));\n const rows = yield* listPassThroughEndpoints();\n const { conflict, mine } = locate(rows, objectId, news.path);\n\n if (mine === undefined) {\n // ⚠️ A CONFLICT HERE — reconcile, not read — means ownership shifted between plan and\n // apply (a config row or a foreign DB row landed on this path after `read` cleared it).\n // `read` gates a genuine adopt by returning `Unowned`; reconcile itself never adopts,\n // so ANY conflict here fails rather than risking a second row on one path.\n if (conflict !== undefined) return yield* Effect.fail(conflictRefusal(conflict, news.path));\n yield* createPassThroughEndpoint(createBody(news, objectId));\n } else if (mine.is_from_config === true) {\n // ⛔ NEVER UPDATE OR DELETE AN `is_from_config` ROW, even one this resource's own\n // deterministic id happens to match (a config.yaml author could in principle choose the\n // same id `createPhysicalName` would). Refuse rather than silently editing the file's row.\n return yield* Effect.fail(new LitellmConfigPathConflictError({ path: news.path }));\n } else if (needsReplace(toAttributes(mine, objectId), news)) {\n yield* deletePassThroughEndpoint(objectId);\n yield* createPassThroughEndpoint(createBody(news, objectId));\n } else if (!matches(toAttributes(mine, objectId), news)) {\n const body = updateBody(news);\n if (Object.keys(body).length > 0) yield* updatePassThroughEndpoint(objectId, body);\n }\n\n const after = (yield* listPassThroughEndpoints()).find((row) => row.id === objectId);\n if (after === undefined) {\n return yield* Effect.die(\n new Error(\n `LiteLLM.PassThroughEndpoint ${news.path}: the write returned no error but id ` +\n `${objectId} is still absent from GET /config/pass_through_endpoint — read back ` +\n 'rather than trusting the call that just returned.',\n ),\n );\n }\n return toAttributes(after, objectId);\n }),\n\n delete: ({\n id,\n instanceId,\n olds,\n output,\n }: {\n id: string;\n instanceId: string;\n olds: PassThroughEndpointProps;\n output: PassThroughEndpointAttributes;\n }) =>\n Effect.gen(function* () {\n const objectId = output.id ?? (yield* physicalIdOf(id, instanceId));\n const rows = yield* listPassThroughEndpoints();\n const live = rows.find((row) => row.id === objectId);\n // ⛔ NEVER DELETE AN `is_from_config` ROW, and a DB row this resource never created (a path\n // match with a different id) is not this resource's to remove either.\n if (live === undefined || live.is_from_config === true || live.path !== olds.path) return;\n yield* deletePassThroughEndpoint(objectId);\n }),\n\n list: () => Effect.succeed([]),\n};\n\nexport const LiteLLMPassThroughEndpointProvider = () =>\n Provider.effect(\n LiteLLMPassThroughEndpoint,\n Effect.succeed(LiteLLMPassThroughEndpoint.Provider.of(passThroughHandlers)),\n );\n",
8
- "/**\n * The wire body for a `LiteLLM.PassThroughEndpoint`, the comparison that decides whether it needs\n * writing, and the refusals that stop a plan before it writes anything unsafe.\n *\n * ★ EXTRACTED SO IT CAN BE TESTED WITHOUT A SERVER — the same reason netbox keeps `prefix-form.ts`\n * beside `prefix.ts` (S32/testing-and-docs.md).\n *\n * ⛔ PROPS ARE THE GENERATED TYPE, MINUS THE TWO FIELDS THIS RESOURCE OWNS ITSELF: `id` (a\n * deterministic physical name — pass-through-endpoint.ts) and `is_from_config` (response-only;\n * the vendor sets it, a declaration never does). Deriving `Props` with `Omit<>` rather than\n * hand-typing it means a vendor schema change that adds, removes or narrows a field is felt here\n * as a compiler error, not silently ignored.\n */\nimport { deepEqual } from 'alchemy/Diff';\nimport type * as Generated from './generated/pass-through.ts';\n\nexport type PassThroughEndpointProps = Omit<\n Generated.PassThroughGenericEndpoint,\n 'id' | 'is_from_config'\n>;\n\n/** What `read` returns: the props plus the two vendor-owned fields, `id` now guaranteed present. */\nexport type PassThroughEndpointAttributes = Omit<Generated.PassThroughGenericEndpoint, 'id'> & {\n readonly id: string;\n};\n\n/** ⚠️ NetBox `settled()`'s pattern: only fields the SCHEMA gives a vendor default for, copied from it (not assumed). */\nexport const settled = (props: PassThroughEndpointProps) => ({\n auth: props.auth ?? true,\n cost_per_request: props.cost_per_request ?? 0,\n default_query_params: props.default_query_params ?? {},\n headers: props.headers ?? {},\n include_subpath: props.include_subpath ?? false,\n});\n\n/** The three fields whose absence the vendor's `exclude_none` update can never write (see client.ts). */\nexport const NULLABLE_FIELDS = ['timeout', 'methods', 'guardrails'] as const;\n\nconst isUnset = (value: unknown): boolean => value === undefined || value === null;\n\n/**\n * ⚠️ BUILT AS A WIDER RECORD AND PRUNED, NOT AS THE GENERATED TYPE DIRECTLY.\n * `exactOptionalPropertyTypes` is on (packages/config/tsconfig.base.json), so writing\n * `timeout: undefined` into a `{ timeout?: number | null }` is a type error rather than an\n * absent key — the same reason `codegen/openapi.ts`'s `prune` exists, and the same fix.\n */\nconst prune = (value: Record<string, unknown>): Record<string, unknown> =>\n Object.fromEntries(Object.entries(value).filter(([, v]) => v !== undefined));\n\n/**\n * Full body for CREATE. `id` is the deterministic physical name (pass-through-endpoint.ts), sent\n * so a failed create is recoverable by `read` rather than orphaning a second row on retry.\n */\nexport const createBody = (\n props: PassThroughEndpointProps,\n id: string,\n): Generated.PassThroughGenericEndpoint =>\n prune({\n ...settled(props),\n guardrails: isUnset(props.guardrails) ? undefined : props.guardrails,\n id,\n methods: isUnset(props.methods) ? undefined : props.methods,\n path: props.path,\n target: props.target,\n timeout: isUnset(props.timeout) ? undefined : props.timeout,\n }) as unknown as Generated.PassThroughGenericEndpoint;\n\n/**\n * Partial body for UPDATE (`POST /{id}`). ⛔ ONLY FIELDS THIS DECLARATION ACTUALLY SETS — the\n * vendor merges the parsed body with `model_dump(exclude_none=True)` (measured at v1.100.0), so an\n * `undefined` OR an explicit `null` here would be dropped by the server anyway; sending neither is\n * the same outcome with no request made when nothing changed (`Object.keys(body).length === 0`\n * checked by the caller in pass-through-endpoint.ts).\n */\nexport const updateBody = (\n props: PassThroughEndpointProps,\n): Partial<Generated.PassThroughGenericEndpoint> =>\n prune({\n ...settled(props),\n guardrails: isUnset(props.guardrails) ? undefined : props.guardrails,\n methods: isUnset(props.methods) ? undefined : props.methods,\n path: props.path,\n target: props.target,\n timeout: isUnset(props.timeout) ? undefined : props.timeout,\n }) as Partial<Generated.PassThroughGenericEndpoint>;\n\n/**\n * Whether ANY of the three nullable fields went from set (in `live`) to unset (in `props`) — the\n * one case `updateBody` cannot express, because the vendor's `exclude_none` merge silently keeps\n * the old value instead of clearing it. Detected here so `pass-through-endpoint.ts` can plan a\n * `replace` (delete-then-create) instead of an update that would look like it worked.\n */\nexport const needsReplace = (\n live: PassThroughEndpointAttributes,\n props: PassThroughEndpointProps,\n): boolean => NULLABLE_FIELDS.some((field) => !isUnset(live[field]) && isUnset(props[field]));\n\n/** Whether the live object already says what the declaration says — the `diff` \"noop\" test. */\nexport const matches = (\n live: PassThroughEndpointAttributes,\n props: PassThroughEndpointProps,\n): boolean => {\n const fixed = settled(props);\n return (\n live.target === props.target &&\n live.auth === fixed.auth &&\n live.cost_per_request === fixed.cost_per_request &&\n live.include_subpath === fixed.include_subpath &&\n deepEqual(live.headers, fixed.headers) &&\n deepEqual(live.default_query_params, fixed.default_query_params) &&\n (isUnset(props.timeout) ? isUnset(live.timeout) : live.timeout === props.timeout) &&\n (isUnset(props.methods) ? isUnset(live.methods) : deepEqual(live.methods, props.methods)) &&\n (isUnset(props.guardrails)\n ? isUnset(live.guardrails)\n : deepEqual(live.guardrails, props.guardrails))\n );\n};\n\n/**\n * A literal secret in a forwarded header (S25, house rule — not a vendor one; see\n * pass-through-endpoint.ts). Case-insensitive on the header name; the reference form is LiteLLM's\n * own, `os.environ/NAME` (`set_env_variables_in_header`, pass_through_endpoints.py:117-160 at the\n * tag) — a missing variable on the proxy host leaves that literal string in the header, which\n * nothing in the API can detect, so this is enforced here rather than trusted to the vendor.\n */\nconst SECRET_HEADER_NAMES = new Set(['authorization', 'x-api-key', 'cf-aig-authorization']);\n\nexport const literalSecretHeaders = (\n headers: Readonly<Record<string, unknown>> | undefined,\n): readonly string[] =>\n Object.entries(headers ?? {})\n .filter(\n ([name, value]) =>\n SECRET_HEADER_NAMES.has(name.toLowerCase()) && !String(value).includes('os.environ/'),\n )\n .map(([name]) => name);\n",
9
- "/**\n * The LiteLLM provider, with its credential source, as one layer for a stack.\n *\n * Layer.mergeAll(litellmProviders(), …the stack's other providers)\n *\n * ★ THE DEFAULT READS `LITELLM_PROXY_URL`/`LITELLM_PROXY_API_KEY` AT CALL TIME (credentials.ts),\n * never at layer build — pass another `Layer.Layer<LitellmCredentials>` (see\n * `litellmCredentialsLayerFor` in a test) to source them another way.\n * ⚠️ `HttpClient` is NOT provided here. It is ambient in every Alchemy runtime the same way it is\n * for `netboxProviders`-style families in this kit; a stack that already deploys anything over\n * HTTP already has one.\n */\nimport * as Layer from 'effect/Layer';\nimport { type LitellmCredentials, litellmCredentialsLayer } from './credentials.ts';\nimport { LiteLLMPassThroughEndpointProvider } from './pass-through-endpoint.ts';\n\nexport const litellmProviders = (\n creds: Layer.Layer<LitellmCredentials> = litellmCredentialsLayer,\n) => LiteLLMPassThroughEndpointProvider().pipe(Layer.provide(creds));\n"
5
+ "/**\n * `LiteLLM.PassThroughEndpoint` — one row in LiteLLM's `general_settings.pass_through_endpoints`.\n *\n * ★ ADOPT-FRIENDLY BY id, NOT BY PATH. `output?.id` is used as the object's live id once the\n * engine has one — from our own prior create (the deterministic physical name) or from an\n * adopted foreign row — and `read` computes a FRESH physical name only for a resource the\n * engine has never resolved before. This is S7/S9's \"output is a cache of stable identifiers,\n * not proof the object exists\" and S13's \"an adopted object keeps its live name as an explicit\n * prop\", applied to an id LiteLLM lets a client choose (`_types.py:2192` at v1.100.0: create\n * takes a caller-supplied `id`, else `uuid4()`).\n *\n * ⛔ A PATH HELD BY AN `is_from_config` ROW IS REFUSED, NOT ADOPTED. A DB row on the same path\n * overrides it at runtime (`pass_through_endpoints.py` merges DB after config, at the tag) — so\n * creating one would silently take over a route the operator declared in `config.yaml`, the\n * exact \"DB row silently overrides the file\" the task names. `is_from_config` rows are also\n * never updated or deleted by this provider, for the same reason.\n * ⛔ A DB ROW WITH NO `id` (path-only, `_types.py`'s \"backwards compatibility\" case) CANNOT BE\n * ADDRESSED by the id-keyed update/delete calls this provider uses, so it is refused rather than\n * silently adopted into an id-based lifecycle it cannot actually manage — see docs/litellm.md.\n * ⛔ NO CREDENTIAL IS A PROP (S25). `LITELLM_PROXY_URL`/`LITELLM_PROXY_API_KEY` are read at call\n * time by `@distilled.cloud/litellm`'s own `CredentialsFromEnv` (providers.ts) — the same two\n * variable names the retired hand-rolled `credentials.ts` read.\n */\nimport { Resource } from 'alchemy';\nimport { Unowned } from 'alchemy/AdoptPolicy';\nimport { isResolved } from 'alchemy/Diff';\nimport type { Input } from 'alchemy/Input';\nimport { createPhysicalName } from 'alchemy/PhysicalName';\nimport * as Provider from 'alchemy/Provider';\nimport type { Stack } from 'alchemy/Stack';\nimport type { Stage } from 'alchemy/Stage';\nimport type * as misc from '@distilled.cloud/litellm/misc';\nimport * as Effect from 'effect/Effect';\nimport * as Predicate from 'effect/Predicate';\nimport {\n type LitellmRequirements,\n createPassThroughEndpoint,\n deletePassThroughEndpoint,\n listPassThroughEndpoints,\n updatePassThroughEndpoint,\n} from './operations.ts';\nimport {\n LitellmConfigPathConflictError,\n LitellmLiteralSecretHeaderError,\n LitellmUnaddressableRowError,\n} from './pass-through-errors.ts';\nimport {\n type PassThroughEndpointAttributes,\n type PassThroughEndpointProps,\n createBody,\n literalSecretHeaders,\n matches,\n needsReplace,\n updateBody,\n} from './pass-through-form.ts';\n\nexport type { PassThroughEndpointAttributes, PassThroughEndpointProps };\nexport {\n LitellmConfigPathConflictError,\n LitellmLiteralSecretHeaderError,\n LitellmUnaddressableRowError,\n type PassThroughEndpointError,\n} from './pass-through-errors.ts';\n\nexport interface LiteLLMPassThroughEndpoint extends Resource<\n 'LiteLLM.PassThroughEndpoint',\n PassThroughEndpointProps,\n PassThroughEndpointAttributes,\n never,\n LitellmRequirements | Stack | Stage\n> {}\n\nexport const LiteLLMPassThroughEndpoint = Resource<LiteLLMPassThroughEndpoint>(\n 'LiteLLM.PassThroughEndpoint',\n);\n\nexport const isLiteLLMPassThroughEndpoint = (value: unknown): value is LiteLLMPassThroughEndpoint =>\n Predicate.hasProperty(value, 'Type') && value.Type === 'LiteLLM.PassThroughEndpoint';\n\nconst toAttributes = (\n row: misc.PassThroughGenericEndpoint,\n fallbackId: string,\n): PassThroughEndpointAttributes => ({\n ...row,\n id: row.id ?? fallbackId,\n});\n\nconst physicalIdOf = (logicalId: string, instanceId: string) =>\n createPhysicalName({ id: logicalId, instanceId, lowercase: true, maxLength: 64 });\n\n/**\n * Find this resource's live row (by id) and, when absent, the row that already holds its `path`\n * (a config-file row to refuse, or a DB row LiteLLM did not give an id — also refused, see the\n * file header — or a genuine foreign DB row to hand back `Unowned`).\n */\nconst locate = (\n rows: readonly misc.PassThroughGenericEndpoint[],\n objectId: string,\n path: string,\n): {\n readonly mine: misc.PassThroughGenericEndpoint | undefined;\n readonly conflict: misc.PassThroughGenericEndpoint | undefined;\n} => {\n const mine = rows.find((row) => row.id === objectId);\n const conflict = mine === undefined ? rows.find((row) => row.path === path) : undefined;\n return { conflict, mine };\n};\n\n/** The typed refusal for a `path` conflict that cannot ever be adopted (config row, or no id). */\nconst conflictRefusal = (conflict: misc.PassThroughGenericEndpoint, path: string) =>\n conflict.is_from_config === true\n ? new LitellmConfigPathConflictError({ path })\n : new LitellmUnaddressableRowError({ path });\n\n/** `read`'s answer for a path conflict: `Unowned` when it is a real, addressable DB row — a typed refusal otherwise. */\nconst readConflict = (conflict: misc.PassThroughGenericEndpoint, path: string) =>\n conflict.is_from_config !== true && conflict.id !== undefined && conflict.id !== null\n ? Effect.succeed(Unowned(toAttributes(conflict, conflict.id)))\n : Effect.fail(conflictRefusal(conflict, path));\n\nconst refuseLiteralSecrets = (headers: Readonly<Record<string, unknown>> | undefined) => {\n const bad = literalSecretHeaders(headers);\n return bad.length === 0\n ? Effect.void\n : Effect.fail(new LitellmLiteralSecretHeaderError({ headers: bad }));\n};\n\n/** ⛔ TEST-ONLY EXPORT. Not on index.ts's barrel — a lifecycle test calls these directly against the fake. */\nexport const passThroughHandlers = {\n read: ({\n id,\n instanceId,\n olds,\n output,\n }: {\n id: string;\n instanceId: string;\n olds: PassThroughEndpointProps;\n output: PassThroughEndpointAttributes | undefined;\n }) =>\n Effect.gen(function* () {\n const objectId = output?.id ?? (yield* physicalIdOf(id, instanceId));\n const rows = yield* listPassThroughEndpoints();\n const { conflict, mine } = locate(rows, objectId, olds.path);\n if (mine !== undefined) return toAttributes(mine, objectId);\n if (conflict === undefined) return undefined;\n return yield* readConflict(conflict, olds.path);\n }),\n\n diff: ({\n news,\n output,\n }: {\n news: Input<PassThroughEndpointProps>;\n output: PassThroughEndpointAttributes | undefined;\n }) =>\n Effect.gen(function* () {\n if (!isResolved(news)) return undefined;\n yield* refuseLiteralSecrets(news.headers);\n if (output === undefined) return undefined;\n // ⛔ deleteFirst: TRUE — a create-first replace mints a new instanceId/id before the old row\n // on `path` is gone, so the new generation's `reconcile` would refuse it as a foreign\n // conflict (Apply.ts). Same fix this kit's other unique-identity providers use.\n if (needsReplace(output, news)) return { action: 'replace', deleteFirst: true } as const;\n return matches(output, news)\n ? ({ action: 'noop' } as const)\n : ({ action: 'update' } as const);\n }),\n\n reconcile: ({\n id,\n instanceId,\n news,\n output,\n }: {\n id: string;\n instanceId: string;\n news: PassThroughEndpointProps;\n output: PassThroughEndpointAttributes | undefined;\n }) =>\n Effect.gen(function* () {\n yield* refuseLiteralSecrets(news.headers);\n const objectId = output?.id ?? (yield* physicalIdOf(id, instanceId));\n const rows = yield* listPassThroughEndpoints();\n const { conflict, mine } = locate(rows, objectId, news.path);\n\n if (mine === undefined) {\n // ⚠️ A CONFLICT HERE — reconcile, not read — means ownership shifted between plan and\n // apply (a config row or a foreign DB row landed on this path after `read` cleared it).\n // `read` gates a genuine adopt by returning `Unowned`; reconcile itself never adopts,\n // so ANY conflict here fails rather than risking a second row on one path.\n if (conflict !== undefined) return yield* Effect.fail(conflictRefusal(conflict, news.path));\n yield* createPassThroughEndpoint(createBody(news, objectId));\n } else if (mine.is_from_config === true) {\n // ⛔ NEVER UPDATE OR DELETE AN `is_from_config` ROW, even one this resource's own\n // deterministic id happens to match (a config.yaml author could in principle choose the\n // same id `createPhysicalName` would). Refuse rather than silently editing the file's row.\n return yield* Effect.fail(new LitellmConfigPathConflictError({ path: news.path }));\n } else if (needsReplace(toAttributes(mine, objectId), news)) {\n yield* deletePassThroughEndpoint(objectId);\n yield* createPassThroughEndpoint(createBody(news, objectId));\n } else if (!matches(toAttributes(mine, objectId), news)) {\n const body = updateBody(news);\n if (Object.keys(body).length > 0) yield* updatePassThroughEndpoint(objectId, body);\n }\n\n const after = (yield* listPassThroughEndpoints()).find((row) => row.id === objectId);\n if (after === undefined) {\n return yield* Effect.die(\n new Error(\n `LiteLLM.PassThroughEndpoint ${news.path}: the write returned no error but id ` +\n `${objectId} is still absent from GET /config/pass_through_endpoint — read back ` +\n 'rather than trusting the call that just returned.',\n ),\n );\n }\n return toAttributes(after, objectId);\n }),\n\n delete: ({\n id,\n instanceId,\n olds,\n output,\n }: {\n id: string;\n instanceId: string;\n olds: PassThroughEndpointProps;\n output: PassThroughEndpointAttributes;\n }) =>\n Effect.gen(function* () {\n const objectId = output.id ?? (yield* physicalIdOf(id, instanceId));\n const rows = yield* listPassThroughEndpoints();\n const live = rows.find((row) => row.id === objectId);\n // ⛔ NEVER DELETE AN `is_from_config` ROW, and a DB row this resource never created (a path\n // match with a different id) is not this resource's to remove either.\n if (live === undefined || live.is_from_config === true || live.path !== olds.path) return;\n yield* deletePassThroughEndpoint(objectId);\n }),\n\n list: () => Effect.succeed([]),\n};\n\nexport const LiteLLMPassThroughEndpointProvider = () =>\n Provider.effect(\n LiteLLMPassThroughEndpoint,\n Effect.succeed(LiteLLMPassThroughEndpoint.Provider.of(passThroughHandlers)),\n );\n",
6
+ "/**\n * The four LiteLLM `/config/pass_through_endpoint*` calls this package writes to and reads from —\n * now through `@distilled.cloud/litellm`'s typed operations (S23), not a hand-rolled `HttpClient`\n * client. `client.ts` is retired; nothing else in this package imported it.\n *\n * ⛔ STILL WRAPPED IN A PER-BASE-URL SEMAPHORE, UNCHANGED FROM `client.ts`. LiteLLM stores every\n * pass-through endpoint in ONE `general_settings.pass_through_endpoints` list\n * (`pass_through_endpoints.py` at tag v1.100.0, mirrored in the SDK's own `misc.ts` docstrings),\n * so create/update/delete are each a read-modify-write of the WHOLE list through\n * `update_config_general_settings`. Two of this package's own calls racing each other — two\n * endpoints created in the same deploy — would each read the list, add their own row and write\n * it back, and the second write would silently drop the first row. The SDK has no opinion on\n * this: it is a quirk of how THIS vendor stores the resource, not a distilled protocol concern,\n * so it stays here, one layer above the typed calls. One permit per proxy serialises this\n * package's own writes; it cannot serialise against the LiteLLM UI or a second deploy process,\n * which is why `pass-through-endpoint.ts`'s `reconcile` reads back after writing rather than\n * trusting the call that just returned (docs/litellm.md).\n * ⛔ NO STATUS SNIFFING (S21). Every failure the SDK's own typed operations declare — `BadRequest`\n * (400), `NotFound` (404 on update only), `UnprocessableEntity` (422) plus the shared\n * `Unauthorized`/`TooManyRequests`/`InternalServerError`/`BadGateway`/`ServiceUnavailable`/\n * `GatewayTimeout` every operation carries — is a distilled patch's doing\n * (`@distilled.cloud/litellm`'s own `patches/misc/*.json`, applied at generation time), never a\n * status check here or in `pass-through-endpoint.ts`. Deleting an id LiteLLM does not have\n * answers `BadRequest` (measured against the tag's `pass_through_endpoint_delete` — the id is\n * looked up in the list and a miss raises `HTTPException(400)`, not 404) — but so does a\n * genuinely-live row when the caller isn't PROXY_ADMIN, or the DB is disconnected. Telling those\n * apart by re-listing, not by the `BadRequest`'s message text, is `pass-through-endpoint.ts`'s\n * `deletePassThroughEndpoint`'s own job (S21 — a status-and-a-real-read decision, never body\n * text) — this file only forwards the typed error.\n */\nimport * as misc from '@distilled.cloud/litellm/misc';\nimport { Credentials } from '@distilled.cloud/litellm/Credentials';\nimport type { LitellmOpContext } from '@distilled.cloud/litellm/Protocol';\nimport type { ConfigError } from '@distilled.cloud/litellm/Errors';\nimport * as Effect from 'effect/Effect';\nimport * as Semaphore from 'effect/Semaphore';\n\nexport type { LitellmOpContext } from '@distilled.cloud/litellm/Protocol';\nexport type LitellmRequirements = LitellmOpContext;\nexport type {\n PassThroughEndpointResponse,\n PassThroughGenericEndpoint,\n PassThroughGuardrailSettings,\n} from '@distilled.cloud/litellm/misc';\n\nconst semaphores = new Map<string, Semaphore.Semaphore>();\n\n/** One semaphore per base URL, created on first use. Never `Hash.structure` (S18) — a plain Map key. */\nconst semaphoreFor = (baseUrl: string): Effect.Effect<Semaphore.Semaphore> =>\n Effect.sync(() => {\n const existing = semaphores.get(baseUrl);\n if (existing !== undefined) return existing;\n const created = Semaphore.makeUnsafe(1);\n semaphores.set(baseUrl, created);\n return created;\n });\n\n/**\n * Serialises a write against this call's own base URL — see the file header.\n *\n * Resolving `Credentials` can itself fail typed (`ConfigError` — S20/S24, credentials.ts), so\n * the return type carries that alongside the wrapped operation's own error `E`; every call\n * site's declared error type already includes `ConfigError` as a member of the SDK's shared\n * `LitellmOpError` (protocol.ts), so this widening is a no-op for callers.\n */\nconst mutate = <A, E>(\n io: Effect.Effect<A, E, LitellmOpContext>,\n): Effect.Effect<A, E | ConfigError, LitellmOpContext> =>\n Effect.gen(function* () {\n const resolve = yield* Credentials;\n const creds = yield* resolve;\n const semaphore = yield* semaphoreFor(creds.apiBaseUrl);\n return yield* semaphore.withPermits(1)(io);\n });\n\n/** GET /config/pass_through_endpoint — every row, config-file and DB alike. Not under the semaphore: reads don't race the field. */\nexport const listPassThroughEndpoints = (): Effect.Effect<\n readonly misc.PassThroughGenericEndpoint[],\n misc.GetPassThroughEndpointsConfigPassThroughEndpointGetError,\n LitellmOpContext\n> =>\n misc\n .getPassThroughEndpointsConfigPassThroughEndpointGet({})\n .pipe(Effect.map((response) => response.endpoints));\n\n/** POST /config/pass_through_endpoint. `body` carries `id` — see pass-through-form.ts. */\nexport const createPassThroughEndpoint = (\n body: misc.PassThroughGenericEndpoint,\n): Effect.Effect<\n void,\n misc.CreatePassThroughEndpointsConfigPassThroughEndpointPostError,\n LitellmOpContext\n> => mutate(misc.createPassThroughEndpointsConfigPassThroughEndpointPost(body).pipe(Effect.asVoid));\n\n/**\n * POST /config/pass_through_endpoint/{endpoint_id}. Merges with `exclude_none` — see\n * pass-through-form.ts. `body` is `pass-through-form.ts`'s own `UpdateBody`, not a blanket\n * `Partial<>` — `path`/`target` are the two fields the SDK's request type still requires\n * non-optionally on an update.\n */\nexport const updatePassThroughEndpoint = (\n endpointId: string,\n body: Partial<Omit<misc.PassThroughGenericEndpoint, 'path' | 'target'>> &\n Pick<misc.PassThroughGenericEndpoint, 'path' | 'target'>,\n): Effect.Effect<\n void,\n misc.UpdatePassThroughEndpointsConfigPassThroughEndpointEndpointIdPostError,\n LitellmOpContext\n> =>\n mutate(\n misc\n .updatePassThroughEndpointsConfigPassThroughEndpointEndpointIdPost({\n ...body,\n endpoint_id: endpointId,\n })\n .pipe(Effect.asVoid),\n );\n\n/**\n * DELETE /config/pass_through_endpoint?endpoint_id=… — idempotent BY THIS FUNCTION, not by the\n * vendor. ⚠️ Measured at v1.100.0: deleting an id the list does not have raises `HTTPException(400)`\n * from `pass_through_endpoint_delete`, which the SDK decodes as a typed `BadRequest` — but the SAME\n * route also raises the SAME `BadRequest` for `not_allowed_access` (a non-PROXY_ADMIN caller) or a\n * disconnected DB, on a row that never got deleted. A `BadRequest` alone cannot tell the two apart,\n * so THIS FUNCTION DOESN'T GUESS FROM THE TAG ALONE: on `BadRequest` it re-lists (a GET — no\n * PROXY_ADMIN required) and only treats the delete as already-done if `endpointId` is genuinely\n * absent; otherwise the delete failed and this re-fails with the ORIGINAL error, not a message\n * match (S21 — a status-and-a-real-read decision, never body text).\n */\nexport const deletePassThroughEndpoint = (\n endpointId: string,\n): Effect.Effect<\n void,\n misc.DeletePassThroughEndpointsConfigPassThroughEndpointDeleteError,\n LitellmOpContext\n> =>\n mutate(\n misc\n .deletePassThroughEndpointsConfigPassThroughEndpointDelete({ endpoint_id: endpointId })\n .pipe(\n Effect.asVoid,\n Effect.catchTag('BadRequest', (original) =>\n Effect.gen(function* () {\n const rows = yield* listPassThroughEndpoints();\n if (rows.some((row) => row.id === endpointId)) return yield* Effect.fail(original);\n }),\n ),\n ),\n );\n",
7
+ "/**\n * The typed refusals `LiteLLM.PassThroughEndpoint` raises on top of `@distilled.cloud/litellm`'s\n * own SDK errors — split out of pass-through-endpoint.ts to keep that file under the house's\n * 250-line cap once this migration added the four named SDK error-union re-exports.\n */\nimport type * as misc from '@distilled.cloud/litellm/misc';\nimport * as Data from 'effect/Data';\n\nexport class LitellmConfigPathConflictError extends Data.TaggedError(\n 'LitellmConfigPathConflictError',\n)<{\n readonly path: string;\n}> {}\nexport class LitellmUnaddressableRowError extends Data.TaggedError('LitellmUnaddressableRowError')<{\n readonly path: string;\n}> {}\nexport class LitellmLiteralSecretHeaderError extends Data.TaggedError(\n 'LitellmLiteralSecretHeaderError',\n)<{\n readonly headers: readonly string[];\n}> {}\n\n/**\n * ⛔ THE FOUR SDK ERROR UNIONS, NAMED, NOT `LitellmOpError` ALONE. `catchTag`'s tag-literal\n * inference needs a concrete union to resolve `\"BadRequest\"`/`\"NotFound\"` against (the same\n * reason `netbox/resource.ts` leaves `NotFound` folding to each resource file, not its shared\n * engine) — `operations.ts` already returns each call's own precise per-operation error type, so\n * this is just their union, not a re-widening.\n */\nexport type PassThroughEndpointError =\n | misc.GetPassThroughEndpointsConfigPassThroughEndpointGetError\n | misc.CreatePassThroughEndpointsConfigPassThroughEndpointPostError\n | misc.UpdatePassThroughEndpointsConfigPassThroughEndpointEndpointIdPostError\n | misc.DeletePassThroughEndpointsConfigPassThroughEndpointDeleteError\n | LitellmConfigPathConflictError\n | LitellmUnaddressableRowError\n | LitellmLiteralSecretHeaderError;\n",
8
+ "/**\n * The wire body for a `LiteLLM.PassThroughEndpoint`, the comparison that decides whether it needs\n * writing, and the refusals that stop a plan before it writes anything unsafe.\n *\n * ★ EXTRACTED SO IT CAN BE TESTED WITHOUT A SERVER — the same reason netbox keeps `prefix-form.ts`\n * beside `prefix.ts` (S32/testing-and-docs.md).\n *\n * ⛔ PROPS ARE `@distilled.cloud/litellm`'s OWN GENERATED TYPE, MINUS THE TWO FIELDS THIS RESOURCE\n * OWNS ITSELF: `id` (a deterministic physical name — pass-through-endpoint.ts) and\n * `is_from_config` (response-only; the vendor sets it, a declaration never does). Deriving\n * `Props` with `Omit<>` rather than hand-typing it means a vendor schema change the SDK's own\n * next regeneration picks up is felt here as a compiler error, not silently ignored — the same\n * reason this used to derive from the kit's own hand-generated `./generated/pass-through.ts`\n * (retired by this migration: the SDK's type is the same shape, generated from the same LiteLLM\n * 1.100.0 OpenAPI document, and keeping a second copy would only drift).\n */\nimport { deepEqual } from 'alchemy/Diff';\nimport type * as Generated from '@distilled.cloud/litellm/misc';\n\nexport type PassThroughEndpointProps = Omit<\n Generated.PassThroughGenericEndpoint,\n 'id' | 'is_from_config'\n>;\n\n/** What `read` returns: the props plus the two vendor-owned fields, `id` now guaranteed present. */\nexport type PassThroughEndpointAttributes = Omit<Generated.PassThroughGenericEndpoint, 'id'> & {\n readonly id: string;\n};\n\n/** ⚠️ NetBox `settled()`'s pattern: only fields the SCHEMA gives a vendor default for, copied from it (not assumed). */\nexport const settled = (props: PassThroughEndpointProps) => ({\n auth: props.auth ?? true,\n cost_per_request: props.cost_per_request ?? 0,\n default_query_params: props.default_query_params ?? {},\n headers: props.headers ?? {},\n include_subpath: props.include_subpath ?? false,\n});\n\n/** The three fields whose absence the vendor's `exclude_none` update can never write (see client.ts). */\nexport const NULLABLE_FIELDS = ['timeout', 'methods', 'guardrails'] as const;\n\nconst isUnset = (value: unknown): boolean => value === undefined || value === null;\n\n/**\n * ⚠️ BUILT AS A WIDER RECORD AND PRUNED, NOT AS THE GENERATED TYPE DIRECTLY.\n * `exactOptionalPropertyTypes` is on (packages/config/tsconfig.base.json), so writing\n * `timeout: undefined` into a `{ timeout?: number | null }` is a type error rather than an\n * absent key — the same reason `codegen/openapi.ts`'s `prune` exists, and the same fix.\n */\nconst prune = (value: Record<string, unknown>): Record<string, unknown> =>\n Object.fromEntries(Object.entries(value).filter(([, v]) => v !== undefined));\n\n/**\n * Full body for CREATE. `id` is the deterministic physical name (pass-through-endpoint.ts), sent\n * so a failed create is recoverable by `read` rather than orphaning a second row on retry.\n */\nexport const createBody = (\n props: PassThroughEndpointProps,\n id: string,\n): Generated.PassThroughGenericEndpoint =>\n prune({\n ...settled(props),\n guardrails: isUnset(props.guardrails) ? undefined : props.guardrails,\n id,\n methods: isUnset(props.methods) ? undefined : props.methods,\n path: props.path,\n target: props.target,\n timeout: isUnset(props.timeout) ? undefined : props.timeout,\n }) as unknown as Generated.PassThroughGenericEndpoint;\n\n/**\n * Partial body for UPDATE (`POST /{id}`). ⛔ ONLY FIELDS THIS DECLARATION ACTUALLY SETS — the\n * vendor merges the parsed body with `model_dump(exclude_none=True)` (measured at v1.100.0), so an\n * `undefined` OR an explicit `null` here would be dropped by the server anyway; sending neither is\n * the same outcome with no request made when nothing changed (`Object.keys(body).length === 0`\n * checked by the caller in pass-through-endpoint.ts).\n *\n * ⛔ `path`/`target` ARE NOT `Partial` HERE, UNLIKE EVERY OTHER FIELD. The SDK's own update\n * request type requires both non-optionally (the vendor's PATCH route still wants the full\n * route/target pair on every call, unlike the other fields' `exclude_none` merge) — typing them\n * as always-present here is what lets `operations.ts`'s `updatePassThroughEndpoint` pass this\n * straight to the SDK without an unsafe cast.\n */\nexport type UpdateBody = Partial<Omit<Generated.PassThroughGenericEndpoint, 'path' | 'target'>> &\n Pick<Generated.PassThroughGenericEndpoint, 'path' | 'target'>;\n\nexport const updateBody = (props: PassThroughEndpointProps): UpdateBody =>\n prune({\n ...settled(props),\n guardrails: isUnset(props.guardrails) ? undefined : props.guardrails,\n methods: isUnset(props.methods) ? undefined : props.methods,\n path: props.path,\n target: props.target,\n timeout: isUnset(props.timeout) ? undefined : props.timeout,\n }) as UpdateBody;\n\n/**\n * Whether ANY of the three nullable fields went from set (in `live`) to unset (in `props`) — the\n * one case `updateBody` cannot express, because the vendor's `exclude_none` merge silently keeps\n * the old value instead of clearing it. Detected here so `pass-through-endpoint.ts` can plan a\n * `replace` (delete-then-create) instead of an update that would look like it worked.\n */\nexport const needsReplace = (\n live: PassThroughEndpointAttributes,\n props: PassThroughEndpointProps,\n): boolean => NULLABLE_FIELDS.some((field) => !isUnset(live[field]) && isUnset(props[field]));\n\n/** Whether the live object already says what the declaration says — the `diff` \"noop\" test. */\nexport const matches = (\n live: PassThroughEndpointAttributes,\n props: PassThroughEndpointProps,\n): boolean => {\n const fixed = settled(props);\n return (\n live.target === props.target &&\n live.auth === fixed.auth &&\n live.cost_per_request === fixed.cost_per_request &&\n live.include_subpath === fixed.include_subpath &&\n deepEqual(live.headers, fixed.headers) &&\n deepEqual(live.default_query_params, fixed.default_query_params) &&\n (isUnset(props.timeout) ? isUnset(live.timeout) : live.timeout === props.timeout) &&\n (isUnset(props.methods) ? isUnset(live.methods) : deepEqual(live.methods, props.methods)) &&\n (isUnset(props.guardrails)\n ? isUnset(live.guardrails)\n : deepEqual(live.guardrails, props.guardrails))\n );\n};\n\n/**\n * A literal secret in a forwarded header (S25, house rule — not a vendor one; see\n * pass-through-endpoint.ts). Case-insensitive on the header name; the reference form is LiteLLM's\n * own, `os.environ/NAME` (`set_env_variables_in_header`, pass_through_endpoints.py:117-160 at the\n * tag) — a missing variable on the proxy host leaves that literal string in the header, which\n * nothing in the API can detect, so this is enforced here rather than trusted to the vendor.\n */\nconst SECRET_HEADER_NAMES = new Set(['authorization', 'x-api-key', 'cf-aig-authorization']);\n\nexport const literalSecretHeaders = (\n headers: Readonly<Record<string, unknown>> | undefined,\n): readonly string[] =>\n Object.entries(headers ?? {})\n .filter(\n ([name, value]) =>\n SECRET_HEADER_NAMES.has(name.toLowerCase()) && !String(value).includes('os.environ/'),\n )\n .map(([name]) => name);\n",
9
+ "/**\n * The LiteLLM provider, with its credential source, as one layer for a stack.\n *\n * Layer.mergeAll(litellmProviders(), …the stack's other providers)\n *\n * ★ THE DEFAULT READS `LITELLM_PROXY_URL`/`LITELLM_PROXY_API_KEY` AT CALL TIME, through\n * `@distilled.cloud/litellm`'s own `CredentialsFromEnv` — the same two variable names the\n * retired hand-rolled `credentials.ts` read — never at layer build. Pass another\n * `Layer.Layer<Credentials>` (see the SDK's own `credentials({ apiKey, baseUrl })` in a test) to\n * source them another way.\n * ⚠️ `HttpClient` is NOT provided here. It is ambient in every Alchemy runtime the same way it is\n * for `netboxProviders`-style families in this kit; a stack that already deploys anything over\n * HTTP already has one.\n */\nimport { type Credentials, CredentialsFromEnv } from '@distilled.cloud/litellm/Credentials';\nimport * as Layer from 'effect/Layer';\nimport { LiteLLMPassThroughEndpointProvider } from './pass-through-endpoint.ts';\n\nexport const litellmProviders = (creds: Layer.Layer<Credentials> = CredentialsFromEnv) =>\n LiteLLMPassThroughEndpointProvider().pipe(Layer.provide(creds));\n"
10
10
  ],
11
- "mappings": "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",
12
- "debugId": "9216FE33E5E3721264756E2164756E21",
11
+ "mappings": "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",
12
+ "debugId": "F883BA858F0CF3AD64756E2164756E21",
13
13
  "names": []
14
14
  }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The four LiteLLM `/config/pass_through_endpoint*` calls this package writes to and reads from —
3
+ * now through `@distilled.cloud/litellm`'s typed operations (S23), not a hand-rolled `HttpClient`
4
+ * client. `client.ts` is retired; nothing else in this package imported it.
5
+ *
6
+ * ⛔ STILL WRAPPED IN A PER-BASE-URL SEMAPHORE, UNCHANGED FROM `client.ts`. LiteLLM stores every
7
+ * pass-through endpoint in ONE `general_settings.pass_through_endpoints` list
8
+ * (`pass_through_endpoints.py` at tag v1.100.0, mirrored in the SDK's own `misc.ts` docstrings),
9
+ * so create/update/delete are each a read-modify-write of the WHOLE list through
10
+ * `update_config_general_settings`. Two of this package's own calls racing each other — two
11
+ * endpoints created in the same deploy — would each read the list, add their own row and write
12
+ * it back, and the second write would silently drop the first row. The SDK has no opinion on
13
+ * this: it is a quirk of how THIS vendor stores the resource, not a distilled protocol concern,
14
+ * so it stays here, one layer above the typed calls. One permit per proxy serialises this
15
+ * package's own writes; it cannot serialise against the LiteLLM UI or a second deploy process,
16
+ * which is why `pass-through-endpoint.ts`'s `reconcile` reads back after writing rather than
17
+ * trusting the call that just returned (docs/litellm.md).
18
+ * ⛔ NO STATUS SNIFFING (S21). Every failure the SDK's own typed operations declare — `BadRequest`
19
+ * (400), `NotFound` (404 on update only), `UnprocessableEntity` (422) plus the shared
20
+ * `Unauthorized`/`TooManyRequests`/`InternalServerError`/`BadGateway`/`ServiceUnavailable`/
21
+ * `GatewayTimeout` every operation carries — is a distilled patch's doing
22
+ * (`@distilled.cloud/litellm`'s own `patches/misc/*.json`, applied at generation time), never a
23
+ * status check here or in `pass-through-endpoint.ts`. Deleting an id LiteLLM does not have
24
+ * answers `BadRequest` (measured against the tag's `pass_through_endpoint_delete` — the id is
25
+ * looked up in the list and a miss raises `HTTPException(400)`, not 404) — but so does a
26
+ * genuinely-live row when the caller isn't PROXY_ADMIN, or the DB is disconnected. Telling those
27
+ * apart by re-listing, not by the `BadRequest`'s message text, is `pass-through-endpoint.ts`'s
28
+ * `deletePassThroughEndpoint`'s own job (S21 — a status-and-a-real-read decision, never body
29
+ * text) — this file only forwards the typed error.
30
+ */
31
+ import * as misc from '@distilled.cloud/litellm/misc';
32
+ import type { LitellmOpContext } from '@distilled.cloud/litellm/Protocol';
33
+ import * as Effect from 'effect/Effect';
34
+ export type { LitellmOpContext } from '@distilled.cloud/litellm/Protocol';
35
+ export type LitellmRequirements = LitellmOpContext;
36
+ export type { PassThroughEndpointResponse, PassThroughGenericEndpoint, PassThroughGuardrailSettings, } from '@distilled.cloud/litellm/misc';
37
+ /** GET /config/pass_through_endpoint — every row, config-file and DB alike. Not under the semaphore: reads don't race the field. */
38
+ export declare const listPassThroughEndpoints: () => Effect.Effect<readonly misc.PassThroughGenericEndpoint[], misc.GetPassThroughEndpointsConfigPassThroughEndpointGetError, LitellmOpContext>;
39
+ /** POST /config/pass_through_endpoint. `body` carries `id` — see pass-through-form.ts. */
40
+ export declare const createPassThroughEndpoint: (body: misc.PassThroughGenericEndpoint) => Effect.Effect<void, misc.CreatePassThroughEndpointsConfigPassThroughEndpointPostError, LitellmOpContext>;
41
+ /**
42
+ * POST /config/pass_through_endpoint/{endpoint_id}. Merges with `exclude_none` — see
43
+ * pass-through-form.ts. `body` is `pass-through-form.ts`'s own `UpdateBody`, not a blanket
44
+ * `Partial<>` — `path`/`target` are the two fields the SDK's request type still requires
45
+ * non-optionally on an update.
46
+ */
47
+ export declare const updatePassThroughEndpoint: (endpointId: string, body: Partial<Omit<misc.PassThroughGenericEndpoint, 'path' | 'target'>> & Pick<misc.PassThroughGenericEndpoint, 'path' | 'target'>) => Effect.Effect<void, misc.UpdatePassThroughEndpointsConfigPassThroughEndpointEndpointIdPostError, LitellmOpContext>;
48
+ /**
49
+ * DELETE /config/pass_through_endpoint?endpoint_id=… — idempotent BY THIS FUNCTION, not by the
50
+ * vendor. ⚠️ Measured at v1.100.0: deleting an id the list does not have raises `HTTPException(400)`
51
+ * from `pass_through_endpoint_delete`, which the SDK decodes as a typed `BadRequest` — but the SAME
52
+ * route also raises the SAME `BadRequest` for `not_allowed_access` (a non-PROXY_ADMIN caller) or a
53
+ * disconnected DB, on a row that never got deleted. A `BadRequest` alone cannot tell the two apart,
54
+ * so THIS FUNCTION DOESN'T GUESS FROM THE TAG ALONE: on `BadRequest` it re-lists (a GET — no
55
+ * PROXY_ADMIN required) and only treats the delete as already-done if `endpointId` is genuinely
56
+ * absent; otherwise the delete failed and this re-fails with the ORIGINAL error, not a message
57
+ * match (S21 — a status-and-a-real-read decision, never body text).
58
+ */
59
+ export declare const deletePassThroughEndpoint: (endpointId: string) => Effect.Effect<void, misc.DeletePassThroughEndpointsConfigPassThroughEndpointDeleteError, LitellmOpContext>;
60
+ //# sourceMappingURL=operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/litellm/operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,IAAI,MAAM,+BAA+B,CAAC;AAEtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAE1E,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAGxC,YAAY,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,CAAC;AACnD,YAAY,EACV,2BAA2B,EAC3B,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,+BAA+B,CAAC;AAgCvC,oIAAoI;AACpI,eAAO,MAAM,wBAAwB,QAAO,MAAM,CAAC,MAAM,CACvD,SAAS,IAAI,CAAC,0BAA0B,EAAE,EAC1C,IAAI,CAAC,wDAAwD,EAC7D,gBAAgB,CAIqC,CAAC;AAExD,0FAA0F;AAC1F,eAAO,MAAM,yBAAyB,SAC9B,IAAI,CAAC,0BAA0B,KACpC,MAAM,CAAC,MAAM,CACd,IAAI,EACJ,IAAI,CAAC,4DAA4D,EACjE,gBAAgB,CACiF,CAAC;AAEpG;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,eACxB,MAAM,QACZ,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,GACrE,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,MAAM,GAAG,QAAQ,CAAC,KACzD,MAAM,CAAC,MAAM,CACd,IAAI,EACJ,IAAI,CAAC,sEAAsE,EAC3E,gBAAgB,CASf,CAAC;AAEJ;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,eACxB,MAAM,KACjB,MAAM,CAAC,MAAM,CACd,IAAI,EACJ,IAAI,CAAC,8DAA8D,EACnE,gBAAgB,CAcf,CAAC"}