@elizaos/cli 1.0.15 → 1.0.16
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/assets/{index-CYy-fwbh.js → index-BBiLesJT.js} +3 -3
- package/dist/assets/index-BBiLesJT.js.br +0 -0
- package/dist/assets/{index-CYy-fwbh.js.map → index-BBiLesJT.js.map} +1 -1
- package/dist/assets/index-DxW_jg81.css +1 -0
- package/dist/assets/index-DxW_jg81.css.br +0 -0
- package/dist/assets/{index-TE3LspKB.js → index-EfDd1Y35.js} +2103 -1818
- package/dist/assets/index-EfDd1Y35.js.br +0 -0
- package/dist/assets/{index-TE3LspKB.js.map → index-EfDd1Y35.js.map} +1 -1
- package/dist/assets/{vendor-DSdxb8P-.js → vendor-DS2z8upE.js} +2 -2
- package/dist/assets/vendor-DS2z8upE.js.br +0 -0
- package/dist/assets/{vendor-DSdxb8P-.js.map → vendor-DS2z8upE.js.map} +1 -1
- package/dist/{chunk-AZUBN22B.js → chunk-OK5O2MHJ.js} +503 -705
- package/dist/{chunk-OXZUNMVC.js → chunk-PRO6QOLZ.js} +175 -48
- package/dist/{chunk-BRDZOULQ.js → chunk-UVBNT4WP.js} +19 -6
- package/dist/{chunk-KB3JDWUI.js → chunk-W4NJVJQV.js} +43 -1
- package/dist/commands/agent/actions/index.js +2 -3
- package/dist/commands/agent/index.js +2 -3
- package/dist/commands/create/actions/index.d.ts +3 -0
- package/dist/commands/create/actions/index.js +3 -4
- package/dist/commands/create/index.js +4 -5
- package/dist/elizaos-avatar.png +0 -0
- package/dist/index.html +3 -3
- package/dist/index.js +1462 -381
- package/dist/migration-guides/advanced-migration-guide.md +459 -0
- package/dist/migration-guides/completion-requirements.md +379 -0
- package/dist/migration-guides/integrated-migration-loop.md +392 -0
- package/dist/migration-guides/migration-guide.md +712 -0
- package/dist/migration-guides/prompt-and-generation-guide.md +702 -0
- package/dist/migration-guides/state-and-providers-guide.md +544 -0
- package/dist/migration-guides/testing-guide.md +1021 -0
- package/dist/{plugin-creator-TLQLTQIB.js → plugin-creator-ZCOZ3UCT.js} +1 -2
- package/dist/{registry-BQSPZS3F.js → registry-FBPEGL2T.js} +2 -3
- package/dist/templates/project-starter/package.json +4 -4
- package/dist/templates/project-tee-starter/package.json +3 -3
- package/dist/{utils-BROS5JZQ.js → utils-I3EA43DE.js} +6 -19
- package/package.json +8 -6
- package/templates/project-starter/package.json +4 -4
- package/templates/project-tee-starter/package.json +3 -3
- package/dist/assets/index-CYy-fwbh.js.br +0 -0
- package/dist/assets/index-DzLbKTxV.css +0 -1
- package/dist/assets/index-DzLbKTxV.css.br +0 -0
- package/dist/assets/index-TE3LspKB.js.br +0 -0
- package/dist/assets/vendor-DSdxb8P-.js.br +0 -0
- package/dist/chunk-RIAWNDYI.js +0 -49
- package/dist/migrator-UQ4XFYE5.js +0 -744
package/dist/index.js
CHANGED
|
@@ -5,10 +5,10 @@ const require = createRequire(import.meta.url);
|
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
create
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-UVBNT4WP.js";
|
|
9
9
|
import {
|
|
10
10
|
getElizaCharacter
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-PRO6QOLZ.js";
|
|
12
12
|
import {
|
|
13
13
|
TestRunner,
|
|
14
14
|
UserEnvironment,
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
buildProject,
|
|
17
17
|
checkAndShowUpdateNotification,
|
|
18
18
|
configureDatabaseSettings,
|
|
19
|
+
createEnvFileService,
|
|
19
20
|
detectDirectoryType,
|
|
20
21
|
detectPluginContext,
|
|
21
22
|
displayBanner,
|
|
@@ -38,7 +39,6 @@ import {
|
|
|
38
39
|
logHeader,
|
|
39
40
|
migrateCliToBun,
|
|
40
41
|
normalizePluginName,
|
|
41
|
-
promptForEnvVars,
|
|
42
42
|
provideLocalPluginGuidance,
|
|
43
43
|
publishToGitHub,
|
|
44
44
|
resolvePgliteDir,
|
|
@@ -46,14 +46,12 @@ import {
|
|
|
46
46
|
testPublishToGitHub,
|
|
47
47
|
testPublishToNpm,
|
|
48
48
|
validateDataDir
|
|
49
|
-
} from "./chunk-
|
|
50
|
-
import {
|
|
51
|
-
runBunCommand
|
|
52
|
-
} from "./chunk-RIAWNDYI.js";
|
|
49
|
+
} from "./chunk-OK5O2MHJ.js";
|
|
53
50
|
import {
|
|
54
51
|
configureEmojis,
|
|
55
|
-
emoji
|
|
56
|
-
|
|
52
|
+
emoji,
|
|
53
|
+
runBunCommand
|
|
54
|
+
} from "./chunk-W4NJVJQV.js";
|
|
57
55
|
import "./chunk-F24MS2YR.js";
|
|
58
56
|
import "./chunk-AQ6OMR2A.js";
|
|
59
57
|
|
|
@@ -412,51 +410,30 @@ import { existsSync as existsSync4 } from "fs";
|
|
|
412
410
|
import path4 from "path";
|
|
413
411
|
|
|
414
412
|
// src/commands/env/utils/file-operations.ts
|
|
415
|
-
import dotenv from "dotenv";
|
|
416
413
|
import { existsSync as existsSync3 } from "fs";
|
|
417
|
-
import fs from "fs/promises";
|
|
418
414
|
import path3 from "path";
|
|
419
415
|
async function getLocalEnvPath() {
|
|
420
416
|
const localEnvPath = path3.join(process.cwd(), ".env");
|
|
421
417
|
return existsSync3(localEnvPath) ? localEnvPath : null;
|
|
422
418
|
}
|
|
423
419
|
async function parseEnvFile(filePath) {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
return {};
|
|
427
|
-
}
|
|
428
|
-
const content = await fs.readFile(filePath, "utf-8");
|
|
429
|
-
if (content.trim() === "") {
|
|
430
|
-
return {};
|
|
431
|
-
}
|
|
432
|
-
return dotenv.parse(content);
|
|
433
|
-
} catch (error) {
|
|
434
|
-
console.error(
|
|
435
|
-
`Error parsing .env file: ${error instanceof Error ? error.message : String(error)}`
|
|
436
|
-
);
|
|
437
|
-
return {};
|
|
438
|
-
}
|
|
420
|
+
const service = createEnvFileService(filePath);
|
|
421
|
+
return service.read();
|
|
439
422
|
}
|
|
440
423
|
async function writeEnvFile(filePath, envVars) {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
const content = Object.entries(envVars).map(([key, value]) => `${key}=${value}`).join("\n");
|
|
447
|
-
await fs.writeFile(filePath, content);
|
|
448
|
-
} catch (error) {
|
|
449
|
-
console.error(
|
|
450
|
-
`Error writing .env file: ${error instanceof Error ? error.message : String(error)}`
|
|
451
|
-
);
|
|
452
|
-
}
|
|
424
|
+
const service = createEnvFileService(filePath);
|
|
425
|
+
await service.write(envVars, {
|
|
426
|
+
preserveComments: true,
|
|
427
|
+
updateProcessEnv: true
|
|
428
|
+
});
|
|
453
429
|
}
|
|
454
430
|
async function resetEnvFile(filePath) {
|
|
455
431
|
try {
|
|
456
432
|
if (!existsSync3(filePath)) {
|
|
457
433
|
return false;
|
|
458
434
|
}
|
|
459
|
-
const
|
|
435
|
+
const service = createEnvFileService(filePath);
|
|
436
|
+
const envVars = await service.read();
|
|
460
437
|
if (Object.keys(envVars).length === 0) {
|
|
461
438
|
return false;
|
|
462
439
|
}
|
|
@@ -464,7 +441,11 @@ async function resetEnvFile(filePath) {
|
|
|
464
441
|
acc[key] = "";
|
|
465
442
|
return acc;
|
|
466
443
|
}, {});
|
|
467
|
-
await
|
|
444
|
+
await service.write(resetVars, {
|
|
445
|
+
preserveComments: true,
|
|
446
|
+
updateProcessEnv: false
|
|
447
|
+
// Don't update process.env with empty values
|
|
448
|
+
});
|
|
468
449
|
return true;
|
|
469
450
|
} catch (error) {
|
|
470
451
|
console.error(
|
|
@@ -584,7 +565,7 @@ async function editEnvVars(options, fromMainMenu = false) {
|
|
|
584
565
|
console.log(`\u2713 Updated ${selection}`);
|
|
585
566
|
}
|
|
586
567
|
} else if (action === "delete") {
|
|
587
|
-
let
|
|
568
|
+
let confirm9 = true;
|
|
588
569
|
if (!yes) {
|
|
589
570
|
const resp = await clack.confirm({
|
|
590
571
|
message: `Are you sure you want to delete ${selection}?`,
|
|
@@ -594,9 +575,9 @@ async function editEnvVars(options, fromMainMenu = false) {
|
|
|
594
575
|
clack.cancel("Operation cancelled.");
|
|
595
576
|
process.exit(0);
|
|
596
577
|
}
|
|
597
|
-
|
|
578
|
+
confirm9 = resp;
|
|
598
579
|
}
|
|
599
|
-
if (
|
|
580
|
+
if (confirm9) {
|
|
600
581
|
delete envVars[selection];
|
|
601
582
|
await writeEnvFile(localEnvPath, envVars);
|
|
602
583
|
console.log(`\u2713 Removed ${selection}`);
|
|
@@ -810,15 +791,15 @@ async function resetEnv(options) {
|
|
|
810
791
|
const item = resetItems.find((item2) => item2.value === value);
|
|
811
792
|
console.log(` \u2022 ${item?.title || value}`);
|
|
812
793
|
}
|
|
813
|
-
const
|
|
794
|
+
const confirm9 = await clack2.confirm({
|
|
814
795
|
message: "Are you sure you want to reset the selected items?",
|
|
815
796
|
initialValue: false
|
|
816
797
|
});
|
|
817
|
-
if (clack2.isCancel(
|
|
798
|
+
if (clack2.isCancel(confirm9)) {
|
|
818
799
|
clack2.cancel("Operation cancelled.");
|
|
819
800
|
process.exit(0);
|
|
820
801
|
}
|
|
821
|
-
if (!
|
|
802
|
+
if (!confirm9) {
|
|
822
803
|
console.log("Reset cancelled.");
|
|
823
804
|
return;
|
|
824
805
|
}
|
|
@@ -996,21 +977,70 @@ var extractPackageName = (pluginInput) => {
|
|
|
996
977
|
|
|
997
978
|
// src/commands/plugins/utils/env-vars.ts
|
|
998
979
|
import { logger } from "@elizaos/core";
|
|
999
|
-
import { existsSync as existsSync8, readFileSync,
|
|
980
|
+
import { existsSync as existsSync8, readFileSync, readdirSync as readdirSync2 } from "fs";
|
|
1000
981
|
import path7 from "path";
|
|
1001
982
|
import * as clack4 from "@clack/prompts";
|
|
1002
983
|
var extractPluginEnvRequirements = async (packageName, cwd) => {
|
|
1003
984
|
try {
|
|
1004
|
-
const
|
|
1005
|
-
|
|
1006
|
-
|
|
985
|
+
const possiblePaths = [
|
|
986
|
+
// Direct path
|
|
987
|
+
path7.join(cwd, "node_modules", packageName, "package.json"),
|
|
988
|
+
// Scoped package path (e.g., @elizaos/plugin-discord)
|
|
989
|
+
path7.join(cwd, "node_modules", packageName.replace("/", path7.sep), "package.json")
|
|
990
|
+
];
|
|
991
|
+
if (!packageName.startsWith("@elizaos/")) {
|
|
992
|
+
possiblePaths.push(
|
|
993
|
+
path7.join(cwd, "node_modules", "@elizaos", packageName, "package.json"),
|
|
994
|
+
path7.join(cwd, "node_modules", "@elizaos", `plugin-${packageName}`, "package.json")
|
|
995
|
+
);
|
|
996
|
+
}
|
|
997
|
+
let currentDir = cwd;
|
|
998
|
+
for (let i = 0; i < 5; i++) {
|
|
999
|
+
const parentNodeModules = path7.join(currentDir, "node_modules");
|
|
1000
|
+
if (existsSync8(parentNodeModules)) {
|
|
1001
|
+
possiblePaths.push(
|
|
1002
|
+
path7.join(parentNodeModules, packageName, "package.json"),
|
|
1003
|
+
path7.join(parentNodeModules, packageName.replace("/", path7.sep), "package.json")
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
const parentDir = path7.dirname(currentDir);
|
|
1007
|
+
if (parentDir === currentDir) break;
|
|
1008
|
+
currentDir = parentDir;
|
|
1009
|
+
}
|
|
1010
|
+
let packageJsonPath = null;
|
|
1011
|
+
for (const possiblePath of possiblePaths) {
|
|
1012
|
+
if (existsSync8(possiblePath)) {
|
|
1013
|
+
packageJsonPath = possiblePath;
|
|
1014
|
+
logger.debug(`Found plugin package.json at: ${packageJsonPath}`);
|
|
1015
|
+
break;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
if (!packageJsonPath) {
|
|
1019
|
+
const nodeModulesPath = path7.join(cwd, "node_modules");
|
|
1020
|
+
if (existsSync8(nodeModulesPath)) {
|
|
1021
|
+
const packages = readdirSync2(nodeModulesPath);
|
|
1022
|
+
for (const pkg of packages) {
|
|
1023
|
+
if (pkg.includes(packageName.replace("@elizaos/", "").replace("plugin-", ""))) {
|
|
1024
|
+
const pkgJsonPath = path7.join(nodeModulesPath, pkg, "package.json");
|
|
1025
|
+
if (existsSync8(pkgJsonPath)) {
|
|
1026
|
+
packageJsonPath = pkgJsonPath;
|
|
1027
|
+
logger.debug(`Found matching plugin package.json at: ${packageJsonPath}`);
|
|
1028
|
+
break;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
if (!packageJsonPath) {
|
|
1035
|
+
logger.debug(`Plugin package.json not found for: ${packageName}`);
|
|
1036
|
+
logger.debug(`Searched paths: ${possiblePaths.join(", ")}`);
|
|
1007
1037
|
return {};
|
|
1008
1038
|
}
|
|
1009
|
-
const packageJsonContent = readFileSync(
|
|
1039
|
+
const packageJsonContent = readFileSync(packageJsonPath, "utf-8");
|
|
1010
1040
|
const packageJson = JSON.parse(packageJsonContent);
|
|
1011
1041
|
const agentConfig = packageJson.agentConfig;
|
|
1012
1042
|
if (!agentConfig || !agentConfig.pluginParameters) {
|
|
1013
|
-
logger.debug(`No agentConfig.pluginParameters found in ${packageName}`);
|
|
1043
|
+
logger.debug(`No agentConfig.pluginParameters found in ${packageName} at ${packageJsonPath}`);
|
|
1014
1044
|
return {};
|
|
1015
1045
|
}
|
|
1016
1046
|
logger.debug(
|
|
@@ -1024,17 +1054,10 @@ var extractPluginEnvRequirements = async (packageName, cwd) => {
|
|
|
1024
1054
|
return {};
|
|
1025
1055
|
}
|
|
1026
1056
|
};
|
|
1027
|
-
var readEnvFile = (cwd) => {
|
|
1028
|
-
const envPath = path7.join(cwd, ".env");
|
|
1029
|
-
try {
|
|
1030
|
-
return readFileSync(envPath, "utf-8");
|
|
1031
|
-
} catch (error) {
|
|
1032
|
-
return "";
|
|
1033
|
-
}
|
|
1034
|
-
};
|
|
1035
|
-
var writeEnvFile2 = (cwd, content) => {
|
|
1057
|
+
var readEnvFile = async (cwd) => {
|
|
1036
1058
|
const envPath = path7.join(cwd, ".env");
|
|
1037
|
-
|
|
1059
|
+
const envService = createEnvFileService(envPath);
|
|
1060
|
+
return envService.read();
|
|
1038
1061
|
};
|
|
1039
1062
|
var extractDefaultFromDescription = (description) => {
|
|
1040
1063
|
const patterns = [
|
|
@@ -1057,40 +1080,158 @@ var extractDefaultFromDescription = (description) => {
|
|
|
1057
1080
|
};
|
|
1058
1081
|
var promptForEnvVar = async (varName, config2) => {
|
|
1059
1082
|
const {
|
|
1083
|
+
type = "string",
|
|
1060
1084
|
description = "No description available",
|
|
1061
1085
|
default: explicitDefault,
|
|
1062
|
-
sensitive = false
|
|
1086
|
+
sensitive = false,
|
|
1087
|
+
required = true
|
|
1088
|
+
// Default to true for backwards compatibility
|
|
1063
1089
|
} = config2;
|
|
1064
1090
|
const defaultValue = explicitDefault || extractDefaultFromDescription(description);
|
|
1065
1091
|
const isSecret = sensitive !== void 0 ? sensitive : varName.toLowerCase().includes("key") || varName.toLowerCase().includes("token") || varName.toLowerCase().includes("secret") || varName.toLowerCase().includes("password");
|
|
1066
|
-
const message = defaultValue ? `Enter ${varName} (default: ${defaultValue})` : `Enter ${varName}`;
|
|
1067
|
-
const placeholder = isSecret ? "Your secret key/token..." : defaultValue || "Enter value...";
|
|
1068
1092
|
if (description && description !== "No description available") {
|
|
1069
1093
|
clack4.note(`${description}`, `${varName} Info`);
|
|
1070
1094
|
}
|
|
1095
|
+
if (type === "boolean") {
|
|
1096
|
+
const defaultBool = defaultValue === "true" || String(explicitDefault).toLowerCase() === "true";
|
|
1097
|
+
const response2 = await clack4.confirm({
|
|
1098
|
+
message: required ? `Enable ${varName}?` : `Enable ${varName}? (optional)`,
|
|
1099
|
+
initialValue: defaultBool
|
|
1100
|
+
});
|
|
1101
|
+
if (clack4.isCancel(response2)) {
|
|
1102
|
+
clack4.cancel("Operation cancelled.");
|
|
1103
|
+
process.exit(0);
|
|
1104
|
+
}
|
|
1105
|
+
if (!required && response2 === void 0) {
|
|
1106
|
+
return "";
|
|
1107
|
+
}
|
|
1108
|
+
return String(response2);
|
|
1109
|
+
}
|
|
1110
|
+
if (type === "number") {
|
|
1111
|
+
const message2 = defaultValue ? `Enter ${varName} (default: ${String(defaultValue)})` : required ? `Enter ${varName}` : `Enter ${varName} (press Enter to skip)`;
|
|
1112
|
+
const promptConfig2 = {
|
|
1113
|
+
message: message2,
|
|
1114
|
+
placeholder: required ? String(defaultValue || "Enter a number") : String(defaultValue || "Press Enter to skip"),
|
|
1115
|
+
initialValue: defaultValue ? String(defaultValue) : void 0,
|
|
1116
|
+
validate: (input) => {
|
|
1117
|
+
if ((!input || input.trim() === "") && !required) {
|
|
1118
|
+
return void 0;
|
|
1119
|
+
}
|
|
1120
|
+
if ((!input || input.trim() === "") && required && !defaultValue) {
|
|
1121
|
+
return "This field cannot be empty. Press Ctrl+C to cancel.";
|
|
1122
|
+
}
|
|
1123
|
+
const trimmed = input.trim();
|
|
1124
|
+
if (trimmed && isNaN(Number(trimmed))) {
|
|
1125
|
+
return "Please enter a valid number";
|
|
1126
|
+
}
|
|
1127
|
+
return void 0;
|
|
1128
|
+
}
|
|
1129
|
+
};
|
|
1130
|
+
const response2 = await clack4.text(promptConfig2);
|
|
1131
|
+
if (clack4.isCancel(response2)) {
|
|
1132
|
+
clack4.cancel("Operation cancelled.");
|
|
1133
|
+
process.exit(0);
|
|
1134
|
+
}
|
|
1135
|
+
const finalValue2 = response2 && response2.trim() || defaultValue || "";
|
|
1136
|
+
return finalValue2.trim();
|
|
1137
|
+
}
|
|
1138
|
+
if (type === "array") {
|
|
1139
|
+
const message2 = defaultValue ? `Enter ${varName} (comma-separated, default: ${String(defaultValue)})` : required ? `Enter ${varName} (comma-separated values)` : `Enter ${varName} (comma-separated values, press Enter to skip)`;
|
|
1140
|
+
const promptConfig2 = {
|
|
1141
|
+
message: message2,
|
|
1142
|
+
placeholder: required ? String(defaultValue || "value1,value2,value3") : String(defaultValue || "Press Enter to skip"),
|
|
1143
|
+
initialValue: defaultValue ? String(defaultValue) : void 0,
|
|
1144
|
+
validate: (input) => {
|
|
1145
|
+
if ((!input || input.trim() === "") && !required) {
|
|
1146
|
+
return void 0;
|
|
1147
|
+
}
|
|
1148
|
+
if ((!input || input.trim() === "") && required && !defaultValue) {
|
|
1149
|
+
return "This field cannot be empty. Press Ctrl+C to cancel.";
|
|
1150
|
+
}
|
|
1151
|
+
return void 0;
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
const response2 = await clack4.text(promptConfig2);
|
|
1155
|
+
if (clack4.isCancel(response2)) {
|
|
1156
|
+
clack4.cancel("Operation cancelled.");
|
|
1157
|
+
process.exit(0);
|
|
1158
|
+
}
|
|
1159
|
+
const finalValue2 = response2 && response2.trim() || defaultValue || "";
|
|
1160
|
+
if (finalValue2) {
|
|
1161
|
+
return finalValue2.split(",").map((v) => v.trim()).filter((v) => v).join(",");
|
|
1162
|
+
}
|
|
1163
|
+
return finalValue2;
|
|
1164
|
+
}
|
|
1165
|
+
if (type === "json") {
|
|
1166
|
+
clack4.log.info("Enter a JSON object. For multi-line input, use the editor.");
|
|
1167
|
+
const message2 = defaultValue ? `Enter ${varName} JSON (default: ${String(defaultValue)})` : required ? `Enter ${varName} JSON` : `Enter ${varName} JSON (press Enter to skip)`;
|
|
1168
|
+
const promptConfig2 = {
|
|
1169
|
+
message: message2,
|
|
1170
|
+
placeholder: required ? String(defaultValue || '{"key": "value"}') : String(defaultValue || "Press Enter to skip"),
|
|
1171
|
+
initialValue: defaultValue ? String(defaultValue) : void 0,
|
|
1172
|
+
validate: (input) => {
|
|
1173
|
+
if ((!input || input.trim() === "") && !required) {
|
|
1174
|
+
return void 0;
|
|
1175
|
+
}
|
|
1176
|
+
if ((!input || input.trim() === "") && required && !defaultValue) {
|
|
1177
|
+
return "This field cannot be empty. Press Ctrl+C to cancel.";
|
|
1178
|
+
}
|
|
1179
|
+
if (input && input.trim()) {
|
|
1180
|
+
try {
|
|
1181
|
+
JSON.parse(input.trim());
|
|
1182
|
+
} catch (error) {
|
|
1183
|
+
return "Please enter valid JSON format";
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
return void 0;
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
const response2 = await clack4.text(promptConfig2);
|
|
1190
|
+
if (clack4.isCancel(response2)) {
|
|
1191
|
+
clack4.cancel("Operation cancelled.");
|
|
1192
|
+
process.exit(0);
|
|
1193
|
+
}
|
|
1194
|
+
const finalValue2 = response2 && response2.trim() || defaultValue || "";
|
|
1195
|
+
if (finalValue2) {
|
|
1196
|
+
try {
|
|
1197
|
+
const parsed = JSON.parse(finalValue2);
|
|
1198
|
+
return JSON.stringify(parsed);
|
|
1199
|
+
} catch {
|
|
1200
|
+
return finalValue2;
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
return finalValue2;
|
|
1204
|
+
}
|
|
1205
|
+
const message = defaultValue ? `Enter ${varName} (default: ${String(defaultValue)})` : required ? `Enter ${varName}` : `Enter ${varName} (press Enter to skip)`;
|
|
1206
|
+
const placeholder = isSecret ? "Your secret key/token..." : required ? String(defaultValue || "Required value") : String(defaultValue || "Press Enter to skip");
|
|
1071
1207
|
const promptFn = isSecret ? clack4.password : clack4.text;
|
|
1072
1208
|
const promptConfig = {
|
|
1073
1209
|
message,
|
|
1074
1210
|
placeholder,
|
|
1075
1211
|
validate: (input) => {
|
|
1076
|
-
if ((!input || input.trim() === "") && !defaultValue) {
|
|
1212
|
+
if ((!input || input.trim() === "") && required && !defaultValue) {
|
|
1077
1213
|
return "This field cannot be empty. Press Ctrl+C to cancel.";
|
|
1078
1214
|
}
|
|
1215
|
+
if ((!input || input.trim() === "") && !required) {
|
|
1216
|
+
return void 0;
|
|
1217
|
+
}
|
|
1079
1218
|
if (varName.includes("URL") || varName.includes("ENDPOINT")) {
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1219
|
+
if (input && input.trim()) {
|
|
1220
|
+
try {
|
|
1221
|
+
new URL(input.trim());
|
|
1222
|
+
} catch {
|
|
1223
|
+
return "Please enter a valid URL (e.g., https://api.example.com)";
|
|
1224
|
+
}
|
|
1084
1225
|
}
|
|
1085
1226
|
}
|
|
1086
|
-
if (varName.includes("API_KEY") && input.trim().length < 5) {
|
|
1227
|
+
if (varName.includes("API_KEY") && input.trim().length > 0 && input.trim().length < 5) {
|
|
1087
1228
|
return "API key seems too short. Please verify you entered the complete key.";
|
|
1088
1229
|
}
|
|
1089
1230
|
return void 0;
|
|
1090
1231
|
}
|
|
1091
1232
|
};
|
|
1092
1233
|
if (defaultValue && !isSecret) {
|
|
1093
|
-
promptConfig.initialValue = defaultValue;
|
|
1234
|
+
promptConfig.initialValue = String(defaultValue);
|
|
1094
1235
|
}
|
|
1095
1236
|
const response = await promptFn(promptConfig);
|
|
1096
1237
|
if (clack4.isCancel(response)) {
|
|
@@ -1100,37 +1241,54 @@ var promptForEnvVar = async (varName, config2) => {
|
|
|
1100
1241
|
const finalValue = response && response.trim() || defaultValue || "";
|
|
1101
1242
|
return finalValue.trim();
|
|
1102
1243
|
};
|
|
1103
|
-
var updateEnvFile = (cwd, varName, value) => {
|
|
1104
|
-
const
|
|
1105
|
-
const
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
}
|
|
1110
|
-
if (envContent && !envContent.endsWith("\n")) {
|
|
1111
|
-
lines.push("");
|
|
1112
|
-
}
|
|
1113
|
-
lines.push(`${varName}=${value}`);
|
|
1114
|
-
}
|
|
1115
|
-
writeEnvFile2(cwd, lines.join("\n"));
|
|
1244
|
+
var updateEnvFile = async (cwd, varName, value) => {
|
|
1245
|
+
const envPath = path7.join(cwd, ".env");
|
|
1246
|
+
const envService = createEnvFileService(envPath);
|
|
1247
|
+
await envService.update(varName, value, {
|
|
1248
|
+
preserveComments: true,
|
|
1249
|
+
updateProcessEnv: true
|
|
1250
|
+
});
|
|
1116
1251
|
};
|
|
1117
1252
|
var promptForPluginEnvVars = async (packageName, cwd) => {
|
|
1118
|
-
|
|
1253
|
+
let envRequirements = await extractPluginEnvRequirements(packageName, cwd);
|
|
1254
|
+
if (Object.keys(envRequirements).length === 0 && !packageName.startsWith("@elizaos/")) {
|
|
1255
|
+
const elizaosPackageName = `@elizaos/${packageName.replace("plugin-", "")}`;
|
|
1256
|
+
envRequirements = await extractPluginEnvRequirements(elizaosPackageName, cwd);
|
|
1257
|
+
if (Object.keys(envRequirements).length === 0) {
|
|
1258
|
+
const elizaosPluginPackageName = `@elizaos/plugin-${packageName.replace("plugin-", "")}`;
|
|
1259
|
+
envRequirements = await extractPluginEnvRequirements(elizaosPluginPackageName, cwd);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1119
1262
|
if (Object.keys(envRequirements).length === 0) {
|
|
1120
|
-
|
|
1121
|
-
|
|
1263
|
+
const nodeModulesPath = path7.join(cwd, "node_modules");
|
|
1264
|
+
const possiblePackages = [
|
|
1265
|
+
packageName,
|
|
1266
|
+
`@elizaos/${packageName.replace("plugin-", "")}`,
|
|
1267
|
+
`@elizaos/plugin-${packageName.replace("plugin-", "")}`
|
|
1268
|
+
];
|
|
1269
|
+
let packageFound = false;
|
|
1270
|
+
for (const pkg of possiblePackages) {
|
|
1271
|
+
const pkgPath = path7.join(nodeModulesPath, ...pkg.split("/"));
|
|
1272
|
+
if (existsSync8(path7.join(pkgPath, "package.json"))) {
|
|
1273
|
+
packageFound = true;
|
|
1274
|
+
break;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
if (packageFound) {
|
|
1278
|
+
logger.debug(`Package ${packageName} found but has no environment variables defined`);
|
|
1279
|
+
clack4.log.success(`No environment variables required for ${packageName}`);
|
|
1280
|
+
} else {
|
|
1281
|
+
logger.debug(`Package ${packageName} not found in node_modules`);
|
|
1282
|
+
clack4.log.warn(
|
|
1283
|
+
`Could not find ${packageName} in node_modules. Environment variables may need to be configured manually.`
|
|
1284
|
+
);
|
|
1285
|
+
}
|
|
1122
1286
|
return;
|
|
1123
1287
|
}
|
|
1124
1288
|
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
1125
1289
|
clack4.intro(`Setting up ${packageName} Plugin`);
|
|
1126
|
-
const
|
|
1127
|
-
const existingVars =
|
|
1128
|
-
envContent.split("\n").forEach((line) => {
|
|
1129
|
-
const match = line.match(/^([^=]+)=(.*)$/);
|
|
1130
|
-
if (match) {
|
|
1131
|
-
existingVars[match[1]] = match[2];
|
|
1132
|
-
}
|
|
1133
|
-
});
|
|
1290
|
+
const envVars = await readEnvFile(cwd);
|
|
1291
|
+
const existingVars = envVars;
|
|
1134
1292
|
const missingVars = [];
|
|
1135
1293
|
const existingConfigured = [];
|
|
1136
1294
|
Object.entries(envRequirements).forEach(([varName, config2]) => {
|
|
@@ -1183,7 +1341,7 @@ ${optionalVars.map(([name]) => ` - ${name}`).join("\n")}
|
|
|
1183
1341
|
const value = await promptForEnvVar(varName, config2);
|
|
1184
1342
|
if (value) {
|
|
1185
1343
|
spinner2.start(`Saving ${varName} to .env file...`);
|
|
1186
|
-
updateEnvFile(cwd, varName, value);
|
|
1344
|
+
await updateEnvFile(cwd, varName, value);
|
|
1187
1345
|
spinner2.stop(`${varName} configured successfully`);
|
|
1188
1346
|
newlyConfigured++;
|
|
1189
1347
|
configuredCount++;
|
|
@@ -1302,7 +1460,7 @@ async function installPluginFromGitHub(plugin, cwd, opts) {
|
|
|
1302
1460
|
if (success) {
|
|
1303
1461
|
logger3.info(`Successfully installed ${pluginNameForPostInstall} from ${githubSpecifier}.`);
|
|
1304
1462
|
if (!opts.skipEnvPrompt) {
|
|
1305
|
-
await new Promise((resolve2) => setTimeout(resolve2,
|
|
1463
|
+
await new Promise((resolve2) => setTimeout(resolve2, 500));
|
|
1306
1464
|
const packageName = extractPackageName(plugin);
|
|
1307
1465
|
console.log(`
|
|
1308
1466
|
\u{1F527} Checking environment variables for ${packageName}...`);
|
|
@@ -1341,7 +1499,7 @@ async function installPluginFromRegistry(plugin, cwd, opts) {
|
|
|
1341
1499
|
if (registryInstallResult) {
|
|
1342
1500
|
console.log(`Successfully installed ${targetName}`);
|
|
1343
1501
|
if (!opts.skipEnvPrompt) {
|
|
1344
|
-
await new Promise((resolve2) => setTimeout(resolve2,
|
|
1502
|
+
await new Promise((resolve2) => setTimeout(resolve2, 500));
|
|
1345
1503
|
const updatedDependencies = getDependenciesFromDirectory(cwd);
|
|
1346
1504
|
const actualPackageName = findPluginPackageName(targetName, updatedDependencies || {}) || targetName;
|
|
1347
1505
|
console.log(`
|
|
@@ -1566,78 +1724,996 @@ async function listInstalledPlugins() {
|
|
|
1566
1724
|
}
|
|
1567
1725
|
|
|
1568
1726
|
// src/commands/plugins/actions/upgrade.ts
|
|
1569
|
-
import { logger as
|
|
1727
|
+
import { logger as logger8 } from "@elizaos/core";
|
|
1728
|
+
import path11 from "path";
|
|
1729
|
+
import { existsSync as existsSync11 } from "fs";
|
|
1730
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1731
|
+
import fs from "fs-extra";
|
|
1732
|
+
|
|
1733
|
+
// src/utils/upgrade/simple-migration-agent.ts
|
|
1734
|
+
import { query } from "@anthropic-ai/claude-code";
|
|
1735
|
+
import { EventEmitter } from "events";
|
|
1736
|
+
|
|
1737
|
+
// src/utils/upgrade/migration-guide-loader.ts
|
|
1738
|
+
import { existsSync as existsSync10, readFileSync as readFileSync3 } from "fs";
|
|
1570
1739
|
import path10 from "path";
|
|
1740
|
+
import { fileURLToPath } from "url";
|
|
1741
|
+
import { logger as logger6 } from "@elizaos/core";
|
|
1742
|
+
var MigrationGuideLoader = class {
|
|
1743
|
+
guides = [];
|
|
1744
|
+
guidesDir;
|
|
1745
|
+
constructor(projectRoot) {
|
|
1746
|
+
this.guidesDir = this.findGuidesDirectory(projectRoot);
|
|
1747
|
+
this.loadGuides();
|
|
1748
|
+
}
|
|
1749
|
+
findGuidesDirectory(projectRoot) {
|
|
1750
|
+
if (projectRoot) {
|
|
1751
|
+
const guidesPath = path10.join(projectRoot, "packages/docs/docs/plugins/migration/claude-code");
|
|
1752
|
+
if (existsSync10(guidesPath)) {
|
|
1753
|
+
return guidesPath;
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
let currentRoot = process.cwd();
|
|
1757
|
+
let previousRoot = "";
|
|
1758
|
+
while (currentRoot !== previousRoot && !existsSync10(path10.join(currentRoot, "packages/docs"))) {
|
|
1759
|
+
previousRoot = currentRoot;
|
|
1760
|
+
currentRoot = path10.dirname(currentRoot);
|
|
1761
|
+
}
|
|
1762
|
+
const monorepoGuidesPath = path10.join(
|
|
1763
|
+
currentRoot,
|
|
1764
|
+
"packages/docs/docs/plugins/migration/claude-code"
|
|
1765
|
+
);
|
|
1766
|
+
if (existsSync10(monorepoGuidesPath)) {
|
|
1767
|
+
return monorepoGuidesPath;
|
|
1768
|
+
}
|
|
1769
|
+
const workingDirGuides = path10.join(process.cwd(), "migration-guides");
|
|
1770
|
+
if (existsSync10(workingDirGuides)) {
|
|
1771
|
+
return workingDirGuides;
|
|
1772
|
+
}
|
|
1773
|
+
const currentFileUrl = import.meta.url;
|
|
1774
|
+
const currentFilePath = fileURLToPath(currentFileUrl);
|
|
1775
|
+
const cliPackageRoot = path10.dirname(path10.dirname(path10.dirname(path10.dirname(currentFilePath))));
|
|
1776
|
+
const bundledGuidesPath = path10.join(cliPackageRoot, "migration-guides");
|
|
1777
|
+
if (existsSync10(bundledGuidesPath)) {
|
|
1778
|
+
return bundledGuidesPath;
|
|
1779
|
+
}
|
|
1780
|
+
return "";
|
|
1781
|
+
}
|
|
1782
|
+
loadGuides() {
|
|
1783
|
+
const guideConfigs = [
|
|
1784
|
+
{
|
|
1785
|
+
name: "migration-guide.md",
|
|
1786
|
+
category: "basic",
|
|
1787
|
+
keywords: [
|
|
1788
|
+
"import",
|
|
1789
|
+
"path",
|
|
1790
|
+
"action",
|
|
1791
|
+
"provider",
|
|
1792
|
+
"basic",
|
|
1793
|
+
"core",
|
|
1794
|
+
"elizaLogger",
|
|
1795
|
+
"logger",
|
|
1796
|
+
"IAgentRuntime",
|
|
1797
|
+
"AgentRuntime",
|
|
1798
|
+
"Account",
|
|
1799
|
+
"Entity",
|
|
1800
|
+
"composeContext",
|
|
1801
|
+
"generateObject",
|
|
1802
|
+
"package.json",
|
|
1803
|
+
"dependencies",
|
|
1804
|
+
"scripts",
|
|
1805
|
+
"build"
|
|
1806
|
+
]
|
|
1807
|
+
},
|
|
1808
|
+
{
|
|
1809
|
+
name: "state-and-providers-guide.md",
|
|
1810
|
+
category: "basic",
|
|
1811
|
+
keywords: [
|
|
1812
|
+
"state",
|
|
1813
|
+
"provider",
|
|
1814
|
+
"ProviderResult",
|
|
1815
|
+
"context",
|
|
1816
|
+
"memory",
|
|
1817
|
+
"runtime",
|
|
1818
|
+
"world",
|
|
1819
|
+
"room",
|
|
1820
|
+
"entityId",
|
|
1821
|
+
"userId",
|
|
1822
|
+
"optional"
|
|
1823
|
+
]
|
|
1824
|
+
},
|
|
1825
|
+
{
|
|
1826
|
+
name: "prompt-and-generation-guide.md",
|
|
1827
|
+
category: "basic",
|
|
1828
|
+
keywords: [
|
|
1829
|
+
"template",
|
|
1830
|
+
"prompt",
|
|
1831
|
+
"generation",
|
|
1832
|
+
"XML",
|
|
1833
|
+
"JSON",
|
|
1834
|
+
"useModel",
|
|
1835
|
+
"generateText",
|
|
1836
|
+
"messages",
|
|
1837
|
+
"format"
|
|
1838
|
+
]
|
|
1839
|
+
},
|
|
1840
|
+
{
|
|
1841
|
+
name: "advanced-migration-guide.md",
|
|
1842
|
+
category: "advanced",
|
|
1843
|
+
keywords: [
|
|
1844
|
+
"service",
|
|
1845
|
+
"evaluator",
|
|
1846
|
+
"settings",
|
|
1847
|
+
"singleton",
|
|
1848
|
+
"lifecycle",
|
|
1849
|
+
"initialize",
|
|
1850
|
+
"start",
|
|
1851
|
+
"stop",
|
|
1852
|
+
"client",
|
|
1853
|
+
"complex"
|
|
1854
|
+
]
|
|
1855
|
+
},
|
|
1856
|
+
{
|
|
1857
|
+
name: "testing-guide.md",
|
|
1858
|
+
category: "testing",
|
|
1859
|
+
keywords: [
|
|
1860
|
+
"test",
|
|
1861
|
+
"coverage",
|
|
1862
|
+
"vitest",
|
|
1863
|
+
"bun",
|
|
1864
|
+
"mock",
|
|
1865
|
+
"unit",
|
|
1866
|
+
"integration",
|
|
1867
|
+
"error",
|
|
1868
|
+
"edge",
|
|
1869
|
+
"performance",
|
|
1870
|
+
"test-utils"
|
|
1871
|
+
]
|
|
1872
|
+
},
|
|
1873
|
+
{
|
|
1874
|
+
name: "completion-requirements.md",
|
|
1875
|
+
category: "completion",
|
|
1876
|
+
keywords: [
|
|
1877
|
+
"release",
|
|
1878
|
+
"workflow",
|
|
1879
|
+
"npm",
|
|
1880
|
+
"deploy",
|
|
1881
|
+
"gitignore",
|
|
1882
|
+
"npmignore",
|
|
1883
|
+
"license",
|
|
1884
|
+
"prettier",
|
|
1885
|
+
"final",
|
|
1886
|
+
"validation"
|
|
1887
|
+
]
|
|
1888
|
+
}
|
|
1889
|
+
];
|
|
1890
|
+
if (!this.guidesDir || !existsSync10(this.guidesDir)) {
|
|
1891
|
+
logger6.info("Using embedded migration guidance (external CLI mode)");
|
|
1892
|
+
this.createEmbeddedGuides(guideConfigs);
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
for (const config2 of guideConfigs) {
|
|
1896
|
+
const guidePath = path10.join(this.guidesDir, config2.name);
|
|
1897
|
+
if (existsSync10(guidePath)) {
|
|
1898
|
+
try {
|
|
1899
|
+
const content = readFileSync3(guidePath, "utf-8");
|
|
1900
|
+
this.guides.push({
|
|
1901
|
+
name: config2.name,
|
|
1902
|
+
path: guidePath,
|
|
1903
|
+
content,
|
|
1904
|
+
category: config2.category,
|
|
1905
|
+
keywords: config2.keywords
|
|
1906
|
+
});
|
|
1907
|
+
} catch (error) {
|
|
1908
|
+
logger6.warn(`Failed to load migration guide: ${config2.name}`, error);
|
|
1909
|
+
}
|
|
1910
|
+
} else {
|
|
1911
|
+
logger6.warn(`Migration guide not found: ${guidePath}`);
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
logger6.info(`Loaded ${this.guides.length} migration guides from ${this.guidesDir}`);
|
|
1915
|
+
}
|
|
1916
|
+
createEmbeddedGuides(guideConfigs) {
|
|
1917
|
+
const embeddedGuides = {
|
|
1918
|
+
"migration-guide.md": this.getEmbeddedMigrationGuide(),
|
|
1919
|
+
"testing-guide.md": this.getEmbeddedTestingGuide(),
|
|
1920
|
+
"completion-requirements.md": this.getEmbeddedCompletionGuide()
|
|
1921
|
+
};
|
|
1922
|
+
for (const config2 of guideConfigs) {
|
|
1923
|
+
const embeddedContent = embeddedGuides[config2.name];
|
|
1924
|
+
if (embeddedContent) {
|
|
1925
|
+
this.guides.push({
|
|
1926
|
+
name: config2.name,
|
|
1927
|
+
path: `embedded:${config2.name}`,
|
|
1928
|
+
content: embeddedContent,
|
|
1929
|
+
category: config2.category,
|
|
1930
|
+
keywords: config2.keywords
|
|
1931
|
+
});
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
getEmbeddedMigrationGuide() {
|
|
1936
|
+
return `# ElizaOS Plugin Migration Guide - Essential Steps
|
|
1937
|
+
|
|
1938
|
+
## Core Migration Requirements
|
|
1939
|
+
|
|
1940
|
+
### 1. Import Path Updates
|
|
1941
|
+
- elizaLogger \u2192 logger
|
|
1942
|
+
- IAgentRuntime \u2192 AgentRuntime
|
|
1943
|
+
- Account \u2192 Entity
|
|
1944
|
+
- userId \u2192 entityId
|
|
1945
|
+
|
|
1946
|
+
### 2. Package.json Updates
|
|
1947
|
+
- Update to @elizaos/core ^1.0.0
|
|
1948
|
+
- Update scripts to use bun
|
|
1949
|
+
- Add proper exports and types
|
|
1950
|
+
|
|
1951
|
+
### 3. Action Migration
|
|
1952
|
+
- Replace composeContext with new patterns
|
|
1953
|
+
- Convert JSON templates to XML
|
|
1954
|
+
- Update generateObject to runtime.useModel
|
|
1955
|
+
- Fix handler patterns
|
|
1956
|
+
|
|
1957
|
+
### 4. Provider Migration
|
|
1958
|
+
- Add name property
|
|
1959
|
+
- Return ProviderResult
|
|
1960
|
+
- Make state parameter required
|
|
1961
|
+
|
|
1962
|
+
### 5. Testing Requirements
|
|
1963
|
+
- Use bun test framework
|
|
1964
|
+
- Achieve 95%+ coverage
|
|
1965
|
+
- Test all components thoroughly
|
|
1966
|
+
|
|
1967
|
+
For complete details, refer to the comprehensive guides in the ElizaOS documentation.`;
|
|
1968
|
+
}
|
|
1969
|
+
getEmbeddedTestingGuide() {
|
|
1970
|
+
return `# ElizaOS Testing Guide - Essential Requirements
|
|
1971
|
+
|
|
1972
|
+
## Test Framework
|
|
1973
|
+
- Use bun test (not vitest)
|
|
1974
|
+
- Achieve 95%+ code coverage
|
|
1975
|
+
- Test all actions, providers, evaluators
|
|
1976
|
+
|
|
1977
|
+
## Test Structure
|
|
1978
|
+
\`\`\`
|
|
1979
|
+
src/__tests__/
|
|
1980
|
+
\u251C\u2500\u2500 test-utils.ts
|
|
1981
|
+
\u251C\u2500\u2500 actions/
|
|
1982
|
+
\u251C\u2500\u2500 providers/
|
|
1983
|
+
\u2514\u2500\u2500 evaluators/
|
|
1984
|
+
\`\`\`
|
|
1985
|
+
|
|
1986
|
+
## Coverage Requirements
|
|
1987
|
+
- All components must be tested
|
|
1988
|
+
- Error cases must be covered
|
|
1989
|
+
- Edge cases must be handled
|
|
1990
|
+
- Integration tests required
|
|
1991
|
+
|
|
1992
|
+
## Common Issues
|
|
1993
|
+
- Mock all async dependencies
|
|
1994
|
+
- Clean up after each test
|
|
1995
|
+
- Use proper test isolation
|
|
1996
|
+
|
|
1997
|
+
Run: bun test --coverage`;
|
|
1998
|
+
}
|
|
1999
|
+
getEmbeddedCompletionGuide() {
|
|
2000
|
+
return `# ElizaOS Completion Requirements
|
|
2001
|
+
|
|
2002
|
+
## Required Files
|
|
2003
|
+
- .gitignore
|
|
2004
|
+
- .npmignore
|
|
2005
|
+
- LICENSE
|
|
2006
|
+
- .prettierrc
|
|
2007
|
+
- .github/workflows/npm-deploy.yml
|
|
2008
|
+
|
|
2009
|
+
## Final Validation
|
|
2010
|
+
\`\`\`bash
|
|
2011
|
+
bun run build # Must pass
|
|
2012
|
+
bun test # Must pass
|
|
2013
|
+
bunx tsc --noEmit # Must pass
|
|
2014
|
+
\`\`\`
|
|
2015
|
+
|
|
2016
|
+
## Package.json Requirements
|
|
2017
|
+
- Correct name format
|
|
2018
|
+
- Version 1.0.0
|
|
2019
|
+
- Proper exports
|
|
2020
|
+
- Build scripts
|
|
2021
|
+
- Test scripts
|
|
2022
|
+
|
|
2023
|
+
## Release Workflow
|
|
2024
|
+
- GitHub workflow for npm publish
|
|
2025
|
+
- Automated testing
|
|
2026
|
+
- Version management`;
|
|
2027
|
+
}
|
|
2028
|
+
/**
|
|
2029
|
+
* Search for relevant guides based on keywords or content
|
|
2030
|
+
*/
|
|
2031
|
+
searchGuides(query2, limit = 3) {
|
|
2032
|
+
const queryLower = query2.toLowerCase();
|
|
2033
|
+
const queryWords = queryLower.split(/\s+/).filter((word) => word.length > 2);
|
|
2034
|
+
const results = [];
|
|
2035
|
+
for (const guide of this.guides) {
|
|
2036
|
+
let relevanceScore = 0;
|
|
2037
|
+
const matchedKeywords = [];
|
|
2038
|
+
for (const keyword of guide.keywords) {
|
|
2039
|
+
if (queryWords.some((word) => keyword.toLowerCase().includes(word))) {
|
|
2040
|
+
relevanceScore += 2;
|
|
2041
|
+
matchedKeywords.push(keyword);
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
const contentLower = guide.content.toLowerCase();
|
|
2045
|
+
for (const word of queryWords) {
|
|
2046
|
+
const matches = (contentLower.match(new RegExp(word, "g")) || []).length;
|
|
2047
|
+
relevanceScore += matches * 0.5;
|
|
2048
|
+
}
|
|
2049
|
+
if (queryLower.includes("import") && guide.name === "migration-guide.md") {
|
|
2050
|
+
relevanceScore += 3;
|
|
2051
|
+
}
|
|
2052
|
+
if (queryLower.includes("test") && guide.name === "testing-guide.md") {
|
|
2053
|
+
relevanceScore += 3;
|
|
2054
|
+
}
|
|
2055
|
+
if (queryLower.includes("state") && guide.name === "state-and-providers-guide.md") {
|
|
2056
|
+
relevanceScore += 3;
|
|
2057
|
+
}
|
|
2058
|
+
if (relevanceScore > 0) {
|
|
2059
|
+
results.push({
|
|
2060
|
+
guide,
|
|
2061
|
+
relevanceScore,
|
|
2062
|
+
matchedKeywords
|
|
2063
|
+
});
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
return results.sort((a, b) => b.relevanceScore - a.relevanceScore).slice(0, limit);
|
|
2067
|
+
}
|
|
2068
|
+
/**
|
|
2069
|
+
* Get a specific guide by name
|
|
2070
|
+
*/
|
|
2071
|
+
getGuide(name) {
|
|
2072
|
+
return this.guides.find((guide) => guide.name === name) || null;
|
|
2073
|
+
}
|
|
2074
|
+
/**
|
|
2075
|
+
* Get all guides of a specific category
|
|
2076
|
+
*/
|
|
2077
|
+
getGuidesByCategory(category) {
|
|
2078
|
+
return this.guides.filter((guide) => guide.category === category);
|
|
2079
|
+
}
|
|
2080
|
+
/**
|
|
2081
|
+
* Get guides that are most relevant for common migration issues
|
|
2082
|
+
*/
|
|
2083
|
+
getRelevantGuidesForIssue(issue) {
|
|
2084
|
+
const issueMap = {
|
|
2085
|
+
import_error: ["import", "path", "elizaLogger", "logger"],
|
|
2086
|
+
build_error: ["build", "typescript", "package.json", "dependencies"],
|
|
2087
|
+
type_error: ["typescript", "type", "IAgentRuntime", "AgentRuntime"],
|
|
2088
|
+
action_migration: ["action", "composeContext", "generateObject", "handler"],
|
|
2089
|
+
provider_migration: ["provider", "ProviderResult", "state", "context"],
|
|
2090
|
+
test_failure: ["test", "coverage", "mock", "unit"],
|
|
2091
|
+
service_migration: ["service", "lifecycle", "initialize", "singleton"],
|
|
2092
|
+
template_migration: ["template", "XML", "JSON", "prompt"],
|
|
2093
|
+
release_setup: ["release", "workflow", "npm", "deploy"]
|
|
2094
|
+
};
|
|
2095
|
+
const keywords = issueMap[issue];
|
|
2096
|
+
if (!keywords) {
|
|
2097
|
+
return this.searchGuides(issue);
|
|
2098
|
+
}
|
|
2099
|
+
return this.searchGuides(keywords.join(" "));
|
|
2100
|
+
}
|
|
2101
|
+
/**
|
|
2102
|
+
* Generate a comprehensive migration context for Claude
|
|
2103
|
+
*/
|
|
2104
|
+
generateMigrationContext() {
|
|
2105
|
+
const context = [
|
|
2106
|
+
"# ELIZAOS PLUGIN MIGRATION GUIDE REFERENCES",
|
|
2107
|
+
"",
|
|
2108
|
+
"You have access to the following comprehensive migration guides:",
|
|
2109
|
+
""
|
|
2110
|
+
];
|
|
2111
|
+
for (const guide of this.guides) {
|
|
2112
|
+
context.push(`## ${guide.name.replace(".md", "").toUpperCase()}`);
|
|
2113
|
+
context.push(`Category: ${guide.category}`);
|
|
2114
|
+
context.push(`Keywords: ${guide.keywords.join(", ")}`);
|
|
2115
|
+
context.push("");
|
|
2116
|
+
const preview = guide.content.substring(0, 500).replace(/\n/g, " ");
|
|
2117
|
+
context.push(`Preview: ${preview}...`);
|
|
2118
|
+
context.push("");
|
|
2119
|
+
context.push("---");
|
|
2120
|
+
context.push("");
|
|
2121
|
+
}
|
|
2122
|
+
context.push("## GUIDE USAGE INSTRUCTIONS");
|
|
2123
|
+
context.push("");
|
|
2124
|
+
context.push("- Reference specific guides for detailed migration steps");
|
|
2125
|
+
context.push("- Use migration-guide.md for basic actions and providers");
|
|
2126
|
+
context.push("- Use advanced-migration-guide.md for services and evaluators");
|
|
2127
|
+
context.push("- Use testing-guide.md for comprehensive test coverage");
|
|
2128
|
+
context.push("- Use completion-requirements.md for final release preparation");
|
|
2129
|
+
context.push("");
|
|
2130
|
+
return context.join("\n");
|
|
2131
|
+
}
|
|
2132
|
+
/**
|
|
2133
|
+
* Get full content of all guides for RAG embedding
|
|
2134
|
+
*/
|
|
2135
|
+
getAllGuidesContent() {
|
|
2136
|
+
const content = [
|
|
2137
|
+
"# COMPLETE ELIZAOS MIGRATION KNOWLEDGE BASE",
|
|
2138
|
+
"",
|
|
2139
|
+
"This contains all migration guides and their complete content for reference.",
|
|
2140
|
+
""
|
|
2141
|
+
];
|
|
2142
|
+
for (const guide of this.guides) {
|
|
2143
|
+
content.push(`# GUIDE: ${guide.name}`);
|
|
2144
|
+
content.push(`Category: ${guide.category}`);
|
|
2145
|
+
content.push(`Keywords: ${guide.keywords.join(", ")}`);
|
|
2146
|
+
content.push("");
|
|
2147
|
+
content.push("## CONTENT:");
|
|
2148
|
+
content.push("");
|
|
2149
|
+
content.push(guide.content);
|
|
2150
|
+
content.push("");
|
|
2151
|
+
content.push("---");
|
|
2152
|
+
content.push("");
|
|
2153
|
+
}
|
|
2154
|
+
return content.join("\n");
|
|
2155
|
+
}
|
|
2156
|
+
};
|
|
2157
|
+
function createMigrationGuideLoader(projectRoot) {
|
|
2158
|
+
return new MigrationGuideLoader(projectRoot);
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
// src/utils/upgrade/simple-migration-agent.ts
|
|
2162
|
+
import { logger as logger7 } from "@elizaos/core";
|
|
2163
|
+
var SimpleMigrationAgent = class extends EventEmitter {
|
|
2164
|
+
repoPath;
|
|
2165
|
+
abortController;
|
|
2166
|
+
verbose;
|
|
2167
|
+
guideLoader;
|
|
2168
|
+
constructor(repoPath, options = {}) {
|
|
2169
|
+
super();
|
|
2170
|
+
this.repoPath = repoPath;
|
|
2171
|
+
this.abortController = new AbortController();
|
|
2172
|
+
this.verbose = options.verbose || false;
|
|
2173
|
+
try {
|
|
2174
|
+
this.guideLoader = createMigrationGuideLoader();
|
|
2175
|
+
if (this.verbose) {
|
|
2176
|
+
logger7.info("Migration guide loader initialized successfully");
|
|
2177
|
+
}
|
|
2178
|
+
} catch (error) {
|
|
2179
|
+
logger7.warn("Failed to initialize migration guide loader", error);
|
|
2180
|
+
throw new Error("Cannot initialize migration system without guide access");
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
isImportantUpdate(text3) {
|
|
2184
|
+
const importantPatterns = [
|
|
2185
|
+
/GATE \d+/i,
|
|
2186
|
+
/analysis/i,
|
|
2187
|
+
/migration/i,
|
|
2188
|
+
/complete/i,
|
|
2189
|
+
/success/i,
|
|
2190
|
+
/error/i,
|
|
2191
|
+
/building/i,
|
|
2192
|
+
/testing/i,
|
|
2193
|
+
/✓|✗|🎉|🚀|📊/
|
|
2194
|
+
];
|
|
2195
|
+
return importantPatterns.some((pattern) => pattern.test(text3)) && text3.length < 200;
|
|
2196
|
+
}
|
|
2197
|
+
formatProgressUpdate(text3) {
|
|
2198
|
+
text3 = text3.trim();
|
|
2199
|
+
if (text3.includes("GATE")) {
|
|
2200
|
+
return `
|
|
2201
|
+
\u{1F3AF} ${text3}`;
|
|
2202
|
+
} else if (text3.includes("complete") || text3.includes("\u2713")) {
|
|
2203
|
+
return `\u2705 ${text3}`;
|
|
2204
|
+
} else if (text3.includes("error") || text3.includes("\u2717")) {
|
|
2205
|
+
return `\u274C ${text3}`;
|
|
2206
|
+
} else if (text3.includes("analyzing") || text3.includes("migration")) {
|
|
2207
|
+
return `\u{1F50D} ${text3}`;
|
|
2208
|
+
} else if (text3.includes("building")) {
|
|
2209
|
+
return `\u{1F528} ${text3}`;
|
|
2210
|
+
} else if (text3.includes("testing")) {
|
|
2211
|
+
return `\u{1F9EA} ${text3}`;
|
|
2212
|
+
}
|
|
2213
|
+
return text3;
|
|
2214
|
+
}
|
|
2215
|
+
getSimplifiedToolName(toolName) {
|
|
2216
|
+
const toolMap = {
|
|
2217
|
+
TodoWrite: "\u{1F4DD} Planning",
|
|
2218
|
+
Bash: "\u26A1 Running",
|
|
2219
|
+
Read: "\u{1F4D6} Reading",
|
|
2220
|
+
Edit: "\u270F\uFE0F Editing",
|
|
2221
|
+
Write: "\u{1F4C4} Writing",
|
|
2222
|
+
LS: "\u{1F50D} Exploring",
|
|
2223
|
+
Grep: "\u{1F50E} Searching",
|
|
2224
|
+
Task: "\u{1F527} Processing"
|
|
2225
|
+
};
|
|
2226
|
+
return toolMap[toolName] || null;
|
|
2227
|
+
}
|
|
2228
|
+
async migrate() {
|
|
2229
|
+
const startTime = Date.now();
|
|
2230
|
+
let messageCount = 0;
|
|
2231
|
+
try {
|
|
2232
|
+
process.env.CLAUDE_CODE_ENABLE_TELEMETRY = "0";
|
|
2233
|
+
process.env.OTEL_LOGS_EXPORTER = "";
|
|
2234
|
+
process.env.OTEL_LOG_USER_PROMPTS = "0";
|
|
2235
|
+
process.env.OTEL_METRICS_EXPORTER = "";
|
|
2236
|
+
console.log("Claude is analyzing and migrating your plugin...\n");
|
|
2237
|
+
this.emit("start");
|
|
2238
|
+
console.log(`Starting migration in directory: ${this.repoPath}`);
|
|
2239
|
+
const migrationContext = this.guideLoader.getAllGuidesContent();
|
|
2240
|
+
const guideReferences = this.guideLoader.generateMigrationContext();
|
|
2241
|
+
const migrationPrompt = `You are about to help migrate an ElizaOS plugin from 0.x to 1.x format.
|
|
2242
|
+
|
|
2243
|
+
CRITICAL: You must follow the INTEGRATED EXECUTION PROTOCOL exactly as specified in the CLAUDE.md file.
|
|
2244
|
+
|
|
2245
|
+
This is a GATED PROCESS with 9 gates (0-8). You CANNOT skip steps.
|
|
2246
|
+
|
|
2247
|
+
COMPREHENSIVE MIGRATION KNOWLEDGE BASE:
|
|
2248
|
+
${migrationContext}
|
|
2249
|
+
|
|
2250
|
+
GUIDE REFERENCE SYSTEM:
|
|
2251
|
+
${guideReferences}
|
|
2252
|
+
|
|
2253
|
+
REFERENCE GUIDES are in migration-guides/ directory:
|
|
2254
|
+
- migration-guide.md (basic migration steps)
|
|
2255
|
+
- state-and-providers-guide.md (state & providers migration)
|
|
2256
|
+
- prompt-and-generation-guide.md (templates & generation)
|
|
2257
|
+
- advanced-migration-guide.md (services, settings, evaluators)
|
|
2258
|
+
- testing-guide.md (comprehensive testing requirements)
|
|
2259
|
+
- completion-requirements.md (final validation and release preparation)
|
|
2260
|
+
|
|
2261
|
+
ENHANCED RAG CAPABILITIES:
|
|
2262
|
+
You have access to the complete content of all migration guides above. Use this knowledge to:
|
|
2263
|
+
1. Provide specific, detailed migration steps
|
|
2264
|
+
2. Reference exact sections from the appropriate guides
|
|
2265
|
+
3. Troubleshoot specific issues with targeted solutions
|
|
2266
|
+
4. Ensure comprehensive coverage of all migration requirements
|
|
2267
|
+
|
|
2268
|
+
CRITICAL TEST VALIDATION REQUIREMENTS - ABSOLUTE REQUIREMENTS
|
|
2269
|
+
|
|
2270
|
+
MIGRATION CANNOT BE COMPLETED UNTIL ALL TESTS PASS
|
|
2271
|
+
|
|
2272
|
+
Throughout the migration process, you MUST validate these requirements and loop until they pass:
|
|
2273
|
+
|
|
2274
|
+
1. MANDATORY TEST VALIDATION LOOP: After every significant code change, run:
|
|
2275
|
+
- bun run test - ALL tests must pass (100% success rate, ZERO failures)
|
|
2276
|
+
- bunx tsc --noEmit - ZERO TypeScript errors in src/ directory
|
|
2277
|
+
- Only test files can have type errors, src/ must be error-free
|
|
2278
|
+
|
|
2279
|
+
2. CONTINUOUS VALIDATION LOOP: If ANY of these fail:
|
|
2280
|
+
- Analyze the errors thoroughly
|
|
2281
|
+
- Fix all issues identified
|
|
2282
|
+
- Re-run the validation commands
|
|
2283
|
+
- Repeat until BOTH commands succeed with zero errors
|
|
2284
|
+
- DO NOT PROCEED until validation passes
|
|
2285
|
+
|
|
2286
|
+
3. COVERAGE VS TEST CONFLICTS: If tests conflict with 95% coverage requirements:
|
|
2287
|
+
- Prioritize making tests pass over coverage percentage
|
|
2288
|
+
- Use workarounds like test mocks, stubs, or simplified implementations
|
|
2289
|
+
- Lower coverage if necessary - tests passing is more important
|
|
2290
|
+
- Add // @ts-ignore comments if needed for test compatibility
|
|
2291
|
+
|
|
2292
|
+
4. RELEASE WORKFLOW REQUIREMENT: The .github/workflows/release.yml requires bun run test to pass before npm publish. Migration is NOT complete until all tests pass.
|
|
2293
|
+
|
|
2294
|
+
5. ABSOLUTE REQUIREMENTS - NO EXCEPTIONS:
|
|
2295
|
+
- bun run test MUST show 0 failing tests
|
|
2296
|
+
- If ANY test fails, the migration is INCOMPLETE
|
|
2297
|
+
- Do not declare success until bun run test passes completely
|
|
2298
|
+
- Work around any test issues rather than leaving them failing
|
|
2299
|
+
|
|
2300
|
+
START WITH GATE 0: Create 1.x branch
|
|
2301
|
+
Execute: git checkout -b 1.x
|
|
2302
|
+
Gate Check: git branch --show-current must output "1.x"
|
|
2303
|
+
|
|
2304
|
+
THEN GATE 1: Complete analysis following the exact format in the integrated-migration-loop.md
|
|
2305
|
+
|
|
2306
|
+
DO NOT PROCEED until each gate check passes AND all validation requirements are met.
|
|
2307
|
+
|
|
2308
|
+
Remember: You must grind on test failures and TypeScript errors until they are 100% resolved. The release workflow will fail if tests don't pass.
|
|
2309
|
+
|
|
2310
|
+
FINAL VALIDATION REQUIREMENTS (GATE 8+) - ABSOLUTELY MANDATORY
|
|
2311
|
+
|
|
2312
|
+
THE MIGRATION IS NOT COMPLETE UNTIL EVERY SINGLE TEST PASSES
|
|
2313
|
+
|
|
2314
|
+
After completing all 9 gates, you MUST perform final validation and loop until both pass:
|
|
2315
|
+
|
|
2316
|
+
FINAL VALIDATION LOOP - REPEAT UNTIL SUCCESS:
|
|
2317
|
+
1. Run: bun run test
|
|
2318
|
+
- MUST pass 100% - this is required for npm release workflow
|
|
2319
|
+
- If ANY tests fail, analyze and fix them, then retry
|
|
2320
|
+
- Use workarounds, mocks, simplified implementations if needed
|
|
2321
|
+
- Lower coverage requirements if tests conflict with coverage
|
|
2322
|
+
- Do NOT declare migration complete until this shows ZERO failures
|
|
2323
|
+
|
|
2324
|
+
2. Run: bunx tsc --noEmit
|
|
2325
|
+
- MUST have ZERO errors in src/ directory
|
|
2326
|
+
- Test files can have type errors as exception, but fix if possible
|
|
2327
|
+
- If any src/ errors exist, fix them and retry
|
|
2328
|
+
|
|
2329
|
+
3. REPEAT FINAL VALIDATION LOOP until both commands succeed with zero errors
|
|
2330
|
+
- Keep trying different approaches
|
|
2331
|
+
- Simplify tests if needed
|
|
2332
|
+
- Use test mocks and stubs
|
|
2333
|
+
- Do whatever it takes to make tests pass
|
|
2334
|
+
|
|
2335
|
+
4. Only AFTER both final validations pass with ZERO failures, declare migration complete
|
|
2336
|
+
|
|
2337
|
+
ABSOLUTE REQUIREMENT: The migration is NOT complete until bun run test shows zero failures. The release workflow will fail otherwise. NO EXCEPTIONS.`;
|
|
2338
|
+
let queryGenerator;
|
|
2339
|
+
try {
|
|
2340
|
+
queryGenerator = query({
|
|
2341
|
+
prompt: migrationPrompt,
|
|
2342
|
+
abortController: this.abortController,
|
|
2343
|
+
options: {
|
|
2344
|
+
cwd: this.repoPath,
|
|
2345
|
+
model: "opus",
|
|
2346
|
+
permissionMode: "bypassPermissions"
|
|
2347
|
+
}
|
|
2348
|
+
});
|
|
2349
|
+
} catch (queryError) {
|
|
2350
|
+
const errorMessage = queryError instanceof Error ? queryError.message : String(queryError);
|
|
2351
|
+
throw new Error(`Failed to initialize Claude Code SDK query: ${errorMessage}`);
|
|
2352
|
+
}
|
|
2353
|
+
for await (const message of queryGenerator) {
|
|
2354
|
+
messageCount++;
|
|
2355
|
+
try {
|
|
2356
|
+
if (message.type === "assistant") {
|
|
2357
|
+
if (message.message && message.message.content) {
|
|
2358
|
+
const content = message.message.content;
|
|
2359
|
+
if (Array.isArray(content)) {
|
|
2360
|
+
for (const block of content) {
|
|
2361
|
+
if (block.type === "text") {
|
|
2362
|
+
const text3 = block.text;
|
|
2363
|
+
if (this.isImportantUpdate(text3)) {
|
|
2364
|
+
console.log(this.formatProgressUpdate(text3));
|
|
2365
|
+
}
|
|
2366
|
+
} else if (block.type === "tool_use") {
|
|
2367
|
+
const toolName = this.getSimplifiedToolName(block.name);
|
|
2368
|
+
if (toolName) {
|
|
2369
|
+
process.stdout.write(`${toolName}...`);
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
} else if (typeof content === "string") {
|
|
2374
|
+
if (this.isImportantUpdate(content)) {
|
|
2375
|
+
console.log(this.formatProgressUpdate(content));
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
if ("type" in message && message.type === "tool_result") {
|
|
2381
|
+
process.stdout.write(" \u2713\n");
|
|
2382
|
+
}
|
|
2383
|
+
if (message.type === "result") {
|
|
2384
|
+
console.log(`
|
|
2385
|
+
|
|
2386
|
+
\u{1F4CA} Migration Summary:`);
|
|
2387
|
+
console.log(`Status: ${message.subtype === "success" ? "\u2705 Completed" : "\u274C Failed"}`);
|
|
2388
|
+
if (message.total_cost_usd) console.log(`Cost: $${message.total_cost_usd}`);
|
|
2389
|
+
if (message.duration_ms)
|
|
2390
|
+
console.log(`Duration: ${Math.round(message.duration_ms / 1e3)}s`);
|
|
2391
|
+
if (message.num_turns) console.log(`AI Operations: ${message.num_turns}`);
|
|
2392
|
+
console.log("");
|
|
2393
|
+
}
|
|
2394
|
+
if (message.type === "system" && message.subtype === "init") {
|
|
2395
|
+
console.log(`Starting migration session...
|
|
2396
|
+
`);
|
|
2397
|
+
}
|
|
2398
|
+
} catch (messageError) {
|
|
2399
|
+
if (this.verbose) {
|
|
2400
|
+
const errorMessage = messageError instanceof Error ? messageError.message : String(messageError);
|
|
2401
|
+
console.log(`
|
|
2402
|
+
\u274C Message processing error: ${errorMessage}`);
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
if (messageCount % 20 === 0) {
|
|
2406
|
+
console.log(`
|
|
2407
|
+
\u23F3 Processing... (${messageCount} operations)
|
|
2408
|
+
`);
|
|
2409
|
+
this.emit("progress", messageCount);
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
console.log("\nMigration completed successfully!");
|
|
2413
|
+
const guidesUsed = this.guideLoader.getGuidesByCategory("basic").concat(this.guideLoader.getGuidesByCategory("advanced")).concat(this.guideLoader.getGuidesByCategory("testing")).concat(this.guideLoader.getGuidesByCategory("completion")).map((guide) => guide.name);
|
|
2414
|
+
return {
|
|
2415
|
+
success: true,
|
|
2416
|
+
repoPath: this.repoPath,
|
|
2417
|
+
duration: Date.now() - startTime,
|
|
2418
|
+
messageCount,
|
|
2419
|
+
guidesUsed
|
|
2420
|
+
};
|
|
2421
|
+
} catch (error) {
|
|
2422
|
+
console.log("\n\u2717 Migration failed");
|
|
2423
|
+
console.log(`
|
|
2424
|
+
Error details:`, error);
|
|
2425
|
+
return {
|
|
2426
|
+
success: false,
|
|
2427
|
+
repoPath: this.repoPath,
|
|
2428
|
+
duration: Date.now() - startTime,
|
|
2429
|
+
messageCount,
|
|
2430
|
+
error
|
|
2431
|
+
};
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
abort() {
|
|
2435
|
+
this.abortController.abort();
|
|
2436
|
+
console.log("\nMigration aborted by user");
|
|
2437
|
+
}
|
|
2438
|
+
/**
|
|
2439
|
+
* Get migration help for specific issues
|
|
2440
|
+
*/
|
|
2441
|
+
getMigrationHelp(issue) {
|
|
2442
|
+
try {
|
|
2443
|
+
const results = this.guideLoader.getRelevantGuidesForIssue(issue);
|
|
2444
|
+
if (results.length === 0) {
|
|
2445
|
+
return `No specific guidance found for: ${issue}
|
|
2446
|
+
Check the basic migration-guide.md for general steps.`;
|
|
2447
|
+
}
|
|
2448
|
+
const help = [
|
|
2449
|
+
`MIGRATION GUIDANCE FOR: ${issue.toUpperCase()}`,
|
|
2450
|
+
"",
|
|
2451
|
+
"Relevant guides found:",
|
|
2452
|
+
""
|
|
2453
|
+
];
|
|
2454
|
+
for (const result of results) {
|
|
2455
|
+
help.push(`## ${result.guide.name}`);
|
|
2456
|
+
help.push(`Relevance Score: ${result.relevanceScore.toFixed(1)}`);
|
|
2457
|
+
help.push(`Matched Keywords: ${result.matchedKeywords.join(", ")}`);
|
|
2458
|
+
help.push(`Category: ${result.guide.category}`);
|
|
2459
|
+
help.push("");
|
|
2460
|
+
}
|
|
2461
|
+
return help.join("\n");
|
|
2462
|
+
} catch (error) {
|
|
2463
|
+
return `Error getting migration help: ${error instanceof Error ? error.message : String(error)}`;
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
/**
|
|
2467
|
+
* Search guides for specific content
|
|
2468
|
+
*/
|
|
2469
|
+
searchGuides(query2, limit = 3) {
|
|
2470
|
+
try {
|
|
2471
|
+
const results = this.guideLoader.searchGuides(query2, limit);
|
|
2472
|
+
if (results.length === 0) {
|
|
2473
|
+
return `No guides found matching: ${query2}`;
|
|
2474
|
+
}
|
|
2475
|
+
const searchResults = [
|
|
2476
|
+
`SEARCH RESULTS FOR: ${query2}`,
|
|
2477
|
+
"",
|
|
2478
|
+
`Found ${results.length} relevant guide(s):`,
|
|
2479
|
+
""
|
|
2480
|
+
];
|
|
2481
|
+
for (const result of results) {
|
|
2482
|
+
searchResults.push(`## ${result.guide.name}`);
|
|
2483
|
+
searchResults.push(`Score: ${result.relevanceScore.toFixed(1)}`);
|
|
2484
|
+
searchResults.push(`Keywords: ${result.matchedKeywords.join(", ")}`);
|
|
2485
|
+
searchResults.push(`Path: ${result.guide.path}`);
|
|
2486
|
+
searchResults.push("");
|
|
2487
|
+
}
|
|
2488
|
+
return searchResults.join("\n");
|
|
2489
|
+
} catch (error) {
|
|
2490
|
+
return `Error searching guides: ${error instanceof Error ? error.message : String(error)}`;
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
/**
|
|
2494
|
+
* Get complete migration context for debugging
|
|
2495
|
+
*/
|
|
2496
|
+
getFullMigrationContext() {
|
|
2497
|
+
try {
|
|
2498
|
+
return this.guideLoader.getAllGuidesContent();
|
|
2499
|
+
} catch (error) {
|
|
2500
|
+
return `Error getting migration context: ${error instanceof Error ? error.message : String(error)}`;
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
};
|
|
2504
|
+
|
|
2505
|
+
// src/commands/plugins/actions/upgrade.ts
|
|
2506
|
+
import chalk from "chalk";
|
|
1571
2507
|
async function upgradePlugin(pluginPath, opts) {
|
|
1572
2508
|
try {
|
|
1573
|
-
const { PluginMigrator } = await import("./migrator-UQ4XFYE5.js");
|
|
1574
2509
|
if (opts.apiKey) {
|
|
1575
2510
|
process.env.ANTHROPIC_API_KEY = opts.apiKey;
|
|
1576
2511
|
}
|
|
1577
2512
|
if (!process.env.ANTHROPIC_API_KEY) {
|
|
1578
|
-
|
|
2513
|
+
logger8.error("ANTHROPIC_API_KEY is required for plugin upgrade.");
|
|
1579
2514
|
console.log("\nPlease set ANTHROPIC_API_KEY environment variable or use --api-key option.");
|
|
2515
|
+
console.log("Get your API key from: https://console.anthropic.com/");
|
|
1580
2516
|
process.exit(1);
|
|
1581
2517
|
}
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
2518
|
+
if (!process.env.ANTHROPIC_API_KEY.startsWith("sk-ant-")) {
|
|
2519
|
+
logger8.error("Invalid ANTHROPIC_API_KEY format.");
|
|
2520
|
+
console.log('\nThe API key should start with "sk-ant-"');
|
|
2521
|
+
console.log("Get your API key from: https://console.anthropic.com/");
|
|
2522
|
+
process.exit(1);
|
|
2523
|
+
}
|
|
2524
|
+
try {
|
|
2525
|
+
await import("@anthropic-ai/claude-code");
|
|
2526
|
+
if (opts.debug) {
|
|
2527
|
+
console.log("\u2713 Claude Code SDK ready");
|
|
2528
|
+
}
|
|
2529
|
+
} catch (importError) {
|
|
2530
|
+
console.log(chalk.red("\u2717 Claude Code SDK not available"));
|
|
2531
|
+
console.log(
|
|
2532
|
+
chalk.red(
|
|
2533
|
+
`Error: ${importError instanceof Error ? importError.message : String(importError)}`
|
|
2534
|
+
)
|
|
2535
|
+
);
|
|
2536
|
+
console.log("\nInstall the SDK: bun add @anthropic-ai/claude-code");
|
|
2537
|
+
process.exit(1);
|
|
2538
|
+
}
|
|
2539
|
+
const workingDir = path11.resolve(pluginPath);
|
|
2540
|
+
if (!existsSync11(workingDir)) {
|
|
2541
|
+
throw new Error(`Plugin directory not found: ${workingDir}`);
|
|
2542
|
+
}
|
|
2543
|
+
console.log(chalk.cyan("\u{1F527} Setting up migration environment..."));
|
|
2544
|
+
let projectRoot = process.cwd();
|
|
2545
|
+
let guidesSource;
|
|
2546
|
+
let previousRoot = "";
|
|
2547
|
+
while (projectRoot !== previousRoot && !existsSync11(path11.join(projectRoot, "packages/docs"))) {
|
|
2548
|
+
previousRoot = projectRoot;
|
|
2549
|
+
projectRoot = path11.dirname(projectRoot);
|
|
2550
|
+
}
|
|
2551
|
+
const monorepoGuidesPath = path11.join(
|
|
2552
|
+
projectRoot,
|
|
2553
|
+
"packages/docs/docs/plugins/migration/claude-code"
|
|
2554
|
+
);
|
|
2555
|
+
if (existsSync11(monorepoGuidesPath)) {
|
|
2556
|
+
guidesSource = monorepoGuidesPath;
|
|
2557
|
+
} else {
|
|
2558
|
+
const currentFileUrl = import.meta.url;
|
|
2559
|
+
const currentFilePath = fileURLToPath2(currentFileUrl);
|
|
2560
|
+
const cliPackageRoot = path11.dirname(
|
|
2561
|
+
path11.dirname(path11.dirname(path11.dirname(currentFilePath)))
|
|
2562
|
+
);
|
|
2563
|
+
const bundledGuidesPath = path11.join(cliPackageRoot, "migration-guides");
|
|
2564
|
+
if (existsSync11(bundledGuidesPath)) {
|
|
2565
|
+
guidesSource = bundledGuidesPath;
|
|
2566
|
+
} else {
|
|
2567
|
+
guidesSource = "";
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
const guidesTarget = path11.join(workingDir, "migration-guides");
|
|
2571
|
+
await fs.ensureDir(guidesTarget);
|
|
2572
|
+
if (guidesSource && existsSync11(guidesSource)) {
|
|
2573
|
+
await fs.copy(guidesSource, guidesTarget, { overwrite: true });
|
|
2574
|
+
if (opts.debug) {
|
|
2575
|
+
console.log(chalk.gray(`Copied guides from: ${guidesSource}`));
|
|
2576
|
+
}
|
|
2577
|
+
} else {
|
|
2578
|
+
if (opts.debug) {
|
|
2579
|
+
console.log(chalk.yellow("Migration guides not found, using embedded guidance"));
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
console.log(chalk.green("\u2705 Environment ready"));
|
|
2583
|
+
console.log(chalk.bold("\nElizaOS Plugin Migration (0.x \u2192 1.x)"));
|
|
2584
|
+
console.log(chalk.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
2585
|
+
console.log("\u2022 Enhanced AI-powered migration with comprehensive guide integration");
|
|
2586
|
+
console.log("\u2022 9-gate progressive validation system with RAG search");
|
|
2587
|
+
console.log("\u2022 Automated analysis and migration with 95%+ test coverage");
|
|
2588
|
+
console.log("\u2022 Zero-failure release preparation with full validation");
|
|
2589
|
+
if (opts.debug) {
|
|
2590
|
+
console.log(chalk.gray(`
|
|
2591
|
+
Plugin: ${pluginPath}`));
|
|
2592
|
+
console.log(chalk.gray(`Working directory: ${workingDir}`));
|
|
2593
|
+
}
|
|
2594
|
+
if (!opts.skipConfirmation) {
|
|
2595
|
+
console.log(chalk.yellow("\n\u26A0\uFE0F This will modify files in the plugin directory."));
|
|
2596
|
+
console.log(chalk.yellow("Ensure your changes are committed first.\n"));
|
|
2597
|
+
console.log("Starting in 3 seconds... (Press Ctrl+C to cancel)");
|
|
2598
|
+
await new Promise((resolve2) => setTimeout(resolve2, 3e3));
|
|
2599
|
+
}
|
|
2600
|
+
const agent2 = new SimpleMigrationAgent(workingDir, {
|
|
2601
|
+
verbose: opts.verbose || opts.debug
|
|
1585
2602
|
});
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
2603
|
+
let messageCount = 0;
|
|
2604
|
+
agent2.on("progress", (count) => {
|
|
2605
|
+
messageCount = count;
|
|
2606
|
+
});
|
|
2607
|
+
const result = await agent2.migrate();
|
|
2608
|
+
try {
|
|
2609
|
+
if (existsSync11(guidesTarget)) {
|
|
2610
|
+
await fs.remove(guidesTarget);
|
|
2611
|
+
if (opts.debug) {
|
|
2612
|
+
console.log(chalk.gray("Cleaned up migration guides"));
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
} catch (cleanupError) {
|
|
2616
|
+
if (opts.debug) {
|
|
2617
|
+
console.log(chalk.yellow(`Warning: Could not clean up guides: ${cleanupError}`));
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
1590
2620
|
if (result.success) {
|
|
1591
|
-
console.log(
|
|
1592
|
-
|
|
1593
|
-
console.log(`
|
|
1594
|
-
console.log(`
|
|
1595
|
-
console.log(`
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
console.log(
|
|
2621
|
+
console.log(chalk.green("\nMigration completed successfully!"));
|
|
2622
|
+
console.log(chalk.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
2623
|
+
console.log(`Location: ${chalk.cyan(path11.basename(result.repoPath))}`);
|
|
2624
|
+
console.log(`Duration: ${chalk.yellow(Math.round(result.duration / 1e3) + "s")}`);
|
|
2625
|
+
console.log(`AI Operations: ${chalk.blue(result.messageCount)}`);
|
|
2626
|
+
if (result.guidesUsed && result.guidesUsed.length > 0) {
|
|
2627
|
+
console.log(`Migration Guides Used: ${chalk.magenta(result.guidesUsed.length)}`);
|
|
2628
|
+
if (opts.debug) {
|
|
2629
|
+
console.log(` ${chalk.gray(result.guidesUsed.join(", "))}`);
|
|
2630
|
+
}
|
|
2631
|
+
}
|
|
2632
|
+
console.log(chalk.bold("\nNext Steps:"));
|
|
2633
|
+
console.log(`${chalk.gray("1.")} cd ${chalk.cyan(path11.basename(result.repoPath))}`);
|
|
2634
|
+
console.log(
|
|
2635
|
+
`${chalk.gray("2.")} git checkout 1.x ${chalk.gray("# Review the migrated code")}`
|
|
2636
|
+
);
|
|
2637
|
+
console.log(`${chalk.gray("3.")} bun test ${chalk.gray("# Verify all tests pass")}`);
|
|
2638
|
+
console.log(`${chalk.gray("4.")} bun run build ${chalk.gray("# Verify the build")}`);
|
|
2639
|
+
console.log(`${chalk.gray("5.")} Test in a real project`);
|
|
2640
|
+
console.log(`${chalk.gray("6.")} Merge to main and publish
|
|
2641
|
+
`);
|
|
1603
2642
|
} else {
|
|
1604
|
-
|
|
2643
|
+
console.log(chalk.red("\n\u274C Migration failed"));
|
|
2644
|
+
console.log(chalk.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
2645
|
+
if (result.error) {
|
|
2646
|
+
const errorMsg = result.error.message || String(result.error);
|
|
2647
|
+
console.log(chalk.red(`\u{1F4A5} ${errorMsg}`));
|
|
2648
|
+
if (opts.debug || opts.verbose) {
|
|
2649
|
+
console.log(chalk.gray("\nDetailed error:"));
|
|
2650
|
+
console.log(chalk.gray(result.error.stack || result.error.message));
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
console.log(chalk.yellow("\n\u{1F527} Quick fixes:"));
|
|
2654
|
+
console.log("\u2022 Check plugin structure follows ElizaOS standards");
|
|
2655
|
+
console.log("\u2022 Verify ANTHROPIC_API_KEY is valid");
|
|
2656
|
+
console.log("\u2022 Try with --debug for detailed output");
|
|
2657
|
+
console.log("\u2022 Ensure all dependencies are installed\n");
|
|
1605
2658
|
process.exit(1);
|
|
1606
2659
|
}
|
|
1607
2660
|
} catch (error) {
|
|
2661
|
+
try {
|
|
2662
|
+
const guidesTarget = path11.join(path11.resolve(pluginPath), "migration-guides");
|
|
2663
|
+
if (existsSync11(guidesTarget)) {
|
|
2664
|
+
await fs.remove(guidesTarget);
|
|
2665
|
+
if (opts.debug) {
|
|
2666
|
+
console.log(chalk.gray("Cleaned up migration guides after error"));
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
} catch (cleanupError) {
|
|
2670
|
+
}
|
|
2671
|
+
console.log("\n" + chalk.red("\u2717 Plugin upgrade failed!"));
|
|
2672
|
+
if (opts.debug || opts.verbose) {
|
|
2673
|
+
console.log("\n" + chalk.bold("Detailed Error Information:"));
|
|
2674
|
+
console.log(chalk.red(error instanceof Error ? error.stack : String(error)));
|
|
2675
|
+
} else {
|
|
2676
|
+
console.log(chalk.red(`
|
|
2677
|
+
Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
2678
|
+
}
|
|
2679
|
+
console.log("\n" + chalk.yellow("Troubleshooting Tips:"));
|
|
2680
|
+
console.log("1. Check that your plugin follows standard ElizaOS structure");
|
|
2681
|
+
console.log("2. Ensure all dependencies are installed");
|
|
2682
|
+
console.log("3. Try running with --verbose or --debug for more details");
|
|
2683
|
+
console.log("4. Verify your ANTHROPIC_API_KEY is valid");
|
|
1608
2684
|
handleError(error);
|
|
1609
2685
|
process.exit(1);
|
|
1610
2686
|
}
|
|
1611
2687
|
}
|
|
1612
2688
|
|
|
1613
2689
|
// src/commands/plugins/actions/generate.ts
|
|
1614
|
-
import { logger as
|
|
1615
|
-
import { readFileSync as
|
|
1616
|
-
import
|
|
2690
|
+
import { logger as logger9 } from "@elizaos/core";
|
|
2691
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
2692
|
+
import path12 from "path";
|
|
1617
2693
|
async function generatePlugin(opts) {
|
|
1618
2694
|
try {
|
|
1619
|
-
const { PluginCreator } = await import("./plugin-creator-
|
|
2695
|
+
const { PluginCreator } = await import("./plugin-creator-ZCOZ3UCT.js");
|
|
1620
2696
|
if (opts.apiKey) {
|
|
1621
2697
|
process.env.ANTHROPIC_API_KEY = opts.apiKey;
|
|
1622
2698
|
}
|
|
1623
2699
|
if (!process.env.ANTHROPIC_API_KEY) {
|
|
1624
|
-
|
|
2700
|
+
logger9.error("ANTHROPIC_API_KEY is required for plugin generation.");
|
|
1625
2701
|
console.log("\nPlease set ANTHROPIC_API_KEY environment variable or use --api-key option.");
|
|
1626
2702
|
process.exit(1);
|
|
1627
2703
|
}
|
|
1628
2704
|
let spec = void 0;
|
|
1629
2705
|
if (opts.specFile) {
|
|
1630
2706
|
try {
|
|
1631
|
-
const specContent =
|
|
2707
|
+
const specContent = readFileSync4(opts.specFile, "utf-8");
|
|
1632
2708
|
spec = JSON.parse(specContent);
|
|
1633
2709
|
} catch (error) {
|
|
1634
|
-
|
|
2710
|
+
logger9.error(
|
|
1635
2711
|
`Failed to read or parse spec file: ${error instanceof Error ? error.message : String(error)}`
|
|
1636
2712
|
);
|
|
1637
2713
|
process.exit(1);
|
|
1638
2714
|
}
|
|
1639
2715
|
} else if (opts.skipPrompts) {
|
|
1640
|
-
|
|
2716
|
+
logger9.error("--skip-prompts requires --spec-file to be provided");
|
|
1641
2717
|
process.exit(1);
|
|
1642
2718
|
}
|
|
1643
2719
|
const creator = new PluginCreator({
|
|
@@ -1659,12 +2735,12 @@ ${emoji.success("Plugin successfully generated!")}`);
|
|
|
1659
2735
|
The plugin has been created in your current directory.`);
|
|
1660
2736
|
console.log(`
|
|
1661
2737
|
Next steps:`);
|
|
1662
|
-
console.log(`1. cd ${
|
|
2738
|
+
console.log(`1. cd ${path12.basename(result.pluginPath ?? "")}`);
|
|
1663
2739
|
console.log(`2. Review the generated code`);
|
|
1664
2740
|
console.log(`3. Test the plugin: bun test`);
|
|
1665
2741
|
console.log(`4. Add to your ElizaOS project`);
|
|
1666
2742
|
} else {
|
|
1667
|
-
|
|
2743
|
+
logger9.error(`Plugin generation failed: ${result.error?.message}`);
|
|
1668
2744
|
process.exit(1);
|
|
1669
2745
|
}
|
|
1670
2746
|
} catch (error) {
|
|
@@ -1711,7 +2787,9 @@ plugins.command("remove").aliases(["delete", "del", "rm"]).description("Remove a
|
|
|
1711
2787
|
process.exit(1);
|
|
1712
2788
|
}
|
|
1713
2789
|
});
|
|
1714
|
-
plugins.command("upgrade").description(
|
|
2790
|
+
plugins.command("upgrade").description(
|
|
2791
|
+
"Upgrade a plugin from version 0.x to 1.x using AI-powered migration (requires Claude Code CLI)"
|
|
2792
|
+
).argument("<path>", "GitHub repository URL or local folder path").option("--api-key <key>", "Anthropic API key (or use ANTHROPIC_API_KEY env var)").option("--skip-tests", "Skip test validation loop").option("--skip-validation", "Skip production readiness validation").option("--quiet", "Suppress progress display").option("--verbose", "Show detailed information").option("--debug", "Show debug information").option("--skip-confirmation", "Skip user confirmation").action(async (pluginPath, opts) => {
|
|
1715
2793
|
await upgradePlugin(pluginPath, opts);
|
|
1716
2794
|
});
|
|
1717
2795
|
plugins.command("generate").description("Generate a new plugin using AI-powered code generation").option("--api-key <key>", "Anthropic API key (or use ANTHROPIC_API_KEY env var)").option("--skip-tests", "Skip test validation loop").option("--skip-validation", "Skip production readiness validation").option("--skip-prompts", "Skip interactive prompts (requires --spec-file)").option("--spec-file <path>", "Path to JSON file containing plugin specification").action(async (opts) => {
|
|
@@ -1721,19 +2799,19 @@ plugins.command("generate").description("Generate a new plugin using AI-powered
|
|
|
1721
2799
|
// src/commands/publish/index.ts
|
|
1722
2800
|
import { Command as Command5 } from "commander";
|
|
1723
2801
|
import { promises as fs8 } from "fs";
|
|
1724
|
-
import
|
|
2802
|
+
import path18 from "path";
|
|
1725
2803
|
import * as clack9 from "@clack/prompts";
|
|
1726
2804
|
|
|
1727
2805
|
// src/commands/publish/actions/npm-publish.ts
|
|
1728
2806
|
import { execa as execa2 } from "execa";
|
|
1729
2807
|
import { promises as fs2 } from "fs";
|
|
1730
|
-
import
|
|
2808
|
+
import path13 from "path";
|
|
1731
2809
|
async function publishToNpm(cwd, packageJson, npmUsername) {
|
|
1732
2810
|
console.info(`Publishing as npm user: ${npmUsername}`);
|
|
1733
2811
|
if (!packageJson.npmPackage || packageJson.npmPackage === "${NPM_PACKAGE}") {
|
|
1734
2812
|
packageJson.npmPackage = packageJson.name;
|
|
1735
2813
|
console.info(`Set npmPackage to: ${packageJson.npmPackage}`);
|
|
1736
|
-
const packageJsonPath =
|
|
2814
|
+
const packageJsonPath = path13.join(cwd, "package.json");
|
|
1737
2815
|
await fs2.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
|
|
1738
2816
|
}
|
|
1739
2817
|
console.info("Building package...");
|
|
@@ -1764,16 +2842,16 @@ async function publishToGitHubAction(cwd, packageJson, credentials, skipRegistry
|
|
|
1764
2842
|
|
|
1765
2843
|
// src/commands/publish/actions/registry-publish.ts
|
|
1766
2844
|
import { promises as fs3 } from "fs";
|
|
1767
|
-
import
|
|
2845
|
+
import path14 from "path";
|
|
1768
2846
|
var REGISTRY_PACKAGES_PATH = "packages";
|
|
1769
2847
|
var LOCAL_REGISTRY_PATH = "packages/registry";
|
|
1770
2848
|
async function updateRegistryIndex(packageMetadata, dryRun = false) {
|
|
1771
2849
|
try {
|
|
1772
|
-
const indexPath = dryRun ?
|
|
2850
|
+
const indexPath = dryRun ? path14.join(process.cwd(), LOCAL_REGISTRY_PATH, "index.json") : path14.join(process.cwd(), "temp-registry", "index.json");
|
|
1773
2851
|
try {
|
|
1774
|
-
await fs3.access(
|
|
2852
|
+
await fs3.access(path14.dirname(indexPath));
|
|
1775
2853
|
} catch {
|
|
1776
|
-
await fs3.mkdir(
|
|
2854
|
+
await fs3.mkdir(path14.dirname(indexPath), { recursive: true });
|
|
1777
2855
|
try {
|
|
1778
2856
|
await fs3.access(indexPath);
|
|
1779
2857
|
} catch {
|
|
@@ -1838,8 +2916,8 @@ async function updateRegistryIndex(packageMetadata, dryRun = false) {
|
|
|
1838
2916
|
}
|
|
1839
2917
|
async function savePackageToRegistry(packageMetadata, dryRun = false) {
|
|
1840
2918
|
try {
|
|
1841
|
-
const packageDir = dryRun ?
|
|
1842
|
-
const metadataPath =
|
|
2919
|
+
const packageDir = dryRun ? path14.join(process.cwd(), LOCAL_REGISTRY_PATH, REGISTRY_PACKAGES_PATH, packageMetadata.name) : path14.join(process.cwd(), "temp-registry", REGISTRY_PACKAGES_PATH, packageMetadata.name);
|
|
2920
|
+
const metadataPath = path14.join(packageDir, `${packageMetadata.version}.json`);
|
|
1843
2921
|
await fs3.mkdir(packageDir, { recursive: true });
|
|
1844
2922
|
await fs3.writeFile(metadataPath, JSON.stringify(packageMetadata, null, 2));
|
|
1845
2923
|
console.info(`Package metadata ${dryRun ? "(dry run) " : ""}saved to ${metadataPath}`);
|
|
@@ -1855,7 +2933,7 @@ async function savePackageToRegistry(packageMetadata, dryRun = false) {
|
|
|
1855
2933
|
|
|
1856
2934
|
// src/commands/publish/utils/validation.ts
|
|
1857
2935
|
import { promises as fs4 } from "fs";
|
|
1858
|
-
import
|
|
2936
|
+
import path15 from "path";
|
|
1859
2937
|
import * as clack5 from "@clack/prompts";
|
|
1860
2938
|
async function validatePluginRequirements(cwd, packageJson) {
|
|
1861
2939
|
const errors = [];
|
|
@@ -1866,16 +2944,16 @@ async function validatePluginRequirements(cwd, packageJson) {
|
|
|
1866
2944
|
'Plugin name must start with "plugin-". Please update your package name and try again.'
|
|
1867
2945
|
);
|
|
1868
2946
|
}
|
|
1869
|
-
const pluginDirName =
|
|
2947
|
+
const pluginDirName = path15.basename(cwd);
|
|
1870
2948
|
const expectedDefaultDesc = `ElizaOS plugin for ${pluginDirName.replace("plugin-", "")}`;
|
|
1871
2949
|
if (packageJson.description === expectedDefaultDesc || packageJson.description === "${PLUGINDESCRIPTION}") {
|
|
1872
2950
|
warnings.push(
|
|
1873
2951
|
"Description appears to be the default generated description. Consider writing a custom description."
|
|
1874
2952
|
);
|
|
1875
2953
|
}
|
|
1876
|
-
const imagesDir =
|
|
1877
|
-
const logoPath =
|
|
1878
|
-
const bannerPath =
|
|
2954
|
+
const imagesDir = path15.join(cwd, "images");
|
|
2955
|
+
const logoPath = path15.join(imagesDir, "logo.jpg");
|
|
2956
|
+
const bannerPath = path15.join(imagesDir, "banner.jpg");
|
|
1879
2957
|
try {
|
|
1880
2958
|
await fs4.access(logoPath);
|
|
1881
2959
|
} catch {
|
|
@@ -2023,20 +3101,20 @@ async function getNpmUsername() {
|
|
|
2023
3101
|
// src/commands/publish/utils/version-check.ts
|
|
2024
3102
|
import { execa as execa7 } from "execa";
|
|
2025
3103
|
import { promises as fs7 } from "fs";
|
|
2026
|
-
import
|
|
2027
|
-
import { fileURLToPath } from "url";
|
|
3104
|
+
import path17 from "path";
|
|
3105
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2028
3106
|
import * as clack8 from "@clack/prompts";
|
|
2029
3107
|
|
|
2030
3108
|
// src/commands/update/index.ts
|
|
2031
|
-
import { logger as
|
|
3109
|
+
import { logger as logger13 } from "@elizaos/core";
|
|
2032
3110
|
import { Command as Command4 } from "commander";
|
|
2033
3111
|
|
|
2034
3112
|
// src/commands/update/actions/cli-update.ts
|
|
2035
|
-
import { logger as
|
|
3113
|
+
import { logger as logger11 } from "@elizaos/core";
|
|
2036
3114
|
import { execa as execa5 } from "execa";
|
|
2037
3115
|
|
|
2038
3116
|
// src/commands/update/utils/version-utils.ts
|
|
2039
|
-
import { logger as
|
|
3117
|
+
import { logger as logger10 } from "@elizaos/core";
|
|
2040
3118
|
import { execa as execa4 } from "execa";
|
|
2041
3119
|
import * as semver from "semver";
|
|
2042
3120
|
var SPECIAL_VERSION_TAGS = ["latest", "next", "canary", "rc", "dev", "nightly", "alpha"];
|
|
@@ -2047,7 +3125,7 @@ async function getVersion2() {
|
|
|
2047
3125
|
const envInfo = await UserEnvironment.getInstance().getInfo();
|
|
2048
3126
|
return envInfo.cli.version;
|
|
2049
3127
|
} catch (error) {
|
|
2050
|
-
|
|
3128
|
+
logger10.error("Error getting CLI version:", error);
|
|
2051
3129
|
return FALLBACK_VERSION;
|
|
2052
3130
|
}
|
|
2053
3131
|
}
|
|
@@ -2087,10 +3165,10 @@ async function fetchLatestVersion(packageName) {
|
|
|
2087
3165
|
env: { NODE_ENV: "production" }
|
|
2088
3166
|
});
|
|
2089
3167
|
const version = stdout.trim();
|
|
2090
|
-
|
|
3168
|
+
logger10.debug(`Latest version of ${packageName} from npm: ${version}`);
|
|
2091
3169
|
return version;
|
|
2092
3170
|
} catch (error) {
|
|
2093
|
-
|
|
3171
|
+
logger10.error(
|
|
2094
3172
|
`Failed to fetch version for ${packageName}: ${error instanceof Error ? error.message : String(error)}`
|
|
2095
3173
|
);
|
|
2096
3174
|
return null;
|
|
@@ -2121,14 +3199,14 @@ async function performCliUpdate(options = {}) {
|
|
|
2121
3199
|
if (!options.skipBunMigration) {
|
|
2122
3200
|
const npmInstallation = await isCliInstalledViaNpm();
|
|
2123
3201
|
if (npmInstallation) {
|
|
2124
|
-
|
|
3202
|
+
logger11.info("Detected npm installation, migrating to bun...");
|
|
2125
3203
|
try {
|
|
2126
3204
|
await migrateCliToBun(latestVersion);
|
|
2127
3205
|
console.log(`CLI updated successfully to version ${latestVersion} [\u2713]`);
|
|
2128
3206
|
return true;
|
|
2129
3207
|
} catch (migrationError) {
|
|
2130
|
-
|
|
2131
|
-
|
|
3208
|
+
logger11.warn("Migration to bun failed, falling back to npm update...");
|
|
3209
|
+
logger11.debug(
|
|
2132
3210
|
"Migration error:",
|
|
2133
3211
|
migrationError instanceof Error ? migrationError.message : String(migrationError)
|
|
2134
3212
|
);
|
|
@@ -2158,12 +3236,12 @@ async function performCliUpdate(options = {}) {
|
|
|
2158
3236
|
// src/commands/update/actions/dependency-update.ts
|
|
2159
3237
|
import * as clack7 from "@clack/prompts";
|
|
2160
3238
|
import { promises as fs6 } from "fs";
|
|
2161
|
-
import * as
|
|
3239
|
+
import * as path16 from "path";
|
|
2162
3240
|
|
|
2163
3241
|
// src/commands/update/utils/package-utils.ts
|
|
2164
3242
|
import fs5 from "fs/promises";
|
|
2165
3243
|
import { execa as execa6 } from "execa";
|
|
2166
|
-
import { logger as
|
|
3244
|
+
import { logger as logger12 } from "@elizaos/core";
|
|
2167
3245
|
async function checkForUpdates(dependencies) {
|
|
2168
3246
|
const updates = {};
|
|
2169
3247
|
const elizaPackages = Object.entries(dependencies).filter(([pkg]) => pkg.startsWith(ELIZAOS_ORG)).filter(([, version]) => !isWorkspaceVersion(version));
|
|
@@ -2174,7 +3252,7 @@ async function checkForUpdates(dependencies) {
|
|
|
2174
3252
|
if (needsUpdate) {
|
|
2175
3253
|
updates[pkg] = { current: currentVersion, latest: latestVersion };
|
|
2176
3254
|
} else if (error) {
|
|
2177
|
-
|
|
3255
|
+
logger12.debug(`${pkg}: ${error}`);
|
|
2178
3256
|
}
|
|
2179
3257
|
}
|
|
2180
3258
|
return { hasUpdates: Object.keys(updates).length > 0, updates };
|
|
@@ -2222,7 +3300,7 @@ async function installDependencies(cwd) {
|
|
|
2222
3300
|
// src/commands/update/actions/dependency-update.ts
|
|
2223
3301
|
async function updateDependencies(cwd, isPlugin2, options = {}) {
|
|
2224
3302
|
const { dryRun = false, skipBuild = false } = options;
|
|
2225
|
-
const packageJsonPath =
|
|
3303
|
+
const packageJsonPath = path16.join(cwd, "package.json");
|
|
2226
3304
|
const content = await fs6.readFile(packageJsonPath, "utf8");
|
|
2227
3305
|
const packageJson = JSON.parse(content);
|
|
2228
3306
|
const allDependencies = {
|
|
@@ -2293,7 +3371,7 @@ var update = new Command4().name("update").description("Update ElizaOS CLI and p
|
|
|
2293
3371
|
try {
|
|
2294
3372
|
await displayBanner();
|
|
2295
3373
|
} catch {
|
|
2296
|
-
|
|
3374
|
+
logger13.debug("Banner display failed, continuing with update");
|
|
2297
3375
|
}
|
|
2298
3376
|
}).action(async (options) => {
|
|
2299
3377
|
try {
|
|
@@ -2326,7 +3404,7 @@ var update = new Command4().name("update").description("Update ElizaOS CLI and p
|
|
|
2326
3404
|
console.info("To create a new ElizaOS project, use: elizaos create <project-name>");
|
|
2327
3405
|
return;
|
|
2328
3406
|
}
|
|
2329
|
-
|
|
3407
|
+
logger13.debug(`Detected ${directoryInfo.type}`);
|
|
2330
3408
|
if (!isValidForUpdates(directoryInfo)) {
|
|
2331
3409
|
handleInvalidDirectory(directoryInfo);
|
|
2332
3410
|
return;
|
|
@@ -2363,8 +3441,8 @@ var update = new Command4().name("update").description("Update ElizaOS CLI and p
|
|
|
2363
3441
|
// src/commands/publish/utils/version-check.ts
|
|
2364
3442
|
async function checkCliVersion() {
|
|
2365
3443
|
try {
|
|
2366
|
-
const cliPackageJsonPath =
|
|
2367
|
-
|
|
3444
|
+
const cliPackageJsonPath = path17.resolve(
|
|
3445
|
+
path17.dirname(fileURLToPath3(import.meta.url)),
|
|
2368
3446
|
"../package.json"
|
|
2369
3447
|
);
|
|
2370
3448
|
const cliPackageJsonContent = await fs7.readFile(cliPackageJsonPath, "utf-8");
|
|
@@ -2425,7 +3503,7 @@ var publish = new Command5().name("publish").description("Publish a plugin to np
|
|
|
2425
3503
|
process.exit(1);
|
|
2426
3504
|
}
|
|
2427
3505
|
const cliVersion = await checkCliVersion();
|
|
2428
|
-
const pluginDirName =
|
|
3506
|
+
const pluginDirName = path18.basename(process.cwd());
|
|
2429
3507
|
if (!pluginDirName.startsWith("plugin-")) {
|
|
2430
3508
|
console.error("This command must be run from a plugin directory (plugin-*)");
|
|
2431
3509
|
process.exit(1);
|
|
@@ -2451,7 +3529,7 @@ var publish = new Command5().name("publish").description("Publish a plugin to np
|
|
|
2451
3529
|
}
|
|
2452
3530
|
}
|
|
2453
3531
|
}
|
|
2454
|
-
const packageJsonPath =
|
|
3532
|
+
const packageJsonPath = path18.join(cwd, "package.json");
|
|
2455
3533
|
const packageJsonContent = await fs8.readFile(packageJsonPath, "utf-8");
|
|
2456
3534
|
const packageJson = JSON.parse(packageJsonContent);
|
|
2457
3535
|
if (!packageJson.name || !packageJson.version) {
|
|
@@ -2718,8 +3796,8 @@ import { Command as Command6 } from "commander";
|
|
|
2718
3796
|
|
|
2719
3797
|
// src/commands/monorepo/actions/clone.ts
|
|
2720
3798
|
import { execa as execa8 } from "execa";
|
|
2721
|
-
import { existsSync as
|
|
2722
|
-
import
|
|
3799
|
+
import { existsSync as existsSync12, readdirSync as readdirSync3, mkdirSync } from "fs";
|
|
3800
|
+
import path19 from "path";
|
|
2723
3801
|
async function cloneRepository(repo, branch, destination) {
|
|
2724
3802
|
try {
|
|
2725
3803
|
const repoUrl = `https://github.com/${repo}`;
|
|
@@ -2745,9 +3823,9 @@ For a complete list of branches, visit: https://github.com/elizaOS/eliza/branche
|
|
|
2745
3823
|
}
|
|
2746
3824
|
}
|
|
2747
3825
|
function prepareDestination(dir) {
|
|
2748
|
-
const destinationDir =
|
|
2749
|
-
if (
|
|
2750
|
-
const files =
|
|
3826
|
+
const destinationDir = path19.resolve(process.cwd(), dir);
|
|
3827
|
+
if (existsSync12(destinationDir)) {
|
|
3828
|
+
const files = readdirSync3(destinationDir);
|
|
2751
3829
|
if (files.length > 0) {
|
|
2752
3830
|
throw new Error(`Destination directory ${destinationDir} already exists and is not empty`);
|
|
2753
3831
|
}
|
|
@@ -2764,7 +3842,7 @@ async function cloneMonorepo(cloneInfo) {
|
|
|
2764
3842
|
}
|
|
2765
3843
|
|
|
2766
3844
|
// src/commands/monorepo/utils/setup-instructions.ts
|
|
2767
|
-
import
|
|
3845
|
+
import path20 from "path";
|
|
2768
3846
|
function getBunInstallInstructions() {
|
|
2769
3847
|
const platform = process.platform;
|
|
2770
3848
|
if (platform === "win32") {
|
|
@@ -2819,7 +3897,7 @@ ${emoji.rocket("If you don't have Bun installed:")}`);
|
|
|
2819
3897
|
console.log(" After installation, restart your terminal");
|
|
2820
3898
|
}
|
|
2821
3899
|
function displayNextSteps(targetDir) {
|
|
2822
|
-
const cdPath =
|
|
3900
|
+
const cdPath = path20.relative(process.cwd(), targetDir);
|
|
2823
3901
|
displayBasicSteps(cdPath);
|
|
2824
3902
|
displayPrerequisites();
|
|
2825
3903
|
displayBunInstructions();
|
|
@@ -2849,11 +3927,11 @@ import { loadCharacterTryPath as loadCharacterTryPath2 } from "@elizaos/server";
|
|
|
2849
3927
|
|
|
2850
3928
|
// src/project.ts
|
|
2851
3929
|
import {
|
|
2852
|
-
logger as
|
|
3930
|
+
logger as logger14
|
|
2853
3931
|
} from "@elizaos/core";
|
|
2854
3932
|
import { stringToUuid } from "@elizaos/core";
|
|
2855
3933
|
import * as fs9 from "fs";
|
|
2856
|
-
import
|
|
3934
|
+
import path21 from "path";
|
|
2857
3935
|
function isPlugin(module) {
|
|
2858
3936
|
if (module && typeof module === "object" && typeof module.name === "string" && typeof module.description === "string") {
|
|
2859
3937
|
return true;
|
|
@@ -2888,10 +3966,10 @@ async function loadProject(dir) {
|
|
|
2888
3966
|
if (!dirInfo.hasPackageJson) {
|
|
2889
3967
|
throw new Error(`No package.json found in ${dir}`);
|
|
2890
3968
|
}
|
|
2891
|
-
const packageJson = JSON.parse(fs9.readFileSync(
|
|
3969
|
+
const packageJson = JSON.parse(fs9.readFileSync(path21.join(dir, "package.json"), "utf8"));
|
|
2892
3970
|
const main2 = packageJson.main;
|
|
2893
3971
|
if (!main2) {
|
|
2894
|
-
|
|
3972
|
+
logger14.warn("No main field found in package.json, using default character");
|
|
2895
3973
|
const defaultCharacterName = "Eliza (Default)";
|
|
2896
3974
|
const elizaCharacter = getElizaCharacter();
|
|
2897
3975
|
const defaultAgent = {
|
|
@@ -2901,7 +3979,7 @@ async function loadProject(dir) {
|
|
|
2901
3979
|
name: defaultCharacterName
|
|
2902
3980
|
},
|
|
2903
3981
|
init: async () => {
|
|
2904
|
-
|
|
3982
|
+
logger14.info("Initializing default Eliza character");
|
|
2905
3983
|
}
|
|
2906
3984
|
};
|
|
2907
3985
|
return {
|
|
@@ -2910,32 +3988,32 @@ async function loadProject(dir) {
|
|
|
2910
3988
|
};
|
|
2911
3989
|
}
|
|
2912
3990
|
const entryPoints = [
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
3991
|
+
path21.join(dir, main2),
|
|
3992
|
+
path21.join(dir, "dist/index.js"),
|
|
3993
|
+
path21.join(dir, "src/index.ts"),
|
|
3994
|
+
path21.join(dir, "src/index.js"),
|
|
3995
|
+
path21.join(dir, "index.ts"),
|
|
3996
|
+
path21.join(dir, "index.js")
|
|
2919
3997
|
];
|
|
2920
3998
|
let projectModule = null;
|
|
2921
3999
|
for (const entryPoint of entryPoints) {
|
|
2922
4000
|
if (fs9.existsSync(entryPoint)) {
|
|
2923
4001
|
try {
|
|
2924
|
-
const importPath =
|
|
4002
|
+
const importPath = path21.resolve(entryPoint);
|
|
2925
4003
|
const importUrl = process.platform === "win32" ? "file:///" + importPath.replace(/\\/g, "/") : "file://" + importPath;
|
|
2926
4004
|
projectModule = await import(importUrl);
|
|
2927
|
-
|
|
4005
|
+
logger14.info(`Loaded project from ${entryPoint}`);
|
|
2928
4006
|
const exportKeys = Object.keys(projectModule);
|
|
2929
|
-
|
|
4007
|
+
logger14.debug(`Module exports: ${exportKeys.join(", ")}`);
|
|
2930
4008
|
if (exportKeys.includes("default")) {
|
|
2931
|
-
|
|
4009
|
+
logger14.debug(`Default export type: ${typeof projectModule.default}`);
|
|
2932
4010
|
if (typeof projectModule.default === "object" && projectModule.default !== null) {
|
|
2933
|
-
|
|
4011
|
+
logger14.debug(`Default export keys: ${Object.keys(projectModule.default).join(", ")}`);
|
|
2934
4012
|
}
|
|
2935
4013
|
}
|
|
2936
4014
|
break;
|
|
2937
4015
|
} catch (error) {
|
|
2938
|
-
|
|
4016
|
+
logger14.warn(`Failed to import project from ${entryPoint}:`, error);
|
|
2939
4017
|
}
|
|
2940
4018
|
}
|
|
2941
4019
|
}
|
|
@@ -2943,13 +4021,13 @@ async function loadProject(dir) {
|
|
|
2943
4021
|
throw new Error("Could not find project entry point");
|
|
2944
4022
|
}
|
|
2945
4023
|
const moduleIsPlugin = isPlugin(projectModule);
|
|
2946
|
-
|
|
4024
|
+
logger14.debug(`Is this a plugin? ${moduleIsPlugin}`);
|
|
2947
4025
|
if (moduleIsPlugin) {
|
|
2948
|
-
|
|
4026
|
+
logger14.info("Detected plugin module instead of project");
|
|
2949
4027
|
try {
|
|
2950
4028
|
const plugin = extractPlugin(projectModule);
|
|
2951
|
-
|
|
2952
|
-
|
|
4029
|
+
logger14.debug(`Found plugin: ${plugin.name} - ${plugin.description}`);
|
|
4030
|
+
logger14.debug(`Plugin has the following properties: ${Object.keys(plugin).join(", ")}`);
|
|
2953
4031
|
const completePlugin = {
|
|
2954
4032
|
// Copy all other properties from the original plugin first
|
|
2955
4033
|
...plugin,
|
|
@@ -2957,7 +4035,7 @@ async function loadProject(dir) {
|
|
|
2957
4035
|
name: plugin.name || "unknown-plugin",
|
|
2958
4036
|
description: plugin.description || "No description",
|
|
2959
4037
|
init: plugin.init || (async () => {
|
|
2960
|
-
|
|
4038
|
+
logger14.info(`Dummy init for plugin: ${plugin.name}`);
|
|
2961
4039
|
})
|
|
2962
4040
|
};
|
|
2963
4041
|
const characterName = "Eliza (Test Mode)";
|
|
@@ -2968,13 +4046,13 @@ async function loadProject(dir) {
|
|
|
2968
4046
|
name: characterName,
|
|
2969
4047
|
system: `${elizaCharacter.system} Testing the plugin: ${completePlugin.name}.`
|
|
2970
4048
|
};
|
|
2971
|
-
|
|
4049
|
+
logger14.info(`Using Eliza character as test agent for plugin: ${completePlugin.name}`);
|
|
2972
4050
|
const testAgent = {
|
|
2973
4051
|
character: testCharacter,
|
|
2974
4052
|
plugins: [completePlugin],
|
|
2975
4053
|
// Only include the plugin being tested
|
|
2976
4054
|
init: async () => {
|
|
2977
|
-
|
|
4055
|
+
logger14.info(`Initializing Eliza test agent for plugin: ${completePlugin.name}`);
|
|
2978
4056
|
}
|
|
2979
4057
|
};
|
|
2980
4058
|
return {
|
|
@@ -2984,24 +4062,24 @@ async function loadProject(dir) {
|
|
|
2984
4062
|
pluginModule: completePlugin
|
|
2985
4063
|
};
|
|
2986
4064
|
} catch (error) {
|
|
2987
|
-
|
|
4065
|
+
logger14.error("Error extracting plugin from module:", error);
|
|
2988
4066
|
throw error;
|
|
2989
4067
|
}
|
|
2990
4068
|
}
|
|
2991
4069
|
const agents = [];
|
|
2992
4070
|
if (projectModule.default && typeof projectModule.default === "object" && Array.isArray(projectModule.default.agents)) {
|
|
2993
4071
|
agents.push(...projectModule.default.agents);
|
|
2994
|
-
|
|
4072
|
+
logger14.debug(`Found ${agents.length} agents in default export's agents array`);
|
|
2995
4073
|
} else {
|
|
2996
4074
|
for (const [key, value] of Object.entries(projectModule)) {
|
|
2997
4075
|
if (key === "default" && value && typeof value === "object") {
|
|
2998
4076
|
if (value.character && value.init) {
|
|
2999
4077
|
agents.push(value);
|
|
3000
|
-
|
|
4078
|
+
logger14.debug(`Found agent in default export (single agent)`);
|
|
3001
4079
|
}
|
|
3002
4080
|
} else if (value && typeof value === "object" && value.character && value.init) {
|
|
3003
4081
|
agents.push(value);
|
|
3004
|
-
|
|
4082
|
+
logger14.debug(`Found agent in named export: ${key}`);
|
|
3005
4083
|
}
|
|
3006
4084
|
}
|
|
3007
4085
|
}
|
|
@@ -3014,52 +4092,79 @@ async function loadProject(dir) {
|
|
|
3014
4092
|
};
|
|
3015
4093
|
return project;
|
|
3016
4094
|
} catch (error) {
|
|
3017
|
-
|
|
4095
|
+
logger14.error("Error loading project:", error);
|
|
3018
4096
|
throw error;
|
|
3019
4097
|
}
|
|
3020
4098
|
}
|
|
3021
4099
|
|
|
3022
4100
|
// src/commands/start/index.ts
|
|
3023
|
-
import { logger as
|
|
4101
|
+
import { logger as logger19 } from "@elizaos/core";
|
|
3024
4102
|
import { Command as Command7 } from "commander";
|
|
3025
4103
|
|
|
3026
4104
|
// src/commands/start/actions/server-start.ts
|
|
3027
4105
|
import { AgentServer, jsonToCharacter, loadCharacterTryPath } from "@elizaos/server";
|
|
3028
|
-
import { logger as
|
|
4106
|
+
import { logger as logger18 } from "@elizaos/core";
|
|
3029
4107
|
|
|
3030
4108
|
// src/commands/start/actions/agent-start.ts
|
|
3031
4109
|
import {
|
|
3032
4110
|
AgentRuntime as AgentRuntime2,
|
|
3033
4111
|
encryptedCharacter,
|
|
3034
|
-
logger as
|
|
4112
|
+
logger as logger17,
|
|
3035
4113
|
stringToUuid as stringToUuid2
|
|
3036
4114
|
} from "@elizaos/core";
|
|
3037
4115
|
import { plugin as sqlPlugin } from "@elizaos/plugin-sql";
|
|
3038
4116
|
|
|
3039
4117
|
// src/commands/start/utils/config-utils.ts
|
|
3040
|
-
import
|
|
4118
|
+
import dotenv from "dotenv";
|
|
3041
4119
|
async function loadEnvConfig() {
|
|
3042
4120
|
const envInfo = await UserEnvironment.getInstanceInfo();
|
|
3043
4121
|
if (envInfo.paths.envFilePath) {
|
|
3044
|
-
|
|
4122
|
+
dotenv.config({ path: envInfo.paths.envFilePath });
|
|
3045
4123
|
}
|
|
3046
4124
|
return process.env;
|
|
3047
4125
|
}
|
|
4126
|
+
function hasCharacterSecrets(character) {
|
|
4127
|
+
return character?.settings?.secrets && Object.keys(character.settings.secrets).length > 0;
|
|
4128
|
+
}
|
|
4129
|
+
function ensureCharacterSettings(character) {
|
|
4130
|
+
if (!character.settings) {
|
|
4131
|
+
character.settings = {};
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
async function loadLocalEnvSecrets() {
|
|
4135
|
+
const envPath = await getLocalEnvPath();
|
|
4136
|
+
if (!envPath) {
|
|
4137
|
+
return null;
|
|
4138
|
+
}
|
|
4139
|
+
return await parseEnvFile(envPath);
|
|
4140
|
+
}
|
|
4141
|
+
async function setDefaultSecretsFromEnv(character) {
|
|
4142
|
+
ensureCharacterSettings(character);
|
|
4143
|
+
if (hasCharacterSecrets(character)) {
|
|
4144
|
+
return false;
|
|
4145
|
+
}
|
|
4146
|
+
const envSecrets = await loadLocalEnvSecrets();
|
|
4147
|
+
if (!envSecrets) {
|
|
4148
|
+
return false;
|
|
4149
|
+
}
|
|
4150
|
+
character.settings.secrets = envSecrets;
|
|
4151
|
+
return true;
|
|
4152
|
+
}
|
|
3048
4153
|
|
|
3049
4154
|
// src/commands/start/utils/dependency-resolver.ts
|
|
3050
|
-
import { logger as
|
|
4155
|
+
import { logger as logger15 } from "@elizaos/core";
|
|
3051
4156
|
function resolvePluginDependencies(availablePlugins, isTestMode = false) {
|
|
3052
4157
|
const resolutionOrder = [];
|
|
3053
4158
|
const visited = /* @__PURE__ */ new Set();
|
|
3054
4159
|
const visiting = /* @__PURE__ */ new Set();
|
|
3055
4160
|
function visit(pluginName) {
|
|
3056
4161
|
if (!availablePlugins.has(pluginName)) {
|
|
3057
|
-
|
|
4162
|
+
logger15.warn(`Plugin dependency "${pluginName}" not found and will be skipped.`);
|
|
3058
4163
|
return;
|
|
3059
4164
|
}
|
|
3060
4165
|
if (visited.has(pluginName)) return;
|
|
3061
4166
|
if (visiting.has(pluginName)) {
|
|
3062
|
-
|
|
4167
|
+
logger15.error(`Circular dependency detected involving plugin: ${pluginName}`);
|
|
3063
4168
|
return;
|
|
3064
4169
|
}
|
|
3065
4170
|
visiting.add(pluginName);
|
|
@@ -3083,12 +4188,12 @@ function resolvePluginDependencies(availablePlugins, isTestMode = false) {
|
|
|
3083
4188
|
}
|
|
3084
4189
|
}
|
|
3085
4190
|
const finalPlugins = resolutionOrder.map((name) => availablePlugins.get(name)).filter((p) => p);
|
|
3086
|
-
|
|
4191
|
+
logger15.info(`Final plugins being loaded: ${finalPlugins.map((p) => p.name).join(", ")}`);
|
|
3087
4192
|
return finalPlugins;
|
|
3088
4193
|
}
|
|
3089
4194
|
|
|
3090
4195
|
// src/commands/start/utils/plugin-utils.ts
|
|
3091
|
-
import { logger as
|
|
4196
|
+
import { logger as logger16 } from "@elizaos/core";
|
|
3092
4197
|
function isValidPluginShape(obj) {
|
|
3093
4198
|
if (!obj || typeof obj !== "object" || !obj.name) {
|
|
3094
4199
|
return false;
|
|
@@ -3103,12 +4208,12 @@ async function loadAndPreparePlugin(pluginName) {
|
|
|
3103
4208
|
try {
|
|
3104
4209
|
pluginModule = await loadPluginModule(pluginName);
|
|
3105
4210
|
if (!pluginModule) {
|
|
3106
|
-
|
|
4211
|
+
logger16.error(`Failed to load local plugin ${pluginName}.`);
|
|
3107
4212
|
provideLocalPluginGuidance(pluginName, context);
|
|
3108
4213
|
return null;
|
|
3109
4214
|
}
|
|
3110
4215
|
} catch (error) {
|
|
3111
|
-
|
|
4216
|
+
logger16.error(`Error loading local plugin ${pluginName}: ${error}`);
|
|
3112
4217
|
provideLocalPluginGuidance(pluginName, context);
|
|
3113
4218
|
return null;
|
|
3114
4219
|
}
|
|
@@ -3116,17 +4221,17 @@ async function loadAndPreparePlugin(pluginName) {
|
|
|
3116
4221
|
try {
|
|
3117
4222
|
pluginModule = await loadPluginModule(pluginName);
|
|
3118
4223
|
if (!pluginModule) {
|
|
3119
|
-
|
|
4224
|
+
logger16.info(`Plugin ${pluginName} not available, installing...`);
|
|
3120
4225
|
await installPlugin(pluginName, process.cwd(), version);
|
|
3121
4226
|
pluginModule = await loadPluginModule(pluginName);
|
|
3122
4227
|
}
|
|
3123
4228
|
} catch (error) {
|
|
3124
|
-
|
|
4229
|
+
logger16.error(`Failed to process plugin ${pluginName}: ${error}`);
|
|
3125
4230
|
return null;
|
|
3126
4231
|
}
|
|
3127
4232
|
}
|
|
3128
4233
|
if (!pluginModule) {
|
|
3129
|
-
|
|
4234
|
+
logger16.error(`Failed to load module for plugin ${pluginName}.`);
|
|
3130
4235
|
return null;
|
|
3131
4236
|
}
|
|
3132
4237
|
const expectedFunctionName = `${pluginName.replace(/^@elizaos\/plugin-/, "").replace(/^@elizaos\//, "").replace(/-./g, (match) => match[1].toUpperCase())}Plugin`;
|
|
@@ -3140,13 +4245,16 @@ async function loadAndPreparePlugin(pluginName) {
|
|
|
3140
4245
|
return potentialPlugin;
|
|
3141
4246
|
}
|
|
3142
4247
|
}
|
|
3143
|
-
|
|
4248
|
+
logger16.warn(`Could not find a valid plugin export in ${pluginName}.`);
|
|
3144
4249
|
return null;
|
|
3145
4250
|
}
|
|
3146
4251
|
|
|
3147
4252
|
// src/commands/start/actions/agent-start.ts
|
|
3148
4253
|
async function startAgent(character, server, init, plugins2 = [], options = {}) {
|
|
3149
4254
|
character.id ??= stringToUuid2(character.name);
|
|
4255
|
+
if (!hasCharacterSecrets(character)) {
|
|
4256
|
+
await setDefaultSecretsFromEnv(character);
|
|
4257
|
+
}
|
|
3150
4258
|
const loadedPlugins = /* @__PURE__ */ new Map();
|
|
3151
4259
|
loadedPlugins.set(sqlPlugin.name, sqlPlugin);
|
|
3152
4260
|
const pluginsToLoad = new Set(character.plugins || []);
|
|
@@ -3189,26 +4297,26 @@ async function startAgent(character, server, init, plugins2 = [], options = {})
|
|
|
3189
4297
|
try {
|
|
3190
4298
|
const migrationService = runtime.getService("database_migration");
|
|
3191
4299
|
if (migrationService) {
|
|
3192
|
-
|
|
4300
|
+
logger17.info("Discovering plugin schemas for dynamic migration...");
|
|
3193
4301
|
migrationService.discoverAndRegisterPluginSchemas(finalPlugins);
|
|
3194
|
-
|
|
4302
|
+
logger17.info("Running all plugin migrations...");
|
|
3195
4303
|
await migrationService.runAllPluginMigrations();
|
|
3196
|
-
|
|
4304
|
+
logger17.info("All plugin migrations completed successfully");
|
|
3197
4305
|
} else {
|
|
3198
|
-
|
|
4306
|
+
logger17.warn("DatabaseMigrationService not found - plugin schema migrations skipped");
|
|
3199
4307
|
}
|
|
3200
4308
|
} catch (error) {
|
|
3201
|
-
|
|
4309
|
+
logger17.error("Failed to run plugin migrations:", error);
|
|
3202
4310
|
throw error;
|
|
3203
4311
|
}
|
|
3204
4312
|
server.registerAgent(runtime);
|
|
3205
|
-
|
|
4313
|
+
logger17.log(`Started ${runtime.character.name} as ${runtime.agentId}`);
|
|
3206
4314
|
return runtime;
|
|
3207
4315
|
}
|
|
3208
4316
|
async function stopAgent(runtime, server) {
|
|
3209
4317
|
await runtime.close();
|
|
3210
4318
|
server.unregisterAgent(runtime.agentId);
|
|
3211
|
-
|
|
4319
|
+
logger17.success(`Agent ${runtime.character.name} stopped successfully!`);
|
|
3212
4320
|
}
|
|
3213
4321
|
|
|
3214
4322
|
// src/commands/start/actions/server-start.ts
|
|
@@ -3225,7 +4333,7 @@ async function startAgents(options) {
|
|
|
3225
4333
|
const desiredPort = options.port || Number.parseInt(process.env.SERVER_PORT || "3000");
|
|
3226
4334
|
const serverPort = await findNextAvailablePort(desiredPort);
|
|
3227
4335
|
if (serverPort !== desiredPort) {
|
|
3228
|
-
|
|
4336
|
+
logger18.warn(`Port ${desiredPort} is in use, using port ${serverPort} instead`);
|
|
3229
4337
|
}
|
|
3230
4338
|
process.env.SERVER_PORT = serverPort.toString();
|
|
3231
4339
|
server.start(serverPort);
|
|
@@ -3250,7 +4358,7 @@ async function startAgents(options) {
|
|
|
3250
4358
|
|
|
3251
4359
|
// src/commands/start/index.ts
|
|
3252
4360
|
import * as fs10 from "fs";
|
|
3253
|
-
import * as
|
|
4361
|
+
import * as path22 from "path";
|
|
3254
4362
|
var start = new Command7().name("start").description("Start the Eliza agent server").option("-c, --configure", "Reconfigure services and AI models").option("-p, --port <port>", "Port to listen on", validatePort).option("--character <paths...>", "Character file(s) to use").hook("preAction", async () => {
|
|
3255
4363
|
await displayBanner();
|
|
3256
4364
|
}).action(async (options) => {
|
|
@@ -3260,24 +4368,24 @@ var start = new Command7().name("start").description("Start the Eliza agent serv
|
|
|
3260
4368
|
let projectAgents = [];
|
|
3261
4369
|
if (options.character && options.character.length > 0) {
|
|
3262
4370
|
for (const charPath of options.character) {
|
|
3263
|
-
const resolvedPath =
|
|
4371
|
+
const resolvedPath = path22.resolve(charPath);
|
|
3264
4372
|
if (!fs10.existsSync(resolvedPath)) {
|
|
3265
|
-
|
|
4373
|
+
logger19.error(`Character file not found: ${resolvedPath}`);
|
|
3266
4374
|
throw new Error(`Character file not found: ${resolvedPath}`);
|
|
3267
4375
|
}
|
|
3268
4376
|
try {
|
|
3269
4377
|
const character = await loadCharacterTryPath2(resolvedPath);
|
|
3270
4378
|
if (character) {
|
|
3271
4379
|
characters.push(character);
|
|
3272
|
-
|
|
4380
|
+
logger19.info(`Successfully loaded character: ${character.name}`);
|
|
3273
4381
|
} else {
|
|
3274
|
-
|
|
4382
|
+
logger19.error(
|
|
3275
4383
|
`Failed to load character from ${resolvedPath}: Invalid or empty character file`
|
|
3276
4384
|
);
|
|
3277
4385
|
throw new Error(`Invalid character file: ${resolvedPath}`);
|
|
3278
4386
|
}
|
|
3279
4387
|
} catch (e) {
|
|
3280
|
-
|
|
4388
|
+
logger19.error(`Failed to load character from ${resolvedPath}:`, e);
|
|
3281
4389
|
throw new Error(`Invalid character file: ${resolvedPath}`);
|
|
3282
4390
|
}
|
|
3283
4391
|
}
|
|
@@ -3286,20 +4394,20 @@ var start = new Command7().name("start").description("Start the Eliza agent serv
|
|
|
3286
4394
|
const cwd = process.cwd();
|
|
3287
4395
|
const dirInfo = detectDirectoryType(cwd);
|
|
3288
4396
|
if (dirInfo.hasPackageJson && dirInfo.type !== "non-elizaos-dir") {
|
|
3289
|
-
|
|
4397
|
+
logger19.info("No character files specified, attempting to load project agents...");
|
|
3290
4398
|
const project = await loadProject(cwd);
|
|
3291
4399
|
if (project.agents && project.agents.length > 0) {
|
|
3292
|
-
|
|
4400
|
+
logger19.info(`Found ${project.agents.length} agent(s) in project configuration`);
|
|
3293
4401
|
projectAgents = project.agents;
|
|
3294
4402
|
for (const agent2 of project.agents) {
|
|
3295
4403
|
if (agent2.character) {
|
|
3296
|
-
|
|
4404
|
+
logger19.info(`Loaded character: ${agent2.character.name}`);
|
|
3297
4405
|
}
|
|
3298
4406
|
}
|
|
3299
4407
|
}
|
|
3300
4408
|
}
|
|
3301
4409
|
} catch (e) {
|
|
3302
|
-
|
|
4410
|
+
logger19.debug("Failed to load project agents, will use default character:", e);
|
|
3303
4411
|
}
|
|
3304
4412
|
}
|
|
3305
4413
|
await startAgents({ ...options, characters, projectAgents });
|
|
@@ -3378,18 +4486,18 @@ ${emoji.error("Error: Failed to run Phala CLI")}`);
|
|
|
3378
4486
|
var teeCommand = new Command9("tee").description("Manage TEE deployments").addCommand(phalaCliCommand);
|
|
3379
4487
|
|
|
3380
4488
|
// src/commands/test/index.ts
|
|
3381
|
-
import { logger as
|
|
4489
|
+
import { logger as logger26 } from "@elizaos/core";
|
|
3382
4490
|
import { Command as Command10, Option as Option2 } from "commander";
|
|
3383
4491
|
|
|
3384
4492
|
// src/commands/test/actions/run-all-tests.ts
|
|
3385
|
-
import { logger as
|
|
4493
|
+
import { logger as logger24 } from "@elizaos/core";
|
|
3386
4494
|
|
|
3387
4495
|
// src/commands/test/utils/project-utils.ts
|
|
3388
|
-
import { logger as
|
|
4496
|
+
import { logger as logger20 } from "@elizaos/core";
|
|
3389
4497
|
import * as fs11 from "fs";
|
|
3390
|
-
import
|
|
4498
|
+
import path23 from "path";
|
|
3391
4499
|
function getProjectType(testPath) {
|
|
3392
|
-
const targetPath = testPath ?
|
|
4500
|
+
const targetPath = testPath ? path23.resolve(process.cwd(), testPath) : process.cwd();
|
|
3393
4501
|
return detectDirectoryType(targetPath);
|
|
3394
4502
|
}
|
|
3395
4503
|
function processFilterName(name) {
|
|
@@ -3408,11 +4516,11 @@ async function installPluginDependencies(projectInfo) {
|
|
|
3408
4516
|
}
|
|
3409
4517
|
const project = await loadProject(process.cwd());
|
|
3410
4518
|
if (project.isPlugin && project.pluginModule?.dependencies && project.pluginModule.dependencies.length > 0) {
|
|
3411
|
-
const pluginsDir =
|
|
4519
|
+
const pluginsDir = path23.join(process.cwd(), ".eliza", "plugins");
|
|
3412
4520
|
if (!fs11.existsSync(pluginsDir)) {
|
|
3413
4521
|
await fs11.promises.mkdir(pluginsDir, { recursive: true });
|
|
3414
4522
|
}
|
|
3415
|
-
const packageJsonPath =
|
|
4523
|
+
const packageJsonPath = path23.join(pluginsDir, "package.json");
|
|
3416
4524
|
if (!fs11.existsSync(packageJsonPath)) {
|
|
3417
4525
|
const packageJsonContent = {
|
|
3418
4526
|
name: "test-plugin-dependencies",
|
|
@@ -3422,15 +4530,15 @@ async function installPluginDependencies(projectInfo) {
|
|
|
3422
4530
|
};
|
|
3423
4531
|
await fs11.promises.writeFile(packageJsonPath, JSON.stringify(packageJsonContent, null, 2));
|
|
3424
4532
|
}
|
|
3425
|
-
const { installPlugin: installPlugin2 } = await import("./utils-
|
|
4533
|
+
const { installPlugin: installPlugin2 } = await import("./utils-I3EA43DE.js");
|
|
3426
4534
|
for (const dependency of project.pluginModule.dependencies) {
|
|
3427
4535
|
await installPlugin2(dependency, pluginsDir);
|
|
3428
|
-
const dependencyPath =
|
|
4536
|
+
const dependencyPath = path23.join(pluginsDir, "node_modules", dependency);
|
|
3429
4537
|
if (fs11.existsSync(dependencyPath)) {
|
|
3430
4538
|
try {
|
|
3431
4539
|
await runBunCommand(["install"], dependencyPath);
|
|
3432
4540
|
} catch (error) {
|
|
3433
|
-
|
|
4541
|
+
logger20.warn(
|
|
3434
4542
|
`[Test Command] Failed to install devDependencies for ${dependency}: ${error}`
|
|
3435
4543
|
);
|
|
3436
4544
|
}
|
|
@@ -3440,18 +4548,18 @@ async function installPluginDependencies(projectInfo) {
|
|
|
3440
4548
|
}
|
|
3441
4549
|
|
|
3442
4550
|
// src/commands/test/actions/component-tests.ts
|
|
3443
|
-
import { logger as
|
|
4551
|
+
import { logger as logger22 } from "@elizaos/core";
|
|
3444
4552
|
import { spawn as spawn3 } from "child_process";
|
|
3445
|
-
import
|
|
4553
|
+
import path25 from "path";
|
|
3446
4554
|
|
|
3447
4555
|
// src/utils/testing/tsc-validator.ts
|
|
3448
|
-
import { logger as
|
|
4556
|
+
import { logger as logger21 } from "@elizaos/core";
|
|
3449
4557
|
import { execa as execa9 } from "execa";
|
|
3450
|
-
import
|
|
3451
|
-
import { existsSync as
|
|
4558
|
+
import path24 from "path";
|
|
4559
|
+
import { existsSync as existsSync16 } from "fs";
|
|
3452
4560
|
async function runTypeCheck(projectPath, strict = true) {
|
|
3453
|
-
const tsconfigPath =
|
|
3454
|
-
if (!
|
|
4561
|
+
const tsconfigPath = path24.join(projectPath, "tsconfig.json");
|
|
4562
|
+
if (!existsSync16(tsconfigPath)) {
|
|
3455
4563
|
return {
|
|
3456
4564
|
success: false,
|
|
3457
4565
|
errors: [`No tsconfig.json found at ${tsconfigPath}`],
|
|
@@ -3474,7 +4582,7 @@ async function runTypeCheck(projectPath, strict = true) {
|
|
|
3474
4582
|
warnings: stderr.includes("warning") ? [stderr] : []
|
|
3475
4583
|
};
|
|
3476
4584
|
} catch (error) {
|
|
3477
|
-
|
|
4585
|
+
logger21.error("TypeScript validation failed:", error);
|
|
3478
4586
|
return {
|
|
3479
4587
|
success: false,
|
|
3480
4588
|
errors: [`TypeScript validation error: ${error.message}`],
|
|
@@ -3488,37 +4596,39 @@ async function runComponentTests(testPath, options, projectInfo) {
|
|
|
3488
4596
|
const cwd = process.cwd();
|
|
3489
4597
|
const isPlugin2 = projectInfo.type === "elizaos-plugin";
|
|
3490
4598
|
if (!options.skipTypeCheck) {
|
|
3491
|
-
|
|
4599
|
+
logger22.info("Running TypeScript validation...");
|
|
3492
4600
|
const typeCheckResult = await runTypeCheck(cwd, true);
|
|
3493
4601
|
if (!typeCheckResult.success) {
|
|
3494
|
-
|
|
3495
|
-
typeCheckResult.errors.forEach((error) =>
|
|
4602
|
+
logger22.error("TypeScript validation failed:");
|
|
4603
|
+
typeCheckResult.errors.forEach((error) => logger22.error(error));
|
|
3496
4604
|
return { failed: true };
|
|
3497
4605
|
}
|
|
3498
|
-
|
|
4606
|
+
logger22.success("TypeScript validation passed");
|
|
3499
4607
|
}
|
|
3500
4608
|
if (!options.skipBuild) {
|
|
3501
4609
|
try {
|
|
3502
|
-
|
|
4610
|
+
logger22.info(`Building ${isPlugin2 ? "plugin" : "project"}...`);
|
|
3503
4611
|
await buildProject(cwd, isPlugin2);
|
|
3504
|
-
|
|
4612
|
+
logger22.success(`Build completed successfully`);
|
|
3505
4613
|
} catch (buildError) {
|
|
3506
|
-
|
|
4614
|
+
logger22.error(`Build failed: ${buildError}`);
|
|
3507
4615
|
return { failed: true };
|
|
3508
4616
|
}
|
|
3509
4617
|
}
|
|
3510
|
-
|
|
4618
|
+
logger22.info("Running component tests...");
|
|
3511
4619
|
return new Promise((resolve2) => {
|
|
3512
4620
|
const args = ["test", "--passWithNoTests"];
|
|
3513
4621
|
if (options.name) {
|
|
3514
4622
|
const baseName = processFilterName(options.name);
|
|
3515
4623
|
if (baseName) {
|
|
3516
|
-
|
|
4624
|
+
logger22.info(`Using test filter: ${baseName}`);
|
|
3517
4625
|
args.push("-t", baseName);
|
|
3518
4626
|
}
|
|
3519
4627
|
}
|
|
3520
|
-
const
|
|
3521
|
-
|
|
4628
|
+
const monorepoRoot = UserEnvironment.getInstance().findMonorepoRoot(process.cwd());
|
|
4629
|
+
const baseDir = monorepoRoot ?? process.cwd();
|
|
4630
|
+
const targetPath = testPath ? path25.resolve(baseDir, testPath) : process.cwd();
|
|
4631
|
+
logger22.info(`Executing: bun ${args.join(" ")} in ${targetPath}`);
|
|
3522
4632
|
const child = spawn3("bun", args, {
|
|
3523
4633
|
stdio: "inherit",
|
|
3524
4634
|
shell: false,
|
|
@@ -3532,11 +4642,11 @@ async function runComponentTests(testPath, options, projectInfo) {
|
|
|
3532
4642
|
}
|
|
3533
4643
|
});
|
|
3534
4644
|
child.on("close", (code) => {
|
|
3535
|
-
|
|
4645
|
+
logger22.info("Component tests completed");
|
|
3536
4646
|
resolve2({ failed: code !== 0 });
|
|
3537
4647
|
});
|
|
3538
4648
|
child.on("error", (error) => {
|
|
3539
|
-
|
|
4649
|
+
logger22.error("Error running component tests:", error);
|
|
3540
4650
|
resolve2({ failed: true });
|
|
3541
4651
|
});
|
|
3542
4652
|
});
|
|
@@ -3544,31 +4654,31 @@ async function runComponentTests(testPath, options, projectInfo) {
|
|
|
3544
4654
|
|
|
3545
4655
|
// src/commands/test/actions/e2e-tests.ts
|
|
3546
4656
|
import { AgentServer as AgentServer2, jsonToCharacter as jsonToCharacter2, loadCharacterTryPath as loadCharacterTryPath3 } from "@elizaos/server";
|
|
3547
|
-
import { logger as
|
|
3548
|
-
import * as
|
|
4657
|
+
import { logger as logger23 } from "@elizaos/core";
|
|
4658
|
+
import * as dotenv2 from "dotenv";
|
|
3549
4659
|
import * as fs12 from "fs";
|
|
3550
|
-
import
|
|
4660
|
+
import path26 from "path";
|
|
3551
4661
|
async function runE2eTests(testPath, options, projectInfo) {
|
|
3552
4662
|
if (!options.skipBuild) {
|
|
3553
4663
|
try {
|
|
3554
4664
|
const cwd = process.cwd();
|
|
3555
4665
|
const isPlugin2 = projectInfo.type === "elizaos-plugin";
|
|
3556
|
-
|
|
4666
|
+
logger23.info(`Building ${isPlugin2 ? "plugin" : "project"}...`);
|
|
3557
4667
|
await buildProject(cwd, isPlugin2);
|
|
3558
|
-
|
|
4668
|
+
logger23.info(`Build completed successfully`);
|
|
3559
4669
|
} catch (buildError) {
|
|
3560
|
-
|
|
3561
|
-
|
|
4670
|
+
logger23.error(`Build error: ${buildError}`);
|
|
4671
|
+
logger23.warn(`Attempting to continue with tests despite build error`);
|
|
3562
4672
|
}
|
|
3563
4673
|
}
|
|
3564
4674
|
let server;
|
|
3565
4675
|
try {
|
|
3566
4676
|
const runtimes = [];
|
|
3567
4677
|
const projectAgents = [];
|
|
3568
|
-
const elizaDir =
|
|
3569
|
-
const packageName =
|
|
4678
|
+
const elizaDir = path26.join(process.cwd(), ".eliza");
|
|
4679
|
+
const packageName = path26.basename(process.cwd());
|
|
3570
4680
|
const timestamp = Date.now();
|
|
3571
|
-
const uniqueDbDir =
|
|
4681
|
+
const uniqueDbDir = path26.join(process.cwd(), ".elizadb-test", `${packageName}-${timestamp}`);
|
|
3572
4682
|
const elizaDbDir = uniqueDbDir;
|
|
3573
4683
|
const envInfo = await UserEnvironment.getInstanceInfo();
|
|
3574
4684
|
const envFilePath = envInfo.paths.envFilePath;
|
|
@@ -3592,91 +4702,73 @@ async function runE2eTests(testPath, options, projectInfo) {
|
|
|
3592
4702
|
process.env.PGLITE_DATA_DIR = elizaDbDir;
|
|
3593
4703
|
console.info(`Set PGLITE_DATA_DIR to: ${elizaDbDir}`);
|
|
3594
4704
|
if (fs12.existsSync(envFilePath)) {
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
4705
|
+
logger23.info(`Loading environment variables from: ${envFilePath}`);
|
|
4706
|
+
dotenv2.config({ path: envFilePath });
|
|
4707
|
+
logger23.info("Environment variables loaded");
|
|
3598
4708
|
} else {
|
|
3599
|
-
|
|
3600
|
-
}
|
|
3601
|
-
try {
|
|
3602
|
-
logger21.info("Configuring database...");
|
|
3603
|
-
await promptForEnvVars("pglite");
|
|
3604
|
-
logger21.info("Database configuration completed");
|
|
3605
|
-
} catch (error) {
|
|
3606
|
-
logger21.error("Error configuring database:", error);
|
|
3607
|
-
if (error instanceof Error) {
|
|
3608
|
-
logger21.error("Error details:", error.message);
|
|
3609
|
-
logger21.error("Stack trace:", error.stack);
|
|
3610
|
-
}
|
|
3611
|
-
throw error;
|
|
4709
|
+
logger23.warn(`Environment file not found: ${envFilePath}`);
|
|
3612
4710
|
}
|
|
3613
4711
|
const postgresUrl = process.env.POSTGRES_URL;
|
|
3614
|
-
|
|
4712
|
+
logger23.info(
|
|
3615
4713
|
`PostgreSQL URL for e2e tests: ${postgresUrl ? "found" : "not found (will use PGlite)"}`
|
|
3616
4714
|
);
|
|
3617
|
-
|
|
4715
|
+
logger23.info("Creating server instance...");
|
|
3618
4716
|
server = new AgentServer2();
|
|
3619
|
-
|
|
3620
|
-
|
|
4717
|
+
logger23.info("Server instance created");
|
|
4718
|
+
logger23.info("Initializing server...");
|
|
3621
4719
|
try {
|
|
3622
4720
|
await server.initialize({
|
|
3623
4721
|
dataDir: elizaDbDir,
|
|
3624
4722
|
postgresUrl
|
|
3625
4723
|
});
|
|
3626
|
-
|
|
4724
|
+
logger23.info("Server initialized successfully");
|
|
3627
4725
|
} catch (initError) {
|
|
3628
|
-
|
|
4726
|
+
logger23.error("Server initialization failed:", initError);
|
|
3629
4727
|
throw initError;
|
|
3630
4728
|
}
|
|
3631
4729
|
let project;
|
|
3632
4730
|
try {
|
|
3633
|
-
|
|
4731
|
+
logger23.info("Attempting to load project or plugin...");
|
|
3634
4732
|
const monorepoRoot = UserEnvironment.getInstance().findMonorepoRoot(process.cwd());
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
"Could not find monorepo root. Make sure to run tests from within the Eliza project."
|
|
3638
|
-
);
|
|
3639
|
-
}
|
|
3640
|
-
const targetPath = testPath ? path25.resolve(monorepoRoot, testPath) : process.cwd();
|
|
4733
|
+
const baseDir = monorepoRoot ?? process.cwd();
|
|
4734
|
+
const targetPath = testPath ? path26.resolve(baseDir, testPath) : process.cwd();
|
|
3641
4735
|
project = await loadProject(targetPath);
|
|
3642
4736
|
if (!project || !project.agents || project.agents.length === 0) {
|
|
3643
4737
|
throw new Error("No agents found in project configuration");
|
|
3644
4738
|
}
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
);
|
|
3648
|
-
logger21.info("Setting up server properties...");
|
|
4739
|
+
logger23.info(`Found ${project.agents.length} agents`);
|
|
4740
|
+
logger23.info("Setting up server properties...");
|
|
3649
4741
|
server.startAgent = async (character) => {
|
|
3650
|
-
|
|
4742
|
+
logger23.info(`Starting agent for character ${character.name}`);
|
|
3651
4743
|
return startAgent(character, server, void 0, [], { isTestMode: true });
|
|
3652
4744
|
};
|
|
3653
4745
|
server.loadCharacterTryPath = loadCharacterTryPath3;
|
|
3654
4746
|
server.jsonToCharacter = jsonToCharacter2;
|
|
3655
|
-
|
|
4747
|
+
logger23.info("Server properties set up");
|
|
3656
4748
|
const desiredPort = options.port || Number.parseInt(process.env.SERVER_PORT || "3000");
|
|
3657
4749
|
const serverPort = await findNextAvailablePort(desiredPort);
|
|
3658
4750
|
if (serverPort !== desiredPort) {
|
|
3659
|
-
|
|
4751
|
+
logger23.warn(`Port ${desiredPort} is in use for testing, using port ${serverPort} instead.`);
|
|
3660
4752
|
}
|
|
3661
|
-
|
|
4753
|
+
logger23.info("Starting server...");
|
|
3662
4754
|
try {
|
|
3663
4755
|
await server.start(serverPort);
|
|
3664
|
-
|
|
4756
|
+
logger23.info("Server started successfully on port", serverPort);
|
|
3665
4757
|
} catch (error) {
|
|
3666
|
-
|
|
4758
|
+
logger23.error("Error starting server:", error);
|
|
3667
4759
|
if (error instanceof Error) {
|
|
3668
|
-
|
|
3669
|
-
|
|
4760
|
+
logger23.error("Error details:", error.message);
|
|
4761
|
+
logger23.error("Stack trace:", error.stack);
|
|
3670
4762
|
}
|
|
3671
4763
|
throw error;
|
|
3672
4764
|
}
|
|
3673
4765
|
try {
|
|
3674
|
-
|
|
4766
|
+
logger23.info(
|
|
3675
4767
|
`Found ${project.agents.length} agents in ${project.isPlugin ? "plugin" : "project"}`
|
|
3676
4768
|
);
|
|
3677
4769
|
if (project.isPlugin || project.agents.length === 0) {
|
|
3678
4770
|
process.env.ELIZA_TESTING_PLUGIN = "true";
|
|
3679
|
-
|
|
4771
|
+
logger23.info("Using default Eliza character as test agent");
|
|
3680
4772
|
try {
|
|
3681
4773
|
const pluginUnderTest = project.pluginModule;
|
|
3682
4774
|
if (!pluginUnderTest) {
|
|
@@ -3699,16 +4791,16 @@ async function runE2eTests(testPath, options, projectInfo) {
|
|
|
3699
4791
|
plugins: runtime.plugins
|
|
3700
4792
|
// Pass all plugins, not just the one under test
|
|
3701
4793
|
});
|
|
3702
|
-
|
|
4794
|
+
logger23.info("Default test agent started successfully");
|
|
3703
4795
|
} catch (pluginError) {
|
|
3704
|
-
|
|
4796
|
+
logger23.error(`Error starting plugin test agent: ${pluginError}`);
|
|
3705
4797
|
throw pluginError;
|
|
3706
4798
|
}
|
|
3707
4799
|
} else {
|
|
3708
4800
|
for (const agent2 of project.agents) {
|
|
3709
4801
|
try {
|
|
3710
4802
|
const originalCharacter = { ...agent2.character };
|
|
3711
|
-
|
|
4803
|
+
logger23.debug(`Starting agent: ${originalCharacter.name}`);
|
|
3712
4804
|
const runtime = await startAgent(
|
|
3713
4805
|
originalCharacter,
|
|
3714
4806
|
server,
|
|
@@ -3721,28 +4813,28 @@ async function runE2eTests(testPath, options, projectInfo) {
|
|
|
3721
4813
|
projectAgents.push(agent2);
|
|
3722
4814
|
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
3723
4815
|
} catch (agentError) {
|
|
3724
|
-
|
|
4816
|
+
logger23.error(`Error starting agent ${agent2.character.name}:`, agentError);
|
|
3725
4817
|
if (agentError instanceof Error) {
|
|
3726
|
-
|
|
3727
|
-
|
|
4818
|
+
logger23.error("Error details:", agentError.message);
|
|
4819
|
+
logger23.error("Stack trace:", agentError.stack);
|
|
3728
4820
|
}
|
|
3729
|
-
|
|
4821
|
+
logger23.warn(`Skipping agent ${agent2.character.name} due to startup error`);
|
|
3730
4822
|
}
|
|
3731
4823
|
}
|
|
3732
4824
|
}
|
|
3733
4825
|
if (runtimes.length === 0) {
|
|
3734
4826
|
throw new Error("Failed to start any agents from project");
|
|
3735
4827
|
}
|
|
3736
|
-
|
|
4828
|
+
logger23.debug(`Successfully started ${runtimes.length} agents for testing`);
|
|
3737
4829
|
let totalFailed = 0;
|
|
3738
4830
|
let anyTestsFound = false;
|
|
3739
4831
|
for (let i = 0; i < runtimes.length; i++) {
|
|
3740
4832
|
const runtime = runtimes[i];
|
|
3741
4833
|
const projectAgent = projectAgents[i];
|
|
3742
4834
|
if (project.isPlugin) {
|
|
3743
|
-
|
|
4835
|
+
logger23.debug(`Running tests for plugin: ${project.pluginModule?.name}`);
|
|
3744
4836
|
} else {
|
|
3745
|
-
|
|
4837
|
+
logger23.debug(`Running tests for agent: ${runtime.character.name}`);
|
|
3746
4838
|
}
|
|
3747
4839
|
const testRunner = new TestRunner(runtime, projectAgent);
|
|
3748
4840
|
const currentDirInfo = projectInfo;
|
|
@@ -3763,17 +4855,17 @@ async function runE2eTests(testPath, options, projectInfo) {
|
|
|
3763
4855
|
}
|
|
3764
4856
|
return { failed: anyTestsFound ? totalFailed > 0 : false };
|
|
3765
4857
|
} catch (error) {
|
|
3766
|
-
|
|
4858
|
+
logger23.error("Error in runE2eTests:", error);
|
|
3767
4859
|
if (error instanceof Error) {
|
|
3768
|
-
|
|
3769
|
-
|
|
4860
|
+
logger23.error("Error details:", error.message);
|
|
4861
|
+
logger23.error("Stack trace:", error.stack);
|
|
3770
4862
|
} else {
|
|
3771
|
-
|
|
3772
|
-
|
|
4863
|
+
logger23.error("Unknown error type:", typeof error);
|
|
4864
|
+
logger23.error("Error value:", error);
|
|
3773
4865
|
try {
|
|
3774
|
-
|
|
4866
|
+
logger23.error("Stringified error:", JSON.stringify(error, null, 2));
|
|
3775
4867
|
} catch (e) {
|
|
3776
|
-
|
|
4868
|
+
logger23.error("Could not stringify error:", e);
|
|
3777
4869
|
}
|
|
3778
4870
|
}
|
|
3779
4871
|
return { failed: true };
|
|
@@ -3787,7 +4879,7 @@ async function runE2eTests(testPath, options, projectInfo) {
|
|
|
3787
4879
|
fs12.rmSync(elizaDbDir, { recursive: true, force: true });
|
|
3788
4880
|
console.info(`Successfully cleaned up test database directory`);
|
|
3789
4881
|
}
|
|
3790
|
-
const testDir =
|
|
4882
|
+
const testDir = path26.dirname(elizaDbDir);
|
|
3791
4883
|
if (fs12.existsSync(testDir) && fs12.readdirSync(testDir).length === 0) {
|
|
3792
4884
|
fs12.rmSync(testDir, { recursive: true, force: true });
|
|
3793
4885
|
}
|
|
@@ -3796,33 +4888,33 @@ async function runE2eTests(testPath, options, projectInfo) {
|
|
|
3796
4888
|
}
|
|
3797
4889
|
}
|
|
3798
4890
|
} catch (error) {
|
|
3799
|
-
|
|
4891
|
+
logger23.error("Error in runE2eTests:", error);
|
|
3800
4892
|
if (error instanceof Error) {
|
|
3801
|
-
|
|
3802
|
-
|
|
4893
|
+
logger23.error("Error details:", error.message);
|
|
4894
|
+
logger23.error("Stack trace:", error.stack);
|
|
3803
4895
|
} else {
|
|
3804
|
-
|
|
3805
|
-
|
|
4896
|
+
logger23.error("Unknown error type:", typeof error);
|
|
4897
|
+
logger23.error("Error value:", error);
|
|
3806
4898
|
try {
|
|
3807
|
-
|
|
4899
|
+
logger23.error("Stringified error:", JSON.stringify(error, null, 2));
|
|
3808
4900
|
} catch (e) {
|
|
3809
|
-
|
|
4901
|
+
logger23.error("Could not stringify error:", e);
|
|
3810
4902
|
}
|
|
3811
4903
|
}
|
|
3812
4904
|
return { failed: true };
|
|
3813
4905
|
}
|
|
3814
4906
|
} catch (error) {
|
|
3815
|
-
|
|
4907
|
+
logger23.error("Error in runE2eTests:", error);
|
|
3816
4908
|
if (error instanceof Error) {
|
|
3817
|
-
|
|
3818
|
-
|
|
4909
|
+
logger23.error("Error details:", error.message);
|
|
4910
|
+
logger23.error("Stack trace:", error.stack);
|
|
3819
4911
|
} else {
|
|
3820
|
-
|
|
3821
|
-
|
|
4912
|
+
logger23.error("Unknown error type:", typeof error);
|
|
4913
|
+
logger23.error("Error value:", error);
|
|
3822
4914
|
try {
|
|
3823
|
-
|
|
4915
|
+
logger23.error("Stringified error:", JSON.stringify(error, null, 2));
|
|
3824
4916
|
} catch (e) {
|
|
3825
|
-
|
|
4917
|
+
logger23.error("Could not stringify error:", e);
|
|
3826
4918
|
}
|
|
3827
4919
|
}
|
|
3828
4920
|
return { failed: true };
|
|
@@ -3835,15 +4927,15 @@ async function runAllTests(testPath, options) {
|
|
|
3835
4927
|
if (!options.skipBuild) {
|
|
3836
4928
|
const componentResult = await runComponentTests(testPath, options, projectInfo);
|
|
3837
4929
|
if (componentResult.failed) {
|
|
3838
|
-
|
|
4930
|
+
logger24.error("Component tests failed. Continuing to e2e tests...");
|
|
3839
4931
|
}
|
|
3840
4932
|
}
|
|
3841
4933
|
const e2eResult = await runE2eTests(testPath, options, projectInfo);
|
|
3842
4934
|
if (e2eResult.failed) {
|
|
3843
|
-
|
|
4935
|
+
logger24.error("E2E tests failed.");
|
|
3844
4936
|
process.exit(1);
|
|
3845
4937
|
}
|
|
3846
|
-
|
|
4938
|
+
logger24.success("All tests passed successfully!");
|
|
3847
4939
|
process.exit(0);
|
|
3848
4940
|
}
|
|
3849
4941
|
|
|
@@ -3851,9 +4943,9 @@ async function runAllTests(testPath, options) {
|
|
|
3851
4943
|
import * as net from "net";
|
|
3852
4944
|
|
|
3853
4945
|
// src/commands/test/utils/plugin-utils.ts
|
|
3854
|
-
import { logger as
|
|
4946
|
+
import { logger as logger25 } from "@elizaos/core";
|
|
3855
4947
|
import * as fs13 from "fs";
|
|
3856
|
-
import
|
|
4948
|
+
import path27 from "path";
|
|
3857
4949
|
|
|
3858
4950
|
// src/commands/test/index.ts
|
|
3859
4951
|
var test = new Command10().name("test").description("Run tests for the current project or a specified plugin").argument("[path]", "Optional path to the project or plugin to test").addOption(
|
|
@@ -3863,31 +4955,31 @@ var test = new Command10().name("test").description("Run tests for the current p
|
|
|
3863
4955
|
const projectInfo = getProjectType(testPath);
|
|
3864
4956
|
await installPluginDependencies(projectInfo);
|
|
3865
4957
|
}).action(async (testPath, options) => {
|
|
3866
|
-
|
|
4958
|
+
logger26.info("Starting tests...");
|
|
3867
4959
|
try {
|
|
3868
4960
|
const projectInfo = getProjectType(testPath);
|
|
3869
4961
|
switch (options.type) {
|
|
3870
4962
|
case "component":
|
|
3871
|
-
|
|
4963
|
+
logger26.info("Running component tests only...");
|
|
3872
4964
|
const componentResult = await runComponentTests(testPath, options, projectInfo);
|
|
3873
4965
|
if (componentResult.failed) {
|
|
3874
|
-
|
|
4966
|
+
logger26.error("Component tests failed.");
|
|
3875
4967
|
process.exit(1);
|
|
3876
4968
|
}
|
|
3877
|
-
|
|
4969
|
+
logger26.success("Component tests passed successfully!");
|
|
3878
4970
|
break;
|
|
3879
4971
|
case "e2e":
|
|
3880
|
-
|
|
4972
|
+
logger26.info("Running e2e tests only...");
|
|
3881
4973
|
const e2eResult = await runE2eTests(testPath, options, projectInfo);
|
|
3882
4974
|
if (e2eResult.failed) {
|
|
3883
|
-
|
|
4975
|
+
logger26.error("E2E tests failed.");
|
|
3884
4976
|
process.exit(1);
|
|
3885
4977
|
}
|
|
3886
|
-
|
|
4978
|
+
logger26.success("E2E tests passed successfully!");
|
|
3887
4979
|
break;
|
|
3888
4980
|
case "all":
|
|
3889
4981
|
default:
|
|
3890
|
-
|
|
4982
|
+
logger26.info("Running all tests...");
|
|
3891
4983
|
await runAllTests(testPath, options);
|
|
3892
4984
|
break;
|
|
3893
4985
|
}
|
|
@@ -3898,11 +4990,8 @@ var test = new Command10().name("test").description("Run tests for the current p
|
|
|
3898
4990
|
});
|
|
3899
4991
|
|
|
3900
4992
|
// src/index.ts
|
|
3901
|
-
import { logger as
|
|
4993
|
+
import { logger as logger27 } from "@elizaos/core";
|
|
3902
4994
|
import { Command as Command11 } from "commander";
|
|
3903
|
-
import { existsSync as existsSync17, readFileSync as readFileSync5 } from "fs";
|
|
3904
|
-
import path27, { dirname } from "path";
|
|
3905
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3906
4995
|
process.env.NODE_OPTIONS = "--no-deprecation";
|
|
3907
4996
|
process.env.NODE_NO_WARNINGS = "1";
|
|
3908
4997
|
process.on("SIGINT", () => process.exit(0));
|
|
@@ -3914,15 +5003,7 @@ async function main() {
|
|
|
3914
5003
|
if (process.argv.includes("--no-auto-install")) {
|
|
3915
5004
|
process.env.ELIZA_NO_AUTO_INSTALL = "true";
|
|
3916
5005
|
}
|
|
3917
|
-
const
|
|
3918
|
-
const __dirname = dirname(__filename);
|
|
3919
|
-
const packageJsonPath = path27.resolve(__dirname, "../package.json");
|
|
3920
|
-
let version = "0.0.0";
|
|
3921
|
-
if (!existsSync17(packageJsonPath)) {
|
|
3922
|
-
} else {
|
|
3923
|
-
const packageJson = JSON.parse(readFileSync5(packageJsonPath, "utf-8"));
|
|
3924
|
-
version = packageJson.version;
|
|
3925
|
-
}
|
|
5006
|
+
const version = getVersion();
|
|
3926
5007
|
const args = process.argv.slice(2);
|
|
3927
5008
|
const isUpdateCommand = args.includes("update");
|
|
3928
5009
|
const willShowBanner = args.length === 0;
|
|
@@ -3938,6 +5019,6 @@ async function main() {
|
|
|
3938
5019
|
await program.parseAsync();
|
|
3939
5020
|
}
|
|
3940
5021
|
main().catch((error) => {
|
|
3941
|
-
|
|
5022
|
+
logger27.error("An error occurred:", error);
|
|
3942
5023
|
process.exit(1);
|
|
3943
5024
|
});
|