@dexcost/sdk 0.2.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 (211) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +210 -0
  3. package/dist/adapters/_netbytes.d.ts +31 -0
  4. package/dist/adapters/_netbytes.d.ts.map +1 -0
  5. package/dist/adapters/_netbytes.js +154 -0
  6. package/dist/adapters/_netbytes.js.map +1 -0
  7. package/dist/adapters/aws-lambda.d.ts +41 -0
  8. package/dist/adapters/aws-lambda.d.ts.map +1 -0
  9. package/dist/adapters/aws-lambda.js +65 -0
  10. package/dist/adapters/aws-lambda.js.map +1 -0
  11. package/dist/adapters/browser.d.ts +52 -0
  12. package/dist/adapters/browser.d.ts.map +1 -0
  13. package/dist/adapters/browser.js +127 -0
  14. package/dist/adapters/browser.js.map +1 -0
  15. package/dist/adapters/compute-wrap.d.ts +33 -0
  16. package/dist/adapters/compute-wrap.d.ts.map +1 -0
  17. package/dist/adapters/compute-wrap.js +188 -0
  18. package/dist/adapters/compute-wrap.js.map +1 -0
  19. package/dist/adapters/data/aws_lambda_pricing.json +61 -0
  20. package/dist/adapters/gpu-wrap.d.ts +31 -0
  21. package/dist/adapters/gpu-wrap.d.ts.map +1 -0
  22. package/dist/adapters/gpu-wrap.js +147 -0
  23. package/dist/adapters/gpu-wrap.js.map +1 -0
  24. package/dist/adapters/http.d.ts +58 -0
  25. package/dist/adapters/http.d.ts.map +1 -0
  26. package/dist/adapters/http.js +769 -0
  27. package/dist/adapters/http.js.map +1 -0
  28. package/dist/adapters/index.d.ts +11 -0
  29. package/dist/adapters/index.d.ts.map +1 -0
  30. package/dist/adapters/index.js +12 -0
  31. package/dist/adapters/index.js.map +1 -0
  32. package/dist/adapters/network-accountant.d.ts +63 -0
  33. package/dist/adapters/network-accountant.d.ts.map +1 -0
  34. package/dist/adapters/network-accountant.js +153 -0
  35. package/dist/adapters/network-accountant.js.map +1 -0
  36. package/dist/cli/index.d.ts +13 -0
  37. package/dist/cli/index.d.ts.map +1 -0
  38. package/dist/cli/index.js +225 -0
  39. package/dist/cli/index.js.map +1 -0
  40. package/dist/cli/scanner.d.ts +39 -0
  41. package/dist/cli/scanner.d.ts.map +1 -0
  42. package/dist/cli/scanner.js +480 -0
  43. package/dist/cli/scanner.js.map +1 -0
  44. package/dist/clients.d.ts +54 -0
  45. package/dist/clients.d.ts.map +1 -0
  46. package/dist/clients.js +240 -0
  47. package/dist/clients.js.map +1 -0
  48. package/dist/cloud-detect.d.ts +96 -0
  49. package/dist/cloud-detect.d.ts.map +1 -0
  50. package/dist/cloud-detect.js +545 -0
  51. package/dist/cloud-detect.js.map +1 -0
  52. package/dist/core/auto-task.d.ts +20 -0
  53. package/dist/core/auto-task.d.ts.map +1 -0
  54. package/dist/core/auto-task.js +34 -0
  55. package/dist/core/auto-task.js.map +1 -0
  56. package/dist/core/cgroup-reader.d.ts +45 -0
  57. package/dist/core/cgroup-reader.d.ts.map +1 -0
  58. package/dist/core/cgroup-reader.js +124 -0
  59. package/dist/core/cgroup-reader.js.map +1 -0
  60. package/dist/core/cgroup-walker.d.ts +60 -0
  61. package/dist/core/cgroup-walker.d.ts.map +1 -0
  62. package/dist/core/cgroup-walker.js +166 -0
  63. package/dist/core/cgroup-walker.js.map +1 -0
  64. package/dist/core/compute-accountant.d.ts +51 -0
  65. package/dist/core/compute-accountant.d.ts.map +1 -0
  66. package/dist/core/compute-accountant.js +179 -0
  67. package/dist/core/compute-accountant.js.map +1 -0
  68. package/dist/core/compute-runtime.d.ts +42 -0
  69. package/dist/core/compute-runtime.d.ts.map +1 -0
  70. package/dist/core/compute-runtime.js +80 -0
  71. package/dist/core/compute-runtime.js.map +1 -0
  72. package/dist/core/config.d.ts +44 -0
  73. package/dist/core/config.d.ts.map +1 -0
  74. package/dist/core/config.js +66 -0
  75. package/dist/core/config.js.map +1 -0
  76. package/dist/core/context.d.ts +76 -0
  77. package/dist/core/context.d.ts.map +1 -0
  78. package/dist/core/context.js +91 -0
  79. package/dist/core/context.js.map +1 -0
  80. package/dist/core/fargate-metadata.d.ts +27 -0
  81. package/dist/core/fargate-metadata.d.ts.map +1 -0
  82. package/dist/core/fargate-metadata.js +102 -0
  83. package/dist/core/fargate-metadata.js.map +1 -0
  84. package/dist/core/gpu-accountant.d.ts +104 -0
  85. package/dist/core/gpu-accountant.d.ts.map +1 -0
  86. package/dist/core/gpu-accountant.js +383 -0
  87. package/dist/core/gpu-accountant.js.map +1 -0
  88. package/dist/core/gpu-runtime.d.ts +58 -0
  89. package/dist/core/gpu-runtime.d.ts.map +1 -0
  90. package/dist/core/gpu-runtime.js +131 -0
  91. package/dist/core/gpu-runtime.js.map +1 -0
  92. package/dist/core/heuristics.d.ts +74 -0
  93. package/dist/core/heuristics.d.ts.map +1 -0
  94. package/dist/core/heuristics.js +182 -0
  95. package/dist/core/heuristics.js.map +1 -0
  96. package/dist/core/models.d.ts +149 -0
  97. package/dist/core/models.d.ts.map +1 -0
  98. package/dist/core/models.js +226 -0
  99. package/dist/core/models.js.map +1 -0
  100. package/dist/core/nvml-reader.d.ts +114 -0
  101. package/dist/core/nvml-reader.d.ts.map +1 -0
  102. package/dist/core/nvml-reader.js +323 -0
  103. package/dist/core/nvml-reader.js.map +1 -0
  104. package/dist/core/session.d.ts +48 -0
  105. package/dist/core/session.d.ts.map +1 -0
  106. package/dist/core/session.js +123 -0
  107. package/dist/core/session.js.map +1 -0
  108. package/dist/core/tracker.d.ts +364 -0
  109. package/dist/core/tracker.d.ts.map +1 -0
  110. package/dist/core/tracker.js +1073 -0
  111. package/dist/core/tracker.js.map +1 -0
  112. package/dist/data/compute_prices.json +180 -0
  113. package/dist/data/egress_prices.json +418 -0
  114. package/dist/data/gpu_prices.json +412 -0
  115. package/dist/data/service_prices.json +2595 -0
  116. package/dist/dev-console.d.ts +12 -0
  117. package/dist/dev-console.d.ts.map +1 -0
  118. package/dist/dev-console.js +60 -0
  119. package/dist/dev-console.js.map +1 -0
  120. package/dist/index.d.ts +52 -0
  121. package/dist/index.d.ts.map +1 -0
  122. package/dist/index.js +61 -0
  123. package/dist/index.js.map +1 -0
  124. package/dist/instruments/anthropic.d.ts +26 -0
  125. package/dist/instruments/anthropic.d.ts.map +1 -0
  126. package/dist/instruments/anthropic.js +242 -0
  127. package/dist/instruments/anthropic.js.map +1 -0
  128. package/dist/instruments/bedrock.d.ts +29 -0
  129. package/dist/instruments/bedrock.d.ts.map +1 -0
  130. package/dist/instruments/bedrock.js +215 -0
  131. package/dist/instruments/bedrock.js.map +1 -0
  132. package/dist/instruments/cohere.d.ts +29 -0
  133. package/dist/instruments/cohere.d.ts.map +1 -0
  134. package/dist/instruments/cohere.js +237 -0
  135. package/dist/instruments/cohere.js.map +1 -0
  136. package/dist/instruments/gemini.d.ts +30 -0
  137. package/dist/instruments/gemini.d.ts.map +1 -0
  138. package/dist/instruments/gemini.js +247 -0
  139. package/dist/instruments/gemini.js.map +1 -0
  140. package/dist/instruments/index.d.ts +35 -0
  141. package/dist/instruments/index.d.ts.map +1 -0
  142. package/dist/instruments/index.js +54 -0
  143. package/dist/instruments/index.js.map +1 -0
  144. package/dist/instruments/mcp.d.ts +24 -0
  145. package/dist/instruments/mcp.d.ts.map +1 -0
  146. package/dist/instruments/mcp.js +459 -0
  147. package/dist/instruments/mcp.js.map +1 -0
  148. package/dist/instruments/openai.d.ts +26 -0
  149. package/dist/instruments/openai.d.ts.map +1 -0
  150. package/dist/instruments/openai.js +221 -0
  151. package/dist/instruments/openai.js.map +1 -0
  152. package/dist/instruments/vercel-ai.d.ts +28 -0
  153. package/dist/instruments/vercel-ai.d.ts.map +1 -0
  154. package/dist/instruments/vercel-ai.js +192 -0
  155. package/dist/instruments/vercel-ai.js.map +1 -0
  156. package/dist/integrations/langchain.d.ts +65 -0
  157. package/dist/integrations/langchain.d.ts.map +1 -0
  158. package/dist/integrations/langchain.js +165 -0
  159. package/dist/integrations/langchain.js.map +1 -0
  160. package/dist/middleware/express.d.ts +55 -0
  161. package/dist/middleware/express.d.ts.map +1 -0
  162. package/dist/middleware/express.js +101 -0
  163. package/dist/middleware/express.js.map +1 -0
  164. package/dist/middleware/index.d.ts +6 -0
  165. package/dist/middleware/index.d.ts.map +1 -0
  166. package/dist/middleware/index.js +5 -0
  167. package/dist/middleware/index.js.map +1 -0
  168. package/dist/pricing/compute-pricing.d.ts +57 -0
  169. package/dist/pricing/compute-pricing.d.ts.map +1 -0
  170. package/dist/pricing/compute-pricing.js +627 -0
  171. package/dist/pricing/compute-pricing.js.map +1 -0
  172. package/dist/pricing/cost_map.json +37665 -0
  173. package/dist/pricing/egress-pricing.d.ts +55 -0
  174. package/dist/pricing/egress-pricing.d.ts.map +1 -0
  175. package/dist/pricing/egress-pricing.js +226 -0
  176. package/dist/pricing/egress-pricing.js.map +1 -0
  177. package/dist/pricing/engine.d.ts +24 -0
  178. package/dist/pricing/engine.d.ts.map +1 -0
  179. package/dist/pricing/engine.js +148 -0
  180. package/dist/pricing/engine.js.map +1 -0
  181. package/dist/pricing/gpu-pricing.d.ts +63 -0
  182. package/dist/pricing/gpu-pricing.d.ts.map +1 -0
  183. package/dist/pricing/gpu-pricing.js +484 -0
  184. package/dist/pricing/gpu-pricing.js.map +1 -0
  185. package/dist/pricing/rates.d.ts +17 -0
  186. package/dist/pricing/rates.d.ts.map +1 -0
  187. package/dist/pricing/rates.js +102 -0
  188. package/dist/pricing/rates.js.map +1 -0
  189. package/dist/pricing/service-catalog.d.ts +87 -0
  190. package/dist/pricing/service-catalog.d.ts.map +1 -0
  191. package/dist/pricing/service-catalog.js +406 -0
  192. package/dist/pricing/service-catalog.js.map +1 -0
  193. package/dist/schema/dexcost-event.v1.json +111 -0
  194. package/dist/schema/dexcost-task.v1.json +160 -0
  195. package/dist/schema/validate.d.ts +15 -0
  196. package/dist/schema/validate.d.ts.map +1 -0
  197. package/dist/schema/validate.js +87 -0
  198. package/dist/schema/validate.js.map +1 -0
  199. package/dist/security/redaction.d.ts +55 -0
  200. package/dist/security/redaction.d.ts.map +1 -0
  201. package/dist/security/redaction.js +144 -0
  202. package/dist/security/redaction.js.map +1 -0
  203. package/dist/transport/buffer.d.ts +117 -0
  204. package/dist/transport/buffer.d.ts.map +1 -0
  205. package/dist/transport/buffer.js +759 -0
  206. package/dist/transport/buffer.js.map +1 -0
  207. package/dist/transport/pusher.d.ts +89 -0
  208. package/dist/transport/pusher.d.ts.map +1 -0
  209. package/dist/transport/pusher.js +323 -0
  210. package/dist/transport/pusher.js.map +1 -0
  211. package/package.json +93 -0
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Active compute-runtime resolver.
3
+ *
4
+ * Cascade priority (capture spec §5.5):
5
+ *
6
+ * 1. Serverless env vars — Lambda, Fargate, Cloud Run, Cloud Functions Gen2,
7
+ * Azure Functions, Vercel
8
+ * 2. KUBERNETES_SERVICE_HOST → k8s_pod (wins over the underlying VM so a
9
+ * pod-on-EC2 is billed once as k8s_pod, not twice as k8s_pod + ec2)
10
+ * 3. cloud_detect IaaS fallback — EC2 / GCE / Azure VM via the existing
11
+ * CloudEnv.provider resolved by cloud-detect.
12
+ * 4. UNKNOWN
13
+ *
14
+ * The discriminator value emitted on compute_cost events
15
+ * (details.billing_model) is derived from this enum in
16
+ * compute-accountant._billingModelFor.
17
+ *
18
+ * **String values match Python** — cross-SDK event portability. Do not change.
19
+ *
20
+ * Mirrors python/src/dexcost/compute_runtime.py.
21
+ */
22
+ /**
23
+ * Runtime kind discriminator. String values are pinned to Python so events
24
+ * serialized in one SDK can be consumed by another.
25
+ */
26
+ export declare const RuntimeKind: {
27
+ readonly Lambda: "lambda";
28
+ readonly Fargate: "fargate";
29
+ readonly Ec2: "ec2";
30
+ readonly CloudRun: "cloud_run";
31
+ readonly CloudFunctions: "cloud_functions";
32
+ readonly Gce: "gce";
33
+ readonly AzureFunctions: "azure_functions";
34
+ readonly AzureVm: "azure_vm";
35
+ readonly Vercel: "vercel_fluid";
36
+ readonly K8sPod: "k8s_pod";
37
+ readonly Unknown: "unknown";
38
+ };
39
+ export type RuntimeKind = (typeof RuntimeKind)[keyof typeof RuntimeKind];
40
+ /** Return the active compute runtime for the current process. */
41
+ export declare function resolveRuntime(): RuntimeKind;
42
+ //# sourceMappingURL=compute-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-runtime.d.ts","sourceRoot":"","sources":["../../src/core/compute-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;CAYd,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAMzE,iEAAiE;AACjE,wBAAgB,cAAc,IAAI,WAAW,CA+B5C"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Active compute-runtime resolver.
3
+ *
4
+ * Cascade priority (capture spec §5.5):
5
+ *
6
+ * 1. Serverless env vars — Lambda, Fargate, Cloud Run, Cloud Functions Gen2,
7
+ * Azure Functions, Vercel
8
+ * 2. KUBERNETES_SERVICE_HOST → k8s_pod (wins over the underlying VM so a
9
+ * pod-on-EC2 is billed once as k8s_pod, not twice as k8s_pod + ec2)
10
+ * 3. cloud_detect IaaS fallback — EC2 / GCE / Azure VM via the existing
11
+ * CloudEnv.provider resolved by cloud-detect.
12
+ * 4. UNKNOWN
13
+ *
14
+ * The discriminator value emitted on compute_cost events
15
+ * (details.billing_model) is derived from this enum in
16
+ * compute-accountant._billingModelFor.
17
+ *
18
+ * **String values match Python** — cross-SDK event portability. Do not change.
19
+ *
20
+ * Mirrors python/src/dexcost/compute_runtime.py.
21
+ */
22
+ import { getCloudEnv } from "../cloud-detect.js";
23
+ /**
24
+ * Runtime kind discriminator. String values are pinned to Python so events
25
+ * serialized in one SDK can be consumed by another.
26
+ */
27
+ export const RuntimeKind = {
28
+ Lambda: "lambda",
29
+ Fargate: "fargate",
30
+ Ec2: "ec2",
31
+ CloudRun: "cloud_run",
32
+ CloudFunctions: "cloud_functions",
33
+ Gce: "gce",
34
+ AzureFunctions: "azure_functions",
35
+ AzureVm: "azure_vm",
36
+ Vercel: "vercel_fluid",
37
+ K8sPod: "k8s_pod",
38
+ Unknown: "unknown",
39
+ };
40
+ function _isNode() {
41
+ return typeof process !== "undefined" && !!process.versions?.node;
42
+ }
43
+ /** Return the active compute runtime for the current process. */
44
+ export function resolveRuntime() {
45
+ // In browser bundles process.env doesn't expose the serverless env vars
46
+ // — collapse straight to Unknown.
47
+ if (!_isNode())
48
+ return RuntimeKind.Unknown;
49
+ const env = process.env;
50
+ // 1. Serverless env vars — highest priority.
51
+ if (env.AWS_LAMBDA_FUNCTION_NAME)
52
+ return RuntimeKind.Lambda;
53
+ if (env.ECS_CONTAINER_METADATA_URI_V4 || env.ECS_CONTAINER_METADATA_URI) {
54
+ return RuntimeKind.Fargate;
55
+ }
56
+ if (env.K_SERVICE) {
57
+ // Cloud Functions Gen2 sets BOTH K_SERVICE and FUNCTION_TARGET; plain
58
+ // Cloud Run sets only K_SERVICE.
59
+ if (env.FUNCTION_TARGET)
60
+ return RuntimeKind.CloudFunctions;
61
+ return RuntimeKind.CloudRun;
62
+ }
63
+ if (env.FUNCTIONS_WORKER_RUNTIME)
64
+ return RuntimeKind.AzureFunctions;
65
+ if (env.VERCEL)
66
+ return RuntimeKind.Vercel;
67
+ // 2. Kubernetes wins over the underlying VM.
68
+ if (env.KUBERNETES_SERVICE_HOST)
69
+ return RuntimeKind.K8sPod;
70
+ // 3. Fall through to cloud-detect IaaS classification.
71
+ const cloud = getCloudEnv();
72
+ if (cloud.provider === "aws")
73
+ return RuntimeKind.Ec2;
74
+ if (cloud.provider === "gcp")
75
+ return RuntimeKind.Gce;
76
+ if (cloud.provider === "azure")
77
+ return RuntimeKind.AzureVm;
78
+ return RuntimeKind.Unknown;
79
+ }
80
+ //# sourceMappingURL=compute-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute-runtime.js","sourceRoot":"","sources":["../../src/core/compute-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,GAAG,EAAE,KAAK;IACV,QAAQ,EAAE,WAAW;IACrB,cAAc,EAAE,iBAAiB;IACjC,GAAG,EAAE,KAAK;IACV,cAAc,EAAE,iBAAiB;IACjC,OAAO,EAAE,UAAU;IACnB,MAAM,EAAE,cAAc;IACtB,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,SAAS;CACV,CAAC;AAIX,SAAS,OAAO;IACd,OAAO,OAAO,OAAO,KAAK,WAAW,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC;AACpE,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,cAAc;IAC5B,wEAAwE;IACxE,kCAAkC;IAClC,IAAI,CAAC,OAAO,EAAE;QAAE,OAAO,WAAW,CAAC,OAAO,CAAC;IAE3C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAExB,6CAA6C;IAC7C,IAAI,GAAG,CAAC,wBAAwB;QAAE,OAAO,WAAW,CAAC,MAAM,CAAC;IAC5D,IAAI,GAAG,CAAC,6BAA6B,IAAI,GAAG,CAAC,0BAA0B,EAAE,CAAC;QACxE,OAAO,WAAW,CAAC,OAAO,CAAC;IAC7B,CAAC;IACD,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;QAClB,sEAAsE;QACtE,iCAAiC;QACjC,IAAI,GAAG,CAAC,eAAe;YAAE,OAAO,WAAW,CAAC,cAAc,CAAC;QAC3D,OAAO,WAAW,CAAC,QAAQ,CAAC;IAC9B,CAAC;IACD,IAAI,GAAG,CAAC,wBAAwB;QAAE,OAAO,WAAW,CAAC,cAAc,CAAC;IACpE,IAAI,GAAG,CAAC,MAAM;QAAE,OAAO,WAAW,CAAC,MAAM,CAAC;IAE1C,6CAA6C;IAC7C,IAAI,GAAG,CAAC,uBAAuB;QAAE,OAAO,WAAW,CAAC,MAAM,CAAC;IAE3D,uDAAuD;IACvD,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;IAC5B,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK;QAAE,OAAO,WAAW,CAAC,GAAG,CAAC;IACrD,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK;QAAE,OAAO,WAAW,CAAC,GAAG,CAAC;IACrD,IAAI,KAAK,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,WAAW,CAAC,OAAO,CAAC;IAE3D,OAAO,WAAW,CAAC,OAAO,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * SDK configuration and API-key infrastructure.
3
+ *
4
+ * Mirrors the Python SDK's `config.py`: API keys must start with
5
+ * `dx_live_` or `dx_test_`, the key is resolved from the
6
+ * `DEXCOST_API_KEY` environment variable when not passed explicitly,
7
+ * and an explicit `storage: "local"` forces local-only mode.
8
+ */
9
+ /** Raised when an API key has an invalid format. */
10
+ export declare class InvalidAPIKeyError extends Error {
11
+ constructor(message: string);
12
+ }
13
+ /** Detected key type — `"live"`, `"test"`, or `undefined` when no key. */
14
+ export type KeyType = "live" | "test";
15
+ /**
16
+ * Validate an API key's format.
17
+ *
18
+ * Returns `"live"`, `"test"`, or `undefined` when `key` is undefined/null.
19
+ * Throws `InvalidAPIKeyError` for any other (non-empty) value.
20
+ */
21
+ export declare function validateApiKey(key: string | undefined | null): KeyType | undefined;
22
+ /** Storage mode — `"cloud"` syncs to the Control Layer, `"local"` does not. */
23
+ export type StorageMode = "cloud" | "local";
24
+ /** Resolved SDK configuration. */
25
+ export interface ResolvedConfig {
26
+ /** The effective API key (explicit arg or `DEXCOST_API_KEY` env var). */
27
+ apiKey?: string;
28
+ /** Detected key type. */
29
+ keyType?: KeyType;
30
+ /** True when the key is a test/sandbox key. */
31
+ isSandbox: boolean;
32
+ /** Resolved storage mode. */
33
+ storageMode: StorageMode;
34
+ }
35
+ /**
36
+ * Resolve the effective API key and storage mode.
37
+ *
38
+ * @param apiKey - Explicit API key (takes precedence over the env var).
39
+ * @param storage - Explicit storage mode. `"local"` forces local-only and
40
+ * skips env-var resolution; otherwise the mode is inferred from whether
41
+ * a key is present.
42
+ */
43
+ export declare function resolveConfig(apiKey?: string, storage?: StorageMode): ResolvedConfig;
44
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,oDAAoD;AACpD,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,0EAA0E;AAC1E,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEtC;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,GAAG,SAAS,CAclF;AAED,+EAA+E;AAC/E,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,OAAO,CAAC;AAE5C,kCAAkC;AAClC,MAAM,WAAW,cAAc;IAC7B,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,6BAA6B;IAC7B,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,GACpB,cAAc,CAuBhB"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * SDK configuration and API-key infrastructure.
3
+ *
4
+ * Mirrors the Python SDK's `config.py`: API keys must start with
5
+ * `dx_live_` or `dx_test_`, the key is resolved from the
6
+ * `DEXCOST_API_KEY` environment variable when not passed explicitly,
7
+ * and an explicit `storage: "local"` forces local-only mode.
8
+ */
9
+ /** Raised when an API key has an invalid format. */
10
+ export class InvalidAPIKeyError extends Error {
11
+ constructor(message) {
12
+ super(message);
13
+ this.name = "InvalidAPIKeyError";
14
+ }
15
+ }
16
+ /**
17
+ * Validate an API key's format.
18
+ *
19
+ * Returns `"live"`, `"test"`, or `undefined` when `key` is undefined/null.
20
+ * Throws `InvalidAPIKeyError` for any other (non-empty) value.
21
+ */
22
+ export function validateApiKey(key) {
23
+ if (key === undefined || key === null) {
24
+ return undefined;
25
+ }
26
+ if (key.startsWith("dx_live_")) {
27
+ return "live";
28
+ }
29
+ if (key.startsWith("dx_test_")) {
30
+ return "test";
31
+ }
32
+ throw new InvalidAPIKeyError(`Invalid API key format: key must start with 'dx_live_' or 'dx_test_', ` +
33
+ `got '${key.slice(0, 10)}...'`);
34
+ }
35
+ /**
36
+ * Resolve the effective API key and storage mode.
37
+ *
38
+ * @param apiKey - Explicit API key (takes precedence over the env var).
39
+ * @param storage - Explicit storage mode. `"local"` forces local-only and
40
+ * skips env-var resolution; otherwise the mode is inferred from whether
41
+ * a key is present.
42
+ */
43
+ export function resolveConfig(apiKey, storage) {
44
+ let effectiveKey = apiKey;
45
+ if (effectiveKey === undefined && storage !== "local") {
46
+ effectiveKey = process.env.DEXCOST_API_KEY ?? undefined;
47
+ }
48
+ const keyType = validateApiKey(effectiveKey);
49
+ let storageMode;
50
+ if (storage === "local") {
51
+ storageMode = "local";
52
+ }
53
+ else if (effectiveKey !== undefined) {
54
+ storageMode = "cloud";
55
+ }
56
+ else {
57
+ storageMode = "local";
58
+ }
59
+ return {
60
+ apiKey: effectiveKey,
61
+ keyType,
62
+ isSandbox: keyType === "test",
63
+ storageMode,
64
+ };
65
+ }
66
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,oDAAoD;AACpD,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAKD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,GAA8B;IAC3D,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACtC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,IAAI,kBAAkB,CAC1B,wEAAwE;QACtE,QAAQ,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CACjC,CAAC;AACJ,CAAC;AAiBD;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAe,EACf,OAAqB;IAErB,IAAI,YAAY,GAAG,MAAM,CAAC;IAC1B,IAAI,YAAY,KAAK,SAAS,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACtD,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,SAAS,CAAC;IAC1D,CAAC;IAED,MAAM,OAAO,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAE7C,IAAI,WAAwB,CAAC;IAC7B,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,WAAW,GAAG,OAAO,CAAC;IACxB,CAAC;SAAM,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QACtC,WAAW,GAAG,OAAO,CAAC;IACxB,CAAC;SAAM,CAAC;QACN,WAAW,GAAG,OAAO,CAAC;IACxB,CAAC;IAED,OAAO;QACL,MAAM,EAAE,YAAY;QACpB,OAAO;QACP,SAAS,EAAE,OAAO,KAAK,MAAM;QAC7B,WAAW;KACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Task context propagation using AsyncLocalStorage.
3
+ *
4
+ * Allows automatic association of cost events with the currently-active
5
+ * task without explicit parameter passing.
6
+ */
7
+ import type { Task } from "./models.js";
8
+ /**
9
+ * Return the currently-active Task, or undefined if no task context is set.
10
+ */
11
+ export declare function getCurrentTask(): Task | undefined;
12
+ /**
13
+ * Execute `fn` with `task` as the current task context.
14
+ *
15
+ * Any code running inside `fn` (including async continuations) can call
16
+ * `getCurrentTask()` to retrieve the task.
17
+ */
18
+ export declare function runWithTask<T>(task: Task, fn: () => T): T;
19
+ /**
20
+ * Set the current task for the remaining async execution context.
21
+ *
22
+ * Uses `AsyncLocalStorage.enterWith()` (Node 18+) so the task is visible
23
+ * to all subsequent code in the current async chain without wrapping in
24
+ * a callback.
25
+ */
26
+ export declare function setCurrentTask(task: Task): void;
27
+ /**
28
+ * Ambient context for automatic cost attribution.
29
+ *
30
+ * Set once at request/job start (e.g., in Express middleware) and any
31
+ * auto-instrumented LLM call without an explicit task will inherit
32
+ * customerId, projectId, and metadata from this context.
33
+ */
34
+ export interface DexcostContext {
35
+ customerId?: string;
36
+ projectId?: string;
37
+ metadata?: Record<string, unknown>;
38
+ agent?: string;
39
+ }
40
+ /**
41
+ * Set the ambient DexcostContext for the current async execution context.
42
+ *
43
+ * Uses `AsyncLocalStorage.enterWith()` (Node 18+) so the context is visible
44
+ * to all code in the remaining async chain without wrapping in a callback.
45
+ *
46
+ * For concurrent request isolation (web servers), call this inside a
47
+ * per-request middleware or use `runWithTask()` which isolates its own
48
+ * async context.
49
+ */
50
+ export declare function setContext(ctx: {
51
+ customerId?: string;
52
+ projectId?: string;
53
+ metadata?: Record<string, unknown>;
54
+ agent?: string;
55
+ }): void;
56
+ /**
57
+ * Return the current DexcostContext, or undefined if none is set.
58
+ */
59
+ export declare function getContext(): DexcostContext | undefined;
60
+ /**
61
+ * Clear the ambient DexcostContext for the current async execution context.
62
+ */
63
+ export declare function clearContext(): void;
64
+ /**
65
+ * Returns `true` when the current async scope has suppressed `network`
66
+ * event emission. Bytes are still counted into the accountant; only the
67
+ * standalone event is withheld.
68
+ */
69
+ export declare function isNetworkEventSuppressed(): boolean;
70
+ /**
71
+ * Run `fn` (sync or async) inside a scope where `network`-event emission
72
+ * is suppressed. Used by LLM instruments around their fetch call so the
73
+ * call doesn't double-emit (llm_call + network).
74
+ */
75
+ export declare function suppressNetworkEvent<T>(fn: () => T): T;
76
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAIxC;;GAEG;AACH,wBAAgB,cAAc,IAAI,IAAI,GAAG,SAAS,CAEjD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAEzD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAE/C;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CAOP;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,cAAc,GAAG,SAAS,CAEvD;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAcD;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAEtD"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Task context propagation using AsyncLocalStorage.
3
+ *
4
+ * Allows automatic association of cost events with the currently-active
5
+ * task without explicit parameter passing.
6
+ */
7
+ import { AsyncLocalStorage } from "node:async_hooks";
8
+ const taskStore = new AsyncLocalStorage();
9
+ /**
10
+ * Return the currently-active Task, or undefined if no task context is set.
11
+ */
12
+ export function getCurrentTask() {
13
+ return taskStore.getStore();
14
+ }
15
+ /**
16
+ * Execute `fn` with `task` as the current task context.
17
+ *
18
+ * Any code running inside `fn` (including async continuations) can call
19
+ * `getCurrentTask()` to retrieve the task.
20
+ */
21
+ export function runWithTask(task, fn) {
22
+ return taskStore.run(task, fn);
23
+ }
24
+ /**
25
+ * Set the current task for the remaining async execution context.
26
+ *
27
+ * Uses `AsyncLocalStorage.enterWith()` (Node 18+) so the task is visible
28
+ * to all subsequent code in the current async chain without wrapping in
29
+ * a callback.
30
+ */
31
+ export function setCurrentTask(task) {
32
+ taskStore.enterWith(task);
33
+ }
34
+ const contextStore = new AsyncLocalStorage();
35
+ /**
36
+ * Set the ambient DexcostContext for the current async execution context.
37
+ *
38
+ * Uses `AsyncLocalStorage.enterWith()` (Node 18+) so the context is visible
39
+ * to all code in the remaining async chain without wrapping in a callback.
40
+ *
41
+ * For concurrent request isolation (web servers), call this inside a
42
+ * per-request middleware or use `runWithTask()` which isolates its own
43
+ * async context.
44
+ */
45
+ export function setContext(ctx) {
46
+ contextStore.enterWith({
47
+ customerId: ctx.customerId,
48
+ projectId: ctx.projectId,
49
+ metadata: ctx.metadata ?? {},
50
+ agent: ctx.agent,
51
+ });
52
+ }
53
+ /**
54
+ * Return the current DexcostContext, or undefined if none is set.
55
+ */
56
+ export function getContext() {
57
+ return contextStore.getStore();
58
+ }
59
+ /**
60
+ * Clear the ambient DexcostContext for the current async execution context.
61
+ */
62
+ export function clearContext() {
63
+ contextStore.enterWith({});
64
+ }
65
+ // ---------------------------------------------------------------------------
66
+ // Per-call network-event suppression flag (v1 §5.3 invariant)
67
+ // ---------------------------------------------------------------------------
68
+ //
69
+ // When set, the HTTP adapter still records bytes into the NetworkAccountant
70
+ // but does NOT emit a standalone `network` event. LLM instruments wrap
71
+ // their outbound fetch call inside suppressNetworkEvent(...) so each call
72
+ // produces at most one of {llm_call, external_cost, network} — the v1
73
+ // §5.3 "≤ 1 event per HTTP call" invariant.
74
+ const suppressStore = new AsyncLocalStorage();
75
+ /**
76
+ * Returns `true` when the current async scope has suppressed `network`
77
+ * event emission. Bytes are still counted into the accountant; only the
78
+ * standalone event is withheld.
79
+ */
80
+ export function isNetworkEventSuppressed() {
81
+ return suppressStore.getStore() === true;
82
+ }
83
+ /**
84
+ * Run `fn` (sync or async) inside a scope where `network`-event emission
85
+ * is suppressed. Used by LLM instruments around their fetch call so the
86
+ * call doesn't double-emit (llm_call + network).
87
+ */
88
+ export function suppressNetworkEvent(fn) {
89
+ return suppressStore.run(true, fn);
90
+ }
91
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,MAAM,SAAS,GAAG,IAAI,iBAAiB,EAAQ,CAAC;AAEhD;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,SAAS,CAAC,QAAQ,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAI,IAAU,EAAE,EAAW;IACpD,OAAO,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAU;IACvC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAoBD,MAAM,YAAY,GAAG,IAAI,iBAAiB,EAAkB,CAAC;AAE7D;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAC,GAK1B;IACC,YAAY,CAAC,SAAS,CAAC;QACrB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE;QAC5B,KAAK,EAAE,GAAG,CAAC,KAAK;KACjB,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,YAAY,CAAC,QAAQ,EAAE,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED,8EAA8E;AAC9E,8DAA8D;AAC9D,8EAA8E;AAC9E,EAAE;AACF,4EAA4E;AAC5E,uEAAuE;AACvE,0EAA0E;AAC1E,sEAAsE;AACtE,4CAA4C;AAE5C,MAAM,aAAa,GAAG,IAAI,iBAAiB,EAAW,CAAC;AAEvD;;;;GAIG;AACH,MAAM,UAAU,wBAAwB;IACtC,OAAO,aAAa,CAAC,QAAQ,EAAE,KAAK,IAAI,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAI,EAAW;IACjD,OAAO,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Fargate ECS task metadata reader (node-only, browser-safe).
3
+ *
4
+ * Hits `${ECS_CONTAINER_METADATA_URI_V4}/task` (or v3) once per process and
5
+ * caches the parsed result. Exposes vcpuCount (number) and
6
+ * memoryBytesLimit (number — converted from MiB per Decision #7).
7
+ *
8
+ * Fail-silent contract (convention §9): unreachable endpoint, malformed JSON,
9
+ * missing fields all return `null` and log once via convention §11.
10
+ *
11
+ * Mirrors python/src/dexcost/fargate_metadata.py.
12
+ */
13
+ export interface FargateTaskMetadata {
14
+ vcpuCount: number;
15
+ memoryBytesLimit: number;
16
+ }
17
+ /** Test-only — clear cached state. */
18
+ export declare function _resetForTests(): void;
19
+ export declare function _setFetchForTests(impl: typeof fetch | null): void;
20
+ /**
21
+ * Read + cache the ECS task metadata. Idempotent.
22
+ *
23
+ * Returns `null` when not on Fargate, when the endpoint is unreachable,
24
+ * or when the Limits block is missing / malformed.
25
+ */
26
+ export declare function fetchFargateMetadata(): Promise<FargateTaskMetadata | null>;
27
+ //# sourceMappingURL=fargate-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fargate-metadata.d.ts","sourceRoot":"","sources":["../../src/core/fargate-metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAMD,sCAAsC;AACtC,wBAAgB,cAAc,IAAI,IAAI,CAIrC;AAID,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,KAAK,GAAG,IAAI,GAAG,IAAI,CAEjE;AAeD;;;;;GAKG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CA+DhF"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Fargate ECS task metadata reader (node-only, browser-safe).
3
+ *
4
+ * Hits `${ECS_CONTAINER_METADATA_URI_V4}/task` (or v3) once per process and
5
+ * caches the parsed result. Exposes vcpuCount (number) and
6
+ * memoryBytesLimit (number — converted from MiB per Decision #7).
7
+ *
8
+ * Fail-silent contract (convention §9): unreachable endpoint, malformed JSON,
9
+ * missing fields all return `null` and log once via convention §11.
10
+ *
11
+ * Mirrors python/src/dexcost/fargate_metadata.py.
12
+ */
13
+ const PROBE_TIMEOUT_MS = 250;
14
+ let _cached = null;
15
+ let _resolved = false;
16
+ let _warned = false;
17
+ /** Test-only — clear cached state. */
18
+ export function _resetForTests() {
19
+ _cached = null;
20
+ _resolved = false;
21
+ _warned = false;
22
+ }
23
+ /** Hookable fetch — tests replace this to avoid real network calls. */
24
+ let _fetchImpl = (...args) => fetch(...args);
25
+ export function _setFetchForTests(impl) {
26
+ _fetchImpl = impl ?? ((...args) => fetch(...args));
27
+ }
28
+ function _isNode() {
29
+ return typeof process !== "undefined" && !!process.versions?.node;
30
+ }
31
+ function _endpoint() {
32
+ if (!_isNode())
33
+ return null;
34
+ const base = process.env.ECS_CONTAINER_METADATA_URI_V4 ||
35
+ process.env.ECS_CONTAINER_METADATA_URI;
36
+ if (!base)
37
+ return null;
38
+ return base.replace(/\/+$/, "") + "/task";
39
+ }
40
+ /**
41
+ * Read + cache the ECS task metadata. Idempotent.
42
+ *
43
+ * Returns `null` when not on Fargate, when the endpoint is unreachable,
44
+ * or when the Limits block is missing / malformed.
45
+ */
46
+ export async function fetchFargateMetadata() {
47
+ if (_resolved)
48
+ return _cached;
49
+ const url = _endpoint();
50
+ if (url === null) {
51
+ _resolved = true;
52
+ return null;
53
+ }
54
+ let payload;
55
+ try {
56
+ const resp = await _fetchImpl(url, {
57
+ signal: AbortSignal.timeout(PROBE_TIMEOUT_MS),
58
+ });
59
+ if (!resp.ok)
60
+ throw new Error(`HTTP ${resp.status}`);
61
+ payload = await resp.json();
62
+ }
63
+ catch (exc) {
64
+ _resolved = true;
65
+ if (!_warned) {
66
+ _warned = true;
67
+ // eslint-disable-next-line no-console
68
+ console.warn(`fargate metadata unreachable (${exc?.message ?? exc}); ` +
69
+ "compute cost will fall through to default rates");
70
+ }
71
+ return null;
72
+ }
73
+ const limits = typeof payload === "object" && payload !== null
74
+ ? payload.Limits
75
+ : undefined;
76
+ if (!limits) {
77
+ _resolved = true;
78
+ return null;
79
+ }
80
+ const cpuRaw = limits.CPU;
81
+ const memRaw = limits.Memory;
82
+ const vcpu = typeof cpuRaw === "number" ? cpuRaw : Number(cpuRaw);
83
+ const memMib = typeof memRaw === "number" ? memRaw : Number(memRaw);
84
+ if (!Number.isFinite(vcpu) ||
85
+ Number.isNaN(vcpu) ||
86
+ !Number.isFinite(memMib) ||
87
+ Number.isNaN(memMib)) {
88
+ _resolved = true;
89
+ return null;
90
+ }
91
+ // Decision #7 — Fargate memory is in MiB (binary), NOT MB. Convert to
92
+ // bytes via the binary divisor.
93
+ const memoryBytesLimit = Math.trunc(memMib) * 1024 * 1024;
94
+ const result = {
95
+ vcpuCount: vcpu,
96
+ memoryBytesLimit,
97
+ };
98
+ _cached = result;
99
+ _resolved = true;
100
+ return result;
101
+ }
102
+ //# sourceMappingURL=fargate-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fargate-metadata.js","sourceRoot":"","sources":["../../src/core/fargate-metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAO7B,IAAI,OAAO,GAA+B,IAAI,CAAC;AAC/C,IAAI,SAAS,GAAG,KAAK,CAAC;AACtB,IAAI,OAAO,GAAG,KAAK,CAAC;AAEpB,sCAAsC;AACtC,MAAM,UAAU,cAAc;IAC5B,OAAO,GAAG,IAAI,CAAC;IACf,SAAS,GAAG,KAAK,CAAC;IAClB,OAAO,GAAG,KAAK,CAAC;AAClB,CAAC;AAED,uEAAuE;AACvE,IAAI,UAAU,GAAiB,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;AAC3D,MAAM,UAAU,iBAAiB,CAAC,IAAyB;IACzD,UAAU,GAAG,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,OAAO;IACd,OAAO,OAAO,OAAO,KAAK,WAAW,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC;AACpE,CAAC;AAED,SAAS,SAAS;IAChB,IAAI,CAAC,OAAO,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,IAAI,GACR,OAAO,CAAC,GAAG,CAAC,6BAA6B;QACzC,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,IAAI,SAAS;QAAE,OAAO,OAAO,CAAC;IAE9B,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,SAAS,GAAG,IAAI,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE;YACjC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,gBAAgB,CAAC;SAC9C,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,SAAS,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,CAAC;YACf,sCAAsC;YACtC,OAAO,CAAC,IAAI,CACV,iCAAkC,GAAa,EAAE,OAAO,IAAI,GAAG,KAAK;gBAClE,iDAAiD,CACpD,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GACV,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;QAC7C,CAAC,CAAG,OAAmC,CAAC,MAA8C;QACtF,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,SAAS,GAAG,IAAI,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC;IAC1B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,MAAM,IAAI,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpE,IACE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QACtB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QAClB,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QACxB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EACpB,CAAC;QACD,SAAS,GAAG,IAAI,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,sEAAsE;IACtE,gCAAgC;IAChC,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;IAE1D,MAAM,MAAM,GAAwB;QAClC,SAAS,EAAE,IAAI;QACf,gBAAgB;KACjB,CAAC;IACF,OAAO,GAAG,MAAM,CAAC;IACjB,SAAS,GAAG,IAAI,CAAC;IACjB,OAAO,MAAM,CAAC;AAChB,CAAC"}