@andreprado/agentkit 0.1.0-alpha.17 → 0.1.0-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/docs/guides/add-channel.md +14 -8
- package/docs/guides/add-knowledge.md +10 -0
- package/docs/guides/add-managed-composio.md +43 -17
- package/docs/guides/channel-security.md +60 -39
- package/docs/guides/connect-discord.md +178 -0
- package/docs/guides/create-agent.md +13 -0
- package/docs/guides/debug-channel.md +147 -0
- package/docs/guides/improve-from-production.md +151 -0
- package/docs/guides/prepare-deploy.md +30 -14
- package/docs/guides/replay-production-traces.md +72 -0
- package/docs/guides/run-evals.md +18 -0
- package/docs/guides/security-rules.md +5 -5
- package/docs/guides/use-provider.md +11 -1
- package/docs/llms-full.txt +106 -15
- package/docs/llms.txt +22 -4
- package/package.json +1 -3
- package/src/cli/args.ts +23 -2
- package/src/cli/cloud-client.ts +75 -0
- package/src/cli/commands/channels.ts +139 -14
- package/src/cli/deploy-chat-ui.ts +146 -3
- package/src/cli/deploy-readiness.ts +57 -1
- package/src/cli/help.ts +32 -8
- package/src/cli/index.ts +447 -17
- package/src/create-project.ts +13 -2
- package/src/index.ts +46 -3
- package/src/providers/pi.ts +49 -15
- package/src/runtime/channel-test-harness.ts +4 -1
- package/src/runtime/channels/discord.ts +887 -0
- package/src/runtime/channels.ts +15 -0
- package/src/runtime/config.ts +39 -3
- package/src/runtime/core/manifest.ts +2 -0
- package/src/runtime/dev-server.ts +149 -8
- package/src/runtime/evals.ts +27 -6
- package/src/runtime/improve.ts +868 -0
- package/src/runtime/inspect.ts +1 -0
- package/src/runtime/integrations/composio.ts +168 -2
- package/src/runtime/knowledge/retrieve.ts +25 -5
- package/src/runtime/knowledge/schema.ts +45 -1
- package/src/runtime/runtime-contract.ts +54 -0
- package/src/runtime/targets/cloudflare/build.ts +479 -194
- package/src/runtime/targets/vps/deploy.ts +1 -1
- package/src/storage/sqlite.ts +7 -2
- package/src/templates/skills/agentkit-capsule/SKILL.md +8 -1
- package/src/templates/skills/agentkit-capsule/references/docs-router.md +1 -2
- package/src/templates/skills/agentkit-channels/SKILL.md +6 -1
- package/src/templates/skills/agentkit-channels/references/channel-debugging.md +2 -1
- package/src/templates/skills/agentkit-channels/references/discord.md +93 -0
- package/src/templates/skills/agentkit-deploy/SKILL.md +6 -0
- package/src/templates/skills/agentkit-evals/SKILL.md +12 -3
- package/src/templates/skills/agentkit-improve/SKILL.md +86 -0
- package/src/templates/skills/agentkit-improve/references/replay-side-effects.md +18 -0
- package/src/templates/skills/agentkit-improve/references/trace-packets.md +22 -0
- package/src/templates/skills/agentkit-improve/templates/regression.eval.md +18 -0
- package/src/templates/skills/agentkit-integrations/SKILL.md +12 -2
- package/src/templates/skills/agentkit-knowledge/SKILL.md +4 -1
- package/src/templates/skills/agentkit-provider/SKILL.md +4 -1
- package/src/templates/skills/agentkit-security/SKILL.md +3 -2
- package/src/templates/skills/agentkit-troubleshooting/SKILL.md +9 -0
- package/src/templates/support.ts +4 -2
- package/docs/guides/agentkit-skills-architecture.md +0 -472
- package/docs/guides/channels-implementation-map.md +0 -243
- package/docs/guides/channels-production-handoff.md +0 -118
- package/docs/portable-deploy-release-checklist.md +0 -41
package/src/cli/index.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
import { runEvalsFromCwd, writeEvalFromConversation } from "../runtime/evals";
|
|
22
22
|
import { findAgentKitDocs } from "../runtime/docs";
|
|
23
23
|
import { listCapsuleEnv, setCapsuleEnv, unsetCapsuleEnv } from "../runtime/env";
|
|
24
|
+
import { collectDeployImproveBundle, collectLocalImproveBundle, generateImproveEvals, replayImproveBundle } from "../runtime/improve";
|
|
24
25
|
import { checkAgentSpec, initializeAgentSpec } from "../runtime/spec";
|
|
25
26
|
import { checkDefaultSkillStatus, syncDefaultSkillFiles } from "../runtime/skills";
|
|
26
27
|
import { initializeSyncScaffold, runCapsuleSync } from "../runtime/sync";
|
|
@@ -44,6 +45,12 @@ import {
|
|
|
44
45
|
resolveCloudApiUrl,
|
|
45
46
|
verifyCloudLogin,
|
|
46
47
|
writeCloudAuth,
|
|
48
|
+
type AccountApiTokenCreateResponse,
|
|
49
|
+
type AccountApiTokenListResponse,
|
|
50
|
+
type BillingCheckoutIntentResponse,
|
|
51
|
+
type BillingCheckoutResponse,
|
|
52
|
+
type BillingClaimResponse,
|
|
53
|
+
type BillingPortalResponse,
|
|
47
54
|
type CloudMeResponse,
|
|
48
55
|
type DeployAccessTokenCreateResponse,
|
|
49
56
|
type DeployAccessTokenListResponse,
|
|
@@ -70,6 +77,8 @@ import { handleChannelsCommand } from "./commands/channels";
|
|
|
70
77
|
import { handleKnowledgeCommand } from "./commands/knowledge";
|
|
71
78
|
import { handleTranscribeCommand } from "./commands/transcribe";
|
|
72
79
|
|
|
80
|
+
const hostedDeployEntitlement = "agentkit_cloud_deploy";
|
|
81
|
+
|
|
73
82
|
async function main() {
|
|
74
83
|
const args = parseArgs(process.argv.slice(2));
|
|
75
84
|
|
|
@@ -336,10 +345,132 @@ async function main() {
|
|
|
336
345
|
return;
|
|
337
346
|
}
|
|
338
347
|
|
|
348
|
+
if (args.command === "improve") {
|
|
349
|
+
const [subcommand, bundlePath] = args.positional;
|
|
350
|
+
|
|
351
|
+
if (subcommand === "collect") {
|
|
352
|
+
const since = parseOptionalStringFlag(args.flags.since, "since", 'agentkit improve collect --since "24h"');
|
|
353
|
+
const conversationId = parseOptionalStringFlag(
|
|
354
|
+
args.flags["conversation-id"] ?? args.flags.conversation,
|
|
355
|
+
"conversation id",
|
|
356
|
+
"agentkit improve collect --conversation-id <id>",
|
|
357
|
+
);
|
|
358
|
+
const out = parseOptionalStringFlag(args.flags.out, "out", "agentkit improve collect --out <directory>");
|
|
359
|
+
const deployState = args.flags.deploy === true ? await requireLocalDeployState() : null;
|
|
360
|
+
const apiUrl = args.flags.deploy === true ? await resolveCloudApiUrl(args.flags.api) : null;
|
|
361
|
+
const cloudAuth = apiUrl ? await readCloudAuthForApiUrl(apiUrl) : null;
|
|
362
|
+
const result = args.flags.deploy === true
|
|
363
|
+
? await collectDeployImproveBundle(process.cwd(), {
|
|
364
|
+
deployId: deployState?.deploy_id ?? "",
|
|
365
|
+
since,
|
|
366
|
+
conversationId,
|
|
367
|
+
out,
|
|
368
|
+
collector: {
|
|
369
|
+
...(cloudAuth && apiUrl && deployState
|
|
370
|
+
? {
|
|
371
|
+
exportEvidence: (input: { deployId: string; since?: string; conversationId?: string }) =>
|
|
372
|
+
fetchDeployImproveEvidence(apiUrl, input),
|
|
373
|
+
}
|
|
374
|
+
: {}),
|
|
375
|
+
listConversations: () => fetchDeployConversationJson(process.cwd(), "/v1/conversations"),
|
|
376
|
+
getTrace: (id: string) =>
|
|
377
|
+
fetchDeployConversationJson(process.cwd(), `/v1/conversations/${encodeURIComponent(id)}/trace`),
|
|
378
|
+
},
|
|
379
|
+
})
|
|
380
|
+
: await collectLocalImproveBundle(process.cwd(), {
|
|
381
|
+
since,
|
|
382
|
+
conversationId,
|
|
383
|
+
out,
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
console.log("Improve bundle collected");
|
|
387
|
+
console.log(`Source: ${result.source}`);
|
|
388
|
+
console.log(`Directory: ${relativePath(result.root, result.directory)}`);
|
|
389
|
+
console.log(`Bundle: ${relativePath(result.root, result.bundlePath)}`);
|
|
390
|
+
console.log(`Report: ${relativePath(result.root, result.reportPath)}`);
|
|
391
|
+
console.log(`Traces: ${result.traceCount}`);
|
|
392
|
+
console.log("");
|
|
393
|
+
console.log(`Next: agentkit improve evals ${relativePath(result.root, result.directory)}`);
|
|
394
|
+
console.log(`Replay: agentkit replay ${relativePath(result.root, result.directory)} --against local`);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (subcommand === "evals") {
|
|
399
|
+
if (!bundlePath) {
|
|
400
|
+
throw new Error("Missing bundle path. Usage: agentkit improve evals <bundle-dir-or-json> [--force]");
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const result = await generateImproveEvals(process.cwd(), {
|
|
404
|
+
bundle: bundlePath,
|
|
405
|
+
force: args.flags.force === true,
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
console.log("Improve evals generated");
|
|
409
|
+
console.log(`Bundle: ${relativePath(result.root, result.bundlePath)}`);
|
|
410
|
+
console.log(`Files: ${result.files.length}`);
|
|
411
|
+
for (const file of result.files) {
|
|
412
|
+
console.log(` ${relativePath(result.root, file)}`);
|
|
413
|
+
}
|
|
414
|
+
if (result.skipped.length > 0) {
|
|
415
|
+
console.log(`Skipped: ${result.skipped.length}`);
|
|
416
|
+
for (const skipped of result.skipped) {
|
|
417
|
+
console.log(` ${skipped.trace_id}: ${skipped.reason}`);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
throw new Error("Usage: agentkit improve collect [--deploy] [--since <duration|iso>] [--conversation-id <id>] [--out <directory>] | agentkit improve evals <bundle-dir-or-json> [--force]");
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
if (args.command === "replay") {
|
|
427
|
+
const [bundlePath] = args.positional;
|
|
428
|
+
|
|
429
|
+
if (!bundlePath) {
|
|
430
|
+
throw new Error("Missing bundle path. Usage: agentkit replay <bundle-dir-or-json> --against local");
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const against = parseOptionalStringFlag(args.flags.against, "against", "agentkit replay <bundle> --against local") ?? "local";
|
|
434
|
+
|
|
435
|
+
if (against !== "local") {
|
|
436
|
+
throw new Error("Usage: agentkit replay <bundle-dir-or-json> --against local");
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const result = await replayImproveBundle(process.cwd(), {
|
|
440
|
+
bundle: bundlePath,
|
|
441
|
+
against,
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
for (const item of result.results) {
|
|
445
|
+
console.log(`${item.status.toUpperCase()} ${item.conversation_id} (${item.turns} turns)`);
|
|
446
|
+
if (item.error) {
|
|
447
|
+
console.log(` - ${item.error}`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
console.log("");
|
|
452
|
+
console.log(`Replay passed: ${result.passed}`);
|
|
453
|
+
console.log(`Replay failed: ${result.failed}`);
|
|
454
|
+
console.log(`Replay skipped: ${result.skipped}`);
|
|
455
|
+
|
|
456
|
+
if (result.failed > 0) {
|
|
457
|
+
process.exitCode = 1;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
|
|
339
463
|
if (args.command === "conversations") {
|
|
340
464
|
const [subcommand, conversationId] = args.positional;
|
|
465
|
+
const fromDeploy = args.flags.deploy === true;
|
|
341
466
|
|
|
342
467
|
if (subcommand === "list") {
|
|
468
|
+
if (fromDeploy) {
|
|
469
|
+
const payload = await fetchDeployConversationJson(process.cwd(), "/v1/conversations");
|
|
470
|
+
printJson(payload);
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
|
|
343
474
|
const conversations = await listConversationsFromCwd(process.cwd());
|
|
344
475
|
|
|
345
476
|
if (conversations.length === 0) {
|
|
@@ -365,7 +496,16 @@ async function main() {
|
|
|
365
496
|
|
|
366
497
|
if (subcommand === "show") {
|
|
367
498
|
if (!conversationId) {
|
|
368
|
-
throw new Error("Missing conversation id. Usage: agentkit conversations show <conversation-id>");
|
|
499
|
+
throw new Error("Missing conversation id. Usage: agentkit conversations show <conversation-id> [--deploy]");
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
if (fromDeploy) {
|
|
503
|
+
const payload = await fetchDeployConversationJson(
|
|
504
|
+
process.cwd(),
|
|
505
|
+
`/v1/conversations/${encodeURIComponent(conversationId)}`,
|
|
506
|
+
);
|
|
507
|
+
printJson(payload);
|
|
508
|
+
return;
|
|
369
509
|
}
|
|
370
510
|
|
|
371
511
|
const conversation = await getConversationFromCwd(process.cwd(), conversationId);
|
|
@@ -384,7 +524,16 @@ async function main() {
|
|
|
384
524
|
|
|
385
525
|
if (subcommand === "trace") {
|
|
386
526
|
if (!conversationId) {
|
|
387
|
-
throw new Error("Missing conversation id. Usage: agentkit conversations trace <conversation-id>");
|
|
527
|
+
throw new Error("Missing conversation id. Usage: agentkit conversations trace <conversation-id> [--deploy]");
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (fromDeploy) {
|
|
531
|
+
const trace = await fetchDeployConversationJson(
|
|
532
|
+
process.cwd(),
|
|
533
|
+
`/v1/conversations/${encodeURIComponent(conversationId)}/trace`,
|
|
534
|
+
);
|
|
535
|
+
printJson(trace);
|
|
536
|
+
return;
|
|
388
537
|
}
|
|
389
538
|
|
|
390
539
|
const trace = await getConversationTraceFromCwd(process.cwd(), conversationId);
|
|
@@ -392,7 +541,7 @@ async function main() {
|
|
|
392
541
|
return;
|
|
393
542
|
}
|
|
394
543
|
|
|
395
|
-
throw new Error("Usage: agentkit conversations list | agentkit conversations show <conversation-id> | agentkit conversations trace <conversation-id>");
|
|
544
|
+
throw new Error("Usage: agentkit conversations list [--deploy] | agentkit conversations show <conversation-id> [--deploy] | agentkit conversations trace <conversation-id> [--deploy]");
|
|
396
545
|
}
|
|
397
546
|
|
|
398
547
|
if (args.command === "knowledge") {
|
|
@@ -492,13 +641,15 @@ async function main() {
|
|
|
492
641
|
const email = verified.me.account?.email;
|
|
493
642
|
console.log(email ? `Logged in to AgentKit Cloud as ${email}.` : "AgentKit Cloud token verified and stored.");
|
|
494
643
|
|
|
495
|
-
const
|
|
496
|
-
(capability) =>
|
|
644
|
+
const hasHostedDeploy = (verified.capabilities.capabilities ?? []).some(
|
|
645
|
+
(capability) =>
|
|
646
|
+
(capability.name === "cloudflare_deploy_alpha" || capability.name === hostedDeployEntitlement) &&
|
|
647
|
+
capability.status === "active",
|
|
497
648
|
);
|
|
498
649
|
console.log(
|
|
499
|
-
|
|
500
|
-
? "Entitlement:
|
|
501
|
-
:
|
|
650
|
+
hasHostedDeploy
|
|
651
|
+
? "Entitlement: hosted deploy active."
|
|
652
|
+
: `Warning: cloudflare_deploy_alpha or ${hostedDeployEntitlement} entitlement was not found for this account.`,
|
|
502
653
|
);
|
|
503
654
|
|
|
504
655
|
if (process.env.AGENTKIT_CLOUD_API_TOKEN && process.env.AGENTKIT_CLOUD_API_TOKEN !== token) {
|
|
@@ -514,6 +665,208 @@ async function main() {
|
|
|
514
665
|
return;
|
|
515
666
|
}
|
|
516
667
|
|
|
668
|
+
if (args.command === "account") {
|
|
669
|
+
const [noun, verb, value] = args.positional;
|
|
670
|
+
|
|
671
|
+
if (noun !== "token") {
|
|
672
|
+
throw new Error("Usage: agentkit account token create <name> [--use] [--out <path>] | list | revoke <token-id> [--api <url>]");
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
const apiUrl = await resolveCloudApiUrl(args.flags.api);
|
|
676
|
+
|
|
677
|
+
if (verb === "create" && value) {
|
|
678
|
+
const payload = (await cloudApiRequest(apiUrl, "/v1/account/tokens", {
|
|
679
|
+
method: "POST",
|
|
680
|
+
body: JSON.stringify({ name: value }),
|
|
681
|
+
})) as AccountApiTokenCreateResponse;
|
|
682
|
+
const token = payload.token;
|
|
683
|
+
|
|
684
|
+
if (!token?.token || !token.id) {
|
|
685
|
+
throw new AgentKitError("account_token_invalid", "AgentKit Cloud returned an invalid account token payload.");
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
const outPath = parseOptionalStringFlag(
|
|
689
|
+
args.flags.out,
|
|
690
|
+
"out",
|
|
691
|
+
"agentkit account token create <name> [--api <url>] [--use] [--out <path>]",
|
|
692
|
+
);
|
|
693
|
+
|
|
694
|
+
if (outPath) {
|
|
695
|
+
const absolutePath = resolve(process.cwd(), outPath);
|
|
696
|
+
await writeSecretJson(absolutePath, payload);
|
|
697
|
+
console.log(`Account token written to ${absolutePath}`);
|
|
698
|
+
} else {
|
|
699
|
+
printJson(payload);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
if (args.flags.use === true) {
|
|
703
|
+
await writeCloudAuth({ apiUrl, token: token.token });
|
|
704
|
+
console.log(`Saved ${token.id} as the current AgentKit Cloud login.`);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
if (verb === "list" && !value) {
|
|
711
|
+
const payload = (await cloudApiRequest(apiUrl, "/v1/account/tokens", {
|
|
712
|
+
method: "GET",
|
|
713
|
+
})) as AccountApiTokenListResponse;
|
|
714
|
+
printJson(payload);
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
if (verb === "revoke" && value) {
|
|
719
|
+
const payload = await cloudApiRequest(apiUrl, `/v1/account/tokens/${encodeURIComponent(value)}/revoke`, {
|
|
720
|
+
method: "POST",
|
|
721
|
+
});
|
|
722
|
+
printJson(payload);
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
throw new Error("Usage: agentkit account token create <name> [--use] [--out <path>] | list | revoke <token-id> [--api <url>]");
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
if (args.command === "billing") {
|
|
730
|
+
const [subcommand, intentId] = args.positional;
|
|
731
|
+
const apiUrl = await resolveCloudApiUrl(args.flags.api);
|
|
732
|
+
|
|
733
|
+
if (subcommand === "checkout") {
|
|
734
|
+
const slots = parsePositiveIntegerFlag(
|
|
735
|
+
args.flags.slots,
|
|
736
|
+
"slots",
|
|
737
|
+
"agentkit billing checkout --slots <count> [--email <email>] [--api <url>]",
|
|
738
|
+
);
|
|
739
|
+
const email = parseOptionalStringFlag(
|
|
740
|
+
args.flags.email,
|
|
741
|
+
"email",
|
|
742
|
+
"agentkit billing checkout --slots <count> --email <email>",
|
|
743
|
+
);
|
|
744
|
+
const payload = (await cloudApiRequest(apiUrl, "/v1/billing/checkout", {
|
|
745
|
+
method: "POST",
|
|
746
|
+
body: JSON.stringify({
|
|
747
|
+
slots,
|
|
748
|
+
...(email ? { email } : {}),
|
|
749
|
+
}),
|
|
750
|
+
})) as BillingCheckoutResponse;
|
|
751
|
+
const checkoutUrl = payload.checkout?.url;
|
|
752
|
+
const billingIntentId = payload.billing_intent?.id;
|
|
753
|
+
const secret = payload.billing_intent?.secret;
|
|
754
|
+
|
|
755
|
+
if (!checkoutUrl || !billingIntentId || !secret) {
|
|
756
|
+
throw new AgentKitError("billing_checkout_invalid", "AgentKit Cloud returned an invalid billing checkout payload.");
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
if (args.flags.json === true) {
|
|
760
|
+
printJson(payload);
|
|
761
|
+
} else {
|
|
762
|
+
console.log("AgentKit Cloud checkout");
|
|
763
|
+
console.log("");
|
|
764
|
+
console.log(`URL: ${checkoutUrl}`);
|
|
765
|
+
console.log(`Intent: ${billingIntentId}`);
|
|
766
|
+
console.log(`Secret: ${secret}`);
|
|
767
|
+
console.log("");
|
|
768
|
+
console.log(`After payment: agentkit billing claim ${billingIntentId} --secret ${secret} --api ${apiUrl}`);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
if (args.flags.open === true) {
|
|
772
|
+
await openLocalUrl(checkoutUrl);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
if (subcommand === "status" && intentId) {
|
|
779
|
+
const secret = parseRequiredStringFlag(
|
|
780
|
+
args.flags.secret,
|
|
781
|
+
"secret",
|
|
782
|
+
"agentkit billing status <billing-intent-id> --secret <secret> [--api <url>]",
|
|
783
|
+
);
|
|
784
|
+
const payload = (await cloudApiRequest(
|
|
785
|
+
apiUrl,
|
|
786
|
+
`/v1/billing/checkout-intents/${encodeURIComponent(intentId)}?secret=${encodeURIComponent(secret)}`,
|
|
787
|
+
{ method: "GET" },
|
|
788
|
+
)) as BillingCheckoutIntentResponse;
|
|
789
|
+
printJson(payload);
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
if (subcommand === "claim" && intentId) {
|
|
794
|
+
const secret = parseRequiredStringFlag(
|
|
795
|
+
args.flags.secret,
|
|
796
|
+
"secret",
|
|
797
|
+
"agentkit billing claim <billing-intent-id> --secret <secret> [--token-name <name>] [--api <url>]",
|
|
798
|
+
);
|
|
799
|
+
const tokenName = parseOptionalStringFlag(
|
|
800
|
+
args.flags["token-name"],
|
|
801
|
+
"token-name",
|
|
802
|
+
"agentkit billing claim <billing-intent-id> --secret <secret> --token-name <name>",
|
|
803
|
+
);
|
|
804
|
+
const payload = (await cloudApiRequest(apiUrl, `/v1/billing/checkout-intents/${encodeURIComponent(intentId)}/claim`, {
|
|
805
|
+
method: "POST",
|
|
806
|
+
body: JSON.stringify({
|
|
807
|
+
secret,
|
|
808
|
+
...(tokenName ? { token_name: tokenName } : {}),
|
|
809
|
+
}),
|
|
810
|
+
})) as BillingClaimResponse;
|
|
811
|
+
const token = payload.token;
|
|
812
|
+
|
|
813
|
+
if (!token?.token || !token.id) {
|
|
814
|
+
throw new AgentKitError("billing_claim_invalid", "AgentKit Cloud returned an invalid billing claim payload.");
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
await writeCloudAuth({ apiUrl, token: token.token });
|
|
818
|
+
|
|
819
|
+
const outPath = parseOptionalStringFlag(
|
|
820
|
+
args.flags.out,
|
|
821
|
+
"out",
|
|
822
|
+
"agentkit billing claim <billing-intent-id> --secret <secret> [--out <path>]",
|
|
823
|
+
);
|
|
824
|
+
|
|
825
|
+
if (outPath) {
|
|
826
|
+
const absolutePath = resolve(process.cwd(), outPath);
|
|
827
|
+
await writeSecretJson(absolutePath, payload);
|
|
828
|
+
console.log(`Account token written to ${absolutePath}`);
|
|
829
|
+
} else if (args.flags.json === true) {
|
|
830
|
+
printJson(payload);
|
|
831
|
+
} else {
|
|
832
|
+
console.log("AgentKit Cloud account token claimed and saved.");
|
|
833
|
+
console.log(`Token: ${token.id}`);
|
|
834
|
+
console.log(`API: ${apiUrl}`);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if (subcommand === "portal") {
|
|
841
|
+
const payload = (await cloudApiRequest(apiUrl, "/v1/billing/portal", {
|
|
842
|
+
method: "POST",
|
|
843
|
+
body: JSON.stringify({}),
|
|
844
|
+
})) as BillingPortalResponse;
|
|
845
|
+
const portalUrl = payload.portal?.url;
|
|
846
|
+
|
|
847
|
+
if (!portalUrl) {
|
|
848
|
+
throw new AgentKitError("billing_portal_invalid", "AgentKit Cloud returned an invalid billing portal payload.");
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
if (args.flags.json === true) {
|
|
852
|
+
printJson(payload);
|
|
853
|
+
} else {
|
|
854
|
+
console.log("AgentKit Cloud billing portal");
|
|
855
|
+
console.log(`URL: ${portalUrl}`);
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
if (args.flags.open === true) {
|
|
859
|
+
await openLocalUrl(portalUrl);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
throw new Error(
|
|
866
|
+
"Usage: agentkit billing checkout --slots <count> [--email <email>] | status <intent-id> --secret <secret> | claim <intent-id> --secret <secret> | portal [--api <url>]",
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
|
|
517
870
|
if (args.command === "deploy") {
|
|
518
871
|
const [deploySubcommand] = args.positional;
|
|
519
872
|
|
|
@@ -522,7 +875,7 @@ async function main() {
|
|
|
522
875
|
parseOptionalStringFlag(args.flags.message ?? args.flags.smoke, "message", 'agentkit deploy smoke --message "hello"') ??
|
|
523
876
|
"hello";
|
|
524
877
|
const state = await requireLocalDeployState();
|
|
525
|
-
const token = await
|
|
878
|
+
const token = await readDeployAccessTokenForHostedRequest(process.cwd());
|
|
526
879
|
await runDeploySmoke({
|
|
527
880
|
deployUrl: requireDeployUrl(state),
|
|
528
881
|
message,
|
|
@@ -621,7 +974,7 @@ async function main() {
|
|
|
621
974
|
apiUrl,
|
|
622
975
|
root: result.root,
|
|
623
976
|
deployId: deploy.deploy.id,
|
|
624
|
-
skip: anonymous || !auth?.token
|
|
977
|
+
skip: anonymous || !auth?.token,
|
|
625
978
|
});
|
|
626
979
|
|
|
627
980
|
console.log("");
|
|
@@ -634,7 +987,7 @@ async function main() {
|
|
|
634
987
|
if (chatAccess?.status === "ready") {
|
|
635
988
|
console.log(`Chat auth: ${relativePath(process.cwd(), chatAccess.path)}`);
|
|
636
989
|
} else if (chatAccess?.status === "skipped") {
|
|
637
|
-
console.log("Chat auth:
|
|
990
|
+
console.log("Chat auth: anonymous deploy; no local chat token was created.");
|
|
638
991
|
} else if (chatAccess?.status === "failed") {
|
|
639
992
|
console.log(`Chat auth: could not create local chat token. ${formatReadinessError(chatAccess.error)}`);
|
|
640
993
|
console.log(`Run: agentkit access token create ${defaultDeployChatAccessTokenName} --out ${defaultDeployChatAccessTokenPath}`);
|
|
@@ -805,9 +1158,16 @@ async function main() {
|
|
|
805
1158
|
const apiUrl = await resolveCloudApiUrl(args.flags.api);
|
|
806
1159
|
|
|
807
1160
|
if (subcommand === "status") {
|
|
1161
|
+
const toolkit = parseOptionalStringFlag(
|
|
1162
|
+
args.flags.toolkit,
|
|
1163
|
+
"toolkit",
|
|
1164
|
+
"agentkit integrations status --toolkit <slug>",
|
|
1165
|
+
);
|
|
808
1166
|
const payload = await cloudApiRequest(
|
|
809
1167
|
apiUrl,
|
|
810
|
-
`/v1/deploys/${encodeURIComponent(state.deploy_id)}/integrations/composio/status
|
|
1168
|
+
`/v1/deploys/${encodeURIComponent(state.deploy_id)}/integrations/composio/status${
|
|
1169
|
+
toolkit ? `?toolkit=${encodeURIComponent(toolkit)}` : ""
|
|
1170
|
+
}`,
|
|
811
1171
|
{ method: "GET" },
|
|
812
1172
|
);
|
|
813
1173
|
printJson(payload);
|
|
@@ -842,6 +1202,7 @@ async function main() {
|
|
|
842
1202
|
redirect_url?: string;
|
|
843
1203
|
expires_at?: string;
|
|
844
1204
|
connected_account_id?: string;
|
|
1205
|
+
auth_config_source?: string;
|
|
845
1206
|
};
|
|
846
1207
|
};
|
|
847
1208
|
|
|
@@ -854,6 +1215,9 @@ async function main() {
|
|
|
854
1215
|
console.log("Composio connect link");
|
|
855
1216
|
console.log(`Toolkit: ${link.toolkit ?? toolkit ?? "unknown"}`);
|
|
856
1217
|
console.log(`User: ${link.user_id ?? "unknown"}`);
|
|
1218
|
+
if (link.auth_config_source) {
|
|
1219
|
+
console.log(`Auth: ${link.auth_config_source}`);
|
|
1220
|
+
}
|
|
857
1221
|
console.log(`URL: ${link.redirect_url}`);
|
|
858
1222
|
|
|
859
1223
|
if (link.expires_at) {
|
|
@@ -1129,11 +1493,7 @@ function requireDeployUrl(state: Pick<LocalDeployState, "deploy_id" | "url">): s
|
|
|
1129
1493
|
return state.url;
|
|
1130
1494
|
}
|
|
1131
1495
|
|
|
1132
|
-
async function
|
|
1133
|
-
if (state.access?.mode === "public") {
|
|
1134
|
-
return undefined;
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1496
|
+
async function readDeployAccessTokenForHostedRequest(cwd: string): Promise<string> {
|
|
1137
1497
|
const root = await findAgentCapsuleRoot(cwd);
|
|
1138
1498
|
return readDeployAccessTokenForUi(join(root, defaultDeployChatAccessTokenPath));
|
|
1139
1499
|
}
|
|
@@ -1180,6 +1540,62 @@ async function runDeploySmoke(input: { deployUrl: string; message: string; token
|
|
|
1180
1540
|
}
|
|
1181
1541
|
}
|
|
1182
1542
|
|
|
1543
|
+
async function fetchDeployConversationJson(cwd: string, path: string): Promise<unknown> {
|
|
1544
|
+
const state = await requireLocalDeployState();
|
|
1545
|
+
const deployUrl = requireDeployUrl(state);
|
|
1546
|
+
const token = await readDeployAccessTokenForHostedRequest(cwd);
|
|
1547
|
+
const headers = new Headers();
|
|
1548
|
+
|
|
1549
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
1550
|
+
|
|
1551
|
+
let response: Response;
|
|
1552
|
+
|
|
1553
|
+
try {
|
|
1554
|
+
response = await fetch(new URL(path, deployUrl).href, {
|
|
1555
|
+
method: "GET",
|
|
1556
|
+
headers,
|
|
1557
|
+
});
|
|
1558
|
+
} catch (error) {
|
|
1559
|
+
throw new AgentKitError(
|
|
1560
|
+
"deploy_conversation_request_failed",
|
|
1561
|
+
`Could not read hosted conversation data: ${error instanceof Error ? error.message : String(error)}`,
|
|
1562
|
+
);
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
const payload = await response.json().catch(() => null);
|
|
1566
|
+
|
|
1567
|
+
if (!response.ok) {
|
|
1568
|
+
throw new AgentKitError("deploy_conversation_request_failed", readCloudError(payload, response.status));
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
return payload;
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
async function fetchDeployImproveEvidence(
|
|
1575
|
+
apiUrl: string,
|
|
1576
|
+
input: { deployId: string; since?: string; conversationId?: string },
|
|
1577
|
+
): Promise<unknown | null> {
|
|
1578
|
+
try {
|
|
1579
|
+
return await cloudApiRequest(apiUrl, `/v1/deploys/${encodeURIComponent(input.deployId)}/improve/export`, {
|
|
1580
|
+
method: "POST",
|
|
1581
|
+
body: JSON.stringify({
|
|
1582
|
+
status: "all",
|
|
1583
|
+
...(input.since ? { since: input.since } : {}),
|
|
1584
|
+
...(input.conversationId ? { conversation_id: input.conversationId } : {}),
|
|
1585
|
+
}),
|
|
1586
|
+
});
|
|
1587
|
+
} catch (error) {
|
|
1588
|
+
if (
|
|
1589
|
+
isAgentKitError(error) &&
|
|
1590
|
+
(error.code === "improve_evidence_store_not_configured" || error.code === "not_found")
|
|
1591
|
+
) {
|
|
1592
|
+
return null;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
throw error;
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1183
1599
|
function printJson(value: unknown): void {
|
|
1184
1600
|
console.log(JSON.stringify(value, null, 2));
|
|
1185
1601
|
}
|
|
@@ -1221,6 +1637,20 @@ async function printJsonOrWrite(value: unknown, outFlag: string | boolean | unde
|
|
|
1221
1637
|
console.log(`Deploy access token written to ${absolutePath}`);
|
|
1222
1638
|
}
|
|
1223
1639
|
|
|
1640
|
+
function parsePositiveIntegerFlag(value: string | boolean | undefined, name: string, usage: string): number {
|
|
1641
|
+
if (typeof value !== "string") {
|
|
1642
|
+
throw new Error(`Missing ${name}. Usage: ${usage}`);
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
const parsed = Number(value);
|
|
1646
|
+
|
|
1647
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
1648
|
+
throw new Error(`Invalid ${name}. Usage: ${usage}`);
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
return parsed;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1224
1654
|
function relativePath(root: string, path: string): string {
|
|
1225
1655
|
const output = relative(root, path);
|
|
1226
1656
|
return output.startsWith("..") ? path : output || ".";
|
package/src/create-project.ts
CHANGED
|
@@ -42,8 +42,7 @@ export async function createProject(options: CreateProjectOptions): Promise<Crea
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
for (const file of files) {
|
|
45
|
-
const absolutePath =
|
|
46
|
-
const directory = absolutePath.slice(0, absolutePath.lastIndexOf("/"));
|
|
45
|
+
const { absolutePath, directory } = resolveProjectFilePath(projectPath, file.path);
|
|
47
46
|
|
|
48
47
|
await mkdir(directory, { recursive: true });
|
|
49
48
|
await writeFile(absolutePath, file.contents);
|
|
@@ -58,6 +57,18 @@ export async function createProject(options: CreateProjectOptions): Promise<Crea
|
|
|
58
57
|
};
|
|
59
58
|
}
|
|
60
59
|
|
|
60
|
+
export function resolveProjectFilePath(
|
|
61
|
+
projectPath: string,
|
|
62
|
+
filePath: string,
|
|
63
|
+
pathApi: Pick<typeof import("node:path"), "dirname" | "join"> = { dirname, join },
|
|
64
|
+
): { absolutePath: string; directory: string } {
|
|
65
|
+
const absolutePath = pathApi.join(projectPath, filePath);
|
|
66
|
+
return {
|
|
67
|
+
absolutePath,
|
|
68
|
+
directory: pathApi.dirname(absolutePath),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
61
72
|
function resolveProjectTarget(options: CreateProjectOptions): { name: string; path: string; currentDirectory: boolean } {
|
|
62
73
|
if (options.name === ".") {
|
|
63
74
|
const path = resolve(options.cwd);
|