@goodandready/dsh-image-gen 0.10.34 → 0.10.35

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 +119 -2
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -2479,7 +2479,124 @@ window.__ModuleLoader__.load({
2479
2479
  }
2480
2480
 
2481
2481
  // -------------------------------------------------------------- Registration & Apply
2482
- const inject = ['slots', 'configForms', 'locale', 'sessions']
2482
+ // Dual compatibility with DSH 0.1.5-rc.3 (settingsScope) and 0.1.6+ (configForms) (#291)
2483
+ const inject = ['slots', 'locale', 'sessions']
2484
+
2485
+ function resolveActiveScope(ctx) {
2486
+ if (!ctx) return null
2487
+ if (ctx.get && typeof ctx.get === 'function') {
2488
+ try {
2489
+ const lan = ctx.get('lanSettings')
2490
+ if (lan && typeof lan.get === 'function') {
2491
+ const s = lan.get(SETTINGS_NS)
2492
+ if (s) return s
2493
+ }
2494
+ } catch (_) { /* scope unavailable */ }
2495
+ try {
2496
+ const cf = ctx.get('configForms')
2497
+ if (cf && typeof cf.get === 'function') {
2498
+ const s = cf.get(SETTINGS_NS)
2499
+ if (s) return s
2500
+ }
2501
+ } catch (_) { /* scope unavailable */ }
2502
+ try {
2503
+ const ss = ctx.get('settingsScope')
2504
+ if (ss && typeof ss.bind === 'function') {
2505
+ const s = ss.bind({ namespace: SETTINGS_NS })
2506
+ if (s) return s
2507
+ }
2508
+ } catch (_) { /* scope unavailable */ }
2509
+ }
2510
+ if (ctx.configForms && typeof ctx.configForms.get === 'function') {
2511
+ try {
2512
+ const s = ctx.configForms.get(SETTINGS_NS)
2513
+ if (s) return s
2514
+ } catch (_) { /* scope unavailable */ }
2515
+ }
2516
+ if (ctx.settingsScope && typeof ctx.settingsScope.bind === 'function') {
2517
+ try {
2518
+ const s = ctx.settingsScope.bind({ namespace: SETTINGS_NS })
2519
+ if (s) return s
2520
+ } catch (_) { /* scope unavailable */ }
2521
+ }
2522
+ return null
2523
+ }
2524
+
2525
+ function createDynamicSettingsScope(ctx) {
2526
+ const listeners = new Set()
2527
+ let activeTarget = resolveActiveScope(ctx)
2528
+ let activeUnsub = null
2529
+
2530
+ const bindTarget = (target) => {
2531
+ if (!target || target === activeTarget) return
2532
+ if (typeof activeUnsub === 'function') {
2533
+ try { activeUnsub() } catch (_) { /* scope unavailable */ }
2534
+ activeUnsub = null
2535
+ }
2536
+ activeTarget = target
2537
+ if (typeof activeTarget.subscribe === 'function') {
2538
+ try {
2539
+ activeUnsub = activeTarget.subscribe(() => {
2540
+ for (const fn of listeners) fn()
2541
+ })
2542
+ } catch (_) { /* scope unavailable */ }
2543
+ }
2544
+ for (const fn of listeners) fn()
2545
+ }
2546
+
2547
+ if (activeTarget && typeof activeTarget.subscribe === 'function') {
2548
+ try {
2549
+ activeUnsub = activeTarget.subscribe(() => {
2550
+ for (const fn of listeners) fn()
2551
+ })
2552
+ } catch (_) { /* scope unavailable */ }
2553
+ }
2554
+
2555
+ if (typeof ctx?.inject === 'function') {
2556
+ try {
2557
+ ctx.inject(['configForms'], (sctx) => {
2558
+ try {
2559
+ const s = sctx?.configForms?.get?.(SETTINGS_NS)
2560
+ if (s) bindTarget(s)
2561
+ } catch (_) { /* scope unavailable */ }
2562
+ })
2563
+ } catch (_) { /* scope unavailable */ }
2564
+ try {
2565
+ ctx.inject(['settingsScope'], (sctx) => {
2566
+ try {
2567
+ const s = sctx?.settingsScope?.bind?.({ namespace: SETTINGS_NS })
2568
+ if (s) bindTarget(s)
2569
+ } catch (_) { /* scope unavailable */ }
2570
+ })
2571
+ } catch (_) { /* scope unavailable */ }
2572
+ }
2573
+
2574
+ return {
2575
+ getSnapshot() {
2576
+ const target = activeTarget || resolveActiveScope(ctx)
2577
+ if (target && typeof target.getSnapshot === 'function') {
2578
+ return target.getSnapshot()
2579
+ }
2580
+ return { status: 'unavailable', writable: false, value: {} }
2581
+ },
2582
+ async set(key, val) {
2583
+ const target = activeTarget || resolveActiveScope(ctx)
2584
+ if (target && typeof target.set === 'function') {
2585
+ return target.set(key, val)
2586
+ }
2587
+ },
2588
+ async delete(key) {
2589
+ const target = activeTarget || resolveActiveScope(ctx)
2590
+ if (target && typeof target.delete === 'function') {
2591
+ return target.delete(key)
2592
+ }
2593
+ },
2594
+ subscribe(fn) {
2595
+ listeners.add(fn)
2596
+ return () => listeners.delete(fn)
2597
+ },
2598
+ }
2599
+ }
2483
2600
 
2484
2601
  function apply(ctx) {
2485
2602
  if (ctx.locale && typeof ctx.locale.define === 'function') {
@@ -2490,7 +2607,7 @@ window.__ModuleLoader__.load({
2490
2607
  let card
2491
2608
  const cardOnce = () => {
2492
2609
  if (card === undefined) {
2493
- const scope = ((ctx.get && ctx.get('lanSettings')) || ctx.configForms).get(SETTINGS_NS)
2610
+ const scope = createDynamicSettingsScope(ctx)
2494
2611
  card = new FalSettingsCardController(scope)
2495
2612
  }
2496
2613
  return card
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-image-gen",
3
- "version": "0.10.34",
3
+ "version": "0.10.35",
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",