@productmaker/mcp 2.9.3 → 2.10.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/README.md +64 -57
- package/dist/http.js +2087 -1004
- package/dist/stdio.js +2087 -1004
- package/dist/ui/meta-upload-app.html +196 -45
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
6
|
<meta name="color-scheme" content="light dark" />
|
|
7
|
-
<title>
|
|
7
|
+
<title>Upload media · ProductMaker</title>
|
|
8
8
|
<style>
|
|
9
9
|
:root {
|
|
10
10
|
color-scheme: light dark;
|
|
@@ -98,10 +98,8 @@
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
.upload-feedback {
|
|
101
|
-
display:
|
|
102
|
-
|
|
103
|
-
flex-wrap: wrap;
|
|
104
|
-
gap: 10px;
|
|
101
|
+
display: grid;
|
|
102
|
+
gap: 8px;
|
|
105
103
|
margin-top: 10px;
|
|
106
104
|
}
|
|
107
105
|
|
|
@@ -202,21 +200,31 @@
|
|
|
202
200
|
cursor: not-allowed;
|
|
203
201
|
}
|
|
204
202
|
|
|
205
|
-
.
|
|
206
|
-
display: grid;
|
|
207
|
-
width: 48px;
|
|
208
|
-
height: 48px;
|
|
209
|
-
place-items: center;
|
|
210
|
-
border: 1px solid var(--pm-line);
|
|
211
|
-
border-radius: 50%;
|
|
212
|
-
background: var(--pm-card);
|
|
213
|
-
box-shadow: 0 7px 20px rgb(27 36 66 / 8%);
|
|
203
|
+
.add-symbol {
|
|
214
204
|
color: var(--pm-text);
|
|
215
|
-
font-size:
|
|
216
|
-
font-weight:
|
|
205
|
+
font-size: 44px;
|
|
206
|
+
font-weight: 300;
|
|
217
207
|
line-height: 1;
|
|
218
208
|
}
|
|
219
209
|
|
|
210
|
+
.complete-button {
|
|
211
|
+
justify-self: start;
|
|
212
|
+
min-width: 76px;
|
|
213
|
+
margin-top: 10px;
|
|
214
|
+
padding: 10px 20px;
|
|
215
|
+
border: 0;
|
|
216
|
+
border-radius: 12px;
|
|
217
|
+
background: var(--pm-primary);
|
|
218
|
+
color: #ffffff;
|
|
219
|
+
cursor: pointer;
|
|
220
|
+
font-weight: 780;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.complete-button:disabled {
|
|
224
|
+
cursor: not-allowed;
|
|
225
|
+
opacity: 0.5;
|
|
226
|
+
}
|
|
227
|
+
|
|
220
228
|
.drop-help {
|
|
221
229
|
position: absolute;
|
|
222
230
|
width: 1px;
|
|
@@ -447,7 +455,7 @@
|
|
|
447
455
|
aria-label="Agregar otro archivo"
|
|
448
456
|
disabled
|
|
449
457
|
>
|
|
450
|
-
<span class="
|
|
458
|
+
<span class="add-symbol" aria-hidden="true">+</span>
|
|
451
459
|
</button>
|
|
452
460
|
<button
|
|
453
461
|
class="compatibility-control"
|
|
@@ -493,6 +501,15 @@
|
|
|
493
501
|
aria-live="polite"
|
|
494
502
|
></p>
|
|
495
503
|
</div>
|
|
504
|
+
<button
|
|
505
|
+
class="complete-button"
|
|
506
|
+
type="button"
|
|
507
|
+
data-testid="meta-upload-complete-btn"
|
|
508
|
+
hidden
|
|
509
|
+
disabled
|
|
510
|
+
>
|
|
511
|
+
OK
|
|
512
|
+
</button>
|
|
496
513
|
</section>
|
|
497
514
|
</article>
|
|
498
515
|
</main>
|
|
@@ -548,6 +565,9 @@
|
|
|
548
565
|
batchError: document.querySelector(
|
|
549
566
|
'[data-testid="meta-upload-batch-error"]',
|
|
550
567
|
),
|
|
568
|
+
completeButton: document.querySelector(
|
|
569
|
+
'[data-testid="meta-upload-complete-btn"]',
|
|
570
|
+
),
|
|
551
571
|
fileList: document.querySelector(
|
|
552
572
|
'[data-testid="meta-upload-file-list"]',
|
|
553
573
|
),
|
|
@@ -643,6 +663,38 @@
|
|
|
643
663
|
scheduleIntrinsicSizeReport(true);
|
|
644
664
|
}
|
|
645
665
|
|
|
666
|
+
function canMessageHost() {
|
|
667
|
+
return (
|
|
668
|
+
hasOpenAiFunction("sendFollowUpMessage") || state.hostCanMessage
|
|
669
|
+
);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
function canCompleteUpload() {
|
|
673
|
+
return (
|
|
674
|
+
!state.disposed &&
|
|
675
|
+
Boolean(state.session) &&
|
|
676
|
+
!sessionExpired() &&
|
|
677
|
+
!state.busyBatch &&
|
|
678
|
+
!state.completionNotified &&
|
|
679
|
+
!state.completionNotificationInFlight &&
|
|
680
|
+
state.assets.length > 0 &&
|
|
681
|
+
state.items.length > 0 &&
|
|
682
|
+
state.assets.length === state.items.length &&
|
|
683
|
+
state.items.every((item) => item.status === "uploaded") &&
|
|
684
|
+
canMessageHost()
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
function renderCompletionAction() {
|
|
689
|
+
const hasVerifiedAssets = state.assets.length > 0;
|
|
690
|
+
elements.completeButton.hidden =
|
|
691
|
+
state.completionNotified || !hasVerifiedAssets || !canMessageHost();
|
|
692
|
+
elements.completeButton.disabled = !canCompleteUpload();
|
|
693
|
+
elements.completeButton.textContent =
|
|
694
|
+
state.completionNotificationInFlight ? "…" : "OK";
|
|
695
|
+
scheduleIntrinsicSizeReport(true);
|
|
696
|
+
}
|
|
697
|
+
|
|
646
698
|
function parseFinitePositiveNumber(value) {
|
|
647
699
|
return typeof value === "number" &&
|
|
648
700
|
Number.isFinite(value) &&
|
|
@@ -861,6 +913,8 @@
|
|
|
861
913
|
!state.session ||
|
|
862
914
|
sessionExpired() ||
|
|
863
915
|
state.uploadBlocked ||
|
|
916
|
+
state.completionNotified ||
|
|
917
|
+
state.completionNotificationInFlight ||
|
|
864
918
|
state.busyBatch ||
|
|
865
919
|
state.items.length >= safeSessionLimit();
|
|
866
920
|
elements.input.disabled = disabled;
|
|
@@ -957,7 +1011,7 @@
|
|
|
957
1011
|
async function initializeStandardHost() {
|
|
958
1012
|
try {
|
|
959
1013
|
const result = await rpcRequest("ui/initialize", {
|
|
960
|
-
appInfo: { name: "ProductMaker
|
|
1014
|
+
appInfo: { name: "ProductMaker media upload", version: "1.0.0" },
|
|
961
1015
|
appCapabilities: {
|
|
962
1016
|
availableDisplayModes: ["inline", "fullscreen"],
|
|
963
1017
|
},
|
|
@@ -1081,6 +1135,17 @@
|
|
|
1081
1135
|
const sessionChanged =
|
|
1082
1136
|
!state.session || state.session.sessionId !== session.sessionId;
|
|
1083
1137
|
if (sessionChanged) {
|
|
1138
|
+
abortActiveWork();
|
|
1139
|
+
for (const item of state.items) revokePreviewUrl(item);
|
|
1140
|
+
state.items = [];
|
|
1141
|
+
state.assets = [];
|
|
1142
|
+
state.consumedBridgeIds.clear();
|
|
1143
|
+
state.consumingBridgeFiles = false;
|
|
1144
|
+
state.bridgeConsumptionQueued = false;
|
|
1145
|
+
state.ingestionQueue = Promise.resolve();
|
|
1146
|
+
state.busyBatch = false;
|
|
1147
|
+
elements.input.value = "";
|
|
1148
|
+
renderItems();
|
|
1084
1149
|
state.uploadBlocked = false;
|
|
1085
1150
|
state.fallbackRequired = false;
|
|
1086
1151
|
state.completionNotified = false;
|
|
@@ -1103,6 +1168,7 @@
|
|
|
1103
1168
|
setSessionStatus("Sesión lista para recibir archivos.", "neutral");
|
|
1104
1169
|
}
|
|
1105
1170
|
setPickerAvailability();
|
|
1171
|
+
renderCompletionAction();
|
|
1106
1172
|
void consumePendingBridgeFiles();
|
|
1107
1173
|
scheduleIntrinsicSizeReport(true);
|
|
1108
1174
|
}
|
|
@@ -1113,6 +1179,15 @@
|
|
|
1113
1179
|
const mediaKind = candidate.mediaKind;
|
|
1114
1180
|
const assetRole = candidate.assetRole;
|
|
1115
1181
|
const expiresAt = boundedString(candidate.expiresAt, 100);
|
|
1182
|
+
const checkToolName = [
|
|
1183
|
+
"check_media_upload",
|
|
1184
|
+
"check_meta_media_upload",
|
|
1185
|
+
].includes(candidate.checkToolName)
|
|
1186
|
+
? candidate.checkToolName
|
|
1187
|
+
: "check_meta_media_upload";
|
|
1188
|
+
const resolveEndpoint =
|
|
1189
|
+
boundedString(candidate.resolveEndpoint, 200) ||
|
|
1190
|
+
"/api/meta-upload/resolve";
|
|
1116
1191
|
if (!sessionId || !["image", "video", "mixed"].includes(mediaKind))
|
|
1117
1192
|
return null;
|
|
1118
1193
|
if (!["media", "thumbnail"].includes(assetRole)) return null;
|
|
@@ -1130,6 +1205,8 @@
|
|
|
1130
1205
|
assetRole,
|
|
1131
1206
|
maxFiles: candidate.maxFiles,
|
|
1132
1207
|
expiresAt,
|
|
1208
|
+
checkToolName,
|
|
1209
|
+
resolveEndpoint,
|
|
1133
1210
|
};
|
|
1134
1211
|
}
|
|
1135
1212
|
|
|
@@ -1218,7 +1295,9 @@
|
|
|
1218
1295
|
state.disposed ||
|
|
1219
1296
|
!state.session ||
|
|
1220
1297
|
sessionExpired() ||
|
|
1221
|
-
state.uploadBlocked
|
|
1298
|
+
state.uploadBlocked ||
|
|
1299
|
+
state.completionNotified ||
|
|
1300
|
+
state.completionNotificationInFlight
|
|
1222
1301
|
)
|
|
1223
1302
|
return;
|
|
1224
1303
|
state.workCancelled = false;
|
|
@@ -1237,7 +1316,9 @@
|
|
|
1237
1316
|
state.disposed ||
|
|
1238
1317
|
!state.session ||
|
|
1239
1318
|
sessionExpired() ||
|
|
1240
|
-
state.uploadBlocked
|
|
1319
|
+
state.uploadBlocked ||
|
|
1320
|
+
state.completionNotified ||
|
|
1321
|
+
state.completionNotificationInFlight
|
|
1241
1322
|
)
|
|
1242
1323
|
return;
|
|
1243
1324
|
const bridge = openAiBridge();
|
|
@@ -1411,6 +1492,8 @@
|
|
|
1411
1492
|
!state.session ||
|
|
1412
1493
|
sessionExpired() ||
|
|
1413
1494
|
state.uploadBlocked ||
|
|
1495
|
+
state.completionNotified ||
|
|
1496
|
+
state.completionNotificationInFlight ||
|
|
1414
1497
|
state.busyBatch
|
|
1415
1498
|
)
|
|
1416
1499
|
return;
|
|
@@ -1430,7 +1513,10 @@
|
|
|
1430
1513
|
if (!selected.length) return;
|
|
1431
1514
|
|
|
1432
1515
|
state.busyBatch = true;
|
|
1516
|
+
state.assets = [];
|
|
1517
|
+
state.completionNotified = false;
|
|
1433
1518
|
setPickerAvailability();
|
|
1519
|
+
renderCompletionAction();
|
|
1434
1520
|
for (const file of selected) {
|
|
1435
1521
|
const mediaKind = mediaKindForType(file.type) || "image";
|
|
1436
1522
|
const item = createItem(file, mediaKind);
|
|
@@ -1440,6 +1526,7 @@
|
|
|
1440
1526
|
}
|
|
1441
1527
|
state.busyBatch = false;
|
|
1442
1528
|
setPickerAvailability();
|
|
1529
|
+
renderCompletionAction();
|
|
1443
1530
|
if (state.items.some((item) => item.status === "uploaded")) {
|
|
1444
1531
|
await refreshSessionStatus();
|
|
1445
1532
|
}
|
|
@@ -1458,7 +1545,7 @@
|
|
|
1458
1545
|
attempts: 0,
|
|
1459
1546
|
error: "",
|
|
1460
1547
|
failureStage: "",
|
|
1461
|
-
|
|
1548
|
+
assetId: "",
|
|
1462
1549
|
previewUrl: "",
|
|
1463
1550
|
};
|
|
1464
1551
|
}
|
|
@@ -1756,7 +1843,7 @@
|
|
|
1756
1843
|
renderItems();
|
|
1757
1844
|
},
|
|
1758
1845
|
);
|
|
1759
|
-
item.
|
|
1846
|
+
item.assetId = resolved.assetId;
|
|
1760
1847
|
return;
|
|
1761
1848
|
} catch (error) {
|
|
1762
1849
|
if (error && error.message === "session_expired") throw error;
|
|
@@ -1777,14 +1864,16 @@
|
|
|
1777
1864
|
const uploadPage = new URL(state.session.uploadPageUrl);
|
|
1778
1865
|
if (!safeUploadPageUrl(uploadPage))
|
|
1779
1866
|
throw new Error("unsafe_upload_page");
|
|
1780
|
-
const token =
|
|
1867
|
+
const token =
|
|
1868
|
+
uploadPage.searchParams.get("token") ||
|
|
1869
|
+
new URLSearchParams(uploadPage.hash.slice(1)).get("token");
|
|
1781
1870
|
if (!token) {
|
|
1782
1871
|
const error = new Error("missing_token");
|
|
1783
1872
|
error.safeStage = "resolve";
|
|
1784
1873
|
throw error;
|
|
1785
1874
|
}
|
|
1786
1875
|
const resolveUrl = new URL(
|
|
1787
|
-
|
|
1876
|
+
state.session.resolveEndpoint,
|
|
1788
1877
|
uploadPage.origin,
|
|
1789
1878
|
);
|
|
1790
1879
|
const response = await fetch(resolveUrl.toString(), {
|
|
@@ -1812,14 +1901,17 @@
|
|
|
1812
1901
|
const body = await response.json();
|
|
1813
1902
|
if (!isRecord(body)) throw new Error("invalid_resolve_response");
|
|
1814
1903
|
const uploadUrl = boundedString(body.uploadUrl, 3000);
|
|
1815
|
-
const
|
|
1904
|
+
const assetId = boundedString(
|
|
1905
|
+
body.assetId || body.stagingAssetId,
|
|
1906
|
+
300,
|
|
1907
|
+
);
|
|
1816
1908
|
const parsedUploadUrl = new URL(uploadUrl);
|
|
1817
|
-
if (!safeWebProtocol(parsedUploadUrl) || !
|
|
1909
|
+
if (!safeWebProtocol(parsedUploadUrl) || !assetId) {
|
|
1818
1910
|
const error = new Error("invalid_resolve_response");
|
|
1819
1911
|
error.safeStage = "resolve";
|
|
1820
1912
|
throw error;
|
|
1821
1913
|
}
|
|
1822
|
-
return { uploadUrl: parsedUploadUrl.toString(),
|
|
1914
|
+
return { uploadUrl: parsedUploadUrl.toString(), assetId };
|
|
1823
1915
|
}
|
|
1824
1916
|
|
|
1825
1917
|
function createClientUuid() {
|
|
@@ -2085,6 +2177,7 @@
|
|
|
2085
2177
|
fragment.append(card);
|
|
2086
2178
|
});
|
|
2087
2179
|
elements.fileList.replaceChildren(fragment);
|
|
2180
|
+
renderCompletionAction();
|
|
2088
2181
|
scheduleIntrinsicSizeReport(true);
|
|
2089
2182
|
}
|
|
2090
2183
|
|
|
@@ -2098,13 +2191,21 @@
|
|
|
2098
2191
|
|
|
2099
2192
|
async function refreshSessionStatus() {
|
|
2100
2193
|
if (!state.session) return;
|
|
2194
|
+
const requestedSessionId = state.session.sessionId;
|
|
2101
2195
|
setSessionStatus("Comprobando el staging privado…", "neutral");
|
|
2102
2196
|
try {
|
|
2103
|
-
const result = await callReadOnlyTool(
|
|
2104
|
-
sessionId:
|
|
2197
|
+
const result = await callReadOnlyTool(state.session.checkToolName, {
|
|
2198
|
+
sessionId: requestedSessionId,
|
|
2105
2199
|
});
|
|
2106
|
-
|
|
2200
|
+
if (
|
|
2201
|
+
state.disposed ||
|
|
2202
|
+
!state.session ||
|
|
2203
|
+
state.session.sessionId !== requestedSessionId
|
|
2204
|
+
)
|
|
2205
|
+
return;
|
|
2206
|
+
const status = parseStatusResult(result, requestedSessionId);
|
|
2107
2207
|
state.assets = status.assets;
|
|
2208
|
+
renderCompletionAction();
|
|
2108
2209
|
if (!status.assets.length) {
|
|
2109
2210
|
if (status.legacyKindAmbiguous) {
|
|
2110
2211
|
requireFallback(
|
|
@@ -2138,7 +2239,6 @@
|
|
|
2138
2239
|
: "Carga completada.",
|
|
2139
2240
|
partial ? "warning" : "success",
|
|
2140
2241
|
);
|
|
2141
|
-
await notifyChatUploadComplete();
|
|
2142
2242
|
} catch (error) {
|
|
2143
2243
|
const expired =
|
|
2144
2244
|
sessionExpired() ||
|
|
@@ -2155,7 +2255,9 @@
|
|
|
2155
2255
|
}
|
|
2156
2256
|
|
|
2157
2257
|
async function callReadOnlyTool(name, args) {
|
|
2158
|
-
if (
|
|
2258
|
+
if (
|
|
2259
|
+
!["check_media_upload", "check_meta_media_upload"].includes(name)
|
|
2260
|
+
) {
|
|
2159
2261
|
throw new Error("tool_not_allowed");
|
|
2160
2262
|
}
|
|
2161
2263
|
const bridge = openAiBridge();
|
|
@@ -2200,18 +2302,26 @@
|
|
|
2200
2302
|
return parsed;
|
|
2201
2303
|
}
|
|
2202
2304
|
|
|
2203
|
-
function parseStatusResult(result) {
|
|
2305
|
+
function parseStatusResult(result, expectedSessionId) {
|
|
2204
2306
|
const payload = resultPayload(result);
|
|
2307
|
+
if (
|
|
2308
|
+
state.session.checkToolName === "check_meta_media_upload" &&
|
|
2309
|
+
payload.sessionId !== expectedSessionId
|
|
2310
|
+
)
|
|
2311
|
+
throw new Error("status_session_mismatch");
|
|
2205
2312
|
const status = payload.status;
|
|
2206
2313
|
if (!["pending", "uploaded"].includes(status))
|
|
2207
2314
|
throw new Error("invalid_status");
|
|
2208
2315
|
const assets = Array.isArray(payload.assets)
|
|
2209
2316
|
? payload.assets.slice(0, MAX_FILES).flatMap((asset) => {
|
|
2210
2317
|
if (!isRecord(asset)) return [];
|
|
2211
|
-
const
|
|
2318
|
+
const assetId = boundedString(
|
|
2319
|
+
asset.assetId || asset.stagingAssetId,
|
|
2320
|
+
300,
|
|
2321
|
+
);
|
|
2212
2322
|
const mediaKind = asset.mediaKind;
|
|
2213
|
-
return
|
|
2214
|
-
? [{
|
|
2323
|
+
return assetId && ["image", "video"].includes(mediaKind)
|
|
2324
|
+
? [{ assetId, mediaKind }]
|
|
2215
2325
|
: [];
|
|
2216
2326
|
})
|
|
2217
2327
|
: [];
|
|
@@ -2236,7 +2346,7 @@
|
|
|
2236
2346
|
: null;
|
|
2237
2347
|
if (inferredMediaKind) {
|
|
2238
2348
|
assets.push({
|
|
2239
|
-
|
|
2349
|
+
assetId: legacyStagingAssetId,
|
|
2240
2350
|
mediaKind: inferredMediaKind,
|
|
2241
2351
|
});
|
|
2242
2352
|
} else {
|
|
@@ -2253,38 +2363,79 @@
|
|
|
2253
2363
|
!state.session
|
|
2254
2364
|
)
|
|
2255
2365
|
return;
|
|
2366
|
+
const completionSessionId = state.session.sessionId;
|
|
2256
2367
|
state.completionNotificationInFlight = true;
|
|
2257
|
-
|
|
2258
|
-
|
|
2368
|
+
setPickerAvailability();
|
|
2369
|
+
renderCompletionAction();
|
|
2370
|
+
const assets = state.assets
|
|
2371
|
+
.map((asset) => `${asset.mediaKind} asset_id ${asset.assetId}`)
|
|
2372
|
+
.join(", ");
|
|
2373
|
+
const metaGuard =
|
|
2374
|
+
state.session.checkToolName === "check_meta_media_upload"
|
|
2375
|
+
? " Do not publish anything until you have asked me for the Meta portfolio, ad account, and Facebook Page."
|
|
2376
|
+
: "";
|
|
2377
|
+
const message = `The ProductMaker upload is complete. Continue my previous request using these uploaded assets: ${assets}. Do not ask me to upload them again.${metaGuard}`;
|
|
2259
2378
|
try {
|
|
2260
2379
|
const bridge = openAiBridge();
|
|
2261
2380
|
if (bridge && typeof bridge.sendFollowUpMessage === "function") {
|
|
2262
2381
|
await bridge.sendFollowUpMessage({ prompt: message });
|
|
2382
|
+
if (
|
|
2383
|
+
!state.session ||
|
|
2384
|
+
state.session.sessionId !== completionSessionId
|
|
2385
|
+
)
|
|
2386
|
+
return;
|
|
2263
2387
|
state.completionNotified = true;
|
|
2388
|
+
setPickerAvailability();
|
|
2389
|
+
renderCompletionAction();
|
|
2264
2390
|
return;
|
|
2265
2391
|
}
|
|
2266
2392
|
if (state.hostCanMessage) {
|
|
2267
|
-
await rpcRequest("ui/message", {
|
|
2393
|
+
const messageResult = await rpcRequest("ui/message", {
|
|
2268
2394
|
role: "user",
|
|
2269
2395
|
content: [{ type: "text", text: message }],
|
|
2270
2396
|
});
|
|
2397
|
+
if (isRecord(messageResult) && messageResult.isError === true)
|
|
2398
|
+
throw new Error("host_message_rejected");
|
|
2399
|
+
if (
|
|
2400
|
+
!state.session ||
|
|
2401
|
+
state.session.sessionId !== completionSessionId
|
|
2402
|
+
)
|
|
2403
|
+
return;
|
|
2271
2404
|
state.completionNotified = true;
|
|
2405
|
+
setPickerAvailability();
|
|
2406
|
+
renderCompletionAction();
|
|
2272
2407
|
return;
|
|
2273
2408
|
}
|
|
2274
2409
|
setSessionStatus(
|
|
2275
|
-
"
|
|
2276
|
-
"
|
|
2410
|
+
"La carga terminó, pero este host no puede continuar el chat desde el widget. Vuelve al chat para seguir.",
|
|
2411
|
+
"warning",
|
|
2277
2412
|
);
|
|
2278
2413
|
} catch {
|
|
2414
|
+
if (
|
|
2415
|
+
!state.session ||
|
|
2416
|
+
state.session.sessionId !== completionSessionId
|
|
2417
|
+
)
|
|
2418
|
+
return;
|
|
2279
2419
|
setSessionStatus(
|
|
2280
|
-
"
|
|
2281
|
-
"
|
|
2420
|
+
"No pudimos continuar el chat. Intenta nuevamente.",
|
|
2421
|
+
"danger",
|
|
2282
2422
|
);
|
|
2283
2423
|
} finally {
|
|
2284
|
-
|
|
2424
|
+
if (
|
|
2425
|
+
state.session &&
|
|
2426
|
+
state.session.sessionId === completionSessionId
|
|
2427
|
+
) {
|
|
2428
|
+
state.completionNotificationInFlight = false;
|
|
2429
|
+
setPickerAvailability();
|
|
2430
|
+
renderCompletionAction();
|
|
2431
|
+
}
|
|
2285
2432
|
}
|
|
2286
2433
|
}
|
|
2287
2434
|
|
|
2435
|
+
elements.completeButton.addEventListener("click", () => {
|
|
2436
|
+
if (canCompleteUpload()) void notifyChatUploadComplete();
|
|
2437
|
+
});
|
|
2438
|
+
|
|
2288
2439
|
document.addEventListener("DOMContentLoaded", initialize, {
|
|
2289
2440
|
once: true,
|
|
2290
2441
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@productmaker/mcp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Product Maker MCP server — cost products, generate dropshipping landing pages, UGC videos, and ad creatives, and publish to Shopify and Meta Ads from Claude, ChatGPT, or Gemini.",
|