@spendgraph/workflows 0.3.2 → 0.3.3

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
@@ -115,6 +115,7 @@ result.usage.inputTokens; // the model side
115
115
  result.usage.byModel["claude-sonnet-4-6"];
116
116
 
117
117
  result.usage.tools.calls; // the tool side
118
+ result.usage.tools.failed; // and what did not come back
118
119
  result.usage.tools.costMicros; // where a tool priced itself
119
120
  result.usage.tools.byTool.web_search; // tokens, keyed by the tool that ran
120
121
  ```
@@ -4,12 +4,16 @@ import type { SubQuestionTool } from "../producers/decompose/index.js";
4
4
  export interface ToolSpend {
5
5
  /** Tool calls that ran, whether or not the tool priced itself. */
6
6
  calls: number;
7
+ /** Calls that failed or were skipped. Counted, because a summary that
8
+ * reported only what worked would read as a healthy run. */
9
+ failed: number;
7
10
  /** Summed where a tool priced itself. Undefined where none did. */
8
11
  costMicros?: number;
9
12
  byTool: Record<string, ToolUsage>;
10
13
  }
11
14
  export interface ToolUsage {
12
15
  calls: number;
16
+ failed: number;
13
17
  model?: string;
14
18
  inputTokens: number;
15
19
  outputTokens: number;
@@ -25,7 +29,7 @@ export declare const NO_TOOL_SPEND: ToolSpend;
25
29
  * reports Perplexity's four token counts, `deep_recall` reports micro-USD. Both
26
30
  * are read where present and nothing is invented where absent.
27
31
  */
28
- export declare function readToolUsage(result: unknown): Omit<ToolUsage, "calls"> | null;
32
+ export declare function readToolUsage(result: unknown): Omit<ToolUsage, "calls" | "failed"> | null;
29
33
  /**
30
34
  * Every tool call in one execution, summed under the tool that actually ran.
31
35
  *
@@ -1,4 +1,4 @@
1
- export const NO_TOOL_SPEND = { calls: 0, byTool: {} };
1
+ export const NO_TOOL_SPEND = { calls: 0, failed: 0, byTool: {} };
2
2
  const numberAt = (source, field) => {
3
3
  const value = source[field];
4
4
  return typeof value === "number" && Number.isFinite(value) ? value : 0;
@@ -24,23 +24,32 @@ export function readToolUsage(result) {
24
24
  export function toolSpendOf(answers, wiring = {}) {
25
25
  const byTool = {};
26
26
  let calls = 0;
27
+ let failed = 0;
27
28
  let costMicros;
29
+ const blank = () => ({
30
+ calls: 0,
31
+ failed: 0,
32
+ inputTokens: 0,
33
+ outputTokens: 0,
34
+ citationTokens: 0,
35
+ reasoningTokens: 0,
36
+ });
28
37
  for (const answer of answers) {
38
+ const named = wiring[answer.tool]?.name ?? answer.tool;
29
39
  if (answer.status === "answered")
30
40
  calls++;
41
+ else {
42
+ failed++;
43
+ byTool[named] = { ...(byTool[named] ?? blank()), failed: (byTool[named]?.failed ?? 0) + 1 };
44
+ continue;
45
+ }
31
46
  const one = readToolUsage(answer.result);
32
47
  if (!one)
33
48
  continue;
34
- const named = wiring[answer.tool]?.name ?? answer.tool;
35
- const prior = byTool[named] ?? {
36
- calls: 0,
37
- inputTokens: 0,
38
- outputTokens: 0,
39
- citationTokens: 0,
40
- reasoningTokens: 0,
41
- };
49
+ const prior = byTool[named] ?? blank();
42
50
  const merged = {
43
51
  calls: prior.calls + 1,
52
+ failed: prior.failed,
44
53
  inputTokens: prior.inputTokens + one.inputTokens,
45
54
  outputTokens: prior.outputTokens + one.outputTokens,
46
55
  citationTokens: prior.citationTokens + one.citationTokens,
@@ -53,7 +62,7 @@ export function toolSpendOf(answers, wiring = {}) {
53
62
  }
54
63
  byTool[named] = merged;
55
64
  }
56
- return { calls, byTool, ...(costMicros !== undefined ? { costMicros } : {}) };
65
+ return { calls, failed, byTool, ...(costMicros !== undefined ? { costMicros } : {}) };
57
66
  }
58
67
  export function addToolSpend(a, b) {
59
68
  const byTool = { ...a.byTool };
@@ -62,6 +71,7 @@ export function addToolSpend(a, b) {
62
71
  byTool[tool] = prior
63
72
  ? {
64
73
  calls: prior.calls + one.calls,
74
+ failed: prior.failed + one.failed,
65
75
  inputTokens: prior.inputTokens + one.inputTokens,
66
76
  outputTokens: prior.outputTokens + one.outputTokens,
67
77
  citationTokens: prior.citationTokens + one.citationTokens,
@@ -76,7 +86,12 @@ export function addToolSpend(a, b) {
76
86
  const costMicros = a.costMicros !== undefined || b.costMicros !== undefined
77
87
  ? (a.costMicros ?? 0) + (b.costMicros ?? 0)
78
88
  : undefined;
79
- return { calls: a.calls + b.calls, byTool, ...(costMicros !== undefined ? { costMicros } : {}) };
89
+ return {
90
+ calls: a.calls + b.calls,
91
+ failed: a.failed + b.failed,
92
+ byTool,
93
+ ...(costMicros !== undefined ? { costMicros } : {}),
94
+ };
80
95
  }
81
96
  export function recorded(execution) {
82
97
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spendgraph/workflows",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Ready-made workflows assembled from the spendgraph packages.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -33,10 +33,10 @@
33
33
  "README.md"
34
34
  ],
35
35
  "dependencies": {
36
- "@spendgraph/harness": "^0.3.2",
37
- "@spendgraph/llms": "^0.3.2",
38
- "@spendgraph/prompt": "^0.3.2",
39
- "@spendgraph/tools": "^0.3.2"
36
+ "@spendgraph/harness": "^0.3.3",
37
+ "@spendgraph/llms": "^0.3.3",
38
+ "@spendgraph/prompt": "^0.3.3",
39
+ "@spendgraph/tools": "^0.3.3"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "tsc -p tsconfig.json --emitDeclarationOnly && tsc -p tsconfig.json --declaration false --removeComments",
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "devDependencies": {
49
49
  "@locusgraph/client": "^0.8.1",
50
- "@spendgraph/evals": "^0.3.2",
50
+ "@spendgraph/evals": "^0.3.3",
51
51
  "typescript": "^5"
52
52
  },
53
53
  "engines": {