@cortex-context/cli 0.0.13 → 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +232 -24
- package/dist/index.js.map +1 -1
- package/dist/templates/local/docker-compose.local.yml +14 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -18309,12 +18309,26 @@ async function deployLocalStack(workspacePath, opts = {}) {
|
|
|
18309
18309
|
if (!(0, import_fs5.existsSync)(templatePath)) {
|
|
18310
18310
|
return { started: false, error: `Template not found: ${templatePath}` };
|
|
18311
18311
|
}
|
|
18312
|
-
|
|
18313
|
-
|
|
18314
|
-
|
|
18312
|
+
(0, import_fs5.cpSync)(templatePath, destPath);
|
|
18313
|
+
const specsSample = (0, import_path5.join)(workspacePath, "specs-sample");
|
|
18314
|
+
const reposSample = (0, import_path5.join)(workspacePath, "repos-sample");
|
|
18315
|
+
(0, import_fs5.mkdirSync)(specsSample, { recursive: true });
|
|
18316
|
+
(0, import_fs5.mkdirSync)(reposSample, { recursive: true });
|
|
18315
18317
|
const envPath = (0, import_path5.join)(workspacePath, ".env");
|
|
18316
|
-
|
|
18317
|
-
|
|
18318
|
+
let existingEnv = "";
|
|
18319
|
+
if ((0, import_fs5.existsSync)(envPath)) {
|
|
18320
|
+
existingEnv = (0, import_fs5.readFileSync)(envPath, "utf-8");
|
|
18321
|
+
}
|
|
18322
|
+
const setEnvVar = (content, key, value) => {
|
|
18323
|
+
const re = new RegExp(`^${key}=.*$`, "m");
|
|
18324
|
+
const line = `${key}=${value}`;
|
|
18325
|
+
return re.test(content) ? content.replace(re, line) : content + (content.endsWith("\n") || !content ? "" : "\n") + line + "\n";
|
|
18326
|
+
};
|
|
18327
|
+
let envContent = existingEnv;
|
|
18328
|
+
envContent = setEnvVar(envContent, "CORTEX_API_TOKEN", opts.token ?? "");
|
|
18329
|
+
envContent = setEnvVar(envContent, "SPECS_DIR_HOST", opts.specsDir ?? "./specs-sample");
|
|
18330
|
+
envContent = setEnvVar(envContent, "REPOS_DIR_HOST", opts.reposDir ?? "./repos-sample");
|
|
18331
|
+
if (!envContent.endsWith("\n")) envContent += "\n";
|
|
18318
18332
|
(0, import_fs5.writeFileSync)(envPath, envContent, { encoding: "utf-8" });
|
|
18319
18333
|
const imageTag = opts.embeddings ? "latest-embeddings" : "latest";
|
|
18320
18334
|
const cortexImage = `ghcr.io/rodrigoroldan/cortex-context:${imageTag}`;
|
|
@@ -18342,6 +18356,66 @@ ${stderr.trim()}` : ""}`
|
|
|
18342
18356
|
};
|
|
18343
18357
|
}
|
|
18344
18358
|
}
|
|
18359
|
+
async function upgradeLocalStack(workspacePath, opts = {}) {
|
|
18360
|
+
const composePath = (0, import_path5.join)(workspacePath, "docker-compose.local.yml");
|
|
18361
|
+
if (!(0, import_fs5.existsSync)(composePath)) {
|
|
18362
|
+
return {
|
|
18363
|
+
upgraded: false,
|
|
18364
|
+
error: `docker-compose.local.yml not found in ${workspacePath}. Run: cortex-context server`
|
|
18365
|
+
};
|
|
18366
|
+
}
|
|
18367
|
+
const imageTag = opts.embeddings ? "latest-embeddings" : "latest";
|
|
18368
|
+
const cortexImage = `ghcr.io/rodrigoroldan/cortex-context:${imageTag}`;
|
|
18369
|
+
const composeCmd = `docker compose --project-name cortex-local -f "${composePath}"`;
|
|
18370
|
+
try {
|
|
18371
|
+
(0, import_child_process.execSync)(`${composeCmd} pull cortex-api`, {
|
|
18372
|
+
cwd: workspacePath,
|
|
18373
|
+
stdio: ["inherit", "inherit", "pipe"],
|
|
18374
|
+
env: { ...process.env, CORTEX_IMAGE: cortexImage }
|
|
18375
|
+
});
|
|
18376
|
+
} catch (err) {
|
|
18377
|
+
const stderr = err instanceof Error && "stderr" in err ? err.stderr?.toString() ?? "" : "";
|
|
18378
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
18379
|
+
return {
|
|
18380
|
+
upgraded: false,
|
|
18381
|
+
error: `docker compose pull failed: ${msg}${stderr ? `
|
|
18382
|
+
${stderr.trim()}` : ""}`
|
|
18383
|
+
};
|
|
18384
|
+
}
|
|
18385
|
+
try {
|
|
18386
|
+
(0, import_child_process.execSync)(`${composeCmd} up -d --no-deps --force-recreate cortex-api`, {
|
|
18387
|
+
cwd: workspacePath,
|
|
18388
|
+
stdio: ["inherit", "inherit", "pipe"],
|
|
18389
|
+
env: { ...process.env, CORTEX_IMAGE: cortexImage }
|
|
18390
|
+
});
|
|
18391
|
+
} catch (err) {
|
|
18392
|
+
const stderr = err instanceof Error && "stderr" in err ? err.stderr?.toString() ?? "" : "";
|
|
18393
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
18394
|
+
return {
|
|
18395
|
+
upgraded: false,
|
|
18396
|
+
error: `docker compose up failed: ${msg}${stderr ? `
|
|
18397
|
+
${stderr.trim()}` : ""}`
|
|
18398
|
+
};
|
|
18399
|
+
}
|
|
18400
|
+
return { upgraded: true };
|
|
18401
|
+
}
|
|
18402
|
+
function restartCortexApi(workspacePath) {
|
|
18403
|
+
const composePath = (0, import_path5.join)(workspacePath, "docker-compose.local.yml");
|
|
18404
|
+
if (!(0, import_fs5.existsSync)(composePath))
|
|
18405
|
+
return { restarted: false, error: "docker-compose.local.yml not found" };
|
|
18406
|
+
try {
|
|
18407
|
+
(0, import_child_process.execSync)(
|
|
18408
|
+
`docker compose --project-name cortex-local -f "${composePath}" restart cortex-api`,
|
|
18409
|
+
{ cwd: workspacePath, stdio: "ignore" }
|
|
18410
|
+
);
|
|
18411
|
+
return { restarted: true };
|
|
18412
|
+
} catch (err) {
|
|
18413
|
+
return {
|
|
18414
|
+
restarted: false,
|
|
18415
|
+
error: err instanceof Error ? err.message : String(err)
|
|
18416
|
+
};
|
|
18417
|
+
}
|
|
18418
|
+
}
|
|
18345
18419
|
function isDockerAvailable() {
|
|
18346
18420
|
try {
|
|
18347
18421
|
(0, import_child_process.execSync)("docker --version", { stdio: "ignore" });
|
|
@@ -18619,7 +18693,7 @@ async function initCommand(options) {
|
|
|
18619
18693
|
const spinner2 = ora(
|
|
18620
18694
|
" Starting Cortex stack with Docker Compose..."
|
|
18621
18695
|
).start();
|
|
18622
|
-
const dockerResult = await deployLocalStack(workspacePath);
|
|
18696
|
+
const dockerResult = await deployLocalStack(workspacePath, { token: cortexToken });
|
|
18623
18697
|
if (!dockerResult.started) {
|
|
18624
18698
|
spinner2.fail(
|
|
18625
18699
|
source_default.red(` \u2717 Docker deploy failed: ${dockerResult.error}`)
|
|
@@ -28720,6 +28794,39 @@ var import_os5 = require("os");
|
|
|
28720
28794
|
var import_prompts6 = __toESM(require_prompts3());
|
|
28721
28795
|
var CORTEX_DIR = (0, import_path15.join)((0, import_os5.homedir)(), ".cortex-context");
|
|
28722
28796
|
var ENV_FILE = (0, import_path15.join)(CORTEX_DIR, ".env");
|
|
28797
|
+
async function applyTokenRestart() {
|
|
28798
|
+
if (!isDockerAvailable()) return;
|
|
28799
|
+
console.log(
|
|
28800
|
+
source_default.dim(" Restarting cortex-api container to apply new token...")
|
|
28801
|
+
);
|
|
28802
|
+
const result = restartCortexApi(CORTEX_DIR);
|
|
28803
|
+
if (!result.restarted) {
|
|
28804
|
+
console.log(
|
|
28805
|
+
source_default.yellow(
|
|
28806
|
+
` \u26A0 Could not restart container: ${result.error ?? "unknown error"}`
|
|
28807
|
+
)
|
|
28808
|
+
);
|
|
28809
|
+
console.log(
|
|
28810
|
+
source_default.dim(
|
|
28811
|
+
" docker compose -f ~/.cortex-context/docker-compose.local.yml restart cortex-api"
|
|
28812
|
+
)
|
|
28813
|
+
);
|
|
28814
|
+
return;
|
|
28815
|
+
}
|
|
28816
|
+
const config2 = readConfig();
|
|
28817
|
+
const url = config2.url ?? "http://localhost:8082";
|
|
28818
|
+
console.log(source_default.dim(` Waiting for Cortex API at ${url}...`));
|
|
28819
|
+
const { healthy } = await waitForCortexHealth(url, 6e4);
|
|
28820
|
+
if (healthy) {
|
|
28821
|
+
console.log(source_default.green(" \u2713 Container restarted and healthy"));
|
|
28822
|
+
} else {
|
|
28823
|
+
console.log(
|
|
28824
|
+
source_default.yellow(
|
|
28825
|
+
" \u26A0 Container restarted but did not become healthy within 60s"
|
|
28826
|
+
)
|
|
28827
|
+
);
|
|
28828
|
+
}
|
|
28829
|
+
}
|
|
28723
28830
|
function readEnvToken() {
|
|
28724
28831
|
if (!(0, import_fs14.existsSync)(ENV_FILE)) return "";
|
|
28725
28832
|
const content = (0, import_fs14.readFileSync)(ENV_FILE, "utf-8");
|
|
@@ -28756,15 +28863,8 @@ async function tokenCommand(options) {
|
|
|
28756
28863
|
console.log(
|
|
28757
28864
|
source_default.green(newToken ? " \u2713 Token updated" : " \u2713 Token cleared")
|
|
28758
28865
|
);
|
|
28759
|
-
|
|
28760
|
-
|
|
28761
|
-
console.log(source_default.dim(" Restart the Cortex container to apply:"));
|
|
28762
|
-
console.log(
|
|
28763
|
-
source_default.cyan(
|
|
28764
|
-
" docker compose -f ~/.cortex-context/docker-compose.local.yml restart cortex-api"
|
|
28765
|
-
)
|
|
28766
|
-
);
|
|
28767
|
-
}
|
|
28866
|
+
console.log("");
|
|
28867
|
+
await applyTokenRestart();
|
|
28768
28868
|
console.log("");
|
|
28769
28869
|
return;
|
|
28770
28870
|
}
|
|
@@ -28805,12 +28905,8 @@ async function tokenCommand(options) {
|
|
|
28805
28905
|
` cortex-context init --url ${config3.url ?? "http://localhost:8082"} --token ${newToken}`
|
|
28806
28906
|
)
|
|
28807
28907
|
);
|
|
28808
|
-
console.log(
|
|
28809
|
-
|
|
28810
|
-
source_default.cyan(
|
|
28811
|
-
" docker compose -f ~/.cortex-context/docker-compose.local.yml restart cortex-api"
|
|
28812
|
-
)
|
|
28813
|
-
);
|
|
28908
|
+
console.log("");
|
|
28909
|
+
await applyTokenRestart();
|
|
28814
28910
|
console.log("");
|
|
28815
28911
|
return;
|
|
28816
28912
|
}
|
|
@@ -28834,11 +28930,114 @@ async function tokenCommand(options) {
|
|
|
28834
28930
|
console.log("");
|
|
28835
28931
|
}
|
|
28836
28932
|
|
|
28837
|
-
// src/
|
|
28838
|
-
var import_fs15 = require("fs");
|
|
28933
|
+
// src/commands/upgrade.ts
|
|
28839
28934
|
var import_path16 = require("path");
|
|
28935
|
+
var import_os6 = require("os");
|
|
28936
|
+
var import_fs15 = require("fs");
|
|
28937
|
+
async function upgradeCommand(options) {
|
|
28938
|
+
console.log("");
|
|
28939
|
+
console.log(source_default.bold.cyan(" \u25C6 Cortex Context \u2014 Upgrade"));
|
|
28940
|
+
console.log(
|
|
28941
|
+
source_default.dim(
|
|
28942
|
+
" Pulls the latest backend image and recreates the cortex-api container."
|
|
28943
|
+
)
|
|
28944
|
+
);
|
|
28945
|
+
console.log("");
|
|
28946
|
+
if (!isDockerAvailable()) {
|
|
28947
|
+
console.error(source_default.red(" \u2717 Docker is not available on $PATH."));
|
|
28948
|
+
console.log(
|
|
28949
|
+
source_default.dim(" Install Docker or ensure it is running, then retry.")
|
|
28950
|
+
);
|
|
28951
|
+
process.exit(1);
|
|
28952
|
+
}
|
|
28953
|
+
const workDir = options.dir ?? (0, import_path16.join)((0, import_os6.homedir)(), ".cortex-context");
|
|
28954
|
+
const composePath = (0, import_path16.join)(workDir, "docker-compose.local.yml");
|
|
28955
|
+
if (!(0, import_fs15.existsSync)(composePath)) {
|
|
28956
|
+
console.error(
|
|
28957
|
+
source_default.red(` \u2717 docker-compose.local.yml not found in ${workDir}`)
|
|
28958
|
+
);
|
|
28959
|
+
console.log(
|
|
28960
|
+
source_default.dim(" The local Cortex stack has not been set up yet. Run:")
|
|
28961
|
+
);
|
|
28962
|
+
console.log(source_default.cyan(" cortex-context server"));
|
|
28963
|
+
console.log("");
|
|
28964
|
+
process.exit(1);
|
|
28965
|
+
}
|
|
28966
|
+
const imageTag = options.embeddings ? "latest-embeddings" : "latest";
|
|
28967
|
+
const cortexImage = `ghcr.io/rodrigoroldan/cortex-context:${imageTag}`;
|
|
28968
|
+
console.log(source_default.dim(` Target image: ${cortexImage}`));
|
|
28969
|
+
console.log(source_default.dim(` Compose dir: ${workDir}`));
|
|
28970
|
+
console.log("");
|
|
28971
|
+
console.log(source_default.bold(" Step 1 \u2014 Pulling latest image..."));
|
|
28972
|
+
if (options.pullOnly) {
|
|
28973
|
+
const { execSync: execSync3 } = await import("child_process");
|
|
28974
|
+
try {
|
|
28975
|
+
execSync3(
|
|
28976
|
+
`docker compose --project-name cortex-local -f "${composePath}" pull cortex-api`,
|
|
28977
|
+
{
|
|
28978
|
+
cwd: workDir,
|
|
28979
|
+
stdio: ["inherit", "inherit", "pipe"],
|
|
28980
|
+
env: { ...process.env, CORTEX_IMAGE: cortexImage }
|
|
28981
|
+
}
|
|
28982
|
+
);
|
|
28983
|
+
console.log("");
|
|
28984
|
+
console.log(
|
|
28985
|
+
source_default.green(" \u2713 Image pulled successfully (--pull-only mode)")
|
|
28986
|
+
);
|
|
28987
|
+
console.log(
|
|
28988
|
+
source_default.dim(
|
|
28989
|
+
" Run without --pull-only to recreate the container with the new image."
|
|
28990
|
+
)
|
|
28991
|
+
);
|
|
28992
|
+
console.log("");
|
|
28993
|
+
} catch (err) {
|
|
28994
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
28995
|
+
console.error(source_default.red(` \u2717 Pull failed: ${msg}`));
|
|
28996
|
+
process.exit(1);
|
|
28997
|
+
}
|
|
28998
|
+
return;
|
|
28999
|
+
}
|
|
29000
|
+
const result = await upgradeLocalStack(workDir, {
|
|
29001
|
+
embeddings: options.embeddings
|
|
29002
|
+
});
|
|
29003
|
+
if (!result.upgraded) {
|
|
29004
|
+
console.error(source_default.red(` \u2717 Upgrade failed: ${result.error}`));
|
|
29005
|
+
process.exit(1);
|
|
29006
|
+
}
|
|
29007
|
+
console.log("");
|
|
29008
|
+
console.log(source_default.bold(" Step 2 \u2014 Waiting for Cortex API to be healthy..."));
|
|
29009
|
+
const config2 = readConfig();
|
|
29010
|
+
const cortexUrl = config2.url ?? "http://localhost:8082";
|
|
29011
|
+
const { healthy } = await waitForCortexHealth(cortexUrl, 12e4);
|
|
29012
|
+
console.log("");
|
|
29013
|
+
if (healthy) {
|
|
29014
|
+
console.log(source_default.green(" \u2713 Cortex API is healthy"));
|
|
29015
|
+
console.log("");
|
|
29016
|
+
console.log(source_default.bold(" \u25C6 Upgrade complete!"));
|
|
29017
|
+
console.log(source_default.dim(` API running at ${cortexUrl}`));
|
|
29018
|
+
console.log("");
|
|
29019
|
+
} else {
|
|
29020
|
+
console.log(
|
|
29021
|
+
source_default.yellow(
|
|
29022
|
+
" \u26A0 Container is up but did not become healthy within 120s"
|
|
29023
|
+
)
|
|
29024
|
+
);
|
|
29025
|
+
console.log(source_default.dim(" Check container logs:"));
|
|
29026
|
+
console.log(
|
|
29027
|
+
source_default.cyan(
|
|
29028
|
+
` docker compose -f ${workDir}/docker-compose.local.yml logs cortex-api`
|
|
29029
|
+
)
|
|
29030
|
+
);
|
|
29031
|
+
console.log("");
|
|
29032
|
+
process.exit(1);
|
|
29033
|
+
}
|
|
29034
|
+
}
|
|
29035
|
+
|
|
29036
|
+
// src/cli.ts
|
|
29037
|
+
var import_fs16 = require("fs");
|
|
29038
|
+
var import_path17 = require("path");
|
|
28840
29039
|
var pkg = JSON.parse(
|
|
28841
|
-
(0,
|
|
29040
|
+
(0, import_fs16.readFileSync)((0, import_path17.join)(__dirname, "..", "package.json"), "utf-8")
|
|
28842
29041
|
);
|
|
28843
29042
|
function createCli() {
|
|
28844
29043
|
const program3 = new Command();
|
|
@@ -28892,6 +29091,15 @@ function createCli() {
|
|
|
28892
29091
|
"--set <value>",
|
|
28893
29092
|
"Set a specific token value (empty string clears auth)"
|
|
28894
29093
|
).action(tokenCommand);
|
|
29094
|
+
program3.command("upgrade").description(
|
|
29095
|
+
"Pull the latest Cortex backend image and restart the local stack"
|
|
29096
|
+
).option(
|
|
29097
|
+
"--dir <path>",
|
|
29098
|
+
"Directory with docker-compose.local.yml (defaults to ~/.cortex-context)"
|
|
29099
|
+
).option("--embeddings", "Use the embeddings-enabled image variant").option(
|
|
29100
|
+
"--pull-only",
|
|
29101
|
+
"Pull the latest image without recreating the container"
|
|
29102
|
+
).action(upgradeCommand);
|
|
28895
29103
|
return program3;
|
|
28896
29104
|
}
|
|
28897
29105
|
|