@nodetool-ai/execution 0.8.1

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 (231) hide show
  1. package/README.md +129 -0
  2. package/dist/.nodetool-build-stamp +1 -0
  3. package/dist/app-debug/app-spec.d.ts +94 -0
  4. package/dist/app-debug/app-spec.d.ts.map +1 -0
  5. package/dist/app-debug/app-spec.js +710 -0
  6. package/dist/app-debug/app-spec.js.map +1 -0
  7. package/dist/app-debug/application-target.d.ts +53 -0
  8. package/dist/app-debug/application-target.d.ts.map +1 -0
  9. package/dist/app-debug/application-target.js +126 -0
  10. package/dist/app-debug/application-target.js.map +1 -0
  11. package/dist/app-debug/bundle-target.d.ts +21 -0
  12. package/dist/app-debug/bundle-target.d.ts.map +1 -0
  13. package/dist/app-debug/bundle-target.js +51 -0
  14. package/dist/app-debug/bundle-target.js.map +1 -0
  15. package/dist/app-debug/graph-shape.d.ts +14 -0
  16. package/dist/app-debug/graph-shape.d.ts.map +1 -0
  17. package/dist/app-debug/graph-shape.js +23 -0
  18. package/dist/app-debug/graph-shape.js.map +1 -0
  19. package/dist/app-debug/index.d.ts +26 -0
  20. package/dist/app-debug/index.d.ts.map +1 -0
  21. package/dist/app-debug/index.js +19 -0
  22. package/dist/app-debug/index.js.map +1 -0
  23. package/dist/app-debug/markdown.d.ts +6 -0
  24. package/dist/app-debug/markdown.d.ts.map +1 -0
  25. package/dist/app-debug/markdown.js +133 -0
  26. package/dist/app-debug/markdown.js.map +1 -0
  27. package/dist/app-debug/runtime.d.ts +267 -0
  28. package/dist/app-debug/runtime.d.ts.map +1 -0
  29. package/dist/app-debug/runtime.js +633 -0
  30. package/dist/app-debug/runtime.js.map +1 -0
  31. package/dist/app-debug/script-operation.d.ts +58 -0
  32. package/dist/app-debug/script-operation.d.ts.map +1 -0
  33. package/dist/app-debug/script-operation.js +44 -0
  34. package/dist/app-debug/script-operation.js.map +1 -0
  35. package/dist/app-debug/simulate.d.ts +85 -0
  36. package/dist/app-debug/simulate.d.ts.map +1 -0
  37. package/dist/app-debug/simulate.js +991 -0
  38. package/dist/app-debug/simulate.js.map +1 -0
  39. package/dist/app-debug/summarize.d.ts +64 -0
  40. package/dist/app-debug/summarize.d.ts.map +1 -0
  41. package/dist/app-debug/summarize.js +65 -0
  42. package/dist/app-debug/summarize.js.map +1 -0
  43. package/dist/app-debug/types.d.ts +343 -0
  44. package/dist/app-debug/types.d.ts.map +1 -0
  45. package/dist/app-debug/types.js +2 -0
  46. package/dist/app-debug/types.js.map +1 -0
  47. package/dist/cost-ledger.d.ts +147 -0
  48. package/dist/cost-ledger.d.ts.map +1 -0
  49. package/dist/cost-ledger.js +288 -0
  50. package/dist/cost-ledger.js.map +1 -0
  51. package/dist/debug/collector.d.ts +28 -0
  52. package/dist/debug/collector.d.ts.map +1 -0
  53. package/dist/debug/collector.js +284 -0
  54. package/dist/debug/collector.js.map +1 -0
  55. package/dist/debug/index.d.ts +15 -0
  56. package/dist/debug/index.d.ts.map +1 -0
  57. package/dist/debug/index.js +16 -0
  58. package/dist/debug/index.js.map +1 -0
  59. package/dist/debug/types.d.ts +179 -0
  60. package/dist/debug/types.d.ts.map +1 -0
  61. package/dist/debug/types.js +11 -0
  62. package/dist/debug/types.js.map +1 -0
  63. package/dist/debug/verdict.d.ts +27 -0
  64. package/dist/debug/verdict.d.ts.map +1 -0
  65. package/dist/debug/verdict.js +51 -0
  66. package/dist/debug/verdict.js.map +1 -0
  67. package/dist/executor-resolver.d.ts +13 -0
  68. package/dist/executor-resolver.d.ts.map +1 -0
  69. package/dist/executor-resolver.js +13 -0
  70. package/dist/executor-resolver.js.map +1 -0
  71. package/dist/fal-output-decoder.d.ts +36 -0
  72. package/dist/fal-output-decoder.d.ts.map +1 -0
  73. package/dist/fal-output-decoder.js +129 -0
  74. package/dist/fal-output-decoder.js.map +1 -0
  75. package/dist/generation-lifecycle.d.ts +54 -0
  76. package/dist/generation-lifecycle.d.ts.map +1 -0
  77. package/dist/generation-lifecycle.js +431 -0
  78. package/dist/generation-lifecycle.js.map +1 -0
  79. package/dist/generation-recovery-worker.d.ts +100 -0
  80. package/dist/generation-recovery-worker.d.ts.map +1 -0
  81. package/dist/generation-recovery-worker.js +995 -0
  82. package/dist/generation-recovery-worker.js.map +1 -0
  83. package/dist/generation-tracker.d.ts +83 -0
  84. package/dist/generation-tracker.d.ts.map +1 -0
  85. package/dist/generation-tracker.js +436 -0
  86. package/dist/generation-tracker.js.map +1 -0
  87. package/dist/index.d.ts +28 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +21 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/js-script-debug/index.d.ts +13 -0
  92. package/dist/js-script-debug/index.d.ts.map +1 -0
  93. package/dist/js-script-debug/index.js +12 -0
  94. package/dist/js-script-debug/index.js.map +1 -0
  95. package/dist/js-script-debug/markdown.d.ts +6 -0
  96. package/dist/js-script-debug/markdown.d.ts.map +1 -0
  97. package/dist/js-script-debug/markdown.js +62 -0
  98. package/dist/js-script-debug/markdown.js.map +1 -0
  99. package/dist/js-script-debug/outputs.d.ts +20 -0
  100. package/dist/js-script-debug/outputs.d.ts.map +1 -0
  101. package/dist/js-script-debug/outputs.js +30 -0
  102. package/dist/js-script-debug/outputs.js.map +1 -0
  103. package/dist/js-script-debug/report.d.ts +15 -0
  104. package/dist/js-script-debug/report.d.ts.map +1 -0
  105. package/dist/js-script-debug/report.js +90 -0
  106. package/dist/js-script-debug/report.js.map +1 -0
  107. package/dist/js-script-debug/types.d.ts +63 -0
  108. package/dist/js-script-debug/types.d.ts.map +1 -0
  109. package/dist/js-script-debug/types.js +10 -0
  110. package/dist/js-script-debug/types.js.map +1 -0
  111. package/dist/js-script-debug/validate.d.ts +38 -0
  112. package/dist/js-script-debug/validate.d.ts.map +1 -0
  113. package/dist/js-script-debug/validate.js +137 -0
  114. package/dist/js-script-debug/validate.js.map +1 -0
  115. package/dist/message-stream.d.ts +33 -0
  116. package/dist/message-stream.d.ts.map +1 -0
  117. package/dist/message-stream.js +58 -0
  118. package/dist/message-stream.js.map +1 -0
  119. package/dist/normalize-graph.d.ts +13 -0
  120. package/dist/normalize-graph.d.ts.map +1 -0
  121. package/dist/normalize-graph.js +63 -0
  122. package/dist/normalize-graph.js.map +1 -0
  123. package/dist/output-names.d.ts +13 -0
  124. package/dist/output-names.d.ts.map +1 -0
  125. package/dist/output-names.js +13 -0
  126. package/dist/output-names.js.map +1 -0
  127. package/dist/predicates.d.ts +6 -0
  128. package/dist/predicates.d.ts.map +1 -0
  129. package/dist/predicates.js +6 -0
  130. package/dist/predicates.js.map +1 -0
  131. package/dist/preflight.d.ts +87 -0
  132. package/dist/preflight.d.ts.map +1 -0
  133. package/dist/preflight.js +139 -0
  134. package/dist/preflight.js.map +1 -0
  135. package/dist/provider-secret-key.d.ts +3 -0
  136. package/dist/provider-secret-key.d.ts.map +1 -0
  137. package/dist/provider-secret-key.js +7 -0
  138. package/dist/provider-secret-key.js.map +1 -0
  139. package/dist/service/app-debug-service.d.ts +78 -0
  140. package/dist/service/app-debug-service.d.ts.map +1 -0
  141. package/dist/service/app-debug-service.js +201 -0
  142. package/dist/service/app-debug-service.js.map +1 -0
  143. package/dist/service/app-run-server.d.ts +28 -0
  144. package/dist/service/app-run-server.d.ts.map +1 -0
  145. package/dist/service/app-run-server.js +104 -0
  146. package/dist/service/app-run-server.js.map +1 -0
  147. package/dist/service/debug-sessions.d.ts +158 -0
  148. package/dist/service/debug-sessions.d.ts.map +1 -0
  149. package/dist/service/debug-sessions.js +358 -0
  150. package/dist/service/debug-sessions.js.map +1 -0
  151. package/dist/service/index.d.ts +22 -0
  152. package/dist/service/index.d.ts.map +1 -0
  153. package/dist/service/index.js +17 -0
  154. package/dist/service/index.js.map +1 -0
  155. package/dist/service/job-progress.d.ts +40 -0
  156. package/dist/service/job-progress.d.ts.map +1 -0
  157. package/dist/service/job-progress.js +53 -0
  158. package/dist/service/job-progress.js.map +1 -0
  159. package/dist/service/workflow-run.d.ts +279 -0
  160. package/dist/service/workflow-run.d.ts.map +1 -0
  161. package/dist/service/workflow-run.js +598 -0
  162. package/dist/service/workflow-run.js.map +1 -0
  163. package/dist/service/workflow-workspace.d.ts +89 -0
  164. package/dist/service/workflow-workspace.d.ts.map +1 -0
  165. package/dist/service/workflow-workspace.js +160 -0
  166. package/dist/service/workflow-workspace.js.map +1 -0
  167. package/dist/session.d.ts +62 -0
  168. package/dist/session.d.ts.map +1 -0
  169. package/dist/session.js +353 -0
  170. package/dist/session.js.map +1 -0
  171. package/dist/sketch-debug/index.d.ts +11 -0
  172. package/dist/sketch-debug/index.d.ts.map +1 -0
  173. package/dist/sketch-debug/index.js +10 -0
  174. package/dist/sketch-debug/index.js.map +1 -0
  175. package/dist/sketch-debug/markdown.d.ts +6 -0
  176. package/dist/sketch-debug/markdown.d.ts.map +1 -0
  177. package/dist/sketch-debug/markdown.js +93 -0
  178. package/dist/sketch-debug/markdown.js.map +1 -0
  179. package/dist/sketch-debug/report.d.ts +15 -0
  180. package/dist/sketch-debug/report.d.ts.map +1 -0
  181. package/dist/sketch-debug/report.js +98 -0
  182. package/dist/sketch-debug/report.js.map +1 -0
  183. package/dist/sketch-debug/types.d.ts +62 -0
  184. package/dist/sketch-debug/types.d.ts.map +1 -0
  185. package/dist/sketch-debug/types.js +10 -0
  186. package/dist/sketch-debug/types.js.map +1 -0
  187. package/dist/sketch-debug/validate.d.ts +14 -0
  188. package/dist/sketch-debug/validate.d.ts.map +1 -0
  189. package/dist/sketch-debug/validate.js +478 -0
  190. package/dist/sketch-debug/validate.js.map +1 -0
  191. package/dist/supervisor.d.ts +45 -0
  192. package/dist/supervisor.d.ts.map +1 -0
  193. package/dist/supervisor.js +97 -0
  194. package/dist/supervisor.js.map +1 -0
  195. package/dist/timeline-debug/index.d.ts +11 -0
  196. package/dist/timeline-debug/index.d.ts.map +1 -0
  197. package/dist/timeline-debug/index.js +10 -0
  198. package/dist/timeline-debug/index.js.map +1 -0
  199. package/dist/timeline-debug/legibility.d.ts +23 -0
  200. package/dist/timeline-debug/legibility.d.ts.map +1 -0
  201. package/dist/timeline-debug/legibility.js +240 -0
  202. package/dist/timeline-debug/legibility.js.map +1 -0
  203. package/dist/timeline-debug/markdown.d.ts +6 -0
  204. package/dist/timeline-debug/markdown.d.ts.map +1 -0
  205. package/dist/timeline-debug/markdown.js +103 -0
  206. package/dist/timeline-debug/markdown.js.map +1 -0
  207. package/dist/timeline-debug/motion.d.ts +20 -0
  208. package/dist/timeline-debug/motion.d.ts.map +1 -0
  209. package/dist/timeline-debug/motion.js +362 -0
  210. package/dist/timeline-debug/motion.js.map +1 -0
  211. package/dist/timeline-debug/report.d.ts +16 -0
  212. package/dist/timeline-debug/report.d.ts.map +1 -0
  213. package/dist/timeline-debug/report.js +100 -0
  214. package/dist/timeline-debug/report.js.map +1 -0
  215. package/dist/timeline-debug/showcase.d.ts +7 -0
  216. package/dist/timeline-debug/showcase.d.ts.map +1 -0
  217. package/dist/timeline-debug/showcase.js +347 -0
  218. package/dist/timeline-debug/showcase.js.map +1 -0
  219. package/dist/timeline-debug/types.d.ts +64 -0
  220. package/dist/timeline-debug/types.d.ts.map +1 -0
  221. package/dist/timeline-debug/types.js +10 -0
  222. package/dist/timeline-debug/types.js.map +1 -0
  223. package/dist/timeline-debug/validate.d.ts +24 -0
  224. package/dist/timeline-debug/validate.d.ts.map +1 -0
  225. package/dist/timeline-debug/validate.js +1432 -0
  226. package/dist/timeline-debug/validate.js.map +1 -0
  227. package/dist/types.d.ts +211 -0
  228. package/dist/types.d.ts.map +1 -0
  229. package/dist/types.js +2 -0
  230. package/dist/types.js.map +1 -0
  231. package/package.json +103 -0
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Provider-spend ledger — the write half of `nodetool costs`.
3
+ *
4
+ * `BaseProvider` accounts for chat and stream in tokens, and the host writes
5
+ * that row. Image, video and audio generation had no equivalent: the money went
6
+ * out and nothing reached the `predictions` table, so a render session read as
7
+ * free.
8
+ *
9
+ * Two kinds of generation reach a ledger row here:
10
+ *
11
+ * - A node that knows its own charge calls `context.setProviderCost()`, which
12
+ * rides out on the completed `node_update` as `provider_cost`. FAL and kie do
13
+ * this — the number comes from the provider, so it wins. When the provider
14
+ * also exposes a request-keyed billing API, the estimate is reconciled to the
15
+ * actual charge in the background.
16
+ * - Everything else goes through `ProcessingContext.runProviderPrediction` (and
17
+ * its streaming/encoded siblings), which emits a `prediction` message
18
+ * carrying provider, model, capability and the job's parameters. That is
19
+ * priced here against `@nodetool-ai/model-pricing` — the same catalog the
20
+ * editor's cost preview and the pre-run budget gate read.
21
+ *
22
+ * A model in no catalog still gets a row, with `cost` left null rather than set
23
+ * to zero: the call is visible in `nodetool costs`, and a null is countable as
24
+ * unpriced instead of summing as free. The units behind a price are recorded
25
+ * next to it (`billing_unit`, `quantity`, `unit_price`, `currency`, plus the
26
+ * catalog's own breakdown in `metadata`) so a per-second or per-megapixel row
27
+ * is auditable even when the estimate is imperfect.
28
+ */
29
+ import { Prediction } from "@nodetool-ai/models";
30
+ import type { ProcessingMessage, ProviderCost } from "@nodetool-ai/protocol";
31
+ import { type GenerationTrackerState } from "./generation-tracker.js";
32
+ /** Whether a capability is billed per unit of output (and so belongs here). */
33
+ export declare function isUnitBilledCapability(capability: string | null | undefined): boolean;
34
+ /** One generation to price and record. */
35
+ export interface GenerationSpend {
36
+ userId: string;
37
+ provider: string;
38
+ model: string;
39
+ capability?: string | null;
40
+ /** Outputs produced — the multiplier on the catalog's per-run price. */
41
+ quantity?: number;
42
+ /** What the job stated, in provider parameter spelling (`duration_seconds`, `resolution`, …). */
43
+ params?: Record<string, unknown> | null;
44
+ nodeId?: string;
45
+ nodeType?: string;
46
+ workflowId?: string | null;
47
+ /** The project this run belongs to, when it has one. */
48
+ projectId?: string | null;
49
+ /** The project document this run is producing, when it names one. */
50
+ documentId?: string | null;
51
+ durationMs?: number | null;
52
+ }
53
+ /** What the catalog answered for a generation, or `null` when it knows no price. */
54
+ export interface PricedGeneration {
55
+ cost: number;
56
+ unit_price: number;
57
+ quantity: number;
58
+ billing_unit: string;
59
+ currency: string;
60
+ /** The catalog's own reasoning, e.g. "5 s × $0.205/s at 720p". */
61
+ breakdown?: string;
62
+ /** What the catalog filled in because the job did not state it. */
63
+ assumptions?: string[];
64
+ }
65
+ /**
66
+ * Price a generation against the model catalogs. Returns `null` when no catalog
67
+ * carries the model, or when the catalog declines to extrapolate — a refusal is
68
+ * an answer, and inventing a number would be worse than recording none.
69
+ */
70
+ export declare function priceGeneration(spend: GenerationSpend): PricedGeneration | null;
71
+ /**
72
+ * Write one generation to the ledger. Best-effort: a host with no database
73
+ * (a hermetic run, an eval) must not fail because accounting could not be
74
+ * persisted — the generation already happened and was already billed.
75
+ */
76
+ export declare function recordGenerationSpend(spend: GenerationSpend): Promise<Prediction | null>;
77
+ /** A charge a node reported for itself, as it rides out on `node_update`. */
78
+ export interface NodeCostSpend {
79
+ userId: string;
80
+ cost: ProviderCost;
81
+ nodeId: string;
82
+ nodeType: string;
83
+ workflowId: string | null;
84
+ /** The project this run belongs to, when it has one. */
85
+ projectId?: string | null;
86
+ /** The project document this run is producing, when it names one. */
87
+ documentId?: string | null;
88
+ /** Resolves the provider API key used to look the actual charge up, when one exists. */
89
+ resolveSecret?: (key: string) => Promise<string | null | undefined>;
90
+ }
91
+ /**
92
+ * Write a node-reported provider charge to the ledger, then refine it into the
93
+ * provider's actual billed amount in the background when that provider
94
+ * registered a reconciler. Best-effort throughout.
95
+ */
96
+ export declare function recordNodeProviderCost(spend: NodeCostSpend): Promise<Prediction | null>;
97
+ export interface RunCostLedgerOptions {
98
+ userId: string;
99
+ workflowId: string | null;
100
+ /**
101
+ * The project this run belongs to. Left unset outside a project, and the row
102
+ * then carries a null rather than being attributed to the loose bucket — a
103
+ * project's total counts only what named it.
104
+ */
105
+ projectId?: string | null;
106
+ /** The project document this run is producing, when the host names one. */
107
+ documentId?: string | null;
108
+ /** Node type for a node id, so a row names the node that spent the money. */
109
+ nodeType?: (nodeId: string) => string;
110
+ resolveSecret?: (key: string) => Promise<string | null | undefined>;
111
+ }
112
+ /**
113
+ * A `nodeType` lookup built once per run. Scanning the node list per message
114
+ * would be O(nodes × messages), which a 20 000-node graph feels.
115
+ */
116
+ export declare function nodeTypeLookup(nodes: ReadonlyArray<{
117
+ id: string;
118
+ type: string;
119
+ }>): (nodeId: string) => string;
120
+ /** The slice of `ProcessingContext` the ledger listens on. */
121
+ export interface CostLedgerSource {
122
+ addMessageListener(listener: (msg: ProcessingMessage) => void): () => void;
123
+ }
124
+ /**
125
+ * Record every generation a run pays for. Returns the detach function.
126
+ *
127
+ * Listens on the context rather than on a host's outbound message loop so each
128
+ * surface — CLI, ws server, app runtime, debug harness — records once, from the
129
+ * same seam, and cannot drift.
130
+ */
131
+ export interface RunCostLedgerHandle {
132
+ /** Detach the listener. */
133
+ (): void;
134
+ /**
135
+ * Resolve once every write the listener has started so far has landed.
136
+ * The listener fires and forgets; a caller that reads the row right after
137
+ * the generation returned (a direct RPC answering its client) waits here.
138
+ */
139
+ settled(): Promise<void>;
140
+ }
141
+ export declare function attachRunCostLedger(context: CostLedgerSource, options: RunCostLedgerOptions): RunCostLedgerHandle;
142
+ /**
143
+ * Ledger one run message: a node's self-reported charge, or a completed
144
+ * unit-billed prediction. Anything else is not spend and writes nothing.
145
+ */
146
+ export declare function recordFromMessage(msg: ProcessingMessage, options: RunCostLedgerOptions, state?: GenerationTrackerState): Promise<void>;
147
+ //# sourceMappingURL=cost-ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-ledger.d.ts","sourceRoot":"","sources":["../src/cost-ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,288 @@
1
+ /**
2
+ * Provider-spend ledger — the write half of `nodetool costs`.
3
+ *
4
+ * `BaseProvider` accounts for chat and stream in tokens, and the host writes
5
+ * that row. Image, video and audio generation had no equivalent: the money went
6
+ * out and nothing reached the `predictions` table, so a render session read as
7
+ * free.
8
+ *
9
+ * Two kinds of generation reach a ledger row here:
10
+ *
11
+ * - A node that knows its own charge calls `context.setProviderCost()`, which
12
+ * rides out on the completed `node_update` as `provider_cost`. FAL and kie do
13
+ * this — the number comes from the provider, so it wins. When the provider
14
+ * also exposes a request-keyed billing API, the estimate is reconciled to the
15
+ * actual charge in the background.
16
+ * - Everything else goes through `ProcessingContext.runProviderPrediction` (and
17
+ * its streaming/encoded siblings), which emits a `prediction` message
18
+ * carrying provider, model, capability and the job's parameters. That is
19
+ * priced here against `@nodetool-ai/model-pricing` — the same catalog the
20
+ * editor's cost preview and the pre-run budget gate read.
21
+ *
22
+ * A model in no catalog still gets a row, with `cost` left null rather than set
23
+ * to zero: the call is visible in `nodetool costs`, and a null is countable as
24
+ * unpriced instead of summing as free. The units behind a price are recorded
25
+ * next to it (`billing_unit`, `quantity`, `unit_price`, `currency`, plus the
26
+ * catalog's own breakdown in `metadata`) so a per-second or per-megapixel row
27
+ * is auditable even when the estimate is imperfect.
28
+ */
29
+ import { createLogger } from "@nodetool-ai/config";
30
+ import { Prediction } from "@nodetool-ai/models";
31
+ import { getModelUnitPrice } from "@nodetool-ai/model-pricing";
32
+ import { extractPricingParams } from "@nodetool-ai/node-sdk";
33
+ import { getCostReconciler } from "@nodetool-ai/runtime";
34
+ import { createTrackerState, trackPredictionMessage } from "./generation-tracker.js";
35
+ import { providerBillingSecretKey } from "./provider-secret-key.js";
36
+ const log = createLogger("nodetool.execution.cost-ledger");
37
+ /**
38
+ * Capabilities a provider bills per output rather than per token. Chat,
39
+ * streaming chat and embeddings are absent on purpose: a token-billed call
40
+ * reaches this ledger by a different road, so admitting it here would book it
41
+ * twice. A chat turn writes the provider instance's running total through
42
+ * `ChatTurn._logProviderCall`; a workflow node reports its own delta through
43
+ * `meterProviderSpend` -> `setProviderCost` -> `recordNodeProviderCost`.
44
+ */
45
+ const UNIT_BILLED_CAPABILITIES = new Set([
46
+ "text_to_image",
47
+ "image_to_image",
48
+ "inpainting",
49
+ "outpaint_image",
50
+ "text_to_video",
51
+ "image_to_video",
52
+ "reference_to_video",
53
+ "video_to_video",
54
+ "upscale_video",
55
+ "interpolate_video",
56
+ "outpaint_video",
57
+ "upscale_image",
58
+ "remove_background",
59
+ "relight_image",
60
+ "segment_image",
61
+ "vectorize_image",
62
+ "lip_sync",
63
+ "text_to_speech",
64
+ "text_to_music",
65
+ "audio_to_audio",
66
+ "video_to_audio",
67
+ "automatic_speech_recognition",
68
+ "text_to_3d",
69
+ "image_to_3d",
70
+ "render_model3d"
71
+ ]);
72
+ /** Whether a capability is billed per unit of output (and so belongs here). */
73
+ export function isUnitBilledCapability(capability) {
74
+ return capability != null && UNIT_BILLED_CAPABILITIES.has(capability);
75
+ }
76
+ /**
77
+ * Price a generation against the model catalogs. Returns `null` when no catalog
78
+ * carries the model, or when the catalog declines to extrapolate — a refusal is
79
+ * an answer, and inventing a number would be worse than recording none.
80
+ */
81
+ export function priceGeneration(spend) {
82
+ const quantity = spend.quantity ?? 1;
83
+ if (!Number.isFinite(quantity) || quantity <= 0)
84
+ return null;
85
+ const price = getModelUnitPrice({ id: spend.model, provider: spend.provider }, extractPricingParams(spend.params));
86
+ if (!price || price.declined)
87
+ return null;
88
+ if (!Number.isFinite(price.unit_price))
89
+ return null;
90
+ const priced = {
91
+ cost: price.unit_price * quantity,
92
+ unit_price: price.unit_price,
93
+ quantity,
94
+ billing_unit: price.billing_unit || (spend.capability ?? "run"),
95
+ currency: price.currency || "USD"
96
+ };
97
+ if (price.breakdown)
98
+ priced.breakdown = price.breakdown;
99
+ if (price.assumptions?.length)
100
+ priced.assumptions = price.assumptions;
101
+ return priced;
102
+ }
103
+ /**
104
+ * Write one generation to the ledger. Best-effort: a host with no database
105
+ * (a hermetic run, an eval) must not fail because accounting could not be
106
+ * persisted — the generation already happened and was already billed.
107
+ */
108
+ export async function recordGenerationSpend(spend) {
109
+ const priced = priceGeneration(spend);
110
+ const metadata = {
111
+ capability: spend.capability ?? null
112
+ };
113
+ if (priced) {
114
+ metadata.price_source = "model-catalog";
115
+ if (priced.breakdown)
116
+ metadata.price_breakdown = priced.breakdown;
117
+ if (priced.assumptions)
118
+ metadata.price_assumptions = priced.assumptions;
119
+ }
120
+ else {
121
+ metadata.unpriced_reason = `No unit price for ${spend.provider}/${spend.model} in the model catalogs`;
122
+ }
123
+ try {
124
+ return await Prediction.create({
125
+ user_id: spend.userId,
126
+ provider: spend.provider,
127
+ model: spend.model,
128
+ node_id: spend.nodeId ?? "",
129
+ node_type: spend.nodeType ?? "",
130
+ workflow_id: spend.workflowId ?? null,
131
+ project_id: spend.projectId ?? null,
132
+ document_id: spend.documentId ?? null,
133
+ status: "completed",
134
+ cost: priced ? priced.cost : null,
135
+ billing_unit: priced ? priced.billing_unit : (spend.capability ?? null),
136
+ quantity: priced ? priced.quantity : (spend.quantity ?? 1),
137
+ unit_price: priced ? priced.unit_price : null,
138
+ currency: priced ? priced.currency : null,
139
+ duration: spend.durationMs != null ? spend.durationMs / 1000 : null,
140
+ metadata
141
+ });
142
+ }
143
+ catch (err) {
144
+ log.debug("Generation spend not recorded", {
145
+ provider: spend.provider,
146
+ model: spend.model,
147
+ error: err instanceof Error ? err.message : String(err)
148
+ });
149
+ return null;
150
+ }
151
+ }
152
+ /**
153
+ * Write a node-reported provider charge to the ledger, then refine it into the
154
+ * provider's actual billed amount in the background when that provider
155
+ * registered a reconciler. Best-effort throughout.
156
+ */
157
+ export async function recordNodeProviderCost(spend) {
158
+ const { cost } = spend;
159
+ // A NaN/Infinity amount from a buggy provider call can't be stored: SQLite
160
+ // has no representation for it and JSON turns it into `null`.
161
+ if (!Number.isFinite(cost.amount))
162
+ return null;
163
+ try {
164
+ const prediction = await Prediction.create({
165
+ user_id: spend.userId,
166
+ provider: cost.provider,
167
+ model: cost.model ?? spend.nodeType,
168
+ node_type: spend.nodeType,
169
+ node_id: spend.nodeId,
170
+ workflow_id: spend.workflowId,
171
+ project_id: spend.projectId ?? null,
172
+ document_id: spend.documentId ?? null,
173
+ status: "completed",
174
+ cost: cost.amount,
175
+ currency: cost.currency ?? cost.unit ?? null,
176
+ billing_unit: cost.billing_unit ?? null,
177
+ quantity: cost.quantity ?? null,
178
+ unit_price: cost.unit_price ?? null,
179
+ provider_request_id: cost.provider_request_id ?? null,
180
+ // Set by a token-billed call (an LLM node reporting a `generateLoop`
181
+ // delta), left null by a per-output generation that counts no tokens.
182
+ input_tokens: cost.input_tokens ?? null,
183
+ output_tokens: cost.output_tokens ?? null,
184
+ cached_tokens: cost.cached_tokens ?? null
185
+ });
186
+ if (cost.provider_request_id) {
187
+ void reconcileProviderCost(prediction, spend);
188
+ }
189
+ return prediction;
190
+ }
191
+ catch (err) {
192
+ log.debug("Node provider cost not recorded", {
193
+ provider: cost.provider,
194
+ error: err instanceof Error ? err.message : String(err)
195
+ });
196
+ return null;
197
+ }
198
+ }
199
+ /**
200
+ * Replace an estimated charge with the provider's actual billed amount, looked
201
+ * up by request id. Runs detached; leaves the estimate in place when no actual
202
+ * is available.
203
+ */
204
+ async function reconcileProviderCost(prediction, spend) {
205
+ const reconciler = getCostReconciler(spend.cost.provider);
206
+ if (!reconciler || !spend.cost.provider_request_id)
207
+ return;
208
+ try {
209
+ const secretKey = providerBillingSecretKey(spend.cost.provider);
210
+ const apiKey = await spend.resolveSecret?.(secretKey);
211
+ const actual = await reconciler({
212
+ requestId: spend.cost.provider_request_id,
213
+ endpointId: spend.cost.model ?? null,
214
+ secrets: apiKey ? { [secretKey]: apiKey } : {}
215
+ });
216
+ if (!actual)
217
+ return;
218
+ await prediction.update({
219
+ cost: actual.cost,
220
+ currency: actual.currency ?? prediction.currency,
221
+ quantity: actual.quantity ?? prediction.quantity,
222
+ unit_price: actual.unit_price ?? prediction.unit_price
223
+ });
224
+ }
225
+ catch (err) {
226
+ log.warn("Failed to reconcile provider cost", {
227
+ provider: spend.cost.provider,
228
+ error: err instanceof Error ? err.message : String(err)
229
+ });
230
+ }
231
+ }
232
+ /**
233
+ * A `nodeType` lookup built once per run. Scanning the node list per message
234
+ * would be O(nodes × messages), which a 20 000-node graph feels.
235
+ */
236
+ export function nodeTypeLookup(nodes) {
237
+ const types = new Map(nodes.map((node) => [node.id, node.type]));
238
+ return (nodeId) => types.get(nodeId) ?? "";
239
+ }
240
+ export function attachRunCostLedger(context, options) {
241
+ const state = createTrackerState();
242
+ const pending = new Set();
243
+ const detach = context.addMessageListener((msg) => {
244
+ const write = recordFromMessage(msg, options, state)
245
+ .catch(() => undefined)
246
+ .finally(() => pending.delete(write));
247
+ pending.add(write);
248
+ });
249
+ return Object.assign(detach, {
250
+ settled: async () => {
251
+ await Promise.all([...pending]);
252
+ }
253
+ });
254
+ }
255
+ /**
256
+ * Ledger one run message: a node's self-reported charge, or a completed
257
+ * unit-billed prediction. Anything else is not spend and writes nothing.
258
+ */
259
+ export async function recordFromMessage(msg, options, state = createTrackerState()) {
260
+ if (msg.type === "node_update" && msg.status === "completed") {
261
+ if (!msg.provider_cost)
262
+ return;
263
+ // A node that went through the generation seam and whose provider stated
264
+ // its charge already has a row with that charge (design § 6.5). Its own
265
+ // `provider_cost` is the same money a second time.
266
+ if (state.receiptCostNodes.has(msg.node_id)) {
267
+ state.receiptCostNodes.delete(msg.node_id);
268
+ return;
269
+ }
270
+ await recordNodeProviderCost({
271
+ userId: options.userId,
272
+ cost: msg.provider_cost,
273
+ nodeId: msg.node_id,
274
+ nodeType: msg.node_type || options.nodeType?.(msg.node_id) || "",
275
+ workflowId: options.workflowId,
276
+ projectId: options.projectId,
277
+ documentId: options.documentId,
278
+ resolveSecret: options.resolveSecret
279
+ });
280
+ return;
281
+ }
282
+ if (msg.type !== "prediction")
283
+ return;
284
+ // The tracker opens the row on `running` and closes it on the terminal
285
+ // message, so every state of a generation is a row state.
286
+ await trackPredictionMessage(msg, options, state);
287
+ }
288
+ //# sourceMappingURL=cost-ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-ledger.js","sourceRoot":"","sources":["../src/cost-ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Folds a workflow run's processing-message stream into an `ExecutionSummary`.
3
+ *
4
+ * Pure and surface-agnostic: the same reducer distills the server runner's
5
+ * `RunResult.messages` and the browser harness's raw event log, so both surfaces
6
+ * report identically. Only `import type` is used here so the module stays free of
7
+ * runtime workspace dependencies (testable under the CLI vitest stub setup).
8
+ */
9
+ import type { ProcessingMessage } from "@nodetool-ai/protocol";
10
+ import type { ExecutionSummary } from "./types.js";
11
+ /**
12
+ * Make a value safe to embed in a JSON debug report: truncate long strings,
13
+ * collapse binary and base64 blobs, and cap array/object fan-out. Keeps enough
14
+ * to debug (shape, prefixes, sizes) without dumping megabytes of media bytes.
15
+ */
16
+ /** A value reduced to what a JSON debug report can carry. */
17
+ export type PreviewValue = string | number | boolean | null | undefined | PreviewValue[] | {
18
+ [key: string]: PreviewValue;
19
+ };
20
+ export declare function previewValue(value: unknown, maxLen?: number): PreviewValue;
21
+ /**
22
+ * Reduce a processing-message stream into a structured execution summary.
23
+ *
24
+ * Accepts loosely-typed messages (the browser harness decodes JSON into bags of
25
+ * unknown fields) and reads only the fields each `type` is known to carry.
26
+ */
27
+ export declare function collectExecutionSummary(messages: ReadonlyArray<ProcessingMessage | Record<string, unknown>>): ExecutionSummary;
28
+ //# sourceMappingURL=collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/debug/collector.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAgB,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,KAAK,EAEV,gBAAgB,EAKjB,MAAM,YAAY,CAAC;AA6BpB;;;;GAIG;AACH,6DAA6D;AAC7D,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,GACT,YAAY,EAAE,GACd;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;CAAE,CAAC;AAEpC,wBAAgB,YAAY,CAC1B,KAAK,EAAE,OAAO,EACd,MAAM,GAAE,MAA2B,GAClC,YAAY,CA+Bd;AAcD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,aAAa,CAAC,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACnE,gBAAgB,CAiLlB"}