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 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("Ready to authenticate!");
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.3";
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
- program.help();
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();