genlayer 0.0.28 → 0.0.30
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/CHANGELOG.md +4 -0
- package/dist/index.js +148 -30
- package/package.json +1 -1
- package/src/commands/general/index.ts +1 -0
- package/src/commands/general/init.ts +17 -2
- package/src/commands/general/start.ts +25 -3
- package/src/lib/clients/system.ts +52 -18
- package/src/lib/config/simulator.ts +17 -7
- package/src/lib/services/simulator.ts +60 -9
package/CHANGELOG.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -39896,7 +39896,7 @@ var {
|
|
|
39896
39896
|
} = import_index.default;
|
|
39897
39897
|
|
|
39898
39898
|
// package.json
|
|
39899
|
-
var version = "0.0.
|
|
39899
|
+
var version = "0.0.30";
|
|
39900
39900
|
|
|
39901
39901
|
// src/lib/config/text.ts
|
|
39902
39902
|
var CLI_DESCRIPTION = "GenLayer CLI is a development environment for the GenLayer ecosystem. It allows developers to interact with the protocol by creating accounts, sending transactions, and working with Intelligent Contracts by testing, debugging, and deploying them.";
|
|
@@ -42491,6 +42491,7 @@ var inquirer_default = inquirer;
|
|
|
42491
42491
|
// src/lib/config/simulator.ts
|
|
42492
42492
|
var DEFAULT_JSON_RPC_URL = "http://localhost:4000/api";
|
|
42493
42493
|
var DEFAULT_REPO_GH_URL = "https://github.com/yeagerai/genlayer-simulator.git";
|
|
42494
|
+
var DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX = "genlayer-simulator-";
|
|
42494
42495
|
var DEFAULT_RUN_SIMULATOR_COMMAND = (simulatorLocation) => ({
|
|
42495
42496
|
darwin: `osascript -e 'tell application "Terminal" to do script "cd ${simulatorLocation} && docker compose build && docker compose up"'`,
|
|
42496
42497
|
win32: `start cmd.exe /c "cd /d ${simulatorLocation} && docker compose build && docker compose up && pause"`,
|
|
@@ -42501,23 +42502,31 @@ var DEFAULT_PULL_OLLAMA_COMMAND = (simulatorLocation) => ({
|
|
|
42501
42502
|
win32: `cd /d ${simulatorLocation} && docker exec ollama ollama pull llama3`,
|
|
42502
42503
|
linux: `cd ${simulatorLocation} && docker exec ollama ollama pull llama3`
|
|
42503
42504
|
});
|
|
42505
|
+
var DEFAULT_RUN_DOCKER_COMMAND = {
|
|
42506
|
+
darwin: "open -a Docker",
|
|
42507
|
+
win32: 'start "" "C:\\Program Files\\Docker\\Docker\\Docker Desktop.exe"',
|
|
42508
|
+
linux: "sudo systemctl start docker"
|
|
42509
|
+
};
|
|
42504
42510
|
var AVAILABLE_PLATFORMS = ["darwin", "win32", "linux"];
|
|
42505
42511
|
var STARTING_TIMEOUT_WAIT_CYLCE = 2e3;
|
|
42506
42512
|
var STARTING_TIMEOUT_ATTEMPTS = 120;
|
|
42507
42513
|
var AI_PROVIDERS_CONFIG = {
|
|
42508
42514
|
ollama: {
|
|
42509
|
-
name: "Ollama
|
|
42515
|
+
name: "Ollama",
|
|
42516
|
+
hint: "(This will download and run a local instance of Llama 3)",
|
|
42510
42517
|
cliOptionValue: "ollama"
|
|
42511
42518
|
},
|
|
42512
42519
|
openai: {
|
|
42513
|
-
name: "OpenAI
|
|
42520
|
+
name: "OpenAI",
|
|
42521
|
+
hint: "(You will need to provide an OpenAI API key)",
|
|
42514
42522
|
envVar: "OPENAIKEY",
|
|
42515
42523
|
cliOptionValue: "openai"
|
|
42516
42524
|
},
|
|
42517
|
-
|
|
42518
|
-
name:
|
|
42525
|
+
heuristai: {
|
|
42526
|
+
name: "Heurist",
|
|
42527
|
+
hint: '(You will need to provide an API key. Get free API credits at https://dev-api-form.heurist.ai/ with referral code: "genlayer")',
|
|
42519
42528
|
envVar: "HEURISTAIAPIKEY",
|
|
42520
|
-
cliOptionValue: "
|
|
42529
|
+
cliOptionValue: "heuristai"
|
|
42521
42530
|
}
|
|
42522
42531
|
};
|
|
42523
42532
|
|
|
@@ -44384,21 +44393,12 @@ function checkCommand(command, toolName) {
|
|
|
44384
44393
|
});
|
|
44385
44394
|
}
|
|
44386
44395
|
function executeCommand(cmdsByPlatform, toolName) {
|
|
44387
|
-
try {
|
|
44388
|
-
const runningPlatform = getPlatform();
|
|
44389
|
-
const command = cmdsByPlatform[runningPlatform];
|
|
44390
|
-
return asyncExec(command);
|
|
44391
|
-
} catch (error) {
|
|
44392
|
-
throw new Error(`Error executing ${toolName}: ${error.message}`);
|
|
44393
|
-
}
|
|
44394
|
-
}
|
|
44395
|
-
function executeCommandInNewTerminal(cmdsByPlatform) {
|
|
44396
44396
|
const runningPlatform = getPlatform();
|
|
44397
44397
|
const command = cmdsByPlatform[runningPlatform];
|
|
44398
44398
|
try {
|
|
44399
44399
|
return asyncExec(command);
|
|
44400
44400
|
} catch (error) {
|
|
44401
|
-
throw new Error(`Error executing command ${
|
|
44401
|
+
throw new Error(`Error executing ${toolName || command}: ${error.message}.`);
|
|
44402
44402
|
}
|
|
44403
44403
|
}
|
|
44404
44404
|
function getHomeDirectory() {
|
|
@@ -44407,13 +44407,64 @@ function getHomeDirectory() {
|
|
|
44407
44407
|
function getPlatform() {
|
|
44408
44408
|
const currentPlatform = process.platform;
|
|
44409
44409
|
if (!AVAILABLE_PLATFORMS.includes(currentPlatform)) {
|
|
44410
|
-
throw new Error(`Unsupported platform: ${currentPlatform}
|
|
44410
|
+
throw new Error(`Unsupported platform: ${currentPlatform}.`);
|
|
44411
44411
|
}
|
|
44412
44412
|
return currentPlatform;
|
|
44413
44413
|
}
|
|
44414
44414
|
function openUrl(url) {
|
|
44415
44415
|
return open_default(url);
|
|
44416
44416
|
}
|
|
44417
|
+
function listDockerContainers() {
|
|
44418
|
+
return __async(this, null, function* () {
|
|
44419
|
+
try {
|
|
44420
|
+
const dockerResponse = yield asyncExec("docker ps -a --format '{{.Names}}'");
|
|
44421
|
+
const dockerContainers = dockerResponse.stdout.split("\n");
|
|
44422
|
+
return dockerContainers;
|
|
44423
|
+
} catch (error) {
|
|
44424
|
+
throw new Error("Error listing Docker containers.");
|
|
44425
|
+
}
|
|
44426
|
+
return [];
|
|
44427
|
+
});
|
|
44428
|
+
}
|
|
44429
|
+
function listDockerImages() {
|
|
44430
|
+
return __async(this, null, function* () {
|
|
44431
|
+
try {
|
|
44432
|
+
const dockerResponse = yield asyncExec("docker images --format '{{.Repository}}'");
|
|
44433
|
+
const dockerImages = dockerResponse.stdout.split("\n");
|
|
44434
|
+
return dockerImages;
|
|
44435
|
+
} catch (error) {
|
|
44436
|
+
throw new Error("Error listing Docker images.");
|
|
44437
|
+
}
|
|
44438
|
+
return [];
|
|
44439
|
+
});
|
|
44440
|
+
}
|
|
44441
|
+
function stopDockerContainer(containerName) {
|
|
44442
|
+
return __async(this, null, function* () {
|
|
44443
|
+
try {
|
|
44444
|
+
yield asyncExec(`docker stop ${containerName}`);
|
|
44445
|
+
} catch (error) {
|
|
44446
|
+
throw new Error(`Error stopping Docker container ${containerName}.`);
|
|
44447
|
+
}
|
|
44448
|
+
});
|
|
44449
|
+
}
|
|
44450
|
+
function removeDockerContainer(containerName) {
|
|
44451
|
+
return __async(this, null, function* () {
|
|
44452
|
+
try {
|
|
44453
|
+
yield asyncExec(`docker rm ${containerName}`);
|
|
44454
|
+
} catch (error) {
|
|
44455
|
+
throw new Error(`Error removing container ${containerName}.`);
|
|
44456
|
+
}
|
|
44457
|
+
});
|
|
44458
|
+
}
|
|
44459
|
+
function removeDockerImage(imageName) {
|
|
44460
|
+
return __async(this, null, function* () {
|
|
44461
|
+
try {
|
|
44462
|
+
yield asyncExec(`docker rmi ${imageName}`);
|
|
44463
|
+
} catch (error) {
|
|
44464
|
+
throw new Error(`Error removing image ${imageName}.`);
|
|
44465
|
+
}
|
|
44466
|
+
});
|
|
44467
|
+
}
|
|
44417
44468
|
|
|
44418
44469
|
// src/lib/services/simulator.ts
|
|
44419
44470
|
function getSimulatorLocation() {
|
|
@@ -44463,6 +44514,13 @@ function checkRequirements() {
|
|
|
44463
44514
|
throw error;
|
|
44464
44515
|
}
|
|
44465
44516
|
}
|
|
44517
|
+
if (requirementsInstalled.docker) {
|
|
44518
|
+
try {
|
|
44519
|
+
yield checkCommand("docker ps", "docker");
|
|
44520
|
+
} catch (error) {
|
|
44521
|
+
yield executeCommand(DEFAULT_RUN_DOCKER_COMMAND);
|
|
44522
|
+
}
|
|
44523
|
+
}
|
|
44466
44524
|
return requirementsInstalled;
|
|
44467
44525
|
});
|
|
44468
44526
|
}
|
|
@@ -44496,7 +44554,7 @@ function pullOllamaModel() {
|
|
|
44496
44554
|
return __async(this, null, function* () {
|
|
44497
44555
|
const simulatorLocation = getSimulatorLocation();
|
|
44498
44556
|
const cmdsByPlatform = DEFAULT_PULL_OLLAMA_COMMAND(simulatorLocation);
|
|
44499
|
-
yield
|
|
44557
|
+
yield executeCommand(cmdsByPlatform);
|
|
44500
44558
|
return true;
|
|
44501
44559
|
});
|
|
44502
44560
|
}
|
|
@@ -44513,7 +44571,7 @@ function configSimulator(newConfig) {
|
|
|
44513
44571
|
function runSimulator() {
|
|
44514
44572
|
const simulatorLocation = getSimulatorLocation();
|
|
44515
44573
|
const commandsByPlatform = DEFAULT_RUN_SIMULATOR_COMMAND(simulatorLocation);
|
|
44516
|
-
return
|
|
44574
|
+
return executeCommand(commandsByPlatform);
|
|
44517
44575
|
}
|
|
44518
44576
|
function waitForSimulatorToBeReady() {
|
|
44519
44577
|
return __async(this, arguments, function* (retries = STARTING_TIMEOUT_ATTEMPTS) {
|
|
@@ -44528,7 +44586,7 @@ function waitForSimulatorToBeReady() {
|
|
|
44528
44586
|
return waitForSimulatorToBeReady(retries - 1);
|
|
44529
44587
|
}
|
|
44530
44588
|
} catch (error) {
|
|
44531
|
-
if ((error.message.includes("ECONNRESET") || error.message.includes("ECONNREFUSED") || error.message.includes("socket hang up")) && retries > 0) {
|
|
44589
|
+
if ((error.name === "FetchError" || error.message.includes("ECONNRESET") || error.message.includes("ECONNREFUSED") || error.message.includes("socket hang up")) && retries > 0) {
|
|
44532
44590
|
yield sleep(STARTING_TIMEOUT_WAIT_CYLCE * 2);
|
|
44533
44591
|
return waitForSimulatorToBeReady(retries - 1);
|
|
44534
44592
|
}
|
|
@@ -44547,15 +44605,21 @@ function initializeDatabase() {
|
|
|
44547
44605
|
return { createResponse, tablesResponse };
|
|
44548
44606
|
});
|
|
44549
44607
|
}
|
|
44550
|
-
function createRandomValidators(numValidators) {
|
|
44551
|
-
return rpcClient.request({
|
|
44608
|
+
function createRandomValidators(numValidators, llmProviders) {
|
|
44609
|
+
return rpcClient.request({
|
|
44610
|
+
method: "create_random_validators",
|
|
44611
|
+
params: [numValidators, 1, 10, llmProviders]
|
|
44612
|
+
});
|
|
44552
44613
|
}
|
|
44553
44614
|
function deleteAllValidators() {
|
|
44554
44615
|
return rpcClient.request({ method: "delete_all_validators", params: [] });
|
|
44555
44616
|
}
|
|
44556
|
-
function getAiProvidersOptions() {
|
|
44617
|
+
function getAiProvidersOptions(withHint = true) {
|
|
44557
44618
|
return Object.values(AI_PROVIDERS_CONFIG).map((providerConfig) => {
|
|
44558
|
-
return {
|
|
44619
|
+
return {
|
|
44620
|
+
name: `${providerConfig.name}${withHint ? ` ${providerConfig.hint}` : ""}`,
|
|
44621
|
+
value: providerConfig.cliOptionValue
|
|
44622
|
+
};
|
|
44559
44623
|
});
|
|
44560
44624
|
}
|
|
44561
44625
|
function getFrontendUrl() {
|
|
@@ -44568,6 +44632,34 @@ function openFrontend() {
|
|
|
44568
44632
|
return true;
|
|
44569
44633
|
});
|
|
44570
44634
|
}
|
|
44635
|
+
function resetDockerContainers() {
|
|
44636
|
+
return __async(this, null, function* () {
|
|
44637
|
+
const containers = yield listDockerContainers();
|
|
44638
|
+
const genlayerContainers = containers.filter(
|
|
44639
|
+
(container) => container.startsWith(DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX)
|
|
44640
|
+
);
|
|
44641
|
+
const containersStopPromises = genlayerContainers.map(
|
|
44642
|
+
(container) => stopDockerContainer(container)
|
|
44643
|
+
);
|
|
44644
|
+
yield Promise.all(containersStopPromises);
|
|
44645
|
+
const containersRemovePromises = genlayerContainers.map(
|
|
44646
|
+
(container) => removeDockerContainer(container)
|
|
44647
|
+
);
|
|
44648
|
+
yield Promise.all(containersRemovePromises);
|
|
44649
|
+
return true;
|
|
44650
|
+
});
|
|
44651
|
+
}
|
|
44652
|
+
function resetDockerImages() {
|
|
44653
|
+
return __async(this, null, function* () {
|
|
44654
|
+
const images = yield listDockerImages();
|
|
44655
|
+
const genlayerImages = images.filter(
|
|
44656
|
+
(image) => image.startsWith(DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX)
|
|
44657
|
+
);
|
|
44658
|
+
const imagesRemovePromises = genlayerImages.map((image) => removeDockerImage(image));
|
|
44659
|
+
yield Promise.all(imagesRemovePromises);
|
|
44660
|
+
return true;
|
|
44661
|
+
});
|
|
44662
|
+
}
|
|
44571
44663
|
|
|
44572
44664
|
// src/commands/general/init.ts
|
|
44573
44665
|
function getRequirementsErrorMessage({ git, docker }) {
|
|
@@ -44589,6 +44681,9 @@ function initAction(options) {
|
|
|
44589
44681
|
const { git, docker } = yield checkRequirements();
|
|
44590
44682
|
const errorMessage = getRequirementsErrorMessage({ git, docker });
|
|
44591
44683
|
if (errorMessage) {
|
|
44684
|
+
console.log(
|
|
44685
|
+
"There was a problem running the docker service. Please start the docker service and try again."
|
|
44686
|
+
);
|
|
44592
44687
|
console.error(errorMessage);
|
|
44593
44688
|
return;
|
|
44594
44689
|
}
|
|
@@ -44596,6 +44691,14 @@ function initAction(options) {
|
|
|
44596
44691
|
console.error(error);
|
|
44597
44692
|
return;
|
|
44598
44693
|
}
|
|
44694
|
+
console.log(`Resetting Docker containers and images...`);
|
|
44695
|
+
try {
|
|
44696
|
+
yield resetDockerContainers();
|
|
44697
|
+
yield resetDockerImages();
|
|
44698
|
+
} catch (error) {
|
|
44699
|
+
console.error(error);
|
|
44700
|
+
return;
|
|
44701
|
+
}
|
|
44599
44702
|
const answers = yield inquirer_default.prompt([
|
|
44600
44703
|
{
|
|
44601
44704
|
type: "confirm",
|
|
@@ -44623,7 +44726,7 @@ function initAction(options) {
|
|
|
44623
44726
|
type: "checkbox",
|
|
44624
44727
|
name: "selectedLlmProviders",
|
|
44625
44728
|
message: "Select which LLM providers do you want to use:",
|
|
44626
|
-
choices: getAiProvidersOptions(),
|
|
44729
|
+
choices: getAiProvidersOptions(true),
|
|
44627
44730
|
validate: function(answer) {
|
|
44628
44731
|
if (answer.length < 1) {
|
|
44629
44732
|
return "You must choose at least one option.";
|
|
@@ -44708,7 +44811,7 @@ function initAction(options) {
|
|
|
44708
44811
|
console.log("Initializing validators...");
|
|
44709
44812
|
try {
|
|
44710
44813
|
yield deleteAllValidators();
|
|
44711
|
-
yield createRandomValidators(Number(options.numValidators));
|
|
44814
|
+
yield createRandomValidators(Number(options.numValidators), selectedLlmProviders);
|
|
44712
44815
|
} catch (error) {
|
|
44713
44816
|
console.error("Unable to initialize the validators.");
|
|
44714
44817
|
console.error(error);
|
|
@@ -44728,9 +44831,9 @@ function initAction(options) {
|
|
|
44728
44831
|
// src/commands/general/start.ts
|
|
44729
44832
|
function startAction(options) {
|
|
44730
44833
|
return __async(this, null, function* () {
|
|
44731
|
-
const { resetAccounts, resetValidators } = options;
|
|
44834
|
+
const { resetAccounts, resetValidators, numValidators } = options;
|
|
44732
44835
|
const restartAccountsHintText = resetAccounts ? "restarting the accounts and transactions database" : "keeping the accounts and transactions records";
|
|
44733
|
-
const restartValidatorsHintText = resetValidators ?
|
|
44836
|
+
const restartValidatorsHintText = resetValidators ? `and creating new ${numValidators} random validators` : "and keeping the existing validators";
|
|
44734
44837
|
console.log(`Starting GenLayer simulator ${restartAccountsHintText} ${restartValidatorsHintText}`);
|
|
44735
44838
|
console.log(`Updating GenLayer Simulator...`);
|
|
44736
44839
|
try {
|
|
@@ -44783,7 +44886,22 @@ function startAction(options) {
|
|
|
44783
44886
|
console.log("Initializing validators...");
|
|
44784
44887
|
try {
|
|
44785
44888
|
yield deleteAllValidators();
|
|
44786
|
-
|
|
44889
|
+
const questions = [
|
|
44890
|
+
{
|
|
44891
|
+
type: "checkbox",
|
|
44892
|
+
name: "selectedLlmProviders",
|
|
44893
|
+
message: "Select which LLM providers do you want to use:",
|
|
44894
|
+
choices: getAiProvidersOptions(false),
|
|
44895
|
+
validate: function(answer) {
|
|
44896
|
+
if (answer.length < 1) {
|
|
44897
|
+
return "You must choose at least one option.";
|
|
44898
|
+
}
|
|
44899
|
+
return true;
|
|
44900
|
+
}
|
|
44901
|
+
}
|
|
44902
|
+
];
|
|
44903
|
+
const llmProvidersAnswer = yield inquirer_default.prompt(questions);
|
|
44904
|
+
yield createRandomValidators(Number(options.numValidators), llmProvidersAnswer.selectedLlmProviders);
|
|
44787
44905
|
} catch (error) {
|
|
44788
44906
|
console.error("Unable to initialize the validators.");
|
|
44789
44907
|
console.error(error);
|
|
@@ -44805,7 +44923,7 @@ function startAction(options) {
|
|
|
44805
44923
|
// src/commands/general/index.ts
|
|
44806
44924
|
function initializeGeneralCommands(program2) {
|
|
44807
44925
|
program2.command("init").description("Initialize the GenLayer Environment").option("-n, --numValidators <numValidators>", "Number of validators", "5").action(initAction);
|
|
44808
|
-
program2.command("up").description("Starts GenLayer's simulator").option("--no-reset-accounts", "Don't restart the database for accouts and transactions", true).option("--reset-validators", "Remove all current validators and create new random ones", false).action(startAction);
|
|
44926
|
+
program2.command("up").description("Starts GenLayer's simulator").option("--no-reset-accounts", "Don't restart the database for accouts and transactions", true).option("--reset-validators", "Remove all current validators and create new random ones", false).option("--numValidators <numValidators>", "Number of validators", "5").action(startAction);
|
|
44809
44927
|
return program2;
|
|
44810
44928
|
}
|
|
44811
44929
|
|
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@ export function initializeGeneralCommands(program: Command) {
|
|
|
15
15
|
.description("Starts GenLayer's simulator")
|
|
16
16
|
.option("--no-reset-accounts", "Don't restart the database for accouts and transactions", true)
|
|
17
17
|
.option("--reset-validators", "Remove all current validators and create new random ones", false)
|
|
18
|
+
.option("--numValidators <numValidators>", "Number of validators", "5")
|
|
18
19
|
.action(startAction);
|
|
19
20
|
|
|
20
21
|
return program;
|
|
@@ -17,6 +17,8 @@ import {
|
|
|
17
17
|
getSimulatorLocation,
|
|
18
18
|
getFrontendUrl,
|
|
19
19
|
openFrontend,
|
|
20
|
+
resetDockerContainers,
|
|
21
|
+
resetDockerImages,
|
|
20
22
|
} from "@/lib/services/simulator";
|
|
21
23
|
export interface InitActionOptions {
|
|
22
24
|
numValidators: number;
|
|
@@ -43,6 +45,9 @@ export async function initAction(options: InitActionOptions) {
|
|
|
43
45
|
const {git, docker} = await checkRequirements();
|
|
44
46
|
const errorMessage = getRequirementsErrorMessage({git, docker});
|
|
45
47
|
if (errorMessage) {
|
|
48
|
+
console.log(
|
|
49
|
+
"There was a problem running the docker service. Please start the docker service and try again.",
|
|
50
|
+
);
|
|
46
51
|
console.error(errorMessage);
|
|
47
52
|
return;
|
|
48
53
|
}
|
|
@@ -51,6 +56,16 @@ export async function initAction(options: InitActionOptions) {
|
|
|
51
56
|
return;
|
|
52
57
|
}
|
|
53
58
|
|
|
59
|
+
// Reset Docker containers and images
|
|
60
|
+
console.log(`Resetting Docker containers and images...`);
|
|
61
|
+
try {
|
|
62
|
+
await resetDockerContainers();
|
|
63
|
+
await resetDockerImages();
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error(error);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
54
69
|
// Ask for confirmation on downloading the GenLayer Simulator from GitHub
|
|
55
70
|
const answers = await inquirer.prompt([
|
|
56
71
|
{
|
|
@@ -84,7 +99,7 @@ export async function initAction(options: InitActionOptions) {
|
|
|
84
99
|
type: "checkbox",
|
|
85
100
|
name: "selectedLlmProviders",
|
|
86
101
|
message: "Select which LLM providers do you want to use:",
|
|
87
|
-
choices: getAiProvidersOptions(),
|
|
102
|
+
choices: getAiProvidersOptions(true),
|
|
88
103
|
validate: function (answer: string[]) {
|
|
89
104
|
if (answer.length < 1) {
|
|
90
105
|
return "You must choose at least one option.";
|
|
@@ -188,7 +203,7 @@ export async function initAction(options: InitActionOptions) {
|
|
|
188
203
|
//remove all validators
|
|
189
204
|
await deleteAllValidators();
|
|
190
205
|
// create random validators
|
|
191
|
-
await createRandomValidators(Number(options.numValidators));
|
|
206
|
+
await createRandomValidators(Number(options.numValidators), selectedLlmProviders);
|
|
192
207
|
} catch (error) {
|
|
193
208
|
console.error("Unable to initialize the validators.");
|
|
194
209
|
console.error(error);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import inquirer from "inquirer";
|
|
2
|
+
|
|
1
3
|
import {
|
|
2
4
|
updateSimulator,
|
|
3
5
|
runSimulator,
|
|
@@ -8,22 +10,24 @@ import {
|
|
|
8
10
|
initializeDatabase,
|
|
9
11
|
getFrontendUrl,
|
|
10
12
|
openFrontend,
|
|
13
|
+
getAiProvidersOptions,
|
|
11
14
|
} from "@/lib/services/simulator";
|
|
12
15
|
|
|
13
16
|
export interface StartActionOptions {
|
|
14
17
|
resetAccounts: string;
|
|
15
18
|
resetValidators: string;
|
|
19
|
+
numValidators: number;
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
export async function startAction(options: StartActionOptions) {
|
|
19
|
-
const {resetAccounts, resetValidators} = options;
|
|
23
|
+
const {resetAccounts, resetValidators, numValidators} = options;
|
|
20
24
|
|
|
21
25
|
const restartAccountsHintText = resetAccounts
|
|
22
26
|
? "restarting the accounts and transactions database"
|
|
23
27
|
: "keeping the accounts and transactions records";
|
|
24
28
|
|
|
25
29
|
const restartValidatorsHintText = resetValidators
|
|
26
|
-
?
|
|
30
|
+
? `and creating new ${numValidators} random validators`
|
|
27
31
|
: "and keeping the existing validators";
|
|
28
32
|
|
|
29
33
|
console.log(`Starting GenLayer simulator ${restartAccountsHintText} ${restartValidatorsHintText}`);
|
|
@@ -90,8 +94,26 @@ export async function startAction(options: StartActionOptions) {
|
|
|
90
94
|
try {
|
|
91
95
|
//remove all validators
|
|
92
96
|
await deleteAllValidators();
|
|
97
|
+
const questions = [
|
|
98
|
+
{
|
|
99
|
+
type: "checkbox",
|
|
100
|
+
name: "selectedLlmProviders",
|
|
101
|
+
message: "Select which LLM providers do you want to use:",
|
|
102
|
+
choices: getAiProvidersOptions(false),
|
|
103
|
+
validate: function (answer: string[]) {
|
|
104
|
+
if (answer.length < 1) {
|
|
105
|
+
return "You must choose at least one option.";
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
// Since ollama runs locally we can run it here and then look for the other providers
|
|
113
|
+
const llmProvidersAnswer = await inquirer.prompt(questions);
|
|
114
|
+
|
|
93
115
|
// create random validators
|
|
94
|
-
await createRandomValidators();
|
|
116
|
+
await createRandomValidators(Number(options.numValidators), llmProvidersAnswer.selectedLlmProviders);
|
|
95
117
|
} catch (error) {
|
|
96
118
|
console.error("Unable to initialize the validators.");
|
|
97
119
|
console.error(error);
|
|
@@ -20,32 +20,20 @@ type ExecuteCommandResult = {
|
|
|
20
20
|
stderr: string;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
type
|
|
23
|
+
type ExecuteCommandByPlatformInput = {
|
|
24
24
|
[key in RunningPlatform]: string;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
export function executeCommand(
|
|
28
|
-
cmdsByPlatform:
|
|
29
|
-
toolName
|
|
30
|
-
):
|
|
31
|
-
try {
|
|
32
|
-
const runningPlatform = getPlatform();
|
|
33
|
-
const command = cmdsByPlatform[runningPlatform];
|
|
34
|
-
return asyncExec(command);
|
|
35
|
-
} catch (error: any) {
|
|
36
|
-
throw new Error(`Error executing ${toolName}: ${error.message}`);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function executeCommandInNewTerminal(
|
|
41
|
-
cmdsByPlatform: ExecuteCommandInNewTerminalInput,
|
|
42
|
-
): PromiseWithChild<{stdout: string; stderr: string}> {
|
|
28
|
+
cmdsByPlatform: ExecuteCommandByPlatformInput,
|
|
29
|
+
toolName?: string,
|
|
30
|
+
): PromiseWithChild<ExecuteCommandResult> {
|
|
43
31
|
const runningPlatform = getPlatform();
|
|
44
32
|
const command = cmdsByPlatform[runningPlatform];
|
|
45
33
|
try {
|
|
46
34
|
return asyncExec(command);
|
|
47
35
|
} catch (error: any) {
|
|
48
|
-
throw new Error(`Error executing command ${
|
|
36
|
+
throw new Error(`Error executing ${toolName || command}: ${error.message}.`);
|
|
49
37
|
}
|
|
50
38
|
}
|
|
51
39
|
|
|
@@ -56,7 +44,7 @@ export function getHomeDirectory(): string {
|
|
|
56
44
|
function getPlatform(): RunningPlatform {
|
|
57
45
|
const currentPlatform = process.platform as RunningPlatform;
|
|
58
46
|
if (!AVAILABLE_PLATFORMS.includes(currentPlatform)) {
|
|
59
|
-
throw new Error(`Unsupported platform: ${currentPlatform}
|
|
47
|
+
throw new Error(`Unsupported platform: ${currentPlatform}.`);
|
|
60
48
|
}
|
|
61
49
|
return currentPlatform;
|
|
62
50
|
}
|
|
@@ -64,3 +52,49 @@ function getPlatform(): RunningPlatform {
|
|
|
64
52
|
export function openUrl(url: string): Promise<ChildProcess> {
|
|
65
53
|
return open(url);
|
|
66
54
|
}
|
|
55
|
+
|
|
56
|
+
export async function listDockerContainers(): Promise<string[]> {
|
|
57
|
+
try {
|
|
58
|
+
const dockerResponse = await asyncExec("docker ps -a --format '{{.Names}}'");
|
|
59
|
+
const dockerContainers = dockerResponse.stdout.split("\n");
|
|
60
|
+
return dockerContainers;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
throw new Error("Error listing Docker containers.");
|
|
63
|
+
}
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export async function listDockerImages(): Promise<string[]> {
|
|
68
|
+
try {
|
|
69
|
+
const dockerResponse = await asyncExec("docker images --format '{{.Repository}}'");
|
|
70
|
+
const dockerImages = dockerResponse.stdout.split("\n");
|
|
71
|
+
return dockerImages;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
throw new Error("Error listing Docker images.");
|
|
74
|
+
}
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function stopDockerContainer(containerName: string): Promise<void> {
|
|
79
|
+
try {
|
|
80
|
+
await asyncExec(`docker stop ${containerName}`);
|
|
81
|
+
} catch (error) {
|
|
82
|
+
throw new Error(`Error stopping Docker container ${containerName}.`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function removeDockerContainer(containerName: string) {
|
|
87
|
+
try {
|
|
88
|
+
await asyncExec(`docker rm ${containerName}`);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
throw new Error(`Error removing container ${containerName}.`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export async function removeDockerImage(imageName: string) {
|
|
95
|
+
try {
|
|
96
|
+
await asyncExec(`docker rmi ${imageName}`);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
throw new Error(`Error removing image ${imageName}.`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export const DEFAULT_JSON_RPC_URL = "http://localhost:4000/api";
|
|
2
2
|
export const DEFAULT_REPO_GH_URL = "https://github.com/yeagerai/genlayer-simulator.git";
|
|
3
|
+
export const DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX = "genlayer-simulator-";
|
|
3
4
|
export const DEFAULT_RUN_SIMULATOR_COMMAND = (simulatorLocation: string) => ({
|
|
4
5
|
darwin: `osascript -e 'tell application "Terminal" to do script "cd ${simulatorLocation} && docker compose build && docker compose up"'`,
|
|
5
6
|
win32: `start cmd.exe /c "cd /d ${simulatorLocation} && docker compose build && docker compose up && pause"`,
|
|
@@ -10,30 +11,39 @@ export const DEFAULT_PULL_OLLAMA_COMMAND = (simulatorLocation: string) => ({
|
|
|
10
11
|
win32: `cd /d ${simulatorLocation} && docker exec ollama ollama pull llama3`,
|
|
11
12
|
linux: `cd ${simulatorLocation} && docker exec ollama ollama pull llama3`,
|
|
12
13
|
});
|
|
14
|
+
export const DEFAULT_RUN_DOCKER_COMMAND = {
|
|
15
|
+
darwin: "open -a Docker",
|
|
16
|
+
win32: 'start "" "C:\\Program Files\\Docker\\Docker\\Docker Desktop.exe"',
|
|
17
|
+
linux: "sudo systemctl start docker",
|
|
18
|
+
};
|
|
19
|
+
|
|
13
20
|
export const AVAILABLE_PLATFORMS = ["darwin", "win32", "linux"] as const;
|
|
14
21
|
export type RunningPlatform = (typeof AVAILABLE_PLATFORMS)[number];
|
|
15
22
|
export const STARTING_TIMEOUT_WAIT_CYLCE = 2000;
|
|
16
23
|
export const STARTING_TIMEOUT_ATTEMPTS = 120;
|
|
17
24
|
|
|
18
|
-
export type AiProviders = "ollama" | "openai" | "
|
|
25
|
+
export type AiProviders = "ollama" | "openai" | "heuristai";
|
|
19
26
|
export type AiProvidersEnvVars = "ollama" | "OPENAIKEY" | "HEURISTAIAPIKEY";
|
|
20
27
|
export type AiProvidersConfigType = {
|
|
21
|
-
[key in AiProviders]: {name: string; envVar?: AiProvidersEnvVars; cliOptionValue: string};
|
|
28
|
+
[key in AiProviders]: {name: string; hint: string; envVar?: AiProvidersEnvVars; cliOptionValue: string};
|
|
22
29
|
};
|
|
23
30
|
|
|
24
31
|
export const AI_PROVIDERS_CONFIG: AiProvidersConfigType = {
|
|
25
32
|
ollama: {
|
|
26
|
-
name: "Ollama
|
|
33
|
+
name: "Ollama",
|
|
34
|
+
hint: "(This will download and run a local instance of Llama 3)",
|
|
27
35
|
cliOptionValue: "ollama",
|
|
28
36
|
},
|
|
29
37
|
openai: {
|
|
30
|
-
name: "OpenAI
|
|
38
|
+
name: "OpenAI",
|
|
39
|
+
hint: "(You will need to provide an OpenAI API key)",
|
|
31
40
|
envVar: "OPENAIKEY",
|
|
32
41
|
cliOptionValue: "openai",
|
|
33
42
|
},
|
|
34
|
-
|
|
35
|
-
name:
|
|
43
|
+
heuristai: {
|
|
44
|
+
name: "Heurist",
|
|
45
|
+
hint: '(You will need to provide an API key. Get free API credits at https://dev-api-form.heurist.ai/ with referral code: "genlayer")',
|
|
36
46
|
envVar: "HEURISTAIAPIKEY",
|
|
37
|
-
cliOptionValue: "
|
|
47
|
+
cliOptionValue: "heuristai",
|
|
38
48
|
},
|
|
39
49
|
};
|
|
@@ -5,18 +5,25 @@ import * as path from "path";
|
|
|
5
5
|
import {rpcClient} from "@/lib/clients/jsonRpcClient";
|
|
6
6
|
import {
|
|
7
7
|
DEFAULT_REPO_GH_URL,
|
|
8
|
+
DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX,
|
|
8
9
|
DEFAULT_RUN_SIMULATOR_COMMAND,
|
|
10
|
+
DEFAULT_RUN_DOCKER_COMMAND,
|
|
9
11
|
DEFAULT_PULL_OLLAMA_COMMAND,
|
|
10
12
|
STARTING_TIMEOUT_WAIT_CYLCE,
|
|
11
13
|
STARTING_TIMEOUT_ATTEMPTS,
|
|
12
14
|
AI_PROVIDERS_CONFIG,
|
|
15
|
+
AiProviders,
|
|
13
16
|
} from "@/lib/config/simulator";
|
|
14
17
|
import {
|
|
15
18
|
checkCommand,
|
|
16
19
|
getHomeDirectory,
|
|
17
20
|
executeCommand,
|
|
18
|
-
executeCommandInNewTerminal,
|
|
19
21
|
openUrl,
|
|
22
|
+
listDockerContainers,
|
|
23
|
+
stopDockerContainer,
|
|
24
|
+
removeDockerContainer,
|
|
25
|
+
listDockerImages,
|
|
26
|
+
removeDockerImage,
|
|
20
27
|
} from "@/lib/clients/system";
|
|
21
28
|
import {MissingRequirementError} from "../errors/missingRequirement";
|
|
22
29
|
|
|
@@ -79,12 +86,20 @@ export async function checkRequirements(): Promise<Record<string, boolean>> {
|
|
|
79
86
|
try {
|
|
80
87
|
await checkCommand("docker --version", "docker");
|
|
81
88
|
requirementsInstalled.docker = true;
|
|
82
|
-
} catch (error) {
|
|
89
|
+
} catch (error: any) {
|
|
83
90
|
if (!(error instanceof MissingRequirementError)) {
|
|
84
91
|
throw error;
|
|
85
92
|
}
|
|
86
93
|
}
|
|
87
94
|
|
|
95
|
+
if (requirementsInstalled.docker) {
|
|
96
|
+
try {
|
|
97
|
+
await checkCommand("docker ps", "docker");
|
|
98
|
+
} catch (error: any) {
|
|
99
|
+
await executeCommand(DEFAULT_RUN_DOCKER_COMMAND);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
88
103
|
return requirementsInstalled;
|
|
89
104
|
}
|
|
90
105
|
|
|
@@ -120,7 +135,7 @@ export async function updateSimulator(): Promise<DownloadSimulatorResultType> {
|
|
|
120
135
|
export async function pullOllamaModel(): Promise<boolean> {
|
|
121
136
|
const simulatorLocation = getSimulatorLocation();
|
|
122
137
|
const cmdsByPlatform = DEFAULT_PULL_OLLAMA_COMMAND(simulatorLocation);
|
|
123
|
-
await
|
|
138
|
+
await executeCommand(cmdsByPlatform);
|
|
124
139
|
return true;
|
|
125
140
|
}
|
|
126
141
|
|
|
@@ -136,7 +151,7 @@ export async function configSimulator(newConfig: Record<string, string>): Promis
|
|
|
136
151
|
export function runSimulator(): Promise<{stdout: string; stderr: string}> {
|
|
137
152
|
const simulatorLocation = getSimulatorLocation();
|
|
138
153
|
const commandsByPlatform = DEFAULT_RUN_SIMULATOR_COMMAND(simulatorLocation);
|
|
139
|
-
return
|
|
154
|
+
return executeCommand(commandsByPlatform);
|
|
140
155
|
}
|
|
141
156
|
|
|
142
157
|
type WaitForSimulatorToBeReadyResultType = {
|
|
@@ -160,7 +175,8 @@ export async function waitForSimulatorToBeReady(
|
|
|
160
175
|
}
|
|
161
176
|
} catch (error: any) {
|
|
162
177
|
if (
|
|
163
|
-
(error.
|
|
178
|
+
(error.name === "FetchError" ||
|
|
179
|
+
error.message.includes("ECONNRESET") ||
|
|
164
180
|
error.message.includes("ECONNREFUSED") ||
|
|
165
181
|
error.message.includes("socket hang up")) &&
|
|
166
182
|
retries > 0
|
|
@@ -189,17 +205,23 @@ export async function initializeDatabase(): Promise<InitializeDatabaseResultType
|
|
|
189
205
|
return {createResponse, tablesResponse};
|
|
190
206
|
}
|
|
191
207
|
|
|
192
|
-
export function createRandomValidators(numValidators: number): Promise<any> {
|
|
193
|
-
return rpcClient.request({
|
|
208
|
+
export function createRandomValidators(numValidators: number, llmProviders: AiProviders[]): Promise<any> {
|
|
209
|
+
return rpcClient.request({
|
|
210
|
+
method: "create_random_validators",
|
|
211
|
+
params: [numValidators, 1, 10, llmProviders],
|
|
212
|
+
});
|
|
194
213
|
}
|
|
195
214
|
|
|
196
215
|
export function deleteAllValidators(): Promise<any> {
|
|
197
216
|
return rpcClient.request({method: "delete_all_validators", params: []});
|
|
198
217
|
}
|
|
199
218
|
|
|
200
|
-
export function getAiProvidersOptions(): Array<{name: string; value: string}> {
|
|
219
|
+
export function getAiProvidersOptions(withHint: boolean = true): Array<{name: string; value: string}> {
|
|
201
220
|
return Object.values(AI_PROVIDERS_CONFIG).map(providerConfig => {
|
|
202
|
-
return {
|
|
221
|
+
return {
|
|
222
|
+
name: `${providerConfig.name}${withHint ? ` ${providerConfig.hint}` : ""}`,
|
|
223
|
+
value: providerConfig.cliOptionValue,
|
|
224
|
+
};
|
|
203
225
|
});
|
|
204
226
|
}
|
|
205
227
|
|
|
@@ -212,3 +234,32 @@ export async function openFrontend(): Promise<boolean> {
|
|
|
212
234
|
await openUrl(getFrontendUrl());
|
|
213
235
|
return true;
|
|
214
236
|
}
|
|
237
|
+
|
|
238
|
+
export async function resetDockerContainers(): Promise<boolean> {
|
|
239
|
+
const containers = await listDockerContainers();
|
|
240
|
+
const genlayerContainers = containers.filter((container: string) =>
|
|
241
|
+
container.startsWith(DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX),
|
|
242
|
+
);
|
|
243
|
+
const containersStopPromises = genlayerContainers.map((container: string) =>
|
|
244
|
+
stopDockerContainer(container),
|
|
245
|
+
);
|
|
246
|
+
await Promise.all(containersStopPromises);
|
|
247
|
+
|
|
248
|
+
const containersRemovePromises = genlayerContainers.map((container: string) =>
|
|
249
|
+
removeDockerContainer(container),
|
|
250
|
+
);
|
|
251
|
+
await Promise.all(containersRemovePromises);
|
|
252
|
+
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export async function resetDockerImages(): Promise<boolean> {
|
|
257
|
+
const images = await listDockerImages();
|
|
258
|
+
const genlayerImages = images.filter((image: string) =>
|
|
259
|
+
image.startsWith(DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX),
|
|
260
|
+
);
|
|
261
|
+
const imagesRemovePromises = genlayerImages.map((image: string) => removeDockerImage(image));
|
|
262
|
+
await Promise.all(imagesRemovePromises);
|
|
263
|
+
|
|
264
|
+
return true;
|
|
265
|
+
}
|