@andreprado/agentkit 0.1.0-alpha.16 → 0.1.0-alpha.17
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 +2 -0
- package/docs/guides/add-managed-composio.md +137 -0
- package/docs/guides/channels-production-handoff.md +1 -1
- package/docs/guides/connect-telegram.md +3 -1
- package/docs/guides/prepare-deploy.md +3 -1
- package/docs/llms-full.txt +13 -1
- package/docs/llms.txt +7 -0
- package/package.json +1 -1
- package/src/cli/commands/channels.ts +119 -7
- package/src/cli/commands/transcribe.ts +171 -0
- package/src/cli/deploy-readiness.ts +59 -3
- package/src/cli/help.ts +15 -0
- package/src/cli/index.ts +130 -0
- package/src/create-project.ts +4 -32
- package/src/index.ts +145 -0
- package/src/runtime/chat.ts +2 -1
- package/src/runtime/config.ts +129 -0
- package/src/runtime/core/manifest.ts +29 -2
- package/src/runtime/deploy-readiness.ts +31 -1
- package/src/runtime/inspect.ts +108 -4
- package/src/runtime/integrations/composio.ts +257 -0
- package/src/runtime/skills.ts +95 -0
- package/src/runtime/targets/cloudflare/build.ts +160 -5
- 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 +66 -0
- package/src/templates/skills/agentkit-troubleshooting/SKILL.md +3 -2
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { basename, extname, resolve } from "node:path";
|
|
3
|
+
|
|
4
|
+
import type { TranscriptionProviderName } from "../../index";
|
|
5
|
+
import { findAgentCapsuleRoot, loadAgentCapsule } from "../../runtime/config";
|
|
6
|
+
import { loadCapsuleEnv } from "../../runtime/env";
|
|
7
|
+
import {
|
|
8
|
+
defaultTranscriptionSecret,
|
|
9
|
+
resolveTranscriptionConfig,
|
|
10
|
+
transcribeAudio,
|
|
11
|
+
type ResolvedTranscriptionConfig,
|
|
12
|
+
} from "../../runtime/transcription";
|
|
13
|
+
import type { ParsedArgs } from "../args";
|
|
14
|
+
|
|
15
|
+
type SmokeFixture = {
|
|
16
|
+
audio: Uint8Array;
|
|
17
|
+
filename: string;
|
|
18
|
+
mimeType: string;
|
|
19
|
+
source: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const defaultModels: Record<TranscriptionProviderName, string> = {
|
|
23
|
+
test: "fake",
|
|
24
|
+
openai: "gpt-4o-mini-transcribe",
|
|
25
|
+
groq: "whisper-large-v3-turbo",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Short macOS-generated spoken "hello" sample encoded as M4A. M4A is supported by OpenAI and Groq.
|
|
29
|
+
const builtinSmokeM4aBase64 =
|
|
30
|
+
"AAAAHGZ0eXBNNEEgAAAAAE00QSBtcDQyaXNvbQAAA3ptb292AAAAbG12aGQAAAAA5kTZseZE2bEAAFYiAAA4AAABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACDHRyYWsAAABcdGtoZAAAAAfmRNmx5kTZsQAAAAEAAAAAAAA4AAAAAAAAAAAAAAAAAAEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAahtZGlhAAAAIG1kaGQAAAAA5kTZseZE2bEAAFYiAAA4AAAAAAAAAAAiaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAAAAAAABXm1pbmYAAAAQc21oZAAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABInN0YmwAAAB2c3RzZAAAAAAAAAABAAAAZm1wNGEAAAAAAAAAAQAAAAAAAAAAAAIAEAAAAABWIgAAAAAAM2VzZHMAAAAAA4CAgCIAAAAEgICAFEAUABgAAAAU+AAAfQAFgICAAhOIBoCAgAECAAAAD3NidGQAAAAASTE2AAAAGHN0dHMAAAAAAAAAAQAAAA4AAAQAAAAAKHN0c2MAAAAAAAAAAgAAAAEAAAALAAAAAQAAAAIAAAADAAAAAQAAAExzdHN6AAAAAAAAAAAAAAAOAAAABAAAAbkAAADiAAAA0wAAAL8AAADLAAAAzAAAAJMAAACmAAAA5wAAALcAAACnAAAAtgAAADoAAAAYc3RjbwAAAAAAAAACAAAQAAAAGJ8AAAD6dWR0YQAAAPJtZXRhAAAAAAAAACJoZGxyAAAAAAAAAABtZGlyYXBwbAAAAAAAAAAAAAAAAADEaWxzdAAAALwtLS0tAAAAHG1lYW4AAAAAY29tLmFwcGxlLmlUdW5lcwAAABRuYW1lAAAAAGlUdW5TTVBCAAAAhGRhdGEAAAABAAAAACAwMDAwMDAwMCAwMDAwMDg0MCAwMDAwMDEwOCAwMDAwMDAwMDAwMDAyRUI4IDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwAAAMYmZyZWUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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";
|
|
31
|
+
|
|
32
|
+
export async function handleTranscribeCommand(args: ParsedArgs): Promise<void> {
|
|
33
|
+
const [subcommand] = args.positional;
|
|
34
|
+
|
|
35
|
+
if (subcommand !== "smoke") {
|
|
36
|
+
throw new Error("Usage: agentkit transcribe smoke [--provider test|openai|groq] [--model <model>] [--fixture <audio-file>]");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const root = await findAgentCapsuleRoot(process.cwd());
|
|
40
|
+
const capsule = await loadAgentCapsule(root);
|
|
41
|
+
const env = compactEnv(await loadCapsuleEnv(root, process.env));
|
|
42
|
+
const configured = resolveTranscriptionConfig(capsule.config.transcription);
|
|
43
|
+
const provider = parseProviderFlag(args.flags.provider, configured);
|
|
44
|
+
const model = typeof args.flags.model === "string" ? args.flags.model : configured.enabled && configured.provider === provider ? configured.model : defaultModels[provider];
|
|
45
|
+
const secret = typeof args.flags.secret === "string"
|
|
46
|
+
? args.flags.secret
|
|
47
|
+
: configured.enabled && configured.provider === provider
|
|
48
|
+
? configured.secret
|
|
49
|
+
: defaultTranscriptionSecret(provider);
|
|
50
|
+
const fixture = await loadSmokeFixture(provider, args.flags.fixture);
|
|
51
|
+
|
|
52
|
+
const config: ResolvedTranscriptionConfig = {
|
|
53
|
+
enabled: true,
|
|
54
|
+
provider,
|
|
55
|
+
model,
|
|
56
|
+
secret,
|
|
57
|
+
language: typeof args.flags.language === "string" ? args.flags.language : configured.enabled ? configured.language : null,
|
|
58
|
+
prompt: typeof args.flags.prompt === "string" ? args.flags.prompt : configured.enabled ? configured.prompt : null,
|
|
59
|
+
limits: configured.enabled ? configured.limits : {},
|
|
60
|
+
rawAudioTtlSeconds: configured.enabled ? configured.rawAudioTtlSeconds : 3600,
|
|
61
|
+
};
|
|
62
|
+
const result = await transcribeAudio({
|
|
63
|
+
config,
|
|
64
|
+
secrets: env,
|
|
65
|
+
audio: fixture.audio,
|
|
66
|
+
filename: fixture.filename,
|
|
67
|
+
mimeType: fixture.mimeType,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
console.log("Transcription smoke");
|
|
71
|
+
console.log(`Provider: ${provider}`);
|
|
72
|
+
console.log(`Model: ${model}`);
|
|
73
|
+
console.log(`Fixture: ${fixture.source} (${fixture.mimeType})`);
|
|
74
|
+
|
|
75
|
+
if (result.ok) {
|
|
76
|
+
console.log("Status: ok");
|
|
77
|
+
console.log(`Transcript: ${JSON.stringify(result.text)}`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.log("Status: failed");
|
|
82
|
+
console.log(`Code: ${result.code}`);
|
|
83
|
+
console.log(`Message: ${result.message}`);
|
|
84
|
+
process.exitCode = 1;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function parseProviderFlag(
|
|
88
|
+
value: string | boolean | undefined,
|
|
89
|
+
configured: ResolvedTranscriptionConfig,
|
|
90
|
+
): TranscriptionProviderName {
|
|
91
|
+
if (value === undefined || value === false) {
|
|
92
|
+
return configured.enabled ? configured.provider : "groq";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (value === "test" || value === "openai" || value === "groq") {
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
throw new Error("Usage: agentkit transcribe smoke [--provider test|openai|groq] [--model <model>] [--fixture <audio-file>]");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function compactEnv(env: Record<string, string | undefined>): Record<string, string> {
|
|
103
|
+
const compact: Record<string, string> = {};
|
|
104
|
+
|
|
105
|
+
for (const [name, value] of Object.entries(env)) {
|
|
106
|
+
if (value !== undefined) {
|
|
107
|
+
compact[name] = value;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return compact;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function loadSmokeFixture(
|
|
115
|
+
provider: TranscriptionProviderName,
|
|
116
|
+
fixtureFlag: string | boolean | undefined,
|
|
117
|
+
): Promise<SmokeFixture> {
|
|
118
|
+
if (typeof fixtureFlag === "string") {
|
|
119
|
+
const filename = resolve(process.cwd(), fixtureFlag);
|
|
120
|
+
return {
|
|
121
|
+
audio: new Uint8Array(await readFile(filename)),
|
|
122
|
+
filename: basename(filename),
|
|
123
|
+
mimeType: mimeTypeForFilename(filename),
|
|
124
|
+
source: fixtureFlag,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (provider === "test") {
|
|
129
|
+
return {
|
|
130
|
+
audio: new TextEncoder().encode("hello"),
|
|
131
|
+
filename: "agentkit-smoke.ogg",
|
|
132
|
+
mimeType: "audio/ogg",
|
|
133
|
+
source: "built-in text fixture",
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
audio: new Uint8Array(Buffer.from(builtinSmokeM4aBase64, "base64")),
|
|
139
|
+
filename: "agentkit-transcribe-smoke.m4a",
|
|
140
|
+
mimeType: "audio/m4a",
|
|
141
|
+
source: "built-in spoken hello",
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function mimeTypeForFilename(filename: string): string {
|
|
146
|
+
const extension = extname(filename).toLowerCase();
|
|
147
|
+
|
|
148
|
+
if (extension === ".ogg" || extension === ".opus") {
|
|
149
|
+
return "audio/ogg";
|
|
150
|
+
}
|
|
151
|
+
if (extension === ".mp3" || extension === ".mpeg" || extension === ".mpga") {
|
|
152
|
+
return "audio/mpeg";
|
|
153
|
+
}
|
|
154
|
+
if (extension === ".m4a") {
|
|
155
|
+
return "audio/m4a";
|
|
156
|
+
}
|
|
157
|
+
if (extension === ".mp4") {
|
|
158
|
+
return "audio/mp4";
|
|
159
|
+
}
|
|
160
|
+
if (extension === ".wav") {
|
|
161
|
+
return "audio/wav";
|
|
162
|
+
}
|
|
163
|
+
if (extension === ".webm") {
|
|
164
|
+
return "audio/webm";
|
|
165
|
+
}
|
|
166
|
+
if (extension === ".flac") {
|
|
167
|
+
return "audio/flac";
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return "application/octet-stream";
|
|
171
|
+
}
|
|
@@ -2,6 +2,7 @@ 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_ENTITLEMENT } from "../runtime/integrations/composio";
|
|
5
6
|
import {
|
|
6
7
|
cloudApiRequest,
|
|
7
8
|
formatCloudAuthSource,
|
|
@@ -53,6 +54,22 @@ export async function checkDeployReadiness(options: {
|
|
|
53
54
|
});
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
const nodeMajor = majorNodeVersion(process.versions.node);
|
|
58
|
+
if (nodeMajor !== null && nodeMajor < 24) {
|
|
59
|
+
checks.push({
|
|
60
|
+
status: "warn",
|
|
61
|
+
title: "Node version",
|
|
62
|
+
message: `@andreprado/agentkit requires Node >=24; current Node is ${process.versions.node}.`,
|
|
63
|
+
action: "use Node 24+ before running direct node imports or production container commands",
|
|
64
|
+
});
|
|
65
|
+
} else {
|
|
66
|
+
checks.push({
|
|
67
|
+
status: "pass",
|
|
68
|
+
title: "Node version",
|
|
69
|
+
message: `Node ${process.versions.node} satisfies @andreprado/agentkit engines.node >=24.`,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
56
73
|
if (!auth?.token) {
|
|
57
74
|
checks.push({
|
|
58
75
|
status: options.requireLogin ? "fail" : "warn",
|
|
@@ -104,6 +121,9 @@ export async function checkDeployReadiness(options: {
|
|
|
104
121
|
const hasCloudflareAlpha = capabilities.some(
|
|
105
122
|
(capability) => capability.name === "cloudflare_deploy_alpha" && capability.status === "active",
|
|
106
123
|
);
|
|
124
|
+
const hasManagedComposio = capabilities.some(
|
|
125
|
+
(capability) => capability.name === MANAGED_COMPOSIO_ENTITLEMENT && capability.status === "active",
|
|
126
|
+
);
|
|
107
127
|
|
|
108
128
|
checks.push({
|
|
109
129
|
status: hasCloudflareAlpha ? "pass" : "fail",
|
|
@@ -113,6 +133,17 @@ export async function checkDeployReadiness(options: {
|
|
|
113
133
|
: "This account is missing the cloudflare_deploy_alpha entitlement.",
|
|
114
134
|
...(hasCloudflareAlpha ? {} : { action: "log in with an invited AgentKit Cloud alpha token" }),
|
|
115
135
|
});
|
|
136
|
+
|
|
137
|
+
if (context.integrations.managedComposio.enabled) {
|
|
138
|
+
checks.push({
|
|
139
|
+
status: hasManagedComposio ? "pass" : "fail",
|
|
140
|
+
title: "Managed Composio entitlement",
|
|
141
|
+
message: hasManagedComposio
|
|
142
|
+
? `${MANAGED_COMPOSIO_ENTITLEMENT} is active.`
|
|
143
|
+
: `This capsule uses AgentKit-managed Composio, but this account is missing ${MANAGED_COMPOSIO_ENTITLEMENT}.`,
|
|
144
|
+
...(hasManagedComposio ? {} : { action: "upgrade the AgentKit Cloud account or ask an operator to grant managed_composio" }),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
116
147
|
} catch (error) {
|
|
117
148
|
checks.push({
|
|
118
149
|
status: "fail",
|
|
@@ -184,6 +215,25 @@ export async function checkDeployReadiness(options: {
|
|
|
184
215
|
});
|
|
185
216
|
}
|
|
186
217
|
|
|
218
|
+
if (context.integrations.managedComposio.enabled) {
|
|
219
|
+
if (!options.requireLogin) {
|
|
220
|
+
checks.push({
|
|
221
|
+
status: "fail",
|
|
222
|
+
title: "Managed Composio access",
|
|
223
|
+
message: "AgentKit-managed Composio is paid hosted infrastructure and cannot be used by anonymous deploys.",
|
|
224
|
+
action: "run agentkit deploy without --anonymous after logging in with a paid AgentKit Cloud account",
|
|
225
|
+
});
|
|
226
|
+
} else {
|
|
227
|
+
checks.push({
|
|
228
|
+
status: "info",
|
|
229
|
+
title: "Managed Composio",
|
|
230
|
+
message: `Configured for ${context.integrations.managedComposio.toolkits.join(", ")} with ${
|
|
231
|
+
context.integrations.managedComposio.toolCount
|
|
232
|
+
} allowed action${context.integrations.managedComposio.toolCount === 1 ? "" : "s"}. AgentKit Cloud injects COMPOSIO_API_KEY.`,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
187
237
|
if (context.accessMode === "private") {
|
|
188
238
|
checks.push({
|
|
189
239
|
status: "info",
|
|
@@ -350,20 +400,26 @@ async function resolveCloudProjectId(apiUrl: string, projectName: string): Promi
|
|
|
350
400
|
|
|
351
401
|
function secretSetCommand(secret: string, source: DeployReadinessContext["localSecrets"][string] | undefined): string {
|
|
352
402
|
if (source?.dotenv) {
|
|
353
|
-
return `agentkit secret set ${secret} --from-local-env`;
|
|
403
|
+
return `npm run agentkit -- secret set ${secret} --from-local-env`;
|
|
354
404
|
}
|
|
355
405
|
|
|
356
406
|
if (source?.environment) {
|
|
357
|
-
return `agentkit secret set ${secret} --from-env`;
|
|
407
|
+
return `npm run agentkit -- secret set ${secret} --from-env`;
|
|
358
408
|
}
|
|
359
409
|
|
|
360
|
-
return `agentkit secret set ${secret} --stdin`;
|
|
410
|
+
return `npm run agentkit -- secret set ${secret} --stdin`;
|
|
361
411
|
}
|
|
362
412
|
|
|
363
413
|
function normalizeOptionalNumber(value: number | null | undefined): number | undefined {
|
|
364
414
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
365
415
|
}
|
|
366
416
|
|
|
417
|
+
function majorNodeVersion(version: string): number | null {
|
|
418
|
+
const [major] = version.split(".");
|
|
419
|
+
const parsed = Number(major);
|
|
420
|
+
return Number.isInteger(parsed) ? parsed : null;
|
|
421
|
+
}
|
|
422
|
+
|
|
367
423
|
function isString(value: unknown): value is string {
|
|
368
424
|
return typeof value === "string";
|
|
369
425
|
}
|
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
|
|
@@ -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 [--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
|
|
@@ -173,11 +183,16 @@ export function renderCommandHelp(command: string): string {
|
|
|
173
183
|
eval: "agentkit eval run | agentkit eval from-conversation <conversation-id> [--out <path>] [--force]",
|
|
174
184
|
conversations:
|
|
175
185
|
"agentkit conversations list | agentkit conversations show <conversation-id> | agentkit conversations trace <conversation-id>",
|
|
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 | 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));
|
|
@@ -764,6 +766,110 @@ async function main() {
|
|
|
764
766
|
return;
|
|
765
767
|
}
|
|
766
768
|
|
|
769
|
+
if (args.command === "transcribe") {
|
|
770
|
+
await handleTranscribeCommand(args);
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
if (args.command === "skills") {
|
|
775
|
+
const [subcommand] = args.positional;
|
|
776
|
+
const root = await findAgentCapsuleRoot(process.cwd());
|
|
777
|
+
|
|
778
|
+
if (subcommand === "status") {
|
|
779
|
+
const status = await checkDefaultSkillStatus(root);
|
|
780
|
+
printSkillStatus(status);
|
|
781
|
+
if (status.status !== "current") {
|
|
782
|
+
process.exitCode = 1;
|
|
783
|
+
}
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
if (subcommand === "sync") {
|
|
788
|
+
const result = await syncDefaultSkillFiles(root);
|
|
789
|
+
console.log(`Synced ${result.files.length} AgentKit skill files.`);
|
|
790
|
+
console.log("Status: current");
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
throw new Error("Usage: agentkit skills status | agentkit skills sync");
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
if (args.command === "integrations") {
|
|
798
|
+
const [subcommand, provider] = args.positional;
|
|
799
|
+
|
|
800
|
+
if (provider !== undefined && provider !== "composio") {
|
|
801
|
+
throw new Error("Usage: agentkit integrations status | connect composio [--toolkit <slug>] [--callback-url <url>] [--api <url>]");
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
const state = await requireLocalDeployState();
|
|
805
|
+
const apiUrl = await resolveCloudApiUrl(args.flags.api);
|
|
806
|
+
|
|
807
|
+
if (subcommand === "status") {
|
|
808
|
+
const payload = await cloudApiRequest(
|
|
809
|
+
apiUrl,
|
|
810
|
+
`/v1/deploys/${encodeURIComponent(state.deploy_id)}/integrations/composio/status`,
|
|
811
|
+
{ method: "GET" },
|
|
812
|
+
);
|
|
813
|
+
printJson(payload);
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
if (subcommand === "connect" && provider === "composio") {
|
|
818
|
+
const toolkit = parseOptionalStringFlag(
|
|
819
|
+
args.flags.toolkit,
|
|
820
|
+
"toolkit",
|
|
821
|
+
"agentkit integrations connect composio --toolkit <slug>",
|
|
822
|
+
);
|
|
823
|
+
const callbackUrl = parseOptionalStringFlag(
|
|
824
|
+
args.flags["callback-url"],
|
|
825
|
+
"callback-url",
|
|
826
|
+
"agentkit integrations connect composio --callback-url <url>",
|
|
827
|
+
);
|
|
828
|
+
const payload = (await cloudApiRequest(
|
|
829
|
+
apiUrl,
|
|
830
|
+
`/v1/deploys/${encodeURIComponent(state.deploy_id)}/integrations/composio/connect-link`,
|
|
831
|
+
{
|
|
832
|
+
method: "POST",
|
|
833
|
+
body: JSON.stringify({
|
|
834
|
+
...(toolkit ? { toolkit } : {}),
|
|
835
|
+
...(callbackUrl ? { callback_url: callbackUrl } : {}),
|
|
836
|
+
}),
|
|
837
|
+
},
|
|
838
|
+
)) as {
|
|
839
|
+
connect_link?: {
|
|
840
|
+
toolkit?: string;
|
|
841
|
+
user_id?: string;
|
|
842
|
+
redirect_url?: string;
|
|
843
|
+
expires_at?: string;
|
|
844
|
+
connected_account_id?: string;
|
|
845
|
+
};
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
const link = payload.connect_link;
|
|
849
|
+
|
|
850
|
+
if (!link?.redirect_url) {
|
|
851
|
+
throw new AgentKitError("integration_response_invalid", "AgentKit Cloud returned an invalid Composio connect-link payload.");
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
console.log("Composio connect link");
|
|
855
|
+
console.log(`Toolkit: ${link.toolkit ?? toolkit ?? "unknown"}`);
|
|
856
|
+
console.log(`User: ${link.user_id ?? "unknown"}`);
|
|
857
|
+
console.log(`URL: ${link.redirect_url}`);
|
|
858
|
+
|
|
859
|
+
if (link.expires_at) {
|
|
860
|
+
console.log(`Expires: ${link.expires_at}`);
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
if (link.connected_account_id) {
|
|
864
|
+
console.log(`Account: ${link.connected_account_id}`);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
throw new Error("Usage: agentkit integrations status | connect composio [--toolkit <slug>] [--callback-url <url>] [--api <url>]");
|
|
871
|
+
}
|
|
872
|
+
|
|
767
873
|
if (args.command === "env") {
|
|
768
874
|
const [subcommand, name, ...valueParts] = args.positional;
|
|
769
875
|
const root = await findAgentCapsuleRoot(process.cwd());
|
|
@@ -1078,6 +1184,30 @@ function printJson(value: unknown): void {
|
|
|
1078
1184
|
console.log(JSON.stringify(value, null, 2));
|
|
1079
1185
|
}
|
|
1080
1186
|
|
|
1187
|
+
function printSkillStatus(status: Awaited<ReturnType<typeof checkDefaultSkillStatus>>): void {
|
|
1188
|
+
console.log("AgentKit skills");
|
|
1189
|
+
console.log(`Status: ${status.status}`);
|
|
1190
|
+
console.log(`Checked: ${status.checked}`);
|
|
1191
|
+
|
|
1192
|
+
if (status.missing.length > 0) {
|
|
1193
|
+
console.log(`Missing: ${status.missing.length}`);
|
|
1194
|
+
for (const file of status.missing.slice(0, 10)) {
|
|
1195
|
+
console.log(` ${file}`);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
if (status.outdated.length > 0) {
|
|
1200
|
+
console.log(`Outdated: ${status.outdated.length}`);
|
|
1201
|
+
for (const file of status.outdated.slice(0, 10)) {
|
|
1202
|
+
console.log(` ${file}`);
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
if (status.status !== "current") {
|
|
1207
|
+
console.log("Run: npm run agentkit -- skills sync");
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1081
1211
|
async function printJsonOrWrite(value: unknown, outFlag: string | boolean | undefined, usage: string): Promise<void> {
|
|
1082
1212
|
const outPath = parseOptionalStringFlag(outFlag, "out", usage);
|
|
1083
1213
|
|
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);
|