@botpress/adk 1.16.7 → 1.17.0
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.map +1 -1
- package/dist/agent-project/agent-project.d.ts +9 -1
- package/dist/agent-project/agent-project.d.ts.map +1 -1
- package/dist/agent-project/agent-resolver.d.ts.map +1 -1
- package/dist/agent-project/dependencies-parser.d.ts.map +1 -1
- package/dist/agent-project/types.d.ts +27 -19
- package/dist/agent-project/types.d.ts.map +1 -1
- package/dist/agent-project/validation-errors.d.ts.map +1 -1
- package/dist/auth/credentials.d.ts +15 -1
- package/dist/auth/credentials.d.ts.map +1 -1
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/bot-generator/generator.d.ts.map +1 -1
- package/dist/commands/base-command.d.ts.map +1 -1
- package/dist/commands/bp-add-command.d.ts.map +1 -1
- package/dist/commands/bp-build-command.d.ts.map +1 -1
- package/dist/commands/bp-chat-command.d.ts.map +1 -1
- package/dist/commands/bp-deploy-command.d.ts.map +1 -1
- package/dist/commands/bp-dev-command.d.ts +2 -2
- package/dist/commands/bp-dev-command.d.ts.map +1 -1
- package/dist/commands/opencode-command.d.ts +2 -2
- package/dist/commands/opencode-command.d.ts.map +1 -1
- package/dist/commands/opencode-config.d.ts +1 -1
- package/dist/commands/opencode-config.d.ts.map +1 -1
- package/dist/config/coerce-config-value.d.ts.map +1 -1
- package/dist/config/manager.d.ts +5 -5
- package/dist/config/manager.d.ts.map +1 -1
- package/dist/eval/client.d.ts +8 -0
- package/dist/eval/client.d.ts.map +1 -1
- package/dist/eval/graders/index.d.ts +1 -0
- package/dist/eval/graders/index.d.ts.map +1 -1
- package/dist/eval/graders/llm.d.ts +6 -2
- package/dist/eval/graders/llm.d.ts.map +1 -1
- package/dist/eval/graders/response.d.ts +1 -0
- package/dist/eval/graders/response.d.ts.map +1 -1
- package/dist/eval/graders/state.d.ts +1 -1
- package/dist/eval/graders/state.d.ts.map +1 -1
- package/dist/eval/graders/tables.d.ts.map +1 -1
- package/dist/eval/graders/timing.d.ts +7 -0
- package/dist/eval/graders/timing.d.ts.map +1 -0
- package/dist/eval/graders/workflow.d.ts.map +1 -1
- package/dist/eval/index.d.ts +2 -2
- package/dist/eval/index.d.ts.map +1 -1
- package/dist/eval/runner.d.ts +1 -0
- package/dist/eval/runner.d.ts.map +1 -1
- package/dist/eval/traces.d.ts.map +1 -1
- package/dist/eval/types.d.ts +47 -2
- package/dist/eval/types.d.ts.map +1 -1
- package/dist/file-watcher/watcher.d.ts +9 -0
- package/dist/file-watcher/watcher.d.ts.map +1 -1
- package/dist/generators/client-wrapper.d.ts.map +1 -1
- package/dist/generators/conversation-types.d.ts.map +1 -1
- package/dist/generators/integration-types.d.ts.map +1 -1
- package/dist/generators/interface-types.d.ts.map +1 -1
- package/dist/generators/plugin-types.d.ts.map +1 -1
- package/dist/generators/table-types.d.ts.map +1 -1
- package/dist/generators/tests.d.ts.map +1 -1
- package/dist/generators/workflow-types.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +522 -158
- package/dist/index.js.map +58 -57
- package/dist/integrations/checker.d.ts +2 -2
- package/dist/integrations/checker.d.ts.map +1 -1
- package/dist/integrations/config-utils.d.ts +3 -3
- package/dist/integrations/config-utils.d.ts.map +1 -1
- package/dist/integrations/types.d.ts +1 -1
- package/dist/integrations/types.d.ts.map +1 -1
- package/dist/interfaces/manager.d.ts.map +1 -1
- package/dist/interfaces/types.d.ts +1 -1
- package/dist/interfaces/types.d.ts.map +1 -1
- package/dist/knowledge/manager.d.ts.map +1 -1
- package/dist/plugins/types.d.ts +1 -1
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/preflight/agent-config-sync.d.ts +2 -1
- package/dist/preflight/agent-config-sync.d.ts.map +1 -1
- package/dist/preflight/types.d.ts +8 -8
- package/dist/preflight/types.d.ts.map +1 -1
- package/dist/runner/index.d.ts +1 -1
- package/dist/runner/script-runner.d.ts +1 -1
- package/dist/runner/script-runner.d.ts.map +1 -1
- package/dist/tables/table-manager.d.ts.map +1 -1
- package/dist/tables/types.d.ts +2 -1
- package/dist/tables/types.d.ts.map +1 -1
- package/dist/utils/json-ordering.d.ts +5 -4
- package/dist/utils/json-ordering.d.ts.map +1 -1
- package/package.json +32 -31
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
15
15
|
|
|
16
16
|
// src/agent-project/types.ts
|
|
17
17
|
import { z } from "@botpress/sdk";
|
|
18
|
-
var pluginDependencyMappingSchema, dependenciesSchema, agentInfoSchema, ValidationErrorCode, ValidationSeverity, ProjectState;
|
|
18
|
+
var pluginDependencyMappingSchema, dependenciesSchema, agentInfoSchema, agentLocalInfoSchema, ValidationErrorCode, ValidationSeverity, ProjectState;
|
|
19
19
|
var init_types = __esm(() => {
|
|
20
20
|
pluginDependencyMappingSchema = z.object({
|
|
21
21
|
integrationAlias: z.string(),
|
|
@@ -40,6 +40,9 @@ var init_types = __esm(() => {
|
|
|
40
40
|
apiUrl: z.string().optional().describe("The Botpress API URL (e.g., https://api.botpress.cloud)"),
|
|
41
41
|
devId: z.string().optional().describe("The development ID used during local development")
|
|
42
42
|
});
|
|
43
|
+
agentLocalInfoSchema = z.object({
|
|
44
|
+
devId: z.string().optional().describe("The development bot ID used during local development")
|
|
45
|
+
});
|
|
43
46
|
((ValidationErrorCode2) => {
|
|
44
47
|
ValidationErrorCode2["DIRECTORY_NOT_FOUND"] = "DIRECTORY_NOT_FOUND";
|
|
45
48
|
ValidationErrorCode2["DIRECTORY_ACCESS_ERROR"] = "DIRECTORY_ACCESS_ERROR";
|
|
@@ -487,6 +490,15 @@ async function resolveAgent(agentPath, options = {}) {
|
|
|
487
490
|
if (!agentInfo.apiUrl) {
|
|
488
491
|
agentInfo.apiUrl = DEFAULT_API_URL;
|
|
489
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 {}
|
|
490
502
|
if (requireWorkspace && !agentInfo.workspaceId) {
|
|
491
503
|
throw ValidationErrors.workspaceIdMissing();
|
|
492
504
|
}
|
|
@@ -525,10 +537,14 @@ import os from "os";
|
|
|
525
537
|
class CredentialsManager {
|
|
526
538
|
credentialsPath;
|
|
527
539
|
configDir;
|
|
540
|
+
profileOverride;
|
|
528
541
|
constructor() {
|
|
529
542
|
this.configDir = path2.join(os.homedir(), ".adk");
|
|
530
543
|
this.credentialsPath = path2.join(this.configDir, "credentials");
|
|
531
544
|
}
|
|
545
|
+
setProfileOverride(profile) {
|
|
546
|
+
this.profileOverride = profile;
|
|
547
|
+
}
|
|
532
548
|
async ensureConfigDir() {
|
|
533
549
|
try {
|
|
534
550
|
await fs2.mkdir(this.configDir, { recursive: true });
|
|
@@ -644,23 +660,54 @@ class CredentialsManager {
|
|
|
644
660
|
await this.writeCredentials(store);
|
|
645
661
|
}
|
|
646
662
|
async getActiveCredentials() {
|
|
647
|
-
const
|
|
648
|
-
const credentials = await this.getCredentials(
|
|
663
|
+
const profileName = this.profileOverride || process.env.ADK_PROFILE;
|
|
664
|
+
const credentials = await this.getCredentials(profileName);
|
|
649
665
|
if (!credentials) {
|
|
650
|
-
const
|
|
651
|
-
throw new Error(`No credentials found for profile '${
|
|
666
|
+
const displayName = profileName || "default";
|
|
667
|
+
throw new Error(`No credentials found for profile '${displayName}'. ` + `Please run 'adk login' to authenticate.`);
|
|
652
668
|
}
|
|
653
669
|
return credentials;
|
|
654
670
|
}
|
|
671
|
+
findProfileByApiUrl(store, apiUrl) {
|
|
672
|
+
const normalizedUrl = apiUrl.replace(/\/+$/, "");
|
|
673
|
+
for (const [, credentials] of Object.entries(store.profiles)) {
|
|
674
|
+
if (!credentials.apiUrl)
|
|
675
|
+
continue;
|
|
676
|
+
const profileUrl = credentials.apiUrl.replace(/\/+$/, "");
|
|
677
|
+
if (profileUrl === normalizedUrl) {
|
|
678
|
+
return credentials;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return null;
|
|
682
|
+
}
|
|
655
683
|
async getAgentCredentials(agentPath) {
|
|
656
|
-
const baseCredentials = await this.getActiveCredentials();
|
|
657
684
|
const agentInfo = await resolveAgent(agentPath, {
|
|
658
685
|
required: true,
|
|
659
686
|
requireWorkspace: true
|
|
660
687
|
});
|
|
688
|
+
const agentApiUrl = agentInfo.apiUrl;
|
|
689
|
+
let baseCredentials;
|
|
690
|
+
const hasExplicitProfile = !!(this.profileOverride || process.env.ADK_PROFILE);
|
|
691
|
+
if (hasExplicitProfile) {
|
|
692
|
+
baseCredentials = await this.getActiveCredentials();
|
|
693
|
+
} else {
|
|
694
|
+
const store = await this.readCredentials();
|
|
695
|
+
const matchingCredentials = this.findProfileByApiUrl(store, agentApiUrl);
|
|
696
|
+
if (matchingCredentials) {
|
|
697
|
+
console.info(`Using profile matching agent.json API URL (${agentApiUrl})`);
|
|
698
|
+
baseCredentials = matchingCredentials;
|
|
699
|
+
} else {
|
|
700
|
+
const profileName = store.currentProfile || "default";
|
|
701
|
+
const activeCredentials = store.profiles[profileName];
|
|
702
|
+
if (!activeCredentials) {
|
|
703
|
+
throw new Error(`No credentials found for profile '${profileName}'. ` + `Please run 'adk login' to authenticate.`);
|
|
704
|
+
}
|
|
705
|
+
baseCredentials = activeCredentials;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
661
708
|
return {
|
|
662
709
|
...baseCredentials,
|
|
663
|
-
apiUrl:
|
|
710
|
+
apiUrl: agentApiUrl,
|
|
664
711
|
workspaceId: agentInfo.workspaceId,
|
|
665
712
|
botId: agentInfo.botId
|
|
666
713
|
};
|
|
@@ -729,7 +776,7 @@ var _format = null, _formatLoaded = false, formatCode = async (code, filepath) =
|
|
|
729
776
|
`));
|
|
730
777
|
return code;
|
|
731
778
|
}
|
|
732
|
-
}, ADK_VERSION = "1.
|
|
779
|
+
}, ADK_VERSION = "1.17.0", relative2 = (from, to) => {
|
|
733
780
|
const fromDir = path10.dirname(from);
|
|
734
781
|
const relative3 = path10.relative(fromDir, to);
|
|
735
782
|
return relative3.startsWith(".") ? relative3 : `./${relative3}`;
|
|
@@ -860,16 +907,31 @@ var init_integration_action_types = __esm(() => {
|
|
|
860
907
|
var require_package = __commonJS((exports, module) => {
|
|
861
908
|
module.exports = {
|
|
862
909
|
name: "@botpress/adk",
|
|
863
|
-
version: "1.
|
|
910
|
+
version: "1.17.0",
|
|
864
911
|
description: "Core ADK library for building AI agents on Botpress",
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
912
|
+
keywords: [
|
|
913
|
+
"adk",
|
|
914
|
+
"agent",
|
|
915
|
+
"ai",
|
|
916
|
+
"botpress",
|
|
917
|
+
"chatbot",
|
|
918
|
+
"conversational-ai",
|
|
919
|
+
"development-kit"
|
|
920
|
+
],
|
|
921
|
+
license: "MIT",
|
|
922
|
+
author: "Botpress",
|
|
923
|
+
repository: {
|
|
924
|
+
type: "git",
|
|
925
|
+
url: "https://github.com/botpress/adk"
|
|
926
|
+
},
|
|
868
927
|
files: [
|
|
869
928
|
"dist/**/*",
|
|
870
929
|
"package.json",
|
|
871
930
|
"README.md"
|
|
872
931
|
],
|
|
932
|
+
type: "module",
|
|
933
|
+
main: "dist/index.js",
|
|
934
|
+
types: "dist/index.d.ts",
|
|
873
935
|
exports: {
|
|
874
936
|
".": {
|
|
875
937
|
types: "./dist/index.d.ts",
|
|
@@ -884,33 +946,18 @@ var require_package = __commonJS((exports, module) => {
|
|
|
884
946
|
watch: "bun run build:types && bun build ./src/index.ts --outdir ./dist --target node --format esm --sourcemap --watch",
|
|
885
947
|
clean: "rm -rf dist",
|
|
886
948
|
prepublishOnly: "bun run clean && bun run build",
|
|
887
|
-
test: "
|
|
888
|
-
"test:watch": "
|
|
889
|
-
"test:
|
|
890
|
-
"
|
|
891
|
-
},
|
|
892
|
-
keywords: [
|
|
893
|
-
"botpress",
|
|
894
|
-
"adk",
|
|
895
|
-
"agent",
|
|
896
|
-
"ai",
|
|
897
|
-
"chatbot",
|
|
898
|
-
"conversational-ai",
|
|
899
|
-
"development-kit"
|
|
900
|
-
],
|
|
901
|
-
author: "Botpress",
|
|
902
|
-
license: "MIT",
|
|
903
|
-
repository: {
|
|
904
|
-
type: "git",
|
|
905
|
-
url: "https://github.com/botpress/adk"
|
|
949
|
+
test: "bun test",
|
|
950
|
+
"test:watch": "bun test --watch",
|
|
951
|
+
"test:coverage": "bun test",
|
|
952
|
+
"check:type": "tsc --noEmit"
|
|
906
953
|
},
|
|
907
954
|
dependencies: {
|
|
908
|
-
"@botpress/chat": "
|
|
909
|
-
"@botpress/cli": "
|
|
910
|
-
"@botpress/client": "1.
|
|
911
|
-
"@botpress/cognitive": "0.
|
|
912
|
-
"@botpress/runtime": "^1.
|
|
913
|
-
"@botpress/sdk": "
|
|
955
|
+
"@botpress/chat": "0.5.5",
|
|
956
|
+
"@botpress/cli": "6.2.2",
|
|
957
|
+
"@botpress/client": "1.38.1",
|
|
958
|
+
"@botpress/cognitive": "0.4.2",
|
|
959
|
+
"@botpress/runtime": "^1.17.0",
|
|
960
|
+
"@botpress/sdk": "6.3.1",
|
|
914
961
|
"@bpinternal/jex": "^1.2.4",
|
|
915
962
|
"@bpinternal/yargs-extra": "^0.0.21",
|
|
916
963
|
"@parcel/watcher": "^2.5.1",
|
|
@@ -924,6 +971,7 @@ var require_package = __commonJS((exports, module) => {
|
|
|
924
971
|
"ts-morph": "^27.0.2"
|
|
925
972
|
},
|
|
926
973
|
devDependencies: {
|
|
974
|
+
"@bpinternal/zui": "2.1.0",
|
|
927
975
|
"@types/debug": "^4.1.12",
|
|
928
976
|
"@types/glob": "^9.0.0",
|
|
929
977
|
"@types/luxon": "^3.7.1",
|
|
@@ -934,8 +982,8 @@ var require_package = __commonJS((exports, module) => {
|
|
|
934
982
|
typescript: ">=4.5.0"
|
|
935
983
|
},
|
|
936
984
|
engines: {
|
|
937
|
-
|
|
938
|
-
|
|
985
|
+
bun: ">=1.3.9",
|
|
986
|
+
node: ">=22.0.0"
|
|
939
987
|
},
|
|
940
988
|
packageManager: "bun@1.3.9"
|
|
941
989
|
};
|
|
@@ -1104,6 +1152,9 @@ class Auth {
|
|
|
1104
1152
|
async setCurrentProfile(profileName) {
|
|
1105
1153
|
return this.credentialsManager.setCurrentProfile(profileName);
|
|
1106
1154
|
}
|
|
1155
|
+
setProfileOverride(profile) {
|
|
1156
|
+
this.credentialsManager.setProfileOverride(profile);
|
|
1157
|
+
}
|
|
1107
1158
|
async getActiveCredentials() {
|
|
1108
1159
|
return this.credentialsManager.getActiveCredentials();
|
|
1109
1160
|
}
|
|
@@ -1153,7 +1204,7 @@ import os3 from "os";
|
|
|
1153
1204
|
import path4 from "path";
|
|
1154
1205
|
import createDebug from "debug";
|
|
1155
1206
|
var debug = createDebug("adk:bp-cli");
|
|
1156
|
-
var BP_CLI_VERSION = "
|
|
1207
|
+
var BP_CLI_VERSION = "6.2.2";
|
|
1157
1208
|
var BP_CLI_INSTALL_ALL = path4.join(os3.homedir(), ".adk", `bp-cli`);
|
|
1158
1209
|
var BP_CLI_INSTALL_DIR = path4.join(BP_CLI_INSTALL_ALL, BP_CLI_VERSION);
|
|
1159
1210
|
var BP_CLI_BIN_PATH = path4.join(BP_CLI_INSTALL_DIR, "node_modules", "@botpress", "cli", "bin.js");
|
|
@@ -1648,9 +1699,9 @@ class BpDevCommand extends BaseCommand {
|
|
|
1648
1699
|
if (sourceMap) {
|
|
1649
1700
|
bpArgs.push("--sourceMap");
|
|
1650
1701
|
}
|
|
1651
|
-
const
|
|
1702
|
+
const spanIngestUrl = `http://localhost:${this.options.spanIngestPort}`;
|
|
1652
1703
|
const otlpEndpoint = this.options.otlpPort ? `http://localhost:${this.options.otlpPort}` : undefined;
|
|
1653
|
-
const traceLines = [`[bp-dev] Trace endpoints:`, `
|
|
1704
|
+
const traceLines = [`[bp-dev] Trace endpoints:`, ` ADK_SPAN_INGEST_URL=${spanIngestUrl}`];
|
|
1654
1705
|
if (otlpEndpoint) {
|
|
1655
1706
|
traceLines.push(` OTEL_EXPORTER_OTLP_ENDPOINT=${otlpEndpoint}`);
|
|
1656
1707
|
}
|
|
@@ -1673,7 +1724,7 @@ class BpDevCommand extends BaseCommand {
|
|
|
1673
1724
|
},
|
|
1674
1725
|
WORKER_MODE: "true",
|
|
1675
1726
|
WORKER_LIFETIME_MS: process.env.WORKER_LIFETIME_MS || "120000",
|
|
1676
|
-
|
|
1727
|
+
ADK_SPAN_INGEST_URL: spanIngestUrl,
|
|
1677
1728
|
...otlpEndpoint && { OTEL_EXPORTER_OTLP_ENDPOINT: otlpEndpoint },
|
|
1678
1729
|
...this.options.botName && { ADK_BOT_NAME: this.options.botName },
|
|
1679
1730
|
ADK_DIRECTORY: join2(botPath, ".."),
|
|
@@ -1902,10 +1953,11 @@ class BpChatCommand extends BaseCommand {
|
|
|
1902
1953
|
try {
|
|
1903
1954
|
await this.childProcess;
|
|
1904
1955
|
} catch (error) {
|
|
1956
|
+
const errObj = error != null && typeof error === "object" ? error : {};
|
|
1905
1957
|
this.emit("error", {
|
|
1906
|
-
exitCode:
|
|
1907
|
-
stderr:
|
|
1908
|
-
message: error.message || "Chat command failed"
|
|
1958
|
+
exitCode: "exitCode" in errObj ? errObj.exitCode || 1 : 1,
|
|
1959
|
+
stderr: "stderr" in errObj ? errObj.stderr || "" : "",
|
|
1960
|
+
message: error instanceof Error ? error.message || "Chat command failed" : "Chat command failed"
|
|
1909
1961
|
});
|
|
1910
1962
|
throw error;
|
|
1911
1963
|
}
|
|
@@ -1986,8 +2038,8 @@ You also have access to Botpress documentation search for platform-level questio
|
|
|
1986
2038
|
**Never read or display the contents of .env files or credentials.** If you need to verify a configuration value, ask the developer to confirm it.`;
|
|
1987
2039
|
function buildOpenCodeConfig(options) {
|
|
1988
2040
|
const command = [options.adkBinPath, "mcp", "--cwd", options.agentPath];
|
|
1989
|
-
if (options.
|
|
1990
|
-
command.push("--port", String(options.
|
|
2041
|
+
if (options.uiServerPort)
|
|
2042
|
+
command.push("--port", String(options.uiServerPort));
|
|
1991
2043
|
return {
|
|
1992
2044
|
...options.openCodePort && {
|
|
1993
2045
|
server: {
|
|
@@ -2060,7 +2112,7 @@ class OpenCodeCommand extends BaseCommand {
|
|
|
2060
2112
|
const opencodeConfig = JSON.stringify(buildOpenCodeConfig({
|
|
2061
2113
|
adkBinPath: adkBin,
|
|
2062
2114
|
agentPath: cwd,
|
|
2063
|
-
|
|
2115
|
+
uiServerPort: this.options.uiServerPort,
|
|
2064
2116
|
openCodePort: port,
|
|
2065
2117
|
corsOrigins
|
|
2066
2118
|
}));
|
|
@@ -2122,7 +2174,13 @@ class OpenCodeCommand extends BaseCommand {
|
|
|
2122
2174
|
} catch {}
|
|
2123
2175
|
await new Promise((r) => setTimeout(r, 500));
|
|
2124
2176
|
}
|
|
2125
|
-
this.
|
|
2177
|
+
if (!this.readyEmitted && !this.killed) {
|
|
2178
|
+
this.emit("progress", {
|
|
2179
|
+
type: "error",
|
|
2180
|
+
startTime: Date.now(),
|
|
2181
|
+
data: { reason: "OpenCode server did not respond in time" }
|
|
2182
|
+
});
|
|
2183
|
+
}
|
|
2126
2184
|
}
|
|
2127
2185
|
kill(signal = "SIGTERM") {
|
|
2128
2186
|
this.killed = true;
|
|
@@ -2207,7 +2265,8 @@ function getChatClient(cwd = process.cwd()) {
|
|
|
2207
2265
|
return Client4;
|
|
2208
2266
|
}
|
|
2209
2267
|
// src/utils/json-ordering.ts
|
|
2210
|
-
var agentInfoKeyOrder = ["botId", "workspaceId", "apiUrl"
|
|
2268
|
+
var agentInfoKeyOrder = ["botId", "workspaceId", "apiUrl"];
|
|
2269
|
+
var agentLocalInfoKeyOrder = ["devId"];
|
|
2211
2270
|
var dependenciesKeyOrder = ["integrations"];
|
|
2212
2271
|
var integrationKeyOrder = ["version", "enabled", "configurationType", "config"];
|
|
2213
2272
|
function orderKeys(obj, keyOrder) {
|
|
@@ -2292,7 +2351,7 @@ class AssetsCacheManager {
|
|
|
2292
2351
|
const content = await fs4.readFile(this.cachePath, "utf-8");
|
|
2293
2352
|
this.cache = JSON.parse(content);
|
|
2294
2353
|
return this.cache;
|
|
2295
|
-
} catch
|
|
2354
|
+
} catch {
|
|
2296
2355
|
this.cache = {
|
|
2297
2356
|
version: "1.0",
|
|
2298
2357
|
entries: {}
|
|
@@ -2825,7 +2884,7 @@ class EnhancedIntegrationCache {
|
|
|
2825
2884
|
|
|
2826
2885
|
// src/agent-project/dependencies-parser.ts
|
|
2827
2886
|
init_validation_errors();
|
|
2828
|
-
import { z as z2
|
|
2887
|
+
import { z as z2 } from "@botpress/sdk";
|
|
2829
2888
|
var INTEGRATION_ALIAS_MIN_LENGTH = 2;
|
|
2830
2889
|
var INTEGRATION_ALIAS_MAX_LENGTH = 100;
|
|
2831
2890
|
var INTEGRATION_ALIAS_REGEX = /^(?:[a-z][a-z0-9_-]*\/)?[a-z][a-z0-9_-]*$/;
|
|
@@ -2836,10 +2895,10 @@ var integrationRefSchema = z2.string().transform((val, ctx) => {
|
|
|
2836
2895
|
const match = val.match(/^(?:([^/]+)\/)?([^@]+)@(.+)$/);
|
|
2837
2896
|
if (!match) {
|
|
2838
2897
|
ctx.addIssue({
|
|
2839
|
-
code:
|
|
2898
|
+
code: "custom",
|
|
2840
2899
|
message: `Invalid integration version format: ${val}. Expected format: 'name@version' or 'workspace/name@version'`
|
|
2841
2900
|
});
|
|
2842
|
-
return
|
|
2901
|
+
return;
|
|
2843
2902
|
}
|
|
2844
2903
|
const [, workspace, name, version] = match;
|
|
2845
2904
|
return {
|
|
@@ -2938,10 +2997,10 @@ var pluginRefSchema = z2.string().transform((val, ctx) => {
|
|
|
2938
2997
|
const match = val.match(/^([^/@]+)@(.+)$/);
|
|
2939
2998
|
if (!match) {
|
|
2940
2999
|
ctx.addIssue({
|
|
2941
|
-
code:
|
|
3000
|
+
code: "custom",
|
|
2942
3001
|
message: `Invalid plugin version format: ${val}. Expected format: 'name@version' (no workspace prefix)`
|
|
2943
3002
|
});
|
|
2944
|
-
return
|
|
3003
|
+
return;
|
|
2945
3004
|
}
|
|
2946
3005
|
const [, name, version] = match;
|
|
2947
3006
|
return {
|
|
@@ -2998,7 +3057,7 @@ class PluginParser {
|
|
|
2998
3057
|
if (!pluginConfig.dependencies) {
|
|
2999
3058
|
continue;
|
|
3000
3059
|
}
|
|
3001
|
-
for (const [
|
|
3060
|
+
for (const [_depAlias, depMapping] of Object.entries(pluginConfig.dependencies)) {
|
|
3002
3061
|
if (!integrationAliases.includes(depMapping.integrationAlias)) {
|
|
3003
3062
|
errors.push(ValidationErrors.invalidPluginDependency(alias, depMapping.integrationAlias, integrationAliases));
|
|
3004
3063
|
}
|
|
@@ -3269,7 +3328,7 @@ class IntegrationCache {
|
|
|
3269
3328
|
}
|
|
3270
3329
|
}
|
|
3271
3330
|
return cached.definition;
|
|
3272
|
-
} catch
|
|
3331
|
+
} catch {
|
|
3273
3332
|
return null;
|
|
3274
3333
|
}
|
|
3275
3334
|
}
|
|
@@ -4658,7 +4717,7 @@ async function expandExports(options) {
|
|
|
4658
4717
|
});
|
|
4659
4718
|
return {};
|
|
4660
4719
|
}
|
|
4661
|
-
currentError = currentError.cause;
|
|
4720
|
+
currentError = currentError instanceof Error ? currentError.cause : undefined;
|
|
4662
4721
|
}
|
|
4663
4722
|
throw importError;
|
|
4664
4723
|
}
|
|
@@ -4924,20 +4983,62 @@ class AgentProject {
|
|
|
4924
4983
|
return this._assetsManager;
|
|
4925
4984
|
}
|
|
4926
4985
|
async createAgentInfo(info) {
|
|
4986
|
+
const { devId, ...agentJsonInfo } = info;
|
|
4927
4987
|
const agentPath = path13.join(this._path, "agent.json");
|
|
4928
|
-
const agentContent = stringifyWithOrder(
|
|
4988
|
+
const agentContent = stringifyWithOrder(agentJsonInfo, agentInfoKeyOrder);
|
|
4929
4989
|
await fs10.writeFile(agentPath, agentContent);
|
|
4930
4990
|
this._agentInfo = info;
|
|
4991
|
+
if (devId) {
|
|
4992
|
+
await this.createAgentLocalInfo({ devId });
|
|
4993
|
+
}
|
|
4931
4994
|
}
|
|
4932
4995
|
async updateAgentInfo(updates) {
|
|
4933
4996
|
if (!this._agentInfo) {
|
|
4934
4997
|
throw new Error("No agent.json found. Use createAgentInfo() first.");
|
|
4935
4998
|
}
|
|
4936
|
-
const
|
|
4999
|
+
const { devId, ...agentJsonUpdates } = updates;
|
|
5000
|
+
const updatedInfo = { ...this._agentInfo, ...agentJsonUpdates };
|
|
5001
|
+
const { devId: _devId, ...agentJsonData } = updatedInfo;
|
|
4937
5002
|
const agentPath = path13.join(this._path, "agent.json");
|
|
4938
|
-
const agentContent = stringifyWithOrder(
|
|
5003
|
+
const agentContent = stringifyWithOrder(agentJsonData, agentInfoKeyOrder);
|
|
4939
5004
|
await fs10.writeFile(agentPath, agentContent);
|
|
4940
5005
|
this._agentInfo = updatedInfo;
|
|
5006
|
+
if (devId !== undefined) {
|
|
5007
|
+
await this.updateAgentLocalInfo({ devId });
|
|
5008
|
+
}
|
|
5009
|
+
}
|
|
5010
|
+
async createAgentLocalInfo(info) {
|
|
5011
|
+
const localPath = path13.join(this._path, "agent.local.json");
|
|
5012
|
+
let existing = {};
|
|
5013
|
+
try {
|
|
5014
|
+
const content2 = await fs10.readFile(localPath, "utf-8");
|
|
5015
|
+
existing = JSON.parse(content2);
|
|
5016
|
+
} catch {}
|
|
5017
|
+
const merged = { ...existing, ...info };
|
|
5018
|
+
const content = stringifyWithOrder(merged, agentLocalInfoKeyOrder);
|
|
5019
|
+
await fs10.writeFile(localPath, content);
|
|
5020
|
+
if (this._agentInfo) {
|
|
5021
|
+
this._agentInfo.devId = merged.devId;
|
|
5022
|
+
}
|
|
5023
|
+
}
|
|
5024
|
+
async updateAgentLocalInfo(updates) {
|
|
5025
|
+
const localPath = path13.join(this._path, "agent.local.json");
|
|
5026
|
+
let existing = {};
|
|
5027
|
+
try {
|
|
5028
|
+
const content2 = await fs10.readFile(localPath, "utf-8");
|
|
5029
|
+
existing = JSON.parse(content2);
|
|
5030
|
+
} catch {}
|
|
5031
|
+
const updated = { ...existing, ...updates };
|
|
5032
|
+
for (const key of Object.keys(updated)) {
|
|
5033
|
+
if (updated[key] === undefined) {
|
|
5034
|
+
delete updated[key];
|
|
5035
|
+
}
|
|
5036
|
+
}
|
|
5037
|
+
const content = stringifyWithOrder(updated, agentLocalInfoKeyOrder);
|
|
5038
|
+
await fs10.writeFile(localPath, content);
|
|
5039
|
+
if (this._agentInfo) {
|
|
5040
|
+
this._agentInfo.devId = updated.devId;
|
|
5041
|
+
}
|
|
4941
5042
|
}
|
|
4942
5043
|
requiresAgentInfo(operation) {
|
|
4943
5044
|
if (!this._agentInfo?.botId) {
|
|
@@ -5128,6 +5229,19 @@ ${err.stack?.split(`
|
|
|
5128
5229
|
console.warn(`Failed to register data source workflows for ${kbPath}:`, error);
|
|
5129
5230
|
}
|
|
5130
5231
|
}
|
|
5232
|
+
isBarrelReexport(existing, newPath, newExport, newDefinition) {
|
|
5233
|
+
const isNewBarrel = /^index\.[tj]s$/i.test(path13.basename(newPath));
|
|
5234
|
+
const isExistingBarrel = /^index\.[tj]s$/i.test(path13.basename(existing.path));
|
|
5235
|
+
if (!isNewBarrel && !isExistingBarrel) {
|
|
5236
|
+
return false;
|
|
5237
|
+
}
|
|
5238
|
+
if (isExistingBarrel && !isNewBarrel) {
|
|
5239
|
+
existing.path = newPath;
|
|
5240
|
+
existing.export = newExport;
|
|
5241
|
+
existing.definition = newDefinition;
|
|
5242
|
+
}
|
|
5243
|
+
return true;
|
|
5244
|
+
}
|
|
5131
5245
|
getChannelsList(channelSpec) {
|
|
5132
5246
|
if (channelSpec === "*") {
|
|
5133
5247
|
return ["*"];
|
|
@@ -5210,6 +5324,9 @@ ${err.stack?.split(`
|
|
|
5210
5324
|
return existingChannels.some((ch) => newChannels.includes(ch));
|
|
5211
5325
|
});
|
|
5212
5326
|
if (overlapping) {
|
|
5327
|
+
if (this.isBarrelReexport(overlapping, relPath, key, definition)) {
|
|
5328
|
+
continue;
|
|
5329
|
+
}
|
|
5213
5330
|
this._warnings.push({
|
|
5214
5331
|
$type: "ValidationError",
|
|
5215
5332
|
code: "DUPLICATE_PRIMITIVE" /* DUPLICATE_PRIMITIVE */,
|
|
@@ -5227,6 +5344,9 @@ ${err.stack?.split(`
|
|
|
5227
5344
|
} else if (Primitives2.Definitions.isKnowledgeDefinition(definition)) {
|
|
5228
5345
|
const existing = this._knowledge.find((p) => p.definition.name === definition.name);
|
|
5229
5346
|
if (existing) {
|
|
5347
|
+
if (this.isBarrelReexport(existing, relPath, key, definition)) {
|
|
5348
|
+
continue;
|
|
5349
|
+
}
|
|
5230
5350
|
this._warnings.push({
|
|
5231
5351
|
$type: "ValidationError",
|
|
5232
5352
|
code: "DUPLICATE_PRIMITIVE" /* DUPLICATE_PRIMITIVE */,
|
|
@@ -5245,6 +5365,9 @@ ${err.stack?.split(`
|
|
|
5245
5365
|
} else if (Primitives2.Definitions.isTriggerDefinition(definition)) {
|
|
5246
5366
|
const existing = this._triggers.find((p) => p.definition.name === definition.name);
|
|
5247
5367
|
if (existing) {
|
|
5368
|
+
if (this.isBarrelReexport(existing, relPath, key, definition)) {
|
|
5369
|
+
continue;
|
|
5370
|
+
}
|
|
5248
5371
|
this._warnings.push({
|
|
5249
5372
|
$type: "ValidationError",
|
|
5250
5373
|
code: "DUPLICATE_PRIMITIVE" /* DUPLICATE_PRIMITIVE */,
|
|
@@ -5262,6 +5385,9 @@ ${err.stack?.split(`
|
|
|
5262
5385
|
} else if (Primitives2.Definitions.isWorkflowDefinition(definition)) {
|
|
5263
5386
|
const existing = this._workflows.find((p) => p.definition.name === definition.name);
|
|
5264
5387
|
if (existing) {
|
|
5388
|
+
if (this.isBarrelReexport(existing, relPath, key, definition)) {
|
|
5389
|
+
continue;
|
|
5390
|
+
}
|
|
5265
5391
|
this._warnings.push({
|
|
5266
5392
|
$type: "ValidationError",
|
|
5267
5393
|
code: "DUPLICATE_PRIMITIVE" /* DUPLICATE_PRIMITIVE */,
|
|
@@ -5279,6 +5405,9 @@ ${err.stack?.split(`
|
|
|
5279
5405
|
} else if (Primitives2.Definitions.isActionDefinition(definition)) {
|
|
5280
5406
|
const existing = this._actions.find((p) => p.definition.name === definition.name);
|
|
5281
5407
|
if (existing) {
|
|
5408
|
+
if (this.isBarrelReexport(existing, relPath, key, definition)) {
|
|
5409
|
+
continue;
|
|
5410
|
+
}
|
|
5282
5411
|
this._warnings.push({
|
|
5283
5412
|
$type: "ValidationError",
|
|
5284
5413
|
code: "DUPLICATE_PRIMITIVE" /* DUPLICATE_PRIMITIVE */,
|
|
@@ -5296,6 +5425,9 @@ ${err.stack?.split(`
|
|
|
5296
5425
|
} else if (Primitives2.Definitions.isTableDefinition(definition)) {
|
|
5297
5426
|
const existing = this._tables.find((p) => p.definition.name === definition.name);
|
|
5298
5427
|
if (existing) {
|
|
5428
|
+
if (this.isBarrelReexport(existing, relPath, key, definition)) {
|
|
5429
|
+
continue;
|
|
5430
|
+
}
|
|
5299
5431
|
this._warnings.push({
|
|
5300
5432
|
$type: "ValidationError",
|
|
5301
5433
|
code: "DUPLICATE_PRIMITIVE" /* DUPLICATE_PRIMITIVE */,
|
|
@@ -5619,22 +5751,36 @@ adk deploy # Deploy to Botpress Cloud
|
|
|
5619
5751
|
adk chat # Chat with your agent in the terminal
|
|
5620
5752
|
\`\`\`
|
|
5621
5753
|
|
|
5622
|
-
##
|
|
5754
|
+
## MCP Tools (ADK Dev Server)
|
|
5623
5755
|
|
|
5624
|
-
This project
|
|
5756
|
+
This project includes an MCP server that provides AI coding assistants with deep ADK integration.
|
|
5757
|
+
Run \`adk mcp:init --all\` to generate configuration for your editor, or use the tools below directly.
|
|
5625
5758
|
|
|
5626
|
-
|
|
5627
|
-
| ------------------ | ------------------------------------------------ |
|
|
5628
|
-
| \`/adk\` | ADK concepts, patterns, and API reference |
|
|
5629
|
-
| \`/adk-integration\` | Finding and using Botpress integrations |
|
|
5630
|
-
| \`/adk-debugger\` | Debugging with traces and test conversations |
|
|
5631
|
-
| \`/adk-frontend\` | Building frontends that connect to ADK bots |
|
|
5759
|
+
### Debugging & Testing
|
|
5632
5760
|
|
|
5633
|
-
|
|
5761
|
+
| Tool | Use for |
|
|
5762
|
+
| ------------------ | ------------------------------------------------------------ |
|
|
5763
|
+
| \`adk_send_message\` | Send a test message to the running bot and receive responses |
|
|
5764
|
+
| \`adk_query_traces\` | Query trace spans for debugging conversations and workflows |
|
|
5765
|
+
| \`adk_get_dev_logs\` | Get dev server logs, build output, errors, and warnings |
|
|
5634
5766
|
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5767
|
+
### Project & Integration Management
|
|
5768
|
+
|
|
5769
|
+
| Tool | Use for |
|
|
5770
|
+
| ------------------------- | ----------------------------------------------------------- |
|
|
5771
|
+
| \`adk_get_agent_info\` | Get project info: name, version, and all primitives |
|
|
5772
|
+
| \`adk_search_integrations\` | Search available integrations on the Botpress Hub |
|
|
5773
|
+
| \`adk_get_integration\` | Get detailed info about an integration before adding it |
|
|
5774
|
+
| \`adk_add_integration\` | Add an integration to the project (updates agent.config.ts) |
|
|
5775
|
+
|
|
5776
|
+
### Workflows
|
|
5777
|
+
|
|
5778
|
+
| Tool | Use for |
|
|
5779
|
+
| -------------------- | ------------------------------------------ |
|
|
5780
|
+
| \`adk_list_workflows\` | List available workflows with descriptions |
|
|
5781
|
+
| \`adk_start_workflow\` | Start a workflow or get its input schema |
|
|
5782
|
+
|
|
5783
|
+
> **Tip:** The dev server must be running (\`adk dev\`) for debugging and testing tools to work.
|
|
5638
5784
|
|
|
5639
5785
|
## Project Overview
|
|
5640
5786
|
|
|
@@ -5694,7 +5840,7 @@ class AgentProjectGenerator {
|
|
|
5694
5840
|
deploy: "adk deploy"
|
|
5695
5841
|
},
|
|
5696
5842
|
dependencies: {
|
|
5697
|
-
"@botpress/runtime": `^${"1.
|
|
5843
|
+
"@botpress/runtime": `^${"1.17.0"}`
|
|
5698
5844
|
},
|
|
5699
5845
|
devDependencies: {
|
|
5700
5846
|
typescript: "^5.9.3"
|
|
@@ -5797,6 +5943,12 @@ dist/
|
|
|
5797
5943
|
.env.local
|
|
5798
5944
|
.env.production
|
|
5799
5945
|
|
|
5946
|
+
# Local development
|
|
5947
|
+
agent.local.json
|
|
5948
|
+
|
|
5949
|
+
# MCP configuration (auto-generated by adk mcp:init)
|
|
5950
|
+
.mcp.json
|
|
5951
|
+
|
|
5800
5952
|
# IDE files
|
|
5801
5953
|
.vscode/
|
|
5802
5954
|
.idea/
|
|
@@ -6227,7 +6379,7 @@ if (typeof globalThis !== 'undefined') {
|
|
|
6227
6379
|
}
|
|
6228
6380
|
}
|
|
6229
6381
|
// src/generators/integration-types.ts
|
|
6230
|
-
import {
|
|
6382
|
+
import { z as z3 } from "@botpress/sdk";
|
|
6231
6383
|
import crypto2 from "crypto";
|
|
6232
6384
|
import path18 from "path";
|
|
6233
6385
|
|
|
@@ -6255,6 +6407,7 @@ function getPluginAlias(pluginName) {
|
|
|
6255
6407
|
}
|
|
6256
6408
|
|
|
6257
6409
|
// src/generators/integration-types.ts
|
|
6410
|
+
var { transforms } = z3;
|
|
6258
6411
|
var getIntegrationHash = (integration) => {
|
|
6259
6412
|
return crypto2.createHash("sha256").update(`${integration.alias}|${integration.definition?.id}|${integration.definition?.version}|${integration.definition?.updatedAt}`).digest("hex");
|
|
6260
6413
|
};
|
|
@@ -6487,9 +6640,10 @@ Description: ${tag?.description}`);
|
|
|
6487
6640
|
}
|
|
6488
6641
|
if (integration.definition?.configurations) {
|
|
6489
6642
|
for (const [key, config] of Object.entries(integration.definition.configurations)) {
|
|
6490
|
-
const
|
|
6491
|
-
const
|
|
6492
|
-
const
|
|
6643
|
+
const configRecord = config;
|
|
6644
|
+
const title = configRecord.title || key;
|
|
6645
|
+
const description = configRecord.description || "";
|
|
6646
|
+
const schema = configRecord.schema;
|
|
6493
6647
|
let tsType = "{}";
|
|
6494
6648
|
if (schema) {
|
|
6495
6649
|
tsType = transforms.fromJSONSchema(schema).toTypescriptType();
|
|
@@ -6606,12 +6760,14 @@ async function generateClientWrapper(project) {
|
|
|
6606
6760
|
let schema;
|
|
6607
6761
|
let computed = false;
|
|
6608
6762
|
if (typeof colDef === "object" && colDef !== null && "schema" in colDef) {
|
|
6609
|
-
|
|
6610
|
-
|
|
6763
|
+
const colDefRecord = colDef;
|
|
6764
|
+
schema = colDefRecord.schema;
|
|
6765
|
+
computed = colDefRecord.computed || false;
|
|
6611
6766
|
} else {
|
|
6612
6767
|
schema = colDef;
|
|
6613
6768
|
}
|
|
6614
|
-
const
|
|
6769
|
+
const schemaObj = schema;
|
|
6770
|
+
const tsType = typeof schemaObj.toTypescriptType === "function" ? schemaObj.toTypescriptType({ treatDefaultAsOptional: true }) : "any";
|
|
6615
6771
|
if (!computed) {
|
|
6616
6772
|
inputColumns.push(`${colName}: ${tsType}`);
|
|
6617
6773
|
}
|
|
@@ -6926,10 +7082,11 @@ import fs18 from "fs/promises";
|
|
|
6926
7082
|
import path38 from "path";
|
|
6927
7083
|
|
|
6928
7084
|
// src/generators/plugin-types.ts
|
|
6929
|
-
import {
|
|
7085
|
+
import { z as z4 } from "@botpress/sdk";
|
|
6930
7086
|
import crypto4 from "crypto";
|
|
6931
7087
|
import path20 from "path";
|
|
6932
7088
|
init_utils();
|
|
7089
|
+
var { transforms: transforms2 } = z4;
|
|
6933
7090
|
function stripRefs(schema) {
|
|
6934
7091
|
if (typeof schema !== "object" || schema === null) {
|
|
6935
7092
|
return schema;
|
|
@@ -7075,10 +7232,11 @@ export type PluginActions = PluginsMap<Plugins>;
|
|
|
7075
7232
|
}
|
|
7076
7233
|
|
|
7077
7234
|
// src/generators/interface-types.ts
|
|
7078
|
-
import {
|
|
7235
|
+
import { z as z5 } from "@botpress/sdk";
|
|
7079
7236
|
import crypto5 from "crypto";
|
|
7080
7237
|
import path22 from "path";
|
|
7081
7238
|
init_utils();
|
|
7239
|
+
var { transforms: transforms3 } = z5;
|
|
7082
7240
|
var sameMajorVersion = (a, b) => {
|
|
7083
7241
|
const majorA = a.split(".")[0];
|
|
7084
7242
|
const majorB = b.split(".")[0];
|
|
@@ -7864,7 +8022,7 @@ class DevIdManager {
|
|
|
7864
8022
|
if (!project.agentInfo) {
|
|
7865
8023
|
throw ValidationErrors.agentNotLinked();
|
|
7866
8024
|
}
|
|
7867
|
-
await project.
|
|
8025
|
+
await project.updateAgentLocalInfo({
|
|
7868
8026
|
devId: projectCache.devId
|
|
7869
8027
|
});
|
|
7870
8028
|
}
|
|
@@ -7891,7 +8049,7 @@ class DevIdManager {
|
|
|
7891
8049
|
const client = await this.getClient();
|
|
7892
8050
|
await client.getBot({ id: agentInfo.devId });
|
|
7893
8051
|
return true;
|
|
7894
|
-
} catch
|
|
8052
|
+
} catch {
|
|
7895
8053
|
return false;
|
|
7896
8054
|
}
|
|
7897
8055
|
}
|
|
@@ -8264,10 +8422,11 @@ class PluginSync {
|
|
|
8264
8422
|
|
|
8265
8423
|
// src/bot-generator/generator.ts
|
|
8266
8424
|
init_utils();
|
|
8267
|
-
import {
|
|
8425
|
+
import { z as z6 } from "@botpress/sdk";
|
|
8268
8426
|
init_constants();
|
|
8269
8427
|
import { BuiltInActions as BuiltInActions2, BuiltInWorkflows as BuiltInWorkflows4, Primitives as Primitives3 } from "@botpress/runtime/internal";
|
|
8270
8428
|
import { BUILT_IN_TAGS as BUILT_IN_TAGS2 } from "@botpress/runtime/definition";
|
|
8429
|
+
var { transforms: transforms4 } = z6;
|
|
8271
8430
|
var plural = (n, word) => `${n} ${word}${n === 1 ? "" : "s"}`;
|
|
8272
8431
|
function isBuiltinWorkflow3(name) {
|
|
8273
8432
|
return !!Object.values(BuiltInWorkflows4).find((x) => x.name === name);
|
|
@@ -9281,7 +9440,9 @@ export default bot;`;
|
|
|
9281
9440
|
}
|
|
9282
9441
|
{
|
|
9283
9442
|
const dest = path38.join(srcDir, "triggers.ts");
|
|
9284
|
-
const {
|
|
9443
|
+
const {
|
|
9444
|
+
z: { transforms: transforms5 }
|
|
9445
|
+
} = await import("@botpress/sdk");
|
|
9285
9446
|
const imports = new Map;
|
|
9286
9447
|
const exports = new Set;
|
|
9287
9448
|
const payloadTypes = {};
|
|
@@ -9569,7 +9730,9 @@ async function generateBotProject(options) {
|
|
|
9569
9730
|
}
|
|
9570
9731
|
// src/tables/table-manager.ts
|
|
9571
9732
|
import { Client as Client15 } from "@botpress/client";
|
|
9572
|
-
import {
|
|
9733
|
+
import { z as z7 } from "@botpress/sdk";
|
|
9734
|
+
var { transforms: transforms5 } = z7;
|
|
9735
|
+
|
|
9573
9736
|
class TableManager {
|
|
9574
9737
|
client;
|
|
9575
9738
|
botId;
|
|
@@ -9600,13 +9763,14 @@ class TableManager {
|
|
|
9600
9763
|
}
|
|
9601
9764
|
getSchemaType(schema) {
|
|
9602
9765
|
if (schema.type) {
|
|
9603
|
-
|
|
9604
|
-
|
|
9766
|
+
const items = schema.items;
|
|
9767
|
+
if (schema.type === "array" && items?.type) {
|
|
9768
|
+
return `array<${items.type}>`;
|
|
9605
9769
|
}
|
|
9606
|
-
return schema.type;
|
|
9770
|
+
return String(schema.type);
|
|
9607
9771
|
}
|
|
9608
9772
|
if (schema.$ref) {
|
|
9609
|
-
return schema.$ref.split("/").pop() || "unknown";
|
|
9773
|
+
return String(schema.$ref).split("/").pop() || "unknown";
|
|
9610
9774
|
}
|
|
9611
9775
|
return "unknown";
|
|
9612
9776
|
}
|
|
@@ -9617,8 +9781,8 @@ class TableManager {
|
|
|
9617
9781
|
} else if (Math.abs(oldPosition - newPosition) <= 1) {
|
|
9618
9782
|
score += 1;
|
|
9619
9783
|
}
|
|
9620
|
-
const oldDesc = (oldSchema?.description || "").toLowerCase();
|
|
9621
|
-
const newDesc = (newSchema?.description || "").toLowerCase();
|
|
9784
|
+
const oldDesc = String(oldSchema?.description || "").toLowerCase();
|
|
9785
|
+
const newDesc = String(newSchema?.description || "").toLowerCase();
|
|
9622
9786
|
if (oldDesc && newDesc && oldDesc === newDesc) {
|
|
9623
9787
|
score += 5;
|
|
9624
9788
|
} else if (oldDesc && newDesc && oldDesc.length > 5 && newDesc.length > 5) {
|
|
@@ -9633,8 +9797,10 @@ class TableManager {
|
|
|
9633
9797
|
}
|
|
9634
9798
|
}
|
|
9635
9799
|
}
|
|
9636
|
-
const
|
|
9637
|
-
const
|
|
9800
|
+
const oldType = oldSchema?.type;
|
|
9801
|
+
const newType = newSchema?.type;
|
|
9802
|
+
const oldOptional = typeof oldType === "string" && oldType.includes("null") || oldSchema?.nullable === true;
|
|
9803
|
+
const newOptional = typeof newType === "string" && newType.includes("null") || newSchema?.nullable === true;
|
|
9638
9804
|
if (oldOptional === newOptional) {
|
|
9639
9805
|
score += 1;
|
|
9640
9806
|
}
|
|
@@ -10862,7 +11028,7 @@ class KBSyncFormatter {
|
|
|
10862
11028
|
}
|
|
10863
11029
|
}
|
|
10864
11030
|
// src/file-watcher/watcher.ts
|
|
10865
|
-
import { watch as watch2, readdirSync as readdirSync2 } from "fs";
|
|
11031
|
+
import { watch as watch2, readdirSync as readdirSync2, statSync } from "fs";
|
|
10866
11032
|
import { EventEmitter as EventEmitter3 } from "events";
|
|
10867
11033
|
import { join as join9, relative as relative3 } from "path";
|
|
10868
11034
|
import { existsSync as existsSync9 } from "fs";
|
|
@@ -10904,7 +11070,7 @@ class FileWatcher2 extends EventEmitter3 {
|
|
|
10904
11070
|
this.updateFileState(fullPath);
|
|
10905
11071
|
}
|
|
10906
11072
|
}
|
|
10907
|
-
} catch
|
|
11073
|
+
} catch {}
|
|
10908
11074
|
}
|
|
10909
11075
|
watchFile(filePath) {
|
|
10910
11076
|
if (this.watchers.has(filePath)) {
|
|
@@ -10937,6 +11103,12 @@ class FileWatcher2 extends EventEmitter3 {
|
|
|
10937
11103
|
}
|
|
10938
11104
|
}
|
|
10939
11105
|
handleFileChange(filePath) {
|
|
11106
|
+
try {
|
|
11107
|
+
if (existsSync9(filePath) && statSync(filePath).isDirectory()) {
|
|
11108
|
+
this.scanDirectoryForChanges(filePath);
|
|
11109
|
+
return;
|
|
11110
|
+
}
|
|
11111
|
+
} catch {}
|
|
10940
11112
|
const fileExists = existsSync9(filePath);
|
|
10941
11113
|
const previousState = this.fileStates.get(filePath);
|
|
10942
11114
|
let changeType;
|
|
@@ -10957,12 +11129,7 @@ class FileWatcher2 extends EventEmitter3 {
|
|
|
10957
11129
|
path: relativePath,
|
|
10958
11130
|
type: changeType
|
|
10959
11131
|
});
|
|
10960
|
-
|
|
10961
|
-
clearTimeout(this.debounceTimer);
|
|
10962
|
-
}
|
|
10963
|
-
this.debounceTimer = setTimeout(() => {
|
|
10964
|
-
this.emitPendingChanges();
|
|
10965
|
-
}, this.debounceMs);
|
|
11132
|
+
this.scheduleDebouncedEmit();
|
|
10966
11133
|
}
|
|
10967
11134
|
emitPendingChanges() {
|
|
10968
11135
|
if (this.pendingChanges.size === 0) {
|
|
@@ -10976,6 +11143,44 @@ class FileWatcher2 extends EventEmitter3 {
|
|
|
10976
11143
|
};
|
|
10977
11144
|
this.emit("change", event);
|
|
10978
11145
|
}
|
|
11146
|
+
scanDirectoryForChanges(dirPath) {
|
|
11147
|
+
try {
|
|
11148
|
+
const entries = readdirSync2(dirPath, { withFileTypes: true });
|
|
11149
|
+
const currentFiles = new Set;
|
|
11150
|
+
for (const entry of entries) {
|
|
11151
|
+
const fullPath = join9(dirPath, entry.name);
|
|
11152
|
+
if (entry.isFile()) {
|
|
11153
|
+
currentFiles.add(fullPath);
|
|
11154
|
+
if (!this.fileStates.has(fullPath)) {
|
|
11155
|
+
this.updateFileState(fullPath);
|
|
11156
|
+
const relativePath = relative3(this.projectPath, fullPath);
|
|
11157
|
+
this.pendingChanges.set(relativePath, { path: relativePath, type: "added" });
|
|
11158
|
+
this.scheduleDebouncedEmit();
|
|
11159
|
+
}
|
|
11160
|
+
} else if (entry.isDirectory()) {
|
|
11161
|
+
this.scanDirectoryForChanges(fullPath);
|
|
11162
|
+
}
|
|
11163
|
+
}
|
|
11164
|
+
for (const [trackedPath] of this.fileStates) {
|
|
11165
|
+
if (trackedPath.startsWith(dirPath) && !trackedPath.includes("/", dirPath.length + 1)) {
|
|
11166
|
+
if (!currentFiles.has(trackedPath)) {
|
|
11167
|
+
this.fileStates.delete(trackedPath);
|
|
11168
|
+
const relativePath = relative3(this.projectPath, trackedPath);
|
|
11169
|
+
this.pendingChanges.set(relativePath, { path: relativePath, type: "deleted" });
|
|
11170
|
+
this.scheduleDebouncedEmit();
|
|
11171
|
+
}
|
|
11172
|
+
}
|
|
11173
|
+
}
|
|
11174
|
+
} catch {}
|
|
11175
|
+
}
|
|
11176
|
+
scheduleDebouncedEmit() {
|
|
11177
|
+
if (this.debounceTimer) {
|
|
11178
|
+
clearTimeout(this.debounceTimer);
|
|
11179
|
+
}
|
|
11180
|
+
this.debounceTimer = setTimeout(() => {
|
|
11181
|
+
this.emitPendingChanges();
|
|
11182
|
+
}, this.debounceMs);
|
|
11183
|
+
}
|
|
10979
11184
|
updateFileState(filePath) {
|
|
10980
11185
|
if (existsSync9(filePath)) {
|
|
10981
11186
|
this.fileStates.set(filePath, Date.now());
|
|
@@ -11755,6 +11960,7 @@ function filterEvals(evals, filter) {
|
|
|
11755
11960
|
}
|
|
11756
11961
|
// src/eval/runner.ts
|
|
11757
11962
|
import { Client as BpClient2 } from "@botpress/client";
|
|
11963
|
+
import { BUILT_IN_STATES as BUILT_IN_STATES2 } from "@botpress/runtime/internal";
|
|
11758
11964
|
|
|
11759
11965
|
// src/eval/client.ts
|
|
11760
11966
|
import { Client as BpClient } from "@botpress/client";
|
|
@@ -11775,20 +11981,21 @@ class ChatSession {
|
|
|
11775
11981
|
}
|
|
11776
11982
|
return this.client.user.id;
|
|
11777
11983
|
}
|
|
11778
|
-
async
|
|
11984
|
+
async ensureConversation() {
|
|
11779
11985
|
if (!this.client) {
|
|
11780
11986
|
throw new Error("ChatSession not connected. Call connect() first.");
|
|
11781
11987
|
}
|
|
11782
|
-
const { timeout = 30000, idleTimeout = 3000 } = options;
|
|
11783
11988
|
if (!this.conversationId) {
|
|
11784
11989
|
const conv = await this.client.createConversation({});
|
|
11785
11990
|
this.conversationId = conv.conversation.id;
|
|
11991
|
+
return conv.conversation.id;
|
|
11786
11992
|
}
|
|
11787
|
-
|
|
11993
|
+
return this.conversationId;
|
|
11994
|
+
}
|
|
11995
|
+
async _awaitResponses(conversationId, trigger, options = {}) {
|
|
11996
|
+
const { timeout = 30000, idleTimeout = 3000 } = options;
|
|
11788
11997
|
const responses = [];
|
|
11789
|
-
const listener = await this.client.listenConversation({
|
|
11790
|
-
id: conversationId
|
|
11791
|
-
});
|
|
11998
|
+
const listener = await this.client.listenConversation({ id: conversationId });
|
|
11792
11999
|
return new Promise((resolve4, reject) => {
|
|
11793
12000
|
let idleTimer = null;
|
|
11794
12001
|
let resolved = false;
|
|
@@ -11808,7 +12015,7 @@ class ChatSession {
|
|
|
11808
12015
|
};
|
|
11809
12016
|
const overallTimer = setTimeout(() => {
|
|
11810
12017
|
if (!resolved) {
|
|
11811
|
-
if (responses.length > 0) {
|
|
12018
|
+
if (responses.length > 0 || options.expectSilence) {
|
|
11812
12019
|
done();
|
|
11813
12020
|
} else {
|
|
11814
12021
|
resolved = true;
|
|
@@ -11831,10 +12038,7 @@ class ChatSession {
|
|
|
11831
12038
|
done();
|
|
11832
12039
|
}
|
|
11833
12040
|
});
|
|
11834
|
-
|
|
11835
|
-
conversationId,
|
|
11836
|
-
payload: { type: "text", text: message }
|
|
11837
|
-
}).then(() => {
|
|
12041
|
+
trigger().then(() => {
|
|
11838
12042
|
resetIdle();
|
|
11839
12043
|
}).catch((err) => {
|
|
11840
12044
|
clearTimeout(overallTimer);
|
|
@@ -11845,6 +12049,20 @@ class ChatSession {
|
|
|
11845
12049
|
});
|
|
11846
12050
|
});
|
|
11847
12051
|
}
|
|
12052
|
+
async sendMessage(message, options = {}) {
|
|
12053
|
+
if (!this.client) {
|
|
12054
|
+
throw new Error("ChatSession not connected. Call connect() first.");
|
|
12055
|
+
}
|
|
12056
|
+
const conversationId = await this.ensureConversation();
|
|
12057
|
+
return this._awaitResponses(conversationId, () => this.client.createMessage({ conversationId, payload: { type: "text", text: message } }), options);
|
|
12058
|
+
}
|
|
12059
|
+
async sendEvent(type, payload, options = {}) {
|
|
12060
|
+
if (!this.client) {
|
|
12061
|
+
throw new Error("ChatSession not connected. Call connect() first.");
|
|
12062
|
+
}
|
|
12063
|
+
const conversationId = await this.ensureConversation();
|
|
12064
|
+
return this._awaitResponses(conversationId, () => this.client.createEvent({ type, payload, conversationId }), options);
|
|
12065
|
+
}
|
|
11848
12066
|
}
|
|
11849
12067
|
async function discoverWebhookId(botId, token, apiUrl) {
|
|
11850
12068
|
const client = new BpClient({ token, botId, apiUrl });
|
|
@@ -11852,7 +12070,7 @@ async function discoverWebhookId(botId, token, apiUrl) {
|
|
|
11852
12070
|
const integrations = bot.integrations || {};
|
|
11853
12071
|
const chat = Object.values(integrations).find((int) => int.name === "chat");
|
|
11854
12072
|
const webhookId = chat?.webhookId;
|
|
11855
|
-
if (!webhookId) {
|
|
12073
|
+
if (!webhookId || typeof webhookId !== "string") {
|
|
11856
12074
|
throw new Error("No chat integration found on bot. Make sure the bot has the chat integration enabled.");
|
|
11857
12075
|
}
|
|
11858
12076
|
return webhookId;
|
|
@@ -11914,9 +12132,11 @@ async function getTraceData(conversationId, devServerUrl, options = {}) {
|
|
|
11914
12132
|
}
|
|
11915
12133
|
|
|
11916
12134
|
// src/eval/graders/llm.ts
|
|
11917
|
-
import { Cognitive } from "@botpress/
|
|
12135
|
+
import { Cognitive } from "@botpress/runtime";
|
|
11918
12136
|
import { Client as Client18 } from "@botpress/client";
|
|
11919
|
-
var
|
|
12137
|
+
var DEFAULT_PASS_THRESHOLD = 3;
|
|
12138
|
+
function buildJudgeSystemPrompt(passThreshold) {
|
|
12139
|
+
return `You are an evaluation judge for a chatbot. You will be given:
|
|
11920
12140
|
- The user's message
|
|
11921
12141
|
- The bot's response
|
|
11922
12142
|
- Grading criteria
|
|
@@ -11937,32 +12157,44 @@ Scoring guide:
|
|
|
11937
12157
|
- 2: Barely meets criteria, significant issues
|
|
11938
12158
|
- 1: Does not meet criteria
|
|
11939
12159
|
|
|
11940
|
-
A score of
|
|
12160
|
+
A score of ${passThreshold} or above is a pass.`;
|
|
12161
|
+
}
|
|
12162
|
+
var MODEL_ALIASES = ["fast", "best"];
|
|
11941
12163
|
var _cognitive = null;
|
|
11942
|
-
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
|
|
11946
|
-
|
|
11947
|
-
|
|
11948
|
-
|
|
11949
|
-
|
|
11950
|
-
const client = new Client18({ token, apiUrl, botId });
|
|
11951
|
-
_cognitive = new Cognitive({ client, __experimental_beta: true });
|
|
11952
|
-
return _cognitive;
|
|
12164
|
+
var _availableModels = [];
|
|
12165
|
+
var _judgeModel = "fast";
|
|
12166
|
+
function _isModelValid(model) {
|
|
12167
|
+
if (MODEL_ALIASES.includes(model))
|
|
12168
|
+
return true;
|
|
12169
|
+
if (_availableModels.length === 0)
|
|
12170
|
+
return false;
|
|
12171
|
+
return _availableModels.includes(model);
|
|
11953
12172
|
}
|
|
11954
|
-
function initLLMJudge(credentials) {
|
|
12173
|
+
async function initLLMJudge(credentials, options) {
|
|
12174
|
+
const log = options?.logger ?? console;
|
|
11955
12175
|
const client = new Client18({
|
|
11956
12176
|
token: credentials.token,
|
|
11957
12177
|
apiUrl: credentials.apiUrl,
|
|
11958
12178
|
botId: credentials.botId
|
|
11959
12179
|
});
|
|
11960
12180
|
_cognitive = new Cognitive({ client, __experimental_beta: true });
|
|
12181
|
+
try {
|
|
12182
|
+
_availableModels = Array.from((await _cognitive.fetchRemoteModels()).keys());
|
|
12183
|
+
} catch (err) {
|
|
12184
|
+
log.warn(`Failed to fetch available models: ${err.message}. LLM judge will be unavailable.`);
|
|
12185
|
+
_availableModels = [];
|
|
12186
|
+
}
|
|
12187
|
+
_judgeModel = options?.model ?? "fast";
|
|
12188
|
+
if (_availableModels.length === 0) {
|
|
12189
|
+
log.warn("No available Cognitive models: cannot validate judge model.");
|
|
12190
|
+
} else if (!_isModelValid(_judgeModel)) {
|
|
12191
|
+
log.warn(`Configured LLM judge model "${_judgeModel}" is invalid. Run "adk models" to list available models.`);
|
|
12192
|
+
}
|
|
11961
12193
|
}
|
|
11962
12194
|
async function gradeLLMJudge(botResponse, criteria, context) {
|
|
12195
|
+
const threshold = Math.max(1, Math.min(5, context.passThreshold ?? DEFAULT_PASS_THRESHOLD));
|
|
11963
12196
|
try {
|
|
11964
|
-
|
|
11965
|
-
if (!cognitive) {
|
|
12197
|
+
if (!_cognitive) {
|
|
11966
12198
|
return {
|
|
11967
12199
|
assertion: `llm_judge: "${criteria}"`,
|
|
11968
12200
|
pass: true,
|
|
@@ -11970,11 +12202,19 @@ async function gradeLLMJudge(botResponse, criteria, context) {
|
|
|
11970
12202
|
actual: "SKIPPED — LLM judge unavailable: no credentials configured"
|
|
11971
12203
|
};
|
|
11972
12204
|
}
|
|
11973
|
-
|
|
11974
|
-
|
|
12205
|
+
if (!_isModelValid(_judgeModel)) {
|
|
12206
|
+
return {
|
|
12207
|
+
assertion: `llm_judge: "${criteria}"`,
|
|
12208
|
+
pass: false,
|
|
12209
|
+
expected: criteria,
|
|
12210
|
+
actual: "FAILED — invalid LLM judge model"
|
|
12211
|
+
};
|
|
12212
|
+
}
|
|
12213
|
+
const { output } = await _cognitive.generateContent({
|
|
12214
|
+
model: _judgeModel,
|
|
11975
12215
|
temperature: 0,
|
|
11976
12216
|
responseFormat: "json_object",
|
|
11977
|
-
systemPrompt:
|
|
12217
|
+
systemPrompt: buildJudgeSystemPrompt(threshold),
|
|
11978
12218
|
messages: [
|
|
11979
12219
|
{
|
|
11980
12220
|
role: "user",
|
|
@@ -11999,9 +12239,9 @@ Criteria: ${criteria}`
|
|
|
11999
12239
|
const verdict = JSON.parse(content);
|
|
12000
12240
|
return {
|
|
12001
12241
|
assertion: `llm_judge: "${criteria}"`,
|
|
12002
|
-
pass: verdict.score >=
|
|
12242
|
+
pass: verdict.score >= threshold,
|
|
12003
12243
|
expected: criteria,
|
|
12004
|
-
actual: `Score ${verdict.score}/5 — ${verdict.reason}`
|
|
12244
|
+
actual: `Score ${verdict.score}/5 (threshold: ${threshold}) — ${verdict.reason}`
|
|
12005
12245
|
};
|
|
12006
12246
|
} catch (err) {
|
|
12007
12247
|
return {
|
|
@@ -12049,7 +12289,10 @@ async function gradeResponse(botResponse, assertions, context) {
|
|
|
12049
12289
|
continue;
|
|
12050
12290
|
}
|
|
12051
12291
|
if ("llm_judge" in assertion) {
|
|
12052
|
-
const result = await gradeLLMJudge(botResponse, assertion.llm_judge,
|
|
12292
|
+
const result = await gradeLLMJudge(botResponse, assertion.llm_judge, {
|
|
12293
|
+
userMessage: context.userMessage,
|
|
12294
|
+
passThreshold: context.judgePassThreshold
|
|
12295
|
+
});
|
|
12053
12296
|
results.push(result);
|
|
12054
12297
|
continue;
|
|
12055
12298
|
}
|
|
@@ -12201,6 +12444,7 @@ function gradeTools(toolCalls, assertions) {
|
|
|
12201
12444
|
}
|
|
12202
12445
|
|
|
12203
12446
|
// src/eval/graders/state.ts
|
|
12447
|
+
import { BUILT_IN_STATES } from "@botpress/runtime/internal";
|
|
12204
12448
|
function parseStatePath(path42) {
|
|
12205
12449
|
const dot = path42.indexOf(".");
|
|
12206
12450
|
if (dot === -1) {
|
|
@@ -12210,11 +12454,16 @@ function parseStatePath(path42) {
|
|
|
12210
12454
|
const field = path42.slice(dot + 1);
|
|
12211
12455
|
switch (prefix) {
|
|
12212
12456
|
case "bot":
|
|
12213
|
-
return { type: "bot", stateName:
|
|
12457
|
+
return { type: "bot", stateName: BUILT_IN_STATES.bot, stateId: (ctx) => ctx.botId, field };
|
|
12214
12458
|
case "user":
|
|
12215
|
-
return { type: "user", stateName:
|
|
12459
|
+
return { type: "user", stateName: BUILT_IN_STATES.user, stateId: (ctx) => ctx.userId, field };
|
|
12216
12460
|
case "conversation":
|
|
12217
|
-
return {
|
|
12461
|
+
return {
|
|
12462
|
+
type: "conversation",
|
|
12463
|
+
stateName: BUILT_IN_STATES.conversation,
|
|
12464
|
+
stateId: (ctx) => ctx.conversationId,
|
|
12465
|
+
field
|
|
12466
|
+
};
|
|
12218
12467
|
default:
|
|
12219
12468
|
throw new Error(`Unknown state type "${prefix}" in path "${path42}" — expected bot, user, or conversation`);
|
|
12220
12469
|
}
|
|
@@ -12225,7 +12474,9 @@ async function fetchState(client, type, id, name) {
|
|
|
12225
12474
|
const payload = result.state?.payload;
|
|
12226
12475
|
return payload?.value ?? payload ?? null;
|
|
12227
12476
|
} catch (err) {
|
|
12228
|
-
|
|
12477
|
+
const code = err != null && typeof err === "object" && "code" in err ? err.code : undefined;
|
|
12478
|
+
const message = err instanceof Error ? err.message : "";
|
|
12479
|
+
if (code === 404 || message.includes("404") || message.includes("doesn't exist")) {
|
|
12229
12480
|
return null;
|
|
12230
12481
|
}
|
|
12231
12482
|
throw err;
|
|
@@ -12249,7 +12500,7 @@ async function snapshotState(client, assertions, ctx) {
|
|
|
12249
12500
|
if (assertion.changed === undefined)
|
|
12250
12501
|
continue;
|
|
12251
12502
|
const parsed = parseStatePath(assertion.path);
|
|
12252
|
-
if (parsed.type === "conversation")
|
|
12503
|
+
if (parsed.type === "conversation" && !ctx.conversationId)
|
|
12253
12504
|
continue;
|
|
12254
12505
|
const payload = await fetchState(client, parsed.type, parsed.stateId(ctx), parsed.stateName);
|
|
12255
12506
|
snapshots.set(assertion.path, payload ? payload[parsed.field] : undefined);
|
|
@@ -12462,6 +12713,22 @@ function gradeWorkflows(spans, assertions) {
|
|
|
12462
12713
|
return results;
|
|
12463
12714
|
}
|
|
12464
12715
|
|
|
12716
|
+
// src/eval/graders/timing.ts
|
|
12717
|
+
function gradeTiming(botDuration, assertions) {
|
|
12718
|
+
const results = [];
|
|
12719
|
+
for (const assertion of assertions) {
|
|
12720
|
+
const pass = matchValue(assertion.response_time, botDuration);
|
|
12721
|
+
const expected = operatorToString(assertion.response_time);
|
|
12722
|
+
results.push({
|
|
12723
|
+
assertion: `response_time ${expected}`,
|
|
12724
|
+
pass,
|
|
12725
|
+
expected: `Response time ${expected}`,
|
|
12726
|
+
actual: `${botDuration}ms`
|
|
12727
|
+
});
|
|
12728
|
+
}
|
|
12729
|
+
return results;
|
|
12730
|
+
}
|
|
12731
|
+
|
|
12465
12732
|
// src/eval/graders/outcome.ts
|
|
12466
12733
|
async function snapshotOutcomeState(client, evalDef, ctx) {
|
|
12467
12734
|
if (!evalDef.outcome?.state) {
|
|
@@ -12492,9 +12759,64 @@ async function gradeOutcome(client, evalDef, ctx, traceSpans, preSnapshots) {
|
|
|
12492
12759
|
// src/eval/runner.ts
|
|
12493
12760
|
import { randomUUID } from "crypto";
|
|
12494
12761
|
var DEFAULT_IDLE_TIMEOUT = 15000;
|
|
12762
|
+
var WORKFLOW_TRIGGER_TIMEOUT_MS = 5 * 60 * 1000;
|
|
12763
|
+
function buildStatePayload(value) {
|
|
12764
|
+
return {
|
|
12765
|
+
value,
|
|
12766
|
+
location: { type: "state" }
|
|
12767
|
+
};
|
|
12768
|
+
}
|
|
12769
|
+
async function seedEvalState(client, ctx, setup) {
|
|
12770
|
+
const state = setup?.state;
|
|
12771
|
+
if (!state)
|
|
12772
|
+
return;
|
|
12773
|
+
const writes = [];
|
|
12774
|
+
if (state.bot) {
|
|
12775
|
+
writes.push(client.setState({
|
|
12776
|
+
type: "bot",
|
|
12777
|
+
id: ctx.botId,
|
|
12778
|
+
name: BUILT_IN_STATES2.bot,
|
|
12779
|
+
payload: buildStatePayload(state.bot)
|
|
12780
|
+
}));
|
|
12781
|
+
}
|
|
12782
|
+
if (state.user) {
|
|
12783
|
+
writes.push(client.setState({
|
|
12784
|
+
type: "user",
|
|
12785
|
+
id: ctx.userId,
|
|
12786
|
+
name: BUILT_IN_STATES2.user,
|
|
12787
|
+
payload: buildStatePayload(state.user)
|
|
12788
|
+
}));
|
|
12789
|
+
}
|
|
12790
|
+
if (state.conversation) {
|
|
12791
|
+
if (!ctx.conversationId) {
|
|
12792
|
+
throw new Error("Cannot seed conversation state before a conversation is created.");
|
|
12793
|
+
}
|
|
12794
|
+
writes.push(client.setState({
|
|
12795
|
+
type: "conversation",
|
|
12796
|
+
id: ctx.conversationId,
|
|
12797
|
+
name: BUILT_IN_STATES2.conversation,
|
|
12798
|
+
payload: buildStatePayload(state.conversation)
|
|
12799
|
+
}));
|
|
12800
|
+
}
|
|
12801
|
+
await Promise.all(writes);
|
|
12802
|
+
}
|
|
12803
|
+
async function triggerEvalWorkflow(client, ctx, setup) {
|
|
12804
|
+
const workflow = setup?.workflow;
|
|
12805
|
+
if (!workflow)
|
|
12806
|
+
return;
|
|
12807
|
+
await client.createWorkflow({
|
|
12808
|
+
name: workflow.trigger,
|
|
12809
|
+
input: workflow.input ?? {},
|
|
12810
|
+
status: "pending",
|
|
12811
|
+
conversationId: ctx.conversationId,
|
|
12812
|
+
userId: ctx.userId,
|
|
12813
|
+
timeoutAt: new Date(Date.now() + WORKFLOW_TRIGGER_TIMEOUT_MS).toISOString()
|
|
12814
|
+
});
|
|
12815
|
+
}
|
|
12495
12816
|
async function runEval(evalDef, connection, options = {}) {
|
|
12496
12817
|
const devServerUrl = options.devServerUrl || "http://localhost:3001";
|
|
12497
12818
|
const idleTimeout = evalDef.options?.idleTimeout ?? options.idleTimeout ?? DEFAULT_IDLE_TIMEOUT;
|
|
12819
|
+
const judgePassThreshold = evalDef.options?.judgePassThreshold ?? options.judgePassThreshold;
|
|
12498
12820
|
const start = Date.now();
|
|
12499
12821
|
const turns = [];
|
|
12500
12822
|
let outcomeAssertions = [];
|
|
@@ -12512,34 +12834,67 @@ async function runEval(evalDef, connection, options = {}) {
|
|
|
12512
12834
|
}
|
|
12513
12835
|
return bpClient;
|
|
12514
12836
|
};
|
|
12837
|
+
let lastConversationId = "";
|
|
12838
|
+
if (evalDef.setup?.state?.conversation || evalDef.setup?.workflow) {
|
|
12839
|
+
lastConversationId = await session.ensureConversation();
|
|
12840
|
+
}
|
|
12841
|
+
await seedEvalState(getBpClient(), {
|
|
12842
|
+
botId: connection.botId,
|
|
12843
|
+
userId: session.userId,
|
|
12844
|
+
conversationId: lastConversationId || undefined
|
|
12845
|
+
}, evalDef.setup);
|
|
12846
|
+
await triggerEvalWorkflow(getBpClient(), {
|
|
12847
|
+
userId: session.userId,
|
|
12848
|
+
conversationId: lastConversationId || undefined
|
|
12849
|
+
}, evalDef.setup);
|
|
12515
12850
|
let preSnapshots = new Map;
|
|
12516
12851
|
if (evalDef.outcome?.state) {
|
|
12517
12852
|
const ctx = {
|
|
12518
12853
|
botId: connection.botId,
|
|
12519
12854
|
userId: session.userId,
|
|
12520
|
-
conversationId:
|
|
12855
|
+
conversationId: lastConversationId
|
|
12521
12856
|
};
|
|
12522
12857
|
preSnapshots = await snapshotOutcomeState(getBpClient(), evalDef, ctx);
|
|
12523
12858
|
}
|
|
12524
12859
|
let previousToolCallCount = 0;
|
|
12525
|
-
let lastConversationId = "";
|
|
12526
12860
|
let allSpans = [];
|
|
12527
12861
|
for (let i = 0;i < evalDef.conversation.length; i++) {
|
|
12528
12862
|
const turn = evalDef.conversation[i];
|
|
12529
12863
|
const turnStart = Date.now();
|
|
12530
|
-
|
|
12531
|
-
|
|
12532
|
-
|
|
12533
|
-
|
|
12864
|
+
if (turn.expectSilence && turn.assert?.response) {
|
|
12865
|
+
throw new Error(`Turn ${i + 1}: 'expectSilence' and 'assert.response' are mutually exclusive.`);
|
|
12866
|
+
}
|
|
12867
|
+
if (turn.user && turn.event) {
|
|
12868
|
+
throw new Error(`Turn ${i + 1}: 'user' and 'event' are mutually exclusive.`);
|
|
12869
|
+
}
|
|
12870
|
+
if (!turn.user && !turn.event) {
|
|
12871
|
+
throw new Error(`Turn ${i + 1}: must have either 'user' or 'event'.`);
|
|
12872
|
+
}
|
|
12873
|
+
const sendOptions = { timeout: Math.max(30000, idleTimeout * 2), idleTimeout, expectSilence: turn.expectSilence };
|
|
12874
|
+
const result = turn.event ? await session.sendEvent(turn.event.type, turn.event.payload ?? {}, sendOptions) : await session.sendMessage(turn.user, sendOptions);
|
|
12534
12875
|
const botDuration = Date.now() - turnStart;
|
|
12876
|
+
if (!turn.expectSilence && result.responses.length === 0) {
|
|
12877
|
+
throw new Error(`Turn ${i + 1}: bot produced no response.`);
|
|
12878
|
+
}
|
|
12535
12879
|
lastConversationId = result.conversationId;
|
|
12536
12880
|
const botResponse = result.responses.map((r) => r.text).join(`
|
|
12537
12881
|
`);
|
|
12882
|
+
const turnLabel = turn.event ? `[event: ${turn.event.type}]` : turn.user;
|
|
12538
12883
|
const evalStart = Date.now();
|
|
12539
12884
|
let assertions = [];
|
|
12885
|
+
if (turn.expectSilence) {
|
|
12886
|
+
const wasSilent = result.responses.length === 0;
|
|
12887
|
+
assertions.push({
|
|
12888
|
+
assertion: "no_response",
|
|
12889
|
+
pass: wasSilent,
|
|
12890
|
+
expected: "No response",
|
|
12891
|
+
actual: wasSilent ? "No response" : `Bot responded: "${botResponse}"`
|
|
12892
|
+
});
|
|
12893
|
+
}
|
|
12540
12894
|
if (turn.assert?.response) {
|
|
12541
12895
|
assertions = await gradeResponse(botResponse, turn.assert.response, {
|
|
12542
|
-
userMessage:
|
|
12896
|
+
userMessage: turnLabel,
|
|
12897
|
+
judgePassThreshold
|
|
12543
12898
|
});
|
|
12544
12899
|
}
|
|
12545
12900
|
if (turn.assert?.tools) {
|
|
@@ -12606,11 +12961,15 @@ async function runEval(evalDef, connection, options = {}) {
|
|
|
12606
12961
|
const workflowResults = gradeWorkflows(allSpans, turn.assert.workflow);
|
|
12607
12962
|
assertions.push(...workflowResults);
|
|
12608
12963
|
}
|
|
12964
|
+
if (turn.assert?.timing) {
|
|
12965
|
+
const timingResults = gradeTiming(botDuration, turn.assert.timing);
|
|
12966
|
+
assertions.push(...timingResults);
|
|
12967
|
+
}
|
|
12609
12968
|
const turnPass = assertions.every((a) => a.pass);
|
|
12610
12969
|
const evalDuration = Date.now() - evalStart;
|
|
12611
12970
|
turns.push({
|
|
12612
12971
|
turnNumber: i + 1,
|
|
12613
|
-
userMessage:
|
|
12972
|
+
userMessage: turnLabel,
|
|
12614
12973
|
botResponse,
|
|
12615
12974
|
assertions,
|
|
12616
12975
|
pass: turnPass,
|
|
@@ -12672,11 +13031,11 @@ async function runEval(evalDef, connection, options = {}) {
|
|
|
12672
13031
|
async function runEvalSuite(config, filter) {
|
|
12673
13032
|
const start = Date.now();
|
|
12674
13033
|
const runId = randomUUID().replace(/-/g, "").slice(0, 26);
|
|
12675
|
-
initLLMJudge({
|
|
13034
|
+
await initLLMJudge({
|
|
12676
13035
|
token: config.credentials.token,
|
|
12677
13036
|
apiUrl: config.credentials.apiUrl,
|
|
12678
13037
|
botId: config.credentials.botId
|
|
12679
|
-
});
|
|
13038
|
+
}, { model: config.evalOptions?.judgeModel, logger: config.logger });
|
|
12680
13039
|
const evalsDir = `${config.agentPath}/evals`;
|
|
12681
13040
|
const allEvals = await loadEvalsFromDir(evalsDir);
|
|
12682
13041
|
const evals = filterEvals(allEvals, filter);
|
|
@@ -12708,7 +13067,11 @@ async function runEvalSuite(config, filter) {
|
|
|
12708
13067
|
for (let i = 0;i < evals.length; i++) {
|
|
12709
13068
|
const evalDef = evals[i];
|
|
12710
13069
|
config.onProgress?.({ type: "eval_start", evalName: evalDef.name, index: i });
|
|
12711
|
-
const report = await runEval(evalDef, connection, {
|
|
13070
|
+
const report = await runEval(evalDef, connection, {
|
|
13071
|
+
devServerUrl,
|
|
13072
|
+
idleTimeout: config.evalOptions?.idleTimeout,
|
|
13073
|
+
judgePassThreshold: config.evalOptions?.judgePassThreshold
|
|
13074
|
+
});
|
|
12712
13075
|
reports.push(report);
|
|
12713
13076
|
config.onProgress?.({ type: "eval_complete", evalName: evalDef.name, index: i, report });
|
|
12714
13077
|
}
|
|
@@ -12799,6 +13162,7 @@ export {
|
|
|
12799
13162
|
buildOpenCodeConfig,
|
|
12800
13163
|
bpCliImporter,
|
|
12801
13164
|
auth,
|
|
13165
|
+
agentLocalInfoKeyOrder,
|
|
12802
13166
|
agentInfoKeyOrder,
|
|
12803
13167
|
ValidationSeverity,
|
|
12804
13168
|
ValidationErrors,
|
|
@@ -12845,4 +13209,4 @@ export {
|
|
|
12845
13209
|
AgentProject
|
|
12846
13210
|
};
|
|
12847
13211
|
|
|
12848
|
-
//# debugId=
|
|
13212
|
+
//# debugId=984405F8F441F45F64756E2164756E21
|