@axlsdk/studio 0.18.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -107,7 +107,7 @@ Waterfall visualization of execution traces. Filter by type, agent, or tool; see
107
107
 
108
108
  ### Cost Dashboard
109
109
 
110
- Track spending across agents, models, workflows, and embedders with time-window filtering (24h/7d/30d/all). Sortable breakdown tables, a **Retry Overhead** section that decomposes cost by `retryReason` when retries happen, and a **Memory (Embedder)** section bucketed by embedder model. Sub-cent values use tiered precision so embedder costs don't collapse to `$0.0000`.
110
+ Track spending across agents, models, workflows, and embedders with time-window filtering (24h/7d/30d/all). Sortable breakdown tables, a **Retry Overhead** section that decomposes cost by `retryReason` when retries happen, and a **Memory (Embedder)** section bucketed by embedder model. Sub-cent values use tiered precision so embedder costs don't collapse to `$0.0000`. Calls to unpriced models (a pricing-table miss, or a provider that reports no per-call cost) render as `≥ $X` with an "N unpriced calls" note, so the total reads as an honest lower bound rather than a misleading exact figure.
111
111
 
112
112
  <p align="center">
113
113
  <img src="../../docs/assets/studio-cost-dashboard.gif" alt="Axl Studio cost dashboard — spend by agent, model, and workflow with time-window filtering" width="840">
@@ -775,7 +775,7 @@ var EvalAggregator = class {
775
775
  };
776
776
 
777
777
  // src/server/aggregates/reducers.ts
778
- import { eventCostContribution } from "@axlsdk/axl";
778
+ import { eventCostContribution, isUnpricedLeaf } from "@axlsdk/axl";
779
779
  var finite = (v) => Number.isFinite(v) ? v : 0;
780
780
  function emptyRetry() {
781
781
  return {
@@ -793,6 +793,7 @@ function emptyRetry() {
793
793
  function emptyCostData() {
794
794
  return {
795
795
  totalCost: 0,
796
+ unpricedCalls: 0,
796
797
  totalTokens: { input: 0, output: 0, reasoning: 0 },
797
798
  byAgent: {},
798
799
  byModel: {},
@@ -805,7 +806,7 @@ function reduceCost(acc, event) {
805
806
  const isWorkflowStart = event.type === "workflow_start";
806
807
  if (isWorkflowStart && event.workflow) {
807
808
  const byWorkflow2 = { ...acc.byWorkflow };
808
- const prev = byWorkflow2[event.workflow] ?? { cost: 0, executions: 0 };
809
+ const prev = byWorkflow2[event.workflow] ?? { cost: 0, executions: 0, unpricedCalls: 0 };
809
810
  byWorkflow2[event.workflow] = { ...prev, executions: prev.executions + 1 };
810
811
  return { ...acc, byWorkflow: byWorkflow2 };
811
812
  }
@@ -813,6 +814,7 @@ function reduceCost(acc, event) {
813
814
  const cost = eventCostContribution(event);
814
815
  if (event.type === "ask_end") return acc;
815
816
  const tokens = event.tokens ?? {};
817
+ const unpricedLeaf = isUnpricedLeaf(event);
816
818
  const totalTokens = event.type === "agent_call_end" ? {
817
819
  input: acc.totalTokens.input + finite(tokens.input),
818
820
  output: acc.totalTokens.output + finite(tokens.output),
@@ -820,15 +822,25 @@ function reduceCost(acc, event) {
820
822
  } : acc.totalTokens;
821
823
  const byAgent = { ...acc.byAgent };
822
824
  if (event.agent) {
823
- const prev = byAgent[event.agent] ?? { cost: 0, calls: 0 };
824
- byAgent[event.agent] = { cost: prev.cost + cost, calls: prev.calls + 1 };
825
+ const prev = byAgent[event.agent] ?? { cost: 0, calls: 0, unpricedCalls: 0 };
826
+ byAgent[event.agent] = {
827
+ cost: prev.cost + cost,
828
+ calls: prev.calls + 1,
829
+ unpricedCalls: prev.unpricedCalls + (unpricedLeaf ? 1 : 0)
830
+ };
825
831
  }
826
832
  const byModel = { ...acc.byModel };
827
833
  if (event.model) {
828
- const prev = byModel[event.model] ?? { cost: 0, calls: 0, tokens: { input: 0, output: 0 } };
834
+ const prev = byModel[event.model] ?? {
835
+ cost: 0,
836
+ calls: 0,
837
+ unpricedCalls: 0,
838
+ tokens: { input: 0, output: 0 }
839
+ };
829
840
  byModel[event.model] = {
830
841
  cost: prev.cost + cost,
831
842
  calls: prev.calls + 1,
843
+ unpricedCalls: prev.unpricedCalls + (unpricedLeaf ? 1 : 0),
832
844
  tokens: {
833
845
  input: prev.tokens.input + finite(tokens.input),
834
846
  output: prev.tokens.output + finite(tokens.output)
@@ -837,10 +849,11 @@ function reduceCost(acc, event) {
837
849
  }
838
850
  const byWorkflow = { ...acc.byWorkflow };
839
851
  if (event.workflow) {
840
- const prev = byWorkflow[event.workflow] ?? { cost: 0, executions: 0 };
852
+ const prev = byWorkflow[event.workflow] ?? { cost: 0, executions: 0, unpricedCalls: 0 };
841
853
  byWorkflow[event.workflow] = {
842
854
  cost: prev.cost + cost,
843
- executions: prev.executions + (isWorkflowStart ? 1 : 0)
855
+ executions: prev.executions + (isWorkflowStart ? 1 : 0),
856
+ unpricedCalls: prev.unpricedCalls + (unpricedLeaf ? 1 : 0)
844
857
  };
845
858
  }
846
859
  let retry = acc.retry;
@@ -871,15 +884,17 @@ function reduceCost(acc, event) {
871
884
  byEmbedder = { ...acc.byEmbedder };
872
885
  const modelKey = usage?.model ?? "unknown";
873
886
  const embedTokens = typeof usage?.tokens === "number" ? finite(usage.tokens) : 0;
874
- const prev = byEmbedder[modelKey] ?? { cost: 0, calls: 0, tokens: 0 };
887
+ const prev = byEmbedder[modelKey] ?? { cost: 0, calls: 0, unpricedCalls: 0, tokens: 0 };
875
888
  byEmbedder[modelKey] = {
876
889
  cost: prev.cost + cost,
877
890
  calls: prev.calls + 1,
891
+ unpricedCalls: prev.unpricedCalls + (unpricedLeaf ? 1 : 0),
878
892
  tokens: prev.tokens + embedTokens
879
893
  };
880
894
  }
881
895
  return {
882
896
  totalCost: acc.totalCost + cost,
897
+ unpricedCalls: acc.unpricedCalls + (unpricedLeaf ? 1 : 0),
883
898
  totalTokens,
884
899
  byAgent,
885
900
  byModel,
@@ -16180,4 +16195,4 @@ export {
16180
16195
  EvalAggregator,
16181
16196
  createServer
16182
16197
  };
16183
- //# sourceMappingURL=chunk-RLG3DDQZ.js.map
16198
+ //# sourceMappingURL=chunk-S6HQOGOQ.js.map