@poncho-ai/cli 0.24.1 → 0.24.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 +5 -5
- package/CHANGELOG.md +8 -0
- package/dist/{chunk-3ETNDULB.js → chunk-UTZB2CS7.js} +134 -40
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{run-interactive-ink-IEB4MZ2C.js → run-interactive-ink-REIUGQ5X.js} +1 -1
- package/package.json +3 -3
- package/src/index.ts +24 -0
- package/src/web-ui-client.ts +95 -39
- package/src/web-ui-styles.ts +19 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @poncho-ai/cli@0.24.
|
|
2
|
+
> @poncho-ai/cli@0.24.2 build /home/runner/work/poncho-ai/poncho-ai/packages/cli
|
|
3
3
|
> tsup src/index.ts src/cli.ts --format esm --dts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/cli.ts, src/index.ts
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
[34mESM[39m Build start
|
|
10
10
|
[32mESM[39m [1mdist/cli.js [22m[32m94.00 B[39m
|
|
11
11
|
[32mESM[39m [1mdist/index.js [22m[32m857.00 B[39m
|
|
12
|
-
[32mESM[39m [1mdist/run-interactive-ink-
|
|
13
|
-
[32mESM[39m [1mdist/chunk-
|
|
14
|
-
[32mESM[39m ⚡️ Build success in
|
|
12
|
+
[32mESM[39m [1mdist/run-interactive-ink-REIUGQ5X.js [22m[32m56.74 KB[39m
|
|
13
|
+
[32mESM[39m [1mdist/chunk-UTZB2CS7.js [22m[32m404.26 KB[39m
|
|
14
|
+
[32mESM[39m ⚡️ Build success in 65ms
|
|
15
15
|
[34mDTS[39m Build start
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 3948ms
|
|
17
17
|
[32mDTS[39m [1mdist/cli.d.ts [22m[32m20.00 B[39m
|
|
18
18
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.59 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @poncho-ai/cli
|
|
2
2
|
|
|
3
|
+
## 0.24.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`70c4cfc`](https://github.com/cesr/poncho-ai/commit/70c4cfcb8d70e8b382157a82f2dc341bf526226b) Thanks [@cesr](https://github.com/cesr)! - Improve tool approval UX: optimistic approve/deny, fix browser panel not opening after approval, and restore real-time SSE streaming for resumed runs.
|
|
8
|
+
|
|
9
|
+
- [`ab4c1cb`](https://github.com/cesr/poncho-ai/commit/ab4c1cb0729a68ba0f296fd37380b5c228abfb5b) Thanks [@cesr](https://github.com/cesr)! - Fix browser hangs during long conversations in the web UI by throttling streaming renders with requestAnimationFrame and caching markdown parse output.
|
|
10
|
+
|
|
3
11
|
## 0.24.1
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
|
@@ -866,6 +866,25 @@ var WEB_UI_STYLES = `
|
|
|
866
866
|
border-color: var(--deny-border);
|
|
867
867
|
color: var(--deny);
|
|
868
868
|
}
|
|
869
|
+
.approval-request-item.resolved {
|
|
870
|
+
opacity: 0.7;
|
|
871
|
+
}
|
|
872
|
+
.approval-resolved-status {
|
|
873
|
+
font-size: 12px;
|
|
874
|
+
font-weight: 600;
|
|
875
|
+
letter-spacing: 0.04em;
|
|
876
|
+
}
|
|
877
|
+
.approval-resolved-status code {
|
|
878
|
+
font-family: ui-monospace, "SF Mono", "Fira Code", monospace;
|
|
879
|
+
letter-spacing: 0;
|
|
880
|
+
color: var(--fg-strong);
|
|
881
|
+
}
|
|
882
|
+
.approval-resolved-status.approve {
|
|
883
|
+
color: var(--approve);
|
|
884
|
+
}
|
|
885
|
+
.approval-resolved-status.deny {
|
|
886
|
+
color: var(--deny);
|
|
887
|
+
}
|
|
869
888
|
.user-bubble {
|
|
870
889
|
background: var(--bg-elevated);
|
|
871
890
|
border: 1px solid var(--border-2);
|
|
@@ -1735,15 +1754,23 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
1735
1754
|
.replace(/"/g, """)
|
|
1736
1755
|
.replace(/'/g, "'");
|
|
1737
1756
|
|
|
1757
|
+
const _mdCache = new Map();
|
|
1738
1758
|
const renderAssistantMarkdown = (value) => {
|
|
1739
1759
|
const source = String(value || "").trim();
|
|
1740
1760
|
if (!source) return "<p></p>";
|
|
1741
1761
|
|
|
1762
|
+
const cached = _mdCache.get(source);
|
|
1763
|
+
if (cached !== undefined) return cached;
|
|
1764
|
+
|
|
1742
1765
|
try {
|
|
1743
|
-
|
|
1766
|
+
const result = marked.parse(source);
|
|
1767
|
+
_mdCache.set(source, result);
|
|
1768
|
+
if (_mdCache.size > 500) {
|
|
1769
|
+
_mdCache.delete(_mdCache.keys().next().value);
|
|
1770
|
+
}
|
|
1771
|
+
return result;
|
|
1744
1772
|
} catch (error) {
|
|
1745
1773
|
console.error("Markdown parsing error:", error);
|
|
1746
|
-
// Fallback to escaped text
|
|
1747
1774
|
return "<p>" + escapeHtml(source) + "</p>";
|
|
1748
1775
|
}
|
|
1749
1776
|
};
|
|
@@ -1834,15 +1861,26 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
1834
1861
|
const approvalId = typeof req.approvalId === "string" ? req.approvalId : "";
|
|
1835
1862
|
const tool = typeof req.tool === "string" ? req.tool : "tool";
|
|
1836
1863
|
const input = req.input != null ? req.input : {};
|
|
1864
|
+
const subagentLabel = req._subagentLabel
|
|
1865
|
+
? ' <span style="color: var(--text-3); font-size: 11px;">(from ' + escapeHtml(req._subagentLabel) + ')</span>'
|
|
1866
|
+
: "";
|
|
1867
|
+
if (req.state === "resolved") {
|
|
1868
|
+
const isApproved = req.resolvedDecision === "approve";
|
|
1869
|
+
const label = isApproved ? "Approved" : "Denied";
|
|
1870
|
+
const cls = isApproved ? "approve" : "deny";
|
|
1871
|
+
return (
|
|
1872
|
+
'<div class="approval-request-item resolved">' +
|
|
1873
|
+
'<div class="approval-resolved-status ' + cls + '">' + label + ': <code>' +
|
|
1874
|
+
escapeHtml(tool) + "</code>" + subagentLabel + "</div>" +
|
|
1875
|
+
"</div>"
|
|
1876
|
+
);
|
|
1877
|
+
}
|
|
1837
1878
|
const submitting = req.state === "submitting";
|
|
1838
1879
|
const approveLabel = submitting && req.pendingDecision === "approve" ? "Approving..." : "Approve";
|
|
1839
1880
|
const denyLabel = submitting && req.pendingDecision === "deny" ? "Denying..." : "Deny";
|
|
1840
1881
|
const errorHtml = req._error
|
|
1841
1882
|
? '<div style="color: var(--deny); font-size: 11px; margin-top: 4px;">Submit failed: ' + escapeHtml(req._error) + "</div>"
|
|
1842
1883
|
: "";
|
|
1843
|
-
const subagentLabel = req._subagentLabel
|
|
1844
|
-
? ' <span style="color: var(--text-3); font-size: 11px;">(from ' + escapeHtml(req._subagentLabel) + ')</span>'
|
|
1845
|
-
: "";
|
|
1846
1884
|
return (
|
|
1847
1885
|
'<div class="approval-request-item">' +
|
|
1848
1886
|
'<div class="approval-requests-label">Approval required: <code>' +
|
|
@@ -1870,10 +1908,11 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
1870
1908
|
);
|
|
1871
1909
|
})
|
|
1872
1910
|
.join("");
|
|
1873
|
-
const
|
|
1911
|
+
const actionableCount = requests.filter((r) => r.state !== "resolved").length;
|
|
1912
|
+
const batchButtons = actionableCount > 1
|
|
1874
1913
|
? '<div class="approval-batch-actions">' +
|
|
1875
|
-
'<button class="approval-batch-btn approve" data-approval-batch="approve">Approve all (' +
|
|
1876
|
-
'<button class="approval-batch-btn deny" data-approval-batch="deny">Deny all (' +
|
|
1914
|
+
'<button class="approval-batch-btn approve" data-approval-batch="approve">Approve all (' + actionableCount + ')</button>' +
|
|
1915
|
+
'<button class="approval-batch-btn deny" data-approval-batch="deny">Deny all (' + actionableCount + ')</button>' +
|
|
1877
1916
|
"</div>"
|
|
1878
1917
|
: "";
|
|
1879
1918
|
return (
|
|
@@ -2002,6 +2041,14 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2002
2041
|
return false;
|
|
2003
2042
|
};
|
|
2004
2043
|
|
|
2044
|
+
const clearResolvedApprovals = (message) => {
|
|
2045
|
+
if (Array.isArray(message._pendingApprovals)) {
|
|
2046
|
+
message._pendingApprovals = message._pendingApprovals.filter(
|
|
2047
|
+
(req) => req.state !== "resolved",
|
|
2048
|
+
);
|
|
2049
|
+
}
|
|
2050
|
+
};
|
|
2051
|
+
|
|
2005
2052
|
const toUiPendingApprovals = (pendingApprovals) => {
|
|
2006
2053
|
if (!Array.isArray(pendingApprovals)) {
|
|
2007
2054
|
return [];
|
|
@@ -2394,12 +2441,16 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2394
2441
|
);
|
|
2395
2442
|
}
|
|
2396
2443
|
});
|
|
2397
|
-
// While streaming, show current tools
|
|
2398
|
-
if (isStreaming && i === messages.length - 1
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2444
|
+
// While streaming, show current tools and/or pending approvals
|
|
2445
|
+
if (isStreaming && i === messages.length - 1) {
|
|
2446
|
+
const hasCurrentTools = m._currentTools && m._currentTools.length > 0;
|
|
2447
|
+
const hasStreamApprovals = Array.isArray(m._pendingApprovals) && m._pendingApprovals.length > 0;
|
|
2448
|
+
if (hasCurrentTools || hasStreamApprovals) {
|
|
2449
|
+
content.insertAdjacentHTML(
|
|
2450
|
+
"beforeend",
|
|
2451
|
+
renderToolActivity(m._currentTools || [], m._pendingApprovals || [], m._toolImages || []),
|
|
2452
|
+
);
|
|
2453
|
+
}
|
|
2403
2454
|
}
|
|
2404
2455
|
// When reloading with unresolved approvals, show them even when not streaming
|
|
2405
2456
|
if (!isStreaming && pendingApprovals.length > 0 && lastToolsSectionIndex < 0) {
|
|
@@ -2675,6 +2726,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2675
2726
|
renderMessages(state.activeMessages, payload.hasActiveRun);
|
|
2676
2727
|
}
|
|
2677
2728
|
if (payload.hasActiveRun) {
|
|
2729
|
+
if (window._connectBrowserStream) window._connectBrowserStream();
|
|
2678
2730
|
setTimeout(poll, 2000);
|
|
2679
2731
|
} else {
|
|
2680
2732
|
setStreaming(false);
|
|
@@ -2692,12 +2744,24 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2692
2744
|
const liveOnly = options && options.liveOnly;
|
|
2693
2745
|
return new Promise((resolve) => {
|
|
2694
2746
|
const localMessages = state.activeMessages || [];
|
|
2747
|
+
let _rafId = 0;
|
|
2695
2748
|
const renderIfActiveConversation = (streaming) => {
|
|
2696
2749
|
if (state.activeConversationId !== conversationId) {
|
|
2697
2750
|
return;
|
|
2698
2751
|
}
|
|
2699
2752
|
state.activeMessages = localMessages;
|
|
2700
|
-
|
|
2753
|
+
if (!streaming) {
|
|
2754
|
+
if (_rafId) { cancelAnimationFrame(_rafId); _rafId = 0; }
|
|
2755
|
+
renderMessages(localMessages, false);
|
|
2756
|
+
return;
|
|
2757
|
+
}
|
|
2758
|
+
if (!_rafId) {
|
|
2759
|
+
_rafId = requestAnimationFrame(() => {
|
|
2760
|
+
_rafId = 0;
|
|
2761
|
+
if (state.activeConversationId !== conversationId) return;
|
|
2762
|
+
renderMessages(localMessages, true);
|
|
2763
|
+
});
|
|
2764
|
+
}
|
|
2701
2765
|
};
|
|
2702
2766
|
let assistantMessage = localMessages[localMessages.length - 1];
|
|
2703
2767
|
if (!assistantMessage || assistantMessage.role !== "assistant") {
|
|
@@ -2766,6 +2830,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2766
2830
|
}
|
|
2767
2831
|
if (eventName === "model:chunk") {
|
|
2768
2832
|
const chunk = String(payload.content || "");
|
|
2833
|
+
if (chunk.length > 0) clearResolvedApprovals(assistantMessage);
|
|
2769
2834
|
if (assistantMessage._currentTools.length > 0 && chunk.length > 0) {
|
|
2770
2835
|
assistantMessage._sections.push({
|
|
2771
2836
|
type: "tools",
|
|
@@ -2807,6 +2872,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2807
2872
|
renderIfActiveConversation(true);
|
|
2808
2873
|
}
|
|
2809
2874
|
if (eventName === "tool:started") {
|
|
2875
|
+
clearResolvedApprovals(assistantMessage);
|
|
2810
2876
|
const toolName = payload.tool || "tool";
|
|
2811
2877
|
removeActiveActivityForTool(assistantMessage, toolName);
|
|
2812
2878
|
const startedActivity = addActiveActivityFromToolStart(
|
|
@@ -2961,7 +3027,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2961
3027
|
typeof payload.approvalId === "string" ? payload.approvalId : "";
|
|
2962
3028
|
if (approvalId && Array.isArray(assistantMessage._pendingApprovals)) {
|
|
2963
3029
|
assistantMessage._pendingApprovals = assistantMessage._pendingApprovals.filter(
|
|
2964
|
-
(req) => req.approvalId !== approvalId,
|
|
3030
|
+
(req) => req.approvalId !== approvalId || req.state === "resolved",
|
|
2965
3031
|
);
|
|
2966
3032
|
}
|
|
2967
3033
|
renderIfActiveConversation(true);
|
|
@@ -2974,7 +3040,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2974
3040
|
typeof payload.approvalId === "string" ? payload.approvalId : "";
|
|
2975
3041
|
if (approvalId && Array.isArray(assistantMessage._pendingApprovals)) {
|
|
2976
3042
|
assistantMessage._pendingApprovals = assistantMessage._pendingApprovals.filter(
|
|
2977
|
-
(req) => req.approvalId !== approvalId,
|
|
3043
|
+
(req) => req.approvalId !== approvalId || req.state === "resolved",
|
|
2978
3044
|
);
|
|
2979
3045
|
}
|
|
2980
3046
|
renderIfActiveConversation(true);
|
|
@@ -3511,12 +3577,24 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
3511
3577
|
}
|
|
3512
3578
|
state.activeStreamConversationId = conversationId;
|
|
3513
3579
|
const streamConversationId = conversationId;
|
|
3580
|
+
let _rafId = 0;
|
|
3514
3581
|
const renderIfActiveConversation = (streaming) => {
|
|
3515
3582
|
if (state.activeConversationId !== streamConversationId) {
|
|
3516
3583
|
return;
|
|
3517
3584
|
}
|
|
3518
3585
|
state.activeMessages = localMessages;
|
|
3519
|
-
|
|
3586
|
+
if (!streaming) {
|
|
3587
|
+
if (_rafId) { cancelAnimationFrame(_rafId); _rafId = 0; }
|
|
3588
|
+
renderMessages(localMessages, false);
|
|
3589
|
+
return;
|
|
3590
|
+
}
|
|
3591
|
+
if (!_rafId) {
|
|
3592
|
+
_rafId = requestAnimationFrame(() => {
|
|
3593
|
+
_rafId = 0;
|
|
3594
|
+
if (state.activeConversationId !== streamConversationId) return;
|
|
3595
|
+
renderMessages(localMessages, true);
|
|
3596
|
+
});
|
|
3597
|
+
}
|
|
3520
3598
|
};
|
|
3521
3599
|
const finalizeAssistantMessage = () => {
|
|
3522
3600
|
assistantMessage._activeActivities = [];
|
|
@@ -3577,7 +3655,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
3577
3655
|
try {
|
|
3578
3656
|
if (eventName === "model:chunk") {
|
|
3579
3657
|
const chunk = String(payload.content || "");
|
|
3580
|
-
|
|
3658
|
+
if (chunk.length > 0) clearResolvedApprovals(assistantMessage);
|
|
3581
3659
|
if (assistantMessage._currentTools.length > 0 && chunk.length > 0) {
|
|
3582
3660
|
assistantMessage._sections.push({ type: "tools", content: assistantMessage._currentTools });
|
|
3583
3661
|
assistantMessage._currentTools = [];
|
|
@@ -3621,6 +3699,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
3621
3699
|
renderIfActiveConversation(true);
|
|
3622
3700
|
}
|
|
3623
3701
|
if (eventName === "tool:started") {
|
|
3702
|
+
clearResolvedApprovals(assistantMessage);
|
|
3624
3703
|
const toolName = payload.tool || "tool";
|
|
3625
3704
|
removeActiveActivityForTool(assistantMessage, toolName);
|
|
3626
3705
|
const startedActivity = addActiveActivityFromToolStart(
|
|
@@ -3775,7 +3854,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
3775
3854
|
typeof payload.approvalId === "string" ? payload.approvalId : "";
|
|
3776
3855
|
if (approvalId && Array.isArray(assistantMessage._pendingApprovals)) {
|
|
3777
3856
|
assistantMessage._pendingApprovals = assistantMessage._pendingApprovals.filter(
|
|
3778
|
-
(req) => req.approvalId !== approvalId,
|
|
3857
|
+
(req) => req.approvalId !== approvalId || req.state === "resolved",
|
|
3779
3858
|
);
|
|
3780
3859
|
}
|
|
3781
3860
|
renderIfActiveConversation(true);
|
|
@@ -3790,7 +3869,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
3790
3869
|
typeof payload.approvalId === "string" ? payload.approvalId : "";
|
|
3791
3870
|
if (approvalId && Array.isArray(assistantMessage._pendingApprovals)) {
|
|
3792
3871
|
assistantMessage._pendingApprovals = assistantMessage._pendingApprovals.filter(
|
|
3793
|
-
(req) => req.approvalId !== approvalId,
|
|
3872
|
+
(req) => req.approvalId !== approvalId || req.state === "resolved",
|
|
3794
3873
|
);
|
|
3795
3874
|
}
|
|
3796
3875
|
renderIfActiveConversation(true);
|
|
@@ -4119,21 +4198,17 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
4119
4198
|
openLightbox(img.src);
|
|
4120
4199
|
});
|
|
4121
4200
|
|
|
4122
|
-
const submitApproval =
|
|
4123
|
-
const wasStreaming = opts && opts.wasStreaming;
|
|
4201
|
+
const submitApproval = (approvalId, decision) => {
|
|
4124
4202
|
state.approvalRequestsInFlight[approvalId] = true;
|
|
4125
4203
|
updatePendingApproval(approvalId, (request) => ({
|
|
4126
4204
|
...request,
|
|
4127
|
-
state: "
|
|
4128
|
-
|
|
4205
|
+
state: "resolved",
|
|
4206
|
+
resolvedDecision: decision,
|
|
4129
4207
|
}));
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
});
|
|
4135
|
-
updatePendingApproval(approvalId, () => null);
|
|
4136
|
-
} catch (error) {
|
|
4208
|
+
api("/api/approvals/" + encodeURIComponent(approvalId), {
|
|
4209
|
+
method: "POST",
|
|
4210
|
+
body: JSON.stringify({ approved: decision === "approve" }),
|
|
4211
|
+
}).catch((error) => {
|
|
4137
4212
|
const isStale = error && error.payload && error.payload.code === "APPROVAL_NOT_FOUND";
|
|
4138
4213
|
if (isStale) {
|
|
4139
4214
|
updatePendingApproval(approvalId, () => null);
|
|
@@ -4143,12 +4218,14 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
4143
4218
|
...request,
|
|
4144
4219
|
state: "pending",
|
|
4145
4220
|
pendingDecision: null,
|
|
4221
|
+
resolvedDecision: null,
|
|
4146
4222
|
_error: errMsg,
|
|
4147
4223
|
}));
|
|
4148
4224
|
}
|
|
4149
|
-
|
|
4225
|
+
renderMessages(state.activeMessages, state.isStreaming);
|
|
4226
|
+
}).finally(() => {
|
|
4150
4227
|
delete state.approvalRequestsInFlight[approvalId];
|
|
4151
|
-
}
|
|
4228
|
+
});
|
|
4152
4229
|
};
|
|
4153
4230
|
|
|
4154
4231
|
elements.messages.addEventListener("click", async (event) => {
|
|
@@ -4167,7 +4244,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
4167
4244
|
for (const m of messages) {
|
|
4168
4245
|
if (Array.isArray(m._pendingApprovals)) {
|
|
4169
4246
|
for (const req of m._pendingApprovals) {
|
|
4170
|
-
if (req.approvalId && req.state !== "
|
|
4247
|
+
if (req.approvalId && req.state !== "resolved" && !state.approvalRequestsInFlight[req.approvalId]) {
|
|
4171
4248
|
pending.push(req.approvalId);
|
|
4172
4249
|
}
|
|
4173
4250
|
}
|
|
@@ -4176,8 +4253,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
4176
4253
|
if (pending.length === 0) return;
|
|
4177
4254
|
const wasStreaming = state.isStreaming;
|
|
4178
4255
|
if (!wasStreaming) setStreaming(true);
|
|
4179
|
-
|
|
4180
|
-
await Promise.all(pending.map((aid) => submitApproval(aid, decision, { wasStreaming })));
|
|
4256
|
+
pending.forEach((aid) => submitApproval(aid, decision));
|
|
4181
4257
|
renderMessages(state.activeMessages, state.isStreaming);
|
|
4182
4258
|
loadConversations();
|
|
4183
4259
|
if (!wasStreaming && state.activeConversationId) {
|
|
@@ -4207,8 +4283,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
4207
4283
|
if (!wasStreaming) {
|
|
4208
4284
|
setStreaming(true);
|
|
4209
4285
|
}
|
|
4210
|
-
|
|
4211
|
-
await submitApproval(approvalId, decision, { wasStreaming });
|
|
4286
|
+
submitApproval(approvalId, decision);
|
|
4212
4287
|
renderMessages(state.activeMessages, state.isStreaming);
|
|
4213
4288
|
loadConversations();
|
|
4214
4289
|
if (!wasStreaming && state.activeConversationId) {
|
|
@@ -8931,6 +9006,17 @@ data: ${JSON.stringify(data)}
|
|
|
8931
9006
|
foundConversation.runStatus = "running";
|
|
8932
9007
|
await conversationStore.update(foundConversation);
|
|
8933
9008
|
const checkpointRef = allApprovals[0];
|
|
9009
|
+
const prevStream = conversationEventStreams.get(conversationId);
|
|
9010
|
+
if (prevStream) {
|
|
9011
|
+
prevStream.finished = false;
|
|
9012
|
+
prevStream.buffer = [];
|
|
9013
|
+
} else {
|
|
9014
|
+
conversationEventStreams.set(conversationId, {
|
|
9015
|
+
buffer: [],
|
|
9016
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
9017
|
+
finished: false
|
|
9018
|
+
});
|
|
9019
|
+
}
|
|
8934
9020
|
const resumeWork = (async () => {
|
|
8935
9021
|
try {
|
|
8936
9022
|
const toolContext = {
|
|
@@ -8966,6 +9052,14 @@ data: ${JSON.stringify(data)}
|
|
|
8966
9052
|
error: r.error
|
|
8967
9053
|
})));
|
|
8968
9054
|
}
|
|
9055
|
+
const bs = harness.browserSession;
|
|
9056
|
+
if (bs?.isActiveFor(conversationId)) {
|
|
9057
|
+
broadcastRawSse(conversationId, "browser:status", {
|
|
9058
|
+
active: true,
|
|
9059
|
+
url: bs.getUrl(conversationId) ?? null,
|
|
9060
|
+
interactionAllowed: true
|
|
9061
|
+
});
|
|
9062
|
+
}
|
|
8969
9063
|
await resumeRunFromCheckpoint(
|
|
8970
9064
|
conversationId,
|
|
8971
9065
|
foundConversation,
|
|
@@ -10094,7 +10188,7 @@ var runInteractive = async (workingDir, params) => {
|
|
|
10094
10188
|
await harness.initialize();
|
|
10095
10189
|
const identity = await ensureAgentIdentity2(workingDir);
|
|
10096
10190
|
try {
|
|
10097
|
-
const { runInteractiveInk } = await import("./run-interactive-ink-
|
|
10191
|
+
const { runInteractiveInk } = await import("./run-interactive-ink-REIUGQ5X.js");
|
|
10098
10192
|
await runInteractiveInk({
|
|
10099
10193
|
harness,
|
|
10100
10194
|
params,
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poncho-ai/cli",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.2",
|
|
4
4
|
"description": "CLI for building and deploying AI agents",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"react": "^19.2.4",
|
|
28
28
|
"react-devtools-core": "^6.1.5",
|
|
29
29
|
"yaml": "^2.8.1",
|
|
30
|
+
"@poncho-ai/harness": "0.22.1",
|
|
30
31
|
"@poncho-ai/messaging": "0.5.1",
|
|
31
|
-
"@poncho-ai/sdk": "1.5.0"
|
|
32
|
-
"@poncho-ai/harness": "0.22.1"
|
|
32
|
+
"@poncho-ai/sdk": "1.5.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/busboy": "^1.5.4",
|
package/src/index.ts
CHANGED
|
@@ -3103,6 +3103,20 @@ export const createRequestHandler = async (options?: {
|
|
|
3103
3103
|
// Use the first approval as the checkpoint reference (all share the same checkpoint data)
|
|
3104
3104
|
const checkpointRef = allApprovals[0]!;
|
|
3105
3105
|
|
|
3106
|
+
// Reset the event stream so new SSE subscribers can connect to the
|
|
3107
|
+
// resumed run (the previous run's stream was marked finished).
|
|
3108
|
+
const prevStream = conversationEventStreams.get(conversationId);
|
|
3109
|
+
if (prevStream) {
|
|
3110
|
+
prevStream.finished = false;
|
|
3111
|
+
prevStream.buffer = [];
|
|
3112
|
+
} else {
|
|
3113
|
+
conversationEventStreams.set(conversationId, {
|
|
3114
|
+
buffer: [],
|
|
3115
|
+
subscribers: new Set(),
|
|
3116
|
+
finished: false,
|
|
3117
|
+
});
|
|
3118
|
+
}
|
|
3119
|
+
|
|
3106
3120
|
const resumeWork = (async () => {
|
|
3107
3121
|
try {
|
|
3108
3122
|
const toolContext = {
|
|
@@ -3145,6 +3159,16 @@ export const createRequestHandler = async (options?: {
|
|
|
3145
3159
|
})));
|
|
3146
3160
|
}
|
|
3147
3161
|
|
|
3162
|
+
// If approved tools activated the browser, notify connected clients
|
|
3163
|
+
const bs = harness.browserSession as BrowserSessionForStatus | undefined;
|
|
3164
|
+
if (bs?.isActiveFor(conversationId)) {
|
|
3165
|
+
broadcastRawSse(conversationId, "browser:status", {
|
|
3166
|
+
active: true,
|
|
3167
|
+
url: bs.getUrl(conversationId) ?? null,
|
|
3168
|
+
interactionAllowed: true,
|
|
3169
|
+
});
|
|
3170
|
+
}
|
|
3171
|
+
|
|
3148
3172
|
await resumeRunFromCheckpoint(
|
|
3149
3173
|
conversationId,
|
|
3150
3174
|
foundConversation!,
|
package/src/web-ui-client.ts
CHANGED
|
@@ -151,15 +151,23 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
151
151
|
.replace(/"/g, """)
|
|
152
152
|
.replace(/'/g, "'");
|
|
153
153
|
|
|
154
|
+
const _mdCache = new Map();
|
|
154
155
|
const renderAssistantMarkdown = (value) => {
|
|
155
156
|
const source = String(value || "").trim();
|
|
156
157
|
if (!source) return "<p></p>";
|
|
157
158
|
|
|
159
|
+
const cached = _mdCache.get(source);
|
|
160
|
+
if (cached !== undefined) return cached;
|
|
161
|
+
|
|
158
162
|
try {
|
|
159
|
-
|
|
163
|
+
const result = marked.parse(source);
|
|
164
|
+
_mdCache.set(source, result);
|
|
165
|
+
if (_mdCache.size > 500) {
|
|
166
|
+
_mdCache.delete(_mdCache.keys().next().value);
|
|
167
|
+
}
|
|
168
|
+
return result;
|
|
160
169
|
} catch (error) {
|
|
161
170
|
console.error("Markdown parsing error:", error);
|
|
162
|
-
// Fallback to escaped text
|
|
163
171
|
return "<p>" + escapeHtml(source) + "</p>";
|
|
164
172
|
}
|
|
165
173
|
};
|
|
@@ -250,15 +258,26 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
250
258
|
const approvalId = typeof req.approvalId === "string" ? req.approvalId : "";
|
|
251
259
|
const tool = typeof req.tool === "string" ? req.tool : "tool";
|
|
252
260
|
const input = req.input != null ? req.input : {};
|
|
261
|
+
const subagentLabel = req._subagentLabel
|
|
262
|
+
? ' <span style="color: var(--text-3); font-size: 11px;">(from ' + escapeHtml(req._subagentLabel) + ')</span>'
|
|
263
|
+
: "";
|
|
264
|
+
if (req.state === "resolved") {
|
|
265
|
+
const isApproved = req.resolvedDecision === "approve";
|
|
266
|
+
const label = isApproved ? "Approved" : "Denied";
|
|
267
|
+
const cls = isApproved ? "approve" : "deny";
|
|
268
|
+
return (
|
|
269
|
+
'<div class="approval-request-item resolved">' +
|
|
270
|
+
'<div class="approval-resolved-status ' + cls + '">' + label + ': <code>' +
|
|
271
|
+
escapeHtml(tool) + "</code>" + subagentLabel + "</div>" +
|
|
272
|
+
"</div>"
|
|
273
|
+
);
|
|
274
|
+
}
|
|
253
275
|
const submitting = req.state === "submitting";
|
|
254
276
|
const approveLabel = submitting && req.pendingDecision === "approve" ? "Approving..." : "Approve";
|
|
255
277
|
const denyLabel = submitting && req.pendingDecision === "deny" ? "Denying..." : "Deny";
|
|
256
278
|
const errorHtml = req._error
|
|
257
279
|
? '<div style="color: var(--deny); font-size: 11px; margin-top: 4px;">Submit failed: ' + escapeHtml(req._error) + "</div>"
|
|
258
280
|
: "";
|
|
259
|
-
const subagentLabel = req._subagentLabel
|
|
260
|
-
? ' <span style="color: var(--text-3); font-size: 11px;">(from ' + escapeHtml(req._subagentLabel) + ')</span>'
|
|
261
|
-
: "";
|
|
262
281
|
return (
|
|
263
282
|
'<div class="approval-request-item">' +
|
|
264
283
|
'<div class="approval-requests-label">Approval required: <code>' +
|
|
@@ -286,10 +305,11 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
286
305
|
);
|
|
287
306
|
})
|
|
288
307
|
.join("");
|
|
289
|
-
const
|
|
308
|
+
const actionableCount = requests.filter((r) => r.state !== "resolved").length;
|
|
309
|
+
const batchButtons = actionableCount > 1
|
|
290
310
|
? '<div class="approval-batch-actions">' +
|
|
291
|
-
'<button class="approval-batch-btn approve" data-approval-batch="approve">Approve all (' +
|
|
292
|
-
'<button class="approval-batch-btn deny" data-approval-batch="deny">Deny all (' +
|
|
311
|
+
'<button class="approval-batch-btn approve" data-approval-batch="approve">Approve all (' + actionableCount + ')</button>' +
|
|
312
|
+
'<button class="approval-batch-btn deny" data-approval-batch="deny">Deny all (' + actionableCount + ')</button>' +
|
|
293
313
|
"</div>"
|
|
294
314
|
: "";
|
|
295
315
|
return (
|
|
@@ -418,6 +438,14 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
418
438
|
return false;
|
|
419
439
|
};
|
|
420
440
|
|
|
441
|
+
const clearResolvedApprovals = (message) => {
|
|
442
|
+
if (Array.isArray(message._pendingApprovals)) {
|
|
443
|
+
message._pendingApprovals = message._pendingApprovals.filter(
|
|
444
|
+
(req) => req.state !== "resolved",
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
|
|
421
449
|
const toUiPendingApprovals = (pendingApprovals) => {
|
|
422
450
|
if (!Array.isArray(pendingApprovals)) {
|
|
423
451
|
return [];
|
|
@@ -810,12 +838,16 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
810
838
|
);
|
|
811
839
|
}
|
|
812
840
|
});
|
|
813
|
-
// While streaming, show current tools
|
|
814
|
-
if (isStreaming && i === messages.length - 1
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
841
|
+
// While streaming, show current tools and/or pending approvals
|
|
842
|
+
if (isStreaming && i === messages.length - 1) {
|
|
843
|
+
const hasCurrentTools = m._currentTools && m._currentTools.length > 0;
|
|
844
|
+
const hasStreamApprovals = Array.isArray(m._pendingApprovals) && m._pendingApprovals.length > 0;
|
|
845
|
+
if (hasCurrentTools || hasStreamApprovals) {
|
|
846
|
+
content.insertAdjacentHTML(
|
|
847
|
+
"beforeend",
|
|
848
|
+
renderToolActivity(m._currentTools || [], m._pendingApprovals || [], m._toolImages || []),
|
|
849
|
+
);
|
|
850
|
+
}
|
|
819
851
|
}
|
|
820
852
|
// When reloading with unresolved approvals, show them even when not streaming
|
|
821
853
|
if (!isStreaming && pendingApprovals.length > 0 && lastToolsSectionIndex < 0) {
|
|
@@ -1091,6 +1123,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
1091
1123
|
renderMessages(state.activeMessages, payload.hasActiveRun);
|
|
1092
1124
|
}
|
|
1093
1125
|
if (payload.hasActiveRun) {
|
|
1126
|
+
if (window._connectBrowserStream) window._connectBrowserStream();
|
|
1094
1127
|
setTimeout(poll, 2000);
|
|
1095
1128
|
} else {
|
|
1096
1129
|
setStreaming(false);
|
|
@@ -1108,12 +1141,24 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
1108
1141
|
const liveOnly = options && options.liveOnly;
|
|
1109
1142
|
return new Promise((resolve) => {
|
|
1110
1143
|
const localMessages = state.activeMessages || [];
|
|
1144
|
+
let _rafId = 0;
|
|
1111
1145
|
const renderIfActiveConversation = (streaming) => {
|
|
1112
1146
|
if (state.activeConversationId !== conversationId) {
|
|
1113
1147
|
return;
|
|
1114
1148
|
}
|
|
1115
1149
|
state.activeMessages = localMessages;
|
|
1116
|
-
|
|
1150
|
+
if (!streaming) {
|
|
1151
|
+
if (_rafId) { cancelAnimationFrame(_rafId); _rafId = 0; }
|
|
1152
|
+
renderMessages(localMessages, false);
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
if (!_rafId) {
|
|
1156
|
+
_rafId = requestAnimationFrame(() => {
|
|
1157
|
+
_rafId = 0;
|
|
1158
|
+
if (state.activeConversationId !== conversationId) return;
|
|
1159
|
+
renderMessages(localMessages, true);
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1117
1162
|
};
|
|
1118
1163
|
let assistantMessage = localMessages[localMessages.length - 1];
|
|
1119
1164
|
if (!assistantMessage || assistantMessage.role !== "assistant") {
|
|
@@ -1182,6 +1227,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
1182
1227
|
}
|
|
1183
1228
|
if (eventName === "model:chunk") {
|
|
1184
1229
|
const chunk = String(payload.content || "");
|
|
1230
|
+
if (chunk.length > 0) clearResolvedApprovals(assistantMessage);
|
|
1185
1231
|
if (assistantMessage._currentTools.length > 0 && chunk.length > 0) {
|
|
1186
1232
|
assistantMessage._sections.push({
|
|
1187
1233
|
type: "tools",
|
|
@@ -1223,6 +1269,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
1223
1269
|
renderIfActiveConversation(true);
|
|
1224
1270
|
}
|
|
1225
1271
|
if (eventName === "tool:started") {
|
|
1272
|
+
clearResolvedApprovals(assistantMessage);
|
|
1226
1273
|
const toolName = payload.tool || "tool";
|
|
1227
1274
|
removeActiveActivityForTool(assistantMessage, toolName);
|
|
1228
1275
|
const startedActivity = addActiveActivityFromToolStart(
|
|
@@ -1377,7 +1424,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
1377
1424
|
typeof payload.approvalId === "string" ? payload.approvalId : "";
|
|
1378
1425
|
if (approvalId && Array.isArray(assistantMessage._pendingApprovals)) {
|
|
1379
1426
|
assistantMessage._pendingApprovals = assistantMessage._pendingApprovals.filter(
|
|
1380
|
-
(req) => req.approvalId !== approvalId,
|
|
1427
|
+
(req) => req.approvalId !== approvalId || req.state === "resolved",
|
|
1381
1428
|
);
|
|
1382
1429
|
}
|
|
1383
1430
|
renderIfActiveConversation(true);
|
|
@@ -1390,7 +1437,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
1390
1437
|
typeof payload.approvalId === "string" ? payload.approvalId : "";
|
|
1391
1438
|
if (approvalId && Array.isArray(assistantMessage._pendingApprovals)) {
|
|
1392
1439
|
assistantMessage._pendingApprovals = assistantMessage._pendingApprovals.filter(
|
|
1393
|
-
(req) => req.approvalId !== approvalId,
|
|
1440
|
+
(req) => req.approvalId !== approvalId || req.state === "resolved",
|
|
1394
1441
|
);
|
|
1395
1442
|
}
|
|
1396
1443
|
renderIfActiveConversation(true);
|
|
@@ -1927,12 +1974,24 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
1927
1974
|
}
|
|
1928
1975
|
state.activeStreamConversationId = conversationId;
|
|
1929
1976
|
const streamConversationId = conversationId;
|
|
1977
|
+
let _rafId = 0;
|
|
1930
1978
|
const renderIfActiveConversation = (streaming) => {
|
|
1931
1979
|
if (state.activeConversationId !== streamConversationId) {
|
|
1932
1980
|
return;
|
|
1933
1981
|
}
|
|
1934
1982
|
state.activeMessages = localMessages;
|
|
1935
|
-
|
|
1983
|
+
if (!streaming) {
|
|
1984
|
+
if (_rafId) { cancelAnimationFrame(_rafId); _rafId = 0; }
|
|
1985
|
+
renderMessages(localMessages, false);
|
|
1986
|
+
return;
|
|
1987
|
+
}
|
|
1988
|
+
if (!_rafId) {
|
|
1989
|
+
_rafId = requestAnimationFrame(() => {
|
|
1990
|
+
_rafId = 0;
|
|
1991
|
+
if (state.activeConversationId !== streamConversationId) return;
|
|
1992
|
+
renderMessages(localMessages, true);
|
|
1993
|
+
});
|
|
1994
|
+
}
|
|
1936
1995
|
};
|
|
1937
1996
|
const finalizeAssistantMessage = () => {
|
|
1938
1997
|
assistantMessage._activeActivities = [];
|
|
@@ -1993,7 +2052,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
1993
2052
|
try {
|
|
1994
2053
|
if (eventName === "model:chunk") {
|
|
1995
2054
|
const chunk = String(payload.content || "");
|
|
1996
|
-
|
|
2055
|
+
if (chunk.length > 0) clearResolvedApprovals(assistantMessage);
|
|
1997
2056
|
if (assistantMessage._currentTools.length > 0 && chunk.length > 0) {
|
|
1998
2057
|
assistantMessage._sections.push({ type: "tools", content: assistantMessage._currentTools });
|
|
1999
2058
|
assistantMessage._currentTools = [];
|
|
@@ -2037,6 +2096,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
2037
2096
|
renderIfActiveConversation(true);
|
|
2038
2097
|
}
|
|
2039
2098
|
if (eventName === "tool:started") {
|
|
2099
|
+
clearResolvedApprovals(assistantMessage);
|
|
2040
2100
|
const toolName = payload.tool || "tool";
|
|
2041
2101
|
removeActiveActivityForTool(assistantMessage, toolName);
|
|
2042
2102
|
const startedActivity = addActiveActivityFromToolStart(
|
|
@@ -2191,7 +2251,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
2191
2251
|
typeof payload.approvalId === "string" ? payload.approvalId : "";
|
|
2192
2252
|
if (approvalId && Array.isArray(assistantMessage._pendingApprovals)) {
|
|
2193
2253
|
assistantMessage._pendingApprovals = assistantMessage._pendingApprovals.filter(
|
|
2194
|
-
(req) => req.approvalId !== approvalId,
|
|
2254
|
+
(req) => req.approvalId !== approvalId || req.state === "resolved",
|
|
2195
2255
|
);
|
|
2196
2256
|
}
|
|
2197
2257
|
renderIfActiveConversation(true);
|
|
@@ -2206,7 +2266,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
2206
2266
|
typeof payload.approvalId === "string" ? payload.approvalId : "";
|
|
2207
2267
|
if (approvalId && Array.isArray(assistantMessage._pendingApprovals)) {
|
|
2208
2268
|
assistantMessage._pendingApprovals = assistantMessage._pendingApprovals.filter(
|
|
2209
|
-
(req) => req.approvalId !== approvalId,
|
|
2269
|
+
(req) => req.approvalId !== approvalId || req.state === "resolved",
|
|
2210
2270
|
);
|
|
2211
2271
|
}
|
|
2212
2272
|
renderIfActiveConversation(true);
|
|
@@ -2535,21 +2595,17 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
2535
2595
|
openLightbox(img.src);
|
|
2536
2596
|
});
|
|
2537
2597
|
|
|
2538
|
-
const submitApproval =
|
|
2539
|
-
const wasStreaming = opts && opts.wasStreaming;
|
|
2598
|
+
const submitApproval = (approvalId, decision) => {
|
|
2540
2599
|
state.approvalRequestsInFlight[approvalId] = true;
|
|
2541
2600
|
updatePendingApproval(approvalId, (request) => ({
|
|
2542
2601
|
...request,
|
|
2543
|
-
state: "
|
|
2544
|
-
|
|
2602
|
+
state: "resolved",
|
|
2603
|
+
resolvedDecision: decision,
|
|
2545
2604
|
}));
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
});
|
|
2551
|
-
updatePendingApproval(approvalId, () => null);
|
|
2552
|
-
} catch (error) {
|
|
2605
|
+
api("/api/approvals/" + encodeURIComponent(approvalId), {
|
|
2606
|
+
method: "POST",
|
|
2607
|
+
body: JSON.stringify({ approved: decision === "approve" }),
|
|
2608
|
+
}).catch((error) => {
|
|
2553
2609
|
const isStale = error && error.payload && error.payload.code === "APPROVAL_NOT_FOUND";
|
|
2554
2610
|
if (isStale) {
|
|
2555
2611
|
updatePendingApproval(approvalId, () => null);
|
|
@@ -2559,12 +2615,14 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
2559
2615
|
...request,
|
|
2560
2616
|
state: "pending",
|
|
2561
2617
|
pendingDecision: null,
|
|
2618
|
+
resolvedDecision: null,
|
|
2562
2619
|
_error: errMsg,
|
|
2563
2620
|
}));
|
|
2564
2621
|
}
|
|
2565
|
-
|
|
2622
|
+
renderMessages(state.activeMessages, state.isStreaming);
|
|
2623
|
+
}).finally(() => {
|
|
2566
2624
|
delete state.approvalRequestsInFlight[approvalId];
|
|
2567
|
-
}
|
|
2625
|
+
});
|
|
2568
2626
|
};
|
|
2569
2627
|
|
|
2570
2628
|
elements.messages.addEventListener("click", async (event) => {
|
|
@@ -2583,7 +2641,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
2583
2641
|
for (const m of messages) {
|
|
2584
2642
|
if (Array.isArray(m._pendingApprovals)) {
|
|
2585
2643
|
for (const req of m._pendingApprovals) {
|
|
2586
|
-
if (req.approvalId && req.state !== "
|
|
2644
|
+
if (req.approvalId && req.state !== "resolved" && !state.approvalRequestsInFlight[req.approvalId]) {
|
|
2587
2645
|
pending.push(req.approvalId);
|
|
2588
2646
|
}
|
|
2589
2647
|
}
|
|
@@ -2592,8 +2650,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
2592
2650
|
if (pending.length === 0) return;
|
|
2593
2651
|
const wasStreaming = state.isStreaming;
|
|
2594
2652
|
if (!wasStreaming) setStreaming(true);
|
|
2595
|
-
|
|
2596
|
-
await Promise.all(pending.map((aid) => submitApproval(aid, decision, { wasStreaming })));
|
|
2653
|
+
pending.forEach((aid) => submitApproval(aid, decision));
|
|
2597
2654
|
renderMessages(state.activeMessages, state.isStreaming);
|
|
2598
2655
|
loadConversations();
|
|
2599
2656
|
if (!wasStreaming && state.activeConversationId) {
|
|
@@ -2623,8 +2680,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
2623
2680
|
if (!wasStreaming) {
|
|
2624
2681
|
setStreaming(true);
|
|
2625
2682
|
}
|
|
2626
|
-
|
|
2627
|
-
await submitApproval(approvalId, decision, { wasStreaming });
|
|
2683
|
+
submitApproval(approvalId, decision);
|
|
2628
2684
|
renderMessages(state.activeMessages, state.isStreaming);
|
|
2629
2685
|
loadConversations();
|
|
2630
2686
|
if (!wasStreaming && state.activeConversationId) {
|
package/src/web-ui-styles.ts
CHANGED
|
@@ -825,6 +825,25 @@ export const WEB_UI_STYLES = `
|
|
|
825
825
|
border-color: var(--deny-border);
|
|
826
826
|
color: var(--deny);
|
|
827
827
|
}
|
|
828
|
+
.approval-request-item.resolved {
|
|
829
|
+
opacity: 0.7;
|
|
830
|
+
}
|
|
831
|
+
.approval-resolved-status {
|
|
832
|
+
font-size: 12px;
|
|
833
|
+
font-weight: 600;
|
|
834
|
+
letter-spacing: 0.04em;
|
|
835
|
+
}
|
|
836
|
+
.approval-resolved-status code {
|
|
837
|
+
font-family: ui-monospace, "SF Mono", "Fira Code", monospace;
|
|
838
|
+
letter-spacing: 0;
|
|
839
|
+
color: var(--fg-strong);
|
|
840
|
+
}
|
|
841
|
+
.approval-resolved-status.approve {
|
|
842
|
+
color: var(--approve);
|
|
843
|
+
}
|
|
844
|
+
.approval-resolved-status.deny {
|
|
845
|
+
color: var(--deny);
|
|
846
|
+
}
|
|
828
847
|
.user-bubble {
|
|
829
848
|
background: var(--bg-elevated);
|
|
830
849
|
border: 1px solid var(--border-2);
|