@shadowob/cli 1.1.3 → 1.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/index.js +246 -90
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-T3BKMB7N.js";
|
|
7
7
|
|
|
8
8
|
// src/index.ts
|
|
9
|
-
import { Command as
|
|
9
|
+
import { Command as Command26 } from "commander";
|
|
10
10
|
|
|
11
11
|
// src/commands/agents.ts
|
|
12
12
|
import { Command } from "commander";
|
|
@@ -265,11 +265,169 @@ function createApiTokensCommand() {
|
|
|
265
265
|
return tokens;
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
+
// src/commands/app.ts
|
|
269
|
+
import { readFile, writeFile } from "fs/promises";
|
|
270
|
+
import { basename } from "path";
|
|
271
|
+
import { Command as Command3 } from "commander";
|
|
272
|
+
function resolveServer(value) {
|
|
273
|
+
const server = value ?? process.env.SHADOWOB_SERVER_ID;
|
|
274
|
+
if (!server) throw new Error("Missing server. Pass --server or set SHADOWOB_SERVER_ID.");
|
|
275
|
+
return server;
|
|
276
|
+
}
|
|
277
|
+
function parseJsonInput(value) {
|
|
278
|
+
if (!value) return {};
|
|
279
|
+
const parsed = JSON.parse(value);
|
|
280
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed) && "input" in parsed && Object.keys(parsed).every((key) => key === "input" || key === "channelId")) {
|
|
281
|
+
return parsed.input ?? {};
|
|
282
|
+
}
|
|
283
|
+
return parsed;
|
|
284
|
+
}
|
|
285
|
+
async function readJsonFile(path) {
|
|
286
|
+
return JSON.parse(await readFile(path, "utf8"));
|
|
287
|
+
}
|
|
288
|
+
function commandHandlerError(error, json) {
|
|
289
|
+
outputError(error instanceof Error ? error.message : String(error), { json });
|
|
290
|
+
process.exit(1);
|
|
291
|
+
}
|
|
292
|
+
function createAppCommand() {
|
|
293
|
+
const app = new Command3("app").description("Server App integration commands");
|
|
294
|
+
app.command("list").description("List apps installed in a server").requiredOption("--server <server>", "Server ID or slug").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
295
|
+
try {
|
|
296
|
+
const client = await getClient(options.profile);
|
|
297
|
+
output(await client.listServerApps(resolveServer(options.server)), { json: options.json });
|
|
298
|
+
} catch (error) {
|
|
299
|
+
commandHandlerError(error, options.json);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
app.command("preview").description("Discover and preview a server App manifest before installing it").requiredOption("--server <server>", "Server ID or slug").option("--manifest-url <url>", "Manifest URL").option("--manifest-file <path>", "Local manifest JSON file").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(
|
|
303
|
+
async (options) => {
|
|
304
|
+
try {
|
|
305
|
+
if (!options.manifestUrl && !options.manifestFile) {
|
|
306
|
+
throw new Error("Pass --manifest-url or --manifest-file");
|
|
307
|
+
}
|
|
308
|
+
const client = await getClient(options.profile);
|
|
309
|
+
const manifest = options.manifestFile ? await readJsonFile(options.manifestFile) : void 0;
|
|
310
|
+
output(
|
|
311
|
+
await client.discoverServerApp(resolveServer(options.server), {
|
|
312
|
+
manifestUrl: options.manifestUrl,
|
|
313
|
+
manifest
|
|
314
|
+
}),
|
|
315
|
+
{ json: options.json }
|
|
316
|
+
);
|
|
317
|
+
} catch (error) {
|
|
318
|
+
commandHandlerError(error, options.json);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
app.command("install").description("Install or update a server App from a manifest").requiredOption("--server <server>", "Server ID or slug").option("--manifest-url <url>", "Manifest URL").option("--manifest-file <path>", "Local manifest JSON file").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(
|
|
323
|
+
async (options) => {
|
|
324
|
+
try {
|
|
325
|
+
if (!options.manifestUrl && !options.manifestFile) {
|
|
326
|
+
throw new Error("Pass --manifest-url or --manifest-file");
|
|
327
|
+
}
|
|
328
|
+
const client = await getClient(options.profile);
|
|
329
|
+
const manifest = options.manifestFile ? await readJsonFile(options.manifestFile) : void 0;
|
|
330
|
+
const result = await client.installServerApp(resolveServer(options.server), {
|
|
331
|
+
manifestUrl: options.manifestUrl,
|
|
332
|
+
manifest
|
|
333
|
+
});
|
|
334
|
+
output(result, { json: options.json });
|
|
335
|
+
} catch (error) {
|
|
336
|
+
commandHandlerError(error, options.json);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
);
|
|
340
|
+
app.command("inspect").description("Inspect an installed server App").argument("<app-key>", "App key").requiredOption("--server <server>", "Server ID or slug").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(
|
|
341
|
+
async (appKey, options) => {
|
|
342
|
+
try {
|
|
343
|
+
const client = await getClient(options.profile);
|
|
344
|
+
output(await client.getServerApp(resolveServer(options.server), appKey), {
|
|
345
|
+
json: options.json
|
|
346
|
+
});
|
|
347
|
+
} catch (error) {
|
|
348
|
+
commandHandlerError(error, options.json);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
);
|
|
352
|
+
app.command("grant").description("Grant a Buddy access to an installed server App").argument("<app-key>", "App key").requiredOption("--server <server>", "Server ID or slug").requiredOption("--buddy <agent-id>", "Buddy agent ID").requiredOption("--permissions <permissions>", "Comma-separated permissions, or *").option("--approval-mode <mode>", "none, first_time, every_time, or policy", "none").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(
|
|
353
|
+
async (appKey, options) => {
|
|
354
|
+
try {
|
|
355
|
+
const client = await getClient(options.profile);
|
|
356
|
+
const permissions = options.permissions.split(",").map((item) => item.trim()).filter(Boolean);
|
|
357
|
+
const result = await client.grantServerAppToBuddy(resolveServer(options.server), appKey, {
|
|
358
|
+
buddyAgentId: options.buddy,
|
|
359
|
+
permissions,
|
|
360
|
+
approvalMode: options.approvalMode
|
|
361
|
+
});
|
|
362
|
+
output(result, { json: options.json });
|
|
363
|
+
} catch (error) {
|
|
364
|
+
commandHandlerError(error, options.json);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
);
|
|
368
|
+
app.command("discover").description("Emit Skill-style command discovery for server Apps").requiredOption("--server <server>", "Server ID or slug").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
369
|
+
try {
|
|
370
|
+
const client = await getClient(options.profile);
|
|
371
|
+
const server = resolveServer(options.server);
|
|
372
|
+
const apps = await client.listServerApps(server);
|
|
373
|
+
const docs = await Promise.all(
|
|
374
|
+
apps.map((entry) => client.getServerAppSkills(server, entry.appKey))
|
|
375
|
+
);
|
|
376
|
+
if (options.json) {
|
|
377
|
+
output(docs, { json: true });
|
|
378
|
+
} else {
|
|
379
|
+
console.log(docs.map((doc) => doc.markdown).join("\n\n---\n\n"));
|
|
380
|
+
}
|
|
381
|
+
} catch (error) {
|
|
382
|
+
commandHandlerError(error, options.json);
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
app.command("skills").description("Emit Skill text for one installed server App").argument("<app-key>", "App key").requiredOption("--server <server>", "Server ID or slug").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(
|
|
386
|
+
async (appKey, options) => {
|
|
387
|
+
try {
|
|
388
|
+
const client = await getClient(options.profile);
|
|
389
|
+
const result = await client.getServerAppSkills(resolveServer(options.server), appKey);
|
|
390
|
+
if (options.json) output(result, { json: true });
|
|
391
|
+
else console.log(result.markdown);
|
|
392
|
+
} catch (error) {
|
|
393
|
+
commandHandlerError(error, options.json);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
);
|
|
397
|
+
app.command("call").description("Call a server App command").argument("<app-key>", "App key").argument("<command>", "Command name").requiredOption("--server <server>", "Server ID or slug").option("--json-input <json>", "JSON command input").option("--input-file <path>", "Read JSON command input from file").option("--file <path>", "Attach a binary file").option("--field <field>", "Multipart file field name", "file").option("--output <path>", "Write binary dataBase64 response to this path").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(
|
|
398
|
+
async (appKey, commandName, options) => {
|
|
399
|
+
try {
|
|
400
|
+
const client = await getClient(options.profile);
|
|
401
|
+
const input = options.inputFile ? await readJsonFile(options.inputFile) : parseJsonInput(options.jsonInput);
|
|
402
|
+
const server = resolveServer(options.server);
|
|
403
|
+
const result = options.file ? await client.callServerAppCommandMultipart(server, appKey, commandName, {
|
|
404
|
+
input,
|
|
405
|
+
file: new Blob([await readFile(options.file)]),
|
|
406
|
+
filename: basename(options.file),
|
|
407
|
+
field: options.field
|
|
408
|
+
}) : await client.callServerAppCommand(server, appKey, commandName, { input });
|
|
409
|
+
if (options.output && result && typeof result === "object" && "dataBase64" in result && typeof result.dataBase64 === "string") {
|
|
410
|
+
await writeFile(
|
|
411
|
+
options.output,
|
|
412
|
+
Buffer.from(result.dataBase64, "base64")
|
|
413
|
+
);
|
|
414
|
+
outputSuccess(`Wrote ${options.output}`, { json: options.json });
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
output(result, { json: options.json });
|
|
418
|
+
} catch (error) {
|
|
419
|
+
commandHandlerError(error, options.json);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
);
|
|
423
|
+
return app;
|
|
424
|
+
}
|
|
425
|
+
|
|
268
426
|
// src/commands/auth.ts
|
|
269
427
|
import { ShadowClient } from "@shadowob/sdk";
|
|
270
|
-
import { Command as
|
|
428
|
+
import { Command as Command4 } from "commander";
|
|
271
429
|
function createAuthCommand() {
|
|
272
|
-
const auth = new
|
|
430
|
+
const auth = new Command4("auth").description("Authentication commands");
|
|
273
431
|
auth.command("login").description("Authenticate with a Shadow server").requiredOption("--server-url <url>", "Shadow server URL").requiredOption("--token <token>", "JWT token").option("--profile <name>", "Profile name", "default").option("--json", "Output as JSON").action(
|
|
274
432
|
async (options) => {
|
|
275
433
|
try {
|
|
@@ -382,9 +540,9 @@ function createAuthCommand() {
|
|
|
382
540
|
}
|
|
383
541
|
|
|
384
542
|
// src/commands/channels.ts
|
|
385
|
-
import { Command as
|
|
543
|
+
import { Command as Command5 } from "commander";
|
|
386
544
|
function createChannelsCommand() {
|
|
387
|
-
const channels = new
|
|
545
|
+
const channels = new Command5("channels").description("Channel commands");
|
|
388
546
|
channels.command("list").description("List channels in a server").requiredOption("--server-id <id>", "Server ID").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
389
547
|
try {
|
|
390
548
|
const client = await getClient(options.profile);
|
|
@@ -572,9 +730,9 @@ function createChannelsCommand() {
|
|
|
572
730
|
|
|
573
731
|
// src/commands/cloud.ts
|
|
574
732
|
import { execFileSync, spawnSync } from "child_process";
|
|
575
|
-
import { Command as
|
|
733
|
+
import { Command as Command6 } from "commander";
|
|
576
734
|
function createCloudCommand() {
|
|
577
|
-
const cloud = new
|
|
735
|
+
const cloud = new Command6("cloud").description("Shadow Cloud \u2014 deploy AI agent clusters to Kubernetes (via shadowob-cloud)").allowUnknownOption(true).allowExcessArguments(true).action(async (_, cmd) => {
|
|
578
736
|
const args = cmd.args ?? [];
|
|
579
737
|
ensureCloudCliInstalled();
|
|
580
738
|
spawnCloudCli(args);
|
|
@@ -598,9 +756,9 @@ function spawnCloudCli(args) {
|
|
|
598
756
|
}
|
|
599
757
|
|
|
600
758
|
// src/commands/config.ts
|
|
601
|
-
import { Command as
|
|
759
|
+
import { Command as Command7 } from "commander";
|
|
602
760
|
function createConfigCommand() {
|
|
603
|
-
const config = new
|
|
761
|
+
const config = new Command7("config").description("Configuration management commands");
|
|
604
762
|
config.command("path").description("Show configuration file path").action(() => {
|
|
605
763
|
console.log(configManager.getConfigPath());
|
|
606
764
|
});
|
|
@@ -671,9 +829,9 @@ function createConfigCommand() {
|
|
|
671
829
|
}
|
|
672
830
|
|
|
673
831
|
// src/commands/discover.ts
|
|
674
|
-
import { Command as
|
|
832
|
+
import { Command as Command8 } from "commander";
|
|
675
833
|
function createDiscoverCommand() {
|
|
676
|
-
const discover = new
|
|
834
|
+
const discover = new Command8("discover").description("Discover popular servers and channels");
|
|
677
835
|
discover.command("feed").description("Get the discovery feed").option("--type <type>", "Filter by type (all, servers, channels, rentals)", "all").option("--limit <n>", "Number of results", "20").option("--offset <n>", "Offset for pagination", "0").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
678
836
|
try {
|
|
679
837
|
const client = await getClient(options.profile);
|
|
@@ -710,9 +868,9 @@ function createDiscoverCommand() {
|
|
|
710
868
|
}
|
|
711
869
|
|
|
712
870
|
// src/commands/dms.ts
|
|
713
|
-
import { Command as
|
|
871
|
+
import { Command as Command9 } from "commander";
|
|
714
872
|
function createDirectMessagesCommand() {
|
|
715
|
-
const dms = new
|
|
873
|
+
const dms = new Command9("dms").description("Direct message commands");
|
|
716
874
|
dms.command("list").description("List direct channels").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
717
875
|
try {
|
|
718
876
|
const client = await getClient(options.profile);
|
|
@@ -790,9 +948,9 @@ function createDirectMessagesCommand() {
|
|
|
790
948
|
}
|
|
791
949
|
|
|
792
950
|
// src/commands/friends.ts
|
|
793
|
-
import { Command as
|
|
951
|
+
import { Command as Command10 } from "commander";
|
|
794
952
|
function createFriendsCommand() {
|
|
795
|
-
const friends = new
|
|
953
|
+
const friends = new Command10("friends").description("Friendship management commands");
|
|
796
954
|
friends.command("list").description("List friends").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
797
955
|
try {
|
|
798
956
|
const client = await getClient(options.profile);
|
|
@@ -876,9 +1034,9 @@ function createFriendsCommand() {
|
|
|
876
1034
|
}
|
|
877
1035
|
|
|
878
1036
|
// src/commands/invites.ts
|
|
879
|
-
import { Command as
|
|
1037
|
+
import { Command as Command11 } from "commander";
|
|
880
1038
|
function createInvitesCommand() {
|
|
881
|
-
const invites = new
|
|
1039
|
+
const invites = new Command11("invites").description("Invite code management commands");
|
|
882
1040
|
invites.command("list").description("List your invite codes").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
883
1041
|
try {
|
|
884
1042
|
const client = await getClient(options.profile);
|
|
@@ -929,9 +1087,9 @@ function createInvitesCommand() {
|
|
|
929
1087
|
}
|
|
930
1088
|
|
|
931
1089
|
// src/commands/listen.ts
|
|
932
|
-
import { Command as
|
|
1090
|
+
import { Command as Command12 } from "commander";
|
|
933
1091
|
function createListenCommand() {
|
|
934
|
-
const listen = new
|
|
1092
|
+
const listen = new Command12("listen").description("Listen to real-time events");
|
|
935
1093
|
listen.command("channel").description("Listen to events in a channel").argument("<channel-id>", "Channel ID").option("--mode <mode>", "Listen mode: stream or poll", "stream").option("--timeout <seconds>", "Timeout in seconds (stream mode)", "60").option("--count <n>", "Stop after N events (stream mode)").option("--since <duration>", "Poll events since duration (e.g., 5m, 1h)", "5m").option("--last <n>", "Poll last N messages", "50").option("--event-type <type>", "Filter by event type (comma-separated)").option("--profile <name>", "Profile to use").option("--json", "Output as JSON (one per line)").action(
|
|
936
1094
|
async (channelId, options) => {
|
|
937
1095
|
try {
|
|
@@ -1051,9 +1209,9 @@ function createListenCommand() {
|
|
|
1051
1209
|
}
|
|
1052
1210
|
|
|
1053
1211
|
// src/commands/marketplace.ts
|
|
1054
|
-
import { Command as
|
|
1212
|
+
import { Command as Command13 } from "commander";
|
|
1055
1213
|
function createMarketplaceCommand() {
|
|
1056
|
-
const marketplace = new
|
|
1214
|
+
const marketplace = new Command13("marketplace").description("Marketplace commands");
|
|
1057
1215
|
const listings = marketplace.command("listings").description("Listing commands");
|
|
1058
1216
|
listings.command("list").description("Browse marketplace listings").option("--search <text>", "Search query").option("--tags <tags>", "Comma-separated tags").option("--min-price <n>", "Minimum price per hour").option("--max-price <n>", "Maximum price per hour").option("--limit <n>", "Number of results", "20").option("--offset <n>", "Pagination offset", "0").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(
|
|
1059
1217
|
async (options) => {
|
|
@@ -1198,9 +1356,9 @@ function createMarketplaceCommand() {
|
|
|
1198
1356
|
|
|
1199
1357
|
// src/commands/media.ts
|
|
1200
1358
|
import { readFileSync } from "fs";
|
|
1201
|
-
import { Command as
|
|
1359
|
+
import { Command as Command14 } from "commander";
|
|
1202
1360
|
function createMediaCommand() {
|
|
1203
|
-
const media = new
|
|
1361
|
+
const media = new Command14("media").description("Media management commands");
|
|
1204
1362
|
media.command("upload").description("Upload a file").requiredOption("--file <path>", "File path to upload").option("--message-id <id>", "Associate with message").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(
|
|
1205
1363
|
async (options) => {
|
|
1206
1364
|
try {
|
|
@@ -1266,16 +1424,18 @@ function createMediaCommand() {
|
|
|
1266
1424
|
}
|
|
1267
1425
|
|
|
1268
1426
|
// src/commands/notifications.ts
|
|
1269
|
-
import { Command as
|
|
1427
|
+
import { Command as Command15 } from "commander";
|
|
1270
1428
|
function createNotificationsCommand() {
|
|
1271
|
-
const notifications = new
|
|
1429
|
+
const notifications = new Command15("notifications").description("Notification commands");
|
|
1272
1430
|
notifications.command("list").description("List notifications").option("--unread-only", "Show only unread notifications").option("--limit <n>", "Number of notifications", "20").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(
|
|
1273
1431
|
async (options) => {
|
|
1274
1432
|
try {
|
|
1275
1433
|
const client = await getClient(options.profile);
|
|
1276
1434
|
const limit = parseInt(options.limit ?? "20", 10);
|
|
1277
1435
|
const result = await client.listNotifications(limit);
|
|
1278
|
-
const notifications2 = Array.isArray(result) ? result : []
|
|
1436
|
+
const notifications2 = (Array.isArray(result) ? result : []).filter(
|
|
1437
|
+
(item) => !options.unreadOnly || item.isRead === false
|
|
1438
|
+
);
|
|
1279
1439
|
output(notifications2, { json: options.json });
|
|
1280
1440
|
} catch (error) {
|
|
1281
1441
|
outputError(error instanceof Error ? error.message : String(error), {
|
|
@@ -1307,13 +1467,47 @@ function createNotificationsCommand() {
|
|
|
1307
1467
|
process.exit(1);
|
|
1308
1468
|
}
|
|
1309
1469
|
});
|
|
1470
|
+
const preferences = notifications.command("preferences").description("Notification preferences");
|
|
1471
|
+
preferences.command("get").description("Get notification preferences").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
1472
|
+
try {
|
|
1473
|
+
const client = await getClient(options.profile);
|
|
1474
|
+
output(await client.getNotificationPreferences(), { json: options.json });
|
|
1475
|
+
} catch (error) {
|
|
1476
|
+
outputError(error instanceof Error ? error.message : String(error), { json: options.json });
|
|
1477
|
+
process.exit(1);
|
|
1478
|
+
}
|
|
1479
|
+
});
|
|
1480
|
+
preferences.command("update").description("Update notification preferences").option("--strategy <strategy>", "all | mention_only | none").option("--muted-server-ids <ids>", "Comma-separated server IDs").option("--muted-channel-ids <ids>", "Comma-separated channel IDs").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(
|
|
1481
|
+
async (options) => {
|
|
1482
|
+
try {
|
|
1483
|
+
if (options.strategy && !["all", "mention_only", "none"].includes(options.strategy)) {
|
|
1484
|
+
throw new Error("Invalid --strategy. Expected all, mention_only, or none");
|
|
1485
|
+
}
|
|
1486
|
+
const client = await getClient(options.profile);
|
|
1487
|
+
const data = {
|
|
1488
|
+
...options.strategy ? { strategy: options.strategy } : {},
|
|
1489
|
+
...options.mutedServerIds !== void 0 ? { mutedServerIds: splitIds(options.mutedServerIds) } : {},
|
|
1490
|
+
...options.mutedChannelIds !== void 0 ? { mutedChannelIds: splitIds(options.mutedChannelIds) } : {}
|
|
1491
|
+
};
|
|
1492
|
+
output(await client.updateNotificationPreferences(data), { json: options.json });
|
|
1493
|
+
} catch (error) {
|
|
1494
|
+
outputError(error instanceof Error ? error.message : String(error), {
|
|
1495
|
+
json: options.json
|
|
1496
|
+
});
|
|
1497
|
+
process.exit(1);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
);
|
|
1310
1501
|
return notifications;
|
|
1311
1502
|
}
|
|
1503
|
+
function splitIds(value) {
|
|
1504
|
+
return value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
1505
|
+
}
|
|
1312
1506
|
|
|
1313
1507
|
// src/commands/oauth.ts
|
|
1314
|
-
import { Command as
|
|
1508
|
+
import { Command as Command16 } from "commander";
|
|
1315
1509
|
function createOAuthCommand() {
|
|
1316
|
-
const oauth = new
|
|
1510
|
+
const oauth = new Command16("oauth").description("OAuth management commands");
|
|
1317
1511
|
oauth.command("list").description("List OAuth apps").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
1318
1512
|
try {
|
|
1319
1513
|
const client = await getClient(options.profile);
|
|
@@ -1407,9 +1601,9 @@ function createOAuthCommand() {
|
|
|
1407
1601
|
}
|
|
1408
1602
|
|
|
1409
1603
|
// src/commands/ping.ts
|
|
1410
|
-
import { Command as
|
|
1604
|
+
import { Command as Command17 } from "commander";
|
|
1411
1605
|
function createPingCommand() {
|
|
1412
|
-
const ping = new
|
|
1606
|
+
const ping = new Command17("ping").description("Test connection to Shadow server");
|
|
1413
1607
|
ping.option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
1414
1608
|
const startTime = Date.now();
|
|
1415
1609
|
const outputOpts = { json: options.json };
|
|
@@ -1458,9 +1652,9 @@ function createPingCommand() {
|
|
|
1458
1652
|
}
|
|
1459
1653
|
|
|
1460
1654
|
// src/commands/profile-comments.ts
|
|
1461
|
-
import { Command as
|
|
1655
|
+
import { Command as Command18 } from "commander";
|
|
1462
1656
|
function createProfileCommentsCommand() {
|
|
1463
|
-
const comments = new
|
|
1657
|
+
const comments = new Command18("profile-comments").description(
|
|
1464
1658
|
"Profile comment management commands"
|
|
1465
1659
|
);
|
|
1466
1660
|
comments.command("get").description("Get comments for a user profile").argument("<user-id>", "Profile user ID").option("--limit <n>", "Number of results", "20").option("--offset <n>", "Offset for pagination", "0").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (userId, options) => {
|
|
@@ -1510,9 +1704,9 @@ function createProfileCommentsCommand() {
|
|
|
1510
1704
|
}
|
|
1511
1705
|
|
|
1512
1706
|
// src/commands/search.ts
|
|
1513
|
-
import { Command as
|
|
1707
|
+
import { Command as Command19 } from "commander";
|
|
1514
1708
|
function createSearchCommand() {
|
|
1515
|
-
const search = new
|
|
1709
|
+
const search = new Command19("search").description("Search commands");
|
|
1516
1710
|
search.command("messages").description("Search messages").requiredOption("--query <text>", "Search query").option("--server-id <id>", "Limit to server").option("--channel-id <id>", "Limit to channel").option("--limit <n>", "Number of results (1-100)", "20").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(
|
|
1517
1711
|
async (options) => {
|
|
1518
1712
|
try {
|
|
@@ -1537,9 +1731,9 @@ function createSearchCommand() {
|
|
|
1537
1731
|
}
|
|
1538
1732
|
|
|
1539
1733
|
// src/commands/servers.ts
|
|
1540
|
-
import { Command as
|
|
1734
|
+
import { Command as Command20 } from "commander";
|
|
1541
1735
|
function createServersCommand() {
|
|
1542
|
-
const servers = new
|
|
1736
|
+
const servers = new Command20("servers").description("Server management commands");
|
|
1543
1737
|
servers.command("list").description("List all servers you have joined").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
1544
1738
|
try {
|
|
1545
1739
|
const client = await getClient(options.profile);
|
|
@@ -1619,45 +1813,6 @@ function createServersCommand() {
|
|
|
1619
1813
|
process.exit(1);
|
|
1620
1814
|
}
|
|
1621
1815
|
});
|
|
1622
|
-
servers.command("homepage").description("Get or set server homepage").argument("<server-id>", "Server ID or slug").option("--set <file>", 'Set homepage from HTML file (use "-" for stdin)').option("--clear", "Clear homepage (reset to default)").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(
|
|
1623
|
-
async (serverId, options) => {
|
|
1624
|
-
try {
|
|
1625
|
-
const client = await getClient(options.profile);
|
|
1626
|
-
if (options.clear) {
|
|
1627
|
-
const result = await client.updateServerHomepage(serverId, null);
|
|
1628
|
-
output(result, { json: options.json });
|
|
1629
|
-
return;
|
|
1630
|
-
}
|
|
1631
|
-
if (options.set) {
|
|
1632
|
-
let html;
|
|
1633
|
-
if (options.set === "-") {
|
|
1634
|
-
const chunks = [];
|
|
1635
|
-
for await (const chunk of process.stdin) {
|
|
1636
|
-
chunks.push(Buffer.from(chunk));
|
|
1637
|
-
}
|
|
1638
|
-
html = Buffer.concat(chunks).toString("utf-8");
|
|
1639
|
-
} else {
|
|
1640
|
-
const { readFile: readFile2 } = await import("fs/promises");
|
|
1641
|
-
html = await readFile2(options.set, "utf-8");
|
|
1642
|
-
}
|
|
1643
|
-
const result = await client.updateServerHomepage(serverId, html);
|
|
1644
|
-
output(result, { json: options.json });
|
|
1645
|
-
return;
|
|
1646
|
-
}
|
|
1647
|
-
const server = await client.getServer(serverId);
|
|
1648
|
-
if (options.json) {
|
|
1649
|
-
output({ homepageHtml: server.homepageHtml }, { json: true });
|
|
1650
|
-
} else {
|
|
1651
|
-
console.log(server.homepageHtml ?? "(default homepage)");
|
|
1652
|
-
}
|
|
1653
|
-
} catch (error) {
|
|
1654
|
-
outputError(error instanceof Error ? error.message : String(error), {
|
|
1655
|
-
json: options.json
|
|
1656
|
-
});
|
|
1657
|
-
process.exit(1);
|
|
1658
|
-
}
|
|
1659
|
-
}
|
|
1660
|
-
);
|
|
1661
1816
|
servers.command("discover").description("Discover public servers").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
1662
1817
|
try {
|
|
1663
1818
|
const client = await getClient(options.profile);
|
|
@@ -1672,9 +1827,9 @@ function createServersCommand() {
|
|
|
1672
1827
|
}
|
|
1673
1828
|
|
|
1674
1829
|
// src/commands/shop.ts
|
|
1675
|
-
import { Command as
|
|
1830
|
+
import { Command as Command21 } from "commander";
|
|
1676
1831
|
function createShopCommand() {
|
|
1677
|
-
const shop = new
|
|
1832
|
+
const shop = new Command21("shop").description("Shop commands");
|
|
1678
1833
|
shop.command("get").description("Get shop info").argument("<server-id>", "Server ID").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (serverId, options) => {
|
|
1679
1834
|
try {
|
|
1680
1835
|
const client = await getClient(options.profile);
|
|
@@ -1765,9 +1920,9 @@ function createShopCommand() {
|
|
|
1765
1920
|
}
|
|
1766
1921
|
|
|
1767
1922
|
// src/commands/status.ts
|
|
1768
|
-
import { Command as
|
|
1923
|
+
import { Command as Command22 } from "commander";
|
|
1769
1924
|
function createStatusCommand() {
|
|
1770
|
-
const status = new
|
|
1925
|
+
const status = new Command22("status").description("Show detailed status information");
|
|
1771
1926
|
status.option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
1772
1927
|
const outputOpts = { json: options.json };
|
|
1773
1928
|
try {
|
|
@@ -1782,7 +1937,7 @@ function createStatusCommand() {
|
|
|
1782
1937
|
}
|
|
1783
1938
|
const client = await getClient(options.profile);
|
|
1784
1939
|
const user = await client.getMe();
|
|
1785
|
-
const
|
|
1940
|
+
const unread = await client.getUnreadCount().catch(() => ({ count: 0 }));
|
|
1786
1941
|
const statusInfo = {
|
|
1787
1942
|
profile: {
|
|
1788
1943
|
name: profileName,
|
|
@@ -1795,7 +1950,7 @@ function createStatusCommand() {
|
|
|
1795
1950
|
avatarUrl: user.avatarUrl
|
|
1796
1951
|
},
|
|
1797
1952
|
stats: {
|
|
1798
|
-
unreadNotifications:
|
|
1953
|
+
unreadNotifications: unread.count
|
|
1799
1954
|
},
|
|
1800
1955
|
connection: {
|
|
1801
1956
|
status: "connected",
|
|
@@ -1845,9 +2000,9 @@ function createStatusCommand() {
|
|
|
1845
2000
|
}
|
|
1846
2001
|
|
|
1847
2002
|
// src/commands/threads.ts
|
|
1848
|
-
import { Command as
|
|
2003
|
+
import { Command as Command23 } from "commander";
|
|
1849
2004
|
function createThreadsCommand() {
|
|
1850
|
-
const threads = new
|
|
2005
|
+
const threads = new Command23("threads").description("Thread commands");
|
|
1851
2006
|
threads.command("list").description("List threads in a channel").argument("<channel-id>", "Channel ID").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (channelId, options) => {
|
|
1852
2007
|
try {
|
|
1853
2008
|
const client = await getClient(options.profile);
|
|
@@ -1929,9 +2084,9 @@ function createThreadsCommand() {
|
|
|
1929
2084
|
}
|
|
1930
2085
|
|
|
1931
2086
|
// src/commands/voice-enhance.ts
|
|
1932
|
-
import { Command as
|
|
2087
|
+
import { Command as Command24 } from "commander";
|
|
1933
2088
|
function createVoiceEnhanceCommand() {
|
|
1934
|
-
const voice = new
|
|
2089
|
+
const voice = new Command24("voice-enhance").description("Voice enhancement commands");
|
|
1935
2090
|
voice.command("enhance").description("Enhance a voice transcript").requiredOption("--transcript <text>", "Transcript text to enhance").option("--language <lang>", "Language code (e.g. zh-CN, en-US)").option("--no-self-correction", "Disable self-correction").option("--no-list-formatting", "Disable list formatting").option("--no-filler-removal", "Disable filler word removal").option("--tone-adjustment", "Enable tone adjustment").option("--target-tone <tone>", "Target tone (formal, casual, professional)").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (options) => {
|
|
1936
2091
|
try {
|
|
1937
2092
|
const client = await getClient(options.profile);
|
|
@@ -1970,10 +2125,10 @@ function createVoiceEnhanceCommand() {
|
|
|
1970
2125
|
}
|
|
1971
2126
|
|
|
1972
2127
|
// src/commands/workspace.ts
|
|
1973
|
-
import { readFile } from "fs/promises";
|
|
1974
|
-
import { Command as
|
|
2128
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
2129
|
+
import { Command as Command25 } from "commander";
|
|
1975
2130
|
function createWorkspaceCommand() {
|
|
1976
|
-
const workspace = new
|
|
2131
|
+
const workspace = new Command25("workspace").description("Workspace file management commands");
|
|
1977
2132
|
workspace.command("get").description("Get workspace info").argument("<server-id>", "Server ID or slug").option("--profile <name>", "Profile to use").option("--json", "Output as JSON").action(async (serverId, options) => {
|
|
1978
2133
|
try {
|
|
1979
2134
|
const client = await getClient(options.profile);
|
|
@@ -2069,7 +2224,7 @@ function createWorkspaceCommand() {
|
|
|
2069
2224
|
async (serverId, options) => {
|
|
2070
2225
|
try {
|
|
2071
2226
|
const client = await getClient(options.profile);
|
|
2072
|
-
const content = await
|
|
2227
|
+
const content = await readFile2(options.file);
|
|
2073
2228
|
const blob = new Blob([content]);
|
|
2074
2229
|
const name = options.name ?? options.file.split("/").pop() ?? "upload";
|
|
2075
2230
|
const result = await client.uploadWorkspaceFile(serverId, blob, name, options.parentId);
|
|
@@ -2155,12 +2310,13 @@ function createWorkspaceCommand() {
|
|
|
2155
2310
|
}
|
|
2156
2311
|
|
|
2157
2312
|
// src/index.ts
|
|
2158
|
-
var program = new
|
|
2313
|
+
var program = new Command26();
|
|
2159
2314
|
program.name("shadowob").description("Shadow CLI \u2014 command-line interface for Shadow servers").version("0.1.0").configureHelp({
|
|
2160
2315
|
sortSubcommands: true
|
|
2161
2316
|
});
|
|
2162
2317
|
program.option("--profile <name>", "Profile to use (default: current)");
|
|
2163
2318
|
program.addCommand(createAuthCommand());
|
|
2319
|
+
program.addCommand(createAppCommand());
|
|
2164
2320
|
program.addCommand(createServersCommand());
|
|
2165
2321
|
program.addCommand(createChannelsCommand());
|
|
2166
2322
|
program.addCommand(createThreadsCommand());
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shadowob/cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "Shadow CLI — command-line interface for Shadow servers",
|
|
5
|
+
"license": "MIT",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"bin": {
|
|
7
8
|
"shadowob": "./dist/index.js"
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|
"dependencies": {
|
|
13
14
|
"commander": "^13.1.0",
|
|
14
15
|
"chalk": "^5.4.1",
|
|
15
|
-
"@shadowob/sdk": "1.1.
|
|
16
|
+
"@shadowob/sdk": "1.1.4"
|
|
16
17
|
},
|
|
17
18
|
"devDependencies": {
|
|
18
19
|
"@types/node": "^22.15.21",
|