dsh-comfyui 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +3 -1
- package/README.md +3 -1
- package/client/client.js +644 -17
- package/client/client.js.map +1 -1
- package/lib/analyze.d.ts +3 -1
- package/lib/analyze.js +2 -1
- package/lib/convert.d.ts +0 -9
- package/lib/convert.js +15 -7
- package/lib/graph.d.ts +15 -0
- package/lib/graph.js +48 -0
- package/lib/index.js +9 -2
- package/lib/routes.js +181 -0
- package/lib/skill.js +1 -0
- package/lib/skillpack.d.ts +29 -2
- package/lib/skillpack.js +73 -5
- package/lib/transfer.d.ts +158 -0
- package/lib/transfer.js +460 -0
- package/package.json +3 -2
package/client/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["h","useState","h","useState","h","useSyncExternalStore","h","useState","useRef","h","useCallback","h"],"sources":["../src/client/i18n.ts","../src/client/lightbox.tsx","../src/client/card.tsx","../src/client/api.ts","../src/client/settings.tsx","../src/client/panel-store.ts","../src/client/trigger.tsx","../src/client/panel.tsx","../src/client/styles.ts","../src/client/index.ts"],"sourcesContent":["/** zh/en dictionaries for dsh-comfyui UI (settings page, tool card, panel). */\nexport const zh = {\n // settings page\n settingsTitle: 'ComfyUI',\n settingsDesc: '连接你的 ComfyUI 服务器,让 Agent 直接生成与处理图像、视频。',\n baseUrl: '服务器地址',\n baseUrlHint: 'ComfyUI 的 HTTP 地址(默认 http://127.0.0.1:8188)。',\n apiKeyEnv: 'API Key 环境变量名',\n apiKeyEnvHint: '密钥名:环境变量或凭据存储(默认 COMFYUI_API_KEY)。',\n hasApiKey: '已配置 API Key',\n noApiKey: '未配置 API Key(本地服务通常不需要)',\n save: '保存',\n saved: '已保存',\n saveFailed: '保存失败',\n test: '测试连接',\n testing: '正在测试…',\n testOk: '连接成功 · ComfyUI {version} · {ms} ms',\n testFail: '连接失败:{message}',\n configNotWritable: '设置服务不可用,请通过 cordis.yml 修改配置。',\n mediaHost: '媒体访问地址',\n mediaHostHint: '媒体在聊天中显示的完整地址(如 http://192.168.1.5:3080)。留空自动检测;图片不显示时填你访问本页的地址。',\n comfyuiDirs: 'ComfyUI 目录',\n comfyuiDirsHint: '本机 ComfyUI 安装目录(可多个,支持映射/多实例/便携版)。Agent 据此定位 models、工作流、音色库等文件。',\n comfyuiDirAdd: '+ 添加目录',\n comfyuiDirRemove: '移除该目录',\n comfyuiDirPlaceholder: '如 D:\\\\ComfyUI',\n skillsDir: '技能包目录',\n skillsDirHint: '工作流技能包(SKILL.md 与参考文档)目录。留空 = 数据目录下 skills/;填绝对路径可放到别的盘或同步盘。改后需手动搬移已有目录。当前实际使用:{current}',\n language: '界面语言',\n languageHint: '界面语言,切换后页面自动刷新。',\n // tool card\n cardGenerating: 'ComfyUI 生成中…',\n cardBackground: '后台任务',\n cardBackgroundDone: '已完成',\n cardPrompt: '任务 ID',\n cardElapsed: '耗时',\n cardMedia: '结果',\n cardEmpty: '无媒体输出',\n cardFailed: '执行失败',\n cardInterrupted: '已中断',\n cardCollect: '使用 job_output 收集后台任务结果',\n cardLoadFailed: '加载失败,点下方下载',\n cardDownload: '下载',\n cardWorkflow: '工作流',\n cardMode: '模式',\n cardListed: '已列出 {runs} 个运行工作流,{graphs} 个图工作流',\n // panel shell\n panelTitle: 'ComfyUI 面板',\n panelReset: '复位位置与大小',\n close: '关闭',\n lbPrev: '上一张',\n lbNext: '下一张',\n tabWorkflows: '工作流',\n tabAssets: '资产',\n tabQueue: '队列',\n error: '出错',\n refresh: '刷新',\n ours: '本插件',\n // workflows tab\n wfAdd: '新建工作流',\n wfName: '名称',\n wfDesc: '概述',\n wfDescPlaceholder: '告诉 Agent 这个工作流做什么',\n wfNameCopyHint: '点击复制工作流名称',\n wfNameCopied: '已复制工作流名称',\n wfParams: '可调参数',\n wfTags: '标签',\n wfTagAll: '全部',\n wfTagAdd: '自定义标签,回车添加',\n wfTagRemove: '点击移除标签',\n wfParamsEmpty: '未定义参数。点击\"识别参数\"自动提取提示词/分辨率/步数/种子,或\"高级参数\"手动指定任意节点输入。',\n wfParamsDrop: '拖拽/点击/粘贴上传',\n wfPasteHint: '悬停此处后按 Ctrl+V 粘贴剪贴板里的图片/文件',\n wfUploadSection: '加载区',\n wfUploadHint: '点击大图选择图像,或粘贴/上传新图像;选中后图生图默认使用该图像',\n wfUploadZone: '拖拽 / 点击 / 粘贴上传到 ComfyUI input 目录',\n wfUploaded: '已上传',\n wfCopyName: '复制文件名',\n wfLoadArea: '加载区',\n wfLoadHint: '点击放入素材(加载区的素材按顺序填入工作流未指定的加载参数)',\n wfLoadEmpty: '加载区为空,点击下方“添加加载区”放入素材',\n wfLoadPicked: '已加载',\n wfLoadAddSlot: '+ 添加加载区',\n wfLoadAddMedia: '添加素材',\n wfLoadRemoveSlot: '删除加载区',\n wfLoadNone: '空',\n wfLoadNoneHint: '清空该加载位(保留加载位,不放素材)',\n wfLoadSlotLabel: '加载位',\n wfLoadSummary: '加载位 {slots} 个 · 已放入 {loaded} 个素材,未指定的加载参数按顺序取用',\n wfTabAll: '全部',\n wfTabImported: '已导入',\n wfTabGenerated: '已生成',\n wfTypeAll: '全部类型',\n wfUploadedToast: '文件已上传',\n wfPickerUpload: '粘贴 / 点击上传',\n wfLoadNoFiles: '没有可用的图像',\n wfParamsUploading: '上传中…',\n uploadKind_image: '图片',\n uploadKind_video: '视频',\n uploadKind_audio: '音频',\n wfMediaClear: '清空',\n wfMediaEmpty: '文件名(留空=移除该参考位)',\n wfRefSlot: '参考',\n wfParamsRecognize: '识别参数',\n wfParamsRecognizing: '识别中…',\n wfParamsRecognizeFailed: '识别失败:无法连接 ComfyUI 或工作流无效',\n wfParamsAdd: '高级参数',\n wfParamAdd: '添加',\n wfParamLabel: '名称',\n wfParamCustomLabel: '自定义名称',\n wfParamCustomHint: '仅用于展示与 Agent 描述,传参键由系统自动生成;留空使用默认',\n wfParamDefault: '默认值',\n wfParamRandom: '随机',\n wfParamDelete: '删除',\n wfParamNode: '节点',\n wfParamInput: '输入',\n wfJson: '工作流 JSON(ComfyUI UI 导出的 API 格式)',\n wfSave: '保存',\n wfSaveRun: '保存并运行',\n wfCancel: '取消',\n wfEdit: '编辑',\n wfRun: '运行',\n wfDelete: '删除',\n wfQueued: '已入队:',\n wfJsonError: '工作流 JSON 解析失败',\n wfUpdated: '更新于',\n wfEmpty: '没有检测到任何工作流,请通过新建、导入或提取来创建执行流程。',\n wfLibrarySection: 'API 工作流',\n wfRefresh: '刷新',\n wfImportFile: '导入文件',\n wfComfyuiSection: 'ComfyUI 工作流',\n wfComfyuiHint: '面板自动检测 ComfyUI 中保存的工作流。\\n注:非 API 流程,无法直接执行,需经过提取转化为 API 工作流,或自行导入 API 工作流即可执行。',\n wfComfyuiEmpty: 'ComfyUI 端没有检测到保存的工作流',\n wfExtracted: '已提取',\n wfNotExtracted: '未提取',\n wfView: '查看',\n wfExtract: '提取',\n wfExtractedNotice: '已提取并加入插件库',\n wfExtractTitle: '提取执行流',\n wfExtractModeAll: '整体提取',\n wfExtractModeAllHint: '所有分量合成一个执行流(运行时全部执行)',\n wfExtractModeSplit: '按分量提取',\n wfExtractModeSplitHint: '每个独立流程一个执行流(推荐)',\n wfExtractModeMain: '只提取主流程',\n wfExtractModeMainHint: '只提取最大分量(通常是当前测试区块)',\n wfExtractRun: '提取',\n wfExtractEmpty: '图里没有可提取的分量',\n wfComponents: '分量',\n wfComponentLabel: '分量',\n wfNodes: '节点',\n wfBypassed: '已绕过节点',\n wfIsolated: '悬空节点',\n wfViewBack: '返回',\n wfViewNodes: '节点清单',\n wfViewJson: 'JSON 预览',\n wfViewEmpty: '图中没有可执行的节点',\n // assets tab\n assetAll: '全部工作流',\n assetBack: '返回',\n assetEmpty: '还没有生成记录。运行工作流后,结果会出现在这里。',\n assetGone: '源文件已被 ComfyUI 清理',\n assetDelete: '删除资产',\n assetDeleteTitle: '删除该资产?',\n assetDeleteBody: '将从资产库移除这条记录,并删除 ComfyUI 输出目录里的 {count} 个文件。此操作不可恢复。',\n assetDeleteNoDir: '未能定位 ComfyUI 输出目录,只会移除资产记录,磁盘文件保留(可在 cordis.yml 的 outputDir 里指定输出目录)。',\n assetDeleteDone: '已删除记录,磁盘文件删除 {deleted} 个',\n assetDeleteFailed: '删除失败:{message}',\n confirmDelete: '确定删除',\n cancel: '取消',\n // skill pack (per-workflow SKILL.md bundle)\n skillButton: '技能包',\n skillBadge: '技能包',\n skillBadgeRequired: '技能包·必读',\n skillBadgeHint: '该工作流挂了技能包:Agent 运行前会读它。',\n skillTitle: '技能包',\n skillIntro: '点击「启用技能包」后,可为这个工作流添加给 Agent 看的额外 skills 说明:什么时候用、参数怎么填、有哪些坑。',\n skillEnable: '启用技能包',\n skillDetach: '停用(保留文件)',\n skillDestroy: '销毁技能包',\n skillDestroyConfirm: '⚠ 永久删除整个技能包({count} 个文件),不可恢复',\n skillDestroyConfirmButton: '确认销毁',\n skillDropHint: '可把文件拖到这里导入',\n skillRequired: '运行前必读',\n skillDir: '目录',\n skillSummary: '摘要',\n skillSummaryPlaceholder: '一句话说明这个工作流适合做什么',\n skillSummaryHint: 'Agent 靠它决定要不要读正文,等同 skills 里的 description 字段。',\n skillSave: '保存',\n skillSaved: '已保存',\n skillDirty: '未保存',\n skillDirtyPrompt: '当前文件有未保存的修改。',\n skillSaveAndSwitch: '保存并切换',\n skillDiscard: '丢弃修改',\n skillImport: '↑ 导入文件',\n skillImportHint: '导入本地文件到技能包:md/txt/json/yaml 进 references,脚本进 scripts,图片/csv 进 assets(也可直接拖进左栏)。',\n skillImported: '已导入',\n skillImageHint: '图片只能预览,不能在此编辑;Agent 会在正文点名它时才去读取。',\n skillNewFile: '+ 新建文件',\n skillNewDir: '+ 新建目录',\n skillReveal: '📂 打开目录',\n skillRevealHint: '在文件管理器中打开这个技能包的文件夹,方便直接拷贝文件进去。打开的是运行 DSH 那台机器上的目录;若你正从另一台机器访问本页面,请按下方显示的路径自行前往。',\n skillRevealed: '已打开',\n skillRefresh: '刷新',\n skillRefreshHint: '重新读取技能包目录,显示 Agent 写入或文件管理器里新增/替换的文件。',\n skillRefreshed: '已刷新',\n skillNewDirPlaceholder: '目录名,如 templates',\n skillNewDirHint: '技能包可以有任意一层子目录。常用:{presets};也可以自己起名(字母/数字/汉字/下划线/连字符)。',\n skillDirCreated: '已创建目录',\n skillNewPlaceholder: '文件名(默认 .md)',\n skillCreate: '创建',\n skillRename: '重命名',\n skillDeleteFile: '删除文件',\n skillDeleteConfirm: '删除文件',\n skillReadFailed: '读取失败',\n skillFailed: '操作失败',\n skillDeleteWithWorkflow: '该工作流有技能包,要一起删除吗?',\n skillDeleteBoth: '一起删除',\n skillKeepPack: '只删工作流',\n // queue tab (task center)\n queueEmpty: '当前没有任务',\n queueError: '无法读取队列(ComfyUI 未运行?)',\n jobFilterLabel: '历史',\n jobFilterAll: '全部',\n jobFilterPending: '待生成',\n jobFilterInProgress: '生成中',\n jobFilterCompleted: '已完成',\n jobFilterFailed: '失败',\n jobFilterCancelled: '已取消',\n jobActive: '进行中',\n jobDelete: '删除',\n jobInterrupt: '中断',\n jobRerun: '重跑',\n jobViewAssets: '查看资产',\n jobMore: '更多操作',\n jobClearQueue: '清空队列',\n jobClearHistory: '清空历史',\n jobFree: '释放内存',\n jobDuration: '耗时',\n jobOurs: '本插件',\n}\n\nexport const en = {\n // settings page\n settingsTitle: 'ComfyUI',\n settingsDesc: 'Connect your ComfyUI server so the agent can generate and process images and videos directly.',\n baseUrl: 'Server URL',\n baseUrlHint: 'ComfyUI HTTP address (default http://127.0.0.1:8188).',\n apiKeyEnv: 'API key env var',\n apiKeyEnvHint: 'Name of the key: env var or credential store (default COMFYUI_API_KEY).',\n hasApiKey: 'API key configured',\n noApiKey: 'No API key configured (usually not needed for local servers)',\n save: 'Save',\n saved: 'Saved',\n saveFailed: 'Save failed',\n test: 'Test connection',\n testing: 'Testing…',\n testOk: 'Connected · ComfyUI {version} · {ms} ms',\n testFail: 'Connection failed: {message}',\n configNotWritable: 'Settings service unavailable — edit cordis.yml instead.',\n mediaHost: 'Media base URL',\n mediaHostHint: 'Base URL for media shown in chat (e.g. http://192.168.1.5:3080). Auto-detected when empty; set it if images do not load over LAN or a reverse proxy.',\n comfyuiDirs: 'ComfyUI directories',\n comfyuiDirsHint: 'ComfyUI install roots on this machine (multiple allowed: mapped/multiple/portable installs). The agent uses them to locate models, workflows and voice libraries.',\n comfyuiDirAdd: '+ Add directory',\n comfyuiDirRemove: 'Remove this directory',\n comfyuiDirPlaceholder: 'e.g. D:\\\\ComfyUI',\n skillsDir: 'Skill pack directory',\n skillsDirHint: 'Directory for workflow skill packs (SKILL.md + reference files). Empty = skills/ under the plugin data dir; an absolute path may target another drive or a synced folder. Existing packs are not moved automatically. Currently in use: {current}',\n language: 'Language',\n languageHint: 'UI language; the page reloads after switching.',\n // tool card\n cardGenerating: 'ComfyUI generating…',\n cardBackground: 'Background job',\n cardBackgroundDone: 'Completed',\n cardPrompt: 'Prompt ID',\n cardElapsed: 'Elapsed',\n cardMedia: 'Results',\n cardEmpty: 'No media outputs',\n cardFailed: 'Execution failed',\n cardInterrupted: 'Interrupted',\n cardCollect: 'Collect the background job result with job_output',\n cardLoadFailed: 'failed to load, use the download link below',\n cardDownload: 'Download',\n cardWorkflow: 'Workflow',\n cardMode: 'Mode',\n cardListed: 'Listed {runs} runnable workflows, {graphs} graph workflows',\n // panel shell\n panelTitle: 'ComfyUI Panel',\n panelReset: 'Reset position & size',\n close: 'Close',\n lbPrev: 'Previous image',\n lbNext: 'Next image',\n tabWorkflows: 'Workflows',\n tabAssets: 'Assets',\n tabQueue: 'Queue',\n error: 'Error',\n refresh: 'Refresh',\n ours: 'ours',\n // workflows tab\n wfAdd: 'New workflow',\n wfName: 'Name',\n wfDesc: 'Overview',\n wfDescPlaceholder: 'Tells the agent what this workflow does',\n wfNameCopyHint: 'Click to copy the workflow name',\n wfNameCopied: 'Workflow name copied',\n wfParams: 'Parameters',\n wfTags: 'Tags',\n wfTagAll: 'All',\n wfTagAdd: 'Custom tag, press Enter to add',\n wfTagRemove: 'Click to remove tag',\n wfParamsEmpty: 'No parameters yet. Click \"Detect\" to auto-extract prompt / resolution / steps / seed, or \"Advanced\" to expose any node input manually.',\n wfParamsDrop: 'Drop / Click / Paste to upload',\n wfPasteHint: 'Hover here and press Ctrl+V to paste an image/file',\n wfUploadSection: 'Load area',\n wfUploadHint: 'Click the preview to pick an image, or paste/upload a new one; the selection becomes the default source for image-to-image',\n wfUploadZone: 'Drag / Click / Paste to upload into the ComfyUI input dir',\n wfUploaded: 'Uploaded',\n wfCopyName: 'Copy file name',\n wfLoadArea: 'Load area',\n wfLoadHint: 'Click to put media in this slot (slots fill the workflow unset loader parameters in order)',\n wfLoadEmpty: 'Load area is empty — use \"Add slot\" below to put media in it',\n wfLoadPicked: 'Loaded',\n wfLoadAddSlot: '+ Add slot',\n wfLoadAddMedia: 'Add media',\n wfLoadRemoveSlot: 'Delete slot',\n wfLoadNone: 'None',\n wfLoadNoneHint: 'Empty this slot (the slot stays, with no media)',\n wfLoadSlotLabel: 'Slot',\n wfLoadSummary: '{slots} slot(s) · {loaded} loaded; unset loader parameters take them in order',\n wfTabAll: 'All',\n wfTabImported: 'Imported',\n wfTabGenerated: 'Generated',\n wfTypeAll: 'All types',\n wfUploadedToast: 'File uploaded',\n wfPickerUpload: 'Paste / Click to upload',\n wfLoadNoFiles: 'No images available',\n wfParamsUploading: 'Uploading…',\n uploadKind_image: 'image',\n uploadKind_video: 'video',\n uploadKind_audio: 'audio',\n wfMediaClear: 'Clear',\n wfMediaEmpty: 'filename (empty = drop this slot)',\n wfRefSlot: 'Ref ',\n wfParamsRecognize: 'Detect',\n wfParamsRecognizing: 'Detecting…',\n wfParamsRecognizeFailed: 'Detection failed: ComfyUI unreachable or invalid workflow',\n wfParamsAdd: 'Advanced',\n wfParamAdd: 'Add',\n wfParamLabel: 'Name',\n wfParamCustomLabel: 'Custom name',\n wfParamCustomHint: 'Shown to the user and the agent only; the parameter key is generated automatically. Leave empty for the default',\n wfParamDefault: 'Default',\n wfParamRandom: 'Random',\n wfParamDelete: 'Delete',\n wfParamNode: 'Node',\n wfParamInput: 'Input',\n wfJson: 'Workflow JSON (API format exported from the ComfyUI UI)',\n wfSave: 'Save',\n wfSaveRun: 'Save & Run',\n wfCancel: 'Cancel',\n wfEdit: 'Edit',\n wfRun: 'Run',\n wfDelete: 'Delete',\n wfQueued: 'Queued: ',\n wfJsonError: 'Workflow JSON could not be parsed',\n wfUpdated: 'updated',\n wfEmpty: 'No workflows detected — create one via New, Import, or Extract.',\n wfLibrarySection: 'API workflows',\n wfRefresh: 'Refresh',\n wfImportFile: 'Import file',\n wfComfyuiSection: 'ComfyUI workflows',\n wfComfyuiHint: 'Auto-detects workflows saved in ComfyUI.\\nNote: these are UI graphs, not directly runnable — extract them into API workflows, or import an API workflow instead.',\n wfComfyuiEmpty: 'No workflows detected on the ComfyUI server',\n wfExtracted: 'extracted',\n wfNotExtracted: 'not extracted',\n wfView: 'View',\n wfExtract: 'Extract',\n wfExtractedNotice: 'extracted into the library',\n wfExtractTitle: 'Extract runnable workflows',\n wfExtractModeAll: 'All as one',\n wfExtractModeAllHint: 'Merge every component into one runnable workflow (everything executes)',\n wfExtractModeSplit: 'Per component',\n wfExtractModeSplitHint: 'One runnable workflow per independent flow (recommended)',\n wfExtractModeMain: 'Main flow only',\n wfExtractModeMainHint: 'Only the largest component (usually the flow under test)',\n wfExtractRun: 'Extract',\n wfExtractEmpty: 'No extractable components in this graph',\n wfComponents: 'components',\n wfComponentLabel: 'Component',\n wfNodes: 'nodes',\n wfBypassed: 'bypassed nodes',\n wfIsolated: 'dangling nodes',\n wfViewBack: 'Back',\n wfViewNodes: 'Nodes',\n wfViewJson: 'JSON preview',\n wfViewEmpty: 'No executable nodes in this graph',\n // assets tab\n assetAll: 'All workflows',\n assetBack: 'Back',\n assetEmpty: 'Nothing generated yet. Results appear here after workflows run.',\n assetGone: 'Source file evicted by ComfyUI',\n assetDelete: 'Delete asset',\n assetDeleteTitle: 'Delete this asset?',\n assetDeleteBody: 'Removes the record from the asset library and deletes {count} file(s) from the ComfyUI output directory. This cannot be undone.',\n assetDeleteNoDir: 'The ComfyUI output directory could not be located, so only the record is removed and the files stay on disk (set outputDir in cordis.yml to enable file deletion).',\n assetDeleteDone: 'Record removed, {deleted} file(s) deleted',\n assetDeleteFailed: 'Delete failed: {message}',\n confirmDelete: 'Delete',\n cancel: 'Cancel',\n // skill pack (per-workflow SKILL.md bundle)\n skillButton: 'Skill pack',\n skillBadge: 'Skill pack',\n skillBadgeRequired: 'Skill pack (required)',\n skillBadgeHint: 'This workflow has a skill pack: the agent reads it before running.',\n skillTitle: 'Skill pack',\n skillIntro: 'Click \"Create skill pack\" to add extra skill instructions for this workflow: when to use it, how to fill its parameters, and which pitfalls to avoid.',\n skillEnable: 'Create skill pack',\n skillDetach: 'Detach (keep files)',\n skillDestroy: 'Destroy pack',\n skillDestroyConfirm: '⚠ Permanently delete the whole pack ({count} files) — cannot be undone',\n skillDestroyConfirmButton: 'Destroy',\n skillDropHint: 'Drop files here to import',\n skillRequired: 'Required before running',\n skillDir: 'Directory',\n skillSummary: 'Summary',\n skillSummaryPlaceholder: 'One line on what this workflow is for',\n skillSummaryHint: 'The agent uses it to decide whether to read the body — like the description field of a skill.',\n skillSave: 'Save',\n skillSaved: 'Saved',\n skillDirty: 'Unsaved',\n skillDirtyPrompt: 'The current file has unsaved changes.',\n skillSaveAndSwitch: 'Save and switch',\n skillDiscard: 'Discard changes',\n skillImport: 'Import files',\n skillImportHint: 'Import local files into the pack: md/txt/json/yaml go to references, scripts to scripts, images/csv to assets (drag onto the list works too).',\n skillImported: 'Imported',\n skillImageHint: 'Images are preview-only here; the agent reads one only when the body points at it.',\n skillNewFile: '+ New file',\n skillNewDir: '+ New folder',\n skillReveal: '📂 Open folder',\n skillRevealHint: 'Open this pack folder in the file manager so you can copy files straight in. It opens on the machine running DSH; if you are viewing this page from another machine, use the path shown below instead.',\n skillRevealed: 'Opened',\n skillRefresh: 'Refresh',\n skillRefreshHint: 'Re-read the pack directory to show files added or replaced by the agent or the file manager.',\n skillRefreshed: 'Refreshed',\n skillNewDirPlaceholder: 'Folder name, e.g. templates',\n skillNewDirHint: 'A pack may hold any one-level sub-directory. Common ones: {presets}; custom names work too (letters, digits, CJK, underscore, dash).',\n skillDirCreated: 'Folder created',\n skillNewPlaceholder: 'File name (.md by default)',\n skillCreate: 'Create',\n skillRename: 'Rename',\n skillDeleteFile: 'Delete file',\n skillDeleteConfirm: 'Delete file',\n skillReadFailed: 'Read failed',\n skillFailed: 'Operation failed',\n skillDeleteWithWorkflow: 'This workflow has a skill pack. Delete it too?',\n skillDeleteBoth: 'Delete both',\n skillKeepPack: 'Workflow only',\n // queue tab (task center)\n queueEmpty: 'No tasks right now',\n queueError: 'Cannot read the queue (ComfyUI not running?)',\n jobFilterLabel: 'History',\n jobFilterAll: 'All',\n jobFilterPending: 'Pending',\n jobFilterInProgress: 'Running',\n jobFilterCompleted: 'Completed',\n jobFilterFailed: 'Failed',\n jobFilterCancelled: 'Cancelled',\n jobActive: 'Active',\n jobDelete: 'Delete',\n jobInterrupt: 'Interrupt',\n jobRerun: 'Rerun',\n jobViewAssets: 'View assets',\n jobMore: 'More actions',\n jobClearQueue: 'Clear queue',\n jobClearHistory: 'Clear history',\n jobFree: 'Free memory',\n jobDuration: 'Took',\n jobOurs: 'ours',\n}\n\nexport type Lang = 'zh' | 'en'\nexport const LANGS: readonly Lang[] = ['zh', 'en']\nconst LANG_KEY = 'dsh-comfyui.lang'\n\n/** Current plugin UI language, read from localStorage (default zh). */\nexport function getLang(): Lang {\n try {\n return localStorage.getItem(LANG_KEY) === 'en' ? 'en' : 'zh'\n } catch {\n return 'zh'\n }\n}\n\n/** Persist the plugin UI language choice. */\nexport function setLang(lang: Lang): void {\n try {\n localStorage.setItem(LANG_KEY, lang)\n } catch {\n // storage unavailable (e.g. private mode): the choice just does not persist\n }\n}\n\nconst DICTS: Record<Lang, Record<string, string>> = { zh, en }\n\n/** Build a plugin-local translator for one language. Resolves {name}\n * placeholders from the first rest argument (same contract as the DSH\n * locale bind), falling back to the key itself when untranslated. */\nexport function makeT(lang: Lang): (key: string, ...rest: unknown[]) => string {\n const dict = DICTS[lang]\n return (key, ...rest) => {\n const template = dict[key] ?? key\n const params = (rest[0] ?? {}) as Record<string, unknown>\n if (params !== null && typeof params === 'object') {\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) => {\n const value = params[name]\n return value === undefined ? match : String(value)\n })\n }\n return template\n }\n}\n","/**\n * Shared lightbox: opens a generated image full-screen with prev/next\n * navigation, keyboard support, and a download pill. Used by both the panel\n * (assets/queue previews) and the tool card (result images).\n */\nimport { createElement as h, useEffect } from 'react'\n\nexport interface LightboxProps {\n t: (key: string, ...rest: unknown[]) => string\n images: string[]\n /** Per-image media kind, parallel to `images`; omitted defaults to image. */\n kinds?: Array<'image' | 'video' | 'audio' | 'other'>\n index: number\n onClose: () => void\n onIndex: (index: number) => void\n}\n\n/** Full-screen media overlay with prev/next navigation. */\nexport function Lightbox({ t, images, kinds, index, onClose, onIndex }: LightboxProps): ReturnType<typeof h> | null {\n const count = images.length\n useEffect(() => {\n const onKey = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') onClose()\n else if (event.key === 'ArrowLeft') onIndex((index - 1 + count) % count)\n else if (event.key === 'ArrowRight') onIndex((index + 1) % count)\n }\n document.addEventListener('keydown', onKey)\n return () => document.removeEventListener('keydown', onKey)\n }, [index, count, onClose, onIndex])\n const src = images[index]\n if (src === undefined) return null\n const kind = kinds?.[index] ?? 'image'\n const media = kind === 'video'\n ? h('video', { className: 'dsc-lightbox-media', src, controls: true, autoPlay: true })\n : kind === 'audio'\n ? h('audio', { className: 'dsc-lightbox-media', src, controls: true, autoPlay: true })\n : kind === 'image'\n ? h('img', { className: 'dsc-lightbox-img', src, alt: '' })\n : h('div', { className: 'dsc-lightbox-media' }, src)\n return h('div', { className: 'dsc-lightbox', onClick: onClose },\n h('div', { className: 'dsc-lightbox-body', onClick: (event: { stopPropagation: () => void }) => event.stopPropagation() },\n h('button', {\n className: 'dsc-lightbox-close',\n 'aria-label': t('close'),\n onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); onClose() },\n }, '✕'),\n count > 1\n ? h('button', {\n className: 'dsc-lightbox-nav dsc-lightbox-nav--prev',\n 'aria-label': t('lbPrev'),\n onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); onIndex((index - 1 + count) % count) },\n }, '‹')\n : null,\n media,\n h('div', { className: 'dsc-lightbox-meta' },\n h('span', null, `${index + 1} / ${count}`),\n h('a', { className: 'dsc-lightbox-download', href: src, download: '', target: '_blank', rel: 'noreferrer' }, t('cardDownload')),\n ),\n count > 1\n ? h('button', {\n className: 'dsc-lightbox-nav dsc-lightbox-nav--next',\n 'aria-label': t('lbNext'),\n onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); onIndex((index + 1) % count) },\n }, '›')\n : null,\n ),\n )\n}\n","/**\n * Tool cards for comfyui_run and comfyui_workflow (tool.call.toolview, keys\n * 'comfyui_run' / 'comfyui_workflow'). A pure function of the frozen tool-call\n * block: running calls show a generating state, settled calls render the\n * presentationMeta payload (media wall with size labels, click-to-zoom\n * lightbox, status) that the host threaded into the session log.\n */\nimport { createElement as h, useEffect, useState } from 'react'\nimport { Lightbox } from './lightbox.js'\n\ninterface MediaItem {\n filename: string\n subfolder: string\n type: string\n node: string\n index: number\n kind: 'image' | 'video' | 'audio' | 'other'\n url: string\n}\n\ninterface SyncMeta {\n kind: 'sync'\n promptId: string\n status: 'completed' | 'interrupted'\n elapsedMs: number\n media: MediaItem[]\n summary: string\n}\n\ninterface BackgroundMeta {\n kind: 'background'\n jobId: string\n promptId: string\n label: string\n}\n\ntype RunMeta = SyncMeta | BackgroundMeta\n\n/** Settled tool-result node (structural slice of the wire ToolCallBlock). */\ninterface ToolResultNode {\n kind: 'tool-result'\n call?: { name: string; argsRaw: string } | null\n isError?: boolean\n error?: { name?: string; code?: string }\n meta?: unknown\n}\n\n/** Running tool-call node (structural slice). */\ninterface RunningToolCall {\n callId: string\n name: string\n argsRaw: string\n}\n\ntype Block = ToolResultNode | RunningToolCall\n\n/** Discriminate the settled result node from a running call. */\nfunction isResultNode(block: Block): block is ToolResultNode {\n return (block as ToolResultNode).kind === 'tool-result'\n}\n\nexport interface ComfyUICardProps {\n t: (key: string, ...rest: unknown[]) => string\n block: Block\n}\n\nfunction parseArgs(raw: string): Record<string, unknown> {\n try {\n const parsed = JSON.parse(raw)\n return typeof parsed === 'object' && parsed !== null ? parsed as Record<string, unknown> : {}\n } catch {\n return {}\n }\n}\n\nfunction argsSummary(args: Record<string, unknown>): string {\n const parts: string[] = []\n if (typeof args.template === 'string') parts.push(`template=${args.template}`)\n if (args.mode !== undefined && args.mode !== 'sync') parts.push(`mode=${String(args.mode)}`)\n if (parts.length === 0) parts.push('custom workflow')\n return parts.join(' · ')\n}\n\nfunction aspectLabel(width: number, height: number): string {\n const gcd = (a: number, b: number): number => (b === 0 ? a : gcd(b, a % b))\n const g = gcd(width, height)\n const rw = width / g\n const rh = height / g\n return rw <= 32 && rh <= 32 ? `${rw}:${rh}` : ''\n}\n\nfunction MediaItem({ item, t, onOpen }: {\n item: MediaItem\n t: ComfyUICardProps['t']\n onOpen: () => void\n}): ReturnType<typeof h> {\n const [size, setSize] = useState<{ width: number; height: number } | null>(null)\n const [failed, setFailed] = useState(false)\n const media = item.kind === 'video'\n ? h('video', { src: item.url, controls: true, preload: 'metadata' })\n : item.kind === 'audio'\n ? h('audio', { src: item.url, controls: true, preload: 'metadata' })\n : item.kind === 'image'\n ? failed\n ? h('span', { className: 'dsc-media-other' }, `${item.filename}(${t('cardLoadFailed')})`)\n : h('img', {\n src: item.url,\n alt: item.filename,\n loading: 'lazy',\n className: 'dsc-media-img dsc-media-img--clickable',\n onClick: onOpen,\n onLoad: (event: { target: { naturalWidth?: number; naturalHeight?: number } }) => {\n const width = event.target.naturalWidth\n const height = event.target.naturalHeight\n if (typeof width === 'number' && typeof height === 'number' && width > 0 && height > 0) {\n setSize({ width, height })\n }\n },\n onError: () => setFailed(true),\n })\n : h('span', { className: 'dsc-media-other' }, item.filename)\n const ratio = size === null ? null : aspectLabel(size.width, size.height)\n return h('div', { className: 'dsc-media' },\n media,\n h('div', { className: 'dsc-media-meta' },\n size !== null\n ? h('span', { className: 'dsc-media-size' }, `${size.width}×${size.height}${ratio !== '' ? ` · ${ratio}` : ''}`)\n : null,\n h('a', { href: item.url, download: item.filename, target: '_blank', rel: 'noreferrer' }, t('cardDownload')),\n ),\n )\n}\n\nfunction ResultCard({ title, result, t }: {\n title: string\n result: SyncMeta\n t: ComfyUICardProps['t']\n}): ReturnType<typeof h> {\n const failed = result.status === 'interrupted'\n const [lightbox, setLightbox] = useState<number | null>(null)\n const urls = result.media.map((item) => item.url)\n const kinds = result.media.map((item) => item.kind)\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' },\n title !== '' ? h('span', { className: 'dsc-badge' }, title) : null,\n h('span', { className: failed ? 'dsc-badge dsc-badge--err' : 'dsc-badge dsc-badge--ok' },\n failed ? t('cardInterrupted') : result.status),\n h('span', { className: 'dsc-meta' }, `${t('cardPrompt')} ${result.promptId}`),\n h('span', { className: 'dsc-meta' }, `${t('cardElapsed')} ${result.elapsedMs} ms`),\n ),\n h('div', { className: 'dsc-meta' }, result.summary),\n result.media.length > 0\n ? h('div', { className: 'dsc-grid' }, result.media.map((item, index) => h(MediaItem, {\n key: `${item.node}-${item.index}`,\n item,\n t,\n onOpen: () => setLightbox(index),\n })))\n : h('div', { className: 'dsc-meta' }, t('cardEmpty')),\n lightbox !== null\n ? h(Lightbox, { t, images: urls, kinds, index: lightbox, onClose: () => setLightbox(null), onIndex: setLightbox })\n : null,\n )\n}\n\nfunction BackgroundCard({ label, promptId, t }: {\n label: string\n promptId: string\n t: ComfyUICardProps['t']\n}): ReturnType<typeof h> {\n // The tool returns immediately with a background job; this card polls the\n // job's history entry and, once completed, renders the collected media in\n // place (same wall as a sync result).\n const [result, setResult] = useState<{ status: string; media?: MediaItem[]; error?: string } | null>(null)\n const [lightbox, setLightbox] = useState<number | null>(null)\n\n useEffect(() => {\n let stopped = false\n let timer: number | undefined\n const poll = async (): Promise<void> => {\n try {\n const response = await fetch(`/comfyui/jobs/media?promptId=${encodeURIComponent(promptId)}`, { headers: { accept: 'application/json' } })\n const data = (await response.json()) as { ok?: boolean; status?: string; media?: MediaItem[]; error?: string }\n if (stopped) return\n if (data.ok !== true || data.status === undefined) return\n if (data.status === 'completed' || data.status === 'failed') {\n setResult({ status: data.status, media: data.media, error: data.error })\n return\n }\n timer = window.setTimeout(() => { void poll() }, 3_000)\n } catch {\n timer = window.setTimeout(() => { void poll() }, 5_000)\n }\n }\n void poll()\n return () => {\n stopped = true\n if (timer !== undefined) window.clearTimeout(timer)\n }\n }, [promptId])\n\n if (result !== null && (result.status === 'completed' || result.status === 'failed')) {\n const media = result.media ?? []\n const urls = media.map((item) => item.url)\n const kinds = media.map((item) => item.kind)\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' },\n h('span', { className: result.status === 'failed' ? 'dsc-badge dsc-badge--err' : 'dsc-badge dsc-badge--ok' },\n result.status === 'failed' ? t('cardFailed') : t('cardBackgroundDone')),\n h('span', { className: 'dsc-meta' }, `${label} · ${promptId}`),\n ),\n result.status === 'failed'\n ? h('div', { className: 'dsc-meta dsc-job-error' }, result.error ?? t('cardFailed'))\n : media.length > 0\n ? h('div', { className: 'dsc-grid' }, media.map((item, index) => h(MediaItem, {\n key: `${item.node}-${item.index}`,\n item,\n t,\n onOpen: () => setLightbox(index),\n })))\n : h('div', { className: 'dsc-meta' }, t('cardEmpty')),\n lightbox !== null\n ? h(Lightbox, { t, images: urls, kinds, index: lightbox, onClose: () => setLightbox(null), onIndex: setLightbox })\n : null,\n )\n }\n\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' },\n h('span', { className: 'dsc-badge' }, t('cardBackground')),\n h('span', { className: 'dsc-meta' }, `${label} · ${promptId}`),\n ),\n h('div', { className: 'dsc-meta' }, t('cardCollect')),\n )\n}\n\n/** meta of a comfyui_workflow call (action: run / list / get). */\ntype WorkflowMeta = {\n action: 'run'\n id: string\n workflowName?: string\n result?: SyncMeta\n background?: BackgroundMeta\n} | {\n action: 'list'\n workflows?: unknown[]\n comfyuiWorkflows?: unknown[]\n} | {\n action: 'get'\n id?: string\n name?: string\n}\n\nfunction SettledCard({ block, t }: { block: ToolResultNode; t: ComfyUICardProps['t'] }): ReturnType<typeof h> {\n if (block.isError === true) {\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' },\n h('span', { className: 'dsc-badge dsc-badge--err' }, t('cardFailed')),\n ),\n h('div', { className: 'dsc-meta' }, block.error?.name ?? 'error'),\n )\n }\n const meta = block.meta as RunMeta | WorkflowMeta | undefined\n if (meta === undefined || typeof meta !== 'object') {\n return h('div', { className: 'dsc-card' }, h('span', { className: 'dsc-badge' }, block.call?.name ?? 'comfyui'))\n }\n // comfyui_workflow: action-shaped meta.\n if ('action' in meta) {\n if (meta.action === 'run') {\n if (meta.background !== undefined) {\n return h(BackgroundCard, { label: meta.workflowName ?? '', promptId: meta.background.promptId, t })\n }\n if (meta.result !== undefined) {\n return h(ResultCard, { title: meta.workflowName ?? '', result: meta.result, t })\n }\n }\n if (meta.action === 'list') {\n const runs = meta.workflows?.length ?? 0\n const graphs = meta.comfyuiWorkflows?.length ?? 0\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' }, h('span', { className: 'dsc-badge' }, 'comfyui_workflow')),\n h('div', { className: 'dsc-meta' }, t('cardListed', { runs, graphs })),\n )\n }\n if (meta.action === 'get') {\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' }, h('span', { className: 'dsc-badge' }, 'comfyui_workflow')),\n h('div', { className: 'dsc-meta' }, meta.name ?? meta.id ?? 'get'),\n )\n }\n return h('div', { className: 'dsc-card' }, h('span', { className: 'dsc-badge' }, 'comfyui_workflow'))\n }\n // comfyui_run: kind-shaped meta.\n if (meta.kind === 'background') {\n return h(BackgroundCard, { label: meta.label, promptId: meta.promptId, t })\n }\n return h(ResultCard, { title: '', result: meta, t })\n}\n\n/** The card component: picks running vs settled rendering from the block. */\nexport function ComfyUICard({ t, block }: ComfyUICardProps): ReturnType<typeof h> {\n if (isResultNode(block)) {\n return h(SettledCard, { block, t })\n }\n const args = parseArgs(block.argsRaw)\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' },\n h('span', { className: 'dsc-badge' }, t('cardGenerating')),\n h('span', { className: 'dsc-meta' }, `${t('cardWorkflow')} ${argsSummary(args)} · ${t('cardMode')} ${String(args.mode ?? 'sync')}`),\n ),\n )\n}\n","/** Same-origin JSON helpers shared by the settings page and the panel. */\nexport async function getJson<T>(url: string): Promise<T> {\n const response = await fetch(url, { headers: { accept: 'application/json' } })\n if (!response.ok) throw new Error(`HTTP ${response.status}`)\n return (await response.json()) as T\n}\n\nexport async function postJson(url: string, body: unknown): Promise<unknown> {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n })\n if (!response.ok) {\n const payload = (await response.json().catch(() => ({}))) as { error?: string }\n throw new Error(payload.error ?? `HTTP ${response.status}`)\n }\n return response.json() as Promise<unknown>\n}\n\n/** POST raw bytes (an imported file) and read the JSON reply. */\nexport async function postRaw(url: string, bytes: ArrayBuffer): Promise<unknown> {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/octet-stream' },\n body: bytes,\n })\n if (!response.ok) {\n const payload = (await response.json().catch(() => ({}))) as { error?: string }\n throw new Error(payload.error ?? `HTTP ${response.status}`)\n }\n return response.json() as Promise<unknown>\n}\n","/**\n * The ComfyUI settings page (settings.section, id 'comfyui'). Reads the\n * redacted host config over /comfyui/config, persists edits through the same\n * route, and probes the server over /comfyui/test.\n */\nimport { createElement as h, useEffect, useState } from 'react'\nimport { getJson, postJson } from './api.ts'\nimport { getLang, setLang, type Lang } from './i18n.ts'\n\nexport interface ComfyUISettingsProps {\n t: (key: string, ...rest: unknown[]) => string\n close: () => void\n}\n\ninterface ConfigView {\n baseUrl: string\n apiKeyEnv: string\n hasApiKey: boolean\n timeoutMs: number\n pollIntervalMs: number\n maxMediaItems: number\n mediaHost: string\n comfyuiDirs: string[]\n skillsDir: string\n /** The path packs actually use, including the `<dataDir>/skills` default. */\n skillsRoot: string\n writable: boolean\n}\n\ninterface TestResult {\n ok: boolean\n text: string\n}\n\n/** The ComfyUI settings page component. */\nexport function ComfyUISettings({ t }: ComfyUISettingsProps): ReturnType<typeof h> {\n const [config, setConfig] = useState<ConfigView | null>(null)\n const [baseUrl, setBaseUrl] = useState('')\n const [apiKeyEnv, setApiKeyEnv] = useState('')\n const [mediaHost, setMediaHost] = useState('')\n const [comfyuiDirs, setComfyuiDirs] = useState<string[]>([])\n const [skillsDir, setSkillsDir] = useState('')\n const [loadError, setLoadError] = useState<string | null>(null)\n const [saving, setSaving] = useState(false)\n const [saveState, setSaveState] = useState<'idle' | 'saved' | 'failed'>('idle')\n const [testing, setTesting] = useState(false)\n const [testResult, setTestResult] = useState<TestResult | null>(null)\n const [lang, setLangState] = useState<Lang>(getLang())\n\n useEffect(() => {\n let cancelled = false\n getJson<ConfigView>('/comfyui/config').then((view) => {\n if (cancelled) return\n setConfig(view)\n setBaseUrl(view.baseUrl)\n setApiKeyEnv(view.apiKeyEnv)\n setMediaHost(view.mediaHost ?? '')\n setComfyuiDirs(Array.isArray(view.comfyuiDirs) ? view.comfyuiDirs : [])\n setSkillsDir(view.skillsDir ?? '')\n }).catch((error: unknown) => {\n if (cancelled) return\n setLoadError(error instanceof Error ? error.message : String(error))\n })\n return () => {\n cancelled = true\n }\n }, [])\n\n const save = async (): Promise<void> => {\n setSaving(true)\n setSaveState('idle')\n try {\n // Trim blanks and drop empty rows before persisting.\n const dirs = comfyuiDirs.map((dir) => dir.trim()).filter((dir) => dir !== '')\n const payload = (await postJson('/comfyui/config', { patch: { baseUrl, apiKeyEnv, mediaHost, comfyuiDirs: dirs, skillsDir: skillsDir.trim() } })) as { config?: ConfigView }\n if (payload.config !== undefined) {\n setConfig(payload.config)\n setBaseUrl(payload.config.baseUrl)\n setApiKeyEnv(payload.config.apiKeyEnv)\n setMediaHost(payload.config.mediaHost ?? '')\n setComfyuiDirs(payload.config.comfyuiDirs ?? [])\n setSkillsDir(payload.config.skillsDir ?? '')\n }\n setSaveState('saved')\n } catch (error) {\n setSaveState('failed')\n setTestResult({ ok: false, text: error instanceof Error ? error.message : String(error) })\n } finally {\n setSaving(false)\n }\n }\n\n const test = async (): Promise<void> => {\n setTesting(true)\n setTestResult(null)\n try {\n const payload = (await postJson('/comfyui/test', {})) as { ok: boolean; version?: string; latencyMs?: number; error?: string }\n if (payload.ok === true) {\n setTestResult({ ok: true, text: t('testOk', { version: payload.version ?? 'unknown', ms: payload.latencyMs ?? 0 }) })\n } else {\n setTestResult({ ok: false, text: t('testFail', { message: payload.error ?? 'unknown error' }) })\n }\n } catch (error) {\n setTestResult({ ok: false, text: t('testFail', { message: error instanceof Error ? error.message : String(error) }) })\n } finally {\n setTesting(false)\n }\n }\n\n if (loadError !== null) {\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-meta' }, `${t('saveFailed')}: ${loadError}`),\n )\n }\n if (config === null) {\n return h('div', { className: 'dsc-card' }, h('div', { className: 'dsc-meta' }, '…'))\n }\n\n return h('div', { className: 'dsc-form' },\n h('div', { className: 'dsc-meta' }, t('settingsDesc')),\n h('div', { className: 'dsc-field' },\n h('label', null, t('language')),\n h('select', {\n className: 'dsc-input',\n value: lang,\n onChange: (event: { target: { value: string } }) => {\n const next: Lang = event.target.value === 'en' ? 'en' : 'zh'\n setLangState(next)\n setLang(next)\n window.location.reload()\n },\n },\n h('option', { value: 'zh' }, '中文'),\n h('option', { value: 'en' }, 'English'),\n ),\n h('div', { className: 'dsc-hint' }, t('languageHint')),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('baseUrl')),\n h('input', {\n value: baseUrl,\n placeholder: 'http://127.0.0.1:8188',\n onChange: (event: { target: { value: string } }) => { setBaseUrl(event.target.value); setSaveState('idle') },\n }),\n h('div', { className: 'dsc-hint' }, t('baseUrlHint')),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('apiKeyEnv')),\n h('input', {\n value: apiKeyEnv,\n placeholder: 'COMFYUI_API_KEY',\n onChange: (event: { target: { value: string } }) => { setApiKeyEnv(event.target.value); setSaveState('idle') },\n }),\n h('div', { className: 'dsc-hint' }, `${t('apiKeyEnvHint')} — ${config.hasApiKey ? t('hasApiKey') : t('noApiKey')}`),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('mediaHost')),\n h('input', {\n value: mediaHost,\n placeholder: 'http://192.168.1.5:3080',\n onChange: (event: { target: { value: string } }) => { setMediaHost(event.target.value); setSaveState('idle') },\n }),\n h('div', { className: 'dsc-hint' }, t('mediaHostHint')),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('comfyuiDirs')),\n comfyuiDirs.map((dir, index) => h('div', {\n key: `dsc-dir-${index}`,\n style: { display: 'flex', gap: '8px', marginBottom: '8px', alignItems: 'center' },\n },\n h('input', {\n className: 'dsc-input',\n value: dir,\n placeholder: t('comfyuiDirPlaceholder'),\n style: { flex: '1' },\n onChange: (event: { target: { value: string } }) => {\n const next = comfyuiDirs.slice()\n next[index] = event.target.value\n setComfyuiDirs(next)\n setSaveState('idle')\n },\n }),\n h('button', {\n className: 'dsc-btn',\n title: t('comfyuiDirRemove'),\n disabled: !config.writable,\n onClick: () => {\n const next = comfyuiDirs.slice()\n next.splice(index, 1)\n setComfyuiDirs(next)\n setSaveState('idle')\n },\n }, '×'),\n )),\n h('button', {\n className: 'dsc-btn',\n disabled: !config.writable,\n onClick: () => {\n setComfyuiDirs([...comfyuiDirs, ''])\n setSaveState('idle')\n },\n }, t('comfyuiDirAdd')),\n h('div', { className: 'dsc-hint' }, t('comfyuiDirsHint')),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('skillsDir')),\n h('input', {\n className: 'dsc-input',\n value: skillsDir,\n placeholder: config.skillsRoot,\n onChange: (event: { target: { value: string } }) => { setSkillsDir(event.target.value); setSaveState('idle') },\n }),\n h('div', { className: 'dsc-hint' }, t('skillsDirHint', { current: config.skillsRoot })),\n ),\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn', disabled: saving || !config.writable, onClick: () => void save() }, t('save')),\n h('button', { className: 'dsc-btn', disabled: testing, onClick: () => void test() }, testing ? t('testing') : t('test')),\n saveState === 'saved' ? h('span', { className: 'dsc-note' }, t('saved')) : null,\n saveState === 'failed' ? h('span', { className: 'dsc-note' }, t('saveFailed')) : null,\n ),\n testResult !== null\n ? h('div', { className: testResult.ok ? 'dsc-note' : 'dsc-note', style: testResult.ok ? { color: '#22c55e' } : { color: '#ef4444' } }, testResult.text)\n : null,\n config.writable ? null : h('div', { className: 'dsc-hint' }, t('configNotWritable')),\n )\n}\n","/**\n * Shared open/close/tab state for the ComfyUI panel. The overlay occupant\n * and the session-header trigger are separate registrations in one bundle,\n * so they coordinate through this module-level store plus useSyncExternalStore.\n */\nimport { useSyncExternalStore } from 'react'\n\nconst listeners = new Set<() => void>()\nlet open = false\nlet tab: PanelTab = 'workflows'\nlet assetFilter = ''\n\nfunction emit(): void {\n for (const listener of listeners) listener()\n}\n\nexport type PanelTab = 'workflows' | 'assets' | 'queue'\n\nexport const panelStore = {\n isOpen: () => open,\n toggle: () => {\n open = !open\n emit()\n },\n open: () => {\n if (!open) {\n open = true\n emit()\n }\n },\n close: () => {\n if (open) {\n open = false\n emit()\n }\n },\n getTab: () => tab,\n setTab: (next: PanelTab) => {\n if (tab !== next) {\n tab = next\n emit()\n }\n },\n getAssetFilter: () => assetFilter,\n setAssetFilter: (name: string) => {\n if (assetFilter !== name) {\n assetFilter = name\n emit()\n }\n },\n subscribe(listener: () => void): () => void {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n}\n\n/** React hook reading the panel open state. */\nexport function usePanelOpen(): boolean {\n return useSyncExternalStore(panelStore.subscribe, panelStore.isOpen, panelStore.isOpen)\n}\n\n/** React hook reading the active panel tab. */\nexport function usePanelTab(): PanelTab {\n return useSyncExternalStore(panelStore.subscribe, panelStore.getTab, panelStore.getTab)\n}\n","/**\n * The session-header trigger (conversation.session.header.actions, id\n * 'comfyui'): a labelled button that toggles the ComfyUI panel.\n */\nimport { createElement as h } from 'react'\nimport { panelStore, usePanelOpen } from './panel-store.ts'\n\nexport interface ComfyUITriggerProps {\n t: (key: string, ...rest: unknown[]) => string\n}\n\n/**\n * ComfyUI brand glyph (mono), inlined from @lobehub/icons-static-svg\n * (lobehub.com/icons). currentColor fill keeps it theme-aware.\n */\nexport function ComfyUIIcon(): ReturnType<typeof h> {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: '1em', height: '1em',\n fill: 'currentColor', fillRule: 'evenodd',\n style: { flex: 'none', lineHeight: 1 },\n 'aria-hidden': true,\n }, h('path', { d: 'M5.485 23.76c-.568 0-1.026-.207-1.325-.598-.307-.402-.387-.964-.22-1.54l.672-2.315a.605.605 0 00-.1-.536.622.622 0 00-.494-.243H2.085c-.568 0-1.026-.207-1.325-.598-.307-.403-.387-.964-.22-1.54l2.31-7.917.255-.87c.343-1.18 1.592-2.14 2.786-2.14h2.313c.276 0 .519-.18.595-.442l.764-2.633C9.906 1.208 11.155.249 12.35.249l4.945-.008h3.62c.568 0 1.027.206 1.325.597.307.402.387.964.22 1.54l-1.035 3.566c-.343 1.178-1.593 2.137-2.787 2.137l-4.956.01H11.37a.618.618 0 00-.594.441l-1.928 6.604a.605.605 0 00.1.537c.118.153.3.243.495.243l3.275-.006h3.61c.568 0 1.026.206 1.325.598.307.402.387.964.22 1.54l-1.036 3.565c-.342 1.179-1.592 2.138-2.786 2.138l-4.957.01h-3.61z' }),\n )\n}\n\n/** Header-action button toggling the ComfyUI panel. */\nexport function ComfyUITrigger({ t }: ComfyUITriggerProps): ReturnType<typeof h> {\n const open = usePanelOpen()\n return h('button', {\n className: 'dsc-trigger',\n title: t('panelTitle'),\n 'aria-label': t('panelTitle'),\n 'aria-pressed': open,\n onClick: () => panelStore.toggle(),\n },\n h('span', { className: 'dsc-trigger-glyph' }, h(ComfyUIIcon)),\n h('span', null, t('panelTitle')),\n )\n}\n","/**\n * The ComfyUI panel (shell.overlay, id 'comfyui.panel'): a floating panel\n * with three tabs — workflow library management, generated asset preview,\n * and the live ComfyUI queue. Draggable by its header and resizable via the\n * corner handle; geometry persists in localStorage. Renders null while closed\n * (the overlay layer is click-through, so nothing blocks the app underneath).\n */\nimport { createElement as h, useCallback, useEffect, useRef, useState } from 'react'\nimport { getJson, postJson, postRaw } from './api.ts'\nimport { panelStore, usePanelOpen, usePanelTab } from './panel-store.ts'\nimport { ComfyUIIcon } from './trigger.tsx'\nimport { Lightbox } from './lightbox.js'\n\n/** Panel geometry: pixel position/size once the user dragged or resized. */\ninterface PanelGeom {\n x?: number\n y?: number\n width?: number\n height?: number\n}\n\nconst GEOM_KEY = 'dsh-comfyui-panel-geom'\n\nfunction loadGeom(): PanelGeom {\n try {\n const raw = localStorage.getItem(GEOM_KEY)\n if (raw === null) return {}\n const parsed = JSON.parse(raw) as Record<string, unknown>\n const geom: PanelGeom = {}\n if (typeof parsed.x === 'number') geom.x = parsed.x\n if (typeof parsed.y === 'number') geom.y = parsed.y\n if (typeof parsed.width === 'number' && parsed.width >= 300) geom.width = parsed.width\n if (typeof parsed.height === 'number' && parsed.height >= 200) geom.height = parsed.height\n return geom\n } catch {\n return {}\n }\n}\n\nfunction saveGeom(geom: PanelGeom): void {\n try {\n localStorage.setItem(GEOM_KEY, JSON.stringify(geom))\n } catch {\n // storage unavailable — geometry just won't persist\n }\n}\n\n/** Default panel width from styles.ts (`.dsc-panel` width var), used only to\n * estimate the panel extent while clamping a saved position. */\nconst PANEL_WIDTH_FALLBACK = 400\n/** Approx. height of the drag-handle band (`.dsc-panel-head`). */\nconst HEAD_BAND = 48\n/** Minimum margin kept between the panel and the viewport edge. */\nconst EDGE = 8\n\n/**\n * Clamp a top-left corner so the drag-handle band always stays inside the\n * viewport. The failure this prevents: once the header is pushed past the top\n * edge (or a saved position from a larger monitor no longer fits), there is no\n * grab surface left and the panel cannot be moved back at all.\n */\nfunction clampPos(x: number, y: number, width: number, vw: number, vh: number): { x: number; y: number } {\n const maxX = Math.max(EDGE, vw - width - EDGE)\n const maxY = Math.max(EDGE, vh - HEAD_BAND - EDGE)\n return { x: Math.min(Math.max(x, EDGE), maxX), y: Math.min(Math.max(y, EDGE), maxY) }\n}\n\n/** Snap persisted geometry back within reach of the cursor. Geometry that\n * never carried an explicit position (the CSS-anchored default) is returned\n * unchanged; geometry already inside the safe area keeps its object identity\n * so callers can skip pointless re-renders. */\nfunction healGeom(geom: PanelGeom, vw: number, vh: number): PanelGeom {\n if (geom.x === undefined || geom.y === undefined) return geom\n const pos = clampPos(geom.x, geom.y, geom.width ?? PANEL_WIDTH_FALLBACK, vw, vh)\n if (pos.x === geom.x && pos.y === geom.y) return geom\n return { ...geom, x: pos.x, y: pos.y }\n}\n\ninterface PointerEventLike {\n pointerId: number\n clientX: number\n clientY: number\n button: number\n target: EventTarget | null\n currentTarget: EventTarget | null\n}\n\nexport interface ComfyUIPanelProps {\n t: (key: string, ...rest: unknown[]) => string\n}\n\ninterface MediaItem {\n filename: string\n subfolder: string\n type: string\n node: string\n index: number\n kind: 'image' | 'video' | 'audio' | 'other'\n url: string\n}\n\ninterface WorkflowEntry {\n id: string\n name: string\n description: string\n workflow: Record<string, unknown>\n parameters?: WorkflowParameter[]\n tags?: string[]\n /** Skill-pack directory name; present when this workflow has a pack. */\n skillDir?: string\n /** Whether the agent must read the pack before running this workflow. */\n requireSkill?: boolean\n updatedAt: string\n}\n\n/** One file inside a workflow's skill pack. */\ninterface SkillPackFile {\n path: string\n size: number\n updatedAt: string\n}\n\n/** A workflow's skill pack as the routes report it. */\ninterface SkillPack {\n slug: string\n dir: string\n summary: string\n files: SkillPackFile[]\n /** Sub-directories present in the pack, including empty ones. */\n dirs: string[]\n totalBytes: number\n workflowId: string\n workflowName: string\n required: boolean\n}\n\ninterface SkillPackResponse {\n ok?: boolean\n enabled?: boolean\n root?: string\n /** Suggested directory names; the host owns the list. */\n presetDirs?: string[]\n pack?: SkillPack | null\n error?: string\n}\n\n/** Fallback suggestions when the config route has not answered yet; the\n * authoritative list comes from the host (`presetDirs`). */\nconst SKILL_FALLBACK_DIRS = ['references', 'scripts', 'assets']\n\n/** Imported binaries land in assets/; the editor previews these instead of\n * trying to read them as text. */\nconst SKILL_IMAGE_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.webp', '.gif', '.svg']\n\nfunction isSkillImage(path: string): boolean {\n const dot = path.lastIndexOf('.')\n return dot !== -1 && SKILL_IMAGE_EXTENSIONS.includes(path.slice(dot).toLowerCase())\n}\n\n/** Preset workflow classification tags (users can add custom ones). Stored as\n * plain text, so the tag identity is the label itself. */\nconst PRESET_TAGS = ['图生图', '文生图', '文生视频', '图生视频', '参考生视频', '文生音频', '参考生音频']\n\n/** A workflow saved on the ComfyUI server (userdata/workflows). */\ninterface ComfyUIWorkflowEntry {\n name: string\n size?: number\n modified?: number\n /** Whether at least one runnable API workflow was extracted from this graph. */\n extracted: boolean\n /** Runnable API workflows extracted from this graph. */\n derived: Array<{ libraryId: string; name: string }>\n}\n\n/** One connected component of a ComfyUI-side graph. */\ninterface ComponentInfo {\n index: number\n size: number\n groups: string[]\n nodeTypes: string[]\n}\n\n/** Canvas analysis result for the extract dialog. */\ninterface GraphAnalysis {\n components: ComponentInfo[]\n isolated: Array<{ id: number; type: string }>\n bypassedCount: number\n mode: 'single' | 'multi'\n}\n\ntype ExtractMode = 'all' | 'split' | 'main'\n\n/** Extract-dialog state: the graph file being extracted. */\ninterface ExtractState {\n file: string\n analysis: GraphAnalysis | null\n error: string | null\n mode: ExtractMode\n}\n\n/** Read-only view state for a ComfyUI-side workflow. */\ninterface WorkflowViewState {\n file: string\n graph: Record<string, unknown>\n}\n\ninterface AssetEntry {\n promptId: string\n ts: string\n workflowName: string | null\n source: string\n media: MediaItem[]\n}\n\ntype JobStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'cancelled'\n/** History filter: 'all' shows every terminal task; others narrow it. */\ntype JobFilter = 'all' | 'completed' | 'failed' | 'cancelled'\n\n/** One unified job from ComfyUI /api/jobs, as served by /comfyui/jobs. */\ninterface JobView {\n id: string\n status: JobStatus\n createTime: number | null\n executionStartTime: number | null\n executionEndTime: number | null\n executionError: { message?: string; exception_message?: string; node_type?: string } | null\n outputsCount: number\n previewOutput: { filename?: string; subfolder?: string; type?: string; mediaType?: string } | null\n workflowId: string | null\n workflowName: string | null\n ours: boolean\n progress: { value: number; max: number } | null\n}\n\ninterface JobsView {\n ok: boolean\n error?: string\n jobs: JobView[]\n total: number\n hasMore: boolean\n}\n\nconst JOB_FILTERS: Array<{ key: JobFilter; label: string }> = [\n { key: 'all', label: 'jobFilterAll' },\n { key: 'completed', label: 'jobFilterCompleted' },\n { key: 'failed', label: 'jobFilterFailed' },\n { key: 'cancelled', label: 'jobFilterCancelled' },\n]\n\n/** One adjustable parameter of a saved workflow (mirrors host WorkflowParameter). */\ninterface WorkflowParameter {\n id: string\n name: string\n label: string\n type: 'string' | 'number' | 'boolean'\n nodeId: string\n inputKey: string\n default: string | number | boolean\n description?: string\n random?: boolean\n /** Declared numeric type of the node input; absent = unknown (decimals ok). */\n numberKind?: 'int' | 'float'\n min?: number\n max?: number\n step?: number\n options?: Array<string | number>\n upload?: 'image' | 'video' | 'audio' | 'media'\n subfolder?: string\n}\n\n/** Editing state for a workflow: the JSON field is text while being edited. */\ninterface WorkflowDraft {\n id?: string\n name?: string\n description?: string\n tags?: string[]\n inputs?: string\n workflow: string | Record<string, unknown>\n parameters?: WorkflowParameter[]\n updatedAt?: string\n}\n\nfunction shortId(promptId: string): string {\n return promptId.length > 10 ? `${promptId.slice(0, 10)}…` : promptId\n}\n\n/** Open a job's preview image URL (via the media proxy) when it has one. */\nfunction previewUrlOf(job: JobView): string | null {\n const preview = job.previewOutput\n if (preview === undefined || preview === null || preview.filename === undefined || preview.filename === null) return null\n return `/comfyui/media?file=${encodeURIComponent(preview.filename)}&subfolder=${encodeURIComponent(preview.subfolder ?? '')}&type=${encodeURIComponent(preview.type ?? 'output')}`\n}\n\n/** Opens a generated image in a large overlay with prev/next navigation. */\n\n/** Whether a node input is fed by a link ([nodeId, slot]) rather than a widget value. */\nfunction isLinkValue(value: unknown): boolean {\n return Array.isArray(value) && value.length === 2 && typeof value[0] === 'string' && typeof value[1] === 'number'\n}\n\n/** Short description of a node input's current value, for the advanced\n * picker's dropdown. */\nfunction inputValueKind(value: unknown): string {\n if (value === null) return 'null'\n if (Array.isArray(value)) return 'array'\n if (typeof value === 'object') return 'object'\n return typeof value\n}\n\n/** Read a parameter default as a boolean. Defaults saved before the editor\n * had a checkbox are strings (\"true\"/\"false\"), so they are coerced here rather\n * than silently reading as `true` for every non-empty string. */\nfunction asBool(value: string | number | boolean): boolean {\n if (typeof value === 'boolean') return value\n if (typeof value === 'number') return value !== 0\n return /^(true|1|yes|on)$/i.test(value.trim())\n}\n\n/** Tooltip for a number field: the declared type and bounds, when known. */\nfunction numberRangeHint(param: WorkflowParameter): string {\n const parts: string[] = [param.numberKind ?? 'number']\n if (param.min !== undefined || param.max !== undefined) parts.push(`${param.min ?? '-∞'} ~ ${param.max ?? '∞'}`)\n if (param.step !== undefined) parts.push(`step ${param.step}`)\n return parts.join(' · ')\n}\n\nfunction newParamId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') return crypto.randomUUID()\n return `p${Date.now().toString(36)}${Math.floor(Math.random() * 1e6).toString(36)}`\n}\n\n/** Parse the draft workflow into a plain object (empty on invalid JSON). */\nfunction parseDraftWorkflow(workflow: string | Record<string, unknown>): Record<string, unknown> {\n if (typeof workflow !== 'string') return workflow\n try {\n const parsed = JSON.parse(workflow) as unknown\n return typeof parsed === 'object' && parsed !== null ? (parsed as Record<string, unknown>) : {}\n } catch {\n return {}\n }\n}\n\n/**\n * Custom dropdown for loader-node file lists: each option shows a small\n * server-side thumbnail (images only; <select> cannot render images).\n */\nfunction UploadSelect(props: {\n value: string\n options: Array<string | number>\n kind: 'image' | 'video' | 'audio'\n onChange: (value: string) => void\n onRefresh?: () => Promise<Array<string | number> | undefined>\n}): ReturnType<typeof h> {\n const [open, setOpen] = useState(false)\n const [live, setLive] = useState<Array<string | number> | null>(null)\n const ref = useRef<HTMLDivElement | null>(null)\n // Keep the latest refresh callback without re-running the open-effect.\n const refreshRef = useRef(props.onRefresh)\n refreshRef.current = props.onRefresh\n\n useEffect(() => {\n if (!open) return\n const onDoc = (event: MouseEvent): void => {\n if (ref.current !== null && !ref.current.contains(event.target as Node)) setOpen(false)\n }\n document.addEventListener('mousedown', onDoc)\n return () => document.removeEventListener('mousedown', onDoc)\n }, [open])\n\n // Pull the live file list from the server every time the menu opens, so\n // files uploaded elsewhere show up without reloading the workflow editor.\n useEffect(() => {\n if (!open) return\n const fn = refreshRef.current\n if (fn === undefined) return\n let cancelled = false\n void fn().then((latest) => {\n if (!cancelled && latest !== undefined) setLive(latest)\n })\n return () => { cancelled = true }\n }, [open])\n\n const options = live ?? props.options\n const thumbUrl = (name: string | number): string | null =>\n props.kind === 'image' ? `/comfyui/media?file=${encodeURIComponent(String(name))}&type=input` : null\n const current = options.some((option) => String(option) === props.value) ? props.value : String(props.value)\n\n return h('div', { ref, className: 'dsc-upload-select' },\n h('button', {\n className: 'dsc-upload-select-btn',\n onClick: () => setOpen(!open),\n title: String(current),\n },\n thumbUrl(props.value) !== null\n ? h('img', { className: 'dsc-upload-select-thumb', src: thumbUrl(props.value) ?? '', alt: '', loading: 'lazy' })\n : null,\n h('span', { className: 'dsc-upload-select-name' }, String(current)),\n ),\n open\n ? h('div', { className: 'dsc-upload-select-pop' },\n options.map((option) => {\n const name = String(option)\n return h('div', {\n key: name,\n className: `dsc-upload-select-item${name === props.value ? ' dsc-upload-select-item--active' : ''}`,\n onClick: () => { props.onChange(name); setOpen(false) },\n },\n thumbUrl(option) !== null\n ? h('img', { className: 'dsc-upload-select-thumb', src: thumbUrl(option) ?? '', alt: '', loading: 'lazy' })\n : null,\n h('span', { className: 'dsc-upload-select-name' }, name),\n )\n }),\n )\n : null,\n )\n}\n\n/** Merge a freshly fetched option list with the previous one (latest first,\n * deduped) so the dropdown never drops options mid-session. */\nfunction mergeOptions(prev: Array<string | number>, latest: Array<string | number>): Array<string | number> {\n const seen = new Set<string>()\n const out: Array<string | number> = []\n for (const item of [...latest, ...prev]) {\n const key = String(item)\n if (!seen.has(key)) { seen.add(key); out.push(item) }\n }\n return out\n}\n\n/** Copy text to the clipboard; falls back to a hidden textarea when the\n * clipboard API is unavailable (non-secure LAN http). */\nfunction copyText(text: string): Promise<boolean> {\n if (navigator.clipboard !== undefined) {\n return navigator.clipboard.writeText(text).then(() => true).catch(() => copyViaTextarea(text))\n }\n return Promise.resolve(copyViaTextarea(text))\n}\n\nfunction copyViaTextarea(text: string): boolean {\n const textarea = document.createElement('textarea')\n textarea.value = text\n textarea.style.position = 'fixed'\n textarea.style.opacity = '0'\n document.body.appendChild(textarea)\n textarea.select()\n let ok = false\n try {\n ok = document.execCommand('copy')\n } catch {\n ok = false\n }\n document.body.removeChild(textarea)\n return ok\n}\n\n/** Read a file's pixel size in the browser (image only) and report it to the\n * plugin so the workflow output size can default to the source image. Returns\n * the size text for display, or undefined when unreadable. */\nasync function recordMediaSize(file: File, name: string): Promise<string | undefined> {\n try {\n const bitmap = await createImageBitmap(file)\n const width = bitmap.width\n const height = bitmap.height\n bitmap.close()\n await fetch('/comfyui/media-size', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name, width, height }),\n }).catch(() => undefined)\n return `${width}×${height}`\n } catch {\n return undefined\n }\n}\n\n/** SHA-256 hex digest (pure JS — crypto.subtle needs a secure context, which a\n * LAN http origin is not). Uses the standard padding/compression; the input is\n * any byte array. */\nfunction sha256Hex(data: Uint8Array): string {\n const K = new Uint32Array([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n ])\n const H = new Uint32Array([0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19])\n const len = data.length\n const total = len + 1 + (((56 - ((len + 1) % 64)) + 64) % 64) + 8\n const msg = new Uint8Array(total)\n msg.set(data)\n msg[len] = 0x80\n const bitLenLo = (len * 8) >>> 0\n const bitLenHi = Math.floor(len / 0x20000000)\n const dv = new DataView(msg.buffer)\n dv.setUint32(total - 8, bitLenHi)\n dv.setUint32(total - 4, bitLenLo)\n const w = new Uint32Array(64)\n for (let offset = 0; offset < total; offset += 64) {\n for (let i = 0; i < 16; i++) w[i] = dv.getUint32(offset + i * 4)\n for (let i = 16; i < 64; i++) {\n const s0 = ((w[i - 15]! >>> 7) | (w[i - 15]! << 25)) ^ ((w[i - 15]! >>> 18) | (w[i - 15]! << 14)) ^ (w[i - 15]! >>> 3)\n const s1 = ((w[i - 2]! >>> 17) | (w[i - 2]! << 15)) ^ ((w[i - 2]! >>> 19) | (w[i - 2]! << 13)) ^ (w[i - 2]! >>> 10)\n w[i] = (w[i - 16]! + s0 + w[i - 7]! + s1) >>> 0\n }\n let a = H[0]!, b = H[1]!, c = H[2]!, d = H[3]!, e = H[4]!, f = H[5]!, g = H[6]!, h = H[7]!\n for (let i = 0; i < 64; i++) {\n const S1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7))\n const ch = (e & f) ^ (~e & g)\n const temp1 = (h + S1 + ch + K[i]! + w[i]!) >>> 0\n const S0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10))\n const maj = (a & b) ^ (a & c) ^ (b & c)\n const temp2 = (S0 + maj) >>> 0\n h = g; g = f; f = e; e = (d + temp1) >>> 0; d = c; c = b; b = a; a = (temp1 + temp2) >>> 0\n }\n H[0] = (H[0]! + a) >>> 0; H[1] = (H[1]! + b) >>> 0; H[2] = (H[2]! + c) >>> 0; H[3] = (H[3]! + d) >>> 0\n H[4] = (H[4]! + e) >>> 0; H[5] = (H[5]! + f) >>> 0; H[6] = (H[6]! + g) >>> 0; H[7] = (H[7]! + h) >>> 0\n }\n let out = ''\n for (let i = 0; i < 8; i++) out += H[i]!.toString(16).padStart(8, '0')\n return out\n}\n\n/** `image.png` + hash → `image_3f9a2b1c0d.png`: keeps the name readable while\n * making it content-unique, so re-uploading the same file reuses the name. */\nfunction renameWithHash(original: string, hash: string): string {\n const short = hash.slice(0, 10)\n const dot = original.lastIndexOf('.')\n const base = dot > 0 ? original.slice(0, dot) : original\n const ext = dot > 0 ? original.slice(dot) : ''\n return `${base}_${short}${ext}`\n}\n\n/** Upload a file with content-hash naming and dedup: same bytes → same file\n * name, and (for root uploads) the existing file is reused instead of creating\n * a duplicate. Returns the file name on the ComfyUI server. */\nasync function uploadDedup(file: File, subfolder?: string): Promise<string> {\n const hash = sha256Hex(new Uint8Array(await file.arrayBuffer()))\n const dedup = subfolder === undefined || subfolder === ''\n if (dedup) {\n const lookup = await fetch('/comfyui/media-lookup', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ hash }),\n }).then((response) => response.json() as Promise<{ ok?: boolean; found?: boolean; name?: string }>).catch(() => undefined)\n if (lookup !== undefined && lookup.ok === true && lookup.found === true && typeof lookup.name === 'string') {\n return lookup.name\n }\n }\n const renamed = new File([file], renameWithHash(file.name, hash), { type: file.type })\n const form = new FormData()\n form.append('image', renamed)\n if (!dedup) form.append('subfolder', subfolder)\n const response = await fetch('/comfyui/upload', { method: 'POST', body: form })\n const data = (await response.json()) as { ok?: boolean; name?: string; error?: string }\n if (data.ok !== true || typeof data.name !== 'string') throw new Error(data.error ?? 'upload failed')\n if (dedup) {\n await fetch('/comfyui/media-hash', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ hash, name: data.name }),\n }).catch(() => undefined)\n }\n return data.name\n}\n\n/**\n * Parameter editor: lists the workflow's adjustable parameters (auto-detected\n * prompt/size/steps/seed) with editable name/label/default and a random\n * toggle for number parameters, plus an \"advanced\" picker that exposes any\n * node input as a custom parameter.\n */\nfunction ParameterEditor(props: {\n t: ComfyUIPanelProps['t']\n params: WorkflowParameter[]\n workflow: Record<string, unknown>\n onChange: (params: WorkflowParameter[]) => void\n}): ReturnType<typeof h> {\n const { t, params, workflow, onChange } = props\n const [advanced, setAdvanced] = useState(false)\n const [advNode, setAdvNode] = useState('')\n const [advInput, setAdvInput] = useState('')\n const [advLabel, setAdvLabel] = useState('')\n const [recognizing, setRecognizing] = useState(false)\n const [recognizeError, setRecognizeError] = useState<string | null>(null)\n const [uploading, setUploading] = useState<Record<string, boolean>>({})\n // Raw text of number fields while they are being typed. Parsing on every\n // keystroke would swallow an in-progress decimal (\"1.\" → 1), which is what\n // used to make float defaults impossible to enter.\n const [numDraft, setNumDraft] = useState<Record<string, string>>({})\n const [hovered, setHovered] = useState<string | null>(null)\n // Latest params/uploadFile for the global paste listener (bound once).\n const hoverRef = useRef<string | null>(null)\n const latestRef = useRef<{ params: WorkflowParameter[]; uploadFile: (param: WorkflowParameter, file: File) => Promise<void> }>({\n params,\n uploadFile: async () => undefined,\n })\n\n /** Re-fetch a parameter's live option list (ComfyUI input dir files) and\n * merge it into the stored options, so uploads made anywhere show up in the\n * dropdown without reloading the workflow editor. */\n const refreshOptions = async (param: WorkflowParameter): Promise<Array<string | number> | undefined> => {\n const rawNode = (workflow as Record<string, { class_type?: string }>)[param.nodeId]\n const classType = typeof rawNode?.class_type === 'string' ? rawNode.class_type : ''\n if (classType === '') return undefined\n const result = (await postJson('/comfyui/workflows/input-options', { classType, inputKey: param.inputKey })) as\n { ok?: boolean; options?: Array<string | number> }\n if (result.ok !== true || !Array.isArray(result.options)) return undefined\n const latest = result.options\n const index = params.findIndex((entry) => entry.id === param.id)\n if (index !== -1 && params[index]?.options !== undefined) {\n update(index, { options: mergeOptions(params[index]!.options!, latest) })\n }\n return latest\n }\n\n /** Upload a dropped file through the plugin proxy into ComfyUI's input dir. */\n const uploadFile = async (param: WorkflowParameter, file: File): Promise<void> => {\n setUploading((prev) => ({ ...prev, [param.id]: true }))\n try {\n const name = await uploadDedup(file, param.subfolder)\n void recordMediaSize(file, name)\n const index = params.findIndex((entry) => entry.id === param.id)\n if (index !== -1) update(index, { default: name })\n void refreshOptions(param)\n } finally {\n setUploading((prev) => ({ ...prev, [param.id]: false }))\n }\n }\n latestRef.current = { params, uploadFile }\n\n /** Global paste: Ctrl+V with the mouse hovering an upload parameter routes\n * the clipboard file (e.g. a screenshot) to that parameter — same mental\n * model as pasting an image into a chat input. */\n useEffect(() => {\n const onPaste = (event: ClipboardEvent): void => {\n const targetId = hoverRef.current\n if (targetId === null) return\n const file = event.clipboardData?.files?.[0]\n if (file === undefined) return\n const param = latestRef.current.params.find((entry) => entry.id === targetId)\n if (param === undefined || param.upload === undefined) return\n event.preventDefault()\n void latestRef.current.uploadFile(param, file)\n }\n document.addEventListener('paste', onPaste)\n return () => document.removeEventListener('paste', onPaste)\n }, [])\n\n /** Auto-generate the internal parameter name from the input key, deduped against existing params. */\n const genParamName = (base: string): string => {\n let name = base\n let index = 2\n while (params.some((param) => param.name === name)) name = `${base}_${index++}`\n return name\n }\n\n const nodeEntries = Object.entries(workflow).map(([id, raw]) => [id, raw as { class_type?: string; inputs?: Record<string, unknown> }] as const)\n const advNodeInfo = nodeEntries.find(([id]) => id === advNode)?.[1]\n // Widget-valued inputs are offered without filtering (the loader `upload`\n // pseudo-input included). Inputs currently fed by a link ([nodeId, slot])\n // are left out: they carry no value to edit, and exposing one only creates\n // a parameter that would fight the connection.\n const advInputs = advNodeInfo !== undefined && advNodeInfo.inputs !== undefined\n ? Object.entries(advNodeInfo.inputs).filter(([, value]) => !isLinkValue(value))\n : []\n const selectedInput = advInputs.find(([key]) => key === advInput)\n\n /** Server-side auto-detection: prompt/size/steps/seed + dropdown options (object_info). */\n const recognize = async (): Promise<void> => {\n if (recognizing) return\n setRecognizing(true)\n setRecognizeError(null)\n try {\n const result = (await postJson('/comfyui/workflows/recognize', { workflow })) as { ok?: boolean; parameters?: WorkflowParameter[]; error?: string }\n if (result.ok === true && Array.isArray(result.parameters)) {\n onChange(result.parameters)\n setAdvanced(false)\n } else {\n setRecognizeError(result.error ?? t('wfParamsRecognizeFailed'))\n }\n } catch {\n setRecognizeError(t('wfParamsRecognizeFailed'))\n } finally {\n setRecognizing(false)\n }\n }\n\n const update = (index: number, patch: Partial<WorkflowParameter>): void => {\n onChange(params.map((param, i) => (i === index ? { ...param, ...patch } : param)))\n }\n\n const addAdvanced = async (): Promise<void> => {\n if (advNode === '' || advInput === '' || selectedInput === undefined || advNodeInfo === undefined) return\n const [, value] = selectedInput\n // A linked or object-valued input has no widget value to start from: it\n // becomes a string parameter with an empty default, which the run path\n // reads as \"leave the link alone unless a value is passed\".\n const type = typeof value === 'number' ? 'number' : typeof value === 'boolean' ? 'boolean' : 'string'\n\n // Generic media-list heuristic: a string holding a JSON array of\n // {kind, file, ...} items (e.g. MiniMaxH3 media_state) becomes one\n // reference-slot parameter per item. Detection is shape-based, never\n // class-specific.\n const existingMedia = params.some((param) => param.nodeId === advNode && param.inputKey === advInput && param.upload === 'media')\n if (!existingMedia && typeof value === 'string') {\n let parsed: unknown\n try {\n parsed = JSON.parse(value) as unknown\n } catch {\n parsed = undefined\n }\n if (Array.isArray(parsed) && parsed.length > 0\n && parsed.every((item) => typeof item === 'object' && item !== null && typeof (item as { file?: unknown }).file === 'string')) {\n const items = parsed as Array<{ name?: unknown; file?: unknown }>\n const firstFile = items[0]?.file\n const slash = typeof firstFile === 'string' ? firstFile.indexOf('/') : -1\n const subfolder = typeof firstFile === 'string' && slash > 0 ? firstFile.slice(0, slash) : undefined\n const added: WorkflowParameter[] = items.map((item, i) => ({\n id: newParamId(),\n name: genParamName(`media_${i + 1}`),\n label: `${t('wfRefSlot')}${i + 1}`,\n type: 'string',\n nodeId: advNode,\n inputKey: advInput,\n default: typeof item.name === 'string' ? item.name : '',\n upload: 'media',\n subfolder,\n }))\n onChange([...params, ...added])\n setAdvanced(false)\n setAdvNode('')\n setAdvInput('')\n setAdvLabel('')\n return\n }\n }\n\n // Ask the server for the node's dropdown options (object_info combos) and\n // whether this input is a loader file picker (upload kind).\n let options: Array<string | number> | undefined\n let upload: WorkflowParameter['upload']\n let numberSpec: { kind?: 'int' | 'float'; min?: number; max?: number; step?: number } | undefined\n if (typeof advNodeInfo.class_type === 'string') {\n try {\n const result = (await postJson('/comfyui/workflows/input-options', { classType: advNodeInfo.class_type, inputKey: advInput })) as {\n ok?: boolean\n options?: Array<string | number>\n upload?: 'image' | 'video' | 'audio'\n number?: { kind?: 'int' | 'float'; min?: number; max?: number; step?: number }\n }\n if (result.ok === true && Array.isArray(result.options) && result.options.length > 0) options = result.options\n upload = result.upload\n numberSpec = result.number\n } catch {\n // options and the numeric type are a nice-to-have; fall back to free text\n }\n }\n onChange([...params, {\n id: newParamId(),\n name: genParamName(advInput),\n label: advLabel !== '' ? advLabel : `${advNode} · ${advInput}`,\n type,\n nodeId: advNode,\n inputKey: advInput,\n default: typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' ? value : '',\n numberKind: type === 'number' ? numberSpec?.kind : undefined,\n min: type === 'number' ? numberSpec?.min : undefined,\n max: type === 'number' ? numberSpec?.max : undefined,\n step: type === 'number' ? numberSpec?.step : undefined,\n options,\n upload,\n }])\n setAdvanced(false)\n setAdvNode('')\n setAdvInput('')\n setAdvLabel('')\n }\n\n /** Update a parameter's default; DynamicCombo parents refresh their child (size) parameter. */\n const updateDefault = (index: number, value: string | number | boolean): void => {\n update(index, { default: value })\n const param = params[index]\n if (param === undefined || typeof value !== 'string') return\n if (param.options === undefined || param.options.length === 0) return\n // Child parameter key is \"<parent>.<child>\" on the same node (e.g. aspect_ratio.size).\n const childIndex = params.findIndex((entry) => entry.nodeId === param.nodeId && entry.inputKey.startsWith(`${param.inputKey}.`))\n if (childIndex === -1) return\n const child = params[childIndex]\n if (child === undefined) return\n const rawNode = (workflow as Record<string, { class_type?: string }>)[child.nodeId]\n const classType = typeof rawNode?.class_type === 'string' ? rawNode.class_type : ''\n void postJson('/comfyui/workflows/input-options', { classType, inputKey: param.inputKey, parentValue: value })\n .then((result) => {\n const data = result as { ok?: boolean; child?: { childInputKey: string; options: Array<string | number>; default: string } }\n if (data.ok === true && data.child !== undefined && childIndex < params.length) {\n update(childIndex, { options: data.child.options, default: data.child.default })\n }\n })\n .catch(() => undefined)\n }\n\n return h('div', { className: 'dsc-params' },\n params.length === 0\n ? h('div', { className: 'dsc-hint' }, t('wfParamsEmpty'))\n : h('div', { className: 'dsc-list' }, params.map((param, index) => h('div', { key: param.id, className: 'dsc-param-row' },\n h('div', { className: 'dsc-param-fields' },\n h('input', {\n className: 'dsc-input dsc-input--sm',\n value: param.label,\n placeholder: t('wfParamLabel'),\n onChange: (event: { target: { value: string } }) => update(index, { label: event.target.value }),\n }),\n ),\n param.upload === 'media'\n ? h('div', {\n className: 'dsc-param-upload-wrap',\n onMouseEnter: () => { hoverRef.current = param.id; setHovered(param.id) },\n onMouseLeave: () => { hoverRef.current = null; setHovered(null) },\n },\n h('input', {\n className: 'dsc-input dsc-input--sm dsc-param-default',\n value: String(param.default),\n placeholder: t('wfMediaEmpty'),\n title: `${param.subfolder ?? ''}/`,\n onChange: (event: { target: { value: string } }) => updateDefault(index, event.target.value),\n }),\n h('label', {\n className: hovered === param.id ? 'dsc-dropzone dsc-dropzone--over' : 'dsc-dropzone',\n title: t('wfPasteHint'),\n tabIndex: 0,\n onDragOver: (event: { preventDefault: () => void }) => event.preventDefault(),\n onDrop: (event: { preventDefault: () => void; dataTransfer?: { files?: File[] } }) => {\n event.preventDefault()\n const file = event.dataTransfer?.files?.[0]\n if (file !== undefined) void uploadFile(param, file)\n },\n onPaste: (event: { clipboardData?: { files?: File[] } }) => {\n const file = event.clipboardData?.files?.[0]\n if (file !== undefined) void uploadFile(param, file)\n },\n },\n h('input', {\n type: 'file',\n style: { display: 'none' },\n onChange: (event: { target: HTMLInputElement }) => {\n const file = event.target.files?.[0]\n if (file !== undefined) void uploadFile(param, file)\n event.target.value = ''\n },\n }),\n uploading[param.id] === true ? t('wfParamsUploading') : t('wfParamsDrop'),\n ),\n h('button', { className: 'dsc-btn', onClick: () => updateDefault(index, '') }, t('wfMediaClear')),\n )\n : param.upload !== undefined\n ? h('div', {\n className: 'dsc-param-upload-wrap',\n onMouseEnter: () => { hoverRef.current = param.id; setHovered(param.id) },\n onMouseLeave: () => { hoverRef.current = null; setHovered(null) },\n },\n param.options !== undefined && param.options.length > 0\n ? h(UploadSelect, {\n value: String(param.default),\n options: param.options,\n kind: param.upload,\n onChange: (value: string) => updateDefault(index, value),\n onRefresh: () => refreshOptions(param),\n })\n : null,\n h('label', {\n className: hovered === param.id ? 'dsc-dropzone dsc-dropzone--over' : 'dsc-dropzone',\n title: t('wfPasteHint'),\n tabIndex: 0,\n onDragOver: (event: { preventDefault: () => void }) => event.preventDefault(),\n onDrop: (event: { preventDefault: () => void; dataTransfer?: { files?: File[] } }) => {\n event.preventDefault()\n const file = event.dataTransfer?.files?.[0]\n if (file !== undefined) void uploadFile(param, file)\n },\n onPaste: (event: { clipboardData?: { files?: File[] } }) => {\n const file = event.clipboardData?.files?.[0]\n if (file !== undefined) void uploadFile(param, file)\n },\n },\n h('input', {\n type: 'file',\n style: { display: 'none' },\n onChange: (event: { target: HTMLInputElement }) => {\n const file = event.target.files?.[0]\n if (file !== undefined) void uploadFile(param, file)\n event.target.value = ''\n },\n }),\n uploading[param.id] === true ? t('wfParamsUploading') : `${t('wfParamsDrop')} ${t(`uploadKind_${param.upload}`)}`,\n ),\n )\n : (param.options !== undefined && param.options.length > 0)\n ? h('select', {\n className: 'dsc-input dsc-input--sm dsc-param-default',\n value: String(param.default),\n onChange: (event: { target: { value: string } }) => updateDefault(index, event.target.value),\n },\n param.options.map((option) => h('option', { key: String(option), value: String(option) }, String(option))),\n )\n : param.type === 'string'\n ? h('textarea', {\n className: 'dsc-input dsc-param-default',\n rows: 2,\n value: String(param.default),\n placeholder: t('wfParamDefault'),\n onChange: (event: { target: { value: string } }) => updateDefault(index, event.target.value),\n })\n : param.type === 'boolean'\n ? h('label', { className: 'dsc-param-bool dsc-param-default' },\n h('input', {\n type: 'checkbox',\n checked: asBool(param.default),\n onChange: (event: { target: { checked: boolean } }) => updateDefault(index, event.target.checked),\n }),\n h('span', null, asBool(param.default) ? 'true' : 'false'),\n )\n : param.type === 'number'\n ? h('input', {\n className: 'dsc-input dsc-input--sm dsc-param-default',\n inputMode: param.numberKind === 'int' ? 'numeric' : 'decimal',\n value: numDraft[param.id] ?? String(param.default),\n placeholder: t('wfParamDefault'),\n title: numberRangeHint(param),\n onChange: (event: { target: { value: string } }) => {\n const raw = event.target.value\n setNumDraft((prev) => ({ ...prev, [param.id]: raw }))\n const parsed = Number(raw)\n if (raw.trim() !== '' && Number.isFinite(parsed)) updateDefault(index, parsed)\n },\n onBlur: () => {\n // Commit: an int input rounds, an empty/garbled field falls\n // back to 0, and the draft is dropped so the stored value\n // shows through again.\n const raw = numDraft[param.id]\n setNumDraft((prev) => {\n const next = { ...prev }\n delete next[param.id]\n return next\n })\n if (raw === undefined) return\n const parsed = Number(raw)\n const value = raw.trim() === '' || !Number.isFinite(parsed) ? 0 : parsed\n updateDefault(index, param.numberKind === 'int' ? Math.round(value) : value)\n },\n })\n : h('input', {\n className: 'dsc-input dsc-input--sm dsc-param-default',\n value: String(param.default),\n placeholder: t('wfParamDefault'),\n onChange: (event: { target: { value: string } }) => updateDefault(index, event.target.value),\n }),\n h('div', { className: 'dsc-param-meta' },\n h('span', { className: 'dsc-meta' }, `${param.type}${param.type === 'number' ? `/${param.numberKind ?? '?'}` : ''} · #${param.nodeId}.${param.inputKey}`),\n param.type === 'number'\n ? h('label', { className: 'dsc-param-random' },\n h('input', {\n type: 'checkbox',\n checked: param.random === true,\n onChange: (event: { target: { checked: boolean } }) => update(index, { random: event.target.checked }),\n }),\n h('span', null, t('wfParamRandom')),\n )\n : null,\n h('button', { className: 'dsc-btn', onClick: () => onChange(params.filter((_, i) => i !== index)) }, t('wfParamDelete')),\n ),\n ))),\n h('div', { className: 'dsc-toolbar' },\n h('button', { className: 'dsc-btn', disabled: recognizing, onClick: () => { void recognize() } }, recognizing ? t('wfParamsRecognizing') : t('wfParamsRecognize')),\n h('button', { className: 'dsc-btn', onClick: () => setAdvanced(!advanced) }, t('wfParamsAdd')),\n ),\n recognizeError !== null ? h('div', { className: 'dsc-hint dsc-hint--error' }, recognizeError) : null,\n advanced\n ? h('div', { className: 'dsc-param-advanced' },\n h('div', { className: 'dsc-param-fields' },\n h('select', {\n className: 'dsc-input dsc-input--sm',\n value: advNode,\n onChange: (event: { target: { value: string } }) => { setAdvNode(event.target.value); setAdvInput('') },\n },\n h('option', { value: '' }, '—'),\n nodeEntries.map(([id, node]) => h('option', { key: id, value: id }, `#${id} ${node.class_type ?? ''}`)),\n ),\n advNodeInfo !== undefined\n ? h('select', {\n className: 'dsc-input dsc-input--sm',\n value: advInput,\n onChange: (event: { target: { value: string } }) => setAdvInput(event.target.value),\n },\n h('option', { value: '' }, '—'),\n advInputs.map(([key, value]) => h('option', { key, value: key }, `${key} (${inputValueKind(value)})`)),\n )\n : null,\n h('input', {\n className: 'dsc-input dsc-input--sm',\n value: advLabel,\n placeholder: t('wfParamCustomLabel'),\n onChange: (event: { target: { value: string } }) => setAdvLabel(event.target.value),\n }),\n h('button', { className: 'dsc-btn', disabled: advNode === '' || advInput === '', onClick: () => { void addAdvanced() } }, t('wfParamAdd')),\n ),\n h('div', { className: 'dsc-hint' }, t('wfParamCustomHint')),\n )\n : null,\n )\n}\n\nfunction formatTs(ts: string): string {\n const date = new Date(ts)\n return Number.isNaN(date.getTime()) ? ts : date.toLocaleString()\n}\n\nfunction formatBytes(bytes: number | undefined): string {\n if (bytes === undefined) return ''\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(2)} MB`\n}\n\n/** The panel shell: header (drag handle), tabs, and the active tab body. */\nexport function ComfyUIPanel({ t }: ComfyUIPanelProps): ReturnType<typeof h> | null {\n const open = usePanelOpen()\n const tab = usePanelTab()\n const [geom, setGeom] = useState<PanelGeom>(() => healGeom(loadGeom(), window.innerWidth, window.innerHeight))\n const [dragging, setDragging] = useState<'move' | 'resize' | null>(null)\n const [lightbox, setLightbox] = useState<{ images: string[]; kinds: Array<'image' | 'video' | 'audio' | 'other'>; index: number } | null>(null)\n const panelRef = useRef<HTMLDivElement | null>(null)\n const dragRef = useRef<{ startX: number; startY: number; origX: number; origY: number; width: number; height: number } | null>(null)\n\n const openPreview = (images: string[], kinds: Array<'image' | 'video' | 'audio' | 'other'>, index: number): void => setLightbox({ images, kinds, index })\n\n useEffect(() => {\n if (open) {\n // The window may have been resized or moved to another monitor while the\n // panel was closed, or the saved position may predate the reachability\n // clamp — snap a header that ended up out of reach back into the viewport.\n setGeom((prev) => healGeom(prev, window.innerWidth, window.innerHeight))\n return\n }\n saveGeom(geom)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open])\n\n // While the panel is open, keep the header reachable across viewport\n // resizes too (shrinking the window can otherwise strand it off-screen).\n useEffect(() => {\n if (!open) return\n const onResize = (): void => setGeom((prev) => healGeom(prev, window.innerWidth, window.innerHeight))\n window.addEventListener('resize', onResize)\n return () => window.removeEventListener('resize', onResize)\n }, [open])\n\n const startDrag = (event: PointerEventLike, mode: 'move' | 'resize'): void => {\n if (event.button !== 0) return\n if (mode === 'move') {\n const target = event.target as HTMLElement | null\n if (target !== null && target.closest('button, input, textarea, select, a, label')) return\n }\n const rect = panelRef.current?.getBoundingClientRect()\n if (rect === undefined) return\n dragRef.current = {\n startX: event.clientX, startY: event.clientY,\n origX: rect.left, origY: rect.top, width: rect.width, height: rect.height,\n }\n setDragging(mode)\n const el = event.currentTarget as HTMLElement | null\n if (el !== null && typeof el.setPointerCapture === 'function') el.setPointerCapture(event.pointerId)\n }\n\n const moveDrag = (event: PointerEventLike): void => {\n const d = dragRef.current\n if (d === null) return\n if (dragging === 'move') {\n // Clamp while dragging so the header can never be pushed out of reach.\n const pos = clampPos(\n Math.round(d.origX + event.clientX - d.startX),\n Math.round(d.origY + event.clientY - d.startY),\n d.width,\n window.innerWidth,\n window.innerHeight,\n )\n setGeom((prev) => ({ ...prev, x: pos.x, y: pos.y }))\n } else if (dragging === 'resize') {\n const width = Math.max(300, Math.min(720, d.width + event.clientX - d.startX))\n const height = Math.max(200, Math.min(Math.max(300, window.innerHeight - 40), d.height + event.clientY - d.startY))\n setGeom((prev) => ({ ...prev, width, height }))\n }\n }\n\n const endDrag = (): void => {\n if (dragRef.current === null) return\n dragRef.current = null\n setDragging(null)\n setGeom((prev) => {\n saveGeom(prev)\n return prev\n })\n }\n\n if (!open) return null\n\n const panelStyle: Record<string, string> = {}\n if (geom.x !== undefined && geom.y !== undefined) {\n panelStyle.left = `${geom.x}px`\n panelStyle.top = `${geom.y}px`\n panelStyle.right = 'auto'\n panelStyle.bottom = 'auto'\n }\n if (geom.width !== undefined) panelStyle.width = `${geom.width}px`\n if (geom.height !== undefined) panelStyle.height = `${geom.height}px`\n\n return h('div',\n { ref: panelRef, className: `dsc-panel${dragging !== null ? ' dsc-panel--dragging' : ''}`, style: panelStyle },\n h('div', {\n className: 'dsc-panel-head',\n onPointerDown: (event: PointerEventLike) => startDrag(event, 'move'),\n onPointerMove: (event: PointerEventLike) => moveDrag(event),\n onPointerUp: () => endDrag(),\n onPointerCancel: () => endDrag(),\n },\n h('span', { className: 'dsc-panel-title' },\n h('span', { className: 'dsc-trigger-glyph' }, h(ComfyUIIcon)),\n h('span', null, t('panelTitle')),\n ),\n h('span', { className: 'dsc-panel-head-actions' },\n h('button', {\n className: 'dsc-panel-reset',\n type: 'button',\n title: t('panelReset'),\n 'aria-label': t('panelReset'),\n onClick: () => {\n // Restore the CSS-anchored default (right side, 400px wide) and\n // clear the stored geometry so the default also survives refresh.\n setGeom({})\n try {\n localStorage.removeItem(GEOM_KEY)\n } catch {\n // storage unavailable — nothing persisted anyway\n }\n },\n }, '↺'),\n h('button', {\n className: 'dsc-panel-close',\n 'aria-label': t('close'),\n onClick: () => panelStore.close(),\n }, '✕'),\n ),\n ),\n h('div', { className: 'dsc-tabs' },\n h(TabButton, { t, active: tab === 'workflows', label: t('tabWorkflows'), onClick: () => panelStore.setTab('workflows') }),\n h(TabButton, { t, active: tab === 'assets', label: t('tabAssets'), onClick: () => panelStore.setTab('assets') }),\n h(TabButton, { t, active: tab === 'queue', label: t('tabQueue'), onClick: () => panelStore.setTab('queue') }),\n ),\n h('div', { className: 'dsc-panel-body' },\n tab === 'workflows' ? h(WorkflowsTab, { t })\n : tab === 'assets' ? h(AssetsTab, { t, onPreview: openPreview })\n : h(QueueTab, { t, onPreview: openPreview }),\n ),\n lightbox !== null ? h(Lightbox, {\n t,\n images: lightbox.images,\n kinds: lightbox.kinds,\n index: lightbox.index,\n onClose: () => setLightbox(null),\n onIndex: (index: number) => setLightbox({ images: lightbox.images, kinds: lightbox.kinds, index }),\n }) : null,\n h('div', {\n className: 'dsc-panel-resize',\n onPointerDown: (event: PointerEventLike) => startDrag(event, 'resize'),\n onPointerMove: (event: PointerEventLike) => moveDrag(event),\n onPointerUp: () => endDrag(),\n onPointerCancel: () => endDrag(),\n }),\n )\n}\n\nfunction TabButton(props: { t: ComfyUIPanelProps['t']; active: boolean; label: string; onClick: () => void }): ReturnType<typeof h> {\n return h('button', {\n className: props.active ? 'dsc-tab dsc-tab--active' : 'dsc-tab',\n onClick: props.onClick,\n }, props.label)\n}\n\nfunction ErrorNote({ t, message }: { t: ComfyUIPanelProps['t']; message: string }): ReturnType<typeof h> {\n return h('div', { className: 'dsc-err' }, `${t('error')}: ${message}`)\n}\n\n/** Tab 1: workflow library — plugin library + ComfyUI-side saved workflows. */\n/** One selectable item in the load-area picker (mirrors the host response). */\ninterface LoadAreaFile {\n name: string\n kind: 'image' | 'video' | 'audio'\n url: string\n source: 'imported' | 'generated'\n ts?: string\n workflowName?: string | null\n width?: number\n height?: number\n}\n\n/** Load area at the bottom of the workflow library, modeled on the ComfyUI\n * LoadImage node — a list of **slots** rather than a single image.\n *\n * A lone slot stretches across the panel; from two slots on they share a\n * fixed width and wrap into rows. A slot is either filled with a file or\n * empty (added but not yet picked, or emptied through the picker's \"空\"\n * tile); the whole card is the pick button, and hovering reveals an × in the\n * corner that removes the slot. Filled slots feed the workflow's loader\n * parameters in order, so a run that takes two reference images picks up\n * slots 1 and 2 without the agent naming files. */\nfunction LoadArea(props: { t: ComfyUIPanelProps['t']; onNotice: (message: string) => void }): ReturnType<typeof h> {\n const [slots, setSlots] = useState<Array<LoadAreaFile | null>>([])\n const [files, setFiles] = useState<LoadAreaFile[]>([])\n /** Slot index the picker is currently filling; null = picker closed. */\n const [pickerFor, setPickerFor] = useState<number | null>(null)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const refresh = useCallback(async (): Promise<void> => {\n const data = (await fetch('/comfyui/loadarea').then((response) => response.json()).catch(() => undefined)) as\n { ok?: boolean; current?: LoadAreaFile | null; slots?: Array<LoadAreaFile | null>; files?: LoadAreaFile[] } | undefined\n if (data?.ok === true) {\n // `slots` is the current contract; `current` is the older single-image\n // payload, kept working so a stale client/server pair still shows something.\n setSlots(data.slots ?? (data.current !== null && data.current !== undefined ? [data.current] : []))\n setFiles(data.files ?? [])\n }\n }, [])\n\n useEffect(() => { void refresh() }, [refresh])\n\n const post = async (body: Record<string, unknown>): Promise<boolean> => {\n setBusy(true)\n setError(null)\n try {\n const response = await fetch('/comfyui/current-image', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n const data = (await response.json().catch(() => ({}))) as { ok?: boolean; error?: string }\n if (data.ok !== true) throw new Error(data.error ?? `HTTP ${response.status}`)\n await refresh()\n return true\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n return false\n } finally {\n setBusy(false)\n }\n }\n\n const upload = async (file: File): Promise<string> => {\n setBusy(true)\n setError(null)\n try {\n const name = await uploadDedup(file)\n const sizeText = await recordMediaSize(file, name)\n await refresh()\n props.onNotice(`${props.t('wfUploaded')}:${name}${sizeText !== undefined ? `(${sizeText})` : ''}`)\n return name\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n throw cause\n } finally {\n setBusy(false)\n }\n }\n\n const pick = async (file: LoadAreaFile): Promise<void> => {\n const index = pickerFor\n setPickerFor(null)\n const ok = await post({ name: file.name, kind: file.kind, source: file.source, ...(index !== null ? { index } : {}) })\n if (ok) props.onNotice(`${props.t('wfLoadPicked')}:${file.name}`)\n }\n\n /** \"+ 添加加载区\": opens a slot and goes straight to the picker for it, so\n * adding material is one gesture; closing the picker leaves the empty slot. */\n const addSlot = async (): Promise<void> => {\n const index = slots.length\n if (await post({ action: 'addSlot' })) setPickerFor(index)\n }\n\n const loaded = slots.filter((slot) => slot !== null).length\n\n return h('div', { className: 'dsc-loadarea' },\n h('div', { className: 'dsc-loadarea-head' },\n h('span', { className: 'dsc-loadarea-title' }, props.t('wfLoadArea')),\n h('span', { className: 'dsc-meta' }, slots.length === 0\n ? props.t('wfLoadEmpty')\n : props.t('wfLoadSummary', { slots: slots.length, loaded })),\n ),\n h('div', { className: 'dsc-loadslots' },\n slots.map((slot, index) => h(LoadSlot, {\n key: index,\n t: props.t,\n slot,\n index,\n busy,\n // A single slot fills the panel width; two or more share a fixed one.\n wide: slots.length === 1,\n onPick: () => setPickerFor(index),\n onRemove: () => { void post({ action: 'removeSlot', index }) },\n })),\n ),\n h('div', { className: 'dsc-toolbar' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => { void addSlot() } }, props.t('wfLoadAddSlot')),\n ),\n pickerFor !== null\n ? h(LoadPicker, {\n t: props.t,\n files,\n current: (pickerFor < slots.length ? slots[pickerFor]?.name : undefined) ?? null,\n onUpload: upload,\n onPick: pick,\n // First tile of the grid: empties the slot without removing it.\n onClear: () => { const index = pickerFor; setPickerFor(null); void post({ action: 'clear', index }) },\n onClose: () => setPickerFor(null),\n })\n : null,\n error !== null ? h('div', { className: 'dsc-hint dsc-hint--error' }, error) : null,\n )\n}\n\n/** One load-area slot card. The card is the pick button (empty slots show\n * \"加载位 N / 添加素材\"); the × in the corner, revealed on hover, removes the\n * slot. Emptying a slot without removing it is done from the picker's \"空\"\n * tile, so the card carries no button row of its own. */\nfunction LoadSlot(props: {\n t: ComfyUIPanelProps['t']\n slot: LoadAreaFile | null\n index: number\n busy: boolean\n wide: boolean\n onPick: () => void\n onRemove: () => void\n}): ReturnType<typeof h> {\n const { t, slot, index } = props\n const size = slot?.width !== undefined && slot.height !== undefined ? `(${slot.width}×${slot.height})` : ''\n return h('div', { className: props.wide ? 'dsc-loadslot dsc-loadslot--wide' : 'dsc-loadslot' },\n h('button', {\n className: 'dsc-loadslot-pick',\n onClick: props.onPick,\n disabled: props.busy,\n title: slot !== null ? slot.name : t('wfLoadHint'),\n },\n slot === null\n ? h('span', { className: 'dsc-loadslot-empty' },\n h('span', { className: 'dsc-loadslot-index' }, `${t('wfLoadSlotLabel')} ${index + 1}`),\n h('span', { className: 'dsc-loadslot-add' }, t('wfLoadAddMedia')),\n )\n : slot.kind === 'video'\n ? h('video', { className: 'dsc-loadslot-media', src: slot.url, preload: 'metadata', muted: true })\n : slot.kind === 'audio'\n ? h('span', { className: 'dsc-loadslot-empty' }, '♪')\n : h('img', { className: 'dsc-loadslot-media', src: slot.url, alt: '', loading: 'lazy' }),\n slot !== null ? h('span', { className: 'dsc-loadslot-name' }, `${slot.name}${size}`) : null,\n ),\n h('button', {\n className: 'dsc-loadslot-x',\n disabled: props.busy,\n title: t('wfLoadRemoveSlot'),\n 'aria-label': t('wfLoadRemoveSlot'),\n onClick: props.onRemove,\n }, '×'),\n )\n}\n\n/** The load-area picker dialog: tab bar (全部/已导入/已生成) with a\n * paste/click upload zone on the right, and a masonry image grid below. */\nfunction LoadPicker(props: {\n t: ComfyUIPanelProps['t']\n files: LoadAreaFile[]\n current: string | null\n onUpload: (file: File) => Promise<string>\n onPick: (file: LoadAreaFile) => Promise<void>\n /** Empty the slot this picker was opened for (first tile of the grid). */\n onClear?: () => void\n onClose: () => void\n}): ReturnType<typeof h> {\n const [tab, setTab] = useState<'all' | 'imported' | 'generated'>('all')\n const [type, setType] = useState<'all' | 'image' | 'video' | 'audio'>('all')\n const hoverRef = useRef(false)\n const [uploadFlash, setUploadFlash] = useState<string | null>(null)\n const [scrollTo, setScrollTo] = useState<string | null>(null)\n const cardRefs = useRef<Map<string, HTMLElement>>(new Map())\n const flashTimer = useRef<number | undefined>(undefined)\n\n useEffect(() => () => {\n if (flashTimer.current !== undefined) window.clearTimeout(flashTimer.current)\n }, [])\n\n useEffect(() => {\n const onPaste = (event: ClipboardEvent): void => {\n if (!hoverRef.current) return\n const file = event.clipboardData?.files?.[0]\n if (file === undefined) return\n event.preventDefault()\n void handleUpload(file)\n }\n document.addEventListener('paste', onPaste)\n return () => document.removeEventListener('paste', onPaste)\n })\n\n /** Upload, then flash a confirmation and scroll the grid to the new file. */\n const handleUpload = async (file: File): Promise<void> => {\n try {\n const name = await props.onUpload(file)\n setScrollTo(name)\n setUploadFlash(`${props.t('wfUploadedToast')}:${name}`)\n if (flashTimer.current !== undefined) window.clearTimeout(flashTimer.current)\n flashTimer.current = window.setTimeout(() => setUploadFlash(null), 2500)\n } catch {\n // LoadArea shows the upload error in its own area.\n }\n }\n\n const bySource = tab === 'all' ? props.files : props.files.filter((file) => file.source === tab)\n const filtered = type === 'all' ? bySource : bySource.filter((file) => file.kind === type)\n\n // After the refreshed file list renders, scroll the matching card into view.\n useEffect(() => {\n if (scrollTo === null) return\n let found: HTMLElement | undefined\n for (const [key, el] of cardRefs.current) {\n if (key.endsWith(`:${scrollTo}`)) { found = el; break }\n }\n if (found !== undefined) {\n found.scrollIntoView({ block: 'center', behavior: 'smooth' })\n setScrollTo(null)\n }\n }, [scrollTo, filtered])\n // Distribute into 3 vertical columns (round-robin) — a masonry look that\n // scrolls reliably, unlike CSS multi-column which balances columns to the\n // container height and never overflows.\n const columns: LoadAreaFile[][] = [[], [], []]\n filtered.forEach((file, index) => { columns[index % 3]!.push(file) })\n const tabs: Array<{ id: 'all' | 'imported' | 'generated'; label: string }> = [\n { id: 'all', label: props.t('wfTabAll') },\n { id: 'imported', label: props.t('wfTabImported') },\n { id: 'generated', label: props.t('wfTabGenerated') },\n ]\n const typeOptions: Array<{ id: 'all' | 'image' | 'video' | 'audio'; label: string }> = [\n { id: 'all', label: props.t('wfTypeAll') },\n { id: 'image', label: props.t('uploadKind_image') },\n { id: 'video', label: props.t('uploadKind_video') },\n { id: 'audio', label: props.t('uploadKind_audio') },\n ]\n\n return h('div', { className: 'dsc-picker-overlay', onClick: props.onClose },\n h('div', { className: 'dsc-picker', onClick: (event: { stopPropagation: () => void }) => event.stopPropagation() },\n h('div', { className: 'dsc-picker-bar' },\n h('div', { className: 'dsc-picker-tabs' },\n tabs.map((entry) => h('button', {\n key: entry.id,\n className: `dsc-picker-tab${tab === entry.id ? ' dsc-picker-tab--active' : ''}`,\n onClick: () => setTab(entry.id),\n }, entry.label)),\n ),\n h('label', {\n className: 'dsc-dropzone dsc-picker-upload',\n title: props.t('wfPasteHint'),\n onMouseEnter: () => { hoverRef.current = true },\n onMouseLeave: () => { hoverRef.current = false },\n onDragOver: (event: { preventDefault: () => void }) => event.preventDefault(),\n onDrop: (event: { preventDefault: () => void; dataTransfer?: { files?: File[] } }) => {\n event.preventDefault()\n const file = event.dataTransfer?.files?.[0]\n if (file !== undefined) void handleUpload(file)\n },\n },\n h('input', {\n type: 'file',\n style: { display: 'none' },\n onChange: (event: { target: HTMLInputElement }) => {\n const file = event.target.files?.[0]\n if (file !== undefined) void handleUpload(file)\n event.target.value = ''\n },\n }),\n props.t('wfPickerUpload'),\n ),\n h('select', {\n className: 'dsc-picker-type',\n value: type,\n onChange: (event: { target: { value: string } }) => setType(event.target.value as 'all' | 'image' | 'video' | 'audio'),\n }, typeOptions.map((option) => h('option', { key: option.id, value: option.id }, option.label))),\n ),\n filtered.length === 0 && props.onClear === undefined\n ? h('div', { className: 'dsc-picker-empty' }, props.t('wfLoadNoFiles'))\n : h('div', { className: 'dsc-picker-grid' },\n columns.map((column, columnIndex) => h('div', { key: columnIndex, className: 'dsc-picker-col' },\n // \"空\": clears the slot the picker was opened for, so a slot can be\n // emptied without deleting it.\n columnIndex === 0 && props.onClear !== undefined\n ? h('div', {\n className: `dsc-picker-card dsc-picker-card--none${props.current === null ? ' dsc-picker-card--active' : ''}`,\n role: 'button',\n tabIndex: 0,\n onClick: () => props.onClear?.(),\n onKeyDown: (event: { key: string; preventDefault: () => void }) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n props.onClear?.()\n }\n },\n title: props.t('wfLoadNoneHint'),\n },\n h('span', { className: 'dsc-picker-thumb dsc-picker-thumb--media' }, '∅'),\n h('span', { className: 'dsc-picker-name' }, props.t('wfLoadNone')),\n )\n : null,\n // A card is a div rather than a button: video/audio players are\n // interactive content and may not be nested inside a button, and\n // clicking their controls must not select the card.\n column.map((file) => h('div', {\n key: `${file.source}:${file.name}`,\n className: `dsc-picker-card${file.name === props.current ? ' dsc-picker-card--active' : ''}`,\n role: 'button',\n tabIndex: 0,\n onClick: () => { void props.onPick(file) },\n onKeyDown: (event: { key: string; preventDefault: () => void }) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n void props.onPick(file)\n }\n },\n title: file.name,\n ref: (el: HTMLElement | null): void => {\n if (el !== null) cardRefs.current.set(`${file.source}:${file.name}`, el)\n else cardRefs.current.delete(`${file.source}:${file.name}`)\n },\n },\n file.kind === 'image'\n ? h('img', { className: 'dsc-picker-thumb', src: file.url, alt: '', loading: 'lazy' })\n : file.kind === 'video'\n ? h('video', {\n className: 'dsc-picker-thumb dsc-picker-player',\n src: file.url,\n controls: true,\n preload: 'metadata',\n onClick: (event: { stopPropagation: () => void }) => event.stopPropagation(),\n })\n : h('audio', {\n className: 'dsc-picker-player dsc-picker-player--audio',\n src: file.url,\n controls: true,\n preload: 'metadata',\n onClick: (event: { stopPropagation: () => void }) => event.stopPropagation(),\n }),\n // On a video/audio card the player keeps its own clicks, so this\n // name row is the click target that picks the file — it is sized\n // accordingly.\n h('span', { className: 'dsc-picker-name' }, file.name),\n file.width !== undefined && file.height !== undefined\n ? h('span', { className: 'dsc-meta' }, `${file.width}×${file.height}`)\n : null,\n )),\n )),\n ),\n uploadFlash !== null ? h('div', { className: 'dsc-picker-toast' }, uploadFlash) : null,\n ),\n )\n}\n\n/** Tag editor: preset classification chips (图生图 etc.) toggle on/off, plus\n * free-form custom tags added with Enter and removed by clicking. */\nfunction TagEditor(props: {\n t: ComfyUIPanelProps['t']\n tags: string[]\n onChange: (tags: string[]) => void\n}): ReturnType<typeof h> {\n const [custom, setCustom] = useState('')\n\n const toggle = (tag: string): void => {\n props.onChange(props.tags.includes(tag) ? props.tags.filter((entry) => entry !== tag) : [...props.tags, tag])\n }\n\n const addCustom = (): void => {\n const tag = custom.trim()\n if (tag === '' || props.tags.includes(tag)) return\n props.onChange([...props.tags, tag])\n setCustom('')\n }\n\n const customTags = props.tags.filter((tag) => !PRESET_TAGS.includes(tag))\n\n return h('div', { className: 'dsc-tag-editor' },\n h('div', { className: 'dsc-tag-row' },\n PRESET_TAGS.map((tag) => h('button', {\n key: tag,\n className: `dsc-tag-chip${props.tags.includes(tag) ? ' dsc-tag-chip--active' : ''}`,\n onClick: () => toggle(tag),\n }, tag)),\n ),\n customTags.length > 0\n ? h('div', { className: 'dsc-tag-row' },\n customTags.map((tag) => h('button', {\n key: tag,\n className: 'dsc-tag-chip dsc-tag-chip--active',\n title: props.t('wfTagRemove'),\n onClick: () => toggle(tag),\n }, `✕ ${tag}`)),\n )\n : null,\n h('input', {\n className: 'dsc-input dsc-input--sm dsc-tag-input',\n value: custom,\n placeholder: props.t('wfTagAdd'),\n onChange: (event: { target: { value: string } }) => setCustom(event.target.value),\n onKeyDown: (event: { key: string; preventDefault: () => void }) => {\n if (event.key === 'Enter') { event.preventDefault(); addCustom() }\n },\n }),\n )\n}\n\n/**\n * The skill-pack editor for one workflow: attach/detach the pack, toggle the\n * run-time gate, and manage its files (SKILL.md plus references/ and scripts/).\n *\n * The pack is what `comfyui_workflow action: skill` hands the agent, so this\n * view is the only place its content is authored. Each file saves explicitly —\n * no autosave — because the model reads whatever is on disk the moment it asks.\n * SKILL.md is edited as a summary field plus a body: the `---` frontmatter that\n * carries the summary is composed on the host, never typed here.\n */\nfunction SkillPackEditor(props: {\n t: ComfyUIPanelProps['t']\n workflow: WorkflowEntry\n onBack: () => void\n onChanged: () => void\n}): ReturnType<typeof h> {\n const { t } = props\n const [pack, setPack] = useState<SkillPack | null>(null)\n const [enabled, setEnabled] = useState<boolean>(props.workflow.skillDir !== undefined)\n const [active, setActive] = useState<string>('SKILL.md')\n const [summary, setSummary] = useState<string>('')\n const [text, setText] = useState<string>('')\n const [dirty, setDirty] = useState<boolean>(false)\n const [pendingOpen, setPendingOpen] = useState<string | null>(null)\n const [creating, setCreating] = useState<{ bucket: string; name: string } | null>(null)\n const [creatingDir, setCreatingDir] = useState<string | null>(null)\n const [presetDirs, setPresetDirs] = useState<string[]>(SKILL_FALLBACK_DIRS)\n const [renaming, setRenaming] = useState<{ from: string; to: string } | null>(null)\n const [confirming, setConfirming] = useState<string | null>(null)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [notice, setNotice] = useState<string | null>(null)\n\n /** Load one file into the editor; SKILL.md arrives pre-split into summary + body. */\n const openFile = useCallback(async (path: string): Promise<void> => {\n // Images are shown, not edited: reading one as UTF-8 would only produce\n // garbage in the textarea.\n if (isSkillImage(path)) {\n setActive(path)\n setSummary('')\n setText('')\n setDirty(false)\n setError(null)\n return\n }\n try {\n const data = await getJson<{ ok?: boolean; content?: string; summary?: string; body?: string; error?: string }>(\n `/comfyui/workflows/skill?id=${encodeURIComponent(props.workflow.id)}&path=${encodeURIComponent(path)}`,\n )\n if (data.ok !== true) {\n setError(data.error ?? t('skillReadFailed'))\n return\n }\n setActive(path)\n if (path === 'SKILL.md') {\n setSummary(data.summary ?? '')\n setText(data.body ?? '')\n } else {\n setSummary('')\n setText(data.content ?? '')\n }\n setDirty(false)\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }, [props.workflow.id, t])\n\n /** Re-read the pack listing, then the requested file. */\n const refresh = useCallback(async (path?: string): Promise<void> => {\n try {\n const data = await getJson<SkillPackResponse>(`/comfyui/workflows/skill?id=${encodeURIComponent(props.workflow.id)}`)\n setEnabled(data.enabled === true)\n setPack(data.pack ?? null)\n if (Array.isArray(data.presetDirs) && data.presetDirs.length > 0) setPresetDirs(data.presetDirs)\n if (data.enabled === true) await openFile(path ?? 'SKILL.md')\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }, [props.workflow.id, openFile])\n\n /** Re-read the pack listing and — only when nothing is unsaved — the file\n * currently open, so files added or replaced outside this panel (the agent\n * writing via comfyui_skill, or the file manager after `打开目录`) show up\n * without leaving and re-entering the view. */\n const refreshFiles = async (): Promise<void> => {\n setBusy(true)\n setNotice(null)\n try {\n const data = await getJson<SkillPackResponse>(`/comfyui/workflows/skill?id=${encodeURIComponent(props.workflow.id)}`)\n setEnabled(data.enabled === true)\n setPack(data.pack ?? null)\n if (Array.isArray(data.presetDirs) && data.presetDirs.length > 0) setPresetDirs(data.presetDirs)\n setError(null)\n props.onChanged()\n if (data.enabled === true && !dirty) await openFile(active)\n setNotice(t('skillRefreshed'))\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n useEffect(() => {\n void refresh()\n }, [refresh])\n\n /** Every mutation goes through here so the listing and the flags stay in sync. */\n const mutate = async (body: Record<string, unknown>, after?: string): Promise<boolean> => {\n setBusy(true)\n setNotice(null)\n try {\n const data = (await postJson('/comfyui/workflows/skill', { id: props.workflow.id, ...body })) as SkillPackResponse\n if (data.ok !== true) {\n setError(data.error ?? t('skillFailed'))\n return false\n }\n setEnabled(data.enabled === true)\n setPack(data.pack ?? null)\n setError(null)\n props.onChanged()\n if (after !== undefined && data.enabled === true) await openFile(after)\n return true\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n return false\n } finally {\n setBusy(false)\n }\n }\n\n const saveFile = async (): Promise<boolean> => {\n const body: Record<string, unknown> = { action: 'write', path: active, content: text }\n if (active === 'SKILL.md') body.summary = summary\n const ok = await mutate(body)\n if (ok) {\n setDirty(false)\n setNotice(`${t('skillSaved')} ${active}`)\n }\n return ok\n }\n\n /** Switching files with unsaved edits parks the request until the user decides. */\n const selectFile = (path: string): void => {\n if (path === active) return\n if (dirty) {\n setPendingOpen(path)\n return\n }\n void openFile(path)\n }\n\n const createFile = async (): Promise<void> => {\n if (creating === null) return\n const name = creating.name.trim()\n if (name === '') return\n const path = `${creating.bucket}/${name.includes('.') ? name : `${name}.md`}`\n const ok = await mutate({ action: 'write', path, content: '' }, path)\n if (ok) setCreating(null)\n }\n\n /** Open the pack directory in the desktop file manager (on the machine\n * running DSH — the hint says so, and the path stays visible below). */\n const revealDir = async (): Promise<void> => {\n setNotice(null)\n try {\n const data = (await postJson('/comfyui/workflows/skill/reveal', { id: props.workflow.id })) as { ok?: boolean; error?: string; dir?: string }\n if (data.ok !== true) {\n setError(data.error ?? t('skillFailed'))\n return\n }\n setError(null)\n setNotice(`${t('skillRevealed')} ${data.dir ?? ''}`)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n const createDir = async (): Promise<void> => {\n if (creatingDir === null) return\n const name = creatingDir.trim()\n if (name === '') return\n const ok = await mutate({ action: 'mkdir', name })\n if (ok) {\n setCreatingDir(null)\n setNotice(`${t('skillDirCreated')} ${name}/`)\n }\n }\n\n const applyRename = async (): Promise<void> => {\n if (renaming === null) return\n const to = renaming.to.trim()\n if (to === '') return\n const bucket = renaming.from.includes('/') ? `${renaming.from.split('/')[0] ?? ''}/` : ''\n const target = to.includes('/') ? to : `${bucket}${to}`\n const ok = await mutate({ action: 'rename', path: renaming.from, to: target }, target)\n if (ok) setRenaming(null)\n }\n\n /** Import local files into the pack. The destination bucket comes from the\n * host (one extension rule, shared with the agent-facing listing), so the\n * panel only sends the name and the bytes. */\n const importFiles = async (files: File[]): Promise<void> => {\n if (files.length === 0) return\n setBusy(true)\n setNotice(null)\n let imported: string | null = null\n let failed = 0\n for (const file of files) {\n try {\n const bytes = await file.arrayBuffer()\n const data = (await postRaw(\n `/comfyui/workflows/skill/import?id=${encodeURIComponent(props.workflow.id)}&name=${encodeURIComponent(file.name)}`,\n bytes,\n )) as SkillPackResponse & { path?: string }\n if (data.ok !== true) {\n failed += 1\n setError(data.error ?? t('skillFailed'))\n continue\n }\n setPack(data.pack ?? null)\n imported = data.path ?? null\n } catch (cause) {\n failed += 1\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n setBusy(false)\n props.onChanged()\n if (imported !== null) {\n if (failed === 0) {\n setError(null)\n setNotice(`${t('skillImported')} ${imported}`)\n }\n await openFile(imported)\n }\n }\n\n const head = h('div', { className: 'dsc-view-head' },\n h('button', { className: 'dsc-btn', onClick: props.onBack }, t('wfViewBack')),\n h('div', { className: 'dsc-wf-name', title: props.workflow.name }, `${t('skillTitle')} · ${props.workflow.name}`),\n )\n\n if (!enabled) {\n return h('div', null,\n head,\n h('div', { className: 'dsc-hint' }, t('skillIntro')),\n error !== null ? h(ErrorNote, { t, message: error }) : null,\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => void mutate({ action: 'enable' }, 'SKILL.md') }, t('skillEnable')),\n ),\n )\n }\n\n const files = pack?.files ?? []\n // Directories come from disk, so a folder the user created by hand (or an\n // empty one they just added) shows up exactly like a preset would. The list\n // is unioned with the directories the file paths imply: a host that predates\n // the `dirs` field would otherwise hide every sub-directory it does report\n // files for.\n const impliedDirs = files\n .filter((file) => file.path.includes('/'))\n .map((file) => file.path.split('/')[0] ?? '')\n .filter((dir) => dir !== '')\n const packDirs = [...new Set([...(pack?.dirs ?? []), ...impliedDirs])].sort((a, b) => a.localeCompare(b))\n const buckets: Array<{ label: string; items: SkillPackFile[] }> = [\n { label: '', items: files.filter((file) => !file.path.includes('/')) },\n ...packDirs.map((bucket) => ({\n label: bucket,\n items: files.filter((file) => file.path.startsWith(`${bucket}/`)),\n })),\n ]\n /** Where a new file may go: the pack's own directories first, then the\n * presets it has not used yet. */\n const targetDirs = [...packDirs, ...presetDirs.filter((dir) => !packDirs.includes(dir))]\n\n /** One row in the pack file list; clicking opens it for editing. */\n const fileButton = (file: SkillPackFile): ReturnType<typeof h> => h('button', {\n key: file.path,\n className: `dsc-skill-file${file.path === active ? ' dsc-skill-file--active' : ''}`,\n onClick: () => selectFile(file.path),\n },\n h('span', { className: 'dsc-skill-file-name' }, file.path.includes('/') ? file.path.split('/')[1] : file.path),\n h('span', { className: 'dsc-skill-file-size' }, formatBytes(file.size)),\n )\n\n const fileList = h('div', {\n className: 'dsc-skill-files',\n onDragOver: (event: { preventDefault: () => void }) => event.preventDefault(),\n onDrop: (event: { preventDefault: () => void; dataTransfer?: { files?: File[] } }) => {\n event.preventDefault()\n const dropped = Array.from(event.dataTransfer?.files ?? [])\n if (dropped.length > 0) void importFiles(dropped)\n },\n },\n // Both actions sit at the top of the column: below a long file list they\n // were easy to miss entirely.\n h('div', { className: 'dsc-skill-actions' },\n h('label', { className: 'dsc-btn dsc-btn--sm', title: t('skillImportHint') },\n t('skillImport'),\n h('input', {\n type: 'file',\n multiple: true,\n style: { display: 'none' },\n disabled: busy,\n onChange: (event: { target: HTMLInputElement }) => {\n const picked = Array.from(event.target.files ?? [])\n event.target.value = ''\n if (picked.length > 0) void importFiles(picked)\n },\n }),\n ),\n creating === null\n ? h('button', {\n className: 'dsc-btn dsc-btn--sm',\n disabled: busy,\n onClick: () => { setCreatingDir(null); setCreating({ bucket: targetDirs[0] ?? 'references', name: '' }) },\n }, t('skillNewFile'))\n : null,\n creatingDir === null\n ? h('button', {\n className: 'dsc-btn dsc-btn--sm',\n disabled: busy,\n onClick: () => { setCreating(null); setCreatingDir('') },\n }, t('skillNewDir'))\n : null,\n h('button', {\n className: 'dsc-btn dsc-btn--sm',\n disabled: busy,\n title: t('skillRevealHint'),\n onClick: () => void revealDir(),\n }, t('skillReveal')),\n h('button', {\n className: 'dsc-btn dsc-btn--sm',\n disabled: busy,\n title: t('skillRefreshHint'),\n onClick: () => void refreshFiles(),\n }, t('skillRefresh')),\n ),\n creatingDir === null\n ? null\n : h('div', { className: 'dsc-skill-create' },\n h('input', {\n className: 'dsc-input dsc-input--sm',\n value: creatingDir,\n placeholder: t('skillNewDirPlaceholder'),\n onChange: (event: { target: { value: string } }) => setCreatingDir(event.target.value),\n onKeyDown: (event: { key: string; preventDefault: () => void }) => {\n if (event.key === 'Enter') { event.preventDefault(); void createDir() }\n },\n }),\n h('div', { className: 'dsc-hint' }, t('skillNewDirHint', { presets: presetDirs.join(' / ') })),\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn dsc-btn--sm', disabled: busy, onClick: () => void createDir() }, t('skillCreate')),\n h('button', { className: 'dsc-btn dsc-btn--sm', onClick: () => setCreatingDir(null) }, t('cancel')),\n ),\n ),\n h('div', { className: 'dsc-skill-drop-hint' }, t('skillDropHint')),\n buckets.map((bucket) => bucket.items.length === 0 && bucket.label !== ''\n ? null\n : bucket.label === ''\n // Root files (SKILL.md and anything dropped at the top level) are\n // always visible; only directories fold, so a crowded pack can be\n // collapsed per folder.\n ? h('div', { key: '.', className: 'dsc-skill-bucket' }, bucket.items.map(fileButton))\n : h('details', { key: bucket.label, className: 'dsc-fold dsc-skill-fold', open: true },\n h('summary', null, `${bucket.label}/`),\n h('div', { className: 'dsc-skill-bucket' }, bucket.items.map(fileButton)),\n ),\n ),\n creating === null\n ? null\n : h('div', { className: 'dsc-skill-create' },\n h('select', {\n className: 'dsc-input dsc-input--sm',\n value: creating.bucket,\n onChange: (event: { target: { value: string } }) => setCreating({ ...creating, bucket: event.target.value }),\n }, targetDirs.map((bucket) => h('option', { key: bucket, value: bucket }, `${bucket}/`))),\n h('input', {\n className: 'dsc-input dsc-input--sm',\n value: creating.name,\n placeholder: t('skillNewPlaceholder'),\n onChange: (event: { target: { value: string } }) => setCreating({ ...creating, name: event.target.value }),\n onKeyDown: (event: { key: string; preventDefault: () => void }) => {\n if (event.key === 'Enter') { event.preventDefault(); void createFile() }\n },\n }),\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn dsc-btn--sm', disabled: busy, onClick: () => void createFile() }, t('skillCreate')),\n h('button', { className: 'dsc-btn dsc-btn--sm', onClick: () => setCreating(null) }, t('cancel')),\n ),\n ),\n )\n\n const editor = h('div', { className: 'dsc-skill-main' },\n h('div', { className: 'dsc-skill-editor-head' },\n h('span', { className: 'dsc-skill-path' }, active),\n dirty ? h('span', { className: 'dsc-badge dsc-badge--warn' }, t('skillDirty')) : null,\n ),\n active === 'SKILL.md'\n ? h('div', { className: 'dsc-field' },\n h('label', null, t('skillSummary')),\n h('input', {\n className: 'dsc-input',\n value: summary,\n placeholder: t('skillSummaryPlaceholder'),\n onChange: (event: { target: { value: string } }) => { setSummary(event.target.value); setDirty(true) },\n }),\n h('div', { className: 'dsc-hint' }, t('skillSummaryHint')),\n )\n : null,\n isSkillImage(active)\n ? h('div', { className: 'dsc-skill-preview' },\n h('img', {\n src: `/comfyui/workflows/skill/raw?id=${encodeURIComponent(props.workflow.id)}&path=${encodeURIComponent(active)}`,\n alt: active,\n }),\n h('div', { className: 'dsc-hint' }, t('skillImageHint')),\n )\n : h('textarea', {\n className: 'dsc-textarea dsc-textarea--skill',\n value: text,\n spellCheck: false,\n onChange: (event: { target: { value: string } }) => { setText(event.target.value); setDirty(true) },\n onKeyDown: (event: { key: string; preventDefault: () => void; target: HTMLTextAreaElement }) => {\n // Tab indents instead of leaving the field: these files hold scripts.\n if (event.key !== 'Tab') return\n event.preventDefault()\n const area = event.target\n const start = area.selectionStart\n const end = area.selectionEnd\n setText(`${text.slice(0, start)} ${text.slice(end)}`)\n setDirty(true)\n window.requestAnimationFrame(() => {\n area.selectionStart = start + 2\n area.selectionEnd = start + 2\n })\n },\n }),\n h('div', { className: 'dsc-row' },\n isSkillImage(active)\n ? null\n : h('button', { className: 'dsc-btn', disabled: busy || !dirty, onClick: () => void saveFile() }, t('skillSave')),\n active !== 'SKILL.md'\n ? h('button', { className: 'dsc-btn', disabled: busy, onClick: () => setRenaming({ from: active, to: active.includes('/') ? active.split('/')[1] ?? '' : active }) }, t('skillRename'))\n : null,\n active !== 'SKILL.md'\n ? h('button', { className: 'dsc-btn', disabled: busy, onClick: () => setConfirming(active) }, t('skillDeleteFile'))\n : null,\n ),\n confirming !== null && confirming !== '*pack*'\n ? h('div', { className: 'dsc-dialog dsc-dialog--danger' },\n h('div', { className: 'dsc-dialog-head dsc-danger-text' }, `${t('skillDeleteConfirm')} ${confirming}`),\n h('div', { className: 'dsc-row' },\n h('button', {\n className: 'dsc-btn dsc-btn--danger',\n disabled: busy,\n onClick: () => {\n const target = confirming\n setConfirming(null)\n void mutate({ action: 'delete', path: target }, 'SKILL.md')\n },\n }, t('confirmDelete')),\n h('button', { className: 'dsc-btn', onClick: () => setConfirming(null) }, t('cancel')),\n ),\n )\n : null,\n renaming !== null\n ? h('div', { className: 'dsc-skill-create' },\n h('input', {\n className: 'dsc-input dsc-input--sm',\n value: renaming.to,\n onChange: (event: { target: { value: string } }) => setRenaming({ ...renaming, to: event.target.value }),\n }),\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn dsc-btn--sm', disabled: busy, onClick: () => void applyRename() }, t('skillRename')),\n h('button', { className: 'dsc-btn dsc-btn--sm', onClick: () => setRenaming(null) }, t('cancel')),\n ),\n )\n : null,\n )\n\n return h('div', null,\n head,\n h('div', { className: 'dsc-row dsc-skill-flags' },\n h('label', { className: 'dsc-check' },\n h('input', {\n type: 'checkbox',\n checked: pack?.required === true,\n disabled: busy,\n onChange: (event: { target: { checked: boolean } }) => void mutate({ action: 'require', required: event.target.checked }),\n }),\n t('skillRequired'),\n ),\n ),\n pack !== null ? h('div', { className: 'dsc-skill-dir', title: pack.dir }, `${t('skillDir')}: ${pack.dir}`) : null,\n pendingOpen !== null\n ? h('div', { className: 'dsc-dialog' },\n h('div', { className: 'dsc-dialog-head' }, t('skillDirtyPrompt')),\n h('div', { className: 'dsc-row' },\n h('button', {\n className: 'dsc-btn',\n disabled: busy,\n onClick: () => {\n const target = pendingOpen\n setPendingOpen(null)\n void saveFile().then((ok) => { if (ok) void openFile(target) })\n },\n }, t('skillSaveAndSwitch')),\n h('button', {\n className: 'dsc-btn',\n onClick: () => {\n const target = pendingOpen\n setPendingOpen(null)\n setDirty(false)\n void openFile(target)\n },\n }, t('skillDiscard')),\n h('button', { className: 'dsc-btn', onClick: () => setPendingOpen(null) }, t('cancel')),\n ),\n )\n : null,\n notice !== null ? h('div', { className: 'dsc-ok' }, notice) : null,\n error !== null ? h(ErrorNote, { t, message: error }) : null,\n h('div', { className: 'dsc-skill' }, fileList, editor),\n // Both confirmations render next to the button that opened them: a dialog\n // pinned to the top of the view reads as \"the page jumped\", not as a\n // question, and destroying a pack is unrecoverable.\n h('div', { className: 'dsc-skill-footer' },\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => void mutate({ action: 'disable' }).then(() => props.onBack()) }, t('skillDetach')),\n h('button', { className: 'dsc-btn dsc-btn--danger', disabled: busy, onClick: () => setConfirming('*pack*') }, t('skillDestroy')),\n ),\n confirming === '*pack*'\n ? h('div', { className: 'dsc-dialog dsc-dialog--danger' },\n h('div', { className: 'dsc-dialog-head dsc-danger-text' }, t('skillDestroyConfirm', { count: pack?.files.length ?? 0 })),\n h('div', { className: 'dsc-row' },\n h('button', {\n className: 'dsc-btn dsc-btn--danger',\n disabled: busy,\n onClick: () => {\n setConfirming(null)\n void mutate({ action: 'destroy' }).then(() => props.onBack())\n },\n }, t('skillDestroyConfirmButton')),\n h('button', { className: 'dsc-btn', onClick: () => setConfirming(null) }, t('cancel')),\n ),\n )\n : null,\n ),\n )\n}\n\nfunction WorkflowsTab({ t }: ComfyUIPanelProps): ReturnType<typeof h> {\n const [list, setList] = useState<WorkflowEntry[] | null>(null)\n const [comfyui, setComfyui] = useState<ComfyUIWorkflowEntry[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [comfyuiError, setComfyuiError] = useState<string | null>(null)\n const [notice, setNotice] = useState<string | null>(null)\n const [editing, setEditing] = useState<WorkflowDraft | null>(null)\n const [busy, setBusy] = useState(false)\n const [viewing, setViewing] = useState<WorkflowViewState | null>(null)\n const [extract, setExtract] = useState<ExtractState | null>(null)\n const [tagFilter, setTagFilter] = useState<string | null>(null)\n const [skillFor, setSkillFor] = useState<WorkflowEntry | null>(null)\n /** A delete waiting on the user's answer about the workflow's skill pack. */\n const [deleting, setDeleting] = useState<WorkflowEntry | null>(null)\n\n const load = async (): Promise<void> => {\n try {\n const data = await getJson<{ workflows: WorkflowEntry[] }>('/comfyui/workflows')\n setList(data.workflows)\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n try {\n const data = await getJson<{ workflows: ComfyUIWorkflowEntry[] }>('/comfyui/comfy-workflows')\n setComfyui(data.workflows)\n setComfyuiError(null)\n } catch (cause) {\n setComfyuiError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n useEffect(() => {\n let cancelled = false\n void getJson<{ workflows: WorkflowEntry[] }>('/comfyui/workflows').then((data) => {\n if (!cancelled) setList(data.workflows)\n }).catch((cause: unknown) => {\n if (!cancelled) setError(cause instanceof Error ? cause.message : String(cause))\n })\n void getJson<{ workflows: ComfyUIWorkflowEntry[] }>('/comfyui/comfy-workflows').then((data) => {\n if (!cancelled) setComfyui(data.workflows)\n }).catch((cause: unknown) => {\n if (!cancelled) setComfyuiError(cause instanceof Error ? cause.message : String(cause))\n })\n return () => {\n cancelled = true\n }\n }, [])\n\n /** Persist the current draft; returns the saved workflow id, or null on failure (error already set). */\n const persist = async (): Promise<string | null> => {\n if (editing === null) return null\n setBusy(true)\n setError(null)\n setNotice(null)\n let workflow: unknown\n if (typeof editing.workflow === 'string') {\n try {\n workflow = JSON.parse(editing.workflow)\n } catch {\n setError(t('wfJsonError'))\n setBusy(false)\n return null\n }\n } else {\n workflow = editing.workflow\n }\n try {\n const body: Record<string, unknown> = {\n name: String(editing.name ?? ''),\n description: String(editing.description ?? ''),\n workflow,\n parameters: editing.parameters ?? [],\n tags: editing.tags ?? [],\n }\n if (editing.id !== undefined) body.id = editing.id\n const result = (await postJson('/comfyui/workflows', body)) as { workflow?: { id?: string } }\n return result.workflow?.id ?? (typeof editing.id === 'string' ? editing.id : null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n return null\n } finally {\n setBusy(false)\n }\n }\n\n const save = async (): Promise<void> => {\n const id = await persist()\n if (id === null) return\n setEditing(null)\n await load()\n }\n\n /** Save the draft, then immediately queue it with the saved parameters. */\n const saveAndRun = async (): Promise<void> => {\n const id = await persist()\n if (id === null) return\n setEditing(null)\n await load()\n await run(id)\n }\n\n const run = async (id: string): Promise<void> => {\n setBusy(true)\n setError(null)\n setNotice(null)\n try {\n const result = (await postJson('/comfyui/workflows/run', { id })) as { promptId: string }\n setNotice(`${t('wfQueued')} ${shortId(result.promptId)}`)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n /** Delete a workflow. A workflow carrying a skill pack asks first: the pack\n * holds hand-written notes that nothing else can restore. */\n const remove = async (id: string, deleteSkill = false): Promise<void> => {\n setBusy(true)\n setError(null)\n try {\n await postJson('/comfyui/workflows/delete', { id, deleteSkill })\n await load()\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n const requestRemove = (workflow: WorkflowEntry): void => {\n if (workflow.skillDir !== undefined) {\n setDeleting(workflow)\n return\n }\n void remove(workflow.id)\n }\n\n const openExtract = (file: string): void => {\n setError(null)\n setExtract({ file, analysis: null, error: null, mode: 'split' })\n }\n\n const runExtract = async (state: ExtractState): Promise<void> => {\n setBusy(true)\n try {\n const data = (await postJson('/comfyui/comfy-workflows/extract', { file: state.file, mode: state.mode })) as { ok: boolean; saved: WorkflowEntry[]; warnings: string[]; error?: string }\n if (data.ok !== true) throw new Error(data.error ?? 'failed to extract')\n setNotice(`${state.file} → ${t('wfExtractedNotice')}${data.warnings.length > 0 ? `(${t('error')}: ${data.warnings.join(';')})` : ''}`)\n setExtract(null)\n await load()\n } catch (cause) {\n setExtract({ ...state, error: cause instanceof Error ? cause.message : String(cause) })\n } finally {\n setBusy(false)\n }\n }\n\n const importFile = (file: File): void => {\n const reader = new FileReader()\n reader.onload = () => {\n try {\n const parsed = JSON.parse(String(reader.result)) as unknown\n setEditing({ name: file.name.replace(/\\.json$/i, ''), workflow: parsed as Record<string, unknown> })\n setError(null)\n } catch {\n setError(t('wfJsonError'))\n }\n }\n reader.readAsText(file)\n }\n\n const view = async (file: string): Promise<void> => {\n setBusy(true)\n setError(null)\n try {\n const data = await getJson<{ ok: boolean; workflow?: Record<string, unknown>; error?: string }>(`/comfyui/comfy-workflows?file=${encodeURIComponent(file)}`)\n if (data.ok !== true || data.workflow === undefined) {\n throw new Error(data.error ?? 'failed to read workflow')\n }\n setViewing({ file, graph: data.workflow })\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n if (skillFor !== null) {\n return h(SkillPackEditor, {\n t,\n workflow: skillFor,\n onBack: () => { setSkillFor(null); void load() },\n onChanged: () => { void load() },\n })\n }\n if (viewing !== null) {\n return h(WorkflowView, { t, file: viewing.file, graph: viewing.graph, onBack: () => setViewing(null) })\n }\n if (extract !== null) {\n return h(ExtractDialog, { t, state: extract, onUpdate: setExtract, onRun: (state) => runExtract(state), onClose: () => setExtract(null) })\n }\n if (error !== null) return h('div', null, h(ErrorNote, { t, message: error }))\n if (list === null) return h('div', { className: 'dsc-meta' }, '…')\n\n if (editing !== null) {\n return h('div', { className: 'dsc-form' },\n h('div', { className: 'dsc-field' },\n h('label', null, t('wfName')),\n h('input', { className: 'dsc-input', value: editing.name ?? '', onChange: (event: { target: { value: string } }) => setEditing({ ...editing, name: event.target.value }) }),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('wfDesc')),\n h('textarea', { className: 'dsc-textarea', placeholder: t('wfDescPlaceholder'), value: editing.description ?? '', onChange: (event: { target: { value: string } }) => setEditing({ ...editing, description: event.target.value }) }),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('wfTags')),\n h(TagEditor, { t, tags: editing.tags ?? [], onChange: (tags) => setEditing({ ...editing, tags }) }),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('wfParams')),\n h(ParameterEditor, {\n t,\n params: editing.parameters ?? [],\n workflow: parseDraftWorkflow(editing.workflow),\n onChange: (parameters) => setEditing({ ...editing, parameters }),\n }),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('wfJson')),\n h('textarea', {\n className: 'dsc-textarea dsc-textarea--json',\n value: typeof editing.workflow === 'string' ? editing.workflow : JSON.stringify(editing.workflow ?? {}, null, 2),\n onChange: (event: { target: { value: string } }) => setEditing({ ...editing, workflow: event.target.value }),\n }),\n ),\n notice !== null ? h('div', { className: 'dsc-ok' }, notice) : null,\n error !== null ? h(ErrorNote, { t, message: error }) : null,\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => void save() }, t('wfSave')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => void saveAndRun() }, t('wfSaveRun')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => { setEditing(null); setError(null) } }, t('wfCancel')),\n ),\n )\n }\n\n const comfyuiFold = h('details', { className: 'dsc-fold' },\n h('summary', null, `${t('wfComfyuiSection')} (${comfyui?.length ?? 0})`),\n h('div', { className: 'dsc-fold-body' },\n h('div', { className: 'dsc-hint' }, t('wfComfyuiHint')),\n comfyuiError !== null ? h(ErrorNote, { t, message: comfyuiError }) : null,\n comfyui === null\n ? h('div', { className: 'dsc-meta' }, '…')\n : comfyui.length === 0\n ? h('div', { className: 'dsc-meta' }, t('wfComfyuiEmpty'))\n : h('div', { className: 'dsc-list' }, comfyui.map((workflow) => h('div', { key: workflow.name, className: 'dsc-wf dsc-wf--comfyui', title: t('wfNameCopyHint'), onClick: () => { void copyText(workflow.name).then((ok) => { if (ok) setNotice(`${t('wfNameCopied')}:${workflow.name}`) }) } },\n h('div', { className: 'dsc-wf-col' },\n h('div', { className: 'dsc-wf-name', title: workflow.name }, workflow.name),\n h('div', { className: 'dsc-wf-actions' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); void view(workflow.name) } }, t('wfView')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); openExtract(workflow.name) } }, t('wfExtract')),\n ),\n h('div', { className: 'dsc-meta' }, [formatBytes(workflow.size), workflow.modified !== undefined ? formatTs(new Date(workflow.modified).toISOString()) : ''].filter(Boolean).join(' · ')),\n ),\n h('span', { className: workflow.extracted ? 'dsc-badge dsc-badge--ok' : 'dsc-badge dsc-badge--warn' }, workflow.extracted ? `${t('wfExtracted')} ${workflow.derived.length}` : t('wfNotExtracted')),\n ))),\n ),\n )\n\n // Tag filter bar: every tag present in the library, preset order first,\n // with counts; null = all workflows.\n const tagCounts = new Map<string, number>()\n for (const workflow of list) {\n for (const tag of workflow.tags ?? []) tagCounts.set(tag, (tagCounts.get(tag) ?? 0) + 1)\n }\n const visibleTags = [...tagCounts.entries()].sort((a, b) => {\n const pa = PRESET_TAGS.indexOf(a[0])\n const pb = PRESET_TAGS.indexOf(b[0])\n if (pa !== -1 && pb !== -1) return pa - pb\n if (pa !== -1) return -1\n if (pb !== -1) return 1\n return b[1] - a[1]\n }).map(([tag]) => tag)\n const visibleList = tagFilter === null ? list : list.filter((workflow) => (workflow.tags ?? []).includes(tagFilter))\n\n const apiFold = h('details', { className: 'dsc-fold', open: true },\n h('summary', null, `${t('wfLibrarySection')} (${visibleList.length})`),\n h('div', { className: 'dsc-fold-body' },\n visibleTags.length > 0 || tagFilter !== null\n ? h('div', { className: 'dsc-tag-filter' },\n // A simple dropdown instead of a chip row: the library can grow\n // many custom tags, and a horizontal strip of chips would push the\n // workflow list down and visually crowd the toolbar. First option\n // is always \"all\"; picking a tag filters, picking \"all\" clears.\n h('select', {\n className: 'dsc-input dsc-input--inline',\n title: t('wfTags'),\n value: tagFilter ?? '',\n onChange: (event: { target: { value: string } }) => setTagFilter(event.target.value === '' ? null : event.target.value),\n },\n h('option', { value: '' }, `${t('wfTagAll')} (${list.length})`),\n visibleTags.map((tag) => h('option', { key: tag, value: tag }, `${tag} (${tagCounts.get(tag) ?? 0})`)),\n ),\n )\n : null,\n visibleList.length === 0\n ? h('div', { className: 'dsc-meta' }, t('wfEmpty'))\n : h('div', { className: 'dsc-list' }, visibleList.map((workflow) => h('div', { key: workflow.id, className: 'dsc-wf', title: t('wfNameCopyHint'), onClick: () => { void copyText(workflow.name).then((ok) => { if (ok) setNotice(`${t('wfNameCopied')}:${workflow.name}`) }) } },\n h('div', { className: 'dsc-wf-top' },\n h('div', { className: 'dsc-wf-name', title: workflow.name }, workflow.name),\n (workflow.tags ?? []).length > 0\n ? h('div', { className: 'dsc-wf-tags' }, (workflow.tags ?? []).map((tag) => h('span', { key: tag, className: 'dsc-tag-chip dsc-tag-chip--mini' }, tag)))\n : null,\n workflow.skillDir !== undefined\n ? h('span', { className: 'dsc-badge dsc-badge--ok', title: t('skillBadgeHint') }, workflow.requireSkill === true ? t('skillBadgeRequired') : t('skillBadge'))\n : null,\n ),\n workflow.description !== '' ? h('div', { className: 'dsc-wf-desc' }, workflow.description) : null,\n h('div', { className: 'dsc-wf-updated' }, `${t('wfUpdated')} ${formatTs(workflow.updatedAt)}`),\n h('div', { className: 'dsc-wf-actions' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); void run(workflow.id) } }, t('wfRun')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); setEditing({ ...workflow, workflow: JSON.stringify(workflow.workflow, null, 2), parameters: workflow.parameters ?? [], tags: workflow.tags ?? [] }); setError(null) } }, t('wfEdit')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); setSkillFor(workflow); setError(null) } }, t('skillButton')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); requestRemove(workflow) } }, t('wfDelete')),\n ),\n deleting?.id === workflow.id\n ? h('div', { className: 'dsc-dialog dsc-dialog--danger', onClick: (event: { stopPropagation: () => void }) => event.stopPropagation() },\n h('div', { className: 'dsc-dialog-head dsc-danger-text' }, t('skillDeleteWithWorkflow')),\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn dsc-btn--danger', disabled: busy, onClick: () => { setDeleting(null); void remove(workflow.id, true) } }, t('skillDeleteBoth')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => { setDeleting(null); void remove(workflow.id, false) } }, t('skillKeepPack')),\n h('button', { className: 'dsc-btn', onClick: () => setDeleting(null) }, t('cancel')),\n ),\n )\n : null,\n ))),\n ),\n )\n\n return h('div', null,\n h('div', { className: 'dsc-toolbar' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => { setEditing({ workflow: {}, parameters: [], tags: [] }); setError(null) } }, t('wfAdd')),\n h('label', { className: 'dsc-btn' },\n t('wfImportFile'),\n h('input', {\n type: 'file',\n accept: '.json,application/json',\n style: { display: 'none' },\n onChange: (event: { target: HTMLInputElement }) => {\n const file = event.target.files?.[0]\n if (file !== undefined) importFile(file)\n event.target.value = ''\n },\n }),\n ),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => void load() }, t('wfRefresh')),\n ),\n notice !== null ? h('div', { className: 'dsc-ok' }, notice) : null,\n comfyuiFold,\n apiFold,\n h(LoadArea, { t, onNotice: setNotice }),\n )\n}\n\n/** Extract-mode chooser: shows the canvas analysis and lets the user pick how\n * to extract runnable API workflows from a ComfyUI-side graph. */\nfunction ExtractDialog(props: {\n t: ComfyUIPanelProps['t']\n state: ExtractState\n onUpdate: (state: ExtractState) => void\n onRun: (state: ExtractState) => Promise<void>\n onClose: () => void\n}): ReturnType<typeof h> {\n const { t, state, onUpdate, onRun, onClose } = props\n useEffect(() => {\n if (state.analysis === null && state.error === null) {\n let cancelled = false\n void getJson<{ ok: boolean; analysis?: GraphAnalysis; error?: string }>(`/comfyui/comfy-workflows/analyze?file=${encodeURIComponent(state.file)}`)\n .then((data) => {\n if (cancelled) return\n if (data.ok !== true || data.analysis === undefined) onUpdate({ ...state, error: data.error ?? 'failed to analyze' })\n else onUpdate({ ...state, analysis: data.analysis, mode: data.analysis.mode === 'single' ? 'all' : 'split' })\n })\n .catch((cause: unknown) => {\n if (!cancelled) onUpdate({ ...state, error: cause instanceof Error ? cause.message : String(cause) })\n })\n return () => {\n cancelled = true\n }\n }\n return undefined\n })\n\n const modes: Array<{ mode: ExtractMode; label: string; hint: string }> = [\n { mode: 'all', label: t('wfExtractModeAll'), hint: t('wfExtractModeAllHint') },\n { mode: 'split', label: t('wfExtractModeSplit'), hint: t('wfExtractModeSplitHint') },\n { mode: 'main', label: t('wfExtractModeMain'), hint: t('wfExtractModeMainHint') },\n ]\n const analysis = state.analysis\n return h('div', { className: 'dsc-dialog' },\n h('div', { className: 'dsc-dialog-head' },\n h('span', { className: 'dsc-wf-name' }, `${t('wfExtractTitle')}: ${state.file}`),\n h('button', { className: 'dsc-panel-close', 'aria-label': t('close'), onClick: onClose }, '✕'),\n ),\n analysis === null\n ? h('div', { className: 'dsc-meta' }, '…')\n : h('div', null,\n h('div', { className: 'dsc-hint' },\n `${t('wfComponents')}: ${analysis.components.length} · ${t('wfBypassed')}: ${analysis.bypassedCount} · ${t('wfIsolated')}: ${analysis.isolated.length}`,\n ),\n analysis.components.length > 0\n ? h('ul', { className: 'dsc-node-list' },\n analysis.components.map((component) => h('li', { key: String(component.index) },\n `${t('wfComponentLabel')} ${component.index}(${component.size} ${t('wfNodes')})${component.groups.length > 0 ? `[${component.groups.slice(0, 3).join('+')}]` : ''}`,\n )),\n )\n : h('div', { className: 'dsc-meta' }, t('wfExtractEmpty')),\n h('div', { className: 'dsc-extract-modes' },\n modes.map((entry) => h('label', { key: entry.mode, className: 'dsc-mode' },\n h('input', {\n type: 'radio',\n name: 'extract-mode',\n checked: state.mode === entry.mode,\n onChange: () => onUpdate({ ...state, mode: entry.mode }),\n }),\n h('span', { className: 'dsc-mode-label' }, entry.label),\n h('span', { className: 'dsc-hint' }, entry.hint),\n )),\n ),\n state.error !== null ? h(ErrorNote, { t, message: state.error }) : null,\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn', disabled: analysis.components.length === 0, onClick: () => void onRun(state) }, t('wfExtractRun')),\n h('button', { className: 'dsc-btn', onClick: onClose }, t('wfCancel')),\n ),\n ),\n )\n}\n\n/** Read-only inspection of a ComfyUI-side saved workflow: node list + JSON. */\nfunction WorkflowView(props: { t: ComfyUIPanelProps['t']; file: string; graph: Record<string, unknown>; onBack: () => void }): ReturnType<typeof h> {\n const nodes = Array.isArray(props.graph.nodes)\n ? (props.graph.nodes as Array<Record<string, unknown>>).filter((node) => node.mode !== 4 && typeof node.type === 'string' && node.type !== '')\n : []\n const json = JSON.stringify(props.graph, null, 2)\n return h('div', { className: 'dsc-view' },\n h('div', { className: 'dsc-view-head' },\n h('span', { className: 'dsc-wf-name' }, props.file),\n h('button', { className: 'dsc-btn', onClick: props.onBack }, props.t('wfViewBack')),\n ),\n h('div', { className: 'dsc-view-label' }, `${props.t('wfViewNodes')} (${nodes.length})`),\n nodes.length === 0\n ? h('div', { className: 'dsc-meta' }, props.t('wfViewEmpty'))\n : h('ul', { className: 'dsc-node-list' }, nodes.map((node) => h('li', { key: String(node.id) }, `${String(node.id)} · ${String(node.type)}`))),\n h('div', { className: 'dsc-view-label' }, props.t('wfViewJson')),\n h('textarea', { className: 'dsc-textarea dsc-textarea--json dsc-textarea--view', readOnly: true, value: json }),\n )\n}\n\n/** Tab 2: asset preview — thumbnails of everything the plugin generated. */\nfunction AssetsTab({ t, onPreview }: { t: ComfyUIPanelProps['t']; onPreview: (images: string[], kinds: Array<'image' | 'video' | 'audio' | 'other'>, index: number) => void }): ReturnType<typeof h> {\n const [assets, setAssets] = useState<AssetEntry[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [filter, setFilter] = useState(() => panelStore.getAssetFilter())\n /** Asset awaiting the delete confirmation, if any. */\n const [pendingDelete, setPendingDelete] = useState<AssetEntry | null>(null)\n const [deleting, setDeleting] = useState(false)\n const [notice, setNotice] = useState<string | null>(null)\n\n const load = async (): Promise<void> => {\n try {\n const data = await getJson<{ assets: AssetEntry[] }>('/comfyui/assets')\n setAssets(data.assets)\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n useEffect(() => {\n let cancelled = false\n void getJson<{ assets: AssetEntry[] }>('/comfyui/assets').then((data) => {\n if (!cancelled) setAssets(data.assets)\n }).catch((cause: unknown) => {\n if (!cancelled) setError(cause instanceof Error ? cause.message : String(cause))\n })\n return () => {\n cancelled = true\n }\n }, [])\n\n /** Delete the record and (when the output directory is known) its files. */\n const confirmDelete = async (asset: AssetEntry): Promise<void> => {\n setDeleting(true)\n try {\n const result = (await postJson('/comfyui/assets/delete', { promptId: asset.promptId })) as\n { ok?: boolean; error?: string; deleted?: number; failures?: string[] }\n if (result.ok !== true) throw new Error(result.error ?? 'delete failed')\n setPendingDelete(null)\n setNotice(t('assetDeleteDone', { deleted: result.deleted ?? 0 }))\n if (Array.isArray(result.failures) && result.failures.length > 0) {\n setError(result.failures.join('; '))\n }\n await load()\n } catch (cause) {\n setError(t('assetDeleteFailed', { message: cause instanceof Error ? cause.message : String(cause) }))\n setPendingDelete(null)\n } finally {\n setDeleting(false)\n }\n }\n\n if (error !== null && assets === null) return h('div', null, h(ErrorNote, { t, message: error }))\n if (assets === null) return h('div', { className: 'dsc-meta' }, '…')\n\n const names = [...new Set(assets.map((asset) => asset.workflowName ?? ''))]\n const visible = filter === '' ? assets : assets.filter((asset) => (asset.workflowName ?? '') === filter)\n // Every media item in the visible grid, in display order, for the lightbox\n // sequence (videos/audio included so clicking a thumbnail can play it).\n const previewItems = visible.flatMap((asset) => asset.media.map((item) => ({ url: item.url, kind: item.kind })))\n const openAsset = (asset: AssetEntry): void => {\n const first = asset.media[0]\n const index = first !== undefined ? previewItems.findIndex((item) => item.url === first.url) : 0\n onPreview(previewItems.map((item) => item.url), previewItems.map((item) => item.kind), index < 0 ? 0 : index)\n }\n\n return h('div', null,\n h('div', { className: 'dsc-toolbar' },\n h('select', { className: 'dsc-input dsc-input--inline', value: filter, onChange: (event: { target: { value: string } }) => setFilter(event.target.value) },\n h('option', { value: '' }, t('assetAll')),\n names.map((name) => h('option', { key: name, value: name }, name === '' ? '—' : name)),\n ),\n h('button', { className: 'dsc-btn', onClick: () => void load() }, t('refresh')),\n ),\n error !== null ? h(ErrorNote, { t, message: error }) : null,\n notice !== null ? h('div', { className: 'dsc-ok' }, notice) : null,\n visible.length === 0\n ? h('div', { className: 'dsc-meta' }, t('assetEmpty'))\n : h('div', { className: 'dsc-assets-grid' }, visible.map((asset) => h(AssetThumb, {\n key: asset.promptId,\n asset,\n t,\n onClick: () => openAsset(asset),\n onDelete: () => { setNotice(null); setPendingDelete(asset) },\n }))),\n pendingDelete !== null\n ? h(ConfirmDialog, {\n t,\n title: t('assetDeleteTitle'),\n body: t('assetDeleteBody', { count: pendingDelete.media.length }),\n detail: pendingDelete.media.map((item) => item.filename).join('、'),\n busy: deleting,\n onConfirm: () => { void confirmDelete(pendingDelete) },\n onCancel: () => setPendingDelete(null),\n })\n : null,\n )\n}\n\n/** Modal confirmation for a destructive action (asset deletion). */\nfunction ConfirmDialog(props: {\n t: ComfyUIPanelProps['t']\n title: string\n body: string\n detail?: string\n busy: boolean\n onConfirm: () => void\n onCancel: () => void\n}): ReturnType<typeof h> {\n return h('div', { className: 'dsc-picker-overlay', onClick: props.onCancel },\n h('div', { className: 'dsc-confirm', onClick: (event: { stopPropagation: () => void }) => event.stopPropagation() },\n h('div', { className: 'dsc-confirm-title' }, props.title),\n h('div', { className: 'dsc-confirm-body' }, props.body),\n props.detail !== undefined && props.detail !== ''\n ? h('div', { className: 'dsc-confirm-detail' }, props.detail)\n : null,\n h('div', { className: 'dsc-confirm-actions' },\n h('button', { className: 'dsc-btn', disabled: props.busy, onClick: props.onCancel }, props.t('cancel')),\n h('button', { className: 'dsc-btn dsc-btn--danger', disabled: props.busy, onClick: props.onConfirm }, props.t('confirmDelete')),\n ),\n ),\n )\n}\n\nfunction AssetThumb(props: { asset: AssetEntry; t: ComfyUIPanelProps['t']; onClick: () => void; onDelete: () => void }): ReturnType<typeof h> {\n const first = props.asset.media[0]\n const [broken, setBroken] = useState(false)\n // Deleting is destructive, so the button stays out of the way until the\n // pointer is on the card, and it never triggers the card's own click.\n const trash = h('button', {\n className: 'dsc-asset-trash',\n title: props.t('assetDelete'),\n 'aria-label': props.t('assetDelete'),\n onClick: (event: { stopPropagation: () => void }) => {\n event.stopPropagation()\n props.onDelete()\n },\n }, '🗑')\n if (first === undefined || broken) {\n return h('div', { className: 'dsc-asset dsc-asset--empty', onClick: props.onClick },\n h('div', null, props.t('assetGone')),\n h('div', { className: 'dsc-meta' }, props.asset.workflowName ?? '—'),\n trash,\n )\n }\n return h('div', { className: 'dsc-asset', onClick: props.onClick },\n first.kind === 'video'\n ? h('video', { src: first.url, controls: true, preload: 'metadata', onClick: (event: { stopPropagation: () => void }) => event.stopPropagation() })\n : first.kind === 'audio'\n // Audio cards show a plain note icon + filename (no player inline —\n // an <img> or <audio> here mislabels live files as evicted or squats\n // in the grid); the actual player opens in the lightbox preview.\n ? h('div', { className: 'dsc-asset-audio-icon' },\n // Dim waveform bars tiled across the green tile (pure decoration;\n // the speaker glyph stays on top).\n h('svg', { className: 'dsc-asset-audio-icon-wave', 'aria-hidden': 'true' },\n h('defs', null,\n // One horizontal waveform: the pattern tile is as tall as the\n // card (110px) so nothing repeats vertically, and the bars are\n // thin (2px) and dense (6px spacing) for a fine waveform look.\n h('pattern', { id: 'dsc-wave-pattern', width: 64, height: 110, patternUnits: 'userSpaceOnUse' },\n h('g', { fill: 'rgba(255,255,255,0.15)' },\n h('rect', { x: 0, y: 50, width: 2, height: 10, rx: 1 }),\n h('rect', { x: 4, y: 44, width: 2, height: 22, rx: 1 }),\n h('rect', { x: 8, y: 48, width: 2, height: 14, rx: 1 }),\n h('rect', { x: 12, y: 38, width: 2, height: 34, rx: 1 }),\n h('rect', { x: 16, y: 46, width: 2, height: 18, rx: 1 }),\n h('rect', { x: 20, y: 52, width: 2, height: 6, rx: 1 }),\n h('rect', { x: 24, y: 40, width: 2, height: 30, rx: 1 }),\n h('rect', { x: 28, y: 48, width: 2, height: 14, rx: 1 }),\n h('rect', { x: 32, y: 42, width: 2, height: 26, rx: 1 }),\n h('rect', { x: 36, y: 36, width: 2, height: 38, rx: 1 }),\n h('rect', { x: 40, y: 47, width: 2, height: 16, rx: 1 }),\n h('rect', { x: 44, y: 51, width: 2, height: 8, rx: 1 }),\n h('rect', { x: 48, y: 40, width: 2, height: 30, rx: 1 }),\n h('rect', { x: 52, y: 45, width: 2, height: 20, rx: 1 }),\n h('rect', { x: 56, y: 38, width: 2, height: 34, rx: 1 }),\n h('rect', { x: 60, y: 49, width: 2, height: 12, rx: 1 })))),\n h('rect', { width: '100%', height: '100%', fill: 'url(#dsc-wave-pattern)' })),\n h('svg', { className: 'dsc-asset-audio-icon-sym', viewBox: '0 0 24 24', 'aria-hidden': 'true', dangerouslySetInnerHTML: { __html: '<path fill=\"currentColor\" d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"/>' } }),\n h('span', { className: 'dsc-asset-audio-icon-name', title: first.filename }, first.filename))\n : h('img', { src: first.url, alt: first.filename, loading: 'lazy', onError: () => setBroken(true) }),\n h('div', { className: 'dsc-asset-meta' }, props.asset.workflowName ?? '—'),\n trash,\n )\n}\n\n/**\n * Tab 3: the task center — active tasks (pending / generating) shown as\n * cards with id, status and progress, plus history filtered by the\n * completed / failed / cancelled chips. Polled every 3 seconds.\n */\nfunction QueueTab({ t, onPreview }: { t: ComfyUIPanelProps['t']; onPreview: (images: string[], kinds: Array<'image' | 'video' | 'audio' | 'other'>, index: number) => void }): ReturnType<typeof h> {\n const [filter, setFilter] = useState<JobFilter>('all')\n const [active, setActive] = useState<JobView[] | null>(null)\n const [history, setHistory] = useState<JobView[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [busy, setBusy] = useState(false)\n\n const load = async (current: JobFilter): Promise<void> => {\n try {\n const historyStatus = current === 'all' ? 'completed,failed,cancelled' : current\n const [activeData, historyData] = await Promise.all([\n getJson<JobsView>('/comfyui/jobs?status=pending,in_progress&limit=100'),\n getJson<JobsView>(`/comfyui/jobs?status=${historyStatus}&limit=100`),\n ])\n if (activeData.ok !== true) throw new Error(activeData.error ?? t('queueError'))\n if (historyData.ok !== true) throw new Error(historyData.error ?? t('queueError'))\n // Active queue: earliest submitted first (running on top, later joins append below).\n setActive([...(activeData.jobs ?? [])].sort((a, b) => (a.createTime ?? 0) - (b.createTime ?? 0)))\n setHistory(historyData.jobs)\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n useEffect(() => {\n void load(filter)\n const timer = setInterval(() => void load(filter), 3_000)\n return () => clearInterval(timer)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [filter])\n\n const act = async (payload: Record<string, unknown>): Promise<void> => {\n setBusy(true)\n try {\n const data = (await postJson('/comfyui/jobs/actions', payload)) as { ok: boolean; error?: string }\n if (data.ok !== true) throw new Error(data.error ?? 'action failed')\n await load(filter)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n if (error !== null) return h('div', null, h(ErrorNote, { t, message: error }))\n if (active === null || history === null) return h('div', { className: 'dsc-meta' }, '…')\n\n // Preview image sequence over the history list, plus each job's position in it.\n const historyPreviewUrls = history.map(previewUrlOf)\n const previewImages = historyPreviewUrls.filter((url): url is string => url !== null)\n const previewPrefix: number[] = []\n {\n let acc = 0\n for (const url of historyPreviewUrls) {\n previewPrefix.push(acc)\n if (url !== null) acc += 1\n }\n }\n\n return h('div', { className: 'dsc-list' },\n h('div', { className: 'dsc-queue-actions' },\n h('button', { className: 'dsc-btn', onClick: () => void act({ action: 'clear' }), disabled: busy }, t('jobClearQueue')),\n h('button', { className: 'dsc-btn', onClick: () => void act({ action: 'clearHistory' }), disabled: busy }, t('jobClearHistory')),\n h('button', { className: 'dsc-btn', onClick: () => void act({ action: 'free', unloadModels: true, freeMemory: true }), disabled: busy }, t('jobFree')),\n ),\n h('div', { className: 'dsc-section' },\n h('div', { className: 'dsc-section-head' },\n h('span', { className: 'dsc-section-title' }, `${t('jobActive')} (${active.length})`),\n ),\n active.length === 0\n ? h('div', { className: 'dsc-meta' }, t('queueEmpty'))\n : h('div', { className: 'dsc-list' }, active.map((job) => h(JobRow, { key: job.id, job, t, busy, act }))),\n ),\n h('div', { className: 'dsc-section' },\n h('div', { className: 'dsc-section-head' },\n h('span', { className: 'dsc-section-title' }, `${t('jobFilterLabel')} (${history.length})`),\n h('div', { className: 'dsc-queue-head' },\n JOB_FILTERS.map((item) =>\n h('button', {\n key: item.key,\n className: `dsc-chip${filter === item.key ? ' dsc-chip--active' : ''}`,\n onClick: () => setFilter(item.key),\n disabled: busy,\n }, t(item.label))),\n ),\n ),\n history.length === 0\n ? h('div', { className: 'dsc-meta' }, t('queueEmpty'))\n : h('div', { className: 'dsc-list' }, history.map((job, index) => h(JobRow, {\n key: job.id,\n job,\n t,\n busy,\n act,\n onPreview: historyPreviewUrls[index] !== null && previewImages.length > 0\n ? () => onPreview(previewImages, previewImages.map(() => 'image' as const), previewPrefix[index]!)\n : undefined,\n }))),\n ),\n )\n}\n\nfunction jobBadge(status: JobStatus): string {\n switch (status) {\n case 'in_progress': return 'dsc-badge--info'\n case 'completed': return 'dsc-badge--ok'\n case 'failed': return 'dsc-badge--danger'\n default: return ''\n }\n}\n\nconst STATUS_LABELS: Record<JobStatus, string> = {\n pending: 'jobFilterPending',\n in_progress: 'jobFilterInProgress',\n completed: 'jobFilterCompleted',\n failed: 'jobFilterFailed',\n cancelled: 'jobFilterCancelled',\n}\n\n/**\n * One task card: a compact row with a status badge, task name + short id,\n * duration (and error/progress for in-flight tasks), and a ⋯ menu with\n * per-state actions. Hover highlights the row. Rendered as a component\n * instance (h(JobRow, ...)) so its hooks stay per-card.\n */\nfunction JobRow(props: {\n job: JobView\n t: ComfyUIPanelProps['t']\n busy: boolean\n act: (payload: Record<string, unknown>) => Promise<void>\n onPreview?: () => void\n}): ReturnType<typeof h> {\n const { job, t, busy, act, onPreview } = props\n const [menuOpen, setMenuOpen] = useState(false)\n const menuRef = useRef<HTMLDivElement | null>(null)\n\n useEffect(() => {\n if (!menuOpen) return\n const onDoc = (event: MouseEvent): void => {\n if (menuRef.current !== null && !menuRef.current.contains(event.target as Node)) setMenuOpen(false)\n }\n document.addEventListener('mousedown', onDoc)\n return () => document.removeEventListener('mousedown', onDoc)\n }, [menuOpen])\n\n const running = job.status === 'in_progress'\n const terminal = job.status === 'completed' || job.status === 'failed' || job.status === 'cancelled'\n const pct = job.progress !== null && job.progress !== undefined && job.progress.max > 0\n ? Math.min(100, Math.round((job.progress.value / job.progress.max) * 100))\n : null\n const duration = job.executionStartTime !== null && job.executionEndTime !== null\n ? Math.max(0, Math.round(((job.executionEndTime ?? 0) - (job.executionStartTime ?? 0)) / 1000))\n : null\n const errMsg = job.executionError?.exception_message ?? job.executionError?.message\n const name = job.workflowName ?? job.workflowId\n const preview = previewUrlOf(job)\n const close = (): void => setMenuOpen(false)\n const statusClass = job.status === 'failed' ? ' dsc-job-item--failed' : job.status === 'cancelled' ? ' dsc-job-item--cancelled' : ''\n\n return h('div', { className: `dsc-job-item${statusClass}` },\n preview !== null\n ? h('img', {\n src: preview,\n alt: '',\n loading: 'lazy',\n className: onPreview !== undefined ? 'dsc-job-preview dsc-job-preview--clickable' : 'dsc-job-preview',\n onClick: onPreview,\n })\n : null,\n h('div', { className: 'dsc-job-main' },\n h('div', { className: 'dsc-job-name', title: name ?? undefined },\n name !== null && name !== undefined && name !== '' ? name : '—',\n ),\n h('div', { className: 'dsc-job-mid' },\n running && job.progress !== null && job.progress !== undefined\n ? h('div', { className: 'dsc-progress' },\n h('div', { className: 'dsc-progress-track' },\n h('div', { className: 'dsc-progress-fill', style: { width: `${pct ?? 0}%` } }),\n ),\n h('span', { className: 'dsc-job-progress' },\n `${job.progress.value}/${job.progress.max} · ${pct ?? 0}%`,\n ),\n )\n : null,\n h('div', { className: 'dsc-job-mid-right' },\n h('span', { className: `dsc-badge dsc-badge--status ${jobBadge(job.status)}` }, t(STATUS_LABELS[job.status] ?? job.status)),\n h('div', { ref: menuRef, className: 'dsc-job-menu' },\n h('button', {\n className: 'dsc-job-menu-btn',\n 'aria-label': t('jobMore'),\n onClick: () => setMenuOpen(!menuOpen),\n }, '⋯'),\n menuOpen ? h('div', { className: 'dsc-job-menu-pop' },\n job.status === 'pending'\n ? h('button', { onClick: () => { void act({ action: 'delete', ids: [job.id] }); close() } }, t('jobDelete'))\n : null,\n running\n ? h('button', { onClick: () => { void act({ action: 'interrupt', promptId: job.id }); close() } }, t('jobInterrupt'))\n : null,\n terminal\n ? h('button', { onClick: () => { void act({ action: 'deleteHistory', ids: [job.id] }); close() } }, t('jobDelete'))\n : null,\n terminal\n ? h('button', { onClick: () => { void act({ action: 'rerun', jobId: job.id }); close() } }, t('jobRerun'))\n : null,\n terminal\n ? h('button', { onClick: () => { panelStore.setAssetFilter(name ?? ''); panelStore.setTab('assets'); close() } }, t('jobViewAssets'))\n : null,\n ) : null,\n ),\n ),\n ),\n h('div', { className: 'dsc-job-bottom' },\n h('span', { className: 'dsc-job-duration' }, `${t('jobDuration')} ${duration ?? 0}s`),\n errMsg !== undefined && errMsg !== null ? h('span', { className: 'dsc-job-error', title: errMsg }, errMsg) : null,\n ),\n ),\n )\n}\n","/**\n * dsh-comfyui stylesheet, injected once with plugin ownership. Colors come\n * from the host theme tokens (--dsw-alias-*), so the UI follows light/dark.\n */\nconst CSS = `\n/* --- shared primitives --- */\n.dsc-card {\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n padding: 10px 12px;\n margin: 4px 0;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsc-card-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }\n.dsc-badge {\n border-radius: 999px; padding: 1px 8px; font-size: 11px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-secondary);\n}\n.dsc-badge--ok { background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 16%, transparent); }\n.dsc-badge--err { background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 16%, transparent); }\n.dsc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; margin-top: 6px; }\n.dsc-media { border-radius: 6px; overflow: hidden; background: var(--dsw-alias-bg-layer-1); }\n.dsc-media img, .dsc-media video, .dsc-media audio { display: block; width: 100%; max-height: 320px; object-fit: contain; background: #000; }\n.dsc-media audio { height: 44px; }\n.dsc-media-img--clickable { cursor: zoom-in; }\n.dsc-media-other { display: block; padding: 8px 6px; font-size: 12px; color: var(--dsw-alias-label-secondary); word-break: break-all; }\n.dsc-media-meta { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 3px 6px; }\n.dsc-media-size { font-size: 11px; color: var(--dsw-alias-label-secondary); white-space: nowrap; }\n.dsc-media-meta a { display: inline; padding: 0; font-size: 11px; color: var(--dsw-alias-label-secondary); text-decoration: none; }\n.dsc-media-meta a:hover { color: var(--dsw-alias-label-primary); }\n.dsc-meta { color: var(--dsw-alias-label-secondary); font-size: 12px; }\n.dsc-err { color: var(--dsw-alias-state-error-primary); font-size: 12px; margin: 4px 0; }\n.dsc-ok { color: var(--dsw-alias-state-success-primary); font-size: 12px; margin: 4px 0; }\n.dsc-form { display: flex; flex-direction: column; gap: 12px; max-width: 460px; }\n.dsc-field label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 4px; color: var(--dsw-alias-label-primary); }\n.dsc-input, .dsc-textarea {\n width: 100%; box-sizing: border-box; padding: 6px 8px; border-radius: 6px;\n border: 1px solid var(--dsw-alias-border-l1);\n background: transparent; color: inherit; font-size: 13px;\n}\nselect.dsc-input { background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); color-scheme: inherit; }\nselect.dsc-input option { background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); }\n.dsc-textarea { min-height: 90px; resize: vertical; font-family: ui-monospace, monospace; }\n.dsc-hint { font-size: 12px; color: var(--dsw-alias-label-secondary); margin-top: 2px; }\n.dsc-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }\n.dsc-btn {\n border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px;\n background: transparent; color: inherit; padding: 5px 12px; font-size: 13px; cursor: pointer;\n}\n.dsc-btn:disabled { opacity: 0.5; cursor: default; }\n.dsc-btn--link { display: inline-block; text-decoration: none; }\n/* --- header action trigger --- */\n.dsc-trigger {\n display: inline-flex; align-items: center; gap: 5px;\n border: 1px solid transparent; background: transparent; color: var(--dsw-alias-label-secondary);\n cursor: pointer; font-size: 13px; padding: 3px 8px; border-radius: 6px;\n white-space: nowrap;\n}\n.dsc-trigger:hover { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-bg-layer-1); border-color: var(--dsw-alias-border-l1); }\n.dsc-trigger[aria-pressed='true'] { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-bg-layer-2); }\n.dsc-trigger-glyph { font-size: 13px; line-height: 1; }\n/* --- panel shell: floating window, percentage-anchored to the page header\n (top) and the composer (bottom), draggable by the header and resizable via\n the corner handle. Follows the host light/dark theme. --- */\n.dsc-panel {\n position: fixed;\n top: var(--dsc-panel-top, 9%);\n right: var(--dsc-panel-right, 1.5%);\n bottom: var(--dsc-panel-bottom, 2%);\n width: var(--dsc-panel-width, 400px);\n max-width: min(92vw, 560px); min-width: 300px;\n z-index: 900;\n display: flex; flex-direction: column;\n background: var(--dsw-alias-bg-layer-1);\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 14px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.28), 0 2px 8px rgba(0, 0, 0, 0.12);\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n user-select: none;\n}\n.dsc-panel--dragging { cursor: grabbing; }\n.dsc-panel-head { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; border-bottom: 1px solid var(--dsw-alias-border-l1); cursor: grab; touch-action: none; }\n.dsc-panel--dragging .dsc-panel-head { cursor: grabbing; }\n.dsc-panel-resize {\n position: absolute; right: 0; bottom: 0; width: 16px; height: 16px;\n cursor: nwse-resize; touch-action: none;\n background: linear-gradient(135deg, transparent 50%, var(--dsw-alias-label-tertiary) 50%);\n border-bottom-right-radius: 14px;\n opacity: 0.55;\n}\n.dsc-panel-resize:hover { opacity: 1; }\n.dsc-panel-title { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; font-size: 14px; }\n.dsc-panel-head-actions { display: inline-flex; align-items: center; gap: 2px; }\n.dsc-panel-reset { border: none; background: transparent; color: var(--dsw-alias-label-tertiary); cursor: pointer; font-size: 13px; padding: 4px 6px; line-height: 1; }\n.dsc-panel-reset:hover { color: var(--dsw-alias-label-primary); }\n.dsc-panel-close { border: none; background: transparent; color: var(--dsw-alias-label-secondary); cursor: pointer; font-size: 14px; padding: 4px 8px; }\n.dsc-panel-close:hover { color: var(--dsw-alias-label-primary); }\n.dsc-tabs { display: flex; border-bottom: 1px solid var(--dsw-alias-border-l1); }\n.dsc-tab {\n flex: 1; padding: 8px 4px; background: transparent; border: none;\n border-bottom: 2px solid transparent; color: var(--dsw-alias-label-secondary);\n cursor: pointer; font-size: 13px;\n}\n.dsc-tab--active { color: var(--dsw-alias-label-primary); border-bottom-color: var(--dsw-alias-brand-primary); }\n.dsc-panel-body { flex: 1; overflow-y: auto; padding: 10px 12px; }\n.dsc-toolbar { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; flex-wrap: wrap; }\n.dsc-list { display: flex; flex-direction: column; gap: 8px; }\n/* --- workflows tab --- */\n.dsc-wf { border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 8px 10px; background: var(--dsw-alias-bg-layer-1); transition: background 0.12s, border-color 0.12s; cursor: pointer; }\n.dsc-wf:hover { background: var(--dsw-alias-bg-layer-2); border-color: var(--dsw-alias-border-l2); }\n.dsc-wf-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }\n.dsc-wf--comfyui { display: flex; align-items: center; gap: 10px; }\n.dsc-wf-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }\n.dsc-wf-name { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsc-wf-desc { color: var(--dsw-alias-label-secondary); font-size: 12px; margin: 2px 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.dsc-wf-updated { color: var(--dsw-alias-label-tertiary); font-size: 11px; margin-top: 4px; }\n.dsc-wf-actions { display: flex; gap: 6px; margin-top: 6px; }\n.dsc-section { margin-top: 14px; }\n.dsc-section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }\n.dsc-section-title { font-weight: 600; font-size: 13px; }\n.dsc-fold { border: 1px solid var(--dsw-alias-border-l1); border-radius: 10px; margin-top: 10px; overflow: hidden; background: var(--dsw-alias-bg-layer-1); }\n.dsc-fold summary { list-style: none; display: flex; align-items: center; gap: 6px; padding: 8px 10px; cursor: pointer; user-select: none; font-weight: 600; font-size: 13px; }\n.dsc-fold summary::-webkit-details-marker { display: none; }\n.dsc-fold summary::before { content: '▸'; font-size: 11px; color: var(--dsw-alias-label-secondary); transition: transform 0.15s; }\n.dsc-fold[open] summary::before { transform: rotate(90deg); }\n.dsc-fold summary:hover { background: var(--dsw-alias-bg-layer-2); }\n.dsc-fold-body { padding: 0 10px 10px; }\n.dsc-hint { color: var(--dsw-alias-label-secondary); font-size: 11px; margin: 2px 0 6px; white-space: pre-line; }\n.dsc-badge { font-size: 11px; padding: 1px 8px; border-radius: 999px; }\n.dsc-badge--ok { color: var(--dsw-alias-state-success-primary); border: 1px solid var(--dsw-alias-state-success-primary); }\n.dsc-badge--warn { color: var(--dsw-alias-state-warn-primary); border: 1px solid var(--dsw-alias-state-warn-primary); }\n.dsc-view-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }\n.dsc-view-label { font-weight: 600; font-size: 12px; margin: 8px 0 4px; }\n.dsc-node-list { margin: 0; padding-left: 18px; font-size: 12px; color: var(--dsw-alias-label-secondary); max-height: 180px; overflow-y: auto; }\n.dsc-node-list li { margin: 2px 0; }\n.dsc-textarea--view { min-height: 220px; resize: vertical; }\n.dsc-derived { margin: 6px 0; display: flex; flex-direction: column; gap: 4px; }\n.dsc-derived-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 12px; }\n.dsc-derived-name { color: var(--dsw-alias-label-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsc-dialog { border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 10px; }\n/* --- skill pack editor: file list beside a plain-text editor --- */\n.dsc-skill { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; margin-top: 8px; }\n.dsc-skill-files { flex: 0 0 190px; min-width: 160px; display: flex; flex-direction: column; gap: 6px; }\n.dsc-skill-main { flex: 1 1 300px; min-width: 260px; display: flex; flex-direction: column; gap: 6px; }\n.dsc-skill-bucket { display: flex; flex-direction: column; gap: 2px; }\n/* Foldable pack directories: each folder renders as a <details> whose header\n stays put while its files collapse, keeping crowded packs scannable. */\n.dsc-skill-fold { border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; margin: 2px 0; }\n.dsc-skill-fold summary { padding: 5px 10px; font-size: 12px; color: var(--dsw-alias-label-secondary); border-radius: 8px; }\n.dsc-skill-fold[open] summary { color: var(--dsw-alias-label-primary); border-bottom: 1px solid var(--dsw-alias-border-l1); border-radius: 8px 8px 0 0; }\n.dsc-skill-fold .dsc-skill-bucket { padding: 4px 6px 6px; }\n.dsc-skill-file {\n display: flex; align-items: center; justify-content: space-between; gap: 6px;\n border: 1px solid transparent; border-radius: 6px; background: transparent;\n color: inherit; font-size: 12px; padding: 4px 6px; cursor: pointer; text-align: left;\n}\n.dsc-skill-file:hover { background: var(--dsw-alias-bg-layer-2); }\n.dsc-skill-file--active { border-color: var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-2); }\n.dsc-skill-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsc-skill-file-size { color: var(--dsw-alias-label-secondary); font-size: 11px; flex: none; }\n.dsc-skill-create { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }\n.dsc-skill-editor-head { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 600; }\n.dsc-skill-path { color: var(--dsw-alias-label-primary); }\n.dsc-textarea--skill { min-height: 260px; font-size: 12px; line-height: 1.5; }\n.dsc-skill-preview { border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 10px; display: flex; flex-direction: column; gap: 6px; align-items: center; }\n.dsc-skill-preview img { max-width: 100%; max-height: 320px; object-fit: contain; border-radius: 6px; }\n.dsc-skill-dir { font-size: 11px; color: var(--dsw-alias-label-secondary); margin: 4px 0; word-break: break-all; }\n.dsc-skill-flags { margin-top: 6px; }\n.dsc-skill-footer { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }\n.dsc-skill-actions { display: flex; gap: 6px; flex-wrap: wrap; }\n.dsc-skill-drop-hint { font-size: 11px; color: var(--dsw-alias-label-secondary); border: 1px dashed var(--dsw-alias-border-l1); border-radius: 6px; padding: 4px 6px; text-align: center; }\n.dsc-dialog--danger { border-color: var(--dsw-alias-state-error-primary); }\n.dsc-danger-text { color: var(--dsw-alias-state-error-primary); font-weight: 600; font-size: 12px; line-height: 1.5; }\n.dsc-check { display: flex; align-items: center; gap: 6px; font-size: 12px; }\n.dsc-dialog-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }\n.dsc-extract-modes { display: flex; flex-direction: column; gap: 8px; margin: 10px 0; }\n.dsc-mode { display: flex; flex-direction: column; gap: 2px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 8px 10px; cursor: pointer; }\n.dsc-mode input { accent-color: var(--dsw-alias-brand-primary); }\n.dsc-mode-label { font-size: 13px; }\n/* --- assets tab --- */\n.dsc-assets-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 8px; }\n.dsc-asset { position: relative; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; overflow: hidden; cursor: pointer; background: var(--dsw-alias-bg-layer-1); }\n/* Destructive, so it only appears while the pointer is on the card. */\n.dsc-asset-trash {\n position: absolute; top: 4px; right: 4px; width: 26px; height: 26px; padding: 0; line-height: 1;\n display: flex; align-items: center; justify-content: center;\n border: 1px solid var(--dsw-alias-state-error-primary); border-radius: 6px;\n background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-state-error-primary);\n font-size: 14px; cursor: pointer; opacity: 0; transition: opacity 0.12s;\n}\n.dsc-asset:hover .dsc-asset-trash, .dsc-asset-trash:focus-visible { opacity: 1; }\n.dsc-asset-trash:hover { background: var(--dsw-alias-state-error-primary); color: #fff; }\n.dsc-asset img, .dsc-asset video { width: 100%; height: 110px; object-fit: cover; display: block; background: #000; }\n.dsc-asset-audio-icon { position: relative; width: 100%; height: 110px; box-sizing: border-box; padding: 0 6px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; background: #26702b; overflow: hidden; }\n.dsc-asset-audio-icon-wave { position: absolute; inset: 0; width: 100%; height: 100%; }\n.dsc-asset-audio-icon-sym { position: relative; width: 42px; height: 42px; color: #fff; }\n.dsc-asset-audio-icon-name { position: relative; max-width: 100%; font-size: 11px; color: rgba(255, 255, 255, 0.9); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.dsc-asset--empty {\n height: 110px; padding: 8px; box-sizing: border-box;\n display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 4px;\n font-size: 11px; color: var(--dsw-alias-label-secondary); text-align: center;\n}\n.dsc-asset-meta { padding: 3px 6px; font-size: 11px; color: var(--dsw-alias-label-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n/* confirmation modal (asset deletion) */\n.dsc-confirm { width: min(360px, 88vw); display: flex; flex-direction: column; gap: 8px; padding: 14px 16px; border-radius: 12px; border: 1px solid var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.32); }\n.dsc-confirm-title { font-weight: 600; font-size: 14px; }\n.dsc-confirm-body { font-size: 13px; line-height: 1.6; color: var(--dsw-alias-label-secondary); }\n.dsc-confirm-detail { font-size: 12px; line-height: 1.5; color: var(--dsw-alias-label-tertiary); word-break: break-all; max-height: 96px; overflow-y: auto; }\n.dsc-confirm-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 4px; }\n.dsc-btn--danger { border-color: var(--dsw-alias-state-error-primary); color: var(--dsw-alias-state-error-primary); }\n.dsc-btn--danger:hover:not(:disabled) { background: var(--dsw-alias-state-error-primary); color: #fff; }\n.dsc-asset-detail-media { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }\n.dsc-asset-detail-media img, .dsc-asset-detail-media video { width: 100%; max-height: 320px; object-fit: contain; background: #000; border-radius: 8px; }\n.dsc-asset-detail-file { display: flex; align-items: center; justify-content: space-between; gap: 8px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 6px 8px; }\n.dsc-input--inline { width: auto; }\n/* --- queue tab --- */\n.dsc-queue-head { display: flex; gap: 8px; flex-wrap: wrap; }\n.dsc-queue-item { display: flex; gap: 8px; align-items: center; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 6px 8px; font-size: 12px; flex-wrap: wrap; }\n.dsc-queue-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px; }\n.dsc-queue-meta { color: var(--dsw-alias-label-secondary); font-size: 11px; }\n.dsc-queue-tracked { margin-top: 10px; display: flex; flex-direction: column; gap: 4px; }\n.dsc-progress { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 90px; }\n.dsc-progress-track { flex: 1; height: 6px; border-radius: 3px; background: var(--dsw-alias-bg-layer-2); overflow: hidden; }\n.dsc-progress-fill { height: 100%; background: #3b82f6; transition: width 0.4s; }\n.dsc-progress:hover .dsc-progress-fill { background: #2563eb; }\n.dsc-param-upload-wrap { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1; }\n.dsc-param-upload-wrap select { flex: 1; min-width: 0; }\n.dsc-dropzone { flex: 1; min-width: 120px; border: 1px dashed var(--dsw-alias-border-l2); border-radius: 6px; padding: 5px 10px; font-size: 11px; color: var(--dsw-alias-label-secondary); text-align: center; cursor: pointer; transition: border-color 0.12s, color 0.12s; }\n.dsc-dropzone:hover, .dsc-dropzone--over { border-color: #3b82f6; color: #3b82f6; }\n.dsc-upload-select { position: relative; flex: 1; min-width: 0; }\n.dsc-upload-select-btn { display: flex; align-items: center; gap: 6px; width: 100%; border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; padding: 3px 8px; background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); cursor: pointer; font-size: 12px; text-align: left; }\n.dsc-upload-select-btn:hover { border-color: var(--dsw-alias-border-l2); }\n.dsc-upload-select-thumb { width: 36px; height: 24px; object-fit: cover; border-radius: 3px; background: var(--dsw-alias-bg-layer-2); flex: none; }\n.dsc-upload-select-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }\n.dsc-upload-select-pop { position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 30; max-height: 220px; overflow-y: auto; border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; background: var(--dsw-alias-bg-layer-2); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35); padding: 4px; }\n.dsc-upload-select-item { display: flex; align-items: center; gap: 8px; padding: 5px 8px; border-radius: 6px; cursor: pointer; font-size: 12px; color: var(--dsw-alias-label-primary); }\n.dsc-upload-select-item:hover { background: var(--dsw-alias-bg-layer-3); }\n.dsc-upload-dock { margin-top: 14px; border-top: 1px solid var(--dsw-alias-border-l1); padding-top: 10px; display: flex; flex-direction: column; gap: 8px; }\n.dsc-upload-dock-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }\n.dsc-upload-dock-title { font-weight: 600; font-size: 12px; color: var(--dsw-alias-label-primary); }\n.dsc-upload-dock-zone { min-height: 44px; display: flex; align-items: center; justify-content: center; }\n.dsc-upload-list { display: flex; flex-direction: column; gap: 4px; }\n.dsc-upload-item { display: flex; align-items: center; gap: 8px; }\n.dsc-upload-thumb { width: 40px; height: 28px; object-fit: cover; border-radius: 4px; background: var(--dsw-alias-bg-layer-2); flex: none; }\n.dsc-upload-thumb--media { display: inline-flex; align-items: center; justify-content: center; font-size: 14px; }\n.dsc-upload-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: var(--dsw-alias-label-primary); }\n.dsc-upload-select-item--active { background: var(--dsw-alias-bg-layer-3); }\n/* --- load area: big preview + picker dialog (ComfyUI LoadImage-like) --- */\n.dsc-loadarea { margin-top: 14px; border-top: 1px solid var(--dsw-alias-border-l1); padding-top: 10px; display: flex; flex-direction: column; gap: 8px; }\n.dsc-loadarea-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }\n.dsc-loadarea-title { font-weight: 600; font-size: 12px; color: var(--dsw-alias-label-primary); }\n/* load-area slots: slot 0 is the primary (big) source, the rest are thumbs.\n Each slot carries its own actions (add / clear media / delete slot). */\n.dsc-loadslots { display: flex; flex-wrap: wrap; gap: 8px; }\n/* One slot stretches across the panel; from two on they share a fixed width\n and wrap into rows. The × sits in the corner and appears on hover. */\n.dsc-loadslot { position: relative; display: flex; flex-direction: column; gap: 4px; width: 128px; border: 1px solid var(--dsw-alias-border-l2); border-radius: 10px; padding: 6px; background: var(--dsw-alias-bg-layer-1); }\n.dsc-loadslot--wide { width: 100%; }\n.dsc-loadslot-pick { display: flex; flex-direction: column; align-items: center; gap: 4px; border: none; border-radius: 8px; padding: 0; background: transparent; color: inherit; cursor: pointer; width: 100%; }\n.dsc-loadslot-media { width: 100%; height: 104px; object-fit: contain; border-radius: 6px; background: var(--dsw-alias-bg-layer-2); }\n.dsc-loadslot--wide .dsc-loadslot-media { height: 220px; }\n.dsc-loadslot-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; width: 100%; height: 104px; border-radius: 6px; border: 1px dashed var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-2); font-size: 12px; }\n.dsc-loadslot--wide .dsc-loadslot-empty { height: 120px; font-size: 13px; }\n.dsc-loadslot-name { width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; color: var(--dsw-alias-label-primary); text-align: center; }\n.dsc-loadslot-index { color: var(--dsw-alias-label-tertiary); }\n.dsc-loadslot-add { color: var(--dsw-alias-label-secondary); }\n.dsc-loadslot-pick:hover .dsc-loadslot-add { color: var(--dsw-alias-brand-primary); }\n.dsc-loadslot-x {\n position: absolute; top: 3px; right: 3px; width: 26px; height: 26px; padding: 0; line-height: 1;\n display: flex; align-items: center; justify-content: center;\n border: 1px solid var(--dsw-alias-border-l2); border-radius: 50%;\n background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-secondary);\n font-size: 18px; cursor: pointer; opacity: 0; transition: opacity 0.12s;\n}\n.dsc-loadslot:hover .dsc-loadslot-x, .dsc-loadslot-x:focus-visible { opacity: 1; }\n.dsc-loadslot-x:hover { color: var(--dsw-alias-state-error-primary); border-color: var(--dsw-alias-state-error-primary); }\n.dsc-picker-player { width: 100%; border-radius: 6px; background: var(--dsw-alias-bg-layer-1); }\nvideo.dsc-picker-player { max-height: 180px; }\n.dsc-picker-player--audio { height: 34px; }\n.dsc-loadslot-x:disabled { opacity: 0; cursor: default; }\n.dsc-picker-card--none .dsc-picker-thumb--media { font-size: 26px; color: var(--dsw-alias-label-tertiary); }\n/* picker overlay: dims the page, dialog floats in the center */\n.dsc-picker-overlay { position: fixed; inset: 0; z-index: 9990; background: rgba(6, 8, 12, 0.6); display: flex; align-items: center; justify-content: center; padding: 24px; }\n.dsc-picker { position: relative; display: flex; flex-direction: column; width: min(860px, 92vw); height: min(560px, 84vh); background: var(--dsw-alias-bg-layer-1); border: 1px solid var(--dsw-alias-border-l2); border-radius: 12px; box-shadow: 0 16px 56px rgba(0, 0, 0, 0.5); overflow: hidden; }\n.dsc-picker-toast { position: absolute; top: 54px; left: 50%; transform: translateX(-50%); z-index: 5; background: var(--dsw-alias-brand-primary); color: var(--dsw-alias-bg-layer-1); padding: 6px 14px; border-radius: 8px; font-size: 12px; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); pointer-events: none; max-width: 80%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsc-picker-bar { display: flex; align-items: center; gap: 4px; padding: 8px 10px; border-bottom: 1px solid var(--dsw-alias-border-l1); flex-wrap: wrap; }\n.dsc-picker-tab { border: 1px solid transparent; border-radius: 6px; padding: 4px 12px; font-size: 12px; cursor: pointer; background: transparent; color: var(--dsw-alias-label-primary); }\n.dsc-picker-tab--active { background: var(--dsw-alias-brand-primary); color: var(--dsw-alias-bg-layer-1); }\n.dsc-picker-tabs { display: flex; gap: 4px; }\n.dsc-picker-type { flex: none; border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; padding: 3px 8px; font-size: 12px; background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); }\n.dsc-picker-upload { margin: 0 auto; flex: none; max-width: 200px; min-height: 32px; display: flex; align-items: center; justify-content: center; padding: 0 12px; font-size: 12px; white-space: nowrap; }\n.dsc-picker-empty { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; color: var(--dsw-alias-label-tertiary); font-size: 13px; }\n.dsc-picker-grid { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 12px; display: flex; gap: 10px; align-items: flex-start; }\n.dsc-picker-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }\n.dsc-picker-card { display: flex; flex-direction: column; gap: 4px; min-width: 0; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 6px; background: var(--dsw-alias-bg-layer-2); cursor: pointer; text-align: left; }\n.dsc-picker-card:hover { border-color: #3b82f6; }\n.dsc-picker-card--active { border-color: var(--dsw-alias-brand-primary); box-shadow: 0 0 0 1px var(--dsw-alias-brand-primary); }\n.dsc-picker-thumb { width: 100%; height: auto; object-fit: contain; border-radius: 6px; background: var(--dsw-alias-bg-layer-1); }\n.dsc-picker-thumb--media { display: flex; align-items: center; justify-content: center; height: 100px; font-size: 22px; }\n.dsc-picker-name { font-size: 13px; line-height: 1.5; padding: 2px 0; color: var(--dsw-alias-label-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsc-picker-card:hover .dsc-picker-name { color: var(--dsw-alias-brand-primary); }\n/* --- workflow tags: filter bar, chips, editor --- */\n.dsc-tag-filter { display: flex; justify-content: flex-end; padding: 6px 0 2px; }\n.dsc-tag-chip { border: 1px solid var(--dsw-alias-border-l1); border-radius: 999px; padding: 2px 10px; font-size: 12px; cursor: pointer; background: transparent; color: var(--dsw-alias-label-primary); }\n.dsc-tag-chip--active { background: var(--dsw-alias-brand-primary); border-color: var(--dsw-alias-brand-primary); color: var(--dsw-alias-bg-layer-1); }\n.dsc-tag-chip--mini { font-size: 11px; padding: 1px 8px; cursor: default; border: 1px solid var(--dsw-alias-brand-primary); color: var(--dsw-alias-brand-primary); background: color-mix(in srgb, var(--dsw-alias-brand-primary) 10%, transparent); }\n.dsc-wf-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }\n.dsc-wf-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; min-width: 0; }\n.dsc-wf-top .dsc-wf-tags { margin-top: 0; flex: none; justify-content: flex-end; }\n.dsc-tag-editor { display: flex; flex-direction: column; gap: 6px; }\n.dsc-tag-row { display: flex; flex-wrap: wrap; gap: 6px; }\n.dsc-tag-input { max-width: 260px; }\n.dsc-chip { border: 1px solid var(--dsw-alias-border-l1); border-radius: 999px; padding: 2px 10px; font-size: 12px; cursor: pointer; background: transparent; color: var(--dsw-alias-label-primary); }\n.dsc-chip--active { background: var(--dsw-alias-brand-primary); border-color: var(--dsw-alias-brand-primary); color: var(--dsw-alias-bg-layer-1); }\n.dsc-badge--info { background: var(--dsw-alias-brand-primary); color: var(--dsw-alias-bg-layer-1); }\n.dsc-badge--danger { background: var(--dsw-alias-state-error-primary); color: #fff; }\n.dsc-queue-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }\n.dsc-btn { border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; padding: 2px 8px; font-size: 12px; cursor: pointer; background: transparent; color: var(--dsw-alias-label-primary); }\n.dsc-btn--sm { padding: 1px 6px; font-size: 11px; }\n.dsc-input--sm { padding: 3px 6px; font-size: 12px; }\n.dsc-btn:disabled { opacity: 0.5; cursor: default; }\n.dsc-job-item { display: flex; align-items: center; gap: 10px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 7px 10px; background: var(--dsw-alias-bg-layer-1); transition: background 0.12s, border-color 0.12s; }\n.dsc-job-item:hover { background: var(--dsw-alias-bg-layer-2); border-color: var(--dsw-alias-border-l2); }\n.dsc-job-item--failed { border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary) 55%, transparent); }\n.dsc-job-item--cancelled { border-color: var(--dsw-alias-border-l2); opacity: 0.85; }\n.dsc-badge--status { flex: none; font-weight: 600; }\n.dsc-job-preview { width: 56px; height: 56px; flex: none; border-radius: 6px; object-fit: cover; border: 1px solid var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-2); }\n.dsc-job-preview--clickable { cursor: zoom-in; }\n/* --- lightbox: floating local panel, no full-screen dim --- */\n.dsc-lightbox { position: fixed; inset: 0; z-index: 9999; background: transparent; display: flex; align-items: center; justify-content: center; }\n.dsc-lightbox-body { position: relative; display: flex; flex-direction: column; align-items: center; gap: 10px; width: 90vw; padding: 12px 12px 10px; background: rgba(12, 14, 18, 0.88); border: 1px solid var(--dsw-alias-border-l2); border-radius: 14px; box-shadow: 0 12px 48px rgba(0, 0, 0, 0.45); }\n.dsc-lightbox-img { width: 100%; height: 80vh; object-fit: contain; border-radius: 8px; }\n.dsc-lightbox-media { max-width: 100%; max-height: 80vh; border-radius: 8px; }\n.dsc-lightbox-meta { display: flex; align-items: center; gap: 14px; color: rgba(255, 255, 255, 0.75); font-size: 12px; }\n.dsc-lightbox-download { border: 1px solid rgba(255, 255, 255, 0.35); border-radius: 999px; padding: 5px 16px; color: #fff; font-size: 12px; text-decoration: none; display: inline-block; }\n.dsc-lightbox-download:hover { background: rgba(255, 255, 255, 0.12); }\n.dsc-lightbox-close { position: absolute; top: clamp(4px, 0.6vw, 14px); right: clamp(4px, 0.6vw, 14px); z-index: 3; width: clamp(28px, 2.2vw, 48px); height: clamp(28px, 2.2vw, 48px); border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.35); background: transparent; color: #fff; font-size: clamp(13px, 1.1vw, 22px); line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; }\n.dsc-lightbox-close:hover { background: rgba(255, 255, 255, 0.12); }\n.dsc-lightbox-nav { position: absolute; top: 0; bottom: 0; z-index: 2; width: clamp(64px, 7vw, 128px); display: flex; align-items: center; background: transparent; border: none; color: #fff; font-size: clamp(38px, 3.4vw, 84px); line-height: 1; cursor: pointer; opacity: 0.6; padding: 0; }\n.dsc-lightbox-nav:hover { opacity: 1; color: var(--dsw-alias-brand-primary); background: rgba(255, 255, 255, 0.06); }\n.dsc-lightbox-nav--prev { left: 0; justify-content: flex-start; padding-left: clamp(14px, 1.8vw, 36px); }\n.dsc-lightbox-nav--next { right: 0; justify-content: flex-end; padding-right: clamp(14px, 1.8vw, 36px); }\n.dsc-job-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }\n.dsc-job-name { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dsw-alias-label-primary); }\n.dsc-job-mid { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }\n.dsc-job-mid-right { display: flex; align-items: center; gap: 6px; flex: none; margin-left: auto; }\n.dsc-job-bottom { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--dsw-alias-label-secondary); min-width: 0; }\n.dsc-job-duration { flex: none; }\n.dsc-job-progress { color: #3b82f6; font-variant-numeric: tabular-nums; }\n.dsc-job-menu { position: relative; flex: none; }\n.dsc-job-menu-btn { border: none; background: transparent; color: var(--dsw-alias-label-secondary); font-size: 15px; line-height: 1; padding: 3px 7px; border-radius: 6px; cursor: pointer; }\n.dsc-job-menu-btn:hover { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-bg-layer-2); }\n.dsc-job-menu-pop { position: absolute; right: 0; top: calc(100% + 4px); z-index: 950; min-width: 128px; padding: 4px; display: flex; flex-direction: column; gap: 2px; background: var(--dsw-alias-bg-layer-2); border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25); }\n.dsc-job-menu-pop button { border: none; background: transparent; color: var(--dsw-alias-label-primary); text-align: left; font-size: 13px; padding: 6px 10px; border-radius: 6px; cursor: pointer; }\n.dsc-job-menu-pop button:hover { background: var(--dsw-alias-bg-layer-3); }\n.dsc-job-error { color: var(--dsw-alias-state-error-primary); font-size: 11px; margin-left: auto; flex: 1; min-width: 0; text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n/* --- parameter editor --- */\n.dsc-params { display: flex; flex-direction: column; gap: 8px; }\n.dsc-param-row { display: flex; flex-direction: column; gap: 6px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 6px 8px; }\n.dsc-param-fields { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }\n.dsc-param-default { min-width: 0; }\n.dsc-param-meta { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }\n.dsc-param-random { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--dsw-alias-label-secondary); cursor: pointer; }\n.dsc-param-bool { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--dsw-alias-label-primary); cursor: pointer; }\n.dsc-param-advanced { display: flex; flex-direction: column; gap: 8px; border: 1px dashed var(--dsw-alias-border-l2); border-radius: 8px; padding: 8px; }\n`\n\n/** Inject the stylesheet once (idempotent), owned by this plugin for HMR. */\nexport function injectStyles(): void {\n if (typeof document === 'undefined') return\n if (document.getElementById('dsh-comfyui-styles') !== null) return\n const style = document.createElement('style')\n style.id = 'dsh-comfyui-styles'\n style.setAttribute('data-plugin', 'dsh-comfyui')\n style.textContent = CSS\n document.head.append(style)\n}\n","/**\n * dsh-comfyui client half: registers the comfyui_run tool card and the\n * ComfyUI settings page. Registered through slots.inject so contributions\n * wait on the real slot declarations and unwind with this plugin's fiber.\n */\nimport { createElement as h } from 'react'\nimport { makeT, getLang } from './i18n.ts'\nimport { ComfyUICard, type ComfyUICardProps } from './card.tsx'\nimport { ComfyUISettings, type ComfyUISettingsProps } from './settings.tsx'\nimport { ComfyUIPanel, type ComfyUIPanelProps } from './panel.tsx'\nimport { ComfyUITrigger, type ComfyUITriggerProps } from './trigger.tsx'\nimport { injectStyles } from './styles.ts'\n\nexport const name = 'dsh-comfyui'\nexport const inject = ['slots']\n\ninterface SlotsService {\n inject(slot: string, register: () => unknown): void\n register(meta: Record<string, unknown>, component: unknown): unknown\n}\n\ninterface ComfyUIClientContext {\n effect(callback: () => unknown, label?: string): void\n slots: SlotsService\n}\n\nexport function apply(ctx: ComfyUIClientContext): void {\n // Plugin-local i18n: language comes from localStorage (settings page), not\n // the host locale, so zh/en switching works without a host change.\n const t = makeT(getLang())\n ctx.effect(() => injectStyles(), 'dsh-comfyui: styles')\n\n ctx.slots.inject('tool.call.toolview', () => ctx.slots.register(\n { name: 'tool.call.toolview', key: 'comfyui_run' },\n (props: unknown) => h(ComfyUICard, { t, ...((props ?? {}) as Record<string, unknown>) } as unknown as ComfyUICardProps),\n ))\n\n ctx.slots.inject('tool.call.toolview', () => ctx.slots.register(\n { name: 'tool.call.toolview', key: 'comfyui_workflow' },\n (props: unknown) => h(ComfyUICard, { t, ...((props ?? {}) as Record<string, unknown>) } as unknown as ComfyUICardProps),\n ))\n\n ctx.slots.inject('settings.section', () => ctx.slots.register(\n { name: 'settings.section', id: 'comfyui', order: 30, label: () => t('settingsTitle') },\n (props: unknown) => h(ComfyUISettings, { t, ...((props ?? {}) as Record<string, unknown>) } as unknown as ComfyUISettingsProps),\n ))\n\n ctx.slots.inject('shell.overlay', () => ctx.slots.register(\n { name: 'shell.overlay', id: 'comfyui.panel', order: 20, label: () => t('panelTitle') },\n (props: unknown) => h(ComfyUIPanel, { t, ...((props ?? {}) as Record<string, unknown>) } as unknown as ComfyUIPanelProps),\n ))\n\n ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register(\n { name: 'conversation.session.header.actions', id: 'comfyui', order: 100, label: () => t('panelTitle') },\n (props: unknown) => h(ComfyUITrigger, { t, ...((props ?? {}) as Record<string, unknown>) } as unknown as ComfyUITriggerProps),\n ))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["h","useState","h","useState","h","listeners","emit","useSyncExternalStore","useSyncExternalStore","h","h","Fragment","useState","useRef","h","useCallback","h"],"sources":["../src/client/i18n.ts","../src/client/lightbox.tsx","../src/client/card.tsx","../src/client/api.ts","../src/client/settings.tsx","../src/client/panel-store.ts","../src/client/connection.tsx","../src/client/trigger.tsx","../src/client/panel.tsx","../src/client/styles.ts","../src/client/index.ts"],"sourcesContent":["/** zh/en dictionaries for dsh-comfyui UI (settings page, tool card, panel). */\nexport const zh = {\n // settings page\n settingsTitle: 'ComfyUI',\n settingsDesc: '连接你的 ComfyUI 服务器,让 Agent 直接生成与处理图像、视频。',\n baseUrl: '服务器地址',\n baseUrlHint: 'ComfyUI 的 HTTP 地址(默认 http://127.0.0.1:8188)。',\n apiKeyEnv: 'API Key 环境变量名',\n apiKeyEnvHint: '密钥名:环境变量或凭据存储(默认 COMFYUI_API_KEY)。',\n hasApiKey: '已配置 API Key',\n noApiKey: '未配置 API Key(本地服务通常不需要)',\n save: '保存',\n saved: '已保存',\n saveFailed: '保存失败',\n test: '测试连接',\n testing: '正在测试…',\n testOk: '连接成功 · ComfyUI {version} · {ms} ms',\n testFail: '连接失败:{message}',\n configNotWritable: '设置服务不可用,请通过 cordis.yml 修改配置。',\n mediaHost: '媒体访问地址',\n mediaHostHint: '媒体在聊天中显示的完整地址(如 http://192.168.1.5:3080)。留空自动检测;图片不显示时填你访问本页的地址。',\n comfyuiDirs: 'ComfyUI 目录',\n comfyuiDirsHint: '本机 ComfyUI 安装目录(可多个,支持映射/多实例/便携版)。Agent 据此定位 models、工作流、音色库等文件。',\n comfyuiDirAdd: '+ 添加目录',\n comfyuiDirRemove: '移除该目录',\n comfyuiDirPlaceholder: '如 D:\\\\ComfyUI',\n skillsDir: '技能包目录',\n skillsDirHint: '工作流技能包(SKILL.md 与参考文档)目录。留空 = 数据目录下 skills/;填绝对路径可放到别的盘或同步盘。改后需手动搬移已有目录。当前实际使用:{current}',\n language: '界面语言',\n languageHint: '界面语言,切换后页面自动刷新。',\n // tool card\n cardGenerating: 'ComfyUI 生成中…',\n cardBackground: '后台任务',\n cardBackgroundDone: '已完成',\n cardPrompt: '任务 ID',\n cardElapsed: '耗时',\n cardMedia: '结果',\n cardEmpty: '无媒体输出',\n cardFailed: '执行失败',\n cardInterrupted: '已中断',\n cardCollect: '使用 job_output 收集后台任务结果',\n cardLoadFailed: '加载失败,点下方下载',\n cardDownload: '下载',\n cardWorkflow: '工作流',\n cardMode: '模式',\n cardListed: '已列出 {runs} 个运行工作流,{graphs} 个图工作流',\n // panel shell\n panelTitle: 'ComfyUI 面板',\n panelReset: '复位位置与大小',\n close: '关闭',\n lbPrev: '上一张',\n lbNext: '下一张',\n tabWorkflows: '工作流',\n tabAssets: '资产',\n tabQueue: '队列',\n error: '出错',\n refresh: '刷新',\n ours: '本插件',\n // connection probe toast (header trigger)\n connChecking: '正在检测 ComfyUI 连接…',\n connOk: '连接正常 · ComfyUI {version} · {ms} ms',\n connFailTitle: '无法连接 ComfyUI',\n connFailBody: '后端未能连上 ComfyUI({message})。请先启动本机 ComfyUI,确保后端能检测到其端口;若使用远程服务器,请到设置页检查服务器地址并点「测试连接」。',\n // workflows tab\n wfAdd: '新建工作流',\n wfName: '名称',\n wfDesc: '概述',\n wfDescPlaceholder: '告诉 Agent 这个工作流做什么',\n wfNameCopyHint: '点击复制工作流名称',\n wfNameCopied: '已复制工作流名称',\n wfParams: '可调参数',\n wfTags: '标签',\n wfTagAll: '全部',\n wfTagAdd: '自定义标签,回车添加',\n wfTagRemove: '点击移除标签',\n wfParamsEmpty: '未定义参数。点击\"识别参数\"自动提取提示词/分辨率/步数/种子,或\"高级参数\"手动指定任意节点输入。',\n wfParamsDrop: '拖拽/点击/粘贴上传',\n wfPasteHint: '悬停此处后按 Ctrl+V 粘贴剪贴板里的图片/文件',\n wfUploadSection: '加载区',\n wfUploadHint: '点击大图选择图像,或粘贴/上传新图像;选中后图生图默认使用该图像',\n wfUploadZone: '拖拽 / 点击 / 粘贴上传到 ComfyUI input 目录',\n wfUploaded: '已上传',\n wfCopyName: '复制文件名',\n wfLoadArea: '加载区',\n wfLoadHint: '点击放入素材(加载区的素材按顺序填入工作流未指定的加载参数)',\n wfLoadEmpty: '加载区为空,点击下方“添加加载区”放入素材',\n wfLoadPicked: '已加载',\n wfLoadAddSlot: '+ 添加加载区',\n wfLoadAddMedia: '添加素材',\n wfLoadRemoveSlot: '删除加载区',\n wfLoadNone: '空',\n wfLoadNoneHint: '清空该加载位(保留加载位,不放素材)',\n wfLoadSlotLabel: '加载位',\n wfLoadSummary: '加载位 {slots} 个 · 已放入 {loaded} 个素材,未指定的加载参数按顺序取用',\n wfTabAll: '全部',\n wfTabImported: '已导入',\n wfTabGenerated: '已生成',\n wfTypeAll: '全部类型',\n wfUploadedToast: '文件已上传',\n wfPickerUpload: '粘贴 / 点击上传',\n wfLoadNoFiles: '没有可用的图像',\n wfParamsUploading: '上传中…',\n uploadKind_image: '图片',\n uploadKind_video: '视频',\n uploadKind_audio: '音频',\n wfMediaClear: '清空',\n wfMediaEmpty: '文件名(留空=移除该参考位)',\n wfRefSlot: '参考',\n wfParamsRecognize: '识别参数',\n wfParamsRecognizing: '识别中…',\n wfParamsRecognizeFailed: '识别失败:无法连接 ComfyUI 或工作流无效',\n wfParamsAdd: '高级参数',\n wfParamAdd: '添加',\n wfParamLabel: '名称',\n wfParamCustomLabel: '自定义名称',\n wfParamCustomHint: '仅用于展示与 Agent 描述,传参键由系统自动生成;留空使用默认',\n wfParamDefault: '默认值',\n wfParamRandom: '随机',\n wfParamDelete: '删除',\n wfParamNode: '节点',\n wfParamInput: '输入',\n wfJson: '工作流 JSON(ComfyUI UI 导出的 API 格式)',\n wfSave: '保存',\n wfSaveRun: '保存并运行',\n wfCancel: '取消',\n wfEdit: '编辑',\n wfRun: '运行',\n wfDelete: '删除',\n wfQueued: '已入队:',\n wfJsonError: '工作流 JSON 解析失败',\n wfUpdated: '更新于',\n wfEmpty: '没有检测到任何工作流,请通过新建、导入或提取来创建执行流程。',\n wfLibrarySection: 'API 工作流',\n wfRefresh: '刷新',\n wfImportFile: '导入 JSON',\n // workflow preset transfer (export / import)\n exportPresets: '导出预设',\n importPresets: '导入预设',\n transferExportTitle: '导出工作流预设',\n transferImportTitle: '导入工作流预设',\n transferExportHint: '共 {total} 个可导出工作流,已选 {selected} 个。运行参数与技能包会一并导出。',\n transferSelectAll: '全选',\n transferSelectNone: '全不选',\n transferExportRun: '导出 ({n})',\n transferImportRun: '导入 ({n})',\n transferExporting: '正在导出…',\n transferImporting: '正在导入…',\n transferExportDone: '已导出 {n} 个工作流:{names}(浏览器正在下载预设包)',\n transferExportFile: '文件 {file}({size} KB)',\n transferExportWarnings: '导出警告:{warnings}',\n transferSelectedList: '将导出:{names}',\n transferExportEmpty: '没有可导出的工作流',\n transferPickFile: '点击选择或拖入 .zip 预设包',\n transferPickHint: '导入会创建为新工作流,不会覆盖库中已有的工作流',\n transferPackageInfo: '包内共 {n} 个工作流 · 导出于 {date}',\n transferParamBadge: '参数 {n}',\n transferSkillBadge: '技能包 · {n} 个文件',\n transferSkillRequired: '技能包 · {n} 个文件 · 必读',\n transferImportDone: '已导入 {n} 个工作流',\n transferImportedItem: '✓ {src} → {dst}',\n transferImportFailedItem: '✗ {src}:{reason}',\n transferImportNote: '重名工作流自动追加(导入)后缀',\n transferFinish: '完成',\n wfComfyuiSection: 'ComfyUI 工作流',\n wfComfyuiHint: '面板自动检测 ComfyUI 中保存的工作流。\\n注:非 API 流程,无法直接执行,需经过提取转化为 API 工作流,或自行导入 API 工作流即可执行。',\n wfComfyuiEmpty: 'ComfyUI 端没有检测到保存的工作流',\n wfExtracted: '已提取',\n wfNotExtracted: '未提取',\n wfView: '查看',\n wfExtract: '提取',\n wfExtractedNotice: '已提取并加入插件库',\n wfExtractTitle: '提取执行流',\n wfExtractModeAll: '整体提取',\n wfExtractModeAllHint: '所有分量合成一个执行流(运行时全部执行)',\n wfExtractModeSplit: '按分量提取',\n wfExtractModeSplitHint: '每个独立流程一个执行流(推荐)',\n wfExtractModeMain: '只提取主流程',\n wfExtractModeMainHint: '只提取最大分量(通常是当前测试区块)',\n wfExtractRun: '提取',\n wfExtractEmpty: '图里没有可提取的分量',\n wfComponents: '分量',\n wfComponentLabel: '分量',\n wfNodes: '节点',\n wfBypassed: '已绕过节点',\n wfIsolated: '悬空节点',\n wfViewBack: '返回',\n wfViewNodes: '节点清单',\n wfViewJson: 'JSON 预览',\n wfViewEmpty: '图中没有可执行的节点',\n // assets tab\n assetAll: '全部工作流',\n assetBack: '返回',\n assetEmpty: '还没有生成记录。运行工作流后,结果会出现在这里。',\n assetGone: '源文件已被 ComfyUI 清理',\n assetDelete: '删除资产',\n assetDeleteTitle: '删除该资产?',\n assetDeleteBody: '将从资产库移除这条记录,并删除 ComfyUI 输出目录里的 {count} 个文件。此操作不可恢复。',\n assetDeleteNoDir: '未能定位 ComfyUI 输出目录,只会移除资产记录,磁盘文件保留(可在 cordis.yml 的 outputDir 里指定输出目录)。',\n assetDeleteDone: '已删除记录,磁盘文件删除 {deleted} 个',\n assetDeleteFailed: '删除失败:{message}',\n confirmDelete: '确定删除',\n cancel: '取消',\n // skill pack (per-workflow SKILL.md bundle)\n skillButton: '技能包',\n skillBadge: '技能包',\n skillBadgeRequired: '技能包·必读',\n skillBadgeHint: '该工作流挂了技能包:Agent 运行前会读它。',\n skillTitle: '技能包',\n skillIntro: '点击「启用技能包」后,可为这个工作流添加给 Agent 看的额外 skills 说明:什么时候用、参数怎么填、有哪些坑。',\n skillEnable: '启用技能包',\n skillDetach: '停用(保留文件)',\n skillDestroy: '销毁技能包',\n skillDestroyConfirm: '⚠ 永久删除整个技能包({count} 个文件),不可恢复',\n skillDestroyConfirmButton: '确认销毁',\n skillDropHint: '可把文件拖到这里导入',\n skillRequired: '运行前必读',\n skillDir: '目录',\n skillSummary: '摘要',\n skillSummaryPlaceholder: '一句话说明这个工作流适合做什么',\n skillSummaryHint: 'Agent 靠它决定要不要读正文,等同 skills 里的 description 字段。',\n skillSave: '保存',\n skillSaved: '已保存',\n skillDirty: '未保存',\n skillDirtyPrompt: '当前文件有未保存的修改。',\n skillSaveAndSwitch: '保存并切换',\n skillDiscard: '丢弃修改',\n skillImport: '↑ 导入文件',\n skillImportHint: '导入本地文件到技能包:md/txt/json/yaml 进 references,脚本进 scripts,图片/csv 进 assets(也可直接拖进左栏)。',\n skillImported: '已导入',\n skillImageHint: '图片只能预览,不能在此编辑;Agent 会在正文点名它时才去读取。',\n skillNewFile: '+ 新建文件',\n skillNewDir: '+ 新建目录',\n skillReveal: '📂 打开目录',\n skillRevealHint: '在文件管理器中打开这个技能包的文件夹,方便直接拷贝文件进去。打开的是运行 DSH 那台机器上的目录;若你正从另一台机器访问本页面,请按下方显示的路径自行前往。',\n skillRevealed: '已打开',\n skillRefresh: '刷新',\n skillRefreshHint: '重新读取技能包目录,显示 Agent 写入或文件管理器里新增/替换的文件。',\n skillRefreshed: '已刷新',\n skillNewDirPlaceholder: '目录名,如 templates',\n skillNewDirHint: '技能包可以有任意一层子目录。常用:{presets};也可以自己起名(字母/数字/汉字/下划线/连字符)。',\n skillDirCreated: '已创建目录',\n skillNewPlaceholder: '文件名(默认 .md)',\n skillCreate: '创建',\n skillRename: '重命名',\n skillDeleteFile: '删除文件',\n skillDeleteConfirm: '删除文件',\n skillReadFailed: '读取失败',\n skillFailed: '操作失败',\n skillDeleteWithWorkflow: '该工作流有技能包,要一起删除吗?',\n skillDeleteBoth: '一起删除',\n skillKeepPack: '只删工作流',\n // queue tab (task center)\n queueEmpty: '当前没有任务',\n queueError: '无法读取队列(ComfyUI 未运行?)',\n jobFilterLabel: '历史',\n jobFilterAll: '全部',\n jobFilterPending: '待生成',\n jobFilterInProgress: '生成中',\n jobFilterCompleted: '已完成',\n jobFilterFailed: '失败',\n jobFilterCancelled: '已取消',\n jobActive: '进行中',\n jobDelete: '删除',\n jobInterrupt: '中断',\n jobRerun: '重跑',\n jobViewAssets: '查看资产',\n jobMore: '更多操作',\n jobClearQueue: '清空队列',\n jobClearHistory: '清空历史',\n jobFree: '释放内存',\n jobDuration: '耗时',\n jobOurs: '本插件',\n}\n\nexport const en = {\n // settings page\n settingsTitle: 'ComfyUI',\n settingsDesc: 'Connect your ComfyUI server so the agent can generate and process images and videos directly.',\n baseUrl: 'Server URL',\n baseUrlHint: 'ComfyUI HTTP address (default http://127.0.0.1:8188).',\n apiKeyEnv: 'API key env var',\n apiKeyEnvHint: 'Name of the key: env var or credential store (default COMFYUI_API_KEY).',\n hasApiKey: 'API key configured',\n noApiKey: 'No API key configured (usually not needed for local servers)',\n save: 'Save',\n saved: 'Saved',\n saveFailed: 'Save failed',\n test: 'Test connection',\n testing: 'Testing…',\n testOk: 'Connected · ComfyUI {version} · {ms} ms',\n testFail: 'Connection failed: {message}',\n configNotWritable: 'Settings service unavailable — edit cordis.yml instead.',\n mediaHost: 'Media base URL',\n mediaHostHint: 'Base URL for media shown in chat (e.g. http://192.168.1.5:3080). Auto-detected when empty; set it if images do not load over LAN or a reverse proxy.',\n comfyuiDirs: 'ComfyUI directories',\n comfyuiDirsHint: 'ComfyUI install roots on this machine (multiple allowed: mapped/multiple/portable installs). The agent uses them to locate models, workflows and voice libraries.',\n comfyuiDirAdd: '+ Add directory',\n comfyuiDirRemove: 'Remove this directory',\n comfyuiDirPlaceholder: 'e.g. D:\\\\ComfyUI',\n skillsDir: 'Skill pack directory',\n skillsDirHint: 'Directory for workflow skill packs (SKILL.md + reference files). Empty = skills/ under the plugin data dir; an absolute path may target another drive or a synced folder. Existing packs are not moved automatically. Currently in use: {current}',\n language: 'Language',\n languageHint: 'UI language; the page reloads after switching.',\n // tool card\n cardGenerating: 'ComfyUI generating…',\n cardBackground: 'Background job',\n cardBackgroundDone: 'Completed',\n cardPrompt: 'Prompt ID',\n cardElapsed: 'Elapsed',\n cardMedia: 'Results',\n cardEmpty: 'No media outputs',\n cardFailed: 'Execution failed',\n cardInterrupted: 'Interrupted',\n cardCollect: 'Collect the background job result with job_output',\n cardLoadFailed: 'failed to load, use the download link below',\n cardDownload: 'Download',\n cardWorkflow: 'Workflow',\n cardMode: 'Mode',\n cardListed: 'Listed {runs} runnable workflows, {graphs} graph workflows',\n // panel shell\n panelTitle: 'ComfyUI Panel',\n panelReset: 'Reset position & size',\n close: 'Close',\n lbPrev: 'Previous image',\n lbNext: 'Next image',\n tabWorkflows: 'Workflows',\n tabAssets: 'Assets',\n tabQueue: 'Queue',\n error: 'Error',\n refresh: 'Refresh',\n ours: 'ours',\n // connection probe toast (header trigger)\n connChecking: 'Checking the ComfyUI connection…',\n connOk: 'Connected · ComfyUI {version} · {ms} ms',\n connFailTitle: 'Cannot reach ComfyUI',\n connFailBody: 'The backend could not reach ComfyUI ({message}). Start the local ComfyUI and make sure the backend can see its port; for a remote server, check the URL in settings and run \"Test connection\".',\n // workflows tab\n wfAdd: 'New workflow',\n wfName: 'Name',\n wfDesc: 'Overview',\n wfDescPlaceholder: 'Tells the agent what this workflow does',\n wfNameCopyHint: 'Click to copy the workflow name',\n wfNameCopied: 'Workflow name copied',\n wfParams: 'Parameters',\n wfTags: 'Tags',\n wfTagAll: 'All',\n wfTagAdd: 'Custom tag, press Enter to add',\n wfTagRemove: 'Click to remove tag',\n wfParamsEmpty: 'No parameters yet. Click \"Detect\" to auto-extract prompt / resolution / steps / seed, or \"Advanced\" to expose any node input manually.',\n wfParamsDrop: 'Drop / Click / Paste to upload',\n wfPasteHint: 'Hover here and press Ctrl+V to paste an image/file',\n wfUploadSection: 'Load area',\n wfUploadHint: 'Click the preview to pick an image, or paste/upload a new one; the selection becomes the default source for image-to-image',\n wfUploadZone: 'Drag / Click / Paste to upload into the ComfyUI input dir',\n wfUploaded: 'Uploaded',\n wfCopyName: 'Copy file name',\n wfLoadArea: 'Load area',\n wfLoadHint: 'Click to put media in this slot (slots fill the workflow unset loader parameters in order)',\n wfLoadEmpty: 'Load area is empty — use \"Add slot\" below to put media in it',\n wfLoadPicked: 'Loaded',\n wfLoadAddSlot: '+ Add slot',\n wfLoadAddMedia: 'Add media',\n wfLoadRemoveSlot: 'Delete slot',\n wfLoadNone: 'None',\n wfLoadNoneHint: 'Empty this slot (the slot stays, with no media)',\n wfLoadSlotLabel: 'Slot',\n wfLoadSummary: '{slots} slot(s) · {loaded} loaded; unset loader parameters take them in order',\n wfTabAll: 'All',\n wfTabImported: 'Imported',\n wfTabGenerated: 'Generated',\n wfTypeAll: 'All types',\n wfUploadedToast: 'File uploaded',\n wfPickerUpload: 'Paste / Click to upload',\n wfLoadNoFiles: 'No images available',\n wfParamsUploading: 'Uploading…',\n uploadKind_image: 'image',\n uploadKind_video: 'video',\n uploadKind_audio: 'audio',\n wfMediaClear: 'Clear',\n wfMediaEmpty: 'filename (empty = drop this slot)',\n wfRefSlot: 'Ref ',\n wfParamsRecognize: 'Detect',\n wfParamsRecognizing: 'Detecting…',\n wfParamsRecognizeFailed: 'Detection failed: ComfyUI unreachable or invalid workflow',\n wfParamsAdd: 'Advanced',\n wfParamAdd: 'Add',\n wfParamLabel: 'Name',\n wfParamCustomLabel: 'Custom name',\n wfParamCustomHint: 'Shown to the user and the agent only; the parameter key is generated automatically. Leave empty for the default',\n wfParamDefault: 'Default',\n wfParamRandom: 'Random',\n wfParamDelete: 'Delete',\n wfParamNode: 'Node',\n wfParamInput: 'Input',\n wfJson: 'Workflow JSON (API format exported from the ComfyUI UI)',\n wfSave: 'Save',\n wfSaveRun: 'Save & Run',\n wfCancel: 'Cancel',\n wfEdit: 'Edit',\n wfRun: 'Run',\n wfDelete: 'Delete',\n wfQueued: 'Queued: ',\n wfJsonError: 'Workflow JSON could not be parsed',\n wfUpdated: 'updated',\n wfEmpty: 'No workflows detected — create one via New, Import, or Extract.',\n wfLibrarySection: 'API workflows',\n wfRefresh: 'Refresh',\n wfImportFile: 'Import JSON',\n // workflow preset transfer (export / import)\n exportPresets: 'Export presets',\n importPresets: 'Import presets',\n transferExportTitle: 'Export workflow presets',\n transferImportTitle: 'Import workflow presets',\n transferExportHint: '{total} exportable workflows, {selected} selected. Parameters and skill packs are included.',\n transferSelectAll: 'Select all',\n transferSelectNone: 'Select none',\n transferExportRun: 'Export ({n})',\n transferImportRun: 'Import ({n})',\n transferExporting: 'Exporting…',\n transferImporting: 'Importing…',\n transferExportDone: 'Exported {n} workflows: {names} (the browser is downloading the package)',\n transferExportFile: 'File {file} ({size} KB)',\n transferExportWarnings: 'Export warnings: {warnings}',\n transferSelectedList: 'Will export: {names}',\n transferExportEmpty: 'No exportable workflows',\n transferPickFile: 'Click to choose, or drop a .zip preset package here',\n transferPickHint: 'Import creates new workflows — nothing in your library is overwritten',\n transferPackageInfo: '{n} workflows in package · exported {date}',\n transferParamBadge: '{n} params',\n transferSkillBadge: 'Skill pack · {n} files',\n transferSkillRequired: 'Skill pack · {n} files · required',\n transferImportDone: 'Imported {n} workflows',\n transferImportedItem: '✓ {src} → {dst}',\n transferImportFailedItem: '✗ {src}: {reason}',\n transferImportNote: 'Name clashes get an \"(imported)\" suffix',\n transferFinish: 'Done',\n wfComfyuiSection: 'ComfyUI workflows',\n wfComfyuiHint: 'Auto-detects workflows saved in ComfyUI.\\nNote: these are UI graphs, not directly runnable — extract them into API workflows, or import an API workflow instead.',\n wfComfyuiEmpty: 'No workflows detected on the ComfyUI server',\n wfExtracted: 'extracted',\n wfNotExtracted: 'not extracted',\n wfView: 'View',\n wfExtract: 'Extract',\n wfExtractedNotice: 'extracted into the library',\n wfExtractTitle: 'Extract runnable workflows',\n wfExtractModeAll: 'All as one',\n wfExtractModeAllHint: 'Merge every component into one runnable workflow (everything executes)',\n wfExtractModeSplit: 'Per component',\n wfExtractModeSplitHint: 'One runnable workflow per independent flow (recommended)',\n wfExtractModeMain: 'Main flow only',\n wfExtractModeMainHint: 'Only the largest component (usually the flow under test)',\n wfExtractRun: 'Extract',\n wfExtractEmpty: 'No extractable components in this graph',\n wfComponents: 'components',\n wfComponentLabel: 'Component',\n wfNodes: 'nodes',\n wfBypassed: 'bypassed nodes',\n wfIsolated: 'dangling nodes',\n wfViewBack: 'Back',\n wfViewNodes: 'Nodes',\n wfViewJson: 'JSON preview',\n wfViewEmpty: 'No executable nodes in this graph',\n // assets tab\n assetAll: 'All workflows',\n assetBack: 'Back',\n assetEmpty: 'Nothing generated yet. Results appear here after workflows run.',\n assetGone: 'Source file evicted by ComfyUI',\n assetDelete: 'Delete asset',\n assetDeleteTitle: 'Delete this asset?',\n assetDeleteBody: 'Removes the record from the asset library and deletes {count} file(s) from the ComfyUI output directory. This cannot be undone.',\n assetDeleteNoDir: 'The ComfyUI output directory could not be located, so only the record is removed and the files stay on disk (set outputDir in cordis.yml to enable file deletion).',\n assetDeleteDone: 'Record removed, {deleted} file(s) deleted',\n assetDeleteFailed: 'Delete failed: {message}',\n confirmDelete: 'Delete',\n cancel: 'Cancel',\n // skill pack (per-workflow SKILL.md bundle)\n skillButton: 'Skill pack',\n skillBadge: 'Skill pack',\n skillBadgeRequired: 'Skill pack (required)',\n skillBadgeHint: 'This workflow has a skill pack: the agent reads it before running.',\n skillTitle: 'Skill pack',\n skillIntro: 'Click \"Create skill pack\" to add extra skill instructions for this workflow: when to use it, how to fill its parameters, and which pitfalls to avoid.',\n skillEnable: 'Create skill pack',\n skillDetach: 'Detach (keep files)',\n skillDestroy: 'Destroy pack',\n skillDestroyConfirm: '⚠ Permanently delete the whole pack ({count} files) — cannot be undone',\n skillDestroyConfirmButton: 'Destroy',\n skillDropHint: 'Drop files here to import',\n skillRequired: 'Required before running',\n skillDir: 'Directory',\n skillSummary: 'Summary',\n skillSummaryPlaceholder: 'One line on what this workflow is for',\n skillSummaryHint: 'The agent uses it to decide whether to read the body — like the description field of a skill.',\n skillSave: 'Save',\n skillSaved: 'Saved',\n skillDirty: 'Unsaved',\n skillDirtyPrompt: 'The current file has unsaved changes.',\n skillSaveAndSwitch: 'Save and switch',\n skillDiscard: 'Discard changes',\n skillImport: 'Import files',\n skillImportHint: 'Import local files into the pack: md/txt/json/yaml go to references, scripts to scripts, images/csv to assets (drag onto the list works too).',\n skillImported: 'Imported',\n skillImageHint: 'Images are preview-only here; the agent reads one only when the body points at it.',\n skillNewFile: '+ New file',\n skillNewDir: '+ New folder',\n skillReveal: '📂 Open folder',\n skillRevealHint: 'Open this pack folder in the file manager so you can copy files straight in. It opens on the machine running DSH; if you are viewing this page from another machine, use the path shown below instead.',\n skillRevealed: 'Opened',\n skillRefresh: 'Refresh',\n skillRefreshHint: 'Re-read the pack directory to show files added or replaced by the agent or the file manager.',\n skillRefreshed: 'Refreshed',\n skillNewDirPlaceholder: 'Folder name, e.g. templates',\n skillNewDirHint: 'A pack may hold any one-level sub-directory. Common ones: {presets}; custom names work too (letters, digits, CJK, underscore, dash).',\n skillDirCreated: 'Folder created',\n skillNewPlaceholder: 'File name (.md by default)',\n skillCreate: 'Create',\n skillRename: 'Rename',\n skillDeleteFile: 'Delete file',\n skillDeleteConfirm: 'Delete file',\n skillReadFailed: 'Read failed',\n skillFailed: 'Operation failed',\n skillDeleteWithWorkflow: 'This workflow has a skill pack. Delete it too?',\n skillDeleteBoth: 'Delete both',\n skillKeepPack: 'Workflow only',\n // queue tab (task center)\n queueEmpty: 'No tasks right now',\n queueError: 'Cannot read the queue (ComfyUI not running?)',\n jobFilterLabel: 'History',\n jobFilterAll: 'All',\n jobFilterPending: 'Pending',\n jobFilterInProgress: 'Running',\n jobFilterCompleted: 'Completed',\n jobFilterFailed: 'Failed',\n jobFilterCancelled: 'Cancelled',\n jobActive: 'Active',\n jobDelete: 'Delete',\n jobInterrupt: 'Interrupt',\n jobRerun: 'Rerun',\n jobViewAssets: 'View assets',\n jobMore: 'More actions',\n jobClearQueue: 'Clear queue',\n jobClearHistory: 'Clear history',\n jobFree: 'Free memory',\n jobDuration: 'Took',\n jobOurs: 'ours',\n}\n\nexport type Lang = 'zh' | 'en'\nexport const LANGS: readonly Lang[] = ['zh', 'en']\nconst LANG_KEY = 'dsh-comfyui.lang'\n\n/** Current plugin UI language, read from localStorage (default zh). */\nexport function getLang(): Lang {\n try {\n return localStorage.getItem(LANG_KEY) === 'en' ? 'en' : 'zh'\n } catch {\n return 'zh'\n }\n}\n\n/** Persist the plugin UI language choice. */\nexport function setLang(lang: Lang): void {\n try {\n localStorage.setItem(LANG_KEY, lang)\n } catch {\n // storage unavailable (e.g. private mode): the choice just does not persist\n }\n}\n\nconst DICTS: Record<Lang, Record<string, string>> = { zh, en }\n\n/** Build a plugin-local translator for one language. Resolves {name}\n * placeholders from the first rest argument (same contract as the DSH\n * locale bind), falling back to the key itself when untranslated. */\nexport function makeT(lang: Lang): (key: string, ...rest: unknown[]) => string {\n const dict = DICTS[lang]\n return (key, ...rest) => {\n const template = dict[key] ?? key\n const params = (rest[0] ?? {}) as Record<string, unknown>\n if (params !== null && typeof params === 'object') {\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) => {\n const value = params[name]\n return value === undefined ? match : String(value)\n })\n }\n return template\n }\n}\n","/**\n * Shared lightbox: opens a generated image full-screen with prev/next\n * navigation, keyboard support, and a download pill. Used by both the panel\n * (assets/queue previews) and the tool card (result images).\n */\nimport { createElement as h, useEffect } from 'react'\n\nexport interface LightboxProps {\n t: (key: string, ...rest: unknown[]) => string\n images: string[]\n /** Per-image media kind, parallel to `images`; omitted defaults to image. */\n kinds?: Array<'image' | 'video' | 'audio' | 'other'>\n index: number\n onClose: () => void\n onIndex: (index: number) => void\n}\n\n/** Full-screen media overlay with prev/next navigation. */\nexport function Lightbox({ t, images, kinds, index, onClose, onIndex }: LightboxProps): ReturnType<typeof h> | null {\n const count = images.length\n useEffect(() => {\n const onKey = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') onClose()\n else if (event.key === 'ArrowLeft') onIndex((index - 1 + count) % count)\n else if (event.key === 'ArrowRight') onIndex((index + 1) % count)\n }\n document.addEventListener('keydown', onKey)\n return () => document.removeEventListener('keydown', onKey)\n }, [index, count, onClose, onIndex])\n const src = images[index]\n if (src === undefined) return null\n const kind = kinds?.[index] ?? 'image'\n const media = kind === 'video'\n ? h('video', { className: 'dsc-lightbox-media', src, controls: true, autoPlay: true })\n : kind === 'audio'\n ? h('audio', { className: 'dsc-lightbox-media', src, controls: true, autoPlay: true })\n : kind === 'image'\n ? h('img', { className: 'dsc-lightbox-img', src, alt: '' })\n : h('div', { className: 'dsc-lightbox-media' }, src)\n return h('div', { className: 'dsc-lightbox', onClick: onClose },\n h('div', { className: 'dsc-lightbox-body', onClick: (event: { stopPropagation: () => void }) => event.stopPropagation() },\n h('button', {\n className: 'dsc-lightbox-close',\n 'aria-label': t('close'),\n onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); onClose() },\n }, '✕'),\n count > 1\n ? h('button', {\n className: 'dsc-lightbox-nav dsc-lightbox-nav--prev',\n 'aria-label': t('lbPrev'),\n onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); onIndex((index - 1 + count) % count) },\n }, '‹')\n : null,\n media,\n h('div', { className: 'dsc-lightbox-meta' },\n h('span', null, `${index + 1} / ${count}`),\n h('a', { className: 'dsc-lightbox-download', href: src, download: '', target: '_blank', rel: 'noreferrer' }, t('cardDownload')),\n ),\n count > 1\n ? h('button', {\n className: 'dsc-lightbox-nav dsc-lightbox-nav--next',\n 'aria-label': t('lbNext'),\n onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); onIndex((index + 1) % count) },\n }, '›')\n : null,\n ),\n )\n}\n","/**\n * Tool cards for comfyui_run and comfyui_workflow (tool.call.toolview, keys\n * 'comfyui_run' / 'comfyui_workflow'). A pure function of the frozen tool-call\n * block: running calls show a generating state, settled calls render the\n * presentationMeta payload (media wall with size labels, click-to-zoom\n * lightbox, status) that the host threaded into the session log.\n */\nimport { createElement as h, useEffect, useState } from 'react'\nimport { Lightbox } from './lightbox.js'\n\ninterface MediaItem {\n filename: string\n subfolder: string\n type: string\n node: string\n index: number\n kind: 'image' | 'video' | 'audio' | 'other'\n url: string\n}\n\ninterface SyncMeta {\n kind: 'sync'\n promptId: string\n status: 'completed' | 'interrupted'\n elapsedMs: number\n media: MediaItem[]\n summary: string\n}\n\ninterface BackgroundMeta {\n kind: 'background'\n jobId: string\n promptId: string\n label: string\n}\n\ntype RunMeta = SyncMeta | BackgroundMeta\n\n/** Settled tool-result node (structural slice of the wire ToolCallBlock). */\ninterface ToolResultNode {\n kind: 'tool-result'\n call?: { name: string; argsRaw: string } | null\n isError?: boolean\n error?: { name?: string; code?: string }\n meta?: unknown\n}\n\n/** Running tool-call node (structural slice). */\ninterface RunningToolCall {\n callId: string\n name: string\n argsRaw: string\n}\n\ntype Block = ToolResultNode | RunningToolCall\n\n/** Discriminate the settled result node from a running call. */\nfunction isResultNode(block: Block): block is ToolResultNode {\n return (block as ToolResultNode).kind === 'tool-result'\n}\n\nexport interface ComfyUICardProps {\n t: (key: string, ...rest: unknown[]) => string\n block: Block\n}\n\nfunction parseArgs(raw: string): Record<string, unknown> {\n try {\n const parsed = JSON.parse(raw)\n return typeof parsed === 'object' && parsed !== null ? parsed as Record<string, unknown> : {}\n } catch {\n return {}\n }\n}\n\nfunction argsSummary(args: Record<string, unknown>): string {\n const parts: string[] = []\n if (typeof args.template === 'string') parts.push(`template=${args.template}`)\n if (args.mode !== undefined && args.mode !== 'sync') parts.push(`mode=${String(args.mode)}`)\n if (parts.length === 0) parts.push('custom workflow')\n return parts.join(' · ')\n}\n\nfunction aspectLabel(width: number, height: number): string {\n const gcd = (a: number, b: number): number => (b === 0 ? a : gcd(b, a % b))\n const g = gcd(width, height)\n const rw = width / g\n const rh = height / g\n return rw <= 32 && rh <= 32 ? `${rw}:${rh}` : ''\n}\n\nfunction MediaItem({ item, t, onOpen }: {\n item: MediaItem\n t: ComfyUICardProps['t']\n onOpen: () => void\n}): ReturnType<typeof h> {\n const [size, setSize] = useState<{ width: number; height: number } | null>(null)\n const [failed, setFailed] = useState(false)\n const media = item.kind === 'video'\n ? h('video', { src: item.url, controls: true, preload: 'metadata' })\n : item.kind === 'audio'\n ? h('audio', { src: item.url, controls: true, preload: 'metadata' })\n : item.kind === 'image'\n ? failed\n ? h('span', { className: 'dsc-media-other' }, `${item.filename}(${t('cardLoadFailed')})`)\n : h('img', {\n src: item.url,\n alt: item.filename,\n loading: 'lazy',\n className: 'dsc-media-img dsc-media-img--clickable',\n onClick: onOpen,\n onLoad: (event: { target: { naturalWidth?: number; naturalHeight?: number } }) => {\n const width = event.target.naturalWidth\n const height = event.target.naturalHeight\n if (typeof width === 'number' && typeof height === 'number' && width > 0 && height > 0) {\n setSize({ width, height })\n }\n },\n onError: () => setFailed(true),\n })\n : h('span', { className: 'dsc-media-other' }, item.filename)\n const ratio = size === null ? null : aspectLabel(size.width, size.height)\n return h('div', { className: 'dsc-media' },\n media,\n h('div', { className: 'dsc-media-meta' },\n size !== null\n ? h('span', { className: 'dsc-media-size' }, `${size.width}×${size.height}${ratio !== '' ? ` · ${ratio}` : ''}`)\n : null,\n h('a', { href: item.url, download: item.filename, target: '_blank', rel: 'noreferrer' }, t('cardDownload')),\n ),\n )\n}\n\nfunction ResultCard({ title, result, t }: {\n title: string\n result: SyncMeta\n t: ComfyUICardProps['t']\n}): ReturnType<typeof h> {\n const failed = result.status === 'interrupted'\n const [lightbox, setLightbox] = useState<number | null>(null)\n const urls = result.media.map((item) => item.url)\n const kinds = result.media.map((item) => item.kind)\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' },\n title !== '' ? h('span', { className: 'dsc-badge' }, title) : null,\n h('span', { className: failed ? 'dsc-badge dsc-badge--err' : 'dsc-badge dsc-badge--ok' },\n failed ? t('cardInterrupted') : result.status),\n h('span', { className: 'dsc-meta' }, `${t('cardPrompt')} ${result.promptId}`),\n h('span', { className: 'dsc-meta' }, `${t('cardElapsed')} ${result.elapsedMs} ms`),\n ),\n h('div', { className: 'dsc-meta' }, result.summary),\n result.media.length > 0\n ? h('div', { className: 'dsc-grid' }, result.media.map((item, index) => h(MediaItem, {\n key: `${item.node}-${item.index}`,\n item,\n t,\n onOpen: () => setLightbox(index),\n })))\n : h('div', { className: 'dsc-meta' }, t('cardEmpty')),\n lightbox !== null\n ? h(Lightbox, { t, images: urls, kinds, index: lightbox, onClose: () => setLightbox(null), onIndex: setLightbox })\n : null,\n )\n}\n\nfunction BackgroundCard({ label, promptId, t }: {\n label: string\n promptId: string\n t: ComfyUICardProps['t']\n}): ReturnType<typeof h> {\n // The tool returns immediately with a background job; this card polls the\n // job's history entry and, once completed, renders the collected media in\n // place (same wall as a sync result).\n const [result, setResult] = useState<{ status: string; media?: MediaItem[]; error?: string } | null>(null)\n const [lightbox, setLightbox] = useState<number | null>(null)\n\n useEffect(() => {\n let stopped = false\n let timer: number | undefined\n const poll = async (): Promise<void> => {\n try {\n const response = await fetch(`/comfyui/jobs/media?promptId=${encodeURIComponent(promptId)}`, { headers: { accept: 'application/json' } })\n const data = (await response.json()) as { ok?: boolean; status?: string; media?: MediaItem[]; error?: string }\n if (stopped) return\n if (data.ok !== true || data.status === undefined) return\n if (data.status === 'completed' || data.status === 'failed') {\n setResult({ status: data.status, media: data.media, error: data.error })\n return\n }\n timer = window.setTimeout(() => { void poll() }, 3_000)\n } catch {\n timer = window.setTimeout(() => { void poll() }, 5_000)\n }\n }\n void poll()\n return () => {\n stopped = true\n if (timer !== undefined) window.clearTimeout(timer)\n }\n }, [promptId])\n\n if (result !== null && (result.status === 'completed' || result.status === 'failed')) {\n const media = result.media ?? []\n const urls = media.map((item) => item.url)\n const kinds = media.map((item) => item.kind)\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' },\n h('span', { className: result.status === 'failed' ? 'dsc-badge dsc-badge--err' : 'dsc-badge dsc-badge--ok' },\n result.status === 'failed' ? t('cardFailed') : t('cardBackgroundDone')),\n h('span', { className: 'dsc-meta' }, `${label} · ${promptId}`),\n ),\n result.status === 'failed'\n ? h('div', { className: 'dsc-meta dsc-job-error' }, result.error ?? t('cardFailed'))\n : media.length > 0\n ? h('div', { className: 'dsc-grid' }, media.map((item, index) => h(MediaItem, {\n key: `${item.node}-${item.index}`,\n item,\n t,\n onOpen: () => setLightbox(index),\n })))\n : h('div', { className: 'dsc-meta' }, t('cardEmpty')),\n lightbox !== null\n ? h(Lightbox, { t, images: urls, kinds, index: lightbox, onClose: () => setLightbox(null), onIndex: setLightbox })\n : null,\n )\n }\n\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' },\n h('span', { className: 'dsc-badge' }, t('cardBackground')),\n h('span', { className: 'dsc-meta' }, `${label} · ${promptId}`),\n ),\n h('div', { className: 'dsc-meta' }, t('cardCollect')),\n )\n}\n\n/** meta of a comfyui_workflow call (action: run / list / get). */\ntype WorkflowMeta = {\n action: 'run'\n id: string\n workflowName?: string\n result?: SyncMeta\n background?: BackgroundMeta\n} | {\n action: 'list'\n workflows?: unknown[]\n comfyuiWorkflows?: unknown[]\n} | {\n action: 'get'\n id?: string\n name?: string\n}\n\nfunction SettledCard({ block, t }: { block: ToolResultNode; t: ComfyUICardProps['t'] }): ReturnType<typeof h> {\n if (block.isError === true) {\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' },\n h('span', { className: 'dsc-badge dsc-badge--err' }, t('cardFailed')),\n ),\n h('div', { className: 'dsc-meta' }, block.error?.name ?? 'error'),\n )\n }\n const meta = block.meta as RunMeta | WorkflowMeta | undefined\n if (meta === undefined || typeof meta !== 'object') {\n return h('div', { className: 'dsc-card' }, h('span', { className: 'dsc-badge' }, block.call?.name ?? 'comfyui'))\n }\n // comfyui_workflow: action-shaped meta.\n if ('action' in meta) {\n if (meta.action === 'run') {\n if (meta.background !== undefined) {\n return h(BackgroundCard, { label: meta.workflowName ?? '', promptId: meta.background.promptId, t })\n }\n if (meta.result !== undefined) {\n return h(ResultCard, { title: meta.workflowName ?? '', result: meta.result, t })\n }\n }\n if (meta.action === 'list') {\n const runs = meta.workflows?.length ?? 0\n const graphs = meta.comfyuiWorkflows?.length ?? 0\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' }, h('span', { className: 'dsc-badge' }, 'comfyui_workflow')),\n h('div', { className: 'dsc-meta' }, t('cardListed', { runs, graphs })),\n )\n }\n if (meta.action === 'get') {\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' }, h('span', { className: 'dsc-badge' }, 'comfyui_workflow')),\n h('div', { className: 'dsc-meta' }, meta.name ?? meta.id ?? 'get'),\n )\n }\n return h('div', { className: 'dsc-card' }, h('span', { className: 'dsc-badge' }, 'comfyui_workflow'))\n }\n // comfyui_run: kind-shaped meta.\n if (meta.kind === 'background') {\n return h(BackgroundCard, { label: meta.label, promptId: meta.promptId, t })\n }\n return h(ResultCard, { title: '', result: meta, t })\n}\n\n/** The card component: picks running vs settled rendering from the block. */\nexport function ComfyUICard({ t, block }: ComfyUICardProps): ReturnType<typeof h> {\n if (isResultNode(block)) {\n return h(SettledCard, { block, t })\n }\n const args = parseArgs(block.argsRaw)\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-card-head' },\n h('span', { className: 'dsc-badge' }, t('cardGenerating')),\n h('span', { className: 'dsc-meta' }, `${t('cardWorkflow')} ${argsSummary(args)} · ${t('cardMode')} ${String(args.mode ?? 'sync')}`),\n ),\n )\n}\n","/** Same-origin JSON helpers shared by the settings page and the panel. */\nexport async function getJson<T>(url: string): Promise<T> {\n const response = await fetch(url, { headers: { accept: 'application/json' } })\n if (!response.ok) throw new Error(`HTTP ${response.status}`)\n return (await response.json()) as T\n}\n\nexport async function postJson(url: string, body: unknown): Promise<unknown> {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n })\n if (!response.ok) {\n const payload = (await response.json().catch(() => ({}))) as { error?: string }\n throw new Error(payload.error ?? `HTTP ${response.status}`)\n }\n return response.json() as Promise<unknown>\n}\n\n/** POST raw bytes (an imported file) and read the JSON reply. */\nexport async function postRaw(url: string, bytes: ArrayBuffer): Promise<unknown> {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/octet-stream' },\n body: bytes,\n })\n if (!response.ok) {\n const payload = (await response.json().catch(() => ({}))) as { error?: string }\n throw new Error(payload.error ?? `HTTP ${response.status}`)\n }\n return response.json() as Promise<unknown>\n}\n","/**\n * The ComfyUI settings page (settings.section, id 'comfyui'). Reads the\n * redacted host config over /comfyui/config, persists edits through the same\n * route, and probes the server over /comfyui/test.\n */\nimport { createElement as h, useEffect, useState } from 'react'\nimport { getJson, postJson } from './api.ts'\nimport { getLang, setLang, type Lang } from './i18n.ts'\n\nexport interface ComfyUISettingsProps {\n t: (key: string, ...rest: unknown[]) => string\n close: () => void\n}\n\ninterface ConfigView {\n baseUrl: string\n apiKeyEnv: string\n hasApiKey: boolean\n timeoutMs: number\n pollIntervalMs: number\n maxMediaItems: number\n mediaHost: string\n comfyuiDirs: string[]\n skillsDir: string\n /** The path packs actually use, including the `<dataDir>/skills` default. */\n skillsRoot: string\n writable: boolean\n}\n\ninterface TestResult {\n ok: boolean\n text: string\n}\n\n/** The ComfyUI settings page component. */\nexport function ComfyUISettings({ t }: ComfyUISettingsProps): ReturnType<typeof h> {\n const [config, setConfig] = useState<ConfigView | null>(null)\n const [baseUrl, setBaseUrl] = useState('')\n const [apiKeyEnv, setApiKeyEnv] = useState('')\n const [mediaHost, setMediaHost] = useState('')\n const [comfyuiDirs, setComfyuiDirs] = useState<string[]>([])\n const [skillsDir, setSkillsDir] = useState('')\n const [loadError, setLoadError] = useState<string | null>(null)\n const [saving, setSaving] = useState(false)\n const [saveState, setSaveState] = useState<'idle' | 'saved' | 'failed'>('idle')\n const [testing, setTesting] = useState(false)\n const [testResult, setTestResult] = useState<TestResult | null>(null)\n const [lang, setLangState] = useState<Lang>(getLang())\n\n useEffect(() => {\n let cancelled = false\n getJson<ConfigView>('/comfyui/config').then((view) => {\n if (cancelled) return\n setConfig(view)\n setBaseUrl(view.baseUrl)\n setApiKeyEnv(view.apiKeyEnv)\n setMediaHost(view.mediaHost ?? '')\n setComfyuiDirs(Array.isArray(view.comfyuiDirs) ? view.comfyuiDirs : [])\n setSkillsDir(view.skillsDir ?? '')\n }).catch((error: unknown) => {\n if (cancelled) return\n setLoadError(error instanceof Error ? error.message : String(error))\n })\n return () => {\n cancelled = true\n }\n }, [])\n\n const save = async (): Promise<void> => {\n setSaving(true)\n setSaveState('idle')\n try {\n // Trim blanks and drop empty rows before persisting.\n const dirs = comfyuiDirs.map((dir) => dir.trim()).filter((dir) => dir !== '')\n const payload = (await postJson('/comfyui/config', { patch: { baseUrl, apiKeyEnv, mediaHost, comfyuiDirs: dirs, skillsDir: skillsDir.trim() } })) as { config?: ConfigView }\n if (payload.config !== undefined) {\n setConfig(payload.config)\n setBaseUrl(payload.config.baseUrl)\n setApiKeyEnv(payload.config.apiKeyEnv)\n setMediaHost(payload.config.mediaHost ?? '')\n setComfyuiDirs(payload.config.comfyuiDirs ?? [])\n setSkillsDir(payload.config.skillsDir ?? '')\n }\n setSaveState('saved')\n } catch (error) {\n setSaveState('failed')\n setTestResult({ ok: false, text: error instanceof Error ? error.message : String(error) })\n } finally {\n setSaving(false)\n }\n }\n\n const test = async (): Promise<void> => {\n setTesting(true)\n setTestResult(null)\n try {\n const payload = (await postJson('/comfyui/test', {})) as { ok: boolean; version?: string; latencyMs?: number; error?: string }\n if (payload.ok === true) {\n setTestResult({ ok: true, text: t('testOk', { version: payload.version ?? 'unknown', ms: payload.latencyMs ?? 0 }) })\n } else {\n setTestResult({ ok: false, text: t('testFail', { message: payload.error ?? 'unknown error' }) })\n }\n } catch (error) {\n setTestResult({ ok: false, text: t('testFail', { message: error instanceof Error ? error.message : String(error) }) })\n } finally {\n setTesting(false)\n }\n }\n\n if (loadError !== null) {\n return h('div', { className: 'dsc-card' },\n h('div', { className: 'dsc-meta' }, `${t('saveFailed')}: ${loadError}`),\n )\n }\n if (config === null) {\n return h('div', { className: 'dsc-card' }, h('div', { className: 'dsc-meta' }, '…'))\n }\n\n return h('div', { className: 'dsc-form' },\n h('div', { className: 'dsc-meta' }, t('settingsDesc')),\n h('div', { className: 'dsc-field' },\n h('label', null, t('language')),\n h('select', {\n className: 'dsc-input',\n value: lang,\n onChange: (event: { target: { value: string } }) => {\n const next: Lang = event.target.value === 'en' ? 'en' : 'zh'\n setLangState(next)\n setLang(next)\n window.location.reload()\n },\n },\n h('option', { value: 'zh' }, '中文'),\n h('option', { value: 'en' }, 'English'),\n ),\n h('div', { className: 'dsc-hint' }, t('languageHint')),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('baseUrl')),\n h('input', {\n value: baseUrl,\n placeholder: 'http://127.0.0.1:8188',\n onChange: (event: { target: { value: string } }) => { setBaseUrl(event.target.value); setSaveState('idle') },\n }),\n h('div', { className: 'dsc-hint' }, t('baseUrlHint')),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('apiKeyEnv')),\n h('input', {\n value: apiKeyEnv,\n placeholder: 'COMFYUI_API_KEY',\n onChange: (event: { target: { value: string } }) => { setApiKeyEnv(event.target.value); setSaveState('idle') },\n }),\n h('div', { className: 'dsc-hint' }, `${t('apiKeyEnvHint')} — ${config.hasApiKey ? t('hasApiKey') : t('noApiKey')}`),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('mediaHost')),\n h('input', {\n value: mediaHost,\n placeholder: 'http://192.168.1.5:3080',\n onChange: (event: { target: { value: string } }) => { setMediaHost(event.target.value); setSaveState('idle') },\n }),\n h('div', { className: 'dsc-hint' }, t('mediaHostHint')),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('comfyuiDirs')),\n comfyuiDirs.map((dir, index) => h('div', {\n key: `dsc-dir-${index}`,\n style: { display: 'flex', gap: '8px', marginBottom: '8px', alignItems: 'center' },\n },\n h('input', {\n className: 'dsc-input',\n value: dir,\n placeholder: t('comfyuiDirPlaceholder'),\n style: { flex: '1' },\n onChange: (event: { target: { value: string } }) => {\n const next = comfyuiDirs.slice()\n next[index] = event.target.value\n setComfyuiDirs(next)\n setSaveState('idle')\n },\n }),\n h('button', {\n className: 'dsc-btn',\n title: t('comfyuiDirRemove'),\n disabled: !config.writable,\n onClick: () => {\n const next = comfyuiDirs.slice()\n next.splice(index, 1)\n setComfyuiDirs(next)\n setSaveState('idle')\n },\n }, '×'),\n )),\n h('button', {\n className: 'dsc-btn',\n disabled: !config.writable,\n onClick: () => {\n setComfyuiDirs([...comfyuiDirs, ''])\n setSaveState('idle')\n },\n }, t('comfyuiDirAdd')),\n h('div', { className: 'dsc-hint' }, t('comfyuiDirsHint')),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('skillsDir')),\n h('input', {\n className: 'dsc-input',\n value: skillsDir,\n placeholder: config.skillsRoot,\n onChange: (event: { target: { value: string } }) => { setSkillsDir(event.target.value); setSaveState('idle') },\n }),\n h('div', { className: 'dsc-hint' }, t('skillsDirHint', { current: config.skillsRoot })),\n ),\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn', disabled: saving || !config.writable, onClick: () => void save() }, t('save')),\n h('button', { className: 'dsc-btn', disabled: testing, onClick: () => void test() }, testing ? t('testing') : t('test')),\n saveState === 'saved' ? h('span', { className: 'dsc-note' }, t('saved')) : null,\n saveState === 'failed' ? h('span', { className: 'dsc-note' }, t('saveFailed')) : null,\n ),\n testResult !== null\n ? h('div', { className: testResult.ok ? 'dsc-note' : 'dsc-note', style: testResult.ok ? { color: '#22c55e' } : { color: '#ef4444' } }, testResult.text)\n : null,\n config.writable ? null : h('div', { className: 'dsc-hint' }, t('configNotWritable')),\n )\n}\n","/**\n * Shared open/close/tab state for the ComfyUI panel. The overlay occupant\n * and the session-header trigger are separate registrations in one bundle,\n * so they coordinate through this module-level store plus useSyncExternalStore.\n */\nimport { useSyncExternalStore } from 'react'\n\nconst listeners = new Set<() => void>()\nlet open = false\nlet tab: PanelTab = 'workflows'\nlet assetFilter = ''\n\nfunction emit(): void {\n for (const listener of listeners) listener()\n}\n\nexport type PanelTab = 'workflows' | 'assets' | 'queue'\n\nexport const panelStore = {\n isOpen: () => open,\n toggle: () => {\n open = !open\n emit()\n },\n open: () => {\n if (!open) {\n open = true\n emit()\n }\n },\n close: () => {\n if (open) {\n open = false\n emit()\n }\n },\n getTab: () => tab,\n setTab: (next: PanelTab) => {\n if (tab !== next) {\n tab = next\n emit()\n }\n },\n getAssetFilter: () => assetFilter,\n setAssetFilter: (name: string) => {\n if (assetFilter !== name) {\n assetFilter = name\n emit()\n }\n },\n subscribe(listener: () => void): () => void {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n}\n\n/** React hook reading the panel open state. */\nexport function usePanelOpen(): boolean {\n return useSyncExternalStore(panelStore.subscribe, panelStore.isOpen, panelStore.isOpen)\n}\n\n/** React hook reading the active panel tab. */\nexport function usePanelTab(): PanelTab {\n return useSyncExternalStore(panelStore.subscribe, panelStore.getTab, panelStore.getTab)\n}\n","/**\n * Connection probe + reminder toast. Opening the panel used to give zero\n * feedback when ComfyUI was down: the workflows/queue tabs just stayed empty\n * with no explanation. The header trigger now fires a real backend probe\n * (POST /comfyui/test → the host connects to the configured ComfyUI server —\n * local port or remote URL alike); when it fails, the panel closes again —\n * the trigger must not stay highlighted against a dead backend — and a fixed\n * toast at the top of the page tells the user to start ComfyUI or fix the\n * server address. The probe never blocks the panel: it opens immediately,\n * the toast settles whenever the probe answers.\n */\nimport { createElement as h, useSyncExternalStore } from 'react'\nimport { postJson } from './api.ts'\nimport { panelStore } from './panel-store.ts'\n\nexport interface ConnectionToastProps {\n t: (key: string, ...rest: unknown[]) => string\n}\n\n/** hidden → probing (delayed fade-in) → fail (sticky) / ok (auto-hide). */\ntype ConnStatus = 'hidden' | 'probing' | 'fail' | 'ok'\n\ninterface ConnState {\n status: ConnStatus\n /** Raw failure reason from the /comfyui/test route. */\n message?: string\n version?: string\n latencyMs?: number\n}\n\nconst listeners = new Set<() => void>()\nlet state: ConnState = { status: 'hidden' }\n/** Dedupe concurrent probes (rapid trigger clicks). */\nlet inFlight: Promise<void> | null = null\n/** Skip re-probing while a \"connected\" verdict is still fresh. */\nlet lastOkAt = 0\n/** The ok toast only shows on fail→ok transitions, never on healthy opens. */\nlet hadFailure = false\nlet okHideTimer: ReturnType<typeof setTimeout> | null = null\n\nfunction emit(): void {\n for (const listener of listeners) listener()\n}\n\nfunction setState(next: ConnState): void {\n state = next\n emit()\n}\n\nfunction clearOkTimer(): void {\n if (okHideTimer !== null) {\n clearTimeout(okHideTimer)\n okHideTimer = null\n }\n}\n\n/** Close button on the toast; also ends the transient ok feedback early. */\nexport function dismissConnectionToast(): void {\n clearOkTimer()\n if (state.status !== 'hidden') setState({ status: 'hidden' })\n}\n\n/**\n * Probe the ComfyUI server through the host and surface the result as toast\n * state. A success within the last 30s skips the round-trip entirely, so\n * healthy repeated panel opens do not hammer the server; failures always\n * re-probe on the next open (the user may have just started ComfyUI).\n */\nexport function probeConnection(): Promise<void> {\n if (inFlight !== null) return inFlight\n if (Date.now() - lastOkAt < 30_000) return Promise.resolve()\n // A visible fail toast stays up (and keeps its reason) while re-checking;\n // only upgrade hidden → probing so the check itself never flashes red.\n if (state.status !== 'fail') {\n clearOkTimer()\n setState({ status: 'probing' })\n }\n inFlight = (async () => {\n try {\n const payload = (await postJson('/comfyui/test', {})) as {\n ok?: boolean\n version?: string\n latencyMs?: number\n error?: string\n }\n if (payload.ok === true) {\n lastOkAt = Date.now()\n const recovered = hadFailure\n hadFailure = false\n if (recovered) {\n // Come-back feedback: a previous failure just resolved.\n setState({ status: 'ok', version: payload.version, latencyMs: payload.latencyMs })\n clearOkTimer()\n okHideTimer = setTimeout(dismissConnectionToast, 4000)\n } else {\n setState({ status: 'hidden' })\n }\n } else {\n hadFailure = true\n setState({ status: 'fail', message: payload.error ?? 'unknown error' })\n // The panel this click opened has nothing to show (dead tabs only) —\n // close it so the trigger does not stay highlighted against a dead\n // backend. The toast stays up as the actual reminder.\n panelStore.close()\n }\n } catch (error) {\n hadFailure = true\n setState({ status: 'fail', message: error instanceof Error ? error.message : String(error) })\n panelStore.close()\n } finally {\n inFlight = null\n }\n })()\n return inFlight\n}\n\nfunction getConnState(): ConnState {\n return state\n}\n\nfunction subscribe(listener: () => void): () => void {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n}\n\n/** Fixed top-center status toast; mounted next to the header trigger so it\n * renders (and can be dismissed) even when the panel is closed again. The\n * probing variant fades in after a short CSS delay, so a fast successful\n * probe never paints anything. */\nexport function ConnectionToast({ t }: ConnectionToastProps): ReturnType<typeof h> | null {\n const conn = useSyncExternalStore(subscribe, getConnState, getConnState)\n if (conn.status === 'hidden') return null\n return h('div', { className: `dsc-conn-toast dsc-conn-toast--${conn.status}`, role: 'status' },\n h('span', { className: 'dsc-conn-toast-dot', 'aria-hidden': true }),\n h('div', { className: 'dsc-conn-toast-body' },\n conn.status === 'fail'\n ? h('div', { className: 'dsc-conn-toast-body-inner' },\n h('div', { className: 'dsc-conn-toast-title' }, t('connFailTitle')),\n h('div', { className: 'dsc-conn-toast-text' }, t('connFailBody', { message: conn.message ?? '' })),\n )\n : h('div', { className: 'dsc-conn-toast-title' },\n conn.status === 'probing'\n ? t('connChecking')\n : t('connOk', { version: conn.version ?? 'unknown', ms: conn.latencyMs ?? 0 }),\n ),\n ),\n h('button', {\n className: 'dsc-conn-toast-close',\n 'aria-label': t('close'),\n onClick: dismissConnectionToast,\n }, '✕'),\n )\n}\n","/**\n * The session-header trigger (conversation.session.header.actions, id\n * 'comfyui'): a labelled button that toggles the ComfyUI panel, plus the\n * connection reminder toast shown when the backend cannot reach ComfyUI.\n */\nimport { Fragment, createElement as h } from 'react'\nimport { panelStore, usePanelOpen } from './panel-store.ts'\nimport { ConnectionToast, probeConnection } from './connection.tsx'\n\nexport interface ComfyUITriggerProps {\n t: (key: string, ...rest: unknown[]) => string\n}\n\n/**\n * ComfyUI brand glyph (mono), inlined from @lobehub/icons-static-svg\n * (lobehub.com/icons). currentColor fill keeps it theme-aware.\n */\nexport function ComfyUIIcon(): ReturnType<typeof h> {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: '1em', height: '1em',\n fill: 'currentColor', fillRule: 'evenodd',\n style: { flex: 'none', lineHeight: 1 },\n 'aria-hidden': true,\n }, h('path', { d: 'M5.485 23.76c-.568 0-1.026-.207-1.325-.598-.307-.402-.387-.964-.22-1.54l.672-2.315a.605.605 0 00-.1-.536.622.622 0 00-.494-.243H2.085c-.568 0-1.026-.207-1.325-.598-.307-.403-.387-.964-.22-1.54l2.31-7.917.255-.87c.343-1.18 1.592-2.14 2.786-2.14h2.313c.276 0 .519-.18.595-.442l.764-2.633C9.906 1.208 11.155.249 12.35.249l4.945-.008h3.62c.568 0 1.027.206 1.325.597.307.402.387.964.22 1.54l-1.035 3.566c-.343 1.178-1.593 2.137-2.787 2.137l-4.956.01H11.37a.618.618 0 00-.594.441l-1.928 6.604a.605.605 0 00.1.537c.118.153.3.243.495.243l3.275-.006h3.61c.568 0 1.026.206 1.325.598.307.402.387.964.22 1.54l-1.036 3.565c-.342 1.179-1.592 2.138-2.786 2.138l-4.957.01h-3.61z' }),\n )\n}\n\n/** Header-action button toggling the ComfyUI panel. Opening it also fires a\n * backend connectivity probe: when ComfyUI is down, a reminder toast explains\n * why the panel stays empty instead of the click appearing to do nothing. */\nexport function ComfyUITrigger({ t }: ComfyUITriggerProps): ReturnType<typeof h> {\n const open = usePanelOpen()\n return h(Fragment, null,\n h('button', {\n className: 'dsc-trigger',\n title: t('panelTitle'),\n 'aria-label': t('panelTitle'),\n 'aria-pressed': open,\n onClick: () => {\n const opening = !panelStore.isOpen()\n panelStore.toggle()\n if (opening) void probeConnection()\n },\n },\n h('span', { className: 'dsc-trigger-glyph' }, h(ComfyUIIcon)),\n h('span', null, t('panelTitle')),\n ),\n h(ConnectionToast, { t }),\n )\n}\n","/**\n * The ComfyUI panel (shell.overlay, id 'comfyui.panel'): a floating panel\n * with three tabs — workflow library management, generated asset preview,\n * and the live ComfyUI queue. Draggable by its header and resizable via the\n * corner handle; geometry persists in localStorage. Renders null while closed\n * (the overlay layer is click-through, so nothing blocks the app underneath).\n */\nimport { createElement as h, useCallback, useEffect, useRef, useState } from 'react'\nimport { getJson, postJson, postRaw } from './api.ts'\nimport { panelStore, usePanelOpen, usePanelTab } from './panel-store.ts'\nimport { ComfyUIIcon } from './trigger.tsx'\nimport { Lightbox } from './lightbox.js'\n\n/** Panel geometry: pixel position/size once the user dragged or resized. */\ninterface PanelGeom {\n x?: number\n y?: number\n width?: number\n height?: number\n}\n\nconst GEOM_KEY = 'dsh-comfyui-panel-geom'\n\nfunction loadGeom(): PanelGeom {\n try {\n const raw = localStorage.getItem(GEOM_KEY)\n if (raw === null) return {}\n const parsed = JSON.parse(raw) as Record<string, unknown>\n const geom: PanelGeom = {}\n if (typeof parsed.x === 'number') geom.x = parsed.x\n if (typeof parsed.y === 'number') geom.y = parsed.y\n if (typeof parsed.width === 'number' && parsed.width >= 300) geom.width = parsed.width\n if (typeof parsed.height === 'number' && parsed.height >= 200) geom.height = parsed.height\n return geom\n } catch {\n return {}\n }\n}\n\nfunction saveGeom(geom: PanelGeom): void {\n try {\n localStorage.setItem(GEOM_KEY, JSON.stringify(geom))\n } catch {\n // storage unavailable — geometry just won't persist\n }\n}\n\n/** Default panel width from styles.ts (`.dsc-panel` width var), used only to\n * estimate the panel extent while clamping a saved position. */\nconst PANEL_WIDTH_FALLBACK = 400\n/** Approx. height of the drag-handle band (`.dsc-panel-head`). */\nconst HEAD_BAND = 48\n/** Minimum margin kept between the panel and the viewport edge. */\nconst EDGE = 8\n\n/**\n * Clamp a top-left corner so the drag-handle band always stays inside the\n * viewport. The failure this prevents: once the header is pushed past the top\n * edge (or a saved position from a larger monitor no longer fits), there is no\n * grab surface left and the panel cannot be moved back at all.\n */\nfunction clampPos(x: number, y: number, width: number, vw: number, vh: number): { x: number; y: number } {\n const maxX = Math.max(EDGE, vw - width - EDGE)\n const maxY = Math.max(EDGE, vh - HEAD_BAND - EDGE)\n return { x: Math.min(Math.max(x, EDGE), maxX), y: Math.min(Math.max(y, EDGE), maxY) }\n}\n\n/** Snap persisted geometry back within reach of the cursor. Geometry that\n * never carried an explicit position (the CSS-anchored default) is returned\n * unchanged; geometry already inside the safe area keeps its object identity\n * so callers can skip pointless re-renders. */\nfunction healGeom(geom: PanelGeom, vw: number, vh: number): PanelGeom {\n if (geom.x === undefined || geom.y === undefined) return geom\n const pos = clampPos(geom.x, geom.y, geom.width ?? PANEL_WIDTH_FALLBACK, vw, vh)\n if (pos.x === geom.x && pos.y === geom.y) return geom\n return { ...geom, x: pos.x, y: pos.y }\n}\n\ninterface PointerEventLike {\n pointerId: number\n clientX: number\n clientY: number\n button: number\n target: EventTarget | null\n currentTarget: EventTarget | null\n}\n\nexport interface ComfyUIPanelProps {\n t: (key: string, ...rest: unknown[]) => string\n}\n\ninterface MediaItem {\n filename: string\n subfolder: string\n type: string\n node: string\n index: number\n kind: 'image' | 'video' | 'audio' | 'other'\n url: string\n}\n\ninterface WorkflowEntry {\n id: string\n name: string\n description: string\n workflow: Record<string, unknown>\n parameters?: WorkflowParameter[]\n tags?: string[]\n /** Skill-pack directory name; present when this workflow has a pack. */\n skillDir?: string\n /** Whether the agent must read the pack before running this workflow. */\n requireSkill?: boolean\n updatedAt: string\n}\n\n/** One file inside a workflow's skill pack. */\ninterface SkillPackFile {\n path: string\n size: number\n updatedAt: string\n}\n\n/** A workflow's skill pack as the routes report it. */\ninterface SkillPack {\n slug: string\n dir: string\n summary: string\n files: SkillPackFile[]\n /** Sub-directories present in the pack, including empty ones. */\n dirs: string[]\n totalBytes: number\n workflowId: string\n workflowName: string\n required: boolean\n}\n\ninterface SkillPackResponse {\n ok?: boolean\n enabled?: boolean\n root?: string\n /** Suggested directory names; the host owns the list. */\n presetDirs?: string[]\n pack?: SkillPack | null\n error?: string\n}\n\n/** Fallback suggestions when the config route has not answered yet; the\n * authoritative list comes from the host (`presetDirs`). */\nconst SKILL_FALLBACK_DIRS = ['references', 'scripts', 'assets']\n\n/** Imported binaries land in assets/; the editor previews these instead of\n * trying to read them as text. */\nconst SKILL_IMAGE_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.webp', '.gif', '.svg']\n\nfunction isSkillImage(path: string): boolean {\n const dot = path.lastIndexOf('.')\n return dot !== -1 && SKILL_IMAGE_EXTENSIONS.includes(path.slice(dot).toLowerCase())\n}\n\n/** Preset workflow classification tags (users can add custom ones). Stored as\n * plain text, so the tag identity is the label itself. */\nconst PRESET_TAGS = ['图生图', '文生图', '文生视频', '图生视频', '参考生视频', '文生音频', '参考生音频']\n\n/** A workflow saved on the ComfyUI server (userdata/workflows). */\ninterface ComfyUIWorkflowEntry {\n name: string\n size?: number\n modified?: number\n /** Whether at least one runnable API workflow was extracted from this graph. */\n extracted: boolean\n /** Runnable API workflows extracted from this graph. */\n derived: Array<{ libraryId: string; name: string }>\n}\n\n/** One connected component of a ComfyUI-side graph. */\ninterface ComponentInfo {\n index: number\n size: number\n groups: string[]\n nodeTypes: string[]\n}\n\n/** Canvas analysis result for the extract dialog. */\ninterface GraphAnalysis {\n ok: true\n components: ComponentInfo[]\n isolated: Array<{ id: number; type: string }>\n bypassedCount: number\n mode: 'single' | 'multi'\n}\n\n/** The analyze route wraps the host result, which itself is a union: a\n * non-graph file (e.g. ComfyUI's `.index.json`) yields the nested failure. */\ntype AnalyzePayload = { ok: boolean; error?: string; analysis?: GraphAnalysis | { ok: false; error: string } }\n\ntype ExtractMode = 'all' | 'split' | 'main'\n\n/** Extract-dialog state: the graph file being extracted. */\ninterface ExtractState {\n file: string\n analysis: GraphAnalysis | null\n error: string | null\n mode: ExtractMode\n}\n\n/** Read-only view state for a ComfyUI-side workflow. */\ninterface WorkflowViewState {\n file: string\n graph: Record<string, unknown>\n}\n\ninterface AssetEntry {\n promptId: string\n ts: string\n workflowName: string | null\n source: string\n media: MediaItem[]\n}\n\ntype JobStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'cancelled'\n/** History filter: 'all' shows every terminal task; others narrow it. */\ntype JobFilter = 'all' | 'completed' | 'failed' | 'cancelled'\n\n/** One unified job from ComfyUI /api/jobs, as served by /comfyui/jobs. */\ninterface JobView {\n id: string\n status: JobStatus\n createTime: number | null\n executionStartTime: number | null\n executionEndTime: number | null\n executionError: { message?: string; exception_message?: string; node_type?: string } | null\n outputsCount: number\n previewOutput: { filename?: string; subfolder?: string; type?: string; mediaType?: string } | null\n workflowId: string | null\n workflowName: string | null\n ours: boolean\n progress: { value: number; max: number } | null\n}\n\ninterface JobsView {\n ok: boolean\n error?: string\n jobs: JobView[]\n total: number\n hasMore: boolean\n}\n\nconst JOB_FILTERS: Array<{ key: JobFilter; label: string }> = [\n { key: 'all', label: 'jobFilterAll' },\n { key: 'completed', label: 'jobFilterCompleted' },\n { key: 'failed', label: 'jobFilterFailed' },\n { key: 'cancelled', label: 'jobFilterCancelled' },\n]\n\n/** One adjustable parameter of a saved workflow (mirrors host WorkflowParameter). */\ninterface WorkflowParameter {\n id: string\n name: string\n label: string\n type: 'string' | 'number' | 'boolean'\n nodeId: string\n inputKey: string\n default: string | number | boolean\n description?: string\n random?: boolean\n /** Declared numeric type of the node input; absent = unknown (decimals ok). */\n numberKind?: 'int' | 'float'\n min?: number\n max?: number\n step?: number\n options?: Array<string | number>\n upload?: 'image' | 'video' | 'audio' | 'media'\n subfolder?: string\n}\n\n/** Editing state for a workflow: the JSON field is text while being edited. */\ninterface WorkflowDraft {\n id?: string\n name?: string\n description?: string\n tags?: string[]\n inputs?: string\n workflow: string | Record<string, unknown>\n parameters?: WorkflowParameter[]\n updatedAt?: string\n}\n\n/** One workflow offered by an uploaded preset package (import analyze). */\ninterface ImportCandidateView {\n /** Position in the package manifest; apply selects by this index. */\n index: number\n id: string\n name: string\n description: string\n tags: string[]\n paramCount: number\n skill: { fileCount: number; totalBytes: number; required: boolean } | null\n warnings: string[]\n}\n\n/** Analyze reply for a preset package. */\ninterface ImportAnalysisView {\n version: number\n exportedAt: string\n pluginVersion: string\n workflows: ImportCandidateView[]\n}\n\n/** Per-workflow result of an import apply. */\ninterface ImportOutcomeView {\n index: number\n name: string\n ok: boolean\n newName?: string\n error?: string\n warnings: string[]\n}\n\n/** The server's record of the most recent export — the packaged facts the\n * panel reports back, because the native form download hides the response.\n * File name + size ride along so a stale download (download managers have\n * already confused tasks on this setup) cannot masquerade as this export. */\ninterface LastExport {\n at: string\n count: number\n names: string[]\n warnings: string[]\n filename: string\n size: number\n}\n\nfunction shortId(promptId: string): string {\n return promptId.length > 10 ? `${promptId.slice(0, 10)}…` : promptId\n}\n\n/** Open a job's preview image URL (via the media proxy) when it has one. */\nfunction previewUrlOf(job: JobView): string | null {\n const preview = job.previewOutput\n if (preview === undefined || preview === null || preview.filename === undefined || preview.filename === null) return null\n return `/comfyui/media?file=${encodeURIComponent(preview.filename)}&subfolder=${encodeURIComponent(preview.subfolder ?? '')}&type=${encodeURIComponent(preview.type ?? 'output')}`\n}\n\n/** Opens a generated image in a large overlay with prev/next navigation. */\n\n/** Whether a node input is fed by a link ([nodeId, slot]) rather than a widget value. */\nfunction isLinkValue(value: unknown): boolean {\n return Array.isArray(value) && value.length === 2 && typeof value[0] === 'string' && typeof value[1] === 'number'\n}\n\n/** Short description of a node input's current value, for the advanced\n * picker's dropdown. */\nfunction inputValueKind(value: unknown): string {\n if (value === null) return 'null'\n if (Array.isArray(value)) return 'array'\n if (typeof value === 'object') return 'object'\n return typeof value\n}\n\n/** Read a parameter default as a boolean. Defaults saved before the editor\n * had a checkbox are strings (\"true\"/\"false\"), so they are coerced here rather\n * than silently reading as `true` for every non-empty string. */\nfunction asBool(value: string | number | boolean): boolean {\n if (typeof value === 'boolean') return value\n if (typeof value === 'number') return value !== 0\n return /^(true|1|yes|on)$/i.test(value.trim())\n}\n\n/** Tooltip for a number field: the declared type and bounds, when known. */\nfunction numberRangeHint(param: WorkflowParameter): string {\n const parts: string[] = [param.numberKind ?? 'number']\n if (param.min !== undefined || param.max !== undefined) parts.push(`${param.min ?? '-∞'} ~ ${param.max ?? '∞'}`)\n if (param.step !== undefined) parts.push(`step ${param.step}`)\n return parts.join(' · ')\n}\n\nfunction newParamId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') return crypto.randomUUID()\n return `p${Date.now().toString(36)}${Math.floor(Math.random() * 1e6).toString(36)}`\n}\n\n/** Parse the draft workflow into a plain object (empty on invalid JSON). */\nfunction parseDraftWorkflow(workflow: string | Record<string, unknown>): Record<string, unknown> {\n if (typeof workflow !== 'string') return workflow\n try {\n const parsed = JSON.parse(workflow) as unknown\n return typeof parsed === 'object' && parsed !== null ? (parsed as Record<string, unknown>) : {}\n } catch {\n return {}\n }\n}\n\n/**\n * Custom dropdown for loader-node file lists: each option shows a small\n * server-side thumbnail (images only; <select> cannot render images).\n */\nfunction UploadSelect(props: {\n value: string\n options: Array<string | number>\n kind: 'image' | 'video' | 'audio'\n onChange: (value: string) => void\n onRefresh?: () => Promise<Array<string | number> | undefined>\n}): ReturnType<typeof h> {\n const [open, setOpen] = useState(false)\n const [live, setLive] = useState<Array<string | number> | null>(null)\n const ref = useRef<HTMLDivElement | null>(null)\n // Keep the latest refresh callback without re-running the open-effect.\n const refreshRef = useRef(props.onRefresh)\n refreshRef.current = props.onRefresh\n\n useEffect(() => {\n if (!open) return\n const onDoc = (event: MouseEvent): void => {\n if (ref.current !== null && !ref.current.contains(event.target as Node)) setOpen(false)\n }\n document.addEventListener('mousedown', onDoc)\n return () => document.removeEventListener('mousedown', onDoc)\n }, [open])\n\n // Pull the live file list from the server every time the menu opens, so\n // files uploaded elsewhere show up without reloading the workflow editor.\n useEffect(() => {\n if (!open) return\n const fn = refreshRef.current\n if (fn === undefined) return\n let cancelled = false\n void fn().then((latest) => {\n if (!cancelled && latest !== undefined) setLive(latest)\n })\n return () => { cancelled = true }\n }, [open])\n\n const options = live ?? props.options\n const thumbUrl = (name: string | number): string | null =>\n props.kind === 'image' ? `/comfyui/media?file=${encodeURIComponent(String(name))}&type=input` : null\n const current = options.some((option) => String(option) === props.value) ? props.value : String(props.value)\n\n return h('div', { ref, className: 'dsc-upload-select' },\n h('button', {\n className: 'dsc-upload-select-btn',\n onClick: () => setOpen(!open),\n title: String(current),\n },\n thumbUrl(props.value) !== null\n ? h('img', { className: 'dsc-upload-select-thumb', src: thumbUrl(props.value) ?? '', alt: '', loading: 'lazy' })\n : null,\n h('span', { className: 'dsc-upload-select-name' }, String(current)),\n ),\n open\n ? h('div', { className: 'dsc-upload-select-pop' },\n options.map((option) => {\n const name = String(option)\n return h('div', {\n key: name,\n className: `dsc-upload-select-item${name === props.value ? ' dsc-upload-select-item--active' : ''}`,\n onClick: () => { props.onChange(name); setOpen(false) },\n },\n thumbUrl(option) !== null\n ? h('img', { className: 'dsc-upload-select-thumb', src: thumbUrl(option) ?? '', alt: '', loading: 'lazy' })\n : null,\n h('span', { className: 'dsc-upload-select-name' }, name),\n )\n }),\n )\n : null,\n )\n}\n\n/** Merge a freshly fetched option list with the previous one (latest first,\n * deduped) so the dropdown never drops options mid-session. */\nfunction mergeOptions(prev: Array<string | number>, latest: Array<string | number>): Array<string | number> {\n const seen = new Set<string>()\n const out: Array<string | number> = []\n for (const item of [...latest, ...prev]) {\n const key = String(item)\n if (!seen.has(key)) { seen.add(key); out.push(item) }\n }\n return out\n}\n\n/** Copy text to the clipboard; falls back to a hidden textarea when the\n * clipboard API is unavailable (non-secure LAN http). */\nfunction copyText(text: string): Promise<boolean> {\n if (navigator.clipboard !== undefined) {\n return navigator.clipboard.writeText(text).then(() => true).catch(() => copyViaTextarea(text))\n }\n return Promise.resolve(copyViaTextarea(text))\n}\n\nfunction copyViaTextarea(text: string): boolean {\n const textarea = document.createElement('textarea')\n textarea.value = text\n textarea.style.position = 'fixed'\n textarea.style.opacity = '0'\n document.body.appendChild(textarea)\n textarea.select()\n let ok = false\n try {\n ok = document.execCommand('copy')\n } catch {\n ok = false\n }\n document.body.removeChild(textarea)\n return ok\n}\n\n/** Read a file's pixel size in the browser (image only) and report it to the\n * plugin so the workflow output size can default to the source image. Returns\n * the size text for display, or undefined when unreadable. */\nasync function recordMediaSize(file: File, name: string): Promise<string | undefined> {\n try {\n const bitmap = await createImageBitmap(file)\n const width = bitmap.width\n const height = bitmap.height\n bitmap.close()\n await fetch('/comfyui/media-size', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name, width, height }),\n }).catch(() => undefined)\n return `${width}×${height}`\n } catch {\n return undefined\n }\n}\n\n/** SHA-256 hex digest (pure JS — crypto.subtle needs a secure context, which a\n * LAN http origin is not). Uses the standard padding/compression; the input is\n * any byte array. */\nfunction sha256Hex(data: Uint8Array): string {\n const K = new Uint32Array([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n ])\n const H = new Uint32Array([0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19])\n const len = data.length\n const total = len + 1 + (((56 - ((len + 1) % 64)) + 64) % 64) + 8\n const msg = new Uint8Array(total)\n msg.set(data)\n msg[len] = 0x80\n const bitLenLo = (len * 8) >>> 0\n const bitLenHi = Math.floor(len / 0x20000000)\n const dv = new DataView(msg.buffer)\n dv.setUint32(total - 8, bitLenHi)\n dv.setUint32(total - 4, bitLenLo)\n const w = new Uint32Array(64)\n for (let offset = 0; offset < total; offset += 64) {\n for (let i = 0; i < 16; i++) w[i] = dv.getUint32(offset + i * 4)\n for (let i = 16; i < 64; i++) {\n const s0 = ((w[i - 15]! >>> 7) | (w[i - 15]! << 25)) ^ ((w[i - 15]! >>> 18) | (w[i - 15]! << 14)) ^ (w[i - 15]! >>> 3)\n const s1 = ((w[i - 2]! >>> 17) | (w[i - 2]! << 15)) ^ ((w[i - 2]! >>> 19) | (w[i - 2]! << 13)) ^ (w[i - 2]! >>> 10)\n w[i] = (w[i - 16]! + s0 + w[i - 7]! + s1) >>> 0\n }\n let a = H[0]!, b = H[1]!, c = H[2]!, d = H[3]!, e = H[4]!, f = H[5]!, g = H[6]!, h = H[7]!\n for (let i = 0; i < 64; i++) {\n const S1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7))\n const ch = (e & f) ^ (~e & g)\n const temp1 = (h + S1 + ch + K[i]! + w[i]!) >>> 0\n const S0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10))\n const maj = (a & b) ^ (a & c) ^ (b & c)\n const temp2 = (S0 + maj) >>> 0\n h = g; g = f; f = e; e = (d + temp1) >>> 0; d = c; c = b; b = a; a = (temp1 + temp2) >>> 0\n }\n H[0] = (H[0]! + a) >>> 0; H[1] = (H[1]! + b) >>> 0; H[2] = (H[2]! + c) >>> 0; H[3] = (H[3]! + d) >>> 0\n H[4] = (H[4]! + e) >>> 0; H[5] = (H[5]! + f) >>> 0; H[6] = (H[6]! + g) >>> 0; H[7] = (H[7]! + h) >>> 0\n }\n let out = ''\n for (let i = 0; i < 8; i++) out += H[i]!.toString(16).padStart(8, '0')\n return out\n}\n\n/** `image.png` + hash → `image_3f9a2b1c0d.png`: keeps the name readable while\n * making it content-unique, so re-uploading the same file reuses the name. */\nfunction renameWithHash(original: string, hash: string): string {\n const short = hash.slice(0, 10)\n const dot = original.lastIndexOf('.')\n const base = dot > 0 ? original.slice(0, dot) : original\n const ext = dot > 0 ? original.slice(dot) : ''\n return `${base}_${short}${ext}`\n}\n\n/** Upload a file with content-hash naming and dedup: same bytes → same file\n * name, and (for root uploads) the existing file is reused instead of creating\n * a duplicate. Returns the file name on the ComfyUI server. */\nasync function uploadDedup(file: File, subfolder?: string): Promise<string> {\n const hash = sha256Hex(new Uint8Array(await file.arrayBuffer()))\n const dedup = subfolder === undefined || subfolder === ''\n if (dedup) {\n const lookup = await fetch('/comfyui/media-lookup', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ hash }),\n }).then((response) => response.json() as Promise<{ ok?: boolean; found?: boolean; name?: string }>).catch(() => undefined)\n if (lookup !== undefined && lookup.ok === true && lookup.found === true && typeof lookup.name === 'string') {\n return lookup.name\n }\n }\n const renamed = new File([file], renameWithHash(file.name, hash), { type: file.type })\n const form = new FormData()\n form.append('image', renamed)\n if (!dedup) form.append('subfolder', subfolder)\n const response = await fetch('/comfyui/upload', { method: 'POST', body: form })\n const data = (await response.json()) as { ok?: boolean; name?: string; error?: string }\n if (data.ok !== true || typeof data.name !== 'string') throw new Error(data.error ?? 'upload failed')\n if (dedup) {\n await fetch('/comfyui/media-hash', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ hash, name: data.name }),\n }).catch(() => undefined)\n }\n return data.name\n}\n\n/**\n * Parameter editor: lists the workflow's adjustable parameters (auto-detected\n * prompt/size/steps/seed) with editable name/label/default and a random\n * toggle for number parameters, plus an \"advanced\" picker that exposes any\n * node input as a custom parameter.\n */\nfunction ParameterEditor(props: {\n t: ComfyUIPanelProps['t']\n params: WorkflowParameter[]\n workflow: Record<string, unknown>\n onChange: (params: WorkflowParameter[]) => void\n}): ReturnType<typeof h> {\n const { t, params, workflow, onChange } = props\n const [advanced, setAdvanced] = useState(false)\n const [advNode, setAdvNode] = useState('')\n const [advInput, setAdvInput] = useState('')\n const [advLabel, setAdvLabel] = useState('')\n const [recognizing, setRecognizing] = useState(false)\n const [recognizeError, setRecognizeError] = useState<string | null>(null)\n const [uploading, setUploading] = useState<Record<string, boolean>>({})\n // Raw text of number fields while they are being typed. Parsing on every\n // keystroke would swallow an in-progress decimal (\"1.\" → 1), which is what\n // used to make float defaults impossible to enter.\n const [numDraft, setNumDraft] = useState<Record<string, string>>({})\n const [hovered, setHovered] = useState<string | null>(null)\n // Latest params/uploadFile for the global paste listener (bound once).\n const hoverRef = useRef<string | null>(null)\n const latestRef = useRef<{ params: WorkflowParameter[]; uploadFile: (param: WorkflowParameter, file: File) => Promise<void> }>({\n params,\n uploadFile: async () => undefined,\n })\n\n /** Re-fetch a parameter's live option list (ComfyUI input dir files) and\n * merge it into the stored options, so uploads made anywhere show up in the\n * dropdown without reloading the workflow editor. */\n const refreshOptions = async (param: WorkflowParameter): Promise<Array<string | number> | undefined> => {\n const rawNode = (workflow as Record<string, { class_type?: string }>)[param.nodeId]\n const classType = typeof rawNode?.class_type === 'string' ? rawNode.class_type : ''\n if (classType === '') return undefined\n const result = (await postJson('/comfyui/workflows/input-options', { classType, inputKey: param.inputKey })) as\n { ok?: boolean; options?: Array<string | number> }\n if (result.ok !== true || !Array.isArray(result.options)) return undefined\n const latest = result.options\n const index = params.findIndex((entry) => entry.id === param.id)\n if (index !== -1 && params[index]?.options !== undefined) {\n update(index, { options: mergeOptions(params[index]!.options!, latest) })\n }\n return latest\n }\n\n /** Upload a dropped file through the plugin proxy into ComfyUI's input dir. */\n const uploadFile = async (param: WorkflowParameter, file: File): Promise<void> => {\n setUploading((prev) => ({ ...prev, [param.id]: true }))\n try {\n const name = await uploadDedup(file, param.subfolder)\n void recordMediaSize(file, name)\n const index = params.findIndex((entry) => entry.id === param.id)\n if (index !== -1) update(index, { default: name })\n void refreshOptions(param)\n } finally {\n setUploading((prev) => ({ ...prev, [param.id]: false }))\n }\n }\n latestRef.current = { params, uploadFile }\n\n /** Global paste: Ctrl+V with the mouse hovering an upload parameter routes\n * the clipboard file (e.g. a screenshot) to that parameter — same mental\n * model as pasting an image into a chat input. */\n useEffect(() => {\n const onPaste = (event: ClipboardEvent): void => {\n const targetId = hoverRef.current\n if (targetId === null) return\n const file = event.clipboardData?.files?.[0]\n if (file === undefined) return\n const param = latestRef.current.params.find((entry) => entry.id === targetId)\n if (param === undefined || param.upload === undefined) return\n event.preventDefault()\n void latestRef.current.uploadFile(param, file)\n }\n document.addEventListener('paste', onPaste)\n return () => document.removeEventListener('paste', onPaste)\n }, [])\n\n /** Auto-generate the internal parameter name from the input key, deduped against existing params. */\n const genParamName = (base: string): string => {\n let name = base\n let index = 2\n while (params.some((param) => param.name === name)) name = `${base}_${index++}`\n return name\n }\n\n const nodeEntries = Object.entries(workflow).map(([id, raw]) => [id, raw as { class_type?: string; inputs?: Record<string, unknown> }] as const)\n const advNodeInfo = nodeEntries.find(([id]) => id === advNode)?.[1]\n // Widget-valued inputs are offered without filtering (the loader `upload`\n // pseudo-input included). Inputs currently fed by a link ([nodeId, slot])\n // are left out: they carry no value to edit, and exposing one only creates\n // a parameter that would fight the connection.\n const advInputs = advNodeInfo !== undefined && advNodeInfo.inputs !== undefined\n ? Object.entries(advNodeInfo.inputs).filter(([, value]) => !isLinkValue(value))\n : []\n const selectedInput = advInputs.find(([key]) => key === advInput)\n\n /** Server-side auto-detection: prompt/size/steps/seed + dropdown options (object_info). */\n const recognize = async (): Promise<void> => {\n if (recognizing) return\n setRecognizing(true)\n setRecognizeError(null)\n try {\n const result = (await postJson('/comfyui/workflows/recognize', { workflow })) as { ok?: boolean; parameters?: WorkflowParameter[]; error?: string }\n if (result.ok === true && Array.isArray(result.parameters)) {\n onChange(result.parameters)\n setAdvanced(false)\n } else {\n setRecognizeError(result.error ?? t('wfParamsRecognizeFailed'))\n }\n } catch {\n setRecognizeError(t('wfParamsRecognizeFailed'))\n } finally {\n setRecognizing(false)\n }\n }\n\n const update = (index: number, patch: Partial<WorkflowParameter>): void => {\n onChange(params.map((param, i) => (i === index ? { ...param, ...patch } : param)))\n }\n\n const addAdvanced = async (): Promise<void> => {\n if (advNode === '' || advInput === '' || selectedInput === undefined || advNodeInfo === undefined) return\n const [, value] = selectedInput\n // A linked or object-valued input has no widget value to start from: it\n // becomes a string parameter with an empty default, which the run path\n // reads as \"leave the link alone unless a value is passed\".\n const type = typeof value === 'number' ? 'number' : typeof value === 'boolean' ? 'boolean' : 'string'\n\n // Generic media-list heuristic: a string holding a JSON array of\n // {kind, file, ...} items (e.g. MiniMaxH3 media_state) becomes one\n // reference-slot parameter per item. Detection is shape-based, never\n // class-specific.\n const existingMedia = params.some((param) => param.nodeId === advNode && param.inputKey === advInput && param.upload === 'media')\n if (!existingMedia && typeof value === 'string') {\n let parsed: unknown\n try {\n parsed = JSON.parse(value) as unknown\n } catch {\n parsed = undefined\n }\n if (Array.isArray(parsed) && parsed.length > 0\n && parsed.every((item) => typeof item === 'object' && item !== null && typeof (item as { file?: unknown }).file === 'string')) {\n const items = parsed as Array<{ name?: unknown; file?: unknown }>\n const firstFile = items[0]?.file\n const slash = typeof firstFile === 'string' ? firstFile.indexOf('/') : -1\n const subfolder = typeof firstFile === 'string' && slash > 0 ? firstFile.slice(0, slash) : undefined\n const added: WorkflowParameter[] = items.map((item, i) => ({\n id: newParamId(),\n name: genParamName(`media_${i + 1}`),\n label: `${t('wfRefSlot')}${i + 1}`,\n type: 'string',\n nodeId: advNode,\n inputKey: advInput,\n default: typeof item.name === 'string' ? item.name : '',\n upload: 'media',\n subfolder,\n }))\n onChange([...params, ...added])\n setAdvanced(false)\n setAdvNode('')\n setAdvInput('')\n setAdvLabel('')\n return\n }\n }\n\n // Ask the server for the node's dropdown options (object_info combos) and\n // whether this input is a loader file picker (upload kind).\n let options: Array<string | number> | undefined\n let upload: WorkflowParameter['upload']\n let numberSpec: { kind?: 'int' | 'float'; min?: number; max?: number; step?: number } | undefined\n if (typeof advNodeInfo.class_type === 'string') {\n try {\n const result = (await postJson('/comfyui/workflows/input-options', { classType: advNodeInfo.class_type, inputKey: advInput })) as {\n ok?: boolean\n options?: Array<string | number>\n upload?: 'image' | 'video' | 'audio'\n number?: { kind?: 'int' | 'float'; min?: number; max?: number; step?: number }\n }\n if (result.ok === true && Array.isArray(result.options) && result.options.length > 0) options = result.options\n upload = result.upload\n numberSpec = result.number\n } catch {\n // options and the numeric type are a nice-to-have; fall back to free text\n }\n }\n onChange([...params, {\n id: newParamId(),\n name: genParamName(advInput),\n label: advLabel !== '' ? advLabel : `${advNode} · ${advInput}`,\n type,\n nodeId: advNode,\n inputKey: advInput,\n default: typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' ? value : '',\n numberKind: type === 'number' ? numberSpec?.kind : undefined,\n min: type === 'number' ? numberSpec?.min : undefined,\n max: type === 'number' ? numberSpec?.max : undefined,\n step: type === 'number' ? numberSpec?.step : undefined,\n options,\n upload,\n }])\n setAdvanced(false)\n setAdvNode('')\n setAdvInput('')\n setAdvLabel('')\n }\n\n /** Update a parameter's default; DynamicCombo parents refresh their child (size) parameter. */\n const updateDefault = (index: number, value: string | number | boolean): void => {\n update(index, { default: value })\n const param = params[index]\n if (param === undefined || typeof value !== 'string') return\n if (param.options === undefined || param.options.length === 0) return\n // Child parameter key is \"<parent>.<child>\" on the same node (e.g. aspect_ratio.size).\n const childIndex = params.findIndex((entry) => entry.nodeId === param.nodeId && entry.inputKey.startsWith(`${param.inputKey}.`))\n if (childIndex === -1) return\n const child = params[childIndex]\n if (child === undefined) return\n const rawNode = (workflow as Record<string, { class_type?: string }>)[child.nodeId]\n const classType = typeof rawNode?.class_type === 'string' ? rawNode.class_type : ''\n void postJson('/comfyui/workflows/input-options', { classType, inputKey: param.inputKey, parentValue: value })\n .then((result) => {\n const data = result as { ok?: boolean; child?: { childInputKey: string; options: Array<string | number>; default: string } }\n if (data.ok === true && data.child !== undefined && childIndex < params.length) {\n update(childIndex, { options: data.child.options, default: data.child.default })\n }\n })\n .catch(() => undefined)\n }\n\n return h('div', { className: 'dsc-params' },\n params.length === 0\n ? h('div', { className: 'dsc-hint' }, t('wfParamsEmpty'))\n : h('div', { className: 'dsc-list' }, params.map((param, index) => h('div', { key: param.id, className: 'dsc-param-row' },\n h('div', { className: 'dsc-param-fields' },\n h('input', {\n className: 'dsc-input dsc-input--sm',\n value: param.label,\n placeholder: t('wfParamLabel'),\n onChange: (event: { target: { value: string } }) => update(index, { label: event.target.value }),\n }),\n ),\n param.upload === 'media'\n ? h('div', {\n className: 'dsc-param-upload-wrap',\n onMouseEnter: () => { hoverRef.current = param.id; setHovered(param.id) },\n onMouseLeave: () => { hoverRef.current = null; setHovered(null) },\n },\n h('input', {\n className: 'dsc-input dsc-input--sm dsc-param-default',\n value: String(param.default),\n placeholder: t('wfMediaEmpty'),\n title: `${param.subfolder ?? ''}/`,\n onChange: (event: { target: { value: string } }) => updateDefault(index, event.target.value),\n }),\n h('label', {\n className: hovered === param.id ? 'dsc-dropzone dsc-dropzone--over' : 'dsc-dropzone',\n title: t('wfPasteHint'),\n tabIndex: 0,\n onDragOver: (event: { preventDefault: () => void }) => event.preventDefault(),\n onDrop: (event: { preventDefault: () => void; dataTransfer?: { files?: File[] } }) => {\n event.preventDefault()\n const file = event.dataTransfer?.files?.[0]\n if (file !== undefined) void uploadFile(param, file)\n },\n onPaste: (event: { clipboardData?: { files?: File[] } }) => {\n const file = event.clipboardData?.files?.[0]\n if (file !== undefined) void uploadFile(param, file)\n },\n },\n h('input', {\n type: 'file',\n style: { display: 'none' },\n onChange: (event: { target: HTMLInputElement }) => {\n const file = event.target.files?.[0]\n if (file !== undefined) void uploadFile(param, file)\n event.target.value = ''\n },\n }),\n uploading[param.id] === true ? t('wfParamsUploading') : t('wfParamsDrop'),\n ),\n h('button', { className: 'dsc-btn', onClick: () => updateDefault(index, '') }, t('wfMediaClear')),\n )\n : param.upload !== undefined\n ? h('div', {\n className: 'dsc-param-upload-wrap',\n onMouseEnter: () => { hoverRef.current = param.id; setHovered(param.id) },\n onMouseLeave: () => { hoverRef.current = null; setHovered(null) },\n },\n param.options !== undefined && param.options.length > 0\n ? h(UploadSelect, {\n value: String(param.default),\n options: param.options,\n kind: param.upload,\n onChange: (value: string) => updateDefault(index, value),\n onRefresh: () => refreshOptions(param),\n })\n : null,\n h('label', {\n className: hovered === param.id ? 'dsc-dropzone dsc-dropzone--over' : 'dsc-dropzone',\n title: t('wfPasteHint'),\n tabIndex: 0,\n onDragOver: (event: { preventDefault: () => void }) => event.preventDefault(),\n onDrop: (event: { preventDefault: () => void; dataTransfer?: { files?: File[] } }) => {\n event.preventDefault()\n const file = event.dataTransfer?.files?.[0]\n if (file !== undefined) void uploadFile(param, file)\n },\n onPaste: (event: { clipboardData?: { files?: File[] } }) => {\n const file = event.clipboardData?.files?.[0]\n if (file !== undefined) void uploadFile(param, file)\n },\n },\n h('input', {\n type: 'file',\n style: { display: 'none' },\n onChange: (event: { target: HTMLInputElement }) => {\n const file = event.target.files?.[0]\n if (file !== undefined) void uploadFile(param, file)\n event.target.value = ''\n },\n }),\n uploading[param.id] === true ? t('wfParamsUploading') : `${t('wfParamsDrop')} ${t(`uploadKind_${param.upload}`)}`,\n ),\n )\n : (param.options !== undefined && param.options.length > 0)\n ? h('select', {\n className: 'dsc-input dsc-input--sm dsc-param-default',\n value: String(param.default),\n onChange: (event: { target: { value: string } }) => updateDefault(index, event.target.value),\n },\n param.options.map((option) => h('option', { key: String(option), value: String(option) }, String(option))),\n )\n : param.type === 'string'\n ? h('textarea', {\n className: 'dsc-input dsc-param-default',\n rows: 2,\n value: String(param.default),\n placeholder: t('wfParamDefault'),\n onChange: (event: { target: { value: string } }) => updateDefault(index, event.target.value),\n })\n : param.type === 'boolean'\n ? h('label', { className: 'dsc-param-bool dsc-param-default' },\n h('input', {\n type: 'checkbox',\n checked: asBool(param.default),\n onChange: (event: { target: { checked: boolean } }) => updateDefault(index, event.target.checked),\n }),\n h('span', null, asBool(param.default) ? 'true' : 'false'),\n )\n : param.type === 'number'\n ? h('input', {\n className: 'dsc-input dsc-input--sm dsc-param-default',\n inputMode: param.numberKind === 'int' ? 'numeric' : 'decimal',\n value: numDraft[param.id] ?? String(param.default),\n placeholder: t('wfParamDefault'),\n title: numberRangeHint(param),\n onChange: (event: { target: { value: string } }) => {\n const raw = event.target.value\n setNumDraft((prev) => ({ ...prev, [param.id]: raw }))\n const parsed = Number(raw)\n if (raw.trim() !== '' && Number.isFinite(parsed)) updateDefault(index, parsed)\n },\n onBlur: () => {\n // Commit: an int input rounds, an empty/garbled field falls\n // back to 0, and the draft is dropped so the stored value\n // shows through again.\n const raw = numDraft[param.id]\n setNumDraft((prev) => {\n const next = { ...prev }\n delete next[param.id]\n return next\n })\n if (raw === undefined) return\n const parsed = Number(raw)\n const value = raw.trim() === '' || !Number.isFinite(parsed) ? 0 : parsed\n updateDefault(index, param.numberKind === 'int' ? Math.round(value) : value)\n },\n })\n : h('input', {\n className: 'dsc-input dsc-input--sm dsc-param-default',\n value: String(param.default),\n placeholder: t('wfParamDefault'),\n onChange: (event: { target: { value: string } }) => updateDefault(index, event.target.value),\n }),\n h('div', { className: 'dsc-param-meta' },\n h('span', { className: 'dsc-meta' }, `${param.type}${param.type === 'number' ? `/${param.numberKind ?? '?'}` : ''} · #${param.nodeId}.${param.inputKey}`),\n param.type === 'number'\n ? h('label', { className: 'dsc-param-random' },\n h('input', {\n type: 'checkbox',\n checked: param.random === true,\n onChange: (event: { target: { checked: boolean } }) => update(index, { random: event.target.checked }),\n }),\n h('span', null, t('wfParamRandom')),\n )\n : null,\n h('button', { className: 'dsc-btn', onClick: () => onChange(params.filter((_, i) => i !== index)) }, t('wfParamDelete')),\n ),\n ))),\n h('div', { className: 'dsc-toolbar' },\n h('button', { className: 'dsc-btn', disabled: recognizing, onClick: () => { void recognize() } }, recognizing ? t('wfParamsRecognizing') : t('wfParamsRecognize')),\n h('button', { className: 'dsc-btn', onClick: () => setAdvanced(!advanced) }, t('wfParamsAdd')),\n ),\n recognizeError !== null ? h('div', { className: 'dsc-hint dsc-hint--error' }, recognizeError) : null,\n advanced\n ? h('div', { className: 'dsc-param-advanced' },\n h('div', { className: 'dsc-param-fields' },\n h('select', {\n className: 'dsc-input dsc-input--sm',\n value: advNode,\n onChange: (event: { target: { value: string } }) => { setAdvNode(event.target.value); setAdvInput('') },\n },\n h('option', { value: '' }, '—'),\n nodeEntries.map(([id, node]) => h('option', { key: id, value: id }, `#${id} ${node.class_type ?? ''}`)),\n ),\n advNodeInfo !== undefined\n ? h('select', {\n className: 'dsc-input dsc-input--sm',\n value: advInput,\n onChange: (event: { target: { value: string } }) => setAdvInput(event.target.value),\n },\n h('option', { value: '' }, '—'),\n advInputs.map(([key, value]) => h('option', { key, value: key }, `${key} (${inputValueKind(value)})`)),\n )\n : null,\n h('input', {\n className: 'dsc-input dsc-input--sm',\n value: advLabel,\n placeholder: t('wfParamCustomLabel'),\n onChange: (event: { target: { value: string } }) => setAdvLabel(event.target.value),\n }),\n h('button', { className: 'dsc-btn', disabled: advNode === '' || advInput === '', onClick: () => { void addAdvanced() } }, t('wfParamAdd')),\n ),\n h('div', { className: 'dsc-hint' }, t('wfParamCustomHint')),\n )\n : null,\n )\n}\n\nfunction formatTs(ts: string): string {\n const date = new Date(ts)\n return Number.isNaN(date.getTime()) ? ts : date.toLocaleString()\n}\n\nfunction formatBytes(bytes: number | undefined): string {\n if (bytes === undefined) return ''\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(2)} MB`\n}\n\n/** The panel shell: header (drag handle), tabs, and the active tab body. */\nexport function ComfyUIPanel({ t }: ComfyUIPanelProps): ReturnType<typeof h> | null {\n const open = usePanelOpen()\n const tab = usePanelTab()\n const [geom, setGeom] = useState<PanelGeom>(() => healGeom(loadGeom(), window.innerWidth, window.innerHeight))\n const [dragging, setDragging] = useState<'move' | 'resize' | null>(null)\n const [lightbox, setLightbox] = useState<{ images: string[]; kinds: Array<'image' | 'video' | 'audio' | 'other'>; index: number } | null>(null)\n const panelRef = useRef<HTMLDivElement | null>(null)\n const dragRef = useRef<{ startX: number; startY: number; origX: number; origY: number; width: number; height: number } | null>(null)\n\n const openPreview = (images: string[], kinds: Array<'image' | 'video' | 'audio' | 'other'>, index: number): void => setLightbox({ images, kinds, index })\n\n useEffect(() => {\n if (open) {\n // The window may have been resized or moved to another monitor while the\n // panel was closed, or the saved position may predate the reachability\n // clamp — snap a header that ended up out of reach back into the viewport.\n setGeom((prev) => healGeom(prev, window.innerWidth, window.innerHeight))\n return\n }\n saveGeom(geom)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open])\n\n // While the panel is open, keep the header reachable across viewport\n // resizes too (shrinking the window can otherwise strand it off-screen).\n useEffect(() => {\n if (!open) return\n const onResize = (): void => setGeom((prev) => healGeom(prev, window.innerWidth, window.innerHeight))\n window.addEventListener('resize', onResize)\n return () => window.removeEventListener('resize', onResize)\n }, [open])\n\n const startDrag = (event: PointerEventLike, mode: 'move' | 'resize'): void => {\n if (event.button !== 0) return\n if (mode === 'move') {\n const target = event.target as HTMLElement | null\n if (target !== null && target.closest('button, input, textarea, select, a, label')) return\n }\n const rect = panelRef.current?.getBoundingClientRect()\n if (rect === undefined) return\n dragRef.current = {\n startX: event.clientX, startY: event.clientY,\n origX: rect.left, origY: rect.top, width: rect.width, height: rect.height,\n }\n setDragging(mode)\n const el = event.currentTarget as HTMLElement | null\n if (el !== null && typeof el.setPointerCapture === 'function') el.setPointerCapture(event.pointerId)\n }\n\n const moveDrag = (event: PointerEventLike): void => {\n const d = dragRef.current\n if (d === null) return\n if (dragging === 'move') {\n // Clamp while dragging so the header can never be pushed out of reach.\n const pos = clampPos(\n Math.round(d.origX + event.clientX - d.startX),\n Math.round(d.origY + event.clientY - d.startY),\n d.width,\n window.innerWidth,\n window.innerHeight,\n )\n setGeom((prev) => ({ ...prev, x: pos.x, y: pos.y }))\n } else if (dragging === 'resize') {\n const width = Math.max(300, Math.min(720, d.width + event.clientX - d.startX))\n const height = Math.max(200, Math.min(Math.max(300, window.innerHeight - 40), d.height + event.clientY - d.startY))\n setGeom((prev) => ({ ...prev, width, height }))\n }\n }\n\n const endDrag = (): void => {\n if (dragRef.current === null) return\n dragRef.current = null\n setDragging(null)\n setGeom((prev) => {\n saveGeom(prev)\n return prev\n })\n }\n\n if (!open) return null\n\n const panelStyle: Record<string, string> = {}\n if (geom.x !== undefined && geom.y !== undefined) {\n panelStyle.left = `${geom.x}px`\n panelStyle.top = `${geom.y}px`\n panelStyle.right = 'auto'\n panelStyle.bottom = 'auto'\n }\n if (geom.width !== undefined) panelStyle.width = `${geom.width}px`\n if (geom.height !== undefined) panelStyle.height = `${geom.height}px`\n\n return h('div',\n { ref: panelRef, className: `dsc-panel${dragging !== null ? ' dsc-panel--dragging' : ''}`, style: panelStyle },\n h('div', {\n className: 'dsc-panel-head',\n onPointerDown: (event: PointerEventLike) => startDrag(event, 'move'),\n onPointerMove: (event: PointerEventLike) => moveDrag(event),\n onPointerUp: () => endDrag(),\n onPointerCancel: () => endDrag(),\n },\n h('span', { className: 'dsc-panel-title' },\n h('span', { className: 'dsc-trigger-glyph' }, h(ComfyUIIcon)),\n h('span', null, t('panelTitle')),\n ),\n h('span', { className: 'dsc-panel-head-actions' },\n h('button', {\n className: 'dsc-panel-reset',\n type: 'button',\n title: t('panelReset'),\n 'aria-label': t('panelReset'),\n onClick: () => {\n // Restore the CSS-anchored default (right side, 400px wide) and\n // clear the stored geometry so the default also survives refresh.\n setGeom({})\n try {\n localStorage.removeItem(GEOM_KEY)\n } catch {\n // storage unavailable — nothing persisted anyway\n }\n },\n }, '↺'),\n h('button', {\n className: 'dsc-panel-close',\n 'aria-label': t('close'),\n onClick: () => panelStore.close(),\n }, '✕'),\n ),\n ),\n h('div', { className: 'dsc-tabs' },\n h(TabButton, { t, active: tab === 'workflows', label: t('tabWorkflows'), onClick: () => panelStore.setTab('workflows') }),\n h(TabButton, { t, active: tab === 'assets', label: t('tabAssets'), onClick: () => panelStore.setTab('assets') }),\n h(TabButton, { t, active: tab === 'queue', label: t('tabQueue'), onClick: () => panelStore.setTab('queue') }),\n ),\n h('div', { className: 'dsc-panel-body' },\n tab === 'workflows' ? h(WorkflowsTab, { t })\n : tab === 'assets' ? h(AssetsTab, { t, onPreview: openPreview })\n : h(QueueTab, { t, onPreview: openPreview }),\n ),\n lightbox !== null ? h(Lightbox, {\n t,\n images: lightbox.images,\n kinds: lightbox.kinds,\n index: lightbox.index,\n onClose: () => setLightbox(null),\n onIndex: (index: number) => setLightbox({ images: lightbox.images, kinds: lightbox.kinds, index }),\n }) : null,\n h('div', {\n className: 'dsc-panel-resize',\n onPointerDown: (event: PointerEventLike) => startDrag(event, 'resize'),\n onPointerMove: (event: PointerEventLike) => moveDrag(event),\n onPointerUp: () => endDrag(),\n onPointerCancel: () => endDrag(),\n }),\n )\n}\n\nfunction TabButton(props: { t: ComfyUIPanelProps['t']; active: boolean; label: string; onClick: () => void }): ReturnType<typeof h> {\n return h('button', {\n className: props.active ? 'dsc-tab dsc-tab--active' : 'dsc-tab',\n onClick: props.onClick,\n }, props.label)\n}\n\nfunction ErrorNote({ t, message }: { t: ComfyUIPanelProps['t']; message: string }): ReturnType<typeof h> {\n return h('div', { className: 'dsc-err' }, `${t('error')}: ${message}`)\n}\n\n/** Tab 1: workflow library — plugin library + ComfyUI-side saved workflows. */\n/** One selectable item in the load-area picker (mirrors the host response). */\ninterface LoadAreaFile {\n name: string\n kind: 'image' | 'video' | 'audio'\n url: string\n source: 'imported' | 'generated'\n ts?: string\n workflowName?: string | null\n width?: number\n height?: number\n}\n\n/** Load area at the bottom of the workflow library, modeled on the ComfyUI\n * LoadImage node — a list of **slots** rather than a single image.\n *\n * A lone slot stretches across the panel; from two slots on they share a\n * fixed width and wrap into rows. A slot is either filled with a file or\n * empty (added but not yet picked, or emptied through the picker's \"空\"\n * tile); the whole card is the pick button, and hovering reveals an × in the\n * corner that removes the slot. Filled slots feed the workflow's loader\n * parameters in order, so a run that takes two reference images picks up\n * slots 1 and 2 without the agent naming files. */\nfunction LoadArea(props: { t: ComfyUIPanelProps['t']; onNotice: (message: string) => void }): ReturnType<typeof h> {\n const [slots, setSlots] = useState<Array<LoadAreaFile | null>>([])\n const [files, setFiles] = useState<LoadAreaFile[]>([])\n /** Slot index the picker is currently filling; null = picker closed. */\n const [pickerFor, setPickerFor] = useState<number | null>(null)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const refresh = useCallback(async (): Promise<void> => {\n const data = (await fetch('/comfyui/loadarea').then((response) => response.json()).catch(() => undefined)) as\n { ok?: boolean; current?: LoadAreaFile | null; slots?: Array<LoadAreaFile | null>; files?: LoadAreaFile[] } | undefined\n if (data?.ok === true) {\n // `slots` is the current contract; `current` is the older single-image\n // payload, kept working so a stale client/server pair still shows something.\n setSlots(data.slots ?? (data.current !== null && data.current !== undefined ? [data.current] : []))\n setFiles(data.files ?? [])\n }\n }, [])\n\n useEffect(() => { void refresh() }, [refresh])\n\n const post = async (body: Record<string, unknown>): Promise<boolean> => {\n setBusy(true)\n setError(null)\n try {\n const response = await fetch('/comfyui/current-image', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n const data = (await response.json().catch(() => ({}))) as { ok?: boolean; error?: string }\n if (data.ok !== true) throw new Error(data.error ?? `HTTP ${response.status}`)\n await refresh()\n return true\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n return false\n } finally {\n setBusy(false)\n }\n }\n\n const upload = async (file: File): Promise<string> => {\n setBusy(true)\n setError(null)\n try {\n const name = await uploadDedup(file)\n const sizeText = await recordMediaSize(file, name)\n await refresh()\n props.onNotice(`${props.t('wfUploaded')}:${name}${sizeText !== undefined ? `(${sizeText})` : ''}`)\n return name\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n throw cause\n } finally {\n setBusy(false)\n }\n }\n\n const pick = async (file: LoadAreaFile): Promise<void> => {\n const index = pickerFor\n setPickerFor(null)\n const ok = await post({ name: file.name, kind: file.kind, source: file.source, ...(index !== null ? { index } : {}) })\n if (ok) props.onNotice(`${props.t('wfLoadPicked')}:${file.name}`)\n }\n\n /** \"+ 添加加载区\": opens a slot and goes straight to the picker for it, so\n * adding material is one gesture; closing the picker leaves the empty slot. */\n const addSlot = async (): Promise<void> => {\n const index = slots.length\n if (await post({ action: 'addSlot' })) setPickerFor(index)\n }\n\n const loaded = slots.filter((slot) => slot !== null).length\n\n return h('div', { className: 'dsc-loadarea' },\n h('div', { className: 'dsc-loadarea-head' },\n h('span', { className: 'dsc-loadarea-title' }, props.t('wfLoadArea')),\n h('span', { className: 'dsc-meta' }, slots.length === 0\n ? props.t('wfLoadEmpty')\n : props.t('wfLoadSummary', { slots: slots.length, loaded })),\n ),\n h('div', { className: 'dsc-loadslots' },\n slots.map((slot, index) => h(LoadSlot, {\n key: index,\n t: props.t,\n slot,\n index,\n busy,\n // A single slot fills the panel width; two or more share a fixed one.\n wide: slots.length === 1,\n onPick: () => setPickerFor(index),\n onRemove: () => { void post({ action: 'removeSlot', index }) },\n })),\n ),\n h('div', { className: 'dsc-toolbar' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => { void addSlot() } }, props.t('wfLoadAddSlot')),\n ),\n pickerFor !== null\n ? h(LoadPicker, {\n t: props.t,\n files,\n current: (pickerFor < slots.length ? slots[pickerFor]?.name : undefined) ?? null,\n onUpload: upload,\n onPick: pick,\n // First tile of the grid: empties the slot without removing it.\n onClear: () => { const index = pickerFor; setPickerFor(null); void post({ action: 'clear', index }) },\n onClose: () => setPickerFor(null),\n })\n : null,\n error !== null ? h('div', { className: 'dsc-hint dsc-hint--error' }, error) : null,\n )\n}\n\n/** One load-area slot card. The card is the pick button (empty slots show\n * \"加载位 N / 添加素材\"); the × in the corner, revealed on hover, removes the\n * slot. Emptying a slot without removing it is done from the picker's \"空\"\n * tile, so the card carries no button row of its own. */\nfunction LoadSlot(props: {\n t: ComfyUIPanelProps['t']\n slot: LoadAreaFile | null\n index: number\n busy: boolean\n wide: boolean\n onPick: () => void\n onRemove: () => void\n}): ReturnType<typeof h> {\n const { t, slot, index } = props\n const size = slot?.width !== undefined && slot.height !== undefined ? `(${slot.width}×${slot.height})` : ''\n return h('div', { className: props.wide ? 'dsc-loadslot dsc-loadslot--wide' : 'dsc-loadslot' },\n h('button', {\n className: 'dsc-loadslot-pick',\n onClick: props.onPick,\n disabled: props.busy,\n title: slot !== null ? slot.name : t('wfLoadHint'),\n },\n slot === null\n ? h('span', { className: 'dsc-loadslot-empty' },\n h('span', { className: 'dsc-loadslot-index' }, `${t('wfLoadSlotLabel')} ${index + 1}`),\n h('span', { className: 'dsc-loadslot-add' }, t('wfLoadAddMedia')),\n )\n : slot.kind === 'video'\n ? h('video', { className: 'dsc-loadslot-media', src: slot.url, preload: 'metadata', muted: true })\n : slot.kind === 'audio'\n ? h('span', { className: 'dsc-loadslot-empty' }, '♪')\n : h('img', { className: 'dsc-loadslot-media', src: slot.url, alt: '', loading: 'lazy' }),\n slot !== null ? h('span', { className: 'dsc-loadslot-name' }, `${slot.name}${size}`) : null,\n ),\n h('button', {\n className: 'dsc-loadslot-x',\n disabled: props.busy,\n title: t('wfLoadRemoveSlot'),\n 'aria-label': t('wfLoadRemoveSlot'),\n onClick: props.onRemove,\n }, '×'),\n )\n}\n\n/** The load-area picker dialog: tab bar (全部/已导入/已生成) with a\n * paste/click upload zone on the right, and a masonry image grid below. */\nfunction LoadPicker(props: {\n t: ComfyUIPanelProps['t']\n files: LoadAreaFile[]\n current: string | null\n onUpload: (file: File) => Promise<string>\n onPick: (file: LoadAreaFile) => Promise<void>\n /** Empty the slot this picker was opened for (first tile of the grid). */\n onClear?: () => void\n onClose: () => void\n}): ReturnType<typeof h> {\n const [tab, setTab] = useState<'all' | 'imported' | 'generated'>('all')\n const [type, setType] = useState<'all' | 'image' | 'video' | 'audio'>('all')\n const hoverRef = useRef(false)\n const [uploadFlash, setUploadFlash] = useState<string | null>(null)\n const [scrollTo, setScrollTo] = useState<string | null>(null)\n const cardRefs = useRef<Map<string, HTMLElement>>(new Map())\n const flashTimer = useRef<number | undefined>(undefined)\n\n useEffect(() => () => {\n if (flashTimer.current !== undefined) window.clearTimeout(flashTimer.current)\n }, [])\n\n useEffect(() => {\n const onPaste = (event: ClipboardEvent): void => {\n if (!hoverRef.current) return\n const file = event.clipboardData?.files?.[0]\n if (file === undefined) return\n event.preventDefault()\n void handleUpload(file)\n }\n document.addEventListener('paste', onPaste)\n return () => document.removeEventListener('paste', onPaste)\n })\n\n /** Upload, then flash a confirmation and scroll the grid to the new file. */\n const handleUpload = async (file: File): Promise<void> => {\n try {\n const name = await props.onUpload(file)\n setScrollTo(name)\n setUploadFlash(`${props.t('wfUploadedToast')}:${name}`)\n if (flashTimer.current !== undefined) window.clearTimeout(flashTimer.current)\n flashTimer.current = window.setTimeout(() => setUploadFlash(null), 2500)\n } catch {\n // LoadArea shows the upload error in its own area.\n }\n }\n\n const bySource = tab === 'all' ? props.files : props.files.filter((file) => file.source === tab)\n const filtered = type === 'all' ? bySource : bySource.filter((file) => file.kind === type)\n\n // After the refreshed file list renders, scroll the matching card into view.\n useEffect(() => {\n if (scrollTo === null) return\n let found: HTMLElement | undefined\n for (const [key, el] of cardRefs.current) {\n if (key.endsWith(`:${scrollTo}`)) { found = el; break }\n }\n if (found !== undefined) {\n found.scrollIntoView({ block: 'center', behavior: 'smooth' })\n setScrollTo(null)\n }\n }, [scrollTo, filtered])\n // Distribute into 3 vertical columns (round-robin) — a masonry look that\n // scrolls reliably, unlike CSS multi-column which balances columns to the\n // container height and never overflows.\n const columns: LoadAreaFile[][] = [[], [], []]\n filtered.forEach((file, index) => { columns[index % 3]!.push(file) })\n const tabs: Array<{ id: 'all' | 'imported' | 'generated'; label: string }> = [\n { id: 'all', label: props.t('wfTabAll') },\n { id: 'imported', label: props.t('wfTabImported') },\n { id: 'generated', label: props.t('wfTabGenerated') },\n ]\n const typeOptions: Array<{ id: 'all' | 'image' | 'video' | 'audio'; label: string }> = [\n { id: 'all', label: props.t('wfTypeAll') },\n { id: 'image', label: props.t('uploadKind_image') },\n { id: 'video', label: props.t('uploadKind_video') },\n { id: 'audio', label: props.t('uploadKind_audio') },\n ]\n\n return h('div', { className: 'dsc-picker-overlay', onClick: props.onClose },\n h('div', { className: 'dsc-picker', onClick: (event: { stopPropagation: () => void }) => event.stopPropagation() },\n h('div', { className: 'dsc-picker-bar' },\n h('div', { className: 'dsc-picker-tabs' },\n tabs.map((entry) => h('button', {\n key: entry.id,\n className: `dsc-picker-tab${tab === entry.id ? ' dsc-picker-tab--active' : ''}`,\n onClick: () => setTab(entry.id),\n }, entry.label)),\n ),\n h('label', {\n className: 'dsc-dropzone dsc-picker-upload',\n title: props.t('wfPasteHint'),\n onMouseEnter: () => { hoverRef.current = true },\n onMouseLeave: () => { hoverRef.current = false },\n onDragOver: (event: { preventDefault: () => void }) => event.preventDefault(),\n onDrop: (event: { preventDefault: () => void; dataTransfer?: { files?: File[] } }) => {\n event.preventDefault()\n const file = event.dataTransfer?.files?.[0]\n if (file !== undefined) void handleUpload(file)\n },\n },\n h('input', {\n type: 'file',\n style: { display: 'none' },\n onChange: (event: { target: HTMLInputElement }) => {\n const file = event.target.files?.[0]\n if (file !== undefined) void handleUpload(file)\n event.target.value = ''\n },\n }),\n props.t('wfPickerUpload'),\n ),\n h('select', {\n className: 'dsc-picker-type',\n value: type,\n onChange: (event: { target: { value: string } }) => setType(event.target.value as 'all' | 'image' | 'video' | 'audio'),\n }, typeOptions.map((option) => h('option', { key: option.id, value: option.id }, option.label))),\n ),\n filtered.length === 0 && props.onClear === undefined\n ? h('div', { className: 'dsc-picker-empty' }, props.t('wfLoadNoFiles'))\n : h('div', { className: 'dsc-picker-grid' },\n columns.map((column, columnIndex) => h('div', { key: columnIndex, className: 'dsc-picker-col' },\n // \"空\": clears the slot the picker was opened for, so a slot can be\n // emptied without deleting it.\n columnIndex === 0 && props.onClear !== undefined\n ? h('div', {\n className: `dsc-picker-card dsc-picker-card--none${props.current === null ? ' dsc-picker-card--active' : ''}`,\n role: 'button',\n tabIndex: 0,\n onClick: () => props.onClear?.(),\n onKeyDown: (event: { key: string; preventDefault: () => void }) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n props.onClear?.()\n }\n },\n title: props.t('wfLoadNoneHint'),\n },\n h('span', { className: 'dsc-picker-thumb dsc-picker-thumb--media' }, '∅'),\n h('span', { className: 'dsc-picker-name' }, props.t('wfLoadNone')),\n )\n : null,\n // A card is a div rather than a button: video/audio players are\n // interactive content and may not be nested inside a button, and\n // clicking their controls must not select the card.\n column.map((file) => h('div', {\n key: `${file.source}:${file.name}`,\n className: `dsc-picker-card${file.name === props.current ? ' dsc-picker-card--active' : ''}`,\n role: 'button',\n tabIndex: 0,\n onClick: () => { void props.onPick(file) },\n onKeyDown: (event: { key: string; preventDefault: () => void }) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n void props.onPick(file)\n }\n },\n title: file.name,\n ref: (el: HTMLElement | null): void => {\n if (el !== null) cardRefs.current.set(`${file.source}:${file.name}`, el)\n else cardRefs.current.delete(`${file.source}:${file.name}`)\n },\n },\n file.kind === 'image'\n ? h('img', { className: 'dsc-picker-thumb', src: file.url, alt: '', loading: 'lazy' })\n : file.kind === 'video'\n ? h('video', {\n className: 'dsc-picker-thumb dsc-picker-player',\n src: file.url,\n controls: true,\n preload: 'metadata',\n onClick: (event: { stopPropagation: () => void }) => event.stopPropagation(),\n })\n : h('audio', {\n className: 'dsc-picker-player dsc-picker-player--audio',\n src: file.url,\n controls: true,\n preload: 'metadata',\n onClick: (event: { stopPropagation: () => void }) => event.stopPropagation(),\n }),\n // On a video/audio card the player keeps its own clicks, so this\n // name row is the click target that picks the file — it is sized\n // accordingly.\n h('span', { className: 'dsc-picker-name' }, file.name),\n file.width !== undefined && file.height !== undefined\n ? h('span', { className: 'dsc-meta' }, `${file.width}×${file.height}`)\n : null,\n )),\n )),\n ),\n uploadFlash !== null ? h('div', { className: 'dsc-picker-toast' }, uploadFlash) : null,\n ),\n )\n}\n\n/** Tag editor: preset classification chips (图生图 etc.) toggle on/off, plus\n * free-form custom tags added with Enter and removed by clicking. */\nfunction TagEditor(props: {\n t: ComfyUIPanelProps['t']\n tags: string[]\n onChange: (tags: string[]) => void\n}): ReturnType<typeof h> {\n const [custom, setCustom] = useState('')\n\n const toggle = (tag: string): void => {\n props.onChange(props.tags.includes(tag) ? props.tags.filter((entry) => entry !== tag) : [...props.tags, tag])\n }\n\n const addCustom = (): void => {\n const tag = custom.trim()\n if (tag === '' || props.tags.includes(tag)) return\n props.onChange([...props.tags, tag])\n setCustom('')\n }\n\n const customTags = props.tags.filter((tag) => !PRESET_TAGS.includes(tag))\n\n return h('div', { className: 'dsc-tag-editor' },\n h('div', { className: 'dsc-tag-row' },\n PRESET_TAGS.map((tag) => h('button', {\n key: tag,\n className: `dsc-tag-chip${props.tags.includes(tag) ? ' dsc-tag-chip--active' : ''}`,\n onClick: () => toggle(tag),\n }, tag)),\n ),\n customTags.length > 0\n ? h('div', { className: 'dsc-tag-row' },\n customTags.map((tag) => h('button', {\n key: tag,\n className: 'dsc-tag-chip dsc-tag-chip--active',\n title: props.t('wfTagRemove'),\n onClick: () => toggle(tag),\n }, `✕ ${tag}`)),\n )\n : null,\n h('input', {\n className: 'dsc-input dsc-input--sm dsc-tag-input',\n value: custom,\n placeholder: props.t('wfTagAdd'),\n onChange: (event: { target: { value: string } }) => setCustom(event.target.value),\n onKeyDown: (event: { key: string; preventDefault: () => void }) => {\n if (event.key === 'Enter') { event.preventDefault(); addCustom() }\n },\n }),\n )\n}\n\n/**\n * The skill-pack editor for one workflow: attach/detach the pack, toggle the\n * run-time gate, and manage its files (SKILL.md plus references/ and scripts/).\n *\n * The pack is what `comfyui_workflow action: skill` hands the agent, so this\n * view is the only place its content is authored. Each file saves explicitly —\n * no autosave — because the model reads whatever is on disk the moment it asks.\n * SKILL.md is edited as a summary field plus a body: the `---` frontmatter that\n * carries the summary is composed on the host, never typed here.\n */\nfunction SkillPackEditor(props: {\n t: ComfyUIPanelProps['t']\n workflow: WorkflowEntry\n onBack: () => void\n onChanged: () => void\n}): ReturnType<typeof h> {\n const { t } = props\n const [pack, setPack] = useState<SkillPack | null>(null)\n const [enabled, setEnabled] = useState<boolean>(props.workflow.skillDir !== undefined)\n const [active, setActive] = useState<string>('SKILL.md')\n const [summary, setSummary] = useState<string>('')\n const [text, setText] = useState<string>('')\n const [dirty, setDirty] = useState<boolean>(false)\n const [pendingOpen, setPendingOpen] = useState<string | null>(null)\n const [creating, setCreating] = useState<{ bucket: string; name: string } | null>(null)\n const [creatingDir, setCreatingDir] = useState<string | null>(null)\n const [presetDirs, setPresetDirs] = useState<string[]>(SKILL_FALLBACK_DIRS)\n const [renaming, setRenaming] = useState<{ from: string; to: string } | null>(null)\n const [confirming, setConfirming] = useState<string | null>(null)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [notice, setNotice] = useState<string | null>(null)\n\n /** Load one file into the editor; SKILL.md arrives pre-split into summary + body. */\n const openFile = useCallback(async (path: string): Promise<void> => {\n // Images are shown, not edited: reading one as UTF-8 would only produce\n // garbage in the textarea.\n if (isSkillImage(path)) {\n setActive(path)\n setSummary('')\n setText('')\n setDirty(false)\n setError(null)\n return\n }\n try {\n const data = await getJson<{ ok?: boolean; content?: string; summary?: string; body?: string; error?: string }>(\n `/comfyui/workflows/skill?id=${encodeURIComponent(props.workflow.id)}&path=${encodeURIComponent(path)}`,\n )\n if (data.ok !== true) {\n setError(data.error ?? t('skillReadFailed'))\n return\n }\n setActive(path)\n if (path === 'SKILL.md') {\n setSummary(data.summary ?? '')\n setText(data.body ?? '')\n } else {\n setSummary('')\n setText(data.content ?? '')\n }\n setDirty(false)\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }, [props.workflow.id, t])\n\n /** Re-read the pack listing, then the requested file. */\n const refresh = useCallback(async (path?: string): Promise<void> => {\n try {\n const data = await getJson<SkillPackResponse>(`/comfyui/workflows/skill?id=${encodeURIComponent(props.workflow.id)}`)\n setEnabled(data.enabled === true)\n setPack(data.pack ?? null)\n if (Array.isArray(data.presetDirs) && data.presetDirs.length > 0) setPresetDirs(data.presetDirs)\n if (data.enabled === true) await openFile(path ?? 'SKILL.md')\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }, [props.workflow.id, openFile])\n\n /** Re-read the pack listing and — only when nothing is unsaved — the file\n * currently open, so files added or replaced outside this panel (the agent\n * writing via comfyui_skill, or the file manager after `打开目录`) show up\n * without leaving and re-entering the view. */\n const refreshFiles = async (): Promise<void> => {\n setBusy(true)\n setNotice(null)\n try {\n const data = await getJson<SkillPackResponse>(`/comfyui/workflows/skill?id=${encodeURIComponent(props.workflow.id)}`)\n setEnabled(data.enabled === true)\n setPack(data.pack ?? null)\n if (Array.isArray(data.presetDirs) && data.presetDirs.length > 0) setPresetDirs(data.presetDirs)\n setError(null)\n props.onChanged()\n if (data.enabled === true && !dirty) await openFile(active)\n setNotice(t('skillRefreshed'))\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n useEffect(() => {\n void refresh()\n }, [refresh])\n\n /** Every mutation goes through here so the listing and the flags stay in sync. */\n const mutate = async (body: Record<string, unknown>, after?: string): Promise<boolean> => {\n setBusy(true)\n setNotice(null)\n try {\n const data = (await postJson('/comfyui/workflows/skill', { id: props.workflow.id, ...body })) as SkillPackResponse\n if (data.ok !== true) {\n setError(data.error ?? t('skillFailed'))\n return false\n }\n setEnabled(data.enabled === true)\n setPack(data.pack ?? null)\n setError(null)\n props.onChanged()\n if (after !== undefined && data.enabled === true) await openFile(after)\n return true\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n return false\n } finally {\n setBusy(false)\n }\n }\n\n const saveFile = async (): Promise<boolean> => {\n const body: Record<string, unknown> = { action: 'write', path: active, content: text }\n if (active === 'SKILL.md') body.summary = summary\n const ok = await mutate(body)\n if (ok) {\n setDirty(false)\n setNotice(`${t('skillSaved')} ${active}`)\n }\n return ok\n }\n\n /** Switching files with unsaved edits parks the request until the user decides. */\n const selectFile = (path: string): void => {\n if (path === active) return\n if (dirty) {\n setPendingOpen(path)\n return\n }\n void openFile(path)\n }\n\n const createFile = async (): Promise<void> => {\n if (creating === null) return\n const name = creating.name.trim()\n if (name === '') return\n const path = `${creating.bucket}/${name.includes('.') ? name : `${name}.md`}`\n const ok = await mutate({ action: 'write', path, content: '' }, path)\n if (ok) setCreating(null)\n }\n\n /** Open the pack directory in the desktop file manager (on the machine\n * running DSH — the hint says so, and the path stays visible below). */\n const revealDir = async (): Promise<void> => {\n setNotice(null)\n try {\n const data = (await postJson('/comfyui/workflows/skill/reveal', { id: props.workflow.id })) as { ok?: boolean; error?: string; dir?: string }\n if (data.ok !== true) {\n setError(data.error ?? t('skillFailed'))\n return\n }\n setError(null)\n setNotice(`${t('skillRevealed')} ${data.dir ?? ''}`)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n const createDir = async (): Promise<void> => {\n if (creatingDir === null) return\n const name = creatingDir.trim()\n if (name === '') return\n const ok = await mutate({ action: 'mkdir', name })\n if (ok) {\n setCreatingDir(null)\n setNotice(`${t('skillDirCreated')} ${name}/`)\n }\n }\n\n const applyRename = async (): Promise<void> => {\n if (renaming === null) return\n const to = renaming.to.trim()\n if (to === '') return\n const bucket = renaming.from.includes('/') ? `${renaming.from.split('/')[0] ?? ''}/` : ''\n const target = to.includes('/') ? to : `${bucket}${to}`\n const ok = await mutate({ action: 'rename', path: renaming.from, to: target }, target)\n if (ok) setRenaming(null)\n }\n\n /** Import local files into the pack. The destination bucket comes from the\n * host (one extension rule, shared with the agent-facing listing), so the\n * panel only sends the name and the bytes. */\n const importFiles = async (files: File[]): Promise<void> => {\n if (files.length === 0) return\n setBusy(true)\n setNotice(null)\n let imported: string | null = null\n let failed = 0\n for (const file of files) {\n try {\n const bytes = await file.arrayBuffer()\n const data = (await postRaw(\n `/comfyui/workflows/skill/import?id=${encodeURIComponent(props.workflow.id)}&name=${encodeURIComponent(file.name)}`,\n bytes,\n )) as SkillPackResponse & { path?: string }\n if (data.ok !== true) {\n failed += 1\n setError(data.error ?? t('skillFailed'))\n continue\n }\n setPack(data.pack ?? null)\n imported = data.path ?? null\n } catch (cause) {\n failed += 1\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n setBusy(false)\n props.onChanged()\n if (imported !== null) {\n if (failed === 0) {\n setError(null)\n setNotice(`${t('skillImported')} ${imported}`)\n }\n await openFile(imported)\n }\n }\n\n const head = h('div', { className: 'dsc-view-head' },\n h('button', { className: 'dsc-btn', onClick: props.onBack }, t('wfViewBack')),\n h('div', { className: 'dsc-wf-name', title: props.workflow.name }, `${t('skillTitle')} · ${props.workflow.name}`),\n )\n\n if (!enabled) {\n return h('div', null,\n head,\n h('div', { className: 'dsc-hint' }, t('skillIntro')),\n error !== null ? h(ErrorNote, { t, message: error }) : null,\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => void mutate({ action: 'enable' }, 'SKILL.md') }, t('skillEnable')),\n ),\n )\n }\n\n const files = pack?.files ?? []\n // Directories come from disk, so a folder the user created by hand (or an\n // empty one they just added) shows up exactly like a preset would. The list\n // is unioned with the directories the file paths imply: a host that predates\n // the `dirs` field would otherwise hide every sub-directory it does report\n // files for.\n const impliedDirs = files\n .filter((file) => file.path.includes('/'))\n .map((file) => file.path.split('/')[0] ?? '')\n .filter((dir) => dir !== '')\n const packDirs = [...new Set([...(pack?.dirs ?? []), ...impliedDirs])].sort((a, b) => a.localeCompare(b))\n const buckets: Array<{ label: string; items: SkillPackFile[] }> = [\n { label: '', items: files.filter((file) => !file.path.includes('/')) },\n ...packDirs.map((bucket) => ({\n label: bucket,\n items: files.filter((file) => file.path.startsWith(`${bucket}/`)),\n })),\n ]\n /** Where a new file may go: the pack's own directories first, then the\n * presets it has not used yet. */\n const targetDirs = [...packDirs, ...presetDirs.filter((dir) => !packDirs.includes(dir))]\n\n /** One row in the pack file list; clicking opens it for editing. */\n const fileButton = (file: SkillPackFile): ReturnType<typeof h> => h('button', {\n key: file.path,\n className: `dsc-skill-file${file.path === active ? ' dsc-skill-file--active' : ''}`,\n onClick: () => selectFile(file.path),\n },\n h('span', { className: 'dsc-skill-file-name' }, file.path.includes('/') ? file.path.split('/')[1] : file.path),\n h('span', { className: 'dsc-skill-file-size' }, formatBytes(file.size)),\n )\n\n const fileList = h('div', {\n className: 'dsc-skill-files',\n onDragOver: (event: { preventDefault: () => void }) => event.preventDefault(),\n onDrop: (event: { preventDefault: () => void; dataTransfer?: { files?: File[] } }) => {\n event.preventDefault()\n const dropped = Array.from(event.dataTransfer?.files ?? [])\n if (dropped.length > 0) void importFiles(dropped)\n },\n },\n // Both actions sit at the top of the column: below a long file list they\n // were easy to miss entirely.\n h('div', { className: 'dsc-skill-actions' },\n h('label', { className: 'dsc-btn dsc-btn--sm', title: t('skillImportHint') },\n t('skillImport'),\n h('input', {\n type: 'file',\n multiple: true,\n style: { display: 'none' },\n disabled: busy,\n onChange: (event: { target: HTMLInputElement }) => {\n const picked = Array.from(event.target.files ?? [])\n event.target.value = ''\n if (picked.length > 0) void importFiles(picked)\n },\n }),\n ),\n creating === null\n ? h('button', {\n className: 'dsc-btn dsc-btn--sm',\n disabled: busy,\n onClick: () => { setCreatingDir(null); setCreating({ bucket: targetDirs[0] ?? 'references', name: '' }) },\n }, t('skillNewFile'))\n : null,\n creatingDir === null\n ? h('button', {\n className: 'dsc-btn dsc-btn--sm',\n disabled: busy,\n onClick: () => { setCreating(null); setCreatingDir('') },\n }, t('skillNewDir'))\n : null,\n h('button', {\n className: 'dsc-btn dsc-btn--sm',\n disabled: busy,\n title: t('skillRevealHint'),\n onClick: () => void revealDir(),\n }, t('skillReveal')),\n h('button', {\n className: 'dsc-btn dsc-btn--sm',\n disabled: busy,\n title: t('skillRefreshHint'),\n onClick: () => void refreshFiles(),\n }, t('skillRefresh')),\n ),\n creatingDir === null\n ? null\n : h('div', { className: 'dsc-skill-create' },\n h('input', {\n className: 'dsc-input dsc-input--sm',\n value: creatingDir,\n placeholder: t('skillNewDirPlaceholder'),\n onChange: (event: { target: { value: string } }) => setCreatingDir(event.target.value),\n onKeyDown: (event: { key: string; preventDefault: () => void }) => {\n if (event.key === 'Enter') { event.preventDefault(); void createDir() }\n },\n }),\n h('div', { className: 'dsc-hint' }, t('skillNewDirHint', { presets: presetDirs.join(' / ') })),\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn dsc-btn--sm', disabled: busy, onClick: () => void createDir() }, t('skillCreate')),\n h('button', { className: 'dsc-btn dsc-btn--sm', onClick: () => setCreatingDir(null) }, t('cancel')),\n ),\n ),\n h('div', { className: 'dsc-skill-drop-hint' }, t('skillDropHint')),\n buckets.map((bucket) => bucket.items.length === 0 && bucket.label !== ''\n ? null\n : bucket.label === ''\n // Root files (SKILL.md and anything dropped at the top level) are\n // always visible; only directories fold, so a crowded pack can be\n // collapsed per folder.\n ? h('div', { key: '.', className: 'dsc-skill-bucket' }, bucket.items.map(fileButton))\n : h('details', { key: bucket.label, className: 'dsc-fold dsc-skill-fold', open: true },\n h('summary', null, `${bucket.label}/`),\n h('div', { className: 'dsc-skill-bucket' }, bucket.items.map(fileButton)),\n ),\n ),\n creating === null\n ? null\n : h('div', { className: 'dsc-skill-create' },\n h('select', {\n className: 'dsc-input dsc-input--sm',\n value: creating.bucket,\n onChange: (event: { target: { value: string } }) => setCreating({ ...creating, bucket: event.target.value }),\n }, targetDirs.map((bucket) => h('option', { key: bucket, value: bucket }, `${bucket}/`))),\n h('input', {\n className: 'dsc-input dsc-input--sm',\n value: creating.name,\n placeholder: t('skillNewPlaceholder'),\n onChange: (event: { target: { value: string } }) => setCreating({ ...creating, name: event.target.value }),\n onKeyDown: (event: { key: string; preventDefault: () => void }) => {\n if (event.key === 'Enter') { event.preventDefault(); void createFile() }\n },\n }),\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn dsc-btn--sm', disabled: busy, onClick: () => void createFile() }, t('skillCreate')),\n h('button', { className: 'dsc-btn dsc-btn--sm', onClick: () => setCreating(null) }, t('cancel')),\n ),\n ),\n )\n\n const editor = h('div', { className: 'dsc-skill-main' },\n h('div', { className: 'dsc-skill-editor-head' },\n h('span', { className: 'dsc-skill-path' }, active),\n dirty ? h('span', { className: 'dsc-badge dsc-badge--warn' }, t('skillDirty')) : null,\n ),\n active === 'SKILL.md'\n ? h('div', { className: 'dsc-field' },\n h('label', null, t('skillSummary')),\n h('input', {\n className: 'dsc-input',\n value: summary,\n placeholder: t('skillSummaryPlaceholder'),\n onChange: (event: { target: { value: string } }) => { setSummary(event.target.value); setDirty(true) },\n }),\n h('div', { className: 'dsc-hint' }, t('skillSummaryHint')),\n )\n : null,\n isSkillImage(active)\n ? h('div', { className: 'dsc-skill-preview' },\n h('img', {\n src: `/comfyui/workflows/skill/raw?id=${encodeURIComponent(props.workflow.id)}&path=${encodeURIComponent(active)}`,\n alt: active,\n }),\n h('div', { className: 'dsc-hint' }, t('skillImageHint')),\n )\n : h('textarea', {\n className: 'dsc-textarea dsc-textarea--skill',\n value: text,\n spellCheck: false,\n onChange: (event: { target: { value: string } }) => { setText(event.target.value); setDirty(true) },\n onKeyDown: (event: { key: string; preventDefault: () => void; target: HTMLTextAreaElement }) => {\n // Tab indents instead of leaving the field: these files hold scripts.\n if (event.key !== 'Tab') return\n event.preventDefault()\n const area = event.target\n const start = area.selectionStart\n const end = area.selectionEnd\n setText(`${text.slice(0, start)} ${text.slice(end)}`)\n setDirty(true)\n window.requestAnimationFrame(() => {\n area.selectionStart = start + 2\n area.selectionEnd = start + 2\n })\n },\n }),\n h('div', { className: 'dsc-row' },\n isSkillImage(active)\n ? null\n : h('button', { className: 'dsc-btn', disabled: busy || !dirty, onClick: () => void saveFile() }, t('skillSave')),\n active !== 'SKILL.md'\n ? h('button', { className: 'dsc-btn', disabled: busy, onClick: () => setRenaming({ from: active, to: active.includes('/') ? active.split('/')[1] ?? '' : active }) }, t('skillRename'))\n : null,\n active !== 'SKILL.md'\n ? h('button', { className: 'dsc-btn', disabled: busy, onClick: () => setConfirming(active) }, t('skillDeleteFile'))\n : null,\n ),\n confirming !== null && confirming !== '*pack*'\n ? h('div', { className: 'dsc-dialog dsc-dialog--danger' },\n h('div', { className: 'dsc-dialog-head dsc-danger-text' }, `${t('skillDeleteConfirm')} ${confirming}`),\n h('div', { className: 'dsc-row' },\n h('button', {\n className: 'dsc-btn dsc-btn--danger',\n disabled: busy,\n onClick: () => {\n const target = confirming\n setConfirming(null)\n void mutate({ action: 'delete', path: target }, 'SKILL.md')\n },\n }, t('confirmDelete')),\n h('button', { className: 'dsc-btn', onClick: () => setConfirming(null) }, t('cancel')),\n ),\n )\n : null,\n renaming !== null\n ? h('div', { className: 'dsc-skill-create' },\n h('input', {\n className: 'dsc-input dsc-input--sm',\n value: renaming.to,\n onChange: (event: { target: { value: string } }) => setRenaming({ ...renaming, to: event.target.value }),\n }),\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn dsc-btn--sm', disabled: busy, onClick: () => void applyRename() }, t('skillRename')),\n h('button', { className: 'dsc-btn dsc-btn--sm', onClick: () => setRenaming(null) }, t('cancel')),\n ),\n )\n : null,\n )\n\n return h('div', null,\n head,\n h('div', { className: 'dsc-row dsc-skill-flags' },\n h('label', { className: 'dsc-check' },\n h('input', {\n type: 'checkbox',\n checked: pack?.required === true,\n disabled: busy,\n onChange: (event: { target: { checked: boolean } }) => void mutate({ action: 'require', required: event.target.checked }),\n }),\n t('skillRequired'),\n ),\n ),\n pack !== null ? h('div', { className: 'dsc-skill-dir', title: pack.dir }, `${t('skillDir')}: ${pack.dir}`) : null,\n pendingOpen !== null\n ? h('div', { className: 'dsc-dialog' },\n h('div', { className: 'dsc-dialog-head' }, t('skillDirtyPrompt')),\n h('div', { className: 'dsc-row' },\n h('button', {\n className: 'dsc-btn',\n disabled: busy,\n onClick: () => {\n const target = pendingOpen\n setPendingOpen(null)\n void saveFile().then((ok) => { if (ok) void openFile(target) })\n },\n }, t('skillSaveAndSwitch')),\n h('button', {\n className: 'dsc-btn',\n onClick: () => {\n const target = pendingOpen\n setPendingOpen(null)\n setDirty(false)\n void openFile(target)\n },\n }, t('skillDiscard')),\n h('button', { className: 'dsc-btn', onClick: () => setPendingOpen(null) }, t('cancel')),\n ),\n )\n : null,\n notice !== null ? h('div', { className: 'dsc-ok' }, notice) : null,\n error !== null ? h(ErrorNote, { t, message: error }) : null,\n h('div', { className: 'dsc-skill' }, fileList, editor),\n // Both confirmations render next to the button that opened them: a dialog\n // pinned to the top of the view reads as \"the page jumped\", not as a\n // question, and destroying a pack is unrecoverable.\n h('div', { className: 'dsc-skill-footer' },\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => void mutate({ action: 'disable' }).then(() => props.onBack()) }, t('skillDetach')),\n h('button', { className: 'dsc-btn dsc-btn--danger', disabled: busy, onClick: () => setConfirming('*pack*') }, t('skillDestroy')),\n ),\n confirming === '*pack*'\n ? h('div', { className: 'dsc-dialog dsc-dialog--danger' },\n h('div', { className: 'dsc-dialog-head dsc-danger-text' }, t('skillDestroyConfirm', { count: pack?.files.length ?? 0 })),\n h('div', { className: 'dsc-row' },\n h('button', {\n className: 'dsc-btn dsc-btn--danger',\n disabled: busy,\n onClick: () => {\n setConfirming(null)\n void mutate({ action: 'destroy' }).then(() => props.onBack())\n },\n }, t('skillDestroyConfirmButton')),\n h('button', { className: 'dsc-btn', onClick: () => setConfirming(null) }, t('cancel')),\n ),\n )\n : null,\n ),\n )\n}\n\nfunction WorkflowsTab({ t }: ComfyUIPanelProps): ReturnType<typeof h> {\n const [list, setList] = useState<WorkflowEntry[] | null>(null)\n const [comfyui, setComfyui] = useState<ComfyUIWorkflowEntry[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [comfyuiError, setComfyuiError] = useState<string | null>(null)\n const [notice, setNotice] = useState<string | null>(null)\n const [editing, setEditing] = useState<WorkflowDraft | null>(null)\n const [busy, setBusy] = useState(false)\n const [viewing, setViewing] = useState<WorkflowViewState | null>(null)\n const [extract, setExtract] = useState<ExtractState | null>(null)\n /** Open transfer dialog: 'export' | 'import', null = closed. */\n const [transfer, setTransfer] = useState<'export' | 'import' | null>(null)\n const [tagFilter, setTagFilter] = useState<string | null>(null)\n const [skillFor, setSkillFor] = useState<WorkflowEntry | null>(null)\n /** A delete waiting on the user's answer about the workflow's skill pack. */\n const [deleting, setDeleting] = useState<WorkflowEntry | null>(null)\n\n const load = async (): Promise<void> => {\n try {\n const data = await getJson<{ workflows: WorkflowEntry[] }>('/comfyui/workflows')\n setList(data.workflows)\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n try {\n const data = await getJson<{ workflows: ComfyUIWorkflowEntry[] }>('/comfyui/comfy-workflows')\n setComfyui(data.workflows)\n setComfyuiError(null)\n } catch (cause) {\n setComfyuiError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n useEffect(() => {\n let cancelled = false\n void getJson<{ workflows: WorkflowEntry[] }>('/comfyui/workflows').then((data) => {\n if (!cancelled) setList(data.workflows)\n }).catch((cause: unknown) => {\n if (!cancelled) setError(cause instanceof Error ? cause.message : String(cause))\n })\n void getJson<{ workflows: ComfyUIWorkflowEntry[] }>('/comfyui/comfy-workflows').then((data) => {\n if (!cancelled) setComfyui(data.workflows)\n }).catch((cause: unknown) => {\n if (!cancelled) setComfyuiError(cause instanceof Error ? cause.message : String(cause))\n })\n return () => {\n cancelled = true\n }\n }, [])\n\n /** Persist the current draft; returns the saved workflow id, or null on failure (error already set). */\n const persist = async (): Promise<string | null> => {\n if (editing === null) return null\n setBusy(true)\n setError(null)\n setNotice(null)\n let workflow: unknown\n if (typeof editing.workflow === 'string') {\n try {\n workflow = JSON.parse(editing.workflow)\n } catch {\n setError(t('wfJsonError'))\n setBusy(false)\n return null\n }\n } else {\n workflow = editing.workflow\n }\n try {\n const body: Record<string, unknown> = {\n name: String(editing.name ?? ''),\n description: String(editing.description ?? ''),\n workflow,\n parameters: editing.parameters ?? [],\n tags: editing.tags ?? [],\n }\n if (editing.id !== undefined) body.id = editing.id\n const result = (await postJson('/comfyui/workflows', body)) as { workflow?: { id?: string } }\n return result.workflow?.id ?? (typeof editing.id === 'string' ? editing.id : null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n return null\n } finally {\n setBusy(false)\n }\n }\n\n const save = async (): Promise<void> => {\n const id = await persist()\n if (id === null) return\n setEditing(null)\n await load()\n }\n\n /** Save the draft, then immediately queue it with the saved parameters. */\n const saveAndRun = async (): Promise<void> => {\n const id = await persist()\n if (id === null) return\n setEditing(null)\n await load()\n await run(id)\n }\n\n const run = async (id: string): Promise<void> => {\n setBusy(true)\n setError(null)\n setNotice(null)\n try {\n const result = (await postJson('/comfyui/workflows/run', { id })) as { promptId: string }\n setNotice(`${t('wfQueued')} ${shortId(result.promptId)}`)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n /** Delete a workflow. A workflow carrying a skill pack asks first: the pack\n * holds hand-written notes that nothing else can restore. */\n const remove = async (id: string, deleteSkill = false): Promise<void> => {\n setBusy(true)\n setError(null)\n try {\n await postJson('/comfyui/workflows/delete', { id, deleteSkill })\n await load()\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n const requestRemove = (workflow: WorkflowEntry): void => {\n if (workflow.skillDir !== undefined) {\n setDeleting(workflow)\n return\n }\n void remove(workflow.id)\n }\n\n const openExtract = (file: string): void => {\n setError(null)\n setExtract({ file, analysis: null, error: null, mode: 'split' })\n }\n\n const runExtract = async (state: ExtractState): Promise<void> => {\n setBusy(true)\n try {\n const data = (await postJson('/comfyui/comfy-workflows/extract', { file: state.file, mode: state.mode })) as { ok: boolean; saved: WorkflowEntry[]; warnings: string[]; error?: string }\n if (data.ok !== true) throw new Error(data.error ?? 'failed to extract')\n setNotice(`${state.file} → ${t('wfExtractedNotice')}${data.warnings.length > 0 ? `(${t('error')}: ${data.warnings.join(';')})` : ''}`)\n setExtract(null)\n await load()\n } catch (cause) {\n setExtract({ ...state, error: cause instanceof Error ? cause.message : String(cause) })\n } finally {\n setBusy(false)\n }\n }\n\n const importFile = (file: File): void => {\n const reader = new FileReader()\n reader.onload = () => {\n try {\n const parsed = JSON.parse(String(reader.result)) as unknown\n setEditing({ name: file.name.replace(/\\.json$/i, ''), workflow: parsed as Record<string, unknown> })\n setError(null)\n } catch {\n setError(t('wfJsonError'))\n }\n }\n reader.readAsText(file)\n }\n\n const view = async (file: string): Promise<void> => {\n setBusy(true)\n setError(null)\n try {\n const data = await getJson<{ ok: boolean; workflow?: Record<string, unknown>; error?: string }>(`/comfyui/comfy-workflows?file=${encodeURIComponent(file)}`)\n if (data.ok !== true || data.workflow === undefined) {\n throw new Error(data.error ?? 'failed to read workflow')\n }\n setViewing({ file, graph: data.workflow })\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n if (skillFor !== null) {\n return h(SkillPackEditor, {\n t,\n workflow: skillFor,\n onBack: () => { setSkillFor(null); void load() },\n onChanged: () => { void load() },\n })\n }\n if (viewing !== null) {\n return h(WorkflowView, { t, file: viewing.file, graph: viewing.graph, onBack: () => setViewing(null) })\n }\n if (extract !== null) {\n return h(ExtractDialog, { t, state: extract, onUpdate: setExtract, onRun: (state) => runExtract(state), onClose: () => setExtract(null) })\n }\n if (transfer === 'export') {\n return h(ExportDialog, {\n t,\n workflows: list ?? [],\n onClose: () => setTransfer(null),\n onDone: (notice) => { setTransfer(null); setNotice(notice); void load() },\n })\n }\n if (transfer === 'import') {\n return h(ImportDialog, {\n t,\n onClose: () => setTransfer(null),\n onDone: (notice) => { setTransfer(null); setNotice(notice); void load() },\n })\n }\n if (error !== null) return h('div', null, h(ErrorNote, { t, message: error }))\n if (list === null) return h('div', { className: 'dsc-meta' }, '…')\n\n if (editing !== null) {\n return h('div', { className: 'dsc-form' },\n h('div', { className: 'dsc-field' },\n h('label', null, t('wfName')),\n h('input', { className: 'dsc-input', value: editing.name ?? '', onChange: (event: { target: { value: string } }) => setEditing({ ...editing, name: event.target.value }) }),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('wfDesc')),\n h('textarea', { className: 'dsc-textarea', placeholder: t('wfDescPlaceholder'), value: editing.description ?? '', onChange: (event: { target: { value: string } }) => setEditing({ ...editing, description: event.target.value }) }),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('wfTags')),\n h(TagEditor, { t, tags: editing.tags ?? [], onChange: (tags) => setEditing({ ...editing, tags }) }),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('wfParams')),\n h(ParameterEditor, {\n t,\n params: editing.parameters ?? [],\n workflow: parseDraftWorkflow(editing.workflow),\n onChange: (parameters) => setEditing({ ...editing, parameters }),\n }),\n ),\n h('div', { className: 'dsc-field' },\n h('label', null, t('wfJson')),\n h('textarea', {\n className: 'dsc-textarea dsc-textarea--json',\n value: typeof editing.workflow === 'string' ? editing.workflow : JSON.stringify(editing.workflow ?? {}, null, 2),\n onChange: (event: { target: { value: string } }) => setEditing({ ...editing, workflow: event.target.value }),\n }),\n ),\n notice !== null ? h('div', { className: 'dsc-ok' }, notice) : null,\n error !== null ? h(ErrorNote, { t, message: error }) : null,\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => void save() }, t('wfSave')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => void saveAndRun() }, t('wfSaveRun')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => { setEditing(null); setError(null) } }, t('wfCancel')),\n ),\n )\n }\n\n const comfyuiFold = h('details', { className: 'dsc-fold' },\n h('summary', null, `${t('wfComfyuiSection')} (${comfyui?.length ?? 0})`),\n h('div', { className: 'dsc-fold-body' },\n h('div', { className: 'dsc-hint' }, t('wfComfyuiHint')),\n comfyuiError !== null ? h(ErrorNote, { t, message: comfyuiError }) : null,\n comfyui === null\n ? h('div', { className: 'dsc-meta' }, '…')\n : comfyui.length === 0\n ? h('div', { className: 'dsc-meta' }, t('wfComfyuiEmpty'))\n : h('div', { className: 'dsc-list' }, comfyui.map((workflow) => h('div', { key: workflow.name, className: 'dsc-wf dsc-wf--comfyui', title: t('wfNameCopyHint'), onClick: () => { void copyText(workflow.name).then((ok) => { if (ok) setNotice(`${t('wfNameCopied')}:${workflow.name}`) }) } },\n h('div', { className: 'dsc-wf-col' },\n h('div', { className: 'dsc-wf-name', title: workflow.name }, workflow.name),\n h('div', { className: 'dsc-wf-actions' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); void view(workflow.name) } }, t('wfView')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); openExtract(workflow.name) } }, t('wfExtract')),\n ),\n h('div', { className: 'dsc-meta' }, [formatBytes(workflow.size), workflow.modified !== undefined ? formatTs(new Date(workflow.modified).toISOString()) : ''].filter(Boolean).join(' · ')),\n ),\n h('span', { className: workflow.extracted ? 'dsc-badge dsc-badge--ok' : 'dsc-badge dsc-badge--warn' }, workflow.extracted ? `${t('wfExtracted')} ${workflow.derived.length}` : t('wfNotExtracted')),\n ))),\n ),\n )\n\n // Tag filter bar: every tag present in the library, preset order first,\n // with counts; null = all workflows.\n const tagCounts = new Map<string, number>()\n for (const workflow of list) {\n for (const tag of workflow.tags ?? []) tagCounts.set(tag, (tagCounts.get(tag) ?? 0) + 1)\n }\n const visibleTags = [...tagCounts.entries()].sort((a, b) => {\n const pa = PRESET_TAGS.indexOf(a[0])\n const pb = PRESET_TAGS.indexOf(b[0])\n if (pa !== -1 && pb !== -1) return pa - pb\n if (pa !== -1) return -1\n if (pb !== -1) return 1\n return b[1] - a[1]\n }).map(([tag]) => tag)\n const visibleList = tagFilter === null ? list : list.filter((workflow) => (workflow.tags ?? []).includes(tagFilter))\n\n const apiFold = h('details', { className: 'dsc-fold', open: true },\n h('summary', null, `${t('wfLibrarySection')} (${visibleList.length})`),\n h('div', { className: 'dsc-fold-body' },\n visibleTags.length > 0 || tagFilter !== null\n ? h('div', { className: 'dsc-tag-filter' },\n // A simple dropdown instead of a chip row: the library can grow\n // many custom tags, and a horizontal strip of chips would push the\n // workflow list down and visually crowd the toolbar. First option\n // is always \"all\"; picking a tag filters, picking \"all\" clears.\n h('select', {\n className: 'dsc-input dsc-input--inline',\n title: t('wfTags'),\n value: tagFilter ?? '',\n onChange: (event: { target: { value: string } }) => setTagFilter(event.target.value === '' ? null : event.target.value),\n },\n h('option', { value: '' }, `${t('wfTagAll')} (${list.length})`),\n visibleTags.map((tag) => h('option', { key: tag, value: tag }, `${tag} (${tagCounts.get(tag) ?? 0})`)),\n ),\n )\n : null,\n visibleList.length === 0\n ? h('div', { className: 'dsc-meta' }, t('wfEmpty'))\n : h('div', { className: 'dsc-list' }, visibleList.map((workflow) => h('div', { key: workflow.id, className: 'dsc-wf', title: t('wfNameCopyHint'), onClick: () => { void copyText(workflow.name).then((ok) => { if (ok) setNotice(`${t('wfNameCopied')}:${workflow.name}`) }) } },\n h('div', { className: 'dsc-wf-top' },\n h('div', { className: 'dsc-wf-name', title: workflow.name }, workflow.name),\n (workflow.tags ?? []).length > 0\n ? h('div', { className: 'dsc-wf-tags' }, (workflow.tags ?? []).map((tag) => h('span', { key: tag, className: 'dsc-tag-chip dsc-tag-chip--mini' }, tag)))\n : null,\n workflow.skillDir !== undefined\n ? h('span', { className: 'dsc-badge dsc-badge--ok', title: t('skillBadgeHint') }, workflow.requireSkill === true ? t('skillBadgeRequired') : t('skillBadge'))\n : null,\n ),\n workflow.description !== '' ? h('div', { className: 'dsc-wf-desc' }, workflow.description) : null,\n h('div', { className: 'dsc-wf-updated' }, `${t('wfUpdated')} ${formatTs(workflow.updatedAt)}`),\n h('div', { className: 'dsc-wf-actions' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); void run(workflow.id) } }, t('wfRun')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); setEditing({ ...workflow, workflow: JSON.stringify(workflow.workflow, null, 2), parameters: workflow.parameters ?? [], tags: workflow.tags ?? [] }); setError(null) } }, t('wfEdit')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); setSkillFor(workflow); setError(null) } }, t('skillButton')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: (event: { stopPropagation: () => void }) => { event.stopPropagation(); requestRemove(workflow) } }, t('wfDelete')),\n ),\n deleting?.id === workflow.id\n ? h('div', { className: 'dsc-dialog dsc-dialog--danger', onClick: (event: { stopPropagation: () => void }) => event.stopPropagation() },\n h('div', { className: 'dsc-dialog-head dsc-danger-text' }, t('skillDeleteWithWorkflow')),\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn dsc-btn--danger', disabled: busy, onClick: () => { setDeleting(null); void remove(workflow.id, true) } }, t('skillDeleteBoth')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => { setDeleting(null); void remove(workflow.id, false) } }, t('skillKeepPack')),\n h('button', { className: 'dsc-btn', onClick: () => setDeleting(null) }, t('cancel')),\n ),\n )\n : null,\n ))),\n ),\n )\n\n return h('div', null,\n h('div', { className: 'dsc-toolbar' },\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => { setEditing({ workflow: {}, parameters: [], tags: [] }); setError(null) } }, t('wfAdd')),\n h('label', { className: 'dsc-btn' },\n t('wfImportFile'),\n h('input', {\n type: 'file',\n accept: '.json,application/json',\n style: { display: 'none' },\n onChange: (event: { target: HTMLInputElement }) => {\n const file = event.target.files?.[0]\n if (file !== undefined) importFile(file)\n event.target.value = ''\n },\n }),\n ),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => { setError(null); setTransfer('export') } }, t('exportPresets')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => { setError(null); setTransfer('import') } }, t('importPresets')),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: () => void load() }, t('wfRefresh')),\n ),\n notice !== null ? h('div', { className: 'dsc-ok' }, notice) : null,\n comfyuiFold,\n apiFold,\n h(LoadArea, { t, onNotice: setNotice }),\n )\n}\n\n/** Extract-mode chooser: shows the canvas analysis and lets the user pick how\n * to extract runnable API workflows from a ComfyUI-side graph. */\nfunction ExtractDialog(props: {\n t: ComfyUIPanelProps['t']\n state: ExtractState\n onUpdate: (state: ExtractState) => void\n onRun: (state: ExtractState) => Promise<void>\n onClose: () => void\n}): ReturnType<typeof h> {\n const { t, state, onUpdate, onRun, onClose } = props\n useEffect(() => {\n if (state.analysis === null && state.error === null) {\n let cancelled = false\n void getJson<AnalyzePayload>(`/comfyui/comfy-workflows/analyze?file=${encodeURIComponent(state.file)}`)\n .then((data) => {\n if (cancelled) return\n if (data.ok !== true || data.analysis === undefined) onUpdate({ ...state, error: data.error ?? 'failed to analyze' })\n else if (data.analysis.ok !== true) onUpdate({ ...state, error: data.analysis.error })\n else onUpdate({ ...state, analysis: data.analysis, mode: data.analysis.mode === 'single' ? 'all' : 'split' })\n })\n .catch((cause: unknown) => {\n if (!cancelled) onUpdate({ ...state, error: cause instanceof Error ? cause.message : String(cause) })\n })\n return () => {\n cancelled = true\n }\n }\n return undefined\n })\n\n const modes: Array<{ mode: ExtractMode; label: string; hint: string }> = [\n { mode: 'all', label: t('wfExtractModeAll'), hint: t('wfExtractModeAllHint') },\n { mode: 'split', label: t('wfExtractModeSplit'), hint: t('wfExtractModeSplitHint') },\n { mode: 'main', label: t('wfExtractModeMain'), hint: t('wfExtractModeMainHint') },\n ]\n const analysis = state.analysis\n return h('div', { className: 'dsc-dialog' },\n h('div', { className: 'dsc-dialog-head' },\n h('span', { className: 'dsc-wf-name' }, `${t('wfExtractTitle')}: ${state.file}`),\n h('button', { className: 'dsc-panel-close', 'aria-label': t('close'), onClick: onClose }, '✕'),\n ),\n analysis === null\n ? h('div', { className: 'dsc-meta' }, '…')\n : h('div', null,\n h('div', { className: 'dsc-hint' },\n `${t('wfComponents')}: ${analysis.components.length} · ${t('wfBypassed')}: ${analysis.bypassedCount} · ${t('wfIsolated')}: ${analysis.isolated.length}`,\n ),\n analysis.components.length > 0\n ? h('ul', { className: 'dsc-node-list' },\n analysis.components.map((component) => h('li', { key: String(component.index) },\n `${t('wfComponentLabel')} ${component.index}(${component.size} ${t('wfNodes')})${component.groups.length > 0 ? `[${component.groups.slice(0, 3).join('+')}]` : ''}`,\n )),\n )\n : h('div', { className: 'dsc-meta' }, t('wfExtractEmpty')),\n h('div', { className: 'dsc-extract-modes' },\n modes.map((entry) => h('label', { key: entry.mode, className: 'dsc-mode' },\n h('input', {\n type: 'radio',\n name: 'extract-mode',\n checked: state.mode === entry.mode,\n onChange: () => onUpdate({ ...state, mode: entry.mode }),\n }),\n h('span', { className: 'dsc-mode-label' }, entry.label),\n h('span', { className: 'dsc-hint' }, entry.hint),\n )),\n ),\n state.error !== null ? h(ErrorNote, { t, message: state.error }) : null,\n h('div', { className: 'dsc-row' },\n h('button', { className: 'dsc-btn', disabled: analysis.components.length === 0, onClick: () => void onRun(state) }, t('wfExtractRun')),\n h('button', { className: 'dsc-btn', onClick: onClose }, t('wfCancel')),\n ),\n ),\n )\n}\n\n/** Shared checkbox row for the transfer dialogs: name, badges, description. */\nfunction TransferItem(props: {\n name: string\n description: string\n paramBadge: string | null\n skillBadge: string | null\n warnings: string[]\n checked: boolean\n onToggle: () => void\n}): ReturnType<typeof h> {\n return h('label', { className: 'dsc-transfer-item' },\n h('input', { type: 'checkbox', checked: props.checked, onChange: props.onToggle }),\n h('span', { className: 'dsc-transfer-item-name', title: props.name }, props.name),\n props.paramBadge !== null ? h('span', { className: 'dsc-badge' }, props.paramBadge) : null,\n props.skillBadge !== null ? h('span', { className: 'dsc-badge dsc-badge--ok' }, props.skillBadge) : null,\n props.description !== ''\n ? h('span', { className: 'dsc-transfer-item-desc', title: props.description }, props.description)\n : null,\n props.warnings.length > 0\n ? h('span', { className: 'dsc-transfer-item-desc dsc-danger-text', title: props.warnings.join(';') }, props.warnings.join(';'))\n : null,\n )\n}\n\n/** While a transfer dialog is open, swallow drag events aimed at the host\n * page. The conversation shell attaches dropped files to the chat with\n * document-level bubble listeners, so dragging a preset toward the dialog\n * also dropped it into the conversation. Window-capture listeners run before\n * any document-bubble handler and shield everything OUTSIDE the dialog;\n * events landing inside the dialog pass through — the dialog box itself must\n * stopPropagation() them at React's dispatch root, or they bubble on to the\n * document and the shell attaches the file anyway. */\nfunction DragGuard(): null {\n useEffect(() => {\n const guard = (event: DragEvent): void => {\n if (event.target instanceof Element && event.target.closest('.dsc-transfer') !== null) return\n event.preventDefault()\n event.stopPropagation()\n }\n for (const type of ['dragenter', 'dragover', 'drop'] as const) window.addEventListener(type, guard, true)\n return () => {\n for (const type of ['dragenter', 'dragover', 'drop'] as const) window.removeEventListener(type, guard, true)\n }\n }, [])\n return null\n}\n\n/** Export dialog: pick library workflows (checkboxes + select-all, all\n * pre-selected) and download one preset package. Packaging happens host-side;\n * the dialog lists, selects, and submits a native form download. */\nfunction ExportDialog(props: {\n t: ComfyUIPanelProps['t']\n workflows: WorkflowEntry[]\n onClose: () => void\n onDone: (notice: string) => void\n}): ReturnType<typeof h> {\n const { t, workflows } = props\n const [selected, setSelected] = useState<Set<string>>(() => new Set(workflows.map((workflow) => workflow.id)))\n const [busy, setBusy] = useState(false)\n\n const toggle = (id: string): void => {\n setSelected((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n return next\n })\n }\n const allSelected = workflows.length > 0 && selected.size === workflows.length\n const toggleAll = (): void => {\n setSelected(allSelected ? new Set() : new Set(workflows.map((workflow) => workflow.id)))\n }\n\n /** Download natively: a hidden form GETs `/comfyui/workflows/export/<file\n * name>?ids=…` and the server answers with `content-disposition:\n * attachment`, so the browser — not JS blob plumbing (fetch → blob →\n * objectURL → revoke, which one environment turned into a 0-byte file) —\n * owns the transfer. The page never navigates because the response is an\n * attachment.\n *\n * GET with the name in the path is deliberate: this setup's download\n * manager mangles POST downloads (renames them, or re-fetches the URL on\n * its own), which is where the phantom \"skills sometimes missing\" zips\n * came from. A GET is the one verb every manager handles correctly — and\n * since the name rides in the URL, saved name == receipt name even under\n * interception, and a manager's own re-fetch still gets a genuine export\n * of the same ids (the route is a pure read).\n *\n * The form response is invisible to JS, so the notice is fed from\n * `export/last` — the server's record of what it ACTUALLY packaged — not\n * from the checkboxes. */\n const exportSelected = (): void => {\n if (busy) return\n setBusy(true)\n void (async () => {\n let previousAt: string | null = null\n try {\n const before = await getJson<{ last: LastExport | null }>('/comfyui/workflows/export/last')\n previousAt = before.last?.at ?? null\n } catch { /* first export ever, or a blip — polling below still works */ }\n const now = new Date()\n const p = (n: number, width = 2): string => String(n).padStart(width, '0')\n const filename = `dsh-comfyui-presets-${now.getFullYear()}${p(now.getMonth() + 1)}${p(now.getDate())}-${p(now.getHours())}${p(now.getMinutes())}${p(now.getSeconds())}-${p(now.getMilliseconds(), 3)}-${Math.random().toString(36).slice(2, 8)}.zip`\n const form = document.createElement('form')\n form.method = 'GET'\n form.action = `/comfyui/workflows/export/${filename}`\n form.style.display = 'none'\n for (const id of selected) {\n const input = document.createElement('input')\n input.type = 'hidden'\n input.name = 'ids'\n input.value = id\n form.append(input)\n }\n document.body.append(form)\n form.submit()\n form.remove()\n // Poll briefly for the record of THIS export (a big pack takes a\n // second or two to zip); fall back to the client's own selection.\n let last: LastExport | null = null\n for (let attempt = 0; attempt < 10 && last === null; attempt++) {\n await new Promise((resolve) => window.setTimeout(resolve, 350))\n try {\n const payload = await getJson<{ last: LastExport | null }>('/comfyui/workflows/export/last')\n if (payload.last !== null && payload.last.at !== previousAt) last = payload.last\n } catch { /* retried below */ }\n }\n const names = (last?.names ?? selectedNames()).join('、')\n let notice = t('transferExportDone', { n: last?.count ?? selected.size, names })\n // The file fingerprint: whatever the user opens must match this name\n // (and roughly this size) — anything else is an older download.\n if (last !== null) notice += ' ' + t('transferExportFile', { file: last.filename, size: Math.max(1, Math.round(last.size / 1024)) })\n if (last !== null && last.warnings.length > 0) notice += ' ' + t('transferExportWarnings', { warnings: last.warnings.join(';') })\n props.onDone(notice)\n })()\n }\n\n /** Names behind the current selection, dialog order, with pack-bearing\n * entries annotated. Shown next to the submit button so \"what will be\n * packaged — and will it carry skills\" is readable at the decision point:\n * a selection that happens to exclude the one pack-bearing workflow looks\n * exactly like \"skills export unreliably\" from the zip alone. */\n const selectedNames = (): string[] =>\n workflows\n .filter((workflow) => selected.has(workflow.id))\n .map((workflow) => (workflow.skillDir !== undefined ? `${workflow.name} (${t('skillBadge')})` : workflow.name))\n\n return h('div', { className: 'dsc-picker-overlay', onClick: props.onClose },\n h(DragGuard),\n h('div', {\n className: 'dsc-transfer',\n onClick: (event: { stopPropagation: () => void }) => event.stopPropagation(),\n // Absorb drag events inside the dialog: without stopPropagation they\n // bubble past React's dispatch root to the document, where the shell's\n // composer listeners attach the file to the conversation.\n onDragEnter: (event: { preventDefault: () => void; stopPropagation: () => void }) => { event.preventDefault(); event.stopPropagation() },\n onDragOver: (event: { preventDefault: () => void; stopPropagation: () => void }) => { event.preventDefault(); event.stopPropagation() },\n onDrop: (event: { preventDefault: () => void; stopPropagation: () => void }) => { event.preventDefault(); event.stopPropagation() },\n },\n h('div', { className: 'dsc-transfer-head' },\n h('span', { className: 'dsc-transfer-title' }, t('transferExportTitle')),\n h('button', { className: 'dsc-panel-close', 'aria-label': t('close'), onClick: props.onClose }, '✕'),\n ),\n workflows.length === 0\n ? h('div', { className: 'dsc-transfer-empty' }, t('transferExportEmpty'))\n : h('div', { className: 'dsc-transfer-body' },\n h('div', { className: 'dsc-transfer-bar' },\n h('span', { className: 'dsc-hint' }, t('transferExportHint', { total: workflows.length, selected: selected.size })),\n h('button', { className: 'dsc-btn dsc-btn--sm', onClick: toggleAll }, allSelected ? t('transferSelectNone') : t('transferSelectAll')),\n ),\n h('div', { className: 'dsc-transfer-list' },\n workflows.map((workflow) => h(TransferItem, {\n key: workflow.id,\n name: workflow.name,\n description: workflow.description,\n paramBadge: (workflow.parameters ?? []).length > 0 ? t('transferParamBadge', { n: (workflow.parameters ?? []).length }) : null,\n skillBadge: workflow.skillDir !== undefined ? t('skillBadge') : null,\n warnings: [],\n checked: selected.has(workflow.id),\n onToggle: () => toggle(workflow.id),\n })),\n ),\n ),\n selected.size > 0\n ? h('div', { className: 'dsc-transfer-note' },\n h('span', { className: 'dsc-hint', title: selectedNames().join('、') },\n t('transferSelectedList', { names: selectedNames().join('、') })))\n : null,\n h('div', { className: 'dsc-transfer-actions' },\n workflows.length === 0\n ? null\n : h('button', {\n className: 'dsc-btn dsc-btn--primary',\n disabled: busy || selected.size === 0,\n onClick: () => exportSelected(),\n }, busy ? t('transferExporting') : t('transferExportRun', { n: selected.size })),\n h('button', { className: 'dsc-btn', disabled: busy, onClick: props.onClose }, t('cancel')),\n ),\n ),\n )\n}\n\n/** Import dialog: choose a preset package (file picker or drag-drop), see\n * what it offers, then import the selection as NEW workflows. The file is\n * POSTed twice by design — analyze and apply parse the same bytes, so the\n * host needs no temp-file staging or cleanup. */\nfunction ImportDialog(props: {\n t: ComfyUIPanelProps['t']\n onClose: () => void\n onDone: (notice: string) => void\n}): ReturnType<typeof h> {\n const { t } = props\n const [file, setFile] = useState<File | null>(null)\n const [analysis, setAnalysis] = useState<ImportAnalysisView | null>(null)\n const [selected, setSelected] = useState<Set<number>>(new Set())\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [results, setResults] = useState<ImportOutcomeView[] | null>(null)\n const [imported, setImported] = useState(0)\n const [dragOver, setDragOver] = useState(false)\n\n /** Phase 1: upload the package for analysis (no server-side writes). */\n const analyze = async (picked: File): Promise<void> => {\n setBusy(true)\n setError(null)\n try {\n const bytes = await picked.arrayBuffer()\n const data = await postRaw('/comfyui/workflows/import/analyze', bytes) as { ok?: boolean; analysis?: ImportAnalysisView; error?: string }\n if (data.ok !== true || data.analysis === undefined) throw new Error(data.error ?? 'failed to analyze')\n setFile(picked)\n setAnalysis(data.analysis)\n setSelected(new Set(data.analysis.workflows.map((entry) => entry.index)))\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n const toggle = (index: number): void => {\n setSelected((prev) => {\n const next = new Set(prev)\n if (next.has(index)) next.delete(index)\n else next.add(index)\n return next\n })\n }\n const allSelected = analysis !== null && analysis.workflows.length > 0 && selected.size === analysis.workflows.length\n const toggleAll = (): void => {\n if (analysis === null) return\n setSelected(allSelected ? new Set() : new Set(analysis.workflows.map((entry) => entry.index)))\n }\n\n /** Phase 2: re-upload the same bytes with the selection as manifest indexes. */\n const importSelected = async (): Promise<void> => {\n if (file === null) return\n setBusy(true)\n setError(null)\n try {\n const bytes = await file.arrayBuffer()\n const query = [...selected].join(',')\n const data = await postRaw(`/comfyui/workflows/import/apply?select=${query}`, bytes) as { ok?: boolean; results?: ImportOutcomeView[]; imported?: number; error?: string }\n if (data.ok !== true || data.results === undefined) throw new Error(data.error ?? 'failed to import')\n setResults(data.results)\n setImported(data.imported ?? 0)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n const finish = (): void => {\n if (imported > 0) props.onDone(t('transferImportDone', { n: imported }))\n else props.onClose()\n }\n\n return h('div', { className: 'dsc-picker-overlay', onClick: props.onClose },\n h(DragGuard),\n h('div', {\n className: 'dsc-transfer',\n onClick: (event: { stopPropagation: () => void }) => event.stopPropagation(),\n // Absorb drag events inside the dialog: without stopPropagation they\n // bubble past React's dispatch root to the document, where the shell's\n // composer listeners attach the file to the conversation.\n onDragEnter: (event: { preventDefault: () => void; stopPropagation: () => void }) => { event.preventDefault(); event.stopPropagation() },\n onDragOver: (event: { preventDefault: () => void; stopPropagation: () => void }) => { event.preventDefault(); event.stopPropagation() },\n onDrop: (event: { preventDefault: () => void; stopPropagation: () => void }) => { event.preventDefault(); event.stopPropagation() },\n },\n h('div', { className: 'dsc-transfer-head' },\n h('span', { className: 'dsc-transfer-title' }, t('transferImportTitle')),\n h('button', { className: 'dsc-panel-close', 'aria-label': t('close'), onClick: props.onClose }, '✕'),\n ),\n h('div', { className: 'dsc-transfer-body' },\n results !== null\n ? h('div', { className: 'dsc-transfer-list' },\n results.map((outcome) => h('div', {\n key: outcome.index,\n className: `dsc-transfer-item dsc-transfer-item--static${outcome.ok ? ' dsc-transfer-item--ok' : ' dsc-transfer-item--fail'}`,\n },\n h('span', { className: 'dsc-transfer-item-name', title: outcome.name },\n outcome.ok\n ? t('transferImportedItem', { src: outcome.name, dst: outcome.newName ?? '' })\n : t('transferImportFailedItem', { src: outcome.name, reason: outcome.error ?? '' }),\n ),\n outcome.warnings.length > 0\n ? h('span', { className: 'dsc-transfer-item-desc', title: outcome.warnings.join(';') }, outcome.warnings.join(';'))\n : null,\n )),\n )\n : analysis === null\n ? h('label', {\n className: `dsc-transfer-drop${dragOver ? ' dsc-transfer-drop--over' : ''}`,\n onDragOver: (event: { preventDefault: () => void }) => { event.preventDefault(); setDragOver(true) },\n onDragLeave: () => setDragOver(false),\n onDrop: (event: { preventDefault: () => void; dataTransfer?: { files?: File[] } }) => {\n event.preventDefault()\n setDragOver(false)\n const dropped = event.dataTransfer?.files?.[0]\n if (dropped !== undefined) void analyze(dropped)\n },\n },\n h('input', {\n type: 'file',\n accept: '.zip,application/zip,application/x-zip-compressed',\n style: { display: 'none' },\n onChange: (event: { target: HTMLInputElement }) => {\n const picked = event.target.files?.[0]\n if (picked !== undefined) void analyze(picked)\n event.target.value = ''\n },\n }),\n busy ? t('transferImporting') : t('transferPickFile'),\n )\n : h('div', { className: 'dsc-transfer-body' },\n h('div', { className: 'dsc-transfer-bar' },\n h('span', { className: 'dsc-hint' }, t('transferPackageInfo', { n: analysis.workflows.length, date: formatTs(analysis.exportedAt) })),\n h('button', { className: 'dsc-btn dsc-btn--sm', onClick: toggleAll }, allSelected ? t('transferSelectNone') : t('transferSelectAll')),\n ),\n h('div', { className: 'dsc-transfer-list' },\n analysis.workflows.map((entry) => h(TransferItem, {\n key: entry.index,\n name: entry.name,\n description: entry.description,\n paramBadge: entry.paramCount > 0 ? t('transferParamBadge', { n: entry.paramCount }) : null,\n skillBadge: entry.skill !== null\n ? (entry.skill.required\n ? t('transferSkillRequired', { n: entry.skill.fileCount })\n : t('transferSkillBadge', { n: entry.skill.fileCount }))\n : null,\n warnings: entry.warnings,\n checked: selected.has(entry.index),\n onToggle: () => toggle(entry.index),\n })),\n ),\n ),\n error !== null ? h(ErrorNote, { t, message: error }) : null,\n analysis !== null && results === null ? h('div', { className: 'dsc-hint' }, t('transferImportNote')) : null,\n analysis === null && results === null ? h('div', { className: 'dsc-hint' }, t('transferPickHint')) : null,\n ),\n h('div', { className: 'dsc-transfer-actions' },\n results !== null\n ? h('button', { className: 'dsc-btn dsc-btn--primary', onClick: finish }, t('transferFinish'))\n : analysis !== null\n ? h('button', {\n className: 'dsc-btn dsc-btn--primary',\n disabled: busy || selected.size === 0,\n onClick: () => { void importSelected() },\n }, busy ? t('transferImporting') : t('transferImportRun', { n: selected.size }))\n : null,\n h('button', { className: 'dsc-btn', disabled: busy, onClick: results !== null ? finish : props.onClose }, t('cancel')),\n ),\n ),\n )\n}\n\n/** Read-only inspection of a ComfyUI-side saved workflow: node list + JSON. */\nfunction WorkflowView(props: { t: ComfyUIPanelProps['t']; file: string; graph: Record<string, unknown>; onBack: () => void }): ReturnType<typeof h> {\n const nodes = Array.isArray(props.graph.nodes)\n ? (props.graph.nodes as Array<Record<string, unknown>>).filter((node) => node.mode !== 4 && typeof node.type === 'string' && node.type !== '')\n : []\n const json = JSON.stringify(props.graph, null, 2)\n return h('div', { className: 'dsc-view' },\n h('div', { className: 'dsc-view-head' },\n h('span', { className: 'dsc-wf-name' }, props.file),\n h('button', { className: 'dsc-btn', onClick: props.onBack }, props.t('wfViewBack')),\n ),\n h('div', { className: 'dsc-view-label' }, `${props.t('wfViewNodes')} (${nodes.length})`),\n nodes.length === 0\n ? h('div', { className: 'dsc-meta' }, props.t('wfViewEmpty'))\n : h('ul', { className: 'dsc-node-list' }, nodes.map((node) => h('li', { key: String(node.id) }, `${String(node.id)} · ${String(node.type)}`))),\n h('div', { className: 'dsc-view-label' }, props.t('wfViewJson')),\n h('textarea', { className: 'dsc-textarea dsc-textarea--json dsc-textarea--view', readOnly: true, value: json }),\n )\n}\n\n/** Tab 2: asset preview — thumbnails of everything the plugin generated. */\nfunction AssetsTab({ t, onPreview }: { t: ComfyUIPanelProps['t']; onPreview: (images: string[], kinds: Array<'image' | 'video' | 'audio' | 'other'>, index: number) => void }): ReturnType<typeof h> {\n const [assets, setAssets] = useState<AssetEntry[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [filter, setFilter] = useState(() => panelStore.getAssetFilter())\n /** Asset awaiting the delete confirmation, if any. */\n const [pendingDelete, setPendingDelete] = useState<AssetEntry | null>(null)\n const [deleting, setDeleting] = useState(false)\n const [notice, setNotice] = useState<string | null>(null)\n\n const load = async (): Promise<void> => {\n try {\n const data = await getJson<{ assets: AssetEntry[] }>('/comfyui/assets')\n setAssets(data.assets)\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n useEffect(() => {\n let cancelled = false\n void getJson<{ assets: AssetEntry[] }>('/comfyui/assets').then((data) => {\n if (!cancelled) setAssets(data.assets)\n }).catch((cause: unknown) => {\n if (!cancelled) setError(cause instanceof Error ? cause.message : String(cause))\n })\n return () => {\n cancelled = true\n }\n }, [])\n\n /** Delete the record and (when the output directory is known) its files. */\n const confirmDelete = async (asset: AssetEntry): Promise<void> => {\n setDeleting(true)\n try {\n const result = (await postJson('/comfyui/assets/delete', { promptId: asset.promptId })) as\n { ok?: boolean; error?: string; deleted?: number; failures?: string[] }\n if (result.ok !== true) throw new Error(result.error ?? 'delete failed')\n setPendingDelete(null)\n setNotice(t('assetDeleteDone', { deleted: result.deleted ?? 0 }))\n if (Array.isArray(result.failures) && result.failures.length > 0) {\n setError(result.failures.join('; '))\n }\n await load()\n } catch (cause) {\n setError(t('assetDeleteFailed', { message: cause instanceof Error ? cause.message : String(cause) }))\n setPendingDelete(null)\n } finally {\n setDeleting(false)\n }\n }\n\n if (error !== null && assets === null) return h('div', null, h(ErrorNote, { t, message: error }))\n if (assets === null) return h('div', { className: 'dsc-meta' }, '…')\n\n const names = [...new Set(assets.map((asset) => asset.workflowName ?? ''))]\n const visible = filter === '' ? assets : assets.filter((asset) => (asset.workflowName ?? '') === filter)\n // Every media item in the visible grid, in display order, for the lightbox\n // sequence (videos/audio included so clicking a thumbnail can play it).\n const previewItems = visible.flatMap((asset) => asset.media.map((item) => ({ url: item.url, kind: item.kind })))\n const openAsset = (asset: AssetEntry): void => {\n const first = asset.media[0]\n const index = first !== undefined ? previewItems.findIndex((item) => item.url === first.url) : 0\n onPreview(previewItems.map((item) => item.url), previewItems.map((item) => item.kind), index < 0 ? 0 : index)\n }\n\n return h('div', null,\n h('div', { className: 'dsc-toolbar' },\n h('select', { className: 'dsc-input dsc-input--inline', value: filter, onChange: (event: { target: { value: string } }) => setFilter(event.target.value) },\n h('option', { value: '' }, t('assetAll')),\n names.map((name) => h('option', { key: name, value: name }, name === '' ? '—' : name)),\n ),\n h('button', { className: 'dsc-btn', onClick: () => void load() }, t('refresh')),\n ),\n error !== null ? h(ErrorNote, { t, message: error }) : null,\n notice !== null ? h('div', { className: 'dsc-ok' }, notice) : null,\n visible.length === 0\n ? h('div', { className: 'dsc-meta' }, t('assetEmpty'))\n : h('div', { className: 'dsc-assets-grid' }, visible.map((asset) => h(AssetThumb, {\n key: asset.promptId,\n asset,\n t,\n onClick: () => openAsset(asset),\n onDelete: () => { setNotice(null); setPendingDelete(asset) },\n }))),\n pendingDelete !== null\n ? h(ConfirmDialog, {\n t,\n title: t('assetDeleteTitle'),\n body: t('assetDeleteBody', { count: pendingDelete.media.length }),\n detail: pendingDelete.media.map((item) => item.filename).join('、'),\n busy: deleting,\n onConfirm: () => { void confirmDelete(pendingDelete) },\n onCancel: () => setPendingDelete(null),\n })\n : null,\n )\n}\n\n/** Modal confirmation for a destructive action (asset deletion). */\nfunction ConfirmDialog(props: {\n t: ComfyUIPanelProps['t']\n title: string\n body: string\n detail?: string\n busy: boolean\n onConfirm: () => void\n onCancel: () => void\n}): ReturnType<typeof h> {\n return h('div', { className: 'dsc-picker-overlay', onClick: props.onCancel },\n h('div', { className: 'dsc-confirm', onClick: (event: { stopPropagation: () => void }) => event.stopPropagation() },\n h('div', { className: 'dsc-confirm-title' }, props.title),\n h('div', { className: 'dsc-confirm-body' }, props.body),\n props.detail !== undefined && props.detail !== ''\n ? h('div', { className: 'dsc-confirm-detail' }, props.detail)\n : null,\n h('div', { className: 'dsc-confirm-actions' },\n h('button', { className: 'dsc-btn', disabled: props.busy, onClick: props.onCancel }, props.t('cancel')),\n h('button', { className: 'dsc-btn dsc-btn--danger', disabled: props.busy, onClick: props.onConfirm }, props.t('confirmDelete')),\n ),\n ),\n )\n}\n\nfunction AssetThumb(props: { asset: AssetEntry; t: ComfyUIPanelProps['t']; onClick: () => void; onDelete: () => void }): ReturnType<typeof h> {\n const first = props.asset.media[0]\n const [broken, setBroken] = useState(false)\n // Deleting is destructive, so the button stays out of the way until the\n // pointer is on the card, and it never triggers the card's own click.\n const trash = h('button', {\n className: 'dsc-asset-trash',\n title: props.t('assetDelete'),\n 'aria-label': props.t('assetDelete'),\n onClick: (event: { stopPropagation: () => void }) => {\n event.stopPropagation()\n props.onDelete()\n },\n }, '🗑')\n if (first === undefined || broken) {\n return h('div', { className: 'dsc-asset dsc-asset--empty', onClick: props.onClick },\n h('div', null, props.t('assetGone')),\n h('div', { className: 'dsc-meta' }, props.asset.workflowName ?? '—'),\n trash,\n )\n }\n return h('div', { className: 'dsc-asset', onClick: props.onClick },\n first.kind === 'video'\n ? h('video', { src: first.url, controls: true, preload: 'metadata', onClick: (event: { stopPropagation: () => void }) => event.stopPropagation() })\n : first.kind === 'audio'\n // Audio cards show a plain note icon + filename (no player inline —\n // an <img> or <audio> here mislabels live files as evicted or squats\n // in the grid); the actual player opens in the lightbox preview.\n ? h('div', { className: 'dsc-asset-audio-icon' },\n // Dim waveform bars tiled across the green tile (pure decoration;\n // the speaker glyph stays on top).\n h('svg', { className: 'dsc-asset-audio-icon-wave', 'aria-hidden': 'true' },\n h('defs', null,\n // One horizontal waveform: the pattern tile is as tall as the\n // card (110px) so nothing repeats vertically, and the bars are\n // thin (2px) and dense (6px spacing) for a fine waveform look.\n h('pattern', { id: 'dsc-wave-pattern', width: 64, height: 110, patternUnits: 'userSpaceOnUse' },\n h('g', { fill: 'rgba(255,255,255,0.15)' },\n h('rect', { x: 0, y: 50, width: 2, height: 10, rx: 1 }),\n h('rect', { x: 4, y: 44, width: 2, height: 22, rx: 1 }),\n h('rect', { x: 8, y: 48, width: 2, height: 14, rx: 1 }),\n h('rect', { x: 12, y: 38, width: 2, height: 34, rx: 1 }),\n h('rect', { x: 16, y: 46, width: 2, height: 18, rx: 1 }),\n h('rect', { x: 20, y: 52, width: 2, height: 6, rx: 1 }),\n h('rect', { x: 24, y: 40, width: 2, height: 30, rx: 1 }),\n h('rect', { x: 28, y: 48, width: 2, height: 14, rx: 1 }),\n h('rect', { x: 32, y: 42, width: 2, height: 26, rx: 1 }),\n h('rect', { x: 36, y: 36, width: 2, height: 38, rx: 1 }),\n h('rect', { x: 40, y: 47, width: 2, height: 16, rx: 1 }),\n h('rect', { x: 44, y: 51, width: 2, height: 8, rx: 1 }),\n h('rect', { x: 48, y: 40, width: 2, height: 30, rx: 1 }),\n h('rect', { x: 52, y: 45, width: 2, height: 20, rx: 1 }),\n h('rect', { x: 56, y: 38, width: 2, height: 34, rx: 1 }),\n h('rect', { x: 60, y: 49, width: 2, height: 12, rx: 1 })))),\n h('rect', { width: '100%', height: '100%', fill: 'url(#dsc-wave-pattern)' })),\n h('svg', { className: 'dsc-asset-audio-icon-sym', viewBox: '0 0 24 24', 'aria-hidden': 'true', dangerouslySetInnerHTML: { __html: '<path fill=\"currentColor\" d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"/>' } }),\n h('span', { className: 'dsc-asset-audio-icon-name', title: first.filename }, first.filename))\n : h('img', { src: first.url, alt: first.filename, loading: 'lazy', onError: () => setBroken(true) }),\n h('div', { className: 'dsc-asset-meta' }, props.asset.workflowName ?? '—'),\n trash,\n )\n}\n\n/**\n * Tab 3: the task center — active tasks (pending / generating) shown as\n * cards with id, status and progress, plus history filtered by the\n * completed / failed / cancelled chips. Polled every 3 seconds.\n */\nfunction QueueTab({ t, onPreview }: { t: ComfyUIPanelProps['t']; onPreview: (images: string[], kinds: Array<'image' | 'video' | 'audio' | 'other'>, index: number) => void }): ReturnType<typeof h> {\n const [filter, setFilter] = useState<JobFilter>('all')\n const [active, setActive] = useState<JobView[] | null>(null)\n const [history, setHistory] = useState<JobView[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [busy, setBusy] = useState(false)\n\n const load = async (current: JobFilter): Promise<void> => {\n try {\n const historyStatus = current === 'all' ? 'completed,failed,cancelled' : current\n const [activeData, historyData] = await Promise.all([\n getJson<JobsView>('/comfyui/jobs?status=pending,in_progress&limit=100'),\n getJson<JobsView>(`/comfyui/jobs?status=${historyStatus}&limit=100`),\n ])\n if (activeData.ok !== true) throw new Error(activeData.error ?? t('queueError'))\n if (historyData.ok !== true) throw new Error(historyData.error ?? t('queueError'))\n // Active queue: earliest submitted first (running on top, later joins append below).\n setActive([...(activeData.jobs ?? [])].sort((a, b) => (a.createTime ?? 0) - (b.createTime ?? 0)))\n setHistory(historyData.jobs)\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n }\n }\n\n useEffect(() => {\n void load(filter)\n const timer = setInterval(() => void load(filter), 3_000)\n return () => clearInterval(timer)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [filter])\n\n const act = async (payload: Record<string, unknown>): Promise<void> => {\n setBusy(true)\n try {\n const data = (await postJson('/comfyui/jobs/actions', payload)) as { ok: boolean; error?: string }\n if (data.ok !== true) throw new Error(data.error ?? 'action failed')\n await load(filter)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }\n\n if (error !== null) return h('div', null, h(ErrorNote, { t, message: error }))\n if (active === null || history === null) return h('div', { className: 'dsc-meta' }, '…')\n\n // Preview image sequence over the history list, plus each job's position in it.\n const historyPreviewUrls = history.map(previewUrlOf)\n const previewImages = historyPreviewUrls.filter((url): url is string => url !== null)\n const previewPrefix: number[] = []\n {\n let acc = 0\n for (const url of historyPreviewUrls) {\n previewPrefix.push(acc)\n if (url !== null) acc += 1\n }\n }\n\n return h('div', { className: 'dsc-list' },\n h('div', { className: 'dsc-queue-actions' },\n h('button', { className: 'dsc-btn', onClick: () => void act({ action: 'clear' }), disabled: busy }, t('jobClearQueue')),\n h('button', { className: 'dsc-btn', onClick: () => void act({ action: 'clearHistory' }), disabled: busy }, t('jobClearHistory')),\n h('button', { className: 'dsc-btn', onClick: () => void act({ action: 'free', unloadModels: true, freeMemory: true }), disabled: busy }, t('jobFree')),\n ),\n h('div', { className: 'dsc-section' },\n h('div', { className: 'dsc-section-head' },\n h('span', { className: 'dsc-section-title' }, `${t('jobActive')} (${active.length})`),\n ),\n active.length === 0\n ? h('div', { className: 'dsc-meta' }, t('queueEmpty'))\n : h('div', { className: 'dsc-list' }, active.map((job) => h(JobRow, { key: job.id, job, t, busy, act }))),\n ),\n h('div', { className: 'dsc-section' },\n h('div', { className: 'dsc-section-head' },\n h('span', { className: 'dsc-section-title' }, `${t('jobFilterLabel')} (${history.length})`),\n h('div', { className: 'dsc-queue-head' },\n JOB_FILTERS.map((item) =>\n h('button', {\n key: item.key,\n className: `dsc-chip${filter === item.key ? ' dsc-chip--active' : ''}`,\n onClick: () => setFilter(item.key),\n disabled: busy,\n }, t(item.label))),\n ),\n ),\n history.length === 0\n ? h('div', { className: 'dsc-meta' }, t('queueEmpty'))\n : h('div', { className: 'dsc-list' }, history.map((job, index) => h(JobRow, {\n key: job.id,\n job,\n t,\n busy,\n act,\n onPreview: historyPreviewUrls[index] !== null && previewImages.length > 0\n ? () => onPreview(previewImages, previewImages.map(() => 'image' as const), previewPrefix[index]!)\n : undefined,\n }))),\n ),\n )\n}\n\nfunction jobBadge(status: JobStatus): string {\n switch (status) {\n case 'in_progress': return 'dsc-badge--info'\n case 'completed': return 'dsc-badge--ok'\n case 'failed': return 'dsc-badge--danger'\n default: return ''\n }\n}\n\nconst STATUS_LABELS: Record<JobStatus, string> = {\n pending: 'jobFilterPending',\n in_progress: 'jobFilterInProgress',\n completed: 'jobFilterCompleted',\n failed: 'jobFilterFailed',\n cancelled: 'jobFilterCancelled',\n}\n\n/**\n * One task card: a compact row with a status badge, task name + short id,\n * duration (and error/progress for in-flight tasks), and a ⋯ menu with\n * per-state actions. Hover highlights the row. Rendered as a component\n * instance (h(JobRow, ...)) so its hooks stay per-card.\n */\nfunction JobRow(props: {\n job: JobView\n t: ComfyUIPanelProps['t']\n busy: boolean\n act: (payload: Record<string, unknown>) => Promise<void>\n onPreview?: () => void\n}): ReturnType<typeof h> {\n const { job, t, busy, act, onPreview } = props\n const [menuOpen, setMenuOpen] = useState(false)\n const menuRef = useRef<HTMLDivElement | null>(null)\n\n useEffect(() => {\n if (!menuOpen) return\n const onDoc = (event: MouseEvent): void => {\n if (menuRef.current !== null && !menuRef.current.contains(event.target as Node)) setMenuOpen(false)\n }\n document.addEventListener('mousedown', onDoc)\n return () => document.removeEventListener('mousedown', onDoc)\n }, [menuOpen])\n\n const running = job.status === 'in_progress'\n const terminal = job.status === 'completed' || job.status === 'failed' || job.status === 'cancelled'\n const pct = job.progress !== null && job.progress !== undefined && job.progress.max > 0\n ? Math.min(100, Math.round((job.progress.value / job.progress.max) * 100))\n : null\n const duration = job.executionStartTime !== null && job.executionEndTime !== null\n ? Math.max(0, Math.round(((job.executionEndTime ?? 0) - (job.executionStartTime ?? 0)) / 1000))\n : null\n const errMsg = job.executionError?.exception_message ?? job.executionError?.message\n const name = job.workflowName ?? job.workflowId\n const preview = previewUrlOf(job)\n const close = (): void => setMenuOpen(false)\n const statusClass = job.status === 'failed' ? ' dsc-job-item--failed' : job.status === 'cancelled' ? ' dsc-job-item--cancelled' : ''\n\n return h('div', { className: `dsc-job-item${statusClass}` },\n preview !== null\n ? h('img', {\n src: preview,\n alt: '',\n loading: 'lazy',\n className: onPreview !== undefined ? 'dsc-job-preview dsc-job-preview--clickable' : 'dsc-job-preview',\n onClick: onPreview,\n })\n : null,\n h('div', { className: 'dsc-job-main' },\n h('div', { className: 'dsc-job-name', title: name ?? undefined },\n name !== null && name !== undefined && name !== '' ? name : '—',\n ),\n h('div', { className: 'dsc-job-mid' },\n running && job.progress !== null && job.progress !== undefined\n ? h('div', { className: 'dsc-progress' },\n h('div', { className: 'dsc-progress-track' },\n h('div', { className: 'dsc-progress-fill', style: { width: `${pct ?? 0}%` } }),\n ),\n h('span', { className: 'dsc-job-progress' },\n `${job.progress.value}/${job.progress.max} · ${pct ?? 0}%`,\n ),\n )\n : null,\n h('div', { className: 'dsc-job-mid-right' },\n h('span', { className: `dsc-badge dsc-badge--status ${jobBadge(job.status)}` }, t(STATUS_LABELS[job.status] ?? job.status)),\n h('div', { ref: menuRef, className: 'dsc-job-menu' },\n h('button', {\n className: 'dsc-job-menu-btn',\n 'aria-label': t('jobMore'),\n onClick: () => setMenuOpen(!menuOpen),\n }, '⋯'),\n menuOpen ? h('div', { className: 'dsc-job-menu-pop' },\n job.status === 'pending'\n ? h('button', { onClick: () => { void act({ action: 'delete', ids: [job.id] }); close() } }, t('jobDelete'))\n : null,\n running\n ? h('button', { onClick: () => { void act({ action: 'interrupt', promptId: job.id }); close() } }, t('jobInterrupt'))\n : null,\n terminal\n ? h('button', { onClick: () => { void act({ action: 'deleteHistory', ids: [job.id] }); close() } }, t('jobDelete'))\n : null,\n terminal\n ? h('button', { onClick: () => { void act({ action: 'rerun', jobId: job.id }); close() } }, t('jobRerun'))\n : null,\n terminal\n ? h('button', { onClick: () => { panelStore.setAssetFilter(name ?? ''); panelStore.setTab('assets'); close() } }, t('jobViewAssets'))\n : null,\n ) : null,\n ),\n ),\n ),\n h('div', { className: 'dsc-job-bottom' },\n h('span', { className: 'dsc-job-duration' }, `${t('jobDuration')} ${duration ?? 0}s`),\n errMsg !== undefined && errMsg !== null ? h('span', { className: 'dsc-job-error', title: errMsg }, errMsg) : null,\n ),\n ),\n )\n}\n","/**\n * dsh-comfyui stylesheet, injected once with plugin ownership. Colors come\n * from the host theme tokens (--dsw-alias-*), so the UI follows light/dark.\n */\nconst CSS = `\n/* --- shared primitives --- */\n.dsc-card {\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n padding: 10px 12px;\n margin: 4px 0;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n.dsc-card-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }\n.dsc-badge {\n border-radius: 999px; padding: 1px 8px; font-size: 11px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-secondary);\n}\n.dsc-badge--ok { background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 16%, transparent); }\n.dsc-badge--err { background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 16%, transparent); }\n.dsc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; margin-top: 6px; }\n.dsc-media { border-radius: 6px; overflow: hidden; background: var(--dsw-alias-bg-layer-1); }\n.dsc-media img, .dsc-media video, .dsc-media audio { display: block; width: 100%; max-height: 320px; object-fit: contain; background: #000; }\n.dsc-media audio { height: 44px; }\n.dsc-media-img--clickable { cursor: zoom-in; }\n.dsc-media-other { display: block; padding: 8px 6px; font-size: 12px; color: var(--dsw-alias-label-secondary); word-break: break-all; }\n.dsc-media-meta { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 3px 6px; }\n.dsc-media-size { font-size: 11px; color: var(--dsw-alias-label-secondary); white-space: nowrap; }\n.dsc-media-meta a { display: inline; padding: 0; font-size: 11px; color: var(--dsw-alias-label-secondary); text-decoration: none; }\n.dsc-media-meta a:hover { color: var(--dsw-alias-label-primary); }\n.dsc-meta { color: var(--dsw-alias-label-secondary); font-size: 12px; }\n.dsc-err { color: var(--dsw-alias-state-error-primary); font-size: 12px; margin: 4px 0; }\n.dsc-ok { color: var(--dsw-alias-state-success-primary); font-size: 12px; margin: 4px 0; }\n.dsc-form { display: flex; flex-direction: column; gap: 12px; max-width: 460px; }\n.dsc-field label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 4px; color: var(--dsw-alias-label-primary); }\n.dsc-input, .dsc-textarea {\n width: 100%; box-sizing: border-box; padding: 6px 8px; border-radius: 6px;\n border: 1px solid var(--dsw-alias-border-l1);\n background: transparent; color: inherit; font-size: 13px;\n}\nselect.dsc-input { background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); color-scheme: inherit; }\nselect.dsc-input option { background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); }\n.dsc-textarea { min-height: 90px; resize: vertical; font-family: ui-monospace, monospace; }\n.dsc-hint { font-size: 12px; color: var(--dsw-alias-label-secondary); margin-top: 2px; }\n.dsc-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }\n.dsc-btn {\n border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px;\n background: transparent; color: inherit; padding: 5px 12px; font-size: 13px; cursor: pointer;\n}\n.dsc-btn:disabled { opacity: 0.5; cursor: default; }\n.dsc-btn--link { display: inline-block; text-decoration: none; }\n/* --- header action trigger --- */\n.dsc-trigger {\n display: inline-flex; align-items: center; gap: 5px;\n border: 1px solid transparent; background: transparent; color: var(--dsw-alias-label-secondary);\n cursor: pointer; font-size: 13px; padding: 3px 8px; border-radius: 6px;\n white-space: nowrap;\n}\n.dsc-trigger:hover { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-bg-layer-1); border-color: var(--dsw-alias-border-l1); }\n.dsc-trigger[aria-pressed='true'] { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-bg-layer-2); }\n.dsc-trigger-glyph { font-size: 13px; line-height: 1; }\n/* --- connection reminder toast: fixed at the top of the page, mounted by the\n header trigger when the backend probe cannot reach ComfyUI. The probing\n state fades in after a short delay so a fast successful probe never paints;\n the fail state is sticky until dismissed or a later probe recovers. --- */\n.dsc-conn-toast {\n position: fixed; top: 14px; left: 50%;\n z-index: 980;\n display: flex; align-items: flex-start; gap: 10px;\n max-width: min(560px, 92vw);\n padding: 10px 12px;\n background: var(--dsw-alias-bg-layer-2);\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n box-shadow: 0 10px 32px rgba(0, 0, 0, 0.3);\n color: var(--dsw-alias-label-primary);\n font-size: 12px; line-height: 1.5;\n animation: dsc-conn-toast-in 0.16s ease-out both;\n}\n.dsc-conn-toast--probing { animation-delay: 0.45s; }\n.dsc-conn-toast--ok { border-color: var(--dsw-alias-state-success-primary); }\n.dsc-conn-toast--fail { border-color: var(--dsw-alias-state-error-primary); }\n.dsc-conn-toast-dot { flex: none; width: 8px; height: 8px; margin-top: 5px; border-radius: 50%; }\n.dsc-conn-toast--probing .dsc-conn-toast-dot { background: var(--dsw-alias-state-warn-primary); animation: dsc-conn-dot 1s ease-in-out infinite; }\n.dsc-conn-toast--ok .dsc-conn-toast-dot { background: var(--dsw-alias-state-success-primary); }\n.dsc-conn-toast--fail .dsc-conn-toast-dot { background: var(--dsw-alias-state-error-primary); }\n.dsc-conn-toast-body { min-width: 0; }\n.dsc-conn-toast-title { font-weight: 600; }\n.dsc-conn-toast--fail .dsc-conn-toast-title { color: var(--dsw-alias-state-error-primary); }\n.dsc-conn-toast--ok .dsc-conn-toast-title { color: var(--dsw-alias-state-success-primary); }\n.dsc-conn-toast-text { color: var(--dsw-alias-label-secondary); margin-top: 2px; overflow-wrap: anywhere; }\n.dsc-conn-toast-close { flex: none; border: none; background: transparent; color: var(--dsw-alias-label-tertiary); cursor: pointer; font-size: 13px; padding: 2px 4px; line-height: 1; }\n.dsc-conn-toast-close:hover { color: var(--dsw-alias-label-primary); }\n@keyframes dsc-conn-toast-in { from { opacity: 0; transform: translate(-50%, -6px); } to { opacity: 1; transform: translate(-50%, 0); } }\n@keyframes dsc-conn-dot { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }\n/* --- panel shell: floating window, percentage-anchored to the page header\n (top) and the composer (bottom), draggable by the header and resizable via\n the corner handle. Follows the host light/dark theme. --- */\n.dsc-panel {\n position: fixed;\n top: var(--dsc-panel-top, 9%);\n right: var(--dsc-panel-right, 1.5%);\n bottom: var(--dsc-panel-bottom, 2%);\n width: var(--dsc-panel-width, 400px);\n max-width: min(92vw, 560px); min-width: 300px;\n z-index: 900;\n display: flex; flex-direction: column;\n background: var(--dsw-alias-bg-layer-1);\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 14px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.28), 0 2px 8px rgba(0, 0, 0, 0.12);\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n user-select: none;\n}\n.dsc-panel--dragging { cursor: grabbing; }\n.dsc-panel-head { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; border-bottom: 1px solid var(--dsw-alias-border-l1); cursor: grab; touch-action: none; }\n.dsc-panel--dragging .dsc-panel-head { cursor: grabbing; }\n.dsc-panel-resize {\n position: absolute; right: 0; bottom: 0; width: 16px; height: 16px;\n cursor: nwse-resize; touch-action: none;\n background: linear-gradient(135deg, transparent 50%, var(--dsw-alias-label-tertiary) 50%);\n border-bottom-right-radius: 14px;\n opacity: 0.55;\n}\n.dsc-panel-resize:hover { opacity: 1; }\n.dsc-panel-title { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; font-size: 14px; }\n.dsc-panel-head-actions { display: inline-flex; align-items: center; gap: 2px; }\n.dsc-panel-reset { border: none; background: transparent; color: var(--dsw-alias-label-tertiary); cursor: pointer; font-size: 13px; padding: 4px 6px; line-height: 1; }\n.dsc-panel-reset:hover { color: var(--dsw-alias-label-primary); }\n.dsc-panel-close { border: none; background: transparent; color: var(--dsw-alias-label-secondary); cursor: pointer; font-size: 14px; padding: 4px 8px; }\n.dsc-panel-close:hover { color: var(--dsw-alias-label-primary); }\n.dsc-tabs { display: flex; border-bottom: 1px solid var(--dsw-alias-border-l1); }\n.dsc-tab {\n flex: 1; padding: 8px 4px; background: transparent; border: none;\n border-bottom: 2px solid transparent; color: var(--dsw-alias-label-secondary);\n cursor: pointer; font-size: 13px;\n}\n.dsc-tab--active { color: var(--dsw-alias-label-primary); border-bottom-color: var(--dsw-alias-brand-primary); }\n.dsc-panel-body { flex: 1; overflow-y: auto; padding: 10px 12px; }\n.dsc-toolbar { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; flex-wrap: wrap; }\n.dsc-list { display: flex; flex-direction: column; gap: 8px; }\n/* --- workflows tab --- */\n.dsc-wf { border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 8px 10px; background: var(--dsw-alias-bg-layer-1); transition: background 0.12s, border-color 0.12s; cursor: pointer; }\n.dsc-wf:hover { background: var(--dsw-alias-bg-layer-2); border-color: var(--dsw-alias-border-l2); }\n.dsc-wf-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }\n.dsc-wf--comfyui { display: flex; align-items: center; gap: 10px; }\n.dsc-wf-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }\n.dsc-wf-name { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsc-wf-desc { color: var(--dsw-alias-label-secondary); font-size: 12px; margin: 2px 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.dsc-wf-updated { color: var(--dsw-alias-label-tertiary); font-size: 11px; margin-top: 4px; }\n.dsc-wf-actions { display: flex; gap: 6px; margin-top: 6px; }\n.dsc-section { margin-top: 14px; }\n.dsc-section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }\n.dsc-section-title { font-weight: 600; font-size: 13px; }\n.dsc-fold { border: 1px solid var(--dsw-alias-border-l1); border-radius: 10px; margin-top: 10px; overflow: hidden; background: var(--dsw-alias-bg-layer-1); }\n.dsc-fold summary { list-style: none; display: flex; align-items: center; gap: 6px; padding: 8px 10px; cursor: pointer; user-select: none; font-weight: 600; font-size: 13px; }\n.dsc-fold summary::-webkit-details-marker { display: none; }\n.dsc-fold summary::before { content: '▸'; font-size: 11px; color: var(--dsw-alias-label-secondary); transition: transform 0.15s; }\n.dsc-fold[open] summary::before { transform: rotate(90deg); }\n.dsc-fold summary:hover { background: var(--dsw-alias-bg-layer-2); }\n.dsc-fold-body { padding: 0 10px 10px; }\n.dsc-hint { color: var(--dsw-alias-label-secondary); font-size: 11px; margin: 2px 0 6px; white-space: pre-line; }\n.dsc-badge { font-size: 11px; padding: 1px 8px; border-radius: 999px; }\n.dsc-badge--ok { color: var(--dsw-alias-state-success-primary); border: 1px solid var(--dsw-alias-state-success-primary); }\n.dsc-badge--warn { color: var(--dsw-alias-state-warn-primary); border: 1px solid var(--dsw-alias-state-warn-primary); }\n.dsc-view-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }\n.dsc-view-label { font-weight: 600; font-size: 12px; margin: 8px 0 4px; }\n.dsc-node-list { margin: 0; padding-left: 18px; font-size: 12px; color: var(--dsw-alias-label-secondary); max-height: 180px; overflow-y: auto; }\n.dsc-node-list li { margin: 2px 0; }\n.dsc-textarea--view { min-height: 220px; resize: vertical; }\n.dsc-derived { margin: 6px 0; display: flex; flex-direction: column; gap: 4px; }\n.dsc-derived-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 12px; }\n.dsc-derived-name { color: var(--dsw-alias-label-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsc-dialog { border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 10px; }\n/* --- skill pack editor: file list beside a plain-text editor --- */\n.dsc-skill { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; margin-top: 8px; }\n.dsc-skill-files { flex: 0 0 190px; min-width: 160px; display: flex; flex-direction: column; gap: 6px; }\n.dsc-skill-main { flex: 1 1 300px; min-width: 260px; display: flex; flex-direction: column; gap: 6px; }\n.dsc-skill-bucket { display: flex; flex-direction: column; gap: 2px; }\n/* Foldable pack directories: each folder renders as a <details> whose header\n stays put while its files collapse, keeping crowded packs scannable. */\n.dsc-skill-fold { border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; margin: 2px 0; }\n.dsc-skill-fold summary { padding: 5px 10px; font-size: 12px; color: var(--dsw-alias-label-secondary); border-radius: 8px; }\n.dsc-skill-fold[open] summary { color: var(--dsw-alias-label-primary); border-bottom: 1px solid var(--dsw-alias-border-l1); border-radius: 8px 8px 0 0; }\n.dsc-skill-fold .dsc-skill-bucket { padding: 4px 6px 6px; }\n.dsc-skill-file {\n display: flex; align-items: center; justify-content: space-between; gap: 6px;\n border: 1px solid transparent; border-radius: 6px; background: transparent;\n color: inherit; font-size: 12px; padding: 4px 6px; cursor: pointer; text-align: left;\n}\n.dsc-skill-file:hover { background: var(--dsw-alias-bg-layer-2); }\n.dsc-skill-file--active { border-color: var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-2); }\n.dsc-skill-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsc-skill-file-size { color: var(--dsw-alias-label-secondary); font-size: 11px; flex: none; }\n.dsc-skill-create { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }\n.dsc-skill-editor-head { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 600; }\n.dsc-skill-path { color: var(--dsw-alias-label-primary); }\n.dsc-textarea--skill { min-height: 260px; font-size: 12px; line-height: 1.5; }\n.dsc-skill-preview { border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 10px; display: flex; flex-direction: column; gap: 6px; align-items: center; }\n.dsc-skill-preview img { max-width: 100%; max-height: 320px; object-fit: contain; border-radius: 6px; }\n.dsc-skill-dir { font-size: 11px; color: var(--dsw-alias-label-secondary); margin: 4px 0; word-break: break-all; }\n.dsc-skill-flags { margin-top: 6px; }\n.dsc-skill-footer { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }\n.dsc-skill-actions { display: flex; gap: 6px; flex-wrap: wrap; }\n.dsc-skill-drop-hint { font-size: 11px; color: var(--dsw-alias-label-secondary); border: 1px dashed var(--dsw-alias-border-l1); border-radius: 6px; padding: 4px 6px; text-align: center; }\n.dsc-dialog--danger { border-color: var(--dsw-alias-state-error-primary); }\n.dsc-danger-text { color: var(--dsw-alias-state-error-primary); font-weight: 600; font-size: 12px; line-height: 1.5; }\n.dsc-check { display: flex; align-items: center; gap: 6px; font-size: 12px; }\n.dsc-dialog-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }\n.dsc-extract-modes { display: flex; flex-direction: column; gap: 8px; margin: 10px 0; }\n.dsc-mode { display: flex; flex-direction: column; gap: 2px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 8px 10px; cursor: pointer; }\n.dsc-mode input { accent-color: var(--dsw-alias-brand-primary); }\n.dsc-mode-label { font-size: 13px; }\n/* --- assets tab --- */\n.dsc-assets-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 8px; }\n.dsc-asset { position: relative; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; overflow: hidden; cursor: pointer; background: var(--dsw-alias-bg-layer-1); }\n/* Destructive, so it only appears while the pointer is on the card. */\n.dsc-asset-trash {\n position: absolute; top: 4px; right: 4px; width: 26px; height: 26px; padding: 0; line-height: 1;\n display: flex; align-items: center; justify-content: center;\n border: 1px solid var(--dsw-alias-state-error-primary); border-radius: 6px;\n background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-state-error-primary);\n font-size: 14px; cursor: pointer; opacity: 0; transition: opacity 0.12s;\n}\n.dsc-asset:hover .dsc-asset-trash, .dsc-asset-trash:focus-visible { opacity: 1; }\n.dsc-asset-trash:hover { background: var(--dsw-alias-state-error-primary); color: #fff; }\n.dsc-asset img, .dsc-asset video { width: 100%; height: 110px; object-fit: cover; display: block; background: #000; }\n.dsc-asset-audio-icon { position: relative; width: 100%; height: 110px; box-sizing: border-box; padding: 0 6px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; background: #26702b; overflow: hidden; }\n.dsc-asset-audio-icon-wave { position: absolute; inset: 0; width: 100%; height: 100%; }\n.dsc-asset-audio-icon-sym { position: relative; width: 42px; height: 42px; color: #fff; }\n.dsc-asset-audio-icon-name { position: relative; max-width: 100%; font-size: 11px; color: rgba(255, 255, 255, 0.9); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.dsc-asset--empty {\n height: 110px; padding: 8px; box-sizing: border-box;\n display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 4px;\n font-size: 11px; color: var(--dsw-alias-label-secondary); text-align: center;\n}\n.dsc-asset-meta { padding: 3px 6px; font-size: 11px; color: var(--dsw-alias-label-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n/* confirmation modal (asset deletion) */\n.dsc-confirm { width: min(360px, 88vw); display: flex; flex-direction: column; gap: 8px; padding: 14px 16px; border-radius: 12px; border: 1px solid var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.32); }\n.dsc-confirm-title { font-weight: 600; font-size: 14px; }\n.dsc-confirm-body { font-size: 13px; line-height: 1.6; color: var(--dsw-alias-label-secondary); }\n.dsc-confirm-detail { font-size: 12px; line-height: 1.5; color: var(--dsw-alias-label-tertiary); word-break: break-all; max-height: 96px; overflow-y: auto; }\n.dsc-confirm-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 4px; }\n.dsc-btn--danger { border-color: var(--dsw-alias-state-error-primary); color: var(--dsw-alias-state-error-primary); }\n.dsc-btn--danger:hover:not(:disabled) { background: var(--dsw-alias-state-error-primary); color: #fff; }\n.dsc-asset-detail-media { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }\n.dsc-asset-detail-media img, .dsc-asset-detail-media video { width: 100%; max-height: 320px; object-fit: contain; background: #000; border-radius: 8px; }\n.dsc-asset-detail-file { display: flex; align-items: center; justify-content: space-between; gap: 8px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 6px 8px; }\n.dsc-input--inline { width: auto; }\n/* --- queue tab --- */\n.dsc-queue-head { display: flex; gap: 8px; flex-wrap: wrap; }\n.dsc-queue-item { display: flex; gap: 8px; align-items: center; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 6px 8px; font-size: 12px; flex-wrap: wrap; }\n.dsc-queue-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 180px; }\n.dsc-queue-meta { color: var(--dsw-alias-label-secondary); font-size: 11px; }\n.dsc-queue-tracked { margin-top: 10px; display: flex; flex-direction: column; gap: 4px; }\n.dsc-progress { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 90px; }\n.dsc-progress-track { flex: 1; height: 6px; border-radius: 3px; background: var(--dsw-alias-bg-layer-2); overflow: hidden; }\n.dsc-progress-fill { height: 100%; background: #3b82f6; transition: width 0.4s; }\n.dsc-progress:hover .dsc-progress-fill { background: #2563eb; }\n.dsc-param-upload-wrap { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1; }\n.dsc-param-upload-wrap select { flex: 1; min-width: 0; }\n.dsc-dropzone { flex: 1; min-width: 120px; border: 1px dashed var(--dsw-alias-border-l2); border-radius: 6px; padding: 5px 10px; font-size: 11px; color: var(--dsw-alias-label-secondary); text-align: center; cursor: pointer; transition: border-color 0.12s, color 0.12s; }\n.dsc-dropzone:hover, .dsc-dropzone--over { border-color: #3b82f6; color: #3b82f6; }\n.dsc-upload-select { position: relative; flex: 1; min-width: 0; }\n.dsc-upload-select-btn { display: flex; align-items: center; gap: 6px; width: 100%; border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; padding: 3px 8px; background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); cursor: pointer; font-size: 12px; text-align: left; }\n.dsc-upload-select-btn:hover { border-color: var(--dsw-alias-border-l2); }\n.dsc-upload-select-thumb { width: 36px; height: 24px; object-fit: cover; border-radius: 3px; background: var(--dsw-alias-bg-layer-2); flex: none; }\n.dsc-upload-select-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }\n.dsc-upload-select-pop { position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 30; max-height: 220px; overflow-y: auto; border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; background: var(--dsw-alias-bg-layer-2); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35); padding: 4px; }\n.dsc-upload-select-item { display: flex; align-items: center; gap: 8px; padding: 5px 8px; border-radius: 6px; cursor: pointer; font-size: 12px; color: var(--dsw-alias-label-primary); }\n.dsc-upload-select-item:hover { background: var(--dsw-alias-bg-layer-3); }\n.dsc-upload-dock { margin-top: 14px; border-top: 1px solid var(--dsw-alias-border-l1); padding-top: 10px; display: flex; flex-direction: column; gap: 8px; }\n.dsc-upload-dock-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }\n.dsc-upload-dock-title { font-weight: 600; font-size: 12px; color: var(--dsw-alias-label-primary); }\n.dsc-upload-dock-zone { min-height: 44px; display: flex; align-items: center; justify-content: center; }\n.dsc-upload-list { display: flex; flex-direction: column; gap: 4px; }\n.dsc-upload-item { display: flex; align-items: center; gap: 8px; }\n.dsc-upload-thumb { width: 40px; height: 28px; object-fit: cover; border-radius: 4px; background: var(--dsw-alias-bg-layer-2); flex: none; }\n.dsc-upload-thumb--media { display: inline-flex; align-items: center; justify-content: center; font-size: 14px; }\n.dsc-upload-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: var(--dsw-alias-label-primary); }\n.dsc-upload-select-item--active { background: var(--dsw-alias-bg-layer-3); }\n/* --- load area: big preview + picker dialog (ComfyUI LoadImage-like) --- */\n.dsc-loadarea { margin-top: 14px; border-top: 1px solid var(--dsw-alias-border-l1); padding-top: 10px; display: flex; flex-direction: column; gap: 8px; }\n.dsc-loadarea-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }\n.dsc-loadarea-title { font-weight: 600; font-size: 12px; color: var(--dsw-alias-label-primary); }\n/* load-area slots: slot 0 is the primary (big) source, the rest are thumbs.\n Each slot carries its own actions (add / clear media / delete slot). */\n.dsc-loadslots { display: flex; flex-wrap: wrap; gap: 8px; }\n/* One slot stretches across the panel; from two on they share a fixed width\n and wrap into rows. The × sits in the corner and appears on hover. */\n.dsc-loadslot { position: relative; display: flex; flex-direction: column; gap: 4px; width: 128px; border: 1px solid var(--dsw-alias-border-l2); border-radius: 10px; padding: 6px; background: var(--dsw-alias-bg-layer-1); }\n.dsc-loadslot--wide { width: 100%; }\n.dsc-loadslot-pick { display: flex; flex-direction: column; align-items: center; gap: 4px; border: none; border-radius: 8px; padding: 0; background: transparent; color: inherit; cursor: pointer; width: 100%; }\n.dsc-loadslot-media { width: 100%; height: 104px; object-fit: contain; border-radius: 6px; background: var(--dsw-alias-bg-layer-2); }\n.dsc-loadslot--wide .dsc-loadslot-media { height: 220px; }\n.dsc-loadslot-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; width: 100%; height: 104px; border-radius: 6px; border: 1px dashed var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-2); font-size: 12px; }\n.dsc-loadslot--wide .dsc-loadslot-empty { height: 120px; font-size: 13px; }\n.dsc-loadslot-name { width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; color: var(--dsw-alias-label-primary); text-align: center; }\n.dsc-loadslot-index { color: var(--dsw-alias-label-tertiary); }\n.dsc-loadslot-add { color: var(--dsw-alias-label-secondary); }\n.dsc-loadslot-pick:hover .dsc-loadslot-add { color: var(--dsw-alias-brand-primary); }\n.dsc-loadslot-x {\n position: absolute; top: 3px; right: 3px; width: 26px; height: 26px; padding: 0; line-height: 1;\n display: flex; align-items: center; justify-content: center;\n border: 1px solid var(--dsw-alias-border-l2); border-radius: 50%;\n background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-secondary);\n font-size: 18px; cursor: pointer; opacity: 0; transition: opacity 0.12s;\n}\n.dsc-loadslot:hover .dsc-loadslot-x, .dsc-loadslot-x:focus-visible { opacity: 1; }\n.dsc-loadslot-x:hover { color: var(--dsw-alias-state-error-primary); border-color: var(--dsw-alias-state-error-primary); }\n.dsc-picker-player { width: 100%; border-radius: 6px; background: var(--dsw-alias-bg-layer-1); }\nvideo.dsc-picker-player { max-height: 180px; }\n.dsc-picker-player--audio { height: 34px; }\n.dsc-loadslot-x:disabled { opacity: 0; cursor: default; }\n.dsc-picker-card--none .dsc-picker-thumb--media { font-size: 26px; color: var(--dsw-alias-label-tertiary); }\n/* picker overlay: dims the page, dialog floats in the center */\n.dsc-picker-overlay { position: fixed; inset: 0; z-index: 9990; background: rgba(6, 8, 12, 0.6); display: flex; align-items: center; justify-content: center; padding: 24px; }\n.dsc-picker { position: relative; display: flex; flex-direction: column; width: min(860px, 92vw); height: min(560px, 84vh); background: var(--dsw-alias-bg-layer-1); border: 1px solid var(--dsw-alias-border-l2); border-radius: 12px; box-shadow: 0 16px 56px rgba(0, 0, 0, 0.5); overflow: hidden; }\n.dsc-picker-toast { position: absolute; top: 54px; left: 50%; transform: translateX(-50%); z-index: 5; background: var(--dsw-alias-brand-primary); color: var(--dsw-alias-bg-layer-1); padding: 6px 14px; border-radius: 8px; font-size: 12px; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); pointer-events: none; max-width: 80%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsc-picker-bar { display: flex; align-items: center; gap: 4px; padding: 8px 10px; border-bottom: 1px solid var(--dsw-alias-border-l1); flex-wrap: wrap; }\n.dsc-picker-tab { border: 1px solid transparent; border-radius: 6px; padding: 4px 12px; font-size: 12px; cursor: pointer; background: transparent; color: var(--dsw-alias-label-primary); }\n.dsc-picker-tab--active { background: var(--dsw-alias-brand-primary); color: var(--dsw-alias-bg-layer-1); }\n.dsc-picker-tabs { display: flex; gap: 4px; }\n.dsc-picker-type { flex: none; border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; padding: 3px 8px; font-size: 12px; background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); }\n.dsc-picker-upload { margin: 0 auto; flex: none; max-width: 200px; min-height: 32px; display: flex; align-items: center; justify-content: center; padding: 0 12px; font-size: 12px; white-space: nowrap; }\n.dsc-picker-empty { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; color: var(--dsw-alias-label-tertiary); font-size: 13px; }\n.dsc-picker-grid { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 12px; display: flex; gap: 10px; align-items: flex-start; }\n.dsc-picker-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }\n.dsc-picker-card { display: flex; flex-direction: column; gap: 4px; min-width: 0; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 6px; background: var(--dsw-alias-bg-layer-2); cursor: pointer; text-align: left; }\n.dsc-picker-card:hover { border-color: #3b82f6; }\n.dsc-picker-card--active { border-color: var(--dsw-alias-brand-primary); box-shadow: 0 0 0 1px var(--dsw-alias-brand-primary); }\n.dsc-picker-thumb { width: 100%; height: auto; object-fit: contain; border-radius: 6px; background: var(--dsw-alias-bg-layer-1); }\n.dsc-picker-thumb--media { display: flex; align-items: center; justify-content: center; height: 100px; font-size: 22px; }\n.dsc-picker-name { font-size: 13px; line-height: 1.5; padding: 2px 0; color: var(--dsw-alias-label-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.dsc-picker-card:hover .dsc-picker-name { color: var(--dsw-alias-brand-primary); }\n/* --- workflow tags: filter bar, chips, editor --- */\n.dsc-tag-filter { display: flex; justify-content: flex-end; padding: 6px 0 2px; }\n.dsc-tag-chip { border: 1px solid var(--dsw-alias-border-l1); border-radius: 999px; padding: 2px 10px; font-size: 12px; cursor: pointer; background: transparent; color: var(--dsw-alias-label-primary); }\n.dsc-tag-chip--active { background: var(--dsw-alias-brand-primary); border-color: var(--dsw-alias-brand-primary); color: var(--dsw-alias-bg-layer-1); }\n.dsc-tag-chip--mini { font-size: 11px; padding: 1px 8px; cursor: default; border: 1px solid var(--dsw-alias-brand-primary); color: var(--dsw-alias-brand-primary); background: color-mix(in srgb, var(--dsw-alias-brand-primary) 10%, transparent); }\n.dsc-wf-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }\n.dsc-wf-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; min-width: 0; }\n.dsc-wf-top .dsc-wf-tags { margin-top: 0; flex: none; justify-content: flex-end; }\n.dsc-tag-editor { display: flex; flex-direction: column; gap: 6px; }\n.dsc-tag-row { display: flex; flex-wrap: wrap; gap: 6px; }\n.dsc-tag-input { max-width: 260px; }\n.dsc-chip { border: 1px solid var(--dsw-alias-border-l1); border-radius: 999px; padding: 2px 10px; font-size: 12px; cursor: pointer; background: transparent; color: var(--dsw-alias-label-primary); }\n.dsc-chip--active { background: var(--dsw-alias-brand-primary); border-color: var(--dsw-alias-brand-primary); color: var(--dsw-alias-bg-layer-1); }\n.dsc-badge--info { background: var(--dsw-alias-brand-primary); color: var(--dsw-alias-bg-layer-1); }\n.dsc-badge--danger { background: var(--dsw-alias-state-error-primary); color: #fff; }\n.dsc-queue-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }\n.dsc-btn { border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; padding: 2px 8px; font-size: 12px; cursor: pointer; background: transparent; color: var(--dsw-alias-label-primary); }\n.dsc-btn--sm { padding: 1px 6px; font-size: 11px; }\n.dsc-input--sm { padding: 3px 6px; font-size: 12px; }\n.dsc-btn:disabled { opacity: 0.5; cursor: default; }\n.dsc-job-item { display: flex; align-items: center; gap: 10px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 7px 10px; background: var(--dsw-alias-bg-layer-1); transition: background 0.12s, border-color 0.12s; }\n.dsc-job-item:hover { background: var(--dsw-alias-bg-layer-2); border-color: var(--dsw-alias-border-l2); }\n.dsc-job-item--failed { border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary) 55%, transparent); }\n.dsc-job-item--cancelled { border-color: var(--dsw-alias-border-l2); opacity: 0.85; }\n.dsc-badge--status { flex: none; font-weight: 600; }\n.dsc-job-preview { width: 56px; height: 56px; flex: none; border-radius: 6px; object-fit: cover; border: 1px solid var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-2); }\n.dsc-job-preview--clickable { cursor: zoom-in; }\n/* --- lightbox: floating local panel, no full-screen dim --- */\n.dsc-lightbox { position: fixed; inset: 0; z-index: 9999; background: transparent; display: flex; align-items: center; justify-content: center; }\n.dsc-lightbox-body { position: relative; display: flex; flex-direction: column; align-items: center; gap: 10px; width: 90vw; padding: 12px 12px 10px; background: rgba(12, 14, 18, 0.88); border: 1px solid var(--dsw-alias-border-l2); border-radius: 14px; box-shadow: 0 12px 48px rgba(0, 0, 0, 0.45); }\n.dsc-lightbox-img { width: 100%; height: 80vh; object-fit: contain; border-radius: 8px; }\n.dsc-lightbox-media { max-width: 100%; max-height: 80vh; border-radius: 8px; }\n.dsc-lightbox-meta { display: flex; align-items: center; gap: 14px; color: rgba(255, 255, 255, 0.75); font-size: 12px; }\n.dsc-lightbox-download { border: 1px solid rgba(255, 255, 255, 0.35); border-radius: 999px; padding: 5px 16px; color: #fff; font-size: 12px; text-decoration: none; display: inline-block; }\n.dsc-lightbox-download:hover { background: rgba(255, 255, 255, 0.12); }\n.dsc-lightbox-close { position: absolute; top: clamp(4px, 0.6vw, 14px); right: clamp(4px, 0.6vw, 14px); z-index: 3; width: clamp(28px, 2.2vw, 48px); height: clamp(28px, 2.2vw, 48px); border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.35); background: transparent; color: #fff; font-size: clamp(13px, 1.1vw, 22px); line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; }\n.dsc-lightbox-close:hover { background: rgba(255, 255, 255, 0.12); }\n.dsc-lightbox-nav { position: absolute; top: 0; bottom: 0; z-index: 2; width: clamp(64px, 7vw, 128px); display: flex; align-items: center; background: transparent; border: none; color: #fff; font-size: clamp(38px, 3.4vw, 84px); line-height: 1; cursor: pointer; opacity: 0.6; padding: 0; }\n.dsc-lightbox-nav:hover { opacity: 1; color: var(--dsw-alias-brand-primary); background: rgba(255, 255, 255, 0.06); }\n.dsc-lightbox-nav--prev { left: 0; justify-content: flex-start; padding-left: clamp(14px, 1.8vw, 36px); }\n.dsc-lightbox-nav--next { right: 0; justify-content: flex-end; padding-right: clamp(14px, 1.8vw, 36px); }\n.dsc-job-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }\n.dsc-job-name { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dsw-alias-label-primary); }\n.dsc-job-mid { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }\n.dsc-job-mid-right { display: flex; align-items: center; gap: 6px; flex: none; margin-left: auto; }\n.dsc-job-bottom { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--dsw-alias-label-secondary); min-width: 0; }\n.dsc-job-duration { flex: none; }\n.dsc-job-progress { color: #3b82f6; font-variant-numeric: tabular-nums; }\n.dsc-job-menu { position: relative; flex: none; }\n.dsc-job-menu-btn { border: none; background: transparent; color: var(--dsw-alias-label-secondary); font-size: 15px; line-height: 1; padding: 3px 7px; border-radius: 6px; cursor: pointer; }\n.dsc-job-menu-btn:hover { color: var(--dsw-alias-label-primary); background: var(--dsw-alias-bg-layer-2); }\n.dsc-job-menu-pop { position: absolute; right: 0; top: calc(100% + 4px); z-index: 950; min-width: 128px; padding: 4px; display: flex; flex-direction: column; gap: 2px; background: var(--dsw-alias-bg-layer-2); border: 1px solid var(--dsw-alias-border-l2); border-radius: 8px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25); }\n.dsc-job-menu-pop button { border: none; background: transparent; color: var(--dsw-alias-label-primary); text-align: left; font-size: 13px; padding: 6px 10px; border-radius: 6px; cursor: pointer; }\n.dsc-job-menu-pop button:hover { background: var(--dsw-alias-bg-layer-3); }\n.dsc-job-error { color: var(--dsw-alias-state-error-primary); font-size: 11px; margin-left: auto; flex: 1; min-width: 0; text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n/* --- parameter editor --- */\n.dsc-params { display: flex; flex-direction: column; gap: 8px; }\n.dsc-param-row { display: flex; flex-direction: column; gap: 6px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; padding: 6px 8px; }\n.dsc-param-fields { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }\n.dsc-param-default { min-width: 0; }\n.dsc-param-meta { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }\n.dsc-param-random { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--dsw-alias-label-secondary); cursor: pointer; }\n.dsc-param-bool { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--dsw-alias-label-primary); cursor: pointer; }\n.dsc-param-advanced { display: flex; flex-direction: column; gap: 8px; border: 1px dashed var(--dsw-alias-border-l2); border-radius: 8px; padding: 8px; }\n/* --- workflow preset transfer dialogs (export / import) --- */\n.dsc-transfer { position: relative; display: flex; flex-direction: column; width: min(580px, 92vw); max-height: min(640px, 86vh); background: var(--dsw-alias-bg-layer-1); border: 1px solid var(--dsw-alias-border-l2); border-radius: 12px; box-shadow: 0 16px 56px rgba(0, 0, 0, 0.5); overflow: hidden; }\n.dsc-transfer-head { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; border-bottom: 1px solid var(--dsw-alias-border-l1); }\n.dsc-transfer-title { font-weight: 600; font-size: 13px; color: var(--dsw-alias-label-primary); }\n.dsc-transfer-body { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px; overflow-y: auto; min-height: 0; }\n.dsc-transfer-bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; }\n.dsc-transfer-list { display: flex; flex-direction: column; gap: 4px; }\n.dsc-transfer-item { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border: 1px solid var(--dsw-alias-border-l1); border-radius: 8px; cursor: pointer; font-size: 12px; color: var(--dsw-alias-label-primary); }\n.dsc-transfer-item:hover { border-color: var(--dsw-alias-brand-primary); }\n.dsc-transfer-item--static, .dsc-transfer-item--static:hover { cursor: default; border-color: var(--dsw-alias-border-l1); }\n.dsc-transfer-item--ok { border-color: color-mix(in srgb, var(--dsw-alias-state-success-primary) 45%, transparent); }\n.dsc-transfer-item--fail { border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary) 45%, transparent); }\n.dsc-transfer-item-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 240px; }\n.dsc-transfer-item-desc { color: var(--dsw-alias-label-tertiary); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 40px; text-align: right; }\n.dsc-transfer-actions { display: flex; gap: 8px; justify-content: flex-end; padding: 10px 12px; border-top: 1px solid var(--dsw-alias-border-l1); }\n.dsc-transfer-note { padding: 6px 12px 0; }\n.dsc-transfer-note .dsc-hint { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.dsc-transfer-drop { display: flex; align-items: center; justify-content: center; min-height: 150px; border: 1px dashed var(--dsw-alias-border-l2); border-radius: 10px; color: var(--dsw-alias-label-secondary); font-size: 13px; cursor: pointer; text-align: center; padding: 12px; transition: border-color 0.12s, color 0.12s; }\n.dsc-transfer-drop:hover, .dsc-transfer-drop--over { border-color: var(--dsw-alias-brand-primary); color: var(--dsw-alias-brand-primary); }\n.dsc-transfer-empty { padding: 40px 12px; text-align: center; color: var(--dsw-alias-label-tertiary); font-size: 13px; }\n.dsc-btn--primary { background: var(--dsw-alias-brand-primary); border-color: var(--dsw-alias-brand-primary); color: var(--dsw-alias-bg-layer-1); }\n.dsc-btn--primary:disabled { opacity: 0.5; cursor: default; }\n`\n\n/** Inject the stylesheet once (idempotent), owned by this plugin for HMR. */\nexport function injectStyles(): void {\n if (typeof document === 'undefined') return\n if (document.getElementById('dsh-comfyui-styles') !== null) return\n const style = document.createElement('style')\n style.id = 'dsh-comfyui-styles'\n style.setAttribute('data-plugin', 'dsh-comfyui')\n style.textContent = CSS\n document.head.append(style)\n}\n","/**\n * dsh-comfyui client half: registers the comfyui_run tool card and the\n * ComfyUI settings page. Registered through slots.inject so contributions\n * wait on the real slot declarations and unwind with this plugin's fiber.\n */\nimport { createElement as h } from 'react'\nimport { makeT, getLang } from './i18n.ts'\nimport { ComfyUICard, type ComfyUICardProps } from './card.tsx'\nimport { ComfyUISettings, type ComfyUISettingsProps } from './settings.tsx'\nimport { ComfyUIPanel, type ComfyUIPanelProps } from './panel.tsx'\nimport { ComfyUITrigger, type ComfyUITriggerProps } from './trigger.tsx'\nimport { injectStyles } from './styles.ts'\n\nexport const name = 'dsh-comfyui'\nexport const inject = ['slots']\n\ninterface SlotsService {\n inject(slot: string, register: () => unknown): void\n register(meta: Record<string, unknown>, component: unknown): unknown\n}\n\ninterface ComfyUIClientContext {\n effect(callback: () => unknown, label?: string): void\n slots: SlotsService\n}\n\nexport function apply(ctx: ComfyUIClientContext): void {\n // Plugin-local i18n: language comes from localStorage (settings page), not\n // the host locale, so zh/en switching works without a host change.\n const t = makeT(getLang())\n ctx.effect(() => injectStyles(), 'dsh-comfyui: styles')\n\n ctx.slots.inject('tool.call.toolview', () => ctx.slots.register(\n { name: 'tool.call.toolview', key: 'comfyui_run' },\n (props: unknown) => h(ComfyUICard, { t, ...((props ?? {}) as Record<string, unknown>) } as unknown as ComfyUICardProps),\n ))\n\n ctx.slots.inject('tool.call.toolview', () => ctx.slots.register(\n { name: 'tool.call.toolview', key: 'comfyui_workflow' },\n (props: unknown) => h(ComfyUICard, { t, ...((props ?? {}) as Record<string, unknown>) } as unknown as ComfyUICardProps),\n ))\n\n ctx.slots.inject('settings.section', () => ctx.slots.register(\n { name: 'settings.section', id: 'comfyui', order: 30, label: () => t('settingsTitle') },\n (props: unknown) => h(ComfyUISettings, { t, ...((props ?? {}) as Record<string, unknown>) } as unknown as ComfyUISettingsProps),\n ))\n\n ctx.slots.inject('shell.overlay', () => ctx.slots.register(\n { name: 'shell.overlay', id: 'comfyui.panel', order: 20, label: () => t('panelTitle') },\n (props: unknown) => h(ComfyUIPanel, { t, ...((props ?? {}) as Record<string, unknown>) } as unknown as ComfyUIPanelProps),\n ))\n\n ctx.slots.inject('conversation.session.header.actions', () => ctx.slots.register(\n { name: 'conversation.session.header.actions', id: 'comfyui', order: 100, label: () => t('panelTitle') },\n (props: unknown) => h(ComfyUITrigger, { t, ...((props ?? {}) as Record<string, unknown>) } as unknown as ComfyUITriggerProps),\n ))\n}\n"],"mappings":"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"}
|