@andreprado/agentkit 0.1.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/README.md +69 -0
  2. package/bin/agentkit.mjs +23 -0
  3. package/docs/guides/add-channel.md +114 -0
  4. package/docs/guides/add-knowledge.md +134 -0
  5. package/docs/guides/add-tool.md +342 -0
  6. package/docs/guides/agentkit-skills-architecture.md +471 -0
  7. package/docs/guides/channel-security.md +81 -0
  8. package/docs/guides/channels-implementation-map.md +243 -0
  9. package/docs/guides/channels-production-handoff.md +102 -0
  10. package/docs/guides/connect-telegram.md +110 -0
  11. package/docs/guides/connect-whatsapp-zapster.md +119 -0
  12. package/docs/guides/create-agent.md +220 -0
  13. package/docs/guides/prepare-deploy.md +209 -0
  14. package/docs/guides/run-evals.md +179 -0
  15. package/docs/guides/security-rules.md +156 -0
  16. package/docs/guides/use-provider.md +140 -0
  17. package/docs/llms-full.txt +876 -0
  18. package/docs/llms.txt +83 -0
  19. package/docs/portable-deploy-release-checklist.md +41 -0
  20. package/package.json +47 -0
  21. package/src/cli/args.ts +36 -0
  22. package/src/cli/cloud-client.ts +265 -0
  23. package/src/cli/commands/channels.ts +810 -0
  24. package/src/cli/commands/knowledge.ts +136 -0
  25. package/src/cli/constants.ts +4 -0
  26. package/src/cli/deploy-chat-ui.ts +392 -0
  27. package/src/cli/deploy-readiness.ts +348 -0
  28. package/src/cli/flags.ts +162 -0
  29. package/src/cli/help.ts +184 -0
  30. package/src/cli/index.ts +1276 -0
  31. package/src/cli/process.ts +31 -0
  32. package/src/cloud/artifact.ts +139 -0
  33. package/src/cloud/client.ts +79 -0
  34. package/src/cloud/contracts.ts +63 -0
  35. package/src/cloud/index.ts +3 -0
  36. package/src/create-project.ts +177 -0
  37. package/src/index.ts +408 -0
  38. package/src/providers/index.ts +25 -0
  39. package/src/providers/pi.ts +286 -0
  40. package/src/providers/test.ts +133 -0
  41. package/src/providers/types.ts +34 -0
  42. package/src/runtime/build.ts +43 -0
  43. package/src/runtime/channel-buffer.ts +30 -0
  44. package/src/runtime/channel-test-harness.ts +112 -0
  45. package/src/runtime/channels/telegram.ts +360 -0
  46. package/src/runtime/channels/website.ts +132 -0
  47. package/src/runtime/channels/whatsapp-meta.ts +71 -0
  48. package/src/runtime/channels/whatsapp-zapster.ts +278 -0
  49. package/src/runtime/channels.ts +138 -0
  50. package/src/runtime/chat.ts +218 -0
  51. package/src/runtime/config.ts +684 -0
  52. package/src/runtime/conversations.ts +38 -0
  53. package/src/runtime/core/deploy-state.ts +54 -0
  54. package/src/runtime/core/manifest.ts +213 -0
  55. package/src/runtime/core/targets.ts +133 -0
  56. package/src/runtime/database.ts +256 -0
  57. package/src/runtime/db-commands.ts +167 -0
  58. package/src/runtime/deploy-readiness.ts +105 -0
  59. package/src/runtime/deploy.ts +1 -0
  60. package/src/runtime/dev-server.ts +1247 -0
  61. package/src/runtime/docs.ts +36 -0
  62. package/src/runtime/env.ts +152 -0
  63. package/src/runtime/errors.ts +13 -0
  64. package/src/runtime/evals.ts +509 -0
  65. package/src/runtime/inspect.ts +203 -0
  66. package/src/runtime/knowledge/chunk.ts +333 -0
  67. package/src/runtime/knowledge/config.ts +135 -0
  68. package/src/runtime/knowledge/embeddings.ts +133 -0
  69. package/src/runtime/knowledge/ingest.ts +521 -0
  70. package/src/runtime/knowledge/prompt-policy.ts +30 -0
  71. package/src/runtime/knowledge/retrieve.ts +283 -0
  72. package/src/runtime/knowledge/schema.ts +56 -0
  73. package/src/runtime/knowledge/tool.ts +64 -0
  74. package/src/runtime/knowledge/vector.ts +258 -0
  75. package/src/runtime/runtime-contract.ts +93 -0
  76. package/src/runtime/spec.ts +152 -0
  77. package/src/runtime/sync.ts +144 -0
  78. package/src/runtime/targets/cloudflare/build.ts +2517 -0
  79. package/src/runtime/targets/container/build.ts +146 -0
  80. package/src/runtime/targets/container/server.ts +33 -0
  81. package/src/runtime/targets/vps/deploy.ts +206 -0
  82. package/src/runtime/tool-runner.ts +65 -0
  83. package/src/runtime/tools.ts +470 -0
  84. package/src/runtime/traces.ts +41 -0
  85. package/src/storage/sqlite.ts +1118 -0
  86. package/src/templates/blank.ts +394 -0
  87. package/src/templates/dentista.ts +1003 -0
  88. package/src/templates/index.ts +33 -0
  89. package/src/templates/skills/agentkit-build-agent/SKILL.md +51 -0
  90. package/src/templates/skills/agentkit-build-agent/templates/appointment-intake.instructions.md +20 -0
  91. package/src/templates/skills/agentkit-build-agent/templates/sales-qualifier.instructions.md +17 -0
  92. package/src/templates/skills/agentkit-build-agent/templates/support-agent.instructions.md +16 -0
  93. package/src/templates/skills/agentkit-capsule/SKILL.md +62 -0
  94. package/src/templates/skills/agentkit-capsule/references/docs-router.md +15 -0
  95. package/src/templates/skills/agentkit-channels/SKILL.md +62 -0
  96. package/src/templates/skills/agentkit-channels/references/channel-buffering.md +58 -0
  97. package/src/templates/skills/agentkit-channels/references/channel-debugging.md +41 -0
  98. package/src/templates/skills/agentkit-channels/references/telegram.md +38 -0
  99. package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +44 -0
  100. package/src/templates/skills/agentkit-database/SKILL.md +45 -0
  101. package/src/templates/skills/agentkit-database/templates/appointments.schema.sql +15 -0
  102. package/src/templates/skills/agentkit-database/templates/leads.schema.sql +17 -0
  103. package/src/templates/skills/agentkit-deploy/SKILL.md +44 -0
  104. package/src/templates/skills/agentkit-evals/SKILL.md +60 -0
  105. package/src/templates/skills/agentkit-evals/templates/multi-turn.eval.md +22 -0
  106. package/src/templates/skills/agentkit-evals/templates/no-leak.eval.md +14 -0
  107. package/src/templates/skills/agentkit-evals/templates/smoke.eval.md +14 -0
  108. package/src/templates/skills/agentkit-evals/templates/tool-call.eval.md +18 -0
  109. package/src/templates/skills/agentkit-knowledge/SKILL.md +40 -0
  110. package/src/templates/skills/agentkit-knowledge/templates/faq.md +14 -0
  111. package/src/templates/skills/agentkit-knowledge/templates/policies.md +14 -0
  112. package/src/templates/skills/agentkit-knowledge/templates/prices.csv +3 -0
  113. package/src/templates/skills/agentkit-prompts/SKILL.md +45 -0
  114. package/src/templates/skills/agentkit-prompts/templates/knowledge-grounded-faq.instructions.md +11 -0
  115. package/src/templates/skills/agentkit-provider/SKILL.md +57 -0
  116. package/src/templates/skills/agentkit-security/SKILL.md +55 -0
  117. package/src/templates/skills/agentkit-tools/SKILL.md +36 -0
  118. package/src/templates/skills/agentkit-tools/examples/database-write.tool.md +35 -0
  119. package/src/templates/skills/agentkit-tools/examples/eval-safe-external-action.tool.md +37 -0
  120. package/src/templates/skills/agentkit-tools/examples/lookup-order.tool.md +46 -0
  121. package/src/templates/skills/agentkit-troubleshooting/SKILL.md +52 -0
  122. package/src/templates/support.ts +401 -0
@@ -0,0 +1,133 @@
1
+ import { AgentKitError } from "../runtime/errors";
2
+ import type { AgentMessage, ProviderAdapter } from "./types";
3
+
4
+ export const testProviderAdapter: ProviderAdapter = {
5
+ name: "test",
6
+ async run(input) {
7
+ if (input.agent.provider.model !== "fake") {
8
+ throw new AgentKitError("provider_model_unsupported", 'The test provider only supports model "fake".');
9
+ }
10
+
11
+ const userMessage = findLastUserMessage(input.messages);
12
+
13
+ if (!userMessage) {
14
+ throw new AgentKitError("runtime_error", "Cannot run the test provider without a user message.");
15
+ }
16
+
17
+ const toolRequest = parseToolRequest(userMessage.content);
18
+
19
+ if (toolRequest) {
20
+ if (!input.toolRuntime) {
21
+ throw new AgentKitError("runtime_error", "The runtime did not provide a tool registry.");
22
+ }
23
+
24
+ const toolResult = await input.toolRuntime.execute(toolRequest);
25
+
26
+ return {
27
+ message: {
28
+ role: "assistant",
29
+ content:
30
+ toolResult.visibility === "internal"
31
+ ? `Tool ${toolResult.name}: completed`
32
+ : toolResult.rendered?.text ?? `Tool ${toolResult.name}: ${JSON.stringify(toolResult.output)}`,
33
+ },
34
+ raw: {
35
+ toolCalls: [toolResult],
36
+ },
37
+ };
38
+ }
39
+
40
+ const rememberedName = answerRememberedName(input.messages);
41
+
42
+ if (rememberedName) {
43
+ return {
44
+ message: {
45
+ role: "assistant",
46
+ content: rememberedName,
47
+ },
48
+ };
49
+ }
50
+
51
+ return {
52
+ message: {
53
+ role: "assistant",
54
+ content: `Echo: ${userMessage.content}`,
55
+ },
56
+ };
57
+ },
58
+ };
59
+
60
+ function findLastUserMessage(messages: AgentMessage[]): AgentMessage | undefined {
61
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
62
+ const message = messages[index];
63
+
64
+ if (message.role === "user") {
65
+ return message;
66
+ }
67
+ }
68
+
69
+ return undefined;
70
+ }
71
+
72
+ function answerRememberedName(messages: AgentMessage[]): string | null {
73
+ const lastUserMessage = findLastUserMessage(messages);
74
+
75
+ if (!lastUserMessage || !asksForName(lastUserMessage.content)) {
76
+ return null;
77
+ }
78
+
79
+ for (let index = messages.length - 2; index >= 0; index -= 1) {
80
+ const message = messages[index];
81
+
82
+ if (message.role !== "user") {
83
+ continue;
84
+ }
85
+
86
+ const name = extractName(message.content);
87
+
88
+ if (name) {
89
+ return /meu nome|qual\s+(é|e)\s*meu nome|como\s+(é|e)\s*meu nome/i.test(lastUserMessage.content)
90
+ ? `Seu nome é ${name}.`
91
+ : `Your name is ${name}.`;
92
+ }
93
+ }
94
+
95
+ return null;
96
+ }
97
+
98
+ function asksForName(content: string): boolean {
99
+ return /what(?:'s| is) my name\??/i.test(content) || /(como|qual)\s+(é|e)\s*(o\s+)?meu nome\??/i.test(content);
100
+ }
101
+
102
+ function extractName(content: string): string | null {
103
+ const match = content.match(/\bmy name is\s+(.+)$/i) ?? content.match(/\bmeu nome (?:é|e)\s+(.+)$/i);
104
+
105
+ if (!match) {
106
+ return null;
107
+ }
108
+
109
+ return match[1].trim().replace(/[.!?]+$/g, "") || null;
110
+ }
111
+
112
+ function parseToolRequest(content: string): { name: string; input?: unknown } | null {
113
+ let parsed: unknown;
114
+
115
+ try {
116
+ parsed = JSON.parse(content);
117
+ } catch {
118
+ return null;
119
+ }
120
+
121
+ if (!isRecord(parsed) || typeof parsed.tool !== "string" || parsed.tool.length === 0) {
122
+ return null;
123
+ }
124
+
125
+ return {
126
+ name: parsed.tool,
127
+ input: "input" in parsed ? parsed.input : {},
128
+ };
129
+ }
130
+
131
+ function isRecord(value: unknown): value is Record<string, unknown> {
132
+ return typeof value === "object" && value !== null && !Array.isArray(value);
133
+ }
@@ -0,0 +1,34 @@
1
+ import type { AgentConfig, AgentProviderName, AgentTool } from "../index";
2
+ import type { ToolRuntime } from "../runtime/tools";
3
+
4
+ export type AgentMessageRole = "system" | "user" | "assistant";
5
+
6
+ export type AgentMessage = {
7
+ role: AgentMessageRole;
8
+ content: string;
9
+ };
10
+
11
+ export type ProviderRunInput = {
12
+ agent: Pick<AgentConfig, "name" | "runtime" | "provider">;
13
+ instructions: string;
14
+ messages: AgentMessage[];
15
+ tools: AgentTool[];
16
+ toolRuntime?: ToolRuntime;
17
+ env?: Record<string, string | undefined>;
18
+ signal?: AbortSignal;
19
+ };
20
+
21
+ export type ProviderRunResult = {
22
+ message: AgentMessage & { role: "assistant" };
23
+ usage?: {
24
+ inputTokens?: number;
25
+ outputTokens?: number;
26
+ totalTokens?: number;
27
+ };
28
+ raw?: unknown;
29
+ };
30
+
31
+ export type ProviderAdapter = {
32
+ name: AgentProviderName;
33
+ run(input: ProviderRunInput): Promise<ProviderRunResult>;
34
+ };
@@ -0,0 +1,43 @@
1
+ import { resolveBuildTarget, type RuntimeTargetId } from "./core/targets";
2
+ import { buildContainerAgentCapsule, type ContainerBuildResult } from "./targets/container/build";
3
+ import {
4
+ buildCloudflareAgentCapsule,
5
+ type AgentBuildResult as CloudflareBuildResult,
6
+ type AgentManifest,
7
+ type AgentManifestWithBundle,
8
+ } from "./targets/cloudflare/build";
9
+
10
+ export type BuildTarget = RuntimeTargetId;
11
+
12
+ export type BuildAgentOptions = {
13
+ target?: string;
14
+ };
15
+
16
+ export type AgentBuildResult = CloudflareBuildResult | ContainerBuildResult;
17
+ export type { AgentManifest, AgentManifestWithBundle };
18
+
19
+ export async function buildAgentCapsule(
20
+ cwd?: string,
21
+ options?: { target?: "cloudflare" },
22
+ ): Promise<CloudflareBuildResult>;
23
+ export async function buildAgentCapsule(
24
+ cwd: string | undefined,
25
+ options: { target: "container" },
26
+ ): Promise<ContainerBuildResult>;
27
+ export async function buildAgentCapsule(cwd?: string, options?: BuildAgentOptions): Promise<AgentBuildResult>;
28
+ export async function buildAgentCapsule(
29
+ cwd = process.cwd(),
30
+ options: BuildAgentOptions = {},
31
+ ): Promise<AgentBuildResult> {
32
+ const target = resolveBuildTarget(options.target);
33
+
34
+ if (target.id === "cloudflare") {
35
+ return buildCloudflareAgentCapsule(cwd);
36
+ }
37
+
38
+ if (target.id === "container") {
39
+ return buildContainerAgentCapsule(cwd);
40
+ }
41
+
42
+ throw new Error(`Target registry returned unsupported build target "${target.id}".`);
43
+ }
@@ -0,0 +1,30 @@
1
+ import type { ChannelBufferConfig, ChannelType } from "../index";
2
+
3
+ export type ChannelBufferCarrier = {
4
+ type: ChannelType;
5
+ buffer?: ChannelBufferConfig;
6
+ };
7
+
8
+ export type ChannelBufferedMessage = {
9
+ content: string;
10
+ receivedAt: string;
11
+ };
12
+
13
+ export function resolveChannelBuffer(channel: ChannelBufferCarrier): ChannelBufferConfig {
14
+ return channel.buffer ?? { mode: "off" };
15
+ }
16
+
17
+ export function isChannelBufferEnabled(channel: ChannelBufferCarrier): boolean {
18
+ return resolveChannelBuffer(channel).mode === "debounce";
19
+ }
20
+
21
+ export function renderBufferedChannelMessage(messages: ChannelBufferedMessage[]): string {
22
+ if (messages.length === 1) {
23
+ return messages[0]?.content ?? "";
24
+ }
25
+
26
+ const lines = messages.map((message, index) => `${index + 1}. ${message.content}`);
27
+
28
+ return `The client sent ${messages.length} messages in one burst. Answer once, using the full context below:\n\n${lines.join("\n")}`;
29
+ }
30
+
@@ -0,0 +1,112 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ import type { ChannelProvider, ChannelType } from "../index";
6
+ import type { NormalizedChannelEvent, RawWebhookEvent } from "./channels";
7
+
8
+ export type ChannelFixtureName =
9
+ | "website-message"
10
+ | "telegram-message"
11
+ | "telegram-duplicate-message"
12
+ | "telegram-malformed-payload"
13
+ | "zapster-message"
14
+ | "zapster-duplicate-message"
15
+ | "zapster-unsupported-media";
16
+
17
+ export type ChannelFixture = {
18
+ name: ChannelFixtureName;
19
+ channelId: string;
20
+ type: ChannelType;
21
+ provider: ChannelProvider;
22
+ request: {
23
+ method: string;
24
+ url: string;
25
+ headers: Record<string, string>;
26
+ body?: unknown;
27
+ rawBody?: string;
28
+ };
29
+ expected: {
30
+ kind?: NormalizedChannelEvent["kind"];
31
+ providerEventId?: string;
32
+ dedupeKey?: string;
33
+ identityKey?: string;
34
+ text?: string;
35
+ unsupportedReason?: string;
36
+ errorCode?: string;
37
+ };
38
+ forbidden: string[];
39
+ };
40
+
41
+ const FIXTURE_DIR = join(dirname(fileURLToPath(import.meta.url)), "fixtures/channels");
42
+
43
+ export async function loadChannelFixture(name: ChannelFixtureName): Promise<ChannelFixture> {
44
+ const source = await readFile(join(FIXTURE_DIR, `${name}.json`), "utf8");
45
+ return JSON.parse(source) as ChannelFixture;
46
+ }
47
+
48
+ export function channelFixtureToRawEvent(
49
+ fixture: ChannelFixture,
50
+ overrides: Partial<RawWebhookEvent> = {},
51
+ ): RawWebhookEvent {
52
+ return {
53
+ type: fixture.type,
54
+ provider: fixture.provider,
55
+ channelId: fixture.channelId,
56
+ method: fixture.request.method,
57
+ url: fixture.request.url,
58
+ headers: new Headers(fixture.request.headers),
59
+ rawBody: fixture.request.rawBody ?? JSON.stringify(fixture.request.body),
60
+ receivedAt: "2026-05-27T15:00:00.000Z",
61
+ ...overrides,
62
+ };
63
+ }
64
+
65
+ export function assertMatchesFixtureEvent(event: NormalizedChannelEvent, fixture: ChannelFixture): void {
66
+ const expected = fixture.expected;
67
+
68
+ if (expected.kind !== undefined && event.kind !== expected.kind) {
69
+ throw new Error(`Expected event kind ${expected.kind}, received ${event.kind}.`);
70
+ }
71
+
72
+ if (expected.providerEventId !== undefined && event.providerEventId !== expected.providerEventId) {
73
+ throw new Error(`Expected providerEventId ${expected.providerEventId}, received ${event.providerEventId}.`);
74
+ }
75
+
76
+ if (expected.dedupeKey !== undefined && event.dedupeKey !== expected.dedupeKey) {
77
+ throw new Error(`Expected dedupeKey ${expected.dedupeKey}, received ${event.dedupeKey}.`);
78
+ }
79
+
80
+ if (expected.identityKey !== undefined && event.externalIdentity.key !== expected.identityKey) {
81
+ throw new Error(`Expected identity key ${expected.identityKey}, received ${event.externalIdentity.key}.`);
82
+ }
83
+
84
+ if (expected.text !== undefined && event.message?.content !== expected.text) {
85
+ throw new Error(`Expected message text ${JSON.stringify(expected.text)}, received ${JSON.stringify(event.message?.content)}.`);
86
+ }
87
+
88
+ if (expected.unsupportedReason !== undefined && event.unsupportedReason !== expected.unsupportedReason) {
89
+ throw new Error(
90
+ `Expected unsupportedReason ${expected.unsupportedReason}, received ${event.unsupportedReason}.`,
91
+ );
92
+ }
93
+ }
94
+
95
+ export function assertNoForbiddenValues(value: unknown, forbidden: string[]): void {
96
+ const serialized = JSON.stringify(value);
97
+
98
+ for (const forbiddenValue of forbidden) {
99
+ if (forbiddenValue && serialized.includes(forbiddenValue)) {
100
+ throw new Error(`Serialized value contains forbidden fixture value: ${forbiddenValue}`);
101
+ }
102
+ }
103
+ }
104
+
105
+ export function assertRedactedExternalIdentity(event: NormalizedChannelEvent): void {
106
+ const display = event.externalIdentity.display;
107
+ const redactedDisplay = event.externalIdentity.redactedDisplay;
108
+
109
+ if (display && redactedDisplay && display === redactedDisplay) {
110
+ throw new Error("externalIdentity.redactedDisplay must not equal display when both are set.");
111
+ }
112
+ }