@andreprado/agentkit 0.1.0-alpha.9 → 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.
Files changed (117) hide show
  1. package/README.md +18 -1
  2. package/docs/guides/add-channel.md +251 -7
  3. package/docs/guides/add-knowledge.md +10 -0
  4. package/docs/guides/add-managed-composio.md +165 -0
  5. package/docs/guides/add-tool.md +10 -3
  6. package/docs/guides/channel-security.md +162 -32
  7. package/docs/guides/connect-discord.md +178 -0
  8. package/docs/guides/connect-slack.md +126 -0
  9. package/docs/guides/connect-telegram.md +61 -1
  10. package/docs/guides/connect-whatsapp-evolution.md +121 -0
  11. package/docs/guides/connect-whatsapp-uazapi.md +139 -0
  12. package/docs/guides/connect-whatsapp-zapster.md +119 -16
  13. package/docs/guides/create-agent.md +31 -4
  14. package/docs/guides/debug-channel.md +159 -0
  15. package/docs/guides/improve-from-production.md +151 -0
  16. package/docs/guides/prepare-deploy.md +32 -14
  17. package/docs/guides/replay-production-traces.md +72 -0
  18. package/docs/guides/run-evals.md +95 -25
  19. package/docs/guides/security-rules.md +9 -5
  20. package/docs/guides/send-feedback.md +135 -0
  21. package/docs/guides/use-jev.md +67 -0
  22. package/docs/guides/use-provider.md +70 -3
  23. package/docs/llms-full.txt +295 -25
  24. package/docs/llms.txt +54 -7
  25. package/package.json +3 -7
  26. package/src/cli/args.ts +23 -2
  27. package/src/cli/cloud-client.ts +121 -9
  28. package/src/cli/commands/channels.ts +856 -36
  29. package/src/cli/commands/feedback.ts +438 -0
  30. package/src/cli/commands/provider.ts +47 -0
  31. package/src/cli/commands/transcribe.ts +171 -0
  32. package/src/cli/deploy-chat-ui.ts +232 -18
  33. package/src/cli/deploy-readiness.ts +227 -14
  34. package/src/cli/help.ts +67 -9
  35. package/src/cli/index.ts +740 -35
  36. package/src/cli/new-command.ts +41 -0
  37. package/src/cloud/client.ts +4 -3
  38. package/src/cloud/contracts.ts +1 -1
  39. package/src/create-project.ts +18 -35
  40. package/src/index.ts +565 -11
  41. package/src/providers/codex-auth.ts +111 -0
  42. package/src/providers/pi.ts +88 -19
  43. package/src/providers/test.ts +36 -0
  44. package/src/providers/types.ts +8 -0
  45. package/src/runtime/channel-test-harness.ts +21 -1
  46. package/src/runtime/channels/discord.ts +896 -0
  47. package/src/runtime/channels/generic-webhook.ts +974 -0
  48. package/src/runtime/channels/slack.ts +646 -0
  49. package/src/runtime/channels/telegram.ts +343 -12
  50. package/src/runtime/channels/whatsapp-evolution.ts +1357 -0
  51. package/src/runtime/channels/whatsapp-meta.ts +9 -0
  52. package/src/runtime/channels/whatsapp-uazapi.ts +1323 -0
  53. package/src/runtime/channels/whatsapp-zapster.ts +674 -40
  54. package/src/runtime/channels.ts +83 -3
  55. package/src/runtime/chat.ts +70 -44
  56. package/src/runtime/config.ts +489 -20
  57. package/src/runtime/core/manifest.ts +75 -5
  58. package/src/runtime/core/targets.ts +5 -5
  59. package/src/runtime/deploy-readiness.ts +34 -4
  60. package/src/runtime/dev-server.ts +639 -39
  61. package/src/runtime/env.ts +8 -3
  62. package/src/runtime/evals.ts +445 -74
  63. package/src/runtime/improve.ts +868 -0
  64. package/src/runtime/inspect.ts +173 -4
  65. package/src/runtime/integrations/composio.ts +425 -0
  66. package/src/runtime/knowledge/retrieve.ts +25 -5
  67. package/src/runtime/knowledge/schema.ts +45 -1
  68. package/src/runtime/prompt-context.ts +141 -0
  69. package/src/runtime/runtime-contract.ts +71 -7
  70. package/src/runtime/skills.ts +95 -0
  71. package/src/runtime/targets/cloudflare/build.ts +1010 -208
  72. package/src/runtime/targets/container/server.ts +1 -1
  73. package/src/runtime/targets/vps/deploy.ts +26 -9
  74. package/src/runtime/tool-runner.ts +9 -1
  75. package/src/runtime/tools.ts +26 -2
  76. package/src/runtime/transcription.ts +483 -0
  77. package/src/storage/sqlite.ts +7 -2
  78. package/src/templates/blank.ts +37 -9
  79. package/src/templates/dentista.ts +40 -14
  80. package/src/templates/skills/agentkit-build-agent/SKILL.md +34 -5
  81. package/src/templates/skills/agentkit-build-agent/templates/appointment-intake.instructions.md +2 -1
  82. package/src/templates/skills/agentkit-capsule/SKILL.md +32 -3
  83. package/src/templates/skills/agentkit-capsule/references/docs-router.md +2 -2
  84. package/src/templates/skills/agentkit-channels/SKILL.md +66 -1
  85. package/src/templates/skills/agentkit-channels/references/channel-buffering.md +8 -1
  86. package/src/templates/skills/agentkit-channels/references/channel-debugging.md +28 -3
  87. package/src/templates/skills/agentkit-channels/references/discord.md +93 -0
  88. package/src/templates/skills/agentkit-channels/references/slack.md +56 -0
  89. package/src/templates/skills/agentkit-channels/references/telegram.md +34 -0
  90. package/src/templates/skills/agentkit-channels/references/whatsapp-evolution.md +57 -0
  91. package/src/templates/skills/agentkit-channels/references/whatsapp-uazapi.md +54 -0
  92. package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +42 -8
  93. package/src/templates/skills/agentkit-database/SKILL.md +11 -0
  94. package/src/templates/skills/agentkit-deploy/SKILL.md +9 -1
  95. package/src/templates/skills/agentkit-evals/SKILL.md +77 -13
  96. package/src/templates/skills/agentkit-evals/templates/multi-turn.eval.md +13 -6
  97. package/src/templates/skills/agentkit-evals/templates/no-leak.eval.md +8 -4
  98. package/src/templates/skills/agentkit-evals/templates/smoke.eval.md +8 -4
  99. package/src/templates/skills/agentkit-evals/templates/tool-call.eval.md +16 -7
  100. package/src/templates/skills/agentkit-improve/SKILL.md +96 -0
  101. package/src/templates/skills/agentkit-improve/references/replay-side-effects.md +18 -0
  102. package/src/templates/skills/agentkit-improve/references/trace-packets.md +22 -0
  103. package/src/templates/skills/agentkit-improve/templates/regression.eval.md +18 -0
  104. package/src/templates/skills/agentkit-integrations/SKILL.md +98 -0
  105. package/src/templates/skills/agentkit-knowledge/SKILL.md +4 -1
  106. package/src/templates/skills/agentkit-prompts/SKILL.md +3 -1
  107. package/src/templates/skills/agentkit-provider/SKILL.md +29 -4
  108. package/src/templates/skills/agentkit-security/SKILL.md +5 -2
  109. package/src/templates/skills/agentkit-tools/SKILL.md +8 -1
  110. package/src/templates/skills/agentkit-tools/examples/eval-safe-external-action.tool.md +8 -8
  111. package/src/templates/skills/agentkit-tools/examples/jev-service-fit.tool.md +110 -0
  112. package/src/templates/skills/agentkit-troubleshooting/SKILL.md +25 -1
  113. package/src/templates/support.ts +42 -12
  114. package/docs/guides/agentkit-skills-architecture.md +0 -471
  115. package/docs/guides/channels-implementation-map.md +0 -243
  116. package/docs/guides/channels-production-handoff.md +0 -101
  117. package/docs/portable-deploy-release-checklist.md +0 -41
@@ -1,5 +1,5 @@
1
1
  import { readFile } from "node:fs/promises";
2
- import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
2
+ import { createServer, type IncomingMessage, type Server, type ServerResponse } from "node:http";
3
3
  import { join, relative, resolve } from "node:path";
4
4
 
5
5
  import { findAgentCapsuleRoot } from "../runtime/config";
@@ -9,8 +9,15 @@ import { defaultDeployChatAccessTokenName, defaultDeployChatAccessTokenPath } fr
9
9
 
10
10
  export async function startDeployChatUiServer(
11
11
  cwd: string,
12
- options: { port: number; tokenFile?: string },
13
- ): Promise<{ url: string; deployUrl: string; tokenSource: string; stop(): Promise<void> }> {
12
+ options: { port: number; tokenFile?: string; autoPort?: boolean },
13
+ ): Promise<{
14
+ url: string;
15
+ deployUrl: string;
16
+ tokenSource: string;
17
+ port: number;
18
+ portConflict: { port: number } | null;
19
+ stop(): Promise<void>;
20
+ }> {
14
21
  const root = await findAgentCapsuleRoot(cwd);
15
22
  const state = await readLocalDeployStateIfExists(root);
16
23
 
@@ -23,9 +30,37 @@ export async function startDeployChatUiServer(
23
30
  : join(root, defaultDeployChatAccessTokenPath);
24
31
  const hostname = "localhost";
25
32
  const deployUrl = state.url;
33
+ const start = await listenForDeployChatUiServer({
34
+ hostname,
35
+ requestedPort: options.port,
36
+ autoPort: options.autoPort === true,
37
+ create: () => createDeployChatUiHttpServer({ root, tokenPath, hostname, requestedPort: options.port, deployUrl }),
38
+ });
39
+
40
+ return {
41
+ url: `http://${hostname}:${start.port}`,
42
+ deployUrl,
43
+ tokenSource: process.env.AGENTKIT_DEPLOY_ACCESS_TOKEN ? "AGENTKIT_DEPLOY_ACCESS_TOKEN" : relativePath(root, tokenPath),
44
+ port: start.port,
45
+ portConflict: start.portConflict,
46
+ stop: () =>
47
+ new Promise<void>((resolvePromise, reject) => {
48
+ start.server.close((error) => (error ? reject(error) : resolvePromise()));
49
+ }),
50
+ };
51
+ }
52
+
53
+ function createDeployChatUiHttpServer(input: {
54
+ root: string;
55
+ tokenPath: string;
56
+ hostname: string;
57
+ requestedPort: number;
58
+ deployUrl: string;
59
+ }): Server {
60
+ const { root, tokenPath, hostname, requestedPort, deployUrl } = input;
26
61
  const server = createServer(async (request, response) => {
27
62
  try {
28
- const requestUrl = new URL(request.url ?? "/", `http://${request.headers.host ?? `${hostname}:${options.port}`}`);
63
+ const requestUrl = new URL(request.url ?? "/", `http://${request.headers.host ?? `${hostname}:${requestedPort}`}`);
29
64
 
30
65
  if (request.method === "GET" && requestUrl.pathname === "/") {
31
66
  sendHtml(response, renderDeployChatUi({ deployUrl }));
@@ -70,6 +105,27 @@ export async function startDeployChatUiServer(
70
105
  return;
71
106
  }
72
107
 
108
+ if (
109
+ request.method === "GET" &&
110
+ (requestUrl.pathname === "/v1/conversations" ||
111
+ /^\/v1\/conversations\/[^/]+(?:\/trace)?$/.test(requestUrl.pathname))
112
+ ) {
113
+ const token = await readDeployAccessTokenForUi(tokenPath);
114
+ const upstream = await fetch(new URL(requestUrl.pathname, deployUrl).href, {
115
+ method: "GET",
116
+ headers: {
117
+ Authorization: `Bearer ${token}`,
118
+ },
119
+ });
120
+ const text = await upstream.text();
121
+
122
+ response.writeHead(upstream.status, {
123
+ "content-type": upstream.headers.get("content-type") ?? "application/json",
124
+ });
125
+ response.end(text);
126
+ return;
127
+ }
128
+
73
129
  sendJson(response, 404, { error: { code: "not_found", message: "Route not found." } });
74
130
  } catch (error) {
75
131
  sendJson(response, 500, {
@@ -81,23 +137,59 @@ export async function startDeployChatUiServer(
81
137
  }
82
138
  });
83
139
 
84
- await new Promise<void>((resolvePromise, reject) => {
140
+ return server;
141
+ }
142
+
143
+ async function listenForDeployChatUiServer(input: {
144
+ hostname: string;
145
+ requestedPort: number;
146
+ autoPort: boolean;
147
+ create: () => Server;
148
+ }): Promise<{ server: Server; port: number; portConflict: { port: number } | null }> {
149
+ let firstConflict: { port: number } | null = null;
150
+ const lastPort = input.autoPort ? input.requestedPort + 50 : input.requestedPort;
151
+
152
+ for (let port = input.requestedPort; port <= lastPort; port += 1) {
153
+ const server = input.create();
154
+
155
+ try {
156
+ await listen(server, input.hostname, port);
157
+ return { server, port, portConflict: port === input.requestedPort ? null : firstConflict };
158
+ } catch (error) {
159
+ await closeServerAfterListenError(server);
160
+
161
+ if (!input.autoPort || !isAddressInUseError(error)) {
162
+ throw error;
163
+ }
164
+
165
+ firstConflict ??= { port };
166
+ }
167
+ }
168
+
169
+ throw new AgentKitError(
170
+ "runtime_error",
171
+ `Could not allocate a local AgentKit hosted chat UI port after ${input.requestedPort}-${lastPort}.`,
172
+ );
173
+ }
174
+
175
+ function listen(server: Server, hostname: string, port: number): Promise<void> {
176
+ return new Promise((resolvePromise, reject) => {
85
177
  server.once("error", reject);
86
- server.listen(options.port, hostname, () => {
178
+ server.listen(port, hostname, () => {
87
179
  server.off("error", reject);
88
180
  resolvePromise();
89
181
  });
90
182
  });
183
+ }
91
184
 
92
- return {
93
- url: `http://${hostname}:${options.port}`,
94
- deployUrl,
95
- tokenSource: process.env.AGENTKIT_DEPLOY_ACCESS_TOKEN ? "AGENTKIT_DEPLOY_ACCESS_TOKEN" : relativePath(root, tokenPath),
96
- stop: () =>
97
- new Promise<void>((resolvePromise, reject) => {
98
- server.close((error) => (error ? reject(error) : resolvePromise()));
99
- }),
100
- };
185
+ async function closeServerAfterListenError(server: Server): Promise<void> {
186
+ await new Promise<void>((resolvePromise) => {
187
+ server.close(() => resolvePromise());
188
+ });
189
+ }
190
+
191
+ function isAddressInUseError(error: unknown): boolean {
192
+ return Boolean(error && typeof error === "object" && "code" in error && error.code === "EADDRINUSE");
101
193
  }
102
194
 
103
195
  export async function readDeployAccessTokenForUi(tokenPath: string): Promise<string> {
@@ -196,6 +288,8 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
196
288
  header {
197
289
  border-bottom: 1px solid var(--line);
198
290
  padding: 18px 22px;
291
+ display: grid;
292
+ gap: 10px;
199
293
  }
200
294
 
201
295
  h1 {
@@ -204,12 +298,27 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
204
298
  line-height: 1.2;
205
299
  }
206
300
 
301
+ .topline {
302
+ display: flex;
303
+ align-items: start;
304
+ justify-content: space-between;
305
+ gap: 12px;
306
+ }
307
+
207
308
  code {
208
309
  color: var(--muted);
209
310
  font-size: 12px;
210
311
  overflow-wrap: anywhere;
211
312
  }
212
313
 
314
+ .meta {
315
+ display: flex;
316
+ flex-wrap: wrap;
317
+ gap: 8px 14px;
318
+ color: var(--muted);
319
+ font-size: 12px;
320
+ }
321
+
213
322
  #messages {
214
323
  padding: 22px;
215
324
  overflow: auto;
@@ -255,6 +364,39 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
255
364
  background: #fff6f6;
256
365
  }
257
366
 
367
+ #trace {
368
+ border-top: 1px solid var(--line);
369
+ padding: 12px 22px;
370
+ display: grid;
371
+ gap: 8px;
372
+ background: #fbfbfa;
373
+ }
374
+
375
+ .tool-call {
376
+ border: 1px solid var(--line);
377
+ border-radius: 8px;
378
+ padding: 10px 12px;
379
+ display: grid;
380
+ gap: 6px;
381
+ font-size: 12px;
382
+ }
383
+
384
+ .tool-head {
385
+ display: flex;
386
+ flex-wrap: wrap;
387
+ gap: 8px;
388
+ align-items: center;
389
+ color: var(--muted);
390
+ font-weight: 700;
391
+ }
392
+
393
+ .tool-call pre {
394
+ margin: 0;
395
+ max-height: 180px;
396
+ overflow: auto;
397
+ white-space: pre-wrap;
398
+ }
399
+
258
400
  form {
259
401
  border-top: 1px solid var(--line);
260
402
  padding: 14px;
@@ -286,6 +428,13 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
286
428
  cursor: pointer;
287
429
  }
288
430
 
431
+ button.secondary {
432
+ min-height: 34px;
433
+ color: var(--ink);
434
+ background: #eef1ee;
435
+ border: 1px solid var(--line);
436
+ }
437
+
289
438
  button:disabled {
290
439
  cursor: wait;
291
440
  opacity: 0.65;
@@ -305,10 +454,20 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
305
454
  <body>
306
455
  <main>
307
456
  <header>
308
- <h1>AgentKit Hosted Chat</h1>
309
- <code>${deployUrl}</code>
457
+ <div class="topline">
458
+ <div>
459
+ <h1>AgentKit Hosted Chat</h1>
460
+ <code>${deployUrl}</code>
461
+ </div>
462
+ <button class="secondary" id="new-conversation" type="button">New conversation</button>
463
+ </div>
464
+ <div class="meta">
465
+ <span>Conversation: <code id="conversation-id">none</code></span>
466
+ <span>Tool calls: <code id="tool-count">0</code></span>
467
+ </div>
310
468
  </header>
311
469
  <section id="messages" aria-live="polite"></section>
470
+ <section id="trace" aria-live="polite"></section>
312
471
  <form id="form">
313
472
  <textarea id="message" name="message" placeholder="Type a message" required autofocus></textarea>
314
473
  <button id="send" type="submit">Send</button>
@@ -319,6 +478,10 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
319
478
  const textarea = document.querySelector("#message");
320
479
  const send = document.querySelector("#send");
321
480
  const messages = document.querySelector("#messages");
481
+ const trace = document.querySelector("#trace");
482
+ const conversationLabel = document.querySelector("#conversation-id");
483
+ const toolCount = document.querySelector("#tool-count");
484
+ const newConversation = document.querySelector("#new-conversation");
322
485
  let conversationId = null;
323
486
 
324
487
  function addMessage(role, content, className = "") {
@@ -335,6 +498,55 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
335
498
  messages.scrollTop = messages.scrollHeight;
336
499
  }
337
500
 
501
+ function setConversationId(value) {
502
+ conversationId = value || null;
503
+ conversationLabel.textContent = conversationId || "none";
504
+ }
505
+
506
+ function renderTrace(payload) {
507
+ const calls = [];
508
+ for (const run of payload.runs || []) {
509
+ for (const call of run.toolCalls || []) {
510
+ calls.push(call);
511
+ }
512
+ }
513
+
514
+ toolCount.textContent = String(calls.length);
515
+ trace.innerHTML = "";
516
+
517
+ for (const call of calls.slice(-8)) {
518
+ const item = document.createElement("article");
519
+ item.className = "tool-call";
520
+ const head = document.createElement("div");
521
+ head.className = "tool-head";
522
+ head.textContent = [call.name, call.status, call.errorMessage].filter(Boolean).join(" · ");
523
+ const input = document.createElement("pre");
524
+ input.textContent = JSON.stringify(call.input || {}, null, 2);
525
+ item.append(head, input);
526
+ trace.append(item);
527
+ }
528
+ }
529
+
530
+ async function refreshTrace() {
531
+ if (!conversationId) {
532
+ toolCount.textContent = "0";
533
+ trace.innerHTML = "";
534
+ return;
535
+ }
536
+
537
+ const response = await fetch("/v1/conversations/" + encodeURIComponent(conversationId) + "/trace");
538
+ const payload = await response.json();
539
+ if (response.ok) renderTrace(payload);
540
+ }
541
+
542
+ newConversation.addEventListener("click", () => {
543
+ setConversationId(null);
544
+ messages.innerHTML = "";
545
+ trace.innerHTML = "";
546
+ toolCount.textContent = "0";
547
+ textarea.focus();
548
+ });
549
+
338
550
  textarea.addEventListener("keydown", (event) => {
339
551
  if (event.key !== "Enter" || event.shiftKey || event.isComposing) return;
340
552
  event.preventDefault();
@@ -363,10 +575,12 @@ function renderDeployChatUi(input: { deployUrl: string }): string {
363
575
  throw new Error(payload.error?.message || "Request failed");
364
576
  }
365
577
 
366
- conversationId = payload.conversationId || conversationId;
578
+ setConversationId(payload.conversationId || conversationId);
367
579
  addMessage("assistant", payload.message?.content || "");
580
+ await refreshTrace();
368
581
  } catch (error) {
369
582
  addMessage("error", error instanceof Error ? error.message : String(error), "error");
583
+ await refreshTrace().catch(() => {});
370
584
  } finally {
371
585
  send.disabled = false;
372
586
  textarea.focus();