@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 CHANGED
@@ -1,103 +1,78 @@
1
1
  # RAGSuite test CLI (`ragsuite-test`)
2
2
 
3
- > **TESTING PACKAGE** temporary name before the final `ragsuite` CLI.
4
-
5
- Two ways to run. Pick one:
6
-
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 |
16
-
17
- ---
18
-
19
- ## A) Git source (clone)
3
+ npm-style deploy: **init once**, then **start / update / stop** via host **npm scripts** — **no Docker**.
20
4
 
21
5
  ```bash
22
6
  npm install -g @nitsan-ai/ragsuite-test
7
+
8
+ # First time only
23
9
  ragsuite-test init
24
- # clones https://github.com/nitsan-ai/RAGSUITE.git → ~/ragsuite-test
25
- # auto: docker if daemon up, else native
10
+ # clones → ~/ragsuite-test
26
11
 
27
- ragsuite-test start --repo-root ~/ragsuite-test --detach # docker
28
- # or after init --mode native:
29
- # ragsuite-test start --repo-root ~/ragsuite-test
12
+ # Needs Postgres :5436 (db ragsuite_v3) and Redis :6382 on the host
13
+ ragsuite-test start
14
+ # API http://localhost:9090 · Web http://localhost:9191
30
15
 
31
- # API http://localhost:9090
32
- # Web http://localhost:9091 (docker) or :9191 (native)
33
- ragsuite-test stop --repo-root ~/ragsuite-test
16
+ ragsuite-test stop
34
17
  ```
35
18
 
36
- ### Native (no Docker) — git install only
37
-
38
- Needs Postgres `:5436` (`ragsuite_v3`) and Redis `:6382`:
19
+ Same under the hood as:
39
20
 
40
21
  ```bash
41
- ragsuite-test init --mode native
42
- ragsuite-test start --repo-root ~/ragsuite-test
22
+ cd ~/ragsuite-test
23
+ npm start # scripts/native-start.sh
24
+ npm run stop # scripts/native-stop.sh
43
25
  ```
44
26
 
45
- ---
27
+ Active install is remembered in `~/.ragsuite-test/config.json`.
46
28
 
47
- ## B) Docker images (no source on disk)
48
-
49
- **Maintainer (once):** publish images — Actions → **Publish images (GHCR)**
50
- (packages: `ghcr.io/nitsan-ai/ragsuite-backend`, `…/ragsuite-frontend`)
29
+ ---
51
30
 
52
- **User:**
31
+ ## Upgrade (keeps data & `.env`)
53
32
 
54
33
  ```bash
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
34
+ npm install -g @nitsan-ai/ragsuite-test@latest
35
+ ragsuite-test update # git pull only
36
+ ragsuite-test start
60
37
  ```
61
38
 
62
- Optional pin:
39
+ **Never** run `docker compose down -v` or `init --force` unless you mean to wipe data.
63
40
 
64
- ```bash
65
- # in ~/ragsuite-test/.env
66
- IMAGE_TAG=1.0.0
67
- IMAGE_REGISTRY=ghcr.io/nitsan-ai
68
- ```
69
-
70
- If images are private on GHCR, make packages public or `docker login ghcr.io`.
41
+ If you already installed and run `init` again → **Already installed** (exit OK).
71
42
 
72
43
  ---
73
44
 
74
- ## Prerequisites
45
+ ## Prerequisites (host)
75
46
 
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) |
47
+ | Tool | Notes |
48
+ |------|--------|
49
+ | Node.js 18+ | |
50
+ | Python 3 + venv | backend |
51
+ | Yarn | Expo frontend |
52
+ | Git | `init` clone |
53
+ | Postgres | `localhost:5436`, database `ragsuite_v3` |
54
+ | Redis | `localhost:6382` |
82
55
 
83
- SMTP/LLM: no init prompts. Real SMTP only in local `.env` (gitignored).
56
+ Docker is **not** required for this CLI.
84
57
 
85
- ## Ports
58
+ ---
86
59
 
87
- | Service | Port |
88
- |---------|------|
89
- | API | 9090 |
90
- | Web (Docker/images) | 9091 |
91
- | Web (native Expo) | 9191 |
92
- | Postgres | 5436 |
93
- | Redis | 6382 |
60
+ ## Commands
94
61
 
95
- ## Publish CLI
62
+ | Command | Purpose |
63
+ |---------|---------|
64
+ | `init` | First-time git install |
65
+ | `start` | `scripts/native-start.sh` |
66
+ | `stop` | `scripts/native-stop.sh` (host PIDs only) |
67
+ | `update` | `git pull` in place |
68
+ | `doctor` | Native prereq checks |
69
+ | `logs` | Tail `.ragsuite/native/*.log` |
70
+ | `version` | CLI version |
96
71
 
97
- See [PUBLISH.md](./PUBLISH.md). Version bump then Actions → **CLI publish**.
72
+ ## Ports
98
73
 
99
- ## Tests
74
+ API **9090** · Web **9191** · Postgres **5436** · Redis **6382** · Chroma **8004** (started by native-start if needed)
100
75
 
101
- ```bash
102
- cd cli && npm test && npm run prepublish:check
103
- ```
76
+ ## Publish (maintainers)
77
+
78
+ See [PUBLISH.md](./PUBLISH.md).
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@nitsan-ai/ragsuite-test",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "private": false,
5
- "description": "RAGSuite testing CLI — init (git source) or init --from-images (pull-only, no source).",
5
+ "description": "RAGSuite testing CLI — init once, then start/update/stop via native npm scripts (no Docker).",
6
6
  "main": "src/index.js",
7
7
  "bin": {
8
8
  "ragsuite-test": "./bin/ragsuite-test.js"
@@ -10,7 +10,6 @@
10
10
  "files": [
11
11
  "bin/",
12
12
  "src/",
13
- "templates/",
14
13
  "package.json",
15
14
  "README.md",
16
15
  "LICENSE"
@@ -2,20 +2,22 @@
2
2
 
3
3
  const path = require('path');
4
4
  const { resolveMode } = require('../utils/config');
5
- const { resolveRepoRoot, isImagesInstall } = require('../utils/paths');
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 = 'doctor';
9
- const summary = 'Run doctor checks (git or images install)';
10
+ const summary = 'Check native deploy prerequisites';
10
11
 
11
12
  function help() {
12
13
  return `Usage: ragsuite-test doctor [options]
13
14
 
14
- Git install: scripts/doctor.sh
15
- Images install: scripts/docker-doctor-images.sh
15
+ Runs scripts/doctor.sh with RAGSUITE_MODE=native.
16
+
17
+ Postgres (:5436) and Redis (:6382) must be reachable for a real install.
18
+ In CI smoke, runtime TCP checks are skipped unless RAGSUITE_DOCTOR_STRICT=1.
16
19
 
17
20
  Options:
18
- --mode <docker|native> Git install gate
19
21
  --repo-root <path>
20
22
  --dry-run
21
23
  `;
@@ -26,18 +28,16 @@ function run(ctx) {
26
28
  cwd: ctx.cwd,
27
29
  repoRootFlag: ctx.globals.repoRoot,
28
30
  });
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), [], {
31
+ try {
32
+ assertNativeDeploy(repoRoot);
33
+ } catch (err) {
34
+ error(err.message);
35
+ return 1;
36
+ }
37
+
38
+ return runScript(repoRoot, path.join('scripts', 'doctor.sh'), [], {
39
39
  dryRun: ctx.globals.dryRun,
40
- env: { ...ctx.env, RAGSUITE_MODE: mode },
40
+ env: { ...ctx.env, RAGSUITE_MODE: resolveMode() },
41
41
  });
42
42
  }
43
43
 
@@ -1,85 +1,97 @@
1
1
  'use strict';
2
2
 
3
3
  const path = require('path');
4
- const { writeConfig, CONFIG_DIR } = require('../utils/config');
4
+ const { writeConfig, CONFIG_DIR, readConfig } = require('../utils/config');
5
5
  const {
6
6
  ensureRagsuiteDir,
7
7
  resolveRepoRoot,
8
- isImagesInstall,
8
+ looksLikeRepoRoot,
9
+ isDirEmptyOrMissing,
9
10
  } = require('../utils/paths');
11
+ const { setActiveInstall } = require('../utils/global-config');
10
12
  const { assertSupportedInstall, installHint } = require('../utils/distribution');
11
13
  const {
12
14
  DEFAULT_GIT_URL,
13
15
  defaultInstallDir,
14
16
  cloneGitToInstallDir,
15
17
  } = require('../utils/git-install');
16
- const { materializeImagesInstall } = require('../utils/images-install');
17
18
  const { detectOs } = require('../utils/os-detect');
18
- const {
19
- printPrereqs,
20
- resolvePreferredMode,
21
- } = require('../utils/prereqs');
19
+ const { printPrereqs, resolvePreferredMode } = require('../utils/prereqs');
22
20
  const {
23
21
  generateJwtSecret,
24
22
  isPlaceholderSecret,
25
23
  writeInstallEnv,
26
24
  } = require('../utils/env-file');
27
25
  const { assertPortsFree } = require('../utils/port');
28
- const { info, error } = require('../utils/log');
26
+ const { info, warn, error } = require('../utils/log');
29
27
 
30
28
  const name = 'init';
31
- const summary = 'Install: git clone (source) or pull-only Docker images';
29
+ const summary = 'First-time install (git + native npm scripts). Safe if already installed.';
32
30
 
33
- function printSuccess(repoRoot, mode, source) {
31
+ function printSuccess(repoRoot) {
34
32
  info('');
35
33
  info('=== Install complete ===');
36
34
  info(` Install dir : ${repoRoot}`);
37
- info(` Source : ${source}`);
38
- info(` Mode : ${mode}`);
39
- info(` Config : ${path.join(repoRoot, CONFIG_DIR, 'config.json')}`);
35
+ info(' Mode : native (npm scripts — no Docker)');
40
36
  info('');
41
37
  info(' API http://localhost:9090');
42
- if (source === 'images') {
43
- info(' Web http://localhost:9091 (images / Docker nginx)');
44
- } else if (mode === 'native') {
45
- info(' Web http://localhost:9191 (Expo web — native mode)');
46
- } else {
47
- info(' Web http://localhost:9091 (Docker nginx)');
48
- }
38
+ info(' Web http://localhost:9191');
49
39
  info('');
50
- info('Next steps:');
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');
54
- info(` 3. ragsuite-test doctor --repo-root ${repoRoot}`);
40
+ info('Next (no --repo-root needed):');
41
+ info(' ragsuite-test start');
42
+ info(' ragsuite-test stop');
43
+ info(' ragsuite-test update # later upgrades, keeps data');
44
+ info('');
45
+ info('Or in the install directory:');
46
+ info(' npm start');
47
+ info(' npm run stop');
55
48
  info('');
56
49
  info(installHint());
57
50
  }
58
51
 
52
+ function printAlreadyInstalled(repoRoot) {
53
+ const cfg = readConfig(repoRoot);
54
+ setActiveInstall(repoRoot);
55
+ info('');
56
+ info('=== Already installed ===');
57
+ info(` ${repoRoot}`);
58
+ if (cfg) info(` source=${cfg.source} mode=native`);
59
+ info('');
60
+ info('Use:');
61
+ info(' ragsuite-test start # run the app (npm scripts)');
62
+ info(' ragsuite-test update # upgrade code (keeps .env + data)');
63
+ info(' ragsuite-test stop');
64
+ info('');
65
+ info('Do NOT run init --force unless you intend to wipe and reinstall.');
66
+ }
67
+
68
+ function isInitializedInstall(dir) {
69
+ return looksLikeRepoRoot(dir) && Boolean(readConfig(dir));
70
+ }
71
+
59
72
  function help() {
60
73
  return `Usage: ragsuite-test init [options]
61
74
 
62
- Two install styles:
75
+ First-time setup (npm-style, no Docker):
76
+
77
+ ragsuite-test init # git clone → ~/ragsuite-test
78
+ ragsuite-test start # scripts/native-start.sh
79
+
80
+ If already installed, init exits OK and tells you to start/update.
63
81
 
64
- A) Source on disk (git) default
65
- ragsuite-test init
66
- Clones ${DEFAULT_GIT_URL} → ~/ragsuite-test
67
- Supports --mode docker|native
82
+ Requires host Postgres (:5436) and Redis (:6382).
68
83
 
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)
84
+ Day-to-day:
85
+ ragsuite-test start
86
+ ragsuite-test update
87
+ ragsuite-test stop
73
88
 
74
89
  Options:
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)
80
- --force Overwrite non-empty install dir / existing .env
90
+ --from-git [url] Clone URL (default public repo)
91
+ --repo-root <path> Point at an existing checkout
92
+ --install-dir <path> Default: ~/ragsuite-test
93
+ --force Wipe install dir and reinstall (destructive)
81
94
  --yes, -y Non-interactive
82
- --llm-api-key / --smtp-* Optional overrides
83
95
  `;
84
96
  }
85
97
 
@@ -100,10 +112,9 @@ function resolveLlmOverride(g, env) {
100
112
  return null;
101
113
  }
102
114
 
103
- function countSources(fromGit, fromImages, repoRootFlag) {
115
+ function countSources(fromGit, repoRootFlag) {
104
116
  let n = 0;
105
117
  if (fromGit !== null && fromGit !== undefined) n += 1;
106
- if (fromImages) n += 1;
107
118
  if (repoRootFlag) n += 1;
108
119
  return n;
109
120
  }
@@ -113,12 +124,34 @@ async function run(ctx) {
113
124
  const g = ctx.globals;
114
125
 
115
126
  if (g.fromRelease) {
116
- error('--from-release is not supported. Use init, --from-images, --from-git, or --repo-root.');
127
+ error('--from-release is not supported.');
117
128
  return 1;
118
129
  }
119
130
 
120
- if (countSources(g.fromGit, g.fromImages, g.repoRoot) > 1) {
121
- error('Use only one of --from-images, --from-git, or --repo-root');
131
+ if (g.fromImages) {
132
+ error(
133
+ [
134
+ '--from-images was removed (Docker deployment retired).',
135
+ ' Use: ragsuite-test init',
136
+ ' Then: ragsuite-test start',
137
+ ].join('\n'),
138
+ );
139
+ return 1;
140
+ }
141
+
142
+ if (g.mode === 'docker') {
143
+ error(
144
+ [
145
+ 'Docker mode was removed from deployment.',
146
+ ' Init always uses native npm scripts (no containers).',
147
+ ' Omit --mode, or use --mode native.',
148
+ ].join('\n'),
149
+ );
150
+ return 1;
151
+ }
152
+
153
+ if (countSources(g.fromGit, g.repoRoot) > 1) {
154
+ error('Use only one of --from-git or --repo-root');
122
155
  return 1;
123
156
  }
124
157
 
@@ -126,30 +159,53 @@ async function run(ctx) {
126
159
  info(`OS: ${osInfo.label} (${osInfo.platform})`);
127
160
 
128
161
  let fromGit = g.fromGit;
129
- let fromImages = Boolean(g.fromImages);
130
162
  let repoRootFlag = g.repoRoot;
131
- const installDir = g.installDir || defaultInstallDir();
163
+ const installDir = path.resolve(g.installDir || defaultInstallDir());
164
+
165
+ if (!g.force) {
166
+ if (repoRootFlag && isInitializedInstall(path.resolve(repoRootFlag))) {
167
+ printAlreadyInstalled(path.resolve(repoRootFlag));
168
+ return 0;
169
+ }
170
+ if (!repoRootFlag && isInitializedInstall(installDir)) {
171
+ printAlreadyInstalled(installDir);
172
+ return 0;
173
+ }
174
+ }
132
175
 
133
- if (!fromImages && fromGit === null && !repoRootFlag) {
176
+ if (fromGit === null && !repoRootFlag) {
134
177
  fromGit = '';
135
- info(`Install style: git clone (source on disk)`);
136
- info(` ${DEFAULT_GIT_URL} → ${path.resolve(installDir)}`);
178
+ info(`First-time install (git): ${DEFAULT_GIT_URL}`);
179
+ info(` → ${installDir}`);
137
180
  }
138
181
 
139
- if (fromImages) {
140
- info('Install style: Docker images only (no app source on disk)');
141
- info(` Target: ${path.resolve(installDir)}`);
182
+ if (
183
+ !g.force &&
184
+ !repoRootFlag &&
185
+ looksLikeRepoRoot(installDir) &&
186
+ !readConfig(installDir)
187
+ ) {
188
+ info(`Found existing source at ${installDir} — finishing setup (no re-clone).`);
189
+ repoRootFlag = installDir;
190
+ fromGit = null;
142
191
  }
143
192
 
144
- let mode;
145
- if (fromImages) {
146
- mode = 'docker';
147
- } else {
148
- mode = g.mode || resolvePreferredMode(null);
193
+ if (!g.force && !isDirEmptyOrMissing(installDir) && !looksLikeRepoRoot(installDir) && !repoRootFlag) {
194
+ error(
195
+ [
196
+ `Directory exists but is not a RAGSuite install: ${installDir}`,
197
+ ' Fix leftover files, or:',
198
+ ' ragsuite-test init --force # wipe & reinstall (destructive)',
199
+ ' ragsuite-test init --install-dir ~/ragsuite-test-2',
200
+ ].join('\n'),
201
+ );
202
+ return 1;
149
203
  }
150
- info(`Run mode: ${mode}`);
151
204
 
152
- const needGit = !fromImages && fromGit !== null && fromGit !== undefined;
205
+ const mode = resolvePreferredMode();
206
+ info(`Run mode: ${mode} (npm scripts — Docker not used)`);
207
+
208
+ const needGit = fromGit !== null && fromGit !== undefined;
153
209
  if (!printPrereqs(mode, { needGit })) {
154
210
  error('Fix prerequisites above and re-run init');
155
211
  return 1;
@@ -157,7 +213,6 @@ async function run(ctx) {
157
213
 
158
214
  const jwtSecret = generateJwtSecret();
159
215
  info(`JWT_SECRET_KEY will be auto-generated (…${jwtSecret.slice(-8)})`);
160
- info('SMTP + LLM: from .env.example into .env (no prompts).');
161
216
 
162
217
  const llmKey = resolveLlmOverride(g, ctx.env);
163
218
  const smtp = optionalSmtpOverrides(g, ctx.env);
@@ -175,31 +230,17 @@ async function run(ctx) {
175
230
  let source = 'checkout';
176
231
 
177
232
  try {
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
+ if (fromGit !== null && fromGit !== undefined) {
187
234
  const url = fromGit === '' ? DEFAULT_GIT_URL : fromGit;
188
- info(`Cloning ${url} ${path.resolve(installDir)}`);
189
- const result = cloneGitToInstallDir(url, {
190
- installDir,
191
- force: g.force,
192
- });
235
+ const result = cloneGitToInstallDir(url, { installDir, force: g.force });
193
236
  repoRoot = result.repoRoot;
194
237
  source = 'git';
195
- info(`Installed app at ${repoRoot}`);
196
238
  } else {
197
239
  repoRoot = resolveRepoRoot({
198
240
  cwd: ctx.cwd,
199
241
  repoRootFlag,
200
242
  env: ctx.env,
201
243
  });
202
- if (isImagesInstall(repoRoot)) source = 'images';
203
244
  }
204
245
  } catch (err) {
205
246
  error(err.message || String(err));
@@ -208,11 +249,12 @@ async function run(ctx) {
208
249
 
209
250
  ensureRagsuiteDir(repoRoot);
210
251
  const cfg = writeConfig(repoRoot, {
211
- mode,
252
+ mode: 'native',
212
253
  source,
213
254
  repoRoot,
214
255
  installDir: repoRoot,
215
256
  });
257
+ setActiveInstall(repoRoot);
216
258
 
217
259
  try {
218
260
  writeInstallEnv(repoRoot, {
@@ -222,17 +264,19 @@ async function run(ctx) {
222
264
  smtp,
223
265
  });
224
266
  } catch (err) {
225
- if (err.code === 'ENV_EXISTS' || err.code === 'ENV_INCOMPLETE') {
267
+ if (err.code === 'ENV_EXISTS') {
268
+ warn('.env already present — keeping it (use --force only if you want to regenerate).');
269
+ } else if (err.code === 'ENV_INCOMPLETE') {
226
270
  error(err.message);
227
271
  return 1;
272
+ } else {
273
+ error(err.message || String(err));
274
+ return 1;
228
275
  }
229
- error(err.message || String(err));
230
- return 1;
231
276
  }
232
277
 
233
- info(`Wrote ${path.join(repoRoot, CONFIG_DIR, 'config.json')}`);
234
- info(` mode=${cfg.mode} source=${cfg.source}`);
235
- printSuccess(repoRoot, mode, source);
278
+ info(`Config: mode=${cfg.mode} source=${cfg.source}`);
279
+ printSuccess(repoRoot);
236
280
  return 0;
237
281
  }
238
282
 
@@ -2,23 +2,20 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const { resolveMode } = require('../utils/config');
6
- const { resolveRepoRoot, nativeLogDir } = require('../utils/paths');
5
+ const { resolveRepoRoot, nativeLogDir, assertNativeDeploy } = require('../utils/paths');
7
6
  const { runCommand } = require('../utils/spawn');
8
7
  const { error, info } = require('../utils/log');
9
8
 
10
9
  const name = 'logs';
11
- const summary = 'Follow Docker compose or native process logs';
10
+ const summary = 'Follow native process logs';
12
11
 
13
12
  function help() {
14
13
  return `Usage: ragsuite-test logs [options]
15
14
 
16
- Docker mode: docker compose logs -f (same as root npm run logs).
17
- Native mode: tail -f .ragsuite/native/*.log when present.
15
+ Tails .ragsuite/native/*.log (host processes no Docker).
18
16
 
19
17
  Options:
20
- --mode <docker|native> Override config / RAGSUITE_MODE
21
- --repo-root <path> Monorepo root
18
+ --repo-root <path> Install root
22
19
  --dry-run Print the command and exit 0
23
20
  `;
24
21
  }
@@ -28,36 +25,27 @@ function run(ctx) {
28
25
  cwd: ctx.cwd,
29
26
  repoRootFlag: ctx.globals.repoRoot,
30
27
  });
31
- const mode = resolveMode({
32
- flagMode: ctx.globals.mode,
33
- repoRoot,
34
- env: ctx.env,
35
- });
36
-
37
- if (mode === 'native') {
38
- const dir = nativeLogDir(repoRoot);
39
- let logs = [];
40
- if (fs.existsSync(dir)) {
41
- logs = fs
42
- .readdirSync(dir)
43
- .filter((f) => f.endsWith('.log'))
44
- .map((f) => path.join(dir, f));
45
- }
46
- if (logs.length === 0) {
47
- error(
48
- `No native log files under ${dir}. Start with mode=native first, or use --mode docker.`,
49
- );
50
- return 1;
51
- }
52
- info(`Following ${logs.length} native log file(s)…`);
53
- return runCommand('tail', ['-f', ...logs], {
54
- cwd: repoRoot,
55
- dryRun: ctx.globals.dryRun,
56
- env: ctx.env,
57
- });
28
+ try {
29
+ assertNativeDeploy(repoRoot);
30
+ } catch (err) {
31
+ error(err.message);
32
+ return 1;
58
33
  }
59
34
 
60
- return runCommand('docker', ['compose', 'logs', '-f'], {
35
+ const dir = nativeLogDir(repoRoot);
36
+ let logs = [];
37
+ if (fs.existsSync(dir)) {
38
+ logs = fs
39
+ .readdirSync(dir)
40
+ .filter((f) => f.endsWith('.log'))
41
+ .map((f) => path.join(dir, f));
42
+ }
43
+ if (logs.length === 0) {
44
+ error(`No native log files under ${dir}. Start with: ragsuite-test start`);
45
+ return 1;
46
+ }
47
+ info(`Following ${logs.length} native log file(s)…`);
48
+ return runCommand('tail', ['-f', ...logs], {
61
49
  cwd: repoRoot,
62
50
  dryRun: ctx.globals.dryRun,
63
51
  env: ctx.env,