@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
package/src/index.ts
CHANGED
|
@@ -145,6 +145,30 @@ export type WhatsappChannelConfig = {
|
|
|
145
145
|
|
|
146
146
|
export type AgentChannel = WebsiteChannelConfig | TelegramChannelConfig | WhatsappChannelConfig;
|
|
147
147
|
|
|
148
|
+
export type IntegrationTagsConfig = {
|
|
149
|
+
enable?: string[];
|
|
150
|
+
disable?: string[];
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export type ComposioManagedIntegrationInput = {
|
|
154
|
+
name?: string;
|
|
155
|
+
toolkits: string[];
|
|
156
|
+
tools?: Record<string, string[]>;
|
|
157
|
+
tags?: IntegrationTagsConfig;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export type ComposioManagedIntegration = {
|
|
161
|
+
type: "composio";
|
|
162
|
+
provider: "composio";
|
|
163
|
+
mode: "managed";
|
|
164
|
+
name: string;
|
|
165
|
+
toolkits: string[];
|
|
166
|
+
tools?: Record<string, string[]>;
|
|
167
|
+
tags?: IntegrationTagsConfig;
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
export type AgentIntegration = ComposioManagedIntegration;
|
|
171
|
+
|
|
148
172
|
export type AgentDatabaseConfig =
|
|
149
173
|
| {
|
|
150
174
|
driver: "none";
|
|
@@ -316,6 +340,7 @@ export type AgentConfig = {
|
|
|
316
340
|
instructions: string;
|
|
317
341
|
secrets: string[];
|
|
318
342
|
tools?: AgentTool[];
|
|
343
|
+
integrations?: AgentIntegration[];
|
|
319
344
|
channels?: AgentChannel[];
|
|
320
345
|
transcription?: AgentTranscriptionConfig;
|
|
321
346
|
knowledge?: AgentKnowledgeConfig;
|
|
@@ -338,6 +363,23 @@ export function defineTool<Input = unknown, Output = unknown>(tool: AgentTool<In
|
|
|
338
363
|
return tool;
|
|
339
364
|
}
|
|
340
365
|
|
|
366
|
+
export function composioManaged(input: ComposioManagedIntegrationInput): ComposioManagedIntegration {
|
|
367
|
+
const name = normalizeIntegrationName(input.name ?? "composio", "composio integration name");
|
|
368
|
+
const toolkits = normalizeToolkitList(input.toolkits, "composioManaged.toolkits");
|
|
369
|
+
const tools = input.tools ? normalizeComposioToolMap(input.tools, toolkits) : undefined;
|
|
370
|
+
const tags = input.tags ? normalizeIntegrationTags(input.tags) : undefined;
|
|
371
|
+
|
|
372
|
+
return {
|
|
373
|
+
type: "composio",
|
|
374
|
+
provider: "composio",
|
|
375
|
+
mode: "managed",
|
|
376
|
+
name,
|
|
377
|
+
toolkits,
|
|
378
|
+
...(tools ? { tools } : {}),
|
|
379
|
+
...(tags ? { tags } : {}),
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
341
383
|
export function websiteChannel(input: WebsiteChannelInput): WebsiteChannelConfig {
|
|
342
384
|
return {
|
|
343
385
|
type: "website",
|
|
@@ -404,6 +446,109 @@ function normalizeChannelSecrets(secrets: string[], context: string): string[] {
|
|
|
404
446
|
return Array.from(uniqueSecrets).sort();
|
|
405
447
|
}
|
|
406
448
|
|
|
449
|
+
function normalizeIntegrationName(value: string, context: string): string {
|
|
450
|
+
const name = value.trim();
|
|
451
|
+
|
|
452
|
+
if (!/^[a-z][a-z0-9-]*$/.test(name)) {
|
|
453
|
+
throw new Error(`${context} must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
return name;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function normalizeToolkitList(values: string[], context: string): string[] {
|
|
460
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
461
|
+
throw new Error(`${context} must include at least one toolkit slug.`);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const toolkits = new Set<string>();
|
|
465
|
+
|
|
466
|
+
for (const value of values) {
|
|
467
|
+
if (typeof value !== "string") {
|
|
468
|
+
throw new Error(`${context} entries must be toolkit slug strings.`);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const toolkit = value.trim().toLowerCase();
|
|
472
|
+
|
|
473
|
+
if (!/^[a-z][a-z0-9_-]*$/.test(toolkit)) {
|
|
474
|
+
throw new Error(`${context} entries must start with a letter and contain only letters, numbers, underscores, and hyphens.`);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
toolkits.add(toolkit);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return Array.from(toolkits).sort();
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function normalizeComposioToolMap(values: Record<string, string[]>, toolkits: string[]): Record<string, string[]> | undefined {
|
|
484
|
+
const toolkitSet = new Set(toolkits);
|
|
485
|
+
const normalized: Record<string, string[]> = {};
|
|
486
|
+
|
|
487
|
+
for (const [rawToolkit, rawTools] of Object.entries(values)) {
|
|
488
|
+
const toolkit = rawToolkit.trim().toLowerCase();
|
|
489
|
+
|
|
490
|
+
if (!toolkitSet.has(toolkit)) {
|
|
491
|
+
throw new Error(`composioManaged.tools.${rawToolkit} must reference a toolkit listed in composioManaged.toolkits.`);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if (!Array.isArray(rawTools) || rawTools.length === 0) {
|
|
495
|
+
throw new Error(`composioManaged.tools.${rawToolkit} must include at least one Composio action slug.`);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
const tools = new Set<string>();
|
|
499
|
+
|
|
500
|
+
for (const rawTool of rawTools) {
|
|
501
|
+
if (typeof rawTool !== "string") {
|
|
502
|
+
throw new Error(`composioManaged.tools.${rawToolkit} entries must be Composio action slug strings.`);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const tool = rawTool.trim().toUpperCase();
|
|
506
|
+
|
|
507
|
+
if (!/^[A-Z][A-Z0-9_]*$/.test(tool)) {
|
|
508
|
+
throw new Error(`composioManaged.tools.${rawToolkit} entries must be uppercase Composio action slugs.`);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
tools.add(tool);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
normalized[toolkit] = Array.from(tools).sort();
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
function normalizeIntegrationTags(tags: IntegrationTagsConfig): IntegrationTagsConfig {
|
|
521
|
+
const normalized: IntegrationTagsConfig = {};
|
|
522
|
+
|
|
523
|
+
if (tags.enable !== undefined) {
|
|
524
|
+
normalized.enable = normalizeTagList(tags.enable, "composioManaged.tags.enable");
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (tags.disable !== undefined) {
|
|
528
|
+
normalized.disable = normalizeTagList(tags.disable, "composioManaged.tags.disable");
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
return normalized;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
function normalizeTagList(values: string[], context: string): string[] {
|
|
535
|
+
if (!Array.isArray(values)) {
|
|
536
|
+
throw new Error(`${context} must be an array of tag strings.`);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
return Array.from(
|
|
540
|
+
new Set(
|
|
541
|
+
values.map((value) => {
|
|
542
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
543
|
+
throw new Error(`${context} entries must be non-empty strings.`);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return value.trim();
|
|
547
|
+
}),
|
|
548
|
+
),
|
|
549
|
+
).sort();
|
|
550
|
+
}
|
|
551
|
+
|
|
407
552
|
function normalizeChannelBuffer(input: ChannelBufferInput, context: string): ChannelBufferConfig {
|
|
408
553
|
if (input.mode === "off") {
|
|
409
554
|
return { mode: "off" };
|
package/src/runtime/chat.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { loadAgentCapsule } from "./config";
|
|
|
7
7
|
import { openPreparedCapsuleStore } from "./database";
|
|
8
8
|
import { loadCapsuleEnv } from "./env";
|
|
9
9
|
import { AgentKitError, isAgentKitError } from "./errors";
|
|
10
|
+
import { createManagedComposioTools } from "./integrations/composio";
|
|
10
11
|
import { syncConfiguredKnowledgeSources } from "./knowledge/ingest";
|
|
11
12
|
import { appendKnowledgePromptPolicy } from "./knowledge/prompt-policy";
|
|
12
13
|
import { createKnowledgeSearchTool } from "./knowledge/tool";
|
|
@@ -145,7 +146,7 @@ export async function runAgentMessage(
|
|
|
145
146
|
}
|
|
146
147
|
|
|
147
148
|
function withKnowledgeTools(capsule: LoadedAgentCapsule): NonNullable<LoadedAgentCapsule["config"]["tools"]> {
|
|
148
|
-
const tools = [...(capsule.config.tools ?? [])];
|
|
149
|
+
const tools = [...createManagedComposioTools(capsule.config), ...(capsule.config.tools ?? [])];
|
|
149
150
|
const knowledgeTool = createKnowledgeSearchTool(capsule);
|
|
150
151
|
|
|
151
152
|
if (knowledgeTool) {
|
package/src/runtime/config.ts
CHANGED
|
@@ -16,9 +16,11 @@ import type {
|
|
|
16
16
|
TelegramAllowedUpdate,
|
|
17
17
|
AgentKnowledgeEmbeddingProvider,
|
|
18
18
|
ChannelBufferMode,
|
|
19
|
+
AgentIntegration,
|
|
19
20
|
ChannelAudioMode,
|
|
20
21
|
TranscriptionProviderName,
|
|
21
22
|
} from "../index";
|
|
23
|
+
import { MANAGED_COMPOSIO_TOOL_NAME } from "./integrations/composio";
|
|
22
24
|
import { AgentKitError } from "./errors";
|
|
23
25
|
import { isValidTimeZone } from "./prompt-context";
|
|
24
26
|
|
|
@@ -35,6 +37,9 @@ const TELEGRAM_ALLOWED_UPDATES = new Set<TelegramAllowedUpdate>(["message"]);
|
|
|
35
37
|
const KNOWLEDGE_EMBEDDING_PROVIDERS = new Set<AgentKnowledgeEmbeddingProvider>(["none", "test", "openai"]);
|
|
36
38
|
const TRANSCRIPTION_PROVIDERS = new Set<TranscriptionProviderName>(["test", "openai", "groq"]);
|
|
37
39
|
const CHANNEL_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
40
|
+
const INTEGRATION_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
41
|
+
const COMPOSIO_TOOLKIT_PATTERN = /^[a-z][a-z0-9_-]*$/;
|
|
42
|
+
const COMPOSIO_TOOL_SLUG_PATTERN = /^[A-Z][A-Z0-9_]*$/;
|
|
38
43
|
const SECRET_NAME_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
|
|
39
44
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
40
45
|
let configImportNonce = 0;
|
|
@@ -234,6 +239,7 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
|
|
|
234
239
|
}
|
|
235
240
|
}
|
|
236
241
|
|
|
242
|
+
validateIntegrations(value.integrations, value.runtime as AgentRuntime, value.tools);
|
|
237
243
|
validateTranscriptionConfig(value.transcription);
|
|
238
244
|
validateChannels(value.channels, value.runtime as AgentRuntime, Boolean(value.transcription));
|
|
239
245
|
validateKnowledgeConfig(value.knowledge);
|
|
@@ -258,6 +264,129 @@ function validateAgentConfig(value: unknown): asserts value is AgentConfig {
|
|
|
258
264
|
validateFilesConfig(value.storage.files);
|
|
259
265
|
}
|
|
260
266
|
|
|
267
|
+
function validateIntegrations(
|
|
268
|
+
value: unknown,
|
|
269
|
+
runtime: AgentRuntime,
|
|
270
|
+
tools: AgentConfig["tools"] = [],
|
|
271
|
+
): void {
|
|
272
|
+
if (value === undefined) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (!Array.isArray(value)) {
|
|
277
|
+
throw invalidConfig("integrations must be an array when provided.");
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (value.length > 0 && runtime !== "edge") {
|
|
281
|
+
throw invalidConfig('managed integrations require runtime: "edge". Use BYO defineTool wrappers for local-only integrations.');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
let composioCount = 0;
|
|
285
|
+
|
|
286
|
+
for (const [index, integration] of value.entries()) {
|
|
287
|
+
if (!isRecord(integration)) {
|
|
288
|
+
throw invalidConfig(`integrations[${index}] must be an object.`);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (integration.provider !== "composio" || integration.type !== "composio" || integration.mode !== "managed") {
|
|
292
|
+
throw invalidConfig(`integrations[${index}] must be composioManaged({...}) or { type: "composio", provider: "composio", mode: "managed", ... }.`);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
composioCount += 1;
|
|
296
|
+
validateComposioManagedIntegration(integration as unknown as AgentIntegration, index);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (composioCount > 1) {
|
|
300
|
+
throw invalidConfig("Only one managed Composio integration is supported per agent.");
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const hasExplicitComposioTools = value.some(
|
|
304
|
+
(integration) => isRecord(integration) && integration.provider === "composio" && isRecord(integration.tools),
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
if (hasExplicitComposioTools && tools.some((tool) => isRecord(tool) && tool.name === MANAGED_COMPOSIO_TOOL_NAME)) {
|
|
308
|
+
throw invalidConfig(`tools must not declare reserved managed Composio tool name "${MANAGED_COMPOSIO_TOOL_NAME}".`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function validateComposioManagedIntegration(value: AgentIntegration, index: number): void {
|
|
313
|
+
expectString(value.name, `integrations[${index}].name`);
|
|
314
|
+
|
|
315
|
+
if (!INTEGRATION_NAME_PATTERN.test(value.name)) {
|
|
316
|
+
throw invalidConfig(`integrations[${index}].name must start with a lowercase letter and contain only lowercase letters, numbers, and hyphens.`);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (!Array.isArray(value.toolkits) || value.toolkits.length === 0) {
|
|
320
|
+
throw invalidConfig(`integrations[${index}].toolkits must include at least one Composio toolkit slug.`);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const toolkits = new Set<string>();
|
|
324
|
+
|
|
325
|
+
for (const [toolkitIndex, toolkit] of value.toolkits.entries()) {
|
|
326
|
+
expectString(toolkit, `integrations[${index}].toolkits[${toolkitIndex}]`);
|
|
327
|
+
|
|
328
|
+
if (!COMPOSIO_TOOLKIT_PATTERN.test(toolkit)) {
|
|
329
|
+
throw invalidConfig(`integrations[${index}].toolkits[${toolkitIndex}] must be a lowercase Composio toolkit slug.`);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (toolkits.has(toolkit)) {
|
|
333
|
+
throw invalidConfig(`integrations[${index}].toolkits must not contain duplicates.`);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
toolkits.add(toolkit);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (value.tools !== undefined) {
|
|
340
|
+
if (!isRecord(value.tools)) {
|
|
341
|
+
throw invalidConfig(`integrations[${index}].tools must be an object when provided.`);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
for (const [toolkit, tools] of Object.entries(value.tools)) {
|
|
345
|
+
if (!toolkits.has(toolkit)) {
|
|
346
|
+
throw invalidConfig(`integrations[${index}].tools.${toolkit} must reference a toolkit listed in integrations[${index}].toolkits.`);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (!Array.isArray(tools) || tools.length === 0) {
|
|
350
|
+
throw invalidConfig(`integrations[${index}].tools.${toolkit} must include at least one Composio action slug.`);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const seenTools = new Set<string>();
|
|
354
|
+
|
|
355
|
+
for (const [toolIndex, tool] of tools.entries()) {
|
|
356
|
+
expectString(tool, `integrations[${index}].tools.${toolkit}[${toolIndex}]`);
|
|
357
|
+
|
|
358
|
+
if (!COMPOSIO_TOOL_SLUG_PATTERN.test(tool)) {
|
|
359
|
+
throw invalidConfig(`integrations[${index}].tools.${toolkit}[${toolIndex}] must be an uppercase Composio action slug.`);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (seenTools.has(tool)) {
|
|
363
|
+
throw invalidConfig(`integrations[${index}].tools.${toolkit} must not contain duplicates.`);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
seenTools.add(tool);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (value.tags !== undefined) {
|
|
372
|
+
validateIntegrationTags(value.tags, `integrations[${index}].tags`);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function validateIntegrationTags(value: unknown, label: string): void {
|
|
377
|
+
if (!isRecord(value)) {
|
|
378
|
+
throw invalidConfig(`${label} must be an object when provided.`);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (value.enable !== undefined) {
|
|
382
|
+
expectStringArray(value.enable, `${label}.enable`);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (value.disable !== undefined) {
|
|
386
|
+
expectStringArray(value.disable, `${label}.disable`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
261
390
|
function validateTranscriptionConfig(value: unknown): void {
|
|
262
391
|
if (value === undefined) {
|
|
263
392
|
return;
|
|
@@ -2,6 +2,11 @@ import { relative, resolve } from "node:path";
|
|
|
2
2
|
|
|
3
3
|
import type { AgentConfig, AgentTool } from "../../index";
|
|
4
4
|
import type { LoadedAgentCapsule } from "../config";
|
|
5
|
+
import {
|
|
6
|
+
createManagedComposioTools,
|
|
7
|
+
managedComposioRequiredSecrets,
|
|
8
|
+
resolveManagedComposioIntegrations,
|
|
9
|
+
} from "../integrations/composio";
|
|
5
10
|
import { resolveKnowledgeConfig } from "../knowledge/config";
|
|
6
11
|
import { KNOWLEDGE_SEARCH_TOOL_NAME } from "../knowledge/tool";
|
|
7
12
|
import { resolveTranscriptionConfig } from "../transcription";
|
|
@@ -28,6 +33,14 @@ export type SharedAgentManifest = {
|
|
|
28
33
|
permissions: string[];
|
|
29
34
|
timeoutMs: number | null;
|
|
30
35
|
}>;
|
|
36
|
+
integrations: Array<{
|
|
37
|
+
name: string;
|
|
38
|
+
provider: "composio";
|
|
39
|
+
mode: "managed";
|
|
40
|
+
toolkits: string[];
|
|
41
|
+
tools: string[];
|
|
42
|
+
userId: string;
|
|
43
|
+
}>;
|
|
31
44
|
channels: NonNullable<AgentConfig["channels"]>;
|
|
32
45
|
transcription: {
|
|
33
46
|
enabled: boolean;
|
|
@@ -94,6 +107,8 @@ export function buildSharedAgentManifest(
|
|
|
94
107
|
const database = buildDatabaseManifest(capsule, options.databaseSchema ?? null);
|
|
95
108
|
const files = buildFilesManifest(capsule);
|
|
96
109
|
const knowledge = resolveKnowledgeConfig(capsule.config);
|
|
110
|
+
const integrationTools = createManagedComposioTools(capsule.config);
|
|
111
|
+
const tools = [...integrationTools, ...(capsule.config.tools ?? [])];
|
|
97
112
|
const transcription = resolveTranscriptionConfig(capsule.config.transcription);
|
|
98
113
|
|
|
99
114
|
requiredSecrets.add("AGENTKIT_PRIVATE_TOKEN");
|
|
@@ -119,7 +134,11 @@ export function buildSharedAgentManifest(
|
|
|
119
134
|
requiredSecrets.add(transcription.secret);
|
|
120
135
|
}
|
|
121
136
|
|
|
122
|
-
for (const
|
|
137
|
+
for (const secret of managedComposioRequiredSecrets(capsule.config)) {
|
|
138
|
+
requiredSecrets.add(secret);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
for (const tool of tools) {
|
|
123
142
|
for (const secret of tool.secrets ?? []) {
|
|
124
143
|
requiredSecrets.add(secret);
|
|
125
144
|
}
|
|
@@ -139,7 +158,7 @@ export function buildSharedAgentManifest(
|
|
|
139
158
|
timeZone: capsule.config.timeZone ?? null,
|
|
140
159
|
prompt: toCapsulePath(capsule, capsule.instructionsPath),
|
|
141
160
|
secrets: Array.from(requiredSecrets).sort(),
|
|
142
|
-
tools:
|
|
161
|
+
tools: tools.map((tool) => ({
|
|
143
162
|
name: tool.name,
|
|
144
163
|
description: tool.description,
|
|
145
164
|
inputSchema: tool.inputSchema,
|
|
@@ -148,6 +167,14 @@ export function buildSharedAgentManifest(
|
|
|
148
167
|
permissions: [...(tool.permissions ?? [])].sort(),
|
|
149
168
|
timeoutMs: tool.timeoutMs ?? null,
|
|
150
169
|
})),
|
|
170
|
+
integrations: resolveManagedComposioIntegrations(capsule.config).map((integration) => ({
|
|
171
|
+
name: integration.name,
|
|
172
|
+
provider: integration.provider,
|
|
173
|
+
mode: integration.mode,
|
|
174
|
+
toolkits: integration.toolkits,
|
|
175
|
+
tools: integration.allowedTools,
|
|
176
|
+
userId: integration.userId,
|
|
177
|
+
})),
|
|
151
178
|
channels: capsule.config.channels ?? [],
|
|
152
179
|
transcription: {
|
|
153
180
|
enabled: transcription.enabled,
|
|
@@ -3,6 +3,10 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
import { loadAgentCapsule } from "./config";
|
|
4
4
|
import { buildSharedAgentManifest } from "./core/manifest";
|
|
5
5
|
import { listCapsuleEnv } from "./env";
|
|
6
|
+
import {
|
|
7
|
+
MANAGED_COMPOSIO_API_KEY_SECRET,
|
|
8
|
+
resolveManagedComposioIntegrations,
|
|
9
|
+
} from "./integrations/composio";
|
|
6
10
|
|
|
7
11
|
export type DeployReadinessSecretSource = {
|
|
8
12
|
dotenv: boolean;
|
|
@@ -30,6 +34,14 @@ export type DeployReadinessContext = {
|
|
|
30
34
|
embeddingProvider: string;
|
|
31
35
|
databaseDriver: "none" | "turso";
|
|
32
36
|
};
|
|
37
|
+
integrations: {
|
|
38
|
+
managedComposio: {
|
|
39
|
+
enabled: boolean;
|
|
40
|
+
toolkits: string[];
|
|
41
|
+
toolCount: number;
|
|
42
|
+
userId: string | null;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
33
45
|
};
|
|
34
46
|
|
|
35
47
|
export async function loadDeployReadinessContext(
|
|
@@ -38,6 +50,7 @@ export async function loadDeployReadinessContext(
|
|
|
38
50
|
): Promise<DeployReadinessContext> {
|
|
39
51
|
const capsule = await loadAgentCapsule(cwd);
|
|
40
52
|
const manifest = buildSharedAgentManifest(capsule);
|
|
53
|
+
const managedComposio = resolveManagedComposioIntegrations(capsule.config)[0];
|
|
41
54
|
const dotenvNames = new Set(await listCapsuleEnv(capsule.root));
|
|
42
55
|
const requiredSecrets = manifest.secrets;
|
|
43
56
|
const localSecrets: Record<string, DeployReadinessSecretSource> = {};
|
|
@@ -57,6 +70,7 @@ export async function loadDeployReadinessContext(
|
|
|
57
70
|
isAgentKitManagedDeploySecret(name, {
|
|
58
71
|
accessMode: capsule.config.access.mode,
|
|
59
72
|
databaseDriver: manifest.storage.database.driver,
|
|
73
|
+
managedComposioEnabled: Boolean(managedComposio),
|
|
60
74
|
}),
|
|
61
75
|
);
|
|
62
76
|
const managed = new Set(agentKitManagedSecrets);
|
|
@@ -82,6 +96,14 @@ export async function loadDeployReadinessContext(
|
|
|
82
96
|
embeddingProvider: manifest.knowledge.embedding.provider,
|
|
83
97
|
databaseDriver: manifest.storage.database.driver,
|
|
84
98
|
},
|
|
99
|
+
integrations: {
|
|
100
|
+
managedComposio: {
|
|
101
|
+
enabled: Boolean(managedComposio),
|
|
102
|
+
toolkits: managedComposio?.toolkits ?? [],
|
|
103
|
+
toolCount: managedComposio?.allowedTools.length ?? 0,
|
|
104
|
+
userId: managedComposio?.userId ?? null,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
85
107
|
};
|
|
86
108
|
}
|
|
87
109
|
|
|
@@ -91,7 +113,11 @@ export function stableCloudProjectId(name: string, accountId?: string | null): s
|
|
|
91
113
|
|
|
92
114
|
function isAgentKitManagedDeploySecret(
|
|
93
115
|
name: string,
|
|
94
|
-
context: {
|
|
116
|
+
context: {
|
|
117
|
+
accessMode: DeployReadinessContext["accessMode"];
|
|
118
|
+
databaseDriver: "none" | "turso";
|
|
119
|
+
managedComposioEnabled: boolean;
|
|
120
|
+
},
|
|
95
121
|
): boolean {
|
|
96
122
|
if (context.databaseDriver === "turso" && (name === "TURSO_DATABASE_URL" || name === "TURSO_AUTH_TOKEN")) {
|
|
97
123
|
return true;
|
|
@@ -101,5 +127,9 @@ function isAgentKitManagedDeploySecret(
|
|
|
101
127
|
return true;
|
|
102
128
|
}
|
|
103
129
|
|
|
130
|
+
if (context.managedComposioEnabled && name === MANAGED_COMPOSIO_API_KEY_SECRET) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
|
|
104
134
|
return false;
|
|
105
135
|
}
|
package/src/runtime/inspect.ts
CHANGED
|
@@ -4,9 +4,15 @@ import type { AgentChannel, AgentProvider, AgentRuntime, AccessMode } from "../i
|
|
|
4
4
|
import type { LoadedAgentCapsule } from "./config";
|
|
5
5
|
import { loadAgentCapsule } from "./config";
|
|
6
6
|
import { loadCapsuleEnv } from "./env";
|
|
7
|
+
import {
|
|
8
|
+
createManagedComposioTools,
|
|
9
|
+
managedComposioRequiredSecrets,
|
|
10
|
+
resolveManagedComposioIntegrations,
|
|
11
|
+
} from "./integrations/composio";
|
|
7
12
|
import { resolveKnowledgeConfig } from "./knowledge/config";
|
|
8
13
|
import { KNOWLEDGE_SEARCH_TOOL_NAME } from "./knowledge/tool";
|
|
9
14
|
import { resolveRuntimeTimeZone } from "./prompt-context";
|
|
15
|
+
import { checkDefaultSkillStatus, type DefaultSkillStatus } from "./skills";
|
|
10
16
|
import { resolveTranscriptionConfig } from "./transcription";
|
|
11
17
|
|
|
12
18
|
export type SecretState = "set" | "missing";
|
|
@@ -21,6 +27,7 @@ export type AgentInspectState = {
|
|
|
21
27
|
};
|
|
22
28
|
prompt: string;
|
|
23
29
|
tools: string[];
|
|
30
|
+
integrations: AgentInspectIntegration[];
|
|
24
31
|
channels: AgentInspectChannel[];
|
|
25
32
|
transcription: {
|
|
26
33
|
enabled: boolean;
|
|
@@ -71,6 +78,8 @@ export type AgentInspectState = {
|
|
|
71
78
|
secrets: Record<string, SecretState>;
|
|
72
79
|
managedSecrets: string[];
|
|
73
80
|
userSecrets: string[];
|
|
81
|
+
skills: AgentInspectSkills;
|
|
82
|
+
warnings: AgentInspectWarning[];
|
|
74
83
|
};
|
|
75
84
|
|
|
76
85
|
export type AgentInspectDatabase = {
|
|
@@ -97,23 +106,48 @@ export type AgentInspectChannel = {
|
|
|
97
106
|
audio?: AgentChannel["audio"];
|
|
98
107
|
};
|
|
99
108
|
|
|
109
|
+
export type AgentInspectSkills = {
|
|
110
|
+
status: "current" | "missing" | "outdated" | "not_checked";
|
|
111
|
+
checked: number;
|
|
112
|
+
missing: string[];
|
|
113
|
+
outdated: string[];
|
|
114
|
+
syncCommand: string | null;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export type AgentInspectWarning = {
|
|
118
|
+
code: string;
|
|
119
|
+
message: string;
|
|
120
|
+
command?: string;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export type AgentInspectIntegration = {
|
|
124
|
+
name: string;
|
|
125
|
+
provider: "composio";
|
|
126
|
+
mode: "managed";
|
|
127
|
+
toolkits: string[];
|
|
128
|
+
tools: string[];
|
|
129
|
+
userId: string;
|
|
130
|
+
};
|
|
131
|
+
|
|
100
132
|
export async function inspectAgentCapsule(
|
|
101
133
|
cwd = process.cwd(),
|
|
102
134
|
env: Record<string, string | undefined> = process.env,
|
|
103
135
|
): Promise<AgentInspectState> {
|
|
104
136
|
const capsule = await loadAgentCapsule(cwd);
|
|
105
|
-
return buildInspectState(capsule, await loadCapsuleEnv(capsule.root, env));
|
|
137
|
+
return buildInspectState(capsule, await loadCapsuleEnv(capsule.root, env), await checkDefaultSkillStatus(capsule.root));
|
|
106
138
|
}
|
|
107
139
|
|
|
108
140
|
export function buildInspectState(
|
|
109
141
|
capsule: LoadedAgentCapsule,
|
|
110
142
|
env: Record<string, string | undefined> = process.env,
|
|
143
|
+
skillStatus: DefaultSkillStatus | null = null,
|
|
111
144
|
): AgentInspectState {
|
|
112
145
|
const declaredSecrets = new Set(capsule.config.secrets);
|
|
113
146
|
const knowledge = resolveKnowledgeConfig(capsule.config);
|
|
147
|
+
const integrationTools = createManagedComposioTools(capsule.config);
|
|
114
148
|
const transcription = resolveTranscriptionConfig(capsule.config.transcription);
|
|
115
149
|
|
|
116
|
-
for (const tool of capsule.config.tools ?? []) {
|
|
150
|
+
for (const tool of [...integrationTools, ...(capsule.config.tools ?? [])]) {
|
|
117
151
|
for (const secret of tool.secrets ?? []) {
|
|
118
152
|
declaredSecrets.add(secret);
|
|
119
153
|
}
|
|
@@ -134,7 +168,10 @@ export function buildInspectState(
|
|
|
134
168
|
}
|
|
135
169
|
|
|
136
170
|
const managedSecrets = managedCloudSecrets(capsule);
|
|
137
|
-
const
|
|
171
|
+
const managedSecretSet = new Set(managedSecrets);
|
|
172
|
+
const userSecrets = Array.from(declaredSecrets)
|
|
173
|
+
.filter((secret) => !managedSecretSet.has(secret))
|
|
174
|
+
.sort();
|
|
138
175
|
const secrets: Record<string, SecretState> = {};
|
|
139
176
|
|
|
140
177
|
for (const secret of userSecrets) {
|
|
@@ -143,6 +180,9 @@ export function buildInspectState(
|
|
|
143
180
|
|
|
144
181
|
const database = inspectDatabase(capsule);
|
|
145
182
|
|
|
183
|
+
const skills = inspectSkills(skillStatus);
|
|
184
|
+
const warnings = inspectWarnings(capsule, transcription, skills);
|
|
185
|
+
|
|
146
186
|
return {
|
|
147
187
|
agent: capsule.config.name,
|
|
148
188
|
runtime: capsule.config.runtime,
|
|
@@ -155,7 +195,15 @@ export function buildInspectState(
|
|
|
155
195
|
}),
|
|
156
196
|
},
|
|
157
197
|
prompt: toCapsulePath(capsule.root, capsule.instructionsPath),
|
|
158
|
-
tools: (capsule.config.tools ?? []).map((tool) => tool.name),
|
|
198
|
+
tools: [...integrationTools, ...(capsule.config.tools ?? [])].map((tool) => tool.name),
|
|
199
|
+
integrations: resolveManagedComposioIntegrations(capsule.config).map((integration) => ({
|
|
200
|
+
name: integration.name,
|
|
201
|
+
provider: integration.provider,
|
|
202
|
+
mode: integration.mode,
|
|
203
|
+
toolkits: integration.toolkits,
|
|
204
|
+
tools: integration.allowedTools,
|
|
205
|
+
userId: integration.userId,
|
|
206
|
+
})),
|
|
159
207
|
channels: (capsule.config.channels ?? []).map((channel) => ({
|
|
160
208
|
name: channel.name,
|
|
161
209
|
type: channel.type,
|
|
@@ -208,6 +256,8 @@ export function buildInspectState(
|
|
|
208
256
|
secrets,
|
|
209
257
|
managedSecrets,
|
|
210
258
|
userSecrets,
|
|
259
|
+
skills,
|
|
260
|
+
warnings,
|
|
211
261
|
};
|
|
212
262
|
}
|
|
213
263
|
|
|
@@ -237,6 +287,56 @@ function inspectDatabase(capsule: LoadedAgentCapsule): AgentInspectDatabase {
|
|
|
237
287
|
};
|
|
238
288
|
}
|
|
239
289
|
|
|
290
|
+
function inspectSkills(status: DefaultSkillStatus | null): AgentInspectSkills {
|
|
291
|
+
if (!status) {
|
|
292
|
+
return {
|
|
293
|
+
status: "not_checked",
|
|
294
|
+
checked: 0,
|
|
295
|
+
missing: [],
|
|
296
|
+
outdated: [],
|
|
297
|
+
syncCommand: null,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return {
|
|
302
|
+
status: status.status,
|
|
303
|
+
checked: status.checked,
|
|
304
|
+
missing: status.missing,
|
|
305
|
+
outdated: status.outdated,
|
|
306
|
+
syncCommand: status.status === "current" ? null : "npm run agentkit -- skills sync",
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function inspectWarnings(
|
|
311
|
+
capsule: LoadedAgentCapsule,
|
|
312
|
+
transcription: ReturnType<typeof resolveTranscriptionConfig>,
|
|
313
|
+
skills: AgentInspectSkills,
|
|
314
|
+
): AgentInspectWarning[] {
|
|
315
|
+
const warnings: AgentInspectWarning[] = [];
|
|
316
|
+
|
|
317
|
+
if (skills.status === "missing" || skills.status === "outdated") {
|
|
318
|
+
warnings.push({
|
|
319
|
+
code: "local_skills_outdated",
|
|
320
|
+
message: "Local AgentKit skills are older than or missing from the installed package docs.",
|
|
321
|
+
command: "npm run agentkit -- skills sync",
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (
|
|
326
|
+
transcription.enabled &&
|
|
327
|
+
transcription.provider === "openai" &&
|
|
328
|
+
(capsule.config.channels ?? []).some((channel) => channel.type === "telegram" && channel.audio?.mode === "transcribe")
|
|
329
|
+
) {
|
|
330
|
+
warnings.push({
|
|
331
|
+
code: "telegram_audio_openai_format",
|
|
332
|
+
message: "Telegram voice notes arrive as OGG/Opus; use Groq for the default Telegram voice-note transcription path.",
|
|
333
|
+
command: "Set transcription.provider to \"groq\" and secret to \"GROQ_API_KEY\".",
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return warnings;
|
|
338
|
+
}
|
|
339
|
+
|
|
240
340
|
function managedCloudSecrets(capsule: LoadedAgentCapsule): string[] {
|
|
241
341
|
const secrets = new Set<string>();
|
|
242
342
|
|
|
@@ -245,5 +345,9 @@ function managedCloudSecrets(capsule: LoadedAgentCapsule): string[] {
|
|
|
245
345
|
secrets.add("TURSO_DATABASE_URL");
|
|
246
346
|
}
|
|
247
347
|
|
|
348
|
+
for (const secret of managedComposioRequiredSecrets(capsule.config)) {
|
|
349
|
+
secrets.add(secret);
|
|
350
|
+
}
|
|
351
|
+
|
|
248
352
|
return Array.from(secrets).sort();
|
|
249
353
|
}
|