devwing 0.1.3 → 0.1.5
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 +291 -249
- package/dist/index.js.map +1 -1
- package/package.json +11 -12
package/dist/index.js
CHANGED
|
@@ -554,32 +554,14 @@ async function loginWithBrowser() {
|
|
|
554
554
|
try {
|
|
555
555
|
const deviceInfo = `DevWing CLI on ${os2.platform()}`;
|
|
556
556
|
const initResponse = await apiClient.initiateCliAuth(deviceInfo);
|
|
557
|
-
logger.succeedSpinner("
|
|
557
|
+
logger.succeedSpinner("Opening browser...");
|
|
558
558
|
logger.newline();
|
|
559
|
-
logger.box(
|
|
560
|
-
[
|
|
561
|
-
"Browser Authentication",
|
|
562
|
-
"",
|
|
563
|
-
`Code: ${chalk3.bold.yellow(initResponse.user_code)}`,
|
|
564
|
-
"",
|
|
565
|
-
`Opening browser to ${chalk3.cyan(initResponse.verification_url)}`,
|
|
566
|
-
"",
|
|
567
|
-
`Enter the code above when prompted.`,
|
|
568
|
-
"",
|
|
569
|
-
`Expires in ${Math.floor(initResponse.expires_in / 60)} minutes.`
|
|
570
|
-
].join("\n"),
|
|
571
|
-
{ title: "Verify Device", color: "blue" }
|
|
572
|
-
);
|
|
573
|
-
logger.newline();
|
|
574
|
-
logger.info("Opening browser...");
|
|
575
559
|
try {
|
|
576
560
|
await open.default(initResponse.verification_url_complete);
|
|
577
|
-
logger.success("Browser opened! Please complete authentication.");
|
|
561
|
+
logger.success("Browser opened! Please log in to complete authentication.");
|
|
578
562
|
} catch (err) {
|
|
579
563
|
logger.warn("Could not open browser automatically");
|
|
580
|
-
logger.info(
|
|
581
|
-
`Please visit: ${chalk3.cyan(initResponse.verification_url_complete)}`
|
|
582
|
-
);
|
|
564
|
+
logger.info(`Please visit: ${chalk3.cyan(initResponse.verification_url_complete)}`);
|
|
583
565
|
}
|
|
584
566
|
logger.newline();
|
|
585
567
|
logger.startSpinner("Waiting for authorization...");
|
|
@@ -1631,230 +1613,6 @@ async function promptCommand(prompt, options) {
|
|
|
1631
1613
|
process.exit(1);
|
|
1632
1614
|
}
|
|
1633
1615
|
}
|
|
1634
|
-
var ChatSession = class {
|
|
1635
|
-
conversationHistory = [];
|
|
1636
|
-
sessionContext = null;
|
|
1637
|
-
sessionId = null;
|
|
1638
|
-
addMessage(role, content) {
|
|
1639
|
-
this.conversationHistory.push({ role, content });
|
|
1640
|
-
}
|
|
1641
|
-
getHistory() {
|
|
1642
|
-
return this.conversationHistory;
|
|
1643
|
-
}
|
|
1644
|
-
setContext(context) {
|
|
1645
|
-
this.sessionContext = context;
|
|
1646
|
-
}
|
|
1647
|
-
getContext() {
|
|
1648
|
-
return this.sessionContext;
|
|
1649
|
-
}
|
|
1650
|
-
setSessionId(id) {
|
|
1651
|
-
this.sessionId = id;
|
|
1652
|
-
}
|
|
1653
|
-
getSessionId() {
|
|
1654
|
-
return this.sessionId;
|
|
1655
|
-
}
|
|
1656
|
-
clear() {
|
|
1657
|
-
this.conversationHistory = [];
|
|
1658
|
-
this.sessionId = null;
|
|
1659
|
-
}
|
|
1660
|
-
getConversationSummary() {
|
|
1661
|
-
return this.conversationHistory.map((msg) => `${msg.role === "user" ? "You" : "DevWing"}: ${msg.content.substring(0, 100)}...`).join("\n");
|
|
1662
|
-
}
|
|
1663
|
-
};
|
|
1664
|
-
function handleSpecialCommand(command, session) {
|
|
1665
|
-
const cmd = command.toLowerCase();
|
|
1666
|
-
if (cmd === "/help") {
|
|
1667
|
-
logger.box([
|
|
1668
|
-
chalk3.bold("DevWing Chat Commands:"),
|
|
1669
|
-
"",
|
|
1670
|
-
chalk3.cyan("/help") + " - Show this help message",
|
|
1671
|
-
chalk3.cyan("/exit, /quit") + " - Exit chat mode",
|
|
1672
|
-
chalk3.cyan("/clear") + " - Clear conversation history",
|
|
1673
|
-
chalk3.cyan("/context") + " - Show current context",
|
|
1674
|
-
chalk3.cyan("/history") + " - Show conversation history",
|
|
1675
|
-
chalk3.cyan("/memory save") + " - Save note to project memory",
|
|
1676
|
-
"",
|
|
1677
|
-
"Just type your message to chat with DevWing!"
|
|
1678
|
-
].join("\n"), { title: "Chat Commands", color: "blue" });
|
|
1679
|
-
return true;
|
|
1680
|
-
}
|
|
1681
|
-
if (cmd === "/exit" || cmd === "/quit") {
|
|
1682
|
-
logger.info("Exiting chat mode...");
|
|
1683
|
-
return false;
|
|
1684
|
-
}
|
|
1685
|
-
if (cmd === "/clear") {
|
|
1686
|
-
session.clear();
|
|
1687
|
-
console.clear();
|
|
1688
|
-
logger.success("Conversation cleared!");
|
|
1689
|
-
printWelcomeBanner();
|
|
1690
|
-
return true;
|
|
1691
|
-
}
|
|
1692
|
-
if (cmd === "/context") {
|
|
1693
|
-
const context = session.getContext();
|
|
1694
|
-
if (!context) {
|
|
1695
|
-
logger.warn("No context loaded yet. Send a message to load context.");
|
|
1696
|
-
return true;
|
|
1697
|
-
}
|
|
1698
|
-
logger.box([
|
|
1699
|
-
chalk3.bold("Current Context:"),
|
|
1700
|
-
"",
|
|
1701
|
-
`Working Directory: ${chalk3.cyan(context.cwd)}`,
|
|
1702
|
-
`Shell: ${context.shell}`,
|
|
1703
|
-
`OS: ${context.os}`,
|
|
1704
|
-
`Files: ${context.files.length}`,
|
|
1705
|
-
context.git_branch ? `Git Branch: ${context.git_branch}` : "",
|
|
1706
|
-
"",
|
|
1707
|
-
"Files included:",
|
|
1708
|
-
...context.files.slice(0, 10).map((f) => ` \u2022 ${f.path}`),
|
|
1709
|
-
context.files.length > 10 ? ` ... and ${context.files.length - 10} more` : ""
|
|
1710
|
-
].filter(Boolean).join("\n"), { title: "Context Info", color: "cyan" });
|
|
1711
|
-
return true;
|
|
1712
|
-
}
|
|
1713
|
-
if (cmd === "/history") {
|
|
1714
|
-
const history = session.getHistory();
|
|
1715
|
-
if (history.length === 0) {
|
|
1716
|
-
logger.info("No conversation history yet.");
|
|
1717
|
-
return true;
|
|
1718
|
-
}
|
|
1719
|
-
logger.box([
|
|
1720
|
-
chalk3.bold("Conversation History:"),
|
|
1721
|
-
"",
|
|
1722
|
-
session.getConversationSummary()
|
|
1723
|
-
].join("\n"), { title: "History", color: "magenta" });
|
|
1724
|
-
return true;
|
|
1725
|
-
}
|
|
1726
|
-
return true;
|
|
1727
|
-
}
|
|
1728
|
-
function printWelcomeBanner() {
|
|
1729
|
-
logger.box([
|
|
1730
|
-
chalk3.bold.cyan("DevWing AI - Interactive Chat Mode"),
|
|
1731
|
-
"",
|
|
1732
|
-
"Chat with AI about your codebase. Type your message and press Enter.",
|
|
1733
|
-
"",
|
|
1734
|
-
chalk3.dim("Type /help for commands \u2022 /exit to quit")
|
|
1735
|
-
].join("\n"), { title: "\u{1F680} Welcome", color: "cyan" });
|
|
1736
|
-
}
|
|
1737
|
-
async function chatCommand(options) {
|
|
1738
|
-
try {
|
|
1739
|
-
const apiKey = await configManager.getApiKey();
|
|
1740
|
-
if (!apiKey) {
|
|
1741
|
-
logger.error('Not authenticated. Run "devwing login" first.');
|
|
1742
|
-
process.exit(1);
|
|
1743
|
-
}
|
|
1744
|
-
const session = new ChatSession();
|
|
1745
|
-
console.clear();
|
|
1746
|
-
printWelcomeBanner();
|
|
1747
|
-
logger.newline();
|
|
1748
|
-
const rl = readline.createInterface({
|
|
1749
|
-
input: process.stdin,
|
|
1750
|
-
output: process.stdout,
|
|
1751
|
-
prompt: chalk3.bold.green("You: ")
|
|
1752
|
-
});
|
|
1753
|
-
rl.on("SIGINT", () => {
|
|
1754
|
-
logger.newline();
|
|
1755
|
-
logger.info("Exiting chat mode...");
|
|
1756
|
-
rl.close();
|
|
1757
|
-
process.exit(0);
|
|
1758
|
-
});
|
|
1759
|
-
logger.startSpinner("Loading codebase context...");
|
|
1760
|
-
const collector = new ContextCollector(process.cwd());
|
|
1761
|
-
const initialContext = await collector.collect("");
|
|
1762
|
-
session.setContext(initialContext);
|
|
1763
|
-
logger.succeedSpinner("Context loaded!");
|
|
1764
|
-
logger.newline();
|
|
1765
|
-
rl.prompt();
|
|
1766
|
-
rl.on("line", async (input) => {
|
|
1767
|
-
const userMessage = input.trim();
|
|
1768
|
-
if (!userMessage) {
|
|
1769
|
-
rl.prompt();
|
|
1770
|
-
return;
|
|
1771
|
-
}
|
|
1772
|
-
if (userMessage.startsWith("/")) {
|
|
1773
|
-
const shouldContinue = handleSpecialCommand(userMessage, session);
|
|
1774
|
-
if (!shouldContinue) {
|
|
1775
|
-
rl.close();
|
|
1776
|
-
return;
|
|
1777
|
-
}
|
|
1778
|
-
logger.newline();
|
|
1779
|
-
rl.prompt();
|
|
1780
|
-
return;
|
|
1781
|
-
}
|
|
1782
|
-
session.addMessage("user", userMessage);
|
|
1783
|
-
logger.newline();
|
|
1784
|
-
logger.info(chalk3.dim("DevWing is thinking..."));
|
|
1785
|
-
logger.newline();
|
|
1786
|
-
try {
|
|
1787
|
-
const request = {
|
|
1788
|
-
prompt: buildPromptWithHistory(session),
|
|
1789
|
-
mode: options.mode,
|
|
1790
|
-
model: options.model,
|
|
1791
|
-
project_id: options.project || configManager.getProjectId(),
|
|
1792
|
-
context: session.getContext(),
|
|
1793
|
-
stream: true,
|
|
1794
|
-
max_tokens: 4096
|
|
1795
|
-
};
|
|
1796
|
-
let assistantResponse = "";
|
|
1797
|
-
streamingRenderer.reset();
|
|
1798
|
-
streamingRenderer.clearPendingTools();
|
|
1799
|
-
for await (const message of apiClient.streamCompletion(request)) {
|
|
1800
|
-
await streamingRenderer.processMessage(message);
|
|
1801
|
-
if (message.type === "token" && message.content) {
|
|
1802
|
-
assistantResponse += message.content;
|
|
1803
|
-
}
|
|
1804
|
-
if (message.session_id) {
|
|
1805
|
-
session.setSessionId(message.session_id);
|
|
1806
|
-
}
|
|
1807
|
-
}
|
|
1808
|
-
if (assistantResponse) {
|
|
1809
|
-
session.addMessage("assistant", assistantResponse);
|
|
1810
|
-
}
|
|
1811
|
-
const pendingTools = streamingRenderer.getPendingToolCalls();
|
|
1812
|
-
if (pendingTools.length > 0) {
|
|
1813
|
-
logger.newline();
|
|
1814
|
-
logger.info("Executing tools...");
|
|
1815
|
-
const toolResults = await streamingRenderer.executePendingTools();
|
|
1816
|
-
if (session.getSessionId()) {
|
|
1817
|
-
for await (const message of apiClient.continueCompletion(session.getSessionId(), toolResults)) {
|
|
1818
|
-
await streamingRenderer.processMessage(message);
|
|
1819
|
-
}
|
|
1820
|
-
}
|
|
1821
|
-
}
|
|
1822
|
-
logger.newline();
|
|
1823
|
-
logger.newline();
|
|
1824
|
-
} catch (error) {
|
|
1825
|
-
logger.newline();
|
|
1826
|
-
logger.error("Error:", error.message || error);
|
|
1827
|
-
logger.newline();
|
|
1828
|
-
}
|
|
1829
|
-
rl.prompt();
|
|
1830
|
-
});
|
|
1831
|
-
rl.on("close", () => {
|
|
1832
|
-
logger.newline();
|
|
1833
|
-
logger.success("Chat session ended. Goodbye!");
|
|
1834
|
-
process.exit(0);
|
|
1835
|
-
});
|
|
1836
|
-
} catch (error) {
|
|
1837
|
-
logger.error("Chat command failed", error);
|
|
1838
|
-
process.exit(1);
|
|
1839
|
-
}
|
|
1840
|
-
}
|
|
1841
|
-
function buildPromptWithHistory(session) {
|
|
1842
|
-
const history = session.getHistory();
|
|
1843
|
-
if (history.length === 0) {
|
|
1844
|
-
return "";
|
|
1845
|
-
}
|
|
1846
|
-
const lastUserMessage = history[history.length - 1];
|
|
1847
|
-
if (history.length === 1) {
|
|
1848
|
-
return lastUserMessage.content;
|
|
1849
|
-
}
|
|
1850
|
-
const recentHistory = history.slice(-10);
|
|
1851
|
-
const historyContext = recentHistory.slice(0, -1).map((msg) => `${msg.role === "user" ? "User" : "Assistant"}: ${msg.content}`).join("\n\n");
|
|
1852
|
-
return `Previous conversation:
|
|
1853
|
-
${historyContext}
|
|
1854
|
-
|
|
1855
|
-
Current question:
|
|
1856
|
-
${lastUserMessage.content}`;
|
|
1857
|
-
}
|
|
1858
1616
|
async function scanCommand(options) {
|
|
1859
1617
|
logger.info("Running security vulnerability scan...");
|
|
1860
1618
|
logger.newline();
|
|
@@ -2069,6 +1827,290 @@ async function configCommand(action, key, value) {
|
|
|
2069
1827
|
process.exit(1);
|
|
2070
1828
|
}
|
|
2071
1829
|
}
|
|
1830
|
+
|
|
1831
|
+
// src/commands/chat.ts
|
|
1832
|
+
var ChatSession = class {
|
|
1833
|
+
conversationHistory = [];
|
|
1834
|
+
sessionContext = null;
|
|
1835
|
+
sessionId = null;
|
|
1836
|
+
addMessage(role, content) {
|
|
1837
|
+
this.conversationHistory.push({ role, content });
|
|
1838
|
+
}
|
|
1839
|
+
getHistory() {
|
|
1840
|
+
return this.conversationHistory;
|
|
1841
|
+
}
|
|
1842
|
+
setContext(context) {
|
|
1843
|
+
this.sessionContext = context;
|
|
1844
|
+
}
|
|
1845
|
+
getContext() {
|
|
1846
|
+
return this.sessionContext;
|
|
1847
|
+
}
|
|
1848
|
+
setSessionId(id) {
|
|
1849
|
+
this.sessionId = id;
|
|
1850
|
+
}
|
|
1851
|
+
getSessionId() {
|
|
1852
|
+
return this.sessionId;
|
|
1853
|
+
}
|
|
1854
|
+
clear() {
|
|
1855
|
+
this.conversationHistory = [];
|
|
1856
|
+
this.sessionId = null;
|
|
1857
|
+
}
|
|
1858
|
+
getConversationSummary() {
|
|
1859
|
+
return this.conversationHistory.map((msg) => `${msg.role === "user" ? "You" : "DevWing"}: ${msg.content.substring(0, 100)}...`).join("\n");
|
|
1860
|
+
}
|
|
1861
|
+
};
|
|
1862
|
+
async function handleSpecialCommand(command, session, options) {
|
|
1863
|
+
const cmd = command.toLowerCase().trim();
|
|
1864
|
+
const parts = command.split(" ");
|
|
1865
|
+
const mainCmd = parts[0].toLowerCase();
|
|
1866
|
+
if (cmd === "/help") {
|
|
1867
|
+
logger.box([
|
|
1868
|
+
chalk3.bold("DevWing Chat Commands:"),
|
|
1869
|
+
"",
|
|
1870
|
+
chalk3.bold.yellow("Navigation & Session:"),
|
|
1871
|
+
chalk3.cyan("/help") + " - Show this help message",
|
|
1872
|
+
chalk3.cyan("/exit, /quit") + " - Exit chat mode",
|
|
1873
|
+
chalk3.cyan("/clear") + " - Clear conversation history",
|
|
1874
|
+
chalk3.cyan("/context") + " - Show current context",
|
|
1875
|
+
chalk3.cyan("/history") + " - Show conversation history",
|
|
1876
|
+
"",
|
|
1877
|
+
chalk3.bold.yellow("Specialized Commands:"),
|
|
1878
|
+
chalk3.cyan("/scan") + " - Run security vulnerability scan",
|
|
1879
|
+
chalk3.cyan("/review") + " - Perform code review",
|
|
1880
|
+
chalk3.cyan("/explain <target>") + " - Explain code, file, or concept",
|
|
1881
|
+
"",
|
|
1882
|
+
chalk3.bold.yellow("Project Memory:"),
|
|
1883
|
+
chalk3.cyan("/memory save <content>") + " - Save note to project memory",
|
|
1884
|
+
chalk3.cyan("/memory show") + " - Show all project memories",
|
|
1885
|
+
chalk3.cyan("/memory clear") + " - Clear all project memories",
|
|
1886
|
+
"",
|
|
1887
|
+
chalk3.dim("Just type your message to chat with DevWing!")
|
|
1888
|
+
].join("\n"), { title: "Chat Commands", color: "blue" });
|
|
1889
|
+
return true;
|
|
1890
|
+
}
|
|
1891
|
+
if (cmd === "/exit" || cmd === "/quit") {
|
|
1892
|
+
logger.info("Exiting chat mode...");
|
|
1893
|
+
return false;
|
|
1894
|
+
}
|
|
1895
|
+
if (cmd === "/clear") {
|
|
1896
|
+
session.clear();
|
|
1897
|
+
console.clear();
|
|
1898
|
+
logger.success("Conversation cleared!");
|
|
1899
|
+
printWelcomeBanner();
|
|
1900
|
+
return true;
|
|
1901
|
+
}
|
|
1902
|
+
if (cmd === "/context") {
|
|
1903
|
+
const context = session.getContext();
|
|
1904
|
+
if (!context) {
|
|
1905
|
+
logger.warn("No context loaded yet. Send a message to load context.");
|
|
1906
|
+
return true;
|
|
1907
|
+
}
|
|
1908
|
+
logger.box([
|
|
1909
|
+
chalk3.bold("Current Context:"),
|
|
1910
|
+
"",
|
|
1911
|
+
`Working Directory: ${chalk3.cyan(context.cwd)}`,
|
|
1912
|
+
`Shell: ${context.shell}`,
|
|
1913
|
+
`OS: ${context.os}`,
|
|
1914
|
+
`Files: ${context.files.length}`,
|
|
1915
|
+
context.git_branch ? `Git Branch: ${context.git_branch}` : "",
|
|
1916
|
+
"",
|
|
1917
|
+
"Files included:",
|
|
1918
|
+
...context.files.slice(0, 10).map((f) => ` \u2022 ${f.path}`),
|
|
1919
|
+
context.files.length > 10 ? ` ... and ${context.files.length - 10} more` : ""
|
|
1920
|
+
].filter(Boolean).join("\n"), { title: "Context Info", color: "cyan" });
|
|
1921
|
+
return true;
|
|
1922
|
+
}
|
|
1923
|
+
if (cmd === "/history") {
|
|
1924
|
+
const history = session.getHistory();
|
|
1925
|
+
if (history.length === 0) {
|
|
1926
|
+
logger.info("No conversation history yet.");
|
|
1927
|
+
return true;
|
|
1928
|
+
}
|
|
1929
|
+
logger.box([
|
|
1930
|
+
chalk3.bold("Conversation History:"),
|
|
1931
|
+
"",
|
|
1932
|
+
session.getConversationSummary()
|
|
1933
|
+
].join("\n"), { title: "History", color: "magenta" });
|
|
1934
|
+
return true;
|
|
1935
|
+
}
|
|
1936
|
+
if (cmd === "/scan") {
|
|
1937
|
+
logger.newline();
|
|
1938
|
+
await scanCommand(options);
|
|
1939
|
+
return true;
|
|
1940
|
+
}
|
|
1941
|
+
if (cmd === "/review") {
|
|
1942
|
+
logger.newline();
|
|
1943
|
+
await reviewCommand(options);
|
|
1944
|
+
return true;
|
|
1945
|
+
}
|
|
1946
|
+
if (mainCmd === "/explain") {
|
|
1947
|
+
const target = parts.slice(1).join(" ").trim();
|
|
1948
|
+
if (!target) {
|
|
1949
|
+
logger.error("Please provide something to explain. Example: /explain src/auth.ts");
|
|
1950
|
+
return true;
|
|
1951
|
+
}
|
|
1952
|
+
logger.newline();
|
|
1953
|
+
await explainCommand(target, options);
|
|
1954
|
+
return true;
|
|
1955
|
+
}
|
|
1956
|
+
if (mainCmd === "/memory") {
|
|
1957
|
+
const subCmd = parts[1]?.toLowerCase();
|
|
1958
|
+
if (subCmd === "save") {
|
|
1959
|
+
const content = parts.slice(2).join(" ").trim();
|
|
1960
|
+
if (!content) {
|
|
1961
|
+
logger.error("Please provide content to save. Example: /memory save Auth uses JWT");
|
|
1962
|
+
return true;
|
|
1963
|
+
}
|
|
1964
|
+
logger.newline();
|
|
1965
|
+
await memoryCommand("save", content, options);
|
|
1966
|
+
return true;
|
|
1967
|
+
}
|
|
1968
|
+
if (subCmd === "show") {
|
|
1969
|
+
logger.newline();
|
|
1970
|
+
await memoryCommand("show", void 0, options);
|
|
1971
|
+
return true;
|
|
1972
|
+
}
|
|
1973
|
+
if (subCmd === "clear") {
|
|
1974
|
+
logger.newline();
|
|
1975
|
+
await memoryCommand("clear", void 0, options);
|
|
1976
|
+
return true;
|
|
1977
|
+
}
|
|
1978
|
+
logger.error("Invalid memory command. Use: /memory save|show|clear");
|
|
1979
|
+
return true;
|
|
1980
|
+
}
|
|
1981
|
+
logger.warn(`Unknown command: ${mainCmd}. Type /help for available commands.`);
|
|
1982
|
+
return true;
|
|
1983
|
+
}
|
|
1984
|
+
function printWelcomeBanner() {
|
|
1985
|
+
logger.box([
|
|
1986
|
+
chalk3.bold.cyan("DevWing AI - Interactive Chat Mode"),
|
|
1987
|
+
"",
|
|
1988
|
+
"Chat with AI about your codebase. Type your message and press Enter.",
|
|
1989
|
+
"",
|
|
1990
|
+
chalk3.dim("Type /help for commands \u2022 /exit to quit")
|
|
1991
|
+
].join("\n"), { title: "\u{1F680} Welcome", color: "cyan" });
|
|
1992
|
+
}
|
|
1993
|
+
async function chatCommand(options) {
|
|
1994
|
+
try {
|
|
1995
|
+
const apiKey = await configManager.getApiKey();
|
|
1996
|
+
if (!apiKey) {
|
|
1997
|
+
logger.error('Not authenticated. Run "devwing login" first.');
|
|
1998
|
+
process.exit(1);
|
|
1999
|
+
}
|
|
2000
|
+
const session = new ChatSession();
|
|
2001
|
+
console.clear();
|
|
2002
|
+
printWelcomeBanner();
|
|
2003
|
+
logger.newline();
|
|
2004
|
+
const rl = readline.createInterface({
|
|
2005
|
+
input: process.stdin,
|
|
2006
|
+
output: process.stdout,
|
|
2007
|
+
prompt: chalk3.bold.green("You: ")
|
|
2008
|
+
});
|
|
2009
|
+
rl.on("SIGINT", () => {
|
|
2010
|
+
logger.newline();
|
|
2011
|
+
logger.info("Exiting chat mode...");
|
|
2012
|
+
rl.close();
|
|
2013
|
+
process.exit(0);
|
|
2014
|
+
});
|
|
2015
|
+
logger.startSpinner("Loading codebase context...");
|
|
2016
|
+
const collector = new ContextCollector(process.cwd());
|
|
2017
|
+
const initialContext = await collector.collect("");
|
|
2018
|
+
session.setContext(initialContext);
|
|
2019
|
+
logger.succeedSpinner("Context loaded!");
|
|
2020
|
+
logger.newline();
|
|
2021
|
+
rl.prompt();
|
|
2022
|
+
rl.on("line", async (input) => {
|
|
2023
|
+
const userMessage = input.trim();
|
|
2024
|
+
if (!userMessage) {
|
|
2025
|
+
rl.prompt();
|
|
2026
|
+
return;
|
|
2027
|
+
}
|
|
2028
|
+
if (userMessage.startsWith("/")) {
|
|
2029
|
+
const shouldContinue = await handleSpecialCommand(userMessage, session, options);
|
|
2030
|
+
if (!shouldContinue) {
|
|
2031
|
+
rl.close();
|
|
2032
|
+
return;
|
|
2033
|
+
}
|
|
2034
|
+
logger.newline();
|
|
2035
|
+
rl.prompt();
|
|
2036
|
+
return;
|
|
2037
|
+
}
|
|
2038
|
+
session.addMessage("user", userMessage);
|
|
2039
|
+
logger.newline();
|
|
2040
|
+
logger.info(chalk3.dim("DevWing is thinking..."));
|
|
2041
|
+
logger.newline();
|
|
2042
|
+
try {
|
|
2043
|
+
const request = {
|
|
2044
|
+
prompt: buildPromptWithHistory(session),
|
|
2045
|
+
mode: options.mode,
|
|
2046
|
+
model: options.model,
|
|
2047
|
+
project_id: options.project || configManager.getProjectId(),
|
|
2048
|
+
context: session.getContext(),
|
|
2049
|
+
stream: true,
|
|
2050
|
+
max_tokens: 4096
|
|
2051
|
+
};
|
|
2052
|
+
let assistantResponse = "";
|
|
2053
|
+
streamingRenderer.reset();
|
|
2054
|
+
streamingRenderer.clearPendingTools();
|
|
2055
|
+
for await (const message of apiClient.streamCompletion(request)) {
|
|
2056
|
+
await streamingRenderer.processMessage(message);
|
|
2057
|
+
if (message.type === "token" && message.content) {
|
|
2058
|
+
assistantResponse += message.content;
|
|
2059
|
+
}
|
|
2060
|
+
if (message.session_id) {
|
|
2061
|
+
session.setSessionId(message.session_id);
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
if (assistantResponse) {
|
|
2065
|
+
session.addMessage("assistant", assistantResponse);
|
|
2066
|
+
}
|
|
2067
|
+
const pendingTools = streamingRenderer.getPendingToolCalls();
|
|
2068
|
+
if (pendingTools.length > 0) {
|
|
2069
|
+
logger.newline();
|
|
2070
|
+
logger.info("Executing tools...");
|
|
2071
|
+
const toolResults = await streamingRenderer.executePendingTools();
|
|
2072
|
+
if (session.getSessionId()) {
|
|
2073
|
+
for await (const message of apiClient.continueCompletion(session.getSessionId(), toolResults)) {
|
|
2074
|
+
await streamingRenderer.processMessage(message);
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
logger.newline();
|
|
2079
|
+
logger.newline();
|
|
2080
|
+
} catch (error) {
|
|
2081
|
+
logger.newline();
|
|
2082
|
+
logger.error("Error:", error.message || error);
|
|
2083
|
+
logger.newline();
|
|
2084
|
+
}
|
|
2085
|
+
rl.prompt();
|
|
2086
|
+
});
|
|
2087
|
+
rl.on("close", () => {
|
|
2088
|
+
logger.newline();
|
|
2089
|
+
logger.success("Chat session ended. Goodbye!");
|
|
2090
|
+
process.exit(0);
|
|
2091
|
+
});
|
|
2092
|
+
} catch (error) {
|
|
2093
|
+
logger.error("Chat command failed", error);
|
|
2094
|
+
process.exit(1);
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
function buildPromptWithHistory(session) {
|
|
2098
|
+
const history = session.getHistory();
|
|
2099
|
+
if (history.length === 0) {
|
|
2100
|
+
return "";
|
|
2101
|
+
}
|
|
2102
|
+
const lastUserMessage = history[history.length - 1];
|
|
2103
|
+
if (history.length === 1) {
|
|
2104
|
+
return lastUserMessage.content;
|
|
2105
|
+
}
|
|
2106
|
+
const recentHistory = history.slice(-10);
|
|
2107
|
+
const historyContext = recentHistory.slice(0, -1).map((msg) => `${msg.role === "user" ? "User" : "Assistant"}: ${msg.content}`).join("\n\n");
|
|
2108
|
+
return `Previous conversation:
|
|
2109
|
+
${historyContext}
|
|
2110
|
+
|
|
2111
|
+
Current question:
|
|
2112
|
+
${lastUserMessage.content}`;
|
|
2113
|
+
}
|
|
2072
2114
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
2073
2115
|
var __dirname2 = dirname(__filename2);
|
|
2074
2116
|
function getCurrentVersion() {
|
|
@@ -2215,7 +2257,7 @@ async function updateCommand(options) {
|
|
|
2215
2257
|
|
|
2216
2258
|
// src/index.ts
|
|
2217
2259
|
var program = new Command();
|
|
2218
|
-
var VERSION = "0.1.
|
|
2260
|
+
var VERSION = "0.1.4";
|
|
2219
2261
|
program.name("devwing").description("DevWing.ai - Your AI Wingman in the Terminal").version(VERSION, "-v, --version", "Display version number").helpOption("-h, --help", "Display help information");
|
|
2220
2262
|
program.option("--mode <mode>", "AI mode: general|frontend|backend|security|devops").option("--model <model>", "Specific model to use").option("--project <id>", "Project ID").option("--workspace <id>", "Workspace ID").option("--verbose", "Verbose output for debugging").option("-y, --yes", "Auto-confirm destructive actions");
|
|
2221
2263
|
program.command("login").description("Authenticate with DevWing").action(async () => {
|
|
@@ -2269,13 +2311,13 @@ configCmd.command("set <key> <value>").description("Set configuration value").ac
|
|
|
2269
2311
|
program.command("update").description("Check for and install CLI updates").option("--check", "Only check for updates, do not install").option("--force", "Skip confirmation prompt").action(async (options) => {
|
|
2270
2312
|
await updateCommand(options);
|
|
2271
2313
|
});
|
|
2272
|
-
program.argument("[prompt...]", "Natural language prompt for AI").action(async (promptParts) => {
|
|
2314
|
+
program.argument("[prompt...]", "Natural language prompt for AI (optional - starts chat mode if empty)").action(async (promptParts) => {
|
|
2315
|
+
const opts = program.opts();
|
|
2273
2316
|
if (promptParts.length === 0) {
|
|
2274
|
-
|
|
2317
|
+
await chatCommand(opts);
|
|
2275
2318
|
return;
|
|
2276
2319
|
}
|
|
2277
2320
|
const prompt = promptParts.join(" ");
|
|
2278
|
-
const opts = program.opts();
|
|
2279
2321
|
await promptCommand(prompt, opts);
|
|
2280
2322
|
});
|
|
2281
2323
|
program.exitOverride();
|