devwing 0.1.20 → 0.1.22
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 +321 -423
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2679,6 +2679,20 @@ var TOOL_ICONS = {
|
|
|
2679
2679
|
http_request: "\u{1F310}",
|
|
2680
2680
|
cve_lookup: "\u{1F512}"
|
|
2681
2681
|
};
|
|
2682
|
+
function resetStdinState() {
|
|
2683
|
+
try {
|
|
2684
|
+
if (typeof process.stdin.setRawMode === "function") {
|
|
2685
|
+
try {
|
|
2686
|
+
process.stdin.setRawMode(false);
|
|
2687
|
+
} catch {
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
process.stdin.removeAllListeners("keypress");
|
|
2691
|
+
process.stdin.removeAllListeners("data");
|
|
2692
|
+
if (process.stdin.isPaused()) process.stdin.resume();
|
|
2693
|
+
} catch {
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2682
2696
|
async function showToolCall(tool, args) {
|
|
2683
2697
|
await sleep(PAUSE_SHORT);
|
|
2684
2698
|
console.log();
|
|
@@ -2697,6 +2711,8 @@ async function showToolCall(tool, args) {
|
|
|
2697
2711
|
default: true
|
|
2698
2712
|
}
|
|
2699
2713
|
]);
|
|
2714
|
+
resetStdinState();
|
|
2715
|
+
await sleep(60);
|
|
2700
2716
|
if (!allowed) {
|
|
2701
2717
|
console.log(chalk7.dim(" \u2717 Skipped"));
|
|
2702
2718
|
throw Object.assign(new Error("TOOL_SKIPPED"), { skipped: true });
|
|
@@ -2771,7 +2787,7 @@ function getVersion() {
|
|
|
2771
2787
|
continue;
|
|
2772
2788
|
}
|
|
2773
2789
|
}
|
|
2774
|
-
return "0.1.
|
|
2790
|
+
return "0.1.22";
|
|
2775
2791
|
}
|
|
2776
2792
|
var DEMO_USER2 = {
|
|
2777
2793
|
id: "usr_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
|
@@ -2786,8 +2802,7 @@ var DEMO_USER2 = {
|
|
|
2786
2802
|
tokens_reset_at: "2026-04-10T00:00:00Z"
|
|
2787
2803
|
};
|
|
2788
2804
|
var DEMO_WORKSPACE2 = {
|
|
2789
|
-
name: "Kano State Government"
|
|
2790
|
-
plan: "enterprise"};
|
|
2805
|
+
name: "Kano State Government"};
|
|
2791
2806
|
var DEMO_PROJECT2 = {
|
|
2792
2807
|
name: "Tallon SaaS ERP"};
|
|
2793
2808
|
var DEMO_MODELS = [
|
|
@@ -2796,11 +2811,11 @@ var DEMO_MODELS = [
|
|
|
2796
2811
|
{ name: "devwing-backend-1", display_name: "DevWing Backend", domain: "backend", status: "active", min_plan: "pro", context_window: 32768, tokens_per_sec: 82, version: "1.0" },
|
|
2797
2812
|
{ name: "devwing-security-1", display_name: "DevWing Security", domain: "security", status: "active", min_plan: "pro", context_window: 32768, tokens_per_sec: 74, version: "1.0" },
|
|
2798
2813
|
{ name: "devwing-devops-1", display_name: "DevWing DevOps", domain: "devops", status: "beta", min_plan: "pro", context_window: 32768, tokens_per_sec: 70, version: "0.9" },
|
|
2799
|
-
{ name: "devwing-mobile-1", display_name: "DevWing Mobile", domain: "
|
|
2800
|
-
{ name: "devwing-data-1", display_name: "DevWing Data", domain: "
|
|
2814
|
+
{ name: "devwing-mobile-1", display_name: "DevWing Mobile", domain: "mobile", status: "beta", min_plan: "pro", context_window: 32768, tokens_per_sec: 72, version: "0.8" },
|
|
2815
|
+
{ name: "devwing-data-1", display_name: "DevWing Data", domain: "data", status: "beta", min_plan: "pro", context_window: 32768, tokens_per_sec: 68, version: "0.7" }
|
|
2801
2816
|
];
|
|
2802
2817
|
var DEMO_PLANS = [
|
|
2803
|
-
{ name: "Free", price: "$0", tokens_day: "50,000", models: "General only", projects: "1", seats: "1" },
|
|
2818
|
+
{ name: "Free", price: "$0/mo", tokens_day: "50,000", models: "General only", projects: "1", seats: "1" },
|
|
2804
2819
|
{ name: "Pro", price: "$19/mo", tokens_day: "500,000", models: "All models", projects: "10", seats: "1" },
|
|
2805
2820
|
{ name: "Team", price: "$99/mo", tokens_day: "2,000,000", models: "All + priority", projects: "Unlimited", seats: "5 included" },
|
|
2806
2821
|
{ name: "Enterprise", price: "Custom", tokens_day: "Unlimited", models: "Dedicated", projects: "Unlimited", seats: "Unlimited" }
|
|
@@ -2825,8 +2840,7 @@ var InteractiveSession = class {
|
|
|
2825
2840
|
sigintCount = 0;
|
|
2826
2841
|
sigintTimer = null;
|
|
2827
2842
|
version;
|
|
2828
|
-
|
|
2829
|
-
// prevent readline events during command execution
|
|
2843
|
+
isRunningCommand = false;
|
|
2830
2844
|
constructor(options) {
|
|
2831
2845
|
this.options = options;
|
|
2832
2846
|
this.isDemo = isDemoMode();
|
|
@@ -2845,63 +2859,76 @@ var InteractiveSession = class {
|
|
|
2845
2859
|
this.printSystemInfo();
|
|
2846
2860
|
this.createReadline();
|
|
2847
2861
|
console.log();
|
|
2848
|
-
this.
|
|
2862
|
+
this.prompt();
|
|
2849
2863
|
}
|
|
2850
2864
|
// ============================================================
|
|
2851
|
-
// READLINE
|
|
2865
|
+
// READLINE — created once, never destroyed
|
|
2852
2866
|
// ============================================================
|
|
2853
2867
|
createReadline() {
|
|
2854
|
-
this.isBusy = false;
|
|
2855
2868
|
this.rl = readline.createInterface({
|
|
2856
2869
|
input: process.stdin,
|
|
2857
2870
|
output: process.stdout,
|
|
2858
|
-
prompt:
|
|
2859
|
-
|
|
2871
|
+
prompt: "",
|
|
2872
|
+
terminal: true
|
|
2860
2873
|
});
|
|
2861
2874
|
this.rl.on("SIGINT", () => {
|
|
2875
|
+
if (this.isRunningCommand) {
|
|
2876
|
+
process.stdout.write("\n");
|
|
2877
|
+
return;
|
|
2878
|
+
}
|
|
2862
2879
|
this.sigintCount++;
|
|
2863
2880
|
if (this.sigintCount >= 2) {
|
|
2864
2881
|
this.exitSession();
|
|
2865
2882
|
return;
|
|
2866
2883
|
}
|
|
2867
|
-
|
|
2884
|
+
process.stdout.write(chalk7.dim("\n Press Ctrl+C again to exit, or type /exit\n"));
|
|
2868
2885
|
this.sigintTimer = setTimeout(() => {
|
|
2869
2886
|
this.sigintCount = 0;
|
|
2870
2887
|
}, 1500);
|
|
2871
|
-
this.
|
|
2888
|
+
this.prompt();
|
|
2872
2889
|
});
|
|
2873
|
-
const currentRl = this.rl;
|
|
2874
2890
|
this.rl.on("line", async (input) => {
|
|
2875
|
-
if (this.
|
|
2891
|
+
if (this.isRunningCommand) return;
|
|
2876
2892
|
const trimmed = input.trim();
|
|
2877
2893
|
if (!trimmed) {
|
|
2878
|
-
this.
|
|
2894
|
+
this.prompt();
|
|
2879
2895
|
return;
|
|
2880
2896
|
}
|
|
2881
|
-
this.
|
|
2897
|
+
this.isRunningCommand = true;
|
|
2898
|
+
this.rl.pause();
|
|
2882
2899
|
try {
|
|
2883
2900
|
if (trimmed.startsWith("/")) {
|
|
2884
2901
|
await this.handleSlashCommand(trimmed);
|
|
2885
|
-
return;
|
|
2886
2902
|
} else {
|
|
2887
2903
|
await this.handleAIPrompt(trimmed);
|
|
2888
2904
|
}
|
|
2889
2905
|
} catch (error) {
|
|
2890
2906
|
logger.error(error.message || "An error occurred");
|
|
2891
2907
|
}
|
|
2892
|
-
this.
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2908
|
+
this.restoreStdin();
|
|
2909
|
+
await sleep2(60);
|
|
2910
|
+
this.isRunningCommand = false;
|
|
2911
|
+
this.rl.resume();
|
|
2912
|
+
this.prompt();
|
|
2897
2913
|
});
|
|
2898
2914
|
this.rl.on("close", () => {
|
|
2899
|
-
if (!this.
|
|
2915
|
+
if (!this.isRunningCommand) {
|
|
2900
2916
|
this.exitSession();
|
|
2901
2917
|
}
|
|
2902
2918
|
});
|
|
2903
2919
|
}
|
|
2904
|
-
|
|
2920
|
+
// Pause readline, run fn (which may use inquirer), restore
|
|
2921
|
+
async withInquirer(fn) {
|
|
2922
|
+
this.rl.pause();
|
|
2923
|
+
try {
|
|
2924
|
+
return await fn();
|
|
2925
|
+
} finally {
|
|
2926
|
+
this.restoreStdin();
|
|
2927
|
+
await sleep2(80);
|
|
2928
|
+
this.rl.resume();
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
restoreStdin() {
|
|
2905
2932
|
try {
|
|
2906
2933
|
if (typeof process.stdin.setRawMode === "function") {
|
|
2907
2934
|
try {
|
|
@@ -2911,18 +2938,17 @@ var InteractiveSession = class {
|
|
|
2911
2938
|
}
|
|
2912
2939
|
process.stdin.removeAllListeners("keypress");
|
|
2913
2940
|
process.stdin.removeAllListeners("data");
|
|
2914
|
-
if (process.stdin.isPaused())
|
|
2915
|
-
process.stdin.resume();
|
|
2916
|
-
}
|
|
2941
|
+
if (process.stdin.isPaused()) process.stdin.resume();
|
|
2917
2942
|
} catch {
|
|
2918
2943
|
}
|
|
2919
2944
|
}
|
|
2920
|
-
|
|
2921
|
-
this.
|
|
2922
|
-
|
|
2945
|
+
prompt() {
|
|
2946
|
+
const p = this.buildPrompt();
|
|
2947
|
+
process.stdout.write(p);
|
|
2948
|
+
this.rl.setPrompt(p);
|
|
2923
2949
|
}
|
|
2924
2950
|
// ============================================================
|
|
2925
|
-
// STARTUP UI
|
|
2951
|
+
// STARTUP UI — Claude Code style
|
|
2926
2952
|
// ============================================================
|
|
2927
2953
|
printStartupBanner() {
|
|
2928
2954
|
const banner = gradient.pastel.multiline([
|
|
@@ -2936,78 +2962,79 @@ var InteractiveSession = class {
|
|
|
2936
2962
|
""
|
|
2937
2963
|
].join("\n"));
|
|
2938
2964
|
console.log(banner);
|
|
2939
|
-
console.log(
|
|
2965
|
+
console.log(
|
|
2966
|
+
chalk7.dim(" Your AI Wingman in the Terminal") + chalk7.dim(" ".repeat(18)) + chalk7.dim(`v${this.version}`)
|
|
2967
|
+
);
|
|
2940
2968
|
console.log();
|
|
2941
2969
|
}
|
|
2942
2970
|
printSystemInfo() {
|
|
2943
|
-
const
|
|
2944
|
-
|
|
2971
|
+
const W = 64;
|
|
2972
|
+
const top = chalk7.dim("\u256D" + "\u2500".repeat(W - 2) + "\u256E");
|
|
2973
|
+
const bottom = chalk7.dim("\u2570" + "\u2500".repeat(W - 2) + "\u256F");
|
|
2974
|
+
const div = chalk7.dim("\u251C" + "\u2500".repeat(W - 2) + "\u2524");
|
|
2975
|
+
const row = (label, value) => {
|
|
2976
|
+
const labelPart2 = chalk7.dim("\u2502 ") + chalk7.bold(label.padEnd(11)) + chalk7.dim(" \u2502 ");
|
|
2977
|
+
const rawValue = value.replace(/\x1B\[[0-9;]*m/g, "");
|
|
2978
|
+
const padLen2 = W - 4 - 11 - 3 - rawValue.length;
|
|
2979
|
+
return labelPart2 + value + " ".repeat(Math.max(0, padLen2)) + chalk7.dim(" \u2502");
|
|
2980
|
+
};
|
|
2981
|
+
console.log(top);
|
|
2945
2982
|
if (this.isAuthenticated && this.userProfile) {
|
|
2946
2983
|
const name = this.userProfile.full_name || this.userProfile.email;
|
|
2947
2984
|
const plan = (this.userProfile.subscription_plan || "free").toUpperCase();
|
|
2948
|
-
const
|
|
2949
|
-
console.log(
|
|
2950
|
-
` ${chalk7.bold("Auth")} ${chalk7.green("\u25CF")} ${name} ${planColor(`(${plan})`)}`
|
|
2951
|
-
);
|
|
2952
|
-
} else if (this.isAuthenticated) {
|
|
2953
|
-
console.log(
|
|
2954
|
-
` ${chalk7.bold("Auth")} ${chalk7.green("\u25CF")} Authenticated ${chalk7.dim("(offline)")}`
|
|
2955
|
-
);
|
|
2985
|
+
const planBadge = plan === "PRO" ? chalk7.bgCyan.black(` ${plan} `) : plan === "ENTERPRISE" ? chalk7.bgMagenta.white(` ${plan} `) : plan === "TEAM" ? chalk7.bgYellow.black(` ${plan} `) : chalk7.bgGray.white(` ${plan} `);
|
|
2986
|
+
console.log(row("Logged in", chalk7.green("\u25CF ") + chalk7.white(name) + " " + planBadge));
|
|
2956
2987
|
} else {
|
|
2957
|
-
console.log(
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
const
|
|
2962
|
-
const
|
|
2963
|
-
|
|
2964
|
-
const
|
|
2988
|
+
console.log(row("Auth", chalk7.red("\u25CF ") + chalk7.dim("Not logged in \u2014 type ") + chalk7.cyan("/login")));
|
|
2989
|
+
}
|
|
2990
|
+
console.log(div);
|
|
2991
|
+
const modeVal = chalk7.yellow.bold(this.currentMode);
|
|
2992
|
+
const modelVal = this.currentModel ? chalk7.cyan(this.currentModel) : chalk7.dim("auto");
|
|
2993
|
+
const labelPart = chalk7.dim("\u2502 ") + chalk7.bold("Mode".padEnd(11)) + chalk7.dim(" \u2502 ");
|
|
2994
|
+
const raw1 = this.currentMode;
|
|
2995
|
+
const mid = " " + chalk7.bold("Model".padEnd(8)) + " " + modelVal;
|
|
2996
|
+
const raw2 = mid.replace(/\x1B\[[0-9;]*m/g, "");
|
|
2997
|
+
const padLen = W - 4 - 11 - 3 - raw1.length - raw2.length;
|
|
2998
|
+
console.log(labelPart + modeVal + mid + " ".repeat(Math.max(0, padLen)) + chalk7.dim(" \u2502"));
|
|
2999
|
+
console.log(div);
|
|
2965
3000
|
if (this.isDemo) {
|
|
2966
|
-
console.log(
|
|
3001
|
+
console.log(row("Project", chalk7.cyan(DEMO_PROJECT2.name)));
|
|
2967
3002
|
} else {
|
|
2968
|
-
const
|
|
2969
|
-
|
|
2970
|
-
console.log(` ${chalk7.bold("Project")} ${projectStr} ${chalk7.bold("CWD")} ${chalk7.dim(cwd)}`);
|
|
3003
|
+
const pid = configManager.getProjectId();
|
|
3004
|
+
console.log(row("Project", pid ? chalk7.cyan(pid) : chalk7.dim("none")));
|
|
2971
3005
|
}
|
|
2972
|
-
const
|
|
2973
|
-
console.log(
|
|
3006
|
+
const cwd = process.cwd().replace(process.env.HOME || "", "~");
|
|
3007
|
+
console.log(row("Directory", chalk7.dim(cwd)));
|
|
2974
3008
|
if (this.isDemo) {
|
|
2975
|
-
console.log(
|
|
3009
|
+
console.log(div);
|
|
3010
|
+
console.log(row("Demo", chalk7.yellow("\u25C6 ") + chalk7.yellow("Demo mode") + chalk7.dim(" \u2014 no backend required")));
|
|
2976
3011
|
}
|
|
2977
|
-
console.log(
|
|
3012
|
+
console.log(bottom);
|
|
2978
3013
|
console.log();
|
|
2979
|
-
console.log(
|
|
3014
|
+
console.log(
|
|
3015
|
+
chalk7.dim(" Chat freely, or use ") + chalk7.cyan("/help") + chalk7.dim(" to see all commands.")
|
|
3016
|
+
);
|
|
2980
3017
|
}
|
|
2981
3018
|
// ============================================================
|
|
2982
|
-
// PROMPT
|
|
3019
|
+
// PROMPT LINE — Claude Code style
|
|
2983
3020
|
// ============================================================
|
|
2984
3021
|
buildPrompt() {
|
|
2985
3022
|
const parts = [];
|
|
2986
|
-
|
|
2987
|
-
|
|
3023
|
+
const sep = chalk7.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
3024
|
+
let nameTag = "";
|
|
2988
3025
|
if (this.isAuthenticated && this.userProfile) {
|
|
2989
|
-
const
|
|
2990
|
-
|
|
2991
|
-
}
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
if (!line.startsWith("/")) return [[], line];
|
|
3002
|
-
const allNames = [];
|
|
3003
|
-
for (const cmd of this.commands.values()) {
|
|
3004
|
-
allNames.push("/" + cmd.name);
|
|
3005
|
-
for (const alias of cmd.aliases) {
|
|
3006
|
-
allNames.push("/" + alias);
|
|
3007
|
-
}
|
|
3008
|
-
}
|
|
3009
|
-
const hits = allNames.filter((n) => n.startsWith(line));
|
|
3010
|
-
return [hits.length ? hits : allNames, line];
|
|
3026
|
+
const first = (this.userProfile.full_name || this.userProfile.email).split(" ")[0].split("@")[0];
|
|
3027
|
+
nameTag = chalk7.dim("@") + chalk7.green(first.toLowerCase());
|
|
3028
|
+
}
|
|
3029
|
+
const modeTag = chalk7.dim("[") + chalk7.yellow(this.currentMode) + chalk7.dim("]");
|
|
3030
|
+
const demoTag = this.isDemo ? chalk7.dim.yellow(" demo") : "";
|
|
3031
|
+
const icon = chalk7.bold.cyan("\u2B21");
|
|
3032
|
+
const label = chalk7.bold.white("devwing");
|
|
3033
|
+
parts.push(`
|
|
3034
|
+
${sep}`);
|
|
3035
|
+
parts.push(` ${icon} ${label} ${modeTag}${nameTag ? " " + nameTag : ""}${demoTag}`);
|
|
3036
|
+
parts.push(" " + chalk7.bold.cyan("\u276F") + " ");
|
|
3037
|
+
return parts.join("\n");
|
|
3011
3038
|
}
|
|
3012
3039
|
// ============================================================
|
|
3013
3040
|
// AUTH CHECK
|
|
@@ -3054,23 +3081,17 @@ var InteractiveSession = class {
|
|
|
3054
3081
|
}
|
|
3055
3082
|
}
|
|
3056
3083
|
if (!command) {
|
|
3084
|
+
console.log();
|
|
3057
3085
|
logger.warn(`Unknown command: /${cmdName}. Type /help for available commands.`);
|
|
3058
3086
|
return;
|
|
3059
3087
|
}
|
|
3060
3088
|
if (command.requiresAuth && !this.isAuthenticated) {
|
|
3089
|
+
console.log();
|
|
3061
3090
|
logger.warn("You need to be logged in for this command. Type /login first.");
|
|
3062
3091
|
return;
|
|
3063
3092
|
}
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
try {
|
|
3067
|
-
await command.handler(args);
|
|
3068
|
-
} catch (error) {
|
|
3069
|
-
logger.error(error.message || "Command failed");
|
|
3070
|
-
}
|
|
3071
|
-
this.resetStdin();
|
|
3072
|
-
await sleep2(80);
|
|
3073
|
-
this.recreateReadline();
|
|
3093
|
+
console.log();
|
|
3094
|
+
await command.handler(args);
|
|
3074
3095
|
}
|
|
3075
3096
|
// ============================================================
|
|
3076
3097
|
// AI PROMPT HANDLER
|
|
@@ -3083,20 +3104,11 @@ var InteractiveSession = class {
|
|
|
3083
3104
|
}
|
|
3084
3105
|
console.log();
|
|
3085
3106
|
if (this.isDemo) {
|
|
3086
|
-
this.
|
|
3087
|
-
this.
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
{ role: "user", content: input, timestamp: /* @__PURE__ */ new Date() },
|
|
3092
|
-
{ role: "assistant", content: "[demo response]", timestamp: /* @__PURE__ */ new Date() }
|
|
3093
|
-
);
|
|
3094
|
-
} catch (error) {
|
|
3095
|
-
logger.error(error.message || "Command failed");
|
|
3096
|
-
}
|
|
3097
|
-
this.resetStdin();
|
|
3098
|
-
await sleep2(80);
|
|
3099
|
-
this.recreateReadline();
|
|
3107
|
+
await demoPromptCommand(input, { ...this.options, mode: this.currentMode });
|
|
3108
|
+
this.conversationHistory.push(
|
|
3109
|
+
{ role: "user", content: input, timestamp: /* @__PURE__ */ new Date() },
|
|
3110
|
+
{ role: "assistant", content: "[demo response]", timestamp: /* @__PURE__ */ new Date() }
|
|
3111
|
+
);
|
|
3100
3112
|
return;
|
|
3101
3113
|
}
|
|
3102
3114
|
if (!this.sessionContext) {
|
|
@@ -3157,9 +3169,7 @@ var InteractiveSession = class {
|
|
|
3157
3169
|
}
|
|
3158
3170
|
buildPromptWithHistory() {
|
|
3159
3171
|
const history = this.conversationHistory;
|
|
3160
|
-
if (history.length <= 1)
|
|
3161
|
-
return history[history.length - 1]?.content || "";
|
|
3162
|
-
}
|
|
3172
|
+
if (history.length <= 1) return history[history.length - 1]?.content || "";
|
|
3163
3173
|
const recent = history.slice(-10);
|
|
3164
3174
|
const context = recent.slice(0, -1).map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`).join("\n\n");
|
|
3165
3175
|
return `Previous conversation:
|
|
@@ -3173,9 +3183,9 @@ ${recent[recent.length - 1].content}`;
|
|
|
3173
3183
|
// ============================================================
|
|
3174
3184
|
exitSession() {
|
|
3175
3185
|
if (this.sigintTimer) clearTimeout(this.sigintTimer);
|
|
3176
|
-
this.
|
|
3186
|
+
this.restoreStdin();
|
|
3177
3187
|
console.log();
|
|
3178
|
-
console.log(chalk7.dim(" Goodbye! Happy
|
|
3188
|
+
console.log(chalk7.dim(" Goodbye! Happy shipping. \u{1F680}"));
|
|
3179
3189
|
console.log();
|
|
3180
3190
|
process.exit(0);
|
|
3181
3191
|
}
|
|
@@ -3183,150 +3193,24 @@ ${recent[recent.length - 1].content}`;
|
|
|
3183
3193
|
// COMMAND REGISTRATION
|
|
3184
3194
|
// ============================================================
|
|
3185
3195
|
registerCommands() {
|
|
3186
|
-
this.addCommand({
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
});
|
|
3194
|
-
this.addCommand({
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
});
|
|
3202
|
-
this.addCommand({
|
|
3203
|
-
|
|
3204
|
-
aliases: ["cls"],
|
|
3205
|
-
description: "Clear screen and conversation",
|
|
3206
|
-
category: "session",
|
|
3207
|
-
requiresAuth: false,
|
|
3208
|
-
handler: async () => this.cmdClear()
|
|
3209
|
-
});
|
|
3210
|
-
this.addCommand({
|
|
3211
|
-
name: "login",
|
|
3212
|
-
aliases: ["signin"],
|
|
3213
|
-
description: "Authenticate with DevWing",
|
|
3214
|
-
category: "session",
|
|
3215
|
-
requiresAuth: false,
|
|
3216
|
-
handler: async () => this.cmdLogin()
|
|
3217
|
-
});
|
|
3218
|
-
this.addCommand({
|
|
3219
|
-
name: "logout",
|
|
3220
|
-
aliases: ["signout"],
|
|
3221
|
-
description: "Clear credentials and log out",
|
|
3222
|
-
category: "session",
|
|
3223
|
-
requiresAuth: true,
|
|
3224
|
-
handler: async () => this.cmdLogout()
|
|
3225
|
-
});
|
|
3226
|
-
this.addCommand({
|
|
3227
|
-
name: "status",
|
|
3228
|
-
aliases: ["whoami"],
|
|
3229
|
-
description: "Show auth status and profile",
|
|
3230
|
-
category: "session",
|
|
3231
|
-
requiresAuth: false,
|
|
3232
|
-
handler: async () => this.cmdStatus()
|
|
3233
|
-
});
|
|
3234
|
-
this.addCommand({
|
|
3235
|
-
name: "scan",
|
|
3236
|
-
aliases: [],
|
|
3237
|
-
description: "Run security vulnerability scan",
|
|
3238
|
-
category: "tools",
|
|
3239
|
-
requiresAuth: true,
|
|
3240
|
-
handler: async () => this.cmdScan()
|
|
3241
|
-
});
|
|
3242
|
-
this.addCommand({
|
|
3243
|
-
name: "review",
|
|
3244
|
-
aliases: [],
|
|
3245
|
-
description: "Perform code review on recent changes",
|
|
3246
|
-
category: "tools",
|
|
3247
|
-
requiresAuth: true,
|
|
3248
|
-
handler: async () => this.cmdReview()
|
|
3249
|
-
});
|
|
3250
|
-
this.addCommand({
|
|
3251
|
-
name: "explain",
|
|
3252
|
-
aliases: [],
|
|
3253
|
-
description: "Explain code, file, or concept",
|
|
3254
|
-
category: "tools",
|
|
3255
|
-
requiresAuth: true,
|
|
3256
|
-
handler: async (args) => this.cmdExplain(args)
|
|
3257
|
-
});
|
|
3258
|
-
this.addCommand({
|
|
3259
|
-
name: "memory",
|
|
3260
|
-
aliases: ["mem"],
|
|
3261
|
-
description: "Manage project memory (save/show/clear)",
|
|
3262
|
-
category: "tools",
|
|
3263
|
-
requiresAuth: true,
|
|
3264
|
-
handler: async (args) => this.cmdMemory(args)
|
|
3265
|
-
});
|
|
3266
|
-
this.addCommand({
|
|
3267
|
-
name: "mode",
|
|
3268
|
-
aliases: [],
|
|
3269
|
-
description: "Show or set AI mode",
|
|
3270
|
-
category: "config",
|
|
3271
|
-
requiresAuth: false,
|
|
3272
|
-
handler: async (args) => this.cmdMode(args)
|
|
3273
|
-
});
|
|
3274
|
-
this.addCommand({
|
|
3275
|
-
name: "model",
|
|
3276
|
-
aliases: [],
|
|
3277
|
-
description: "Show or set AI model",
|
|
3278
|
-
category: "config",
|
|
3279
|
-
requiresAuth: false,
|
|
3280
|
-
handler: async (args) => this.cmdModel(args)
|
|
3281
|
-
});
|
|
3282
|
-
this.addCommand({
|
|
3283
|
-
name: "models",
|
|
3284
|
-
aliases: [],
|
|
3285
|
-
description: "List all available AI models",
|
|
3286
|
-
category: "config",
|
|
3287
|
-
requiresAuth: false,
|
|
3288
|
-
handler: async () => this.cmdModels()
|
|
3289
|
-
});
|
|
3290
|
-
this.addCommand({
|
|
3291
|
-
name: "usage",
|
|
3292
|
-
aliases: ["stats"],
|
|
3293
|
-
description: "Show token usage statistics",
|
|
3294
|
-
category: "config",
|
|
3295
|
-
requiresAuth: true,
|
|
3296
|
-
handler: async () => this.cmdUsage()
|
|
3297
|
-
});
|
|
3298
|
-
this.addCommand({
|
|
3299
|
-
name: "plans",
|
|
3300
|
-
aliases: ["pricing"],
|
|
3301
|
-
description: "Show available plans and pricing",
|
|
3302
|
-
category: "config",
|
|
3303
|
-
requiresAuth: false,
|
|
3304
|
-
handler: async () => this.cmdPlans()
|
|
3305
|
-
});
|
|
3306
|
-
this.addCommand({
|
|
3307
|
-
name: "context",
|
|
3308
|
-
aliases: ["ctx"],
|
|
3309
|
-
description: "Show loaded codebase context",
|
|
3310
|
-
category: "config",
|
|
3311
|
-
requiresAuth: false,
|
|
3312
|
-
handler: async () => this.cmdContext()
|
|
3313
|
-
});
|
|
3314
|
-
this.addCommand({
|
|
3315
|
-
name: "history",
|
|
3316
|
-
aliases: [],
|
|
3317
|
-
description: "Show conversation history",
|
|
3318
|
-
category: "config",
|
|
3319
|
-
requiresAuth: false,
|
|
3320
|
-
handler: async () => this.cmdHistory()
|
|
3321
|
-
});
|
|
3322
|
-
this.addCommand({
|
|
3323
|
-
name: "config",
|
|
3324
|
-
aliases: ["settings"],
|
|
3325
|
-
description: "Show or set CLI configuration",
|
|
3326
|
-
category: "config",
|
|
3327
|
-
requiresAuth: false,
|
|
3328
|
-
handler: async (args) => this.cmdConfig(args)
|
|
3329
|
-
});
|
|
3196
|
+
this.addCommand({ name: "help", aliases: ["h", "?"], description: "Show all available commands", category: "session", requiresAuth: false, handler: async () => this.cmdHelp() });
|
|
3197
|
+
this.addCommand({ name: "exit", aliases: ["quit", "q"], description: "Exit DevWing", category: "session", requiresAuth: false, handler: async () => this.exitSession() });
|
|
3198
|
+
this.addCommand({ name: "clear", aliases: ["cls"], description: "Clear screen and conversation", category: "session", requiresAuth: false, handler: async () => this.cmdClear() });
|
|
3199
|
+
this.addCommand({ name: "login", aliases: ["signin"], description: "Authenticate with DevWing", category: "session", requiresAuth: false, handler: async () => this.cmdLogin() });
|
|
3200
|
+
this.addCommand({ name: "logout", aliases: ["signout"], description: "Clear credentials and log out", category: "session", requiresAuth: true, handler: async () => this.cmdLogout() });
|
|
3201
|
+
this.addCommand({ name: "status", aliases: ["whoami"], description: "Show auth status and profile", category: "session", requiresAuth: false, handler: async () => this.cmdStatus() });
|
|
3202
|
+
this.addCommand({ name: "scan", aliases: [], description: "Run security vulnerability scan", category: "tools", requiresAuth: true, handler: async () => this.cmdScan() });
|
|
3203
|
+
this.addCommand({ name: "review", aliases: [], description: "Perform code review on recent changes", category: "tools", requiresAuth: true, handler: async () => this.cmdReview() });
|
|
3204
|
+
this.addCommand({ name: "explain", aliases: [], description: "Explain code, file, or concept", category: "tools", requiresAuth: true, handler: async (a) => this.cmdExplain(a) });
|
|
3205
|
+
this.addCommand({ name: "memory", aliases: ["mem"], description: "Manage project memory (save/show/clear)", category: "tools", requiresAuth: true, handler: async (a) => this.cmdMemory(a) });
|
|
3206
|
+
this.addCommand({ name: "mode", aliases: [], description: "Show or set AI mode", category: "config", requiresAuth: false, handler: async (a) => this.cmdMode(a) });
|
|
3207
|
+
this.addCommand({ name: "model", aliases: [], description: "Show or set AI model", category: "config", requiresAuth: false, handler: async (a) => this.cmdModel(a) });
|
|
3208
|
+
this.addCommand({ name: "models", aliases: [], description: "List all available AI models", category: "config", requiresAuth: false, handler: async () => this.cmdModels() });
|
|
3209
|
+
this.addCommand({ name: "usage", aliases: ["stats"], description: "Show token usage statistics", category: "config", requiresAuth: true, handler: async () => this.cmdUsage() });
|
|
3210
|
+
this.addCommand({ name: "plans", aliases: ["pricing"], description: "Show available plans and pricing", category: "config", requiresAuth: false, handler: async () => this.cmdPlans() });
|
|
3211
|
+
this.addCommand({ name: "context", aliases: ["ctx"], description: "Show loaded codebase context", category: "config", requiresAuth: false, handler: async () => this.cmdContext() });
|
|
3212
|
+
this.addCommand({ name: "history", aliases: [], description: "Show conversation history", category: "config", requiresAuth: false, handler: async () => this.cmdHistory() });
|
|
3213
|
+
this.addCommand({ name: "config", aliases: ["settings"], description: "Show or set CLI configuration", category: "config", requiresAuth: false, handler: async (a) => this.cmdConfig(a) });
|
|
3330
3214
|
}
|
|
3331
3215
|
addCommand(cmd) {
|
|
3332
3216
|
this.commands.set(cmd.name, cmd);
|
|
@@ -3335,24 +3219,42 @@ ${recent[recent.length - 1].content}`;
|
|
|
3335
3219
|
// COMMAND IMPLEMENTATIONS
|
|
3336
3220
|
// ============================================================
|
|
3337
3221
|
async cmdHelp() {
|
|
3338
|
-
|
|
3222
|
+
const W = 64;
|
|
3223
|
+
const top = chalk7.dim("\u256D" + "\u2500".repeat(W - 2) + "\u256E");
|
|
3224
|
+
const bottom = chalk7.dim("\u2570" + "\u2500".repeat(W - 2) + "\u256F");
|
|
3225
|
+
const div = chalk7.dim("\u251C" + "\u2500".repeat(W - 2) + "\u2524");
|
|
3226
|
+
const hRow = (left, right) => {
|
|
3227
|
+
const rawLeft = left.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3228
|
+
const rawRight = right.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3229
|
+
const pad = W - 2 - rawLeft.length - rawRight.length - 2;
|
|
3230
|
+
return chalk7.dim("\u2502 ") + left + " ".repeat(Math.max(0, pad)) + right + chalk7.dim(" \u2502");
|
|
3231
|
+
};
|
|
3232
|
+
const catRow = (label) => {
|
|
3233
|
+
const raw = label.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3234
|
+
const pad = W - 4 - raw.length;
|
|
3235
|
+
return chalk7.dim("\u2502 ") + label + " ".repeat(Math.max(0, pad)) + chalk7.dim(" \u2502");
|
|
3236
|
+
};
|
|
3339
3237
|
const categories = [
|
|
3340
3238
|
{ key: "session", label: "Session", color: chalk7.bold.green },
|
|
3341
3239
|
{ key: "tools", label: "AI Tools", color: chalk7.bold.magenta },
|
|
3342
3240
|
{ key: "config", label: "Configuration", color: chalk7.bold.yellow }
|
|
3343
3241
|
];
|
|
3344
|
-
|
|
3242
|
+
console.log(top);
|
|
3243
|
+
console.log(catRow(chalk7.bold.white(" Commands")));
|
|
3345
3244
|
for (const cat of categories) {
|
|
3346
|
-
|
|
3245
|
+
console.log(div);
|
|
3246
|
+
console.log(catRow(" " + cat.color(cat.label)));
|
|
3347
3247
|
for (const cmd of this.commands.values()) {
|
|
3348
3248
|
if (cmd.category !== cat.key) continue;
|
|
3349
|
-
const
|
|
3350
|
-
|
|
3249
|
+
const cmdStr = chalk7.cyan(("/" + cmd.name).padEnd(14));
|
|
3250
|
+
const descStr = chalk7.dim(cmd.description);
|
|
3251
|
+
const aliasStr = cmd.aliases.length > 0 ? chalk7.dim(` \xB7 ${cmd.aliases.map((a) => "/" + a).join(", ")}`) : "";
|
|
3252
|
+
console.log(hRow(" " + cmdStr + " " + descStr, aliasStr));
|
|
3351
3253
|
}
|
|
3352
|
-
lines.push("");
|
|
3353
3254
|
}
|
|
3354
|
-
|
|
3355
|
-
|
|
3255
|
+
console.log(div);
|
|
3256
|
+
console.log(catRow(chalk7.dim(" Just type a message to chat with DevWing AI")));
|
|
3257
|
+
console.log(bottom);
|
|
3356
3258
|
}
|
|
3357
3259
|
async cmdClear() {
|
|
3358
3260
|
this.conversationHistory = [];
|
|
@@ -3363,53 +3265,50 @@ ${recent[recent.length - 1].content}`;
|
|
|
3363
3265
|
this.printSystemInfo();
|
|
3364
3266
|
}
|
|
3365
3267
|
async cmdLogin() {
|
|
3366
|
-
console.log();
|
|
3367
3268
|
if (this.isDemo) {
|
|
3368
|
-
await demoLoginCommand({ fromSession: true });
|
|
3269
|
+
await this.withInquirer(() => demoLoginCommand({ fromSession: true }));
|
|
3369
3270
|
} else {
|
|
3370
|
-
await loginCommand();
|
|
3271
|
+
await this.withInquirer(() => loginCommand());
|
|
3371
3272
|
}
|
|
3372
3273
|
await this.checkAuthStatus();
|
|
3373
|
-
this.rl.setPrompt(this.buildPrompt());
|
|
3374
3274
|
}
|
|
3375
3275
|
async cmdLogout() {
|
|
3376
|
-
console.log();
|
|
3377
3276
|
if (this.isDemo) {
|
|
3378
|
-
await demoLogoutCommand();
|
|
3277
|
+
await this.withInquirer(() => demoLogoutCommand());
|
|
3379
3278
|
} else {
|
|
3380
|
-
await logoutCommand();
|
|
3279
|
+
await this.withInquirer(() => logoutCommand());
|
|
3381
3280
|
}
|
|
3382
3281
|
await this.checkAuthStatus();
|
|
3383
|
-
this.rl.setPrompt(this.buildPrompt());
|
|
3384
3282
|
}
|
|
3385
3283
|
async cmdStatus() {
|
|
3386
|
-
console.log();
|
|
3387
3284
|
if (!this.isAuthenticated) {
|
|
3388
3285
|
logger.info("Not logged in. Type /login to authenticate.");
|
|
3389
3286
|
return;
|
|
3390
3287
|
}
|
|
3391
3288
|
if (this.isDemo) {
|
|
3392
|
-
const
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
);
|
|
3406
|
-
console.log(
|
|
3289
|
+
const W = 54;
|
|
3290
|
+
const top = chalk7.dim("\u256D" + "\u2500".repeat(W - 2) + "\u256E");
|
|
3291
|
+
const bottom = chalk7.dim("\u2570" + "\u2500".repeat(W - 2) + "\u256F");
|
|
3292
|
+
const row = (k, v) => {
|
|
3293
|
+
const rawV = v.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3294
|
+
const pad = W - 4 - k.length - rawV.length;
|
|
3295
|
+
return chalk7.dim("\u2502 ") + chalk7.bold(k) + " ".repeat(Math.max(0, pad)) + v + chalk7.dim(" \u2502");
|
|
3296
|
+
};
|
|
3297
|
+
console.log(top);
|
|
3298
|
+
console.log(row("Email", DEMO_USER2.email));
|
|
3299
|
+
console.log(row("Name", DEMO_USER2.full_name));
|
|
3300
|
+
console.log(row("Plan", chalk7.bgCyan.black(" PRO ")));
|
|
3301
|
+
console.log(row("Verified", chalk7.green("\u2713 Yes")));
|
|
3302
|
+
console.log(row("2FA", chalk7.dim("Disabled")));
|
|
3303
|
+
console.log(row("Workspace", DEMO_WORKSPACE2.name + chalk7.dim(" (enterprise)")));
|
|
3304
|
+
console.log(row("Project", DEMO_PROJECT2.name));
|
|
3305
|
+
console.log(row("Tokens today", `${(DEMO_USER2.tokens_used_today).toLocaleString()} / 500,000`));
|
|
3306
|
+
console.log(bottom);
|
|
3407
3307
|
} else {
|
|
3408
3308
|
await statusCommand();
|
|
3409
3309
|
}
|
|
3410
3310
|
}
|
|
3411
3311
|
async cmdScan() {
|
|
3412
|
-
console.log();
|
|
3413
3312
|
if (this.isDemo) {
|
|
3414
3313
|
await demoPromptCommand("scan auth service for OWASP vulnerabilities", { ...this.options, mode: "security" });
|
|
3415
3314
|
} else {
|
|
@@ -3417,7 +3316,6 @@ ${recent[recent.length - 1].content}`;
|
|
|
3417
3316
|
}
|
|
3418
3317
|
}
|
|
3419
3318
|
async cmdReview() {
|
|
3420
|
-
console.log();
|
|
3421
3319
|
if (this.isDemo) {
|
|
3422
3320
|
await demoReviewCommand();
|
|
3423
3321
|
} else {
|
|
@@ -3430,7 +3328,6 @@ ${recent[recent.length - 1].content}`;
|
|
|
3430
3328
|
logger.info("Example: /explain src/auth/middleware.ts");
|
|
3431
3329
|
return;
|
|
3432
3330
|
}
|
|
3433
|
-
console.log();
|
|
3434
3331
|
if (this.isDemo) {
|
|
3435
3332
|
await demoExplainCommand(args);
|
|
3436
3333
|
} else {
|
|
@@ -3447,10 +3344,11 @@ ${recent[recent.length - 1].content}`;
|
|
|
3447
3344
|
console.log(` ${chalk7.cyan("/memory clear")} \u2014 Clear all memories`);
|
|
3448
3345
|
return;
|
|
3449
3346
|
}
|
|
3450
|
-
console.log();
|
|
3451
3347
|
const content = parts.slice(1).join(" ").trim();
|
|
3452
3348
|
if (this.isDemo) {
|
|
3453
|
-
await
|
|
3349
|
+
await this.withInquirer(
|
|
3350
|
+
() => demoMemoryCommand(sub, content || void 0)
|
|
3351
|
+
);
|
|
3454
3352
|
} else {
|
|
3455
3353
|
await memoryCommand(sub, content || void 0, this.options);
|
|
3456
3354
|
}
|
|
@@ -3458,17 +3356,32 @@ ${recent[recent.length - 1].content}`;
|
|
|
3458
3356
|
async cmdMode(args) {
|
|
3459
3357
|
const validModes = ["general", "frontend", "backend", "security", "devops"];
|
|
3460
3358
|
if (!args) {
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
const
|
|
3467
|
-
const
|
|
3468
|
-
|
|
3359
|
+
const W = 58;
|
|
3360
|
+
const top = chalk7.dim("\u256D" + "\u2500".repeat(W - 2) + "\u256E");
|
|
3361
|
+
const bottom = chalk7.dim("\u2570" + "\u2500".repeat(W - 2) + "\u256F");
|
|
3362
|
+
const row = (icon, name, desc) => {
|
|
3363
|
+
const left = ` ${icon} ${name.padEnd(12)} ${chalk7.dim(desc)}`;
|
|
3364
|
+
const rawLeft = left.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3365
|
+
const pad = W - 2 - rawLeft.length;
|
|
3366
|
+
return chalk7.dim("\u2502") + left + " ".repeat(Math.max(0, pad)) + chalk7.dim("\u2502");
|
|
3367
|
+
};
|
|
3368
|
+
console.log(top);
|
|
3369
|
+
console.log(chalk7.dim("\u2502 ") + chalk7.bold("AI Mode".padEnd(W - 4)) + chalk7.dim(" \u2502"));
|
|
3370
|
+
for (const m of validModes) {
|
|
3371
|
+
const active = m === this.currentMode;
|
|
3372
|
+
const icon = active ? chalk7.green("\u25CF") : chalk7.dim("\u25CB");
|
|
3373
|
+
const name = active ? chalk7.yellow.bold(m) : chalk7.white(m);
|
|
3374
|
+
const descs = {
|
|
3375
|
+
general: "All-purpose coding assistant",
|
|
3376
|
+
frontend: "React, Vue, CSS, TypeScript",
|
|
3377
|
+
backend: "APIs, databases, microservices",
|
|
3378
|
+
security: "OWASP, CVE, penetration testing",
|
|
3379
|
+
devops: "Docker, Kubernetes, CI/CD"
|
|
3380
|
+
};
|
|
3381
|
+
console.log(row(icon, name, descs[m] || ""));
|
|
3469
3382
|
}
|
|
3470
|
-
console.log();
|
|
3471
|
-
console.log(chalk7.dim(
|
|
3383
|
+
console.log(bottom);
|
|
3384
|
+
console.log(chalk7.dim(" Usage: /mode <name>"));
|
|
3472
3385
|
return;
|
|
3473
3386
|
}
|
|
3474
3387
|
const mode = args.toLowerCase();
|
|
@@ -3478,124 +3391,111 @@ ${recent[recent.length - 1].content}`;
|
|
|
3478
3391
|
}
|
|
3479
3392
|
this.currentMode = mode;
|
|
3480
3393
|
this.options.mode = mode;
|
|
3481
|
-
|
|
3394
|
+
console.log();
|
|
3395
|
+
console.log(` ${chalk7.green("\u2713")} Mode \u2192 ${chalk7.yellow.bold(mode)}`);
|
|
3482
3396
|
}
|
|
3483
3397
|
async cmdModel(args) {
|
|
3484
3398
|
if (!args) {
|
|
3399
|
+
const current = this.currentModel || "auto";
|
|
3485
3400
|
console.log();
|
|
3486
|
-
|
|
3487
|
-
console.log(
|
|
3488
|
-
console.log(chalk7.dim(` Usage: /model <name> | /model auto | /models to list all`));
|
|
3401
|
+
console.log(` ${chalk7.bold("Current model:")} ${chalk7.cyan(current)}`);
|
|
3402
|
+
console.log(chalk7.dim(" /model <name> \xB7 /model auto \xB7 /models to list all"));
|
|
3489
3403
|
return;
|
|
3490
3404
|
}
|
|
3491
3405
|
if (args === "auto") {
|
|
3492
3406
|
this.currentModel = null;
|
|
3493
3407
|
this.options.model = void 0;
|
|
3494
|
-
logger.success("Model
|
|
3408
|
+
logger.success("Model \u2192 auto");
|
|
3495
3409
|
return;
|
|
3496
3410
|
}
|
|
3497
3411
|
this.currentModel = args;
|
|
3498
3412
|
this.options.model = args;
|
|
3499
|
-
|
|
3413
|
+
console.log();
|
|
3414
|
+
console.log(` ${chalk7.green("\u2713")} Model \u2192 ${chalk7.cyan.bold(args)}`);
|
|
3500
3415
|
}
|
|
3501
3416
|
async cmdModels() {
|
|
3502
|
-
console.log();
|
|
3503
3417
|
if (this.isDemo) {
|
|
3504
3418
|
const table = new Table3({
|
|
3505
3419
|
head: [
|
|
3506
3420
|
chalk7.bold("Model"),
|
|
3507
3421
|
chalk7.bold("Domain"),
|
|
3508
3422
|
chalk7.bold("Status"),
|
|
3509
|
-
chalk7.bold("
|
|
3423
|
+
chalk7.bold("Plan"),
|
|
3510
3424
|
chalk7.bold("Context"),
|
|
3511
3425
|
chalk7.bold("Speed")
|
|
3512
3426
|
],
|
|
3513
|
-
|
|
3427
|
+
style: { head: [], border: ["dim"] }
|
|
3514
3428
|
});
|
|
3515
3429
|
for (const m of DEMO_MODELS) {
|
|
3516
|
-
const
|
|
3517
|
-
const
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
statusColor(m.status),
|
|
3522
|
-
planColor(m.min_plan),
|
|
3523
|
-
`${(m.context_window / 1024).toFixed(0)}k`,
|
|
3524
|
-
`${m.tokens_per_sec} tok/s`
|
|
3525
|
-
]);
|
|
3430
|
+
const active = m.name === (this.currentModel || "");
|
|
3431
|
+
const nameStr = active ? chalk7.cyan.bold(m.display_name + " \u25CF") : m.display_name;
|
|
3432
|
+
const statusBadge = m.status === "active" ? chalk7.green("active") : chalk7.yellow("beta");
|
|
3433
|
+
const planBadge = m.min_plan === "free" ? chalk7.green("free") : chalk7.cyan("pro");
|
|
3434
|
+
table.push([nameStr, chalk7.yellow(m.domain), statusBadge, planBadge, `${(m.context_window / 1024).toFixed(0)}k`, `${m.tokens_per_sec} t/s`]);
|
|
3526
3435
|
}
|
|
3527
3436
|
console.log(table.toString());
|
|
3528
|
-
console.log();
|
|
3529
|
-
console.log(chalk7.dim(` Set a model: /model devwing-backend-1 | /model auto`));
|
|
3437
|
+
console.log(chalk7.dim(" /model <name> to select \xB7 /model auto for automatic"));
|
|
3530
3438
|
} else {
|
|
3531
3439
|
try {
|
|
3532
3440
|
const models = await apiClient.getModels();
|
|
3533
|
-
if (models.length
|
|
3441
|
+
if (!models.length) {
|
|
3534
3442
|
logger.info("No models available");
|
|
3535
3443
|
return;
|
|
3536
3444
|
}
|
|
3537
|
-
const table = new Table3({
|
|
3538
|
-
|
|
3539
|
-
});
|
|
3540
|
-
for (const m of models) {
|
|
3541
|
-
table.push([m.display_name || m.name, m.domain, m.status, m.min_plan]);
|
|
3542
|
-
}
|
|
3445
|
+
const table = new Table3({ head: [chalk7.bold("Name"), chalk7.bold("Domain"), chalk7.bold("Status"), chalk7.bold("Plan")] });
|
|
3446
|
+
for (const m of models) table.push([m.display_name || m.name, m.domain, m.status, m.min_plan]);
|
|
3543
3447
|
console.log(table.toString());
|
|
3544
|
-
} catch (
|
|
3545
|
-
logger.error("Failed to fetch models: " +
|
|
3448
|
+
} catch (e) {
|
|
3449
|
+
logger.error("Failed to fetch models: " + e.message);
|
|
3546
3450
|
}
|
|
3547
3451
|
}
|
|
3548
3452
|
}
|
|
3549
3453
|
async cmdUsage() {
|
|
3550
|
-
console.log();
|
|
3551
3454
|
if (this.isDemo) {
|
|
3552
|
-
console.log(chalk7.bold(" Token Usage"));
|
|
3553
|
-
console.log();
|
|
3554
3455
|
const table = new Table3({
|
|
3555
|
-
head: [chalk7.bold("Period"), chalk7.bold("Requests"), chalk7.bold("Tokens In"), chalk7.bold("Tokens Out"), chalk7.bold("Cost")]
|
|
3456
|
+
head: [chalk7.bold("Period"), chalk7.bold("Requests"), chalk7.bold("Tokens In"), chalk7.bold("Tokens Out"), chalk7.bold("Cost")],
|
|
3457
|
+
style: { head: [], border: ["dim"] }
|
|
3556
3458
|
});
|
|
3557
3459
|
table.push(
|
|
3558
|
-
["Today", DEMO_USAGE.today.requests
|
|
3559
|
-
["This Week", DEMO_USAGE.week.requests
|
|
3560
|
-
["This Month", DEMO_USAGE.month.requests
|
|
3460
|
+
["Today", String(DEMO_USAGE.today.requests), DEMO_USAGE.today.tokens_in.toLocaleString(), DEMO_USAGE.today.tokens_out.toLocaleString(), `$${DEMO_USAGE.today.cost.toFixed(4)}`],
|
|
3461
|
+
["This Week", String(DEMO_USAGE.week.requests), DEMO_USAGE.week.tokens_in.toLocaleString(), DEMO_USAGE.week.tokens_out.toLocaleString(), `$${DEMO_USAGE.week.cost.toFixed(4)}`],
|
|
3462
|
+
["This Month", String(DEMO_USAGE.month.requests), DEMO_USAGE.month.tokens_in.toLocaleString(), DEMO_USAGE.month.tokens_out.toLocaleString(), `$${DEMO_USAGE.month.cost.toFixed(4)}`]
|
|
3561
3463
|
);
|
|
3562
3464
|
console.log(table.toString());
|
|
3563
|
-
console.log();
|
|
3564
3465
|
const used = DEMO_USER2.tokens_used_today;
|
|
3565
3466
|
const limit = 5e5;
|
|
3566
3467
|
const pct = Math.round(used / limit * 100);
|
|
3567
|
-
const
|
|
3568
|
-
const filled = Math.round(pct / 100 *
|
|
3569
|
-
const bar = chalk7.cyan("\u2588".repeat(filled)) + chalk7.dim("\u2591".repeat(
|
|
3570
|
-
console.log(` Daily Quota: ${bar} ${pct}% (${used.toLocaleString()} / ${limit.toLocaleString()})`);
|
|
3468
|
+
const barW = 32;
|
|
3469
|
+
const filled = Math.round(pct / 100 * barW);
|
|
3470
|
+
const bar = chalk7.cyan("\u2588".repeat(filled)) + chalk7.dim("\u2591".repeat(barW - filled));
|
|
3571
3471
|
console.log();
|
|
3572
|
-
console.log(chalk7.bold("
|
|
3472
|
+
console.log(` Daily Quota ${bar} ${chalk7.bold(pct + "%")} ${chalk7.dim(`${used.toLocaleString()} / ${limit.toLocaleString()} tokens`)}`);
|
|
3573
3473
|
console.log();
|
|
3574
|
-
|
|
3575
|
-
|
|
3474
|
+
console.log(chalk7.bold(" By Model"));
|
|
3475
|
+
const mt = new Table3({
|
|
3476
|
+
head: [chalk7.bold("Model"), chalk7.bold("Requests"), chalk7.bold("Tokens"), chalk7.bold("Cost")],
|
|
3477
|
+
style: { head: [], border: ["dim"] }
|
|
3576
3478
|
});
|
|
3577
|
-
|
|
3479
|
+
mt.push(
|
|
3578
3480
|
["devwing-backend-1", "312", "421,000", "$1.4721"],
|
|
3579
3481
|
["devwing-security-1", "145", "198,500", "$0.6948"],
|
|
3580
3482
|
["devwing-general-1", "98", "132,200", "$0.4627"],
|
|
3581
3483
|
["devwing-frontend-1", "42", "56,800", "$0.1988"],
|
|
3582
3484
|
["devwing-devops-1", "15", "15,600", "$0.1728"]
|
|
3583
3485
|
);
|
|
3584
|
-
console.log(
|
|
3486
|
+
console.log(mt.toString());
|
|
3585
3487
|
} else {
|
|
3586
3488
|
try {
|
|
3587
3489
|
const usage = await apiClient.getUsage();
|
|
3588
|
-
console.log(`
|
|
3589
|
-
console.log(` Tokens
|
|
3590
|
-
console.log(` Tokens Out: ${usage.total_tokens_out.toLocaleString()}`);
|
|
3490
|
+
console.log(` Requests: ${usage.total_requests}`);
|
|
3491
|
+
console.log(` Tokens: ${usage.total_tokens_in.toLocaleString()} in, ${usage.total_tokens_out.toLocaleString()} out`);
|
|
3591
3492
|
console.log(` Cost: $${usage.total_cost_usd.toFixed(4)}`);
|
|
3592
|
-
} catch (
|
|
3593
|
-
logger.error("Failed to fetch usage: " +
|
|
3493
|
+
} catch (e) {
|
|
3494
|
+
logger.error("Failed to fetch usage: " + e.message);
|
|
3594
3495
|
}
|
|
3595
3496
|
}
|
|
3596
3497
|
}
|
|
3597
3498
|
async cmdPlans() {
|
|
3598
|
-
console.log();
|
|
3599
3499
|
const table = new Table3({
|
|
3600
3500
|
head: [
|
|
3601
3501
|
chalk7.bold("Plan"),
|
|
@@ -3605,102 +3505,100 @@ ${recent[recent.length - 1].content}`;
|
|
|
3605
3505
|
chalk7.bold("Projects"),
|
|
3606
3506
|
chalk7.bold("Seats")
|
|
3607
3507
|
],
|
|
3608
|
-
|
|
3508
|
+
style: { head: [], border: ["dim"] }
|
|
3609
3509
|
});
|
|
3510
|
+
const currentPlan = this.userProfile?.subscription_plan?.toLowerCase() || "";
|
|
3610
3511
|
for (const plan of DEMO_PLANS) {
|
|
3611
|
-
const
|
|
3612
|
-
const nameStr =
|
|
3512
|
+
const isCurrent = this.isAuthenticated && currentPlan === plan.name.toLowerCase();
|
|
3513
|
+
const nameStr = isCurrent ? chalk7.cyan.bold(plan.name) + chalk7.dim(" \u2190") : plan.name;
|
|
3613
3514
|
table.push([nameStr, plan.price, plan.tokens_day, plan.models, plan.projects, plan.seats]);
|
|
3614
3515
|
}
|
|
3615
3516
|
console.log(table.toString());
|
|
3616
3517
|
console.log();
|
|
3617
3518
|
if (this.isAuthenticated) {
|
|
3618
|
-
|
|
3619
|
-
console.log(chalk7.dim(` Your plan: ${currentPlan.toUpperCase()}. Upgrade at https://devwing.ai/dashboard/billing`));
|
|
3519
|
+
console.log(chalk7.dim(` Your plan: ${currentPlan.toUpperCase()} \xB7 Upgrade at devwing.ai/dashboard/billing`));
|
|
3620
3520
|
} else {
|
|
3621
|
-
console.log(chalk7.dim(" Sign up at
|
|
3521
|
+
console.log(chalk7.dim(" Sign up at devwing.ai"));
|
|
3622
3522
|
}
|
|
3623
3523
|
}
|
|
3624
3524
|
async cmdContext() {
|
|
3625
|
-
console.log();
|
|
3626
3525
|
if (this.isDemo) {
|
|
3627
|
-
const
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
"
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
console.log(
|
|
3526
|
+
const W = 58;
|
|
3527
|
+
const top = chalk7.dim("\u256D" + "\u2500".repeat(W - 2) + "\u256E");
|
|
3528
|
+
const bottom = chalk7.dim("\u2570" + "\u2500".repeat(W - 2) + "\u256F");
|
|
3529
|
+
const div = chalk7.dim("\u251C" + "\u2500".repeat(W - 2) + "\u2524");
|
|
3530
|
+
const row = (k, v) => {
|
|
3531
|
+
const rawV = v.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3532
|
+
const pad = W - 4 - k.length - rawV.length;
|
|
3533
|
+
return chalk7.dim("\u2502 ") + chalk7.bold(k) + " ".repeat(Math.max(0, pad)) + v + chalk7.dim(" \u2502");
|
|
3534
|
+
};
|
|
3535
|
+
const fileRow = (f) => {
|
|
3536
|
+
const pad = W - 4 - 2 - f.length;
|
|
3537
|
+
return chalk7.dim("\u2502 ") + chalk7.dim("\xB7") + " " + chalk7.cyan(f) + " ".repeat(Math.max(0, pad)) + chalk7.dim("\u2502");
|
|
3538
|
+
};
|
|
3539
|
+
const textRow = (t) => {
|
|
3540
|
+
const pad = W - 4 - t.length;
|
|
3541
|
+
return chalk7.dim("\u2502 ") + t + " ".repeat(Math.max(0, pad)) + chalk7.dim(" \u2502");
|
|
3542
|
+
};
|
|
3543
|
+
console.log(top);
|
|
3544
|
+
console.log(row("Directory", chalk7.cyan(process.cwd().replace(process.env.HOME || "", "~"))));
|
|
3545
|
+
console.log(row("Git Branch", "main"));
|
|
3546
|
+
console.log(row("Files Loaded", "34"));
|
|
3547
|
+
console.log(row("Framework", "FastAPI + TypeScript"));
|
|
3548
|
+
console.log(row("Shell", process.env.SHELL?.split("/").pop() || "unknown"));
|
|
3549
|
+
console.log(div);
|
|
3550
|
+
console.log(textRow(chalk7.bold("Top files in context")));
|
|
3551
|
+
const files = ["src/auth/auth_controller.ts", "src/middleware/jwt.middleware.ts", "src/services/user_service.ts", "src/auth/repositories/user.repository.ts", "package.json", "docker-compose.yml"];
|
|
3552
|
+
for (const f of files) console.log(fileRow(f));
|
|
3553
|
+
console.log(textRow(chalk7.dim("... and 28 more")));
|
|
3554
|
+
console.log(bottom);
|
|
3654
3555
|
} else if (this.sessionContext) {
|
|
3655
|
-
console.log(`
|
|
3656
|
-
console.log(`
|
|
3657
|
-
console.log(` Files: ${this.sessionContext.files.length}`);
|
|
3658
|
-
if (this.sessionContext.git_branch) {
|
|
3659
|
-
console.log(` Git Branch: ${this.sessionContext.git_branch}`);
|
|
3660
|
-
}
|
|
3556
|
+
console.log(` Dir: ${chalk7.cyan(this.sessionContext.cwd)} \xB7 Shell: ${this.sessionContext.shell} \xB7 Files: ${this.sessionContext.files.length}`);
|
|
3557
|
+
if (this.sessionContext.git_branch) console.log(` Branch: ${this.sessionContext.git_branch}`);
|
|
3661
3558
|
console.log();
|
|
3662
|
-
console.log(chalk7.bold(" Files in context:"));
|
|
3663
3559
|
for (const f of this.sessionContext.files.slice(0, 10)) {
|
|
3664
|
-
console.log(`
|
|
3560
|
+
console.log(` ${chalk7.dim("\xB7")} ${chalk7.cyan(f.path)}`);
|
|
3665
3561
|
}
|
|
3666
3562
|
if (this.sessionContext.files.length > 10) {
|
|
3667
|
-
console.log(chalk7.dim(`
|
|
3563
|
+
console.log(chalk7.dim(` ... and ${this.sessionContext.files.length - 10} more`));
|
|
3668
3564
|
}
|
|
3669
3565
|
} else {
|
|
3670
3566
|
logger.info("No context loaded yet. Send a message to load context.");
|
|
3671
3567
|
}
|
|
3672
3568
|
}
|
|
3673
3569
|
async cmdHistory() {
|
|
3674
|
-
|
|
3675
|
-
if (this.conversationHistory.length === 0) {
|
|
3570
|
+
if (!this.conversationHistory.length) {
|
|
3676
3571
|
logger.info("No conversation history yet.");
|
|
3677
3572
|
return;
|
|
3678
3573
|
}
|
|
3574
|
+
console.log();
|
|
3679
3575
|
for (const msg of this.conversationHistory.slice(-20)) {
|
|
3680
|
-
const label = msg.role === "user" ? chalk7.green.bold("You") : chalk7.cyan.bold("DevWing");
|
|
3576
|
+
const label = msg.role === "user" ? chalk7.green.bold("You ") : chalk7.cyan.bold("DevWing ");
|
|
3681
3577
|
const time = chalk7.dim(msg.timestamp.toLocaleTimeString());
|
|
3682
|
-
const preview = msg.content.length >
|
|
3683
|
-
console.log(` ${time}
|
|
3578
|
+
const preview = msg.content.length > 100 ? msg.content.substring(0, 100) + "\u2026" : msg.content;
|
|
3579
|
+
console.log(` ${time} ${label} ${preview}`);
|
|
3684
3580
|
}
|
|
3685
3581
|
}
|
|
3686
3582
|
async cmdConfig(args) {
|
|
3687
3583
|
if (!args) {
|
|
3688
|
-
console.log();
|
|
3689
3584
|
const config = configManager.getAll();
|
|
3690
|
-
const
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
);
|
|
3701
|
-
console.log(
|
|
3702
|
-
console.log();
|
|
3703
|
-
console.log(chalk7.dim(
|
|
3585
|
+
const W = 56;
|
|
3586
|
+
const top = chalk7.dim("\u256D" + "\u2500".repeat(W - 2) + "\u256E");
|
|
3587
|
+
const bottom = chalk7.dim("\u2570" + "\u2500".repeat(W - 2) + "\u256F");
|
|
3588
|
+
const row = (k, v) => {
|
|
3589
|
+
const rawV = v.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3590
|
+
const pad = W - 4 - k.length - rawV.length;
|
|
3591
|
+
return chalk7.dim("\u2502 ") + chalk7.bold(k) + " ".repeat(Math.max(0, pad)) + v + chalk7.dim(" \u2502");
|
|
3592
|
+
};
|
|
3593
|
+
console.log(top);
|
|
3594
|
+
console.log(row("API URL", chalk7.dim(config.apiUrl || "default")));
|
|
3595
|
+
console.log(row("Workspace", chalk7.dim(config.workspaceId || "none")));
|
|
3596
|
+
console.log(row("Project", chalk7.dim(config.projectId || "none")));
|
|
3597
|
+
console.log(row("Model", chalk7.dim(config.model || "auto")));
|
|
3598
|
+
console.log(row("Mode", chalk7.dim(config.mode || "general")));
|
|
3599
|
+
console.log(row("Config", chalk7.dim(configManager.getPath())));
|
|
3600
|
+
console.log(bottom);
|
|
3601
|
+
console.log(chalk7.dim(" /config set <key> <value> \xB7 /config get <key>"));
|
|
3704
3602
|
return;
|
|
3705
3603
|
}
|
|
3706
3604
|
const parts = args.split(/\s+/);
|