@voltro/ai 0.29.0 → 0.30.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/CHANGELOG.md +377 -0
- package/THIRD-PARTY-NOTICES.md +63 -1
- package/dist/index.d.ts +185 -0
- package/dist/index.js +474 -664
- package/dist/inferenceQueue-B25RTJZ4.js +447 -0
- package/dist/workflow.d.ts +304 -0
- package/dist/workflow.js +153 -0
- package/package.json +10 -4
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { QueryDescriptor } from '@voltro/database';
|
|
|
16
16
|
import { QueryProcedureDescriptor } from '@voltro/protocol';
|
|
17
17
|
import { Runtime } from 'effect';
|
|
18
18
|
import { Schema } from 'effect';
|
|
19
|
+
import { SchemaTable } from '@voltro/database';
|
|
19
20
|
import { SemanticCacheShape } from '@voltro/cache';
|
|
20
21
|
import { simulateStreamingMiddleware } from 'ai';
|
|
21
22
|
import { SpeechModelV4 } from '@ai-sdk/provider';
|
|
@@ -231,6 +232,8 @@ export declare const agentThreadsTable: Table<typeof AGENT_THREADS_TABLE, Record
|
|
|
231
232
|
|
|
232
233
|
export declare const AI_BUDGET_TABLE = "_voltro_ai_budget";
|
|
233
234
|
|
|
235
|
+
export declare const AI_INFERENCES_TABLE = "_voltro_ai_inferences";
|
|
236
|
+
|
|
234
237
|
export declare const AI_USAGE_TABLE = "_voltro_ai_usage";
|
|
235
238
|
|
|
236
239
|
/** Thrown when an AI call would push a tenant over its USD budget. */
|
|
@@ -299,6 +302,15 @@ declare const AiError_base: Schema.TaggedErrorClass<AiError, "AiError", {
|
|
|
299
302
|
message: typeof Schema.String;
|
|
300
303
|
}>;
|
|
301
304
|
|
|
305
|
+
/**
|
|
306
|
+
* One offloaded model call.
|
|
307
|
+
*
|
|
308
|
+
* The row IS the wait. A run parked on `awaitSignalSuspending` holds nothing;
|
|
309
|
+
* everything needed to perform the call, resume the right run, and explain the
|
|
310
|
+
* outcome afterwards is here.
|
|
311
|
+
*/
|
|
312
|
+
export declare const aiInferencesTable: SchemaTable;
|
|
313
|
+
|
|
302
314
|
/** Provider-specific knobs forwarded verbatim to the Vercel AI SDK's
|
|
303
315
|
* `providerOptions` on generateText / streamText / generateObject. The outer
|
|
304
316
|
* key is the provider id, the inner record its options. The headline use is
|
|
@@ -653,6 +665,38 @@ export declare interface DataCopilotDeps {
|
|
|
653
665
|
*/
|
|
654
666
|
export declare const dataStoreResumableStreamStore: (store: DataStore) => ResumableStreamStore;
|
|
655
667
|
|
|
668
|
+
export declare const decideInferenceFailure: (input: {
|
|
669
|
+
readonly attempts: number;
|
|
670
|
+
readonly maxAttempts: number;
|
|
671
|
+
readonly baseDelayMs: number;
|
|
672
|
+
readonly maxDelayMs: number;
|
|
673
|
+
/** Milliseconds the provider itself asked us to wait, when it said so. */
|
|
674
|
+
readonly retryAfterMs?: number | undefined;
|
|
675
|
+
}) => InferenceFailureAction;
|
|
676
|
+
|
|
677
|
+
/** Attempts before a queued call is reported as failed to its waiting run. */
|
|
678
|
+
export declare const DEFAULT_INFERENCE_ATTEMPTS = 4;
|
|
679
|
+
|
|
680
|
+
/** How many queued calls one dispatcher performs concurrently.
|
|
681
|
+
*
|
|
682
|
+
* This is the number offloading exists to make explicit: inline, the ceiling
|
|
683
|
+
* is "however many runs happen to be waiting". Here it is declared, and it is
|
|
684
|
+
* the knob to turn when a provider starts rate-limiting. */
|
|
685
|
+
export declare const DEFAULT_INFERENCE_CONCURRENCY = 4;
|
|
686
|
+
|
|
687
|
+
/** How long a dispatcher's claim survives with nothing completing it.
|
|
688
|
+
*
|
|
689
|
+
* Generous relative to a model call, for the asymmetry the admission lease
|
|
690
|
+
* documents: reclaiming early performs a paid call twice, reclaiming late
|
|
691
|
+
* delays one call. */
|
|
692
|
+
export declare const DEFAULT_INFERENCE_LEASE_MS: number;
|
|
693
|
+
|
|
694
|
+
/** How often the dispatcher looks for work. Fast, because it sits directly in
|
|
695
|
+
* the latency of every offloaded call — a suspend/resume round trip already
|
|
696
|
+
* costs one engine wake, and there is no reason to add a second of polling on
|
|
697
|
+
* top of it. */
|
|
698
|
+
export declare const DEFAULT_INFERENCE_POLL_MS = 250;
|
|
699
|
+
|
|
656
700
|
declare const DEFAULT_INPUT: Schema.Struct<{
|
|
657
701
|
prompt: typeof Schema.String;
|
|
658
702
|
}>;
|
|
@@ -739,6 +783,15 @@ export declare const defineTool: <A, I, O>(def: {
|
|
|
739
783
|
readonly timeoutMs?: number;
|
|
740
784
|
}) => AnyTool;
|
|
741
785
|
|
|
786
|
+
/**
|
|
787
|
+
* One dispatch tick. Never throws.
|
|
788
|
+
*
|
|
789
|
+
* A tick that threw would stop every offloaded call in the deployment until
|
|
790
|
+
* somebody noticed, and every run parked on one would sit there. Failures are
|
|
791
|
+
* collected and reported.
|
|
792
|
+
*/
|
|
793
|
+
export declare const dispatchInferences: (deps: InferenceDispatchDeps, options?: InferenceDispatchOptions) => Promise<InferenceDispatchResult>;
|
|
794
|
+
|
|
742
795
|
/**
|
|
743
796
|
* Embed a single string to a vector. Returns the embedding through Effect's
|
|
744
797
|
* success channel; provider failures surface as a typed
|
|
@@ -1005,6 +1058,30 @@ export declare interface GenerateImageResult {
|
|
|
1005
1058
|
|
|
1006
1059
|
export declare const generateObject: <A, I>(options: GenerateObjectOptions<A, I>) => Effect.Effect<GenerateObjectResult<A>, AiError>;
|
|
1007
1060
|
|
|
1061
|
+
/**
|
|
1062
|
+
* Structured output against an already-rendered JSON Schema, WITHOUT the decode
|
|
1063
|
+
* step.
|
|
1064
|
+
*
|
|
1065
|
+
* Extracted from `generateObject` rather than written beside it: an offloaded
|
|
1066
|
+
* inference is performed by a dispatcher that has the stored JSON Schema and no
|
|
1067
|
+
* access to the caller's Effect Schema (a closure cannot be journaled), and the
|
|
1068
|
+
* awaiting workflow decodes on resume. Two implementations of "ask the model for
|
|
1069
|
+
* JSON matching this shape" would have been two sets of provider-option
|
|
1070
|
+
* handling, fallback behaviour and span attributes.
|
|
1071
|
+
*/
|
|
1072
|
+
export declare const generateObjectJson: (options: GenerateObjectJsonOptions) => Effect.Effect<GenerateObjectResult<unknown>, AiError>;
|
|
1073
|
+
|
|
1074
|
+
export declare interface GenerateObjectJsonOptions {
|
|
1075
|
+
/** A JSON Schema, already rendered. */
|
|
1076
|
+
readonly jsonSchema: Record<string, unknown>;
|
|
1077
|
+
readonly prompt: string;
|
|
1078
|
+
readonly system?: string;
|
|
1079
|
+
readonly provider?: ProviderConfig;
|
|
1080
|
+
readonly fallbacks?: ProviderFallbacks;
|
|
1081
|
+
readonly maxTokens?: number;
|
|
1082
|
+
readonly providerOptions?: AiProviderOptions;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1008
1085
|
export declare interface GenerateObjectOptions<A, I> {
|
|
1009
1086
|
/** Effect Schema the model output must satisfy. Converted to JSON
|
|
1010
1087
|
* Schema for the SDK, then decoded back through this schema so the
|
|
@@ -1245,6 +1322,74 @@ export declare const hashToVector: (text: string, dim: number) => number[];
|
|
|
1245
1322
|
*/
|
|
1246
1323
|
export declare const historyToModelMessages: (history: ReadonlyArray<AgentMessage>) => ModelMessage[];
|
|
1247
1324
|
|
|
1325
|
+
export declare interface InferenceDispatchDeps {
|
|
1326
|
+
readonly store: DataStore;
|
|
1327
|
+
/**
|
|
1328
|
+
* Resume the parked run with the call's outcome.
|
|
1329
|
+
*
|
|
1330
|
+
* MUST be idempotent — completing an already-resolved durable deferred is a
|
|
1331
|
+
* no-op, which is what makes the perform → resume → mark ordering safe.
|
|
1332
|
+
*/
|
|
1333
|
+
readonly resume: (input: {
|
|
1334
|
+
readonly executionId: string;
|
|
1335
|
+
readonly workflowName: string;
|
|
1336
|
+
readonly signalName: string;
|
|
1337
|
+
readonly payload: unknown;
|
|
1338
|
+
}) => Promise<void>;
|
|
1339
|
+
/** Runs an `@voltro/ai` Effect. Injected so this module needs no runtime. */
|
|
1340
|
+
readonly run: <A>(effect: Effect.Effect<A, unknown>) => Promise<A>;
|
|
1341
|
+
readonly now?: () => number;
|
|
1342
|
+
readonly replicaId?: string;
|
|
1343
|
+
readonly log?: {
|
|
1344
|
+
readonly info: (message: string, meta?: Record<string, unknown>) => void;
|
|
1345
|
+
readonly warn: (message: string, meta?: Record<string, unknown>) => void;
|
|
1346
|
+
};
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
export declare interface InferenceDispatchOptions {
|
|
1350
|
+
readonly batch?: number;
|
|
1351
|
+
readonly concurrency?: number;
|
|
1352
|
+
readonly leaseMs?: number;
|
|
1353
|
+
readonly maxAttempts?: number;
|
|
1354
|
+
readonly baseDelayMs?: number;
|
|
1355
|
+
readonly maxDelayMs?: number;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
export declare interface InferenceDispatchResult {
|
|
1359
|
+
/** `false` when nothing was claimed AND nothing was waiting — so an empty
|
|
1360
|
+
* tick and a tick that could not read are never the same report. */
|
|
1361
|
+
readonly examined: boolean;
|
|
1362
|
+
readonly claimed: number;
|
|
1363
|
+
readonly succeeded: number;
|
|
1364
|
+
readonly failed: number;
|
|
1365
|
+
readonly retried: number;
|
|
1366
|
+
readonly reclaimed: number;
|
|
1367
|
+
readonly failures: ReadonlyArray<{
|
|
1368
|
+
readonly id: string;
|
|
1369
|
+
readonly detail: string;
|
|
1370
|
+
}>;
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
/**
|
|
1374
|
+
* What the dispatcher should do with a call that just failed.
|
|
1375
|
+
*
|
|
1376
|
+
* PURE, and separated for the usual reason: the interesting cases here are
|
|
1377
|
+
* "when do we give up" and "does the waiting run learn about it", and neither
|
|
1378
|
+
* needs a store, a clock or a provider to decide.
|
|
1379
|
+
*/
|
|
1380
|
+
export declare type InferenceFailureAction = {
|
|
1381
|
+
readonly kind: 'retry';
|
|
1382
|
+
readonly attempts: number;
|
|
1383
|
+
readonly delayMs: number;
|
|
1384
|
+
} | {
|
|
1385
|
+
readonly kind: 'give-up';
|
|
1386
|
+
readonly attempts: number;
|
|
1387
|
+
};
|
|
1388
|
+
|
|
1389
|
+
/** The signal name a parked run awaits for one queued call. Derived from the
|
|
1390
|
+
* row id, so the run and the dispatcher agree without sharing anything. */
|
|
1391
|
+
export declare const inferenceSignalName: (inferenceId: string) => string;
|
|
1392
|
+
|
|
1248
1393
|
/** Discovery predicate for `*.agent.tsx` exports. */
|
|
1249
1394
|
export declare const isAgentDescriptor: (x: unknown) => x is AnyAgentDescriptor;
|
|
1250
1395
|
|
|
@@ -1454,8 +1599,26 @@ export declare const modelPricing: () => Record<string, ModelPrice>;
|
|
|
1454
1599
|
*/
|
|
1455
1600
|
export declare const observeStream: (attributes: AiCallAttributes, stream: Stream.Stream<AgentEvent>) => Stream.Stream<AgentEvent>;
|
|
1456
1601
|
|
|
1602
|
+
/**
|
|
1603
|
+
* The DETERMINISTIC row id for an offloaded call.
|
|
1604
|
+
*
|
|
1605
|
+
* Keyed on the execution + step, not on a generated id, so a replay that
|
|
1606
|
+
* reaches the enqueue before the first attempt's journal entry is durable
|
|
1607
|
+
* cannot queue — and pay for — the same call twice. `insertIgnore` on this id
|
|
1608
|
+
* is what makes the enqueue idempotent.
|
|
1609
|
+
*
|
|
1610
|
+
* Hashed for LENGTH, exactly like `pendingSlotId`: `id()` is VARCHAR(64) on
|
|
1611
|
+
* MySQL/MariaDB and a step name is app-chosen text.
|
|
1612
|
+
*/
|
|
1613
|
+
export declare const offloadedInferenceId: (executionId: string, stepName: string) => string;
|
|
1614
|
+
|
|
1457
1615
|
export declare type OpenAIModel = 'gpt-5.5' | 'gpt-4o' | 'gpt-4o-mini' | (string & {});
|
|
1458
1616
|
|
|
1617
|
+
/** The JSON Schema a `generateObject` output schema renders to. Exported
|
|
1618
|
+
* because an OFFLOADED inference has to store it: a JavaScript Schema object
|
|
1619
|
+
* cannot be journaled, and its JSON rendering can. */
|
|
1620
|
+
export declare const outputJsonSchema: (schema: Schema.Schema.Any, fn: string) => Effect.Effect<Record<string, unknown>, AiError>;
|
|
1621
|
+
|
|
1459
1622
|
/** Does this tag pass the allow/deny policy? deny wins; allow (when set) gates. */
|
|
1460
1623
|
export declare const passesPolicy: (tag: string, policy: AppToolPolicy) => boolean;
|
|
1461
1624
|
|
|
@@ -1572,6 +1735,26 @@ export declare interface QueryableStore {
|
|
|
1572
1735
|
} & Record<string, unknown>): Promise<ReadonlyArray<Record<string, unknown>>>;
|
|
1573
1736
|
}
|
|
1574
1737
|
|
|
1738
|
+
/** A queued call in domain shape. */
|
|
1739
|
+
export declare interface QueuedInference {
|
|
1740
|
+
readonly id: string;
|
|
1741
|
+
readonly tenantId: string | null;
|
|
1742
|
+
readonly executionId: string;
|
|
1743
|
+
readonly workflowName: string;
|
|
1744
|
+
readonly runId: string | null;
|
|
1745
|
+
readonly signalName: string;
|
|
1746
|
+
readonly stepName: string;
|
|
1747
|
+
readonly kind: 'text' | 'object';
|
|
1748
|
+
readonly provider: string;
|
|
1749
|
+
readonly model: string;
|
|
1750
|
+
readonly prompt: string;
|
|
1751
|
+
readonly system: string | null;
|
|
1752
|
+
readonly maxTokens: number | null;
|
|
1753
|
+
readonly providerOptions: unknown;
|
|
1754
|
+
readonly jsonSchema: Record<string, unknown> | null;
|
|
1755
|
+
readonly attempts: number;
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1575
1758
|
/** A store wrapper that records the dependency set of everything read through
|
|
1576
1759
|
* it — the provenance the semantic cache tags entries with. */
|
|
1577
1760
|
export declare interface ReadRecorder<S extends QueryableStore> {
|
|
@@ -2244,6 +2427,8 @@ export declare interface ToolDef<A, I, O> {
|
|
|
2244
2427
|
* a Promise; `buildSdkTools` normalises both. */
|
|
2245
2428
|
export declare type ToolHandler<A, O> = (input: A, ctx: ToolContext) => Effect.Effect<O, never, unknown> | Promise<O>;
|
|
2246
2429
|
|
|
2430
|
+
export declare const toQueuedInference: (row: Record<string, unknown>) => QueuedInference;
|
|
2431
|
+
|
|
2247
2432
|
/**
|
|
2248
2433
|
* Drop a stream's controller. `streamText` calls this in its finaliser when the
|
|
2249
2434
|
* stream ends — success, error, cancel, or consumer interrupt. Idempotent.
|