@nitsan-ai/ragsuite-test 0.1.3 → 0.1.5
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/README.md +46 -71
- package/package.json +2 -3
- package/src/commands/doctor.js +16 -16
- package/src/commands/init.js +129 -85
- package/src/commands/logs.js +23 -35
- package/src/commands/start.js +12 -37
- package/src/commands/stop.js +15 -24
- package/src/commands/update.js +55 -52
- package/src/index.js +7 -7
- package/src/utils/args.js +10 -3
- package/src/utils/config.js +11 -26
- package/src/utils/distribution.js +10 -16
- package/src/utils/git-install.js +13 -8
- package/src/utils/global-config.js +61 -0
- package/src/utils/paths.js +81 -22
- package/src/utils/port.js +3 -4
- package/src/utils/prereqs.js +25 -65
- package/src/utils/images-install.js +0 -100
- package/templates/images/.env.example +0 -76
- package/templates/images/docker-compose.yml +0 -165
- package/templates/images/scripts/docker-doctor-images.sh +0 -48
- package/templates/images/scripts/docker-start-images.sh +0 -107
- package/templates/images/scripts/docker-stop-images.sh +0 -22
package/src/commands/start.js
CHANGED
|
@@ -2,25 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { resolveMode } = require('../utils/config');
|
|
5
|
-
const { resolveRepoRoot,
|
|
5
|
+
const { resolveRepoRoot, assertNativeDeploy } = require('../utils/paths');
|
|
6
6
|
const { runScript } = require('../utils/spawn');
|
|
7
7
|
const { assertApiPortFree } = require('../utils/port');
|
|
8
8
|
const { error } = require('../utils/log');
|
|
9
9
|
|
|
10
10
|
const name = 'start';
|
|
11
|
-
const summary = 'Start
|
|
11
|
+
const summary = 'Start app via npm scripts (native — no Docker)';
|
|
12
12
|
|
|
13
13
|
function help() {
|
|
14
14
|
return `Usage: ragsuite-test start [options]
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
Runs scripts/native-start.sh (same as \`npm start\` in the install dir).
|
|
17
|
+
Does not use Docker — no containers, no volume risk.
|
|
18
18
|
|
|
19
19
|
Options:
|
|
20
|
-
--
|
|
21
|
-
--repo-root <path> Install root
|
|
20
|
+
--repo-root <path> Override active install
|
|
22
21
|
--dry-run Print script path and exit 0
|
|
23
|
-
--detach, -d Detached start
|
|
24
22
|
`;
|
|
25
23
|
}
|
|
26
24
|
|
|
@@ -29,24 +27,14 @@ async function run(ctx) {
|
|
|
29
27
|
cwd: ctx.cwd,
|
|
30
28
|
repoRootFlag: ctx.globals.repoRoot,
|
|
31
29
|
});
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
repoRoot,
|
|
38
|
-
env: ctx.env,
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
let scriptName;
|
|
42
|
-
if (images) {
|
|
43
|
-
scriptName = 'docker-start-images.sh';
|
|
44
|
-
} else {
|
|
45
|
-
scriptName = mode === 'native' ? 'native-start.sh' : 'docker-start.sh';
|
|
30
|
+
try {
|
|
31
|
+
assertNativeDeploy(repoRoot);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
error(err.message);
|
|
34
|
+
return 1;
|
|
46
35
|
}
|
|
47
36
|
|
|
48
|
-
const
|
|
49
|
-
|
|
37
|
+
const mode = resolveMode();
|
|
50
38
|
if (!ctx.globals.dryRun) {
|
|
51
39
|
try {
|
|
52
40
|
await assertApiPortFree(ctx.env);
|
|
@@ -56,23 +44,10 @@ async function run(ctx) {
|
|
|
56
44
|
}
|
|
57
45
|
}
|
|
58
46
|
|
|
59
|
-
return runScript(repoRoot, path.join('scripts',
|
|
47
|
+
return runScript(repoRoot, path.join('scripts', 'native-start.sh'), [], {
|
|
60
48
|
dryRun: ctx.globals.dryRun,
|
|
61
49
|
env: { ...ctx.env, RAGSUITE_MODE: mode },
|
|
62
50
|
});
|
|
63
51
|
}
|
|
64
52
|
|
|
65
|
-
function normalizeStartArgs(args) {
|
|
66
|
-
const out = [];
|
|
67
|
-
for (const a of args) {
|
|
68
|
-
if (a === '--detach' || a === '-d') {
|
|
69
|
-
out.push('--detach');
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
if (a === '--') continue;
|
|
73
|
-
out.push(a);
|
|
74
|
-
}
|
|
75
|
-
return out;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
53
|
module.exports = { name, summary, help, run };
|
package/src/commands/stop.js
CHANGED
|
@@ -2,22 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { resolveMode } = require('../utils/config');
|
|
5
|
-
const { resolveRepoRoot,
|
|
5
|
+
const { resolveRepoRoot, assertNativeDeploy } = require('../utils/paths');
|
|
6
6
|
const { runScript } = require('../utils/spawn');
|
|
7
|
+
const { error } = require('../utils/log');
|
|
7
8
|
|
|
8
9
|
const name = 'stop';
|
|
9
|
-
const summary = 'Stop
|
|
10
|
+
const summary = 'Stop native app processes (does not touch Docker volumes)';
|
|
10
11
|
|
|
11
12
|
function help() {
|
|
12
13
|
return `Usage: ragsuite-test stop [options]
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Never wipes Docker volumes.
|
|
15
|
+
Runs scripts/native-stop.sh (same as \`npm run stop\` in the install dir).
|
|
16
|
+
Stops host processes only — never runs docker compose down.
|
|
17
17
|
|
|
18
18
|
Options:
|
|
19
|
-
--
|
|
20
|
-
--repo-root <path> Install root
|
|
19
|
+
--repo-root <path> Override active install
|
|
21
20
|
--dry-run Print script path and exit 0
|
|
22
21
|
`;
|
|
23
22
|
}
|
|
@@ -27,24 +26,16 @@ function run(ctx) {
|
|
|
27
26
|
cwd: ctx.cwd,
|
|
28
27
|
repoRootFlag: ctx.globals.repoRoot,
|
|
29
28
|
});
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const scriptName = images
|
|
40
|
-
? 'docker-stop-images.sh'
|
|
41
|
-
: mode === 'native'
|
|
42
|
-
? 'native-stop.sh'
|
|
43
|
-
: 'docker-stop.sh';
|
|
44
|
-
|
|
45
|
-
return runScript(repoRoot, path.join('scripts', scriptName), [], {
|
|
29
|
+
try {
|
|
30
|
+
assertNativeDeploy(repoRoot);
|
|
31
|
+
} catch (err) {
|
|
32
|
+
error(err.message);
|
|
33
|
+
return 1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return runScript(repoRoot, path.join('scripts', 'native-stop.sh'), [], {
|
|
46
37
|
dryRun: ctx.globals.dryRun,
|
|
47
|
-
env: { ...ctx.env, RAGSUITE_MODE:
|
|
38
|
+
env: { ...ctx.env, RAGSUITE_MODE: resolveMode() },
|
|
48
39
|
});
|
|
49
40
|
}
|
|
50
41
|
|
package/src/commands/update.js
CHANGED
|
@@ -2,86 +2,89 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
const { resolveRepoRoot } = require('../utils/paths');
|
|
5
|
+
const { resolveRepoRoot, assertNativeDeploy, looksLikeGitCheckout } = require('../utils/paths');
|
|
6
6
|
const { readConfig } = require('../utils/config');
|
|
7
|
+
const { setActiveInstall } = require('../utils/global-config');
|
|
7
8
|
const { captureCommand } = require('../utils/spawn');
|
|
8
|
-
const { info, warn } = require('../utils/log');
|
|
9
|
+
const { info, warn, error } = require('../utils/log');
|
|
9
10
|
|
|
10
11
|
const name = 'update';
|
|
11
|
-
const summary = '
|
|
12
|
+
const summary = 'git pull in place — keeps .env and data (no Docker)';
|
|
12
13
|
|
|
13
14
|
function help() {
|
|
14
|
-
return `Usage: ragsuite-test update
|
|
15
|
+
return `Usage: ragsuite-test update
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
Upgrades the active git install without wiping data:
|
|
18
|
+
• git pull --ff-only in the install dir
|
|
19
|
+
• Keeps .env and any host Postgres/Redis/Chroma data
|
|
18
20
|
|
|
19
|
-
Never runs docker compose
|
|
21
|
+
Never runs docker compose (no volume risk).
|
|
22
|
+
|
|
23
|
+
Typical flow after a new release:
|
|
24
|
+
npm install -g @nitsan-ai/ragsuite-test@latest
|
|
25
|
+
ragsuite-test update
|
|
26
|
+
ragsuite-test start
|
|
20
27
|
|
|
21
28
|
Options:
|
|
22
|
-
--repo-root <path>
|
|
29
|
+
--repo-root <path> Override active install
|
|
30
|
+
--dry-run Print actions only
|
|
23
31
|
`;
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
function run(ctx) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
let repoRoot;
|
|
36
|
+
try {
|
|
37
|
+
repoRoot = resolveRepoRoot({
|
|
38
|
+
cwd: ctx.cwd,
|
|
39
|
+
repoRootFlag: ctx.globals.repoRoot,
|
|
40
|
+
env: ctx.env,
|
|
41
|
+
});
|
|
42
|
+
assertNativeDeploy(repoRoot);
|
|
43
|
+
} catch (err) {
|
|
44
|
+
error(err.message);
|
|
45
|
+
return 1;
|
|
46
|
+
}
|
|
32
47
|
|
|
48
|
+
setActiveInstall(repoRoot);
|
|
33
49
|
const cfg = readConfig(repoRoot);
|
|
34
|
-
const source = (cfg && cfg.source) || '
|
|
35
|
-
|
|
36
|
-
info(`Install path OK: ${repoRoot}`);
|
|
37
|
-
info(` source=${source}`);
|
|
38
|
-
info('');
|
|
50
|
+
const source = (cfg && cfg.source) || 'git';
|
|
39
51
|
|
|
40
|
-
info(
|
|
41
|
-
info(
|
|
42
|
-
info('
|
|
43
|
-
info(' 3. Docker: npm run rebuild or docker compose build');
|
|
44
|
-
info(' 4. Native: re-run backend/scripts/setup.sh if Python deps changed');
|
|
45
|
-
info(' 5. Start again (ragsuite-test start --repo-root …)');
|
|
46
|
-
info(' 6. Run doctor after upgrades');
|
|
47
|
-
info('');
|
|
48
|
-
info('Never: docker compose down -v (destroys Postgres/Chroma data).');
|
|
52
|
+
info(`Updating install: ${repoRoot}`);
|
|
53
|
+
info(` source=${source} mode=native`);
|
|
54
|
+
info(' (.env and database data are kept)');
|
|
49
55
|
info('');
|
|
50
56
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
warn('No .git directory — skip fetch/status. Re-init with --from-git if needed.');
|
|
57
|
+
if (ctx.globals.dryRun) {
|
|
58
|
+
info('[dry-run] would update via git pull --ff-only');
|
|
54
59
|
return 0;
|
|
55
60
|
}
|
|
56
61
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return 0;
|
|
62
|
+
if (!looksLikeGitCheckout(repoRoot) && !fs.existsSync(path.join(repoRoot, '.git'))) {
|
|
63
|
+
error('This install has no .git directory. Re-run: ragsuite-test init --force');
|
|
64
|
+
return 1;
|
|
61
65
|
}
|
|
62
66
|
|
|
63
|
-
info('
|
|
64
|
-
|
|
65
|
-
info('');
|
|
66
|
-
info('Running git fetch (non-destructive)…');
|
|
67
|
-
const fetch = captureCommand('git', ['fetch', '--all', '--prune'], {
|
|
67
|
+
info('Fetching and pulling latest from git (non-destructive)…');
|
|
68
|
+
const pull = captureCommand('git', ['pull', '--ff-only'], {
|
|
68
69
|
cwd: repoRoot,
|
|
69
70
|
env: ctx.env,
|
|
70
71
|
});
|
|
71
|
-
if (
|
|
72
|
-
warn(
|
|
73
|
-
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const status = captureCommand('git', ['status', '-sb'], { cwd: repoRoot, env: ctx.env });
|
|
81
|
-
if (status.stdout) {
|
|
82
|
-
info('');
|
|
83
|
-
info(String(status.stdout).trimEnd());
|
|
72
|
+
if (pull.status !== 0) {
|
|
73
|
+
warn(`git pull --ff-only failed (exit ${pull.status}). Trying fetch + status…`);
|
|
74
|
+
if (pull.stderr) warn(String(pull.stderr).trimEnd());
|
|
75
|
+
captureCommand('git', ['fetch', '--all', '--prune'], { cwd: repoRoot, env: ctx.env });
|
|
76
|
+
const st = captureCommand('git', ['status', '-sb'], { cwd: repoRoot, env: ctx.env });
|
|
77
|
+
if (st.stdout) info(String(st.stdout).trimEnd());
|
|
78
|
+
error('Could not fast-forward. Fix local commits or stash, then: cd install && git pull');
|
|
79
|
+
return 1;
|
|
84
80
|
}
|
|
81
|
+
if (pull.stdout) info(String(pull.stdout).trimEnd());
|
|
82
|
+
info('git pull OK.');
|
|
83
|
+
info('');
|
|
84
|
+
info('Restart to apply:');
|
|
85
|
+
info(' ragsuite-test stop');
|
|
86
|
+
info(' ragsuite-test start');
|
|
87
|
+
info(' # or: cd install && npm run stop && npm start');
|
|
85
88
|
return 0;
|
|
86
89
|
}
|
|
87
90
|
|
package/src/index.js
CHANGED
|
@@ -19,7 +19,8 @@ function globalHelp() {
|
|
|
19
19
|
'RAGSuite test CLI (experimental)',
|
|
20
20
|
'',
|
|
21
21
|
'Usage: ragsuite-test <command> [options]',
|
|
22
|
-
'
|
|
22
|
+
'',
|
|
23
|
+
'Deploy path: git clone + native npm scripts (no Docker).',
|
|
23
24
|
'',
|
|
24
25
|
'Commands:',
|
|
25
26
|
];
|
|
@@ -30,9 +31,8 @@ function globalHelp() {
|
|
|
30
31
|
'',
|
|
31
32
|
'Global options:',
|
|
32
33
|
' --help, -h Show help',
|
|
33
|
-
' --repo-root <path>
|
|
34
|
+
' --repo-root <path> Override active install',
|
|
34
35
|
' --from-git [url] init: clone source (default public repo)',
|
|
35
|
-
' --from-images init: Docker images only (no app source on disk)',
|
|
36
36
|
' --install-dir <path> init: install target (default ~/ragsuite-test)',
|
|
37
37
|
' --llm-api-key <key> init: optional override for CUSTOM_LLM_INTERNAL_API_KEY',
|
|
38
38
|
' --smtp-host <host> init: optional SMTP override',
|
|
@@ -40,10 +40,10 @@ function globalHelp() {
|
|
|
40
40
|
' --smtp-password <pass> init: optional SMTP override',
|
|
41
41
|
' --email-from <email> init: optional SMTP override',
|
|
42
42
|
' --force init: overwrite non-empty install dir / .env',
|
|
43
|
-
' --yes, -y Non-interactive
|
|
44
|
-
' --
|
|
45
|
-
' --dry-run Print actions without running (start/stop/doctor/logs)',
|
|
43
|
+
' --yes, -y Non-interactive',
|
|
44
|
+
' --dry-run Print actions without running (start/stop/doctor/logs/update)',
|
|
46
45
|
'',
|
|
46
|
+
'Active install: ~/.ragsuite-test/config.json (set by init)',
|
|
47
47
|
'Env: RAGSUITE_REPO_ROOT or RAGSUITE_INSTALL_DIR',
|
|
48
48
|
' RAGSUITE_TEST_LLM_API_KEY, RAGSUITE_TEST_SMTP_* , RAGSUITE_TEST_EMAIL_FROM',
|
|
49
49
|
'',
|
|
@@ -93,7 +93,7 @@ async function main(argv = process.argv) {
|
|
|
93
93
|
const code = typeof result?.then === 'function' ? await result : result;
|
|
94
94
|
return typeof code === 'number' ? code : 0;
|
|
95
95
|
} catch (err) {
|
|
96
|
-
if (err && (err.code === 'NOT_REPO_ROOT' || err.code === 'USAGE' || err.code === 'INSTALL_DIR_NONEMPTY' || err.code === 'ENV_EXISTS' || err.code === 'ENV_INCOMPLETE' || err.code === 'PORT_IN_USE' || err.code === 'LLM_KEY_INVALID' || err.code === 'SMTP_REQUIRED' || err.code === 'GIT_CLONE_FAILED' || err.code === 'MISSING_GIT')) {
|
|
96
|
+
if (err && (err.code === 'NOT_REPO_ROOT' || err.code === 'USAGE' || err.code === 'INSTALL_DIR_NONEMPTY' || err.code === 'ENV_EXISTS' || err.code === 'ENV_INCOMPLETE' || err.code === 'PORT_IN_USE' || err.code === 'LLM_KEY_INVALID' || err.code === 'SMTP_REQUIRED' || err.code === 'GIT_CLONE_FAILED' || err.code === 'MISSING_GIT' || err.code === 'IMAGES_REMOVED' || err.code === 'NATIVE_SCRIPT_MISSING')) {
|
|
97
97
|
error(err.message);
|
|
98
98
|
return 1;
|
|
99
99
|
}
|
package/src/utils/args.js
CHANGED
|
@@ -72,7 +72,7 @@ function parseArgv(argv) {
|
|
|
72
72
|
const { value, nextI } = takeValue('--mode', t, i);
|
|
73
73
|
i = nextI;
|
|
74
74
|
if (!value || String(value).startsWith('-')) {
|
|
75
|
-
const err = new Error('--mode requires docker
|
|
75
|
+
const err = new Error('--mode requires native (docker was removed from deployment)');
|
|
76
76
|
err.code = 'USAGE';
|
|
77
77
|
throw err;
|
|
78
78
|
}
|
|
@@ -208,8 +208,15 @@ function parseArgv(argv) {
|
|
|
208
208
|
|
|
209
209
|
function normalizeMode(value) {
|
|
210
210
|
const m = String(value).trim().toLowerCase();
|
|
211
|
-
if (m
|
|
212
|
-
const err = new Error(
|
|
211
|
+
if (m === 'docker') {
|
|
212
|
+
const err = new Error(
|
|
213
|
+
'Docker mode was removed from deployment. Use native (omit --mode or pass --mode native).',
|
|
214
|
+
);
|
|
215
|
+
err.code = 'USAGE';
|
|
216
|
+
throw err;
|
|
217
|
+
}
|
|
218
|
+
if (m !== 'native') {
|
|
219
|
+
const err = new Error(`Invalid mode "${value}" (use native)`);
|
|
213
220
|
err.code = 'USAGE';
|
|
214
221
|
throw err;
|
|
215
222
|
}
|
package/src/utils/config.js
CHANGED
|
@@ -10,11 +10,11 @@ function configPath(repoRoot) {
|
|
|
10
10
|
return path.join(repoRoot, CONFIG_DIR, 'config.json');
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
function defaultConfig(repoRoot
|
|
13
|
+
function defaultConfig(repoRoot) {
|
|
14
14
|
const root = path.resolve(repoRoot);
|
|
15
15
|
return {
|
|
16
16
|
version: CONFIG_VERSION,
|
|
17
|
-
mode:
|
|
17
|
+
mode: 'native',
|
|
18
18
|
source: 'checkout',
|
|
19
19
|
repoRoot: root,
|
|
20
20
|
installDir: root,
|
|
@@ -23,7 +23,9 @@ function defaultConfig(repoRoot, mode = 'docker') {
|
|
|
23
23
|
|
|
24
24
|
function normalizeSource(raw) {
|
|
25
25
|
const s = String(raw || '').trim();
|
|
26
|
-
if (s === '
|
|
26
|
+
if (s === 'git' || s === 'checkout' || s === 'zip') return s === 'zip' ? 'checkout' : s;
|
|
27
|
+
// Legacy images installs are no longer supported for start/stop
|
|
28
|
+
if (s === 'images') return 'images';
|
|
27
29
|
return 'checkout';
|
|
28
30
|
}
|
|
29
31
|
|
|
@@ -39,7 +41,7 @@ function readConfig(repoRoot) {
|
|
|
39
41
|
}
|
|
40
42
|
return {
|
|
41
43
|
version: Number(raw.version) || CONFIG_VERSION,
|
|
42
|
-
mode:
|
|
44
|
+
mode: 'native',
|
|
43
45
|
source: normalizeSource(raw.source),
|
|
44
46
|
repoRoot: path.resolve(String(raw.repoRoot || repoRoot)),
|
|
45
47
|
installDir: path.resolve(String(raw.installDir || raw.repoRoot || repoRoot)),
|
|
@@ -62,37 +64,20 @@ function writeConfig(repoRoot, partial = {}) {
|
|
|
62
64
|
...existing,
|
|
63
65
|
...partial,
|
|
64
66
|
version: CONFIG_VERSION,
|
|
65
|
-
source,
|
|
67
|
+
source: source === 'images' ? 'git' : source,
|
|
66
68
|
repoRoot: path.resolve(partial.repoRoot || existing.repoRoot || repoRoot),
|
|
67
69
|
installDir: path.resolve(
|
|
68
70
|
partial.installDir || existing.installDir || partial.repoRoot || existing.repoRoot || repoRoot,
|
|
69
71
|
),
|
|
70
|
-
mode:
|
|
72
|
+
mode: 'native',
|
|
71
73
|
};
|
|
72
74
|
fs.writeFileSync(configPath(repoRoot), `${JSON.stringify(next, null, 2)}\n`, 'utf8');
|
|
73
75
|
return next;
|
|
74
76
|
}
|
|
75
77
|
|
|
76
|
-
/**
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
function resolveMode({ flagMode, repoRoot, env = process.env } = {}) {
|
|
80
|
-
if (flagMode === 'docker' || flagMode === 'native') {
|
|
81
|
-
return flagMode;
|
|
82
|
-
}
|
|
83
|
-
if (repoRoot) {
|
|
84
|
-
const cfg = readConfig(repoRoot);
|
|
85
|
-
if (cfg && (cfg.mode === 'docker' || cfg.mode === 'native')) {
|
|
86
|
-
return cfg.mode;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
const fromEnv = String(env.RAGSUITE_MODE || '')
|
|
90
|
-
.trim()
|
|
91
|
-
.toLowerCase();
|
|
92
|
-
if (fromEnv === 'native') {
|
|
93
|
-
return 'native';
|
|
94
|
-
}
|
|
95
|
-
return 'docker';
|
|
78
|
+
/** Deployment always uses native npm scripts. */
|
|
79
|
+
function resolveMode() {
|
|
80
|
+
return 'native';
|
|
96
81
|
}
|
|
97
82
|
|
|
98
83
|
module.exports = {
|
|
@@ -1,42 +1,36 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Distribution
|
|
5
|
-
*
|
|
6
|
-
* - git-clone: `ragsuite-test init` (source on disk)
|
|
7
|
-
* - images: `ragsuite-test init --from-images` (pull GHCR, no app source)
|
|
8
|
-
* - local-checkout: --repo-root
|
|
4
|
+
* Distribution for the testing CLI.
|
|
5
|
+
* Deploy path is git clone + native npm scripts only (no Docker).
|
|
9
6
|
*/
|
|
10
7
|
|
|
11
8
|
const MODE_LOCAL = 'local-checkout';
|
|
12
9
|
const MODE_GIT = 'git-clone';
|
|
13
|
-
const MODE_IMAGES = 'images';
|
|
14
|
-
const MODE_REGISTRY = 'registry-compose';
|
|
15
10
|
|
|
16
11
|
function assertSupportedInstall() {}
|
|
17
12
|
|
|
18
13
|
function resolveComposeBundle() {
|
|
19
|
-
const err = new Error(
|
|
20
|
-
'Use: ragsuite-test init --from-images (pull-only) OR ragsuite-test init (git source)',
|
|
21
|
-
);
|
|
14
|
+
const err = new Error('Docker compose bundles were removed from deployment. Use: ragsuite-test init');
|
|
22
15
|
err.code = 'DIST_NOT_READY';
|
|
23
16
|
throw err;
|
|
24
17
|
}
|
|
25
18
|
|
|
26
19
|
function installHint() {
|
|
27
20
|
return [
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
'
|
|
31
|
-
'
|
|
21
|
+
'Day-to-day (native / npm scripts — no Docker):',
|
|
22
|
+
' ragsuite-test start',
|
|
23
|
+
' ragsuite-test update',
|
|
24
|
+
' ragsuite-test stop',
|
|
25
|
+
'Or in the install dir:',
|
|
26
|
+
' npm start',
|
|
27
|
+
' npm run stop',
|
|
32
28
|
].join('\n');
|
|
33
29
|
}
|
|
34
30
|
|
|
35
31
|
module.exports = {
|
|
36
32
|
MODE_LOCAL,
|
|
37
33
|
MODE_GIT,
|
|
38
|
-
MODE_IMAGES,
|
|
39
|
-
MODE_REGISTRY,
|
|
40
34
|
mode: MODE_GIT,
|
|
41
35
|
assertSupportedInstall,
|
|
42
36
|
resolveComposeBundle,
|
package/src/utils/git-install.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
|
-
const os = require('os');
|
|
5
4
|
const path = require('path');
|
|
6
5
|
const { spawnSync } = require('child_process');
|
|
7
|
-
const {
|
|
6
|
+
const {
|
|
7
|
+
defaultInstallDir,
|
|
8
|
+
looksLikeFullBundleRoot,
|
|
9
|
+
looksLikeRepoRoot,
|
|
10
|
+
} = require('./paths');
|
|
8
11
|
|
|
9
12
|
/** Default public monorepo (when the GitHub repo is public). */
|
|
10
13
|
const DEFAULT_GIT_URL = 'https://github.com/nitsan-ai/RAGSUITE.git';
|
|
11
14
|
|
|
12
|
-
function defaultInstallDir() {
|
|
13
|
-
return path.join(os.homedir(), 'ragsuite-test');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
15
|
function requireGit() {
|
|
17
16
|
const which = spawnSync('which', ['git'], { encoding: 'utf8' });
|
|
18
17
|
if (which.status !== 0) {
|
|
@@ -49,7 +48,13 @@ function cloneGitToInstallDir(gitUrl, options = {}) {
|
|
|
49
48
|
if (!isDirEmptyOrMissing(target)) {
|
|
50
49
|
if (!force) {
|
|
51
50
|
const err = new Error(
|
|
52
|
-
|
|
51
|
+
[
|
|
52
|
+
`Install directory is not empty: ${target}`,
|
|
53
|
+
' If already installed: ragsuite-test start',
|
|
54
|
+
' To upgrade in place: ragsuite-test update',
|
|
55
|
+
' To wipe & reinstall: ragsuite-test init --force',
|
|
56
|
+
' Or use another path: ragsuite-test init --install-dir <path>',
|
|
57
|
+
].join('\n'),
|
|
53
58
|
);
|
|
54
59
|
err.code = 'INSTALL_DIR_NONEMPTY';
|
|
55
60
|
throw err;
|
|
@@ -76,7 +81,7 @@ function cloneGitToInstallDir(gitUrl, options = {}) {
|
|
|
76
81
|
const repoRoot = target;
|
|
77
82
|
if (!looksLikeRepoRoot(repoRoot) && !looksLikeFullBundleRoot(repoRoot)) {
|
|
78
83
|
const err = new Error(
|
|
79
|
-
`Cloned repo at ${repoRoot} does not look like a RAGSuite monorepo (missing scripts/docker-start.sh).`,
|
|
84
|
+
`Cloned repo at ${repoRoot} does not look like a RAGSuite monorepo (missing scripts/native-start.sh or docker-start.sh).`,
|
|
80
85
|
);
|
|
81
86
|
err.code = 'GIT_INVALID_REPO';
|
|
82
87
|
throw err;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
/** User-level CLI state (not inside the app install). Like other npm CLIs. */
|
|
8
|
+
function globalConfigDir() {
|
|
9
|
+
return path.join(os.homedir(), '.ragsuite-test');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function globalConfigPath() {
|
|
13
|
+
return path.join(globalConfigDir(), 'config.json');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function readGlobalConfig() {
|
|
17
|
+
const file = globalConfigPath();
|
|
18
|
+
if (!fs.existsSync(file)) return null;
|
|
19
|
+
try {
|
|
20
|
+
const raw = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
21
|
+
if (!raw || typeof raw !== 'object') return null;
|
|
22
|
+
return {
|
|
23
|
+
installDir: raw.installDir ? path.resolve(String(raw.installDir)) : null,
|
|
24
|
+
updatedAt: raw.updatedAt || null,
|
|
25
|
+
};
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function writeGlobalConfig(partial = {}) {
|
|
32
|
+
const dir = globalConfigDir();
|
|
33
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
34
|
+
const existing = readGlobalConfig() || {};
|
|
35
|
+
const next = {
|
|
36
|
+
...existing,
|
|
37
|
+
...partial,
|
|
38
|
+
updatedAt: new Date().toISOString(),
|
|
39
|
+
};
|
|
40
|
+
if (next.installDir) next.installDir = path.resolve(String(next.installDir));
|
|
41
|
+
fs.writeFileSync(globalConfigPath(), `${JSON.stringify(next, null, 2)}\n`, 'utf8');
|
|
42
|
+
return next;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function setActiveInstall(installDir) {
|
|
46
|
+
return writeGlobalConfig({ installDir: path.resolve(installDir) });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function getActiveInstall() {
|
|
50
|
+
const g = readGlobalConfig();
|
|
51
|
+
return g && g.installDir ? g.installDir : null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = {
|
|
55
|
+
globalConfigDir,
|
|
56
|
+
globalConfigPath,
|
|
57
|
+
readGlobalConfig,
|
|
58
|
+
writeGlobalConfig,
|
|
59
|
+
setActiveInstall,
|
|
60
|
+
getActiveInstall,
|
|
61
|
+
};
|