@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.
- package/LICENSE +21 -0
- package/README.md +210 -0
- package/dist/adapters/_netbytes.d.ts +31 -0
- package/dist/adapters/_netbytes.d.ts.map +1 -0
- package/dist/adapters/_netbytes.js +154 -0
- package/dist/adapters/_netbytes.js.map +1 -0
- package/dist/adapters/aws-lambda.d.ts +41 -0
- package/dist/adapters/aws-lambda.d.ts.map +1 -0
- package/dist/adapters/aws-lambda.js +65 -0
- package/dist/adapters/aws-lambda.js.map +1 -0
- package/dist/adapters/browser.d.ts +52 -0
- package/dist/adapters/browser.d.ts.map +1 -0
- package/dist/adapters/browser.js +127 -0
- package/dist/adapters/browser.js.map +1 -0
- package/dist/adapters/compute-wrap.d.ts +33 -0
- package/dist/adapters/compute-wrap.d.ts.map +1 -0
- package/dist/adapters/compute-wrap.js +188 -0
- package/dist/adapters/compute-wrap.js.map +1 -0
- package/dist/adapters/data/aws_lambda_pricing.json +61 -0
- package/dist/adapters/gpu-wrap.d.ts +31 -0
- package/dist/adapters/gpu-wrap.d.ts.map +1 -0
- package/dist/adapters/gpu-wrap.js +147 -0
- package/dist/adapters/gpu-wrap.js.map +1 -0
- package/dist/adapters/http.d.ts +58 -0
- package/dist/adapters/http.d.ts.map +1 -0
- package/dist/adapters/http.js +769 -0
- package/dist/adapters/http.js.map +1 -0
- package/dist/adapters/index.d.ts +11 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +12 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/network-accountant.d.ts +63 -0
- package/dist/adapters/network-accountant.d.ts.map +1 -0
- package/dist/adapters/network-accountant.js +153 -0
- package/dist/adapters/network-accountant.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +225 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/scanner.d.ts +39 -0
- package/dist/cli/scanner.d.ts.map +1 -0
- package/dist/cli/scanner.js +480 -0
- package/dist/cli/scanner.js.map +1 -0
- package/dist/clients.d.ts +54 -0
- package/dist/clients.d.ts.map +1 -0
- package/dist/clients.js +240 -0
- package/dist/clients.js.map +1 -0
- package/dist/cloud-detect.d.ts +96 -0
- package/dist/cloud-detect.d.ts.map +1 -0
- package/dist/cloud-detect.js +545 -0
- package/dist/cloud-detect.js.map +1 -0
- package/dist/core/auto-task.d.ts +20 -0
- package/dist/core/auto-task.d.ts.map +1 -0
- package/dist/core/auto-task.js +34 -0
- package/dist/core/auto-task.js.map +1 -0
- package/dist/core/cgroup-reader.d.ts +45 -0
- package/dist/core/cgroup-reader.d.ts.map +1 -0
- package/dist/core/cgroup-reader.js +124 -0
- package/dist/core/cgroup-reader.js.map +1 -0
- package/dist/core/cgroup-walker.d.ts +60 -0
- package/dist/core/cgroup-walker.d.ts.map +1 -0
- package/dist/core/cgroup-walker.js +166 -0
- package/dist/core/cgroup-walker.js.map +1 -0
- package/dist/core/compute-accountant.d.ts +51 -0
- package/dist/core/compute-accountant.d.ts.map +1 -0
- package/dist/core/compute-accountant.js +179 -0
- package/dist/core/compute-accountant.js.map +1 -0
- package/dist/core/compute-runtime.d.ts +42 -0
- package/dist/core/compute-runtime.d.ts.map +1 -0
- package/dist/core/compute-runtime.js +80 -0
- package/dist/core/compute-runtime.js.map +1 -0
- package/dist/core/config.d.ts +44 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +66 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/context.d.ts +76 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +91 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/fargate-metadata.d.ts +27 -0
- package/dist/core/fargate-metadata.d.ts.map +1 -0
- package/dist/core/fargate-metadata.js +102 -0
- package/dist/core/fargate-metadata.js.map +1 -0
- package/dist/core/gpu-accountant.d.ts +104 -0
- package/dist/core/gpu-accountant.d.ts.map +1 -0
- package/dist/core/gpu-accountant.js +383 -0
- package/dist/core/gpu-accountant.js.map +1 -0
- package/dist/core/gpu-runtime.d.ts +58 -0
- package/dist/core/gpu-runtime.d.ts.map +1 -0
- package/dist/core/gpu-runtime.js +131 -0
- package/dist/core/gpu-runtime.js.map +1 -0
- package/dist/core/heuristics.d.ts +74 -0
- package/dist/core/heuristics.d.ts.map +1 -0
- package/dist/core/heuristics.js +182 -0
- package/dist/core/heuristics.js.map +1 -0
- package/dist/core/models.d.ts +149 -0
- package/dist/core/models.d.ts.map +1 -0
- package/dist/core/models.js +226 -0
- package/dist/core/models.js.map +1 -0
- package/dist/core/nvml-reader.d.ts +114 -0
- package/dist/core/nvml-reader.d.ts.map +1 -0
- package/dist/core/nvml-reader.js +323 -0
- package/dist/core/nvml-reader.js.map +1 -0
- package/dist/core/session.d.ts +48 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +123 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/tracker.d.ts +364 -0
- package/dist/core/tracker.d.ts.map +1 -0
- package/dist/core/tracker.js +1073 -0
- package/dist/core/tracker.js.map +1 -0
- package/dist/data/compute_prices.json +180 -0
- package/dist/data/egress_prices.json +418 -0
- package/dist/data/gpu_prices.json +412 -0
- package/dist/data/service_prices.json +2595 -0
- package/dist/dev-console.d.ts +12 -0
- package/dist/dev-console.d.ts.map +1 -0
- package/dist/dev-console.js +60 -0
- package/dist/dev-console.js.map +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/instruments/anthropic.d.ts +26 -0
- package/dist/instruments/anthropic.d.ts.map +1 -0
- package/dist/instruments/anthropic.js +242 -0
- package/dist/instruments/anthropic.js.map +1 -0
- package/dist/instruments/bedrock.d.ts +29 -0
- package/dist/instruments/bedrock.d.ts.map +1 -0
- package/dist/instruments/bedrock.js +215 -0
- package/dist/instruments/bedrock.js.map +1 -0
- package/dist/instruments/cohere.d.ts +29 -0
- package/dist/instruments/cohere.d.ts.map +1 -0
- package/dist/instruments/cohere.js +237 -0
- package/dist/instruments/cohere.js.map +1 -0
- package/dist/instruments/gemini.d.ts +30 -0
- package/dist/instruments/gemini.d.ts.map +1 -0
- package/dist/instruments/gemini.js +247 -0
- package/dist/instruments/gemini.js.map +1 -0
- package/dist/instruments/index.d.ts +35 -0
- package/dist/instruments/index.d.ts.map +1 -0
- package/dist/instruments/index.js +54 -0
- package/dist/instruments/index.js.map +1 -0
- package/dist/instruments/mcp.d.ts +24 -0
- package/dist/instruments/mcp.d.ts.map +1 -0
- package/dist/instruments/mcp.js +459 -0
- package/dist/instruments/mcp.js.map +1 -0
- package/dist/instruments/openai.d.ts +26 -0
- package/dist/instruments/openai.d.ts.map +1 -0
- package/dist/instruments/openai.js +221 -0
- package/dist/instruments/openai.js.map +1 -0
- package/dist/instruments/vercel-ai.d.ts +28 -0
- package/dist/instruments/vercel-ai.d.ts.map +1 -0
- package/dist/instruments/vercel-ai.js +192 -0
- package/dist/instruments/vercel-ai.js.map +1 -0
- package/dist/integrations/langchain.d.ts +65 -0
- package/dist/integrations/langchain.d.ts.map +1 -0
- package/dist/integrations/langchain.js +165 -0
- package/dist/integrations/langchain.js.map +1 -0
- package/dist/middleware/express.d.ts +55 -0
- package/dist/middleware/express.d.ts.map +1 -0
- package/dist/middleware/express.js +101 -0
- package/dist/middleware/express.js.map +1 -0
- package/dist/middleware/index.d.ts +6 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +5 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/pricing/compute-pricing.d.ts +57 -0
- package/dist/pricing/compute-pricing.d.ts.map +1 -0
- package/dist/pricing/compute-pricing.js +627 -0
- package/dist/pricing/compute-pricing.js.map +1 -0
- package/dist/pricing/cost_map.json +37665 -0
- package/dist/pricing/egress-pricing.d.ts +55 -0
- package/dist/pricing/egress-pricing.d.ts.map +1 -0
- package/dist/pricing/egress-pricing.js +226 -0
- package/dist/pricing/egress-pricing.js.map +1 -0
- package/dist/pricing/engine.d.ts +24 -0
- package/dist/pricing/engine.d.ts.map +1 -0
- package/dist/pricing/engine.js +148 -0
- package/dist/pricing/engine.js.map +1 -0
- package/dist/pricing/gpu-pricing.d.ts +63 -0
- package/dist/pricing/gpu-pricing.d.ts.map +1 -0
- package/dist/pricing/gpu-pricing.js +484 -0
- package/dist/pricing/gpu-pricing.js.map +1 -0
- package/dist/pricing/rates.d.ts +17 -0
- package/dist/pricing/rates.d.ts.map +1 -0
- package/dist/pricing/rates.js +102 -0
- package/dist/pricing/rates.js.map +1 -0
- package/dist/pricing/service-catalog.d.ts +87 -0
- package/dist/pricing/service-catalog.d.ts.map +1 -0
- package/dist/pricing/service-catalog.js +406 -0
- package/dist/pricing/service-catalog.js.map +1 -0
- package/dist/schema/dexcost-event.v1.json +111 -0
- package/dist/schema/dexcost-task.v1.json +160 -0
- package/dist/schema/validate.d.ts +15 -0
- package/dist/schema/validate.d.ts.map +1 -0
- package/dist/schema/validate.js +87 -0
- package/dist/schema/validate.js.map +1 -0
- package/dist/security/redaction.d.ts +55 -0
- package/dist/security/redaction.d.ts.map +1 -0
- package/dist/security/redaction.js +144 -0
- package/dist/security/redaction.js.map +1 -0
- package/dist/transport/buffer.d.ts +117 -0
- package/dist/transport/buffer.d.ts.map +1 -0
- package/dist/transport/buffer.js +759 -0
- package/dist/transport/buffer.js.map +1 -0
- package/dist/transport/pusher.d.ts +89 -0
- package/dist/transport/pusher.d.ts.map +1 -0
- package/dist/transport/pusher.js +323 -0
- package/dist/transport/pusher.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Active GPU runtime resolver — Phase 2 Task 3.
|
|
3
|
+
*
|
|
4
|
+
* Sibling of `compute-runtime.ts`. Coexists without modification —
|
|
5
|
+
* compute-runtime answers "which compute billing model" and gpu-runtime
|
|
6
|
+
* answers "which GPU billing model (if any)".
|
|
7
|
+
*
|
|
8
|
+
* Cascade priority (capture spec §5.5):
|
|
9
|
+
*
|
|
10
|
+
* 1. Serverless GPU env vars (MODAL_TASK_ID / RUNPOD_POD_ID /
|
|
11
|
+
* REPLICATE_MODEL) — win immediately when NVML is available.
|
|
12
|
+
* 2. IaaS GPU via cloud_detect — provider AWS/GCP/Azure AND instanceType
|
|
13
|
+
* matches a GPU-family regex AND NVML reports ≥1 device. Classifies as
|
|
14
|
+
* AWS_EC2_GPU / GCP_GCE_BUNDLED / GCP_GCE_N1_ATTACHED (Decision #9) /
|
|
15
|
+
* AZURE_VM_GPU / AZURE_VM_VGPU (Decision #10).
|
|
16
|
+
* 3. Reserved-GPU providers — Lambda Labs / CoreWeave from cloud_detect
|
|
17
|
+
* AND NVML reports ≥1 device.
|
|
18
|
+
* 4. NONE when NVML unavailable, 0 devices, or unmatched runtime.
|
|
19
|
+
*
|
|
20
|
+
* **String values match Python EXACTLY** — cross-SDK event portability.
|
|
21
|
+
*
|
|
22
|
+
* **TS deviation**: takes an `Options` object with hook functions. This
|
|
23
|
+
* lets tests inject deterministic stubs without monkeypatching module-
|
|
24
|
+
* level imports (ESM bindings are immutable). The default options use the
|
|
25
|
+
* production nvml-reader + cloud-detect modules.
|
|
26
|
+
*
|
|
27
|
+
* Mirrors python/src/dexcost/gpu_runtime.py.
|
|
28
|
+
*/
|
|
29
|
+
import { getCloudEnv as defaultGetCloudEnv } from "../cloud-detect.js";
|
|
30
|
+
import { getDeviceCount as defaultGetDeviceCount, nvmlAvailable as defaultNvmlAvailable, } from "./nvml-reader.js";
|
|
31
|
+
/** GPU runtime kind discriminator. String values pinned to Python. */
|
|
32
|
+
export const GpuRuntimeKind = {
|
|
33
|
+
Modal: "modal",
|
|
34
|
+
RunPod: "runpod",
|
|
35
|
+
Replicate: "replicate",
|
|
36
|
+
LambdaLabs: "lambda_labs",
|
|
37
|
+
CoreWeave: "coreweave",
|
|
38
|
+
AwsEc2Gpu: "aws_ec2_gpu",
|
|
39
|
+
GcpGceBundled: "gcp_gce_bundled",
|
|
40
|
+
GcpGceN1Attached: "gcp_gce_n1_attached",
|
|
41
|
+
AzureVmGpu: "azure_vm_gpu",
|
|
42
|
+
AzureVmVgpu: "azure_vm_vgpu",
|
|
43
|
+
None: "none",
|
|
44
|
+
};
|
|
45
|
+
// ─── GPU instance-family matchers ───────────────────────────────────────────
|
|
46
|
+
// AWS GPU EC2 families: g4/g4dn/g5/g5g/g6/g6e/p3/p4d/p4de/p5/p5e/p5en
|
|
47
|
+
const AWS_GPU_FAMILY_RE = /^(g4|g4dn|g5|g5g|g6|g6e|p3|p4d|p4de|p5|p5e|p5en)\./i;
|
|
48
|
+
// GCP A2/A3/A4 (bundled GPU) + G2 (L4-bundled)
|
|
49
|
+
const GCP_BUNDLED_GPU_FAMILY_RE = /^(a2|a3|a4|g2)-/i;
|
|
50
|
+
// GCP N1 — attached-accelerator path (Decision #9 — accelerator type not
|
|
51
|
+
// exposed by metadata; rely on NVML fallback).
|
|
52
|
+
const GCP_N1_FAMILY_RE = /^n1-/i;
|
|
53
|
+
// Azure ND/NC series — bundled GPU instances.
|
|
54
|
+
const AZURE_GPU_FAMILY_RE = /^Standard_(ND|NC)/i;
|
|
55
|
+
// Azure NVadsA10 v5 — fractional vGPU (Decision #10). More specific; matched first.
|
|
56
|
+
const AZURE_VGPU_FAMILY_RE = /^Standard_NV\d+ads_A10_v5/i;
|
|
57
|
+
function isAwsGpuInstance(it) {
|
|
58
|
+
return !!it && AWS_GPU_FAMILY_RE.test(it);
|
|
59
|
+
}
|
|
60
|
+
function isGcpBundledGpuInstance(it) {
|
|
61
|
+
return !!it && GCP_BUNDLED_GPU_FAMILY_RE.test(it);
|
|
62
|
+
}
|
|
63
|
+
function isGcpN1Instance(it) {
|
|
64
|
+
return !!it && GCP_N1_FAMILY_RE.test(it);
|
|
65
|
+
}
|
|
66
|
+
function isAzureVgpuInstance(it) {
|
|
67
|
+
return !!it && AZURE_VGPU_FAMILY_RE.test(it);
|
|
68
|
+
}
|
|
69
|
+
function isAzureGpuInstance(it) {
|
|
70
|
+
return !!it && AZURE_GPU_FAMILY_RE.test(it);
|
|
71
|
+
}
|
|
72
|
+
// ─── Resolver ───────────────────────────────────────────────────────────────
|
|
73
|
+
function _isNode() {
|
|
74
|
+
return typeof process !== "undefined" && !!process.versions?.node;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Return the active GPU runtime, or NONE when there's no GPU.
|
|
78
|
+
*
|
|
79
|
+
* The cascade short-circuits on the FIRST positive match. If NVML can't
|
|
80
|
+
* initialize or reports 0 devices, returns NONE regardless of env-var
|
|
81
|
+
* signals — a Modal task on a CPU-only Modal function emits no GPU events.
|
|
82
|
+
*/
|
|
83
|
+
export function resolveGpuRuntime(options) {
|
|
84
|
+
const nvmlAvailable = options?.nvmlAvailable ?? defaultNvmlAvailable;
|
|
85
|
+
const getDeviceCount = options?.getDeviceCount ?? defaultGetDeviceCount;
|
|
86
|
+
const getCloudEnv = options?.getCloudEnv ?? defaultGetCloudEnv;
|
|
87
|
+
// Browser → no GPU.
|
|
88
|
+
if (!_isNode())
|
|
89
|
+
return GpuRuntimeKind.None;
|
|
90
|
+
// NVML must be available AND see ≥1 device for any GPU event emission.
|
|
91
|
+
if (!nvmlAvailable())
|
|
92
|
+
return GpuRuntimeKind.None;
|
|
93
|
+
const count = getDeviceCount() ?? 0;
|
|
94
|
+
if (count <= 0)
|
|
95
|
+
return GpuRuntimeKind.None;
|
|
96
|
+
// 1. Serverless GPU env vars — fastest path, decisive when set.
|
|
97
|
+
const env = process.env;
|
|
98
|
+
if (env.MODAL_TASK_ID || env.MODAL_IMAGE_ID)
|
|
99
|
+
return GpuRuntimeKind.Modal;
|
|
100
|
+
if (env.RUNPOD_POD_ID || env.RUNPOD_POD_HOSTNAME)
|
|
101
|
+
return GpuRuntimeKind.RunPod;
|
|
102
|
+
if (env.REPLICATE_MODEL || env.REPLICATE_PREDICTION_ID) {
|
|
103
|
+
return GpuRuntimeKind.Replicate;
|
|
104
|
+
}
|
|
105
|
+
// 2/3. Cloud-detect IaaS / reserved-GPU.
|
|
106
|
+
const cloud = getCloudEnv();
|
|
107
|
+
const provider = cloud.provider;
|
|
108
|
+
const it = cloud.instanceType ?? null;
|
|
109
|
+
if (provider === "lambda_labs")
|
|
110
|
+
return GpuRuntimeKind.LambdaLabs;
|
|
111
|
+
if (provider === "coreweave")
|
|
112
|
+
return GpuRuntimeKind.CoreWeave;
|
|
113
|
+
if (provider === "aws") {
|
|
114
|
+
if (isAwsGpuInstance(it))
|
|
115
|
+
return GpuRuntimeKind.AwsEc2Gpu;
|
|
116
|
+
}
|
|
117
|
+
if (provider === "gcp") {
|
|
118
|
+
if (isGcpBundledGpuInstance(it))
|
|
119
|
+
return GpuRuntimeKind.GcpGceBundled;
|
|
120
|
+
if (isGcpN1Instance(it))
|
|
121
|
+
return GpuRuntimeKind.GcpGceN1Attached;
|
|
122
|
+
}
|
|
123
|
+
if (provider === "azure") {
|
|
124
|
+
if (isAzureVgpuInstance(it))
|
|
125
|
+
return GpuRuntimeKind.AzureVmVgpu;
|
|
126
|
+
if (isAzureGpuInstance(it))
|
|
127
|
+
return GpuRuntimeKind.AzureVmGpu;
|
|
128
|
+
}
|
|
129
|
+
return GpuRuntimeKind.None;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=gpu-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gpu-runtime.js","sourceRoot":"","sources":["../../src/core/gpu-runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry Heuristic Engine for the dexcost TypeScript SDK.
|
|
3
|
+
*
|
|
4
|
+
* Analyses a sliding window of recent events per task and auto-detects
|
|
5
|
+
* probable retries by identifying LLM calls that follow a failed call
|
|
6
|
+
* (transient error) to the same model within the configured time window.
|
|
7
|
+
*/
|
|
8
|
+
import type { CostEvent } from "./models.js";
|
|
9
|
+
/** Error types that indicate a transient failure likely to be retried. */
|
|
10
|
+
export declare const TRANSIENT_ERRORS: Set<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Base likelihood (0–1) that each transient error type leads to a retry.
|
|
13
|
+
* Used as the starting multiplier before time-decay is applied.
|
|
14
|
+
*/
|
|
15
|
+
export declare const ERROR_LIKELIHOODS: Record<string, number>;
|
|
16
|
+
/** Result returned by `RetryHeuristicEngine.check()`. */
|
|
17
|
+
export interface HeuristicMatch {
|
|
18
|
+
/** Whether the event is likely a retry. */
|
|
19
|
+
isRetry: boolean;
|
|
20
|
+
/** Confidence score from 0.0 to 1.0. */
|
|
21
|
+
confidence: number;
|
|
22
|
+
/** Event ID of the failed predecessor, if matched. */
|
|
23
|
+
matchedEventId: string | undefined;
|
|
24
|
+
/** "heuristic" when a match is found, "" otherwise. */
|
|
25
|
+
reason: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Sliding-window heuristic engine that detects probable retry events.
|
|
29
|
+
*
|
|
30
|
+
* Call `record(event)` for every event you process.
|
|
31
|
+
* Call `check(event)` *before* recording to determine whether the
|
|
32
|
+
* incoming event looks like a retry of a recently failed call.
|
|
33
|
+
*/
|
|
34
|
+
export declare class RetryHeuristicEngine {
|
|
35
|
+
private readonly _windowSeconds;
|
|
36
|
+
private readonly _threshold;
|
|
37
|
+
/** Map from taskId → ordered list of recorded events. */
|
|
38
|
+
private readonly _windows;
|
|
39
|
+
/**
|
|
40
|
+
* @param windowSeconds - How far back (in seconds) to look for a matching
|
|
41
|
+
* failed predecessor. Defaults to 30.
|
|
42
|
+
* @param threshold - Minimum confidence score required to flag an event as
|
|
43
|
+
* a retry. Defaults to 0.8.
|
|
44
|
+
*/
|
|
45
|
+
constructor(windowSeconds?: number, threshold?: number);
|
|
46
|
+
/** The configured sliding-window size in seconds. */
|
|
47
|
+
get windowSeconds(): number;
|
|
48
|
+
/** The minimum confidence threshold for flagging a retry. */
|
|
49
|
+
get threshold(): number;
|
|
50
|
+
/**
|
|
51
|
+
* Record an event into the sliding window for its task.
|
|
52
|
+
*
|
|
53
|
+
* Events older than `windowSeconds` relative to the new event are pruned
|
|
54
|
+
* before appending.
|
|
55
|
+
*/
|
|
56
|
+
record(event: CostEvent): void;
|
|
57
|
+
/**
|
|
58
|
+
* Check whether an incoming event looks like a retry.
|
|
59
|
+
*
|
|
60
|
+
* Walks the recorded events for the same task backwards (most-recent
|
|
61
|
+
* first) looking for an `llm_call` event with the same model that ended
|
|
62
|
+
* with a transient error within the time window.
|
|
63
|
+
*
|
|
64
|
+
* Does NOT modify the window — call `record()` separately.
|
|
65
|
+
*/
|
|
66
|
+
check(event: CostEvent): HeuristicMatch;
|
|
67
|
+
private _getOrCreate;
|
|
68
|
+
/**
|
|
69
|
+
* Remove events from the front of the list that are older than
|
|
70
|
+
* `windowSeconds` relative to `referenceTime`.
|
|
71
|
+
*/
|
|
72
|
+
private _prune;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=heuristics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heuristics.d.ts","sourceRoot":"","sources":["../../src/core/heuristics.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAM7C,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,aAM3B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMpD,CAAC;AAMF,yDAAyD;AACzD,MAAM,WAAW,cAAc;IAC7B,2CAA2C;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;CAChB;AAcD;;;;;;GAMG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,yDAAyD;IACzD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAEhE;;;;;OAKG;gBACS,aAAa,GAAE,MAAW,EAAE,SAAS,GAAE,MAAY;IAW/D,qDAAqD;IACrD,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,6DAA6D;IAC7D,IAAI,SAAS,IAAI,MAAM,CAEtB;IAMD;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAa9B;;;;;;;;OAQG;IACH,KAAK,CAAC,KAAK,EAAE,SAAS,GAAG,cAAc;IAoEvC,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,OAAO,CAAC,MAAM;CAWf"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry Heuristic Engine for the dexcost TypeScript SDK.
|
|
3
|
+
*
|
|
4
|
+
* Analyses a sliding window of recent events per task and auto-detects
|
|
5
|
+
* probable retries by identifying LLM calls that follow a failed call
|
|
6
|
+
* (transient error) to the same model within the configured time window.
|
|
7
|
+
*/
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Constants
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
/** Error types that indicate a transient failure likely to be retried. */
|
|
12
|
+
export const TRANSIENT_ERRORS = new Set([
|
|
13
|
+
"rate_limit",
|
|
14
|
+
"timeout",
|
|
15
|
+
"5xx",
|
|
16
|
+
"server_error",
|
|
17
|
+
"connection_error",
|
|
18
|
+
]);
|
|
19
|
+
/**
|
|
20
|
+
* Base likelihood (0–1) that each transient error type leads to a retry.
|
|
21
|
+
* Used as the starting multiplier before time-decay is applied.
|
|
22
|
+
*/
|
|
23
|
+
export const ERROR_LIKELIHOODS = {
|
|
24
|
+
rate_limit: 1.0,
|
|
25
|
+
timeout: 0.9,
|
|
26
|
+
"5xx": 0.85,
|
|
27
|
+
server_error: 0.85,
|
|
28
|
+
connection_error: 0.8,
|
|
29
|
+
};
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Engine
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
/** Canonical no-match result. */
|
|
34
|
+
const NO_MATCH = {
|
|
35
|
+
isRetry: false,
|
|
36
|
+
confidence: 0,
|
|
37
|
+
matchedEventId: undefined,
|
|
38
|
+
reason: "",
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Sliding-window heuristic engine that detects probable retry events.
|
|
42
|
+
*
|
|
43
|
+
* Call `record(event)` for every event you process.
|
|
44
|
+
* Call `check(event)` *before* recording to determine whether the
|
|
45
|
+
* incoming event looks like a retry of a recently failed call.
|
|
46
|
+
*/
|
|
47
|
+
export class RetryHeuristicEngine {
|
|
48
|
+
_windowSeconds;
|
|
49
|
+
_threshold;
|
|
50
|
+
/** Map from taskId → ordered list of recorded events. */
|
|
51
|
+
_windows = new Map();
|
|
52
|
+
/**
|
|
53
|
+
* @param windowSeconds - How far back (in seconds) to look for a matching
|
|
54
|
+
* failed predecessor. Defaults to 30.
|
|
55
|
+
* @param threshold - Minimum confidence score required to flag an event as
|
|
56
|
+
* a retry. Defaults to 0.8.
|
|
57
|
+
*/
|
|
58
|
+
constructor(windowSeconds = 30, threshold = 0.8) {
|
|
59
|
+
if (windowSeconds <= 0) {
|
|
60
|
+
throw new Error(`windowSeconds must be positive, got ${windowSeconds}`);
|
|
61
|
+
}
|
|
62
|
+
if (threshold <= 0 || threshold > 1) {
|
|
63
|
+
throw new Error(`threshold must be in (0, 1], got ${threshold}`);
|
|
64
|
+
}
|
|
65
|
+
this._windowSeconds = windowSeconds;
|
|
66
|
+
this._threshold = threshold;
|
|
67
|
+
}
|
|
68
|
+
/** The configured sliding-window size in seconds. */
|
|
69
|
+
get windowSeconds() {
|
|
70
|
+
return this._windowSeconds;
|
|
71
|
+
}
|
|
72
|
+
/** The minimum confidence threshold for flagging a retry. */
|
|
73
|
+
get threshold() {
|
|
74
|
+
return this._threshold;
|
|
75
|
+
}
|
|
76
|
+
// -------------------------------------------------------------------------
|
|
77
|
+
// Public API
|
|
78
|
+
// -------------------------------------------------------------------------
|
|
79
|
+
/**
|
|
80
|
+
* Record an event into the sliding window for its task.
|
|
81
|
+
*
|
|
82
|
+
* Events older than `windowSeconds` relative to the new event are pruned
|
|
83
|
+
* before appending.
|
|
84
|
+
*/
|
|
85
|
+
record(event) {
|
|
86
|
+
const list = this._getOrCreate(event.taskId);
|
|
87
|
+
this._prune(list, event.occurredAt);
|
|
88
|
+
if (list.length === 0) {
|
|
89
|
+
this._windows.delete(event.taskId);
|
|
90
|
+
// Re-create the entry for the incoming event
|
|
91
|
+
const fresh = [event];
|
|
92
|
+
this._windows.set(event.taskId, fresh);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
list.push(event);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Check whether an incoming event looks like a retry.
|
|
100
|
+
*
|
|
101
|
+
* Walks the recorded events for the same task backwards (most-recent
|
|
102
|
+
* first) looking for an `llm_call` event with the same model that ended
|
|
103
|
+
* with a transient error within the time window.
|
|
104
|
+
*
|
|
105
|
+
* Does NOT modify the window — call `record()` separately.
|
|
106
|
+
*/
|
|
107
|
+
check(event) {
|
|
108
|
+
const list = this._windows.get(event.taskId);
|
|
109
|
+
if (!list || list.length === 0) {
|
|
110
|
+
return NO_MATCH;
|
|
111
|
+
}
|
|
112
|
+
const eventMs = event.occurredAt.getTime();
|
|
113
|
+
// Walk backwards through the window list (most-recent first)
|
|
114
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
115
|
+
const candidate = list[i];
|
|
116
|
+
// Skip self (same eventId)
|
|
117
|
+
if (candidate.eventId === event.eventId) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
// Only consider llm_call events
|
|
121
|
+
if (candidate.eventType !== "llm_call") {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
// Only consider the same model
|
|
125
|
+
if (candidate.model !== event.model) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
// We found an llm_call for the same model — inspect its outcome
|
|
129
|
+
const errorType = candidate.details["error_type"];
|
|
130
|
+
if (typeof errorType !== "string" || !TRANSIENT_ERRORS.has(errorType)) {
|
|
131
|
+
// Same model succeeded (or had a non-transient error) — not a retry chain
|
|
132
|
+
return NO_MATCH;
|
|
133
|
+
}
|
|
134
|
+
// Transient error found — compute time gap
|
|
135
|
+
const candidateMs = candidate.occurredAt.getTime();
|
|
136
|
+
const gapSeconds = (eventMs - candidateMs) / 1000;
|
|
137
|
+
if (gapSeconds < 0 || gapSeconds > this._windowSeconds) {
|
|
138
|
+
return NO_MATCH;
|
|
139
|
+
}
|
|
140
|
+
const baseLikelihood = ERROR_LIKELIHOODS[errorType] ?? 0.8;
|
|
141
|
+
const confidence = baseLikelihood * Math.max(0, 1 - gapSeconds / this._windowSeconds);
|
|
142
|
+
if (confidence >= this._threshold) {
|
|
143
|
+
return {
|
|
144
|
+
isRetry: true,
|
|
145
|
+
confidence,
|
|
146
|
+
matchedEventId: candidate.eventId,
|
|
147
|
+
reason: "heuristic",
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
// Confidence too low — still not a confirmed retry
|
|
151
|
+
return NO_MATCH;
|
|
152
|
+
}
|
|
153
|
+
// No matching candidate found
|
|
154
|
+
return NO_MATCH;
|
|
155
|
+
}
|
|
156
|
+
// -------------------------------------------------------------------------
|
|
157
|
+
// Private helpers
|
|
158
|
+
// -------------------------------------------------------------------------
|
|
159
|
+
_getOrCreate(taskId) {
|
|
160
|
+
let list = this._windows.get(taskId);
|
|
161
|
+
if (!list) {
|
|
162
|
+
list = [];
|
|
163
|
+
this._windows.set(taskId, list);
|
|
164
|
+
}
|
|
165
|
+
return list;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Remove events from the front of the list that are older than
|
|
169
|
+
* `windowSeconds` relative to `referenceTime`.
|
|
170
|
+
*/
|
|
171
|
+
_prune(list, referenceTime) {
|
|
172
|
+
const cutoffMs = referenceTime.getTime() - this._windowSeconds * 1000;
|
|
173
|
+
let i = 0;
|
|
174
|
+
while (i < list.length && list[i].occurredAt.getTime() < cutoffMs) {
|
|
175
|
+
i++;
|
|
176
|
+
}
|
|
177
|
+
if (i > 0) {
|
|
178
|
+
list.splice(0, i);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=heuristics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heuristics.js","sourceRoot":"","sources":["../../src/core/heuristics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core data models for dexcost TypeScript SDK.
|
|
3
|
+
*
|
|
4
|
+
* These interfaces match the Dexcost Standard Event Schema v1
|
|
5
|
+
* and mirror the Python SDK's Task and Event dataclasses.
|
|
6
|
+
*/
|
|
7
|
+
/** Lifecycle status of a tracked task. */
|
|
8
|
+
export type TaskStatus = "pending" | "success" | "failed";
|
|
9
|
+
/** Discriminator for cost-generating events. */
|
|
10
|
+
export type EventType = "llm_call" | "external_cost" | "compute_cost" | "retry_marker" | "network" | "gpu_cost" | "gpu_utilization_signal";
|
|
11
|
+
/** How trustworthy the reported costUsd value is. */
|
|
12
|
+
export type CostConfidence = "exact" | "computed" | "estimated" | "unknown";
|
|
13
|
+
/** Where the costUsd figure was derived from. */
|
|
14
|
+
/**
|
|
15
|
+
* Sprint 3 Theme F / §4.1.3 (P3): canonical 8-value set aligned
|
|
16
|
+
* across all 4 SDKs. Adding new values requires a coordinated wire-
|
|
17
|
+
* contract change — bump schema_version.
|
|
18
|
+
*/
|
|
19
|
+
export type PricingSource = "litellm" | "tokencost" | "provider_response" | "manual" | "custom" | "rate_registry" | "service_catalog" | "unknown";
|
|
20
|
+
/**
|
|
21
|
+
* A tracked business task (e.g., "resolve support ticket").
|
|
22
|
+
*
|
|
23
|
+
* All downstream events roll up into the aggregated cost and token fields.
|
|
24
|
+
* `metadata` is an open record for caller-defined context.
|
|
25
|
+
*/
|
|
26
|
+
export interface Task {
|
|
27
|
+
taskId: string;
|
|
28
|
+
taskType: string;
|
|
29
|
+
status: TaskStatus;
|
|
30
|
+
startedAt: Date;
|
|
31
|
+
endedAt?: Date;
|
|
32
|
+
metadata: Record<string, unknown>;
|
|
33
|
+
customerId?: string;
|
|
34
|
+
projectId?: string;
|
|
35
|
+
parentTaskId?: string;
|
|
36
|
+
experimentId?: string;
|
|
37
|
+
variant?: string;
|
|
38
|
+
llmCostUsd: number;
|
|
39
|
+
externalCostUsd: number;
|
|
40
|
+
computeCostUsd: number;
|
|
41
|
+
/**
|
|
42
|
+
* v2 cloud-egress cost in USD, computed at task finalize from the
|
|
43
|
+
* accountant's canonical external_bytes_out scalar. Distinct from
|
|
44
|
+
* externalCostUsd (vendor API charges) — see Decision #7.
|
|
45
|
+
*/
|
|
46
|
+
networkCostUsd: number;
|
|
47
|
+
/**
|
|
48
|
+
* v2 GPU cost in USD, computed at task finalize from the GpuAccountant's
|
|
49
|
+
* NVML diff (per-PID SM-time) + cgroup-walk PID filter. Distinct from
|
|
50
|
+
* computeCostUsd (CPU/memory rollup) — GPU billing is a separate dimension.
|
|
51
|
+
* Mirrors the Python SDK's Task.gpu_cost_usd field.
|
|
52
|
+
*/
|
|
53
|
+
gpuCostUsd: number;
|
|
54
|
+
totalCostUsd: number;
|
|
55
|
+
totalInputTokens: number;
|
|
56
|
+
totalOutputTokens: number;
|
|
57
|
+
totalCachedTokens: number;
|
|
58
|
+
retryCount: number;
|
|
59
|
+
retryCostUsd: number;
|
|
60
|
+
failureCount: number;
|
|
61
|
+
networkBytesIn: number;
|
|
62
|
+
networkBytesOut: number;
|
|
63
|
+
networkCallCount: number;
|
|
64
|
+
/**
|
|
65
|
+
* Per-host network breakdown, shape `{ hosts: Array<...> }`. Capped at 20
|
|
66
|
+
* entries plus an `_other` overflow bucket during finalize.
|
|
67
|
+
*/
|
|
68
|
+
networkByHost: Record<string, unknown>;
|
|
69
|
+
schemaVersion: string;
|
|
70
|
+
/**
|
|
71
|
+
* In-memory only. The per-task ComputeAccountant (cgroup start/end
|
|
72
|
+
* snapshots + runtime context). Never serialized — the buffer's
|
|
73
|
+
* upsertTask() writes named columns only, so this field cannot leak to
|
|
74
|
+
* SQLite or the wire payload. Compatible with the Python SDK's
|
|
75
|
+
* Task._compute pattern.
|
|
76
|
+
*
|
|
77
|
+
* Typed as unknown to avoid a circular import from core/compute-
|
|
78
|
+
* accountant.ts (which imports from cgroup-reader / compute-runtime).
|
|
79
|
+
*/
|
|
80
|
+
_compute?: unknown;
|
|
81
|
+
/**
|
|
82
|
+
* In-memory only. The per-task GpuAccountant (NVML start snapshot +
|
|
83
|
+
* cgroup PID scope + per-device handles). Never serialized — same
|
|
84
|
+
* contract as _compute. Mirrors Python's Task._gpu.
|
|
85
|
+
*/
|
|
86
|
+
_gpu?: unknown;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A single cost event (LLM call, external API, compute, retry).
|
|
90
|
+
*
|
|
91
|
+
* Matches the Dexcost Standard Event Schema v1. LLM-specific fields are
|
|
92
|
+
* undefined for non-LLM event types.
|
|
93
|
+
*/
|
|
94
|
+
export interface CostEvent {
|
|
95
|
+
eventId: string;
|
|
96
|
+
taskId: string;
|
|
97
|
+
eventType: EventType;
|
|
98
|
+
occurredAt: Date;
|
|
99
|
+
costUsd: number;
|
|
100
|
+
costConfidence: CostConfidence;
|
|
101
|
+
pricingSource?: PricingSource;
|
|
102
|
+
pricingVersion?: string;
|
|
103
|
+
provider?: string;
|
|
104
|
+
model?: string;
|
|
105
|
+
inputTokens?: number;
|
|
106
|
+
outputTokens?: number;
|
|
107
|
+
cachedTokens?: number;
|
|
108
|
+
latencyMs?: number;
|
|
109
|
+
serviceName?: string;
|
|
110
|
+
isRetry: boolean;
|
|
111
|
+
retryReason?: string;
|
|
112
|
+
retryOf?: string;
|
|
113
|
+
details: Record<string, unknown>;
|
|
114
|
+
schemaVersion: string;
|
|
115
|
+
}
|
|
116
|
+
/** Create a default Task with required fields. */
|
|
117
|
+
export declare function createTask(overrides: Partial<Task> & {
|
|
118
|
+
taskId: string;
|
|
119
|
+
}): Task;
|
|
120
|
+
/** Create a default CostEvent with required fields. */
|
|
121
|
+
export declare function createCostEvent(overrides: Partial<CostEvent> & {
|
|
122
|
+
eventId: string;
|
|
123
|
+
taskId: string;
|
|
124
|
+
}): CostEvent;
|
|
125
|
+
/**
|
|
126
|
+
* Serialise a Task to a JSON-safe dictionary matching the Standard Event Schema v1.
|
|
127
|
+
* Costs are serialised as strings to preserve precision.
|
|
128
|
+
*/
|
|
129
|
+
export declare function taskToDict(task: Task): Record<string, unknown>;
|
|
130
|
+
/**
|
|
131
|
+
* Serialise a CostEvent to a JSON-safe dictionary matching the Standard Event Schema v1.
|
|
132
|
+
* Costs are serialised as strings to preserve precision.
|
|
133
|
+
*/
|
|
134
|
+
export declare function eventToDict(event: CostEvent): Record<string, unknown>;
|
|
135
|
+
/**
|
|
136
|
+
* Deserialise a Task from a JSON-safe dictionary (inverse of `taskToDict`).
|
|
137
|
+
*
|
|
138
|
+
* Mirrors the Python SDK's `Task.from_dict`. Throws an Error when required
|
|
139
|
+
* fields are missing or malformed.
|
|
140
|
+
*/
|
|
141
|
+
export declare function taskFromDict(data: Record<string, unknown>): Task;
|
|
142
|
+
/**
|
|
143
|
+
* Deserialise a CostEvent from a JSON-safe dictionary (inverse of `eventToDict`).
|
|
144
|
+
*
|
|
145
|
+
* Mirrors the Python SDK's `Event.from_dict`. Throws an Error when required
|
|
146
|
+
* fields are missing or malformed.
|
|
147
|
+
*/
|
|
148
|
+
export declare function eventFromDict(data: Record<string, unknown>): CostEvent;
|
|
149
|
+
//# sourceMappingURL=models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/core/models.ts"],"names":[],"mappings":"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"}
|