@lotics/cli 0.3.1 → 0.5.0
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 +21 -5
- package/dist/src/cli.js +84 -11
- package/dist/src/client.d.ts +1 -0
- package/dist/src/client.js +2 -1
- package/dist/src/config.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,18 +23,34 @@ npm install -g @lotics/cli@latest
|
|
|
23
23
|
|
|
24
24
|
The CLI checks for updates once per day and prompts when a new version is available.
|
|
25
25
|
|
|
26
|
-
##
|
|
26
|
+
## Authentication
|
|
27
|
+
|
|
28
|
+
**`lotics signup`** — Creates a new Lotics account, organization, workspace, and API key in one step. Prints email and auto-generated password for web app login.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
lotics signup # interactive prompts
|
|
32
|
+
lotics signup --email a@b.com --name "Agent" # non-interactive
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**`lotics auth`** — Saves an existing API key directly (e.g. one created in the Lotics web app).
|
|
27
36
|
|
|
28
37
|
```bash
|
|
29
|
-
# 1. Authenticate
|
|
30
38
|
lotics auth # interactive prompt
|
|
31
|
-
lotics auth ltk_... # non-interactive
|
|
39
|
+
lotics auth ltk_... # non-interactive
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
API key is saved to `~/.lotics/config.json`. Run `lotics logout` to remove saved credentials.
|
|
43
|
+
|
|
44
|
+
Auth priority: `--api-key` flag > `LOTICS_API_KEY` env > `~/.lotics/config.json`.
|
|
32
45
|
|
|
33
|
-
|
|
46
|
+
## CLI
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Discover tools
|
|
34
50
|
lotics tools # list tools by category with descriptions
|
|
35
51
|
lotics tools query_records # show full description + input schema
|
|
36
52
|
|
|
37
|
-
#
|
|
53
|
+
# Execute
|
|
38
54
|
lotics run query_tables '{}'
|
|
39
55
|
lotics run query_records '{"table_id":"tbl_...","field_keys":["name"]}'
|
|
40
56
|
|
package/dist/src/cli.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import readline from "node:readline";
|
|
5
|
-
import { LoticsClient } from "./client.js";
|
|
6
|
-
import { resolveAuth, loadConfig, saveConfig, deleteConfig,
|
|
5
|
+
import { LoticsClient, API_BASE_URL } from "./client.js";
|
|
6
|
+
import { resolveAuth, loadConfig, saveConfig, deleteConfig, checkForUpdate } from "./config.js";
|
|
7
7
|
import { VERSION } from "./version.js";
|
|
8
8
|
function printHelp() {
|
|
9
9
|
console.log(`Lotics CLI v${VERSION} — AI agent interface for Lotics
|
|
@@ -14,8 +14,22 @@ Lotics is an AI-powered operations platform. Through this CLI you can:
|
|
|
14
14
|
- Build and run automations (event-driven workflows)
|
|
15
15
|
- Create and manage apps, knowledge docs, and files
|
|
16
16
|
|
|
17
|
+
AUTHENTICATION
|
|
18
|
+
lotics signup Create account, org, workspace, and API key
|
|
19
|
+
lotics auth [api_key] Save an existing API key (e.g. from the web app)
|
|
20
|
+
lotics whoami Show the email of the current account
|
|
21
|
+
lotics logout Remove saved credentials
|
|
22
|
+
|
|
23
|
+
Signup flags:
|
|
24
|
+
--email <email> Email (required; prompted if omitted)
|
|
25
|
+
--name <name> Display name (defaults to email prefix)
|
|
26
|
+
|
|
27
|
+
Signup prints email and auto-generated password for web app login.
|
|
28
|
+
Use lotics whoami to check the current account email.
|
|
29
|
+
Auth priority: --api-key flag > LOTICS_API_KEY env > saved config.
|
|
30
|
+
|
|
17
31
|
USAGE
|
|
18
|
-
1. lotics
|
|
32
|
+
1. lotics signup Create account and get API key
|
|
19
33
|
2. lotics tools List available tools by category
|
|
20
34
|
3. lotics tools <name> Show tool description and full input schema
|
|
21
35
|
4. lotics run <tool> '<json>' Execute a tool with JSON arguments
|
|
@@ -25,8 +39,6 @@ USAGE
|
|
|
25
39
|
Query tools return IDs used as arguments to other tools.
|
|
26
40
|
|
|
27
41
|
COMMANDS
|
|
28
|
-
lotics auth [api_key] Save API key (interactive prompt if omitted)
|
|
29
|
-
lotics logout Remove saved credentials
|
|
30
42
|
lotics tools List all available tools
|
|
31
43
|
lotics tools <name> Show tool description and input schema
|
|
32
44
|
lotics run <tool> '<json>' Execute a tool
|
|
@@ -41,9 +53,6 @@ FLAGS
|
|
|
41
53
|
--api-key <key> API key (overrides saved config and LOTICS_API_KEY)
|
|
42
54
|
--version Show version
|
|
43
55
|
|
|
44
|
-
For non-interactive use, set LOTICS_API_KEY in the environment
|
|
45
|
-
instead of running lotics auth.
|
|
46
|
-
|
|
47
56
|
OUTPUT
|
|
48
57
|
Default output is a human-readable text summary. Use --json to get
|
|
49
58
|
structured JSON for programmatic use. Errors print to stderr and
|
|
@@ -73,6 +82,8 @@ function parseArgs(argv) {
|
|
|
73
82
|
output: undefined,
|
|
74
83
|
as: undefined,
|
|
75
84
|
apiKey: undefined,
|
|
85
|
+
email: undefined,
|
|
86
|
+
name: undefined,
|
|
76
87
|
version: false,
|
|
77
88
|
help: false,
|
|
78
89
|
};
|
|
@@ -100,6 +111,12 @@ function parseArgs(argv) {
|
|
|
100
111
|
case "--api-key":
|
|
101
112
|
flags.apiKey = argv[++i];
|
|
102
113
|
break;
|
|
114
|
+
case "--email":
|
|
115
|
+
flags.email = argv[++i];
|
|
116
|
+
break;
|
|
117
|
+
case "--name":
|
|
118
|
+
flags.name = argv[++i];
|
|
119
|
+
break;
|
|
103
120
|
case "--version":
|
|
104
121
|
case "-v":
|
|
105
122
|
flags.version = true;
|
|
@@ -147,6 +164,46 @@ function prompt(question) {
|
|
|
147
164
|
});
|
|
148
165
|
});
|
|
149
166
|
}
|
|
167
|
+
async function publicPost(path, body) {
|
|
168
|
+
const response = await fetch(`${API_BASE_URL}${path}`, {
|
|
169
|
+
method: "POST",
|
|
170
|
+
headers: { "Content-Type": "application/json" },
|
|
171
|
+
body: JSON.stringify(body),
|
|
172
|
+
});
|
|
173
|
+
const data = await response.json();
|
|
174
|
+
return { ok: response.ok, status: response.status, data };
|
|
175
|
+
}
|
|
176
|
+
async function handleSignup(flags) {
|
|
177
|
+
const email = flags.email ?? (process.stdin.isTTY ? await prompt("Email: ") : "");
|
|
178
|
+
if (!email) {
|
|
179
|
+
console.error("Email is required. Use --email or run interactively.");
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
const name = flags.name ?? (process.stdin.isTTY ? await prompt("Name (enter to use email): ") : undefined);
|
|
183
|
+
const body = { email };
|
|
184
|
+
if (name)
|
|
185
|
+
body.name = name;
|
|
186
|
+
const { ok, status, data } = await publicPost("/v1/cli/signup", body);
|
|
187
|
+
if (!ok) {
|
|
188
|
+
if (status === 409) {
|
|
189
|
+
console.error("An account with this email already exists. Use: lotics auth");
|
|
190
|
+
}
|
|
191
|
+
else if (status === 429) {
|
|
192
|
+
console.error("Too many signup attempts. Try again later.");
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
console.error(`Signup failed: ${data.message ?? JSON.stringify(data)}`);
|
|
196
|
+
}
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
const existing = loadConfig() ?? {};
|
|
200
|
+
saveConfig({ ...existing, api_key: data.api_key, email: data.email });
|
|
201
|
+
console.error(`Account created. You can now use the CLI.`);
|
|
202
|
+
console.error(` Email: ${data.email}`);
|
|
203
|
+
console.error(` Password: ${data.password}`);
|
|
204
|
+
console.error(`\nUse these credentials to log into the Lotics web app.`);
|
|
205
|
+
console.error(`Run "lotics whoami" to check the current account email.`);
|
|
206
|
+
}
|
|
150
207
|
async function handleAuth(providedKey) {
|
|
151
208
|
const apiKey = providedKey ?? await prompt("Enter your API key: ");
|
|
152
209
|
if (!apiKey) {
|
|
@@ -164,7 +221,7 @@ async function handleAuth(providedKey) {
|
|
|
164
221
|
}
|
|
165
222
|
const existing = loadConfig() ?? {};
|
|
166
223
|
saveConfig({ ...existing, api_key: apiKey });
|
|
167
|
-
console.error(
|
|
224
|
+
console.error("Authenticated.");
|
|
168
225
|
}
|
|
169
226
|
function requireClient(flags) {
|
|
170
227
|
const auth = resolveAuth(flags);
|
|
@@ -207,10 +264,25 @@ async function main() {
|
|
|
207
264
|
return;
|
|
208
265
|
}
|
|
209
266
|
// --- Commands that don't require auth ---
|
|
267
|
+
if (command === "signup") {
|
|
268
|
+
await handleSignup(flags);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
210
271
|
if (command === "auth") {
|
|
211
272
|
await handleAuth(subcommand ?? flags.apiKey);
|
|
212
273
|
return;
|
|
213
274
|
}
|
|
275
|
+
if (command === "whoami") {
|
|
276
|
+
const config = loadConfig();
|
|
277
|
+
if (config?.email) {
|
|
278
|
+
console.log(config.email);
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
console.error("Not signed up. Run: lotics signup");
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
214
286
|
if (command === "logout") {
|
|
215
287
|
deleteConfig();
|
|
216
288
|
console.error("Logged out. Credentials removed.");
|
|
@@ -287,8 +359,9 @@ async function main() {
|
|
|
287
359
|
console.log(JSON.stringify({ files: upload.files, errors: upload.errors }, null, 2));
|
|
288
360
|
}
|
|
289
361
|
else {
|
|
290
|
-
for (
|
|
291
|
-
|
|
362
|
+
for (let i = 0; i < upload.files.length; i++) {
|
|
363
|
+
const file = upload.files[i];
|
|
364
|
+
console.log(`[${i + 1}] ${file.id} ${file.filename} ${file.mime_type}`);
|
|
292
365
|
}
|
|
293
366
|
for (const error of upload.errors) {
|
|
294
367
|
console.error(`FAILED ${error.filename} ${error.error}`);
|
package/dist/src/client.d.ts
CHANGED
package/dist/src/client.js
CHANGED
|
@@ -21,12 +21,13 @@ function getMimeType(filename) {
|
|
|
21
21
|
const ext = path.extname(filename).toLowerCase();
|
|
22
22
|
return MIME_MAP[ext] ?? "application/octet-stream";
|
|
23
23
|
}
|
|
24
|
+
export const API_BASE_URL = process.env.LOTICS_API_URL ?? "https://api.lotics.ai";
|
|
24
25
|
export class LoticsClient {
|
|
25
26
|
apiKey;
|
|
26
27
|
baseUrl;
|
|
27
28
|
constructor(options) {
|
|
28
29
|
this.apiKey = options.apiKey;
|
|
29
|
-
this.baseUrl =
|
|
30
|
+
this.baseUrl = API_BASE_URL;
|
|
30
31
|
}
|
|
31
32
|
async throwResponseError(response) {
|
|
32
33
|
const text = await response.text();
|
package/dist/src/config.d.ts
CHANGED