@lotics/cli 0.4.0 → 0.6.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 CHANGED
@@ -32,11 +32,11 @@ lotics signup # interactive prompts
32
32
  lotics signup --email a@b.com --name "Agent" # non-interactive
33
33
  ```
34
34
 
35
- **`lotics auth`** — Saves an existing API key directly (e.g. one created in the Lotics web app).
35
+ **`lotics setup`** — Saves an existing API key directly (e.g. one created in the Lotics web app).
36
36
 
37
37
  ```bash
38
- lotics auth # interactive prompt
39
- lotics auth ltk_... # non-interactive
38
+ lotics setup # interactive prompt
39
+ lotics setup ltk_... # non-interactive
40
40
  ```
41
41
 
42
42
  API key is saved to `~/.lotics/config.json`. Run `lotics logout` to remove saved credentials.
package/dist/src/cli.js CHANGED
@@ -16,20 +16,21 @@ Lotics is an AI-powered operations platform. Through this CLI you can:
16
16
 
17
17
  AUTHENTICATION
18
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)
19
+ lotics setup [api_key] Save an existing API key (e.g. from the web app)
20
20
  lotics whoami Show the email of the current account
21
21
  lotics logout Remove saved credentials
22
22
 
23
23
  Signup flags:
24
- --email <email> Email (required; prompted if omitted)
25
- --name <name> Display name (defaults to email prefix)
24
+ --email <email> Email (required; prompted if omitted)
25
+ --name <name> Display name (defaults to email prefix)
26
+ --timezone <timezone> Workspace timezone (defaults to UTC, e.g. Asia/Ho_Chi_Minh)
26
27
 
27
28
  Signup prints email and auto-generated password for web app login.
28
29
  Use lotics whoami to check the current account email.
29
- Auth priority: --api-key flag > LOTICS_API_KEY env > saved config.
30
+ Setup priority: --api-key flag > LOTICS_API_KEY env > saved config.
30
31
 
31
32
  USAGE
32
- 1. lotics signup Create account and get API key
33
+ 1. lotics signup (or lotics setup) Create account or set up API key
33
34
  2. lotics tools List available tools by category
34
35
  3. lotics tools <name> Show tool description and full input schema
35
36
  4. lotics run <tool> '<json>' Execute a tool with JSON arguments
@@ -84,6 +85,7 @@ function parseArgs(argv) {
84
85
  apiKey: undefined,
85
86
  email: undefined,
86
87
  name: undefined,
88
+ timezone: undefined,
87
89
  version: false,
88
90
  help: false,
89
91
  };
@@ -117,6 +119,9 @@ function parseArgs(argv) {
117
119
  case "--name":
118
120
  flags.name = argv[++i];
119
121
  break;
122
+ case "--timezone":
123
+ flags.timezone = argv[++i];
124
+ break;
120
125
  case "--version":
121
126
  case "-v":
122
127
  flags.version = true;
@@ -183,10 +188,12 @@ async function handleSignup(flags) {
183
188
  const body = { email };
184
189
  if (name)
185
190
  body.name = name;
191
+ if (flags.timezone)
192
+ body.timezone = flags.timezone;
186
193
  const { ok, status, data } = await publicPost("/v1/cli/signup", body);
187
194
  if (!ok) {
188
195
  if (status === 409) {
189
- console.error("An account with this email already exists. Use: lotics auth");
196
+ console.error("An account with this email already exists. Use: lotics setup");
190
197
  }
191
198
  else if (status === 429) {
192
199
  console.error("Too many signup attempts. Try again later.");
@@ -204,15 +211,17 @@ async function handleSignup(flags) {
204
211
  console.error(`\nUse these credentials to log into the Lotics web app.`);
205
212
  console.error(`Run "lotics whoami" to check the current account email.`);
206
213
  }
207
- async function handleAuth(providedKey) {
214
+ async function handleSetup(providedKey) {
208
215
  const apiKey = providedKey ?? await prompt("Enter your API key: ");
209
216
  if (!apiKey) {
210
217
  console.error("No API key provided.");
211
218
  process.exit(1);
212
219
  }
213
220
  const client = new LoticsClient({ apiKey });
221
+ let email;
214
222
  try {
215
- await client.listTools();
223
+ const info = await client.whoami();
224
+ email = info.email;
216
225
  }
217
226
  catch (error) {
218
227
  const message = error instanceof Error ? error.message : String(error);
@@ -220,13 +229,13 @@ async function handleAuth(providedKey) {
220
229
  process.exit(1);
221
230
  }
222
231
  const existing = loadConfig() ?? {};
223
- saveConfig({ ...existing, api_key: apiKey });
232
+ saveConfig({ ...existing, api_key: apiKey, email });
224
233
  console.error("Authenticated.");
225
234
  }
226
235
  function requireClient(flags) {
227
236
  const auth = resolveAuth(flags);
228
237
  if (!auth) {
229
- console.error('Not authenticated. Run "lotics auth" or set LOTICS_API_KEY.');
238
+ console.error('Not authenticated. Run "lotics setup" or set LOTICS_API_KEY.');
230
239
  process.exit(1);
231
240
  }
232
241
  return new LoticsClient({ apiKey: auth.apiKey });
@@ -268,17 +277,33 @@ async function main() {
268
277
  await handleSignup(flags);
269
278
  return;
270
279
  }
271
- if (command === "auth") {
272
- await handleAuth(subcommand ?? flags.apiKey);
280
+ if (command === "setup") {
281
+ await handleSetup(subcommand ?? flags.apiKey);
273
282
  return;
274
283
  }
275
284
  if (command === "whoami") {
276
285
  const config = loadConfig();
277
286
  if (config?.email) {
278
287
  console.log(config.email);
288
+ return;
279
289
  }
280
- else {
281
- console.error("Not signed up. Run: lotics signup");
290
+ // No email cached — try fetching from API
291
+ const auth = resolveAuth(flags);
292
+ if (!auth) {
293
+ console.error('Not authenticated. Run "lotics setup" or set LOTICS_API_KEY.');
294
+ process.exit(1);
295
+ }
296
+ const client = new LoticsClient({ apiKey: auth.apiKey });
297
+ try {
298
+ const info = await client.whoami();
299
+ // Cache for next time
300
+ const existing = loadConfig() ?? {};
301
+ saveConfig({ ...existing, email: info.email });
302
+ console.log(info.email);
303
+ }
304
+ catch (error) {
305
+ const message = error instanceof Error ? error.message : String(error);
306
+ console.error(`Failed to fetch account info: ${message}`);
282
307
  process.exit(1);
283
308
  }
284
309
  return;
@@ -359,8 +384,9 @@ async function main() {
359
384
  console.log(JSON.stringify({ files: upload.files, errors: upload.errors }, null, 2));
360
385
  }
361
386
  else {
362
- for (const file of upload.files) {
363
- console.log(`${file.id} ${file.filename} ${file.mime_type}`);
387
+ for (let i = 0; i < upload.files.length; i++) {
388
+ const file = upload.files[i];
389
+ console.log(`[${i + 1}] ${file.id} ${file.filename} ${file.mime_type}`);
364
390
  }
365
391
  for (const error of upload.errors) {
366
392
  console.error(`FAILED ${error.filename} ${error.error}`);
@@ -29,6 +29,11 @@ export declare class LoticsClient {
29
29
  constructor(options: LoticsClientOptions);
30
30
  private throwResponseError;
31
31
  private request;
32
+ whoami(): Promise<{
33
+ email: string;
34
+ name: string;
35
+ organization_id: string;
36
+ }>;
32
37
  listTools(): Promise<{
33
38
  tools: string[];
34
39
  categories: Record<string, {
@@ -56,6 +56,9 @@ export class LoticsClient {
56
56
  await this.throwResponseError(response);
57
57
  return response.json();
58
58
  }
59
+ async whoami() {
60
+ return this.request("GET", "/v1/cli/whoami");
61
+ }
59
62
  async listTools() {
60
63
  return this.request("GET", "/v1/tools");
61
64
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/cli",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Lotics SDK and CLI for AI agents",
5
5
  "type": "module",
6
6
  "bin": {