genlayer 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.18.0 (2025-05-28)
4
+
5
+ ### Features
6
+
7
+ * using profiles to set frontend and ollama containers ([#221](https://github.com/yeagerai/genlayer-cli/issues/221)) ([a3d0d4e](https://github.com/yeagerai/genlayer-cli/commit/a3d0d4e77e7a92a5a31ae534f5f83e81a1672783))
8
+
3
9
  ## 0.17.0 (2025-05-05)
4
10
 
5
11
  ### Features
package/dist/index.js CHANGED
@@ -16853,7 +16853,7 @@ var require_semver2 = __commonJS({
16853
16853
  import { program } from "commander";
16854
16854
 
16855
16855
  // package.json
16856
- var version = "0.17.0";
16856
+ var version = "0.18.0";
16857
16857
  var package_default = {
16858
16858
  name: "genlayer",
16859
16859
  version,
@@ -16944,14 +16944,14 @@ var CLI_DESCRIPTION = "GenLayer CLI is a development environment for the GenLaye
16944
16944
  import inquirer2 from "inquirer";
16945
16945
 
16946
16946
  // src/lib/config/simulator.ts
16947
- var localnetCompatibleVersion = "v0.51.1";
16947
+ var localnetCompatibleVersion = "v0.55.0";
16948
16948
  var DEFAULT_JSON_RPC_URL = "http://localhost:4000/api";
16949
16949
  var CONTAINERS_NAME_PREFIX = "/genlayer-";
16950
16950
  var IMAGES_NAME_PREFIX = "yeagerai";
16951
- var DEFAULT_RUN_SIMULATOR_COMMAND = (location, options) => ({
16952
- darwin: `osascript -e 'tell application "Terminal" to do script "cd ${location} && docker compose build && docker compose -p genlayer up ${options}"'`,
16953
- win32: `start cmd.exe /c "cd /d ${location} && docker compose build && docker compose -p genlayer up ${options} && pause"`,
16954
- linux: `nohup bash -c 'cd ${location} && docker compose build && docker compose -p genlayer up ${options} -d '`
16951
+ var DEFAULT_RUN_SIMULATOR_COMMAND = (location, profiles) => ({
16952
+ darwin: `osascript -e 'tell application "Terminal" to do script "cd ${location} && docker compose build && docker compose -p genlayer ${profiles} up"'`,
16953
+ win32: `start cmd.exe /c "cd /d ${location} && docker compose build && docker compose -p genlayer ${profiles} up && pause"`,
16954
+ linux: `nohup bash -c 'cd ${location} && docker compose build && docker compose -p genlayer ${profiles} up -d '`
16955
16955
  });
16956
16956
  var DEFAULT_RUN_DOCKER_COMMAND = {
16957
16957
  darwin: "open -a Docker",
@@ -27905,7 +27905,7 @@ var OllamaAction = class extends BaseAction {
27905
27905
  try {
27906
27906
  this.startSpinner(`Executing '${command}' command on model "${modelName}"...`);
27907
27907
  let success = false;
27908
- const ollamaContainer = this.docker.getContainer("ollama");
27908
+ const ollamaContainer = this.docker.getContainer("genlayer-ollama");
27909
27909
  const exec2 = await ollamaContainer.exec({
27910
27910
  Cmd: ["ollama", command, modelName],
27911
27911
  AttachStdout: true,
@@ -28465,12 +28465,12 @@ function sleep2(millliseconds) {
28465
28465
  }
28466
28466
  var SimulatorService = class {
28467
28467
  constructor() {
28468
- __publicField(this, "composeOptions");
28468
+ __publicField(this, "profileOptions");
28469
28469
  __publicField(this, "docker");
28470
28470
  __publicField(this, "location");
28471
28471
  const __filename = fileURLToPath2(import.meta.url);
28472
28472
  this.location = path3.resolve(path3.dirname(__filename), "..");
28473
- this.composeOptions = "";
28473
+ this.profileOptions = "";
28474
28474
  this.docker = new Docker2();
28475
28475
  }
28476
28476
  readEnvConfigValue(key) {
@@ -28482,7 +28482,7 @@ var SimulatorService = class {
28482
28482
  const containers = await this.docker.listContainers({ all: true });
28483
28483
  return containers.filter(
28484
28484
  (container) => container.Names.some(
28485
- (name) => name.startsWith(CONTAINERS_NAME_PREFIX) || name.includes("ollama")
28485
+ (name) => name.startsWith(CONTAINERS_NAME_PREFIX)
28486
28486
  )
28487
28487
  );
28488
28488
  }
@@ -28510,11 +28510,18 @@ var SimulatorService = class {
28510
28510
  }).join("\n");
28511
28511
  fs7.writeFileSync(envFilePath, updatedConfig);
28512
28512
  }
28513
- setComposeOptions(headless) {
28514
- this.composeOptions = headless ? "--scale frontend=0" : "";
28513
+ setComposeOptions(headless, ollama = false) {
28514
+ let profiles = [];
28515
+ if (!headless) {
28516
+ profiles.push("frontend");
28517
+ }
28518
+ if (ollama) {
28519
+ profiles.push("ollama");
28520
+ }
28521
+ this.profileOptions = profiles.length > 0 ? `--profile ${profiles.join(" --profile ")}` : "";
28515
28522
  }
28516
28523
  getComposeOptions() {
28517
- return this.composeOptions;
28524
+ return this.profileOptions;
28518
28525
  }
28519
28526
  async checkCliVersion() {
28520
28527
  const update = await updateCheck(package_default);
@@ -28607,8 +28614,8 @@ Run npm install -g genlayer to update
28607
28614
  deleteAllValidators() {
28608
28615
  return rpcClient.request({ method: "sim_deleteAllValidators", params: [] });
28609
28616
  }
28610
- getAiProvidersOptions(withHint = true) {
28611
- return Object.values(AI_PROVIDERS_CONFIG).map((providerConfig) => {
28617
+ getAiProvidersOptions(withHint = true, excludeProviders = []) {
28618
+ return Object.values(AI_PROVIDERS_CONFIG).filter((providerConfig) => !excludeProviders.includes(providerConfig.cliOptionValue)).map((providerConfig) => {
28612
28619
  return {
28613
28620
  name: `${providerConfig.name}${withHint ? ` ${providerConfig.hint}` : ""}`,
28614
28621
  value: providerConfig.cliOptionValue
@@ -28698,7 +28705,7 @@ var InitAction = class extends BaseAction {
28698
28705
  }
28699
28706
  async execute(options) {
28700
28707
  try {
28701
- this.simulatorService.setComposeOptions(options.headless);
28708
+ this.simulatorService.setComposeOptions(options.headless, options.ollama);
28702
28709
  let localnetVersion = options.localnetVersion;
28703
28710
  if (localnetVersion !== "latest") {
28704
28711
  localnetVersion = this.simulatorService.normalizeLocalnetVersion(localnetVersion);
@@ -28733,7 +28740,7 @@ var InitAction = class extends BaseAction {
28733
28740
  type: "checkbox",
28734
28741
  name: "selectedLlmProviders",
28735
28742
  message: "Select which LLM providers do you want to use:",
28736
- choices: this.simulatorService.getAiProvidersOptions(true),
28743
+ choices: this.simulatorService.getAiProvidersOptions(true, options.ollama ? [] : ["ollama"]),
28737
28744
  validate: (answer) => answer.length < 1 ? "You must choose at least one option." : true
28738
28745
  }
28739
28746
  ];
@@ -28818,8 +28825,8 @@ var StartAction = class extends BaseAction {
28818
28825
  this.simulatorService = new SimulatorService();
28819
28826
  }
28820
28827
  async execute(options) {
28821
- const { resetValidators, numValidators, headless, resetDb } = options;
28822
- this.simulatorService.setComposeOptions(headless);
28828
+ const { resetValidators, numValidators, headless, resetDb, ollama } = options;
28829
+ this.simulatorService.setComposeOptions(headless, ollama);
28823
28830
  this.startSpinner("Checking CLI version...");
28824
28831
  await this.simulatorService.checkCliVersion();
28825
28832
  const isRunning = await this.simulatorService.isLocalnetRunning();
@@ -28867,7 +28874,7 @@ var StartAction = class extends BaseAction {
28867
28874
  type: "checkbox",
28868
28875
  name: "selectedLlmProviders",
28869
28876
  message: "Select which LLM providers do you want to use:",
28870
- choices: this.simulatorService.getAiProvidersOptions(false),
28877
+ choices: this.simulatorService.getAiProvidersOptions(false, ollama ? [] : ["ollama"]),
28871
28878
  validate: (answer) => answer.length < 1 ? "You must choose at least one option." : true
28872
28879
  }
28873
28880
  ];
@@ -28916,11 +28923,11 @@ var StopAction = class extends BaseAction {
28916
28923
 
28917
28924
  // src/commands/general/index.ts
28918
28925
  function initializeGeneralCommands(program2) {
28919
- program2.command("init").description("Initialize the GenLayer Environment").option("--numValidators <numValidators>", "Number of validators", "5").option("--headless", "Headless mode", false).option("--reset-db", "Reset Database", false).option("--localnet-version <localnetVersion>", "Select a specific localnet version", localnetCompatibleVersion).action(async (options) => {
28926
+ program2.command("init").description("Initialize the GenLayer Environment").option("--numValidators <numValidators>", "Number of validators", "5").option("--headless", "Headless mode", false).option("--reset-db", "Reset Database", false).option("--localnet-version <localnetVersion>", "Select a specific localnet version", localnetCompatibleVersion).option("--ollama", "Enable Ollama container", false).action(async (options) => {
28920
28927
  const initAction = new InitAction();
28921
28928
  await initAction.execute(options);
28922
28929
  });
28923
- program2.command("up").description("Starts GenLayer's simulator").option("--reset-validators", "Remove all current validators and create new random ones", false).option("--numValidators <numValidators>", "Number of validators", "5").option("--headless", "Headless mode", false).option("--reset-db", "Reset Database", false).action(async (options) => {
28930
+ program2.command("up").description("Starts GenLayer's simulator").option("--reset-validators", "Remove all current validators and create new random ones", false).option("--numValidators <numValidators>", "Number of validators", "5").option("--headless", "Headless mode", false).option("--reset-db", "Reset Database", false).option("--ollama", "Enable Ollama container", false).action(async (options) => {
28924
28931
  const startAction = new StartAction();
28925
28932
  await startAction.execute(options);
28926
28933
  });
@@ -22,6 +22,8 @@ services:
22
22
  options:
23
23
  max-size: "10m"
24
24
  max-file: "3"
25
+ profiles:
26
+ - frontend
25
27
 
26
28
 
27
29
  jsonrpc:
@@ -83,6 +85,7 @@ services:
83
85
  depends_on:
84
86
  ollama:
85
87
  condition: service_started
88
+ required: false
86
89
  restart: always
87
90
  security_opt:
88
91
  - "no-new-privileges=true"
@@ -96,7 +99,7 @@ services:
96
99
  image: ollama/ollama:0.6.6
97
100
  ports:
98
101
  - 11434:11434
99
- container_name: ollama
102
+ container_name: genlayer-ollama
100
103
  tty: true
101
104
  restart: always
102
105
  security_opt:
@@ -106,6 +109,8 @@ services:
106
109
  options:
107
110
  max-size: "10m"
108
111
  max-file: "3"
112
+ profiles:
113
+ - ollama
109
114
 
110
115
  postgres:
111
116
  image: postgres:17-alpine
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genlayer",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "GenLayer Command Line Tool",
5
5
  "main": "src/index.ts",
6
6
  "type": "module",
@@ -14,6 +14,7 @@ export function initializeGeneralCommands(program: Command) {
14
14
  .option("--headless", "Headless mode", false)
15
15
  .option("--reset-db", "Reset Database", false)
16
16
  .option("--localnet-version <localnetVersion>", "Select a specific localnet version", localnetCompatibleVersion)
17
+ .option("--ollama", "Enable Ollama container", false)
17
18
  .action(async (options: InitActionOptions) => {
18
19
  const initAction = new InitAction();
19
20
  await initAction.execute(options)
@@ -26,6 +27,7 @@ export function initializeGeneralCommands(program: Command) {
26
27
  .option("--numValidators <numValidators>", "Number of validators", "5")
27
28
  .option("--headless", "Headless mode", false)
28
29
  .option("--reset-db", "Reset Database", false)
30
+ .option("--ollama", "Enable Ollama container", false)
29
31
  .action(async (options: StartActionOptions) => {
30
32
  const startAction = new StartAction();
31
33
  await startAction.execute(options);
@@ -11,6 +11,7 @@ export interface InitActionOptions {
11
11
  headless: boolean;
12
12
  resetDb: boolean;
13
13
  localnetVersion: string;
14
+ ollama: boolean;
14
15
  }
15
16
 
16
17
  function getRequirementsErrorMessage({ docker }: Record<string, boolean>): string {
@@ -41,7 +42,7 @@ export class InitAction extends BaseAction {
41
42
 
42
43
  public async execute(options: InitActionOptions): Promise<void> {
43
44
  try {
44
- this.simulatorService.setComposeOptions(options.headless);
45
+ this.simulatorService.setComposeOptions(options.headless, options.ollama);
45
46
  let localnetVersion = options.localnetVersion;
46
47
  if (localnetVersion !== "latest") {
47
48
  localnetVersion = this.simulatorService.normalizeLocalnetVersion(localnetVersion);
@@ -88,7 +89,7 @@ export class InitAction extends BaseAction {
88
89
  type: "checkbox",
89
90
  name: "selectedLlmProviders",
90
91
  message: "Select which LLM providers do you want to use:",
91
- choices: this.simulatorService.getAiProvidersOptions(true),
92
+ choices: this.simulatorService.getAiProvidersOptions(true, options.ollama ? [] : ["ollama"]),
92
93
  validate: (answer) =>
93
94
  answer.length < 1 ? "You must choose at least one option." : true,
94
95
  },
@@ -9,6 +9,7 @@ export interface StartActionOptions {
9
9
  numValidators: number;
10
10
  headless: boolean;
11
11
  resetDb: boolean;
12
+ ollama: boolean;
12
13
  }
13
14
 
14
15
  export class StartAction extends BaseAction {
@@ -20,9 +21,9 @@ export class StartAction extends BaseAction {
20
21
  }
21
22
 
22
23
  async execute(options: StartActionOptions) {
23
- const { resetValidators, numValidators, headless, resetDb } = options;
24
+ const { resetValidators, numValidators, headless, resetDb, ollama } = options;
24
25
 
25
- this.simulatorService.setComposeOptions(headless);
26
+ this.simulatorService.setComposeOptions(headless, ollama);
26
27
  this.startSpinner("Checking CLI version...");
27
28
  await this.simulatorService.checkCliVersion();
28
29
 
@@ -81,7 +82,7 @@ export class StartAction extends BaseAction {
81
82
  type: "checkbox",
82
83
  name: "selectedLlmProviders",
83
84
  message: "Select which LLM providers do you want to use:",
84
- choices: this.simulatorService.getAiProvidersOptions(false),
85
+ choices: this.simulatorService.getAiProvidersOptions(false, ollama ? [] : ["ollama"]),
85
86
  validate: (answer) => (answer.length < 1 ? "You must choose at least one option." : true),
86
87
  },
87
88
  ];
@@ -67,7 +67,7 @@ export class OllamaAction extends BaseAction {
67
67
  this.startSpinner(`Executing '${command}' command on model "${modelName}"...`);
68
68
 
69
69
  let success = false;
70
- const ollamaContainer = this.docker.getContainer("ollama");
70
+ const ollamaContainer = this.docker.getContainer("genlayer-ollama");
71
71
  const exec = await ollamaContainer.exec({
72
72
  Cmd: ["ollama", command, modelName],
73
73
  AttachStdout: true,
@@ -1,11 +1,11 @@
1
- export const localnetCompatibleVersion = "v0.51.1";
1
+ export const localnetCompatibleVersion = "v0.55.0";
2
2
  export const DEFAULT_JSON_RPC_URL = "http://localhost:4000/api";
3
3
  export const CONTAINERS_NAME_PREFIX = "/genlayer-";
4
4
  export const IMAGES_NAME_PREFIX = "yeagerai";
5
- export const DEFAULT_RUN_SIMULATOR_COMMAND = (location: string, options: string) => ({
6
- darwin: `osascript -e 'tell application "Terminal" to do script "cd ${location} && docker compose build && docker compose -p genlayer up ${options}"'`,
7
- win32: `start cmd.exe /c "cd /d ${location} && docker compose build && docker compose -p genlayer up ${options} && pause"`,
8
- linux: `nohup bash -c 'cd ${location} && docker compose build && docker compose -p genlayer up ${options} -d '`,
5
+ export const DEFAULT_RUN_SIMULATOR_COMMAND = (location: string, profiles: string) => ({
6
+ darwin: `osascript -e 'tell application "Terminal" to do script "cd ${location} && docker compose build && docker compose -p genlayer ${profiles} up"'`,
7
+ win32: `start cmd.exe /c "cd /d ${location} && docker compose build && docker compose -p genlayer ${profiles} up && pause"`,
8
+ linux: `nohup bash -c 'cd ${location} && docker compose build && docker compose -p genlayer ${profiles} up -d '`,
9
9
  });
10
10
  export const DEFAULT_RUN_DOCKER_COMMAND = {
11
11
  darwin: "open -a Docker",
@@ -1,7 +1,7 @@
1
1
  import {AiProviders} from "../config/simulator";
2
2
 
3
3
  export interface ISimulatorService {
4
- setComposeOptions(headless: boolean): void;
4
+ setComposeOptions(headless: boolean, disableOllama?: boolean): void;
5
5
  getComposeOptions(): string;
6
6
  checkInstallRequirements(): Promise<Record<string, boolean>>;
7
7
  checkVersionRequirements(): Promise<Record<string, string>>;
@@ -9,7 +9,7 @@ export interface ISimulatorService {
9
9
  waitForSimulatorToBeReady(retries?: number): Promise<WaitForSimulatorToBeReadyResultType>;
10
10
  createRandomValidators(numValidators: number, llmProviders: AiProviders[]): Promise<any>;
11
11
  deleteAllValidators(): Promise<any>;
12
- getAiProvidersOptions(withHint: boolean): Array<{name: string; value: string}>;
12
+ getAiProvidersOptions(withHint: boolean, excludeProviders?: AiProviders[]): Array<{name: string; value: string}>;
13
13
  getFrontendUrl(): string;
14
14
  openFrontend(): Promise<boolean>;
15
15
  stopDockerContainers(): Promise<void>;
@@ -40,14 +40,14 @@ function sleep(millliseconds: number): Promise<void> {
40
40
  }
41
41
 
42
42
  export class SimulatorService implements ISimulatorService {
43
- private composeOptions: string
43
+ private profileOptions: string
44
44
  private docker: Docker;
45
45
  public location: string;
46
46
 
47
47
  constructor() {
48
48
  const __filename = fileURLToPath(import.meta.url);
49
49
  this.location = path.resolve(path.dirname(__filename), '..');
50
- this.composeOptions = "";
50
+ this.profileOptions = "";
51
51
  this.docker = new Docker();
52
52
  }
53
53
 
@@ -62,7 +62,7 @@ export class SimulatorService implements ISimulatorService {
62
62
  const containers = await this.docker.listContainers({ all: true });
63
63
  return containers.filter(container =>
64
64
  container.Names.some(name =>
65
- name.startsWith(CONTAINERS_NAME_PREFIX) || name.includes("ollama")
65
+ name.startsWith(CONTAINERS_NAME_PREFIX)
66
66
  )
67
67
  );
68
68
  }
@@ -104,12 +104,22 @@ export class SimulatorService implements ISimulatorService {
104
104
  fs.writeFileSync(envFilePath, updatedConfig);
105
105
  }
106
106
 
107
- public setComposeOptions(headless: boolean): void {
108
- this.composeOptions = headless ? '--scale frontend=0' : '';
107
+ public setComposeOptions(headless: boolean, ollama: boolean = false): void {
108
+ let profiles = [];
109
+
110
+ if (!headless) {
111
+ profiles.push("frontend");
112
+ }
113
+
114
+ if (ollama) {
115
+ profiles.push("ollama");
116
+ }
117
+
118
+ this.profileOptions = profiles.length > 0 ? `--profile ${profiles.join(" --profile ")}` : "";
109
119
  }
110
120
 
111
121
  public getComposeOptions(): string {
112
- return this.composeOptions;
122
+ return this.profileOptions;
113
123
  }
114
124
 
115
125
  public async checkCliVersion(): Promise<void> {
@@ -227,13 +237,15 @@ export class SimulatorService implements ISimulatorService {
227
237
  return rpcClient.request({method: "sim_deleteAllValidators", params: []});
228
238
  }
229
239
 
230
- public getAiProvidersOptions(withHint: boolean = true): Array<{name: string; value: string}> {
231
- return Object.values(AI_PROVIDERS_CONFIG).map(providerConfig => {
232
- return {
233
- name: `${providerConfig.name}${withHint ? ` ${providerConfig.hint}` : ""}`,
234
- value: providerConfig.cliOptionValue,
235
- };
236
- });
240
+ public getAiProvidersOptions(withHint: boolean = true, excludeProviders: AiProviders[] = []): Array<{name: string; value: string}> {
241
+ return Object.values(AI_PROVIDERS_CONFIG)
242
+ .filter(providerConfig => !excludeProviders.includes(providerConfig.cliOptionValue as AiProviders))
243
+ .map(providerConfig => {
244
+ return {
245
+ name: `${providerConfig.name}${withHint ? ` ${providerConfig.hint}` : ""}`,
246
+ value: providerConfig.cliOptionValue,
247
+ };
248
+ });
237
249
  }
238
250
 
239
251
  public getFrontendUrl(): string {
@@ -29,6 +29,7 @@ describe("InitAction", () => {
29
29
  headless: false,
30
30
  resetDb: false,
31
31
  localnetVersion: "v1.0.0",
32
+ ollama: false
32
33
  };
33
34
 
34
35
  beforeEach(() => {
@@ -130,6 +131,7 @@ describe("InitAction", () => {
130
131
  headless: true,
131
132
  resetDb: true,
132
133
  localnetVersion: "v1.0.0",
134
+ ollama: true
133
135
  };
134
136
  await initAction.execute(headlessOptions);
135
137
  expect(cleanDatabaseSpy).toHaveBeenCalled();
@@ -191,6 +193,30 @@ describe("InitAction", () => {
191
193
  expect(capturedQuestion.validate([])).toBe("You must choose at least one option.");
192
194
  expect(capturedQuestion.validate(["openai"])).toBe(true);
193
195
  });
196
+
197
+ test("should exclude ollama from choices when ollama option is false", async () => {
198
+ const getAiProvidersOptionsSpy = vi.spyOn(SimulatorService.prototype, "getAiProvidersOptions");
199
+ inquirerPromptSpy
200
+ .mockResolvedValueOnce({ confirmAction: true })
201
+ .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
202
+ .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
203
+
204
+ await initAction.execute({ ...defaultOptions, ollama: false });
205
+
206
+ expect(getAiProvidersOptionsSpy).toHaveBeenCalledWith(true, ["ollama"]);
207
+ });
208
+
209
+ test("should include ollama in choices when ollama option is true", async () => {
210
+ const getAiProvidersOptionsSpy = vi.spyOn(SimulatorService.prototype, "getAiProvidersOptions");
211
+ inquirerPromptSpy
212
+ .mockResolvedValueOnce({ confirmAction: true })
213
+ .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
214
+ .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
215
+
216
+ await initAction.execute({ ...defaultOptions, ollama: true });
217
+
218
+ expect(getAiProvidersOptionsSpy).toHaveBeenCalledWith(true, []);
219
+ });
194
220
  });
195
221
 
196
222
  describe("Error Handling", () => {
@@ -70,7 +70,7 @@ describe("OllamaAction", () => {
70
70
  await ollamaAction.updateModel("mocked_model");
71
71
 
72
72
  expect(ollamaAction["startSpinner"]).toHaveBeenCalledWith(`Updating model "mocked_model"...`);
73
- expect(mockGetContainer).toHaveBeenCalledWith("ollama");
73
+ expect(mockGetContainer).toHaveBeenCalledWith("genlayer-ollama");
74
74
  expect(mockExec).toHaveBeenCalledWith({
75
75
  Cmd: ["ollama", "pull", "mocked_model"],
76
76
  AttachStdout: true,
@@ -94,7 +94,7 @@ describe("OllamaAction", () => {
94
94
  await ollamaAction.removeModel("mocked_model");
95
95
 
96
96
  expect(ollamaAction["startSpinner"]).toHaveBeenCalledWith(`Executing 'rm' command on model "mocked_model"...`);
97
- expect(mockGetContainer).toHaveBeenCalledWith("ollama");
97
+ expect(mockGetContainer).toHaveBeenCalledWith("genlayer-ollama");
98
98
  expect(mockExec).toHaveBeenCalledWith({
99
99
  Cmd: ["ollama", "rm", "mocked_model"],
100
100
  AttachStdout: true,
@@ -20,6 +20,7 @@ describe("StartAction", () => {
20
20
 
21
21
  mockSimulatorService.waitForSimulatorToBeReady = vi.fn().mockResolvedValue({ initialized: true });
22
22
  mockSimulatorService.stopDockerContainers = vi.fn().mockResolvedValue(undefined);
23
+ mockSimulatorService.getAiProvidersOptions = vi.fn().mockResolvedValue(undefined);
23
24
 
24
25
  mockConfirmPrompt = vi.spyOn(startAction as any, "confirmPrompt").mockResolvedValue(undefined);
25
26
  vi.spyOn(startAction as any, "startSpinner").mockImplementation(() => {});
@@ -37,6 +38,7 @@ describe("StartAction", () => {
37
38
  numValidators: 5,
38
39
  headless: false,
39
40
  resetDb: false,
41
+ ollama: false
40
42
  };
41
43
 
42
44
  test("should check if localnet is running and proceed without confirmation when not running", async () => {
@@ -194,4 +196,16 @@ describe("StartAction", () => {
194
196
  "GenLayer simulator initialized successfully! "
195
197
  );
196
198
  });
199
+
200
+ test("should exclude ollama from choices when ollama option is false", async () => {
201
+ await startAction.execute({ ...defaultOptions, resetValidators: true, ollama: false });
202
+
203
+ expect(mockSimulatorService.getAiProvidersOptions).toHaveBeenCalledWith(false, ["ollama"]);
204
+ });
205
+
206
+ test("should include ollama in choices when ollama option is true", async () => {
207
+ await startAction.execute({ ...defaultOptions, resetValidators: true, ollama: true });
208
+
209
+ expect(mockSimulatorService.getAiProvidersOptions).toHaveBeenCalledWith(false, []);
210
+ });
197
211
  });
@@ -15,7 +15,8 @@ const defaultOptions = {
15
15
  numValidators: "5",
16
16
  headless: false,
17
17
  resetDb: false,
18
- localnetVersion: localnetCompatibleVersion
18
+ localnetVersion: localnetCompatibleVersion,
19
+ ollama: false,
19
20
  }
20
21
 
21
22
  vi.mock("inquirer", () => ({
@@ -81,4 +82,10 @@ describe("init command", () => {
81
82
  expect(InitAction.prototype.execute).toHaveBeenCalledWith({...defaultOptions, localnetVersion: "v1.0.0"});
82
83
  expect(openFrontendSpy).not.toHaveBeenCalled();
83
84
  });
85
+
86
+ test("option --ollama is accepted", async () => {
87
+ program.parse(["node", "test", "init", "--ollama"]);
88
+ expect(InitAction).toHaveBeenCalledTimes(1);
89
+ expect(InitAction.prototype.execute).toHaveBeenCalledWith({...defaultOptions, ollama: true});
90
+ });
84
91
  });
@@ -31,6 +31,7 @@ describe("up command", () => {
31
31
  numValidators: "5",
32
32
  headless: false,
33
33
  resetDb: false,
34
+ ollama: false,
34
35
  })
35
36
  );
36
37
  });
@@ -72,6 +73,7 @@ describe("up command", () => {
72
73
  numValidators: "5",
73
74
  headless: false,
74
75
  resetDb: false,
76
+ ollama: false,
75
77
  })
76
78
  );
77
79
  });
@@ -85,7 +87,8 @@ describe("up command", () => {
85
87
  "--numValidators",
86
88
  "10",
87
89
  "--headless",
88
- "--reset-db"
90
+ "--reset-db",
91
+ "--ollama",
89
92
  ]);
90
93
 
91
94
  expect(StartAction).toHaveBeenCalledTimes(1);
@@ -95,6 +98,7 @@ describe("up command", () => {
95
98
  numValidators: "10",
96
99
  headless: true,
97
100
  resetDb: true,
101
+ ollama: true,
98
102
  })
99
103
  );
100
104
  });
@@ -144,6 +144,33 @@ describe("SimulatorService - Basic Tests", () => {
144
144
  expect(result).toEqual({ stdout: "Simulator started", stderr: "" });
145
145
  });
146
146
 
147
+ test("should execute the correct run simulator command based on ollama option", async () => {
148
+ (executeCommand as Mock).mockResolvedValue({
149
+ stdout: "Simulator started",
150
+ stderr: "",
151
+ });
152
+
153
+ simulatorService.setComposeOptions(false, true);
154
+ let commandOptions = simulatorService.getComposeOptions();
155
+ expect(commandOptions).toBe("--profile frontend --profile ollama");
156
+
157
+ simulatorService.setComposeOptions(true, true);
158
+ commandOptions = simulatorService.getComposeOptions();
159
+ expect(commandOptions).toBe("--profile ollama");
160
+
161
+ simulatorService.setComposeOptions(false, false);
162
+ commandOptions = simulatorService.getComposeOptions();
163
+ expect(commandOptions).toBe("--profile frontend");
164
+
165
+ simulatorService.setComposeOptions(true, false);
166
+ commandOptions = simulatorService.getComposeOptions();
167
+ expect(commandOptions).toBe("");
168
+
169
+ await simulatorService.runSimulator();
170
+ const expectedCommand = DEFAULT_RUN_SIMULATOR_COMMAND(simulatorService.location, commandOptions);
171
+ expect(executeCommand).toHaveBeenCalledWith(expectedCommand);
172
+ });
173
+
147
174
  test("should create a backup of the .env file and add new config", () => {
148
175
  const envFilePath = `/.env`;
149
176
  const originalEnvContent = "KEY1=value1\nKEY2=value2";
@@ -277,6 +304,32 @@ describe("SimulatorService - Basic Tests", () => {
277
304
  expect(simulatorService.getAiProvidersOptions(false)).toEqual(expect.any(Array));
278
305
  });
279
306
 
307
+ test("should exclude specified providers from the options list", () => {
308
+ const allProviders = simulatorService.getAiProvidersOptions(false);
309
+ const providersWithoutOllama = simulatorService.getAiProvidersOptions(false, ["ollama"]);
310
+
311
+ expect(providersWithoutOllama.length).toBeLessThan(allProviders.length);
312
+
313
+ const ollamaProvider = providersWithoutOllama.find(p => p.value === "ollama");
314
+ expect(ollamaProvider).toBeUndefined();
315
+
316
+ const openaiProvider = providersWithoutOllama.find(p => p.value === "openai");
317
+ expect(openaiProvider).toBeDefined();
318
+ });
319
+
320
+ test("should exclude multiple providers when specified", () => {
321
+ const providersWithoutMultiple = simulatorService.getAiProvidersOptions(false, ["ollama", "openai"]);
322
+
323
+ const ollamaProvider = providersWithoutMultiple.find(p => p.value === "ollama");
324
+ const openaiProvider = providersWithoutMultiple.find(p => p.value === "openai");
325
+
326
+ expect(ollamaProvider).toBeUndefined();
327
+ expect(openaiProvider).toBeUndefined();
328
+
329
+ const heuristaiProvider = providersWithoutMultiple.find(p => p.value === "heuristai");
330
+ expect(heuristaiProvider).toBeDefined();
331
+ });
332
+
280
333
  test("clean simulator should success", async () => {
281
334
  vi.mocked(rpcClient.request).mockResolvedValueOnce('Success');
282
335
  await expect(simulatorService.cleanDatabase).not.toThrow();