@poncho-ai/cli 0.10.2 → 0.11.1
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 +18 -0
- package/dist/{chunk-COLXQM6J.js → chunk-T2F6ICXI.js} +595 -45
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{run-interactive-ink-Z3U5SV4C.js → run-interactive-ink-7FP5PT7Q.js} +83 -6
- package/package.json +5 -3
- package/src/index.ts +206 -26
- package/src/run-interactive-ink.ts +84 -5
- package/src/web-ui.ts +391 -17
- package/test/cli.test.ts +5 -0
|
@@ -13,11 +13,15 @@ import {
|
|
|
13
13
|
LocalMcpBridge,
|
|
14
14
|
TelemetryEmitter,
|
|
15
15
|
createConversationStore,
|
|
16
|
+
createUploadStore,
|
|
17
|
+
deriveUploadKey,
|
|
16
18
|
ensureAgentIdentity as ensureAgentIdentity2,
|
|
17
19
|
generateAgentId,
|
|
18
20
|
loadPonchoConfig,
|
|
19
21
|
resolveStateConfig
|
|
20
22
|
} from "@poncho-ai/harness";
|
|
23
|
+
import { getTextContent } from "@poncho-ai/sdk";
|
|
24
|
+
import Busboy from "busboy";
|
|
21
25
|
import { Command } from "commander";
|
|
22
26
|
import dotenv from "dotenv";
|
|
23
27
|
import YAML from "yaml";
|
|
@@ -897,7 +901,7 @@ var renderWebUiHtml = (options) => {
|
|
|
897
901
|
border-radius: 24px;
|
|
898
902
|
display: flex;
|
|
899
903
|
align-items: end;
|
|
900
|
-
padding: 4px 6px 4px
|
|
904
|
+
padding: 4px 6px 4px 6px;
|
|
901
905
|
transition: border-color 0.15s;
|
|
902
906
|
}
|
|
903
907
|
.composer-shell:focus-within { border-color: rgba(255,255,255,0.2); }
|
|
@@ -910,7 +914,7 @@ var renderWebUiHtml = (options) => {
|
|
|
910
914
|
min-height: 40px;
|
|
911
915
|
max-height: 200px;
|
|
912
916
|
resize: none;
|
|
913
|
-
padding:
|
|
917
|
+
padding: 11px 0 8px;
|
|
914
918
|
font-size: 14px;
|
|
915
919
|
line-height: 1.5;
|
|
916
920
|
margin-top: -4px;
|
|
@@ -938,6 +942,149 @@ var renderWebUiHtml = (options) => {
|
|
|
938
942
|
.send-btn.stop-mode:hover { background: #565656; }
|
|
939
943
|
.send-btn:disabled { opacity: 0.2; cursor: default; }
|
|
940
944
|
.send-btn:disabled:hover { background: #ededed; }
|
|
945
|
+
.attach-btn {
|
|
946
|
+
width: 32px;
|
|
947
|
+
height: 32px;
|
|
948
|
+
background: rgba(255,255,255,0.08);
|
|
949
|
+
border: 0;
|
|
950
|
+
border-radius: 50%;
|
|
951
|
+
color: #999;
|
|
952
|
+
cursor: pointer;
|
|
953
|
+
display: grid;
|
|
954
|
+
place-items: center;
|
|
955
|
+
flex-shrink: 0;
|
|
956
|
+
margin-bottom: 2px;
|
|
957
|
+
margin-right: 8px;
|
|
958
|
+
transition: color 0.15s, background 0.15s;
|
|
959
|
+
}
|
|
960
|
+
.attach-btn:hover { color: #ededed; background: rgba(255,255,255,0.14); }
|
|
961
|
+
.attachment-preview {
|
|
962
|
+
display: flex;
|
|
963
|
+
gap: 8px;
|
|
964
|
+
padding: 8px 0;
|
|
965
|
+
flex-wrap: wrap;
|
|
966
|
+
}
|
|
967
|
+
.attachment-chip {
|
|
968
|
+
display: inline-flex;
|
|
969
|
+
align-items: center;
|
|
970
|
+
gap: 6px;
|
|
971
|
+
background: rgba(0, 0, 0, 0.6);
|
|
972
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
973
|
+
border-radius: 9999px;
|
|
974
|
+
padding: 4px 10px 4px 6px;
|
|
975
|
+
font-size: 11px;
|
|
976
|
+
color: #777;
|
|
977
|
+
max-width: 200px;
|
|
978
|
+
cursor: pointer;
|
|
979
|
+
backdrop-filter: blur(6px);
|
|
980
|
+
-webkit-backdrop-filter: blur(6px);
|
|
981
|
+
transition: color 0.15s, border-color 0.15s, background 0.15s;
|
|
982
|
+
}
|
|
983
|
+
.attachment-chip:hover {
|
|
984
|
+
color: #ededed;
|
|
985
|
+
border-color: rgba(255, 255, 255, 0.25);
|
|
986
|
+
background: rgba(0, 0, 0, 0.75);
|
|
987
|
+
}
|
|
988
|
+
.attachment-chip img {
|
|
989
|
+
width: 20px;
|
|
990
|
+
height: 20px;
|
|
991
|
+
object-fit: cover;
|
|
992
|
+
border-radius: 50%;
|
|
993
|
+
flex-shrink: 0;
|
|
994
|
+
cursor: pointer;
|
|
995
|
+
}
|
|
996
|
+
.attachment-chip .file-icon {
|
|
997
|
+
width: 20px;
|
|
998
|
+
height: 20px;
|
|
999
|
+
border-radius: 50%;
|
|
1000
|
+
background: rgba(255,255,255,0.1);
|
|
1001
|
+
display: grid;
|
|
1002
|
+
place-items: center;
|
|
1003
|
+
font-size: 11px;
|
|
1004
|
+
flex-shrink: 0;
|
|
1005
|
+
}
|
|
1006
|
+
.attachment-chip .remove-attachment {
|
|
1007
|
+
cursor: pointer;
|
|
1008
|
+
color: #555;
|
|
1009
|
+
font-size: 14px;
|
|
1010
|
+
margin-left: 2px;
|
|
1011
|
+
line-height: 1;
|
|
1012
|
+
transition: color 0.15s;
|
|
1013
|
+
}
|
|
1014
|
+
.attachment-chip .remove-attachment:hover { color: #fff; }
|
|
1015
|
+
.attachment-chip .filename { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100px; }
|
|
1016
|
+
.user-bubble .user-file-attachments {
|
|
1017
|
+
display: flex;
|
|
1018
|
+
gap: 6px;
|
|
1019
|
+
flex-wrap: wrap;
|
|
1020
|
+
margin-top: 8px;
|
|
1021
|
+
}
|
|
1022
|
+
.user-file-attachments img {
|
|
1023
|
+
max-width: 200px;
|
|
1024
|
+
max-height: 160px;
|
|
1025
|
+
border-radius: 8px;
|
|
1026
|
+
object-fit: cover;
|
|
1027
|
+
cursor: pointer;
|
|
1028
|
+
transition: opacity 0.15s;
|
|
1029
|
+
}
|
|
1030
|
+
.user-file-attachments img:hover { opacity: 0.85; }
|
|
1031
|
+
.lightbox {
|
|
1032
|
+
position: fixed;
|
|
1033
|
+
inset: 0;
|
|
1034
|
+
z-index: 9999;
|
|
1035
|
+
display: flex;
|
|
1036
|
+
align-items: center;
|
|
1037
|
+
justify-content: center;
|
|
1038
|
+
background: rgba(0,0,0,0);
|
|
1039
|
+
backdrop-filter: blur(0px);
|
|
1040
|
+
cursor: zoom-out;
|
|
1041
|
+
transition: background 0.25s ease, backdrop-filter 0.25s ease;
|
|
1042
|
+
}
|
|
1043
|
+
.lightbox.active {
|
|
1044
|
+
background: rgba(0,0,0,0.85);
|
|
1045
|
+
backdrop-filter: blur(8px);
|
|
1046
|
+
}
|
|
1047
|
+
.lightbox img {
|
|
1048
|
+
max-width: 90vw;
|
|
1049
|
+
max-height: 90vh;
|
|
1050
|
+
border-radius: 8px;
|
|
1051
|
+
object-fit: contain;
|
|
1052
|
+
transform: scale(0.4);
|
|
1053
|
+
opacity: 0;
|
|
1054
|
+
transition: transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94), opacity 0.25s ease;
|
|
1055
|
+
}
|
|
1056
|
+
.lightbox.active img {
|
|
1057
|
+
transform: scale(1);
|
|
1058
|
+
opacity: 1;
|
|
1059
|
+
}
|
|
1060
|
+
.user-file-badge {
|
|
1061
|
+
display: inline-flex;
|
|
1062
|
+
align-items: center;
|
|
1063
|
+
gap: 4px;
|
|
1064
|
+
background: rgba(0,0,0,0.2);
|
|
1065
|
+
border-radius: 6px;
|
|
1066
|
+
padding: 4px 8px;
|
|
1067
|
+
font-size: 12px;
|
|
1068
|
+
color: rgba(255,255,255,0.8);
|
|
1069
|
+
}
|
|
1070
|
+
.drag-overlay {
|
|
1071
|
+
position: fixed;
|
|
1072
|
+
inset: 0;
|
|
1073
|
+
background: rgba(0,0,0,0.6);
|
|
1074
|
+
z-index: 9999;
|
|
1075
|
+
display: none;
|
|
1076
|
+
align-items: center;
|
|
1077
|
+
justify-content: center;
|
|
1078
|
+
pointer-events: none;
|
|
1079
|
+
}
|
|
1080
|
+
.drag-overlay.active { display: flex; }
|
|
1081
|
+
.drag-overlay-inner {
|
|
1082
|
+
border: 2px dashed rgba(255,255,255,0.4);
|
|
1083
|
+
border-radius: 16px;
|
|
1084
|
+
padding: 40px 60px;
|
|
1085
|
+
color: #fff;
|
|
1086
|
+
font-size: 16px;
|
|
1087
|
+
}
|
|
941
1088
|
.disclaimer {
|
|
942
1089
|
text-align: center;
|
|
943
1090
|
color: #333;
|
|
@@ -1081,7 +1228,12 @@ var renderWebUiHtml = (options) => {
|
|
|
1081
1228
|
</div>
|
|
1082
1229
|
<form id="composer" class="composer">
|
|
1083
1230
|
<div class="composer-inner">
|
|
1231
|
+
<div id="attachment-preview" class="attachment-preview" style="display:none"></div>
|
|
1084
1232
|
<div class="composer-shell">
|
|
1233
|
+
<button id="attach-btn" class="attach-btn" type="button" title="Attach files">
|
|
1234
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 3v10M3 8h10" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
|
|
1235
|
+
</button>
|
|
1236
|
+
<input id="file-input" type="file" multiple accept="image/*,video/*,application/pdf,.txt,.csv,.json,.html" style="display:none" />
|
|
1085
1237
|
<textarea id="prompt" class="composer-input" placeholder="Send a message..." rows="1"></textarea>
|
|
1086
1238
|
<button id="send" class="send-btn" type="submit">
|
|
1087
1239
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 12V4M4 7l4-4 4 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
@@ -1091,6 +1243,8 @@ var renderWebUiHtml = (options) => {
|
|
|
1091
1243
|
</form>
|
|
1092
1244
|
</main>
|
|
1093
1245
|
</div>
|
|
1246
|
+
<div id="drag-overlay" class="drag-overlay"><div class="drag-overlay-inner">Drop files to attach</div></div>
|
|
1247
|
+
<div id="lightbox" class="lightbox" style="display:none"><img /></div>
|
|
1094
1248
|
|
|
1095
1249
|
<script>
|
|
1096
1250
|
// Marked library (inlined)
|
|
@@ -1113,7 +1267,8 @@ var renderWebUiHtml = (options) => {
|
|
|
1113
1267
|
activeStreamRunId: null,
|
|
1114
1268
|
isMessagesPinnedToBottom: true,
|
|
1115
1269
|
confirmDeleteId: null,
|
|
1116
|
-
approvalRequestsInFlight: {}
|
|
1270
|
+
approvalRequestsInFlight: {},
|
|
1271
|
+
pendingFiles: [],
|
|
1117
1272
|
};
|
|
1118
1273
|
|
|
1119
1274
|
const agentInitial = document.body.dataset.agentInitial || "A";
|
|
@@ -1135,7 +1290,12 @@ var renderWebUiHtml = (options) => {
|
|
|
1135
1290
|
send: $("send"),
|
|
1136
1291
|
shell: $("app"),
|
|
1137
1292
|
sidebarToggle: $("sidebar-toggle"),
|
|
1138
|
-
sidebarBackdrop: $("sidebar-backdrop")
|
|
1293
|
+
sidebarBackdrop: $("sidebar-backdrop"),
|
|
1294
|
+
attachBtn: $("attach-btn"),
|
|
1295
|
+
fileInput: $("file-input"),
|
|
1296
|
+
attachmentPreview: $("attachment-preview"),
|
|
1297
|
+
dragOverlay: $("drag-overlay"),
|
|
1298
|
+
lightbox: $("lightbox"),
|
|
1139
1299
|
};
|
|
1140
1300
|
const sendIconMarkup =
|
|
1141
1301
|
'<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 12V4M4 7l4-4 4 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
|
|
@@ -1631,7 +1791,47 @@ var renderWebUiHtml = (options) => {
|
|
|
1631
1791
|
wrap.appendChild(content);
|
|
1632
1792
|
row.appendChild(wrap);
|
|
1633
1793
|
} else {
|
|
1634
|
-
|
|
1794
|
+
const bubble = document.createElement("div");
|
|
1795
|
+
bubble.className = "user-bubble";
|
|
1796
|
+
if (typeof m.content === "string") {
|
|
1797
|
+
bubble.textContent = m.content;
|
|
1798
|
+
} else if (Array.isArray(m.content)) {
|
|
1799
|
+
const textParts = m.content.filter(p => p.type === "text").map(p => p.text).join("");
|
|
1800
|
+
if (textParts) {
|
|
1801
|
+
const textEl = document.createElement("div");
|
|
1802
|
+
textEl.textContent = textParts;
|
|
1803
|
+
bubble.appendChild(textEl);
|
|
1804
|
+
}
|
|
1805
|
+
const fileParts = m.content.filter(p => p.type === "file");
|
|
1806
|
+
if (fileParts.length > 0) {
|
|
1807
|
+
const filesEl = document.createElement("div");
|
|
1808
|
+
filesEl.className = "user-file-attachments";
|
|
1809
|
+
fileParts.forEach(fp => {
|
|
1810
|
+
if (fp.mediaType && fp.mediaType.startsWith("image/")) {
|
|
1811
|
+
const img = document.createElement("img");
|
|
1812
|
+
if (fp._localBlob) {
|
|
1813
|
+
if (!fp._cachedUrl) fp._cachedUrl = URL.createObjectURL(fp._localBlob);
|
|
1814
|
+
img.src = fp._cachedUrl;
|
|
1815
|
+
} else if (fp.data && fp.data.startsWith("poncho-upload://")) {
|
|
1816
|
+
img.src = "/api/uploads/" + encodeURIComponent(fp.data.replace("poncho-upload://", ""));
|
|
1817
|
+
} else if (fp.data && (fp.data.startsWith("http://") || fp.data.startsWith("https://"))) {
|
|
1818
|
+
img.src = fp.data;
|
|
1819
|
+
} else if (fp.data) {
|
|
1820
|
+
img.src = "data:" + fp.mediaType + ";base64," + fp.data;
|
|
1821
|
+
}
|
|
1822
|
+
img.alt = fp.filename || "image";
|
|
1823
|
+
filesEl.appendChild(img);
|
|
1824
|
+
} else {
|
|
1825
|
+
const badge = document.createElement("span");
|
|
1826
|
+
badge.className = "user-file-badge";
|
|
1827
|
+
badge.textContent = "\u{1F4CE} " + (fp.filename || "file");
|
|
1828
|
+
filesEl.appendChild(badge);
|
|
1829
|
+
}
|
|
1830
|
+
});
|
|
1831
|
+
bubble.appendChild(filesEl);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
row.appendChild(bubble);
|
|
1635
1835
|
}
|
|
1636
1836
|
col.appendChild(row);
|
|
1637
1837
|
});
|
|
@@ -2137,12 +2337,62 @@ var renderWebUiHtml = (options) => {
|
|
|
2137
2337
|
}
|
|
2138
2338
|
};
|
|
2139
2339
|
|
|
2340
|
+
const renderAttachmentPreview = () => {
|
|
2341
|
+
const el = elements.attachmentPreview;
|
|
2342
|
+
if (state.pendingFiles.length === 0) {
|
|
2343
|
+
el.style.display = "none";
|
|
2344
|
+
el.innerHTML = "";
|
|
2345
|
+
return;
|
|
2346
|
+
}
|
|
2347
|
+
el.style.display = "flex";
|
|
2348
|
+
el.innerHTML = state.pendingFiles.map((f, i) => {
|
|
2349
|
+
const isImage = f.type.startsWith("image/");
|
|
2350
|
+
const thumbHtml = isImage
|
|
2351
|
+
? '<img src="' + URL.createObjectURL(f) + '" alt="" />'
|
|
2352
|
+
: '<span class="file-icon">\u{1F4CE}</span>';
|
|
2353
|
+
return '<div class="attachment-chip" data-idx="' + i + '">'
|
|
2354
|
+
+ thumbHtml
|
|
2355
|
+
+ '<span class="filename">' + escapeHtml(f.name) + '</span>'
|
|
2356
|
+
+ '<span class="remove-attachment" data-idx="' + i + '">×</span>'
|
|
2357
|
+
+ '</div>';
|
|
2358
|
+
}).join("");
|
|
2359
|
+
};
|
|
2360
|
+
|
|
2361
|
+
const addFiles = (fileList) => {
|
|
2362
|
+
for (const f of fileList) {
|
|
2363
|
+
if (f.size > 25 * 1024 * 1024) {
|
|
2364
|
+
alert("File too large: " + f.name + " (max 25MB)");
|
|
2365
|
+
continue;
|
|
2366
|
+
}
|
|
2367
|
+
state.pendingFiles.push(f);
|
|
2368
|
+
}
|
|
2369
|
+
renderAttachmentPreview();
|
|
2370
|
+
};
|
|
2371
|
+
|
|
2140
2372
|
const sendMessage = async (text) => {
|
|
2141
2373
|
const messageText = (text || "").trim();
|
|
2142
2374
|
if (!messageText || state.isStreaming) {
|
|
2143
2375
|
return;
|
|
2144
2376
|
}
|
|
2145
|
-
const
|
|
2377
|
+
const filesToSend = [...state.pendingFiles];
|
|
2378
|
+
state.pendingFiles = [];
|
|
2379
|
+
renderAttachmentPreview();
|
|
2380
|
+
let userContent;
|
|
2381
|
+
if (filesToSend.length > 0) {
|
|
2382
|
+
userContent = [{ type: "text", text: messageText }];
|
|
2383
|
+
for (const f of filesToSend) {
|
|
2384
|
+
userContent.push({
|
|
2385
|
+
type: "file",
|
|
2386
|
+
data: URL.createObjectURL(f),
|
|
2387
|
+
mediaType: f.type,
|
|
2388
|
+
filename: f.name,
|
|
2389
|
+
_localBlob: f,
|
|
2390
|
+
});
|
|
2391
|
+
}
|
|
2392
|
+
} else {
|
|
2393
|
+
userContent = messageText;
|
|
2394
|
+
}
|
|
2395
|
+
const localMessages = [...(state.activeMessages || []), { role: "user", content: userContent }];
|
|
2146
2396
|
let assistantMessage = {
|
|
2147
2397
|
role: "assistant",
|
|
2148
2398
|
content: "",
|
|
@@ -2185,13 +2435,38 @@ var renderWebUiHtml = (options) => {
|
|
|
2185
2435
|
assistantMessage._currentText = "";
|
|
2186
2436
|
}
|
|
2187
2437
|
};
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2438
|
+
let _continuationMessage = messageText;
|
|
2439
|
+
let _totalSteps = 0;
|
|
2440
|
+
let _maxSteps = 0;
|
|
2441
|
+
while (_continuationMessage) {
|
|
2442
|
+
let _shouldContinue = false;
|
|
2443
|
+
let fetchOpts;
|
|
2444
|
+
if (filesToSend.length > 0 && _continuationMessage === messageText) {
|
|
2445
|
+
const formData = new FormData();
|
|
2446
|
+
formData.append("message", _continuationMessage);
|
|
2447
|
+
for (const f of filesToSend) {
|
|
2448
|
+
formData.append("files", f, f.name);
|
|
2449
|
+
}
|
|
2450
|
+
fetchOpts = {
|
|
2451
|
+
method: "POST",
|
|
2452
|
+
credentials: "include",
|
|
2453
|
+
headers: { "x-csrf-token": state.csrfToken },
|
|
2454
|
+
body: formData,
|
|
2455
|
+
signal: streamAbortController.signal,
|
|
2456
|
+
};
|
|
2457
|
+
} else {
|
|
2458
|
+
fetchOpts = {
|
|
2459
|
+
method: "POST",
|
|
2460
|
+
credentials: "include",
|
|
2461
|
+
headers: { "Content-Type": "application/json", "x-csrf-token": state.csrfToken },
|
|
2462
|
+
body: JSON.stringify({ message: _continuationMessage }),
|
|
2463
|
+
signal: streamAbortController.signal,
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2466
|
+
const response = await fetch(
|
|
2467
|
+
"/api/conversations/" + encodeURIComponent(conversationId) + "/messages",
|
|
2468
|
+
fetchOpts,
|
|
2469
|
+
);
|
|
2195
2470
|
if (!response.ok || !response.body) {
|
|
2196
2471
|
throw new Error("Failed to stream response");
|
|
2197
2472
|
}
|
|
@@ -2366,11 +2641,17 @@ var renderWebUiHtml = (options) => {
|
|
|
2366
2641
|
renderIfActiveConversation(true);
|
|
2367
2642
|
}
|
|
2368
2643
|
if (eventName === "run:completed") {
|
|
2369
|
-
|
|
2370
|
-
if (
|
|
2371
|
-
|
|
2644
|
+
_totalSteps += typeof payload.result?.steps === "number" ? payload.result.steps : 0;
|
|
2645
|
+
if (typeof payload.result?.maxSteps === "number") _maxSteps = payload.result.maxSteps;
|
|
2646
|
+
if (payload.result?.continuation === true && (_maxSteps <= 0 || _totalSteps < _maxSteps)) {
|
|
2647
|
+
_shouldContinue = true;
|
|
2648
|
+
} else {
|
|
2649
|
+
finalizeAssistantMessage();
|
|
2650
|
+
if (!assistantMessage.content || assistantMessage.content.length === 0) {
|
|
2651
|
+
assistantMessage.content = String(payload.result?.response || "");
|
|
2652
|
+
}
|
|
2653
|
+
renderIfActiveConversation(false);
|
|
2372
2654
|
}
|
|
2373
|
-
renderIfActiveConversation(false);
|
|
2374
2655
|
}
|
|
2375
2656
|
if (eventName === "run:cancelled") {
|
|
2376
2657
|
finalizeAssistantMessage();
|
|
@@ -2388,6 +2669,9 @@ var renderWebUiHtml = (options) => {
|
|
|
2388
2669
|
}
|
|
2389
2670
|
});
|
|
2390
2671
|
}
|
|
2672
|
+
if (!_shouldContinue) break;
|
|
2673
|
+
_continuationMessage = "Continue";
|
|
2674
|
+
}
|
|
2391
2675
|
// Update active state only if user is still on this conversation.
|
|
2392
2676
|
if (state.activeConversationId === streamConversationId) {
|
|
2393
2677
|
state.activeMessages = localMessages;
|
|
@@ -2534,6 +2818,100 @@ var renderWebUiHtml = (options) => {
|
|
|
2534
2818
|
await sendMessage(value);
|
|
2535
2819
|
});
|
|
2536
2820
|
|
|
2821
|
+
elements.attachBtn.addEventListener("click", () => elements.fileInput.click());
|
|
2822
|
+
elements.fileInput.addEventListener("change", () => {
|
|
2823
|
+
if (elements.fileInput.files && elements.fileInput.files.length > 0) {
|
|
2824
|
+
addFiles(elements.fileInput.files);
|
|
2825
|
+
elements.fileInput.value = "";
|
|
2826
|
+
}
|
|
2827
|
+
});
|
|
2828
|
+
elements.attachmentPreview.addEventListener("click", (e) => {
|
|
2829
|
+
const rm = e.target.closest(".remove-attachment");
|
|
2830
|
+
if (rm) {
|
|
2831
|
+
const idx = parseInt(rm.dataset.idx, 10);
|
|
2832
|
+
state.pendingFiles.splice(idx, 1);
|
|
2833
|
+
renderAttachmentPreview();
|
|
2834
|
+
}
|
|
2835
|
+
});
|
|
2836
|
+
|
|
2837
|
+
let dragCounter = 0;
|
|
2838
|
+
document.addEventListener("dragenter", (e) => {
|
|
2839
|
+
e.preventDefault();
|
|
2840
|
+
dragCounter++;
|
|
2841
|
+
if (dragCounter === 1) elements.dragOverlay.classList.add("active");
|
|
2842
|
+
});
|
|
2843
|
+
document.addEventListener("dragleave", (e) => {
|
|
2844
|
+
e.preventDefault();
|
|
2845
|
+
dragCounter--;
|
|
2846
|
+
if (dragCounter <= 0) { dragCounter = 0; elements.dragOverlay.classList.remove("active"); }
|
|
2847
|
+
});
|
|
2848
|
+
document.addEventListener("dragover", (e) => e.preventDefault());
|
|
2849
|
+
document.addEventListener("drop", (e) => {
|
|
2850
|
+
e.preventDefault();
|
|
2851
|
+
dragCounter = 0;
|
|
2852
|
+
elements.dragOverlay.classList.remove("active");
|
|
2853
|
+
if (e.dataTransfer && e.dataTransfer.files.length > 0) {
|
|
2854
|
+
addFiles(e.dataTransfer.files);
|
|
2855
|
+
}
|
|
2856
|
+
});
|
|
2857
|
+
|
|
2858
|
+
// Paste files/images from clipboard
|
|
2859
|
+
elements.prompt.addEventListener("paste", (e) => {
|
|
2860
|
+
const items = e.clipboardData && e.clipboardData.items;
|
|
2861
|
+
if (!items) return;
|
|
2862
|
+
const files = [];
|
|
2863
|
+
for (let i = 0; i < items.length; i++) {
|
|
2864
|
+
if (items[i].kind === "file") {
|
|
2865
|
+
const f = items[i].getAsFile();
|
|
2866
|
+
if (f) files.push(f);
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
if (files.length > 0) {
|
|
2870
|
+
e.preventDefault();
|
|
2871
|
+
addFiles(files);
|
|
2872
|
+
}
|
|
2873
|
+
});
|
|
2874
|
+
|
|
2875
|
+
// Lightbox: open/close helpers
|
|
2876
|
+
const lightboxImg = elements.lightbox.querySelector("img");
|
|
2877
|
+
const openLightbox = (src) => {
|
|
2878
|
+
lightboxImg.src = src;
|
|
2879
|
+
elements.lightbox.style.display = "flex";
|
|
2880
|
+
requestAnimationFrame(() => {
|
|
2881
|
+
requestAnimationFrame(() => elements.lightbox.classList.add("active"));
|
|
2882
|
+
});
|
|
2883
|
+
};
|
|
2884
|
+
const closeLightbox = () => {
|
|
2885
|
+
elements.lightbox.classList.remove("active");
|
|
2886
|
+
elements.lightbox.addEventListener("transitionend", function handler() {
|
|
2887
|
+
elements.lightbox.removeEventListener("transitionend", handler);
|
|
2888
|
+
elements.lightbox.style.display = "none";
|
|
2889
|
+
lightboxImg.src = "";
|
|
2890
|
+
});
|
|
2891
|
+
};
|
|
2892
|
+
elements.lightbox.addEventListener("click", closeLightbox);
|
|
2893
|
+
document.addEventListener("keydown", (e) => {
|
|
2894
|
+
if (e.key === "Escape" && elements.lightbox.style.display !== "none") closeLightbox();
|
|
2895
|
+
});
|
|
2896
|
+
|
|
2897
|
+
// Lightbox from message images
|
|
2898
|
+
elements.messages.addEventListener("click", (e) => {
|
|
2899
|
+
const img = e.target;
|
|
2900
|
+
if (!(img instanceof HTMLImageElement) || !img.closest(".user-file-attachments")) return;
|
|
2901
|
+
openLightbox(img.src);
|
|
2902
|
+
});
|
|
2903
|
+
|
|
2904
|
+
// Lightbox from attachment preview chips
|
|
2905
|
+
elements.attachmentPreview.addEventListener("click", (e) => {
|
|
2906
|
+
if (e.target.closest(".remove-attachment")) return;
|
|
2907
|
+
const chip = e.target.closest(".attachment-chip");
|
|
2908
|
+
if (!chip) return;
|
|
2909
|
+
const img = chip.querySelector("img");
|
|
2910
|
+
if (!img) return;
|
|
2911
|
+
e.stopPropagation();
|
|
2912
|
+
openLightbox(img.src);
|
|
2913
|
+
});
|
|
2914
|
+
|
|
2537
2915
|
elements.messages.addEventListener("click", async (event) => {
|
|
2538
2916
|
const target = event.target;
|
|
2539
2917
|
if (!(target instanceof Element)) {
|
|
@@ -3374,6 +3752,24 @@ var writeHtml = (response, statusCode, payload) => {
|
|
|
3374
3752
|
response.writeHead(statusCode, { "Content-Type": "text/html; charset=utf-8" });
|
|
3375
3753
|
response.end(payload);
|
|
3376
3754
|
};
|
|
3755
|
+
var EXT_MIME_MAP = {
|
|
3756
|
+
jpg: "image/jpeg",
|
|
3757
|
+
jpeg: "image/jpeg",
|
|
3758
|
+
png: "image/png",
|
|
3759
|
+
gif: "image/gif",
|
|
3760
|
+
webp: "image/webp",
|
|
3761
|
+
svg: "image/svg+xml",
|
|
3762
|
+
pdf: "application/pdf",
|
|
3763
|
+
mp4: "video/mp4",
|
|
3764
|
+
webm: "video/webm",
|
|
3765
|
+
mp3: "audio/mpeg",
|
|
3766
|
+
wav: "audio/wav",
|
|
3767
|
+
txt: "text/plain",
|
|
3768
|
+
json: "application/json",
|
|
3769
|
+
csv: "text/csv",
|
|
3770
|
+
html: "text/html"
|
|
3771
|
+
};
|
|
3772
|
+
var extToMime = (ext) => EXT_MIME_MAP[ext] ?? "application/octet-stream";
|
|
3377
3773
|
var readRequestBody = async (request) => {
|
|
3378
3774
|
const chunks = [];
|
|
3379
3775
|
for await (const chunk of request) {
|
|
@@ -3382,6 +3778,38 @@ var readRequestBody = async (request) => {
|
|
|
3382
3778
|
const body = Buffer.concat(chunks).toString("utf8");
|
|
3383
3779
|
return body.length > 0 ? JSON.parse(body) : {};
|
|
3384
3780
|
};
|
|
3781
|
+
var MAX_UPLOAD_SIZE = 25 * 1024 * 1024;
|
|
3782
|
+
var parseMultipartRequest = (request) => new Promise((resolve4, reject) => {
|
|
3783
|
+
const result = { message: "", files: [] };
|
|
3784
|
+
const bb = Busboy({
|
|
3785
|
+
headers: request.headers,
|
|
3786
|
+
limits: { fileSize: MAX_UPLOAD_SIZE }
|
|
3787
|
+
});
|
|
3788
|
+
bb.on("field", (name, value) => {
|
|
3789
|
+
if (name === "message") result.message = value;
|
|
3790
|
+
if (name === "parameters") {
|
|
3791
|
+
try {
|
|
3792
|
+
result.parameters = JSON.parse(value);
|
|
3793
|
+
} catch {
|
|
3794
|
+
}
|
|
3795
|
+
}
|
|
3796
|
+
});
|
|
3797
|
+
bb.on("file", (_name, stream, info) => {
|
|
3798
|
+
const chunks = [];
|
|
3799
|
+
stream.on("data", (chunk) => chunks.push(chunk));
|
|
3800
|
+
stream.on("end", () => {
|
|
3801
|
+
const buf = Buffer.concat(chunks);
|
|
3802
|
+
result.files.push({
|
|
3803
|
+
data: buf.toString("base64"),
|
|
3804
|
+
mediaType: info.mimeType,
|
|
3805
|
+
filename: info.filename
|
|
3806
|
+
});
|
|
3807
|
+
});
|
|
3808
|
+
});
|
|
3809
|
+
bb.on("finish", () => resolve4(result));
|
|
3810
|
+
bb.on("error", (err) => reject(err));
|
|
3811
|
+
request.pipe(bb);
|
|
3812
|
+
});
|
|
3385
3813
|
var resolveHarnessEnvironment = () => {
|
|
3386
3814
|
if (process.env.PONCHO_ENV) {
|
|
3387
3815
|
const value = process.env.PONCHO_ENV.toLowerCase();
|
|
@@ -3903,7 +4331,14 @@ var writeScaffoldFile = async (filePath, content, options) => {
|
|
|
3903
4331
|
await writeFile3(filePath, content, "utf8");
|
|
3904
4332
|
options.writtenPaths.push(relative(options.baseDir, filePath));
|
|
3905
4333
|
};
|
|
3906
|
-
var
|
|
4334
|
+
var UPLOAD_PROVIDER_DEPS = {
|
|
4335
|
+
"vercel-blob": [{ name: "@vercel/blob", fallback: "^2.3.0" }],
|
|
4336
|
+
s3: [
|
|
4337
|
+
{ name: "@aws-sdk/client-s3", fallback: "^3.700.0" },
|
|
4338
|
+
{ name: "@aws-sdk/s3-request-presigner", fallback: "^3.700.0" }
|
|
4339
|
+
]
|
|
4340
|
+
};
|
|
4341
|
+
var ensureRuntimeCliDependency = async (projectDir, cliVersion, config) => {
|
|
3907
4342
|
const packageJsonPath = resolve3(projectDir, "package.json");
|
|
3908
4343
|
const content = await readFile3(packageJsonPath, "utf8");
|
|
3909
4344
|
const parsed = JSON.parse(content);
|
|
@@ -3917,10 +4352,20 @@ var ensureRuntimeCliDependency = async (projectDir, cliVersion) => {
|
|
|
3917
4352
|
}
|
|
3918
4353
|
dependencies.marked = await readCliDependencyVersion("marked", "^17.0.2");
|
|
3919
4354
|
dependencies["@poncho-ai/cli"] = `^${cliVersion}`;
|
|
4355
|
+
const addedDeps = [];
|
|
4356
|
+
const uploadsProvider = config?.uploads?.provider;
|
|
4357
|
+
if (uploadsProvider && UPLOAD_PROVIDER_DEPS[uploadsProvider]) {
|
|
4358
|
+
for (const dep of UPLOAD_PROVIDER_DEPS[uploadsProvider]) {
|
|
4359
|
+
if (!dependencies[dep.name]) {
|
|
4360
|
+
dependencies[dep.name] = dep.fallback;
|
|
4361
|
+
addedDeps.push(dep.name);
|
|
4362
|
+
}
|
|
4363
|
+
}
|
|
4364
|
+
}
|
|
3920
4365
|
parsed.dependencies = dependencies;
|
|
3921
4366
|
await writeFile3(packageJsonPath, `${JSON.stringify(parsed, null, 2)}
|
|
3922
4367
|
`, "utf8");
|
|
3923
|
-
return [relative(projectDir, packageJsonPath)];
|
|
4368
|
+
return { paths: [relative(projectDir, packageJsonPath)], addedDeps };
|
|
3924
4369
|
};
|
|
3925
4370
|
var scaffoldDeployTarget = async (projectDir, target, options) => {
|
|
3926
4371
|
const writtenPaths = [];
|
|
@@ -4053,10 +4498,16 @@ CMD ["node","server.js"]
|
|
|
4053
4498
|
baseDir: projectDir
|
|
4054
4499
|
});
|
|
4055
4500
|
}
|
|
4056
|
-
const
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4501
|
+
const config = await loadPonchoConfig(projectDir);
|
|
4502
|
+
const { paths: packagePaths, addedDeps } = await ensureRuntimeCliDependency(
|
|
4503
|
+
projectDir,
|
|
4504
|
+
cliVersion,
|
|
4505
|
+
config
|
|
4506
|
+
);
|
|
4507
|
+
const depNote = addedDeps.length > 0 ? ` (added ${addedDeps.join(", ")})` : "";
|
|
4508
|
+
for (const p of packagePaths) {
|
|
4509
|
+
if (!writtenPaths.includes(p)) {
|
|
4510
|
+
writtenPaths.push(depNote ? `${p}${depNote}` : p);
|
|
4060
4511
|
}
|
|
4061
4512
|
}
|
|
4062
4513
|
return writtenPaths;
|
|
@@ -4312,9 +4763,11 @@ var createRequestHandler = async (options) => {
|
|
|
4312
4763
|
}
|
|
4313
4764
|
await persistConversationPendingApprovals(conversationId);
|
|
4314
4765
|
};
|
|
4766
|
+
const uploadStore = await createUploadStore(config?.uploads, workingDir);
|
|
4315
4767
|
const harness = new AgentHarness({
|
|
4316
4768
|
workingDir,
|
|
4317
4769
|
environment: resolveHarnessEnvironment(),
|
|
4770
|
+
uploadStore,
|
|
4318
4771
|
approvalHandler: async (request) => new Promise((resolveApproval) => {
|
|
4319
4772
|
const ownerIdForRun = runOwners.get(request.runId) ?? "local-owner";
|
|
4320
4773
|
const conversationIdForRun = runConversations.get(request.runId) ?? null;
|
|
@@ -4712,6 +5165,40 @@ var createRequestHandler = async (options) => {
|
|
|
4712
5165
|
});
|
|
4713
5166
|
return;
|
|
4714
5167
|
}
|
|
5168
|
+
const uploadMatch = pathname.match(/^\/api\/uploads\/(.+)$/);
|
|
5169
|
+
if (uploadMatch && request.method === "GET") {
|
|
5170
|
+
const key = decodeURIComponent(uploadMatch[1] ?? "");
|
|
5171
|
+
try {
|
|
5172
|
+
const data = await uploadStore.get(key);
|
|
5173
|
+
const ext = key.split(".").pop() ?? "";
|
|
5174
|
+
const mimeMap = {
|
|
5175
|
+
jpg: "image/jpeg",
|
|
5176
|
+
jpeg: "image/jpeg",
|
|
5177
|
+
png: "image/png",
|
|
5178
|
+
gif: "image/gif",
|
|
5179
|
+
webp: "image/webp",
|
|
5180
|
+
svg: "image/svg+xml",
|
|
5181
|
+
pdf: "application/pdf",
|
|
5182
|
+
mp4: "video/mp4",
|
|
5183
|
+
webm: "video/webm",
|
|
5184
|
+
mp3: "audio/mpeg",
|
|
5185
|
+
wav: "audio/wav",
|
|
5186
|
+
txt: "text/plain",
|
|
5187
|
+
json: "application/json",
|
|
5188
|
+
csv: "text/csv",
|
|
5189
|
+
html: "text/html"
|
|
5190
|
+
};
|
|
5191
|
+
response.writeHead(200, {
|
|
5192
|
+
"Content-Type": mimeMap[ext] ?? "application/octet-stream",
|
|
5193
|
+
"Content-Length": data.length,
|
|
5194
|
+
"Cache-Control": "public, max-age=86400"
|
|
5195
|
+
});
|
|
5196
|
+
response.end(data);
|
|
5197
|
+
} catch {
|
|
5198
|
+
writeJson(response, 404, { code: "NOT_FOUND", message: "Upload not found" });
|
|
5199
|
+
}
|
|
5200
|
+
return;
|
|
5201
|
+
}
|
|
4715
5202
|
const conversationMessageMatch = pathname.match(/^\/api\/conversations\/([^/]+)\/messages$/);
|
|
4716
5203
|
if (conversationMessageMatch && request.method === "POST") {
|
|
4717
5204
|
const conversationId = decodeURIComponent(conversationMessageMatch[1] ?? "");
|
|
@@ -4723,8 +5210,25 @@ var createRequestHandler = async (options) => {
|
|
|
4723
5210
|
});
|
|
4724
5211
|
return;
|
|
4725
5212
|
}
|
|
4726
|
-
|
|
4727
|
-
|
|
5213
|
+
let messageText = "";
|
|
5214
|
+
let bodyParameters;
|
|
5215
|
+
let files = [];
|
|
5216
|
+
const contentType = request.headers["content-type"] ?? "";
|
|
5217
|
+
if (contentType.includes("multipart/form-data")) {
|
|
5218
|
+
const parsed = await parseMultipartRequest(request);
|
|
5219
|
+
messageText = parsed.message.trim();
|
|
5220
|
+
bodyParameters = parsed.parameters;
|
|
5221
|
+
files = parsed.files;
|
|
5222
|
+
} else {
|
|
5223
|
+
const body = await readRequestBody(request);
|
|
5224
|
+
messageText = body.message?.trim() ?? "";
|
|
5225
|
+
bodyParameters = body.parameters;
|
|
5226
|
+
if (Array.isArray(body.files)) {
|
|
5227
|
+
files = body.files.filter(
|
|
5228
|
+
(f) => typeof f.data === "string" && typeof f.mediaType === "string"
|
|
5229
|
+
);
|
|
5230
|
+
}
|
|
5231
|
+
}
|
|
4728
5232
|
if (!messageText) {
|
|
4729
5233
|
writeJson(response, 400, {
|
|
4730
5234
|
code: "VALIDATION_ERROR",
|
|
@@ -4766,8 +5270,43 @@ var createRequestHandler = async (options) => {
|
|
|
4766
5270
|
let currentText = "";
|
|
4767
5271
|
let currentTools = [];
|
|
4768
5272
|
let runCancelled = false;
|
|
5273
|
+
let userContent = messageText;
|
|
5274
|
+
if (files.length > 0) {
|
|
5275
|
+
try {
|
|
5276
|
+
const uploadedParts = await Promise.all(
|
|
5277
|
+
files.map(async (f) => {
|
|
5278
|
+
const buf = Buffer.from(f.data, "base64");
|
|
5279
|
+
const key = deriveUploadKey(buf, f.mediaType);
|
|
5280
|
+
const ref = await uploadStore.put(key, buf, f.mediaType);
|
|
5281
|
+
return {
|
|
5282
|
+
type: "file",
|
|
5283
|
+
data: ref,
|
|
5284
|
+
mediaType: f.mediaType,
|
|
5285
|
+
filename: f.filename
|
|
5286
|
+
};
|
|
5287
|
+
})
|
|
5288
|
+
);
|
|
5289
|
+
userContent = [
|
|
5290
|
+
{ type: "text", text: messageText },
|
|
5291
|
+
...uploadedParts
|
|
5292
|
+
];
|
|
5293
|
+
} catch (uploadErr) {
|
|
5294
|
+
const errMsg = uploadErr instanceof Error ? uploadErr.message : String(uploadErr);
|
|
5295
|
+
console.error("[poncho] File upload failed:", errMsg);
|
|
5296
|
+
const errorEvent = {
|
|
5297
|
+
type: "run:error",
|
|
5298
|
+
runId: "",
|
|
5299
|
+
error: { code: "UPLOAD_ERROR", message: `File upload failed: ${errMsg}` }
|
|
5300
|
+
};
|
|
5301
|
+
broadcastEvent(conversationId, errorEvent);
|
|
5302
|
+
finishConversationStream(conversationId);
|
|
5303
|
+
activeConversationRuns.delete(conversationId);
|
|
5304
|
+
response.end();
|
|
5305
|
+
return;
|
|
5306
|
+
}
|
|
5307
|
+
}
|
|
4769
5308
|
try {
|
|
4770
|
-
conversation.messages = [...historyMessages, { role: "user", content:
|
|
5309
|
+
conversation.messages = [...historyMessages, { role: "user", content: userContent }];
|
|
4771
5310
|
conversation.updatedAt = Date.now();
|
|
4772
5311
|
await conversationStore.update(conversation);
|
|
4773
5312
|
const persistDraftAssistantTurn = async () => {
|
|
@@ -4789,7 +5328,7 @@ var createRequestHandler = async (options) => {
|
|
|
4789
5328
|
}
|
|
4790
5329
|
conversation.messages = [
|
|
4791
5330
|
...historyMessages,
|
|
4792
|
-
{ role: "user", content:
|
|
5331
|
+
{ role: "user", content: userContent },
|
|
4793
5332
|
{
|
|
4794
5333
|
role: "assistant",
|
|
4795
5334
|
content: assistantResponse,
|
|
@@ -4806,16 +5345,17 @@ var createRequestHandler = async (options) => {
|
|
|
4806
5345
|
conversationId: item.conversationId,
|
|
4807
5346
|
title: item.title,
|
|
4808
5347
|
updatedAt: item.updatedAt,
|
|
4809
|
-
content: item.messages.slice(-6).map((message) => `${message.role}: ${message.content}`).join("\n").slice(0, 2e3)
|
|
5348
|
+
content: item.messages.slice(-6).map((message) => `${message.role}: ${typeof message.content === "string" ? message.content : getTextContent(message)}`).join("\n").slice(0, 2e3)
|
|
4810
5349
|
})).filter((item) => item.content.length > 0);
|
|
4811
5350
|
for await (const event of harness.runWithTelemetry({
|
|
4812
5351
|
task: messageText,
|
|
4813
5352
|
parameters: {
|
|
4814
|
-
...
|
|
5353
|
+
...bodyParameters ?? {},
|
|
4815
5354
|
__conversationRecallCorpus: recallCorpus,
|
|
4816
5355
|
__activeConversationId: conversationId
|
|
4817
5356
|
},
|
|
4818
5357
|
messages: historyMessages,
|
|
5358
|
+
files: files.length > 0 ? files : void 0,
|
|
4819
5359
|
abortSignal: abortController.signal
|
|
4820
5360
|
})) {
|
|
4821
5361
|
if (event.type === "run:started") {
|
|
@@ -4857,6 +5397,9 @@ var createRequestHandler = async (options) => {
|
|
|
4857
5397
|
toolTimeline.push(toolText);
|
|
4858
5398
|
currentTools.push(toolText);
|
|
4859
5399
|
}
|
|
5400
|
+
if (event.type === "step:completed") {
|
|
5401
|
+
await persistDraftAssistantTurn();
|
|
5402
|
+
}
|
|
4860
5403
|
if (event.type === "tool:approval:required") {
|
|
4861
5404
|
const toolText = `- approval required \`${event.tool}\``;
|
|
4862
5405
|
toolTimeline.push(toolText);
|
|
@@ -4894,7 +5437,7 @@ var createRequestHandler = async (options) => {
|
|
|
4894
5437
|
const hasAssistantContent = assistantResponse.length > 0 || toolTimeline.length > 0 || sections.length > 0;
|
|
4895
5438
|
conversation.messages = hasAssistantContent ? [
|
|
4896
5439
|
...historyMessages,
|
|
4897
|
-
{ role: "user", content:
|
|
5440
|
+
{ role: "user", content: userContent },
|
|
4898
5441
|
{
|
|
4899
5442
|
role: "assistant",
|
|
4900
5443
|
content: assistantResponse,
|
|
@@ -4903,7 +5446,7 @@ var createRequestHandler = async (options) => {
|
|
|
4903
5446
|
sections: sections.length > 0 ? sections : void 0
|
|
4904
5447
|
} : void 0
|
|
4905
5448
|
}
|
|
4906
|
-
] : [...historyMessages, { role: "user", content:
|
|
5449
|
+
] : [...historyMessages, { role: "user", content: userContent }];
|
|
4907
5450
|
conversation.runtimeRunId = latestRunId || conversation.runtimeRunId;
|
|
4908
5451
|
conversation.pendingApprovals = [];
|
|
4909
5452
|
conversation.updatedAt = Date.now();
|
|
@@ -4920,7 +5463,7 @@ var createRequestHandler = async (options) => {
|
|
|
4920
5463
|
if (assistantResponse.length > 0 || toolTimeline.length > 0 || fallbackSections.length > 0) {
|
|
4921
5464
|
conversation.messages = [
|
|
4922
5465
|
...historyMessages,
|
|
4923
|
-
{ role: "user", content:
|
|
5466
|
+
{ role: "user", content: userContent },
|
|
4924
5467
|
{
|
|
4925
5468
|
role: "assistant",
|
|
4926
5469
|
content: assistantResponse,
|
|
@@ -4958,7 +5501,7 @@ var createRequestHandler = async (options) => {
|
|
|
4958
5501
|
if (assistantResponse.length > 0 || toolTimeline.length > 0 || fallbackSections.length > 0) {
|
|
4959
5502
|
conversation.messages = [
|
|
4960
5503
|
...historyMessages,
|
|
4961
|
-
{ role: "user", content:
|
|
5504
|
+
{ role: "user", content: userContent },
|
|
4962
5505
|
{
|
|
4963
5506
|
role: "assistant",
|
|
4964
5507
|
content: assistantResponse,
|
|
@@ -5016,21 +5559,26 @@ var runOnce = async (task, options) => {
|
|
|
5016
5559
|
const workingDir = options.workingDir ?? process.cwd();
|
|
5017
5560
|
dotenv.config({ path: resolve3(workingDir, ".env") });
|
|
5018
5561
|
const config = await loadPonchoConfig(workingDir);
|
|
5019
|
-
const
|
|
5562
|
+
const uploadStore = await createUploadStore(config?.uploads, workingDir);
|
|
5563
|
+
const harness = new AgentHarness({ workingDir, uploadStore });
|
|
5020
5564
|
const telemetry = new TelemetryEmitter(config?.telemetry);
|
|
5021
5565
|
await harness.initialize();
|
|
5022
|
-
const
|
|
5023
|
-
options.filePaths.map(async (
|
|
5024
|
-
const
|
|
5025
|
-
|
|
5026
|
-
|
|
5566
|
+
const fileInputs = await Promise.all(
|
|
5567
|
+
options.filePaths.map(async (filePath) => {
|
|
5568
|
+
const absPath = resolve3(workingDir, filePath);
|
|
5569
|
+
const buf = await readFile3(absPath);
|
|
5570
|
+
const ext = absPath.split(".").pop()?.toLowerCase() ?? "";
|
|
5571
|
+
return {
|
|
5572
|
+
data: buf.toString("base64"),
|
|
5573
|
+
mediaType: extToMime(ext),
|
|
5574
|
+
filename: basename2(filePath)
|
|
5575
|
+
};
|
|
5027
5576
|
})
|
|
5028
5577
|
);
|
|
5029
5578
|
const input2 = {
|
|
5030
|
-
task
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
parameters: options.params
|
|
5579
|
+
task,
|
|
5580
|
+
parameters: options.params,
|
|
5581
|
+
files: fileInputs.length > 0 ? fileInputs : void 0
|
|
5034
5582
|
};
|
|
5035
5583
|
if (options.json) {
|
|
5036
5584
|
const output = await harness.runToCompletion(input2);
|
|
@@ -5079,15 +5627,17 @@ var runInteractive = async (workingDir, params) => {
|
|
|
5079
5627
|
}
|
|
5080
5628
|
});
|
|
5081
5629
|
};
|
|
5630
|
+
const uploadStore = await createUploadStore(config?.uploads, workingDir);
|
|
5082
5631
|
const harness = new AgentHarness({
|
|
5083
5632
|
workingDir,
|
|
5084
5633
|
environment: resolveHarnessEnvironment(),
|
|
5085
|
-
approvalHandler
|
|
5634
|
+
approvalHandler,
|
|
5635
|
+
uploadStore
|
|
5086
5636
|
});
|
|
5087
5637
|
await harness.initialize();
|
|
5088
5638
|
const identity = await ensureAgentIdentity2(workingDir);
|
|
5089
5639
|
try {
|
|
5090
|
-
const { runInteractiveInk } = await import("./run-interactive-ink-
|
|
5640
|
+
const { runInteractiveInk } = await import("./run-interactive-ink-7FP5PT7Q.js");
|
|
5091
5641
|
await runInteractiveInk({
|
|
5092
5642
|
harness,
|
|
5093
5643
|
params,
|