@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.
Files changed (97) hide show
  1. package/README.md +8 -77
  2. package/docs/guides/add-channel.md +14 -92
  3. package/docs/guides/add-knowledge.md +0 -21
  4. package/docs/guides/add-tool.md +5 -11
  5. package/docs/guides/channel-security.md +3 -207
  6. package/docs/guides/connect-discord.md +7 -172
  7. package/docs/guides/connect-slack.md +6 -121
  8. package/docs/guides/connect-telegram.md +6 -165
  9. package/docs/guides/connect-whatsapp-evolution.md +6 -116
  10. package/docs/guides/connect-whatsapp-uazapi.md +6 -134
  11. package/docs/guides/connect-whatsapp-zapster.md +6 -202
  12. package/docs/guides/create-agent.md +5 -14
  13. package/docs/guides/debug-channel.md +4 -156
  14. package/docs/guides/improve-local.md +13 -0
  15. package/docs/guides/local-only-migration.md +35 -0
  16. package/docs/guides/replay-local-traces.md +11 -0
  17. package/docs/guides/run-evals.md +2 -4
  18. package/docs/guides/security-rules.md +5 -154
  19. package/docs/guides/use-jev.md +3 -6
  20. package/docs/guides/use-provider.md +5 -6
  21. package/docs/guides/write-feedback.md +10 -0
  22. package/docs/llms-full.txt +27 -448
  23. package/docs/llms.txt +8 -44
  24. package/package.json +3 -5
  25. package/src/cli/commands/channels.ts +8 -1613
  26. package/src/cli/commands/feedback.ts +8 -86
  27. package/src/cli/commands/provider.ts +29 -11
  28. package/src/cli/constants.ts +0 -3
  29. package/src/cli/flags.ts +0 -28
  30. package/src/cli/help.ts +16 -92
  31. package/src/cli/index.ts +15 -1091
  32. package/src/index.ts +6 -158
  33. package/src/providers/codex-auth.ts +16 -2
  34. package/src/providers/pi.ts +36 -19
  35. package/src/runtime/channels/discord.ts +2 -2
  36. package/src/runtime/chat.ts +5 -3
  37. package/src/runtime/config.ts +14 -148
  38. package/src/runtime/database.ts +2 -2
  39. package/src/runtime/dev-server.ts +8 -8
  40. package/src/runtime/env.ts +11 -0
  41. package/src/runtime/improve.ts +2 -262
  42. package/src/runtime/inspect.ts +13 -73
  43. package/src/runtime/knowledge/ingest.ts +1 -1
  44. package/src/runtime/knowledge/tool.ts +16 -2
  45. package/src/runtime/knowledge/vector.ts +1 -1
  46. package/src/runtime/tool-runner.ts +5 -3
  47. package/src/runtime/tools.ts +10 -14
  48. package/src/storage/sqlite.ts +11 -32
  49. package/src/templates/blank.ts +15 -102
  50. package/src/templates/common.ts +60 -0
  51. package/src/templates/dentista.ts +7 -74
  52. package/src/templates/skills/agentkit-capsule/SKILL.md +5 -7
  53. package/src/templates/skills/agentkit-capsule/references/docs-router.md +2 -3
  54. package/src/templates/skills/agentkit-channels/SKILL.md +6 -119
  55. package/src/templates/skills/agentkit-channels/references/channel-buffering.md +0 -9
  56. package/src/templates/skills/agentkit-channels/references/channel-debugging.md +1 -64
  57. package/src/templates/skills/agentkit-channels/references/discord.md +2 -92
  58. package/src/templates/skills/agentkit-channels/references/slack.md +2 -55
  59. package/src/templates/skills/agentkit-channels/references/telegram.md +2 -71
  60. package/src/templates/skills/agentkit-channels/references/whatsapp-evolution.md +2 -56
  61. package/src/templates/skills/agentkit-channels/references/whatsapp-uazapi.md +2 -53
  62. package/src/templates/skills/agentkit-channels/references/whatsapp-zapster.md +2 -70
  63. package/src/templates/skills/agentkit-database/SKILL.md +2 -4
  64. package/src/templates/skills/agentkit-evals/SKILL.md +1 -1
  65. package/src/templates/skills/agentkit-improve/SKILL.md +6 -85
  66. package/src/templates/skills/agentkit-improve/references/trace-packets.md +1 -1
  67. package/src/templates/skills/agentkit-provider/SKILL.md +1 -2
  68. package/src/templates/skills/agentkit-security/SKILL.md +1 -3
  69. package/src/templates/skills/agentkit-tools/SKILL.md +1 -1
  70. package/src/templates/skills/agentkit-tools/examples/database-write.tool.md +1 -2
  71. package/src/templates/skills/agentkit-troubleshooting/SKILL.md +5 -11
  72. package/src/templates/support.ts +8 -92
  73. package/docs/guides/add-managed-composio.md +0 -165
  74. package/docs/guides/improve-from-production.md +0 -151
  75. package/docs/guides/prepare-deploy.md +0 -227
  76. package/docs/guides/replay-production-traces.md +0 -72
  77. package/docs/guides/send-feedback.md +0 -135
  78. package/src/cli/cloud-client.ts +0 -377
  79. package/src/cli/deploy-chat-ui.ts +0 -606
  80. package/src/cli/deploy-readiness.ts +0 -561
  81. package/src/cloud/artifact.ts +0 -139
  82. package/src/cloud/client.ts +0 -80
  83. package/src/cloud/contracts.ts +0 -63
  84. package/src/cloud/index.ts +0 -3
  85. package/src/runtime/build.ts +0 -43
  86. package/src/runtime/core/deploy-state.ts +0 -54
  87. package/src/runtime/core/manifest.ts +0 -283
  88. package/src/runtime/core/targets.ts +0 -133
  89. package/src/runtime/deploy-readiness.ts +0 -135
  90. package/src/runtime/deploy.ts +0 -1
  91. package/src/runtime/integrations/composio.ts +0 -425
  92. package/src/runtime/targets/cloudflare/build.ts +0 -3319
  93. package/src/runtime/targets/container/build.ts +0 -146
  94. package/src/runtime/targets/container/server.ts +0 -33
  95. package/src/runtime/targets/vps/deploy.ts +0 -223
  96. package/src/templates/skills/agentkit-deploy/SKILL.md +0 -52
  97. package/src/templates/skills/agentkit-integrations/SKILL.md +0 -98
package/src/cli/index.ts CHANGED
@@ -1,17 +1,13 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { existsSync } from "node:fs";
3
- import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
4
- import { dirname, join, relative, resolve } from "node:path";
3
+ import { readFile } from "node:fs/promises";
4
+ import { join, relative, resolve } from "node:path";
5
5
 
6
6
  import { createProject } from "../create-project";
7
- import { buildAgentCapsule } from "../runtime/build";
8
7
  import { findAgentCapsuleRoot, loadAgentCapsule } from "../runtime/config";
9
- import { readLocalDeployStateIfExists, type LocalDeployState } from "../runtime/core/deploy-state";
10
- import { resolveBuildTarget, resolveDeployTarget } from "../runtime/core/targets";
11
8
  import { getConversationFromCwd, listConversationsFromCwd } from "../runtime/conversations";
12
9
  import { getConversationTraceFromCwd } from "../runtime/traces";
13
10
  import { runAgentMessageFromCwd } from "../runtime/chat";
14
- import { deployBuildToAgentKitCloud, writeLocalDeployState } from "../runtime/deploy";
15
11
  import {
16
12
  migrateLocalDatabase,
17
13
  openLocalDatabaseShell,
@@ -21,57 +17,23 @@ import {
21
17
  import { runEvalsFromCwd, writeEvalFromConversation } from "../runtime/evals";
22
18
  import { findAgentKitDocs } from "../runtime/docs";
23
19
  import { listCapsuleEnv, setCapsuleEnv, unsetCapsuleEnv } from "../runtime/env";
24
- import { collectDeployImproveBundle, collectLocalImproveBundle, generateImproveEvals, replayImproveBundle } from "../runtime/improve";
20
+ import { collectLocalImproveBundle, generateImproveEvals, replayImproveBundle } from "../runtime/improve";
25
21
  import { checkAgentSpec, initializeAgentSpec } from "../runtime/spec";
26
22
  import { checkDefaultSkillStatus, syncDefaultSkillFiles } from "../runtime/skills";
27
23
  import { initializeSyncScaffold, runCapsuleSync } from "../runtime/sync";
28
24
  import { runToolFromCwd } from "../runtime/tool-runner";
29
25
  import { startAgentDevServer } from "../runtime/dev-server";
30
26
  import { inspectAgentCapsule } from "../runtime/inspect";
31
- import { AgentKitError, isAgentKitError } from "../runtime/errors";
32
- import { prepareVpsDeploy } from "../runtime/targets/vps/deploy";
33
- import { parseArgs, isHelpRequested, type ParsedArgs } from "./args";
27
+ import { isAgentKitError } from "../runtime/errors";
28
+ import { parseArgs, isHelpRequested } from "./args";
34
29
  import { resolveNewProjectName } from "./new-command";
35
30
  import {
36
31
  defaultAgentKitDevPort,
37
- defaultDeployChatAccessTokenName,
38
- defaultDeployChatAccessTokenPath,
39
32
  } from "./constants";
40
33
  import {
41
- clearCloudAuth,
42
- cloudApiRequest,
43
- readCloudAuth,
44
- readCloudAuthForApiUrl,
45
- readCloudError,
46
- resolveCloudApiUrl,
47
- verifyCloudLogin,
48
- writeCloudAuth,
49
- type AccountApiTokenCreateResponse,
50
- type AccountApiTokenListResponse,
51
- type BillingCheckoutIntentResponse,
52
- type BillingCheckoutResponse,
53
- type BillingClaimResponse,
54
- type BillingPortalResponse,
55
- type CloudMeResponse,
56
- type DeployAccessTokenCreateResponse,
57
- type DeployAccessTokenListResponse,
58
- } from "./cloud-client";
59
- import {
60
- checkDeployReadiness,
61
- formatDeployCloudAuthSummary,
62
- formatDeployOnlineCapacity,
63
- formatReadinessError,
64
- printDeployReadinessReport,
65
- resolveProjectIdForSecretCommand,
66
- syncHostedSecretsFromLocal,
67
- } from "./deploy-readiness";
68
- import { readDeployAccessTokenForUi, startDeployChatUiServer } from "./deploy-chat-ui";
69
- import {
70
- parseCloudApiUrl,
71
34
  parseOptionalStringFlag,
72
35
  parsePort,
73
36
  parseRequiredStringFlag,
74
- parseTargetFlag,
75
37
  resolveSecretInputValue,
76
38
  } from "./flags";
77
39
  import { renderCommandHelp, renderCommandReference, renderHelp } from "./help";
@@ -82,7 +44,6 @@ import { handleFeedbackCommand } from "./commands/feedback";
82
44
  import { handleKnowledgeCommand } from "./commands/knowledge";
83
45
  import { handleTranscribeCommand } from "./commands/transcribe";
84
46
 
85
- const hostedDeployEntitlement = "agentkit_cloud_deploy";
86
47
 
87
48
  async function main() {
88
49
  const args = parseArgs(process.argv.slice(2));
@@ -113,6 +74,10 @@ async function main() {
113
74
  throw new Error("Usage: agentkit help [commands]");
114
75
  }
115
76
 
77
+ if (args.flags.deploy !== undefined || args.flags.api !== undefined || args.flags.target !== undefined) {
78
+ throw new Error("AgentKit runs locally. Hosted --deploy, --api, and --target options are no longer supported.");
79
+ }
80
+
116
81
  warnIfUnsupportedNode();
117
82
 
118
83
  if (args.command === "provider") {
@@ -147,7 +112,6 @@ async function main() {
147
112
  console.log(" Codex starts at skills/agentkit-capsule/SKILL.md and treats your request as the brief");
148
113
  console.log(' npm run chat -- --message "hello"');
149
114
  console.log(" npm run dev");
150
- console.log(" npm run agentkit -- deploy");
151
115
  console.log("");
152
116
  console.log("Optional: manage local secrets with `printf %s \"$VALUE\" | npm run agentkit -- env set <NAME> --stdin`.");
153
117
  return;
@@ -189,37 +153,6 @@ async function main() {
189
153
  return;
190
154
  }
191
155
 
192
- if (args.command === "chat-ui") {
193
- if (!args.flags.deploy) {
194
- throw new Error("Usage: agentkit chat-ui --deploy [--port <number>] [--token-file <path>]");
195
- }
196
-
197
- const requestedPort = parsePort(args.flags.port, "agentkit chat-ui --deploy --port <number>");
198
- const port = requestedPort ?? 4124;
199
- const tokenFile = parseOptionalStringFlag(
200
- args.flags["token-file"],
201
- "token-file",
202
- "agentkit chat-ui --deploy --token-file <path>",
203
- );
204
- const server = await startDeployChatUiServer(process.cwd(), {
205
- port,
206
- tokenFile,
207
- autoPort: requestedPort === undefined,
208
- });
209
-
210
- console.log("AgentKit hosted chat UI running");
211
- console.log("");
212
- if (server.portConflict) {
213
- console.log(`Port ${server.portConflict.port} is already used. Started hosted chat UI at ${server.url}.`);
214
- console.log("");
215
- }
216
- console.log(`Chat: ${server.url}`);
217
- console.log(`Production: ${server.deployUrl}`);
218
- console.log(`Token: ${server.tokenSource}`);
219
- await waitForShutdown(server.stop);
220
- return;
221
- }
222
-
223
156
  if (args.command === "chat") {
224
157
  const message = args.flags.message;
225
158
  const conversationId = parseOptionalStringFlag(
@@ -373,32 +306,7 @@ async function main() {
373
306
  "agentkit improve collect --conversation-id <id>",
374
307
  );
375
308
  const out = parseOptionalStringFlag(args.flags.out, "out", "agentkit improve collect --out <directory>");
376
- const deployState = args.flags.deploy === true ? await requireLocalDeployState() : null;
377
- const apiUrl = args.flags.deploy === true ? await resolveCloudApiUrl(args.flags.api) : null;
378
- const cloudAuth = apiUrl ? await readCloudAuthForApiUrl(apiUrl) : null;
379
- const result = args.flags.deploy === true
380
- ? await collectDeployImproveBundle(process.cwd(), {
381
- deployId: deployState?.deploy_id ?? "",
382
- since,
383
- conversationId,
384
- out,
385
- collector: {
386
- ...(cloudAuth && apiUrl && deployState
387
- ? {
388
- exportEvidence: (input: { deployId: string; since?: string; conversationId?: string }) =>
389
- fetchDeployImproveEvidence(apiUrl, input),
390
- }
391
- : {}),
392
- listConversations: () => fetchDeployConversationJson(process.cwd(), "/v1/conversations"),
393
- getTrace: (id: string) =>
394
- fetchDeployConversationJson(process.cwd(), `/v1/conversations/${encodeURIComponent(id)}/trace`),
395
- },
396
- })
397
- : await collectLocalImproveBundle(process.cwd(), {
398
- since,
399
- conversationId,
400
- out,
401
- });
309
+ const result = await collectLocalImproveBundle(process.cwd(), { since, conversationId, out });
402
310
 
403
311
  console.log("Improve bundle collected");
404
312
  console.log(`Source: ${result.source}`);
@@ -437,7 +345,7 @@ async function main() {
437
345
  return;
438
346
  }
439
347
 
440
- throw new Error("Usage: agentkit improve collect [--deploy] [--since <duration|iso>] [--conversation-id <id>] [--out <directory>] | agentkit improve evals <bundle-dir-or-json> [--force]");
348
+ throw new Error("Usage: agentkit improve collect [--since <duration|iso>] [--conversation-id <id>] [--out <directory>] | agentkit improve evals <bundle-dir-or-json> [--force]");
441
349
  }
442
350
 
443
351
  if (args.command === "replay") {
@@ -479,14 +387,8 @@ async function main() {
479
387
 
480
388
  if (args.command === "conversations") {
481
389
  const [subcommand, conversationId] = args.positional;
482
- const fromDeploy = args.flags.deploy === true;
483
390
 
484
391
  if (subcommand === "list") {
485
- if (fromDeploy) {
486
- const payload = await fetchDeployConversationJson(process.cwd(), "/v1/conversations");
487
- printJson(payload);
488
- return;
489
- }
490
392
 
491
393
  const conversations = await listConversationsFromCwd(process.cwd());
492
394
 
@@ -513,16 +415,7 @@ async function main() {
513
415
 
514
416
  if (subcommand === "show") {
515
417
  if (!conversationId) {
516
- throw new Error("Missing conversation id. Usage: agentkit conversations show <conversation-id> [--deploy]");
517
- }
518
-
519
- if (fromDeploy) {
520
- const payload = await fetchDeployConversationJson(
521
- process.cwd(),
522
- `/v1/conversations/${encodeURIComponent(conversationId)}`,
523
- );
524
- printJson(payload);
525
- return;
418
+ throw new Error("Missing conversation id. Usage: agentkit conversations show <conversation-id>");
526
419
  }
527
420
 
528
421
  const conversation = await getConversationFromCwd(process.cwd(), conversationId);
@@ -541,16 +434,7 @@ async function main() {
541
434
 
542
435
  if (subcommand === "trace") {
543
436
  if (!conversationId) {
544
- throw new Error("Missing conversation id. Usage: agentkit conversations trace <conversation-id> [--deploy]");
545
- }
546
-
547
- if (fromDeploy) {
548
- const trace = await fetchDeployConversationJson(
549
- process.cwd(),
550
- `/v1/conversations/${encodeURIComponent(conversationId)}/trace`,
551
- );
552
- printJson(trace);
553
- return;
437
+ throw new Error("Missing conversation id. Usage: agentkit conversations trace <conversation-id>");
554
438
  }
555
439
 
556
440
  const trace = await getConversationTraceFromCwd(process.cwd(), conversationId);
@@ -558,7 +442,7 @@ async function main() {
558
442
  return;
559
443
  }
560
444
 
561
- throw new Error("Usage: agentkit conversations list [--deploy] | agentkit conversations show <conversation-id> [--deploy] | agentkit conversations trace <conversation-id> [--deploy]");
445
+ throw new Error("Usage: agentkit conversations list | agentkit conversations show <conversation-id> | agentkit conversations trace <conversation-id>");
562
446
  }
563
447
 
564
448
  if (args.command === "knowledge") {
@@ -648,505 +532,6 @@ async function main() {
648
532
  return;
649
533
  }
650
534
 
651
- if (args.command === "build") {
652
- const target = resolveBuildTarget(parseTargetFlag(args.flags.target, "build"));
653
- const result = await buildAgentCapsule(process.cwd(), { target: target.id });
654
- printBuildResult(result);
655
- return;
656
- }
657
-
658
- if (args.command === "login") {
659
- const token = parseRequiredStringFlag(args.flags.token, "token", "agentkit login --token <token> [--api <url>]");
660
- const apiUrl = parseCloudApiUrl(args.flags.api);
661
- const verified = await verifyCloudLogin(apiUrl, token);
662
- await writeCloudAuth({ apiUrl, token });
663
- const email = verified.me.account?.email;
664
- console.log(email ? `Logged in to AgentKit Cloud as ${email}.` : "AgentKit Cloud token verified and stored.");
665
-
666
- const hasHostedDeploy = (verified.capabilities.capabilities ?? []).some(
667
- (capability) =>
668
- (capability.name === "cloudflare_deploy_alpha" || capability.name === hostedDeployEntitlement) &&
669
- capability.status === "active",
670
- );
671
- console.log(
672
- hasHostedDeploy
673
- ? "Entitlement: hosted deploy active."
674
- : `Warning: cloudflare_deploy_alpha or ${hostedDeployEntitlement} entitlement was not found for this account.`,
675
- );
676
-
677
- if (process.env.AGENTKIT_CLOUD_API_TOKEN && process.env.AGENTKIT_CLOUD_API_TOKEN !== token) {
678
- console.log("Warning: AGENTKIT_CLOUD_API_TOKEN is set and will override this saved login in the current shell.");
679
- }
680
-
681
- return;
682
- }
683
-
684
- if (args.command === "logout") {
685
- await clearCloudAuth();
686
- console.log("AgentKit Cloud token removed.");
687
- return;
688
- }
689
-
690
- if (args.command === "account") {
691
- const [noun, verb, value] = args.positional;
692
-
693
- if (noun !== "token") {
694
- throw new Error("Usage: agentkit account token create <name> [--use] [--out <path>] | list | revoke <token-id> [--api <url>]");
695
- }
696
-
697
- const apiUrl = await resolveCloudApiUrl(args.flags.api);
698
-
699
- if (verb === "create" && value) {
700
- const payload = (await cloudApiRequest(apiUrl, "/v1/account/tokens", {
701
- method: "POST",
702
- body: JSON.stringify({ name: value }),
703
- })) as AccountApiTokenCreateResponse;
704
- const token = payload.token;
705
-
706
- if (!token?.token || !token.id) {
707
- throw new AgentKitError("account_token_invalid", "AgentKit Cloud returned an invalid account token payload.");
708
- }
709
-
710
- const outPath = parseOptionalStringFlag(
711
- args.flags.out,
712
- "out",
713
- "agentkit account token create <name> [--api <url>] [--use] [--out <path>]",
714
- );
715
-
716
- if (outPath) {
717
- const absolutePath = resolve(process.cwd(), outPath);
718
- await writeSecretJson(absolutePath, payload);
719
- console.log(`Account token written to ${absolutePath}`);
720
- } else {
721
- printJson(payload);
722
- }
723
-
724
- if (args.flags.use === true) {
725
- await writeCloudAuth({ apiUrl, token: token.token });
726
- console.log(`Saved ${token.id} as the current AgentKit Cloud login.`);
727
- }
728
-
729
- return;
730
- }
731
-
732
- if (verb === "list" && !value) {
733
- const payload = (await cloudApiRequest(apiUrl, "/v1/account/tokens", {
734
- method: "GET",
735
- })) as AccountApiTokenListResponse;
736
- printJson(payload);
737
- return;
738
- }
739
-
740
- if (verb === "revoke" && value) {
741
- const payload = await cloudApiRequest(apiUrl, `/v1/account/tokens/${encodeURIComponent(value)}/revoke`, {
742
- method: "POST",
743
- });
744
- printJson(payload);
745
- return;
746
- }
747
-
748
- throw new Error("Usage: agentkit account token create <name> [--use] [--out <path>] | list | revoke <token-id> [--api <url>]");
749
- }
750
-
751
- if (args.command === "billing") {
752
- const [subcommand, intentId] = args.positional;
753
- const apiUrl = await resolveCloudApiUrl(args.flags.api);
754
-
755
- if (subcommand === "checkout") {
756
- const slots = parsePositiveIntegerFlag(
757
- args.flags.slots,
758
- "slots",
759
- "agentkit billing checkout --slots <count> [--email <email>] [--api <url>]",
760
- );
761
- const email = parseOptionalStringFlag(
762
- args.flags.email,
763
- "email",
764
- "agentkit billing checkout --slots <count> --email <email>",
765
- );
766
- const payload = (await cloudApiRequest(apiUrl, "/v1/billing/checkout", {
767
- method: "POST",
768
- body: JSON.stringify({
769
- slots,
770
- ...(email ? { email } : {}),
771
- }),
772
- })) as BillingCheckoutResponse;
773
- const checkoutUrl = payload.checkout?.url;
774
- const billingIntentId = payload.billing_intent?.id;
775
- const secret = payload.billing_intent?.secret;
776
-
777
- if (!checkoutUrl || !billingIntentId || !secret) {
778
- throw new AgentKitError("billing_checkout_invalid", "AgentKit Cloud returned an invalid billing checkout payload.");
779
- }
780
-
781
- if (args.flags.json === true) {
782
- printJson(payload);
783
- } else {
784
- console.log("AgentKit Cloud checkout");
785
- console.log("");
786
- console.log(`URL: ${checkoutUrl}`);
787
- console.log(`Intent: ${billingIntentId}`);
788
- console.log(`Secret: ${secret}`);
789
- console.log("");
790
- console.log(`After payment: agentkit billing claim ${billingIntentId} --secret ${secret} --api ${apiUrl}`);
791
- }
792
-
793
- if (args.flags.open === true) {
794
- await openLocalUrl(checkoutUrl);
795
- }
796
-
797
- return;
798
- }
799
-
800
- if (subcommand === "status" && intentId) {
801
- const secret = parseRequiredStringFlag(
802
- args.flags.secret,
803
- "secret",
804
- "agentkit billing status <billing-intent-id> --secret <secret> [--api <url>]",
805
- );
806
- const payload = (await cloudApiRequest(
807
- apiUrl,
808
- `/v1/billing/checkout-intents/${encodeURIComponent(intentId)}?secret=${encodeURIComponent(secret)}`,
809
- { method: "GET" },
810
- )) as BillingCheckoutIntentResponse;
811
- printJson(payload);
812
- return;
813
- }
814
-
815
- if (subcommand === "claim" && intentId) {
816
- const secret = parseRequiredStringFlag(
817
- args.flags.secret,
818
- "secret",
819
- "agentkit billing claim <billing-intent-id> --secret <secret> [--token-name <name>] [--api <url>]",
820
- );
821
- const tokenName = parseOptionalStringFlag(
822
- args.flags["token-name"],
823
- "token-name",
824
- "agentkit billing claim <billing-intent-id> --secret <secret> --token-name <name>",
825
- );
826
- const payload = (await cloudApiRequest(apiUrl, `/v1/billing/checkout-intents/${encodeURIComponent(intentId)}/claim`, {
827
- method: "POST",
828
- body: JSON.stringify({
829
- secret,
830
- ...(tokenName ? { token_name: tokenName } : {}),
831
- }),
832
- })) as BillingClaimResponse;
833
- const token = payload.token;
834
-
835
- if (!token?.token || !token.id) {
836
- throw new AgentKitError("billing_claim_invalid", "AgentKit Cloud returned an invalid billing claim payload.");
837
- }
838
-
839
- await writeCloudAuth({ apiUrl, token: token.token });
840
-
841
- const outPath = parseOptionalStringFlag(
842
- args.flags.out,
843
- "out",
844
- "agentkit billing claim <billing-intent-id> --secret <secret> [--out <path>]",
845
- );
846
-
847
- if (outPath) {
848
- const absolutePath = resolve(process.cwd(), outPath);
849
- await writeSecretJson(absolutePath, payload);
850
- console.log(`Account token written to ${absolutePath}`);
851
- } else if (args.flags.json === true) {
852
- printJson(payload);
853
- } else {
854
- console.log("AgentKit Cloud account token claimed and saved.");
855
- console.log(`Token: ${token.id}`);
856
- console.log(`API: ${apiUrl}`);
857
- }
858
-
859
- return;
860
- }
861
-
862
- if (subcommand === "portal") {
863
- const payload = (await cloudApiRequest(apiUrl, "/v1/billing/portal", {
864
- method: "POST",
865
- body: JSON.stringify({}),
866
- })) as BillingPortalResponse;
867
- const portalUrl = payload.portal?.url;
868
-
869
- if (!portalUrl) {
870
- throw new AgentKitError("billing_portal_invalid", "AgentKit Cloud returned an invalid billing portal payload.");
871
- }
872
-
873
- if (args.flags.json === true) {
874
- printJson(payload);
875
- } else {
876
- console.log("AgentKit Cloud billing portal");
877
- console.log(`URL: ${portalUrl}`);
878
- }
879
-
880
- if (args.flags.open === true) {
881
- await openLocalUrl(portalUrl);
882
- }
883
-
884
- return;
885
- }
886
-
887
- throw new Error(
888
- "Usage: agentkit billing checkout --slots <count> [--email <email>] | status <intent-id> --secret <secret> | claim <intent-id> --secret <secret> | portal [--api <url>]",
889
- );
890
- }
891
-
892
- if (args.command === "deploy") {
893
- const [deploySubcommand] = args.positional;
894
-
895
- if (deploySubcommand === "smoke") {
896
- const message =
897
- parseOptionalStringFlag(args.flags.message ?? args.flags.smoke, "message", 'agentkit deploy smoke --message "hello"') ??
898
- "hello";
899
- const state = await requireLocalDeployState();
900
- const token = await readDeployAccessTokenForHostedRequest(process.cwd());
901
- await runDeploySmoke({
902
- deployUrl: requireDeployUrl(state),
903
- message,
904
- token,
905
- });
906
- return;
907
- }
908
-
909
- if (deploySubcommand === "doctor") {
910
- const report = await checkDeployReadiness({
911
- apiUrl: await resolveCloudApiUrl(args.flags.api),
912
- requireLogin: !args.flags.anonymous,
913
- });
914
- printDeployReadinessReport(report);
915
-
916
- if (!report.ok) {
917
- process.exitCode = 1;
918
- }
919
-
920
- return;
921
- }
922
-
923
- if (deploySubcommand === "status" || deploySubcommand === "pause" || deploySubcommand === "resume") {
924
- const state = await requireLocalDeployState();
925
- const apiUrl = await resolveCloudApiUrl(args.flags.api);
926
-
927
- if (deploySubcommand === "status") {
928
- const payload = await cloudApiRequest(apiUrl, `/v1/deploys/${encodeURIComponent(state.deploy_id)}`, {
929
- method: "GET",
930
- });
931
- printJson(payload);
932
- return;
933
- }
934
-
935
- const payload = await cloudApiRequest(apiUrl, `/v1/deploys/${encodeURIComponent(state.deploy_id)}/${deploySubcommand}`, {
936
- method: "POST",
937
- });
938
- printJson(payload);
939
- return;
940
- }
941
-
942
- const target = resolveDeployTarget(parseTargetFlag(args.flags.target, "deploy"));
943
- const anonymous = Boolean(args.flags.anonymous);
944
- const smokeMessage = parseOptionalStringFlag(args.flags.smoke, "smoke", 'agentkit deploy --smoke "hello"');
945
-
946
- if (target.id === "vps") {
947
- const host = parseRequiredStringFlag(args.flags.host, "host", "agentkit deploy --target vps --host <host>");
948
- const container = await buildAgentCapsule(process.cwd(), { target: "container" });
949
- const plan = await prepareVpsDeploy(container, { host, dryRun: Boolean(args.flags["dry-run"]) });
950
- printBuildResult(container);
951
- printVpsDeployPlan(plan);
952
- return;
953
- }
954
-
955
- let readinessReport: Awaited<ReturnType<typeof checkDeployReadiness>> | null = null;
956
-
957
- if (!args.flags["dry-run"] && !args.flags["local-wrangler"]) {
958
- readinessReport = await checkDeployReadiness({
959
- apiUrl: await resolveCloudApiUrl(args.flags.api),
960
- requireLogin: !anonymous,
961
- });
962
-
963
- if (!readinessReport.ok) {
964
- printDeployReadinessReport(readinessReport);
965
- throw new AgentKitError(
966
- "deploy_readiness_failed",
967
- "Fix deploy readiness failures before running agentkit deploy.",
968
- );
969
- }
970
- }
971
-
972
- const result = await buildAgentCapsule(process.cwd(), { target: target.id });
973
- if (result.target !== "cloudflare") {
974
- throw new Error(`Unsupported AgentKit Cloud deploy target: ${result.target}`);
975
- }
976
- printBuildResult(result);
977
-
978
- if (args.flags["dry-run"]) {
979
- console.log("");
980
- console.log("Dry run only. Artifact is ready for AgentKit Cloud.");
981
- return;
982
- }
983
-
984
- if (args.flags["local-wrangler"]) {
985
- await deployCloudflare(result.wranglerPath, result.buildDir);
986
- return;
987
- }
988
-
989
- const apiUrl = await resolveCloudApiUrl(args.flags.api);
990
- const auth = anonymous ? null : await readCloudAuthForApiUrl(apiUrl);
991
- const deploy = await deployBuildToAgentKitCloud(result, {
992
- apiUrl,
993
- apiToken: anonymous ? null : auth?.token,
994
- anonymous: anonymous || !auth?.token,
995
- });
996
- const statePath = await writeLocalDeployState(result.root, deploy);
997
- const chatAccess = await ensureDeployChatAccessToken({
998
- apiUrl,
999
- root: result.root,
1000
- deployId: deploy.deploy.id,
1001
- skip: anonymous || !auth?.token,
1002
- });
1003
-
1004
- console.log("");
1005
- console.log("Deploy ready");
1006
- console.log(`URL: ${deploy.deploy.url}`);
1007
- console.log(`Project: ${deploy.project.id}`);
1008
- console.log(`Deploy: ${deploy.deploy.id}`);
1009
- console.log(`State: ${statePath}`);
1010
- printDeployCloudSummary(readinessReport);
1011
-
1012
- if (chatAccess?.status === "ready") {
1013
- console.log(`Chat auth: ${relativePath(process.cwd(), chatAccess.path)}`);
1014
- } else if (chatAccess?.status === "skipped") {
1015
- console.log("Chat auth: anonymous deploy; no local chat token was created.");
1016
- } else if (chatAccess?.status === "failed") {
1017
- console.log(`Chat auth: could not create local chat token. ${formatReadinessError(chatAccess.error)}`);
1018
- console.log(`Run: agentkit access token create ${defaultDeployChatAccessTokenName} --out ${defaultDeployChatAccessTokenPath}`);
1019
- }
1020
-
1021
- if (smokeMessage) {
1022
- if (chatAccess?.status === "failed") {
1023
- throw new AgentKitError("deploy_smoke_failed", "Could not run deploy smoke because chat access token creation failed.");
1024
- }
1025
-
1026
- await runDeploySmoke({
1027
- deployUrl: requireDeployUrl({
1028
- deploy_id: deploy.deploy.id,
1029
- url: deploy.deploy.url,
1030
- }),
1031
- message: smokeMessage,
1032
- token:
1033
- chatAccess?.status === "ready"
1034
- ? await readDeployAccessTokenForUi(chatAccess.path)
1035
- : undefined,
1036
- });
1037
- }
1038
- printDeployProductionHandoff({
1039
- deployUrl: deploy.deploy.url,
1040
- statePath,
1041
- chatAccess,
1042
- databaseSchemaPath: result.tursoSchemaPath,
1043
- readinessReport,
1044
- smokeMessage,
1045
- });
1046
- return;
1047
- }
1048
-
1049
- if (args.command === "secret") {
1050
- const [subcommand, name, ...valueParts] = args.positional;
1051
- const apiUrl = await resolveCloudApiUrl(args.flags.api);
1052
- const projectId = await resolveProjectIdForSecretCommand(process.cwd(), apiUrl);
1053
-
1054
- if (subcommand === "list") {
1055
- const payload = await cloudApiRequest(apiUrl, `/v1/projects/${encodeURIComponent(projectId)}/secrets`, {
1056
- method: "GET",
1057
- });
1058
- printJson(payload);
1059
- return;
1060
- }
1061
-
1062
- if (subcommand === "set") {
1063
- const value = await resolveSecretInputValue({
1064
- name,
1065
- valueParts,
1066
- stdinFlag: args.flags.stdin,
1067
- fromEnvFlag: args.flags["from-env"],
1068
- fromLocalEnvFlag: args.flags["from-local-env"],
1069
- localEnvRoot: args.flags["from-local-env"] !== undefined ? await findAgentCapsuleRoot(process.cwd()) : undefined,
1070
- usage: "agentkit secret set <NAME> <VALUE> | agentkit secret set <NAME> --stdin | agentkit secret set <NAME> --from-env [ENV_NAME] | agentkit secret set <NAME> --from-local-env [--api <url>]",
1071
- inlineSensitiveHelp: "Prefer --stdin, --from-env, or --from-local-env so the value does not enter shell history.",
1072
- });
1073
-
1074
- if (!name) {
1075
- throw new Error("Usage: agentkit secret set <NAME> <VALUE> | agentkit secret set <NAME> --stdin | agentkit secret set <NAME> --from-env [ENV_NAME] | agentkit secret set <NAME> --from-local-env [--api <url>]");
1076
- }
1077
-
1078
- const payload = await cloudApiRequest(apiUrl, `/v1/projects/${encodeURIComponent(projectId)}/secrets/${encodeURIComponent(name)}`, {
1079
- method: "PUT",
1080
- body: JSON.stringify({ value }),
1081
- });
1082
- printJson(payload);
1083
- return;
1084
- }
1085
-
1086
- if (subcommand === "sync") {
1087
- if (args.flags["from-local"] !== true) {
1088
- throw new Error("Usage: agentkit secret sync --from-local [--api <url>]");
1089
- }
1090
-
1091
- await syncHostedSecretsFromLocal({ apiUrl, projectId });
1092
- return;
1093
- }
1094
-
1095
- if (subcommand === "unset") {
1096
- if (!name) {
1097
- throw new Error("Usage: agentkit secret unset <NAME> [--api <url>]");
1098
- }
1099
-
1100
- const payload = await cloudApiRequest(apiUrl, `/v1/projects/${encodeURIComponent(projectId)}/secrets/${encodeURIComponent(name)}`, {
1101
- method: "DELETE",
1102
- });
1103
- printJson(payload);
1104
- return;
1105
- }
1106
-
1107
- throw new Error("Usage: agentkit secret set <NAME> <VALUE> | agentkit secret set <NAME> --stdin | agentkit secret set <NAME> --from-env [ENV_NAME] | agentkit secret set <NAME> --from-local-env | agentkit secret sync --from-local | agentkit secret list | agentkit secret unset <NAME>");
1108
- }
1109
-
1110
- if (args.command === "access") {
1111
- const [subcommand, noun, name] = args.positional;
1112
-
1113
- if (subcommand !== "token") {
1114
- throw new Error("Usage: agentkit access token create <name> [--out <path>] | list | revoke <token-id> [--api <url>]");
1115
- }
1116
-
1117
- const state = await requireLocalDeployState();
1118
- const apiUrl = await resolveCloudApiUrl(args.flags.api);
1119
-
1120
- if (noun === "create" && name) {
1121
- const payload = await cloudApiRequest(apiUrl, `/v1/deploys/${encodeURIComponent(state.deploy_id)}/access-tokens`, {
1122
- method: "POST",
1123
- body: JSON.stringify({ name }),
1124
- });
1125
- await printJsonOrWrite(payload, args.flags.out, "agentkit access token create <name> [--api <url>] [--out <path>]");
1126
- return;
1127
- }
1128
-
1129
- if (noun === "list" && !name) {
1130
- const payload = await cloudApiRequest(apiUrl, `/v1/deploys/${encodeURIComponent(state.deploy_id)}/access-tokens`, {
1131
- method: "GET",
1132
- });
1133
- printJson(payload);
1134
- return;
1135
- }
1136
-
1137
- if (noun === "revoke" && name) {
1138
- const payload = await cloudApiRequest(
1139
- apiUrl,
1140
- `/v1/deploys/${encodeURIComponent(state.deploy_id)}/access-tokens/${encodeURIComponent(name)}/revoke`,
1141
- { method: "POST" },
1142
- );
1143
- printJson(payload);
1144
- return;
1145
- }
1146
-
1147
- throw new Error("Usage: agentkit access token create <name> [--out <path>] | list | revoke <token-id> [--api <url>]");
1148
- }
1149
-
1150
535
  if (args.command === "channels") {
1151
536
  await handleChannelsCommand(args);
1152
537
  return;
@@ -1180,93 +565,6 @@ async function main() {
1180
565
  throw new Error("Usage: agentkit skills status | agentkit skills sync");
1181
566
  }
1182
567
 
1183
- if (args.command === "integrations") {
1184
- const [subcommand, provider] = args.positional;
1185
-
1186
- if (provider !== undefined && provider !== "composio") {
1187
- throw new Error("Usage: agentkit integrations status | connect composio [--toolkit <slug>] [--callback-url <url>] [--api <url>]");
1188
- }
1189
-
1190
- const state = await requireLocalDeployState();
1191
- const apiUrl = await resolveCloudApiUrl(args.flags.api);
1192
-
1193
- if (subcommand === "status") {
1194
- const toolkit = parseOptionalStringFlag(
1195
- args.flags.toolkit,
1196
- "toolkit",
1197
- "agentkit integrations status --toolkit <slug>",
1198
- );
1199
- const payload = await cloudApiRequest(
1200
- apiUrl,
1201
- `/v1/deploys/${encodeURIComponent(state.deploy_id)}/integrations/composio/status${
1202
- toolkit ? `?toolkit=${encodeURIComponent(toolkit)}` : ""
1203
- }`,
1204
- { method: "GET" },
1205
- );
1206
- printJson(payload);
1207
- return;
1208
- }
1209
-
1210
- if (subcommand === "connect" && provider === "composio") {
1211
- const toolkit = parseOptionalStringFlag(
1212
- args.flags.toolkit,
1213
- "toolkit",
1214
- "agentkit integrations connect composio --toolkit <slug>",
1215
- );
1216
- const callbackUrl = parseOptionalStringFlag(
1217
- args.flags["callback-url"],
1218
- "callback-url",
1219
- "agentkit integrations connect composio --callback-url <url>",
1220
- );
1221
- const payload = (await cloudApiRequest(
1222
- apiUrl,
1223
- `/v1/deploys/${encodeURIComponent(state.deploy_id)}/integrations/composio/connect-link`,
1224
- {
1225
- method: "POST",
1226
- body: JSON.stringify({
1227
- ...(toolkit ? { toolkit } : {}),
1228
- ...(callbackUrl ? { callback_url: callbackUrl } : {}),
1229
- }),
1230
- },
1231
- )) as {
1232
- connect_link?: {
1233
- toolkit?: string;
1234
- user_id?: string;
1235
- redirect_url?: string;
1236
- expires_at?: string;
1237
- connected_account_id?: string;
1238
- auth_config_source?: string;
1239
- };
1240
- };
1241
-
1242
- const link = payload.connect_link;
1243
-
1244
- if (!link?.redirect_url) {
1245
- throw new AgentKitError("integration_response_invalid", "AgentKit Cloud returned an invalid Composio connect-link payload.");
1246
- }
1247
-
1248
- console.log("Composio connect link");
1249
- console.log(`Toolkit: ${link.toolkit ?? toolkit ?? "unknown"}`);
1250
- console.log(`User: ${link.user_id ?? "unknown"}`);
1251
- if (link.auth_config_source) {
1252
- console.log(`Auth: ${link.auth_config_source}`);
1253
- }
1254
- console.log(`URL: ${link.redirect_url}`);
1255
-
1256
- if (link.expires_at) {
1257
- console.log(`Expires: ${link.expires_at}`);
1258
- }
1259
-
1260
- if (link.connected_account_id) {
1261
- console.log(`Account: ${link.connected_account_id}`);
1262
- }
1263
-
1264
- return;
1265
- }
1266
-
1267
- throw new Error("Usage: agentkit integrations status | connect composio [--toolkit <slug>] [--callback-url <url>] [--api <url>]");
1268
- }
1269
-
1270
568
  if (args.command === "env") {
1271
569
  const [subcommand, name, ...valueParts] = args.positional;
1272
570
  const root = await findAgentCapsuleRoot(process.cwd());
@@ -1413,7 +711,6 @@ npm run agentkit -- tool tool_name --input '{}'
1413
711
 
1414
712
  UI testing:
1415
713
  - For local UI testing, run \`npm run dev\`, open the printed \`Chat:\` URL, and tell the owner the exact URL.
1416
- - For hosted UI testing after deploy, run \`npm run agentkit -- chat-ui --deploy\`, open the printed \`Chat:\` URL, and tell the owner it is connected to the hosted deploy.
1417
714
  - If the provider is still \`test/fake\`, say the UI was tested only with the deterministic fake provider.
1418
715
 
1419
716
  Final response:
@@ -1425,16 +722,12 @@ Final response:
1425
722
  `;
1426
723
  }
1427
724
 
1428
- function isRecord(value: unknown): value is Record<string, unknown> {
1429
- return typeof value === "object" && value !== null && !Array.isArray(value);
1430
- }
1431
-
1432
725
  function warnIfUnsupportedNode(): void {
1433
726
  const major = majorNodeVersion(process.versions.node);
1434
727
 
1435
728
  if (major !== null && major < 24) {
1436
729
  console.warn(
1437
- `Warning: @andreprado/agentkit requires Node >=24; current Node is ${process.versions.node}. Use Node 24+ before relying on local runtime or deploy commands.`,
730
+ `Warning: @andreprado/agentkit requires Node >=24; current Node is ${process.versions.node}. Use Node 24+ before relying on local runtime commands.`,
1438
731
  );
1439
732
  }
1440
733
  }
@@ -1445,291 +738,6 @@ function majorNodeVersion(version: string): number | null {
1445
738
  return Number.isInteger(parsed) ? parsed : null;
1446
739
  }
1447
740
 
1448
- function printDeployProductionHandoff(input: {
1449
- deployUrl: string;
1450
- statePath: string;
1451
- chatAccess: Awaited<ReturnType<typeof ensureDeployChatAccessToken>>;
1452
- databaseSchemaPath: string | null;
1453
- readinessReport: Awaited<ReturnType<typeof checkDeployReadiness>> | null;
1454
- smokeMessage?: string;
1455
- }): void {
1456
- const context = input.readinessReport?.context;
1457
- const userSecrets = context?.userManagedSecrets ?? [];
1458
- const managedSecrets = context?.agentKitManagedSecrets ?? [];
1459
- const composio = context?.integrations.managedComposio;
1460
-
1461
- console.log("");
1462
- console.log("Production handoff");
1463
- console.log(`URL: ${input.deployUrl}`);
1464
- console.log(`UI: npm run agentkit -- chat-ui --deploy`);
1465
- console.log(`State: ${input.statePath}`);
1466
- console.log(
1467
- `Secrets: ${
1468
- userSecrets.length > 0
1469
- ? `user-managed set (${userSecrets.join(", ")})`
1470
- : "no user-managed hosted secrets required"
1471
- }${managedSecrets.length > 0 ? `; AgentKit-managed: ${managedSecrets.join(", ")}` : ""}`,
1472
- );
1473
- console.log(
1474
- `Database: ${
1475
- input.databaseSchemaPath
1476
- ? `AgentKit-managed; schema artifact ${input.databaseSchemaPath}`
1477
- : "AgentKit-managed; no application schema artifact"
1478
- }`,
1479
- );
1480
-
1481
- if (composio?.enabled) {
1482
- console.log(`Integrations: managed Composio configured for ${composio.toolkits.join(", ")}`);
1483
- for (const toolkit of composio.toolkits) {
1484
- console.log(`Connect: npm run agentkit -- integrations connect composio --toolkit ${toolkit}`);
1485
- }
1486
- } else {
1487
- console.log("Integrations: none configured");
1488
- }
1489
-
1490
- if (input.smokeMessage) {
1491
- console.log(`Smoke: verified with ${JSON.stringify(input.smokeMessage)}`);
1492
- } else {
1493
- console.log('Smoke: not run; next check: npm run agentkit -- deploy smoke --message "hello"');
1494
- }
1495
-
1496
- if (input.chatAccess.status === "ready") {
1497
- console.log(`Chat token: ${relativePath(process.cwd(), input.chatAccess.path)}`);
1498
- } else if (input.chatAccess.status === "skipped") {
1499
- console.log("Chat token: not created for anonymous deploy");
1500
- } else {
1501
- console.log(`Chat token: failed; run npm run agentkit -- access token create ${defaultDeployChatAccessTokenName} --out ${defaultDeployChatAccessTokenPath}`);
1502
- }
1503
-
1504
- const nextCommand = composio?.enabled && composio.toolkits.length > 0
1505
- ? `npm run agentkit -- integrations connect composio --toolkit ${composio.toolkits[0]}`
1506
- : "npm run agentkit -- chat-ui --deploy";
1507
- console.log(`Next: ${nextCommand}`);
1508
- }
1509
-
1510
- function printDeployCloudSummary(report: Awaited<ReturnType<typeof checkDeployReadiness>> | null): void {
1511
- if (!report) {
1512
- return;
1513
- }
1514
-
1515
- const authSummary = formatDeployCloudAuthSummary(report);
1516
-
1517
- if (authSummary) {
1518
- console.log(`Account: ${authSummary.account}`);
1519
- console.log(`Auth: ${authSummary.source}`);
1520
- }
1521
-
1522
- const capacitySummary = formatDeployOnlineCapacity(report, "before deploy");
1523
-
1524
- if (capacitySummary) {
1525
- console.log(`Capacity: ${capacitySummary}`);
1526
- }
1527
- }
1528
-
1529
- async function ensureDeployChatAccessToken(options: {
1530
- apiUrl: string;
1531
- root: string;
1532
- deployId: string;
1533
- skip: boolean;
1534
- }): Promise<
1535
- | { status: "ready"; path: string; tokenId: string; created: boolean }
1536
- | { status: "skipped" }
1537
- | { status: "failed"; error: unknown }
1538
- > {
1539
- if (options.skip) {
1540
- return { status: "skipped" };
1541
- }
1542
-
1543
- try {
1544
- const path = join(options.root, defaultDeployChatAccessTokenPath);
1545
- const existing = await readDeployAccessTokenFile(path);
1546
-
1547
- if (existing?.deploy_id === options.deployId && existing.id) {
1548
- const listed = (await cloudApiRequest(
1549
- options.apiUrl,
1550
- `/v1/deploys/${encodeURIComponent(options.deployId)}/access-tokens`,
1551
- { method: "GET" },
1552
- )) as DeployAccessTokenListResponse;
1553
- const stillUsable = (listed.access_tokens ?? []).some(
1554
- (token) => token.id === existing.id && deployAccessTokenMetadataIsUsable(token),
1555
- );
1556
-
1557
- if (stillUsable) {
1558
- await chmod(path, 0o600);
1559
- return { status: "ready", path, tokenId: existing.id, created: false };
1560
- }
1561
- }
1562
-
1563
- const created = (await cloudApiRequest(
1564
- options.apiUrl,
1565
- `/v1/deploys/${encodeURIComponent(options.deployId)}/access-tokens`,
1566
- {
1567
- method: "POST",
1568
- body: JSON.stringify({ name: defaultDeployChatAccessTokenName }),
1569
- },
1570
- )) as DeployAccessTokenCreateResponse;
1571
- const token = created.access_token;
1572
-
1573
- if (!token?.id || token.deploy_id !== options.deployId || !token.token) {
1574
- throw new AgentKitError("access_token_invalid", "AgentKit Cloud returned an invalid deploy access token payload.");
1575
- }
1576
-
1577
- await writeSecretJson(path, created);
1578
- return { status: "ready", path, tokenId: token.id, created: true };
1579
- } catch (error) {
1580
- return { status: "failed", error };
1581
- }
1582
- }
1583
-
1584
- function deployAccessTokenMetadataIsUsable(token: { expires_at?: string }): boolean {
1585
- if (!token.expires_at) {
1586
- return true;
1587
- }
1588
-
1589
- const expiresAtMs = Date.parse(token.expires_at);
1590
- return Number.isFinite(expiresAtMs) && expiresAtMs > Date.now();
1591
- }
1592
-
1593
- async function readDeployAccessTokenFile(path: string): Promise<{ id?: string; deploy_id?: string } | null> {
1594
- try {
1595
- const parsed = JSON.parse(await readFile(path, "utf8")) as DeployAccessTokenCreateResponse;
1596
- return parsed.access_token ?? null;
1597
- } catch {
1598
- return null;
1599
- }
1600
- }
1601
-
1602
- async function writeSecretJson(path: string, value: unknown): Promise<void> {
1603
- await mkdir(dirname(path), { recursive: true });
1604
- await writeFile(path, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
1605
- await chmod(path, 0o600);
1606
- }
1607
-
1608
- async function requireLocalDeployState(): Promise<LocalDeployState> {
1609
- const state = await readLocalDeployStateIfExists(process.cwd());
1610
-
1611
- if (!state) {
1612
- throw new Error("No .agentkit/deploy.json found. Run agentkit deploy first.");
1613
- }
1614
-
1615
- return state;
1616
- }
1617
-
1618
- function requireDeployUrl(state: Pick<LocalDeployState, "deploy_id" | "url">): string {
1619
- if (!state.url) {
1620
- throw new Error(`Deploy ${state.deploy_id} does not have a URL. Run agentkit deploy again.`);
1621
- }
1622
-
1623
- return state.url;
1624
- }
1625
-
1626
- async function readDeployAccessTokenForHostedRequest(cwd: string): Promise<string> {
1627
- const root = await findAgentCapsuleRoot(cwd);
1628
- return readDeployAccessTokenForUi(join(root, defaultDeployChatAccessTokenPath));
1629
- }
1630
-
1631
- async function runDeploySmoke(input: { deployUrl: string; message: string; token?: string }): Promise<void> {
1632
- const headers = new Headers({ "Content-Type": "application/json" });
1633
-
1634
- if (input.token) {
1635
- headers.set("Authorization", `Bearer ${input.token}`);
1636
- }
1637
-
1638
- let response: Response;
1639
-
1640
- try {
1641
- response = await fetch(new URL("/v1/chat", input.deployUrl).href, {
1642
- method: "POST",
1643
- headers,
1644
- body: JSON.stringify({ message: input.message }),
1645
- });
1646
- } catch (error) {
1647
- throw new AgentKitError(
1648
- "deploy_smoke_failed",
1649
- `Deploy smoke request failed before a response: ${error instanceof Error ? error.message : String(error)}`,
1650
- );
1651
- }
1652
-
1653
- const payload = await response.json().catch(() => null);
1654
-
1655
- if (!response.ok) {
1656
- throw new AgentKitError("deploy_smoke_failed", readCloudError(payload, response.status));
1657
- }
1658
-
1659
- const content =
1660
- payload && typeof payload === "object" && "message" in payload && isRecord((payload as { message?: unknown }).message)
1661
- ? (payload as { message: { content?: unknown } }).message.content
1662
- : undefined;
1663
-
1664
- console.log("");
1665
- console.log("Deploy smoke verified");
1666
- console.log(`URL: ${input.deployUrl}`);
1667
- console.log(`Message: ${input.message}`);
1668
- if (typeof content === "string") {
1669
- console.log(`Response: ${content}`);
1670
- }
1671
- }
1672
-
1673
- async function fetchDeployConversationJson(cwd: string, path: string): Promise<unknown> {
1674
- const state = await requireLocalDeployState();
1675
- const deployUrl = requireDeployUrl(state);
1676
- const token = await readDeployAccessTokenForHostedRequest(cwd);
1677
- const headers = new Headers();
1678
-
1679
- headers.set("Authorization", `Bearer ${token}`);
1680
-
1681
- let response: Response;
1682
-
1683
- try {
1684
- response = await fetch(new URL(path, deployUrl).href, {
1685
- method: "GET",
1686
- headers,
1687
- });
1688
- } catch (error) {
1689
- throw new AgentKitError(
1690
- "deploy_conversation_request_failed",
1691
- `Could not read hosted conversation data: ${error instanceof Error ? error.message : String(error)}`,
1692
- );
1693
- }
1694
-
1695
- const payload = await response.json().catch(() => null);
1696
-
1697
- if (!response.ok) {
1698
- throw new AgentKitError("deploy_conversation_request_failed", readCloudError(payload, response.status));
1699
- }
1700
-
1701
- return payload;
1702
- }
1703
-
1704
- async function fetchDeployImproveEvidence(
1705
- apiUrl: string,
1706
- input: { deployId: string; since?: string; conversationId?: string },
1707
- ): Promise<unknown | null> {
1708
- try {
1709
- return await cloudApiRequest(apiUrl, `/v1/deploys/${encodeURIComponent(input.deployId)}/improve/export`, {
1710
- method: "POST",
1711
- body: JSON.stringify({
1712
- status: "all",
1713
- ...(input.since ? { since: input.since } : {}),
1714
- ...(input.conversationId ? { conversation_id: input.conversationId } : {}),
1715
- }),
1716
- });
1717
- } catch (error) {
1718
- if (
1719
- isAgentKitError(error) &&
1720
- (error.code === "improve_evidence_store_not_configured" || error.code === "not_found")
1721
- ) {
1722
- return null;
1723
- }
1724
-
1725
- throw error;
1726
- }
1727
- }
1728
-
1729
- function printJson(value: unknown): void {
1730
- console.log(JSON.stringify(value, null, 2));
1731
- }
1732
-
1733
741
  function printSkillStatus(status: Awaited<ReturnType<typeof checkDefaultSkillStatus>>): void {
1734
742
  console.log("AgentKit skills");
1735
743
  console.log(`Status: ${status.status}`);
@@ -1754,95 +762,11 @@ function printSkillStatus(status: Awaited<ReturnType<typeof checkDefaultSkillSta
1754
762
  }
1755
763
  }
1756
764
 
1757
- async function printJsonOrWrite(value: unknown, outFlag: string | boolean | undefined, usage: string): Promise<void> {
1758
- const outPath = parseOptionalStringFlag(outFlag, "out", usage);
1759
-
1760
- if (!outPath) {
1761
- printJson(value);
1762
- return;
1763
- }
1764
-
1765
- const absolutePath = resolve(process.cwd(), outPath);
1766
- await writeSecretJson(absolutePath, value);
1767
- console.log(`Deploy access token written to ${absolutePath}`);
1768
- }
1769
-
1770
- function parsePositiveIntegerFlag(value: string | boolean | undefined, name: string, usage: string): number {
1771
- if (typeof value !== "string") {
1772
- throw new Error(`Missing ${name}. Usage: ${usage}`);
1773
- }
1774
-
1775
- const parsed = Number(value);
1776
-
1777
- if (!Number.isInteger(parsed) || parsed <= 0) {
1778
- throw new Error(`Invalid ${name}. Usage: ${usage}`);
1779
- }
1780
-
1781
- return parsed;
1782
- }
1783
-
1784
765
  function relativePath(root: string, path: string): string {
1785
766
  const output = relative(root, path);
1786
767
  return output.startsWith("..") ? path : output || ".";
1787
768
  }
1788
769
 
1789
- function printBuildResult(result: Awaited<ReturnType<typeof buildAgentCapsule>>): void {
1790
- console.log("AgentKit build complete");
1791
- console.log("");
1792
- console.log(`Target: ${result.target}`);
1793
- console.log(`Build dir: ${result.buildDir}`);
1794
- console.log(`Manifest: ${result.manifestPath}`);
1795
-
1796
- if (result.target === "cloudflare") {
1797
- console.log(`Worker: ${result.workerPath}`);
1798
- console.log(`Wrangler: ${result.wranglerPath}`);
1799
- if (result.tursoSchemaPath) {
1800
- console.log(`Turso: ${result.tursoSchemaPath}`);
1801
- }
1802
- console.log(`Bundle: ${result.bundleSha256}`);
1803
- }
1804
-
1805
- if (result.target === "container") {
1806
- console.log(`Server: ${result.serverPath}`);
1807
- console.log(`Docker: ${result.dockerfilePath}`);
1808
- console.log(`Migrations:${result.migrationsDir}`);
1809
- }
1810
-
1811
- if (result.warnings.length > 0) {
1812
- console.log("");
1813
- console.log("Warnings:");
1814
-
1815
- for (const warning of result.warnings) {
1816
- console.log(` - ${warning}`);
1817
- }
1818
- }
1819
- }
1820
-
1821
- function printVpsDeployPlan(plan: Awaited<ReturnType<typeof prepareVpsDeploy>>): void {
1822
- console.log("");
1823
- console.log("VPS deploy plan ready");
1824
- console.log(`Host: ${plan.host}`);
1825
- console.log(`Compose: ${plan.composePath}`);
1826
- console.log(`Env: ${plan.envExamplePath}`);
1827
- console.log(`Secrets: ${plan.secretsPath}`);
1828
- console.log(`Handoff: ${plan.handoffPath}`);
1829
- console.log(`State: ${plan.statePath}`);
1830
- console.log("");
1831
- console.log("Commands:");
1832
-
1833
- for (const command of plan.commands) {
1834
- console.log(` ${command}`);
1835
- }
1836
- }
1837
-
1838
- async function deployCloudflare(wranglerPath: string, buildDir: string): Promise<void> {
1839
- const exitCode = await runInheritedCommand("npx", ["wrangler", "deploy", "--config", wranglerPath], buildDir);
1840
-
1841
- if (exitCode !== 0) {
1842
- throw new Error(`Cloudflare deploy failed with exit code ${exitCode}.`);
1843
- }
1844
- }
1845
-
1846
770
  async function installProjectDependencies(projectPath: string): Promise<void> {
1847
771
  const exitCode = await runInheritedCommand("npm", ["install"], projectPath);
1848
772