@waniwani/cli 0.0.22 → 0.0.24
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 +509 -215
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command24 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/init.ts
|
|
7
7
|
import { existsSync } from "fs";
|
|
@@ -561,16 +561,36 @@ var loginCommand = new Command2("login").description("Log in to WaniWani").optio
|
|
|
561
561
|
const json = globalOptions.json ?? false;
|
|
562
562
|
try {
|
|
563
563
|
if (await auth.isLoggedIn()) {
|
|
564
|
-
if (
|
|
565
|
-
|
|
564
|
+
if (await auth.isTokenExpired()) {
|
|
565
|
+
const refreshed = await auth.tryRefreshToken();
|
|
566
|
+
if (refreshed) {
|
|
567
|
+
if (json) {
|
|
568
|
+
formatOutput({ alreadyLoggedIn: true, refreshed: true }, true);
|
|
569
|
+
} else {
|
|
570
|
+
console.log(
|
|
571
|
+
chalk3.green("Session refreshed. You're still logged in.")
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
if (!json) {
|
|
577
|
+
console.log(
|
|
578
|
+
chalk3.yellow("Session expired. Starting new login flow...")
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
await auth.clear();
|
|
566
582
|
} else {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
583
|
+
if (json) {
|
|
584
|
+
formatOutput({ alreadyLoggedIn: true }, true);
|
|
585
|
+
} else {
|
|
586
|
+
console.log(
|
|
587
|
+
chalk3.yellow(
|
|
588
|
+
"Already logged in. Use 'waniwani logout' to log out first."
|
|
589
|
+
)
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
return;
|
|
572
593
|
}
|
|
573
|
-
return;
|
|
574
594
|
}
|
|
575
595
|
if (!json) {
|
|
576
596
|
console.log(chalk3.bold("\nWaniWani CLI Login\n"));
|
|
@@ -667,7 +687,7 @@ var logoutCommand = new Command3("logout").description("Log out from WaniWani").
|
|
|
667
687
|
});
|
|
668
688
|
|
|
669
689
|
// src/commands/mcp/index.ts
|
|
670
|
-
import { Command as
|
|
690
|
+
import { Command as Command19 } from "commander";
|
|
671
691
|
|
|
672
692
|
// src/commands/mcp/create.ts
|
|
673
693
|
import { Command as Command4 } from "commander";
|
|
@@ -710,11 +730,31 @@ async function request(method, path, options) {
|
|
|
710
730
|
if (response.status === 204) {
|
|
711
731
|
return void 0;
|
|
712
732
|
}
|
|
713
|
-
|
|
733
|
+
let data;
|
|
734
|
+
let rawBody;
|
|
735
|
+
try {
|
|
736
|
+
rawBody = await response.text();
|
|
737
|
+
data = JSON.parse(rawBody);
|
|
738
|
+
} catch {
|
|
739
|
+
throw new ApiError(
|
|
740
|
+
rawBody || `Request failed with status ${response.status}`,
|
|
741
|
+
"API_ERROR",
|
|
742
|
+
response.status,
|
|
743
|
+
{ statusText: response.statusText }
|
|
744
|
+
);
|
|
745
|
+
}
|
|
714
746
|
if (!response.ok || data.error) {
|
|
715
|
-
const
|
|
716
|
-
|
|
717
|
-
|
|
747
|
+
const errorMessage = data.error?.message || data.message || data.error || rawBody || `Request failed with status ${response.status}`;
|
|
748
|
+
const errorCode = data.error?.code || data.code || "API_ERROR";
|
|
749
|
+
const errorDetails = {
|
|
750
|
+
...data.error?.details,
|
|
751
|
+
statusText: response.statusText,
|
|
752
|
+
...data.error ? {} : { rawResponse: data }
|
|
753
|
+
};
|
|
754
|
+
const error = {
|
|
755
|
+
code: errorCode,
|
|
756
|
+
message: errorMessage,
|
|
757
|
+
details: errorDetails
|
|
718
758
|
};
|
|
719
759
|
if (response.status === 401) {
|
|
720
760
|
const refreshed = await auth.tryRefreshToken();
|
|
@@ -774,10 +814,41 @@ var createCommand = new Command4("create").description("Create a new MCP sandbox
|
|
|
774
814
|
}
|
|
775
815
|
});
|
|
776
816
|
|
|
777
|
-
// src/commands/mcp/
|
|
817
|
+
// src/commands/mcp/delete.ts
|
|
778
818
|
import { Command as Command5 } from "commander";
|
|
779
819
|
import ora3 from "ora";
|
|
780
|
-
var
|
|
820
|
+
var deleteCommand = new Command5("delete").description("Delete the MCP sandbox").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
|
|
821
|
+
const globalOptions = command.optsWithGlobals();
|
|
822
|
+
const json = globalOptions.json ?? false;
|
|
823
|
+
try {
|
|
824
|
+
let mcpId = options.mcpId;
|
|
825
|
+
if (!mcpId) {
|
|
826
|
+
mcpId = await config.getMcpId();
|
|
827
|
+
if (!mcpId) {
|
|
828
|
+
throw new McpError("No active MCP. Use --mcp-id to specify one.");
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
const spinner = ora3("Deleting MCP sandbox...").start();
|
|
832
|
+
await api.delete(`/api/mcp/sandboxes/${mcpId}`);
|
|
833
|
+
spinner.succeed("MCP sandbox deleted");
|
|
834
|
+
if (await config.getMcpId() === mcpId) {
|
|
835
|
+
await config.setMcpId(null);
|
|
836
|
+
}
|
|
837
|
+
if (json) {
|
|
838
|
+
formatOutput({ deleted: mcpId }, true);
|
|
839
|
+
} else {
|
|
840
|
+
formatSuccess("MCP sandbox deleted and cleaned up.", false);
|
|
841
|
+
}
|
|
842
|
+
} catch (error) {
|
|
843
|
+
handleError(error, json);
|
|
844
|
+
process.exit(1);
|
|
845
|
+
}
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
// src/commands/mcp/deploy.ts
|
|
849
|
+
import { Command as Command6 } from "commander";
|
|
850
|
+
import ora4 from "ora";
|
|
851
|
+
var deployCommand = new Command6("deploy").description("Deploy MCP server to GitHub + Vercel from sandbox").option("--repo <name>", "GitHub repository name").option("--org <name>", "GitHub organization").option("--private", "Create private repository").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
|
|
781
852
|
const globalOptions = command.optsWithGlobals();
|
|
782
853
|
const json = globalOptions.json ?? false;
|
|
783
854
|
try {
|
|
@@ -790,7 +861,7 @@ var deployCommand = new Command5("deploy").description("Deploy MCP server to Git
|
|
|
790
861
|
);
|
|
791
862
|
}
|
|
792
863
|
}
|
|
793
|
-
const spinner =
|
|
864
|
+
const spinner = ora4("Deploying to GitHub...").start();
|
|
794
865
|
const result = await api.post(
|
|
795
866
|
`/api/admin/mcps/${mcpId}/deploy`,
|
|
796
867
|
{
|
|
@@ -821,71 +892,14 @@ var deployCommand = new Command5("deploy").description("Deploy MCP server to Git
|
|
|
821
892
|
}
|
|
822
893
|
});
|
|
823
894
|
|
|
824
|
-
// src/commands/mcp/
|
|
825
|
-
import
|
|
826
|
-
import { Command as Command6 } from "commander";
|
|
827
|
-
import ora4 from "ora";
|
|
828
|
-
var listCommand = new Command6("list").description("List all MCPs in your organization").option("--all", "Include stopped/expired MCPs").action(async (options, command) => {
|
|
829
|
-
const globalOptions = command.optsWithGlobals();
|
|
830
|
-
const json = globalOptions.json ?? false;
|
|
831
|
-
try {
|
|
832
|
-
const spinner = ora4("Fetching MCPs...").start();
|
|
833
|
-
const mcps = await api.get(
|
|
834
|
-
`/api/mcp/sandboxes${options.all ? "?all=true" : ""}`
|
|
835
|
-
);
|
|
836
|
-
spinner.stop();
|
|
837
|
-
const activeMcpId = await config.getMcpId();
|
|
838
|
-
if (json) {
|
|
839
|
-
formatOutput(
|
|
840
|
-
{
|
|
841
|
-
mcps: mcps.map((m) => ({
|
|
842
|
-
...m,
|
|
843
|
-
isActive: m.id === activeMcpId
|
|
844
|
-
})),
|
|
845
|
-
activeMcpId
|
|
846
|
-
},
|
|
847
|
-
true
|
|
848
|
-
);
|
|
849
|
-
} else {
|
|
850
|
-
if (mcps.length === 0) {
|
|
851
|
-
console.log("No MCPs found.");
|
|
852
|
-
console.log("\nCreate a new MCP sandbox: waniwani mcp create <name>");
|
|
853
|
-
return;
|
|
854
|
-
}
|
|
855
|
-
console.log(chalk4.bold("\nMCPs:\n"));
|
|
856
|
-
const rows = mcps.map((m) => {
|
|
857
|
-
const isActive = m.id === activeMcpId;
|
|
858
|
-
const statusColor = m.status === "active" ? chalk4.green : m.status === "stopped" ? chalk4.red : chalk4.yellow;
|
|
859
|
-
return [
|
|
860
|
-
isActive ? chalk4.cyan(`* ${m.id.slice(0, 8)}`) : ` ${m.id.slice(0, 8)}`,
|
|
861
|
-
m.name,
|
|
862
|
-
statusColor(m.status),
|
|
863
|
-
m.previewUrl,
|
|
864
|
-
m.createdAt ? new Date(m.createdAt).toLocaleString() : "N/A"
|
|
865
|
-
];
|
|
866
|
-
});
|
|
867
|
-
formatTable(
|
|
868
|
-
["ID", "Name", "Status", "Preview URL", "Created"],
|
|
869
|
-
rows,
|
|
870
|
-
false
|
|
871
|
-
);
|
|
872
|
-
console.log();
|
|
873
|
-
if (activeMcpId) {
|
|
874
|
-
console.log(`Active MCP: ${chalk4.cyan(activeMcpId.slice(0, 8))}`);
|
|
875
|
-
}
|
|
876
|
-
console.log("\nSelect an MCP: waniwani mcp use <name>");
|
|
877
|
-
}
|
|
878
|
-
} catch (error) {
|
|
879
|
-
handleError(error, json);
|
|
880
|
-
process.exit(1);
|
|
881
|
-
}
|
|
882
|
-
});
|
|
895
|
+
// src/commands/mcp/file/index.ts
|
|
896
|
+
import { Command as Command10 } from "commander";
|
|
883
897
|
|
|
884
|
-
// src/commands/mcp/list
|
|
885
|
-
import
|
|
898
|
+
// src/commands/mcp/file/list.ts
|
|
899
|
+
import chalk4 from "chalk";
|
|
886
900
|
import { Command as Command7 } from "commander";
|
|
887
901
|
import ora5 from "ora";
|
|
888
|
-
var
|
|
902
|
+
var listCommand = new Command7("list").description("List files in the MCP sandbox").argument("[path]", "Directory path (defaults to /app)", "/app").option("--mcp-id <id>", "Specific MCP ID").action(async (path, options, command) => {
|
|
889
903
|
const globalOptions = command.optsWithGlobals();
|
|
890
904
|
const json = globalOptions.json ?? false;
|
|
891
905
|
try {
|
|
@@ -906,15 +920,15 @@ var listFilesCommand = new Command7("list-files").description("List files in the
|
|
|
906
920
|
if (json) {
|
|
907
921
|
formatOutput(result, true);
|
|
908
922
|
} else {
|
|
909
|
-
console.log(
|
|
923
|
+
console.log(chalk4.bold(`
|
|
910
924
|
Directory: ${result.path}
|
|
911
925
|
`));
|
|
912
926
|
if (result.entries.length === 0) {
|
|
913
927
|
console.log(" (empty)");
|
|
914
928
|
} else {
|
|
915
929
|
const rows = result.entries.map((entry) => {
|
|
916
|
-
const name = entry.type === "directory" ?
|
|
917
|
-
const size = entry.type === "directory" ?
|
|
930
|
+
const name = entry.type === "directory" ? chalk4.blue(`${entry.name}/`) : entry.name;
|
|
931
|
+
const size = entry.type === "directory" ? chalk4.gray("<dir>") : formatSize(entry.size);
|
|
918
932
|
return [name, size];
|
|
919
933
|
});
|
|
920
934
|
formatTable(["Name", "Size"], rows, false);
|
|
@@ -933,11 +947,11 @@ function formatSize(bytes) {
|
|
|
933
947
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
934
948
|
}
|
|
935
949
|
|
|
936
|
-
// src/commands/mcp/read
|
|
950
|
+
// src/commands/mcp/file/read.ts
|
|
937
951
|
import { writeFile as writeFile4 } from "fs/promises";
|
|
938
952
|
import { Command as Command8 } from "commander";
|
|
939
953
|
import ora6 from "ora";
|
|
940
|
-
var
|
|
954
|
+
var readCommand = new Command8("read").description("Read a file from the MCP sandbox").argument("<path>", "Path in sandbox (e.g., /app/src/index.ts)").option("--mcp-id <id>", "Specific MCP ID").option("--output <file>", "Write to local file instead of stdout").option("--base64", "Output as base64 (for binary files)").action(async (path, options, command) => {
|
|
941
955
|
const globalOptions = command.optsWithGlobals();
|
|
942
956
|
const json = globalOptions.json ?? false;
|
|
943
957
|
try {
|
|
@@ -981,11 +995,281 @@ var readFileCommand = new Command8("read-file").description("Read a file from th
|
|
|
981
995
|
}
|
|
982
996
|
});
|
|
983
997
|
|
|
984
|
-
// src/commands/mcp/
|
|
985
|
-
import
|
|
998
|
+
// src/commands/mcp/file/write.ts
|
|
999
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
986
1000
|
import { Command as Command9 } from "commander";
|
|
987
1001
|
import ora7 from "ora";
|
|
988
|
-
var
|
|
1002
|
+
var writeCommand = new Command9("write").description("Write a file to the MCP sandbox").argument("<path>", "Path in sandbox (e.g., /app/src/index.ts)").option("--mcp-id <id>", "Specific MCP ID").option("--content <content>", "Content to write").option("--file <localFile>", "Local file to upload").option("--base64", "Treat content as base64 encoded").action(async (path, options, command) => {
|
|
1003
|
+
const globalOptions = command.optsWithGlobals();
|
|
1004
|
+
const json = globalOptions.json ?? false;
|
|
1005
|
+
try {
|
|
1006
|
+
let mcpId = options.mcpId;
|
|
1007
|
+
if (!mcpId) {
|
|
1008
|
+
mcpId = await config.getMcpId();
|
|
1009
|
+
if (!mcpId) {
|
|
1010
|
+
throw new McpError(
|
|
1011
|
+
"No active MCP. Run 'waniwani mcp create <name>' or 'waniwani mcp use <name>'."
|
|
1012
|
+
);
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
let content;
|
|
1016
|
+
let encoding = "utf8";
|
|
1017
|
+
if (options.content) {
|
|
1018
|
+
content = options.content;
|
|
1019
|
+
if (options.base64) {
|
|
1020
|
+
encoding = "base64";
|
|
1021
|
+
}
|
|
1022
|
+
} else if (options.file) {
|
|
1023
|
+
const fileBuffer = await readFile3(options.file);
|
|
1024
|
+
if (options.base64) {
|
|
1025
|
+
content = fileBuffer.toString("base64");
|
|
1026
|
+
encoding = "base64";
|
|
1027
|
+
} else {
|
|
1028
|
+
content = fileBuffer.toString("utf8");
|
|
1029
|
+
}
|
|
1030
|
+
} else {
|
|
1031
|
+
throw new CLIError(
|
|
1032
|
+
"Either --content or --file is required",
|
|
1033
|
+
"MISSING_CONTENT"
|
|
1034
|
+
);
|
|
1035
|
+
}
|
|
1036
|
+
const spinner = ora7(`Writing ${path}...`).start();
|
|
1037
|
+
const result = await api.post(
|
|
1038
|
+
`/api/mcp/sandboxes/${mcpId}/files`,
|
|
1039
|
+
{
|
|
1040
|
+
files: [{ path, content, encoding }]
|
|
1041
|
+
}
|
|
1042
|
+
);
|
|
1043
|
+
spinner.succeed(`Wrote ${path}`);
|
|
1044
|
+
if (json) {
|
|
1045
|
+
formatOutput(result, true);
|
|
1046
|
+
} else {
|
|
1047
|
+
formatSuccess(`File written: ${path}`, false);
|
|
1048
|
+
}
|
|
1049
|
+
} catch (error) {
|
|
1050
|
+
handleError(error, json);
|
|
1051
|
+
process.exit(1);
|
|
1052
|
+
}
|
|
1053
|
+
});
|
|
1054
|
+
|
|
1055
|
+
// src/commands/mcp/file/index.ts
|
|
1056
|
+
var fileCommand = new Command10("file").description("File operations in MCP sandbox").addCommand(readCommand).addCommand(writeCommand).addCommand(listCommand);
|
|
1057
|
+
|
|
1058
|
+
// src/commands/mcp/list.ts
|
|
1059
|
+
import chalk5 from "chalk";
|
|
1060
|
+
import { Command as Command11 } from "commander";
|
|
1061
|
+
import ora8 from "ora";
|
|
1062
|
+
var listCommand2 = new Command11("list").description("List all MCPs in your organization").option("--all", "Include stopped/expired MCPs").action(async (options, command) => {
|
|
1063
|
+
const globalOptions = command.optsWithGlobals();
|
|
1064
|
+
const json = globalOptions.json ?? false;
|
|
1065
|
+
try {
|
|
1066
|
+
const spinner = ora8("Fetching MCPs...").start();
|
|
1067
|
+
const mcps = await api.get(
|
|
1068
|
+
`/api/mcp/sandboxes${options.all ? "?all=true" : ""}`
|
|
1069
|
+
);
|
|
1070
|
+
spinner.stop();
|
|
1071
|
+
const activeMcpId = await config.getMcpId();
|
|
1072
|
+
if (json) {
|
|
1073
|
+
formatOutput(
|
|
1074
|
+
{
|
|
1075
|
+
mcps: mcps.map((m) => ({
|
|
1076
|
+
...m,
|
|
1077
|
+
isActive: m.id === activeMcpId
|
|
1078
|
+
})),
|
|
1079
|
+
activeMcpId
|
|
1080
|
+
},
|
|
1081
|
+
true
|
|
1082
|
+
);
|
|
1083
|
+
} else {
|
|
1084
|
+
if (mcps.length === 0) {
|
|
1085
|
+
console.log("No MCPs found.");
|
|
1086
|
+
console.log("\nCreate a new MCP sandbox: waniwani mcp create <name>");
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
console.log(chalk5.bold("\nMCPs:\n"));
|
|
1090
|
+
const rows = mcps.map((m) => {
|
|
1091
|
+
const isActive = m.id === activeMcpId;
|
|
1092
|
+
const statusColor = m.status === "active" ? chalk5.green : m.status === "stopped" ? chalk5.red : chalk5.yellow;
|
|
1093
|
+
return [
|
|
1094
|
+
isActive ? chalk5.cyan(`* ${m.id.slice(0, 8)}`) : ` ${m.id.slice(0, 8)}`,
|
|
1095
|
+
m.name,
|
|
1096
|
+
statusColor(m.status),
|
|
1097
|
+
m.previewUrl,
|
|
1098
|
+
m.createdAt ? new Date(m.createdAt).toLocaleString() : "N/A"
|
|
1099
|
+
];
|
|
1100
|
+
});
|
|
1101
|
+
formatTable(
|
|
1102
|
+
["ID", "Name", "Status", "Preview URL", "Created"],
|
|
1103
|
+
rows,
|
|
1104
|
+
false
|
|
1105
|
+
);
|
|
1106
|
+
console.log();
|
|
1107
|
+
if (activeMcpId) {
|
|
1108
|
+
console.log(`Active MCP: ${chalk5.cyan(activeMcpId.slice(0, 8))}`);
|
|
1109
|
+
}
|
|
1110
|
+
console.log("\nSelect an MCP: waniwani mcp use <name>");
|
|
1111
|
+
}
|
|
1112
|
+
} catch (error) {
|
|
1113
|
+
handleError(error, json);
|
|
1114
|
+
process.exit(1);
|
|
1115
|
+
}
|
|
1116
|
+
});
|
|
1117
|
+
|
|
1118
|
+
// src/commands/mcp/logs.ts
|
|
1119
|
+
import chalk6 from "chalk";
|
|
1120
|
+
import { Command as Command12 } from "commander";
|
|
1121
|
+
import ora9 from "ora";
|
|
1122
|
+
var logsCommand = new Command12("logs").description("Stream logs from the MCP server").argument("[cmdId]", "Command ID (defaults to running server)").option("--mcp-id <id>", "Specific MCP ID").option("-f, --follow", "Keep streaming logs (default)", true).option("--no-follow", "Fetch logs and exit").action(async (cmdIdArg, options, command) => {
|
|
1123
|
+
const globalOptions = command.optsWithGlobals();
|
|
1124
|
+
const json = globalOptions.json ?? false;
|
|
1125
|
+
let reader;
|
|
1126
|
+
const cleanup = () => {
|
|
1127
|
+
if (reader) {
|
|
1128
|
+
reader.cancel().catch(() => {
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
process.exit(0);
|
|
1132
|
+
};
|
|
1133
|
+
process.on("SIGINT", cleanup);
|
|
1134
|
+
process.on("SIGTERM", cleanup);
|
|
1135
|
+
try {
|
|
1136
|
+
let mcpId = options.mcpId;
|
|
1137
|
+
if (!mcpId) {
|
|
1138
|
+
mcpId = await config.getMcpId();
|
|
1139
|
+
if (!mcpId) {
|
|
1140
|
+
throw new McpError(
|
|
1141
|
+
"No active MCP. Run 'waniwani mcp create <name>' or 'waniwani mcp use <name>'."
|
|
1142
|
+
);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
const token = await auth.getAccessToken();
|
|
1146
|
+
if (!token) {
|
|
1147
|
+
throw new AuthError(
|
|
1148
|
+
"Not logged in. Run 'waniwani login' to authenticate."
|
|
1149
|
+
);
|
|
1150
|
+
}
|
|
1151
|
+
let cmdId = cmdIdArg;
|
|
1152
|
+
if (!cmdId) {
|
|
1153
|
+
const spinner = ora9("Getting server status...").start();
|
|
1154
|
+
const status = await api.post(
|
|
1155
|
+
`/api/mcp/sandboxes/${mcpId}/server`,
|
|
1156
|
+
{ action: "status" }
|
|
1157
|
+
);
|
|
1158
|
+
spinner.stop();
|
|
1159
|
+
if (!status.running || !status.cmdId) {
|
|
1160
|
+
throw new McpError(
|
|
1161
|
+
"No server is running. Run 'waniwani mcp start' first."
|
|
1162
|
+
);
|
|
1163
|
+
}
|
|
1164
|
+
cmdId = status.cmdId;
|
|
1165
|
+
}
|
|
1166
|
+
const baseUrl = await api.getBaseUrl();
|
|
1167
|
+
const streamParam = options.follow ? "?stream=true" : "";
|
|
1168
|
+
const url = `${baseUrl}/api/mcp/sandboxes/${mcpId}/commands/${cmdId}${streamParam}`;
|
|
1169
|
+
if (!json) {
|
|
1170
|
+
console.log(chalk6.gray(`Streaming logs for command ${cmdId}...`));
|
|
1171
|
+
console.log(chalk6.gray("Press Ctrl+C to stop\n"));
|
|
1172
|
+
}
|
|
1173
|
+
const response = await fetch(url, {
|
|
1174
|
+
method: "GET",
|
|
1175
|
+
headers: {
|
|
1176
|
+
Authorization: `Bearer ${token}`,
|
|
1177
|
+
Accept: options.follow ? "text/event-stream" : "application/json"
|
|
1178
|
+
}
|
|
1179
|
+
});
|
|
1180
|
+
if (!response.ok) {
|
|
1181
|
+
const error = await response.json().catch(() => ({ message: response.statusText }));
|
|
1182
|
+
throw new Error(
|
|
1183
|
+
error.message || `Request failed with status ${response.status}`
|
|
1184
|
+
);
|
|
1185
|
+
}
|
|
1186
|
+
if (!options.follow) {
|
|
1187
|
+
const data = await response.json();
|
|
1188
|
+
if (json) {
|
|
1189
|
+
formatOutput(data, true);
|
|
1190
|
+
} else {
|
|
1191
|
+
if (data.stdout) {
|
|
1192
|
+
process.stdout.write(data.stdout);
|
|
1193
|
+
}
|
|
1194
|
+
if (data.stderr) {
|
|
1195
|
+
process.stderr.write(chalk6.red(data.stderr));
|
|
1196
|
+
}
|
|
1197
|
+
if (data.exitCode !== void 0) {
|
|
1198
|
+
console.log(chalk6.gray(`
|
|
1199
|
+
Exit code: ${data.exitCode}`));
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
return;
|
|
1203
|
+
}
|
|
1204
|
+
reader = response.body?.getReader();
|
|
1205
|
+
if (!reader) {
|
|
1206
|
+
throw new Error("No response body");
|
|
1207
|
+
}
|
|
1208
|
+
const decoder = new TextDecoder();
|
|
1209
|
+
let buffer = "";
|
|
1210
|
+
const collectedLogs = [];
|
|
1211
|
+
while (true) {
|
|
1212
|
+
const { done, value } = await reader.read();
|
|
1213
|
+
if (done) break;
|
|
1214
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1215
|
+
const lines = buffer.split("\n");
|
|
1216
|
+
buffer = lines.pop() || "";
|
|
1217
|
+
for (const line of lines) {
|
|
1218
|
+
if (line.startsWith("event: ")) {
|
|
1219
|
+
continue;
|
|
1220
|
+
}
|
|
1221
|
+
if (line.startsWith("data: ")) {
|
|
1222
|
+
const data = line.slice(6);
|
|
1223
|
+
if (!data || data === "[DONE]") continue;
|
|
1224
|
+
try {
|
|
1225
|
+
const event = JSON.parse(data);
|
|
1226
|
+
collectedLogs.push(event);
|
|
1227
|
+
if (json) {
|
|
1228
|
+
continue;
|
|
1229
|
+
}
|
|
1230
|
+
if (event.cmdId) {
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1233
|
+
if (event.stream && event.data !== void 0) {
|
|
1234
|
+
if (event.stream === "stdout") {
|
|
1235
|
+
process.stdout.write(event.data);
|
|
1236
|
+
} else if (event.stream === "stderr") {
|
|
1237
|
+
process.stderr.write(chalk6.red(event.data));
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
if (event.exitCode !== void 0) {
|
|
1241
|
+
const exitColor = event.exitCode === 0 ? chalk6.green : chalk6.red;
|
|
1242
|
+
console.log(
|
|
1243
|
+
exitColor(`
|
|
1244
|
+
Process exited with code ${event.exitCode}`)
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
if (event.error) {
|
|
1248
|
+
console.error(chalk6.red(`
|
|
1249
|
+
Error: ${event.error}`));
|
|
1250
|
+
}
|
|
1251
|
+
} catch {
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
if (json) {
|
|
1257
|
+
formatOutput(collectedLogs, true);
|
|
1258
|
+
}
|
|
1259
|
+
} catch (error) {
|
|
1260
|
+
handleError(error, json);
|
|
1261
|
+
process.exit(1);
|
|
1262
|
+
} finally {
|
|
1263
|
+
process.off("SIGINT", cleanup);
|
|
1264
|
+
process.off("SIGTERM", cleanup);
|
|
1265
|
+
}
|
|
1266
|
+
});
|
|
1267
|
+
|
|
1268
|
+
// src/commands/mcp/run-command.ts
|
|
1269
|
+
import chalk7 from "chalk";
|
|
1270
|
+
import { Command as Command13 } from "commander";
|
|
1271
|
+
import ora10 from "ora";
|
|
1272
|
+
var runCommandCommand = new Command13("run-command").description("Run a command in the MCP sandbox").argument("<command>", "Command to run").argument("[args...]", "Command arguments").option("--mcp-id <id>", "Specific MCP ID").option("--cwd <path>", "Working directory").option(
|
|
989
1273
|
"--timeout <ms>",
|
|
990
1274
|
"Command timeout in milliseconds (default: 30000, max: 300000)"
|
|
991
1275
|
).action(async (cmd, args, options, command) => {
|
|
@@ -1002,7 +1286,7 @@ var runCommandCommand = new Command9("run-command").description("Run a command i
|
|
|
1002
1286
|
}
|
|
1003
1287
|
}
|
|
1004
1288
|
const timeout = options.timeout ? Number.parseInt(options.timeout, 10) : void 0;
|
|
1005
|
-
const spinner =
|
|
1289
|
+
const spinner = ora10(`Running: ${cmd} ${args.join(" ")}`.trim()).start();
|
|
1006
1290
|
const result = await api.post(
|
|
1007
1291
|
`/api/mcp/sandboxes/${mcpId}/command`,
|
|
1008
1292
|
{
|
|
@@ -1017,7 +1301,7 @@ var runCommandCommand = new Command9("run-command").description("Run a command i
|
|
|
1017
1301
|
formatOutput(result, true);
|
|
1018
1302
|
} else {
|
|
1019
1303
|
const cmdLine = [cmd, ...args].join(" ");
|
|
1020
|
-
console.log(
|
|
1304
|
+
console.log(chalk7.gray(`$ ${cmdLine}`));
|
|
1021
1305
|
console.log();
|
|
1022
1306
|
if (result.stdout) {
|
|
1023
1307
|
process.stdout.write(result.stdout);
|
|
@@ -1026,16 +1310,16 @@ var runCommandCommand = new Command9("run-command").description("Run a command i
|
|
|
1026
1310
|
}
|
|
1027
1311
|
}
|
|
1028
1312
|
if (result.stderr) {
|
|
1029
|
-
process.stderr.write(
|
|
1313
|
+
process.stderr.write(chalk7.red(result.stderr));
|
|
1030
1314
|
if (!result.stderr.endsWith("\n")) {
|
|
1031
1315
|
process.stderr.write("\n");
|
|
1032
1316
|
}
|
|
1033
1317
|
}
|
|
1034
1318
|
console.log();
|
|
1035
|
-
const exitColor = result.exitCode === 0 ?
|
|
1319
|
+
const exitColor = result.exitCode === 0 ? chalk7.green : chalk7.red;
|
|
1036
1320
|
console.log(
|
|
1037
1321
|
exitColor(`Exit code: ${result.exitCode}`),
|
|
1038
|
-
|
|
1322
|
+
chalk7.gray(`(${(result.duration / 1e3).toFixed(2)}s)`)
|
|
1039
1323
|
);
|
|
1040
1324
|
}
|
|
1041
1325
|
if (result.exitCode !== 0) {
|
|
@@ -1047,11 +1331,56 @@ var runCommandCommand = new Command9("run-command").description("Run a command i
|
|
|
1047
1331
|
}
|
|
1048
1332
|
});
|
|
1049
1333
|
|
|
1334
|
+
// src/commands/mcp/start.ts
|
|
1335
|
+
import chalk8 from "chalk";
|
|
1336
|
+
import { Command as Command14 } from "commander";
|
|
1337
|
+
import ora11 from "ora";
|
|
1338
|
+
var startCommand = new Command14("start").description("Start the MCP server (npm run dev)").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
|
|
1339
|
+
const globalOptions = command.optsWithGlobals();
|
|
1340
|
+
const json = globalOptions.json ?? false;
|
|
1341
|
+
try {
|
|
1342
|
+
let mcpId = options.mcpId;
|
|
1343
|
+
if (!mcpId) {
|
|
1344
|
+
mcpId = await config.getMcpId();
|
|
1345
|
+
if (!mcpId) {
|
|
1346
|
+
throw new McpError(
|
|
1347
|
+
"No active MCP. Run 'waniwani mcp create <name>' or 'waniwani mcp use <name>'."
|
|
1348
|
+
);
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
const spinner = ora11("Starting MCP server...").start();
|
|
1352
|
+
const result = await api.post(
|
|
1353
|
+
`/api/mcp/sandboxes/${mcpId}/server`,
|
|
1354
|
+
{ action: "start" }
|
|
1355
|
+
);
|
|
1356
|
+
spinner.succeed("MCP server started");
|
|
1357
|
+
if (json) {
|
|
1358
|
+
formatOutput(result, true);
|
|
1359
|
+
} else {
|
|
1360
|
+
console.log();
|
|
1361
|
+
formatList(
|
|
1362
|
+
[
|
|
1363
|
+
{ label: "Command ID", value: result.cmdId },
|
|
1364
|
+
{ label: "Preview URL", value: chalk8.cyan(result.previewUrl) }
|
|
1365
|
+
],
|
|
1366
|
+
false
|
|
1367
|
+
);
|
|
1368
|
+
console.log();
|
|
1369
|
+
console.log(
|
|
1370
|
+
chalk8.gray("Run 'waniwani mcp logs' to stream server output")
|
|
1371
|
+
);
|
|
1372
|
+
}
|
|
1373
|
+
} catch (error) {
|
|
1374
|
+
handleError(error, json);
|
|
1375
|
+
process.exit(1);
|
|
1376
|
+
}
|
|
1377
|
+
});
|
|
1378
|
+
|
|
1050
1379
|
// src/commands/mcp/status.ts
|
|
1051
|
-
import
|
|
1052
|
-
import { Command as
|
|
1053
|
-
import
|
|
1054
|
-
var statusCommand = new
|
|
1380
|
+
import chalk9 from "chalk";
|
|
1381
|
+
import { Command as Command15 } from "commander";
|
|
1382
|
+
import ora12 from "ora";
|
|
1383
|
+
var statusCommand = new Command15("status").description("Show current MCP sandbox status").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
|
|
1055
1384
|
const globalOptions = command.optsWithGlobals();
|
|
1056
1385
|
const json = globalOptions.json ?? false;
|
|
1057
1386
|
try {
|
|
@@ -1064,13 +1393,24 @@ var statusCommand = new Command10("status").description("Show current MCP sandbo
|
|
|
1064
1393
|
);
|
|
1065
1394
|
}
|
|
1066
1395
|
}
|
|
1067
|
-
const spinner =
|
|
1068
|
-
const result = await
|
|
1396
|
+
const spinner = ora12("Fetching MCP status...").start();
|
|
1397
|
+
const [result, serverStatus] = await Promise.all([
|
|
1398
|
+
api.get(`/api/mcp/sandboxes/${mcpId}`),
|
|
1399
|
+
api.post(`/api/mcp/sandboxes/${mcpId}/server`, {
|
|
1400
|
+
action: "status"
|
|
1401
|
+
}).catch(() => ({
|
|
1402
|
+
running: false,
|
|
1403
|
+
cmdId: void 0,
|
|
1404
|
+
previewUrl: void 0
|
|
1405
|
+
}))
|
|
1406
|
+
]);
|
|
1069
1407
|
spinner.stop();
|
|
1070
1408
|
if (json) {
|
|
1071
|
-
formatOutput(result, true);
|
|
1409
|
+
formatOutput({ ...result, server: serverStatus }, true);
|
|
1072
1410
|
} else {
|
|
1073
|
-
const statusColor = result.status === "active" ?
|
|
1411
|
+
const statusColor = result.status === "active" ? chalk9.green : chalk9.red;
|
|
1412
|
+
const serverRunning = serverStatus.running;
|
|
1413
|
+
const serverStatusColor = serverRunning ? chalk9.green : chalk9.yellow;
|
|
1074
1414
|
formatList(
|
|
1075
1415
|
[
|
|
1076
1416
|
{ label: "MCP ID", value: result.id },
|
|
@@ -1078,6 +1418,11 @@ var statusCommand = new Command10("status").description("Show current MCP sandbo
|
|
|
1078
1418
|
{ label: "Status", value: statusColor(result.status) },
|
|
1079
1419
|
{ label: "Sandbox ID", value: result.sandboxId },
|
|
1080
1420
|
{ label: "Preview URL", value: result.previewUrl },
|
|
1421
|
+
{
|
|
1422
|
+
label: "Server",
|
|
1423
|
+
value: serverStatusColor(serverRunning ? "Running" : "Stopped")
|
|
1424
|
+
},
|
|
1425
|
+
...serverStatus.cmdId ? [{ label: "Server Cmd ID", value: serverStatus.cmdId }] : [],
|
|
1081
1426
|
{ label: "Created", value: result.createdAt },
|
|
1082
1427
|
{ label: "Expires", value: result.expiresAt ?? "N/A" }
|
|
1083
1428
|
],
|
|
@@ -1091,9 +1436,9 @@ var statusCommand = new Command10("status").description("Show current MCP sandbo
|
|
|
1091
1436
|
});
|
|
1092
1437
|
|
|
1093
1438
|
// src/commands/mcp/stop.ts
|
|
1094
|
-
import { Command as
|
|
1095
|
-
import
|
|
1096
|
-
var stopCommand = new
|
|
1439
|
+
import { Command as Command16 } from "commander";
|
|
1440
|
+
import ora13 from "ora";
|
|
1441
|
+
var stopCommand = new Command16("stop").description("Stop the MCP server process").option("--mcp-id <id>", "Specific MCP ID").action(async (options, command) => {
|
|
1097
1442
|
const globalOptions = command.optsWithGlobals();
|
|
1098
1443
|
const json = globalOptions.json ?? false;
|
|
1099
1444
|
try {
|
|
@@ -1101,19 +1446,25 @@ var stopCommand = new Command11("stop").description("Stop and clean up the MCP s
|
|
|
1101
1446
|
if (!mcpId) {
|
|
1102
1447
|
mcpId = await config.getMcpId();
|
|
1103
1448
|
if (!mcpId) {
|
|
1104
|
-
throw new McpError(
|
|
1449
|
+
throw new McpError(
|
|
1450
|
+
"No active MCP. Run 'waniwani mcp create <name>' or 'waniwani mcp use <name>'."
|
|
1451
|
+
);
|
|
1105
1452
|
}
|
|
1106
1453
|
}
|
|
1107
|
-
const spinner =
|
|
1108
|
-
await api.
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1454
|
+
const spinner = ora13("Stopping MCP server...").start();
|
|
1455
|
+
const result = await api.post(
|
|
1456
|
+
`/api/mcp/sandboxes/${mcpId}/server`,
|
|
1457
|
+
{ action: "stop" }
|
|
1458
|
+
);
|
|
1459
|
+
if (result.stopped) {
|
|
1460
|
+
spinner.succeed("MCP server stopped");
|
|
1461
|
+
} else {
|
|
1462
|
+
spinner.warn("Server was not running");
|
|
1112
1463
|
}
|
|
1113
1464
|
if (json) {
|
|
1114
|
-
formatOutput(
|
|
1465
|
+
formatOutput(result, true);
|
|
1115
1466
|
} else {
|
|
1116
|
-
formatSuccess("MCP
|
|
1467
|
+
formatSuccess("MCP server stopped.", false);
|
|
1117
1468
|
}
|
|
1118
1469
|
} catch (error) {
|
|
1119
1470
|
handleError(error, json);
|
|
@@ -1122,10 +1473,10 @@ var stopCommand = new Command11("stop").description("Stop and clean up the MCP s
|
|
|
1122
1473
|
});
|
|
1123
1474
|
|
|
1124
1475
|
// src/commands/mcp/test.ts
|
|
1125
|
-
import
|
|
1126
|
-
import { Command as
|
|
1127
|
-
import
|
|
1128
|
-
var testCommand = new
|
|
1476
|
+
import chalk10 from "chalk";
|
|
1477
|
+
import { Command as Command17 } from "commander";
|
|
1478
|
+
import ora14 from "ora";
|
|
1479
|
+
var testCommand = new Command17("test").description("Test MCP tools via the sandbox").argument("[tool]", "Tool name to test (lists tools if omitted)").argument("[args...]", "JSON arguments for the tool").option("--mcp-id <id>", "Specific MCP ID").action(
|
|
1129
1480
|
async (tool, args, options, command) => {
|
|
1130
1481
|
const globalOptions = command.optsWithGlobals();
|
|
1131
1482
|
const json = globalOptions.json ?? false;
|
|
@@ -1140,7 +1491,7 @@ var testCommand = new Command12("test").description("Test MCP tools via the sand
|
|
|
1140
1491
|
}
|
|
1141
1492
|
}
|
|
1142
1493
|
if (!tool) {
|
|
1143
|
-
const spinner =
|
|
1494
|
+
const spinner = ora14("Fetching available tools...").start();
|
|
1144
1495
|
const result = await api.post(
|
|
1145
1496
|
`/api/mcp/sandboxes/${mcpId}/test`,
|
|
1146
1497
|
{ action: "list" }
|
|
@@ -1153,7 +1504,7 @@ var testCommand = new Command12("test").description("Test MCP tools via the sand
|
|
|
1153
1504
|
if (tools.length === 0) {
|
|
1154
1505
|
console.log("No tools available.");
|
|
1155
1506
|
} else {
|
|
1156
|
-
console.log(
|
|
1507
|
+
console.log(chalk10.bold("\nAvailable Tools:\n"));
|
|
1157
1508
|
formatTable(
|
|
1158
1509
|
["Name", "Description"],
|
|
1159
1510
|
tools.map((t) => [t.name, t.description || "No description"]),
|
|
@@ -1176,7 +1527,7 @@ Test a tool: waniwani mcp test <tool-name> '{"arg": "value"}'`
|
|
|
1176
1527
|
);
|
|
1177
1528
|
}
|
|
1178
1529
|
}
|
|
1179
|
-
const spinner =
|
|
1530
|
+
const spinner = ora14(`Calling tool "${tool}"...`).start();
|
|
1180
1531
|
const startTime = Date.now();
|
|
1181
1532
|
const result = await api.post(
|
|
1182
1533
|
`/api/mcp/sandboxes/${mcpId}/test`,
|
|
@@ -1197,11 +1548,11 @@ Test a tool: waniwani mcp test <tool-name> '{"arg": "value"}'`
|
|
|
1197
1548
|
if (json) {
|
|
1198
1549
|
formatOutput(output, true);
|
|
1199
1550
|
} else {
|
|
1200
|
-
console.log(
|
|
1201
|
-
console.log(
|
|
1202
|
-
console.log(
|
|
1203
|
-
console.log(
|
|
1204
|
-
console.log(
|
|
1551
|
+
console.log(chalk10.bold("\nTool Result:\n"));
|
|
1552
|
+
console.log(chalk10.gray("Tool:"), tool);
|
|
1553
|
+
console.log(chalk10.gray("Input:"), JSON.stringify(toolArgs));
|
|
1554
|
+
console.log(chalk10.gray("Duration:"), `${duration}ms`);
|
|
1555
|
+
console.log(chalk10.gray("Result:"));
|
|
1205
1556
|
console.log(JSON.stringify(result.result, null, 2));
|
|
1206
1557
|
}
|
|
1207
1558
|
}
|
|
@@ -1213,13 +1564,13 @@ Test a tool: waniwani mcp test <tool-name> '{"arg": "value"}'`
|
|
|
1213
1564
|
);
|
|
1214
1565
|
|
|
1215
1566
|
// src/commands/mcp/use.ts
|
|
1216
|
-
import { Command as
|
|
1217
|
-
import
|
|
1218
|
-
var useCommand = new
|
|
1567
|
+
import { Command as Command18 } from "commander";
|
|
1568
|
+
import ora15 from "ora";
|
|
1569
|
+
var useCommand = new Command18("use").description("Select an MCP to use for subsequent commands").argument("<name>", "Name of the MCP to use").option("--global", "Save to global config instead of project config").action(async (name, options, command) => {
|
|
1219
1570
|
const globalOptions = command.optsWithGlobals();
|
|
1220
1571
|
const json = globalOptions.json ?? false;
|
|
1221
1572
|
try {
|
|
1222
|
-
const spinner =
|
|
1573
|
+
const spinner = ora15("Fetching MCPs...").start();
|
|
1223
1574
|
const mcps = await api.get("/api/admin/mcps");
|
|
1224
1575
|
spinner.stop();
|
|
1225
1576
|
const mcp = mcps.find((m) => m.name === name);
|
|
@@ -1254,78 +1605,21 @@ var useCommand = new Command13("use").description("Select an MCP to use for subs
|
|
|
1254
1605
|
}
|
|
1255
1606
|
});
|
|
1256
1607
|
|
|
1257
|
-
// src/commands/mcp/write-file.ts
|
|
1258
|
-
import { readFile as readFile3 } from "fs/promises";
|
|
1259
|
-
import { Command as Command14 } from "commander";
|
|
1260
|
-
import ora12 from "ora";
|
|
1261
|
-
var writeFileCommand = new Command14("write-file").description("Write a file to the MCP sandbox").argument("<path>", "Path in sandbox (e.g., /app/src/index.ts)").option("--mcp-id <id>", "Specific MCP ID").option("--content <content>", "Content to write").option("--file <localFile>", "Local file to upload").option("--base64", "Treat content as base64 encoded").action(async (path, options, command) => {
|
|
1262
|
-
const globalOptions = command.optsWithGlobals();
|
|
1263
|
-
const json = globalOptions.json ?? false;
|
|
1264
|
-
try {
|
|
1265
|
-
let mcpId = options.mcpId;
|
|
1266
|
-
if (!mcpId) {
|
|
1267
|
-
mcpId = await config.getMcpId();
|
|
1268
|
-
if (!mcpId) {
|
|
1269
|
-
throw new McpError(
|
|
1270
|
-
"No active MCP. Run 'waniwani mcp create <name>' or 'waniwani mcp use <name>'."
|
|
1271
|
-
);
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
let content;
|
|
1275
|
-
let encoding = "utf8";
|
|
1276
|
-
if (options.content) {
|
|
1277
|
-
content = options.content;
|
|
1278
|
-
if (options.base64) {
|
|
1279
|
-
encoding = "base64";
|
|
1280
|
-
}
|
|
1281
|
-
} else if (options.file) {
|
|
1282
|
-
const fileBuffer = await readFile3(options.file);
|
|
1283
|
-
if (options.base64) {
|
|
1284
|
-
content = fileBuffer.toString("base64");
|
|
1285
|
-
encoding = "base64";
|
|
1286
|
-
} else {
|
|
1287
|
-
content = fileBuffer.toString("utf8");
|
|
1288
|
-
}
|
|
1289
|
-
} else {
|
|
1290
|
-
throw new CLIError(
|
|
1291
|
-
"Either --content or --file is required",
|
|
1292
|
-
"MISSING_CONTENT"
|
|
1293
|
-
);
|
|
1294
|
-
}
|
|
1295
|
-
const spinner = ora12(`Writing ${path}...`).start();
|
|
1296
|
-
const result = await api.post(
|
|
1297
|
-
`/api/mcp/sandboxes/${mcpId}/files`,
|
|
1298
|
-
{
|
|
1299
|
-
files: [{ path, content, encoding }]
|
|
1300
|
-
}
|
|
1301
|
-
);
|
|
1302
|
-
spinner.succeed(`Wrote ${path}`);
|
|
1303
|
-
if (json) {
|
|
1304
|
-
formatOutput(result, true);
|
|
1305
|
-
} else {
|
|
1306
|
-
formatSuccess(`File written: ${path}`, false);
|
|
1307
|
-
}
|
|
1308
|
-
} catch (error) {
|
|
1309
|
-
handleError(error, json);
|
|
1310
|
-
process.exit(1);
|
|
1311
|
-
}
|
|
1312
|
-
});
|
|
1313
|
-
|
|
1314
1608
|
// src/commands/mcp/index.ts
|
|
1315
|
-
var mcpCommand = new
|
|
1609
|
+
var mcpCommand = new Command19("mcp").description("MCP sandbox management commands").addCommand(createCommand).addCommand(listCommand2).addCommand(useCommand).addCommand(statusCommand).addCommand(startCommand).addCommand(stopCommand).addCommand(logsCommand).addCommand(deleteCommand).addCommand(testCommand).addCommand(deployCommand).addCommand(fileCommand).addCommand(runCommandCommand);
|
|
1316
1610
|
|
|
1317
1611
|
// src/commands/org/index.ts
|
|
1318
|
-
import { Command as
|
|
1612
|
+
import { Command as Command22 } from "commander";
|
|
1319
1613
|
|
|
1320
1614
|
// src/commands/org/list.ts
|
|
1321
|
-
import
|
|
1322
|
-
import { Command as
|
|
1323
|
-
import
|
|
1324
|
-
var
|
|
1615
|
+
import chalk11 from "chalk";
|
|
1616
|
+
import { Command as Command20 } from "commander";
|
|
1617
|
+
import ora16 from "ora";
|
|
1618
|
+
var listCommand3 = new Command20("list").description("List your organizations").action(async (_, command) => {
|
|
1325
1619
|
const globalOptions = command.optsWithGlobals();
|
|
1326
1620
|
const json = globalOptions.json ?? false;
|
|
1327
1621
|
try {
|
|
1328
|
-
const spinner =
|
|
1622
|
+
const spinner = ora16("Fetching organizations...").start();
|
|
1329
1623
|
const result = await api.get("/api/oauth/orgs");
|
|
1330
1624
|
spinner.stop();
|
|
1331
1625
|
const { orgs, activeOrgId } = result;
|
|
@@ -1345,11 +1639,11 @@ var listCommand2 = new Command16("list").description("List your organizations").
|
|
|
1345
1639
|
console.log("No organizations found.");
|
|
1346
1640
|
return;
|
|
1347
1641
|
}
|
|
1348
|
-
console.log(
|
|
1642
|
+
console.log(chalk11.bold("\nOrganizations:\n"));
|
|
1349
1643
|
const rows = orgs.map((o) => {
|
|
1350
1644
|
const isActive = o.id === activeOrgId;
|
|
1351
1645
|
return [
|
|
1352
|
-
isActive ?
|
|
1646
|
+
isActive ? chalk11.cyan(`* ${o.name}`) : ` ${o.name}`,
|
|
1353
1647
|
o.slug,
|
|
1354
1648
|
o.role
|
|
1355
1649
|
];
|
|
@@ -1359,7 +1653,7 @@ var listCommand2 = new Command16("list").description("List your organizations").
|
|
|
1359
1653
|
if (activeOrgId) {
|
|
1360
1654
|
const activeOrg = orgs.find((o) => o.id === activeOrgId);
|
|
1361
1655
|
if (activeOrg) {
|
|
1362
|
-
console.log(`Active organization: ${
|
|
1656
|
+
console.log(`Active organization: ${chalk11.cyan(activeOrg.name)}`);
|
|
1363
1657
|
}
|
|
1364
1658
|
}
|
|
1365
1659
|
console.log("\nSwitch organization: waniwani org switch <name>");
|
|
@@ -1371,13 +1665,13 @@ var listCommand2 = new Command16("list").description("List your organizations").
|
|
|
1371
1665
|
});
|
|
1372
1666
|
|
|
1373
1667
|
// src/commands/org/switch.ts
|
|
1374
|
-
import { Command as
|
|
1375
|
-
import
|
|
1376
|
-
var switchCommand = new
|
|
1668
|
+
import { Command as Command21 } from "commander";
|
|
1669
|
+
import ora17 from "ora";
|
|
1670
|
+
var switchCommand = new Command21("switch").description("Switch to a different organization").argument("<name>", "Name or slug of the organization to switch to").action(async (name, _, command) => {
|
|
1377
1671
|
const globalOptions = command.optsWithGlobals();
|
|
1378
1672
|
const json = globalOptions.json ?? false;
|
|
1379
1673
|
try {
|
|
1380
|
-
const spinner =
|
|
1674
|
+
const spinner = ora17("Fetching organizations...").start();
|
|
1381
1675
|
const { orgs } = await api.get("/api/oauth/orgs");
|
|
1382
1676
|
const org = orgs.find((o) => o.name === name || o.slug === name);
|
|
1383
1677
|
if (!org) {
|
|
@@ -1410,13 +1704,13 @@ var switchCommand = new Command17("switch").description("Switch to a different o
|
|
|
1410
1704
|
});
|
|
1411
1705
|
|
|
1412
1706
|
// src/commands/org/index.ts
|
|
1413
|
-
var orgCommand = new
|
|
1707
|
+
var orgCommand = new Command22("org").description("Organization management commands").addCommand(listCommand3).addCommand(switchCommand);
|
|
1414
1708
|
|
|
1415
1709
|
// src/commands/task.ts
|
|
1416
|
-
import
|
|
1417
|
-
import { Command as
|
|
1418
|
-
import
|
|
1419
|
-
var taskCommand = new
|
|
1710
|
+
import chalk12 from "chalk";
|
|
1711
|
+
import { Command as Command23 } from "commander";
|
|
1712
|
+
import ora18 from "ora";
|
|
1713
|
+
var taskCommand = new Command23("task").description("Send a task to Claude running in the sandbox").argument("<prompt>", "Task description/prompt").option("--mcp-id <id>", "Specific MCP ID").option("--model <model>", "Claude model to use").option("--max-steps <n>", "Maximum tool use steps").action(async (prompt, options, command) => {
|
|
1420
1714
|
const globalOptions = command.optsWithGlobals();
|
|
1421
1715
|
const json = globalOptions.json ?? false;
|
|
1422
1716
|
try {
|
|
@@ -1440,10 +1734,10 @@ var taskCommand = new Command19("task").description("Send a task to Claude runni
|
|
|
1440
1734
|
const maxSteps = options.maxSteps ? Number.parseInt(options.maxSteps, 10) : defaults.maxSteps;
|
|
1441
1735
|
if (!json) {
|
|
1442
1736
|
console.log();
|
|
1443
|
-
console.log(
|
|
1737
|
+
console.log(chalk12.bold("Task:"), prompt);
|
|
1444
1738
|
console.log();
|
|
1445
1739
|
}
|
|
1446
|
-
const spinner =
|
|
1740
|
+
const spinner = ora18("Starting task...").start();
|
|
1447
1741
|
const baseUrl = await api.getBaseUrl();
|
|
1448
1742
|
const response = await fetch(
|
|
1449
1743
|
`${baseUrl}/api/mcp/sandboxes/${mcpId}/task`,
|
|
@@ -1497,7 +1791,7 @@ var taskCommand = new Command19("task").description("Send a task to Claude runni
|
|
|
1497
1791
|
const event = parsed;
|
|
1498
1792
|
steps.push({ type: "text", text: event.content });
|
|
1499
1793
|
if (!json && event.content) {
|
|
1500
|
-
console.log(
|
|
1794
|
+
console.log(chalk12.white(event.content));
|
|
1501
1795
|
}
|
|
1502
1796
|
} else if (parsed.type === "tool_call") {
|
|
1503
1797
|
const event = parsed;
|
|
@@ -1508,24 +1802,24 @@ var taskCommand = new Command19("task").description("Send a task to Claude runni
|
|
|
1508
1802
|
output: event.output
|
|
1509
1803
|
});
|
|
1510
1804
|
if (!json) {
|
|
1511
|
-
console.log(
|
|
1805
|
+
console.log(chalk12.cyan(`> Using tool: ${event.tool}`));
|
|
1512
1806
|
if (event.input?.command) {
|
|
1513
|
-
console.log(
|
|
1807
|
+
console.log(chalk12.gray(` $ ${event.input.command}`));
|
|
1514
1808
|
}
|
|
1515
1809
|
if (event.output) {
|
|
1516
1810
|
const outputLines = event.output.split("\n");
|
|
1517
1811
|
if (outputLines.length > 10) {
|
|
1518
1812
|
console.log(
|
|
1519
|
-
|
|
1813
|
+
chalk12.gray(outputLines.slice(0, 5).join("\n"))
|
|
1520
1814
|
);
|
|
1521
1815
|
console.log(
|
|
1522
|
-
|
|
1816
|
+
chalk12.gray(
|
|
1523
1817
|
` ... (${outputLines.length - 10} more lines)`
|
|
1524
1818
|
)
|
|
1525
1819
|
);
|
|
1526
|
-
console.log(
|
|
1820
|
+
console.log(chalk12.gray(outputLines.slice(-5).join("\n")));
|
|
1527
1821
|
} else {
|
|
1528
|
-
console.log(
|
|
1822
|
+
console.log(chalk12.gray(event.output));
|
|
1529
1823
|
}
|
|
1530
1824
|
}
|
|
1531
1825
|
console.log();
|
|
@@ -1552,12 +1846,12 @@ var taskCommand = new Command19("task").description("Send a task to Claude runni
|
|
|
1552
1846
|
} else {
|
|
1553
1847
|
console.log();
|
|
1554
1848
|
console.log(
|
|
1555
|
-
|
|
1849
|
+
chalk12.green("\u2713"),
|
|
1556
1850
|
`Task completed in ${finalStepCount} steps.`
|
|
1557
1851
|
);
|
|
1558
1852
|
if (maxStepsReached) {
|
|
1559
1853
|
console.log(
|
|
1560
|
-
|
|
1854
|
+
chalk12.yellow("\u26A0"),
|
|
1561
1855
|
"Maximum steps reached. Task may be incomplete."
|
|
1562
1856
|
);
|
|
1563
1857
|
}
|
|
@@ -1570,7 +1864,7 @@ var taskCommand = new Command19("task").description("Send a task to Claude runni
|
|
|
1570
1864
|
|
|
1571
1865
|
// src/cli.ts
|
|
1572
1866
|
var version = "0.1.0";
|
|
1573
|
-
var program = new
|
|
1867
|
+
var program = new Command24().name("waniwani").description("WaniWani CLI for MCP development workflow").version(version).option("--json", "Output results as JSON").option("--verbose", "Enable verbose logging");
|
|
1574
1868
|
program.addCommand(loginCommand);
|
|
1575
1869
|
program.addCommand(logoutCommand);
|
|
1576
1870
|
program.addCommand(initCommand);
|