@andreprado/agentkit 0.1.0-alpha.8 → 0.1.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/README.md +18 -1
- package/docs/guides/add-channel.md +251 -7
- package/docs/guides/add-knowledge.md +10 -0
- package/docs/guides/add-managed-composio.md +165 -0
- package/docs/guides/add-tool.md +10 -3
- package/docs/guides/channel-security.md +162 -32
- package/docs/guides/connect-discord.md +178 -0
- package/docs/guides/connect-slack.md +126 -0
- package/docs/guides/connect-telegram.md +61 -1
- package/docs/guides/connect-whatsapp-evolution.md +121 -0
- package/docs/guides/connect-whatsapp-uazapi.md +139 -0
- package/docs/guides/connect-whatsapp-zapster.md +119 -16
- package/docs/guides/create-agent.md +31 -4
- package/docs/guides/debug-channel.md +159 -0
- package/docs/guides/improve-from-production.md +151 -0
- package/docs/guides/prepare-deploy.md +32 -14
- package/docs/guides/replay-production-traces.md +72 -0
- package/docs/guides/run-evals.md +95 -25
- package/docs/guides/security-rules.md +9 -5
- package/docs/guides/send-feedback.md +135 -0
- package/docs/guides/use-jev.md +67 -0
- package/docs/guides/use-provider.md +70 -3
- package/docs/llms-full.txt +295 -25
- package/docs/llms.txt +54 -7
- package/package.json +3 -7
- package/src/cli/args.ts +23 -2
- package/src/cli/cloud-client.ts +121 -9
- package/src/cli/commands/channels.ts +1185 -50
- package/src/cli/commands/feedback.ts +438 -0
- package/src/cli/commands/provider.ts +47 -0
- package/src/cli/commands/transcribe.ts +171 -0
- package/src/cli/deploy-chat-ui.ts +232 -18
- package/src/cli/deploy-readiness.ts +227 -14
- package/src/cli/help.ts +68 -8
- package/src/cli/index.ts +740 -35
- package/src/cli/new-command.ts +41 -0
- package/src/cloud/client.ts +4 -3
- package/src/cloud/contracts.ts +1 -1
- package/src/create-project.ts +18 -35
- package/src/index.ts +565 -11
- package/src/providers/codex-auth.ts +111 -0
- package/src/providers/pi.ts +88 -19
- package/src/providers/test.ts +36 -0
- package/src/providers/types.ts +8 -0
- package/src/runtime/channel-test-harness.ts +21 -1
- package/src/runtime/channels/discord.ts +896 -0
- package/src/runtime/channels/generic-webhook.ts +974 -0
- package/src/runtime/channels/slack.ts +646 -0
- package/src/runtime/channels/telegram.ts +466 -23
- package/src/runtime/channels/whatsapp-evolution.ts +1357 -0
- package/src/runtime/channels/whatsapp-meta.ts +9 -0
- package/src/runtime/channels/whatsapp-uazapi.ts +1323 -0
- package/src/runtime/channels/whatsapp-zapster.ts +674 -40
- package/src/runtime/channels.ts +89 -4
- package/src/runtime/chat.ts +70 -44
- package/src/runtime/config.ts +489 -20
- package/src/runtime/core/manifest.ts +75 -5
- package/src/runtime/core/targets.ts +5 -5
- package/src/runtime/deploy-readiness.ts +34 -4
- package/src/runtime/dev-server.ts +639 -39
- package/src/runtime/env.ts +8 -3
- package/src/runtime/evals.ts +445 -74
- package/src/runtime/improve.ts +868 -0
- package/src/runtime/inspect.ts +173 -4
- package/src/runtime/integrations/composio.ts +425 -0
- package/src/runtime/knowledge/retrieve.ts +25 -5
- package/src/runtime/knowledge/schema.ts +45 -1
- package/src/runtime/prompt-context.ts +141 -0
- package/src/runtime/runtime-contract.ts +71 -7
- package/src/runtime/skills.ts +95 -0
- package/src/runtime/targets/cloudflare/build.ts +1010 -208
- package/src/runtime/targets/container/server.ts +1 -1
- package/src/runtime/targets/vps/deploy.ts +26 -9
- package/src/runtime/tool-runner.ts +9 -1
- package/src/runtime/tools.ts +26 -2
- package/src/runtime/transcription.ts +483 -0
- package/src/storage/sqlite.ts +7 -2
- package/src/templates/blank.ts +37 -9
- package/src/templates/dentista.ts +40 -14
- package/src/templates/skills/agentkit-build-agent/SKILL.md +34 -5
- package/src/templates/skills/agentkit-build-agent/templates/appointment-intake.instructions.md +2 -1
- package/src/templates/skills/agentkit-capsule/SKILL.md +32 -3
- package/src/templates/skills/agentkit-capsule/references/docs-router.md +2 -2
- package/src/templates/skills/agentkit-channels/SKILL.md +71 -6
- package/src/templates/skills/agentkit-channels/references/channel-buffering.md +9 -2
- package/src/templates/skills/agentkit-channels/references/channel-debugging.md +34 -5
- package/src/templates/skills/agentkit-channels/references/discord.md +93 -0
- package/src/templates/skills/agentkit-channels/references/slack.md +56 -0
- package/src/templates/skills/agentkit-channels/references/telegram.md +39 -4
- package/src/templates/skills/agentkit-channels/references/whatsapp-evolution.md +57 -0
- package/src/templates/skills/agentkit-channels/references/whatsapp-uazapi.md +54 -0
- package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +42 -8
- package/src/templates/skills/agentkit-database/SKILL.md +11 -0
- package/src/templates/skills/agentkit-deploy/SKILL.md +9 -1
- package/src/templates/skills/agentkit-evals/SKILL.md +77 -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-improve/SKILL.md +96 -0
- package/src/templates/skills/agentkit-improve/references/replay-side-effects.md +18 -0
- package/src/templates/skills/agentkit-improve/references/trace-packets.md +22 -0
- package/src/templates/skills/agentkit-improve/templates/regression.eval.md +18 -0
- package/src/templates/skills/agentkit-integrations/SKILL.md +98 -0
- package/src/templates/skills/agentkit-knowledge/SKILL.md +4 -1
- package/src/templates/skills/agentkit-prompts/SKILL.md +3 -1
- package/src/templates/skills/agentkit-provider/SKILL.md +29 -4
- package/src/templates/skills/agentkit-security/SKILL.md +5 -2
- package/src/templates/skills/agentkit-tools/SKILL.md +8 -1
- package/src/templates/skills/agentkit-tools/examples/eval-safe-external-action.tool.md +8 -8
- package/src/templates/skills/agentkit-tools/examples/jev-service-fit.tool.md +110 -0
- package/src/templates/skills/agentkit-troubleshooting/SKILL.md +25 -1
- package/src/templates/support.ts +42 -12
- package/docs/guides/agentkit-skills-architecture.md +0 -471
- package/docs/guides/channels-implementation-map.md +0 -243
- package/docs/guides/channels-production-handoff.md +0 -101
- package/docs/portable-deploy-release-checklist.md +0 -41
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { chmod, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
6
|
+
|
|
7
|
+
import { refreshOpenAICodexToken, type OAuthCredentials } from "@earendil-works/pi-ai/oauth";
|
|
8
|
+
|
|
9
|
+
import { AgentKitError } from "../runtime/errors";
|
|
10
|
+
|
|
11
|
+
export function codexAuthPath(): string {
|
|
12
|
+
return join(homedir(), ".agentkit", "providers", "openai-codex.json");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function validateCredentials(value: unknown): OAuthCredentials {
|
|
16
|
+
if (!value || typeof value !== "object" ||
|
|
17
|
+
!("access" in value) || typeof value.access !== "string" || !value.access.trim() ||
|
|
18
|
+
!("refresh" in value) || typeof value.refresh !== "string" || !value.refresh.trim() ||
|
|
19
|
+
!("expires" in value) || typeof value.expires !== "number" || !Number.isFinite(value.expires) || value.expires <= 0) {
|
|
20
|
+
throw new AgentKitError("provider_auth_invalid", "Invalid Codex credentials. Run agentkit provider login openai-codex again.");
|
|
21
|
+
}
|
|
22
|
+
return value as OAuthCredentials;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function readCredentials(path: string): Promise<OAuthCredentials | null> {
|
|
26
|
+
let source: string;
|
|
27
|
+
try {
|
|
28
|
+
source = await readFile(path, "utf8");
|
|
29
|
+
} catch (error) {
|
|
30
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return null;
|
|
31
|
+
throw new AgentKitError("provider_auth_unreadable", "Cannot read the local Codex login. Check credential file permissions.");
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
return validateCredentials(JSON.parse(source));
|
|
35
|
+
} catch {
|
|
36
|
+
throw new AgentKitError("provider_auth_invalid", "Invalid Codex credentials. Run agentkit provider login openai-codex again.");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function writeCredentials(path: string, credentials: OAuthCredentials): Promise<void> {
|
|
41
|
+
validateCredentials(credentials);
|
|
42
|
+
const temporary = `${path}.${randomUUID()}.tmp`;
|
|
43
|
+
try {
|
|
44
|
+
await writeFile(temporary, JSON.stringify(credentials), { mode: 0o600, flag: "wx" });
|
|
45
|
+
await rename(temporary, path);
|
|
46
|
+
} finally {
|
|
47
|
+
await rm(temporary, { force: true });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function withAuthLock<T>(path: string, action: () => Promise<T>): Promise<T> {
|
|
52
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
53
|
+
await chmod(dirname(path), 0o700);
|
|
54
|
+
const lock = `${path}.lock`;
|
|
55
|
+
const deadline = Date.now() + 10_000;
|
|
56
|
+
while (true) {
|
|
57
|
+
try {
|
|
58
|
+
await mkdir(lock, { mode: 0o700 });
|
|
59
|
+
break;
|
|
60
|
+
} catch (error) {
|
|
61
|
+
if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
|
|
62
|
+
if (Date.now() >= deadline) {
|
|
63
|
+
throw new AgentKitError("provider_auth_busy", `Codex credentials are busy. Retry; if the previous process crashed, remove ${lock} after stopping AgentKit processes.`);
|
|
64
|
+
}
|
|
65
|
+
await delay(50);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
return await action();
|
|
70
|
+
} finally {
|
|
71
|
+
await rm(lock, { recursive: true, force: true });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function saveCodexLogin(credentials: OAuthCredentials, path = codexAuthPath()): Promise<void> {
|
|
76
|
+
await withAuthLock(path, () => writeCredentials(path, credentials));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function clearCodexLogin(path = codexAuthPath()): Promise<void> {
|
|
80
|
+
await withAuthLock(path, () => rm(path, { force: true }));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function codexLoginStatus(path = codexAuthPath()) {
|
|
84
|
+
const credentials = await readCredentials(path);
|
|
85
|
+
return {
|
|
86
|
+
provider: "openai-codex",
|
|
87
|
+
status: !credentials ? "logged_out" : credentials.expires <= Date.now() ? "refresh_required" : "logged_in",
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export async function getCodexApiKey(
|
|
92
|
+
path = codexAuthPath(),
|
|
93
|
+
refresh = refreshOpenAICodexToken,
|
|
94
|
+
): Promise<string> {
|
|
95
|
+
return withAuthLock(path, async () => {
|
|
96
|
+
const credentials = await readCredentials(path);
|
|
97
|
+
if (!credentials) {
|
|
98
|
+
throw new AgentKitError("provider_auth_required", "Run agentkit provider login openai-codex before using this provider.");
|
|
99
|
+
}
|
|
100
|
+
if (credentials.expires > Date.now() + 60_000) return credentials.access;
|
|
101
|
+
let updated: OAuthCredentials;
|
|
102
|
+
try {
|
|
103
|
+
updated = validateCredentials(await refresh(credentials.refresh));
|
|
104
|
+
} catch {
|
|
105
|
+
// Do not persist or expose provider error bodies containing credentials.
|
|
106
|
+
throw new AgentKitError("provider_auth_refresh_failed", "Could not refresh the Codex login. Run agentkit provider login openai-codex again.");
|
|
107
|
+
}
|
|
108
|
+
await writeCredentials(path, updated);
|
|
109
|
+
return updated.access;
|
|
110
|
+
});
|
|
111
|
+
}
|
package/src/providers/pi.ts
CHANGED
|
@@ -17,8 +17,11 @@ import type { AgentProviderName, AgentTool } from "../index";
|
|
|
17
17
|
import { AgentKitError } from "../runtime/errors";
|
|
18
18
|
import type { ProviderAdapter, ProviderRunInput, ProviderRunResult } from "./types";
|
|
19
19
|
|
|
20
|
-
const PI_PROVIDER_NAMES = ["openai", "anthropic", "openrouter"] as const satisfies AgentProviderName[];
|
|
20
|
+
const PI_PROVIDER_NAMES = ["openai", "openai-codex", "anthropic", "openrouter", "opencode", "opencode-go"] as const satisfies AgentProviderName[];
|
|
21
21
|
const MAX_TOOL_TURNS = 8;
|
|
22
|
+
const OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
|
|
23
|
+
const UNKNOWN_OPENROUTER_CONTEXT_WINDOW = 128000;
|
|
24
|
+
const UNKNOWN_OPENROUTER_MAX_TOKENS = 8192;
|
|
22
25
|
|
|
23
26
|
export const piProviderAdapters: ProviderAdapter[] = PI_PROVIDER_NAMES.map((name) => ({
|
|
24
27
|
name,
|
|
@@ -29,7 +32,7 @@ export const piProviderAdapters: ProviderAdapter[] = PI_PROVIDER_NAMES.map((name
|
|
|
29
32
|
|
|
30
33
|
async function runPiProvider(input: ProviderRunInput): Promise<ProviderRunResult> {
|
|
31
34
|
const provider = toPiProvider(input.agent.provider.name);
|
|
32
|
-
const apiKey = requireProviderApiKey(provider, input.env ?? process.env);
|
|
35
|
+
const apiKey = input.apiKey ?? requireProviderApiKey(provider, input.env ?? process.env);
|
|
33
36
|
const model = resolveModel(provider, input.agent.provider.model);
|
|
34
37
|
const messages = toPiMessages(input.messages);
|
|
35
38
|
const tools = input.tools.map(toPiTool);
|
|
@@ -97,7 +100,7 @@ async function runPiProvider(input: ProviderRunInput): Promise<ProviderRunResult
|
|
|
97
100
|
content: [
|
|
98
101
|
{
|
|
99
102
|
type: "text",
|
|
100
|
-
text:
|
|
103
|
+
text: providerToolResultText(result),
|
|
101
104
|
},
|
|
102
105
|
],
|
|
103
106
|
isError: false,
|
|
@@ -109,6 +112,19 @@ async function runPiProvider(input: ProviderRunInput): Promise<ProviderRunResult
|
|
|
109
112
|
throw new AgentKitError("runtime_error", `Pi provider exceeded ${MAX_TOOL_TURNS} tool turns.`);
|
|
110
113
|
}
|
|
111
114
|
|
|
115
|
+
export function providerToolResultText(result: {
|
|
116
|
+
name: string;
|
|
117
|
+
visibility?: "user" | "internal";
|
|
118
|
+
rendered?: { text?: string };
|
|
119
|
+
output: unknown;
|
|
120
|
+
}): string {
|
|
121
|
+
if (result.visibility === "internal") {
|
|
122
|
+
return `Internal tool ${result.name} completed.`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return result.rendered?.text ?? JSON.stringify(result.output);
|
|
126
|
+
}
|
|
127
|
+
|
|
112
128
|
async function runPiTurn(
|
|
113
129
|
model: Model<any>,
|
|
114
130
|
context: Parameters<typeof stream>[1],
|
|
@@ -143,7 +159,14 @@ async function runPiTurn(
|
|
|
143
159
|
}
|
|
144
160
|
|
|
145
161
|
function toPiProvider(provider: string): Provider {
|
|
146
|
-
if (
|
|
162
|
+
if (
|
|
163
|
+
provider === "openai" ||
|
|
164
|
+
provider === "openai-codex" ||
|
|
165
|
+
provider === "anthropic" ||
|
|
166
|
+
provider === "openrouter" ||
|
|
167
|
+
provider === "opencode" ||
|
|
168
|
+
provider === "opencode-go"
|
|
169
|
+
) {
|
|
147
170
|
return provider;
|
|
148
171
|
}
|
|
149
172
|
|
|
@@ -151,6 +174,10 @@ function toPiProvider(provider: string): Provider {
|
|
|
151
174
|
}
|
|
152
175
|
|
|
153
176
|
function requireProviderApiKey(provider: Provider, env: Record<string, string | undefined>): string {
|
|
177
|
+
if (provider === "openai-codex") {
|
|
178
|
+
throw new AgentKitError("provider_auth_required", "Run agentkit provider login openai-codex, then use local chat, dev, or eval.");
|
|
179
|
+
}
|
|
180
|
+
|
|
154
181
|
const envNames = findEnvKeys(provider) ?? defaultProviderSecretNames(provider);
|
|
155
182
|
const setName = envNames.find((name) => env[name]);
|
|
156
183
|
|
|
@@ -165,6 +192,10 @@ function requireProviderApiKey(provider: Provider, env: Record<string, string |
|
|
|
165
192
|
}
|
|
166
193
|
|
|
167
194
|
function defaultProviderSecretNames(provider: Provider): string[] {
|
|
195
|
+
if (provider === "opencode" || provider === "opencode-go") {
|
|
196
|
+
return ["OPENCODE_API_KEY"];
|
|
197
|
+
}
|
|
198
|
+
|
|
168
199
|
return [`${provider.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_API_KEY`];
|
|
169
200
|
}
|
|
170
201
|
|
|
@@ -176,25 +207,56 @@ function formatSecretList(names: string[]): string {
|
|
|
176
207
|
return `one of: ${names.join(", ")}`;
|
|
177
208
|
}
|
|
178
209
|
|
|
179
|
-
function resolveModel(provider: Provider, modelId: string): Model<any> {
|
|
180
|
-
const
|
|
210
|
+
export function resolveModel(provider: Provider, modelId: string): Model<any> {
|
|
211
|
+
const model = getModel(provider as any, modelId as any) as Model<any> | undefined;
|
|
181
212
|
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
"provider_model_unsupported",
|
|
185
|
-
`Pi SDK could not resolve provider "${provider}" model "${modelId}".`,
|
|
186
|
-
);
|
|
213
|
+
if (model) {
|
|
214
|
+
return model;
|
|
187
215
|
}
|
|
188
216
|
|
|
189
|
-
|
|
190
|
-
return
|
|
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
|
-
);
|
|
217
|
+
if (provider === "openrouter") {
|
|
218
|
+
return createOpenRouterPassThroughModel(modelId);
|
|
197
219
|
}
|
|
220
|
+
|
|
221
|
+
throw new AgentKitError(
|
|
222
|
+
"provider_model_unsupported",
|
|
223
|
+
`Pi SDK could not resolve provider "${provider}" model "${modelId}". ${knownModelHint(provider)}`,
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function createOpenRouterPassThroughModel(modelId: string): Model<"openai-completions"> {
|
|
228
|
+
return {
|
|
229
|
+
id: modelId,
|
|
230
|
+
name: `OpenRouter ${modelId}`,
|
|
231
|
+
api: "openai-completions",
|
|
232
|
+
provider: "openrouter",
|
|
233
|
+
baseUrl: OPENROUTER_BASE_URL,
|
|
234
|
+
reasoning: false,
|
|
235
|
+
input: ["text"],
|
|
236
|
+
cost: {
|
|
237
|
+
input: 0,
|
|
238
|
+
output: 0,
|
|
239
|
+
cacheRead: 0,
|
|
240
|
+
cacheWrite: 0,
|
|
241
|
+
},
|
|
242
|
+
contextWindow: UNKNOWN_OPENROUTER_CONTEXT_WINDOW,
|
|
243
|
+
maxTokens: UNKNOWN_OPENROUTER_MAX_TOKENS,
|
|
244
|
+
compat: {
|
|
245
|
+
openRouterRouting: {},
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function knownModelHint(provider: Provider): string {
|
|
251
|
+
const examples = getModels(provider as any)
|
|
252
|
+
.slice(0, 5)
|
|
253
|
+
.map((model) => model.id);
|
|
254
|
+
|
|
255
|
+
if (examples.length === 0) {
|
|
256
|
+
return "Use a model id supported by the installed Pi SDK for that provider.";
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return `Use a model id supported by the installed Pi SDK for that provider. Examples: ${examples.join(", ")}.`;
|
|
198
260
|
}
|
|
199
261
|
|
|
200
262
|
function toPiMessages(messages: ProviderRunInput["messages"]): Message[] {
|
|
@@ -244,6 +306,13 @@ function normalizeUsage(usage: Usage | undefined): ProviderRunResult["usage"] |
|
|
|
244
306
|
inputTokens: usage.input,
|
|
245
307
|
outputTokens: usage.output,
|
|
246
308
|
totalTokens: usage.totalTokens,
|
|
309
|
+
cost: {
|
|
310
|
+
input: usage.cost.input,
|
|
311
|
+
output: usage.cost.output,
|
|
312
|
+
cacheRead: usage.cost.cacheRead,
|
|
313
|
+
cacheWrite: usage.cost.cacheWrite,
|
|
314
|
+
total: usage.cost.total,
|
|
315
|
+
},
|
|
247
316
|
};
|
|
248
317
|
}
|
|
249
318
|
|
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
|
}
|
package/src/providers/types.ts
CHANGED
|
@@ -15,6 +15,7 @@ export type ProviderRunInput = {
|
|
|
15
15
|
tools: AgentTool[];
|
|
16
16
|
toolRuntime?: ToolRuntime;
|
|
17
17
|
env?: Record<string, string | undefined>;
|
|
18
|
+
apiKey?: string;
|
|
18
19
|
signal?: AbortSignal;
|
|
19
20
|
};
|
|
20
21
|
|
|
@@ -24,6 +25,13 @@ export type ProviderRunResult = {
|
|
|
24
25
|
inputTokens?: number;
|
|
25
26
|
outputTokens?: number;
|
|
26
27
|
totalTokens?: number;
|
|
28
|
+
cost?: {
|
|
29
|
+
input?: number;
|
|
30
|
+
output?: number;
|
|
31
|
+
cacheRead?: number;
|
|
32
|
+
cacheWrite?: number;
|
|
33
|
+
total?: number;
|
|
34
|
+
};
|
|
27
35
|
};
|
|
28
36
|
raw?: unknown;
|
|
29
37
|
};
|
|
@@ -8,11 +8,31 @@ 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
|
-
| "zapster-unsupported-media"
|
|
17
|
+
| "zapster-unsupported-media"
|
|
18
|
+
| "uazapi-message"
|
|
19
|
+
| "uazapi-audio-message"
|
|
20
|
+
| "uazapi-duplicate-message"
|
|
21
|
+
| "uazapi-unsupported-media"
|
|
22
|
+
| "uazapi-was-sent-by-api"
|
|
23
|
+
| "evolution-message"
|
|
24
|
+
| "evolution-audio-message"
|
|
25
|
+
| "evolution-captioned-media"
|
|
26
|
+
| "evolution-duplicate-message"
|
|
27
|
+
| "evolution-from-me"
|
|
28
|
+
| "evolution-unsupported-media"
|
|
29
|
+
| "discord-command"
|
|
30
|
+
| "discord-message-create"
|
|
31
|
+
| "discord-ping"
|
|
32
|
+
| "slack-app-mention"
|
|
33
|
+
| "slack-direct-message"
|
|
34
|
+
| "generic-webhook-message"
|
|
35
|
+
| "generic-webhook-duplicate";
|
|
16
36
|
|
|
17
37
|
export type ChannelFixture = {
|
|
18
38
|
name: ChannelFixtureName;
|