devwing 0.1.21 → 0.1.23
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 +399 -601
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,7 +22,6 @@ import util from 'util';
|
|
|
22
22
|
import Table3 from 'cli-table3';
|
|
23
23
|
import { fileURLToPath } from 'url';
|
|
24
24
|
import semver from 'semver';
|
|
25
|
-
import readline from 'readline';
|
|
26
25
|
|
|
27
26
|
var SERVICE_NAME = "DevWing CLI";
|
|
28
27
|
var API_KEY_ACCOUNT = "api-key";
|
|
@@ -2772,7 +2771,7 @@ function isDemoMode() {
|
|
|
2772
2771
|
}
|
|
2773
2772
|
var __sessionFile = fileURLToPath(import.meta.url);
|
|
2774
2773
|
var __sessionDir = dirname(__sessionFile);
|
|
2775
|
-
var sleep2 = (ms) => new Promise((
|
|
2774
|
+
var sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
2776
2775
|
function getVersion() {
|
|
2777
2776
|
const paths = [
|
|
2778
2777
|
join(__sessionDir, "../package.json"),
|
|
@@ -2787,10 +2786,10 @@ function getVersion() {
|
|
|
2787
2786
|
continue;
|
|
2788
2787
|
}
|
|
2789
2788
|
}
|
|
2790
|
-
return "0.1.
|
|
2789
|
+
return "0.1.23";
|
|
2791
2790
|
}
|
|
2792
2791
|
var DEMO_USER2 = {
|
|
2793
|
-
id: "usr_a1b2c3d4
|
|
2792
|
+
id: "usr_a1b2c3d4",
|
|
2794
2793
|
email: "aliyu@devwing.ai",
|
|
2795
2794
|
full_name: "Aliyu Mohammed",
|
|
2796
2795
|
subscription_plan: "pro",
|
|
@@ -2801,22 +2800,19 @@ var DEMO_USER2 = {
|
|
|
2801
2800
|
tokens_used_today: 47832,
|
|
2802
2801
|
tokens_reset_at: "2026-04-10T00:00:00Z"
|
|
2803
2802
|
};
|
|
2804
|
-
var DEMO_WORKSPACE2 = {
|
|
2805
|
-
|
|
2806
|
-
plan: "enterprise"};
|
|
2807
|
-
var DEMO_PROJECT2 = {
|
|
2808
|
-
name: "Tallon SaaS ERP"};
|
|
2803
|
+
var DEMO_WORKSPACE2 = { name: "Kano State Government"};
|
|
2804
|
+
var DEMO_PROJECT2 = { name: "Tallon SaaS ERP"};
|
|
2809
2805
|
var DEMO_MODELS = [
|
|
2810
|
-
{ name: "devwing-general-1", display_name: "DevWing General", domain: "general", status: "active", min_plan: "free", context_window: 32768, tokens_per_sec: 85
|
|
2811
|
-
{ name: "devwing-frontend-1", display_name: "DevWing Frontend", domain: "frontend", status: "active", min_plan: "pro", context_window: 32768, tokens_per_sec: 78
|
|
2812
|
-
{ name: "devwing-backend-1", display_name: "DevWing Backend", domain: "backend", status: "active", min_plan: "pro", context_window: 32768, tokens_per_sec: 82
|
|
2813
|
-
{ name: "devwing-security-1", display_name: "DevWing Security", domain: "security", status: "active", min_plan: "pro", context_window: 32768, tokens_per_sec: 74
|
|
2814
|
-
{ name: "devwing-devops-1", display_name: "DevWing DevOps", domain: "devops", status: "beta", min_plan: "pro", context_window: 32768, tokens_per_sec: 70
|
|
2815
|
-
{ name: "devwing-mobile-1", display_name: "DevWing Mobile", domain: "
|
|
2816
|
-
{ name: "devwing-data-1", display_name: "DevWing Data", domain: "
|
|
2806
|
+
{ name: "devwing-general-1", display_name: "DevWing General", domain: "general", status: "active", min_plan: "free", context_window: 32768, tokens_per_sec: 85 },
|
|
2807
|
+
{ name: "devwing-frontend-1", display_name: "DevWing Frontend", domain: "frontend", status: "active", min_plan: "pro", context_window: 32768, tokens_per_sec: 78 },
|
|
2808
|
+
{ name: "devwing-backend-1", display_name: "DevWing Backend", domain: "backend", status: "active", min_plan: "pro", context_window: 32768, tokens_per_sec: 82 },
|
|
2809
|
+
{ name: "devwing-security-1", display_name: "DevWing Security", domain: "security", status: "active", min_plan: "pro", context_window: 32768, tokens_per_sec: 74 },
|
|
2810
|
+
{ name: "devwing-devops-1", display_name: "DevWing DevOps", domain: "devops", status: "beta", min_plan: "pro", context_window: 32768, tokens_per_sec: 70 },
|
|
2811
|
+
{ name: "devwing-mobile-1", display_name: "DevWing Mobile", domain: "mobile", status: "beta", min_plan: "pro", context_window: 32768, tokens_per_sec: 72 },
|
|
2812
|
+
{ name: "devwing-data-1", display_name: "DevWing Data", domain: "data", status: "beta", min_plan: "pro", context_window: 32768, tokens_per_sec: 68 }
|
|
2817
2813
|
];
|
|
2818
2814
|
var DEMO_PLANS = [
|
|
2819
|
-
{ name: "Free", price: "$0", tokens_day: "50,000", models: "General only", projects: "1", seats: "1" },
|
|
2815
|
+
{ name: "Free", price: "$0/mo", tokens_day: "50,000", models: "General only", projects: "1", seats: "1" },
|
|
2820
2816
|
{ name: "Pro", price: "$19/mo", tokens_day: "500,000", models: "All models", projects: "10", seats: "1" },
|
|
2821
2817
|
{ name: "Team", price: "$99/mo", tokens_day: "2,000,000", models: "All + priority", projects: "Unlimited", seats: "5 included" },
|
|
2822
2818
|
{ name: "Enterprise", price: "Custom", tokens_day: "Unlimited", models: "Dedicated", projects: "Unlimited", seats: "Unlimited" }
|
|
@@ -2826,6 +2822,65 @@ var DEMO_USAGE = {
|
|
|
2826
2822
|
week: { requests: 147, tokens_in: 198340, tokens_out: 102890, cost: 0.7213 },
|
|
2827
2823
|
month: { requests: 612, tokens_in: 824100, tokens_out: 428750, cost: 3.0012 }
|
|
2828
2824
|
};
|
|
2825
|
+
function readLine() {
|
|
2826
|
+
return new Promise((resolve) => {
|
|
2827
|
+
try {
|
|
2828
|
+
if (typeof process.stdin.setRawMode === "function") {
|
|
2829
|
+
process.stdin.setRawMode(false);
|
|
2830
|
+
}
|
|
2831
|
+
} catch {
|
|
2832
|
+
}
|
|
2833
|
+
process.stdin.resume();
|
|
2834
|
+
process.stdin.setEncoding("utf8");
|
|
2835
|
+
let buf = "";
|
|
2836
|
+
const onData = (chunk) => {
|
|
2837
|
+
for (const ch of chunk) {
|
|
2838
|
+
if (ch === "\n" || ch === "\r") {
|
|
2839
|
+
cleanup();
|
|
2840
|
+
resolve(buf);
|
|
2841
|
+
return;
|
|
2842
|
+
} else if (ch === "") {
|
|
2843
|
+
cleanup();
|
|
2844
|
+
resolve("");
|
|
2845
|
+
return;
|
|
2846
|
+
} else if (ch === "\x7F" || ch === "\b") {
|
|
2847
|
+
if (buf.length > 0) {
|
|
2848
|
+
buf = buf.slice(0, -1);
|
|
2849
|
+
process.stdout.write("\b \b");
|
|
2850
|
+
}
|
|
2851
|
+
} else if (ch >= " ") {
|
|
2852
|
+
buf += ch;
|
|
2853
|
+
process.stdout.write(ch);
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
};
|
|
2857
|
+
const onEnd = () => {
|
|
2858
|
+
cleanup();
|
|
2859
|
+
resolve("");
|
|
2860
|
+
};
|
|
2861
|
+
const cleanup = () => {
|
|
2862
|
+
process.stdin.removeListener("data", onData);
|
|
2863
|
+
process.stdin.removeListener("end", onEnd);
|
|
2864
|
+
process.stdin.pause();
|
|
2865
|
+
};
|
|
2866
|
+
process.stdin.on("data", onData);
|
|
2867
|
+
process.stdin.once("end", onEnd);
|
|
2868
|
+
});
|
|
2869
|
+
}
|
|
2870
|
+
function restoreStdin() {
|
|
2871
|
+
try {
|
|
2872
|
+
if (typeof process.stdin.setRawMode === "function") {
|
|
2873
|
+
try {
|
|
2874
|
+
process.stdin.setRawMode(false);
|
|
2875
|
+
} catch {
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
process.stdin.removeAllListeners("keypress");
|
|
2879
|
+
process.stdin.removeAllListeners("data");
|
|
2880
|
+
if (process.stdin.isPaused()) process.stdin.resume();
|
|
2881
|
+
} catch {
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2829
2884
|
var InteractiveSession = class {
|
|
2830
2885
|
isAuthenticated = false;
|
|
2831
2886
|
userProfile = null;
|
|
@@ -2836,13 +2891,10 @@ var InteractiveSession = class {
|
|
|
2836
2891
|
sessionId = null;
|
|
2837
2892
|
isDemo;
|
|
2838
2893
|
options;
|
|
2839
|
-
rl;
|
|
2840
2894
|
commands = /* @__PURE__ */ new Map();
|
|
2841
|
-
sigintCount = 0;
|
|
2842
|
-
sigintTimer = null;
|
|
2843
2895
|
version;
|
|
2844
|
-
|
|
2845
|
-
|
|
2896
|
+
running = true;
|
|
2897
|
+
ctrlCCount = 0;
|
|
2846
2898
|
constructor(options) {
|
|
2847
2899
|
this.options = options;
|
|
2848
2900
|
this.isDemo = isDemoMode();
|
|
@@ -2851,97 +2903,48 @@ var InteractiveSession = class {
|
|
|
2851
2903
|
if (options.model) this.currentModel = options.model;
|
|
2852
2904
|
this.registerCommands();
|
|
2853
2905
|
}
|
|
2854
|
-
//
|
|
2855
|
-
// START
|
|
2856
|
-
// ============================================================
|
|
2906
|
+
// ─── START ───────────────────────────────────────────────
|
|
2857
2907
|
async start() {
|
|
2858
2908
|
console.clear();
|
|
2859
|
-
this.
|
|
2860
|
-
await this.
|
|
2909
|
+
this.printBanner();
|
|
2910
|
+
await this.checkAuth();
|
|
2861
2911
|
this.printSystemInfo();
|
|
2862
|
-
this.createReadline();
|
|
2863
2912
|
console.log();
|
|
2864
|
-
this.
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
if (this.sigintCount >= 2) {
|
|
2880
|
-
this.exitSession();
|
|
2881
|
-
return;
|
|
2913
|
+
while (this.running) {
|
|
2914
|
+
this.printPrompt();
|
|
2915
|
+
const input = await readLine();
|
|
2916
|
+
process.stdout.write("\n");
|
|
2917
|
+
if (input === "") {
|
|
2918
|
+
this.ctrlCCount++;
|
|
2919
|
+
if (this.ctrlCCount >= 2) {
|
|
2920
|
+
this.exit();
|
|
2921
|
+
return;
|
|
2922
|
+
}
|
|
2923
|
+
console.log(chalk7.dim(" Press Ctrl+C again to exit, or type /exit"));
|
|
2924
|
+
setTimeout(() => {
|
|
2925
|
+
this.ctrlCCount = 0;
|
|
2926
|
+
}, 1500);
|
|
2927
|
+
continue;
|
|
2882
2928
|
}
|
|
2883
|
-
|
|
2884
|
-
this.sigintTimer = setTimeout(() => {
|
|
2885
|
-
this.sigintCount = 0;
|
|
2886
|
-
}, 1500);
|
|
2887
|
-
this.rl.prompt();
|
|
2888
|
-
});
|
|
2889
|
-
const currentRl = this.rl;
|
|
2890
|
-
this.rl.on("line", async (input) => {
|
|
2891
|
-
if (this.isBusy) return;
|
|
2929
|
+
this.ctrlCCount = 0;
|
|
2892
2930
|
const trimmed = input.trim();
|
|
2893
|
-
if (!trimmed)
|
|
2894
|
-
this.rl.prompt();
|
|
2895
|
-
return;
|
|
2896
|
-
}
|
|
2897
|
-
this.isBusy = true;
|
|
2931
|
+
if (!trimmed) continue;
|
|
2898
2932
|
try {
|
|
2899
2933
|
if (trimmed.startsWith("/")) {
|
|
2900
|
-
await this.
|
|
2901
|
-
return;
|
|
2934
|
+
await this.handleSlash(trimmed);
|
|
2902
2935
|
} else {
|
|
2903
|
-
await this.
|
|
2904
|
-
}
|
|
2905
|
-
} catch (error) {
|
|
2906
|
-
logger.error(error.message || "An error occurred");
|
|
2907
|
-
}
|
|
2908
|
-
this.isBusy = false;
|
|
2909
|
-
if (this.rl === currentRl) {
|
|
2910
|
-
this.rl.setPrompt(this.buildPrompt());
|
|
2911
|
-
this.rl.prompt();
|
|
2912
|
-
}
|
|
2913
|
-
});
|
|
2914
|
-
this.rl.on("close", () => {
|
|
2915
|
-
if (!this.isBusy) {
|
|
2916
|
-
this.exitSession();
|
|
2917
|
-
}
|
|
2918
|
-
});
|
|
2919
|
-
}
|
|
2920
|
-
resetStdin() {
|
|
2921
|
-
try {
|
|
2922
|
-
if (typeof process.stdin.setRawMode === "function") {
|
|
2923
|
-
try {
|
|
2924
|
-
process.stdin.setRawMode(false);
|
|
2925
|
-
} catch {
|
|
2936
|
+
await this.handlePrompt(trimmed);
|
|
2926
2937
|
}
|
|
2938
|
+
} catch (err) {
|
|
2939
|
+
logger.error(err.message || "An error occurred");
|
|
2927
2940
|
}
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
if (process.stdin.isPaused()) {
|
|
2931
|
-
process.stdin.resume();
|
|
2932
|
-
}
|
|
2933
|
-
} catch {
|
|
2941
|
+
restoreStdin();
|
|
2942
|
+
await sleep2(50);
|
|
2934
2943
|
}
|
|
2935
2944
|
}
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
}
|
|
2940
|
-
// ============================================================
|
|
2941
|
-
// STARTUP UI
|
|
2942
|
-
// ============================================================
|
|
2943
|
-
printStartupBanner() {
|
|
2944
|
-
const banner = gradient.pastel.multiline([
|
|
2945
|
+
// ─── BANNER ──────────────────────────────────────────────
|
|
2946
|
+
printBanner() {
|
|
2947
|
+
const art = gradient.pastel.multiline([
|
|
2945
2948
|
"",
|
|
2946
2949
|
" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ",
|
|
2947
2950
|
" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ",
|
|
@@ -2951,101 +2954,81 @@ var InteractiveSession = class {
|
|
|
2951
2954
|
" \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D ",
|
|
2952
2955
|
""
|
|
2953
2956
|
].join("\n"));
|
|
2954
|
-
console.log(
|
|
2955
|
-
console.log(
|
|
2957
|
+
console.log(art);
|
|
2958
|
+
console.log(
|
|
2959
|
+
chalk7.dim(" Your AI Wingman in the Terminal") + " " + chalk7.dim(`v${this.version}`)
|
|
2960
|
+
);
|
|
2956
2961
|
console.log();
|
|
2957
2962
|
}
|
|
2963
|
+
// ─── SYSTEM INFO PANEL ───────────────────────────────────
|
|
2958
2964
|
printSystemInfo() {
|
|
2959
|
-
const
|
|
2960
|
-
|
|
2965
|
+
const W = 62;
|
|
2966
|
+
const ln = (s = "") => {
|
|
2967
|
+
const raw = s.replace(/\x1B\[[0-9;]*m/g, "");
|
|
2968
|
+
const pad = W - 4 - raw.length;
|
|
2969
|
+
return chalk7.dim("\u2502 ") + s + " ".repeat(Math.max(0, pad)) + chalk7.dim(" \u2502");
|
|
2970
|
+
};
|
|
2971
|
+
const div = chalk7.dim("\u251C" + "\u2500".repeat(W - 2) + "\u2524");
|
|
2972
|
+
const top = chalk7.dim("\u256D" + "\u2500".repeat(W - 2) + "\u256E");
|
|
2973
|
+
const bot = chalk7.dim("\u2570" + "\u2500".repeat(W - 2) + "\u256F");
|
|
2974
|
+
const kv = (k, v) => ln(chalk7.bold(k.padEnd(12)) + v);
|
|
2975
|
+
console.log(top);
|
|
2961
2976
|
if (this.isAuthenticated && this.userProfile) {
|
|
2962
2977
|
const name = this.userProfile.full_name || this.userProfile.email;
|
|
2963
2978
|
const plan = (this.userProfile.subscription_plan || "free").toUpperCase();
|
|
2964
|
-
const
|
|
2965
|
-
console.log(
|
|
2966
|
-
` ${chalk7.bold("Auth")} ${chalk7.green("\u25CF")} ${name} ${planColor(`(${plan})`)}`
|
|
2967
|
-
);
|
|
2968
|
-
} else if (this.isAuthenticated) {
|
|
2969
|
-
console.log(
|
|
2970
|
-
` ${chalk7.bold("Auth")} ${chalk7.green("\u25CF")} Authenticated ${chalk7.dim("(offline)")}`
|
|
2971
|
-
);
|
|
2979
|
+
const badge = plan === "PRO" ? chalk7.bgCyan.black(` ${plan} `) : plan === "ENTERPRISE" ? chalk7.bgMagenta.white(` ${plan} `) : plan === "TEAM" ? chalk7.bgYellow.black(` ${plan} `) : chalk7.bgGray.white(` ${plan} `);
|
|
2980
|
+
console.log(ln(chalk7.bold("Auth".padEnd(12)) + chalk7.green("\u25CF ") + chalk7.white(name) + " " + badge));
|
|
2972
2981
|
} else {
|
|
2973
|
-
console.log(
|
|
2974
|
-
` ${chalk7.bold("Auth")} ${chalk7.red("\u25CF")} Not logged in ${chalk7.dim("\u2014 type /login")}`
|
|
2975
|
-
);
|
|
2982
|
+
console.log(ln(chalk7.bold("Auth".padEnd(12)) + chalk7.red("\u25CF ") + chalk7.dim("Not logged in") + " " + chalk7.cyan("/login")));
|
|
2976
2983
|
}
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
console.log(
|
|
2980
|
-
const cwd = process.cwd().replace(process.env.HOME || "", "~");
|
|
2984
|
+
console.log(div);
|
|
2985
|
+
console.log(kv("Mode", chalk7.yellow(this.currentMode) + " " + chalk7.bold("Model".padEnd(8)) + (this.currentModel ? chalk7.cyan(this.currentModel) : chalk7.dim("auto"))));
|
|
2986
|
+
console.log(div);
|
|
2981
2987
|
if (this.isDemo) {
|
|
2982
|
-
console.log(
|
|
2988
|
+
console.log(kv("Project", chalk7.cyan(DEMO_PROJECT2.name)));
|
|
2983
2989
|
} else {
|
|
2984
|
-
const
|
|
2985
|
-
|
|
2986
|
-
console.log(` ${chalk7.bold("Project")} ${projectStr} ${chalk7.bold("CWD")} ${chalk7.dim(cwd)}`);
|
|
2990
|
+
const pid = configManager.getProjectId();
|
|
2991
|
+
console.log(kv("Project", pid ? chalk7.cyan(pid) : chalk7.dim("none")));
|
|
2987
2992
|
}
|
|
2988
|
-
const
|
|
2989
|
-
console.log(
|
|
2993
|
+
const cwd = process.cwd().replace(process.env.HOME || "", "~");
|
|
2994
|
+
console.log(kv("Directory", chalk7.dim(cwd)));
|
|
2990
2995
|
if (this.isDemo) {
|
|
2991
|
-
console.log(
|
|
2996
|
+
console.log(div);
|
|
2997
|
+
console.log(ln(chalk7.yellow("\u25C6 ") + chalk7.yellow("Demo mode") + chalk7.dim(" \u2014 no backend required")));
|
|
2992
2998
|
}
|
|
2993
|
-
console.log(
|
|
2999
|
+
console.log(bot);
|
|
2994
3000
|
console.log();
|
|
2995
|
-
console.log(chalk7.dim(" Type a message to chat
|
|
2996
|
-
}
|
|
2997
|
-
//
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
const
|
|
3002
|
-
|
|
3003
|
-
|
|
3001
|
+
console.log(chalk7.dim(" Type a message to chat, or ") + chalk7.cyan("/help") + chalk7.dim(" for commands."));
|
|
3002
|
+
}
|
|
3003
|
+
// ─── PROMPT LINE ─────────────────────────────────────────
|
|
3004
|
+
printPrompt() {
|
|
3005
|
+
const sep = chalk7.dim("\n " + "\u2500".repeat(50));
|
|
3006
|
+
const icon = chalk7.bold.cyan("\u2B21");
|
|
3007
|
+
const name = chalk7.bold.white("devwing");
|
|
3008
|
+
const mode = chalk7.dim("[") + chalk7.yellow(this.currentMode) + chalk7.dim("]");
|
|
3009
|
+
let user = "";
|
|
3004
3010
|
if (this.isAuthenticated && this.userProfile) {
|
|
3005
|
-
const
|
|
3006
|
-
|
|
3007
|
-
}
|
|
3008
|
-
if (this.isDemo) {
|
|
3009
|
-
parts.push(chalk7.dim.yellow("demo"));
|
|
3011
|
+
const first = (this.userProfile.full_name || this.userProfile.email).split(" ")[0].split("@")[0].toLowerCase();
|
|
3012
|
+
user = " " + chalk7.dim("@") + chalk7.green(first);
|
|
3010
3013
|
}
|
|
3011
|
-
|
|
3014
|
+
const demo = this.isDemo ? chalk7.dim.yellow(" demo") : "";
|
|
3015
|
+
process.stdout.write(`${sep}
|
|
3016
|
+
${icon} ${name} ${mode}${user}${demo}
|
|
3017
|
+
${chalk7.bold.cyan("\u276F")} `);
|
|
3012
3018
|
}
|
|
3013
|
-
//
|
|
3014
|
-
|
|
3015
|
-
// ============================================================
|
|
3016
|
-
completer(line) {
|
|
3017
|
-
if (!line.startsWith("/")) return [[], line];
|
|
3018
|
-
const allNames = [];
|
|
3019
|
-
for (const cmd of this.commands.values()) {
|
|
3020
|
-
allNames.push("/" + cmd.name);
|
|
3021
|
-
for (const alias of cmd.aliases) {
|
|
3022
|
-
allNames.push("/" + alias);
|
|
3023
|
-
}
|
|
3024
|
-
}
|
|
3025
|
-
const hits = allNames.filter((n) => n.startsWith(line));
|
|
3026
|
-
return [hits.length ? hits : allNames, line];
|
|
3027
|
-
}
|
|
3028
|
-
// ============================================================
|
|
3029
|
-
// AUTH CHECK
|
|
3030
|
-
// ============================================================
|
|
3031
|
-
async checkAuthStatus() {
|
|
3019
|
+
// ─── AUTH CHECK ──────────────────────────────────────────
|
|
3020
|
+
async checkAuth() {
|
|
3032
3021
|
try {
|
|
3033
|
-
const
|
|
3022
|
+
const key = await configManager.getApiKey();
|
|
3034
3023
|
if (this.isDemo) {
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
this.userProfile = { ...DEMO_USER2 };
|
|
3038
|
-
} else {
|
|
3039
|
-
this.isAuthenticated = false;
|
|
3040
|
-
this.userProfile = null;
|
|
3041
|
-
}
|
|
3024
|
+
this.isAuthenticated = !!key;
|
|
3025
|
+
this.userProfile = key ? { ...DEMO_USER2 } : null;
|
|
3042
3026
|
return;
|
|
3043
3027
|
}
|
|
3044
|
-
if (!
|
|
3028
|
+
if (!key) return;
|
|
3045
3029
|
try {
|
|
3046
|
-
|
|
3030
|
+
this.userProfile = await apiClient.getProfile();
|
|
3047
3031
|
this.isAuthenticated = true;
|
|
3048
|
-
this.userProfile = profile;
|
|
3049
3032
|
} catch {
|
|
3050
3033
|
this.isAuthenticated = true;
|
|
3051
3034
|
this.userProfile = null;
|
|
@@ -3055,10 +3038,8 @@ var InteractiveSession = class {
|
|
|
3055
3038
|
this.userProfile = null;
|
|
3056
3039
|
}
|
|
3057
3040
|
}
|
|
3058
|
-
//
|
|
3059
|
-
|
|
3060
|
-
// ============================================================
|
|
3061
|
-
async handleSlashCommand(input) {
|
|
3041
|
+
// ─── SLASH COMMAND DISPATCH ──────────────────────────────
|
|
3042
|
+
async handleSlash(input) {
|
|
3062
3043
|
const parts = input.split(/\s+/);
|
|
3063
3044
|
const cmdName = parts[0].substring(1).toLowerCase();
|
|
3064
3045
|
const args = parts.slice(1).join(" ").trim();
|
|
@@ -3070,60 +3051,43 @@ var InteractiveSession = class {
|
|
|
3070
3051
|
}
|
|
3071
3052
|
}
|
|
3072
3053
|
if (!command) {
|
|
3054
|
+
console.log();
|
|
3073
3055
|
logger.warn(`Unknown command: /${cmdName}. Type /help for available commands.`);
|
|
3074
3056
|
return;
|
|
3075
3057
|
}
|
|
3076
3058
|
if (command.requiresAuth && !this.isAuthenticated) {
|
|
3077
|
-
|
|
3059
|
+
console.log();
|
|
3060
|
+
logger.warn("You need to be logged in. Type /login first.");
|
|
3078
3061
|
return;
|
|
3079
3062
|
}
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
try {
|
|
3083
|
-
await command.handler(args);
|
|
3084
|
-
} catch (error) {
|
|
3085
|
-
logger.error(error.message || "Command failed");
|
|
3086
|
-
}
|
|
3087
|
-
this.resetStdin();
|
|
3088
|
-
await sleep2(80);
|
|
3089
|
-
this.recreateReadline();
|
|
3063
|
+
console.log();
|
|
3064
|
+
await command.handler(args);
|
|
3090
3065
|
}
|
|
3091
|
-
//
|
|
3092
|
-
|
|
3093
|
-
// ============================================================
|
|
3094
|
-
async handleAIPrompt(input) {
|
|
3066
|
+
// ─── AI PROMPT ───────────────────────────────────────────
|
|
3067
|
+
async handlePrompt(input) {
|
|
3095
3068
|
if (!this.isAuthenticated) {
|
|
3096
3069
|
console.log();
|
|
3097
|
-
logger.warn("You need to log in
|
|
3070
|
+
logger.warn("You need to log in first. Type /login to authenticate.");
|
|
3098
3071
|
return;
|
|
3099
3072
|
}
|
|
3100
3073
|
console.log();
|
|
3101
3074
|
if (this.isDemo) {
|
|
3102
|
-
this.
|
|
3103
|
-
this.
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
{ role: "user", content: input, timestamp: /* @__PURE__ */ new Date() },
|
|
3108
|
-
{ role: "assistant", content: "[demo response]", timestamp: /* @__PURE__ */ new Date() }
|
|
3109
|
-
);
|
|
3110
|
-
} catch (error) {
|
|
3111
|
-
logger.error(error.message || "Command failed");
|
|
3112
|
-
}
|
|
3113
|
-
this.resetStdin();
|
|
3114
|
-
await sleep2(80);
|
|
3115
|
-
this.recreateReadline();
|
|
3075
|
+
await demoPromptCommand(input, { ...this.options, mode: this.currentMode });
|
|
3076
|
+
this.conversationHistory.push(
|
|
3077
|
+
{ role: "user", content: input, timestamp: /* @__PURE__ */ new Date() },
|
|
3078
|
+
{ role: "assistant", content: "[demo response]", timestamp: /* @__PURE__ */ new Date() }
|
|
3079
|
+
);
|
|
3116
3080
|
return;
|
|
3117
3081
|
}
|
|
3118
3082
|
if (!this.sessionContext) {
|
|
3119
3083
|
logger.startSpinner("Loading codebase context...");
|
|
3120
3084
|
try {
|
|
3121
|
-
const
|
|
3122
|
-
this.sessionContext = await
|
|
3085
|
+
const col = new ContextCollector(process.cwd());
|
|
3086
|
+
this.sessionContext = await col.collect(input);
|
|
3123
3087
|
logger.succeedSpinner(`Context loaded \u2014 ${this.sessionContext.files.length} files`);
|
|
3124
|
-
} catch (
|
|
3088
|
+
} catch (err) {
|
|
3125
3089
|
logger.failSpinner("Failed to load context");
|
|
3126
|
-
logger.error(
|
|
3090
|
+
logger.error(err.message);
|
|
3127
3091
|
return;
|
|
3128
3092
|
}
|
|
3129
3093
|
}
|
|
@@ -3131,8 +3095,8 @@ var InteractiveSession = class {
|
|
|
3131
3095
|
logger.info(chalk7.dim("DevWing is thinking..."));
|
|
3132
3096
|
console.log();
|
|
3133
3097
|
try {
|
|
3134
|
-
const
|
|
3135
|
-
prompt: this.
|
|
3098
|
+
const req = {
|
|
3099
|
+
prompt: this.buildHistory(),
|
|
3136
3100
|
mode: this.currentMode,
|
|
3137
3101
|
model: this.currentModel || void 0,
|
|
3138
3102
|
project_id: this.options.project || configManager.getProjectId(),
|
|
@@ -3140,292 +3104,164 @@ var InteractiveSession = class {
|
|
|
3140
3104
|
stream: true,
|
|
3141
3105
|
max_tokens: 4096
|
|
3142
3106
|
};
|
|
3143
|
-
let
|
|
3107
|
+
let reply = "";
|
|
3144
3108
|
streamingRenderer.reset();
|
|
3145
3109
|
streamingRenderer.clearPendingTools();
|
|
3146
|
-
for await (const
|
|
3147
|
-
await streamingRenderer.processMessage(
|
|
3148
|
-
if (
|
|
3149
|
-
|
|
3150
|
-
}
|
|
3151
|
-
if (message.session_id) {
|
|
3152
|
-
this.sessionId = message.session_id;
|
|
3153
|
-
}
|
|
3110
|
+
for await (const msg of apiClient.streamCompletion(req)) {
|
|
3111
|
+
await streamingRenderer.processMessage(msg);
|
|
3112
|
+
if (msg.type === "token" && msg.content) reply += msg.content;
|
|
3113
|
+
if (msg.session_id) this.sessionId = msg.session_id;
|
|
3154
3114
|
}
|
|
3155
|
-
if (
|
|
3156
|
-
this.conversationHistory.push({ role: "assistant", content:
|
|
3115
|
+
if (reply) {
|
|
3116
|
+
this.conversationHistory.push({ role: "assistant", content: reply, timestamp: /* @__PURE__ */ new Date() });
|
|
3157
3117
|
}
|
|
3158
|
-
const
|
|
3159
|
-
if (
|
|
3118
|
+
const pending = streamingRenderer.getPendingToolCalls();
|
|
3119
|
+
if (pending.length > 0) {
|
|
3160
3120
|
logger.newline();
|
|
3161
|
-
|
|
3162
|
-
const toolResults = await streamingRenderer.executePendingTools();
|
|
3121
|
+
const results = await streamingRenderer.executePendingTools();
|
|
3163
3122
|
if (this.sessionId) {
|
|
3164
|
-
for await (const
|
|
3165
|
-
await streamingRenderer.processMessage(
|
|
3123
|
+
for await (const msg of apiClient.continueCompletion(this.sessionId, results)) {
|
|
3124
|
+
await streamingRenderer.processMessage(msg);
|
|
3166
3125
|
}
|
|
3167
3126
|
}
|
|
3168
3127
|
}
|
|
3169
3128
|
console.log();
|
|
3170
|
-
} catch (
|
|
3171
|
-
logger.error(
|
|
3129
|
+
} catch (err) {
|
|
3130
|
+
logger.error(err.message || "AI request failed");
|
|
3172
3131
|
}
|
|
3173
3132
|
}
|
|
3174
|
-
|
|
3175
|
-
const
|
|
3176
|
-
if (
|
|
3177
|
-
|
|
3178
|
-
}
|
|
3179
|
-
const recent = history.slice(-10);
|
|
3180
|
-
const context = recent.slice(0, -1).map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`).join("\n\n");
|
|
3133
|
+
buildHistory() {
|
|
3134
|
+
const h = this.conversationHistory;
|
|
3135
|
+
if (h.length <= 1) return h[h.length - 1]?.content || "";
|
|
3136
|
+
const recent = h.slice(-10);
|
|
3137
|
+
const ctx = recent.slice(0, -1).map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`).join("\n\n");
|
|
3181
3138
|
return `Previous conversation:
|
|
3182
|
-
${
|
|
3139
|
+
${ctx}
|
|
3183
3140
|
|
|
3184
3141
|
Current question:
|
|
3185
3142
|
${recent[recent.length - 1].content}`;
|
|
3186
3143
|
}
|
|
3187
|
-
//
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
exitSession() {
|
|
3191
|
-
if (this.sigintTimer) clearTimeout(this.sigintTimer);
|
|
3192
|
-
this.resetStdin();
|
|
3144
|
+
// ─── EXIT ────────────────────────────────────────────────
|
|
3145
|
+
exit() {
|
|
3146
|
+
restoreStdin();
|
|
3193
3147
|
console.log();
|
|
3194
|
-
console.log(chalk7.dim(" Goodbye! Happy
|
|
3148
|
+
console.log(chalk7.dim(" Goodbye! Happy shipping."));
|
|
3195
3149
|
console.log();
|
|
3196
3150
|
process.exit(0);
|
|
3197
3151
|
}
|
|
3198
|
-
//
|
|
3199
|
-
// COMMAND REGISTRATION
|
|
3200
|
-
// ============================================================
|
|
3152
|
+
// ─── COMMAND REGISTRATION ────────────────────────────────
|
|
3201
3153
|
registerCommands() {
|
|
3202
|
-
this.
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
});
|
|
3210
|
-
this.
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
});
|
|
3218
|
-
this.
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
requiresAuth: false,
|
|
3224
|
-
handler: async () => this.cmdClear()
|
|
3225
|
-
});
|
|
3226
|
-
this.addCommand({
|
|
3227
|
-
name: "login",
|
|
3228
|
-
aliases: ["signin"],
|
|
3229
|
-
description: "Authenticate with DevWing",
|
|
3230
|
-
category: "session",
|
|
3231
|
-
requiresAuth: false,
|
|
3232
|
-
handler: async () => this.cmdLogin()
|
|
3233
|
-
});
|
|
3234
|
-
this.addCommand({
|
|
3235
|
-
name: "logout",
|
|
3236
|
-
aliases: ["signout"],
|
|
3237
|
-
description: "Clear credentials and log out",
|
|
3238
|
-
category: "session",
|
|
3239
|
-
requiresAuth: true,
|
|
3240
|
-
handler: async () => this.cmdLogout()
|
|
3241
|
-
});
|
|
3242
|
-
this.addCommand({
|
|
3243
|
-
name: "status",
|
|
3244
|
-
aliases: ["whoami"],
|
|
3245
|
-
description: "Show auth status and profile",
|
|
3246
|
-
category: "session",
|
|
3247
|
-
requiresAuth: false,
|
|
3248
|
-
handler: async () => this.cmdStatus()
|
|
3249
|
-
});
|
|
3250
|
-
this.addCommand({
|
|
3251
|
-
name: "scan",
|
|
3252
|
-
aliases: [],
|
|
3253
|
-
description: "Run security vulnerability scan",
|
|
3254
|
-
category: "tools",
|
|
3255
|
-
requiresAuth: true,
|
|
3256
|
-
handler: async () => this.cmdScan()
|
|
3257
|
-
});
|
|
3258
|
-
this.addCommand({
|
|
3259
|
-
name: "review",
|
|
3260
|
-
aliases: [],
|
|
3261
|
-
description: "Perform code review on recent changes",
|
|
3262
|
-
category: "tools",
|
|
3263
|
-
requiresAuth: true,
|
|
3264
|
-
handler: async () => this.cmdReview()
|
|
3265
|
-
});
|
|
3266
|
-
this.addCommand({
|
|
3267
|
-
name: "explain",
|
|
3268
|
-
aliases: [],
|
|
3269
|
-
description: "Explain code, file, or concept",
|
|
3270
|
-
category: "tools",
|
|
3271
|
-
requiresAuth: true,
|
|
3272
|
-
handler: async (args) => this.cmdExplain(args)
|
|
3273
|
-
});
|
|
3274
|
-
this.addCommand({
|
|
3275
|
-
name: "memory",
|
|
3276
|
-
aliases: ["mem"],
|
|
3277
|
-
description: "Manage project memory (save/show/clear)",
|
|
3278
|
-
category: "tools",
|
|
3279
|
-
requiresAuth: true,
|
|
3280
|
-
handler: async (args) => this.cmdMemory(args)
|
|
3281
|
-
});
|
|
3282
|
-
this.addCommand({
|
|
3283
|
-
name: "mode",
|
|
3284
|
-
aliases: [],
|
|
3285
|
-
description: "Show or set AI mode",
|
|
3286
|
-
category: "config",
|
|
3287
|
-
requiresAuth: false,
|
|
3288
|
-
handler: async (args) => this.cmdMode(args)
|
|
3289
|
-
});
|
|
3290
|
-
this.addCommand({
|
|
3291
|
-
name: "model",
|
|
3292
|
-
aliases: [],
|
|
3293
|
-
description: "Show or set AI model",
|
|
3294
|
-
category: "config",
|
|
3295
|
-
requiresAuth: false,
|
|
3296
|
-
handler: async (args) => this.cmdModel(args)
|
|
3297
|
-
});
|
|
3298
|
-
this.addCommand({
|
|
3299
|
-
name: "models",
|
|
3300
|
-
aliases: [],
|
|
3301
|
-
description: "List all available AI models",
|
|
3302
|
-
category: "config",
|
|
3303
|
-
requiresAuth: false,
|
|
3304
|
-
handler: async () => this.cmdModels()
|
|
3305
|
-
});
|
|
3306
|
-
this.addCommand({
|
|
3307
|
-
name: "usage",
|
|
3308
|
-
aliases: ["stats"],
|
|
3309
|
-
description: "Show token usage statistics",
|
|
3310
|
-
category: "config",
|
|
3311
|
-
requiresAuth: true,
|
|
3312
|
-
handler: async () => this.cmdUsage()
|
|
3313
|
-
});
|
|
3314
|
-
this.addCommand({
|
|
3315
|
-
name: "plans",
|
|
3316
|
-
aliases: ["pricing"],
|
|
3317
|
-
description: "Show available plans and pricing",
|
|
3318
|
-
category: "config",
|
|
3319
|
-
requiresAuth: false,
|
|
3320
|
-
handler: async () => this.cmdPlans()
|
|
3321
|
-
});
|
|
3322
|
-
this.addCommand({
|
|
3323
|
-
name: "context",
|
|
3324
|
-
aliases: ["ctx"],
|
|
3325
|
-
description: "Show loaded codebase context",
|
|
3326
|
-
category: "config",
|
|
3327
|
-
requiresAuth: false,
|
|
3328
|
-
handler: async () => this.cmdContext()
|
|
3329
|
-
});
|
|
3330
|
-
this.addCommand({
|
|
3331
|
-
name: "history",
|
|
3332
|
-
aliases: [],
|
|
3333
|
-
description: "Show conversation history",
|
|
3334
|
-
category: "config",
|
|
3335
|
-
requiresAuth: false,
|
|
3336
|
-
handler: async () => this.cmdHistory()
|
|
3337
|
-
});
|
|
3338
|
-
this.addCommand({
|
|
3339
|
-
name: "config",
|
|
3340
|
-
aliases: ["settings"],
|
|
3341
|
-
description: "Show or set CLI configuration",
|
|
3342
|
-
category: "config",
|
|
3343
|
-
requiresAuth: false,
|
|
3344
|
-
handler: async (args) => this.cmdConfig(args)
|
|
3345
|
-
});
|
|
3346
|
-
}
|
|
3347
|
-
addCommand(cmd) {
|
|
3348
|
-
this.commands.set(cmd.name, cmd);
|
|
3349
|
-
}
|
|
3350
|
-
// ============================================================
|
|
3351
|
-
// COMMAND IMPLEMENTATIONS
|
|
3352
|
-
// ============================================================
|
|
3154
|
+
const add = (c) => this.commands.set(c.name, c);
|
|
3155
|
+
add({ name: "help", aliases: ["h", "?"], description: "Show all available commands", category: "session", requiresAuth: false, handler: async () => this.cmdHelp() });
|
|
3156
|
+
add({ name: "exit", aliases: ["quit", "q"], description: "Exit DevWing", category: "session", requiresAuth: false, handler: async () => this.exit() });
|
|
3157
|
+
add({ name: "clear", aliases: ["cls"], description: "Clear screen and reset conversation", category: "session", requiresAuth: false, handler: async () => this.cmdClear() });
|
|
3158
|
+
add({ name: "login", aliases: ["signin"], description: "Authenticate with DevWing", category: "session", requiresAuth: false, handler: async () => this.cmdLogin() });
|
|
3159
|
+
add({ name: "logout", aliases: ["signout"], description: "Clear credentials and log out", category: "session", requiresAuth: true, handler: async () => this.cmdLogout() });
|
|
3160
|
+
add({ name: "status", aliases: ["whoami"], description: "Show auth status and profile", category: "session", requiresAuth: false, handler: async () => this.cmdStatus() });
|
|
3161
|
+
add({ name: "scan", aliases: [], description: "Run security vulnerability scan", category: "tools", requiresAuth: true, handler: async () => this.cmdScan() });
|
|
3162
|
+
add({ name: "review", aliases: [], description: "Perform code review on recent changes", category: "tools", requiresAuth: true, handler: async () => this.cmdReview() });
|
|
3163
|
+
add({ name: "explain", aliases: [], description: "Explain code, file, or concept", category: "tools", requiresAuth: true, handler: async (a) => this.cmdExplain(a) });
|
|
3164
|
+
add({ name: "memory", aliases: ["mem"], description: "Project memory save / show / clear", category: "tools", requiresAuth: true, handler: async (a) => this.cmdMemory(a) });
|
|
3165
|
+
add({ name: "mode", aliases: [], description: "Show or set AI mode", category: "config", requiresAuth: false, handler: async (a) => this.cmdMode(a) });
|
|
3166
|
+
add({ name: "model", aliases: [], description: "Show or set AI model", category: "config", requiresAuth: false, handler: async (a) => this.cmdModel(a) });
|
|
3167
|
+
add({ name: "models", aliases: [], description: "List all available AI models", category: "config", requiresAuth: false, handler: async () => this.cmdModels() });
|
|
3168
|
+
add({ name: "usage", aliases: ["stats"], description: "Show token usage statistics", category: "config", requiresAuth: true, handler: async () => this.cmdUsage() });
|
|
3169
|
+
add({ name: "plans", aliases: ["pricing"], description: "Show available plans and pricing", category: "config", requiresAuth: false, handler: async () => this.cmdPlans() });
|
|
3170
|
+
add({ name: "context", aliases: ["ctx"], description: "Show loaded codebase context", category: "config", requiresAuth: false, handler: async () => this.cmdContext() });
|
|
3171
|
+
add({ name: "history", aliases: [], description: "Show conversation history", category: "config", requiresAuth: false, handler: async () => this.cmdHistory() });
|
|
3172
|
+
add({ name: "config", aliases: ["settings"], description: "Show or set CLI configuration", category: "config", requiresAuth: false, handler: async (a) => this.cmdConfig(a) });
|
|
3173
|
+
}
|
|
3174
|
+
// ─── COMMAND IMPLEMENTATIONS ─────────────────────────────
|
|
3353
3175
|
async cmdHelp() {
|
|
3354
|
-
|
|
3355
|
-
const
|
|
3176
|
+
const W = 62;
|
|
3177
|
+
const top = chalk7.dim("\u256D" + "\u2500".repeat(W - 2) + "\u256E");
|
|
3178
|
+
const bot = chalk7.dim("\u2570" + "\u2500".repeat(W - 2) + "\u256F");
|
|
3179
|
+
const div = chalk7.dim("\u251C" + "\u2500".repeat(W - 2) + "\u2524");
|
|
3180
|
+
const ln = (s = "") => {
|
|
3181
|
+
const raw = s.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3182
|
+
const pad = W - 4 - raw.length;
|
|
3183
|
+
return chalk7.dim("\u2502 ") + s + " ".repeat(Math.max(0, pad)) + chalk7.dim(" \u2502");
|
|
3184
|
+
};
|
|
3185
|
+
console.log(top);
|
|
3186
|
+
console.log(ln(chalk7.bold.white("Commands")));
|
|
3187
|
+
const cats = [
|
|
3356
3188
|
{ key: "session", label: "Session", color: chalk7.bold.green },
|
|
3357
3189
|
{ key: "tools", label: "AI Tools", color: chalk7.bold.magenta },
|
|
3358
3190
|
{ key: "config", label: "Configuration", color: chalk7.bold.yellow }
|
|
3359
3191
|
];
|
|
3360
|
-
const
|
|
3361
|
-
|
|
3362
|
-
|
|
3192
|
+
for (const cat of cats) {
|
|
3193
|
+
console.log(div);
|
|
3194
|
+
console.log(ln(" " + cat.color(cat.label)));
|
|
3363
3195
|
for (const cmd of this.commands.values()) {
|
|
3364
3196
|
if (cmd.category !== cat.key) continue;
|
|
3365
|
-
const
|
|
3366
|
-
|
|
3197
|
+
const cmdStr = chalk7.cyan(("/" + cmd.name).padEnd(13));
|
|
3198
|
+
const descStr = chalk7.dim(cmd.description);
|
|
3199
|
+
const alias = cmd.aliases.length ? chalk7.dim(" \xB7 " + cmd.aliases.map((a) => "/" + a).join(", ")) : "";
|
|
3200
|
+
console.log(ln(" " + cmdStr + " " + descStr + alias));
|
|
3367
3201
|
}
|
|
3368
|
-
lines.push("");
|
|
3369
3202
|
}
|
|
3370
|
-
|
|
3371
|
-
|
|
3203
|
+
console.log(div);
|
|
3204
|
+
console.log(ln(chalk7.dim(" Type any message to chat with DevWing AI")));
|
|
3205
|
+
console.log(bot);
|
|
3372
3206
|
}
|
|
3373
3207
|
async cmdClear() {
|
|
3374
3208
|
this.conversationHistory = [];
|
|
3375
3209
|
this.sessionContext = null;
|
|
3376
3210
|
this.sessionId = null;
|
|
3377
3211
|
console.clear();
|
|
3378
|
-
this.
|
|
3212
|
+
this.printBanner();
|
|
3379
3213
|
this.printSystemInfo();
|
|
3214
|
+
console.log();
|
|
3380
3215
|
}
|
|
3381
3216
|
async cmdLogin() {
|
|
3382
|
-
console.log();
|
|
3383
3217
|
if (this.isDemo) {
|
|
3384
3218
|
await demoLoginCommand({ fromSession: true });
|
|
3385
3219
|
} else {
|
|
3386
3220
|
await loginCommand();
|
|
3387
3221
|
}
|
|
3388
|
-
|
|
3389
|
-
|
|
3222
|
+
restoreStdin();
|
|
3223
|
+
await sleep2(80);
|
|
3224
|
+
await this.checkAuth();
|
|
3390
3225
|
}
|
|
3391
3226
|
async cmdLogout() {
|
|
3392
|
-
console.log();
|
|
3393
3227
|
if (this.isDemo) {
|
|
3394
3228
|
await demoLogoutCommand();
|
|
3395
3229
|
} else {
|
|
3396
3230
|
await logoutCommand();
|
|
3397
3231
|
}
|
|
3398
|
-
|
|
3399
|
-
|
|
3232
|
+
restoreStdin();
|
|
3233
|
+
await sleep2(80);
|
|
3234
|
+
await this.checkAuth();
|
|
3400
3235
|
}
|
|
3401
3236
|
async cmdStatus() {
|
|
3402
|
-
console.log();
|
|
3403
3237
|
if (!this.isAuthenticated) {
|
|
3404
3238
|
logger.info("Not logged in. Type /login to authenticate.");
|
|
3405
3239
|
return;
|
|
3406
3240
|
}
|
|
3407
3241
|
if (this.isDemo) {
|
|
3408
|
-
const
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
);
|
|
3422
|
-
console.log(
|
|
3242
|
+
const W = 54;
|
|
3243
|
+
const top = chalk7.dim("\u256D" + "\u2500".repeat(W - 2) + "\u256E");
|
|
3244
|
+
const bot = chalk7.dim("\u2570" + "\u2500".repeat(W - 2) + "\u256F");
|
|
3245
|
+
const kv = (k, v) => {
|
|
3246
|
+
const rawV = v.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3247
|
+
const pad = W - 4 - k.length - rawV.length;
|
|
3248
|
+
return chalk7.dim("\u2502 ") + chalk7.bold(k) + " ".repeat(Math.max(0, pad)) + v + chalk7.dim(" \u2502");
|
|
3249
|
+
};
|
|
3250
|
+
console.log(top);
|
|
3251
|
+
console.log(kv("Email", DEMO_USER2.email));
|
|
3252
|
+
console.log(kv("Name", DEMO_USER2.full_name));
|
|
3253
|
+
console.log(kv("Plan", chalk7.bgCyan.black(" PRO ")));
|
|
3254
|
+
console.log(kv("Verified", chalk7.green("\u2713 Yes")));
|
|
3255
|
+
console.log(kv("2FA", chalk7.dim("Disabled")));
|
|
3256
|
+
console.log(kv("Workspace", DEMO_WORKSPACE2.name + chalk7.dim(" (enterprise)")));
|
|
3257
|
+
console.log(kv("Project", DEMO_PROJECT2.name));
|
|
3258
|
+
console.log(kv("Tokens today", `${(DEMO_USER2.tokens_used_today).toLocaleString()} / 500,000`));
|
|
3259
|
+
console.log(bot);
|
|
3423
3260
|
} else {
|
|
3424
3261
|
await statusCommand();
|
|
3425
3262
|
}
|
|
3426
3263
|
}
|
|
3427
3264
|
async cmdScan() {
|
|
3428
|
-
console.log();
|
|
3429
3265
|
if (this.isDemo) {
|
|
3430
3266
|
await demoPromptCommand("scan auth service for OWASP vulnerabilities", { ...this.options, mode: "security" });
|
|
3431
3267
|
} else {
|
|
@@ -3433,7 +3269,6 @@ ${recent[recent.length - 1].content}`;
|
|
|
3433
3269
|
}
|
|
3434
3270
|
}
|
|
3435
3271
|
async cmdReview() {
|
|
3436
|
-
console.log();
|
|
3437
3272
|
if (this.isDemo) {
|
|
3438
3273
|
await demoReviewCommand();
|
|
3439
3274
|
} else {
|
|
@@ -3442,11 +3277,9 @@ ${recent[recent.length - 1].content}`;
|
|
|
3442
3277
|
}
|
|
3443
3278
|
async cmdExplain(args) {
|
|
3444
3279
|
if (!args) {
|
|
3445
|
-
logger.error("Usage: /explain <file
|
|
3446
|
-
logger.info("Example: /explain src/auth/middleware.ts");
|
|
3280
|
+
logger.error("Usage: /explain <file or concept>");
|
|
3447
3281
|
return;
|
|
3448
3282
|
}
|
|
3449
|
-
console.log();
|
|
3450
3283
|
if (this.isDemo) {
|
|
3451
3284
|
await demoExplainCommand(args);
|
|
3452
3285
|
} else {
|
|
@@ -3457,275 +3290,240 @@ ${recent[recent.length - 1].content}`;
|
|
|
3457
3290
|
const parts = args.split(/\s+/);
|
|
3458
3291
|
const sub = parts[0]?.toLowerCase();
|
|
3459
3292
|
if (!sub || !["save", "show", "clear"].includes(sub)) {
|
|
3460
|
-
console.log();
|
|
3461
3293
|
console.log(` ${chalk7.cyan("/memory show")} \u2014 Show all project memories`);
|
|
3462
3294
|
console.log(` ${chalk7.cyan("/memory save <text>")} \u2014 Save a memory`);
|
|
3463
3295
|
console.log(` ${chalk7.cyan("/memory clear")} \u2014 Clear all memories`);
|
|
3464
3296
|
return;
|
|
3465
3297
|
}
|
|
3466
|
-
console.log();
|
|
3467
3298
|
const content = parts.slice(1).join(" ").trim();
|
|
3468
3299
|
if (this.isDemo) {
|
|
3469
3300
|
await demoMemoryCommand(sub, content || void 0);
|
|
3301
|
+
restoreStdin();
|
|
3302
|
+
await sleep2(80);
|
|
3470
3303
|
} else {
|
|
3471
3304
|
await memoryCommand(sub, content || void 0, this.options);
|
|
3472
3305
|
}
|
|
3473
3306
|
}
|
|
3474
3307
|
async cmdMode(args) {
|
|
3475
|
-
const
|
|
3308
|
+
const valid = ["general", "frontend", "backend", "security", "devops"];
|
|
3476
3309
|
if (!args) {
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3310
|
+
const descs = {
|
|
3311
|
+
general: "All-purpose coding assistant",
|
|
3312
|
+
frontend: "React, Vue, CSS, TypeScript",
|
|
3313
|
+
backend: "APIs, databases, microservices",
|
|
3314
|
+
security: "OWASP, CVE, penetration testing",
|
|
3315
|
+
devops: "Docker, Kubernetes, CI/CD"
|
|
3316
|
+
};
|
|
3317
|
+
for (const m of valid) {
|
|
3318
|
+
const active = m === this.currentMode;
|
|
3319
|
+
const dot = active ? chalk7.green("\u25CF") : chalk7.dim("\u25CB");
|
|
3320
|
+
const label = active ? chalk7.yellow.bold(m.padEnd(10)) : chalk7.white(m.padEnd(10));
|
|
3321
|
+
console.log(` ${dot} ${label} ${chalk7.dim(descs[m])}`);
|
|
3485
3322
|
}
|
|
3486
3323
|
console.log();
|
|
3487
|
-
console.log(chalk7.dim(
|
|
3324
|
+
console.log(chalk7.dim(" Usage: /mode <name>"));
|
|
3488
3325
|
return;
|
|
3489
3326
|
}
|
|
3490
3327
|
const mode = args.toLowerCase();
|
|
3491
|
-
if (!
|
|
3492
|
-
logger.error(`Invalid mode "${args}". Valid: ${
|
|
3328
|
+
if (!valid.includes(mode)) {
|
|
3329
|
+
logger.error(`Invalid mode "${args}". Valid: ${valid.join(", ")}`);
|
|
3493
3330
|
return;
|
|
3494
3331
|
}
|
|
3495
3332
|
this.currentMode = mode;
|
|
3496
3333
|
this.options.mode = mode;
|
|
3497
|
-
|
|
3334
|
+
console.log(` ${chalk7.green("\u2713")} Mode \u2192 ${chalk7.yellow.bold(mode)}`);
|
|
3498
3335
|
}
|
|
3499
3336
|
async cmdModel(args) {
|
|
3500
3337
|
if (!args) {
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
console.log(
|
|
3504
|
-
console.log(chalk7.dim(` Usage: /model <name> | /model auto | /models to list all`));
|
|
3338
|
+
const cur = this.currentModel || "auto";
|
|
3339
|
+
console.log(` Current model: ${chalk7.cyan.bold(cur)}`);
|
|
3340
|
+
console.log(chalk7.dim(" /model <name> \xB7 /model auto \xB7 /models to list all"));
|
|
3505
3341
|
return;
|
|
3506
3342
|
}
|
|
3507
3343
|
if (args === "auto") {
|
|
3508
3344
|
this.currentModel = null;
|
|
3509
3345
|
this.options.model = void 0;
|
|
3510
|
-
logger.success("Model
|
|
3346
|
+
logger.success("Model \u2192 auto");
|
|
3511
3347
|
return;
|
|
3512
3348
|
}
|
|
3513
3349
|
this.currentModel = args;
|
|
3514
3350
|
this.options.model = args;
|
|
3515
|
-
|
|
3351
|
+
console.log(` ${chalk7.green("\u2713")} Model \u2192 ${chalk7.cyan.bold(args)}`);
|
|
3516
3352
|
}
|
|
3517
3353
|
async cmdModels() {
|
|
3518
|
-
console.log();
|
|
3519
3354
|
if (this.isDemo) {
|
|
3520
3355
|
const table = new Table3({
|
|
3521
|
-
head: [
|
|
3522
|
-
|
|
3523
|
-
chalk7.bold("Domain"),
|
|
3524
|
-
chalk7.bold("Status"),
|
|
3525
|
-
chalk7.bold("Min Plan"),
|
|
3526
|
-
chalk7.bold("Context"),
|
|
3527
|
-
chalk7.bold("Speed")
|
|
3528
|
-
],
|
|
3529
|
-
colWidths: [24, 12, 10, 10, 10, 12]
|
|
3356
|
+
head: [chalk7.bold("Model"), chalk7.bold("Domain"), chalk7.bold("Status"), chalk7.bold("Plan"), chalk7.bold("Context"), chalk7.bold("Speed")],
|
|
3357
|
+
style: { border: ["dim"] }
|
|
3530
3358
|
});
|
|
3531
3359
|
for (const m of DEMO_MODELS) {
|
|
3532
|
-
const
|
|
3533
|
-
const
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
statusColor(m.status),
|
|
3538
|
-
planColor(m.min_plan),
|
|
3539
|
-
`${(m.context_window / 1024).toFixed(0)}k`,
|
|
3540
|
-
`${m.tokens_per_sec} tok/s`
|
|
3541
|
-
]);
|
|
3360
|
+
const cur = m.name === (this.currentModel || "");
|
|
3361
|
+
const nm = cur ? chalk7.cyan.bold(m.display_name + " \u25CF") : m.display_name;
|
|
3362
|
+
const status = m.status === "active" ? chalk7.green("active") : chalk7.yellow("beta");
|
|
3363
|
+
const plan = m.min_plan === "free" ? chalk7.green("free") : chalk7.cyan("pro");
|
|
3364
|
+
table.push([nm, chalk7.yellow(m.domain), status, plan, `${(m.context_window / 1024).toFixed(0)}k`, `${m.tokens_per_sec} t/s`]);
|
|
3542
3365
|
}
|
|
3543
3366
|
console.log(table.toString());
|
|
3544
|
-
console.log();
|
|
3545
|
-
console.log(chalk7.dim(` Set a model: /model devwing-backend-1 | /model auto`));
|
|
3367
|
+
console.log(chalk7.dim(" /model <name> to select \xB7 /model auto for automatic"));
|
|
3546
3368
|
} else {
|
|
3547
3369
|
try {
|
|
3548
3370
|
const models = await apiClient.getModels();
|
|
3549
|
-
if (models.length
|
|
3371
|
+
if (!models.length) {
|
|
3550
3372
|
logger.info("No models available");
|
|
3551
3373
|
return;
|
|
3552
3374
|
}
|
|
3553
|
-
const table = new Table3({
|
|
3554
|
-
|
|
3555
|
-
});
|
|
3556
|
-
for (const m of models) {
|
|
3557
|
-
table.push([m.display_name || m.name, m.domain, m.status, m.min_plan]);
|
|
3558
|
-
}
|
|
3375
|
+
const table = new Table3({ head: [chalk7.bold("Name"), chalk7.bold("Domain"), chalk7.bold("Status"), chalk7.bold("Plan")] });
|
|
3376
|
+
for (const m of models) table.push([m.display_name || m.name, m.domain, m.status, m.min_plan]);
|
|
3559
3377
|
console.log(table.toString());
|
|
3560
|
-
} catch (
|
|
3561
|
-
logger.error("Failed to fetch models: " +
|
|
3378
|
+
} catch (e) {
|
|
3379
|
+
logger.error("Failed to fetch models: " + e.message);
|
|
3562
3380
|
}
|
|
3563
3381
|
}
|
|
3564
3382
|
}
|
|
3565
3383
|
async cmdUsage() {
|
|
3566
|
-
console.log();
|
|
3567
3384
|
if (this.isDemo) {
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
head: [chalk7.bold("Period"), chalk7.bold("Requests"), chalk7.bold("Tokens In"), chalk7.bold("Tokens Out"), chalk7.bold("Cost")]
|
|
3385
|
+
const t = new Table3({
|
|
3386
|
+
head: [chalk7.bold("Period"), chalk7.bold("Requests"), chalk7.bold("Tokens In"), chalk7.bold("Tokens Out"), chalk7.bold("Cost")],
|
|
3387
|
+
style: { border: ["dim"] }
|
|
3572
3388
|
});
|
|
3573
|
-
|
|
3574
|
-
["Today", DEMO_USAGE.today.requests
|
|
3575
|
-
["This Week", DEMO_USAGE.week.requests
|
|
3576
|
-
["This Month", DEMO_USAGE.month.requests
|
|
3389
|
+
t.push(
|
|
3390
|
+
["Today", String(DEMO_USAGE.today.requests), DEMO_USAGE.today.tokens_in.toLocaleString(), DEMO_USAGE.today.tokens_out.toLocaleString(), `$${DEMO_USAGE.today.cost.toFixed(4)}`],
|
|
3391
|
+
["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)}`],
|
|
3392
|
+
["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)}`]
|
|
3577
3393
|
);
|
|
3578
|
-
console.log(
|
|
3579
|
-
console.log();
|
|
3394
|
+
console.log(t.toString());
|
|
3580
3395
|
const used = DEMO_USER2.tokens_used_today;
|
|
3581
3396
|
const limit = 5e5;
|
|
3582
3397
|
const pct = Math.round(used / limit * 100);
|
|
3583
|
-
const
|
|
3584
|
-
const
|
|
3585
|
-
const bar = chalk7.cyan("\u2588".repeat(
|
|
3586
|
-
console.log(` Daily Quota: ${bar} ${pct}% (${used.toLocaleString()} / ${limit.toLocaleString()})`);
|
|
3398
|
+
const barW = 30;
|
|
3399
|
+
const fill = Math.round(pct / 100 * barW);
|
|
3400
|
+
const bar = chalk7.cyan("\u2588".repeat(fill)) + chalk7.dim("\u2591".repeat(barW - fill));
|
|
3587
3401
|
console.log();
|
|
3588
|
-
console.log(chalk7.bold("
|
|
3402
|
+
console.log(` Daily Quota ${bar} ${chalk7.bold(pct + "%")} ${chalk7.dim(`${used.toLocaleString()} / ${limit.toLocaleString()}`)}`);
|
|
3589
3403
|
console.log();
|
|
3590
|
-
const
|
|
3591
|
-
head: [chalk7.bold("Model"), chalk7.bold("Requests"), chalk7.bold("Tokens"), chalk7.bold("Cost")]
|
|
3404
|
+
const mt = new Table3({
|
|
3405
|
+
head: [chalk7.bold("Model"), chalk7.bold("Requests"), chalk7.bold("Tokens"), chalk7.bold("Cost")],
|
|
3406
|
+
style: { border: ["dim"] }
|
|
3592
3407
|
});
|
|
3593
|
-
|
|
3408
|
+
mt.push(
|
|
3594
3409
|
["devwing-backend-1", "312", "421,000", "$1.4721"],
|
|
3595
3410
|
["devwing-security-1", "145", "198,500", "$0.6948"],
|
|
3596
3411
|
["devwing-general-1", "98", "132,200", "$0.4627"],
|
|
3597
3412
|
["devwing-frontend-1", "42", "56,800", "$0.1988"],
|
|
3598
3413
|
["devwing-devops-1", "15", "15,600", "$0.1728"]
|
|
3599
3414
|
);
|
|
3600
|
-
console.log(
|
|
3415
|
+
console.log(mt.toString());
|
|
3601
3416
|
} else {
|
|
3602
3417
|
try {
|
|
3603
|
-
const
|
|
3604
|
-
console.log(`
|
|
3605
|
-
console.log(` Tokens
|
|
3606
|
-
console.log(`
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
logger.error("Failed to fetch usage: " + error.message);
|
|
3418
|
+
const u = await apiClient.getUsage();
|
|
3419
|
+
console.log(` Requests: ${u.total_requests}`);
|
|
3420
|
+
console.log(` Tokens: ${u.total_tokens_in.toLocaleString()} in, ${u.total_tokens_out.toLocaleString()} out`);
|
|
3421
|
+
console.log(` Cost: $${u.total_cost_usd.toFixed(4)}`);
|
|
3422
|
+
} catch (e) {
|
|
3423
|
+
logger.error("Failed to fetch usage: " + e.message);
|
|
3610
3424
|
}
|
|
3611
3425
|
}
|
|
3612
3426
|
}
|
|
3613
3427
|
async cmdPlans() {
|
|
3614
|
-
console.log();
|
|
3615
3428
|
const table = new Table3({
|
|
3616
|
-
head: [
|
|
3617
|
-
|
|
3618
|
-
chalk7.bold("Price"),
|
|
3619
|
-
chalk7.bold("Tokens/Day"),
|
|
3620
|
-
chalk7.bold("Models"),
|
|
3621
|
-
chalk7.bold("Projects"),
|
|
3622
|
-
chalk7.bold("Seats")
|
|
3623
|
-
],
|
|
3624
|
-
colWidths: [14, 12, 14, 16, 12, 14]
|
|
3429
|
+
head: [chalk7.bold("Plan"), chalk7.bold("Price"), chalk7.bold("Tokens/Day"), chalk7.bold("Models"), chalk7.bold("Projects"), chalk7.bold("Seats")],
|
|
3430
|
+
style: { border: ["dim"] }
|
|
3625
3431
|
});
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
const
|
|
3629
|
-
|
|
3432
|
+
const cur = this.userProfile?.subscription_plan?.toLowerCase() || "";
|
|
3433
|
+
for (const p of DEMO_PLANS) {
|
|
3434
|
+
const isCur = this.isAuthenticated && cur === p.name.toLowerCase();
|
|
3435
|
+
const nm = isCur ? chalk7.cyan.bold(p.name) + chalk7.dim(" \u2190") : p.name;
|
|
3436
|
+
table.push([nm, p.price, p.tokens_day, p.models, p.projects, p.seats]);
|
|
3630
3437
|
}
|
|
3631
3438
|
console.log(table.toString());
|
|
3632
3439
|
console.log();
|
|
3633
3440
|
if (this.isAuthenticated) {
|
|
3634
|
-
|
|
3635
|
-
console.log(chalk7.dim(` Your plan: ${currentPlan.toUpperCase()}. Upgrade at https://devwing.ai/dashboard/billing`));
|
|
3441
|
+
console.log(chalk7.dim(` Your plan: ${cur.toUpperCase()} \xB7 Upgrade at devwing.ai/dashboard/billing`));
|
|
3636
3442
|
} else {
|
|
3637
|
-
console.log(chalk7.dim(" Sign up at
|
|
3443
|
+
console.log(chalk7.dim(" Sign up at devwing.ai"));
|
|
3638
3444
|
}
|
|
3639
3445
|
}
|
|
3640
3446
|
async cmdContext() {
|
|
3641
|
-
console.log();
|
|
3642
3447
|
if (this.isDemo) {
|
|
3643
|
-
const
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
"
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3448
|
+
const W = 56;
|
|
3449
|
+
const top = chalk7.dim("\u256D" + "\u2500".repeat(W - 2) + "\u256E");
|
|
3450
|
+
const bot = chalk7.dim("\u2570" + "\u2500".repeat(W - 2) + "\u256F");
|
|
3451
|
+
const div = chalk7.dim("\u251C" + "\u2500".repeat(W - 2) + "\u2524");
|
|
3452
|
+
const kv = (k, v) => {
|
|
3453
|
+
const rv = v.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3454
|
+
const pad = W - 4 - k.length - rv.length;
|
|
3455
|
+
return chalk7.dim("\u2502 ") + chalk7.bold(k) + " ".repeat(Math.max(0, pad)) + v + chalk7.dim(" \u2502");
|
|
3456
|
+
};
|
|
3457
|
+
const fl = (f) => {
|
|
3458
|
+
const pad = W - 6 - f.length;
|
|
3459
|
+
return chalk7.dim("\u2502 \xB7 ") + chalk7.cyan(f) + " ".repeat(Math.max(0, pad)) + chalk7.dim("\u2502");
|
|
3460
|
+
};
|
|
3461
|
+
const ln = (s) => {
|
|
3462
|
+
const raw = s.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3463
|
+
const pad = W - 4 - raw.length;
|
|
3464
|
+
return chalk7.dim("\u2502 ") + s + " ".repeat(Math.max(0, pad)) + chalk7.dim(" \u2502");
|
|
3465
|
+
};
|
|
3466
|
+
console.log(top);
|
|
3467
|
+
console.log(kv("Directory", chalk7.dim(process.cwd().replace(process.env.HOME || "", "~"))));
|
|
3468
|
+
console.log(kv("Git Branch", "main"));
|
|
3469
|
+
console.log(kv("Files", "34 files loaded"));
|
|
3470
|
+
console.log(kv("Framework", "FastAPI + TypeScript"));
|
|
3471
|
+
console.log(div);
|
|
3472
|
+
console.log(ln(chalk7.bold("Top files")));
|
|
3473
|
+
for (const f of ["src/auth/auth_controller.ts", "src/middleware/jwt.middleware.ts", "src/services/user_service.ts", "package.json", "docker-compose.yml"]) {
|
|
3474
|
+
console.log(fl(f));
|
|
3475
|
+
}
|
|
3476
|
+
console.log(ln(chalk7.dim("... and 29 more")));
|
|
3477
|
+
console.log(bot);
|
|
3670
3478
|
} else if (this.sessionContext) {
|
|
3671
|
-
console.log(`
|
|
3672
|
-
console.log(` Shell: ${this.sessionContext.shell} | OS: ${this.sessionContext.os}`);
|
|
3673
|
-
console.log(` Files: ${this.sessionContext.files.length}`);
|
|
3674
|
-
if (this.sessionContext.git_branch) {
|
|
3675
|
-
console.log(` Git Branch: ${this.sessionContext.git_branch}`);
|
|
3676
|
-
}
|
|
3677
|
-
console.log();
|
|
3678
|
-
console.log(chalk7.bold(" Files in context:"));
|
|
3479
|
+
console.log(` Dir: ${this.sessionContext.cwd} \xB7 Files: ${this.sessionContext.files.length}`);
|
|
3679
3480
|
for (const f of this.sessionContext.files.slice(0, 10)) {
|
|
3680
|
-
console.log(`
|
|
3681
|
-
}
|
|
3682
|
-
if (this.sessionContext.files.length > 10) {
|
|
3683
|
-
console.log(chalk7.dim(` ... and ${this.sessionContext.files.length - 10} more`));
|
|
3481
|
+
console.log(` ${chalk7.dim("\xB7")} ${chalk7.cyan(f.path)}`);
|
|
3684
3482
|
}
|
|
3685
3483
|
} else {
|
|
3686
3484
|
logger.info("No context loaded yet. Send a message to load context.");
|
|
3687
3485
|
}
|
|
3688
3486
|
}
|
|
3689
3487
|
async cmdHistory() {
|
|
3690
|
-
|
|
3691
|
-
if (this.conversationHistory.length === 0) {
|
|
3488
|
+
if (!this.conversationHistory.length) {
|
|
3692
3489
|
logger.info("No conversation history yet.");
|
|
3693
3490
|
return;
|
|
3694
3491
|
}
|
|
3695
|
-
for (const
|
|
3696
|
-
const label =
|
|
3697
|
-
const time = chalk7.dim(
|
|
3698
|
-
const preview =
|
|
3699
|
-
console.log(` ${time}
|
|
3492
|
+
for (const m of this.conversationHistory.slice(-20)) {
|
|
3493
|
+
const label = m.role === "user" ? chalk7.green.bold("You ") : chalk7.cyan.bold("DevWing ");
|
|
3494
|
+
const time = chalk7.dim(m.timestamp.toLocaleTimeString());
|
|
3495
|
+
const preview = m.content.length > 100 ? m.content.slice(0, 100) + "\u2026" : m.content;
|
|
3496
|
+
console.log(` ${time} ${label} ${preview}`);
|
|
3700
3497
|
}
|
|
3701
3498
|
}
|
|
3702
3499
|
async cmdConfig(args) {
|
|
3703
3500
|
if (!args) {
|
|
3704
|
-
|
|
3705
|
-
const
|
|
3706
|
-
const
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
);
|
|
3717
|
-
console.log(
|
|
3718
|
-
console.log();
|
|
3719
|
-
console.log(chalk7.dim(
|
|
3501
|
+
const cfg = configManager.getAll();
|
|
3502
|
+
const W = 54;
|
|
3503
|
+
const top = chalk7.dim("\u256D" + "\u2500".repeat(W - 2) + "\u256E");
|
|
3504
|
+
const bot = chalk7.dim("\u2570" + "\u2500".repeat(W - 2) + "\u256F");
|
|
3505
|
+
const kv = (k, v) => {
|
|
3506
|
+
const rv = v.replace(/\x1B\[[0-9;]*m/g, "");
|
|
3507
|
+
const pad = W - 4 - k.length - rv.length;
|
|
3508
|
+
return chalk7.dim("\u2502 ") + chalk7.bold(k) + " ".repeat(Math.max(0, pad)) + v + chalk7.dim(" \u2502");
|
|
3509
|
+
};
|
|
3510
|
+
console.log(top);
|
|
3511
|
+
console.log(kv("API URL", chalk7.dim(cfg.apiUrl || "default")));
|
|
3512
|
+
console.log(kv("Workspace", chalk7.dim(cfg.workspaceId || "none")));
|
|
3513
|
+
console.log(kv("Project", chalk7.dim(cfg.projectId || "none")));
|
|
3514
|
+
console.log(kv("Model", chalk7.dim(cfg.model || "auto")));
|
|
3515
|
+
console.log(kv("Mode", chalk7.dim(cfg.mode || "general")));
|
|
3516
|
+
console.log(kv("Config", chalk7.dim(configManager.getPath())));
|
|
3517
|
+
console.log(bot);
|
|
3518
|
+
console.log(chalk7.dim(" /config set <key> <value> \xB7 /config get <key>"));
|
|
3720
3519
|
return;
|
|
3721
3520
|
}
|
|
3722
3521
|
const parts = args.split(/\s+/);
|
|
3723
|
-
|
|
3724
|
-
if (sub === "list") {
|
|
3522
|
+
if (parts[0] === "list") {
|
|
3725
3523
|
await configCommand("list");
|
|
3726
|
-
} else if (
|
|
3524
|
+
} else if (parts[0] === "get" && parts[1]) {
|
|
3727
3525
|
await configCommand("get", parts[1]);
|
|
3728
|
-
} else if (
|
|
3526
|
+
} else if (parts[0] === "set" && parts[1] && parts[2]) {
|
|
3729
3527
|
await configCommand("set", parts[1], parts[2]);
|
|
3730
3528
|
if (parts[1] === "mode") this.currentMode = parts[2];
|
|
3731
3529
|
if (parts[1] === "model") this.currentModel = parts[2];
|