@nitsan-ai/ragsuite-test 0.1.0 → 0.1.1
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 +56 -39
- package/package.json +1 -1
- package/src/commands/init.js +123 -94
- package/src/commands/update.js +7 -20
- package/src/index.js +10 -6
- package/src/utils/args.js +91 -30
- package/src/utils/distribution.js +13 -8
- package/src/utils/env-file.js +124 -21
- package/src/utils/git-install.js +93 -0
- package/src/utils/paths.js +1 -1
- package/src/utils/port.js +15 -1
- package/src/utils/prereqs.js +78 -16
- package/src/utils/zip-install.js +0 -213
package/README.md
CHANGED
|
@@ -2,84 +2,101 @@
|
|
|
2
2
|
|
|
3
3
|
> **TESTING PACKAGE** — `@nitsan-ai/ragsuite-test` / `ragsuite-test` is temporary.
|
|
4
4
|
> **Not** the final production `@nitsan-ai/ragsuite` / `ragsuite` CLI (later release).
|
|
5
|
-
> Do **not** treat this as the long-term npm identity.
|
|
6
5
|
|
|
7
6
|
Wraps monorepo Docker/native scripts. Does **not** reimplement compose.
|
|
8
7
|
|
|
9
|
-
Requires **Node.js 18+**.
|
|
8
|
+
Requires **Node.js 18+**. **Docker is optional.** Public deploy path: **`npm` → `init --from-git`**.
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
## Prerequisites
|
|
12
11
|
|
|
13
|
-
|
|
|
14
|
-
|
|
15
|
-
|
|
|
16
|
-
|
|
|
12
|
+
| Need | Why | How to get it |
|
|
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 |
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
### Mode A — Docker (optional)
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
- Docker Desktop / daemon + `docker compose`
|
|
23
|
+
- https://www.docker.com/products/docker-desktop/
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
### Mode B — Native (no Docker)
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
- `python3`, `yarn` (or corepack)
|
|
28
|
+
- Postgres on **localhost:5436**, database `ragsuite_v3`
|
|
29
|
+
- Redis on **localhost:6382**
|
|
30
|
+
|
|
31
|
+
## Install (public)
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
ragsuite-test
|
|
33
|
+
```bash
|
|
34
|
+
npm install -g @nitsan-ai/ragsuite-test
|
|
30
35
|
|
|
31
|
-
# Or CI / noninteractive:
|
|
32
36
|
ragsuite-test init --yes \
|
|
33
|
-
--from-
|
|
37
|
+
--from-git \
|
|
34
38
|
--install-dir ~/ragsuite-test \
|
|
35
|
-
--mode docker
|
|
36
|
-
--llm-api-key 'your-key'
|
|
39
|
+
--mode docker
|
|
37
40
|
|
|
38
41
|
ragsuite-test start --repo-root ~/ragsuite-test --detach
|
|
39
42
|
# API http://localhost:9090 · Web http://localhost:9091
|
|
40
43
|
```
|
|
41
44
|
|
|
42
|
-
|
|
45
|
+
SMTP + LLM: **no init prompts**. JWT is auto-generated. Real SMTP belongs only in local `.env` (never commit). If `.env.example` still has placeholders, init writes smoke SMTP so the app can start — edit `.env` for real mail.
|
|
46
|
+
|
|
47
|
+
No Docker:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
ragsuite-test init --yes --from-git --install-dir ~/ragsuite-test --mode native
|
|
51
|
+
ragsuite-test start --repo-root ~/ragsuite-test
|
|
52
|
+
# API :9090 · Expo web :9191
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Existing checkout:
|
|
43
56
|
|
|
44
|
-
|
|
57
|
+
```bash
|
|
58
|
+
ragsuite-test init --yes --repo-root /path/to/RAGSUITE --mode native
|
|
59
|
+
```
|
|
45
60
|
|
|
46
|
-
|
|
47
|
-
|--------|------|
|
|
48
|
-
| Local ZIP | `--from-zip` (recommended for private testing) |
|
|
49
|
-
| Existing checkout | `--repo-root` |
|
|
50
|
-
| GitHub Release | `--from-release` — not implemented yet |
|
|
61
|
+
Interactive: `ragsuite-test init`
|
|
51
62
|
|
|
52
|
-
|
|
63
|
+
## Ports
|
|
53
64
|
|
|
54
|
-
|
|
65
|
+
| Service | Port |
|
|
66
|
+
|---------|------|
|
|
67
|
+
| API | 9090 |
|
|
68
|
+
| Web (Docker) | 9091 |
|
|
69
|
+
| Web (native Expo) | 9191 |
|
|
70
|
+
| Postgres | 5436 |
|
|
71
|
+
| Redis | 6382 |
|
|
55
72
|
|
|
56
|
-
|
|
57
|
-
-
|
|
73
|
+
```bash
|
|
74
|
+
ragsuite-test stop --repo-root ~/ragsuite-test
|
|
75
|
+
lsof -nP -iTCP:9090 -sTCP:LISTEN
|
|
76
|
+
docker ps
|
|
77
|
+
```
|
|
58
78
|
|
|
59
79
|
## Commands
|
|
60
80
|
|
|
61
81
|
| Command | Behavior |
|
|
62
82
|
|---------|----------|
|
|
63
|
-
| `init` |
|
|
83
|
+
| `init` | git clone or checkout → `.env` + config |
|
|
64
84
|
| `start` / `stop` | `scripts/docker-*.sh` or `native-*.sh` |
|
|
65
|
-
| `doctor` | `scripts/doctor.sh` |
|
|
85
|
+
| `doctor` | prereqs + `scripts/doctor.sh` |
|
|
66
86
|
| `logs` / `update` / `version` | As before |
|
|
67
87
|
|
|
68
|
-
## Publish
|
|
88
|
+
## Publish
|
|
69
89
|
|
|
70
|
-
See [PUBLISH.md](./PUBLISH.md)
|
|
90
|
+
See [PUBLISH.md](./PUBLISH.md) and [TEST_DISTRIBUTION.md](./TEST_DISTRIBUTION.md).
|
|
71
91
|
|
|
72
92
|
```bash
|
|
73
93
|
cd cli && npm run prepublish:check
|
|
74
|
-
|
|
75
|
-
RAGSUITE_TEST_ALLOW_PUBLISH=1 npm publish --access public
|
|
76
|
-
# Or: GitHub Actions → CLI publish (workflow_dispatch, NPM_TOKEN)
|
|
77
|
-
# Optional app ZIP: Actions → Release app ZIP
|
|
94
|
+
RAGSUITE_TEST_ALLOW_PUBLISH=1 npm publish --access public # only when approved
|
|
78
95
|
```
|
|
79
96
|
|
|
80
97
|
## Windows
|
|
81
98
|
|
|
82
|
-
Use WSL or Git Bash
|
|
99
|
+
Use WSL or Git Bash.
|
|
83
100
|
|
|
84
101
|
## Tests
|
|
85
102
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitsan-ai/ragsuite-test",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "RAGSuite testing CLI (ragsuite-test) — install from ZIP or --repo-root checkout. Temporary npm identity before public ragsuite release.",
|
|
6
6
|
"main": "src/index.js",
|
package/src/commands/init.js
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const fs = require('fs');
|
|
4
3
|
const path = require('path');
|
|
5
4
|
const { writeConfig, CONFIG_DIR } = require('../utils/config');
|
|
6
5
|
const { ensureRagsuiteDir, resolveRepoRoot, looksLikeRepoRoot } = require('../utils/paths');
|
|
7
6
|
const { assertSupportedInstall, installHint } = require('../utils/distribution');
|
|
8
7
|
const {
|
|
8
|
+
DEFAULT_GIT_URL,
|
|
9
9
|
defaultInstallDir,
|
|
10
|
-
|
|
11
|
-
} = require('../utils/
|
|
10
|
+
cloneGitToInstallDir,
|
|
11
|
+
} = require('../utils/git-install');
|
|
12
12
|
const { detectOs } = require('../utils/os-detect');
|
|
13
|
-
const {
|
|
14
|
-
|
|
13
|
+
const {
|
|
14
|
+
printPrereqs,
|
|
15
|
+
resolvePreferredMode,
|
|
16
|
+
dockerDaemonRunning,
|
|
17
|
+
commandExists,
|
|
18
|
+
} = require('../utils/prereqs');
|
|
19
|
+
const { ask, choose } = require('../utils/prompt');
|
|
15
20
|
const {
|
|
16
21
|
generateJwtSecret,
|
|
17
|
-
generateCiLlmKey,
|
|
18
22
|
isPlaceholderSecret,
|
|
19
23
|
writeInstallEnv,
|
|
20
24
|
} = require('../utils/env-file');
|
|
@@ -22,30 +26,7 @@ const { assertPortsFree } = require('../utils/port');
|
|
|
22
26
|
const { info, warn, error } = require('../utils/log');
|
|
23
27
|
|
|
24
28
|
const name = 'init';
|
|
25
|
-
const summary = 'Installer wizard:
|
|
26
|
-
|
|
27
|
-
function help() {
|
|
28
|
-
return `Usage: ragsuite-test init [options]
|
|
29
|
-
|
|
30
|
-
Interactive installer (or --yes for CI) that:
|
|
31
|
-
- detects OS / prerequisites
|
|
32
|
-
- installs from ZIP or configures a checkout
|
|
33
|
-
- writes .ragsuite-test/config.json and .env (JWT auto-generated)
|
|
34
|
-
- checks ports 9090, 9091, 5436, 6382
|
|
35
|
-
|
|
36
|
-
Install sources:
|
|
37
|
-
--from-zip <path> Extract app ZIP into --install-dir
|
|
38
|
-
--repo-root <path> Use an existing monorepo checkout
|
|
39
|
-
--from-release <tag> Not implemented (download ZIP manually)
|
|
40
|
-
|
|
41
|
-
Options:
|
|
42
|
-
--install-dir <path> ZIP target (default: ~/ragsuite-test)
|
|
43
|
-
--mode <docker|native> docker = Docker stack; native = no Docker (needs host Postgres/Redis)
|
|
44
|
-
--llm-api-key <key> CUSTOM_LLM_INTERNAL_API_KEY (--yes)
|
|
45
|
-
--force Overwrite non-empty install dir / existing .env
|
|
46
|
-
--yes, -y Non-interactive (requires --from-zip or --repo-root)
|
|
47
|
-
`;
|
|
48
|
-
}
|
|
29
|
+
const summary = 'Installer wizard: git clone or checkout → .env + config';
|
|
49
30
|
|
|
50
31
|
function printSuccess(repoRoot, mode) {
|
|
51
32
|
info('');
|
|
@@ -61,7 +42,7 @@ function printSuccess(repoRoot, mode) {
|
|
|
61
42
|
info(' Web http://localhost:9091 (Docker nginx)');
|
|
62
43
|
}
|
|
63
44
|
info('');
|
|
64
|
-
info('
|
|
45
|
+
info(' Docker is optional: native mode needs host Postgres :5436 + Redis :6382.');
|
|
65
46
|
info(' Each install directory is one deployment / one organization.');
|
|
66
47
|
info('');
|
|
67
48
|
info('Next steps:');
|
|
@@ -76,23 +57,57 @@ function printSuccess(repoRoot, mode) {
|
|
|
76
57
|
info(installHint());
|
|
77
58
|
}
|
|
78
59
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
60
|
+
function help() {
|
|
61
|
+
return `Usage: ragsuite-test init [options]
|
|
62
|
+
|
|
63
|
+
Interactive installer (or --yes for CI) that:
|
|
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
|
|
73
|
+
|
|
74
|
+
Run mode (Docker is NOT required):
|
|
75
|
+
--mode native Default when Docker is unavailable — host Postgres/Redis
|
|
76
|
+
--mode docker Full compose stack (needs Docker Desktop / daemon)
|
|
77
|
+
|
|
78
|
+
Optional overrides (defaults come from .env.example — usually not needed):
|
|
79
|
+
--llm-api-key <key> Override CUSTOM_LLM_INTERNAL_API_KEY
|
|
80
|
+
--smtp-host / --smtp-user / --smtp-password / --email-from
|
|
81
|
+
|
|
82
|
+
Options:
|
|
83
|
+
--install-dir <path> Target for --from-git (default: ~/ragsuite-test)
|
|
84
|
+
--force Overwrite non-empty install dir / existing .env
|
|
85
|
+
--yes, -y Non-interactive (requires --from-git or --repo-root)
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function optionalSmtpOverrides(g, env) {
|
|
90
|
+
const host = g.smtpHost || env.RAGSUITE_TEST_SMTP_HOST || null;
|
|
91
|
+
const user = g.smtpUser || env.RAGSUITE_TEST_SMTP_USER || null;
|
|
92
|
+
const password = g.smtpPassword || env.RAGSUITE_TEST_SMTP_PASSWORD || null;
|
|
93
|
+
const emailFrom = g.emailFrom || env.RAGSUITE_TEST_EMAIL_FROM || null;
|
|
94
|
+
if (!host && !user && !password && !emailFrom) return null;
|
|
95
|
+
return { host, user, password, emailFrom };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function resolveLlmOverride(g, env) {
|
|
99
|
+
if (g.llmApiKey && !isPlaceholderSecret(g.llmApiKey)) return g.llmApiKey;
|
|
83
100
|
if (env.RAGSUITE_TEST_LLM_API_KEY && !isPlaceholderSecret(env.RAGSUITE_TEST_LLM_API_KEY)) {
|
|
84
101
|
return env.RAGSUITE_TEST_LLM_API_KEY;
|
|
85
102
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
error('Key required and must not start with change-me');
|
|
95
|
-
}
|
|
103
|
+
return null; // keep .env.example default
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function countSources(fromGit, repoRootFlag) {
|
|
107
|
+
let n = 0;
|
|
108
|
+
if (fromGit !== null && fromGit !== undefined) n += 1;
|
|
109
|
+
if (repoRootFlag) n += 1;
|
|
110
|
+
return n;
|
|
96
111
|
}
|
|
97
112
|
|
|
98
113
|
async function run(ctx) {
|
|
@@ -101,45 +116,49 @@ async function run(ctx) {
|
|
|
101
116
|
const interactive = Boolean(process.stdin.isTTY) && !g.yes;
|
|
102
117
|
|
|
103
118
|
if (g.fromRelease) {
|
|
104
|
-
error(
|
|
105
|
-
`--from-release is not implemented. Download a ZIP (private Release asset or local file), then: ragsuite-test init --from-zip <file.zip>`,
|
|
106
|
-
);
|
|
119
|
+
error('--from-release is not supported. Use --from-git or --repo-root.');
|
|
107
120
|
return 1;
|
|
108
121
|
}
|
|
109
122
|
|
|
110
|
-
if (g.
|
|
111
|
-
error('Use
|
|
123
|
+
if (countSources(g.fromGit, g.repoRoot) > 1) {
|
|
124
|
+
error('Use only one of --from-git or --repo-root');
|
|
112
125
|
return 1;
|
|
113
126
|
}
|
|
114
127
|
|
|
115
128
|
const osInfo = detectOs();
|
|
116
129
|
info(`OS: ${osInfo.label} (${osInfo.platform})`);
|
|
117
130
|
|
|
118
|
-
let
|
|
119
|
-
let fromZip = g.fromZip;
|
|
131
|
+
let fromGit = g.fromGit;
|
|
120
132
|
let repoRootFlag = g.repoRoot;
|
|
121
133
|
let installDir = g.installDir || defaultInstallDir();
|
|
134
|
+
let mode = g.mode || null;
|
|
122
135
|
|
|
123
136
|
if (g.yes) {
|
|
124
|
-
if (
|
|
125
|
-
error('--yes requires --from-
|
|
137
|
+
if (fromGit === null && !repoRootFlag) {
|
|
138
|
+
error('--yes requires --from-git [url] or --repo-root <path>');
|
|
126
139
|
return 1;
|
|
127
140
|
}
|
|
128
|
-
} else if (interactive &&
|
|
141
|
+
} else if (interactive && fromGit === null && !repoRootFlag) {
|
|
129
142
|
const method = await choose(
|
|
130
143
|
'Install method:',
|
|
131
144
|
[
|
|
132
|
-
{
|
|
133
|
-
|
|
145
|
+
{
|
|
146
|
+
id: 'git',
|
|
147
|
+
label: 'Public git clone (--from-git) — recommended',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: 'checkout',
|
|
151
|
+
label: 'Existing checkout (--repo-root)',
|
|
152
|
+
},
|
|
134
153
|
],
|
|
135
154
|
{ defaultIndex: 0 },
|
|
136
155
|
);
|
|
137
|
-
if (method.id === '
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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;
|
|
143
162
|
installDir = await ask('Install directory', {
|
|
144
163
|
defaultValue: defaultInstallDir(),
|
|
145
164
|
yesMode: false,
|
|
@@ -152,63 +171,73 @@ async function run(ctx) {
|
|
|
152
171
|
}
|
|
153
172
|
}
|
|
154
173
|
|
|
174
|
+
const dockerOk = commandExists('docker') && dockerDaemonRunning();
|
|
155
175
|
const modeChoice = await choose(
|
|
156
|
-
'Run mode (Docker is optional):',
|
|
176
|
+
'Run mode (Docker is optional — native works without Docker):',
|
|
157
177
|
[
|
|
158
|
-
{
|
|
159
|
-
|
|
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
|
+
},
|
|
160
188
|
],
|
|
161
189
|
{ defaultIndex: 0 },
|
|
162
190
|
);
|
|
163
191
|
mode = modeChoice.id;
|
|
164
|
-
|
|
165
|
-
|
|
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');
|
|
166
198
|
return 1;
|
|
167
199
|
}
|
|
168
200
|
|
|
169
|
-
if (!
|
|
201
|
+
if (!mode) {
|
|
202
|
+
mode = resolvePreferredMode(g.mode);
|
|
203
|
+
info(`Run mode: ${mode} (Docker is optional; pass --mode docker|native to force)`);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const needGit = fromGit !== null && fromGit !== undefined;
|
|
207
|
+
if (!printPrereqs(mode, { needGit })) {
|
|
170
208
|
error('Fix prerequisites above and re-run init');
|
|
171
209
|
return 1;
|
|
172
210
|
}
|
|
173
211
|
|
|
174
212
|
const jwtSecret = generateJwtSecret();
|
|
175
213
|
info(`JWT_SECRET_KEY will be auto-generated (…${jwtSecret.slice(-8)})`);
|
|
214
|
+
info('SMTP + LLM: using defaults from .env.example (optional flags can override).');
|
|
176
215
|
|
|
177
|
-
const llmKey =
|
|
216
|
+
const llmKey = resolveLlmOverride(g, ctx.env);
|
|
217
|
+
const smtp = optionalSmtpOverrides(g, ctx.env);
|
|
178
218
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (!smtpSkipped) {
|
|
186
|
-
info('After init, edit SMTP_* in .env (SMTP_HOST, SMTP_USER, SMTP_PASSWORD, EMAIL_FROM).');
|
|
219
|
+
if (ctx.env.RAGSUITE_TEST_SKIP_PORT_CHECK !== '1') {
|
|
220
|
+
try {
|
|
221
|
+
await assertPortsFree();
|
|
222
|
+
} catch (err) {
|
|
223
|
+
error(err.message);
|
|
224
|
+
return 1;
|
|
187
225
|
}
|
|
188
|
-
} else {
|
|
189
|
-
warn('SMTP skipped (--yes / noninteractive). Invites/email may fail until SMTP_* is set.');
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Port checks before mutating install (clearer UX)
|
|
193
|
-
try {
|
|
194
|
-
await assertPortsFree();
|
|
195
|
-
} catch (err) {
|
|
196
|
-
error(err.message);
|
|
197
|
-
return 1;
|
|
198
226
|
}
|
|
199
227
|
|
|
200
228
|
let repoRoot;
|
|
201
229
|
let source = 'checkout';
|
|
202
230
|
|
|
203
231
|
try {
|
|
204
|
-
if (
|
|
205
|
-
|
|
206
|
-
|
|
232
|
+
if (fromGit !== null && fromGit !== undefined) {
|
|
233
|
+
const url = fromGit === '' ? DEFAULT_GIT_URL : fromGit;
|
|
234
|
+
info(`Cloning ${url} → ${path.resolve(installDir)}`);
|
|
235
|
+
const result = cloneGitToInstallDir(url, {
|
|
207
236
|
installDir,
|
|
208
237
|
force: g.force,
|
|
209
238
|
});
|
|
210
239
|
repoRoot = result.repoRoot;
|
|
211
|
-
source = '
|
|
240
|
+
source = 'git';
|
|
212
241
|
info(`Installed app at ${repoRoot}`);
|
|
213
242
|
} else {
|
|
214
243
|
repoRoot = resolveRepoRoot({
|
|
@@ -235,10 +264,10 @@ async function run(ctx) {
|
|
|
235
264
|
force: g.force,
|
|
236
265
|
jwtSecret,
|
|
237
266
|
llmApiKey: llmKey,
|
|
238
|
-
|
|
267
|
+
smtp,
|
|
239
268
|
});
|
|
240
269
|
} catch (err) {
|
|
241
|
-
if (err.code === 'ENV_EXISTS') {
|
|
270
|
+
if (err.code === 'ENV_EXISTS' || err.code === 'ENV_INCOMPLETE') {
|
|
242
271
|
error(err.message);
|
|
243
272
|
return 1;
|
|
244
273
|
}
|
package/src/commands/update.js
CHANGED
|
@@ -14,8 +14,7 @@ function help() {
|
|
|
14
14
|
return `Usage: ragsuite-test update [options]
|
|
15
15
|
|
|
16
16
|
Verifies the install/repo path and prints safe update steps.
|
|
17
|
-
|
|
18
|
-
Checkout installs: optional git fetch + status (no reset).
|
|
17
|
+
Git installs: git fetch + pull guidance (no destructive reset).
|
|
19
18
|
|
|
20
19
|
Never runs docker compose down -v.
|
|
21
20
|
|
|
@@ -32,38 +31,26 @@ function run(ctx) {
|
|
|
32
31
|
});
|
|
33
32
|
|
|
34
33
|
const cfg = readConfig(repoRoot);
|
|
35
|
-
const source = cfg && cfg.source
|
|
34
|
+
const source = (cfg && cfg.source) || 'checkout';
|
|
36
35
|
|
|
37
36
|
info(`Install path OK: ${repoRoot}`);
|
|
38
37
|
info(` source=${source}`);
|
|
39
38
|
info('');
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
info('This install came from a ZIP. Safe update steps:');
|
|
43
|
-
info(' 1. ragsuite-test stop --repo-root ' + repoRoot);
|
|
44
|
-
info(' 2. Download a newer release ZIP (do not wipe Docker volumes)');
|
|
45
|
-
info(' 3. Extract to a NEW directory, e.g. --install-dir ~/ragsuite-test-v2');
|
|
46
|
-
info(' or: backup this dir, then init --from-zip … --force');
|
|
47
|
-
info(' 4. Copy your .env into the new install (do not commit secrets)');
|
|
48
|
-
info(' 5. ragsuite-test doctor --repo-root <new-dir>');
|
|
49
|
-
info(' 6. ragsuite-test start --repo-root <new-dir>');
|
|
50
|
-
info('');
|
|
51
|
-
info('Never: docker compose down -v (destroys Postgres/Chroma data).');
|
|
52
|
-
return 0;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
info('Safe update steps (checkout install):');
|
|
40
|
+
info('Safe update steps:');
|
|
56
41
|
info(' 1. Stop the stack (ragsuite-test stop --repo-root …)');
|
|
57
|
-
info(' 2. Update sources (git pull
|
|
42
|
+
info(' 2. Update sources (git pull)');
|
|
58
43
|
info(' 3. Docker: npm run rebuild or docker compose build');
|
|
59
44
|
info(' 4. Native: re-run backend/scripts/setup.sh if Python deps changed');
|
|
60
45
|
info(' 5. Start again (ragsuite-test start --repo-root …)');
|
|
61
46
|
info(' 6. Run doctor after upgrades');
|
|
62
47
|
info('');
|
|
48
|
+
info('Never: docker compose down -v (destroys Postgres/Chroma data).');
|
|
49
|
+
info('');
|
|
63
50
|
|
|
64
51
|
const gitDir = path.join(repoRoot, '.git');
|
|
65
52
|
if (!fs.existsSync(gitDir)) {
|
|
66
|
-
warn('No .git directory — skip fetch/status
|
|
53
|
+
warn('No .git directory — skip fetch/status. Re-init with --from-git if needed.');
|
|
67
54
|
return 0;
|
|
68
55
|
}
|
|
69
56
|
|
package/src/index.js
CHANGED
|
@@ -31,16 +31,20 @@ function globalHelp() {
|
|
|
31
31
|
'Global options:',
|
|
32
32
|
' --help, -h Show help',
|
|
33
33
|
' --repo-root <path> Monorepo / install root',
|
|
34
|
-
' --from-
|
|
35
|
-
' --install-dir <path> init:
|
|
36
|
-
' --
|
|
37
|
-
' --
|
|
34
|
+
' --from-git [url] init: clone public monorepo',
|
|
35
|
+
' --install-dir <path> init: target for --from-git (default ~/ragsuite-test)',
|
|
36
|
+
' --llm-api-key <key> init: optional override for CUSTOM_LLM_INTERNAL_API_KEY',
|
|
37
|
+
' --smtp-host <host> init: optional SMTP override',
|
|
38
|
+
' --smtp-user <user> init: optional SMTP override',
|
|
39
|
+
' --smtp-password <pass> init: optional SMTP override',
|
|
40
|
+
' --email-from <email> init: optional SMTP override',
|
|
38
41
|
' --force init: overwrite non-empty install dir / .env',
|
|
39
42
|
' --yes, -y Non-interactive',
|
|
40
|
-
' --mode <docker|native> Override
|
|
43
|
+
' --mode <docker|native> Override config (Docker optional)',
|
|
41
44
|
' --dry-run Print actions without running (start/stop/doctor/logs)',
|
|
42
45
|
'',
|
|
43
46
|
'Env: RAGSUITE_REPO_ROOT or RAGSUITE_INSTALL_DIR',
|
|
47
|
+
' RAGSUITE_TEST_LLM_API_KEY, RAGSUITE_TEST_SMTP_* , RAGSUITE_TEST_EMAIL_FROM',
|
|
44
48
|
'',
|
|
45
49
|
'Run ragsuite-test <command> --help for command details.',
|
|
46
50
|
);
|
|
@@ -88,7 +92,7 @@ async function main(argv = process.argv) {
|
|
|
88
92
|
const code = typeof result?.then === 'function' ? await result : result;
|
|
89
93
|
return typeof code === 'number' ? code : 0;
|
|
90
94
|
} catch (err) {
|
|
91
|
-
if (err && (err.code === 'NOT_REPO_ROOT' || err.code === 'USAGE' || err.code === '
|
|
95
|
+
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')) {
|
|
92
96
|
error(err.message);
|
|
93
97
|
return 1;
|
|
94
98
|
}
|