satoridb 1.2.5 → 1.2.6

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.
Files changed (2) hide show
  1. package/cli.js +287 -278
  2. package/package.json +8 -3
package/cli.js CHANGED
@@ -1,278 +1,287 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Satori Interactive CLI (Improved)
5
- * - Command registry (easy to extend)
6
- * - Robust arg parsing (quotes, escapes)
7
- * - Fixed bugs (lecture args check, set_mindspace double call)
8
- * - Better UX (history, tab completion, prompt context)
9
- * - Centralized error handling
10
- */
11
-
12
- const path = require("path");
13
- const os = require("os");
14
- const fs = require("fs");
15
- const { spawnSync } = require("child_process");
16
- const readline = require("readline");
17
- const { Satori } = require("satori-node");
18
-
19
- // -------------------------------
20
- // Globals / State
21
- // -------------------------------
22
- const binName = os.platform() === "win32" ? "satori.exe" : "satori";
23
- const binPath = path.join(os.homedir(), ".satori", "bin", binName);
24
-
25
- let satori = null;
26
- let session = {
27
- host: null,
28
- user: null,
29
- password: null,
30
- mindspace: null,
31
- };
32
-
33
- // -------------------------------
34
- // Utils
35
- // -------------------------------
36
- function assertInstalled() {
37
- if (!fs.existsSync(binPath)) {
38
- console.error("āŒ Satori binary not found. Reinstall the package.");
39
- process.exit(1);
40
- }
41
- }
42
-
43
- function runBinary(args) {
44
- assertInstalled();
45
- const r = spawnSync(binPath, args, { stdio: "inherit" });
46
- if (r.error) throw r.error;
47
- }
48
-
49
- function parseArgs(line) {
50
- const re = /"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|(\S+)/g;
51
- const out = [];
52
- let m;
53
- while ((m = re.exec(line))) out.push(m[1] ?? m[2] ?? m[3]);
54
- return out.map(v => v.replace(/\\"/g, '"').replace(/\\'/g, "'"));
55
- }
56
-
57
- function parseData(v) {
58
- if (typeof v !== "string") return v;
59
- const t = v.trim();
60
- if (t === "true") return true;
61
- if (t === "false") return false;
62
- if (!isNaN(t) && t !== "") return Number(t);
63
- if (t.startsWith("{") || t.startsWith("[")) {
64
- try { return JSON.parse(t); } catch {}
65
- }
66
- return v;
67
- }
68
-
69
- function requireConn() {
70
- if (!satori) throw new Error("No active connection. Use: connect <host> [user] [password]");
71
- }
72
-
73
- function withCreds(p = {}) {
74
- if (session.user) p.user = session.user;
75
- if (session.password) p.password = session.password;
76
- return p;
77
- }
78
-
79
- function promptLabel() {
80
- return `satori${session.mindspace ? `:${session.mindspace}` : ""}> `;
81
- }
82
-
83
- // -------------------------------
84
- // Commands Registry
85
- // -------------------------------
86
- const commands = {
87
- help: {
88
- desc: "Show help",
89
- run() { showHelp(); }
90
- },
91
-
92
- exit: { run() { process.exit(0); } },
93
- quit: { run() { process.exit(0); } },
94
- clear: { run() { console.clear(); } },
95
-
96
- connect: {
97
- desc: "connect <host> [user] [password]",
98
- async run([host, user = null, password = null]) {
99
- if (!host) throw new Error("Usage: connect <host> [user] [password]");
100
- console.log(`šŸ”— Connecting to ${host}...`);
101
- satori = new Satori({ host, user, password });
102
- await satori.connect();
103
- Object.assign(session, { host, user, password });
104
- console.log("āœ… Connected");
105
- }
106
- },
107
-
108
- mindspace: {
109
- desc: "mindspace select <id>",
110
- run([sub, id]) {
111
- if (sub !== "select" || !id) throw new Error("Usage: mindspace select <id>");
112
- session.mindspace = id;
113
- console.log(`🧠 Mindspace selected: ${id}`);
114
- }
115
- },
116
-
117
- set: {
118
- desc: "set <key> <data>",
119
- async run([key, ...rest]) {
120
- requireConn();
121
- if (!key || !rest.length) throw new Error("Usage: set <key> <data>");
122
- const data = parseData(rest.join(" "));
123
- await satori.set(withCreds({ key, data }));
124
- console.log(`āœ… Saved: ${key}`);
125
- }
126
- },
127
-
128
- get: {
129
- desc: "get <key>",
130
- async run([key]) {
131
- requireConn();
132
- const r = await satori.get(withCreds(key ? { key } : {}));
133
- console.log(JSON.stringify(r, null, 2));
134
- }
135
- },
136
-
137
- put: {
138
- desc: "put <key> <field> <value>",
139
- async run([key, field, value]) {
140
- requireConn();
141
- if (!key || !field) throw new Error("Usage: put <key> <field> <value>");
142
- await satori.put(withCreds({ key, replace_field: field, replace_value: parseData(value) }));
143
- console.log("āœ… Updated");
144
- }
145
- },
146
-
147
- delete: {
148
- desc: "delete <key>",
149
- async run([key]) {
150
- requireConn();
151
- if (!key) throw new Error("Usage: delete <key>");
152
- await satori.delete(withCreds({ key }));
153
- console.log(`šŸ—‘ļø Deleted: ${key}`);
154
- }
155
- },
156
-
157
- ask: {
158
- desc: "ask \"<question>\"",
159
- async run([q, backend = null]) {
160
- requireConn();
161
- if (!q) throw new Error("Usage: ask \"<question>\"");
162
- const r = await satori.ask(withCreds({ question: q, backend }));
163
- console.log(JSON.stringify(r, null, 2));
164
- }
165
- },
166
-
167
- query: {
168
- desc: "query \"<query>\"",
169
- async run([q, backend = null]) {
170
- requireConn();
171
- if (!q) throw new Error("Usage: query \"<query>\"");
172
- const r = await satori.query(withCreds({ query: q, backend }));
173
- console.log(JSON.stringify(r, null, 2));
174
- }
175
- },
176
-
177
- chat: {
178
- desc: "chat \"<message>\"",
179
- async run([msg]) {
180
- requireConn();
181
- if (!session.mindspace) throw new Error("Select a mindspace first");
182
- const r = await satori.chatMindspace({ mindspace_id: session.mindspace, message: msg });
183
- console.log(r);
184
- }
185
- },
186
-
187
- lecture: {
188
- desc: "lecture \"<corpus>\"",
189
- async run([corpus]) {
190
- requireConn();
191
- if (!session.mindspace) throw new Error("Select a mindspace first");
192
- const r = await satori.lectureMindspace({ mindspace_id: session.mindspace, corpus });
193
- console.log(r.data);
194
- }
195
- },
196
- set_mindspace: {
197
- desc: "set_mindspace <config> [mindspace_id]",
198
- async run([config, mindspace_id]) {
199
- requireConn();
200
- if (!config) throw new Error("Usage: set_mindspace <config> [mindspace_id]");
201
-
202
-
203
- const payload = { config };
204
- if (mindspace_id) payload.mindspace_id = mindspace_id;
205
- else if (session.mindspace) payload.mindspace_id = session.mindspace;
206
-
207
-
208
- const res = await satori.setMindspace(payload);
209
- if (payload.mindspace_id) session.mindspace = payload.mindspace_id;
210
-
211
-
212
- console.log(`🧠 Mindspace configured: ${payload.mindspace_id ?? res.data}`);
213
- }
214
- },
215
- };
216
-
217
- // -------------------------------
218
- // Help
219
- // -------------------------------
220
- function showHelp() {
221
- console.log("\nšŸ“š Commands:\n");
222
- Object.entries(commands).forEach(([k, v]) => {
223
- if (v.desc) console.log(` ${k.padEnd(12)} ${v.desc}`);
224
- });
225
- console.log("");
226
- }
227
-
228
- // -------------------------------
229
- // Interactive Shell
230
- // -------------------------------
231
- async function startREPL() {
232
- const rl = readline.createInterface({
233
- input: process.stdin,
234
- output: process.stdout,
235
- historySize: 500,
236
- completer(line) {
237
- const hits = Object.keys(commands).filter(c => c.startsWith(line));
238
- return [hits.length ? hits : Object.keys(commands), line];
239
- }
240
- });
241
-
242
- const refreshPrompt = () => rl.setPrompt(promptLabel());
243
- refreshPrompt();
244
- rl.prompt();
245
-
246
- rl.on("line", async (line) => {
247
- const parts = parseArgs(line.trim());
248
- if (!parts.length) return rl.prompt();
249
-
250
- const [cmd, ...args] = parts;
251
- const entry = commands[cmd];
252
-
253
- try {
254
- if (!entry) throw new Error("Unknown command. Type 'help'.");
255
- await entry.run(args);
256
- } catch (e) {
257
- console.error("āŒ", e.message);
258
- }
259
-
260
- refreshPrompt();
261
- rl.prompt();
262
- });
263
- }
264
-
265
- // -------------------------------
266
- // Entry
267
- // -------------------------------
268
- const argv = process.argv.slice(2);
269
-
270
- if (argv[0] === "run") {
271
- runBinary(argv.slice(1));
272
- } else if (argv[0] === "update") {
273
- require("./postinstall");
274
- } else if (argv[0] === "verify") {
275
- require("./verify-install");
276
- } else {
277
- startREPL();
278
- }
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Satori Interactive CLI (Improved)
5
+ * - Command registry (easy to extend)
6
+ * - Robust arg parsing (quotes, escapes)
7
+ * - Fixed bugs (lecture args check, set_mindspace double call)
8
+ * - Better UX (history, tab completion, prompt context)
9
+ * - Centralized error handling
10
+ */
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const satori_node_1 = require("satori-node");
16
+ const path_1 = __importDefault(require("path"));
17
+ const os_1 = __importDefault(require("os"));
18
+ const fs_1 = __importDefault(require("fs"));
19
+ const child_process_1 = require("child_process");
20
+ const readline_1 = __importDefault(require("readline"));
21
+ // -------------------------------
22
+ // Globals / State
23
+ // -------------------------------
24
+ const binName = os_1.default.platform() === "win32" ? "satori.exe" : "satori";
25
+ const binPath = path_1.default.join(os_1.default.homedir(), ".satori", "bin", binName);
26
+ let satori = null;
27
+ let session = {
28
+ host: null,
29
+ user: null,
30
+ password: null,
31
+ mindspace: null,
32
+ };
33
+ // -------------------------------
34
+ // Utils
35
+ // -------------------------------
36
+ function assertInstalled() {
37
+ if (!fs_1.default.existsSync(binPath)) {
38
+ console.error("āŒ Satori binary not found. Reinstall the package.");
39
+ process.exit(1);
40
+ }
41
+ }
42
+ function runBinary(args) {
43
+ assertInstalled();
44
+ const r = (0, child_process_1.spawnSync)(binPath, args, { stdio: "inherit" });
45
+ if (r.error)
46
+ throw r.error;
47
+ }
48
+ function parseArgs(line) {
49
+ const re = /"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|(\S+)/g;
50
+ const out = [];
51
+ let m;
52
+ while ((m = re.exec(line)))
53
+ out.push(m[1] ?? m[2] ?? m[3]);
54
+ return out.map(v => v.replace(/\\"/g, '"').replace(/\\'/g, "'"));
55
+ }
56
+ function parseData(v) {
57
+ if (typeof v !== "string")
58
+ return v;
59
+ const t = v.trim();
60
+ if (t === "true")
61
+ return true;
62
+ if (t === "false")
63
+ return false;
64
+ if (!isNaN(Number(t)) && t !== "")
65
+ return Number(t);
66
+ if (t.startsWith("{") || t.startsWith("[")) {
67
+ try {
68
+ return JSON.parse(t);
69
+ }
70
+ catch { }
71
+ }
72
+ return v;
73
+ }
74
+ function requireConn() {
75
+ if (!satori)
76
+ throw new Error("No active connection. Use: connect <host> [user] [password]");
77
+ }
78
+ function withCreds(p = {}) {
79
+ if (session.user)
80
+ p.user = session.user;
81
+ if (session.password)
82
+ p.password = session.password;
83
+ return p;
84
+ }
85
+ function promptLabel() {
86
+ return `satori${session.mindspace ? `:${session.mindspace}` : ""}> `;
87
+ }
88
+ // -------------------------------
89
+ // Commands Registry
90
+ // -------------------------------
91
+ const commands = {
92
+ help: {
93
+ desc: "Show help",
94
+ run() { showHelp(); }
95
+ },
96
+ exit: { run() { process.exit(0); } },
97
+ quit: { run() { process.exit(0); } },
98
+ clear: { run() { console.clear(); } },
99
+ connect: {
100
+ desc: "connect <host> [user] [password]",
101
+ async run([host, user = null, password = null]) {
102
+ if (!host)
103
+ throw new Error("Usage: connect <host> [user] [password]");
104
+ console.log(`šŸ”— Connecting to ${host}...`);
105
+ if (user != null && password != null) {
106
+ satori = new satori_node_1.Satori({ host, username: user, password });
107
+ }
108
+ else {
109
+ satori = new satori_node_1.Satori({ host: host, username: "", password: "" });
110
+ }
111
+ await satori.connect();
112
+ Object.assign(session, { host, user, password });
113
+ console.log("āœ… Connected");
114
+ }
115
+ },
116
+ mindspace: {
117
+ desc: "mindspace select <id>",
118
+ run([sub, id]) {
119
+ if (sub !== "select" || !id)
120
+ throw new Error("Usage: mindspace select <id>");
121
+ session.mindspace = id;
122
+ console.log(`🧠 Mindspace selected: ${id}`);
123
+ }
124
+ },
125
+ set: {
126
+ desc: "set <key> <data>",
127
+ async run([key, ...rest]) {
128
+ requireConn();
129
+ if (!key || !rest.length)
130
+ throw new Error("Usage: set <key> <data>");
131
+ const data = parseData(rest.join(" "));
132
+ await satori.set(withCreds({ key, data }));
133
+ console.log(`āœ… Saved: ${key}`);
134
+ }
135
+ },
136
+ get: {
137
+ desc: "get <key>",
138
+ async run([key]) {
139
+ requireConn();
140
+ const r = await satori.get(withCreds(key ? { key } : {}));
141
+ console.log(JSON.stringify(r, null, 2));
142
+ }
143
+ },
144
+ put: {
145
+ desc: "put <key> <field> <value>",
146
+ async run([key, field, value]) {
147
+ requireConn();
148
+ if (!key || !field)
149
+ throw new Error("Usage: put <key> <field> <value>");
150
+ await satori.put(withCreds({ key, replace_field: field, replace_value: parseData(value) }));
151
+ console.log("āœ… Updated");
152
+ }
153
+ },
154
+ delete: {
155
+ desc: "delete <key>",
156
+ async run([key]) {
157
+ requireConn();
158
+ if (!key)
159
+ throw new Error("Usage: delete <key>");
160
+ await satori.delete(withCreds({ key }));
161
+ console.log(`šŸ—‘ļø Deleted: ${key}`);
162
+ }
163
+ },
164
+ ask: {
165
+ desc: "ask \"<question>\"",
166
+ async run([q, backend = null]) {
167
+ requireConn();
168
+ if (!q)
169
+ throw new Error("Usage: ask \"<question>\"");
170
+ const r = await satori.ask(withCreds({ question: q, backend }));
171
+ console.log(JSON.stringify(r, null, 2));
172
+ }
173
+ },
174
+ query: {
175
+ desc: "query \"<query>\"",
176
+ async run([q, backend = null]) {
177
+ requireConn();
178
+ if (!q)
179
+ throw new Error("Usage: query \"<query>\"");
180
+ const r = await satori.query(withCreds({ query: q, backend }));
181
+ console.log(JSON.stringify(r, null, 2));
182
+ }
183
+ },
184
+ chat: {
185
+ desc: "chat \"<message>\"",
186
+ async run([msg]) {
187
+ requireConn();
188
+ if (!session.mindspace)
189
+ throw new Error("Select a mindspace first");
190
+ const r = await satori.chatMindspace({ minspace_id: session.mindspace, message: msg });
191
+ console.log(r);
192
+ }
193
+ },
194
+ lecture: {
195
+ desc: "lecture \"<corpus>\"",
196
+ async run([corpus]) {
197
+ requireConn();
198
+ if (!session.mindspace)
199
+ throw new Error("Select a mindspace first");
200
+ const r = await satori.lectureMindspace({ mindspace_id: session.mindspace, corpus });
201
+ console.log(r.message);
202
+ }
203
+ },
204
+ set_mindspace: {
205
+ desc: "set_mindspace [mindspace_id]",
206
+ async run([mindspace_id = null]) {
207
+ requireConn();
208
+ if (!satori)
209
+ throw new Error("No active connection");
210
+ let payload = { config: {} };
211
+ if (mindspace_id)
212
+ payload.mindspace_id = mindspace_id;
213
+ else if (session.mindspace)
214
+ payload.mindspace_id = session.mindspace;
215
+ const res = await satori.setMindspace(payload);
216
+ if (payload.mindspace_id)
217
+ session.mindspace = payload.mindspace_id;
218
+ console.log(`🧠 Mindspace configured: ${payload.mindspace_id ?? res.data}`);
219
+ }
220
+ },
221
+ };
222
+ // -------------------------------
223
+ // Help
224
+ // -------------------------------
225
+ function showHelp() {
226
+ console.log("\nšŸ“š Commands:\n");
227
+ Object.entries(commands).forEach(([k, v]) => {
228
+ if ('desc' in v && v.desc)
229
+ console.log(` ${k.padEnd(12)} ${v.desc}`);
230
+ });
231
+ console.log("");
232
+ }
233
+ // -------------------------------
234
+ // Interactive Shell
235
+ // -------------------------------
236
+ async function startREPL() {
237
+ const rl = readline_1.default.createInterface({
238
+ input: process.stdin,
239
+ output: process.stdout,
240
+ historySize: 500,
241
+ completer(line) {
242
+ const hits = Object.keys(commands).filter(c => c.startsWith(line));
243
+ return [hits.length ? hits : Object.keys(commands), line];
244
+ }
245
+ });
246
+ const refreshPrompt = () => rl.setPrompt(promptLabel());
247
+ refreshPrompt();
248
+ rl.prompt();
249
+ rl.on("line", async (line) => {
250
+ const parts = parseArgs(line.trim());
251
+ if (!parts.length)
252
+ return rl.prompt();
253
+ const [cmd, ...args] = parts;
254
+ const entry = commands[cmd];
255
+ try {
256
+ if (!entry)
257
+ throw new Error("Unknown command. Type 'help'.");
258
+ if (satori == null) {
259
+ console.error("āŒ You are not connected");
260
+ }
261
+ else {
262
+ await entry.run(args);
263
+ }
264
+ }
265
+ catch (e) {
266
+ console.error("āŒ", e.message);
267
+ }
268
+ refreshPrompt();
269
+ rl.prompt();
270
+ });
271
+ }
272
+ // -------------------------------
273
+ // Entry
274
+ // -------------------------------
275
+ const argv = process.argv.slice(2);
276
+ if (argv[0] === "run") {
277
+ runBinary(argv.slice(1));
278
+ }
279
+ else if (argv[0] === "update") {
280
+ require("./postinstall");
281
+ }
282
+ else if (argv[0] === "verify") {
283
+ require("./verify-install");
284
+ }
285
+ else {
286
+ startREPL();
287
+ }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "satoridb",
3
- "version": "1.2.5",
3
+ "version": "1.2.6",
4
4
  "description": "Install satori",
5
5
  "bin": {
6
6
  "satoridb": "./cli.js"
7
7
  },
8
8
  "scripts": {
9
+ "build": "tsc cli.ts --outDir . --target es2020 --module commonjs --esModuleInterop",
9
10
  "postinstall": "node postinstall.js",
10
11
  "verify": "node verify-install.js"
11
12
  },
@@ -13,12 +14,16 @@
13
14
  "license": "ISC",
14
15
  "dependencies": {
15
16
  "adm-zip": "^0.5.16",
16
- "satori-node": "^1.1.13"
17
+ "satori-node": "^1.1.13",
18
+ "typescript": "^5.9.3"
17
19
  },
18
20
  "files": [
19
21
  "postinstall.js",
20
22
  "add-to-path.ps1",
21
23
  "add-to-path.sh",
22
24
  "verify-install.js"
23
- ]
25
+ ],
26
+ "devDependencies": {
27
+ "@types/node": "^25.1.0"
28
+ }
24
29
  }