@nitsan-ai/ragsuite-test 0.1.5 → 0.1.7

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,48 +1,42 @@
1
1
  # RAGSuite test CLI (`ragsuite-test`)
2
2
 
3
- npm-style deploy: **init once**, then **start / update / stop** via host **npm scripts** — **no Docker**.
3
+ End-user deploy: install the CLI **globally**, init once, then start/update/stop.
4
4
 
5
5
  ```bash
6
- npm install -g @nitsan-ai/ragsuite-test
7
-
8
- # First time only
9
- ragsuite-test init
10
- # clones → ~/ragsuite-test
11
-
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
6
+ # Always use -g (puts ragsuite-test on your PATH)
7
+ npm install -g @nitsan-ai/ragsuite-test@latest
15
8
 
9
+ ragsuite-test init # once → ~/ragsuite-test
10
+ ragsuite-test start # API :9090 · Web :9191
16
11
  ragsuite-test stop
17
12
  ```
18
13
 
19
- Same under the hood as:
14
+ ### Upgrade later (CLI + app, keeps data)
20
15
 
21
16
  ```bash
22
- cd ~/ragsuite-test
23
- npm start # scripts/native-start.sh
24
- npm run stop # scripts/native-stop.sh
17
+ ragsuite-test update
18
+ ragsuite-test start
25
19
  ```
26
20
 
27
- Active install is remembered in `~/.ragsuite-test/config.json`.
21
+ `update` runs `npm install -g @nitsan-ai/ragsuite-test@latest` then `git pull` in the install dir. It never runs `docker compose down -v`.
28
22
 
29
- ---
23
+ > If you run `npm i @nitsan-ai/ragsuite-test` **without** `-g`, the `ragsuite-test` command will be missing. Fix: `npm install -g @nitsan-ai/ragsuite-test@latest`.
30
24
 
31
- ## Upgrade (keeps data & `.env`)
25
+ Same as:
32
26
 
33
27
  ```bash
34
- npm install -g @nitsan-ai/ragsuite-test@latest
35
- ragsuite-test update # git pull only
36
- ragsuite-test start
28
+ cd ~/ragsuite-test
29
+ npm start # scripts/native-start.sh
30
+ npm run stop # scripts/native-stop.sh
37
31
  ```
38
32
 
39
- **Never** run `docker compose down -v` or `init --force` unless you mean to wipe data.
33
+ Active install: `~/.ragsuite-test/config.json`.
40
34
 
41
- If you already installed and run `init` again **Already installed** (exit OK).
35
+ **Data safety:** `start` may run `docker compose up -d postgres redis` only (existing volumes). App processes run on the host.
42
36
 
43
37
  ---
44
38
 
45
- ## Prerequisites (host)
39
+ ## Prerequisites
46
40
 
47
41
  | Tool | Notes |
48
42
  |------|--------|
@@ -50,10 +44,8 @@ If you already installed and run `init` again → **Already installed** (exit OK
50
44
  | Python 3 + venv | backend |
51
45
  | Yarn | Expo frontend |
52
46
  | Git | `init` clone |
53
- | Postgres | `localhost:5436`, database `ragsuite_v3` |
54
- | Redis | `localhost:6382` |
55
-
56
- Docker is **not** required for this CLI.
47
+ | Postgres + Redis | Host brew **or** data-only compose on :5436 / :6382 |
48
+ | Docker (optional) | Auto-start/reuse existing postgres/redis volumes |
57
49
 
58
50
  ---
59
51
 
@@ -62,16 +54,16 @@ Docker is **not** required for this CLI.
62
54
  | Command | Purpose |
63
55
  |---------|---------|
64
56
  | `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 |
57
+ | `start` | Native app (+ data services if needed) |
58
+ | `stop` | Native PIDs + leftover app containers (DB kept) |
59
+ | `update` | Upgrade CLI (`npm -g`) + app (`git pull`) |
68
60
  | `doctor` | Native prereq checks |
69
61
  | `logs` | Tail `.ragsuite/native/*.log` |
70
62
  | `version` | CLI version |
71
63
 
72
64
  ## Ports
73
65
 
74
- API **9090** · Web **9191** · Postgres **5436** · Redis **6382** · Chroma **8004** (started by native-start if needed)
66
+ API **9090** · Web **9191** · Postgres **5436** · Redis **6382** · Chroma **8004**
75
67
 
76
68
  ## Publish (maintainers)
77
69
 
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@nitsan-ai/ragsuite-test",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "private": false,
5
- "description": "RAGSuite testing CLI — init once, then start/update/stop via native npm scripts (no Docker).",
5
+ "description": "RAGSuite testing CLI — npm -g install, then init/start/update/stop (keeps data).",
6
6
  "main": "src/index.js",
7
7
  "bin": {
8
- "ragsuite-test": "./bin/ragsuite-test.js"
8
+ "ragsuite-test": "bin/ragsuite-test.js"
9
9
  },
10
10
  "files": [
11
11
  "bin/",
@@ -17,13 +17,12 @@ const {
17
17
  } = require('../utils/git-install');
18
18
  const { detectOs } = require('../utils/os-detect');
19
19
  const { printPrereqs, resolvePreferredMode } = require('../utils/prereqs');
20
+ const { info, warn, error } = require('../utils/log');
20
21
  const {
21
22
  generateJwtSecret,
22
23
  isPlaceholderSecret,
23
24
  writeInstallEnv,
24
25
  } = require('../utils/env-file');
25
- const { assertPortsFree } = require('../utils/port');
26
- const { info, warn, error } = require('../utils/log');
27
26
 
28
27
  const name = 'init';
29
28
  const summary = 'First-time install (git + native npm scripts). Safe if already installed.';
@@ -217,14 +216,8 @@ async function run(ctx) {
217
216
  const llmKey = resolveLlmOverride(g, ctx.env);
218
217
  const smtp = optionalSmtpOverrides(g, ctx.env);
219
218
 
220
- if (ctx.env.RAGSUITE_TEST_SKIP_PORT_CHECK !== '1') {
221
- try {
222
- await assertPortsFree();
223
- } catch (err) {
224
- error(err.message);
225
- return 1;
226
- }
227
- }
219
+ // Init only installs files — do not require ports free.
220
+ // (Postgres/Redis being "in use" is good; API busy is a start-time concern.)
228
221
 
229
222
  let repoRoot;
230
223
  let source = 'checkout';
@@ -5,16 +5,19 @@ const { resolveMode } = require('../utils/config');
5
5
  const { resolveRepoRoot, assertNativeDeploy } = require('../utils/paths');
6
6
  const { runScript } = require('../utils/spawn');
7
7
  const { assertApiPortFree } = require('../utils/port');
8
- const { error } = require('../utils/log');
8
+ const { error, info } = require('../utils/log');
9
9
 
10
10
  const name = 'start';
11
- const summary = 'Start app via npm scripts (native no Docker)';
11
+ const summary = 'Start app via npm scripts (native); auto-starts DB containers if needed';
12
12
 
13
13
  function help() {
14
14
  return `Usage: ragsuite-test start [options]
15
15
 
16
16
  Runs scripts/native-start.sh (same as \`npm start\` in the install dir).
17
- Does not use Docker — no containers, no volume risk.
17
+
18
+ App runs on the host. If Postgres/Redis are down, start may bring up
19
+ data-only compose services (postgres + redis) using existing volumes —
20
+ never \`down -v\`. Backend/frontend Docker containers are not started.
18
21
 
19
22
  Options:
20
23
  --repo-root <path> Override active install
@@ -42,6 +45,8 @@ async function run(ctx) {
42
45
  error(err.message);
43
46
  return 1;
44
47
  }
48
+ } else {
49
+ info('[dry-run] would run scripts/native-start.sh');
45
50
  }
46
51
 
47
52
  return runScript(repoRoot, path.join('scripts', 'native-start.sh'), [], {
@@ -7,13 +7,15 @@ const { runScript } = require('../utils/spawn');
7
7
  const { error } = require('../utils/log');
8
8
 
9
9
  const name = 'stop';
10
- const summary = 'Stop native app processes (does not touch Docker volumes)';
10
+ const summary = 'Stop native app + leftover Docker app containers (keeps DB volumes)';
11
11
 
12
12
  function help() {
13
13
  return `Usage: ragsuite-test stop [options]
14
14
 
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.
15
+ Runs scripts/native-stop.sh:
16
+ Stops host API / Expo / chroma PIDs
17
+ • Stops leftover Docker backend/frontend/worker if present
18
+ • Leaves postgres/redis running (and never uses down -v)
17
19
 
18
20
  Options:
19
21
  --repo-root <path> Override active install
@@ -5,25 +5,25 @@ const path = require('path');
5
5
  const { resolveRepoRoot, assertNativeDeploy, looksLikeGitCheckout } = require('../utils/paths');
6
6
  const { readConfig } = require('../utils/config');
7
7
  const { setActiveInstall } = require('../utils/global-config');
8
+ const { upgradeGlobalCli } = require('../utils/cli-self-update');
8
9
  const { captureCommand } = require('../utils/spawn');
9
10
  const { info, warn, error } = require('../utils/log');
10
11
 
11
12
  const name = 'update';
12
- const summary = 'git pull in place — keeps .env and data (no Docker)';
13
+ const summary = 'Upgrade CLI (npm -g) + app (git pull) — keeps .env and data';
13
14
 
14
15
  function help() {
15
16
  return `Usage: ragsuite-test update
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
+ Upgrades everything safely:
19
+ 1. npm install -g @nitsan-ai/ragsuite-test@latest (CLI on PATH)
20
+ 2. git pull in the active install dir (app source)
20
21
 
21
- Never runs docker compose (no volume risk).
22
+ Keeps .env and database volumes. Never runs docker compose down -v.
22
23
 
23
- Typical flow after a new release:
24
+ If you previously ran \`npm i @nitsan-ai/ragsuite-test\` without -g,
25
+ the command disappears from PATH. Fix with:
24
26
  npm install -g @nitsan-ai/ragsuite-test@latest
25
- ragsuite-test update
26
- ragsuite-test start
27
27
 
28
28
  Options:
29
29
  --repo-root <path> Override active install
@@ -31,30 +31,12 @@ Options:
31
31
  `;
32
32
  }
33
33
 
34
- function run(ctx) {
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
- }
47
-
48
- setActiveInstall(repoRoot);
49
- const cfg = readConfig(repoRoot);
50
- const source = (cfg && cfg.source) || 'git';
51
-
52
- info(`Updating install: ${repoRoot}`);
53
- info(` source=${source} mode=native`);
34
+ function updateAppSource(repoRoot, env, dryRun) {
35
+ info(`Updating app install: ${repoRoot}`);
54
36
  info(' (.env and database data are kept)');
55
37
  info('');
56
38
 
57
- if (ctx.globals.dryRun) {
39
+ if (dryRun) {
58
40
  info('[dry-run] would update via git pull --ff-only');
59
41
  return 0;
60
42
  }
@@ -67,24 +49,63 @@ function run(ctx) {
67
49
  info('Fetching and pulling latest from git (non-destructive)…');
68
50
  const pull = captureCommand('git', ['pull', '--ff-only'], {
69
51
  cwd: repoRoot,
70
- env: ctx.env,
52
+ env,
71
53
  });
72
54
  if (pull.status !== 0) {
73
- warn(`git pull --ff-only failed (exit ${pull.status}). Trying fetch + status…`);
55
+ warn(`git pull --ff-only failed (exit ${pull.status}).`);
74
56
  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 });
57
+ captureCommand('git', ['fetch', '--all', '--prune'], { cwd: repoRoot, env });
58
+ const st = captureCommand('git', ['status', '-sb'], { cwd: repoRoot, env });
77
59
  if (st.stdout) info(String(st.stdout).trimEnd());
78
60
  error('Could not fast-forward. Fix local commits or stash, then: cd install && git pull');
79
61
  return 1;
80
62
  }
81
63
  if (pull.stdout) info(String(pull.stdout).trimEnd());
82
64
  info('git pull OK.');
65
+ return 0;
66
+ }
67
+
68
+ function run(ctx) {
69
+ info('=== Upgrade ===');
70
+ info('');
71
+
72
+ const cliResult = upgradeGlobalCli({
73
+ dryRun: ctx.globals.dryRun,
74
+ env: ctx.env,
75
+ });
76
+ if (cliResult.status !== 0) {
77
+ return cliResult.status;
78
+ }
79
+
80
+ info('');
81
+
82
+ let repoRoot = null;
83
+ try {
84
+ repoRoot = resolveRepoRoot({
85
+ cwd: ctx.cwd,
86
+ repoRootFlag: ctx.globals.repoRoot,
87
+ env: ctx.env,
88
+ });
89
+ assertNativeDeploy(repoRoot);
90
+ } catch (err) {
91
+ warn('No app install found yet — CLI was updated only.');
92
+ info('First time? ragsuite-test init && ragsuite-test start');
93
+ return 0;
94
+ }
95
+
96
+ setActiveInstall(repoRoot);
97
+ const cfg = readConfig(repoRoot);
98
+ const source = (cfg && cfg.source) || 'git';
99
+ info(`App source=${source} mode=native`);
100
+ info('');
101
+
102
+ const appCode = updateAppSource(repoRoot, ctx.env, ctx.globals.dryRun);
103
+ if (appCode !== 0) return appCode;
104
+
83
105
  info('');
84
- info('Restart to apply:');
106
+ info('Done. Apply with:');
85
107
  info(' ragsuite-test stop');
86
108
  info(' ragsuite-test start');
87
- info(' # or: cd install && npm run stop && npm start');
88
109
  return 0;
89
110
  }
90
111
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  const path = require('path');
4
4
  const { info } = require('../utils/log');
5
+ const { PACKAGE_NAME } = require('../utils/cli-self-update');
5
6
 
6
7
  const name = 'version';
7
8
  const summary = 'Print CLI package version';
@@ -9,7 +10,11 @@ const summary = 'Print CLI package version';
9
10
  function help() {
10
11
  return `Usage: ragsuite-test version
11
12
 
12
- Print @nitsan-ai/ragsuite-test version from package.json.
13
+ Print ${PACKAGE_NAME} version from package.json.
14
+
15
+ Upgrade:
16
+ npm install -g ${PACKAGE_NAME}@latest
17
+ # or: ragsuite-test update
13
18
  `;
14
19
  }
15
20
 
@@ -17,6 +22,7 @@ function run() {
17
22
  const pkgPath = path.join(__dirname, '..', '..', 'package.json');
18
23
  const pkg = require(pkgPath);
19
24
  info(`${pkg.name}@${pkg.version}`);
25
+ info(`Upgrade: npm install -g ${PACKAGE_NAME}@latest`);
20
26
  return 0;
21
27
  }
22
28
 
package/src/index.js CHANGED
@@ -18,9 +18,16 @@ function globalHelp() {
18
18
  const lines = [
19
19
  'RAGSuite test CLI (experimental)',
20
20
  '',
21
+ 'Install / upgrade (global — required for the ragsuite-test command):',
22
+ ' npm install -g @nitsan-ai/ragsuite-test@latest',
23
+ '',
21
24
  'Usage: ragsuite-test <command> [options]',
22
25
  '',
23
- 'Deploy path: git clone + native npm scripts (no Docker).',
26
+ 'Typical flow:',
27
+ ' ragsuite-test init',
28
+ ' ragsuite-test start',
29
+ ' ragsuite-test update # upgrades CLI + app (keeps data)',
30
+ ' ragsuite-test stop',
24
31
  '',
25
32
  'Commands:',
26
33
  ];
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const { captureCommand } = require('./spawn');
5
+ const { info, warn, error } = require('./log');
6
+
7
+ const PACKAGE_NAME = '@nitsan-ai/ragsuite-test';
8
+
9
+ function localCliVersion() {
10
+ try {
11
+ const pkg = require(path.join(__dirname, '..', '..', 'package.json'));
12
+ return String(pkg.version || '');
13
+ } catch {
14
+ return '';
15
+ }
16
+ }
17
+
18
+ /**
19
+ * Upgrade the global CLI binary (npm install -g).
20
+ * Safe for end users; does not touch app data or Docker volumes.
21
+ * @returns {{ status: number, versionBefore: string, versionAfter: string|null }}
22
+ */
23
+ function upgradeGlobalCli({ dryRun = false, env = process.env } = {}) {
24
+ const versionBefore = localCliVersion();
25
+ info(`Updating CLI package: npm install -g ${PACKAGE_NAME}@latest`);
26
+ info(' (must use -g so the ragsuite-test command stays on your PATH)');
27
+
28
+ if (dryRun) {
29
+ info(`[dry-run] would run: npm install -g ${PACKAGE_NAME}@latest`);
30
+ return { status: 0, versionBefore, versionAfter: versionBefore };
31
+ }
32
+
33
+ const result = captureCommand(
34
+ 'npm',
35
+ ['install', '-g', `${PACKAGE_NAME}@latest`],
36
+ { env },
37
+ );
38
+ if (result.status !== 0) {
39
+ error(`CLI update failed (exit ${result.status}).`);
40
+ if (result.stderr) error(String(result.stderr).trimEnd());
41
+ if (result.stdout) warn(String(result.stdout).trimEnd());
42
+ error(`Fix: npm install -g ${PACKAGE_NAME}@latest`);
43
+ return { status: result.status || 1, versionBefore, versionAfter: null };
44
+ }
45
+ if (result.stdout) info(String(result.stdout).trimEnd());
46
+
47
+ // Re-read from the newly installed global package when possible
48
+ let versionAfter = null;
49
+ const which = captureCommand('npm', ['root', '-g'], { env });
50
+ if (which.status === 0 && which.stdout) {
51
+ const root = String(which.stdout).trim();
52
+ try {
53
+ const pkg = require(path.join(root, PACKAGE_NAME, 'package.json'));
54
+ versionAfter = String(pkg.version || '');
55
+ } catch {
56
+ versionAfter = null;
57
+ }
58
+ }
59
+
60
+ if (versionAfter) {
61
+ info(`CLI is now ${PACKAGE_NAME}@${versionAfter}`);
62
+ } else {
63
+ info(`CLI update finished. Check: ragsuite-test version`);
64
+ }
65
+ return { status: 0, versionBefore, versionAfter };
66
+ }
67
+
68
+ module.exports = {
69
+ PACKAGE_NAME,
70
+ localCliVersion,
71
+ upgradeGlobalCli,
72
+ };
package/src/utils/port.js CHANGED
@@ -35,7 +35,17 @@ async function assertApiPortFree(env = process.env) {
35
35
  const busy = await isPortInUse(port);
36
36
  if (busy) {
37
37
  const err = new Error(
38
- `API port ${port} is already in use. Stop the other process (e.g. npm run down or npm run stop:native) and retry. This CLI will not kill foreign processes.`,
38
+ [
39
+ `API port ${port} is already in use.`,
40
+ 'This CLI will not kill foreign processes.',
41
+ '',
42
+ 'If a previous RAGSuite install is running:',
43
+ ' ragsuite-test stop',
44
+ ' # frees native PIDs + leftover Docker app containers (keeps DB volumes)',
45
+ '',
46
+ 'See what owns the port:',
47
+ ` lsof -nP -iTCP:${port} -sTCP:LISTEN`,
48
+ ].join('\n'),
39
49
  );
40
50
  err.code = 'PORT_IN_USE';
41
51
  throw err;
@@ -43,11 +53,10 @@ async function assertApiPortFree(env = process.env) {
43
53
  return port;
44
54
  }
45
55
 
56
+ /** @deprecated Prefer start-time API checks; init must not require free DB ports. */
46
57
  const DEFAULT_INSTALL_PORTS = [
47
58
  { port: 9090, label: 'API' },
48
- { port: 9091, label: 'Web UI' },
49
- { port: 5436, label: 'Postgres' },
50
- { port: 6382, label: 'Redis' },
59
+ { port: 9191, label: 'Expo web' },
51
60
  ];
52
61
 
53
62
  async function assertPortsFree(ports = DEFAULT_INSTALL_PORTS) {
@@ -63,17 +72,8 @@ async function assertPortsFree(ports = DEFAULT_INSTALL_PORTS) {
63
72
  const err = new Error(
64
73
  [
65
74
  `Port(s) already in use: ${busy.join(', ')}.`,
66
- 'Free them, then retry. This CLI will not kill foreign processes.',
67
- '',
68
- 'If a previous RAGSuite install is running:',
69
- ' ragsuite-test stop',
70
- ' # or: npm run stop',
71
- '',
72
- 'See what owns the ports (macOS/Linux):',
73
- ' lsof -nP -iTCP:9090 -sTCP:LISTEN',
74
- ' lsof -nP -iTCP:9191 -sTCP:LISTEN',
75
- ' lsof -nP -iTCP:5436 -sTCP:LISTEN',
76
- ' lsof -nP -iTCP:6382 -sTCP:LISTEN',
75
+ 'Run: ragsuite-test stop',
76
+ 'Then retry. Postgres/Redis being up is expected for native mode.',
77
77
  ].join('\n'),
78
78
  );
79
79
  err.code = 'PORT_IN_USE';