@andreprado/agentkit 0.1.0-alpha.10
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 +69 -0
- package/bin/agentkit.mjs +23 -0
- package/docs/guides/add-channel.md +114 -0
- package/docs/guides/add-knowledge.md +134 -0
- package/docs/guides/add-tool.md +342 -0
- package/docs/guides/agentkit-skills-architecture.md +471 -0
- package/docs/guides/channel-security.md +81 -0
- package/docs/guides/channels-implementation-map.md +243 -0
- package/docs/guides/channels-production-handoff.md +102 -0
- package/docs/guides/connect-telegram.md +110 -0
- package/docs/guides/connect-whatsapp-zapster.md +119 -0
- package/docs/guides/create-agent.md +220 -0
- package/docs/guides/prepare-deploy.md +209 -0
- package/docs/guides/run-evals.md +179 -0
- package/docs/guides/security-rules.md +156 -0
- package/docs/guides/use-provider.md +140 -0
- package/docs/llms-full.txt +876 -0
- package/docs/llms.txt +83 -0
- package/docs/portable-deploy-release-checklist.md +41 -0
- package/package.json +47 -0
- package/src/cli/args.ts +36 -0
- package/src/cli/cloud-client.ts +265 -0
- package/src/cli/commands/channels.ts +810 -0
- package/src/cli/commands/knowledge.ts +136 -0
- package/src/cli/constants.ts +4 -0
- package/src/cli/deploy-chat-ui.ts +392 -0
- package/src/cli/deploy-readiness.ts +348 -0
- package/src/cli/flags.ts +162 -0
- package/src/cli/help.ts +184 -0
- package/src/cli/index.ts +1276 -0
- package/src/cli/process.ts +31 -0
- package/src/cloud/artifact.ts +139 -0
- package/src/cloud/client.ts +79 -0
- package/src/cloud/contracts.ts +63 -0
- package/src/cloud/index.ts +3 -0
- package/src/create-project.ts +177 -0
- package/src/index.ts +408 -0
- package/src/providers/index.ts +25 -0
- package/src/providers/pi.ts +286 -0
- package/src/providers/test.ts +133 -0
- package/src/providers/types.ts +34 -0
- package/src/runtime/build.ts +43 -0
- package/src/runtime/channel-buffer.ts +30 -0
- package/src/runtime/channel-test-harness.ts +112 -0
- package/src/runtime/channels/telegram.ts +360 -0
- package/src/runtime/channels/website.ts +132 -0
- package/src/runtime/channels/whatsapp-meta.ts +71 -0
- package/src/runtime/channels/whatsapp-zapster.ts +278 -0
- package/src/runtime/channels.ts +138 -0
- package/src/runtime/chat.ts +218 -0
- package/src/runtime/config.ts +684 -0
- package/src/runtime/conversations.ts +38 -0
- package/src/runtime/core/deploy-state.ts +54 -0
- package/src/runtime/core/manifest.ts +213 -0
- package/src/runtime/core/targets.ts +133 -0
- package/src/runtime/database.ts +256 -0
- package/src/runtime/db-commands.ts +167 -0
- package/src/runtime/deploy-readiness.ts +105 -0
- package/src/runtime/deploy.ts +1 -0
- package/src/runtime/dev-server.ts +1247 -0
- package/src/runtime/docs.ts +36 -0
- package/src/runtime/env.ts +152 -0
- package/src/runtime/errors.ts +13 -0
- package/src/runtime/evals.ts +509 -0
- package/src/runtime/inspect.ts +203 -0
- package/src/runtime/knowledge/chunk.ts +333 -0
- package/src/runtime/knowledge/config.ts +135 -0
- package/src/runtime/knowledge/embeddings.ts +133 -0
- package/src/runtime/knowledge/ingest.ts +521 -0
- package/src/runtime/knowledge/prompt-policy.ts +30 -0
- package/src/runtime/knowledge/retrieve.ts +283 -0
- package/src/runtime/knowledge/schema.ts +56 -0
- package/src/runtime/knowledge/tool.ts +64 -0
- package/src/runtime/knowledge/vector.ts +258 -0
- package/src/runtime/runtime-contract.ts +93 -0
- package/src/runtime/spec.ts +152 -0
- package/src/runtime/sync.ts +144 -0
- package/src/runtime/targets/cloudflare/build.ts +2517 -0
- package/src/runtime/targets/container/build.ts +146 -0
- package/src/runtime/targets/container/server.ts +33 -0
- package/src/runtime/targets/vps/deploy.ts +206 -0
- package/src/runtime/tool-runner.ts +65 -0
- package/src/runtime/tools.ts +470 -0
- package/src/runtime/traces.ts +41 -0
- package/src/storage/sqlite.ts +1118 -0
- package/src/templates/blank.ts +394 -0
- package/src/templates/dentista.ts +1003 -0
- package/src/templates/index.ts +33 -0
- package/src/templates/skills/agentkit-build-agent/SKILL.md +51 -0
- package/src/templates/skills/agentkit-build-agent/templates/appointment-intake.instructions.md +20 -0
- package/src/templates/skills/agentkit-build-agent/templates/sales-qualifier.instructions.md +17 -0
- package/src/templates/skills/agentkit-build-agent/templates/support-agent.instructions.md +16 -0
- package/src/templates/skills/agentkit-capsule/SKILL.md +62 -0
- package/src/templates/skills/agentkit-capsule/references/docs-router.md +15 -0
- package/src/templates/skills/agentkit-channels/SKILL.md +62 -0
- package/src/templates/skills/agentkit-channels/references/channel-buffering.md +58 -0
- package/src/templates/skills/agentkit-channels/references/channel-debugging.md +41 -0
- package/src/templates/skills/agentkit-channels/references/telegram.md +38 -0
- package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +44 -0
- package/src/templates/skills/agentkit-database/SKILL.md +45 -0
- package/src/templates/skills/agentkit-database/templates/appointments.schema.sql +15 -0
- package/src/templates/skills/agentkit-database/templates/leads.schema.sql +17 -0
- package/src/templates/skills/agentkit-deploy/SKILL.md +44 -0
- package/src/templates/skills/agentkit-evals/SKILL.md +60 -0
- package/src/templates/skills/agentkit-evals/templates/multi-turn.eval.md +22 -0
- package/src/templates/skills/agentkit-evals/templates/no-leak.eval.md +14 -0
- package/src/templates/skills/agentkit-evals/templates/smoke.eval.md +14 -0
- package/src/templates/skills/agentkit-evals/templates/tool-call.eval.md +18 -0
- package/src/templates/skills/agentkit-knowledge/SKILL.md +40 -0
- package/src/templates/skills/agentkit-knowledge/templates/faq.md +14 -0
- package/src/templates/skills/agentkit-knowledge/templates/policies.md +14 -0
- package/src/templates/skills/agentkit-knowledge/templates/prices.csv +3 -0
- package/src/templates/skills/agentkit-prompts/SKILL.md +45 -0
- package/src/templates/skills/agentkit-prompts/templates/knowledge-grounded-faq.instructions.md +11 -0
- package/src/templates/skills/agentkit-provider/SKILL.md +57 -0
- package/src/templates/skills/agentkit-security/SKILL.md +55 -0
- package/src/templates/skills/agentkit-tools/SKILL.md +36 -0
- package/src/templates/skills/agentkit-tools/examples/database-write.tool.md +35 -0
- package/src/templates/skills/agentkit-tools/examples/eval-safe-external-action.tool.md +37 -0
- package/src/templates/skills/agentkit-tools/examples/lookup-order.tool.md +46 -0
- package/src/templates/skills/agentkit-troubleshooting/SKILL.md +52 -0
- package/src/templates/support.ts +401 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
export type AgentRuntime = "local" | "edge";
|
|
2
|
+
export type AgentProviderName = "test" | "openai" | "anthropic" | "openrouter" | "custom";
|
|
3
|
+
export type AccessMode = "private" | "token" | "public";
|
|
4
|
+
export type ToolVisibility = "user" | "internal";
|
|
5
|
+
export type ChannelType = "website" | "telegram" | "whatsapp";
|
|
6
|
+
export type ChannelProvider = "agentkit" | "telegram" | "zapster" | "meta";
|
|
7
|
+
export type WhatsappChannelProvider = "zapster" | "meta";
|
|
8
|
+
export type TelegramAllowedUpdate = "message";
|
|
9
|
+
|
|
10
|
+
export type AgentProvider = {
|
|
11
|
+
name: AgentProviderName;
|
|
12
|
+
model: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type ChannelLimits = {
|
|
16
|
+
messagesPerDay?: number;
|
|
17
|
+
usdPerDay?: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type ChannelBufferMode = "off" | "debounce";
|
|
21
|
+
|
|
22
|
+
export type ChannelBufferInput = {
|
|
23
|
+
mode?: ChannelBufferMode;
|
|
24
|
+
quietWindowMs?: number;
|
|
25
|
+
maxWaitMs?: number;
|
|
26
|
+
maxMessages?: number;
|
|
27
|
+
maxChars?: number;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type ChannelBufferConfig =
|
|
31
|
+
| {
|
|
32
|
+
mode: "off";
|
|
33
|
+
}
|
|
34
|
+
| {
|
|
35
|
+
mode: "debounce";
|
|
36
|
+
quietWindowMs: number;
|
|
37
|
+
maxWaitMs: number;
|
|
38
|
+
maxMessages: number;
|
|
39
|
+
maxChars: number;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type WebsiteChannelAccess = {
|
|
43
|
+
mode: "token";
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type WebsiteChannelInput = {
|
|
47
|
+
name: string;
|
|
48
|
+
access?: WebsiteChannelAccess;
|
|
49
|
+
secrets?: string[];
|
|
50
|
+
limits?: ChannelLimits;
|
|
51
|
+
buffer?: ChannelBufferInput;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type WebsiteChannelConfig = {
|
|
55
|
+
type: "website";
|
|
56
|
+
provider: "agentkit";
|
|
57
|
+
name: string;
|
|
58
|
+
access: WebsiteChannelAccess;
|
|
59
|
+
secrets: string[];
|
|
60
|
+
limits?: ChannelLimits;
|
|
61
|
+
buffer?: ChannelBufferConfig;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export type TelegramChannelInput = {
|
|
65
|
+
name: string;
|
|
66
|
+
secrets?: string[];
|
|
67
|
+
allowedUpdates?: TelegramAllowedUpdate[];
|
|
68
|
+
limits?: ChannelLimits;
|
|
69
|
+
buffer?: ChannelBufferInput;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type TelegramChannelConfig = {
|
|
73
|
+
type: "telegram";
|
|
74
|
+
provider: "telegram";
|
|
75
|
+
name: string;
|
|
76
|
+
secrets: string[];
|
|
77
|
+
allowedUpdates: TelegramAllowedUpdate[];
|
|
78
|
+
limits?: ChannelLimits;
|
|
79
|
+
buffer?: ChannelBufferConfig;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export type WhatsappChannelInput = {
|
|
83
|
+
name: string;
|
|
84
|
+
provider: WhatsappChannelProvider;
|
|
85
|
+
secrets?: string[];
|
|
86
|
+
limits?: ChannelLimits;
|
|
87
|
+
buffer?: ChannelBufferInput;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export type WhatsappChannelConfig = {
|
|
91
|
+
type: "whatsapp";
|
|
92
|
+
provider: WhatsappChannelProvider;
|
|
93
|
+
name: string;
|
|
94
|
+
secrets: string[];
|
|
95
|
+
limits?: ChannelLimits;
|
|
96
|
+
buffer?: ChannelBufferConfig;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export type AgentChannel = WebsiteChannelConfig | TelegramChannelConfig | WhatsappChannelConfig;
|
|
100
|
+
|
|
101
|
+
export type AgentDatabaseConfig =
|
|
102
|
+
| {
|
|
103
|
+
driver: "none";
|
|
104
|
+
}
|
|
105
|
+
| {
|
|
106
|
+
driver: "turso";
|
|
107
|
+
schema?: string;
|
|
108
|
+
migrations?: string;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export type AgentFilesConfig =
|
|
112
|
+
| {
|
|
113
|
+
driver: "none";
|
|
114
|
+
}
|
|
115
|
+
| {
|
|
116
|
+
driver: "r2";
|
|
117
|
+
bucket?: string;
|
|
118
|
+
prefix?: string;
|
|
119
|
+
maxUploadBytes?: number;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export type AgentKnowledgeSource =
|
|
123
|
+
| string
|
|
124
|
+
| {
|
|
125
|
+
path: string;
|
|
126
|
+
title?: string;
|
|
127
|
+
}
|
|
128
|
+
| {
|
|
129
|
+
url: string;
|
|
130
|
+
title?: string;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export type AgentKnowledgeEmbeddingProvider = "none" | "test" | "openai";
|
|
134
|
+
|
|
135
|
+
export type AgentKnowledgeEmbeddingConfig = {
|
|
136
|
+
provider?: AgentKnowledgeEmbeddingProvider;
|
|
137
|
+
model?: string;
|
|
138
|
+
dimensions?: number;
|
|
139
|
+
secret?: string;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
export type AgentKnowledgeRetrievalConfig = {
|
|
143
|
+
topK?: number;
|
|
144
|
+
hybrid?: boolean;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export type AgentKnowledgeConfig = {
|
|
148
|
+
sources?: AgentKnowledgeSource[];
|
|
149
|
+
embedding?: AgentKnowledgeEmbeddingConfig;
|
|
150
|
+
retrieval?: AgentKnowledgeRetrievalConfig;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export type JsonSchema = {
|
|
154
|
+
type: string | string[];
|
|
155
|
+
properties?: Record<string, JsonSchema>;
|
|
156
|
+
required?: string[];
|
|
157
|
+
items?: JsonSchema;
|
|
158
|
+
[key: string]: unknown;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export type DatabaseValue = string | number | boolean | null;
|
|
162
|
+
export type DatabaseArgs = readonly DatabaseValue[];
|
|
163
|
+
export type DatabaseRow = Record<string, DatabaseValue>;
|
|
164
|
+
export type DatabaseResult = {
|
|
165
|
+
rows: DatabaseRow[];
|
|
166
|
+
rowsAffected: number;
|
|
167
|
+
lastInsertRowid: number | string | null;
|
|
168
|
+
columns: string[];
|
|
169
|
+
};
|
|
170
|
+
export type DatabaseStatement = {
|
|
171
|
+
sql: string;
|
|
172
|
+
args?: DatabaseArgs;
|
|
173
|
+
};
|
|
174
|
+
export type DatabaseRunner = {
|
|
175
|
+
(sql: string, args?: DatabaseArgs): Promise<DatabaseResult>;
|
|
176
|
+
execute(sql: string, args?: DatabaseArgs): Promise<DatabaseResult>;
|
|
177
|
+
query(sql: string, args?: DatabaseArgs): Promise<DatabaseResult>;
|
|
178
|
+
transaction<T>(callback: (tx: DatabaseRunner) => Promise<T> | T): Promise<T>;
|
|
179
|
+
batch(statements: DatabaseStatement[]): Promise<DatabaseResult[]>;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export type ToolRenderField = {
|
|
183
|
+
label: string;
|
|
184
|
+
value: string;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export type ToolRenderAction = {
|
|
188
|
+
label: string;
|
|
189
|
+
href?: string;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
export type ToolRenderBlock =
|
|
193
|
+
| {
|
|
194
|
+
type: "text";
|
|
195
|
+
text: string;
|
|
196
|
+
}
|
|
197
|
+
| {
|
|
198
|
+
type: "card";
|
|
199
|
+
title: string;
|
|
200
|
+
subtitle?: string;
|
|
201
|
+
fields?: ToolRenderField[];
|
|
202
|
+
actions?: ToolRenderAction[];
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export type ToolRenderResult = {
|
|
206
|
+
text: string;
|
|
207
|
+
blocks?: ToolRenderBlock[];
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export type ToolRenderContext<Input = unknown> = {
|
|
211
|
+
input: Input;
|
|
212
|
+
runtime: ToolRuntimeContext;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export type ToolRuntimeContext = {
|
|
216
|
+
environment: "local" | "hosted" | "eval" | "test";
|
|
217
|
+
invocation: "chat" | "tool" | "dev" | "channel" | "eval" | "sync";
|
|
218
|
+
target: "bun" | "cloudflare";
|
|
219
|
+
database: "sqlite" | "turso" | "none";
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
export type ToolContext = {
|
|
223
|
+
secrets: Record<string, string>;
|
|
224
|
+
signal: AbortSignal;
|
|
225
|
+
runtime: ToolRuntimeContext;
|
|
226
|
+
database: DatabaseRunner;
|
|
227
|
+
db: DatabaseRunner;
|
|
228
|
+
storage: {
|
|
229
|
+
sql: DatabaseRunner;
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
export type SyncContext = {
|
|
234
|
+
env: Record<string, string | undefined>;
|
|
235
|
+
database: DatabaseRunner;
|
|
236
|
+
db: DatabaseRunner;
|
|
237
|
+
runtime: ToolRuntimeContext;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
export type AgentTool<Input = unknown, Output = unknown> = {
|
|
241
|
+
name: string;
|
|
242
|
+
description: string;
|
|
243
|
+
visibility?: ToolVisibility;
|
|
244
|
+
inputSchema: JsonSchema;
|
|
245
|
+
outputSchema?: JsonSchema;
|
|
246
|
+
secrets?: string[];
|
|
247
|
+
permissions?: string[];
|
|
248
|
+
timeoutMs?: number;
|
|
249
|
+
execute(input: Input, ctx: ToolContext): Promise<Output> | Output;
|
|
250
|
+
render?(output: Output, ctx: ToolRenderContext<Input>): string | ToolRenderResult;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
export type AgentConfig = {
|
|
254
|
+
name: string;
|
|
255
|
+
runtime: AgentRuntime;
|
|
256
|
+
provider: AgentProvider;
|
|
257
|
+
instructions: string;
|
|
258
|
+
secrets: string[];
|
|
259
|
+
tools?: AgentTool[];
|
|
260
|
+
channels?: AgentChannel[];
|
|
261
|
+
knowledge?: AgentKnowledgeConfig;
|
|
262
|
+
access: {
|
|
263
|
+
mode: AccessMode;
|
|
264
|
+
};
|
|
265
|
+
storage: {
|
|
266
|
+
driver: "sqlite" | "agentkit";
|
|
267
|
+
path?: string;
|
|
268
|
+
database?: AgentDatabaseConfig;
|
|
269
|
+
files?: AgentFilesConfig;
|
|
270
|
+
};
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
export function defineAgent(config: AgentConfig): AgentConfig {
|
|
274
|
+
return config;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export function defineTool<Input = unknown, Output = unknown>(tool: AgentTool<Input, Output>): AgentTool<Input, Output> {
|
|
278
|
+
return tool;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export function websiteChannel(input: WebsiteChannelInput): WebsiteChannelConfig {
|
|
282
|
+
return {
|
|
283
|
+
type: "website",
|
|
284
|
+
provider: "agentkit",
|
|
285
|
+
name: input.name,
|
|
286
|
+
access: input.access ?? { mode: "token" },
|
|
287
|
+
secrets: normalizeChannelSecrets(input.secrets ?? ["AGENTKIT_WEBSITE_CHANNEL_TOKEN"], "website channel"),
|
|
288
|
+
...(input.limits ? { limits: input.limits } : {}),
|
|
289
|
+
...(input.buffer ? { buffer: normalizeChannelBuffer(input.buffer, "website channel") } : {}),
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export function telegramChannel(input: TelegramChannelInput): TelegramChannelConfig {
|
|
294
|
+
return {
|
|
295
|
+
type: "telegram",
|
|
296
|
+
provider: "telegram",
|
|
297
|
+
name: input.name,
|
|
298
|
+
secrets: normalizeChannelSecrets(
|
|
299
|
+
input.secrets ?? ["TELEGRAM_BOT_TOKEN", "TELEGRAM_WEBHOOK_SECRET"],
|
|
300
|
+
"telegram channel",
|
|
301
|
+
),
|
|
302
|
+
allowedUpdates: input.allowedUpdates ?? ["message"],
|
|
303
|
+
...(input.limits ? { limits: input.limits } : {}),
|
|
304
|
+
...(input.buffer ? { buffer: normalizeChannelBuffer(input.buffer, "telegram channel") } : {}),
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export function whatsappChannel(input: WhatsappChannelInput): WhatsappChannelConfig {
|
|
309
|
+
return {
|
|
310
|
+
type: "whatsapp",
|
|
311
|
+
provider: input.provider,
|
|
312
|
+
name: input.name,
|
|
313
|
+
secrets: normalizeChannelSecrets(
|
|
314
|
+
input.secrets ?? defaultWhatsappChannelSecrets(input.provider),
|
|
315
|
+
`${input.provider} whatsapp channel`,
|
|
316
|
+
),
|
|
317
|
+
...(input.limits ? { limits: input.limits } : {}),
|
|
318
|
+
...(input.buffer ? { buffer: normalizeChannelBuffer(input.buffer, `${input.provider} whatsapp channel`) } : {}),
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function defaultWhatsappChannelSecrets(provider: WhatsappChannelProvider): string[] {
|
|
323
|
+
if (provider === "zapster") {
|
|
324
|
+
return ["ZAPSTER_API_KEY", "ZAPSTER_INSTANCE_ID", "ZAPSTER_WEBHOOK_ID"];
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return ["META_WHATSAPP_ACCESS_TOKEN", "META_WHATSAPP_APP_SECRET", "META_WHATSAPP_VERIFY_TOKEN"];
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function normalizeChannelSecrets(secrets: string[], context: string): string[] {
|
|
331
|
+
const uniqueSecrets = new Set<string>();
|
|
332
|
+
|
|
333
|
+
for (const secret of secrets) {
|
|
334
|
+
if (!/^[A-Z_][A-Z0-9_]*$/.test(secret)) {
|
|
335
|
+
throw new Error(`${context} secrets must be environment variable names, not secret values.`);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
uniqueSecrets.add(secret);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return Array.from(uniqueSecrets).sort();
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function normalizeChannelBuffer(input: ChannelBufferInput, context: string): ChannelBufferConfig {
|
|
345
|
+
if (input.mode === "off") {
|
|
346
|
+
return { mode: "off" };
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (input.mode !== undefined && input.mode !== "debounce") {
|
|
350
|
+
throw new Error(`${context} buffer.mode must be "off" or "debounce".`);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const buffer: ChannelBufferConfig = {
|
|
354
|
+
mode: "debounce",
|
|
355
|
+
quietWindowMs: input.quietWindowMs ?? 2500,
|
|
356
|
+
maxWaitMs: input.maxWaitMs ?? 12000,
|
|
357
|
+
maxMessages: input.maxMessages ?? 20,
|
|
358
|
+
maxChars: input.maxChars ?? 8000,
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
validatePositiveInteger(buffer.quietWindowMs, `${context} buffer.quietWindowMs`);
|
|
362
|
+
validatePositiveInteger(buffer.maxWaitMs, `${context} buffer.maxWaitMs`);
|
|
363
|
+
validatePositiveInteger(buffer.maxMessages, `${context} buffer.maxMessages`);
|
|
364
|
+
validatePositiveInteger(buffer.maxChars, `${context} buffer.maxChars`);
|
|
365
|
+
|
|
366
|
+
if (buffer.maxWaitMs < buffer.quietWindowMs) {
|
|
367
|
+
throw new Error(`${context} buffer.maxWaitMs must be greater than or equal to buffer.quietWindowMs.`);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return buffer;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function validatePositiveInteger(value: number, field: string): void {
|
|
374
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
375
|
+
throw new Error(`${field} must be a positive integer.`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export { loadAgentCapsule, findAgentCapsuleRoot } from "./runtime/config";
|
|
380
|
+
export { runAgentMessage, runAgentMessageFromCwd } from "./runtime/chat";
|
|
381
|
+
export { listConversationsFromCwd, getConversationFromCwd } from "./runtime/conversations";
|
|
382
|
+
export { runEvalsFromCwd } from "./runtime/evals";
|
|
383
|
+
export { getConversationTraceFromCwd } from "./runtime/traces";
|
|
384
|
+
export { runToolFromCwd } from "./runtime/tool-runner";
|
|
385
|
+
export { startAgentDevServer } from "./runtime/dev-server";
|
|
386
|
+
export { inspectAgentCapsule } from "./runtime/inspect";
|
|
387
|
+
export { buildAgentCapsule } from "./runtime/build";
|
|
388
|
+
export { deployBuildToAgentKitCloud } from "./runtime/deploy";
|
|
389
|
+
export { AgentKitError } from "./runtime/errors";
|
|
390
|
+
export type {
|
|
391
|
+
ChannelAdapter,
|
|
392
|
+
ChannelAdapterId,
|
|
393
|
+
ChannelDeliveryDirection,
|
|
394
|
+
ChannelDeliveryState,
|
|
395
|
+
ChannelEventKind,
|
|
396
|
+
ChannelExternalIdentity,
|
|
397
|
+
ChannelMessageContentType,
|
|
398
|
+
ChannelMessageRole,
|
|
399
|
+
ChannelSendInput,
|
|
400
|
+
ChannelSendResult,
|
|
401
|
+
ChannelStatusInput,
|
|
402
|
+
ChannelStatusResult,
|
|
403
|
+
NormalizedChannelEvent,
|
|
404
|
+
NormalizedChannelMessage,
|
|
405
|
+
RawWebhookEvent,
|
|
406
|
+
WebhookVerificationInput,
|
|
407
|
+
WebhookVerificationResult,
|
|
408
|
+
} from "./runtime/channels";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AgentProvider } from "../index";
|
|
2
|
+
import { AgentKitError } from "../runtime/errors";
|
|
3
|
+
import { piProviderAdapters } from "./pi";
|
|
4
|
+
import { testProviderAdapter } from "./test";
|
|
5
|
+
import type { ProviderAdapter } from "./types";
|
|
6
|
+
|
|
7
|
+
const providerAdapters = new Map<string, ProviderAdapter>([
|
|
8
|
+
[testProviderAdapter.name, testProviderAdapter],
|
|
9
|
+
...piProviderAdapters.map((adapter) => [adapter.name, adapter] as const),
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
export function getProviderAdapter(provider: AgentProvider): ProviderAdapter {
|
|
13
|
+
const adapter = providerAdapters.get(provider.name);
|
|
14
|
+
|
|
15
|
+
if (!adapter) {
|
|
16
|
+
throw new AgentKitError(
|
|
17
|
+
"provider_not_supported",
|
|
18
|
+
`Provider "${provider.name}" is not implemented in this AgentKit runtime yet.`,
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return adapter;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type { AgentMessage, AgentMessageRole, ProviderAdapter, ProviderRunInput, ProviderRunResult } from "./types";
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findEnvKeys,
|
|
3
|
+
getModel,
|
|
4
|
+
getModels,
|
|
5
|
+
stream,
|
|
6
|
+
type AssistantMessage,
|
|
7
|
+
type AssistantMessageEvent,
|
|
8
|
+
type Message,
|
|
9
|
+
type Model,
|
|
10
|
+
type Provider,
|
|
11
|
+
type Tool as PiTool,
|
|
12
|
+
type ToolCall,
|
|
13
|
+
type Usage,
|
|
14
|
+
} from "@earendil-works/pi-ai";
|
|
15
|
+
|
|
16
|
+
import type { AgentProviderName, AgentTool } from "../index";
|
|
17
|
+
import { AgentKitError } from "../runtime/errors";
|
|
18
|
+
import type { ProviderAdapter, ProviderRunInput, ProviderRunResult } from "./types";
|
|
19
|
+
|
|
20
|
+
const PI_PROVIDER_NAMES = ["openai", "anthropic", "openrouter"] as const satisfies AgentProviderName[];
|
|
21
|
+
const MAX_TOOL_TURNS = 8;
|
|
22
|
+
|
|
23
|
+
export const piProviderAdapters: ProviderAdapter[] = PI_PROVIDER_NAMES.map((name) => ({
|
|
24
|
+
name,
|
|
25
|
+
run(input) {
|
|
26
|
+
return runPiProvider(input);
|
|
27
|
+
},
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
async function runPiProvider(input: ProviderRunInput): Promise<ProviderRunResult> {
|
|
31
|
+
const provider = toPiProvider(input.agent.provider.name);
|
|
32
|
+
const apiKey = requireProviderApiKey(provider, input.env ?? process.env);
|
|
33
|
+
const model = resolveModel(provider, input.agent.provider.model);
|
|
34
|
+
const messages = toPiMessages(input.messages);
|
|
35
|
+
const tools = input.tools.map(toPiTool);
|
|
36
|
+
const rawMessages: AssistantMessage[] = [];
|
|
37
|
+
const rawEvents: AssistantMessageEvent[] = [];
|
|
38
|
+
let usage: Usage | undefined;
|
|
39
|
+
|
|
40
|
+
for (let turn = 0; turn < MAX_TOOL_TURNS; turn += 1) {
|
|
41
|
+
const assistant = await runPiTurn(
|
|
42
|
+
model,
|
|
43
|
+
{
|
|
44
|
+
systemPrompt: input.instructions,
|
|
45
|
+
messages,
|
|
46
|
+
tools,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
apiKey,
|
|
50
|
+
signal: input.signal,
|
|
51
|
+
},
|
|
52
|
+
rawEvents,
|
|
53
|
+
);
|
|
54
|
+
rawMessages.push(assistant);
|
|
55
|
+
usage = addUsage(usage, assistant.usage);
|
|
56
|
+
|
|
57
|
+
if (assistant.stopReason === "error" || assistant.stopReason === "aborted") {
|
|
58
|
+
throw new AgentKitError(
|
|
59
|
+
assistant.stopReason === "aborted" ? "runtime_aborted" : "runtime_error",
|
|
60
|
+
assistant.errorMessage ?? `Pi provider "${provider}" returned stop reason "${assistant.stopReason}".`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const toolCalls = assistant.content.filter((block): block is ToolCall => block.type === "toolCall");
|
|
65
|
+
|
|
66
|
+
if (toolCalls.length === 0) {
|
|
67
|
+
return {
|
|
68
|
+
message: {
|
|
69
|
+
role: "assistant",
|
|
70
|
+
content: assistantText(assistant),
|
|
71
|
+
},
|
|
72
|
+
usage: normalizeUsage(usage),
|
|
73
|
+
raw: {
|
|
74
|
+
provider: "pi",
|
|
75
|
+
events: rawEvents,
|
|
76
|
+
messages: rawMessages,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!input.toolRuntime) {
|
|
82
|
+
throw new AgentKitError("runtime_error", "The runtime did not provide a tool registry.");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
messages.push(assistant);
|
|
86
|
+
|
|
87
|
+
for (const toolCall of toolCalls) {
|
|
88
|
+
const result = await input.toolRuntime.execute({
|
|
89
|
+
name: toolCall.name,
|
|
90
|
+
input: toolCall.arguments,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
messages.push({
|
|
94
|
+
role: "toolResult",
|
|
95
|
+
toolCallId: toolCall.id,
|
|
96
|
+
toolName: toolCall.name,
|
|
97
|
+
content: [
|
|
98
|
+
{
|
|
99
|
+
type: "text",
|
|
100
|
+
text: result.rendered?.text ?? JSON.stringify(result.output),
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
isError: false,
|
|
104
|
+
timestamp: Date.now(),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
throw new AgentKitError("runtime_error", `Pi provider exceeded ${MAX_TOOL_TURNS} tool turns.`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function runPiTurn(
|
|
113
|
+
model: Model<any>,
|
|
114
|
+
context: Parameters<typeof stream>[1],
|
|
115
|
+
options: Parameters<typeof stream>[2],
|
|
116
|
+
rawEvents: AssistantMessageEvent[],
|
|
117
|
+
): Promise<AssistantMessage> {
|
|
118
|
+
const eventStream = stream(model, context, options);
|
|
119
|
+
let assistant: AssistantMessage | undefined;
|
|
120
|
+
let failed: AssistantMessage | undefined;
|
|
121
|
+
|
|
122
|
+
for await (const event of eventStream) {
|
|
123
|
+
rawEvents.push(event);
|
|
124
|
+
|
|
125
|
+
if (event.type === "done") {
|
|
126
|
+
assistant = event.message;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (event.type === "error") {
|
|
130
|
+
failed = event.error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (failed) {
|
|
135
|
+
return failed;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (!assistant) {
|
|
139
|
+
throw new AgentKitError("runtime_error", "Pi provider stream ended without a final assistant message.");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return assistant;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function toPiProvider(provider: string): Provider {
|
|
146
|
+
if (provider === "openai" || provider === "anthropic" || provider === "openrouter") {
|
|
147
|
+
return provider;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
throw new AgentKitError("provider_not_supported", `Provider "${provider}" is not supported by the Pi adapter yet.`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function requireProviderApiKey(provider: Provider, env: Record<string, string | undefined>): string {
|
|
154
|
+
const envNames = findEnvKeys(provider) ?? defaultProviderSecretNames(provider);
|
|
155
|
+
const setName = envNames.find((name) => env[name]);
|
|
156
|
+
|
|
157
|
+
if (!setName) {
|
|
158
|
+
throw new AgentKitError(
|
|
159
|
+
"secret_not_found",
|
|
160
|
+
`Provider "${provider}" requires ${formatSecretList(envNames)}. Set it in .env or the process environment.`,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return env[setName] as string;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function defaultProviderSecretNames(provider: Provider): string[] {
|
|
168
|
+
return [`${provider.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_API_KEY`];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function formatSecretList(names: string[]): string {
|
|
172
|
+
if (names.length === 1) {
|
|
173
|
+
return names[0];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return `one of: ${names.join(", ")}`;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function resolveModel(provider: Provider, modelId: string): Model<any> {
|
|
180
|
+
const modelExists = getModels(provider as any).some((model) => model.id === modelId);
|
|
181
|
+
|
|
182
|
+
if (!modelExists) {
|
|
183
|
+
throw new AgentKitError(
|
|
184
|
+
"provider_model_unsupported",
|
|
185
|
+
`Pi SDK could not resolve provider "${provider}" model "${modelId}".`,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
return getModel(provider as any, modelId as any) as Model<any>;
|
|
191
|
+
} catch (error) {
|
|
192
|
+
throw new AgentKitError(
|
|
193
|
+
"provider_model_unsupported",
|
|
194
|
+
`Pi SDK could not resolve provider "${provider}" model "${modelId}".`,
|
|
195
|
+
{ cause: error },
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function toPiMessages(messages: ProviderRunInput["messages"]): Message[] {
|
|
201
|
+
return messages.map((message) => ({
|
|
202
|
+
role: message.role === "assistant" ? "assistant" : "user",
|
|
203
|
+
content: [
|
|
204
|
+
{
|
|
205
|
+
type: "text",
|
|
206
|
+
text: message.content,
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
timestamp: Date.now(),
|
|
210
|
+
...(message.role === "assistant"
|
|
211
|
+
? {
|
|
212
|
+
api: "agentkit",
|
|
213
|
+
provider: "agentkit",
|
|
214
|
+
model: "agentkit",
|
|
215
|
+
usage: emptyUsage(),
|
|
216
|
+
stopReason: "stop",
|
|
217
|
+
}
|
|
218
|
+
: {}),
|
|
219
|
+
})) as Message[];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function toPiTool(tool: AgentTool): PiTool {
|
|
223
|
+
return {
|
|
224
|
+
name: tool.name,
|
|
225
|
+
description: tool.description,
|
|
226
|
+
parameters: tool.inputSchema as PiTool["parameters"],
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function assistantText(message: AssistantMessage): string {
|
|
231
|
+
return message.content
|
|
232
|
+
.filter((block) => block.type === "text")
|
|
233
|
+
.map((block) => block.text)
|
|
234
|
+
.join("\n")
|
|
235
|
+
.trim();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function normalizeUsage(usage: Usage | undefined): ProviderRunResult["usage"] | undefined {
|
|
239
|
+
if (!usage) {
|
|
240
|
+
return undefined;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
inputTokens: usage.input,
|
|
245
|
+
outputTokens: usage.output,
|
|
246
|
+
totalTokens: usage.totalTokens,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function addUsage(current: Usage | undefined, next: Usage): Usage {
|
|
251
|
+
if (!current) {
|
|
252
|
+
return next;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return {
|
|
256
|
+
input: current.input + next.input,
|
|
257
|
+
output: current.output + next.output,
|
|
258
|
+
cacheRead: current.cacheRead + next.cacheRead,
|
|
259
|
+
cacheWrite: current.cacheWrite + next.cacheWrite,
|
|
260
|
+
totalTokens: current.totalTokens + next.totalTokens,
|
|
261
|
+
cost: {
|
|
262
|
+
input: current.cost.input + next.cost.input,
|
|
263
|
+
output: current.cost.output + next.cost.output,
|
|
264
|
+
cacheRead: current.cost.cacheRead + next.cost.cacheRead,
|
|
265
|
+
cacheWrite: current.cost.cacheWrite + next.cost.cacheWrite,
|
|
266
|
+
total: current.cost.total + next.cost.total,
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function emptyUsage(): Usage {
|
|
272
|
+
return {
|
|
273
|
+
input: 0,
|
|
274
|
+
output: 0,
|
|
275
|
+
cacheRead: 0,
|
|
276
|
+
cacheWrite: 0,
|
|
277
|
+
totalTokens: 0,
|
|
278
|
+
cost: {
|
|
279
|
+
input: 0,
|
|
280
|
+
output: 0,
|
|
281
|
+
cacheRead: 0,
|
|
282
|
+
cacheWrite: 0,
|
|
283
|
+
total: 0,
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
}
|