@nitsan-ai/ragsuite-test 0.1.1 → 0.1.3
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 +61 -63
- package/package.json +3 -2
- package/src/commands/doctor.js +17 -13
- package/src/commands/init.js +67 -112
- package/src/commands/start.js +25 -17
- package/src/commands/stop.js +23 -13
- package/src/index.js +4 -3
- package/src/utils/args.js +6 -0
- package/src/utils/config.js +11 -5
- package/src/utils/distribution.js +11 -11
- package/src/utils/images-install.js +100 -0
- package/src/utils/paths.js +34 -9
- package/templates/images/.env.example +76 -0
- package/templates/images/docker-compose.yml +165 -0
- package/templates/images/scripts/docker-doctor-images.sh +48 -0
- package/templates/images/scripts/docker-start-images.sh +107 -0
- package/templates/images/scripts/docker-stop-images.sh +22 -0
package/README.md
CHANGED
|
@@ -1,102 +1,100 @@
|
|
|
1
1
|
# RAGSuite test CLI (`ragsuite-test`)
|
|
2
2
|
|
|
3
|
-
> **TESTING PACKAGE** —
|
|
4
|
-
> **Not** the final production `@nitsan-ai/ragsuite` / `ragsuite` CLI (later release).
|
|
3
|
+
> **TESTING PACKAGE** — temporary name before the final `ragsuite` CLI.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
Two ways to run. Pick one:
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
| | **A) Git source** | **B) Docker images only** |
|
|
8
|
+
|--|-------------------|---------------------------|
|
|
9
|
+
| Command | `ragsuite-test init` | `ragsuite-test init --from-images` |
|
|
10
|
+
| On disk | Full monorepo clone | Tiny compose bundle only |
|
|
11
|
+
| App code visible? | Yes | **No** (runs in containers) |
|
|
12
|
+
| Needs | git + Node; Docker *or* native Postgres/Redis | Node + **Docker** |
|
|
13
|
+
| Best for | Dev, debugging, native mode, reading code | Testers / “just run the app” |
|
|
14
|
+
| Pros | Native mode; full scripts; offline rebuild from source | No source leak; faster to start; smaller disk |
|
|
15
|
+
| Cons | Source on disk; larger checkout | Needs published GHCR images; Docker required; no native mode |
|
|
9
16
|
|
|
10
|
-
|
|
17
|
+
---
|
|
11
18
|
|
|
12
|
-
|
|
13
|
-
|------|-----|----------------|
|
|
14
|
-
| Node.js 18+ | CLI + native frontend tooling | https://nodejs.org · `brew install node` · `sudo apt install nodejs` |
|
|
15
|
-
| git | `--from-git` clone | `xcode-select --install` · `brew install git` · `sudo apt install git` |
|
|
16
|
-
| **SMTP** | No prompts. Real values only in **local `.env`** (gitignored) | Gmail App Password → edit `.env` |
|
|
17
|
-
| LLM API key | Default in `.env.example` / `.env` — no prompt | Override in `.env` or `--llm-api-key` |
|
|
18
|
-
| **Either Docker** *or* **native data stores** | Run the stack | See modes below |
|
|
19
|
+
## A) Git source (clone)
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g @nitsan-ai/ragsuite-test
|
|
23
|
+
ragsuite-test init
|
|
24
|
+
# clones https://github.com/nitsan-ai/RAGSUITE.git → ~/ragsuite-test
|
|
25
|
+
# auto: docker if daemon up, else native
|
|
21
26
|
|
|
22
|
-
-
|
|
23
|
-
|
|
27
|
+
ragsuite-test start --repo-root ~/ragsuite-test --detach # docker
|
|
28
|
+
# or after init --mode native:
|
|
29
|
+
# ragsuite-test start --repo-root ~/ragsuite-test
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
# API http://localhost:9090
|
|
32
|
+
# Web http://localhost:9091 (docker) or :9191 (native)
|
|
33
|
+
ragsuite-test stop --repo-root ~/ragsuite-test
|
|
34
|
+
```
|
|
26
35
|
|
|
27
|
-
|
|
28
|
-
- Postgres on **localhost:5436**, database `ragsuite_v3`
|
|
29
|
-
- Redis on **localhost:6382**
|
|
36
|
+
### Native (no Docker) — git install only
|
|
30
37
|
|
|
31
|
-
|
|
38
|
+
Needs Postgres `:5436` (`ragsuite_v3`) and Redis `:6382`:
|
|
32
39
|
|
|
33
40
|
```bash
|
|
34
|
-
|
|
41
|
+
ragsuite-test init --mode native
|
|
42
|
+
ragsuite-test start --repo-root ~/ragsuite-test
|
|
43
|
+
```
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
--from-git \
|
|
38
|
-
--install-dir ~/ragsuite-test \
|
|
39
|
-
--mode docker
|
|
45
|
+
---
|
|
40
46
|
|
|
41
|
-
|
|
42
|
-
# API http://localhost:9090 · Web http://localhost:9091
|
|
43
|
-
```
|
|
47
|
+
## B) Docker images (no source on disk)
|
|
44
48
|
|
|
45
|
-
|
|
49
|
+
**Maintainer (once):** publish images — Actions → **Publish images (GHCR)**
|
|
50
|
+
(packages: `ghcr.io/nitsan-ai/ragsuite-backend`, `…/ragsuite-frontend`)
|
|
46
51
|
|
|
47
|
-
|
|
52
|
+
**User:**
|
|
48
53
|
|
|
49
54
|
```bash
|
|
50
|
-
|
|
51
|
-
ragsuite-test
|
|
52
|
-
|
|
55
|
+
npm install -g @nitsan-ai/ragsuite-test
|
|
56
|
+
ragsuite-test init --from-images
|
|
57
|
+
ragsuite-test start --repo-root ~/ragsuite-test --detach
|
|
58
|
+
# pulls images — does NOT clone app source
|
|
59
|
+
ragsuite-test stop --repo-root ~/ragsuite-test
|
|
53
60
|
```
|
|
54
61
|
|
|
55
|
-
|
|
62
|
+
Optional pin:
|
|
56
63
|
|
|
57
64
|
```bash
|
|
58
|
-
ragsuite-test
|
|
65
|
+
# in ~/ragsuite-test/.env
|
|
66
|
+
IMAGE_TAG=1.0.0
|
|
67
|
+
IMAGE_REGISTRY=ghcr.io/nitsan-ai
|
|
59
68
|
```
|
|
60
69
|
|
|
61
|
-
|
|
70
|
+
If images are private on GHCR, make packages public or `docker login ghcr.io`.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Prerequisites
|
|
75
|
+
|
|
76
|
+
| Need | Git install | Images install |
|
|
77
|
+
|------|-------------|----------------|
|
|
78
|
+
| Node 18+ | Yes | Yes |
|
|
79
|
+
| git | Yes | No |
|
|
80
|
+
| Docker | Optional | **Required** |
|
|
81
|
+
| Postgres/Redis on host | Only for `--mode native` | No (in compose) |
|
|
82
|
+
|
|
83
|
+
SMTP/LLM: no init prompts. Real SMTP only in local `.env` (gitignored).
|
|
62
84
|
|
|
63
85
|
## Ports
|
|
64
86
|
|
|
65
87
|
| Service | Port |
|
|
66
88
|
|---------|------|
|
|
67
89
|
| API | 9090 |
|
|
68
|
-
| Web (Docker) | 9091 |
|
|
90
|
+
| Web (Docker/images) | 9091 |
|
|
69
91
|
| Web (native Expo) | 9191 |
|
|
70
92
|
| Postgres | 5436 |
|
|
71
93
|
| Redis | 6382 |
|
|
72
94
|
|
|
73
|
-
|
|
74
|
-
ragsuite-test stop --repo-root ~/ragsuite-test
|
|
75
|
-
lsof -nP -iTCP:9090 -sTCP:LISTEN
|
|
76
|
-
docker ps
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## Commands
|
|
80
|
-
|
|
81
|
-
| Command | Behavior |
|
|
82
|
-
|---------|----------|
|
|
83
|
-
| `init` | git clone or checkout → `.env` + config |
|
|
84
|
-
| `start` / `stop` | `scripts/docker-*.sh` or `native-*.sh` |
|
|
85
|
-
| `doctor` | prereqs + `scripts/doctor.sh` |
|
|
86
|
-
| `logs` / `update` / `version` | As before |
|
|
87
|
-
|
|
88
|
-
## Publish
|
|
89
|
-
|
|
90
|
-
See [PUBLISH.md](./PUBLISH.md) and [TEST_DISTRIBUTION.md](./TEST_DISTRIBUTION.md).
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
cd cli && npm run prepublish:check
|
|
94
|
-
RAGSUITE_TEST_ALLOW_PUBLISH=1 npm publish --access public # only when approved
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Windows
|
|
95
|
+
## Publish CLI
|
|
98
96
|
|
|
99
|
-
|
|
97
|
+
See [PUBLISH.md](./PUBLISH.md). Version bump then Actions → **CLI publish**.
|
|
100
98
|
|
|
101
99
|
## Tests
|
|
102
100
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitsan-ai/ragsuite-test",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "RAGSuite testing CLI
|
|
5
|
+
"description": "RAGSuite testing CLI — init (git source) or init --from-images (pull-only, no source).",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"ragsuite-test": "./bin/ragsuite-test.js"
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"bin/",
|
|
12
12
|
"src/",
|
|
13
|
+
"templates/",
|
|
13
14
|
"package.json",
|
|
14
15
|
"README.md",
|
|
15
16
|
"LICENSE"
|
package/src/commands/doctor.js
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { resolveMode } = require('../utils/config');
|
|
5
|
-
const { resolveRepoRoot } = require('../utils/paths');
|
|
5
|
+
const { resolveRepoRoot, isImagesInstall } = require('../utils/paths');
|
|
6
6
|
const { runScript } = require('../utils/spawn');
|
|
7
7
|
|
|
8
8
|
const name = 'doctor';
|
|
9
|
-
const summary = 'Run
|
|
9
|
+
const summary = 'Run doctor checks (git or images install)';
|
|
10
10
|
|
|
11
11
|
function help() {
|
|
12
12
|
return `Usage: ragsuite-test doctor [options]
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
Git install: scripts/doctor.sh
|
|
15
|
+
Images install: scripts/docker-doctor-images.sh
|
|
16
16
|
|
|
17
17
|
Options:
|
|
18
|
-
--mode <docker|native>
|
|
19
|
-
--repo-root <path>
|
|
20
|
-
--dry-run
|
|
18
|
+
--mode <docker|native> Git install gate
|
|
19
|
+
--repo-root <path>
|
|
20
|
+
--dry-run
|
|
21
21
|
`;
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -26,12 +26,16 @@ function run(ctx) {
|
|
|
26
26
|
cwd: ctx.cwd,
|
|
27
27
|
repoRootFlag: ctx.globals.repoRoot,
|
|
28
28
|
});
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
const images = isImagesInstall(repoRoot);
|
|
30
|
+
const mode = images
|
|
31
|
+
? 'docker'
|
|
32
|
+
: resolveMode({
|
|
33
|
+
flagMode: ctx.globals.mode,
|
|
34
|
+
repoRoot,
|
|
35
|
+
env: ctx.env,
|
|
36
|
+
});
|
|
37
|
+
const script = images ? 'docker-doctor-images.sh' : 'doctor.sh';
|
|
38
|
+
return runScript(repoRoot, path.join('scripts', script), [], {
|
|
35
39
|
dryRun: ctx.globals.dryRun,
|
|
36
40
|
env: { ...ctx.env, RAGSUITE_MODE: mode },
|
|
37
41
|
});
|
package/src/commands/init.js
CHANGED
|
@@ -2,56 +2,55 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { writeConfig, CONFIG_DIR } = require('../utils/config');
|
|
5
|
-
const {
|
|
5
|
+
const {
|
|
6
|
+
ensureRagsuiteDir,
|
|
7
|
+
resolveRepoRoot,
|
|
8
|
+
isImagesInstall,
|
|
9
|
+
} = require('../utils/paths');
|
|
6
10
|
const { assertSupportedInstall, installHint } = require('../utils/distribution');
|
|
7
11
|
const {
|
|
8
12
|
DEFAULT_GIT_URL,
|
|
9
13
|
defaultInstallDir,
|
|
10
14
|
cloneGitToInstallDir,
|
|
11
15
|
} = require('../utils/git-install');
|
|
16
|
+
const { materializeImagesInstall } = require('../utils/images-install');
|
|
12
17
|
const { detectOs } = require('../utils/os-detect');
|
|
13
18
|
const {
|
|
14
19
|
printPrereqs,
|
|
15
20
|
resolvePreferredMode,
|
|
16
|
-
dockerDaemonRunning,
|
|
17
|
-
commandExists,
|
|
18
21
|
} = require('../utils/prereqs');
|
|
19
|
-
const { ask, choose } = require('../utils/prompt');
|
|
20
22
|
const {
|
|
21
23
|
generateJwtSecret,
|
|
22
24
|
isPlaceholderSecret,
|
|
23
25
|
writeInstallEnv,
|
|
24
26
|
} = require('../utils/env-file');
|
|
25
27
|
const { assertPortsFree } = require('../utils/port');
|
|
26
|
-
const { info,
|
|
28
|
+
const { info, error } = require('../utils/log');
|
|
27
29
|
|
|
28
30
|
const name = 'init';
|
|
29
|
-
const summary = '
|
|
31
|
+
const summary = 'Install: git clone (source) or pull-only Docker images';
|
|
30
32
|
|
|
31
|
-
function printSuccess(repoRoot, mode) {
|
|
33
|
+
function printSuccess(repoRoot, mode, source) {
|
|
32
34
|
info('');
|
|
33
35
|
info('=== Install complete ===');
|
|
34
36
|
info(` Install dir : ${repoRoot}`);
|
|
37
|
+
info(` Source : ${source}`);
|
|
35
38
|
info(` Mode : ${mode}`);
|
|
36
39
|
info(` Config : ${path.join(repoRoot, CONFIG_DIR, 'config.json')}`);
|
|
37
40
|
info('');
|
|
38
41
|
info(' API http://localhost:9090');
|
|
39
|
-
if (
|
|
42
|
+
if (source === 'images') {
|
|
43
|
+
info(' Web http://localhost:9091 (images / Docker nginx)');
|
|
44
|
+
} else if (mode === 'native') {
|
|
40
45
|
info(' Web http://localhost:9191 (Expo web — native mode)');
|
|
41
46
|
} else {
|
|
42
47
|
info(' Web http://localhost:9091 (Docker nginx)');
|
|
43
48
|
}
|
|
44
49
|
info('');
|
|
45
|
-
info(' Docker is optional: native mode needs host Postgres :5436 + Redis :6382.');
|
|
46
|
-
info(' Each install directory is one deployment / one organization.');
|
|
47
|
-
info('');
|
|
48
50
|
info('Next steps:');
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
} else {
|
|
53
|
-
info(' 2. Open http://localhost:9091 and bootstrap the first admin');
|
|
54
|
-
}
|
|
51
|
+
const detach = mode === 'docker' || source === 'images' ? ' --detach' : '';
|
|
52
|
+
info(` 1. ragsuite-test start --repo-root ${repoRoot}${detach}`);
|
|
53
|
+
info(' 2. Open the Web URL above and bootstrap the first admin');
|
|
55
54
|
info(` 3. ragsuite-test doctor --repo-root ${repoRoot}`);
|
|
56
55
|
info('');
|
|
57
56
|
info(installHint());
|
|
@@ -60,29 +59,27 @@ function printSuccess(repoRoot, mode) {
|
|
|
60
59
|
function help() {
|
|
61
60
|
return `Usage: ragsuite-test init [options]
|
|
62
61
|
|
|
63
|
-
|
|
64
|
-
- detects OS / prerequisites (Docker is optional)
|
|
65
|
-
- clones the public monorepo or configures an existing checkout
|
|
66
|
-
- writes .ragsuite-test/config.json and .env
|
|
67
|
-
- JWT is auto-generated; SMTP + LLM defaults come from .env.example
|
|
68
|
-
- checks ports 9090, 9091, 5436, 6382
|
|
69
|
-
|
|
70
|
-
Install sources (pick one):
|
|
71
|
-
--from-git [url] Clone public monorepo (default: ${DEFAULT_GIT_URL})
|
|
72
|
-
--repo-root <path> Use an existing monorepo checkout
|
|
62
|
+
Two install styles:
|
|
73
63
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
64
|
+
A) Source on disk (git) — default
|
|
65
|
+
ragsuite-test init
|
|
66
|
+
Clones ${DEFAULT_GIT_URL} → ~/ragsuite-test
|
|
67
|
+
Supports --mode docker|native
|
|
77
68
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
69
|
+
B) No source (Docker images only)
|
|
70
|
+
ragsuite-test init --from-images
|
|
71
|
+
Copies a tiny compose bundle → ~/ragsuite-test
|
|
72
|
+
Pulls ghcr.io/nitsan-ai/ragsuite-backend|frontend (no git clone of app code)
|
|
81
73
|
|
|
82
74
|
Options:
|
|
83
|
-
--
|
|
75
|
+
--from-images Pull-only images install (no monorepo source)
|
|
76
|
+
--from-git [url] Clone this URL (default public repo)
|
|
77
|
+
--repo-root <path> Configure an existing git checkout
|
|
78
|
+
--install-dir <path> Target dir (default: ~/ragsuite-test)
|
|
79
|
+
--mode <docker|native> Git install only (images install is always docker)
|
|
84
80
|
--force Overwrite non-empty install dir / existing .env
|
|
85
|
-
--yes, -y Non-interactive
|
|
81
|
+
--yes, -y Non-interactive
|
|
82
|
+
--llm-api-key / --smtp-* Optional overrides
|
|
86
83
|
`;
|
|
87
84
|
}
|
|
88
85
|
|
|
@@ -100,12 +97,13 @@ function resolveLlmOverride(g, env) {
|
|
|
100
97
|
if (env.RAGSUITE_TEST_LLM_API_KEY && !isPlaceholderSecret(env.RAGSUITE_TEST_LLM_API_KEY)) {
|
|
101
98
|
return env.RAGSUITE_TEST_LLM_API_KEY;
|
|
102
99
|
}
|
|
103
|
-
return null;
|
|
100
|
+
return null;
|
|
104
101
|
}
|
|
105
102
|
|
|
106
|
-
function countSources(fromGit, repoRootFlag) {
|
|
103
|
+
function countSources(fromGit, fromImages, repoRootFlag) {
|
|
107
104
|
let n = 0;
|
|
108
105
|
if (fromGit !== null && fromGit !== undefined) n += 1;
|
|
106
|
+
if (fromImages) n += 1;
|
|
109
107
|
if (repoRootFlag) n += 1;
|
|
110
108
|
return n;
|
|
111
109
|
}
|
|
@@ -113,15 +111,14 @@ function countSources(fromGit, repoRootFlag) {
|
|
|
113
111
|
async function run(ctx) {
|
|
114
112
|
assertSupportedInstall();
|
|
115
113
|
const g = ctx.globals;
|
|
116
|
-
const interactive = Boolean(process.stdin.isTTY) && !g.yes;
|
|
117
114
|
|
|
118
115
|
if (g.fromRelease) {
|
|
119
|
-
error('--from-release is not supported. Use --from-git or --repo-root.');
|
|
116
|
+
error('--from-release is not supported. Use init, --from-images, --from-git, or --repo-root.');
|
|
120
117
|
return 1;
|
|
121
118
|
}
|
|
122
119
|
|
|
123
|
-
if (countSources(g.fromGit, g.repoRoot) > 1) {
|
|
124
|
-
error('Use only one of --from-git or --repo-root');
|
|
120
|
+
if (countSources(g.fromGit, g.fromImages, g.repoRoot) > 1) {
|
|
121
|
+
error('Use only one of --from-images, --from-git, or --repo-root');
|
|
125
122
|
return 1;
|
|
126
123
|
}
|
|
127
124
|
|
|
@@ -129,81 +126,30 @@ async function run(ctx) {
|
|
|
129
126
|
info(`OS: ${osInfo.label} (${osInfo.platform})`);
|
|
130
127
|
|
|
131
128
|
let fromGit = g.fromGit;
|
|
129
|
+
let fromImages = Boolean(g.fromImages);
|
|
132
130
|
let repoRootFlag = g.repoRoot;
|
|
133
|
-
|
|
134
|
-
let mode = g.mode || null;
|
|
131
|
+
const installDir = g.installDir || defaultInstallDir();
|
|
135
132
|
|
|
136
|
-
if (
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
} else if (interactive && fromGit === null && !repoRootFlag) {
|
|
142
|
-
const method = await choose(
|
|
143
|
-
'Install method:',
|
|
144
|
-
[
|
|
145
|
-
{
|
|
146
|
-
id: 'git',
|
|
147
|
-
label: 'Public git clone (--from-git) — recommended',
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
id: 'checkout',
|
|
151
|
-
label: 'Existing checkout (--repo-root)',
|
|
152
|
-
},
|
|
153
|
-
],
|
|
154
|
-
{ defaultIndex: 0 },
|
|
155
|
-
);
|
|
156
|
-
if (method.id === 'git') {
|
|
157
|
-
const url = await ask('Git repository URL', {
|
|
158
|
-
defaultValue: DEFAULT_GIT_URL,
|
|
159
|
-
yesMode: false,
|
|
160
|
-
});
|
|
161
|
-
fromGit = url || DEFAULT_GIT_URL;
|
|
162
|
-
installDir = await ask('Install directory', {
|
|
163
|
-
defaultValue: defaultInstallDir(),
|
|
164
|
-
yesMode: false,
|
|
165
|
-
});
|
|
166
|
-
} else {
|
|
167
|
-
repoRootFlag = await ask('Path to existing RAGSUITE checkout', { yesMode: false });
|
|
168
|
-
if (!repoRootFlag || !looksLikeRepoRoot(path.resolve(repoRootFlag))) {
|
|
169
|
-
error('Not a valid checkout (need scripts/docker-start.sh)');
|
|
170
|
-
return 1;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
133
|
+
if (!fromImages && fromGit === null && !repoRootFlag) {
|
|
134
|
+
fromGit = '';
|
|
135
|
+
info(`Install style: git clone (source on disk)`);
|
|
136
|
+
info(` ${DEFAULT_GIT_URL} → ${path.resolve(installDir)}`);
|
|
137
|
+
}
|
|
173
138
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
[
|
|
178
|
-
{
|
|
179
|
-
id: 'native',
|
|
180
|
-
label: 'Native — no Docker; needs Postgres :5436 + Redis :6382 on this machine',
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
id: 'docker',
|
|
184
|
-
label: dockerOk
|
|
185
|
-
? 'Docker — full compose stack (Docker Desktop / daemon)'
|
|
186
|
-
: 'Docker — not available on this machine (install Docker Desktop first)',
|
|
187
|
-
},
|
|
188
|
-
],
|
|
189
|
-
{ defaultIndex: 0 },
|
|
190
|
-
);
|
|
191
|
-
mode = modeChoice.id;
|
|
192
|
-
if (mode === 'docker' && !dockerOk) {
|
|
193
|
-
warn('Docker is not available — switching to native mode.');
|
|
194
|
-
mode = 'native';
|
|
195
|
-
}
|
|
196
|
-
} else if (fromGit === null && !repoRootFlag) {
|
|
197
|
-
error('Pass --from-git / --repo-root, or run in a TTY for the interactive wizard');
|
|
198
|
-
return 1;
|
|
139
|
+
if (fromImages) {
|
|
140
|
+
info('Install style: Docker images only (no app source on disk)');
|
|
141
|
+
info(` Target: ${path.resolve(installDir)}`);
|
|
199
142
|
}
|
|
200
143
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
144
|
+
let mode;
|
|
145
|
+
if (fromImages) {
|
|
146
|
+
mode = 'docker';
|
|
147
|
+
} else {
|
|
148
|
+
mode = g.mode || resolvePreferredMode(null);
|
|
204
149
|
}
|
|
150
|
+
info(`Run mode: ${mode}`);
|
|
205
151
|
|
|
206
|
-
const needGit = fromGit !== null && fromGit !== undefined;
|
|
152
|
+
const needGit = !fromImages && fromGit !== null && fromGit !== undefined;
|
|
207
153
|
if (!printPrereqs(mode, { needGit })) {
|
|
208
154
|
error('Fix prerequisites above and re-run init');
|
|
209
155
|
return 1;
|
|
@@ -211,7 +157,7 @@ async function run(ctx) {
|
|
|
211
157
|
|
|
212
158
|
const jwtSecret = generateJwtSecret();
|
|
213
159
|
info(`JWT_SECRET_KEY will be auto-generated (…${jwtSecret.slice(-8)})`);
|
|
214
|
-
info('SMTP + LLM:
|
|
160
|
+
info('SMTP + LLM: from .env.example into .env (no prompts).');
|
|
215
161
|
|
|
216
162
|
const llmKey = resolveLlmOverride(g, ctx.env);
|
|
217
163
|
const smtp = optionalSmtpOverrides(g, ctx.env);
|
|
@@ -229,7 +175,15 @@ async function run(ctx) {
|
|
|
229
175
|
let source = 'checkout';
|
|
230
176
|
|
|
231
177
|
try {
|
|
232
|
-
if (
|
|
178
|
+
if (fromImages) {
|
|
179
|
+
const result = materializeImagesInstall({
|
|
180
|
+
installDir,
|
|
181
|
+
force: g.force,
|
|
182
|
+
});
|
|
183
|
+
repoRoot = result.repoRoot;
|
|
184
|
+
source = 'images';
|
|
185
|
+
info(`Images bundle installed at ${repoRoot}`);
|
|
186
|
+
} else if (fromGit !== null && fromGit !== undefined) {
|
|
233
187
|
const url = fromGit === '' ? DEFAULT_GIT_URL : fromGit;
|
|
234
188
|
info(`Cloning ${url} → ${path.resolve(installDir)}`);
|
|
235
189
|
const result = cloneGitToInstallDir(url, {
|
|
@@ -245,6 +199,7 @@ async function run(ctx) {
|
|
|
245
199
|
repoRootFlag,
|
|
246
200
|
env: ctx.env,
|
|
247
201
|
});
|
|
202
|
+
if (isImagesInstall(repoRoot)) source = 'images';
|
|
248
203
|
}
|
|
249
204
|
} catch (err) {
|
|
250
205
|
error(err.message || String(err));
|
|
@@ -277,7 +232,7 @@ async function run(ctx) {
|
|
|
277
232
|
|
|
278
233
|
info(`Wrote ${path.join(repoRoot, CONFIG_DIR, 'config.json')}`);
|
|
279
234
|
info(` mode=${cfg.mode} source=${cfg.source}`);
|
|
280
|
-
printSuccess(repoRoot, mode);
|
|
235
|
+
printSuccess(repoRoot, mode, source);
|
|
281
236
|
return 0;
|
|
282
237
|
}
|
|
283
238
|
|
package/src/commands/start.js
CHANGED
|
@@ -2,25 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { resolveMode } = require('../utils/config');
|
|
5
|
-
const { resolveRepoRoot } = require('../utils/paths');
|
|
5
|
+
const { resolveRepoRoot, isImagesInstall } = 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 stack
|
|
11
|
+
const summary = 'Start stack (git scripts or images pull-only)';
|
|
12
12
|
|
|
13
13
|
function help() {
|
|
14
|
-
return `Usage: ragsuite-test start [options]
|
|
14
|
+
return `Usage: ragsuite-test start [options]
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
Git install: scripts/docker-start.sh or native-start.sh
|
|
17
|
+
Images install (--from-images): scripts/docker-start-images.sh (pull, no build)
|
|
18
18
|
|
|
19
19
|
Options:
|
|
20
|
-
--mode <docker|native> Override
|
|
21
|
-
--repo-root <path>
|
|
22
|
-
--dry-run Print
|
|
23
|
-
--detach, -d
|
|
20
|
+
--mode <docker|native> Override (git install; images always docker)
|
|
21
|
+
--repo-root <path> Install root
|
|
22
|
+
--dry-run Print script path and exit 0
|
|
23
|
+
--detach, -d Detached start
|
|
24
24
|
`;
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -29,14 +29,22 @@ async function run(ctx) {
|
|
|
29
29
|
cwd: ctx.cwd,
|
|
30
30
|
repoRootFlag: ctx.globals.repoRoot,
|
|
31
31
|
});
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
const images = isImagesInstall(repoRoot);
|
|
33
|
+
const mode = images
|
|
34
|
+
? 'docker'
|
|
35
|
+
: resolveMode({
|
|
36
|
+
flagMode: ctx.globals.mode,
|
|
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';
|
|
46
|
+
}
|
|
37
47
|
|
|
38
|
-
const scriptName = mode === 'native' ? 'native-start.sh' : 'docker-start.sh';
|
|
39
|
-
const rel = path.join('scripts', scriptName);
|
|
40
48
|
const forward = normalizeStartArgs(ctx.commandArgs);
|
|
41
49
|
|
|
42
50
|
if (!ctx.globals.dryRun) {
|
|
@@ -48,7 +56,7 @@ async function run(ctx) {
|
|
|
48
56
|
}
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
return runScript(repoRoot,
|
|
59
|
+
return runScript(repoRoot, path.join('scripts', scriptName), forward, {
|
|
52
60
|
dryRun: ctx.globals.dryRun,
|
|
53
61
|
env: { ...ctx.env, RAGSUITE_MODE: mode },
|
|
54
62
|
});
|
package/src/commands/stop.js
CHANGED
|
@@ -2,22 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { resolveMode } = require('../utils/config');
|
|
5
|
-
const { resolveRepoRoot } = require('../utils/paths');
|
|
5
|
+
const { resolveRepoRoot, isImagesInstall } = require('../utils/paths');
|
|
6
6
|
const { runScript } = require('../utils/spawn');
|
|
7
7
|
|
|
8
8
|
const name = 'stop';
|
|
9
|
-
const summary = 'Stop stack
|
|
9
|
+
const summary = 'Stop stack (git scripts or images pull-only)';
|
|
10
10
|
|
|
11
11
|
function help() {
|
|
12
12
|
return `Usage: ragsuite-test stop [options]
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
Git install: docker-stop.sh / native-stop.sh
|
|
15
|
+
Images install: docker-stop-images.sh
|
|
16
|
+
Never wipes Docker volumes.
|
|
16
17
|
|
|
17
18
|
Options:
|
|
18
|
-
--mode <docker|native> Override
|
|
19
|
-
--repo-root <path>
|
|
20
|
-
--dry-run Print
|
|
19
|
+
--mode <docker|native> Override (git install)
|
|
20
|
+
--repo-root <path> Install root
|
|
21
|
+
--dry-run Print script path and exit 0
|
|
21
22
|
`;
|
|
22
23
|
}
|
|
23
24
|
|
|
@@ -26,12 +27,21 @@ function run(ctx) {
|
|
|
26
27
|
cwd: ctx.cwd,
|
|
27
28
|
repoRootFlag: ctx.globals.repoRoot,
|
|
28
29
|
});
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
const images = isImagesInstall(repoRoot);
|
|
31
|
+
const mode = images
|
|
32
|
+
? 'docker'
|
|
33
|
+
: resolveMode({
|
|
34
|
+
flagMode: ctx.globals.mode,
|
|
35
|
+
repoRoot,
|
|
36
|
+
env: ctx.env,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const scriptName = images
|
|
40
|
+
? 'docker-stop-images.sh'
|
|
41
|
+
: mode === 'native'
|
|
42
|
+
? 'native-stop.sh'
|
|
43
|
+
: 'docker-stop.sh';
|
|
44
|
+
|
|
35
45
|
return runScript(repoRoot, path.join('scripts', scriptName), [], {
|
|
36
46
|
dryRun: ctx.globals.dryRun,
|
|
37
47
|
env: { ...ctx.env, RAGSUITE_MODE: mode },
|