@jayyuen66/dsh-ocr-review 0.1.10 → 0.1.12

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/client.js CHANGED
@@ -8,6 +8,7 @@ window.__ModuleLoader__.load({
8
8
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
9
9
  let react = require("react");
10
10
  let zod = require("zod");
11
+ let _jayyuen66_dsh_plugin_shared_client = require("@jayyuen66/dsh-plugin-shared/client");
11
12
  // src/ui-messages.ts
12
13
  const UI_MESSAGES = {
13
14
  zh: {
@@ -213,592 +214,6 @@ const UI_MESSAGES = {
213
214
  binaryGuideDismiss: "Got it"
214
215
  }
215
216
  };
216
- // node_modules/@jayyuen66/dsh-plugin-shared/dist/record.js
217
- function e$3(e) {
218
- return typeof e == `object` && !!e && !Array.isArray(e);
219
- }
220
- const t$3 = { absent: !0 };
221
- function n$2(e, n) {
222
- try {
223
- return {
224
- absent: !1,
225
- value: e[n]
226
- };
227
- } catch {
228
- return t$3;
229
- }
230
- }
231
- function i$1(r, i) {
232
- let a = e$3(r) ? n$2(r, i) : t$3;
233
- return a.absent ? void 0 : a.value;
234
- }
235
- // node_modules/@jayyuen66/dsh-plugin-shared/dist/card-apply.js
236
- const e$2 = (e) => e.length > 0 && !(e in Object.prototype);
237
- function t$2(e, t, n) {
238
- n === void 0 ? e[t] = void 0 : Object.defineProperty(e, t, n);
239
- }
240
- function n$1(n, r, i) {
241
- if (!e$2(r)) throw Error(`claimApply 的 flag 不得为空、也不得命中 Object.prototype 的成员(__proto__ 一类会让占位静默失灵或遮蔽全局成员):${r}`);
242
- let a = globalThis, o = Object.hasOwn(a, r) ? a[r] : void 0;
243
- if (o === !0 || typeof o == `symbol`) return !1;
244
- let s = Object.getOwnPropertyDescriptor(a, r), c = Symbol(r);
245
- a[r] = c;
246
- try {
247
- n.effect(() => () => {
248
- a[r] === c && t$2(a, r, s);
249
- }, i);
250
- } catch (e) {
251
- throw a[r] === c && t$2(a, r, s), e;
252
- }
253
- return !0;
254
- }
255
- // node_modules/@jayyuen66/dsh-plugin-shared/dist/card-diff.js
256
- function e$1(t, n, r) {
257
- if (t == null || n == null) return (t ?? null) === (n ?? null);
258
- if (Object.is(t, n)) return !0;
259
- if (typeof t != `object` || typeof n != `object`) return !1;
260
- if (r.get(t) === n) return !0;
261
- if (r.set(t, n), Array.isArray(t) || Array.isArray(n)) return !Array.isArray(t) || !Array.isArray(n) || t.length !== n.length ? !1 : t.every((t, i) => e$1(t, n[i], r));
262
- let i = Object.keys(t), a = Object.keys(n);
263
- return i.length === a.length && i.every((i) => Object.hasOwn(n, i) && e$1(Reflect.get(t, i), Reflect.get(n, i), r));
264
- }
265
- function t$1(t, n) {
266
- let r = [];
267
- for (let i of Object.keys(t)) e$1(t[i], n[i], /* @__PURE__ */ new WeakMap()) || r.push(i);
268
- return r;
269
- }
270
- // node_modules/@jayyuen66/dsh-plugin-shared/dist/card-ui.js
271
- const c = `
272
- .dsu-form{display:flex;flex-direction:column}
273
- .dsu-section{margin-top:24px;padding-top:24px;border-top:.5px solid var(--dsw-alias-border-l1)}
274
- .dsu-form>.dsu-section:first-child{margin-top:0;padding-top:0;border-top:0}
275
- .dsu-sectionTitle{margin:0;font-size:15px;font-weight:600;line-height:1.4;color:var(--dsw-alias-label-primary)}
276
- .dsu-sectionHint{margin:4px 0 0;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}
277
- .dsu-statusbar{display:flex;flex-wrap:wrap;gap:4px 8px;margin-top:8px;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}
278
- .dsu-field{display:grid;grid-template-columns:minmax(0,1fr) minmax(240px,360px);column-gap:32px;align-items:center;padding:12px 0;border-top:.5px solid var(--dsw-alias-border-l2)}
279
- .dsu-fieldMeta{display:flex;flex-direction:column;gap:4px;min-width:0}
280
- .dsu-labelRow{display:flex;align-items:center;gap:6px;min-width:0}
281
- .dsu-label{font-size:13px;font-weight:500;line-height:1.5;color:var(--dsw-alias-label-primary)}
282
- .dsu-labelMono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px}
283
- .dsu-hint{margin:0;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}
284
- .dsu-control{min-width:0;display:flex;align-items:center;gap:8px}
285
- .dsu-fieldWide{grid-template-columns:minmax(0,1fr);align-items:start}
286
- .dsu-fieldWide .dsu-control{width:100%;max-width:720px;margin-top:2px}
287
- .dsu-help{display:inline-flex;align-items:center;gap:6px;min-width:0}
288
- .dsu-helpBtn{appearance:none;border:0;background:transparent;padding:0;width:16px;height:16px;display:inline-flex;align-items:center;justify-content:center;color:var(--dsw-alias-label-tertiary);cursor:help;border-radius:50%;flex:none}
289
- .dsu-help:hover .dsu-helpBtn,.dsu-helpBtn:focus-visible{color:var(--dsw-alias-label-primary)}
290
- .dsu-helpBtn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}
291
- .dsu-tip{position:fixed;z-index:60;box-sizing:border-box;max-width:min(340px,calc(100vw - 16px));max-height:calc(100vh - 16px);overflow:auto;overflow-wrap:anywhere;padding:10px 12px;border-radius:10px;background:var(--dsw-alias-bg-layer-2);border:.5px solid var(--dsw-alias-border-l3);box-shadow:0 12px 32px rgb(0 0 0 / 45%);font-size:12px;line-height:1.6;font-weight:400;color:var(--dsw-alias-label-secondary)}
292
- .dsu-input{width:100%;height:34px;padding:0 12px;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px}
293
- .dsu-input:focus-visible{outline:none;border-color:var(--dsw-alias-state-business-primary)}
294
- .dsu-input[aria-invalid="true"]{border-color:var(--dsw-alias-state-error-primary)}
295
- .dsu-input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}
296
- .dsu-input::placeholder{color:var(--dsw-alias-label-tertiary)}
297
- .dsu-textarea{height:auto;min-height:96px;padding:8px 12px;line-height:1.6;resize:vertical}
298
- .dsu-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
299
- .dsu-numberWrap{display:flex;flex-direction:column;gap:4px;width:100%;min-width:0}
300
- .dsu-number{display:flex;align-items:center;gap:8px;min-width:0}
301
- .dsu-number .dsu-input{min-width:0}
302
- .dsu-unit{flex:none;font-size:12px;color:var(--dsw-alias-label-tertiary)}
303
- .dsu-error{margin:0;font-size:12px;line-height:1.5;color:var(--dsw-alias-state-error-primary)}
304
- .dsu-switch{appearance:none;width:36px;height:20px;border-radius:999px;border:0;padding:2px;background:var(--dsw-alias-border-l3);display:flex;align-items:center;cursor:pointer;flex:none;transition:background-color .16s}
305
- .dsu-knob{width:16px;height:16px;border-radius:50%;background:var(--dsw-alias-label-primary);transition:transform .16s,background-color .16s}
306
- .dsu-switch[aria-checked="true"]{background:var(--dsw-alias-label-primary)}
307
- .dsu-switch[aria-checked="true"] .dsu-knob{transform:translateX(16px);background:var(--dsw-alias-label-primary-foreground)}
308
- .dsu-switch:disabled{opacity:.4;cursor:not-allowed}
309
- .dsu-switch:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}
310
- .dsu-selectWrap{position:relative;width:100%;min-width:0}
311
- .dsu-select{display:flex;align-items:center;justify-content:space-between;gap:8px;text-align:left;cursor:pointer}
312
- .dsu-select[aria-expanded="true"]{border-color:var(--dsw-alias-state-business-primary)}
313
- .dsu-selectValue{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
314
- .dsu-chevron{flex:none;color:var(--dsw-alias-label-tertiary);transition:transform .16s}
315
- .dsu-select[aria-expanded="true"] .dsu-chevron{transform:rotate(180deg)}
316
- .dsu-menu{position:fixed;z-index:70;padding:4px;background:var(--dsw-alias-bg-layer-2);border:.5px solid var(--dsw-alias-border-l3);border-radius:12px;box-shadow:0 12px 32px rgb(0 0 0 / 50%);max-height:280px;overflow:auto}
317
- .dsu-option{appearance:none;border:0;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:1.4;width:100%;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:8px 10px;border-radius:8px;cursor:pointer;text-align:left}
318
- .dsu-option:hover,.dsu-option[data-active="true"]{background:var(--dsw-alias-bg-layer-3)}
319
- .dsu-option:disabled{color:var(--dsw-alias-label-tertiary);cursor:not-allowed}
320
- .dsu-option:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}
321
- .dsu-optionGroup{padding:6px 10px 2px;font-size:11px;font-weight:600;color:var(--dsw-alias-label-tertiary)}
322
- .dsu-check{opacity:0;flex:none}
323
- .dsu-option[aria-selected="true"] .dsu-check{opacity:1}
324
- .dsu-savebar{display:flex;align-items:center;gap:8px;padding:12px 0;margin-top:24px;border-top:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base)}
325
- .dsu-savebar[data-dirty="true"]{position:sticky;bottom:0;z-index:2;box-shadow:0 -12px 24px rgb(0 0 0 / 35%)}
326
- .dsu-btn{appearance:none;border:.5px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:1.5;border-radius:var(--dsw-radius-md);padding:5px 14px;cursor:pointer;transition:background-color .12s,border-color .12s,color .12s,filter .12s}
327
- .dsu-btn:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-l3)}
328
- .dsu-btn:active:not(:disabled){background:var(--dsw-alias-bg-layer-1)}
329
- .dsu-btn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:1px}
330
- .dsu-btn:disabled{opacity:.4;cursor:not-allowed}
331
- .dsu-btnPrimary{background:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}
332
- .dsu-btnPrimary:hover:not(:disabled){background:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-primary);filter:brightness(.9)}
333
- .dsu-btnPrimary:active:not(:disabled){background:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-primary);filter:brightness(.84)}
334
- .dsu-btnDanger{color:var(--dsw-alias-state-error-primary)}
335
- .dsu-btnDanger:hover:not(:disabled){color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-2)}
336
- .dsu-status{margin-left:auto;font-size:12px;color:var(--dsw-alias-label-tertiary)}
337
- .dsu-statusError{color:var(--dsw-alias-state-error-primary)}
338
- .dsu-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr));gap:0 24px}
339
- .dsu-grid>.dsu-field{display:flex;flex-direction:column;align-items:stretch;gap:6px;padding:10px 0;border-top:.5px solid var(--dsw-alias-border-l1)}
340
- .dsu-grid>.dsu-field .dsu-control{width:100%}
341
- @media (max-width:640px){
342
- .dsu-field{grid-template-columns:minmax(0,1fr);align-items:start}
343
- .dsu-control{width:100%;max-width:720px}
344
- .dsu-section{margin-top:20px;padding-top:20px}
345
- }
346
- @media (prefers-reduced-motion:reduce){
347
- .dsu-switch,.dsu-knob,.dsu-chevron,.dsu-btn{transition:none}
348
- }
349
- `;
350
- function l(e, t = 30) {
351
- return e.length <= t ? { hint: e } : { detail: e };
352
- }
353
- function u(t) {
354
- return (0, react.createElement)(`div`, { className: `dsu-form` }, t.children);
355
- }
356
- function d(t) {
357
- return (0, react.createElement)(`section`, { className: `dsu-section` }, (0, react.createElement)(`h2`, { className: `dsu-sectionTitle` }, t.title), t.hint === void 0 ? null : (0, react.createElement)(`p`, { className: `dsu-sectionHint` }, t.hint), t.children);
358
- }
359
- function m(a) {
360
- let c = (0, react.useId)(), [l, u] = (0, react.useState)(!1), [d, f] = (0, react.useState)(!1), p = (0, react.useRef)(!1), m = (0, react.useRef)(!1), h = (0, react.useRef)(!1), g = (0, react.useRef)(null), _ = (0, react.useRef)(null), v = (0, react.useRef)(null), y = (0, react.useCallback)(() => {
361
- v.current !== null && (clearTimeout(v.current), v.current = null);
362
- }, []), b = (0, react.useCallback)(() => {
363
- let e = g.current, t = _.current;
364
- /* v8 ignore next 3 -- place 只在 open 的 layout effect 与挂载期监听器里调用;refs 为空只可能是卸载竞态 */
365
- if (e === null || t === null) return;
366
- let n = e.getBoundingClientRect(), r = t.offsetWidth, i = t.offsetHeight, { left: a } = n, o = n.bottom + 8;
367
- o + i > window.innerHeight - 8 && (o = n.top - i - 8), a + r > window.innerWidth - 8 && (a = window.innerWidth - r - 8);
368
- let s = Math.max(8, window.innerWidth - r - 8), c = Math.max(8, window.innerHeight - i - 8);
369
- t.style.left = `${Math.min(Math.max(8, a), s)}px`, t.style.top = `${Math.min(Math.max(8, o), c)}px`;
370
- }, []), x = (0, react.useCallback)(() => {
371
- y(), h.current = !1, f(!1), u(!1);
372
- }, [y]), S = (0, react.useCallback)(() => {
373
- y(), u(!0);
374
- }, [y]), C = (0, react.useCallback)(() => {
375
- y(), !(p.current || m.current || h.current) && (v.current = setTimeout(() => {
376
- /* v8 ignore next 3 -- 任何重新进入/钉住都会 cancelHide;这次复查只防未来的异步路径 */
377
- v.current = null, p.current || m.current || h.current || u(!1);
378
- }, 120));
379
- }, [y]), w = (0, react.useCallback)((e) => {
380
- h.current = e, f(e);
381
- }, []);
382
- (0, react.useLayoutEffect)(() => {
383
- if (!l) return () => {};
384
- b();
385
- let e = (e) => {
386
- let { target: t } = e;
387
- t instanceof Node && _.current?.contains(t) === !0 || (h.current ? b() : x());
388
- }, t = () => {
389
- b();
390
- };
391
- return window.addEventListener(`scroll`, e, !0), window.addEventListener(`resize`, t), () => {
392
- window.removeEventListener(`scroll`, e, !0), window.removeEventListener(`resize`, t);
393
- };
394
- }, [
395
- l,
396
- a.detail,
397
- b,
398
- x
399
- ]), (0, react.useEffect)(() => {
400
- if (!l) return () => {};
401
- let e = (e) => {
402
- e.key === `Escape` && x();
403
- };
404
- return document.addEventListener(`keydown`, e), () => {
405
- document.removeEventListener(`keydown`, e);
406
- };
407
- }, [l, x]), (0, react.useEffect)(() => y, [y]);
408
- let T = (0, react.createElement)(`button`, {
409
- ref: g,
410
- type: `button`,
411
- className: `dsu-helpBtn`,
412
- "aria-label": `${a.label} 说明`,
413
- "aria-describedby": c,
414
- "aria-pressed": d,
415
- onClick: () => {
416
- h.current ? x() : (w(!0), S());
417
- }
418
- }, (0, react.createElement)(`svg`, {
419
- width: 12,
420
- height: 12,
421
- viewBox: `0 0 14 14`,
422
- "aria-hidden": !0
423
- }, (0, react.createElement)(`circle`, {
424
- cx: 7,
425
- cy: 7,
426
- r: 6,
427
- fill: `none`,
428
- stroke: `currentColor`,
429
- strokeWidth: 1.2
430
- }), (0, react.createElement)(`path`, {
431
- d: `M7 6.2v4`,
432
- stroke: `currentColor`,
433
- strokeWidth: 1.3,
434
- strokeLinecap: `round`
435
- }), (0, react.createElement)(`circle`, {
436
- cx: 7,
437
- cy: 4.3,
438
- r: .8,
439
- fill: `currentColor`
440
- }))), E = (0, react.createElement)(`div`, {
441
- ref: _,
442
- id: c,
443
- role: `tooltip`,
444
- className: `dsu-tip`,
445
- hidden: !l
446
- }, a.detail), D = a.showLabel === !1 ? null : (0, react.createElement)(`span`, { className: `dsu-label${a.compact === !0 ? ` dsu-labelMono` : ``}` }, a.label);
447
- return (0, react.createElement)(`span`, {
448
- className: `dsu-help`,
449
- onMouseEnter: () => {
450
- p.current = !0, S();
451
- },
452
- onMouseLeave: () => {
453
- p.current = !1, C();
454
- },
455
- onFocus: () => {
456
- m.current = !0, S();
457
- },
458
- onBlur: (e) => {
459
- let t = e.relatedTarget;
460
- t instanceof Node && e.currentTarget.contains(t) || (m.current = !1, C());
461
- }
462
- }, D, T, E);
463
- }
464
- function h(t) {
465
- let n = `dsu-label${t.compact === !0 ? ` dsu-labelMono` : ``}`, r = t.controlId === void 0 ? (0, react.createElement)(`span`, { className: n }, t.label) : (0, react.createElement)(`label`, {
466
- className: n,
467
- htmlFor: t.controlId
468
- }, t.label);
469
- return (0, react.createElement)(`div`, { className: `dsu-labelRow` }, r, t.detail === void 0 ? null : (0, react.createElement)(m, {
470
- label: t.label,
471
- detail: t.detail,
472
- showLabel: !1
473
- }));
474
- }
475
- function g(t) {
476
- let n = t.controlId === void 0 ? void 0 : `${t.controlId}-hint`;
477
- return (0, react.createElement)(`div`, { className: `dsu-field${t.wide === !0 ? ` dsu-fieldWide` : ``}` }, (0, react.createElement)(`div`, { className: `dsu-fieldMeta` }, (0, react.createElement)(h, {
478
- label: t.label,
479
- detail: t.detail,
480
- compact: t.compact,
481
- controlId: t.controlId
482
- }), t.hint === void 0 ? null : (0, react.createElement)(`p`, {
483
- className: `dsu-hint`,
484
- id: n
485
- }, t.hint)), (0, react.createElement)(`div`, { className: `dsu-control` }, t.children));
486
- }
487
- function _(t) {
488
- let n = (0, react.useId)(), i = t.hint === void 0 ? void 0 : `${n}-hint`;
489
- return (0, react.createElement)(g, {
490
- ...t,
491
- controlId: n
492
- }, (0, react.createElement)(`button`, {
493
- type: `button`,
494
- role: `switch`,
495
- id: n,
496
- className: `dsu-switch`,
497
- "aria-checked": t.checked,
498
- "aria-describedby": i,
499
- "data-field": t.field,
500
- disabled: t.disabled === !0,
501
- onClick: () => {
502
- t.onChange(!t.checked);
503
- }
504
- }, (0, react.createElement)(`span`, { className: `dsu-knob` })));
505
- }
506
- function v(t) {
507
- let i = typeof t.value == `number` && Number.isFinite(t.value) ? String(t.value) : ``, [a, c] = (0, react.useState)(i), [l, u] = (0, react.useState)(!1), d = (0, react.useRef)(void 0), f = (0, react.useId)(), p = (0, react.useId)(), m = [t.hint === void 0 ? void 0 : `${f}-hint`, l ? p : void 0].filter((e) => e !== void 0), h = m.length === 0 ? void 0 : m.join(` `);
508
- (0, react.useEffect)(() => {
509
- t.value !== d.current && (d.current = t.value, c(i), u(!1));
510
- }, [t.value, i]);
511
- let _ = (e) => {
512
- let n = t.min ?? -1 / 0, r = t.max ?? 1 / 0;
513
- if (!Number.isFinite(e) || e < n || e > r) return !1;
514
- let { step: i } = t;
515
- if (i === void 0 || i <= 0) return !0;
516
- let a = (e - (t.min ?? 0)) / i;
517
- return Math.abs(a - Math.round(a)) < 1e-9;
518
- }, v = (e) => {
519
- if (c(e), e === ``) {
520
- u(!1), d.current = void 0, t.onChange(void 0);
521
- return;
522
- }
523
- let n = Number(e);
524
- _(n) ? (u(!1), d.current = n, t.onChange(n)) : u(!0);
525
- }, y = () => {
526
- a === `` || l || c(String(Number(a)));
527
- };
528
- return (0, react.createElement)(g, {
529
- ...t,
530
- controlId: f
531
- }, (0, react.createElement)(`div`, { className: `dsu-numberWrap` }, (0, react.createElement)(`div`, { className: `dsu-number` }, (0, react.createElement)(`input`, {
532
- className: `dsu-input`,
533
- type: `number`,
534
- inputMode: `numeric`,
535
- id: f,
536
- value: a,
537
- min: t.min,
538
- max: t.max,
539
- step: t.step,
540
- placeholder: t.placeholder,
541
- "aria-invalid": l || void 0,
542
- "aria-describedby": h,
543
- "data-field": t.field,
544
- disabled: t.disabled === !0,
545
- onChange: (e) => {
546
- v(e.target.value);
547
- },
548
- onBlur: y
549
- }), t.unit === void 0 ? null : (0, react.createElement)(`span`, { className: `dsu-unit` }, t.unit)), l ? (0, react.createElement)(`p`, {
550
- className: `dsu-error`,
551
- id: p
552
- }, t.invalidHint) : null));
553
- }
554
- function y(t) {
555
- let [i, a] = (0, react.useState)(t.value), [o, c] = (0, react.useState)(!1), l = (0, react.useId)(), u = t.hint === void 0 ? void 0 : `${l}-hint`;
556
- (0, react.useEffect)(() => {
557
- o || a(t.value);
558
- }, [t.value, o]);
559
- let d = {
560
- id: l,
561
- className: `dsu-input${t.multiline === !0 ? ` dsu-textarea` : ``}${t.monospace === !0 ? ` dsu-mono` : ``}`,
562
- value: i,
563
- placeholder: t.placeholder,
564
- "aria-describedby": u,
565
- "data-field": t.field,
566
- disabled: t.disabled === !0,
567
- onFocus: () => {
568
- c(!0);
569
- },
570
- onBlur: () => {
571
- c(!1);
572
- },
573
- onChange: (e) => {
574
- a(e.target.value), t.onChange(e.target.value);
575
- }
576
- };
577
- return (0, react.createElement)(g, {
578
- ...t,
579
- controlId: l
580
- }, t.multiline === !0 ? (0, react.createElement)(`textarea`, d) : (0, react.createElement)(`input`, d));
581
- }
582
- function x(c) {
583
- let [l, u] = (0, react.useState)(!1), [d, f] = (0, react.useState)(0), p = (0, react.useRef)(null), m = (0, react.useRef)(null), h = (0, react.useId)(), _ = (0, react.useId)(), v = c.hint === void 0 ? void 0 : `${_}-hint`, { disabled: y, value: b, options: x, onChange: S } = c, C = (0, react.useMemo)(() => x.map((e, t) => ({
584
- option: e,
585
- index: t
586
- })).filter((e) => e.option.disabled !== !0), [x]), w = x.find((e) => e.value === b)?.label ?? b, T = x[d], E = T !== void 0 && T.disabled !== !0, D = (0, react.useCallback)(() => {
587
- let e = p.current, t = m.current;
588
- /* v8 ignore next 3 -- place 只在 open 的 layout effect 里调用;refs 为空只可能是卸载竞态 */
589
- if (e === null || t === null) return;
590
- let n = e.getBoundingClientRect(), r = Math.min(n.width, window.innerWidth - 16), { left: i } = n;
591
- i + r > window.innerWidth - 8 && (i = window.innerWidth - r - 8);
592
- let a = t.offsetHeight, o = n.bottom + 6;
593
- o + a > window.innerHeight - 8 && (o = n.top - a - 6);
594
- let s = Math.max(8, window.innerWidth - r - 8), c = Math.max(8, window.innerHeight - a - 8);
595
- t.style.width = `${r}px`, t.style.left = `${Math.min(Math.max(8, i), s)}px`, t.style.top = `${Math.min(Math.max(8, o), c)}px`;
596
- }, []), O = (0, react.useCallback)(() => {
597
- u(!1);
598
- }, []), k = (0, react.useCallback)(() => {
599
- if (y === !0) return;
600
- let e = C.find((e) => e.option.value === b) ?? C.at(0);
601
- e !== void 0 && (f(e.index), u(!0));
602
- }, [
603
- y,
604
- b,
605
- C
606
- ]), A = (0, react.useCallback)((e) => {
607
- /* v8 ignore next 3 -- 浮层只能经由 openMenu 打开;组件禁用时打不开 */
608
- if (y === !0) return;
609
- let t = x[e];
610
- /* v8 ignore next 3 -- disabled 选项在浏览器里不派发 click;越界下标由调用面保证 */
611
- t !== void 0 && t.disabled !== !0 && (S(t.value), O(), p.current?.focus());
612
- }, [
613
- y,
614
- x,
615
- S,
616
- O
617
- ]), j = (0, react.useCallback)((e) => {
618
- let t = C.findIndex((e) => e.index === d);
619
- /* v8 ignore next 5 -- open 时归一 effect 已保证 enabled 非空且 active 落在可用项上 */
620
- if (t === -1 || C.length === 0) return;
621
- let n = (t + e + C.length) % C.length, r = C[n];
622
- /* v8 ignore next 3 -- next 由取模保证在界内 */
623
- r !== void 0 && f(r.index);
624
- }, [d, C]);
625
- (0, react.useLayoutEffect)(() => {
626
- if (!l) return () => {};
627
- D();
628
- let e = (e) => {
629
- let t = e.target;
630
- m.current?.contains(t) !== !0 && p.current?.contains(t) !== !0 && O();
631
- }, t = (e) => {
632
- let { target: t } = e;
633
- t instanceof Node && m.current?.contains(t) === !0 || O();
634
- }, n = () => {
635
- D();
636
- };
637
- return document.addEventListener(`pointerdown`, e, !0), window.addEventListener(`scroll`, t, !0), window.addEventListener(`resize`, n), () => {
638
- document.removeEventListener(`pointerdown`, e, !0), window.removeEventListener(`scroll`, t, !0), window.removeEventListener(`resize`, n);
639
- };
640
- }, [
641
- l,
642
- c.options,
643
- D,
644
- O
645
- ]), (0, react.useEffect)(() => {
646
- if (!l) return;
647
- if (y === !0 || C.length === 0) {
648
- O();
649
- return;
650
- }
651
- if (C.some((e) => e.index === d)) return;
652
- let e = C.find((e) => e.option.value === b) ?? C.at(0);
653
- /* v8 ignore next 3 -- enabled 非空在上一分支已保证 */
654
- e !== void 0 && f(e.index);
655
- }, [
656
- l,
657
- y,
658
- b,
659
- x,
660
- d,
661
- O,
662
- C
663
- ]), (0, react.useLayoutEffect)(() => {
664
- if (!l) return;
665
- let e = m.current;
666
- /* v8 ignore next 2 -- 同上,menu 在 open 的 commit 之后必然已挂上 */
667
- if (e === null) return;
668
- let t = e.querySelector(`[data-active="true"]`);
669
- /* v8 ignore next 2 -- active 已由归一 effect 保证落在可用项上 */
670
- t !== null && (t.offsetTop < e.scrollTop ? e.scrollTop = t.offsetTop : t.offsetTop + t.offsetHeight > e.scrollTop + e.clientHeight && (e.scrollTop = t.offsetTop + t.offsetHeight - e.clientHeight));
671
- }, [
672
- l,
673
- d,
674
- x
675
- ]);
676
- let M = (e) => {
677
- if (e.key === `ArrowDown` || e.key === `ArrowUp`) {
678
- if (e.preventDefault(), !l) {
679
- k();
680
- return;
681
- }
682
- j(e.key === `ArrowDown` ? 1 : -1);
683
- } else if (e.key === `Home` || e.key === `End`) {
684
- if (e.preventDefault(), l || k(), C.length === 0) return;
685
- let t = e.key === `Home` ? C.at(0) : C.at(-1);
686
- /* v8 ignore next 3 -- enabled 为空已在上一条返回 */
687
- if (t === void 0) return;
688
- f(t.index);
689
- } else if (e.key === `Enter` || e.key === ` `) {
690
- if (e.preventDefault(), !l) {
691
- k();
692
- return;
693
- }
694
- A(d);
695
- } else (e.key === `Tab` || e.key === `Escape`) && O();
696
- }, N = [], P;
697
- for (let [t, n] of x.entries()) n.group !== P && (n.group !== void 0 && N.push((0, react.createElement)(`div`, {
698
- key: `group-${t}-${n.group}`,
699
- className: `dsu-optionGroup`,
700
- role: `presentation`
701
- }, n.group)), P = n.group), N.push((0, react.createElement)(`button`, {
702
- key: `option-${n.value}`,
703
- type: `button`,
704
- role: `option`,
705
- id: `${h}-${t}`,
706
- className: `dsu-option`,
707
- tabIndex: -1,
708
- "aria-selected": n.value === c.value,
709
- "data-active": t === d,
710
- disabled: n.disabled === !0,
711
- onMouseDown: (e) => {
712
- e.preventDefault();
713
- },
714
- onClick: () => {
715
- A(t);
716
- },
717
- onMouseEnter: () => {
718
- /* v8 ignore next -- happy-dom 对 disabled 元素不派发 mouse 事件;浏览器实现各有差异,保留禁用检查 */
719
- n.disabled !== !0 && f(t);
720
- }
721
- }, (0, react.createElement)(`span`, null, n.label), (0, react.createElement)(`svg`, {
722
- className: `dsu-check`,
723
- width: 14,
724
- height: 14,
725
- viewBox: `0 0 14 14`,
726
- "aria-hidden": !0
727
- }, (0, react.createElement)(`path`, {
728
- d: `M2.5 7.5l3 3 6-7`,
729
- fill: `none`,
730
- stroke: `currentColor`,
731
- strokeWidth: 1.5,
732
- strokeLinecap: `round`,
733
- strokeLinejoin: `round`
734
- }))));
735
- return (0, react.createElement)(g, {
736
- ...c,
737
- controlId: _
738
- }, (0, react.createElement)(`div`, {
739
- className: `dsu-selectWrap`,
740
- onBlur: (e) => {
741
- let t = e.relatedTarget;
742
- t instanceof Node && e.currentTarget.contains(t) || O();
743
- }
744
- }, (0, react.createElement)(`button`, {
745
- ref: p,
746
- type: `button`,
747
- id: _,
748
- className: `dsu-select dsu-input`,
749
- role: `combobox`,
750
- "aria-haspopup": `listbox`,
751
- "aria-expanded": l,
752
- "aria-controls": `${h}-list`,
753
- "aria-activedescendant": l && E ? `${h}-${d}` : void 0,
754
- "aria-describedby": v,
755
- "data-field": c.field,
756
- disabled: y === !0 || x.length === 0,
757
- onClick: () => {
758
- l ? O() : k();
759
- },
760
- onKeyDown: M
761
- }, (0, react.createElement)(`span`, { className: `dsu-selectValue` }, w), (0, react.createElement)(`svg`, {
762
- className: `dsu-chevron`,
763
- width: 14,
764
- height: 14,
765
- viewBox: `0 0 14 14`,
766
- "aria-hidden": !0
767
- }, (0, react.createElement)(`path`, {
768
- d: `M3 5l4 4 4-4`,
769
- fill: `none`,
770
- stroke: `currentColor`,
771
- strokeWidth: 1.5,
772
- strokeLinecap: `round`,
773
- strokeLinejoin: `round`
774
- }))), (0, react.createElement)(`div`, {
775
- ref: m,
776
- id: `${h}-list`,
777
- role: `listbox`,
778
- className: `dsu-menu`,
779
- "aria-label": c.label,
780
- hidden: !l
781
- }, ...N)));
782
- }
783
- function S(t) {
784
- let n = !t.writable || t.busy || !t.dirty, r;
785
- return r = t.error === null ? t.writable ? t.dirty ? t.dirtyLabel : t.cleanLabel : t.readOnlyLabel : t.error, (0, react.createElement)(`div`, {
786
- className: `dsu-savebar`,
787
- "data-dirty": t.dirty
788
- }, (0, react.createElement)(`button`, {
789
- type: `button`,
790
- className: `dsu-btn dsu-btnPrimary`,
791
- "data-field": `save`,
792
- disabled: n,
793
- onClick: t.onSave
794
- }, t.busy ? t.savingLabel : t.saveLabel), (0, react.createElement)(`button`, {
795
- type: `button`,
796
- className: `dsu-btn`,
797
- "data-field": `discard`,
798
- disabled: n,
799
- onClick: t.onDiscard
800
- }, t.revertLabel), (0, react.createElement)(`span`, { className: t.error === null ? `dsu-status` : `dsu-status dsu-statusError` }, r));
801
- }
802
217
  // lib/remote-shape.ts
803
218
  /** 宿主服务键 = 客户端线上命名空间(两侧共用的唯一来源)。 */
804
219
  const OCR_REMOTE_NAMESPACE = "ocrReview";
@@ -953,9 +368,9 @@ const OCR_DESCRIPTORS = [
953
368
  }
954
369
  ];
955
370
  /** 这个值能当远程面用吗(只核我们要调的那一位;服务来自别的实现或版本时保守当作没有)。 */
956
- const isRemoteMounter = (value) => e$3(value) && typeof value["$mount"] === "function";
371
+ const isRemoteMounter = (value) => (0, _jayyuen66_dsh_plugin_shared_client.isRecord)(value) && typeof value["$mount"] === "function";
957
372
  /** 同上:命名空间服务(挂载之后才有,缺它说明网关没认这枚贡献)。 */
958
- const isOcrNamespace = (value) => e$3(value) && typeof value["providers"] === "function" && typeof value["select"] === "function" && typeof value["migrate"] === "function" && typeof value["test"] === "function" && typeof value["probe"] === "function" && typeof value["mcp"] === "function" && typeof value["saveMcp"] === "function" && typeof value["auth"] === "function" && typeof value["chatGpt"] === "function";
373
+ const isOcrNamespace = (value) => (0, _jayyuen66_dsh_plugin_shared_client.isRecord)(value) && typeof value["providers"] === "function" && typeof value["select"] === "function" && typeof value["migrate"] === "function" && typeof value["test"] === "function" && typeof value["probe"] === "function" && typeof value["mcp"] === "function" && typeof value["saveMcp"] === "function" && typeof value["auth"] === "function" && typeof value["chatGpt"] === "function";
959
374
  /** 网关回执 → 值;载体/网关失败抛(卡片那层按「请求失败」显示)。
960
375
  * 机器码放 `cause`:卡片只展示 message,`REMOTE_...` 这类内部标识不是给用户看的。 */
961
376
  function unwrap(result) {
@@ -1114,7 +529,7 @@ const PROVIDER_SCHEMA = zod.z.object({
1114
529
  displayName: STRING_OR_EMPTY,
1115
530
  apiKeyEnv: NULLABLE_STRING,
1116
531
  baseURL: STRING_OR_EMPTY,
1117
- models: zod.z.preprocess((value) => Array.isArray(value) ? value.map((item) => e$3(item) ? item : {}) : [], zod.z.array(MODEL_SCHEMA)),
532
+ models: zod.z.preprocess((value) => Array.isArray(value) ? value.map((item) => (0, _jayyuen66_dsh_plugin_shared_client.isRecord)(item) ? item : {}) : [], zod.z.array(MODEL_SCHEMA)),
1118
533
  hasKey: TRUE_ONLY
1119
534
  });
1120
535
  const CURRENT_SCHEMA = zod.z.object({
@@ -1174,7 +589,7 @@ function binaryOf(raw) {
1174
589
  async function loadCliStatus(reader) {
1175
590
  if (reader === void 0) return null;
1176
591
  try {
1177
- return binaryOf(i$1(await reader.providers(), "ocrBinary"));
592
+ return binaryOf((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(await reader.providers(), "ocrBinary"));
1178
593
  } catch {
1179
594
  return null;
1180
595
  }
@@ -1196,10 +611,10 @@ const EMPTY_PAYLOAD = {
1196
611
  ocrBinary: null
1197
612
  };
1198
613
  const PROVIDERS_PAYLOAD_SCHEMA = zod.z.object({
1199
- providers: zod.z.preprocess((value) => Array.isArray(value) ? value.map((item) => e$3(item) ? item : {}) : [], zod.z.array(PROVIDER_SCHEMA)),
1200
- current: zod.z.preprocess((value) => e$3(value) ? value : {}, CURRENT_SCHEMA),
614
+ providers: zod.z.preprocess((value) => Array.isArray(value) ? value.map((item) => (0, _jayyuen66_dsh_plugin_shared_client.isRecord)(item) ? item : {}) : [], zod.z.array(PROVIDER_SCHEMA)),
615
+ current: zod.z.preprocess((value) => (0, _jayyuen66_dsh_plugin_shared_client.isRecord)(value) ? value : {}, CURRENT_SCHEMA),
1201
616
  getCredReady: TRUE_ONLY,
1202
- source: zod.z.preprocess((value) => e$3(value) ? value : {}, SOURCE_SCHEMA),
617
+ source: zod.z.preprocess((value) => (0, _jayyuen66_dsh_plugin_shared_client.isRecord)(value) ? value : {}, SOURCE_SCHEMA),
1203
618
  endpointVerify: zod.z.preprocess((value) => {
1204
619
  const parsed = ENDPOINT_VERIFY_SCHEMA.safeParse(value);
1205
620
  return parsed.success ? parsed.data : null;
@@ -1345,7 +760,7 @@ function buildCliStatusRow(deps) {
1345
760
  className: statusClass(deps.probeMsg.ok),
1346
761
  "data-field": "probe-result"
1347
762
  }, deps.probeMsg.text) : null;
1348
- return (0, react.createElement)(d, {
763
+ return (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.Section, {
1349
764
  title: t("binaryTitle"),
1350
765
  hint: t("binaryProbeHint")
1351
766
  }, status, versionLine, installLine, controls, probe);
@@ -1500,7 +915,7 @@ function buildActionField(deps) {
1500
915
  onClick: deps.onMigrate,
1501
916
  "data-field": "migrate"
1502
917
  }, t("migrateKeys"));
1503
- return (0, react.createElement)(g, {
918
+ return (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.Field, {
1504
919
  label: t("actionsLabel"),
1505
920
  wide: true
1506
921
  }, (0, react.createElement)("div", { className: ACTIONS_CLASS }, applyBtn, testBtn, migrateBtn));
@@ -1565,16 +980,16 @@ function buildReadyProviderSection(deps, data) {
1565
980
  }];
1566
981
  const modelUrl = deps.chosenProvider?.baseURL ?? "";
1567
982
  return [
1568
- (0, react.createElement)(x, {
983
+ (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.SelectField, {
1569
984
  label: "Provider",
1570
- ...l(t("providerHint")),
985
+ ...(0, _jayyuen66_dsh_plugin_shared_client.splitHint)(t("providerHint")),
1571
986
  field: "ocrProvider",
1572
987
  value: deps.effectiveProvider,
1573
988
  options: providerOptions,
1574
989
  disabled: data.providers.length === 0,
1575
990
  onChange: deps.onPickProvider
1576
991
  }),
1577
- (0, react.createElement)(x, {
992
+ (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.SelectField, {
1578
993
  label: "Model",
1579
994
  ...modelUrl === "" ? {} : { hint: modelUrl },
1580
995
  field: "ocrModel",
@@ -1583,9 +998,9 @@ function buildReadyProviderSection(deps, data) {
1583
998
  disabled: !deps.chosenProvider || deps.modelOptions.length === 0,
1584
999
  onChange: deps.onPickModel
1585
1000
  }),
1586
- (0, react.createElement)(x, {
1001
+ (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.SelectField, {
1587
1002
  label: t("effortLabel"),
1588
- ...l(t("effortHint")),
1003
+ ...(0, _jayyuen66_dsh_plugin_shared_client.splitHint)(t("effortHint")),
1589
1004
  field: "effort",
1590
1005
  value: deps.effortValue,
1591
1006
  options: effortOptions,
@@ -1594,9 +1009,9 @@ function buildReadyProviderSection(deps, data) {
1594
1009
  deps.onField("effort", next);
1595
1010
  }
1596
1011
  }),
1597
- (0, react.createElement)(x, {
1012
+ (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.SelectField, {
1598
1013
  label: t("languageLabel"),
1599
- ...l(t("languageHint")),
1014
+ ...(0, _jayyuen66_dsh_plugin_shared_client.splitHint)(t("languageHint")),
1600
1015
  field: "language",
1601
1016
  value: deps.languageValue,
1602
1017
  options: languageOptions,
@@ -1605,9 +1020,9 @@ function buildReadyProviderSection(deps, data) {
1605
1020
  deps.onField("language", next);
1606
1021
  }
1607
1022
  }),
1608
- (0, react.createElement)(_, {
1023
+ (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.ToggleField, {
1609
1024
  label: t("autoVerifyLabel"),
1610
- ...l(t("autoVerifyHint")),
1025
+ ...(0, _jayyuen66_dsh_plugin_shared_client.splitHint)(t("autoVerifyHint")),
1611
1026
  field: "autoVerify",
1612
1027
  checked: deps.autoVerifyValue,
1613
1028
  disabled: !deps.writable,
@@ -1634,7 +1049,7 @@ function buildProviderSection(deps) {
1634
1049
  const reason = sourceMessage === "" ? t("noReason") : sourceMessage;
1635
1050
  body = (0, react.createElement)("p", { className: "dsu-error" }, t("readProvidersFailed", { reason }));
1636
1051
  }
1637
- return (0, react.createElement)(d, { title: t("modelSection") }, body);
1052
+ return (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.Section, { title: t("modelSection") }, body);
1638
1053
  }
1639
1054
  /** provider 预选:显式选择 > 当前 OCR 配置(仍存在)> 第一个有 key 的 provider。 */
1640
1055
  function resolveBackend(providerList, current, selProvider) {
@@ -1667,9 +1082,9 @@ function resolveSelection(providerList, current, selProvider, selModel) {
1667
1082
  /** 审查参数小节:评论条数、运行超时、配置文件路径 + 保存条。 */
1668
1083
  function buildSettingsSection(deps, writable, setField) {
1669
1084
  const { t } = deps;
1670
- const maxCommentsRow = (0, react.createElement)(v, {
1085
+ const maxCommentsRow = (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.NumberField, {
1671
1086
  label: t("maxCommentsLabel"),
1672
- ...l(t("maxCommentsHint")),
1087
+ ...(0, _jayyuen66_dsh_plugin_shared_client.splitHint)(t("maxCommentsHint")),
1673
1088
  field: "maxComments",
1674
1089
  value: deps.maxCommentsValue,
1675
1090
  ...COUNT_SCHEMA.minValue === null ? {} : { min: COUNT_SCHEMA.minValue },
@@ -1680,9 +1095,9 @@ function buildSettingsSection(deps, writable, setField) {
1680
1095
  setField("maxComments", next);
1681
1096
  }
1682
1097
  });
1683
- const timeoutRow = (0, react.createElement)(v, {
1098
+ const timeoutRow = (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.NumberField, {
1684
1099
  label: t("timeoutLabel"),
1685
- ...l(t("timeoutHint")),
1100
+ ...(0, _jayyuen66_dsh_plugin_shared_client.splitHint)(t("timeoutHint")),
1686
1101
  field: "timeoutMinutes",
1687
1102
  value: deps.timeoutMinutesValue,
1688
1103
  ...COUNT_SCHEMA.minValue === null ? {} : { min: COUNT_SCHEMA.minValue },
@@ -1693,9 +1108,9 @@ function buildSettingsSection(deps, writable, setField) {
1693
1108
  setField("timeoutMinutes", next);
1694
1109
  }
1695
1110
  });
1696
- const configPathRow = (0, react.createElement)(y, {
1111
+ const configPathRow = (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.TextField, {
1697
1112
  label: t("configPathLabel"),
1698
- ...l(t("configPathHint")),
1113
+ ...(0, _jayyuen66_dsh_plugin_shared_client.splitHint)(t("configPathHint")),
1699
1114
  field: "ocrConfigPath",
1700
1115
  value: deps.ocrConfigPathValue,
1701
1116
  placeholder: "~/.opencodereview/config.json",
@@ -1706,7 +1121,7 @@ function buildSettingsSection(deps, writable, setField) {
1706
1121
  setField("ocrConfigPath", next.trim());
1707
1122
  }
1708
1123
  });
1709
- const saveRow = (0, react.createElement)(S, {
1124
+ const saveRow = (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.SaveBar, {
1710
1125
  dirty: deps.dirty,
1711
1126
  writable,
1712
1127
  busy: deps.settingsBusy,
@@ -1721,7 +1136,7 @@ function buildSettingsSection(deps, writable, setField) {
1721
1136
  onDiscard: deps.onDiscard
1722
1137
  });
1723
1138
  const statusHintNode = deps.statusHint !== null && deps.statusHint !== "" ? (0, react.createElement)("p", { className: "dsu-hint" }, deps.statusHint) : null;
1724
- return (0, react.createElement)(d, { title: t("reviewSection") }, statusHintNode, maxCommentsRow, timeoutRow, configPathRow, saveRow);
1139
+ return (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.Section, { title: t("reviewSection") }, statusHintNode, maxCommentsRow, timeoutRow, configPathRow, saveRow);
1725
1140
  }
1726
1141
  function buildMcpAdmin(props) {
1727
1142
  const { t } = props;
@@ -1743,7 +1158,7 @@ function buildMcpAdmin(props) {
1743
1158
  onClick: props.onMcpSave
1744
1159
  }, props.mcpBusy ? t("mcpSaving") : t("mcpSave"));
1745
1160
  const message = props.mcpMsg === null ? null : (0, react.createElement)("p", { className: "dsu-hint" }, props.mcpMsg);
1746
- return (0, react.createElement)(d, {
1161
+ return (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.Section, {
1747
1162
  title: t("mcpTitle"),
1748
1163
  hint: t("mcpHint")
1749
1164
  }, props.available ? textarea : (0, react.createElement)("p", { className: "dsu-hint" }, t("adminUnavailable")), (0, react.createElement)("div", { className: ACTIONS_CLASS }, button), message);
@@ -1776,7 +1191,7 @@ function buildAuthAdmin(props) {
1776
1191
  }, props.authBusy ? t("chatGptUsing") : t("chatGptUse"));
1777
1192
  const output = props.authOutput === null ? null : (0, react.createElement)("pre", { className: "ocr-status dsu-mono" }, props.authOutput);
1778
1193
  const message = props.authMsg === null ? null : (0, react.createElement)("p", { className: "dsu-hint" }, props.authMsg);
1779
- return (0, react.createElement)(d, {
1194
+ return (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.Section, {
1780
1195
  title: t("chatGptTitle"),
1781
1196
  hint: t("chatGptHint")
1782
1197
  }, (0, react.createElement)("div", { className: ACTIONS_CLASS }, check), (0, react.createElement)("p", { className: "dsu-hint" }, `${t("chatGptLoginHint")} ${props.loginCommand}`), output, (0, react.createElement)("p", { className: "dsu-hint" }, t("chatGptModelLabel")), model, (0, react.createElement)("div", { className: ACTIONS_CLASS }, use), message);
@@ -1795,8 +1210,8 @@ async function refreshProviders(reader, t, sinks) {
1795
1210
  try {
1796
1211
  if (reader === void 0) throw new Error(t("remoteUnavailable"));
1797
1212
  const json = await reader.providers();
1798
- if (i$1(json, "ok") === false) {
1799
- const detail = strOf(i$1(json, "error"));
1213
+ if ((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(json, "ok") === false) {
1214
+ const detail = strOf((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(json, "error"));
1800
1215
  throw new Error(detail === "" ? t("remoteUnavailable") : detail);
1801
1216
  }
1802
1217
  const payload = providersPayloadOf(json);
@@ -1813,8 +1228,8 @@ function readerPost(reader, t) {
1813
1228
  if (reader === void 0) throw new Error(t("remoteUnavailable"));
1814
1229
  switch (action) {
1815
1230
  case "select": {
1816
- const provider = strOf(i$1(body, "provider"));
1817
- const model = strOf(i$1(body, "model"));
1231
+ const provider = strOf((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(body, "provider"));
1232
+ const model = strOf((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(body, "model"));
1818
1233
  const reply = await reader.select(provider, model);
1819
1234
  return { json: () => Promise.resolve(reply) };
1820
1235
  }
@@ -1852,13 +1267,13 @@ async function runApplySelection(deps) {
1852
1267
  provider: effectiveProvider,
1853
1268
  model: effectiveModel
1854
1269
  })).json();
1855
- if (i$1(selJson, "ok") === true) {
1270
+ if ((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(selJson, "ok") === true) {
1856
1271
  let testText;
1857
1272
  let verified = true;
1858
- const llmTestRaw = i$1(selJson, "llmTest");
1859
- if (e$3(llmTestRaw)) {
1860
- const testOutput = strOf(i$1(llmTestRaw, "output")).slice(0, 400);
1861
- verified = i$1(llmTestRaw, "ok") === true;
1273
+ const llmTestRaw = (0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(selJson, "llmTest");
1274
+ if ((0, _jayyuen66_dsh_plugin_shared_client.isRecord)(llmTestRaw)) {
1275
+ const testOutput = strOf((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(llmTestRaw, "output")).slice(0, 400);
1276
+ verified = (0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(llmTestRaw, "ok") === true;
1862
1277
  testText = verified ? t("llmTestPassed") : `${t("llmTestFailed")}${testOutput}`;
1863
1278
  } else testText = t("notVerified");
1864
1279
  const appliedText = t("applied", {
@@ -1872,7 +1287,7 @@ async function runApplySelection(deps) {
1872
1287
  });
1873
1288
  deps.refresh();
1874
1289
  } else {
1875
- const failure = strOf(i$1(selJson, "error"));
1290
+ const failure = strOf((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(selJson, "error"));
1876
1291
  deps.setActionMsg({
1877
1292
  ok: false,
1878
1293
  text: failure === "" ? t("applyFailed") : failure
@@ -1895,11 +1310,11 @@ async function runMigrateKeys(deps) {
1895
1310
  deps.setActionMsg(null);
1896
1311
  try {
1897
1312
  const json = await (await deps.post("migrate")).json();
1898
- const migratedVal = i$1(json, "migrated");
1899
- const skippedVal = i$1(json, "skippedUnknown");
1313
+ const migratedVal = (0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(json, "migrated");
1314
+ const skippedVal = (0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(json, "skippedUnknown");
1900
1315
  const migrated = Array.isArray(migratedVal) ? migratedVal.filter((item) => typeof item === "string") : [];
1901
1316
  const skipped = Array.isArray(skippedVal) ? skippedVal.filter((item) => typeof item === "string") : [];
1902
- const ok = i$1(json, "ok") === true;
1317
+ const ok = (0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(json, "ok") === true;
1903
1318
  const migratedText = migrated.length > 0 ? t("migratedPrefix") + migrated.join(", ") : t("noPlainKey");
1904
1319
  const skippedText = skipped.length > 0 ? t("skippedPrefix") + skipped.join(", ") : "";
1905
1320
  const head = ok ? migratedText + skippedText : t("migrateFailed");
@@ -1925,8 +1340,8 @@ async function runTestConnection(deps) {
1925
1340
  deps.setActionMsg(null);
1926
1341
  try {
1927
1342
  const json = await (await deps.post("test")).json();
1928
- const ok = i$1(json, "ok") === true;
1929
- const testOutput = strOf(i$1(json, "output"));
1343
+ const ok = (0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(json, "ok") === true;
1344
+ const testOutput = strOf((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(json, "output"));
1930
1345
  deps.setActionMsg({
1931
1346
  ok,
1932
1347
  text: (ok ? t("llmTestPassed") : t("llmTestFailed")) + testOutput
@@ -1953,12 +1368,12 @@ async function runProbe(deps) {
1953
1368
  deps.setProbeMsg(null);
1954
1369
  try {
1955
1370
  const json = await (await deps.post("probe")).json();
1956
- const ok = i$1(json, "ok") === true;
1957
- const head = ok ? t("probeVersion", { version: strOf(i$1(json, "version")) }) : t("probeReason", { reason: strOf(i$1(json, "reason")) });
1958
- const output = strOf(i$1(json, "output"));
1371
+ const ok = (0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(json, "ok") === true;
1372
+ const head = ok ? t("probeVersion", { version: strOf((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(json, "version")) }) : t("probeReason", { reason: strOf((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(json, "reason")) });
1373
+ const output = strOf((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(json, "output"));
1959
1374
  const lines = [
1960
1375
  head,
1961
- strOf(i$1(json, "changeText")),
1376
+ strOf((0, _jayyuen66_dsh_plugin_shared_client.fieldOf)(json, "changeText")),
1962
1377
  output
1963
1378
  ].filter((line) => line !== "");
1964
1379
  deps.setProbeMsg({
@@ -1981,7 +1396,7 @@ async function runProbe(deps) {
1981
1396
  * 传输失败仍以 rejection 表达。 */
1982
1397
  async function saveSettingsDraft(deps) {
1983
1398
  const { t, value, touched } = deps;
1984
- const keys = t$1(touched, value);
1399
+ const keys = (0, _jayyuen66_dsh_plugin_shared_client.diffTouched)(touched, value);
1985
1400
  if (keys.length === 0) return;
1986
1401
  deps.setSettingsBusy(true);
1987
1402
  deps.setSaveError(null);
@@ -2222,7 +1637,7 @@ function OcrCard(props) {
2222
1637
  const [touched, setTouched] = (0, react.useState)({});
2223
1638
  const [settingsBusy, setSettingsBusy] = (0, react.useState)(false);
2224
1639
  const [saveError, setSaveError] = (0, react.useState)(null);
2225
- const dirty = t$1(touched, value).length > 0;
1640
+ const dirty = (0, _jayyuen66_dsh_plugin_shared_client.diffTouched)(touched, value).length > 0;
2226
1641
  const setField = (field, draft) => {
2227
1642
  setTouched((prev) => ({
2228
1643
  ...prev,
@@ -2294,7 +1709,7 @@ function OcrCard(props) {
2294
1709
  t,
2295
1710
  writable
2296
1711
  });
2297
- return (0, react.createElement)(u, null, cliStatus, providerPanel, settingsSection, adminSection);
1712
+ return (0, react.createElement)(_jayyuen66_dsh_plugin_shared_client.CardForm, null, cliStatus, providerPanel, settingsSection, adminSection);
2298
1713
  }
2299
1714
  const inject = [
2300
1715
  "slots",
@@ -2302,11 +1717,11 @@ const inject = [
2302
1717
  "locale"
2303
1718
  ];
2304
1719
  function apply(ctx) {
2305
- if (!n$1(ctx, "ocrReviewCardApplied", "ocr-review-card: apply claim")) return;
1720
+ if (!(0, _jayyuen66_dsh_plugin_shared_client.claimApply)(ctx, "ocrReviewCardApplied", "ocr-review-card: apply claim")) return;
2306
1721
  ctx.effect(() => {
2307
1722
  const tag = document.createElement("style");
2308
1723
  tag.id = "ocr-review-card-css";
2309
- tag.textContent = `${CARD_CSS}\n${c}`;
1724
+ tag.textContent = `${CARD_CSS}\n${_jayyuen66_dsh_plugin_shared_client.CARD_UI_CSS}`;
2310
1725
  document.head.append(tag);
2311
1726
  return () => {
2312
1727
  tag.remove();