@springbrand/message-panel 0.2.0-alpha.47 → 0.2.0-alpha.49

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.
@@ -21,6 +21,7 @@ import {
21
21
  CollapsibleTrigger,
22
22
  } from "../primitives/collapsible";
23
23
  import { Tooltip } from "../primitives/tooltip";
24
+ import { ImagePreview } from "../file-view";
24
25
  import { WorkshopButton } from "../primitives/workshop-controls";
25
26
  import { MarkdownMessage } from "./markdown-message";
26
27
  import { collapsePanel } from "./surfaces";
@@ -305,17 +306,27 @@ export function AskUserAttachmentField({
305
306
  className="flex min-w-0 items-center gap-3 rounded-xl border border-kumo-line bg-kumo-elevated/55 p-2"
306
307
  >
307
308
  {attachment.status === "ready" && attachment.previewUrl
308
- ? (
309
+ ? image
310
+ ? (
311
+ <ImagePreview
312
+ src={attachment.previewUrl}
313
+ label={label}
314
+ placement="assistant-message"
315
+ >
316
+ {preview}
317
+ </ImagePreview>
318
+ )
319
+ : (
309
320
  <a
310
321
  href={attachment.previewUrl}
311
322
  target="_blank"
312
323
  rel="noopener noreferrer"
313
- aria-label={`${image ? "Preview" : "Open"} ${label}`}
324
+ aria-label={`Open ${label}`}
314
325
  className="rounded-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-kumo-brand/40"
315
326
  >
316
327
  {preview}
317
328
  </a>
318
- )
329
+ )
319
330
  : preview}
320
331
  <span className="flex min-w-0 flex-1 flex-col">
321
332
  <span className="truncate text-[13px] font-medium text-kumo-default">
@@ -403,6 +414,19 @@ export function AskUserBlock({
403
414
  const [inFlight, setInFlight] = useState(false);
404
415
  const [submissionError, setSubmissionError] = useState(false);
405
416
  const outcome = askUserOutcome(call);
417
+ const responseTimerRef = useRef<number | null>(null);
418
+ const hasAttachmentQuestion = questions.some(
419
+ (question) => question.kind === "attachment",
420
+ );
421
+ const clearResponseTimer = () => {
422
+ if (responseTimerRef.current === null) return;
423
+ window.clearTimeout(responseTimerRef.current);
424
+ responseTimerRef.current = null;
425
+ };
426
+ useEffect(() => () => clearResponseTimer(), []);
427
+ useEffect(() => {
428
+ if (outcome.kind !== "pending") clearResponseTimer();
429
+ }, [outcome.kind]);
406
430
  const displayAnswerAt = (index: number): DraftAnswer => {
407
431
  if (outcome.kind !== "answered") return answerAt(index);
408
432
  const answer = outcome.answers[index];
@@ -448,19 +472,28 @@ export function AskUserBlock({
448
472
  ),
449
473
  };
450
474
  setInFlight(true);
475
+ clearResponseTimer();
476
+ responseTimerRef.current = window.setTimeout(() => {
477
+ responseTimerRef.current = null;
478
+ setInFlight(false);
479
+ setSubmissionError(hasAttachmentQuestion);
480
+ }, 30_000);
451
481
  // 失败就把按钮放回可点:权威状态由 part 决定,这里只管别把用户锁死。
452
482
  void onRespond(call.toolCallId, response).then((ok) => {
453
483
  if (!ok) {
484
+ clearResponseTimer();
454
485
  setInFlight(false);
455
- setSubmissionError(true);
486
+ setSubmissionError(hasAttachmentQuestion);
456
487
  }
457
488
  }, () => {
489
+ clearResponseTimer();
458
490
  setInFlight(false);
459
- setSubmissionError(true);
491
+ setSubmissionError(hasAttachmentQuestion);
460
492
  });
461
493
  } catch {
494
+ clearResponseTimer();
462
495
  setInFlight(false);
463
- setSubmissionError(true);
496
+ setSubmissionError(hasAttachmentQuestion);
464
497
  }
465
498
  };
466
499
 
@@ -270,7 +270,7 @@ function ProductFileView({
270
270
  );
271
271
  }
272
272
 
273
- function ImagePreview({
273
+ export function ImagePreview({
274
274
  src,
275
275
  label,
276
276
  placement,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@springbrand/message-panel",
3
- "version": "0.2.0-alpha.47",
3
+ "version": "0.2.0-alpha.49",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src",