BoxOfColors Claude Sonnet 4.6 commited on
Commit
0224191
·
1 Parent(s): d916fd2

revert: back to queue/join — call endpoint gives 404 Session not found

Browse files

/gradio_api/call/{api_name} requires a different session registration
that our queue/join session_hash doesn't satisfy, causing 404 errors.
Revert to the working queue/join + queue/data SSE approach.

The quota attribution issue (Pro vs anon) remains a known limitation —
the queue/join path with credentials:include is the best we can do
without server-side gr.Request changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (1) hide show
  1. app.py +66 -112
app.py CHANGED
@@ -2085,22 +2085,27 @@ _GLOBAL_JS = """
2085
  const lbl = document.getElementById('wf_seglabel_' + slot_id);
2086
  if (lbl) lbl.textContent = 'Regenerating Seg ' + (seg_idx + 1) + '...';
2087
 
2088
- // Use the newer /gradio_api/call/{api_name} endpoint — this is what Gradio's
2089
- // own Svelte client uses and correctly carries the HF session through the
2090
- // proxy so ZeroGPU can attribute quota to the logged-in user's Pro account.
2091
- fetch('/gradio_api/call/' + apiName, {
 
 
2092
  method: 'POST',
2093
  credentials: 'include',
2094
  headers: {'Content-Type': 'application/json'},
2095
  body: JSON.stringify({
2096
  data: data,
 
2097
  session_hash: window.__gradio_session_hash__,
 
 
2098
  })
2099
  }).then(function(r) { return r.json(); }).then(function(j) {
2100
  if (!j.event_id) { console.error('[fireRegen] no event_id:', j); return; }
2101
  console.log('[fireRegen] queued, event_id:', j.event_id);
2102
  // Subscribe to SSE stream and apply outputs when ready
2103
- _listenAndApply(j.event_id, slot_id, seg_idx, _preRegenWaveHtml, _preRegenVideoSrc, apiName);
2104
  }).catch(function(e) {
2105
  console.error('[fireRegen] fetch error:', e);
2106
  if (lbl) lbl.textContent = 'Error — see console';
@@ -2142,49 +2147,31 @@ _GLOBAL_JS = """
2142
  }, isError ? 8000 : 3000);
2143
  }
2144
 
2145
- function _listenAndApply(eventId, slot_id, seg_idx, preRegenWaveHtml, preRegenVideoSrc, apiName) {
2146
- var _pendingVideoSrc = null; // track the latest resolved video URL
2147
- // Use the call-based SSE endpoint — same one Gradio's Svelte client uses,
2148
- // so HF's proxy correctly forwards the session for ZeroGPU quota attribution.
2149
- // Message format: event: generating|complete|error, data: JSON array
2150
- const es = new EventSource('/gradio_api/call/' + apiName + '/' + eventId);
2151
- es.addEventListener('generating', function(e) {
2152
- var data;
2153
- try { data = JSON.parse(e.data); } catch(_) { return; }
2154
- // data is a plain array: [vidUpdate, waveUpdate]
2155
- var out = { data: data };
2156
- (function handleData(out) {
2157
  if (out && out.data) {
2158
- // data[0] = video update, data[1] = waveform HTML update
2159
  var vidUpdate = out.data[0];
2160
  var waveUpdate = out.data[1];
2161
-
2162
- // Extract video URL — Gradio 5 wraps final output as
2163
- // {value:{video:{url:"..."},subtitles:null},__type__:"update"}
2164
  var newSrc = null;
2165
  if (vidUpdate) {
2166
- if (vidUpdate.value && vidUpdate.value.video && vidUpdate.value.video.url) {
2167
- newSrc = vidUpdate.value.video.url; // final update shape
2168
- } else if (vidUpdate.video && vidUpdate.video.url) {
2169
- newSrc = vidUpdate.video.url; // direct shape
2170
- } else if (vidUpdate.value && vidUpdate.value.url) {
2171
- newSrc = vidUpdate.value.url; // older style
2172
- } else if (typeof vidUpdate.value === 'string') {
2173
- newSrc = vidUpdate.value;
2174
- } else if (vidUpdate.url) {
2175
- newSrc = vidUpdate.url;
2176
- }
2177
  }
2178
  if (newSrc) _pendingVideoSrc = newSrc;
2179
-
2180
- // Apply waveform HTML immediately (waveform is plain HTML, no Svelte reactivity)
2181
  var waveHtml = null;
2182
  if (waveUpdate) {
2183
- if (typeof waveUpdate === 'string') {
2184
- waveHtml = waveUpdate;
2185
- } else if (waveUpdate.value && typeof waveUpdate.value === 'string') {
2186
- waveHtml = waveUpdate.value;
2187
- }
2188
  }
2189
  if (waveHtml) {
2190
  var waveEl = document.getElementById('slot_wave_' + slot_id);
@@ -2195,82 +2182,49 @@ _GLOBAL_JS = """
2195
  }
2196
  }
2197
  }
2198
- })(out);
2199
- });
2200
-
2201
- function _onComplete(errMsg) {
2202
- es.close();
2203
- var hadError = !!errMsg;
2204
- console.log('[fireRegen] completed for', slot_id, 'error:', hadError, errMsg || '');
2205
- var lbl = document.getElementById('wf_seglabel_' + slot_id);
2206
- if (hadError) {
2207
- var toastMsg = typeof errMsg === 'string' ? errMsg : JSON.stringify(errMsg);
2208
- // Restore waveform HTML FIRST so the statusbar span exists
2209
- if (preRegenWaveHtml !== null) {
2210
- var waveEl = document.getElementById('slot_wave_' + slot_id);
2211
- if (waveEl) waveEl.innerHTML = preRegenWaveHtml;
2212
- }
2213
- // Restore video src
2214
- if (preRegenVideoSrc !== null) {
2215
- var vidElR = document.getElementById('slot_vid_' + slot_id);
2216
- if (vidElR) {
2217
- var vR = vidElR.querySelector('video');
2218
- if (vR) { vR.setAttribute('src', preRegenVideoSrc); vR.src = preRegenVideoSrc; vR.load(); }
2219
- }
2220
- }
2221
- // Write error into status bar
2222
- var statusBar = document.getElementById('wf_statusbar_' + slot_id);
2223
- if (statusBar) {
2224
- statusBar.style.color = '#e05252';
2225
- statusBar.textContent = '\u26a0 ' + toastMsg;
2226
- setTimeout(function() {
2227
- statusBar.style.color = '#888';
2228
- statusBar.textContent = 'Click a segment to regenerate \u00a0|\u00a0 Playhead syncs to video';
2229
- }, 15000);
2230
- }
2231
- var lbl2 = document.getElementById('wf_seglabel_' + slot_id);
2232
- if (lbl2) lbl2.textContent = 'Quota exceeded try again later';
2233
- } else {
2234
- if (lbl) lbl.textContent = 'Done';
2235
- var src = _pendingVideoSrc;
2236
- if (src) {
2237
- _applyVideoSrc(slot_id, src);
2238
- setTimeout(function() { _applyVideoSrc(slot_id, src); }, 50);
2239
- setTimeout(function() { _applyVideoSrc(slot_id, src); }, 300);
2240
- setTimeout(function() { _applyVideoSrc(slot_id, src); }, 800);
2241
- var vidEl = document.getElementById('slot_vid_' + slot_id);
2242
- if (vidEl) {
2243
- var obs = new MutationObserver(function() { _applyVideoSrc(slot_id, src); });
2244
- obs.observe(vidEl, {subtree: true, attributes: true, attributeFilter: ['src'], childList: true});
2245
- setTimeout(function() { obs.disconnect(); }, 2000);
2246
  }
2247
  }
2248
  }
2249
- }
2250
-
2251
- es.addEventListener('complete', function(e) {
2252
- var data;
2253
- try { data = JSON.parse(e.data); } catch(_) { data = []; }
2254
- // Final output array — extract video URL if present
2255
- if (data && data[0]) {
2256
- var vidU = data[0];
2257
- var newSrc = null;
2258
- if (vidU.value && vidU.value.video && vidU.value.video.url) newSrc = vidU.value.video.url;
2259
- else if (vidU.video && vidU.video.url) newSrc = vidU.video.url;
2260
- else if (vidU.value && vidU.value.url) newSrc = vidU.value.url;
2261
- else if (typeof vidU.value === 'string') newSrc = vidU.value;
2262
- else if (vidU.url) newSrc = vidU.url;
2263
- if (newSrc) _pendingVideoSrc = newSrc;
2264
- }
2265
- _onComplete(null);
2266
- });
2267
-
2268
- es.addEventListener('error', function(e) {
2269
- var errMsg = 'Unknown error';
2270
- try { var d = JSON.parse(e.data); errMsg = d.error || d.message || JSON.stringify(d); } catch(_) { errMsg = e.data || 'Unknown error'; }
2271
- _onComplete(errMsg);
2272
- });
2273
-
2274
  es.onerror = function() { es.close(); };
2275
  }
2276
 
 
2085
  const lbl = document.getElementById('wf_seglabel_' + slot_id);
2086
  if (lbl) lbl.textContent = 'Regenerating Seg ' + (seg_idx + 1) + '...';
2087
 
2088
+ const fnIndex = getFnIndex(apiName);
2089
+ if (fnIndex === undefined) {
2090
+ console.warn('[fireRegen] fn_index not found for api_name:', apiName);
2091
+ return;
2092
+ }
2093
+ fetch('/gradio_api/queue/join', {
2094
  method: 'POST',
2095
  credentials: 'include',
2096
  headers: {'Content-Type': 'application/json'},
2097
  body: JSON.stringify({
2098
  data: data,
2099
+ fn_index: fnIndex,
2100
  session_hash: window.__gradio_session_hash__,
2101
+ event_data: null,
2102
+ trigger_id: null
2103
  })
2104
  }).then(function(r) { return r.json(); }).then(function(j) {
2105
  if (!j.event_id) { console.error('[fireRegen] no event_id:', j); return; }
2106
  console.log('[fireRegen] queued, event_id:', j.event_id);
2107
  // Subscribe to SSE stream and apply outputs when ready
2108
+ _listenAndApply(j.event_id, slot_id, seg_idx, _preRegenWaveHtml, _preRegenVideoSrc);
2109
  }).catch(function(e) {
2110
  console.error('[fireRegen] fetch error:', e);
2111
  if (lbl) lbl.textContent = 'Error — see console';
 
2147
  }, isError ? 8000 : 3000);
2148
  }
2149
 
2150
+ function _listenAndApply(eventId, slot_id, seg_idx, preRegenWaveHtml, preRegenVideoSrc) {
2151
+ var _pendingVideoSrc = null;
2152
+ const es = new EventSource('/gradio_api/queue/data?session_hash=' + window.__gradio_session_hash__);
2153
+ es.onmessage = function(e) {
2154
+ var msg;
2155
+ try { msg = JSON.parse(e.data); } catch(_) { return; }
2156
+ if (msg.event_id !== eventId) return;
2157
+ if (msg.msg === 'process_generating' || msg.msg === 'process_completed') {
2158
+ var out = msg.output;
 
 
 
2159
  if (out && out.data) {
 
2160
  var vidUpdate = out.data[0];
2161
  var waveUpdate = out.data[1];
 
 
 
2162
  var newSrc = null;
2163
  if (vidUpdate) {
2164
+ if (vidUpdate.value && vidUpdate.value.video && vidUpdate.value.video.url) newSrc = vidUpdate.value.video.url;
2165
+ else if (vidUpdate.video && vidUpdate.video.url) newSrc = vidUpdate.video.url;
2166
+ else if (vidUpdate.value && vidUpdate.value.url) newSrc = vidUpdate.value.url;
2167
+ else if (typeof vidUpdate.value === 'string') newSrc = vidUpdate.value;
2168
+ else if (vidUpdate.url) newSrc = vidUpdate.url;
 
 
 
 
 
 
2169
  }
2170
  if (newSrc) _pendingVideoSrc = newSrc;
 
 
2171
  var waveHtml = null;
2172
  if (waveUpdate) {
2173
+ if (typeof waveUpdate === 'string') waveHtml = waveUpdate;
2174
+ else if (waveUpdate.value && typeof waveUpdate.value === 'string') waveHtml = waveUpdate.value;
 
 
 
2175
  }
2176
  if (waveHtml) {
2177
  var waveEl = document.getElementById('slot_wave_' + slot_id);
 
2182
  }
2183
  }
2184
  }
2185
+ if (msg.msg === 'process_completed') {
2186
+ es.close();
2187
+ var errMsg = msg.output && msg.output.error;
2188
+ var hadError = !!errMsg;
2189
+ console.log('[fireRegen] completed for', slot_id, 'error:', hadError, errMsg || '');
2190
+ var lbl = document.getElementById('wf_seglabel_' + slot_id);
2191
+ if (hadError) {
2192
+ var toastMsg = typeof errMsg === 'string' ? errMsg : JSON.stringify(errMsg);
2193
+ if (preRegenWaveHtml !== null) {
2194
+ var waveEl2 = document.getElementById('slot_wave_' + slot_id);
2195
+ if (waveEl2) waveEl2.innerHTML = preRegenWaveHtml;
2196
+ }
2197
+ if (preRegenVideoSrc !== null) {
2198
+ var vidElR = document.getElementById('slot_vid_' + slot_id);
2199
+ if (vidElR) { var vR = vidElR.querySelector('video'); if (vR) { vR.setAttribute('src', preRegenVideoSrc); vR.src = preRegenVideoSrc; vR.load(); } }
2200
+ }
2201
+ var statusBar = document.getElementById('wf_statusbar_' + slot_id);
2202
+ if (statusBar) {
2203
+ statusBar.style.color = '#e05252';
2204
+ statusBar.textContent = '\u26a0 ' + toastMsg;
2205
+ setTimeout(function() { statusBar.style.color = '#888'; statusBar.textContent = 'Click a segment to regenerate \u00a0|\u00a0 Playhead syncs to video'; }, 15000);
2206
+ }
2207
+ if (lbl) lbl.textContent = 'Quota exceeded — try again later';
2208
+ } else {
2209
+ if (lbl) lbl.textContent = 'Done';
2210
+ var src = _pendingVideoSrc;
2211
+ if (src) {
2212
+ _applyVideoSrc(slot_id, src);
2213
+ setTimeout(function() { _applyVideoSrc(slot_id, src); }, 50);
2214
+ setTimeout(function() { _applyVideoSrc(slot_id, src); }, 300);
2215
+ setTimeout(function() { _applyVideoSrc(slot_id, src); }, 800);
2216
+ var vidEl = document.getElementById('slot_vid_' + slot_id);
2217
+ if (vidEl) {
2218
+ var obs = new MutationObserver(function() { _applyVideoSrc(slot_id, src); });
2219
+ obs.observe(vidEl, {subtree: true, attributes: true, attributeFilter: ['src'], childList: true});
2220
+ setTimeout(function() { obs.disconnect(); }, 2000);
2221
+ }
2222
+ }
 
 
 
 
 
 
 
 
 
 
2223
  }
2224
  }
2225
  }
2226
+ if (msg.msg === 'close_stream') { es.close(); }
2227
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2228
  es.onerror = function() { es.close(); };
2229
  }
2230