@poncho-ai/cli 0.6.0 → 0.6.2
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/.turbo/turbo-build.log +7 -7
- package/dist/chunk-2TLKQG7R.js +5360 -0
- package/dist/chunk-3FY4LP2E.js +4981 -0
- package/dist/chunk-3WQANPEG.js +5086 -0
- package/dist/chunk-44DXWF6D.js +5450 -0
- package/dist/chunk-62G3MI43.js +5316 -0
- package/dist/chunk-6J2JICGH.js +5135 -0
- package/dist/chunk-6KLC6MWK.js +5357 -0
- package/dist/chunk-6LG2DUWF.js +5181 -0
- package/dist/chunk-ASAXSYEZ.js +5179 -0
- package/dist/chunk-B5B5LAR2.js +5181 -0
- package/dist/chunk-C7T4EJNQ.js +4934 -0
- package/dist/chunk-EPG7ZYDE.js +5452 -0
- package/dist/chunk-FMRRGTJX.js +5041 -0
- package/dist/chunk-HHMFEU26.js +5451 -0
- package/dist/chunk-JRJY6LUC.js +5178 -0
- package/dist/chunk-O7SJY7YQ.js +5177 -0
- package/dist/chunk-PYP4SKOI.js +5125 -0
- package/dist/chunk-VECWMU7E.js +5276 -0
- package/dist/chunk-XEBDWQI6.js +5178 -0
- package/dist/chunk-YW2D7Z22.js +5360 -0
- package/dist/chunk-YZXMEO2T.js +5177 -0
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +18 -2
- package/dist/index.js +11 -1
- package/dist/run-interactive-ink-6EJ6Z5HE.js +494 -0
- package/dist/run-interactive-ink-72BHZB7Q.js +494 -0
- package/dist/run-interactive-ink-BNRIM52Y.js +494 -0
- package/dist/run-interactive-ink-BZNBOELJ.js +494 -0
- package/dist/run-interactive-ink-GODBXZF3.js +494 -0
- package/dist/run-interactive-ink-J4AISGNQ.js +494 -0
- package/dist/run-interactive-ink-K75SE2J2.js +494 -0
- package/dist/run-interactive-ink-M2XKKPIJ.js +494 -0
- package/dist/run-interactive-ink-MITWAF7L.js +494 -0
- package/dist/run-interactive-ink-NR5BRFUF.js +494 -0
- package/dist/run-interactive-ink-OGNG6UYE.js +494 -0
- package/dist/run-interactive-ink-P3VNJEXK.js +494 -0
- package/dist/run-interactive-ink-PHLW5YWV.js +494 -0
- package/dist/run-interactive-ink-PVU3XABN.js +494 -0
- package/dist/run-interactive-ink-SLSK7BY5.js +494 -0
- package/dist/run-interactive-ink-TRPYQYHG.js +494 -0
- package/dist/run-interactive-ink-U2RPRBIR.js +494 -0
- package/dist/run-interactive-ink-U2WTGZJ3.js +494 -0
- package/dist/run-interactive-ink-UHBFYNNB.js +494 -0
- package/dist/run-interactive-ink-XQDUN6OS.js +494 -0
- package/dist/run-interactive-ink-XUHSJCGH.js +494 -0
- package/package.json +1 -1
- package/src/index.ts +322 -27
- package/src/web-ui.ts +350 -33
- package/test/cli.test.ts +232 -1
package/src/web-ui.ts
CHANGED
|
@@ -839,6 +839,7 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
839
839
|
.assistant-content td {
|
|
840
840
|
padding: 10px 12px;
|
|
841
841
|
border-bottom: 1px solid rgba(255,255,255,0.06);
|
|
842
|
+
width: 100%;
|
|
842
843
|
min-width: 100px;
|
|
843
844
|
}
|
|
844
845
|
.assistant-content tr:last-child td {
|
|
@@ -1024,6 +1025,23 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1024
1025
|
color: #ededed;
|
|
1025
1026
|
opacity: 0.5;
|
|
1026
1027
|
}
|
|
1028
|
+
.thinking-status {
|
|
1029
|
+
display: inline-flex;
|
|
1030
|
+
align-items: center;
|
|
1031
|
+
gap: 8px;
|
|
1032
|
+
margin-top: 2px;
|
|
1033
|
+
color: #8a8a8a;
|
|
1034
|
+
font-size: 14px;
|
|
1035
|
+
line-height: 1.65;
|
|
1036
|
+
font-weight: 400;
|
|
1037
|
+
}
|
|
1038
|
+
.thinking-status-label {
|
|
1039
|
+
color: #8a8a8a;
|
|
1040
|
+
font-size: 14px;
|
|
1041
|
+
line-height: 1.65;
|
|
1042
|
+
font-weight: 400;
|
|
1043
|
+
white-space: nowrap;
|
|
1044
|
+
}
|
|
1027
1045
|
|
|
1028
1046
|
/* Composer */
|
|
1029
1047
|
.composer {
|
|
@@ -1220,6 +1238,7 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1220
1238
|
activeConversationId: null,
|
|
1221
1239
|
activeMessages: [],
|
|
1222
1240
|
isStreaming: false,
|
|
1241
|
+
isMessagesPinnedToBottom: true,
|
|
1223
1242
|
confirmDeleteId: null,
|
|
1224
1243
|
approvalRequestsInFlight: {}
|
|
1225
1244
|
};
|
|
@@ -1590,8 +1609,21 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1590
1609
|
}
|
|
1591
1610
|
};
|
|
1592
1611
|
|
|
1593
|
-
const
|
|
1594
|
-
|
|
1612
|
+
const isNearBottom = (element, threshold = 64) => {
|
|
1613
|
+
if (!element) return true;
|
|
1614
|
+
return (
|
|
1615
|
+
element.scrollHeight - element.clientHeight - element.scrollTop <= threshold
|
|
1616
|
+
);
|
|
1617
|
+
};
|
|
1618
|
+
|
|
1619
|
+
const renderMessages = (messages, isStreaming = false, options = {}) => {
|
|
1620
|
+
const previousScrollTop = elements.messages.scrollTop;
|
|
1621
|
+
const shouldStickToBottom =
|
|
1622
|
+
options.forceScrollBottom === true || state.isMessagesPinnedToBottom;
|
|
1623
|
+
|
|
1624
|
+
const createThinkingIndicator = (label) => {
|
|
1625
|
+
const status = document.createElement("div");
|
|
1626
|
+
status.className = "thinking-status";
|
|
1595
1627
|
const spinner = document.createElement("span");
|
|
1596
1628
|
spinner.className = "thinking-indicator";
|
|
1597
1629
|
const starFrames = ["✶", "✸", "✹", "✺", "✹", "✷"];
|
|
@@ -1601,12 +1633,20 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1601
1633
|
frame = (frame + 1) % starFrames.length;
|
|
1602
1634
|
spinner.textContent = starFrames[frame];
|
|
1603
1635
|
}, 70);
|
|
1604
|
-
|
|
1636
|
+
status.appendChild(spinner);
|
|
1637
|
+
if (label) {
|
|
1638
|
+
const text = document.createElement("span");
|
|
1639
|
+
text.className = "thinking-status-label";
|
|
1640
|
+
text.textContent = label;
|
|
1641
|
+
status.appendChild(text);
|
|
1642
|
+
}
|
|
1643
|
+
return status;
|
|
1605
1644
|
};
|
|
1606
1645
|
|
|
1607
1646
|
elements.messages.innerHTML = "";
|
|
1608
1647
|
if (!messages || !messages.length) {
|
|
1609
1648
|
elements.messages.innerHTML = '<div class="empty-state"><div class="assistant-avatar">' + agentInitial + '</div><div>How can I help you today?</div></div>';
|
|
1649
|
+
elements.messages.scrollTop = 0;
|
|
1610
1650
|
return;
|
|
1611
1651
|
}
|
|
1612
1652
|
const col = document.createElement("div");
|
|
@@ -1638,7 +1678,7 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1638
1678
|
errorEl.innerHTML = "<strong>Error</strong><br>" + escapeHtml(m._error);
|
|
1639
1679
|
content.appendChild(errorEl);
|
|
1640
1680
|
} else if (shouldRenderEmptyStreamingIndicator) {
|
|
1641
|
-
content.appendChild(createThinkingIndicator());
|
|
1681
|
+
content.appendChild(createThinkingIndicator(getThinkingStatusLabel(m)));
|
|
1642
1682
|
} else {
|
|
1643
1683
|
// Check for sections in _sections (streaming) or metadata.sections (stored)
|
|
1644
1684
|
const sections = m._sections || (m.metadata && m.metadata.sections);
|
|
@@ -1712,7 +1752,7 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1712
1752
|
(!m._currentText || m._currentText.length === 0)
|
|
1713
1753
|
) {
|
|
1714
1754
|
const waitIndicator = document.createElement("div");
|
|
1715
|
-
waitIndicator.appendChild(createThinkingIndicator());
|
|
1755
|
+
waitIndicator.appendChild(createThinkingIndicator(getThinkingStatusLabel(m)));
|
|
1716
1756
|
content.appendChild(waitIndicator);
|
|
1717
1757
|
}
|
|
1718
1758
|
}
|
|
@@ -1724,7 +1764,14 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1724
1764
|
col.appendChild(row);
|
|
1725
1765
|
});
|
|
1726
1766
|
elements.messages.appendChild(col);
|
|
1727
|
-
|
|
1767
|
+
if (shouldStickToBottom) {
|
|
1768
|
+
elements.messages.scrollTop = elements.messages.scrollHeight;
|
|
1769
|
+
state.isMessagesPinnedToBottom = true;
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
if (options.preserveScroll !== false) {
|
|
1773
|
+
elements.messages.scrollTop = previousScrollTop;
|
|
1774
|
+
}
|
|
1728
1775
|
};
|
|
1729
1776
|
|
|
1730
1777
|
const loadConversations = async () => {
|
|
@@ -1740,13 +1787,20 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1740
1787
|
payload.conversation.messages || [],
|
|
1741
1788
|
payload.conversation.pendingApprovals || payload.pendingApprovals || [],
|
|
1742
1789
|
);
|
|
1743
|
-
renderMessages(state.activeMessages);
|
|
1790
|
+
renderMessages(state.activeMessages, false, { forceScrollBottom: true });
|
|
1744
1791
|
elements.prompt.focus();
|
|
1745
1792
|
};
|
|
1746
1793
|
|
|
1747
1794
|
const streamConversationEvents = (conversationId) => {
|
|
1748
1795
|
return new Promise((resolve) => {
|
|
1749
1796
|
const localMessages = state.activeMessages || [];
|
|
1797
|
+
const renderIfActiveConversation = (streaming) => {
|
|
1798
|
+
if (state.activeConversationId !== conversationId) {
|
|
1799
|
+
return;
|
|
1800
|
+
}
|
|
1801
|
+
state.activeMessages = localMessages;
|
|
1802
|
+
renderMessages(localMessages, streaming);
|
|
1803
|
+
};
|
|
1750
1804
|
let assistantMessage = localMessages[localMessages.length - 1];
|
|
1751
1805
|
if (!assistantMessage || assistantMessage.role !== "assistant") {
|
|
1752
1806
|
assistantMessage = {
|
|
@@ -1764,6 +1818,7 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1764
1818
|
if (!assistantMessage._sections) assistantMessage._sections = [];
|
|
1765
1819
|
if (!assistantMessage._currentText) assistantMessage._currentText = "";
|
|
1766
1820
|
if (!assistantMessage._currentTools) assistantMessage._currentTools = [];
|
|
1821
|
+
if (!assistantMessage._activeActivities) assistantMessage._activeActivities = [];
|
|
1767
1822
|
if (!assistantMessage._pendingApprovals) assistantMessage._pendingApprovals = [];
|
|
1768
1823
|
if (!assistantMessage.metadata) assistantMessage.metadata = {};
|
|
1769
1824
|
if (!assistantMessage.metadata.toolActivity) assistantMessage.metadata.toolActivity = [];
|
|
@@ -1800,10 +1855,14 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1800
1855
|
}
|
|
1801
1856
|
assistantMessage.content += chunk;
|
|
1802
1857
|
assistantMessage._currentText += chunk;
|
|
1803
|
-
|
|
1858
|
+
renderIfActiveConversation(true);
|
|
1804
1859
|
}
|
|
1805
1860
|
if (eventName === "tool:started") {
|
|
1806
1861
|
const toolName = payload.tool || "tool";
|
|
1862
|
+
const startedActivity = addActiveActivityFromToolStart(
|
|
1863
|
+
assistantMessage,
|
|
1864
|
+
payload,
|
|
1865
|
+
);
|
|
1807
1866
|
if (assistantMessage._currentText.length > 0) {
|
|
1808
1867
|
assistantMessage._sections.push({
|
|
1809
1868
|
type: "text",
|
|
@@ -1811,33 +1870,67 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1811
1870
|
});
|
|
1812
1871
|
assistantMessage._currentText = "";
|
|
1813
1872
|
}
|
|
1814
|
-
const
|
|
1873
|
+
const detail =
|
|
1874
|
+
startedActivity && typeof startedActivity.detail === "string"
|
|
1875
|
+
? startedActivity.detail.trim()
|
|
1876
|
+
: "";
|
|
1877
|
+
const toolText =
|
|
1878
|
+
"- start \\x60" +
|
|
1879
|
+
toolName +
|
|
1880
|
+
"\\x60" +
|
|
1881
|
+
(detail ? " (" + detail + ")" : "");
|
|
1815
1882
|
assistantMessage._currentTools.push(toolText);
|
|
1816
1883
|
assistantMessage.metadata.toolActivity.push(toolText);
|
|
1817
|
-
|
|
1884
|
+
renderIfActiveConversation(true);
|
|
1818
1885
|
}
|
|
1819
1886
|
if (eventName === "tool:completed") {
|
|
1820
1887
|
const toolName = payload.tool || "tool";
|
|
1888
|
+
const activeActivity = removeActiveActivityForTool(
|
|
1889
|
+
assistantMessage,
|
|
1890
|
+
toolName,
|
|
1891
|
+
);
|
|
1821
1892
|
const duration =
|
|
1822
1893
|
typeof payload.duration === "number" ? payload.duration : null;
|
|
1894
|
+
const detail =
|
|
1895
|
+
activeActivity && typeof activeActivity.detail === "string"
|
|
1896
|
+
? activeActivity.detail.trim()
|
|
1897
|
+
: "";
|
|
1898
|
+
const meta = [];
|
|
1899
|
+
if (duration !== null) meta.push(duration + "ms");
|
|
1900
|
+
if (detail) meta.push(detail);
|
|
1823
1901
|
const toolText =
|
|
1824
1902
|
"- done \\x60" +
|
|
1825
1903
|
toolName +
|
|
1826
1904
|
"\\x60" +
|
|
1827
|
-
(
|
|
1905
|
+
(meta.length > 0 ? " (" + meta.join(", ") + ")" : "");
|
|
1828
1906
|
assistantMessage._currentTools.push(toolText);
|
|
1829
1907
|
assistantMessage.metadata.toolActivity.push(toolText);
|
|
1830
|
-
|
|
1908
|
+
renderIfActiveConversation(true);
|
|
1831
1909
|
}
|
|
1832
1910
|
if (eventName === "tool:error") {
|
|
1833
1911
|
const toolName = payload.tool || "tool";
|
|
1912
|
+
const activeActivity = removeActiveActivityForTool(
|
|
1913
|
+
assistantMessage,
|
|
1914
|
+
toolName,
|
|
1915
|
+
);
|
|
1834
1916
|
const errorMsg = payload.error || "unknown error";
|
|
1835
|
-
const
|
|
1917
|
+
const detail =
|
|
1918
|
+
activeActivity && typeof activeActivity.detail === "string"
|
|
1919
|
+
? activeActivity.detail.trim()
|
|
1920
|
+
: "";
|
|
1921
|
+
const toolText =
|
|
1922
|
+
"- error \\x60" +
|
|
1923
|
+
toolName +
|
|
1924
|
+
"\\x60" +
|
|
1925
|
+
(detail ? " (" + detail + ")" : "") +
|
|
1926
|
+
": " +
|
|
1927
|
+
errorMsg;
|
|
1836
1928
|
assistantMessage._currentTools.push(toolText);
|
|
1837
1929
|
assistantMessage.metadata.toolActivity.push(toolText);
|
|
1838
|
-
|
|
1930
|
+
renderIfActiveConversation(true);
|
|
1839
1931
|
}
|
|
1840
1932
|
if (eventName === "run:completed") {
|
|
1933
|
+
assistantMessage._activeActivities = [];
|
|
1841
1934
|
if (
|
|
1842
1935
|
!assistantMessage.content ||
|
|
1843
1936
|
assistantMessage.content.length === 0
|
|
@@ -1860,14 +1953,15 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1860
1953
|
});
|
|
1861
1954
|
assistantMessage._currentText = "";
|
|
1862
1955
|
}
|
|
1863
|
-
|
|
1956
|
+
renderIfActiveConversation(false);
|
|
1864
1957
|
}
|
|
1865
1958
|
if (eventName === "run:error") {
|
|
1959
|
+
assistantMessage._activeActivities = [];
|
|
1866
1960
|
const errMsg =
|
|
1867
1961
|
payload.error?.message || "Something went wrong";
|
|
1868
1962
|
assistantMessage.content = "";
|
|
1869
1963
|
assistantMessage._error = errMsg;
|
|
1870
|
-
|
|
1964
|
+
renderIfActiveConversation(false);
|
|
1871
1965
|
}
|
|
1872
1966
|
} catch (error) {
|
|
1873
1967
|
console.error("SSE reconnect event error:", eventName, error);
|
|
@@ -1876,7 +1970,9 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1876
1970
|
}
|
|
1877
1971
|
};
|
|
1878
1972
|
processChunks().finally(() => {
|
|
1879
|
-
state.
|
|
1973
|
+
if (state.activeConversationId === conversationId) {
|
|
1974
|
+
state.activeMessages = localMessages;
|
|
1975
|
+
}
|
|
1880
1976
|
resolve(undefined);
|
|
1881
1977
|
});
|
|
1882
1978
|
}).catch(() => {
|
|
@@ -1951,6 +2047,159 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1951
2047
|
assistantMessage.metadata.toolActivity.push(line);
|
|
1952
2048
|
};
|
|
1953
2049
|
|
|
2050
|
+
const ensureActiveActivities = (assistantMessage) => {
|
|
2051
|
+
if (!Array.isArray(assistantMessage._activeActivities)) {
|
|
2052
|
+
assistantMessage._activeActivities = [];
|
|
2053
|
+
}
|
|
2054
|
+
return assistantMessage._activeActivities;
|
|
2055
|
+
};
|
|
2056
|
+
|
|
2057
|
+
const getStringInputField = (input, key) => {
|
|
2058
|
+
if (!input || typeof input !== "object") {
|
|
2059
|
+
return "";
|
|
2060
|
+
}
|
|
2061
|
+
const value = input[key];
|
|
2062
|
+
return typeof value === "string" ? value.trim() : "";
|
|
2063
|
+
};
|
|
2064
|
+
|
|
2065
|
+
const describeToolStart = (payload) => {
|
|
2066
|
+
const toolName = payload && typeof payload.tool === "string" ? payload.tool : "tool";
|
|
2067
|
+
const input = payload && payload.input && typeof payload.input === "object" ? payload.input : {};
|
|
2068
|
+
|
|
2069
|
+
if (toolName === "activate_skill") {
|
|
2070
|
+
const skillName = getStringInputField(input, "name") || "skill";
|
|
2071
|
+
return {
|
|
2072
|
+
kind: "skill",
|
|
2073
|
+
tool: toolName,
|
|
2074
|
+
label: "Activating " + skillName + " skill",
|
|
2075
|
+
detail: "skill: " + skillName,
|
|
2076
|
+
};
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
if (toolName === "run_skill_script") {
|
|
2080
|
+
const scriptPath = getStringInputField(input, "script");
|
|
2081
|
+
const skillName = getStringInputField(input, "skill");
|
|
2082
|
+
if (scriptPath && skillName) {
|
|
2083
|
+
return {
|
|
2084
|
+
kind: "tool",
|
|
2085
|
+
tool: toolName,
|
|
2086
|
+
label: "Running script " + scriptPath + " in " + skillName + " skill",
|
|
2087
|
+
detail: "script: " + scriptPath + ", skill: " + skillName,
|
|
2088
|
+
};
|
|
2089
|
+
}
|
|
2090
|
+
if (scriptPath) {
|
|
2091
|
+
return {
|
|
2092
|
+
kind: "tool",
|
|
2093
|
+
tool: toolName,
|
|
2094
|
+
label: "Running script " + scriptPath,
|
|
2095
|
+
detail: "script: " + scriptPath,
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
if (toolName === "read_skill_resource") {
|
|
2101
|
+
const resourcePath = getStringInputField(input, "path");
|
|
2102
|
+
const skillName = getStringInputField(input, "skill");
|
|
2103
|
+
if (resourcePath && skillName) {
|
|
2104
|
+
return {
|
|
2105
|
+
kind: "tool",
|
|
2106
|
+
tool: toolName,
|
|
2107
|
+
label: "Reading " + resourcePath + " from " + skillName + " skill",
|
|
2108
|
+
detail: "path: " + resourcePath + ", skill: " + skillName,
|
|
2109
|
+
};
|
|
2110
|
+
}
|
|
2111
|
+
if (resourcePath) {
|
|
2112
|
+
return {
|
|
2113
|
+
kind: "tool",
|
|
2114
|
+
tool: toolName,
|
|
2115
|
+
label: "Reading " + resourcePath,
|
|
2116
|
+
detail: "path: " + resourcePath,
|
|
2117
|
+
};
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
if (toolName === "read_file") {
|
|
2122
|
+
const path = getStringInputField(input, "path");
|
|
2123
|
+
if (path) {
|
|
2124
|
+
return {
|
|
2125
|
+
kind: "tool",
|
|
2126
|
+
tool: toolName,
|
|
2127
|
+
label: "Reading " + path,
|
|
2128
|
+
detail: "path: " + path,
|
|
2129
|
+
};
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
return {
|
|
2134
|
+
kind: "tool",
|
|
2135
|
+
tool: toolName,
|
|
2136
|
+
label: "Running " + toolName + " tool",
|
|
2137
|
+
detail: "",
|
|
2138
|
+
};
|
|
2139
|
+
};
|
|
2140
|
+
|
|
2141
|
+
const addActiveActivityFromToolStart = (assistantMessage, payload) => {
|
|
2142
|
+
const activities = ensureActiveActivities(assistantMessage);
|
|
2143
|
+
const activity = describeToolStart(payload);
|
|
2144
|
+
activities.push(activity);
|
|
2145
|
+
return activity;
|
|
2146
|
+
};
|
|
2147
|
+
|
|
2148
|
+
const removeActiveActivityForTool = (assistantMessage, toolName) => {
|
|
2149
|
+
if (!toolName || !Array.isArray(assistantMessage._activeActivities)) {
|
|
2150
|
+
return null;
|
|
2151
|
+
}
|
|
2152
|
+
const activities = assistantMessage._activeActivities;
|
|
2153
|
+
const idx = activities.findIndex((item) => item && item.tool === toolName);
|
|
2154
|
+
if (idx >= 0) {
|
|
2155
|
+
return activities.splice(idx, 1)[0] || null;
|
|
2156
|
+
}
|
|
2157
|
+
return null;
|
|
2158
|
+
};
|
|
2159
|
+
|
|
2160
|
+
const getThinkingStatusLabel = (assistantMessage) => {
|
|
2161
|
+
const activities = Array.isArray(assistantMessage?._activeActivities)
|
|
2162
|
+
? assistantMessage._activeActivities
|
|
2163
|
+
: [];
|
|
2164
|
+
const labels = [];
|
|
2165
|
+
activities.forEach((item) => {
|
|
2166
|
+
if (!item || typeof item.label !== "string") {
|
|
2167
|
+
return;
|
|
2168
|
+
}
|
|
2169
|
+
const label = item.label.trim();
|
|
2170
|
+
if (!label || labels.includes(label)) {
|
|
2171
|
+
return;
|
|
2172
|
+
}
|
|
2173
|
+
labels.push(label);
|
|
2174
|
+
});
|
|
2175
|
+
if (labels.length === 1) {
|
|
2176
|
+
return labels[0];
|
|
2177
|
+
}
|
|
2178
|
+
if (labels.length === 2) {
|
|
2179
|
+
return labels[0] + ", " + labels[1];
|
|
2180
|
+
}
|
|
2181
|
+
if (labels.length > 2) {
|
|
2182
|
+
return labels[0] + ", " + labels[1] + " +" + (labels.length - 2) + " more";
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
if (Array.isArray(assistantMessage?._currentTools)) {
|
|
2186
|
+
const tick = String.fromCharCode(96);
|
|
2187
|
+
const startPrefix = "- start " + tick;
|
|
2188
|
+
for (let idx = assistantMessage._currentTools.length - 1; idx >= 0; idx -= 1) {
|
|
2189
|
+
const item = String(assistantMessage._currentTools[idx] || "");
|
|
2190
|
+
if (item.startsWith(startPrefix)) {
|
|
2191
|
+
const rest = item.slice(startPrefix.length);
|
|
2192
|
+
const endIdx = rest.indexOf(tick);
|
|
2193
|
+
const toolName = (endIdx >= 0 ? rest.slice(0, endIdx) : rest).trim();
|
|
2194
|
+
if (toolName) {
|
|
2195
|
+
return "Running " + toolName + " tool";
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
return "Thinking...";
|
|
2201
|
+
};
|
|
2202
|
+
|
|
1954
2203
|
const autoResizePrompt = () => {
|
|
1955
2204
|
const el = elements.prompt;
|
|
1956
2205
|
el.style.height = "auto";
|
|
@@ -1972,18 +2221,27 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
1972
2221
|
_sections: [], // Array of {type: 'text'|'tools', content: string|array}
|
|
1973
2222
|
_currentText: "",
|
|
1974
2223
|
_currentTools: [],
|
|
2224
|
+
_activeActivities: [],
|
|
1975
2225
|
_pendingApprovals: [],
|
|
1976
2226
|
metadata: { toolActivity: [] }
|
|
1977
2227
|
};
|
|
1978
2228
|
localMessages.push(assistantMessage);
|
|
1979
2229
|
state.activeMessages = localMessages;
|
|
1980
|
-
renderMessages(localMessages, true);
|
|
2230
|
+
renderMessages(localMessages, true, { forceScrollBottom: true });
|
|
1981
2231
|
setStreaming(true);
|
|
1982
2232
|
let conversationId = state.activeConversationId;
|
|
1983
2233
|
try {
|
|
1984
2234
|
if (!conversationId) {
|
|
1985
2235
|
conversationId = await createConversation(messageText, { loadConversation: false });
|
|
1986
2236
|
}
|
|
2237
|
+
const streamConversationId = conversationId;
|
|
2238
|
+
const renderIfActiveConversation = (streaming) => {
|
|
2239
|
+
if (state.activeConversationId !== streamConversationId) {
|
|
2240
|
+
return;
|
|
2241
|
+
}
|
|
2242
|
+
state.activeMessages = localMessages;
|
|
2243
|
+
renderMessages(localMessages, streaming);
|
|
2244
|
+
};
|
|
1987
2245
|
const response = await fetch("/api/conversations/" + encodeURIComponent(conversationId) + "/messages", {
|
|
1988
2246
|
method: "POST",
|
|
1989
2247
|
credentials: "include",
|
|
@@ -2013,45 +2271,96 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
2013
2271
|
}
|
|
2014
2272
|
assistantMessage.content += chunk;
|
|
2015
2273
|
assistantMessage._currentText += chunk;
|
|
2016
|
-
|
|
2274
|
+
renderIfActiveConversation(true);
|
|
2017
2275
|
}
|
|
2018
2276
|
if (eventName === "tool:started") {
|
|
2019
2277
|
const toolName = payload.tool || "tool";
|
|
2278
|
+
const startedActivity = addActiveActivityFromToolStart(
|
|
2279
|
+
assistantMessage,
|
|
2280
|
+
payload,
|
|
2281
|
+
);
|
|
2020
2282
|
// If we have text accumulated, push it as a text section
|
|
2021
2283
|
if (assistantMessage._currentText.length > 0) {
|
|
2022
2284
|
assistantMessage._sections.push({ type: "text", content: assistantMessage._currentText });
|
|
2023
2285
|
assistantMessage._currentText = "";
|
|
2024
2286
|
}
|
|
2025
|
-
const
|
|
2287
|
+
const detail =
|
|
2288
|
+
startedActivity && typeof startedActivity.detail === "string"
|
|
2289
|
+
? startedActivity.detail.trim()
|
|
2290
|
+
: "";
|
|
2291
|
+
const toolText =
|
|
2292
|
+
"- start \\x60" + toolName + "\\x60" + (detail ? " (" + detail + ")" : "");
|
|
2026
2293
|
assistantMessage._currentTools.push(toolText);
|
|
2027
2294
|
if (!assistantMessage.metadata) assistantMessage.metadata = {};
|
|
2028
2295
|
if (!assistantMessage.metadata.toolActivity) assistantMessage.metadata.toolActivity = [];
|
|
2029
2296
|
assistantMessage.metadata.toolActivity.push(toolText);
|
|
2030
|
-
|
|
2297
|
+
renderIfActiveConversation(true);
|
|
2031
2298
|
}
|
|
2032
2299
|
if (eventName === "tool:completed") {
|
|
2033
2300
|
const toolName = payload.tool || "tool";
|
|
2301
|
+
const activeActivity = removeActiveActivityForTool(
|
|
2302
|
+
assistantMessage,
|
|
2303
|
+
toolName,
|
|
2304
|
+
);
|
|
2034
2305
|
const duration = typeof payload.duration === "number" ? payload.duration : null;
|
|
2035
|
-
const
|
|
2306
|
+
const detail =
|
|
2307
|
+
activeActivity && typeof activeActivity.detail === "string"
|
|
2308
|
+
? activeActivity.detail.trim()
|
|
2309
|
+
: "";
|
|
2310
|
+
const meta = [];
|
|
2311
|
+
if (duration !== null) meta.push(duration + "ms");
|
|
2312
|
+
if (detail) meta.push(detail);
|
|
2313
|
+
const toolText =
|
|
2314
|
+
"- done \\x60" + toolName + "\\x60" + (meta.length > 0 ? " (" + meta.join(", ") + ")" : "");
|
|
2036
2315
|
assistantMessage._currentTools.push(toolText);
|
|
2037
2316
|
if (!assistantMessage.metadata) assistantMessage.metadata = {};
|
|
2038
2317
|
if (!assistantMessage.metadata.toolActivity) assistantMessage.metadata.toolActivity = [];
|
|
2039
2318
|
assistantMessage.metadata.toolActivity.push(toolText);
|
|
2040
|
-
|
|
2319
|
+
renderIfActiveConversation(true);
|
|
2041
2320
|
}
|
|
2042
2321
|
if (eventName === "tool:error") {
|
|
2043
2322
|
const toolName = payload.tool || "tool";
|
|
2323
|
+
const activeActivity = removeActiveActivityForTool(
|
|
2324
|
+
assistantMessage,
|
|
2325
|
+
toolName,
|
|
2326
|
+
);
|
|
2044
2327
|
const errorMsg = payload.error || "unknown error";
|
|
2045
|
-
const
|
|
2328
|
+
const detail =
|
|
2329
|
+
activeActivity && typeof activeActivity.detail === "string"
|
|
2330
|
+
? activeActivity.detail.trim()
|
|
2331
|
+
: "";
|
|
2332
|
+
const toolText =
|
|
2333
|
+
"- error \\x60" +
|
|
2334
|
+
toolName +
|
|
2335
|
+
"\\x60" +
|
|
2336
|
+
(detail ? " (" + detail + ")" : "") +
|
|
2337
|
+
": " +
|
|
2338
|
+
errorMsg;
|
|
2046
2339
|
assistantMessage._currentTools.push(toolText);
|
|
2047
2340
|
if (!assistantMessage.metadata) assistantMessage.metadata = {};
|
|
2048
2341
|
if (!assistantMessage.metadata.toolActivity) assistantMessage.metadata.toolActivity = [];
|
|
2049
2342
|
assistantMessage.metadata.toolActivity.push(toolText);
|
|
2050
|
-
|
|
2343
|
+
renderIfActiveConversation(true);
|
|
2051
2344
|
}
|
|
2052
2345
|
if (eventName === "tool:approval:required") {
|
|
2053
2346
|
const toolName = payload.tool || "tool";
|
|
2054
|
-
const
|
|
2347
|
+
const activeActivity = removeActiveActivityForTool(
|
|
2348
|
+
assistantMessage,
|
|
2349
|
+
toolName,
|
|
2350
|
+
);
|
|
2351
|
+
const detailFromPayload = describeToolStart(payload);
|
|
2352
|
+
const detail =
|
|
2353
|
+
(activeActivity && typeof activeActivity.detail === "string"
|
|
2354
|
+
? activeActivity.detail.trim()
|
|
2355
|
+
: "") ||
|
|
2356
|
+
(detailFromPayload && typeof detailFromPayload.detail === "string"
|
|
2357
|
+
? detailFromPayload.detail.trim()
|
|
2358
|
+
: "");
|
|
2359
|
+
const toolText =
|
|
2360
|
+
"- approval required \\x60" +
|
|
2361
|
+
toolName +
|
|
2362
|
+
"\\x60" +
|
|
2363
|
+
(detail ? " (" + detail + ")" : "");
|
|
2055
2364
|
assistantMessage._currentTools.push(toolText);
|
|
2056
2365
|
if (!assistantMessage.metadata) assistantMessage.metadata = {};
|
|
2057
2366
|
if (!assistantMessage.metadata.toolActivity) assistantMessage.metadata.toolActivity = [];
|
|
@@ -2076,7 +2385,7 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
2076
2385
|
});
|
|
2077
2386
|
}
|
|
2078
2387
|
}
|
|
2079
|
-
|
|
2388
|
+
renderIfActiveConversation(true);
|
|
2080
2389
|
}
|
|
2081
2390
|
if (eventName === "tool:approval:granted") {
|
|
2082
2391
|
const toolText = "- approval granted";
|
|
@@ -2091,7 +2400,7 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
2091
2400
|
(req) => req.approvalId !== approvalId,
|
|
2092
2401
|
);
|
|
2093
2402
|
}
|
|
2094
|
-
|
|
2403
|
+
renderIfActiveConversation(true);
|
|
2095
2404
|
}
|
|
2096
2405
|
if (eventName === "tool:approval:denied") {
|
|
2097
2406
|
const toolText = "- approval denied";
|
|
@@ -2106,9 +2415,10 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
2106
2415
|
(req) => req.approvalId !== approvalId,
|
|
2107
2416
|
);
|
|
2108
2417
|
}
|
|
2109
|
-
|
|
2418
|
+
renderIfActiveConversation(true);
|
|
2110
2419
|
}
|
|
2111
2420
|
if (eventName === "run:completed") {
|
|
2421
|
+
assistantMessage._activeActivities = [];
|
|
2112
2422
|
if (!assistantMessage.content || assistantMessage.content.length === 0) {
|
|
2113
2423
|
assistantMessage.content = String(payload.result?.response || "");
|
|
2114
2424
|
}
|
|
@@ -2121,21 +2431,24 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
2121
2431
|
assistantMessage._sections.push({ type: "text", content: assistantMessage._currentText });
|
|
2122
2432
|
assistantMessage._currentText = "";
|
|
2123
2433
|
}
|
|
2124
|
-
|
|
2434
|
+
renderIfActiveConversation(false);
|
|
2125
2435
|
}
|
|
2126
2436
|
if (eventName === "run:error") {
|
|
2437
|
+
assistantMessage._activeActivities = [];
|
|
2127
2438
|
const errMsg = payload.error?.message || "Something went wrong";
|
|
2128
2439
|
assistantMessage.content = "";
|
|
2129
2440
|
assistantMessage._error = errMsg;
|
|
2130
|
-
|
|
2441
|
+
renderIfActiveConversation(false);
|
|
2131
2442
|
}
|
|
2132
2443
|
} catch (error) {
|
|
2133
2444
|
console.error("SSE event handling error:", eventName, error);
|
|
2134
2445
|
}
|
|
2135
2446
|
});
|
|
2136
2447
|
}
|
|
2137
|
-
// Update
|
|
2138
|
-
state.
|
|
2448
|
+
// Update active state only if user is still on this conversation.
|
|
2449
|
+
if (state.activeConversationId === streamConversationId) {
|
|
2450
|
+
state.activeMessages = localMessages;
|
|
2451
|
+
}
|
|
2139
2452
|
await loadConversations();
|
|
2140
2453
|
// Don't reload the conversation - we already have the latest state with tool chips
|
|
2141
2454
|
} finally {
|
|
@@ -2303,6 +2616,10 @@ export const renderWebUiHtml = (options?: { agentName?: string }): string => {
|
|
|
2303
2616
|
}
|
|
2304
2617
|
});
|
|
2305
2618
|
|
|
2619
|
+
elements.messages.addEventListener("scroll", () => {
|
|
2620
|
+
state.isMessagesPinnedToBottom = isNearBottom(elements.messages);
|
|
2621
|
+
}, { passive: true });
|
|
2622
|
+
|
|
2306
2623
|
document.addEventListener("click", (event) => {
|
|
2307
2624
|
if (!(event.target instanceof Node)) {
|
|
2308
2625
|
return;
|