@blade-hq/agent-kit 0.4.8 → 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-CDmaNuOE.d.ts → SkillStatusBar-BnDtYUf9.d.ts} +2 -2
  2. package/dist/{blade-client-X5TOnkQa.d.ts → blade-client-n7fiBaFk.d.ts} +28 -2
  3. package/dist/{chunk-SAKSQ7OO.js → chunk-5ZFK62RQ.js} +2 -2
  4. package/dist/{chunk-DNT6RM5E.js → chunk-C3KSHIRA.js} +46 -5
  5. package/dist/chunk-C3KSHIRA.js.map +1 -0
  6. package/dist/{chunk-YFKHSFRB.js → chunk-CK7JMN5S.js} +228 -82
  7. package/dist/chunk-CK7JMN5S.js.map +1 -0
  8. package/dist/{chunk-TWZHUASA.js → chunk-EDMS2G5P.js} +86 -17
  9. package/dist/chunk-EDMS2G5P.js.map +1 -0
  10. package/dist/{chunk-I5BTVM3C.js → chunk-EFNGK46B.js} +2 -2
  11. package/dist/{chunk-MAMDVXTM.js → chunk-FYPS4SFF.js} +2 -2
  12. package/dist/{chunk-QO6CO372.js → chunk-TYCA6WYX.js} +98 -81
  13. package/dist/chunk-TYCA6WYX.js.map +1 -0
  14. package/dist/client/index.d.ts +203 -29
  15. package/dist/client/index.js +1 -1
  16. package/dist/{licenses-DWJmNvpn.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 +37 -12
  28. package/dist/react/index.js +21 -7
  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-DNT6RM5E.js.map +0 -1
  34. package/dist/chunk-QO6CO372.js.map +0 -1
  35. package/dist/chunk-TWZHUASA.js.map +0 -1
  36. package/dist/chunk-YFKHSFRB.js.map +0 -1
  37. /package/dist/{chunk-SAKSQ7OO.js.map → chunk-5ZFK62RQ.js.map} +0 -0
  38. /package/dist/{chunk-I5BTVM3C.js.map → chunk-EFNGK46B.js.map} +0 -0
  39. /package/dist/{chunk-MAMDVXTM.js.map → chunk-FYPS4SFF.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/lib/code-highlight.ts","../src/react/components/card/CardContext.tsx","../src/react/components/card/CardCodeBlock.tsx","../src/react/components/card/CardRenderer.tsx","../src/react/components/card/CardStates.tsx","../src/react/components/markdown/MarkdownContent.tsx","../src/react/components/markdown/ExternalLinkDialog.tsx","../src/react/components/chat/AskUserQuestionBlock.tsx","../src/react/components/plan/parse-plan-tree.ts","../src/react/components/plan/parse-plan-messages.ts","../src/react/components/plan/PlanSummaryCard.tsx","../src/react/components/plan/extract-plan-messages.ts"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\"\n\nconst DARK_THEME = \"github-dark-default\"\nconst LIGHT_THEME = \"github-light-default\"\n\nconst SUPPORTED_LANGUAGES = [\n \"python\",\n \"javascript\",\n \"typescript\",\n \"tsx\",\n \"jsx\",\n \"yaml\",\n \"markdown\",\n \"bash\",\n \"json\",\n \"go\",\n \"rust\",\n \"css\",\n \"html\",\n] as const\n\nexport type SupportedCodeLanguage = (typeof SUPPORTED_LANGUAGES)[number]\n\nconst LANGUAGE_ALIASES: Record<string, SupportedCodeLanguage> = {\n bash: \"bash\",\n css: \"css\",\n go: \"go\",\n golang: \"go\",\n htm: \"html\",\n html: \"html\",\n javascript: \"javascript\",\n js: \"javascript\",\n json: \"json\",\n jsonc: \"json\",\n jsx: \"jsx\",\n markdown: \"markdown\",\n md: \"markdown\",\n py: \"python\",\n python: \"python\",\n rs: \"rust\",\n rust: \"rust\",\n scss: \"css\",\n sh: \"bash\",\n shell: \"bash\",\n ts: \"typescript\",\n tsx: \"tsx\",\n typescript: \"typescript\",\n yaml: \"yaml\",\n yml: \"yaml\",\n zsh: \"bash\",\n}\n\nconst FILE_EXTENSION_ALIASES: Record<string, SupportedCodeLanguage> = {\n \".bash\": \"bash\",\n \".css\": \"css\",\n \".go\": \"go\",\n \".htm\": \"html\",\n \".html\": \"html\",\n \".js\": \"javascript\",\n \".json\": \"json\",\n \".jsonc\": \"json\",\n \".jsx\": \"jsx\",\n \".md\": \"markdown\",\n \".mdx\": \"markdown\",\n \".py\": \"python\",\n \".rs\": \"rust\",\n \".scss\": \"css\",\n \".sh\": \"bash\",\n \".ts\": \"typescript\",\n \".tsx\": \"tsx\",\n \".yaml\": \"yaml\",\n \".yml\": \"yaml\",\n \".zsh\": \"bash\",\n}\n\ntype CodeHighlighter = {\n codeToHtml: (\n code: string,\n options: {\n lang: SupportedCodeLanguage\n themes: { light: string; dark: string }\n defaultColor?: false\n },\n ) => string\n}\n\nlet highlighterPromise: Promise<CodeHighlighter> | null = null\n\nconst CACHE_MAX_SIZE = 200\nconst highlightCache = new Map<string, Promise<string | null>>()\n\nexport function normalizeCodeLanguage(language?: string | null): SupportedCodeLanguage | null {\n if (!language) return null\n\n return LANGUAGE_ALIASES[language.trim().toLowerCase()] ?? null\n}\n\nexport function getCodeLanguageFromFilename(filePath?: string | null): SupportedCodeLanguage | null {\n if (!filePath) return null\n\n const dotIndex = filePath.lastIndexOf(\".\")\n if (dotIndex < 0) return null\n\n return FILE_EXTENSION_ALIASES[filePath.slice(dotIndex).toLowerCase()] ?? null\n}\n\nexport function useHighlightedCodeHtml(code: string, language?: string | null) {\n const normalizedLanguage = useMemo(() => normalizeCodeLanguage(language), [language])\n const [highlightedHtml, setHighlightedHtml] = useState<string | null>(null)\n\n useEffect(() => {\n let cancelled = false\n\n setHighlightedHtml(null)\n\n if (!normalizedLanguage) {\n return () => {\n cancelled = true\n }\n }\n\n void highlightCodeToInnerHtml(code, normalizedLanguage).then((result) => {\n if (!cancelled) {\n setHighlightedHtml(result)\n }\n })\n\n return () => {\n cancelled = true\n }\n }, [code, normalizedLanguage])\n\n return { highlightedHtml, language: normalizedLanguage }\n}\n\nasync function highlightCodeToInnerHtml(code: string, language: SupportedCodeLanguage) {\n const cacheKey = `${language}\\u0000${code}`\n const cached = highlightCache.get(cacheKey)\n\n if (cached) {\n return cached\n }\n\n const request = loadCodeHighlighter()\n .then((highlighter) => {\n const html = highlighter.codeToHtml(code, {\n lang: language,\n themes: { light: LIGHT_THEME, dark: DARK_THEME },\n defaultColor: false,\n })\n return extractInnerCodeHtml(html)\n })\n .catch(() => {\n highlightCache.delete(cacheKey)\n return null\n })\n\n if (highlightCache.size >= CACHE_MAX_SIZE) {\n const oldest = highlightCache.keys().next().value\n if (oldest !== undefined) highlightCache.delete(oldest)\n }\n highlightCache.set(cacheKey, request)\n return request\n}\n\nasync function loadCodeHighlighter(): Promise<CodeHighlighter> {\n if (!highlighterPromise) {\n highlighterPromise = Promise.all([\n import(\"shiki/core\"),\n import(\"shiki/engine/javascript\"),\n import(\"@shikijs/langs/bash\"),\n import(\"@shikijs/langs/css\"),\n import(\"@shikijs/langs/go\"),\n import(\"@shikijs/langs/html\"),\n import(\"@shikijs/langs/javascript\"),\n import(\"@shikijs/langs/json\"),\n import(\"@shikijs/langs/jsx\"),\n import(\"@shikijs/langs/markdown\"),\n import(\"@shikijs/langs/python\"),\n import(\"@shikijs/langs/rust\"),\n import(\"@shikijs/langs/tsx\"),\n import(\"@shikijs/langs/typescript\"),\n import(\"@shikijs/langs/yaml\"),\n import(\"@shikijs/themes/github-dark-default\"),\n import(\"@shikijs/themes/github-light-default\"),\n ]).then(\n ([\n core,\n engine,\n bash,\n css,\n go,\n html,\n javascript,\n json,\n jsx,\n markdown,\n python,\n rust,\n tsx,\n typescript,\n yaml,\n darkTheme,\n lightTheme,\n ]) =>\n core.createHighlighterCore({\n engine: engine.createJavaScriptRegexEngine(),\n langs: [\n bash.default,\n css.default,\n go.default,\n html.default,\n javascript.default,\n json.default,\n jsx.default,\n markdown.default,\n python.default,\n rust.default,\n tsx.default,\n typescript.default,\n yaml.default,\n ],\n themes: [darkTheme.default, lightTheme.default],\n }),\n ).catch((err) => {\n highlighterPromise = null\n throw err\n })\n }\n\n return highlighterPromise as Promise<CodeHighlighter>\n}\n\nfunction extractInnerCodeHtml(html: string) {\n const match = html.match(/<code[^>]*>([\\s\\S]*)<\\/code><\\/pre>\\s*$/)\n return match?.[1] ?? null\n}\n","import { createContext, useContext } from \"react\"\n\nexport interface CardContextValue {\n sendMessage?: (content: string) => Promise<void>\n sessionId?: string\n messageId?: string\n}\n\nexport const CardContext = createContext<CardContextValue>({})\n\nexport const useCardContext = () => useContext(CardContext)\n","import type { JSX } from \"react\"\nimport { useIsCodeFenceIncomplete } from \"streamdown\"\nimport type { ExtraProps } from \"streamdown\"\nimport { CardJSON } from \"../../lib/card-registry\"\nimport { normalizeCodeLanguage, useHighlightedCodeHtml } from \"../../lib/code-highlight\"\nimport { CardRenderer } from \"./CardRenderer\"\n\ntype CodeProps = JSX.IntrinsicElements[\"code\"] & ExtraProps\n\nexport function CardCodeBlock({ className, children, node, ...props }: CodeProps) {\n const isIncomplete = useIsCodeFenceIncomplete()\n const match = /language-(\\S+)/.exec(className || \"\")\n const lang = match?.[1]\n const isInline = !className\n const raw = String(children ?? \"\")\n const normalizedLang = normalizeCodeLanguage(lang)\n const { highlightedHtml } = useHighlightedCodeHtml(raw, normalizedLang)\n\n if (!isInline && CardJSON.isCardsLanguage(lang)) {\n return (\n <CardRenderer\n raw={raw}\n blockPosition={node?.position?.start?.line}\n isCodeFenceIncomplete={isIncomplete}\n />\n )\n }\n\n if (!isInline && highlightedHtml) {\n return (\n <code\n className={className}\n {...props}\n // biome-ignore lint/security/noDangerouslySetInnerHtml: syntax highlighting output is generated locally\n dangerouslySetInnerHTML={{ __html: highlightedHtml }}\n />\n )\n }\n\n return (\n <code className={className} {...props}>\n {children}\n </code>\n )\n}\n","import { Component, type ErrorInfo, type ReactNode } from \"react\"\nimport { type Card, CardJSON, cardRegistry } from \"../../lib/card-registry\"\nimport { useUiStore } from \"../../stores/ui-store\"\nimport { useCardContext } from \"./CardContext\"\nimport { CardErrorState, CardLoadingState, CardWarningState } from \"./CardStates\"\n\ninterface Props {\n raw: string\n blockPosition?: number\n isCodeFenceIncomplete?: boolean\n}\n\nfunction looksIncomplete(text: string): boolean {\n const t = text.trim()\n if (!t) return true\n const openBraces = (t.match(/{/g) || []).length\n const closeBraces = (t.match(/}/g) || []).length\n const openBrackets = (t.match(/\\[/g) || []).length\n const closeBrackets = (t.match(/]/g) || []).length\n const quotes = (t.match(/\"/g) || []).length\n\n return (\n (!t.endsWith(\"}\") && !t.endsWith(\"]\")) ||\n openBraces !== closeBraces ||\n openBrackets !== closeBrackets ||\n t.endsWith(\",\") ||\n t.endsWith(\":\") ||\n quotes % 2 !== 0\n )\n}\n\ninterface ErrorBoundaryProps {\n fallback: ReactNode\n children: ReactNode\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean\n}\n\nclass CardErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n state: ErrorBoundaryState = { hasError: false }\n\n static getDerivedStateFromError(): ErrorBoundaryState {\n return { hasError: true }\n }\n\n componentDidCatch(error: Error, info: ErrorInfo) {\n console.error(\"Card render error:\", error, info)\n }\n\n render() {\n if (this.state.hasError) return this.props.fallback\n return this.props.children\n }\n}\n\nfunction OpenInPreviewButton({ card }: { card: Card }) {\n const pushArtifact = useUiStore((s) => s.pushArtifact)\n\n return (\n <button\n type=\"button\"\n onClick={() =>\n pushArtifact({\n type: \"card\",\n content: JSON.stringify(card, null, 2),\n title: card.title || card.type,\n key: `card-${card.id}`,\n })\n }\n className=\"absolute right-2 top-2 rounded bg-[hsl(var(--accent))] px-1.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))] opacity-0 transition-opacity group-hover/card:opacity-100 hover:text-[hsl(var(--foreground))]\"\n >\n 预览\n </button>\n )\n}\n\nexport function CardRenderer({ raw, blockPosition, isCodeFenceIncomplete }: Props) {\n const { sessionId, messageId, sendMessage } = useCardContext()\n const trimmed = raw.trim()\n\n if (!trimmed) return <CardLoadingState content=\"\" />\n\n // If code fence is still streaming, show loading\n if (isCodeFenceIncomplete) {\n return <CardLoadingState content={trimmed} />\n }\n\n const parsed = CardJSON.safeParseJSON(trimmed)\n\n if (!parsed.ok) {\n if (looksIncomplete(trimmed)) {\n return <CardLoadingState content={trimmed} />\n }\n return <CardErrorState content={trimmed} message={parsed.error} />\n }\n\n const cards = CardJSON.toCardArray(parsed.value)\n if (!cards) {\n return <CardWarningState content={trimmed} message=\"JSON 格式正确但不符合卡片结构\" />\n }\n\n const cardsWithIds = cards.map((c, i) => {\n if (c.id) return c\n return {\n ...c,\n id: `${messageId || \"msg\"}-block-${blockPosition ?? 0}-card-${i}`,\n }\n })\n\n return (\n <>\n {cardsWithIds.map((card) => {\n const CardComponent = cardRegistry.get(card.type)\n if (!CardComponent) {\n return (\n <CardWarningState\n key={card.id}\n content={JSON.stringify(card, null, 2)}\n message={`未知的卡片类型: ${card.type}`}\n />\n )\n }\n return (\n <div key={card.id} className=\"group/card relative my-4\">\n <CardErrorBoundary\n fallback={\n <CardErrorState\n content={JSON.stringify(card, null, 2)}\n message=\"卡片渲染出错\"\n />\n }\n >\n <CardComponent card={card} sendMessage={sendMessage} sessionId={sessionId} />\n <OpenInPreviewButton card={card} />\n </CardErrorBoundary>\n </div>\n )\n })}\n </>\n )\n}\n","interface CardStateProps {\n content: string\n message?: string\n}\n\nexport function CardLoadingState({ content }: CardStateProps) {\n return (\n <div className=\"my-4 rounded-md border border-[hsl(var(--primary)/0.2)] bg-[hsl(var(--primary)/0.05)] p-4\">\n <div className=\"mb-2 flex items-center gap-2\">\n <div className=\"h-4 w-4 animate-spin rounded-full border-2 border-[hsl(var(--primary))] border-t-transparent\" />\n <p className=\"text-sm text-[hsl(var(--primary))]\">正在加载卡片数据...</p>\n </div>\n <details className=\"mt-2\">\n <summary className=\"cursor-pointer text-xs text-[hsl(var(--primary)/0.7)]\">查看接收中的数据</summary>\n <pre className=\"mt-1 whitespace-pre-wrap rounded bg-[hsl(var(--primary)/0.1)] p-2 font-mono text-xs text-[hsl(var(--primary)/0.8)]\">\n {content}\n </pre>\n </details>\n </div>\n )\n}\n\nexport function CardErrorState({ content, message }: CardStateProps) {\n return (\n <div className=\"my-4 rounded-md border border-red-500/20 bg-red-500/5 p-4\">\n <p className=\"mb-2 text-sm text-red-400\">{message || \"卡片数据解析失败\"}</p>\n <details className=\"mt-2\">\n <summary className=\"cursor-pointer text-xs text-red-400/70 hover:underline\">\n 查看原始代码块\n </summary>\n <pre className=\"mt-2 overflow-x-auto whitespace-pre-wrap rounded bg-red-500/10 p-3 font-mono text-xs text-red-400/80\">\n {content}\n </pre>\n </details>\n </div>\n )\n}\n\nexport function CardWarningState({ content, message }: CardStateProps) {\n return (\n <div className=\"my-4 rounded-md border border-yellow-500/20 bg-yellow-500/5 p-4\">\n <p className=\"mb-2 text-sm text-yellow-400\">{message || \"数据格式不符合卡片要求\"}</p>\n <details className=\"mt-2\">\n <summary className=\"cursor-pointer text-xs text-yellow-400/70\">查看原始数据</summary>\n <pre className=\"mt-1 whitespace-pre-wrap rounded bg-yellow-500/10 p-2 font-mono text-xs text-yellow-400/80\">\n {content}\n </pre>\n </details>\n </div>\n )\n}\n","import { mermaid } from \"@streamdown/mermaid\"\nimport { Check, Copy, Download } from \"lucide-react\"\nimport {\n type ComponentProps,\n type ComponentPropsWithRef,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\"\nimport { type ExtraProps, Streamdown } from \"streamdown\"\nimport { getAuthedUrl } from \"../../api/client\"\nimport { cn, copyToClipboard } from \"../../lib/utils\"\nimport { CardCodeBlock } from \"../card/CardCodeBlock\"\nimport { ExternalLinkDialog } from \"./ExternalLinkDialog\"\n\ntype StreamdownProps = ComponentProps<typeof Streamdown>\n\nconst LINK_SAFETY_CONFIG: NonNullable<StreamdownProps[\"linkSafety\"]> = {\n enabled: true,\n renderModal: (props) => <ExternalLinkDialog {...props} />,\n}\n\nconst STREAMDOWN_PLUGINS = { mermaid } satisfies NonNullable<StreamdownProps[\"plugins\"]>\n\nconst SYSTEM_REMINDER_TAG = \"system-reminder\"\nconst HIDDEN_SYSTEM_REMINDER_TAGS: NonNullable<StreamdownProps[\"allowedTags\"]> = {\n [SYSTEM_REMINDER_TAG]: [],\n}\nconst HIDDEN_SYSTEM_REMINDER_COMPONENTS = {\n [SYSTEM_REMINDER_TAG]: () => null,\n} as NonNullable<StreamdownProps[\"components\"]>\n\ntype PreProps = ComponentPropsWithRef<\"pre\"> & ExtraProps\n\nfunction CodeBlockPre({ children, node: _node, ...props }: PreProps) {\n const preRef = useRef<HTMLPreElement>(null)\n const [copied, setCopied] = useState(false)\n const [hasCodeNode, setHasCodeNode] = useState(false)\n\n useEffect(() => {\n setHasCodeNode(!!preRef.current?.querySelector(\"code\"))\n }, [])\n\n const getRawCode = () => preRef.current?.querySelector(\"code\")?.textContent ?? \"\"\n\n const handleCopy = async () => {\n const ok = await copyToClipboard(getRawCode())\n if (ok) {\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n }\n }\n\n const handleDownload = () => {\n const codeEl = preRef.current?.querySelector(\"code\")\n const text = codeEl?.textContent ?? \"\"\n const ext = codeEl?.className.match(/language-(\\S+)/)?.[1] ?? \"txt\"\n const blob = new Blob([text], { type: \"text/plain\" })\n const url = URL.createObjectURL(blob)\n const a = document.createElement(\"a\")\n a.href = url\n a.download = `code.${ext}`\n a.click()\n URL.revokeObjectURL(url)\n }\n\n return (\n <div className=\"relative group\">\n <pre ref={preRef} {...props}>\n {children}\n </pre>\n {hasCodeNode && (\n <div className=\"absolute top-2 right-2 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity\">\n <button\n type=\"button\"\n onClick={handleCopy}\n className={cn(\n \"flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[11px] transition-colors\",\n copied\n ? \"text-[hsl(var(--primary))]\"\n : \"text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))]\",\n )}\n >\n {copied ? <Check size={12} /> : <Copy size={12} />}\n <span>{copied ? \"已复制\" : \"复制\"}</span>\n </button>\n <button\n type=\"button\"\n onClick={handleDownload}\n 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))]\"\n >\n <Download size={12} />\n <span>下载</span>\n </button>\n </div>\n )}\n </div>\n )\n}\n\nfunction isExternalImageSrc(src: string): boolean {\n if (!src) return false\n if (src.startsWith(\"data:\") || src.startsWith(\"blob:\")) return true\n if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(src)) return true\n if (src.startsWith(\"/\")) return true\n return false\n}\n\nfunction decodeMarkdownPath(src: string): string {\n try {\n return decodeURIComponent(src)\n } catch {\n return src\n }\n}\n\nconst MARKDOWN_IMAGE_PATTERN =\n /!\\[((?:\\\\.|[^\\]\\\\])*)\\]\\(\\s*(?:<([^>\\n]+)>|([^\\s)]+))(\\s+(?:\"[^\"]*\"|'[^']*'|\\([^)]*\\)))?\\s*\\)/g\n\nfunction resolveSessionImageMarkdown(children: string, sessionId: string): string {\n return children.replace(\n MARKDOWN_IMAGE_PATTERN,\n (match, alt: string, angleSrc: string | undefined, plainSrc: string | undefined, title = \"\") => {\n const src = angleSrc ?? plainSrc\n if (!src || isExternalImageSrc(src)) {\n return match\n }\n\n const resolved = getAuthedUrl(\n `/api/sessions/${encodeURIComponent(sessionId)}/files/${encodeURIComponent(decodeMarkdownPath(src))}`,\n )\n return `![${alt}](<${resolved}>${title})`\n },\n )\n}\n\ntype MarkdownContentProps = StreamdownProps & {\n /** 当提供时,markdown 中相对路径的 <img> src 会解析为 session 工作区文件 URL */\n sessionId?: string\n}\n\nexport function MarkdownContent({\n allowedTags,\n children,\n components,\n mode,\n plugins,\n sessionId,\n ...props\n}: MarkdownContentProps) {\n const resolvedChildren = useMemo(\n () =>\n sessionId && typeof children === \"string\"\n ? resolveSessionImageMarkdown(children, sessionId)\n : children,\n [children, sessionId],\n )\n\n return (\n <Streamdown\n {...props}\n linkSafety={LINK_SAFETY_CONFIG}\n mode={mode ?? \"static\"}\n allowedTags={{\n ...(allowedTags ?? {}),\n ...HIDDEN_SYSTEM_REMINDER_TAGS,\n }}\n components={{\n code: CardCodeBlock,\n pre: CodeBlockPre,\n ...(components ?? {}),\n ...HIDDEN_SYSTEM_REMINDER_COMPONENTS,\n }}\n plugins={{\n ...STREAMDOWN_PLUGINS,\n ...(plugins ?? {}),\n }}\n >\n {resolvedChildren}\n </Streamdown>\n )\n}\n","import { Check, Copy, ExternalLink, X } from \"lucide-react\"\nimport { useEffect, useState } from \"react\"\nimport { createPortal } from \"react-dom\"\nimport { copyToClipboard } from \"../../lib/utils\"\n\ninterface Props {\n isOpen: boolean\n onClose: () => void\n onConfirm: () => void\n url: string\n}\n\nexport function ExternalLinkDialog({ isOpen, onClose, onConfirm, url }: Props) {\n const [copied, setCopied] = useState(false)\n\n useEffect(() => {\n if (!isOpen) return\n const handleKey = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") onClose()\n }\n window.addEventListener(\"keydown\", handleKey)\n return () => window.removeEventListener(\"keydown\", handleKey)\n }, [isOpen, onClose])\n\n useEffect(() => {\n if (!isOpen) setCopied(false)\n }, [isOpen])\n\n if (!isOpen) return null\n\n const handleCopy = async () => {\n const ok = await copyToClipboard(url)\n if (ok) {\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n }\n }\n\n return createPortal(\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4\"\n onClick={onClose}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") onClose()\n }}\n // biome-ignore lint/a11y/useSemanticElements: 外层 div 作为可点击关闭的 backdrop\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"external-link-dialog-title\"\n >\n <div\n className=\"w-full max-w-md overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background))] shadow-2xl\"\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n >\n <div className=\"flex items-start justify-between gap-3 px-5 pt-5\">\n <div className=\"flex items-center gap-2\">\n <ExternalLink size={20} className=\"text-[hsl(var(--foreground))]\" />\n <h3\n id=\"external-link-dialog-title\"\n className=\"text-lg font-semibold text-[hsl(var(--foreground))]\"\n >\n 打开外部链接?\n </h3>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n title=\"关闭\"\n 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))]\"\n >\n <X size={14} />\n </button>\n </div>\n <div className=\"px-5 pt-2 pb-4\">\n <p className=\"text-sm text-[hsl(var(--muted-foreground))]\">即将访问外部网站:</p>\n <div className=\"mt-3 break-all rounded-md bg-[hsl(var(--muted))] p-3 font-mono text-sm text-[hsl(var(--foreground))]\">\n {url}\n </div>\n </div>\n <div className=\"flex justify-end gap-2 px-5 pb-5\">\n <button\n type=\"button\"\n onClick={handleCopy}\n 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))]\"\n >\n {copied ? <Check size={14} /> : <Copy size={14} />}\n <span>{copied ? \"已复制\" : \"复制链接\"}</span>\n </button>\n <button\n type=\"button\"\n onClick={() => {\n onConfirm()\n onClose()\n }}\n 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\"\n >\n <ExternalLink size={14} />\n <span>打开链接</span>\n </button>\n </div>\n </div>\n </div>,\n document.body,\n )\n}\n","import { Check, Loader2, MessageSquareMore } from \"lucide-react\"\nimport { useEffect, useMemo, useState } from \"react\"\nimport { cn } from \"../../lib/utils\"\nimport { MarkdownContent } from \"../markdown/MarkdownContent\"\n\ninterface OptionItem {\n label: string\n description: string\n}\n\ninterface QuestionItem {\n question: string\n options: OptionItem[]\n multiSelect?: boolean\n}\n\ninterface SourceLoopInfo {\n loop_name: string\n description: string\n}\n\ninterface AskUserQuestionData {\n questions: QuestionItem[]\n source_loop?: SourceLoopInfo | null\n}\n\nexport type AskUserAnswerData = {\n selections: Record<number, number[]>\n custom: Record<number, string>\n}\n\ninterface Props {\n data: AskUserQuestionData\n answered: boolean\n toolCallId: string\n sessionStatus: string\n answerData?: AskUserAnswerData | undefined\n onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void\n}\n\nexport function AskUserQuestionBlock({\n data,\n answered,\n toolCallId,\n sessionStatus,\n answerData,\n onAnswer,\n}: Props) {\n // Per-question state: selected option indices or custom text\n const [selections, setSelections] = useState<Map<number, Set<number>>>(new Map())\n const [customTexts, setCustomTexts] = useState<Map<number, string>>(new Map())\n const [usingCustom, setUsingCustom] = useState<Set<number>>(new Set())\n const [submitted, setSubmitted] = useState(false)\n\n useEffect(() => {\n if (sessionStatus === \"failed\" || sessionStatus === \"interrupted\") {\n setSubmitted(false)\n }\n }, [sessionStatus])\n\n const displayAnswerState = useMemo(() => {\n if (!(answered && answerData)) {\n return {\n selections,\n customTexts,\n usingCustom,\n }\n }\n\n const nextSelections = new Map<number, Set<number>>()\n const nextCustomTexts = new Map<number, string>()\n const nextUsingCustom = new Set<number>()\n\n for (const [questionKey, optionIndexes] of Object.entries(answerData.selections)) {\n nextSelections.set(Number(questionKey), new Set(optionIndexes))\n }\n\n for (const [questionKey, text] of Object.entries(answerData.custom)) {\n const qIdx = Number(questionKey)\n nextCustomTexts.set(qIdx, text)\n nextUsingCustom.add(qIdx)\n }\n\n return {\n selections: nextSelections,\n customTexts: nextCustomTexts,\n usingCustom: nextUsingCustom,\n }\n }, [answerData, answered, customTexts, selections, usingCustom])\n\n const displaySelections = displayAnswerState.selections\n const displayCustomTexts = displayAnswerState.customTexts\n const displayUsingCustom = displayAnswerState.usingCustom\n\n const toggleOption = (qIdx: number, optIdx: number, multi: boolean) => {\n if (answered || submitted) return\n setSelections((prev) => {\n const next = new Map(prev)\n const current = new Set(next.get(qIdx) ?? [])\n if (multi) {\n if (current.has(optIdx)) current.delete(optIdx)\n else current.add(optIdx)\n } else {\n current.clear()\n current.add(optIdx)\n }\n next.set(qIdx, current)\n return next\n })\n // Clear custom for this question\n setUsingCustom((prev) => {\n const next = new Set(prev)\n next.delete(qIdx)\n return next\n })\n }\n\n const handleCustomFocus = (qIdx: number) => {\n if (answered || submitted) return\n setSelections((prev) => {\n const next = new Map(prev)\n next.delete(qIdx)\n return next\n })\n setUsingCustom((prev) => new Set(prev).add(qIdx))\n }\n\n const setCustomText = (qIdx: number, text: string) => {\n if (answered || submitted) return\n setCustomTexts((prev) => new Map(prev).set(qIdx, text))\n }\n\n const getAnswer = (qIdx: number): string | null => {\n const q = data.questions[qIdx]\n if (usingCustom.has(qIdx)) {\n const text = (customTexts.get(qIdx) ?? \"\").trim()\n return text || null\n }\n const sel = selections.get(qIdx)\n if (!sel || sel.size === 0) return null\n return [...sel]\n .sort()\n .map((i) => q.options[i].label)\n .join(\", \")\n }\n\n const allAnswered = data.questions.every((_, i) => getAnswer(i) !== null)\n\n const handleSubmit = () => {\n if (answered || submitted || !allAnswered || !onAnswer) return\n\n const nextAnswerData: AskUserAnswerData = {\n selections: Object.fromEntries(\n Array.from(selections.entries()).map(([qIdx, optionIndexes]) => [\n qIdx,\n Array.from(optionIndexes).sort((a, b) => a - b),\n ]),\n ) as Record<number, number[]>,\n custom: Object.fromEntries(\n Array.from(usingCustom)\n .map((qIdx) => [qIdx, (customTexts.get(qIdx) ?? \"\").trim()] as const)\n .filter(([, text]) => text.length > 0),\n ) as Record<number, string>,\n }\n\n const parts = data.questions.map((q, i) => `- ${q.question} -> ${getAnswer(i)}`)\n const text = `关于需要确认的问题,用户的回答如下:\\n${parts.join(\"\\n\")}`\n setSubmitted(true)\n onAnswer(text, toolCallId, nextAnswerData)\n }\n\n return (\n <div\n className={cn(\n \"ml-4 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))]\",\n answered\n ? \"max-w-2xl space-y-3 p-3 text-xs text-[hsl(var(--muted-foreground))] opacity-80\"\n : \"max-w-lg space-y-5 p-4 text-sm\",\n )}\n >\n {data.source_loop?.description && (\n <div className=\"rounded-lg bg-[hsl(var(--muted)/0.35)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]\">\n 子智能体「{data.source_loop.description}」在等待你的回答\n </div>\n )}\n {data.questions.map((q, qIdx) => (\n <QuestionCard\n key={q.question}\n question={q}\n qIdx={qIdx}\n answered={answered}\n selected={displaySelections.get(qIdx) ?? new Set()}\n isCustom={displayUsingCustom.has(qIdx)}\n customText={displayCustomTexts.get(qIdx) ?? \"\"}\n onToggle={toggleOption}\n onCustomFocus={handleCustomFocus}\n onCustomChange={setCustomText}\n />\n ))}\n\n {!answered && !submitted && onAnswer && (\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={!allAnswered}\n className=\"w-full rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-xs font-semibold text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-60\"\n >\n {allAnswered ? \"确认\" : \"请先选择一个选项\"}\n </button>\n )}\n\n {submitted && !answered && (\n <button\n type=\"button\"\n disabled\n 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\"\n >\n <Loader2 size={14} className=\"animate-spin\" />\n 确认中\n </button>\n )}\n </div>\n )\n}\n\nfunction QuestionCard({\n question,\n qIdx,\n answered,\n selected,\n isCustom,\n customText,\n onToggle,\n onCustomFocus,\n onCustomChange,\n}: {\n question: QuestionItem\n qIdx: number\n answered: boolean\n selected: Set<number>\n isCustom: boolean\n customText: string\n onToggle: (qIdx: number, optIdx: number, multi: boolean) => void\n onCustomFocus: (qIdx: number) => void\n onCustomChange: (qIdx: number, text: string) => void\n}) {\n const multi = question.multiSelect ?? false\n\n return (\n <div>\n <div className={cn(\"flex items-start gap-2\", answered ? \"mb-2\" : \"mb-3\")}>\n <MessageSquareMore\n size={answered ? 12 : 13}\n className=\"mt-0.5 shrink-0 text-[hsl(var(--primary))]\"\n />\n <div\n className={cn(\n \"min-w-0 flex-1 font-medium text-[hsl(var(--foreground))]\",\n answered ? \"text-xs\" : \"text-sm\",\n )}\n >\n <MarkdownContent\n className={cn(\n \"prose prose-sm prose-invert max-w-none [&_li>p]:inline [&_ol]:my-1 [&_p]:my-1 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0 [&_ul]:my-1\",\n answered ? \"text-xs\" : \"text-sm\",\n )}\n controls={{ code: true }}\n >\n {question.question}\n </MarkdownContent>\n </div>\n </div>\n\n <div className={cn(\"flex flex-col pl-5\", answered ? \"gap-1\" : \"gap-1.5\")}>\n {question.options.map((opt, optIdx) => {\n const isSel = selected.has(optIdx)\n return (\n <button\n key={opt.label}\n type=\"button\"\n disabled={answered}\n onClick={() => onToggle(qIdx, optIdx, multi)}\n className={cn(\n \"flex items-start gap-2.5 rounded-lg border text-left transition-all\",\n answered ? \"px-2.5 py-1.5\" : \"px-3 py-2.5\",\n isSel && !answered\n ? \"border-[hsl(var(--primary)/0.8)] bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))]\"\n : isSel\n ? \"border-[hsl(var(--primary)/0.45)] bg-[hsl(var(--primary)/0.08)] text-[hsl(var(--foreground))]\"\n : \"border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.2)]\",\n !answered && !isSel && \"hover:border-[hsl(var(--ring)/0.4)] hover:bg-[hsl(var(--accent))]\",\n answered && \"cursor-default opacity-70\",\n )}\n >\n {multi && (\n <div\n className={cn(\n \"mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors\",\n isSel && !answered\n ? \"border-[hsl(var(--primary-foreground)/0.6)] bg-[hsl(var(--primary-foreground)/0.2)]\"\n : isSel\n ? \"border-[hsl(var(--primary)/0.45)] bg-[hsl(var(--primary)/0.12)]\"\n : \"border-[hsl(var(--border))]\",\n )}\n >\n {isSel && (\n <Check\n size={9}\n className={\n answered\n ? \"text-[hsl(var(--primary))]\"\n : \"text-[hsl(var(--primary-foreground))]\"\n }\n />\n )}\n </div>\n )}\n <div className=\"min-w-0\">\n <div className={cn(\"font-medium\", answered ? \"text-xs\" : \"text-[13px]\")}>\n {opt.label}\n </div>\n {opt.description && (\n <div\n className={cn(\n \"mt-0.5\",\n answered ? \"text-[11px]\" : \"text-xs\",\n isSel && !answered ? \"opacity-75\" : \"text-[hsl(var(--muted-foreground))]\",\n )}\n >\n {opt.description}\n </div>\n )}\n </div>\n </button>\n )\n })}\n\n {/* \"Other\" inline input */}\n {answered && !isCustom ? null : (\n <div\n className={cn(\n \"flex items-center gap-2 rounded-lg border transition-all\",\n answered ? \"px-2.5 py-1.5\" : \"px-3 py-2.5\",\n isCustom\n ? \"border-[hsl(var(--ring)/0.6)] bg-[hsl(var(--accent))]\"\n : \"border-[hsl(var(--border))] hover:border-[hsl(var(--ring)/0.3)] hover:bg-[hsl(var(--accent))]\",\n answered && \"cursor-default opacity-70\",\n )}\n >\n <span className=\"shrink-0 text-xs text-[hsl(var(--muted-foreground))]\">其他:</span>\n <input\n type=\"text\"\n value={customText}\n disabled={answered}\n onChange={(e) => onCustomChange(qIdx, e.target.value)}\n onFocus={() => onCustomFocus(qIdx)}\n aria-label=\"自定义回答\"\n placeholder=\"输入你的答案...\"\n className={cn(\n \"min-w-0 flex-1 bg-transparent text-[hsl(var(--foreground))] outline-none placeholder:text-[hsl(var(--muted-foreground)/0.5)]\",\n answered ? \"text-xs\" : \"text-sm\",\n )}\n />\n </div>\n )}\n </div>\n </div>\n )\n}\n\nexport function parseAskUserQuestion(\n toolResult: string | null | undefined,\n): AskUserQuestionData | null {\n if (!toolResult) return null\n try {\n const parsed = JSON.parse(toolResult)\n let questions = parsed?.questions\n // 容错:LLM 偶尔将 questions 输出为 JSON 字符串而非数组\n if (typeof questions === \"string\") {\n try {\n questions = JSON.parse(questions)\n } catch {\n return null\n }\n }\n if (Array.isArray(questions) && questions.every(isQuestionItem)) {\n return { ...parsed, questions } as AskUserQuestionData\n }\n } catch {\n // not JSON\n }\n return null\n}\n\nfunction isQuestionItem(value: unknown): value is QuestionItem {\n if (!value || typeof value !== \"object\") return false\n const question = (value as { question?: unknown }).question\n const options = (value as { options?: unknown }).options\n return typeof question === \"string\" && Array.isArray(options) && options.every(isOptionItem)\n}\n\nfunction isOptionItem(value: unknown): value is OptionItem {\n if (!value || typeof value !== \"object\") return false\n const option = value as { label?: unknown; description?: unknown }\n return typeof option.label === \"string\" && typeof option.description === \"string\"\n}\n","import { load } from \"js-yaml\"\nimport type { PlanNode } from \"./types\"\n\ninterface PlanStep {\n label: string\n skill?: string\n id?: string\n status?: string\n children?: PlanStep[]\n}\n\ninterface PlanDocument {\n title: string\n objective: string\n steps: PlanStep[]\n notes?: string[]\n}\n\ninterface ParsedPlanResult {\n plan: { root: PlanNode; notes: string[] } | null\n error: string | null\n}\n\nexport type PlanStatusMap = Record<string, PlanNode[\"status\"]>\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.trim().length > 0\n}\n\nfunction isPlanStep(value: unknown): value is PlanStep {\n if (!value || typeof value !== \"object\") return false\n const step = value as Record<string, unknown>\n if (!isNonEmptyString(step.label)) return false\n if (\"skill\" in step && step.skill !== undefined && !isNonEmptyString(step.skill)) return false\n if (\"children\" in step && !Array.isArray(step.children)) return false\n\n const children = Array.isArray(step.children) ? step.children : []\n if (children.length > 0 && !isNonEmptyString(step.skill)) return false\n return children.every((child) => isPlanStep(child))\n}\n\nfunction isPlanDocument(value: unknown): value is PlanDocument {\n if (!value || typeof value !== \"object\") return false\n const doc = value as Record<string, unknown>\n if (!isNonEmptyString(doc.title) || !isNonEmptyString(doc.objective)) return false\n if (!Array.isArray(doc.steps) || doc.steps.length === 0) return false\n if (!doc.steps.every((step) => isPlanStep(step))) return false\n if (\"notes\" in doc) {\n if (!Array.isArray(doc.notes)) return false\n if (!doc.notes.every((note) => isNonEmptyString(note))) return false\n }\n return true\n}\n\nfunction getPlanDocumentError(value: unknown): string {\n if (!value || typeof value !== \"object\") return \"PLAN.yaml 顶层结构必须是对象\"\n\n const doc = value as Record<string, unknown>\n if (!isNonEmptyString(doc.title)) return \"PLAN.yaml 缺少非空 title\"\n if (!isNonEmptyString(doc.objective)) return \"PLAN.yaml 缺少非空 objective\"\n if (!Array.isArray(doc.steps) || doc.steps.length === 0) return \"PLAN.yaml 缺少非空 steps\"\n if (!doc.steps.every((step) => isPlanStep(step))) {\n return \"PLAN.yaml 步骤结构无效,请检查 label / skill / children\"\n }\n if (\"notes\" in doc) {\n if (!Array.isArray(doc.notes) || !doc.notes.every((note) => isNonEmptyString(note))) {\n return \"PLAN.yaml notes 必须是非空字符串列表\"\n }\n }\n return \"PLAN.yaml 结构无效\"\n}\n\nfunction toPlanStatus(value: unknown): PlanNode[\"status\"] {\n if (!isNonEmptyString(value)) return \"pending\"\n const normalized = value.trim().toLowerCase()\n return normalized === \"pending\" || normalized === \"running\" || normalized === \"done\" || normalized === \"failed\"\n ? normalized\n : \"pending\"\n}\n\nexport function parsePlanTree(content: string): { root: PlanNode; notes: string[] } | null {\n return parsePlanTreeResult(content).plan\n}\n\nexport function applyPlanStatusesById(root: PlanNode, statuses: PlanStatusMap): PlanNode {\n const nextStatus = statuses[root.id] ?? root.status\n const children = Array.isArray(root.children) ? root.children : []\n return {\n ...root,\n status: nextStatus,\n children: children.map((child) => applyPlanStatusesById(child, statuses)),\n }\n}\n\nexport function parsePlanTreeResult(content: string): ParsedPlanResult {\n if (!content.trim()) {\n return { plan: null, error: null }\n }\n\n let parsed: unknown\n try {\n parsed = load(content)\n } catch (error) {\n return {\n plan: null,\n error: error instanceof Error ? `PLAN.yaml YAML 语法错误:${error.message}` : \"PLAN.yaml YAML 语法错误\",\n }\n }\n\n if (!isPlanDocument(parsed)) {\n return { plan: null, error: getPlanDocumentError(parsed) }\n }\n\n const createNode = (step: PlanStep, depth: number, fallbackId: string): PlanNode => {\n const children = Array.isArray(step.children) ? step.children : []\n return {\n id: isNonEmptyString(step.id) ? step.id.trim() : fallbackId,\n label: step.label.trim(),\n skillRef: isNonEmptyString(step.skill) ? step.skill.trim() : null,\n status: toPlanStatus(step.status),\n children: children.map((child, index) => createNode(child, depth + 1, `${fallbackId}.${index + 1}`)),\n depth,\n }\n }\n\n const root: PlanNode = {\n id: \"plan-root\",\n label: parsed.title.trim(),\n skillRef: null,\n status: \"pending\",\n children: parsed.steps.map((step, index) => createNode(step, 1, `${index + 1}`)),\n depth: 0,\n }\n\n const notes = [parsed.objective.trim(), ...(parsed.notes ?? []).map((note) => note.trim())]\n\n return { plan: { root, notes }, error: null }\n}\n","import type { ChatMessage } from \"../../schemas/message\"\nimport { parseAskUserQuestion } from \"../chat/AskUserQuestionBlock\"\nimport { applyPlanStatusesById, parsePlanTreeResult, type PlanStatusMap } from \"./parse-plan-tree\"\nimport type { PlanData, SkillInfo } from \"./types\"\n\nfunction resultAsString(result: unknown): string | null {\n if (typeof result === \"string\") return result\n return null\n}\n\nconst PAUSE_TOOLS = new Set([\"AskUserQuestion\", \"ExitPlanMode\"])\nconst READ_FILE_TOOLS = new Set([\"Read\"])\nconst PLAN_WRITE_TOOLS = new Set([\"Write\"])\nconst PLAN_EDIT_TOOLS = new Set([\"Edit\"])\n\nfunction getSkillId(payload: { skill_id?: string; name?: string } | null | undefined): string {\n if (!payload) {\n return \"\"\n }\n if (typeof payload.skill_id === \"string\" && payload.skill_id) {\n return payload.skill_id\n }\n if (typeof payload.name === \"string\" && payload.name) {\n return payload.name\n }\n return \"\"\n}\n\nfunction getSkillDisplayName(\n payload: { display_name?: string; skill_id?: string; name?: string } | null | undefined,\n): string | undefined {\n if (!payload || typeof payload.display_name !== \"string\") {\n return undefined\n }\n const displayName = payload.display_name.trim()\n if (!displayName) {\n return undefined\n }\n const skillId = getSkillId(payload)\n return displayName === skillId ? undefined : displayName\n}\n\nfunction parseModeChange(message: ChatMessage): { from: string; to: string } | null {\n if (message.kind !== \"mode_change\" || typeof message.content !== \"string\") {\n return null\n }\n try {\n const parsed = JSON.parse(message.content) as { from?: unknown; to?: unknown }\n if (typeof parsed.from === \"string\" && typeof parsed.to === \"string\") {\n return { from: parsed.from, to: parsed.to }\n }\n } catch {}\n return null\n}\n\nfunction isPlanningBoundaryMessage(message: ChatMessage): boolean {\n if (message.kind === \"planning_enter\" || message.kind === \"planning_exit\") {\n return true\n }\n const modeChange = parseModeChange(message)\n if (!modeChange) {\n return false\n }\n return modeChange.to === \"planning\" || modeChange.from === \"planning\"\n}\n\n/**\n * Extract structured plan data from planning phase messages.\n *\n * Expects messages between planning_enter/exit markers containing:\n * - search_skills tool calls (Phase 1)\n * - get_skill_content tool calls (Phase 2)\n * - Write tool call to PLAN.yaml with plan YAML (Phase 3)\n */\nexport function parsePlanMessages(allMessages: ChatMessage[]): PlanData {\n const messages = Array.isArray(allMessages) ? allMessages : []\n // Extract intent from the first search_skills query\n let intent = \"\"\n for (const msg of messages) {\n if (!msg.tool_calls) continue\n const searchTc = msg.tool_calls.find(\n (tc) => tc.name === \"search_skills\" || tc.name === \"SearchSkills\",\n )\n if (searchTc) {\n try {\n intent = JSON.parse(searchTc.arguments).query ?? \"\"\n } catch {}\n if (intent) break\n }\n }\n\n const plannerMsgs = messages.filter(\n (message) => !isPlanningBoundaryMessage(message),\n )\n const searchResults: SkillInfo[] = []\n const searchMap = new Map<string, SkillInfo>()\n const selectedSkills: SkillInfo[] = []\n const selectedSet = new Set<string>()\n const askQuestions: PlanData[\"askQuestions\"] = []\n const readFiles: PlanData[\"readFiles\"] = []\n let lastPauseTool: PlanData[\"lastPauseTool\"] = null\n let planContent = \"\"\n let planContentPriority = 0\n let latestStatuses: PlanStatusMap = {}\n\n const setPlanContent = (nextContent: unknown, priority: number) => {\n if (typeof nextContent !== \"string\" || !nextContent.trim()) {\n return\n }\n if (priority < planContentPriority) {\n return\n }\n planContent = nextContent\n planContentPriority = priority\n }\n\n const applyPlanEdit = (args: Record<string, unknown>) => {\n const oldString = typeof args.old_string === \"string\" ? args.old_string : \"\"\n const newString = typeof args.new_string === \"string\" ? args.new_string : \"\"\n if (!planContent || !oldString || !planContent.includes(oldString)) {\n return\n }\n planContent = planContent.replace(oldString, newString)\n }\n\n const maybeParsePlanStatus = (msg: ChatMessage) => {\n if (msg.kind !== \"plan_status\") return\n if (typeof msg.content !== \"string\" || !msg.content.trim()) return\n try {\n const data = JSON.parse(msg.content) as { plan_yaml?: unknown; statuses?: unknown }\n setPlanContent(data.plan_yaml, 3)\n if (data.statuses && typeof data.statuses === \"object\" && !Array.isArray(data.statuses)) {\n latestStatuses = Object.fromEntries(\n Object.entries(data.statuses)\n .filter((entry): entry is [string, string] => typeof entry[0] === \"string\" && typeof entry[1] === \"string\")\n .map(([stepId, status]) => [stepId, normalizePlanStatus(status)]),\n )\n }\n } catch {}\n }\n\n for (const msg of plannerMsgs) {\n maybeParsePlanStatus(msg)\n if (!msg.tool_calls) continue\n for (const tc of msg.tool_calls) {\n if ((tc.name === \"search_skills\" || tc.name === \"SearchSkills\") && resultAsString(tc.result)) {\n try {\n const parsed = JSON.parse(resultAsString(tc.result)!)\n const results: Array<{\n skill_id?: string\n name?: string\n display_name?: string\n description?: string\n }> =\n Array.isArray(parsed) ? parsed : Array.isArray(parsed?.results) ? parsed.results : []\n for (const r of results) {\n const skillId = getSkillId(r)\n if (!skillId || searchMap.has(skillId)) continue\n const skill: SkillInfo = {\n skillId,\n displayName: getSkillDisplayName(r),\n description: r.description ?? \"\",\n }\n searchMap.set(skillId, skill)\n searchResults.push(skill)\n }\n } catch {}\n }\n if (\n (tc.name === \"get_skill_content\" || tc.name === \"GetSkillContent\") &&\n resultAsString(tc.result)\n ) {\n try {\n const data = JSON.parse(resultAsString(tc.result)!) as {\n skill_id?: string\n name?: string\n display_name?: string\n description?: string\n content?: string\n }\n const skillId = getSkillId(data)\n if (!skillId || selectedSet.has(skillId)) continue\n let existing = searchMap.get(skillId)\n if (!existing) {\n // Skill fetched directly without prior search — auto-add to searchResults\n existing = {\n skillId,\n displayName: getSkillDisplayName(data),\n description: data.description ?? \"\",\n }\n searchMap.set(skillId, existing)\n searchResults.push(existing)\n }\n existing.displayName ??= getSkillDisplayName(data)\n existing.content = data.content\n existing.references = extractRefs(data.content ?? \"\")\n selectedSkills.push(existing)\n selectedSet.add(skillId)\n } catch {}\n }\n if (tc.name === \"AskUserQuestion\" && resultAsString(tc.result)) {\n const data = parseAskUserQuestion(resultAsString(tc.result))\n if (data) {\n askQuestions.push({ toolCallId: tc.id, data })\n }\n }\n if (READ_FILE_TOOLS.has(tc.name) && tc.arguments) {\n try {\n const args = JSON.parse(tc.arguments)\n if (typeof args.file_path === \"string\" && args.file_path) {\n readFiles.push({ path: args.file_path, status: tc.status ?? \"done\" })\n }\n } catch {}\n }\n if (\n PLAN_WRITE_TOOLS.has(tc.name) &&\n tc.arguments &&\n tc.status === \"done\" &&\n !(typeof tc.result === \"string\" && tc.result.startsWith(\"错误\"))\n ) {\n try {\n const args = JSON.parse(tc.arguments) as {\n file_path?: unknown\n content?: unknown\n }\n if (\n typeof args.file_path === \"string\" &&\n (args.file_path === \"PLAN.yaml\" || args.file_path.endsWith(\"/PLAN.yaml\")) &&\n typeof args.content === \"string\"\n ) {\n setPlanContent(args.content, 1)\n }\n } catch {}\n }\n if (\n PLAN_EDIT_TOOLS.has(tc.name) &&\n tc.arguments &&\n tc.status === \"done\" &&\n !(typeof tc.result === \"string\" && tc.result.startsWith(\"错误\"))\n ) {\n try {\n const args = JSON.parse(tc.arguments) as {\n file_path?: unknown\n old_string?: unknown\n new_string?: unknown\n }\n if (\n typeof args.file_path === \"string\" &&\n (args.file_path === \"PLAN.yaml\" || args.file_path.endsWith(\"/PLAN.yaml\"))\n ) {\n applyPlanEdit(args as Record<string, unknown>)\n }\n } catch {}\n }\n // Track the last pause-triggering tool across the whole phase.\n // Multi-round planning produces multiple pauses (e.g. AskUserQuestion\n // then ExitPlanMode); the UI needs the most recent one.\n if (PAUSE_TOOLS.has(tc.name) && tc.status === \"done\") {\n lastPauseTool = tc.name as PlanData[\"lastPauseTool\"]\n }\n if (tc.name === \"ExitPlanMode\" && resultAsString(tc.result)) {\n try {\n const data = JSON.parse(resultAsString(tc.result)!) as { plan?: unknown }\n setPlanContent(data.plan, 2)\n } catch {}\n }\n }\n }\n\n const { plan: parsedPlan, error: parseError } = parsePlanTreeResult(planContent)\n const plan =\n parsedPlan == null\n ? null\n : {\n ...parsedPlan,\n root: applyPlanStatusesById(parsedPlan.root, latestStatuses),\n }\n\n return {\n intent,\n searchResults,\n selectedSkills,\n plan,\n hasPlanContent: planContent.trim().length > 0,\n parseError,\n askQuestions,\n readFiles,\n lastPauseTool,\n }\n}\n\nfunction normalizePlanStatus(value: string): \"pending\" | \"running\" | \"done\" | \"failed\" {\n const normalized = value.trim().toLowerCase()\n return normalized === \"running\" || normalized === \"done\" || normalized === \"failed\"\n ? normalized\n : \"pending\"\n}\n\nfunction extractRefs(content: string): string[] {\n const seen = new Set<string>()\n const refs: string[] = []\n for (const m of content.matchAll(/\\[\\[([^\\]]+)\\]\\]/g)) {\n const ref = m[1].trim()\n if (ref && !seen.has(ref)) {\n seen.add(ref)\n refs.push(ref)\n }\n }\n return refs\n}\n","import { CheckCircle2, ChevronRight, PencilLine, Play, Sparkles } from \"lucide-react\"\nimport { useMemo, useState } from \"react\"\nimport { cn } from \"../../lib/utils\"\nimport type { ChatMessage } from \"../../schemas/message\"\nimport { useUiStore } from \"../../stores/ui-store\"\nimport { parsePlanMessages } from \"./parse-plan-messages\"\n\ninterface Props {\n messages: ChatMessage[]\n sessionStatus?: string\n onConfirmPlan?: (action: \"execute\" | \"revise\", text?: string) => void\n}\n\ntype SummaryState =\n | { kind: \"complete\"; label: string }\n | { kind: \"failed\"; label: string }\n | { kind: \"interrupted\"; label: string }\n | { kind: \"progress\"; label: string; dots: string }\n\nexport function PlanSummaryCard({\n messages,\n sessionStatus,\n onConfirmPlan,\n}: Props) {\n const data = useMemo(() => parsePlanMessages(messages), [messages])\n const rightPanelCollapsed = useUiStore((state) => state.rightPanelCollapsed)\n const toggleRightPanel = useUiStore((state) => state.toggleRightPanel)\n const setActiveRightTab = useUiStore((state) => state.setActiveRightTab)\n const summaryState = useMemo(() => getSummaryState(data, sessionStatus), [data, sessionStatus])\n const stepCount = useMemo(() => countPlanSteps(data.plan), [data.plan])\n const isWaitingForInput = sessionStatus === \"waiting_for_input\"\n const canConfirm =\n Boolean(onConfirmPlan) &&\n isWaitingForInput &&\n data.lastPauseTool === \"ExitPlanMode\"\n\n const openPlanPanel = () => {\n if (rightPanelCollapsed) {\n toggleRightPanel()\n }\n setActiveRightTab(\"situation\")\n }\n\n return (\n <div className=\"flex w-full flex-col gap-4 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card)/0.55)] p-4\">\n <button\n type=\"button\"\n onClick={openPlanPanel}\n className=\"flex w-full flex-col gap-4 text-left transition-colors hover:text-[hsl(var(--foreground))]\"\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0 space-y-2\">\n <div className=\"flex items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]\">\n <Sparkles size={12} />\n <span>规划摘要</span>\n </div>\n <div className=\"truncate text-base font-medium text-[hsl(var(--foreground))]\">\n {data.intent || \"当前规划\"}\n </div>\n <div className=\"flex flex-wrap items-center gap-2 text-xs\">\n {summaryState.kind === \"progress\" ? (\n <>\n <span className=\"rounded-full bg-[hsl(var(--accent))] px-2.5 py-1 text-[hsl(var(--foreground))]\">\n {summaryState.label}\n </span>\n <span className=\"font-mono tracking-[0.25em] text-[hsl(var(--muted-foreground))]\">\n {summaryState.dots}\n </span>\n </>\n ) : (\n <span\n className={cn(\n \"rounded-full px-2.5 py-1\",\n summaryState.kind === \"complete\" &&\n \"bg-[hsl(var(--primary)/0.12)] text-[hsl(var(--primary))]\",\n summaryState.kind === \"failed\" &&\n \"bg-[hsl(var(--destructive)/0.12)] text-[hsl(var(--destructive))]\",\n summaryState.kind === \"interrupted\" && \"bg-orange-500/12 text-orange-300\",\n )}\n >\n {summaryState.label}\n </span>\n )}\n </div>\n </div>\n <ChevronRight\n size={16}\n className=\"mt-1 shrink-0 text-[hsl(var(--muted-foreground))]\"\n aria-hidden=\"true\"\n />\n </div>\n\n {summaryState.kind === \"complete\" && (\n <div className=\"flex flex-wrap items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]\">\n <span className=\"rounded-full border border-[hsl(var(--border))] px-2.5 py-1\">\n {data.selectedSkills.length} 个技能\n </span>\n <span className=\"rounded-full border border-[hsl(var(--border))] px-2.5 py-1\">\n {stepCount} 个步骤\n </span>\n <span className=\"inline-flex items-center gap-1 text-[hsl(var(--muted-foreground))]\">\n <CheckCircle2 size={12} />\n 右侧查看详情\n </span>\n </div>\n )}\n </button>\n\n {canConfirm && <PlanConfirmationPanel onConfirmPlan={onConfirmPlan} />}\n </div>\n )\n}\n\nfunction PlanConfirmationPanel({\n onConfirmPlan,\n}: {\n onConfirmPlan?: (action: \"execute\" | \"revise\", text?: string) => void\n}) {\n const [isEditing, setIsEditing] = useState(false)\n const [revisionText, setRevisionText] = useState(\"\")\n\n const submitRevision = () => {\n const trimmed = revisionText.trim()\n if (!trimmed) return\n onConfirmPlan?.(\"revise\", trimmed)\n setRevisionText(\"\")\n setIsEditing(false)\n }\n\n return (\n <div className=\"space-y-3 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background)/0.45)] p-3\">\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => onConfirmPlan?.(\"execute\")}\n 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\"\n >\n <Play size={14} />\n 开始执行\n </button>\n <button\n type=\"button\"\n onClick={() => setIsEditing((value) => !value)}\n 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))]\"\n >\n <PencilLine size={14} />\n 修改\n </button>\n </div>\n\n {isEditing && (\n <div className=\"space-y-2\">\n <textarea\n value={revisionText}\n onChange={(event) => setRevisionText(event.target.value)}\n placeholder=\"输入修改建议...\"\n 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))]\"\n />\n <div className=\"flex justify-end\">\n <button\n type=\"button\"\n disabled={!revisionText.trim()}\n onClick={submitRevision}\n className=\"rounded-lg bg-[hsl(var(--primary))] px-3 py-1.5 text-xs font-medium text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-90 disabled:opacity-30\"\n >\n 提交修改意见\n </button>\n </div>\n </div>\n )}\n </div>\n )\n}\n\nfunction getSummaryState(\n data: ReturnType<typeof parsePlanMessages>,\n sessionStatus?: string,\n): SummaryState {\n if (sessionStatus === \"failed\") {\n return { kind: \"failed\", label: \"出错\" }\n }\n if (sessionStatus === \"interrupted\") {\n return { kind: \"interrupted\", label: \"已中断\" }\n }\n if (data.parseError) {\n return { kind: \"failed\", label: \"解析失败\" }\n }\n if (data.hasPlanContent || data.plan != null) {\n return { kind: \"complete\", label: \"已生成\" }\n }\n if (data.selectedSkills.length > 0) {\n return { kind: \"progress\", label: \"技能分析中\", dots: \"●●○\" }\n }\n if (data.searchResults.length > 0) {\n return { kind: \"progress\", label: \"技能发现中\", dots: \"●○○\" }\n }\n return { kind: \"progress\", label: \"规划准备中\", dots: \"○○○\" }\n}\n\nfunction countPlanSteps(plan: ReturnType<typeof parsePlanMessages>[\"plan\"]): number {\n if (!plan) return 0\n\n const countNode = (node: (typeof plan.root)[\"children\"][number] | typeof plan.root): number => {\n const children = Array.isArray(node.children) ? node.children : []\n return 1 + children.reduce((total, child) => total + countNode(child), 0)\n }\n\n if (plan.root.id === \"plan-root\") {\n const children = Array.isArray(plan.root.children) ? plan.root.children : []\n return children.reduce((total, child) => total + countNode(child), 0)\n }\n\n return countNode(plan.root)\n}\n","import type { ChatMessage } from \"../../schemas/message\"\n\nfunction parseModeChange(message: ChatMessage): { from: string; to: string } | null {\n if (message.kind !== \"mode_change\" || typeof message.content !== \"string\") {\n return null\n }\n try {\n const parsed = JSON.parse(message.content) as { from?: unknown; to?: unknown }\n if (typeof parsed.from === \"string\" && typeof parsed.to === \"string\") {\n return { from: parsed.from, to: parsed.to }\n }\n } catch {}\n return null\n}\n\nfunction isPlanningEnter(message: ChatMessage): boolean {\n if (message.kind === \"planning_enter\") {\n return true\n }\n const modeChange = parseModeChange(message)\n return modeChange?.to === \"planning\"\n}\n\nfunction isPlanningExit(message: ChatMessage): boolean {\n if (message.kind === \"planning_exit\") {\n return true\n }\n const modeChange = parseModeChange(message)\n return modeChange?.from === \"planning\"\n}\n\nexport function extractLatestPlanMessages(messages: ChatMessage[]): ChatMessage[] {\n const safeMessages = Array.isArray(messages) ? messages : []\n let enterIndex = -1\n let exitIndex = -1\n\n for (let i = safeMessages.length - 1; i >= 0; i -= 1) {\n const message = safeMessages[i]\n if (isPlanningExit(message) && exitIndex === -1) {\n exitIndex = i\n continue\n }\n if (isPlanningEnter(message)) {\n enterIndex = i\n break\n }\n }\n\n if (enterIndex === -1) {\n return []\n }\n\n return safeMessages\n .slice(enterIndex + 1)\n .filter((message, offset) => {\n const absoluteIndex = enterIndex + 1 + offset\n if (isPlanningEnter(message) || isPlanningExit(message)) {\n return false\n }\n if (exitIndex !== -1 && absoluteIndex > exitIndex) {\n return message.kind === \"plan_status\"\n }\n return true\n })\n}\n"],"mappings":"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","names":["jsx","jsx","jsxs","jsx","Check","Copy","useEffect","useMemo","useState","useEffect","useState","jsx","jsxs","useState","useEffect","jsx","jsxs","useState","useEffect","Check","Copy","useMemo","Check","useEffect","useMemo","useState","jsx","jsxs","useState","useEffect","useMemo","text","Check","useMemo","useState","Fragment","jsx","jsxs","useMemo","useState","parseModeChange"]}
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-J3XVFPOV.js";
4
4
  import {
5
5
  BladeClient
6
- } from "./chunk-DNT6RM5E.js";
6
+ } from "./chunk-C3KSHIRA.js";
7
7
  import {
8
8
  createClientActions,
9
9
  useCardStateStore
@@ -15,7 +15,8 @@ import {
15
15
  // src/react/api/partner-skill.ts
16
16
  var partner_skill_exports = {};
17
17
  __export(partner_skill_exports, {
18
- installPartnerSkill: () => installPartnerSkill
18
+ installPartnerSkill: () => installPartnerSkill,
19
+ uploadSessionSkill: () => uploadSessionSkill
19
20
  });
20
21
 
21
22
  // src/react/api/skills.ts
@@ -29,7 +30,8 @@ __export(skills_exports, {
29
30
  listSessionSkills: () => listSessionSkills,
30
31
  listSkills: () => listSkills,
31
32
  resyncSkills: () => resyncSkills,
32
- searchSkills: () => searchSkills
33
+ searchSkills: () => searchSkills,
34
+ uploadSessionSkill: () => uploadSessionSkill
33
35
  });
34
36
  var r = () => getClient().skills;
35
37
  var listSkills = (...args) => r().listSkills(...args);
@@ -40,29 +42,34 @@ var searchSkills = (...args) => r().searchSkills(...args);
40
42
  var getSkillStats = (...args) => r().getSkillStats(...args);
41
43
  var getGlobalSkillStats = (...args) => r().getGlobalSkillStats(...args);
42
44
  var getSkill = (...args) => r().getSkill(...args);
45
+ var uploadSessionSkill = (...args) => r().uploadSessionSkill(...args);
43
46
  var installPartnerSkill = (...args) => r().installPartnerSkill(...args);
44
47
 
45
48
  // src/react/schemas/partner-skill.ts
46
49
  import { type } from "arktype";
47
50
  var PartnerSkillName = type("/^[a-z0-9-]+\\/[a-z0-9-]+$/");
51
+ var SessionSkillName = PartnerSkillName;
48
52
  var PartnerSkillFile = type({
49
53
  path: "string > 0",
50
54
  content: "string"
51
55
  });
56
+ var SessionSkillFile = PartnerSkillFile;
52
57
  var PartnerSkillInstallPayload = type({
53
58
  name: PartnerSkillName,
54
59
  files: PartnerSkillFile.array().atLeastLength(1)
55
60
  });
61
+ var SessionSkillUploadPayload = PartnerSkillInstallPayload;
56
62
  var PartnerSkillInstallResult = type({
57
63
  name: PartnerSkillName,
58
64
  skill_dir: "string",
59
65
  file_count: "number.integer >= 0",
60
66
  overwritten: "boolean"
61
67
  });
62
- function parsePartnerSkillInstallPayload(payload) {
63
- const parsed = PartnerSkillInstallPayload.assert(payload);
68
+ var SessionSkillUploadResult = PartnerSkillInstallResult;
69
+ function parseSessionSkillUploadPayload(payload) {
70
+ const parsed = SessionSkillUploadPayload.assert(payload);
64
71
  if (!parsed.files.some((file) => file.path === "SKILL.md")) {
65
- throw new Error("installSkill payload must include SKILL.md");
72
+ throw new Error("session skill upload payload must include SKILL.md");
66
73
  }
67
74
  return parsed;
68
75
  }
@@ -314,26 +321,27 @@ function attachHostBridgeListener(getState) {
314
321
  }
315
322
  switch (envelope.action) {
316
323
  case "installSkill":
324
+ case "uploadSessionSkill":
317
325
  if (!envelope.canonical || envelope.direction !== "host-to-agent") {
318
326
  tap(
319
- "installSkill rejected: requires __bladeBridge envelope with direction=host-to-agent",
327
+ "uploadSessionSkill rejected: requires __bladeBridge envelope with direction=host-to-agent",
320
328
  true
321
329
  );
322
330
  console.warn(
323
- "[parent-bridge] installSkill rejected: requires __bladeBridge envelope with direction=host-to-agent"
331
+ "[parent-bridge] uploadSessionSkill rejected: requires __bladeBridge envelope with direction=host-to-agent"
324
332
  );
325
333
  return;
326
334
  }
327
335
  tap(void 0, false);
328
336
  try {
329
- const payload = parsePartnerSkillInstallPayload(envelope.payload);
330
- void installPartnerSkill(sessionId, payload).then(() => {
337
+ const payload = parseSessionSkillUploadPayload(envelope.payload);
338
+ void uploadSessionSkill(sessionId, payload).then(() => {
331
339
  invalidateSkillStats(sessionId);
332
340
  }).catch((error) => {
333
- console.warn("[parent-bridge] installSkill request failed", error);
341
+ console.warn("[parent-bridge] uploadSessionSkill request failed", error);
334
342
  });
335
343
  } catch (error) {
336
- console.warn("[parent-bridge] invalid installSkill payload", error);
344
+ console.warn("[parent-bridge] invalid uploadSessionSkill payload", error);
337
345
  }
338
346
  return;
339
347
  default:
@@ -861,7 +869,7 @@ function getToolDisplayLabel(toolCall) {
861
869
  }
862
870
  case "Bash": {
863
871
  const description = getCommandDescription(args);
864
- return description ? `\u6267\u884C\u547D\u4EE4\u884C\u64CD\u4F5C\uFF1A${description}` : "\u6267\u884C\u547D\u4EE4\u884C\u64CD\u4F5C";
872
+ return description || "\u6267\u884C\u547D\u4EE4\u884C\u64CD\u4F5C";
865
873
  }
866
874
  case "BgBash": {
867
875
  const description = getCommandDescription(args);
@@ -2094,6 +2102,7 @@ var useGisStore = create10()((set, get) => ({
2094
2102
  }));
2095
2103
 
2096
2104
  // src/react/sockets/event-bridge.ts
2105
+ var OOM_MESSAGE = "\u6C99\u76D2\u5185\u5B58\u4F7F\u7528\u8D85\u51FA\u9650\u5236\uFF0C\u5DF2\u81EA\u52A8\u91CD\u542F\u3002\u5982\u679C\u7ECF\u5E38\u89E6\u53D1\uFF0C\u53EF\u4EE5\u8054\u7CFB\u7BA1\u7406\u5458\u8C03\u6574\u989D\u5EA6\u3002";
2097
2106
  function extractSkillIdForAnalytics(message) {
2098
2107
  const text = getTextContent(message);
2099
2108
  const tagMatch = text.match(/<skill>([^<]+)<\/skill>/);
@@ -2181,7 +2190,7 @@ function notifyWorkspaceFilesChanged(sessionId, filePath) {
2181
2190
  onWorkspaceFilesChanged?.({ sessionId, filePath });
2182
2191
  }
2183
2192
  function isRecord4(value) {
2184
- return typeof value === "object" && value !== null;
2193
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2185
2194
  }
2186
2195
  function extractModeFromBlocks3(blocks) {
2187
2196
  const modeBlock = blocks.find((block) => block.type === "mode_change");
@@ -2192,6 +2201,38 @@ function extractModeFromBlocks3(blocks) {
2192
2201
  if (blocks.some((block) => block.type === "planning_exit")) return "executing";
2193
2202
  return null;
2194
2203
  }
2204
+ function parseJsonRecord(value) {
2205
+ if (isRecord4(value)) return value;
2206
+ if (typeof value !== "string") return null;
2207
+ try {
2208
+ const parsed = JSON.parse(value);
2209
+ return isRecord4(parsed) ? parsed : null;
2210
+ } catch {
2211
+ return null;
2212
+ }
2213
+ }
2214
+ var OOM_KEYWORDS_RE = /(?:\b(?:exit_code|ExitedWith|exited with)|退出码)\D*(?<!\d)137(?!\d)/i;
2215
+ function isOomText(value) {
2216
+ return typeof value === "string" && OOM_KEYWORDS_RE.test(value);
2217
+ }
2218
+ function isOomResult(value) {
2219
+ if (Array.isArray(value)) {
2220
+ return value.some((part) => isOomResult(part));
2221
+ }
2222
+ if (typeof value === "object" && value !== null) {
2223
+ const record = value;
2224
+ if (record.exit_code === 137) return true;
2225
+ if (typeof record.text === "string" && isOomText(record.text)) return true;
2226
+ if (typeof record.content === "string" && isOomText(record.content)) return true;
2227
+ return false;
2228
+ }
2229
+ if (typeof value === "string") {
2230
+ const parsed = parseJsonRecord(value);
2231
+ if (parsed?.exit_code === 137) return true;
2232
+ return isOomText(value);
2233
+ }
2234
+ return false;
2235
+ }
2195
2236
  function hasAuthenticatedSession(client) {
2196
2237
  if (hasTokenValue(resolveClientToken(client))) return true;
2197
2238
  const { token, socketAuthToken, user } = useAuthStore.getState();
@@ -2279,6 +2320,7 @@ var AgentSocket = class {
2279
2320
  previewArtifactsByToolCall = /* @__PURE__ */ new Map();
2280
2321
  pendingReplayMessages = /* @__PURE__ */ new Map();
2281
2322
  pendingReplayModes = /* @__PURE__ */ new Map();
2323
+ oomNotifiedKeys = /* @__PURE__ */ new Set();
2282
2324
  _ensureConnected() {
2283
2325
  if (this.socket.connected || this.socket.active) {
2284
2326
  return;
@@ -2366,15 +2408,16 @@ var AgentSocket = class {
2366
2408
  s.on("system:error", (data) => {
2367
2409
  const sessionId = this._resolveSessionId(data);
2368
2410
  if (sessionId) {
2411
+ const message = isOomText(data.message) ? OOM_MESSAGE : data.message;
2369
2412
  useSessionStore.getState().updateSessionStatus(sessionId, "failed");
2370
2413
  useChatStore.getState().markFailed(sessionId);
2371
- useChatStore.getState().addErrorMessage(sessionId, data.message);
2414
+ useChatStore.getState().addErrorMessage(sessionId, message);
2372
2415
  useChatStore.getState().setStreaming(sessionId, false);
2373
2416
  useRuntimeStore.getState().addEvent(sessionId, {
2374
2417
  type: "system:error",
2375
2418
  title: "Runtime error",
2376
2419
  status: "error",
2377
- detail: data.message
2420
+ detail: message
2378
2421
  });
2379
2422
  }
2380
2423
  });
@@ -2551,6 +2594,9 @@ var AgentSocket = class {
2551
2594
  }
2552
2595
  _applyProjectionSideEffects(sessionId, turn) {
2553
2596
  for (const block of turn.blocks) {
2597
+ if (block.type === "tool_result" && isOomResult(block.content)) {
2598
+ this._notifySandboxOom(sessionId, block.tool_call_id ?? turn.id);
2599
+ }
2554
2600
  if (block.type === "tool_bridge" && isToolBridgeContent(block.content)) {
2555
2601
  if (block.content.action === "gis.goals.updated" && isGisGoalListPayload(block.content.payload)) {
2556
2602
  useGisStore.getState().setGoals(sessionId, block.content.payload.goals);
@@ -2617,6 +2663,25 @@ var AgentSocket = class {
2617
2663
  }
2618
2664
  this._applySystemNotification(sessionId, turn.loop_id, block.content);
2619
2665
  }
2666
+ for (const toolCall of turn.tool_calls) {
2667
+ if (toolCall.status === "done" || toolCall.status === "error") {
2668
+ if (isOomResult(toolCall.result)) {
2669
+ this._notifySandboxOom(sessionId, toolCall.id);
2670
+ }
2671
+ }
2672
+ }
2673
+ }
2674
+ _notifySandboxOom(sessionId, key) {
2675
+ const dedupeKey = `${sessionId}:${key}`;
2676
+ if (this.oomNotifiedKeys.has(dedupeKey)) return;
2677
+ this.oomNotifiedKeys.add(dedupeKey);
2678
+ useChatStore.getState().addErrorMessage(sessionId, OOM_MESSAGE);
2679
+ useRuntimeStore.getState().addEvent(sessionId, {
2680
+ type: "sandbox:oom",
2681
+ title: "\u6C99\u76D2\u5185\u5B58\u8D85\u9650",
2682
+ status: "error",
2683
+ detail: OOM_MESSAGE
2684
+ });
2620
2685
  }
2621
2686
  _applySystemNotification(sessionId, loopId, notification) {
2622
2687
  const notificationType = notification.notification_type ?? "system_notification";
@@ -2922,9 +2987,13 @@ export {
2922
2987
  skills_exports,
2923
2988
  partner_skill_exports,
2924
2989
  PartnerSkillName,
2990
+ SessionSkillName,
2925
2991
  PartnerSkillFile,
2992
+ SessionSkillFile,
2926
2993
  PartnerSkillInstallPayload,
2994
+ SessionSkillUploadPayload,
2927
2995
  PartnerSkillInstallResult,
2996
+ SessionSkillUploadResult,
2928
2997
  useUiBridgeStore,
2929
2998
  resourceBridgeDispatch,
2930
2999
  isInsideIframe,
@@ -2983,4 +3052,4 @@ export {
2983
3052
  bootstrapBladeClient,
2984
3053
  getBootstrappedClient
2985
3054
  };
2986
- //# sourceMappingURL=chunk-TWZHUASA.js.map
3055
+ //# sourceMappingURL=chunk-EDMS2G5P.js.map