@botpress/adk 1.17.0 → 1.18.0-beta.2
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/dist/agent-init/agent-project-generator.d.ts +32 -8
- package/dist/agent-init/agent-project-generator.d.ts.map +1 -1
- package/dist/agent-init/index.d.ts +1 -0
- package/dist/agent-init/index.d.ts.map +1 -1
- package/dist/agent-project/agent-project.d.ts +5 -1
- package/dist/agent-project/agent-project.d.ts.map +1 -1
- package/dist/agent-project/agent-resolver.d.ts +4 -3
- package/dist/agent-project/agent-resolver.d.ts.map +1 -1
- package/dist/agent-project/config-writer.d.ts +33 -0
- package/dist/agent-project/config-writer.d.ts.map +1 -1
- package/dist/agent-project/dependencies-parser.d.ts.map +1 -1
- package/dist/agent-project/index.d.ts +1 -1
- package/dist/agent-project/index.d.ts.map +1 -1
- package/dist/agent-project/types.d.ts +22 -4
- package/dist/agent-project/types.d.ts.map +1 -1
- package/dist/auth/credentials.d.ts.map +1 -1
- package/dist/bot-generator/dev-id-manager.d.ts.map +1 -1
- package/dist/bot-generator/generator.d.ts.map +1 -1
- package/dist/eval/index.d.ts +1 -1
- package/dist/eval/index.d.ts.map +1 -1
- package/dist/eval/loader.d.ts +2 -1
- package/dist/eval/loader.d.ts.map +1 -1
- package/dist/eval/types.d.ts +15 -2
- package/dist/eval/types.d.ts.map +1 -1
- package/dist/generators/tests.d.ts.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +704 -468
- package/dist/index.js.map +21 -21
- package/dist/integrations/checker.d.ts.map +1 -1
- package/dist/integrations/config-utils.d.ts +1 -0
- package/dist/integrations/config-utils.d.ts.map +1 -1
- package/dist/integrations/operations.d.ts +19 -6
- package/dist/integrations/operations.d.ts.map +1 -1
- package/dist/knowledge/manager.d.ts.map +1 -1
- package/dist/preflight/checker.d.ts.map +1 -1
- package/dist/templates/README.md +101 -0
- package/dist/templates/blank/README.md +36 -0
- package/dist/templates/blank/agent.config.ts +49 -0
- package/dist/templates/blank/package.json +17 -0
- package/dist/templates/blank/src/actions/index.ts +19 -0
- package/dist/templates/blank/src/conversations/index.ts +16 -0
- package/dist/templates/blank/src/knowledge/index.ts +17 -0
- package/dist/templates/blank/src/tables/index.ts +19 -0
- package/dist/templates/blank/src/triggers/index.ts +20 -0
- package/dist/templates/blank/src/workflows/index.ts +23 -0
- package/dist/templates/blank/tsconfig.json +22 -0
- package/dist/templates/crm-enrichment/README.md +85 -0
- package/dist/templates/crm-enrichment/agent.config.ts +33 -0
- package/dist/templates/crm-enrichment/package.json +17 -0
- package/dist/templates/crm-enrichment/src/actions/enrich-contact.ts +81 -0
- package/dist/templates/crm-enrichment/src/conversations/index.ts +14 -0
- package/dist/templates/crm-enrichment/src/knowledge/index.ts +17 -0
- package/dist/templates/crm-enrichment/src/tables/contacts.ts +43 -0
- package/dist/templates/crm-enrichment/src/triggers/daily-enrichment.ts +30 -0
- package/dist/templates/crm-enrichment/src/workflows/enrichment-pipeline.ts +171 -0
- package/dist/templates/crm-enrichment/tsconfig.json +22 -0
- package/dist/templates/hello-world/README.md +46 -0
- package/dist/templates/hello-world/agent.config.ts +48 -0
- package/dist/templates/hello-world/package.json +17 -0
- package/dist/templates/hello-world/src/actions/index.ts +19 -0
- package/dist/templates/hello-world/src/conversations/index.ts +10 -0
- package/dist/templates/hello-world/src/knowledge/index.ts +17 -0
- package/dist/templates/hello-world/src/tables/index.ts +19 -0
- package/dist/templates/hello-world/src/triggers/index.ts +20 -0
- package/dist/templates/hello-world/src/workflows/index.ts +23 -0
- package/dist/templates/hello-world/tsconfig.json +22 -0
- package/dist/templates/knowledge-assistant/README.md +66 -0
- package/dist/templates/knowledge-assistant/agent.config.ts +26 -0
- package/dist/templates/knowledge-assistant/package.json +17 -0
- package/dist/templates/knowledge-assistant/src/actions/index.ts +19 -0
- package/dist/templates/knowledge-assistant/src/actions/search-docs.ts +50 -0
- package/dist/templates/knowledge-assistant/src/conversations/index.ts +33 -0
- package/dist/templates/knowledge-assistant/src/knowledge/docs.ts +23 -0
- package/dist/templates/knowledge-assistant/src/knowledge/getting-started.md +49 -0
- package/dist/templates/knowledge-assistant/src/tables/index.ts +21 -0
- package/dist/templates/knowledge-assistant/src/triggers/index.ts +17 -0
- package/dist/templates/knowledge-assistant/src/workflows/index.ts +28 -0
- package/dist/templates/knowledge-assistant/tsconfig.json +22 -0
- package/dist/templates/slack-triage/README.md +74 -0
- package/dist/templates/slack-triage/agent.config.ts +35 -0
- package/dist/templates/slack-triage/evals/triage-basic.eval.ts +55 -0
- package/dist/templates/slack-triage/package.json +17 -0
- package/dist/templates/slack-triage/src/actions/classify-request.ts +65 -0
- package/dist/templates/slack-triage/src/conversations/slack-dm.ts +72 -0
- package/dist/templates/slack-triage/src/knowledge/team-directory.md +33 -0
- package/dist/templates/slack-triage/src/tables/routing-rules.ts +38 -0
- package/dist/templates/slack-triage/src/triggers/new-message.ts +44 -0
- package/dist/templates/slack-triage/src/workflows/triage-flow.ts +104 -0
- package/dist/templates/slack-triage/tsconfig.json +22 -0
- package/dist/templates/template.config.json +47 -0
- package/dist/utils/json-ordering.d.ts +1 -1
- package/dist/utils/json-ordering.d.ts.map +1 -1
- package/package.json +7 -15
package/dist/index.js
CHANGED
|
@@ -22,12 +22,15 @@ var init_types = __esm(() => {
|
|
|
22
22
|
integrationInterfaceAlias: z.string().optional()
|
|
23
23
|
});
|
|
24
24
|
dependenciesSchema = z.object({
|
|
25
|
-
integrations: z.record(z.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
integrations: z.record(z.union([
|
|
26
|
+
z.string(),
|
|
27
|
+
z.object({
|
|
28
|
+
version: z.string(),
|
|
29
|
+
enabled: z.boolean(),
|
|
30
|
+
configurationType: z.string().optional(),
|
|
31
|
+
config: z.record(z.any()).optional()
|
|
32
|
+
})
|
|
33
|
+
])).optional(),
|
|
31
34
|
plugins: z.record(z.object({
|
|
32
35
|
version: z.string(),
|
|
33
36
|
config: z.record(z.any()).optional(),
|
|
@@ -41,6 +44,9 @@ var init_types = __esm(() => {
|
|
|
41
44
|
devId: z.string().optional().describe("The development ID used during local development")
|
|
42
45
|
});
|
|
43
46
|
agentLocalInfoSchema = z.object({
|
|
47
|
+
botId: z.string().optional().describe("The bot ID (overrides agent.json for local development)"),
|
|
48
|
+
workspaceId: z.string().optional().describe("The workspace ID (overrides agent.json for local development)"),
|
|
49
|
+
apiUrl: z.string().optional().describe("The Botpress API URL (overrides agent.json for local development)"),
|
|
44
50
|
devId: z.string().optional().describe("The development bot ID used during local development")
|
|
45
51
|
});
|
|
46
52
|
((ValidationErrorCode2) => {
|
|
@@ -470,9 +476,46 @@ var init_constants = __esm(() => {
|
|
|
470
476
|
// src/agent-project/agent-resolver.ts
|
|
471
477
|
import fs from "fs/promises";
|
|
472
478
|
import path from "path";
|
|
479
|
+
async function readLocalInfo(agentPath) {
|
|
480
|
+
const localPath = path.join(agentPath, "agent.local.json");
|
|
481
|
+
try {
|
|
482
|
+
const localContent = await fs.readFile(localPath, "utf-8");
|
|
483
|
+
const localData = JSON.parse(localContent);
|
|
484
|
+
const localResult = agentLocalInfoSchema.safeParse(localData);
|
|
485
|
+
if (!localResult.success) {
|
|
486
|
+
const issue = localResult.error.errors[0];
|
|
487
|
+
throw ValidationErrors.warning(`agent.local.json has an invalid field: ${issue?.path.join(".")} — ${issue?.message}`, "agent.local.json");
|
|
488
|
+
}
|
|
489
|
+
return localResult.data;
|
|
490
|
+
} catch (error) {
|
|
491
|
+
if (error.code === "ENOENT") {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
if (ValidationErrors.isValidationError(error)) {
|
|
495
|
+
throw error;
|
|
496
|
+
}
|
|
497
|
+
throw ValidationErrors.warning(`Failed to read agent.local.json: ${error.message}`, "agent.local.json");
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
function applyLocalOverrides(agentInfo, localInfo) {
|
|
501
|
+
if (localInfo.botId) {
|
|
502
|
+
agentInfo.botId = localInfo.botId;
|
|
503
|
+
}
|
|
504
|
+
if (localInfo.workspaceId) {
|
|
505
|
+
agentInfo.workspaceId = localInfo.workspaceId;
|
|
506
|
+
}
|
|
507
|
+
if (localInfo.apiUrl) {
|
|
508
|
+
agentInfo.apiUrl = localInfo.apiUrl;
|
|
509
|
+
}
|
|
510
|
+
if (localInfo.devId) {
|
|
511
|
+
agentInfo.devId = localInfo.devId;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
473
514
|
async function resolveAgent(agentPath, options = {}) {
|
|
474
515
|
const { required = false, requireWorkspace = false, requireBot = false } = options;
|
|
475
516
|
const agentJsonPath = path.join(agentPath, "agent.json");
|
|
517
|
+
const localInfo = await readLocalInfo(agentPath);
|
|
518
|
+
let agentInfo = null;
|
|
476
519
|
try {
|
|
477
520
|
const agentJsonContent = await fs.readFile(agentJsonPath, "utf-8");
|
|
478
521
|
let agentData;
|
|
@@ -486,38 +529,42 @@ async function resolveAgent(agentPath, options = {}) {
|
|
|
486
529
|
const zodError = validationResult.error.errors[0];
|
|
487
530
|
throw ValidationErrors.invalidConfigSchema("agent.json", zodError?.path.join(".") || "unknown", zodError?.message || "Invalid schema");
|
|
488
531
|
}
|
|
489
|
-
|
|
490
|
-
if (!agentInfo.apiUrl) {
|
|
491
|
-
agentInfo.apiUrl = DEFAULT_API_URL;
|
|
492
|
-
}
|
|
493
|
-
const localPath = path.join(agentPath, "agent.local.json");
|
|
494
|
-
try {
|
|
495
|
-
const localContent = await fs.readFile(localPath, "utf-8");
|
|
496
|
-
const localData = JSON.parse(localContent);
|
|
497
|
-
const localResult = agentLocalInfoSchema.safeParse(localData);
|
|
498
|
-
if (localResult.success && localResult.data.devId) {
|
|
499
|
-
agentInfo.devId = localResult.data.devId;
|
|
500
|
-
}
|
|
501
|
-
} catch {}
|
|
502
|
-
if (requireWorkspace && !agentInfo.workspaceId) {
|
|
503
|
-
throw ValidationErrors.workspaceIdMissing();
|
|
504
|
-
}
|
|
505
|
-
if (requireBot && !agentInfo.botId) {
|
|
506
|
-
throw ValidationErrors.botIdMissing();
|
|
507
|
-
}
|
|
508
|
-
return agentInfo;
|
|
532
|
+
agentInfo = validationResult.data;
|
|
509
533
|
} catch (error) {
|
|
510
|
-
if (error.code === "ENOENT") {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
}
|
|
534
|
+
if (error.code === "ENOENT") {} else if (ValidationErrors.isValidationError(error)) {
|
|
535
|
+
throw error;
|
|
536
|
+
} else {
|
|
537
|
+
throw ValidationErrors.warning(`Failed to read agent.json: ${error.message}`, "agent.json");
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
if (!agentInfo) {
|
|
541
|
+
if (localInfo?.botId && localInfo?.workspaceId) {
|
|
542
|
+
agentInfo = {
|
|
543
|
+
botId: localInfo.botId,
|
|
544
|
+
workspaceId: localInfo.workspaceId,
|
|
545
|
+
apiUrl: localInfo.apiUrl,
|
|
546
|
+
devId: localInfo.devId
|
|
547
|
+
};
|
|
548
|
+
} else if (required || requireWorkspace || requireBot) {
|
|
549
|
+
throw ValidationErrors.requiredFileMissing("agent.json or agent.local.json");
|
|
550
|
+
} else {
|
|
514
551
|
return null;
|
|
515
552
|
}
|
|
516
|
-
|
|
517
|
-
|
|
553
|
+
} else {
|
|
554
|
+
if (localInfo) {
|
|
555
|
+
applyLocalOverrides(agentInfo, localInfo);
|
|
518
556
|
}
|
|
519
|
-
throw ValidationErrors.warning(`Failed to read agent.json: ${error.message}`, "agent.json");
|
|
520
557
|
}
|
|
558
|
+
if (!agentInfo.apiUrl) {
|
|
559
|
+
agentInfo.apiUrl = DEFAULT_API_URL;
|
|
560
|
+
}
|
|
561
|
+
if (requireWorkspace && !agentInfo.workspaceId) {
|
|
562
|
+
throw ValidationErrors.workspaceIdMissing();
|
|
563
|
+
}
|
|
564
|
+
if (requireBot && !agentInfo.botId) {
|
|
565
|
+
throw ValidationErrors.botIdMissing();
|
|
566
|
+
}
|
|
567
|
+
return agentInfo;
|
|
521
568
|
}
|
|
522
569
|
var init_agent_resolver = __esm(() => {
|
|
523
570
|
init_types();
|
|
@@ -694,7 +741,6 @@ class CredentialsManager {
|
|
|
694
741
|
const store = await this.readCredentials();
|
|
695
742
|
const matchingCredentials = this.findProfileByApiUrl(store, agentApiUrl);
|
|
696
743
|
if (matchingCredentials) {
|
|
697
|
-
console.info(`Using profile matching agent.json API URL (${agentApiUrl})`);
|
|
698
744
|
baseCredentials = matchingCredentials;
|
|
699
745
|
} else {
|
|
700
746
|
const profileName = store.currentProfile || "default";
|
|
@@ -776,7 +822,7 @@ var _format = null, _formatLoaded = false, formatCode = async (code, filepath) =
|
|
|
776
822
|
`));
|
|
777
823
|
return code;
|
|
778
824
|
}
|
|
779
|
-
}, ADK_VERSION = "1.
|
|
825
|
+
}, ADK_VERSION = "1.18.0-beta.2", relative2 = (from, to) => {
|
|
780
826
|
const fromDir = path10.dirname(from);
|
|
781
827
|
const relative3 = path10.relative(fromDir, to);
|
|
782
828
|
return relative3.startsWith(".") ? relative3 : `./${relative3}`;
|
|
@@ -907,7 +953,7 @@ var init_integration_action_types = __esm(() => {
|
|
|
907
953
|
var require_package = __commonJS((exports, module) => {
|
|
908
954
|
module.exports = {
|
|
909
955
|
name: "@botpress/adk",
|
|
910
|
-
version: "1.
|
|
956
|
+
version: "1.18.0-beta.2",
|
|
911
957
|
description: "Core ADK library for building AI agents on Botpress",
|
|
912
958
|
keywords: [
|
|
913
959
|
"adk",
|
|
@@ -952,12 +998,12 @@ var require_package = __commonJS((exports, module) => {
|
|
|
952
998
|
"check:type": "tsc --noEmit"
|
|
953
999
|
},
|
|
954
1000
|
dependencies: {
|
|
955
|
-
"@botpress/chat": "0.5.5",
|
|
956
|
-
"@botpress/cli": "6.
|
|
957
|
-
"@botpress/client": "1.
|
|
958
|
-
"@botpress/cognitive": "0.
|
|
959
|
-
"@botpress/runtime": "^1.
|
|
960
|
-
"@botpress/sdk": "6.
|
|
1001
|
+
"@botpress/chat": "~0.5.5",
|
|
1002
|
+
"@botpress/cli": "~6.3.2",
|
|
1003
|
+
"@botpress/client": "~1.39.0",
|
|
1004
|
+
"@botpress/cognitive": "~0.5.2",
|
|
1005
|
+
"@botpress/runtime": "^1.18.0-beta.2",
|
|
1006
|
+
"@botpress/sdk": "~6.4.4",
|
|
961
1007
|
"@bpinternal/jex": "^1.2.4",
|
|
962
1008
|
"@bpinternal/yargs-extra": "^0.0.21",
|
|
963
1009
|
"@parcel/watcher": "^2.5.1",
|
|
@@ -970,14 +1016,6 @@ var require_package = __commonJS((exports, module) => {
|
|
|
970
1016
|
semver: "^7.7.2",
|
|
971
1017
|
"ts-morph": "^27.0.2"
|
|
972
1018
|
},
|
|
973
|
-
devDependencies: {
|
|
974
|
-
"@bpinternal/zui": "2.1.0",
|
|
975
|
-
"@types/debug": "^4.1.12",
|
|
976
|
-
"@types/glob": "^9.0.0",
|
|
977
|
-
"@types/luxon": "^3.7.1",
|
|
978
|
-
"@types/semver": "^7.7.1",
|
|
979
|
-
dotenv: "^17.2.3"
|
|
980
|
-
},
|
|
981
1019
|
peerDependencies: {
|
|
982
1020
|
typescript: ">=4.5.0"
|
|
983
1021
|
},
|
|
@@ -1204,7 +1242,7 @@ import os3 from "os";
|
|
|
1204
1242
|
import path4 from "path";
|
|
1205
1243
|
import createDebug from "debug";
|
|
1206
1244
|
var debug = createDebug("adk:bp-cli");
|
|
1207
|
-
var BP_CLI_VERSION = "6.
|
|
1245
|
+
var BP_CLI_VERSION = "6.3.2";
|
|
1208
1246
|
var BP_CLI_INSTALL_ALL = path4.join(os3.homedir(), ".adk", `bp-cli`);
|
|
1209
1247
|
var BP_CLI_INSTALL_DIR = path4.join(BP_CLI_INSTALL_ALL, BP_CLI_VERSION);
|
|
1210
1248
|
var BP_CLI_BIN_PATH = path4.join(BP_CLI_INSTALL_DIR, "node_modules", "@botpress", "cli", "bin.js");
|
|
@@ -2266,7 +2304,7 @@ function getChatClient(cwd = process.cwd()) {
|
|
|
2266
2304
|
}
|
|
2267
2305
|
// src/utils/json-ordering.ts
|
|
2268
2306
|
var agentInfoKeyOrder = ["botId", "workspaceId", "apiUrl"];
|
|
2269
|
-
var agentLocalInfoKeyOrder = ["devId"];
|
|
2307
|
+
var agentLocalInfoKeyOrder = ["botId", "workspaceId", "apiUrl", "devId"];
|
|
2270
2308
|
var dependenciesKeyOrder = ["integrations"];
|
|
2271
2309
|
var integrationKeyOrder = ["version", "enabled", "configurationType", "config"];
|
|
2272
2310
|
function orderKeys(obj, keyOrder) {
|
|
@@ -2317,6 +2355,7 @@ function stringifyWithOrder(obj, keyOrder, space = 2) {
|
|
|
2317
2355
|
}
|
|
2318
2356
|
// src/agent-project/agent-project.ts
|
|
2319
2357
|
import { BuiltInActions, BuiltInWorkflows, Errors as Errors2, Primitives as Primitives2, setAdkCommand } from "@botpress/runtime/internal";
|
|
2358
|
+
import { Autonomous } from "@botpress/runtime";
|
|
2320
2359
|
import createDebug2 from "debug";
|
|
2321
2360
|
import { createRequire as createRequire3 } from "module";
|
|
2322
2361
|
import fs10 from "fs/promises";
|
|
@@ -2935,7 +2974,8 @@ class IntegrationParser {
|
|
|
2935
2974
|
errors.push(ValidationErrors.invalidIntegrationAlias(alias));
|
|
2936
2975
|
continue;
|
|
2937
2976
|
}
|
|
2938
|
-
const
|
|
2977
|
+
const normalized = typeof value === "string" ? { version: value } : value;
|
|
2978
|
+
const ref = this.parseIntegrationRef(normalized.version);
|
|
2939
2979
|
const versionResult = versionSchema.safeParse(ref.version);
|
|
2940
2980
|
if (!versionResult.success) {
|
|
2941
2981
|
errors.push(ValidationErrors.invalidVersionFormat(alias, ref.version));
|
|
@@ -2943,9 +2983,9 @@ class IntegrationParser {
|
|
|
2943
2983
|
integrations.push({
|
|
2944
2984
|
alias,
|
|
2945
2985
|
ref,
|
|
2946
|
-
enabled:
|
|
2947
|
-
configurationType:
|
|
2948
|
-
config:
|
|
2986
|
+
enabled: "enabled" in normalized ? normalized.enabled : undefined,
|
|
2987
|
+
configurationType: "configurationType" in normalized ? normalized.configurationType : undefined,
|
|
2988
|
+
config: "config" in normalized ? normalized.config : undefined
|
|
2949
2989
|
});
|
|
2950
2990
|
} catch (error) {
|
|
2951
2991
|
errors.push(ValidationErrors.invalidDependenciesSyntax(`Invalid integration '${alias}': ${error instanceof Error ? error.message : String(error)}`));
|
|
@@ -3262,7 +3302,7 @@ class IntegrationManager {
|
|
|
3262
3302
|
return { valid: false, errors, warnings };
|
|
3263
3303
|
}
|
|
3264
3304
|
const hasChannels = integration.definition.channels && Object.keys(integration.definition.channels).length > 0;
|
|
3265
|
-
if (!integration.config) {
|
|
3305
|
+
if (!integration.config && integration.enabled !== undefined) {
|
|
3266
3306
|
let requiresConfig = false;
|
|
3267
3307
|
if (integration.definition.configurations) {
|
|
3268
3308
|
requiresConfig = Object.values(integration.definition.configurations).some((config) => config.identifier?.required === true);
|
|
@@ -3532,6 +3572,7 @@ class HubCache {
|
|
|
3532
3572
|
// src/agent-project/config-writer.ts
|
|
3533
3573
|
init_utils();
|
|
3534
3574
|
import { Project, SyntaxKind } from "ts-morph";
|
|
3575
|
+
import { readFileSync } from "fs";
|
|
3535
3576
|
import * as path11 from "path";
|
|
3536
3577
|
|
|
3537
3578
|
class ConfigWriter {
|
|
@@ -3541,7 +3582,9 @@ class ConfigWriter {
|
|
|
3541
3582
|
}
|
|
3542
3583
|
loadConfig() {
|
|
3543
3584
|
const project = new Project;
|
|
3544
|
-
const sourceFile = project.
|
|
3585
|
+
const sourceFile = project.createSourceFile(this.configPath, readFileSync(this.configPath, "utf-8"), {
|
|
3586
|
+
overwrite: true
|
|
3587
|
+
});
|
|
3545
3588
|
const defineConfigCall = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).find((call) => {
|
|
3546
3589
|
return call.getExpression().getText() === "defineConfig";
|
|
3547
3590
|
});
|
|
@@ -3561,6 +3604,47 @@ class ConfigWriter {
|
|
|
3561
3604
|
sourceFile.replaceWithText(formatted);
|
|
3562
3605
|
await sourceFile.save();
|
|
3563
3606
|
}
|
|
3607
|
+
serializeDefaultModelSelection(value) {
|
|
3608
|
+
if (Array.isArray(value)) {
|
|
3609
|
+
return `[${value.map((entry) => `'${entry.replace(/'/g, "\\'")}'`).join(", ")}]`;
|
|
3610
|
+
}
|
|
3611
|
+
return `'${value.replace(/'/g, "\\'")}'`;
|
|
3612
|
+
}
|
|
3613
|
+
getIntegrationConfigMigrationCandidates() {
|
|
3614
|
+
const { sourceFile, configObject } = this.loadConfig();
|
|
3615
|
+
const dependenciesProp = configObject.getProperty("dependencies");
|
|
3616
|
+
if (!dependenciesProp) {
|
|
3617
|
+
return { sourceFile, candidates: [] };
|
|
3618
|
+
}
|
|
3619
|
+
const depsInit = dependenciesProp.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression);
|
|
3620
|
+
if (!depsInit) {
|
|
3621
|
+
return { sourceFile, candidates: [] };
|
|
3622
|
+
}
|
|
3623
|
+
const integrationsProp = depsInit.getProperty("integrations");
|
|
3624
|
+
if (!integrationsProp) {
|
|
3625
|
+
return { sourceFile, candidates: [] };
|
|
3626
|
+
}
|
|
3627
|
+
const integrationsInit = integrationsProp.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression);
|
|
3628
|
+
if (!integrationsInit) {
|
|
3629
|
+
return { sourceFile, candidates: [] };
|
|
3630
|
+
}
|
|
3631
|
+
const candidates = integrationsInit.getProperties().flatMap((prop) => {
|
|
3632
|
+
if (!prop.isKind(SyntaxKind.PropertyAssignment)) {
|
|
3633
|
+
return [];
|
|
3634
|
+
}
|
|
3635
|
+
const assignment = prop;
|
|
3636
|
+
const initializer = assignment.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression);
|
|
3637
|
+
if (!initializer) {
|
|
3638
|
+
return [];
|
|
3639
|
+
}
|
|
3640
|
+
const hasConfigProperty = initializer.getProperty("config") !== undefined;
|
|
3641
|
+
const versionProp = initializer.getProperty("version");
|
|
3642
|
+
const versionInitializer = versionProp?.getInitializer();
|
|
3643
|
+
const versionInitializerText = versionInitializer && (versionInitializer.isKind(SyntaxKind.StringLiteral) || versionInitializer.isKind(SyntaxKind.NoSubstitutionTemplateLiteral)) ? versionInitializer.getText() : undefined;
|
|
3644
|
+
return [{ alias: assignment.getName(), assignment, hasConfigProperty, versionInitializerText }];
|
|
3645
|
+
});
|
|
3646
|
+
return { sourceFile, candidates };
|
|
3647
|
+
}
|
|
3564
3648
|
async updateDependencies(dependencies) {
|
|
3565
3649
|
const { sourceFile, configObject } = this.loadConfig();
|
|
3566
3650
|
let dependenciesProperty = configObject.getProperty("dependencies");
|
|
@@ -3582,6 +3666,67 @@ class ConfigWriter {
|
|
|
3582
3666
|
}
|
|
3583
3667
|
await this.saveConfig(sourceFile);
|
|
3584
3668
|
}
|
|
3669
|
+
async updateDefaultModels(updates) {
|
|
3670
|
+
const requestedEntries = Object.entries(updates).filter(([, value]) => value !== undefined);
|
|
3671
|
+
if (requestedEntries.length === 0) {
|
|
3672
|
+
return;
|
|
3673
|
+
}
|
|
3674
|
+
const { sourceFile, configObject } = this.loadConfig();
|
|
3675
|
+
let defaultModelsProperty = configObject.getProperty("defaultModels");
|
|
3676
|
+
if (!defaultModelsProperty) {
|
|
3677
|
+
defaultModelsProperty = configObject.addPropertyAssignment({
|
|
3678
|
+
name: "defaultModels",
|
|
3679
|
+
initializer: "{}"
|
|
3680
|
+
});
|
|
3681
|
+
}
|
|
3682
|
+
const defaultModelsObject = defaultModelsProperty.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression);
|
|
3683
|
+
if (!defaultModelsObject) {
|
|
3684
|
+
throw new Error("defaultModels must be an object literal in agent.config.ts");
|
|
3685
|
+
}
|
|
3686
|
+
for (const [key, value] of requestedEntries) {
|
|
3687
|
+
const existingProperty = defaultModelsObject.getProperty(key);
|
|
3688
|
+
const initializer = this.serializeDefaultModelSelection(value);
|
|
3689
|
+
if (existingProperty) {
|
|
3690
|
+
existingProperty.setInitializer(initializer);
|
|
3691
|
+
} else {
|
|
3692
|
+
defaultModelsObject.addPropertyAssignment({
|
|
3693
|
+
name: key,
|
|
3694
|
+
initializer
|
|
3695
|
+
});
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
await this.saveConfig(sourceFile);
|
|
3699
|
+
}
|
|
3700
|
+
async migrateIntegrationsToStringFormat() {
|
|
3701
|
+
const { sourceFile, candidates } = this.getIntegrationConfigMigrationCandidates();
|
|
3702
|
+
const migrated = [];
|
|
3703
|
+
for (const candidate of candidates) {
|
|
3704
|
+
if (!candidate.versionInitializerText || candidate.hasConfigProperty) {
|
|
3705
|
+
continue;
|
|
3706
|
+
}
|
|
3707
|
+
candidate.assignment.setInitializer(candidate.versionInitializerText);
|
|
3708
|
+
migrated.push(candidate.alias);
|
|
3709
|
+
}
|
|
3710
|
+
if (migrated.length > 0) {
|
|
3711
|
+
await this.saveConfig(sourceFile);
|
|
3712
|
+
}
|
|
3713
|
+
return migrated;
|
|
3714
|
+
}
|
|
3715
|
+
getIntegrationConfigMigrationState() {
|
|
3716
|
+
try {
|
|
3717
|
+
const { candidates } = this.getIntegrationConfigMigrationCandidates();
|
|
3718
|
+
const deprecatedAliases = candidates.map((candidate) => candidate.alias);
|
|
3719
|
+
const migratableAliases = candidates.filter((candidate) => candidate.versionInitializerText && !candidate.hasConfigProperty).map((candidate) => candidate.alias);
|
|
3720
|
+
return { deprecatedAliases, migratableAliases };
|
|
3721
|
+
} catch (error) {
|
|
3722
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3723
|
+
console.error(`Configuration update failed with error: ${message} — please verify that there are no syntax errors in your agent.config.ts`);
|
|
3724
|
+
return { deprecatedAliases: [], migratableAliases: [] };
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
getObjectFormatIntegrations() {
|
|
3728
|
+
return this.getIntegrationConfigMigrationState().deprecatedAliases;
|
|
3729
|
+
}
|
|
3585
3730
|
async updateConfiguration(updates) {
|
|
3586
3731
|
const { sourceFile, configObject } = this.loadConfig();
|
|
3587
3732
|
const hasAdds = updates.some((u) => u.action === "add");
|
|
@@ -3693,6 +3838,66 @@ class IntegrationOperations {
|
|
|
3693
3838
|
}
|
|
3694
3839
|
return { name, version, fullName: name };
|
|
3695
3840
|
}
|
|
3841
|
+
isIntegrationVersionId(input) {
|
|
3842
|
+
return input.startsWith("intver_");
|
|
3843
|
+
}
|
|
3844
|
+
isResourceNotFoundError(error) {
|
|
3845
|
+
return Boolean(error && typeof error === "object" && "type" in error && error.type === "ResourceNotFound");
|
|
3846
|
+
}
|
|
3847
|
+
getCanonicalIntegrationFullName(integration) {
|
|
3848
|
+
if (integration.public) {
|
|
3849
|
+
return integration.name;
|
|
3850
|
+
}
|
|
3851
|
+
const workspaceHandle = integration.ownerWorkspace?.handle;
|
|
3852
|
+
return workspaceHandle ? `${workspaceHandle}/${integration.name}` : integration.name;
|
|
3853
|
+
}
|
|
3854
|
+
async resolveIntegrationVersionId(id) {
|
|
3855
|
+
const client = await this.getClient();
|
|
3856
|
+
try {
|
|
3857
|
+
const response = await client.getIntegration({ id });
|
|
3858
|
+
return response.integration;
|
|
3859
|
+
} catch (error) {
|
|
3860
|
+
if (!this.isResourceNotFoundError(error)) {
|
|
3861
|
+
throw error;
|
|
3862
|
+
}
|
|
3863
|
+
}
|
|
3864
|
+
try {
|
|
3865
|
+
const response = await client.getPublicIntegrationById({ id });
|
|
3866
|
+
return response.integration;
|
|
3867
|
+
} catch (error) {
|
|
3868
|
+
if (this.isResourceNotFoundError(error)) {
|
|
3869
|
+
throw new Error(`Integration "${id}" not found`);
|
|
3870
|
+
}
|
|
3871
|
+
throw error;
|
|
3872
|
+
}
|
|
3873
|
+
}
|
|
3874
|
+
async resolveAddIntegrationInput(options) {
|
|
3875
|
+
const requestedVersion = options.version || "latest";
|
|
3876
|
+
if (!this.isIntegrationVersionId(options.name)) {
|
|
3877
|
+
const ref = this.parseIntegrationRef(`${options.name}@${requestedVersion}`);
|
|
3878
|
+
return {
|
|
3879
|
+
name: ref.name,
|
|
3880
|
+
fullName: ref.fullName,
|
|
3881
|
+
version: ref.version,
|
|
3882
|
+
alias: options.alias || ref.name,
|
|
3883
|
+
ref: `${ref.fullName}@${ref.version}`,
|
|
3884
|
+
isIntegrationId: false
|
|
3885
|
+
};
|
|
3886
|
+
}
|
|
3887
|
+
if (options.version && options.version !== "latest") {
|
|
3888
|
+
throw new Error("Integration version IDs are already version-pinned and do not accept an additional @version override");
|
|
3889
|
+
}
|
|
3890
|
+
const integration = await this.resolveIntegrationVersionId(options.name);
|
|
3891
|
+
const fullName = this.getCanonicalIntegrationFullName(integration);
|
|
3892
|
+
return {
|
|
3893
|
+
name: integration.name,
|
|
3894
|
+
fullName,
|
|
3895
|
+
version: integration.version,
|
|
3896
|
+
alias: options.alias || integration.name,
|
|
3897
|
+
ref: `${fullName}@${integration.version}`,
|
|
3898
|
+
isIntegrationId: true
|
|
3899
|
+
};
|
|
3900
|
+
}
|
|
3696
3901
|
async getIntegrationVersions(name) {
|
|
3697
3902
|
const client = await this.getClient();
|
|
3698
3903
|
const ref = this.parseIntegrationRef(name);
|
|
@@ -3726,9 +3931,8 @@ class IntegrationOperations {
|
|
|
3726
3931
|
}
|
|
3727
3932
|
async addIntegration(options) {
|
|
3728
3933
|
const project = await AgentProject.load(this.projectPath || process2.cwd());
|
|
3729
|
-
const
|
|
3730
|
-
const
|
|
3731
|
-
const alias = options.alias || ref.name;
|
|
3934
|
+
const resolvedInput = await this.resolveAddIntegrationInput(options);
|
|
3935
|
+
const { alias } = resolvedInput;
|
|
3732
3936
|
const dependencies = project.dependencies || { integrations: {} };
|
|
3733
3937
|
if (!dependencies.integrations) {
|
|
3734
3938
|
dependencies.integrations = {};
|
|
@@ -3745,11 +3949,17 @@ class IntegrationOperations {
|
|
|
3745
3949
|
} else {
|
|
3746
3950
|
existingVersion = "unknown";
|
|
3747
3951
|
}
|
|
3748
|
-
|
|
3952
|
+
const effectiveVersionSpecified = Boolean(options.version) || resolvedInput.isIntegrationId;
|
|
3953
|
+
if (!effectiveVersionSpecified || resolvedInput.version === "latest" || resolvedInput.version === existingVersion) {
|
|
3749
3954
|
return {
|
|
3750
3955
|
success: false,
|
|
3751
3956
|
message: `Integration '${alias}' already exists with version ${existingVersion}. Use 'adk upgrade ${alias}' to upgrade to the latest version.`,
|
|
3752
|
-
existingVersion
|
|
3957
|
+
existingVersion,
|
|
3958
|
+
name: resolvedInput.name,
|
|
3959
|
+
fullName: resolvedInput.fullName,
|
|
3960
|
+
alias: resolvedInput.alias,
|
|
3961
|
+
version: existingVersion,
|
|
3962
|
+
ref: `${resolvedInput.fullName}@${existingVersion}`
|
|
3753
3963
|
};
|
|
3754
3964
|
}
|
|
3755
3965
|
}
|
|
@@ -3761,7 +3971,7 @@ class IntegrationOperations {
|
|
|
3761
3971
|
const loadResult = await tempManager.loadIntegrations({
|
|
3762
3972
|
integrations: {
|
|
3763
3973
|
[alias]: {
|
|
3764
|
-
version:
|
|
3974
|
+
version: resolvedInput.ref,
|
|
3765
3975
|
enabled: true
|
|
3766
3976
|
}
|
|
3767
3977
|
}
|
|
@@ -3779,88 +3989,28 @@ class IntegrationOperations {
|
|
|
3779
3989
|
throw new Error(`Failed to add integration: ${error instanceof Error ? error.message : String(error)}`);
|
|
3780
3990
|
}
|
|
3781
3991
|
const actualVersion = integrationDefinition.version;
|
|
3782
|
-
const integrationVersion = `${
|
|
3992
|
+
const integrationVersion = `${resolvedInput.fullName}@${actualVersion}`;
|
|
3783
3993
|
const existingEntry = dependencies.integrations[alias];
|
|
3784
|
-
const existingConfig = existingEntry && typeof existingEntry === "object" ? existingEntry.config : undefined;
|
|
3785
|
-
const existingConfigurationType = existingEntry && typeof existingEntry === "object" ? existingEntry.configurationType : undefined;
|
|
3786
|
-
const configurationType = existingConfigurationType || this.selectBestConfigurationType(integrationDefinition.configurations);
|
|
3787
|
-
let requiresConfiguration = false;
|
|
3788
|
-
const selectedConfigDef = configurationType && integrationDefinition.configurations?.[configurationType] || integrationDefinition.configurations?.["default"] || integrationDefinition.configuration;
|
|
3789
|
-
if (selectedConfigDef) {
|
|
3790
|
-
if (selectedConfigDef.identifier?.required === true) {
|
|
3791
|
-
requiresConfiguration = true;
|
|
3792
|
-
}
|
|
3793
|
-
if (selectedConfigDef.schema?.required && selectedConfigDef.schema.required.length > 0) {
|
|
3794
|
-
requiresConfiguration = true;
|
|
3795
|
-
}
|
|
3796
|
-
}
|
|
3797
|
-
const config = requiresConfiguration && !existingConfig ? this.getPlaceholderConfig(integrationDefinition, configurationType) : existingConfig;
|
|
3798
3994
|
if (existingEntry && typeof existingEntry === "object" && "version" in existingEntry) {
|
|
3799
|
-
const resolvedConfigType = existingEntry.configurationType || configurationType;
|
|
3800
3995
|
dependencies.integrations[alias] = {
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
...resolvedConfigType ? { configurationType: resolvedConfigType } : {},
|
|
3804
|
-
config: existingEntry.config
|
|
3996
|
+
...existingEntry,
|
|
3997
|
+
version: integrationVersion
|
|
3805
3998
|
};
|
|
3806
3999
|
} else {
|
|
3807
|
-
dependencies.integrations[alias] =
|
|
3808
|
-
version: integrationVersion,
|
|
3809
|
-
enabled: !requiresConfiguration,
|
|
3810
|
-
...configurationType ? { configurationType } : {},
|
|
3811
|
-
config
|
|
3812
|
-
};
|
|
4000
|
+
dependencies.integrations[alias] = integrationVersion;
|
|
3813
4001
|
}
|
|
3814
4002
|
const configWriter = new ConfigWriter(project.path);
|
|
3815
4003
|
await configWriter.updateDependencies(dependencies);
|
|
3816
4004
|
return {
|
|
3817
4005
|
success: true,
|
|
3818
|
-
|
|
3819
|
-
|
|
4006
|
+
newVersion: actualVersion,
|
|
4007
|
+
name: resolvedInput.name,
|
|
4008
|
+
fullName: resolvedInput.fullName,
|
|
4009
|
+
alias: resolvedInput.alias,
|
|
4010
|
+
version: actualVersion,
|
|
4011
|
+
ref: integrationVersion
|
|
3820
4012
|
};
|
|
3821
4013
|
}
|
|
3822
|
-
selectBestConfigurationType(configurations) {
|
|
3823
|
-
if (!configurations || Object.keys(configurations).length === 0) {
|
|
3824
|
-
return;
|
|
3825
|
-
}
|
|
3826
|
-
const keys = Object.keys(configurations);
|
|
3827
|
-
if (keys.length === 1) {
|
|
3828
|
-
return keys[0];
|
|
3829
|
-
}
|
|
3830
|
-
const priority = ["apiKey", "api", "api_key", "token", "default", "refreshToken", "oauth", "oauth2"];
|
|
3831
|
-
for (const preferred of priority) {
|
|
3832
|
-
const match = keys.find((k) => k.toLowerCase() === preferred.toLowerCase());
|
|
3833
|
-
if (match)
|
|
3834
|
-
return match;
|
|
3835
|
-
}
|
|
3836
|
-
return keys[0];
|
|
3837
|
-
}
|
|
3838
|
-
getPlaceholderConfig(integrationDefinition, configurationType) {
|
|
3839
|
-
const configPlaceholder = {};
|
|
3840
|
-
const configDef = configurationType && integrationDefinition.configurations?.[configurationType] || integrationDefinition.configurations?.["default"] || integrationDefinition.configuration;
|
|
3841
|
-
if (configDef) {
|
|
3842
|
-
const schema = configDef.schema;
|
|
3843
|
-
if (schema?.required && schema.required.length > 0) {
|
|
3844
|
-
const properties = schema.properties || {};
|
|
3845
|
-
for (const fieldName of schema.required) {
|
|
3846
|
-
const fieldDef = properties[fieldName];
|
|
3847
|
-
if (fieldDef?.type === "string") {
|
|
3848
|
-
configPlaceholder[fieldName] = `YOUR_${fieldName.toUpperCase()}_HERE`;
|
|
3849
|
-
} else if (fieldDef?.type === "number" || fieldDef?.type === "integer") {
|
|
3850
|
-
configPlaceholder[fieldName] = 0;
|
|
3851
|
-
} else if (fieldDef?.type === "boolean") {
|
|
3852
|
-
configPlaceholder[fieldName] = false;
|
|
3853
|
-
} else {
|
|
3854
|
-
configPlaceholder[fieldName] = null;
|
|
3855
|
-
}
|
|
3856
|
-
}
|
|
3857
|
-
if (Object.keys(configPlaceholder).length > 0) {
|
|
3858
|
-
return configPlaceholder;
|
|
3859
|
-
}
|
|
3860
|
-
}
|
|
3861
|
-
}
|
|
3862
|
-
return;
|
|
3863
|
-
}
|
|
3864
4014
|
async removeIntegration(name) {
|
|
3865
4015
|
const project = await AgentProject.load(this.projectPath || process2.cwd());
|
|
3866
4016
|
const dependencies = project.dependencies;
|
|
@@ -3899,10 +4049,8 @@ class IntegrationOperations {
|
|
|
3899
4049
|
}
|
|
3900
4050
|
const versionInfo = await this.getIntegrationVersions(ref.fullName);
|
|
3901
4051
|
if (versionInfo.latestVersion && versionInfo.latestVersion !== currentVersion) {
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
version: `${ref.fullName}@${versionInfo.latestVersion}`
|
|
3905
|
-
};
|
|
4052
|
+
const newVersion = `${ref.fullName}@${versionInfo.latestVersion}`;
|
|
4053
|
+
dependencies.integrations[alias] = typeof value === "string" ? newVersion : { ...value, version: newVersion };
|
|
3906
4054
|
upgraded.push(`${alias} (${currentVersion} → ${versionInfo.latestVersion})`);
|
|
3907
4055
|
}
|
|
3908
4056
|
} catch {
|
|
@@ -3991,7 +4139,7 @@ async function fetchServerIntegrationConfigs(project, targetBotId) {
|
|
|
3991
4139
|
const { devId, botId } = project.agentInfo ?? {};
|
|
3992
4140
|
const targetId = targetBotId || devId || botId;
|
|
3993
4141
|
if (!targetId) {
|
|
3994
|
-
return { configs: {}, fetched: false, skipped: true };
|
|
4142
|
+
return { configs: {}, enabledStates: {}, fetched: false, skipped: true };
|
|
3995
4143
|
}
|
|
3996
4144
|
try {
|
|
3997
4145
|
const credentials = await auth.getActiveCredentials();
|
|
@@ -4014,18 +4162,26 @@ async function fetchServerIntegrationConfigs(project, targetBotId) {
|
|
|
4014
4162
|
}
|
|
4015
4163
|
} catch (err) {
|
|
4016
4164
|
const message = err instanceof Error ? err.message : String(err);
|
|
4017
|
-
return {
|
|
4165
|
+
return {
|
|
4166
|
+
configs: {},
|
|
4167
|
+
enabledStates: {},
|
|
4168
|
+
fetched: false,
|
|
4169
|
+
skipped: false,
|
|
4170
|
+
error: message
|
|
4171
|
+
};
|
|
4018
4172
|
}
|
|
4019
4173
|
}
|
|
4020
4174
|
async function fetchBotConfigs(client, botId) {
|
|
4021
4175
|
const { bot } = await client.getBot({ id: botId });
|
|
4022
4176
|
const configs = {};
|
|
4177
|
+
const enabledStates = {};
|
|
4023
4178
|
for (const [alias, integration] of Object.entries(bot.integrations || {})) {
|
|
4024
4179
|
if (integration.configuration && Object.keys(integration.configuration).length > 0) {
|
|
4025
4180
|
configs[alias] = integration.configuration;
|
|
4026
4181
|
}
|
|
4182
|
+
enabledStates[alias] = integration.enabled;
|
|
4027
4183
|
}
|
|
4028
|
-
return { configs, fetched: true, skipped: false };
|
|
4184
|
+
return { configs, enabledStates, fetched: true, skipped: false };
|
|
4029
4185
|
}
|
|
4030
4186
|
|
|
4031
4187
|
// src/integrations/checker.ts
|
|
@@ -4139,7 +4295,7 @@ class IntegrationChecker {
|
|
|
4139
4295
|
}
|
|
4140
4296
|
}
|
|
4141
4297
|
}
|
|
4142
|
-
const desiredInstallStatus = enabled === false ? "disabled" : "enabled";
|
|
4298
|
+
const desiredInstallStatus = enabled === true ? "enabled" : enabled === false ? "disabled" : installedIntegration ? installedIntegration.enabled ? "enabled" : "disabled" : "disabled";
|
|
4143
4299
|
const result = {
|
|
4144
4300
|
alias,
|
|
4145
4301
|
name: ref.fullName,
|
|
@@ -4167,7 +4323,7 @@ class IntegrationChecker {
|
|
|
4167
4323
|
}
|
|
4168
4324
|
}
|
|
4169
4325
|
if (!installedIntegration) {
|
|
4170
|
-
result.needsInstall =
|
|
4326
|
+
result.needsInstall = true;
|
|
4171
4327
|
if (result.needsInstall && config) {
|
|
4172
4328
|
result.needsConfiguration = true;
|
|
4173
4329
|
}
|
|
@@ -4187,11 +4343,7 @@ class IntegrationChecker {
|
|
|
4187
4343
|
}
|
|
4188
4344
|
}
|
|
4189
4345
|
if (enabled !== undefined && enabled !== installedIntegration.enabled) {
|
|
4190
|
-
|
|
4191
|
-
result.needsRemoval = true;
|
|
4192
|
-
} else if (enabled === true && result.installStatus === "disabled") {
|
|
4193
|
-
result.needsConfiguration = true;
|
|
4194
|
-
}
|
|
4346
|
+
result.needsUpdate = true;
|
|
4195
4347
|
}
|
|
4196
4348
|
}
|
|
4197
4349
|
return result;
|
|
@@ -4728,6 +4880,21 @@ init_agent_resolver();
|
|
|
4728
4880
|
init_types();
|
|
4729
4881
|
init_validation_errors();
|
|
4730
4882
|
var debug2 = createDebug2("adk:agent-project");
|
|
4883
|
+
function getToolDefinition(value) {
|
|
4884
|
+
if (typeof value !== "object" || value === null) {
|
|
4885
|
+
return;
|
|
4886
|
+
}
|
|
4887
|
+
const maybeTool = value;
|
|
4888
|
+
const isAutonomousToolInstance = value instanceof Autonomous.Tool;
|
|
4889
|
+
const looksLikeAutonomousTool = maybeTool.constructor?.name === Autonomous.Tool.name && typeof maybeTool.name === "string" && typeof maybeTool.execute === "function" && typeof maybeTool.toJSON === "function";
|
|
4890
|
+
if (!isAutonomousToolInstance && !looksLikeAutonomousTool) {
|
|
4891
|
+
return;
|
|
4892
|
+
}
|
|
4893
|
+
return {
|
|
4894
|
+
name: maybeTool.name,
|
|
4895
|
+
description: maybeTool.description
|
|
4896
|
+
};
|
|
4897
|
+
}
|
|
4731
4898
|
|
|
4732
4899
|
class AgentProject {
|
|
4733
4900
|
static _projectCache = new Map;
|
|
@@ -4751,6 +4918,7 @@ class AgentProject {
|
|
|
4751
4918
|
_workflows = [];
|
|
4752
4919
|
_actions = [];
|
|
4753
4920
|
_tables = [];
|
|
4921
|
+
_tools = [];
|
|
4754
4922
|
constructor(projectPath, options = {}) {
|
|
4755
4923
|
this._options = options;
|
|
4756
4924
|
this._path = path13.resolve(projectPath);
|
|
@@ -4807,6 +4975,9 @@ class AgentProject {
|
|
|
4807
4975
|
get tables() {
|
|
4808
4976
|
return this._tables;
|
|
4809
4977
|
}
|
|
4978
|
+
get tools() {
|
|
4979
|
+
return this._tools;
|
|
4980
|
+
}
|
|
4810
4981
|
get config() {
|
|
4811
4982
|
return this._config;
|
|
4812
4983
|
}
|
|
@@ -4845,6 +5016,7 @@ class AgentProject {
|
|
|
4845
5016
|
this._workflows = [];
|
|
4846
5017
|
this._actions = [];
|
|
4847
5018
|
this._tables = [];
|
|
5019
|
+
this._tools = [];
|
|
4848
5020
|
this._errors = [];
|
|
4849
5021
|
this._warnings = [];
|
|
4850
5022
|
const validation = await this.validate();
|
|
@@ -5018,7 +5190,21 @@ class AgentProject {
|
|
|
5018
5190
|
const content = stringifyWithOrder(merged, agentLocalInfoKeyOrder);
|
|
5019
5191
|
await fs10.writeFile(localPath, content);
|
|
5020
5192
|
if (this._agentInfo) {
|
|
5021
|
-
|
|
5193
|
+
if (merged.botId)
|
|
5194
|
+
this._agentInfo.botId = merged.botId;
|
|
5195
|
+
if (merged.workspaceId)
|
|
5196
|
+
this._agentInfo.workspaceId = merged.workspaceId;
|
|
5197
|
+
if (merged.apiUrl)
|
|
5198
|
+
this._agentInfo.apiUrl = merged.apiUrl;
|
|
5199
|
+
if (merged.devId)
|
|
5200
|
+
this._agentInfo.devId = merged.devId;
|
|
5201
|
+
} else if (merged.botId && merged.workspaceId) {
|
|
5202
|
+
this._agentInfo = {
|
|
5203
|
+
botId: merged.botId,
|
|
5204
|
+
workspaceId: merged.workspaceId,
|
|
5205
|
+
apiUrl: merged.apiUrl,
|
|
5206
|
+
devId: merged.devId
|
|
5207
|
+
};
|
|
5022
5208
|
}
|
|
5023
5209
|
}
|
|
5024
5210
|
async updateAgentLocalInfo(updates) {
|
|
@@ -5037,7 +5223,15 @@ class AgentProject {
|
|
|
5037
5223
|
const content = stringifyWithOrder(updated, agentLocalInfoKeyOrder);
|
|
5038
5224
|
await fs10.writeFile(localPath, content);
|
|
5039
5225
|
if (this._agentInfo) {
|
|
5040
|
-
|
|
5226
|
+
const local = updated;
|
|
5227
|
+
if (local.botId)
|
|
5228
|
+
this._agentInfo.botId = local.botId;
|
|
5229
|
+
if (local.workspaceId)
|
|
5230
|
+
this._agentInfo.workspaceId = local.workspaceId;
|
|
5231
|
+
if (local.apiUrl)
|
|
5232
|
+
this._agentInfo.apiUrl = local.apiUrl;
|
|
5233
|
+
if (local.devId)
|
|
5234
|
+
this._agentInfo.devId = local.devId;
|
|
5041
5235
|
}
|
|
5042
5236
|
}
|
|
5043
5237
|
requiresAgentInfo(operation) {
|
|
@@ -5242,6 +5436,19 @@ ${err.stack?.split(`
|
|
|
5242
5436
|
}
|
|
5243
5437
|
return true;
|
|
5244
5438
|
}
|
|
5439
|
+
isToolBarrelReexport(existingPath, newPath) {
|
|
5440
|
+
const isNewBarrel = /^index\.[tj]s$/i.test(path13.basename(newPath));
|
|
5441
|
+
const isExistingBarrel = /^index\.[tj]s$/i.test(path13.basename(existingPath));
|
|
5442
|
+
if (!isNewBarrel && !isExistingBarrel) {
|
|
5443
|
+
return false;
|
|
5444
|
+
}
|
|
5445
|
+
return true;
|
|
5446
|
+
}
|
|
5447
|
+
shouldPreferToolDefinition(existingPath, newPath) {
|
|
5448
|
+
const isNewBarrel = /^index\.[tj]s$/i.test(path13.basename(newPath));
|
|
5449
|
+
const isExistingBarrel = /^index\.[tj]s$/i.test(path13.basename(existingPath));
|
|
5450
|
+
return isExistingBarrel && !isNewBarrel;
|
|
5451
|
+
}
|
|
5245
5452
|
getChannelsList(channelSpec) {
|
|
5246
5453
|
if (channelSpec === "*") {
|
|
5247
5454
|
return ["*"];
|
|
@@ -5442,6 +5649,35 @@ ${err.stack?.split(`
|
|
|
5442
5649
|
export: key,
|
|
5443
5650
|
path: relPath
|
|
5444
5651
|
});
|
|
5652
|
+
} else {
|
|
5653
|
+
const toolDefinition = getToolDefinition(expandedExports[key]);
|
|
5654
|
+
if (!toolDefinition) {
|
|
5655
|
+
continue;
|
|
5656
|
+
}
|
|
5657
|
+
const existing = this._tools.find((tool) => tool.definition.name === toolDefinition.name);
|
|
5658
|
+
if (existing) {
|
|
5659
|
+
if (this.isToolBarrelReexport(existing.path, relPath)) {
|
|
5660
|
+
if (this.shouldPreferToolDefinition(existing.path, relPath)) {
|
|
5661
|
+
existing.path = relPath;
|
|
5662
|
+
existing.export = key;
|
|
5663
|
+
existing.definition = toolDefinition;
|
|
5664
|
+
}
|
|
5665
|
+
continue;
|
|
5666
|
+
}
|
|
5667
|
+
this._warnings.push({
|
|
5668
|
+
$type: "ValidationError",
|
|
5669
|
+
code: "DUPLICATE_PRIMITIVE" /* DUPLICATE_PRIMITIVE */,
|
|
5670
|
+
severity: "warning" /* WARNING */,
|
|
5671
|
+
message: `Duplicate tool definition found: ${filename} -> ${key} (already defined in ${existing.path} -> ${existing.export})`,
|
|
5672
|
+
file: relPath
|
|
5673
|
+
});
|
|
5674
|
+
continue;
|
|
5675
|
+
}
|
|
5676
|
+
this._tools.push({
|
|
5677
|
+
definition: toolDefinition,
|
|
5678
|
+
export: key,
|
|
5679
|
+
path: relPath
|
|
5680
|
+
});
|
|
5445
5681
|
}
|
|
5446
5682
|
}
|
|
5447
5683
|
} catch (error) {
|
|
@@ -5725,6 +5961,8 @@ class ConfigManager {
|
|
|
5725
5961
|
init_utils();
|
|
5726
5962
|
import * as fs11 from "fs";
|
|
5727
5963
|
import * as path15 from "path";
|
|
5964
|
+
import { fileURLToPath } from "url";
|
|
5965
|
+
import { createRequire as createRequire4 } from "module";
|
|
5728
5966
|
|
|
5729
5967
|
// src/agent-init/ai-assistant-instructions.template.md
|
|
5730
5968
|
var ai_assistant_instructions_template_default = `# Botpress ADK Agent
|
|
@@ -5775,10 +6013,12 @@ Run \`adk mcp:init --all\` to generate configuration for your editor, or use the
|
|
|
5775
6013
|
|
|
5776
6014
|
### Workflows
|
|
5777
6015
|
|
|
5778
|
-
| Tool | Use for
|
|
5779
|
-
| -------------------- |
|
|
5780
|
-
| \`adk_list_workflows\` |
|
|
5781
|
-
| \`adk_start_workflow\` | Start a workflow or get its input schema
|
|
6016
|
+
| Tool | Use for |
|
|
6017
|
+
| -------------------- | ---------------------------------------- |
|
|
6018
|
+
| \`adk_list_workflows\` | Deprecated compat workflow discovery |
|
|
6019
|
+
| \`adk_start_workflow\` | Start a workflow or get its input schema |
|
|
6020
|
+
|
|
6021
|
+
> **Tip:** Prefer \`adk workflows\` in the terminal to discover workflow names and metadata. Keep \`adk_list_workflows\` for MCP compatibility only.
|
|
5782
6022
|
|
|
5783
6023
|
> **Tip:** The dev server must be running (\`adk dev\`) for debugging and testing tools to work.
|
|
5784
6024
|
|
|
@@ -5796,6 +6036,30 @@ Run \`adk mcp:init --all\` to generate configuration for your editor, or use the
|
|
|
5796
6036
|
`;
|
|
5797
6037
|
|
|
5798
6038
|
// src/agent-init/agent-project-generator.ts
|
|
6039
|
+
var TEXT_EXTENSIONS = new Set([
|
|
6040
|
+
".ts",
|
|
6041
|
+
".tsx",
|
|
6042
|
+
".js",
|
|
6043
|
+
".jsx",
|
|
6044
|
+
".mjs",
|
|
6045
|
+
".cjs",
|
|
6046
|
+
".json",
|
|
6047
|
+
".md",
|
|
6048
|
+
".txt",
|
|
6049
|
+
".yml",
|
|
6050
|
+
".yaml",
|
|
6051
|
+
".html",
|
|
6052
|
+
".css",
|
|
6053
|
+
".svg",
|
|
6054
|
+
".gitignore"
|
|
6055
|
+
]);
|
|
6056
|
+
function isTextFile(filename) {
|
|
6057
|
+
if (filename === ".gitignore")
|
|
6058
|
+
return true;
|
|
6059
|
+
const ext = path15.extname(filename).toLowerCase();
|
|
6060
|
+
return TEXT_EXTENSIONS.has(ext);
|
|
6061
|
+
}
|
|
6062
|
+
|
|
5799
6063
|
class AgentProjectGenerator {
|
|
5800
6064
|
projectPath;
|
|
5801
6065
|
projectName;
|
|
@@ -5809,253 +6073,146 @@ class AgentProjectGenerator {
|
|
|
5809
6073
|
}
|
|
5810
6074
|
async generate() {
|
|
5811
6075
|
this.ensureEmptyDirectory();
|
|
5812
|
-
this.
|
|
5813
|
-
await this.
|
|
5814
|
-
this.
|
|
5815
|
-
|
|
5816
|
-
this.createGitIgnore();
|
|
5817
|
-
await this.createReadme();
|
|
5818
|
-
this.createAIAssistantInstructions();
|
|
5819
|
-
await this.createSourceStructure();
|
|
5820
|
-
}
|
|
5821
|
-
ensureEmptyDirectory() {
|
|
5822
|
-
if (!fs11.existsSync(this.projectPath)) {
|
|
5823
|
-
fs11.mkdirSync(this.projectPath, { recursive: true });
|
|
6076
|
+
const templateDir = this.resolveTemplateDir();
|
|
6077
|
+
await this.copyTemplateFiles(templateDir);
|
|
6078
|
+
if (!fs11.existsSync(path15.join(this.projectPath, "agent.json"))) {
|
|
6079
|
+
this.createAgentJson();
|
|
5824
6080
|
}
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
throw new Error(`Directory ${this.projectPath} is not empty. Please use an empty directory.`);
|
|
6081
|
+
if (!fs11.existsSync(path15.join(this.projectPath, "CLAUDE.md"))) {
|
|
6082
|
+
this.createAIAssistantInstructions();
|
|
5828
6083
|
}
|
|
5829
6084
|
}
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
packageManager: this.packageManager === "npm" ? undefined : `${this.packageManager}@latest`,
|
|
5837
|
-
scripts: {
|
|
5838
|
-
dev: "adk dev",
|
|
5839
|
-
build: "adk build",
|
|
5840
|
-
deploy: "adk deploy"
|
|
5841
|
-
},
|
|
5842
|
-
dependencies: {
|
|
5843
|
-
"@botpress/runtime": `^${"1.17.0"}`
|
|
5844
|
-
},
|
|
5845
|
-
devDependencies: {
|
|
5846
|
-
typescript: "^5.9.3"
|
|
6085
|
+
static getAvailableTemplates() {
|
|
6086
|
+
try {
|
|
6087
|
+
const templatesRoot = AgentProjectGenerator.getTemplatesRoot();
|
|
6088
|
+
const configPath = path15.join(templatesRoot, "template.config.json");
|
|
6089
|
+
if (!fs11.existsSync(configPath)) {
|
|
6090
|
+
return [];
|
|
5847
6091
|
}
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
6092
|
+
const raw = fs11.readFileSync(configPath, "utf-8");
|
|
6093
|
+
const registry = JSON.parse(raw);
|
|
6094
|
+
return registry.templates;
|
|
6095
|
+
} catch {
|
|
6096
|
+
return [];
|
|
5851
6097
|
}
|
|
5852
|
-
this.writeJsonFile("package.json", packageJson);
|
|
5853
6098
|
}
|
|
5854
|
-
|
|
5855
|
-
const
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
if (this.template === "hello-world") {
|
|
5859
|
-
dependencies.integrations = {
|
|
5860
|
-
chat: {
|
|
5861
|
-
version: "chat@latest",
|
|
5862
|
-
enabled: true
|
|
5863
|
-
},
|
|
5864
|
-
webchat: {
|
|
5865
|
-
version: "webchat@latest",
|
|
5866
|
-
enabled: true
|
|
5867
|
-
}
|
|
5868
|
-
};
|
|
5869
|
-
}
|
|
5870
|
-
return dependencies;
|
|
6099
|
+
getPostInitCommands() {
|
|
6100
|
+
const templates = AgentProjectGenerator.getAvailableTemplates();
|
|
6101
|
+
const config = templates.find((t) => t.name === this.template);
|
|
6102
|
+
return config?.postInit ?? [];
|
|
5871
6103
|
}
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
6104
|
+
static _templatesRootOverride = null;
|
|
6105
|
+
static setTemplatesRoot(dir) {
|
|
6106
|
+
AgentProjectGenerator._templatesRootOverride = dir;
|
|
6107
|
+
}
|
|
6108
|
+
static getTemplatesRoot() {
|
|
6109
|
+
if (AgentProjectGenerator._templatesRootOverride) {
|
|
6110
|
+
return AgentProjectGenerator._templatesRootOverride;
|
|
6111
|
+
}
|
|
6112
|
+
const candidates = [];
|
|
6113
|
+
try {
|
|
6114
|
+
const esmRequire = createRequire4(import.meta.url);
|
|
6115
|
+
const adkPkgPath = esmRequire.resolve("@botpress/adk/package.json");
|
|
6116
|
+
const adkRoot = path15.dirname(adkPkgPath);
|
|
6117
|
+
candidates.push(path15.join(adkRoot, "dist", "templates"));
|
|
6118
|
+
candidates.push(path15.join(adkRoot, "templates"));
|
|
6119
|
+
} catch {}
|
|
6120
|
+
const thisDir = path15.dirname(fileURLToPath(import.meta.url));
|
|
6121
|
+
candidates.push(path15.resolve(thisDir, "templates"));
|
|
6122
|
+
candidates.push(path15.resolve(thisDir, "../../templates"));
|
|
6123
|
+
candidates.push(path15.join(path15.dirname(process.execPath), "templates"));
|
|
6124
|
+
for (const candidate of candidates) {
|
|
6125
|
+
if (fs11.existsSync(candidate) && fs11.existsSync(path15.join(candidate, "template.config.json"))) {
|
|
6126
|
+
return candidate;
|
|
6127
|
+
}
|
|
6128
|
+
}
|
|
6129
|
+
const tried = candidates.map((c) => ` - ${c}`).join(`
|
|
6130
|
+
`);
|
|
6131
|
+
throw new Error(`Could not find templates directory.
|
|
5891
6132
|
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
},
|
|
6133
|
+
Searched:
|
|
6134
|
+
${tried}
|
|
5895
6135
|
|
|
5896
|
-
|
|
5897
|
-
integrations: ${integrationsJson},
|
|
5898
|
-
},
|
|
5899
|
-
});
|
|
5900
|
-
`;
|
|
5901
|
-
await this.writeFormattedFile("agent.config.ts", agentConfig);
|
|
6136
|
+
Ensure the ADK package is properly installed or run the CLI build.`);
|
|
5902
6137
|
}
|
|
5903
|
-
|
|
5904
|
-
const
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
6138
|
+
resolveTemplateDir() {
|
|
6139
|
+
const templatesRoot = AgentProjectGenerator.getTemplatesRoot();
|
|
6140
|
+
const templateDir = path15.join(templatesRoot, this.template);
|
|
6141
|
+
if (!fs11.existsSync(templateDir)) {
|
|
6142
|
+
const available = AgentProjectGenerator.getAvailableTemplates();
|
|
6143
|
+
const names = available.map((t) => ` - ${t.name}: ${t.description}`).join(`
|
|
6144
|
+
`);
|
|
6145
|
+
throw new Error(`Unknown template: "${this.template}"
|
|
6146
|
+
|
|
6147
|
+
Available templates:
|
|
6148
|
+
${names || " (none found)"}`);
|
|
6149
|
+
}
|
|
6150
|
+
const configFile = path15.join(templateDir, "agent.config.ts");
|
|
6151
|
+
if (!fs11.existsSync(configFile)) {
|
|
6152
|
+
throw new Error(`Template "${this.template}" is missing agent.config.ts`);
|
|
6153
|
+
}
|
|
6154
|
+
return templateDir;
|
|
6155
|
+
}
|
|
6156
|
+
async copyTemplateFiles(templateDir) {
|
|
6157
|
+
const substitutions = {
|
|
6158
|
+
"{{projectName}}": this.projectName,
|
|
6159
|
+
"{{runtimeVersion}}": "1.18.0-beta.2",
|
|
6160
|
+
"{{packageManager}}": this.packageManager
|
|
5925
6161
|
};
|
|
5926
|
-
this.
|
|
6162
|
+
await this.copyDirRecursive(templateDir, this.projectPath, substitutions);
|
|
6163
|
+
}
|
|
6164
|
+
async copyDirRecursive(src, dest, substitutions) {
|
|
6165
|
+
if (!fs11.existsSync(dest)) {
|
|
6166
|
+
fs11.mkdirSync(dest, { recursive: true });
|
|
6167
|
+
}
|
|
6168
|
+
const entries = fs11.readdirSync(src, { withFileTypes: true });
|
|
6169
|
+
for (const entry of entries) {
|
|
6170
|
+
const srcPath = path15.join(src, entry.name);
|
|
6171
|
+
const destPath = path15.join(dest, entry.name);
|
|
6172
|
+
if (entry.isDirectory()) {
|
|
6173
|
+
await this.copyDirRecursive(srcPath, destPath, substitutions);
|
|
6174
|
+
} else if (isTextFile(entry.name)) {
|
|
6175
|
+
let content = fs11.readFileSync(srcPath, "utf-8");
|
|
6176
|
+
for (const [placeholder, value] of Object.entries(substitutions)) {
|
|
6177
|
+
content = content.replaceAll(placeholder, value);
|
|
6178
|
+
}
|
|
6179
|
+
const remaining = content.match(/\{\{[a-zA-Z]+\}\}/g);
|
|
6180
|
+
if (remaining) {
|
|
6181
|
+
console.warn(`Warning: unresolved placeholders in ${entry.name}: ${remaining.join(", ")}`);
|
|
6182
|
+
}
|
|
6183
|
+
if (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx")) {
|
|
6184
|
+
try {
|
|
6185
|
+
content = await formatCode(content, destPath);
|
|
6186
|
+
} catch {}
|
|
6187
|
+
}
|
|
6188
|
+
fs11.writeFileSync(destPath, content);
|
|
6189
|
+
} else {
|
|
6190
|
+
fs11.copyFileSync(srcPath, destPath);
|
|
6191
|
+
}
|
|
6192
|
+
}
|
|
6193
|
+
}
|
|
6194
|
+
ensureEmptyDirectory() {
|
|
6195
|
+
if (!fs11.existsSync(this.projectPath)) {
|
|
6196
|
+
fs11.mkdirSync(this.projectPath, { recursive: true });
|
|
6197
|
+
}
|
|
6198
|
+
const files = fs11.readdirSync(this.projectPath);
|
|
6199
|
+
if (files.length > 0) {
|
|
6200
|
+
throw new Error(`Directory ${this.projectPath} is not empty. Please use an empty directory.`);
|
|
6201
|
+
}
|
|
5927
6202
|
}
|
|
5928
6203
|
createAgentJson() {
|
|
5929
6204
|
const agentJson = {};
|
|
5930
6205
|
this.writeJsonFile("agent.json", agentJson);
|
|
5931
6206
|
}
|
|
5932
|
-
createGitIgnore() {
|
|
5933
|
-
const gitIgnore = `# Dependencies
|
|
5934
|
-
node_modules/
|
|
5935
|
-
.pnpm-store/
|
|
5936
|
-
|
|
5937
|
-
# Build outputs
|
|
5938
|
-
dist/
|
|
5939
|
-
.adk/
|
|
5940
|
-
|
|
5941
|
-
# Environment files
|
|
5942
|
-
.env
|
|
5943
|
-
.env.local
|
|
5944
|
-
.env.production
|
|
5945
|
-
|
|
5946
|
-
# Local development
|
|
5947
|
-
agent.local.json
|
|
5948
|
-
|
|
5949
|
-
# MCP configuration (auto-generated by adk mcp:init)
|
|
5950
|
-
.mcp.json
|
|
5951
|
-
|
|
5952
|
-
# IDE files
|
|
5953
|
-
.vscode/
|
|
5954
|
-
.idea/
|
|
5955
|
-
*.swp
|
|
5956
|
-
*.swo
|
|
5957
|
-
|
|
5958
|
-
# OS files
|
|
5959
|
-
.DS_Store
|
|
5960
|
-
Thumbs.db
|
|
5961
|
-
|
|
5962
|
-
# Logs
|
|
5963
|
-
*.log
|
|
5964
|
-
logs/
|
|
5965
|
-
|
|
5966
|
-
# Runtime files
|
|
5967
|
-
*.pid
|
|
5968
|
-
*.seed
|
|
5969
|
-
*.pid.lock
|
|
5970
|
-
`;
|
|
5971
|
-
this.writeFile(".gitignore", gitIgnore);
|
|
5972
|
-
}
|
|
5973
|
-
async createReadme() {
|
|
5974
|
-
const installCommand = this.packageManager === "npm" ? "npm install" : this.packageManager === "yarn" ? "yarn install" : `${this.packageManager} install`;
|
|
5975
|
-
const readme = `# ${this.projectName}
|
|
5976
|
-
|
|
5977
|
-
A Botpress Agent built with the ADK.
|
|
5978
|
-
|
|
5979
|
-
## Getting Started
|
|
5980
|
-
|
|
5981
|
-
1. Install dependencies:
|
|
5982
|
-
\`\`\`bash
|
|
5983
|
-
${installCommand}
|
|
5984
|
-
\`\`\`
|
|
5985
|
-
|
|
5986
|
-
2. Start development server:
|
|
5987
|
-
\`\`\`bash
|
|
5988
|
-
adk dev
|
|
5989
|
-
\`\`\`
|
|
5990
|
-
|
|
5991
|
-
3. Deploy your agent:
|
|
5992
|
-
\`\`\`bash
|
|
5993
|
-
adk deploy
|
|
5994
|
-
\`\`\`
|
|
5995
|
-
|
|
5996
|
-
## Project Structure
|
|
5997
|
-
|
|
5998
|
-
- \`src/actions/\` - Define callable functions
|
|
5999
|
-
- \`src/workflows/\` - Define long-running processes
|
|
6000
|
-
- \`src/conversations/\` - Define conversation handlers
|
|
6001
|
-
- \`src/tables/\` - Define data storage schemas
|
|
6002
|
-
- \`src/triggers/\` - Define event subscriptions
|
|
6003
|
-
- \`src/knowledge/\` - Add knowledge base files
|
|
6004
|
-
|
|
6005
|
-
## Learn More
|
|
6006
|
-
|
|
6007
|
-
- [ADK Documentation](https://botpress.com/docs/adk)
|
|
6008
|
-
- [Botpress Platform](https://botpress.com)
|
|
6009
|
-
`;
|
|
6010
|
-
await this.writeFormattedFile("README.md", readme);
|
|
6011
|
-
}
|
|
6012
6207
|
createAIAssistantInstructions() {
|
|
6013
6208
|
const content = ai_assistant_instructions_template_default;
|
|
6014
6209
|
this.writeFile("CLAUDE.md", content);
|
|
6015
6210
|
this.writeFile("AGENTS.md", content);
|
|
6016
6211
|
}
|
|
6017
|
-
async createSourceStructure() {
|
|
6018
|
-
const srcPath = path15.join(this.projectPath, "src");
|
|
6019
|
-
fs11.mkdirSync(srcPath);
|
|
6020
|
-
const subdirectories = ["actions", "conversations", "knowledge", "tables", "triggers", "workflows"];
|
|
6021
|
-
for (const subdir of subdirectories) {
|
|
6022
|
-
const subdirPath = path15.join(srcPath, subdir);
|
|
6023
|
-
fs11.mkdirSync(subdirPath);
|
|
6024
|
-
if (subdir === "conversations" && this.template === "hello-world") {
|
|
6025
|
-
const conversationContent = `import { Conversation } from "@botpress/runtime";
|
|
6026
|
-
|
|
6027
|
-
export default new Conversation({
|
|
6028
|
-
channel: "*",
|
|
6029
|
-
handler: async ({ execute }) => {
|
|
6030
|
-
await execute({
|
|
6031
|
-
instructions: \`You are a helpful AI assistant built with Botpress ADK. You can assist users with their questions and tasks.\`,
|
|
6032
|
-
});
|
|
6033
|
-
},
|
|
6034
|
-
});
|
|
6035
|
-
`;
|
|
6036
|
-
await this.writeFormattedFile(path15.join("src", subdir, "index.ts"), conversationContent);
|
|
6037
|
-
} else {
|
|
6038
|
-
const placeholderContent = `/**
|
|
6039
|
-
* TODO: Add your ${subdir} here
|
|
6040
|
-
*
|
|
6041
|
-
* This is a placeholder file to initialize the ${subdir} directory.
|
|
6042
|
-
* You can delete this file once you add your own ${subdir}.
|
|
6043
|
-
*/
|
|
6044
|
-
|
|
6045
|
-
export default {};
|
|
6046
|
-
`;
|
|
6047
|
-
await this.writeFormattedFile(path15.join("src", subdir, "index.ts"), placeholderContent);
|
|
6048
|
-
}
|
|
6049
|
-
}
|
|
6050
|
-
}
|
|
6051
6212
|
writeFile(relativePath, content) {
|
|
6052
6213
|
const filePath = path15.join(this.projectPath, relativePath);
|
|
6053
6214
|
fs11.writeFileSync(filePath, content);
|
|
6054
6215
|
}
|
|
6055
|
-
async writeFormattedFile(relativePath, content) {
|
|
6056
|
-
const formatted = await formatCode(content, relativePath);
|
|
6057
|
-
this.writeFile(relativePath, formatted);
|
|
6058
|
-
}
|
|
6059
6216
|
writeJsonFile(relativePath, data) {
|
|
6060
6217
|
this.writeFile(relativePath, JSON.stringify(data, null, 2) + `
|
|
6061
6218
|
`);
|
|
@@ -7077,7 +7234,7 @@ export function createAdkClient(client: Client): AdkClient {
|
|
|
7077
7234
|
}
|
|
7078
7235
|
// src/bot-generator/generator.ts
|
|
7079
7236
|
import dedent from "dedent";
|
|
7080
|
-
import { existsSync as
|
|
7237
|
+
import { existsSync as existsSync7 } from "fs";
|
|
7081
7238
|
import fs18 from "fs/promises";
|
|
7082
7239
|
import path38 from "path";
|
|
7083
7240
|
|
|
@@ -7962,8 +8119,10 @@ async function linkSdk(agentDir, botDir) {
|
|
|
7962
8119
|
// src/bot-generator/dev-id-manager.ts
|
|
7963
8120
|
import path32 from "path";
|
|
7964
8121
|
import fs14 from "fs/promises";
|
|
7965
|
-
import
|
|
8122
|
+
import createDebug3 from "debug";
|
|
7966
8123
|
import { Client as Client14 } from "@botpress/client";
|
|
8124
|
+
var debug3 = createDebug3("adk:dev-id-manager");
|
|
8125
|
+
|
|
7967
8126
|
class DevIdManager {
|
|
7968
8127
|
projectPath;
|
|
7969
8128
|
botProjectPath;
|
|
@@ -7998,11 +8157,26 @@ class DevIdManager {
|
|
|
7998
8157
|
}
|
|
7999
8158
|
async readProjectCache() {
|
|
8000
8159
|
try {
|
|
8001
|
-
|
|
8002
|
-
|
|
8003
|
-
|
|
8160
|
+
const content = await fs14.readFile(this.projectCachePath, "utf-8");
|
|
8161
|
+
if (content.trim().length === 0) {
|
|
8162
|
+
debug3("project cache is empty, treating as bootstrap state: %s", this.projectCachePath);
|
|
8163
|
+
return {};
|
|
8004
8164
|
}
|
|
8165
|
+
const parsed = JSON.parse(content);
|
|
8166
|
+
if (!isProjectCache(parsed)) {
|
|
8167
|
+
debug3("project cache contains unexpected JSON type, treating as bootstrap state: %s", this.projectCachePath);
|
|
8168
|
+
return {};
|
|
8169
|
+
}
|
|
8170
|
+
return parsed;
|
|
8005
8171
|
} catch (error) {
|
|
8172
|
+
if (isMissingFileError(error)) {
|
|
8173
|
+
debug3("project cache missing, treating as bootstrap state: %s", this.projectCachePath);
|
|
8174
|
+
return {};
|
|
8175
|
+
}
|
|
8176
|
+
if (error instanceof SyntaxError) {
|
|
8177
|
+
debug3("project cache contains transient invalid JSON, treating as bootstrap state: %s (%O)", this.projectCachePath, error);
|
|
8178
|
+
return {};
|
|
8179
|
+
}
|
|
8006
8180
|
console.error("Error reading project.cache.json:", error);
|
|
8007
8181
|
}
|
|
8008
8182
|
return {};
|
|
@@ -8056,11 +8230,17 @@ class DevIdManager {
|
|
|
8056
8230
|
return false;
|
|
8057
8231
|
}
|
|
8058
8232
|
}
|
|
8233
|
+
function isMissingFileError(error) {
|
|
8234
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
8235
|
+
}
|
|
8236
|
+
function isProjectCache(value) {
|
|
8237
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8238
|
+
}
|
|
8059
8239
|
|
|
8060
8240
|
// src/bot-generator/integration-sync.ts
|
|
8061
8241
|
import path33 from "path";
|
|
8062
8242
|
import fs15 from "fs/promises";
|
|
8063
|
-
import { existsSync as
|
|
8243
|
+
import { existsSync as existsSync4 } from "fs";
|
|
8064
8244
|
class IntegrationSync {
|
|
8065
8245
|
projectPath;
|
|
8066
8246
|
botProjectPath;
|
|
@@ -8100,12 +8280,12 @@ class IntegrationSync {
|
|
|
8100
8280
|
}
|
|
8101
8281
|
async isIntegrationSynced(integration) {
|
|
8102
8282
|
const targetFolder = path33.join(this.bpModulesPath, `integration_${integration.alias}`);
|
|
8103
|
-
if (!
|
|
8283
|
+
if (!existsSync4(targetFolder)) {
|
|
8104
8284
|
return false;
|
|
8105
8285
|
}
|
|
8106
8286
|
try {
|
|
8107
8287
|
const indexPath = path33.join(targetFolder, "index.ts");
|
|
8108
|
-
if (!
|
|
8288
|
+
if (!existsSync4(indexPath)) {
|
|
8109
8289
|
return false;
|
|
8110
8290
|
}
|
|
8111
8291
|
const indexContent = await fs15.readFile(indexPath, "utf-8");
|
|
@@ -8138,17 +8318,17 @@ class IntegrationSync {
|
|
|
8138
8318
|
async renameIntegrationFolder(integration) {
|
|
8139
8319
|
const sourceFolder = path33.join(this.bpModulesPath, integration.name.replace("/", "-"));
|
|
8140
8320
|
const targetFolder = path33.join(this.bpModulesPath, `integration_${integration.alias}`);
|
|
8141
|
-
if (!
|
|
8321
|
+
if (!existsSync4(sourceFolder)) {
|
|
8142
8322
|
throw new Error(`Integration folder not found: ${sourceFolder}`);
|
|
8143
8323
|
}
|
|
8144
|
-
if (
|
|
8324
|
+
if (existsSync4(targetFolder)) {
|
|
8145
8325
|
await fs15.rm(targetFolder, { recursive: true, force: true });
|
|
8146
8326
|
}
|
|
8147
8327
|
await fs15.rename(sourceFolder, targetFolder);
|
|
8148
8328
|
}
|
|
8149
8329
|
async removeIntegrationFolder(alias) {
|
|
8150
8330
|
const targetFolder = path33.join(this.bpModulesPath, `integration_${alias}`);
|
|
8151
|
-
if (
|
|
8331
|
+
if (existsSync4(targetFolder)) {
|
|
8152
8332
|
await fs15.rm(targetFolder, { recursive: true, force: true });
|
|
8153
8333
|
}
|
|
8154
8334
|
}
|
|
@@ -8183,7 +8363,7 @@ class IntegrationSync {
|
|
|
8183
8363
|
// src/bot-generator/interface-sync.ts
|
|
8184
8364
|
import path34 from "path";
|
|
8185
8365
|
import fs16 from "fs/promises";
|
|
8186
|
-
import { existsSync as
|
|
8366
|
+
import { existsSync as existsSync5 } from "fs";
|
|
8187
8367
|
init_constants();
|
|
8188
8368
|
class InterfaceSync {
|
|
8189
8369
|
projectPath;
|
|
@@ -8211,12 +8391,12 @@ class InterfaceSync {
|
|
|
8211
8391
|
}
|
|
8212
8392
|
async isInterfaceSynced(interfaceInfo) {
|
|
8213
8393
|
const targetFolder = path34.join(this.bpModulesPath, `interface_${pascalCase(interfaceInfo.alias)}`);
|
|
8214
|
-
if (!
|
|
8394
|
+
if (!existsSync5(targetFolder)) {
|
|
8215
8395
|
return false;
|
|
8216
8396
|
}
|
|
8217
8397
|
try {
|
|
8218
8398
|
const indexPath = path34.join(targetFolder, "index.ts");
|
|
8219
|
-
if (!
|
|
8399
|
+
if (!existsSync5(indexPath)) {
|
|
8220
8400
|
return false;
|
|
8221
8401
|
}
|
|
8222
8402
|
const indexContent = await fs16.readFile(indexPath, "utf-8");
|
|
@@ -8263,17 +8443,17 @@ class InterfaceSync {
|
|
|
8263
8443
|
async renameInterfaceFolder(interfaceInfo) {
|
|
8264
8444
|
const sourceFolder = path34.join(this.bpModulesPath, interfaceInfo.name);
|
|
8265
8445
|
const targetFolder = path34.join(this.bpModulesPath, `interface_${pascalCase(interfaceInfo.alias)}`);
|
|
8266
|
-
if (!
|
|
8446
|
+
if (!existsSync5(sourceFolder)) {
|
|
8267
8447
|
throw new Error(`Interface folder not found: ${sourceFolder}`);
|
|
8268
8448
|
}
|
|
8269
|
-
if (
|
|
8449
|
+
if (existsSync5(targetFolder)) {
|
|
8270
8450
|
await fs16.rm(targetFolder, { recursive: true, force: true });
|
|
8271
8451
|
}
|
|
8272
8452
|
await fs16.rename(sourceFolder, targetFolder);
|
|
8273
8453
|
}
|
|
8274
8454
|
async removeInterfaceFolder(alias) {
|
|
8275
8455
|
const targetFolder = path34.join(this.bpModulesPath, `interface_${pascalCase(alias)}`);
|
|
8276
|
-
if (
|
|
8456
|
+
if (existsSync5(targetFolder)) {
|
|
8277
8457
|
await fs16.rm(targetFolder, { recursive: true, force: true });
|
|
8278
8458
|
}
|
|
8279
8459
|
}
|
|
@@ -8308,7 +8488,7 @@ class InterfaceSync {
|
|
|
8308
8488
|
// src/bot-generator/plugin-sync.ts
|
|
8309
8489
|
import path35 from "path";
|
|
8310
8490
|
import fs17 from "fs/promises";
|
|
8311
|
-
import { existsSync as
|
|
8491
|
+
import { existsSync as existsSync6 } from "fs";
|
|
8312
8492
|
class PluginSync {
|
|
8313
8493
|
projectPath;
|
|
8314
8494
|
botProjectPath;
|
|
@@ -8340,12 +8520,12 @@ class PluginSync {
|
|
|
8340
8520
|
}
|
|
8341
8521
|
async isPluginSynced(plugin) {
|
|
8342
8522
|
const targetFolder = path35.join(this.bpModulesPath, `plugin_${plugin.alias}`);
|
|
8343
|
-
if (!
|
|
8523
|
+
if (!existsSync6(targetFolder)) {
|
|
8344
8524
|
return false;
|
|
8345
8525
|
}
|
|
8346
8526
|
try {
|
|
8347
8527
|
const indexPath = path35.join(targetFolder, "index.ts");
|
|
8348
|
-
if (!
|
|
8528
|
+
if (!existsSync6(indexPath)) {
|
|
8349
8529
|
return false;
|
|
8350
8530
|
}
|
|
8351
8531
|
const indexContent = await fs17.readFile(indexPath, "utf-8");
|
|
@@ -8378,17 +8558,17 @@ class PluginSync {
|
|
|
8378
8558
|
async renamePluginFolder(plugin) {
|
|
8379
8559
|
const sourceFolder = path35.join(this.bpModulesPath, plugin.name.replace("/", "-"));
|
|
8380
8560
|
const targetFolder = path35.join(this.bpModulesPath, `plugin_${plugin.alias}`);
|
|
8381
|
-
if (!
|
|
8561
|
+
if (!existsSync6(sourceFolder)) {
|
|
8382
8562
|
throw new Error(`Plugin folder not found: ${sourceFolder}`);
|
|
8383
8563
|
}
|
|
8384
|
-
if (
|
|
8564
|
+
if (existsSync6(targetFolder)) {
|
|
8385
8565
|
await fs17.rm(targetFolder, { recursive: true, force: true });
|
|
8386
8566
|
}
|
|
8387
8567
|
await fs17.rename(sourceFolder, targetFolder);
|
|
8388
8568
|
}
|
|
8389
8569
|
async removePluginFolder(alias) {
|
|
8390
8570
|
const targetFolder = path35.join(this.bpModulesPath, `plugin_${alias}`);
|
|
8391
|
-
if (
|
|
8571
|
+
if (existsSync6(targetFolder)) {
|
|
8392
8572
|
await fs17.rm(targetFolder, { recursive: true, force: true });
|
|
8393
8573
|
}
|
|
8394
8574
|
}
|
|
@@ -8451,7 +8631,7 @@ class BotGenerator {
|
|
|
8451
8631
|
}
|
|
8452
8632
|
async listFilesRecursive(rootDir) {
|
|
8453
8633
|
try {
|
|
8454
|
-
if (!
|
|
8634
|
+
if (!existsSync7(rootDir))
|
|
8455
8635
|
return [];
|
|
8456
8636
|
const result = [];
|
|
8457
8637
|
const walk = async (dir, relativeBase) => {
|
|
@@ -8473,7 +8653,7 @@ class BotGenerator {
|
|
|
8473
8653
|
}
|
|
8474
8654
|
}
|
|
8475
8655
|
async removeEmptyDirectories(rootDir) {
|
|
8476
|
-
if (!
|
|
8656
|
+
if (!existsSync7(rootDir))
|
|
8477
8657
|
return;
|
|
8478
8658
|
const removeIfEmpty = async (dir) => {
|
|
8479
8659
|
const entries = await fs18.readdir(dir, { withFileTypes: true });
|
|
@@ -8679,7 +8859,7 @@ class BotGenerator {
|
|
|
8679
8859
|
const integrations = await manager3.loadIntegrations(project.dependencies || {});
|
|
8680
8860
|
const channels = [];
|
|
8681
8861
|
for (const integration of integrations.integrations) {
|
|
8682
|
-
if (integration.
|
|
8862
|
+
if (integration.definition) {
|
|
8683
8863
|
const alias = integration.alias;
|
|
8684
8864
|
for (const channelName of Object.keys(integration.definition.channels || {})) {
|
|
8685
8865
|
channels.push(`"${alias}.${channelName}"`);
|
|
@@ -8737,7 +8917,7 @@ declare module "@botpress/runtime/_types/state" {
|
|
|
8737
8917
|
const interfacesDir = path38.join(this.projectPath, ".adk", "interfaces");
|
|
8738
8918
|
const existingInterfaceFiles = await this.listFilesRecursive(interfacesDir);
|
|
8739
8919
|
const interfaces = await manager3.loadInterfaces(project.dependencies || {}).then((result) => result.interfaces.filter((int) => int.definition).map((x) => x.definition));
|
|
8740
|
-
const integrationsWithAlias = await integrationManager.loadIntegrations(project.dependencies || {}).then((result) => result.integrations.filter((int) => int.
|
|
8920
|
+
const integrationsWithAlias = await integrationManager.loadIntegrations(project.dependencies || {}).then((result) => result.integrations.filter((int) => int.definition).map((x) => ({ alias: x.alias, definition: x.definition })));
|
|
8741
8921
|
let imports = new Set;
|
|
8742
8922
|
let aliases = new Set;
|
|
8743
8923
|
let files = new Set;
|
|
@@ -8802,10 +8982,7 @@ declare module "@botpress/runtime/_types/state" {
|
|
|
8802
8982
|
const integrations = project.dependencies?.integrations || {};
|
|
8803
8983
|
const imports = [];
|
|
8804
8984
|
const integrationDefs = [];
|
|
8805
|
-
for (const [alias
|
|
8806
|
-
if (config.enabled === false) {
|
|
8807
|
-
continue;
|
|
8808
|
-
}
|
|
8985
|
+
for (const [alias] of Object.entries(integrations)) {
|
|
8809
8986
|
const normalizedAlias = getIntegrationAlias(alias);
|
|
8810
8987
|
imports.push(`import integration_${normalizedAlias} from "../bp_modules/integration_${normalizedAlias}";`);
|
|
8811
8988
|
integrationDefs.push(`"${alias}": integration_${normalizedAlias}`);
|
|
@@ -8907,21 +9084,21 @@ declare module "@botpress/runtime/_types/state" {
|
|
|
8907
9084
|
async generateBotDefinition() {
|
|
8908
9085
|
const project = await AgentProject.load(this.projectPath);
|
|
8909
9086
|
const integrations = project.integrations;
|
|
8910
|
-
const enabledIntegrations = integrations.filter((i) => i.enabled);
|
|
8911
9087
|
const isDeployOrBuild = this.adkCommand === "adk-deploy" || this.adkCommand === "adk-build";
|
|
8912
9088
|
const configTargetBotId = isDeployOrBuild ? project.agentInfo?.botId : undefined;
|
|
8913
9089
|
const serverConfigResult = await fetchServerIntegrationConfigs(project, configTargetBotId);
|
|
8914
|
-
this.reportServerConfigSync(serverConfigResult,
|
|
9090
|
+
this.reportServerConfigSync(serverConfigResult, integrations);
|
|
8915
9091
|
const imports = [];
|
|
8916
9092
|
const addIntegrations = [];
|
|
8917
|
-
for (const integration of
|
|
9093
|
+
for (const integration of integrations) {
|
|
8918
9094
|
const { alias, configurationType, config } = integration;
|
|
8919
9095
|
const importName = `integration_${getIntegrationAlias(alias)}`;
|
|
8920
9096
|
imports.push(`import ${importName} from "./bp_modules/${importName}";`);
|
|
8921
9097
|
const configType = configurationType && configurationType !== "default" ? `, configurationType: "${configurationType}"` : "";
|
|
8922
9098
|
const mergedConfig = mergeIntegrationConfig(serverConfigResult.configs[alias], config);
|
|
8923
9099
|
const configData = Object.keys(mergedConfig).length > 0 ? `, configuration: ${JSON.stringify(mergedConfig)}` : "";
|
|
8924
|
-
|
|
9100
|
+
const enabled = integration.enabled ?? serverConfigResult.enabledStates[alias] ?? false;
|
|
9101
|
+
addIntegrations.push(`bot.addIntegration(${importName}, { alias: "${alias}", enabled: ${enabled}${configType}${configData} });`);
|
|
8925
9102
|
}
|
|
8926
9103
|
const depRefErrors = PluginParser.validateDependencyReferences(project.dependencies || {});
|
|
8927
9104
|
if (depRefErrors.length > 0) {
|
|
@@ -9350,7 +9527,7 @@ export default bot;`;
|
|
|
9350
9527
|
async copyAssets() {
|
|
9351
9528
|
const assetsPath = path38.join(this.projectPath, "assets");
|
|
9352
9529
|
const targetPath = path38.join(this.outputPath, "assets");
|
|
9353
|
-
if (
|
|
9530
|
+
if (existsSync7(assetsPath)) {
|
|
9354
9531
|
await fs18.mkdir(targetPath, { recursive: true });
|
|
9355
9532
|
await this.copyDirectory(assetsPath, targetPath);
|
|
9356
9533
|
}
|
|
@@ -9688,7 +9865,7 @@ export default bot;`;
|
|
|
9688
9865
|
}
|
|
9689
9866
|
async copyAssetsRuntime() {
|
|
9690
9867
|
const assetsRuntimePath = path38.join(this.projectPath, ".adk", "assets-runtime.ts");
|
|
9691
|
-
if (
|
|
9868
|
+
if (existsSync7(assetsRuntimePath)) {
|
|
9692
9869
|
const content = await fs18.readFile(assetsRuntimePath, "utf-8");
|
|
9693
9870
|
await createFile(path38.join(this.outputPath, "src", "assets-runtime.ts"), await formatCode(content));
|
|
9694
9871
|
}
|
|
@@ -10752,6 +10929,7 @@ class KnowledgeManager {
|
|
|
10752
10929
|
const sourcesToSync = options.force ? item.sources || [] : (item.sources || []).filter((s) => s.needsSync);
|
|
10753
10930
|
const directorySourcesToSync = sourcesToSync.filter((s) => s.dsType === "document");
|
|
10754
10931
|
const websiteSourcesToSync = sourcesToSync.filter((s) => s.dsType === "web-page");
|
|
10932
|
+
let currentTags = { ...remoteKb.tags ?? {} };
|
|
10755
10933
|
for (const sourceStatus of directorySourcesToSync) {
|
|
10756
10934
|
const source = kbRef.definition.sources?.find((s) => s.id === sourceStatus.dsId);
|
|
10757
10935
|
if (!source || !DataSource.isDirectory(source))
|
|
@@ -10764,27 +10942,52 @@ class KnowledgeManager {
|
|
|
10764
10942
|
syncOutput.deleted.push(...sourceOutput.deleted);
|
|
10765
10943
|
syncOutput.errors.push(...sourceOutput.errors);
|
|
10766
10944
|
const sourceHash = await this.computeDirectorySourceHash(source.directoryPath, source.filterFn);
|
|
10767
|
-
await this.updateSourceHash(remoteKb.id, item.kb.name, source.id, sourceHash,
|
|
10945
|
+
await this.updateSourceHash(remoteKb.id, item.kb.name, source.id, sourceHash, currentTags);
|
|
10946
|
+
currentTags = {
|
|
10947
|
+
...currentTags,
|
|
10948
|
+
[sourceTag(source.id, "hash")]: sourceHash,
|
|
10949
|
+
[sourceTag(source.id, "lastupdatedat")]: new Date().toISOString()
|
|
10950
|
+
};
|
|
10768
10951
|
}
|
|
10769
|
-
|
|
10952
|
+
for (const sourceStatus of websiteSourcesToSync) {
|
|
10953
|
+
const source = kbRef.definition.sources?.find((s) => s.id === sourceStatus.dsId);
|
|
10954
|
+
if (!source || !DataSource.isWebsite(source))
|
|
10955
|
+
continue;
|
|
10956
|
+
const config = source.getConfig();
|
|
10957
|
+
if (config.mode === "website") {
|
|
10958
|
+
console.warn(` ⚠️ Skipping website source "${source.id}": website mode requires browser integration for URL discovery. Use WebsiteSource.fromSitemap() instead.`);
|
|
10959
|
+
continue;
|
|
10960
|
+
}
|
|
10961
|
+
if (config.fetchStrategy === "integration:browser") {
|
|
10962
|
+
console.warn(` ⚠️ Skipping website source "${source.id}": integration:browser fetch strategy requires browser integration. Use fetch: 'node:fetch' or a custom fetch function instead.`);
|
|
10963
|
+
continue;
|
|
10964
|
+
}
|
|
10965
|
+
await this.deleteLegacyWebsiteFiles(item.kb.name, sourceStatus.dsId);
|
|
10770
10966
|
try {
|
|
10771
|
-
|
|
10772
|
-
|
|
10773
|
-
|
|
10774
|
-
|
|
10775
|
-
|
|
10776
|
-
|
|
10777
|
-
|
|
10778
|
-
|
|
10779
|
-
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
|
|
10783
|
-
|
|
10784
|
-
|
|
10967
|
+
this.assertBotId("sync website source");
|
|
10968
|
+
console.log(` Syncing website source "${source.id}" locally...`);
|
|
10969
|
+
const sourceOutput = await source.syncDirect(client, this.botId, {
|
|
10970
|
+
dsId: source.id,
|
|
10971
|
+
kbName: item.kb.name,
|
|
10972
|
+
kbId: remoteKb.id,
|
|
10973
|
+
force: options.force || false
|
|
10974
|
+
});
|
|
10975
|
+
syncOutput.processed += sourceOutput.processed;
|
|
10976
|
+
syncOutput.added.push(...sourceOutput.added);
|
|
10977
|
+
syncOutput.updated.push(...sourceOutput.updated);
|
|
10978
|
+
syncOutput.deleted.push(...sourceOutput.deleted);
|
|
10979
|
+
syncOutput.errors.push(...sourceOutput.errors.map((e) => typeof e === "string" ? { file: source.id, error: e } : e));
|
|
10980
|
+
const configHash = this.computeConfigHash(config);
|
|
10981
|
+
await this.updateSourceHash(remoteKb.id, item.kb.name, source.id, configHash, currentTags);
|
|
10982
|
+
currentTags = {
|
|
10983
|
+
...currentTags,
|
|
10984
|
+
[sourceTag(source.id, "hash")]: configHash,
|
|
10985
|
+
[sourceTag(source.id, "lastupdatedat")]: new Date().toISOString()
|
|
10986
|
+
};
|
|
10785
10987
|
} catch (error) {
|
|
10786
10988
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
10787
|
-
console.
|
|
10989
|
+
console.error(` Failed to sync website source "${source.id}": ${errorMsg}`);
|
|
10990
|
+
syncOutput.errors.push({ file: source.id, error: errorMsg });
|
|
10788
10991
|
}
|
|
10789
10992
|
}
|
|
10790
10993
|
result.synced.push({ name: item.kb.name, result: syncOutput });
|
|
@@ -10928,7 +11131,7 @@ class KnowledgeManager {
|
|
|
10928
11131
|
}
|
|
10929
11132
|
}
|
|
10930
11133
|
// src/knowledge/sync-formatter.ts
|
|
10931
|
-
import { readFileSync } from "fs";
|
|
11134
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
10932
11135
|
import { join as join8 } from "path";
|
|
10933
11136
|
var getAdkVersion = () => {
|
|
10934
11137
|
try {
|
|
@@ -10937,7 +11140,7 @@ var getAdkVersion = () => {
|
|
|
10937
11140
|
} catch {
|
|
10938
11141
|
try {
|
|
10939
11142
|
const adkPackagePath = join8(process.cwd(), "node_modules/@botpress/adk/package.json");
|
|
10940
|
-
const pkg = JSON.parse(
|
|
11143
|
+
const pkg = JSON.parse(readFileSync3(adkPackagePath, "utf-8"));
|
|
10941
11144
|
return pkg.version;
|
|
10942
11145
|
} catch {
|
|
10943
11146
|
return "unknown";
|
|
@@ -11031,7 +11234,7 @@ class KBSyncFormatter {
|
|
|
11031
11234
|
import { watch as watch2, readdirSync as readdirSync2, statSync } from "fs";
|
|
11032
11235
|
import { EventEmitter as EventEmitter3 } from "events";
|
|
11033
11236
|
import { join as join9, relative as relative3 } from "path";
|
|
11034
|
-
import { existsSync as
|
|
11237
|
+
import { existsSync as existsSync8 } from "fs";
|
|
11035
11238
|
|
|
11036
11239
|
class FileWatcher2 extends EventEmitter3 {
|
|
11037
11240
|
projectPath;
|
|
@@ -11049,12 +11252,12 @@ class FileWatcher2 extends EventEmitter3 {
|
|
|
11049
11252
|
const rootFiles = ["package.json", "agent.json", "agent.config.ts"];
|
|
11050
11253
|
for (const file of rootFiles) {
|
|
11051
11254
|
const filePath = join9(this.projectPath, file);
|
|
11052
|
-
if (
|
|
11255
|
+
if (existsSync8(filePath)) {
|
|
11053
11256
|
this.watchFile(filePath);
|
|
11054
11257
|
}
|
|
11055
11258
|
}
|
|
11056
11259
|
const srcPath = join9(this.projectPath, "src");
|
|
11057
|
-
if (
|
|
11260
|
+
if (existsSync8(srcPath)) {
|
|
11058
11261
|
this.initializeDirectoryState(srcPath);
|
|
11059
11262
|
this.watchDirectory(srcPath);
|
|
11060
11263
|
}
|
|
@@ -11104,12 +11307,12 @@ class FileWatcher2 extends EventEmitter3 {
|
|
|
11104
11307
|
}
|
|
11105
11308
|
handleFileChange(filePath) {
|
|
11106
11309
|
try {
|
|
11107
|
-
if (
|
|
11310
|
+
if (existsSync8(filePath) && statSync(filePath).isDirectory()) {
|
|
11108
11311
|
this.scanDirectoryForChanges(filePath);
|
|
11109
11312
|
return;
|
|
11110
11313
|
}
|
|
11111
11314
|
} catch {}
|
|
11112
|
-
const fileExists =
|
|
11315
|
+
const fileExists = existsSync8(filePath);
|
|
11113
11316
|
const previousState = this.fileStates.get(filePath);
|
|
11114
11317
|
let changeType;
|
|
11115
11318
|
if (!fileExists && previousState !== undefined) {
|
|
@@ -11182,7 +11385,7 @@ class FileWatcher2 extends EventEmitter3 {
|
|
|
11182
11385
|
}, this.debounceMs);
|
|
11183
11386
|
}
|
|
11184
11387
|
updateFileState(filePath) {
|
|
11185
|
-
if (
|
|
11388
|
+
if (existsSync8(filePath)) {
|
|
11186
11389
|
this.fileStates.set(filePath, Date.now());
|
|
11187
11390
|
}
|
|
11188
11391
|
}
|
|
@@ -11264,7 +11467,7 @@ class AgentConfigSyncManager {
|
|
|
11264
11467
|
}
|
|
11265
11468
|
|
|
11266
11469
|
// src/preflight/formatter.ts
|
|
11267
|
-
import { readFileSync as
|
|
11470
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
11268
11471
|
import { join as join10 } from "path";
|
|
11269
11472
|
var getAdkVersion2 = () => {
|
|
11270
11473
|
try {
|
|
@@ -11273,7 +11476,7 @@ var getAdkVersion2 = () => {
|
|
|
11273
11476
|
} catch {
|
|
11274
11477
|
try {
|
|
11275
11478
|
const adkPackagePath = join10(process.cwd(), "node_modules/@botpress/adk/package.json");
|
|
11276
|
-
const pkg = JSON.parse(
|
|
11479
|
+
const pkg = JSON.parse(readFileSync4(adkPackagePath, "utf-8"));
|
|
11277
11480
|
return pkg.version;
|
|
11278
11481
|
} catch {
|
|
11279
11482
|
return "unknown";
|
|
@@ -11455,9 +11658,6 @@ class PreflightChecker {
|
|
|
11455
11658
|
const toRemove = [];
|
|
11456
11659
|
const toUpdate = [];
|
|
11457
11660
|
for (const result of results) {
|
|
11458
|
-
if (result.desiredInstallStatus === "disabled" && !result.needsRemoval && !result.needsConfiguration) {
|
|
11459
|
-
continue;
|
|
11460
|
-
}
|
|
11461
11661
|
if (result.needsInstall) {
|
|
11462
11662
|
toInstall.push({
|
|
11463
11663
|
alias: result.alias,
|
|
@@ -11577,7 +11777,7 @@ class PreflightChecker {
|
|
|
11577
11777
|
}
|
|
11578
11778
|
// src/runner/script-runner.ts
|
|
11579
11779
|
import dedent2 from "dedent";
|
|
11580
|
-
import { existsSync as
|
|
11780
|
+
import { existsSync as existsSync9 } from "fs";
|
|
11581
11781
|
import fs20 from "fs/promises";
|
|
11582
11782
|
import path41 from "path";
|
|
11583
11783
|
import { spawn } from "child_process";
|
|
@@ -11615,7 +11815,7 @@ class ScriptRunner {
|
|
|
11615
11815
|
const botPath = path41.join(this.projectPath, ".adk", "bot");
|
|
11616
11816
|
const runnerPath = path41.join(botPath, "src", "script-runner.ts");
|
|
11617
11817
|
const botpressTypesPath = path41.join(botPath, ".botpress", "implementation", "index.ts");
|
|
11618
|
-
const needsRegenerate = this.forceRegenerate || !
|
|
11818
|
+
const needsRegenerate = this.forceRegenerate || !existsSync9(runnerPath) || !existsSync9(botpressTypesPath);
|
|
11619
11819
|
if (needsRegenerate) {
|
|
11620
11820
|
try {
|
|
11621
11821
|
await generateAssetsTypes(project.path);
|
|
@@ -11773,7 +11973,7 @@ class ScriptRunner {
|
|
|
11773
11973
|
initialize: async () => {
|
|
11774
11974
|
const botModule = await import(runtimePath);
|
|
11775
11975
|
const runtimeModule = await import("@botpress/runtime/runtime");
|
|
11776
|
-
const { Autonomous } = await import("@botpress/runtime");
|
|
11976
|
+
const { Autonomous: Autonomous2 } = await import("@botpress/runtime");
|
|
11777
11977
|
const { context, agentRegistry } = runtimeModule;
|
|
11778
11978
|
const { Client: Client18 } = await import("@botpress/client");
|
|
11779
11979
|
const { BotSpecificClient, BotLogger } = await import("@botpress/sdk");
|
|
@@ -11795,7 +11995,7 @@ class ScriptRunner {
|
|
|
11795
11995
|
botId,
|
|
11796
11996
|
client,
|
|
11797
11997
|
cognitive,
|
|
11798
|
-
citations: new
|
|
11998
|
+
citations: new Autonomous2.CitationsManager,
|
|
11799
11999
|
logger,
|
|
11800
12000
|
configuration: configuration ?? {},
|
|
11801
12001
|
integrations: agentRegistry.integrations,
|
|
@@ -11811,7 +12011,7 @@ class ScriptRunner {
|
|
|
11811
12011
|
async run(scriptPath, options = {}) {
|
|
11812
12012
|
const { botPath, runnerPath, project } = await this.prepare();
|
|
11813
12013
|
const absoluteScriptPath = path41.isAbsolute(scriptPath) ? scriptPath : path41.resolve(this.projectPath, scriptPath);
|
|
11814
|
-
if (!
|
|
12014
|
+
if (!existsSync9(absoluteScriptPath)) {
|
|
11815
12015
|
throw new Error(`Script not found: ${absoluteScriptPath}`);
|
|
11816
12016
|
}
|
|
11817
12017
|
const botId = this.prod ? project.agentInfo?.botId : project.agentInfo?.devId || project.agentInfo?.botId;
|
|
@@ -11900,42 +12100,78 @@ Either run from within an agent project directory, or provide projectPath explic
|
|
|
11900
12100
|
return runner.setupTestRuntime({ env: options.env });
|
|
11901
12101
|
}
|
|
11902
12102
|
// src/eval/types.ts
|
|
11903
|
-
|
|
11904
|
-
|
|
12103
|
+
class Eval {
|
|
12104
|
+
name;
|
|
12105
|
+
description;
|
|
12106
|
+
tags;
|
|
12107
|
+
type;
|
|
12108
|
+
setup;
|
|
12109
|
+
conversation;
|
|
12110
|
+
outcome;
|
|
12111
|
+
options;
|
|
12112
|
+
constructor(def) {
|
|
12113
|
+
this.name = def.name;
|
|
12114
|
+
this.description = def.description;
|
|
12115
|
+
this.tags = def.tags;
|
|
12116
|
+
this.type = def.type;
|
|
12117
|
+
this.setup = def.setup;
|
|
12118
|
+
this.conversation = def.conversation;
|
|
12119
|
+
this.outcome = def.outcome;
|
|
12120
|
+
this.options = def.options;
|
|
12121
|
+
}
|
|
11905
12122
|
}
|
|
11906
12123
|
// src/eval/loader.ts
|
|
11907
|
-
import { readdirSync as readdirSync3, existsSync as
|
|
12124
|
+
import { readdirSync as readdirSync3, existsSync as existsSync10 } from "fs";
|
|
11908
12125
|
import { resolve as resolve3 } from "path";
|
|
12126
|
+
function isEvalDefinition(value) {
|
|
12127
|
+
return value !== null && typeof value === "object" && typeof value.name === "string" && value.name !== "" && Array.isArray(value.conversation);
|
|
12128
|
+
}
|
|
11909
12129
|
async function loadEvalFile(filePath) {
|
|
11910
12130
|
const absPath = resolve3(filePath);
|
|
11911
12131
|
const mod = await import(absPath);
|
|
11912
|
-
const
|
|
11913
|
-
|
|
11914
|
-
|
|
12132
|
+
const results = [];
|
|
12133
|
+
for (const [key, value] of Object.entries(mod)) {
|
|
12134
|
+
if (key === "__esModule")
|
|
12135
|
+
continue;
|
|
12136
|
+
if (value instanceof Eval || isEvalDefinition(value)) {
|
|
12137
|
+
results.push(value);
|
|
12138
|
+
}
|
|
11915
12139
|
}
|
|
11916
|
-
|
|
12140
|
+
if (results.length === 0) {
|
|
12141
|
+
throw new Error(`Invalid eval file ${filePath}: no valid evals found. Export one or more \`new Eval({...})\` instances (as default or named exports).`);
|
|
12142
|
+
}
|
|
12143
|
+
return results;
|
|
11917
12144
|
}
|
|
11918
12145
|
async function loadEvalsFromDir(dirPath) {
|
|
11919
12146
|
const absDir = resolve3(dirPath);
|
|
11920
|
-
if (!
|
|
12147
|
+
if (!existsSync10(absDir)) {
|
|
11921
12148
|
return [];
|
|
11922
12149
|
}
|
|
11923
12150
|
const files = readdirSync3(absDir).filter((f) => f.endsWith(".eval.ts"));
|
|
11924
12151
|
const evals = [];
|
|
11925
12152
|
for (const f of files) {
|
|
11926
|
-
|
|
12153
|
+
const defs = await loadEvalFile(`${absDir}/${f}`);
|
|
12154
|
+
evals.push(...defs);
|
|
12155
|
+
}
|
|
12156
|
+
const seen = new Set;
|
|
12157
|
+
for (const e of evals) {
|
|
12158
|
+
if (seen.has(e.name)) {
|
|
12159
|
+
throw new Error(`Duplicate eval name "${e.name}" found in ${dirPath}`);
|
|
12160
|
+
}
|
|
12161
|
+
seen.add(e.name);
|
|
11927
12162
|
}
|
|
11928
12163
|
return evals;
|
|
11929
12164
|
}
|
|
11930
12165
|
async function loadEvalByName(dirPath, name) {
|
|
11931
12166
|
const absDir = resolve3(dirPath);
|
|
11932
|
-
if (!
|
|
12167
|
+
if (!existsSync10(absDir))
|
|
11933
12168
|
return null;
|
|
11934
12169
|
const files = readdirSync3(absDir).filter((f) => f.endsWith(".eval.ts"));
|
|
11935
12170
|
for (const f of files) {
|
|
11936
|
-
const
|
|
11937
|
-
|
|
11938
|
-
|
|
12171
|
+
const defs = await loadEvalFile(`${absDir}/${f}`);
|
|
12172
|
+
const found = defs.find((d) => d.name === name);
|
|
12173
|
+
if (found)
|
|
12174
|
+
return found;
|
|
11939
12175
|
}
|
|
11940
12176
|
return null;
|
|
11941
12177
|
}
|
|
@@ -13089,11 +13325,11 @@ async function runEvalSuite(config, filter) {
|
|
|
13089
13325
|
return runReport;
|
|
13090
13326
|
}
|
|
13091
13327
|
// src/eval/store.ts
|
|
13092
|
-
import { existsSync as
|
|
13328
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "fs";
|
|
13093
13329
|
import { join as join11 } from "path";
|
|
13094
13330
|
function getRunsDir(agentPath) {
|
|
13095
13331
|
const dir = join11(agentPath, ".adk", "evals", "runs");
|
|
13096
|
-
if (!
|
|
13332
|
+
if (!existsSync11(dir)) {
|
|
13097
13333
|
mkdirSync2(dir, { recursive: true });
|
|
13098
13334
|
}
|
|
13099
13335
|
return dir;
|
|
@@ -13111,19 +13347,19 @@ function loadRunResult(agentPath, runId) {
|
|
|
13111
13347
|
for (const file of files) {
|
|
13112
13348
|
if (file.includes(runId)) {
|
|
13113
13349
|
const filepath = join11(dir, file);
|
|
13114
|
-
return JSON.parse(
|
|
13350
|
+
return JSON.parse(readFileSync5(filepath, "utf-8"));
|
|
13115
13351
|
}
|
|
13116
13352
|
}
|
|
13117
13353
|
return null;
|
|
13118
13354
|
}
|
|
13119
13355
|
function listRunResults(agentPath, limit = 50) {
|
|
13120
13356
|
const dir = getRunsDir(agentPath);
|
|
13121
|
-
if (!
|
|
13357
|
+
if (!existsSync11(dir))
|
|
13122
13358
|
return [];
|
|
13123
13359
|
const files = readdirSync4(dir).filter((f) => f.endsWith(".json")).sort().reverse().slice(0, limit);
|
|
13124
13360
|
return files.map((file) => {
|
|
13125
13361
|
const filepath = join11(dir, file);
|
|
13126
|
-
return JSON.parse(
|
|
13362
|
+
return JSON.parse(readFileSync5(filepath, "utf-8"));
|
|
13127
13363
|
});
|
|
13128
13364
|
}
|
|
13129
13365
|
function getLatestRun(agentPath) {
|
|
@@ -13157,7 +13393,6 @@ export {
|
|
|
13157
13393
|
generateAssetsRuntime,
|
|
13158
13394
|
filterEvals,
|
|
13159
13395
|
dependenciesKeyOrder,
|
|
13160
|
-
defineEval,
|
|
13161
13396
|
coerceConfigValue,
|
|
13162
13397
|
buildOpenCodeConfig,
|
|
13163
13398
|
bpCliImporter,
|
|
@@ -13189,6 +13424,7 @@ export {
|
|
|
13189
13424
|
IntegrationCache,
|
|
13190
13425
|
HubCache,
|
|
13191
13426
|
FileWatcher2 as FileWatcher,
|
|
13427
|
+
Eval,
|
|
13192
13428
|
EnhancedInterfaceCache,
|
|
13193
13429
|
DevIdManager,
|
|
13194
13430
|
CredentialsManager,
|
|
@@ -13209,4 +13445,4 @@ export {
|
|
|
13209
13445
|
AgentProject
|
|
13210
13446
|
};
|
|
13211
13447
|
|
|
13212
|
-
//# debugId=
|
|
13448
|
+
//# debugId=F162F419B9B9DD1664756E2164756E21
|