octaflow 0.14.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 +288 -0
- package/dist/ai/index.d.ts +397 -0
- package/dist/ai/index.js +466 -0
- package/dist/core-ERYGlYsS.js +574 -0
- package/dist/dispatcher-BydjyrgU.d.ts +26 -0
- package/dist/dispatcher-pgboss/index.d.ts +170 -0
- package/dist/dispatcher-pgboss/index.js +301 -0
- package/dist/hooks-CDRFQZbT.d.ts +56 -0
- package/dist/index-D_fOYfmf.d.ts +580 -0
- package/dist/index.d.ts +137 -0
- package/dist/index.js +1426 -0
- package/dist/logger-BCus3AOa.d.ts +10 -0
- package/dist/observability-BsrvbhDr.d.ts +249 -0
- package/dist/store-pg/index.d.ts +195 -0
- package/dist/store-pg/index.js +671 -0
- package/package.json +116 -0
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import { K as FlowErrorShape, T as RetryPolicy, h as TypedWorkflow, m as TypedStepContext, p as TypedStep, q as Result } from "../index-D_fOYfmf.js";
|
|
2
|
+
import { n as Logger } from "../logger-BCus3AOa.js";
|
|
3
|
+
import { i as BuildStepContextArgs, o as WorkflowHooks } from "../hooks-CDRFQZbT.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { EmbeddingModelV4, LanguageModelV4 } from "@ai-sdk/provider";
|
|
6
|
+
//#region src/ai/instrumented-model.d.ts
|
|
7
|
+
interface AccumulatedUsage {
|
|
8
|
+
inputTokens: number;
|
|
9
|
+
outputTokens: number;
|
|
10
|
+
cacheReadTokens: number;
|
|
11
|
+
cacheWriteTokens: number;
|
|
12
|
+
modelId: string;
|
|
13
|
+
}
|
|
14
|
+
interface UsageAccumulator {
|
|
15
|
+
/** Record usage from a single LLM call (additive — supports multiple calls per step). */
|
|
16
|
+
record(usage: AccumulatedUsage): void;
|
|
17
|
+
/** Total accumulated usage across all calls. */
|
|
18
|
+
get(): AccumulatedUsage;
|
|
19
|
+
/** Whether any usage was recorded. */
|
|
20
|
+
hasUsage(): boolean;
|
|
21
|
+
}
|
|
22
|
+
declare function createUsageAccumulator(): UsageAccumulator;
|
|
23
|
+
/**
|
|
24
|
+
* Wrap a language model with usage-tracking middleware. The accumulator collects
|
|
25
|
+
* token usage from every doGenerate/doStream call routed through the wrapped model.
|
|
26
|
+
*/
|
|
27
|
+
declare function createInstrumentedModel(model: LanguageModelV4, accumulator: UsageAccumulator): LanguageModelV4;
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/ai/instrumented-embedding-model.d.ts
|
|
30
|
+
interface EmbeddingAccumulatedUsage {
|
|
31
|
+
inputTokens: number;
|
|
32
|
+
callCount: number;
|
|
33
|
+
modelId: string;
|
|
34
|
+
}
|
|
35
|
+
interface EmbeddingUsageAccumulator {
|
|
36
|
+
/** Record usage from a single doEmbed call (additive — supports multiple calls per batch). */
|
|
37
|
+
record(tokens: number, modelId: string): void;
|
|
38
|
+
/** Total accumulated usage across all calls. */
|
|
39
|
+
get(): EmbeddingAccumulatedUsage;
|
|
40
|
+
/** Whether any usage was recorded. */
|
|
41
|
+
hasUsage(): boolean;
|
|
42
|
+
/** Clear all accumulated state — used when a long-lived accumulator is reused across flushes. */
|
|
43
|
+
reset(): void;
|
|
44
|
+
}
|
|
45
|
+
declare function createEmbeddingUsageAccumulator(): EmbeddingUsageAccumulator;
|
|
46
|
+
/**
|
|
47
|
+
* Wrap an embedding model with usage-tracking middleware. The accumulator collects
|
|
48
|
+
* token usage from every doEmbed call routed through the wrapped model — both
|
|
49
|
+
* `embed()` (single value) and `embedMany()` (batched values) invoke doEmbed one or
|
|
50
|
+
* more times, and each invocation is recorded.
|
|
51
|
+
*/
|
|
52
|
+
declare function createInstrumentedEmbeddingModel(model: EmbeddingModelV4, accumulator: EmbeddingUsageAccumulator): EmbeddingModelV4;
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/ai/cost.d.ts
|
|
55
|
+
/**
|
|
56
|
+
* Token → cost estimation. Cost is computed in **microdollars**
|
|
57
|
+
* (1 USD = 1,000,000 microdollars) to avoid float accumulation.
|
|
58
|
+
*
|
|
59
|
+
* The pricing table is injectable: pass your own to `createCostEstimator` for a
|
|
60
|
+
* different provider/model set. A default Anthropic/OpenAI-embedding table ships.
|
|
61
|
+
*/
|
|
62
|
+
interface ModelPricing {
|
|
63
|
+
inputPerMillion: number;
|
|
64
|
+
outputPerMillion: number;
|
|
65
|
+
cacheReadPerMillion: number;
|
|
66
|
+
cacheWritePerMillion: number;
|
|
67
|
+
}
|
|
68
|
+
interface TokenUsage {
|
|
69
|
+
inputTokens: number;
|
|
70
|
+
outputTokens: number;
|
|
71
|
+
cacheReadTokens: number;
|
|
72
|
+
cacheWriteTokens: number;
|
|
73
|
+
}
|
|
74
|
+
/** Default pricing (USD per million tokens), as of 2026-04. */
|
|
75
|
+
declare const DEFAULT_MODEL_PRICING: Record<string, ModelPricing>;
|
|
76
|
+
interface CostEstimatorOptions {
|
|
77
|
+
/** Pricing table keyed by model id. Defaults to `DEFAULT_MODEL_PRICING`. */
|
|
78
|
+
pricing?: Record<string, ModelPricing>;
|
|
79
|
+
/** Pricing used for unknown model ids. Defaults to the priciest entry in the table (safe overcounting). */
|
|
80
|
+
fallback?: ModelPricing;
|
|
81
|
+
}
|
|
82
|
+
type CostEstimator = (usage: TokenUsage, modelId: string) => number;
|
|
83
|
+
/** Build a cost estimator returning microdollars. */
|
|
84
|
+
declare function createCostEstimator(options?: CostEstimatorOptions): CostEstimator;
|
|
85
|
+
/** Convenience estimator using the default pricing table. */
|
|
86
|
+
declare const estimateCostMicros: CostEstimator;
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region src/ai/context.d.ts
|
|
89
|
+
/**
|
|
90
|
+
* The `TContext` flow-core threads through AI workflows. Produced by the
|
|
91
|
+
* `buildStepContext` hook in `createAiWorkflowHooks` and consumed by AI step
|
|
92
|
+
* handlers (which read `ctx.context.model` / `ctx.context.host`).
|
|
93
|
+
*/
|
|
94
|
+
interface AiContext<THost = unknown> {
|
|
95
|
+
/** Instrumented language model — token usage is captured automatically. */
|
|
96
|
+
model: LanguageModelV4;
|
|
97
|
+
/** Host-provided per-step context (DI scope, domain services, …). */
|
|
98
|
+
host: THost;
|
|
99
|
+
/**
|
|
100
|
+
* Internal: the per-step usage accumulator. The `onAfterStep` hook reads this
|
|
101
|
+
* back off the context to persist token/cost. Handlers should not touch it.
|
|
102
|
+
*/
|
|
103
|
+
readonly usage: UsageAccumulator;
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/ai/define-ai-step.d.ts
|
|
107
|
+
/** An AI workflow step — a flow-core `TypedStep` whose context is an `AiContext`. */
|
|
108
|
+
type AiTypedStep<TInput extends Record<string, unknown> = Record<string, unknown>, TOutput extends Record<string, unknown> = Record<string, unknown>, THost = unknown, TDeps extends Record<string, TypedStep<any, any, any, AiContext<THost>>> = {}> = TypedStep<TInput, TOutput, TDeps, AiContext<THost>>;
|
|
109
|
+
interface DefineAiStepConfig<TInput extends Record<string, unknown>, TOutput extends Record<string, unknown>, THost, TDeps extends Record<string, TypedStep<any, any, any, AiContext<THost>>>> {
|
|
110
|
+
type: string;
|
|
111
|
+
workflowInputSchema: z.ZodType<TInput>;
|
|
112
|
+
outputSchema: z.ZodType<TOutput>;
|
|
113
|
+
dependencies?: TDeps;
|
|
114
|
+
handler: (ctx: TypedStepContext<TInput, TDeps, AiContext<THost>>) => Promise<TOutput>;
|
|
115
|
+
/** Optional retry policy (max attempts, backoff) — e.g. for provider 429s. */
|
|
116
|
+
retry?: RetryPolicy;
|
|
117
|
+
/** Optional per-step wall-clock timeout in ms. */
|
|
118
|
+
timeoutMs?: number;
|
|
119
|
+
/** Optional durable start delay in ms — held in the queue once the step is ready. */
|
|
120
|
+
delayMs?: number;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Define a type-safe AI workflow step. Identical to flow-core's `defineStep`
|
|
124
|
+
* except the handler context is fixed to `AiContext<THost>`, so handlers get a
|
|
125
|
+
* ready-to-use `ctx.context.model` (instrumented) and `ctx.context.host`.
|
|
126
|
+
*/
|
|
127
|
+
declare function defineAiStep<TInput extends Record<string, unknown>, TOutput extends Record<string, unknown>, THost = unknown, TDeps extends Record<string, TypedStep<any, any, any, AiContext<THost>>> = {}>(config: DefineAiStepConfig<TInput, TOutput, THost, TDeps>): AiTypedStep<TInput, TOutput, THost, TDeps>;
|
|
128
|
+
/** Build a typed AI workflow from `defineAiStep` definitions. */
|
|
129
|
+
declare function buildAiWorkflow<TInput extends Record<string, unknown>, THost = unknown, TSteps extends Record<string, TypedStep<any, any, any, AiContext<THost>>> = {}>(config: {
|
|
130
|
+
type: string;
|
|
131
|
+
inputSchema: z.ZodType<TInput>;
|
|
132
|
+
steps: TSteps;
|
|
133
|
+
}): TypedWorkflow<TInput, AiContext<THost>>;
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/ai/hooks.d.ts
|
|
136
|
+
interface AiModelResolver<THost = unknown> {
|
|
137
|
+
/** Resolve the base (uninstrumented) model for a step. */
|
|
138
|
+
resolveModel(args: BuildStepContextArgs): Promise<LanguageModelV4> | LanguageModelV4;
|
|
139
|
+
/** Optional host context (DI scope, services) exposed to handlers as `ctx.context.host`. */
|
|
140
|
+
resolveHost?(args: BuildStepContextArgs): Promise<THost> | THost;
|
|
141
|
+
/**
|
|
142
|
+
* Which key paid for the run — stamped into workflow metadata for usage
|
|
143
|
+
* rollups. Any string; `'platform' | 'tenant'` is the usual convention.
|
|
144
|
+
* When absent, rollups default to `'platform'`.
|
|
145
|
+
*/
|
|
146
|
+
resolveKeySource?(): Promise<string> | string;
|
|
147
|
+
}
|
|
148
|
+
interface AiUsageRecorder {
|
|
149
|
+
/** Persist per-step token usage + cost (e.g. onto the step row). */
|
|
150
|
+
recordStepUsage(args: {
|
|
151
|
+
workflowId: number;
|
|
152
|
+
stepId: number;
|
|
153
|
+
usage: AccumulatedUsage;
|
|
154
|
+
costMicros: number;
|
|
155
|
+
}): Promise<void>;
|
|
156
|
+
/** Atomically add this step's usage + cost to the workflow's running totals. */
|
|
157
|
+
incrementWorkflowUsage(args: {
|
|
158
|
+
workflowId: number;
|
|
159
|
+
usage: AccumulatedUsage;
|
|
160
|
+
costMicros: number;
|
|
161
|
+
}): Promise<void>;
|
|
162
|
+
/**
|
|
163
|
+
* Roll the completed workflow's totals into a daily aggregate. The host reads
|
|
164
|
+
* the workflow's accumulated totals from its own store and UPSERTs the rollup.
|
|
165
|
+
*/
|
|
166
|
+
recordWorkflowDaily?(args: {
|
|
167
|
+
workflowId: number;
|
|
168
|
+
workflowType: string;
|
|
169
|
+
keySource: string;
|
|
170
|
+
date: string;
|
|
171
|
+
}): Promise<void>;
|
|
172
|
+
}
|
|
173
|
+
interface AiQuotaPolicy {
|
|
174
|
+
/** Return an error (e.g. `ai_quota_exceeded`) to reject a workflow start. */
|
|
175
|
+
checkQuota(): Promise<Result<void, FlowErrorShape>>;
|
|
176
|
+
}
|
|
177
|
+
interface CreateAiWorkflowHooksDeps<THost = unknown> {
|
|
178
|
+
modelResolver: AiModelResolver<THost>;
|
|
179
|
+
usageRecorder: AiUsageRecorder;
|
|
180
|
+
/** Optional quota guard. BYOK exemption etc. is the policy's concern. */
|
|
181
|
+
quotaPolicy?: AiQuotaPolicy;
|
|
182
|
+
/** Defaults to `createCostEstimator()` (the built-in pricing table). */
|
|
183
|
+
costEstimator?: CostEstimator;
|
|
184
|
+
/** Clock injection for tests. */
|
|
185
|
+
now?: () => Date;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Wire the AI behaviors (model instrumentation, token/cost capture, quota,
|
|
189
|
+
* usage rollups) into a set of flow-core lifecycle hooks. Pass the result as the
|
|
190
|
+
* engine's `hooks`. flow-core stays AI-free; everything AI lives here.
|
|
191
|
+
*/
|
|
192
|
+
declare function createAiWorkflowHooks<THost = unknown>(deps: CreateAiWorkflowHooksDeps<THost>): WorkflowHooks<AiContext<THost>>;
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region src/ai/quota.d.ts
|
|
195
|
+
/**
|
|
196
|
+
* Resolved quota limits for a scope. `null` on any window means **unlimited**
|
|
197
|
+
* for that window (the check is skipped). The {@link AiQuotaConfigResolver} may
|
|
198
|
+
* return `null` for the whole config to exempt a scope entirely (e.g. a
|
|
199
|
+
* bring-your-own-key caller that shouldn't be metered against platform quota).
|
|
200
|
+
*/
|
|
201
|
+
interface AiQuotaConfig {
|
|
202
|
+
/** Max simultaneously-running workflows. `null` = unlimited. */
|
|
203
|
+
maxConcurrentWorkflows: number | null;
|
|
204
|
+
/** Max workflows started per calendar day (UTC). `null` = unlimited. */
|
|
205
|
+
maxWorkflowsPerDay: number | null;
|
|
206
|
+
/** Max workflows started per calendar month (UTC). `null` = unlimited. */
|
|
207
|
+
maxWorkflowsPerMonth: number | null;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Convenience defaults a consumer can spread over partial per-scope limits.
|
|
211
|
+
* flow does **not** apply these automatically — resolution policy lives in the
|
|
212
|
+
* injected {@link AiQuotaConfigResolver}.
|
|
213
|
+
*/
|
|
214
|
+
declare const DEFAULT_AI_QUOTA: AiQuotaConfig;
|
|
215
|
+
/**
|
|
216
|
+
* Resolves the quota limits for a scope. Returning `null` exempts the scope
|
|
217
|
+
* from all quota enforcement (the check short-circuits to success).
|
|
218
|
+
*/
|
|
219
|
+
type AiQuotaConfigResolver = (partitionKey: string) => AiQuotaConfig | null | Promise<AiQuotaConfig | null>;
|
|
220
|
+
/** A `[startDate, endDate]` inclusive query over the daily-usage rollup (dates are `YYYY-MM-DD`). */
|
|
221
|
+
interface AiUsageCountQuery {
|
|
222
|
+
partitionKey: string;
|
|
223
|
+
/** Inclusive lower bound, `YYYY-MM-DD`. */
|
|
224
|
+
startDate: string;
|
|
225
|
+
/** Inclusive upper bound, `YYYY-MM-DD`. */
|
|
226
|
+
endDate: string;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* The reads quota enforcement needs from storage. The consumer implements these
|
|
230
|
+
* with its own queries (over the in-flight workflow table and the daily-usage
|
|
231
|
+
* rollup); flow supplies no implementation. Any workflow-type filtering policy
|
|
232
|
+
* (e.g. excluding synthetic embedding rows from the count) lives in the
|
|
233
|
+
* consumer's SQL, keeping this layer policy-agnostic.
|
|
234
|
+
*/
|
|
235
|
+
interface AiQuotaStore {
|
|
236
|
+
/** Number of workflows currently `running` for the scope. */
|
|
237
|
+
countRunningWorkflows(partitionKey: string): Promise<number>;
|
|
238
|
+
/** Sum of `workflowCount` in the daily rollup over the inclusive date range. */
|
|
239
|
+
sumWorkflowCount(query: AiUsageCountQuery): Promise<number>;
|
|
240
|
+
}
|
|
241
|
+
/** Reason a start was rejected — which window tripped. */
|
|
242
|
+
type AiQuotaExceededReason = 'concurrent_limit' | 'daily_limit' | 'monthly_limit';
|
|
243
|
+
/** Expected error value when a start is rejected by quota. Extends flow's structural error. */
|
|
244
|
+
interface AiQuotaExceededError {
|
|
245
|
+
key: 'ai_quota_exceeded';
|
|
246
|
+
reason: AiQuotaExceededReason;
|
|
247
|
+
message: string;
|
|
248
|
+
/** The limit that was hit. */
|
|
249
|
+
limit: number;
|
|
250
|
+
/** The observed count at rejection (includes in-flight runs for the day/month windows). */
|
|
251
|
+
current: number;
|
|
252
|
+
}
|
|
253
|
+
interface CreateAiQuotaServiceDeps {
|
|
254
|
+
/** Count reads over the in-flight workflow table + daily rollup. */
|
|
255
|
+
store: AiQuotaStore;
|
|
256
|
+
/** Per-scope limit resolver. Return `null` to exempt the scope. */
|
|
257
|
+
getQuota: AiQuotaConfigResolver;
|
|
258
|
+
/** Clock injection for window computation (tests). Defaults to `() => new Date()`. */
|
|
259
|
+
now?: () => Date;
|
|
260
|
+
}
|
|
261
|
+
interface AiQuotaService {
|
|
262
|
+
/**
|
|
263
|
+
* Check all quota windows for the scope. Resolves `ok` when the start is
|
|
264
|
+
* allowed, or an {@link AiQuotaExceededError} naming the window that tripped.
|
|
265
|
+
* The day and month counts include currently-running (not-yet-aggregated)
|
|
266
|
+
* workflows, matching the source semantics.
|
|
267
|
+
*/
|
|
268
|
+
checkQuota(partitionKey: string): Promise<Result<void, AiQuotaExceededError>>;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Build a store-agnostic AI quota service. Enforcement order is concurrent →
|
|
272
|
+
* day → month; the first tripped window short-circuits with its error.
|
|
273
|
+
*/
|
|
274
|
+
declare function createAiQuotaService(deps: CreateAiQuotaServiceDeps): AiQuotaService;
|
|
275
|
+
//#endregion
|
|
276
|
+
//#region src/ai/usage-aggregation.d.ts
|
|
277
|
+
/** An additive write into the daily-usage rollup for one run (workflow completion or embedding batch). */
|
|
278
|
+
interface DailyUsageDelta {
|
|
279
|
+
partitionKey: string;
|
|
280
|
+
/** Calendar day of the run, `YYYY-MM-DD`. */
|
|
281
|
+
date: string;
|
|
282
|
+
workflowType: string;
|
|
283
|
+
/** Which key paid for the run (free-form; e.g. `'platform' | 'tenant'`). */
|
|
284
|
+
keySource: string;
|
|
285
|
+
/** How much to add to `workflowCount` — always `1` for the built-in recorders. */
|
|
286
|
+
workflowCount: number;
|
|
287
|
+
/** Token totals to add. Embeddings set only `inputTokens` (the rest are `0`). */
|
|
288
|
+
usage: TokenUsage;
|
|
289
|
+
/** Cost to add, in microdollars (1 USD = 1,000,000). */
|
|
290
|
+
estimatedCostMicros: number;
|
|
291
|
+
}
|
|
292
|
+
/** Inclusive `[startDate, endDate]` range query for the aggregate reads (`YYYY-MM-DD`). */
|
|
293
|
+
interface AiUsageRangeQuery {
|
|
294
|
+
partitionKey: string;
|
|
295
|
+
startDate: string;
|
|
296
|
+
endDate: string;
|
|
297
|
+
}
|
|
298
|
+
/** One row of the per-day aggregate (GROUP BY date). */
|
|
299
|
+
interface UsageSummaryRow {
|
|
300
|
+
date: string;
|
|
301
|
+
workflowCount: number;
|
|
302
|
+
inputTokens: number;
|
|
303
|
+
outputTokens: number;
|
|
304
|
+
cacheReadTokens: number;
|
|
305
|
+
cacheWriteTokens: number;
|
|
306
|
+
estimatedCostMicros: number;
|
|
307
|
+
}
|
|
308
|
+
/** One row of the per-type aggregate (GROUP BY workflowType, keySource). */
|
|
309
|
+
interface UsageByTypeRow {
|
|
310
|
+
workflowType: string;
|
|
311
|
+
keySource: string;
|
|
312
|
+
workflowCount: number;
|
|
313
|
+
inputTokens: number;
|
|
314
|
+
outputTokens: number;
|
|
315
|
+
estimatedCostMicros: number;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* The reads/writes usage aggregation needs from storage. Extends
|
|
319
|
+
* {@link AiQuotaStore} so a single consumer implementation backs both the quota
|
|
320
|
+
* and aggregation engines. The `addDailyUsage` UPSERT and the two aggregate
|
|
321
|
+
* reads are the consumer's SQL; flow owns everything above the seam.
|
|
322
|
+
*/
|
|
323
|
+
interface AiUsageStore extends AiQuotaStore {
|
|
324
|
+
/** UPSERT-add a run's usage into the daily rollup (unique on partition+date+type+keySource). */
|
|
325
|
+
addDailyUsage(delta: DailyUsageDelta): Promise<void>;
|
|
326
|
+
/** Per-day totals over the range, ascending by date. */
|
|
327
|
+
aggregateByDate(query: AiUsageRangeQuery): Promise<UsageSummaryRow[]>;
|
|
328
|
+
/** Per-(type, keySource) totals over the range. */
|
|
329
|
+
aggregateByWorkflowType(query: AiUsageRangeQuery): Promise<UsageByTypeRow[]>;
|
|
330
|
+
}
|
|
331
|
+
/** A completed LLM workflow's usage to roll up. */
|
|
332
|
+
interface WorkflowUsageInput {
|
|
333
|
+
partitionKey: string;
|
|
334
|
+
/** Calendar day of completion, `YYYY-MM-DD`. */
|
|
335
|
+
date: string;
|
|
336
|
+
workflowType: string;
|
|
337
|
+
keySource: string;
|
|
338
|
+
usage: TokenUsage;
|
|
339
|
+
estimatedCostMicros: number;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* A flushed embedding batch's usage to roll up. Embeddings have only input
|
|
343
|
+
* tokens (no output, no cache); `workflowCount` increments once per flushed
|
|
344
|
+
* batch, not per inner embed call.
|
|
345
|
+
*/
|
|
346
|
+
interface EmbeddingUsageInput {
|
|
347
|
+
partitionKey: string;
|
|
348
|
+
/** Calendar day of the flush, `YYYY-MM-DD`. */
|
|
349
|
+
date: string;
|
|
350
|
+
/** Synthetic type, e.g. `embedding:index-sync`. */
|
|
351
|
+
workflowType: string;
|
|
352
|
+
keySource: string;
|
|
353
|
+
inputTokens: number;
|
|
354
|
+
estimatedCostMicros: number;
|
|
355
|
+
}
|
|
356
|
+
/** Current-window usage snapshot for a scope. */
|
|
357
|
+
interface CurrentQuotaUsage {
|
|
358
|
+
today: {
|
|
359
|
+
workflowCount: number;
|
|
360
|
+
};
|
|
361
|
+
thisMonth: {
|
|
362
|
+
workflowCount: number;
|
|
363
|
+
};
|
|
364
|
+
running: {
|
|
365
|
+
count: number;
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
/** Expected error value from aggregation reads/writes. Extends flow's structural error. */
|
|
369
|
+
interface AiUsageError {
|
|
370
|
+
key: 'ai_usage_error';
|
|
371
|
+
message: string;
|
|
372
|
+
}
|
|
373
|
+
interface CreateAiUsageAggregationServiceDeps {
|
|
374
|
+
store: AiUsageStore;
|
|
375
|
+
/** Clock injection for the current-window computation (tests). Defaults to `() => new Date()`. */
|
|
376
|
+
now?: () => Date;
|
|
377
|
+
/** Optional logger for write failures. Defaults to a no-op. */
|
|
378
|
+
logger?: Logger;
|
|
379
|
+
}
|
|
380
|
+
interface AiUsageAggregationService {
|
|
381
|
+
/** Roll a completed LLM workflow's totals into the daily aggregate (UPSERT +1). */
|
|
382
|
+
recordWorkflowCompletion(data: WorkflowUsageInput): Promise<Result<void, AiUsageError>>;
|
|
383
|
+
/** Roll a flushed embedding batch into the daily aggregate (output/cache tokens = 0). */
|
|
384
|
+
recordEmbeddingUsage(data: EmbeddingUsageInput): Promise<Result<void, AiUsageError>>;
|
|
385
|
+
/** Per-day usage totals over an inclusive date range. */
|
|
386
|
+
getUsageSummary(params: AiUsageRangeQuery): Promise<Result<UsageSummaryRow[], AiUsageError>>;
|
|
387
|
+
/** Per-(type, keySource) usage totals over an inclusive date range. */
|
|
388
|
+
getUsageByWorkflowType(params: AiUsageRangeQuery): Promise<Result<UsageByTypeRow[], AiUsageError>>;
|
|
389
|
+
/** Today's / this-month's workflow counts and the current running count. */
|
|
390
|
+
getCurrentQuotaUsage(params: {
|
|
391
|
+
partitionKey: string;
|
|
392
|
+
}): Promise<Result<CurrentQuotaUsage, AiUsageError>>;
|
|
393
|
+
}
|
|
394
|
+
/** Build a store-agnostic AI usage-aggregation service. */
|
|
395
|
+
declare function createAiUsageAggregationService(deps: CreateAiUsageAggregationServiceDeps): AiUsageAggregationService;
|
|
396
|
+
//#endregion
|
|
397
|
+
export { AccumulatedUsage, AiContext, AiModelResolver, AiQuotaConfig, AiQuotaConfigResolver, AiQuotaExceededError, AiQuotaExceededReason, AiQuotaPolicy, AiQuotaService, AiQuotaStore, AiTypedStep, AiUsageAggregationService, AiUsageCountQuery, AiUsageError, AiUsageRangeQuery, AiUsageRecorder, AiUsageStore, CostEstimator, CostEstimatorOptions, CreateAiQuotaServiceDeps, CreateAiUsageAggregationServiceDeps, CreateAiWorkflowHooksDeps, CurrentQuotaUsage, DEFAULT_AI_QUOTA, DEFAULT_MODEL_PRICING, DailyUsageDelta, EmbeddingAccumulatedUsage, EmbeddingUsageAccumulator, EmbeddingUsageInput, ModelPricing, TokenUsage, UsageAccumulator, UsageByTypeRow, UsageSummaryRow, WorkflowUsageInput, buildAiWorkflow, createAiQuotaService, createAiUsageAggregationService, createAiWorkflowHooks, createCostEstimator, createEmbeddingUsageAccumulator, createInstrumentedEmbeddingModel, createInstrumentedModel, createUsageAccumulator, defineAiStep, estimateCostMicros };
|