@bike4mind/cli 0.2.14-feat-cli-mcp-management.17478 → 0.2.14-feat-cli-markdown-rendering.17480
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 +169 -64
- package/package.json +7 -6
package/dist/index.js
CHANGED
|
@@ -82,14 +82,14 @@ import {
|
|
|
82
82
|
import "./chunk-BPFEGDC7.js";
|
|
83
83
|
|
|
84
84
|
// src/index.tsx
|
|
85
|
-
import
|
|
86
|
-
import { render, Box as
|
|
85
|
+
import React19, { useState as useState8, useEffect as useEffect3, useCallback, useRef as useRef2 } from "react";
|
|
86
|
+
import { render, Box as Box18, Text as Text18, useApp, useInput as useInput7 } from "ink";
|
|
87
87
|
import { execSync } from "child_process";
|
|
88
88
|
import { v4 as uuidv49 } from "uuid";
|
|
89
89
|
|
|
90
90
|
// src/components/App.tsx
|
|
91
|
-
import
|
|
92
|
-
import { Box as
|
|
91
|
+
import React13, { useState as useState4 } from "react";
|
|
92
|
+
import { Box as Box12, Text as Text12, Static } from "ink";
|
|
93
93
|
|
|
94
94
|
// src/components/StatusBar.tsx
|
|
95
95
|
import React from "react";
|
|
@@ -1416,24 +1416,128 @@ function McpViewer({ config, mcpManager, onClose }) {
|
|
|
1416
1416
|
}
|
|
1417
1417
|
|
|
1418
1418
|
// src/components/MessageItem.tsx
|
|
1419
|
+
import React12 from "react";
|
|
1420
|
+
import { Box as Box11, Text as Text11 } from "ink";
|
|
1421
|
+
|
|
1422
|
+
// src/components/MarkdownRenderer.tsx
|
|
1419
1423
|
import React11 from "react";
|
|
1420
1424
|
import { Box as Box10, Text as Text10 } from "ink";
|
|
1425
|
+
import { marked } from "marked";
|
|
1426
|
+
import { highlight } from "cli-highlight";
|
|
1427
|
+
function MarkdownRenderer({ content }) {
|
|
1428
|
+
const tokens = marked.lexer(content);
|
|
1429
|
+
return /* @__PURE__ */ React11.createElement(Box10, { flexDirection: "column" }, tokens.map((token, idx) => renderToken(token, idx)));
|
|
1430
|
+
}
|
|
1431
|
+
function renderToken(token, idx) {
|
|
1432
|
+
switch (token.type) {
|
|
1433
|
+
case "heading":
|
|
1434
|
+
return renderHeading(token, idx);
|
|
1435
|
+
case "code":
|
|
1436
|
+
return renderCodeBlock(token, idx);
|
|
1437
|
+
case "paragraph":
|
|
1438
|
+
return renderParagraph(token, idx);
|
|
1439
|
+
case "list":
|
|
1440
|
+
return renderList(token, idx);
|
|
1441
|
+
case "blockquote":
|
|
1442
|
+
return renderBlockquote(token, idx);
|
|
1443
|
+
case "hr":
|
|
1444
|
+
return /* @__PURE__ */ React11.createElement(Text10, { key: idx, dimColor: true }, "\u2500".repeat(50));
|
|
1445
|
+
case "space":
|
|
1446
|
+
return null;
|
|
1447
|
+
default:
|
|
1448
|
+
if ("text" in token) {
|
|
1449
|
+
return /* @__PURE__ */ React11.createElement(Text10, { key: idx }, token.text);
|
|
1450
|
+
}
|
|
1451
|
+
return null;
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
function renderHeading(token, idx) {
|
|
1455
|
+
const colors = {
|
|
1456
|
+
1: "cyan",
|
|
1457
|
+
2: "cyan",
|
|
1458
|
+
3: "blue",
|
|
1459
|
+
4: "blue",
|
|
1460
|
+
5: "white",
|
|
1461
|
+
6: "white"
|
|
1462
|
+
};
|
|
1463
|
+
const color = colors[token.depth] || "white";
|
|
1464
|
+
return /* @__PURE__ */ React11.createElement(Box10, { key: idx, marginTop: idx > 0 ? 1 : 0 }, /* @__PURE__ */ React11.createElement(Text10, { bold: true, color }, parseInlineText(token.text)));
|
|
1465
|
+
}
|
|
1466
|
+
function renderCodeBlock(token, idx) {
|
|
1467
|
+
let highlightedCode;
|
|
1468
|
+
try {
|
|
1469
|
+
highlightedCode = highlight(token.text, {
|
|
1470
|
+
language: token.lang || "javascript",
|
|
1471
|
+
ignoreIllegals: true
|
|
1472
|
+
});
|
|
1473
|
+
} catch (error) {
|
|
1474
|
+
highlightedCode = token.text;
|
|
1475
|
+
}
|
|
1476
|
+
return /* @__PURE__ */ React11.createElement(Box10, { key: idx, flexDirection: "column", paddingLeft: 2 }, token.lang && /* @__PURE__ */ React11.createElement(Text10, { dimColor: true, color: "gray" }, token.lang), /* @__PURE__ */ React11.createElement(Text10, null, highlightedCode));
|
|
1477
|
+
}
|
|
1478
|
+
function renderParagraph(token, idx) {
|
|
1479
|
+
return /* @__PURE__ */ React11.createElement(Box10, { key: idx }, /* @__PURE__ */ React11.createElement(Text10, null, parseInlineText(token.text)));
|
|
1480
|
+
}
|
|
1481
|
+
function renderList(token, idx) {
|
|
1482
|
+
return /* @__PURE__ */ React11.createElement(Box10, { key: idx, flexDirection: "column" }, token.items.map((item, itemIdx) => renderListItem(item, itemIdx, token.ordered, itemIdx + 1)));
|
|
1483
|
+
}
|
|
1484
|
+
function renderListItem(item, idx, ordered, number) {
|
|
1485
|
+
const bullet = ordered ? `${number}.` : "\u2022";
|
|
1486
|
+
return /* @__PURE__ */ React11.createElement(Box10, { key: idx, paddingLeft: 2 }, /* @__PURE__ */ React11.createElement(Text10, null, bullet, " ", parseInlineText(item.text)));
|
|
1487
|
+
}
|
|
1488
|
+
function renderBlockquote(token, idx) {
|
|
1489
|
+
return /* @__PURE__ */ React11.createElement(Box10, { key: idx, paddingLeft: 2, borderStyle: "single", borderLeft: true, borderColor: "gray" }, token.tokens.map((t, i) => renderToken(t, i)));
|
|
1490
|
+
}
|
|
1491
|
+
function parseInlineText(text) {
|
|
1492
|
+
const parts = [];
|
|
1493
|
+
let lastIndex = 0;
|
|
1494
|
+
const regex = /(\*\*(.+?)\*\*)|(\*(.+?)\*)|(`(.+?)`)/g;
|
|
1495
|
+
let match;
|
|
1496
|
+
while ((match = regex.exec(text)) !== null) {
|
|
1497
|
+
if (match.index > lastIndex) {
|
|
1498
|
+
parts.push(text.slice(lastIndex, match.index));
|
|
1499
|
+
}
|
|
1500
|
+
if (match[1]) {
|
|
1501
|
+
parts.push(
|
|
1502
|
+
/* @__PURE__ */ React11.createElement(Text10, { key: match.index, bold: true }, match[2])
|
|
1503
|
+
);
|
|
1504
|
+
} else if (match[3]) {
|
|
1505
|
+
parts.push(
|
|
1506
|
+
/* @__PURE__ */ React11.createElement(Text10, { key: match.index, italic: true }, match[4])
|
|
1507
|
+
);
|
|
1508
|
+
} else if (match[5]) {
|
|
1509
|
+
parts.push(
|
|
1510
|
+
/* @__PURE__ */ React11.createElement(Text10, { key: match.index, color: "cyan" }, match[6])
|
|
1511
|
+
);
|
|
1512
|
+
}
|
|
1513
|
+
lastIndex = regex.lastIndex;
|
|
1514
|
+
}
|
|
1515
|
+
if (lastIndex < text.length) {
|
|
1516
|
+
parts.push(text.slice(lastIndex));
|
|
1517
|
+
}
|
|
1518
|
+
if (parts.length === 0) {
|
|
1519
|
+
return text;
|
|
1520
|
+
}
|
|
1521
|
+
return /* @__PURE__ */ React11.createElement(React11.Fragment, null, parts);
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
// src/components/MessageItem.tsx
|
|
1421
1525
|
function MessageItem({ message }) {
|
|
1422
1526
|
const isUser = message.role === "user";
|
|
1423
1527
|
const isSystem = message.role === "system";
|
|
1424
|
-
return /* @__PURE__ */
|
|
1528
|
+
return /* @__PURE__ */ React12.createElement(Box11, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React12.createElement(Box11, null, /* @__PURE__ */ React12.createElement(Text11, { bold: true, color: isUser ? "cyan" : isSystem ? "gray" : "green" }, isUser ? "\u{1F464} You" : isSystem ? "\u2139\uFE0F System" : "\u{1F916} Assistant"), isUser && /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, " \u2022 ", new Date(message.timestamp).toLocaleTimeString())), isUser && message.content && /* @__PURE__ */ React12.createElement(Box11, { paddingLeft: 2 }, /* @__PURE__ */ React12.createElement(Text11, { backgroundColor: "whiteBright", color: "black" }, " ", message.content, " ")), !isUser && message.metadata?.steps && message.metadata.steps.length > 0 && /* @__PURE__ */ React12.createElement(Box11, { paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true, bold: true }, "\u{1F527} Agent Reasoning Trace (", message.metadata.steps.filter((s) => s.type === "action").length, " ", "tools used, ", message.metadata.steps.length, " total steps)", message.metadata.tokenUsage && ` \u2022 ${message.metadata.tokenUsage.total} tokens`), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, "Step types: ", message.metadata.steps.map((s) => s.type).join(", ")), message.metadata.steps.map((step, idx) => {
|
|
1425
1529
|
if (step.type === "thought") {
|
|
1426
|
-
return /* @__PURE__ */
|
|
1530
|
+
return /* @__PURE__ */ React12.createElement(Box11, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React12.createElement(Text11, { color: "blue" }, "\u{1F4AD} Thought:"), /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, ` ${step.content}`));
|
|
1427
1531
|
}
|
|
1428
1532
|
if (step.type === "action") {
|
|
1429
1533
|
const toolName = step.metadata?.toolName || "unknown";
|
|
1430
1534
|
const toolInput = step.metadata?.toolInput;
|
|
1431
1535
|
const observationStep = message.metadata.steps[idx + 1];
|
|
1432
1536
|
const result = observationStep?.type === "observation" ? observationStep.content : null;
|
|
1433
|
-
return /* @__PURE__ */
|
|
1537
|
+
return /* @__PURE__ */ React12.createElement(Box11, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React12.createElement(Text11, { color: "yellow" }, "\u{1F527} Action: ", toolName), toolInput && /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, ` Input: ${typeof toolInput === "string" ? toolInput : JSON.stringify(toolInput).slice(0, 100)}`), result && /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, ` Result: ${typeof result === "string" ? result.slice(0, 200) : JSON.stringify(result).slice(0, 200)}${(typeof result === "string" ? result.length : JSON.stringify(result).length) > 200 ? "..." : ""}`));
|
|
1434
1538
|
}
|
|
1435
1539
|
return null;
|
|
1436
|
-
}).filter(Boolean)), !isUser && message.content !== "..." && /* @__PURE__ */
|
|
1540
|
+
}).filter(Boolean)), !isUser && message.content !== "..." && /* @__PURE__ */ React12.createElement(Box11, { paddingLeft: 2, marginTop: message.metadata?.steps?.length ? 1 : 0 }, message.metadata?.permissionDenied ? /* @__PURE__ */ React12.createElement(Text11, { color: "yellow" }, "\u26A0\uFE0F ", message.content) : /* @__PURE__ */ React12.createElement(MarkdownRenderer, { content: message.content })), message.metadata?.tokenUsage && (!message.metadata.steps || message.metadata.steps.length === 0) && /* @__PURE__ */ React12.createElement(Box11, { paddingLeft: 2 }, /* @__PURE__ */ React12.createElement(Text11, { dimColor: true }, `${message.metadata.tokenUsage.total} tokens`)));
|
|
1437
1541
|
}
|
|
1438
1542
|
|
|
1439
1543
|
// src/utils/processFileReferences.ts
|
|
@@ -1580,7 +1684,7 @@ function App({
|
|
|
1580
1684
|
const exitRequested = useCliStore((state) => state.exitRequested);
|
|
1581
1685
|
const setIsThinking = useCliStore((state) => state.setIsThinking);
|
|
1582
1686
|
const [isBashMode, setIsBashMode] = useState4(false);
|
|
1583
|
-
const handleSubmit =
|
|
1687
|
+
const handleSubmit = React13.useCallback(
|
|
1584
1688
|
async (input) => {
|
|
1585
1689
|
const trimmed = input.trim();
|
|
1586
1690
|
if (!trimmed) return;
|
|
@@ -1609,7 +1713,7 @@ ${errorBlock}`;
|
|
|
1609
1713
|
},
|
|
1610
1714
|
[onMessage, onCommand, setIsThinking]
|
|
1611
1715
|
);
|
|
1612
|
-
return /* @__PURE__ */
|
|
1716
|
+
return /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column" }, showConfigEditor && config && onSaveConfig ? /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React13.createElement(
|
|
1613
1717
|
ConfigEditor,
|
|
1614
1718
|
{
|
|
1615
1719
|
config,
|
|
@@ -1619,8 +1723,8 @@ ${errorBlock}`;
|
|
|
1619
1723
|
}
|
|
1620
1724
|
)) : showMcpViewer && config ? (
|
|
1621
1725
|
/* MCP Viewer - full screen takeover */
|
|
1622
|
-
/* @__PURE__ */
|
|
1623
|
-
) : /* @__PURE__ */
|
|
1726
|
+
/* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React13.createElement(McpViewer, { config, mcpManager, onClose: () => setShowMcpViewer(false) }))
|
|
1727
|
+
) : /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(Static, { items: messages }, (message) => /* @__PURE__ */ React13.createElement(Box12, { key: message.id, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React13.createElement(MessageItem, { message }))), /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column" }, pendingMessages.map((message) => /* @__PURE__ */ React13.createElement(Box12, { key: message.id, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React13.createElement(MessageItem, { message })))), permissionPrompt && /* @__PURE__ */ React13.createElement(Box12, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ React13.createElement(
|
|
1624
1728
|
PermissionPrompt,
|
|
1625
1729
|
{
|
|
1626
1730
|
toolName: permissionPrompt.toolName,
|
|
@@ -1629,7 +1733,7 @@ ${errorBlock}`;
|
|
|
1629
1733
|
canBeTrusted: permissionPrompt.canBeTrusted,
|
|
1630
1734
|
onResponse: onPermissionResponse
|
|
1631
1735
|
}
|
|
1632
|
-
)), !permissionPrompt && /* @__PURE__ */
|
|
1736
|
+
)), !permissionPrompt && /* @__PURE__ */ React13.createElement(AgentThinking, null), exitRequested && /* @__PURE__ */ React13.createElement(Box12, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text12, { color: "yellow", bold: true }, "Press Ctrl+C again to exit")), /* @__PURE__ */ React13.createElement(Box12, { borderStyle: "single", borderColor: isBashMode ? "yellow" : "cyan", paddingX: 1 }, /* @__PURE__ */ React13.createElement(
|
|
1633
1737
|
InputPrompt,
|
|
1634
1738
|
{
|
|
1635
1739
|
onSubmit: handleSubmit,
|
|
@@ -1642,24 +1746,24 @@ ${errorBlock}`;
|
|
|
1642
1746
|
onPrefillConsumed,
|
|
1643
1747
|
onBashModeChange: setIsBashMode
|
|
1644
1748
|
}
|
|
1645
|
-
)), /* @__PURE__ */
|
|
1749
|
+
)), /* @__PURE__ */ React13.createElement(StatusBar, { sessionName, model: currentModel, tokenUsage: totalTokens })));
|
|
1646
1750
|
}
|
|
1647
1751
|
|
|
1648
1752
|
// src/components/MessageList.tsx
|
|
1649
|
-
import
|
|
1650
|
-
import { Box as
|
|
1753
|
+
import React14 from "react";
|
|
1754
|
+
import { Box as Box13, Text as Text13 } from "ink";
|
|
1651
1755
|
function stripThinkingTags(content) {
|
|
1652
1756
|
return content.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
|
|
1653
1757
|
}
|
|
1654
|
-
var MessageList =
|
|
1758
|
+
var MessageList = React14.memo(
|
|
1655
1759
|
function MessageList2({ messages }) {
|
|
1656
1760
|
if (messages.length === 0) {
|
|
1657
|
-
return /* @__PURE__ */
|
|
1761
|
+
return /* @__PURE__ */ React14.createElement(Box13, { paddingY: 1 }, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "No messages yet. Type a message to start!"));
|
|
1658
1762
|
}
|
|
1659
|
-
return /* @__PURE__ */
|
|
1763
|
+
return /* @__PURE__ */ React14.createElement(Box13, { flexDirection: "column", gap: 1, paddingY: 1 }, messages.map((message, index) => /* @__PURE__ */ React14.createElement(Box13, { key: index, flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React14.createElement(Box13, null, /* @__PURE__ */ React14.createElement(Text13, { bold: true, color: message.role === "user" ? "cyan" : "green" }, message.role === "user" ? "\u{1F464} You" : "\u{1F916} Assistant"), /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, " \u2022 ", new Date(message.timestamp).toLocaleTimeString())), /* @__PURE__ */ React14.createElement(Box13, { paddingLeft: 2 }, message.metadata?.permissionDenied ? /* @__PURE__ */ React14.createElement(Text13, { color: "yellow" }, "\u26A0\uFE0F ", stripThinkingTags(message.content)) : /* @__PURE__ */ React14.createElement(Text13, null, stripThinkingTags(message.content))), message.metadata?.steps && message.metadata.steps.length > 0 && /* @__PURE__ */ React14.createElement(Box13, { paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true, bold: true }, "\u{1F527} Agent Reasoning Trace (", message.metadata.steps.filter((s) => s.type === "action").length, " tools used,", " ", message.metadata.steps.length, " total steps)", message.metadata.tokenUsage && ` \u2022 ${message.metadata.tokenUsage.total} tokens`), /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, "Step types: ", message.metadata.steps.map((s) => s.type).join(", ")), message.metadata.steps.map((step, idx) => {
|
|
1660
1764
|
if (step.type === "thought") {
|
|
1661
|
-
return /* @__PURE__ */
|
|
1662
|
-
|
|
1765
|
+
return /* @__PURE__ */ React14.createElement(Box13, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Text13, { color: "blue" }, "\u{1F4AD} Thought:"), /* @__PURE__ */ React14.createElement(
|
|
1766
|
+
Text13,
|
|
1663
1767
|
{
|
|
1664
1768
|
dimColor: true
|
|
1665
1769
|
},
|
|
@@ -1671,10 +1775,10 @@ var MessageList = React13.memo(
|
|
|
1671
1775
|
const toolInput = step.metadata?.toolInput;
|
|
1672
1776
|
const observationStep = message.metadata.steps[idx + 1];
|
|
1673
1777
|
const result = observationStep?.type === "observation" ? observationStep.content : null;
|
|
1674
|
-
return /* @__PURE__ */
|
|
1778
|
+
return /* @__PURE__ */ React14.createElement(Box13, { key: idx, paddingLeft: 2, marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React14.createElement(Text13, { color: "yellow" }, "\u{1F527} Action: ", toolName), toolInput && /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, ` Input: ${typeof toolInput === "string" ? toolInput : JSON.stringify(toolInput).slice(0, 100)}`), result && /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, ` Result: ${typeof result === "string" ? result.slice(0, 200) : JSON.stringify(result).slice(0, 200)}${(typeof result === "string" ? result.length : JSON.stringify(result).length) > 200 ? "..." : ""}`));
|
|
1675
1779
|
}
|
|
1676
1780
|
return null;
|
|
1677
|
-
}).filter(Boolean)), message.metadata?.tokenUsage && (!message.metadata.steps || message.metadata.steps.length === 0) && /* @__PURE__ */
|
|
1781
|
+
}).filter(Boolean)), message.metadata?.tokenUsage && (!message.metadata.steps || message.metadata.steps.length === 0) && /* @__PURE__ */ React14.createElement(Box13, { paddingLeft: 2 }, /* @__PURE__ */ React14.createElement(Text13, { dimColor: true }, `${message.metadata.tokenUsage.total} tokens`)))));
|
|
1678
1782
|
},
|
|
1679
1783
|
(prevProps, nextProps) => {
|
|
1680
1784
|
if (prevProps.messages.length !== nextProps.messages.length) {
|
|
@@ -1685,8 +1789,8 @@ var MessageList = React13.memo(
|
|
|
1685
1789
|
);
|
|
1686
1790
|
|
|
1687
1791
|
// src/components/TrustLocationSelector.tsx
|
|
1688
|
-
import
|
|
1689
|
-
import { Box as
|
|
1792
|
+
import React15 from "react";
|
|
1793
|
+
import { Box as Box14, Text as Text14 } from "ink";
|
|
1690
1794
|
import SelectInput2 from "ink-select-input";
|
|
1691
1795
|
function TrustLocationSelector({ inProject, onSelect, onCancel }) {
|
|
1692
1796
|
const items = [];
|
|
@@ -1707,19 +1811,19 @@ function TrustLocationSelector({ inProject, onSelect, onCancel }) {
|
|
|
1707
1811
|
const handleSelect = (item) => {
|
|
1708
1812
|
onSelect(item.value);
|
|
1709
1813
|
};
|
|
1710
|
-
return /* @__PURE__ */
|
|
1814
|
+
return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React15.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text14, { bold: true }, "Where should this rule be saved?")), /* @__PURE__ */ React15.createElement(
|
|
1711
1815
|
SelectInput2,
|
|
1712
1816
|
{
|
|
1713
1817
|
items,
|
|
1714
1818
|
onSelect: handleSelect,
|
|
1715
|
-
itemComponent: ({ isSelected, label }) => /* @__PURE__ */
|
|
1819
|
+
itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React15.createElement(Box14, null, /* @__PURE__ */ React15.createElement(Text14, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
|
|
1716
1820
|
}
|
|
1717
|
-
), /* @__PURE__ */
|
|
1821
|
+
), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text14, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Ctrl+C to cancel")));
|
|
1718
1822
|
}
|
|
1719
1823
|
|
|
1720
1824
|
// src/components/RewindSelector.tsx
|
|
1721
|
-
import
|
|
1722
|
-
import { Box as
|
|
1825
|
+
import React16, { useState as useState5 } from "react";
|
|
1826
|
+
import { Box as Box15, Text as Text15, useInput as useInput5 } from "ink";
|
|
1723
1827
|
import SelectInput3 from "ink-select-input";
|
|
1724
1828
|
function RewindSelector({ messages, onSelect, onCancel }) {
|
|
1725
1829
|
const [step, setStep] = useState5("selection");
|
|
@@ -1761,14 +1865,14 @@ function RewindSelector({ messages, onSelect, onCancel }) {
|
|
|
1761
1865
|
return sum2 + (msg.metadata?.tokenUsage?.total || 0);
|
|
1762
1866
|
}, 0);
|
|
1763
1867
|
if (step === "selection") {
|
|
1764
|
-
return /* @__PURE__ */
|
|
1868
|
+
return /* @__PURE__ */ React16.createElement(Box15, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React16.createElement(Box15, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text15, { bold: true }, "Select a point to rewind to:")), /* @__PURE__ */ React16.createElement(
|
|
1765
1869
|
SelectInput3,
|
|
1766
1870
|
{
|
|
1767
1871
|
items,
|
|
1768
1872
|
onSelect: handleSelectionSelect,
|
|
1769
|
-
itemComponent: ({ isSelected, label }) => /* @__PURE__ */
|
|
1873
|
+
itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React16.createElement(Box15, null, /* @__PURE__ */ React16.createElement(Text15, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
|
|
1770
1874
|
}
|
|
1771
|
-
), /* @__PURE__ */
|
|
1875
|
+
), /* @__PURE__ */ React16.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text15, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Esc to cancel")));
|
|
1772
1876
|
}
|
|
1773
1877
|
const confirmationItems = [
|
|
1774
1878
|
{ label: "Yes, rewind to this point", value: "confirm" },
|
|
@@ -1776,19 +1880,19 @@ function RewindSelector({ messages, onSelect, onCancel }) {
|
|
|
1776
1880
|
];
|
|
1777
1881
|
const selectedMessage = selectedMessageIndex !== null && selectedMessageIndex >= 0 && selectedMessageIndex < messages.length ? messages[selectedMessageIndex] : null;
|
|
1778
1882
|
const selectedPreview = selectedMessage ? selectedMessage.content.length > 50 ? selectedMessage.content.substring(0, 50) + "..." : selectedMessage.content : "";
|
|
1779
|
-
return /* @__PURE__ */
|
|
1883
|
+
return /* @__PURE__ */ React16.createElement(Box15, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React16.createElement(Box15, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Text15, { bold: true }, "Confirm rewind operation:"), /* @__PURE__ */ React16.createElement(Text15, { dimColor: true }, "Message: ", selectedPreview), /* @__PURE__ */ React16.createElement(Text15, { color: "yellow" }, "This will remove ", messagesToRemove.length, " message(s) (", tokensToRemove.toLocaleString(), " tokens)"), /* @__PURE__ */ React16.createElement(Text15, { color: "cyan" }, "The selected message will be placed in your input for editing.")), /* @__PURE__ */ React16.createElement(
|
|
1780
1884
|
SelectInput3,
|
|
1781
1885
|
{
|
|
1782
1886
|
items: confirmationItems,
|
|
1783
1887
|
onSelect: handleConfirmationSelect,
|
|
1784
|
-
itemComponent: ({ isSelected, label }) => /* @__PURE__ */
|
|
1888
|
+
itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React16.createElement(Box15, null, /* @__PURE__ */ React16.createElement(Text15, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
|
|
1785
1889
|
}
|
|
1786
|
-
), /* @__PURE__ */
|
|
1890
|
+
), /* @__PURE__ */ React16.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text15, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Esc to go back")));
|
|
1787
1891
|
}
|
|
1788
1892
|
|
|
1789
1893
|
// src/components/SessionSelector.tsx
|
|
1790
|
-
import
|
|
1791
|
-
import { Box as
|
|
1894
|
+
import React17, { useState as useState6 } from "react";
|
|
1895
|
+
import { Box as Box16, Text as Text16, useInput as useInput6 } from "ink";
|
|
1792
1896
|
import SelectInput4 from "ink-select-input";
|
|
1793
1897
|
function SessionSelector({ sessions, currentSession, onSelect, onCancel }) {
|
|
1794
1898
|
const [step, setStep] = useState6("selection");
|
|
@@ -1826,32 +1930,32 @@ function SessionSelector({ sessions, currentSession, onSelect, onCancel }) {
|
|
|
1826
1930
|
}
|
|
1827
1931
|
};
|
|
1828
1932
|
if (step === "selection") {
|
|
1829
|
-
return /* @__PURE__ */
|
|
1933
|
+
return /* @__PURE__ */ React17.createElement(Box16, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React17.createElement(Box16, { marginBottom: 1 }, /* @__PURE__ */ React17.createElement(Text16, { bold: true }, "Select a session to resume:")), /* @__PURE__ */ React17.createElement(
|
|
1830
1934
|
SelectInput4,
|
|
1831
1935
|
{
|
|
1832
1936
|
items,
|
|
1833
1937
|
onSelect: handleSelectionSelect,
|
|
1834
|
-
itemComponent: ({ isSelected, label }) => /* @__PURE__ */
|
|
1938
|
+
itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React17.createElement(Box16, null, /* @__PURE__ */ React17.createElement(Text16, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
|
|
1835
1939
|
}
|
|
1836
|
-
), /* @__PURE__ */
|
|
1940
|
+
), /* @__PURE__ */ React17.createElement(Box16, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text16, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Esc to cancel")));
|
|
1837
1941
|
}
|
|
1838
1942
|
const confirmationItems = [
|
|
1839
1943
|
{ label: "Yes, resume this session", value: "confirm" },
|
|
1840
1944
|
{ label: "No, go back to selection", value: "cancel" }
|
|
1841
1945
|
];
|
|
1842
|
-
return /* @__PURE__ */
|
|
1946
|
+
return /* @__PURE__ */ React17.createElement(Box16, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React17.createElement(Box16, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React17.createElement(Text16, { bold: true }, 'Resume session: "', selectedSession?.name, '"'), /* @__PURE__ */ React17.createElement(Text16, { dimColor: true }, selectedSession?.messages.length, " messages | ", selectedSession?.model, " |", " ", selectedSession?.metadata?.totalTokens?.toLocaleString() ?? 0, " tokens"), hasUnsavedWork && /* @__PURE__ */ React17.createElement(Text16, { color: "yellow" }, "Warning: Your current session has unsaved messages. Use /save first if needed.")), /* @__PURE__ */ React17.createElement(
|
|
1843
1947
|
SelectInput4,
|
|
1844
1948
|
{
|
|
1845
1949
|
items: confirmationItems,
|
|
1846
1950
|
onSelect: handleConfirmationSelect,
|
|
1847
|
-
itemComponent: ({ isSelected, label }) => /* @__PURE__ */
|
|
1951
|
+
itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React17.createElement(Box16, null, /* @__PURE__ */ React17.createElement(Text16, { color: isSelected ? "cyan" : void 0 }, isSelected ? "\u276F " : " ", label))
|
|
1848
1952
|
}
|
|
1849
|
-
), /* @__PURE__ */
|
|
1953
|
+
), /* @__PURE__ */ React17.createElement(Box16, { marginTop: 1 }, /* @__PURE__ */ React17.createElement(Text16, { dimColor: true }, "Use \u2191\u2193 arrows to navigate, Enter to select, Esc to go back")));
|
|
1850
1954
|
}
|
|
1851
1955
|
|
|
1852
1956
|
// src/components/LoginFlow.tsx
|
|
1853
|
-
import
|
|
1854
|
-
import { Box as
|
|
1957
|
+
import React18, { useState as useState7, useEffect as useEffect2 } from "react";
|
|
1958
|
+
import { Box as Box17, Text as Text17 } from "ink";
|
|
1855
1959
|
import Spinner2 from "ink-spinner";
|
|
1856
1960
|
import jwt from "jsonwebtoken";
|
|
1857
1961
|
import open from "open";
|
|
@@ -2014,15 +2118,15 @@ function LoginFlow({ apiUrl = "http://localhost:3000", configStore, onSuccess, o
|
|
|
2014
2118
|
}
|
|
2015
2119
|
}, [deviceFlow, status]);
|
|
2016
2120
|
if (status === "initiating") {
|
|
2017
|
-
return /* @__PURE__ */
|
|
2121
|
+
return /* @__PURE__ */ React18.createElement(Box17, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React18.createElement(Box17, null, /* @__PURE__ */ React18.createElement(Text17, { color: "cyan" }, /* @__PURE__ */ React18.createElement(Spinner2, { type: "dots" }), " Initiating device authorization...")));
|
|
2018
2122
|
}
|
|
2019
2123
|
if (status === "error") {
|
|
2020
|
-
return /* @__PURE__ */
|
|
2124
|
+
return /* @__PURE__ */ React18.createElement(Box17, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React18.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text17, { color: "red", bold: true }, "\u2716 Authentication Failed")), /* @__PURE__ */ React18.createElement(Box17, null, /* @__PURE__ */ React18.createElement(Text17, { color: "red" }, error)));
|
|
2021
2125
|
}
|
|
2022
2126
|
if (status === "success") {
|
|
2023
|
-
return /* @__PURE__ */
|
|
2127
|
+
return /* @__PURE__ */ React18.createElement(Box17, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React18.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text17, { color: "green", bold: true }, "\u2714 Successfully authenticated!")), /* @__PURE__ */ React18.createElement(Box17, null, /* @__PURE__ */ React18.createElement(Text17, { dimColor: true }, "You can now use B4M CLI with your account.")));
|
|
2024
2128
|
}
|
|
2025
|
-
return /* @__PURE__ */
|
|
2129
|
+
return /* @__PURE__ */ React18.createElement(Box17, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan" }, /* @__PURE__ */ React18.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text17, { color: "cyan", bold: true }, "\u{1F510} Device Authorization")), /* @__PURE__ */ React18.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text17, null, "Opening browser automatically... If it doesn't open, please visit:")), /* @__PURE__ */ React18.createElement(Box17, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React18.createElement(Text17, { color: "blue", bold: true }, deviceFlow?.verification_uri)), /* @__PURE__ */ React18.createElement(Box17, { marginBottom: 1 }, /* @__PURE__ */ React18.createElement(Text17, null, "And enter this code when prompted:")), /* @__PURE__ */ React18.createElement(Box17, { marginBottom: 1, paddingLeft: 2 }, /* @__PURE__ */ React18.createElement(Text17, { color: "yellow", bold: true }, deviceFlow?.user_code)), /* @__PURE__ */ React18.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text17, { color: "cyan" }, /* @__PURE__ */ React18.createElement(Spinner2, { type: "dots" }), " ", statusMessage)), /* @__PURE__ */ React18.createElement(Box17, { marginTop: 1 }, /* @__PURE__ */ React18.createElement(Text17, { dimColor: true }, "Expires in ", deviceFlow ? Math.floor(deviceFlow.expires_in / 60) : 0, " minutes")));
|
|
2026
2130
|
}
|
|
2027
2131
|
|
|
2028
2132
|
// src/storage/SessionStore.ts
|
|
@@ -11313,7 +11417,7 @@ import { isAxiosError as isAxiosError2 } from "axios";
|
|
|
11313
11417
|
// package.json
|
|
11314
11418
|
var package_default = {
|
|
11315
11419
|
name: "@bike4mind/cli",
|
|
11316
|
-
version: "0.2.14-feat-cli-
|
|
11420
|
+
version: "0.2.14-feat-cli-markdown-rendering.17480+ababeaf00",
|
|
11317
11421
|
type: "module",
|
|
11318
11422
|
description: "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
11319
11423
|
license: "UNLICENSED",
|
|
@@ -11377,6 +11481,7 @@ var package_default = {
|
|
|
11377
11481
|
bcryptjs: "^2.4.3",
|
|
11378
11482
|
"better-sqlite3": "^12.5.0",
|
|
11379
11483
|
cheerio: "1.0.0-rc.12",
|
|
11484
|
+
"cli-highlight": "^2.1.11",
|
|
11380
11485
|
"csv-parse": "^5.5.6",
|
|
11381
11486
|
dayjs: "^1.11.13",
|
|
11382
11487
|
diff: "^8.0.2",
|
|
@@ -11419,10 +11524,10 @@ var package_default = {
|
|
|
11419
11524
|
},
|
|
11420
11525
|
devDependencies: {
|
|
11421
11526
|
"@bike4mind/agents": "0.1.0",
|
|
11422
|
-
"@bike4mind/common": "2.42.1-feat-cli-
|
|
11423
|
-
"@bike4mind/mcp": "1.21.3-feat-cli-
|
|
11424
|
-
"@bike4mind/services": "2.37.1-feat-cli-
|
|
11425
|
-
"@bike4mind/utils": "2.1.8-feat-cli-
|
|
11527
|
+
"@bike4mind/common": "2.42.1-feat-cli-markdown-rendering.17480+ababeaf00",
|
|
11528
|
+
"@bike4mind/mcp": "1.21.3-feat-cli-markdown-rendering.17480+ababeaf00",
|
|
11529
|
+
"@bike4mind/services": "2.37.1-feat-cli-markdown-rendering.17480+ababeaf00",
|
|
11530
|
+
"@bike4mind/utils": "2.1.8-feat-cli-markdown-rendering.17480+ababeaf00",
|
|
11426
11531
|
"@types/better-sqlite3": "^7.6.13",
|
|
11427
11532
|
"@types/diff": "^5.0.9",
|
|
11428
11533
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -11436,7 +11541,7 @@ var package_default = {
|
|
|
11436
11541
|
typescript: "^5.9.3",
|
|
11437
11542
|
vitest: "^3.2.4"
|
|
11438
11543
|
},
|
|
11439
|
-
gitHead: "
|
|
11544
|
+
gitHead: "ababeaf00e313fae7df77380b8f624d257030834"
|
|
11440
11545
|
};
|
|
11441
11546
|
|
|
11442
11547
|
// src/config/constants.ts
|
|
@@ -13388,12 +13493,12 @@ No usage data available for the last ${USAGE_DAYS} days.`);
|
|
|
13388
13493
|
}
|
|
13389
13494
|
};
|
|
13390
13495
|
if (initError) {
|
|
13391
|
-
return /* @__PURE__ */
|
|
13496
|
+
return /* @__PURE__ */ React19.createElement(Box18, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React19.createElement(Text18, { color: "red", bold: true }, "\u274C Initialization Error"), /* @__PURE__ */ React19.createElement(Text18, null, initError), /* @__PURE__ */ React19.createElement(Text18, { dimColor: true }, "\n", "Tip: Run /config to set up your API keys"));
|
|
13392
13497
|
}
|
|
13393
13498
|
if (state.trustLocationSelector) {
|
|
13394
13499
|
const projectDir = state.configStore.getProjectConfigDir();
|
|
13395
13500
|
const inProject = projectDir !== null;
|
|
13396
|
-
return /* @__PURE__ */
|
|
13501
|
+
return /* @__PURE__ */ React19.createElement(
|
|
13397
13502
|
TrustLocationSelector,
|
|
13398
13503
|
{
|
|
13399
13504
|
inProject,
|
|
@@ -13411,7 +13516,7 @@ No usage data available for the last ${USAGE_DAYS} days.`);
|
|
|
13411
13516
|
);
|
|
13412
13517
|
}
|
|
13413
13518
|
if (state.rewindSelector && state.session) {
|
|
13414
|
-
return /* @__PURE__ */
|
|
13519
|
+
return /* @__PURE__ */ React19.createElement(
|
|
13415
13520
|
RewindSelector,
|
|
13416
13521
|
{
|
|
13417
13522
|
messages: state.session.messages,
|
|
@@ -13429,7 +13534,7 @@ No usage data available for the last ${USAGE_DAYS} days.`);
|
|
|
13429
13534
|
);
|
|
13430
13535
|
}
|
|
13431
13536
|
if (state.sessionSelector) {
|
|
13432
|
-
return /* @__PURE__ */
|
|
13537
|
+
return /* @__PURE__ */ React19.createElement(
|
|
13433
13538
|
SessionSelector,
|
|
13434
13539
|
{
|
|
13435
13540
|
sessions: state.sessionSelector.sessions,
|
|
@@ -13449,7 +13554,7 @@ No usage data available for the last ${USAGE_DAYS} days.`);
|
|
|
13449
13554
|
}
|
|
13450
13555
|
if (state.showLoginFlow) {
|
|
13451
13556
|
const loginApiUrl = getApiUrl(state.config?.apiConfig);
|
|
13452
|
-
return /* @__PURE__ */
|
|
13557
|
+
return /* @__PURE__ */ React19.createElement(
|
|
13453
13558
|
LoginFlow,
|
|
13454
13559
|
{
|
|
13455
13560
|
apiUrl: loginApiUrl,
|
|
@@ -13472,10 +13577,10 @@ No usage data available for the last ${USAGE_DAYS} days.`);
|
|
|
13472
13577
|
);
|
|
13473
13578
|
}
|
|
13474
13579
|
if (!isInitialized) {
|
|
13475
|
-
return /* @__PURE__ */
|
|
13580
|
+
return /* @__PURE__ */ React19.createElement(Box18, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React19.createElement(Text18, null, "\u{1F680} Initializing..."));
|
|
13476
13581
|
}
|
|
13477
13582
|
const allCommands = mergeCommands(state.customCommandStore.getAllCommands());
|
|
13478
|
-
return /* @__PURE__ */
|
|
13583
|
+
return /* @__PURE__ */ React19.createElement(
|
|
13479
13584
|
App,
|
|
13480
13585
|
{
|
|
13481
13586
|
onMessage: handleMessage,
|
|
@@ -13517,6 +13622,6 @@ var isDevMode = import.meta.url.includes("/src/") || process.env.NODE_ENV === "d
|
|
|
13517
13622
|
if (isDevMode) {
|
|
13518
13623
|
logger.debug("\u{1F527} Running in development mode (using TypeScript source)\n");
|
|
13519
13624
|
}
|
|
13520
|
-
render(/* @__PURE__ */
|
|
13625
|
+
render(/* @__PURE__ */ React19.createElement(CliApp, null), {
|
|
13521
13626
|
exitOnCtrlC: false
|
|
13522
13627
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bike4mind/cli",
|
|
3
|
-
"version": "0.2.14-feat-cli-
|
|
3
|
+
"version": "0.2.14-feat-cli-markdown-rendering.17480+ababeaf00",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Interactive CLI tool for Bike4Mind with ReAct agents",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
"bcryptjs": "^2.4.3",
|
|
65
65
|
"better-sqlite3": "^12.5.0",
|
|
66
66
|
"cheerio": "1.0.0-rc.12",
|
|
67
|
+
"cli-highlight": "^2.1.11",
|
|
67
68
|
"csv-parse": "^5.5.6",
|
|
68
69
|
"dayjs": "^1.11.13",
|
|
69
70
|
"diff": "^8.0.2",
|
|
@@ -106,10 +107,10 @@
|
|
|
106
107
|
},
|
|
107
108
|
"devDependencies": {
|
|
108
109
|
"@bike4mind/agents": "0.1.0",
|
|
109
|
-
"@bike4mind/common": "2.42.1-feat-cli-
|
|
110
|
-
"@bike4mind/mcp": "1.21.3-feat-cli-
|
|
111
|
-
"@bike4mind/services": "2.37.1-feat-cli-
|
|
112
|
-
"@bike4mind/utils": "2.1.8-feat-cli-
|
|
110
|
+
"@bike4mind/common": "2.42.1-feat-cli-markdown-rendering.17480+ababeaf00",
|
|
111
|
+
"@bike4mind/mcp": "1.21.3-feat-cli-markdown-rendering.17480+ababeaf00",
|
|
112
|
+
"@bike4mind/services": "2.37.1-feat-cli-markdown-rendering.17480+ababeaf00",
|
|
113
|
+
"@bike4mind/utils": "2.1.8-feat-cli-markdown-rendering.17480+ababeaf00",
|
|
113
114
|
"@types/better-sqlite3": "^7.6.13",
|
|
114
115
|
"@types/diff": "^5.0.9",
|
|
115
116
|
"@types/jsonwebtoken": "^9.0.4",
|
|
@@ -123,5 +124,5 @@
|
|
|
123
124
|
"typescript": "^5.9.3",
|
|
124
125
|
"vitest": "^3.2.4"
|
|
125
126
|
},
|
|
126
|
-
"gitHead": "
|
|
127
|
+
"gitHead": "ababeaf00e313fae7df77380b8f624d257030834"
|
|
127
128
|
}
|