@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
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { findAgentCapsuleRoot, loadAgentCapsule } from "../runtime/config";
|
|
2
|
-
import {
|
|
3
|
-
import { loadDeployReadinessContext, stableCloudProjectId, type DeployReadinessContext } from "../runtime/deploy-readiness";
|
|
2
|
+
import { loadDeployReadinessContext, type DeployReadinessContext } from "../runtime/deploy-readiness";
|
|
4
3
|
import { loadCapsuleEnv } from "../runtime/env";
|
|
5
4
|
import { isAgentKitError } from "../runtime/errors";
|
|
6
5
|
import {
|
|
7
6
|
cloudApiRequest,
|
|
8
7
|
formatCloudAuthSource,
|
|
9
|
-
|
|
8
|
+
readCloudAuthForApiUrl,
|
|
10
9
|
type CloudCapabilitiesResponse,
|
|
11
10
|
type CloudLimitsResponse,
|
|
12
11
|
type CloudMeResponse,
|
|
12
|
+
type CloudProjectResolveResponse,
|
|
13
13
|
type CloudSecretsResponse,
|
|
14
14
|
} from "./cloud-client";
|
|
15
15
|
|
|
@@ -34,7 +34,7 @@ export async function checkDeployReadiness(options: {
|
|
|
34
34
|
requireLogin: boolean;
|
|
35
35
|
}): Promise<DeployReadinessReport> {
|
|
36
36
|
const context = await loadDeployReadinessContext(process.cwd(), process.env);
|
|
37
|
-
const auth = await
|
|
37
|
+
const auth = options.requireLogin ? await readCloudAuthForApiUrl(options.apiUrl) : null;
|
|
38
38
|
const checks: DeployReadinessCheck[] = [];
|
|
39
39
|
let cloudAuthUsable = false;
|
|
40
40
|
|
|
@@ -82,6 +82,19 @@ export async function checkDeployReadiness(options: {
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
if (cloudAuthUsable) {
|
|
86
|
+
try {
|
|
87
|
+
context.projectId = await resolveCloudProjectId(options.apiUrl, context.projectName);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
checks.push({
|
|
90
|
+
status: "fail",
|
|
91
|
+
title: "Project identity",
|
|
92
|
+
message: `Could not resolve the account-scoped AgentKit Cloud project. ${formatReadinessError(error)}`,
|
|
93
|
+
});
|
|
94
|
+
cloudAuthUsable = false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
85
98
|
if (cloudAuthUsable) {
|
|
86
99
|
try {
|
|
87
100
|
const payload = (await cloudApiRequest(options.apiUrl, "/v1/me/capabilities", {
|
|
@@ -315,16 +328,24 @@ export function formatReadinessError(error: unknown): string {
|
|
|
315
328
|
return error instanceof Error ? error.message : String(error);
|
|
316
329
|
}
|
|
317
330
|
|
|
318
|
-
export async function resolveProjectIdForSecretCommand(cwd: string): Promise<string> {
|
|
319
|
-
const
|
|
331
|
+
export async function resolveProjectIdForSecretCommand(cwd: string, apiUrl: string): Promise<string> {
|
|
332
|
+
const root = await findAgentCapsuleRoot(cwd);
|
|
333
|
+
const capsule = await loadAgentCapsule(root);
|
|
334
|
+
return resolveCloudProjectId(apiUrl, capsule.config.name);
|
|
335
|
+
}
|
|
320
336
|
|
|
321
|
-
|
|
322
|
-
|
|
337
|
+
async function resolveCloudProjectId(apiUrl: string, projectName: string): Promise<string> {
|
|
338
|
+
const payload = (await cloudApiRequest(apiUrl, "/v1/projects/resolve", {
|
|
339
|
+
method: "POST",
|
|
340
|
+
body: JSON.stringify({ project_name: projectName }),
|
|
341
|
+
})) as CloudProjectResolveResponse;
|
|
342
|
+
const projectId = payload.project?.id;
|
|
343
|
+
|
|
344
|
+
if (!projectId) {
|
|
345
|
+
throw new Error("AgentKit Cloud did not return a project id.");
|
|
323
346
|
}
|
|
324
347
|
|
|
325
|
-
|
|
326
|
-
const capsule = await loadAgentCapsule(root);
|
|
327
|
-
return stableCloudProjectId(capsule.config.name);
|
|
348
|
+
return projectId;
|
|
328
349
|
}
|
|
329
350
|
|
|
330
351
|
function secretSetCommand(secret: string, source: DeployReadinessContext["localSecrets"][string] | undefined): string {
|
package/src/cli/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
4
|
import { dirname, join, relative, resolve } from "node:path";
|
|
5
5
|
|
|
6
6
|
import { createProject } from "../create-project";
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
clearCloudAuth,
|
|
39
39
|
cloudApiRequest,
|
|
40
40
|
readCloudAuth,
|
|
41
|
+
readCloudAuthForApiUrl,
|
|
41
42
|
readCloudError,
|
|
42
43
|
resolveCloudApiUrl,
|
|
43
44
|
verifyCloudLogin,
|
|
@@ -607,10 +608,10 @@ async function main() {
|
|
|
607
608
|
}
|
|
608
609
|
|
|
609
610
|
const apiUrl = await resolveCloudApiUrl(args.flags.api);
|
|
610
|
-
const auth = await
|
|
611
|
+
const auth = anonymous ? null : await readCloudAuthForApiUrl(apiUrl);
|
|
611
612
|
const deploy = await deployBuildToAgentKitCloud(result, {
|
|
612
613
|
apiUrl,
|
|
613
|
-
apiToken: auth?.token,
|
|
614
|
+
apiToken: anonymous ? null : auth?.token,
|
|
614
615
|
anonymous: anonymous || !auth?.token,
|
|
615
616
|
});
|
|
616
617
|
const statePath = await writeLocalDeployState(result.root, deploy);
|
|
@@ -659,8 +660,8 @@ async function main() {
|
|
|
659
660
|
|
|
660
661
|
if (args.command === "secret") {
|
|
661
662
|
const [subcommand, name, ...valueParts] = args.positional;
|
|
662
|
-
const projectId = await resolveProjectIdForSecretCommand(process.cwd());
|
|
663
663
|
const apiUrl = await resolveCloudApiUrl(args.flags.api);
|
|
664
|
+
const projectId = await resolveProjectIdForSecretCommand(process.cwd(), apiUrl);
|
|
664
665
|
|
|
665
666
|
if (subcommand === "list") {
|
|
666
667
|
const payload = await cloudApiRequest(apiUrl, `/v1/projects/${encodeURIComponent(projectId)}/secrets`, {
|
|
@@ -949,9 +950,12 @@ async function ensureDeployChatAccessToken(options: {
|
|
|
949
950
|
`/v1/deploys/${encodeURIComponent(options.deployId)}/access-tokens`,
|
|
950
951
|
{ method: "GET" },
|
|
951
952
|
)) as DeployAccessTokenListResponse;
|
|
952
|
-
const
|
|
953
|
+
const stillUsable = (listed.access_tokens ?? []).some(
|
|
954
|
+
(token) => token.id === existing.id && deployAccessTokenMetadataIsUsable(token),
|
|
955
|
+
);
|
|
953
956
|
|
|
954
|
-
if (
|
|
957
|
+
if (stillUsable) {
|
|
958
|
+
await chmod(path, 0o600);
|
|
955
959
|
return { status: "ready", path, tokenId: existing.id, created: false };
|
|
956
960
|
}
|
|
957
961
|
}
|
|
@@ -977,6 +981,15 @@ async function ensureDeployChatAccessToken(options: {
|
|
|
977
981
|
}
|
|
978
982
|
}
|
|
979
983
|
|
|
984
|
+
function deployAccessTokenMetadataIsUsable(token: { expires_at?: string }): boolean {
|
|
985
|
+
if (!token.expires_at) {
|
|
986
|
+
return true;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
const expiresAtMs = Date.parse(token.expires_at);
|
|
990
|
+
return Number.isFinite(expiresAtMs) && expiresAtMs > Date.now();
|
|
991
|
+
}
|
|
992
|
+
|
|
980
993
|
async function readDeployAccessTokenFile(path: string): Promise<{ id?: string; deploy_id?: string } | null> {
|
|
981
994
|
try {
|
|
982
995
|
const parsed = JSON.parse(await readFile(path, "utf8")) as DeployAccessTokenCreateResponse;
|
|
@@ -989,6 +1002,7 @@ async function readDeployAccessTokenFile(path: string): Promise<{ id?: string; d
|
|
|
989
1002
|
async function writeSecretJson(path: string, value: unknown): Promise<void> {
|
|
990
1003
|
await mkdir(dirname(path), { recursive: true });
|
|
991
1004
|
await writeFile(path, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
|
|
1005
|
+
await chmod(path, 0o600);
|
|
992
1006
|
}
|
|
993
1007
|
|
|
994
1008
|
async function requireLocalDeployState(): Promise<LocalDeployState> {
|
package/src/cloud/client.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
1
|
+
import { chmod, mkdir, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
4
|
import type { AgentBuildResult } from "../runtime/targets/cloudflare/build";
|
|
@@ -15,7 +15,7 @@ export async function deployBuildToAgentKitCloud(
|
|
|
15
15
|
const headers = new Headers({
|
|
16
16
|
"Content-Type": "application/json",
|
|
17
17
|
});
|
|
18
|
-
const apiToken = options.apiToken ?? process.env.AGENTKIT_CLOUD_API_TOKEN;
|
|
18
|
+
const apiToken = options.anonymous ? undefined : options.apiToken ?? process.env.AGENTKIT_CLOUD_API_TOKEN;
|
|
19
19
|
|
|
20
20
|
if (apiToken) {
|
|
21
21
|
headers.set("Authorization", `Bearer ${apiToken}`);
|
|
@@ -70,7 +70,8 @@ export async function writeLocalDeployState(root: string, deploy: CreateDeployRe
|
|
|
70
70
|
};
|
|
71
71
|
|
|
72
72
|
await mkdir(join(root, ".agentkit"), { recursive: true });
|
|
73
|
-
await writeFile(statePath, `${JSON.stringify(state, null, 2)}\n
|
|
73
|
+
await writeFile(statePath, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
|
|
74
|
+
await chmod(statePath, 0o600);
|
|
74
75
|
return statePath;
|
|
75
76
|
}
|
|
76
77
|
|
package/src/cloud/contracts.ts
CHANGED
package/src/create-project.ts
CHANGED
|
@@ -114,7 +114,7 @@ async function resolveAgentKitDependency(): Promise<string> {
|
|
|
114
114
|
|
|
115
115
|
const packageRoot = resolve(moduleDir, "..");
|
|
116
116
|
|
|
117
|
-
if (await
|
|
117
|
+
if (await pathExists(resolve(packageRoot, "../..", ".git"))) {
|
|
118
118
|
return `file:${packageRoot}`;
|
|
119
119
|
}
|
|
120
120
|
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,8 @@ export type ChannelType = "website" | "telegram" | "whatsapp";
|
|
|
6
6
|
export type ChannelProvider = "agentkit" | "telegram" | "zapster" | "meta";
|
|
7
7
|
export type WhatsappChannelProvider = "zapster" | "meta";
|
|
8
8
|
export type TelegramAllowedUpdate = "message";
|
|
9
|
+
export type ChannelAudioMode = "off" | "reject" | "transcribe";
|
|
10
|
+
export type TranscriptionProviderName = "test" | "openai" | "groq";
|
|
9
11
|
|
|
10
12
|
export type AgentProvider = {
|
|
11
13
|
name: AgentProviderName;
|
|
@@ -39,6 +41,45 @@ export type ChannelBufferConfig =
|
|
|
39
41
|
maxChars: number;
|
|
40
42
|
};
|
|
41
43
|
|
|
44
|
+
export type ChannelAudioInput = {
|
|
45
|
+
mode?: ChannelAudioMode;
|
|
46
|
+
fallbackMessage?: string;
|
|
47
|
+
maxDurationSeconds?: number;
|
|
48
|
+
maxBytes?: number;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type ChannelAudioConfig =
|
|
52
|
+
| {
|
|
53
|
+
mode: "off";
|
|
54
|
+
}
|
|
55
|
+
| {
|
|
56
|
+
mode: "reject";
|
|
57
|
+
fallbackMessage: string;
|
|
58
|
+
maxDurationSeconds?: number;
|
|
59
|
+
maxBytes?: number;
|
|
60
|
+
}
|
|
61
|
+
| {
|
|
62
|
+
mode: "transcribe";
|
|
63
|
+
fallbackMessage: string;
|
|
64
|
+
maxDurationSeconds?: number;
|
|
65
|
+
maxBytes?: number;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type AgentTranscriptionLimits = {
|
|
69
|
+
maxDurationSeconds?: number;
|
|
70
|
+
maxBytes?: number;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export type AgentTranscriptionConfig = {
|
|
74
|
+
provider: TranscriptionProviderName;
|
|
75
|
+
model: string;
|
|
76
|
+
secret?: string;
|
|
77
|
+
language?: string;
|
|
78
|
+
prompt?: string;
|
|
79
|
+
limits?: AgentTranscriptionLimits;
|
|
80
|
+
rawAudioTtlSeconds?: number;
|
|
81
|
+
};
|
|
82
|
+
|
|
42
83
|
export type WebsiteChannelAccess = {
|
|
43
84
|
mode: "token";
|
|
44
85
|
};
|
|
@@ -49,6 +90,7 @@ export type WebsiteChannelInput = {
|
|
|
49
90
|
secrets?: string[];
|
|
50
91
|
limits?: ChannelLimits;
|
|
51
92
|
buffer?: ChannelBufferInput;
|
|
93
|
+
audio?: ChannelAudioInput;
|
|
52
94
|
};
|
|
53
95
|
|
|
54
96
|
export type WebsiteChannelConfig = {
|
|
@@ -59,6 +101,7 @@ export type WebsiteChannelConfig = {
|
|
|
59
101
|
secrets: string[];
|
|
60
102
|
limits?: ChannelLimits;
|
|
61
103
|
buffer?: ChannelBufferConfig;
|
|
104
|
+
audio?: ChannelAudioConfig;
|
|
62
105
|
};
|
|
63
106
|
|
|
64
107
|
export type TelegramChannelInput = {
|
|
@@ -67,6 +110,7 @@ export type TelegramChannelInput = {
|
|
|
67
110
|
allowedUpdates?: TelegramAllowedUpdate[];
|
|
68
111
|
limits?: ChannelLimits;
|
|
69
112
|
buffer?: ChannelBufferInput;
|
|
113
|
+
audio?: ChannelAudioInput;
|
|
70
114
|
};
|
|
71
115
|
|
|
72
116
|
export type TelegramChannelConfig = {
|
|
@@ -77,6 +121,7 @@ export type TelegramChannelConfig = {
|
|
|
77
121
|
allowedUpdates: TelegramAllowedUpdate[];
|
|
78
122
|
limits?: ChannelLimits;
|
|
79
123
|
buffer?: ChannelBufferConfig;
|
|
124
|
+
audio?: ChannelAudioConfig;
|
|
80
125
|
};
|
|
81
126
|
|
|
82
127
|
export type WhatsappChannelInput = {
|
|
@@ -85,6 +130,7 @@ export type WhatsappChannelInput = {
|
|
|
85
130
|
secrets?: string[];
|
|
86
131
|
limits?: ChannelLimits;
|
|
87
132
|
buffer?: ChannelBufferInput;
|
|
133
|
+
audio?: ChannelAudioInput;
|
|
88
134
|
};
|
|
89
135
|
|
|
90
136
|
export type WhatsappChannelConfig = {
|
|
@@ -94,6 +140,7 @@ export type WhatsappChannelConfig = {
|
|
|
94
140
|
secrets: string[];
|
|
95
141
|
limits?: ChannelLimits;
|
|
96
142
|
buffer?: ChannelBufferConfig;
|
|
143
|
+
audio?: ChannelAudioConfig;
|
|
97
144
|
};
|
|
98
145
|
|
|
99
146
|
export type AgentChannel = WebsiteChannelConfig | TelegramChannelConfig | WhatsappChannelConfig;
|
|
@@ -210,6 +257,7 @@ export type ToolRenderResult = {
|
|
|
210
257
|
export type ToolRenderContext<Input = unknown> = {
|
|
211
258
|
input: Input;
|
|
212
259
|
runtime: ToolRuntimeContext;
|
|
260
|
+
clock: ToolClockContext;
|
|
213
261
|
};
|
|
214
262
|
|
|
215
263
|
export type ToolRuntimeContext = {
|
|
@@ -219,10 +267,20 @@ export type ToolRuntimeContext = {
|
|
|
219
267
|
database: "sqlite" | "turso" | "none";
|
|
220
268
|
};
|
|
221
269
|
|
|
270
|
+
export type ToolClockContext = {
|
|
271
|
+
now: Date;
|
|
272
|
+
isoTimestamp: string;
|
|
273
|
+
timeZone: string;
|
|
274
|
+
localDate: string;
|
|
275
|
+
localWeekday: string;
|
|
276
|
+
localDateTime: string;
|
|
277
|
+
};
|
|
278
|
+
|
|
222
279
|
export type ToolContext = {
|
|
223
280
|
secrets: Record<string, string>;
|
|
224
281
|
signal: AbortSignal;
|
|
225
282
|
runtime: ToolRuntimeContext;
|
|
283
|
+
clock: ToolClockContext;
|
|
226
284
|
database: DatabaseRunner;
|
|
227
285
|
db: DatabaseRunner;
|
|
228
286
|
storage: {
|
|
@@ -254,10 +312,12 @@ export type AgentConfig = {
|
|
|
254
312
|
name: string;
|
|
255
313
|
runtime: AgentRuntime;
|
|
256
314
|
provider: AgentProvider;
|
|
315
|
+
timeZone?: string;
|
|
257
316
|
instructions: string;
|
|
258
317
|
secrets: string[];
|
|
259
318
|
tools?: AgentTool[];
|
|
260
319
|
channels?: AgentChannel[];
|
|
320
|
+
transcription?: AgentTranscriptionConfig;
|
|
261
321
|
knowledge?: AgentKnowledgeConfig;
|
|
262
322
|
access: {
|
|
263
323
|
mode: AccessMode;
|
|
@@ -287,6 +347,7 @@ export function websiteChannel(input: WebsiteChannelInput): WebsiteChannelConfig
|
|
|
287
347
|
secrets: normalizeChannelSecrets(input.secrets ?? ["AGENTKIT_WEBSITE_CHANNEL_TOKEN"], "website channel"),
|
|
288
348
|
...(input.limits ? { limits: input.limits } : {}),
|
|
289
349
|
...(input.buffer ? { buffer: normalizeChannelBuffer(input.buffer, "website channel") } : {}),
|
|
350
|
+
...(input.audio ? { audio: normalizeChannelAudio(input.audio, "website channel") } : {}),
|
|
290
351
|
};
|
|
291
352
|
}
|
|
292
353
|
|
|
@@ -302,6 +363,7 @@ export function telegramChannel(input: TelegramChannelInput): TelegramChannelCon
|
|
|
302
363
|
allowedUpdates: input.allowedUpdates ?? ["message"],
|
|
303
364
|
...(input.limits ? { limits: input.limits } : {}),
|
|
304
365
|
...(input.buffer ? { buffer: normalizeChannelBuffer(input.buffer, "telegram channel") } : {}),
|
|
366
|
+
...(input.audio ? { audio: normalizeChannelAudio(input.audio, "telegram channel") } : {}),
|
|
305
367
|
};
|
|
306
368
|
}
|
|
307
369
|
|
|
@@ -316,6 +378,7 @@ export function whatsappChannel(input: WhatsappChannelInput): WhatsappChannelCon
|
|
|
316
378
|
),
|
|
317
379
|
...(input.limits ? { limits: input.limits } : {}),
|
|
318
380
|
...(input.buffer ? { buffer: normalizeChannelBuffer(input.buffer, `${input.provider} whatsapp channel`) } : {}),
|
|
381
|
+
...(input.audio ? { audio: normalizeChannelAudio(input.audio, `${input.provider} whatsapp channel`) } : {}),
|
|
319
382
|
};
|
|
320
383
|
}
|
|
321
384
|
|
|
@@ -370,6 +433,33 @@ function normalizeChannelBuffer(input: ChannelBufferInput, context: string): Cha
|
|
|
370
433
|
return buffer;
|
|
371
434
|
}
|
|
372
435
|
|
|
436
|
+
function normalizeChannelAudio(input: ChannelAudioInput, context: string): ChannelAudioConfig {
|
|
437
|
+
const mode = input.mode ?? "transcribe";
|
|
438
|
+
|
|
439
|
+
if (mode !== "off" && mode !== "reject" && mode !== "transcribe") {
|
|
440
|
+
throw new Error(`${context} audio.mode must be "off", "reject", or "transcribe".`);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (mode === "off") {
|
|
444
|
+
return { mode: "off" };
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (input.maxDurationSeconds !== undefined) {
|
|
448
|
+
validatePositiveInteger(input.maxDurationSeconds, `${context} audio.maxDurationSeconds`);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (input.maxBytes !== undefined) {
|
|
452
|
+
validatePositiveInteger(input.maxBytes, `${context} audio.maxBytes`);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return {
|
|
456
|
+
mode,
|
|
457
|
+
fallbackMessage: input.fallbackMessage ?? "I received an audio message, but I could not transcribe it. Please send the message as text.",
|
|
458
|
+
...(input.maxDurationSeconds !== undefined ? { maxDurationSeconds: input.maxDurationSeconds } : {}),
|
|
459
|
+
...(input.maxBytes !== undefined ? { maxBytes: input.maxBytes } : {}),
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
373
463
|
function validatePositiveInteger(value: number, field: string): void {
|
|
374
464
|
if (!Number.isInteger(value) || value <= 0) {
|
|
375
465
|
throw new Error(`${field} must be a positive integer.`);
|
|
@@ -379,7 +469,18 @@ function validatePositiveInteger(value: number, field: string): void {
|
|
|
379
469
|
export { loadAgentCapsule, findAgentCapsuleRoot } from "./runtime/config";
|
|
380
470
|
export { runAgentMessage, runAgentMessageFromCwd } from "./runtime/chat";
|
|
381
471
|
export { listConversationsFromCwd, getConversationFromCwd } from "./runtime/conversations";
|
|
382
|
-
export { runEvalsFromCwd } from "./runtime/evals";
|
|
472
|
+
export { defineEval, runEvalsFromCwd } from "./runtime/evals";
|
|
473
|
+
export type {
|
|
474
|
+
EvalCase,
|
|
475
|
+
EvalExpect,
|
|
476
|
+
EvalResponseExpectation,
|
|
477
|
+
EvalRunSummary,
|
|
478
|
+
EvalResult,
|
|
479
|
+
EvalToolsContainerExpectation,
|
|
480
|
+
EvalToolsExpectation,
|
|
481
|
+
EvalTurn,
|
|
482
|
+
ToolExpectation,
|
|
483
|
+
} from "./runtime/evals";
|
|
383
484
|
export { getConversationTraceFromCwd } from "./runtime/traces";
|
|
384
485
|
export { runToolFromCwd } from "./runtime/tool-runner";
|
|
385
486
|
export { startAgentDevServer } from "./runtime/dev-server";
|
|
@@ -390,10 +491,13 @@ export { AgentKitError } from "./runtime/errors";
|
|
|
390
491
|
export type {
|
|
391
492
|
ChannelAdapter,
|
|
392
493
|
ChannelAdapterId,
|
|
494
|
+
ChannelAudioAttachment,
|
|
393
495
|
ChannelDeliveryDirection,
|
|
394
496
|
ChannelDeliveryState,
|
|
395
497
|
ChannelEventKind,
|
|
396
498
|
ChannelExternalIdentity,
|
|
499
|
+
ChannelMediaDownloadInput,
|
|
500
|
+
ChannelMediaDownloadResult,
|
|
397
501
|
ChannelMessageContentType,
|
|
398
502
|
ChannelMessageRole,
|
|
399
503
|
ChannelSendInput,
|
|
@@ -406,3 +510,8 @@ export type {
|
|
|
406
510
|
WebhookVerificationInput,
|
|
407
511
|
WebhookVerificationResult,
|
|
408
512
|
} from "./runtime/channels";
|
|
513
|
+
export type {
|
|
514
|
+
TranscriptionAdapter,
|
|
515
|
+
TranscriptionInput,
|
|
516
|
+
TranscriptionResult,
|
|
517
|
+
} from "./runtime/transcription";
|
package/src/providers/pi.ts
CHANGED
|
@@ -97,7 +97,7 @@ async function runPiProvider(input: ProviderRunInput): Promise<ProviderRunResult
|
|
|
97
97
|
content: [
|
|
98
98
|
{
|
|
99
99
|
type: "text",
|
|
100
|
-
text:
|
|
100
|
+
text: providerToolResultText(result),
|
|
101
101
|
},
|
|
102
102
|
],
|
|
103
103
|
isError: false,
|
|
@@ -109,6 +109,19 @@ async function runPiProvider(input: ProviderRunInput): Promise<ProviderRunResult
|
|
|
109
109
|
throw new AgentKitError("runtime_error", `Pi provider exceeded ${MAX_TOOL_TURNS} tool turns.`);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
export function providerToolResultText(result: {
|
|
113
|
+
name: string;
|
|
114
|
+
visibility?: "user" | "internal";
|
|
115
|
+
rendered?: { text?: string };
|
|
116
|
+
output: unknown;
|
|
117
|
+
}): string {
|
|
118
|
+
if (result.visibility === "internal") {
|
|
119
|
+
return `Internal tool ${result.name} completed.`;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return result.rendered?.text ?? JSON.stringify(result.output);
|
|
123
|
+
}
|
|
124
|
+
|
|
112
125
|
async function runPiTurn(
|
|
113
126
|
model: Model<any>,
|
|
114
127
|
context: Parameters<typeof stream>[1],
|
package/src/providers/test.ts
CHANGED
|
@@ -37,6 +37,17 @@ export const testProviderAdapter: ProviderAdapter = {
|
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
const currentDate = answerCurrentDate(input.instructions, userMessage.content);
|
|
41
|
+
|
|
42
|
+
if (currentDate) {
|
|
43
|
+
return {
|
|
44
|
+
message: {
|
|
45
|
+
role: "assistant",
|
|
46
|
+
content: currentDate,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
40
51
|
const rememberedName = answerRememberedName(input.messages);
|
|
41
52
|
|
|
42
53
|
if (rememberedName) {
|
|
@@ -95,6 +106,31 @@ function answerRememberedName(messages: AgentMessage[]): string | null {
|
|
|
95
106
|
return null;
|
|
96
107
|
}
|
|
97
108
|
|
|
109
|
+
function answerCurrentDate(instructions: string, content: string): string | null {
|
|
110
|
+
if (!/(today|current date|what date|data de hoje|hoje)/i.test(content)) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const localDate = readRuntimeContextValue(instructions, "Local date");
|
|
115
|
+
|
|
116
|
+
if (!localDate) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const localWeekday = readRuntimeContextValue(instructions, "Local weekday");
|
|
121
|
+
const timeZone = readRuntimeContextValue(instructions, "Time zone");
|
|
122
|
+
const weekday = localWeekday ? ` (${localWeekday})` : "";
|
|
123
|
+
const zone = timeZone ? ` in ${timeZone}` : "";
|
|
124
|
+
|
|
125
|
+
return `Today is ${localDate}${weekday}${zone}.`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function readRuntimeContextValue(instructions: string, label: string): string | null {
|
|
129
|
+
const escapedLabel = label.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
130
|
+
const match = instructions.match(new RegExp(`^- ${escapedLabel}: (.+)$`, "m"));
|
|
131
|
+
return match?.[1]?.trim() || null;
|
|
132
|
+
}
|
|
133
|
+
|
|
98
134
|
function asksForName(content: string): boolean {
|
|
99
135
|
return /what(?:'s| is) my name\??/i.test(content) || /(como|qual)\s+(é|e)\s*(o\s+)?meu nome\??/i.test(content);
|
|
100
136
|
}
|
|
@@ -8,9 +8,11 @@ import type { NormalizedChannelEvent, RawWebhookEvent } from "./channels";
|
|
|
8
8
|
export type ChannelFixtureName =
|
|
9
9
|
| "website-message"
|
|
10
10
|
| "telegram-message"
|
|
11
|
+
| "telegram-audio-message"
|
|
11
12
|
| "telegram-duplicate-message"
|
|
12
13
|
| "telegram-malformed-payload"
|
|
13
14
|
| "zapster-message"
|
|
15
|
+
| "zapster-audio-message"
|
|
14
16
|
| "zapster-duplicate-message"
|
|
15
17
|
| "zapster-unsupported-media";
|
|
16
18
|
|