@poncho-ai/cli 0.10.2 → 0.11.0
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 +12 -0
- package/dist/{chunk-COLXQM6J.js → chunk-6GFL3VYM.js} +578 -45
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{run-interactive-ink-Z3U5SV4C.js → run-interactive-ink-QR3RIAJH.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 +374 -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,83 @@ 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
|
+
// Lightbox: open/close helpers
|
|
2859
|
+
const lightboxImg = elements.lightbox.querySelector("img");
|
|
2860
|
+
const openLightbox = (src) => {
|
|
2861
|
+
lightboxImg.src = src;
|
|
2862
|
+
elements.lightbox.style.display = "flex";
|
|
2863
|
+
requestAnimationFrame(() => {
|
|
2864
|
+
requestAnimationFrame(() => elements.lightbox.classList.add("active"));
|
|
2865
|
+
});
|
|
2866
|
+
};
|
|
2867
|
+
const closeLightbox = () => {
|
|
2868
|
+
elements.lightbox.classList.remove("active");
|
|
2869
|
+
elements.lightbox.addEventListener("transitionend", function handler() {
|
|
2870
|
+
elements.lightbox.removeEventListener("transitionend", handler);
|
|
2871
|
+
elements.lightbox.style.display = "none";
|
|
2872
|
+
lightboxImg.src = "";
|
|
2873
|
+
});
|
|
2874
|
+
};
|
|
2875
|
+
elements.lightbox.addEventListener("click", closeLightbox);
|
|
2876
|
+
document.addEventListener("keydown", (e) => {
|
|
2877
|
+
if (e.key === "Escape" && elements.lightbox.style.display !== "none") closeLightbox();
|
|
2878
|
+
});
|
|
2879
|
+
|
|
2880
|
+
// Lightbox from message images
|
|
2881
|
+
elements.messages.addEventListener("click", (e) => {
|
|
2882
|
+
const img = e.target;
|
|
2883
|
+
if (!(img instanceof HTMLImageElement) || !img.closest(".user-file-attachments")) return;
|
|
2884
|
+
openLightbox(img.src);
|
|
2885
|
+
});
|
|
2886
|
+
|
|
2887
|
+
// Lightbox from attachment preview chips
|
|
2888
|
+
elements.attachmentPreview.addEventListener("click", (e) => {
|
|
2889
|
+
if (e.target.closest(".remove-attachment")) return;
|
|
2890
|
+
const chip = e.target.closest(".attachment-chip");
|
|
2891
|
+
if (!chip) return;
|
|
2892
|
+
const img = chip.querySelector("img");
|
|
2893
|
+
if (!img) return;
|
|
2894
|
+
e.stopPropagation();
|
|
2895
|
+
openLightbox(img.src);
|
|
2896
|
+
});
|
|
2897
|
+
|
|
2537
2898
|
elements.messages.addEventListener("click", async (event) => {
|
|
2538
2899
|
const target = event.target;
|
|
2539
2900
|
if (!(target instanceof Element)) {
|
|
@@ -3374,6 +3735,24 @@ var writeHtml = (response, statusCode, payload) => {
|
|
|
3374
3735
|
response.writeHead(statusCode, { "Content-Type": "text/html; charset=utf-8" });
|
|
3375
3736
|
response.end(payload);
|
|
3376
3737
|
};
|
|
3738
|
+
var EXT_MIME_MAP = {
|
|
3739
|
+
jpg: "image/jpeg",
|
|
3740
|
+
jpeg: "image/jpeg",
|
|
3741
|
+
png: "image/png",
|
|
3742
|
+
gif: "image/gif",
|
|
3743
|
+
webp: "image/webp",
|
|
3744
|
+
svg: "image/svg+xml",
|
|
3745
|
+
pdf: "application/pdf",
|
|
3746
|
+
mp4: "video/mp4",
|
|
3747
|
+
webm: "video/webm",
|
|
3748
|
+
mp3: "audio/mpeg",
|
|
3749
|
+
wav: "audio/wav",
|
|
3750
|
+
txt: "text/plain",
|
|
3751
|
+
json: "application/json",
|
|
3752
|
+
csv: "text/csv",
|
|
3753
|
+
html: "text/html"
|
|
3754
|
+
};
|
|
3755
|
+
var extToMime = (ext) => EXT_MIME_MAP[ext] ?? "application/octet-stream";
|
|
3377
3756
|
var readRequestBody = async (request) => {
|
|
3378
3757
|
const chunks = [];
|
|
3379
3758
|
for await (const chunk of request) {
|
|
@@ -3382,6 +3761,38 @@ var readRequestBody = async (request) => {
|
|
|
3382
3761
|
const body = Buffer.concat(chunks).toString("utf8");
|
|
3383
3762
|
return body.length > 0 ? JSON.parse(body) : {};
|
|
3384
3763
|
};
|
|
3764
|
+
var MAX_UPLOAD_SIZE = 25 * 1024 * 1024;
|
|
3765
|
+
var parseMultipartRequest = (request) => new Promise((resolve4, reject) => {
|
|
3766
|
+
const result = { message: "", files: [] };
|
|
3767
|
+
const bb = Busboy({
|
|
3768
|
+
headers: request.headers,
|
|
3769
|
+
limits: { fileSize: MAX_UPLOAD_SIZE }
|
|
3770
|
+
});
|
|
3771
|
+
bb.on("field", (name, value) => {
|
|
3772
|
+
if (name === "message") result.message = value;
|
|
3773
|
+
if (name === "parameters") {
|
|
3774
|
+
try {
|
|
3775
|
+
result.parameters = JSON.parse(value);
|
|
3776
|
+
} catch {
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
});
|
|
3780
|
+
bb.on("file", (_name, stream, info) => {
|
|
3781
|
+
const chunks = [];
|
|
3782
|
+
stream.on("data", (chunk) => chunks.push(chunk));
|
|
3783
|
+
stream.on("end", () => {
|
|
3784
|
+
const buf = Buffer.concat(chunks);
|
|
3785
|
+
result.files.push({
|
|
3786
|
+
data: buf.toString("base64"),
|
|
3787
|
+
mediaType: info.mimeType,
|
|
3788
|
+
filename: info.filename
|
|
3789
|
+
});
|
|
3790
|
+
});
|
|
3791
|
+
});
|
|
3792
|
+
bb.on("finish", () => resolve4(result));
|
|
3793
|
+
bb.on("error", (err) => reject(err));
|
|
3794
|
+
request.pipe(bb);
|
|
3795
|
+
});
|
|
3385
3796
|
var resolveHarnessEnvironment = () => {
|
|
3386
3797
|
if (process.env.PONCHO_ENV) {
|
|
3387
3798
|
const value = process.env.PONCHO_ENV.toLowerCase();
|
|
@@ -3903,7 +4314,14 @@ var writeScaffoldFile = async (filePath, content, options) => {
|
|
|
3903
4314
|
await writeFile3(filePath, content, "utf8");
|
|
3904
4315
|
options.writtenPaths.push(relative(options.baseDir, filePath));
|
|
3905
4316
|
};
|
|
3906
|
-
var
|
|
4317
|
+
var UPLOAD_PROVIDER_DEPS = {
|
|
4318
|
+
"vercel-blob": [{ name: "@vercel/blob", fallback: "^2.3.0" }],
|
|
4319
|
+
s3: [
|
|
4320
|
+
{ name: "@aws-sdk/client-s3", fallback: "^3.700.0" },
|
|
4321
|
+
{ name: "@aws-sdk/s3-request-presigner", fallback: "^3.700.0" }
|
|
4322
|
+
]
|
|
4323
|
+
};
|
|
4324
|
+
var ensureRuntimeCliDependency = async (projectDir, cliVersion, config) => {
|
|
3907
4325
|
const packageJsonPath = resolve3(projectDir, "package.json");
|
|
3908
4326
|
const content = await readFile3(packageJsonPath, "utf8");
|
|
3909
4327
|
const parsed = JSON.parse(content);
|
|
@@ -3917,10 +4335,20 @@ var ensureRuntimeCliDependency = async (projectDir, cliVersion) => {
|
|
|
3917
4335
|
}
|
|
3918
4336
|
dependencies.marked = await readCliDependencyVersion("marked", "^17.0.2");
|
|
3919
4337
|
dependencies["@poncho-ai/cli"] = `^${cliVersion}`;
|
|
4338
|
+
const addedDeps = [];
|
|
4339
|
+
const uploadsProvider = config?.uploads?.provider;
|
|
4340
|
+
if (uploadsProvider && UPLOAD_PROVIDER_DEPS[uploadsProvider]) {
|
|
4341
|
+
for (const dep of UPLOAD_PROVIDER_DEPS[uploadsProvider]) {
|
|
4342
|
+
if (!dependencies[dep.name]) {
|
|
4343
|
+
dependencies[dep.name] = dep.fallback;
|
|
4344
|
+
addedDeps.push(dep.name);
|
|
4345
|
+
}
|
|
4346
|
+
}
|
|
4347
|
+
}
|
|
3920
4348
|
parsed.dependencies = dependencies;
|
|
3921
4349
|
await writeFile3(packageJsonPath, `${JSON.stringify(parsed, null, 2)}
|
|
3922
4350
|
`, "utf8");
|
|
3923
|
-
return [relative(projectDir, packageJsonPath)];
|
|
4351
|
+
return { paths: [relative(projectDir, packageJsonPath)], addedDeps };
|
|
3924
4352
|
};
|
|
3925
4353
|
var scaffoldDeployTarget = async (projectDir, target, options) => {
|
|
3926
4354
|
const writtenPaths = [];
|
|
@@ -4053,10 +4481,16 @@ CMD ["node","server.js"]
|
|
|
4053
4481
|
baseDir: projectDir
|
|
4054
4482
|
});
|
|
4055
4483
|
}
|
|
4056
|
-
const
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4484
|
+
const config = await loadPonchoConfig(projectDir);
|
|
4485
|
+
const { paths: packagePaths, addedDeps } = await ensureRuntimeCliDependency(
|
|
4486
|
+
projectDir,
|
|
4487
|
+
cliVersion,
|
|
4488
|
+
config
|
|
4489
|
+
);
|
|
4490
|
+
const depNote = addedDeps.length > 0 ? ` (added ${addedDeps.join(", ")})` : "";
|
|
4491
|
+
for (const p of packagePaths) {
|
|
4492
|
+
if (!writtenPaths.includes(p)) {
|
|
4493
|
+
writtenPaths.push(depNote ? `${p}${depNote}` : p);
|
|
4060
4494
|
}
|
|
4061
4495
|
}
|
|
4062
4496
|
return writtenPaths;
|
|
@@ -4312,9 +4746,11 @@ var createRequestHandler = async (options) => {
|
|
|
4312
4746
|
}
|
|
4313
4747
|
await persistConversationPendingApprovals(conversationId);
|
|
4314
4748
|
};
|
|
4749
|
+
const uploadStore = await createUploadStore(config?.uploads, workingDir);
|
|
4315
4750
|
const harness = new AgentHarness({
|
|
4316
4751
|
workingDir,
|
|
4317
4752
|
environment: resolveHarnessEnvironment(),
|
|
4753
|
+
uploadStore,
|
|
4318
4754
|
approvalHandler: async (request) => new Promise((resolveApproval) => {
|
|
4319
4755
|
const ownerIdForRun = runOwners.get(request.runId) ?? "local-owner";
|
|
4320
4756
|
const conversationIdForRun = runConversations.get(request.runId) ?? null;
|
|
@@ -4712,6 +5148,40 @@ var createRequestHandler = async (options) => {
|
|
|
4712
5148
|
});
|
|
4713
5149
|
return;
|
|
4714
5150
|
}
|
|
5151
|
+
const uploadMatch = pathname.match(/^\/api\/uploads\/(.+)$/);
|
|
5152
|
+
if (uploadMatch && request.method === "GET") {
|
|
5153
|
+
const key = decodeURIComponent(uploadMatch[1] ?? "");
|
|
5154
|
+
try {
|
|
5155
|
+
const data = await uploadStore.get(key);
|
|
5156
|
+
const ext = key.split(".").pop() ?? "";
|
|
5157
|
+
const mimeMap = {
|
|
5158
|
+
jpg: "image/jpeg",
|
|
5159
|
+
jpeg: "image/jpeg",
|
|
5160
|
+
png: "image/png",
|
|
5161
|
+
gif: "image/gif",
|
|
5162
|
+
webp: "image/webp",
|
|
5163
|
+
svg: "image/svg+xml",
|
|
5164
|
+
pdf: "application/pdf",
|
|
5165
|
+
mp4: "video/mp4",
|
|
5166
|
+
webm: "video/webm",
|
|
5167
|
+
mp3: "audio/mpeg",
|
|
5168
|
+
wav: "audio/wav",
|
|
5169
|
+
txt: "text/plain",
|
|
5170
|
+
json: "application/json",
|
|
5171
|
+
csv: "text/csv",
|
|
5172
|
+
html: "text/html"
|
|
5173
|
+
};
|
|
5174
|
+
response.writeHead(200, {
|
|
5175
|
+
"Content-Type": mimeMap[ext] ?? "application/octet-stream",
|
|
5176
|
+
"Content-Length": data.length,
|
|
5177
|
+
"Cache-Control": "public, max-age=86400"
|
|
5178
|
+
});
|
|
5179
|
+
response.end(data);
|
|
5180
|
+
} catch {
|
|
5181
|
+
writeJson(response, 404, { code: "NOT_FOUND", message: "Upload not found" });
|
|
5182
|
+
}
|
|
5183
|
+
return;
|
|
5184
|
+
}
|
|
4715
5185
|
const conversationMessageMatch = pathname.match(/^\/api\/conversations\/([^/]+)\/messages$/);
|
|
4716
5186
|
if (conversationMessageMatch && request.method === "POST") {
|
|
4717
5187
|
const conversationId = decodeURIComponent(conversationMessageMatch[1] ?? "");
|
|
@@ -4723,8 +5193,25 @@ var createRequestHandler = async (options) => {
|
|
|
4723
5193
|
});
|
|
4724
5194
|
return;
|
|
4725
5195
|
}
|
|
4726
|
-
|
|
4727
|
-
|
|
5196
|
+
let messageText = "";
|
|
5197
|
+
let bodyParameters;
|
|
5198
|
+
let files = [];
|
|
5199
|
+
const contentType = request.headers["content-type"] ?? "";
|
|
5200
|
+
if (contentType.includes("multipart/form-data")) {
|
|
5201
|
+
const parsed = await parseMultipartRequest(request);
|
|
5202
|
+
messageText = parsed.message.trim();
|
|
5203
|
+
bodyParameters = parsed.parameters;
|
|
5204
|
+
files = parsed.files;
|
|
5205
|
+
} else {
|
|
5206
|
+
const body = await readRequestBody(request);
|
|
5207
|
+
messageText = body.message?.trim() ?? "";
|
|
5208
|
+
bodyParameters = body.parameters;
|
|
5209
|
+
if (Array.isArray(body.files)) {
|
|
5210
|
+
files = body.files.filter(
|
|
5211
|
+
(f) => typeof f.data === "string" && typeof f.mediaType === "string"
|
|
5212
|
+
);
|
|
5213
|
+
}
|
|
5214
|
+
}
|
|
4728
5215
|
if (!messageText) {
|
|
4729
5216
|
writeJson(response, 400, {
|
|
4730
5217
|
code: "VALIDATION_ERROR",
|
|
@@ -4766,8 +5253,43 @@ var createRequestHandler = async (options) => {
|
|
|
4766
5253
|
let currentText = "";
|
|
4767
5254
|
let currentTools = [];
|
|
4768
5255
|
let runCancelled = false;
|
|
5256
|
+
let userContent = messageText;
|
|
5257
|
+
if (files.length > 0) {
|
|
5258
|
+
try {
|
|
5259
|
+
const uploadedParts = await Promise.all(
|
|
5260
|
+
files.map(async (f) => {
|
|
5261
|
+
const buf = Buffer.from(f.data, "base64");
|
|
5262
|
+
const key = deriveUploadKey(buf, f.mediaType);
|
|
5263
|
+
const ref = await uploadStore.put(key, buf, f.mediaType);
|
|
5264
|
+
return {
|
|
5265
|
+
type: "file",
|
|
5266
|
+
data: ref,
|
|
5267
|
+
mediaType: f.mediaType,
|
|
5268
|
+
filename: f.filename
|
|
5269
|
+
};
|
|
5270
|
+
})
|
|
5271
|
+
);
|
|
5272
|
+
userContent = [
|
|
5273
|
+
{ type: "text", text: messageText },
|
|
5274
|
+
...uploadedParts
|
|
5275
|
+
];
|
|
5276
|
+
} catch (uploadErr) {
|
|
5277
|
+
const errMsg = uploadErr instanceof Error ? uploadErr.message : String(uploadErr);
|
|
5278
|
+
console.error("[poncho] File upload failed:", errMsg);
|
|
5279
|
+
const errorEvent = {
|
|
5280
|
+
type: "run:error",
|
|
5281
|
+
runId: "",
|
|
5282
|
+
error: { code: "UPLOAD_ERROR", message: `File upload failed: ${errMsg}` }
|
|
5283
|
+
};
|
|
5284
|
+
broadcastEvent(conversationId, errorEvent);
|
|
5285
|
+
finishConversationStream(conversationId);
|
|
5286
|
+
activeConversationRuns.delete(conversationId);
|
|
5287
|
+
response.end();
|
|
5288
|
+
return;
|
|
5289
|
+
}
|
|
5290
|
+
}
|
|
4769
5291
|
try {
|
|
4770
|
-
conversation.messages = [...historyMessages, { role: "user", content:
|
|
5292
|
+
conversation.messages = [...historyMessages, { role: "user", content: userContent }];
|
|
4771
5293
|
conversation.updatedAt = Date.now();
|
|
4772
5294
|
await conversationStore.update(conversation);
|
|
4773
5295
|
const persistDraftAssistantTurn = async () => {
|
|
@@ -4789,7 +5311,7 @@ var createRequestHandler = async (options) => {
|
|
|
4789
5311
|
}
|
|
4790
5312
|
conversation.messages = [
|
|
4791
5313
|
...historyMessages,
|
|
4792
|
-
{ role: "user", content:
|
|
5314
|
+
{ role: "user", content: userContent },
|
|
4793
5315
|
{
|
|
4794
5316
|
role: "assistant",
|
|
4795
5317
|
content: assistantResponse,
|
|
@@ -4806,16 +5328,17 @@ var createRequestHandler = async (options) => {
|
|
|
4806
5328
|
conversationId: item.conversationId,
|
|
4807
5329
|
title: item.title,
|
|
4808
5330
|
updatedAt: item.updatedAt,
|
|
4809
|
-
content: item.messages.slice(-6).map((message) => `${message.role}: ${message.content}`).join("\n").slice(0, 2e3)
|
|
5331
|
+
content: item.messages.slice(-6).map((message) => `${message.role}: ${typeof message.content === "string" ? message.content : getTextContent(message)}`).join("\n").slice(0, 2e3)
|
|
4810
5332
|
})).filter((item) => item.content.length > 0);
|
|
4811
5333
|
for await (const event of harness.runWithTelemetry({
|
|
4812
5334
|
task: messageText,
|
|
4813
5335
|
parameters: {
|
|
4814
|
-
...
|
|
5336
|
+
...bodyParameters ?? {},
|
|
4815
5337
|
__conversationRecallCorpus: recallCorpus,
|
|
4816
5338
|
__activeConversationId: conversationId
|
|
4817
5339
|
},
|
|
4818
5340
|
messages: historyMessages,
|
|
5341
|
+
files: files.length > 0 ? files : void 0,
|
|
4819
5342
|
abortSignal: abortController.signal
|
|
4820
5343
|
})) {
|
|
4821
5344
|
if (event.type === "run:started") {
|
|
@@ -4857,6 +5380,9 @@ var createRequestHandler = async (options) => {
|
|
|
4857
5380
|
toolTimeline.push(toolText);
|
|
4858
5381
|
currentTools.push(toolText);
|
|
4859
5382
|
}
|
|
5383
|
+
if (event.type === "step:completed") {
|
|
5384
|
+
await persistDraftAssistantTurn();
|
|
5385
|
+
}
|
|
4860
5386
|
if (event.type === "tool:approval:required") {
|
|
4861
5387
|
const toolText = `- approval required \`${event.tool}\``;
|
|
4862
5388
|
toolTimeline.push(toolText);
|
|
@@ -4894,7 +5420,7 @@ var createRequestHandler = async (options) => {
|
|
|
4894
5420
|
const hasAssistantContent = assistantResponse.length > 0 || toolTimeline.length > 0 || sections.length > 0;
|
|
4895
5421
|
conversation.messages = hasAssistantContent ? [
|
|
4896
5422
|
...historyMessages,
|
|
4897
|
-
{ role: "user", content:
|
|
5423
|
+
{ role: "user", content: userContent },
|
|
4898
5424
|
{
|
|
4899
5425
|
role: "assistant",
|
|
4900
5426
|
content: assistantResponse,
|
|
@@ -4903,7 +5429,7 @@ var createRequestHandler = async (options) => {
|
|
|
4903
5429
|
sections: sections.length > 0 ? sections : void 0
|
|
4904
5430
|
} : void 0
|
|
4905
5431
|
}
|
|
4906
|
-
] : [...historyMessages, { role: "user", content:
|
|
5432
|
+
] : [...historyMessages, { role: "user", content: userContent }];
|
|
4907
5433
|
conversation.runtimeRunId = latestRunId || conversation.runtimeRunId;
|
|
4908
5434
|
conversation.pendingApprovals = [];
|
|
4909
5435
|
conversation.updatedAt = Date.now();
|
|
@@ -4920,7 +5446,7 @@ var createRequestHandler = async (options) => {
|
|
|
4920
5446
|
if (assistantResponse.length > 0 || toolTimeline.length > 0 || fallbackSections.length > 0) {
|
|
4921
5447
|
conversation.messages = [
|
|
4922
5448
|
...historyMessages,
|
|
4923
|
-
{ role: "user", content:
|
|
5449
|
+
{ role: "user", content: userContent },
|
|
4924
5450
|
{
|
|
4925
5451
|
role: "assistant",
|
|
4926
5452
|
content: assistantResponse,
|
|
@@ -4958,7 +5484,7 @@ var createRequestHandler = async (options) => {
|
|
|
4958
5484
|
if (assistantResponse.length > 0 || toolTimeline.length > 0 || fallbackSections.length > 0) {
|
|
4959
5485
|
conversation.messages = [
|
|
4960
5486
|
...historyMessages,
|
|
4961
|
-
{ role: "user", content:
|
|
5487
|
+
{ role: "user", content: userContent },
|
|
4962
5488
|
{
|
|
4963
5489
|
role: "assistant",
|
|
4964
5490
|
content: assistantResponse,
|
|
@@ -5016,21 +5542,26 @@ var runOnce = async (task, options) => {
|
|
|
5016
5542
|
const workingDir = options.workingDir ?? process.cwd();
|
|
5017
5543
|
dotenv.config({ path: resolve3(workingDir, ".env") });
|
|
5018
5544
|
const config = await loadPonchoConfig(workingDir);
|
|
5019
|
-
const
|
|
5545
|
+
const uploadStore = await createUploadStore(config?.uploads, workingDir);
|
|
5546
|
+
const harness = new AgentHarness({ workingDir, uploadStore });
|
|
5020
5547
|
const telemetry = new TelemetryEmitter(config?.telemetry);
|
|
5021
5548
|
await harness.initialize();
|
|
5022
|
-
const
|
|
5023
|
-
options.filePaths.map(async (
|
|
5024
|
-
const
|
|
5025
|
-
|
|
5026
|
-
|
|
5549
|
+
const fileInputs = await Promise.all(
|
|
5550
|
+
options.filePaths.map(async (filePath) => {
|
|
5551
|
+
const absPath = resolve3(workingDir, filePath);
|
|
5552
|
+
const buf = await readFile3(absPath);
|
|
5553
|
+
const ext = absPath.split(".").pop()?.toLowerCase() ?? "";
|
|
5554
|
+
return {
|
|
5555
|
+
data: buf.toString("base64"),
|
|
5556
|
+
mediaType: extToMime(ext),
|
|
5557
|
+
filename: basename2(filePath)
|
|
5558
|
+
};
|
|
5027
5559
|
})
|
|
5028
5560
|
);
|
|
5029
5561
|
const input2 = {
|
|
5030
|
-
task
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
parameters: options.params
|
|
5562
|
+
task,
|
|
5563
|
+
parameters: options.params,
|
|
5564
|
+
files: fileInputs.length > 0 ? fileInputs : void 0
|
|
5034
5565
|
};
|
|
5035
5566
|
if (options.json) {
|
|
5036
5567
|
const output = await harness.runToCompletion(input2);
|
|
@@ -5079,15 +5610,17 @@ var runInteractive = async (workingDir, params) => {
|
|
|
5079
5610
|
}
|
|
5080
5611
|
});
|
|
5081
5612
|
};
|
|
5613
|
+
const uploadStore = await createUploadStore(config?.uploads, workingDir);
|
|
5082
5614
|
const harness = new AgentHarness({
|
|
5083
5615
|
workingDir,
|
|
5084
5616
|
environment: resolveHarnessEnvironment(),
|
|
5085
|
-
approvalHandler
|
|
5617
|
+
approvalHandler,
|
|
5618
|
+
uploadStore
|
|
5086
5619
|
});
|
|
5087
5620
|
await harness.initialize();
|
|
5088
5621
|
const identity = await ensureAgentIdentity2(workingDir);
|
|
5089
5622
|
try {
|
|
5090
|
-
const { runInteractiveInk } = await import("./run-interactive-ink-
|
|
5623
|
+
const { runInteractiveInk } = await import("./run-interactive-ink-QR3RIAJH.js");
|
|
5091
5624
|
await runInteractiveInk({
|
|
5092
5625
|
harness,
|
|
5093
5626
|
params,
|