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 CHANGED
@@ -1,5 +1,9 @@
1
1
 
2
2
 
3
+ ## 0.0.30 (2024-05-22)
4
+
5
+ ## 0.0.29 (2024-05-15)
6
+
3
7
  ## 0.0.28 (2024-05-13)
4
8
 
5
9
  ## 0.0.27 (2024-05-08)
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.28";
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 (This will download and run a local instance of Llama 3)",
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 (You will need to provide an OpenAI API key)",
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
- heurist: {
42518
- name: 'Heurist (You will need to provide an API key. Get free API credits at https://dev-api-form.heurist.ai/ with referral code: "genlayer"):',
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: "heurist"
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 ${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 executeCommandInNewTerminal(cmdsByPlatform);
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 executeCommandInNewTerminal(commandsByPlatform);
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({ method: "create_random_validators", params: [numValidators, 1, 10] });
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 { name: providerConfig.name, value: providerConfig.cliOptionValue };
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 ? "and creating new random validators" : "and keeping the existing validators";
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
- yield createRandomValidators();
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genlayer",
3
- "version": "0.0.28",
3
+ "version": "0.0.30",
4
4
  "description": "GenLayer Command Line Tool",
5
5
  "main": "src/index.ts",
6
6
  "bin": {
@@ -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
- ? "and creating new random validators"
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 ExecuteCommandInNewTerminalInput = {
23
+ type ExecuteCommandByPlatformInput = {
24
24
  [key in RunningPlatform]: string;
25
25
  };
26
26
 
27
27
  export function executeCommand(
28
- cmdsByPlatform: ExecuteCommandInNewTerminalInput,
29
- toolName: string,
30
- ): Promise<ExecuteCommandResult> {
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 ${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" | "heurist";
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 (This will download and run a local instance of Llama 3)",
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 (You will need to provide an OpenAI API key)",
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
- heurist: {
35
- name: 'Heurist (You will need to provide an API key. Get free API credits at https://dev-api-form.heurist.ai/ with referral code: "genlayer"):',
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: "heurist",
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 executeCommandInNewTerminal(cmdsByPlatform);
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 executeCommandInNewTerminal(commandsByPlatform);
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.message.includes("ECONNRESET") ||
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({method: "create_random_validators", params: [numValidators, 1, 10]});
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 {name: providerConfig.name, value: providerConfig.cliOptionValue};
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
+ }