@tutti-os/agent-gui 0.0.3 → 0.0.4
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/agent-message-center/index.js +1 -1
- package/dist/{chunk-AF5CXBJN.js → chunk-5Q36BEUM.js} +494 -91
- package/dist/chunk-5Q36BEUM.js.map +1 -0
- package/dist/index.js +761 -188
- package/dist/index.js.map +1 -1
- package/package.json +11 -10
- package/dist/chunk-AF5CXBJN.js.map +0 -1
- package/dist/claude-rounded-F6VPQETB.png +0 -0
- package/dist/codex-rounded-SC63MZAW.png +0 -0
- package/dist/gemini-rounded-O4KAJFIM.png +0 -0
- package/dist/hermes-rounded-QGDHBNRJ.png +0 -0
- package/dist/manage-agent-claude-code-F6VPQETB.png +0 -0
- package/dist/manage-agent-codex-SC63MZAW.png +0 -0
- package/dist/manage-agent-gemini-O4KAJFIM.png +0 -0
- package/dist/manage-agent-hermes-QGDHBNRJ.png +0 -0
- package/dist/manage-agent-nextop-UFAQ22K2.png +0 -0
- package/dist/manage-agent-openclaw-24U7O6CA.png +0 -0
- package/dist/nextop-doc-rounded-UFAQ22K2.png +0 -0
- package/dist/openclaw-rounded-24U7O6CA.png +0 -0
|
@@ -101,7 +101,8 @@ function getExplicitWindowTestAgentActivityRuntime() {
|
|
|
101
101
|
// agentActivityHost.tsx
|
|
102
102
|
import {
|
|
103
103
|
createContext as createContext2,
|
|
104
|
-
useContext as useContext2
|
|
104
|
+
useContext as useContext2,
|
|
105
|
+
useMemo
|
|
105
106
|
} from "react";
|
|
106
107
|
|
|
107
108
|
// host/agentHostApi.ts
|
|
@@ -132,7 +133,10 @@ function AgentActivityHostProvider({
|
|
|
132
133
|
agentHostApi,
|
|
133
134
|
children
|
|
134
135
|
}) {
|
|
135
|
-
const resolvedAgentHostApi =
|
|
136
|
+
const resolvedAgentHostApi = useMemo(
|
|
137
|
+
() => agentHostApi ? toAgentHostRuntimeApi(agentHostApi) : null,
|
|
138
|
+
[agentHostApi]
|
|
139
|
+
);
|
|
136
140
|
currentAgentHostApi = resolvedAgentHostApi;
|
|
137
141
|
return /* @__PURE__ */ jsx2(AgentActivityRuntimeProvider, { runtime: agentActivityRuntime, children: /* @__PURE__ */ jsx2(AgentActivityHostContext.Provider, { value: resolvedAgentHostApi, children }) });
|
|
138
142
|
}
|
|
@@ -183,42 +187,6 @@ function getExplicitWindowTestAgentHostApi() {
|
|
|
183
187
|
return testAgentHostApi ? toAgentHostRuntimeApi(testAgentHostApi) : null;
|
|
184
188
|
}
|
|
185
189
|
|
|
186
|
-
// app/renderer/assets/icons/agents/manage-agent-claude-code.png
|
|
187
|
-
var manage_agent_claude_code_default = "./manage-agent-claude-code-F6VPQETB.png";
|
|
188
|
-
|
|
189
|
-
// app/renderer/assets/icons/agents/manage-agent-codex.png
|
|
190
|
-
var manage_agent_codex_default = "./manage-agent-codex-SC63MZAW.png";
|
|
191
|
-
|
|
192
|
-
// app/renderer/assets/icons/agents/manage-agent-gemini.png
|
|
193
|
-
var manage_agent_gemini_default = "./manage-agent-gemini-O4KAJFIM.png";
|
|
194
|
-
|
|
195
|
-
// app/renderer/assets/icons/agents/manage-agent-hermes.png
|
|
196
|
-
var manage_agent_hermes_default = "./manage-agent-hermes-QGDHBNRJ.png";
|
|
197
|
-
|
|
198
|
-
// app/renderer/assets/icons/agents/manage-agent-nextop.png
|
|
199
|
-
var manage_agent_nextop_default = "./manage-agent-nextop-UFAQ22K2.png";
|
|
200
|
-
|
|
201
|
-
// app/renderer/assets/icons/agents/manage-agent-openclaw.png
|
|
202
|
-
var manage_agent_openclaw_default = "./manage-agent-openclaw-24U7O6CA.png";
|
|
203
|
-
|
|
204
|
-
// app/renderer/assets/icons/agents/claude-rounded.png
|
|
205
|
-
var claude_rounded_default = "./claude-rounded-F6VPQETB.png";
|
|
206
|
-
|
|
207
|
-
// app/renderer/assets/icons/agents/codex-rounded.png
|
|
208
|
-
var codex_rounded_default = "./codex-rounded-SC63MZAW.png";
|
|
209
|
-
|
|
210
|
-
// app/renderer/assets/icons/agents/gemini-rounded.png
|
|
211
|
-
var gemini_rounded_default = "./gemini-rounded-O4KAJFIM.png";
|
|
212
|
-
|
|
213
|
-
// app/renderer/assets/icons/agents/hermes-rounded.png
|
|
214
|
-
var hermes_rounded_default = "./hermes-rounded-QGDHBNRJ.png";
|
|
215
|
-
|
|
216
|
-
// app/renderer/assets/icons/agents/nextop-doc-rounded.png
|
|
217
|
-
var nextop_doc_rounded_default = "./nextop-doc-rounded-UFAQ22K2.png";
|
|
218
|
-
|
|
219
|
-
// app/renderer/assets/icons/agents/openclaw-rounded.png
|
|
220
|
-
var openclaw_rounded_default = "./openclaw-rounded-24U7O6CA.png";
|
|
221
|
-
|
|
222
190
|
// shared/managedAgentProviders.ts
|
|
223
191
|
function normalizeManagedAgentProvider(provider) {
|
|
224
192
|
const normalized = provider?.trim().toLowerCase().replace(/[_\s]+/gu, "-") ?? "";
|
|
@@ -234,25 +202,47 @@ function normalizeManagedAgentProvider(provider) {
|
|
|
234
202
|
}
|
|
235
203
|
}
|
|
236
204
|
|
|
205
|
+
// managedAgentIconAssets.ts
|
|
206
|
+
function agentIconUrl(fileName) {
|
|
207
|
+
return new URL(
|
|
208
|
+
`./app/renderer/assets/icons/agents/${fileName}`,
|
|
209
|
+
import.meta.url
|
|
210
|
+
).href;
|
|
211
|
+
}
|
|
212
|
+
var manageAgentClaudeCodeUrl = agentIconUrl(
|
|
213
|
+
"manage-agent-claude-code.png"
|
|
214
|
+
);
|
|
215
|
+
var manageAgentCodexUrl = agentIconUrl("manage-agent-codex.png");
|
|
216
|
+
var manageAgentGeminiUrl = agentIconUrl("manage-agent-gemini.png");
|
|
217
|
+
var manageAgentHermesUrl = agentIconUrl("manage-agent-hermes.png");
|
|
218
|
+
var manageAgentNextopUrl = agentIconUrl("manage-agent-nextop.png");
|
|
219
|
+
var manageAgentOpenclawUrl = agentIconUrl("manage-agent-openclaw.png");
|
|
220
|
+
var claudeRoundedUrl = agentIconUrl("claude-rounded.png");
|
|
221
|
+
var codexRoundedUrl = agentIconUrl("codex-rounded.png");
|
|
222
|
+
var geminiRoundedUrl = agentIconUrl("gemini-rounded.png");
|
|
223
|
+
var hermesRoundedUrl = agentIconUrl("hermes-rounded.png");
|
|
224
|
+
var nextopDocRoundedUrl = agentIconUrl("nextop-doc-rounded.png");
|
|
225
|
+
var openclawRoundedUrl = agentIconUrl("openclaw-rounded.png");
|
|
226
|
+
|
|
237
227
|
// shared/managedAgentIcons.ts
|
|
238
228
|
var MANAGED_AGENT_ICON_URLS = {
|
|
239
|
-
"claude-code":
|
|
240
|
-
codex:
|
|
241
|
-
gemini:
|
|
242
|
-
hermes:
|
|
243
|
-
nextop:
|
|
244
|
-
openclaw:
|
|
229
|
+
"claude-code": manageAgentClaudeCodeUrl,
|
|
230
|
+
codex: manageAgentCodexUrl,
|
|
231
|
+
gemini: manageAgentGeminiUrl,
|
|
232
|
+
hermes: manageAgentHermesUrl,
|
|
233
|
+
nextop: manageAgentNextopUrl,
|
|
234
|
+
openclaw: manageAgentOpenclawUrl
|
|
245
235
|
};
|
|
246
236
|
var MANAGED_AGENT_ICON_ROUNDED_URLS = {
|
|
247
|
-
"claude-code":
|
|
248
|
-
codex:
|
|
249
|
-
gemini:
|
|
250
|
-
hermes:
|
|
251
|
-
nextop:
|
|
252
|
-
openclaw:
|
|
237
|
+
"claude-code": claudeRoundedUrl,
|
|
238
|
+
codex: codexRoundedUrl,
|
|
239
|
+
gemini: geminiRoundedUrl,
|
|
240
|
+
hermes: hermesRoundedUrl,
|
|
241
|
+
nextop: nextopDocRoundedUrl,
|
|
242
|
+
openclaw: openclawRoundedUrl
|
|
253
243
|
};
|
|
254
|
-
var MANAGED_AGENT_ROUNDED_ICON_FALLBACK_URL =
|
|
255
|
-
var MANAGED_AGENT_ICON_FALLBACK_URL =
|
|
244
|
+
var MANAGED_AGENT_ROUNDED_ICON_FALLBACK_URL = nextopDocRoundedUrl;
|
|
245
|
+
var MANAGED_AGENT_ICON_FALLBACK_URL = manageAgentNextopUrl;
|
|
256
246
|
function managedAgentRoundedIconUrl(provider) {
|
|
257
247
|
return MANAGED_AGENT_ICON_ROUNDED_URLS[normalizeManagedAgentProvider(provider)] ?? MANAGED_AGENT_ROUNDED_ICON_FALLBACK_URL;
|
|
258
248
|
}
|
|
@@ -478,7 +468,7 @@ function numericValue(value) {
|
|
|
478
468
|
import {
|
|
479
469
|
useCallback as useCallback2,
|
|
480
470
|
useEffect as useEffect2,
|
|
481
|
-
useMemo,
|
|
471
|
+
useMemo as useMemo2,
|
|
482
472
|
useRef as useRef2,
|
|
483
473
|
useState
|
|
484
474
|
} from "react";
|
|
@@ -754,7 +744,7 @@ function ApprovalPromptSurface({
|
|
|
754
744
|
labels
|
|
755
745
|
}) {
|
|
756
746
|
"use memo";
|
|
757
|
-
const promptDetails =
|
|
747
|
+
const promptDetails = useMemo2(
|
|
758
748
|
() => formatToolDetails(prompt.input ?? null),
|
|
759
749
|
[prompt.input]
|
|
760
750
|
);
|
|
@@ -762,7 +752,7 @@ function ApprovalPromptSurface({
|
|
|
762
752
|
prompt.title,
|
|
763
753
|
promptDetails.length
|
|
764
754
|
);
|
|
765
|
-
const details =
|
|
755
|
+
const details = useMemo2(
|
|
766
756
|
() => filterDuplicatePromptTitleDetails(promptDetails, visiblePromptTitle),
|
|
767
757
|
[promptDetails, visiblePromptTitle]
|
|
768
758
|
);
|
|
@@ -774,7 +764,7 @@ function ApprovalPromptSurface({
|
|
|
774
764
|
const feedbackTextareaRef = useRef2(null);
|
|
775
765
|
const agentHostApi = useOptionalAgentHostApi() ?? getOptionalAgentHostApi();
|
|
776
766
|
const isDarwin = isDarwinPlatform(agentHostApi?.meta?.platform);
|
|
777
|
-
const feedbackOptionId =
|
|
767
|
+
const feedbackOptionId = useMemo2(
|
|
778
768
|
() => approvalFeedbackOptionId(prompt.options),
|
|
779
769
|
[prompt.options]
|
|
780
770
|
);
|
|
@@ -1055,7 +1045,7 @@ function AskUserPromptSurface({
|
|
|
1055
1045
|
const freeText = question ? freeTextByQuestionId[question.id] ?? "" : "";
|
|
1056
1046
|
const canAdvance = question !== null && (selected.length > 0 || freeText.trim() !== "" || question.options.length === 0);
|
|
1057
1047
|
const isLast = index >= prompt.questions.length - 1;
|
|
1058
|
-
const payload =
|
|
1048
|
+
const payload = useMemo2(() => {
|
|
1059
1049
|
const answersByQuestionId = {};
|
|
1060
1050
|
const answers = [];
|
|
1061
1051
|
for (const current of prompt.questions) {
|
|
@@ -1379,12 +1369,13 @@ function interactiveOptionLabel(label, description) {
|
|
|
1379
1369
|
// shared/AgentMessageMarkdown.tsx
|
|
1380
1370
|
import {
|
|
1381
1371
|
createContext as createContext3,
|
|
1382
|
-
startTransition,
|
|
1372
|
+
startTransition as startTransition2,
|
|
1383
1373
|
useCallback as useCallback3,
|
|
1384
|
-
useEffect as
|
|
1374
|
+
useEffect as useEffect4,
|
|
1385
1375
|
useContext as useContext3,
|
|
1386
|
-
|
|
1387
|
-
|
|
1376
|
+
memo,
|
|
1377
|
+
useMemo as useMemo3,
|
|
1378
|
+
useState as useState3
|
|
1388
1379
|
} from "react";
|
|
1389
1380
|
|
|
1390
1381
|
// app/renderer/components/ZoomableImage.tsx
|
|
@@ -1685,13 +1676,320 @@ function isDirectAgentGeneratedImagePath(path) {
|
|
|
1685
1676
|
return /\.(?:png|jpe?g|gif|webp|bmp)$/i.test(path);
|
|
1686
1677
|
}
|
|
1687
1678
|
|
|
1679
|
+
// shared/streamingMarkdownTailStabilizer.ts
|
|
1680
|
+
var DEFAULT_MAX_TAIL_CHARS = 4096;
|
|
1681
|
+
function stabilizeStreamingMarkdownTail(content, options) {
|
|
1682
|
+
if (!options.streaming || content.length === 0) {
|
|
1683
|
+
return { content, changed: false };
|
|
1684
|
+
}
|
|
1685
|
+
const maxTailChars = Math.max(
|
|
1686
|
+
256,
|
|
1687
|
+
options.maxTailChars ?? DEFAULT_MAX_TAIL_CHARS
|
|
1688
|
+
);
|
|
1689
|
+
const tailStart = Math.max(0, content.length - maxTailChars);
|
|
1690
|
+
const tail = content.slice(tailStart);
|
|
1691
|
+
const fence = findOpenFence(tail);
|
|
1692
|
+
if (fence) {
|
|
1693
|
+
return {
|
|
1694
|
+
content: `${content}
|
|
1695
|
+
${fence.marker.repeat(fence.length)}`,
|
|
1696
|
+
changed: true,
|
|
1697
|
+
reason: "open-fence"
|
|
1698
|
+
};
|
|
1699
|
+
}
|
|
1700
|
+
const incompleteLink = stabilizeIncompleteTailLink(content);
|
|
1701
|
+
if (incompleteLink) {
|
|
1702
|
+
return incompleteLink;
|
|
1703
|
+
}
|
|
1704
|
+
const listMarker = stabilizeDanglingListMarker(content);
|
|
1705
|
+
if (listMarker) {
|
|
1706
|
+
return listMarker;
|
|
1707
|
+
}
|
|
1708
|
+
const tableRow = stabilizePartialTableRow(content);
|
|
1709
|
+
if (tableRow) {
|
|
1710
|
+
return tableRow;
|
|
1711
|
+
}
|
|
1712
|
+
const inlineCode = findOpenInlineCodeSpan(tail);
|
|
1713
|
+
if (inlineCode) {
|
|
1714
|
+
return {
|
|
1715
|
+
content: `${content}${"`".repeat(inlineCode.length)}`,
|
|
1716
|
+
changed: true,
|
|
1717
|
+
reason: "open-inline-code"
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1720
|
+
const emphasis = stabilizeTrailingEmphasisMarker(content);
|
|
1721
|
+
if (emphasis) {
|
|
1722
|
+
return emphasis;
|
|
1723
|
+
}
|
|
1724
|
+
return { content, changed: false };
|
|
1725
|
+
}
|
|
1726
|
+
function findOpenFence(tail) {
|
|
1727
|
+
let openFence = null;
|
|
1728
|
+
for (const line of tail.replace(/\r\n?/g, "\n").split("\n")) {
|
|
1729
|
+
const fence = parseFenceLine(line);
|
|
1730
|
+
if (!fence) {
|
|
1731
|
+
continue;
|
|
1732
|
+
}
|
|
1733
|
+
if (!openFence) {
|
|
1734
|
+
openFence = fence;
|
|
1735
|
+
continue;
|
|
1736
|
+
}
|
|
1737
|
+
if (fence.marker === openFence.marker && fence.length >= openFence.length) {
|
|
1738
|
+
openFence = null;
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
return openFence;
|
|
1742
|
+
}
|
|
1743
|
+
function parseFenceLine(line) {
|
|
1744
|
+
let index = 0;
|
|
1745
|
+
while (index < line.length && line[index] === " " && index < 4) {
|
|
1746
|
+
index += 1;
|
|
1747
|
+
}
|
|
1748
|
+
const marker = line[index];
|
|
1749
|
+
if (marker !== "`" && marker !== "~") {
|
|
1750
|
+
return null;
|
|
1751
|
+
}
|
|
1752
|
+
let length = 0;
|
|
1753
|
+
while (line[index + length] === marker) {
|
|
1754
|
+
length += 1;
|
|
1755
|
+
}
|
|
1756
|
+
return length >= 3 ? { marker, length } : null;
|
|
1757
|
+
}
|
|
1758
|
+
function stabilizeIncompleteTailLink(content) {
|
|
1759
|
+
const lineStart = content.lastIndexOf("\n") + 1;
|
|
1760
|
+
const line = content.slice(lineStart);
|
|
1761
|
+
const linkStart = line.lastIndexOf("[");
|
|
1762
|
+
const imageStart = line.lastIndexOf("![");
|
|
1763
|
+
const openBracketIndex = imageStart >= 0 && imageStart + 1 === linkStart ? imageStart : linkStart;
|
|
1764
|
+
if (openBracketIndex < 0) {
|
|
1765
|
+
return null;
|
|
1766
|
+
}
|
|
1767
|
+
const absoluteOpenIndex = lineStart + openBracketIndex;
|
|
1768
|
+
const suffix = content.slice(absoluteOpenIndex);
|
|
1769
|
+
const closeLabelIndex = suffix.indexOf("]");
|
|
1770
|
+
if (closeLabelIndex < 0) {
|
|
1771
|
+
const label2 = suffix.startsWith("![") ? suffix.slice(2) : suffix.slice(1);
|
|
1772
|
+
return {
|
|
1773
|
+
content: `${content.slice(0, absoluteOpenIndex)}${label2}`,
|
|
1774
|
+
changed: true,
|
|
1775
|
+
reason: "incomplete-link-label"
|
|
1776
|
+
};
|
|
1777
|
+
}
|
|
1778
|
+
if (suffix[closeLabelIndex + 1] !== "(" || suffix.includes(")")) {
|
|
1779
|
+
return null;
|
|
1780
|
+
}
|
|
1781
|
+
const label = suffix.startsWith("![") ? suffix.slice(2, closeLabelIndex) : suffix.slice(1, closeLabelIndex);
|
|
1782
|
+
return {
|
|
1783
|
+
content: `${content.slice(0, absoluteOpenIndex)}${label}`,
|
|
1784
|
+
changed: true,
|
|
1785
|
+
reason: "incomplete-link-target"
|
|
1786
|
+
};
|
|
1787
|
+
}
|
|
1788
|
+
function stabilizeDanglingListMarker(content) {
|
|
1789
|
+
const lineStart = content.lastIndexOf("\n") + 1;
|
|
1790
|
+
const line = content.slice(lineStart);
|
|
1791
|
+
const trimmed = line.trim();
|
|
1792
|
+
const isBullet = trimmed === "-" || trimmed === "*" || trimmed === "+";
|
|
1793
|
+
const isOrdered = trimmed.length >= 2 && trimmed.endsWith(".") && [...trimmed.slice(0, -1)].every((char) => char >= "0" && char <= "9");
|
|
1794
|
+
if (!isBullet && !isOrdered) {
|
|
1795
|
+
return null;
|
|
1796
|
+
}
|
|
1797
|
+
return {
|
|
1798
|
+
content: content.slice(0, lineStart),
|
|
1799
|
+
changed: true,
|
|
1800
|
+
reason: "dangling-list-marker"
|
|
1801
|
+
};
|
|
1802
|
+
}
|
|
1803
|
+
function stabilizePartialTableRow(content) {
|
|
1804
|
+
if (content.endsWith("\n")) {
|
|
1805
|
+
return null;
|
|
1806
|
+
}
|
|
1807
|
+
const lines = content.replace(/\r\n?/g, "\n").split("\n");
|
|
1808
|
+
const currentLine = lines.at(-1) ?? "";
|
|
1809
|
+
const previousLine = lines.at(-2) ?? "";
|
|
1810
|
+
if (!currentLine.includes("|") || !previousLine.includes("|")) {
|
|
1811
|
+
return null;
|
|
1812
|
+
}
|
|
1813
|
+
if (currentLine.trimEnd().endsWith("|")) {
|
|
1814
|
+
return null;
|
|
1815
|
+
}
|
|
1816
|
+
if (countChar(previousLine, "|") < 2) {
|
|
1817
|
+
return null;
|
|
1818
|
+
}
|
|
1819
|
+
return {
|
|
1820
|
+
content: `${content} |`,
|
|
1821
|
+
changed: true,
|
|
1822
|
+
reason: "partial-table-row"
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1825
|
+
function findOpenInlineCodeSpan(tail) {
|
|
1826
|
+
const lastParagraph = tail.slice(tail.lastIndexOf("\n\n") + 2);
|
|
1827
|
+
let openLength = 0;
|
|
1828
|
+
for (let index = 0; index < lastParagraph.length; index += 1) {
|
|
1829
|
+
if (lastParagraph[index] !== "`") {
|
|
1830
|
+
continue;
|
|
1831
|
+
}
|
|
1832
|
+
let length = 1;
|
|
1833
|
+
while (lastParagraph[index + length] === "`") {
|
|
1834
|
+
length += 1;
|
|
1835
|
+
}
|
|
1836
|
+
if (length >= 3) {
|
|
1837
|
+
index += length - 1;
|
|
1838
|
+
continue;
|
|
1839
|
+
}
|
|
1840
|
+
openLength = openLength === length ? 0 : length;
|
|
1841
|
+
index += length - 1;
|
|
1842
|
+
}
|
|
1843
|
+
return openLength > 0 ? { length: openLength } : null;
|
|
1844
|
+
}
|
|
1845
|
+
function stabilizeTrailingEmphasisMarker(content) {
|
|
1846
|
+
const marker = content.at(-1);
|
|
1847
|
+
if (marker !== "*" && marker !== "_") {
|
|
1848
|
+
return null;
|
|
1849
|
+
}
|
|
1850
|
+
const previous = content.at(-2);
|
|
1851
|
+
const nextContent = previous === marker ? content.slice(0, -2) : content.slice(0, -1);
|
|
1852
|
+
return {
|
|
1853
|
+
content: nextContent,
|
|
1854
|
+
changed: true,
|
|
1855
|
+
reason: "trailing-emphasis-marker"
|
|
1856
|
+
};
|
|
1857
|
+
}
|
|
1858
|
+
function countChar(value, char) {
|
|
1859
|
+
let count = 0;
|
|
1860
|
+
for (const current of value) {
|
|
1861
|
+
if (current === char) {
|
|
1862
|
+
count += 1;
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
return count;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
// shared/useStreamingVisibleText.ts
|
|
1869
|
+
import {
|
|
1870
|
+
startTransition,
|
|
1871
|
+
useEffect as useEffect3,
|
|
1872
|
+
useRef as useRef3,
|
|
1873
|
+
useState as useState2
|
|
1874
|
+
} from "react";
|
|
1875
|
+
var DEFAULT_FRAME_MS = 24;
|
|
1876
|
+
var DEFAULT_MAX_CHARS_PER_SECOND = 6e3;
|
|
1877
|
+
var DEFAULT_TRAILING_FLUSH_CHARS = 0;
|
|
1878
|
+
function useStreamingVisibleText(sourceText, options) {
|
|
1879
|
+
const {
|
|
1880
|
+
enabled,
|
|
1881
|
+
frameMs = DEFAULT_FRAME_MS,
|
|
1882
|
+
maxCharsPerSecond = DEFAULT_MAX_CHARS_PER_SECOND,
|
|
1883
|
+
trailingFlushChars = DEFAULT_TRAILING_FLUSH_CHARS
|
|
1884
|
+
} = options;
|
|
1885
|
+
const [visibleText, setVisibleText] = useState2(sourceText);
|
|
1886
|
+
const sourceRef = useRef3(sourceText);
|
|
1887
|
+
const visibleRef = useRef3(visibleText);
|
|
1888
|
+
const timerRef = useRef3(null);
|
|
1889
|
+
useEffect3(() => {
|
|
1890
|
+
visibleRef.current = visibleText;
|
|
1891
|
+
}, [visibleText]);
|
|
1892
|
+
useEffect3(
|
|
1893
|
+
() => () => {
|
|
1894
|
+
clearStreamingVisibleTextTimer(timerRef);
|
|
1895
|
+
},
|
|
1896
|
+
[]
|
|
1897
|
+
);
|
|
1898
|
+
useEffect3(() => {
|
|
1899
|
+
sourceRef.current = sourceText;
|
|
1900
|
+
if (!enabled) {
|
|
1901
|
+
clearStreamingVisibleTextTimer(timerRef);
|
|
1902
|
+
visibleRef.current = sourceText;
|
|
1903
|
+
setVisibleText(sourceText);
|
|
1904
|
+
return;
|
|
1905
|
+
}
|
|
1906
|
+
if (sourceText === visibleRef.current || timerRef.current !== null) {
|
|
1907
|
+
return;
|
|
1908
|
+
}
|
|
1909
|
+
timerRef.current = setTimeout(
|
|
1910
|
+
() => {
|
|
1911
|
+
timerRef.current = null;
|
|
1912
|
+
const nextVisibleText = advanceStreamingVisibleText({
|
|
1913
|
+
visibleText: visibleRef.current,
|
|
1914
|
+
sourceText: sourceRef.current,
|
|
1915
|
+
frameMs,
|
|
1916
|
+
maxCharsPerSecond,
|
|
1917
|
+
trailingFlushChars
|
|
1918
|
+
});
|
|
1919
|
+
if (nextVisibleText === visibleRef.current) {
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
visibleRef.current = nextVisibleText;
|
|
1923
|
+
startTransition(() => {
|
|
1924
|
+
setVisibleText(nextVisibleText);
|
|
1925
|
+
});
|
|
1926
|
+
},
|
|
1927
|
+
Math.max(1, frameMs)
|
|
1928
|
+
);
|
|
1929
|
+
return void 0;
|
|
1930
|
+
}, [
|
|
1931
|
+
enabled,
|
|
1932
|
+
frameMs,
|
|
1933
|
+
maxCharsPerSecond,
|
|
1934
|
+
sourceText,
|
|
1935
|
+
trailingFlushChars,
|
|
1936
|
+
visibleText
|
|
1937
|
+
]);
|
|
1938
|
+
return enabled ? visibleText : sourceText;
|
|
1939
|
+
}
|
|
1940
|
+
function advanceStreamingVisibleText({
|
|
1941
|
+
visibleText,
|
|
1942
|
+
sourceText,
|
|
1943
|
+
frameMs = DEFAULT_FRAME_MS,
|
|
1944
|
+
maxCharsPerSecond = DEFAULT_MAX_CHARS_PER_SECOND,
|
|
1945
|
+
trailingFlushChars = DEFAULT_TRAILING_FLUSH_CHARS
|
|
1946
|
+
}) {
|
|
1947
|
+
if (visibleText === sourceText) {
|
|
1948
|
+
return visibleText;
|
|
1949
|
+
}
|
|
1950
|
+
const prefixLength = sourceText.startsWith(visibleText) ? visibleText.length : commonPrefixLength(visibleText, sourceText);
|
|
1951
|
+
const stablePrefix = sourceText.slice(0, prefixLength);
|
|
1952
|
+
const remainingLength = sourceText.length - prefixLength;
|
|
1953
|
+
if (remainingLength <= trailingFlushChars) {
|
|
1954
|
+
return sourceText;
|
|
1955
|
+
}
|
|
1956
|
+
const charsPerFrame = Math.max(
|
|
1957
|
+
1,
|
|
1958
|
+
Math.ceil(Math.max(1, maxCharsPerSecond) * Math.max(1, frameMs) / 1e3)
|
|
1959
|
+
);
|
|
1960
|
+
return sourceText.slice(
|
|
1961
|
+
0,
|
|
1962
|
+
Math.min(sourceText.length, stablePrefix.length + charsPerFrame)
|
|
1963
|
+
);
|
|
1964
|
+
}
|
|
1965
|
+
function commonPrefixLength(left, right) {
|
|
1966
|
+
const maxLength = Math.min(left.length, right.length);
|
|
1967
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
1968
|
+
if (left.charCodeAt(index) !== right.charCodeAt(index)) {
|
|
1969
|
+
return index;
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
return maxLength;
|
|
1973
|
+
}
|
|
1974
|
+
function clearStreamingVisibleTextTimer(timerRef) {
|
|
1975
|
+
if (timerRef.current === null) {
|
|
1976
|
+
return;
|
|
1977
|
+
}
|
|
1978
|
+
clearTimeout(timerRef.current);
|
|
1979
|
+
timerRef.current = null;
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1688
1982
|
// shared/AgentMessageMarkdown.tsx
|
|
1689
|
-
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1983
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1690
1984
|
var COLLAPSED_LINE_LIMIT = 8;
|
|
1691
1985
|
var APPROX_CHARS_PER_LINE = 34;
|
|
1692
1986
|
var DEFERRED_LONG_MARKDOWN_CHAR_THRESHOLD = 4096;
|
|
1987
|
+
var STREAMING_MARKDOWN_EMERGENCY_PLAIN_CHAR_THRESHOLD = 96e3;
|
|
1693
1988
|
var DEFERRED_LONG_MARKDOWN_FALLBACK_DELAY_MS = 80;
|
|
1694
1989
|
var DEFERRED_LONG_MARKDOWN_IDLE_TIMEOUT_MS = 700;
|
|
1990
|
+
var STREAMING_MARKDOWN_FRAME_MS = 24;
|
|
1991
|
+
var STREAMING_MARKDOWN_MAX_CHARS_PER_SECOND = 6e3;
|
|
1992
|
+
var STREAMING_MARKDOWN_TAIL_FLUSH_CHARS = 0;
|
|
1695
1993
|
var PLAIN_SESSION_MENTION_AGENT_LABELS = [
|
|
1696
1994
|
"Claude Code",
|
|
1697
1995
|
"Nexight",
|
|
@@ -1718,34 +2016,47 @@ function AgentMessageMarkdown({
|
|
|
1718
2016
|
inline = false,
|
|
1719
2017
|
normalizePlainIssueMentionTitle = false,
|
|
1720
2018
|
deferLongContentRender = false,
|
|
1721
|
-
enableImageZoom = false
|
|
2019
|
+
enableImageZoom = false,
|
|
2020
|
+
streaming = false
|
|
1722
2021
|
}) {
|
|
1723
2022
|
"use memo";
|
|
1724
2023
|
const { t } = useTranslation();
|
|
2024
|
+
const visibleContent = useStreamingVisibleText(content, {
|
|
2025
|
+
enabled: streaming,
|
|
2026
|
+
frameMs: STREAMING_MARKDOWN_FRAME_MS,
|
|
2027
|
+
maxCharsPerSecond: STREAMING_MARKDOWN_MAX_CHARS_PER_SECOND,
|
|
2028
|
+
trailingFlushChars: STREAMING_MARKDOWN_TAIL_FLUSH_CHARS
|
|
2029
|
+
});
|
|
2030
|
+
const stabilizedContent = useMemo3(
|
|
2031
|
+
() => stabilizeStreamingMarkdownTail(visibleContent, {
|
|
2032
|
+
streaming
|
|
2033
|
+
}).content,
|
|
2034
|
+
[streaming, visibleContent]
|
|
2035
|
+
);
|
|
1725
2036
|
const workspaceRoot = workspaceLinkContext?.workspaceRoot ?? null;
|
|
1726
2037
|
const basePath = workspaceLinkContext?.basePath ?? null;
|
|
1727
2038
|
const workspaceLinkSource = workspaceLinkContext?.source ?? null;
|
|
1728
|
-
const [isExpanded, setIsExpanded] =
|
|
2039
|
+
const [isExpanded, setIsExpanded] = useState3(false);
|
|
1729
2040
|
const resolvedExpandLabel = expandLabel ?? t("agentHost.workspaceAgentMessageExpand");
|
|
1730
|
-
const shouldCollapse = collapsible && isLikelyLongerThanLineLimit(
|
|
2041
|
+
const shouldCollapse = collapsible && isLikelyLongerThanLineLimit(stabilizedContent);
|
|
1731
2042
|
const isCollapsed = shouldCollapse && !isExpanded;
|
|
1732
2043
|
const ContainerTag = inline ? "span" : "div";
|
|
1733
|
-
const contentSignature =
|
|
1734
|
-
() => hashMarkdownProfilerContent(
|
|
1735
|
-
[
|
|
2044
|
+
const contentSignature = useMemo3(
|
|
2045
|
+
() => hashMarkdownProfilerContent(stabilizedContent),
|
|
2046
|
+
[stabilizedContent]
|
|
1736
2047
|
);
|
|
1737
|
-
const normalizedContent =
|
|
2048
|
+
const normalizedContent = useMemo3(
|
|
1738
2049
|
() => linkBareLocalAbsolutePaths(
|
|
1739
2050
|
normalizeMentionMarkdownLinks(
|
|
1740
2051
|
normalizePlainIssueMentionTitle ? normalizePlainIssueMentionTitleContent(
|
|
1741
|
-
normalizePlainSessionMentionTitle(
|
|
1742
|
-
) : normalizePlainSessionMentionTitle(
|
|
2052
|
+
normalizePlainSessionMentionTitle(stabilizedContent)
|
|
2053
|
+
) : normalizePlainSessionMentionTitle(stabilizedContent)
|
|
1743
2054
|
)
|
|
1744
2055
|
),
|
|
1745
|
-
[
|
|
2056
|
+
[normalizePlainIssueMentionTitle, stabilizedContent]
|
|
1746
2057
|
);
|
|
1747
2058
|
const isMentionOnly = isMentionOnlyMarkdownContent(normalizedContent);
|
|
1748
|
-
const shouldDeferMarkdownRender = deferLongContentRender && !inline && content.length >= DEFERRED_LONG_MARKDOWN_CHAR_THRESHOLD && !isExpanded;
|
|
2059
|
+
const shouldDeferMarkdownRender = deferLongContentRender && !inline && content.length >= (streaming ? STREAMING_MARKDOWN_EMERGENCY_PLAIN_CHAR_THRESHOLD : DEFERRED_LONG_MARKDOWN_CHAR_THRESHOLD) && !isExpanded;
|
|
1749
2060
|
const markdownRenderReady = useDeferredMarkdownRenderReady(
|
|
1750
2061
|
contentSignature,
|
|
1751
2062
|
shouldDeferMarkdownRender
|
|
@@ -1780,7 +2091,7 @@ function AgentMessageMarkdown({
|
|
|
1780
2091
|
},
|
|
1781
2092
|
[handleLinkClick]
|
|
1782
2093
|
);
|
|
1783
|
-
const markdownComponents =
|
|
2094
|
+
const markdownComponents = useMemo3(
|
|
1784
2095
|
() => ({
|
|
1785
2096
|
a: (props) => /* @__PURE__ */ jsx6(
|
|
1786
2097
|
MarkdownLink,
|
|
@@ -1836,7 +2147,13 @@ function AgentMessageMarkdown({
|
|
|
1836
2147
|
"data-agent-mention-only": isMentionOnly ? "true" : void 0,
|
|
1837
2148
|
"data-collapsed": isCollapsed ? "true" : "false",
|
|
1838
2149
|
onClickCapture: handleAnchorClickCapture,
|
|
1839
|
-
children: markdownRenderReady ? /* @__PURE__ */ jsx6(
|
|
2150
|
+
children: markdownRenderReady ? streaming ? /* @__PURE__ */ jsx6(
|
|
2151
|
+
StreamingMarkdownBlocks,
|
|
2152
|
+
{
|
|
2153
|
+
content: normalizedContent,
|
|
2154
|
+
components: markdownComponents
|
|
2155
|
+
}
|
|
2156
|
+
) : /* @__PURE__ */ jsx6(
|
|
1840
2157
|
ReactMarkdown,
|
|
1841
2158
|
{
|
|
1842
2159
|
remarkPlugins: [remarkGfm],
|
|
@@ -1868,6 +2185,92 @@ function AgentMessageMarkdown({
|
|
|
1868
2185
|
}
|
|
1869
2186
|
);
|
|
1870
2187
|
}
|
|
2188
|
+
function StreamingMarkdownBlocks({
|
|
2189
|
+
content,
|
|
2190
|
+
components
|
|
2191
|
+
}) {
|
|
2192
|
+
const blocks = useMemo3(
|
|
2193
|
+
() => splitStreamingMarkdownBlocks(content),
|
|
2194
|
+
[content]
|
|
2195
|
+
);
|
|
2196
|
+
return /* @__PURE__ */ jsx6(Fragment2, { children: blocks.map((block, index) => /* @__PURE__ */ jsx6(
|
|
2197
|
+
MemoizedMarkdownBlock,
|
|
2198
|
+
{
|
|
2199
|
+
content: block.content,
|
|
2200
|
+
components
|
|
2201
|
+
},
|
|
2202
|
+
`${index}:${hashMarkdownProfilerContent(block.initialKeyContent)}`
|
|
2203
|
+
)) });
|
|
2204
|
+
}
|
|
2205
|
+
var MemoizedMarkdownBlock = memo(function MemoizedMarkdownBlock2({
|
|
2206
|
+
content,
|
|
2207
|
+
components
|
|
2208
|
+
}) {
|
|
2209
|
+
return /* @__PURE__ */ jsx6(
|
|
2210
|
+
ReactMarkdown,
|
|
2211
|
+
{
|
|
2212
|
+
remarkPlugins: [remarkGfm],
|
|
2213
|
+
rehypePlugins: [[rehypeSanitize, MARKDOWN_SANITIZE_SCHEMA]],
|
|
2214
|
+
urlTransform: markdownUrlTransform,
|
|
2215
|
+
components,
|
|
2216
|
+
children: content
|
|
2217
|
+
}
|
|
2218
|
+
);
|
|
2219
|
+
});
|
|
2220
|
+
function splitStreamingMarkdownBlocks(content) {
|
|
2221
|
+
const normalized = content.replace(/\r\n?/g, "\n");
|
|
2222
|
+
if (!normalized) {
|
|
2223
|
+
return [{ content: "", initialKeyContent: "" }];
|
|
2224
|
+
}
|
|
2225
|
+
const lines = normalized.split("\n");
|
|
2226
|
+
const blocks = [];
|
|
2227
|
+
const current = [];
|
|
2228
|
+
let fence = null;
|
|
2229
|
+
for (const line of lines) {
|
|
2230
|
+
current.push(line);
|
|
2231
|
+
const lineFence = parseStreamingFence(line);
|
|
2232
|
+
if (lineFence) {
|
|
2233
|
+
if (!fence) {
|
|
2234
|
+
fence = lineFence;
|
|
2235
|
+
} else if (lineFence.marker === fence.marker && lineFence.length >= fence.length) {
|
|
2236
|
+
fence = null;
|
|
2237
|
+
}
|
|
2238
|
+
continue;
|
|
2239
|
+
}
|
|
2240
|
+
if (!fence && line.trim() === "") {
|
|
2241
|
+
pushStreamingMarkdownBlock(blocks, current);
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
pushStreamingMarkdownBlock(blocks, current);
|
|
2245
|
+
return blocks.length > 0 ? blocks : [{ content: normalized, initialKeyContent: normalized }];
|
|
2246
|
+
}
|
|
2247
|
+
function pushStreamingMarkdownBlock(blocks, lines) {
|
|
2248
|
+
if (lines.length === 0) {
|
|
2249
|
+
return;
|
|
2250
|
+
}
|
|
2251
|
+
const content = lines.join("\n");
|
|
2252
|
+
if (!content) {
|
|
2253
|
+
lines.length = 0;
|
|
2254
|
+
return;
|
|
2255
|
+
}
|
|
2256
|
+
blocks.push({
|
|
2257
|
+
content,
|
|
2258
|
+
initialKeyContent: content
|
|
2259
|
+
});
|
|
2260
|
+
lines.length = 0;
|
|
2261
|
+
}
|
|
2262
|
+
function parseStreamingFence(line) {
|
|
2263
|
+
const trimmed = line.trimStart();
|
|
2264
|
+
const marker = trimmed[0];
|
|
2265
|
+
if (marker !== "`" && marker !== "~") {
|
|
2266
|
+
return null;
|
|
2267
|
+
}
|
|
2268
|
+
let length = 0;
|
|
2269
|
+
while (trimmed[length] === marker) {
|
|
2270
|
+
length += 1;
|
|
2271
|
+
}
|
|
2272
|
+
return length >= 3 ? { marker, length } : null;
|
|
2273
|
+
}
|
|
1871
2274
|
function resolveMarkdownAnchorHref(target) {
|
|
1872
2275
|
if (!(target instanceof Element)) {
|
|
1873
2276
|
return null;
|
|
@@ -1907,11 +2310,11 @@ function activateMarkdownLinkFromPointer(event, href, onLinkClick) {
|
|
|
1907
2310
|
activateMarkdownLink(event, href, onLinkClick);
|
|
1908
2311
|
}
|
|
1909
2312
|
function useDeferredMarkdownRenderReady(contentSignature, shouldDefer) {
|
|
1910
|
-
const [readySignature, setReadySignature] =
|
|
2313
|
+
const [readySignature, setReadySignature] = useState3(
|
|
1911
2314
|
shouldDefer ? null : contentSignature
|
|
1912
2315
|
);
|
|
1913
2316
|
const renderReady = !shouldDefer || readySignature === contentSignature;
|
|
1914
|
-
|
|
2317
|
+
useEffect4(() => {
|
|
1915
2318
|
if (!shouldDefer) {
|
|
1916
2319
|
setReadySignature(contentSignature);
|
|
1917
2320
|
return;
|
|
@@ -1923,7 +2326,7 @@ function useDeferredMarkdownRenderReady(contentSignature, shouldDefer) {
|
|
|
1923
2326
|
if (canceled) {
|
|
1924
2327
|
return;
|
|
1925
2328
|
}
|
|
1926
|
-
|
|
2329
|
+
startTransition2(() => {
|
|
1927
2330
|
setReadySignature(contentSignature);
|
|
1928
2331
|
});
|
|
1929
2332
|
};
|
|
@@ -2232,10 +2635,10 @@ function MarkdownImage({
|
|
|
2232
2635
|
const canReadWorkspaceImage = Boolean(workspacePath && readWorkspaceImage);
|
|
2233
2636
|
const shouldEnableZoom = enableZoom && !isInsideLink;
|
|
2234
2637
|
const resolvedSrc = typeof src === "string" ? resolveRenderableMarkdownImageSrc(src) : src;
|
|
2235
|
-
const [state, setState] =
|
|
2638
|
+
const [state, setState] = useState3(
|
|
2236
2639
|
() => canReadWorkspaceImage && workspacePath ? peekCachedMarkdownImageState(workspacePath) ?? { status: "loading" } : null
|
|
2237
2640
|
);
|
|
2238
|
-
|
|
2641
|
+
useEffect4(() => {
|
|
2239
2642
|
if (!workspacePath || !readWorkspaceImage) {
|
|
2240
2643
|
setState(null);
|
|
2241
2644
|
return;
|
|
@@ -2784,9 +3187,9 @@ function workspaceAgentActivityStatusLabel(status, t) {
|
|
|
2784
3187
|
import {
|
|
2785
3188
|
forwardRef as forwardRef2,
|
|
2786
3189
|
useCallback as useCallback4,
|
|
2787
|
-
useEffect as
|
|
2788
|
-
useRef as
|
|
2789
|
-
useState as
|
|
3190
|
+
useEffect as useEffect5,
|
|
3191
|
+
useRef as useRef4,
|
|
3192
|
+
useState as useState4
|
|
2790
3193
|
} from "react";
|
|
2791
3194
|
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2792
3195
|
var MIN_THUMB_HEIGHT = 24;
|
|
@@ -2799,14 +3202,14 @@ function CustomScrollbar({
|
|
|
2799
3202
|
syncKey
|
|
2800
3203
|
}) {
|
|
2801
3204
|
"use memo";
|
|
2802
|
-
const trackRef =
|
|
2803
|
-
const dragStateRef =
|
|
2804
|
-
const [scrollbarState, setScrollbarState] =
|
|
3205
|
+
const trackRef = useRef4(null);
|
|
3206
|
+
const dragStateRef = useRef4(null);
|
|
3207
|
+
const [scrollbarState, setScrollbarState] = useState4({
|
|
2805
3208
|
scrollable: false,
|
|
2806
3209
|
thumbHeight: 0,
|
|
2807
3210
|
thumbTop: 0
|
|
2808
3211
|
});
|
|
2809
|
-
const [dragging, setDragging] =
|
|
3212
|
+
const [dragging, setDragging] = useState4(false);
|
|
2810
3213
|
const syncScrollbarState = useCallback4(() => {
|
|
2811
3214
|
const viewport = getViewport();
|
|
2812
3215
|
if (!viewport) {
|
|
@@ -2908,7 +3311,7 @@ function CustomScrollbar({
|
|
|
2908
3311
|
},
|
|
2909
3312
|
[getViewport, scrollbarState.scrollable, scrollbarState.thumbHeight]
|
|
2910
3313
|
);
|
|
2911
|
-
|
|
3314
|
+
useEffect5(() => {
|
|
2912
3315
|
if (!dragging) {
|
|
2913
3316
|
return;
|
|
2914
3317
|
}
|
|
@@ -2933,7 +3336,7 @@ function CustomScrollbar({
|
|
|
2933
3336
|
window.removeEventListener("mouseup", handleMouseUp);
|
|
2934
3337
|
};
|
|
2935
3338
|
}, [dragging, getViewport, syncScrollbarState]);
|
|
2936
|
-
|
|
3339
|
+
useEffect5(() => {
|
|
2937
3340
|
const viewport = getViewport();
|
|
2938
3341
|
if (!viewport) {
|
|
2939
3342
|
setScrollbarState({ scrollable: false, thumbHeight: 0, thumbTop: 0 });
|
|
@@ -2987,7 +3390,7 @@ var CustomScrollArea = forwardRef2(function CustomScrollArea2({
|
|
|
2987
3390
|
...viewportProps
|
|
2988
3391
|
}, forwardedRef) {
|
|
2989
3392
|
"use memo";
|
|
2990
|
-
const viewportRef =
|
|
3393
|
+
const viewportRef = useRef4(null);
|
|
2991
3394
|
const getViewport = useCallback4(() => viewportRef.current, []);
|
|
2992
3395
|
return /* @__PURE__ */ jsxs5(
|
|
2993
3396
|
"div",
|
|
@@ -3072,4 +3475,4 @@ export {
|
|
|
3072
3475
|
normalizeWorkspaceAgentActivityDisplayStatus,
|
|
3073
3476
|
workspaceAgentActivityStatusLabel
|
|
3074
3477
|
};
|
|
3075
|
-
//# sourceMappingURL=chunk-
|
|
3478
|
+
//# sourceMappingURL=chunk-5Q36BEUM.js.map
|