@andreprado/agentkit 0.1.1 → 0.3.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 +8 -77
- package/docs/guides/add-channel.md +14 -92
- package/docs/guides/add-knowledge.md +0 -21
- package/docs/guides/add-tool.md +5 -11
- package/docs/guides/channel-security.md +3 -207
- package/docs/guides/connect-discord.md +7 -172
- package/docs/guides/connect-slack.md +6 -121
- package/docs/guides/connect-telegram.md +6 -165
- package/docs/guides/connect-whatsapp-evolution.md +6 -116
- package/docs/guides/connect-whatsapp-uazapi.md +6 -134
- package/docs/guides/connect-whatsapp-zapster.md +6 -202
- package/docs/guides/create-agent.md +5 -14
- package/docs/guides/debug-channel.md +4 -156
- package/docs/guides/improve-local.md +13 -0
- package/docs/guides/local-only-migration.md +35 -0
- package/docs/guides/replay-local-traces.md +11 -0
- package/docs/guides/run-evals.md +2 -4
- package/docs/guides/security-rules.md +5 -154
- package/docs/guides/use-jev.md +3 -6
- package/docs/guides/use-provider.md +5 -6
- package/docs/guides/write-feedback.md +10 -0
- package/docs/llms-full.txt +27 -448
- package/docs/llms.txt +8 -44
- package/package.json +3 -5
- package/src/cli/commands/channels.ts +8 -1613
- package/src/cli/commands/feedback.ts +8 -86
- package/src/cli/commands/provider.ts +29 -11
- package/src/cli/constants.ts +0 -3
- package/src/cli/flags.ts +0 -28
- package/src/cli/help.ts +16 -92
- package/src/cli/index.ts +15 -1091
- package/src/index.ts +6 -158
- package/src/providers/codex-auth.ts +16 -2
- package/src/providers/pi.ts +36 -19
- package/src/runtime/channels/discord.ts +2 -2
- package/src/runtime/chat.ts +5 -3
- package/src/runtime/config.ts +14 -148
- package/src/runtime/database.ts +2 -2
- package/src/runtime/dev-server.ts +8 -8
- package/src/runtime/env.ts +11 -0
- package/src/runtime/improve.ts +2 -262
- package/src/runtime/inspect.ts +13 -73
- package/src/runtime/knowledge/ingest.ts +1 -1
- package/src/runtime/knowledge/tool.ts +16 -2
- package/src/runtime/knowledge/vector.ts +1 -1
- package/src/runtime/tool-runner.ts +5 -3
- package/src/runtime/tools.ts +10 -14
- package/src/storage/sqlite.ts +11 -32
- package/src/templates/blank.ts +15 -102
- package/src/templates/common.ts +60 -0
- package/src/templates/dentista.ts +7 -74
- package/src/templates/skills/agentkit-capsule/SKILL.md +5 -7
- package/src/templates/skills/agentkit-capsule/references/docs-router.md +2 -3
- package/src/templates/skills/agentkit-channels/SKILL.md +6 -119
- package/src/templates/skills/agentkit-channels/references/channel-buffering.md +0 -9
- package/src/templates/skills/agentkit-channels/references/channel-debugging.md +1 -64
- package/src/templates/skills/agentkit-channels/references/discord.md +2 -92
- package/src/templates/skills/agentkit-channels/references/slack.md +2 -55
- package/src/templates/skills/agentkit-channels/references/telegram.md +2 -71
- package/src/templates/skills/agentkit-channels/references/whatsapp-evolution.md +2 -56
- package/src/templates/skills/agentkit-channels/references/whatsapp-uazapi.md +2 -53
- package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +2 -70
- package/src/templates/skills/agentkit-database/SKILL.md +2 -4
- package/src/templates/skills/agentkit-evals/SKILL.md +1 -1
- package/src/templates/skills/agentkit-improve/SKILL.md +6 -85
- package/src/templates/skills/agentkit-improve/references/trace-packets.md +1 -1
- package/src/templates/skills/agentkit-provider/SKILL.md +1 -2
- package/src/templates/skills/agentkit-security/SKILL.md +1 -3
- package/src/templates/skills/agentkit-tools/SKILL.md +1 -1
- package/src/templates/skills/agentkit-tools/examples/database-write.tool.md +1 -2
- package/src/templates/skills/agentkit-troubleshooting/SKILL.md +5 -11
- package/src/templates/support.ts +8 -92
- package/docs/guides/add-managed-composio.md +0 -165
- package/docs/guides/improve-from-production.md +0 -151
- package/docs/guides/prepare-deploy.md +0 -227
- package/docs/guides/replay-production-traces.md +0 -72
- package/docs/guides/send-feedback.md +0 -135
- package/src/cli/cloud-client.ts +0 -377
- package/src/cli/deploy-chat-ui.ts +0 -606
- package/src/cli/deploy-readiness.ts +0 -561
- package/src/cloud/artifact.ts +0 -139
- package/src/cloud/client.ts +0 -80
- package/src/cloud/contracts.ts +0 -63
- package/src/cloud/index.ts +0 -3
- package/src/runtime/build.ts +0 -43
- package/src/runtime/core/deploy-state.ts +0 -54
- package/src/runtime/core/manifest.ts +0 -283
- package/src/runtime/core/targets.ts +0 -133
- package/src/runtime/deploy-readiness.ts +0 -135
- package/src/runtime/deploy.ts +0 -1
- package/src/runtime/integrations/composio.ts +0 -425
- package/src/runtime/targets/cloudflare/build.ts +0 -3319
- package/src/runtime/targets/container/build.ts +0 -146
- package/src/runtime/targets/container/server.ts +0 -33
- package/src/runtime/targets/vps/deploy.ts +0 -223
- package/src/templates/skills/agentkit-deploy/SKILL.md +0 -52
- package/src/templates/skills/agentkit-integrations/SKILL.md +0 -98
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type AgentRuntime = "local"
|
|
1
|
+
export type AgentRuntime = "local";
|
|
2
2
|
export type AgentProviderName = "test" | "openai" | "openai-codex" | "anthropic" | "openrouter" | "opencode" | "opencode-go" | "custom";
|
|
3
3
|
export type AccessMode = "private" | "token" | "public";
|
|
4
4
|
export type ToolVisibility = "user" | "internal";
|
|
@@ -275,38 +275,12 @@ export type AgentChannel =
|
|
|
275
275
|
| GenericWebhookChannelConfig
|
|
276
276
|
| GenericWebhookOutputChannelConfig;
|
|
277
277
|
|
|
278
|
-
export type IntegrationTagsConfig = {
|
|
279
|
-
enable?: string[];
|
|
280
|
-
disable?: string[];
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
export type ComposioManagedIntegrationInput = {
|
|
284
|
-
name?: string;
|
|
285
|
-
toolkits: string[];
|
|
286
|
-
tools?: Record<string, string[]>;
|
|
287
|
-
tags?: IntegrationTagsConfig;
|
|
288
|
-
confirmExternalWrites?: boolean;
|
|
289
|
-
};
|
|
290
|
-
|
|
291
|
-
export type ComposioManagedIntegration = {
|
|
292
|
-
type: "composio";
|
|
293
|
-
provider: "composio";
|
|
294
|
-
mode: "managed";
|
|
295
|
-
name: string;
|
|
296
|
-
toolkits: string[];
|
|
297
|
-
tools?: Record<string, string[]>;
|
|
298
|
-
tags?: IntegrationTagsConfig;
|
|
299
|
-
confirmExternalWrites?: boolean;
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
export type AgentIntegration = ComposioManagedIntegration;
|
|
303
|
-
|
|
304
278
|
export type AgentDatabaseConfig =
|
|
305
279
|
| {
|
|
306
280
|
driver: "none";
|
|
307
281
|
}
|
|
308
282
|
| {
|
|
309
|
-
driver: "
|
|
283
|
+
driver: "sqlite";
|
|
310
284
|
schema?: string;
|
|
311
285
|
migrations?: string;
|
|
312
286
|
};
|
|
@@ -316,8 +290,7 @@ export type AgentFilesConfig =
|
|
|
316
290
|
driver: "none";
|
|
317
291
|
}
|
|
318
292
|
| {
|
|
319
|
-
driver: "
|
|
320
|
-
bucket?: string;
|
|
293
|
+
driver: "local";
|
|
321
294
|
prefix?: string;
|
|
322
295
|
maxUploadBytes?: number;
|
|
323
296
|
};
|
|
@@ -417,10 +390,10 @@ export type ToolRenderContext<Input = unknown> = {
|
|
|
417
390
|
};
|
|
418
391
|
|
|
419
392
|
export type ToolRuntimeContext = {
|
|
420
|
-
environment: "local" | "
|
|
393
|
+
environment: "local" | "eval" | "test";
|
|
421
394
|
invocation: "chat" | "tool" | "dev" | "channel" | "eval" | "sync";
|
|
422
|
-
target: "bun"
|
|
423
|
-
database: "sqlite" | "
|
|
395
|
+
target: "bun";
|
|
396
|
+
database: "sqlite" | "none";
|
|
424
397
|
};
|
|
425
398
|
|
|
426
399
|
export type ToolClockContext = {
|
|
@@ -472,7 +445,6 @@ export type AgentConfig = {
|
|
|
472
445
|
instructions: string;
|
|
473
446
|
secrets: string[];
|
|
474
447
|
tools?: AgentTool[];
|
|
475
|
-
integrations?: AgentIntegration[];
|
|
476
448
|
channels?: AgentChannel[];
|
|
477
449
|
transcription?: AgentTranscriptionConfig;
|
|
478
450
|
knowledge?: AgentKnowledgeConfig;
|
|
@@ -495,25 +467,6 @@ export function defineTool<Input = unknown, Output = unknown>(tool: AgentTool<In
|
|
|
495
467
|
return tool;
|
|
496
468
|
}
|
|
497
469
|
|
|
498
|
-
export function composioManaged(input: ComposioManagedIntegrationInput): ComposioManagedIntegration {
|
|
499
|
-
const name = normalizeIntegrationName(input.name ?? "composio", "composio integration name");
|
|
500
|
-
const toolkits = normalizeToolkitList(input.toolkits, "composioManaged.toolkits");
|
|
501
|
-
const tools = input.tools ? normalizeComposioToolMap(input.tools, toolkits) : undefined;
|
|
502
|
-
const tags = input.tags ? normalizeIntegrationTags(input.tags) : undefined;
|
|
503
|
-
const confirmExternalWrites = input.confirmExternalWrites;
|
|
504
|
-
|
|
505
|
-
return {
|
|
506
|
-
type: "composio",
|
|
507
|
-
provider: "composio",
|
|
508
|
-
mode: "managed",
|
|
509
|
-
name,
|
|
510
|
-
toolkits,
|
|
511
|
-
...(tools ? { tools } : {}),
|
|
512
|
-
...(tags ? { tags } : {}),
|
|
513
|
-
...(confirmExternalWrites === undefined ? {} : { confirmExternalWrites }),
|
|
514
|
-
};
|
|
515
|
-
}
|
|
516
|
-
|
|
517
470
|
export function websiteChannel(input: WebsiteChannelInput): WebsiteChannelConfig {
|
|
518
471
|
return {
|
|
519
472
|
type: "website",
|
|
@@ -663,109 +616,6 @@ function normalizeSecretName(secret: string, context: string): string {
|
|
|
663
616
|
return secret;
|
|
664
617
|
}
|
|
665
618
|
|
|
666
|
-
function normalizeIntegrationName(value: string, context: string): string {
|
|
667
|
-
const name = value.trim();
|
|
668
|
-
|
|
669
|
-
if (!/^[a-z][a-z0-9-]*$/.test(name)) {
|
|
670
|
-
throw new Error(`${context} must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`);
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
return name;
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
function normalizeToolkitList(values: string[], context: string): string[] {
|
|
677
|
-
if (!Array.isArray(values) || values.length === 0) {
|
|
678
|
-
throw new Error(`${context} must include at least one toolkit slug.`);
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
const toolkits = new Set<string>();
|
|
682
|
-
|
|
683
|
-
for (const value of values) {
|
|
684
|
-
if (typeof value !== "string") {
|
|
685
|
-
throw new Error(`${context} entries must be toolkit slug strings.`);
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
const toolkit = value.trim().toLowerCase();
|
|
689
|
-
|
|
690
|
-
if (!/^[a-z][a-z0-9_-]*$/.test(toolkit)) {
|
|
691
|
-
throw new Error(`${context} entries must start with a letter and contain only letters, numbers, underscores, and hyphens.`);
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
toolkits.add(toolkit);
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
return Array.from(toolkits).sort();
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
function normalizeComposioToolMap(values: Record<string, string[]>, toolkits: string[]): Record<string, string[]> | undefined {
|
|
701
|
-
const toolkitSet = new Set(toolkits);
|
|
702
|
-
const normalized: Record<string, string[]> = {};
|
|
703
|
-
|
|
704
|
-
for (const [rawToolkit, rawTools] of Object.entries(values)) {
|
|
705
|
-
const toolkit = rawToolkit.trim().toLowerCase();
|
|
706
|
-
|
|
707
|
-
if (!toolkitSet.has(toolkit)) {
|
|
708
|
-
throw new Error(`composioManaged.tools.${rawToolkit} must reference a toolkit listed in composioManaged.toolkits.`);
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
if (!Array.isArray(rawTools) || rawTools.length === 0) {
|
|
712
|
-
throw new Error(`composioManaged.tools.${rawToolkit} must include at least one Composio action slug.`);
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
const tools = new Set<string>();
|
|
716
|
-
|
|
717
|
-
for (const rawTool of rawTools) {
|
|
718
|
-
if (typeof rawTool !== "string") {
|
|
719
|
-
throw new Error(`composioManaged.tools.${rawToolkit} entries must be Composio action slug strings.`);
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
const tool = rawTool.trim().toUpperCase();
|
|
723
|
-
|
|
724
|
-
if (!/^[A-Z][A-Z0-9_]*$/.test(tool)) {
|
|
725
|
-
throw new Error(`composioManaged.tools.${rawToolkit} entries must be uppercase Composio action slugs.`);
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
tools.add(tool);
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
normalized[toolkit] = Array.from(tools).sort();
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
function normalizeIntegrationTags(tags: IntegrationTagsConfig): IntegrationTagsConfig {
|
|
738
|
-
const normalized: IntegrationTagsConfig = {};
|
|
739
|
-
|
|
740
|
-
if (tags.enable !== undefined) {
|
|
741
|
-
normalized.enable = normalizeTagList(tags.enable, "composioManaged.tags.enable");
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
if (tags.disable !== undefined) {
|
|
745
|
-
normalized.disable = normalizeTagList(tags.disable, "composioManaged.tags.disable");
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
return normalized;
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
function normalizeTagList(values: string[], context: string): string[] {
|
|
752
|
-
if (!Array.isArray(values)) {
|
|
753
|
-
throw new Error(`${context} must be an array of tag strings.`);
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
return Array.from(
|
|
757
|
-
new Set(
|
|
758
|
-
values.map((value) => {
|
|
759
|
-
if (typeof value !== "string" || value.trim().length === 0) {
|
|
760
|
-
throw new Error(`${context} entries must be non-empty strings.`);
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
return value.trim();
|
|
764
|
-
}),
|
|
765
|
-
),
|
|
766
|
-
).sort();
|
|
767
|
-
}
|
|
768
|
-
|
|
769
619
|
function normalizeChannelBuffer(input: ChannelBufferInput, context: string): ChannelBufferConfig {
|
|
770
620
|
if (input.mode === "off") {
|
|
771
621
|
return { mode: "off" };
|
|
@@ -928,8 +778,6 @@ export { getConversationTraceFromCwd } from "./runtime/traces";
|
|
|
928
778
|
export { runToolFromCwd } from "./runtime/tool-runner";
|
|
929
779
|
export { startAgentDevServer } from "./runtime/dev-server";
|
|
930
780
|
export { inspectAgentCapsule } from "./runtime/inspect";
|
|
931
|
-
export { buildAgentCapsule } from "./runtime/build";
|
|
932
|
-
export { deployBuildToAgentKitCloud } from "./runtime/deploy";
|
|
933
781
|
export { AgentKitError } from "./runtime/errors";
|
|
934
782
|
export type {
|
|
935
783
|
ChannelAdapter,
|
|
@@ -4,10 +4,24 @@ import { homedir } from "node:os";
|
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { setTimeout as delay } from "node:timers/promises";
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import type { OAuthAuth } from "@earendil-works/pi-ai";
|
|
8
|
+
import type { OAuthCredentials } from "@earendil-works/pi-ai/oauth";
|
|
9
|
+
import { openaiCodexProvider } from "@earendil-works/pi-ai/providers/openai-codex";
|
|
8
10
|
|
|
9
11
|
import { AgentKitError } from "../runtime/errors";
|
|
10
12
|
|
|
13
|
+
const REFRESH_TIMEOUT_MS = 15_000;
|
|
14
|
+
|
|
15
|
+
export function codexOAuth(): OAuthAuth {
|
|
16
|
+
const oauth = openaiCodexProvider().auth.oauth;
|
|
17
|
+
if (!oauth) throw new AgentKitError("provider_not_supported", "The installed Pi SDK no longer supports OpenAI Codex sign-in.");
|
|
18
|
+
return oauth;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function refreshCodexToken(refresh: string): Promise<OAuthCredentials> {
|
|
22
|
+
return codexOAuth().refresh({ type: "oauth", access: "", refresh, expires: 0 }, AbortSignal.timeout(REFRESH_TIMEOUT_MS));
|
|
23
|
+
}
|
|
24
|
+
|
|
11
25
|
export function codexAuthPath(): string {
|
|
12
26
|
return join(homedir(), ".agentkit", "providers", "openai-codex.json");
|
|
13
27
|
}
|
|
@@ -90,7 +104,7 @@ export async function codexLoginStatus(path = codexAuthPath()) {
|
|
|
90
104
|
|
|
91
105
|
export async function getCodexApiKey(
|
|
92
106
|
path = codexAuthPath(),
|
|
93
|
-
refresh =
|
|
107
|
+
refresh = refreshCodexToken,
|
|
94
108
|
): Promise<string> {
|
|
95
109
|
return withAuthLock(path, async () => {
|
|
96
110
|
const credentials = await readCredentials(path);
|
package/src/providers/pi.ts
CHANGED
|
@@ -1,28 +1,51 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
getModels,
|
|
5
|
-
stream,
|
|
2
|
+
createModels,
|
|
3
|
+
envApiKeyAuth,
|
|
6
4
|
type AssistantMessage,
|
|
7
5
|
type AssistantMessageEvent,
|
|
6
|
+
type Context,
|
|
8
7
|
type Message,
|
|
9
8
|
type Model,
|
|
10
|
-
type
|
|
9
|
+
type StreamOptions,
|
|
11
10
|
type Tool as PiTool,
|
|
12
11
|
type ToolCall,
|
|
13
12
|
type Usage,
|
|
14
13
|
} from "@earendil-works/pi-ai";
|
|
14
|
+
import { anthropicProvider } from "@earendil-works/pi-ai/providers/anthropic";
|
|
15
|
+
import { openaiProvider } from "@earendil-works/pi-ai/providers/openai";
|
|
16
|
+
import { openaiCodexProvider } from "@earendil-works/pi-ai/providers/openai-codex";
|
|
17
|
+
import { opencodeProvider } from "@earendil-works/pi-ai/providers/opencode";
|
|
18
|
+
import { opencodeGoProvider } from "@earendil-works/pi-ai/providers/opencode-go";
|
|
19
|
+
import { openrouterProvider } from "@earendil-works/pi-ai/providers/openrouter";
|
|
15
20
|
|
|
16
21
|
import type { AgentProviderName, AgentTool } from "../index";
|
|
17
22
|
import { AgentKitError } from "../runtime/errors";
|
|
18
23
|
import type { ProviderAdapter, ProviderRunInput, ProviderRunResult } from "./types";
|
|
19
24
|
|
|
20
25
|
const PI_PROVIDER_NAMES = ["openai", "openai-codex", "anthropic", "openrouter", "opencode", "opencode-go"] as const satisfies AgentProviderName[];
|
|
26
|
+
type Provider = (typeof PI_PROVIDER_NAMES)[number];
|
|
27
|
+
const PROVIDER_SECRET_NAMES: Record<Exclude<Provider, "openai-codex">, string[]> = {
|
|
28
|
+
openai: ["OPENAI_API_KEY"],
|
|
29
|
+
anthropic: ["ANTHROPIC_OAUTH_TOKEN", "ANTHROPIC_API_KEY"],
|
|
30
|
+
openrouter: ["OPENROUTER_API_KEY"],
|
|
31
|
+
opencode: ["OPENCODE_API_KEY"],
|
|
32
|
+
"opencode-go": ["OPENCODE_API_KEY"],
|
|
33
|
+
};
|
|
21
34
|
const MAX_TOOL_TURNS = 8;
|
|
22
35
|
const OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
|
|
23
36
|
const UNKNOWN_OPENROUTER_CONTEXT_WINDOW = 128000;
|
|
24
37
|
const UNKNOWN_OPENROUTER_MAX_TOKENS = 8192;
|
|
25
38
|
|
|
39
|
+
// AgentKit resolves credentials itself (.env secrets, the local Codex login) and passes
|
|
40
|
+
// them per request, so Pi never reads ambient env vars or its own credential store.
|
|
41
|
+
export const piModels = createModels();
|
|
42
|
+
for (const provider of [openaiProvider(), anthropicProvider(), openrouterProvider(), opencodeProvider(), opencodeGoProvider()]) {
|
|
43
|
+
piModels.setProvider(provider);
|
|
44
|
+
}
|
|
45
|
+
const codexProvider = openaiCodexProvider();
|
|
46
|
+
// Pi's Codex provider only accepts its own OAuth store; accept the explicit access token instead.
|
|
47
|
+
piModels.setProvider({ ...codexProvider, auth: { ...codexProvider.auth, apiKey: envApiKeyAuth("OpenAI Codex access token", []) } });
|
|
48
|
+
|
|
26
49
|
export const piProviderAdapters: ProviderAdapter[] = PI_PROVIDER_NAMES.map((name) => ({
|
|
27
50
|
name,
|
|
28
51
|
run(input) {
|
|
@@ -117,7 +140,9 @@ export function providerToolResultText(result: {
|
|
|
117
140
|
visibility?: "user" | "internal";
|
|
118
141
|
rendered?: { text?: string };
|
|
119
142
|
output: unknown;
|
|
143
|
+
modelText?: string;
|
|
120
144
|
}): string {
|
|
145
|
+
if (result.modelText !== undefined) return result.modelText;
|
|
121
146
|
if (result.visibility === "internal") {
|
|
122
147
|
return `Internal tool ${result.name} completed.`;
|
|
123
148
|
}
|
|
@@ -127,11 +152,11 @@ export function providerToolResultText(result: {
|
|
|
127
152
|
|
|
128
153
|
async function runPiTurn(
|
|
129
154
|
model: Model<any>,
|
|
130
|
-
context:
|
|
131
|
-
options:
|
|
155
|
+
context: Context,
|
|
156
|
+
options: StreamOptions,
|
|
132
157
|
rawEvents: AssistantMessageEvent[],
|
|
133
158
|
): Promise<AssistantMessage> {
|
|
134
|
-
const eventStream = stream(model, context, options);
|
|
159
|
+
const eventStream = piModels.stream(model, context, options);
|
|
135
160
|
let assistant: AssistantMessage | undefined;
|
|
136
161
|
let failed: AssistantMessage | undefined;
|
|
137
162
|
|
|
@@ -178,7 +203,7 @@ function requireProviderApiKey(provider: Provider, env: Record<string, string |
|
|
|
178
203
|
throw new AgentKitError("provider_auth_required", "Run agentkit provider login openai-codex, then use local chat, dev, or eval.");
|
|
179
204
|
}
|
|
180
205
|
|
|
181
|
-
const envNames =
|
|
206
|
+
const envNames = PROVIDER_SECRET_NAMES[provider];
|
|
182
207
|
const setName = envNames.find((name) => env[name]);
|
|
183
208
|
|
|
184
209
|
if (!setName) {
|
|
@@ -191,14 +216,6 @@ function requireProviderApiKey(provider: Provider, env: Record<string, string |
|
|
|
191
216
|
return env[setName] as string;
|
|
192
217
|
}
|
|
193
218
|
|
|
194
|
-
function defaultProviderSecretNames(provider: Provider): string[] {
|
|
195
|
-
if (provider === "opencode" || provider === "opencode-go") {
|
|
196
|
-
return ["OPENCODE_API_KEY"];
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return [`${provider.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_API_KEY`];
|
|
200
|
-
}
|
|
201
|
-
|
|
202
219
|
function formatSecretList(names: string[]): string {
|
|
203
220
|
if (names.length === 1) {
|
|
204
221
|
return names[0];
|
|
@@ -208,7 +225,7 @@ function formatSecretList(names: string[]): string {
|
|
|
208
225
|
}
|
|
209
226
|
|
|
210
227
|
export function resolveModel(provider: Provider, modelId: string): Model<any> {
|
|
211
|
-
const model = getModel(provider
|
|
228
|
+
const model = piModels.getModel(provider, modelId);
|
|
212
229
|
|
|
213
230
|
if (model) {
|
|
214
231
|
return model;
|
|
@@ -248,7 +265,7 @@ function createOpenRouterPassThroughModel(modelId: string): Model<"openai-comple
|
|
|
248
265
|
}
|
|
249
266
|
|
|
250
267
|
function knownModelHint(provider: Provider): string {
|
|
251
|
-
const examples = getModels(provider
|
|
268
|
+
const examples = piModels.getModels(provider)
|
|
252
269
|
.slice(0, 5)
|
|
253
270
|
.map((model) => model.id);
|
|
254
271
|
|
|
@@ -124,9 +124,9 @@ export const discordChannelAdapter: ChannelAdapter = {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
return {
|
|
127
|
-
status: "
|
|
127
|
+
status: "needs_setup",
|
|
128
128
|
checkedAt: new Date().toISOString(),
|
|
129
|
-
message: "
|
|
129
|
+
message: "AgentKit does not connect to the Discord Gateway. Use interactions or run your own Gateway bridge to forward authenticated bot events; inviting the bot alone is insufficient. Bridge connectivity cannot be verified here.",
|
|
130
130
|
};
|
|
131
131
|
}
|
|
132
132
|
|
package/src/runtime/chat.ts
CHANGED
|
@@ -6,9 +6,8 @@ import type { ConversationRecord, ConversationSummary, PersistedChatRun } from "
|
|
|
6
6
|
import type { LoadedAgentCapsule } from "./config";
|
|
7
7
|
import { loadAgentCapsule } from "./config";
|
|
8
8
|
import { openPreparedCapsuleStore } from "./database";
|
|
9
|
-
import { loadCapsuleEnv } from "./env";
|
|
9
|
+
import { collectSecretValues, loadCapsuleEnv } from "./env";
|
|
10
10
|
import { AgentKitError, isAgentKitError } from "./errors";
|
|
11
|
-
import { createManagedComposioTools } from "./integrations/composio";
|
|
12
11
|
import { syncConfiguredKnowledgeSources } from "./knowledge/ingest";
|
|
13
12
|
import { appendKnowledgePromptPolicy } from "./knowledge/prompt-policy";
|
|
14
13
|
import { createKnowledgeSearchTool } from "./knowledge/tool";
|
|
@@ -46,6 +45,7 @@ export async function runAgentMessage(
|
|
|
46
45
|
|
|
47
46
|
const adapter = getProviderAdapter(capsule.config.provider);
|
|
48
47
|
const env = await loadCapsuleEnv(capsule.root);
|
|
48
|
+
const secretValues = collectSecretValues(capsule.config, env);
|
|
49
49
|
await syncConfiguredKnowledgeSources(capsule);
|
|
50
50
|
const conversationId = normalizeConversationId(options.conversationId);
|
|
51
51
|
const { store } = await openPreparedCapsuleStore(capsule);
|
|
@@ -81,6 +81,7 @@ export async function runAgentMessage(
|
|
|
81
81
|
runId: run.id,
|
|
82
82
|
conversationId: conversation.id,
|
|
83
83
|
env,
|
|
84
|
+
secretValues,
|
|
84
85
|
signal: options.signal,
|
|
85
86
|
clock,
|
|
86
87
|
runtime: {
|
|
@@ -140,6 +141,7 @@ export async function runAgentMessage(
|
|
|
140
141
|
status: "failed",
|
|
141
142
|
errorCode: isAgentKitError(error) ? error.code : "runtime_error",
|
|
142
143
|
errorMessage: error instanceof Error ? error.message : String(error),
|
|
144
|
+
secretValues,
|
|
143
145
|
});
|
|
144
146
|
}
|
|
145
147
|
|
|
@@ -150,7 +152,7 @@ export async function runAgentMessage(
|
|
|
150
152
|
}
|
|
151
153
|
|
|
152
154
|
function withKnowledgeTools(capsule: LoadedAgentCapsule): NonNullable<LoadedAgentCapsule["config"]["tools"]> {
|
|
153
|
-
const tools =
|
|
155
|
+
const tools = capsule.config.tools ?? [];
|
|
154
156
|
const knowledgeTool = createKnowledgeSearchTool(capsule);
|
|
155
157
|
|
|
156
158
|
if (knowledgeTool) {
|
package/src/runtime/config.ts
CHANGED
|
@@ -17,17 +17,15 @@ import type {
|
|
|
17
17
|
TelegramAllowedUpdate,
|
|
18
18
|
AgentKnowledgeEmbeddingProvider,
|
|
19
19
|
ChannelBufferMode,
|
|
20
|
-
AgentIntegration,
|
|
21
20
|
ChannelAudioMode,
|
|
22
21
|
TranscriptionProviderName,
|
|
23
22
|
ChannelReplyRouteConfig,
|
|
24
23
|
} from "../index";
|
|
25
|
-
import { MANAGED_COMPOSIO_TOOL_NAME } from "./integrations/composio";
|
|
26
24
|
import { AgentKitError } from "./errors";
|
|
27
25
|
import { isValidTimeZone } from "./prompt-context";
|
|
28
26
|
|
|
29
27
|
const CONFIG_FILE = "agentkit.config.ts";
|
|
30
|
-
const AGENT_RUNTIMES = new Set<AgentRuntime>(["local"
|
|
28
|
+
const AGENT_RUNTIMES = new Set<AgentRuntime>(["local"]);
|
|
31
29
|
const PROVIDERS = new Set<AgentProviderName>(["test", "openai", "openai-codex", "anthropic", "openrouter", "opencode", "opencode-go", "custom"]);
|
|
32
30
|
const ACCESS_MODES = new Set<AccessMode>(["private", "token", "public"]);
|
|
33
31
|
const TOOL_VISIBILITIES = new Set<ToolVisibility>(["user", "internal"]);
|
|
@@ -41,9 +39,6 @@ const KNOWLEDGE_EMBEDDING_PROVIDERS = new Set<AgentKnowledgeEmbeddingProvider>([
|
|
|
41
39
|
const TRANSCRIPTION_PROVIDERS = new Set<TranscriptionProviderName>(["test", "openai", "groq"]);
|
|
42
40
|
const CHANNEL_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
43
41
|
const CHANNEL_REPLY_PATH_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
44
|
-
const INTEGRATION_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
45
|
-
const COMPOSIO_TOOLKIT_PATTERN = /^[a-z][a-z0-9_-]*$/;
|
|
46
|
-
const COMPOSIO_TOOL_SLUG_PATTERN = /^[A-Z][A-Z0-9_]*$/;
|
|
47
42
|
const SECRET_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
|
|
48
43
|
const HTTP_HEADER_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9-]*$/;
|
|
49
44
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
@@ -125,7 +120,7 @@ function resolveLocalStoragePath(root: string, config: AgentConfig): string | un
|
|
|
125
120
|
|
|
126
121
|
// Every import of the config goes through a uniquely named temp module, and
|
|
127
122
|
// Node never evicts imported modules. Re-importing on each request (the dev and
|
|
128
|
-
//
|
|
123
|
+
// local servers load the capsule per request) grows memory without bound,
|
|
129
124
|
// so reuse the import while the config source is unchanged. Edits still reload.
|
|
130
125
|
const configModuleCache = new Map<string, { source: string; value: Promise<unknown> }>();
|
|
131
126
|
|
|
@@ -228,7 +223,7 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
|
|
|
228
223
|
expectString(value.name, "name");
|
|
229
224
|
|
|
230
225
|
if (!AGENT_RUNTIMES.has(value.runtime as AgentRuntime)) {
|
|
231
|
-
throw invalidConfig('runtime must be "local"
|
|
226
|
+
throw invalidConfig('runtime must be "local". Hosted runtimes are no longer supported.');
|
|
232
227
|
}
|
|
233
228
|
|
|
234
229
|
if (!isRecord(value.provider)) {
|
|
@@ -267,9 +262,11 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
|
|
|
267
262
|
}
|
|
268
263
|
}
|
|
269
264
|
|
|
270
|
-
|
|
265
|
+
if (value.integrations !== undefined) {
|
|
266
|
+
throw invalidConfig("Managed integrations are no longer supported. Connect external services through defineTool.");
|
|
267
|
+
}
|
|
271
268
|
validateTranscriptionConfig(value.transcription);
|
|
272
|
-
validateChannels(value.channels,
|
|
269
|
+
validateChannels(value.channels, Boolean(value.transcription));
|
|
273
270
|
validateKnowledgeConfig(value.knowledge);
|
|
274
271
|
|
|
275
272
|
if (!isRecord(value.access) || !ACCESS_MODES.has(value.access.mode as AccessMode)) {
|
|
@@ -296,133 +293,6 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
|
|
|
296
293
|
validateFilesConfig(value.storage.files);
|
|
297
294
|
}
|
|
298
295
|
|
|
299
|
-
function validateIntegrations(
|
|
300
|
-
value: unknown,
|
|
301
|
-
runtime: AgentRuntime,
|
|
302
|
-
tools: AgentConfig["tools"] = [],
|
|
303
|
-
): void {
|
|
304
|
-
if (value === undefined) {
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
if (!Array.isArray(value)) {
|
|
309
|
-
throw invalidConfig("integrations must be an array when provided.");
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (value.length > 0 && runtime !== "edge") {
|
|
313
|
-
throw invalidConfig('managed integrations require runtime: "edge". Use BYO defineTool wrappers for local-only integrations.');
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
let composioCount = 0;
|
|
317
|
-
|
|
318
|
-
for (const [index, integration] of value.entries()) {
|
|
319
|
-
if (!isRecord(integration)) {
|
|
320
|
-
throw invalidConfig(`integrations[${index}] must be an object.`);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
if (integration.provider !== "composio" || integration.type !== "composio" || integration.mode !== "managed") {
|
|
324
|
-
throw invalidConfig(`integrations[${index}] must be composioManaged({...}) or { type: "composio", provider: "composio", mode: "managed", ... }.`);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
composioCount += 1;
|
|
328
|
-
validateComposioManagedIntegration(integration as unknown as AgentIntegration, index);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
if (composioCount > 1) {
|
|
332
|
-
throw invalidConfig("Only one managed Composio integration is supported per agent.");
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
const hasExplicitComposioTools = value.some(
|
|
336
|
-
(integration) => isRecord(integration) && integration.provider === "composio" && isRecord(integration.tools),
|
|
337
|
-
);
|
|
338
|
-
|
|
339
|
-
if (hasExplicitComposioTools && tools.some((tool) => isRecord(tool) && tool.name === MANAGED_COMPOSIO_TOOL_NAME)) {
|
|
340
|
-
throw invalidConfig(`tools must not declare reserved managed Composio tool name "${MANAGED_COMPOSIO_TOOL_NAME}".`);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
function validateComposioManagedIntegration(value: AgentIntegration, index: number): void {
|
|
345
|
-
expectString(value.name, `integrations[${index}].name`);
|
|
346
|
-
|
|
347
|
-
if (!INTEGRATION_NAME_PATTERN.test(value.name)) {
|
|
348
|
-
throw invalidConfig(`integrations[${index}].name must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
if (!Array.isArray(value.toolkits) || value.toolkits.length === 0) {
|
|
352
|
-
throw invalidConfig(`integrations[${index}].toolkits must include at least one Composio toolkit slug.`);
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
const toolkits = new Set<string>();
|
|
356
|
-
|
|
357
|
-
for (const [toolkitIndex, toolkit] of value.toolkits.entries()) {
|
|
358
|
-
expectString(toolkit, `integrations[${index}].toolkits[${toolkitIndex}]`);
|
|
359
|
-
|
|
360
|
-
if (!COMPOSIO_TOOLKIT_PATTERN.test(toolkit)) {
|
|
361
|
-
throw invalidConfig(`integrations[${index}].toolkits[${toolkitIndex}] must be a lowercase Composio toolkit slug.`);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (toolkits.has(toolkit)) {
|
|
365
|
-
throw invalidConfig(`integrations[${index}].toolkits must not contain duplicates.`);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
toolkits.add(toolkit);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
if (value.tools !== undefined) {
|
|
372
|
-
if (!isRecord(value.tools)) {
|
|
373
|
-
throw invalidConfig(`integrations[${index}].tools must be an object when provided.`);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
for (const [toolkit, tools] of Object.entries(value.tools)) {
|
|
377
|
-
if (!toolkits.has(toolkit)) {
|
|
378
|
-
throw invalidConfig(`integrations[${index}].tools.${toolkit} must reference a toolkit listed in integrations[${index}].toolkits.`);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
if (!Array.isArray(tools) || tools.length === 0) {
|
|
382
|
-
throw invalidConfig(`integrations[${index}].tools.${toolkit} must include at least one Composio action slug.`);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
const seenTools = new Set<string>();
|
|
386
|
-
|
|
387
|
-
for (const [toolIndex, tool] of tools.entries()) {
|
|
388
|
-
expectString(tool, `integrations[${index}].tools.${toolkit}[${toolIndex}]`);
|
|
389
|
-
|
|
390
|
-
if (!COMPOSIO_TOOL_SLUG_PATTERN.test(tool)) {
|
|
391
|
-
throw invalidConfig(`integrations[${index}].tools.${toolkit}[${toolIndex}] must be an uppercase Composio action slug.`);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
if (seenTools.has(tool)) {
|
|
395
|
-
throw invalidConfig(`integrations[${index}].tools.${toolkit} must not contain duplicates.`);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
seenTools.add(tool);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (value.tags !== undefined) {
|
|
404
|
-
validateIntegrationTags(value.tags, `integrations[${index}].tags`);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
if (value.confirmExternalWrites !== undefined && typeof value.confirmExternalWrites !== "boolean") {
|
|
408
|
-
throw invalidConfig(`integrations[${index}].confirmExternalWrites must be a boolean when provided.`);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
function validateIntegrationTags(value: unknown, label: string): void {
|
|
413
|
-
if (!isRecord(value)) {
|
|
414
|
-
throw invalidConfig(`${label} must be an object when provided.`);
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
if (value.enable !== undefined) {
|
|
418
|
-
expectStringArray(value.enable, `${label}.enable`);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
if (value.disable !== undefined) {
|
|
422
|
-
expectStringArray(value.disable, `${label}.disable`);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
296
|
function validateTranscriptionConfig(value: unknown): void {
|
|
427
297
|
if (value === undefined) {
|
|
428
298
|
return;
|
|
@@ -591,7 +461,7 @@ function validateKnowledgeRetrieval(value: unknown): void {
|
|
|
591
461
|
}
|
|
592
462
|
}
|
|
593
463
|
|
|
594
|
-
function validateChannels(value: unknown,
|
|
464
|
+
function validateChannels(value: unknown, hasTranscriptionConfig: boolean): void {
|
|
595
465
|
if (value === undefined) {
|
|
596
466
|
return;
|
|
597
467
|
}
|
|
@@ -600,10 +470,6 @@ function validateChannels(value: unknown, runtime: AgentRuntime, hasTranscriptio
|
|
|
600
470
|
throw invalidConfig("channels must be an array when provided.");
|
|
601
471
|
}
|
|
602
472
|
|
|
603
|
-
if (value.length > 0 && runtime !== "edge") {
|
|
604
|
-
throw invalidConfig('channels require runtime: "edge".');
|
|
605
|
-
}
|
|
606
|
-
|
|
607
473
|
const names = new Set<string>();
|
|
608
474
|
|
|
609
475
|
for (const [index, channel] of value.entries()) {
|
|
@@ -1045,8 +911,8 @@ function validateDatabaseConfig(value: unknown): void {
|
|
|
1045
911
|
throw invalidConfig("storage.database must be an object when provided.");
|
|
1046
912
|
}
|
|
1047
913
|
|
|
1048
|
-
if (value.driver !== "none" && value.driver !== "
|
|
1049
|
-
throw invalidConfig('storage.database.driver must be "none" or "
|
|
914
|
+
if (value.driver !== "none" && value.driver !== "sqlite") {
|
|
915
|
+
throw invalidConfig('storage.database.driver must be "none" or "sqlite".');
|
|
1050
916
|
}
|
|
1051
917
|
|
|
1052
918
|
if (value.schema !== undefined && typeof value.schema !== "string") {
|
|
@@ -1067,12 +933,12 @@ function validateFilesConfig(value: unknown): void {
|
|
|
1067
933
|
throw invalidConfig("storage.files must be an object when provided.");
|
|
1068
934
|
}
|
|
1069
935
|
|
|
1070
|
-
if (value.driver !== "none" && value.driver !== "
|
|
1071
|
-
throw invalidConfig('storage.files.driver must be "none" or "
|
|
936
|
+
if (value.driver !== "none" && value.driver !== "local") {
|
|
937
|
+
throw invalidConfig('storage.files.driver must be "none" or "local".');
|
|
1072
938
|
}
|
|
1073
939
|
|
|
1074
|
-
if (value.bucket !== undefined
|
|
1075
|
-
throw invalidConfig("storage.files.bucket
|
|
940
|
+
if (value.bucket !== undefined) {
|
|
941
|
+
throw invalidConfig("storage.files.bucket is no longer supported. Files are stored locally.");
|
|
1076
942
|
}
|
|
1077
943
|
|
|
1078
944
|
if (value.prefix !== undefined && typeof value.prefix !== "string") {
|