@voltro/ai 0.63.0 → 0.65.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 +157 -0
- package/dist/agent.d.ts +54 -3
- package/dist/agent.js +2 -2
- package/dist/agentDescriptor-DuxvWGDi.js +63 -0
- package/dist/index.d.ts +113 -16
- package/dist/index.js +424 -381
- package/dist/{inferenceQueue-CS1VouiW.js → inferenceQueue-BS3PVSkk.js} +85 -74
- package/dist/{provider-BOgeCRkg.js → provider-RA0getTL.js} +9 -2
- package/dist/test.js +13 -13
- package/dist/workflow.d.ts +56 -0
- package/dist/workflow.js +115 -101
- package/package.json +5 -5
- package/dist/agentDescriptor-Bv-ikWax.js +0 -46
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { EmbeddingModelV4 } from '@ai-sdk/provider';
|
|
|
8
8
|
import { Experimental_VideoModelV4 } from '@ai-sdk/provider';
|
|
9
9
|
import { extractReasoningMiddleware } from 'ai';
|
|
10
10
|
import { GatewayLanguageModelEntry } from '@ai-sdk/gateway';
|
|
11
|
+
import { Guards } from '@voltro/protocol';
|
|
11
12
|
import { ImageModelV4 } from '@ai-sdk/provider';
|
|
12
13
|
import { LanguageModelMiddleware } from 'ai';
|
|
13
14
|
import { LanguageModelV4 } from '@ai-sdk/provider';
|
|
@@ -37,6 +38,31 @@ export declare const AGENT_MESSAGES_TABLE = "_voltro_agent_messages";
|
|
|
37
38
|
/** Thread metadata table (one row per conversation). */
|
|
38
39
|
export declare const AGENT_THREADS_TABLE = "_voltro_agent_threads";
|
|
39
40
|
|
|
41
|
+
/**
|
|
42
|
+
* WHO MAY TALK TO an agent — the same three-state decision a mutation makes,
|
|
43
|
+
* applied to BOTH synthesized routes (`<name>.send` and `<name>.messages`).
|
|
44
|
+
*
|
|
45
|
+
* The two routes used to carry a hard-coded `openAccess`, honestly worded:
|
|
46
|
+
* "serves any session this app authenticates; defineAgent declares no per-agent
|
|
47
|
+
* guard vocabulary today". That sentence made every agent a free model-spend
|
|
48
|
+
* surface for anyone who could open the socket — anonymous included, since the
|
|
49
|
+
* routes never looked at the subject — and it made the boot gate's carve-out
|
|
50
|
+
* ("synthesized routes are not the app's to guard") true only because there
|
|
51
|
+
* was nothing on the descriptor to read. There is now, so the gate judges an
|
|
52
|
+
* agent like a workflow: one that declares neither refuses the boot under
|
|
53
|
+
* `security.defaultDeny`.
|
|
54
|
+
*/
|
|
55
|
+
export declare interface AgentAccessOptions {
|
|
56
|
+
/** A caller must hold a scope (`{ scope: 'support:chat' }`), or a
|
|
57
|
+
* relationship to the thread (`{ action, resourceType, resource: (i) =>
|
|
58
|
+
* i.threadId }`). Checked on every `send` and on every `messages` delivery. */
|
|
59
|
+
readonly guards?: Guards<AgentRouteInput>;
|
|
60
|
+
/** Anyone who can open the socket may talk to it — and WHY. A reason, not a
|
|
61
|
+
* boolean. Note what it does NOT buy: an anonymous caller owns no thread, so
|
|
62
|
+
* thread privacy (below) is only enforced for authenticated subjects. */
|
|
63
|
+
readonly openAccess?: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
40
66
|
/** Stamp an agent-initiated call's actor with `via: 'agent'` so audit + trace
|
|
41
67
|
* + provenance (08) can distinguish "user X" from "user X via agent". The
|
|
42
68
|
* actor id stays the calling subject's — the agent never escalates identity. */
|
|
@@ -52,6 +78,9 @@ export declare interface AgentDescriptor<S extends Schema.Schema.Any = DefaultAg
|
|
|
52
78
|
/** Input schema (default `{ prompt: string }`). The send route's wire input
|
|
53
79
|
* extends this with `{ threadId, order }`. */
|
|
54
80
|
readonly input?: S;
|
|
81
|
+
/** WHO MAY TALK TO IT — see {@link AgentAccessOptions}. */
|
|
82
|
+
readonly guards?: Guards<AgentRouteInput>;
|
|
83
|
+
readonly openAccess?: string;
|
|
55
84
|
}
|
|
56
85
|
|
|
57
86
|
/** Error taxonomy. `retryable` on the event drives client/agent retry. */
|
|
@@ -201,7 +230,7 @@ export declare const agentMessagesTable: Table<typeof AGENT_MESSAGES_TABLE, Reco
|
|
|
201
230
|
export declare const agentRouteDescriptors: (desc: AnyAgentDescriptor) => {
|
|
202
231
|
send: ActionProcedureDescriptor<`${string}.send`, Schema.Schema.Any, Schema.Struct<{
|
|
203
232
|
text: typeof Schema.String;
|
|
204
|
-
}>, typeof
|
|
233
|
+
}>, typeof AgentThreadAccessDenied>;
|
|
205
234
|
messages: QueryProcedureDescriptor<`${string}.messages`, Schema.Struct<{
|
|
206
235
|
threadId: typeof Schema.String;
|
|
207
236
|
}>, Schema.Array$<Schema.Struct<{
|
|
@@ -218,17 +247,40 @@ export declare const agentRouteDescriptors: (desc: AnyAgentDescriptor) => {
|
|
|
218
247
|
readonly key: typeof Schema.String;
|
|
219
248
|
readonly value: typeof Schema.Unknown;
|
|
220
249
|
}]>>;
|
|
221
|
-
}>>, typeof
|
|
250
|
+
}>>, typeof AgentThreadAccessDenied>;
|
|
222
251
|
};
|
|
223
252
|
|
|
253
|
+
/** The one field both synthesized routes share on the wire — what a
|
|
254
|
+
* resource-scoped agent guard may read its id from. */
|
|
255
|
+
export declare interface AgentRouteInput {
|
|
256
|
+
readonly threadId: string;
|
|
257
|
+
}
|
|
258
|
+
|
|
224
259
|
export declare interface AgentThread {
|
|
225
260
|
readonly id: string;
|
|
226
261
|
readonly tenantId: string | null;
|
|
262
|
+
readonly subjectId: string | null;
|
|
227
263
|
readonly title: string | null;
|
|
228
264
|
readonly createdAt: Date;
|
|
229
265
|
readonly updatedAt: Date;
|
|
230
266
|
}
|
|
231
267
|
|
|
268
|
+
/**
|
|
269
|
+
* A thread belongs to the subject that opened it. Raised by `<name>.send` and
|
|
270
|
+
* `<name>.messages` when an authenticated caller addresses a thread another
|
|
271
|
+
* subject created — the isolation the old `openAccess` sentence said it could
|
|
272
|
+
* not claim. In the routes' error union, so it reaches the client typed.
|
|
273
|
+
*/
|
|
274
|
+
export declare class AgentThreadAccessDenied extends AgentThreadAccessDenied_base {
|
|
275
|
+
get message(): string;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
declare const AgentThreadAccessDenied_base: Schema.TaggedErrorClass<AgentThreadAccessDenied, "AgentThreadAccessDenied", {
|
|
279
|
+
readonly _tag: Schema.tag<"AgentThreadAccessDenied">;
|
|
280
|
+
} & {
|
|
281
|
+
threadId: typeof Schema.String;
|
|
282
|
+
}>;
|
|
283
|
+
|
|
232
284
|
export declare const agentThreadsTable: Table<typeof AGENT_THREADS_TABLE, Record<string, ColumnDefinition<unknown>>, true>;
|
|
233
285
|
|
|
234
286
|
export declare const AI_BUDGET_TABLE = "_voltro_ai_budget";
|
|
@@ -745,6 +797,7 @@ export declare interface CostBreakdown {
|
|
|
745
797
|
/** Open a new thread (the store generates the id). */
|
|
746
798
|
export declare const createThread: (store: DataStore, input?: {
|
|
747
799
|
readonly tenantId?: string | null;
|
|
800
|
+
readonly subjectId?: string | null;
|
|
748
801
|
readonly title?: string | null;
|
|
749
802
|
}) => Effect.Effect<AgentThread>;
|
|
750
803
|
|
|
@@ -880,7 +933,7 @@ export { defaultSettingsMiddleware }
|
|
|
880
933
|
export declare const defineAgent: <S extends Schema.Schema.Any = DefaultAgentInputSchema>(config: {
|
|
881
934
|
readonly name: string;
|
|
882
935
|
readonly input?: S;
|
|
883
|
-
}) => AgentDescriptor<S>;
|
|
936
|
+
} & AgentAccessOptions) => AgentDescriptor<S>;
|
|
884
937
|
|
|
885
938
|
/**
|
|
886
939
|
* Bind a server executor to its descriptor. Default-export the result from
|
|
@@ -1018,6 +1071,24 @@ export declare type EmbeddingProviderName = 'mock' | 'openai' | 'voyage' | 'cohe
|
|
|
1018
1071
|
*/
|
|
1019
1072
|
export declare const embedMany: (texts: ReadonlyArray<string>, config?: EmbeddingProviderConfig) => Effect.Effect<ReadonlyArray<ReadonlyArray<number>>, AiError>;
|
|
1020
1073
|
|
|
1074
|
+
/**
|
|
1075
|
+
* The ownership rule, in one place for both synthesized routes.
|
|
1076
|
+
*
|
|
1077
|
+
* `threadId` is caller-supplied, so the first message on an id is what opens
|
|
1078
|
+
* the thread: the row is created then, owned by the caller. Every later call
|
|
1079
|
+
* on that id compares owners — a thread with an owner refuses every OTHER
|
|
1080
|
+
* authenticated subject with `AgentThreadAccessDenied`; a thread with none
|
|
1081
|
+
* (opened anonymously, or before ownership existed) admits anyone, because a
|
|
1082
|
+
* row that records no owner cannot honestly claim one.
|
|
1083
|
+
*
|
|
1084
|
+
* Returns the thread. Never a silent `null`: a refusal is the typed error.
|
|
1085
|
+
*/
|
|
1086
|
+
export declare const ensureThreadOwned: (store: DataStore, input: {
|
|
1087
|
+
readonly threadId: string;
|
|
1088
|
+
readonly subjectId: string | null;
|
|
1089
|
+
readonly tenantId?: string | null;
|
|
1090
|
+
}) => Effect.Effect<AgentThread, AgentThreadAccessDenied>;
|
|
1091
|
+
|
|
1021
1092
|
/**
|
|
1022
1093
|
* Derive a USD cost from a token `usage` tally + a model price. An
|
|
1023
1094
|
* unknown model (or the `mock` provider) resolves to zero cost rather
|
|
@@ -1462,6 +1533,14 @@ export declare interface GenerateSpeechResult {
|
|
|
1462
1533
|
export declare const generateText: (options: GenerateTextOptions) => Effect.Effect<GenerateTextResult, AiError>;
|
|
1463
1534
|
|
|
1464
1535
|
export declare interface GenerateTextOptions {
|
|
1536
|
+
/** Tools the model may call on the way to its answer — the same tool-loop
|
|
1537
|
+
* `generateObjectWithTools` runs, for a TEXT result. With tools, `usage` is
|
|
1538
|
+
* the SUM over every step, so a usage row records the whole loop. */
|
|
1539
|
+
readonly tools?: Record<string, AnyTool>;
|
|
1540
|
+
/** Max LLM↔tool round-trips before the model must answer. Default 8. */
|
|
1541
|
+
readonly maxSteps?: number;
|
|
1542
|
+
/** Request context threaded into the tool executors. */
|
|
1543
|
+
readonly toolContext?: ToolContext;
|
|
1465
1544
|
/** The user prompt. The SDK auto-wraps it as the single user message. */
|
|
1466
1545
|
readonly prompt: string;
|
|
1467
1546
|
/** Optional system message. Steers the model independently of the prompt. */
|
|
@@ -1746,8 +1825,14 @@ export declare const knowledgeCutoffOf: (raw: RawGatewayModel) => string | undef
|
|
|
1746
1825
|
*/
|
|
1747
1826
|
export declare const llmJudge: EvalJudge;
|
|
1748
1827
|
|
|
1749
|
-
/**
|
|
1750
|
-
|
|
1828
|
+
/**
|
|
1829
|
+
* The synthesized `<name>.messages` body — load the thread's messages, for the
|
|
1830
|
+
* subject that owns the thread. Same rule as `send`: an owned thread refuses
|
|
1831
|
+
* every other authenticated subject; an unknown or unowned thread reads as
|
|
1832
|
+
* its rows (empty, for an id nobody has written to). Re-checked on every
|
|
1833
|
+
* reactive delivery, since the query re-runs its executor.
|
|
1834
|
+
*/
|
|
1835
|
+
export declare const loadAgentMessages: (store: DataStore, threadId: string, subjectId?: string | null) => Effect.Effect<ReadonlyArray<AgentMessage>, AgentThreadAccessDenied>;
|
|
1751
1836
|
|
|
1752
1837
|
/**
|
|
1753
1838
|
* A middleware that logs every generate/stream call's model (and token usage
|
|
@@ -2490,18 +2575,14 @@ export declare type ProviderConfig = {
|
|
|
2490
2575
|
*/
|
|
2491
2576
|
export declare type ProviderFallbacks = ReadonlyArray<ProviderConfig>;
|
|
2492
2577
|
|
|
2578
|
+
export declare const providerFromEnv: (env?: Record<string, string | undefined>) => ProviderConfig;
|
|
2579
|
+
|
|
2493
2580
|
/**
|
|
2494
|
-
*
|
|
2495
|
-
*
|
|
2496
|
-
*
|
|
2497
|
-
* AI_MODEL=<model-id> (default per provider: 'claude-opus-4-8' for
|
|
2498
|
-
* anthropic, 'gpt-5.5' for openai, 'mock' for mock;
|
|
2499
|
-
* REQUIRED for gateway — a `creator/model` id)
|
|
2500
|
-
*
|
|
2501
|
-
* Provider keys are read by the underlying AI SDK packages from their standard
|
|
2502
|
-
* env vars: ANTHROPIC_API_KEY, OPENAI_API_KEY, AI_GATEWAY_API_KEY.
|
|
2581
|
+
* The env var a provider's SDK reads its key from — `undefined` for `mock`,
|
|
2582
|
+
* which needs none. ONE map, exported, so the boot gate that checks a key is
|
|
2583
|
+
* present cannot drift from the provider that reads it.
|
|
2503
2584
|
*/
|
|
2504
|
-
export declare const
|
|
2585
|
+
export declare const providerKeyEnvVar: (name: string) => string | undefined;
|
|
2505
2586
|
|
|
2506
2587
|
export declare type ProviderName = 'mock' | 'anthropic' | 'openai' | 'gateway';
|
|
2507
2588
|
|
|
@@ -2989,11 +3070,15 @@ export declare const runAgentTurn: (exec: AnyAgentExecutor, store: DataStore, ar
|
|
|
2989
3070
|
readonly threadId: string;
|
|
2990
3071
|
readonly input: unknown;
|
|
2991
3072
|
readonly tenantId?: string | null;
|
|
3073
|
+
/** The caller — `null` for an anonymous subject. Opens the thread on its
|
|
3074
|
+
* first message and is checked against the thread's owner on every later
|
|
3075
|
+
* one (`ensureThreadOwned`). Omitted ⇒ treated as anonymous. */
|
|
3076
|
+
readonly subjectId?: string | null;
|
|
2992
3077
|
readonly order: number;
|
|
2993
3078
|
readonly toolContext?: ToolContext;
|
|
2994
3079
|
readonly throttleMs?: number;
|
|
2995
3080
|
readonly promptOf?: (input: unknown) => string;
|
|
2996
|
-
}) => Effect.Effect<string, Error>;
|
|
3081
|
+
}) => Effect.Effect<string, Error | AgentThreadAccessDenied>;
|
|
2997
3082
|
|
|
2998
3083
|
/**
|
|
2999
3084
|
* Drive a streaming assistant turn end-to-end against the persisted row.
|
|
@@ -3028,6 +3113,18 @@ export declare interface RunAssistantInput {
|
|
|
3028
3113
|
readonly order: number;
|
|
3029
3114
|
/** Throttle window for the live `parts` patch. Default 100ms. */
|
|
3030
3115
|
readonly throttleMs?: number;
|
|
3116
|
+
/** The agent this turn belongs to — stamped onto the usage ledger row so
|
|
3117
|
+
* spend is attributable per agent. The synthesized send passes its name. */
|
|
3118
|
+
readonly agent?: string;
|
|
3119
|
+
/**
|
|
3120
|
+
* Record the turn's token usage into `_voltro_ai_usage` (default `true`).
|
|
3121
|
+
* A tool loop is a model call like any other, and this was the one path
|
|
3122
|
+
* that spent without recording: `aiStep` records, and the agent turn — which
|
|
3123
|
+
* owns a store by construction — wrote nothing, so an app whose model sites
|
|
3124
|
+
* are mostly tool loops could show zero spend. `false` for a caller that
|
|
3125
|
+
* records elsewhere.
|
|
3126
|
+
*/
|
|
3127
|
+
readonly recordUsage?: boolean;
|
|
3031
3128
|
}
|
|
3032
3129
|
|
|
3033
3130
|
/**
|