openhome-cli 0.1.3 → 0.1.4
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 +105 -72
- package/package.json +1 -1
- package/src/cli.ts +13 -45
- package/src/commands/login.ts +34 -3
- package/src/commands/status.ts +6 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getApiKey,
|
|
3
3
|
getConfig,
|
|
4
|
-
getJwt
|
|
4
|
+
getJwt,
|
|
5
5
|
getTrackedAbilities,
|
|
6
6
|
keychainDelete,
|
|
7
7
|
registerAbility,
|
|
@@ -16,6 +16,9 @@ import { fileURLToPath } from "url";
|
|
|
16
16
|
import { dirname, join as join6 } from "path";
|
|
17
17
|
import { readFileSync as readFileSync5 } from "fs";
|
|
18
18
|
|
|
19
|
+
// src/commands/login.ts
|
|
20
|
+
import { execFile } from "child_process";
|
|
21
|
+
|
|
19
22
|
// src/api/endpoints.ts
|
|
20
23
|
var API_BASE = "https://app.openhome.com";
|
|
21
24
|
var WS_BASE = "wss://app.openhome.com";
|
|
@@ -272,10 +275,38 @@ function handleCancel(value) {
|
|
|
272
275
|
|
|
273
276
|
// src/commands/login.ts
|
|
274
277
|
import chalk2 from "chalk";
|
|
278
|
+
var SETTINGS_URL = "https://app.openhome.com/dashboard/settings";
|
|
279
|
+
function openBrowser(url) {
|
|
280
|
+
try {
|
|
281
|
+
if (process.platform === "darwin") {
|
|
282
|
+
execFile("open", [url]);
|
|
283
|
+
} else if (process.platform === "win32") {
|
|
284
|
+
execFile("cmd", ["/c", "start", url]);
|
|
285
|
+
} else {
|
|
286
|
+
execFile("xdg-open", [url]);
|
|
287
|
+
}
|
|
288
|
+
} catch {
|
|
289
|
+
}
|
|
290
|
+
}
|
|
275
291
|
async function loginCommand() {
|
|
276
292
|
p.intro("\u{1F511} OpenHome Login");
|
|
293
|
+
const open = await p.confirm({
|
|
294
|
+
message: `Press Enter to open your browser and navigate to the ${chalk2.bold("API Keys")} tab`,
|
|
295
|
+
initialValue: true,
|
|
296
|
+
active: "Open browser",
|
|
297
|
+
inactive: "Skip"
|
|
298
|
+
});
|
|
299
|
+
handleCancel(open);
|
|
300
|
+
if (open) {
|
|
301
|
+
openBrowser(SETTINGS_URL);
|
|
302
|
+
console.log(
|
|
303
|
+
`
|
|
304
|
+
${chalk2.dim(`Opened ${chalk2.bold("app.openhome.com/dashboard/settings")} \u2014 click the ${chalk2.bold("API Keys")} tab`)}
|
|
305
|
+
`
|
|
306
|
+
);
|
|
307
|
+
}
|
|
277
308
|
const apiKey = await p.password({
|
|
278
|
-
message: "
|
|
309
|
+
message: "Paste your API key here",
|
|
279
310
|
validate: (val) => {
|
|
280
311
|
if (!val || !val.trim()) return "API key is required";
|
|
281
312
|
}
|
|
@@ -548,7 +579,7 @@ import archiver from "archiver";
|
|
|
548
579
|
import { createWriteStream } from "fs";
|
|
549
580
|
import { Writable } from "stream";
|
|
550
581
|
async function createAbilityZip(dirPath) {
|
|
551
|
-
return new Promise((
|
|
582
|
+
return new Promise((resolve6, reject) => {
|
|
552
583
|
const chunks = [];
|
|
553
584
|
const writable = new Writable({
|
|
554
585
|
write(chunk, _encoding, callback) {
|
|
@@ -557,7 +588,7 @@ async function createAbilityZip(dirPath) {
|
|
|
557
588
|
}
|
|
558
589
|
});
|
|
559
590
|
writable.on("finish", () => {
|
|
560
|
-
|
|
591
|
+
resolve6(Buffer.concat(chunks));
|
|
561
592
|
});
|
|
562
593
|
writable.on("error", reject);
|
|
563
594
|
const archive = archiver("zip", { zlib: { level: 9 } });
|
|
@@ -1825,7 +1856,7 @@ async function deleteCommand(abilityArg, opts = {}) {
|
|
|
1825
1856
|
client = new MockApiClient();
|
|
1826
1857
|
} else {
|
|
1827
1858
|
const apiKey = getApiKey() ?? "";
|
|
1828
|
-
const jwt =
|
|
1859
|
+
const jwt = getJwt() ?? void 0;
|
|
1829
1860
|
if (!apiKey && !jwt) {
|
|
1830
1861
|
error("Not authenticated. Run: openhome login");
|
|
1831
1862
|
process.exit(1);
|
|
@@ -1914,7 +1945,7 @@ async function toggleCommand(abilityArg, opts = {}) {
|
|
|
1914
1945
|
client = new MockApiClient();
|
|
1915
1946
|
} else {
|
|
1916
1947
|
const apiKey = getApiKey() ?? "";
|
|
1917
|
-
const jwt =
|
|
1948
|
+
const jwt = getJwt() ?? void 0;
|
|
1918
1949
|
if (!apiKey && !jwt) {
|
|
1919
1950
|
error("Not authenticated. Run: openhome login");
|
|
1920
1951
|
process.exit(1);
|
|
@@ -2013,7 +2044,7 @@ async function assignCommand(opts = {}) {
|
|
|
2013
2044
|
client = new MockApiClient();
|
|
2014
2045
|
} else {
|
|
2015
2046
|
const apiKey = getApiKey() ?? "";
|
|
2016
|
-
const jwt =
|
|
2047
|
+
const jwt = getJwt() ?? void 0;
|
|
2017
2048
|
if (!apiKey && !jwt) {
|
|
2018
2049
|
error("Not authenticated. Run: openhome login");
|
|
2019
2050
|
process.exit(1);
|
|
@@ -2122,7 +2153,7 @@ async function listCommand(opts = {}) {
|
|
|
2122
2153
|
client = new MockApiClient();
|
|
2123
2154
|
} else {
|
|
2124
2155
|
const apiKey = getApiKey() ?? "";
|
|
2125
|
-
const jwt =
|
|
2156
|
+
const jwt = getJwt() ?? void 0;
|
|
2126
2157
|
if (!apiKey && !jwt) {
|
|
2127
2158
|
error("Not authenticated. Run: openhome login");
|
|
2128
2159
|
process.exit(1);
|
|
@@ -2422,7 +2453,7 @@ async function chatCommand(agentArg, opts = {}) {
|
|
|
2422
2453
|
}
|
|
2423
2454
|
const wsUrl = `${WS_BASE}${ENDPOINTS.voiceStream(apiKey, agentId)}`;
|
|
2424
2455
|
info(`Connecting to agent ${chalk9.bold(agentId)}...`);
|
|
2425
|
-
await new Promise((
|
|
2456
|
+
await new Promise((resolve6) => {
|
|
2426
2457
|
const ws = new WebSocket(wsUrl, {
|
|
2427
2458
|
perMessageDeflate: false,
|
|
2428
2459
|
headers: {
|
|
@@ -2550,7 +2581,7 @@ async function chatCommand(agentArg, opts = {}) {
|
|
|
2550
2581
|
console.error("");
|
|
2551
2582
|
error(`WebSocket error: ${err.message}`);
|
|
2552
2583
|
rl.close();
|
|
2553
|
-
|
|
2584
|
+
resolve6();
|
|
2554
2585
|
});
|
|
2555
2586
|
ws.on("close", (code) => {
|
|
2556
2587
|
if (pingInterval) clearInterval(pingInterval);
|
|
@@ -2561,7 +2592,7 @@ async function chatCommand(agentArg, opts = {}) {
|
|
|
2561
2592
|
info(`Connection closed (code: ${code})`);
|
|
2562
2593
|
}
|
|
2563
2594
|
rl.close();
|
|
2564
|
-
|
|
2595
|
+
resolve6();
|
|
2565
2596
|
});
|
|
2566
2597
|
rl.on("close", () => {
|
|
2567
2598
|
if (connected) {
|
|
@@ -2628,7 +2659,7 @@ async function triggerCommand(phraseArg, opts = {}) {
|
|
|
2628
2659
|
info(`Sending "${chalk10.bold(phrase)}" to agent ${chalk10.bold(agentId)}...`);
|
|
2629
2660
|
const s = p.spinner();
|
|
2630
2661
|
s.start("Waiting for response...");
|
|
2631
|
-
await new Promise((
|
|
2662
|
+
await new Promise((resolve6) => {
|
|
2632
2663
|
const ws = new WebSocket2(wsUrl, {
|
|
2633
2664
|
perMessageDeflate: false,
|
|
2634
2665
|
headers: {
|
|
@@ -2658,7 +2689,7 @@ async function triggerCommand(phraseArg, opts = {}) {
|
|
|
2658
2689
|
${chalk10.cyan("Agent:")} ${fullResponse}`);
|
|
2659
2690
|
}
|
|
2660
2691
|
cleanup();
|
|
2661
|
-
|
|
2692
|
+
resolve6();
|
|
2662
2693
|
}, RESPONSE_TIMEOUT);
|
|
2663
2694
|
});
|
|
2664
2695
|
ws.on("message", (raw) => {
|
|
@@ -2675,7 +2706,7 @@ ${chalk10.cyan("Agent:")} ${fullResponse}`);
|
|
|
2675
2706
|
${chalk10.cyan("Agent:")} ${fullResponse}
|
|
2676
2707
|
`);
|
|
2677
2708
|
cleanup();
|
|
2678
|
-
|
|
2709
|
+
resolve6();
|
|
2679
2710
|
}
|
|
2680
2711
|
}
|
|
2681
2712
|
break;
|
|
@@ -2692,7 +2723,7 @@ ${chalk10.cyan("Agent:")} ${fullResponse}
|
|
|
2692
2723
|
${chalk10.cyan("Agent:")} ${fullResponse}
|
|
2693
2724
|
`);
|
|
2694
2725
|
cleanup();
|
|
2695
|
-
|
|
2726
|
+
resolve6();
|
|
2696
2727
|
}
|
|
2697
2728
|
}
|
|
2698
2729
|
break;
|
|
@@ -2707,7 +2738,7 @@ ${chalk10.cyan("Agent:")} ${fullResponse}
|
|
|
2707
2738
|
`Server error: ${errData?.message || errData?.title || "Unknown"}`
|
|
2708
2739
|
);
|
|
2709
2740
|
cleanup();
|
|
2710
|
-
|
|
2741
|
+
resolve6();
|
|
2711
2742
|
break;
|
|
2712
2743
|
}
|
|
2713
2744
|
}
|
|
@@ -2717,12 +2748,12 @@ ${chalk10.cyan("Agent:")} ${fullResponse}
|
|
|
2717
2748
|
ws.on("error", (err) => {
|
|
2718
2749
|
s.stop("Connection error.");
|
|
2719
2750
|
error(err.message);
|
|
2720
|
-
|
|
2751
|
+
resolve6();
|
|
2721
2752
|
});
|
|
2722
2753
|
ws.on("close", () => {
|
|
2723
2754
|
if (pingInterval) clearInterval(pingInterval);
|
|
2724
2755
|
if (responseTimer) clearTimeout(responseTimer);
|
|
2725
|
-
|
|
2756
|
+
resolve6();
|
|
2726
2757
|
});
|
|
2727
2758
|
});
|
|
2728
2759
|
}
|
|
@@ -2947,7 +2978,7 @@ async function logsCommand(opts = {}) {
|
|
|
2947
2978
|
info(`Streaming logs from agent ${chalk12.bold(agentId)}...`);
|
|
2948
2979
|
info(`Press ${chalk12.bold("Ctrl+C")} to stop.
|
|
2949
2980
|
`);
|
|
2950
|
-
await new Promise((
|
|
2981
|
+
await new Promise((resolve6) => {
|
|
2951
2982
|
const ws = new WebSocket3(wsUrl, {
|
|
2952
2983
|
perMessageDeflate: false,
|
|
2953
2984
|
headers: {
|
|
@@ -3027,13 +3058,13 @@ async function logsCommand(opts = {}) {
|
|
|
3027
3058
|
});
|
|
3028
3059
|
ws.on("error", (err) => {
|
|
3029
3060
|
error(`WebSocket error: ${err.message}`);
|
|
3030
|
-
|
|
3061
|
+
resolve6();
|
|
3031
3062
|
});
|
|
3032
3063
|
ws.on("close", (code) => {
|
|
3033
3064
|
if (pingInterval) clearInterval(pingInterval);
|
|
3034
3065
|
console.log("");
|
|
3035
3066
|
info(`Connection closed (code: ${code})`);
|
|
3036
|
-
|
|
3067
|
+
resolve6();
|
|
3037
3068
|
});
|
|
3038
3069
|
process.on("SIGINT", () => {
|
|
3039
3070
|
console.log("");
|
|
@@ -3044,17 +3075,17 @@ async function logsCommand(opts = {}) {
|
|
|
3044
3075
|
}
|
|
3045
3076
|
|
|
3046
3077
|
// src/commands/set-jwt.ts
|
|
3047
|
-
import { execFile } from "child_process";
|
|
3078
|
+
import { execFile as execFile2 } from "child_process";
|
|
3048
3079
|
import chalk13 from "chalk";
|
|
3049
3080
|
var OPENHOME_URL = "https://app.openhome.com";
|
|
3050
|
-
function
|
|
3081
|
+
function openBrowser2(url) {
|
|
3051
3082
|
try {
|
|
3052
3083
|
if (process.platform === "darwin") {
|
|
3053
|
-
|
|
3084
|
+
execFile2("open", [url]);
|
|
3054
3085
|
} else if (process.platform === "win32") {
|
|
3055
|
-
|
|
3086
|
+
execFile2("cmd", ["/c", "start", url]);
|
|
3056
3087
|
} else {
|
|
3057
|
-
|
|
3088
|
+
execFile2("xdg-open", [url]);
|
|
3058
3089
|
}
|
|
3059
3090
|
} catch {
|
|
3060
3091
|
}
|
|
@@ -3091,7 +3122,7 @@ async function setJwtCommand(token) {
|
|
|
3091
3122
|
console.log(
|
|
3092
3123
|
chalk13.dim(` Opening ${chalk13.bold("app.openhome.com")} in your browser...`)
|
|
3093
3124
|
);
|
|
3094
|
-
|
|
3125
|
+
openBrowser2(OPENHOME_URL);
|
|
3095
3126
|
console.log("");
|
|
3096
3127
|
p.note(
|
|
3097
3128
|
[
|
|
@@ -3144,6 +3175,45 @@ async function setJwtCommand(token) {
|
|
|
3144
3175
|
}
|
|
3145
3176
|
}
|
|
3146
3177
|
|
|
3178
|
+
// src/commands/validate.ts
|
|
3179
|
+
import { resolve as resolve5 } from "path";
|
|
3180
|
+
import chalk14 from "chalk";
|
|
3181
|
+
async function validateCommand(pathArg = ".") {
|
|
3182
|
+
const targetDir = resolve5(pathArg);
|
|
3183
|
+
p.intro(`\u{1F50E} Validate ability`);
|
|
3184
|
+
const s = p.spinner();
|
|
3185
|
+
s.start("Running checks...");
|
|
3186
|
+
const result = validateAbility(targetDir);
|
|
3187
|
+
if (result.errors.length === 0 && result.warnings.length === 0) {
|
|
3188
|
+
s.stop("All checks passed.");
|
|
3189
|
+
p.outro("Ability is ready to deploy! \u{1F389}");
|
|
3190
|
+
return;
|
|
3191
|
+
}
|
|
3192
|
+
s.stop("Checks complete.");
|
|
3193
|
+
if (result.errors.length > 0) {
|
|
3194
|
+
p.note(
|
|
3195
|
+
result.errors.map(
|
|
3196
|
+
(issue) => `${chalk14.red("\u2717")} ${issue.file ? chalk14.bold(`[${issue.file}]`) + " " : ""}${issue.message}`
|
|
3197
|
+
).join("\n"),
|
|
3198
|
+
`${result.errors.length} Error(s)`
|
|
3199
|
+
);
|
|
3200
|
+
}
|
|
3201
|
+
if (result.warnings.length > 0) {
|
|
3202
|
+
p.note(
|
|
3203
|
+
result.warnings.map(
|
|
3204
|
+
(w) => `${chalk14.yellow("\u26A0")} ${w.file ? chalk14.bold(`[${w.file}]`) + " " : ""}${w.message}`
|
|
3205
|
+
).join("\n"),
|
|
3206
|
+
`${result.warnings.length} Warning(s)`
|
|
3207
|
+
);
|
|
3208
|
+
}
|
|
3209
|
+
if (result.passed) {
|
|
3210
|
+
p.outro("Validation passed (with warnings).");
|
|
3211
|
+
} else {
|
|
3212
|
+
error("Fix errors before deploying.");
|
|
3213
|
+
process.exit(1);
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
3216
|
+
|
|
3147
3217
|
// src/cli.ts
|
|
3148
3218
|
var __filename = fileURLToPath(import.meta.url);
|
|
3149
3219
|
var __dirname = dirname(__filename);
|
|
@@ -3176,16 +3246,6 @@ async function interactiveMenu() {
|
|
|
3176
3246
|
label: "\u2728 Create Ability",
|
|
3177
3247
|
hint: "Scaffold and deploy a new ability"
|
|
3178
3248
|
},
|
|
3179
|
-
{
|
|
3180
|
-
value: "chat",
|
|
3181
|
-
label: "\u{1F4AC} Chat",
|
|
3182
|
-
hint: "Talk to your agent"
|
|
3183
|
-
},
|
|
3184
|
-
{
|
|
3185
|
-
value: "trigger",
|
|
3186
|
-
label: "\u26A1 Trigger",
|
|
3187
|
-
hint: "Fire an ability remotely with a phrase"
|
|
3188
|
-
},
|
|
3189
3249
|
{
|
|
3190
3250
|
value: "list",
|
|
3191
3251
|
label: "\u{1F4CB} My Abilities",
|
|
@@ -3212,30 +3272,15 @@ async function interactiveMenu() {
|
|
|
3212
3272
|
hint: "View agents and set default"
|
|
3213
3273
|
},
|
|
3214
3274
|
{
|
|
3215
|
-
value: "
|
|
3216
|
-
label: "\u{
|
|
3217
|
-
hint: "
|
|
3218
|
-
},
|
|
3219
|
-
{
|
|
3220
|
-
value: "config",
|
|
3221
|
-
label: "\u2699\uFE0F Edit Config",
|
|
3222
|
-
hint: "Update trigger words, description, category"
|
|
3275
|
+
value: "chat",
|
|
3276
|
+
label: "\u{1F4AC} Chat",
|
|
3277
|
+
hint: "Talk to your agent"
|
|
3223
3278
|
},
|
|
3224
3279
|
{
|
|
3225
3280
|
value: "logs",
|
|
3226
3281
|
label: "\u{1F4E1} Logs",
|
|
3227
3282
|
hint: "Stream live agent messages"
|
|
3228
3283
|
},
|
|
3229
|
-
{
|
|
3230
|
-
value: "whoami",
|
|
3231
|
-
label: "\u{1F464} Who Am I",
|
|
3232
|
-
hint: "Show auth, default agent, tracked abilities"
|
|
3233
|
-
},
|
|
3234
|
-
{
|
|
3235
|
-
value: "set-jwt",
|
|
3236
|
-
label: "\u{1F511} Enable Management",
|
|
3237
|
-
hint: "Unlock list, delete, toggle, assign"
|
|
3238
|
-
},
|
|
3239
3284
|
{
|
|
3240
3285
|
value: "logout",
|
|
3241
3286
|
label: "\u{1F513} Log Out",
|
|
@@ -3249,12 +3294,6 @@ async function interactiveMenu() {
|
|
|
3249
3294
|
case "init":
|
|
3250
3295
|
await initCommand();
|
|
3251
3296
|
break;
|
|
3252
|
-
case "chat":
|
|
3253
|
-
await chatCommand();
|
|
3254
|
-
break;
|
|
3255
|
-
case "trigger":
|
|
3256
|
-
await triggerCommand();
|
|
3257
|
-
break;
|
|
3258
3297
|
case "list":
|
|
3259
3298
|
await listCommand();
|
|
3260
3299
|
break;
|
|
@@ -3270,21 +3309,12 @@ async function interactiveMenu() {
|
|
|
3270
3309
|
case "agents":
|
|
3271
3310
|
await agentsCommand();
|
|
3272
3311
|
break;
|
|
3273
|
-
case "
|
|
3274
|
-
await
|
|
3275
|
-
break;
|
|
3276
|
-
case "config":
|
|
3277
|
-
await configEditCommand();
|
|
3312
|
+
case "chat":
|
|
3313
|
+
await chatCommand();
|
|
3278
3314
|
break;
|
|
3279
3315
|
case "logs":
|
|
3280
3316
|
await logsCommand();
|
|
3281
3317
|
break;
|
|
3282
|
-
case "whoami":
|
|
3283
|
-
await whoamiCommand();
|
|
3284
|
-
break;
|
|
3285
|
-
case "set-jwt":
|
|
3286
|
-
await setJwtCommand();
|
|
3287
|
-
break;
|
|
3288
3318
|
case "logout":
|
|
3289
3319
|
await logoutCommand();
|
|
3290
3320
|
await ensureLoggedIn();
|
|
@@ -3350,6 +3380,9 @@ program.command("logs").description("Stream live agent messages and logs").optio
|
|
|
3350
3380
|
program.command("whoami").description("Show auth status, default agent, and tracked abilities").action(async () => {
|
|
3351
3381
|
await whoamiCommand();
|
|
3352
3382
|
});
|
|
3383
|
+
program.command("validate [path]").description("Check an ability for errors before deploying").action(async (path) => {
|
|
3384
|
+
await validateCommand(path);
|
|
3385
|
+
});
|
|
3353
3386
|
program.command("set-jwt [token]").description(
|
|
3354
3387
|
"Save a session token to enable management commands (list, delete, toggle, assign)"
|
|
3355
3388
|
).action(async (token) => {
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { whoamiCommand } from "./commands/whoami.js";
|
|
|
19
19
|
import { configEditCommand } from "./commands/config-edit.js";
|
|
20
20
|
import { logsCommand } from "./commands/logs.js";
|
|
21
21
|
import { setJwtCommand } from "./commands/set-jwt.js";
|
|
22
|
+
import { validateCommand } from "./commands/validate.js";
|
|
22
23
|
import { p, handleCancel } from "./ui/format.js";
|
|
23
24
|
|
|
24
25
|
// Read version from package.json
|
|
@@ -61,16 +62,6 @@ async function interactiveMenu(): Promise<void> {
|
|
|
61
62
|
label: "✨ Create Ability",
|
|
62
63
|
hint: "Scaffold and deploy a new ability",
|
|
63
64
|
},
|
|
64
|
-
{
|
|
65
|
-
value: "chat",
|
|
66
|
-
label: "💬 Chat",
|
|
67
|
-
hint: "Talk to your agent",
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
value: "trigger",
|
|
71
|
-
label: "⚡ Trigger",
|
|
72
|
-
hint: "Fire an ability remotely with a phrase",
|
|
73
|
-
},
|
|
74
65
|
{
|
|
75
66
|
value: "list",
|
|
76
67
|
label: "📋 My Abilities",
|
|
@@ -97,30 +88,15 @@ async function interactiveMenu(): Promise<void> {
|
|
|
97
88
|
hint: "View agents and set default",
|
|
98
89
|
},
|
|
99
90
|
{
|
|
100
|
-
value: "
|
|
101
|
-
label: "
|
|
102
|
-
hint: "
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
value: "config",
|
|
106
|
-
label: "⚙️ Edit Config",
|
|
107
|
-
hint: "Update trigger words, description, category",
|
|
91
|
+
value: "chat",
|
|
92
|
+
label: "💬 Chat",
|
|
93
|
+
hint: "Talk to your agent",
|
|
108
94
|
},
|
|
109
95
|
{
|
|
110
96
|
value: "logs",
|
|
111
97
|
label: "📡 Logs",
|
|
112
98
|
hint: "Stream live agent messages",
|
|
113
99
|
},
|
|
114
|
-
{
|
|
115
|
-
value: "whoami",
|
|
116
|
-
label: "👤 Who Am I",
|
|
117
|
-
hint: "Show auth, default agent, tracked abilities",
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
value: "set-jwt",
|
|
121
|
-
label: "🔑 Enable Management",
|
|
122
|
-
hint: "Unlock list, delete, toggle, assign",
|
|
123
|
-
},
|
|
124
100
|
{
|
|
125
101
|
value: "logout",
|
|
126
102
|
label: "🔓 Log Out",
|
|
@@ -135,12 +111,6 @@ async function interactiveMenu(): Promise<void> {
|
|
|
135
111
|
case "init":
|
|
136
112
|
await initCommand();
|
|
137
113
|
break;
|
|
138
|
-
case "chat":
|
|
139
|
-
await chatCommand();
|
|
140
|
-
break;
|
|
141
|
-
case "trigger":
|
|
142
|
-
await triggerCommand();
|
|
143
|
-
break;
|
|
144
114
|
case "list":
|
|
145
115
|
await listCommand();
|
|
146
116
|
break;
|
|
@@ -156,21 +126,12 @@ async function interactiveMenu(): Promise<void> {
|
|
|
156
126
|
case "agents":
|
|
157
127
|
await agentsCommand();
|
|
158
128
|
break;
|
|
159
|
-
case "
|
|
160
|
-
await
|
|
161
|
-
break;
|
|
162
|
-
case "config":
|
|
163
|
-
await configEditCommand();
|
|
129
|
+
case "chat":
|
|
130
|
+
await chatCommand();
|
|
164
131
|
break;
|
|
165
132
|
case "logs":
|
|
166
133
|
await logsCommand();
|
|
167
134
|
break;
|
|
168
|
-
case "whoami":
|
|
169
|
-
await whoamiCommand();
|
|
170
|
-
break;
|
|
171
|
-
case "set-jwt":
|
|
172
|
-
await setJwtCommand();
|
|
173
|
-
break;
|
|
174
135
|
case "logout":
|
|
175
136
|
await logoutCommand();
|
|
176
137
|
await ensureLoggedIn();
|
|
@@ -325,6 +286,13 @@ program
|
|
|
325
286
|
await whoamiCommand();
|
|
326
287
|
});
|
|
327
288
|
|
|
289
|
+
program
|
|
290
|
+
.command("validate [path]")
|
|
291
|
+
.description("Check an ability for errors before deploying")
|
|
292
|
+
.action(async (path?: string) => {
|
|
293
|
+
await validateCommand(path);
|
|
294
|
+
});
|
|
295
|
+
|
|
328
296
|
program
|
|
329
297
|
.command("set-jwt [token]")
|
|
330
298
|
.description(
|
package/src/commands/login.ts
CHANGED
|
@@ -1,14 +1,46 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
1
2
|
import { ApiClient } from "../api/client.js";
|
|
2
3
|
import type { Personality } from "../api/contracts.js";
|
|
3
|
-
import { saveApiKey
|
|
4
|
+
import { saveApiKey } from "../config/store.js";
|
|
4
5
|
import { success, error, info, p, handleCancel } from "../ui/format.js";
|
|
5
6
|
import chalk from "chalk";
|
|
6
7
|
|
|
8
|
+
const SETTINGS_URL = "https://app.openhome.com/dashboard/settings";
|
|
9
|
+
|
|
10
|
+
function openBrowser(url: string): void {
|
|
11
|
+
try {
|
|
12
|
+
if (process.platform === "darwin") {
|
|
13
|
+
execFile("open", [url]);
|
|
14
|
+
} else if (process.platform === "win32") {
|
|
15
|
+
execFile("cmd", ["/c", "start", url]);
|
|
16
|
+
} else {
|
|
17
|
+
execFile("xdg-open", [url]);
|
|
18
|
+
}
|
|
19
|
+
} catch {
|
|
20
|
+
// best-effort
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
7
24
|
export async function loginCommand(): Promise<void> {
|
|
8
25
|
p.intro("🔑 OpenHome Login");
|
|
9
26
|
|
|
27
|
+
const open = await p.confirm({
|
|
28
|
+
message: `Press Enter to open your browser and navigate to the ${chalk.bold("API Keys")} tab`,
|
|
29
|
+
initialValue: true,
|
|
30
|
+
active: "Open browser",
|
|
31
|
+
inactive: "Skip",
|
|
32
|
+
});
|
|
33
|
+
handleCancel(open);
|
|
34
|
+
|
|
35
|
+
if (open) {
|
|
36
|
+
openBrowser(SETTINGS_URL);
|
|
37
|
+
console.log(
|
|
38
|
+
`\n ${chalk.dim(`Opened ${chalk.bold("app.openhome.com/dashboard/settings")} — click the ${chalk.bold("API Keys")} tab`)}\n`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
10
42
|
const apiKey = await p.password({
|
|
11
|
-
message: "
|
|
43
|
+
message: "Paste your API key here",
|
|
12
44
|
validate: (val) => {
|
|
13
45
|
if (!val || !val.trim()) return "API key is required";
|
|
14
46
|
},
|
|
@@ -38,7 +70,6 @@ export async function loginCommand(): Promise<void> {
|
|
|
38
70
|
saveApiKey(apiKey as string);
|
|
39
71
|
success("API key saved.");
|
|
40
72
|
|
|
41
|
-
// Show agents on this account
|
|
42
73
|
if (agents.length > 0) {
|
|
43
74
|
p.note(
|
|
44
75
|
agents
|
package/src/commands/status.ts
CHANGED
|
@@ -3,7 +3,12 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { ApiClient, NotImplementedError } from "../api/client.js";
|
|
5
5
|
import { MockApiClient } from "../api/mock-client.js";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
getApiKey,
|
|
8
|
+
getConfig,
|
|
9
|
+
getJwt,
|
|
10
|
+
getTrackedAbilities,
|
|
11
|
+
} from "../config/store.js";
|
|
7
12
|
import { error, warn, info, p, handleCancel } from "../ui/format.js";
|
|
8
13
|
import chalk from "chalk";
|
|
9
14
|
|