@goodandready/dsh-image-gen 0.11.42 → 0.11.43

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.
Files changed (2) hide show
  1. package/lib/client.js +33 -2
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -60,10 +60,11 @@ window.__ModuleLoader__.load({
60
60
  return (k, def) => def || k
61
61
  }
62
62
 
63
- async function fetchJson(path, options = {}) {
63
+ async function fetchWithTimeout(path, options = {}) {
64
64
  const { timeoutMs = 15000, signal, ...rest } = options
65
65
  let timer = null
66
66
  let sig = signal
67
+ let removeCallerAbort = null
67
68
 
68
69
  if (!sig) {
69
70
  if (typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout === 'function') {
@@ -76,10 +77,38 @@ window.__ModuleLoader__.load({
76
77
  sig = ctrl.signal
77
78
  }
78
79
  } else if (typeof AbortSignal !== 'undefined' && typeof AbortSignal.any === 'function') {
79
- const timeoutSig = typeof AbortSignal.timeout === 'function' ? AbortSignal.timeout(timeoutMs) : null
80
+ const timeoutSig = typeof AbortSignal.timeout === 'function'
81
+ ? AbortSignal.timeout(timeoutMs)
82
+ : (() => {
83
+ const ctrl = new AbortController()
84
+ timer = setTimeout(() => {
85
+ try { ctrl.abort(new Error('Request timeout')) } catch (_) {}
86
+ }, timeoutMs)
87
+ return ctrl.signal
88
+ })()
80
89
  if (timeoutSig) {
81
90
  sig = AbortSignal.any([signal, timeoutSig])
82
91
  }
92
+ } else if (typeof AbortController !== 'undefined') {
93
+ // Fallback for environments lacking AbortSignal.any when caller provides signal
94
+ const ctrl = new AbortController()
95
+ if (signal.aborted) {
96
+ try { ctrl.abort(signal.reason) } catch (_) { ctrl.abort() }
97
+ } else {
98
+ const onCallerAbort = () => {
99
+ try { ctrl.abort(signal.reason) } catch (_) { ctrl.abort() }
100
+ }
101
+ if (typeof signal.addEventListener === 'function') {
102
+ signal.addEventListener('abort', onCallerAbort, { once: true })
103
+ removeCallerAbort = () => {
104
+ try { signal.removeEventListener('abort', onCallerAbort) } catch (_) {}
105
+ }
106
+ }
107
+ }
108
+ timer = setTimeout(() => {
109
+ try { ctrl.abort(new Error('Request timeout')) } catch (_) {}
110
+ }, timeoutMs)
111
+ sig = ctrl.signal
83
112
  }
84
113
 
85
114
  try {
@@ -87,8 +116,10 @@ window.__ModuleLoader__.load({
87
116
  return res
88
117
  } finally {
89
118
  if (timer) clearTimeout(timer)
119
+ if (removeCallerAbort) removeCallerAbort()
90
120
  }
91
121
  }
122
+ const fetchJson = fetchWithTimeout
92
123
  // -------------------------------------------------------------- CSS & Design System
93
124
  function ensureCss() {
94
125
  if (typeof document === 'undefined') return
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-image-gen",
3
- "version": "0.11.42",
3
+ "version": "0.11.43",
4
4
  "description": "Image generation for DeepSeek Harness: a generate_image tool with pluggable providers — the FAL queue, any OpenAI-compatible images API, or a ChatGPT/Grok subscription with no API key at all. The picture is shown inline in the conversation; the model receives either a link (works with any chat model) or the image itself (needs dsh-vision-bridge or a vision-capable model).",
5
5
  "keywords": [
6
6
  "deepseek-harness",