@ghuri/agents 0.0.0-stage → 0.1.0-alpha.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 +458 -2
- package/dist/index.d.ts +869 -0
- package/dist/index.js +1988 -0
- package/dist/index.js.map +1 -0
- package/package.json +98 -4
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,869 @@
|
|
|
1
|
+
import { GhuriError, RequestUser, GhuriContext, AppConfig, UrlPatterns, Env } from '@ghuri/core';
|
|
2
|
+
import * as _ghuri_rest from '@ghuri/rest';
|
|
3
|
+
import { APIRequest, PermissionClass, AuthenticationClass, APIView, JSONRenderer, BaseAuthentication, BasePermission, APIResponse, APIException, RouterRegistration, BaseRouter } from '@ghuri/rest';
|
|
4
|
+
import { ModelMessage, LanguageModel, LanguageModelUsage, ToolSet, StreamTextResult, UIMessageChunk } from 'ai';
|
|
5
|
+
import * as _ghuri_orm from '@ghuri/orm';
|
|
6
|
+
import { UUIDField, ForeignKey, ModelClass, CharField, JSONField, DateTimeField, Manager } from '@ghuri/orm';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
|
|
9
|
+
/** Base class of `@ghuri/agents` errors. */
|
|
10
|
+
declare class AgentError extends GhuriError {
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A tool failed in a way the model should see (permission denied, validation error, not found…). Thrown from a
|
|
14
|
+
* tool's `execute`, it becomes a tool error for the model (the run continues) and `isError: true` over MCP.
|
|
15
|
+
*/
|
|
16
|
+
declare class ToolError extends AgentError {
|
|
17
|
+
/** HTTP-like status (403, 400, 404…) when the error came from a view. */
|
|
18
|
+
status?: number;
|
|
19
|
+
/** Structured details (DRF error body, validation errors…). */
|
|
20
|
+
detail?: unknown;
|
|
21
|
+
constructor(message: string, opts?: {
|
|
22
|
+
status?: number;
|
|
23
|
+
detail?: unknown;
|
|
24
|
+
cause?: unknown;
|
|
25
|
+
});
|
|
26
|
+
toJSON(): Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
/** Tool input did not match the tool's schema. */
|
|
29
|
+
declare class ToolInputError extends ToolError {
|
|
30
|
+
constructor(message: string, detail?: unknown);
|
|
31
|
+
}
|
|
32
|
+
/** A tool name that no agent / MCP server exposes. */
|
|
33
|
+
declare class UnknownToolError extends AgentError {
|
|
34
|
+
}
|
|
35
|
+
/** A `'provider:model'` string could not be resolved. */
|
|
36
|
+
declare class ModelResolutionError extends AgentError {
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
declare function newConversationId(): string;
|
|
40
|
+
declare function emptyMetadata(): Record<string, unknown>;
|
|
41
|
+
declare const Conversation_base: _ghuri_orm.ModelBaseClass<{
|
|
42
|
+
id: UUIDField<{
|
|
43
|
+
readonly primaryKey: true;
|
|
44
|
+
readonly default: typeof newConversationId;
|
|
45
|
+
readonly editable: false;
|
|
46
|
+
}>;
|
|
47
|
+
user: ForeignKey<ModelClass<_ghuri_orm.BaseModel>, {
|
|
48
|
+
readonly null: true;
|
|
49
|
+
readonly blank: true;
|
|
50
|
+
readonly onDelete: "CASCADE";
|
|
51
|
+
readonly relatedName: "agentConversations";
|
|
52
|
+
}>;
|
|
53
|
+
agent: CharField<{
|
|
54
|
+
readonly maxLength: 100;
|
|
55
|
+
readonly dbIndex: true;
|
|
56
|
+
}>;
|
|
57
|
+
title: CharField<{
|
|
58
|
+
readonly maxLength: 200;
|
|
59
|
+
readonly blank: true;
|
|
60
|
+
readonly default: "";
|
|
61
|
+
}>;
|
|
62
|
+
metadata: JSONField<any, {
|
|
63
|
+
readonly default: typeof emptyMetadata;
|
|
64
|
+
readonly blank: true;
|
|
65
|
+
}>;
|
|
66
|
+
createdAt: DateTimeField<{
|
|
67
|
+
readonly autoNowAdd: true;
|
|
68
|
+
}>;
|
|
69
|
+
updatedAt: DateTimeField<{
|
|
70
|
+
readonly autoNow: true;
|
|
71
|
+
}>;
|
|
72
|
+
}, typeof _ghuri_orm.BaseModel>;
|
|
73
|
+
/** A chat thread between a user and one agent (table `agents_conversation`). */
|
|
74
|
+
declare class Conversation extends Conversation_base {
|
|
75
|
+
static objects: Manager<Conversation>;
|
|
76
|
+
static Meta: {
|
|
77
|
+
appLabel: string;
|
|
78
|
+
ordering: string[];
|
|
79
|
+
verboseName: string;
|
|
80
|
+
};
|
|
81
|
+
toString(): string;
|
|
82
|
+
}
|
|
83
|
+
/** Roles stored in `Message.role` (AI SDK model message roles). */
|
|
84
|
+
declare const MESSAGE_ROLES: readonly ["system", "user", "assistant", "tool"];
|
|
85
|
+
type MessageRole = (typeof MESSAGE_ROLES)[number];
|
|
86
|
+
declare const Message_base: _ghuri_orm.ModelBaseClass<{
|
|
87
|
+
conversation: ForeignKey<typeof Conversation, {
|
|
88
|
+
readonly onDelete: "CASCADE";
|
|
89
|
+
readonly relatedName: "messages";
|
|
90
|
+
}>;
|
|
91
|
+
role: CharField<{
|
|
92
|
+
readonly maxLength: 20;
|
|
93
|
+
readonly choices: [string, string][];
|
|
94
|
+
}>;
|
|
95
|
+
content: JSONField<any, {
|
|
96
|
+
readonly null: true;
|
|
97
|
+
}>;
|
|
98
|
+
createdAt: DateTimeField<{
|
|
99
|
+
readonly autoNowAdd: true;
|
|
100
|
+
}>;
|
|
101
|
+
}, typeof _ghuri_orm.BaseModel>;
|
|
102
|
+
/**
|
|
103
|
+
* One AI SDK model message of a conversation (table `agents_message`). `content` is the message content as
|
|
104
|
+
* JSON: a string, or parts (text, tool calls with their inputs, tool results / errors).
|
|
105
|
+
*/
|
|
106
|
+
declare class Message extends Message_base {
|
|
107
|
+
static objects: Manager<Message>;
|
|
108
|
+
conversationId: string;
|
|
109
|
+
static Meta: {
|
|
110
|
+
appLabel: string;
|
|
111
|
+
ordering: string[];
|
|
112
|
+
verboseName: string;
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** The conversation does not exist, belongs to another agent, or is not owned by the user. */
|
|
117
|
+
declare class ConversationNotFound extends ToolError {
|
|
118
|
+
constructor(message: string);
|
|
119
|
+
}
|
|
120
|
+
/** Is conversation memory available (the `agents` app installed)? */
|
|
121
|
+
declare function memoryAvailable(): boolean;
|
|
122
|
+
/** A user's conversation with `agent`, or `ConversationNotFound`. */
|
|
123
|
+
declare function getConversation(agent: string, id: string, user: RequestUser | null | undefined): Promise<Conversation>;
|
|
124
|
+
/** Start a conversation owned by `user`. */
|
|
125
|
+
declare function createConversation(agent: string, user: RequestUser | null | undefined, opts?: {
|
|
126
|
+
title?: string;
|
|
127
|
+
metadata?: Record<string, unknown>;
|
|
128
|
+
}): Promise<Conversation>;
|
|
129
|
+
/** The stored messages of a conversation, as AI SDK model messages (oldest first). */
|
|
130
|
+
declare function loadMessages(conversation: Conversation | string): Promise<ModelMessage[]>;
|
|
131
|
+
/** Append messages to a conversation and touch its `updatedAt`. */
|
|
132
|
+
declare function saveMessages(conversation: Conversation, messages: ModelMessage[]): Promise<void>;
|
|
133
|
+
|
|
134
|
+
/** Message body sent to the queue by `enqueue()`. */
|
|
135
|
+
interface AgentJob {
|
|
136
|
+
type: 'ghuri.agents.run';
|
|
137
|
+
agent: string;
|
|
138
|
+
input: AgentInput;
|
|
139
|
+
/** Primary key of the user to run as (null: anonymous). */
|
|
140
|
+
userId: unknown;
|
|
141
|
+
conversationId?: string;
|
|
142
|
+
context?: Record<string, unknown>;
|
|
143
|
+
}
|
|
144
|
+
declare const AGENT_JOB_TYPE = "ghuri.agents.run";
|
|
145
|
+
interface EnqueueOptions {
|
|
146
|
+
user?: RequestUser | null;
|
|
147
|
+
conversationId?: string | null;
|
|
148
|
+
/** Queue producer binding (default `AGENTS.QUEUE_BINDING`, else `'AGENTS_QUEUE'`). */
|
|
149
|
+
binding?: string;
|
|
150
|
+
context?: Record<string, unknown>;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Send a run to a Cloudflare Queue (consumed by `AgentRouter.consumeQueue()`). A conversation is created up
|
|
154
|
+
* front (when memory is available) so callers can poll it.
|
|
155
|
+
*/
|
|
156
|
+
declare function enqueueRun(agent: Agent, input: AgentInput, opts?: EnqueueOptions): Promise<{
|
|
157
|
+
conversationId?: string;
|
|
158
|
+
}>;
|
|
159
|
+
/** Load the user a queued run acts for (`AUTH_USER_MODEL`); anonymous when `userId` is null. */
|
|
160
|
+
declare function loadJobUser(userId: unknown): Promise<RequestUser>;
|
|
161
|
+
/**
|
|
162
|
+
* Register a queue consumer running queued agent jobs with `create(name)` (an `AgentRouter`'s factory).
|
|
163
|
+
* Messages that are not agent jobs are left alone; failed runs are retried.
|
|
164
|
+
*/
|
|
165
|
+
declare function consumeAgentQueue(queue: string, create: (name: string) => Agent): () => void;
|
|
166
|
+
|
|
167
|
+
/** A JSON Schema object (draft 2020-12). */
|
|
168
|
+
type JSONSchema = Record<string, unknown>;
|
|
169
|
+
/** Who and what a tool runs for. Every tool executes as `user`. */
|
|
170
|
+
interface ToolContext {
|
|
171
|
+
/** The requesting user (tools never escalate beyond this user's permissions). */
|
|
172
|
+
user: RequestUser;
|
|
173
|
+
/** The agent running the tool (absent for direct MCP calls). */
|
|
174
|
+
agent?: unknown;
|
|
175
|
+
conversationId?: string;
|
|
176
|
+
toolCallId?: string;
|
|
177
|
+
signal?: AbortSignal;
|
|
178
|
+
/** The REST request of the HTTP chat / MCP call, when there is one. */
|
|
179
|
+
request?: APIRequest;
|
|
180
|
+
}
|
|
181
|
+
/** MCP tool annotations (hints for clients; also useful for UIs). */
|
|
182
|
+
interface ToolAnnotations {
|
|
183
|
+
title?: string;
|
|
184
|
+
readOnlyHint?: boolean;
|
|
185
|
+
destructiveHint?: boolean;
|
|
186
|
+
idempotentHint?: boolean;
|
|
187
|
+
openWorldHint?: boolean;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* A normalized tool, the common currency of agents (AI SDK tools) and the MCP server. `ModelTools`,
|
|
191
|
+
* `ViewSetTools`, `RouterTools`, `tool()` and `@tool` methods all produce these.
|
|
192
|
+
*/
|
|
193
|
+
interface AgentTool {
|
|
194
|
+
/** Sanitized name (`posts_list`), unique within an agent / MCP server. */
|
|
195
|
+
name: string;
|
|
196
|
+
description: string;
|
|
197
|
+
/** JSON Schema of the arguments (always `type: 'object'`). */
|
|
198
|
+
inputSchema: JSONSchema;
|
|
199
|
+
/** JSON Schema of the result, when known. */
|
|
200
|
+
outputSchema?: JSONSchema;
|
|
201
|
+
annotations?: ToolAnnotations;
|
|
202
|
+
/** Validate / coerce raw arguments; throws `ToolInputError`. Defaults to accepting any object. */
|
|
203
|
+
parse?(input: unknown): unknown;
|
|
204
|
+
/** Run the tool. Throw `ToolError` for failures the model should see. */
|
|
205
|
+
execute(input: any, ctx: ToolContext): unknown;
|
|
206
|
+
}
|
|
207
|
+
/** A collection of tools (`ModelTools`, `ViewSetTools`, `RouterTools`, or your own). */
|
|
208
|
+
declare abstract class Toolkit {
|
|
209
|
+
abstract getTools(): AgentTool[];
|
|
210
|
+
}
|
|
211
|
+
declare function isToolkit(value: unknown): value is Toolkit;
|
|
212
|
+
declare function isAgentTool(value: unknown): value is AgentTool;
|
|
213
|
+
|
|
214
|
+
/** Marker on methods decorated with `@tool`. */
|
|
215
|
+
declare const TOOL: unique symbol;
|
|
216
|
+
/** Options carried by the decorator returned from `tool()` (for `static tools = {...}` and standalone tools). */
|
|
217
|
+
declare const TOOL_OPTIONS: unique symbol;
|
|
218
|
+
type InputOf<S> = S extends z.ZodType ? z.output<S> : Record<string, any>;
|
|
219
|
+
interface ToolOptions<S = z.ZodType | JSONSchema | undefined> {
|
|
220
|
+
/** Tool name (default: the method / key name). Sanitized to `[A-Za-z0-9_-]{1,64}`. */
|
|
221
|
+
name?: string;
|
|
222
|
+
/** What the tool does — the model reads this to decide when to call it. */
|
|
223
|
+
description: string;
|
|
224
|
+
/** Arguments: a Zod object schema (validated) or a JSON Schema object. Omit for no arguments. */
|
|
225
|
+
input?: S;
|
|
226
|
+
/** JSON Schema of the result (advertised over MCP as `outputSchema`). */
|
|
227
|
+
output?: JSONSchema;
|
|
228
|
+
annotations?: ToolAnnotations;
|
|
229
|
+
/** Standalone tools: the implementation (methods decorated with `@tool` don't need it). */
|
|
230
|
+
execute?: (input: InputOf<S>, ctx: ToolContext) => unknown;
|
|
231
|
+
}
|
|
232
|
+
/** A `tool()` result: a TC39 / legacy method decorator that also carries its options. */
|
|
233
|
+
interface ToolDecorator<S = any> {
|
|
234
|
+
(value: any, context?: any, descriptor?: PropertyDescriptor): any;
|
|
235
|
+
readonly [TOOL_OPTIONS]: ToolOptions<S>;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Declare a tool. Three forms:
|
|
239
|
+
*
|
|
240
|
+
* ```ts
|
|
241
|
+
* class SupportAgent extends Agent {
|
|
242
|
+
* // 1. decorator (standard TC39 decorators)
|
|
243
|
+
* @tool({ description: 'Refund an order', input: z.object({ orderId: z.number() }) })
|
|
244
|
+
* async refund({ orderId }, ctx) { ... }
|
|
245
|
+
*
|
|
246
|
+
* // 2. without decorators: options in a static map, implementation in the method of the same name
|
|
247
|
+
* static tools = { refund: tool({ description: 'Refund an order', input: z.object({ orderId: z.number() }) }) }
|
|
248
|
+
*
|
|
249
|
+
* // 3. standalone, with `execute`
|
|
250
|
+
* tools = [tool({ name: 'now', description: 'Current time', execute: () => new Date().toISOString() })]
|
|
251
|
+
* }
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
declare function tool<S extends z.ZodType | JSONSchema | undefined = undefined>(opts: ToolOptions<S>): ToolDecorator<S>;
|
|
255
|
+
declare function isToolDecorator(value: unknown): value is ToolDecorator;
|
|
256
|
+
/** Build a normalized `AgentTool` from options and an implementation. */
|
|
257
|
+
declare function defineTool(name: string, opts: ToolOptions<any>, execute: (input: any, ctx: ToolContext) => unknown): AgentTool;
|
|
258
|
+
/** A standalone `tool({ ..., execute })` → `AgentTool` (`key` names tools declared in a map). */
|
|
259
|
+
declare function standaloneTool(decorator: ToolDecorator, key?: string): AgentTool;
|
|
260
|
+
/**
|
|
261
|
+
* Tools declared on a class: `@tool` methods and `static tools = { name: tool({...}) }` entries, bound to
|
|
262
|
+
* `instance` (methods receive `(input, ctx)` with `this` = the instance).
|
|
263
|
+
*/
|
|
264
|
+
declare function collectDeclaredTools(instance: object): AgentTool[];
|
|
265
|
+
|
|
266
|
+
/** What can go in an agent's `tools`: toolkits, standalone `tool({...execute})`s and `AgentTool`s. */
|
|
267
|
+
type ToolEntry = Toolkit | ToolDecorator | AgentTool;
|
|
268
|
+
type ToolsInput = ToolEntry[] | Record<string, ToolEntry>;
|
|
269
|
+
/** Input of a run: a user message, or AI SDK model messages to append. */
|
|
270
|
+
type AgentInput = string | ModelMessage[];
|
|
271
|
+
interface RunOptions {
|
|
272
|
+
/** The user the agent acts for; every tool runs with this user's permissions (default: anonymous). */
|
|
273
|
+
user?: RequestUser | null;
|
|
274
|
+
/** Continue a stored conversation (must belong to `user` and this agent). */
|
|
275
|
+
conversationId?: string | null;
|
|
276
|
+
signal?: AbortSignal;
|
|
277
|
+
/** Load / save conversation memory (default: when the `agents` app is installed and `agent.memory`). */
|
|
278
|
+
memory?: boolean;
|
|
279
|
+
/** Check the agent's `permissionClasses` for `user` first (HTTP and MCP always do). */
|
|
280
|
+
checkPermissions?: boolean;
|
|
281
|
+
/** The REST request when running for an HTTP / MCP call. */
|
|
282
|
+
request?: APIRequest;
|
|
283
|
+
/** Free-form values available to `instructions(ctx)` and hooks as `ctx.extra`. */
|
|
284
|
+
context?: Record<string, unknown>;
|
|
285
|
+
/** Title for a new conversation (default: from the first message). */
|
|
286
|
+
title?: string;
|
|
287
|
+
}
|
|
288
|
+
/** Per-run state passed to `instructions(ctx)` and the hooks. */
|
|
289
|
+
interface AgentRunContext {
|
|
290
|
+
agent: Agent;
|
|
291
|
+
agentName: string;
|
|
292
|
+
user: RequestUser;
|
|
293
|
+
input: AgentInput;
|
|
294
|
+
conversationId?: string;
|
|
295
|
+
conversation?: Conversation;
|
|
296
|
+
/** Full prompt: stored history + the new messages. Hooks may edit it. */
|
|
297
|
+
messages: ModelMessage[];
|
|
298
|
+
/** The new messages of this run (saved to memory with the response). */
|
|
299
|
+
newMessages: ModelMessage[];
|
|
300
|
+
signal?: AbortSignal;
|
|
301
|
+
request?: APIRequest;
|
|
302
|
+
extra: Record<string, unknown>;
|
|
303
|
+
}
|
|
304
|
+
/** A tool call made during a run. */
|
|
305
|
+
interface ToolCallRecord {
|
|
306
|
+
toolCallId: string;
|
|
307
|
+
toolName: string;
|
|
308
|
+
input: unknown;
|
|
309
|
+
output?: unknown;
|
|
310
|
+
/** Error message returned to the model (permission denied, validation…). */
|
|
311
|
+
error?: string;
|
|
312
|
+
}
|
|
313
|
+
interface AgentRunResult {
|
|
314
|
+
text: string;
|
|
315
|
+
/** Messages added by this run: the input and the response (assistant / tool messages). */
|
|
316
|
+
messages: ModelMessage[];
|
|
317
|
+
toolCalls: ToolCallRecord[];
|
|
318
|
+
usage: LanguageModelUsage;
|
|
319
|
+
finishReason: string;
|
|
320
|
+
steps: number;
|
|
321
|
+
conversationId?: string;
|
|
322
|
+
}
|
|
323
|
+
/** Passed to `onToolCall` before a tool runs. Throw (e.g. `ToolError`) to refuse the call. */
|
|
324
|
+
interface ToolCallInfo {
|
|
325
|
+
toolName: string;
|
|
326
|
+
toolCallId?: string;
|
|
327
|
+
input: unknown;
|
|
328
|
+
}
|
|
329
|
+
interface Prepared {
|
|
330
|
+
ctx: AgentRunContext;
|
|
331
|
+
model: LanguageModel;
|
|
332
|
+
instructions?: string;
|
|
333
|
+
tools: ToolSet;
|
|
334
|
+
ghuri?: GhuriContext;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* An LLM agent with tools that run as the requesting user.
|
|
338
|
+
*
|
|
339
|
+
* ```ts
|
|
340
|
+
* export class SupportAgent extends Agent {
|
|
341
|
+
* model = 'workers-ai:@cf/meta/llama-3.3-70b-instruct-fp8-fast'
|
|
342
|
+
* instructions = 'You help customers with their orders.'
|
|
343
|
+
* tools = [new ModelTools(Order, { actions: ['list', 'retrieve'], filter: (qs, user) => qs.filter({ customer: user.pk }) })]
|
|
344
|
+
* permissionClasses = [IsAuthenticated]
|
|
345
|
+
*
|
|
346
|
+
* @tool({ description: 'Refund an order', input: z.object({ orderId: z.number() }) })
|
|
347
|
+
* async refund({ orderId }, { user }) { ... }
|
|
348
|
+
* }
|
|
349
|
+
* const { text, conversationId } = await new SupportAgent().run('Where is my order?', { user })
|
|
350
|
+
* ```
|
|
351
|
+
*/
|
|
352
|
+
declare class Agent {
|
|
353
|
+
/** Name used for conversations, URLs and MCP (`ask_<name>`); default: class name minus `Agent`, kebab-case. */
|
|
354
|
+
static agentName?: string;
|
|
355
|
+
/** Shown to MCP clients for the `ask_<name>` tool. */
|
|
356
|
+
static description?: string;
|
|
357
|
+
/** Tools implemented by methods of the same name, without decorators: `{ refund: tool({...}) }`. */
|
|
358
|
+
static tools?: Record<string, ToolDecorator>;
|
|
359
|
+
/** `'provider:model-id'` or an AI SDK `LanguageModel` (default `AGENTS.DEFAULT_MODEL`). */
|
|
360
|
+
model?: string | LanguageModel;
|
|
361
|
+
/** System instructions, or a function of the run context. */
|
|
362
|
+
instructions?: string | ((ctx: AgentRunContext) => string | Promise<string>);
|
|
363
|
+
/** Toolkits and tools (plus `@tool` methods and `static tools`). */
|
|
364
|
+
tools?: ToolsInput;
|
|
365
|
+
/** REST permission classes checked for HTTP / MCP access (default `AGENTS.PERMISSION_CLASSES`). */
|
|
366
|
+
permissionClasses?: PermissionClass[];
|
|
367
|
+
/** Maximum model steps (tool round trips) per run (default `AGENTS.MAX_STEPS`, 10). */
|
|
368
|
+
maxSteps?: number;
|
|
369
|
+
temperature?: number;
|
|
370
|
+
maxOutputTokens?: number;
|
|
371
|
+
/** Provider-specific options passed to the AI SDK (`{ anthropic: { thinking: … } }`). */
|
|
372
|
+
providerOptions?: Record<string, any>;
|
|
373
|
+
/** Use conversation memory when the `agents` app is installed (default true). */
|
|
374
|
+
memory: boolean;
|
|
375
|
+
/** Set by `AgentRouter.register(name, …)`. */
|
|
376
|
+
agentName?: string;
|
|
377
|
+
/** Called before the model runs; may edit `ctx.messages`. Throw to abort the run. */
|
|
378
|
+
beforeRun?(ctx: AgentRunContext): void | Promise<void>;
|
|
379
|
+
/** Called after a run finished and was saved. */
|
|
380
|
+
afterRun?(result: AgentRunResult, ctx: AgentRunContext): void | Promise<void>;
|
|
381
|
+
/** Called before every tool call. Throw (e.g. `ToolError`) to refuse it; the model sees the error. */
|
|
382
|
+
onToolCall?(call: ToolCallInfo, ctx: AgentRunContext): void | Promise<void>;
|
|
383
|
+
/** `new this().run(input, opts)`. */
|
|
384
|
+
static run<T extends Agent>(this: new () => T, input: AgentInput, opts?: RunOptions): Promise<AgentRunResult>;
|
|
385
|
+
getName(): string;
|
|
386
|
+
getDescription(): string;
|
|
387
|
+
getPermissionClasses(): PermissionClass[];
|
|
388
|
+
/** System instructions for a run (override for dynamic instructions). */
|
|
389
|
+
getInstructions(ctx: AgentRunContext): Promise<string | undefined>;
|
|
390
|
+
/** All tools of this agent, normalized (toolkits expanded, declared methods bound). */
|
|
391
|
+
getTools(): AgentTool[];
|
|
392
|
+
/** Check `permissionClasses` for `user` (`NotAuthenticated` / `PermissionDenied` from `@ghuri/rest`). */
|
|
393
|
+
checkPermissions(user: RequestUser, request?: APIRequest): Promise<void>;
|
|
394
|
+
/** AI SDK tool set for a run: validation, `onToolCall`, context and error normalization included. */
|
|
395
|
+
buildToolSet(ctx: AgentRunContext, tools?: AgentTool[]): ToolSet;
|
|
396
|
+
protected prepare(input: AgentInput, opts: RunOptions): Promise<Prepared>;
|
|
397
|
+
protected callSettings(p: Prepared): Record<string, unknown>;
|
|
398
|
+
protected finish(p: Prepared, r: {
|
|
399
|
+
text: string;
|
|
400
|
+
responseMessages: ModelMessage[];
|
|
401
|
+
content: ReadonlyArray<any>;
|
|
402
|
+
usage: LanguageModelUsage;
|
|
403
|
+
finishReason: string;
|
|
404
|
+
steps: number;
|
|
405
|
+
}): Promise<AgentRunResult>;
|
|
406
|
+
/**
|
|
407
|
+
* Run the agent to completion (tool loop included). Tool failures (permission denied, validation, not
|
|
408
|
+
* found) are returned to the model as tool errors; the run itself only throws for model / config errors.
|
|
409
|
+
*/
|
|
410
|
+
run(input: AgentInput, opts?: RunOptions): Promise<AgentRunResult>;
|
|
411
|
+
/**
|
|
412
|
+
* Run in the background through a Cloudflare Queue (`AGENTS.QUEUE_BINDING`); a consumer registered with
|
|
413
|
+
* `AgentRouter.consumeQueue()` performs the run. Returns the conversation id to poll.
|
|
414
|
+
*/
|
|
415
|
+
enqueue(input: AgentInput, opts?: EnqueueOptions): Promise<{
|
|
416
|
+
conversationId?: string;
|
|
417
|
+
}>;
|
|
418
|
+
/**
|
|
419
|
+
* Stream a run. Use `toUIMessageStreamResponse()` for AI SDK UI (`useChat`) / SSE clients, or `textStream`.
|
|
420
|
+
* The conversation is saved when the stream finishes; `await stream.done` for the final result.
|
|
421
|
+
*/
|
|
422
|
+
stream(input: AgentInput, opts?: RunOptions): Promise<AgentStream>;
|
|
423
|
+
}
|
|
424
|
+
/** A streaming run (`agent.stream()`). */
|
|
425
|
+
declare class AgentStream {
|
|
426
|
+
/** The AI SDK `streamText` result (fullStream, textStream, …). */
|
|
427
|
+
readonly result: StreamTextResult<ToolSet, any, any>;
|
|
428
|
+
/** Resolves after the stream finished and the conversation was saved. */
|
|
429
|
+
readonly done: Promise<AgentRunResult>;
|
|
430
|
+
readonly conversationId?: string | undefined;
|
|
431
|
+
constructor(
|
|
432
|
+
/** The AI SDK `streamText` result (fullStream, textStream, …). */
|
|
433
|
+
result: StreamTextResult<ToolSet, any, any>,
|
|
434
|
+
/** Resolves after the stream finished and the conversation was saved. */
|
|
435
|
+
done: Promise<AgentRunResult>, conversationId?: string | undefined);
|
|
436
|
+
/** Plain text deltas. */
|
|
437
|
+
get textStream(): AsyncIterable<string> & ReadableStream<string>;
|
|
438
|
+
/**
|
|
439
|
+
* AI SDK UI message stream chunks (`start`, `text-delta`, `tool-input-available`, `tool-output-available`,
|
|
440
|
+
* `finish`…). The `start` chunk carries `messageMetadata: { conversationId }`. The stream closes only after
|
|
441
|
+
* the conversation was saved.
|
|
442
|
+
*/
|
|
443
|
+
toUIMessageStream(): ReadableStream<UIMessageChunk>;
|
|
444
|
+
/** An SSE `Response` in the AI SDK UI message stream protocol (header `x-conversation-id`). */
|
|
445
|
+
toUIMessageStreamResponse(init?: {
|
|
446
|
+
status?: number;
|
|
447
|
+
headers?: Record<string, string>;
|
|
448
|
+
}): Response;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* The `agents` app: conversation memory (`Conversation`, `Message`) and its migrations. Add it to
|
|
453
|
+
* `INSTALLED_APPS` (after your user model's app) and run `ghuri migrate` to have agents load and save
|
|
454
|
+
* conversations automatically.
|
|
455
|
+
*/
|
|
456
|
+
declare class AgentsConfig extends AppConfig {
|
|
457
|
+
name: string;
|
|
458
|
+
label: string;
|
|
459
|
+
verboseName: string;
|
|
460
|
+
path: string | undefined;
|
|
461
|
+
migrations: Record<string, unknown>;
|
|
462
|
+
models: {
|
|
463
|
+
Conversation: typeof Conversation;
|
|
464
|
+
Message: typeof Message;
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/** Protocol revisions this server speaks (newest first). */
|
|
469
|
+
declare const MCP_PROTOCOL_VERSIONS: readonly ["2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05"];
|
|
470
|
+
declare const MCP_LATEST_PROTOCOL_VERSION: "2025-11-25";
|
|
471
|
+
/** JSON-RPC 2.0 error codes. */
|
|
472
|
+
declare const JSONRPC: {
|
|
473
|
+
readonly PARSE_ERROR: -32700;
|
|
474
|
+
readonly INVALID_REQUEST: -32600;
|
|
475
|
+
readonly METHOD_NOT_FOUND: -32601;
|
|
476
|
+
readonly INVALID_PARAMS: -32602;
|
|
477
|
+
readonly INTERNAL_ERROR: -32603;
|
|
478
|
+
/** Server-defined: authentication / authorization failures. */
|
|
479
|
+
readonly UNAUTHORIZED: -32001;
|
|
480
|
+
};
|
|
481
|
+
type JsonRpcId = string | number | null;
|
|
482
|
+
interface JsonRpcResponse {
|
|
483
|
+
jsonrpc: '2.0';
|
|
484
|
+
id: JsonRpcId;
|
|
485
|
+
result?: unknown;
|
|
486
|
+
error?: {
|
|
487
|
+
code: number;
|
|
488
|
+
message: string;
|
|
489
|
+
data?: unknown;
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
interface McpServerOptions {
|
|
493
|
+
/** Server name shown to clients (default `'ghuri'`). */
|
|
494
|
+
name?: string;
|
|
495
|
+
/** Server version (default `'0.1.0'`). */
|
|
496
|
+
version?: string;
|
|
497
|
+
title?: string;
|
|
498
|
+
/** Instructions for the client's model (returned by `initialize`). */
|
|
499
|
+
instructions?: string;
|
|
500
|
+
/** Tools to expose: toolkits (`ModelTools`, `ViewSetTools`, `RouterTools`), `tool({...execute})`, `AgentTool`s. */
|
|
501
|
+
tools?: ToolsInput;
|
|
502
|
+
/** Agents to expose as `ask_<name>` tools: `{ support: SupportAgent }` or a factory map. */
|
|
503
|
+
agents?: Record<string, () => Agent>;
|
|
504
|
+
/** Authentication (default `AGENTS.AUTHENTICATION_CLASSES`, then REST defaults). */
|
|
505
|
+
authenticationClasses?: AuthenticationClass[];
|
|
506
|
+
/** Access to the endpoint (default `AGENTS.PERMISSION_CLASSES`: `[IsAuthenticated]`). */
|
|
507
|
+
permissionClasses?: PermissionClass[];
|
|
508
|
+
/** Accept browser `Origin`s other than the server's own host / `CSRF_TRUSTED_ORIGINS` (default false). */
|
|
509
|
+
allowAnyOrigin?: boolean;
|
|
510
|
+
}
|
|
511
|
+
interface McpCallContext {
|
|
512
|
+
user: ToolContext['user'];
|
|
513
|
+
request?: APIRequest;
|
|
514
|
+
signal?: AbortSignal;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* A Model Context Protocol server over **Streamable HTTP** (JSON-RPC 2.0 over POST, JSON responses; no
|
|
518
|
+
* server-initiated SSE stream, so GET answers 405). Implements `initialize`, `ping`, `tools/list`,
|
|
519
|
+
* `tools/call`, empty `resources/list` / `prompts/list`, notifications and batches. Requests are authenticated
|
|
520
|
+
* with REST authentication classes and every tool runs as the authenticated user.
|
|
521
|
+
*/
|
|
522
|
+
declare class McpServer {
|
|
523
|
+
readonly opts: McpServerOptions;
|
|
524
|
+
constructor(opts?: McpServerOptions);
|
|
525
|
+
/** All exposed tools (toolkits expanded, agents as `ask_<name>`). */
|
|
526
|
+
getTools(): AgentTool[];
|
|
527
|
+
/** `tools/list` entries. */
|
|
528
|
+
listTools(): Array<Record<string, unknown>>;
|
|
529
|
+
/** `tools/call`: run a tool as `ctx.user`. Tool failures are results with `isError: true`. */
|
|
530
|
+
callTool(name: string, args: unknown, ctx: McpCallContext): Promise<Record<string, unknown>>;
|
|
531
|
+
/** `initialize` result. */
|
|
532
|
+
initializeResult(params: Record<string, unknown>): Record<string, unknown>;
|
|
533
|
+
/** Handle one JSON-RPC message; `null` for notifications and client responses (nothing to send). */
|
|
534
|
+
handleMessage(message: unknown, ctx: McpCallContext): Promise<JsonRpcResponse | null>;
|
|
535
|
+
protected dispatch(method: string, params: Record<string, unknown>, ctx: McpCallContext): Promise<unknown>;
|
|
536
|
+
/** Handle a parsed POST body (single message or batch). Returns the HTTP status and JSON body (or none). */
|
|
537
|
+
handleBody(body: unknown, ctx: McpCallContext): Promise<{
|
|
538
|
+
status: number;
|
|
539
|
+
body?: unknown;
|
|
540
|
+
}>;
|
|
541
|
+
/** The Streamable HTTP endpoint view. */
|
|
542
|
+
asView(): _ghuri_rest.APIViewFunction;
|
|
543
|
+
/** URL patterns: mount with `path('mcp/', server.urls)`. */
|
|
544
|
+
get urls(): UrlPatterns;
|
|
545
|
+
}
|
|
546
|
+
/** A JSON-RPC error raised while dispatching. */
|
|
547
|
+
declare class McpError extends Error {
|
|
548
|
+
readonly code: number;
|
|
549
|
+
readonly data?: unknown | undefined;
|
|
550
|
+
constructor(code: number, message: string, data?: unknown | undefined);
|
|
551
|
+
}
|
|
552
|
+
/** An agent exposed as an MCP tool (`ask_<name>`). */
|
|
553
|
+
declare function agentTool(name: string, factory: () => Agent): AgentTool;
|
|
554
|
+
/** The Streamable HTTP endpoint (POST JSON-RPC; GET / DELETE → 405). */
|
|
555
|
+
declare class McpView extends APIView {
|
|
556
|
+
mcpServer: McpServer;
|
|
557
|
+
rendererClasses: (typeof JSONRenderer)[];
|
|
558
|
+
getAuthenticators(): BaseAuthentication[];
|
|
559
|
+
getPermissions(): BasePermission[];
|
|
560
|
+
performContentNegotiation(request: APIRequest, _force?: boolean): [any, string];
|
|
561
|
+
/** Authentication / permission failures keep their HTTP status (401 + WWW-Authenticate) with a JSON-RPC body. */
|
|
562
|
+
handleException(exc: unknown): Promise<APIResponse>;
|
|
563
|
+
post(request: APIRequest): Promise<APIResponse | Response>;
|
|
564
|
+
get(): Promise<Response>;
|
|
565
|
+
delete(): Promise<Response>;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
type AgentClass = new () => Agent;
|
|
569
|
+
/**
|
|
570
|
+
* 503: the agent's model can't be used (missing provider package, API key or Workers AI binding). The reason
|
|
571
|
+
* is shown with `DEBUG`; production answers stay generic.
|
|
572
|
+
*/
|
|
573
|
+
declare class ModelUnavailable extends APIException {
|
|
574
|
+
static statusCode: number;
|
|
575
|
+
static defaultDetail: string;
|
|
576
|
+
static defaultCode: string;
|
|
577
|
+
}
|
|
578
|
+
/** `AGENTS.AUTHENTICATION_CLASSES`, else `REST_FRAMEWORK.DEFAULT_AUTHENTICATION_CLASSES`. */
|
|
579
|
+
declare function agentAuthenticationClasses(): AuthenticationClass[] | undefined;
|
|
580
|
+
/** Shared base: agent auth settings, permissions from the agent, JSON only (SSE returned as raw responses). */
|
|
581
|
+
declare abstract class AgentBaseView extends APIView {
|
|
582
|
+
agentRouter: AgentRouter;
|
|
583
|
+
agentName: string;
|
|
584
|
+
_agent?: Agent;
|
|
585
|
+
rendererClasses: (typeof JSONRenderer)[];
|
|
586
|
+
/** The agent instance serving this request. */
|
|
587
|
+
get agent(): Agent;
|
|
588
|
+
getAuthenticators(): BaseAuthentication[];
|
|
589
|
+
getPermissions(): BasePermission[];
|
|
590
|
+
performContentNegotiation(request: APIRequest, _force?: boolean): [any, string];
|
|
591
|
+
protected requireMemory(): void;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* `POST <name>/chat` — `{ message, conversationId? }` (or an AI SDK `useChat` body with `messages`). Streams the
|
|
595
|
+
* AI SDK UI message stream as SSE when `Accept: text/event-stream` or `?stream=1`, otherwise answers JSON
|
|
596
|
+
* `{ conversationId, text, toolCalls, usage, finishReason }`.
|
|
597
|
+
*/
|
|
598
|
+
declare class AgentChatView extends AgentBaseView {
|
|
599
|
+
post(request: APIRequest): Promise<Response | APIResponse>;
|
|
600
|
+
}
|
|
601
|
+
/** `GET <name>/conversations/` — the requesting user's conversations with the agent (newest first). */
|
|
602
|
+
declare class ConversationListView extends AgentBaseView {
|
|
603
|
+
get(request: APIRequest): Promise<APIResponse>;
|
|
604
|
+
}
|
|
605
|
+
/** `GET / DELETE <name>/conversations/<id>/` — one conversation with its messages (owner only). */
|
|
606
|
+
declare class ConversationDetailView extends AgentBaseView {
|
|
607
|
+
protected conversation(request: APIRequest, id: string): Promise<any>;
|
|
608
|
+
get(request: APIRequest, kwargs: Record<string, any>): Promise<APIResponse>;
|
|
609
|
+
delete(request: APIRequest, kwargs: Record<string, any>): Promise<APIResponse>;
|
|
610
|
+
}
|
|
611
|
+
interface AgentRouterOptions {
|
|
612
|
+
/** URL name prefix (default `'agents'`: `agents-support-chat`). */
|
|
613
|
+
urlNamePrefix?: string;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Serves agents over HTTP (and MCP).
|
|
617
|
+
*
|
|
618
|
+
* ```ts
|
|
619
|
+
* const agents = new AgentRouter()
|
|
620
|
+
* agents.register('support', SupportAgent)
|
|
621
|
+
* export const urlpatterns = [path('agents/', include(agents.urls)), path('mcp/', agents.mcp({ name: 'shop' }))]
|
|
622
|
+
* // POST /agents/support/chat GET /agents/support/conversations/ GET|DELETE /agents/support/conversations/<id>/
|
|
623
|
+
* ```
|
|
624
|
+
*/
|
|
625
|
+
declare class AgentRouter {
|
|
626
|
+
readonly registry: Map<string, AgentClass>;
|
|
627
|
+
readonly opts: AgentRouterOptions;
|
|
628
|
+
_urls?: UrlPatterns;
|
|
629
|
+
constructor(opts?: AgentRouterOptions);
|
|
630
|
+
/** Register an agent class under `name` (URL segment, conversation `agent` value, MCP `ask_<name>`). */
|
|
631
|
+
register(name: string, agentClass: AgentClass): this;
|
|
632
|
+
/**
|
|
633
|
+
* Consume queued runs (`agent.enqueue()`) from the Cloudflare Queue named `queue` (default: every queue).
|
|
634
|
+
* Call it once, e.g. from an AppConfig's `ready()`. Returns an unregister function.
|
|
635
|
+
*/
|
|
636
|
+
consumeQueue(queue?: string): () => void;
|
|
637
|
+
/** A fresh agent instance for `name`. */
|
|
638
|
+
create(name: string): Agent;
|
|
639
|
+
/** Registered agent names. */
|
|
640
|
+
get names(): string[];
|
|
641
|
+
getUrls(): UrlPatterns;
|
|
642
|
+
/**
|
|
643
|
+
* A Streamable HTTP MCP endpoint exposing `tools` plus the registered agents as `ask_<name>` tools
|
|
644
|
+
* (`agents: false` to leave them out, or a list of names). Mount it with `path('mcp/', agents.mcp())`.
|
|
645
|
+
*/
|
|
646
|
+
mcp(opts?: Omit<McpServerOptions, 'agents'> & {
|
|
647
|
+
agents?: boolean | string[];
|
|
648
|
+
}): UrlPatterns;
|
|
649
|
+
/** The `McpServer` behind `mcp()` (for tests / custom mounting). */
|
|
650
|
+
mcpServer(opts?: Omit<McpServerOptions, 'agents'> & {
|
|
651
|
+
agents?: boolean | string[];
|
|
652
|
+
}): McpServer;
|
|
653
|
+
/** URL patterns to `include()`. */
|
|
654
|
+
get urls(): UrlPatterns;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/** Credentials / options for one provider (`AGENTS.PROVIDERS.anthropic`). */
|
|
658
|
+
interface ProviderConfig {
|
|
659
|
+
apiKey?: string;
|
|
660
|
+
baseURL?: string;
|
|
661
|
+
/** Extra options passed to the provider factory (`createAnthropic({...})`). */
|
|
662
|
+
[option: string]: unknown;
|
|
663
|
+
}
|
|
664
|
+
/** `AGENTS` settings. Every key is optional. */
|
|
665
|
+
interface AgentsSettings {
|
|
666
|
+
/** Model used by agents without a `model` (`'workers-ai:@cf/meta/llama-3.3-70b-instruct-fp8-fast'`). */
|
|
667
|
+
DEFAULT_MODEL?: string | LanguageModel;
|
|
668
|
+
/** Workers AI binding name (default `'AI'`). */
|
|
669
|
+
AI_BINDING?: string;
|
|
670
|
+
/** Provider credentials: `{ anthropic: { apiKey }, openai: { apiKey }, 'workers-ai': { gateway } }`. */
|
|
671
|
+
PROVIDERS?: Record<string, ProviderConfig>;
|
|
672
|
+
/** Default step limit of the tool loop (default 10). */
|
|
673
|
+
MAX_STEPS?: number;
|
|
674
|
+
/** Authentication for the chat / MCP endpoints (default `REST_FRAMEWORK.DEFAULT_AUTHENTICATION_CLASSES`). */
|
|
675
|
+
AUTHENTICATION_CLASSES?: AuthenticationClass[];
|
|
676
|
+
/** Permission classes for agents that don't set `permissionClasses` (default `[IsAuthenticated]`). */
|
|
677
|
+
PERMISSION_CLASSES?: PermissionClass[];
|
|
678
|
+
/** Queue producer binding used by `agent.enqueue()` (default `'AGENTS_QUEUE'`). */
|
|
679
|
+
QUEUE_BINDING?: string;
|
|
680
|
+
}
|
|
681
|
+
declare module '@ghuri/core' {
|
|
682
|
+
interface GhuriSettings {
|
|
683
|
+
/** `@ghuri/agents` settings. */
|
|
684
|
+
AGENTS?: AgentsSettings;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
/** The `AGENTS` settings of the current context (empty outside a context). */
|
|
688
|
+
declare function agentsSettings(): AgentsSettings;
|
|
689
|
+
|
|
690
|
+
interface ProviderContext {
|
|
691
|
+
/** Worker bindings / environment variables of the current request. */
|
|
692
|
+
env: Env;
|
|
693
|
+
settings: AgentsSettings;
|
|
694
|
+
/** `AGENTS.PROVIDERS[name]` (empty object when unset). */
|
|
695
|
+
config: ProviderConfig;
|
|
696
|
+
}
|
|
697
|
+
/** Builds a model for `'<provider>:<modelId>'`. Import provider packages lazily inside the factory. */
|
|
698
|
+
type ProviderFactory = (modelId: string, ctx: ProviderContext) => LanguageModel | Promise<LanguageModel>;
|
|
699
|
+
/**
|
|
700
|
+
* Register (or replace) a model provider used by `'name:model-id'` strings.
|
|
701
|
+
*
|
|
702
|
+
* ```ts
|
|
703
|
+
* registerProvider('google', async (id, { config }) => {
|
|
704
|
+
* const { createGoogleGenerativeAI } = await import('@ai-sdk/google')
|
|
705
|
+
* return createGoogleGenerativeAI({ apiKey: config.apiKey })(id)
|
|
706
|
+
* })
|
|
707
|
+
* ```
|
|
708
|
+
*/
|
|
709
|
+
declare function registerProvider(name: string, factory: ProviderFactory): void;
|
|
710
|
+
declare function unregisterProvider(name: string): boolean;
|
|
711
|
+
/** Names of registered providers. */
|
|
712
|
+
declare function getProviders(): string[];
|
|
713
|
+
/** Is `value` an AI SDK language model instance (not a string id)? */
|
|
714
|
+
declare function isLanguageModel(value: unknown): boolean;
|
|
715
|
+
/**
|
|
716
|
+
* Resolve an agent's `model`: an AI SDK `LanguageModel` is returned as is; `'provider:model-id'` strings go
|
|
717
|
+
* through the provider registry (`workers-ai:`, `anthropic:`, `openai:` built in). Falls back to
|
|
718
|
+
* `AGENTS.DEFAULT_MODEL`.
|
|
719
|
+
*/
|
|
720
|
+
declare function resolveModel(model?: string | LanguageModel | null, env?: Env): Promise<LanguageModel>;
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Normalize anything thrown by a tool into a `ToolError` the model / MCP client may see. Expected failures
|
|
724
|
+
* (permission denied, not found, validation) keep their message; unexpected errors are reported generically
|
|
725
|
+
* unless `DEBUG` is on (the real error is logged).
|
|
726
|
+
*/
|
|
727
|
+
declare function toToolError(err: unknown, toolName?: string): ToolError;
|
|
728
|
+
/** Validate arguments and run a tool, normalizing errors (used by agents and the MCP server). */
|
|
729
|
+
declare function runTool(tool: AgentTool, args: unknown, ctx: ToolContext): Promise<unknown>;
|
|
730
|
+
|
|
731
|
+
interface ViewSetToolsOptions {
|
|
732
|
+
/** Actions to expose (`['list', 'retrieve', 'create', 'partialUpdate', 'destroy', 'publish']`; `'delete'` is an
|
|
733
|
+
* alias of `'destroy'`). Default: every routed action of the viewset. */
|
|
734
|
+
actions?: string[];
|
|
735
|
+
/** Tool name prefix (default: the router prefix, or the model's plural name: `posts` → `posts_list`). */
|
|
736
|
+
prefix?: string;
|
|
737
|
+
/** Router basename when a viewset class is given (default: derived from `queryset`). */
|
|
738
|
+
basename?: string;
|
|
739
|
+
/** Override tool descriptions per action. */
|
|
740
|
+
descriptions?: Record<string, string>;
|
|
741
|
+
}
|
|
742
|
+
interface ActionToolSpec {
|
|
743
|
+
/** Viewset action (`destroy`). */
|
|
744
|
+
action: string;
|
|
745
|
+
/** Tool name suffix (`delete`). */
|
|
746
|
+
suffix: string;
|
|
747
|
+
description?: string;
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* Tools for a REST viewset, executed through `router.registry[i].invoke()`: the viewset's permission classes,
|
|
751
|
+
* throttles, queryset, filters, pagination, validation and serializers apply exactly as over HTTP, as the
|
|
752
|
+
* requesting user. HTTP errors (403, 404, 400…) become tool errors the model can read.
|
|
753
|
+
*
|
|
754
|
+
* ```ts
|
|
755
|
+
* new ViewSetTools(PostViewSet, { actions: ['list', 'retrieve', 'create'] }) // posts_list, posts_retrieve, …
|
|
756
|
+
* new ViewSetTools(router.registry[0]) // every action of a registration
|
|
757
|
+
* ```
|
|
758
|
+
*/
|
|
759
|
+
declare class ViewSetTools extends Toolkit {
|
|
760
|
+
readonly entry: RouterRegistration;
|
|
761
|
+
readonly opts: ViewSetToolsOptions;
|
|
762
|
+
readonly prefix: string;
|
|
763
|
+
protected specs?: ActionToolSpec[];
|
|
764
|
+
constructor(target: any, opts?: ViewSetToolsOptions);
|
|
765
|
+
/** The (action, tool suffix) pairs to expose. */
|
|
766
|
+
actionSpecs(): ActionToolSpec[];
|
|
767
|
+
getTools(): AgentTool[];
|
|
768
|
+
get model(): any;
|
|
769
|
+
protected modelNames(): {
|
|
770
|
+
one: string;
|
|
771
|
+
many: string;
|
|
772
|
+
};
|
|
773
|
+
protected lookup(): {
|
|
774
|
+
kwarg: string;
|
|
775
|
+
param: string;
|
|
776
|
+
schema: JSONSchema;
|
|
777
|
+
};
|
|
778
|
+
protected describe(spec: ActionToolSpec, endpoint: {
|
|
779
|
+
detail: boolean;
|
|
780
|
+
extra: boolean;
|
|
781
|
+
description?: string;
|
|
782
|
+
}): string;
|
|
783
|
+
protected buildTool(spec: ActionToolSpec): AgentTool;
|
|
784
|
+
/** OpenAPI query parameters of the list action (filter backends + paginator). */
|
|
785
|
+
protected listParameters(): Array<Record<string, unknown>>;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
type ModelToolAction = 'list' | 'retrieve' | 'create' | 'update' | 'delete';
|
|
789
|
+
interface ModelToolsOptions {
|
|
790
|
+
/** Tools to generate (default `['list', 'retrieve']`: read-only unless you opt into writes). */
|
|
791
|
+
actions?: ModelToolAction[];
|
|
792
|
+
/** Serializer class (default: a `ModelSerializer` with `fields: '__all__'`). */
|
|
793
|
+
serializer?: any;
|
|
794
|
+
/** Scope the queryset to the requesting user: `(qs, user) => qs.filter({ owner: user.pk })`. Applies to
|
|
795
|
+
* every action (list, retrieve, update, delete), so other users' rows are invisible (404). */
|
|
796
|
+
filter?: (qs: any, user: RequestUser) => any;
|
|
797
|
+
/** Enable `search` over these fields (SearchFilter lookups: `'title'`, `'^slug'`, `'=email'`). */
|
|
798
|
+
searchFields?: string[];
|
|
799
|
+
/** Fields the model may order by (`ordering=-createdAt`); `'__all__'` for any readable field. */
|
|
800
|
+
orderingFields?: string[] | '__all__';
|
|
801
|
+
/** Default ordering. */
|
|
802
|
+
ordering?: string | string[];
|
|
803
|
+
/** Exact-match filters (FieldFilter): `['status']` or `{ createdAt: ['gte', 'lte'] }`. */
|
|
804
|
+
filterFields?: string[] | Record<string, string[]>;
|
|
805
|
+
/** Page size of `list` (default 20; the model may request up to `maxPageSize` with `pageSize`). */
|
|
806
|
+
pageSize?: number;
|
|
807
|
+
maxPageSize?: number;
|
|
808
|
+
/** REST permission classes checked for every call (default `REST_FRAMEWORK.DEFAULT_PERMISSION_CLASSES`). */
|
|
809
|
+
permissionClasses?: PermissionClass[];
|
|
810
|
+
/** Extra values saved on create / update, e.g. the owner: `(user) => ({ owner: user.pk })`. */
|
|
811
|
+
saveKwargs?: (user: RequestUser, action: 'create' | 'update') => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
812
|
+
/** Tool name prefix (default: the model's plural verbose name: `posts`). */
|
|
813
|
+
prefix?: string;
|
|
814
|
+
/** Override tool descriptions per action. */
|
|
815
|
+
descriptions?: Partial<Record<ModelToolAction, string>>;
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* CRUD tools for a model: `posts_list`, `posts_retrieve`, `posts_create`, `posts_update`, `posts_delete`.
|
|
819
|
+
* Built on a generated `ModelViewSet`, so serializers (validation, read-only fields), permission classes,
|
|
820
|
+
* filters and pagination behave exactly like your REST API, and every call runs as the requesting user.
|
|
821
|
+
*
|
|
822
|
+
* ```ts
|
|
823
|
+
* new ModelTools(Order, {
|
|
824
|
+
* actions: ['list', 'retrieve'],
|
|
825
|
+
* serializer: OrderSerializer,
|
|
826
|
+
* filter: (qs, user) => qs.filter({ customer: user.pk }),
|
|
827
|
+
* searchFields: ['number'], orderingFields: ['createdAt'],
|
|
828
|
+
* })
|
|
829
|
+
* ```
|
|
830
|
+
*/
|
|
831
|
+
declare class ModelTools extends ViewSetTools {
|
|
832
|
+
readonly modelClass: any;
|
|
833
|
+
readonly modelOptions: ModelToolsOptions;
|
|
834
|
+
constructor(model: any, opts?: ModelToolsOptions);
|
|
835
|
+
actionSpecs(): ActionToolSpec[];
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
interface RouterToolsOptions {
|
|
839
|
+
/** Only these registrations (by prefix or basename), or a predicate. */
|
|
840
|
+
include?: string[] | ((entry: RouterRegistration) => boolean);
|
|
841
|
+
/** Skip these registrations (by prefix or basename), or tool names (`posts_destroy`). */
|
|
842
|
+
exclude?: string[] | ((entry: RouterRegistration) => boolean);
|
|
843
|
+
/** Restrict actions per registration: `{ posts: ['list', 'retrieve'] }`. */
|
|
844
|
+
actions?: Record<string, string[]>;
|
|
845
|
+
/** Only read-only actions (GET). */
|
|
846
|
+
readOnly?: boolean;
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Expose a whole REST API as tools: one `ViewSetTools` per router registration.
|
|
850
|
+
*
|
|
851
|
+
* ```ts
|
|
852
|
+
* new RouterTools(router, { exclude: ['users'], readOnly: true })
|
|
853
|
+
* ```
|
|
854
|
+
*/
|
|
855
|
+
declare class RouterTools extends Toolkit {
|
|
856
|
+
readonly router: BaseRouter;
|
|
857
|
+
readonly opts: RouterToolsOptions;
|
|
858
|
+
constructor(router: BaseRouter, opts?: RouterToolsOptions);
|
|
859
|
+
/** The `ViewSetTools` of each included registration. */
|
|
860
|
+
toolkits(): ViewSetTools[];
|
|
861
|
+
getTools(): AgentTool[];
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/** Make `name` a valid LLM / MCP tool name: `[A-Za-z0-9_-]{1,64}`. */
|
|
865
|
+
declare function sanitizeToolName(name: string): string;
|
|
866
|
+
/** JSON Schema of a tool input given as a Zod schema, a JSON Schema object or nothing (no arguments). */
|
|
867
|
+
declare function toJSONSchema(input: unknown): JSONSchema;
|
|
868
|
+
|
|
869
|
+
export { AGENT_JOB_TYPE, type ActionToolSpec, Agent, AgentChatView, type AgentClass, AgentError, type AgentInput, type AgentJob, AgentRouter, type AgentRouterOptions, type AgentRunContext, type AgentRunResult, AgentStream, type AgentTool, AgentsConfig, type AgentsSettings, Conversation, ConversationDetailView, ConversationListView, ConversationNotFound, type EnqueueOptions, JSONRPC, type JSONSchema, type JsonRpcId, type JsonRpcResponse, MCP_LATEST_PROTOCOL_VERSION, MCP_PROTOCOL_VERSIONS, MESSAGE_ROLES, type McpCallContext, McpError, McpServer, type McpServerOptions, McpView, Message, type MessageRole, ModelResolutionError, type ModelToolAction, ModelTools, type ModelToolsOptions, ModelUnavailable, type ProviderConfig, type ProviderContext, type ProviderFactory, RouterTools, type RouterToolsOptions, type RunOptions, TOOL, TOOL_OPTIONS, type ToolAnnotations, type ToolCallInfo, type ToolCallRecord, type ToolContext, type ToolDecorator, type ToolEntry, ToolError, ToolInputError, type ToolOptions, Toolkit, type ToolsInput, UnknownToolError, ViewSetTools, type ViewSetToolsOptions, agentAuthenticationClasses, agentTool, agentsSettings, collectDeclaredTools, consumeAgentQueue, createConversation, defineTool, enqueueRun, getConversation, getProviders, isAgentTool, isLanguageModel, isToolDecorator, isToolkit, loadJobUser, loadMessages, memoryAvailable, registerProvider, resolveModel, runTool, sanitizeToolName, saveMessages, standaloneTool, toJSONSchema, toToolError, tool, unregisterProvider };
|