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 +6 -0
- package/dist/index.js +29 -22
- package/docker-compose.yml +6 -1
- package/package.json +1 -1
- package/src/commands/general/index.ts +2 -0
- package/src/commands/general/init.ts +3 -2
- package/src/commands/general/start.ts +4 -3
- package/src/commands/update/ollama.ts +1 -1
- package/src/lib/config/simulator.ts +5 -5
- package/src/lib/interfaces/ISimulatorService.ts +2 -2
- package/src/lib/services/simulator.ts +25 -13
- package/tests/actions/init.test.ts +26 -0
- package/tests/actions/ollama.test.ts +2 -2
- package/tests/actions/start.test.ts +14 -0
- package/tests/commands/init.test.ts +8 -1
- package/tests/commands/up.test.ts +5 -1
- package/tests/services/simulator.test.ts +53 -0
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.
|
|
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.
|
|
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,
|
|
16952
|
-
darwin: `osascript -e 'tell application "Terminal" to do script "cd ${location} && docker compose build && docker compose -p genlayer
|
|
16953
|
-
win32: `start cmd.exe /c "cd /d ${location} && docker compose build && docker compose -p genlayer
|
|
16954
|
-
linux: `nohup bash -c 'cd ${location} && docker compose build && docker compose -p genlayer
|
|
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, "
|
|
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.
|
|
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)
|
|
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
|
-
|
|
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.
|
|
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
|
});
|
package/docker-compose.yml
CHANGED
|
@@ -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
|
@@ -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.
|
|
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,
|
|
6
|
-
darwin: `osascript -e 'tell application "Terminal" to do script "cd ${location} && docker compose build && docker compose -p genlayer
|
|
7
|
-
win32: `start cmd.exe /c "cd /d ${location} && docker compose build && docker compose -p genlayer
|
|
8
|
-
linux: `nohup bash -c 'cd ${location} && docker compose build && docker compose -p genlayer
|
|
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
|
|
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.
|
|
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)
|
|
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
|
-
|
|
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.
|
|
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)
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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();
|