@blade-hq/agent-kit 0.4.7 → 0.4.10

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 (39) hide show
  1. package/dist/{SkillStatusBar-DQyipdzn.d.ts → SkillStatusBar-BnDtYUf9.d.ts} +2 -2
  2. package/dist/{blade-client-nOsdVlb1.d.ts → blade-client-n7fiBaFk.d.ts} +60 -2
  3. package/dist/{chunk-I3FFV63W.js → chunk-5ZFK62RQ.js} +2 -2
  4. package/dist/{chunk-OKQWPNE3.js → chunk-C3KSHIRA.js} +86 -5
  5. package/dist/chunk-C3KSHIRA.js.map +1 -0
  6. package/dist/{chunk-X6MEYCU7.js → chunk-CK7JMN5S.js} +228 -82
  7. package/dist/chunk-CK7JMN5S.js.map +1 -0
  8. package/dist/{chunk-4VWLTG5L.js → chunk-EDMS2G5P.js} +88 -17
  9. package/dist/chunk-EDMS2G5P.js.map +1 -0
  10. package/dist/{chunk-TC5BBLWO.js → chunk-EFNGK46B.js} +2 -2
  11. package/dist/{chunk-VD4CKRMT.js → chunk-FYPS4SFF.js} +2 -2
  12. package/dist/{chunk-CGOQI7ZL.js → chunk-TYCA6WYX.js} +98 -81
  13. package/dist/chunk-TYCA6WYX.js.map +1 -0
  14. package/dist/client/index.d.ts +395 -29
  15. package/dist/client/index.js +1 -1
  16. package/dist/{licenses-Cxl1xGVy.d.ts → licenses-BZpFl0qG.d.ts} +1 -1
  17. package/dist/react/api/licenses.d.ts +3 -3
  18. package/dist/react/api/licenses.js +3 -3
  19. package/dist/react/api/vibe-coding.d.ts +3 -3
  20. package/dist/react/api/vibe-coding.js +2 -2
  21. package/dist/react/components/chat/index.d.ts +4 -4
  22. package/dist/react/components/chat/index.js +5 -5
  23. package/dist/react/components/plan/index.js +3 -3
  24. package/dist/react/components/session/index.d.ts +1 -1
  25. package/dist/react/components/session/index.js +3 -3
  26. package/dist/react/components/workspace/index.js +3 -3
  27. package/dist/react/index.d.ts +64 -12
  28. package/dist/react/index.js +100 -63
  29. package/dist/react/index.js.map +1 -1
  30. package/dist/{session-CDeiO81j.d.ts → session-BKOc2lsz.d.ts} +9 -1
  31. package/dist/style.css +1 -1
  32. package/package.json +2 -1
  33. package/dist/chunk-4VWLTG5L.js.map +0 -1
  34. package/dist/chunk-CGOQI7ZL.js.map +0 -1
  35. package/dist/chunk-OKQWPNE3.js.map +0 -1
  36. package/dist/chunk-X6MEYCU7.js.map +0 -1
  37. /package/dist/{chunk-I3FFV63W.js.map → chunk-5ZFK62RQ.js.map} +0 -0
  38. /package/dist/{chunk-TC5BBLWO.js.map → chunk-EFNGK46B.js.map} +0 -0
  39. /package/dist/{chunk-VD4CKRMT.js.map → chunk-FYPS4SFF.js.map} +0 -0
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  getAuthedUrl,
7
7
  useUiStore
8
- } from "./chunk-4VWLTG5L.js";
8
+ } from "./chunk-EDMS2G5P.js";
9
9
  import {
10
10
  cn,
11
11
  copyToClipboard
@@ -43,6 +43,28 @@ var LANGUAGE_ALIASES = {
43
43
  yml: "yaml",
44
44
  zsh: "bash"
45
45
  };
46
+ var FILE_EXTENSION_ALIASES = {
47
+ ".bash": "bash",
48
+ ".css": "css",
49
+ ".go": "go",
50
+ ".htm": "html",
51
+ ".html": "html",
52
+ ".js": "javascript",
53
+ ".json": "json",
54
+ ".jsonc": "json",
55
+ ".jsx": "jsx",
56
+ ".md": "markdown",
57
+ ".mdx": "markdown",
58
+ ".py": "python",
59
+ ".rs": "rust",
60
+ ".scss": "css",
61
+ ".sh": "bash",
62
+ ".ts": "typescript",
63
+ ".tsx": "tsx",
64
+ ".yaml": "yaml",
65
+ ".yml": "yaml",
66
+ ".zsh": "bash"
67
+ };
46
68
  var highlighterPromise = null;
47
69
  var CACHE_MAX_SIZE = 200;
48
70
  var highlightCache = /* @__PURE__ */ new Map();
@@ -50,6 +72,12 @@ function normalizeCodeLanguage(language) {
50
72
  if (!language) return null;
51
73
  return LANGUAGE_ALIASES[language.trim().toLowerCase()] ?? null;
52
74
  }
75
+ function getCodeLanguageFromFilename(filePath) {
76
+ if (!filePath) return null;
77
+ const dotIndex = filePath.lastIndexOf(".");
78
+ if (dotIndex < 0) return null;
79
+ return FILE_EXTENSION_ALIASES[filePath.slice(dotIndex).toLowerCase()] ?? null;
80
+ }
53
81
  function useHighlightedCodeHtml(code, language) {
54
82
  const normalizedLanguage = useMemo(() => normalizeCodeLanguage(language), [language]);
55
83
  const [highlightedHtml, setHighlightedHtml] = useState(null);
@@ -126,7 +154,7 @@ async function loadCodeHighlighter() {
126
154
  html,
127
155
  javascript,
128
156
  json,
129
- jsx7,
157
+ jsx8,
130
158
  markdown,
131
159
  python,
132
160
  rust,
@@ -144,7 +172,7 @@ async function loadCodeHighlighter() {
144
172
  html.default,
145
173
  javascript.default,
146
174
  json.default,
147
- jsx7.default,
175
+ jsx8.default,
148
176
  markdown.default,
149
177
  python.default,
150
178
  rust.default,
@@ -343,15 +371,131 @@ function CardCodeBlock({ className, children, node, ...props }) {
343
371
 
344
372
  // src/react/components/markdown/MarkdownContent.tsx
345
373
  import { mermaid } from "@streamdown/mermaid";
346
- import { Check, Copy, Download } from "lucide-react";
374
+ import { Check as Check2, Copy as Copy2, Download } from "lucide-react";
347
375
  import {
348
- useEffect as useEffect2,
376
+ useEffect as useEffect3,
349
377
  useMemo as useMemo2,
350
378
  useRef,
351
- useState as useState2
379
+ useState as useState3
352
380
  } from "react";
353
381
  import { Streamdown } from "streamdown";
382
+
383
+ // src/react/components/markdown/ExternalLinkDialog.tsx
384
+ import { Check, Copy, ExternalLink, X } from "lucide-react";
385
+ import { useEffect as useEffect2, useState as useState2 } from "react";
386
+ import { createPortal } from "react-dom";
354
387
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
388
+ function ExternalLinkDialog({ isOpen, onClose, onConfirm, url }) {
389
+ const [copied, setCopied] = useState2(false);
390
+ useEffect2(() => {
391
+ if (!isOpen) return;
392
+ const handleKey = (event) => {
393
+ if (event.key === "Escape") onClose();
394
+ };
395
+ window.addEventListener("keydown", handleKey);
396
+ return () => window.removeEventListener("keydown", handleKey);
397
+ }, [isOpen, onClose]);
398
+ useEffect2(() => {
399
+ if (!isOpen) setCopied(false);
400
+ }, [isOpen]);
401
+ if (!isOpen) return null;
402
+ const handleCopy = async () => {
403
+ const ok = await copyToClipboard(url);
404
+ if (ok) {
405
+ setCopied(true);
406
+ setTimeout(() => setCopied(false), 2e3);
407
+ }
408
+ };
409
+ return createPortal(
410
+ /* @__PURE__ */ jsx4(
411
+ "div",
412
+ {
413
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4",
414
+ onClick: onClose,
415
+ onKeyDown: (event) => {
416
+ if (event.key === "Escape") onClose();
417
+ },
418
+ role: "dialog",
419
+ "aria-modal": "true",
420
+ "aria-labelledby": "external-link-dialog-title",
421
+ children: /* @__PURE__ */ jsxs3(
422
+ "div",
423
+ {
424
+ className: "w-full max-w-md overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background))] shadow-2xl",
425
+ onClick: (event) => event.stopPropagation(),
426
+ onKeyDown: (event) => event.stopPropagation(),
427
+ children: [
428
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-start justify-between gap-3 px-5 pt-5", children: [
429
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
430
+ /* @__PURE__ */ jsx4(ExternalLink, { size: 20, className: "text-[hsl(var(--foreground))]" }),
431
+ /* @__PURE__ */ jsx4(
432
+ "h3",
433
+ {
434
+ id: "external-link-dialog-title",
435
+ className: "text-lg font-semibold text-[hsl(var(--foreground))]",
436
+ children: "\u6253\u5F00\u5916\u90E8\u94FE\u63A5\uFF1F"
437
+ }
438
+ )
439
+ ] }),
440
+ /* @__PURE__ */ jsx4(
441
+ "button",
442
+ {
443
+ type: "button",
444
+ onClick: onClose,
445
+ title: "\u5173\u95ED",
446
+ className: "flex h-7 w-7 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]",
447
+ children: /* @__PURE__ */ jsx4(X, { size: 14 })
448
+ }
449
+ )
450
+ ] }),
451
+ /* @__PURE__ */ jsxs3("div", { className: "px-5 pt-2 pb-4", children: [
452
+ /* @__PURE__ */ jsx4("p", { className: "text-sm text-[hsl(var(--muted-foreground))]", children: "\u5373\u5C06\u8BBF\u95EE\u5916\u90E8\u7F51\u7AD9\uFF1A" }),
453
+ /* @__PURE__ */ jsx4("div", { className: "mt-3 break-all rounded-md bg-[hsl(var(--muted))] p-3 font-mono text-sm text-[hsl(var(--foreground))]", children: url })
454
+ ] }),
455
+ /* @__PURE__ */ jsxs3("div", { className: "flex justify-end gap-2 px-5 pb-5", children: [
456
+ /* @__PURE__ */ jsxs3(
457
+ "button",
458
+ {
459
+ type: "button",
460
+ onClick: handleCopy,
461
+ className: "inline-flex items-center gap-1.5 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--background))] px-3 py-1.5 text-sm font-medium text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))]",
462
+ children: [
463
+ copied ? /* @__PURE__ */ jsx4(Check, { size: 14 }) : /* @__PURE__ */ jsx4(Copy, { size: 14 }),
464
+ /* @__PURE__ */ jsx4("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u94FE\u63A5" })
465
+ ]
466
+ }
467
+ ),
468
+ /* @__PURE__ */ jsxs3(
469
+ "button",
470
+ {
471
+ type: "button",
472
+ onClick: () => {
473
+ onConfirm();
474
+ onClose();
475
+ },
476
+ className: "inline-flex items-center gap-1.5 rounded-md bg-[hsl(var(--primary))] px-3 py-1.5 text-sm font-semibold text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-90",
477
+ children: [
478
+ /* @__PURE__ */ jsx4(ExternalLink, { size: 14 }),
479
+ /* @__PURE__ */ jsx4("span", { children: "\u6253\u5F00\u94FE\u63A5" })
480
+ ]
481
+ }
482
+ )
483
+ ] })
484
+ ]
485
+ }
486
+ )
487
+ }
488
+ ),
489
+ document.body
490
+ );
491
+ }
492
+
493
+ // src/react/components/markdown/MarkdownContent.tsx
494
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
495
+ var LINK_SAFETY_CONFIG = {
496
+ enabled: true,
497
+ renderModal: (props) => /* @__PURE__ */ jsx5(ExternalLinkDialog, { ...props })
498
+ };
355
499
  var STREAMDOWN_PLUGINS = { mermaid };
356
500
  var SYSTEM_REMINDER_TAG = "system-reminder";
357
501
  var HIDDEN_SYSTEM_REMINDER_TAGS = {
@@ -362,9 +506,9 @@ var HIDDEN_SYSTEM_REMINDER_COMPONENTS = {
362
506
  };
363
507
  function CodeBlockPre({ children, node: _node, ...props }) {
364
508
  const preRef = useRef(null);
365
- const [copied, setCopied] = useState2(false);
366
- const [hasCodeNode, setHasCodeNode] = useState2(false);
367
- useEffect2(() => {
509
+ const [copied, setCopied] = useState3(false);
510
+ const [hasCodeNode, setHasCodeNode] = useState3(false);
511
+ useEffect3(() => {
368
512
  setHasCodeNode(!!preRef.current?.querySelector("code"));
369
513
  }, []);
370
514
  const getRawCode = () => preRef.current?.querySelector("code")?.textContent ?? "";
@@ -387,10 +531,10 @@ function CodeBlockPre({ children, node: _node, ...props }) {
387
531
  a.click();
388
532
  URL.revokeObjectURL(url);
389
533
  };
390
- return /* @__PURE__ */ jsxs3("div", { className: "relative group", children: [
391
- /* @__PURE__ */ jsx4("pre", { ref: preRef, ...props, children }),
392
- hasCodeNode && /* @__PURE__ */ jsxs3("div", { className: "absolute top-2 right-2 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity", children: [
393
- /* @__PURE__ */ jsxs3(
534
+ return /* @__PURE__ */ jsxs4("div", { className: "relative group", children: [
535
+ /* @__PURE__ */ jsx5("pre", { ref: preRef, ...props, children }),
536
+ hasCodeNode && /* @__PURE__ */ jsxs4("div", { className: "absolute top-2 right-2 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity", children: [
537
+ /* @__PURE__ */ jsxs4(
394
538
  "button",
395
539
  {
396
540
  type: "button",
@@ -400,20 +544,20 @@ function CodeBlockPre({ children, node: _node, ...props }) {
400
544
  copied ? "text-[hsl(var(--primary))]" : "text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))]"
401
545
  ),
402
546
  children: [
403
- copied ? /* @__PURE__ */ jsx4(Check, { size: 12 }) : /* @__PURE__ */ jsx4(Copy, { size: 12 }),
404
- /* @__PURE__ */ jsx4("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
547
+ copied ? /* @__PURE__ */ jsx5(Check2, { size: 12 }) : /* @__PURE__ */ jsx5(Copy2, { size: 12 }),
548
+ /* @__PURE__ */ jsx5("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
405
549
  ]
406
550
  }
407
551
  ),
408
- /* @__PURE__ */ jsxs3(
552
+ /* @__PURE__ */ jsxs4(
409
553
  "button",
410
554
  {
411
555
  type: "button",
412
556
  onClick: handleDownload,
413
557
  className: "flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[11px] transition-colors text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))]",
414
558
  children: [
415
- /* @__PURE__ */ jsx4(Download, { size: 12 }),
416
- /* @__PURE__ */ jsx4("span", { children: "\u4E0B\u8F7D" })
559
+ /* @__PURE__ */ jsx5(Download, { size: 12 }),
560
+ /* @__PURE__ */ jsx5("span", { children: "\u4E0B\u8F7D" })
417
561
  ]
418
562
  }
419
563
  )
@@ -463,10 +607,11 @@ function MarkdownContent({
463
607
  () => sessionId && typeof children === "string" ? resolveSessionImageMarkdown(children, sessionId) : children,
464
608
  [children, sessionId]
465
609
  );
466
- return /* @__PURE__ */ jsx4(
610
+ return /* @__PURE__ */ jsx5(
467
611
  Streamdown,
468
612
  {
469
613
  ...props,
614
+ linkSafety: LINK_SAFETY_CONFIG,
470
615
  mode: mode ?? "static",
471
616
  allowedTags: {
472
617
  ...allowedTags ?? {},
@@ -488,9 +633,9 @@ function MarkdownContent({
488
633
  }
489
634
 
490
635
  // src/react/components/chat/AskUserQuestionBlock.tsx
491
- import { Check as Check2, Loader2, MessageSquareMore } from "lucide-react";
492
- import { useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
493
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
636
+ import { Check as Check3, Loader2, MessageSquareMore } from "lucide-react";
637
+ import { useEffect as useEffect4, useMemo as useMemo3, useState as useState4 } from "react";
638
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
494
639
  function AskUserQuestionBlock({
495
640
  data,
496
641
  answered,
@@ -499,11 +644,11 @@ function AskUserQuestionBlock({
499
644
  answerData,
500
645
  onAnswer
501
646
  }) {
502
- const [selections, setSelections] = useState3(/* @__PURE__ */ new Map());
503
- const [customTexts, setCustomTexts] = useState3(/* @__PURE__ */ new Map());
504
- const [usingCustom, setUsingCustom] = useState3(/* @__PURE__ */ new Set());
505
- const [submitted, setSubmitted] = useState3(false);
506
- useEffect3(() => {
647
+ const [selections, setSelections] = useState4(/* @__PURE__ */ new Map());
648
+ const [customTexts, setCustomTexts] = useState4(/* @__PURE__ */ new Map());
649
+ const [usingCustom, setUsingCustom] = useState4(/* @__PURE__ */ new Set());
650
+ const [submitted, setSubmitted] = useState4(false);
651
+ useEffect4(() => {
507
652
  if (sessionStatus === "failed" || sessionStatus === "interrupted") {
508
653
  setSubmitted(false);
509
654
  }
@@ -600,7 +745,7 @@ ${parts.join("\n")}`;
600
745
  setSubmitted(true);
601
746
  onAnswer(text, toolCallId, nextAnswerData);
602
747
  };
603
- return /* @__PURE__ */ jsxs4(
748
+ return /* @__PURE__ */ jsxs5(
604
749
  "div",
605
750
  {
606
751
  className: cn(
@@ -608,12 +753,12 @@ ${parts.join("\n")}`;
608
753
  answered ? "max-w-2xl space-y-3 p-3 text-xs text-[hsl(var(--muted-foreground))] opacity-80" : "max-w-lg space-y-5 p-4 text-sm"
609
754
  ),
610
755
  children: [
611
- data.source_loop?.description && /* @__PURE__ */ jsxs4("div", { className: "rounded-lg bg-[hsl(var(--muted)/0.35)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
756
+ data.source_loop?.description && /* @__PURE__ */ jsxs5("div", { className: "rounded-lg bg-[hsl(var(--muted)/0.35)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
612
757
  "\u5B50\u667A\u80FD\u4F53\u300C",
613
758
  data.source_loop.description,
614
759
  "\u300D\u5728\u7B49\u5F85\u4F60\u7684\u56DE\u7B54"
615
760
  ] }),
616
- data.questions.map((q, qIdx) => /* @__PURE__ */ jsx5(
761
+ data.questions.map((q, qIdx) => /* @__PURE__ */ jsx6(
617
762
  QuestionCard,
618
763
  {
619
764
  question: q,
@@ -628,7 +773,7 @@ ${parts.join("\n")}`;
628
773
  },
629
774
  q.question
630
775
  )),
631
- !answered && !submitted && onAnswer && /* @__PURE__ */ jsx5(
776
+ !answered && !submitted && onAnswer && /* @__PURE__ */ jsx6(
632
777
  "button",
633
778
  {
634
779
  type: "button",
@@ -638,14 +783,14 @@ ${parts.join("\n")}`;
638
783
  children: allAnswered ? "\u786E\u8BA4" : "\u8BF7\u5148\u9009\u62E9\u4E00\u4E2A\u9009\u9879"
639
784
  }
640
785
  ),
641
- submitted && !answered && /* @__PURE__ */ jsxs4(
786
+ submitted && !answered && /* @__PURE__ */ jsxs5(
642
787
  "button",
643
788
  {
644
789
  type: "button",
645
790
  disabled: true,
646
791
  className: "flex w-full items-center justify-center gap-2 rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-xs font-semibold text-[hsl(var(--primary-foreground))] opacity-80",
647
792
  children: [
648
- /* @__PURE__ */ jsx5(Loader2, { size: 14, className: "animate-spin" }),
793
+ /* @__PURE__ */ jsx6(Loader2, { size: 14, className: "animate-spin" }),
649
794
  "\u786E\u8BA4\u4E2D"
650
795
  ]
651
796
  }
@@ -666,23 +811,23 @@ function QuestionCard({
666
811
  onCustomChange
667
812
  }) {
668
813
  const multi = question.multiSelect ?? false;
669
- return /* @__PURE__ */ jsxs4("div", { children: [
670
- /* @__PURE__ */ jsxs4("div", { className: cn("flex items-start gap-2", answered ? "mb-2" : "mb-3"), children: [
671
- /* @__PURE__ */ jsx5(
814
+ return /* @__PURE__ */ jsxs5("div", { children: [
815
+ /* @__PURE__ */ jsxs5("div", { className: cn("flex items-start gap-2", answered ? "mb-2" : "mb-3"), children: [
816
+ /* @__PURE__ */ jsx6(
672
817
  MessageSquareMore,
673
818
  {
674
819
  size: answered ? 12 : 13,
675
820
  className: "mt-0.5 shrink-0 text-[hsl(var(--primary))]"
676
821
  }
677
822
  ),
678
- /* @__PURE__ */ jsx5(
823
+ /* @__PURE__ */ jsx6(
679
824
  "div",
680
825
  {
681
826
  className: cn(
682
827
  "min-w-0 flex-1 font-medium text-[hsl(var(--foreground))]",
683
828
  answered ? "text-xs" : "text-sm"
684
829
  ),
685
- children: /* @__PURE__ */ jsx5(
830
+ children: /* @__PURE__ */ jsx6(
686
831
  MarkdownContent,
687
832
  {
688
833
  className: cn(
@@ -696,10 +841,10 @@ function QuestionCard({
696
841
  }
697
842
  )
698
843
  ] }),
699
- /* @__PURE__ */ jsxs4("div", { className: cn("flex flex-col pl-5", answered ? "gap-1" : "gap-1.5"), children: [
844
+ /* @__PURE__ */ jsxs5("div", { className: cn("flex flex-col pl-5", answered ? "gap-1" : "gap-1.5"), children: [
700
845
  question.options.map((opt, optIdx) => {
701
846
  const isSel = selected.has(optIdx);
702
- return /* @__PURE__ */ jsxs4(
847
+ return /* @__PURE__ */ jsxs5(
703
848
  "button",
704
849
  {
705
850
  type: "button",
@@ -713,15 +858,15 @@ function QuestionCard({
713
858
  answered && "cursor-default opacity-70"
714
859
  ),
715
860
  children: [
716
- multi && /* @__PURE__ */ jsx5(
861
+ multi && /* @__PURE__ */ jsx6(
717
862
  "div",
718
863
  {
719
864
  className: cn(
720
865
  "mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors",
721
866
  isSel && !answered ? "border-[hsl(var(--primary-foreground)/0.6)] bg-[hsl(var(--primary-foreground)/0.2)]" : isSel ? "border-[hsl(var(--primary)/0.45)] bg-[hsl(var(--primary)/0.12)]" : "border-[hsl(var(--border))]"
722
867
  ),
723
- children: isSel && /* @__PURE__ */ jsx5(
724
- Check2,
868
+ children: isSel && /* @__PURE__ */ jsx6(
869
+ Check3,
725
870
  {
726
871
  size: 9,
727
872
  className: answered ? "text-[hsl(var(--primary))]" : "text-[hsl(var(--primary-foreground))]"
@@ -729,9 +874,9 @@ function QuestionCard({
729
874
  )
730
875
  }
731
876
  ),
732
- /* @__PURE__ */ jsxs4("div", { className: "min-w-0", children: [
733
- /* @__PURE__ */ jsx5("div", { className: cn("font-medium", answered ? "text-xs" : "text-[13px]"), children: opt.label }),
734
- opt.description && /* @__PURE__ */ jsx5(
877
+ /* @__PURE__ */ jsxs5("div", { className: "min-w-0", children: [
878
+ /* @__PURE__ */ jsx6("div", { className: cn("font-medium", answered ? "text-xs" : "text-[13px]"), children: opt.label }),
879
+ opt.description && /* @__PURE__ */ jsx6(
735
880
  "div",
736
881
  {
737
882
  className: cn(
@@ -748,7 +893,7 @@ function QuestionCard({
748
893
  opt.label
749
894
  );
750
895
  }),
751
- answered && !isCustom ? null : /* @__PURE__ */ jsxs4(
896
+ answered && !isCustom ? null : /* @__PURE__ */ jsxs5(
752
897
  "div",
753
898
  {
754
899
  className: cn(
@@ -758,8 +903,8 @@ function QuestionCard({
758
903
  answered && "cursor-default opacity-70"
759
904
  ),
760
905
  children: [
761
- /* @__PURE__ */ jsx5("span", { className: "shrink-0 text-xs text-[hsl(var(--muted-foreground))]", children: "\u5176\u4ED6\uFF1A" }),
762
- /* @__PURE__ */ jsx5(
906
+ /* @__PURE__ */ jsx6("span", { className: "shrink-0 text-xs text-[hsl(var(--muted-foreground))]", children: "\u5176\u4ED6\uFF1A" }),
907
+ /* @__PURE__ */ jsx6(
763
908
  "input",
764
909
  {
765
910
  type: "text",
@@ -1150,8 +1295,8 @@ function extractRefs(content) {
1150
1295
 
1151
1296
  // src/react/components/plan/PlanSummaryCard.tsx
1152
1297
  import { CheckCircle2, ChevronRight, PencilLine, Play, Sparkles } from "lucide-react";
1153
- import { useMemo as useMemo4, useState as useState4 } from "react";
1154
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1298
+ import { useMemo as useMemo4, useState as useState5 } from "react";
1299
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1155
1300
  function PlanSummaryCard({
1156
1301
  messages,
1157
1302
  sessionStatus,
@@ -1171,25 +1316,25 @@ function PlanSummaryCard({
1171
1316
  }
1172
1317
  setActiveRightTab("situation");
1173
1318
  };
1174
- return /* @__PURE__ */ jsxs5("div", { className: "flex w-full flex-col gap-4 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card)/0.55)] p-4", children: [
1175
- /* @__PURE__ */ jsxs5(
1319
+ return /* @__PURE__ */ jsxs6("div", { className: "flex w-full flex-col gap-4 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card)/0.55)] p-4", children: [
1320
+ /* @__PURE__ */ jsxs6(
1176
1321
  "button",
1177
1322
  {
1178
1323
  type: "button",
1179
1324
  onClick: openPlanPanel,
1180
1325
  className: "flex w-full flex-col gap-4 text-left transition-colors hover:text-[hsl(var(--foreground))]",
1181
1326
  children: [
1182
- /* @__PURE__ */ jsxs5("div", { className: "flex items-start justify-between gap-3", children: [
1183
- /* @__PURE__ */ jsxs5("div", { className: "min-w-0 space-y-2", children: [
1184
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
1185
- /* @__PURE__ */ jsx6(Sparkles, { size: 12 }),
1186
- /* @__PURE__ */ jsx6("span", { children: "\u89C4\u5212\u6458\u8981" })
1327
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-start justify-between gap-3", children: [
1328
+ /* @__PURE__ */ jsxs6("div", { className: "min-w-0 space-y-2", children: [
1329
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
1330
+ /* @__PURE__ */ jsx7(Sparkles, { size: 12 }),
1331
+ /* @__PURE__ */ jsx7("span", { children: "\u89C4\u5212\u6458\u8981" })
1187
1332
  ] }),
1188
- /* @__PURE__ */ jsx6("div", { className: "truncate text-base font-medium text-[hsl(var(--foreground))]", children: data.intent || "\u5F53\u524D\u89C4\u5212" }),
1189
- /* @__PURE__ */ jsx6("div", { className: "flex flex-wrap items-center gap-2 text-xs", children: summaryState.kind === "progress" ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
1190
- /* @__PURE__ */ jsx6("span", { className: "rounded-full bg-[hsl(var(--accent))] px-2.5 py-1 text-[hsl(var(--foreground))]", children: summaryState.label }),
1191
- /* @__PURE__ */ jsx6("span", { className: "font-mono tracking-[0.25em] text-[hsl(var(--muted-foreground))]", children: summaryState.dots })
1192
- ] }) : /* @__PURE__ */ jsx6(
1333
+ /* @__PURE__ */ jsx7("div", { className: "truncate text-base font-medium text-[hsl(var(--foreground))]", children: data.intent || "\u5F53\u524D\u89C4\u5212" }),
1334
+ /* @__PURE__ */ jsx7("div", { className: "flex flex-wrap items-center gap-2 text-xs", children: summaryState.kind === "progress" ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
1335
+ /* @__PURE__ */ jsx7("span", { className: "rounded-full bg-[hsl(var(--accent))] px-2.5 py-1 text-[hsl(var(--foreground))]", children: summaryState.label }),
1336
+ /* @__PURE__ */ jsx7("span", { className: "font-mono tracking-[0.25em] text-[hsl(var(--muted-foreground))]", children: summaryState.dots })
1337
+ ] }) : /* @__PURE__ */ jsx7(
1193
1338
  "span",
1194
1339
  {
1195
1340
  className: cn(
@@ -1202,7 +1347,7 @@ function PlanSummaryCard({
1202
1347
  }
1203
1348
  ) })
1204
1349
  ] }),
1205
- /* @__PURE__ */ jsx6(
1350
+ /* @__PURE__ */ jsx7(
1206
1351
  ChevronRight,
1207
1352
  {
1208
1353
  size: 16,
@@ -1211,31 +1356,31 @@ function PlanSummaryCard({
1211
1356
  }
1212
1357
  )
1213
1358
  ] }),
1214
- summaryState.kind === "complete" && /* @__PURE__ */ jsxs5("div", { className: "flex flex-wrap items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
1215
- /* @__PURE__ */ jsxs5("span", { className: "rounded-full border border-[hsl(var(--border))] px-2.5 py-1", children: [
1359
+ summaryState.kind === "complete" && /* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
1360
+ /* @__PURE__ */ jsxs6("span", { className: "rounded-full border border-[hsl(var(--border))] px-2.5 py-1", children: [
1216
1361
  data.selectedSkills.length,
1217
1362
  " \u4E2A\u6280\u80FD"
1218
1363
  ] }),
1219
- /* @__PURE__ */ jsxs5("span", { className: "rounded-full border border-[hsl(var(--border))] px-2.5 py-1", children: [
1364
+ /* @__PURE__ */ jsxs6("span", { className: "rounded-full border border-[hsl(var(--border))] px-2.5 py-1", children: [
1220
1365
  stepCount,
1221
1366
  " \u4E2A\u6B65\u9AA4"
1222
1367
  ] }),
1223
- /* @__PURE__ */ jsxs5("span", { className: "inline-flex items-center gap-1 text-[hsl(var(--muted-foreground))]", children: [
1224
- /* @__PURE__ */ jsx6(CheckCircle2, { size: 12 }),
1368
+ /* @__PURE__ */ jsxs6("span", { className: "inline-flex items-center gap-1 text-[hsl(var(--muted-foreground))]", children: [
1369
+ /* @__PURE__ */ jsx7(CheckCircle2, { size: 12 }),
1225
1370
  "\u53F3\u4FA7\u67E5\u770B\u8BE6\u60C5"
1226
1371
  ] })
1227
1372
  ] })
1228
1373
  ]
1229
1374
  }
1230
1375
  ),
1231
- canConfirm && /* @__PURE__ */ jsx6(PlanConfirmationPanel, { onConfirmPlan })
1376
+ canConfirm && /* @__PURE__ */ jsx7(PlanConfirmationPanel, { onConfirmPlan })
1232
1377
  ] });
1233
1378
  }
1234
1379
  function PlanConfirmationPanel({
1235
1380
  onConfirmPlan
1236
1381
  }) {
1237
- const [isEditing, setIsEditing] = useState4(false);
1238
- const [revisionText, setRevisionText] = useState4("");
1382
+ const [isEditing, setIsEditing] = useState5(false);
1383
+ const [revisionText, setRevisionText] = useState5("");
1239
1384
  const submitRevision = () => {
1240
1385
  const trimmed = revisionText.trim();
1241
1386
  if (!trimmed) return;
@@ -1243,35 +1388,35 @@ function PlanConfirmationPanel({
1243
1388
  setRevisionText("");
1244
1389
  setIsEditing(false);
1245
1390
  };
1246
- return /* @__PURE__ */ jsxs5("div", { className: "space-y-3 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background)/0.45)] p-3", children: [
1247
- /* @__PURE__ */ jsxs5("div", { className: "flex flex-wrap gap-2", children: [
1248
- /* @__PURE__ */ jsxs5(
1391
+ return /* @__PURE__ */ jsxs6("div", { className: "space-y-3 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background)/0.45)] p-3", children: [
1392
+ /* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap gap-2", children: [
1393
+ /* @__PURE__ */ jsxs6(
1249
1394
  "button",
1250
1395
  {
1251
1396
  type: "button",
1252
1397
  onClick: () => onConfirmPlan?.("execute"),
1253
1398
  className: "inline-flex items-center gap-1.5 rounded-lg bg-[hsl(var(--primary))] px-3 py-2 text-sm font-medium text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-90",
1254
1399
  children: [
1255
- /* @__PURE__ */ jsx6(Play, { size: 14 }),
1400
+ /* @__PURE__ */ jsx7(Play, { size: 14 }),
1256
1401
  "\u5F00\u59CB\u6267\u884C"
1257
1402
  ]
1258
1403
  }
1259
1404
  ),
1260
- /* @__PURE__ */ jsxs5(
1405
+ /* @__PURE__ */ jsxs6(
1261
1406
  "button",
1262
1407
  {
1263
1408
  type: "button",
1264
1409
  onClick: () => setIsEditing((value) => !value),
1265
1410
  className: "inline-flex items-center gap-1.5 rounded-lg border border-[hsl(var(--border))] px-3 py-2 text-sm text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))]",
1266
1411
  children: [
1267
- /* @__PURE__ */ jsx6(PencilLine, { size: 14 }),
1412
+ /* @__PURE__ */ jsx7(PencilLine, { size: 14 }),
1268
1413
  "\u4FEE\u6539"
1269
1414
  ]
1270
1415
  }
1271
1416
  )
1272
1417
  ] }),
1273
- isEditing && /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
1274
- /* @__PURE__ */ jsx6(
1418
+ isEditing && /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1419
+ /* @__PURE__ */ jsx7(
1275
1420
  "textarea",
1276
1421
  {
1277
1422
  value: revisionText,
@@ -1280,7 +1425,7 @@ function PlanConfirmationPanel({
1280
1425
  className: "min-h-24 w-full resize-y rounded-lg border border-[hsl(var(--border))] bg-transparent px-3 py-2 text-sm text-[hsl(var(--foreground))] outline-none placeholder:text-[hsl(var(--muted-foreground))]"
1281
1426
  }
1282
1427
  ),
1283
- /* @__PURE__ */ jsx6("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx6(
1428
+ /* @__PURE__ */ jsx7("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx7(
1284
1429
  "button",
1285
1430
  {
1286
1431
  type: "button",
@@ -1387,6 +1532,7 @@ function extractLatestPlanMessages(messages) {
1387
1532
 
1388
1533
  export {
1389
1534
  normalizeCodeLanguage,
1535
+ getCodeLanguageFromFilename,
1390
1536
  useHighlightedCodeHtml,
1391
1537
  CardContext,
1392
1538
  useCardContext,
@@ -1398,4 +1544,4 @@ export {
1398
1544
  PlanSummaryCard,
1399
1545
  extractLatestPlanMessages
1400
1546
  };
1401
- //# sourceMappingURL=chunk-X6MEYCU7.js.map
1547
+ //# sourceMappingURL=chunk-CK7JMN5S.js.map