diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6b653bb --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.patch whitespace=-space-before-tab diff --git a/.github/workflows/installers.yml b/.github/workflows/installers.yml index a079d24..80e8ced 100644 --- a/.github/workflows/installers.yml +++ b/.github/workflows/installers.yml @@ -1,57 +1,188 @@ -name: Desktop Installers +name: Desktop Release on: + push: + tags: + - "v*" workflow_dispatch: permissions: - contents: read + contents: write + +env: + NODE_VERSION: 22.19.0 + RELEASE_REPOSITORY: Modole/laobos-agent-studio jobs: + verify: + runs-on: ubuntu-latest + timeout-minutes: 30 + outputs: + version: ${{ steps.version.outputs.version }} + tag: ${{ steps.version.outputs.tag }} + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-node@v7 + with: + node-version: ${{ env.NODE_VERSION }} + cache: npm + - run: npm ci + - id: version + shell: bash + run: | + version="$(node -p "require('./package.json').version")" + tag="v${version}" + if [[ "${GITHUB_REF_TYPE}" == "tag" && "${GITHUB_REF_NAME}" != "${tag}" ]]; then + echo "Tag ${GITHUB_REF_NAME} does not match package version ${version}." >&2 + exit 1 + fi + echo "version=${version}" >> "${GITHUB_OUTPUT}" + echo "tag=${tag}" >> "${GITHUB_OUTPUT}" + - run: npm run audit:public + - run: npm run lint + - run: npm test + macos-arm64: + needs: verify runs-on: macos-15 - timeout-minutes: 45 + timeout-minutes: 60 + env: + HAS_MAC_SIGNING: ${{ secrets.MAC_CSC_LINK != '' }} steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v6 + - uses: actions/checkout@v7 + - uses: actions/setup-node@v7 with: - node-version: 22.19.0 + node-version: ${{ env.NODE_VERSION }} cache: npm - run: npm ci - - run: npm run audit:public - - run: npm run desktop:installer -- --mac dmg --arm64 + - name: Build signed and notarized macOS release + if: env.HAS_MAC_SIGNING == 'true' + run: npm run desktop:installer -- --mac dmg zip --arm64 + env: + CSC_LINK: ${{ secrets.MAC_CSC_LINK }} + CSC_KEY_PASSWORD: ${{ secrets.MAC_CSC_KEY_PASSWORD }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + - name: Build reproducibly signed community macOS release + if: env.HAS_MAC_SIGNING != 'true' + run: npm run desktop:installer:test-update -- --mac dmg zip --arm64 - run: node scripts/verify-packaged-runtime.mjs "out/installers/mac-arm64/劳博士.app/Contents/Resources/app.asar" - - run: test "$(find out/installers -maxdepth 1 -name 'laobos-studio-*-macos-arm64.dmg' | wc -l | tr -d ' ')" = "1" + - run: node scripts/verify-desktop-resources.mjs "out/installers/mac-arm64/劳博士.app/Contents/Resources" + - name: Verify macOS signature and update artifacts + shell: bash + run: | + codesign --verify --deep --strict --verbose=2 "out/installers/mac-arm64/劳博士.app" + if [[ "${HAS_MAC_SIGNING}" == "true" ]]; then + xcrun stapler validate "out/installers/mac-arm64/劳博士.app" + spctl --assess --type execute --verbose=2 "out/installers/mac-arm64/劳博士.app" + else + echo "No Developer ID secret configured; publishing the stable ad-hoc community update chain." + fi + test "$(find out/installers -maxdepth 1 -name 'laobos-studio-*-macos-arm64.dmg' | wc -l | tr -d ' ')" = "1" + test "$(find out/installers -maxdepth 1 -name 'laobos-studio-*-macos-arm64.zip' | wc -l | tr -d ' ')" = "1" + test -f out/installers/latest-mac.yml - uses: actions/upload-artifact@v7 with: name: laobos-studio-macos-arm64 - path: out/installers/laobos-studio-*-macos-arm64.dmg + path: | + out/installers/laobos-studio-*-macos-arm64.dmg + out/installers/laobos-studio-*-macos-arm64.zip + out/installers/*.blockmap + out/installers/latest-mac.yml if-no-files-found: error compression-level: 0 - retention-days: 7 + retention-days: 3 windows-x64: + needs: verify runs-on: windows-latest - timeout-minutes: 45 + timeout-minutes: 60 + env: + HAS_WINDOWS_SIGNING: ${{ secrets.WIN_CSC_LINK != '' }} steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v6 + - uses: actions/checkout@v7 + - uses: actions/setup-node@v7 with: - node-version: 22.19.0 + node-version: ${{ env.NODE_VERSION }} cache: npm - run: npm ci - - run: npm run audit:public - - run: npm run desktop:installer -- --win nsis --x64 + - name: Build signed Windows release + if: env.HAS_WINDOWS_SIGNING == 'true' + run: npm run desktop:installer -- --win nsis --x64 + env: + CSC_LINK: ${{ secrets.WIN_CSC_LINK }} + CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }} + - name: Build unsigned community Windows release + if: env.HAS_WINDOWS_SIGNING != 'true' + run: npm run desktop:installer -- --win nsis --x64 + env: + CSC_IDENTITY_AUTO_DISCOVERY: false - run: node scripts/verify-packaged-runtime.mjs "out/installers/win-unpacked/resources/app.asar" - - shell: pwsh + - run: node scripts/verify-desktop-resources.mjs "out/installers/win-unpacked/resources" + - run: node scripts/verify-windows-packaged-runtime.mjs "out/installers/win-unpacked/resources" + - name: Verify Windows signature and update artifacts + shell: pwsh run: | $installers = @(Get-ChildItem "out/installers/laobos-studio-*-windows-x64-setup.exe") - if ($installers.Count -ne 1) { - throw "Windows installer was not generated." + if ($installers.Count -ne 1) { throw "Windows installer was not generated." } + if ($env:HAS_WINDOWS_SIGNING -eq "true") { + $signedFiles = @($installers[0].FullName, "out/installers/win-unpacked/laobos-studio.exe") + foreach ($file in $signedFiles) { + $signature = Get-AuthenticodeSignature $file + if ($signature.Status -ne "Valid") { throw "Invalid Windows signature for ${file}: $($signature.Status)" } + } + } else { + Write-Host "No Authenticode secret configured; publishing the unsigned community installer." } + if (-not (Test-Path "out/installers/latest.yml")) { throw "latest.yml was not generated." } - uses: actions/upload-artifact@v7 with: name: laobos-studio-windows-x64 - path: out/installers/laobos-studio-*-windows-x64-setup.exe + path: | + out/installers/laobos-studio-*-windows-x64-setup.exe + out/installers/*.blockmap + out/installers/latest.yml if-no-files-found: error compression-level: 0 - retention-days: 7 + retention-days: 3 + + publish: + if: github.ref_type == 'tag' + needs: [verify, macos-arm64, windows-x64] + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v7 + - uses: actions/download-artifact@v8 + with: + pattern: laobos-studio-* + path: release-assets + merge-multiple: true + - name: Validate update metadata and create checksums + run: | + node scripts/verify-update-release.mjs release-assets "${{ needs.verify.outputs.version }}" + cd release-assets + sha256sum * > SHA256SUMS + - name: Publish release atomically + env: + GH_TOKEN: ${{ github.token }} + RELEASE_TAG: ${{ needs.verify.outputs.tag }} + RELEASE_VERSION: ${{ needs.verify.outputs.version }} + shell: bash + run: | + test -n "${GH_TOKEN}" + existing_draft="$(gh release view "${RELEASE_TAG}" --repo "${RELEASE_REPOSITORY}" --json isDraft --jq .isDraft 2>/dev/null || true)" + if [[ "${existing_draft}" == "false" ]]; then + echo "Published release ${RELEASE_TAG} already exists in ${RELEASE_REPOSITORY}." >&2 + exit 1 + fi + if [[ "${existing_draft}" != "true" ]]; then + gh release create "${RELEASE_TAG}" \ + --repo "${RELEASE_REPOSITORY}" \ + --draft \ + --title "劳博士开源客户端 ${RELEASE_TAG}" \ + --notes "劳博士开源客户端 ${RELEASE_VERSION}。首次安装请下载 DMG 或 Windows Setup;ZIP、blockmap 和 latest 元数据用于应用内自动更新。" + fi + gh release upload "${RELEASE_TAG}" release-assets/* --repo "${RELEASE_REPOSITORY}" --clobber + gh release edit "${RELEASE_TAG}" --repo "${RELEASE_REPOSITORY}" --draft=false --latest diff --git a/.gitignore b/.gitignore index 9761d7b..f323e27 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ /.next/ /.vinext/ /out/ +/.cache/ +/resources/mingit-win32-x64/ # misc .DS_Store diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2305378..40614e8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,6 +19,16 @@ npm run audit:public Pull Request 应说明改动目的、用户影响、验证方式,以及是否涉及数据迁移、权限、网络访问或依赖许可。 +## 桌面与发布改动 + +涉及 Electron、DSH 内置插件、安装器、平台原生依赖或更新器时,请先阅读[桌面打包与应用内更新手册](docs/desktop-release-playbook.md),并满足以下要求: + +- 插件运行时资源必须放在插件自身目录,不能跨目录引用根 `public/` 或开发机路径。 +- Windows 原生依赖必须在 `app.asar.unpacked` 中验证真实的 x64 PE 文件,不能只检查 package.json。 +- macOS 更新必须验证基线版与新版的完整签名和 designated requirement。 +- 修改功能、架构或发布流程时同步更新 `README.md`、`docs/` 中对应文档及必要的回归测试。 +- Release 先使用草稿聚合资产,安装器和 blockmap 上传成功后再发布 `latest*.yml`。 + ## 贡献许可 提交代码、文档或资源即表示: diff --git a/README.md b/README.md index 1ba17e3..7ee5941 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,11 @@ DSH 官方 Web UI │ loopback HTTP ▼ -DeepSeek Harness 0.1.0-rc.6 +DeepSeek Harness 0.1.0-rc.7 ├─ Agent presets(标准 / PTC / 极简 / 创造 / 性能实验) ├─ Sandbox + Approval + Permission presets ├─ Plan 模式安全联动 - └─ 劳博士项目资源插件(知识库 / 工作流 / Skills / MCP) + └─ 劳博士项目资源插件(知识库 / Skills / MCP) ``` DSH 只监听本机回环地址。Electron 使用随机端口启动运行时,渲染进程保持 `sandbox: true`、`nodeIntegration: false`,并拒绝网页权限请求。 @@ -55,6 +55,20 @@ npm run desktop:installer -- --win nsis --x64 当前公开构建未配置 Apple Developer ID 或 Windows Authenticode 证书,因此首次安装会出现系统的“未知开发者/未知发布者”安全提示;发布页同时提供 SHA-256 校验值用于核对文件完整性。签名证书和密码只允许通过 CI Secret 注入,禁止提交到仓库。 +公开仓库的自动更新与源码 Release 使用同一个 GitHub 仓库。版本号以 `package.json` 为唯一来源,发布标签必须严格等于 `v`。推送版本标签后,GitHub Actions 会分别在 macOS 和 Windows 原生 Runner 生成: + +- macOS:DMG、自动更新 ZIP、两类 blockmap 与 `latest-mac.yml` +- Windows:NSIS 安装器、blockmap 与 `latest.yml` +- 汇总资产:`SHA256SUMS` + +没有配置签名 Secret 时,流水线仍会生成可测试的社区构建:macOS 使用固定要求的稳定 ad-hoc 签名,保证相邻社区版本可以验证更新包;Windows 生成未签名安装器。配置 `MAC_CSC_LINK`、`MAC_CSC_KEY_PASSWORD`、Apple 公证凭据以及 `WIN_CSC_LINK`、`WIN_CSC_KEY_PASSWORD` 后,同一流水线会自动切换到正式签名。手动运行工作流只生成构建产物,不会发布 Release;只有推送匹配版本号的 `v*` 标签才会发布并成为应用内更新源。 + +本机生成 macOS 测试安装包与更新包: + +```bash +npm run release:mac:test +``` + 常用诊断: ```bash @@ -121,22 +135,18 @@ macOS 默认数据目录: ## 项目侧栏与资源管理 -`@laobos/dsh-system-tools` 作为 DSH 插件运行。官方会话栏保持在左侧;项目导航固定在最右侧,与中间工作区组成三列布局。右栏折叠时保留 56px 图标轨道,展开宽度默认为 224px,并可在 200–300px 之间拖动调整。点击“对话、工作流、知识库、Skills、MCP、设置”都会复用中间工作区进行独立页面切换;设置页包含系统提示词编辑,以及可直达模型、Agent 预设、安全审批、插件分区的 DSH 系统设置入口;原左侧设置入口已迁移到右栏底部。 +`@laobos/dsh-system-tools` 作为 DSH 插件运行。官方会话栏保持在左侧;项目导航固定在最右侧,与中间工作区组成三列布局。右栏折叠时保留 56px 图标轨道,展开宽度默认为 224px,并可在 200–300px 之间拖动调整。点击“对话、知识库、Skills、MCP、设置”都会复用中间工作区进行独立页面切换;设置页包含系统提示词编辑,以及可直达模型、Agent 预设、安全审批、插件分区的 DSH 系统设置入口;原左侧设置入口已迁移到右栏底部。 - 本地 SQLite + FTS 全文检索,支持自然问句拆词、标题加权和相邻片段扩展 - Agent 可按需自动创建、读取和更新知识;删除经过 DSH 审批,暂停的知识库不会被全局搜索访问 - Agent 默认把知识写入当前工作区;只有明确的跨项目知识才进入全局作用域 - 知识库页面保持轻量插件形态,支持召回测试、资料编辑、重新索引、启停和删除 -- DAG 工作流由 Agent 通过 `workflow_manager` 创建、读取、更新、测试、发布和启停,删除经 `workflow_delete` 审批 -- 工作流页面使用纯列表和 SVG 快捷操作;查看、编辑会打开弹窗,用户可在弹窗内查看流程图、微调节点、试运行、发布版本、启停和删除,不提供手动新建入口 -- 首次发布会自动启用并注册为 DSH Agent 工具;后续发布保留用户设置的启停状态 -- 已发布工作流同时投影到“设置 > Plugins > Agent 自动化”虚拟插件页,任一侧启停或删除都会同步 - Skills 以名称、简介、范围、状态和实际文件位置的管理表展示;默认管理 DSH 原生目录,可按需查看 `.agents/skills` 兼容内容,并支持一键复制位置、启停、删除和 DSH 热更新 - MCP 支持 stdio 与 streamable HTTP,以 Server、连接方式、连接目标、工具数量和连接状态的管理表展示;可启停、重连和删除,密钥只以遮罩返回界面 - 插件市场源码内置于 `packages/laobos-market`,可在“设置 > 插件市场”搜索、安装和管理带有 `dsh-plugin` topic 的插件;代理地址和上传账号默认留空,由使用者自行配置 - 管理页支持右栏折叠按钮、再次点击当前菜单项、页面“收起”按钮和 Esc 快速返回对话;未保存的 Skills/MCP 修改会先确认 - 设置中的“系统提示词”默认展示可编辑的“劳博士”身份,以 `order: 39` 注册在 preset persona 与旧迁移指令之后、工具说明之前;用户修改姓名或角色后会覆盖冲突设定,不会保留旧名称作为别名 -- 实体插件清单与虚拟工作流插件统一使用 DSH 官方“设置 > Plugins”页面,不占用项目主侧栏 +- 实体插件清单统一使用 DSH 官方“设置 > Plugins”页面,不占用项目主侧栏 - HTTP 管理接口只接受本机请求并校验 Origin 数据位于 DSH Home 的 `data/system-tools.db`。 @@ -145,17 +155,20 @@ macOS 默认数据目录: 桌面版把右侧项目栏分成“对话 / 工作台 / 集成管理”三组,并把高权限能力收敛到 Electron 主进程。网页侧只能调用经过校验的最小化 preload API,文件路径会做工作区边界、真实路径和符号链接检查。 -- 会话:编辑上一轮并从稳定边界创建分支、重试上一轮、完整分页导出 PDF、重命名和可恢复删除 +- 会话:编辑上一轮并从稳定边界创建分支、重试上一轮、导出带内嵌资源的离线 HTML、重命名和可恢复删除 - 右键菜单:工作区可打开文件管理器、Git 审查和终端;会话可打开、编辑、重试、导出、重命名和删除 -- 文件工作台:目录浏览、文本/图片/PDF/音视频预览和 Finder 定位;敏感文件名、二进制内容和超大文件会被限制 -- 版本中心:状态与 staged/unstaged diff、未跟踪文件预览、提交历史、初始化、暂存、提交、分支管理,以及需确认的恢复和远端同步;桌面 UI 与 Agent 共用结构化 Git 服务 -- 文件上传:图片继续使用 DSH 原生图片附件;普通文件通过输入框回形针选择,复制到受管目录后以文件 Chip 显示,并把受管副本的绝对路径封装进提示词 +- 文件工作台:目录浏览、创建、编辑、重命名、删除、文本/图片/PDF/音视频预览和系统文件管理器定位;首次访问启动目录外的工作区会请求授权并记住用户选择 +- 版本中心:状态与 staged/unstaged diff、未跟踪文件预览、提交历史、初始化、暂存、提交、分支管理,以及需确认的恢复和远端同步;Windows 安装包内置固定校验的 MinGit,不依赖图形进程的 `PATH` +- 文件上传:支持选择、粘贴和桌面拖放;支持视觉的模型使用原生图片通道,不支持视觉时图片会作为普通受管文件交给 Agent - 上传路径:在“设置 > 文件上传”中选择“默认”或“工作区内”;默认写入 DSH Home 的 `uploads/v1`,后者使用当前工作区的 `update` 文件夹 +- 剪贴板:桌面端通过受约束的主进程 IPC 写入,浏览器 API 仍作为回退,并在失败时提供明确反馈 - 终端插件:基于 `node-pty` 与 xterm;每个标签使用独立的稳定命名 tmux 会话,打开或重连时自动回到当前工作区,未安装 tmux 时明确提示并回退到登录 Shell - 浏览器插件:使用隔离的 `WebContentsView` 预览 HTTP(S) 地址;BrowserOps daemon 仅在用户点击后启动,并可随时停止 - SSH 插件:密码和私钥使用系统 `safeStorage` 加密,主机密钥采用 TOFU 校验,发生变更时阻止连接 - 应用管理插件:登记、探测、启动、停止和查看日志;进程始终以 `shell: false` 启动,“移出管理”不会删除项目文件 - Shell 与 WSL:自动检测 Windows 的 WSL、Linux 发行版、Git Bash 与 PowerShell;设置页提供需 UAC 确认的 WSL/Ubuntu 安装、分阶段进度、重启恢复和可编辑的标准模式诊断对话 +- 软件更新:设置页可检查、下载并安装公开 GitHub Release;下载状态可恢复,应用退出时会等待本地运行时安全关闭 +- 插件恢复:市场安装前校验 Host/Client 入口和模块 ID;用户插件导致启动失败时会自动隔离并以安全模式重启 删除的会话会先归档,再移动到 DSH Home 下的劳博士回收站;不会直接永久擦除。Terminal、BrowserOps、SSH 和应用管理均为独立 DSH 客户端插件,配置位于 `config/laobos.cordis.patch.yml`。修改终端或 SSH 的 JSX 源码后,可单独重建浏览器插件: diff --git a/SECURITY.md b/SECURITY.md index 46265c8..31d73d6 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -13,3 +13,9 @@ ## 凭据泄露 如果凭据曾进入 Git 历史、Issue、构建日志或发布包,请立即在对应服务撤销并轮换。仅删除文件或提交并不能使已公开的凭据恢复安全。 + +## 软件更新与发布完整性 + +桌面客户端只从固定的劳博士 GitHub Release 仓库读取更新。渲染进程不能指定任意下载地址或安装路径,安装资产通过 `latest*.yml` 中的 SHA-512 和 Release 的 SHA-256 清单校验。 + +正式 macOS 包必须使用 Apple Developer ID 签名并完成公证;正式 Windows 包必须使用 Authenticode。ad-hoc 或未签名构建只允许用于受控测试,不能被描述为可信生产发行版。发现 Release 资产、更新元数据、签名或校验和不一致时,应立即停止发布和更新测试,替换资产并从公网重新下载复核。详细流程见[桌面打包与应用内更新手册](docs/desktop-release-playbook.md)。 diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 6bfe740..df9d853 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -4,7 +4,7 @@ ## DeepSeek Harness -- Package: `@deepseek-ai/dsh` 0.1.0-rc.6 +- Package: `@deepseek-ai/dsh` 0.1.0-rc.7 - Project: - License: MIT - Copyright: Copyright (c) 2026 DeepSeek @@ -55,6 +55,15 @@ SOFTWARE. 劳博士对该社区预设进行了系统 preset 注册、中文元数据和 Windows Shell 路由适配。上游 MIT 许可与 NOTICE 分别保存在 `packages/laobos-performance/LICENSE.upstream` 和 `packages/laobos-performance/NOTICE.upstream`。该社区项目不代表 DeepSeek 官方认可或合作关系。 +## Git for Windows MinGit + +- Component: MinGit 2.55.0.4 (64-bit) +- Project: +- Bundled path on Windows: `resources/git` +- License: GPL-2.0 and the licenses of bundled support libraries + +MinGit 是 Git for Windows 官方提供、面向第三方应用内嵌的最小 Git 发行物。构建脚本固定官方 Release 地址和 SHA-256;Windows 安装包保留 MinGit 根目录 `LICENSE.txt`、`COPYING` 及各支持库随附的许可证文件。对应版本的完整源代码可从上述项目和 `v2.55.0.windows.4` 标签获取。 + ## 其他 npm 依赖 完整依赖及锁定版本见 `package.json` 和 `package-lock.json`。各依赖的许可证文本会在 `npm install` 后位于对应的 `node_modules//LICENSE*` 文件中;Electron 桌面分发物还包含 Electron/Chromium 随附的许可证文件。分发者有责任核对并保留所有适用声明。 diff --git a/app/studio.tsx b/app/studio.tsx index 668c94b..320d87e 100644 --- a/app/studio.tsx +++ b/app/studio.tsx @@ -1425,14 +1425,11 @@ export function PiStudio({ mode = "studio" }: { mode?: StudioMode }) { const selectedModelInfo = models.find( (model) => `${model.provider}/${model.id}` === selectedModel, ); - if ( + const imagesAsFiles = Boolean( pendingAttachments.some((attachment) => attachment.kind === "image") && selectedModelInfo?.input && - !selectedModelInfo.input.includes("image") - ) { - showToast("当前模型不支持图片,请切换到支持视觉输入的模型"); - return; - } + !selectedModelInfo.input.includes("image"), + ); const conversationId = activeConversation.id; const assistantId = newId(); @@ -1449,6 +1446,7 @@ export function PiStudio({ mode = "studio" }: { mode?: StudioMode }) { { method: "POST", body: JSON.stringify({ + imageMode: imagesAsFiles ? "file" : "multimodal", attachments: pendingAttachments.map((attachment) => ({ id: attachment.id, name: attachment.name, diff --git a/bridge/server.mjs b/bridge/server.mjs index aa6a09e..609d35d 100644 --- a/bridge/server.mjs +++ b/bridge/server.mjs @@ -481,7 +481,7 @@ function isTextAttachment(attachment) { ); } -async function saveAttachmentBatch(sessionId, input) { +async function saveAttachmentBatch(sessionId, input, { imagesAsFiles = false } = {}) { if (!Array.isArray(input) || input.length === 0) { throw new HttpError(400, "请选择至少一个附件。"); } @@ -532,7 +532,9 @@ async function saveAttachmentBatch(sessionId, input) { .trim() .toLowerCase() .slice(0, 120); - const kind = supportedInlineImageTypes.has(mimeType) ? "image" : "file"; + const kind = !imagesAsFiles && supportedInlineImageTypes.has(mimeType) + ? "image" + : "file"; normalized.push({ id, name, @@ -651,8 +653,11 @@ async function buildAttachmentPrompt(message, sessionId, batch) { } const prompt = message || "请查看并处理这些附件。"; + const guidance = images.length + ? "Use the image inputs for images and the listed paths or inline content for other files." + : "Use the listed file paths or inline content to inspect the attachments."; return { - message: `${prompt}\n\n\nThe user attached these local files. Use the image inputs for images and the listed paths or inline content for other files.\n${lines.join("\n")}${inlineSections.join("")}\n`, + message: `${prompt}\n\n\nThe user attached these local files. ${guidance}\n${lines.join("\n")}${inlineSections.join("")}\n`, images, }; } @@ -1020,8 +1025,6 @@ async function listSystemToolNames() { try { return await withEmbeddedEngine(async (embeddedEngine) => [ "knowledge_search", - "workflow_manager", - "workflow_delete", "knowledge_manager", "knowledge_delete", "git_manager", @@ -1031,10 +1034,6 @@ async function listSystemToolNames() { .listKnowledgeCollections() .filter((collection) => collection.agentEnabled) .map((collection) => collection.toolName), - ...embeddedEngine - .listWorkflows() - .filter((workflow) => workflow.publishedVersion) - .map((workflow) => workflow.toolName), ]); } catch { return []; @@ -1497,9 +1496,7 @@ function routeMatch(pathname, expression) { async function handleSystemToolsRequest(request, response, url, headers) { if ( url.pathname !== "/api/knowledge" && - !url.pathname.startsWith("/api/knowledge/") && - url.pathname !== "/api/workflows" && - !url.pathname.startsWith("/api/workflows/") + !url.pathname.startsWith("/api/knowledge/") ) { return false; } @@ -1588,61 +1585,7 @@ async function handleSystemToolsRequest(request, response, url, headers) { return true; } - if (request.method === "GET" && url.pathname === "/api/workflows") { - const workflows = await withSystemToolsEngine(async (embeddedEngine) => - embeddedEngine.listWorkflows(), - ); - sendJson(response, 200, { workflows }, headers); - return true; - } - - if (request.method === "PUT" && url.pathname === "/api/workflows") { - const body = await parseBody(request); - const workflow = await withSystemToolsEngine(async (embeddedEngine) => - embeddedEngine.upsertWorkflow(body), - ); - sendJson(response, 200, { workflow }, headers); - return true; - } - - const workflowActionMatch = routeMatch( - url.pathname, - /^\/api\/workflows\/([A-Za-z0-9][A-Za-z0-9._-]{0,127})\/(publish|run)$/u, - ); - if (request.method === "POST" && workflowActionMatch?.[2] === "publish") { - const published = await withSystemToolsEngine(async (embeddedEngine) => - embeddedEngine.publishWorkflow(workflowActionMatch[1]), - ); - restartRuntimes(); - sendJson(response, 200, { published }, headers); - return true; - } - if (request.method === "POST" && workflowActionMatch?.[2] === "run") { - const body = await parseBody(request); - const result = await withSystemToolsEngine(async (embeddedEngine) => - embeddedEngine.runWorkflow(workflowActionMatch[1], body), - ); - sendJson(response, 200, { result }, headers); - return true; - } - - const workflowMatch = routeMatch( - url.pathname, - /^\/api\/workflows\/([A-Za-z0-9][A-Za-z0-9._-]{0,127})$/u, - ); - if (request.method === "DELETE" && workflowMatch) { - await withSystemToolsEngine(async (embeddedEngine) => - embeddedEngine.deleteWorkflow( - workflowMatch[1], - request.headers["x-resource-revision"] || undefined, - ), - ); - restartRuntimes(); - sendJson(response, 200, { ok: true }, headers); - return true; - } - - throw new HttpError(404, "未找到该知识库或工作流接口。"); + throw new HttpError(404, "未找到该知识库接口。"); } async function handleRequest(request, response, token) { @@ -2059,6 +2002,7 @@ async function handleRequest(request, response, token) { const batch = await saveAttachmentBatch( attachmentUploadMatch[1], body.attachments, + { imagesAsFiles: body.imageMode === "file" }, ); sendJson( response, diff --git a/build/test-update-requirements.rqset b/build/test-update-requirements.rqset new file mode 100644 index 0000000..f5d9a9d --- /dev/null +++ b/build/test-update-requirements.rqset @@ -0,0 +1 @@ +designated => identifier "com.laobos.studio" diff --git a/config/laobos.cordis.patch.yml b/config/laobos.cordis.patch.yml index 995150b..5a793e3 100644 --- a/config/laobos.cordis.patch.yml +++ b/config/laobos.cordis.patch.yml @@ -48,3 +48,5 @@ name: '@laobos/dsh-market' config: profile: web + - id: laobos-updater + name: '@laobos/dsh-updater' diff --git a/desktop/domains/apps.mjs b/desktop/domains/apps.mjs index 5d18c42..6c2962a 100644 --- a/desktop/domains/apps.mjs +++ b/desktop/domains/apps.mjs @@ -1,9 +1,10 @@ import crypto from "node:crypto"; import { spawn } from "node:child_process"; -import { access, appendFile, mkdir, readFile, realpath, rename, rm, writeFile } from "node:fs/promises"; +import { access, appendFile, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises"; import net from "node:net"; import path from "node:path"; -import { boundedString, resolveAuthorizedPath } from "../ipc-security.mjs"; +import { boundedString } from "../ipc-security.mjs"; +import { resolveWorkspaceDirectory } from "../workspace-authorization.mjs"; const MAX_APPS = 100; const MAX_LOG_BYTES = 1_500_000; @@ -16,6 +17,7 @@ export function registerAppsIpc({ app, shell, workspace, + workspaceAuthorizer, authorize, getMainWindow, }) { @@ -47,7 +49,7 @@ export function registerAppsIpc({ const registry = await readManagedRegistry(registryFile); const entry = registry.find((item) => item.id === id); if (!entry) throw new Error("应用不存在。 "); - await appCwd(workspace, entry.cwd); + await appCwd(workspace, entry.cwd, workspaceAuthorizer); const port = normalizeManagedAppPort(entry.port); const observed = await applicationRuntime(entry, current); if (observed.state === "online") throw new Error(`端口 ${port} 当前在线,但进程不受本次应用管理器实例控制。请先释放端口或重启对应应用。`); @@ -164,7 +166,7 @@ export function registerAppsIpc({ ipcMain.handle("laobos:apps:detect", async (event, input = {}) => { authorize(event); - return detectApplication(await appCwd(workspace, input.cwd)); + return detectApplication(await appCwd(workspace, input.cwd, workspaceAuthorizer)); }); ipcMain.handle("laobos:apps:find-port", async (event, input = {}) => { @@ -180,7 +182,7 @@ export function registerAppsIpc({ const id = validId(input.id) || crypto.randomUUID(); const previous = registry.find((item) => item.id === id); if (["running", "starting", "stopping"].includes(runtime.get(id)?.state)) throw new Error("请先停止应用,再修改登记信息。 "); - const cwd = await appCwd(workspace, input.cwd); + const cwd = await appCwd(workspace, input.cwd, workspaceAuthorizer); const command = normalizeCommand(input.command); const args = normalizeArgs(input.args); let port; @@ -336,7 +338,18 @@ export async function findFreeApplicationPort(registry = [], start = MANAGED_APP throw new Error(`${MANAGED_APP_MIN_PORT}-${MANAGED_APP_MAX_PORT} 范围内没有可用端口。`); } -export function isTcpPortFree(port) { +export async function isTcpPortFree(port) { + // Probe the loopback and the wildcard address separately. On macOS/BSD, + // binding 127.0.0.1 can succeed while another socket already holds 0.0.0.0 + // (Flask-style `host="0.0.0.0"`), and the reverse is also true; a port is + // free only when both addresses accept a new bind. + for (const host of ["0.0.0.0", "127.0.0.1"]) { + if (!(await probeTcpBind(host, port))) return false; + } + return true; +} + +function probeTcpBind(host, port) { return new Promise((resolve, reject) => { const server = net.createServer(); server.unref(); @@ -344,7 +357,7 @@ export function isTcpPortFree(port) { if (error?.code === "EADDRINUSE" || error?.code === "EACCES") resolve(false); else reject(error); }); - server.listen({ host: "127.0.0.1", port, exclusive: true }, () => server.close(() => resolve(true))); + server.listen({ host, port, exclusive: true }, () => server.close(() => resolve(true))); }); } @@ -354,12 +367,14 @@ async function ensureApplicationPortAvailable(registry, port, ignoreId) { if (!(await isTcpPortFree(port))) throw new Error(`端口 ${port} 已被其他进程占用,请选择新的空闲端口。`); } -async function appCwd(workspace, requested) { +async function appCwd(workspace, requested, workspaceAuthorizer) { const value = boundedString(requested || workspace, "应用目录", 4096); - const root = await realpath(workspace); - const absolute = path.isAbsolute(value) ? value : path.resolve(root, value); - const canonical = await realpath(absolute); - return (await resolveAuthorizedPath(root, path.relative(root, canonical), { kind: "directory" })).path; + return resolveWorkspaceDirectory({ + authorizer: workspaceAuthorizer, + defaultRoot: workspace, + requested: value, + label: "应用工作区", + }); } async function readRegistry(filePath) { diff --git a/desktop/domains/browser.mjs b/desktop/domains/browser.mjs index f32a03d..e267bcb 100644 --- a/desktop/domains/browser.mjs +++ b/desktop/domains/browser.mjs @@ -1,9 +1,12 @@ import { spawn } from "node:child_process"; +import { createRequire } from "node:module"; import net from "node:net"; import path from "node:path"; import { boundedString } from "../ipc-security.mjs"; const BROWSEROPS_PORT = 57_321; +const require = createRequire(import.meta.url); +const BROWSER_HOME_URL = `data:text/html;charset=utf-8,${encodeURIComponent(`浏览器

内置浏览器已就绪

在上方输入 HTTP(S) 地址。预览本地项目时,请先启动对应的开发服务,再打开它实际监听的端口。

`)}`; export function registerBrowserIpc({ ipcMain, @@ -16,6 +19,8 @@ export function registerBrowserIpc({ let visible = false; let browserOpsChild; let browserOpsState = { state: "stopped", message: "" }; + let navigationError = ""; + let currentAddress = ""; ipcMain.handle("laobos:browser:show", (event, input = {}) => { authorize(event); @@ -41,7 +46,14 @@ export function registerBrowserIpc({ ipcMain.handle("laobos:browser:navigate", async (event, input = {}) => { authorize(event); const url = normalizeBrowserUrl(input.url); - await ensureView().webContents.loadURL(url); + currentAddress = url; + navigationError = ""; + try { + await ensureView().webContents.loadURL(url); + } catch (error) { + navigationError = friendlyNavigationError(error, url); + sendState(); + } return browserState(); }); @@ -59,7 +71,7 @@ export function registerBrowserIpc({ ipcMain.handle("laobos:browserops:status", async (event) => { authorize(event); if (!browserOpsChild && await canConnect(BROWSEROPS_PORT)) { - return { state: "external", message: `已检测到本机 BrowserOps daemon(端口 ${BROWSEROPS_PORT})` }; + browserOpsState = { state: "external", message: `已连接外部 BrowserOps daemon(端口 ${BROWSEROPS_PORT})` }; } return { ...browserOpsState }; }); @@ -71,47 +83,62 @@ export function registerBrowserIpc({ browserOpsState = { state: "external", message: `正在使用本机已有 daemon(端口 ${BROWSEROPS_PORT})` }; return { ...browserOpsState }; } - const daemon = path.join(app.getAppPath(), "node_modules", "@browserops", "bridge", "dist", "daemon.js"); + const daemon = resolveBrowserOpsDaemon(app.getAppPath()); browserOpsState = { state: "starting", message: "正在启动 BrowserOps daemon…" }; - browserOpsChild = spawn(process.execPath, [daemon], { + sendBrowserOpsState(); + const child = spawn(process.execPath, [daemon], { env: { ...process.env, ELECTRON_RUN_AS_NODE: "1" }, stdio: ["ignore", "pipe", "pipe"], windowsHide: true, }); + browserOpsChild = child; let recent = ""; const collect = (chunk) => { recent = `${recent}${String(chunk)}`.slice(-2_000); - browserOpsState = { state: "running", message: recent.trim().split("\n").at(-1) || `端口 ${BROWSEROPS_PORT}` }; + if (browserOpsState.state === "starting") { + const detail = recent.trim().split("\n").at(-1); + browserOpsState = { state: "starting", message: detail ? `正在启动:${detail}` : "正在启动 BrowserOps daemon…" }; + } sendBrowserOpsState(); }; - browserOpsChild.stdout.on("data", collect); - browserOpsChild.stderr.on("data", collect); - browserOpsChild.once("error", (error) => { - browserOpsChild = undefined; + child.stdout.on("data", collect); + child.stderr.on("data", collect); + child.once("error", (error) => { + if (browserOpsChild === child) browserOpsChild = undefined; browserOpsState = { state: "error", message: error.message }; sendBrowserOpsState(); }); - browserOpsChild.once("exit", (code, signal) => { + child.once("exit", (code, signal) => { + if (browserOpsChild !== child) return; browserOpsChild = undefined; - browserOpsState = { state: code === 0 ? "stopped" : "error", message: `daemon 已退出(code=${String(code)}, signal=${String(signal)})` }; + if (browserOpsState.state === "stopping") browserOpsState = { state: "stopped", message: "BrowserOps daemon 已停止" }; + else if (browserOpsState.state !== "error") browserOpsState = { state: code === 0 ? "stopped" : "error", message: `daemon 已退出(code=${String(code)}, signal=${String(signal)})` }; sendBrowserOpsState(); }); - for (let attempt = 0; attempt < 20; attempt += 1) { + for (let attempt = 0; attempt < 40; attempt += 1) { if (await canConnect(BROWSEROPS_PORT)) { browserOpsState = { state: "running", message: `BrowserOps daemon 已就绪(端口 ${BROWSEROPS_PORT})` }; sendBrowserOpsState(); - break; + return { ...browserOpsState }; } - await new Promise((resolve) => setTimeout(resolve, 100)); + if (!browserOpsChild) break; + await new Promise((resolve) => setTimeout(resolve, 150)); + } + if (browserOpsChild === child) { + browserOpsState = { state: "error", message: recent.trim().split("\n").at(-1) || "BrowserOps daemon 启动超时,请检查安装或端口占用。" }; + child.kill("SIGTERM"); + sendBrowserOpsState(); } return { ...browserOpsState }; }); ipcMain.handle("laobos:browserops:stop", (event) => { authorize(event); - if (!browserOpsChild) return { stopped: false, state: browserOpsState.state }; + if (!browserOpsChild) return { stopped: false, ...browserOpsState }; + browserOpsState = { state: "stopping", message: "正在停止 BrowserOps daemon…" }; + sendBrowserOpsState(); browserOpsChild.kill("SIGTERM"); - return { stopped: true, state: "stopping" }; + return { stopped: true, ...browserOpsState }; }); function ensureView() { @@ -129,6 +156,7 @@ export function registerBrowserIpc({ }); window.contentView.addChildView(view); view.setBackgroundColor("#ffffff"); + void view.webContents.loadURL(BROWSER_HOME_URL); view.webContents.setWindowOpenHandler(({ url }) => { try { void view.webContents.loadURL(normalizeBrowserUrl(url)); } catch {} return { action: "deny" }; @@ -136,9 +164,16 @@ export function registerBrowserIpc({ view.webContents.on("will-navigate", (event, url) => { try { normalizeBrowserUrl(url); } catch { event.preventDefault(); } }); - for (const eventName of ["did-start-loading", "did-stop-loading", "did-navigate", "did-navigate-in-page", "page-title-updated"]) { - view.webContents.on(eventName, sendState); - } + view.webContents.on("did-start-loading", () => { navigationError = ""; sendState(); }); + view.webContents.on("did-stop-loading", sendState); + view.webContents.on("did-navigate", (_event, url) => { if (!url.startsWith("data:")) currentAddress = url; sendState(); }); + view.webContents.on("did-navigate-in-page", (_event, url) => { currentAddress = url; sendState(); }); + view.webContents.on("page-title-updated", sendState); + view.webContents.on("did-fail-load", (_event, errorCode, errorDescription, validatedURL, isMainFrame) => { + if (!isMainFrame || errorCode === -3) return; + navigationError = friendlyNavigationError({ code: errorCode, message: errorDescription }, validatedURL || currentAddress); + sendState(); + }); syncVisibility(); return view; } @@ -154,8 +189,9 @@ export function registerBrowserIpc({ const history = contents?.navigationHistory; return { visible, - url: contents?.getURL() || "", + url: currentAddress, title: contents?.getTitle() || "", + error: navigationError, loading: contents?.isLoading() || false, canGoBack: history?.canGoBack() || false, canGoForward: history?.canGoForward() || false, @@ -187,14 +223,33 @@ export function registerBrowserIpc({ export function normalizeBrowserUrl(value) { let input = boundedString(value, "浏览器地址", 8_192).trim(); - if (!input) input = "http://127.0.0.1:3000"; + if (!input) throw new Error("请输入要打开的 HTTP(S) 地址。"); if (!/^[a-z][a-z\d+.-]*:\/\//iu.test(input)) input = `http://${input}`; const url = new URL(input); - if (url.protocol !== "http:" && url.protocol !== "https:") throw new Error("浏览器预览只允许 HTTP(S) 地址。 "); - if (url.username || url.password) throw new Error("浏览器地址不能包含用户名或密码。 "); + if (url.protocol !== "http:" && url.protocol !== "https:") throw new Error("浏览器预览只允许 HTTP(S) 地址。"); + if (url.username || url.password) throw new Error("浏览器地址不能包含用户名或密码。"); return url.toString(); } +export function friendlyNavigationError(error, url) { + const message = String(error?.message || error || ""); + const target = (() => { try { return new URL(url).host; } catch { return url || "该地址"; } })(); + if (Number(error?.code) === -102 || /ERR_CONNECTION_REFUSED/iu.test(message)) { + return `无法连接到 ${target}。如果这是本地项目,请先启动开发服务并确认端口。`; + } + if (Number(error?.code) === -105 || /ERR_NAME_NOT_RESOLVED/iu.test(message)) return `找不到 ${target},请检查地址是否正确。`; + if (Number(error?.code) === -106 || /ERR_INTERNET_DISCONNECTED/iu.test(message)) return "当前网络不可用,请检查网络连接。"; + return `页面加载失败:${message.replace(/^Error:\s*/u, "") || "未知错误"}`; +} + +export function resolveBrowserOpsDaemon(appPath) { + try { + return path.join(path.dirname(require.resolve("@browserops/bridge/package.json")), "dist", "daemon.js"); + } catch { + return path.join(appPath, "node_modules", "@browserops", "bridge", "dist", "daemon.js"); + } +} + function clampDimension(value, minimum, maximum) { const number = Number(value); return Math.min(Math.max(minimum, Number.isFinite(number) ? Math.round(number) : minimum), Math.max(minimum, maximum)); diff --git a/desktop/domains/clipboard.mjs b/desktop/domains/clipboard.mjs new file mode 100644 index 0000000..c7f4629 --- /dev/null +++ b/desktop/domains/clipboard.mjs @@ -0,0 +1,14 @@ +import { boundedString } from "../ipc-security.mjs"; + +const MAX_CLIPBOARD_TEXT_LENGTH = 10 * 1024 * 1024; + +export function registerClipboardIpc({ ipcMain, clipboard, authorize }) { + ipcMain.handle("laobos:clipboard:write-text", (event, input = {}) => { + authorize(event); + const text = boundedString(input.text, "剪贴板内容", MAX_CLIPBOARD_TEXT_LENGTH); + clipboard.writeText(text); + return { written: true }; + }); + + return () => ipcMain.removeHandler("laobos:clipboard:write-text"); +} diff --git a/desktop/domains/conversation-export.mjs b/desktop/domains/conversation-export.mjs index 3900698..8ee9600 100644 --- a/desktop/domains/conversation-export.mjs +++ b/desktop/domains/conversation-export.mjs @@ -1,72 +1,42 @@ -import crypto from "node:crypto"; -import { mkdir, rm, writeFile } from "node:fs/promises"; +import { writeFile } from "node:fs/promises"; import path from "node:path"; -import { pathToFileURL } from "node:url"; import { boundedString } from "../ipc-security.mjs"; -const MAX_EXPORT_HTML_BYTES = 20 * 1024 * 1024; +const MAX_EXPORT_HTML_BYTES = 100 * 1024 * 1024; export function registerConversationExportIpc({ ipcMain, - BrowserWindow, dialog, app, authorize, getMainWindow, }) { - ipcMain.handle("laobos:pdf:export-conversation", async (event, input = {}) => { + ipcMain.handle("laobos:html:export-conversation", async (event, input = {}) => { authorize(event); const html = boundedString(input.html, "导出内容", MAX_EXPORT_HTML_BYTES); - const suggestedName = safePdfName(input.suggestedName); + const suggestedName = safeHtmlName(input.suggestedName); const parent = getMainWindow(); const result = await dialog.showSaveDialog(parent, { - title: "导出会话为 PDF", + title: "导出会话为 HTML", defaultPath: path.join(app.getPath("documents"), suggestedName), - filters: [{ name: "PDF 文档", extensions: ["pdf"] }], + filters: [{ name: "HTML 文档", extensions: ["html"] }], properties: ["showOverwriteConfirmation", "createDirectory"], }); if (result.canceled || !result.filePath) return { canceled: true }; - const tempRoot = path.join(app.getPath("temp"), "laobos-conversation-export"); - await mkdir(tempRoot, { recursive: true, mode: 0o700 }); - const tempFile = path.join(tempRoot, `${crypto.randomUUID()}.html`); - await writeFile(tempFile, html, { encoding: "utf8", mode: 0o600 }); - - const exportWindow = new BrowserWindow({ - show: false, - width: 900, - height: 1200, - webPreferences: { - contextIsolation: true, - nodeIntegration: false, - sandbox: true, - }, - }); - - try { - await exportWindow.loadURL(pathToFileURL(tempFile).toString()); - const pdf = await exportWindow.webContents.printToPDF({ - printBackground: true, - pageSize: "A4", - preferCSSPageSize: true, - }); - await writeFile(result.filePath, pdf, { mode: 0o600 }); - return { canceled: false, filePath: result.filePath }; - } finally { - if (!exportWindow.isDestroyed()) exportWindow.destroy(); - await rm(tempFile, { force: true }); - } + await writeFile(result.filePath, html, { encoding: "utf8", mode: 0o600 }); + return { canceled: false, filePath: result.filePath }; }); - return () => ipcMain.removeHandler("laobos:pdf:export-conversation"); + return () => ipcMain.removeHandler("laobos:html:export-conversation"); } -export function safePdfName(value) { +export function safeHtmlName(value) { const base = typeof value === "string" && value.trim() ? value.trim() : "劳博士会话"; const sanitized = base .replace(/[\\/:*?"<>|\u0000-\u001f]/gu, "-") .replace(/\s+/gu, " ") .slice(0, 120) .replace(/[. ]+$/gu, ""); - return `${sanitized || "劳博士会话"}.pdf`; + return `${sanitized || "劳博士会话"}.html`; } diff --git a/desktop/domains/desktop-settings.mjs b/desktop/domains/desktop-settings.mjs index fbab83a..1a6f597 100644 --- a/desktop/domains/desktop-settings.mjs +++ b/desktop/domains/desktop-settings.mjs @@ -2,10 +2,33 @@ import { mkdir, readFile, rename, writeFile } from "node:fs/promises"; import path from "node:path"; const DEFAULTS = Object.freeze({ - version: 2, + version: 5, uploadLocation: "default", + autoCheckUpdates: true, + lastUpdateCheckAt: null, + pendingUpdate: null, + authorizedWorkspaces: [], }); +function normalizePendingUpdate(value) { + if (!value || typeof value !== "object") return null; + const version = typeof value.version === "string" ? value.version.slice(0, 64) : ""; + if (!/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/u.test(version)) return null; + return { + version, + releaseName: typeof value.releaseName === "string" ? value.releaseName.slice(0, 256) : "", + releaseNotes: typeof value.releaseNotes === "string" ? value.releaseNotes.slice(0, 20_000) : "", + releaseDate: + typeof value.releaseDate === "string" && Number.isFinite(Date.parse(value.releaseDate)) + ? value.releaseDate + : "", + downloadedAt: + typeof value.downloadedAt === "string" && Number.isFinite(Date.parse(value.downloadedAt)) + ? value.downloadedAt + : null, + }; +} + export class DesktopSettingsStore { constructor(filePath) { this.filePath = filePath; @@ -51,11 +74,37 @@ export class DesktopSettingsStore { } export function normalizeSettings(value) { + const compatible = [2, 3, 4, 5].includes(value?.version); + const lastUpdateCheckAt = + [3, 4, 5].includes(value?.version) && + typeof value.lastUpdateCheckAt === "string" && + Number.isFinite(Date.parse(value.lastUpdateCheckAt)) + ? value.lastUpdateCheckAt + : null; return { - version: 2, + version: 5, uploadLocation: - value?.version === 2 && value?.uploadLocation === "workspace" + compatible && value?.uploadLocation === "workspace" ? "workspace" : "default", + autoCheckUpdates: + [3, 4, 5].includes(value?.version) ? value.autoCheckUpdates !== false : true, + lastUpdateCheckAt, + pendingUpdate: [4, 5].includes(value?.version) ? normalizePendingUpdate(value.pendingUpdate) : null, + authorizedWorkspaces: value?.version === 5 + ? normalizeAuthorizedWorkspaces(value.authorizedWorkspaces) + : [], }; } + +function normalizeAuthorizedWorkspaces(value) { + if (!Array.isArray(value)) return []; + const roots = []; + for (const entry of value) { + if (typeof entry !== "string" || !path.isAbsolute(entry) || entry.length > 4096) continue; + const normalized = path.normalize(entry); + const key = process.platform === "win32" ? normalized.toLowerCase() : normalized; + if (!roots.some((root) => root.key === key)) roots.push({ key, value: normalized }); + } + return roots.slice(-64).map((root) => root.value); +} diff --git a/desktop/domains/git-review.mjs b/desktop/domains/git-review.mjs index 94877bb..ad208a4 100644 --- a/desktop/domains/git-review.mjs +++ b/desktop/domains/git-review.mjs @@ -1,5 +1,5 @@ -import path from "node:path"; -import { boundedString, resolveAuthorizedPath } from "../ipc-security.mjs"; +import { boundedString } from "../ipc-security.mjs"; +import { resolveWorkspaceDirectory } from "../workspace-authorization.mjs"; import { branchGit, commitGit, @@ -28,10 +28,10 @@ const channels = [ "laobos:git:sync", ]; -export function registerGitReviewIpc({ ipcMain, workspace, authorize }) { +export function registerGitReviewIpc({ ipcMain, workspace, workspaceAuthorizer, authorize }) { const handle = (channel, operation) => ipcMain.handle(channel, async (event, input = {}) => { authorize(event); - const root = await gitRoot(workspace, input.root); + const root = await gitRoot(workspace, input.root, workspaceAuthorizer); return operation(root, input); }); @@ -60,10 +60,14 @@ export function registerGitReviewIpc({ ipcMain, workspace, authorize }) { }; } -async function gitRoot(workspace, requested) { +async function gitRoot(workspace, requested, workspaceAuthorizer) { const root = requested ? boundedString(requested, "工作区路径", 4_096) : workspace; - const relative = path.relative(workspace, path.resolve(root)); - return (await resolveAuthorizedPath(workspace, relative, { kind: "directory" })).path; + return resolveWorkspaceDirectory({ + authorizer: workspaceAuthorizer, + defaultRoot: workspace, + requested: root, + label: "Git 工作区", + }); } // Kept for compatibility with existing callers and fixtures. diff --git a/desktop/domains/shell.mjs b/desktop/domains/shell.mjs index d68a67b..22b21e1 100644 --- a/desktop/domains/shell.mjs +++ b/desktop/domains/shell.mjs @@ -3,19 +3,54 @@ import { access, mkdir, rename, writeFile } from "node:fs/promises"; import path from "node:path"; const READY_MARKER = "LAOBOS_WSL_READY"; -const ALLOWED_DISTRIBUTIONS = new Set(["Ubuntu", "Debian"]); +const ALLOWED_DISTRIBUTIONS = new Set(["Ubuntu", "Ubuntu-24.04", "Debian"]); export function laobosShellStatePath(dshHome) { return path.join(dshHome, "data", "laobos-shell-state.json"); } export function parseWslDistributions(output) { - return String(output || "") + return decodeWindowsNativeOutput(output) .replaceAll("\0", "") .replace(/^\uFEFF/u, "") .split(/\r?\n/u) .map((line) => line.trim().replace(/^\*\s*/u, "")) - .filter(Boolean); + .filter((line) => line + && line.length <= 128 + && !/(?:未安装|没有安装|no installed|usage:|用法:|适用于 Linux)/iu.test(line)); +} + +export function decodeWindowsNativeOutput(value) { + if (Buffer.isBuffer(value)) { + if (value.length === 0) return ""; + const hasUtf16Bom = value[0] === 0xff && value[1] === 0xfe; + const utf8 = value.toString("utf8"); + const utf16 = value.toString("utf16le").replace(/^\uFEFF/u, ""); + let zeroes = 0; + for (let index = 1; index < Math.min(value.length, 256); index += 2) { + if (value[index] === 0) zeroes += 1; + } + const sampledPairs = Math.floor(Math.min(value.length, 256) / 2); + const utf8LooksMisdecoded = utf8.includes("\0") + || (utf8.match(/\uFFFD/gu)?.length || 0) > Math.max(1, utf8.length * 0.03); + if (hasUtf16Bom + || (sampledPairs > 2 && zeroes / sampledPairs > 0.35) + || (value.length % 2 === 0 && utf8LooksMisdecoded && looksLikeText(utf16))) { + return utf16; + } + return utf8.replace(/^\uFEFF/u, ""); + } + return String(value || "").replace(/^\uFEFF/u, ""); +} + +function looksLikeText(value) { + if (!value) return true; + let controls = 0; + for (const character of value) { + const code = character.codePointAt(0); + if (code < 32 && ![9, 10, 13].includes(code)) controls += 1; + } + return controls / value.length < 0.02; } export function preferredWslDistribution(distributions, preferred) { @@ -28,7 +63,7 @@ export function preferredWslDistribution(distributions, preferred) { export function runFile(executable, args, options = {}) { return new Promise((resolve) => { execFile(executable, args, { - encoding: "utf8", + encoding: options.outputEncoding === "windows-native" ? null : "utf8", windowsHide: true, timeout: options.timeoutMs ?? 10_000, maxBuffer: options.maxBuffer ?? 1024 * 1024, @@ -37,8 +72,12 @@ export function runFile(executable, args, options = {}) { code: error ? Number.isInteger(error.code) ? error.code : -1 : 0, signal: error?.signal || null, timedOut: error?.killed === true, - stdout: String(stdout), - stderr: String(stderr || error?.message || ""), + stdout: options.outputEncoding === "windows-native" + ? decodeWindowsNativeOutput(stdout) + : String(stdout), + stderr: options.outputEncoding === "windows-native" + ? decodeWindowsNativeOutput(stderr) || String(error?.message || "") + : String(stderr || error?.message || ""), }); }); }); @@ -89,15 +128,23 @@ export async function detectShellEnvironment({ path.join(systemRoot, "System32", "wsl.exe"), ], canAccess); let listResult; + let statusResult; let distributions = []; let distribution; let wslReady = false; let healthResult; if (wslExecutable) { - listResult = await execute(wslExecutable, ["--list", "--quiet"], { - timeoutMs: 10_000, - }); + [statusResult, listResult] = await Promise.all([ + execute(wslExecutable, ["--status"], { + timeoutMs: 10_000, + outputEncoding: "windows-native", + }), + execute(wslExecutable, ["--list", "--quiet"], { + timeoutMs: 10_000, + outputEncoding: "windows-native", + }), + ]); if (listResult.code === 0) { distributions = parseWslDistributions(listResult.stdout); distribution = preferredWslDistribution( @@ -112,8 +159,8 @@ export async function detectShellEnvironment({ "--exec", "bash", "-lc", - `printf ${READY_MARKER}`, - ], { timeoutMs: 15_000 }); + `printf '${READY_MARKER}:%s' "$(id -u)"`, + ], { timeoutMs: 30_000, outputEncoding: "windows-native" }); wslReady = healthResult.code === 0 && healthResult.stdout.includes(READY_MARKER); } @@ -127,14 +174,34 @@ export async function detectShellEnvironment({ const powershellExecutable = await firstAccessible([ path.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe"), ], canAccess) || "powershell.exe"; + const defaultUserIsRoot = wslReady + && healthResult.stdout.includes(`${READY_MARKER}:0`); + const restartRequired = !distribution && wslRestartRequired(statusResult, listResult); + const phase = wslReady + ? defaultUserIsRoot ? "user-setup-required" : "ready" + : distribution + ? "initialization-required" + : restartRequired + ? "restart-required" + : wslExecutable + ? "distribution-required" + : "component-required"; const selectedBackend = wslReady ? "wsl" : gitBashExecutable ? "git-bash" : "powershell"; - const status = wslReady ? "ready" : "compatible"; + const status = wslReady && !defaultUserIsRoot ? "ready" : "attention"; const message = wslReady - ? `WSL ${distribution} 已就绪,性能模式将使用 Linux Bash。` + ? defaultUserIsRoot + ? `WSL ${distribution} 已可用,但默认登录用户仍是 root;建议完成普通 Linux 用户设置。` + : `WSL ${distribution} 已就绪,性能模式将使用 Linux Bash。` + : distribution + ? healthResult?.timedOut + ? `${distribution} 首次初始化超时,可能有初始化窗口或 OOBE 正在等待。` + : `${distribution} 已安装,但 Bash 尚未通过健康检查。` + : restartRequired + ? "WSL 组件变更需要重启 Windows 后才能生效。" : selectedBackend === "git-bash" ? "WSL 尚未就绪,当前使用 Git Bash 兼容后端。" : "WSL 尚未就绪,当前使用 PowerShell 兼容模式。"; @@ -142,19 +209,21 @@ export async function detectShellEnvironment({ return { version: 1, platform, - phase: wslReady ? "ready" : "fallback", + phase, status, selectedBackend, message, progress: { kind: "determinate", percent: wslReady ? 100 : 0 }, installAvailable: true, - requiresRestart: false, + requiresRestart: restartRequired, wsl: { executable: wslExecutable, available: Boolean(wslExecutable), - componentEnabled: listResult?.code === 0, + componentEnabled: statusResult?.code === 0 || listResult?.code === 0, installed: Boolean(distribution), ready: wslReady, + defaultUserIsRoot, + initializationBlocked: Boolean(distribution && healthResult?.timedOut), distributions, distribution, }, @@ -162,19 +231,30 @@ export async function detectShellEnvironment({ powershell: { executable: powershellExecutable }, diagnostics: { list: diagnosticText(listResult), + status: diagnosticText(statusResult), health: diagnosticText(healthResult), }, updatedAt: now(), }; } +function wslRestartRequired(...results) { + const text = results.map((result) => diagnosticText(result)).join("\n"); + return [ + /restart|required.*reboot|reboot.*required/iu, + /重启|重新启动/u, + /virtualmachineplatform|virtual machine platform/iu, + /虚拟机平台|未启用虚拟化/u, + ].some((pattern) => pattern.test(text)); +} + function quotePowerShellLiteral(value) { return `'${String(value).replaceAll("'", "''")}'`; } export async function runElevatedWslInstall({ state, - distribution = "Ubuntu", + distribution = "Ubuntu-24.04", execute = runFile, }) { if (!ALLOWED_DISTRIBUTIONS.has(distribution)) { @@ -213,7 +293,7 @@ export function buildShellRepairPrompt(state) { diagnostics: state.diagnostics, lastError: state.lastError, }, null, 2); - return `请帮助我诊断并修复劳博士的 WSL/Shell 环境。\n\n当前脱敏诊断数据:\n\n\`\`\`json\n${diagnostics}\n\`\`\`\n\n请先执行只读诊断,判断是 WSL 组件、Linux 发行版、虚拟化、重启、网络还是企业策略问题。给出结论和最小修复步骤。任何需要管理员权限、启停 Windows 功能、安装软件、重启或修改系统策略的动作,都必须先解释影响并征得我的明确确认;不要关闭安全软件,不要执行来源不明的脚本,也不要重复执行可能已经部分成功的安装命令。修复后请使用 wsl.exe --status、wsl.exe --list --verbose 和一个无副作用的 Bash 命令验证。`; + return `请帮助我诊断并修复劳博士的 WSL/Shell 环境。\n\n当前脱敏诊断数据:\n\n\`\`\`json\n${diagnostics}\n\`\`\`\n\n请先执行只读诊断,判断是 WSL 组件、Linux 发行版、虚拟化、待重启、首次初始化/OOBE、网络还是企业策略问题。给出结论和最小修复步骤。Windows 中文环境的 wsl.exe 输出可能是 UTF-16LE;乱码时应采集原始字节并显式解码,不要据乱码下结论。若功能状态与运行状态矛盾,请比较 DISM/CBS 功能变更时间与本次开机时间。若 wsl --install 已下载发行版但一直不退出,先查残留进程、发行版注册状态和 HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Lxss 下的 RunOOBE;只有确认是 OOBE 门闩且获得用户许可后,才可提出修改注册表并配合 wsl --shutdown 的可逆方案。复杂 Linux 命令不要经 cmd.exe 二次转义。若默认 uid 为 0,还需引导创建普通 Linux 用户并设置为默认用户。任何需要管理员权限、启停 Windows 功能、安装软件、重启、结束进程或修改注册表/系统策略的动作,都必须先解释影响并征得我的明确确认;不要关闭安全软件,不要执行来源不明的脚本,也不要重复执行可能已经部分成功的安装命令。若 pwsh 等最小命令出现 0xC0000142,先对比沙箱内外启动,区分注入层兼容问题与系统损坏。修复后请使用 wsl.exe --status、wsl.exe --list --verbose 和一个无副作用的 Bash 命令验证。`; } export class LaobosShellManager { @@ -280,7 +360,7 @@ export class LaobosShellManager { return this.refreshing; } - async install(distribution = "Ubuntu") { + async install(distribution = "Ubuntu-24.04") { if (this.platform !== "win32") throw new Error("当前系统不需要安装 WSL。 "); if (this.installing) return this.installing; if (!ALLOWED_DISTRIBUTIONS.has(distribution)) throw new Error("不支持的 WSL 发行版。 "); @@ -324,17 +404,7 @@ export class LaobosShellManager { canAccess: this.canAccess, preferredDistribution: distribution, }); - if (!detected.wsl?.ready) { - detected.phase = detected.wsl?.installed - ? "initialization-required" - : "restart-required"; - detected.status = "attention"; - detected.requiresRestart = !detected.wsl?.installed; - detected.message = detected.requiresRestart - ? "WSL 组件已安装,重启 Windows 后将自动继续检测。" - : "Linux 发行版已安装,需要完成首次初始化。"; - detected.progress = { kind: "determinate", percent: 90 }; - } + if (!detected.wsl?.ready) detected.progress = { kind: "determinate", percent: 90 }; await this.update(detected, true); return this.snapshot(); })().finally(() => { @@ -420,7 +490,7 @@ export function registerShellIpc({ }); ipcMain.handle("laobos:shell:install-wsl", async (event, input = {}) => { authorize(event); - return manager.install(input.distribution || "Ubuntu"); + return manager.install(input.distribution || "Ubuntu-24.04"); }); ipcMain.handle("laobos:shell:initialize-wsl", async (event) => { authorize(event); diff --git a/desktop/domains/terminal.mjs b/desktop/domains/terminal.mjs index 9c96013..7889dc6 100644 --- a/desktop/domains/terminal.mjs +++ b/desktop/domains/terminal.mjs @@ -3,7 +3,8 @@ import { spawnSync } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; import * as pty from "node-pty"; -import { boundedString, resolveAuthorizedPath } from "../ipc-security.mjs"; +import { boundedString } from "../ipc-security.mjs"; +import { resolveWorkspaceDirectory } from "../workspace-authorization.mjs"; const MAX_TERMINALS = 8; const MAX_WRITE_BYTES = 64 * 1024; @@ -11,6 +12,7 @@ const MAX_WRITE_BYTES = 64 * 1024; export function registerTerminalIpc({ ipcMain, workspace, + workspaceAuthorizer, authorize, getMainWindow, }) { @@ -19,7 +21,7 @@ export function registerTerminalIpc({ ipcMain.handle("laobos:terminal:create", async (event, input = {}) => { authorize(event); if (terminals.size >= MAX_TERMINALS) throw new Error(`终端数量已达到上限(${MAX_TERMINALS})。`); - const cwd = await terminalCwd(workspace, input.cwd); + const cwd = await terminalCwd(workspace, input.cwd, workspaceAuthorizer); const cols = dimension(input.cols, 80, 20, 500); const rows = dimension(input.rows, 24, 5, 200); const tmuxRequested = input.tmux === true && process.platform !== "win32"; @@ -167,10 +169,14 @@ export function findExecutable(command, envPath = process.env.PATH || "") { return undefined; } -async function terminalCwd(workspace, requested) { +async function terminalCwd(workspace, requested, workspaceAuthorizer) { const value = requested ? boundedString(requested, "终端目录", 4096) : workspace; - const relative = path.relative(workspace, path.resolve(value)); - return (await resolveAuthorizedPath(workspace, relative, { kind: "directory" })).path; + return resolveWorkspaceDirectory({ + authorizer: workspaceAuthorizer, + defaultRoot: workspace, + requested: value, + label: "终端工作区", + }); } function terminalTmuxKey(value) { diff --git a/desktop/domains/updater.mjs b/desktop/domains/updater.mjs new file mode 100644 index 0000000..09b362f --- /dev/null +++ b/desktop/domains/updater.mjs @@ -0,0 +1,382 @@ +import electronUpdater from "electron-updater"; +const AUTO_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; +const AUTO_CHECK_DELAY_MS = 15_000; +const MAX_RELEASE_NOTES_LENGTH = 20_000; + +function text(value, maximum = 512) { + return typeof value === "string" ? value.slice(0, maximum) : ""; +} + +function releaseNotes(value) { + if (typeof value === "string") { + return value + .replace(/<\s*br\s*\/?\s*>/giu, "\n") + .replace(/<\s*\/p\s*>/giu, "\n\n") + .replace(/<\s*li(?:\s[^>]*)?>/giu, "- ") + .replace(/<[^>]+>/gu, "") + .replace(/ /giu, " ") + .replace(/&/giu, "&") + .replace(/</giu, "<") + .replace(/>/giu, ">") + .replace(/"/giu, '"') + .replace(/'/giu, "'") + .trim() + .slice(0, MAX_RELEASE_NOTES_LENGTH); + } + if (!Array.isArray(value)) return ""; + return value + .map((item) => `${text(item?.version, 64)}\n${releaseNotes(item?.note).slice(0, 5_000)}`.trim()) + .filter(Boolean) + .join("\n\n") + .slice(0, MAX_RELEASE_NOTES_LENGTH); +} + +function updateInfo(info = {}) { + return { + availableVersion: text(info.version, 64), + releaseName: text(info.releaseName, 256), + releaseNotes: releaseNotes(info.releaseNotes), + releaseDate: text(info.releaseDate, 64), + }; +} + +function errorInfo(error) { + return { + code: text(error?.code, 128), + message: text(error instanceof Error ? error.message : String(error), 2_000), + }; +} + +function compareVersions(left, right) { + const leftParts = String(left).split(/[.+-]/u).slice(0, 3).map(Number); + const rightParts = String(right).split(/[.+-]/u).slice(0, 3).map(Number); + for (let index = 0; index < 3; index += 1) { + const difference = (leftParts[index] || 0) - (rightParts[index] || 0); + if (difference !== 0) return Math.sign(difference); + } + return String(left).localeCompare(String(right), "en", { numeric: true }); +} + +export class DesktopUpdater { + constructor({ + updater, + app, + settings, + getMainWindow, + platform = process.platform, + logger = console, + now = () => Date.now(), + setTimer = setTimeout, + clearTimer = clearTimeout, + }) { + this.updater = updater; + this.app = app; + this.settings = settings; + this.getMainWindow = getMainWindow; + this.logger = logger; + this.now = now; + this.setTimer = setTimer; + this.clearTimer = clearTimer; + this.timer = undefined; + this.listeners = []; + this.pendingWrite = Promise.resolve(); + this.restoring = false; + this.supported = app.isPackaged && ["darwin", "win32"].includes(platform); + this.state = { + schema: 1, + supported: this.supported, + phase: this.supported ? "idle" : "disabled", + currentVersion: app.getVersion(), + availableVersion: "", + releaseName: "", + releaseNotes: "", + releaseDate: "", + progress: null, + cached: false, + error: null, + }; + + if (this.supported && !this.updater) { + throw new Error("当前平台缺少 Electron 更新器。"); + } + if (this.supported) this.configure(); + } + + configure() { + this.updater.autoDownload = false; + this.updater.autoInstallOnAppQuit = false; + this.updater.allowPrerelease = false; + this.updater.logger = this.logger; + + this.listen("checking-for-update", () => { + this.publish({ phase: "checking", progress: null, error: null }); + }); + this.listen("update-available", (info) => { + this.publish({ + phase: "available", + ...updateInfo(info), + progress: null, + cached: this.restoring, + error: null, + }); + }); + this.listen("update-not-available", () => { + void this.clearPendingUpdate(); + this.publish({ + phase: "up-to-date", + availableVersion: "", + releaseName: "", + releaseNotes: "", + releaseDate: "", + progress: null, + cached: false, + error: null, + }); + }); + this.listen("download-progress", (progress = {}) => { + this.publish({ + phase: "downloading", + progress: { + percent: Number.isFinite(progress.percent) ? progress.percent : 0, + bytesPerSecond: Number.isFinite(progress.bytesPerSecond) ? progress.bytesPerSecond : 0, + transferred: Number.isFinite(progress.transferred) ? progress.transferred : 0, + total: Number.isFinite(progress.total) ? progress.total : 0, + }, + error: null, + }); + }); + this.listen("update-downloaded", (info) => { + const received = updateInfo(info); + const next = { + availableVersion: received.availableVersion || this.state.availableVersion, + releaseName: received.releaseName || this.state.releaseName, + releaseNotes: received.releaseNotes || this.state.releaseNotes, + releaseDate: received.releaseDate || this.state.releaseDate, + }; + this.persistPendingUpdate(next); + this.publish({ + phase: "downloaded", + ...next, + progress: null, + cached: true, + error: null, + }); + }); + this.listen("error", (error) => { + this.publish({ + phase: this.state.phase === "installing" ? "downloaded" : "error", + progress: null, + error: errorInfo(error), + }); + }); + } + + persistPendingUpdate(info) { + const pendingUpdate = { + version: info.availableVersion, + releaseName: info.releaseName, + releaseNotes: info.releaseNotes, + releaseDate: info.releaseDate, + downloadedAt: new Date(this.now()).toISOString(), + }; + this.pendingWrite = this.pendingWrite + .then(() => this.settings.update({ pendingUpdate })) + .catch((error) => this.logger.warn?.("无法保存更新缓存状态:", error)); + return this.pendingWrite; + } + + clearPendingUpdate() { + this.pendingWrite = this.pendingWrite + .then(() => this.settings.update({ pendingUpdate: null })) + .catch((error) => this.logger.warn?.("无法清除更新缓存状态:", error)); + return this.pendingWrite; + } + + async initialize() { + if (!this.supported) return this.snapshot(); + const preferences = await this.settings.get(); + const pending = preferences.pendingUpdate; + if (!pending) return this.snapshot(); + if (compareVersions(pending.version, this.state.currentVersion) <= 0) { + await this.clearPendingUpdate(); + return this.snapshot(); + } + + this.restoring = true; + this.publish({ + phase: "restoring", + availableVersion: pending.version, + releaseName: pending.releaseName, + releaseNotes: pending.releaseNotes, + releaseDate: pending.releaseDate, + progress: null, + cached: true, + error: null, + }); + try { + const result = await this.updater.checkForUpdates(); + const latestVersion = result?.updateInfo?.version || this.state.availableVersion; + if (latestVersion !== pending.version) { + await this.clearPendingUpdate(); + this.publish({ cached: false }); + return this.snapshot(); + } + await this.updater.downloadUpdate(); + await this.pendingWrite; + } catch (error) { + if (!this.state.error) this.publish({ phase: "error", cached: true, error: errorInfo(error) }); + } finally { + this.restoring = false; + } + return this.snapshot(); + } + + listen(event, listener) { + this.updater.on(event, listener); + this.listeners.push([event, listener]); + } + + snapshot() { + return structuredClone(this.state); + } + + publish(patch) { + this.state = { ...this.state, ...patch }; + const snapshot = this.snapshot(); + const window = this.getMainWindow?.(); + if (window && !window.isDestroyed()) { + window.webContents.send("laobos:updates:state", snapshot); + } + return snapshot; + } + + async preferences() { + const value = await this.settings.get(); + return { + autoCheckUpdates: value.autoCheckUpdates !== false, + lastUpdateCheckAt: value.lastUpdateCheckAt || null, + }; + } + + async setPreferences(input = {}) { + if (typeof input.autoCheckUpdates !== "boolean") { + throw new TypeError("自动检查更新设置必须是布尔值。"); + } + const value = await this.settings.update({ + autoCheckUpdates: input.autoCheckUpdates, + }); + return { + autoCheckUpdates: value.autoCheckUpdates, + lastUpdateCheckAt: value.lastUpdateCheckAt, + }; + } + + async check({ automatic = false } = {}) { + if (!this.supported) return this.snapshot(); + if (["restoring", "checking", "downloading", "downloaded", "installing"].includes(this.state.phase)) { + return this.snapshot(); + } + + if (automatic) { + const preferences = await this.preferences(); + if (!preferences.autoCheckUpdates) return this.snapshot(); + const lastCheck = preferences.lastUpdateCheckAt + ? Date.parse(preferences.lastUpdateCheckAt) + : 0; + if (Number.isFinite(lastCheck) && this.now() - lastCheck < AUTO_CHECK_INTERVAL_MS) { + return this.snapshot(); + } + } + + this.publish({ phase: "checking", progress: null, error: null }); + try { + await this.updater.checkForUpdates(); + await this.settings.update({ lastUpdateCheckAt: new Date(this.now()).toISOString() }); + } catch (error) { + if (this.state.phase !== "error") { + this.publish({ phase: "error", progress: null, error: errorInfo(error) }); + } + } + return this.snapshot(); + } + + async download() { + if (!this.supported) return this.snapshot(); + if (this.state.phase !== "available") { + throw new Error("当前没有可以下载的软件更新。"); + } + this.publish({ phase: "downloading", progress: null, error: null }); + try { + await this.updater.downloadUpdate(); + await this.pendingWrite; + } catch (error) { + if (this.state.phase !== "error") { + this.publish({ phase: "error", progress: null, error: errorInfo(error) }); + } + } + return this.snapshot(); + } + + async install() { + if (!this.supported) return this.snapshot(); + if (this.state.phase !== "downloaded") { + throw new Error("软件更新尚未下载完成。"); + } + this.publish({ phase: "installing", progress: null, error: null }); + try { + await this.pendingWrite; + this.updater.quitAndInstall(false, true); + } catch (error) { + this.publish({ phase: "downloaded", progress: null, cached: true, error: errorInfo(error) }); + } + return this.snapshot(); + } + + scheduleAutoCheck() { + if (!this.supported || this.timer) return; + this.timer = this.setTimer(() => { + this.timer = undefined; + void this.check({ automatic: true }); + }, AUTO_CHECK_DELAY_MS); + this.timer?.unref?.(); + } + + dispose() { + if (this.timer) this.clearTimer(this.timer); + this.timer = undefined; + for (const [event, listener] of this.listeners) { + this.updater.removeListener(event, listener); + } + this.listeners = []; + } +} + +export function registerUpdaterIpc({ ipcMain, authorize, ...options }) { + const useNativeUpdater = + options.app.isPackaged && ["darwin", "win32"].includes(process.platform); + const service = new DesktopUpdater({ + ...options, + updater: options.updater || (useNativeUpdater ? electronUpdater.autoUpdater : undefined), + }); + const channels = [ + ["laobos:updates:status", () => service.snapshot()], + ["laobos:updates:preferences", () => service.preferences()], + ["laobos:updates:set-preferences", (_event, input) => service.setPreferences(input)], + ["laobos:updates:check", () => service.check()], + ["laobos:updates:download", () => service.download()], + ["laobos:updates:install", () => service.install()], + ]; + + for (const [channel, handler] of channels) { + ipcMain.handle(channel, (event, input) => { + authorize(event); + return handler(event, input); + }); + } + void service.initialize().finally(() => service.scheduleAutoCheck()); + + return () => { + service.dispose(); + for (const [channel] of channels) ipcMain.removeHandler(channel); + }; +} diff --git a/desktop/domains/workspace-files.mjs b/desktop/domains/workspace-files.mjs index 660c86f..a5bb355 100644 --- a/desktop/domains/workspace-files.mjs +++ b/desktop/domains/workspace-files.mjs @@ -8,11 +8,13 @@ import { readFile, readdir, rename, + rmdir, unlink, writeFile, } from "node:fs/promises"; import path from "node:path"; -import { boundedString, isPathInside, resolveAuthorizedPath } from "../ipc-security.mjs"; +import { boundedString, resolveAuthorizedPath } from "../ipc-security.mjs"; +import { resolveWorkspaceDirectory } from "../workspace-authorization.mjs"; const MAX_DIRECTORY_ENTRIES = 2_000; const MAX_TEXT_BYTES = 5 * 1024 * 1024; @@ -30,6 +32,17 @@ const SENSITIVE_NAMES = new Set([ "id_rsa", "id_ed25519", ]); +const PLAIN_TEXT_NAMES = new Set([ + ".editorconfig", + ".gitattributes", + ".gitignore", + ".prettierignore", + "dockerfile", + "license", + "makefile", + "procfile", +]); +const WINDOWS_RESERVED_FILE_NAME = /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/iu; export function registerWorkspaceFilesIpc({ ipcMain, @@ -39,16 +52,21 @@ export function registerWorkspaceFilesIpc({ dshHome, getMainWindow, settings, + workspaceAuthorizer, authorize, }) { ipcMain.handle("laobos:workspace:context", async (event) => { authorize(event); - return { root: workspace, settings: await settings.get() }; + return { + root: workspace, + authorizedRoots: workspaceAuthorizer ? await workspaceAuthorizer.roots() : [workspace], + settings: await settings.get(), + }; }); ipcMain.handle("laobos:workspace:list", async (event, input = {}) => { authorize(event); - const root = await authorizedRoot(workspace, input.root); + const root = await authorizedRoot(workspace, input.root, workspaceAuthorizer); const relative = boundedString(input.path || ".", "目录路径", 4096); const directory = await resolveAuthorizedPath(root, relative, { kind: "directory" }); const entries = await readdir(directory.path, { withFileTypes: true }); @@ -63,6 +81,7 @@ export function registerWorkspaceFilesIpc({ name: entry.name, path: path.relative(root, child.path) || ".", type: child.stat.isDirectory() ? "directory" : "file", + mediaType: child.stat.isFile() ? mediaTypeFor(child.path) : null, size: child.stat.isFile() ? child.stat.size : 0, modifiedAt: child.stat.mtimeMs, }; @@ -75,7 +94,7 @@ export function registerWorkspaceFilesIpc({ ipcMain.handle("laobos:workspace:read", async (event, input = {}) => { authorize(event); - const root = await authorizedRoot(workspace, input.root); + const root = await authorizedRoot(workspace, input.root, workspaceAuthorizer); const relative = boundedString(input.path, "文件路径", 4096); assertPreviewAllowed(relative); const file = await resolveAuthorizedPath(root, relative, { kind: "file" }); @@ -86,13 +105,73 @@ export function registerWorkspaceFilesIpc({ const data = await readFile(file.path); if (isText && data.includes(0)) throw new Error("文件包含二进制数据,不能作为文本预览。 "); return isText - ? { kind: "text", mediaType, content: data.toString("utf8"), size: data.byteLength } - : { kind: mediaType === "application/pdf" ? "pdf" : mediaType.startsWith("image/") ? "image" : mediaType.startsWith("audio/") || mediaType.startsWith("video/") ? "media" : "binary", mediaType, base64: data.toString("base64"), size: data.byteLength }; + ? { kind: "text", mediaType, content: data.toString("utf8"), size: data.byteLength, modifiedAt: file.stat.mtimeMs } + : { kind: mediaType === "application/pdf" ? "pdf" : mediaType.startsWith("image/") ? "image" : mediaType.startsWith("audio/") || mediaType.startsWith("video/") ? "media" : "binary", mediaType, base64: data.toString("base64"), size: data.byteLength, modifiedAt: file.stat.mtimeMs }; + }); + + ipcMain.handle("laobos:workspace:write", async (event, input = {}) => { + authorize(event); + const root = await authorizedRoot(workspace, input.root, workspaceAuthorizer); + const relative = boundedString(input.path, "文件路径", 4096); + const content = boundedString(input.content, "文件内容", MAX_TEXT_BYTES); + assertPreviewAllowed(relative); + const file = await resolveAuthorizedPath(root, relative, { kind: "file" }); + const mediaType = mediaTypeFor(file.path); + if (!isTextMediaType(mediaType)) throw new Error("只有文本文件可以在应用内编辑。 "); + if (Number.isFinite(input.expectedModifiedAt) && Math.abs(file.stat.mtimeMs - input.expectedModifiedAt) > 0.5) { + throw new Error("文件已被其他程序修改,请刷新后再编辑。 "); + } + const data = Buffer.from(content, "utf8"); + if (data.byteLength > MAX_TEXT_BYTES) throw new Error(`文件超过编辑上限(${Math.round(MAX_TEXT_BYTES / 1024 / 1024)} MB)。`); + const temporary = path.join(path.dirname(file.path), `.${path.basename(file.path)}.${randomUUID()}.tmp`); + try { + await writeFile(temporary, data, { flag: "wx", mode: file.stat.mode & 0o777 }); + await rename(temporary, file.path); + const saved = await resolveAuthorizedPath(root, relative, { kind: "file" }); + return { saved: true, size: saved.stat.size, modifiedAt: saved.stat.mtimeMs }; + } catch (error) { + await unlink(temporary).catch(() => {}); + throw error; + } + }); + + ipcMain.handle("laobos:workspace:rename", async (event, input = {}) => { + authorize(event); + const root = await authorizedRoot(workspace, input.root, workspaceAuthorizer); + const relative = boundedString(input.path, "路径", 4096); + if (relative === ".") throw new Error("不能重命名工作区根目录。 "); + const name = safeEntryName(input.name); + const source = await resolveAuthorizedPath(root, relative); + const destination = path.join(path.dirname(source.path), name); + await ensureDestinationAvailable(destination); + await rename(source.path, destination); + return { + renamed: true, + name, + path: path.relative(root, destination) || ".", + type: source.stat.isDirectory() ? "directory" : "file", + }; + }); + + ipcMain.handle("laobos:workspace:remove", async (event, input = {}) => { + authorize(event); + const root = await authorizedRoot(workspace, input.root, workspaceAuthorizer); + const relative = boundedString(input.path, "路径", 4096); + if (relative === ".") throw new Error("不能删除工作区根目录。 "); + const target = await resolveAuthorizedPath(root, relative); + if (target.stat.isDirectory()) { + try { await rmdir(target.path); } + catch (error) { + if (["ENOTEMPTY", "EEXIST"].includes(error?.code)) throw new Error("文件夹不为空,只能删除空文件夹。 "); + throw error; + } + } else await unlink(target.path); + return { removed: true, type: target.stat.isDirectory() ? "directory" : "file" }; }); ipcMain.handle("laobos:workspace:reveal", async (event, input = {}) => { authorize(event); - const root = await authorizedRoot(workspace, input.root); + const root = await authorizedRoot(workspace, input.root, workspaceAuthorizer); const target = await resolveAuthorizedPath(root, boundedString(input.path || ".", "路径", 4096)); if (target.stat.isDirectory()) await shell.openPath(target.path); else shell.showItemInFolder(target.path); @@ -177,6 +256,9 @@ export function registerWorkspaceFilesIpc({ "laobos:workspace:context", "laobos:workspace:list", "laobos:workspace:read", + "laobos:workspace:write", + "laobos:workspace:rename", + "laobos:workspace:remove", "laobos:workspace:reveal", "laobos:uploads:set-location", "laobos:uploads:pick-files", @@ -237,9 +319,13 @@ export function safeUploadFileName(value) { const normalized = path.basename(String(value || "").replaceAll("\\", "/")) .normalize("NFKC") .replace(/[\u0000-\u001f\u007f]/gu, "") + .replace(/[<>:"/\\|?*]/gu, "_") .trim() - .slice(0, 180); - return normalized && normalized !== "." && normalized !== ".." ? normalized : "file"; + .replace(/[. ]+$/gu, "") + .slice(0, 180) + .replace(/[. ]+$/gu, ""); + if (!normalized || normalized === "." || normalized === "..") return "file"; + return WINDOWS_RESERVED_FILE_NAME.test(normalized) ? `_${normalized}`.slice(0, 180) : normalized; } export function managedUploadRoot({ workspace, dshHome, location, sessionId }) { @@ -387,18 +473,16 @@ export async function copyManagedUploadFiles({ } } -async function authorizedRoot(defaultRoot, requested) { - if (requested === undefined || requested === "") { - return (await resolveAuthorizedPath(defaultRoot, ".", { kind: "directory" })).path; +async function authorizedRoot(defaultRoot, requested, workspaceAuthorizer) { + if (requested !== undefined && requested !== "" && !path.isAbsolute(requested)) { + throw new Error("工作区路径必须是绝对路径。 "); } - const root = boundedString(requested, "工作区路径", 4096); - if (!path.isAbsolute(root)) throw new Error("工作区路径必须是绝对路径。 "); - const defaultResolved = await resolveAuthorizedPath(defaultRoot, ".", { kind: "directory" }); - const requestedResolved = await resolveAuthorizedPath(root, ".", { kind: "directory" }); - if (!isPathInside(defaultResolved.path, requestedResolved.path)) { - throw new Error("该工作区不在桌面应用启动时授权的范围内。 "); - } - return requestedResolved.path; + return resolveWorkspaceDirectory({ + authorizer: workspaceAuthorizer, + defaultRoot, + requested: requested || defaultRoot, + label: "文件工作区", + }); } function assertPreviewAllowed(relative) { @@ -408,17 +492,43 @@ function assertPreviewAllowed(relative) { } } +function isTextMediaType(mediaType) { + return mediaType.startsWith("text/") || mediaType === "application/json"; +} + +function safeEntryName(value) { + const name = boundedString(value, "新名称", 255).trim(); + if (!name || name === "." || name === ".." || /[\\/\u0000-\u001f\u007f]/u.test(name)) { + throw new Error("文件名称无效。 "); + } + return name; +} + +async function ensureDestinationAvailable(destination) { + try { + await lstat(destination); + } catch (error) { + if (error?.code === "ENOENT") return; + throw error; + } + throw new Error("同一目录中已存在该名称。 "); +} + export function mediaTypeFor(filePath) { const extension = path.extname(filePath).toLowerCase(); + if (PLAIN_TEXT_NAMES.has(path.basename(filePath).toLowerCase())) return "text/plain"; return ({ ".md": "text/markdown", ".mdx": "text/markdown", ".txt": "text/plain", ".js": "text/javascript", ".mjs": "text/javascript", ".cjs": "text/javascript", ".ts": "text/typescript", ".tsx": "text/typescript", ".jsx": "text/javascript", - ".css": "text/css", ".html": "text/html", ".htm": "text/html", - ".json": "application/json", ".yaml": "text/yaml", ".yml": "text/yaml", + ".css": "text/css", ".scss": "text/css", ".less": "text/css", ".html": "text/html", ".htm": "text/html", + ".json": "application/json", ".jsonc": "application/json", ".yaml": "text/yaml", ".yml": "text/yaml", ".toml": "text/plain", ".xml": "text/xml", ".csv": "text/csv", ".tsv": "text/tab-separated-values", ".log": "text/plain", ".py": "text/x-python", ".rb": "text/x-ruby", ".rs": "text/x-rust", - ".go": "text/x-go", ".java": "text/x-java", ".sh": "text/x-shellscript", + ".go": "text/x-go", ".java": "text/x-java", ".kt": "text/plain", ".kts": "text/plain", + ".c": "text/plain", ".h": "text/plain", ".cc": "text/plain", ".cpp": "text/plain", ".cxx": "text/plain", ".hpp": "text/plain", + ".sh": "text/x-shellscript", ".bash": "text/x-shellscript", ".zsh": "text/x-shellscript", ".fish": "text/x-shellscript", + ".sql": "text/plain", ".graphql": "text/plain", ".gql": "text/plain", ".ini": "text/plain", ".conf": "text/plain", ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".gif": "image/gif", ".webp": "image/webp", ".svg": "image/svg+xml", ".pdf": "application/pdf", ".doc": "application/msword", diff --git a/desktop/local-plugins.mjs b/desktop/local-plugins.mjs index 6d60fb6..a18a86d 100644 --- a/desktop/local-plugins.mjs +++ b/desktop/local-plugins.mjs @@ -26,6 +26,7 @@ export const bundledPluginNames = [ "laobos-ssh", "laobos-app-manager", "laobos-market", + "laobos-updater", ]; const markerName = ".laobos-managed-plugin.json"; diff --git a/desktop/main.mjs b/desktop/main.mjs index 3c5ba0f..12d8bda 100644 --- a/desktop/main.mjs +++ b/desktop/main.mjs @@ -2,8 +2,10 @@ import { existsSync } from "node:fs"; import path from "node:path"; import { app, + autoUpdater as nativeAutoUpdater, BrowserWindow, WebContentsView, + clipboard, dialog, ipcMain, safeStorage, @@ -12,8 +14,15 @@ import { } from "electron"; import { startDshRuntime } from "./dsh-runtime.mjs"; import { bundledPluginMode } from "./local-plugins.mjs"; +import { + clearPendingPlugin, + quarantineUserPlugins, + readPendingPlugin, + restoreLastPluginRecovery, +} from "./plugin-recovery.mjs"; import { migratePiOnFirstRun } from "../migrations/auto-pi.mjs"; import { registerDesktopDomains } from "./register-desktop-domains.mjs"; +import { installPermissionPolicy } from "./permissions.mjs"; const isDevelopment = !app.isPackaged; const productName = isDevelopment ? "劳博士(开发版)" : "劳博士"; @@ -33,6 +42,28 @@ let isQuitting = false; let disposeDesktopDomains; let dshHome; let workspace; +let shutdownPromise; +let quitReady = false; +let runtimeRestarting = false; +let rendererRecoveryAttempted = false; + +const RENDERER_BOOT_TIMEOUT_MS = 20_000; +const RENDERER_BOOT_POLL_MS = 250; + +function prepareToQuit() { + isQuitting = true; + if (!shutdownPromise) { + shutdownPromise = (async () => { + const dispose = disposeDesktopDomains; + disposeDesktopDomains = undefined; + dispose?.(); + const activeRuntime = runtime; + runtime = undefined; + await activeRuntime?.close(); + })(); + } + return shutdownPromise; +} function resolveRuntimeFiles() { const appRoot = app.getAppPath(); @@ -96,7 +127,7 @@ async function bootRuntime() { } runtime.child.once("exit", (code, signal) => { - if (isQuitting) return; + if (isQuitting || runtimeRestarting) return; dialog.showErrorBox( "劳博士运行时已停止", `DSH 运行时意外退出(code=${String(code)}, signal=${String(signal)})。`, @@ -105,10 +136,97 @@ async function bootRuntime() { }); } -function installPermissionPolicy() { - session.defaultSession.setPermissionRequestHandler( - (_webContents, _permission, callback) => callback(false), - ); +function reasonMessage(reason) { + return reason instanceof Error ? reason.message : String(reason); +} + +async function restartRuntimeAfterPluginFailure(reason) { + if (runtimeRestarting) return { changed: false, entryIds: [] }; + runtimeRestarting = true; + try { + const recovery = await quarantineUserPlugins(dshHome, reasonMessage(reason)); + if (!recovery.changed) return recovery; + const previousRuntime = runtime; + runtime = undefined; + runtimeUrl = undefined; + await previousRuntime?.close(); + console.warn( + `[plugins] 已进入安全模式并停用:${recovery.entryIds.join(", ")}`, + ); + try { + await bootRuntime(); + return recovery; + } catch (retryError) { + await restoreLastPluginRecovery(dshHome).catch(() => false); + throw new AggregateError( + [reason, retryError], + `插件安全模式启动仍然失败:${reasonMessage(retryError)}`, + ); + } + } finally { + runtimeRestarting = false; + } +} + +async function bootRuntimeWithPluginRecovery() { + try { + await bootRuntime(); + } catch (error) { + const recovery = await restartRuntimeAfterPluginFailure(error); + if (!recovery.changed) throw error; + } +} + +async function inspectRendererBoot(window) { + const deadline = Date.now() + RENDERER_BOOT_TIMEOUT_MS; + while (!window.isDestroyed() && Date.now() < deadline) { + const state = await window.webContents.executeJavaScript(`(() => { + const root = document.getElementById("root"); + const text = root?.innerText || ""; + if (text.includes("Failed to load plugins")) { + return { state: "failed", detail: text.slice(0, 4000) }; + } + if (globalThis.__DSH_MODULES__ && root?.childElementCount > 0 && !text.includes("Loading plugins")) { + return { state: "ready" }; + } + return { state: "loading" }; + })()`, true).catch((error) => ({ state: "failed", detail: reasonMessage(error) })); + if (state.state !== "loading") return state; + await new Promise((resolve) => setTimeout(resolve, RENDERER_BOOT_POLL_MS)); + } + return { state: "timeout", detail: "DSH 前端插件启动超时。" }; +} + +async function loadRuntimePage(window) { + await window.loadURL(runtimeUrl); + const state = await inspectRendererBoot(window); + if (state.state === "ready") { + await clearPendingPlugin(dshHome); + return; + } + + const pending = await readPendingPlugin(dshHome); + const shouldRecover = state.state === "failed" || pending !== undefined; + if (!shouldRecover || rendererRecoveryAttempted) { + if (state.state !== "timeout") { + dialog.showErrorBox("插件启动失败", state.detail || "DSH 前端插件无法启动。"); + } + return; + } + + rendererRecoveryAttempted = true; + const recovery = await restartRuntimeAfterPluginFailure(state.detail || state.state); + if (!recovery.changed || !runtimeUrl || window.isDestroyed()) { + dialog.showErrorBox("插件启动失败", state.detail || "没有可自动隔离的用户插件。"); + return; + } + await dialog.showMessageBox(window, { + type: "warning", + title: "已隔离故障插件", + message: "检测到用户插件阻止应用启动,已自动进入安全模式。", + detail: `已停用:${recovery.entryIds.join(", ")}\n恢复记录:${recovery.recoveryPath}`, + }); + await loadRuntimePage(window); } function createWindow() { @@ -146,7 +264,10 @@ function createWindow() { event.preventDefault(); } }); - void mainWindow.loadURL(runtimeUrl); + void loadRuntimePage(mainWindow).catch((error) => { + console.error("劳博士页面启动失败:", error); + dialog.showErrorBox("劳博士页面启动失败", reasonMessage(error)); + }); } const hasSingleInstanceLock = app.requestSingleInstanceLock(); @@ -162,12 +283,16 @@ if (!hasSingleInstanceLock) { app.whenReady().then(async () => { try { - await bootRuntime(); - installPermissionPolicy(); + await bootRuntimeWithPluginRecovery(); + installPermissionPolicy({ + session: session.defaultSession, + getRuntimeUrl: () => runtimeUrl, + }); disposeDesktopDomains = registerDesktopDomains({ ipcMain, BrowserWindow, WebContentsView, + clipboard, dialog, shell, safeStorage, @@ -195,11 +320,17 @@ if (!hasSingleInstanceLock) { }); } -app.on("before-quit", () => { - isQuitting = true; - disposeDesktopDomains?.(); - disposeDesktopDomains = undefined; - void runtime?.close(); +nativeAutoUpdater.on("before-quit-for-update", () => { + void prepareToQuit(); +}); + +app.on("before-quit", (event) => { + if (quitReady) return; + event.preventDefault(); + void prepareToQuit().finally(() => { + quitReady = true; + app.quit(); + }); }); app.on("window-all-closed", () => { diff --git a/desktop/permissions.mjs b/desktop/permissions.mjs new file mode 100644 index 0000000..4dc05ec --- /dev/null +++ b/desktop/permissions.mjs @@ -0,0 +1,39 @@ +const CLIPBOARD_WRITE_PERMISSION = "clipboard-sanitized-write"; + +function normalizedOrigin(value) { + try { + return new URL(value).origin; + } catch { + return null; + } +} + +export function isTrustedRuntimePermission({ webContents, requestingOrigin, runtimeUrl }) { + const expectedOrigin = normalizedOrigin(runtimeUrl); + if (!expectedOrigin) return false; + + const requestedOrigin = normalizedOrigin(requestingOrigin); + const pageOrigin = normalizedOrigin(webContents?.getURL?.()); + return requestedOrigin === expectedOrigin && (!pageOrigin || pageOrigin === expectedOrigin); +} + +export function installPermissionPolicy({ session, getRuntimeUrl }) { + const mayWriteClipboard = (webContents, permission, requestingOrigin) => ( + permission === CLIPBOARD_WRITE_PERMISSION + && isTrustedRuntimePermission({ + webContents, + requestingOrigin, + runtimeUrl: getRuntimeUrl(), + }) + ); + + session.setPermissionCheckHandler((webContents, permission, requestingOrigin) => ( + mayWriteClipboard(webContents, permission, requestingOrigin) + )); + session.setPermissionRequestHandler((webContents, permission, callback, details = {}) => { + const requestingOrigin = details.requestingOrigin + || details.requestingUrl + || webContents?.getURL?.(); + callback(mayWriteClipboard(webContents, permission, requestingOrigin)); + }); +} diff --git a/desktop/plugin-recovery.mjs b/desktop/plugin-recovery.mjs new file mode 100644 index 0000000..4d90801 --- /dev/null +++ b/desktop/plugin-recovery.mjs @@ -0,0 +1,177 @@ +import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises"; +import path from "node:path"; + +export const pendingPluginFileName = ".laobos-plugin-pending.json"; +export const pluginRecoveryFileName = ".laobos-plugin-recovery.json"; + +export function webProfileDirectory(dshHome) { + return path.join(dshHome, "profiles", "web"); +} + +export function pendingPluginPath(dshHome) { + return path.join(webProfileDirectory(dshHome), pendingPluginFileName); +} + +export function pluginRecoveryPath(dshHome) { + return path.join(webProfileDirectory(dshHome), pluginRecoveryFileName); +} + +function patchPath(dshHome) { + return path.join(webProfileDirectory(dshHome), "cordis.patch.yml"); +} + +async function readJsonIfPresent(filePath) { + try { + return JSON.parse(await readFile(filePath, "utf8")); + } catch (error) { + if (error?.code === "ENOENT" || error instanceof SyntaxError) return undefined; + throw error; + } +} + +async function writeFileAtomic(filePath, contents) { + await mkdir(path.dirname(filePath), { recursive: true, mode: 0o700 }); + const temporary = `${filePath}.tmp-${process.pid}-${Date.now()}`; + try { + await writeFile(temporary, contents, { encoding: "utf8", mode: 0o600 }); + await rename(temporary, filePath); + } catch (error) { + await rm(temporary, { force: true }); + throw error; + } +} + +function unquoteYamlScalar(value) { + const trimmed = value.trim(); + if ( + trimmed.length >= 2 + && ((trimmed.startsWith("'") && trimmed.endsWith("'")) + || (trimmed.startsWith('"') && trimmed.endsWith('"'))) + ) { + return trimmed.slice(1, -1); + } + return trimmed; +} + +/** + * Read the effective disabled flag for every entry touched by a profile patch. + * The profile market emits a deliberately small YAML subset, so preserving the + * original text is safer than parsing and serializing the whole file. + */ +export function profileEntryStates(patch) { + const lines = String(patch).split(/\r?\n/u); + const states = new Map(); + const inserted = new Set(); + + for (let index = 0; index < lines.length; index += 1) { + const match = /^(\s*)-\s+id:\s*([^#]+?)\s*$/u.exec(lines[index]); + if (!match) continue; + const indentation = match[1].length; + for (let cursor = index - 1; cursor >= 0; cursor -= 1) { + const line = lines[cursor]; + if (!line.trim() || line.trimStart().startsWith("#")) continue; + const leading = /^\s*/u.exec(line)?.[0].length ?? 0; + if (leading >= indentation) continue; + if (/^\s*-\s+insert:\s*$/u.test(line)) { + inserted.add(unquoteYamlScalar(match[2])); + } + break; + } + } + + for (let index = 0; index < lines.length; index += 1) { + const match = /^(\s*)-\s+id:\s*([^#]+?)\s*$/u.exec(lines[index]); + if (!match) continue; + const indentation = match[1].length; + const id = unquoteYamlScalar(match[2]); + if (!inserted.has(id)) continue; + let disabled; + + for (let cursor = index + 1; cursor < lines.length; cursor += 1) { + const line = lines[cursor]; + if (!line.trim() || line.trimStart().startsWith("#")) continue; + const leading = /^\s*/u.exec(line)?.[0].length ?? 0; + if (leading <= indentation && /^\s*-\s/u.test(line)) break; + const disabledMatch = /^\s*disabled:\s*(true|false)\s*(?:#.*)?$/iu.exec(line); + if (disabledMatch) disabled = disabledMatch[1].toLowerCase() === "true"; + } + + if (!states.has(id)) states.set(id, false); + if (disabled !== undefined) states.set(id, disabled); + } + + return states; +} + +export async function readPendingPlugin(dshHome) { + const pending = await readJsonIfPresent(pendingPluginPath(dshHome)); + if ( + pending?.schema !== 1 + || typeof pending.entryId !== "string" + || typeof pending.packageName !== "string" + ) return undefined; + return pending; +} + +export async function clearPendingPlugin(dshHome) { + await rm(pendingPluginPath(dshHome), { force: true }); +} + +/** + * Disable the pending market plugin, or every active user-profile plugin when + * no pending marker exists. The original patch is retained for manual or + * programmatic restoration. + */ +export async function quarantineUserPlugins(dshHome, reason) { + const profilePatchPath = patchPath(dshHome); + let originalPatch; + try { + originalPatch = await readFile(profilePatchPath, "utf8"); + } catch (error) { + if (error?.code === "ENOENT") return { changed: false, entryIds: [] }; + throw error; + } + + const states = profileEntryStates(originalPatch); + const pending = await readPendingPlugin(dshHome); + const requested = pending ? [pending.entryId] : [...states.keys()]; + const entryIds = [...new Set(requested)].filter((id) => states.get(id) !== true); + if (entryIds.length === 0) return { changed: false, entryIds: [], pending }; + + const recovery = { + schema: 1, + createdAt: new Date().toISOString(), + reason: String(reason || "plugin startup failure"), + entryIds, + pending, + originalPatch, + }; + await writeFileAtomic( + pluginRecoveryPath(dshHome), + `${JSON.stringify(recovery, null, 2)}\n`, + ); + + const suffix = [ + "", + "# 劳博士安全模式:以下用户插件因启动失败而自动停用。", + ...entryIds.flatMap((id) => [ + `- id: '${id.replaceAll("'", "''")}'`, + " disabled: true", + ]), + "", + ].join("\n"); + await writeFileAtomic(profilePatchPath, `${originalPatch.replace(/\s*$/u, "")}\n${suffix}`); + await clearPendingPlugin(dshHome); + return { changed: true, entryIds, pending, recoveryPath: pluginRecoveryPath(dshHome) }; +} + +export async function restoreLastPluginRecovery(dshHome) { + const recoveryFile = pluginRecoveryPath(dshHome); + const recovery = await readJsonIfPresent(recoveryFile); + if (recovery?.schema !== 1 || typeof recovery.originalPatch !== "string") { + return false; + } + await writeFileAtomic(patchPath(dshHome), recovery.originalPatch); + await rm(recoveryFile, { force: true }); + return true; +} diff --git a/desktop/preload.cjs b/desktop/preload.cjs index 858a44c..cc25c7b 100644 --- a/desktop/preload.cjs +++ b/desktop/preload.cjs @@ -6,7 +6,7 @@ const invoke = (channel, input) => ipcRenderer.invoke(channel, input); contextBridge.exposeInMainWorld("laobosDesktop", Object.freeze({ version: 1, capabilities: Object.freeze({ - conversationPdf: true, + conversationHtml: true, sessionTrash: true, workspaceFiles: true, gitReview: true, @@ -17,10 +17,28 @@ contextBridge.exposeInMainWorld("laobosDesktop", Object.freeze({ browserOps: true, ssh: true, apps: true, + clipboard: true, shellManager: true, + softwareUpdate: true, }), - pdf: Object.freeze({ - exportConversation: (input) => invoke("laobos:pdf:export-conversation", input), + clipboard: Object.freeze({ + writeText: (text) => invoke("laobos:clipboard:write-text", { text }), + }), + updates: Object.freeze({ + status: () => invoke("laobos:updates:status"), + preferences: () => invoke("laobos:updates:preferences"), + setPreferences: (input) => invoke("laobos:updates:set-preferences", input), + check: () => invoke("laobos:updates:check"), + download: () => invoke("laobos:updates:download"), + install: () => invoke("laobos:updates:install"), + onState: (listener) => { + const wrapped = (_event, payload) => listener(payload); + ipcRenderer.on("laobos:updates:state", wrapped); + return () => ipcRenderer.removeListener("laobos:updates:state", wrapped); + }, + }), + html: Object.freeze({ + exportConversation: (input) => invoke("laobos:html:export-conversation", input), }), sessions: Object.freeze({ trash: (input) => invoke("laobos:sessions:trash", input), @@ -29,6 +47,9 @@ contextBridge.exposeInMainWorld("laobosDesktop", Object.freeze({ context: () => invoke("laobos:workspace:context"), list: (input) => invoke("laobos:workspace:list", input), read: (input) => invoke("laobos:workspace:read", input), + write: (input) => invoke("laobos:workspace:write", input), + rename: (input) => invoke("laobos:workspace:rename", input), + remove: (input) => invoke("laobos:workspace:remove", input), reveal: (input) => invoke("laobos:workspace:reveal", input), }), git: Object.freeze({ diff --git a/desktop/register-desktop-domains.mjs b/desktop/register-desktop-domains.mjs index 7d6ee7c..32345c5 100644 --- a/desktop/register-desktop-domains.mjs +++ b/desktop/register-desktop-domains.mjs @@ -1,5 +1,6 @@ import { registerConversationExportIpc } from "./domains/conversation-export.mjs"; import { registerBrowserIpc } from "./domains/browser.mjs"; +import { registerClipboardIpc } from "./domains/clipboard.mjs"; import { registerAppsIpc } from "./domains/apps.mjs"; import { DesktopSettingsStore } from "./domains/desktop-settings.mjs"; import { registerGitReviewIpc } from "./domains/git-review.mjs"; @@ -7,8 +8,10 @@ import { registerSessionTrashIpc } from "./domains/session-trash.mjs"; import { registerShellIpc } from "./domains/shell.mjs"; import { registerSshIpc } from "./domains/ssh.mjs"; import { registerTerminalIpc } from "./domains/terminal.mjs"; +import { registerUpdaterIpc } from "./domains/updater.mjs"; import { registerWorkspaceFilesIpc } from "./domains/workspace-files.mjs"; import { assertTrustedDesktopSender } from "./ipc-security.mjs"; +import { WorkspaceAuthorization } from "./workspace-authorization.mjs"; import path from "node:path"; export function registerDesktopDomains(options) { @@ -16,16 +19,25 @@ export function registerDesktopDomains(options) { const settings = new DesktopSettingsStore( path.join(options.app.getPath("userData"), "desktop-settings.json"), ); + const workspaceAuthorizer = new WorkspaceAuthorization({ + defaultRoot: options.workspace, + settings, + dialog: options.dialog, + getMainWindow: options.getMainWindow, + }); + const domainOptions = { ...options, authorize, settings, workspaceAuthorizer }; const disposers = [ - registerAppsIpc({ ...options, authorize }), - registerBrowserIpc({ ...options, authorize }), - registerConversationExportIpc({ ...options, authorize }), - registerSessionTrashIpc({ ...options, authorize }), - registerWorkspaceFilesIpc({ ...options, authorize, settings }), - registerGitReviewIpc({ ...options, authorize }), - registerShellIpc({ ...options, authorize }), - registerTerminalIpc({ ...options, authorize }), - registerSshIpc({ ...options, authorize }), + registerClipboardIpc(domainOptions), + registerAppsIpc(domainOptions), + registerBrowserIpc(domainOptions), + registerConversationExportIpc(domainOptions), + registerSessionTrashIpc(domainOptions), + registerWorkspaceFilesIpc(domainOptions), + registerGitReviewIpc(domainOptions), + registerShellIpc(domainOptions), + registerTerminalIpc(domainOptions), + registerSshIpc(domainOptions), + registerUpdaterIpc(domainOptions), ]; return () => { for (const dispose of disposers.reverse()) dispose(); diff --git a/desktop/workspace-authorization.mjs b/desktop/workspace-authorization.mjs new file mode 100644 index 0000000..39c5bdc --- /dev/null +++ b/desktop/workspace-authorization.mjs @@ -0,0 +1,122 @@ +import { realpath, stat } from "node:fs/promises"; +import path from "node:path"; +import { boundedString, isPathInside } from "./ipc-security.mjs"; + +const MAX_AUTHORIZED_WORKSPACES = 64; + +/** + * Desktop tools run in Electron's main process and therefore need a boundary + * independent from the renderer. The startup workspace is trusted immediately; + * a DSH session outside it receives one native, persistent approval instead of + * being rejected merely because it lives on another Windows drive. + */ +export class WorkspaceAuthorization { + constructor({ defaultRoot, settings, dialog, getMainWindow }) { + this.defaultRoot = defaultRoot; + this.settings = settings; + this.dialog = dialog; + this.getMainWindow = getMainWindow; + this.pending = new Map(); + } + + async roots() { + const initial = await canonicalDirectory(this.defaultRoot); + const saved = (await this.settings.get()).authorizedWorkspaces || []; + const roots = [initial]; + for (const entry of saved) { + try { + const canonical = await canonicalDirectory(entry); + if (!roots.some((root) => samePath(root, canonical))) roots.push(canonical); + } catch { + // A removed or temporarily unavailable drive must not break the app. + } + } + return roots; + } + + async resolve(requested, { label = "工作区", prompt = true } = {}) { + const value = requested + ? boundedString(requested, `${label}路径`, 4096) + : this.defaultRoot; + const absolute = path.isAbsolute(value) + ? value + : path.resolve(this.defaultRoot, value); + const candidate = await canonicalDirectory(absolute); + const roots = await this.roots(); + if (roots.some((root) => isPathInside(root, candidate))) return candidate; + if (!prompt) throw unauthorizedWorkspaceError(candidate); + return this.approve(candidate, label); + } + + async approve(candidate, label) { + const key = normalizeForComparison(candidate); + if (this.pending.has(key)) return this.pending.get(key); + const approval = this.requestApproval(candidate, label).finally(() => { + this.pending.delete(key); + }); + this.pending.set(key, approval); + return approval; + } + + async requestApproval(candidate, label) { + const options = { + type: "question", + title: "授权工作区", + message: `是否允许劳博士访问这个${label}?`, + detail: `${candidate}\n\n授权仅覆盖该目录及其子目录,可让终端、文件、Git 和应用管理功能在普通用户模式下工作。`, + buttons: ["允许访问", "取消"], + defaultId: 0, + cancelId: 1, + noLink: true, + }; + const owner = this.getMainWindow?.(); + const result = owner && !owner.isDestroyed() + ? await this.dialog.showMessageBox(owner, options) + : await this.dialog.showMessageBox(options); + if (result.response !== 0) throw unauthorizedWorkspaceError(candidate); + + const current = await this.settings.get(); + const saved = current.authorizedWorkspaces || []; + const next = [...saved.filter((root) => !samePath(root, candidate)), candidate] + .slice(-MAX_AUTHORIZED_WORKSPACES); + await this.settings.update({ authorizedWorkspaces: next }); + return candidate; + } +} + +export async function resolveWorkspaceDirectory({ + authorizer, + defaultRoot, + requested, + label, +}) { + if (authorizer) return authorizer.resolve(requested, { label }); + const value = requested || defaultRoot; + const candidate = path.isAbsolute(value) + ? value + : path.resolve(defaultRoot, value); + const canonicalRoot = await canonicalDirectory(defaultRoot); + const canonical = await canonicalDirectory(candidate); + if (!isPathInside(canonicalRoot, canonical)) throw unauthorizedWorkspaceError(canonical); + return canonical; +} + +async function canonicalDirectory(value) { + const canonical = await realpath(path.resolve(value)); + const info = await stat(canonical); + if (!info.isDirectory()) throw new Error("目标工作区不是目录。 "); + return canonical; +} + +function unauthorizedWorkspaceError(candidate) { + return new Error(`工作区尚未授权:${candidate}。请在授权提示中选择“允许访问”。`); +} + +function samePath(left, right) { + return normalizeForComparison(left) === normalizeForComparison(right); +} + +function normalizeForComparison(value) { + const normalized = path.resolve(value); + return process.platform === "win32" ? normalized.toLowerCase() : normalized; +} diff --git a/electron-builder.test-update.yml b/electron-builder.test-update.yml new file mode 100644 index 0000000..f53c970 --- /dev/null +++ b/electron-builder.test-update.yml @@ -0,0 +1,9 @@ +extends: ./electron-builder.yml +afterSign: ./scripts/sign-test-update.mjs + +# Only for a controlled macOS auto-update test chain. This signs the complete +# application bundle ad-hoc so Squirrel can validate sealed resources. It is not +# a substitute for Developer ID signing or Apple notarization. +mac: + identity: "-" + hardenedRuntime: false diff --git a/electron-builder.yml b/electron-builder.yml index 97644b9..ae72048 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -5,6 +5,14 @@ asarUnpack: - "packages/**" compression: normal npmRebuild: false +electronUpdaterCompatibility: ">=2.16" +beforePack: ./scripts/stage-windows-git.mjs + +publish: + provider: github + owner: Modole + repo: laobos-agent-studio + releaseType: release directories: output: out/installers @@ -16,6 +24,7 @@ files: - "!dist{,/**}" - "!dist-desktop{,/**}" - "!outputs{,/**}" + - "!.cache{,/**}" - "!tests{,/**}" - "!.dsh{,/**}" - "!.git{,/**}" @@ -24,6 +33,7 @@ files: - "!.vinext{,/**}" - "!.wrangler{,/**}" - "!resources/pi{,/**}" + - "!resources/mingit-win32-x64{,/**}" - "!node_modules/cpu-features{,/**}" - "!node_modules/node-pty/build{,/**}" - "!node_modules/ssh2/lib/protocol/crypto/build{,/**}" @@ -31,23 +41,31 @@ files: mac: icon: build/laobos-icon.icns category: public.app-category.developer-tools - identity: null - hardenedRuntime: false + hardenedRuntime: true target: - target: dmg arch: - arm64 + - target: zip + arch: + - arm64 artifactName: "laobos-studio-${version}-macos-${arch}.${ext}" win: icon: public/laobos-logo.png executableName: laobos-studio + extraResources: + - from: resources/mingit-win32-x64 + to: git + filter: + - "**/*" files: - "**/*" - "!out{,/**}" - "!dist{,/**}" - "!dist-desktop{,/**}" - "!outputs{,/**}" + - "!.cache{,/**}" - "!tests{,/**}" - "!.dsh{,/**}" - "!.git{,/**}" @@ -56,6 +74,7 @@ win: - "!.vinext{,/**}" - "!.wrangler{,/**}" - "!resources/pi{,/**}" + - "!resources/mingit-win32-x64{,/**}" - "!node_modules/cpu-features{,/**}" - "!node_modules/node-pty/build{,/**}" - "!node_modules/ssh2/lib/protocol/crypto/build{,/**}" diff --git a/package-lock.json b/package-lock.json index fb760be..ac10220 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,46 +1,48 @@ { "name": "laobos-agent-studio", - "version": "0.2.3", + "version": "0.3.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "laobos-agent-studio", - "version": "0.2.3", + "version": "0.3.10", "hasInstallScript": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { "@browserops/bridge": "^0.0.11", "@deepseek-ai/cordis-plugin-group": "1.0.1", - "@deepseek-ai/dsh": "0.1.0-rc.6", - "@deepseek-ai/dsh-anonymous-user-id": "0.1.0-rc.6", - "@deepseek-ai/dsh-atomic-write": "0.1.0-rc.6", - "@deepseek-ai/dsh-bash-local": "0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-directory-picker-browse": "0.1.0-rc.6", - "@deepseek-ai/dsh-code-runtime": "0.1.0-rc.6", - "@deepseek-ai/dsh-compaction": "0.1.0-rc.6", - "@deepseek-ai/dsh-fs": "0.1.0-rc.6", - "@deepseek-ai/dsh-host-directory-picker-browse": "0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "0.1.0-rc.6", - "@deepseek-ai/dsh-output-retention": "0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "0.1.0-rc.6", - "@deepseek-ai/dsh-session-telemetry": "0.1.0-rc.6", - "@deepseek-ai/dsh-session-title-llm": "0.1.0-rc.6", - "@deepseek-ai/dsh-shell": "0.1.0-rc.6", - "@deepseek-ai/dsh-spill": "0.1.0-rc.6", - "@deepseek-ai/dsh-subagent-in-process-driver": "0.1.0-rc.6", - "@deepseek-ai/dsh-subprocess": "0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "0.1.0-rc.6", - "@deepseek-ai/dsh-workflow": "0.1.0-rc.6", + "@deepseek-ai/dsh": "0.1.0-rc.7", + "@deepseek-ai/dsh-anonymous-user-id": "0.1.0-rc.7", + "@deepseek-ai/dsh-atomic-write": "0.1.0-rc.7", + "@deepseek-ai/dsh-bash-local": "0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-directory-picker-browse": "0.1.0-rc.7", + "@deepseek-ai/dsh-code-runtime": "0.1.0-rc.7", + "@deepseek-ai/dsh-compaction": "0.1.0-rc.7", + "@deepseek-ai/dsh-fs": "0.1.0-rc.7", + "@deepseek-ai/dsh-host-directory-picker-browse": "0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "0.1.0-rc.7", + "@deepseek-ai/dsh-output-retention": "0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "0.1.0-rc.7", + "@deepseek-ai/dsh-session-telemetry": "0.1.0-rc.7", + "@deepseek-ai/dsh-session-title-llm": "0.1.0-rc.7", + "@deepseek-ai/dsh-shell": "0.1.0-rc.7", + "@deepseek-ai/dsh-spill": "0.1.0-rc.7", + "@deepseek-ai/dsh-subagent-in-process-driver": "0.1.0-rc.7", + "@deepseek-ai/dsh-subprocess": "0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "0.1.0-rc.7", + "@deepseek-ai/dsh-workflow": "0.1.0-rc.7", "@laobos/dsh-performance": "file:packages/laobos-performance", "@laobos/dsh-shell": "file:packages/laobos-shell", "@laobos/dsh-system-tools": "file:packages/laobos-system-tools", "@xterm/addon-fit": "^0.11.0", "@xterm/xterm": "^6.0.0", "@xyflow/react": "12.11.3", + "electron-updater": "^6.8.9", "next": "16.2.11", - "node-pty": "^1.1.0", + "node-pty": "1.2.0-beta.15", + "patch-package": "8.0.1", "react": "19.2.6", "react-dom": "19.2.6", "ssh2": "^1.17.0", @@ -66,7 +68,8 @@ "typescript": "5.9.3", "vinext": "0.0.50", "vite": "8.0.13", - "wrangler": "4.92.0" + "wrangler": "4.92.0", + "yauzl": "3.4.0" }, "engines": { "node": ">=22.19.0" @@ -180,13 +183,13 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.977.7", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.977.7.tgz", - "integrity": "sha512-I88Iov89NVmjSmJLKSv7Cn9M2J+a2942OkA8nZCbz+sl4ZeY4zEOcoLOrbt1GRfQ8zEQKnjAJdXixA3J/p1fDQ==", + "version": "3.977.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.977.8.tgz", + "integrity": "sha512-7+Kcrkvrk9lM/m7jRhHpT4jCdvzGHsuaSRbF8TdzzkY1mRzp/Ogwf9c7H29k4gGhey0BBWhCWr16+t0J61gwmg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.974.3", - "@aws-sdk/xml-builder": "^3.972.38", + "@aws-sdk/types": "^3.974.4", + "@aws-sdk/xml-builder": "^3.972.39", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.31.1", "@smithy/signature-v4": "^5.6.12", @@ -199,13 +202,13 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.68", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.68.tgz", - "integrity": "sha512-2a20A/IdNOwUvaDq91iqqS7BA0XlNMfW3iLGZGZLJv0EbUqhSxB0PIx4rQQqssvWj1uXImb3/UCCdHz/+1dOiA==", + "version": "3.972.69", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.69.tgz", + "integrity": "sha512-AreCFzcB4kH2HF9031Ot0jSJr3KXvRg6e8uDeub20JEVdZU3Bv0sTq1plc7VsT3KiqutlzH7l0j50UcCWHUioA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.977.7", - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/core": "^3.977.8", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" @@ -215,13 +218,13 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.70", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.70.tgz", - "integrity": "sha512-0yRem2Fs52r/Nn6UAqIlpjexfaYj8ziEozOe9tamtAVT/5bzFLKx8O2r7MaRqgS3hGKHIa1Jij9nKHSsNnb04A==", + "version": "3.972.71", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.71.tgz", + "integrity": "sha512-A8ObcqVmDMnk4F9NozZ7JwmUu9Q4xyBJkmyq1C5U+wNM9ht9J7+EuuyabsLWXZnOoTqFaJuYBYTKf5CTipkEjA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.977.7", - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/core": "^3.977.8", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/fetch-http-handler": "^5.6.13", "@smithy/node-http-handler": "^4.9.13", @@ -233,13 +236,13 @@ } }, "node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.11.0.tgz", - "integrity": "sha512-ssHIZsadPUA3lGdnoByxfnjtb9xPYQLvdfJRLKIwxOoa6tO1suG4sLFSsgd7D/CsvYd8QbBIuKTImuJha5l6aQ==", + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.11.2.tgz", + "integrity": "sha512-avwAh9HM3h2lcfjvP3zYIZGf+XVgLQ91wOJ2qoFbNpW1UZeZb33aGlhTZvtkANHfcGhJroRY64525OjfgOg30g==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.33.0", - "@smithy/types": "^4.17.0", + "@smithy/core": "^3.33.2", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -247,20 +250,20 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.973.13", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.13.tgz", - "integrity": "sha512-2M39DE02XpYYaSWYk/4AsImXYUU/1L2xmTMLUpMMWq7DfLv191/vCRy3baKtdr45AkJQyVgSjmuVOLm15SwrRQ==", + "version": "3.973.14", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.14.tgz", + "integrity": "sha512-7c+Wti2LsERNWMfm7ySz3/6RPopFW3Nmn7s63Xpcq6R/tRuY5hpvkHA2xVgi5ukJbvok9l0IDtVEvqTtg+X7dw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.977.7", - "@aws-sdk/credential-provider-env": "^3.972.68", - "@aws-sdk/credential-provider-http": "^3.972.70", - "@aws-sdk/credential-provider-login": "^3.972.75", - "@aws-sdk/credential-provider-process": "^3.972.68", - "@aws-sdk/credential-provider-sso": "^3.973.12", - "@aws-sdk/credential-provider-web-identity": "^3.972.74", - "@aws-sdk/nested-clients": "^3.997.42", - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/core": "^3.977.8", + "@aws-sdk/credential-provider-env": "^3.972.69", + "@aws-sdk/credential-provider-http": "^3.972.71", + "@aws-sdk/credential-provider-login": "^3.972.76", + "@aws-sdk/credential-provider-process": "^3.972.69", + "@aws-sdk/credential-provider-sso": "^3.973.13", + "@aws-sdk/credential-provider-web-identity": "^3.972.75", + "@aws-sdk/nested-clients": "^3.997.43", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/credential-provider-imds": "^4.4.16", "@smithy/types": "^4.16.1", @@ -271,14 +274,14 @@ } }, "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.75", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.75.tgz", - "integrity": "sha512-jaTESuJlQsoUZ44f/i2puyPt8VlF/dMMJ9HM3cStYtk7eKX4N9UWi83OLixUkoOJH3BwWlPLCq9YIK9nfWhVBg==", + "version": "3.972.76", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.76.tgz", + "integrity": "sha512-LVixwOnEJfrrfKHeZjBA8pIMTZjNDq8ak8VpcoWUuCJDrSnBNU8POJksULMgvN089P0MXtQYH2Zs627/MK1K0g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.977.7", - "@aws-sdk/nested-clients": "^3.997.42", - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/core": "^3.977.8", + "@aws-sdk/nested-clients": "^3.997.43", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" @@ -288,18 +291,18 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.79", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.79.tgz", - "integrity": "sha512-RIw5dof1EHkWubrZzPC941CDtnFG1iAXsxbFgLkhdYZXHc4icU13c/uxSMI0J5eUx9bxa7LjfpdjfClBB1QsDA==", + "version": "3.972.80", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.80.tgz", + "integrity": "sha512-bE2qh8ww4iClO1jHsBXdOE8FUgzDbdxbyorNjSCoPSkQd51k3jODItuPZfuwcLHZqDXsH+bI4AMHhqtuyR7mSg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.68", - "@aws-sdk/credential-provider-http": "^3.972.70", - "@aws-sdk/credential-provider-ini": "^3.973.13", - "@aws-sdk/credential-provider-process": "^3.972.68", - "@aws-sdk/credential-provider-sso": "^3.973.12", - "@aws-sdk/credential-provider-web-identity": "^3.972.74", - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/credential-provider-env": "^3.972.69", + "@aws-sdk/credential-provider-http": "^3.972.71", + "@aws-sdk/credential-provider-ini": "^3.973.14", + "@aws-sdk/credential-provider-process": "^3.972.69", + "@aws-sdk/credential-provider-sso": "^3.973.13", + "@aws-sdk/credential-provider-web-identity": "^3.972.75", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/credential-provider-imds": "^4.4.16", "@smithy/types": "^4.16.1", @@ -310,13 +313,13 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.68", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.68.tgz", - "integrity": "sha512-nLP3Pda2MQTFJ25hKBMmUuB9Uv+bTZQNlufbeCwklP549Vwnkd8bRLJoCKp5k6xjmdyptrPrOfGOhN0mKuca8A==", + "version": "3.972.69", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.69.tgz", + "integrity": "sha512-9kpTNdZTrcqXTfhxM7fgl9Z68ek3Fu5oe3Yf+A/pJGibEqpgZxz2tSY7SinmyCIU2PJ+ygY4FPoBBnLpocMtrQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.977.7", - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/core": "^3.977.8", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" @@ -326,15 +329,15 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.973.12", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.12.tgz", - "integrity": "sha512-EmgyyHn+f9WCcelp3L/vci+LGbX8GigWaVphRArjVo5Pktkr9YnLy/mQ6VDkDyBD72dtfRNTgHmD2ts4rTDXKQ==", + "version": "3.973.13", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.13.tgz", + "integrity": "sha512-Oc81qauMPzUoTnAS2YKpNwY6sY/LUyQTEeaf6yP197WMxkEBQfcKLR1MFpD7+pNTubXnfkH6gwpji+Gc7iyD2Q==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.977.7", - "@aws-sdk/nested-clients": "^3.997.42", - "@aws-sdk/token-providers": "3.1108.0", - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/core": "^3.977.8", + "@aws-sdk/nested-clients": "^3.997.43", + "@aws-sdk/token-providers": "3.1111.0", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" @@ -344,14 +347,14 @@ } }, "node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers": { - "version": "3.1108.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1108.0.tgz", - "integrity": "sha512-rI80zxDxGJ6904eC/YbjkdjY6JdaZvQ01kOmrMvw7cFQGIHo27fhnIVbMSVDS4T6foQImjxYSRoOu/uSJscXDw==", + "version": "3.1111.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1111.0.tgz", + "integrity": "sha512-JfljgoVtl+s3Qy21n9a7Z48uCQaOXcN74KJ3TEQfPoB293GrXFSt6HSQJF1sTZ8c/5QedEvd3NjJQMO4u9qa5A==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.977.7", - "@aws-sdk/nested-clients": "^3.997.42", - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/core": "^3.977.8", + "@aws-sdk/nested-clients": "^3.997.43", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" @@ -361,14 +364,14 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.74", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.74.tgz", - "integrity": "sha512-0YfczxGXF3RjGj8z7QG/Ho2HnLGKDHfPSHiTs47UU1U/+mmwISDN+rvGKt2zh+3FX8NdT4xd95LGBGyhQw2dgQ==", + "version": "3.972.75", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.75.tgz", + "integrity": "sha512-YPN6uoGDgjjjeVFZrcOeCJqmB6zpXoeeNgIjqe+DexJaWqdjVfCCe+VAZwli9Z2h8KhFW8oxkO39emQ1tyz/Mw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.977.7", - "@aws-sdk/nested-clients": "^3.997.42", - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/core": "^3.977.8", + "@aws-sdk/nested-clients": "^3.997.43", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" @@ -378,12 +381,12 @@ } }, "node_modules/@aws-sdk/eventstream-handler-node": { - "version": "3.972.32", - "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.972.32.tgz", - "integrity": "sha512-rlbmsMG7ZNgrVhWSqqXpq6y9hfiREyzCg3CNTk9UK+AoP7+65kOkqpWmqwLfV1UrRSHATdLnZF2rt9ZTUxYQJA==", + "version": "3.972.33", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.972.33.tgz", + "integrity": "sha512-1Dd5WyEE2Kb3HvY44u7Ob16ST2W6iutOqsQ8Y2hUmsL2mAH/STlGS1dS9h3IOE6L7Ld3AR2HzKJ6XeCMOw8Peg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" @@ -393,12 +396,12 @@ } }, "node_modules/@aws-sdk/middleware-eventstream": { - "version": "3.972.27", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.972.27.tgz", - "integrity": "sha512-M7Ay1VpBpf/YFfic9kkjwE3wyCh4G0gEM4RypRXYm7aPjyfqi+D8FEYMR2E3IqbvN+qi2rEFYAiwWL0XHtQYdQ==", + "version": "3.972.28", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.972.28.tgz", + "integrity": "sha512-Z1EDXnS01P7H5jVrUx+/dBqV0m7dta7bSxLclkOuDuS93pNNQm0IcT4YLUbuvWKPYNxbI8aTG0p5Br30GSKDgA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" @@ -408,13 +411,13 @@ } }, "node_modules/@aws-sdk/middleware-websocket": { - "version": "3.972.50", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.50.tgz", - "integrity": "sha512-gdcWRbmIf1dWA/prf44Bnnzgqj+AbsXX2yfhZhOQLwSm7NfKIYPmkRlPqP0CTepHzjxMIBdWBDdtQB+Y/dFUeg==", + "version": "3.972.51", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.51.tgz", + "integrity": "sha512-jdgP3jR5Q96j1jjZ98GGwpGg1CBNFIO2YE+vXg8cg8PvNY4NvgQNYJsqDaRX2PYv5gSUX/+C0D58Fhspj9ELMQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.977.7", - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/core": "^3.977.8", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/fetch-http-handler": "^5.6.13", "@smithy/signature-v4": "^5.6.12", @@ -426,14 +429,14 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.997.42", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.42.tgz", - "integrity": "sha512-XWRyon2MTHXD/zMoo0Mbge6Vwf+iE0qQaM/RyGO6NfZ9WukCFiQL27nQVZjYy2JwSIg+iXZxKOX95OBXqlSM4w==", + "version": "3.997.43", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.43.tgz", + "integrity": "sha512-bit+VpqWNyi3wHxFoTsTliNXimCSL2r2OeDTm7ZrG+YsTZ2D7ofDJ6r/t9PVBn80i6/v0X2h9Tgw6QP2MAKfPw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.977.7", - "@aws-sdk/signature-v4-multi-region": "^3.996.44", - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/core": "^3.977.8", + "@aws-sdk/signature-v4-multi-region": "^3.996.45", + "@aws-sdk/types": "^3.974.4", "@smithy/core": "^3.31.1", "@smithy/fetch-http-handler": "^5.6.13", "@smithy/node-http-handler": "^4.9.13", @@ -445,13 +448,13 @@ } }, "node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.11.0.tgz", - "integrity": "sha512-ssHIZsadPUA3lGdnoByxfnjtb9xPYQLvdfJRLKIwxOoa6tO1suG4sLFSsgd7D/CsvYd8QbBIuKTImuJha5l6aQ==", + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.11.2.tgz", + "integrity": "sha512-avwAh9HM3h2lcfjvP3zYIZGf+XVgLQ91wOJ2qoFbNpW1UZeZb33aGlhTZvtkANHfcGhJroRY64525OjfgOg30g==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.33.0", - "@smithy/types": "^4.17.0", + "@smithy/core": "^3.33.2", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -459,12 +462,12 @@ } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.996.44", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.44.tgz", - "integrity": "sha512-ZSfQ35Qn4MhSY+A0Whyr+KBx+wJKZUyBsOrjB2pSHOafRzbFe47T8XcXM8hZqUAC69qnqIy0C9ArxTuud0CC2w==", + "version": "3.996.45", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.45.tgz", + "integrity": "sha512-bBuyztukzXq6plzFGHAWiQt0QXo+HL8b8lX5cFTzkez/74PtS1c0qPFCIVuHkyoT+miH2qOjAcm1/yoro2ESPA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.974.3", + "@aws-sdk/types": "^3.974.4", "@smithy/signature-v4": "^5.6.12", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" @@ -491,9 +494,9 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.974.3", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.3.tgz", - "integrity": "sha512-ECAqfpNsef+7MO8qtR0h9KcFIBAygaE7Cm6UOiQl+ft+uVap+1G7bNEjs4mdJE2OnA4m6k7i8peH8uGIAsOMGw==", + "version": "3.974.4", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.4.tgz", + "integrity": "sha512-dSFDNG00MEz0/xl5gxL62giLd1iYyJsTxZ1I1DOj6lC+bbgLB4TRsYClJg3b62dhXT1uATzsTNXPnC+33EJV3A==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.16.1", @@ -504,9 +507,9 @@ } }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.965.9", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.9.tgz", - "integrity": "sha512-wB/ho7pTJKqWz3WYDt2ZWDWI8bxQpN/xwf+5ZQ1zWaj+HDY9B8Fn434i6qZ6j6ZG3aCiIJtZaQVqwajx5xYsQA==", + "version": "3.965.10", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.10.tgz", + "integrity": "sha512-ycwH6Zd2GhuSqdXX9ihbCjeGTB6xOJs+O3+Jb8/zDG9978XU80qs75dfkPJRMNKe5MvBZPuNeFpd4JZKPoUF4g==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -516,9 +519,9 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.972.38", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.38.tgz", - "integrity": "sha512-grf7mzfVxBS5AlsuTvBN7uDpzqohFww9fRPCO+EBSUdvtsYMcPSKdz54h/7XiscqNcUM1Ae1MF7JLHmiYYuzbQ==", + "version": "3.972.39", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.39.tgz", + "integrity": "sha512-FTti8DS5MMWXNUWiRwXAJeYS+0GHHiMy0+7XOhcwk63ILHmfS2UFy2z/HNpZCSOJJ3P3dnWY6hfYNW3DF0nXUA==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.16.1", @@ -1108,9 +1111,9 @@ "license": "MIT" }, "node_modules/@deepseek-ai/dsh": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh/-/dsh-0.1.0-rc.6.tgz", - "integrity": "sha512-brpZfED7ieRa2PQ5tUxMhHrM1pb2CmKFVM/f6yMULBDMicahk+Z2OsHgTwTDnoiZm23Ftu9rQz0NN4pflaoJcg==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh/-/dsh-0.1.0-rc.7.tgz", + "integrity": "sha512-ZceDCJ8FAywih+USW/OMk9jEhunlvJBGEz4kqrhau23hPzbciOazZrywH0nBRsaalSeAJ1JGBmjtw4OSjToStw==", "license": "MIT", "dependencies": { "@deepseek-ai/cordis": "^4.0.1", @@ -1118,59 +1121,59 @@ "@deepseek-ai/cordis-plugin-include": "^1.0.6", "@deepseek-ai/cordis-plugin-loader": "^1.0.2", "@deepseek-ai/cordis-plugin-timer": "^1.1.3", - "@deepseek-ai/dsh-agent-instructions": "^0.1.0-rc.6", - "@deepseek-ai/dsh-agent-tool-presentation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-app-boot": "^0.1.0-rc.6", - "@deepseek-ai/dsh-base": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-agent-preset": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-cordis": "^0.1.0-rc.6", - "@deepseek-ai/dsh-cmdline": "^0.1.0-rc.6", - "@deepseek-ai/dsh-command-compact": "^0.1.0-rc.6", - "@deepseek-ai/dsh-command-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-compaction-basic": "^0.1.0-rc.6", - "@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.0-rc.6", - "@deepseek-ai/dsh-cordis-client-runner": "^0.1.0-rc.6", - "@deepseek-ai/dsh-fs-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-goal-round-driver": "^0.1.0-rc.6", - "@deepseek-ai/dsh-headless": "^0.1.0-rc.6", - "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6", - "@deepseek-ai/dsh-jobs-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-mcp-client": "^0.1.0-rc.6", - "@deepseek-ai/dsh-persona": "^0.1.0-rc.6", - "@deepseek-ai/dsh-plan-mode": "^0.1.0-rc.6", - "@deepseek-ai/dsh-pwsh-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-pwsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-schedule": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-reference": "^0.1.0-rc.6", - "@deepseek-ai/dsh-skill": "^0.1.0-rc.6", - "@deepseek-ai/dsh-skill-filesystem": "^0.1.0-rc.6", - "@deepseek-ai/dsh-terminal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-terminal-bash": "^0.1.0-rc.6", - "@deepseek-ai/dsh-time-context": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tmux-context": "^0.1.0-rc.6", - "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-ask-user": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-bash": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-bash-persistent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-cordis": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-fs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-fs-search": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-jobs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-pwsh": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-ralph": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-skill": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-str-replace-editor": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-subagent-control": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-todo": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-web": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-workflow": "^0.1.0-rc.6", - "@deepseek-ai/dsh-web-app": "^0.1.0-rc.6", - "@deepseek-ai/dsh-workflow-worker-thread": "^0.1.0-rc.6", + "@deepseek-ai/dsh-agent-instructions": "^0.1.0-rc.7", + "@deepseek-ai/dsh-agent-tool-presentation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-app-boot": "^0.1.0-rc.7", + "@deepseek-ai/dsh-base": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-agent-preset": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-cordis": "^0.1.0-rc.7", + "@deepseek-ai/dsh-cmdline": "^0.1.0-rc.7", + "@deepseek-ai/dsh-command-compact": "^0.1.0-rc.7", + "@deepseek-ai/dsh-command-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-compaction-basic": "^0.1.0-rc.7", + "@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.0-rc.7", + "@deepseek-ai/dsh-cordis-client-runner": "^0.1.0-rc.7", + "@deepseek-ai/dsh-fs-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-goal-round-driver": "^0.1.0-rc.7", + "@deepseek-ai/dsh-headless": "^0.1.0-rc.7", + "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.7", + "@deepseek-ai/dsh-jobs-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-mcp-client": "^0.1.0-rc.7", + "@deepseek-ai/dsh-persona": "^0.1.0-rc.7", + "@deepseek-ai/dsh-plan-mode": "^0.1.0-rc.7", + "@deepseek-ai/dsh-pwsh-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-pwsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-schedule": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-reference": "^0.1.0-rc.7", + "@deepseek-ai/dsh-skill": "^0.1.0-rc.7", + "@deepseek-ai/dsh-skill-filesystem": "^0.1.0-rc.7", + "@deepseek-ai/dsh-terminal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-terminal-bash": "^0.1.0-rc.7", + "@deepseek-ai/dsh-time-context": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tmux-context": "^0.1.0-rc.7", + "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-ask-user": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-bash": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-bash-persistent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-cordis": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-fs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-fs-search": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-jobs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-pwsh": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-ralph": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-skill": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-str-replace-editor": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-subagent-control": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-todo": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-web": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-workflow": "^0.1.0-rc.7", + "@deepseek-ai/dsh-web-app": "^0.1.0-rc.7", + "@deepseek-ai/dsh-workflow-worker-thread": "^0.1.0-rc.7", "commander": "^15.0.0", "js-yaml": "^4.2.0", "node-addon-require-builtin": "^0.1.4" @@ -1180,80 +1183,80 @@ } }, "node_modules/@deepseek-ai/dsh-agent": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-agent/-/dsh-agent-0.1.0-rc.6.tgz", - "integrity": "sha512-vtqq2pWTrzn0dKfj5kREZRpP82AwtGjGx9V1lYnKvF+Uc/a8zyWbSvjDE7V1d3YQAQJzs2cWO31hURWDekDXIA==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-agent/-/dsh-agent-0.1.0-rc.7.tgz", + "integrity": "sha512-AqBQavJYgbCUUYBHP7OGCaw8WN5082NXYQOoOfNRO72bub3E+/nWkl8b4B7BAJdFfyLo9ce+Kgb1BCHSJU/JLg==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-agent-default-model": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-agent-default-model/-/dsh-agent-default-model-0.1.0-rc.6.tgz", - "integrity": "sha512-5Fl15p5mHVMlp69Ea0qeS81ej1Bt9vSJtCed+gjvzkKzv5y3VbJQ8PPBV34F1rTSyhTtjj5Q7TuDugQI5ZpjfA==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-agent-default-model/-/dsh-agent-default-model-0.1.0-rc.7.tgz", + "integrity": "sha512-zHtD4FAqxzidyNiyx1bpvLHdOTTsKnmjlHRqDS1KegIMSTNFmmp1B2bHdAUXp/OH7fPDmv+1ZXzDoJhBNUY9jA==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-agent-instructions": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-agent-instructions/-/dsh-agent-instructions-0.1.0-rc.6.tgz", - "integrity": "sha512-RCd3UWJI7b3X6EUnxnqwOFiMWh1PzRRg9GrVt4G0tVNDIxeYX+RF2FTbOrslIOkOCZxG3BlI2M/bZ6yQmB4Vwg==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-agent-instructions/-/dsh-agent-instructions-0.1.0-rc.7.tgz", + "integrity": "sha512-laLz5ee7tKqVzrj15ztHuOnJLxDiGlqFOm6mEJUjJPWWD9Yzj1Iq+6WHZZ3Hw66vrNzYKqEN0TBofWF3DA7OzQ==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-fs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-fs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-agent-loop": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-agent-loop/-/dsh-agent-loop-0.1.0-rc.6.tgz", - "integrity": "sha512-yShuKIMW360H14L4y13j3gz3Ix1s/3lwEEpfJW4hnFAE09h9Z4yJA7UfTQmQdzMRMnuj4uWFPw0e0BbapnkFuw==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-agent-loop/-/dsh-agent-loop-0.1.0-rc.7.tgz", + "integrity": "sha512-98jV+6XnkZ93g4C1BJ/hCcC8k4GVhH+oNrkhLFvc6aOQz6o+9kdV8IrgEVr0qRcAfHKlCMfiV4BIDz4eBBoziw==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-agent-presets": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-agent-presets/-/dsh-agent-presets-0.1.0-rc.6.tgz", - "integrity": "sha512-LtDz0TYE7YNhJOhMDZ8s45xQG57bWF4F1SN3tjYDosaBdINIRTxJ0O80BC+KeliqFDw071ZNOzTUEelwEAIx7w==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-agent-presets/-/dsh-agent-presets-0.1.0-rc.7.tgz", + "integrity": "sha512-T/VcMV7lrXCFmRKrtoMTAz5DAdUmku6hz95wbikRvRc0WizIwQ3R04ke9KIeDiQcxK8xkE8cx+IYqEWa9C5gPg==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1", @@ -1263,88 +1266,88 @@ "@deepseek-ai/cordis": "^4.0.1", "@deepseek-ai/cordis-plugin-include": "^1.0.6", "@deepseek-ai/cordis-plugin-loader": "^1.0.2", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-atomic-write": "^0.1.0-rc.6", - "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-atomic-write": "^0.1.0-rc.7", + "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-agent-tool-presentation": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-agent-tool-presentation/-/dsh-agent-tool-presentation-0.1.0-rc.6.tgz", - "integrity": "sha512-Ysg45g0qnteB6w7krUBRXQ6SFbc8L+laPZTS2y15FFTLueruJaANBLIgnorEtj2bIJYF2Lq0fKH5v0wPNNrlXw==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-agent-tool-presentation/-/dsh-agent-tool-presentation-0.1.0-rc.7.tgz", + "integrity": "sha512-RAtrfRyLZ/ob9lW5/fKeU7T4LYPTXYP7qCmu2i7ZBqwHseMdYHk0U1Ti8z2kr2NF4LIzHNUXIwaE9s7za5cwuA==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-anonymous-user-id": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-anonymous-user-id/-/dsh-anonymous-user-id-0.1.0-rc.6.tgz", - "integrity": "sha512-+K/+tQzuDlmvKhoudB7qVMJMNF/p1+GTRQkkPA3JHIQM5yHj7AUYY8oMLROTvUivs8XWtkNyEP1/c6nPwrHazQ==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-anonymous-user-id/-/dsh-anonymous-user-id-0.1.0-rc.7.tgz", + "integrity": "sha512-g39W2HSWum6ghJG3src3rLVR8mnCsc0xCBSRpef1Fxgsjjn1LS2KNstKThXQtn7lYQZM/DNE7uiaOmsLxayeJQ==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-api-gateway": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-api-gateway/-/dsh-api-gateway-0.1.0-rc.6.tgz", - "integrity": "sha512-pmdQXBEJpUtr87jIfTyzyPWKGbUghzJno/nZpBWfhk+ZTjGwj0jKpyA5GhhS/tzzo67f5IdmEjcxddoDr3o3Kw==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-api-gateway/-/dsh-api-gateway-0.1.0-rc.7.tgz", + "integrity": "sha512-tcoOuHMSqYqCtMxLjWBHKN+glS56XaUo3ImphvDvUkB84FyU3btHNJbYeAt2oXoWbHfOedcIRWpfNN4tSmhPwQ==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6" + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.6" + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-api-remotes": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-api-remotes/-/dsh-api-remotes-0.1.0-rc.6.tgz", - "integrity": "sha512-yYsHgPr5ZiLk+i2RTREdMj8Gin7J8jG2qnTehZmLpCONGbJv2+grPPRuH7OwcQd+HguXL0ay/rlg6L1O1t8xDg==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-api-remotes/-/dsh-api-remotes-0.1.0-rc.7.tgz", + "integrity": "sha512-dsP69u0avHRcJTPzngudqCm73UaTxNvGi/557DNPi3cOSoIh1SyPzPgk8W8rQQEFTL07rkwt8KfdQoMU5ga1fg==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6" + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.6", - "@deepseek-ai/dsh-api-gateway": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-cordis-host-runner": "^0.1.0-rc.6", - "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6", - "@deepseek-ai/dsh-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-plugin-inventory": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-message-feedback": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.7", + "@deepseek-ai/dsh-api-gateway": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-cordis-host-runner": "^0.1.0-rc.7", + "@deepseek-ai/dsh-credentials": "^0.1.0-rc.7", + "@deepseek-ai/dsh-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-plugin-inventory": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-message-feedback": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-app-boot": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-app-boot/-/dsh-app-boot-0.1.0-rc.6.tgz", - "integrity": "sha512-97Xb2wB0cuFMmbvW7/95pfMTyXwUNQxW/ROx19OdjS6PgHQNA28ZADZ19FgZmofguxzWuDD0lJPc1SWkSGLYcg==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-app-boot/-/dsh-app-boot-0.1.0-rc.7.tgz", + "integrity": "sha512-3qgv994YzNGrlDcOyarL4vqNky3ttmYsUhDsMgGdefALK6gpL7ZCWF+9m0ehZjGY0Rb4VcBdieJYOY2EgpWb0w==", "license": "MIT", "dependencies": { "js-yaml": "^4.2.0" @@ -1355,10 +1358,10 @@ "@deepseek-ai/cordis-plugin-hmr": "^1.0.16", "@deepseek-ai/cordis-plugin-include": "^1.0.6", "@deepseek-ai/cordis-plugin-loader": "^1.0.2", - "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6" + "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7" }, "peerDependenciesMeta": { "@deepseek-ai/cordis-plugin-hmr": { @@ -1367,30 +1370,30 @@ } }, "node_modules/@deepseek-ai/dsh-atomic-write": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-atomic-write/-/dsh-atomic-write-0.1.0-rc.6.tgz", - "integrity": "sha512-Ot/2aygDzWuN4ypUkDJA6MpSlGbcvzzKnWAms0lg+2WUtPZr7O0cGb83K3TEO2NoAu0LJfVxlbo8Eya3tDaFtw==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-atomic-write/-/dsh-atomic-write-0.1.0-rc.7.tgz", + "integrity": "sha512-LxRx6K8FJ8bXZHiNhH6Rvj+jh/ZIpolmsmi138XrvMUGvbOBWE6QLbdzcgTgwrYZm5GP2kqqLe/3gQlgtt2bXA==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-attachment": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-attachment/-/dsh-attachment-0.1.0-rc.6.tgz", - "integrity": "sha512-3P6N17NQ8jqSQGzeCs+svCIqArU8oq0YmgEAo+axN9aVuUDferWU4DLRSX59UGpmyldX4LQn81toA+c+DqMcHg==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-attachment/-/dsh-attachment-0.1.0-rc.7.tgz", + "integrity": "sha512-rsR/xVNOGIig8gXxhrKnkd6YD7aYliGtA/e7b4DlPawMpLhsItAh0HQ832n8LJn1aGZxKf68y9PRgzfljsveOQ==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-attachment-local": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-attachment-local/-/dsh-attachment-local-0.1.0-rc.6.tgz", - "integrity": "sha512-vnLDgnFU2Nxxyjrdh1rRhUYhENE2ZMocfXoeWZd4qioCmjibO/GZxqB7HxJhmFzrldSkKI4VnOglPG8lttKW+Q==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-attachment-local/-/dsh-attachment-local-0.1.0-rc.7.tgz", + "integrity": "sha512-7i2Fuj811MFeqrUYnpEG3VBoShZEjQ7zNXdLOa1W5hZ4TWV+tUjX7pJoN88U1LOgEOWMc9uzSPqGA5/aKBYgdQ==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1", @@ -1398,166 +1401,166 @@ }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-attachment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-base": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-base/-/dsh-base-0.1.0-rc.6.tgz", - "integrity": "sha512-SR0V0Lq4Bm2ir7k2OaiINZZWFSDt1n4dS8J6IlIabYhoIF46baEQY2awZ9/InOWCe+dIpQob0/3y3yZOHqjnpw==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-base/-/dsh-base-0.1.0-rc.7.tgz", + "integrity": "sha512-lpAMUO3PdxZwLnCQOdOZ/fu7eI27Ckz3Ec9MB9QYL4u34yatndCliTrGaFBDoNHoWt3V4gojzszRFrEx+Vce/g==", "license": "MIT", "dependencies": { "@deepseek-ai/cordis-plugin-hmr": "^1.0.16", "@deepseek-ai/cordis-plugin-timer": "^1.1.3", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-agent-default-model": "^0.1.0-rc.6", - "@deepseek-ai/dsh-agent-instructions": "^0.1.0-rc.6", - "@deepseek-ai/dsh-agent-loop": "^0.1.0-rc.6", - "@deepseek-ai/dsh-api-gateway": "^0.1.0-rc.6", - "@deepseek-ai/dsh-attachment-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-bash-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-command-compact": "^0.1.0-rc.6", - "@deepseek-ai/dsh-command-feedback": "^0.1.0-rc.6", - "@deepseek-ai/dsh-command-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-compaction-basic": "^0.1.0-rc.6", - "@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.0-rc.6", - "@deepseek-ai/dsh-credentials-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-fs-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-fs-observation-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-fs-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-goal-round-driver": "^0.1.0-rc.6", - "@deepseek-ai/dsh-jobs-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm-deepseek": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm-pi-ai": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm-retry": "^0.1.0-rc.6", - "@deepseek-ai/dsh-permission-presets": "^0.1.0-rc.6", - "@deepseek-ai/dsh-plan-mode": "^0.1.0-rc.6", - "@deepseek-ai/dsh-pwsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-repeat-tool-reminder": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-checkpoint-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence-jsonl": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-query-sqlite": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-telemetry-otel": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-title": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-title-first-prompt-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings-file": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell-env": "^0.1.0-rc.6", - "@deepseek-ai/dsh-skill": "^0.1.0-rc.6", - "@deepseek-ai/dsh-skill-badge": "^0.1.0-rc.6", - "@deepseek-ai/dsh-skill-filesystem": "^0.1.0-rc.6", - "@deepseek-ai/dsh-spill-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-spill-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent-fork-in-process": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent-spawn-in-process": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subprocess-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-bash": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-call-timeout-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-fs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-fs-search": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-jobs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-pwsh": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-ralph": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-skill": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-str-replace-editor": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-subagent-control": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-subagent-report": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-todo": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-web": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-workflow": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-loader": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.6", - "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6", - "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.6", - "@deepseek-ai/dsh-web": "^0.1.0-rc.6", - "@deepseek-ai/dsh-web-search-deepseek": "^0.1.0-rc.6", - "@deepseek-ai/dsh-workflow-worker-thread": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-agent-default-model": "^0.1.0-rc.7", + "@deepseek-ai/dsh-agent-instructions": "^0.1.0-rc.7", + "@deepseek-ai/dsh-agent-loop": "^0.1.0-rc.7", + "@deepseek-ai/dsh-api-gateway": "^0.1.0-rc.7", + "@deepseek-ai/dsh-attachment-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-bash-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-command-compact": "^0.1.0-rc.7", + "@deepseek-ai/dsh-command-feedback": "^0.1.0-rc.7", + "@deepseek-ai/dsh-command-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-compaction-basic": "^0.1.0-rc.7", + "@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.0-rc.7", + "@deepseek-ai/dsh-credentials-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-fs-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-fs-observation-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-fs-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-goal-round-driver": "^0.1.0-rc.7", + "@deepseek-ai/dsh-jobs-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm-deepseek": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm-pi-ai": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm-retry": "^0.1.0-rc.7", + "@deepseek-ai/dsh-permission-presets": "^0.1.0-rc.7", + "@deepseek-ai/dsh-plan-mode": "^0.1.0-rc.7", + "@deepseek-ai/dsh-pwsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-repeat-tool-reminder": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-checkpoint-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence-jsonl": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-query-sqlite": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-telemetry-otel": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-title": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-title-first-prompt-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings-file": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell-env": "^0.1.0-rc.7", + "@deepseek-ai/dsh-skill": "^0.1.0-rc.7", + "@deepseek-ai/dsh-skill-badge": "^0.1.0-rc.7", + "@deepseek-ai/dsh-skill-filesystem": "^0.1.0-rc.7", + "@deepseek-ai/dsh-spill-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-spill-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent-fork-in-process": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent-spawn-in-process": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subprocess-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-bash": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-call-timeout-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-fs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-fs-search": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-jobs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-pwsh": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-ralph": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-skill": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-str-replace-editor": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-subagent-control": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-subagent-report": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-todo": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-web": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-workflow": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-loader": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.7", + "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.7", + "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.7", + "@deepseek-ai/dsh-web": "^0.1.0-rc.7", + "@deepseek-ai/dsh-web-search-deepseek": "^0.1.0-rc.7", + "@deepseek-ai/dsh-workflow-worker-thread": "^0.1.0-rc.7" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-bash-local": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-bash-local/-/dsh-bash-local-0.1.0-rc.6.tgz", - "integrity": "sha512-YAc5W9uR7sN1Rrobp6fQlCaOdHqCWatTktV68UsoDuOJs5eM3nWEUUUVN8jdZCIDZhktT5hqbhe3+DzOX3Xg1w==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-bash-local/-/dsh-bash-local-0.1.0-rc.7.tgz", + "integrity": "sha512-fsw2Ex5ExyX4A62P1+fodbnUG4PXOSyHAM4YtaLg2kcPcElLwatYNPG3gEuulxwbpWDlx/OWvbjHThnJUuzaoA==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-bash-sandbox": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-bash-sandbox/-/dsh-bash-sandbox-0.1.0-rc.6.tgz", - "integrity": "sha512-TNLRriAjpEUrJplrI0BmZtAtntIkV5usYiKylJGPlGUfWWnJkLR0zL9gioyXW3kncHBVSnb+YTuf+7FnDVeVHQ==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-bash-sandbox/-/dsh-bash-sandbox-0.1.0-rc.7.tgz", + "integrity": "sha512-xX+XhqPeRaOqMPDNk8dPboHza2pP13hTIMt+ztvd8WpD0t35idrNrcsXEYs+CtKiFWn6I05WB1BeAimWkLDOcg==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-bash-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell": "^0.1.0-rc.6" + "@deepseek-ai/dsh-bash-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-brand": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-brand/-/dsh-brand-0.1.0-rc.6.tgz", - "integrity": "sha512-E8j9Nby24qP4rfrdcfc7bpt1CHpGT3tYmycOJJkEOH4ptIdT1m2ro9nmnSd5CWYukTr64A77vjm2WGqHRI92UA==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-brand/-/dsh-brand-0.1.0-rc.7.tgz", + "integrity": "sha512-P7+w0fN40yXXQkV360p6jQi63pcl68OOWebNGN5gf8w8sguvni2mA1cU8RLZzDkRNFSZD+BCw3D4uWYM+hhh7A==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-client-connection": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-connection/-/dsh-client-connection-0.1.0-rc.6.tgz", - "integrity": "sha512-ZHqZXmmdcxzw7HKwrSJDlU3/GVulvX/yAc1xHu7hw+cXWws2QK7ahQMpfdiywnxAVYadhFnsvLLkEPp38mOREg==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-connection/-/dsh-client-connection-0.1.0-rc.7.tgz", + "integrity": "sha512-JZWDKCbwKHOUcm7+JadKA3aJCSEB34XfPycCtPgdWfABIiHMaSpnmSVy/8Jed4hw6hxhnR6A3rnvW02Xr2yqwA==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-apiproxy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", + "@deepseek-ai/dsh-attachment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-apiproxy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", "@deepseek-ai/schemastery": "^3.18.1", "ws": "^8.21.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-client-hmr": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-hmr/-/dsh-client-hmr-0.1.0-rc.6.tgz", - "integrity": "sha512-DKm5ePNGDRCBVoyb42vBtE34M+FaIwgNwmJLu7xvOCj/XNlmgCBTakHCoKN9oBZLAPurC+D0skPEcGRHGqzBGw==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-hmr/-/dsh-client-hmr-0.1.0-rc.7.tgz", + "integrity": "sha512-uJVHLMgmf19JI7UCqrC8jipf/5oaM539RPJ5sNv+BJCbt9Ik6VqaKbu4uiF+gz8i8EqbXV3D9criL1IiCS+pdg==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" @@ -1565,49 +1568,70 @@ "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", "@deepseek-ai/cordis-plugin-loader": "^1.0.2", - "@deepseek-ai/dsh-client-modules": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-client-modules": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" + } + }, + "node_modules/@deepseek-ai/dsh-client-locale": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-locale/-/dsh-client-locale-0.1.0-rc.7.tgz", + "integrity": "sha512-1onX79wXJfAzdwIJPUI9jEVYeVQJfWwyQvyL/OmGrnkCs8srJHIXBdYtsUC7ILlR13y5nOY4j6bifBOAoGRn6w==", + "license": "MIT", + "dependencies": { + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/schemastery": "^3.18.1" + }, + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, "node_modules/@deepseek-ai/dsh-client-modules": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-modules/-/dsh-client-modules-0.1.0-rc.6.tgz", - "integrity": "sha512-DFeXjfbfrU2LvVziHsqBsfvnYVuqXTpvNybwBDJqGBNR4VjPVUbvCUrH8pzFRkv0bQO6Vq6dLKUR0Q2ZUYdTwg==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-modules/-/dsh-client-modules-0.1.0-rc.7.tgz", + "integrity": "sha512-hczFl0TRH5sLt/dS0+TMCtQvfDoeLw/r88L6n3rXfY6Q1e4Yddg6RAv4kGsUoMoLYgWi7qPwD6HcUGgyKkDPHg==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-client-runtime": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-runtime/-/dsh-client-runtime-0.1.0-rc.6.tgz", - "integrity": "sha512-qprJMsVPLK2CyJmmCHwECJZlbM7XNG5yKr2Zf/yKYRyz0+QNJfHlIt+4C32tkjFFIq+Dx3gU5YaUQaLXxsR4/w==", - "license": "MIT", - "dependencies": { - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-apiproxy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm-retry": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-title": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-runtime/-/dsh-client-runtime-0.1.0-rc.7.tgz", + "integrity": "sha512-Ish2uFML2FibTpzo7QyVSt29jf/iG4j9BFQ41ychVMPRR3trJGM3h8CMuam3oKWlvB8OXVXFd6gO929w6PI0Ew==", + "license": "MIT", + "dependencies": { + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-attachment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-apiproxy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm-retry": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-title": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", "immer": "^10.1.1", "react": "^18.2.0", "zustand": "~4.4.7" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.6" + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-client-runtime/node_modules/react": { @@ -1660,33 +1684,53 @@ } }, "node_modules/@deepseek-ai/dsh-client-schema-form": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-schema-form/-/dsh-client-schema-form-0.1.0-rc.6.tgz", - "integrity": "sha512-2kFkweuNJlcnYRTy6rXx1gWoWNapFCDOvcYs7Kkir8n3JwQVB6xwTkQxVuZDBTD4jrdIpKTeetx4ghig49joTw==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-schema-form/-/dsh-client-schema-form-0.1.0-rc.7.tgz", + "integrity": "sha512-acGeXjGl2lMqCO+jY1z9/FKbIiskk7FZO266OSBOwHJQP6yBd5MBnrvtPJUB3glP6xsQK8neFLLtRwVgRJ+GqQ==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" + } + }, + "node_modules/@deepseek-ai/dsh-client-ui-agent-preset": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-agent-preset/-/dsh-client-ui-agent-preset-0.1.0-rc.7.tgz", + "integrity": "sha512-85GLGfg3iEISMhHxn9ZePkB/mtXIJdWkpvSHCm9bZizK8KiyRfA/OjDpKfk5kvG16xKNV0KQo65HOf0JdwtyXQ==", + "license": "MIT", + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, "node_modules/@deepseek-ai/dsh-client-ui-attachment": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-attachment/-/dsh-client-ui-attachment-0.1.0-rc.6.tgz", - "integrity": "sha512-/cnnH48758EQxJB/p3qPaAgFmQuxNgu29pGzSd4jH2W9dM29lNkLLZ15mrpS6IIDndx0bEzW/nLJ4x6/iowHnQ==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-attachment/-/dsh-client-ui-attachment-0.1.0-rc.7.tgz", + "integrity": "sha512-IRA778yZpOaoJEkODlfydd6yuASf7hF229s64IY5zaY+22K7D+X1cmDo8D13UylxQXFPAomTlHtQtQpCtghKXw==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", + "@deepseek-ai/dsh-attachment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", "clsx": "^2.0.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-client-ui-attachment/node_modules/react": { @@ -1723,58 +1767,103 @@ "loose-envify": "^1.1.0" } }, - "node_modules/@deepseek-ai/dsh-client-ui-directory-picker-browse": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-directory-picker-browse/-/dsh-client-ui-directory-picker-browse-0.1.0-rc.6.tgz", - "integrity": "sha512-laXJjWRMPYaJaG5TuHB7H98Ahtg1Umxp6tH78WXVULATToJ5BLZ/7fPedc/rSlYwRQFFDpsmK0nNxsAVGY1RnQ==", + "node_modules/@deepseek-ai/dsh-client-ui-commands": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-commands/-/dsh-client-ui-commands-0.1.0-rc.7.tgz", + "integrity": "sha512-gLuzEmgVhEIjVeLlmIAdKX/SEEFavnVOD0mQPlHIMqFAX/80yzYfRD7CMxXc0amOj7uBcw7qsSa4WzFvaWso3w==", "license": "MIT", "dependencies": { "clsx": "^2.0.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-workspace": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-client-ui-primitives": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-primitives/-/dsh-client-ui-primitives-0.1.0-rc.6.tgz", - "integrity": "sha512-vZ9/V5pXYbkumLEOHagEjzSWvVxX+CtXZ13+iNz3BnqDVsy0HYLgnrWwcLLPHqHLUmww9NlxXe9husoS7o/zyw==", + "node_modules/@deepseek-ai/dsh-client-ui-conversation": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-conversation/-/dsh-client-ui-conversation-0.1.0-rc.7.tgz", + "integrity": "sha512-CyjFjP+oRJQ4ydX8WVrKUeloQnAJRA/fN6RRY6NAHldFC9pd1l8YogmTcR1JuCIlqzMnLRyYlGODQBYz8WOjmA==", "license": "MIT", "dependencies": { - "@shikijs/langs": "^4.3.1", - "@types/mdast": "^4.0.4", - "anser": "^2.3.5", - "clsx": "^2.0.0", - "katex": "^0.16.47", - "mdast-util-from-markdown": "^2.0.3", - "mdast-util-gfm": "^3.1.0", - "mdast-util-math": "^3.0.0", - "micromark-core-commonmark": "^2.0.3", - "micromark-extension-gfm": "^3.0.0", - "micromark-extension-math": "^3.1.0", - "micromark-factory-space": "^2.0.1", - "micromark-util-character": "^2.1.1", - "micromark-util-classify-character": "^2.0.1", - "micromark-util-sanitize-uri": "^2.0.1", - "micromark-util-symbol": "^2.0.1", - "micromark-util-types": "^2.0.2", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "shiki": "^4.3.1" + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/schemastery": "^3.18.1", + "clsx": "^2.0.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-attachment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-attachment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-compaction": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm-retry": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-stats": "^0.1.0-rc.7", + "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-client-ui-primitives/node_modules/react": { + "node_modules/@deepseek-ai/dsh-client-ui-cordis": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-cordis/-/dsh-client-ui-cordis-0.1.0-rc.7.tgz", + "integrity": "sha512-8OwbFdMHRIE7L2PvoIGwSOkhUYsznr9u773K3s64DMxp4oLLl3ZzHc2hfaOfQTTmyE7ItpDJm8Von42LsJBKaw==", + "license": "MIT", + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-sidebar": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-tool": "^0.1.0-rc.7", + "@deepseek-ai/dsh-cordis-client-runner": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" + } + }, + "node_modules/@deepseek-ai/dsh-client-ui-deliverables": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-deliverables/-/dsh-client-ui-deliverables-0.1.0-rc.7.tgz", + "integrity": "sha512-uVN7TXKrGQMACKToSTPxOIeDlebQgi2OMiKBaKrYcI7jBsCRief3CTLziZ6Kups2h2s72Eo6gu/0eueccwLYew==", + "license": "MIT", + "dependencies": { + "react": "^18.2.0" + }, + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7" + } + }, + "node_modules/@deepseek-ai/dsh-client-ui-deliverables/node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", @@ -1786,76 +1875,95 @@ "node": ">=0.10.0" } }, - "node_modules/@deepseek-ai/dsh-client-ui-primitives/node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "node_modules/@deepseek-ai/dsh-client-ui-directory-picker-browse": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-directory-picker-browse/-/dsh-client-ui-directory-picker-browse-0.1.0-rc.7.tgz", + "integrity": "sha512-5lj27c68wWqroyIOXmFPGUDFQxICDYEcYAJSuV5ZbnHXyN2cBTTDTW4zJPwisY5GhKfiJXjhS0YZqLi54/Xn+Q==", "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" + "clsx": "^2.0.0" }, "peerDependencies": { - "react": "^18.3.1" + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-workspace": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-client-ui-primitives/node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "node_modules/@deepseek-ai/dsh-client-ui-directory-picker-native": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-directory-picker-native/-/dsh-client-ui-directory-picker-native-0.1.0-rc.7.tgz", + "integrity": "sha512-SZ9NuuIDrBjHJsEcnqwhbiCZknjkyNd0ZBHDl453p2WHkfA8zwDMUJRdAMWd0sC95WH2Yu4rMzkAVYjZwCBjVw==", "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-workspace": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-client-ui-slots": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-slots/-/dsh-client-ui-slots-0.1.0-rc.6.tgz", - "integrity": "sha512-F4VZA60bMRi4DAbZvNipM4E/Jl01QC0cQCPpeIEIh1/lq/y/bpc7IqujtzWESHPe3qSljTURip3hkANfsYs3UA==", + "node_modules/@deepseek-ai/dsh-client-ui-goal": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-goal/-/dsh-client-ui-goal-0.1.0-rc.7.tgz", + "integrity": "sha512-zZEAbaA6ZCMw2ZDGMWFm+nBXnBBRfI8StRtx33GoFcJHlMIP5mJfuSm2gcFHdO+3aeAmuTf5G++DdWwLRLZv9A==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-client-web": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-web/-/dsh-client-web-0.1.0-rc.6.tgz", - "integrity": "sha512-T0N/QeR/cVwj+Ss/GjnbGoEy+a63m5nhjD8Z9eRhaj3rgJHAoYrGf08/IbzAqXULZRZ5Y+Uqg338yhMymv4hwA==", - "license": "MIT", - "dependencies": { - "@deepseek-ai/dsh-client-modules": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-schema-form": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-attachment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-theme": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.6", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "node_modules/@deepseek-ai/dsh-client-ui-input-trigger": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-input-trigger/-/dsh-client-ui-input-trigger-0.1.0-rc.7.tgz", + "integrity": "sha512-Sfn4YlS6dKm/ojGRyZL5oq34+GSeyirzGkmqhtoX7hpjHAhBVmugz2jku2ijYEjjFtD6YKYdWwvQxHdRaHFZ+w==", + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/cordis-plugin-loader": "^1.0.2", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-client-web-react": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-web-react/-/dsh-client-web-react-0.1.0-rc.6.tgz", - "integrity": "sha512-2PAnRsZzokVr/nCcwX87axdxzobQYp76xzX70vYSqghlDab1phsIdgDSm1JxpszN9G3ETBMTLPM9xz30iodqYQ==", + "node_modules/@deepseek-ai/dsh-client-ui-jobs": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-jobs/-/dsh-client-ui-jobs-0.1.0-rc.7.tgz", + "integrity": "sha512-q8WvaB1gxj4OBPCLC/luDLQ7TRY2iwuhOZKrwG1MbXhSmfd14RiyKHG1p/5HIxwTJZfqnxuN69NzdAZY6cjU8g==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "react": "^18.2.0", - "use-sync-external-store": "1.2.0" + "react": "^18.2.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-client-web-react/node_modules/react": { + "node_modules/@deepseek-ai/dsh-client-ui-jobs/node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", @@ -1867,40 +1975,134 @@ "node": ">=0.10.0" } }, - "node_modules/@deepseek-ai/dsh-client-web-react/node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "node_modules/@deepseek-ai/dsh-client-ui-layout": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-layout/-/dsh-client-ui-layout-0.1.0-rc.7.tgz", + "integrity": "sha512-4z5xkH/O8GT6ve1IX15WTel236fJwSuRZusMKJ9qIxdslZZ1h+wMbtgX3tCqg7mTtMznRDspCpC1b1QSAt4nTg==", "license": "MIT", "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-theme": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" + } + }, + "node_modules/@deepseek-ai/dsh-client-ui-message-feedback": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-message-feedback/-/dsh-client-ui-message-feedback-0.1.0-rc.7.tgz", + "integrity": "sha512-B8y2+tu1xorpHmwo8KWsLFZwa4P0uFCI32H1SwYyQjBjoTbSb+TOfPA3i6na988XMiF8NCcxynTFzHRv/77AJw==", + "license": "MIT", + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-message-feedback": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7", + "react": "^18.2.0" + } + }, + "node_modules/@deepseek-ai/dsh-client-ui-model-selection": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-model-selection/-/dsh-client-ui-model-selection-0.1.0-rc.7.tgz", + "integrity": "sha512-Gr5goo9dEGCR/CqpeJgO1mGO1ZqoX4tpuAMuZoq3wmLwaeK8qOMMhHGTxGOI9NbBD1snvbUzOJP/LUoNrS61YQ==", + "license": "MIT", + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "clsx": "^2.1.1", + "react": "^18.2.0" + } + }, + "node_modules/@deepseek-ai/dsh-client-ui-permission-presets": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-permission-presets/-/dsh-client-ui-permission-presets-0.1.0-rc.7.tgz", + "integrity": "sha512-OO/miNmPCJS/5GffqXeBnPvdx1HnHvi9AHb4Uoy9N+zucwo7ZQV40lQ+ODcAX9UaRW/6x3a8CxQ3G4q1t/ltKQ==", + "license": "MIT", + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-schema-form": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-permission-presets": "^0.1.0-rc.7", + "react": "^18.2.0" + } + }, + "node_modules/@deepseek-ai/dsh-client-ui-plan": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-plan/-/dsh-client-ui-plan-0.1.0-rc.7.tgz", + "integrity": "sha512-b6qqGcq5MxulD+XBxcD3ZewgJ17OUegeSA0Ov0afC4hvgyhWhZP3b+odH92ax7Ckaat8/Yx2j4NPpu81e30qLA==", + "license": "MIT", + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-plan-mode": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-client-web/node_modules/@deepseek-ai/dsh-client-ui-theme": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-theme/-/dsh-client-ui-theme-0.1.0-rc.6.tgz", - "integrity": "sha512-Wu+bvnuti/gLA+t5a2cWUMQJ5UCqxt6oEK+OJiJ68gN0ixs2skpaN0nFdFoY2exC5KByXrNlN1rRrD+FsZSBLA==", + "node_modules/@deepseek-ai/dsh-client-ui-primitives": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-primitives/-/dsh-client-ui-primitives-0.1.0-rc.7.tgz", + "integrity": "sha512-x3cnIAeOdDMd7no8JwP65q7J9Fj4xQWAZPPJY4MzgfQAAOcHJb0T0d5Uo4FXMiCcTeU/73n7BssS5PE7jjgiDg==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/schemastery": "^3.18.1", - "clsx": "^2.0.0" + "@shikijs/langs": "^4.3.1", + "@types/mdast": "^4.0.4", + "anser": "^2.3.5", + "clsx": "^2.0.0", + "katex": "^0.16.47", + "mdast-util-from-markdown": "^2.0.3", + "mdast-util-gfm": "^3.1.0", + "mdast-util-math": "^3.0.0", + "micromark-core-commonmark": "^2.0.3", + "micromark-extension-gfm": "^3.0.0", + "micromark-extension-math": "^3.1.0", + "micromark-factory-space": "^2.0.1", + "micromark-util-character": "^2.1.1", + "micromark-util-classify-character": "^2.0.1", + "micromark-util-sanitize-uri": "^2.0.1", + "micromark-util-symbol": "^2.0.1", + "micromark-util-types": "^2.0.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "shiki": "^4.3.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-client-web/node_modules/react": { + "node_modules/@deepseek-ai/dsh-client-ui-primitives/node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", @@ -1912,7 +2114,7 @@ "node": ">=0.10.0" } }, - "node_modules/@deepseek-ai/dsh-client-web/node_modules/react-dom": { + "node_modules/@deepseek-ai/dsh-client-ui-primitives/node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", @@ -1925,7 +2127,7 @@ "react": "^18.3.1" } }, - "node_modules/@deepseek-ai/dsh-client-web/node_modules/scheduler": { + "node_modules/@deepseek-ai/dsh-client-ui-primitives/node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", @@ -1934,613 +2136,598 @@ "loose-envify": "^1.1.0" } }, - "node_modules/@deepseek-ai/dsh-cmdline": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-cmdline/-/dsh-cmdline-0.1.0-rc.6.tgz", - "integrity": "sha512-dqRHF+kIlTBwt+fio/34ttp6B7Lrpm31A+EOoEwBuwaziiHTEAWVl50hS53dPFmPyVBRINavBdx7Fa7UT2/2iw==", - "license": "MIT", - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/cordis-plugin-loader": "^1.0.2", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" - } - }, - "node_modules/@deepseek-ai/dsh-code-runtime": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-code-runtime/-/dsh-code-runtime-0.1.0-rc.6.tgz", - "integrity": "sha512-aw8D4IOeMo11A3uxQeE4LFoW3bvaQnVkGFqqtS+lsINDARrOCJHXLUgecoKpys+Lc5erZZ4UQDnymJmL4OCcKA==", + "node_modules/@deepseek-ai/dsh-client-ui-settings": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-settings/-/dsh-client-ui-settings-0.1.0-rc.7.tgz", + "integrity": "sha512-I02BGKw3/yG25yf5omsMwmwJ2CnFyxTvbxqgRgSmTCUxATkLT87K8SxcemRZqXnFXQZhm6Il6bwVCpVfRfmNoA==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-schema-form": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-code-runtime-worker-thread": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-code-runtime-worker-thread/-/dsh-code-runtime-worker-thread-0.1.0-rc.6.tgz", - "integrity": "sha512-I2YX2ZSeQnQrSJGffM2upL+7y7vGsLwKv478gesusgYtT0kH/MOcszO9ZpnV8sIqvlkgzvWgBhXzniGHWh40ZA==", + "node_modules/@deepseek-ai/dsh-client-ui-settings-general": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-settings-general/-/dsh-client-ui-settings-general-0.1.0-rc.7.tgz", + "integrity": "sha512-L5heQqyzZ/Kd+/hj8Ptd89OOss6FI8TjD3iwC47V3Xj/8ZgtnHwEA7vSqeoTe03uzRz8Zd8ec+bz/q47z8/I/Q==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/schemastery": "^3.18.1", + "clsx": "^2.0.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-code-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6" + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-sidebar": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-command-compact": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-command-compact/-/dsh-command-compact-0.1.0-rc.6.tgz", - "integrity": "sha512-aTadVzxYa+Me/9QqolHnXaduRVKPxe8z3XraZ9EdQp6Cz/QrYS9DMUbO2Bp434qgwAdye0SytuHLBBb9h8GVQw==", + "node_modules/@deepseek-ai/dsh-client-ui-settings-models": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-settings-models/-/dsh-client-ui-settings-models-0.1.0-rc.7.tgz", + "integrity": "sha512-q73sXPomdUGpucj6pgKuO3WrGzqCoqyZhbqOZQL7EIdJcl9N3P+tNhsNj+ls1UOcOpb36Ou2NzUdIeyHSNVmKg==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-compaction": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-schema-form": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-command-feedback": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-command-feedback/-/dsh-command-feedback-0.1.0-rc.6.tgz", - "integrity": "sha512-VGVszTifY/LkgrTOctj8FRCVm62fwLZEGUan8rTqxLwIWYt7JZ9avckTtuB3Ls62hNBKGSAdbZ7fgH4n8KKMxQ==", + "node_modules/@deepseek-ai/dsh-client-ui-settings-plugin-inventory": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-settings-plugin-inventory/-/dsh-client-ui-settings-plugin-inventory-0.1.0-rc.7.tgz", + "integrity": "sha512-Ei6q5/UdUC9SxrTcbn/XR1NCe4iZgovhmbKCKBKBHMCNxhE0umdUJL8M7uKZdlpItJQ2ggiK9L8RmztKDmv59A==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-anonymous-user-id": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-telemetry": "^0.1.0-rc.6" + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-command-goal": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-command-goal/-/dsh-command-goal-0.1.0-rc.6.tgz", - "integrity": "sha512-3roWsvwDYPswLmpxxKcCjAAi8rRP9+jXhZ0yCss/zNAAKHgxlO8AJ5EcTkWnN9ODUnwzith448aQyU5mbm+GCg==", + "node_modules/@deepseek-ai/dsh-client-ui-settings-plugins": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-settings-plugins/-/dsh-client-ui-settings-plugins-0.1.0-rc.7.tgz", + "integrity": "sha512-oOOgj9NTv1GE+QdKhBfkcWG2+WS9uJz5NYgIZzahbg6xCbu4a2vugcCKcyslQEKKOB35mGHH/orPcoj2N+DeHg==", "license": "MIT", + "dependencies": { + "clsx": "^2.0.0" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-commands": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-commands/-/dsh-commands-0.1.0-rc.6.tgz", - "integrity": "sha512-dq1GZmGTPXEGG01ksZ6Jj6DxAkzAbg+nepvfnM/P74d6EUcsFsEy7CfS18n0VJ6/2Wp0xOWsQyyuFElqbynO7w==", + "node_modules/@deepseek-ai/dsh-client-ui-sidebar": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-sidebar/-/dsh-client-ui-sidebar-0.1.0-rc.7.tgz", + "integrity": "sha512-YduvLROf3gniqYggfRfkvNDMtqvWlREmwxVtxullWTXhrgXmcPya7GCKJeru8ZuyrF3FU1XqOR8KJT+OzLSv7w==", "license": "MIT", "dependencies": { - "zod": "^4.4.3" + "clsx": "^2.0.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6" + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-compaction": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-compaction/-/dsh-compaction-0.1.0-rc.6.tgz", - "integrity": "sha512-Uu8qgrHom13gdwwxAnqmNuWM8MqafkRlhjQMMJYmaMVVxjEUewSJ6lwtMbUEBR5ViLsfv4pTm5TnhxNCjedBUw==", + "node_modules/@deepseek-ai/dsh-client-ui-skill": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-skill/-/dsh-client-ui-skill-0.1.0-rc.7.tgz", + "integrity": "sha512-jxqQhu4RkNjEf2zTm/h9qJZ+q/mHdSBVC05XqfsdNP1VRni9k9L/LcR2TWHfyuvM61drtdi5s+/ZW9pbxaQPiQ==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6" + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-tool": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-compaction-basic": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-compaction-basic/-/dsh-compaction-basic-0.1.0-rc.6.tgz", - "integrity": "sha512-sqfFPBy1SqsOmaWro/GOAcDkrryjsmJLU/M+V4HZakoE7hLyGVhMElrRG5E5OlplIl2Akntc+YYwX36kDfEItw==", + "node_modules/@deepseek-ai/dsh-client-ui-slots": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-slots/-/dsh-client-ui-slots-0.1.0-rc.7.tgz", + "integrity": "sha512-5rPP/6IWZflhiegVHU56IOPGHtrhLgBV44mOFn2JNVwiwxxmKeIhEcnYD4M0eKkI+pRiJIO5WvkRYokIGgyFiA==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-compaction": "^0.1.0-rc.6", - "@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.6" - }, - "peerDependenciesMeta": { - "@deepseek-ai/dsh-compaction-tool-result-pruner": { - "optional": true - } + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-compaction-tool-result-pruner": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-compaction-tool-result-pruner/-/dsh-compaction-tool-result-pruner-0.1.0-rc.6.tgz", - "integrity": "sha512-xLtF3Js38AvKRITHi1ghWShsIphgT4EPpgr65VecCVpzCun0Agok2rZwKE7Kecw+pw2oC8kafHAc32SfmUudqw==", + "node_modules/@deepseek-ai/dsh-client-ui-subagent": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-subagent/-/dsh-client-ui-subagent-0.1.0-rc.7.tgz", + "integrity": "sha512-geEZbS5N68tYJIPSToWIFPj0EjRiJBzryLvv3VL+INqt6urYCEm2uY7arNLUFJhHpjOJVi45ZM8qlh0qw5Sk7Q==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" + "react": "^18.2.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-compaction": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.6" - } - }, - "node_modules/@deepseek-ai/dsh-cordis-host-runner": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-cordis-host-runner/-/dsh-cordis-host-runner-0.1.0-rc.6.tgz", - "integrity": "sha512-opN+kvxYf40rBVWhURZmq2E8uGWkv8r9L0YfynYAu/2YE7W/oGEQx2x1Mp0LxuWq1uec8rtu2GL2U17ORNuuVw==", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.7" + } + }, + "node_modules/@deepseek-ai/dsh-client-ui-subagent/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1", - "zod": "^4.4.3" + "loose-envify": "^1.1.0" }, - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6" - } - }, - "node_modules/@deepseek-ai/dsh-credentials": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-credentials/-/dsh-credentials-0.1.0-rc.6.tgz", - "integrity": "sha512-zyYRs3A9gxfZjZfONzJdMhM0Gzbslpha+FGYkLDRAozgPj0N7mZdE+Qflx2V4WNrCnsSjuvOW0HFBxWtSRUTUw==", - "license": "MIT", - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@deepseek-ai/dsh-credentials-local": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-credentials-local/-/dsh-credentials-local-0.1.0-rc.6.tgz", - "integrity": "sha512-DSDcC1i8hd3Ynyr6MTPFoEdAsxcmZSLo68IPBPvaPGHZ+rCX8XDAjghWvXrNkLtkjms0ngNVPJS3rNMRcJFq0w==", + "node_modules/@deepseek-ai/dsh-client-ui-theme": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-theme/-/dsh-client-ui-theme-0.1.0-rc.7.tgz", + "integrity": "sha512-T5YaUZEJv0XHL0VYuP4/Vg+tbQGgRq0+gqsbqryuU5nq59PPISDED81zpCSb1jkZ/xFNc5Weq68+54cUGndpQg==", "license": "MIT", "dependencies": { + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", "@deepseek-ai/schemastery": "^3.18.1", - "chokidar": "^4.0.3", - "yaml": "^2.9.0" + "clsx": "^2.0.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-atomic-write": "^0.1.0-rc.6", - "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6", - "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6" + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-fs": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-fs/-/dsh-fs-0.1.0-rc.6.tgz", - "integrity": "sha512-OTkwb4QsZgmjtA/8ZEPh1FapmrBr3N989/G4Wmo1JkAvKbMxkYty6LxjckOawTTz7GJTfUoZCrw9uopDfIMMNw==", + "node_modules/@deepseek-ai/dsh-client-ui-tool": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-tool/-/dsh-client-ui-tool-0.1.0-rc.7.tgz", + "integrity": "sha512-smo+6QWddCdtLQb4AUVbaaxsu3h8ImQlMDTBYK4qeoxlVTQdKgrNdgtQe5YoB8bvuGLQd6obVVwwScPNaD73xw==", "license": "MIT", + "dependencies": { + "clsx": "^2.0.0" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6" + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-fs-local": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-fs-local/-/dsh-fs-local-0.1.0-rc.6.tgz", - "integrity": "sha512-zP0OW474s7tvzEVQnBBTGL6Jrv/YyQXt4nswIbc3Aqr9JyHSfhZ/5IJoipZqfYXLS3ISWMhrF2npRg8L1NGsIQ==", + "node_modules/@deepseek-ai/dsh-client-ui-trajectory": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-trajectory/-/dsh-client-ui-trajectory-0.1.0-rc.7.tgz", + "integrity": "sha512-Iuksc3q9Rpwj+EQMoCv9BqfLBEclDiUGiGwUec2p2FhZjr1yEBK4ujlQK2N71EteyBjQ5yODE+/S+TzNkrou9w==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1", - "koffi": "^3.1.0" + "@tanstack/react-virtual": "^3.14.9", + "diff": "^9.0.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-fs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-compaction": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "react": "^18.2.0", + "react-dom": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-fs-observation-policy": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-fs-observation-policy/-/dsh-fs-observation-policy-0.1.0-rc.6.tgz", - "integrity": "sha512-EiBMACBVmVEs0fDFkbVH6OwXrVDp9GrTG8c62vGBfuljZvRNv6yVwS+SDblboJrIPcp67axxHRVPOEy7z1CUKQ==", + "node_modules/@deepseek-ai/dsh-client-ui-user-questions": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-user-questions/-/dsh-client-ui-user-questions-0.1.0-rc.7.tgz", + "integrity": "sha512-HrFy3NpBx8J1Az+4WCljgXQvt/TTa6G3SKgtF0ZxdstB+BYoiMyBjO8aXAKQ94BM7zLcOVfUmL1bCb9t6tFmvg==", "license": "MIT", + "dependencies": { + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "clsx": "^2.0.0", + "react": "^18.2.0" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-fs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-fs-sandbox": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-fs-sandbox/-/dsh-fs-sandbox-0.1.0-rc.6.tgz", - "integrity": "sha512-NLUeuZkeQVNPIpUute6TW4Ts1et6XxLkQIOxunL5T9mXwizp+tcdCeNjBW6XMiG6gvpECA+IA3amFCvbVSXtXw==", + "node_modules/@deepseek-ai/dsh-client-ui-user-questions/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-fs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-fs-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6" + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@deepseek-ai/dsh-goal": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-goal/-/dsh-goal-0.1.0-rc.6.tgz", - "integrity": "sha512-cONQOvFqZmjtw5HSgbXJ5/8rZ2gHqdf69ONhH21cLFu5jJKVy9YbLt42SlD2sdGMv/co9nN8Kt9bWQiZ/96VbQ==", + "node_modules/@deepseek-ai/dsh-client-ui-workflow-run": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-workflow-run/-/dsh-client-ui-workflow-run-0.1.0-rc.7.tgz", + "integrity": "sha512-XTKDLADe621GN+D2ysnOdVFvK1Et4nxvdrvsCxl7epsfrelsZD4l+/BleUQ+G/vQVZt3v03VkVVnE0SPGpt9Fg==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1", - "zod": "^4.4.3" + "react": "^18.2.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6" + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tool-workflow": "^0.1.0-rc.7", + "@deepseek-ai/dsh-workflow": "^0.1.0-rc.7" + } + }, + "node_modules/@deepseek-ai/dsh-client-ui-workflow-run/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@deepseek-ai/dsh-goal-round-driver": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-goal-round-driver/-/dsh-goal-round-driver-0.1.0-rc.6.tgz", - "integrity": "sha512-+tpbRXZ3nq/C2btBxyFC88RU0IC0H39JY1WyL07fq3j24AWS5jZb9/05gEJPyoyaIDkV/Li4dJVCdJH4VaF9Fw==", + "node_modules/@deepseek-ai/dsh-client-ui-workspace": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-workspace/-/dsh-client-ui-workspace-0.1.0-rc.7.tgz", + "integrity": "sha512-+8TmQprJ4y1J9AyM+/ABkndWsv6/lwA7by6HlRup4Ks2auQBhejFG7FjZPFACjkWLuJaIgDUN1aRQ5MNFCanfQ==", "license": "MIT", + "dependencies": { + "clsx": "^2.0.0" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6" + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-headless": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-headless/-/dsh-headless-0.1.0-rc.6.tgz", - "integrity": "sha512-0jdWiQMWwkbJ/PnUJng8NrrBM5fsMXCWYFKW3CUFCllhEMJwhoSrd5F7aRsqwKrIGqTRORLPRVOxdawhnVCSGQ==", - "license": "MIT", - "dependencies": { - "@deepseek-ai/dsh-cmdline": "^0.1.0-rc.6", - "@deepseek-ai/dsh-code-runtime-worker-thread": "^0.1.0-rc.6", - "@deepseek-ai/schemastery": "^3.18.1", - "commander": "^15.0.0" + "node_modules/@deepseek-ai/dsh-client-web": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-web/-/dsh-client-web-0.1.0-rc.7.tgz", + "integrity": "sha512-1pb5B7V8vhrgoCFsBwa8A+MsXkPvwPJ8fJ5ldMZ4Cd1RyFPgVev48LW/z2WF4tc6qkots2wnjZ2i6bMz8wvk2g==", + "license": "MIT", + "dependencies": { + "@deepseek-ai/dsh-client-modules": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-schema-form": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-attachment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-theme": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.7", + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", "@deepseek-ai/cordis-plugin-loader": "^1.0.2", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-agent-default-model": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-headless/node_modules/commander": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", - "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==", - "license": "MIT", - "engines": { - "node": ">=22.12.0" - } - }, - "node_modules/@deepseek-ai/dsh-home-paths": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-home-paths/-/dsh-home-paths-0.1.0-rc.6.tgz", - "integrity": "sha512-gIiUBmqB3L8inFr+hvjZv2/i6EVJOHIHCHg7bBFVhcl4HDK94+8wUCXTLGy80tcuISzIQiIaLuJq/NhSmV9Amw==", + "node_modules/@deepseek-ai/dsh-client-web-react": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-web-react/-/dsh-client-web-react-0.1.0-rc.7.tgz", + "integrity": "sha512-aw8s6RgMVJNNPTHB4TzVmKsuROp9yZDMKKXsMEEha8CESlHhCF1c+qxLsjAcilwY5CYCwin2T/3lot88k+ITiw==", "license": "MIT", + "dependencies": { + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "react": "^18.2.0", + "use-sync-external-store": "1.2.0" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-host-apiproxy": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-apiproxy/-/dsh-host-apiproxy-0.1.0-rc.6.tgz", - "integrity": "sha512-sydiTngUEtvCyUwtCpXusQXVuiq0Kv7t2Axe8UKbimhhQLktnfhAmsEF+QHFTG5zcnxAuuigPiUTeY0Cr8+CnA==", - "license": "MIT", - "dependencies": { - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-agent-default-model": "^0.1.0-rc.6", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6", - "@deepseek-ai/dsh-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-directory-picker": "^0.1.0-rc.6", - "@deepseek-ai/dsh-jobs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-native-command": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection-cache": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-query": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-title": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-skill": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6", - "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.6", - "@deepseek-ai/dsh-workspace": "^0.1.0-rc.6", - "@deepseek-ai/schemastery": "^3.18.1", - "fflate": "^0.8.2", - "zod": "^4.4.3" + "node_modules/@deepseek-ai/dsh-client-web-react/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" }, - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.6", - "@deepseek-ai/dsh-cordis-host-runner": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@deepseek-ai/dsh-host-apiproxy/node_modules/fflate": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", - "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", - "license": "MIT" - }, - "node_modules/@deepseek-ai/dsh-host-directory-picker": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-directory-picker/-/dsh-host-directory-picker-0.1.0-rc.6.tgz", - "integrity": "sha512-1XafIFC2H5sPi720ATQWgCTgjZum7ZUng6H+z9uDMOhkKLFO7X2n8D2ddmGuQINnKV7sjlw0Q1uBr/sFiY4Bqw==", + "node_modules/@deepseek-ai/dsh-client-web-react/node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", "license": "MIT", "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@deepseek-ai/dsh-host-directory-picker-browse": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-directory-picker-browse/-/dsh-host-directory-picker-browse-0.1.0-rc.6.tgz", - "integrity": "sha512-NAQOaGoEEpC0XEV5k6He/8t9UVy9EM/fq8a40dy9XjgvcCePelfOZOLaN9lnIp4UAY+CbVFglhzsuFF5M2rueg==", + "node_modules/@deepseek-ai/dsh-client-web/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-host-directory-picker": "^0.1.0-rc.6", - "@deepseek-ai/schemastery": "^3.18.1" + "loose-envify": "^1.1.0" }, - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@deepseek-ai/dsh-host-directory-picker-native": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-directory-picker-native/-/dsh-host-directory-picker-native-0.1.0-rc.6.tgz", - "integrity": "sha512-mr93KFRWfZ5HeAOT7N9IUYCzYsc7/CwG+tx76ozXL5znyUFS7OJfTJovcfglQv+GD+0wftX/N/857iVDsxr2cQ==", + "node_modules/@deepseek-ai/dsh-client-web/node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-host-directory-picker": "^0.1.0-rc.6", - "@deepseek-ai/dsh-native-command": "^0.1.0-rc.6", - "koffi": "^3.1.0" + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" }, "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "react": "^18.3.1" } }, - "node_modules/@deepseek-ai/dsh-host-frontend-static": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-frontend-static/-/dsh-host-frontend-static-0.1.0-rc.6.tgz", - "integrity": "sha512-WrUEn7jCykwbn+weYWbZrrWWOf4VGNsdv9m88AZK9+gX39EqsUU1mZhTMVlw8Pjea11/W091sszyyPDgK8HJNw==", + "node_modules/@deepseek-ai/dsh-client-web/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "loose-envify": "^1.1.0" } }, - "node_modules/@deepseek-ai/dsh-host-plugin-inventory": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-plugin-inventory/-/dsh-host-plugin-inventory-0.1.0-rc.6.tgz", - "integrity": "sha512-FObaWsBb1Wlyg5/UH7nSNRUCjslZmUEOO90E2g01asefzXICmvY9rDsaAHzOvuAljX9+IDWn678kDJBK+3OFkA==", + "node_modules/@deepseek-ai/dsh-cmdline": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-cmdline/-/dsh-cmdline-0.1.0-rc.7.tgz", + "integrity": "sha512-jNY9OOSpcH3csXqCwj8MMinByo42aUVIEauTSK1tNIOn6h6q0Y7SPu1ObIo5i3k0Khh/OWIiBTS1SbBlxcJHjw==", "license": "MIT", - "dependencies": { - "zod": "^4.4.3" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", "@deepseek-ai/cordis-plugin-loader": "^1.0.2", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-host-webserver": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-webserver/-/dsh-host-webserver-0.1.0-rc.6.tgz", - "integrity": "sha512-Zod2L+JPss8uGuVMc+5VMQYidCyOZWV8H7LsvyzVR73dhB9zIIm4smuRwuHrk6ss+F/QWmHWV+/yUgqbBJTLjA==", + "node_modules/@deepseek-ai/dsh-code-runtime": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-code-runtime/-/dsh-code-runtime-0.1.0-rc.7.tgz", + "integrity": "sha512-vzW82eU4so0qJQ/XS7BGBUSguJMAgEOW3GaJJW0g+W5ysBJg+UC/Jjo1Np8mPjSpjjl4eoyXpshJzrwjoxCpRg==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-invariants": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-invariants/-/dsh-invariants-0.1.0-rc.6.tgz", - "integrity": "sha512-WfEfOi99a4cpOugRAHTBSTnesLieu3ist1q9PXDXFBHX++K1rAl9+sB7YrdnbB8LH0UOY532gS9xJUYU6w0SLw==", + "node_modules/@deepseek-ai/dsh-code-runtime-worker-thread": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-code-runtime-worker-thread/-/dsh-code-runtime-worker-thread-0.1.0-rc.7.tgz", + "integrity": "sha512-CEGOMie1k733yc6TCSZuAtgbcs5H2QPO9wZnDnkx/kqaj3W+cEZGz6zZvljYNMWspNpomDTqOqpcB4ZAOI/K3g==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1" + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-code-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-jobs": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-jobs/-/dsh-jobs-0.1.0-rc.6.tgz", - "integrity": "sha512-fmyvSOVsNObmRnciuH57ZntuCSb0gflRleCeQx1ToGHRoGrR4Ndnstx33SuIXUQt6OSUhD2w2WKQTReXogpnSQ==", + "node_modules/@deepseek-ai/dsh-command-compact": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-command-compact/-/dsh-command-compact-0.1.0-rc.7.tgz", + "integrity": "sha512-zDBNVlCAwnieffyctzqZ7hUGLJqyTjqvtCEvzSNckmd2owyuYNPDIeFu4NTo/xN8Z/TISiuGbgA0wnIBCIsNtQ==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6" + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-compaction": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-jobs-local": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-jobs-local/-/dsh-jobs-local-0.1.0-rc.6.tgz", - "integrity": "sha512-vnCcHPjvXLQq2i80No61oKF/165+OvEC2iUBmVTxl6ka87yNECwYf4nrspHKqP9HbVWndtNP0lGgrnz7bo0XCw==", + "node_modules/@deepseek-ai/dsh-command-feedback": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-command-feedback/-/dsh-command-feedback-0.1.0-rc.7.tgz", + "integrity": "sha512-DM/EGrz8vvgRJSxV4UAWtyJpxFi1v8gWkj/iT9q5iGex0zNdDO4Ml0/u/e73brmN3bsGyubsdUuIdkGsl8n/Ig==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-jobs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6" + "@deepseek-ai/dsh-anonymous-user-id": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-telemetry": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-launch-environment": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-launch-environment/-/dsh-launch-environment-0.1.0-rc.6.tgz", - "integrity": "sha512-tTRJ1464PJUDe1Em1qq0mfdgGREzGGWo3JSqP6xeYDoX+MRXVP9/ChsZ5k6VBMjARAxw0HGBf7WR6VcupHbMZg==", + "node_modules/@deepseek-ai/dsh-command-goal": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-command-goal/-/dsh-command-goal-0.1.0-rc.7.tgz", + "integrity": "sha512-ezuYaKmblRkOaFLUpzrTK9DiTrbES2lBtmkzo/Fg4UteDHLBVEaBgoips0J15gXJm8mE6o3LHhsgmGCIdNepKQ==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-llm": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-llm/-/dsh-llm-0.1.0-rc.6.tgz", - "integrity": "sha512-kuFGC8bHlzGTwlRxQhXjf3CYWl8M4NzH+EYIkrW8rri4iMc9W53xrdvkil5No/DUlMm8g1u7GdeiWYFy0TMvtA==", + "node_modules/@deepseek-ai/dsh-commands": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-commands/-/dsh-commands-0.1.0-rc.7.tgz", + "integrity": "sha512-SYrQpJZQ4fvfyfw3IJ5j0goUiOFZb1ZhcANgUp99HVlhhN/l1oEOAvEZL1efaSE7KIG6qp4JEn7iLtNdo8+mEA==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" + "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-llm-deepseek": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-llm-deepseek/-/dsh-llm-deepseek-0.1.0-rc.6.tgz", - "integrity": "sha512-Md9ik1e8tmrKcL2aRpif8qdndl9TObbfHodj6CeVlkrL9y+PEghVPZqOYtnuRcv4/e0nVSIJsUw2gFvaL+T40Q==", + "node_modules/@deepseek-ai/dsh-compaction": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-compaction/-/dsh-compaction-0.1.0-rc.7.tgz", + "integrity": "sha512-9SDsfhfOzriMw4AF/md6MDOjl+YOwtE9BKFwunCGzfyWZnOUljoKEZxjtU0w1sIESSAjJnTicqb2NBOAIV9YQQ==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1", - "eventsource-parser": "^3.1.0" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-anonymous-user-id": "^0.1.0-rc.6", - "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-llm-pi-ai": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-llm-pi-ai/-/dsh-llm-pi-ai-0.1.0-rc.6.tgz", - "integrity": "sha512-5RvzkpVCYLg9A3IGdm04px7XOaF/xikuMLe2toBY4A0qtJraXiZtUN1QBOL9i6u7DTOLG9oHP/USsbWRpyI+1Q==", + "node_modules/@deepseek-ai/dsh-compaction-basic": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-compaction-basic/-/dsh-compaction-basic-0.1.0-rc.7.tgz", + "integrity": "sha512-c4bkTsJMKeDDgN3F9GBvEJCnsaLyl3I+uXb42rBPhOzH85bG2x55fMO9lBhtpvE5h5JUOP/tBMtTAW2OCe10Mg==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1", - "@earendil-works/pi-ai": "^0.82.1" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-compaction": "^0.1.0-rc.7", + "@deepseek-ai/dsh-compaction-tool-result-pruner": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.7" + }, + "peerDependenciesMeta": { + "@deepseek-ai/dsh-compaction-tool-result-pruner": { + "optional": true + } } }, - "node_modules/@deepseek-ai/dsh-llm-retry": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-llm-retry/-/dsh-llm-retry-0.1.0-rc.6.tgz", - "integrity": "sha512-HdjBWcQ6spwA8B5dScRhndLQNiKoQTkq36O+kmJ80B9V4z08K5XrJwAInH9cCxJ91CqNzx/sxCdDds0oZDH1Pw==", + "node_modules/@deepseek-ai/dsh-compaction-tool-result-pruner": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-compaction-tool-result-pruner/-/dsh-compaction-tool-result-pruner-0.1.0-rc.7.tgz", + "integrity": "sha512-W4SbSgHlAhCB6ZXjr1/BdRiTn1F1x5nZdCY+0AazHoJY9FDACN0hUd6Rlkc40n3x0BHxXN/sZFDHCtT/26Fw+Q==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6" + "@deepseek-ai/dsh-compaction": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-mcp-client": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-mcp-client/-/dsh-mcp-client-0.1.0-rc.6.tgz", - "integrity": "sha512-seBl0SLn308CbPwGVSm2BM3HECaNln3mbpcdHtw4DjnI5mZRILxC6wgKXAtYcNWKxMY1FaiwFWcgQ2+HHCQ7PQ==", + "node_modules/@deepseek-ai/dsh-cordis-client-runner": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-cordis-client-runner/-/dsh-cordis-client-runner-0.1.0-rc.7.tgz", + "integrity": "sha512-D8A93lu2T1/QfT9yRErxI3ptgTyGwJUIorzf5WQe4+3/buv1LUKCXJHabm0fknaDiQdUOge+MjdZDNV2SoYGvw==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1", - "@modelcontextprotocol/sdk": "^1.12.0", - "zod": "^4.4.3" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/cordis-plugin-loader": "^1.0.2", + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-modules": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-theme": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-message-feedback": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-message-feedback/-/dsh-message-feedback-0.1.0-rc.6.tgz", - "integrity": "sha512-yqI49BjgVODSPQex7KdRhc4fUquvhifRYe73QP3w6snXYB6058tH8WQk2Yx+m1APi60dLEAZ1AJibRA4oCo6WQ==", + "node_modules/@deepseek-ai/dsh-cordis-host-runner": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-cordis-host-runner/-/dsh-cordis-host-runner-0.1.0-rc.7.tgz", + "integrity": "sha512-A7R39cSNsLwjm+P54bUFBUd5+YbdyKkC5cLQqYt12STt0Z06az10Qt5rsL25rnWkxW7x7Ql0wVA83tOmO2oy0g==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1", @@ -2548,917 +2735,785 @@ }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6", - "@deepseek-ai/dsh-storage-domain": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6" - } - }, - "node_modules/@deepseek-ai/dsh-native-command": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-native-command/-/dsh-native-command-0.1.0-rc.6.tgz", - "integrity": "sha512-b2AwcAlNmTDPho/dMQ5wOicEwkDG1FSNSCUvluFp9JBbM8AqUMI3rVuOGFPIT0BEOi+ehpW/if0BZ2S35FSEwA==", - "license": "MIT", - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-output-retention": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-output-retention/-/dsh-output-retention-0.1.0-rc.6.tgz", - "integrity": "sha512-3TQJxGqjotWrvNKI+Da8nIDjzpKZEGpImeMBp7EklfO0CDbiXA5B0Ms39zBniWkWr1lvbm2iJiYERY5uDeP6og==", + "node_modules/@deepseek-ai/dsh-credentials": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-credentials/-/dsh-credentials-0.1.0-rc.7.tgz", + "integrity": "sha512-24oY36x90GN3QG2BASlryjzsO5eLA1U9vsvH1tPtBRJ1pBC6JqnW2v0SfDI/pcMT0ZbWo0uEATiik8rrv6xRpA==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-permission-presets": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-permission-presets/-/dsh-permission-presets-0.1.0-rc.6.tgz", - "integrity": "sha512-enFyuj9mTN44sMAwLoiommngZSY5yp09JtKOKT541lycacUotuvlTj9W+KJ0whtIOuYQ1jdIzYnyFGnH0J10SQ==", + "node_modules/@deepseek-ai/dsh-credentials-local": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-credentials-local/-/dsh-credentials-local-0.1.0-rc.7.tgz", + "integrity": "sha512-3HB4nHXzR3HreJE4MfVSX45Am1/JiKFSDOYmrnyX7kK3Hvb9qH1J2Mm4gCzNislCemhZ+wlYQgevrvyH1L1PvQ==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1", - "zod": "^4.4.3" + "chokidar": "^4.0.3", + "yaml": "^2.9.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell": "^0.1.0-rc.6", - "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6" + "@deepseek-ai/dsh-atomic-write": "^0.1.0-rc.7", + "@deepseek-ai/dsh-credentials": "^0.1.0-rc.7", + "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-persona": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-persona/-/dsh-persona-0.1.0-rc.6.tgz", - "integrity": "sha512-rY5AVVopkS9vJl+hGHGQP0nSwzxawubRvEKo4JZmGK7bKZlvevRvj8bd2wLNhTx54jppz+u0iEUq/fqG5k9Mvg==", + "node_modules/@deepseek-ai/dsh-fs": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-fs/-/dsh-fs-0.1.0-rc.7.tgz", + "integrity": "sha512-l4jEcfjrV7hWTQo6sH0oXntg4pz1nVuDXRcprps6NhZ0/OOer/9SzUx7J9aLnLeX9XDtExXsFbxkXW5Js3ZFwg==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-plan-mode": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-plan-mode/-/dsh-plan-mode-0.1.0-rc.6.tgz", - "integrity": "sha512-kabVmxbdjLSJkY3bM0s+VuDBuIhPNvKdW8CHXz/UmpQfm2KNfrS46+EEgDgRnz2xFxfAGLcV9KFm0iDEksE22A==", + "node_modules/@deepseek-ai/dsh-fs-local": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-fs-local/-/dsh-fs-local-0.1.0-rc.7.tgz", + "integrity": "sha512-gbiH8xBrBw/1iRM3MLwI9zlFqLRg+1d+hNs8Etdn240xjWPuFdv5Hjg+eu4V5I+lU3M/lZieahEUpwYRScGuVw==", "license": "MIT", "dependencies": { - "zod": "^4.4.3" + "@deepseek-ai/schemastery": "^3.18.1", + "koffi": "^3.1.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.6" - }, - "peerDependenciesMeta": { - "@deepseek-ai/dsh-commands": { - "optional": true - } + "@deepseek-ai/dsh-fs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-pwsh-local": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-pwsh-local/-/dsh-pwsh-local-0.1.0-rc.6.tgz", - "integrity": "sha512-TtITwtlDvxyXDE4HKJW9R6uWKU5kr72Y+8JHYV3Kj/HPAzQqwbVo/2e9wvq7H4t5Soo8K+KG5ZqBpMmpp+FAWg==", + "node_modules/@deepseek-ai/dsh-fs-observation-policy": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-fs-observation-policy/-/dsh-fs-observation-policy-0.1.0-rc.7.tgz", + "integrity": "sha512-UbLBBWzUfBHAaZ6xGY/pPlIemGKz2iPoiCfmMkFQeLXVlLzeMrsTY4mvdx5ywu63tKYHvPpHHGdXMRFHqrTBvw==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6" + "@deepseek-ai/dsh-fs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-pwsh-sandbox": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-pwsh-sandbox/-/dsh-pwsh-sandbox-0.1.0-rc.6.tgz", - "integrity": "sha512-UNVwsEyakQgjKYuWIIb1Xm03RHMtm0NdwYORgtBgVb2FV20KipBt1MhfHhBPT4FPPWIKjM94Vph9ZOhO5cCOeQ==", + "node_modules/@deepseek-ai/dsh-fs-sandbox": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-fs-sandbox/-/dsh-fs-sandbox-0.1.0-rc.7.tgz", + "integrity": "sha512-QMv2QbqVAKkFAmIIPFmW8cvjk8U9T4ZEVsoPdbanw5Enrg3qEYZUmii9WBkAxNtQhG5MRUf5Tg8jDkZqPScYrQ==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-pwsh-local": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell": "^0.1.0-rc.6" + "@deepseek-ai/dsh-fs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-fs-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-repeat-tool-reminder": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-repeat-tool-reminder/-/dsh-repeat-tool-reminder-0.1.0-rc.6.tgz", - "integrity": "sha512-iN9FjWXL8e/IrxTFmybTKDqtB6obV5jt6ao2I3EQWOhQ0GVfXBuz1SY6Yx7gILQXWsCUeGRu1ltLyywdubpJcw==", + "node_modules/@deepseek-ai/dsh-goal": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-goal/-/dsh-goal-0.1.0-rc.7.tgz", + "integrity": "sha512-/pI2o0YcP21ReT+OQx7aA8SyUsnuEHxTQtMbu3DvN9ChvaFeptCTXGvHWocwVtzEEi48mdvAXF4Mx0Ptj1LJYA==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" + "@deepseek-ai/schemastery": "^3.18.1", + "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-sandbox": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-sandbox/-/dsh-sandbox-0.1.0-rc.6.tgz", - "integrity": "sha512-SLZjuivQQKHTx4H7xlsjraEGGMIEA8BYOwvlm/9uZBrBrlttMU+d8Ne6QYpDcOwIEubL8mvrWRg8j3rtY3lVyA==", + "node_modules/@deepseek-ai/dsh-goal-round-driver": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-goal-round-driver/-/dsh-goal-round-driver-0.1.0-rc.7.tgz", + "integrity": "sha512-PWIaza45vFqqrf8bYyw5tPgEXRqLliHqAn3uKEwui8b1hM6UHJtApq1jX83PO4gtJZs/yAnRK6LCbaS5VJBC9A==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-sandbox-local": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-sandbox-local/-/dsh-sandbox-local-0.1.0-rc.6.tgz", - "integrity": "sha512-W0CehRbWqAaHAYFw24wvYLlGxxJr2OlQQlFH/p1QbeNKtHzZ+6pgjksyFotgHdzOycNnVoBjb92RbQPfJhJZ9A==", + "node_modules/@deepseek-ai/dsh-headless": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-headless/-/dsh-headless-0.1.0-rc.7.tgz", + "integrity": "sha512-EKn/wrMKgqxPUPwLgoTGk3BY8vFcYSYBWfXxnc8ZOKiH2pmprKnzm89AcOkbERNBJzPySQEsDdSoWwWJ2Mut4w==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-sandbox-windows-acl": "^0.1.0-rc.6", - "@deepseek-ai/node-addon-landlock-run": "^0.1.1", - "@deepseek-ai/schemastery": "^3.18.1" + "@deepseek-ai/dsh-cmdline": "^0.1.0-rc.7", + "@deepseek-ai/dsh-code-runtime-worker-thread": "^0.1.0-rc.7", + "@deepseek-ai/schemastery": "^3.18.1", + "commander": "^15.0.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6" + "@deepseek-ai/cordis-plugin-loader": "^1.0.2", + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-agent-default-model": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-sandbox-policy": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-sandbox-policy/-/dsh-sandbox-policy-0.1.0-rc.6.tgz", - "integrity": "sha512-XEB7+pJZVPWmZXv27EX/4V/1noVLUF5ZHyy3EY5tC4XtEyayWKtvHL4y9OTLIYhlU4Ualv5ag8s5ueGGq3ID8Q==", + "node_modules/@deepseek-ai/dsh-home-paths": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-home-paths/-/dsh-home-paths-0.1.0-rc.7.tgz", + "integrity": "sha512-9Bu0eAbPw/FfCNpiX9hvyP5wedMUUQBc2sVTtU+xtH27/iUPxXoamFtBt3ydBJUeuVhja/leuhJ/d3MRhXO9fQ==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-sandbox-windows-acl": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-sandbox-windows-acl/-/dsh-sandbox-windows-acl-0.1.0-rc.6.tgz", - "integrity": "sha512-/L1TUOQMsJe8B2v1pJpTaLwkvMQIwrjlUg4+6yx2flU7AyycjFzlKwmzQQzo19/evkiqO88mLgod3FiLhqxEvA==", - "license": "MIT", - "dependencies": { - "koffi": "^3.1.0" + "node_modules/@deepseek-ai/dsh-host-apiproxy": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-apiproxy/-/dsh-host-apiproxy-0.1.0-rc.7.tgz", + "integrity": "sha512-oBCIJzzvVXijtxAPqSlQUlYTywEmkn3JEpMB2PM8W4UafnxNhqvDh8ikGE7/1y6KWoFUS4jHGwerUzyp3C6oWw==", + "license": "MIT", + "dependencies": { + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-agent-default-model": "^0.1.0-rc.7", + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-attachment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-credentials": "^0.1.0-rc.7", + "@deepseek-ai/dsh-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-directory-picker": "^0.1.0-rc.7", + "@deepseek-ai/dsh-jobs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-native-command": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection-cache": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-query": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-title": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-skill": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.7", + "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.7", + "@deepseek-ai/dsh-workspace": "^0.1.0-rc.7", + "@deepseek-ai/schemastery": "^3.18.1", + "fflate": "^0.8.2", + "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.7", + "@deepseek-ai/dsh-cordis-host-runner": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-schedule": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-schedule/-/dsh-schedule-0.1.0-rc.6.tgz", - "integrity": "sha512-83p0mxkMUWwRZkazWICbD1SZO6hKwFVb9W3adDSR4wmojJQYTnawopnwTJn+Sij0V+gvvA4wTcL4rwDgbawDHA==", - "license": "MIT", - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" - } - }, - "node_modules/@deepseek-ai/dsh-scope": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-scope/-/dsh-scope-0.1.0-rc.6.tgz", - "integrity": "sha512-UlDLV4syLoJinNg9imhXrSAHrdaTa5Ff8gg46rzjFJGPUOhAk3DZff0hryT5OhrBi0A5Tj92qVpg2pRVvxnUzQ==", - "license": "MIT", - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" - } + "node_modules/@deepseek-ai/dsh-host-apiproxy/node_modules/fflate": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", + "license": "MIT" }, - "node_modules/@deepseek-ai/dsh-session": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session/-/dsh-session-0.1.0-rc.6.tgz", - "integrity": "sha512-8tu8I6VWC7050GAUXWhcEWQw4pakALQc8TlhKr52m7Y4+kIKeNt3FBgP86PaGPBtpK0p5zUPRQNkFpzZbBdxyw==", + "node_modules/@deepseek-ai/dsh-host-directory-picker": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-directory-picker/-/dsh-host-directory-picker-0.1.0-rc.7.tgz", + "integrity": "sha512-CamVZ4wOjGcgzOiRFQtG0J0hy4EY3nXJBRFs0S397+H7b9eJUTtaMdOxP5w7VhMQ0Aq2ND7gpadwIcFaqINsMw==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-checkpoint-policy": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-checkpoint-policy/-/dsh-session-checkpoint-policy-0.1.0-rc.6.tgz", - "integrity": "sha512-wdWNyS/95wI3QB9SHeeeQ9HDIWeFQKInI54Wqlw35H+bGGjGZE92nx9QiqiiosoxHedQFBdA0TKgON4EIoxCgg==", + "node_modules/@deepseek-ai/dsh-host-directory-picker-auto": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-directory-picker-auto/-/dsh-host-directory-picker-auto-0.1.0-rc.7.tgz", + "integrity": "sha512-QFuI5xGvVQAtbgN5xEZddM9+s5/2GWem8Gvq5hQpi1faUPyY/GS34B3lpuui0khSyS2NTa5GUXtYhDN1qZTVjw==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/cordis-plugin-loader": "^1.0.2", + "@deepseek-ai/dsh-client-ui-directory-picker-browse": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-directory-picker-native": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-directory-picker-browse": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-directory-picker-native": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-persistence": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-persistence/-/dsh-session-persistence-0.1.0-rc.6.tgz", - "integrity": "sha512-AbNBe+IYCbZqSHqOACVdj8QTynm2HZ0cThrEuI6nGMtlWLYLx6lzZ1rgO/56Av9mIScjyTBGJAIKhEYaMTBG9g==", + "node_modules/@deepseek-ai/dsh-host-directory-picker-browse": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-directory-picker-browse/-/dsh-host-directory-picker-browse-0.1.0-rc.7.tgz", + "integrity": "sha512-yVHhAPK61gurrgys+xKia3RCr2OlwFCSb/XGzSDuzkVtAmqtG03oWTvnMiNpRKUyGCRFdgN0TP3QDg46rRlQ/g==", "license": "MIT", + "dependencies": { + "@deepseek-ai/dsh-host-directory-picker": "^0.1.0-rc.7", + "@deepseek-ai/schemastery": "^3.18.1" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-persistence-jsonl": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-persistence-jsonl/-/dsh-session-persistence-jsonl-0.1.0-rc.6.tgz", - "integrity": "sha512-US9Q4b5CZJPRRqa/M+WESL5VAOLjfYWjdzb3TQ/7zmpR4/+EQWCOFA9CtDSMh4t1oFOQBjz2+YJJcGu59MKHDA==", + "node_modules/@deepseek-ai/dsh-host-directory-picker-native": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-directory-picker-native/-/dsh-host-directory-picker-native-0.1.0-rc.7.tgz", + "integrity": "sha512-CMHnPXL0oqwCnwt4TVRBAUfM4GNwkcZ1yURLlUo11ISBYh11LbOCXri3LoDjXzdCaZ21CWEKl25sZHnHnQ2GWg==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1", + "@deepseek-ai/dsh-host-directory-picker": "^0.1.0-rc.7", + "@deepseek-ai/dsh-native-command": "^0.1.0-rc.7", "koffi": "^3.1.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-projection": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-projection/-/dsh-session-projection-0.1.0-rc.6.tgz", - "integrity": "sha512-DYLALBPdEI1LZjJ4B6rdGdGY4gy+iR2+5Xh2xJoAGa/pTyN5Z55TNfvuMJrmeRBjAuDXNUQpmURbvos5rJ4veg==", + "node_modules/@deepseek-ai/dsh-host-frontend-static": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-frontend-static/-/dsh-host-frontend-static-0.1.0-rc.7.tgz", + "integrity": "sha512-qSKYgM2W5EV8mE5J3OEujTY4z7mRwPBCRK3hQrl8vm4IAuSf0vfv2qrS9rpgU2SUrpHlQCqsu44bp8OPX+XeUg==", "license": "MIT", "dependencies": { - "zod": "^4.4.3" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6" + "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-projection-cache": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-projection-cache/-/dsh-session-projection-cache-0.1.0-rc.6.tgz", - "integrity": "sha512-Fqyd5aN7MvIiRMWxs0Q4dWmSMKLqdWNk5U97EFdeWY3Ol5bk8SSFfFrij4941B5y4K2f7C0mE9nLSQ3mfL2KHg==", + "node_modules/@deepseek-ai/dsh-host-plugin-inventory": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-plugin-inventory/-/dsh-host-plugin-inventory-0.1.0-rc.7.tgz", + "integrity": "sha512-B8ITfMnBAdgkkuvoMrBdVgydhsCYGnP8XIGXIouOQyT9/eWbD3WqO76XG+u+e2G36ACXu2NaIxsRh3ijzyorwg==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1", "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-storage-domain": "^0.1.0-rc.6" + "@deepseek-ai/cordis-plugin-loader": "^1.0.2", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-query": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-query/-/dsh-session-query-0.1.0-rc.6.tgz", - "integrity": "sha512-bGzRrZnWuXDUtAmwkRxT74Nuc4PLQJmJ4IeGgSSTIGJ9JQCNbvVjr4ZWDWg+D/PvbZwh9mpYJspDZdUP42eWAA==", + "node_modules/@deepseek-ai/dsh-host-webserver": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-webserver/-/dsh-host-webserver-0.1.0-rc.7.tgz", + "integrity": "sha512-ip6HeN9YpWJXgWKAWsL3JUrI8j+MHEvbQ/m3U5ubP/Pc0AQ9x+6xZ/nYe+22112I12rihiwb85ykFwFfx0QbKQ==", "license": "MIT", + "dependencies": { + "@deepseek-ai/schemastery": "^3.18.1" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-title": "^0.1.0-rc.6" - }, - "peerDependenciesMeta": { - "@deepseek-ai/dsh-session-persistence": { - "optional": true - } + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-query-sqlite": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-query-sqlite/-/dsh-session-query-sqlite-0.1.0-rc.6.tgz", - "integrity": "sha512-sbeOPAAJetQbvgyFB7zVANSlJPjNgEGxiixin/DI9TcXHcUqq3nrPgS+1iI+WJjD6/zhHdIticeEayuWXtORdA==", + "node_modules/@deepseek-ai/dsh-invariants": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-invariants/-/dsh-invariants-0.1.0-rc.7.tgz", + "integrity": "sha512-PnO1F4aZGUmqZPyuPJpBUfQ4DZmjCGCNGr0yuN2iURTP/e6h0kGnTNTYgR2NqMvAtpP66WNiHhvH2LMqumk1+A==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-query": "^0.1.0-rc.6" - }, - "peerDependenciesMeta": { - "@deepseek-ai/dsh-session-persistence": { - "optional": true - } + "@deepseek-ai/cordis": "^4.0.1" } }, - "node_modules/@deepseek-ai/dsh-session-reference": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-reference/-/dsh-session-reference-0.1.0-rc.6.tgz", - "integrity": "sha512-ubnfGbTBy/NnVnY8RXhTTXGO2Ga21Ze/1O9PBCzQk5wYfTqa2SUtx7t4MiJ1rVsDZMQ4YMpehqqGJFXf/z2dhQ==", + "node_modules/@deepseek-ai/dsh-jobs": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-jobs/-/dsh-jobs-0.1.0-rc.7.tgz", + "integrity": "sha512-+omM89dEsaiAL1XtsSTMmRF46POp5g25Qs5KVj+Zfrk7whlXjLXwFiaukt/htdVdHIOM51qM+tCleqlHOU0Chw==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-compaction": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-output-retention": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-query": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-stats": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-stats/-/dsh-session-stats-0.1.0-rc.6.tgz", - "integrity": "sha512-B2Rwp1klSl7DmRpViPnuIlmlPgsARdxqRpsz7MwoXTC1oKYipWgoCw8JFOsDxVj8Rno1o1kWVjVAM10I/FC1aw==", + "node_modules/@deepseek-ai/dsh-jobs-local": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-jobs-local/-/dsh-jobs-local-0.1.0-rc.7.tgz", + "integrity": "sha512-DAC8i+sshAkXPI8IcrUp5O6cOOkLLsKsD7mAcorFFbQjcPVBLdeRmtko3E1J9Jmf79IjoAvKVE+J+y84km9yKA==", "license": "MIT", "dependencies": { - "zod": "^4.4.3" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-jobs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-telemetry": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-telemetry/-/dsh-session-telemetry-0.1.0-rc.6.tgz", - "integrity": "sha512-x3t7lu+SLHvxhmOlocNyOwcj9t4MxUkzh7QyOh/YSMvWgojSOhNdnKcjWq4pE9PxFXBWMDpN3bLNvtk5jFA/+w==", + "node_modules/@deepseek-ai/dsh-launch-environment": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-launch-environment/-/dsh-launch-environment-0.1.0-rc.7.tgz", + "integrity": "sha512-ATVyi47hyAWFINOxi8TGurRF8rShW/WzqWKqjxEQU5gLZbWtAMgkpAc+hwlyo/lXytGaj5cMXyzeyjpD6URHFg==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-telemetry-otel": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-telemetry-otel/-/dsh-session-telemetry-otel-0.1.0-rc.6.tgz", - "integrity": "sha512-e2tbkXm3wh33kkKNLfpM5q019DDG4Bpvlg1UyqZq3mffOP5O3e696mZA+sC0RhKB0xfLWMaAZq9n3WN2qtmWdw==", + "node_modules/@deepseek-ai/dsh-llm": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-llm/-/dsh-llm-0.1.0-rc.7.tgz", + "integrity": "sha512-VaB9kQ8XOA+R5jtsWf92QMc1WpaatEAFUvQePGUYrzQ7Z86b9VhQQzmchh5VmknT4oRSSdn0re5tReCvfcYNXQ==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1", - "@opentelemetry/api": "^1.9.1", - "@opentelemetry/api-logs": "^0.220.0", - "@opentelemetry/exporter-logs-otlp-http": "^0.220.0", - "@opentelemetry/otlp-exporter-base": "^0.220.0", - "@opentelemetry/resources": "^2.9.0", - "@opentelemetry/sdk-logs": "^0.220.0" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-anonymous-user-id": "^0.1.0-rc.6", - "@deepseek-ai/dsh-command-feedback": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-telemetry": "^0.1.0-rc.6" + "@deepseek-ai/dsh-attachment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-title": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-title/-/dsh-session-title-0.1.0-rc.6.tgz", - "integrity": "sha512-RHV1ujuomvQB63HPI/n25c2/2It5XQ7zNQKozSqYOPQw7AIr16PT9iFqC7sCQ4l2gAY5GI3FbI1cQgHzjHNOag==", + "node_modules/@deepseek-ai/dsh-llm-deepseek": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-llm-deepseek/-/dsh-llm-deepseek-0.1.0-rc.7.tgz", + "integrity": "sha512-cWNbBF+LeFrexht5V8cFeo4Kb0KeFaQWtemPJeTHRcijafq4OuQvgJEPx1IyelzzX6vctLQGSlmvvCNesLvIcw==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1", - "zod": "^4.4.3" + "eventsource-parser": "^3.1.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6" + "@deepseek-ai/dsh-anonymous-user-id": "^0.1.0-rc.7", + "@deepseek-ai/dsh-credentials": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-title-first-prompt-llm": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-title-first-prompt-llm/-/dsh-session-title-first-prompt-llm-0.1.0-rc.6.tgz", - "integrity": "sha512-eYta0tVmNnivANde4R2G9NW4V9w1fq9KYod7kZ4YeuVu3rjObCmlXKOOJiGwRis21PC5YVIhaPxszM+V35zizA==", + "node_modules/@deepseek-ai/dsh-llm-pi-ai": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-llm-pi-ai/-/dsh-llm-pi-ai-0.1.0-rc.7.tgz", + "integrity": "sha512-8sZuvgylK9ZKQmZtUU4z3DVBcM4Q4SH4OWo4qeOahLOsteT9NdIwZFer6f0QwqH6DjXIqz2Gq+XtntYXznGZPw==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" + "@deepseek-ai/schemastery": "^3.18.1", + "@earendil-works/pi-ai": "^0.82.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-title": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-title-llm": "^0.1.0-rc.6" + "@deepseek-ai/dsh-attachment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-credentials": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-session-title-llm": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-title-llm/-/dsh-session-title-llm-0.1.0-rc.6.tgz", - "integrity": "sha512-BiqsXDSbyZbQ1XtLhKpILKdnDgZaQKWopZpSQW+Cy6i0wozMJ/xeO+oCWEFn0rQtsgBY6b+rKVKUW4wc7u9Ydg==", + "node_modules/@deepseek-ai/dsh-llm-retry": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-llm-retry/-/dsh-llm-retry-0.1.0-rc.7.tgz", + "integrity": "sha512-yyn5Yqth6vdScgmcYDF7L3a1jbfcu2y205HyTx9d84H+eU+h9m8k0Mc+1l8VCJbv9GILPCvoijP8wFTPDas7gQ==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-title": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-settings": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-settings/-/dsh-settings-0.1.0-rc.6.tgz", - "integrity": "sha512-5ZlH2FNRU0kkdcCoEJohvdb2fiNnxM+iZqN3icbR3WQbMm8RPRrXlZlps5YUaQKPRbNRHA2LkOXW998QRlhHcA==", - "license": "MIT", - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/schemastery": "^3.18.1" - } - }, - "node_modules/@deepseek-ai/dsh-settings-file": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-settings-file/-/dsh-settings-file-0.1.0-rc.6.tgz", - "integrity": "sha512-OgwvP/dTlrWd8MRhjJbeolMJHDdyjLtvd+gS3z2mvCGDmNkkf0RxcB/8o2uoqe97iuklTWmy6cCws6dlmnDL+g==", + "node_modules/@deepseek-ai/dsh-mcp-client": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-mcp-client/-/dsh-mcp-client-0.1.0-rc.7.tgz", + "integrity": "sha512-hjdki2TTXfyZMJuddOVXV0lEhZjdku2aoPagVKV4TOhqz3jDJE0mQds87mtDOI9J4pyRGWfYXky6HN9Bi/usgg==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1", - "chokidar": "^4.0.3", - "yaml": "^2.9.0" + "@modelcontextprotocol/sdk": "^1.12.0", + "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-atomic-write": "^0.1.0-rc.6", - "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6" - } - }, - "node_modules/@deepseek-ai/dsh-shell": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-shell/-/dsh-shell-0.1.0-rc.6.tgz", - "integrity": "sha512-l/pcwbdpM+Zgp2AzH0kH0z7bPU7L3k4uG1t5Du1V5ilk70tyMSxz2upNfAbjkDHZZZO18LTs33aq+zRWHX1CUg==", - "license": "MIT", - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6" + "@deepseek-ai/dsh-attachment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-shell-env": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-shell-env/-/dsh-shell-env-0.1.0-rc.6.tgz", - "integrity": "sha512-znxHFSqduw8U/AxKSO8SgSt703Bl+irRzTU0ukJT+ySlnyAwSAg8sZHLo5ZlEt5K8BdWhxz8Vc5jibOtJPB3ZQ==", + "node_modules/@deepseek-ai/dsh-message-feedback": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-message-feedback/-/dsh-message-feedback-0.1.0-rc.7.tgz", + "integrity": "sha512-P/Inw7dQMZCC6I6NC6G0UF9SeOVlpQxOBg2+LoCdvyTt40itDow2wmlThqkQDIt4UMHLT4yRc0Gd6a4gmTNJ2w==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" + "@deepseek-ai/schemastery": "^3.18.1", + "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7", + "@deepseek-ai/dsh-storage-domain": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-skill": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-skill/-/dsh-skill-0.1.0-rc.6.tgz", - "integrity": "sha512-VyRlCOASIRuTflKwn4NvbdAXxSPnnLJ+RAQUI4GK5pOtPwI2DhJrbovqpyp5kNAkZMsqvIeHWu5PcCEJ+FpQ2w==", + "node_modules/@deepseek-ai/dsh-native-command": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-native-command/-/dsh-native-command-0.1.0-rc.7.tgz", + "integrity": "sha512-c7NiAYPx5Ho2ZYOODRvt0yTZ9l00n7QvRh8paiyLaYBOuzo30KDo5wTJXGLxMkfzi6EQsWw1tljd8MnpGL2P4Q==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-skill-badge": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-skill-badge/-/dsh-skill-badge-0.1.0-rc.6.tgz", - "integrity": "sha512-k268iImXPFwA3barkSqusu9OlA8BcC0O8ZEvs5IY9bUJPCC0Tlw4VY8bumFt/2DSwh5cV4bBzZk96S8XA1Pd2A==", + "node_modules/@deepseek-ai/dsh-output-retention": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-output-retention/-/dsh-output-retention-0.1.0-rc.7.tgz", + "integrity": "sha512-bhmSfXIaLWLrYwC4ziMZ7GkNy5i9ltGBvlNZ5eB7NZoDAMh0Du7pKkMY+oqm2ajvx5O5qiFkHEhYoypRpEB56g==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-skill": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-skill-filesystem": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-skill-filesystem/-/dsh-skill-filesystem-0.1.0-rc.6.tgz", - "integrity": "sha512-NCgz8lCAdvd0oSGIF0EKg1OXfIC7x9r0an7mgC19F0DGzYZJe5ve6AwEYpSvKITE3V8W4NbUzLKyyZG3VH5QtQ==", + "node_modules/@deepseek-ai/dsh-permission-presets": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-permission-presets/-/dsh-permission-presets-0.1.0-rc.7.tgz", + "integrity": "sha512-AC6cyrinc3fQ2/TKmm8V1r/32f3VekR/w6rS1+RWGefRm6PDGnNo4T96/U4EoMyWDq0VBCn1Oye+uqhWPtl/3g==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1", - "chokidar": "^5.0.0", - "yaml": "^2.4.2" + "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-fs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-skill": "^0.1.0-rc.6" + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell": "^0.1.0-rc.7", + "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-skill-filesystem/node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "node_modules/@deepseek-ai/dsh-persona": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-persona/-/dsh-persona-0.1.0-rc.7.tgz", + "integrity": "sha512-1XhQNi3pIQ9TMUiquo+RRS4VpbXYhpFmZJ845kaVGToAexS2gJRVte8i/wKaDHDp/huAhJIsZemHlX0qADDsjw==", "license": "MIT", "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@deepseek-ai/dsh-skill-filesystem/node_modules/readdirp": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", - "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==", - "license": "MIT", - "engines": { - "node": ">= 20.19.0" + "@deepseek-ai/schemastery": "^3.18.1" }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@deepseek-ai/dsh-spill": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-spill/-/dsh-spill-0.1.0-rc.6.tgz", - "integrity": "sha512-reV4utwd3E5LgiNrsaqh6i6zxHboVyrrL1ilALRukDbMxSyup1vuSRh+4CPxSUh9YcoToFJ6jz2Zmlsw755g1w==", - "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-spill-local": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-spill-local/-/dsh-spill-local-0.1.0-rc.6.tgz", - "integrity": "sha512-DskqKnE16ZFmlqEVniiZI/QjVpUfRVol4ZlAlc3PZ4ROmVqzi0eyXIVcxng5BDZSmjHbPO1PAh0I3TkAzFjMuQ==", + "node_modules/@deepseek-ai/dsh-plan-mode": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-plan-mode/-/dsh-plan-mode-0.1.0-rc.7.tgz", + "integrity": "sha512-VXUxBvmZ9PYinVbYsu7GmT8BZMXCfAbqExNMoR4RoZm+leOLzZOkWOKea9THoJwIik0lUbAO5lzrqaeVKa99Dw==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" + "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-spill": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.7" + }, + "peerDependenciesMeta": { + "@deepseek-ai/dsh-commands": { + "optional": true + } } }, - "node_modules/@deepseek-ai/dsh-spill-policy": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-spill-policy/-/dsh-spill-policy-0.1.0-rc.6.tgz", - "integrity": "sha512-irdZNe/nZAeFKW/NyRZZS12sKLQhl3uLEPOCgYwh0jv8kin6fPdiW1cOqh/IOFuL+Bk0yF+646bRzamR9YUn8Q==", + "node_modules/@deepseek-ai/dsh-pwsh-local": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-pwsh-local/-/dsh-pwsh-local-0.1.0-rc.7.tgz", + "integrity": "sha512-AImknM43+7bIR9BzEatmbZMvhjgBgAt7MWqJzmTo1KnBNTY1j7r/RmOiQTBX4R+tpsLXMza5oW7svHSAYw/ypw==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-output-retention": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-spill": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-storage": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-storage/-/dsh-storage-0.1.0-rc.6.tgz", - "integrity": "sha512-zq15tNz5ywWuM15eqWADn7SKAPKyDYBto1WxZDIVJxHwQTBqu8gVaCdZo5IonH827qnabyiuJedgh9SkbSrTjg==", + "node_modules/@deepseek-ai/dsh-pwsh-sandbox": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-pwsh-sandbox/-/dsh-pwsh-sandbox-0.1.0-rc.7.tgz", + "integrity": "sha512-mXJcllRKoGnFhVs1mtUjjmqdfMymTRif5lrtxdhlkpegH6E9qKF7Wyq1Wnjkpsk6QW/iCicrRkXF2Bw623eDag==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-pwsh-local": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-storage-domain": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-storage-domain/-/dsh-storage-domain-0.1.0-rc.6.tgz", - "integrity": "sha512-/5qDCIIf9JNpoRG5VrY/CXFIuch1tDE0H5XREHsKd6LE26TOHcTAUH6gyersFG4e3TPoOLJYDp1+SapFLd7+kQ==", + "node_modules/@deepseek-ai/dsh-repeat-tool-reminder": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-repeat-tool-reminder/-/dsh-repeat-tool-reminder-0.1.0-rc.7.tgz", + "integrity": "sha512-AdG/wyhpWSJcLkRqs3j2VVgS6uH5xQf0mK7WZsdQ/RidB3OVYZiBg9Mto7Of25AtV5lP7ZN6TrqCqWgi60XwFA==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1", - "zod": "^4.4.3" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-storage": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-storage-json": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-storage-json/-/dsh-storage-json-0.1.0-rc.6.tgz", - "integrity": "sha512-BtpDh+k7L5f/wdvUXTNdtTjBORwRxpQAZXgFW6VaVlfsPmsIZZ3L7lrPZWIow9Cbv+lCT8uiFj7A/CxRMb7Ppg==", + "node_modules/@deepseek-ai/dsh-sandbox": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-sandbox/-/dsh-sandbox-0.1.0-rc.7.tgz", + "integrity": "sha512-he43z39/SC8cMzPDsoP7EEXiXKjav3VClj/U943pxycvRL78JGkNEQQjv21n5mnuto0ti/gFBquybSI4sBAFqA==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-storage": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-subagent": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-subagent/-/dsh-subagent-0.1.0-rc.6.tgz", - "integrity": "sha512-vROmBDAlaFAzzSlTBOlvg/7fO55zxhUztnLtB3lKmN5RevrNQBjTsbeIMDQ8ow5ZplxEOnLU+sikFoA5JaoH8A==", + "node_modules/@deepseek-ai/dsh-sandbox-local": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-sandbox-local/-/dsh-sandbox-local-0.1.0-rc.7.tgz", + "integrity": "sha512-jahNeS/WnBinCisOB4O+zeS366v7gWt6Uzfso0/C5He/vZFEITW5jPfWrJkZLuuN5S55LshaDEnegsddEIp6kw==", "license": "MIT", "dependencies": { - "zod": "^4.4.3" + "@deepseek-ai/dsh-sandbox-windows-acl": "^0.1.0-rc.7", + "@deepseek-ai/node-addon-landlock-run": "^0.1.1", + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-jobs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection-cache": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6" - }, - "peerDependenciesMeta": { - "@deepseek-ai/dsh-agent-presets": { - "optional": true - }, - "@deepseek-ai/dsh-jobs": { - "optional": true - }, - "@deepseek-ai/dsh-sandbox": { - "optional": true - }, - "@deepseek-ai/dsh-sandbox-policy": { - "optional": true - }, - "@deepseek-ai/dsh-session-persistence": { - "optional": true - }, - "@deepseek-ai/dsh-session-projection": { - "optional": true - }, - "@deepseek-ai/dsh-session-projection-cache": { - "optional": true - }, - "@deepseek-ai/dsh-user-approval": { - "optional": true - } + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-subagent-fork-in-process": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-subagent-fork-in-process/-/dsh-subagent-fork-in-process-0.1.0-rc.6.tgz", - "integrity": "sha512-S+BF0f2U0YkUf6vD6ZF82nREiWlrVe836U8FPV6PzgnVNGkEOb21rH2W9TSRjerB1G6KWjG/oBqrQIdKyFElVQ==", + "node_modules/@deepseek-ai/dsh-sandbox-policy": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-sandbox-policy/-/dsh-sandbox-policy-0.1.0-rc.7.tgz", + "integrity": "sha512-TnOy1SnnSNPVZyw9UFNwQ7eE2lGxQBU6kye7+aAwDbNvSnudCJDEnQJhjTvGewHWA6PYA0O60XERKcCQAnK+dw==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent-in-process-driver": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-subagent-in-process-driver": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-subagent-in-process-driver/-/dsh-subagent-in-process-driver-0.1.0-rc.6.tgz", - "integrity": "sha512-KK8Ep4PeSyrM3YQdcZhetXsiBd+bliKu6NWWKyTh60LobKtVNREfPBlqRfzc0mU0ZIKD4VEC7RfuJaqvz4UlPw==", - "license": "MIT", - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" - } - }, - "node_modules/@deepseek-ai/dsh-subagent-spawn-in-process": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-subagent-spawn-in-process/-/dsh-subagent-spawn-in-process-0.1.0-rc.6.tgz", - "integrity": "sha512-62mtUEr5megxVy6CwQCdZVq5MCSt+kMw74ns5m7PK0PlZTWcxQVBQHNdfkE9sX4Cageu7YTvciUJuH8amm6bsQ==", + "node_modules/@deepseek-ai/dsh-sandbox-windows-acl": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-sandbox-windows-acl/-/dsh-sandbox-windows-acl-0.1.0-rc.7.tgz", + "integrity": "sha512-Br+Ocg+dr1PcCA71DxPJd7/7Cel+HLnRyglbkhSPx9mEYpXXgioVCkDHJh7J9OvjRw19UF56g2CvgVah6HwFww==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" + "koffi": "^3.1.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent-in-process-driver": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-subprocess": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-subprocess/-/dsh-subprocess-0.1.0-rc.6.tgz", - "integrity": "sha512-nZaZRjSnE1he+GAd14vURAH7n3Fw5eGx3nzMbkB96Y6Qx+oQB/7PTuXxKVxlCh8TSfMJTf851ahwWb1eALjKlw==", + "node_modules/@deepseek-ai/dsh-schedule": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-schedule/-/dsh-schedule-0.1.0-rc.7.tgz", + "integrity": "sha512-vlvjvhE2B07XG3X+jUsfEDUjsiEGln8GFdy+ojWm27FKtA8JuoMdrMMUcCuVHnyr23jyk2Ft/qGA3JIJUOvIKQ==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-subprocess-local": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-subprocess-local/-/dsh-subprocess-local-0.1.0-rc.6.tgz", - "integrity": "sha512-D2daTRaprE25ti1Ra69eURPwLULpnRyUHqAGtcMHddcjNIsZ4yR0DGinYOsgoRymzu3t02qLxyoio05atSViRw==", - "hasInstallScript": true, + "node_modules/@deepseek-ai/dsh-scope": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-scope/-/dsh-scope-0.1.0-rc.7.tgz", + "integrity": "sha512-8gn+sANXhpv+9egbNwq49/uI3XhbmB33obo9yMyzyzruan3zFoxeH4UV54jTC2hjbu8gFNPsyNam9AAtRV8/Cg==", "license": "MIT", - "dependencies": { - "node-pty": "^1.1.0" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-system-prompt": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-system-prompt/-/dsh-system-prompt-0.1.0-rc.6.tgz", - "integrity": "sha512-E7g+XChh4q4/wX++v56z1pV4SA1Rtz42xkznLPPi9FlXrrzJxwHMOUzBZ9Rz3Y1kLhQ++HJG3ZatmNx3rjFilg==", + "node_modules/@deepseek-ai/dsh-session": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session/-/dsh-session-0.1.0-rc.7.tgz", + "integrity": "sha512-02WVTkqIH+TyDL7dhMN3Hm+qcTEdhD0fVDC0aIAyND2fBdXj3CagEXXvpmt3mzwWfKwOTGL1RdxtC6pMA4Bl1A==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-terminal": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-terminal/-/dsh-terminal-0.1.0-rc.6.tgz", - "integrity": "sha512-riHLAQhXJJ2TT9XrDWGMgJf21RBqQgSZdEVvG4+xGEf9NZWcoszxdp+KW7rpwfrKuuD70p8RHCPGW4gCQPA+/A==", + "node_modules/@deepseek-ai/dsh-session-checkpoint-policy": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-checkpoint-policy/-/dsh-session-checkpoint-policy-0.1.0-rc.7.tgz", + "integrity": "sha512-Gw8GDvEJsH815NQuKkWhPPmw61hqhcdVpaaTXbCTAq/+0YdgNzNxAGIzizufAmq099QsqVWX0zs7IWGpWzCfEw==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-terminal-bash": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-terminal-bash/-/dsh-terminal-bash-0.1.0-rc.6.tgz", - "integrity": "sha512-KRR/b/qqKO+sf6yc0xPC64LCZ+SQgTAnEMSO7gNXQ4BeAIzUbeKYfeVYiG6XZRbQ6al6o5sWIbZ0lUt3pHGdXw==", + "node_modules/@deepseek-ai/dsh-session-log-export": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-log-export/-/dsh-session-log-export-0.1.0-rc.7.tgz", + "integrity": "sha512-yToQnjzMGl5KCq//k9bN4OUXxpyRRjh3hBtnf/9AVVSvvV5DGDLHryEm7erECLOnoWZnng5J5SDERcykrVbYlA==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6", - "@deepseek-ai/dsh-terminal": "^0.1.0-rc.6" + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.7", + "@deepseek-ai/dsh-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "react": "^18.2.0" } }, - "node_modules/@deepseek-ai/dsh-time-context": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-time-context/-/dsh-time-context-0.1.0-rc.6.tgz", - "integrity": "sha512-5tylnw0kS74xmhUAW1H1tHsMVjjVuEFyQvn4/ocSmyrR656ghwNuYJ6/CCu358QBMsTrRNfGRlUw/IAZ1ySiLg==", + "node_modules/@deepseek-ai/dsh-session-persistence": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-persistence/-/dsh-session-persistence-0.1.0-rc.7.tgz", + "integrity": "sha512-NFH1uIGQDgMFOijgAv8lLWRiY3eHFEZW2alwuHlu4C32P4+jdChh9fjPlzBar3ZZTq0ZW0qWCdbYZS02DNxsvA==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-timeout": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-timeout/-/dsh-timeout-0.1.0-rc.6.tgz", - "integrity": "sha512-CUean0fAnfsJVszFEip7PsU/S26W+JfDFfsza2dCtlw8n6xlkbHA9Gjxdk2aTwqDGCgXEPkRW7mYkdJ0n6FR7w==", + "node_modules/@deepseek-ai/dsh-session-persistence-jsonl": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-persistence-jsonl/-/dsh-session-persistence-jsonl-0.1.0-rc.7.tgz", + "integrity": "sha512-amPgKP84E99YEiOroeoQNya3Rjm1VRWWU6y0ft02iVtFohTmWRMLESArkAAtFfap76bk34xEkvujp34nJl40Ow==", "license": "MIT", + "dependencies": { + "@deepseek-ai/schemastery": "^3.18.1", + "koffi": "^3.1.0" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tmux-context": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tmux-context/-/dsh-tmux-context-0.1.0-rc.6.tgz", - "integrity": "sha512-Wl7oOUO9XH7i6Bfu5L0+Nph2jzyF972eb949Hx/6akcKq+uNLFrq07L96LcAAQRezU8AQqtowzVs2LUbJ5dViA==", + "node_modules/@deepseek-ai/dsh-session-projection": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-projection/-/dsh-session-projection-0.1.0-rc.7.tgz", + "integrity": "sha512-BXehLYt6wYnV0PNNhv5GECePkH1w+1yuu/R63d2tdYdUQ7XVrd6tu5hMwfTH0P9AnBDxJir08FRu2WKO69JypA==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" + "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-token-meter": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-token-meter/-/dsh-token-meter-0.1.0-rc.6.tgz", - "integrity": "sha512-qU5FT4n1RJXP3Ss8NJ5TTvPo8rZ6cxcrCedp1t0sTAj93SGssAanq47voSmznPP52nwz/SLeunznAIT0jhbsZQ==", + "node_modules/@deepseek-ai/dsh-session-projection-cache": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-projection-cache/-/dsh-session-projection-cache-0.1.0-rc.7.tgz", + "integrity": "sha512-qWf7p2Xgr0LnY4o466ei3L/81QbGFQcCbEi+4XX9rxLKgnU+RvlQzwmIilrgz9N2hK/RqwS1Nb03bFRisxVeaw==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1", @@ -3466,1203 +3521,1158 @@ }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-compaction": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-storage-domain": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-ask-user": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-ask-user/-/dsh-tool-ask-user-0.1.0-rc.6.tgz", - "integrity": "sha512-AlDljdccjmygPkLcW2t7atz1iDtzMr2F55DAB+0nw26er74f4WQsQ6pqJg64glr/03oDVrxSlxtSOid4U3Cvqw==", + "node_modules/@deepseek-ai/dsh-session-query": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-query/-/dsh-session-query-0.1.0-rc.7.tgz", + "integrity": "sha512-JKlEpByllYQU9JZLadrS3ClWCVZMcKRB4nc6iCWuNExyRi/Whwa5GicKFs+jXwGKe/rdSbTCom/jYLwkqipjuw==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.6" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-title": "^0.1.0-rc.7" + }, + "peerDependenciesMeta": { + "@deepseek-ai/dsh-session-persistence": { + "optional": true + } } }, - "node_modules/@deepseek-ai/dsh-tool-bash": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-bash/-/dsh-tool-bash-0.1.0-rc.6.tgz", - "integrity": "sha512-yzo/xPCObiFe+OU0e8E5nVOGpW6mp9vx/3q+MHQ0aqEbqrqHUfVMGPobfDAd/I1Ja/9Nag5NIvHpI2Hwx7lACg==", + "node_modules/@deepseek-ai/dsh-session-query-sqlite": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-query-sqlite/-/dsh-session-query-sqlite-0.1.0-rc.7.tgz", + "integrity": "sha512-XuhVkX2V+tx/xO9/gCzPHGbovoApwaojwCjNFAuBUbHLMvMl1wMdxvxSgk/xLPKnll98daXRPoq5Csg6hrG8MA==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-jobs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell-env": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-query": "^0.1.0-rc.7" + }, + "peerDependenciesMeta": { + "@deepseek-ai/dsh-session-persistence": { + "optional": true + } } }, - "node_modules/@deepseek-ai/dsh-tool-bash-persistent": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-bash-persistent/-/dsh-tool-bash-persistent-0.1.0-rc.6.tgz", - "integrity": "sha512-bsM1RHwkpNRAy0zufIDNUWxeiuGngc+R35RZ20gbWM878rHOZVuicy4MG8NKhzqGLqMD4NuDoNfjtDUkZHC48A==", + "node_modules/@deepseek-ai/dsh-session-reference": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-reference/-/dsh-session-reference-0.1.0-rc.7.tgz", + "integrity": "sha512-lyD9VbGrOSVkAV8mr6aIl22bdWIe61lC9/dtZ6CtS3DLnewvSkZ4CNlUDG/qS1SUIZfk7A2UixgXYBIB2771xw==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-terminal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-compaction": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-output-retention": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-query": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-call-timeout-policy": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-call-timeout-policy/-/dsh-tool-call-timeout-policy-0.1.0-rc.6.tgz", - "integrity": "sha512-PBK6Lkj4AK4LJXBJW+67AfSE1bxMUbjAE8kYL4loKOetGpEpu2iU35jb7HirjsgG7Byz2mRxT/jvbWhW9/uxOA==", + "node_modules/@deepseek-ai/dsh-session-stats": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-stats/-/dsh-session-stats-0.1.0-rc.7.tgz", + "integrity": "sha512-ryf7HSYdmLbrTv4HQmeW/h0bHLiCNnSZYiY9RoBrzg2qh89MU8S+Q/a9CLVWA06TRXKt7tNbizF82dCj2/O0bQ==", "license": "MIT", + "dependencies": { + "zod": "^4.4.3" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-cordis": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-cordis/-/dsh-tool-cordis-0.1.0-rc.6.tgz", - "integrity": "sha512-MdsdiOzLaGps29FW2I6eO3vWUFttK80XGieD99rZM4p1pqwFQ8Ix22SIOhMeIqz70m1CvjoLxLak1vElte3lQw==", + "node_modules/@deepseek-ai/dsh-session-telemetry": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-telemetry/-/dsh-session-telemetry-0.1.0-rc.7.tgz", + "integrity": "sha512-6f5U7nt5Iqwh5RAFBqV2Ib7LJU2o89Et0r0eV7bskYws+PNM7ZRRW/Nw4a12ZcnuTp1eKPyVE8H6oJua6/7XLA==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-cordis-host-runner": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-fs": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-fs/-/dsh-tool-fs-0.1.0-rc.6.tgz", - "integrity": "sha512-bJfo8cCacX3WBygG8GbIlGz3jQ15MyIv4htGCjKpIIRHrXHSAelNtzceO2xQ21/9BkXrvg+i50mqySOcKQ0b3w==", + "node_modules/@deepseek-ai/dsh-session-telemetry-otel": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-telemetry-otel/-/dsh-session-telemetry-otel-0.1.0-rc.7.tgz", + "integrity": "sha512-k5zHavA2RoBtZ5igD+qpbdfyxKvesZa2w+YKLfMtUnZOj7HZM9qcxvfYo4xJ9spNLpN5OGY/sWZBB5itilZlCw==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1", - "diff": "^9.0.0" + "@opentelemetry/api": "^1.9.1", + "@opentelemetry/api-logs": "^0.220.0", + "@opentelemetry/exporter-logs-otlp-http": "^0.220.0", + "@opentelemetry/otlp-exporter-base": "^0.220.0", + "@opentelemetry/resources": "^2.9.0", + "@opentelemetry/sdk-logs": "^0.220.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-fs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6" + "@deepseek-ai/dsh-anonymous-user-id": "^0.1.0-rc.7", + "@deepseek-ai/dsh-command-feedback": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-telemetry": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-fs-search": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-fs-search/-/dsh-tool-fs-search-0.1.0-rc.6.tgz", - "integrity": "sha512-MUu9QF2Du8F6zdFP5rPEti9LKr/IyCYLM24XbaeuZZCrbq6Q1Rf9sng3v5bD9TlT+Wm+uXv3AqPX+8r8gcdqIQ==", + "node_modules/@deepseek-ai/dsh-session-title": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-title/-/dsh-session-title-0.1.0-rc.7.tgz", + "integrity": "sha512-jhFiZa/C58zchuJkBodnkiPil7AEK8mHfB/hMOAW3N/7tUg5nbMLBERNqHdDMbIrvhTndrF4SN9qy+ltUf0cOQ==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1", - "@vscode/ripgrep": "^1.18.0" + "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-output-retention": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-spill": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-goal": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-goal/-/dsh-tool-goal-0.1.0-rc.6.tgz", - "integrity": "sha512-5rYb1wWJa2HfCxi1JNMkPJwN0upoblJEVlnV+omTx4ZDGekg2dyfftaQdFH9cwiW576is8bAUgPE9Rd0sZCAzw==", + "node_modules/@deepseek-ai/dsh-session-title-first-prompt-llm": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-title-first-prompt-llm/-/dsh-session-title-first-prompt-llm-0.1.0-rc.7.tgz", + "integrity": "sha512-tFocCpSglf69VC6a23R9OcomMBQdfQZm8MvAOGgENBzWz9htDLuyq6jukKzPdTtS3VdRDu4wzJtaWKAYBUCX4w==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-title": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-title-llm": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-jobs": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-jobs/-/dsh-tool-jobs-0.1.0-rc.6.tgz", - "integrity": "sha512-mcftmyHx2bq8u5Qwo7znysa3vOKO86ccJvgEZqfDV7S+UhOGbPDue7psyx1/jD/5fbK+653JbxQ8ds9wsLkiPw==", + "node_modules/@deepseek-ai/dsh-session-title-llm": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-title-llm/-/dsh-session-title-llm-0.1.0-rc.7.tgz", + "integrity": "sha512-mpQo/1x4jaWNdQAXckOs68U59u+/WHJlb/BX1zAvr02eJPV3Wac2/7NP+/vTw5TElEyzIAU8k0f3PMgvozUk0g==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-jobs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-output-retention": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-title": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-pwsh": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-pwsh/-/dsh-tool-pwsh-0.1.0-rc.6.tgz", - "integrity": "sha512-x8ZlXUpOmcEiQobSTNSj18TPWVzyGe68pXJi6njea28DKVSe5Cx/L1bl9WImxru9f06+BkAm2ievJ+VKe89aeA==", + "node_modules/@deepseek-ai/dsh-settings": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-settings/-/dsh-settings-0.1.0-rc.7.tgz", + "integrity": "sha512-cS1+StK2xIVykrskw+KrO+hKJxYaVVgY2Jex2we5zASTNLHYCj74WQluPlaFjFgnXoZ1RYz8HNXL5/Ho6h1Ynw==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-jobs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell-env": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/schemastery": "^3.18.1" } }, - "node_modules/@deepseek-ai/dsh-tool-ralph": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-ralph/-/dsh-tool-ralph-0.1.0-rc.6.tgz", - "integrity": "sha512-/PTqAS4oeiC1kn2/V98quJNuzALW3SD8TIk8M0cWQwZUkwS7D421p9WO0PPaV+6BQYFkgONfXJ+vzb6DJ6x5dg==", + "node_modules/@deepseek-ai/dsh-settings-file": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-settings-file/-/dsh-settings-file-0.1.0-rc.7.tgz", + "integrity": "sha512-ODz9QWtCOjmwX7gxewPBfIHkA9twPiHDpcwgAW4sQUztgsJZKUtoe2T47loNH6QlHBPcSL5WMP4/QlnkRVKC0Q==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" + "@deepseek-ai/schemastery": "^3.18.1", + "chokidar": "^4.0.3", + "yaml": "^2.9.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-workflow": "^0.1.0-rc.6" + "@deepseek-ai/dsh-atomic-write": "^0.1.0-rc.7", + "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-skill": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-skill/-/dsh-tool-skill-0.1.0-rc.6.tgz", - "integrity": "sha512-AebSfHSt6j0PXuN3yK9+X4aC6tHSnFdm2hZglII7aEHr/lL9UbynPb3NTumh6thXZ9Earvwhf9JdOxHMsjHqfw==", + "node_modules/@deepseek-ai/dsh-shell": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-shell/-/dsh-shell-0.1.0-rc.7.tgz", + "integrity": "sha512-in3ifbq80tn5cf1ICBBsRdwKjURB0g0dIRdCVUgl/GDqCdC/S0TjMLXw4nmFdCssYLm7JbG5a59BfJG0KFuz6Q==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-skill": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-str-replace-editor": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-str-replace-editor/-/dsh-tool-str-replace-editor-0.1.0-rc.6.tgz", - "integrity": "sha512-Kv+zA9ZQCn85VLfox2WVvNI/iU6e3ml4gPLqXiKMC027/iwmGHTcRMKOlDNnwydFTJOucNs8wW4Ac3FafCn3gA==", + "node_modules/@deepseek-ai/dsh-shell-env": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-shell-env/-/dsh-shell-env-0.1.0-rc.7.tgz", + "integrity": "sha512-joSBNw/d54gq/VjkHLGSJ6y/Qr+594sObF4ApbJi2eEopx41L0Ky7kNW/W7cbrGIIN3KBGRDdiGv1s1paWzsMw==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-fs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-subagent": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-subagent/-/dsh-tool-subagent-0.1.0-rc.6.tgz", - "integrity": "sha512-yK+ETLxDZhtwc19uqv5yAVzq3x/i2hjV9p67Or1a+s9Eqs+eu+ZJJk5hQ/2JeRiJet2otOC4zzOkYb/UVSBFyA==", + "node_modules/@deepseek-ai/dsh-skill": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-skill/-/dsh-skill-0.1.0-rc.7.tgz", + "integrity": "sha512-tDaqB1TOs27fSt6FZdjvPs4THXAFKoKOEgQG+iFUv63O5bm+glyLY3K1LTK8JeofB4lg3+4JIAeWRslnLJH57w==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-jobs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-subagent-control": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-subagent-control/-/dsh-tool-subagent-control-0.1.0-rc.6.tgz", - "integrity": "sha512-zoVt+uV8yyg1dAuIMydtz/AfARZPkjFOXQLd90a3Bj8GdxpE3tdaR6ZIv3xD39Grxe2vRz4gOZEJ9qth3O+s9g==", + "node_modules/@deepseek-ai/dsh-skill-badge": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-skill-badge/-/dsh-skill-badge-0.1.0-rc.7.tgz", + "integrity": "sha512-01Ue3mvLYyBwNj+fAuTUZN4gJLuDySPDqAZhCtWoYagZudCuLB8kAdpYWztKA4TRVSyml+EfGo1LrWvQeTD1wQ==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-skill": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-subagent-report": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-subagent-report/-/dsh-tool-subagent-report-0.1.0-rc.6.tgz", - "integrity": "sha512-DqnJ6yJ0wO35jdcpCSuogbx/PC4xE8wrcVxXPvSw9I59p/8nROsfwB9UXuJoilp/wenREUoTi0X8+5ZOVSRLqw==", + "node_modules/@deepseek-ai/dsh-skill-filesystem": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-skill-filesystem/-/dsh-skill-filesystem-0.1.0-rc.7.tgz", + "integrity": "sha512-i95xycP3vkz4IZnIO4BTzGNB6waKl1M5AsW2x04C0FIqLa4BSILvVUVwqcbwpBZm7Cd/KF50Q050au3NvauGrw==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" + "@deepseek-ai/schemastery": "^3.18.1", + "chokidar": "^5.0.0", + "yaml": "^2.4.2" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "@deepseek-ai/dsh-fs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-skill": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tool-todo": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-todo/-/dsh-tool-todo-0.1.0-rc.6.tgz", - "integrity": "sha512-ll9xmgkrV6nsxjEZn5+YkNwQei7WrMMisnbr9mAKmqN5vpyOVHXisLvKdiASEmgpm4rsicnR8Y0wcBUfbeJTxA==", + "node_modules/@deepseek-ai/dsh-skill-filesystem/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "license": "MIT", "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1", - "zod": "^4.4.3" + "readdirp": "^5.0.0" }, - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6" + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@deepseek-ai/dsh-tool-web": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-web/-/dsh-tool-web-0.1.0-rc.6.tgz", - "integrity": "sha512-2iw+F65+1+I3gwi8N+LzC6GD6vnhDSHfo9D+Pm+4h2O2d+4YKjeaOukx65sV9HTvFumY1tWXnYhBbDCJYBJAig==", + "node_modules/@deepseek-ai/dsh-skill-filesystem/node_modules/readdirp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", + "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1", - "@joplin/turndown-plugin-gfm": "^1.0.67", - "turndown": "^7.2.4" + "engines": { + "node": ">= 20.19.0" }, - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-web": "^0.1.0-rc.6" + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@deepseek-ai/dsh-tool-workflow": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-workflow/-/dsh-tool-workflow-0.1.0-rc.6.tgz", - "integrity": "sha512-w/D4RuFwxcx39Ryb//RFkSi1hp/QFVX/m6K7dFZ8HFdJVyu5otg5RJqvlDO55QNNLA8EndUOnc1GHl691MEDpg==", + "node_modules/@deepseek-ai/dsh-spill": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-spill/-/dsh-spill-0.1.0-rc.7.tgz", + "integrity": "sha512-EdX5AZElelHlCKlbflZipl4KRDiEHWLN/8smgnkzAhJgpXFq5dyp9jK58dO5v7cuODeq+/SfeDyUE5Mffdhh8Q==", "license": "MIT", - "dependencies": { - "@deepseek-ai/schemastery": "^3.18.1" - }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-workflow": "^0.1.0-rc.6" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-tools": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tools/-/dsh-tools-0.1.0-rc.6.tgz", - "integrity": "sha512-Tu08EPK3JyK0iNjH4FGzu/1uADynNSS6SmwOLdfytUN0YNqwNuKFSt2OJUg19famNlTgy992DcHfDu0T+gLXFg==", + "node_modules/@deepseek-ai/dsh-spill-local": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-spill-local/-/dsh-spill-local-0.1.0-rc.7.tgz", + "integrity": "sha512-jx198A2cc1gxsoKb2pRmXnDbIwIHAKg78ZjRMyiLRGpOFEZugVudILdDMp8u+lGpavP9xVAxBc1n75Z5NDRw7g==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-code-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6", - "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-spill": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-typert-loader": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-typert-loader/-/dsh-typert-loader-0.1.0-rc.6.tgz", - "integrity": "sha512-PIC2iV1Sr+GtY9PpIGdW+pzoMDXSlxDx7QIfTbaeOVF5TRCxbe0gL6hsDEUIhkVOdfSpE731yxt0d8YpdNByzg==", + "node_modules/@deepseek-ai/dsh-spill-policy": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-spill-policy/-/dsh-spill-policy-0.1.0-rc.7.tgz", + "integrity": "sha512-fYypZXcXFkXybf8N0tz70+XCtxvnn9mDN8JiKnTp2ZNhXb/zvFbdf661Pp45lFWS6j0cHZsdZ5T8DfuQjfO94Q==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/cordis-plugin-loader": "^1.0.2", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-output-retention": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-spill": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-typert-protocol": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-typert-protocol/-/dsh-typert-protocol-0.1.0-rc.6.tgz", - "integrity": "sha512-weWzN8r01YCkoDCAM7BsKw2YhRrD4zL8N2SAZu9hovYtXSq8xHXsP4Zh8RLYIlYcuotjyff/6hic+0TJPd14YA==", + "node_modules/@deepseek-ai/dsh-storage": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-storage/-/dsh-storage-0.1.0-rc.7.tgz", + "integrity": "sha512-M+6+SOjWWcfYoGASBMx+b1sHmWPFAHXF57rE/Mew9k5tHC5bEV8+owWwYOWQfv41eO1FfRMibZd0rH6mwPNApg==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-typert-registry": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-typert-registry/-/dsh-typert-registry-0.1.0-rc.6.tgz", - "integrity": "sha512-ry2AApGn0vEEIRWDC7TlLiLj5K8+2OblxXlGHs1u9APVxhPjZLok6Kfo57yfeJyW+EONGXv1DQcU05U+aYE7Tg==", + "node_modules/@deepseek-ai/dsh-storage-domain": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-storage-domain/-/dsh-storage-domain-0.1.0-rc.7.tgz", + "integrity": "sha512-UxXwoCB0q4+/F+zddvi8I4LknTIlGD/1ec57Ym52kWRb7a8qGgrcIYrOC3yPCozn8rkirAuhEAkyAhR6AO5QDw==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6", + "@deepseek-ai/schemastery": "^3.18.1", "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-storage": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-user-approval": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-user-approval/-/dsh-user-approval-0.1.0-rc.6.tgz", - "integrity": "sha512-9rnkSDGOpu2XUeGwbPeTzVUTFWTND1PMPM5L/ZQPptV5yyZlQiNxM2rCC6OdL+ZVerwxEqrRhZIQn/KVtQfKag==", + "node_modules/@deepseek-ai/dsh-storage-json": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-storage-json/-/dsh-storage-json-0.1.0-rc.7.tgz", + "integrity": "sha512-xYvEY3+ttxJg4/UPzXuxgeKcLxKvDP4alvPpEfRwuMBcp//O6FtzEJSqV8zycJVYHU8V0wmUKRIn4V1ycXlFgA==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-storage": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-user-questions": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-user-questions/-/dsh-user-questions-0.1.0-rc.6.tgz", - "integrity": "sha512-5vG4Ug+hVQuwU4KN7CFpF9qObBEYY/mPe1FHhToYO8Y2ICdHt3eX0Or9oEJFW68bZAMfuiAshZL8oUubr7obRg==", + "node_modules/@deepseek-ai/dsh-subagent": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-subagent/-/dsh-subagent-0.1.0-rc.7.tgz", + "integrity": "sha512-PEpA9XT6E4hg7N8m7GYQyDLwFUwoqWTz0Cm9SrdAoNcju4byG08qy4+muDZbG0a1tm3PR4rxNB5zKcobDhDocg==", "license": "MIT", + "dependencies": { + "zod": "^4.4.3" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-jobs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection-cache": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.7" + }, + "peerDependenciesMeta": { + "@deepseek-ai/dsh-agent-presets": { + "optional": true + }, + "@deepseek-ai/dsh-jobs": { + "optional": true + }, + "@deepseek-ai/dsh-sandbox": { + "optional": true + }, + "@deepseek-ai/dsh-sandbox-policy": { + "optional": true + }, + "@deepseek-ai/dsh-session-persistence": { + "optional": true + }, + "@deepseek-ai/dsh-session-projection": { + "optional": true + }, + "@deepseek-ai/dsh-session-projection-cache": { + "optional": true + }, + "@deepseek-ai/dsh-user-approval": { + "optional": true + } } }, - "node_modules/@deepseek-ai/dsh-web": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-web/-/dsh-web-0.1.0-rc.6.tgz", - "integrity": "sha512-ABFbyDgo+DGaCtdRnjYG7Rz2K4dFlPA+xCEIt5MDobK/9CRQNpdZ4YrhHiq0nxwl1oxEM1Zw48ylFt+PwtS9ug==", + "node_modules/@deepseek-ai/dsh-subagent-fork-in-process": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-subagent-fork-in-process/-/dsh-subagent-fork-in-process-0.1.0-rc.7.tgz", + "integrity": "sha512-PnT/poBisBmA9U+mLZeyQJfHS4Ps8kwN1ioZEmv36TwnROCrmwzog5FB33r9rXU/gKVX0dD/LkjxxTGmzC1xCA==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent-in-process-driver": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-web-app/-/dsh-web-app-0.1.0-rc.6.tgz", - "integrity": "sha512-GKvfD1oHbdNN4Mbb77nCydfv2ZRxGVnKcKIGUfXGvs5cNC3cfPYPP/Ok9b/Kbk9zFYMuz+lLikka+HK3zyUcAQ==", - "license": "MIT", - "dependencies": { - "@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.6", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-app-boot": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-hmr": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-modules": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-agent-preset": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-cordis": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-deliverables": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-directory-picker-browse": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-directory-picker-native": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-jobs": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-layout": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-message-feedback": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-model-selection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-permission-presets": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-plan": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings-general": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings-models": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings-plugin-inventory": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-sidebar": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-skill": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-theme": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-tool": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-trajectory": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-user-questions": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-workflow-run": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-workspace": "^0.1.0-rc.6", - "@deepseek-ai/dsh-cmdline": "^0.1.0-rc.6", - "@deepseek-ai/dsh-code-runtime-worker-thread": "^0.1.0-rc.6", - "@deepseek-ai/dsh-cordis-client-runner": "^0.1.0-rc.6", - "@deepseek-ai/dsh-cordis-host-runner": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-apiproxy": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-directory-picker-auto": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-directory-picker-browse": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-directory-picker-native": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-frontend-static": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-plugin-inventory": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6", - "@deepseek-ai/dsh-message-feedback": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-log-export": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-projection-cache": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-stats": "^0.1.0-rc.6", - "@deepseek-ai/dsh-storage": "^0.1.0-rc.6", - "@deepseek-ai/dsh-storage-domain": "^0.1.0-rc.6", - "@deepseek-ai/dsh-storage-json": "^0.1.0-rc.6", - "@deepseek-ai/dsh-web-frontend": "^0.1.0-rc.6", - "@deepseek-ai/dsh-workspace": "^0.1.0-rc.6", - "@deepseek-ai/schemastery": "^3.18.1", - "commander": "^15.0.0" - }, + "node_modules/@deepseek-ai/dsh-subagent-in-process-driver": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-subagent-in-process-driver/-/dsh-subagent-in-process-driver-0.1.0-rc.7.tgz", + "integrity": "sha512-YleMt6xtXmW8LkHZ95MLPq1urIt1+sBUK908GCQ2EhV6nyfUwNog4XVDlVbzf3GXzc+3z/xiMW2GvVp3IQ5NIA==", + "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/cordis-plugin-loader": "^1.0.2", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-shell-env": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-locale": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-locale/-/dsh-client-locale-0.1.0-rc.6.tgz", - "integrity": "sha512-IoSLGxfHgcoaNzIlQ7YRTHRTy/MQCvvusrPCwlT30Xc9lpQe6Yo/LiRLDXlm9zbhN6imf/AoQZIfO+T3VGqneg==", + "node_modules/@deepseek-ai/dsh-subagent-spawn-in-process": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-subagent-spawn-in-process/-/dsh-subagent-spawn-in-process-0.1.0-rc.7.tgz", + "integrity": "sha512-4C06MeBvsbgiUrWh+tge91wRLSOOJDU/Ub7b9Q6nTxQKEMJooJwCQRPfgaWtdXuNHrJGIJ87GKsgqV2iwfQ/jA==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent-in-process-driver": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-agent-preset": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-agent-preset/-/dsh-client-ui-agent-preset-0.1.0-rc.6.tgz", - "integrity": "sha512-kJeQdVrUZ0skjyWIAwf+YKZE4VgUXT/7HGQvRVWSWRRlQ0X3dlWUgJnDDzcWBt+cn0cfR5/CANPrPiYEveBxdw==", + "node_modules/@deepseek-ai/dsh-subprocess": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-subprocess/-/dsh-subprocess-0.1.0-rc.7.tgz", + "integrity": "sha512-xiHD61S2trIZ0CzhSMgXxZJVyJ2c76DkX4eqP3Of4mBEnm6C7g7FChII6uL0z5v1bnOnTmpHzwPX8YCwqb7dbg==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-commands": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-commands/-/dsh-client-ui-commands-0.1.0-rc.6.tgz", - "integrity": "sha512-he9tgQtm/yy4qJRzob37rTqfb+FTY1YWzvHjDwfAWzsHH0R8vO2r0L/WHX8ZFpdGzzcPAIGuwEjkDa5Q05PI0A==", + "node_modules/@deepseek-ai/dsh-subprocess-local": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-subprocess-local/-/dsh-subprocess-local-0.1.0-rc.7.tgz", + "integrity": "sha512-Q1zl35fRNSASv2FOi6viwR29cn3vtOcyKfamcmRB789m6sb6CdlhIMettvcxxDDHwTSH/jjz3hqb0JAx2GT32g==", + "hasInstallScript": true, "license": "MIT", "dependencies": { - "clsx": "^2.0.0" + "node-pty": "1.2.0-beta.15" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-conversation": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-conversation/-/dsh-client-ui-conversation-0.1.0-rc.6.tgz", - "integrity": "sha512-pKDKZYTRvO9pBTyHvVOtPDuTzNfCHwy7GmeIaRLjyCORLPM3uv0BuMc1qIHVI6LcK54l+cRGIuSSGah3bO/0vw==", + "node_modules/@deepseek-ai/dsh-system-prompt": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-system-prompt/-/dsh-system-prompt-0.1.0-rc.7.tgz", + "integrity": "sha512-Rair2ZkzgoIIr+UstYVYeqeUgORNPIW1LNcsXz3Zjglx4FGjsmzs0UALdNYvSBpBvCLNmt4E6+XQIrBbS/s9jw==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/schemastery": "^3.18.1", - "clsx": "^2.0.0" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-attachment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-compaction": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm-retry": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-stats": "^0.1.0-rc.6", - "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-cordis": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-cordis/-/dsh-client-ui-cordis-0.1.0-rc.6.tgz", - "integrity": "sha512-gYCef2obc7UMKOjneFvU8pTK2FehGNI9rqvZW9i1CUZ5pSJjAzJ14C4noIMPQxCrhj37QehrxyAC6Z+XzKYEYg==", + "node_modules/@deepseek-ai/dsh-terminal": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-terminal/-/dsh-terminal-0.1.0-rc.7.tgz", + "integrity": "sha512-B22qppmKWvw5Ez9eMKnppHiaMrikIcHmfmvyd296EspnhTBJAvXDnc9NggT0DUnSvm+2gh5ffohhMJel9A2pSA==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-sidebar": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-tool": "^0.1.0-rc.6", - "@deepseek-ai/dsh-cordis-client-runner": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-deliverables": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-deliverables/-/dsh-client-ui-deliverables-0.1.0-rc.6.tgz", - "integrity": "sha512-zs5pa0ug9gFf2+X3UHTLCOcspKAzWnroNyh8BG1gZtcDIZtpabjyG/+Yfpm98Pxl0j0VBnpU0MUOqI5LGrHsHw==", + "node_modules/@deepseek-ai/dsh-terminal-bash": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-terminal-bash/-/dsh-terminal-bash-0.1.0-rc.7.tgz", + "integrity": "sha512-2muS7xmy4olNEpGANp0ViK3/r4A4UlfQa5w24HJ2PrCy0J3qlk1vwHrpj30nAGK6sCaxbXmb8IjYUfNs7st7zw==", "license": "MIT", "dependencies": { - "react": "^18.2.0" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.7", + "@deepseek-ai/dsh-terminal": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-directory-picker-native": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-directory-picker-native/-/dsh-client-ui-directory-picker-native-0.1.0-rc.6.tgz", - "integrity": "sha512-R2tdM0cLwMo9lJSl/tTmPi+jlilvVeVzBn3vZWeRDyvNzj3fwgw9nSy1/7FcwlOuopr9vCAyf3rRDZrnySYixw==", + "node_modules/@deepseek-ai/dsh-time-context": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-time-context/-/dsh-time-context-0.1.0-rc.7.tgz", + "integrity": "sha512-rZhEYA/urMq8sReaMc5rb9A/p7X1MXwktoF5Y6SwGUWqJQsdvHzXppksOEqJpg4a1pNDBe2N9X5o+wMKPmukMQ==", "license": "MIT", + "dependencies": { + "@deepseek-ai/schemastery": "^3.18.1" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-workspace": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-goal": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-goal/-/dsh-client-ui-goal-0.1.0-rc.6.tgz", - "integrity": "sha512-Ixbqu74dbqjkwtVdvCAZWvUfjOsc4N5wAQvNKXR1eB5O+d6j0K3jeGb2rGeo1vCoZGCZVuawy5PWTKuIr2ZiRg==", + "node_modules/@deepseek-ai/dsh-timeout": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-timeout/-/dsh-timeout-0.1.0-rc.7.tgz", + "integrity": "sha512-Ufl9G7zP7Tky/zkXscavEiolEfAwutfbPeLb5sUU/tPQlDykhh1NwGrarNJ11fdR723zmA/3co4LgxtDtWCOEQ==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-goal": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-input-trigger": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-input-trigger/-/dsh-client-ui-input-trigger-0.1.0-rc.6.tgz", - "integrity": "sha512-lp6psRmPzkvz5JiVhV2tIovzVq7oo0LKbQcL77Rlcw1ZmHoZMCzQYResbMa+un9ycM8io/am2VKbTOaqrWjgOA==", + "node_modules/@deepseek-ai/dsh-tmux-context": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tmux-context/-/dsh-tmux-context-0.1.0-rc.7.tgz", + "integrity": "sha512-DYoWGpJglqzWxCFDzynJ7ebt9m7Redlm2Iuon5U2tJ0rsyOSRIgKuwQMXI67FdN/MNVXvSQ2xybUqu+5V0krnA==", "license": "MIT", "dependencies": { - "clsx": "^2.0.0" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-jobs": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-jobs/-/dsh-client-ui-jobs-0.1.0-rc.6.tgz", - "integrity": "sha512-pNJfFOyTyTG7XRysArUacNNw57J1bSoATozsffu5MA5gEnBDz4ZAE8uvlJjnbwD75xYBsfNoDABOWySY/rH/QA==", + "node_modules/@deepseek-ai/dsh-token-meter": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-token-meter/-/dsh-token-meter-0.1.0-rc.7.tgz", + "integrity": "sha512-i2WOx26otsAt3sTFOoXjo2xsdvUyC5CAuNiJyRQoo6yn1smx+NX541clIOYdx1uneZFmV0T6bK46JpdXasxaAA==", "license": "MIT", "dependencies": { - "react": "^18.2.0" + "@deepseek-ai/schemastery": "^3.18.1", + "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-compaction": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-layout": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-layout/-/dsh-client-ui-layout-0.1.0-rc.6.tgz", - "integrity": "sha512-JpQ5rzySpK7molQBfMqrcBCGDWYQngqZmFuFqhcxecIc2n5mBYVP0F5UbGITgxo+D7sDOy78RA1PWqZ/5b/g0g==", + "node_modules/@deepseek-ai/dsh-tool-ask-user": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-ask-user/-/dsh-tool-ask-user-0.1.0-rc.7.tgz", + "integrity": "sha512-ZqwrTw+w4GepNCVQ7NIq71s+Hlrqu3jAfYCdKuNbkUy461EjlRLGMcHspSHAt1uhdwL9QDTodB6RRhpg65Hozw==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-theme": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-message-feedback": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-message-feedback/-/dsh-client-ui-message-feedback-0.1.0-rc.6.tgz", - "integrity": "sha512-CQqh/Uix3z5crbTb8lowJVltLRP39NfoRNoJ6J7gu9FaaX6qA8Cf5x4W3+hMnN2e7el6v3pVSpm+MicGypkeZg==", + "node_modules/@deepseek-ai/dsh-tool-bash": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-bash/-/dsh-tool-bash-0.1.0-rc.7.tgz", + "integrity": "sha512-nfc0SI3Xk36rgIOLmTBDSrSTN3Ufp9Wvefta/M82kbBCo6fesB4lst+VAw74039jzHUboXc2gwQ/j5rRcOpiuw==", "license": "MIT", + "dependencies": { + "@deepseek-ai/schemastery": "^3.18.1" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-message-feedback": "^0.1.0-rc.6", - "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-jobs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell-env": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-model-selection": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-model-selection/-/dsh-client-ui-model-selection-0.1.0-rc.6.tgz", - "integrity": "sha512-adjndhpBq++KGOmA8aK12xTBYvTu1UnY8BCW6smOQa93VVPuMWqstDw7MFZ6mrFQoF3tHwNxoSo+tYWS20o+mg==", + "node_modules/@deepseek-ai/dsh-tool-bash-persistent": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-bash-persistent/-/dsh-tool-bash-persistent-0.1.0-rc.7.tgz", + "integrity": "sha512-5tMC1TuWiGDerYd0UuUUzRdmv+uy/22lXbxmmrmUfR8aACeK6T76yXorvuvJSDYjhPpLoUovz9XU5LqGm3D2Wg==", "license": "MIT", + "dependencies": { + "@deepseek-ai/schemastery": "^3.18.1" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "clsx": "^2.1.1", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-terminal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-permission-presets": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-permission-presets/-/dsh-client-ui-permission-presets-0.1.0-rc.6.tgz", - "integrity": "sha512-6Im98frB6nfM82HWOtAxGmN1lJHZnkwTJNcK9oX6piA+vyQ3LPXAmXq9dmTh/qMeIVgFkE+IljjuQ6hP0Wu8hQ==", + "node_modules/@deepseek-ai/dsh-tool-call-timeout-policy": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-call-timeout-policy/-/dsh-tool-call-timeout-policy-0.1.0-rc.7.tgz", + "integrity": "sha512-GKmrKxwfIhk51dEEzWjvPKTZ2SK/RNxKXROAaSsZ/HGcerv2kmBHRCEPlaphKBoWhFuw7KAhDnzI6foXLg4BWQ==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-schema-form": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-permission-presets": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-plan": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-plan/-/dsh-client-ui-plan-0.1.0-rc.6.tgz", - "integrity": "sha512-9M3IOty+8exURc2h/favb3g5YRb8bkE1X1chyQjAaBqCDN8F3wtBSgc+jrYXW/mOabiM1vygliejvI7bDEjHhg==", + "node_modules/@deepseek-ai/dsh-tool-cordis": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-cordis/-/dsh-tool-cordis-0.1.0-rc.7.tgz", + "integrity": "sha512-tzZ1A+HhfqkMyOWwPgkWezY34rrK/OHD6BBX9DZ4km5/545JZ37+jmViza4TwrUhVxbs+Szhrx6g6V3Hm+674A==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-plan-mode": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-cordis-host-runner": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-settings": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-settings/-/dsh-client-ui-settings-0.1.0-rc.6.tgz", - "integrity": "sha512-g+6w62SWnwMWkn6VuLK6MHcSKbXQZD7oTYLG5wjhDRDULOEBCgikXD3LJo/esOsVncXABDiih8KuDW3Fg8TfSQ==", + "node_modules/@deepseek-ai/dsh-tool-fs": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-fs/-/dsh-tool-fs-0.1.0-rc.7.tgz", + "integrity": "sha512-/Uf2z6OZckk0Nz7XjVbzf/yUnvDeY58CkUjAqy2FxgGuNc0rvIR6VzRER5NZ+30bXeB8TPnjMuCVB+j/8zltrw==", "license": "MIT", + "dependencies": { + "@deepseek-ai/schemastery": "^3.18.1", + "diff": "^9.0.0" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-schema-form": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-attachment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-fs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-settings-general": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-settings-general/-/dsh-client-ui-settings-general-0.1.0-rc.6.tgz", - "integrity": "sha512-AmN1VkT4YJq0Tg7odtLteFGLvGZCklbmL/uCCc3YHw6bQ/n+ZE+92tPMDxjMfHVPPcwqQS5T57ReLdAzJ3WyHA==", + "node_modules/@deepseek-ai/dsh-tool-fs-search": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-fs-search/-/dsh-tool-fs-search-0.1.0-rc.7.tgz", + "integrity": "sha512-0Lo6bbpPcSMKZlWkBGx2KjwyLy5zYJKMH8fmwz8orwOKHjbfYQT51GV9cpdhLq6NYTwKeMUaxTZC4xPlZ03SAg==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", "@deepseek-ai/schemastery": "^3.18.1", - "clsx": "^2.0.0" + "@vscode/ripgrep": "^1.18.0" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-sidebar": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-output-retention": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-spill": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" + } + }, + "node_modules/@deepseek-ai/dsh-tool-goal": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-goal/-/dsh-tool-goal-0.1.0-rc.7.tgz", + "integrity": "sha512-bQTVYD7nAtddefQZvvoKsoRHehA/hAHIPbNRdY+L97HVwKnowg5rlcUn/v+MJFQ1NPaTrTAfVQiHXGKEeeI9tA==", + "license": "MIT", + "dependencies": { + "@deepseek-ai/schemastery": "^3.18.1" + }, + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-settings-models": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-settings-models/-/dsh-client-ui-settings-models-0.1.0-rc.6.tgz", - "integrity": "sha512-cgY7Em1QNwVK+ou2hI6i/vQj8MZK44US/u84wA6zuqvtDTP45jgNfYZBy1BCWnnUh6HslXVLj/1WzawEZn3YLw==", + "node_modules/@deepseek-ai/dsh-tool-jobs": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-jobs/-/dsh-tool-jobs-0.1.0-rc.7.tgz", + "integrity": "sha512-n/YcmHVTBrN3soZqzMElsnzIQoClOS3U1n5oqpg+oPyesMehpp7DFjdqh7kCZGEmI8chtq4AhYsPUWTPo85G7g==", "license": "MIT", + "dependencies": { + "@deepseek-ai/schemastery": "^3.18.1" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-schema-form": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-jobs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-output-retention": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-settings-plugin-inventory": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-settings-plugin-inventory/-/dsh-client-ui-settings-plugin-inventory-0.1.0-rc.6.tgz", - "integrity": "sha512-XRozBoG63/lH2gG8rnISASD3PwPGM429OQVXpJtryR/aPqsLoUzwAefmVETbuWlt25R82dbmGiX/y45dAdG30g==", + "node_modules/@deepseek-ai/dsh-tool-pwsh": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-pwsh/-/dsh-tool-pwsh-0.1.0-rc.7.tgz", + "integrity": "sha512-J24DC4otd3gAVvJ2jPpCfxrrujB/5isEqScp53O2vSvFP7rKn/Rwo8ddr1v462JVWyUG5HtyKpR23cPmQrP0+w==", "license": "MIT", + "dependencies": { + "@deepseek-ai/schemastery": "^3.18.1" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-jobs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell-env": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-settings-plugins": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-settings-plugins/-/dsh-client-ui-settings-plugins-0.1.0-rc.6.tgz", - "integrity": "sha512-KdBqYbXmkt5WMdEC9Hi0jcCd4T19YqE4VgdZSFBsvNHR4RVMAS4G7EgZey2NdAl911Imc/kKsANxWLZ/ETquwQ==", + "node_modules/@deepseek-ai/dsh-tool-ralph": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-ralph/-/dsh-tool-ralph-0.1.0-rc.7.tgz", + "integrity": "sha512-1ZCj5w7GRcbs0zuDiDpZLJKc1zs/WSn1WX9VWTuXvWocV66Rq8GGMZLGDksBeltd+jv/dym7xro4+xFl87059Q==", "license": "MIT", "dependencies": { - "clsx": "^2.0.0" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-workflow": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-sidebar": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-sidebar/-/dsh-client-ui-sidebar-0.1.0-rc.6.tgz", - "integrity": "sha512-q31eeswx19M8tKeMFsDTluWWi9fqZ/m4l8xT5m6eTB50pFFkaPHcl10uHzhCOOxKPMUX3HM4TjyoOclZXruT0Q==", + "node_modules/@deepseek-ai/dsh-tool-skill": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-skill/-/dsh-tool-skill-0.1.0-rc.7.tgz", + "integrity": "sha512-AnXLgiDXq8qB196qq4LnJ6rC5ukoPA4WZH+ILSFpLm59owkfwJLS9rGsfP+PGqiTN7NhoZtAwGmZoYCdSDi0kA==", "license": "MIT", "dependencies": { - "clsx": "^2.0.0" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-skill": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-skill": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-skill/-/dsh-client-ui-skill-0.1.0-rc.6.tgz", - "integrity": "sha512-ucxbx/It3eZodYUfW6tcygYtvERm0xojcpb5OjQ1YwkNh8ldplnDioONTdDVqVTDczIz8vM66QvASr8K3kFMSg==", + "node_modules/@deepseek-ai/dsh-tool-str-replace-editor": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-str-replace-editor/-/dsh-tool-str-replace-editor-0.1.0-rc.7.tgz", + "integrity": "sha512-p4GmCg5wC9uw9BaVK9W0hOnEnjGvhhRF234ClVnQMbHwzfgPbhc0eSYUNJQmouqxLAa4kVuiF0nVZvc3aftCeQ==", "license": "MIT", + "dependencies": { + "@deepseek-ai/schemastery": "^3.18.1" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-tool": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-fs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-subagent": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-subagent/-/dsh-client-ui-subagent-0.1.0-rc.6.tgz", - "integrity": "sha512-8yZkEhPCoOhtDfz1k6lzjF89QS+9zL188dQytCIXUewlhReva6UdoNvIX0OW1a6evDlZ/Vpn2P+mLb4sRG7n7w==", + "node_modules/@deepseek-ai/dsh-tool-subagent": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-subagent/-/dsh-tool-subagent-0.1.0-rc.7.tgz", + "integrity": "sha512-QWs7SeItxpaJ3zY5Vh0scAv84QI+ZRyg9+dws15H88T+dp9dRr4gmR+fqEUdwd9JhPJF5VIORtKY/MqVtaiYQA==", "license": "MIT", "dependencies": { - "react": "^18.2.0" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-token-meter": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-jobs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" + } + }, + "node_modules/@deepseek-ai/dsh-tool-subagent-control": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-subagent-control/-/dsh-tool-subagent-control-0.1.0-rc.7.tgz", + "integrity": "sha512-VPWUrhTc+X9DcrM/WC+ikM7vCjW54KzRU9wfdhFbXD6hea3hBQ4AlhEdtFtRwmgv3HmjYIUgHkPA3h7pqTsB1Q==", + "license": "MIT", + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-theme": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-theme/-/dsh-client-ui-theme-0.1.0-rc.6.tgz", - "integrity": "sha512-Wu+bvnuti/gLA+t5a2cWUMQJ5UCqxt6oEK+OJiJ68gN0ixs2skpaN0nFdFoY2exC5KByXrNlN1rRrD+FsZSBLA==", + "node_modules/@deepseek-ai/dsh-tool-subagent-report": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-subagent-report/-/dsh-tool-subagent-report-0.1.0-rc.7.tgz", + "integrity": "sha512-bdDcRsiB9t4EILfA4gO+FWwXrj6SA12SP0nqymz5yOI5AJWR6pzuIOwRk7IdguHBzq8pDyfelw0YxN+EtkS+tA==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/schemastery": "^3.18.1", - "clsx": "^2.0.0" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-tool": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-tool/-/dsh-client-ui-tool-0.1.0-rc.6.tgz", - "integrity": "sha512-pjNksBDDwWdRTb+YiZ1DSXWPipfw7C89B4bydopjwBtacOmx+rZH8Z9i8iFpmMwD5IFVd9ZJzwRR44sYkiun5g==", + "node_modules/@deepseek-ai/dsh-tool-todo": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-todo/-/dsh-tool-todo-0.1.0-rc.7.tgz", + "integrity": "sha512-Jm00eSYvNq8Qj5GmXdsC7EY3Q6TLSzBTiODNAu2bs5HxEqE5ssQ/fdcxuAXAfSFmh2Vq0ENLZckDg3q5Xvj6Qg==", "license": "MIT", "dependencies": { - "clsx": "^2.0.0" + "@deepseek-ai/schemastery": "^3.18.1", + "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-trajectory": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-trajectory/-/dsh-client-ui-trajectory-0.1.0-rc.6.tgz", - "integrity": "sha512-pTAXYZHfbiRieYzfpH+BmLC2RXA2SDqT4oxGmW5sr2frBOXCZMsDEXJ/r770tmgQW9hzQaK58Nua74ru/bQg2Q==", + "node_modules/@deepseek-ai/dsh-tool-web": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-web/-/dsh-tool-web-0.1.0-rc.7.tgz", + "integrity": "sha512-FJyrD+LspCOIP05/v9hv6MJNkTbgDw8ZpmyAXk6sRopA3yOUju5SnN5HpSZ97ZAK65T6tHYbTMdJhy51D41wOw==", "license": "MIT", "dependencies": { - "@tanstack/react-virtual": "^3.14.9", - "diff": "^9.0.0" + "@deepseek-ai/schemastery": "^3.18.1", + "@joplin/turndown-plugin-gfm": "^1.0.67", + "turndown": "^7.2.4" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-compaction": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-web": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-user-questions": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-user-questions/-/dsh-client-ui-user-questions-0.1.0-rc.6.tgz", - "integrity": "sha512-NiO6w/10LfohgdQKbAihentLzQ72xnc9GdGTZ0DQTEpDu9l712g8OFeFOTcTWycn03N9+tBBTMxt/L21aavMVw==", + "node_modules/@deepseek-ai/dsh-tool-workflow": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tool-workflow/-/dsh-tool-workflow-0.1.0-rc.7.tgz", + "integrity": "sha512-EF9qbGiCK+SdFhckVcS8o4F0Rrib4VEbt5yCe0njj4UrHubjz5Ldmz68TqdrvFqw6mvQ11SUqAm1ookp5hp8gA==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "clsx": "^2.0.0", - "react": "^18.2.0" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-workflow": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-workflow-run": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-workflow-run/-/dsh-client-ui-workflow-run-0.1.0-rc.6.tgz", - "integrity": "sha512-RqaBep4GdAsa2lZ1u2FPsu564EsiloPkvmfU1Nyi5j7+h+azx0wfxAzs5WI++TApm2qsbaHYLK/yxAlkyW89NQ==", + "node_modules/@deepseek-ai/dsh-tools": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-tools/-/dsh-tools-0.1.0-rc.7.tgz", + "integrity": "sha512-7Kq3EEv354aNcxbS0NRfxxyJiZhCsvFV/03a3MdkYO/gG2eM9+E4xQum0N2FL5bw7JiGlgw8jdLMkcNGmavEaA==", "license": "MIT", "dependencies": { - "react": "^18.2.0" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tool-workflow": "^0.1.0-rc.6", - "@deepseek-ai/dsh-workflow": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-code-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7", + "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-client-ui-workspace": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-workspace/-/dsh-client-ui-workspace-0.1.0-rc.6.tgz", - "integrity": "sha512-5Ajod9AuYaw4gMw0DNVVA5XEg9bm/kkWaJwXWw73JQG0FuRFRxNtVtN2p04lRVdZ9v0o2IkvNLVrnexur3S+uA==", + "node_modules/@deepseek-ai/dsh-typert-loader": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-typert-loader/-/dsh-typert-loader-0.1.0-rc.7.tgz", + "integrity": "sha512-0sU6QDo5/8/F7eIi9YGOqI4PTz34O6+NOUr3qRK6U3m6YWh4SVzn1Fc5LXqpnaZPNQpetuLnkvTvFylewBghJA==", "license": "MIT", "dependencies": { - "clsx": "^2.0.0" + "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/cordis-plugin-loader": "^1.0.2", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-cordis-client-runner": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-cordis-client-runner/-/dsh-cordis-client-runner-0.1.0-rc.6.tgz", - "integrity": "sha512-ESZ/Gd4E8F4VjNETEvS5EGeYn1J2CpLMlEHjklaE8HJ1lww/D9D9AMYQVvcn+QmnF0mX3pqmwmeKtA2lh5hOqA==", + "node_modules/@deepseek-ai/dsh-typert-protocol": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-typert-protocol/-/dsh-typert-protocol-0.1.0-rc.7.tgz", + "integrity": "sha512-R7qdvaRRHbz5xijoVOxueeBB/VT0eDzuQNQN4iNEBUbI/L9xG9bZutktTQlgrIlBSn1sPH4pLqiCiM6ErQPTaQ==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/cordis-plugin-loader": "^1.0.2", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-modules": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-theme": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-host-directory-picker-auto": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-host-directory-picker-auto/-/dsh-host-directory-picker-auto-0.1.0-rc.6.tgz", - "integrity": "sha512-0jtXMY67uVQOmYjQKxN3PbJrrCEe5YjDpjw+gpQyuclglyZbZpDzAaoboRnp5PyvM/EQPS+TK/v05/7QNj/owA==", + "node_modules/@deepseek-ai/dsh-typert-registry": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-typert-registry/-/dsh-typert-registry-0.1.0-rc.7.tgz", + "integrity": "sha512-7AQNJLNZTw7/5DzjbfBy4dRqr6VSwc74HBOSPpxm0zzzbmXOEqRCRzMps25IByoAeltRz1ZyY4fzN3tcYa+XwQ==", "license": "MIT", + "dependencies": { + "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7", + "zod": "^4.4.3" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/cordis-plugin-loader": "^1.0.2", - "@deepseek-ai/dsh-client-ui-directory-picker-browse": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-directory-picker-native": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-directory-picker-browse": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-directory-picker-native": "^0.1.0-rc.6", - "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6" + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/@deepseek-ai/dsh-session-log-export": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-session-log-export/-/dsh-session-log-export-0.1.0-rc.6.tgz", - "integrity": "sha512-/4JSblyx7p3uxgVXe/YJSqd7rfXzclKjhi7/XmAj32P/fFAsmD2BIjIykgqdyyg07N2twxpGuH0P6jtlrmOiBg==", + "node_modules/@deepseek-ai/dsh-user-approval": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-user-approval/-/dsh-user-approval-0.1.0-rc.7.tgz", + "integrity": "sha512-kYMpU6eg1m1BcfSC4FLWUcNH/QAE8tcu0WRkQzqzoCw8bK/Nl3dqHtd2qSVzI/emIviTulM5I230e4wPi/kuVg==", "license": "MIT", + "dependencies": { + "@deepseek-ai/schemastery": "^3.18.1" + }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-commands": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/commander": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", - "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==", + "node_modules/@deepseek-ai/dsh-user-questions": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-user-questions/-/dsh-user-questions-0.1.0-rc.7.tgz", + "integrity": "sha512-dfT6pj84lJdhrtbW2pV6hRftoKDkqx0aJevrhUhOy7Lv3CqTOheuLwwyT69Lww+n/q80Z+yp41qJq9loCkrOaw==", "license": "MIT", - "engines": { - "node": ">=22.12.0" + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7" } }, - "node_modules/@deepseek-ai/dsh-web-app/node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "node_modules/@deepseek-ai/dsh-web": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-web/-/dsh-web-0.1.0-rc.7.tgz", + "integrity": "sha512-v3Wx/Kn57RyLDqvEhmz0m0p4YluLGSabmMp7dRVJSemYUzT6ZB0JCtMhWkXh6O3kNHSBGpfxeY9Pk+8k80X11Q==", "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0" + "@deepseek-ai/schemastery": "^3.18.1" }, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7" + } + }, + "node_modules/@deepseek-ai/dsh-web-app": { + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-web-app/-/dsh-web-app-0.1.0-rc.7.tgz", + "integrity": "sha512-hcpVwEk5/SgZ63TRUmGaQsC1p2zBBSO8/KAr4xfM2XSwq/tbvpMLrkyt1zehBXcsx6ijB2s62bsr6AYOz9EczA==", + "license": "MIT", + "dependencies": { + "@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.7", + "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.7", + "@deepseek-ai/dsh-app-boot": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-hmr": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-modules": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-agent-preset": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-commands": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-cordis": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-deliverables": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-directory-picker-browse": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-directory-picker-native": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-goal": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-jobs": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-layout": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-message-feedback": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-model-selection": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-permission-presets": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-plan": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings-general": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings-models": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings-plugin-inventory": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-sidebar": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-skill": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-theme": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-tool": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-trajectory": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-user-questions": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-workflow-run": "^0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-workspace": "^0.1.0-rc.7", + "@deepseek-ai/dsh-cmdline": "^0.1.0-rc.7", + "@deepseek-ai/dsh-code-runtime-worker-thread": "^0.1.0-rc.7", + "@deepseek-ai/dsh-cordis-client-runner": "^0.1.0-rc.7", + "@deepseek-ai/dsh-cordis-host-runner": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-apiproxy": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-directory-picker-auto": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-directory-picker-browse": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-directory-picker-native": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-frontend-static": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-plugin-inventory": "^0.1.0-rc.7", + "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.7", + "@deepseek-ai/dsh-message-feedback": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-log-export": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-projection-cache": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-stats": "^0.1.0-rc.7", + "@deepseek-ai/dsh-storage": "^0.1.0-rc.7", + "@deepseek-ai/dsh-storage-domain": "^0.1.0-rc.7", + "@deepseek-ai/dsh-storage-json": "^0.1.0-rc.7", + "@deepseek-ai/dsh-web-frontend": "^0.1.0-rc.7", + "@deepseek-ai/dsh-workspace": "^0.1.0-rc.7", + "@deepseek-ai/schemastery": "^3.18.1", + "commander": "^15.0.0" + }, + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/cordis-plugin-loader": "^1.0.2", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-shell-env": "^0.1.0-rc.7", + "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-web-frontend": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-web-frontend/-/dsh-web-frontend-0.1.0-rc.6.tgz", - "integrity": "sha512-+RpdDF11FqUZSbJGoZ4oLIk/4PJR+ynTS4ELMn9QqucbYZ8tv0Itq9ZtG2o6pKIe7NO0lj/eBjCR2EoRKx7L+g==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-web-frontend/-/dsh-web-frontend-0.1.0-rc.7.tgz", + "integrity": "sha512-U9Neu6x2/0hrDwCeExEjGO9KkXiJEoJgp61QF/XQkaHyg4E7YSWZDG9NttlhepqFgqs6Dn/qcjrL5G0JGuWYeA==", "license": "MIT", "dependencies": { - "@deepseek-ai/dsh-client-web": "^0.1.0-rc.6", + "@deepseek-ai/dsh-client-web": "^0.1.0-rc.7", "react": "^18.2.0", "react-dom": "^18.2.0" } @@ -4702,142 +4712,74 @@ } }, "node_modules/@deepseek-ai/dsh-web-search-deepseek": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-web-search-deepseek/-/dsh-web-search-deepseek-0.1.0-rc.6.tgz", - "integrity": "sha512-+p3eOiUIN5Gk8KLjgAgIXmC6Y/db7LDb1TQ+iCAxz/zNJ2vbGVAoP+Br2jSUA1vbUdHTj49zTEWAQKaebuldCw==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-web-search-deepseek/-/dsh-web-search-deepseek-0.1.0-rc.7.tgz", + "integrity": "sha512-NciK9Tm68RK5XOzl+Jcr4+eG6M5Svq1/23Mhjor9QVYPW1J+wnyxUt6RKLIrmjyiS6VOCOCcZVtyITFkkfVaSQ==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-web": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-credentials": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-settings": "^0.1.0-rc.7", + "@deepseek-ai/dsh-web": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-workflow": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-workflow/-/dsh-workflow-0.1.0-rc.6.tgz", - "integrity": "sha512-zpTqaEp5/aXp3Zj5OfpZpTZxncak8af0FSSCOj5e6Eo6+o6cW2Y48fPk5Rl9Dzcbm/x4Y4PZfJSyqazeA27YeA==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-workflow/-/dsh-workflow-0.1.0-rc.7.tgz", + "integrity": "sha512-PRGT0iF2KcOTxDC1DDIrNOe9bID3zZms902ScrxGAGj8AksRO97kj+3U2MOhRPfHkkNhSQMHCLt42DiclYhWtA==", "license": "MIT", "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-workflow-worker-thread": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-workflow-worker-thread/-/dsh-workflow-worker-thread-0.1.0-rc.6.tgz", - "integrity": "sha512-PE5F8KW/qPmRzDoyC5EDw+44S1W7EDW+Iwox4l0LNG/WUqeARiRHVtTaNoEQyUqOZwUc6hs11SHlp1cZvwNHfg==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-workflow-worker-thread/-/dsh-workflow-worker-thread-0.1.0-rc.7.tgz", + "integrity": "sha512-v0YIoPylB1SJW5gBV8gaqoE0PCAZLzEgIU5OqckBKiApHBd0jIo7EzCeTW9+9Tzd8gwwcBQYv7Yxr++rmH8WGQ==", "license": "MIT", "dependencies": { "@deepseek-ai/schemastery": "^3.18.1" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", - "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", - "@deepseek-ai/dsh-workflow": "^0.1.0-rc.6" + "@deepseek-ai/dsh-agent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.7", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.7", + "@deepseek-ai/dsh-workflow": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/dsh-workspace": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-workspace/-/dsh-workspace-0.1.0-rc.6.tgz", - "integrity": "sha512-3R5mX5JTBD9jDpUdauqaswDlxxJzlrRtJ7aH4Ok5jPdlxw0LhC5aIsS5S5RCtFLI1xDzonnInEczjmqmdGQcDQ==", + "version": "0.1.0-rc.7", + "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-workspace/-/dsh-workspace-0.1.0-rc.7.tgz", + "integrity": "sha512-0czW0bI+uFFOS8h8eJ9SGZSdv+StEsa/+E1WEjZQXVeIOxo520Pv47dq+Z3mTyBfV8gJB+UcY0AQ3F0FddYohg==", "license": "MIT", "dependencies": { "zod": "^4.4.3" }, "peerDependencies": { "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-brand": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session": "^0.1.0-rc.6", - "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6", - "@deepseek-ai/dsh-storage": "^0.1.0-rc.6", - "@deepseek-ai/dsh-storage-domain": "^0.1.0-rc.6" - } - }, - "node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/dsh-client-ui-agent-preset": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-agent-preset/-/dsh-client-ui-agent-preset-0.1.0-rc.6.tgz", - "integrity": "sha512-kJeQdVrUZ0skjyWIAwf+YKZE4VgUXT/7HGQvRVWSWRRlQ0X3dlWUgJnDDzcWBt+cn0cfR5/CANPrPiYEveBxdw==", - "license": "MIT", - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" - } - }, - "node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/dsh-client-ui-cordis": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-cordis/-/dsh-client-ui-cordis-0.1.0-rc.6.tgz", - "integrity": "sha512-gYCef2obc7UMKOjneFvU8pTK2FehGNI9rqvZW9i1CUZ5pSJjAzJ14C4noIMPQxCrhj37QehrxyAC6Z+XzKYEYg==", - "license": "MIT", - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-sidebar": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-tool": "^0.1.0-rc.6", - "@deepseek-ai/dsh-cordis-client-runner": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" - } - }, - "node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/dsh-cordis-client-runner": { - "version": "0.1.0-rc.6", - "resolved": "https://registry.npmjs.org/@deepseek-ai/dsh-cordis-client-runner/-/dsh-cordis-client-runner-0.1.0-rc.6.tgz", - "integrity": "sha512-ESZ/Gd4E8F4VjNETEvS5EGeYn1J2CpLMlEHjklaE8HJ1lww/D9D9AMYQVvcn+QmnF0mX3pqmwmeKtA2lh5hOqA==", - "license": "MIT", - "peerDependencies": { - "@deepseek-ai/cordis": "^4.0.1", - "@deepseek-ai/cordis-plugin-loader": "^1.0.2", - "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-modules": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-theme": "^0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6", - "react": "^18.2.0" - } - }, - "node_modules/@deepseek-ai/dsh/node_modules/commander": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", - "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==", - "license": "MIT", - "engines": { - "node": ">=22.12.0" + "@deepseek-ai/dsh-brand": "^0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session": "^0.1.0-rc.7", + "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.7", + "@deepseek-ai/dsh-storage": "^0.1.0-rc.7", + "@deepseek-ai/dsh-storage-domain": "^0.1.0-rc.7" } }, "node_modules/@deepseek-ai/node-addon-landlock-run": { @@ -8092,12 +8034,12 @@ } }, "node_modules/@smithy/core": { - "version": "3.33.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.33.0.tgz", - "integrity": "sha512-uKbkxgqLyepQDZoq8aRSdUqD1ID//rOqG96ixBhp++O7vBtmwYM6fwldGhr9HJP0iYrdc7GP/AlgzPWEZIrNRg==", + "version": "3.33.2", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.33.2.tgz", + "integrity": "sha512-CUGXpnPkVdjUCbix+83sWLW9VFgQOm44MDOx/ihITJMAnOZKvL8YYIc7DR9pP/tZ8CIRvMiON/TucvygqbHO3w==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.17.0", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -8105,13 +8047,13 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.5.0.tgz", - "integrity": "sha512-2jsPi+7Zv2hSzD9IXR9D7DTqSn7mv4XalzRm+bESh53jiaUS3NKEUbpQFTJP0HhQy9qzZvluxQ3yS24zdRrqsA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.5.2.tgz", + "integrity": "sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.32.0", - "@smithy/types": "^4.17.0", + "@smithy/core": "^3.33.2", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -8119,13 +8061,13 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.7.0.tgz", - "integrity": "sha512-W/exA8T0LEzCQtJ02w4IzaEQPIspgarqZprb7W8FwnYiDowgCrjl2fTQ6FvuSSUnJORuepBF81abmBJwqh+0XQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.7.2.tgz", + "integrity": "sha512-nZyWTmSpJEXl6VtWVMBJve/7x12DZu6sIX1z1a+ZMaHlQQRs9Zpu6NbTe/gmxYXVRpkjxyDYpZ5gx2IM6f/Wkw==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.32.0", - "@smithy/types": "^4.17.0", + "@smithy/core": "^3.33.2", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -8159,13 +8101,13 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.7.0.tgz", - "integrity": "sha512-hCynhm22wMJ8wTF9crcwu8mxggtUrSLLJgDcGUvYFBqpofxycYJCGKOMYg4xtPPFtgNiDJSYmhsWLTrcU/g59Q==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.7.2.tgz", + "integrity": "sha512-P7Ki6px6OOrxVtx8K7nLmyx4SlXUW/uTKDdMG44UHefmPGSRMBKe2v+TM59WdLcpUIrBrnuCsIqiM2MbsZjmhw==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.32.0", - "@smithy/types": "^4.17.0", + "@smithy/core": "^3.33.2", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -8173,9 +8115,9 @@ } }, "node_modules/@smithy/types": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.17.0.tgz", - "integrity": "sha512-Aw4joiM0ZdErpo39lCj8phT2lxoiKZV+KZzBxnnQhWVtU2Is/WffQSL04uUWRcXUse9Ln8vXZK6V/FwqRVnQpg==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.17.2.tgz", + "integrity": "sha512-FOKpVZob9MPTn2znRzGrnsMHv7BOsKVw3XiP/cOyYLDVZ9qKp4nifIiSCuUU/fIj5Vu0UOAxCFr+qRAtG0NUkA==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -8581,12 +8523,12 @@ } }, "node_modules/@tanstack/react-virtual": { - "version": "3.14.9", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.14.9.tgz", - "integrity": "sha512-qZyr0FZDP8rDC4WBhsryIZmAd9bveJvFGUJJtskWaew6/0dTRS6wZxnR6VQ5bY2KwL3LjerrHqQLk3a0GKcPXQ==", + "version": "3.14.10", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.14.10.tgz", + "integrity": "sha512-SRyoUbdFMRHuYXMijV5H4ZarQWpXkj3iANq8OFre+pybeVap8ZJjZ3Nz9bVjx4d8PfobVUQUdKyyyHYk3E+djw==", "license": "MIT", "dependencies": { - "@tanstack/virtual-core": "3.17.7" + "@tanstack/virtual-core": "3.17.8" }, "funding": { "type": "github", @@ -8598,9 +8540,9 @@ } }, "node_modules/@tanstack/virtual-core": { - "version": "3.17.7", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.17.7.tgz", - "integrity": "sha512-bp+v10y65sp2H7WpWfIMyxTNfl8ZVfxFTLRjPIFRryi6FV/J33z4IS53WO4pTk36KlvJ4iLiQz+oaydDC1xbcA==", + "version": "3.17.8", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.17.8.tgz", + "integrity": "sha512-BfEvehNpOT75r5Ksc5xW6NZuXujTfb7nlSEyVu4XHG3gdxNg1KqXruWbDewXOUaUYIo4oRbSfkjIajz4MAT8tA==", "license": "MIT", "funding": { "type": "github", @@ -9736,6 +9678,12 @@ "d3-zoom": "^3.0.0" } }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "license": "BSD-2-Clause" + }, "node_modules/abbrev": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", @@ -9841,7 +9789,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -10709,7 +10656,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -10804,7 +10750,6 @@ "version": "9.7.0", "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.7.0.tgz", "integrity": "sha512-g/kR520giAFYkSXTzcmF3kqQq7wi8F6N6SzeDgZrqTBN+VHdmgWOyTdD1yD7AATDId/yXLvuP34CxW46/BwCdw==", - "dev": true, "license": "MIT", "dependencies": { "debug": "^4.3.4", @@ -10866,7 +10811,6 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -10964,7 +10908,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -11108,7 +11051,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -11121,7 +11063,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/combined-stream": { @@ -11147,6 +11088,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/commander": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", + "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==", + "license": "MIT", + "engines": { + "node": ">=22.12.0" + } + }, "node_modules/compare-version": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", @@ -11576,7 +11526,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -11866,6 +11815,34 @@ "dev": true, "license": "ISC" }, + "node_modules/electron-updater": { + "version": "6.8.9", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.8.9.tgz", + "integrity": "sha512-ZhVxM9iGONUpZGI1FxdMRgJjUFXi7AYGVa5PwKlO1tV1/4zDxQmfKpXOHVztKrd6L9rLcFjERvi1Mf2vxyTkig==", + "license": "MIT", + "dependencies": { + "builder-util-runtime": "9.7.0", + "fs-extra": "^10.1.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "lodash.escaperegexp": "^4.1.2", + "lodash.isequal": "^4.5.0", + "semver": "~7.7.3", + "tiny-typed-emitter": "^2.1.0" + } + }, + "node_modules/electron-updater/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/electron/node_modules/@electron/get": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@electron/get/-/get-5.0.0.tgz", @@ -12953,7 +12930,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -13000,6 +12976,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "license": "Apache-2.0", + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", @@ -13124,7 +13109,6 @@ "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", @@ -13559,7 +13543,6 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/has-bigints": { @@ -13579,7 +13562,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -13589,7 +13571,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -14125,6 +14106,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -14224,7 +14220,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -14398,11 +14393,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, "license": "MIT" }, "node_modules/isbinaryfile": { @@ -14562,6 +14568,25 @@ "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", "license": "BSD-2-Clause" }, + "node_modules/json-stable-stringify": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz", + "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "isarray": "^2.0.5", + "jsonify": "^0.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -14594,7 +14619,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", - "dev": true, "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -14603,6 +14627,15 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "license": "Public Domain", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -14688,6 +14721,15 @@ "json-buffer": "3.0.1" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -14749,7 +14791,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", - "dev": true, "license": "MIT" }, "node_modules/levn": { @@ -15061,6 +15102,19 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -16021,7 +16075,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -16117,7 +16170,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -16626,9 +16678,9 @@ "license": "MIT" }, "node_modules/node-pty": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/node-pty/-/node-pty-1.1.0.tgz", - "integrity": "sha512-20JqtutY6JPXTUnL0ij1uad7Qe1baT46lyolh2sSENDd4sTzKZ4nmAFkeAARDKwmlLjPx6XKRlwRUxwjOy+lUg==", + "version": "1.2.0-beta.15", + "resolved": "https://registry.npmjs.org/node-pty/-/node-pty-1.2.0-beta.15.tgz", + "integrity": "sha512-vORSzHXi4Ofl7HemVWpuudLqCPdaQb4LfpRCUpE5HPxhp4JYscl8zZwxh11p26v2wvW24WMwnMfLjhRLixrfxA==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -16696,7 +16748,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -16830,6 +16881,22 @@ "regex-recursion": "^6.0.2" } }, + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/openai": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/openai/-/openai-6.26.0.tgz", @@ -16997,6 +17064,62 @@ "integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==", "license": "MIT" }, + "node_modules/patch-package": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz", + "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==", + "license": "MIT", + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^10.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.2.4", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -17089,6 +17212,13 @@ "url": "https://github.com/sponsors/jet2jet" } }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -17099,7 +17229,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -18019,7 +18148,6 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", - "dev": true, "license": "BlueOak-1.0.0", "engines": { "node": ">=11.0.0" @@ -18115,7 +18243,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -18372,6 +18499,15 @@ "node": ">=10" } }, + "node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -18759,7 +18895,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -18867,6 +19002,12 @@ "dev": true, "license": "MIT" }, + "node_modules/tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.16", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", @@ -18919,7 +19060,6 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", - "dev": true, "license": "MIT", "engines": { "node": ">=14.14" @@ -18939,7 +19079,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -19397,7 +19536,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 10.0.0" @@ -20886,6 +21024,19 @@ "node": ">=12" } }, + "node_modules/yauzl": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.4.0.tgz", + "integrity": "sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -21015,7 +21166,7 @@ "version": "0.1.0", "license": "SEE LICENSE IN ../../LICENSE", "dependencies": { - "@deepseek-ai/dsh-mcp-client": "0.1.0-rc.6", + "@deepseek-ai/dsh-mcp-client": "0.1.0-rc.7", "yaml": "2.9.0", "zod": "^4.4.3" } diff --git a/package.json b/package.json index 5d2d7d0..28ee943 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "laobos-agent-studio", - "version": "0.2.3", + "version": "0.3.10", "description": "劳博士:基于 DeepSeek Harness 的本地 Agent 桌面客户端", "author": "Modole contributors", "license": "SEE LICENSE IN LICENSE", @@ -17,7 +17,7 @@ "ws": "8.21.3" }, "scripts": { - "postinstall": "node scripts/ensure-node-pty-helper.mjs", + "postinstall": "patch-package && node scripts/ensure-node-pty-helper.mjs", "dev": "npm run build:desktop-plugins && node scripts/start-dsh.mjs", "dev:full": "npm run build:desktop-plugins && node scripts/start-dsh.mjs", "start": "npm run build:desktop-plugins && node scripts/start-dsh.mjs", @@ -32,6 +32,8 @@ "desktop:package": "npm run build:desktop-plugins && node scripts/package-desktop.mjs", "desktop:make": "npm run build:desktop-plugins && node scripts/make-desktop.mjs", "desktop:installer": "npm run build:desktop-plugins && electron-builder --publish never", + "desktop:installer:test-update": "npm run build:desktop-plugins && electron-builder --config electron-builder.test-update.yml --publish never", + "release:mac:test": "npm run desktop:installer:test-update -- --mac dmg zip --arm64", "site:dev": "WRANGLER_LOG_PATH=.wrangler/wrangler.log vinext dev", "site:start": "WRANGLER_LOG_PATH=.wrangler/wrangler.log vinext start", "build": "WRANGLER_LOG_PATH=.wrangler/wrangler.log vinext build", @@ -44,35 +46,37 @@ "dependencies": { "@browserops/bridge": "^0.0.11", "@deepseek-ai/cordis-plugin-group": "1.0.1", - "@deepseek-ai/dsh": "0.1.0-rc.6", - "@deepseek-ai/dsh-anonymous-user-id": "0.1.0-rc.6", - "@deepseek-ai/dsh-atomic-write": "0.1.0-rc.6", - "@deepseek-ai/dsh-bash-local": "0.1.0-rc.6", - "@deepseek-ai/dsh-code-runtime": "0.1.0-rc.6", - "@deepseek-ai/dsh-client-ui-directory-picker-browse": "0.1.0-rc.6", - "@deepseek-ai/dsh-compaction": "0.1.0-rc.6", - "@deepseek-ai/dsh-fs": "0.1.0-rc.6", - "@deepseek-ai/dsh-host-directory-picker-browse": "0.1.0-rc.6", - "@deepseek-ai/dsh-invariants": "0.1.0-rc.6", - "@deepseek-ai/dsh-output-retention": "0.1.0-rc.6", - "@deepseek-ai/dsh-sandbox": "0.1.0-rc.6", - "@deepseek-ai/dsh-scope": "0.1.0-rc.6", - "@deepseek-ai/dsh-session-telemetry": "0.1.0-rc.6", - "@deepseek-ai/dsh-session-title-llm": "0.1.0-rc.6", - "@deepseek-ai/dsh-shell": "0.1.0-rc.6", - "@deepseek-ai/dsh-spill": "0.1.0-rc.6", - "@deepseek-ai/dsh-subagent-in-process-driver": "0.1.0-rc.6", - "@deepseek-ai/dsh-subprocess": "0.1.0-rc.6", - "@deepseek-ai/dsh-timeout": "0.1.0-rc.6", - "@deepseek-ai/dsh-workflow": "0.1.0-rc.6", + "@deepseek-ai/dsh": "0.1.0-rc.7", + "@deepseek-ai/dsh-anonymous-user-id": "0.1.0-rc.7", + "@deepseek-ai/dsh-atomic-write": "0.1.0-rc.7", + "@deepseek-ai/dsh-bash-local": "0.1.0-rc.7", + "@deepseek-ai/dsh-client-ui-directory-picker-browse": "0.1.0-rc.7", + "@deepseek-ai/dsh-code-runtime": "0.1.0-rc.7", + "@deepseek-ai/dsh-compaction": "0.1.0-rc.7", + "@deepseek-ai/dsh-fs": "0.1.0-rc.7", + "@deepseek-ai/dsh-host-directory-picker-browse": "0.1.0-rc.7", + "@deepseek-ai/dsh-invariants": "0.1.0-rc.7", + "@deepseek-ai/dsh-output-retention": "0.1.0-rc.7", + "@deepseek-ai/dsh-sandbox": "0.1.0-rc.7", + "@deepseek-ai/dsh-scope": "0.1.0-rc.7", + "@deepseek-ai/dsh-session-telemetry": "0.1.0-rc.7", + "@deepseek-ai/dsh-session-title-llm": "0.1.0-rc.7", + "@deepseek-ai/dsh-shell": "0.1.0-rc.7", + "@deepseek-ai/dsh-spill": "0.1.0-rc.7", + "@deepseek-ai/dsh-subagent-in-process-driver": "0.1.0-rc.7", + "@deepseek-ai/dsh-subprocess": "0.1.0-rc.7", + "@deepseek-ai/dsh-timeout": "0.1.0-rc.7", + "@deepseek-ai/dsh-workflow": "0.1.0-rc.7", "@laobos/dsh-performance": "file:packages/laobos-performance", "@laobos/dsh-shell": "file:packages/laobos-shell", "@laobos/dsh-system-tools": "file:packages/laobos-system-tools", "@xterm/addon-fit": "^0.11.0", "@xterm/xterm": "^6.0.0", "@xyflow/react": "12.11.3", + "electron-updater": "^6.8.9", "next": "16.2.11", - "node-pty": "^1.1.0", + "node-pty": "1.2.0-beta.15", + "patch-package": "8.0.1", "react": "19.2.6", "react-dom": "19.2.6", "ssh2": "^1.17.0", @@ -98,7 +102,8 @@ "typescript": "5.9.3", "vinext": "0.0.50", "vite": "8.0.13", - "wrangler": "4.92.0" + "wrangler": "4.92.0", + "yauzl": "3.4.0" }, "type": "module" } diff --git a/packages/laobos-app-manager/lib/client.js b/packages/laobos-app-manager/lib/client.js index c89f1cd..05fa7ac 100644 --- a/packages/laobos-app-manager/lib/client.js +++ b/packages/laobos-app-manager/lib/client.js @@ -17,7 +17,7 @@ .lbs-apps-list-wrap{min-height:0;overflow:auto}.lbs-apps-list-head,.lbs-apps-row{display:grid;gap:14px;grid-template-columns:minmax(250px,1.7fr) minmax(180px,1fr) 132px minmax(218px,auto);padding-left:14px;padding-right:10px}.lbs-apps-list-head{align-items:center;background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);font-size:8px;font-weight:600;height:29px;letter-spacing:.06em;position:sticky;text-transform:uppercase;top:0;z-index:2}.lbs-apps-row{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);min-height:72px;padding-bottom:9px;padding-top:9px;transition:background .14s ease}.lbs-apps-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-apps-row-main{align-items:center;display:grid;gap:9px;grid-template-columns:9px minmax(0,1fr);min-width:0}.lbs-apps-dot{background:#89939e;border-radius:50%;display:block;flex:none;height:7px;width:7px}.lbs-apps-dot[data-state=running]{background:#2ba36d;box-shadow:0 0 0 3px color-mix(in srgb,#2ba36d 16%,transparent)}.lbs-apps-dot[data-state=online]{background:#4b8ed6;box-shadow:0 0 0 3px color-mix(in srgb,#4b8ed6 15%,transparent)}.lbs-apps-dot[data-state=starting],.lbs-apps-dot[data-state=stopping]{background:#d49a29}.lbs-apps-dot[data-state=error]{background:#d94b4b}.lbs-apps-row-copy,.lbs-apps-service,.lbs-apps-status-copy{display:grid;gap:4px;min-width:0}.lbs-apps-row-title{align-items:center;display:flex;gap:7px;min-width:0}.lbs-apps-row-title strong{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-apps-badge{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:4px;color:var(--dsw-alias-label-tertiary);flex:none;font-size:8px;padding:1px 4px;text-transform:uppercase}.lbs-apps-row-sub,.lbs-apps-service span,.lbs-apps-service code,.lbs-apps-status-copy small{color:var(--dsw-alias-label-tertiary);font:9px/1.35 ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-apps-row-command{color:var(--dsw-alias-label-secondary);font-size:9px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-apps-service strong{font:10px/1.35 ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-apps-service span{font-family:inherit}.lbs-apps-status-line{align-items:center;display:flex;font-size:10px;font-weight:600;gap:6px}.lbs-apps-status-line .lbs-apps-dot{box-shadow:none;height:6px;width:6px}.lbs-apps-row-actions{align-items:center;display:flex;gap:2px;justify-content:flex-end}.lbs-apps-action{color:var(--dsw-alias-label-tertiary);position:relative}.lbs-apps-action-separator{background:var(--dsw-alias-border-l1);height:18px;margin:0 3px;width:1px}.lbs-apps-row-error{color:#d94b4b;font-size:9px;grid-column:1/-1;margin:-3px 0 0 18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-apps-empty-list{align-content:center;color:var(--dsw-alias-label-tertiary);display:grid;font-size:10px;gap:10px;justify-items:center;min-height:260px;padding:28px;text-align:center}.lbs-apps-empty-icon{align-items:center;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;display:flex;height:42px;justify-content:center;width:42px}.lbs-apps-empty-list strong{color:var(--dsw-alias-label-primary);font-size:12px}.lbs-apps-empty-list p{line-height:1.55;margin:0;max-width:360px} .lbs-apps-statusbar{align-items:center;background:var(--dsw-alias-bg-layer-1);border-top:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);display:flex;font-size:9px;gap:12px;padding:0 10px}.lbs-apps-statusbar span:last-child{margin-left:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-apps-error{background:#482129;border:1px solid #6d303a;border-radius:6px;color:#ffc4ca;font-size:10px;max-width:min(520px,calc(100% - 20px));padding:7px 10px;position:absolute;right:10px;top:84px;z-index:5} .lbs-apps-modal-backdrop{align-items:center;background:rgba(0,0,0,.46);display:flex;inset:0;justify-content:center;padding:22px;position:fixed;z-index:2147483220}.lbs-apps-modal{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;box-shadow:var(--dsw-shadow-lv3);display:grid;grid-template-rows:46px minmax(0,1fr) auto;max-height:min(780px,92vh);overflow:hidden;width:min(680px,calc(100vw - 34px))}.lbs-apps-modal.wide{width:min(850px,calc(100vw - 34px))}.lbs-apps-modal-header{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;padding:0 14px}.lbs-apps-modal-header h2{font-size:14px;margin:0}.lbs-apps-modal-header button{margin-left:auto}.lbs-apps-modal-body{min-height:0;overflow:auto;padding:15px}.lbs-apps-modal-footer{border-top:1px solid var(--dsw-alias-border-l1);display:flex;gap:7px;justify-content:flex-end;padding:10px 14px} - .lbs-apps-log-viewer{background:#101419;border:1px solid #2b323b;border-radius:8px;color:#dce5ed;display:grid;grid-template-rows:34px minmax(0,1fr);height:min(560px,65vh);min-height:280px;overflow:hidden}.lbs-apps-log-header{align-items:center;background:#181d23;border-bottom:1px solid #2b323b;color:#a9b5c0;display:flex;font-size:9px;gap:7px;padding:0 10px}.lbs-apps-log-header strong{color:#e1e8ee;font-size:10px}.lbs-apps-log-header span{margin-left:auto}.lbs-apps-log{font:10px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace;margin:0;min-height:0;overflow:auto;padding:10px;white-space:pre-wrap}.lbs-apps-log-empty{align-content:center;color:#74808b;display:grid;font-size:10px;height:100%;justify-items:center} + .lbs-apps-log-viewer{background:var(--dsw-alias-markdown-code-block,var(--dsw-alias-bg-layer-1));border:1px solid var(--dsw-alias-border-l2);border-radius:8px;color:var(--dsw-alias-label-primary);display:grid;grid-template-rows:34px minmax(0,1fr);height:min(560px,65vh);min-height:280px;overflow:hidden}.lbs-apps-log-header{align-items:center;background:var(--dsw-alias-markdown-code-block-banner,var(--dsw-alias-bg-layer-2));border-bottom:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);display:flex;font-size:9px;gap:7px;padding:0 10px}.lbs-apps-log-header strong{color:var(--dsw-alias-label-primary);font-size:10px}.lbs-apps-log-header span{margin-left:auto}.lbs-apps-log{font:10px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace;margin:0;min-height:0;overflow:auto;padding:10px;white-space:pre-wrap}.lbs-apps-log-empty{align-content:center;color:var(--dsw-alias-label-tertiary);display:grid;font-size:10px;height:100%;justify-items:center} .lbs-apps-form{display:grid;gap:13px}.lbs-apps-form-grid{display:grid;gap:10px;grid-template-columns:1fr 1fr}.lbs-apps-form label{color:var(--dsw-alias-label-secondary);display:grid;font-size:10px;gap:5px}.lbs-apps-form .wide{grid-column:1/-1}.lbs-apps-form input,.lbs-apps-form select,.lbs-apps-form textarea{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;box-sizing:border-box;color:inherit;font:11px inherit;min-height:32px;padding:6px 8px;width:100%}.lbs-apps-form textarea{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;min-height:330px;resize:vertical}.lbs-apps-port-field{display:grid;gap:5px;grid-template-columns:minmax(0,1fr) auto}.lbs-apps-help{color:var(--dsw-alias-label-tertiary);font-size:9px;line-height:1.5;margin:0}.lbs-apps-rule{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;display:grid;font-size:9px;gap:5px;line-height:1.5;padding:10px}.lbs-apps-rule strong{font-size:10px}.lbs-apps-form-error{color:#d94b4b;font-size:10px;margin:0}.lbs-apps-delete-copy{font-size:11px;line-height:1.6;margin:0}.lbs-apps-delete-copy strong{display:block;margin-bottom:5px} @media(max-width:1050px){.lbs-apps-list-head,.lbs-apps-row{grid-template-columns:minmax(220px,1.5fr) minmax(150px,1fr) 112px minmax(196px,auto);gap:9px}.lbs-apps-action{height:27px;width:27px}}@media(max-width:900px){.lbs-apps-panel{left:0;right:0}.lbs-apps-list-head,.lbs-apps-row{grid-template-columns:minmax(220px,1.5fr) minmax(150px,1fr) 105px minmax(190px,auto)}.lbs-apps-notice-summary{display:none}}@media(max-width:700px){.lbs-apps-panel{grid-template-rows:44px auto 48px minmax(0,1fr) 25px}.lbs-apps-list-head{display:none}.lbs-apps-row{gap:7px;grid-template-columns:minmax(0,1fr) auto;min-height:94px;padding:10px 9px 10px 12px}.lbs-apps-service{grid-column:1}.lbs-apps-status-copy{grid-column:2;grid-row:1}.lbs-apps-row-actions{grid-column:2;grid-row:2}.lbs-apps-row-error{grid-column:1/-1;margin-left:18px}.lbs-apps-notice>span:not(.lbs-apps-notice-summary){display:none}.lbs-apps-filter-meta{display:none}.lbs-apps-form-grid{grid-template-columns:1fr}.lbs-apps-form .wide{grid-column:auto}} `; diff --git a/packages/laobos-app-manager/src/client.jsx b/packages/laobos-app-manager/src/client.jsx index d03210c..125722b 100644 --- a/packages/laobos-app-manager/src/client.jsx +++ b/packages/laobos-app-manager/src/client.jsx @@ -16,7 +16,7 @@ window.__ModuleLoader__.load({ .lbs-apps-list-wrap{min-height:0;overflow:auto}.lbs-apps-list-head,.lbs-apps-row{display:grid;gap:14px;grid-template-columns:minmax(250px,1.7fr) minmax(180px,1fr) 132px minmax(218px,auto);padding-left:14px;padding-right:10px}.lbs-apps-list-head{align-items:center;background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);font-size:8px;font-weight:600;height:29px;letter-spacing:.06em;position:sticky;text-transform:uppercase;top:0;z-index:2}.lbs-apps-row{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);min-height:72px;padding-bottom:9px;padding-top:9px;transition:background .14s ease}.lbs-apps-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-apps-row-main{align-items:center;display:grid;gap:9px;grid-template-columns:9px minmax(0,1fr);min-width:0}.lbs-apps-dot{background:#89939e;border-radius:50%;display:block;flex:none;height:7px;width:7px}.lbs-apps-dot[data-state=running]{background:#2ba36d;box-shadow:0 0 0 3px color-mix(in srgb,#2ba36d 16%,transparent)}.lbs-apps-dot[data-state=online]{background:#4b8ed6;box-shadow:0 0 0 3px color-mix(in srgb,#4b8ed6 15%,transparent)}.lbs-apps-dot[data-state=starting],.lbs-apps-dot[data-state=stopping]{background:#d49a29}.lbs-apps-dot[data-state=error]{background:#d94b4b}.lbs-apps-row-copy,.lbs-apps-service,.lbs-apps-status-copy{display:grid;gap:4px;min-width:0}.lbs-apps-row-title{align-items:center;display:flex;gap:7px;min-width:0}.lbs-apps-row-title strong{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-apps-badge{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:4px;color:var(--dsw-alias-label-tertiary);flex:none;font-size:8px;padding:1px 4px;text-transform:uppercase}.lbs-apps-row-sub,.lbs-apps-service span,.lbs-apps-service code,.lbs-apps-status-copy small{color:var(--dsw-alias-label-tertiary);font:9px/1.35 ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-apps-row-command{color:var(--dsw-alias-label-secondary);font-size:9px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-apps-service strong{font:10px/1.35 ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-apps-service span{font-family:inherit}.lbs-apps-status-line{align-items:center;display:flex;font-size:10px;font-weight:600;gap:6px}.lbs-apps-status-line .lbs-apps-dot{box-shadow:none;height:6px;width:6px}.lbs-apps-row-actions{align-items:center;display:flex;gap:2px;justify-content:flex-end}.lbs-apps-action{color:var(--dsw-alias-label-tertiary);position:relative}.lbs-apps-action-separator{background:var(--dsw-alias-border-l1);height:18px;margin:0 3px;width:1px}.lbs-apps-row-error{color:#d94b4b;font-size:9px;grid-column:1/-1;margin:-3px 0 0 18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-apps-empty-list{align-content:center;color:var(--dsw-alias-label-tertiary);display:grid;font-size:10px;gap:10px;justify-items:center;min-height:260px;padding:28px;text-align:center}.lbs-apps-empty-icon{align-items:center;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;display:flex;height:42px;justify-content:center;width:42px}.lbs-apps-empty-list strong{color:var(--dsw-alias-label-primary);font-size:12px}.lbs-apps-empty-list p{line-height:1.55;margin:0;max-width:360px} .lbs-apps-statusbar{align-items:center;background:var(--dsw-alias-bg-layer-1);border-top:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);display:flex;font-size:9px;gap:12px;padding:0 10px}.lbs-apps-statusbar span:last-child{margin-left:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-apps-error{background:#482129;border:1px solid #6d303a;border-radius:6px;color:#ffc4ca;font-size:10px;max-width:min(520px,calc(100% - 20px));padding:7px 10px;position:absolute;right:10px;top:84px;z-index:5} .lbs-apps-modal-backdrop{align-items:center;background:rgba(0,0,0,.46);display:flex;inset:0;justify-content:center;padding:22px;position:fixed;z-index:2147483220}.lbs-apps-modal{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;box-shadow:var(--dsw-shadow-lv3);display:grid;grid-template-rows:46px minmax(0,1fr) auto;max-height:min(780px,92vh);overflow:hidden;width:min(680px,calc(100vw - 34px))}.lbs-apps-modal.wide{width:min(850px,calc(100vw - 34px))}.lbs-apps-modal-header{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;padding:0 14px}.lbs-apps-modal-header h2{font-size:14px;margin:0}.lbs-apps-modal-header button{margin-left:auto}.lbs-apps-modal-body{min-height:0;overflow:auto;padding:15px}.lbs-apps-modal-footer{border-top:1px solid var(--dsw-alias-border-l1);display:flex;gap:7px;justify-content:flex-end;padding:10px 14px} - .lbs-apps-log-viewer{background:#101419;border:1px solid #2b323b;border-radius:8px;color:#dce5ed;display:grid;grid-template-rows:34px minmax(0,1fr);height:min(560px,65vh);min-height:280px;overflow:hidden}.lbs-apps-log-header{align-items:center;background:#181d23;border-bottom:1px solid #2b323b;color:#a9b5c0;display:flex;font-size:9px;gap:7px;padding:0 10px}.lbs-apps-log-header strong{color:#e1e8ee;font-size:10px}.lbs-apps-log-header span{margin-left:auto}.lbs-apps-log{font:10px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace;margin:0;min-height:0;overflow:auto;padding:10px;white-space:pre-wrap}.lbs-apps-log-empty{align-content:center;color:#74808b;display:grid;font-size:10px;height:100%;justify-items:center} + .lbs-apps-log-viewer{background:var(--dsw-alias-markdown-code-block,var(--dsw-alias-bg-layer-1));border:1px solid var(--dsw-alias-border-l2);border-radius:8px;color:var(--dsw-alias-label-primary);display:grid;grid-template-rows:34px minmax(0,1fr);height:min(560px,65vh);min-height:280px;overflow:hidden}.lbs-apps-log-header{align-items:center;background:var(--dsw-alias-markdown-code-block-banner,var(--dsw-alias-bg-layer-2));border-bottom:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);display:flex;font-size:9px;gap:7px;padding:0 10px}.lbs-apps-log-header strong{color:var(--dsw-alias-label-primary);font-size:10px}.lbs-apps-log-header span{margin-left:auto}.lbs-apps-log{font:10px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace;margin:0;min-height:0;overflow:auto;padding:10px;white-space:pre-wrap}.lbs-apps-log-empty{align-content:center;color:var(--dsw-alias-label-tertiary);display:grid;font-size:10px;height:100%;justify-items:center} .lbs-apps-form{display:grid;gap:13px}.lbs-apps-form-grid{display:grid;gap:10px;grid-template-columns:1fr 1fr}.lbs-apps-form label{color:var(--dsw-alias-label-secondary);display:grid;font-size:10px;gap:5px}.lbs-apps-form .wide{grid-column:1/-1}.lbs-apps-form input,.lbs-apps-form select,.lbs-apps-form textarea{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;box-sizing:border-box;color:inherit;font:11px inherit;min-height:32px;padding:6px 8px;width:100%}.lbs-apps-form textarea{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;min-height:330px;resize:vertical}.lbs-apps-port-field{display:grid;gap:5px;grid-template-columns:minmax(0,1fr) auto}.lbs-apps-help{color:var(--dsw-alias-label-tertiary);font-size:9px;line-height:1.5;margin:0}.lbs-apps-rule{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;display:grid;font-size:9px;gap:5px;line-height:1.5;padding:10px}.lbs-apps-rule strong{font-size:10px}.lbs-apps-form-error{color:#d94b4b;font-size:10px;margin:0}.lbs-apps-delete-copy{font-size:11px;line-height:1.6;margin:0}.lbs-apps-delete-copy strong{display:block;margin-bottom:5px} @media(max-width:1050px){.lbs-apps-list-head,.lbs-apps-row{grid-template-columns:minmax(220px,1.5fr) minmax(150px,1fr) 112px minmax(196px,auto);gap:9px}.lbs-apps-action{height:27px;width:27px}}@media(max-width:900px){.lbs-apps-panel{left:0;right:0}.lbs-apps-list-head,.lbs-apps-row{grid-template-columns:minmax(220px,1.5fr) minmax(150px,1fr) 105px minmax(190px,auto)}.lbs-apps-notice-summary{display:none}}@media(max-width:700px){.lbs-apps-panel{grid-template-rows:44px auto 48px minmax(0,1fr) 25px}.lbs-apps-list-head{display:none}.lbs-apps-row{gap:7px;grid-template-columns:minmax(0,1fr) auto;min-height:94px;padding:10px 9px 10px 12px}.lbs-apps-service{grid-column:1}.lbs-apps-status-copy{grid-column:2;grid-row:1}.lbs-apps-row-actions{grid-column:2;grid-row:2}.lbs-apps-row-error{grid-column:1/-1;margin-left:18px}.lbs-apps-notice>span:not(.lbs-apps-notice-summary){display:none}.lbs-apps-filter-meta{display:none}.lbs-apps-form-grid{grid-template-columns:1fr}.lbs-apps-form .wide{grid-column:auto}} `; diff --git a/packages/laobos-browserops/lib/client.js b/packages/laobos-browserops/lib/client.js index 76fed7b..5967aa8 100644 --- a/packages/laobos-browserops/lib/client.js +++ b/packages/laobos-browserops/lib/client.js @@ -1,42 +1,135 @@ -/* eslint-disable @next/next/no-assign-module-variable -- DSH browser plugins use a CommonJS-style module factory */ -window.__ModuleLoader__.load({ - id: "@laobos/dsh-browserops", - factory: (require) => { - var module = { exports: {} }; var exports = module.exports; - Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); - const React = require("react"); - const { createElement: h, useEffect, useRef, useState } = React; - const css = `.lbs-browser-panel{background:var(--dsw-alias-bg-base);bottom:0;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483060}.lbs-browser-toolbar{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;flex:none;gap:5px;height:48px;padding:0 9px}.lbs-browser-toolbar button{appearance:none;background:transparent;border:0;border-radius:6px;color:inherit;cursor:pointer;font:inherit;font-size:12px;height:29px;padding:0 8px}.lbs-browser-toolbar button:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-browser-toolbar button:disabled{opacity:.4}.lbs-browser-address{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:7px;color:inherit;flex:1;font:12px ui-monospace,SFMono-Regular,Menlo,monospace;height:30px;min-width:90px;padding:0 9px}.lbs-browser-viewport{flex:1;min-height:0}.lbs-browser-ops{align-items:center;border-left:1px solid var(--dsw-alias-border-l1);display:flex;gap:5px;margin-left:4px;padding-left:8px}.lbs-browser-ops span{color:var(--dsw-alias-label-tertiary);font-size:10px;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-browser-error{background:rgba(218,70,70,.1);color:#d94b4b;font-size:12px;padding:7px 11px}@media(max-width:850px){.lbs-browser-panel{left:0;right:0}.lbs-browser-ops span{display:none}}`; - if (typeof document !== "undefined" && !document.querySelector('style[data-plugin-css="@laobos/dsh-browserops"]')) { const style = document.createElement("style"); style.dataset.pluginCss = "@laobos/dsh-browserops"; style.textContent = css; document.head.append(style); } - - function BrowserPanel() { - const [open, setOpen] = useState(false); const [address, setAddress] = useState("http://127.0.0.1:3000"); const [state, setState] = useState({}); const [ops, setOps] = useState({ state: "stopped", message: "" }); const [error, setError] = useState(""); const viewport = useRef(null); const addressRef = useRef(address); - useEffect(() => { addressRef.current = address; }, [address]); - useEffect(() => { const show = (event) => { if (event.detail?.tool === "close") { setOpen(false); return; } if (event.detail?.tool !== "browser") return; setOpen(true); setError(""); }; window.addEventListener("laobos:open-desktop-tool", show); return () => window.removeEventListener("laobos:open-desktop-tool", show); }, []); - useEffect(() => { - if (!open || !window.laobosDesktop?.capabilities?.browserPreview) return undefined; - let disposed = false; - const sync = () => { if (!viewport.current || disposed) return; const rect = viewport.current.getBoundingClientRect(); void window.laobosDesktop.browser.setBounds({ x: rect.left, y: rect.top, width: rect.width, height: rect.height }); }; - const observer = new ResizeObserver(sync); observer.observe(viewport.current); window.addEventListener("resize", sync); - const offState = window.laobosDesktop.browser.onState((value) => { setState(value); if (value.url) setAddress(value.url); }); - const offOps = window.laobosDesktop.browserOps.onState(setOps); - void window.laobosDesktop.browser.show(true).then((value) => { setState(value); sync(); if (!value.url) return window.laobosDesktop.browser.navigate(addressRef.current); }).catch((reason) => setError(reason instanceof Error ? reason.message : String(reason))); - void window.laobosDesktop.browserOps.status().then(setOps); - return () => { disposed = true; observer.disconnect(); window.removeEventListener("resize", sync); offState(); offOps(); void window.laobosDesktop.browser.show(false); }; - }, [open]); - const navigate = async () => { try { setError(""); setState(await window.laobosDesktop.browser.navigate(address)); } catch (reason) { setError(reason instanceof Error ? reason.message : String(reason)); } }; - const action = async (name) => { try { setState(await window.laobosDesktop.browser.action(name)); } catch (reason) { setError(reason instanceof Error ? reason.message : String(reason)); } }; - const toggleOps = async () => { try { setOps(await (ops.state === "running" ? window.laobosDesktop.browserOps.stop() : window.laobosDesktop.browserOps.start())); } catch (reason) { setError(reason instanceof Error ? reason.message : String(reason)); } }; - const close = () => { setOpen(false); window.dispatchEvent(new CustomEvent("laobos:desktop-tool-closed", { detail: { tool: "browser" } })); }; - if (!open) return null; - return h("section", { className: "lbs-browser-panel", role: "dialog", "aria-label": "浏览器预览" }, - h("header", { className: "lbs-browser-toolbar" }, h("button", { disabled: !state.canGoBack, onClick: () => action("back") }, "←"), h("button", { disabled: !state.canGoForward, onClick: () => action("forward") }, "→"), h("button", { onClick: () => action(state.loading ? "stop" : "reload") }, state.loading ? "停止" : "刷新"), h("input", { className: "lbs-browser-address", value: address, onChange: (event) => setAddress(event.target.value), onKeyDown: (event) => { if (event.key === "Enter") void navigate(); }, "aria-label": "浏览器地址" }), h("button", { onClick: navigate }, "打开"), h("div", { className: "lbs-browser-ops" }, h("button", { onClick: toggleOps }, ops.state === "running" ? "停止 BrowserOps" : "启动 BrowserOps"), h("span", { title: ops.message }, ops.message || ops.state)), h("button", { onClick: close }, "关闭")), - error ? h("div", { className: "lbs-browser-error" }, error) : null, - h("div", { className: "lbs-browser-viewport", ref: viewport }), - ); +/* eslint-disable @next/next/no-assign-module-variable -- generated DSH module factory */ +(() => { + // packages/laobos-browserops/src/client.jsx + window.__ModuleLoader__.load({ + id: "@laobos/dsh-browserops", + factory: (require2) => { + var module = { exports: {} }; + var exports = module.exports; + Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); + const React = require2("react"); + const { useEffect, useRef, useState } = React; + const css = ` + .lbs-browser-panel{background:var(--dsw-alias-bg-base);bottom:0;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483060}.lbs-browser-toolbar{align-items:center;background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;flex:none;gap:6px;min-height:52px;padding:0 10px}.lbs-browser-toolbar button{align-items:center;appearance:none;background:transparent;border:0;border-radius:7px;color:inherit;cursor:pointer;display:inline-flex;font:inherit;font-size:12px;height:31px;justify-content:center;padding:0 9px}.lbs-browser-toolbar button:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-browser-toolbar button:disabled{cursor:not-allowed;opacity:.38}.lbs-browser-nav-button{font-size:17px!important;padding:0!important;width:31px}.lbs-browser-address-shell{align-items:center;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;display:flex;flex:1;min-width:110px;padding-left:9px}.lbs-browser-address-icon{color:var(--dsw-alias-label-tertiary);font-size:11px}.lbs-browser-address{appearance:none;background:transparent;border:0;color:inherit;flex:1;font:12px ui-monospace,SFMono-Regular,Menlo,monospace;height:32px;min-width:80px;outline:0;padding:0 8px}.lbs-browser-address-shell:focus-within{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 2px rgba(92,117,255,.12)}.lbs-browser-open{background:var(--dsw-alias-interactive-bg-primary)!important;color:var(--dsw-alias-label-on-primary)!important}.lbs-browser-ops{align-items:center;border-left:1px solid var(--dsw-alias-border-l1);display:flex;gap:6px;margin-left:3px;padding-left:9px}.lbs-browser-ops-state{align-items:center;color:var(--dsw-alias-label-tertiary);display:flex;font-size:10px;gap:5px;max-width:210px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-browser-ops-state:before{background:var(--dsw-alias-label-quaternary);border-radius:50%;content:"";height:6px;width:6px}.lbs-browser-ops-state[data-state=running]:before,.lbs-browser-ops-state[data-state=external]:before{background:#2a9b67}.lbs-browser-ops-state[data-state=starting]:before,.lbs-browser-ops-state[data-state=stopping]:before{background:#d6a84b}.lbs-browser-ops-state[data-state=error]:before{background:#d94b4b}.lbs-browser-error{align-items:center;background:rgba(218,70,70,.1);border-bottom:1px solid rgba(218,70,70,.18);color:#d94b4b;display:flex;font-size:12px;gap:10px;line-height:1.45;padding:8px 12px}.lbs-browser-error span{flex:1}.lbs-browser-error button{background:transparent;border:1px solid currentColor;border-radius:6px;color:inherit;cursor:pointer;font:11px/25px inherit;padding:0 8px}.lbs-browser-viewport{flex:1;min-height:0}.lbs-browser-close{margin-left:2px}@media(max-width:980px){.lbs-browser-ops-state{display:none}}@media(max-width:850px){.lbs-browser-panel{left:0;right:0}.lbs-browser-toolbar{flex-wrap:wrap;padding:7px 9px}.lbs-browser-address-shell{order:3;width:calc(100% - 72px)}.lbs-browser-open{order:3}.lbs-browser-ops{border-left:0;margin-left:auto}.lbs-browser-viewport{min-height:300px}} + `; + if (typeof document !== "undefined" && !document.querySelector('style[data-plugin-css="@laobos/dsh-browserops"]')) { + const style = document.createElement("style"); + style.dataset.pluginCss = "@laobos/dsh-browserops"; + style.textContent = css; + document.head.append(style); + } + const messageOf = (reason) => String(reason instanceof Error ? reason.message : reason).replace(/^Error invoking remote method '[^']+': Error:\s*/u, ""); + function BrowserPanel() { + const [open, setOpen] = useState(false); + const [address, setAddress] = useState(""); + const [state, setState] = useState({}); + const [ops, setOps] = useState({ state: "stopped", message: "BrowserOps 未启动" }); + const [error, setError] = useState(""); + const viewport = useRef(null); + const addressInput = useRef(null); + const addressRef = useRef(address); + useEffect(() => { + addressRef.current = address; + }, [address]); + const applyBrowserState = (value = {}) => { + setState(value); + if (value.url) setAddress(value.url); + setError(value.error || ""); + }; + useEffect(() => { + const show = (event) => { + if (event.detail?.tool === "close") { + setOpen(false); + return; + } + if (event.detail?.tool !== "browser") return; + setOpen(true); + setError(""); + }; + window.addEventListener("laobos:open-desktop-tool", show); + return () => window.removeEventListener("laobos:open-desktop-tool", show); + }, []); + useEffect(() => { + if (!open || !window.laobosDesktop?.capabilities?.browserPreview) return void 0; + let disposed = false; + const sync = () => { + if (!viewport.current || disposed) return; + const rect = viewport.current.getBoundingClientRect(); + void window.laobosDesktop.browser.setBounds({ x: rect.left, y: rect.top, width: rect.width, height: rect.height }); + }; + const observer = new ResizeObserver(sync); + observer.observe(viewport.current); + window.addEventListener("resize", sync); + const offState = window.laobosDesktop.browser.onState(applyBrowserState); + const offOps = window.laobosDesktop.browserOps.onState(setOps); + void window.laobosDesktop.browser.show(true).then((value) => { + applyBrowserState(value); + sync(); + }).catch((reason) => setError(messageOf(reason))); + void window.laobosDesktop.browserOps.status().then(setOps).catch((reason) => setOps({ state: "error", message: messageOf(reason) })); + const focusAddress = (event) => { + if (!(event.metaKey || event.ctrlKey) || event.key.toLowerCase() !== "l") return; + event.preventDefault(); + addressInput.current?.focus(); + addressInput.current?.select(); + }; + window.addEventListener("keydown", focusAddress); + return () => { + disposed = true; + observer.disconnect(); + window.removeEventListener("resize", sync); + window.removeEventListener("keydown", focusAddress); + offState(); + offOps(); + void window.laobosDesktop.browser.show(false); + }; + }, [open]); + const navigate = async () => { + const target = addressRef.current.trim(); + if (!target) { + addressInput.current?.focus(); + return; + } + try { + setError(""); + applyBrowserState(await window.laobosDesktop.browser.navigate(target)); + } catch (reason) { + setError(messageOf(reason)); + } + }; + const action = async (name) => { + try { + applyBrowserState(await window.laobosDesktop.browser.action(name)); + } catch (reason) { + setError(messageOf(reason)); + } + }; + const toggleOps = async () => { + if (["starting", "stopping", "external"].includes(ops.state)) return; + try { + setError(""); + setOps(await (ops.state === "running" ? window.laobosDesktop.browserOps.stop() : window.laobosDesktop.browserOps.start())); + } catch (reason) { + setError(messageOf(reason)); + } + }; + const close = () => { + setOpen(false); + window.dispatchEvent(new CustomEvent("laobos:desktop-tool-closed", { detail: { tool: "browser" } })); + }; + if (!open) return null; + const opsLabel = ops.state === "running" ? "停止 BrowserOps" : ops.state === "external" ? "外部 BrowserOps" : ops.state === "starting" ? "正在启动…" : ops.state === "stopping" ? "正在停止…" : "启动 BrowserOps"; + return /* @__PURE__ */ React.createElement("section", { className: "lbs-browser-panel", role: "dialog", "aria-label": "内置浏览器" }, /* @__PURE__ */ React.createElement("header", { className: "lbs-browser-toolbar" }, /* @__PURE__ */ React.createElement("button", { className: "lbs-browser-nav-button", disabled: !state.canGoBack, onClick: () => action("back"), title: "后退" }, "←"), /* @__PURE__ */ React.createElement("button", { className: "lbs-browser-nav-button", disabled: !state.canGoForward, onClick: () => action("forward"), title: "前进" }, "→"), /* @__PURE__ */ React.createElement("button", { className: "lbs-browser-nav-button", onClick: () => action(state.loading ? "stop" : "reload"), title: state.loading ? "停止加载" : "刷新" }, state.loading ? "×" : "↻"), /* @__PURE__ */ React.createElement("label", { className: "lbs-browser-address-shell" }, /* @__PURE__ */ React.createElement("span", { className: "lbs-browser-address-icon" }, "HTTP"), /* @__PURE__ */ React.createElement("input", { ref: addressInput, className: "lbs-browser-address", value: address, onChange: (event) => setAddress(event.target.value), onKeyDown: (event) => { + if (event.key === "Enter") void navigate(); + }, placeholder: "输入地址,例如 localhost:5173", "aria-label": "浏览器地址" })), /* @__PURE__ */ React.createElement("button", { className: "lbs-browser-open", disabled: !address.trim(), onClick: navigate }, "打开"), /* @__PURE__ */ React.createElement("div", { className: "lbs-browser-ops" }, /* @__PURE__ */ React.createElement("button", { disabled: ["starting", "stopping", "external"].includes(ops.state), onClick: toggleOps }, opsLabel), /* @__PURE__ */ React.createElement("span", { className: "lbs-browser-ops-state", "data-state": ops.state, title: ops.message }, ops.message || ops.state)), /* @__PURE__ */ React.createElement("button", { className: "lbs-browser-close", onClick: close }, "关闭")), error ? /* @__PURE__ */ React.createElement("div", { className: "lbs-browser-error" }, /* @__PURE__ */ React.createElement("span", null, error), /* @__PURE__ */ React.createElement("button", { type: "button", disabled: !address.trim(), onClick: navigate }, "重试")) : null, /* @__PURE__ */ React.createElement("div", { className: "lbs-browser-viewport", ref: viewport })); + } + const inject = ["slots"]; + function apply(ctx) { + ctx.slots.inject("shell.overlay", () => ctx.slots.register({ name: "shell.overlay", id: "laobos-browserops", order: 41 }, BrowserPanel)); + } + exports.apply = apply; + exports.inject = inject; + return module.exports; } - const inject = ["slots"]; - function apply(ctx) { ctx.slots.inject("shell.overlay", () => ctx.slots.register({ name: "shell.overlay", id: "laobos-browserops", order: 41 }, BrowserPanel)); } - exports.apply = apply; exports.inject = inject; return module.exports; - }, -}); + }); +})(); diff --git a/packages/laobos-browserops/src/client.jsx b/packages/laobos-browserops/src/client.jsx new file mode 100644 index 0000000..046ba71 --- /dev/null +++ b/packages/laobos-browserops/src/client.jsx @@ -0,0 +1,113 @@ +/* eslint-disable @next/next/no-assign-module-variable -- DSH browser plugins use a CommonJS-style module factory */ +window.__ModuleLoader__.load({ + id: "@laobos/dsh-browserops", + factory: (require) => { + var module = { exports: {} }; + var exports = module.exports; + Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); + const React = require("react"); + const { useEffect, useRef, useState } = React; + const css = ` + .lbs-browser-panel{background:var(--dsw-alias-bg-base);bottom:0;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483060}.lbs-browser-toolbar{align-items:center;background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;flex:none;gap:6px;min-height:52px;padding:0 10px}.lbs-browser-toolbar button{align-items:center;appearance:none;background:transparent;border:0;border-radius:7px;color:inherit;cursor:pointer;display:inline-flex;font:inherit;font-size:12px;height:31px;justify-content:center;padding:0 9px}.lbs-browser-toolbar button:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-browser-toolbar button:disabled{cursor:not-allowed;opacity:.38}.lbs-browser-nav-button{font-size:17px!important;padding:0!important;width:31px}.lbs-browser-address-shell{align-items:center;background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;display:flex;flex:1;min-width:110px;padding-left:9px}.lbs-browser-address-icon{color:var(--dsw-alias-label-tertiary);font-size:11px}.lbs-browser-address{appearance:none;background:transparent;border:0;color:inherit;flex:1;font:12px ui-monospace,SFMono-Regular,Menlo,monospace;height:32px;min-width:80px;outline:0;padding:0 8px}.lbs-browser-address-shell:focus-within{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 2px rgba(92,117,255,.12)}.lbs-browser-open{background:var(--dsw-alias-interactive-bg-primary)!important;color:var(--dsw-alias-label-on-primary)!important}.lbs-browser-ops{align-items:center;border-left:1px solid var(--dsw-alias-border-l1);display:flex;gap:6px;margin-left:3px;padding-left:9px}.lbs-browser-ops-state{align-items:center;color:var(--dsw-alias-label-tertiary);display:flex;font-size:10px;gap:5px;max-width:210px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-browser-ops-state:before{background:var(--dsw-alias-label-quaternary);border-radius:50%;content:"";height:6px;width:6px}.lbs-browser-ops-state[data-state=running]:before,.lbs-browser-ops-state[data-state=external]:before{background:#2a9b67}.lbs-browser-ops-state[data-state=starting]:before,.lbs-browser-ops-state[data-state=stopping]:before{background:#d6a84b}.lbs-browser-ops-state[data-state=error]:before{background:#d94b4b}.lbs-browser-error{align-items:center;background:rgba(218,70,70,.1);border-bottom:1px solid rgba(218,70,70,.18);color:#d94b4b;display:flex;font-size:12px;gap:10px;line-height:1.45;padding:8px 12px}.lbs-browser-error span{flex:1}.lbs-browser-error button{background:transparent;border:1px solid currentColor;border-radius:6px;color:inherit;cursor:pointer;font:11px/25px inherit;padding:0 8px}.lbs-browser-viewport{flex:1;min-height:0}.lbs-browser-close{margin-left:2px}@media(max-width:980px){.lbs-browser-ops-state{display:none}}@media(max-width:850px){.lbs-browser-panel{left:0;right:0}.lbs-browser-toolbar{flex-wrap:wrap;padding:7px 9px}.lbs-browser-address-shell{order:3;width:calc(100% - 72px)}.lbs-browser-open{order:3}.lbs-browser-ops{border-left:0;margin-left:auto}.lbs-browser-viewport{min-height:300px}} + `; + if (typeof document !== "undefined" && !document.querySelector('style[data-plugin-css="@laobos/dsh-browserops"]')) { + const style = document.createElement("style"); + style.dataset.pluginCss = "@laobos/dsh-browserops"; + style.textContent = css; + document.head.append(style); + } + + const messageOf = (reason) => String(reason instanceof Error ? reason.message : reason).replace(/^Error invoking remote method '[^']+': Error:\s*/u, ""); + + function BrowserPanel() { + const [open, setOpen] = useState(false); + const [address, setAddress] = useState(""); + const [state, setState] = useState({}); + const [ops, setOps] = useState({ state: "stopped", message: "BrowserOps 未启动" }); + const [error, setError] = useState(""); + const viewport = useRef(null); + const addressInput = useRef(null); + const addressRef = useRef(address); + useEffect(() => { addressRef.current = address; }, [address]); + const applyBrowserState = (value = {}) => { + setState(value); + if (value.url) setAddress(value.url); + setError(value.error || ""); + }; + + useEffect(() => { + const show = (event) => { + if (event.detail?.tool === "close") { setOpen(false); return; } + if (event.detail?.tool !== "browser") return; + setOpen(true); setError(""); + }; + window.addEventListener("laobos:open-desktop-tool", show); + return () => window.removeEventListener("laobos:open-desktop-tool", show); + }, []); + + useEffect(() => { + if (!open || !window.laobosDesktop?.capabilities?.browserPreview) return undefined; + let disposed = false; + const sync = () => { + if (!viewport.current || disposed) return; + const rect = viewport.current.getBoundingClientRect(); + void window.laobosDesktop.browser.setBounds({ x: rect.left, y: rect.top, width: rect.width, height: rect.height }); + }; + const observer = new ResizeObserver(sync); + observer.observe(viewport.current); + window.addEventListener("resize", sync); + const offState = window.laobosDesktop.browser.onState(applyBrowserState); + const offOps = window.laobosDesktop.browserOps.onState(setOps); + void window.laobosDesktop.browser.show(true).then((value) => { applyBrowserState(value); sync(); }).catch((reason) => setError(messageOf(reason))); + void window.laobosDesktop.browserOps.status().then(setOps).catch((reason) => setOps({ state: "error", message: messageOf(reason) })); + const focusAddress = (event) => { + if (!(event.metaKey || event.ctrlKey) || event.key.toLowerCase() !== "l") return; + event.preventDefault(); addressInput.current?.focus(); addressInput.current?.select(); + }; + window.addEventListener("keydown", focusAddress); + return () => { + disposed = true; observer.disconnect(); window.removeEventListener("resize", sync); window.removeEventListener("keydown", focusAddress); + offState(); offOps(); void window.laobosDesktop.browser.show(false); + }; + }, [open]); + + const navigate = async () => { + const target = addressRef.current.trim(); + if (!target) { addressInput.current?.focus(); return; } + try { setError(""); applyBrowserState(await window.laobosDesktop.browser.navigate(target)); } + catch (reason) { setError(messageOf(reason)); } + }; + const action = async (name) => { + try { applyBrowserState(await window.laobosDesktop.browser.action(name)); } + catch (reason) { setError(messageOf(reason)); } + }; + const toggleOps = async () => { + if (["starting", "stopping", "external"].includes(ops.state)) return; + try { setError(""); setOps(await (ops.state === "running" ? window.laobosDesktop.browserOps.stop() : window.laobosDesktop.browserOps.start())); } + catch (reason) { setError(messageOf(reason)); } + }; + const close = () => { setOpen(false); window.dispatchEvent(new CustomEvent("laobos:desktop-tool-closed", { detail: { tool: "browser" } })); }; + if (!open) return null; + const opsLabel = ops.state === "running" ? "停止 BrowserOps" : ops.state === "external" ? "外部 BrowserOps" : ops.state === "starting" ? "正在启动…" : ops.state === "stopping" ? "正在停止…" : "启动 BrowserOps"; + return
+
+ + + + + +
{ops.message || ops.state}
+ +
+ {error ?
{error}
: null} +
+
; + } + + const inject = ["slots"]; + function apply(ctx) { ctx.slots.inject("shell.overlay", () => ctx.slots.register({ name: "shell.overlay", id: "laobos-browserops", order: 41 }, BrowserPanel)); } + exports.apply = apply; + exports.inject = inject; + return module.exports; + }, +}); diff --git a/packages/laobos-conversation-tools/lib/client.js b/packages/laobos-conversation-tools/lib/client.js index d181bed..3a7e357 100644 --- a/packages/laobos-conversation-tools/lib/client.js +++ b/packages/laobos-conversation-tools/lib/client.js @@ -17,6 +17,7 @@ window.__ModuleLoader__.load({ .lbs-conv-menu{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:10px;box-shadow:var(--dsw-shadow-lv2);display:flex;flex-direction:column;gap:2px;min-width:168px;padding:5px;position:absolute;right:0;top:30px;z-index:2147483100} .lbs-conv-menu.fixed{bottom:auto;box-sizing:border-box;max-height:calc(100vh - 16px);max-width:calc(100vw - 16px);overflow-y:auto;position:fixed;right:auto}.lbs-conv-menu button{appearance:none;background:transparent;border:0;border-radius:6px;color:inherit;cursor:pointer;font:inherit;font-size:13px;line-height:30px;padding:0 9px;text-align:left;white-space:nowrap}.lbs-conv-menu button:hover,.lbs-conv-menu button:focus-visible{background:var(--dsw-alias-interactive-bg-hover);outline:none}.lbs-conv-menu button.danger{color:#d94b4b}.lbs-conv-menu button:disabled{cursor:not-allowed;opacity:.45} .lbs-conv-inline-action{align-items:center;appearance:none;background:transparent;border:0;border-radius:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;display:inline-flex;height:28px;justify-content:center;padding:6px;width:28px}.lbs-conv-inline-action:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.lbs-conv-inline-action:disabled{background:transparent;color:var(--dsw-alias-label-tertiary);cursor:not-allowed;opacity:.4}.lbs-conv-inline-action svg{display:block} + [data-chat-flow-kind="context"]{display:none!important} [data-time-hover-root]:not([data-turn-tail]){align-items:flex-end!important;flex-direction:column!important;gap:6px!important} .lbs-conv-overlay{align-items:center;background:rgba(0,0,0,.28);display:flex;inset:0;justify-content:center;padding:24px;position:fixed;z-index:2147483200}.lbs-conv-dialog{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:14px;box-shadow:var(--dsw-shadow-lv3);box-sizing:border-box;max-width:620px;padding:18px;width:100%}.lbs-conv-dialog h2{font-size:17px;margin:0 0 5px}.lbs-conv-dialog p{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;margin:0 0 12px}.lbs-conv-dialog textarea{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:9px;box-sizing:border-box;color:inherit;font:inherit;line-height:21px;min-height:150px;padding:10px;resize:vertical;width:100%}.lbs-conv-dialog footer{display:flex;gap:8px;justify-content:flex-end;margin-top:12px}.lbs-conv-primary,.lbs-conv-secondary{appearance:none;border:0;border-radius:8px;cursor:pointer;font:inherit;font-size:13px;height:34px;padding:0 13px}.lbs-conv-primary{background:var(--dsw-alias-interactive-bg-primary);color:var(--dsw-alias-label-on-primary)}.lbs-conv-secondary{background:var(--dsw-alias-interactive-bg-secondary);color:inherit}.lbs-conv-primary:disabled{cursor:not-allowed;opacity:.5}.lbs-conv-feedback{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} [data-phase]>[data-slot="conversation.session.header"]>header{padding:6px 28px 6px 20px!important} @@ -48,10 +49,6 @@ window.__ModuleLoader__.load({ return { text, files, envelopes }; }; const appendFileEnvelopes = (text, envelopes) => [String(text || "").trim(), ...envelopes].filter(Boolean).join("\n"); - const escapeHtml = (value) => String(value ?? "") - .replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">") - .replaceAll('"', """).replaceAll("'", "'"); - function orderedNodes(snapshot) { return snapshot?.chat?.order ?.map((key) => snapshot.chat.nodes.get(key)) @@ -123,52 +120,388 @@ window.__ModuleLoader__.load({ await scopedConversation(ctx, sessionId).send(text); } - function assistantText(node) { - const blocks = node?.data?.blocks; - if (!Array.isArray(blocks)) return ""; - return blocks.filter((block) => block?.kind === "text").map((block) => block.text || "").join("\n").trim(); - } - - function conversationHtml(sessionId, title, snapshot) { - const rows = []; - for (const node of orderedNodes(snapshot)) { - const kind = node?.data?.kind; - if (kind === "user" || kind === "steering") { - const projected = contentProjection(node.data.content); - const fileRows = projected.files.map((file) => `
${escapeHtml(file.name)}${escapeHtml(file.path)}
`).join(""); - rows.push(`
用户
${projected.text ? `
${escapeHtml(projected.text).replaceAll("\n", "
")}
` : ""}${fileRows}
`); - } else if (kind === "assistant") { - const text = assistantText(node); - if (text) rows.push(`
劳博士
${escapeHtml(text).replaceAll("\n", "
")}
`); - } else if (kind === "turn-error" || kind === "retry" || kind === "turn-max-tokens") { - rows.push(`
运行记录:${escapeHtml(kind)}
${escapeHtml(cleanText(node?.data?.message || node?.data?.error || ""))}
`); - } else if (kind === "tool-result") { - rows.push(`
工具:${escapeHtml(node?.data?.name || "调用结果")}
${escapeHtml(cleanText(node?.data?.output || node?.data?.result || ""))}
`); + const EXPORT_ROOT_ID = "lbs-conversation-export-root"; + const nextFrame = () => new Promise((resolve) => requestAnimationFrame(resolve)); + + async function settleFrames(count = 3) { + for (let index = 0; index < count; index += 1) await nextFrame(); + } + + function visibleConversationScroll() { + const candidates = [...document.querySelectorAll("[data-conversation-scroll]")] + .filter((element) => !element.closest(`#${EXPORT_ROOT_ID}`)); + return candidates.find((element) => { + const box = element.getBoundingClientRect(); + return box.width > 0 && box.height > 0; + }) || candidates[0] || null; + } + + async function waitForCurrentSession(ctx, sessionId) { + const deadline = performance.now() + 10_000; + while (performance.now() < deadline) { + if (ctx.sessions.list.getSnapshot().current === sessionId) return; + await nextFrame(); + } + throw new Error("等待会话界面切换超时。 "); + } + + async function loadCompleteSnapshot(session) { + let snapshot = session.getSnapshot(); + let previousMarker = ""; + while (snapshot.hasMore) { + const marker = `${snapshot.chat.order[0] || ""}:${snapshot.chat.order.length}`; + if (marker === previousMarker) throw new Error("历史会话分页没有继续前进,无法保证完整导出。 "); + previousMarker = marker; + await session.loadOlder(); + snapshot = session.getSnapshot(); + } + return snapshot; + } + + async function waitForRenderedConversation(snapshot) { + await settleFrames(); + const scroll = visibleConversationScroll(); + if (!scroll) throw new Error("找不到当前会话的渲染区域。 "); + + // The Chat view has one keyed seat for every ordered DSH node. Other active + // views (for example Trajectory) do not expose these seats and are cloned as-is. + const expected = snapshot.chat.order; + if (scroll.querySelector("[data-chat-flow-key]") && expected.length > 0) { + const deadline = performance.now() + 10_000; + while (performance.now() < deadline) { + const rendered = new Set([...scroll.querySelectorAll("[data-chat-flow-key]")] + .map((element) => element.dataset.chatFlowKey)); + if (expected.every((key) => rendered.has(key))) break; + await nextFrame(); + } + const rendered = new Set([...scroll.querySelectorAll("[data-chat-flow-key]")] + .map((element) => element.dataset.chatFlowKey)); + if (!expected.every((key) => rendered.has(key))) { + throw new Error("会话历史尚未全部渲染,已停止导出以避免生成不完整文件。 "); + } + } + return scroll; + } + + function copyLiveElementState(source, clone) { + const originals = [source, ...source.querySelectorAll("*")]; + const copies = [clone, ...clone.querySelectorAll("*")]; + for (let index = 0; index < originals.length; index += 1) { + const original = originals[index]; + const copy = copies[index]; + if (original instanceof HTMLInputElement && copy instanceof HTMLInputElement) { + copy.value = original.value; + copy.checked = original.checked; + } else if (original instanceof HTMLTextAreaElement && copy instanceof HTMLTextAreaElement) { + copy.value = original.value; + copy.textContent = original.value; + } else if (original instanceof HTMLSelectElement && copy instanceof HTMLSelectElement) { + copy.value = original.value; + } else if (original instanceof HTMLImageElement && copy instanceof HTMLImageElement) { + copy.src = original.currentSrc || original.src; + copy.removeAttribute("srcset"); + copy.removeAttribute("loading"); + } else if (original instanceof HTMLCanvasElement && copy instanceof HTMLCanvasElement) { + try { + const image = document.createElement("img"); + image.src = original.toDataURL("image/png"); + image.className = copy.className; + image.style.cssText = copy.style.cssText; + const box = original.getBoundingClientRect(); + if (box.width > 0) image.style.width = `${box.width}px`; + if (box.height > 0) image.style.height = `${box.height}px`; + copy.replaceWith(image); + } catch { /* A tainted third-party canvas remains as an empty canvas. */ } + } else if (original instanceof HTMLVideoElement && copy instanceof HTMLVideoElement && original.videoWidth > 0) { + try { + const canvas = document.createElement("canvas"); + canvas.width = original.videoWidth; + canvas.height = original.videoHeight; + canvas.getContext("2d")?.drawImage(original, 0, 0); + const image = document.createElement("img"); + image.src = canvas.toDataURL("image/png"); + image.className = copy.className; + image.style.cssText = copy.style.cssText; + copy.replaceWith(image); + } catch { /* Keep the cloned video/poster when a frame cannot be read. */ } + } + } + } + + function cloneRenderedElement(source) { + const clone = source.cloneNode(true); + copyLiveElementState(source, clone); + clone.querySelectorAll(".lbs-conv-actions,.lbs-conv-menu,.lbs-conv-overlay") + .forEach((element) => element.remove()); + clone.querySelectorAll("script").forEach((element) => element.remove()); + for (const element of [clone, ...clone.querySelectorAll("*")]) { + for (const attribute of [...element.attributes]) { + if (attribute.name.toLowerCase().startsWith("on")) element.removeAttribute(attribute.name); } } - const exportedAt = new Date().toLocaleString("zh-CN"); - return `${escapeHtml(title)}

${escapeHtml(title)}

会话 ${escapeHtml(sessionId)} · 导出于 ${escapeHtml(exportedAt)}
${rows.join("")}
由劳博士导出
`; + return clone; + } + + async function expandFoldedContent(scroll) { + const clicked = []; + const attempted = new WeakSet(); + const initialStates = new Map(); + + for (let round = 0; round < 20; round += 1) { + let changed = false; + for (const control of scroll.querySelectorAll("[aria-expanded]")) { + if (!initialStates.has(control)) { + initialStates.set(control, control.getAttribute("aria-expanded") === "true"); + } + } + const controls = [...scroll.querySelectorAll('[aria-expanded="false"]')] + .filter((element) => !attempted.has(element) + && !element.hasAttribute("disabled") + && !element.hasAttribute("aria-haspopup")); + for (const control of controls) { + attempted.add(control); + control.click(); + clicked.push(control); + changed = true; + await settleFrames(2); + } + if (!changed) break; + await settleFrames(2); + } + + return { + initialStates, + restore: async () => { + for (const control of clicked.reverse()) { + if (control.isConnected && control.getAttribute("aria-expanded") === "true") control.click(); + } + await settleFrames(2); + }, + }; + } + + function annotateFoldedContent(scroll, initialStates) { + const annotated = []; + const seen = new Set(); + let index = 0; + for (const control of scroll.querySelectorAll('[aria-expanded="true"]')) { + const toggle = control.closest("[data-disclosure-row]") || control; + if (seen.has(toggle)) continue; + const controlledId = control.getAttribute("aria-controls"); + const controlled = controlledId ? document.getElementById(controlledId) : null; + const panels = controlled && scroll.contains(controlled) ? [controlled] : []; + if (panels.length === 0) { + for (let panel = toggle.nextElementSibling; panel; panel = panel.nextElementSibling) panels.push(panel); + } + if (panels.length === 0) continue; + seen.add(toggle); + const id = `fold-${index += 1}`; + const initiallyOpen = initialStates.get(control) ?? initialStates.get(toggle) ?? true; + toggle.dataset.lbsExportToggle = id; + toggle.dataset.lbsExportInitial = initiallyOpen ? "expanded" : "collapsed"; + const addedTabIndex = !toggle.hasAttribute("tabindex"); + if (addedTabIndex) toggle.tabIndex = 0; + for (const panel of panels) { + panel.dataset.lbsExportPanel = id; + panel.dataset.lbsExportInitial = initiallyOpen ? "expanded" : "collapsed"; + } + annotated.push({ toggle, panels, addedTabIndex }); + } + return () => { + for (const { toggle, panels, addedTabIndex } of annotated) { + delete toggle.dataset.lbsExportToggle; + delete toggle.dataset.lbsExportInitial; + if (addedTabIndex) toggle.removeAttribute("tabindex"); + for (const panel of panels) { + delete panel.dataset.lbsExportPanel; + delete panel.dataset.lbsExportInitial; + } + } + }; + } + + function buildExportSnapshot(scroll) { + const phase = scroll.closest("[data-phase]"); + const sessionView = [...scroll.children] + .find((element) => !element.matches("[data-composer-seat]")); + if (!sessionView) throw new Error("找不到当前会话内容。 "); + + const root = document.createElement("main"); + root.id = EXPORT_ROOT_ID; + root.setAttribute("data-conversation-export", ""); + const shell = document.createElement("article"); + shell.className = [phase?.className || "", "lbs-conversation-export-shell"].filter(Boolean).join(" "); + if (phase?.dataset.phase) shell.dataset.phase = phase.dataset.phase; + + const header = phase?.querySelector(':scope > [data-slot="conversation.session.header"]'); + if (header) shell.append(cloneRenderedElement(header)); + + const scrollClone = document.createElement("div"); + scrollClone.className = scroll.className; + scrollClone.setAttribute("data-conversation-scroll", ""); + scrollClone.append(cloneRenderedElement(sessionView)); + shell.append(scrollClone); + root.append(shell); + + const phaseStyle = phase ? getComputedStyle(phase) : null; + for (const property of [ + "--dsh-chat-content-width", + "--dsh-composer-card-max-width", + "--dsh-composer-side-clearance", + "--dsh-composer-dock-inset", + ]) { + const value = phaseStyle?.getPropertyValue(property); + if (value) root.style.setProperty(property, value); + } + if (phaseStyle) { + root.style.color = phaseStyle.color; + root.style.background = phaseStyle.backgroundColor; + root.style.fontFamily = phaseStyle.fontFamily; + } + return root; + } + + function blobDataUrl(blob) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.addEventListener("load", () => resolve(String(reader.result)), { once: true }); + reader.addEventListener("error", () => reject(reader.error), { once: true }); + reader.readAsDataURL(blob); + }); + } + + async function inlineImageAssets(root) { + await Promise.all([...root.querySelectorAll("img")].map(async (image) => { + const source = image.getAttribute("src"); + if (!source || source.startsWith("data:")) return; + try { + const response = await fetch(source); + if (!response.ok) throw new Error(`HTTP ${response.status}`); + image.src = await blobDataUrl(await response.blob()); + } catch (error) { + throw new Error(`图片资源无法内嵌,已停止导出:${error instanceof Error ? error.message : String(error)}`); + } + })); + } + + function stylesheetText() { + const chunks = []; + for (const sheet of document.styleSheets) { + try { + chunks.push([...sheet.cssRules].map((rule) => rule.cssText).join("\n")); + } catch { /* Cross-origin styles cannot be embedded; DSH plugin styles are same-origin. */ } + } + return chunks.join("\n"); + } + + const escapeHtml = (value) => String(value ?? "") + .replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">") + .replaceAll('"', """).replaceAll("'", "'"); + + function documentAttributes(element) { + return [...element.attributes] + .filter((attribute) => attribute.name === "class" + || attribute.name === "style" + || attribute.name === "lang" + || attribute.name === "dir" + || attribute.name.startsWith("data-")) + .map((attribute) => `${attribute.name}="${escapeHtml(attribute.value)}"`) + .join(" "); + } + + function standaloneConversationHtml(root, title) { + const styles = stylesheetText().replaceAll("*{box-sizing:border-box!important;height:auto!important;max-height:none!important;min-height:0!important;overflow:visible!important} + #${EXPORT_ROOT_ID} [data-conversation-scroll]{display:block!important;padding:0!important;scrollbar-gutter:auto!important} + #${EXPORT_ROOT_ID} [data-composer-seat],#${EXPORT_ROOT_ID} .lbs-conv-actions, + #${EXPORT_ROOT_ID} .lbs-conv-menu,#${EXPORT_ROOT_ID} .lbs-conv-overlay{display:none!important} + #${EXPORT_ROOT_ID} [data-lbs-export-toggle]{cursor:pointer} + #${EXPORT_ROOT_ID} [data-lbs-export-panel][data-lbs-export-initial="collapsed"], + #${EXPORT_ROOT_ID} [data-lbs-export-panel][hidden]{display:none!important} + #${EXPORT_ROOT_ID} img,#${EXPORT_ROOT_ID} svg,#${EXPORT_ROOT_ID} canvas{max-width:100%} + #${EXPORT_ROOT_ID} pre{max-width:100%;white-space:pre-wrap!important;overflow-wrap:anywhere} + #${EXPORT_ROOT_ID} table{max-width:100%;overflow-wrap:anywhere} + `; + const interactions = `(()=>{ + const root=document.getElementById(${JSON.stringify(EXPORT_ROOT_ID)}); + if(!root)return; + const apply=(toggle,open)=>{ + toggle.setAttribute("aria-expanded",String(open)); + toggle.dataset.lbsExportState=open?"expanded":"collapsed"; + const id=toggle.dataset.lbsExportToggle; + for(const panel of root.querySelectorAll("[data-lbs-export-panel]")){ + if(panel.dataset.lbsExportPanel!==id)continue; + panel.hidden=!open; + delete panel.dataset.lbsExportInitial; + } + }; + for(const toggle of root.querySelectorAll("[data-lbs-export-toggle]")){ + let open=toggle.dataset.lbsExportInitial!=="collapsed"; + apply(toggle,open); + delete toggle.dataset.lbsExportInitial; + const flip=(event)=>{event.preventDefault();event.stopPropagation();open=!open;apply(toggle,open);}; + toggle.addEventListener("click",flip); + toggle.addEventListener("keydown",(event)=>{if(event.key==="Enter"||event.key===" ")flip(event);}); + } + })();`; + return `${escapeHtml(title)}${root.outerHTML}`; + } + + function safeHtmlFileName(title) { + const sanitized = String(title || "劳博士会话") + .replace(/[\\/:*?"<>|\u0000-\u001f]/gu, "-") + .replace(/\s+/gu, " ") + .slice(0, 120) + .replace(/[. ]+$/gu, ""); + return `${sanitized || "劳博士会话"}.html`; + } + + function downloadHtml(html, title) { + const url = URL.createObjectURL(new Blob([html], { type: "text/html;charset=utf-8" })); + const anchor = document.createElement("a"); + anchor.href = url; + anchor.download = safeHtmlFileName(title); + anchor.style.display = "none"; + document.body.append(anchor); + anchor.click(); + anchor.remove(); + setTimeout(() => URL.revokeObjectURL(url), 60_000); + return { canceled: false, browserDownload: true }; } async function exportConversation(ctx, sessionId) { const bridge = window.laobosDesktop; - if (!bridge?.capabilities?.conversationPdf) throw new Error("PDF 导出仅在桌面版中可用。 "); + if (ctx.sessions.list.getSnapshot().current !== sessionId) ctx.sessions.open(sessionId); + await waitForCurrentSession(ctx, sessionId); const session = ctx.sessions.binding(sessionId)?.session; if (!session) throw new Error("会话尚未载入。 "); await session.open(); - let snapshot = session.getSnapshot(); - let pages = 0; - while (snapshot.hasMore && pages < 500) { - await session.loadOlder(); - snapshot = session.getSnapshot(); - pages += 1; - } + const snapshot = await loadCompleteSnapshot(session); + const scroll = await waitForRenderedConversation(snapshot); const row = ctx.sessions.list.getSnapshot().byId[sessionId]; const title = cleanText(row?.title) || "劳博士会话"; - return bridge.pdf.exportConversation({ - html: conversationHtml(sessionId, title, snapshot), - suggestedName: title, - }); + const folded = await expandFoldedContent(scroll); + const removeAnnotations = annotateFoldedContent(scroll, folded.initialStates); + try { + const root = buildExportSnapshot(scroll); + await inlineImageAssets(root); + const html = standaloneConversationHtml(root, title); + if (bridge?.capabilities?.conversationHtml) { + return await bridge.html.exportConversation({ html, suggestedName: title }); + } + return downloadHtml(html, title); + } finally { + removeAnnotations(); + await folded.restore(); + } } async function deleteConversation(ctx, sessionId) { @@ -280,7 +613,7 @@ window.__ModuleLoader__.load({ h("button", { className: "lbs-conv-action-button", type: "button", disabled: Boolean(busy), "aria-label": "会话操作", onClick: () => setOpen((value) => !value) }, h(Primitives.IconEllipsisOutline16, { size: 16 })), open ? h("div", { className: "lbs-conv-menu", role: "menu" }, - h("button", { onClick: () => run("导出", () => exportConversation(module.ctx, sessionId)) }, "导出会话为 PDF"), + h("button", { onClick: () => run("导出", () => exportConversation(module.ctx, sessionId)) }, "导出完整会话为 HTML"), h("button", { className: "danger", onClick: () => run("删除", () => deleteConversation(module.ctx, sessionId)) }, "删除会话"), ) : null, editing ? h(EditDialog, { initialValue: initialText, allowEmpty: projection.envelopes.length > 0, busy: busy === "发送", onCancel: () => setEditing(false), onConfirm: (value) => run("发送", async () => { await editAndResend(module.ctx, sessionId, appendFileEnvelopes(value, projection.envelopes)); setEditing(false); }) }) : null, @@ -316,17 +649,48 @@ window.__ModuleLoader__.load({ window.dispatchEvent(new CustomEvent("laobos:open-desktop-tool", { detail: { tool, cwd } })); } + function defaultTitleForPath(value, fallback) { + const title = String(value || "").replace(/[/\\]+$/u, "").split(/[/\\]/u).pop()?.trim(); + return title || fallback; + } + + async function revealInSystemFileManager(cwd) { + if (!cwd) throw new Error("当前项目没有可定位的本地路径。 "); + const reveal = window.laobosDesktop?.workspace?.reveal; + if (!reveal) throw new Error("系统文件管理器仅在桌面版中可用。 "); + await reveal({ root: cwd, path: "." }); + } + + async function renameWorkspace(item) { + const input = window.prompt("工作区名称(清空可恢复目录名称)", item.title); + if (input === null) return; + const title = input.trim() || defaultTitleForPath(item.path, item.workspaceId); + await module.ctx.workspaces.rename(item.workspaceId, title); + } + + async function renameSession(id) { + const summary = module.ctx.sessions.list.getSnapshot().byId[id]; + const session = module.ctx.sessions.binding(id)?.session; + if (!session) return; + const input = window.prompt("会话名称(清空可恢复默认名称)", summary?.title || ""); + if (input === null) return; + const title = input.trim() || defaultTitleForPath(summary?.cwd, id); + const result = await session.rename(title); + if (!result.ok) throw new Error(result.error.message); + } + function ContextMenuBridge() { const [menu, setMenu] = useState(null); useEffect(() => { const onContextMenu = (event) => { + if (event.target instanceof Element && event.target.closest(".lbs-workbench")) return; const row = event.target instanceof Element ? event.target.closest('[role="treeitem"]') : null; if (!row || !row.closest('[role="tree"]')) return; const workspace = row.hasAttribute("aria-expanded") ? resolveWorkspace(module.ctx, row) : undefined; const sessionId = workspace ? undefined : resolveSessionId(module.ctx, row); if (!workspace && !sessionId) return; event.preventDefault(); event.stopPropagation(); - const width = 210; const height = workspace ? 170 : 144; + const width = 240; const height = workspace ? 206 : 176; setMenu({ kind: workspace ? "workspace" : "session", workspace, sessionId, x: Math.min(event.clientX, window.innerWidth - width - 8), y: Math.min(event.clientY, window.innerHeight - height - 8) }); }; const close = () => setMenu(null); @@ -347,15 +711,18 @@ window.__ModuleLoader__.load({ h("button", { onClick: act(() => openDesktopTool("files", item.path)) }, "文件管理器"), h("button", { onClick: act(() => openDesktopTool("git", item.path)) }, "版本中心"), h("button", { onClick: act(() => openDesktopTool("terminal", item.path)) }, "在终端中打开"), - h("button", { onClick: act(async () => { const title = window.prompt("工作区名称", item.title); if (title?.trim()) await module.ctx.workspaces.rename(item.workspaceId, title.trim()); }) }, "重命名工作区"), + h("button", { onClick: act(() => revealInSystemFileManager(item.path)) }, "在系统文件管理器中打开"), + h("button", { onClick: act(() => renameWorkspace(item)) }, "重命名工作区"), h("button", { className: "danger", onClick: act(async () => { if (window.confirm(`从侧栏移除“${item.title}”?\n不会删除目录和会话。`)) await module.ctx.workspaces.delete(item.workspaceId); }) }, "从侧栏移除"), ); } const id = menu.sessionId; + const cwd = module.ctx.sessions.list.getSnapshot().byId[id]?.cwd; return h("div", { className: "lbs-conv-menu fixed", style, role: "menu", onPointerDown: (event) => event.stopPropagation() }, h("button", { onClick: act(() => module.ctx.sessions.open(id)) }, "打开会话"), - h("button", { onClick: act(() => exportConversation(module.ctx, id)) }, "导出为 PDF"), - h("button", { onClick: act(async () => { const session = module.ctx.sessions.binding(id)?.session; const current = module.ctx.sessions.list.getSnapshot().byId[id]?.title || ""; const title = window.prompt("会话名称", current); if (!title?.trim() || !session) return; const result = await session.rename(title.trim()); if (!result.ok) throw new Error(result.error.message); }) }, "重命名会话"), + h("button", { onClick: act(() => revealInSystemFileManager(cwd)) }, "在系统文件管理器中打开"), + h("button", { onClick: act(() => exportConversation(module.ctx, id)) }, "导出为 HTML"), + h("button", { onClick: act(() => renameSession(id)) }, "重命名会话"), h("button", { className: "danger", onClick: act(() => deleteConversation(module.ctx, id)) }, "删除会话"), ); } diff --git a/packages/laobos-file-attachments/lib/client.js b/packages/laobos-file-attachments/lib/client.js index c1320f1..2e91f2d 100644 --- a/packages/laobos-file-attachments/lib/client.js +++ b/packages/laobos-file-attachments/lib/client.js @@ -130,27 +130,61 @@ ${CLOSE_TAG}`; }, [sessionId]); return pendingFiles(sessionId); } + function selectedModelSupportsImages(ctx, sessionId) { + try { + const state = ctx.modelDirectories.directoryFor(sessionId).store.getSnapshot(); + const current = state.current; + if (!current) return void 0; + const model = state.groups.find((group) => group.id === current.provider)?.models.find((candidate) => candidate.id === current.model); + if (!Array.isArray(model?.inputModalities)) return void 0; + return model.inputModalities.includes("image"); + } catch { + return void 0; + } + } + async function persistImagesAsFiles(sessionId, images) { + const bridge = window.laobosDesktop; + if (!bridge?.capabilities?.fileAttachments || !bridge.uploads?.pasteFiles) { + throw new Error("当前模型不支持图片输入,且普通文件上传服务不可用。 "); + } + const payloads = await Promise.all(images.map(async (image) => ({ + name: image.file.name || "image", + mimeType: image.file.type || "application/octet-stream", + size: image.file.size, + bytes: new Uint8Array(await image.file.arrayBuffer()) + }))); + const result = await bridge.uploads.pasteFiles(sessionId, payloads); + return (result?.files || []).map(fileFromReference); + } function installFileSendChannel(ctx) { const conversation = ctx.get("conversation"); if (!conversation?.sendSession) throw new Error("对话发送服务尚未就绪。 "); const original = conversation.sendSession; const routed = async function routedSendSession(session, text, imageIds, mode) { - const files = pendingFiles(session.sessionId); + const pending = pendingFiles(session.sessionId); + const downgradeImages = imageIds.length > 0 && selectedModelSupportsImages(ctx, session.sessionId) !== true; + const images = downgradeImages ? conversation.draftImages(imageIds) : []; + if (downgradeImages && images.length !== imageIds.length) { + throw new Error("一个或多个待发送图片已经失效。 "); + } + const converted = downgradeImages ? await persistImagesAsFiles(session.sessionId, images) : []; + const files = [...pending, ...converted]; const envelopes = files.map(serializeFileEnvelope).join("\n\n"); const prompt = text && envelopes ? `${text} ${envelopes}` : text || envelopes; - if (files.length) { - const sent = new Set(files.map(fileIdentity)); + if (pending.length) { + const sent = new Set(pending.map(fileIdentity)); replacePendingFiles(session.sessionId, pendingFiles(session.sessionId).filter((file) => !sent.has(fileIdentity(file)))); } try { - await original.call(conversation, session, prompt, imageIds, mode); + await original.call(conversation, session, prompt, downgradeImages ? [] : imageIds, mode); + if (downgradeImages) conversation.releaseDraftImages(images); } catch (error) { - if (files.length) { + if (pending.length) { const current = pendingFiles(session.sessionId); const currentIds = new Set(current.map(fileIdentity)); - replacePendingFiles(session.sessionId, [...files.filter((file) => !currentIds.has(fileIdentity(file))), ...current]); + replacePendingFiles(session.sessionId, [...pending.filter((file) => !currentIds.has(fileIdentity(file))), ...current]); } throw error; } @@ -175,6 +209,29 @@ ${envelopes}` : text || envelopes; if (level === "error") window.alert(message); } } + async function writeClipboard(text) { + try { + if (window.laobosDesktop?.clipboard?.writeText) { + const result = await window.laobosDesktop.clipboard.writeText(text); + if (result?.written) return true; + } + } catch { + } + return Primitives.writeClipboard(text); + } + function useClipboardFeedback() { + const [status, setStatus] = useState("idle"); + const resetTimer = useRef(); + useEffect(() => () => window.clearTimeout(resetTimer.current), []); + const copy = async (text) => { + window.clearTimeout(resetTimer.current); + const written = await writeClipboard(text); + setStatus(written ? "copied" : "failed"); + resetTimer.current = window.setTimeout(() => setStatus("idle"), written ? 1800 : 3e3); + return written; + }; + return { status, copy }; + } function imageFileFromDesktop(image) { const source = image?.bytes?.type === "Buffer" ? image.bytes.data : image?.bytes; const bytes = source instanceof Uint8Array ? source : new Uint8Array(source || []); @@ -200,37 +257,50 @@ ${envelopes}` : text || envelopes; const bridge = window.laobosDesktop; const unavailable = !bridge?.capabilities?.fileAttachments || busy || input?.phase === "adjudicating" || input?.phase === "submitting"; useEffect(() => { - const paste = async (event) => { - if (!event.target?.closest?.("[data-composer-card]")) return; - const pasted = Array.from(event.clipboardData?.items || []).filter((item) => item.kind === "file").map((item) => item.getAsFile()).filter(Boolean); - if (!pasted.length || pasted.every((file) => NATIVE_IMAGE_TYPES.has(file.type))) return; + const routeFiles = async (files) => { + const images = files.filter((file) => NATIVE_IMAGE_TYPES.has(file.type)); + const ordinary = files.filter((file) => !NATIVE_IMAGE_TYPES.has(file.type)); + const payloads = await Promise.all(ordinary.map(async (file) => ({ + name: file.name, + mimeType: file.type, + size: file.size, + bytes: new Uint8Array(await file.arrayBuffer()) + }))); + const result = await bridge.uploads.pasteFiles(sessionId, payloads); + insertImageFiles(module.ctx, sessionId, images); + addPendingFiles(sessionId, result?.files || []); + }; + const intercept = (event, files) => { + if (!files.length || files.every((file) => NATIVE_IMAGE_TYPES.has(file.type))) return false; event.preventDefault(); - event.stopPropagation(); + event.stopImmediatePropagation(); if (unavailable) { - notify(module.ctx, sessionId, "error", "当前状态无法粘贴附件,请稍后重试。 "); - return; + notify(module.ctx, sessionId, "error", "当前状态无法添加附件,请稍后重试。 "); + return true; } setBusy(true); - try { - const images = pasted.filter((file) => NATIVE_IMAGE_TYPES.has(file.type)); - const ordinary = pasted.filter((file) => !NATIVE_IMAGE_TYPES.has(file.type)); - const payloads = await Promise.all(ordinary.map(async (file) => ({ - name: file.name, - mimeType: file.type, - size: file.size, - bytes: new Uint8Array(await file.arrayBuffer()) - }))); - const result = await bridge.uploads.pasteFiles(sessionId, payloads); - insertImageFiles(module.ctx, sessionId, images); - addPendingFiles(sessionId, result?.files || []); - } catch (error) { + routeFiles(files).catch((error) => { notify(module.ctx, sessionId, "error", error instanceof Error ? error.message : String(error)); - } finally { + }).finally(() => { if (mounted.current) setBusy(false); - } + }); + return true; + }; + const paste = (event) => { + if (!event.target?.closest?.("[data-composer-card]")) return; + const pasted = Array.from(event.clipboardData?.items || []).filter((item) => item.kind === "file").map((item) => item.getAsFile()).filter(Boolean); + intercept(event, pasted); + }; + const drop = (event) => { + const dropped = Array.from(event.dataTransfer?.files || []); + intercept(event, dropped); }; document.addEventListener("paste", paste, true); - return () => document.removeEventListener("paste", paste, true); + document.addEventListener("drop", drop, true); + return () => { + document.removeEventListener("paste", paste, true); + document.removeEventListener("drop", drop, true); + }; }, [bridge, sessionId, unavailable]); const choose = async () => { if (unavailable) return; @@ -263,12 +333,9 @@ ${envelopes}` : text || envelopes; return /* @__PURE__ */ React.createElement("svg", { viewBox: "0 0 16 16", fill: "none", width: "16", height: "16", "aria-hidden": true }, /* @__PURE__ */ React.createElement("path", { d: "m4.5 4.5 7 7m0-7-7 7", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round" })); } function FileCard({ file }) { - const [copied, setCopied] = useState(false); + const { status, copy } = useClipboardFeedback(); const copyPath = async () => { - if (await Primitives.writeClipboard(file.path)) { - setCopied(true); - window.setTimeout(() => setCopied(false), 1e3); - } + await copy(file.path); }; const reveal = async () => { try { @@ -277,7 +344,7 @@ ${envelopes}` : text || envelopes; window.alert(error instanceof Error ? error.message : String(error)); } }; - return /* @__PURE__ */ React.createElement("article", { className: "lbs-file-card", "data-laobos-file-path": file.path, title: file.path }, /* @__PURE__ */ React.createElement("button", { className: "lbs-file-card-open", type: "button", "aria-label": `在文件夹中显示 ${file.name}`, onClick: reveal }, /* @__PURE__ */ React.createElement(FileSvgIcon, null), /* @__PURE__ */ React.createElement("span", { className: "lbs-file-card-main" }, /* @__PURE__ */ React.createElement("span", { className: "lbs-file-card-name" }, file.name), /* @__PURE__ */ React.createElement("span", { className: "lbs-file-card-meta" }, fileKind(file.name), " · ", formatBytes(file.size)))), /* @__PURE__ */ React.createElement(Primitives.Tooltip, { label: copied ? "已复制" : "复制绝对路径", side: "bottom" }, /* @__PURE__ */ React.createElement("button", { className: "lbs-file-card-action", type: "button", "aria-label": "复制文件绝对路径", onClick: copyPath }, copied ? /* @__PURE__ */ React.createElement(Primitives.IconCheckOutline16, null) : /* @__PURE__ */ React.createElement(Primitives.IconCopyOutline16, null)))); + return /* @__PURE__ */ React.createElement("article", { className: "lbs-file-card", "data-laobos-file-path": file.path, title: file.path }, /* @__PURE__ */ React.createElement("button", { className: "lbs-file-card-open", type: "button", "aria-label": `在文件夹中显示 ${file.name}`, onClick: reveal }, /* @__PURE__ */ React.createElement(FileSvgIcon, null), /* @__PURE__ */ React.createElement("span", { className: "lbs-file-card-main" }, /* @__PURE__ */ React.createElement("span", { className: "lbs-file-card-name" }, file.name), /* @__PURE__ */ React.createElement("span", { className: "lbs-file-card-meta" }, fileKind(file.name), " · ", formatBytes(file.size)))), /* @__PURE__ */ React.createElement(Primitives.Tooltip, { label: status === "copied" ? "已复制" : status === "failed" ? "复制失败,请重试" : "复制绝对路径", side: "bottom" }, /* @__PURE__ */ React.createElement("button", { className: "lbs-file-card-action", type: "button", "aria-label": status === "copied" ? "文件绝对路径已复制" : status === "failed" ? "复制文件绝对路径失败,请重试" : "复制文件绝对路径", onClick: copyPath }, status === "copied" ? /* @__PURE__ */ React.createElement(Primitives.IconCheckOutline16, null) : status === "failed" ? /* @__PURE__ */ React.createElement(Primitives.IconWarningOutline16, null) : /* @__PURE__ */ React.createElement(Primitives.IconCopyOutline16, null)))); } function FileComposerRail({ sessionId, input, inputActions }) { const files = usePendingFiles(sessionId); @@ -309,20 +376,17 @@ ${file.path}` }, /* @__PURE__ */ React.createElement(FileSvgIcon, null), /* @__P return parts; } function MessageActions({ text, files, time }) { - const [copied, setCopied] = useState(false); + const { status, copy: write } = useClipboardFeedback(); const copy = async () => { const value = [text, ...files.map((file) => file.path)].filter(Boolean).join("\n"); - if (await Primitives.writeClipboard(value)) { - setCopied(true); - window.setTimeout(() => setCopied(false), 1e3); - } + await write(value); }; let displayTime = ""; if (time !== void 0) { const date = new Date(time); if (!Number.isNaN(date.getTime())) displayTime = date.toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit" }); } - return /* @__PURE__ */ React.createElement("div", { className: "lbs-file-message-actions" }, displayTime ? /* @__PURE__ */ React.createElement("span", { className: "lbs-file-message-time" }, displayTime) : null, /* @__PURE__ */ React.createElement(Primitives.Tooltip, { label: copied ? "已复制" : "复制", side: "bottom" }, /* @__PURE__ */ React.createElement("button", { className: "lbs-file-message-action", type: "button", "aria-label": "复制消息", onClick: copy }, copied ? /* @__PURE__ */ React.createElement(Primitives.IconCheckOutline16, null) : /* @__PURE__ */ React.createElement(Primitives.IconCopyOutline16, null)))); + return /* @__PURE__ */ React.createElement("div", { className: "lbs-file-message-actions" }, displayTime ? /* @__PURE__ */ React.createElement("span", { className: "lbs-file-message-time" }, displayTime) : null, /* @__PURE__ */ React.createElement(Primitives.Tooltip, { label: status === "copied" ? "已复制" : status === "failed" ? "复制失败,请重试" : "复制", side: "bottom" }, /* @__PURE__ */ React.createElement("button", { className: "lbs-file-message-action", type: "button", "aria-label": status === "copied" ? "消息已复制" : status === "failed" ? "复制消息失败,请重试" : "复制消息", onClick: copy }, status === "copied" ? /* @__PURE__ */ React.createElement(Primitives.IconCheckOutline16, null) : status === "failed" ? /* @__PURE__ */ React.createElement(Primitives.IconWarningOutline16, null) : /* @__PURE__ */ React.createElement(Primitives.IconCopyOutline16, null)))); } function FileMessageNode({ node, loadImage }) { const texts = []; @@ -337,7 +401,7 @@ ${file.path}` }, /* @__PURE__ */ React.createElement(FileSvgIcon, null), /* @__P const showBubble = parsed.text !== "" || rest.length > 0; return /* @__PURE__ */ React.createElement("div", { className: "lbs-file-user-row", "data-time-hover-root": true }, /* @__PURE__ */ React.createElement("div", { className: "lbs-file-user-stack" }, /* @__PURE__ */ React.createElement(AttachmentUI.ImageGallery, { images, load: loadImage, align: "end", labels: imageLabels }), showBubble ? /* @__PURE__ */ React.createElement("div", { className: "lbs-file-bubble" }, projectedText(parsed.text), rest.map((block, index) => /* @__PURE__ */ React.createElement("div", { className: "lbs-file-extra", key: index }, /* @__PURE__ */ React.createElement(Primitives.JsonBlock, { label: "附加内容", payload: block, truncatedLabel: (total) => `内容过长(${total} 项)` })))) : null, parsed.files.length ? /* @__PURE__ */ React.createElement("div", { className: "lbs-file-card-list" }, parsed.files.map((file, index) => /* @__PURE__ */ React.createElement(FileCard, { file, key: `${file.id}:${index}` }))) : null), /* @__PURE__ */ React.createElement(MessageActions, { text: parsed.text, files: parsed.files, time: node?.data?.time })); } - const inject = ["sessions", "slots", "conversation"]; + const inject = ["sessions", "slots", "conversation", "modelDirectories"]; function apply(ctx) { module.ctx = ctx; ctx.effect(() => installFileSendChannel(ctx), "laobos-file-attachments: independent file send channel"); diff --git a/packages/laobos-file-attachments/src/client.jsx b/packages/laobos-file-attachments/src/client.jsx index 4a5d322..8f54097 100644 --- a/packages/laobos-file-attachments/src/client.jsx +++ b/packages/laobos-file-attachments/src/client.jsx @@ -96,25 +96,66 @@ window.__ModuleLoader__.load({ return pendingFiles(sessionId); } + function selectedModelSupportsImages(ctx, sessionId) { + try { + const state = ctx.modelDirectories.directoryFor(sessionId).store.getSnapshot(); + const current = state.current; + if (!current) return undefined; + const model = state.groups + .find((group) => group.id === current.provider) + ?.models.find((candidate) => candidate.id === current.model); + if (!Array.isArray(model?.inputModalities)) return undefined; + return model.inputModalities.includes("image"); + } catch { + return undefined; + } + } + + async function persistImagesAsFiles(sessionId, images) { + const bridge = window.laobosDesktop; + if (!bridge?.capabilities?.fileAttachments || !bridge.uploads?.pasteFiles) { + throw new Error("当前模型不支持图片输入,且普通文件上传服务不可用。 "); + } + const payloads = await Promise.all(images.map(async (image) => ({ + name: image.file.name || "image", + mimeType: image.file.type || "application/octet-stream", + size: image.file.size, + bytes: new Uint8Array(await image.file.arrayBuffer()), + }))); + const result = await bridge.uploads.pasteFiles(sessionId, payloads); + return (result?.files || []).map(fileFromReference); + } + function installFileSendChannel(ctx) { const conversation = ctx.get("conversation"); if (!conversation?.sendSession) throw new Error("对话发送服务尚未就绪。 "); const original = conversation.sendSession; const routed = async function routedSendSession(session, text, imageIds, mode) { - const files = pendingFiles(session.sessionId); + const pending = pendingFiles(session.sessionId); + const downgradeImages = imageIds.length > 0 + && selectedModelSupportsImages(ctx, session.sessionId) !== true; + const images = downgradeImages ? conversation.draftImages(imageIds) : []; + if (downgradeImages && images.length !== imageIds.length) { + throw new Error("一个或多个待发送图片已经失效。 "); + } + const converted = downgradeImages + ? await persistImagesAsFiles(session.sessionId, images) + : []; + const files = [...pending, ...converted]; const envelopes = files.map(serializeFileEnvelope).join("\n\n"); const prompt = text && envelopes ? `${text}\n\n${envelopes}` : text || envelopes; - if (files.length) { - const sent = new Set(files.map(fileIdentity)); + if (pending.length) { + const sent = new Set(pending.map(fileIdentity)); replacePendingFiles(session.sessionId, pendingFiles(session.sessionId).filter((file) => !sent.has(fileIdentity(file)))); } try { - await original.call(conversation, session, prompt, imageIds, mode); + await original.call(conversation, session, prompt, downgradeImages ? [] : imageIds, mode); + if (downgradeImages) conversation.releaseDraftImages(images); } catch (error) { - if (files.length) { + if (pending.length) { const current = pendingFiles(session.sessionId); const currentIds = new Set(current.map(fileIdentity)); - replacePendingFiles(session.sessionId, [...files.filter((file) => !currentIds.has(fileIdentity(file))), ...current]); + replacePendingFiles(session.sessionId, [...pending.filter((file) => !currentIds.has(fileIdentity(file))), ...current]); } throw error; } @@ -139,6 +180,32 @@ window.__ModuleLoader__.load({ catch { if (level === "error") window.alert(message); } } + async function writeClipboard(text) { + try { + if (window.laobosDesktop?.clipboard?.writeText) { + const result = await window.laobosDesktop.clipboard.writeText(text); + if (result?.written) return true; + } + } catch { + // The browser clipboard implementation below remains available as a fallback. + } + return Primitives.writeClipboard(text); + } + + function useClipboardFeedback() { + const [status, setStatus] = useState("idle"); + const resetTimer = useRef(); + useEffect(() => () => window.clearTimeout(resetTimer.current), []); + const copy = async (text) => { + window.clearTimeout(resetTimer.current); + const written = await writeClipboard(text); + setStatus(written ? "copied" : "failed"); + resetTimer.current = window.setTimeout(() => setStatus("idle"), written ? 1_800 : 3_000); + return written; + }; + return { status, copy }; + } + function imageFileFromDesktop(image) { const source = image?.bytes?.type === "Buffer" ? image.bytes.data : image?.bytes; const bytes = source instanceof Uint8Array ? source : new Uint8Array(source || []); @@ -168,40 +235,53 @@ window.__ModuleLoader__.load({ || input?.phase === "adjudicating" || input?.phase === "submitting"; useEffect(() => { - const paste = async (event) => { - if (!event.target?.closest?.("[data-composer-card]")) return; - const pasted = Array.from(event.clipboardData?.items || []) - .filter((item) => item.kind === "file") - .map((item) => item.getAsFile()) - .filter(Boolean); - if (!pasted.length || pasted.every((file) => NATIVE_IMAGE_TYPES.has(file.type))) return; + const routeFiles = async (files) => { + const images = files.filter((file) => NATIVE_IMAGE_TYPES.has(file.type)); + const ordinary = files.filter((file) => !NATIVE_IMAGE_TYPES.has(file.type)); + const payloads = await Promise.all(ordinary.map(async (file) => ({ + name: file.name, + mimeType: file.type, + size: file.size, + bytes: new Uint8Array(await file.arrayBuffer()), + }))); + const result = await bridge.uploads.pasteFiles(sessionId, payloads); + insertImageFiles(module.ctx, sessionId, images); + addPendingFiles(sessionId, result?.files || []); + }; + const intercept = (event, files) => { + if (!files.length || files.every((file) => NATIVE_IMAGE_TYPES.has(file.type))) return false; event.preventDefault(); - event.stopPropagation(); + event.stopImmediatePropagation(); if (unavailable) { - notify(module.ctx, sessionId, "error", "当前状态无法粘贴附件,请稍后重试。 "); - return; + notify(module.ctx, sessionId, "error", "当前状态无法添加附件,请稍后重试。 "); + return true; } setBusy(true); - try { - const images = pasted.filter((file) => NATIVE_IMAGE_TYPES.has(file.type)); - const ordinary = pasted.filter((file) => !NATIVE_IMAGE_TYPES.has(file.type)); - const payloads = await Promise.all(ordinary.map(async (file) => ({ - name: file.name, - mimeType: file.type, - size: file.size, - bytes: new Uint8Array(await file.arrayBuffer()), - }))); - const result = await bridge.uploads.pasteFiles(sessionId, payloads); - insertImageFiles(module.ctx, sessionId, images); - addPendingFiles(sessionId, result?.files || []); - } catch (error) { + routeFiles(files).catch((error) => { notify(module.ctx, sessionId, "error", error instanceof Error ? error.message : String(error)); - } finally { + }).finally(() => { if (mounted.current) setBusy(false); - } + }); + return true; + }; + const paste = (event) => { + if (!event.target?.closest?.("[data-composer-card]")) return; + const pasted = Array.from(event.clipboardData?.items || []) + .filter((item) => item.kind === "file") + .map((item) => item.getAsFile()) + .filter(Boolean); + intercept(event, pasted); + }; + const drop = (event) => { + const dropped = Array.from(event.dataTransfer?.files || []); + intercept(event, dropped); }; document.addEventListener("paste", paste, true); - return () => document.removeEventListener("paste", paste, true); + document.addEventListener("drop", drop, true); + return () => { + document.removeEventListener("paste", paste, true); + document.removeEventListener("drop", drop, true); + }; }, [bridge, sessionId, unavailable]); const choose = async () => { if (unavailable) return; @@ -252,12 +332,9 @@ window.__ModuleLoader__.load({ } function FileCard({ file }) { - const [copied, setCopied] = useState(false); + const { status, copy } = useClipboardFeedback(); const copyPath = async () => { - if (await Primitives.writeClipboard(file.path)) { - setCopied(true); - window.setTimeout(() => setCopied(false), 1_000); - } + await copy(file.path); }; const reveal = async () => { try { await window.laobosDesktop?.uploads?.reveal?.(file.path); } @@ -271,7 +348,7 @@ window.__ModuleLoader__.load({ {fileKind(file.name)} · {formatBytes(file.size)} - + ; } @@ -328,13 +405,10 @@ window.__ModuleLoader__.load({ } function MessageActions({ text, files, time }) { - const [copied, setCopied] = useState(false); + const { status, copy: write } = useClipboardFeedback(); const copy = async () => { const value = [text, ...files.map((file) => file.path)].filter(Boolean).join("\n"); - if (await Primitives.writeClipboard(value)) { - setCopied(true); - window.setTimeout(() => setCopied(false), 1_000); - } + await write(value); }; let displayTime = ""; if (time !== undefined) { @@ -343,7 +417,7 @@ window.__ModuleLoader__.load({ } return
{displayTime ? {displayTime} : null} - +
; } @@ -368,7 +442,7 @@ window.__ModuleLoader__.load({ ; } - const inject = ["sessions", "slots", "conversation"]; + const inject = ["sessions", "slots", "conversation", "modelDirectories"]; function apply(ctx) { module.ctx = ctx; ctx.effect(() => installFileSendChannel(ctx), "laobos-file-attachments: independent file send channel"); diff --git a/packages/laobos-market/README.md b/packages/laobos-market/README.md index 5410ea2..5995784 100644 --- a/packages/laobos-market/README.md +++ b/packages/laobos-market/README.md @@ -9,9 +9,11 @@ | 功能 | 说明 | | --- | --- | | 🔍 查询 + 正则筛选 | 关键词搜索 GitHub `dsh-plugin` 市场(分页拉取、按星数/Fork/更新时间排序),支持对 **仓库名 / owner·仓库 / 描述 / 全部字段** 做正则二次筛选(不区分大小写) | -| 📦 下载安装 | 下载仓库 tarball → 解压到 `/profiles//node_modules/` → 在 `cordis.patch.yml` 注册插件条目(幂等去重)→ 提示重启生效;支持 `force` 覆盖 | +| 📦 下载安装 | 下载仓库 tarball → 校验 Host/Client 入口及 `__ModuleLoader__` 注册 ID → 事务化写入 `/profiles/` → 提示重启生效;支持 `force` 覆盖 | | 🚀 上传发布 | 本地插件目录(含 package.json)→ 自动 `git init` / 提交(缺 README、LICENSE 自动生成)→ `gh repo create` 公开/私有仓库并推送 → 自动添加 `dsh-plugin` topic 上架市场 | | 🤖 对话工具 | 同时注册 `plugin_market_search` / `plugin_market_install` / `plugin_market_upload` 三个工具,在对话中直接操作市场 | + +市场安装会留下一个仅供下一次启动确认的标记。若新增插件导致 Host 启动失败、Client 加载失败或前端启动超时,桌面端会自动停用该用户插件、保留原始 `cordis.patch.yml` 恢复记录,并以安全模式重启;产品内置插件与核心配置覆盖不会被自动停用。 | 🛡 零依赖 | host 端仅使用 Node 内置模块;自带 HTTP 代理(CONNECT 隧道)支持,可走 `http://127.0.0.1:7890` 等本地代理访问 GitHub | ## 📥 安装 diff --git a/packages/laobos-market/lib/market.js b/packages/laobos-market/lib/market.js index f923d01..c359530 100644 --- a/packages/laobos-market/lib/market.js +++ b/packages/laobos-market/lib/market.js @@ -9,7 +9,16 @@ */ import { execFile } from "node:child_process"; import { createHash, randomUUID } from "node:crypto"; -import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs"; +import { + cpSync, + existsSync, + mkdirSync, + readFileSync, + readdirSync, + renameSync, + rmSync, + writeFileSync, +} from "node:fs"; import http from "node:http"; import https from "node:https"; import net from "node:net"; @@ -19,6 +28,7 @@ import path from "node:path"; import { promisify } from "node:util"; const execFileAsync = promisify(execFile); +const PENDING_PLUGIN_FILE = ".laobos-plugin-pending.json"; export class MarketError extends Error { constructor(code, message, status = 500) { @@ -352,6 +362,108 @@ function sanitizePackageName(name) { return value; } +function exportedPath(value) { + if (typeof value === "string") return value; + if (!value || typeof value !== "object" || Array.isArray(value)) return null; + for (const condition of ["default", "import", "node", "require"]) { + if (typeof value[condition] === "string") return value[condition]; + } + return null; +} + +function resolvePackageFile(packageDir, declaration, label) { + const relative = exportedPath(declaration); + if (!relative) return null; + const resolved = path.resolve(packageDir, relative); + const root = `${path.resolve(packageDir)}${path.sep}`; + if (resolved !== path.resolve(packageDir) && !resolved.startsWith(root)) { + throw new MarketError("PKG_ENTRY_OUTSIDE", `${label} 指向插件目录之外:${relative}`, 400); + } + return existsSync(resolved) ? resolved : null; +} + +function literalPattern(value) { + return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} + +/** Validate the package surfaces DSH will import before changing the live profile. */ +export function validatePluginPackage(pkg, packageDir) { + const packageName = sanitizePackageName(pkg?.name); + const hostDeclaration = typeof pkg.exports === "string" + ? pkg.exports + : pkg.exports?.["."] ?? pkg.main; + const hostEntry = resolvePackageFile(packageDir, hostDeclaration, "Host 入口"); + if (!hostEntry) { + throw new MarketError( + "HOST_ENTRY_MISSING", + `${packageName} 缺少可用的 Host 入口(exports[\".\"] 或 main)。`, + 400, + ); + } + + const client = pkg.dsh?.client; + let clientEntry = null; + if (client !== undefined) { + if (!client || typeof client !== "object" || typeof client.platform !== "string") { + throw new MarketError("CLIENT_DECL_INVALID", `${packageName} 的 dsh.client.platform 必须为字符串。`, 400); + } + if (client.inject !== undefined && ( + !Array.isArray(client.inject) + || client.inject.some((value) => typeof value !== "string") + )) { + throw new MarketError("CLIENT_DECL_INVALID", `${packageName} 的 dsh.client.inject 必须为字符串数组。`, 400); + } + if (client.immediately !== undefined && typeof client.immediately !== "boolean") { + throw new MarketError("CLIENT_DECL_INVALID", `${packageName} 的 dsh.client.immediately 必须为布尔值。`, 400); + } + if (client.platform === "web") { + clientEntry = resolvePackageFile(packageDir, pkg.exports?.["./client"], "Client 入口"); + if (!clientEntry) { + throw new MarketError( + "CLIENT_ENTRY_MISSING", + `${packageName} 声明了 Web Client,但 exports[\"./client\"] 不存在。`, + 400, + ); + } + const source = readFileSync(clientEntry, "utf8"); + const hasLoaderCall = /(?:window|globalThis)\s*\.\s*__ModuleLoader__\s*\.\s*load\s*\(/u.test(source); + const hasMatchingId = new RegExp(`\\bid\\s*:\\s*(["'])${literalPattern(packageName)}\\1`, "u").test(source); + if (!hasLoaderCall || !hasMatchingId) { + throw new MarketError( + "CLIENT_REGISTRATION_MISMATCH", + `${packageName} 的 Client bundle 未通过 __ModuleLoader__.load 注册同名模块。`, + 400, + ); + } + } + } + + return { packageName, hostEntry, clientEntry }; +} + +function writeFileAtomicSync(filePath, contents) { + mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 }); + const temporary = `${filePath}.tmp-${process.pid}-${Date.now()}`; + try { + writeFileSync(temporary, contents, { encoding: "utf8", mode: 0o600 }); + renameSync(temporary, filePath); + } catch (error) { + rmSync(temporary, { force: true }); + throw error; + } +} + +function markPluginPending(profileDir, plugin) { + writeFileAtomicSync( + path.join(profileDir, PENDING_PLUGIN_FILE), + `${JSON.stringify({ + schema: 1, + installedAt: new Date().toISOString(), + ...plugin, + }, null, 2)}\n`, + ); +} + export function profileDirOf(dshHome, profileName) { if (!dshHome) throw new MarketError("DSH_HOME_MISSING", "无法确定 DSH_HOME,安装需要主机环境。", 500); return path.join(dshHome, "profiles", profileName || "web"); @@ -413,37 +525,68 @@ export async function installPlugin({ lastError = new MarketError("PKG_INVALID", `package.json 解析失败:${error.message}`, 400); continue; } - const packageName = sanitizePackageName(pkg.name); + const validation = validatePluginPackage(pkg, sourceDir); + const packageName = validation.packageName; const targetDir = path.join(profileDir, "node_modules", ...packageName.split("/")); - if (existsSync(targetDir)) { - if (!force) { - throw new MarketError("ALREADY_INSTALLED", `${packageName} 已安装(${targetDir}),如需覆盖请使用 force。`, 409); - } - rmSync(targetDir, { recursive: true, force: true }); + const targetExists = existsSync(targetDir); + if (targetExists && !force) { + throw new MarketError("ALREADY_INSTALLED", `${packageName} 已安装(${targetDir}),如需覆盖请使用 force。`, 409); } + const patchFile = path.join(profileDir, "cordis.patch.yml"); + const entryId = packageName.replace(/^@/, "").replace(/\//g, "-"); + const stagingDir = `${targetDir}.installing-${randomUUID().slice(0, 8)}`; + const backupDir = `${targetDir}.backup-${randomUUID().slice(0, 8)}`; + const pendingFile = path.join(profileDir, PENDING_PLUGIN_FILE); + const originalPatch = existsSync(patchFile) ? readFileSync(patchFile, "utf8") : null; + const originalPending = existsSync(pendingFile) ? readFileSync(pendingFile, "utf8") : null; + let targetBackedUp = false; + let targetCommitted = false; + mkdirSync(path.dirname(targetDir), { recursive: true, mode: 0o700 }); - await run("cp", ["-R", `${sourceDir}/.`, targetDir], { timeout: 60000 }); + rmSync(stagingDir, { recursive: true, force: true }); + rmSync(backupDir, { recursive: true, force: true }); + cpSync(sourceDir, stagingDir, { recursive: true, force: false, errorOnExist: true }); - const patchFile = path.join(profileDir, "cordis.patch.yml"); - const patch = registerPatchEntry(patchFile, { - id: packageName.replace(/^@/, "").replace(/\//g, "-"), - name: packageName, - }); - const entryFile = resolveEntryFile(pkg, targetDir); - return { - installed: true, - packageName, - owner, - repo, - ref: branch, - targetDir, - patchFile, - patch, - entryFile, - entryWarning: entryFile === null ? "未找到可用的入口文件(exports.\".\" 或 main),该插件可能无法加载。" : null, - restartRequired: true, - message: `已安装 ${packageName} 到 ${targetDir};重启 dsh web 后生效。`, - }; + try { + if (targetExists) { + renameSync(targetDir, backupDir); + targetBackedUp = true; + } + renameSync(stagingDir, targetDir); + targetCommitted = true; + + const patch = registerPatchEntry(patchFile, { id: entryId, name: packageName }); + markPluginPending(profileDir, { entryId, packageName, ref: branch }); + rmSync(backupDir, { recursive: true, force: true }); + return { + installed: true, + packageName, + owner, + repo, + ref: branch, + targetDir, + patchFile, + patch, + entryFile: path.join(targetDir, path.relative(sourceDir, validation.hostEntry)), + clientEntry: validation.clientEntry + ? path.join(targetDir, path.relative(sourceDir, validation.clientEntry)) + : null, + restartRequired: true, + startupProtected: true, + message: `已安装 ${packageName} 到 ${targetDir};重启后若插件启动失败,劳博士会自动隔离并恢复。`, + }; + } catch (error) { + if (targetCommitted) rmSync(targetDir, { recursive: true, force: true }); + if (targetBackedUp && existsSync(backupDir)) renameSync(backupDir, targetDir); + if (originalPatch === null) rmSync(patchFile, { force: true }); + else writeFileAtomicSync(patchFile, originalPatch); + if (originalPending === null) rmSync(pendingFile, { force: true }); + else writeFileAtomicSync(pendingFile, originalPending); + throw error; + } finally { + rmSync(stagingDir, { recursive: true, force: true }); + rmSync(backupDir, { recursive: true, force: true }); + } } throw lastError || new MarketError("INSTALL_FAILED", "安装失败:没有可用分支。", 500); } finally { @@ -451,18 +594,6 @@ export async function installPlugin({ } } -function resolveEntryFile(pkg, packageDir) { - const candidates = []; - const mainEntry = typeof pkg.exports === "string" ? pkg.exports : pkg.exports?.["."]; - if (typeof mainEntry === "string") candidates.push(mainEntry); - if (pkg.main) candidates.push(pkg.main); - for (const candidate of candidates) { - const resolved = path.resolve(packageDir, candidate); - if (existsSync(resolved)) return resolved; - } - return null; -} - /** * 把插件条目追加注册到 profile 的 cordis.patch.yml(幂等:按 id 去重)。 */ @@ -494,7 +625,7 @@ export function registerPatchEntry(patchFile, entry) { } else { next = `${text.replace(/\s+$/, "")}${text ? "\n" : ""}${block}`; } - writeFileSync(patchFile, next, "utf8"); + writeFileAtomicSync(patchFile, next); return { already: false, id: entry.id }; } diff --git a/packages/laobos-shell/lib/client.js b/packages/laobos-shell/lib/client.js index 720a951..94a7077 100644 --- a/packages/laobos-shell/lib/client.js +++ b/packages/laobos-shell/lib/client.js @@ -50,6 +50,8 @@ const wslText = useMemo(() => { if (!state?.wsl?.available) return "Windows 组件尚未启用"; if (!state.wsl.distributions?.length) return "尚未安装 Linux 发行版"; + if (state.wsl.defaultUserIsRoot) return `${state.wsl.distribution} 可用,待创建普通用户`; + if (state.wsl.initializationBlocked) return `${state.wsl.distribution} 首次初始化可能卡住`; if (!state.wsl.ready) return `${state.wsl.distribution || state.wsl.distributions[0]} 需要初始化或修复`; return `${state.wsl.distribution} 已就绪`; }, [state]); @@ -133,11 +135,14 @@ "div", { className: "lbs-shell-actions" }, h("button", { type: "button", className: "lbs-shell-button secondary", disabled: busy, onClick: () => action(() => api.refresh()) }, busy ? "处理中…" : "重新检测"), - state?.platform === "win32" && !state?.wsl?.ready && !state?.wsl?.installed ? h("button", { type: "button", className: "lbs-shell-button", disabled: busy, onClick: () => action(() => api.installWsl("Ubuntu")) }, "安装 WSL + Ubuntu") : null, + state?.platform === "win32" && !state?.wsl?.ready && !state?.wsl?.installed ? h("button", { type: "button", className: "lbs-shell-button", disabled: busy, onClick: () => action(() => api.installWsl("Ubuntu-24.04")) }, "安装 WSL + Ubuntu 24.04") : null, state?.platform === "win32" && !state?.wsl?.ready && state?.wsl?.installed && state?.wsl?.distribution ? h("button", { type: "button", className: "lbs-shell-button", disabled: busy, onClick: () => action(() => api.initializeWsl()) }, "打开 Linux 初始化窗口") : null, + state?.platform === "win32" && state?.wsl?.defaultUserIsRoot ? h("button", { type: "button", className: "lbs-shell-button", disabled: busy, onClick: () => action(() => api.initializeWsl()) }, "打开 Linux 用户设置") : null, state?.status === "error" || state?.status === "attention" || state?.lastError ? h("button", { type: "button", className: "lbs-shell-button secondary", disabled: busy, onClick: prepareRepair }, "创建诊断对话") : null ), state?.requiresRestart ? h("div", { className: "lbs-shell-note" }, "Windows 需要重启。劳博士会保留安装状态,并在下次启动时自动检测。") : null, + state?.wsl?.initializationBlocked ? h("div", { className: "lbs-shell-note" }, "发行版可能被首次启动窗口或 OOBE 状态阻塞。请先关闭残留安装窗口,再创建诊断对话;劳博士不会自动修改注册表。") : null, + state?.wsl?.defaultUserIsRoot ? h("div", { className: "lbs-shell-note" }, "WSL 已能运行,但长期使用 root 风险较高。请创建普通 Linux 用户、加入 sudo 组并设为默认登录用户。") : null, error || state?.lastError ? h("div", { className: "lbs-shell-note lbs-shell-error" }, error || state.lastError) : null, h("div", { className: "lbs-shell-note" }, "性能模式在 Windows 上优先使用 WSL;WSL 不可用时依次降级到 Git Bash 和 PowerShell。需要管理员权限的安装或修复操作始终由你确认。"), repairPrompt ? h( diff --git a/packages/laobos-shell/src/client.jsx b/packages/laobos-shell/src/client.jsx index 256c980..9754917 100644 --- a/packages/laobos-shell/src/client.jsx +++ b/packages/laobos-shell/src/client.jsx @@ -53,6 +53,8 @@ window.__ModuleLoader__.load({ const wslText = useMemo(() => { if (!state?.wsl?.available) return "Windows 组件尚未启用"; if (!state.wsl.distributions?.length) return "尚未安装 Linux 发行版"; + if (state.wsl.defaultUserIsRoot) return `${state.wsl.distribution} 可用,待创建普通用户`; + if (state.wsl.initializationBlocked) return `${state.wsl.distribution} 首次初始化可能卡住`; if (!state.wsl.ready) return `${state.wsl.distribution || state.wsl.distributions[0]} 需要初始化或修复`; return `${state.wsl.distribution} 已就绪`; }, [state]); @@ -136,16 +138,21 @@ window.__ModuleLoader__.load({ h("div", { className: "lbs-shell-actions" }, h("button", { type: "button", className: "lbs-shell-button secondary", disabled: busy, onClick: () => action(() => api.refresh()) }, busy ? "处理中…" : "重新检测"), state?.platform === "win32" && !state?.wsl?.ready && !state?.wsl?.installed - ? h("button", { type: "button", className: "lbs-shell-button", disabled: busy, onClick: () => action(() => api.installWsl("Ubuntu")) }, "安装 WSL + Ubuntu") + ? h("button", { type: "button", className: "lbs-shell-button", disabled: busy, onClick: () => action(() => api.installWsl("Ubuntu-24.04")) }, "安装 WSL + Ubuntu 24.04") : null, state?.platform === "win32" && !state?.wsl?.ready && state?.wsl?.installed && state?.wsl?.distribution ? h("button", { type: "button", className: "lbs-shell-button", disabled: busy, onClick: () => action(() => api.initializeWsl()) }, "打开 Linux 初始化窗口") : null, + state?.platform === "win32" && state?.wsl?.defaultUserIsRoot + ? h("button", { type: "button", className: "lbs-shell-button", disabled: busy, onClick: () => action(() => api.initializeWsl()) }, "打开 Linux 用户设置") + : null, state?.status === "error" || state?.status === "attention" || state?.lastError ? h("button", { type: "button", className: "lbs-shell-button secondary", disabled: busy, onClick: prepareRepair }, "创建诊断对话") : null, ), state?.requiresRestart ? h("div", { className: "lbs-shell-note" }, "Windows 需要重启。劳博士会保留安装状态,并在下次启动时自动检测。") : null, + state?.wsl?.initializationBlocked ? h("div", { className: "lbs-shell-note" }, "发行版可能被首次启动窗口或 OOBE 状态阻塞。请先关闭残留安装窗口,再创建诊断对话;劳博士不会自动修改注册表。") : null, + state?.wsl?.defaultUserIsRoot ? h("div", { className: "lbs-shell-note" }, "WSL 已能运行,但长期使用 root 风险较高。请创建普通 Linux 用户、加入 sudo 组并设为默认登录用户。") : null, error || state?.lastError ? h("div", { className: "lbs-shell-note lbs-shell-error" }, error || state.lastError) : null, h("div", { className: "lbs-shell-note" }, "性能模式在 Windows 上优先使用 WSL;WSL 不可用时依次降级到 Git Bash 和 PowerShell。需要管理员权限的安装或修复操作始终由你确认。"), repairPrompt ? h("section", { className: "lbs-shell-repair" }, diff --git a/packages/laobos-ssh/lib/client.js b/packages/laobos-ssh/lib/client.js index 730d056..7e093ea 100644 --- a/packages/laobos-ssh/lib/client.js +++ b/packages/laobos-ssh/lib/client.js @@ -9438,6 +9438,7 @@ ${h2.join(` const css = `${xterm_default} .lbs-ssh-panel{background:var(--dsw-alias-bg-base);bottom:0;color:var(--dsw-alias-label-primary);display:grid;grid-template-rows:42px minmax(0,1fr) 24px;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483060}.lbs-ssh-toolbar{align-items:center;background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;gap:4px;padding:0 8px}.lbs-ssh-toolbar strong{font-size:13px;margin:0 4px}.lbs-ssh-toolbar-spacer{flex:1}.lbs-ssh-button,.lbs-ssh-icon{appearance:none;background:transparent;border:0;border-radius:6px;color:inherit;cursor:pointer;font:inherit;font-size:11px;height:29px;padding:0 9px}.lbs-ssh-icon{display:grid;padding:0;place-items:center;width:29px}.lbs-ssh-button:hover,.lbs-ssh-icon:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-ssh-button.primary{background:var(--dsw-alias-interactive-bg-primary);color:var(--dsw-alias-label-on-primary)}.lbs-ssh-button:disabled,.lbs-ssh-icon:disabled{cursor:not-allowed;opacity:.42}.lbs-ssh-layout{display:grid;grid-template-columns:230px minmax(0,1fr);min-height:0}.lbs-ssh-sidebar{background:var(--dsw-alias-bg-layer-1);border-right:1px solid var(--dsw-alias-border-l1);display:grid;grid-template-rows:42px minmax(0,1fr);min-height:0}.lbs-ssh-search{align-items:center;display:flex;padding:7px}.lbs-ssh-search input{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;box-sizing:border-box;color:inherit;font:11px inherit;height:28px;padding:0 8px;width:100%}.lbs-ssh-groups{min-height:0;overflow:auto;padding:0 5px 8px}.lbs-ssh-group h3{align-items:center;color:var(--dsw-alias-label-tertiary);display:flex;font-size:9px;height:24px;margin:0;padding:0 5px}.lbs-ssh-group h3 span{margin-left:auto}.lbs-ssh-row{align-items:center;border-radius:6px;display:grid;grid-template-columns:minmax(0,1fr) 27px 27px 27px;margin-bottom:2px}.lbs-ssh-row[data-active=true],.lbs-ssh-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-ssh-row-main{background:transparent;border:0;color:inherit;cursor:pointer;display:grid;font:inherit;gap:2px;min-width:0;padding:7px 5px 7px 8px;text-align:left}.lbs-ssh-row-main strong,.lbs-ssh-row-main small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-ssh-row-main strong{font-size:11px}.lbs-ssh-row-main small{color:var(--dsw-alias-label-tertiary);font-size:9px}.lbs-ssh-row-action{background:transparent;border:0;border-radius:5px;color:var(--dsw-alias-label-secondary);cursor:pointer;height:25px;opacity:.1}.lbs-ssh-row:hover .lbs-ssh-row-action,.lbs-ssh-row-action:focus-visible{opacity:1}.lbs-ssh-row-action:hover{background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary)}.lbs-ssh-row-action.danger:hover{color:#d94b4b}.lbs-ssh-empty-list{align-content:center;color:var(--dsw-alias-label-tertiary);display:grid;font-size:10px;gap:8px;justify-items:center;min-height:150px;padding:14px;text-align:center}.lbs-ssh-workspace{background:#101419;display:grid;grid-template-rows:auto minmax(0,1fr);min-height:0;min-width:0}.lbs-ssh-tabs{background:#181d23;border-bottom:1px solid #2b323b;display:flex;min-height:34px;overflow:auto hidden}.lbs-ssh-tab{align-items:center;border-right:1px solid #2b323b;border-top:2px solid transparent;color:#95a0ab;display:flex;max-width:200px;min-width:125px}.lbs-ssh-tab[data-active=true]{background:#101419;border-top-color:#55b58a;color:#e8edf2}.lbs-ssh-tab-main{align-items:center;background:transparent;border:0;color:inherit;cursor:pointer;display:flex;flex:1;font:10px inherit;gap:6px;min-width:0;padding:0 8px}.lbs-ssh-tab-main span:nth-child(2){overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-ssh-tab-close{background:transparent;border:0;color:inherit;height:25px;width:25px}.lbs-ssh-dot{background:#87929d;border-radius:50%;height:6px;width:6px}.lbs-ssh-dot[data-state=connected]{background:#39b87b}.lbs-ssh-dot[data-state=connecting],.lbs-ssh-dot[data-state=awaiting]{background:#e1a83d}.lbs-ssh-dot[data-state=error]{background:#e25d68}.lbs-ssh-stage{min-height:0;position:relative}.lbs-ssh-surface{inset:0;pointer-events:none;position:absolute;visibility:hidden}.lbs-ssh-surface[data-active=true]{pointer-events:auto;visibility:visible}.lbs-ssh-host{box-sizing:border-box;height:100%;padding:8px}.lbs-ssh-empty{align-content:center;color:#8f9aa6;display:grid;gap:9px;height:100%;justify-items:center;padding:28px;text-align:center}.lbs-ssh-empty strong{color:#e3e9ee;font-size:13px}.lbs-ssh-empty p{font-size:11px;line-height:1.5;margin:0;max-width:430px}.lbs-ssh-error{background:#482129;color:#ffc4ca;font-size:11px;left:10px;max-width:calc(100% - 20px);padding:7px 10px;position:absolute;top:9px;z-index:3}.lbs-ssh-global-error{background:#482129;border:1px solid #6d303a;border-radius:6px;color:#ffc4ca;font-size:10px;max-width:min(520px,calc(100% - 20px));padding:7px 10px;pointer-events:none;position:absolute;right:10px;top:48px;z-index:6}.lbs-ssh-status{align-items:center;background:var(--dsw-alias-bg-layer-1);border-top:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);display:flex;font-size:9px;gap:12px;padding:0 8px}.lbs-ssh-status span:last-child{margin-left:auto}.lbs-ssh-modal-backdrop{align-items:center;background:rgba(0,0,0,.46);display:flex;inset:0;justify-content:center;padding:22px;position:fixed;z-index:2147483220}.lbs-ssh-modal{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;box-shadow:var(--dsw-shadow-lv3);display:grid;grid-template-rows:46px minmax(0,1fr) auto;max-height:min(760px,92vh);overflow:hidden;width:min(610px,calc(100vw - 34px))}.lbs-ssh-modal.wide{width:min(820px,calc(100vw - 34px))}.lbs-ssh-modal-header{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;padding:0 14px}.lbs-ssh-modal-header h2{font-size:14px;margin:0}.lbs-ssh-modal-header button{margin-left:auto}.lbs-ssh-modal-body{min-height:0;overflow:auto;padding:15px}.lbs-ssh-modal-footer{border-top:1px solid var(--dsw-alias-border-l1);display:flex;gap:7px;justify-content:flex-end;padding:10px 14px}.lbs-ssh-form{display:grid;gap:12px}.lbs-ssh-form-grid{display:grid;gap:10px;grid-template-columns:1fr 110px}.lbs-ssh-form label{color:var(--dsw-alias-label-secondary);display:grid;font-size:10px;gap:5px}.lbs-ssh-form .wide{grid-column:1/-1}.lbs-ssh-form input,.lbs-ssh-form select,.lbs-ssh-form textarea{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;box-sizing:border-box;color:inherit;font:11px inherit;height:32px;padding:0 8px;width:100%}.lbs-ssh-form textarea{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;height:112px;padding:8px;resize:vertical}.lbs-ssh-check{align-items:center!important;display:flex!important;gap:7px!important}.lbs-ssh-check input{height:14px!important;width:14px!important}.lbs-ssh-help{color:var(--dsw-alias-label-tertiary);font-size:9px;line-height:1.5;margin:0}.lbs-ssh-form-error{color:#d94b4b;font-size:10px;margin:0}.lbs-ssh-credentials{display:grid;gap:7px}.lbs-ssh-credential{align-items:center;border:1px solid var(--dsw-alias-border-l1);border-radius:7px;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:9px;padding:9px}.lbs-ssh-credential span{display:grid;gap:2px}.lbs-ssh-credential small{color:var(--dsw-alias-label-tertiary);font-size:9px}.lbs-ssh-fingerprint{background:var(--dsw-alias-bg-base);border-radius:6px;font:10px ui-monospace,SFMono-Regular,Menlo,monospace;padding:9px;word-break:break-all}@media(max-width:850px){.lbs-ssh-panel{left:0;right:0}.lbs-ssh-layout{grid-template-columns:195px minmax(0,1fr)}}@media(max-width:620px){.lbs-ssh-layout{grid-template-columns:1fr}.lbs-ssh-sidebar{display:none}.lbs-ssh-toolbar strong{display:none}} + .lbs-ssh-workspace,.lbs-ssh-stage{background:var(--dsw-alias-bg-base)}.lbs-ssh-tabs{background:var(--dsw-alias-bg-layer-1);border-bottom-color:var(--dsw-alias-border-l1)}.lbs-ssh-tab{border-right-color:var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary)}.lbs-ssh-tab[data-active=true]{background:var(--dsw-alias-bg-base);border-top-color:var(--dsw-alias-state-success-primary,#39b87b);color:var(--dsw-alias-label-primary)}.lbs-ssh-empty{color:var(--dsw-alias-label-tertiary)}.lbs-ssh-empty strong{color:var(--dsw-alias-label-primary)}.lbs-ssh-error,.lbs-ssh-global-error{background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#d94b4b) 10%,var(--dsw-alias-bg-layer-1));border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary,#d94b4b) 28%,transparent);color:var(--dsw-alias-state-error-primary,#d94b4b)} `; if (typeof document !== "undefined" && !document.querySelector('style[data-plugin-css="@laobos/dsh-ssh"]')) { const style = document.createElement("style"); @@ -9445,6 +9446,48 @@ ${h2.join(` style.textContent = css; document.head.append(style); } + function terminalTheme(element) { + const styles = getComputedStyle(element); + const color = (name, fallback) => styles.getPropertyValue(name).trim() || fallback; + const dark = document.body.hasAttribute("data-ds-dark-theme"); + return { + background: color("--dsw-alias-bg-base", dark ? "#151517" : "#ffffff"), + foreground: color("--dsw-alias-label-primary", dark ? "#f1f3f5" : "#0f1115"), + cursor: color("--dsw-alias-label-primary", dark ? "#f1f3f5" : "#0f1115"), + cursorAccent: color("--dsw-alias-bg-base", dark ? "#151517" : "#ffffff"), + selectionBackground: color("--dsw-alias-interactive-bg-active", dark ? "rgba(88,166,255,.28)" : "rgba(9,105,218,.18)"), + black: dark ? "#484f58" : "#24292f", + red: dark ? "#ff7b72" : "#cf222e", + green: dark ? "#3fb950" : "#1a7f37", + yellow: dark ? "#d29922" : "#9a6700", + blue: dark ? "#58a6ff" : "#0969da", + magenta: dark ? "#bc8cff" : "#8250df", + cyan: dark ? "#39c5cf" : "#1b7c83", + white: dark ? "#b1bac4" : "#6e7781", + brightBlack: dark ? "#6e7681" : "#57606a", + brightRed: dark ? "#ffa198" : "#a40e26", + brightGreen: dark ? "#56d364" : "#116329", + brightYellow: dark ? "#e3b341" : "#4d2d00", + brightBlue: dark ? "#79c0ff" : "#218bff", + brightMagenta: dark ? "#d2a8ff" : "#a475f9", + brightCyan: dark ? "#56d4dd" : "#3192aa", + brightWhite: dark ? "#f0f6fc" : "#24292f" + }; + } + function syncTerminalTheme(terminal, element) { + const applyTheme = () => { + terminal.options.theme = terminalTheme(element); + }; + const observer = new MutationObserver(applyTheme); + observer.observe(document.body, { attributes: true, attributeFilter: ["data-ds-dark-theme"] }); + const media = window.matchMedia?.("(prefers-color-scheme: dark)"); + media?.addEventListener?.("change", applyTheme); + applyTheme(); + return () => { + observer.disconnect(); + media?.removeEventListener?.("change", applyTheme); + }; + } function Modal({ title, wide, children, footer, onClose }) { return /* @__PURE__ */ React.createElement("div", { className: "lbs-ssh-modal-backdrop", onMouseDown: (event) => { if (event.target === event.currentTarget) onClose(); @@ -9588,11 +9631,12 @@ ${h2.join(` } let connectionId = ""; let disposed = false; - const terminal = new Dl({ cursorBlink: true, fontSize: 13, lineHeight: 1.2, scrollback: 1e4, theme: { background: "#101419", foreground: "#e8edf2", cursor: "#d8e6f3" } }); + const terminal = new Dl({ cursorBlink: true, fontSize: 13, lineHeight: 1.2, scrollback: 1e4, theme: terminalTheme(host.current) }); terminalRef.current = terminal; const fit = new o(); terminal.loadAddon(fit); terminal.open(host.current); + const stopThemeSync = syncTerminalTheme(terminal, host.current); const fitTerminal = () => { try { fit.fit(); @@ -9642,6 +9686,7 @@ ${h2.join(` return () => { disposed = true; terminalRef.current = null; + stopThemeSync(); resize.disconnect(); input.dispose(); offData(); diff --git a/packages/laobos-ssh/src/client.jsx b/packages/laobos-ssh/src/client.jsx index 1ec96e6..ea09a3f 100644 --- a/packages/laobos-ssh/src/client.jsx +++ b/packages/laobos-ssh/src/client.jsx @@ -13,11 +13,39 @@ window.__ModuleLoader__.load({ const css = `${xtermCss}\n .lbs-ssh-panel{background:var(--dsw-alias-bg-base);bottom:0;color:var(--dsw-alias-label-primary);display:grid;grid-template-rows:42px minmax(0,1fr) 24px;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483060}.lbs-ssh-toolbar{align-items:center;background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;gap:4px;padding:0 8px}.lbs-ssh-toolbar strong{font-size:13px;margin:0 4px}.lbs-ssh-toolbar-spacer{flex:1}.lbs-ssh-button,.lbs-ssh-icon{appearance:none;background:transparent;border:0;border-radius:6px;color:inherit;cursor:pointer;font:inherit;font-size:11px;height:29px;padding:0 9px}.lbs-ssh-icon{display:grid;padding:0;place-items:center;width:29px}.lbs-ssh-button:hover,.lbs-ssh-icon:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-ssh-button.primary{background:var(--dsw-alias-interactive-bg-primary);color:var(--dsw-alias-label-on-primary)}.lbs-ssh-button:disabled,.lbs-ssh-icon:disabled{cursor:not-allowed;opacity:.42}.lbs-ssh-layout{display:grid;grid-template-columns:230px minmax(0,1fr);min-height:0}.lbs-ssh-sidebar{background:var(--dsw-alias-bg-layer-1);border-right:1px solid var(--dsw-alias-border-l1);display:grid;grid-template-rows:42px minmax(0,1fr);min-height:0}.lbs-ssh-search{align-items:center;display:flex;padding:7px}.lbs-ssh-search input{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;box-sizing:border-box;color:inherit;font:11px inherit;height:28px;padding:0 8px;width:100%}.lbs-ssh-groups{min-height:0;overflow:auto;padding:0 5px 8px}.lbs-ssh-group h3{align-items:center;color:var(--dsw-alias-label-tertiary);display:flex;font-size:9px;height:24px;margin:0;padding:0 5px}.lbs-ssh-group h3 span{margin-left:auto}.lbs-ssh-row{align-items:center;border-radius:6px;display:grid;grid-template-columns:minmax(0,1fr) 27px 27px 27px;margin-bottom:2px}.lbs-ssh-row[data-active=true],.lbs-ssh-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-ssh-row-main{background:transparent;border:0;color:inherit;cursor:pointer;display:grid;font:inherit;gap:2px;min-width:0;padding:7px 5px 7px 8px;text-align:left}.lbs-ssh-row-main strong,.lbs-ssh-row-main small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-ssh-row-main strong{font-size:11px}.lbs-ssh-row-main small{color:var(--dsw-alias-label-tertiary);font-size:9px}.lbs-ssh-row-action{background:transparent;border:0;border-radius:5px;color:var(--dsw-alias-label-secondary);cursor:pointer;height:25px;opacity:.1}.lbs-ssh-row:hover .lbs-ssh-row-action,.lbs-ssh-row-action:focus-visible{opacity:1}.lbs-ssh-row-action:hover{background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary)}.lbs-ssh-row-action.danger:hover{color:#d94b4b}.lbs-ssh-empty-list{align-content:center;color:var(--dsw-alias-label-tertiary);display:grid;font-size:10px;gap:8px;justify-items:center;min-height:150px;padding:14px;text-align:center}.lbs-ssh-workspace{background:#101419;display:grid;grid-template-rows:auto minmax(0,1fr);min-height:0;min-width:0}.lbs-ssh-tabs{background:#181d23;border-bottom:1px solid #2b323b;display:flex;min-height:34px;overflow:auto hidden}.lbs-ssh-tab{align-items:center;border-right:1px solid #2b323b;border-top:2px solid transparent;color:#95a0ab;display:flex;max-width:200px;min-width:125px}.lbs-ssh-tab[data-active=true]{background:#101419;border-top-color:#55b58a;color:#e8edf2}.lbs-ssh-tab-main{align-items:center;background:transparent;border:0;color:inherit;cursor:pointer;display:flex;flex:1;font:10px inherit;gap:6px;min-width:0;padding:0 8px}.lbs-ssh-tab-main span:nth-child(2){overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-ssh-tab-close{background:transparent;border:0;color:inherit;height:25px;width:25px}.lbs-ssh-dot{background:#87929d;border-radius:50%;height:6px;width:6px}.lbs-ssh-dot[data-state=connected]{background:#39b87b}.lbs-ssh-dot[data-state=connecting],.lbs-ssh-dot[data-state=awaiting]{background:#e1a83d}.lbs-ssh-dot[data-state=error]{background:#e25d68}.lbs-ssh-stage{min-height:0;position:relative}.lbs-ssh-surface{inset:0;pointer-events:none;position:absolute;visibility:hidden}.lbs-ssh-surface[data-active=true]{pointer-events:auto;visibility:visible}.lbs-ssh-host{box-sizing:border-box;height:100%;padding:8px}.lbs-ssh-empty{align-content:center;color:#8f9aa6;display:grid;gap:9px;height:100%;justify-items:center;padding:28px;text-align:center}.lbs-ssh-empty strong{color:#e3e9ee;font-size:13px}.lbs-ssh-empty p{font-size:11px;line-height:1.5;margin:0;max-width:430px}.lbs-ssh-error{background:#482129;color:#ffc4ca;font-size:11px;left:10px;max-width:calc(100% - 20px);padding:7px 10px;position:absolute;top:9px;z-index:3}.lbs-ssh-global-error{background:#482129;border:1px solid #6d303a;border-radius:6px;color:#ffc4ca;font-size:10px;max-width:min(520px,calc(100% - 20px));padding:7px 10px;pointer-events:none;position:absolute;right:10px;top:48px;z-index:6}.lbs-ssh-status{align-items:center;background:var(--dsw-alias-bg-layer-1);border-top:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);display:flex;font-size:9px;gap:12px;padding:0 8px}.lbs-ssh-status span:last-child{margin-left:auto}.lbs-ssh-modal-backdrop{align-items:center;background:rgba(0,0,0,.46);display:flex;inset:0;justify-content:center;padding:22px;position:fixed;z-index:2147483220}.lbs-ssh-modal{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;box-shadow:var(--dsw-shadow-lv3);display:grid;grid-template-rows:46px minmax(0,1fr) auto;max-height:min(760px,92vh);overflow:hidden;width:min(610px,calc(100vw - 34px))}.lbs-ssh-modal.wide{width:min(820px,calc(100vw - 34px))}.lbs-ssh-modal-header{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;padding:0 14px}.lbs-ssh-modal-header h2{font-size:14px;margin:0}.lbs-ssh-modal-header button{margin-left:auto}.lbs-ssh-modal-body{min-height:0;overflow:auto;padding:15px}.lbs-ssh-modal-footer{border-top:1px solid var(--dsw-alias-border-l1);display:flex;gap:7px;justify-content:flex-end;padding:10px 14px}.lbs-ssh-form{display:grid;gap:12px}.lbs-ssh-form-grid{display:grid;gap:10px;grid-template-columns:1fr 110px}.lbs-ssh-form label{color:var(--dsw-alias-label-secondary);display:grid;font-size:10px;gap:5px}.lbs-ssh-form .wide{grid-column:1/-1}.lbs-ssh-form input,.lbs-ssh-form select,.lbs-ssh-form textarea{background:var(--dsw-alias-bg-base);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;box-sizing:border-box;color:inherit;font:11px inherit;height:32px;padding:0 8px;width:100%}.lbs-ssh-form textarea{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;height:112px;padding:8px;resize:vertical}.lbs-ssh-check{align-items:center!important;display:flex!important;gap:7px!important}.lbs-ssh-check input{height:14px!important;width:14px!important}.lbs-ssh-help{color:var(--dsw-alias-label-tertiary);font-size:9px;line-height:1.5;margin:0}.lbs-ssh-form-error{color:#d94b4b;font-size:10px;margin:0}.lbs-ssh-credentials{display:grid;gap:7px}.lbs-ssh-credential{align-items:center;border:1px solid var(--dsw-alias-border-l1);border-radius:7px;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:9px;padding:9px}.lbs-ssh-credential span{display:grid;gap:2px}.lbs-ssh-credential small{color:var(--dsw-alias-label-tertiary);font-size:9px}.lbs-ssh-fingerprint{background:var(--dsw-alias-bg-base);border-radius:6px;font:10px ui-monospace,SFMono-Regular,Menlo,monospace;padding:9px;word-break:break-all}@media(max-width:850px){.lbs-ssh-panel{left:0;right:0}.lbs-ssh-layout{grid-template-columns:195px minmax(0,1fr)}}@media(max-width:620px){.lbs-ssh-layout{grid-template-columns:1fr}.lbs-ssh-sidebar{display:none}.lbs-ssh-toolbar strong{display:none}} + .lbs-ssh-workspace,.lbs-ssh-stage{background:var(--dsw-alias-bg-base)}.lbs-ssh-tabs{background:var(--dsw-alias-bg-layer-1);border-bottom-color:var(--dsw-alias-border-l1)}.lbs-ssh-tab{border-right-color:var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary)}.lbs-ssh-tab[data-active=true]{background:var(--dsw-alias-bg-base);border-top-color:var(--dsw-alias-state-success-primary,#39b87b);color:var(--dsw-alias-label-primary)}.lbs-ssh-empty{color:var(--dsw-alias-label-tertiary)}.lbs-ssh-empty strong{color:var(--dsw-alias-label-primary)}.lbs-ssh-error,.lbs-ssh-global-error{background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#d94b4b) 10%,var(--dsw-alias-bg-layer-1));border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary,#d94b4b) 28%,transparent);color:var(--dsw-alias-state-error-primary,#d94b4b)} `; if (typeof document !== "undefined" && !document.querySelector('style[data-plugin-css="@laobos/dsh-ssh"]')) { const style = document.createElement("style"); style.dataset.pluginCss = "@laobos/dsh-ssh"; style.textContent = css; document.head.append(style); } + function terminalTheme(element) { + const styles = getComputedStyle(element); + const color = (name, fallback) => styles.getPropertyValue(name).trim() || fallback; + const dark = document.body.hasAttribute("data-ds-dark-theme"); + return { + background: color("--dsw-alias-bg-base", dark ? "#151517" : "#ffffff"), + foreground: color("--dsw-alias-label-primary", dark ? "#f1f3f5" : "#0f1115"), + cursor: color("--dsw-alias-label-primary", dark ? "#f1f3f5" : "#0f1115"), + cursorAccent: color("--dsw-alias-bg-base", dark ? "#151517" : "#ffffff"), + selectionBackground: color("--dsw-alias-interactive-bg-active", dark ? "rgba(88,166,255,.28)" : "rgba(9,105,218,.18)"), + black: dark ? "#484f58" : "#24292f", red: dark ? "#ff7b72" : "#cf222e", green: dark ? "#3fb950" : "#1a7f37", yellow: dark ? "#d29922" : "#9a6700", + blue: dark ? "#58a6ff" : "#0969da", magenta: dark ? "#bc8cff" : "#8250df", cyan: dark ? "#39c5cf" : "#1b7c83", white: dark ? "#b1bac4" : "#6e7781", + brightBlack: dark ? "#6e7681" : "#57606a", brightRed: dark ? "#ffa198" : "#a40e26", brightGreen: dark ? "#56d364" : "#116329", brightYellow: dark ? "#e3b341" : "#4d2d00", + brightBlue: dark ? "#79c0ff" : "#218bff", brightMagenta: dark ? "#d2a8ff" : "#a475f9", brightCyan: dark ? "#56d4dd" : "#3192aa", brightWhite: dark ? "#f0f6fc" : "#24292f", + }; + } + + function syncTerminalTheme(terminal, element) { + const applyTheme = () => { terminal.options.theme = terminalTheme(element); }; + const observer = new MutationObserver(applyTheme); + observer.observe(document.body, { attributes: true, attributeFilter: ["data-ds-dark-theme"] }); + const media = window.matchMedia?.("(prefers-color-scheme: dark)"); + media?.addEventListener?.("change", applyTheme); + applyTheme(); + return () => { observer.disconnect(); media?.removeEventListener?.("change", applyTheme); }; + } + function Modal({ title, wide, children, footer, onClose }) { return
{ if (event.target === event.currentTarget) onClose(); }}>
@@ -158,9 +186,10 @@ window.__ModuleLoader__.load({ useEffect(() => { if (!host.current || !window.laobosDesktop?.capabilities?.ssh) { onError(session.id, "SSH 仅在桌面版中可用。"); return undefined; } let connectionId = ""; let disposed = false; - const terminal = new Terminal({ cursorBlink: true, fontSize: 13, lineHeight: 1.2, scrollback: 10000, theme: { background: "#101419", foreground: "#e8edf2", cursor: "#d8e6f3" } }); + const terminal = new Terminal({ cursorBlink: true, fontSize: 13, lineHeight: 1.2, scrollback: 10000, theme: terminalTheme(host.current) }); terminalRef.current = terminal; const fit = new FitAddon(); terminal.loadAddon(fit); terminal.open(host.current); + const stopThemeSync = syncTerminalTheme(terminal, host.current); const fitTerminal = () => { try { fit.fit(); if (connectionId) void window.laobosDesktop.ssh.resize({ id: connectionId, cols: terminal.cols, rows: terminal.rows }); } catch {} }; fitTerminal(); const offData = window.laobosDesktop.ssh.onData((event) => { if (event.id === connectionId) terminal.write(event.data); }); @@ -186,7 +215,7 @@ window.__ModuleLoader__.load({ } }; void connect(); - return () => { disposed = true; terminalRef.current = null; resize.disconnect(); input.dispose(); offData(); offExit(); terminal.dispose(); if (connectionId) void window.laobosDesktop.ssh.disconnect(connectionId); }; + return () => { disposed = true; terminalRef.current = null; stopThemeSync(); resize.disconnect(); input.dispose(); offData(); offExit(); terminal.dispose(); if (connectionId) void window.laobosDesktop.ssh.disconnect(connectionId); }; }, [onChallenge, onError, onState, session.generation, session.id, session.profile]); return
; } diff --git a/packages/laobos-system-tools/assets/laobos-logo.png b/packages/laobos-system-tools/assets/laobos-logo.png new file mode 100644 index 0000000..2e89770 Binary files /dev/null and b/packages/laobos-system-tools/assets/laobos-logo.png differ diff --git a/packages/laobos-system-tools/lib/client.js b/packages/laobos-system-tools/lib/client.js index 9c4304d..cf255b7 100644 --- a/packages/laobos-system-tools/lib/client.js +++ b/packages/laobos-system-tools/lib/client.js @@ -103,9 +103,7 @@ window.__ModuleLoader__.load({ .lbs-card{appearance:none;background:transparent;border:1px solid var(--dsw-alias-line-border);border-radius:10px;color:inherit;cursor:pointer;padding:10px;text-align:left;width:100%}.lbs-card:hover,.lbs-card[data-active=true]{background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-line-border-hover)}.lbs-card-title{font-size:14px;font-weight:550}.lbs-meta{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px} .lbs-button{appearance:none;background:var(--dsw-alias-interactive-bg-primary);border:0;border-radius:9px;color:var(--dsw-alias-label-on-primary);cursor:pointer;font:inherit;font-size:13px;height:34px;padding:0 13px}.lbs-button.secondary{background:var(--dsw-alias-interactive-bg-secondary);color:var(--dsw-alias-label-primary)}.lbs-button.danger{background:rgba(218,70,70,.13);color:#d94b4b}.lbs-button:disabled{cursor:not-allowed;opacity:.5} .lbs-input,.lbs-area{box-sizing:border-box;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-line-border);border-radius:9px;color:inherit;font:inherit;font-size:13px;outline:none;padding:8px 10px;width:100%}.lbs-input:focus,.lbs-area:focus{border-color:var(--dsw-alias-line-border-focus)}.lbs-area{min-height:110px;resize:vertical}.lbs-code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;min-height:220px;tab-size:2}.lbs-label{font-size:12px;font-weight:550;margin-bottom:4px}.lbs-empty{align-items:center;color:var(--dsw-alias-label-secondary);display:flex;justify-content:center;min-height:180px;text-align:center}.lbs-error{background:rgba(218,70,70,.1);border-radius:9px;color:#d94b4b;font-size:12px;padding:9px}.lbs-ok{background:rgba(44,168,110,.1);border-radius:9px;color:#2a9b67;font-size:12px;padding:9px;white-space:pre-wrap;word-break:break-word} - .lbs-svg{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-line-border);border-radius:12px;height:260px;width:100%}.lbs-node{fill:var(--dsw-alias-bg-layer-1);stroke:var(--dsw-alias-line-border);stroke-width:1.5}.lbs-node-group[data-selectable=true]{cursor:pointer;outline:none}.lbs-node-group[data-selectable=true]:hover .lbs-node,.lbs-node-group[data-selected=true] .lbs-node{stroke:var(--dsw-alias-brand-primary);stroke-width:2}.lbs-edge{fill:none;stroke:var(--dsw-alias-label-tertiary);stroke-width:1.4}.lbs-node-title{fill:var(--dsw-alias-label-primary);font-size:12px;font-weight:600}.lbs-node-type{fill:var(--dsw-alias-label-tertiary);font-size:10px}.lbs-workflow-node-editor{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-line-border);border-radius:11px;display:flex;flex-direction:column;gap:9px;padding:11px}.lbs-workflow-node-head{align-items:center;display:flex;gap:8px;justify-content:space-between}.lbs-workflow-node-head strong{font-size:13px}.lbs-workflow-node-editor .lbs-code{min-height:130px}.lbs-check{accent-color:var(--dsw-alias-brand-primary)} - .lbs-workflow-list-panel{overflow:hidden;padding:0}.lbs-workflow-table-scroll{overflow:auto}.lbs-workflow-table{min-width:840px}.lbs-workflow-table-head,.lbs-workflow-row{align-items:center;display:grid;grid-template-columns:minmax(280px,1fr) minmax(150px,.62fr) 104px 74px 132px 154px}.lbs-workflow-table-head{background:var(--dsw-alias-bg-layer-2);border-bottom:1px solid var(--dsw-alias-line-border);color:var(--dsw-alias-label-tertiary);font-size:11px;font-weight:550;min-height:38px}.lbs-workflow-table-head>span,.lbs-workflow-cell{box-sizing:border-box;padding:0 12px}.lbs-workflow-row{border-bottom:1px solid var(--dsw-alias-line-border);min-height:68px}.lbs-workflow-row:last-child{border-bottom:0}.lbs-workflow-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-workflow-primary{align-items:center;display:flex;gap:10px;min-width:0}.lbs-workflow-primary-button{align-items:center;appearance:none;background:transparent;border:0;color:inherit;cursor:pointer;display:flex;gap:10px;min-width:0;padding:0;text-align:left}.lbs-workflow-list-icon{align-items:center;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-line-border);border-radius:8px;color:var(--dsw-alias-label-secondary);display:flex;flex:none;height:32px;justify-content:center;width:32px}.lbs-workflow-row-copy{display:flex;flex-direction:column;min-width:0}.lbs-workflow-row-copy>*{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-workflow-tool-name{font:11px/18px ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-workflow-list-status{align-items:center;color:var(--dsw-alias-label-secondary);display:inline-flex;gap:6px;white-space:nowrap}.lbs-workflow-list-status>span{background:var(--dsw-alias-label-quaternary);border-radius:50%;height:7px;width:7px}.lbs-workflow-list-status[data-enabled=true]{color:#2a9b67}.lbs-workflow-list-status[data-enabled=true]>span{background:#2a9b67}.lbs-workflow-list-actions{display:flex;gap:4px;justify-content:flex-end}.lbs-workflow-modal{max-width:980px}.lbs-workflow-modal-summary{display:grid;gap:10px;grid-template-columns:repeat(4,1fr)}.lbs-workflow-summary-item{background:var(--dsw-alias-bg-layer-2);border-radius:9px;display:flex;flex-direction:column;gap:2px;padding:10px}.lbs-workflow-summary-item strong{font-size:14px}.lbs-workflow-summary-item span{color:var(--dsw-alias-label-tertiary);font-size:11px}.lbs-workflow-readonly{display:grid;gap:10px;grid-template-columns:1fr 1fr}.lbs-workflow-readonly>div{min-width:0}.lbs-workflow-readonly code{display:block;margin-top:4px}.lbs-workflow-run-output{max-height:180px;overflow:auto}@media(max-width:700px){.lbs-workflow-modal-summary,.lbs-workflow-readonly{grid-template-columns:1fr 1fr}} - .lbs-automation-list{display:flex;flex-direction:column;gap:6px}.lbs-automation-card{appearance:none;align-items:center;background:transparent;border:1px solid var(--dsw-alias-line-border);border-radius:10px;color:inherit;cursor:pointer;display:grid;gap:10px;grid-template-columns:minmax(0,1fr) auto;padding:11px;text-align:left;width:100%}.lbs-automation-card:hover,.lbs-automation-card[data-active=true]{background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-line-border-hover)}.lbs-automation-card-copy{display:flex;flex-direction:column;min-width:0}.lbs-automation-card-copy>*{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-automation-state{align-items:center;color:var(--dsw-alias-label-tertiary);display:flex;font-size:11px;gap:6px;white-space:nowrap}.lbs-automation-state>span{background:var(--dsw-alias-label-quaternary);border-radius:50%;height:7px;width:7px}.lbs-automation-state[data-enabled=true]{color:#2a9b67}.lbs-automation-state[data-enabled=true]>span{background:#2a9b67}.lbs-automation-detail{display:flex;flex-direction:column;gap:12px}.lbs-automation-detail-head{align-items:flex-start;display:flex;gap:12px;justify-content:space-between}.lbs-automation-detail-head h2{font-size:18px;line-height:25px;margin:0}.lbs-automation-tool{background:var(--dsw-alias-bg-layer-2);border-radius:7px;color:var(--dsw-alias-label-secondary);display:block;font:11px/18px ui-monospace,SFMono-Regular,Menlo,monospace;overflow-wrap:anywhere;padding:7px 9px}.lbs-automation-actions{display:flex;flex-wrap:wrap;gap:8px}.lbs-automation-note{border-top:1px solid var(--dsw-alias-line-border);color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:18px;padding-top:10px} + .lbs-check{accent-color:var(--dsw-alias-brand-primary)} [data-laobos-right-sidebar]{grid-template-columns:var(--lbs-left-column,280px) minmax(0,1fr) var(--lbs-right-column,56px)!important}[data-laobos-native-settings-trigger]{display:none!important}body:has([data-laobos-native-settings-trigger][aria-expanded="true"])>[role="presentation"]:has(>[role="dialog"][aria-modal="true"]){z-index:2147483600!important}.lbs-right-sidebar{background:var(--dsw-specific-sidebar-fill);border-left:1px solid var(--dsw-alias-border-l1);box-sizing:border-box;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;overflow-y:auto;pointer-events:auto;position:absolute;right:0;top:0;bottom:0;transition:width var(--ds-transition-duration-slow,.2s) var(--ds-ease-in-out,ease);width:var(--lbs-right-column,56px)}.lbs-right-sidebar[data-dragging=true]{transition:none}.lbs-right-top{align-items:center;box-sizing:border-box;display:flex;flex:none;height:60px;justify-content:center;padding:8px 10px}.lbs-right-sidebar[data-expanded=true] .lbs-right-top{justify-content:space-between;padding:8px 16px}.lbs-right-brand{display:flex;flex-direction:column;min-width:0}.lbs-right-brand-title{font-size:14px;font-weight:600;line-height:19px}.lbs-right-brand-sub{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:14px}.lbs-right-toggle{appearance:none;align-items:center;background:transparent;border:0;border-radius:8px;color:var(--dsw-alias-label-secondary);cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;width:32px}.lbs-right-toggle:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.lbs-right-nav{display:flex;flex:none;flex-direction:column;gap:2px;padding:4px 10px}.lbs-right-nav-group+.lbs-right-nav-group{border-top:1px solid var(--dsw-alias-border-l1);margin-top:6px;padding-top:8px}.lbs-right-nav-title{color:var(--dsw-alias-label-tertiary);font-size:10px;font-weight:550;letter-spacing:.04em;line-height:22px;overflow:hidden;padding:0 10px;text-overflow:ellipsis;white-space:nowrap}.lbs-right-nav-bottom{border-top:1px solid var(--dsw-alias-border-l1);margin-top:auto;padding-bottom:8px;padding-top:8px}.lbs-right-sidebar[data-expanded=false] .lbs-right-nav{align-items:center;padding-left:8px;padding-right:8px}.lbs-right-sidebar[data-expanded=false] .lbs-right-nav-title{display:none}.lbs-nav-button{appearance:none;background:transparent;border:0;border-radius:9px;color:var(--dsw-alias-label-secondary);cursor:pointer;display:flex;align-items:center;gap:10px;font:inherit;font-size:13px;height:38px;padding:0 10px;text-align:left;transition:background .12s,color .12s;width:100%}.lbs-nav-button:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.lbs-nav-button[data-active=true]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.lbs-right-sidebar[data-expanded=false] .lbs-nav-button{justify-content:center;padding:0;width:36px}.lbs-nav-icon{align-items:center;color:currentColor;display:inline-flex;flex:none;height:18px;justify-content:center;width:18px}.lbs-nav-svg{display:block}.lbs-nav-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-right-spacer{flex:1;min-height:8px}.lbs-right-resizer{cursor:col-resize;position:absolute;bottom:0;left:-5px;top:0;width:10px}.lbs-right-resizer:after{background:var(--dsw-alias-border-l2);content:"";opacity:0;position:absolute;bottom:0;left:4px;top:0;width:1px;transition:opacity .15s}.lbs-right-resizer:hover:after,.lbs-right-sidebar[data-dragging=true] .lbs-right-resizer:after{opacity:1}.lbs-center-page{background:var(--dsw-alias-bg-base);box-sizing:border-box;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;pointer-events:auto;position:absolute;left:var(--lbs-left-column,280px);right:var(--lbs-right-column,56px);top:0;bottom:0}.lbs-center-bar{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);box-sizing:border-box;display:flex;flex:none;height:56px;justify-content:space-between;padding:0 clamp(16px,2.4vw,32px)}.lbs-center-crumb{align-items:center;display:flex;gap:9px}.lbs-center-crumb-icon{align-items:center;color:var(--dsw-alias-label-secondary);display:flex;height:20px;justify-content:center;width:20px}.lbs-center-crumb-title{font-size:15px;font-weight:600}.lbs-center-close{appearance:none;background:transparent;border:0;border-radius:8px;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;font-size:12px;height:32px;padding:0 10px}.lbs-center-close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.lbs-center-scroll{box-sizing:border-box;flex:1;min-height:0;overflow:auto;padding:22px clamp(16px,3vw,40px) 32px}.lbs-center-content{margin:0 auto;max-width:1180px}.lbs-settings-actions{display:flex;flex-wrap:wrap;gap:8px}.lbs-settings-note{margin-top:2px}.lbs-upload-options{display:flex;flex-direction:column;gap:8px;margin-top:10px}.lbs-upload-option{align-items:flex-start;border:1px solid var(--dsw-alias-line-border);border-radius:10px;cursor:pointer;display:flex;gap:9px;padding:11px 12px}.lbs-upload-option:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-upload-option input{accent-color:var(--dsw-alias-brand-primary);margin-top:3px}.lbs-upload-option-title{font-size:13px;font-weight:550;line-height:19px}.lbs-upload-option-path{color:var(--dsw-alias-label-tertiary);font:11px/18px ui-monospace,SFMono-Regular,Menlo,monospace;overflow-wrap:anywhere} .lbs-toggle-icon{display:block;transform:scaleX(-1)}.lbs-nav-icon{background:transparent;border:0;height:18px;width:18px}.lbs-right-sidebar[data-expanded=false] .lbs-nav-icon{height:18px;width:18px} .lbs-settings-grid{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(260px,.75fr);gap:16px}.lbs-settings-section{padding:2px 0}.lbs-settings-list{display:flex;flex-direction:column;gap:0}.lbs-settings-row{appearance:none;background:transparent;border:0;border-bottom:1px solid var(--dsw-alias-line-border);border-radius:8px;color:inherit;cursor:pointer;display:flex;align-items:center;gap:10px;padding:9px 0;text-align:left;width:100%}.lbs-settings-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-settings-row>div:first-child{flex:1;min-width:0}.lbs-settings-row:last-child{border-bottom:0}.lbs-settings-row-arrow{color:var(--dsw-alias-label-tertiary);display:flex;flex:none}@media(max-width:900px){.lbs-settings-grid{grid-template-columns:1fr}} @@ -123,6 +121,7 @@ window.__ModuleLoader__.load({ .lbs-knowledge-modal{border-radius:13px}.lbs-knowledge-modal-head{padding:13px 16px}.lbs-knowledge-modal-section{padding:16px 18px}.lbs-knowledge-modal-footer{padding:11px 16px}.lbs-knowledge-activity-modal{max-width:700px}.lbs-knowledge-activity-overview{background:var(--dsw-alias-bg-layer-2);border-bottom:1px solid var(--dsw-alias-line-border);display:grid;grid-template-columns:repeat(3,1fr);padding:14px 18px}.lbs-knowledge-activity-stat{display:flex;flex-direction:column;gap:1px}.lbs-knowledge-activity-stat+.lbs-knowledge-activity-stat{border-left:1px solid var(--dsw-alias-line-border);padding-left:18px}.lbs-knowledge-activity-stat strong{font-size:16px;font-weight:600;line-height:23px}.lbs-knowledge-activity-stat span{color:var(--dsw-alias-label-tertiary);font-size:10px}.lbs-knowledge-activity-note{background:rgba(92,117,255,.07);border-bottom:1px solid var(--dsw-alias-line-border);color:var(--dsw-alias-label-secondary);font-size:11px;line-height:18px;padding:10px 18px}.lbs-knowledge-activity-section{padding:15px 18px 18px}.lbs-knowledge-activity-heading{align-items:center;display:flex;justify-content:space-between;margin-bottom:9px}.lbs-knowledge-timeline{display:flex;flex-direction:column}.lbs-knowledge-timeline-item{align-items:center;display:grid;grid-template-columns:15px 30px minmax(0,1fr) 106px;min-height:54px}.lbs-knowledge-timeline-rail{align-self:stretch;position:relative}.lbs-knowledge-timeline-rail:before{background:var(--dsw-alias-line-border);bottom:0;content:"";left:7px;position:absolute;top:0;width:1px}.lbs-knowledge-timeline-rail>span{background:var(--dsw-alias-brand-primary);border:3px solid var(--dsw-alias-bg-layer-1);border-radius:50%;height:7px;left:4px;position:absolute;top:23px;width:7px;z-index:1}.lbs-knowledge-timeline-icon{align-items:center;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-line-border);border-radius:7px;color:var(--dsw-alias-label-secondary);display:flex;height:26px;justify-content:center;width:26px}.lbs-knowledge-timeline-copy{min-width:0;padding:6px 10px}.lbs-knowledge-timeline-copy>*{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-knowledge-timeline-item time{color:var(--dsw-alias-label-tertiary);font-size:10px;text-align:right;white-space:nowrap}.lbs-knowledge-activity-loading,.lbs-knowledge-activity-empty{align-items:center;color:var(--dsw-alias-label-tertiary);display:flex;font-size:11px;gap:8px;justify-content:center;min-height:110px}.lbs-knowledge-activity-empty{border:1px dashed var(--dsw-alias-line-border);border-radius:9px} @media(max-width:760px){.lbs-knowledge-toolbar{grid-template-columns:minmax(0,1fr) auto 30px}.lbs-knowledge-search{grid-column:1/-1}.lbs-knowledge-toolbar-count{justify-self:end}.lbs-knowledge-table{min-width:0}.lbs-knowledge-table-head,.lbs-knowledge-row{grid-template-columns:minmax(0,1fr) 96px 108px}.lbs-knowledge-table-head>span:nth-child(2),.lbs-knowledge-table-head>span:nth-child(4),.lbs-knowledge-table-head>span:nth-child(5),.lbs-knowledge-table-head>span:nth-child(6),.lbs-knowledge-row>.lbs-knowledge-cell:nth-child(2),.lbs-knowledge-row>.lbs-knowledge-cell:nth-child(4),.lbs-knowledge-row>.lbs-knowledge-cell:nth-child(5),.lbs-knowledge-row>.lbs-knowledge-cell:nth-child(6){display:none}.lbs-knowledge-head-summary span{display:none}.lbs-knowledge-timeline-item{grid-template-columns:15px 30px minmax(0,1fr)}.lbs-knowledge-timeline-item time{grid-column:3;padding:0 10px 7px;text-align:left}.lbs-knowledge-modal-head .lbs-badge{display:none}} @media(max-width:600px){.lbs-knowledge-toolbar{grid-template-columns:minmax(0,1fr) 30px}.lbs-knowledge-filters{overflow:auto}.lbs-knowledge-toolbar-count{display:none}.lbs-knowledge-table-head,.lbs-knowledge-row{grid-template-columns:minmax(0,1fr) 100px}.lbs-knowledge-table-head>span:nth-child(3),.lbs-knowledge-row>.lbs-knowledge-cell:nth-child(3){display:none}.lbs-knowledge-activity-overview{grid-template-columns:repeat(3,1fr);padding:12px 14px}.lbs-knowledge-activity-stat+.lbs-knowledge-activity-stat{padding-left:10px}.lbs-knowledge-activity-note,.lbs-knowledge-activity-section{padding-left:14px;padding-right:14px}.lbs-knowledge-activity-modal .lbs-knowledge-modal-footer>.lbs-meta{display:none}} + .lbs-knowledge-image-thumb{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-line-border);border-radius:7px;height:28px;object-fit:cover;width:28px}.lbs-knowledge-image-grid{display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(132px,1fr));margin-top:2px}.lbs-knowledge-image-card{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-line-border);border-radius:9px;display:flex;flex-direction:column;min-width:0;overflow:hidden}.lbs-knowledge-image-card img{aspect-ratio:16/10;background:var(--dsw-alias-bg-layer-2);display:block;object-fit:contain;width:100%}.lbs-knowledge-image-card span{color:var(--dsw-alias-label-tertiary);font:9px/24px ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden;padding:0 7px;text-overflow:ellipsis;white-space:nowrap}.lbs-retrieval-images{display:flex;gap:6px;margin-top:8px}.lbs-retrieval-images img{border:1px solid var(--dsw-alias-line-border);border-radius:6px;height:54px;object-fit:cover;width:76px}.lbs-knowledge-document-has-images{align-items:center;color:#6f8cff;display:inline-flex;gap:3px} @media(min-width:761px){.lbs-knowledge-table{min-width:780px}.lbs-knowledge-table-head,.lbs-knowledge-row{grid-template-columns:minmax(220px,1fr) 78px 94px 62px 62px 124px 126px}} .lbs-knowledge-modal .lbs-button{border:1px solid transparent;transition:background .12s,border-color .12s,filter .12s}.lbs-knowledge-modal .lbs-button:not(.secondary):not(.danger){background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-base)}.lbs-knowledge-modal .lbs-button:not(.secondary):not(.danger):hover{filter:brightness(.92)}.lbs-knowledge-modal .lbs-button.secondary{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-line-border);color:var(--dsw-alias-label-primary)}.lbs-knowledge-modal .lbs-button.secondary:hover{background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-line-border-hover)}.lbs-knowledge-modal .lbs-button:disabled{filter:none;opacity:.42} @media(max-width:720px){.lbs-grid,.lbs-split{grid-template-columns:1fr}.lbs-panel{min-height:auto}} @@ -196,17 +195,24 @@ window.__ModuleLoader__.load({ conversation: Primitives.IconNewChatOutline16, files: Primitives.IconFolderOpenOutline16, git: Primitives.IconBranchOutline16, - workflows: Primitives.IconChecklistOutline14, knowledge: Primitives.IconDataOutline16, skills: Primitives.IconSkillOutline16, - mcp: Primitives.IconApiOutline14, - terminal: Primitives.IconCodeOutline16, + mcp: Primitives.IconCodeOutline16, + terminal: Primitives.IconApiOutline14, browser: Primitives.IconBrowseOutline16, ssh: Primitives.IconLinkOutline16, apps: Primitives.IconCordisPluginOutline14, settings: Primitives.IconSettingsOutline16, }; const ProjectNavIcon = ({ id }) => { + if (id === "trajectory") { + return h("svg", { className: "lbs-nav-svg", viewBox: "0 0 16 16", width: 16, height: 16, fill: "none", stroke: "currentColor", strokeWidth: 1.35, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, focusable: "false" }, + h("circle", { cx: 3.5, cy: 3, r: 1.25 }), + h("circle", { cx: 12.5, cy: 8, r: 1.25 }), + h("circle", { cx: 3.5, cy: 13, r: 1.25 }), + h("path", { d: "M4.75 3h1.5a6.25 6.25 0 0 1 6.25 5M11.25 8h-1.5a6.25 6.25 0 0 0-6.25 5" }), + ); + } const Icon = projectIcons[id] || Primitives.IconFolderOpenOutline16; return h(Icon, { size: 16, className: "lbs-nav-svg" }); }; @@ -218,9 +224,6 @@ window.__ModuleLoader__.load({ activity: [h("path", { key: "a", d: "M3 12a9 9 0 1 0 3-6.7" }), h("path", { key: "b", d: "M3 4v5h5" }), h("path", { key: "c", d: "M12 7v5l3 2" })], refresh: [h("path", { key: "a", d: "M20 6v5h-5" }), h("path", { key: "b", d: "M4 18v-5h5" }), h("path", { key: "c", d: "M18.4 9A7 7 0 0 0 6.7 6.7L4 9" }), h("path", { key: "d", d: "M5.6 15A7 7 0 0 0 17.3 17.3L20 15" })], search: [h("circle", { key: "a", cx: 11, cy: 11, r: 7 }), h("path", { key: "b", d: "m20 20-4-4" })], - eye: [h("path", { key: "a", d: "M2.5 12s3.5-6 9.5-6 9.5 6 9.5 6-3.5 6-9.5 6-9.5-6-9.5-6Z" }), h("circle", { key: "b", cx: 12, cy: 12, r: 2.5 })], - power: [h("path", { key: "a", d: "M12 2v10" }), h("path", { key: "b", d: "M6.3 5.7a8 8 0 1 0 11.4 0" })], - workflow: [h("rect", { key: "a", x: 3, y: 4, width: 7, height: 5, rx: 1 }), h("rect", { key: "b", x: 14, y: 15, width: 7, height: 5, rx: 1 }), h("path", { key: "c", d: "M10 6.5h2a4 4 0 0 1 4 4V15" }), h("path", { key: "d", d: "m13.5 12.5 2.5 2.5 2.5-2.5" })], trash: [h("path", { key: "a", d: "M3 6h18" }), h("path", { key: "b", d: "M8 6V4h8v2" }), h("path", { key: "c", d: "m19 6-1 15H6L5 6" }), h("path", { key: "d", d: "M10 11v5M14 11v5" })], close: [h("path", { key: "a", d: "m6 6 12 12" }), h("path", { key: "b", d: "M18 6 6 18" })], document: [h("path", { key: "a", d: "M6 3h8l4 4v14H6Z" }), h("path", { key: "b", d: "M14 3v5h5" }), h("path", { key: "c", d: "M9 13h6M9 17h6" })], @@ -250,7 +253,6 @@ window.__ModuleLoader__.load({ const workbenchNavigation = [ { id: "files", label: "文件管理器", icon: "文" }, { id: "git", label: "版本中心", icon: "G" }, - { id: "workflows", label: "工作流", icon: "流" }, { id: "knowledge", label: "知识库", icon: "知" }, ]; const integrationNavigation = [ @@ -398,10 +400,12 @@ window.__ModuleLoader__.load({ const [name, setName] = useState(""); const [description, setDescription] = useState(""); const [agentEnabled, setAgentEnabled] = useState(false); + const [documentEditorOpen, setDocumentEditorOpen] = useState(false); const [documentId, setDocumentId] = useState(""); const [documentRevision, setDocumentRevision] = useState(""); const [documentTitle, setDocumentTitle] = useState(""); const [documentSource, setDocumentSource] = useState(""); + const [documentImageUrls, setDocumentImageUrls] = useState(""); const [documentContent, setDocumentContent] = useState(""); const [searchQuery, setSearchQuery] = useState(""); const [searchResults, setSearchResults] = useState([]); @@ -419,11 +423,12 @@ window.__ModuleLoader__.load({ }); }, [collectionFilter, collectionQuery, collections]); const collectionTotals = useMemo(() => collections.reduce((total, item) => ({ documents: total.documents + Number(item.documentCount || 0), chunks: total.chunks + Number(item.chunkCount || 0) }), { documents: 0, chunks: 0 }), [collections]); + const parsedDocumentImageUrls = useMemo(() => [...new Set(documentImageUrls.split(/\r?\n/u).map((value) => value.trim()).filter(Boolean))].slice(0, 12), [documentImageUrls]); const activityEntries = useMemo(() => { if (!activityCollection) return []; return [ { id: `collection-${activityCollection.id}`, type: "collection", title: "知识库配置最近更新", description: `${activityCollection.agentEnabled ? "可召回" : "已暂停"} · ${activityCollection.scope === "workspace" ? "当前项目" : "全局"}`, updatedAt: activityCollection.updatedAt }, - ...activityDocuments.map((document) => ({ id: document.id, type: "document", title: document.title, description: `${document.chunkCount} 个片段 · ${document.contentLength} 字符${document.source ? ` · ${document.source}` : ""}`, updatedAt: document.updatedAt })), + ...activityDocuments.map((document) => ({ id: document.id, type: "document", title: document.title, description: `${document.chunkCount} 个片段 · ${document.contentLength} 字符${document.imageUrls?.length ? ` · ${document.imageUrls.length} 张图片` : ""}${document.source ? ` · ${document.source}` : ""}`, updatedAt: document.updatedAt })), ].sort((left, right) => Number(new Date(right.updatedAt || 0)) - Number(new Date(left.updatedAt || 0))); }, [activityCollection, activityDocuments]); @@ -504,19 +509,24 @@ window.__ModuleLoader__.load({ setSelectedId(""); setActivityId(collection.id); setMessage(""); setError(""); } function cancelDocumentEdit() { - setDocumentId(""); setDocumentRevision(""); setDocumentTitle(""); setDocumentSource(""); setDocumentContent(""); + setDocumentEditorOpen(false); setDocumentId(""); setDocumentRevision(""); setDocumentTitle(""); setDocumentSource(""); setDocumentImageUrls(""); setDocumentContent(""); + } + function createDocument() { + cancelDocumentEdit(); + setDocumentEditorOpen(true); } async function editDocument(document) { try { const detail = await request(`/knowledge/documents/${encodeURIComponent(document.id)}`); + setDocumentEditorOpen(true); setDocumentId(detail.id); setDocumentRevision(detail.revision); setDocumentTitle(detail.title); - setDocumentSource(detail.source || ""); setDocumentContent(detail.content); setMessage(""); setError(""); + setDocumentSource(detail.source || ""); setDocumentImageUrls((detail.imageUrls || []).join("\n")); setDocumentContent(detail.content); setMessage(""); setError(""); } catch (reason) { setError(reason.message); } } async function saveDocument() { if (!selected) return; try { - await request("/knowledge/documents", { method: "POST", body: JSON.stringify({ id: documentId, expectedRevision: documentRevision, collectionId: selected.id, title: documentTitle, source: documentSource, content: documentContent }) }); + await request("/knowledge/documents", { method: "POST", body: JSON.stringify({ id: documentId || undefined, expectedRevision: documentRevision || undefined, collectionId: selected.id, title: documentTitle, source: documentSource, imageUrls: parsedDocumentImageUrls, content: documentContent }) }); cancelDocumentEdit(); await load(selected.id); setMessage("知识内容已更新并重新建立索引。"); setError(""); } catch (reason) { setError(reason.message); } } @@ -614,18 +624,21 @@ window.__ModuleLoader__.load({ searchResults.length ? h("div", { className: "lbs-retrieval-results" }, searchResults.map((result, index) => h("article", { key: `${result.chunkId || result.documentId}-${index}`, className: "lbs-retrieval-result" }, h("div", { className: "lbs-between" }, h("div", null, h("div", { className: "lbs-card-title" }, result.title), h("div", { className: "lbs-meta" }, result.source || `片段 ${Number(result.ordinal || 0) + 1}`)), h("span", { className: "lbs-relevance", "data-level": relevanceLabel(result.score) }, relevanceLabel(result.score))), h("p", { className: "lbs-retrieval-snippet" }, result.content), + result.imageUrls?.length ? h("div", { className: "lbs-retrieval-images" }, result.imageUrls.slice(0, 4).map((url, imageIndex) => h("img", { key: `${url}:${imageIndex}`, src: url, alt: `${result.title} 图片 ${imageIndex + 1}`, loading: "lazy", referrerPolicy: "no-referrer" }))) : null, ))) : null, ), h("section", { className: "lbs-knowledge-modal-section" }, - h("div", { className: "lbs-knowledge-modal-section-head" }, h("div", null, h("div", { className: "lbs-knowledge-modal-section-title" }, "资料"), h("div", { className: "lbs-meta" }, "Agent 写入后会自动切片并建立本地索引。")), h("span", { className: "lbs-meta" }, "自动同步")), + h("div", { className: "lbs-knowledge-modal-section-head" }, h("div", null, h("div", { className: "lbs-knowledge-modal-section-title" }, "资料"), h("div", { className: "lbs-meta" }, "正文会建立本地索引,HTTP(S) 图片 URL 会安全渲染。")), h(Button, { secondary: true, onClick: createDocument }, "添加资料")), h("div", { className: "lbs-knowledge-documents" }, documents.length ? documents.map((document) => h("article", { key: document.id, className: "lbs-knowledge-document" }, - h("span", { className: "lbs-knowledge-document-icon" }, h(LineIcon, { name: "document", size: 15 })), - h("div", { className: "lbs-knowledge-document-copy" }, h("div", { className: "lbs-card-title" }, document.title), h("div", { className: "lbs-meta" }, `${document.chunkCount} 个片段 · ${document.contentLength} 字符${document.source ? ` · ${document.source}` : ""}`)), + document.imageUrls?.[0] ? h("img", { className: "lbs-knowledge-image-thumb", src: document.imageUrls[0], alt: "", loading: "lazy", referrerPolicy: "no-referrer" }) : h("span", { className: "lbs-knowledge-document-icon" }, h(LineIcon, { name: "document", size: 15 })), + h("div", { className: "lbs-knowledge-document-copy" }, h("div", { className: "lbs-card-title" }, document.title), h("div", { className: "lbs-meta" }, `${document.chunkCount} 个片段 · ${document.contentLength} 字符${document.imageUrls?.length ? ` · ${document.imageUrls.length} 张图片` : ""}${document.source ? ` · ${document.source}` : ""}`)), h("div", { className: "lbs-knowledge-document-actions" }, h("button", { type: "button", className: "lbs-icon-action", onClick: () => editDocument(document), title: "编辑资料", "aria-label": `编辑资料 ${document.title}` }, h(LineIcon, { name: "edit" })), h("button", { type: "button", className: "lbs-icon-action danger", onClick: () => removeDocument(document), title: "删除资料", "aria-label": `删除资料 ${document.title}` }, h(LineIcon, { name: "trash" }))), )) : h("div", { className: "lbs-help" }, "暂无资料。你可以在对话中让 Agent 记住重要信息。")), - documentId ? h("div", { className: "lbs-knowledge-editor" }, - h("div", { className: "lbs-between" }, h("div", { className: "lbs-card-title" }, "编辑资料"), h("button", { type: "button", className: "lbs-icon-action", onClick: cancelDocumentEdit, title: "收起", "aria-label": "收起资料编辑" }, h(LineIcon, { name: "close" }))), + documentEditorOpen ? h("div", { className: "lbs-knowledge-editor" }, + h("div", { className: "lbs-between" }, h("div", { className: "lbs-card-title" }, documentId ? "编辑资料" : "添加资料"), h("button", { type: "button", className: "lbs-icon-action", onClick: cancelDocumentEdit, title: "收起", "aria-label": "收起资料编辑" }, h(LineIcon, { name: "close" }))), h("div", { className: "lbs-split" }, h(Field, { label: "标题", value: documentTitle, onChange: (event) => setDocumentTitle(event.target.value) }), h(Field, { label: "来源", value: documentSource, onChange: (event) => setDocumentSource(event.target.value) })), + h(Field, { label: "图片 URL(每行一个,最多 12 个,仅支持 HTTP/HTTPS)", area: true, code: true, value: documentImageUrls, onChange: (event) => setDocumentImageUrls(event.target.value), placeholder: "https://example.com/image.png" }), + parsedDocumentImageUrls.length ? h("div", { className: "lbs-knowledge-image-grid", "aria-label": "图片预览" }, parsedDocumentImageUrls.map((url, imageIndex) => h("div", { className: "lbs-knowledge-image-card", key: `${url}:${imageIndex}` }, h("img", { src: url, alt: `${documentTitle || "知识资料"} 图片 ${imageIndex + 1}`, loading: "lazy", referrerPolicy: "no-referrer" }), h("span", { title: url }, url)))) : null, h(Field, { label: "正文", area: true, code: true, value: documentContent, onChange: (event) => setDocumentContent(event.target.value) }), h(Button, { onClick: saveDocument, disabled: !documentTitle.trim() || !documentContent.trim() }, "保存并重新索引"), ) : null, @@ -678,341 +691,6 @@ window.__ModuleLoader__.load({ ); } - function WorkflowGraph({ definition, selectedNodeId, onSelectNode }) { - const graph = useMemo(() => { - const nodes = definition?.nodes || []; - if (!nodes.length) return null; - const minX = Math.min(...nodes.map((node) => node.position?.x || 0)); - const minY = Math.min(...nodes.map((node) => node.position?.y || 0)); - const maxX = Math.max(...nodes.map((node) => node.position?.x || 0)); - const maxY = Math.max(...nodes.map((node) => node.position?.y || 0)); - const width = Math.max(500, maxX - minX + 220), height = Math.max(260, maxY - minY + 140); - const positions = Object.fromEntries(nodes.map((node) => [node.id, { x: (node.position?.x || 0) - minX + 20, y: (node.position?.y || 0) - minY + 30 }])); - return { nodes, edges: definition.edges || [], positions, width, height }; - }, [definition]); - if (!graph) return h("div", { className: "lbs-empty" }, "没有可视化节点"); - return h("svg", { className: "lbs-svg", viewBox: `0 0 ${graph.width} ${graph.height}`, preserveAspectRatio: "xMidYMid meet" }, - h("defs", null, h("marker", { id: "lbs-arrow", markerWidth: 8, markerHeight: 8, refX: 7, refY: 4, orient: "auto" }, h("path", { d: "M0,0 L8,4 L0,8 Z", fill: "var(--dsw-alias-label-tertiary)" }))), - graph.edges.map((edge) => { const a = graph.positions[edge.source], b = graph.positions[edge.target]; return a && b ? h("path", { key: edge.id, className: "lbs-edge", markerEnd: "url(#lbs-arrow)", d: `M${a.x + 150},${a.y + 30} C${a.x + 190},${a.y + 30} ${b.x - 40},${b.y + 30} ${b.x},${b.y + 30}` }) : null; }), - graph.nodes.map((node) => { - const p = graph.positions[node.id]; - const selectable = typeof onSelectNode === "function"; - return h("g", { - key: node.id, - className: "lbs-node-group", - transform: `translate(${p.x} ${p.y})`, - "data-selectable": selectable, - "data-selected": node.id === selectedNodeId, - role: selectable ? "button" : undefined, - tabIndex: selectable ? 0 : undefined, - onClick: selectable ? () => onSelectNode(node) : undefined, - onKeyDown: selectable ? (event) => { if (["Enter", " "].includes(event.key)) onSelectNode(node); } : undefined, - }, h("rect", { className: "lbs-node", width: 150, height: 60, rx: 10 }), h("text", { className: "lbs-node-title", x: 12, y: 25 }, node.label || node.id), h("text", { className: "lbs-node-type", x: 12, y: 44 }, node.type)); - }), - ); - } - - function WorkflowsSection() { - const [workflows, setWorkflows] = useState([]); - const [selectedId, setSelectedId] = useState(""); - const [dialogMode, setDialogMode] = useState("view"); - const [loading, setLoading] = useState(true); - const [refreshing, setRefreshing] = useState(false); - const [name, setName] = useState(""); const [description, setDescription] = useState(""); const [toolName, setToolName] = useState(""); - const [definition, setDefinition] = useState(null); - const [selectedNodeId, setSelectedNodeId] = useState(""); - const [nodeLabel, setNodeLabel] = useState(""); - const [nodeConfigText, setNodeConfigText] = useState("{}"); - const [runInput, setRunInput] = useState('{"message":"你好","count":2}'); - const [message, setMessage] = useState(""); const [error, setError] = useState(""); - const selected = workflows.find((item) => item.id === selectedId); - const selectedNode = definition?.nodes.find((node) => node.id === selectedNodeId); - const load = useCallback(async (preferred, background = false) => { - if (background) setRefreshing(true); - try { - const next = await request("/workflows"); - setWorkflows(next); - setSelectedId((current) => { - const candidate = preferred || current; - return candidate && next.some((item) => item.id === candidate) ? candidate : ""; - }); - setError(""); - } catch (reason) { setError(reason.message); } - finally { setLoading(false); setRefreshing(false); } - }, []); - useEffect(() => { load(); }, [load]); - useEffect(() => { - if (!selected) return; - setName(selected.name); setDescription(selected.description); setToolName(selected.toolName); - setDefinition(selected.definition); - loadNodeEditor(selected.definition.nodes[0]); - }, [selectedId, selected?.revision]); - - function loadNodeEditor(node) { - if (!node) { setSelectedNodeId(""); setNodeLabel(""); setNodeConfigText("{}"); return; } - const config = { ...node }; - delete config.id; delete config.type; delete config.label; - setSelectedNodeId(node.id); - setNodeLabel(node.label || ""); - setNodeConfigText(JSON.stringify(config, null, 2)); - } - - function openWorkflow(workflow, mode) { - setDialogMode(mode); - setSelectedId(workflow.id); - setMessage(""); - setError(""); - } - - function closeWorkflow() { - setSelectedId(""); - setMessage(""); - setError(""); - } - - function selectNode(node) { - try { - const nextDefinition = editedDefinition(); - const nextNode = nextDefinition?.nodes.find((item) => item.id === node.id) || node; - setDefinition(nextDefinition); - loadNodeEditor(nextNode); - setError(""); - } catch (reason) { - setError(`请先修正当前节点参数:${reason.message}`); - } - } - - function editedDefinition() { - if (!selectedNode || !definition) return definition; - const config = JSON.parse(nodeConfigText); - if (!config || typeof config !== "object" || Array.isArray(config)) throw new Error("节点参数必须是 JSON 对象。"); - delete config.id; delete config.type; delete config.label; - return { - ...definition, - nodes: definition.nodes.map((node) => node.id === selectedNode.id ? { - id: node.id, - type: node.type, - ...(nodeLabel.trim() ? { label: nodeLabel.trim() } : {}), - ...config, - } : node), - }; - } - - async function save(notify = true) { - try { - const nextDefinition = editedDefinition(); - const saved = await request("/workflows", { method: "POST", body: JSON.stringify({ id: selected.id, expectedRevision: selected.revision, name, description, toolName, definition: nextDefinition }) }); - setDefinition(nextDefinition); - await load(saved.id); - if (notify) setMessage("工作流微调已保存。"); - setError(""); - return saved; - } catch (reason) { - setError(reason.message); - return null; - } - } - async function publish() { - try { - const saved = await save(false); - if (!saved) return; - const value = await request(`/workflows/${encodeURIComponent(saved.id)}/publish`, { method: "POST", body: JSON.stringify({ expectedRevision: saved.revision }) }); - await load(saved.id); - setMessage(`已发布并${value.enabled ? "启用" : "保持停用"} v${value.version},虚拟插件:${value.toolName}`); - setError(""); - } - catch (reason) { setError(reason.message); } - } - async function setEnabled(workflow, enabled) { - try { - const value = await request(`/workflows/${encodeURIComponent(workflow.id)}/enabled`, { method: "POST", body: JSON.stringify({ enabled, expectedRevision: workflow.revision }) }); - await load(selectedId === workflow.id ? value.id : undefined); - setMessage(enabled ? "虚拟工作流插件已启用。" : "虚拟工作流插件已停用,工作流和版本仍然保留。"); - setError(""); - } catch (reason) { setError(reason.message); } - } - async function run() { - try { - const input = JSON.parse(runInput); - const saved = await save(false); - if (!saved) return; - const value = await request(`/workflows/${encodeURIComponent(saved.id)}/run`, { method: "POST", body: JSON.stringify({ input }) }); - setMessage(JSON.stringify(value.output, null, 2)); - setError(""); - } - catch (reason) { setError(reason.message); } - } - async function remove(workflow = selected) { - if (!workflow || !confirm(`删除工作流“${workflow.name}”?对应的虚拟插件和全部发布版本也会删除。`)) return; - try { await request(`/workflows/${encodeURIComponent(workflow.id)}?revision=${encodeURIComponent(workflow.revision)}`, { method: "DELETE" }); setSelectedId(""); await load(); setMessage("工作流及虚拟插件已删除。"); } - catch (reason) { setError(reason.message); } - } - - function formatUpdatedAt(value) { - if (!value) return "—"; - try { return new Intl.DateTimeFormat("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" }).format(new Date(value)); } - catch { return "—"; } - } - - return h("div", { className: "lbs-page lbs-workflow-page" }, - h(PageHeader, { title: "工作流", subtitle: "Agent 负责创建和维护;你可以从列表查看、编辑、启停或删除。", action: h("div", { className: "lbs-row" }, h("span", { className: "lbs-meta" }, `${workflows.length} 个工作流 · ${workflows.filter((item) => item.enabled).length} 个已启用`), h("button", { type: "button", className: classNames("lbs-icon-action", refreshing && "is-spinning"), onClick: () => load(undefined, true), title: "刷新列表", "aria-label": "刷新工作流列表", disabled: refreshing }, h(LineIcon, { name: "refresh" }))) }), - h(Status, { error: true, message: error }), h(Status, { message }), - h("section", { className: "lbs-panel lbs-workflow-list-panel" }, - loading ? h("div", { className: "lbs-knowledge-list-empty compact" }, h("span", { className: "lbs-knowledge-loading" }), h("div", null, h("div", { className: "lbs-card-title" }, "正在加载工作流"), h("div", { className: "lbs-meta" }, "正在同步 Agent 自动化状态…"))) - : workflows.length ? h("div", { className: "lbs-workflow-table-scroll" }, - h("div", { className: "lbs-workflow-table", role: "table", "aria-label": "工作流列表" }, - h("div", { className: "lbs-workflow-table-head", role: "row" }, - h("span", { role: "columnheader" }, "工作流"), h("span", { role: "columnheader" }, "Agent 工具"), h("span", { role: "columnheader" }, "状态"), h("span", { role: "columnheader" }, "节点"), h("span", { role: "columnheader" }, "最近更新"), h("span", { role: "columnheader" }, "操作"), - ), - workflows.map((item) => h("article", { key: item.id, className: "lbs-workflow-row", role: "row" }, - h("div", { className: "lbs-workflow-cell lbs-workflow-primary", role: "cell" }, - h("button", { type: "button", className: "lbs-workflow-primary-button", onClick: () => openWorkflow(item, "view"), title: `查看 ${item.name}` }, h("span", { className: "lbs-workflow-list-icon" }, h(LineIcon, { name: "workflow", size: 16 })), h("span", { className: "lbs-workflow-row-copy" }, h("span", { className: "lbs-card-title" }, item.name), h("span", { className: "lbs-meta" }, item.description || "Agent 创建的可复用自动化"))), - ), - h("code", { className: "lbs-workflow-cell lbs-workflow-tool-name", role: "cell", title: item.toolName }, item.toolName), - h("div", { className: "lbs-workflow-cell", role: "cell" }, h("span", { className: "lbs-workflow-list-status", "data-enabled": item.enabled }, h("span", null), item.publishedVersion ? (item.enabled ? `已启用 v${item.publishedVersion}` : `已停用 v${item.publishedVersion}`) : "草稿")), - h("div", { className: "lbs-workflow-cell", role: "cell" }, String(item.definition.nodes.length)), - h("time", { className: "lbs-workflow-cell", role: "cell", dateTime: item.updatedAt || undefined }, formatUpdatedAt(item.updatedAt)), - h("div", { className: "lbs-workflow-cell lbs-workflow-list-actions", role: "cell" }, - h("button", { type: "button", className: "lbs-icon-action", onClick: () => openWorkflow(item, "view"), title: "查看", "aria-label": `查看 ${item.name}` }, h(LineIcon, { name: "eye" })), - h("button", { type: "button", className: "lbs-icon-action", onClick: () => openWorkflow(item, "edit"), title: "编辑", "aria-label": `编辑 ${item.name}` }, h(LineIcon, { name: "edit" })), - item.publishedVersion ? h("button", { type: "button", className: "lbs-icon-action", onClick: () => setEnabled(item, !item.enabled), title: item.enabled ? "停用" : "启用", "aria-label": `${item.enabled ? "停用" : "启用"} ${item.name}` }, h(LineIcon, { name: "power" })) : null, - h("button", { type: "button", className: "lbs-icon-action danger", onClick: () => remove(item), title: "删除", "aria-label": `删除 ${item.name}` }, h(LineIcon, { name: "trash" })), - ), - )), - ), - ) : h("div", { className: "lbs-knowledge-list-empty" }, h("span", { className: "lbs-workflow-list-icon" }, h(LineIcon, { name: "workflow", size: 19 })), h("div", null, h("div", { className: "lbs-card-title" }, "暂无工作流"), h("div", { className: "lbs-meta" }, "直接在对话中让 Agent 创建一个可复用流程。"))), - ), - selected ? h("div", { className: "lbs-knowledge-modal-layer" }, - h("button", { type: "button", className: "lbs-knowledge-modal-backdrop", onClick: closeWorkflow, "aria-label": "关闭工作流窗口" }), - h("section", { className: "lbs-knowledge-modal lbs-workflow-modal", role: "dialog", "aria-modal": true, "aria-labelledby": "lbs-workflow-modal-title" }, - h("header", { className: "lbs-knowledge-modal-head" }, - h("span", { className: "lbs-workflow-list-icon" }, h(LineIcon, { name: "workflow", size: 17 })), - h("div", { className: "lbs-knowledge-modal-head-copy" }, h("div", { id: "lbs-workflow-modal-title", className: "lbs-knowledge-modal-title" }, selected.name), h("div", { className: "lbs-meta" }, dialogMode === "edit" ? "编辑工作流信息和节点参数" : "查看工作流结构和发布状态")), - h("span", { className: "lbs-badge" }, dialogMode === "edit" ? "编辑" : "查看"), - h("button", { type: "button", className: "lbs-icon-action", onClick: closeWorkflow, title: "关闭", "aria-label": "关闭" }, h(LineIcon, { name: "close", size: 18 })), - ), - h("div", { className: "lbs-knowledge-modal-scroll" }, - error || message ? h("div", { className: "lbs-knowledge-modal-feedback" }, h(Status, { error: true, message: error }), h(Status, { message })) : null, - h("section", { className: "lbs-knowledge-modal-section" }, - h("div", { className: "lbs-workflow-modal-summary" }, - h("div", { className: "lbs-workflow-summary-item" }, h("strong", null, selected.publishedVersion ? `v${selected.publishedVersion}` : "草稿"), h("span", null, "当前版本")), - h("div", { className: "lbs-workflow-summary-item" }, h("strong", null, selected.publishedVersion ? (selected.enabled ? "已启用" : "已停用") : "未发布"), h("span", null, "插件状态")), - h("div", { className: "lbs-workflow-summary-item" }, h("strong", null, String(selected.definition.nodes.length)), h("span", null, "流程节点")), - h("div", { className: "lbs-workflow-summary-item" }, h("strong", null, String(selected.definition.edges.length)), h("span", null, "节点连线")), - ), - ), - h("section", { className: "lbs-knowledge-modal-section" }, - h("div", null, h("div", { className: "lbs-knowledge-modal-section-title" }, "基础信息"), h("div", { className: "lbs-meta" }, dialogMode === "edit" ? "修改名称、说明和注册给 Agent 的工具名。" : `最近更新:${formatUpdatedAt(selected.updatedAt)}`)), - dialogMode === "edit" ? [ - h("div", { key: "fields", className: "lbs-split" }, h(Field, { label: "名称", value: name, onChange: (event) => setName(event.target.value) }), h(Field, { label: "Agent 工具名", value: toolName, onChange: (event) => setToolName(event.target.value) })), - h(Field, { key: "description", label: "说明", area: true, value: description, onChange: (event) => setDescription(event.target.value) }), - ] : h("div", { className: "lbs-workflow-readonly" }, - h("div", null, h("div", { className: "lbs-label" }, "Agent 工具名"), h("code", { className: "lbs-automation-tool" }, selected.toolName)), - h("div", null, h("div", { className: "lbs-label" }, "说明"), h("div", { className: "lbs-meta" }, selected.description || "暂无说明")), - ), - ), - h("section", { className: "lbs-knowledge-modal-section" }, - h("div", null, h("div", { className: "lbs-knowledge-modal-section-title" }, "流程图"), h("div", { className: "lbs-meta" }, dialogMode === "edit" ? "点击节点可在下方进行微调。" : "工作流结构由 Agent 维护。")), - h(WorkflowGraph, { definition: selectedNode && dialogMode === "edit" ? { ...definition, nodes: definition.nodes.map((node) => node.id === selectedNode.id ? { ...node, ...(nodeLabel.trim() ? { label: nodeLabel.trim() } : {}) } : node) } : selected.definition, selectedNodeId: dialogMode === "edit" ? selectedNodeId : undefined, onSelectNode: dialogMode === "edit" ? selectNode : undefined }), - dialogMode === "edit" && selectedNode ? h("div", { className: "lbs-workflow-node-editor" }, - h("div", { className: "lbs-workflow-node-head" }, h("strong", null, "节点微调"), h("span", { className: "lbs-badge" }, selectedNode.type)), - h("div", { className: "lbs-meta" }, `节点 ID:${selectedNode.id}`), - h(Field, { label: "显示名称", value: nodeLabel, onChange: (event) => setNodeLabel(event.target.value), placeholder: selectedNode.id }), - h(Field, { label: "节点参数", area: true, code: true, value: nodeConfigText, onChange: (event) => setNodeConfigText(event.target.value) }), - ) : null, - ), - dialogMode === "edit" ? h("section", { className: "lbs-knowledge-modal-section" }, - h("div", null, h("div", { className: "lbs-knowledge-modal-section-title" }, "试运行"), h("div", { className: "lbs-meta" }, "保存当前微调后使用下面的 JSON 输入执行一次。")), - h(Field, { label: "输入参数", area: true, code: true, value: runInput, onChange: (event) => setRunInput(event.target.value) }), - h(Button, { secondary: true, onClick: run }, "试运行"), - ) : null, - ), - h("footer", { className: "lbs-knowledge-modal-footer" }, - h(Button, { danger: true, onClick: () => remove(selected) }, "删除工作流"), - dialogMode === "edit" ? h("div", { className: "lbs-knowledge-modal-footer-actions" }, - selected.publishedVersion ? h(Button, { secondary: true, onClick: () => setEnabled(selected, !selected.enabled) }, selected.enabled ? "停用" : "启用") : null, - h(Button, { secondary: true, onClick: closeWorkflow }, "取消"), - h(Button, { secondary: true, onClick: publish }, selected.publishedVersion ? "发布新版本" : "发布并启用"), - h(Button, { onClick: () => save(), disabled: !name.trim() || !toolName.trim() }, "保存修改"), - ) : h("div", { className: "lbs-knowledge-modal-footer-actions" }, h(Button, { secondary: true, onClick: closeWorkflow }, "关闭"), h(Button, { onClick: () => setDialogMode("edit") }, "编辑")), - ), - ), - ) : null, - ); - } - - function WorkflowPluginsTab() { - const [workflows, setWorkflows] = useState([]); - const [selectedId, setSelectedId] = useState(""); - const [message, setMessage] = useState(""); - const [error, setError] = useState(""); - const published = workflows.filter((item) => item.publishedVersion); - const selected = published.find((item) => item.id === selectedId) || published[0]; - const load = useCallback(async (preferred) => { - try { - const next = await request("/workflows"); - const available = next.filter((item) => item.publishedVersion); - setWorkflows(next); - setSelectedId((current) => preferred || (available.some((item) => item.id === current) ? current : available[0]?.id || "")); - setError(""); - } catch (reason) { setError(reason.message); } - }, []); - useEffect(() => { - load(); - const timer = window.setInterval(() => load(), 2_000); - return () => window.clearInterval(timer); - }, [load]); - - async function setEnabled(workflow, enabled) { - try { - const value = await request(`/workflows/${encodeURIComponent(workflow.id)}/enabled`, { - method: "POST", - body: JSON.stringify({ enabled, expectedRevision: workflow.revision }), - }); - await load(value.id); - setMessage(enabled ? `“${workflow.name}”已启用并注册为 Agent 工具。` : `“${workflow.name}”已停用,流程和版本仍然保留。`); - setError(""); - } catch (reason) { setError(reason.message); } - } - - async function remove(workflow) { - if (!confirm(`删除虚拟工作流插件“${workflow.name}”?工作流和全部发布版本会同步删除。`)) return; - try { - await request(`/workflows/${encodeURIComponent(workflow.id)}?revision=${encodeURIComponent(workflow.revision)}`, { method: "DELETE" }); - await load(); - setMessage(`“${workflow.name}”及其虚拟插件已删除。`); - setError(""); - } catch (reason) { setError(reason.message); } - } - - return h("div", { className: "lbs-page" }, - h(PageHeader, { title: "Agent 自动化", subtitle: "已发布工作流会作为虚拟插件统一出现在这里;启停和删除会与工作流页面实时同步。" }), - h(Status, { error: true, message: error }), - h(Status, { message }), - published.length ? h("div", { className: "lbs-grid" }, - h("section", { className: "lbs-panel lbs-automation-list", "aria-label": "虚拟工作流插件列表" }, published.map((workflow) => h("button", { - type: "button", - key: workflow.id, - className: "lbs-automation-card", - "data-active": workflow.id === selected?.id, - onClick: () => setSelectedId(workflow.id), - }, - h("span", { className: "lbs-automation-card-copy" }, h("strong", { className: "lbs-card-title" }, workflow.name), h("small", { className: "lbs-meta" }, `${workflow.toolName} · v${workflow.publishedVersion}`)), - h("span", { className: "lbs-automation-state", "data-enabled": workflow.enabled }, h("span", null), workflow.enabled ? "已启用" : "已停用")))), - selected ? h("section", { className: "lbs-panel lbs-automation-detail" }, - h("div", { className: "lbs-automation-detail-head" }, h("div", null, h("h2", null, selected.name), h("div", { className: "lbs-sub" }, selected.description || "Agent 生成的可复用工作流。")), h("span", { className: "lbs-badge" }, `虚拟插件 · v${selected.publishedVersion}`)), - h("code", { className: "lbs-automation-tool" }, selected.toolName), - h(WorkflowGraph, { definition: selected.definition }), - h("div", { className: "lbs-automation-actions" }, - h(Button, { onClick: () => setEnabled(selected, !selected.enabled) }, selected.enabled ? "停用" : "启用"), - h(Button, { danger: true, onClick: () => remove(selected) }, "删除"), - ), - h("div", { className: "lbs-automation-note" }, `${selected.definition.nodes.length} 个节点 · ${selected.definition.edges.length} 条连线 · 删除后工作流管理页会同步移除`), - ) : null, - ) : h("div", { className: "lbs-empty" }, "还没有已发布的工作流。Agent 创建并发布后,会自动注册到这里。"), - ); - } - function SkillsSection() { const [catalog, setCatalog] = useState({ roots: [], skills: [] }); const [selectedId, setSelectedId] = useState(""); @@ -2422,7 +2100,6 @@ window.__ModuleLoader__.load({ }, [active]); if (active === "conversation") return null; const Page = { - workflows: WorkflowsSection, knowledge: KnowledgeSection, skills: SkillsSection, mcp: McpSection, @@ -2596,7 +2273,16 @@ window.__ModuleLoader__.load({ const assistants = group.nodes.filter( (node) => flowKind(node) === "assistant-step", ); - const finalAnswer = group.completed ? assistants.at(-1) : undefined; + const hasVisibleAnswer = (node) => { + const clone = node.cloneNode(true); + for (const thinking of clone.querySelectorAll("[data-variant=think]")) { + thinking.remove(); + } + return Boolean(clone.textContent?.trim()); + }; + const finalAnswer = group.completed + ? assistants.findLast(hasVisibleAnswer) + : undefined; const preserved = new Set( group.completed ? group.nodes.filter((node) => @@ -3440,12 +3126,6 @@ window.__ModuleLoader__.load({ order: 15, label: () => "文件上传", }, UploadCacheSettingsSection)); - ctx.slots.inject("settings.plugins.tab", () => ctx.slots.register({ - name: "settings.plugins.tab", - id: "laobos-workflow-plugins", - order: 20, - label: () => "Agent 自动化", - }, WorkflowPluginsTab)); } exports.apply = apply; exports.inject = inject; diff --git a/packages/laobos-system-tools/lib/git-service.mjs b/packages/laobos-system-tools/lib/git-service.mjs index 5ebf0f1..9733e7c 100644 --- a/packages/laobos-system-tools/lib/git-service.mjs +++ b/packages/laobos-system-tools/lib/git-service.mjs @@ -1,12 +1,13 @@ import { execFile } from "node:child_process"; import { createHash } from "node:crypto"; -import { realpath } from "node:fs/promises"; +import { access, realpath } from "node:fs/promises"; import path from "node:path"; import { promisify } from "node:util"; const execFileAsync = promisify(execFile); const MAX_BUFFER = 8 * 1024 * 1024; const MAX_PATHS = 200; +let defaultGitExecutable; export class GitServiceError extends Error { constructor(code, message) { @@ -16,6 +17,56 @@ export class GitServiceError extends Error { } } +export function gitExecutableCandidates({ + platform = process.platform, + env = process.env, + resourcesPath = process.resourcesPath, +} = {}) { + const configured = env.LAOBOS_GIT_EXECUTABLE?.trim(); + if (platform !== "win32") return [...new Set([configured, "git"].filter(Boolean))]; + const pathApi = path.win32; + + const programFiles = env.ProgramFiles || env.PROGRAMFILES; + const programFilesX86 = env["ProgramFiles(x86)"] || env.PROGRAMFILES_X86; + const localAppData = env.LOCALAPPDATA + || (env.USERPROFILE && pathApi.join(env.USERPROFILE, "AppData", "Local")); + const installRoots = [ + env.GIT_INSTALL_ROOT, + env.ProgramW6432 && pathApi.join(env.ProgramW6432, "Git"), + programFiles && pathApi.join(programFiles, "Git"), + programFilesX86 && pathApi.join(programFilesX86, "Git"), + localAppData && pathApi.join(localAppData, "Programs", "Git"), + env.USERPROFILE && pathApi.join(env.USERPROFILE, "scoop", "apps", "git", "current"), + resourcesPath && pathApi.join(resourcesPath, "git"), + ].filter(Boolean); + const absoluteCandidates = installRoots.flatMap((root) => [ + pathApi.join(root, "cmd", "git.exe"), + pathApi.join(root, "bin", "git.exe"), + ]); + if (env.ChocolateyInstall) absoluteCandidates.push(pathApi.join(env.ChocolateyInstall, "bin", "git.exe")); + return [...new Set([configured, ...absoluteCandidates, "git"].filter(Boolean))]; +} + +export async function resolveGitExecutable({ + platform = process.platform, + env = process.env, + resourcesPath = process.resourcesPath, + canAccess = access, +} = {}) { + const candidates = gitExecutableCandidates({ platform, env, resourcesPath }); + const pathApi = platform === "win32" ? path.win32 : path; + for (const candidate of candidates) { + if (!pathApi.isAbsolute(candidate)) return candidate; + try { + await canAccess(candidate); + return candidate; + } catch { + // Try the next known Git for Windows installation location. + } + } + return "git"; +} + export async function inspectGit(root) { const context = await resolveRepository(root, { allowMissing: true }); if (!context.repository) { @@ -351,7 +402,9 @@ function isPathInside(root, candidate) { async function runGit(cwd, args, options = {}) { const acceptedExitCodes = options.acceptedExitCodes || [0]; try { - const { stdout, stderr } = await execFileAsync("git", args, { + defaultGitExecutable ||= resolveGitExecutable(); + const gitExecutable = await defaultGitExecutable; + const { stdout, stderr } = await execFileAsync(gitExecutable, args, { cwd, encoding: "utf8", timeout: options.timeout || 20_000, @@ -361,6 +414,12 @@ async function runGit(cwd, args, options = {}) { }); return { stdout, stderr, code: 0 }; } catch (error) { + if (error?.code === "ENOENT") { + throw new GitServiceError( + "GIT_NOT_FOUND", + "未检测到 Git。请安装 Git for Windows,或将 git.exe 加入 PATH;安装后请完全退出并重新打开劳博士。", + ); + } const code = Number(error?.code); if (acceptedExitCodes.includes(code)) return { stdout: String(error?.stdout || ""), stderr: String(error?.stderr || ""), code }; const message = String(error?.stderr || error?.message || error).trim(); diff --git a/packages/laobos-system-tools/lib/index.js b/packages/laobos-system-tools/lib/index.js index 5d0bb99..83e822d 100644 --- a/packages/laobos-system-tools/lib/index.js +++ b/packages/laobos-system-tools/lib/index.js @@ -1,5 +1,4 @@ -import { randomUUID } from "node:crypto"; -import { readFileSync } from "node:fs"; +import { readFileSync, realpathSync, statSync } from "node:fs"; import path from "node:path"; import z from "@deepseek-ai/schemastery"; import { defineTool } from "@deepseek-ai/dsh-tools"; @@ -95,20 +94,6 @@ const jsonOutput = { render: (_args, value) => [{ type: "text", text: JSON.stringify(value, null, 2) }], }; -function fieldSchema(field) { - const base = { ...(field.required ? { required: true } : {}), ...(field.description ? { description: field.description } : {}) }; - if (field.options?.length) return { ...base, type: "string", enum: field.options }; - if (["string", "number", "boolean"].includes(field.type)) return { ...base, type: field.type }; - if (field.type === "array") return { ...base, type: "array" }; - if (field.type === "object" || field.type === "file") return { ...base, type: "object", additionalProperties: true }; - return { ...base, type: "json" }; -} - -function workflowParameters(definition) { - const input = definition.nodes.find((node) => node.type === "input"); - return Object.fromEntries((input?.fields || []).map((field) => [field.name, fieldSchema(field)])); -} - function json(res, status, value) { const body = JSON.stringify(value); res.writeHead(status, { @@ -155,14 +140,23 @@ function errorResponse(res, error) { }); } -function gitWorkspace(workspacePath, exec) { +export function gitWorkspace(workspacePath, exec) { const requested = exec?.agent?.session?.header?.cwd; - const candidate = path.resolve(workspacePath, typeof requested === "string" ? requested : "."); - const relative = path.relative(workspacePath, candidate); - if (relative.startsWith("..") || path.isAbsolute(relative)) { - throw new SystemToolsError("WORKSPACE_BOUNDARY", "当前会话工作区超出劳博士授权范围。", 403); + const candidate = path.resolve( + workspacePath, + typeof requested === "string" && requested.trim() ? requested : ".", + ); + try { + const canonical = realpathSync(candidate); + if (!statSync(canonical).isDirectory()) throw new Error("not a directory"); + return canonical; + } catch { + throw new SystemToolsError( + "WORKSPACE_UNAVAILABLE", + `当前会话工作区不可访问:${candidate}。请确认目录存在且当前 Windows 用户拥有访问权限。`, + 400, + ); } - return candidate; } function isPlanActive(events) { @@ -321,6 +315,7 @@ function manageKnowledge(store, args, workspacePath) { title: args.title || existing?.title, content: args.content ?? existing?.content, source: args.source ?? existing?.source ?? "Agent 对话", + imageUrls: args.imageUrls ?? existing?.imageUrls ?? [], }); } default: @@ -328,57 +323,6 @@ function manageKnowledge(store, args, workspacePath) { } } -async function manageWorkflow(store, args, executionOptions) { - const find = () => store.getWorkflow(requiredArgument(args.workflowId, "工作流 ID")); - const requireRevision = () => { - if (!args.expectedRevision) { - throw new SystemToolsError("REVISION_REQUIRED", "修改工作流前必须先读取并携带当前 revision。", 409); - } - return args.expectedRevision; - }; - switch (args.action) { - case "list_workflows": - return store.listWorkflows(); - case "get_workflow": - return find(); - case "create_workflow": - return store.upsertWorkflow({ - name: requiredArgument(args.name, "工作流名称"), - description: args.description || "由 Agent 创建的可复用自动化流程。", - toolName: requiredArgument(args.toolName, "工作流工具名"), - definition: args.definition, - }); - case "update_workflow": { - const existing = find(); - return store.upsertWorkflow({ - id: existing.id, - expectedRevision: requireRevision(), - name: args.name ?? existing.name, - description: args.description ?? existing.description, - toolName: args.toolName ?? existing.toolName, - definition: args.definition ?? existing.definition, - }); - } - case "test_workflow": { - const workflow = find(); - return store.runWorkflow(workflow.id, args.input || {}, executionOptions); - } - case "publish_workflow": { - const workflow = find(); - return store.publishWorkflow(workflow.id, requireRevision()); - } - case "set_enabled": { - const workflow = find(); - if (typeof args.enabled !== "boolean") { - throw new SystemToolsError("INPUT_INVALID", "启停工作流必须提供 enabled 布尔值。"); - } - return store.setWorkflowEnabled(workflow.id, args.enabled, requireRevision()); - } - default: - throw new SystemToolsError("ACTION_INVALID", `不支持的工作流操作:${args.action || "空"}。`); - } -} - export function apply(ctx, config) { installConversationLocatorProjection(ctx); installPlanPermissionLink(ctx, config); @@ -421,15 +365,6 @@ export function apply(ctx, config) { 当用户明确要求记住某项信息,或信息稳定且会在后续任务中复用时,使用 knowledge_manager 写入;未指定知识库时让工具自动维护“Agent 知识”。 默认写入当前工作区;只有用户明确要求跨项目复用时才使用 global scope。 不要保存临时对话、猜测、未经确认的结论、凭据或其他秘密。更新前先读取现有文档并携带 revision。删除必须使用 knowledge_delete。`, - }); - ctx.systemPrompt.section({ - name: "laobos:workflow-guidance", - order: 41, - text: () => `# 工作流使用规则 - -工作流是可复用的 Agent 自动化。只有用户明确要求自动化,或一个稳定流程会重复使用时,才使用 workflow_manager 创建工作流;一次性任务不要创建。 -创建后先 test_workflow,确认结果再 publish_workflow。首次发布会自动启用并作为虚拟工作流插件注册,用户可以随时停用。 -更新、发布或启停前先读取当前工作流并携带 revision。删除必须使用 workflow_delete,并说明原因。`, }); ctx.systemPrompt.section({ name: "laobos:git-guidance", @@ -455,31 +390,10 @@ export function apply(ctx, config) { isConcurrencySafe: () => true, })); - const workflowExecutionOptions = (exec = {}) => ({ - signal: exec.signal, - async invokeTool(call) { - if (typeof ctx.tools.execute !== "function") { - throw new SystemToolsError("WORKFLOW_TOOL_UNAVAILABLE", "当前运行环境未提供嵌套工具调用。"); - } - const parentCallId = exec.callId || randomUUID(); - const nested = await ctx.tools.execute({ - callId: `${parentCallId}:workflow:${randomUUID()}`, - rootCallId: exec.rootCallId || parentCallId, - parent: exec.token, - name: call.name, - arguments: call.arguments, - agent: exec.agent, - signal: exec.signal, - }); - if (nested.isError) throw new Error(nested.error.message); - return nested.value; - }, - }); - let dynamicDisposers = []; const refreshDynamicTools = () => { for (const dispose of dynamicDisposers.splice(0)) dispose(); - const names = new Set(["knowledge_search", "knowledge_manager", "knowledge_delete", "workflow_manager", "workflow_delete"]); + const names = new Set(["knowledge_search", "knowledge_manager", "knowledge_delete"]); for (const collection of visibleCollections(store, workspacePath).filter((item) => item.agentEnabled)) { if (names.has(collection.toolName)) continue; names.add(collection.toolName); @@ -495,28 +409,6 @@ export function apply(ctx, config) { isConcurrencySafe: () => true, }))); } - for (const workflow of store.listPublishedWorkflows().filter((item) => item.enabled)) { - if (names.has(workflow.toolName)) { - ctx.logger.warn(`跳过重复的劳博士工具名:${workflow.toolName}`); - continue; - } - names.add(workflow.toolName); - dynamicDisposers.push(ctx.tools.register(defineTool({ - name: workflow.toolName, - description: workflow.description || `Run the published workflow ${workflow.name}.`, - parameters: workflowParameters(workflow.definition), - output: jsonOutput, - async execute(args, exec) { - const result = await store.runWorkflow( - workflow.workflowId, - args, - workflowExecutionOptions(exec), - workflow.version, - ); - return result.output; - }, - }))); - } }; ctx.tools.register(defineTool({ @@ -536,6 +428,7 @@ export function apply(ctx, config) { title: { type: "string", description: "Document title for upsert_document." }, content: { type: "string", description: "Durable document content for upsert_document." }, source: { type: "string", description: "Source file, URL, conversation, or provenance note." }, + imageUrls: { type: "array", description: "Optional HTTP(S) image URLs rendered with this document (maximum 12)." }, }, output: jsonOutput, execute: async (args) => { @@ -570,46 +463,6 @@ export function apply(ctx, config) { }, })); - ctx.tools.register(defineTool({ - name: "workflow_manager", - description: "List, read, create, update, test, publish, enable, or disable reusable workflows. This tool never deletes workflows. Read the current revision before changing an existing workflow.", - parameters: { - action: { type: "string", required: true, enum: ["list_workflows", "get_workflow", "create_workflow", "update_workflow", "test_workflow", "publish_workflow", "set_enabled"], description: "Workflow management action." }, - workflowId: { type: "string", description: "Existing workflow id." }, - expectedRevision: { type: "string", description: "Current revision; required for update, publish, and enable changes." }, - name: { type: "string", description: "Human-readable workflow name." }, - description: { type: "string", description: "When and why the Agent should use this workflow." }, - toolName: { type: "string", description: "Stable lowercase Agent tool name." }, - definition: { type: "json", description: "Workflow DAG definition with nodes and edges." }, - input: { type: "json", description: "JSON object used by test_workflow." }, - enabled: { type: "boolean", description: "Whether the published workflow is available to the Agent." }, - }, - output: jsonOutput, - execute: async (args, exec) => { - const result = await manageWorkflow(store, args, workflowExecutionOptions(exec)); - if (["publish_workflow", "set_enabled"].includes(args.action)) refreshDynamicTools(); - return result; - }, - isConcurrencySafe: (args) => ["list_workflows", "get_workflow"].includes(args.action), - })); - - ctx.tools.register(defineTool({ - name: "workflow_delete", - description: "Delete a workflow and unregister its virtual workflow plugin after user approval. Read the current revision first.", - parameters: { - id: { type: "string", required: true, description: "Exact workflow id." }, - expectedRevision: { type: "string", required: true, description: "Current revision returned by workflow_manager." }, - reason: { type: "string", required: true, description: "Why this workflow should be deleted." }, - }, - output: jsonOutput, - execute: async (args) => { - const workflow = store.getWorkflow(args.id); - store.deleteWorkflow(workflow.id, args.expectedRevision); - refreshDynamicTools(); - return { deleted: true, id: workflow.id, name: workflow.name, reason: args.reason }; - }, - })); - ctx.tools.register(defineTool({ name: "git_manager", description: "Inspect or initialize the current Git repository; stage, unstage, commit, create, or switch local branches with optimistic state checks. Prefer this over Bash for Git version management.", @@ -668,12 +521,10 @@ export function apply(ctx, config) { ctx.on("tools/pre-execute", async (exec, next) => { const decision = await next(); - if (!["knowledge_delete", "workflow_delete", "git_restore", "git_publish"].includes(exec.name) || decision.kind !== "allow") return decision; + if (!["knowledge_delete", "git_restore", "git_publish"].includes(exec.name) || decision.kind !== "allow") return decision; return { kind: "ask", - reason: exec.name === "workflow_delete" - ? "删除工作流会同步移除虚拟插件和全部发布版本,请确认 Agent 的删除请求。" - : exec.name === "knowledge_delete" + reason: exec.name === "knowledge_delete" ? "删除知识库内容不可直接恢复,请确认 Agent 的删除请求。" : exec.name === "git_restore" ? "恢复文件或删除分支会丢弃本地状态,请确认 Agent 的操作请求。" @@ -697,7 +548,9 @@ export function apply(ctx, config) { let value; if (req.method === "GET" && route === "/brand/icon.png") { - const icon = readFileSync(new URL("../../../public/laobos-logo.png", import.meta.url)); + // Packaged plugins are copied into DSH Home and cannot reach the Studio + // repository's public directory. Keep every runtime asset package-local. + const icon = readFileSync(new URL("../assets/laobos-logo.png", import.meta.url)); res.writeHead(200, { "content-type": "image/png", "cache-control": "public, max-age=86400, immutable", @@ -731,7 +584,6 @@ export function apply(ctx, config) { const skillCatalog = await skills.list(); value = { collections: visibleCollections(store, workspacePath), - workflows: store.listWorkflows(), skills: skillCatalog.skills, mcp: mcp.list(), }; @@ -819,28 +671,6 @@ export function apply(ctx, config) { findCollection(store, document.collectionId, workspacePath); store.deleteDocument(id, url.searchParams.get("revision")); value = { deleted: true }; refreshDynamicTools(); - } else if (req.method === "GET" && route === "/workflows") { - value = store.listWorkflows(); - } else if (req.method === "GET" && route.startsWith("/workflows/")) { - value = store.getWorkflow(decodeURIComponent(route.slice(11))); - } else if (req.method === "POST" && route === "/workflows") { - value = store.upsertWorkflow(await body(req)); refreshDynamicTools(); - } else if (req.method === "DELETE" && route.startsWith("/workflows/")) { - store.deleteWorkflow(decodeURIComponent(route.slice(11)), url.searchParams.get("revision")); - value = { deleted: true }; refreshDynamicTools(); - } else if (req.method === "POST" && /^\/workflows\/[^/]+\/publish$/u.test(route)) { - const input = await body(req); - value = store.publishWorkflow(decodeURIComponent(route.split("/")[2]), input.expectedRevision); refreshDynamicTools(); - } else if (req.method === "POST" && /^\/workflows\/[^/]+\/enabled$/u.test(route)) { - const input = await body(req); - value = store.setWorkflowEnabled( - decodeURIComponent(route.split("/")[2]), - input.enabled, - input.expectedRevision, - ); - refreshDynamicTools(); - } else if (req.method === "POST" && /^\/workflows\/[^/]+\/run$/u.test(route)) { - value = await store.runWorkflow(decodeURIComponent(route.split("/")[2]), (await body(req)).input || {}); } else { json(res, 404, { error: { code: "NOT_FOUND", message: "接口不存在。" } }); return; diff --git a/packages/laobos-system-tools/lib/store.js b/packages/laobos-system-tools/lib/store.js index d6587c8..a95e15c 100644 --- a/packages/laobos-system-tools/lib/store.js +++ b/packages/laobos-system-tools/lib/store.js @@ -50,6 +50,36 @@ function toolName(value) { return value; } +export function normalizeImageUrls(value) { + const candidates = (Array.isArray(value) + ? value + : typeof value === "string" + ? value.split(/\r?\n/u) + : []) + .map((candidate) => String(candidate || "").trim()) + .filter(Boolean); + if (candidates.length > 12) fail("IMAGE_URLS_TOO_MANY", "每份知识资料最多添加 12 张图片。"); + const result = []; + for (const candidate of candidates) { + const text = candidate; + if (text.length > 4_096) fail("IMAGE_URL_INVALID", "图片 URL 过长。"); + let url; + try { url = new URL(text); } + catch { fail("IMAGE_URL_INVALID", `图片 URL 无效:${text.slice(0, 120)}`); } + if (!["http:", "https:"].includes(url.protocol) || url.username || url.password) { + fail("IMAGE_URL_INVALID", "图片仅支持不含凭据的 HTTP(S) URL。"); + } + const normalized = url.toString(); + if (!result.includes(normalized)) result.push(normalized); + } + return result; +} + +function parseImageUrls(value) { + try { return normalizeImageUrls(JSON.parse(value || "[]")); } + catch { return []; } +} + function normalizeSearchText(value) { return String(value || "") .normalize("NFKC") @@ -152,7 +182,7 @@ export class SystemToolsStore { CREATE TABLE IF NOT EXISTS knowledge_documents ( id TEXT PRIMARY KEY, revision INTEGER NOT NULL DEFAULT 1, collection_id TEXT NOT NULL REFERENCES knowledge_collections(id) ON DELETE CASCADE, - title TEXT NOT NULL, source TEXT, content TEXT NOT NULL, + title TEXT NOT NULL, source TEXT, image_urls_json TEXT NOT NULL DEFAULT '[]', content TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS knowledge_chunks ( @@ -195,6 +225,12 @@ export class SystemToolsStore { if (!collectionColumns.has("workspace_path")) { this.database.exec("ALTER TABLE knowledge_collections ADD COLUMN workspace_path TEXT"); } + const documentColumns = new Set( + this.database.prepare("PRAGMA table_info(knowledge_documents)").all().map((row) => row.name), + ); + if (!documentColumns.has("image_urls_json")) { + this.database.exec("ALTER TABLE knowledge_documents ADD COLUMN image_urls_json TEXT NOT NULL DEFAULT '[]'"); + } const workflowColumns = new Set( this.database.prepare("PRAGMA table_info(workflows)").all().map((row) => row.name), ); @@ -369,13 +405,13 @@ export class SystemToolsStore { listDocuments(collectionId) { const where = collectionId ? "WHERE d.collection_id=?" : ""; return this.database.prepare(` - SELECT d.id,d.revision,d.collection_id,d.title,d.source,length(d.content) content_length, + SELECT d.id,d.revision,d.collection_id,d.title,d.source,d.image_urls_json,length(d.content) content_length, COUNT(k.id) chunk_count,d.created_at,d.updated_at FROM knowledge_documents d LEFT JOIN knowledge_chunks k ON k.document_id=d.id ${where} GROUP BY d.id ORDER BY d.updated_at DESC,d.title COLLATE NOCASE `).all(...(collectionId ? [collectionId] : [])).map((row) => ({ id: row.id, revision: revision(row), collectionId: row.collection_id, title: row.title, - ...(row.source ? { source: row.source } : {}), contentLength: row.content_length, + ...(row.source ? { source: row.source } : {}), imageUrls: parseImageUrls(row.image_urls_json), contentLength: row.content_length, chunkCount: row.chunk_count, createdAt: row.created_at, updatedAt: row.updated_at, })); } @@ -383,13 +419,13 @@ export class SystemToolsStore { getDocument(id) { identifier(id, "文档 ID"); const row = this.database.prepare(` - SELECT d.id,d.revision,d.collection_id,d.title,d.source,d.content,length(d.content) content_length, + SELECT d.id,d.revision,d.collection_id,d.title,d.source,d.image_urls_json,d.content,length(d.content) content_length, COUNT(k.id) chunk_count,d.created_at,d.updated_at FROM knowledge_documents d LEFT JOIN knowledge_chunks k ON k.document_id=d.id WHERE d.id=? GROUP BY d.id `).get(id); if (!row) fail("DOCUMENT_NOT_FOUND", "文档不存在。", 404); return { id: row.id, revision: revision(row), collectionId: row.collection_id, title: row.title, - ...(row.source ? { source: row.source } : {}), content: row.content, + ...(row.source ? { source: row.source } : {}), imageUrls: parseImageUrls(row.image_urls_json), content: row.content, contentLength: row.content_length, chunkCount: row.chunk_count, createdAt: row.created_at, updatedAt: row.updated_at }; } @@ -403,6 +439,7 @@ export class SystemToolsStore { const title = nonEmpty(input.title, "文档标题", 240); const content = nonEmpty(input.content, "文档内容", MAX_DOCUMENT_CHARACTERS); const source = String(input.source || "").trim().slice(0, 2000) || null; + const imageUrls = normalizeImageUrls(input.imageUrls ?? existing?.imageUrls ?? []); const chunks = splitDocument(content); const timestamp = now(); this.transaction(() => { @@ -411,11 +448,11 @@ export class SystemToolsStore { } this.database.prepare("DELETE FROM knowledge_chunks WHERE document_id=?").run(id); this.database.prepare(` - INSERT INTO knowledge_documents(id,collection_id,title,source,content,created_at,updated_at) - VALUES(?,?,?,?,?,?,?) ON CONFLICT(id) DO UPDATE SET collection_id=excluded.collection_id, - title=excluded.title,source=excluded.source,content=excluded.content, + INSERT INTO knowledge_documents(id,collection_id,title,source,image_urls_json,content,created_at,updated_at) + VALUES(?,?,?,?,?,?,?,?) ON CONFLICT(id) DO UPDATE SET collection_id=excluded.collection_id, + title=excluded.title,source=excluded.source,image_urls_json=excluded.image_urls_json,content=excluded.content, updated_at=excluded.updated_at,revision=revision+1 - `).run(id, collectionId, title, source, content, timestamp, timestamp); + `).run(id, collectionId, title, source, JSON.stringify(imageUrls), content, timestamp, timestamp); for (const [ordinal, chunk] of chunks.entries()) { const chunkId = `chunk-${randomUUID()}`; this.database.prepare("INSERT INTO knowledge_chunks VALUES(?,?,?,?,?,?)").run(chunkId, id, collectionId, ordinal, chunk, timestamp); @@ -446,7 +483,7 @@ export class SystemToolsStore { let rows = []; try { rows = !match ? [] : this.database.prepare(` - SELECT k.id chunk_id,k.ordinal,k.document_id,k.collection_id,d.title,d.source,k.content, + SELECT k.id chunk_id,k.ordinal,k.document_id,k.collection_id,d.title,d.source,d.image_urls_json,k.content, bm25(knowledge_chunks_fts,0.0,0.0,5.0,1.0) rank FROM knowledge_chunks_fts JOIN knowledge_chunks k ON k.id=knowledge_chunks_fts.chunk_id JOIN knowledge_documents d ON d.id=k.document_id @@ -462,7 +499,7 @@ export class SystemToolsStore { const conditions = fallbackTerms.map(() => "(k.content LIKE ? OR d.title LIKE ?)").join(" OR "); const values = fallbackTerms.flatMap((term) => [`%${term}%`, `%${term}%`]); rows = this.database.prepare(` - SELECT k.id chunk_id,k.ordinal,k.document_id,k.collection_id,d.title,d.source,k.content,1.0 rank + SELECT k.id chunk_id,k.ordinal,k.document_id,k.collection_id,d.title,d.source,d.image_urls_json,k.content,1.0 rank FROM knowledge_chunks k JOIN knowledge_documents d ON d.id=k.document_id JOIN knowledge_collections c ON c.id=k.collection_id WHERE (${conditions}) AND (? IS NULL OR k.collection_id=?) AND (?=0 OR c.agent_enabled=1) @@ -498,6 +535,7 @@ export class SystemToolsStore { chunkId: row.chunk_id, ordinal: row.ordinal, documentId: row.document_id, collectionId: row.collection_id, title: row.title, ...(row.source ? { source: row.source } : {}), + imageUrls: parseImageUrls(row.image_urls_json), content: mergeOverlappingText(context.map((item) => item.content)), score: Number(row.score.toFixed(6)), }; diff --git a/packages/laobos-system-tools/package.json b/packages/laobos-system-tools/package.json index d75addd..f3de96a 100644 --- a/packages/laobos-system-tools/package.json +++ b/packages/laobos-system-tools/package.json @@ -11,7 +11,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@deepseek-ai/dsh-mcp-client": "0.1.0-rc.6", + "@deepseek-ai/dsh-mcp-client": "0.1.0-rc.7", "yaml": "2.9.0", "zod": "^4.4.3" }, diff --git a/packages/laobos-terminal-ui/lib/client.js b/packages/laobos-terminal-ui/lib/client.js index fc59f5f..7bb911e 100644 --- a/packages/laobos-terminal-ui/lib/client.js +++ b/packages/laobos-terminal-ui/lib/client.js @@ -9437,8 +9437,8 @@ ${h2.join(` const { useCallback, useEffect, useMemo, useRef, useState } = React; const css = `${xterm_default} - .lbs-terminal-panel{background:#101419;bottom:0;color:#e8edf2;display:grid;grid-template-rows:44px minmax(0,1fr) 24px;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483060} - .lbs-terminal-toolbar{align-items:center;background:#181d23;border-bottom:1px solid #2b323b;display:flex;gap:6px;min-width:0;padding:0 9px}.lbs-terminal-toolbar strong{font-size:13px;margin-right:2px}.lbs-terminal-toolbar .lbs-terminal-tabs{display:flex!important;flex:1;gap:3px;min-width:0;overflow:auto hidden}.lbs-terminal-tab{align-items:center;background:transparent;border:1px solid transparent;border-radius:6px;color:#9aa7b5;display:flex;height:30px;max-width:190px;min-width:112px;padding:0 4px 0 8px}.lbs-terminal-tab[data-active=true]{background:#242b33;border-color:#35404b;color:#edf3f8}.lbs-terminal-tab-main{align-items:center;background:transparent;border:0;color:inherit;cursor:pointer;display:flex;flex:1;font:inherit;font-size:11px;gap:6px;min-width:0;padding:0}.lbs-terminal-tab-main span:nth-child(2){overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-terminal-dot{background:#8b96a1;border-radius:50%;flex:none;height:6px;width:6px}.lbs-terminal-dot[data-state=connected]{background:#39b87b}.lbs-terminal-dot[data-state=creating]{background:#e1a83d}.lbs-terminal-dot[data-state=error]{background:#e25d68}.lbs-terminal-tab-close,.lbs-terminal-icon{appearance:none;background:transparent;border:0;border-radius:5px;color:inherit;cursor:pointer;display:grid;flex:none;height:26px;place-items:center;width:26px}.lbs-terminal-tab-close:hover,.lbs-terminal-icon:hover{background:#303944}.lbs-terminal-select{background:#252c34;border:1px solid #35404b;border-radius:6px;color:#d5dde5;font:11px inherit;height:29px;padding:0 7px}.lbs-terminal-new{appearance:none;background:#e8edf2;border:0;border-radius:6px;color:#14191f;cursor:pointer;font:600 11px inherit;height:29px;padding:0 10px}.lbs-terminal-stage{min-height:0;position:relative}.lbs-terminal-surface{inset:0;pointer-events:none;position:absolute;visibility:hidden}.lbs-terminal-surface[data-active=true]{pointer-events:auto;visibility:visible}.lbs-terminal-host{box-sizing:border-box;height:100%;padding:8px}.lbs-terminal-host .xterm{height:100%}.lbs-terminal-empty{align-content:center;color:#8f9aa6;display:grid;gap:9px;height:100%;justify-items:center;padding:28px;text-align:center}.lbs-terminal-empty strong{color:#dfe6ec;font-size:13px}.lbs-terminal-empty p{font-size:11px;line-height:1.5;margin:0;max-width:460px}.lbs-terminal-empty button{background:#e8edf2;border:0;border-radius:6px;color:#14191f;height:31px;padding:0 11px}.lbs-terminal-message{background:#482129;color:#ffc4ca;font-size:11px;left:10px;max-width:calc(100% - 20px);padding:7px 10px;position:absolute;top:8px;z-index:3}.lbs-terminal-status{align-items:center;background:#181d23;border-top:1px solid #2b323b;color:#8995a1;display:flex;font-size:9px;gap:12px;padding:0 9px}.lbs-terminal-status span:last-child{margin-left:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:850px){.lbs-terminal-panel{left:0;right:0}.lbs-terminal-toolbar strong{display:none}.lbs-terminal-tab{min-width:96px}.lbs-terminal-select{max-width:94px}} + .lbs-terminal-panel{background:var(--dsw-alias-bg-base);bottom:0;color:var(--dsw-alias-label-primary);display:grid;grid-template-rows:44px minmax(0,1fr) 24px;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483060} + .lbs-terminal-toolbar{align-items:center;background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;gap:6px;min-width:0;padding:0 9px}.lbs-terminal-toolbar strong{font-size:13px;margin-right:2px}.lbs-terminal-toolbar .lbs-terminal-tabs{display:flex!important;flex:1;gap:3px;min-width:0;overflow:auto hidden}.lbs-terminal-tab{align-items:center;background:transparent;border:1px solid transparent;border-radius:6px;color:var(--dsw-alias-label-tertiary);display:flex;height:30px;max-width:190px;min-width:112px;padding:0 4px 0 8px}.lbs-terminal-tab[data-active=true]{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary)}.lbs-terminal-tab-main{align-items:center;background:transparent;border:0;color:inherit;cursor:pointer;display:flex;flex:1;font:inherit;font-size:11px;gap:6px;min-width:0;padding:0}.lbs-terminal-tab-main span:nth-child(2){overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-terminal-dot{background:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary));border-radius:50%;flex:none;height:6px;width:6px}.lbs-terminal-dot[data-state=connected]{background:var(--dsw-alias-state-success-primary,#39b87b)}.lbs-terminal-dot[data-state=creating]{background:var(--dsw-alias-state-warn-primary,#e1a83d)}.lbs-terminal-dot[data-state=error]{background:var(--dsw-alias-state-error-primary,#e25d68)}.lbs-terminal-tab-close,.lbs-terminal-icon{appearance:none;background:transparent;border:0;border-radius:5px;color:inherit;cursor:pointer;display:grid;flex:none;height:26px;place-items:center;width:26px}.lbs-terminal-tab-close:hover,.lbs-terminal-icon:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-terminal-select{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-primary);font:11px inherit;height:29px;padding:0 7px}.lbs-terminal-new{appearance:none;background:var(--dsw-alias-button-primary-fill,var(--dsw-alias-interactive-bg-primary));border:0;border-radius:6px;color:var(--dsw-alias-label-primary-foreground,var(--dsw-alias-label-on-primary));cursor:pointer;font:600 11px inherit;height:29px;padding:0 10px}.lbs-terminal-stage{background:var(--dsw-alias-bg-base);min-height:0;position:relative}.lbs-terminal-surface{inset:0;pointer-events:none;position:absolute;visibility:hidden}.lbs-terminal-surface[data-active=true]{pointer-events:auto;visibility:visible}.lbs-terminal-host{box-sizing:border-box;height:100%;padding:8px}.lbs-terminal-host .xterm{height:100%}.lbs-terminal-empty{align-content:center;color:var(--dsw-alias-label-tertiary);display:grid;gap:9px;height:100%;justify-items:center;padding:28px;text-align:center}.lbs-terminal-empty strong{color:var(--dsw-alias-label-primary);font-size:13px}.lbs-terminal-empty p{font-size:11px;line-height:1.5;margin:0;max-width:460px}.lbs-terminal-empty button{background:var(--dsw-alias-button-primary-fill,var(--dsw-alias-interactive-bg-primary));border:0;border-radius:6px;color:var(--dsw-alias-label-primary-foreground,var(--dsw-alias-label-on-primary));height:31px;padding:0 11px}.lbs-terminal-message{background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#d94b4b) 10%,var(--dsw-alias-bg-layer-1));color:var(--dsw-alias-state-error-primary,#d94b4b);font-size:11px;left:10px;max-width:calc(100% - 20px);padding:7px 10px;position:absolute;top:8px;z-index:3}.lbs-terminal-status{align-items:center;background:var(--dsw-alias-bg-layer-1);border-top:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);display:flex;font-size:9px;gap:12px;padding:0 9px}.lbs-terminal-status span:last-child{margin-left:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:850px){.lbs-terminal-panel{left:0;right:0}.lbs-terminal-toolbar strong{display:none}.lbs-terminal-tab{min-width:96px}.lbs-terminal-select{max-width:94px}} `; if (typeof document !== "undefined" && !document.querySelector('style[data-plugin-css="@laobos/dsh-terminal-ui"]')) { const style = document.createElement("style"); @@ -9446,6 +9446,48 @@ ${h2.join(` style.textContent = css; document.head.append(style); } + function terminalTheme(element) { + const styles = getComputedStyle(element); + const color = (name, fallback) => styles.getPropertyValue(name).trim() || fallback; + const dark = document.body.hasAttribute("data-ds-dark-theme"); + return { + background: color("--dsw-alias-bg-base", dark ? "#151517" : "#ffffff"), + foreground: color("--dsw-alias-label-primary", dark ? "#f1f3f5" : "#0f1115"), + cursor: color("--dsw-alias-label-primary", dark ? "#f1f3f5" : "#0f1115"), + cursorAccent: color("--dsw-alias-bg-base", dark ? "#151517" : "#ffffff"), + selectionBackground: color("--dsw-alias-interactive-bg-active", dark ? "rgba(88,166,255,.28)" : "rgba(9,105,218,.18)"), + black: dark ? "#484f58" : "#24292f", + red: dark ? "#ff7b72" : "#cf222e", + green: dark ? "#3fb950" : "#1a7f37", + yellow: dark ? "#d29922" : "#9a6700", + blue: dark ? "#58a6ff" : "#0969da", + magenta: dark ? "#bc8cff" : "#8250df", + cyan: dark ? "#39c5cf" : "#1b7c83", + white: dark ? "#b1bac4" : "#6e7781", + brightBlack: dark ? "#6e7681" : "#57606a", + brightRed: dark ? "#ffa198" : "#a40e26", + brightGreen: dark ? "#56d364" : "#116329", + brightYellow: dark ? "#e3b341" : "#4d2d00", + brightBlue: dark ? "#79c0ff" : "#218bff", + brightMagenta: dark ? "#d2a8ff" : "#a475f9", + brightCyan: dark ? "#56d4dd" : "#3192aa", + brightWhite: dark ? "#f0f6fc" : "#24292f" + }; + } + function syncTerminalTheme(terminal, element) { + const applyTheme = () => { + terminal.options.theme = terminalTheme(element); + }; + const observer = new MutationObserver(applyTheme); + observer.observe(document.body, { attributes: true, attributeFilter: ["data-ds-dark-theme"] }); + const media = window.matchMedia?.("(prefers-color-scheme: dark)"); + media?.addEventListener?.("change", applyTheme); + applyTheme(); + return () => { + observer.disconnect(); + media?.removeEventListener?.("change", applyTheme); + }; + } let tabSequence = 0; const nextTmuxSlot = (tabs) => { const used = new Set(tabs.filter((tab) => tab.tmux).map((tab) => tab.sessionKey)); @@ -9491,12 +9533,13 @@ ${h2.join(` fontSize: 13, lineHeight: 1.2, scrollback: 1e4, - theme: { background: "#101419", foreground: "#e8edf2", cursor: "#d8e6f3", selectionBackground: "#38506a" } + theme: terminalTheme(host.current) }); terminalRef.current = terminal; const fit = new o(); terminal.loadAddon(fit); terminal.open(host.current); + const stopThemeSync = syncTerminalTheme(terminal, host.current); const fitTerminal = () => { try { fit.fit(); @@ -9543,6 +9586,7 @@ ${h2.join(` return () => { disposed = true; terminalRef.current = null; + stopThemeSync(); resize.disconnect(); input.dispose(); offData(); diff --git a/packages/laobos-terminal-ui/src/client.jsx b/packages/laobos-terminal-ui/src/client.jsx index ea42a5c..b8936ba 100644 --- a/packages/laobos-terminal-ui/src/client.jsx +++ b/packages/laobos-terminal-ui/src/client.jsx @@ -13,8 +13,8 @@ window.__ModuleLoader__.load({ const { useCallback, useEffect, useMemo, useRef, useState } = React; const css = `${xtermCss}\n - .lbs-terminal-panel{background:#101419;bottom:0;color:#e8edf2;display:grid;grid-template-rows:44px minmax(0,1fr) 24px;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483060} - .lbs-terminal-toolbar{align-items:center;background:#181d23;border-bottom:1px solid #2b323b;display:flex;gap:6px;min-width:0;padding:0 9px}.lbs-terminal-toolbar strong{font-size:13px;margin-right:2px}.lbs-terminal-toolbar .lbs-terminal-tabs{display:flex!important;flex:1;gap:3px;min-width:0;overflow:auto hidden}.lbs-terminal-tab{align-items:center;background:transparent;border:1px solid transparent;border-radius:6px;color:#9aa7b5;display:flex;height:30px;max-width:190px;min-width:112px;padding:0 4px 0 8px}.lbs-terminal-tab[data-active=true]{background:#242b33;border-color:#35404b;color:#edf3f8}.lbs-terminal-tab-main{align-items:center;background:transparent;border:0;color:inherit;cursor:pointer;display:flex;flex:1;font:inherit;font-size:11px;gap:6px;min-width:0;padding:0}.lbs-terminal-tab-main span:nth-child(2){overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-terminal-dot{background:#8b96a1;border-radius:50%;flex:none;height:6px;width:6px}.lbs-terminal-dot[data-state=connected]{background:#39b87b}.lbs-terminal-dot[data-state=creating]{background:#e1a83d}.lbs-terminal-dot[data-state=error]{background:#e25d68}.lbs-terminal-tab-close,.lbs-terminal-icon{appearance:none;background:transparent;border:0;border-radius:5px;color:inherit;cursor:pointer;display:grid;flex:none;height:26px;place-items:center;width:26px}.lbs-terminal-tab-close:hover,.lbs-terminal-icon:hover{background:#303944}.lbs-terminal-select{background:#252c34;border:1px solid #35404b;border-radius:6px;color:#d5dde5;font:11px inherit;height:29px;padding:0 7px}.lbs-terminal-new{appearance:none;background:#e8edf2;border:0;border-radius:6px;color:#14191f;cursor:pointer;font:600 11px inherit;height:29px;padding:0 10px}.lbs-terminal-stage{min-height:0;position:relative}.lbs-terminal-surface{inset:0;pointer-events:none;position:absolute;visibility:hidden}.lbs-terminal-surface[data-active=true]{pointer-events:auto;visibility:visible}.lbs-terminal-host{box-sizing:border-box;height:100%;padding:8px}.lbs-terminal-host .xterm{height:100%}.lbs-terminal-empty{align-content:center;color:#8f9aa6;display:grid;gap:9px;height:100%;justify-items:center;padding:28px;text-align:center}.lbs-terminal-empty strong{color:#dfe6ec;font-size:13px}.lbs-terminal-empty p{font-size:11px;line-height:1.5;margin:0;max-width:460px}.lbs-terminal-empty button{background:#e8edf2;border:0;border-radius:6px;color:#14191f;height:31px;padding:0 11px}.lbs-terminal-message{background:#482129;color:#ffc4ca;font-size:11px;left:10px;max-width:calc(100% - 20px);padding:7px 10px;position:absolute;top:8px;z-index:3}.lbs-terminal-status{align-items:center;background:#181d23;border-top:1px solid #2b323b;color:#8995a1;display:flex;font-size:9px;gap:12px;padding:0 9px}.lbs-terminal-status span:last-child{margin-left:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:850px){.lbs-terminal-panel{left:0;right:0}.lbs-terminal-toolbar strong{display:none}.lbs-terminal-tab{min-width:96px}.lbs-terminal-select{max-width:94px}} + .lbs-terminal-panel{background:var(--dsw-alias-bg-base);bottom:0;color:var(--dsw-alias-label-primary);display:grid;grid-template-rows:44px minmax(0,1fr) 24px;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483060} + .lbs-terminal-toolbar{align-items:center;background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;gap:6px;min-width:0;padding:0 9px}.lbs-terminal-toolbar strong{font-size:13px;margin-right:2px}.lbs-terminal-toolbar .lbs-terminal-tabs{display:flex!important;flex:1;gap:3px;min-width:0;overflow:auto hidden}.lbs-terminal-tab{align-items:center;background:transparent;border:1px solid transparent;border-radius:6px;color:var(--dsw-alias-label-tertiary);display:flex;height:30px;max-width:190px;min-width:112px;padding:0 4px 0 8px}.lbs-terminal-tab[data-active=true]{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary)}.lbs-terminal-tab-main{align-items:center;background:transparent;border:0;color:inherit;cursor:pointer;display:flex;flex:1;font:inherit;font-size:11px;gap:6px;min-width:0;padding:0}.lbs-terminal-tab-main span:nth-child(2){overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-terminal-dot{background:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary));border-radius:50%;flex:none;height:6px;width:6px}.lbs-terminal-dot[data-state=connected]{background:var(--dsw-alias-state-success-primary,#39b87b)}.lbs-terminal-dot[data-state=creating]{background:var(--dsw-alias-state-warn-primary,#e1a83d)}.lbs-terminal-dot[data-state=error]{background:var(--dsw-alias-state-error-primary,#e25d68)}.lbs-terminal-tab-close,.lbs-terminal-icon{appearance:none;background:transparent;border:0;border-radius:5px;color:inherit;cursor:pointer;display:grid;flex:none;height:26px;place-items:center;width:26px}.lbs-terminal-tab-close:hover,.lbs-terminal-icon:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-terminal-select{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;color:var(--dsw-alias-label-primary);font:11px inherit;height:29px;padding:0 7px}.lbs-terminal-new{appearance:none;background:var(--dsw-alias-button-primary-fill,var(--dsw-alias-interactive-bg-primary));border:0;border-radius:6px;color:var(--dsw-alias-label-primary-foreground,var(--dsw-alias-label-on-primary));cursor:pointer;font:600 11px inherit;height:29px;padding:0 10px}.lbs-terminal-stage{background:var(--dsw-alias-bg-base);min-height:0;position:relative}.lbs-terminal-surface{inset:0;pointer-events:none;position:absolute;visibility:hidden}.lbs-terminal-surface[data-active=true]{pointer-events:auto;visibility:visible}.lbs-terminal-host{box-sizing:border-box;height:100%;padding:8px}.lbs-terminal-host .xterm{height:100%}.lbs-terminal-empty{align-content:center;color:var(--dsw-alias-label-tertiary);display:grid;gap:9px;height:100%;justify-items:center;padding:28px;text-align:center}.lbs-terminal-empty strong{color:var(--dsw-alias-label-primary);font-size:13px}.lbs-terminal-empty p{font-size:11px;line-height:1.5;margin:0;max-width:460px}.lbs-terminal-empty button{background:var(--dsw-alias-button-primary-fill,var(--dsw-alias-interactive-bg-primary));border:0;border-radius:6px;color:var(--dsw-alias-label-primary-foreground,var(--dsw-alias-label-on-primary));height:31px;padding:0 11px}.lbs-terminal-message{background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#d94b4b) 10%,var(--dsw-alias-bg-layer-1));color:var(--dsw-alias-state-error-primary,#d94b4b);font-size:11px;left:10px;max-width:calc(100% - 20px);padding:7px 10px;position:absolute;top:8px;z-index:3}.lbs-terminal-status{align-items:center;background:var(--dsw-alias-bg-layer-1);border-top:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);display:flex;font-size:9px;gap:12px;padding:0 9px}.lbs-terminal-status span:last-child{margin-left:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:850px){.lbs-terminal-panel{left:0;right:0}.lbs-terminal-toolbar strong{display:none}.lbs-terminal-tab{min-width:96px}.lbs-terminal-select{max-width:94px}} `; if (typeof document !== "undefined" && !document.querySelector('style[data-plugin-css="@laobos/dsh-terminal-ui"]')) { const style = document.createElement("style"); @@ -23,6 +23,33 @@ window.__ModuleLoader__.load({ document.head.append(style); } + function terminalTheme(element) { + const styles = getComputedStyle(element); + const color = (name, fallback) => styles.getPropertyValue(name).trim() || fallback; + const dark = document.body.hasAttribute("data-ds-dark-theme"); + return { + background: color("--dsw-alias-bg-base", dark ? "#151517" : "#ffffff"), + foreground: color("--dsw-alias-label-primary", dark ? "#f1f3f5" : "#0f1115"), + cursor: color("--dsw-alias-label-primary", dark ? "#f1f3f5" : "#0f1115"), + cursorAccent: color("--dsw-alias-bg-base", dark ? "#151517" : "#ffffff"), + selectionBackground: color("--dsw-alias-interactive-bg-active", dark ? "rgba(88,166,255,.28)" : "rgba(9,105,218,.18)"), + black: dark ? "#484f58" : "#24292f", red: dark ? "#ff7b72" : "#cf222e", green: dark ? "#3fb950" : "#1a7f37", yellow: dark ? "#d29922" : "#9a6700", + blue: dark ? "#58a6ff" : "#0969da", magenta: dark ? "#bc8cff" : "#8250df", cyan: dark ? "#39c5cf" : "#1b7c83", white: dark ? "#b1bac4" : "#6e7781", + brightBlack: dark ? "#6e7681" : "#57606a", brightRed: dark ? "#ffa198" : "#a40e26", brightGreen: dark ? "#56d364" : "#116329", brightYellow: dark ? "#e3b341" : "#4d2d00", + brightBlue: dark ? "#79c0ff" : "#218bff", brightMagenta: dark ? "#d2a8ff" : "#a475f9", brightCyan: dark ? "#56d4dd" : "#3192aa", brightWhite: dark ? "#f0f6fc" : "#24292f", + }; + } + + function syncTerminalTheme(terminal, element) { + const applyTheme = () => { terminal.options.theme = terminalTheme(element); }; + const observer = new MutationObserver(applyTheme); + observer.observe(document.body, { attributes: true, attributeFilter: ["data-ds-dark-theme"] }); + const media = window.matchMedia?.("(prefers-color-scheme: dark)"); + media?.addEventListener?.("change", applyTheme); + applyTheme(); + return () => { observer.disconnect(); media?.removeEventListener?.("change", applyTheme); }; + } + let tabSequence = 0; const nextTmuxSlot = (tabs) => { const used = new Set(tabs.filter((tab) => tab.tmux).map((tab) => tab.sessionKey)); @@ -69,12 +96,13 @@ window.__ModuleLoader__.load({ fontSize: 13, lineHeight: 1.2, scrollback: 10000, - theme: { background: "#101419", foreground: "#e8edf2", cursor: "#d8e6f3", selectionBackground: "#38506a" }, + theme: terminalTheme(host.current), }); terminalRef.current = terminal; const fit = new FitAddon(); terminal.loadAddon(fit); terminal.open(host.current); + const stopThemeSync = syncTerminalTheme(terminal, host.current); const fitTerminal = () => { try { fit.fit(); @@ -108,7 +136,7 @@ window.__ModuleLoader__.load({ }); return () => { disposed = true; terminalRef.current = null; - resize.disconnect(); input.dispose(); offData(); offExit(); terminal.dispose(); + stopThemeSync(); resize.disconnect(); input.dispose(); offData(); offExit(); terminal.dispose(); if (sessionId) void window.laobosDesktop.terminal.close({ id: sessionId }); }; }, [cwd, onError, onExit, onReady, tab.generation, tab.id, tab.sessionKey, tab.tmux]); diff --git a/packages/laobos-updater/lib/client.js b/packages/laobos-updater/lib/client.js new file mode 100644 index 0000000..26a85f9 --- /dev/null +++ b/packages/laobos-updater/lib/client.js @@ -0,0 +1,108 @@ +/* eslint-disable @next/next/no-assign-module-variable -- generated DSH module factory */ +(() => { + // packages/laobos-updater/src/client.jsx + window.__ModuleLoader__.load({ + id: "@laobos/dsh-updater", + factory: (require2) => { + var module = { exports: {} }; + var exports = module.exports; + Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); + const React = require2("react"); + const { useCallback, useEffect, useState } = React; + const css = ` + .lbs-update{display:flex;flex-direction:column;gap:12px} + .lbs-update-head{align-items:flex-start;display:flex;gap:14px;justify-content:space-between} + .lbs-update-title{font-size:13px;font-weight:600;line-height:20px}.lbs-update-sub{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:18px} + .lbs-update-version{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-line-border);border-radius:999px;color:var(--dsw-alias-label-secondary);font:11px/26px ui-monospace,SFMono-Regular,Menlo,monospace;padding:0 10px;white-space:nowrap} + .lbs-update-card{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-line-border);border-radius:10px;display:flex;flex-direction:column;gap:9px;padding:12px} + .lbs-update-status{align-items:center;display:flex;gap:8px}.lbs-update-dot{background:var(--dsw-alias-label-quaternary);border-radius:50%;height:8px;width:8px}.lbs-update-dot[data-active=true]{background:#2a9b67}.lbs-update-dot[data-error=true]{background:#d94b4b} + .lbs-update-status strong{font-size:12px;font-weight:600}.lbs-update-notes{color:var(--dsw-alias-label-secondary);font:11px/18px inherit;margin:0;max-height:160px;overflow:auto;white-space:pre-wrap} + .lbs-update-progress{background:var(--dsw-alias-bg-layer-1);border-radius:999px;height:6px;overflow:hidden}.lbs-update-progress>span{background:var(--dsw-alias-brand-primary);display:block;height:100%;transition:width .18s ease} + .lbs-update-actions{display:flex;flex-wrap:wrap;gap:8px}.lbs-update-button{appearance:none;background:transparent;border:1px solid var(--dsw-alias-line-border);border-radius:8px;color:inherit;cursor:pointer;font:11px inherit;height:31px;padding:0 11px}.lbs-update-button:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-update-button.primary{background:var(--dsw-alias-interactive-bg-primary);border-color:transparent;color:var(--dsw-alias-label-on-primary)}.lbs-update-button:disabled{cursor:not-allowed;opacity:.45} + .lbs-update-option{align-items:center;display:flex;font-size:11px;gap:8px}.lbs-update-option input{accent-color:var(--dsw-alias-brand-primary)}.lbs-update-error{color:#d94b4b;font-size:11px;line-height:18px} + `; + const labels = { + disabled: "开发环境不启用自动更新", + idle: "尚未检查更新", + restoring: "正在恢复本地更新缓存…", + checking: "正在检查更新…", + available: "发现新版本", + downloading: "正在下载更新…", + downloaded: "更新已下载,可以安装", + installing: "正在退出并安装更新…", + "up-to-date": "当前已经是最新版本", + error: "更新失败" + }; + function formatBytes(value) { + if (!Number.isFinite(value) || value <= 0) return "0 B"; + const units = ["B", "KB", "MB", "GB"]; + const index = Math.min(Math.floor(Math.log(value) / Math.log(1024)), units.length - 1); + return `${(value / 1024 ** index).toFixed(index === 0 ? 0 : 1)} ${units[index]}`; + } + function UpdateSettingsSection() { + const api = window.laobosDesktop?.updates; + const available = window.laobosDesktop?.capabilities?.softwareUpdate === true && Boolean(api); + const [state, setState] = useState(null); + const [preferences, setPreferences] = useState({ autoCheckUpdates: true }); + const [busy, setBusy] = useState(false); + const [localError, setLocalError] = useState(""); + useEffect(() => { + if (!available) return void 0; + let active2 = true; + Promise.all([api.status(), api.preferences()]).then(([nextState, nextPreferences]) => { + if (!active2) return; + setState(nextState); + setPreferences(nextPreferences); + }).catch((error2) => active2 && setLocalError(error2 instanceof Error ? error2.message : String(error2))); + const remove = api.onState((next) => active2 && setState(next)); + return () => { + active2 = false; + remove?.(); + }; + }, [api, available]); + const run = useCallback(async (action) => { + if (!available || busy) return; + setBusy(true); + setLocalError(""); + try { + const next = await action(); + if (next?.schema === 1) setState(next); + } catch (error2) { + setLocalError(error2 instanceof Error ? error2.message : String(error2)); + } finally { + setBusy(false); + } + }, [available, busy]); + async function toggleAutoCheck(event) { + const autoCheckUpdates = event.target.checked; + setPreferences((current) => ({ ...current, autoCheckUpdates })); + try { + const next = await api.setPreferences({ autoCheckUpdates }); + setPreferences(next); + } catch (error2) { + setPreferences((current) => ({ ...current, autoCheckUpdates: !autoCheckUpdates })); + setLocalError(error2 instanceof Error ? error2.message : String(error2)); + } + } + const phase = state?.phase || (available ? "idle" : "disabled"); + const progress = state?.progress; + const percent = Math.max(0, Math.min(100, progress?.percent || 0)); + const error = localError || state?.error?.message || ""; + const active = ["restoring", "available", "downloading", "downloaded", "installing", "up-to-date"].includes(phase); + return /* @__PURE__ */ React.createElement("section", { className: "lbs-update" }, /* @__PURE__ */ React.createElement("style", null, css), /* @__PURE__ */ React.createElement("div", { className: "lbs-update-head" }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { className: "lbs-update-title" }, "软件更新"), /* @__PURE__ */ React.createElement("div", { className: "lbs-update-sub" }, "从劳博士官方 GitHub Release 获取经过签名的软件版本。")), /* @__PURE__ */ React.createElement("span", { className: "lbs-update-version" }, "v", state?.currentVersion || "—")), /* @__PURE__ */ React.createElement("div", { className: "lbs-update-card" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-update-status" }, /* @__PURE__ */ React.createElement("span", { className: "lbs-update-dot", "data-active": active, "data-error": phase === "error" }), /* @__PURE__ */ React.createElement("strong", null, labels[phase] || "更新状态未知")), state?.availableVersion ? /* @__PURE__ */ React.createElement("div", { className: "lbs-update-sub" }, "可用版本:v", state.availableVersion, state.releaseDate ? ` · ${state.releaseDate.slice(0, 10)}` : "") : null, state?.cached ? /* @__PURE__ */ React.createElement("div", { className: "lbs-update-sub" }, "安装包已安全缓存到本地,重启应用后无需重新下载。") : null, state?.releaseNotes ? /* @__PURE__ */ React.createElement("pre", { className: "lbs-update-notes" }, state.releaseNotes) : null, phase === "downloading" ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "lbs-update-progress" }, /* @__PURE__ */ React.createElement("span", { style: { width: `${percent}%` } })), /* @__PURE__ */ React.createElement("div", { className: "lbs-update-sub" }, percent.toFixed(1), "% · ", formatBytes(progress?.transferred), " / ", formatBytes(progress?.total), " · ", formatBytes(progress?.bytesPerSecond), "/s")) : null, error ? /* @__PURE__ */ React.createElement("div", { className: "lbs-update-error" }, error) : null, /* @__PURE__ */ React.createElement("div", { className: "lbs-update-actions" }, /* @__PURE__ */ React.createElement("button", { className: "lbs-update-button", disabled: !available || busy || ["restoring", "checking", "downloading", "downloaded", "installing"].includes(phase), onClick: () => void run(() => api.check()) }, "检查更新"), phase === "available" ? /* @__PURE__ */ React.createElement("button", { className: "lbs-update-button primary", disabled: busy, onClick: () => void run(() => api.download()) }, "下载更新") : null, phase === "downloaded" ? /* @__PURE__ */ React.createElement("button", { className: "lbs-update-button primary", disabled: busy, onClick: () => void run(() => api.install()) }, "重启并安装") : null)), /* @__PURE__ */ React.createElement("label", { className: "lbs-update-option" }, /* @__PURE__ */ React.createElement("input", { type: "checkbox", checked: preferences.autoCheckUpdates !== false, disabled: !available, onChange: (event) => void toggleAutoCheck(event) }), "启动后自动检查更新(每天最多一次,不自动下载)")); + } + const inject = ["slots"]; + function apply(ctx) { + ctx.slots.inject("settings.section", () => ctx.slots.register({ + name: "settings.section", + id: "laobos-software-update", + order: 35, + label: () => "软件更新" + }, UpdateSettingsSection)); + } + exports.apply = apply; + exports.inject = inject; + return module.exports; + } + }); +})(); diff --git a/packages/laobos-updater/lib/index.js b/packages/laobos-updater/lib/index.js new file mode 100644 index 0000000..c4641b6 --- /dev/null +++ b/packages/laobos-updater/lib/index.js @@ -0,0 +1 @@ +export function apply() {} diff --git a/packages/laobos-updater/package.json b/packages/laobos-updater/package.json new file mode 100644 index 0000000..b7ea3b0 --- /dev/null +++ b/packages/laobos-updater/package.json @@ -0,0 +1,22 @@ +{ + "name": "@laobos/dsh-updater", + "version": "0.1.0", + "license": "SEE LICENSE IN ../../LICENSE", + "private": true, + "type": "module", + "main": "lib/index.js", + "exports": { + ".": "./lib/index.js", + "./client": "./lib/client.js", + "./package.json": "./package.json" + }, + "dsh": { + "client": { + "inject": [ + "@deepseek-ai/dsh-client-runtime", + "@deepseek-ai/dsh-client-ui-settings" + ], + "platform": "web" + } + } +} diff --git a/packages/laobos-updater/src/client.jsx b/packages/laobos-updater/src/client.jsx new file mode 100644 index 0000000..024faff --- /dev/null +++ b/packages/laobos-updater/src/client.jsx @@ -0,0 +1,153 @@ +/* eslint-disable @next/next/no-assign-module-variable -- DSH browser plugins use a CommonJS-style module factory */ +window.__ModuleLoader__.load({ + id: "@laobos/dsh-updater", + factory: (require) => { + var module = { exports: {} }; + var exports = module.exports; + Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); + const React = require("react"); + const { useCallback, useEffect, useState } = React; + + const css = ` + .lbs-update{display:flex;flex-direction:column;gap:12px} + .lbs-update-head{align-items:flex-start;display:flex;gap:14px;justify-content:space-between} + .lbs-update-title{font-size:13px;font-weight:600;line-height:20px}.lbs-update-sub{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:18px} + .lbs-update-version{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-line-border);border-radius:999px;color:var(--dsw-alias-label-secondary);font:11px/26px ui-monospace,SFMono-Regular,Menlo,monospace;padding:0 10px;white-space:nowrap} + .lbs-update-card{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-line-border);border-radius:10px;display:flex;flex-direction:column;gap:9px;padding:12px} + .lbs-update-status{align-items:center;display:flex;gap:8px}.lbs-update-dot{background:var(--dsw-alias-label-quaternary);border-radius:50%;height:8px;width:8px}.lbs-update-dot[data-active=true]{background:#2a9b67}.lbs-update-dot[data-error=true]{background:#d94b4b} + .lbs-update-status strong{font-size:12px;font-weight:600}.lbs-update-notes{color:var(--dsw-alias-label-secondary);font:11px/18px inherit;margin:0;max-height:160px;overflow:auto;white-space:pre-wrap} + .lbs-update-progress{background:var(--dsw-alias-bg-layer-1);border-radius:999px;height:6px;overflow:hidden}.lbs-update-progress>span{background:var(--dsw-alias-brand-primary);display:block;height:100%;transition:width .18s ease} + .lbs-update-actions{display:flex;flex-wrap:wrap;gap:8px}.lbs-update-button{appearance:none;background:transparent;border:1px solid var(--dsw-alias-line-border);border-radius:8px;color:inherit;cursor:pointer;font:11px inherit;height:31px;padding:0 11px}.lbs-update-button:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-update-button.primary{background:var(--dsw-alias-interactive-bg-primary);border-color:transparent;color:var(--dsw-alias-label-on-primary)}.lbs-update-button:disabled{cursor:not-allowed;opacity:.45} + .lbs-update-option{align-items:center;display:flex;font-size:11px;gap:8px}.lbs-update-option input{accent-color:var(--dsw-alias-brand-primary)}.lbs-update-error{color:#d94b4b;font-size:11px;line-height:18px} + `; + + const labels = { + disabled: "开发环境不启用自动更新", + idle: "尚未检查更新", + restoring: "正在恢复本地更新缓存…", + checking: "正在检查更新…", + available: "发现新版本", + downloading: "正在下载更新…", + downloaded: "更新已下载,可以安装", + installing: "正在退出并安装更新…", + "up-to-date": "当前已经是最新版本", + error: "更新失败", + }; + + function formatBytes(value) { + if (!Number.isFinite(value) || value <= 0) return "0 B"; + const units = ["B", "KB", "MB", "GB"]; + const index = Math.min(Math.floor(Math.log(value) / Math.log(1024)), units.length - 1); + return `${(value / (1024 ** index)).toFixed(index === 0 ? 0 : 1)} ${units[index]}`; + } + + function UpdateSettingsSection() { + const api = window.laobosDesktop?.updates; + const available = window.laobosDesktop?.capabilities?.softwareUpdate === true && Boolean(api); + const [state, setState] = useState(null); + const [preferences, setPreferences] = useState({ autoCheckUpdates: true }); + const [busy, setBusy] = useState(false); + const [localError, setLocalError] = useState(""); + + useEffect(() => { + if (!available) return undefined; + let active = true; + Promise.all([api.status(), api.preferences()]) + .then(([nextState, nextPreferences]) => { + if (!active) return; + setState(nextState); + setPreferences(nextPreferences); + }) + .catch((error) => active && setLocalError(error instanceof Error ? error.message : String(error))); + const remove = api.onState((next) => active && setState(next)); + return () => { + active = false; + remove?.(); + }; + }, [api, available]); + + const run = useCallback(async (action) => { + if (!available || busy) return; + setBusy(true); + setLocalError(""); + try { + const next = await action(); + if (next?.schema === 1) setState(next); + } catch (error) { + setLocalError(error instanceof Error ? error.message : String(error)); + } finally { + setBusy(false); + } + }, [available, busy]); + + async function toggleAutoCheck(event) { + const autoCheckUpdates = event.target.checked; + setPreferences((current) => ({ ...current, autoCheckUpdates })); + try { + const next = await api.setPreferences({ autoCheckUpdates }); + setPreferences(next); + } catch (error) { + setPreferences((current) => ({ ...current, autoCheckUpdates: !autoCheckUpdates })); + setLocalError(error instanceof Error ? error.message : String(error)); + } + } + + const phase = state?.phase || (available ? "idle" : "disabled"); + const progress = state?.progress; + const percent = Math.max(0, Math.min(100, progress?.percent || 0)); + const error = localError || state?.error?.message || ""; + const active = ["restoring", "available", "downloading", "downloaded", "installing", "up-to-date"].includes(phase); + + return ( +
+ +
+
+
软件更新
+
从劳博士官方 GitHub Release 获取经过签名的软件版本。
+
+ v{state?.currentVersion || "—"} +
+
+
+ + {labels[phase] || "更新状态未知"} +
+ {state?.availableVersion ?
可用版本:v{state.availableVersion}{state.releaseDate ? ` · ${state.releaseDate.slice(0, 10)}` : ""}
: null} + {state?.cached ?
安装包已安全缓存到本地,重启应用后无需重新下载。
: null} + {state?.releaseNotes ?
{state.releaseNotes}
: null} + {phase === "downloading" ? ( + <> +
+
{percent.toFixed(1)}% · {formatBytes(progress?.transferred)} / {formatBytes(progress?.total)} · {formatBytes(progress?.bytesPerSecond)}/s
+ + ) : null} + {error ?
{error}
: null} +
+ + {phase === "available" ? : null} + {phase === "downloaded" ? : null} +
+
+ +
+ ); + } + + const inject = ["slots"]; + function apply(ctx) { + ctx.slots.inject("settings.section", () => ctx.slots.register({ + name: "settings.section", + id: "laobos-software-update", + order: 35, + label: () => "软件更新", + }, UpdateSettingsSection)); + } + exports.apply = apply; + exports.inject = inject; + return module.exports; + }, +}); diff --git a/packages/laobos-workspace-tools/lib/client.js b/packages/laobos-workspace-tools/lib/client.js index 214eaf3..6caa3ae 100644 --- a/packages/laobos-workspace-tools/lib/client.js +++ b/packages/laobos-workspace-tools/lib/client.js @@ -1,5 +1,152 @@ /* eslint-disable @next/next/no-assign-module-variable -- generated DSH module factory */ (() => { + // packages/laobos-workspace-tools/src/code-renderer.mjs + var EXTENSION_LANGUAGE = /* @__PURE__ */ new Map([ + ["js", "javascript"], + ["jsx", "javascript"], + ["mjs", "javascript"], + ["cjs", "javascript"], + ["ts", "typescript"], + ["tsx", "typescript"], + ["json", "json"], + ["jsonc", "json"], + ["py", "python"], + ["rb", "ruby"], + ["rs", "rust"], + ["go", "go"], + ["java", "java"], + ["kt", "kotlin"], + ["kts", "kotlin"], + ["c", "c"], + ["h", "c"], + ["cc", "cpp"], + ["cpp", "cpp"], + ["cxx", "cpp"], + ["hpp", "cpp"], + ["css", "css"], + ["scss", "css"], + ["less", "css"], + ["html", "markup"], + ["htm", "markup"], + ["xml", "markup"], + ["svg", "markup"], + ["md", "markdown"], + ["mdx", "markdown"], + ["yaml", "yaml"], + ["yml", "yaml"], + ["toml", "toml"], + ["sh", "shell"], + ["bash", "shell"], + ["zsh", "shell"], + ["fish", "shell"], + ["sql", "sql"], + ["graphql", "graphql"], + ["gql", "graphql"] + ]); + var KEYWORDS = new Set(` + abstract as async await break case catch class const continue debugger default delete do else + enum export extends false finally for from function get if implements import in instanceof interface + let new null of package private protected public readonly return set static super switch this throw true + try type typeof undefined var void while with yield + and assert def del elif except False finally for from global if import in is lambda None nonlocal not or + pass raise return True try while with yield + bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort + fn impl match mod move mut pub ref self Self struct trait use where + func go map range select chan defer fallthrough package + SELECT FROM WHERE JOIN LEFT RIGHT INNER OUTER ON AS INSERT UPDATE DELETE CREATE ALTER DROP TABLE + INTO VALUES SET AND OR NOT NULL PRIMARY KEY FOREIGN REFERENCES GROUP BY ORDER LIMIT OFFSET HAVING +`.trim().split(/\s+/u)); + function languageForPath(filePath = "") { + const clean = String(filePath).split(/[?#]/u)[0]; + const name = clean.split(/[\\/]/u).at(-1)?.toLowerCase() || ""; + if (["dockerfile", "makefile", "procfile"].includes(name)) return "shell"; + const extension = name.includes(".") ? name.split(".").at(-1) : ""; + return EXTENSION_LANGUAGE.get(extension) || "text"; + } + function isCodePath(filePath = "") { + return languageForPath(filePath) !== "text"; + } + function tokenizeCodeLine(value, language = "text") { + const text = String(value ?? ""); + if (!text || language === "text") return [{ type: "plain", value: text }]; + const commentMarker = ["python", "ruby", "shell", "yaml", "toml"].includes(language) ? "#" : "//"; + const pattern = commentMarker === "#" ? /(`(?:\\.|[^`\\])*`|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|#.*$|\b(?:0x[\da-f]+|\d+(?:\.\d+)?)\b|\b[A-Za-z_$][\w$]*\b)/giu : /(`(?:\\.|[^`\\])*`|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\/\/.*$|\/\*.*?\*\/|\b(?:0x[\da-f]+|\d+(?:\.\d+)?)\b|\b[A-Za-z_$][\w$]*\b)/giu; + const tokens = []; + let cursor = 0; + for (const match of text.matchAll(pattern)) { + if (match.index > cursor) tokens.push({ type: "plain", value: text.slice(cursor, match.index) }); + const token = match[0]; + let type = "plain"; + if (token.startsWith(commentMarker) || token.startsWith("/*")) type = "comment"; + else if (/^[`"']/u.test(token)) type = "string"; + else if (/^(?:\d|0x)/iu.test(token)) type = "number"; + else if (KEYWORDS.has(token) || KEYWORDS.has(token.toUpperCase())) type = "keyword"; + else if (/^[A-Z]/u.test(token)) type = "type"; + else if (text.slice((match.index || 0) + token.length).trimStart().startsWith("(")) type = "function"; + tokens.push({ type, value: token }); + cursor = (match.index || 0) + token.length; + } + if (cursor < text.length) tokens.push({ type: "plain", value: text.slice(cursor) }); + return tokens.length ? tokens : [{ type: "plain", value: text }]; + } + function parseUnifiedDiff(value, fallbackPath = "") { + const rawLines = String(value || "").replace(/\r\n?/gu, "\n").split("\n"); + const lines = []; + let oldLine = null; + let newLine = null; + let currentPath = fallbackPath; + let additions = 0; + let deletions = 0; + for (let index = 0; index < rawLines.length; index += 1) { + const raw = rawLines[index]; + const hunk = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@(.*)$/u.exec(raw); + if (hunk) { + oldLine = Number(hunk[1]); + newLine = Number(hunk[2]); + lines.push({ key: index, type: "hunk", oldLine: null, newLine: null, prefix: "", content: raw, path: currentPath }); + continue; + } + if (raw.startsWith("+++ ")) { + const candidate = raw.slice(4).replace(/^b\//u, ""); + if (candidate !== "/dev/null") currentPath = candidate; + lines.push({ key: index, type: "file", oldLine: null, newLine: null, prefix: "", content: raw, path: currentPath }); + continue; + } + if (raw.startsWith("--- ") || raw.startsWith("diff --git ")) { + if (raw.startsWith("diff --git ")) { + oldLine = null; + newLine = null; + } + lines.push({ key: index, type: "file", oldLine: null, newLine: null, prefix: "", content: raw, path: currentPath }); + continue; + } + if (oldLine !== null && raw.startsWith("+") && !raw.startsWith("+++")) { + lines.push({ key: index, type: "insert", oldLine: null, newLine, prefix: "+", content: raw.slice(1), path: currentPath }); + newLine += 1; + additions += 1; + continue; + } + if (oldLine !== null && raw.startsWith("-") && !raw.startsWith("---")) { + lines.push({ key: index, type: "delete", oldLine, newLine: null, prefix: "-", content: raw.slice(1), path: currentPath }); + oldLine += 1; + deletions += 1; + continue; + } + if (oldLine !== null && raw.startsWith(" ")) { + lines.push({ key: index, type: "normal", oldLine, newLine, prefix: " ", content: raw.slice(1), path: currentPath }); + oldLine += 1; + newLine += 1; + continue; + } + const type = raw.startsWith("\\ No newline") ? "notice" : "meta"; + lines.push({ key: index, type, oldLine: null, newLine: null, prefix: "", content: raw, path: currentPath }); + } + return { lines, additions, deletions }; + } + function codeLines(value) { + return String(value ?? "").replace(/\r\n?/gu, "\n").split("\n"); + } + // packages/laobos-workspace-tools/src/client.jsx window.__ModuleLoader__.load({ id: "@laobos/dsh-workspace-tools", @@ -10,9 +157,15 @@ const React = require2("react"); const { useCallback, useEffect, useMemo, useState } = React; const css = ` - .lbs-workbench{background:var(--dsw-alias-bg-base);bottom:0;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483030}.lbs-workbench-header{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;flex:none;gap:8px;height:56px;padding:0 18px}.lbs-workbench-header strong{font-size:15px}.lbs-workbench-close{margin-left:auto}.lbs-workbench-body{display:flex;flex:1;min-height:0}.lbs-files-list{border-right:1px solid var(--dsw-alias-border-l1);box-sizing:border-box;display:flex;flex-direction:column;min-width:250px;width:34%}.lbs-files-toolbar,.lbs-git-toolbar{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;gap:6px;min-height:43px;padding:0 10px}.lbs-files-path{color:var(--dsw-alias-label-secondary);flex:1;font:11px ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-file-rows{flex:1;overflow:auto;padding:5px}.lbs-file-row{align-items:center;appearance:none;background:transparent;border:0;border-radius:6px;color:inherit;cursor:pointer;display:flex;font:inherit;font-size:12px;gap:7px;height:29px;padding:0 8px;text-align:left;width:100%}.lbs-file-row:hover,.lbs-file-row[data-active=true]{background:var(--dsw-alias-interactive-bg-hover)}.lbs-file-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-file-size{color:var(--dsw-alias-label-tertiary);font-size:10px}.lbs-preview{box-sizing:border-box;flex:1;min-width:0;overflow:auto;padding:16px}.lbs-preview-empty{align-items:center;color:var(--dsw-alias-label-tertiary);display:flex;height:100%;justify-content:center;text-align:center}.lbs-preview-title{align-items:center;display:flex;gap:8px;margin-bottom:12px}.lbs-preview-title strong{font-size:14px}.lbs-preview-title .lbs-wb-button{margin-left:auto}.lbs-preview pre,.lbs-git-diff{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:9px;box-sizing:border-box;font:12px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;margin:0;overflow:auto;padding:12px;tab-size:2;white-space:pre}.lbs-preview img,.lbs-preview video{display:block;height:auto;margin:auto;max-height:calc(100vh - 130px);max-width:100%}.lbs-preview iframe{border:1px solid var(--dsw-alias-border-l1);height:calc(100vh - 115px);width:100%}.lbs-preview audio{margin:40px auto;max-width:620px;width:100%} + .lbs-workbench{background:var(--dsw-alias-bg-base);bottom:0;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483030}.lbs-workbench-header{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;flex:none;gap:8px;height:56px;padding:0 18px}.lbs-workbench-header strong{font-size:15px}.lbs-workbench-close{margin-left:auto}.lbs-workbench-body{display:flex;flex:1;min-height:0}.lbs-files-list{border-right:1px solid var(--dsw-alias-border-l1);box-sizing:border-box;display:flex;flex-direction:column;min-width:250px;width:34%}.lbs-files-toolbar,.lbs-git-toolbar{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;gap:6px;min-height:43px;padding:0 10px}.lbs-files-path{color:var(--dsw-alias-label-secondary);flex:1;font:11px ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-file-rows{flex:1;overflow:auto;padding:5px}.lbs-file-row{align-items:center;appearance:none;background:transparent;border:0;border-radius:6px;color:inherit;cursor:pointer;display:flex;font:inherit;font-size:12px;gap:7px;height:29px;padding:0 8px;text-align:left;width:100%}.lbs-file-row:hover,.lbs-file-row[data-active=true]{background:var(--dsw-alias-interactive-bg-hover)}.lbs-file-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-file-size{color:var(--dsw-alias-label-tertiary);font-size:10px}.lbs-preview{box-sizing:border-box;flex:1;min-width:0;overflow:auto;padding:16px}.lbs-preview-empty{align-items:center;color:var(--dsw-alias-label-tertiary);display:flex;height:100%;justify-content:center;text-align:center}.lbs-preview-title{align-items:center;display:flex;gap:8px;margin-bottom:12px}.lbs-preview-title strong{font-size:14px}.lbs-preview-actions{align-items:center;display:flex;gap:5px;margin-left:auto}.lbs-preview pre,.lbs-git-diff{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:9px;box-sizing:border-box;font:12px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;margin:0;overflow:auto;padding:12px;tab-size:2;white-space:pre}.lbs-preview img,.lbs-preview video{display:block;height:auto;margin:auto;max-height:calc(100vh - 130px);max-width:100%}.lbs-preview iframe{border:1px solid var(--dsw-alias-border-l1);height:calc(100vh - 115px);width:100%}.lbs-preview audio{margin:40px auto;max-width:620px;width:100%}.lbs-preview-editor{background:var(--dsw-alias-markdown-code-block,var(--dsw-alias-bg-layer-1));border:1px solid var(--dsw-alias-border-l2);border-radius:9px;box-sizing:border-box;color:var(--dsw-alias-label-primary);font:12px/1.58 ui-monospace,SFMono-Regular,Menlo,monospace;height:calc(100vh - 145px);min-height:280px;outline:none;padding:12px;resize:none;tab-size:2;width:100%}.lbs-preview-editor:focus{border-color:var(--dsw-alias-border-l3);box-shadow:0 0 0 2px color-mix(in srgb,var(--dsw-alias-brand-primary) 16%,transparent)} .lbs-wb-button{appearance:none;background:transparent;border:0;border-radius:7px;color:inherit;cursor:pointer;font:inherit;font-size:11px;min-height:31px;padding:0 9px}.lbs-wb-button:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-wb-button.primary{background:var(--dsw-alias-interactive-bg-primary);color:var(--dsw-alias-label-on-primary)}.lbs-wb-button.danger{color:#d94b4b}.lbs-wb-button:disabled{cursor:not-allowed;opacity:.38}.lbs-wb-error{background:rgba(218,70,70,.1);border-radius:8px;color:#d94b4b;font-size:11px;line-height:1.5;margin:8px;padding:9px}.lbs-wb-ok{background:rgba(52,163,105,.1);border-radius:8px;color:#38a76f;font-size:11px;margin:8px;padding:9px} .lbs-git-layout{display:grid;flex:1;grid-template-columns:minmax(310px,37%) minmax(0,1fr);min-height:0}.lbs-git-sidebar{border-right:1px solid var(--dsw-alias-border-l1);display:flex;flex-direction:column;min-height:0}.lbs-git-toolbar{flex-wrap:wrap}.lbs-git-toolbar select,.lbs-git-commit-box textarea{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;color:inherit;font:inherit}.lbs-git-toolbar select{font-size:11px;height:29px;max-width:150px;padding:0 7px}.lbs-git-toolbar-spacer{flex:1}.lbs-git-scroll{flex:1;min-height:0;overflow:auto;padding:7px 9px}.lbs-git-section{margin-bottom:15px}.lbs-git-section-head{align-items:center;color:var(--dsw-alias-label-secondary);display:flex;font-size:10px;font-weight:600;height:27px;letter-spacing:.03em;padding:0 5px;text-transform:uppercase}.lbs-git-section-head span{margin-left:auto}.lbs-git-change,.lbs-git-history{align-items:center;appearance:none;background:transparent;border:0;border-radius:6px;color:inherit;cursor:pointer;display:grid;font:inherit;text-align:left;width:100%}.lbs-git-change{grid-template-columns:28px minmax(0,1fr) auto;min-height:34px;padding:4px 5px}.lbs-git-change:hover,.lbs-git-change[data-active=true],.lbs-git-history:hover,.lbs-git-history[data-active=true]{background:var(--dsw-alias-interactive-bg-hover)}.lbs-git-code{font:10px ui-monospace,SFMono-Regular,Menlo,monospace}.lbs-git-change-name,.lbs-git-history strong{font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-git-change-sub,.lbs-git-history small{color:var(--dsw-alias-label-tertiary);display:block;font-size:9px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-git-row-action{appearance:none;background:transparent;border:0;border-radius:5px;color:var(--dsw-alias-label-secondary);cursor:pointer;font-size:9px;height:25px;opacity:.2;padding:0 6px}.lbs-git-change:hover .lbs-git-row-action,.lbs-git-row-action:focus-visible{opacity:1}.lbs-git-history{display:block;padding:6px}.lbs-git-commit-box{border-top:1px solid var(--dsw-alias-border-l1);display:grid;gap:7px;padding:9px}.lbs-git-commit-box textarea{box-sizing:border-box;font-size:11px;line-height:1.45;min-height:58px;padding:7px;resize:vertical;width:100%}.lbs-git-commit-actions{align-items:center;display:flex;gap:6px}.lbs-git-commit-actions span{color:var(--dsw-alias-label-tertiary);font-size:9px;margin-right:auto}.lbs-git-main{display:flex;flex-direction:column;min-width:0}.lbs-git-diff-head{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;gap:8px;min-height:43px;padding:0 13px}.lbs-git-diff-head strong{font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-git-diff-head span{color:var(--dsw-alias-label-tertiary);font-size:9px}.lbs-git-diff{border:0;border-radius:0;flex:1;min-height:0}.lbs-git-onboarding{align-content:center;display:grid;gap:12px;height:100%;justify-items:center;padding:30px;text-align:center}.lbs-git-onboarding strong{font-size:16px}.lbs-git-onboarding p{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6;margin:0;max-width:480px}.lbs-git-badge{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:4px;color:var(--dsw-alias-label-secondary);font-size:9px;padding:2px 5px}.lbs-git-loading{opacity:.58;pointer-events:none} + .lbs-files-list{min-width:280px;width:32%}.lbs-files-toolbar{min-height:46px}.lbs-file-tree{flex:1;overflow:auto;padding:6px 5px 14px}.lbs-file-root-row,.lbs-tree-row{align-items:center;border-radius:6px;box-sizing:border-box;display:flex;min-width:max-content;width:100%}.lbs-file-root-row{color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:600;height:31px;padding:0 8px}.lbs-tree-row{height:29px;padding-right:7px}.lbs-tree-row:hover,.lbs-tree-row[data-active=true]{background:var(--dsw-alias-interactive-bg-hover)}.lbs-tree-toggle,.lbs-tree-file{align-items:center;appearance:none;background:transparent;border:0;color:inherit;cursor:pointer;display:flex;font:inherit;height:100%;min-width:0;padding:0;text-align:left}.lbs-tree-toggle{flex:1}.lbs-tree-chevron{color:var(--dsw-alias-label-tertiary);display:inline-flex;flex:none;font-size:10px;justify-content:center;width:18px}.lbs-tree-icon{align-items:center;color:var(--dsw-alias-label-secondary);display:inline-flex;flex:none;font:10px/1 ui-monospace,SFMono-Regular,Menlo,monospace;height:18px;justify-content:center;margin-right:5px;width:18px}.lbs-tree-row[data-type=directory] .lbs-tree-icon{color:#d6a84b;font-size:15px}.lbs-tree-row[data-code=true] .lbs-tree-icon{color:#6f8cff}.lbs-tree-name{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-tree-file{flex:1}.lbs-tree-size{color:var(--dsw-alias-label-tertiary);font-size:9px;margin-left:10px}.lbs-tree-loading{animation:lbs-tree-spin .8s linear infinite;display:inline-block}@keyframes lbs-tree-spin{to{transform:rotate(360deg)}} + .lbs-file-menu{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:9px;box-shadow:var(--dsw-shadow-lv3);display:grid;min-width:190px;padding:5px;position:fixed;z-index:2147483200}.lbs-file-menu button{appearance:none;background:transparent;border:0;border-radius:6px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;font-size:11px;height:30px;padding:0 9px;text-align:left}.lbs-file-menu button:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-file-menu button.danger{color:var(--dsw-alias-state-error-primary,#d94b4b)}.lbs-file-menu-separator{border-top:1px solid var(--dsw-alias-border-l1);margin:4px 3px} + .lbs-workbench{--lbs-code-keyword:#cf222e;--lbs-code-string:#0a3069;--lbs-code-number:#0550ae;--lbs-code-comment:#6e7781;--lbs-code-type:#953800;--lbs-code-function:#8250df;--lbs-diff-add:#1a7f37;--lbs-diff-delete:#cf222e;--lbs-diff-hunk:#0969da;--lbs-diff-file:#8250df;--lbs-diff-insert-bg:rgba(46,160,67,.1);--lbs-diff-insert-gutter:rgba(46,160,67,.16);--lbs-diff-delete-bg:rgba(248,81,73,.1);--lbs-diff-delete-gutter:rgba(248,81,73,.16);--lbs-diff-hunk-bg:rgba(9,105,218,.08)}body[data-ds-dark-theme] .lbs-workbench{--lbs-code-keyword:#ff7b72;--lbs-code-string:#a5d6ff;--lbs-code-number:#79c0ff;--lbs-code-comment:#8b949e;--lbs-code-type:#ffa657;--lbs-code-function:#d2a8ff;--lbs-diff-add:#56d364;--lbs-diff-delete:#ff7b72;--lbs-diff-hunk:#79c0ff;--lbs-diff-file:#d2a8ff;--lbs-diff-insert-bg:rgba(46,160,67,.17);--lbs-diff-insert-gutter:rgba(46,160,67,.24);--lbs-diff-delete-bg:rgba(248,81,73,.16);--lbs-diff-delete-gutter:rgba(248,81,73,.23);--lbs-diff-hunk-bg:rgba(56,139,253,.13)} + .lbs-code-viewer{background:var(--dsw-alias-markdown-code-block,var(--dsw-alias-bg-layer-1));border:1px solid var(--dsw-alias-border-l2);border-radius:9px;color:var(--dsw-alias-label-primary);min-width:max-content;overflow:auto}.lbs-code-language{align-items:center;background:var(--dsw-alias-markdown-code-block-banner,var(--dsw-alias-bg-layer-2));border-bottom:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);display:flex;font:10px/28px ui-monospace,SFMono-Regular,Menlo,monospace;height:28px;justify-content:space-between;padding:0 10px;position:sticky;left:0}.lbs-code-row{display:grid;font:12px/1.58 ui-monospace,SFMono-Regular,Menlo,monospace;grid-template-columns:52px minmax(max-content,1fr);min-height:19px}.lbs-code-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-code-line-number{border-right:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary));padding:0 10px;text-align:right;user-select:none}.lbs-code-line{padding:0 12px;white-space:pre}.lbs-code-truncated{background:var(--dsw-alias-markdown-code-block-banner,var(--dsw-alias-bg-layer-2));color:var(--dsw-alias-label-tertiary);font-size:11px;padding:8px 12px;position:sticky;left:0}.lbs-token-keyword{color:var(--lbs-code-keyword)}.lbs-token-string{color:var(--lbs-code-string)}.lbs-token-number{color:var(--lbs-code-number)}.lbs-token-comment{color:var(--lbs-code-comment);font-style:italic}.lbs-token-type{color:var(--lbs-code-type)}.lbs-token-function{color:var(--lbs-code-function)} + .lbs-diff-viewer{background:var(--dsw-alias-markdown-code-block,var(--dsw-alias-bg-layer-1));color:var(--dsw-alias-label-primary);display:flex;flex:1;flex-direction:column;min-height:0}.lbs-diff-summary{align-items:center;background:var(--dsw-alias-markdown-code-block-banner,var(--dsw-alias-bg-layer-2));border-bottom:1px solid var(--dsw-alias-border-l2);display:flex;flex:none;gap:10px;height:34px;padding:0 10px}.lbs-diff-summary span{font:10px ui-monospace,SFMono-Regular,Menlo,monospace}.lbs-diff-additions{color:var(--lbs-diff-add)}.lbs-diff-deletions{color:var(--lbs-diff-delete)}.lbs-diff-summary button{background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:5px;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;font-size:10px;line-height:23px;margin-left:auto;padding:0 8px}.lbs-diff-summary button:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-diff-scroll{flex:1;min-height:0;overflow:auto}.lbs-diff-table{border-collapse:collapse;font:12px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace;min-width:100%;table-layout:auto}.lbs-diff-row td{height:20px;padding:0}.lbs-diff-gutter{background:var(--dsw-alias-markdown-code-block,var(--dsw-alias-bg-layer-1));border-right:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary));min-width:43px;padding:0 8px!important;text-align:right;user-select:none;width:43px}.lbs-diff-prefix{color:var(--dsw-alias-label-tertiary);text-align:center;user-select:none;width:24px}.lbs-diff-code{padding-right:14px!important;white-space:pre}.lbs-diff-viewer[data-wrap=true] .lbs-diff-code{overflow-wrap:anywhere;white-space:pre-wrap}.lbs-diff-row[data-type=insert]{background:var(--lbs-diff-insert-bg)}.lbs-diff-row[data-type=insert] .lbs-diff-gutter{background:var(--lbs-diff-insert-gutter);color:var(--lbs-diff-add)}.lbs-diff-row[data-type=insert] .lbs-diff-prefix{color:var(--lbs-diff-add)}.lbs-diff-row[data-type=delete]{background:var(--lbs-diff-delete-bg)}.lbs-diff-row[data-type=delete] .lbs-diff-gutter{background:var(--lbs-diff-delete-gutter);color:var(--lbs-diff-delete)}.lbs-diff-row[data-type=delete] .lbs-diff-prefix{color:var(--lbs-diff-delete)}.lbs-diff-row[data-type=hunk]{background:var(--lbs-diff-hunk-bg);color:var(--lbs-diff-hunk)}.lbs-diff-row[data-type=file]{background:var(--dsw-alias-markdown-code-block-banner,var(--dsw-alias-bg-layer-2));color:var(--lbs-diff-file);font-weight:600}.lbs-diff-row[data-type=meta],.lbs-diff-row[data-type=notice]{color:var(--dsw-alias-label-tertiary)}.lbs-diff-row[data-type=hunk] .lbs-diff-code,.lbs-diff-row[data-type=file] .lbs-diff-code,.lbs-diff-row[data-type=meta] .lbs-diff-code,.lbs-diff-row[data-type=notice] .lbs-diff-code{padding:2px 12px!important}.lbs-diff-row:hover{box-shadow:inset 0 0 0 9999px color-mix(in srgb,var(--dsw-alias-label-primary) 3%,transparent)} + .lbs-git-change[data-status=A] .lbs-git-code,.lbs-git-change[data-status=U] .lbs-git-code{color:#2a9b67}.lbs-git-change[data-status=M] .lbs-git-code{color:#6f8cff}.lbs-git-change[data-status=D] .lbs-git-code{color:#d94b4b}.lbs-git-change[data-status=R] .lbs-git-code{color:#a675d1} @media(max-width:850px){.lbs-workbench{left:0;right:0}.lbs-workbench-body,.lbs-git-layout{display:flex;flex-direction:column}.lbs-files-list,.lbs-git-sidebar{border-bottom:1px solid var(--dsw-alias-border-l1);border-right:0;max-height:46vh;width:100%}.lbs-git-main{min-height:42vh}} `; if (typeof document !== "undefined" && !document.querySelector('style[data-plugin-css="@laobos/dsh-workspace-tools"]')) { @@ -27,11 +180,45 @@ return text.replace(/^Error invoking remote method '[^']+': Error:\s*/u, ""); }; const formatSize = (value) => value < 1024 ? `${value} B` : value < 1024 ** 2 ? `${(value / 1024).toFixed(1)} KB` : `${(value / 1024 ** 2).toFixed(1)} MB`; - const parentPath = (value) => { - const parts = String(value || ".").split("/").filter((part) => part && part !== "."); - parts.pop(); - return parts.join("/") || "."; + const absolutePathPattern = /^(?:\/|[a-zA-Z]:[\\/]|\\\\)/u; + const pathSeparator = (root) => String(root || "").includes("\\") ? "\\" : "/"; + const absoluteWorkspacePath = (root, target) => { + const value = String(target || "."); + if (!root || absolutePathPattern.test(value)) return value; + if (value === ".") return root; + const separator = pathSeparator(root); + return `${String(root).replace(/[\\/]+$/u, "")}${separator}${value.replace(/^[.][\\/]/u, "")}`; + }; + const relativeWorkspacePath = (root, target) => { + const value = String(target || "."); + if (!root) return value; + if (!absolutePathPattern.test(value)) return value.replace(/^[.][\\/]/u, "") || "."; + const windows = pathSeparator(root) === "\\"; + const normalizedRoot = String(root || "").replaceAll("\\", "/").replace(/\/+$/u, ""); + const normalizedTarget = value.replaceAll("\\", "/"); + const comparableRoot = windows ? normalizedRoot.toLowerCase() : normalizedRoot; + const comparableTarget = windows ? normalizedTarget.toLowerCase() : normalizedTarget; + if (comparableTarget === comparableRoot) return "."; + if (comparableTarget.startsWith(`${comparableRoot}/`)) return normalizedTarget.slice(normalizedRoot.length + 1).replaceAll("/", pathSeparator(root)); + return value; }; + const parentWorkspacePath = (value) => { + const parts = String(value || ".").split(/[\\/]/u).filter(Boolean); + return parts.length <= 1 ? "." : parts.slice(0, -1).join(String(value).includes("\\") ? "\\" : "/"); + }; + async function openProducedFile(path) { + const sessions = module.ctx?.sessions?.list?.getSnapshot?.(); + const cwd = sessions?.current ? sessions.byId?.[sessions.current]?.cwd : void 0; + const target = absoluteWorkspacePath(cwd, path); + try { + if (!module.ctx?.workspaces?.openPath) throw new Error("系统文件打开器不可用"); + await module.ctx.workspaces.openPath(target); + } catch { + window.dispatchEvent(new CustomEvent("laobos:open-desktop-tool", { + detail: { tool: "files", cwd, path, source: "file-open-fallback" } + })); + } + } function useDesktopContext() { const [context, setContext] = useState(null); const [error, setError] = useState(""); @@ -48,7 +235,39 @@ }, [refresh]); return { context, error }; } - function Preview({ selected, value, onReveal }) { + function CodeTokens({ value, language }) { + return tokenizeCodeLine(value, language).map((token, index) => /* @__PURE__ */ React.createElement("span", { className: `lbs-token-${token.type}`, key: `${index}:${token.value}` }, token.value)); + } + function CodeViewer({ value, path }) { + const language = languageForPath(path); + const lines = useMemo(() => codeLines(value), [value]); + const visibleLines = lines.slice(0, 6e3); + return /* @__PURE__ */ React.createElement("div", { className: "lbs-code-viewer", "aria-label": `${path} 代码预览` }, /* @__PURE__ */ React.createElement("div", { className: "lbs-code-language" }, /* @__PURE__ */ React.createElement("span", null, language), /* @__PURE__ */ React.createElement("span", null, lines.length, " 行")), visibleLines.map((line, index) => /* @__PURE__ */ React.createElement("div", { className: "lbs-code-row", key: index }, /* @__PURE__ */ React.createElement("span", { className: "lbs-code-line-number" }, index + 1), /* @__PURE__ */ React.createElement("code", { className: "lbs-code-line" }, /* @__PURE__ */ React.createElement(CodeTokens, { value: line, language })))), lines.length > visibleLines.length ? /* @__PURE__ */ React.createElement("div", { className: "lbs-code-truncated" }, "文件较大,仅渲染前 ", visibleLines.length, " 行;可在系统编辑器中查看完整内容。") : null); + } + function DiffViewer({ value, path }) { + const [wrap, setWrap] = useState(false); + const model = useMemo(() => parseUnifiedDiff(value, path), [value, path]); + const visibleLines = model.lines.slice(0, 12e3); + return /* @__PURE__ */ React.createElement("div", { className: "lbs-diff-viewer", "data-wrap": wrap }, /* @__PURE__ */ React.createElement("div", { className: "lbs-diff-summary" }, /* @__PURE__ */ React.createElement("span", { className: "lbs-diff-additions" }, "+", model.additions, " 添加"), /* @__PURE__ */ React.createElement("span", { className: "lbs-diff-deletions" }, "−", model.deletions, " 删除"), /* @__PURE__ */ React.createElement("span", null, model.lines.length, " 行"), /* @__PURE__ */ React.createElement("button", { type: "button", onClick: () => setWrap((value2) => !value2) }, wrap ? "不换行" : "自动换行")), /* @__PURE__ */ React.createElement("div", { className: "lbs-diff-scroll" }, /* @__PURE__ */ React.createElement("table", { className: "lbs-diff-table", "aria-label": "Git 变更内容" }, /* @__PURE__ */ React.createElement("tbody", null, visibleLines.map((line) => { + const codeLine = ["insert", "delete", "normal"].includes(line.type); + const language = languageForPath(line.path || path); + return /* @__PURE__ */ React.createElement("tr", { className: "lbs-diff-row", "data-type": line.type, key: line.key }, /* @__PURE__ */ React.createElement("td", { className: "lbs-diff-gutter" }, line.oldLine ?? ""), /* @__PURE__ */ React.createElement("td", { className: "lbs-diff-gutter" }, line.newLine ?? ""), codeLine ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("td", { className: "lbs-diff-prefix" }, line.prefix), /* @__PURE__ */ React.createElement("td", { className: "lbs-diff-code" }, /* @__PURE__ */ React.createElement("code", null, /* @__PURE__ */ React.createElement(CodeTokens, { value: line.content, language })))) : /* @__PURE__ */ React.createElement("td", { className: "lbs-diff-code", colSpan: 2 }, line.content)); + }))), model.lines.length > visibleLines.length ? /* @__PURE__ */ React.createElement("div", { className: "lbs-code-truncated" }, "Diff 较大,仅渲染前 ", visibleLines.length, " 行。") : null)); + } + function fileGlyph(entry) { + if (entry.type === "directory") return "▰"; + if (isCodePath(entry.path)) return "{}"; + const extension = entry.name.split(".").at(-1)?.toLowerCase(); + if (["png", "jpg", "jpeg", "gif", "webp", "svg"].includes(extension)) return "▧"; + return "·"; + } + function FileTreeNode({ entry, depth, childrenByPath, expanded, loadingPaths, selected, onToggle, onSelect, onContextMenu }) { + const isDirectory = entry.type === "directory"; + const isExpanded = isDirectory && expanded.has(entry.path); + const children = childrenByPath[entry.path] || []; + return /* @__PURE__ */ React.createElement("div", { role: "treeitem", "aria-expanded": isDirectory ? isExpanded : void 0, "aria-selected": !isDirectory && selected === entry.path }, /* @__PURE__ */ React.createElement("div", { className: "lbs-tree-row", "data-active": selected === entry.path, "data-code": !isDirectory && isCodePath(entry.path), "data-type": entry.type, onContextMenu: (event) => onContextMenu(event, entry), style: { paddingLeft: 8 + depth * 16 } }, isDirectory ? /* @__PURE__ */ React.createElement("button", { type: "button", className: "lbs-tree-toggle", onClick: () => onToggle(entry), title: entry.path }, /* @__PURE__ */ React.createElement("span", { className: "lbs-tree-chevron" }, loadingPaths.has(entry.path) ? /* @__PURE__ */ React.createElement("span", { className: "lbs-tree-loading" }, "◌") : isExpanded ? "▾" : "▸"), /* @__PURE__ */ React.createElement("span", { className: "lbs-tree-icon" }, fileGlyph(entry)), /* @__PURE__ */ React.createElement("span", { className: "lbs-tree-name" }, entry.name)) : /* @__PURE__ */ React.createElement("button", { type: "button", className: "lbs-tree-file", onClick: () => onSelect(entry), title: entry.path }, /* @__PURE__ */ React.createElement("span", { className: "lbs-tree-chevron" }), /* @__PURE__ */ React.createElement("span", { className: "lbs-tree-icon" }, fileGlyph(entry)), /* @__PURE__ */ React.createElement("span", { className: "lbs-tree-name" }, entry.name)), !isDirectory ? /* @__PURE__ */ React.createElement("span", { className: "lbs-tree-size" }, formatSize(entry.size)) : null), isExpanded ? /* @__PURE__ */ React.createElement("div", { role: "group" }, children.map((child) => /* @__PURE__ */ React.createElement(FileTreeNode, { key: child.path, entry: child, depth: depth + 1, childrenByPath, expanded, loadingPaths, selected, onToggle, onSelect, onContextMenu }))) : null); + } + function Preview({ selected, value, editing, draft, saving, onBeginEdit, onDraftChange, onSave, onCancelEdit, onReveal }) { const source = useMemo(() => { if (!value?.base64) return ""; const binary = atob(value.base64); @@ -60,54 +279,199 @@ if (source) URL.revokeObjectURL(source); }, [source]); if (!selected) return /* @__PURE__ */ React.createElement("div", { className: "lbs-preview-empty" }, "选择文件以预览"); - return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { className: "lbs-preview-title" }, /* @__PURE__ */ React.createElement("strong", null, selected), value ? /* @__PURE__ */ React.createElement("span", { className: "lbs-file-size" }, formatSize(value.size)) : null, /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: onReveal }, "在系统中显示")), !value ? /* @__PURE__ */ React.createElement("div", { className: "lbs-preview-empty" }, "正在读取…") : value.kind === "text" ? /* @__PURE__ */ React.createElement("pre", null, value.content) : value.kind === "image" ? /* @__PURE__ */ React.createElement("img", { src: source, alt: selected }) : value.kind === "pdf" ? /* @__PURE__ */ React.createElement("iframe", { src: source, title: selected }) : value.kind === "media" && value.mediaType.startsWith("audio/") ? /* @__PURE__ */ React.createElement("audio", { src: source, controls: true }) : value.kind === "media" ? /* @__PURE__ */ React.createElement("video", { src: source, controls: true }) : /* @__PURE__ */ React.createElement("div", { className: "lbs-preview-empty" }, "该二进制文件暂不支持内嵌预览。")); + return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { className: "lbs-preview-title" }, /* @__PURE__ */ React.createElement("strong", null, selected), value ? /* @__PURE__ */ React.createElement("span", { className: "lbs-file-size" }, formatSize(value.size)) : null, /* @__PURE__ */ React.createElement("div", { className: "lbs-preview-actions" }, value?.kind === "text" ? editing ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", disabled: saving, onClick: onCancelEdit }, "取消"), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button primary", disabled: saving, onClick: onSave }, saving ? "正在保存…" : "保存")) : /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: onBeginEdit }, "编辑") : null, /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: onReveal }, "打开所在位置"))), !value ? /* @__PURE__ */ React.createElement("div", { className: "lbs-preview-empty" }, "正在读取…") : value.kind === "text" && editing ? /* @__PURE__ */ React.createElement("textarea", { className: "lbs-preview-editor", "aria-label": `${selected} 文本编辑器`, autoFocus: true, spellCheck: false, value: draft, onChange: (event) => onDraftChange(event.target.value), onKeyDown: (event) => { + if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "s") { + event.preventDefault(); + onSave(); + } + } }) : value.kind === "text" && isCodePath(selected) ? /* @__PURE__ */ React.createElement(CodeViewer, { value: value.content, path: selected }) : value.kind === "text" ? /* @__PURE__ */ React.createElement("pre", null, value.content) : value.kind === "image" ? /* @__PURE__ */ React.createElement("img", { src: source, alt: selected }) : value.kind === "pdf" ? /* @__PURE__ */ React.createElement("iframe", { src: source, title: selected }) : value.kind === "media" && value.mediaType.startsWith("audio/") ? /* @__PURE__ */ React.createElement("audio", { src: source, controls: true }) : value.kind === "media" ? /* @__PURE__ */ React.createElement("video", { src: source, controls: true }) : /* @__PURE__ */ React.createElement("div", { className: "lbs-preview-empty" }, "该二进制文件暂不支持内嵌预览。")); } - function FilesPage({ requestedRoot }) { + function FilesPage({ requestedRoot, requestedPath }) { const desktop = useDesktopContext(); const root = requestedRoot || desktop.context?.root; - const [current, setCurrent] = useState("."); - const [listing, setListing] = useState(null); + const [childrenByPath, setChildrenByPath] = useState({}); + const [expanded, setExpanded] = useState(() => /* @__PURE__ */ new Set(["."])); + const [loadingPaths, setLoadingPaths] = useState(() => /* @__PURE__ */ new Set()); const [selected, setSelected] = useState(""); const [preview, setPreview] = useState(null); const [error, setError] = useState(""); - const load = useCallback(async (next) => { + const [menu, setMenu] = useState(null); + const [editing, setEditing] = useState(false); + const [draft, setDraft] = useState(""); + const [saving, setSaving] = useState(false); + const loadDirectory = useCallback(async (next) => { if (!root) return; + setLoadingPaths((current) => new Set(current).add(next)); try { - setListing(await bridge().workspace.list({ root, path: next })); - setCurrent(next); + const listing = await bridge().workspace.list({ root, path: next }); + setChildrenByPath((current) => ({ ...current, [next]: listing.entries || [] })); setError(""); } catch (reason) { setError(messageOf(reason)); + } finally { + setLoadingPaths((current) => { + const value = new Set(current); + value.delete(next); + return value; + }); } }, [root]); - useEffect(() => { - setCurrent("."); + const choose = useCallback(async (entry) => { + setSelected(entry.path); + setPreview(null); + setEditing(false); + setDraft(""); + setError(""); + try { + setPreview(await bridge().workspace.read({ root, path: entry.path })); + } catch (reason) { + setError(messageOf(reason)); + } + }, [root]); + const initialize = useCallback(async (target = "") => { + setChildrenByPath({}); + setExpanded(/* @__PURE__ */ new Set(["."])); setSelected(""); setPreview(null); - if (root) void load("."); - }, [root, load]); - const choose = async (entry) => { - if (entry.type === "directory") { - setSelected(""); - setPreview(null); - await load(entry.path); + setEditing(false); + setDraft(""); + setMenu(null); + if (!root) return; + const relative = target ? relativeWorkspacePath(root, target) : "."; + const parts = relative.split(/[\\/]/u).filter((part) => part && part !== "."); + const separator = pathSeparator(root); + const directories = parts.slice(0, -1).map((_, index) => parts.slice(0, index + 1).join(separator)); + const openDirectories = [".", ...directories]; + setExpanded(new Set(openDirectories)); + await Promise.all(openDirectories.map((directory) => loadDirectory(directory))); + if (parts.length > 0) await choose({ path: parts.join(separator), type: "file" }); + }, [choose, loadDirectory, root]); + useEffect(() => { + void initialize(requestedPath); + }, [initialize, requestedPath]); + useEffect(() => { + const close = () => setMenu(null); + const key = (event) => { + if (event.key === "Escape") close(); + }; + document.addEventListener("pointerdown", close); + window.addEventListener("blur", close); + window.addEventListener("resize", close); + window.addEventListener("keydown", key); + return () => { + document.removeEventListener("pointerdown", close); + window.removeEventListener("blur", close); + window.removeEventListener("resize", close); + window.removeEventListener("keydown", key); + }; + }, []); + const toggleDirectory = async (entry) => { + if (expanded.has(entry.path)) { + setExpanded((current) => { + const value = new Set(current); + value.delete(entry.path); + return value; + }); return; } + setExpanded((current) => new Set(current).add(entry.path)); + if (!childrenByPath[entry.path]) await loadDirectory(entry.path); + }; + const save = async () => { + if (!selected || preview?.kind !== "text" || saving) return; + setSaving(true); + setError(""); + try { + const result = await bridge().workspace.write({ root, path: selected, content: draft, expectedModifiedAt: preview.modifiedAt }); + setPreview((current) => ({ ...current, content: draft, size: result.size, modifiedAt: result.modifiedAt })); + setEditing(false); + await loadDirectory(parentWorkspacePath(selected)); + } catch (reason) { + setError(messageOf(reason)); + } finally { + setSaving(false); + } + }; + const editEntry = async (entry) => { setSelected(entry.path); setPreview(null); + setEditing(false); + setDraft(""); + const value = await bridge().workspace.read({ root, path: entry.path }); + if (value.kind !== "text") throw new Error("该文件不是可编辑的文本文件。 "); + setPreview(value); + setDraft(value.content); + setEditing(true); + }; + const refresh = async () => Promise.all([...expanded].map((path) => loadDirectory(path))); + const openMenu = (event, entry) => { + event.preventDefault(); + event.stopPropagation(); + setMenu({ entry, x: Math.max(8, Math.min(event.clientX, window.innerWidth - 208)), y: Math.max(8, Math.min(event.clientY, window.innerHeight - 218)) }); + }; + const menuAction = (task) => async (event) => { + event.preventDefault(); + event.stopPropagation(); + setMenu(null); setError(""); try { - setPreview(await bridge().workspace.read({ root, path: entry.path })); + await task(); } catch (reason) { setError(messageOf(reason)); } }; + const renameEntry = async (entry) => { + const name = window.prompt(`重命名${entry.type === "directory" ? "文件夹" : "文件"}`, entry.name); + if (!name?.trim() || name.trim() === entry.name) return; + const result = await bridge().workspace.rename({ root, path: entry.path, name: name.trim() }); + if (entry.type === "directory") { + await initialize(); + return; + } + await loadDirectory(parentWorkspacePath(entry.path)); + if (selected === entry.path) await choose({ ...entry, name: result.name, path: result.path }); + }; + const removeEntry = async (entry) => { + const label = entry.type === "directory" ? `空文件夹“${entry.name}”` : `文件“${entry.name}”`; + if (!window.confirm(`确定删除${label}? +此操作无法撤销。`)) return; + await bridge().workspace.remove({ root, path: entry.path }); + const separator = pathSeparator(root); + if (selected === entry.path || selected.startsWith(`${entry.path}${separator}`)) { + setSelected(""); + setPreview(null); + setEditing(false); + setDraft(""); + } + setExpanded((current) => new Set([...current].filter((item) => item !== entry.path && !item.startsWith(`${entry.path}${separator}`)))); + setChildrenByPath((current) => Object.fromEntries(Object.entries(current).filter(([item]) => item !== entry.path && !item.startsWith(`${entry.path}${separator}`)))); + await loadDirectory(parentWorkspacePath(entry.path)); + }; + const revealSelected = async () => { + try { + await bridge().workspace.reveal({ root, path: selected }); + } catch (reason) { + setError(messageOf(reason)); + } + }; + const rootName = String(root || "项目").split(/[\\/]/u).filter(Boolean).at(-1) || String(root || "项目"); if (!bridge()?.capabilities?.workspaceFiles) return /* @__PURE__ */ React.createElement("div", { className: "lbs-preview-empty" }, "文件工作台仅在桌面版中可用。"); - return /* @__PURE__ */ React.createElement("div", { className: "lbs-workbench-body" }, /* @__PURE__ */ React.createElement("section", { className: "lbs-files-list" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-files-toolbar" }, /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", disabled: current === ".", onClick: () => load(parentPath(current)) }, "←"), /* @__PURE__ */ React.createElement("span", { className: "lbs-files-path", title: `${root || ""}/${current}` }, current), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: () => load(current) }, "刷新")), error || desktop.error ? /* @__PURE__ */ React.createElement("div", { className: "lbs-wb-error" }, error || desktop.error) : null, /* @__PURE__ */ React.createElement("div", { className: "lbs-file-rows" }, listing?.entries?.map((entry) => /* @__PURE__ */ React.createElement("button", { className: "lbs-file-row", key: entry.path, "data-active": selected === entry.path, onClick: () => choose(entry) }, /* @__PURE__ */ React.createElement("span", null, entry.type === "directory" ? "▸" : "·"), /* @__PURE__ */ React.createElement("span", { className: "lbs-file-name" }, entry.name), entry.type === "file" ? /* @__PURE__ */ React.createElement("span", { className: "lbs-file-size" }, formatSize(entry.size)) : null)))), /* @__PURE__ */ React.createElement("section", { className: "lbs-preview" }, /* @__PURE__ */ React.createElement(Preview, { selected, value: preview, onReveal: () => bridge().workspace.reveal({ root, path: selected }) }))); + return /* @__PURE__ */ React.createElement("div", { className: "lbs-workbench-body" }, /* @__PURE__ */ React.createElement("section", { className: "lbs-files-list" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-files-toolbar" }, /* @__PURE__ */ React.createElement("span", { className: "lbs-files-path", title: root }, root || "正在读取项目…"), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", disabled: expanded.size <= 1, onClick: () => setExpanded(/* @__PURE__ */ new Set(["."])) }, "全部折叠"), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: refresh }, "刷新")), error || desktop.error ? /* @__PURE__ */ React.createElement("div", { className: "lbs-wb-error" }, error || desktop.error) : null, /* @__PURE__ */ React.createElement("div", { className: "lbs-file-tree", role: "tree", "aria-label": "项目文件目录树" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-file-root-row" }, /* @__PURE__ */ React.createElement("span", { className: "lbs-tree-chevron" }, "▾"), /* @__PURE__ */ React.createElement("span", { className: "lbs-tree-icon" }, "▰"), /* @__PURE__ */ React.createElement("span", { className: "lbs-tree-name" }, rootName)), /* @__PURE__ */ React.createElement("div", { role: "group" }, (childrenByPath["."] || []).map((entry) => /* @__PURE__ */ React.createElement(FileTreeNode, { key: entry.path, entry, depth: 0, childrenByPath, expanded, loadingPaths, selected, onToggle: toggleDirectory, onSelect: choose, onContextMenu: openMenu }))))), /* @__PURE__ */ React.createElement("section", { className: "lbs-preview" }, /* @__PURE__ */ React.createElement(Preview, { selected, value: preview, editing, draft, saving, onBeginEdit: () => { + setDraft(preview?.content || ""); + setEditing(true); + }, onDraftChange: setDraft, onSave: save, onCancelEdit: () => { + setDraft(preview?.content || ""); + setEditing(false); + }, onReveal: revealSelected })), menu ? /* @__PURE__ */ React.createElement("div", { className: "lbs-file-menu", role: "menu", style: { left: menu.x, top: menu.y }, onPointerDown: (event) => event.stopPropagation(), onContextMenu: (event) => { + event.preventDefault(); + event.stopPropagation(); + } }, /* @__PURE__ */ React.createElement("button", { onClick: menuAction(() => menu.entry.type === "directory" ? toggleDirectory(menu.entry) : choose(menu.entry)) }, menu.entry.type === "directory" ? expanded.has(menu.entry.path) ? "折叠文件夹" : "展开文件夹" : "在文件管理器中打开"), menu.entry.mediaType?.startsWith("text/") || menu.entry.mediaType === "application/json" ? /* @__PURE__ */ React.createElement("button", { onClick: menuAction(() => editEntry(menu.entry)) }, "编辑文本") : null, /* @__PURE__ */ React.createElement("button", { onClick: menuAction(() => bridge().workspace.reveal({ root, path: menu.entry.path })) }, "打开所在位置"), /* @__PURE__ */ React.createElement("button", { onClick: menuAction(() => renameEntry(menu.entry)) }, "重命名…"), /* @__PURE__ */ React.createElement("div", { className: "lbs-file-menu-separator" }), /* @__PURE__ */ React.createElement("button", { className: "danger", onClick: menuAction(() => removeEntry(menu.entry)) }, menu.entry.type === "directory" ? "删除空文件夹" : "删除文件")) : null); } function GitChange({ change, side, active, busy, onSelect, onAction, actionLabel }) { const code = side === "staged" ? change.index : change.worktree; - return /* @__PURE__ */ React.createElement("div", { className: "lbs-git-change", "data-active": active, onClick: onSelect, role: "button", tabIndex: 0 }, /* @__PURE__ */ React.createElement("span", { className: "lbs-git-code" }, code === "?" ? "U" : code), /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement("span", { className: "lbs-git-change-name" }, change.path), change.originalPath ? /* @__PURE__ */ React.createElement("span", { className: "lbs-git-change-sub" }, "来自 ", change.originalPath) : null), /* @__PURE__ */ React.createElement("button", { className: "lbs-git-row-action", disabled: busy, onClick: (event) => { + return /* @__PURE__ */ React.createElement("div", { className: "lbs-git-change", "data-active": active, "data-status": code === "?" ? "U" : code, onClick: onSelect, onKeyDown: (event) => { + if (["Enter", " "].includes(event.key)) onSelect(); + }, role: "button", tabIndex: 0 }, /* @__PURE__ */ React.createElement("span", { className: "lbs-git-code" }, code === "?" ? "U" : code), /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement("span", { className: "lbs-git-change-name" }, change.path), change.originalPath ? /* @__PURE__ */ React.createElement("span", { className: "lbs-git-change-sub" }, "来自 ", change.originalPath) : null), /* @__PURE__ */ React.createElement("button", { className: "lbs-git-row-action", disabled: busy, onClick: (event) => { event.stopPropagation(); onAction(); } }, actionLabel)); @@ -229,36 +593,59 @@ ${state.root}`) && update(() => bridge().git.init({ root, branch: "main" }), "Gi const staged = state.changes.filter((change) => change.staged); const unstaged = state.changes.filter((change) => change.unstaged); const selectedTitle = selection?.kind === "commit" ? `提交 ${selection.ref.slice(0, 8)}` : selection?.path || "版本差异"; - return /* @__PURE__ */ React.createElement("div", { className: `lbs-git-layout ${busy ? "lbs-git-loading" : ""}` }, /* @__PURE__ */ React.createElement("aside", { className: "lbs-git-sidebar" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-git-toolbar" }, /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: refresh }, "刷新"), /* @__PURE__ */ React.createElement("select", { value: state.branch, onChange: (event) => void switchBranch(event.target.value) }, state.branches.map((branch) => /* @__PURE__ */ React.createElement("option", { key: branch.name, value: branch.name }, branch.name))), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: createBranch }, "新分支"), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button danger", onClick: deleteBranch }, "删分支"), /* @__PURE__ */ React.createElement("span", { className: "lbs-git-toolbar-spacer" }), state.upstream ? /* @__PURE__ */ React.createElement("span", { className: "lbs-git-badge" }, "↑", state.ahead, " ↓", state.behind) : null), error || desktop.error ? /* @__PURE__ */ React.createElement("div", { className: "lbs-wb-error" }, error || desktop.error) : notice ? /* @__PURE__ */ React.createElement("div", { className: "lbs-wb-ok" }, notice) : null, /* @__PURE__ */ React.createElement("div", { className: "lbs-git-scroll" }, /* @__PURE__ */ React.createElement("section", { className: "lbs-git-section" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-git-section-head" }, "已暂存 ", /* @__PURE__ */ React.createElement("span", null, staged.length)), staged.map((change) => /* @__PURE__ */ React.createElement(GitChange, { key: `s:${change.path}`, change, side: "staged", active: selection?.side === "staged" && selection.path === change.path, busy, onSelect: () => showChange(change, "staged"), onAction: () => unstage(change), actionLabel: "取消暂存" }))), /* @__PURE__ */ React.createElement("section", { className: "lbs-git-section" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-git-section-head" }, "工作区变更 ", /* @__PURE__ */ React.createElement("span", null, unstaged.length)), unstaged.map((change) => /* @__PURE__ */ React.createElement(GitChange, { key: `w:${change.path}`, change, side: change.untracked ? "untracked" : "unstaged", active: selection?.side !== "staged" && selection?.path === change.path, busy, onSelect: () => showChange(change, change.untracked ? "untracked" : "unstaged"), onAction: () => stage(change), actionLabel: "暂存" })), unstaged.filter((change) => !change.untracked).map((change) => /* @__PURE__ */ React.createElement("button", { key: `r:${change.path}`, className: "lbs-wb-button danger", onClick: () => restore(change) }, "放弃 ", change.path, " 的修改"))), /* @__PURE__ */ React.createElement("section", { className: "lbs-git-section" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-git-section-head" }, "提交历史 ", /* @__PURE__ */ React.createElement("span", null, state.commits.length)), state.commits.map((commit2) => /* @__PURE__ */ React.createElement("button", { className: "lbs-git-history", "data-active": selection?.ref === commit2.hash, key: commit2.hash, onClick: () => showCommit(commit2) }, /* @__PURE__ */ React.createElement("strong", null, commit2.subject), /* @__PURE__ */ React.createElement("small", null, commit2.shortHash, " · ", commit2.author, " · ", new Date(commit2.date).toLocaleString("zh-CN")))))), /* @__PURE__ */ React.createElement("div", { className: "lbs-git-commit-box" }, /* @__PURE__ */ React.createElement("textarea", { value: message, onChange: (event) => setMessage(event.target.value), placeholder: "描述这次本地版本…" }), /* @__PURE__ */ React.createElement("div", { className: "lbs-git-commit-actions" }, /* @__PURE__ */ React.createElement("span", null, staged.length, " 个已暂存文件"), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button primary", disabled: !message.trim() || staged.length === 0 || busy, onClick: commit }, "提交版本")))), /* @__PURE__ */ React.createElement("main", { className: "lbs-git-main" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-git-diff-head" }, /* @__PURE__ */ React.createElement("strong", null, selectedTitle), /* @__PURE__ */ React.createElement("span", null, state.root), /* @__PURE__ */ React.createElement("span", { className: "lbs-git-toolbar-spacer" }), state.remotes.length ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: () => sync("fetch") }, "获取"), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: () => sync("pull") }, "拉取"), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button primary", onClick: () => sync("push") }, "发布")) : /* @__PURE__ */ React.createElement("span", null, "未配置远端")), /* @__PURE__ */ React.createElement("pre", { className: "lbs-git-diff" }, diff || "选择一个变更或提交查看 Diff。"))); + return /* @__PURE__ */ React.createElement("div", { className: `lbs-git-layout ${busy ? "lbs-git-loading" : ""}` }, /* @__PURE__ */ React.createElement("aside", { className: "lbs-git-sidebar" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-git-toolbar" }, /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: refresh }, "刷新"), /* @__PURE__ */ React.createElement("select", { value: state.branch, onChange: (event) => void switchBranch(event.target.value) }, state.branches.map((branch) => /* @__PURE__ */ React.createElement("option", { key: branch.name, value: branch.name }, branch.name))), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: createBranch }, "新分支"), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button danger", onClick: deleteBranch }, "删分支"), /* @__PURE__ */ React.createElement("span", { className: "lbs-git-toolbar-spacer" }), state.upstream ? /* @__PURE__ */ React.createElement("span", { className: "lbs-git-badge" }, "↑", state.ahead, " ↓", state.behind) : null), error || desktop.error ? /* @__PURE__ */ React.createElement("div", { className: "lbs-wb-error" }, error || desktop.error) : notice ? /* @__PURE__ */ React.createElement("div", { className: "lbs-wb-ok" }, notice) : null, /* @__PURE__ */ React.createElement("div", { className: "lbs-git-scroll" }, /* @__PURE__ */ React.createElement("section", { className: "lbs-git-section" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-git-section-head" }, "已暂存 ", /* @__PURE__ */ React.createElement("span", null, staged.length)), staged.map((change) => /* @__PURE__ */ React.createElement(GitChange, { key: `s:${change.path}`, change, side: "staged", active: selection?.side === "staged" && selection.path === change.path, busy, onSelect: () => showChange(change, "staged"), onAction: () => unstage(change), actionLabel: "取消暂存" }))), /* @__PURE__ */ React.createElement("section", { className: "lbs-git-section" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-git-section-head" }, "工作区变更 ", /* @__PURE__ */ React.createElement("span", null, unstaged.length)), unstaged.map((change) => /* @__PURE__ */ React.createElement(GitChange, { key: `w:${change.path}`, change, side: change.untracked ? "untracked" : "unstaged", active: selection?.side !== "staged" && selection?.path === change.path, busy, onSelect: () => showChange(change, change.untracked ? "untracked" : "unstaged"), onAction: () => stage(change), actionLabel: "暂存" })), unstaged.filter((change) => !change.untracked).map((change) => /* @__PURE__ */ React.createElement("button", { key: `r:${change.path}`, className: "lbs-wb-button danger", onClick: () => restore(change) }, "放弃 ", change.path, " 的修改"))), /* @__PURE__ */ React.createElement("section", { className: "lbs-git-section" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-git-section-head" }, "提交历史 ", /* @__PURE__ */ React.createElement("span", null, state.commits.length)), state.commits.map((commit2) => /* @__PURE__ */ React.createElement("button", { className: "lbs-git-history", "data-active": selection?.ref === commit2.hash, key: commit2.hash, onClick: () => showCommit(commit2) }, /* @__PURE__ */ React.createElement("strong", null, commit2.subject), /* @__PURE__ */ React.createElement("small", null, commit2.shortHash, " · ", commit2.author, " · ", new Date(commit2.date).toLocaleString("zh-CN")))))), /* @__PURE__ */ React.createElement("div", { className: "lbs-git-commit-box" }, /* @__PURE__ */ React.createElement("textarea", { value: message, onChange: (event) => setMessage(event.target.value), placeholder: "描述这次本地版本…" }), /* @__PURE__ */ React.createElement("div", { className: "lbs-git-commit-actions" }, /* @__PURE__ */ React.createElement("span", null, staged.length, " 个已暂存文件"), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button primary", disabled: !message.trim() || staged.length === 0 || busy, onClick: commit }, "提交版本")))), /* @__PURE__ */ React.createElement("main", { className: "lbs-git-main" }, /* @__PURE__ */ React.createElement("div", { className: "lbs-git-diff-head" }, /* @__PURE__ */ React.createElement("strong", null, selectedTitle), /* @__PURE__ */ React.createElement("span", null, state.root), /* @__PURE__ */ React.createElement("span", { className: "lbs-git-toolbar-spacer" }), state.remotes.length ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: () => sync("fetch") }, "获取"), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button", onClick: () => sync("pull") }, "拉取"), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button primary", onClick: () => sync("push") }, "发布")) : /* @__PURE__ */ React.createElement("span", null, "未配置远端")), diff ? /* @__PURE__ */ React.createElement(DiffViewer, { value: diff, path: selection?.path || "" }) : /* @__PURE__ */ React.createElement("div", { className: "lbs-preview-empty" }, "选择一个变更或提交查看 Diff。"))); } function WorkspaceWorkbench() { const [page, setPage] = useState(""); const [root, setRoot] = useState(""); + const [requestedPath, setRequestedPath] = useState(""); useEffect(() => { const open = (event) => { const tool = event.detail?.tool; if (tool === "close") { setPage(""); + setRequestedPath(""); return; } if (!["files", "git"].includes(tool)) return; setRoot(event.detail?.cwd || ""); + setRequestedPath(tool === "files" ? event.detail?.path || "" : ""); setPage(tool); }; window.addEventListener("laobos:open-desktop-tool", open); return () => window.removeEventListener("laobos:open-desktop-tool", open); }, []); + useEffect(() => { + const interceptProducedFile = (event) => { + if (!(event.target instanceof Element)) return; + const target = event.target.closest("[data-produced-files-row] button[title], [data-chat-flow] [aria-label][title]"); + if (!target) return; + const produced = target.closest("[data-produced-files-row]"); + const label = target.getAttribute("aria-label") || ""; + if (!produced && !/^(?:打开|Open)\s/u.test(label)) return; + const path = target.getAttribute("title"); + if (!path) return; + event.preventDefault(); + event.stopPropagation(); + event.stopImmediatePropagation(); + void openProducedFile(path); + }; + document.addEventListener("click", interceptProducedFile, true); + return () => document.removeEventListener("click", interceptProducedFile, true); + }, []); const close = () => { const closing = page; setPage(""); + setRequestedPath(""); window.dispatchEvent(new CustomEvent("laobos:desktop-tool-closed", { detail: { tool: closing } })); }; if (!page) return null; const title = page === "files" ? "文件管理器" : "版本中心"; - return /* @__PURE__ */ React.createElement("section", { className: "lbs-workbench", role: "dialog", "aria-label": title }, /* @__PURE__ */ React.createElement("header", { className: "lbs-workbench-header" }, /* @__PURE__ */ React.createElement("strong", null, title), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button lbs-workbench-close", onClick: close }, "关闭")), page === "files" ? /* @__PURE__ */ React.createElement(FilesPage, { requestedRoot: root }) : /* @__PURE__ */ React.createElement(GitPage, { requestedRoot: root })); + return /* @__PURE__ */ React.createElement("section", { className: "lbs-workbench", role: "dialog", "aria-label": title }, /* @__PURE__ */ React.createElement("header", { className: "lbs-workbench-header" }, /* @__PURE__ */ React.createElement("strong", null, title), /* @__PURE__ */ React.createElement("button", { className: "lbs-wb-button lbs-workbench-close", onClick: close }, "关闭")), page === "files" ? /* @__PURE__ */ React.createElement(FilesPage, { requestedRoot: root, requestedPath }) : /* @__PURE__ */ React.createElement(GitPage, { requestedRoot: root })); } - const inject = ["slots"]; + const inject = ["slots", "sessions", "workspaces"]; function apply(ctx) { + module.ctx = ctx; ctx.slots.inject("shell.overlay", () => ctx.slots.register({ name: "shell.overlay", id: "laobos-desktop-workbench", order: 35 }, WorkspaceWorkbench)); } exports.apply = apply; diff --git a/packages/laobos-workspace-tools/src/client.jsx b/packages/laobos-workspace-tools/src/client.jsx index f8de9e6..daf7a2d 100644 --- a/packages/laobos-workspace-tools/src/client.jsx +++ b/packages/laobos-workspace-tools/src/client.jsx @@ -1,4 +1,5 @@ /* eslint-disable @next/next/no-assign-module-variable, @next/next/no-img-element -- DSH module factory and local previews */ +import { codeLines, isCodePath, languageForPath, parseUnifiedDiff, tokenizeCodeLine } from "./code-renderer.mjs"; window.__ModuleLoader__.load({ id: "@laobos/dsh-workspace-tools", factory: (require) => { @@ -9,9 +10,15 @@ window.__ModuleLoader__.load({ const { useCallback, useEffect, useMemo, useState } = React; const css = ` - .lbs-workbench{background:var(--dsw-alias-bg-base);bottom:0;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483030}.lbs-workbench-header{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;flex:none;gap:8px;height:56px;padding:0 18px}.lbs-workbench-header strong{font-size:15px}.lbs-workbench-close{margin-left:auto}.lbs-workbench-body{display:flex;flex:1;min-height:0}.lbs-files-list{border-right:1px solid var(--dsw-alias-border-l1);box-sizing:border-box;display:flex;flex-direction:column;min-width:250px;width:34%}.lbs-files-toolbar,.lbs-git-toolbar{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;gap:6px;min-height:43px;padding:0 10px}.lbs-files-path{color:var(--dsw-alias-label-secondary);flex:1;font:11px ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-file-rows{flex:1;overflow:auto;padding:5px}.lbs-file-row{align-items:center;appearance:none;background:transparent;border:0;border-radius:6px;color:inherit;cursor:pointer;display:flex;font:inherit;font-size:12px;gap:7px;height:29px;padding:0 8px;text-align:left;width:100%}.lbs-file-row:hover,.lbs-file-row[data-active=true]{background:var(--dsw-alias-interactive-bg-hover)}.lbs-file-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-file-size{color:var(--dsw-alias-label-tertiary);font-size:10px}.lbs-preview{box-sizing:border-box;flex:1;min-width:0;overflow:auto;padding:16px}.lbs-preview-empty{align-items:center;color:var(--dsw-alias-label-tertiary);display:flex;height:100%;justify-content:center;text-align:center}.lbs-preview-title{align-items:center;display:flex;gap:8px;margin-bottom:12px}.lbs-preview-title strong{font-size:14px}.lbs-preview-title .lbs-wb-button{margin-left:auto}.lbs-preview pre,.lbs-git-diff{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:9px;box-sizing:border-box;font:12px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;margin:0;overflow:auto;padding:12px;tab-size:2;white-space:pre}.lbs-preview img,.lbs-preview video{display:block;height:auto;margin:auto;max-height:calc(100vh - 130px);max-width:100%}.lbs-preview iframe{border:1px solid var(--dsw-alias-border-l1);height:calc(100vh - 115px);width:100%}.lbs-preview audio{margin:40px auto;max-width:620px;width:100%} + .lbs-workbench{background:var(--dsw-alias-bg-base);bottom:0;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;left:var(--lbs-left-column,280px);pointer-events:auto;position:fixed;right:var(--lbs-right-column,56px);top:0;z-index:2147483030}.lbs-workbench-header{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;flex:none;gap:8px;height:56px;padding:0 18px}.lbs-workbench-header strong{font-size:15px}.lbs-workbench-close{margin-left:auto}.lbs-workbench-body{display:flex;flex:1;min-height:0}.lbs-files-list{border-right:1px solid var(--dsw-alias-border-l1);box-sizing:border-box;display:flex;flex-direction:column;min-width:250px;width:34%}.lbs-files-toolbar,.lbs-git-toolbar{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;gap:6px;min-height:43px;padding:0 10px}.lbs-files-path{color:var(--dsw-alias-label-secondary);flex:1;font:11px ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-file-rows{flex:1;overflow:auto;padding:5px}.lbs-file-row{align-items:center;appearance:none;background:transparent;border:0;border-radius:6px;color:inherit;cursor:pointer;display:flex;font:inherit;font-size:12px;gap:7px;height:29px;padding:0 8px;text-align:left;width:100%}.lbs-file-row:hover,.lbs-file-row[data-active=true]{background:var(--dsw-alias-interactive-bg-hover)}.lbs-file-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-file-size{color:var(--dsw-alias-label-tertiary);font-size:10px}.lbs-preview{box-sizing:border-box;flex:1;min-width:0;overflow:auto;padding:16px}.lbs-preview-empty{align-items:center;color:var(--dsw-alias-label-tertiary);display:flex;height:100%;justify-content:center;text-align:center}.lbs-preview-title{align-items:center;display:flex;gap:8px;margin-bottom:12px}.lbs-preview-title strong{font-size:14px}.lbs-preview-actions{align-items:center;display:flex;gap:5px;margin-left:auto}.lbs-preview pre,.lbs-git-diff{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:9px;box-sizing:border-box;font:12px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;margin:0;overflow:auto;padding:12px;tab-size:2;white-space:pre}.lbs-preview img,.lbs-preview video{display:block;height:auto;margin:auto;max-height:calc(100vh - 130px);max-width:100%}.lbs-preview iframe{border:1px solid var(--dsw-alias-border-l1);height:calc(100vh - 115px);width:100%}.lbs-preview audio{margin:40px auto;max-width:620px;width:100%}.lbs-preview-editor{background:var(--dsw-alias-markdown-code-block,var(--dsw-alias-bg-layer-1));border:1px solid var(--dsw-alias-border-l2);border-radius:9px;box-sizing:border-box;color:var(--dsw-alias-label-primary);font:12px/1.58 ui-monospace,SFMono-Regular,Menlo,monospace;height:calc(100vh - 145px);min-height:280px;outline:none;padding:12px;resize:none;tab-size:2;width:100%}.lbs-preview-editor:focus{border-color:var(--dsw-alias-border-l3);box-shadow:0 0 0 2px color-mix(in srgb,var(--dsw-alias-brand-primary) 16%,transparent)} .lbs-wb-button{appearance:none;background:transparent;border:0;border-radius:7px;color:inherit;cursor:pointer;font:inherit;font-size:11px;min-height:31px;padding:0 9px}.lbs-wb-button:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-wb-button.primary{background:var(--dsw-alias-interactive-bg-primary);color:var(--dsw-alias-label-on-primary)}.lbs-wb-button.danger{color:#d94b4b}.lbs-wb-button:disabled{cursor:not-allowed;opacity:.38}.lbs-wb-error{background:rgba(218,70,70,.1);border-radius:8px;color:#d94b4b;font-size:11px;line-height:1.5;margin:8px;padding:9px}.lbs-wb-ok{background:rgba(52,163,105,.1);border-radius:8px;color:#38a76f;font-size:11px;margin:8px;padding:9px} .lbs-git-layout{display:grid;flex:1;grid-template-columns:minmax(310px,37%) minmax(0,1fr);min-height:0}.lbs-git-sidebar{border-right:1px solid var(--dsw-alias-border-l1);display:flex;flex-direction:column;min-height:0}.lbs-git-toolbar{flex-wrap:wrap}.lbs-git-toolbar select,.lbs-git-commit-box textarea{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;color:inherit;font:inherit}.lbs-git-toolbar select{font-size:11px;height:29px;max-width:150px;padding:0 7px}.lbs-git-toolbar-spacer{flex:1}.lbs-git-scroll{flex:1;min-height:0;overflow:auto;padding:7px 9px}.lbs-git-section{margin-bottom:15px}.lbs-git-section-head{align-items:center;color:var(--dsw-alias-label-secondary);display:flex;font-size:10px;font-weight:600;height:27px;letter-spacing:.03em;padding:0 5px;text-transform:uppercase}.lbs-git-section-head span{margin-left:auto}.lbs-git-change,.lbs-git-history{align-items:center;appearance:none;background:transparent;border:0;border-radius:6px;color:inherit;cursor:pointer;display:grid;font:inherit;text-align:left;width:100%}.lbs-git-change{grid-template-columns:28px minmax(0,1fr) auto;min-height:34px;padding:4px 5px}.lbs-git-change:hover,.lbs-git-change[data-active=true],.lbs-git-history:hover,.lbs-git-history[data-active=true]{background:var(--dsw-alias-interactive-bg-hover)}.lbs-git-code{font:10px ui-monospace,SFMono-Regular,Menlo,monospace}.lbs-git-change-name,.lbs-git-history strong{font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-git-change-sub,.lbs-git-history small{color:var(--dsw-alias-label-tertiary);display:block;font-size:9px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-git-row-action{appearance:none;background:transparent;border:0;border-radius:5px;color:var(--dsw-alias-label-secondary);cursor:pointer;font-size:9px;height:25px;opacity:.2;padding:0 6px}.lbs-git-change:hover .lbs-git-row-action,.lbs-git-row-action:focus-visible{opacity:1}.lbs-git-history{display:block;padding:6px}.lbs-git-commit-box{border-top:1px solid var(--dsw-alias-border-l1);display:grid;gap:7px;padding:9px}.lbs-git-commit-box textarea{box-sizing:border-box;font-size:11px;line-height:1.45;min-height:58px;padding:7px;resize:vertical;width:100%}.lbs-git-commit-actions{align-items:center;display:flex;gap:6px}.lbs-git-commit-actions span{color:var(--dsw-alias-label-tertiary);font-size:9px;margin-right:auto}.lbs-git-main{display:flex;flex-direction:column;min-width:0}.lbs-git-diff-head{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l1);display:flex;gap:8px;min-height:43px;padding:0 13px}.lbs-git-diff-head strong{font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-git-diff-head span{color:var(--dsw-alias-label-tertiary);font-size:9px}.lbs-git-diff{border:0;border-radius:0;flex:1;min-height:0}.lbs-git-onboarding{align-content:center;display:grid;gap:12px;height:100%;justify-items:center;padding:30px;text-align:center}.lbs-git-onboarding strong{font-size:16px}.lbs-git-onboarding p{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6;margin:0;max-width:480px}.lbs-git-badge{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:4px;color:var(--dsw-alias-label-secondary);font-size:9px;padding:2px 5px}.lbs-git-loading{opacity:.58;pointer-events:none} + .lbs-files-list{min-width:280px;width:32%}.lbs-files-toolbar{min-height:46px}.lbs-file-tree{flex:1;overflow:auto;padding:6px 5px 14px}.lbs-file-root-row,.lbs-tree-row{align-items:center;border-radius:6px;box-sizing:border-box;display:flex;min-width:max-content;width:100%}.lbs-file-root-row{color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:600;height:31px;padding:0 8px}.lbs-tree-row{height:29px;padding-right:7px}.lbs-tree-row:hover,.lbs-tree-row[data-active=true]{background:var(--dsw-alias-interactive-bg-hover)}.lbs-tree-toggle,.lbs-tree-file{align-items:center;appearance:none;background:transparent;border:0;color:inherit;cursor:pointer;display:flex;font:inherit;height:100%;min-width:0;padding:0;text-align:left}.lbs-tree-toggle{flex:1}.lbs-tree-chevron{color:var(--dsw-alias-label-tertiary);display:inline-flex;flex:none;font-size:10px;justify-content:center;width:18px}.lbs-tree-icon{align-items:center;color:var(--dsw-alias-label-secondary);display:inline-flex;flex:none;font:10px/1 ui-monospace,SFMono-Regular,Menlo,monospace;height:18px;justify-content:center;margin-right:5px;width:18px}.lbs-tree-row[data-type=directory] .lbs-tree-icon{color:#d6a84b;font-size:15px}.lbs-tree-row[data-code=true] .lbs-tree-icon{color:#6f8cff}.lbs-tree-name{font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lbs-tree-file{flex:1}.lbs-tree-size{color:var(--dsw-alias-label-tertiary);font-size:9px;margin-left:10px}.lbs-tree-loading{animation:lbs-tree-spin .8s linear infinite;display:inline-block}@keyframes lbs-tree-spin{to{transform:rotate(360deg)}} + .lbs-file-menu{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:9px;box-shadow:var(--dsw-shadow-lv3);display:grid;min-width:190px;padding:5px;position:fixed;z-index:2147483200}.lbs-file-menu button{appearance:none;background:transparent;border:0;border-radius:6px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;font-size:11px;height:30px;padding:0 9px;text-align:left}.lbs-file-menu button:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-file-menu button.danger{color:var(--dsw-alias-state-error-primary,#d94b4b)}.lbs-file-menu-separator{border-top:1px solid var(--dsw-alias-border-l1);margin:4px 3px} + .lbs-workbench{--lbs-code-keyword:#cf222e;--lbs-code-string:#0a3069;--lbs-code-number:#0550ae;--lbs-code-comment:#6e7781;--lbs-code-type:#953800;--lbs-code-function:#8250df;--lbs-diff-add:#1a7f37;--lbs-diff-delete:#cf222e;--lbs-diff-hunk:#0969da;--lbs-diff-file:#8250df;--lbs-diff-insert-bg:rgba(46,160,67,.1);--lbs-diff-insert-gutter:rgba(46,160,67,.16);--lbs-diff-delete-bg:rgba(248,81,73,.1);--lbs-diff-delete-gutter:rgba(248,81,73,.16);--lbs-diff-hunk-bg:rgba(9,105,218,.08)}body[data-ds-dark-theme] .lbs-workbench{--lbs-code-keyword:#ff7b72;--lbs-code-string:#a5d6ff;--lbs-code-number:#79c0ff;--lbs-code-comment:#8b949e;--lbs-code-type:#ffa657;--lbs-code-function:#d2a8ff;--lbs-diff-add:#56d364;--lbs-diff-delete:#ff7b72;--lbs-diff-hunk:#79c0ff;--lbs-diff-file:#d2a8ff;--lbs-diff-insert-bg:rgba(46,160,67,.17);--lbs-diff-insert-gutter:rgba(46,160,67,.24);--lbs-diff-delete-bg:rgba(248,81,73,.16);--lbs-diff-delete-gutter:rgba(248,81,73,.23);--lbs-diff-hunk-bg:rgba(56,139,253,.13)} + .lbs-code-viewer{background:var(--dsw-alias-markdown-code-block,var(--dsw-alias-bg-layer-1));border:1px solid var(--dsw-alias-border-l2);border-radius:9px;color:var(--dsw-alias-label-primary);min-width:max-content;overflow:auto}.lbs-code-language{align-items:center;background:var(--dsw-alias-markdown-code-block-banner,var(--dsw-alias-bg-layer-2));border-bottom:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);display:flex;font:10px/28px ui-monospace,SFMono-Regular,Menlo,monospace;height:28px;justify-content:space-between;padding:0 10px;position:sticky;left:0}.lbs-code-row{display:grid;font:12px/1.58 ui-monospace,SFMono-Regular,Menlo,monospace;grid-template-columns:52px minmax(max-content,1fr);min-height:19px}.lbs-code-row:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-code-line-number{border-right:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary));padding:0 10px;text-align:right;user-select:none}.lbs-code-line{padding:0 12px;white-space:pre}.lbs-code-truncated{background:var(--dsw-alias-markdown-code-block-banner,var(--dsw-alias-bg-layer-2));color:var(--dsw-alias-label-tertiary);font-size:11px;padding:8px 12px;position:sticky;left:0}.lbs-token-keyword{color:var(--lbs-code-keyword)}.lbs-token-string{color:var(--lbs-code-string)}.lbs-token-number{color:var(--lbs-code-number)}.lbs-token-comment{color:var(--lbs-code-comment);font-style:italic}.lbs-token-type{color:var(--lbs-code-type)}.lbs-token-function{color:var(--lbs-code-function)} + .lbs-diff-viewer{background:var(--dsw-alias-markdown-code-block,var(--dsw-alias-bg-layer-1));color:var(--dsw-alias-label-primary);display:flex;flex:1;flex-direction:column;min-height:0}.lbs-diff-summary{align-items:center;background:var(--dsw-alias-markdown-code-block-banner,var(--dsw-alias-bg-layer-2));border-bottom:1px solid var(--dsw-alias-border-l2);display:flex;flex:none;gap:10px;height:34px;padding:0 10px}.lbs-diff-summary span{font:10px ui-monospace,SFMono-Regular,Menlo,monospace}.lbs-diff-additions{color:var(--lbs-diff-add)}.lbs-diff-deletions{color:var(--lbs-diff-delete)}.lbs-diff-summary button{background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:5px;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;font-size:10px;line-height:23px;margin-left:auto;padding:0 8px}.lbs-diff-summary button:hover{background:var(--dsw-alias-interactive-bg-hover)}.lbs-diff-scroll{flex:1;min-height:0;overflow:auto}.lbs-diff-table{border-collapse:collapse;font:12px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace;min-width:100%;table-layout:auto}.lbs-diff-row td{height:20px;padding:0}.lbs-diff-gutter{background:var(--dsw-alias-markdown-code-block,var(--dsw-alias-bg-layer-1));border-right:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-caption,var(--dsw-alias-label-tertiary));min-width:43px;padding:0 8px!important;text-align:right;user-select:none;width:43px}.lbs-diff-prefix{color:var(--dsw-alias-label-tertiary);text-align:center;user-select:none;width:24px}.lbs-diff-code{padding-right:14px!important;white-space:pre}.lbs-diff-viewer[data-wrap=true] .lbs-diff-code{overflow-wrap:anywhere;white-space:pre-wrap}.lbs-diff-row[data-type=insert]{background:var(--lbs-diff-insert-bg)}.lbs-diff-row[data-type=insert] .lbs-diff-gutter{background:var(--lbs-diff-insert-gutter);color:var(--lbs-diff-add)}.lbs-diff-row[data-type=insert] .lbs-diff-prefix{color:var(--lbs-diff-add)}.lbs-diff-row[data-type=delete]{background:var(--lbs-diff-delete-bg)}.lbs-diff-row[data-type=delete] .lbs-diff-gutter{background:var(--lbs-diff-delete-gutter);color:var(--lbs-diff-delete)}.lbs-diff-row[data-type=delete] .lbs-diff-prefix{color:var(--lbs-diff-delete)}.lbs-diff-row[data-type=hunk]{background:var(--lbs-diff-hunk-bg);color:var(--lbs-diff-hunk)}.lbs-diff-row[data-type=file]{background:var(--dsw-alias-markdown-code-block-banner,var(--dsw-alias-bg-layer-2));color:var(--lbs-diff-file);font-weight:600}.lbs-diff-row[data-type=meta],.lbs-diff-row[data-type=notice]{color:var(--dsw-alias-label-tertiary)}.lbs-diff-row[data-type=hunk] .lbs-diff-code,.lbs-diff-row[data-type=file] .lbs-diff-code,.lbs-diff-row[data-type=meta] .lbs-diff-code,.lbs-diff-row[data-type=notice] .lbs-diff-code{padding:2px 12px!important}.lbs-diff-row:hover{box-shadow:inset 0 0 0 9999px color-mix(in srgb,var(--dsw-alias-label-primary) 3%,transparent)} + .lbs-git-change[data-status=A] .lbs-git-code,.lbs-git-change[data-status=U] .lbs-git-code{color:#2a9b67}.lbs-git-change[data-status=M] .lbs-git-code{color:#6f8cff}.lbs-git-change[data-status=D] .lbs-git-code{color:#d94b4b}.lbs-git-change[data-status=R] .lbs-git-code{color:#a675d1} @media(max-width:850px){.lbs-workbench{left:0;right:0}.lbs-workbench-body,.lbs-git-layout{display:flex;flex-direction:column}.lbs-files-list,.lbs-git-sidebar{border-bottom:1px solid var(--dsw-alias-border-l1);border-right:0;max-height:46vh;width:100%}.lbs-git-main{min-height:42vh}} `; if (typeof document !== "undefined" && !document.querySelector('style[data-plugin-css="@laobos/dsh-workspace-tools"]')) { @@ -27,7 +34,46 @@ window.__ModuleLoader__.load({ return text.replace(/^Error invoking remote method '[^']+': Error:\s*/u, ""); }; const formatSize = (value) => value < 1024 ? `${value} B` : value < 1024 ** 2 ? `${(value / 1024).toFixed(1)} KB` : `${(value / 1024 ** 2).toFixed(1)} MB`; - const parentPath = (value) => { const parts = String(value || ".").split("/").filter((part) => part && part !== "."); parts.pop(); return parts.join("/") || "."; }; + const absolutePathPattern = /^(?:\/|[a-zA-Z]:[\\/]|\\\\)/u; + const pathSeparator = (root) => String(root || "").includes("\\") ? "\\" : "/"; + const absoluteWorkspacePath = (root, target) => { + const value = String(target || "."); + if (!root || absolutePathPattern.test(value)) return value; + if (value === ".") return root; + const separator = pathSeparator(root); + return `${String(root).replace(/[\\/]+$/u, "")}${separator}${value.replace(/^[.][\\/]/u, "")}`; + }; + const relativeWorkspacePath = (root, target) => { + const value = String(target || "."); + if (!root) return value; + if (!absolutePathPattern.test(value)) return value.replace(/^[.][\\/]/u, "") || "."; + const windows = pathSeparator(root) === "\\"; + const normalizedRoot = String(root || "").replaceAll("\\", "/").replace(/\/+$/u, ""); + const normalizedTarget = value.replaceAll("\\", "/"); + const comparableRoot = windows ? normalizedRoot.toLowerCase() : normalizedRoot; + const comparableTarget = windows ? normalizedTarget.toLowerCase() : normalizedTarget; + if (comparableTarget === comparableRoot) return "."; + if (comparableTarget.startsWith(`${comparableRoot}/`)) return normalizedTarget.slice(normalizedRoot.length + 1).replaceAll("/", pathSeparator(root)); + return value; + }; + const parentWorkspacePath = (value) => { + const parts = String(value || ".").split(/[\\/]/u).filter(Boolean); + return parts.length <= 1 ? "." : parts.slice(0, -1).join(String(value).includes("\\") ? "\\" : "/"); + }; + + async function openProducedFile(path) { + const sessions = module.ctx?.sessions?.list?.getSnapshot?.(); + const cwd = sessions?.current ? sessions.byId?.[sessions.current]?.cwd : undefined; + const target = absoluteWorkspacePath(cwd, path); + try { + if (!module.ctx?.workspaces?.openPath) throw new Error("系统文件打开器不可用"); + await module.ctx.workspaces.openPath(target); + } catch { + window.dispatchEvent(new CustomEvent("laobos:open-desktop-tool", { + detail: { tool: "files", cwd, path, source: "file-open-fallback" }, + })); + } + } function useDesktopContext() { const [context, setContext] = useState(null); @@ -40,7 +86,80 @@ window.__ModuleLoader__.load({ return { context, error }; } - function Preview({ selected, value, onReveal }) { + function CodeTokens({ value, language }) { + return tokenizeCodeLine(value, language).map((token, index) => {token.value}); + } + + function CodeViewer({ value, path }) { + const language = languageForPath(path); + const lines = useMemo(() => codeLines(value), [value]); + const visibleLines = lines.slice(0, 6_000); + return
+
{language}{lines.length} 行
+ {visibleLines.map((line, index) =>
+ {index + 1} + +
)} + {lines.length > visibleLines.length ?
文件较大,仅渲染前 {visibleLines.length} 行;可在系统编辑器中查看完整内容。
: null} +
; + } + + function DiffViewer({ value, path }) { + const [wrap, setWrap] = useState(false); + const model = useMemo(() => parseUnifiedDiff(value, path), [value, path]); + const visibleLines = model.lines.slice(0, 12_000); + return
+
+ +{model.additions} 添加 + −{model.deletions} 删除 + {model.lines.length} 行 + +
+
+ + {visibleLines.map((line) => { + const codeLine = ["insert", "delete", "normal"].includes(line.type); + const language = languageForPath(line.path || path); + return + + + {codeLine ? <> + : } + ; + })} +
{line.oldLine ?? ""}{line.newLine ?? ""}{line.prefix}{line.content}
+ {model.lines.length > visibleLines.length ?
Diff 较大,仅渲染前 {visibleLines.length} 行。
: null} +
+
; + } + + function fileGlyph(entry) { + if (entry.type === "directory") return "▰"; + if (isCodePath(entry.path)) return "{}"; + const extension = entry.name.split(".").at(-1)?.toLowerCase(); + if (["png", "jpg", "jpeg", "gif", "webp", "svg"].includes(extension)) return "▧"; + return "·"; + } + + function FileTreeNode({ entry, depth, childrenByPath, expanded, loadingPaths, selected, onToggle, onSelect, onContextMenu }) { + const isDirectory = entry.type === "directory"; + const isExpanded = isDirectory && expanded.has(entry.path); + const children = childrenByPath[entry.path] || []; + return
+
onContextMenu(event, entry)} style={{ paddingLeft: 8 + depth * 16 }}> + {isDirectory ? : } + {!isDirectory ? {formatSize(entry.size)} : null} +
+ {isExpanded ?
{children.map((child) => )}
: null} +
; + } + + function Preview({ selected, value, editing, draft, saving, onBeginEdit, onDraftChange, onSave, onCancelEdit, onReveal }) { const source = useMemo(() => { if (!value?.base64) return ""; const binary = atob(value.base64); const bytes = new Uint8Array(binary.length); @@ -50,8 +169,13 @@ window.__ModuleLoader__.load({ useEffect(() => () => { if (source) URL.revokeObjectURL(source); }, [source]); if (!selected) return
选择文件以预览
; return
-
{selected}{value ? {formatSize(value.size)} : null}
+
{selected}{value ? {formatSize(value.size)} : null}
+ {value?.kind === "text" ? editing ? <> : : null} + +
{!value ?
正在读取…
+ : value.kind === "text" && editing ?