@andreprado/agentkit 0.1.0-alpha.16 → 0.1.0-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/docs/guides/add-channel.md +4 -2
- package/docs/guides/add-managed-composio.md +161 -0
- package/docs/guides/channel-security.md +36 -39
- package/docs/guides/connect-telegram.md +3 -1
- package/docs/guides/debug-channel.md +141 -0
- package/docs/guides/prepare-deploy.md +7 -10
- package/docs/llms-full.txt +19 -5
- package/docs/llms.txt +11 -2
- package/package.json +1 -3
- package/src/cli/cloud-client.ts +12 -0
- package/src/cli/commands/channels.ts +119 -7
- package/src/cli/commands/transcribe.ts +171 -0
- package/src/cli/deploy-chat-ui.ts +146 -3
- package/src/cli/deploy-readiness.ts +112 -3
- package/src/cli/help.ts +19 -4
- package/src/cli/index.ts +198 -3
- package/src/create-project.ts +4 -32
- package/src/index.ts +149 -0
- package/src/runtime/chat.ts +2 -1
- package/src/runtime/config.ts +133 -0
- package/src/runtime/core/manifest.ts +31 -2
- package/src/runtime/deploy-readiness.ts +31 -1
- package/src/runtime/inspect.ts +109 -4
- package/src/runtime/integrations/composio.ts +423 -0
- package/src/runtime/skills.ts +95 -0
- package/src/runtime/targets/cloudflare/build.ts +395 -10
- package/src/runtime/tool-runner.ts +2 -1
- package/src/templates/skills/agentkit-capsule/SKILL.md +1 -0
- package/src/templates/skills/agentkit-channels/SKILL.md +2 -0
- package/src/templates/skills/agentkit-channels/references/channel-debugging.md +3 -1
- package/src/templates/skills/agentkit-channels/references/telegram.md +3 -1
- package/src/templates/skills/agentkit-deploy/SKILL.md +1 -1
- package/src/templates/skills/agentkit-integrations/SKILL.md +75 -0
- package/src/templates/skills/agentkit-troubleshooting/SKILL.md +3 -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
|
@@ -2,12 +2,14 @@ import { findAgentCapsuleRoot, loadAgentCapsule } from "../runtime/config";
|
|
|
2
2
|
import { loadDeployReadinessContext, type DeployReadinessContext } from "../runtime/deploy-readiness";
|
|
3
3
|
import { loadCapsuleEnv } from "../runtime/env";
|
|
4
4
|
import { isAgentKitError } from "../runtime/errors";
|
|
5
|
+
import { MANAGED_COMPOSIO_API_KEY_SECRET, MANAGED_COMPOSIO_ENTITLEMENT } from "../runtime/integrations/composio";
|
|
5
6
|
import {
|
|
6
7
|
cloudApiRequest,
|
|
7
8
|
formatCloudAuthSource,
|
|
8
9
|
readCloudAuthForApiUrl,
|
|
9
10
|
type CloudCapabilitiesResponse,
|
|
10
11
|
type CloudLimitsResponse,
|
|
12
|
+
type CloudManagedComposioResponse,
|
|
11
13
|
type CloudMeResponse,
|
|
12
14
|
type CloudProjectResolveResponse,
|
|
13
15
|
type CloudSecretsResponse,
|
|
@@ -53,6 +55,22 @@ export async function checkDeployReadiness(options: {
|
|
|
53
55
|
});
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
const nodeMajor = majorNodeVersion(process.versions.node);
|
|
59
|
+
if (nodeMajor !== null && nodeMajor < 24) {
|
|
60
|
+
checks.push({
|
|
61
|
+
status: "warn",
|
|
62
|
+
title: "Node version",
|
|
63
|
+
message: `@andreprado/agentkit requires Node >=24; current Node is ${process.versions.node}.`,
|
|
64
|
+
action: "use Node 24+ before running direct node imports or production container commands",
|
|
65
|
+
});
|
|
66
|
+
} else {
|
|
67
|
+
checks.push({
|
|
68
|
+
status: "pass",
|
|
69
|
+
title: "Node version",
|
|
70
|
+
message: `Node ${process.versions.node} satisfies @andreprado/agentkit engines.node >=24.`,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
56
74
|
if (!auth?.token) {
|
|
57
75
|
checks.push({
|
|
58
76
|
status: options.requireLogin ? "fail" : "warn",
|
|
@@ -104,6 +122,9 @@ export async function checkDeployReadiness(options: {
|
|
|
104
122
|
const hasCloudflareAlpha = capabilities.some(
|
|
105
123
|
(capability) => capability.name === "cloudflare_deploy_alpha" && capability.status === "active",
|
|
106
124
|
);
|
|
125
|
+
const hasManagedComposio = capabilities.some(
|
|
126
|
+
(capability) => capability.name === MANAGED_COMPOSIO_ENTITLEMENT && capability.status === "active",
|
|
127
|
+
);
|
|
107
128
|
|
|
108
129
|
checks.push({
|
|
109
130
|
status: hasCloudflareAlpha ? "pass" : "fail",
|
|
@@ -113,6 +134,17 @@ export async function checkDeployReadiness(options: {
|
|
|
113
134
|
: "This account is missing the cloudflare_deploy_alpha entitlement.",
|
|
114
135
|
...(hasCloudflareAlpha ? {} : { action: "log in with an invited AgentKit Cloud alpha token" }),
|
|
115
136
|
});
|
|
137
|
+
|
|
138
|
+
if (context.integrations.managedComposio.enabled) {
|
|
139
|
+
checks.push({
|
|
140
|
+
status: hasManagedComposio ? "pass" : "fail",
|
|
141
|
+
title: "Managed Composio entitlement",
|
|
142
|
+
message: hasManagedComposio
|
|
143
|
+
? `${MANAGED_COMPOSIO_ENTITLEMENT} is active.`
|
|
144
|
+
: `This capsule uses AgentKit-managed Composio, but this account is missing ${MANAGED_COMPOSIO_ENTITLEMENT}.`,
|
|
145
|
+
...(hasManagedComposio ? {} : { action: "upgrade the AgentKit Cloud account or ask an operator to grant managed_composio" }),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
116
148
|
} catch (error) {
|
|
117
149
|
checks.push({
|
|
118
150
|
status: "fail",
|
|
@@ -172,6 +204,58 @@ export async function checkDeployReadiness(options: {
|
|
|
172
204
|
message: `Could not verify online deploy capacity. ${formatReadinessError(error)}`,
|
|
173
205
|
});
|
|
174
206
|
}
|
|
207
|
+
|
|
208
|
+
if (context.integrations.managedComposio.enabled) {
|
|
209
|
+
try {
|
|
210
|
+
const payload = (await cloudApiRequest(
|
|
211
|
+
options.apiUrl,
|
|
212
|
+
`/v1/me/managed-composio?toolkits=${encodeURIComponent(context.integrations.managedComposio.toolkits.join(","))}`,
|
|
213
|
+
{
|
|
214
|
+
method: "GET",
|
|
215
|
+
},
|
|
216
|
+
)) as CloudManagedComposioResponse;
|
|
217
|
+
const managed = payload.managed_composio;
|
|
218
|
+
const missingToolkits = (managed?.toolkits ?? []).filter((toolkit) => toolkit.auth_config !== "set");
|
|
219
|
+
|
|
220
|
+
if (managed?.api_key !== "set") {
|
|
221
|
+
checks.push({
|
|
222
|
+
status: "fail",
|
|
223
|
+
title: "Managed Composio API key",
|
|
224
|
+
message: `AgentKit Cloud is missing AGENTKIT_SECRET_${MANAGED_COMPOSIO_API_KEY_SECRET}.`,
|
|
225
|
+
action: "ask the AgentKit Cloud operator to configure managed Composio",
|
|
226
|
+
});
|
|
227
|
+
} else {
|
|
228
|
+
checks.push({
|
|
229
|
+
status: "pass",
|
|
230
|
+
title: "Managed Composio API key",
|
|
231
|
+
message: "AgentKit Cloud has the managed COMPOSIO_API_KEY.",
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (missingToolkits.length > 0) {
|
|
236
|
+
checks.push({
|
|
237
|
+
status: "fail",
|
|
238
|
+
title: "Managed Composio auth configs",
|
|
239
|
+
message: `Missing ${missingToolkits
|
|
240
|
+
.map((toolkit) => `${toolkit.auth_config_env ?? "auth config"} for ${toolkit.toolkit ?? "unknown"}`)
|
|
241
|
+
.join(", ")}.`,
|
|
242
|
+
action: "ask the AgentKit Cloud operator to configure the missing toolkit auth config",
|
|
243
|
+
});
|
|
244
|
+
} else {
|
|
245
|
+
checks.push({
|
|
246
|
+
status: "pass",
|
|
247
|
+
title: "Managed Composio auth configs",
|
|
248
|
+
message: `Auth configs are available for ${context.integrations.managedComposio.toolkits.join(", ")}.`,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
} catch (error) {
|
|
252
|
+
checks.push({
|
|
253
|
+
status: "warn",
|
|
254
|
+
title: "Managed Composio auth configs",
|
|
255
|
+
message: `Could not verify managed Composio auth configs. ${formatReadinessError(error)}`,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
175
259
|
}
|
|
176
260
|
|
|
177
261
|
if (context.agentKitManagedSecrets.length > 0) {
|
|
@@ -184,6 +268,25 @@ export async function checkDeployReadiness(options: {
|
|
|
184
268
|
});
|
|
185
269
|
}
|
|
186
270
|
|
|
271
|
+
if (context.integrations.managedComposio.enabled) {
|
|
272
|
+
if (!options.requireLogin) {
|
|
273
|
+
checks.push({
|
|
274
|
+
status: "fail",
|
|
275
|
+
title: "Managed Composio access",
|
|
276
|
+
message: "AgentKit-managed Composio is paid hosted infrastructure and cannot be used by anonymous deploys.",
|
|
277
|
+
action: "run agentkit deploy without --anonymous after logging in with a paid AgentKit Cloud account",
|
|
278
|
+
});
|
|
279
|
+
} else {
|
|
280
|
+
checks.push({
|
|
281
|
+
status: "info",
|
|
282
|
+
title: "Managed Composio",
|
|
283
|
+
message: `Configured for ${context.integrations.managedComposio.toolkits.join(", ")} with ${
|
|
284
|
+
context.integrations.managedComposio.toolCount
|
|
285
|
+
} allowed action${context.integrations.managedComposio.toolCount === 1 ? "" : "s"}. AgentKit Cloud injects COMPOSIO_API_KEY.`,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
187
290
|
if (context.accessMode === "private") {
|
|
188
291
|
checks.push({
|
|
189
292
|
status: "info",
|
|
@@ -350,20 +453,26 @@ async function resolveCloudProjectId(apiUrl: string, projectName: string): Promi
|
|
|
350
453
|
|
|
351
454
|
function secretSetCommand(secret: string, source: DeployReadinessContext["localSecrets"][string] | undefined): string {
|
|
352
455
|
if (source?.dotenv) {
|
|
353
|
-
return `agentkit secret set ${secret} --from-local-env`;
|
|
456
|
+
return `npm run agentkit -- secret set ${secret} --from-local-env`;
|
|
354
457
|
}
|
|
355
458
|
|
|
356
459
|
if (source?.environment) {
|
|
357
|
-
return `agentkit secret set ${secret} --from-env`;
|
|
460
|
+
return `npm run agentkit -- secret set ${secret} --from-env`;
|
|
358
461
|
}
|
|
359
462
|
|
|
360
|
-
return `agentkit secret set ${secret} --stdin`;
|
|
463
|
+
return `npm run agentkit -- secret set ${secret} --stdin`;
|
|
361
464
|
}
|
|
362
465
|
|
|
363
466
|
function normalizeOptionalNumber(value: number | null | undefined): number | undefined {
|
|
364
467
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
365
468
|
}
|
|
366
469
|
|
|
470
|
+
function majorNodeVersion(version: string): number | null {
|
|
471
|
+
const [major] = version.split(".");
|
|
472
|
+
const parsed = Number(major);
|
|
473
|
+
return Number.isInteger(parsed) ? parsed : null;
|
|
474
|
+
}
|
|
475
|
+
|
|
367
476
|
function isString(value: unknown): value is string {
|
|
368
477
|
return typeof value === "string";
|
|
369
478
|
}
|
package/src/cli/help.ts
CHANGED
|
@@ -41,6 +41,7 @@ Deploy:
|
|
|
41
41
|
|
|
42
42
|
More:
|
|
43
43
|
agentkit channels ...
|
|
44
|
+
agentkit integrations status
|
|
44
45
|
agentkit access token ...
|
|
45
46
|
agentkit env ...
|
|
46
47
|
agentkit docs full
|
|
@@ -72,9 +73,9 @@ Usage:
|
|
|
72
73
|
agentkit db seed [--file <path>]
|
|
73
74
|
agentkit eval run
|
|
74
75
|
agentkit eval from-conversation <conversation-id> [--out <path>] [--force]
|
|
75
|
-
agentkit conversations list
|
|
76
|
-
agentkit conversations show <conversation-id>
|
|
77
|
-
agentkit conversations trace <conversation-id>
|
|
76
|
+
agentkit conversations list [--deploy]
|
|
77
|
+
agentkit conversations show <conversation-id> [--deploy]
|
|
78
|
+
agentkit conversations trace <conversation-id> [--deploy]
|
|
78
79
|
agentkit channels list
|
|
79
80
|
agentkit channels add <website|telegram|whatsapp> <name> [--provider zapster|meta] [--api <url>]
|
|
80
81
|
agentkit channels connect <website|telegram|whatsapp> <name> [--provider zapster|meta] [--api <url>]
|
|
@@ -82,6 +83,7 @@ Usage:
|
|
|
82
83
|
agentkit channels status <name> [--api <url>]
|
|
83
84
|
agentkit channels doctor <name> [--api <url>]
|
|
84
85
|
agentkit channels test <name> [--message <text>] [--fixture <path>] [--api <url>]
|
|
86
|
+
agentkit channels test-audio <name> [--fixture voice-note|audio-file|<path>] [--api <url>]
|
|
85
87
|
agentkit channels deliveries list <name> [--api <url>]
|
|
86
88
|
agentkit channels deliveries show <delivery-id> [--api <url>]
|
|
87
89
|
agentkit channels buffers list <name> [--api <url>]
|
|
@@ -89,6 +91,10 @@ Usage:
|
|
|
89
91
|
agentkit channels buffers flush [<name>] <conversation-id> [--api <url>]
|
|
90
92
|
agentkit channels buffers clear [<name>] <conversation-id> [--api <url>]
|
|
91
93
|
agentkit channels buffers retry [<name>] <conversation-id> [--api <url>]
|
|
94
|
+
agentkit integrations status [--toolkit <slug>] [--api <url>]
|
|
95
|
+
agentkit integrations connect composio [--toolkit <slug>] [--callback-url <url>] [--api <url>]
|
|
96
|
+
agentkit skills status
|
|
97
|
+
agentkit skills sync
|
|
92
98
|
agentkit inspect
|
|
93
99
|
agentkit build [--target cloudflare|container]
|
|
94
100
|
agentkit login --token <token> [--api <url>]
|
|
@@ -99,6 +105,7 @@ Usage:
|
|
|
99
105
|
agentkit deploy status [--api <url>]
|
|
100
106
|
agentkit deploy pause [--api <url>]
|
|
101
107
|
agentkit deploy resume [--api <url>]
|
|
108
|
+
agentkit transcribe smoke [--provider test|openai|groq] [--model <model>] [--fixture <audio-file>]
|
|
102
109
|
agentkit secret set <NAME> <VALUE> [--api <url>]
|
|
103
110
|
agentkit secret set <NAME> --stdin [--api <url>]
|
|
104
111
|
agentkit secret set <NAME> --from-env [ENV_NAME] [--api <url>]
|
|
@@ -135,6 +142,9 @@ Commands:
|
|
|
135
142
|
eval Run local eval files or create one from a conversation
|
|
136
143
|
conversations List, inspect, and trace stored local conversations
|
|
137
144
|
channels Manage hosted channel resources
|
|
145
|
+
integrations Manage hosted AgentKit-managed integrations
|
|
146
|
+
skills Check or refresh local AgentKit skill files
|
|
147
|
+
transcribe Smoke-test audio transcription providers
|
|
138
148
|
inspect Print machine-readable Agent Capsule state
|
|
139
149
|
build Build a hosted deploy artifact
|
|
140
150
|
login Store an AgentKit Cloud alpha token outside the capsule
|
|
@@ -172,12 +182,17 @@ export function renderCommandHelp(command: string): string {
|
|
|
172
182
|
sync: "agentkit sync init [--force] | agentkit sync run [--file <path>]",
|
|
173
183
|
eval: "agentkit eval run | agentkit eval from-conversation <conversation-id> [--out <path>] [--force]",
|
|
174
184
|
conversations:
|
|
175
|
-
"agentkit conversations list | agentkit conversations show <conversation-id> | agentkit conversations trace <conversation-id>",
|
|
185
|
+
"agentkit conversations list [--deploy] | agentkit conversations show <conversation-id> [--deploy] | agentkit conversations trace <conversation-id> [--deploy]",
|
|
186
|
+
channels:
|
|
187
|
+
"agentkit channels list | add | connect | setup | status | doctor | test | test-audio | deliveries | buffers",
|
|
188
|
+
skills: "agentkit skills status | agentkit skills sync",
|
|
189
|
+
transcribe: "agentkit transcribe smoke [--provider test|openai|groq] [--model <model>] [--fixture <audio-file>]",
|
|
176
190
|
deploy:
|
|
177
191
|
'agentkit deploy [--smoke "hello"] | agentkit deploy smoke [--message "hello"] | agentkit deploy doctor | status | pause | resume',
|
|
178
192
|
secret:
|
|
179
193
|
"agentkit secret set <NAME> --stdin | --from-env [ENV_NAME] | --from-local-env | agentkit secret sync --from-local | list | unset <NAME>",
|
|
180
194
|
access: "agentkit access token create <name> [--out <path>] | list | revoke <token-id>",
|
|
195
|
+
integrations: "agentkit integrations status [--toolkit <slug>] | agentkit integrations connect composio [--toolkit <slug>]",
|
|
181
196
|
env: "agentkit env set <NAME> --stdin | --from-env [ENV_NAME] | list | unset <NAME>",
|
|
182
197
|
docs: "agentkit docs path | llms | full",
|
|
183
198
|
handoff: "agentkit handoff codex [goal] | agentkit handoff claude [goal]",
|
package/src/cli/index.ts
CHANGED
|
@@ -22,6 +22,7 @@ import { runEvalsFromCwd, writeEvalFromConversation } from "../runtime/evals";
|
|
|
22
22
|
import { findAgentKitDocs } from "../runtime/docs";
|
|
23
23
|
import { listCapsuleEnv, setCapsuleEnv, unsetCapsuleEnv } from "../runtime/env";
|
|
24
24
|
import { checkAgentSpec, initializeAgentSpec } from "../runtime/spec";
|
|
25
|
+
import { checkDefaultSkillStatus, syncDefaultSkillFiles } from "../runtime/skills";
|
|
25
26
|
import { initializeSyncScaffold, runCapsuleSync } from "../runtime/sync";
|
|
26
27
|
import { runToolFromCwd } from "../runtime/tool-runner";
|
|
27
28
|
import { startAgentDevServer } from "../runtime/dev-server";
|
|
@@ -67,6 +68,7 @@ import { renderCommandHelp, renderCommandReference, renderHelp } from "./help";
|
|
|
67
68
|
import { runInheritedCommand, waitForShutdown } from "./process";
|
|
68
69
|
import { handleChannelsCommand } from "./commands/channels";
|
|
69
70
|
import { handleKnowledgeCommand } from "./commands/knowledge";
|
|
71
|
+
import { handleTranscribeCommand } from "./commands/transcribe";
|
|
70
72
|
|
|
71
73
|
async function main() {
|
|
72
74
|
const args = parseArgs(process.argv.slice(2));
|
|
@@ -336,8 +338,15 @@ async function main() {
|
|
|
336
338
|
|
|
337
339
|
if (args.command === "conversations") {
|
|
338
340
|
const [subcommand, conversationId] = args.positional;
|
|
341
|
+
const fromDeploy = args.flags.deploy === true;
|
|
339
342
|
|
|
340
343
|
if (subcommand === "list") {
|
|
344
|
+
if (fromDeploy) {
|
|
345
|
+
const payload = await fetchDeployConversationJson(process.cwd(), "/v1/conversations");
|
|
346
|
+
printJson(payload);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
341
350
|
const conversations = await listConversationsFromCwd(process.cwd());
|
|
342
351
|
|
|
343
352
|
if (conversations.length === 0) {
|
|
@@ -363,7 +372,16 @@ async function main() {
|
|
|
363
372
|
|
|
364
373
|
if (subcommand === "show") {
|
|
365
374
|
if (!conversationId) {
|
|
366
|
-
throw new Error("Missing conversation id. Usage: agentkit conversations show <conversation-id>");
|
|
375
|
+
throw new Error("Missing conversation id. Usage: agentkit conversations show <conversation-id> [--deploy]");
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (fromDeploy) {
|
|
379
|
+
const payload = await fetchDeployConversationJson(
|
|
380
|
+
process.cwd(),
|
|
381
|
+
`/v1/conversations/${encodeURIComponent(conversationId)}`,
|
|
382
|
+
);
|
|
383
|
+
printJson(payload);
|
|
384
|
+
return;
|
|
367
385
|
}
|
|
368
386
|
|
|
369
387
|
const conversation = await getConversationFromCwd(process.cwd(), conversationId);
|
|
@@ -382,7 +400,16 @@ async function main() {
|
|
|
382
400
|
|
|
383
401
|
if (subcommand === "trace") {
|
|
384
402
|
if (!conversationId) {
|
|
385
|
-
throw new Error("Missing conversation id. Usage: agentkit conversations trace <conversation-id>");
|
|
403
|
+
throw new Error("Missing conversation id. Usage: agentkit conversations trace <conversation-id> [--deploy]");
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (fromDeploy) {
|
|
407
|
+
const trace = await fetchDeployConversationJson(
|
|
408
|
+
process.cwd(),
|
|
409
|
+
`/v1/conversations/${encodeURIComponent(conversationId)}/trace`,
|
|
410
|
+
);
|
|
411
|
+
printJson(trace);
|
|
412
|
+
return;
|
|
386
413
|
}
|
|
387
414
|
|
|
388
415
|
const trace = await getConversationTraceFromCwd(process.cwd(), conversationId);
|
|
@@ -390,7 +417,7 @@ async function main() {
|
|
|
390
417
|
return;
|
|
391
418
|
}
|
|
392
419
|
|
|
393
|
-
throw new Error("Usage: agentkit conversations list | agentkit conversations show <conversation-id> | agentkit conversations trace <conversation-id>");
|
|
420
|
+
throw new Error("Usage: agentkit conversations list [--deploy] | agentkit conversations show <conversation-id> [--deploy] | agentkit conversations trace <conversation-id> [--deploy]");
|
|
394
421
|
}
|
|
395
422
|
|
|
396
423
|
if (args.command === "knowledge") {
|
|
@@ -764,6 +791,117 @@ async function main() {
|
|
|
764
791
|
return;
|
|
765
792
|
}
|
|
766
793
|
|
|
794
|
+
if (args.command === "transcribe") {
|
|
795
|
+
await handleTranscribeCommand(args);
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
if (args.command === "skills") {
|
|
800
|
+
const [subcommand] = args.positional;
|
|
801
|
+
const root = await findAgentCapsuleRoot(process.cwd());
|
|
802
|
+
|
|
803
|
+
if (subcommand === "status") {
|
|
804
|
+
const status = await checkDefaultSkillStatus(root);
|
|
805
|
+
printSkillStatus(status);
|
|
806
|
+
if (status.status !== "current") {
|
|
807
|
+
process.exitCode = 1;
|
|
808
|
+
}
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
if (subcommand === "sync") {
|
|
813
|
+
const result = await syncDefaultSkillFiles(root);
|
|
814
|
+
console.log(`Synced ${result.files.length} AgentKit skill files.`);
|
|
815
|
+
console.log("Status: current");
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
throw new Error("Usage: agentkit skills status | agentkit skills sync");
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
if (args.command === "integrations") {
|
|
823
|
+
const [subcommand, provider] = args.positional;
|
|
824
|
+
|
|
825
|
+
if (provider !== undefined && provider !== "composio") {
|
|
826
|
+
throw new Error("Usage: agentkit integrations status | connect composio [--toolkit <slug>] [--callback-url <url>] [--api <url>]");
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
const state = await requireLocalDeployState();
|
|
830
|
+
const apiUrl = await resolveCloudApiUrl(args.flags.api);
|
|
831
|
+
|
|
832
|
+
if (subcommand === "status") {
|
|
833
|
+
const toolkit = parseOptionalStringFlag(
|
|
834
|
+
args.flags.toolkit,
|
|
835
|
+
"toolkit",
|
|
836
|
+
"agentkit integrations status --toolkit <slug>",
|
|
837
|
+
);
|
|
838
|
+
const payload = await cloudApiRequest(
|
|
839
|
+
apiUrl,
|
|
840
|
+
`/v1/deploys/${encodeURIComponent(state.deploy_id)}/integrations/composio/status${
|
|
841
|
+
toolkit ? `?toolkit=${encodeURIComponent(toolkit)}` : ""
|
|
842
|
+
}`,
|
|
843
|
+
{ method: "GET" },
|
|
844
|
+
);
|
|
845
|
+
printJson(payload);
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
if (subcommand === "connect" && provider === "composio") {
|
|
850
|
+
const toolkit = parseOptionalStringFlag(
|
|
851
|
+
args.flags.toolkit,
|
|
852
|
+
"toolkit",
|
|
853
|
+
"agentkit integrations connect composio --toolkit <slug>",
|
|
854
|
+
);
|
|
855
|
+
const callbackUrl = parseOptionalStringFlag(
|
|
856
|
+
args.flags["callback-url"],
|
|
857
|
+
"callback-url",
|
|
858
|
+
"agentkit integrations connect composio --callback-url <url>",
|
|
859
|
+
);
|
|
860
|
+
const payload = (await cloudApiRequest(
|
|
861
|
+
apiUrl,
|
|
862
|
+
`/v1/deploys/${encodeURIComponent(state.deploy_id)}/integrations/composio/connect-link`,
|
|
863
|
+
{
|
|
864
|
+
method: "POST",
|
|
865
|
+
body: JSON.stringify({
|
|
866
|
+
...(toolkit ? { toolkit } : {}),
|
|
867
|
+
...(callbackUrl ? { callback_url: callbackUrl } : {}),
|
|
868
|
+
}),
|
|
869
|
+
},
|
|
870
|
+
)) as {
|
|
871
|
+
connect_link?: {
|
|
872
|
+
toolkit?: string;
|
|
873
|
+
user_id?: string;
|
|
874
|
+
redirect_url?: string;
|
|
875
|
+
expires_at?: string;
|
|
876
|
+
connected_account_id?: string;
|
|
877
|
+
};
|
|
878
|
+
};
|
|
879
|
+
|
|
880
|
+
const link = payload.connect_link;
|
|
881
|
+
|
|
882
|
+
if (!link?.redirect_url) {
|
|
883
|
+
throw new AgentKitError("integration_response_invalid", "AgentKit Cloud returned an invalid Composio connect-link payload.");
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
console.log("Composio connect link");
|
|
887
|
+
console.log(`Toolkit: ${link.toolkit ?? toolkit ?? "unknown"}`);
|
|
888
|
+
console.log(`User: ${link.user_id ?? "unknown"}`);
|
|
889
|
+
console.log(`URL: ${link.redirect_url}`);
|
|
890
|
+
|
|
891
|
+
if (link.expires_at) {
|
|
892
|
+
console.log(`Expires: ${link.expires_at}`);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
if (link.connected_account_id) {
|
|
896
|
+
console.log(`Account: ${link.connected_account_id}`);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
throw new Error("Usage: agentkit integrations status | connect composio [--toolkit <slug>] [--callback-url <url>] [--api <url>]");
|
|
903
|
+
}
|
|
904
|
+
|
|
767
905
|
if (args.command === "env") {
|
|
768
906
|
const [subcommand, name, ...valueParts] = args.positional;
|
|
769
907
|
const root = await findAgentCapsuleRoot(process.cwd());
|
|
@@ -1074,10 +1212,67 @@ async function runDeploySmoke(input: { deployUrl: string; message: string; token
|
|
|
1074
1212
|
}
|
|
1075
1213
|
}
|
|
1076
1214
|
|
|
1215
|
+
async function fetchDeployConversationJson(cwd: string, path: string): Promise<unknown> {
|
|
1216
|
+
const state = await requireLocalDeployState();
|
|
1217
|
+
const deployUrl = requireDeployUrl(state);
|
|
1218
|
+
const token = await readDeployAccessTokenForSmoke(cwd, state);
|
|
1219
|
+
const headers = new Headers();
|
|
1220
|
+
|
|
1221
|
+
if (token) {
|
|
1222
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
let response: Response;
|
|
1226
|
+
|
|
1227
|
+
try {
|
|
1228
|
+
response = await fetch(new URL(path, deployUrl).href, {
|
|
1229
|
+
method: "GET",
|
|
1230
|
+
headers,
|
|
1231
|
+
});
|
|
1232
|
+
} catch (error) {
|
|
1233
|
+
throw new AgentKitError(
|
|
1234
|
+
"deploy_conversation_request_failed",
|
|
1235
|
+
`Could not read hosted conversation data: ${error instanceof Error ? error.message : String(error)}`,
|
|
1236
|
+
);
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
const payload = await response.json().catch(() => null);
|
|
1240
|
+
|
|
1241
|
+
if (!response.ok) {
|
|
1242
|
+
throw new AgentKitError("deploy_conversation_request_failed", readCloudError(payload, response.status));
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
return payload;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1077
1248
|
function printJson(value: unknown): void {
|
|
1078
1249
|
console.log(JSON.stringify(value, null, 2));
|
|
1079
1250
|
}
|
|
1080
1251
|
|
|
1252
|
+
function printSkillStatus(status: Awaited<ReturnType<typeof checkDefaultSkillStatus>>): void {
|
|
1253
|
+
console.log("AgentKit skills");
|
|
1254
|
+
console.log(`Status: ${status.status}`);
|
|
1255
|
+
console.log(`Checked: ${status.checked}`);
|
|
1256
|
+
|
|
1257
|
+
if (status.missing.length > 0) {
|
|
1258
|
+
console.log(`Missing: ${status.missing.length}`);
|
|
1259
|
+
for (const file of status.missing.slice(0, 10)) {
|
|
1260
|
+
console.log(` ${file}`);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
if (status.outdated.length > 0) {
|
|
1265
|
+
console.log(`Outdated: ${status.outdated.length}`);
|
|
1266
|
+
for (const file of status.outdated.slice(0, 10)) {
|
|
1267
|
+
console.log(` ${file}`);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
if (status.status !== "current") {
|
|
1272
|
+
console.log("Run: npm run agentkit -- skills sync");
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1081
1276
|
async function printJsonOrWrite(value: unknown, outFlag: string | boolean | undefined, usage: string): Promise<void> {
|
|
1082
1277
|
const outPath = parseOptionalStringFlag(outFlag, "out", usage);
|
|
1083
1278
|
|
package/src/create-project.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
|
-
import { mkdir, readFile,
|
|
3
|
-
import { basename, dirname, join,
|
|
2
|
+
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { loadDefaultSkillFiles } from "./runtime/skills";
|
|
8
|
+
import { getTemplate } from "./templates";
|
|
8
9
|
|
|
9
10
|
const execFileAsync = promisify(execFile);
|
|
10
11
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
@@ -129,35 +130,6 @@ async function resolveAgentKitDependency(): Promise<string> {
|
|
|
129
130
|
return packageJson.version;
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
async function loadDefaultSkillFiles(): Promise<TemplateFile[]> {
|
|
133
|
-
const sourceRoot = join(moduleDir, "templates", "skills");
|
|
134
|
-
const sourceFiles = await listFiles(sourceRoot);
|
|
135
|
-
|
|
136
|
-
return Promise.all(
|
|
137
|
-
sourceFiles.map(async (sourcePath) => ({
|
|
138
|
-
path: join("skills", relative(sourceRoot, sourcePath)).replaceAll("\\", "/"),
|
|
139
|
-
contents: await readFile(sourcePath, "utf8"),
|
|
140
|
-
})),
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async function listFiles(directory: string): Promise<string[]> {
|
|
145
|
-
const entries = await readdir(directory, { withFileTypes: true });
|
|
146
|
-
const files = await Promise.all(
|
|
147
|
-
entries.map(async (entry) => {
|
|
148
|
-
const path = join(directory, entry.name);
|
|
149
|
-
|
|
150
|
-
if (entry.isDirectory()) {
|
|
151
|
-
return listFiles(path);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return entry.isFile() ? [path] : [];
|
|
155
|
-
}),
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
return files.flat().sort();
|
|
159
|
-
}
|
|
160
|
-
|
|
161
133
|
async function directoryExists(path: string): Promise<boolean> {
|
|
162
134
|
try {
|
|
163
135
|
const result = await stat(path);
|