@venturekit-pro/ai 0.0.47 → 0.0.50
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 +192 -0
- package/dist/agent-loop/index.d.ts +9 -0
- package/dist/agent-loop/index.d.ts.map +1 -0
- package/dist/agent-loop/index.js +7 -0
- package/dist/agent-loop/index.js.map +1 -0
- package/dist/agent-loop/registry.d.ts +85 -0
- package/dist/agent-loop/registry.d.ts.map +1 -0
- package/dist/agent-loop/registry.js +100 -0
- package/dist/agent-loop/registry.js.map +1 -0
- package/dist/agent-loop/run-agent.d.ts +37 -0
- package/dist/agent-loop/run-agent.d.ts.map +1 -0
- package/dist/agent-loop/run-agent.js +405 -0
- package/dist/agent-loop/run-agent.js.map +1 -0
- package/dist/agent-loop/tools.d.ts +10 -0
- package/dist/agent-loop/tools.d.ts.map +1 -0
- package/dist/agent-loop/tools.js +28 -0
- package/dist/agent-loop/tools.js.map +1 -0
- package/dist/agent-loop/types.d.ts +175 -0
- package/dist/agent-loop/types.d.ts.map +1 -0
- package/dist/agent-loop/types.js +8 -0
- package/dist/agent-loop/types.js.map +1 -0
- package/dist/chat/types.d.ts +4 -2
- package/dist/chat/types.d.ts.map +1 -1
- package/dist/cost/types.d.ts +15 -0
- package/dist/cost/types.d.ts.map +1 -1
- package/dist/cost-ledger/migrations/vk_ai_cost_0004_llm_gateway.sql +69 -0
- package/dist/cost-ledger/migrations/vk_ai_cost_0005_harness.sql +99 -0
- package/dist/cost-ledger/migrations/vk_ai_cost_0006_cache_write_prices.sql +17 -0
- package/dist/cost-ledger/migrations/vk_ai_cost_0007_harness_fan_out.sql +47 -0
- package/dist/gateway/errors.d.ts +24 -0
- package/dist/gateway/errors.d.ts.map +1 -0
- package/dist/gateway/errors.js +29 -0
- package/dist/gateway/errors.js.map +1 -0
- package/dist/gateway/gateway.d.ts +27 -0
- package/dist/gateway/gateway.d.ts.map +1 -0
- package/dist/gateway/gateway.js +503 -0
- package/dist/gateway/gateway.js.map +1 -0
- package/dist/gateway/index.d.ts +13 -0
- package/dist/gateway/index.d.ts.map +1 -0
- package/dist/gateway/index.js +10 -0
- package/dist/gateway/index.js.map +1 -0
- package/dist/gateway/policies.d.ts +32 -0
- package/dist/gateway/policies.d.ts.map +1 -0
- package/dist/gateway/policies.js +45 -0
- package/dist/gateway/policies.js.map +1 -0
- package/dist/gateway/postgres.d.ts +55 -0
- package/dist/gateway/postgres.d.ts.map +1 -0
- package/dist/gateway/postgres.js +127 -0
- package/dist/gateway/postgres.js.map +1 -0
- package/dist/gateway/pricing.d.ts +11 -0
- package/dist/gateway/pricing.d.ts.map +1 -0
- package/dist/gateway/pricing.js +47 -0
- package/dist/gateway/pricing.js.map +1 -0
- package/dist/gateway/routing.d.ts +25 -0
- package/dist/gateway/routing.d.ts.map +1 -0
- package/dist/gateway/routing.js +23 -0
- package/dist/gateway/routing.js.map +1 -0
- package/dist/gateway/types.d.ts +225 -0
- package/dist/gateway/types.d.ts.map +1 -0
- package/dist/gateway/types.js +7 -0
- package/dist/gateway/types.js.map +1 -0
- package/dist/generate/anthropic.d.ts +38 -0
- package/dist/generate/anthropic.d.ts.map +1 -0
- package/dist/generate/anthropic.js +446 -0
- package/dist/generate/anthropic.js.map +1 -0
- package/dist/generate/client.d.ts +9 -0
- package/dist/generate/client.d.ts.map +1 -0
- package/dist/generate/client.js +44 -0
- package/dist/generate/client.js.map +1 -0
- package/dist/generate/google.d.ts +39 -0
- package/dist/generate/google.d.ts.map +1 -0
- package/dist/generate/google.js +372 -0
- package/dist/generate/google.js.map +1 -0
- package/dist/generate/http.d.ts +48 -0
- package/dist/generate/http.d.ts.map +1 -0
- package/dist/generate/http.js +180 -0
- package/dist/generate/http.js.map +1 -0
- package/dist/generate/index.d.ts +13 -0
- package/dist/generate/index.d.ts.map +1 -0
- package/dist/generate/index.js +12 -0
- package/dist/generate/index.js.map +1 -0
- package/dist/generate/openai.d.ts +29 -0
- package/dist/generate/openai.d.ts.map +1 -0
- package/dist/generate/openai.js +314 -0
- package/dist/generate/openai.js.map +1 -0
- package/dist/generate/perplexity.d.ts +27 -0
- package/dist/generate/perplexity.d.ts.map +1 -0
- package/dist/generate/perplexity.js +208 -0
- package/dist/generate/perplexity.js.map +1 -0
- package/dist/generate/types.d.ts +253 -0
- package/dist/generate/types.d.ts.map +1 -0
- package/dist/generate/types.js +19 -0
- package/dist/generate/types.js.map +1 -0
- package/dist/harness/define.d.ts +15 -0
- package/dist/harness/define.d.ts.map +1 -0
- package/dist/harness/define.js +38 -0
- package/dist/harness/define.js.map +1 -0
- package/dist/harness/harness.d.ts +29 -0
- package/dist/harness/harness.d.ts.map +1 -0
- package/dist/harness/harness.js +1287 -0
- package/dist/harness/harness.js.map +1 -0
- package/dist/harness/index.d.ts +14 -0
- package/dist/harness/index.d.ts.map +1 -0
- package/dist/harness/index.js +10 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/harness/memory-store.d.ts +8 -0
- package/dist/harness/memory-store.d.ts.map +1 -0
- package/dist/harness/memory-store.js +270 -0
- package/dist/harness/memory-store.js.map +1 -0
- package/dist/harness/postgres-store.d.ts +12 -0
- package/dist/harness/postgres-store.d.ts.map +1 -0
- package/dist/harness/postgres-store.js +368 -0
- package/dist/harness/postgres-store.js.map +1 -0
- package/dist/harness/scheduler.d.ts +12 -0
- package/dist/harness/scheduler.d.ts.map +1 -0
- package/dist/harness/scheduler.js +23 -0
- package/dist/harness/scheduler.js.map +1 -0
- package/dist/harness/store.d.ts +172 -0
- package/dist/harness/store.d.ts.map +1 -0
- package/dist/harness/store.js +21 -0
- package/dist/harness/store.js.map +1 -0
- package/dist/harness/types.d.ts +312 -0
- package/dist/harness/types.d.ts.map +1 -0
- package/dist/harness/types.js +11 -0
- package/dist/harness/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/model-catalog/crud.d.ts.map +1 -1
- package/dist/model-catalog/crud.js +33 -2
- package/dist/model-catalog/crud.js.map +1 -1
- package/dist/model-catalog/types.d.ts +20 -0
- package/dist/model-catalog/types.d.ts.map +1 -1
- package/dist/tracing/index.d.ts +68 -0
- package/dist/tracing/index.d.ts.map +1 -0
- package/dist/tracing/index.js +72 -0
- package/dist/tracing/index.js.map +1 -0
- package/dist/tracing/recording.d.ts +23 -0
- package/dist/tracing/recording.d.ts.map +1 -0
- package/dist/tracing/recording.js +49 -0
- package/dist/tracing/recording.js.map +1 -0
- package/package.json +7 -4
- package/src/cost-ledger/migrations/vk_ai_cost_0004_llm_gateway.sql +69 -0
- package/src/cost-ledger/migrations/vk_ai_cost_0005_harness.sql +99 -0
- package/src/cost-ledger/migrations/vk_ai_cost_0006_cache_write_prices.sql +17 -0
- package/src/cost-ledger/migrations/vk_ai_cost_0007_harness_fan_out.sql +47 -0
package/README.md
CHANGED
|
@@ -33,6 +33,11 @@ npm install @pinecone-database/pinecone
|
|
|
33
33
|
- **Vector stores** — store and query vectors with Pinecone, pgvector, or in-memory
|
|
34
34
|
- **RAG pipelines** — chunking, retrieval, and context building for retrieval-augmented generation
|
|
35
35
|
- **Agents** — AI agents with tool use via OpenAI function calling
|
|
36
|
+
- **`generate`** — one provider-neutral model call (Anthropic, OpenAI, Gemini, Perplexity's Agent API): function tools, native web search with citations, structured output, file inputs, prompt caching, streaming (Perplexity: one-shot only)
|
|
37
|
+
- **LLM gateway** — the single call path: routing (tiers, fallbacks), catalog prices, policies, credentials, retries, cost ledger and audit trail
|
|
38
|
+
- **Agent loop** — a bounded tool-use loop on the gateway (`runAgent`)
|
|
39
|
+
- **Harness** — durable, versioned graphs of nodes on Postgres: retries, gates, map nodes, cancellation, budgets, events
|
|
40
|
+
- **Tracing** — OpenTelemetry GenAI spans through any tracer you pass
|
|
36
41
|
|
|
37
42
|
## Embeddings
|
|
38
43
|
|
|
@@ -135,6 +140,193 @@ console.log(result.output, result.usage, result.cost);
|
|
|
135
140
|
Pair with `withFallback` / `retryWithBackoff` from the fallback module to add
|
|
136
141
|
primary→backup routing or exponential-backoff retries.
|
|
137
142
|
|
|
143
|
+
## LLM Gateway
|
|
144
|
+
|
|
145
|
+
Every text-model call of an app goes through one gateway, which, per call:
|
|
146
|
+
routes (`[model, ...fallbacks]`, or a `tier` mapped by `route`) → resolves
|
|
147
|
+
the catalog key (prices, max tokens, timeout) → runs the policies (a denial
|
|
148
|
+
skips to the next candidate; a policy that throws denies) → gets the API key
|
|
149
|
+
(platform or the tenant's own) → calls with retries on 429 / 5xx, then falls
|
|
150
|
+
back → records one ledger row per billed call and one audit row per call.
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { createLlmGateway, createPostgresGatewaySinks, budgetPolicy, tierRoute } from '@venturekit-pro/ai';
|
|
154
|
+
|
|
155
|
+
const gateway = createLlmGateway({
|
|
156
|
+
catalog: { find: (key) => catalog.get(key) }, // ModelDescriptor by catalog key
|
|
157
|
+
credentials: ({ context, model }) => ({ apiKey: keyFor(context.tenantId, model.provider), source: 'platform' }),
|
|
158
|
+
policies: [budgetPolicy({ check: async (ctx) => ({ allowed: await hasCredits(ctx.tenantId) }) })],
|
|
159
|
+
sinks: createPostgresGatewaySinks(query, { retentionDays: 90 }),
|
|
160
|
+
route: tierRoute({ resolve: ({ tier, context }) => tierKeys(context.tenantId, tier) }),
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const answer = await gateway.generate(
|
|
164
|
+
{ tenantId, feature: 'support-reply', correlationId: `ticket:${ticketId}` },
|
|
165
|
+
{
|
|
166
|
+
model: 'claude-sonnet', // a catalog key — or `tier: 'balanced'`
|
|
167
|
+
fallbacks: ['gpt-mini'],
|
|
168
|
+
messages: [
|
|
169
|
+
{ role: 'system', content: KERNEL_AND_BRAND, cache: true }, // cache the stable prefix
|
|
170
|
+
{ role: 'user', content: question },
|
|
171
|
+
],
|
|
172
|
+
webSearch: { maxUses: 3 },
|
|
173
|
+
responseFormat: { type: 'json_schema', name: 'reply', schema: replySchema },
|
|
174
|
+
},
|
|
175
|
+
);
|
|
176
|
+
// answer.text / .json / .toolCalls / .citations / .usage / .cost / .attempts
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
- **Streaming** — `gateway.stream(context, request)` yields `text`, `tool_call`
|
|
180
|
+
and `search` events, then one `done` with the priced, recorded result.
|
|
181
|
+
Retries and fallbacks only happen before the first event.
|
|
182
|
+
- **Prompt caching** — `cache: true` on a message marks the end of the stable
|
|
183
|
+
prefix (Anthropic `cache_control`, 5 minutes or `cache: { ttl: '1h' }`);
|
|
184
|
+
OpenAI and Gemini cache prefixes on their own (`cache: { key }` becomes
|
|
185
|
+
OpenAI's `prompt_cache_key`). Cache reads and writes come back in the usage
|
|
186
|
+
and are priced from the catalog (`cost_per_1k_cached_input`,
|
|
187
|
+
`cost_per_1k_cache_write`, `cost_per_1k_cache_write_1h`).
|
|
188
|
+
- `listLlmCalls(query, { correlationId })` reads the audit trail of an
|
|
189
|
+
operation; `purgeExpiredLlmCalls(query)` deletes rows past their retention.
|
|
190
|
+
|
|
191
|
+
## Agent Loop
|
|
192
|
+
|
|
193
|
+
A bounded tool loop on the gateway: the model calls tools (and native web
|
|
194
|
+
search) until it answers or a step / tool-call / cost / time limit makes it
|
|
195
|
+
wrap up with one last call.
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
import { runAgent, defineAgentTool, toolResult } from '@venturekit-pro/ai';
|
|
199
|
+
|
|
200
|
+
const lookup = defineAgentTool<{ query: string }>({
|
|
201
|
+
definition: { name: 'lookup', description: 'Search our articles', inputSchema: { type: 'object', properties: { query: { type: 'string' } }, required: ['query'] } },
|
|
202
|
+
parse: (args) => ({ query: String(args.query) }),
|
|
203
|
+
execute: async ({ query }) => toolResult({ content: await searchArticles(query), data: { query } }),
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const result = await runAgent({
|
|
207
|
+
client: gateway.client({ tenantId, feature: 'research' }),
|
|
208
|
+
request: { model: 'claude-sonnet', webSearch: { maxUses: 5 } },
|
|
209
|
+
messages: [{ role: 'user', content: 'What changed in EV charging prices this year?' }],
|
|
210
|
+
tools: [lookup],
|
|
211
|
+
limits: { maxSteps: 10, maxToolCalls: 12, timeoutMs: 5 * 60_000 },
|
|
212
|
+
stream: true, // emits `text.delta` events
|
|
213
|
+
onEvent: (event) => log(event),
|
|
214
|
+
});
|
|
215
|
+
// result.text, .stopReason ('done' | 'budget' | 'length'), .steps, .toolCalls, .usage, .cost
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
A tool that spends itself (a model call, a paid API) reports it with
|
|
219
|
+
`toolResult({ content, cost, usage })`: it counts in the agent's totals and
|
|
220
|
+
cost limit, and is reported apart as `result.toolCost`.
|
|
221
|
+
|
|
222
|
+
### One tool registry for agents and MCP
|
|
223
|
+
|
|
224
|
+
Define each tool once — input schema (Zod, or anything with `safeParse`),
|
|
225
|
+
optional output schema, a token-efficient `format`, a permission class
|
|
226
|
+
(`pure` · `read_tenant` · `read_untrusted` · `write_paid`; nothing that
|
|
227
|
+
approves, publishes or messages) — and serve it to both:
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
import { createToolRegistry, defineRegistryTool } from '@venturekit-pro/ai';
|
|
231
|
+
import { zodToJsonSchema, handleMcpRequest } from '@venturekit/mcp';
|
|
232
|
+
import { z, type ZodType } from 'zod';
|
|
233
|
+
|
|
234
|
+
const search = defineRegistryTool({
|
|
235
|
+
name: 'corpus.search',
|
|
236
|
+
description: 'Search the published articles',
|
|
237
|
+
permission: 'read_tenant',
|
|
238
|
+
input: z.object({ query: z.string() }),
|
|
239
|
+
format: (out: Hit[]) => out.map((h) => h.title),
|
|
240
|
+
run: (args, ctx: { tenantId: string }) => searchCorpus(ctx.tenantId, args.query),
|
|
241
|
+
});
|
|
242
|
+
const registry = createToolRegistry([search], {
|
|
243
|
+
toJsonSchema: (schema) => zodToJsonSchema(schema as ZodType),
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
registry.forAgent({ tenantId }, { permissions: ['read_tenant'] }); // AgentTool[] — names become `corpus_search`
|
|
247
|
+
const mcpTools = registry.forMcp<ZodType>(); // McpToolRegistry for @venturekit/mcp
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The tenant scope is the caller's context — the harness or the MCP server's
|
|
251
|
+
`createContext` — never an argument the model supplies.
|
|
252
|
+
|
|
253
|
+
## Harness
|
|
254
|
+
|
|
255
|
+
Durable, versioned graphs. One queue message per node attempt: lease → run →
|
|
256
|
+
one atomic commit (output, next node, events) → schedule the next task. Gates
|
|
257
|
+
wait with nothing in flight; map nodes checkpoint each item; failed attempts
|
|
258
|
+
retry with backoff; `sweep()` re-sends lost tasks and recovers dead workers;
|
|
259
|
+
`cancel()` aborts a running node through `ctx.signal`.
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
import { createHarness, createPostgresHarnessStore, defineGraph, defineNode } from '@venturekit-pro/ai';
|
|
263
|
+
|
|
264
|
+
const article = defineGraph({
|
|
265
|
+
key: 'article.write',
|
|
266
|
+
version: 1,
|
|
267
|
+
start: 'draft',
|
|
268
|
+
nodes: [
|
|
269
|
+
defineNode({
|
|
270
|
+
id: 'draft',
|
|
271
|
+
kind: 'agent',
|
|
272
|
+
label: 'Writing the draft',
|
|
273
|
+
tier: 'best',
|
|
274
|
+
retry: { maxAttempts: 2 },
|
|
275
|
+
next: 'review',
|
|
276
|
+
run: async (ctx) => (await ctx.runAgent({ request: {}, messages: draftPrompt(ctx.input()) })).text,
|
|
277
|
+
}),
|
|
278
|
+
defineNode({ id: 'review', kind: 'gate', label: 'Ready for you', decisions: ['approve', 'reject'], next: ({ output }) => ((output as { decision: string }).decision === 'approve' ? 'publish' : null) }),
|
|
279
|
+
defineNode({ id: 'publish', kind: 'emit', label: 'Publishing', retry: { maxAttempts: 1 }, run: (ctx) => publish(ctx.require<string>('draft')) }),
|
|
280
|
+
],
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
const harness = createHarness({
|
|
284
|
+
store: createPostgresHarnessStore(query), // migration vk_ai_cost_0005
|
|
285
|
+
scheduler: { enqueue: (task, opts) => queue.send(task, opts?.delayMs) }, // your queue → harness.execute(task)
|
|
286
|
+
graphs: [article],
|
|
287
|
+
gateway,
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const run = await harness.start({ graph: 'article.write', input: { topic }, context: { tenantId } });
|
|
291
|
+
await harness.resume(run.id, { decision: 'approve' });
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
In a node, `ctx.generate` / `ctx.stream` / `ctx.runAgent` go through the
|
|
295
|
+
gateway with the run's context, an idempotency key per attempt and the run's
|
|
296
|
+
spend; tool calls become `tool.called` events; `ctx.progress()` feeds live
|
|
297
|
+
status, and `ctx.state(s)` records the node's state with its
|
|
298
|
+
`detail(s)` line ("3 of 8 sources"). `harness.events(runId, { afterSeq })`
|
|
299
|
+
reads the timeline. `meta` carries app data with a node (artifact contracts,
|
|
300
|
+
tool lists); the harness ignores it.
|
|
301
|
+
|
|
302
|
+
- **Which failures retry** — `retry: { maxAttempts: 3, on: ['rate_limit', 'timeout', 'schema'] }`
|
|
303
|
+
(or a predicate). Categories come from `retryCategory(err)`: 429 →
|
|
304
|
+
`rate_limit`, 5xx → `server`, timeouts, network failures, and errors
|
|
305
|
+
thrown with `category: 'schema'` (an answer that broke its contract).
|
|
306
|
+
Fatal errors (`NodeFatalError`, policy denials, 4xx) never retry.
|
|
307
|
+
- **Fan-out** — a map node with `dispatch: 'tasks'` sends one queue message
|
|
308
|
+
per item (`{ runId, step, attempt, item }`, at most `concurrency` in
|
|
309
|
+
flight). Each item has its own lease, timeout, retries and checkpoint;
|
|
310
|
+
the join counter makes exactly one item — the last — commit the node,
|
|
311
|
+
with the outputs in item order and the items' spend. A failed item fails
|
|
312
|
+
the run; `retry()` redoes only the items not done; `sweep()` re-sends lost
|
|
313
|
+
item tasks and recovers dead item workers (migration `vk_ai_cost_0007`).
|
|
314
|
+
Items and outputs must be JSON. The default, `dispatch: 'inline'`, runs
|
|
315
|
+
the items inside the node attempt.
|
|
316
|
+
|
|
317
|
+
## Tracing
|
|
318
|
+
|
|
319
|
+
Pass any OpenTelemetry tracer — `trace.getTracer('venturekit-ai')` from
|
|
320
|
+
`@opentelemetry/api` fits as is — as `tracer` to the gateway, `runAgent` or
|
|
321
|
+
the harness. `otelTracer()` returns the tracer of the SDK registered in the
|
|
322
|
+
process (the AWS Lambda layer that `lambda.otel` in `@venturekit/infra`
|
|
323
|
+
adds registers one), or `undefined`, without importing anything. Spans: `harness.node <graph>/<node>` per node attempt,
|
|
324
|
+
`invoke_agent <name>`, `execute_tool <tool>`, and `chat <model>` per gateway
|
|
325
|
+
call with the GenAI semantic-convention attributes (`gen_ai.provider.name`,
|
|
326
|
+
`gen_ai.usage.*` with cache reads and writes, finish reasons, time to first
|
|
327
|
+
chunk) plus `vk.ai.*` (cost, call id, tenant, feature, fallback).
|
|
328
|
+
`createRecordingTracer()` keeps spans in memory for tests.
|
|
329
|
+
|
|
138
330
|
## Image Generation
|
|
139
331
|
|
|
140
332
|
Provider-neutral text-to-image (currently Google Imagen), returning raw image
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent loop — a bounded, provider-neutral tool-use loop. See `./run-agent.ts`.
|
|
3
|
+
*/
|
|
4
|
+
export { runAgent, AgentRunError } from './run-agent.js';
|
|
5
|
+
export { defineAgentTool, toolResult, isToolResult } from './tools.js';
|
|
6
|
+
export { createToolRegistry, defineRegistryTool, toModelName } from './registry.js';
|
|
7
|
+
export type { ToolPermission, ToolSchema, ToolSchemaOutput, ToolRunContext, RegistryTool, RegistryMcpTool, ToolFilter, ToolRegistry, } from './registry.js';
|
|
8
|
+
export type { AgentToolContext, ToolSpend, ToolResult, AgentTool, AgentLimits, AgentLimitHit, AgentStopReason, AgentStepResult, AgentToolCallResult, AgentEvent, RunAgentOptions, AgentRunResult, } from './types.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent-loop/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACpF,YAAY,EACV,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,UAAU,EACV,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,gBAAgB,EAChB,SAAS,EACT,UAAU,EACV,SAAS,EACT,WAAW,EACX,aAAa,EACb,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,UAAU,EACV,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent loop — a bounded, provider-neutral tool-use loop. See `./run-agent.ts`.
|
|
3
|
+
*/
|
|
4
|
+
export { runAgent, AgentRunError } from './run-agent.js';
|
|
5
|
+
export { defineAgentTool, toolResult, isToolResult } from './tools.js';
|
|
6
|
+
export { createToolRegistry, defineRegistryTool, toModelName } from './registry.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agent-loop/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool registry — one definition per tool, served to internal agents
|
|
3
|
+
* (`forAgent`) and to an MCP server (`forMcp`, the `@venturekit/mcp`
|
|
4
|
+
* `McpTool` shape).
|
|
5
|
+
*
|
|
6
|
+
* Every tool has an input schema (any schema with Zod's `safeParse` —
|
|
7
|
+
* Zod fits as is), an optional output schema checked before anyone sees
|
|
8
|
+
* the result, a token-efficient `format` for models, and a permission
|
|
9
|
+
* class. The tenant scope is the caller's context, bound by the harness
|
|
10
|
+
* or the MCP server — never an argument the model supplies.
|
|
11
|
+
*
|
|
12
|
+
* There is deliberately no class that approves, publishes, schedules,
|
|
13
|
+
* deletes or messages externally: those are gates or system graphs.
|
|
14
|
+
*/
|
|
15
|
+
import type { AgentTool } from './types.js';
|
|
16
|
+
/**
|
|
17
|
+
* `pure` (no I/O) · `read_tenant` (the tenant's own data) ·
|
|
18
|
+
* `read_untrusted` (the open web — results are untrusted input) ·
|
|
19
|
+
* `write_paid` (creates something that costs money, e.g. an image).
|
|
20
|
+
*/
|
|
21
|
+
export type ToolPermission = 'pure' | 'read_tenant' | 'read_untrusted' | 'write_paid';
|
|
22
|
+
/** Any schema with Zod's `safeParse`. */
|
|
23
|
+
export interface ToolSchema<T> {
|
|
24
|
+
safeParse(value: unknown): {
|
|
25
|
+
success: true;
|
|
26
|
+
data: T;
|
|
27
|
+
} | {
|
|
28
|
+
success: false;
|
|
29
|
+
error: {
|
|
30
|
+
message: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export type ToolSchemaOutput<S> = S extends ToolSchema<infer T> ? T : never;
|
|
35
|
+
/** What a registry tool runs with: the caller's context plus the call's signal. */
|
|
36
|
+
export type ToolRunContext<C> = C & {
|
|
37
|
+
signal: AbortSignal;
|
|
38
|
+
/** Who is calling: an internal agent or an MCP client. */
|
|
39
|
+
via: 'agent' | 'mcp';
|
|
40
|
+
};
|
|
41
|
+
export interface RegistryTool<S extends ToolSchema<any> = ToolSchema<any>, O = unknown, C = unknown> {
|
|
42
|
+
/** `[a-zA-Z0-9_.-]`, ≤ 64 chars. Dots become `_` for model providers (`web.read` → `web_read`). */
|
|
43
|
+
name: string;
|
|
44
|
+
description: string;
|
|
45
|
+
permission: ToolPermission;
|
|
46
|
+
input: S;
|
|
47
|
+
output?: ToolSchema<O>;
|
|
48
|
+
/** The result as models should read it (shorter, no internal ids). Default: the result. */
|
|
49
|
+
format?(output: O): unknown;
|
|
50
|
+
/** Per-call timeout for agents. Default 60 s. */
|
|
51
|
+
timeoutMs?: number;
|
|
52
|
+
run(args: ToolSchemaOutput<S>, ctx: ToolRunContext<C>): Promise<O>;
|
|
53
|
+
}
|
|
54
|
+
/** Declare a registry tool; keeps the input type from the schema to `run`. */
|
|
55
|
+
export declare function defineRegistryTool<S extends ToolSchema<any>, O, C>(tool: RegistryTool<S, O, C>): RegistryTool<S, O, C>;
|
|
56
|
+
/** The `@venturekit/mcp` `McpTool` shape (structural: no dependency on the package). */
|
|
57
|
+
export interface RegistryMcpTool<S, C> {
|
|
58
|
+
name: string;
|
|
59
|
+
description: string;
|
|
60
|
+
inputSchema: S;
|
|
61
|
+
run(args: unknown, ctx: C): Promise<unknown>;
|
|
62
|
+
}
|
|
63
|
+
export interface ToolFilter {
|
|
64
|
+
names?: string[];
|
|
65
|
+
permissions?: ToolPermission[];
|
|
66
|
+
}
|
|
67
|
+
export interface ToolRegistry<C> {
|
|
68
|
+
readonly tools: ReadonlyArray<RegistryTool<ToolSchema<any>, any, C>>;
|
|
69
|
+
get(name: string): RegistryTool<ToolSchema<any>, any, C> | undefined;
|
|
70
|
+
/** Agent tools bound to `ctx` (the tenant scope). */
|
|
71
|
+
forAgent(ctx: C, filter?: ToolFilter): AgentTool[];
|
|
72
|
+
/**
|
|
73
|
+
* MCP tools keyed by name; the MCP server's `createContext` supplies
|
|
74
|
+
* `ctx`. Name your schema type so the result fits `McpToolRegistry`:
|
|
75
|
+
* `registry.forMcp<ZodType>()`.
|
|
76
|
+
*/
|
|
77
|
+
forMcp<S = ToolSchema<any>>(filter?: ToolFilter): Record<string, RegistryMcpTool<S, C>>;
|
|
78
|
+
}
|
|
79
|
+
export declare function createToolRegistry<C>(tools: Array<RegistryTool<any, any, C>>, options: {
|
|
80
|
+
/** Input schema → JSON Schema for the model (e.g. `zodToJsonSchema` from `@venturekit/mcp`). */
|
|
81
|
+
toJsonSchema(schema: ToolSchema<unknown>): object;
|
|
82
|
+
}): ToolRegistry<C>;
|
|
83
|
+
/** Provider tool names allow `[a-zA-Z0-9_-]` only. */
|
|
84
|
+
export declare function toModelName(name: string): string;
|
|
85
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/agent-loop/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool registry — one definition per tool, served to internal agents
|
|
3
|
+
* (`forAgent`) and to an MCP server (`forMcp`, the `@venturekit/mcp`
|
|
4
|
+
* `McpTool` shape).
|
|
5
|
+
*
|
|
6
|
+
* Every tool has an input schema (any schema with Zod's `safeParse` —
|
|
7
|
+
* Zod fits as is), an optional output schema checked before anyone sees
|
|
8
|
+
* the result, a token-efficient `format` for models, and a permission
|
|
9
|
+
* class. The tenant scope is the caller's context, bound by the harness
|
|
10
|
+
* or the MCP server — never an argument the model supplies.
|
|
11
|
+
*
|
|
12
|
+
* There is deliberately no class that approves, publishes, schedules,
|
|
13
|
+
* deletes or messages externally: those are gates or system graphs.
|
|
14
|
+
*/
|
|
15
|
+
import { isToolResult, toolResult } from './tools.js';
|
|
16
|
+
const PERMISSIONS = [
|
|
17
|
+
'pure',
|
|
18
|
+
'read_tenant',
|
|
19
|
+
'read_untrusted',
|
|
20
|
+
'write_paid',
|
|
21
|
+
];
|
|
22
|
+
/** Declare a registry tool; keeps the input type from the schema to `run`. */
|
|
23
|
+
export function defineRegistryTool(tool) {
|
|
24
|
+
return tool;
|
|
25
|
+
}
|
|
26
|
+
const NAME = /^[a-zA-Z0-9_.-]{1,64}$/;
|
|
27
|
+
export function createToolRegistry(tools, options) {
|
|
28
|
+
const byName = new Map();
|
|
29
|
+
const modelNames = new Set();
|
|
30
|
+
for (const tool of tools) {
|
|
31
|
+
if (!NAME.test(tool.name))
|
|
32
|
+
throw new Error(`[ai/tools] '${tool.name}' is not a valid tool name ([a-zA-Z0-9_.-], ≤ 64)`);
|
|
33
|
+
if (byName.has(tool.name))
|
|
34
|
+
throw new Error(`[ai/tools] tool '${tool.name}' is registered twice`);
|
|
35
|
+
if (!PERMISSIONS.includes(tool.permission))
|
|
36
|
+
throw new Error(`[ai/tools] tool '${tool.name}' has an unknown permission class '${String(tool.permission)}'`);
|
|
37
|
+
const modelName = toModelName(tool.name);
|
|
38
|
+
if (modelNames.has(modelName))
|
|
39
|
+
throw new Error(`[ai/tools] '${tool.name}' clashes with another tool as '${modelName}'`);
|
|
40
|
+
modelNames.add(modelName);
|
|
41
|
+
byName.set(tool.name, tool);
|
|
42
|
+
}
|
|
43
|
+
const select = (filter) => [...byName.values()].filter((t) => (!filter?.names || filter.names.includes(t.name)) &&
|
|
44
|
+
(!filter?.permissions || filter.permissions.includes(t.permission)));
|
|
45
|
+
const parse = (tool, args) => {
|
|
46
|
+
const parsed = tool.input.safeParse(args);
|
|
47
|
+
if (!parsed.success)
|
|
48
|
+
throw new Error(`Invalid arguments for ${tool.name}: ${parsed.error.message}`);
|
|
49
|
+
return parsed.data;
|
|
50
|
+
};
|
|
51
|
+
const finish = (tool, out) => {
|
|
52
|
+
const value = isToolResult(out) ? out.content : out;
|
|
53
|
+
if (tool.output) {
|
|
54
|
+
const checked = tool.output.safeParse(value);
|
|
55
|
+
if (!checked.success)
|
|
56
|
+
throw new Error(`${tool.name} returned an invalid result: ${checked.error.message}`);
|
|
57
|
+
}
|
|
58
|
+
const formatted = tool.format ? tool.format(value) : value;
|
|
59
|
+
return isToolResult(out) ? toolResult({ ...out, content: formatted }) : formatted;
|
|
60
|
+
};
|
|
61
|
+
return {
|
|
62
|
+
tools: [...byName.values()],
|
|
63
|
+
get: (name) => byName.get(name),
|
|
64
|
+
forAgent(ctx, filter) {
|
|
65
|
+
return select(filter).map((tool) => ({
|
|
66
|
+
definition: {
|
|
67
|
+
name: toModelName(tool.name),
|
|
68
|
+
description: tool.description,
|
|
69
|
+
inputSchema: options.toJsonSchema(tool.input),
|
|
70
|
+
},
|
|
71
|
+
parse: (args) => parse(tool, args),
|
|
72
|
+
...(tool.timeoutMs !== undefined ? { timeoutMs: tool.timeoutMs } : {}),
|
|
73
|
+
execute: async (args, toolCtx) => finish(tool, await tool.run(args, { ...ctx, signal: toolCtx.signal, via: 'agent' })),
|
|
74
|
+
}));
|
|
75
|
+
},
|
|
76
|
+
forMcp(filter) {
|
|
77
|
+
return Object.fromEntries(select(filter).map((tool) => [
|
|
78
|
+
tool.name,
|
|
79
|
+
{
|
|
80
|
+
name: tool.name,
|
|
81
|
+
description: tool.description,
|
|
82
|
+
inputSchema: tool.input,
|
|
83
|
+
run: async (args, ctx) => {
|
|
84
|
+
const out = finish(tool, await tool.run(parse(tool, args), {
|
|
85
|
+
...ctx,
|
|
86
|
+
signal: new AbortController().signal,
|
|
87
|
+
via: 'mcp',
|
|
88
|
+
}));
|
|
89
|
+
return isToolResult(out) ? out.content : out;
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
]));
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** Provider tool names allow `[a-zA-Z0-9_-]` only. */
|
|
97
|
+
export function toModelName(name) {
|
|
98
|
+
return name.replace(/\./g, '_');
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/agent-loop/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `runAgent` — a bounded tool-use loop on the gateway's `generate`.
|
|
3
|
+
*
|
|
4
|
+
* each step: model call (tools + native web search) → run the function
|
|
5
|
+
* tools it asked for, in order → answer them → next step
|
|
6
|
+
*
|
|
7
|
+
* Limits are soft: when steps, tool calls, cost or time run out, the
|
|
8
|
+
* model gets one last call without tool use and is told to answer from
|
|
9
|
+
* what it has (`stopReason: 'budget'`). A hard stop (cancellation, the
|
|
10
|
+
* wall clock passing its limit mid-call, a gateway error) throws an
|
|
11
|
+
* `AgentRunError` carrying the conversation and spend so far.
|
|
12
|
+
*
|
|
13
|
+
* Every step is one gateway call with a stable idempotency key
|
|
14
|
+
* (`<key>:s<step>`); tool errors go back to the model as error results
|
|
15
|
+
* instead of failing the run.
|
|
16
|
+
*/
|
|
17
|
+
import type { GenerateMessage, GenerateUsage } from '../generate/types.js';
|
|
18
|
+
import type { AgentRunResult, RunAgentOptions } from './types.js';
|
|
19
|
+
type Cost = {
|
|
20
|
+
costUsd: number;
|
|
21
|
+
costMicroUsd: number;
|
|
22
|
+
};
|
|
23
|
+
/** A hard stop, with the conversation and spend so far. `name` stays `AbortError` on cancellation. */
|
|
24
|
+
export declare class AgentRunError extends Error {
|
|
25
|
+
readonly snapshot: {
|
|
26
|
+
messages: GenerateMessage[];
|
|
27
|
+
usage: GenerateUsage;
|
|
28
|
+
cost: Cost | null;
|
|
29
|
+
toolCost: Cost | null;
|
|
30
|
+
steps: number;
|
|
31
|
+
toolCalls: number;
|
|
32
|
+
};
|
|
33
|
+
constructor(message: string, cause: unknown, snapshot: AgentRunError['snapshot']);
|
|
34
|
+
}
|
|
35
|
+
export declare function runAgent(options: RunAgentOptions): Promise<AgentRunResult>;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=run-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-agent.d.ts","sourceRoot":"","sources":["../../src/agent-loop/run-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAEV,eAAe,EACf,aAAa,EAGd,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAGV,cAAc,EAId,eAAe,EAChB,MAAM,YAAY,CAAC;AAepB,KAAK,IAAI,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,sGAAsG;AACtG,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,EAAE,eAAe,EAAE,CAAC;QAC5B,KAAK,EAAE,aAAa,CAAC;QACrB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;QAClB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;QACtB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;gBAEU,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC;CAMjF;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA8BhF"}
|