@andreprado/agentkit 0.1.0-alpha.14 → 0.1.0-alpha.16
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 +2 -0
- package/docs/guides/add-channel.md +63 -0
- package/docs/guides/channel-security.md +32 -0
- package/docs/guides/connect-telegram.md +58 -0
- package/docs/guides/connect-whatsapp-zapster.md +65 -0
- package/docs/guides/run-evals.md +73 -25
- package/docs/llms-full.txt +24 -9
- package/docs/llms.txt +2 -0
- package/package.json +1 -1
- package/src/cli/cloud-client.ts +30 -10
- package/src/cli/commands/channels.ts +2 -0
- package/src/cli/deploy-readiness.ts +32 -11
- package/src/cli/index.ts +20 -6
- package/src/cloud/client.ts +4 -3
- package/src/cloud/contracts.ts +1 -1
- package/src/create-project.ts +1 -1
- package/src/index.ts +110 -1
- package/src/providers/pi.ts +14 -1
- package/src/providers/test.ts +36 -0
- package/src/runtime/channel-test-harness.ts +2 -0
- package/src/runtime/channels/telegram.ts +326 -10
- package/src/runtime/channels/whatsapp-zapster.ts +319 -0
- package/src/runtime/channels.ts +47 -1
- package/src/runtime/chat.ts +59 -42
- package/src/runtime/config.ts +96 -4
- package/src/runtime/core/manifest.ts +35 -3
- package/src/runtime/deploy-readiness.ts +3 -3
- package/src/runtime/dev-server.ts +243 -17
- package/src/runtime/env.ts +8 -3
- package/src/runtime/evals.ts +404 -69
- package/src/runtime/inspect.ts +46 -0
- package/src/runtime/prompt-context.ts +141 -0
- package/src/runtime/runtime-contract.ts +17 -7
- package/src/runtime/targets/cloudflare/build.ts +25 -3
- package/src/runtime/targets/container/server.ts +1 -1
- package/src/runtime/targets/vps/deploy.ts +25 -8
- package/src/runtime/tool-runner.ts +7 -0
- package/src/runtime/tools.ts +8 -2
- package/src/runtime/transcription.ts +483 -0
- package/src/templates/blank.ts +8 -3
- package/src/templates/dentista.ts +18 -10
- package/src/templates/skills/agentkit-build-agent/SKILL.md +6 -5
- package/src/templates/skills/agentkit-build-agent/templates/appointment-intake.instructions.md +2 -1
- package/src/templates/skills/agentkit-capsule/SKILL.md +1 -1
- package/src/templates/skills/agentkit-channels/SKILL.md +34 -1
- package/src/templates/skills/agentkit-channels/references/channel-debugging.md +13 -0
- package/src/templates/skills/agentkit-channels/references/telegram.md +32 -0
- package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +29 -0
- package/src/templates/skills/agentkit-evals/SKILL.md +53 -13
- package/src/templates/skills/agentkit-evals/templates/multi-turn.eval.md +13 -6
- package/src/templates/skills/agentkit-evals/templates/no-leak.eval.md +8 -4
- package/src/templates/skills/agentkit-evals/templates/smoke.eval.md +8 -4
- package/src/templates/skills/agentkit-evals/templates/tool-call.eval.md +16 -7
- package/src/templates/skills/agentkit-prompts/SKILL.md +3 -1
- package/src/templates/skills/agentkit-tools/SKILL.md +2 -1
- package/src/templates/support.ts +8 -3
package/src/runtime/config.ts
CHANGED
|
@@ -16,8 +16,11 @@ import type {
|
|
|
16
16
|
TelegramAllowedUpdate,
|
|
17
17
|
AgentKnowledgeEmbeddingProvider,
|
|
18
18
|
ChannelBufferMode,
|
|
19
|
+
ChannelAudioMode,
|
|
20
|
+
TranscriptionProviderName,
|
|
19
21
|
} from "../index";
|
|
20
22
|
import { AgentKitError } from "./errors";
|
|
23
|
+
import { isValidTimeZone } from "./prompt-context";
|
|
21
24
|
|
|
22
25
|
const CONFIG_FILE = "agentkit.config.ts";
|
|
23
26
|
const AGENT_RUNTIMES = new Set<AgentRuntime>(["local", "edge"]);
|
|
@@ -27,8 +30,10 @@ const TOOL_VISIBILITIES = new Set<ToolVisibility>(["user", "internal"]);
|
|
|
27
30
|
const CHANNEL_TYPES = new Set<ChannelType>(["website", "telegram", "whatsapp"]);
|
|
28
31
|
const CHANNEL_PROVIDERS = new Set<ChannelProvider>(["agentkit", "telegram", "zapster", "meta"]);
|
|
29
32
|
const CHANNEL_BUFFER_MODES = new Set<ChannelBufferMode>(["off", "debounce"]);
|
|
33
|
+
const CHANNEL_AUDIO_MODES = new Set<ChannelAudioMode>(["off", "reject", "transcribe"]);
|
|
30
34
|
const TELEGRAM_ALLOWED_UPDATES = new Set<TelegramAllowedUpdate>(["message"]);
|
|
31
35
|
const KNOWLEDGE_EMBEDDING_PROVIDERS = new Set<AgentKnowledgeEmbeddingProvider>(["none", "test", "openai"]);
|
|
36
|
+
const TRANSCRIPTION_PROVIDERS = new Set<TranscriptionProviderName>(["test", "openai", "groq"]);
|
|
32
37
|
const CHANNEL_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
33
38
|
const SECRET_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
|
|
34
39
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
@@ -207,8 +212,17 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
|
|
|
207
212
|
throw invalidConfig('provider.model must be "fake" when provider.name is "test".');
|
|
208
213
|
}
|
|
209
214
|
|
|
215
|
+
if (value.timeZone !== undefined) {
|
|
216
|
+
expectString(value.timeZone, "timeZone");
|
|
217
|
+
|
|
218
|
+
if (!isValidTimeZone(value.timeZone)) {
|
|
219
|
+
throw invalidConfig('timeZone must be a valid IANA time zone such as "UTC" or "America/New_York".');
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
210
223
|
expectString(value.instructions, "instructions");
|
|
211
224
|
expectStringArray(value.secrets, "secrets");
|
|
225
|
+
validateSecretNames(value.secrets, "secrets");
|
|
212
226
|
|
|
213
227
|
if (value.tools !== undefined) {
|
|
214
228
|
if (!Array.isArray(value.tools)) {
|
|
@@ -220,7 +234,8 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
|
|
|
220
234
|
}
|
|
221
235
|
}
|
|
222
236
|
|
|
223
|
-
|
|
237
|
+
validateTranscriptionConfig(value.transcription);
|
|
238
|
+
validateChannels(value.channels, value.runtime as AgentRuntime, Boolean(value.transcription));
|
|
224
239
|
validateKnowledgeConfig(value.knowledge);
|
|
225
240
|
|
|
226
241
|
if (!isRecord(value.access) || !ACCESS_MODES.has(value.access.mode as AccessMode)) {
|
|
@@ -243,6 +258,46 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
|
|
|
243
258
|
validateFilesConfig(value.storage.files);
|
|
244
259
|
}
|
|
245
260
|
|
|
261
|
+
function validateTranscriptionConfig(value: unknown): void {
|
|
262
|
+
if (value === undefined) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (!isRecord(value)) {
|
|
267
|
+
throw invalidConfig("transcription must be an object when provided.");
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (!TRANSCRIPTION_PROVIDERS.has(value.provider as TranscriptionProviderName)) {
|
|
271
|
+
throw invalidConfig(`transcription.provider must be one of: ${Array.from(TRANSCRIPTION_PROVIDERS).join(", ")}.`);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
expectString(value.model, "transcription.model");
|
|
275
|
+
|
|
276
|
+
if (value.secret !== undefined) {
|
|
277
|
+
expectString(value.secret, "transcription.secret");
|
|
278
|
+
validateSecretNames([value.secret], "transcription.secret");
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (value.language !== undefined) {
|
|
282
|
+
expectString(value.language, "transcription.language");
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (value.prompt !== undefined) {
|
|
286
|
+
expectString(value.prompt, "transcription.prompt");
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (value.limits !== undefined) {
|
|
290
|
+
if (!isRecord(value.limits)) {
|
|
291
|
+
throw invalidConfig("transcription.limits must be an object when provided.");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
validateOptionalPositiveInteger(value.limits.maxDurationSeconds, "transcription.limits.maxDurationSeconds");
|
|
295
|
+
validateOptionalPositiveInteger(value.limits.maxBytes, "transcription.limits.maxBytes");
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
validateOptionalPositiveInteger(value.rawAudioTtlSeconds, "transcription.rawAudioTtlSeconds");
|
|
299
|
+
}
|
|
300
|
+
|
|
246
301
|
function validateKnowledgeConfig(value: unknown): void {
|
|
247
302
|
if (value === undefined) {
|
|
248
303
|
return;
|
|
@@ -371,7 +426,7 @@ function validateKnowledgeRetrieval(value: unknown): void {
|
|
|
371
426
|
}
|
|
372
427
|
}
|
|
373
428
|
|
|
374
|
-
function validateChannels(value: unknown, runtime: AgentRuntime): void {
|
|
429
|
+
function validateChannels(value: unknown, runtime: AgentRuntime, hasTranscriptionConfig: boolean): void {
|
|
375
430
|
if (value === undefined) {
|
|
376
431
|
return;
|
|
377
432
|
}
|
|
@@ -387,7 +442,7 @@ function validateChannels(value: unknown, runtime: AgentRuntime): void {
|
|
|
387
442
|
const names = new Set<string>();
|
|
388
443
|
|
|
389
444
|
for (const [index, channel] of value.entries()) {
|
|
390
|
-
validateChannel(channel, index);
|
|
445
|
+
validateChannel(channel, index, hasTranscriptionConfig);
|
|
391
446
|
|
|
392
447
|
if (names.has(channel.name)) {
|
|
393
448
|
throw invalidConfig(`channels[${index}].name must be unique within the Agent Capsule.`);
|
|
@@ -397,7 +452,7 @@ function validateChannels(value: unknown, runtime: AgentRuntime): void {
|
|
|
397
452
|
}
|
|
398
453
|
}
|
|
399
454
|
|
|
400
|
-
function validateChannel(value: unknown, index: number): asserts value is AgentChannel {
|
|
455
|
+
function validateChannel(value: unknown, index: number, hasTranscriptionConfig: boolean): asserts value is AgentChannel {
|
|
401
456
|
if (!isRecord(value)) {
|
|
402
457
|
throw invalidConfig(`channels[${index}] must be an object.`);
|
|
403
458
|
}
|
|
@@ -422,6 +477,7 @@ function validateChannel(value: unknown, index: number): asserts value is AgentC
|
|
|
422
477
|
validateSecretNames(value.secrets, `channels[${index}].secrets`);
|
|
423
478
|
validateChannelLimits(value.limits, index);
|
|
424
479
|
validateChannelBuffer(value.buffer, index);
|
|
480
|
+
validateChannelAudio(value.audio, index, hasTranscriptionConfig);
|
|
425
481
|
|
|
426
482
|
if (value.type === "website") {
|
|
427
483
|
validateWebsiteChannel(value, index);
|
|
@@ -436,6 +492,31 @@ function validateChannel(value: unknown, index: number): asserts value is AgentC
|
|
|
436
492
|
validateWhatsappChannel(value, index);
|
|
437
493
|
}
|
|
438
494
|
|
|
495
|
+
function validateChannelAudio(value: unknown, index: number, hasTranscriptionConfig: boolean): void {
|
|
496
|
+
if (value === undefined) {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if (!isRecord(value)) {
|
|
501
|
+
throw invalidConfig(`channels[${index}].audio must be an object when provided.`);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (!CHANNEL_AUDIO_MODES.has(value.mode as ChannelAudioMode)) {
|
|
505
|
+
throw invalidConfig(`channels[${index}].audio.mode must be "off", "reject", or "transcribe".`);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (value.mode === "transcribe" && !hasTranscriptionConfig) {
|
|
509
|
+
throw invalidConfig(`channels[${index}].audio.mode "transcribe" requires top-level transcription config.`);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (value.mode !== "off") {
|
|
513
|
+
expectString(value.fallbackMessage, `channels[${index}].audio.fallbackMessage`);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
validateOptionalPositiveInteger(value.maxDurationSeconds, `channels[${index}].audio.maxDurationSeconds`);
|
|
517
|
+
validateOptionalPositiveInteger(value.maxBytes, `channels[${index}].audio.maxBytes`);
|
|
518
|
+
}
|
|
519
|
+
|
|
439
520
|
function validateWebsiteChannel(value: Record<string, unknown>, index: number): void {
|
|
440
521
|
if (value.provider !== "agentkit") {
|
|
441
522
|
throw invalidConfig(`channels[${index}].provider must be "agentkit" when type is "website".`);
|
|
@@ -552,6 +633,16 @@ function validateSecretNames(secrets: string[], field: string): void {
|
|
|
552
633
|
}
|
|
553
634
|
}
|
|
554
635
|
|
|
636
|
+
function validateOptionalPositiveInteger(value: unknown, field: string): void {
|
|
637
|
+
if (value === undefined) {
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
|
|
642
|
+
throw invalidConfig(`${field} must be a positive integer when provided.`);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
555
646
|
function expectRequiredSecrets(value: unknown, requiredSecrets: string[], field: string): void {
|
|
556
647
|
const declaredSecrets = new Set(Array.isArray(value) ? value : []);
|
|
557
648
|
const missingSecrets = requiredSecrets.filter((secret) => !declaredSecrets.has(secret));
|
|
@@ -636,6 +727,7 @@ function validateTool(value: unknown, index: number): asserts value is AgentTool
|
|
|
636
727
|
|
|
637
728
|
if (value.secrets !== undefined) {
|
|
638
729
|
expectStringArray(value.secrets, `tools[${index}].secrets`);
|
|
730
|
+
validateSecretNames(value.secrets, `tools[${index}].secrets`);
|
|
639
731
|
}
|
|
640
732
|
|
|
641
733
|
if (value.permissions !== undefined) {
|
|
@@ -4,6 +4,7 @@ import type { AgentConfig, AgentTool } from "../../index";
|
|
|
4
4
|
import type { LoadedAgentCapsule } from "../config";
|
|
5
5
|
import { resolveKnowledgeConfig } from "../knowledge/config";
|
|
6
6
|
import { KNOWLEDGE_SEARCH_TOOL_NAME } from "../knowledge/tool";
|
|
7
|
+
import { resolveTranscriptionConfig } from "../transcription";
|
|
7
8
|
|
|
8
9
|
export type ManifestSchema = {
|
|
9
10
|
source: string;
|
|
@@ -15,6 +16,7 @@ export type SharedAgentManifest = {
|
|
|
15
16
|
name: string;
|
|
16
17
|
runtime: AgentConfig["runtime"];
|
|
17
18
|
provider: AgentConfig["provider"];
|
|
19
|
+
timeZone: string | null;
|
|
18
20
|
prompt: string;
|
|
19
21
|
secrets: string[];
|
|
20
22
|
tools: Array<{
|
|
@@ -27,6 +29,19 @@ export type SharedAgentManifest = {
|
|
|
27
29
|
timeoutMs: number | null;
|
|
28
30
|
}>;
|
|
29
31
|
channels: NonNullable<AgentConfig["channels"]>;
|
|
32
|
+
transcription: {
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
provider: string | null;
|
|
35
|
+
model: string | null;
|
|
36
|
+
secret: string | null;
|
|
37
|
+
language: string | null;
|
|
38
|
+
prompt: string | null;
|
|
39
|
+
limits: {
|
|
40
|
+
maxDurationSeconds: number | null;
|
|
41
|
+
maxBytes: number | null;
|
|
42
|
+
};
|
|
43
|
+
rawAudioTtlSeconds: number | null;
|
|
44
|
+
};
|
|
30
45
|
knowledge: {
|
|
31
46
|
enabled: boolean;
|
|
32
47
|
sources: Array<{
|
|
@@ -79,10 +94,9 @@ export function buildSharedAgentManifest(
|
|
|
79
94
|
const database = buildDatabaseManifest(capsule, options.databaseSchema ?? null);
|
|
80
95
|
const files = buildFilesManifest(capsule);
|
|
81
96
|
const knowledge = resolveKnowledgeConfig(capsule.config);
|
|
97
|
+
const transcription = resolveTranscriptionConfig(capsule.config.transcription);
|
|
82
98
|
|
|
83
|
-
|
|
84
|
-
requiredSecrets.add("AGENTKIT_PRIVATE_TOKEN");
|
|
85
|
-
}
|
|
99
|
+
requiredSecrets.add("AGENTKIT_PRIVATE_TOKEN");
|
|
86
100
|
|
|
87
101
|
if (capsule.config.access.mode === "token") {
|
|
88
102
|
requiredSecrets.add("AGENTKIT_ACCESS_TOKEN");
|
|
@@ -101,6 +115,10 @@ export function buildSharedAgentManifest(
|
|
|
101
115
|
requiredSecrets.add(knowledge.embedding.secret);
|
|
102
116
|
}
|
|
103
117
|
|
|
118
|
+
if (transcription.secret) {
|
|
119
|
+
requiredSecrets.add(transcription.secret);
|
|
120
|
+
}
|
|
121
|
+
|
|
104
122
|
for (const tool of capsule.config.tools ?? []) {
|
|
105
123
|
for (const secret of tool.secrets ?? []) {
|
|
106
124
|
requiredSecrets.add(secret);
|
|
@@ -118,6 +136,7 @@ export function buildSharedAgentManifest(
|
|
|
118
136
|
name: capsule.config.name,
|
|
119
137
|
runtime: capsule.config.runtime,
|
|
120
138
|
provider: capsule.config.provider,
|
|
139
|
+
timeZone: capsule.config.timeZone ?? null,
|
|
121
140
|
prompt: toCapsulePath(capsule, capsule.instructionsPath),
|
|
122
141
|
secrets: Array.from(requiredSecrets).sort(),
|
|
123
142
|
tools: (capsule.config.tools ?? []).map((tool) => ({
|
|
@@ -130,6 +149,19 @@ export function buildSharedAgentManifest(
|
|
|
130
149
|
timeoutMs: tool.timeoutMs ?? null,
|
|
131
150
|
})),
|
|
132
151
|
channels: capsule.config.channels ?? [],
|
|
152
|
+
transcription: {
|
|
153
|
+
enabled: transcription.enabled,
|
|
154
|
+
provider: transcription.enabled ? transcription.provider : null,
|
|
155
|
+
model: transcription.enabled ? transcription.model : null,
|
|
156
|
+
secret: transcription.secret,
|
|
157
|
+
language: transcription.language,
|
|
158
|
+
prompt: transcription.prompt,
|
|
159
|
+
limits: {
|
|
160
|
+
maxDurationSeconds: transcription.limits.maxDurationSeconds ?? null,
|
|
161
|
+
maxBytes: transcription.limits.maxBytes ?? null,
|
|
162
|
+
},
|
|
163
|
+
rawAudioTtlSeconds: transcription.rawAudioTtlSeconds,
|
|
164
|
+
},
|
|
133
165
|
knowledge: {
|
|
134
166
|
enabled: knowledge.enabled,
|
|
135
167
|
sources: knowledge.sources.map((source) => ({
|
|
@@ -85,8 +85,8 @@ export async function loadDeployReadinessContext(
|
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
export function stableCloudProjectId(name: string): string {
|
|
89
|
-
return `proj_${createHash("sha256").update(name).digest("hex").slice(0, 16)}`;
|
|
88
|
+
export function stableCloudProjectId(name: string, accountId?: string | null): string {
|
|
89
|
+
return `proj_${createHash("sha256").update(`${accountId ? `account:${accountId}` : "anonymous"}:${name}`).digest("hex").slice(0, 16)}`;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
function isAgentKitManagedDeploySecret(
|
|
@@ -97,7 +97,7 @@ function isAgentKitManagedDeploySecret(
|
|
|
97
97
|
return true;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
if (
|
|
100
|
+
if (name === "AGENTKIT_PRIVATE_TOKEN") {
|
|
101
101
|
return true;
|
|
102
102
|
}
|
|
103
103
|
|