openhome-cli 0.1.4 → 0.1.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.
package/dist/cli.js CHANGED
@@ -276,6 +276,7 @@ function handleCancel(value) {
276
276
  // src/commands/login.ts
277
277
  import chalk2 from "chalk";
278
278
  var SETTINGS_URL = "https://app.openhome.com/dashboard/settings";
279
+ var OPENHOME_APP_URL = "https://app.openhome.com";
279
280
  function openBrowser(url) {
280
281
  try {
281
282
  if (process.platform === "darwin") {
@@ -290,14 +291,14 @@ function openBrowser(url) {
290
291
  }
291
292
  async function loginCommand() {
292
293
  p.intro("\u{1F511} OpenHome Login");
293
- const open = await p.confirm({
294
+ const openSettings = await p.confirm({
294
295
  message: `Press Enter to open your browser and navigate to the ${chalk2.bold("API Keys")} tab`,
295
296
  initialValue: true,
296
297
  active: "Open browser",
297
298
  inactive: "Skip"
298
299
  });
299
- handleCancel(open);
300
- if (open) {
300
+ handleCancel(openSettings);
301
+ if (openSettings) {
301
302
  openBrowser(SETTINGS_URL);
302
303
  console.log(
303
304
  `
@@ -317,17 +318,13 @@ async function loginCommand() {
317
318
  let agents;
318
319
  try {
319
320
  const client = new ApiClient(apiKey);
320
- const verification = await client.verifyApiKey(apiKey);
321
- if (!verification.valid) {
322
- s.stop("Verification failed.");
323
- error(verification.message ?? "Invalid API key.");
324
- process.exit(1);
325
- }
326
321
  agents = await client.getPersonalities();
327
322
  s.stop("API key verified.");
328
323
  } catch (err) {
329
324
  s.stop("Verification failed.");
330
- error(err instanceof Error ? err.message : String(err));
325
+ error(
326
+ err instanceof Error && err.message.includes("401") ? "Invalid API key \u2014 check the value and try again." : err instanceof Error ? err.message : String(err)
327
+ );
331
328
  process.exit(1);
332
329
  }
333
330
  saveApiKey(apiKey);
@@ -340,7 +337,79 @@ async function loginCommand() {
340
337
  } else {
341
338
  info("No agents found. Create one at https://app.openhome.com");
342
339
  }
343
- p.outro("Logged in! You're ready to go.");
340
+ console.log("");
341
+ p.note(
342
+ [
343
+ "To manage your abilities (list, delete, enable/disable) from the CLI,",
344
+ "you need one more thing: a session token.",
345
+ "",
346
+ `This takes about ${chalk2.bold("30 seconds")} and you only do it once.`
347
+ ].join("\n"),
348
+ "One more step"
349
+ );
350
+ const doJwt = await p.confirm({
351
+ message: "Set up management access now?",
352
+ initialValue: true,
353
+ active: "Yes, do it now",
354
+ inactive: "Skip for now"
355
+ });
356
+ handleCancel(doJwt);
357
+ if (doJwt) {
358
+ await setupJwt();
359
+ } else {
360
+ p.outro(
361
+ `All set! Run ${chalk2.bold("openhome set-jwt")} anytime to enable management features.`
362
+ );
363
+ return;
364
+ }
365
+ p.outro("You're fully set up. Run openhome to get started.");
366
+ }
367
+ async function setupJwt() {
368
+ const { saveJwt: saveJwt2 } = await import("./store-USDMWKXY.js");
369
+ const openApp = await p.confirm({
370
+ message: `Press Enter to open ${chalk2.bold("app.openhome.com")} in your browser`,
371
+ initialValue: true,
372
+ active: "Open browser",
373
+ inactive: "Skip"
374
+ });
375
+ handleCancel(openApp);
376
+ if (openApp) {
377
+ openBrowser(OPENHOME_APP_URL);
378
+ console.log(
379
+ `
380
+ ${chalk2.dim(`Opened ${chalk2.bold("app.openhome.com")} \u2014 make sure you're logged in`)}
381
+ `
382
+ );
383
+ }
384
+ p.note(
385
+ [
386
+ `${chalk2.bold("1.")} Open the browser console:`,
387
+ ` Mac \u2192 press ${chalk2.cyan("Cmd + Option + J")}`,
388
+ ` Windows / Linux \u2192 press ${chalk2.cyan("F12")}, then click ${chalk2.cyan("Console")}`,
389
+ "",
390
+ `${chalk2.bold("2.")} Paste this command and press ${chalk2.bold("Enter")}:`,
391
+ "",
392
+ ` ${chalk2.green("copy(localStorage.getItem('token'))")}`,
393
+ "",
394
+ `${chalk2.bold("3.")} Your token is now copied to your clipboard.`,
395
+ ` Come back here and paste it below.`
396
+ ].join("\n"),
397
+ "How to get your session token"
398
+ );
399
+ const token = await p.password({
400
+ message: "Paste your session token here",
401
+ validate: (val) => {
402
+ if (!val || !val.trim()) return "Token is required";
403
+ if (val.trim().length < 20)
404
+ return "That doesn't look right \u2014 the token should be much longer";
405
+ }
406
+ });
407
+ if (typeof token === "symbol") {
408
+ p.cancel("Skipped.");
409
+ return;
410
+ }
411
+ saveJwt2(token.trim());
412
+ success("Session token saved. Management features are now unlocked.");
344
413
  }
345
414
 
346
415
  // src/commands/init.ts
@@ -3075,21 +3144,6 @@ async function logsCommand(opts = {}) {
3075
3144
  }
3076
3145
 
3077
3146
  // src/commands/set-jwt.ts
3078
- import { execFile as execFile2 } from "child_process";
3079
- import chalk13 from "chalk";
3080
- var OPENHOME_URL = "https://app.openhome.com";
3081
- function openBrowser2(url) {
3082
- try {
3083
- if (process.platform === "darwin") {
3084
- execFile2("open", [url]);
3085
- } else if (process.platform === "win32") {
3086
- execFile2("cmd", ["/c", "start", url]);
3087
- } else {
3088
- execFile2("xdg-open", [url]);
3089
- }
3090
- } catch {
3091
- }
3092
- }
3093
3147
  async function setJwtCommand(token) {
3094
3148
  if (token) {
3095
3149
  p.intro("\u{1F511} Enable Management Features");
@@ -3108,76 +3162,13 @@ async function setJwtCommand(token) {
3108
3162
  return;
3109
3163
  }
3110
3164
  p.intro("\u{1F511} Enable Management Features");
3111
- p.note(
3112
- [
3113
- "Some commands (list, delete, enable/disable abilities) need your",
3114
- "OpenHome session token to work.",
3115
- "",
3116
- "Think of it as a temporary key that proves you're logged in to",
3117
- "your account. You only need to do this once."
3118
- ].join("\n"),
3119
- "What's this?"
3120
- );
3121
- console.log("");
3122
- console.log(
3123
- chalk13.dim(` Opening ${chalk13.bold("app.openhome.com")} in your browser...`)
3124
- );
3125
- openBrowser2(OPENHOME_URL);
3126
- console.log("");
3127
- p.note(
3128
- [
3129
- `${chalk13.bold("Step 1")} Make sure you're logged in to app.openhome.com`,
3130
- "",
3131
- `${chalk13.bold("Step 2")} Open the browser console:`,
3132
- ` Mac \u2192 ${chalk13.cyan("Cmd + Option + J")}`,
3133
- ` Windows / Linux \u2192 ${chalk13.cyan("F12")}, then click the Console tab`,
3134
- "",
3135
- `${chalk13.bold("Step 3")} Paste this command into the console and press Enter:`,
3136
- "",
3137
- ` ${chalk13.green("copy(localStorage.getItem('token'))")}`,
3138
- "",
3139
- `${chalk13.bold("Step 4")} Your token is now in your clipboard.`,
3140
- ` Come back here and paste it below.`
3141
- ].join("\n"),
3142
- "How to get your token"
3143
- );
3144
- const input = await p.password({
3145
- message: "Paste your token here",
3146
- validate: (val) => {
3147
- if (!val || !val.trim()) return "Token is required";
3148
- if (val.trim().length < 20)
3149
- return "That doesn't look right \u2014 the token should be much longer";
3150
- }
3151
- });
3152
- if (typeof input === "symbol") {
3153
- p.cancel("Cancelled.");
3154
- return;
3155
- }
3156
- try {
3157
- saveJwt(input.trim());
3158
- success("Session token saved.");
3159
- p.note(
3160
- [
3161
- "These commands are now unlocked:",
3162
- ` ${chalk13.bold("openhome list")} \u2014 see all your deployed abilities`,
3163
- ` ${chalk13.bold("openhome delete")} \u2014 remove an ability`,
3164
- ` ${chalk13.bold("openhome toggle")} \u2014 enable or disable an ability`,
3165
- ` ${chalk13.bold("openhome assign")} \u2014 link abilities to an agent`
3166
- ].join("\n"),
3167
- "You're all set"
3168
- );
3169
- p.outro("Done!");
3170
- } catch (err) {
3171
- error(
3172
- `Failed to save token: ${err instanceof Error ? err.message : String(err)}`
3173
- );
3174
- process.exit(1);
3175
- }
3165
+ await setupJwt();
3166
+ p.outro("Done.");
3176
3167
  }
3177
3168
 
3178
3169
  // src/commands/validate.ts
3179
3170
  import { resolve as resolve5 } from "path";
3180
- import chalk14 from "chalk";
3171
+ import chalk13 from "chalk";
3181
3172
  async function validateCommand(pathArg = ".") {
3182
3173
  const targetDir = resolve5(pathArg);
3183
3174
  p.intro(`\u{1F50E} Validate ability`);
@@ -3193,7 +3184,7 @@ async function validateCommand(pathArg = ".") {
3193
3184
  if (result.errors.length > 0) {
3194
3185
  p.note(
3195
3186
  result.errors.map(
3196
- (issue) => `${chalk14.red("\u2717")} ${issue.file ? chalk14.bold(`[${issue.file}]`) + " " : ""}${issue.message}`
3187
+ (issue) => `${chalk13.red("\u2717")} ${issue.file ? chalk13.bold(`[${issue.file}]`) + " " : ""}${issue.message}`
3197
3188
  ).join("\n"),
3198
3189
  `${result.errors.length} Error(s)`
3199
3190
  );
@@ -3201,7 +3192,7 @@ async function validateCommand(pathArg = ".") {
3201
3192
  if (result.warnings.length > 0) {
3202
3193
  p.note(
3203
3194
  result.warnings.map(
3204
- (w) => `${chalk14.yellow("\u26A0")} ${w.file ? chalk14.bold(`[${w.file}]`) + " " : ""}${w.message}`
3195
+ (w) => `${chalk13.yellow("\u26A0")} ${w.file ? chalk13.bold(`[${w.file}]`) + " " : ""}${w.message}`
3205
3196
  ).join("\n"),
3206
3197
  `${result.warnings.length} Warning(s)`
3207
3198
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openhome-cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "CLI for managing OpenHome voice AI abilities",
5
5
  "type": "module",
6
6
  "bin": {
@@ -6,8 +6,9 @@ import { success, error, info, p, handleCancel } from "../ui/format.js";
6
6
  import chalk from "chalk";
7
7
 
8
8
  const SETTINGS_URL = "https://app.openhome.com/dashboard/settings";
9
+ const OPENHOME_APP_URL = "https://app.openhome.com";
9
10
 
10
- function openBrowser(url: string): void {
11
+ export function openBrowser(url: string): void {
11
12
  try {
12
13
  if (process.platform === "darwin") {
13
14
  execFile("open", [url]);
@@ -24,15 +25,16 @@ function openBrowser(url: string): void {
24
25
  export async function loginCommand(): Promise<void> {
25
26
  p.intro("🔑 OpenHome Login");
26
27
 
27
- const open = await p.confirm({
28
+ // Step 1: API key
29
+ const openSettings = await p.confirm({
28
30
  message: `Press Enter to open your browser and navigate to the ${chalk.bold("API Keys")} tab`,
29
31
  initialValue: true,
30
32
  active: "Open browser",
31
33
  inactive: "Skip",
32
34
  });
33
- handleCancel(open);
35
+ handleCancel(openSettings);
34
36
 
35
- if (open) {
37
+ if (openSettings) {
36
38
  openBrowser(SETTINGS_URL);
37
39
  console.log(
38
40
  `\n ${chalk.dim(`Opened ${chalk.bold("app.openhome.com/dashboard/settings")} — click the ${chalk.bold("API Keys")} tab`)}\n`,
@@ -53,17 +55,17 @@ export async function loginCommand(): Promise<void> {
53
55
  let agents: Personality[];
54
56
  try {
55
57
  const client = new ApiClient(apiKey as string);
56
- const verification = await client.verifyApiKey(apiKey as string);
57
- if (!verification.valid) {
58
- s.stop("Verification failed.");
59
- error(verification.message ?? "Invalid API key.");
60
- process.exit(1);
61
- }
62
58
  agents = await client.getPersonalities();
63
59
  s.stop("API key verified.");
64
60
  } catch (err) {
65
61
  s.stop("Verification failed.");
66
- error(err instanceof Error ? err.message : String(err));
62
+ error(
63
+ err instanceof Error && err.message.includes("401")
64
+ ? "Invalid API key — check the value and try again."
65
+ : err instanceof Error
66
+ ? err.message
67
+ : String(err),
68
+ );
67
69
  process.exit(1);
68
70
  }
69
71
 
@@ -81,5 +83,86 @@ export async function loginCommand(): Promise<void> {
81
83
  info("No agents found. Create one at https://app.openhome.com");
82
84
  }
83
85
 
84
- p.outro("Logged in! You're ready to go.");
86
+ // Step 2: Session token for management features
87
+ console.log("");
88
+ p.note(
89
+ [
90
+ "To manage your abilities (list, delete, enable/disable) from the CLI,",
91
+ "you need one more thing: a session token.",
92
+ "",
93
+ `This takes about ${chalk.bold("30 seconds")} and you only do it once.`,
94
+ ].join("\n"),
95
+ "One more step",
96
+ );
97
+
98
+ const doJwt = await p.confirm({
99
+ message: "Set up management access now?",
100
+ initialValue: true,
101
+ active: "Yes, do it now",
102
+ inactive: "Skip for now",
103
+ });
104
+ handleCancel(doJwt);
105
+
106
+ if (doJwt) {
107
+ await setupJwt();
108
+ } else {
109
+ p.outro(
110
+ `All set! Run ${chalk.bold("openhome set-jwt")} anytime to enable management features.`,
111
+ );
112
+ return;
113
+ }
114
+
115
+ p.outro("You're fully set up. Run openhome to get started.");
116
+ }
117
+
118
+ export async function setupJwt(): Promise<void> {
119
+ const { saveJwt } = await import("../config/store.js");
120
+
121
+ const openApp = await p.confirm({
122
+ message: `Press Enter to open ${chalk.bold("app.openhome.com")} in your browser`,
123
+ initialValue: true,
124
+ active: "Open browser",
125
+ inactive: "Skip",
126
+ });
127
+ handleCancel(openApp);
128
+
129
+ if (openApp) {
130
+ openBrowser(OPENHOME_APP_URL);
131
+ console.log(
132
+ `\n ${chalk.dim(`Opened ${chalk.bold("app.openhome.com")} — make sure you're logged in`)}\n`,
133
+ );
134
+ }
135
+
136
+ p.note(
137
+ [
138
+ `${chalk.bold("1.")} Open the browser console:`,
139
+ ` Mac → press ${chalk.cyan("Cmd + Option + J")}`,
140
+ ` Windows / Linux → press ${chalk.cyan("F12")}, then click ${chalk.cyan("Console")}`,
141
+ "",
142
+ `${chalk.bold("2.")} Paste this command and press ${chalk.bold("Enter")}:`,
143
+ "",
144
+ ` ${chalk.green("copy(localStorage.getItem('token'))")}`,
145
+ "",
146
+ `${chalk.bold("3.")} Your token is now copied to your clipboard.`,
147
+ ` Come back here and paste it below.`,
148
+ ].join("\n"),
149
+ "How to get your session token",
150
+ );
151
+
152
+ const token = await p.password({
153
+ message: "Paste your session token here",
154
+ validate: (val) => {
155
+ if (!val || !val.trim()) return "Token is required";
156
+ if (val.trim().length < 20)
157
+ return "That doesn't look right — the token should be much longer";
158
+ },
159
+ });
160
+
161
+ if (typeof token === "symbol") {
162
+ p.cancel("Skipped.");
163
+ return;
164
+ }
165
+
166
+ saveJwt((token as string).trim());
167
+ success("Session token saved. Management features are now unlocked.");
85
168
  }
@@ -1,23 +1,6 @@
1
- import { execFile } from "node:child_process";
1
+ import { setupJwt } from "./login.js";
2
2
  import { saveJwt } from "../config/store.js";
3
3
  import { success, error, p } from "../ui/format.js";
4
- import chalk from "chalk";
5
-
6
- const OPENHOME_URL = "https://app.openhome.com";
7
-
8
- function openBrowser(url: string): void {
9
- try {
10
- if (process.platform === "darwin") {
11
- execFile("open", [url]);
12
- } else if (process.platform === "win32") {
13
- execFile("cmd", ["/c", "start", url]);
14
- } else {
15
- execFile("xdg-open", [url]);
16
- }
17
- } catch {
18
- // best-effort — user can open manually
19
- }
20
- }
21
4
 
22
5
  export async function setJwtCommand(token?: string): Promise<void> {
23
6
  // Direct usage: openhome set-jwt eyJ...
@@ -38,77 +21,8 @@ export async function setJwtCommand(token?: string): Promise<void> {
38
21
  return;
39
22
  }
40
23
 
41
- // Guided interactive flow
24
+ // Guided flow — reuse the same walkthrough from login
42
25
  p.intro("🔑 Enable Management Features");
43
-
44
- p.note(
45
- [
46
- "Some commands (list, delete, enable/disable abilities) need your",
47
- "OpenHome session token to work.",
48
- "",
49
- "Think of it as a temporary key that proves you're logged in to",
50
- "your account. You only need to do this once.",
51
- ].join("\n"),
52
- "What's this?",
53
- );
54
-
55
- console.log("");
56
- console.log(
57
- chalk.dim(` Opening ${chalk.bold("app.openhome.com")} in your browser...`),
58
- );
59
- openBrowser(OPENHOME_URL);
60
- console.log("");
61
-
62
- p.note(
63
- [
64
- `${chalk.bold("Step 1")} Make sure you're logged in to app.openhome.com`,
65
- "",
66
- `${chalk.bold("Step 2")} Open the browser console:`,
67
- ` Mac → ${chalk.cyan("Cmd + Option + J")}`,
68
- ` Windows / Linux → ${chalk.cyan("F12")}, then click the Console tab`,
69
- "",
70
- `${chalk.bold("Step 3")} Paste this command into the console and press Enter:`,
71
- "",
72
- ` ${chalk.green("copy(localStorage.getItem('token'))")}`,
73
- "",
74
- `${chalk.bold("Step 4")} Your token is now in your clipboard.`,
75
- ` Come back here and paste it below.`,
76
- ].join("\n"),
77
- "How to get your token",
78
- );
79
-
80
- const input = await p.password({
81
- message: "Paste your token here",
82
- validate: (val) => {
83
- if (!val || !val.trim()) return "Token is required";
84
- if (val.trim().length < 20)
85
- return "That doesn't look right — the token should be much longer";
86
- },
87
- });
88
-
89
- if (typeof input === "symbol") {
90
- p.cancel("Cancelled.");
91
- return;
92
- }
93
-
94
- try {
95
- saveJwt((input as string).trim());
96
- success("Session token saved.");
97
- p.note(
98
- [
99
- "These commands are now unlocked:",
100
- ` ${chalk.bold("openhome list")} — see all your deployed abilities`,
101
- ` ${chalk.bold("openhome delete")} — remove an ability`,
102
- ` ${chalk.bold("openhome toggle")} — enable or disable an ability`,
103
- ` ${chalk.bold("openhome assign")} — link abilities to an agent`,
104
- ].join("\n"),
105
- "You're all set",
106
- );
107
- p.outro("Done!");
108
- } catch (err) {
109
- error(
110
- `Failed to save token: ${err instanceof Error ? err.message : String(err)}`,
111
- );
112
- process.exit(1);
113
- }
26
+ await setupJwt();
27
+ p.outro("Done.");
114
28
  }