From db25292fb03cf9360ce0a97b684a1deb3ec3b664 Mon Sep 17 00:00:00 2001 From: wangmingxiang Date: Wed, 21 Oct 2026 19:24:14 +0800 Subject: [PATCH 1/6] =?UTF-8?q?chore(deps):=20=E6=9B=B4=E6=96=B0=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E7=89=88=E6=9C=AC=E5=92=8C=E7=A7=BB=E9=99=A4=E9=83=A8?= =?UTF-8?q?=E5=88=86=E8=A6=86=E7=9B=96=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 vite、vitest 和 ws 的覆盖版本配置 - 更新 @deepseek-ai 相关包的版本缓存标识 - 新增多种依赖包,包含 @modelcontextprotocol/sdk 和其他实用库 - 更新多个包的版本与依赖关系 - 添加和升级相关的节点模块依赖及其引擎版本要求 - 调整锁文件中依赖的完整性校验和元数据 --- docs/agents/telemetry-change.md | 1 + packages/commands/src/commands/image/edit.ts | 99 +- .../commands/src/commands/image/generate.ts | 88 +- .../commands/src/commands/shared/aigc-mcp.ts | 316 ++++ .../commands/src/commands/speech/recognize.ts | 93 +- .../src/commands/speech/synthesize.ts | 113 +- .../commands/src/commands/video/generate.ts | 209 ++- packages/commands/tests/aigc-mcp-gate.test.ts | 149 ++ .../tests/e2e/aigc-auto-mcp.e2e.test.ts | 323 +++++ packages/core/package.json | 17 +- packages/core/src/client/aigc-mcp.ts | 265 ++++ packages/core/src/client/client.ts | 15 +- packages/core/src/client/headers.ts | 21 +- packages/core/src/client/index.ts | 25 +- packages/core/src/client/mcp-sdk.ts | 306 ++++ packages/core/src/client/mcp-sse.ts | 474 ------ packages/core/src/client/mcp.ts | 239 +-- packages/core/src/files/index.ts | 1 + packages/core/src/files/upload.ts | 38 +- packages/core/tests/aigc-mcp.test.ts | 151 ++ packages/core/tests/index.test.ts | 34 - packages/core/tests/mcp.test.ts | 813 ++++------- pnpm-lock.yaml | 1277 ++++++++++++++--- skills/bailian-gen/reference/image.md | 8 + skills/bailian-gen/reference/speech.md | 8 + skills/bailian-gen/reference/video.md | 1 + 26 files changed, 3657 insertions(+), 1427 deletions(-) create mode 100644 packages/commands/src/commands/shared/aigc-mcp.ts create mode 100644 packages/commands/tests/aigc-mcp-gate.test.ts create mode 100644 packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts create mode 100644 packages/core/src/client/aigc-mcp.ts create mode 100644 packages/core/src/client/mcp-sdk.ts delete mode 100644 packages/core/src/client/mcp-sse.ts create mode 100644 packages/core/tests/aigc-mcp.test.ts diff --git a/docs/agents/telemetry-change.md b/docs/agents/telemetry-change.md index 600c8302b..91b314ff3 100644 --- a/docs/agents/telemetry-change.md +++ b/docs/agents/telemetry-change.md @@ -64,6 +64,7 @@ - `channel` 与 `t1` 是当前固定口径 - `User-Agent` 是独立标识:`bl` 为 `bailian-cli/`,`kscli` 为 `knowledge-studio-cli/` - `X-Dashscope-Service: bailian-cli` 与 source-config 一起由 `trackingHeaders()` 注入;凡走该函数的百炼 / DashScope 请求(含 MCP 注册与 JSON-RPC)都会带上。OSS、结果文件下载、npm / Skill 仍不发送。 +- **AIGC auto MCP 例外**:AIGC 命令解析出的模型为保留值 `auto` 时,经 `withAigcMcpSession` 调用的 4 个生成类 MCP server(TextGenerateImage / VideoGenerate / TextGenerateSpeech / SpeechGenerateText)把 `X-Dashscope-Service` 覆写为 `bailian-cli-call`(常量 `MCP_CALL_SERVICE`),供网关单独归因 CLI 发起的 MCP 生成流量;此时 `source-config` 的 `channel` 仍是 `bailian-cli`,只有 Service 头变。其它 MCP 命令(`search web`、`mcp tools`、`mcp call`)与所有 REST 请求保持 `bailian-cli`。覆写经 `connectBailianMcp(serverCode, urlOverride?, serviceSource?)` → `connectBailianMcpWithFallback` → `SdkMcpAdapter` → `trackingHeaders(identity, service = CHANNEL)` 逐层透传,未传时回落默认 `CHANNEL`。 source-config 只用于百炼 / DashScope API 侧消费,不发送到通用网络传输: diff --git a/packages/commands/src/commands/image/edit.ts b/packages/commands/src/commands/image/edit.ts index e6af2c0ae..4189eace1 100644 --- a/packages/commands/src/commands/image/edit.ts +++ b/packages/commands/src/commands/image/edit.ts @@ -22,6 +22,11 @@ import { ASYNC_FLAG, CONCURRENT_FLAG, redactDataUri, + bailianMcpPath, + AIGC_MCP_SERVER, + AIGC_MCP_TOOL, + buildImageEditArgs, + parseAigcImageResults, } from "bailian-cli-core"; import { poll } from "bailian-cli-runtime"; import { downloadFile } from "bailian-cli-runtime"; @@ -30,6 +35,14 @@ import { emitResult, emitBare } from "bailian-cli-runtime"; import { resolveImageSize } from "bailian-cli-runtime"; import { join } from "path"; import { BOOL_FLAG_PROMPT_EXTEND_CLI_TRUE, BOOL_FLAG_WATERMARK } from "bailian-cli-runtime"; +import { + isAutoModel, + assertMcpCompatible, + withAigcMcpSession, + resolveAutoImageInput, + mcpSingleImageOnlyError, + type Localize, +} from "../shared/aigc-mcp.ts"; const EDIT_FLAGS = { image: { @@ -181,6 +194,14 @@ export default defineCommand({ "zh-CN": '--image ./photo.png --prompt "将背景替换为海滩" --watermark false', }, ], + notes: [ + { + "en-US": + 'Model "auto" (via --model auto or a config default model of "auto") routes to the official Bailian MCP with a reduced parameter set; MCP-incompatible flags fail fast with a usage error instead of falling back to REST. Auto edit accepts a single --image only.', + "zh-CN": + '模型 "auto"(通过 --model auto 或将配置默认模型设为 "auto")改走百炼官方 MCP,参数面更小;MCP 不支持的参数会直接报用法错误,而不回退 REST。auto 编辑仅支持单个 --image。', + }, + ], async run(ctx) { const { settings, flags } = ctx; // Normalize --image to string array (supports both single and repeated flags) @@ -192,7 +213,20 @@ export default defineCommand({ } const prompt = flags.prompt; - const model = flags.model || settings.defaultImageModel || "qwen-image-3.0"; + const resolvedModel = flags.model || settings.defaultImageModel; + if (isAutoModel(resolvedModel)) { + await handleAutoMcpMode( + ctx.client, + ctx.localize, + settings, + flags, + rawImages, + detectOutputFormat(settings.output), + ); + return; + } + + const model = resolvedModel || "qwen-image-3.0"; const route = resolveImageEditApi(model); // Auto-upload local files (resolve all images in parallel) @@ -329,6 +363,69 @@ export default defineCommand({ }, }); +async function handleAutoMcpMode( + client: Client, + localize: Localize, + settings: Settings, + flags: EditFlags, + rawImages: string[], + format: OutputFormat, +): Promise { + assertMcpCompatible("imageEdit", flags, localize); + + // bailian_image_edit takes a single source image; bailian_image_fusion is out + // of scope, so multi-image merge is rejected in auto mode. + if (rawImages.length > 1) { + throw mcpSingleImageOnlyError(localize); + } + const source = rawImages[0]; + if (!source) { + throw new BailianError("Provide one --image to edit.", ExitCode.USAGE); + } + + const imageUrl = resolveAutoImageInput(source, localize); + const concurrent = getConcurrency(flags); + const args = buildImageEditArgs({ + imageUrl, + prompt: flags.prompt, + negativePrompt: flags.negativePrompt || undefined, + }); + + if (settings.dryRun) { + emitResult( + { + server: AIGC_MCP_SERVER.image, + url: client.url(bailianMcpPath(AIGC_MCP_SERVER.image)), + tool: AIGC_MCP_TOOL.imageEdit, + arguments: { ...args, image_url: redactDataUri(imageUrl) }, + mode: "mcp", + concurrent, + }, + format, + ); + return; + } + + if (!settings.quiet) { + process.stderr.write("[Model: auto] [Mode: mcp] [Images: 1]\n"); + } + + // One shared MCP session; --concurrent fans out parallel tools/call on it. + await withAigcMcpSession(client, AIGC_MCP_SERVER.image, localize, async (callTool) => { + const perRequest = await runConcurrent(concurrent, settings, async () => { + const inner = await callTool(AIGC_MCP_TOOL.imageEdit, args); + return parseAigcImageResults(inner); + }); + + const imageUrls = perRequest.flat(); + if (imageUrls.length === 0) { + throw new BailianError("Edit completed but no images returned.", ExitCode.GENERAL); + } + + await saveImages(imageUrls, flags, settings, format); + }); +} + async function handleSyncMode( client: Client, settings: Settings, diff --git a/packages/commands/src/commands/image/generate.ts b/packages/commands/src/commands/image/generate.ts index 6c09a12b0..e62387485 100644 --- a/packages/commands/src/commands/image/generate.ts +++ b/packages/commands/src/commands/image/generate.ts @@ -20,6 +20,11 @@ import { resolveImageGenerateApi, ASYNC_FLAG, CONCURRENT_FLAG, + bailianMcpPath, + AIGC_MCP_SERVER, + AIGC_MCP_TOOL, + buildImageGenArgs, + parseAigcImageResults, } from "bailian-cli-core"; import { poll } from "bailian-cli-runtime"; import { downloadFile } from "bailian-cli-runtime"; @@ -27,6 +32,12 @@ import { runConcurrent, downloadParallel, getConcurrency } from "bailian-cli-run import { emitResult, emitBare } from "bailian-cli-runtime"; import { resolveImageSize } from "bailian-cli-runtime"; import { BOOL_FLAG_PROMPT_EXTEND_IMAGE_GENERATE, BOOL_FLAG_WATERMARK } from "bailian-cli-runtime"; +import { + isAutoModel, + assertMcpCompatible, + withAigcMcpSession, + type Localize, +} from "../shared/aigc-mcp.ts"; import { join } from "path"; @@ -167,11 +178,31 @@ export default defineCommand({ "zh-CN": '--prompt "产品摄影" --n 2 --concurrent 3 # 并行生成 6 张图片', }, ], + notes: [ + { + "en-US": + 'Model "auto" (via --model auto or a config default model of "auto") routes to the official Bailian MCP with a reduced parameter set; MCP-incompatible flags fail fast with a usage error instead of falling back to REST.', + "zh-CN": + '模型 "auto"(通过 --model auto 或将配置默认模型设为 "auto")改走百炼官方 MCP,参数面更小;MCP 不支持的参数会直接报用法错误,而不回退 REST。', + }, + ], async run(ctx) { const { settings, flags } = ctx; const prompt = flags.prompt; - const model = flags.model || settings.defaultImageModel || "qwen-image-3.0"; + const resolvedModel = flags.model || settings.defaultImageModel; + if (isAutoModel(resolvedModel)) { + await handleAutoMcpMode( + ctx.client, + ctx.localize, + settings, + flags, + detectOutputFormat(settings.output), + ); + return; + } + + const model = resolvedModel || "qwen-image-3.0"; const route = resolveImageGenerateApi(model); const defaultSize = "1:1"; const sizeInput = flags.size || defaultSize; @@ -238,6 +269,61 @@ export default defineCommand({ }, }); +// ---- Auto mode: Bailian AIGC MCP (bailian_image_gen) ---- + +async function handleAutoMcpMode( + client: Client, + localize: Localize, + settings: Settings, + flags: GenerateFlags, + format: string, +): Promise { + assertMcpCompatible("imageGen", flags, localize); + + const concurrent = getConcurrency(flags); + const args = buildImageGenArgs({ + prompt: flags.prompt, + size: flags.size || undefined, + n: flags.n, + negativePrompt: flags.negativePrompt || undefined, + promptExtend: flags.promptExtend, + }); + + if (settings.dryRun) { + emitResult( + { + server: AIGC_MCP_SERVER.image, + url: client.url(bailianMcpPath(AIGC_MCP_SERVER.image)), + tool: AIGC_MCP_TOOL.imageGen, + arguments: args, + mode: "mcp", + concurrent, + }, + format as OutputFormat, + ); + return; + } + + if (!settings.quiet) { + process.stderr.write("[Model: auto] [Mode: mcp]\n"); + } + + // One shared MCP session; --concurrent fans out parallel tools/call on it. + await withAigcMcpSession(client, AIGC_MCP_SERVER.image, localize, async (callTool) => { + const perRequest = await runConcurrent(concurrent, settings, async () => { + const inner = await callTool(AIGC_MCP_TOOL.imageGen, args); + return parseAigcImageResults(inner); + }); + + const imageUrls = perRequest.flat(); + if (imageUrls.length === 0) { + throw new BailianError("Generation completed but no images returned.", ExitCode.GENERAL); + } + + await saveImages(imageUrls, flags, settings, format); + }); +} + // ---- Sync mode: qwen-image / wan2.7-image / z-image ---- async function handleSyncMode( diff --git a/packages/commands/src/commands/shared/aigc-mcp.ts b/packages/commands/src/commands/shared/aigc-mcp.ts new file mode 100644 index 000000000..cf9f7d821 --- /dev/null +++ b/packages/commands/src/commands/shared/aigc-mcp.ts @@ -0,0 +1,316 @@ +/** + * AIGC "auto" mode — command-side glue. + * + * When an AIGC command resolves its effective model to the reserved value + * `auto`, generation is routed through Bailian's official AIGC MCP servers + * instead of the DashScope REST endpoints. This module owns everything that + * needs a {@link CommandContext}: the `auto` check, the parameter + * compatibility gate (flags MCP cannot honor → USAGE error, no silent REST + * fallback), and a shared-session MCP call wrapper that `--concurrent` fan-out + * reuses. + * + * The transport-agnostic mapping (server codes, tool names, request-argument + * builders, response parsers) lives in core — `bailian-cli-core` re-exports + * `packages/core/src/client/aigc-mcp.ts`. + */ + +import { + BailianError, + ExitCode, + parseAigcToolResult, + imageFileToDataUri, + audioFileToDataUri, + MCP_CALL_SERVICE, + type Client, + type LocalizedText, + type McpConnectedClient, +} from "bailian-cli-core"; + +/** Localizer supplied by the runtime (`CommandContext.localize`). */ +export type Localize = (text: LocalizedText) => string; + +/** The reserved model value that routes an AIGC command through MCP. */ +export const AUTO_MODEL = "auto"; + +/** True when the resolved effective model is the reserved `auto` value. */ +export function isAutoModel(model: string | undefined): boolean { + return model === AUTO_MODEL; +} + +// ---- Parameter compatibility gate ---- + +/** AIGC operations that can be routed through MCP in `auto` mode. */ +export type AigcMcpOperation = + | "imageGen" + | "imageEdit" + | "videoTextToVideo" + | "videoImageToVideo" + | "tts" + | "asr"; + +interface IncompatibleFlag { + /** Key in the command's `ParsedFlags`. */ + key: string; + /** CLI flag name shown to the user (kebab-case, with leading `--`). */ + flag: string; + /** Switch flags are "present" when `true`; value flags when `!== undefined`. */ + kind: "switch" | "value"; +} + +function switchFlag(key: string, flag: string): IncompatibleFlag { + return { key, flag, kind: "switch" }; +} + +function valueFlag(key: string, flag: string): IncompatibleFlag { + return { key, flag, kind: "value" }; +} + +/** + * Per-operation flags that MCP cannot honor in `auto` mode; presence of any of + * them raises `BailianError(USAGE)`. Derived from the live tool inputSchemas: + * `bailian_image_gen`(prompt/size/negative_prompt/prompt_extend/n), + * `bailian_image_edit`(image_url/prompt/negative_prompt), + * `bailian_text_to_video_submit_task`(prompt/duration/resolution/ratio), + * `bailian_image_to_video_submit_task`(first_frame_url/prompt/duration/resolution), + * `bailian_tts`(text/voice), `bailian_speech_to_text`(file_urls). MCP has no + * model/seed/watermark concept and TTS has no format/sample-rate/stream, so the + * corresponding flags are rejected. CLI-local output flags (`--out*`, + * `--download`) and `--concurrent` are honored on this side and stay allowed. + */ +const MCP_INCOMPATIBLE_FLAGS: Record = { + imageGen: [ + valueFlag("seed", "--seed"), + valueFlag("watermark", "--watermark"), + switchFlag("async", "--async"), + ], + imageEdit: [ + valueFlag("size", "--size"), + valueFlag("n", "--n"), + valueFlag("seed", "--seed"), + valueFlag("function", "--function"), + valueFlag("promptExtend", "--prompt-extend"), + valueFlag("watermark", "--watermark"), + switchFlag("async", "--async"), + ], + videoTextToVideo: [ + valueFlag("lastFrame", "--last-frame"), + valueFlag("file", "--file"), + valueFlag("negativePrompt", "--negative-prompt"), + valueFlag("promptExtend", "--prompt-extend"), + valueFlag("watermark", "--watermark"), + valueFlag("seed", "--seed"), + switchFlag("prime", "--prime"), + valueFlag("workspaceId", "--workspace-id"), + switchFlag("async", "--async"), + ], + videoImageToVideo: [ + valueFlag("ratio", "--ratio"), + valueFlag("lastFrame", "--last-frame"), + valueFlag("file", "--file"), + valueFlag("negativePrompt", "--negative-prompt"), + valueFlag("promptExtend", "--prompt-extend"), + valueFlag("watermark", "--watermark"), + valueFlag("seed", "--seed"), + switchFlag("prime", "--prime"), + valueFlag("workspaceId", "--workspace-id"), + switchFlag("async", "--async"), + ], + tts: [ + switchFlag("listVoices", "--list-voices"), + valueFlag("format", "--format"), + valueFlag("sampleRate", "--sample-rate"), + valueFlag("volume", "--volume"), + valueFlag("rate", "--rate"), + valueFlag("pitch", "--pitch"), + valueFlag("seed", "--seed"), + valueFlag("language", "--language"), + valueFlag("instruction", "--instruction"), + switchFlag("enableSsml", "--enable-ssml"), + switchFlag("stream", "--stream"), + ], + asr: [ + valueFlag("language", "--language"), + switchFlag("diarization", "--diarization"), + valueFlag("speakerCount", "--speaker-count"), + valueFlag("vocabularyId", "--vocabulary-id"), + valueFlag("vocabulary", "--vocabulary"), + valueFlag("context", "--context"), + valueFlag("channelId", "--channel-id"), + switchFlag("async", "--async"), + ], +}; + +function isFlagPresent(flags: Record, spec: IncompatibleFlag): boolean { + const value = flags[spec.key]; + if (spec.kind === "switch") return value === true; + return value !== undefined; +} + +/** + * Build the localized USAGE error for `auto` mode rejecting flags/usage MCP + * cannot honor. Exported so command-local checks (e.g. multi-image edit) can + * raise a consistent message. + */ +export function mcpUnsupportedError(localize: Localize, names: string[]): BailianError { + const list = names.join(", "); + const many = names.length > 1; + const message = localize({ + "en-US": `The current model (auto) does not support ${list}. Switch to a specific model or remove ${many ? "these flags" : "this flag"}.`, + "zh-CN": `当前模型(auto)不支持参数 ${list},请切换为具体模型或移除${many ? "这些参数" : "该参数"}。`, + }); + const hint = localize({ + "en-US": + 'Pass --model to use a specific model, or set a concrete default model in your config instead of "auto".', + "zh-CN": '传入 --model 指定具体模型,或在配置中把默认模型设为具体值而非 "auto"。', + }); + return new BailianError(message, ExitCode.USAGE, hint); +} + +/** + * Reject any flag MCP cannot honor for `operation` in `auto` mode. Throws + * `BailianError(USAGE)`; never falls back to REST silently. + */ +export function assertMcpCompatible( + operation: AigcMcpOperation, + flags: Record, + localize: Localize, +): void { + const offending = MCP_INCOMPATIBLE_FLAGS[operation] + .filter((spec) => isFlagPresent(flags, spec)) + .map((spec) => spec.flag); + if (offending.length > 0) { + throw mcpUnsupportedError(localize, offending); + } +} + +/** `auto` image edit accepts a single source image only (no `bailian_image_fusion`). */ +export function mcpSingleImageOnlyError(localize: Localize): BailianError { + const message = localize({ + "en-US": + "The current model (auto) supports editing a single image only; multiple --image inputs are not supported. Switch to a specific model or pass one image.", + "zh-CN": + "当前模型(auto)仅支持单图编辑,不支持多个 --image 输入。请切换为具体模型或只传入一张图片。", + }); + const hint = localize({ + "en-US": + 'Pass --model to use a specific model, or set a concrete default model in your config instead of "auto".', + "zh-CN": '传入 --model 指定具体模型,或在配置中把默认模型设为具体值而非 "auto"。', + }); + return new BailianError(message, ExitCode.USAGE, hint); +} + +// ---- Local file input (auto mode inlines files as base64 data URIs) ---- + +/** + * Conservative cap on the inline base64 data-URI size sent through MCP. The + * AIGC MCP servers accept a public http(s) URL or a base64 data URI but reject + * `oss://` and private upload URLs, so `auto` mode inlines local files; an + * oversized payload would bloat the JSON-RPC body and fail obscurely, so it is + * rejected up front with an actionable message. + */ +const MAX_MCP_DATA_URI_BYTES = 10 * 1024 * 1024; + +/** True for inputs already carrying a URL / inline scheme (not a local path). */ +function isUrlScheme(source: string): boolean { + return /^(https?|oss|data):/i.test(source); +} + +function guardDataUriSize(dataUri: string, kind: "image" | "audio", localize: Localize): string { + if (dataUri.length <= MAX_MCP_DATA_URI_BYTES) return dataUri; + const message = localize({ + "en-US": `The local ${kind} file is too large to inline through MCP in auto mode (limit ~10 MB after base64 encoding). Host it at a public http(s) URL, or switch to a specific --model.`, + "zh-CN": `本地${kind === "image" ? "图片" : "音频"}文件过大,无法在 auto 模式下通过 MCP 内联发送(base64 编码后上限约 10 MB)。请将其托管为公网 http(s) URL,或切换为具体的 --model。`, + }); + const hint = localize({ + "en-US": + "Pass a public http(s) URL instead of a local path, or use --model to switch to the REST path.", + "zh-CN": "请传入公网 http(s) URL 而非本地路径,或使用 --model 切换回 REST。", + }); + throw new BailianError(message, ExitCode.USAGE, hint); +} + +/** + * Resolve an `auto`-mode image input: local paths are inlined as base64 data + * URIs; http(s) URLs and data URIs pass through verbatim. + */ +export function resolveAutoImageInput(source: string, localize: Localize): string { + if (isUrlScheme(source)) return source; + return guardDataUriSize(imageFileToDataUri(source), "image", localize); +} + +/** Resolve an `auto`-mode audio input the same way (ASR `file_urls`). */ +export function resolveAutoAudioInput(source: string, localize: Localize): string { + if (isUrlScheme(source)) return source; + return guardDataUriSize(audioFileToDataUri(source), "audio", localize); +} + +// ---- Shared-session MCP call wrapper ---- + +/** A single MCP tool call that returns the parsed inner JSON payload. */ +export type AigcMcpCallTool = ( + tool: string, + args: Record, +) => Promise>; + +/** + * Append a "switch to a specific model" hint to a transport/connect failure, + * preserving the original message and exit code (AGENTS.md §3 — server errors + * are passed through verbatim; only internal transport failures get a hint). + * AUTH/USAGE errors and tool-level errors are re-thrown untouched. + */ +function withAutoModelHint(error: unknown, localize: Localize): never { + if ( + error instanceof BailianError && + !error.hint && + (error.exitCode === ExitCode.NETWORK || error.exitCode === ExitCode.GENERAL) + ) { + const hint = localize({ + "en-US": + 'MCP generation failed. To use the REST path instead, run with a specific --model (or set a concrete default model instead of "auto").', + "zh-CN": + 'MCP 生成失败。如需改走 REST,请使用具体的 --model (或将默认模型设为具体值而非 "auto")。', + }); + throw new BailianError(error.message, error.exitCode, hint, { + cause: error, + api: error.api, + rawResponse: error.rawResponse, + }); + } + throw error; +} + +/** + * Open one MCP session for `serverCode`, run `work` against it, then always + * close. `connectBailianMcp` returns an already-initialized client, so this + * does not re-initialize. Concurrent `--concurrent` fan-out shares this single + * session (the servers are stateless and accept parallel `tools/call`). + * + * Every AIGC auto call is attributed with `X-Dashscope-Service: bailian-cli-call` + * (`MCP_CALL_SERVICE`) so the gateway can separate it from the default channel. + * + * Tool-level failures surface through `parseAigcToolResult` (server text passed + * through verbatim); transport/connect failures get the switch-model hint. + */ +export async function withAigcMcpSession( + client: Client, + serverCode: string, + localize: Localize, + work: (callTool: AigcMcpCallTool) => Promise, +): Promise { + let connected: { client: McpConnectedClient; url: string }; + try { + connected = await client.connectBailianMcp(serverCode, undefined, MCP_CALL_SERVICE); + } catch (error) { + throw withAutoModelHint(error, localize); + } + + const mcpClient = connected.client; + const callTool: AigcMcpCallTool = async (tool, args) => + parseAigcToolResult(await mcpClient.callTool(tool, args)); + + try { + return await work(callTool); + } finally { + mcpClient.close?.(); + } +} diff --git a/packages/commands/src/commands/speech/recognize.ts b/packages/commands/src/commands/speech/recognize.ts index 65b0cedd2..ab9f88a00 100644 --- a/packages/commands/src/commands/speech/recognize.ts +++ b/packages/commands/src/commands/speech/recognize.ts @@ -25,9 +25,22 @@ import { type FlagsDef, type ParsedFlags, ASYNC_FLAG, + redactDataUri, + bailianMcpPath, + AIGC_MCP_SERVER, + AIGC_MCP_TOOL, + buildSpeechToTextArgs, + parseAigcAsrTexts, } from "bailian-cli-core"; import { poll } from "bailian-cli-runtime"; import { emitResult, emitBare } from "bailian-cli-runtime"; +import { + isAutoModel, + assertMcpCompatible, + withAigcMcpSession, + resolveAutoAudioInput, + type Localize, +} from "../shared/aigc-mcp.ts"; const RECOGNIZE_FLAGS = { url: { @@ -195,6 +208,14 @@ export default defineCommand({ "--url https://example.com/audio.mp3 --async --quiet", "--url https://example.com/audio.mp3 --model qwen-audio-3.0-asr-flash --language en", ], + notes: [ + { + "en-US": + 'Model "auto" (via --model auto or a config default model of "auto") routes to the official Bailian MCP with a reduced parameter set and simplified text output; MCP-incompatible flags fail fast with a usage error instead of falling back to REST.', + "zh-CN": + '模型 "auto"(通过 --model auto 或将配置默认模型设为 "auto")改走百炼官方 MCP,参数面更小、输出为简化文本;MCP 不支持的参数会直接报用法错误,而不回退 REST。', + }, + ], async run(ctx) { const { settings, flags } = ctx; // Normalize --url to string[] (supports both single and repeated flags) @@ -205,6 +226,19 @@ export default defineCommand({ rawUrls = [flags.url]; } + const resolvedModel = flags.model || settings.defaultSpeechRecognitionModel; + if (isAutoModel(resolvedModel)) { + await handleAutoMcpMode( + ctx.client, + ctx.localize, + settings, + flags, + rawUrls, + detectOutputFormat(settings.output), + ); + return; + } + // Strict validation: --speaker-count requires --diarization const speakerCount = flags.speakerCount; const diarization = flags.diarization === true; @@ -215,7 +249,7 @@ export default defineCommand({ ); } - const model = flags.model || settings.defaultSpeechRecognitionModel || "fun-asr"; + const model = resolvedModel || "fun-asr"; const route = resolveAsrApi(model); if (route.kind === "unsupported") { throw new BailianError( @@ -309,6 +343,63 @@ export default defineCommand({ }, }); +async function handleAutoMcpMode( + client: Client, + localize: Localize, + settings: Settings, + flags: RecognizeFlags, + rawUrls: string[], + format: OutputFormat, +): Promise { + assertMcpCompatible("asr", flags, localize); + + if (rawUrls.length === 0) { + throw new BailianError("Provide at least one --url to recognize.", ExitCode.USAGE); + } + + // Public http(s)/oss URLs pass through; local files become inline base64 data + // URIs (the MCP server rejects oss:// and cannot fetch private uploads). + const fileUrls = rawUrls.map((source) => resolveAutoAudioInput(source, localize)); + const args = buildSpeechToTextArgs(fileUrls); + + if (settings.dryRun) { + emitResult( + { + server: AIGC_MCP_SERVER.asr, + url: client.url(bailianMcpPath(AIGC_MCP_SERVER.asr)), + tool: AIGC_MCP_TOOL.speechToText, + arguments: { ...args, file_urls: fileUrls.map((fileUrl) => redactDataUri(fileUrl)) }, + mode: "mcp", + }, + format, + ); + return; + } + + if (!settings.quiet) { + process.stderr.write(`[Model: auto] [Mode: mcp] [Files: ${fileUrls.length}]\n`); + } + + // bailian_speech_to_text is synchronous: one tools/call returns all transcripts. + const result = await withAigcMcpSession(client, AIGC_MCP_SERVER.asr, localize, (callTool) => + callTool(AIGC_MCP_TOOL.speechToText, args), + ); + + const texts = parseAigcAsrTexts(result); + + // Simplified output: plain transcription text, one entry per line. + for (const text of texts) { + process.stdout.write(text.endsWith("\n") ? text : `${text}\n`); + } + + if (flags.out) { + writeFileSync(flags.out, JSON.stringify(texts, null, 2) + "\n"); + if (!settings.quiet) { + process.stderr.write(`Full result saved to: ${flags.out}\n`); + } + } +} + async function handleSyncFlashMode( client: Client, settings: Settings, diff --git a/packages/commands/src/commands/speech/synthesize.ts b/packages/commands/src/commands/speech/synthesize.ts index 023709ea3..6987d7a54 100644 --- a/packages/commands/src/commands/speech/synthesize.ts +++ b/packages/commands/src/commands/speech/synthesize.ts @@ -18,12 +18,23 @@ import { type FlagsDef, type ParsedFlags, CONCURRENT_FLAG, + bailianMcpPath, + AIGC_MCP_SERVER, + AIGC_MCP_TOOL, + buildTtsArgs, + parseAigcTtsResult, } from "bailian-cli-core"; import { downloadFile } from "bailian-cli-runtime"; import { runConcurrent, downloadParallel, getConcurrency } from "bailian-cli-runtime"; import { emitResult, emitBare } from "bailian-cli-runtime"; import { VOICE_TTS_PAGE } from "bailian-cli-runtime"; +import { + isAutoModel, + assertMcpCompatible, + withAigcMcpSession, + type Localize, +} from "../shared/aigc-mcp.ts"; const COSYVOICE_CLONE_DESIGN_DOC = `${DOCS_HOSTS.cn}/cosyvoice-clone-design-api`; const QWEN_AUDIO_TTS_VOICE_DOC = `${DOCS_HOSTS.cn}/qwen-audio-tts-voice-list`; @@ -366,6 +377,14 @@ export default defineCommand({ '--text "你好" --voice --stream | ffplay -nodisp -autoexit -f s16le -ar 24000 -ac 1 -', }, ], + notes: [ + { + "en-US": + 'Model "auto" (via --model auto or a config default model of "auto") routes to the official Bailian MCP with a reduced parameter set; MCP-incompatible flags fail fast with a usage error instead of falling back to REST.', + "zh-CN": + '模型 "auto"(通过 --model auto 或将配置默认模型设为 "auto")改走百炼官方 MCP,参数面更小;MCP 不支持的参数会直接报用法错误,而不回退 REST。', + }, + ], validate: (f) => { if (f.listVoices) return undefined; if (!f.text && !f.textFile) return "Provide --text or --text-file."; @@ -375,7 +394,20 @@ export default defineCommand({ }, async run(ctx) { const { settings, flags } = ctx; - const model = flags.model || settings.defaultSpeechModel || "cosyvoice-v3-flash"; + + const resolvedModel = flags.model || settings.defaultSpeechModel; + if (isAutoModel(resolvedModel)) { + await handleAutoMcpMode( + ctx.client, + ctx.localize, + settings, + flags, + detectOutputFormat(settings.output), + ); + return; + } + + const model = resolvedModel || "cosyvoice-v3-flash"; // --list-voices: print voice list for the model and exit if (flags.listVoices) { @@ -445,6 +477,85 @@ export default defineCommand({ }, }); +async function handleAutoMcpMode( + client: Client, + localize: Localize, + settings: Settings, + flags: SynthesizeFlags, + format: OutputFormat, +): Promise { + assertMcpCompatible("tts", flags, localize); + + // Same text precedence as REST: --text, else --text-file. + let text = flags.text || ""; + if (!text && flags.textFile) { + const filePath = flags.textFile; + try { + text = readFileSync(filePath, "utf-8").trim(); + } catch { + throw new BailianError(`Cannot read text file: ${filePath}`, ExitCode.USAGE); + } + } + // Voice is passed through verbatim (validate enforces its presence); the MCP + // server validates it against its own voice enum. + const voice = flags.voice as string; + const args = buildTtsArgs({ text, voice }); + + if (settings.dryRun) { + emitResult( + { + server: AIGC_MCP_SERVER.speech, + url: client.url(bailianMcpPath(AIGC_MCP_SERVER.speech)), + tool: AIGC_MCP_TOOL.tts, + arguments: args, + mode: "mcp", + }, + format, + ); + return; + } + + if (!settings.quiet) { + process.stderr.write(`[Model: auto] [Mode: mcp] [Voice: ${voice}]\n`); + } + + const concurrent = getConcurrency(flags); + // One shared MCP session; --concurrent fans out parallel tools/call on it. + const audios = await withAigcMcpSession( + client, + AIGC_MCP_SERVER.speech, + localize, + async (callTool) => + runConcurrent(concurrent, settings, async () => { + const inner = await callTool(AIGC_MCP_TOOL.tts, args); + return parseAigcTtsResult(inner); + }), + ); + + const path = await import("path"); + const destDir = resolveOutputDir(settings, { subDir: "speech" }); + const audioUrls = audios.map((audio) => audio.audioUrl); + const items = audioUrls.map((audioUrl, index) => { + const suffix = audioUrls.length > 1 ? `_${String(index + 1).padStart(3, "0")}` : ""; + const destPath = + flags.out && audioUrls.length === 1 + ? flags.out + : path.join(destDir, `tts_${Date.now()}${suffix}.wav`); + return { url: audioUrl, destPath }; + }); + + const saved = await downloadParallel(items, downloadFile, { quiet: settings.quiet }); + + // auto output intentionally omits `model` (there is no specific REST model). + if (settings.quiet) { + emitBare(saved.join("\n")); + } else if (saved.length === 1) { + emitResult({ saved: saved[0], audio_url: audioUrls[0], voice }, format); + } else { + emitResult({ saved, audio_urls: audioUrls, total: saved.length, voice }, format); + } +} + async function handleNonStreamMode( client: Client, settings: Settings, diff --git a/packages/commands/src/commands/video/generate.ts b/packages/commands/src/commands/video/generate.ts index 1108ca98a..5bbcee71c 100644 --- a/packages/commands/src/commands/video/generate.ts +++ b/packages/commands/src/commands/video/generate.ts @@ -7,6 +7,8 @@ import { type DashScopeVideoRequest, type DashScopeAsyncResponse, type DashScopeTaskResponse, + type Settings, + type OutputFormat, resolveOutputDir, BailianError, ExitCode, @@ -15,13 +17,28 @@ import { ASYNC_FLAG, CONCURRENT_FLAG, redactDataUri, + bailianMcpPath, + AIGC_MCP_SERVER, + AIGC_MCP_TOOL, + buildTextToVideoArgs, + buildImageToVideoArgs, + buildVideoFetchArgs, + parseAigcVideoTaskId, + parseAigcVideoTaskResult, } from "bailian-cli-core"; -import { poll } from "bailian-cli-runtime"; +import { poll, createSpinner } from "bailian-cli-runtime"; import { downloadFile, formatBytes } from "bailian-cli-runtime"; import { runConcurrent, getConcurrency } from "bailian-cli-runtime"; import { emitResult, emitBare } from "bailian-cli-runtime"; import { BOOL_FLAG_PROMPT_EXTEND_API_DEFAULT, BOOL_FLAG_WATERMARK } from "bailian-cli-runtime"; import { PRIME_FLAGS, resolvePrimeEndpoint, validatePrimeFlags } from "../shared/prime.ts"; +import { + isAutoModel, + assertMcpCompatible, + withAigcMcpSession, + resolveAutoImageInput, + type AigcMcpCallTool, +} from "../shared/aigc-mcp.ts"; export default defineCommand({ description: { @@ -169,6 +186,12 @@ export default defineCommand({ }, ], notes: [ + { + "en-US": + 'Model "auto" (via --model auto or a config default model of "auto") routes to the official Bailian MCP with a reduced parameter set; MCP-incompatible flags fail fast with a usage error instead of falling back to REST.', + "zh-CN": + '模型 "auto"(通过 --model auto 或将配置默认模型设为 "auto")改走百炼官方 MCP,参数面更小;MCP 不支持的参数会直接报用法错误,而不回退 REST。', + }, { "en-US": "Prime mode requires an explicit model.", "zh-CN": "Prime 模式必须显式指定模型。", @@ -185,13 +208,82 @@ export default defineCommand({ const { settings, flags } = ctx; const prompt = flags.prompt; - const model = - flags.model || - (flags.image - ? settings.defaultImageToVideoModel || "wan3.0-video" - : settings.defaultVideoModel || "wan3.0-video"); + const resolvedModel = + flags.model || (flags.image ? settings.defaultImageToVideoModel : settings.defaultVideoModel); const format = detectOutputFormat(settings.output); + // auto model → official AIGC MCP (VideoGenerate); specific models keep the REST path. + if (isAutoModel(resolvedModel)) { + const imageInput = flags.image; + assertMcpCompatible( + imageInput !== undefined ? "videoImageToVideo" : "videoTextToVideo", + flags, + ctx.localize, + ); + + const duration = flags.duration || undefined; + const resolution = flags.resolution || undefined; + const firstFrameUrl = + imageInput !== undefined ? resolveAutoImageInput(imageInput, ctx.localize) : undefined; + const submitTool = + imageInput !== undefined + ? AIGC_MCP_TOOL.imageToVideoSubmit + : AIGC_MCP_TOOL.textToVideoSubmit; + const submitArgs = + imageInput !== undefined + ? buildImageToVideoArgs({ firstFrameUrl, prompt, duration, resolution }) + : buildTextToVideoArgs({ prompt, duration, resolution, ratio: flags.ratio || undefined }); + const concurrent = getConcurrency(flags); + + if (settings.dryRun) { + emitResult( + { + server: AIGC_MCP_SERVER.video, + url: ctx.client.url(bailianMcpPath(AIGC_MCP_SERVER.video)), + tool: submitTool, + arguments: firstFrameUrl + ? { ...submitArgs, first_frame_url: redactDataUri(firstFrameUrl) } + : submitArgs, + mode: "mcp", + concurrent, + }, + format, + ); + return; + } + + if (!settings.quiet) { + process.stderr.write("[Model: auto] [Mode: mcp]\n"); + } + + const pollInterval = flags.pollInterval ?? 5; + // One shared MCP session: submit N task(s), then poll each via fetch_result. + const videos = await withAigcMcpSession( + ctx.client, + AIGC_MCP_SERVER.video, + ctx.localize, + async (callTool) => { + const taskIds = await runConcurrent( + concurrent, + settings, + async () => { + const inner = await callTool(submitTool, submitArgs); + return parseAigcVideoTaskId(inner); + }, + "tasks", + ); + return Promise.all( + taskIds.map((taskId) => pollMcpVideoTask(callTool, taskId, settings, pollInterval)), + ); + }, + ); + + await saveAutoVideos(videos, flags.download, settings, format); + return; + } + + const model = resolvedModel || "wan3.0-video"; + const imageUrl = flags.image; const lastFrameUrl = flags.lastFrame as string | undefined; const fileUrl = flags.file as string | undefined; @@ -426,3 +518,108 @@ export default defineCommand({ } }, }); + +/** + * Poll a video task to completion over MCP `bailian_text_to_video_fetch_result`. + * Mirrors the REST `poll` UX (spinner + status), but the transport is a repeated + * tools/call on the shared session rather than an HTTP GET. + */ +async function pollMcpVideoTask( + callTool: AigcMcpCallTool, + taskId: string, + settings: Settings, + pollInterval: number, +): Promise<{ taskId: string; videoUrl: string }> { + const deadline = Date.now() + settings.timeout * 1000; + const spinner = createSpinner("Polling..."); + if (!settings.quiet) spinner.start(); + + try { + while (Date.now() < deadline) { + const inner = await callTool(AIGC_MCP_TOOL.videoFetchResult, buildVideoFetchArgs(taskId)); + const result = parseAigcVideoTaskResult(inner); + + if (!settings.quiet) spinner.update(`Status: ${result.taskStatus}`); + + if (result.taskStatus === "SUCCEEDED") { + spinner.stop("Done."); + if (!result.videoUrl) { + throw new BailianError( + `Video task succeeded but returned no URL: ${taskId}`, + ExitCode.GENERAL, + ); + } + return { taskId, videoUrl: result.videoUrl }; + } + + if (result.taskStatus === "FAILED") { + spinner.stop("Failed."); + throw new BailianError(`Video task failed: ${taskId}`, ExitCode.GENERAL); + } + + await new Promise((resolve) => setTimeout(resolve, pollInterval * 1000)); + } + } finally { + spinner.stop(); + } + + throw new BailianError( + "Polling timed out.", + ExitCode.TIMEOUT, + "Try increasing --timeout or check task status manually.", + ); +} + +/** Download + emit auto/MCP videos, matching the REST output shape (no `model`). */ +async function saveAutoVideos( + videos: Array<{ taskId: string; videoUrl: string }>, + downloadPath: string | undefined, + settings: Settings, + format: OutputFormat, +): Promise { + if (videos.length === 0) { + throw new BailianError("All tasks completed but no video URLs returned.", ExitCode.GENERAL); + } + + // --download: save the first video to the explicit path. + if (downloadPath) { + const { size } = await downloadFile(videos[0]!.videoUrl, downloadPath, { + quiet: settings.quiet, + }); + if (settings.quiet) { + emitBare(downloadPath); + } else { + emitResult( + { + task_id: videos[0]!.taskId, + video_url: videos[0]!.videoUrl, + status: "SUCCEEDED", + saved: downloadPath, + size: formatBytes(size), + }, + format, + ); + } + return; + } + + // Default: auto-download all to the videos output directory. + const destDir = resolveOutputDir(settings, { subDir: "videos" }); + // eslint-disable-next-line @typescript-eslint/unbound-method + const { join } = await import("path"); + + const saved: Array<{ task_id: string; video_url: string; saved: string }> = []; + await Promise.all( + videos.map(async ({ taskId, videoUrl }) => { + const destPath = join(destDir, `${taskId}.mp4`); + await downloadFile(videoUrl, destPath, { quiet: settings.quiet }); + saved.push({ task_id: taskId, video_url: videoUrl, saved: destPath }); + }), + ); + + if (saved.length === 1) { + emitResult(saved[0]!, format); + } else { + emitResult({ videos: saved, total: saved.length }, format); + } +} diff --git a/packages/commands/tests/aigc-mcp-gate.test.ts b/packages/commands/tests/aigc-mcp-gate.test.ts new file mode 100644 index 000000000..daed6b562 --- /dev/null +++ b/packages/commands/tests/aigc-mcp-gate.test.ts @@ -0,0 +1,149 @@ +import { describe, expect, test } from "vite-plus/test"; +import { BailianError, ExitCode } from "bailian-cli-core"; +import { + AUTO_MODEL, + assertMcpCompatible, + isAutoModel, + mcpSingleImageOnlyError, + mcpUnsupportedError, + type AigcMcpOperation, + type Localize, +} from "../src/commands/shared/aigc-mcp.ts"; + +/** Localizer stubs — the runtime picks one variant by resolved language. */ +const enUS: Localize = (text) => (typeof text === "string" ? text : text["en-US"]); +const zhCN: Localize = (text) => (typeof text === "string" ? text : text["zh-CN"]); + +/** Run a gate call expected to throw, asserting it is a USAGE BailianError. */ +function captureUsage(gateCall: () => void): BailianError { + try { + gateCall(); + } catch (error) { + expect(error).toBeInstanceOf(BailianError); + const usageError = error as BailianError; + expect(usageError.exitCode).toBe(ExitCode.USAGE); + return usageError; + } + throw new Error("expected assertMcpCompatible to throw a USAGE error"); +} + +describe("isAutoModel", () => { + test("matches only the reserved auto value (case-sensitive)", () => { + expect(AUTO_MODEL).toBe("auto"); + expect(isAutoModel("auto")).toBe(true); + expect(isAutoModel("qwen-image-3.0")).toBe(false); + expect(isAutoModel("AUTO")).toBe(false); + expect(isAutoModel("")).toBe(false); + expect(isAutoModel(undefined)).toBe(false); + }); +}); + +describe("assertMcpCompatible rejects flags MCP cannot honor", () => { + const rejectedCases: Array<[AigcMcpOperation, Record, string]> = [ + ["imageGen", { seed: 42 }, "--seed"], + ["imageGen", { watermark: false }, "--watermark"], + ["imageGen", { async: true }, "--async"], + ["imageEdit", { size: "1:1" }, "--size"], + ["imageEdit", { n: 2 }, "--n"], + ["imageEdit", { function: "stylize_all" }, "--function"], + ["imageEdit", { promptExtend: true }, "--prompt-extend"], + ["videoTextToVideo", { negativePrompt: "x" }, "--negative-prompt"], + ["videoTextToVideo", { lastFrame: "https://x/l.png" }, "--last-frame"], + ["videoTextToVideo", { prime: true }, "--prime"], + ["videoTextToVideo", { workspaceId: "ws" }, "--workspace-id"], + ["videoImageToVideo", { ratio: "16:9" }, "--ratio"], + ["videoImageToVideo", { file: "https://x/f.mp4" }, "--file"], + ["tts", { listVoices: true }, "--list-voices"], + ["tts", { format: "mp3" }, "--format"], + ["tts", { sampleRate: "16000" }, "--sample-rate"], + ["tts", { stream: true }, "--stream"], + ["tts", { enableSsml: true }, "--enable-ssml"], + ["asr", { language: "zh" }, "--language"], + ["asr", { diarization: true }, "--diarization"], + ["asr", { speakerCount: 2 }, "--speaker-count"], + ["asr", { vocabularyId: "vocab-1" }, "--vocabulary-id"], + ["asr", { channelId: 1 }, "--channel-id"], + ["asr", { async: true }, "--async"], + ]; + + for (const [operation, flags, expectedFlag] of rejectedCases) { + test(`${operation} rejects ${expectedFlag}`, () => { + const usageError = captureUsage(() => assertMcpCompatible(operation, flags, enUS)); + expect(usageError.message).toContain(expectedFlag); + expect(usageError.message).toContain("auto"); + expect(usageError.hint).toContain("--model"); + }); + } + + test("lists every offending flag in a single message", () => { + const usageError = captureUsage(() => + assertMcpCompatible("imageGen", { seed: 1, watermark: true, async: true }, enUS), + ); + expect(usageError.message).toContain("--seed"); + expect(usageError.message).toContain("--watermark"); + expect(usageError.message).toContain("--async"); + expect(usageError.message).toContain("these flags"); + }); + + test("localizes the rejection to zh-CN", () => { + const usageError = captureUsage(() => assertMcpCompatible("imageGen", { seed: 1 }, zhCN)); + expect(usageError.message).toContain("不支持"); + expect(usageError.message).toContain("--seed"); + expect(usageError.message).toContain("该参数"); + }); +}); + +describe("assertMcpCompatible allows MCP-honored and CLI-local flags", () => { + test("imageGen keeps prompt/size/n/negativePrompt/promptExtend plus output+concurrency", () => { + expect(() => + assertMcpCompatible( + "imageGen", + { + prompt: "x", + size: "1024*1024", + n: 2, + negativePrompt: "blur", + promptExtend: false, + concurrent: 3, + outDir: "./out", + outPrefix: "img", + pollInterval: 3, + }, + enUS, + ), + ).not.toThrow(); + }); + + test("switch flags are rejected only when true", () => { + expect(() => assertMcpCompatible("imageGen", { async: false }, enUS)).not.toThrow(); + expect(() => assertMcpCompatible("videoTextToVideo", { prime: false }, enUS)).not.toThrow(); + expect(() => assertMcpCompatible("tts", { stream: false }, enUS)).not.toThrow(); + }); + + test("value flags are rejected only when defined", () => { + expect(() => assertMcpCompatible("imageGen", { seed: undefined }, enUS)).not.toThrow(); + expect(() => assertMcpCompatible("imageEdit", { size: undefined }, enUS)).not.toThrow(); + }); + + test("tts keeps text/voice/out; asr keeps url/out", () => { + expect(() => + assertMcpCompatible("tts", { text: "hi", voice: "longxiaochun", out: "a.wav" }, enUS), + ).not.toThrow(); + expect(() => + assertMcpCompatible("asr", { url: ["data:audio/wav;base64,AA"], out: "o.json" }, enUS), + ).not.toThrow(); + }); +}); + +describe("error message builders", () => { + test("mcpUnsupportedError uses singular phrasing for one flag", () => { + expect(mcpUnsupportedError(enUS, ["--seed"]).message).toContain("this flag"); + }); + + test("mcpSingleImageOnlyError is a USAGE error mentioning single image", () => { + const singleImageError = mcpSingleImageOnlyError(enUS); + expect(singleImageError).toBeInstanceOf(BailianError); + expect(singleImageError.exitCode).toBe(ExitCode.USAGE); + expect(singleImageError.message).toContain("single image"); + }); +}); diff --git a/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts b/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts new file mode 100644 index 000000000..2e3ca936a --- /dev/null +++ b/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts @@ -0,0 +1,323 @@ +import { writeFileSync } from "node:fs"; +import { join } from "node:path"; +import { describe, expect, test } from "vite-plus/test"; +import { makeE2eOutputDir, parseStdoutJson, runCommandE2e } from "./helpers.ts"; +import type { E2eRouteExports } from "./topic-routes.ts"; + +/** + * AIGC `auto` 模式(`--model auto` 或配置默认模型为 `auto`)改走百炼官方 MCP。 + * + * 全部用例都是离线 dry-run:auto 分支在任何联网 / 上传之前先做 gate 校验并打印 + * 预览,因此无需密钥、不触发真实请求(dry-run 下 authStage 也会放行凭证缺失)。 + * 覆盖三类契约: + * 1) 每命令 auto dry-run 预览(server / tool / arguments / mode:mcp); + * 2) auto + MCP 不支持的 flag → USAGE(2),双语消息均含 flag 名; + * 3) 本地文件入参内联为 base64 data URI,且预览中脱敏为 ``。 + */ + +const AUTO_ROUTES: E2eRouteExports = { + "image generate": "imageGenerate", + "image edit": "imageEdit", + "video generate": "videoGenerate", + "speech synthesize": "speechSynthesize", + "speech recognize": "speechRecognize", +}; + +/** Shape of the `auto`/MCP dry-run preview emitted by every AIGC command. */ +interface McpPreview { + server?: string; + url?: string; + tool?: string; + mode?: string; + arguments?: Record; +} + +describe("e2e: aigc auto → mcp", () => { + test("image generate auto dry-run 预览走 TextGenerateImage/bailian_image_gen", async () => { + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "image", + "generate", + "--model", + "auto", + "--prompt", + "a cat", + "--dry-run", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson(stdout); + expect(data.mode).toBe("mcp"); + expect(data.server).toBe("TextGenerateImage"); + expect(data.tool).toBe("bailian_image_gen"); + expect(data.arguments?.prompt).toBe("a cat"); + }); + + test("image edit auto dry-run 预览走 bailian_image_edit(公网 URL 透传)", async () => { + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "image", + "edit", + "--model", + "auto", + "--image", + "https://example.com/a.png", + "--prompt", + "make it blue", + "--dry-run", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson(stdout); + expect(data.mode).toBe("mcp"); + expect(data.server).toBe("TextGenerateImage"); + expect(data.tool).toBe("bailian_image_edit"); + expect(data.arguments?.image_url).toBe("https://example.com/a.png"); + }); + + test("image edit auto 本地图片内联为脱敏 data URI", async () => { + const configDir = makeE2eOutputDir("aigc-auto-image-edit-local"); + const imagePath = join(configDir, "input.png"); + writeFileSync(imagePath, Buffer.from([1, 2, 3])); + + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "image", + "edit", + "--model", + "auto", + "--image", + imagePath, + "--prompt", + "make it blue", + "--dry-run", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson(stdout); + expect(data.arguments?.image_url).toBe("data:image/png;base64,"); + }); + + test("image edit auto 多图输入被拒 (USAGE 2)", async () => { + const { stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "image", + "edit", + "--model", + "auto", + "--image", + "https://example.com/a.png", + "--image", + "https://example.com/b.png", + "--prompt", + "merge", + "--dry-run", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(2); + expect(stderr).toMatch(/--image/); + }); + + test("video generate auto(t2v) dry-run 预览走 bailian_text_to_video_submit_task", async () => { + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "video", + "generate", + "--model", + "auto", + "--prompt", + "ocean waves", + "--dry-run", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson(stdout); + expect(data.mode).toBe("mcp"); + expect(data.server).toBe("VideoGenerate"); + expect(data.tool).toBe("bailian_text_to_video_submit_task"); + expect(data.arguments?.prompt).toBe("ocean waves"); + }); + + test("video generate auto(i2v) dry-run 预览走 bailian_image_to_video_submit_task", async () => { + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "video", + "generate", + "--model", + "auto", + "--prompt", + "make it move", + "--image", + "https://example.com/a.png", + "--dry-run", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson(stdout); + expect(data.mode).toBe("mcp"); + expect(data.server).toBe("VideoGenerate"); + expect(data.tool).toBe("bailian_image_to_video_submit_task"); + expect(data.arguments?.first_frame_url).toBe("https://example.com/a.png"); + }); + + test("speech synthesize auto dry-run 预览走 TextGenerateSpeech/bailian_tts(透传 voice)", async () => { + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "speech", + "synthesize", + "--model", + "auto", + "--text", + "hello", + "--voice", + "longxiaochun_v3", + "--dry-run", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson(stdout); + expect(data.mode).toBe("mcp"); + expect(data.server).toBe("TextGenerateSpeech"); + expect(data.tool).toBe("bailian_tts"); + expect(data.arguments?.text).toBe("hello"); + expect(data.arguments?.voice).toBe("longxiaochun_v3"); + }); + + test("speech recognize auto dry-run 预览走 SpeechGenerateText/bailian_speech_to_text", async () => { + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "speech", + "recognize", + "--model", + "auto", + "--url", + "https://example.com/a.mp3", + "--dry-run", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson(stdout); + expect(data.mode).toBe("mcp"); + expect(data.server).toBe("SpeechGenerateText"); + expect(data.tool).toBe("bailian_speech_to_text"); + expect(data.arguments?.file_urls).toEqual(["https://example.com/a.mp3"]); + }); + + test("speech recognize auto 本地音频内联为脱敏 data URI", async () => { + const configDir = makeE2eOutputDir("aigc-auto-speech-recognize-local"); + const audioPath = join(configDir, "input.wav"); + writeFileSync(audioPath, Buffer.from([1, 2, 3])); + + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "speech", + "recognize", + "--model", + "auto", + "--url", + audioPath, + "--dry-run", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson(stdout); + expect(data.arguments?.file_urls).toEqual(["data:audio/wav;base64,"]); + }); + + // auto + MCP 承接不了的 flag → USAGE(2),绝不静默回退 REST。 + const gateCases: Array<[string, string[], RegExp]> = [ + [ + "image generate --seed", + ["image", "generate", "--model", "auto", "--prompt", "x", "--seed", "42"], + /--seed/, + ], + [ + "image edit --size", + [ + "image", + "edit", + "--model", + "auto", + "--image", + "https://example.com/a.png", + "--prompt", + "x", + "--size", + "1024*1024", + ], + /--size/, + ], + [ + "video generate t2v --seed", + ["video", "generate", "--model", "auto", "--prompt", "x", "--seed", "1"], + /--seed/, + ], + [ + "video generate i2v --ratio", + [ + "video", + "generate", + "--model", + "auto", + "--prompt", + "x", + "--image", + "https://example.com/a.png", + "--ratio", + "16:9", + ], + /--ratio/, + ], + [ + "speech synthesize --format", + [ + "speech", + "synthesize", + "--model", + "auto", + "--text", + "x", + "--voice", + "longxiaochun_v3", + "--format", + "mp3", + ], + /--format/, + ], + [ + "speech synthesize --list-voices", + ["speech", "synthesize", "--model", "auto", "--list-voices"], + /--list-voices/, + ], + [ + "speech recognize --language", + [ + "speech", + "recognize", + "--model", + "auto", + "--url", + "https://example.com/a.mp3", + "--language", + "zh", + ], + /--language/, + ], + [ + "speech recognize --async", + ["speech", "recognize", "--model", "auto", "--url", "https://example.com/a.mp3", "--async"], + /--async/, + ], + ]; + + test.each(gateCases)("auto 拒绝不支持的 flag: %s (USAGE 2)", async (label, args, pattern) => { + const { stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + ...args, + "--dry-run", + "--output", + "json", + ]); + expect(exitCode, `${label} → ${stderr}`).toBe(2); + expect(stderr, label).toMatch(pattern); + }); +}); diff --git a/packages/core/package.json b/packages/core/package.json index 6882dc6ea..fc83d1cdc 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -45,14 +45,29 @@ "yauzl": "catalog:" }, "devDependencies": { + "@modelcontextprotocol/sdk": "^1", "@types/node": "catalog:", "@types/tar-stream": "catalog:", "@types/yauzl": "catalog:", "@typescript/native-preview": "7.0.0-dev.20260328.1", "typescript": "^6.0.2", - "vite-plus": "catalog:" + "vite-plus": "catalog:", + "zod": "^3" }, "engines": { "node": ">=18.17.0" + }, + "inlinedDependencies": { + "@modelcontextprotocol/sdk": "1.32.1", + "ajv": "8.20.0", + "ajv-formats": "3.0.1", + "content-type": "1.0.5", + "eventsource": "3.0.7", + "eventsource-parser": "3.1.1", + "fast-deep-equal": "3.1.3", + "fast-uri": "3.1.2", + "json-schema-traverse": "1.0.0", + "pkce-challenge": "5.0.1", + "zod": "3.25.76" } } diff --git a/packages/core/src/client/aigc-mcp.ts b/packages/core/src/client/aigc-mcp.ts new file mode 100644 index 000000000..27e29fc5b --- /dev/null +++ b/packages/core/src/client/aigc-mcp.ts @@ -0,0 +1,265 @@ +/** + * AIGC "auto" mode → Bailian MCP mapping layer (pure logic). + * + * When an AIGC command resolves its effective model to the reserved value + * `auto`, generation is routed through Bailian's official AIGC MCP servers + * (`/api/v1/mcps//mcp`) instead of the DashScope REST endpoints. This + * module holds the transport-agnostic pieces so they stay trivially unit + * testable: server codes, tool names, request-argument builders, and response + * parsers. The command layer (`packages/commands/src/commands/shared/aigc-mcp.ts`) + * owns the connection lifecycle, the `auto` parameter gate, concurrency, disk + * output, and localization. + * + * Wire contract (Phase 0 probe): + * - Every tool resolves to `content[0].type === "text"` whose `text` is a JSON + * string; parse it and honour `isError`. + * - Auth reuses the command's DashScope API key; these four servers need no + * marketplace activation. + * - The MCP input surface is smaller than REST (no model/seed/watermark; TTS has + * no format/sample-rate/stream), so the `auto` gate rejects the extra flags. + */ + +import { BailianError } from "../errors/base.ts"; +import { ExitCode } from "../errors/codes.ts"; +import type { McpToolResult } from "./mcp.ts"; + +// ---- Server codes (verbatim from `bl mcp list`) ---- + +/** Bailian AIGC MCP server codes, keyed by modality. */ +export const AIGC_MCP_SERVER = { + image: "TextGenerateImage", + video: "VideoGenerate", + speech: "TextGenerateSpeech", + asr: "SpeechGenerateText", +} as const; + +// ---- Tool names ---- + +/** Bailian AIGC MCP tool names. Only the tools listed in the switch-interface + * requirements doc are mapped here (no `bailian_image_fusion`, no multichannel + * ASR): multi-image edit and other out-of-scope usages are rejected by the gate. */ +export const AIGC_MCP_TOOL = { + imageGen: "bailian_image_gen", + imageEdit: "bailian_image_edit", + textToVideoSubmit: "bailian_text_to_video_submit_task", + imageToVideoSubmit: "bailian_image_to_video_submit_task", + videoFetchResult: "bailian_text_to_video_fetch_result", + tts: "bailian_tts", + speechToText: "bailian_speech_to_text", +} as const; + +// ---- Tool result envelope ---- + +/** + * Extract and JSON-parse the inner payload carried by an AIGC MCP tool result. + * + * A tool-level `isError` is a server-side failure: its text is passed through + * verbatim (AGENTS.md §3 — the CLI does not translate server errors). A missing + * or non-object payload is an unexpected shape and fails as GENERAL. + */ +export function parseAigcToolResult(result: McpToolResult): Record { + const joinedText = result.content + .map((part) => part.text) + .filter((text): text is string => typeof text === "string" && text.length > 0) + .join("\n"); + + if (result.isError) { + throw new BailianError(`Tool error: ${joinedText}`, ExitCode.GENERAL); + } + if (joinedText.length === 0) { + throw new BailianError("MCP tool returned no text content.", ExitCode.GENERAL); + } + + let parsed: unknown; + try { + parsed = JSON.parse(joinedText); + } catch (error) { + throw new BailianError( + `Failed to parse MCP tool result: ${(error as Error).message}`, + ExitCode.GENERAL, + ); + } + if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) { + throw new BailianError("MCP tool returned an unexpected payload shape.", ExitCode.GENERAL); + } + return parsed as Record; +} + +// ---- Request argument builders (pure) ---- + +/** Input for `bailian_image_gen`. */ +export interface AigcImageGenInput { + prompt: string; + size?: string; + n?: number; + negativePrompt?: string; + promptExtend?: boolean; +} + +/** Build `bailian_image_gen` arguments, omitting undefined optional params. */ +export function buildImageGenArgs(input: AigcImageGenInput): Record { + return { + prompt: input.prompt, + ...(input.size !== undefined ? { size: input.size } : {}), + ...(input.n !== undefined ? { n: input.n } : {}), + ...(input.negativePrompt !== undefined ? { negative_prompt: input.negativePrompt } : {}), + ...(input.promptExtend !== undefined ? { prompt_extend: input.promptExtend } : {}), + }; +} + +/** Input for `bailian_image_edit` (single source image only). */ +export interface AigcImageEditInput { + /** Public http(s) URL or inline base64 data URI; resolved by the command layer. */ + imageUrl: string; + prompt: string; + negativePrompt?: string; +} + +/** Build `bailian_image_edit` arguments. */ +export function buildImageEditArgs(input: AigcImageEditInput): Record { + return { + image_url: input.imageUrl, + prompt: input.prompt, + ...(input.negativePrompt !== undefined ? { negative_prompt: input.negativePrompt } : {}), + }; +} + +/** Input for the video submit tools (`bailian_text_to_video_submit_task` / + * `bailian_image_to_video_submit_task`). */ +export interface AigcVideoSubmitInput { + prompt?: string; + duration?: number; + resolution?: string; + /** Aspect ratio; text-to-video only. */ + ratio?: string; + /** First-frame public URL or data URI; image-to-video only. */ + firstFrameUrl?: string; +} + +/** Build `bailian_text_to_video_submit_task` arguments (text-to-video). */ +export function buildTextToVideoArgs(input: AigcVideoSubmitInput): Record { + return { + ...(input.prompt !== undefined ? { prompt: input.prompt } : {}), + ...(input.duration !== undefined ? { duration: input.duration } : {}), + ...(input.resolution !== undefined ? { resolution: input.resolution } : {}), + ...(input.ratio !== undefined ? { ratio: input.ratio } : {}), + }; +} + +/** Build `bailian_image_to_video_submit_task` arguments (image-to-video). */ +export function buildImageToVideoArgs(input: AigcVideoSubmitInput): Record { + return { + ...(input.firstFrameUrl !== undefined ? { first_frame_url: input.firstFrameUrl } : {}), + ...(input.prompt !== undefined ? { prompt: input.prompt } : {}), + ...(input.duration !== undefined ? { duration: input.duration } : {}), + ...(input.resolution !== undefined ? { resolution: input.resolution } : {}), + }; +} + +/** Build `bailian_text_to_video_fetch_result` arguments. */ +export function buildVideoFetchArgs(taskId: string): Record { + return { task_id: taskId }; +} + +/** Input for `bailian_tts`. */ +export interface AigcTtsInput { + text: string; + /** Passed through verbatim; the MCP server validates the voice enum. */ + voice?: string; +} + +/** Build `bailian_tts` arguments. */ +export function buildTtsArgs(input: AigcTtsInput): Record { + return { + text: input.text, + ...(input.voice !== undefined ? { voice: input.voice } : {}), + }; +} + +/** Build `bailian_speech_to_text` arguments (synchronous). */ +export function buildSpeechToTextArgs(fileUrls: string[]): Record { + return { file_urls: fileUrls }; +} + +// ---- Response parsers (pure) ---- + +/** Pull a URL out of a result entry that may be a bare string or `{ url }`. */ +function extractResultUrl(entry: unknown): string | undefined { + if (typeof entry === "string" && entry.length > 0) return entry; + if (entry && typeof entry === "object") { + const url = (entry as Record).url; + if (typeof url === "string" && url.length > 0) return url; + } + return undefined; +} + +/** + * Parse image generate/edit results into a URL list. The MCP shape is + * `{ request_id, results: ["", …] }` (bare strings, unlike REST's + * `[{ url }]`); object entries are tolerated defensively. An empty list is + * returned as-is so the caller can raise its own command-specific message. + */ +export function parseAigcImageResults(inner: Record): string[] { + const results = inner.results; + if (!Array.isArray(results)) { + throw new BailianError("MCP image result is missing a `results` array.", ExitCode.GENERAL); + } + return results.map(extractResultUrl).filter((url): url is string => url !== undefined); +} + +/** Parsed `bailian_tts` result. */ +export interface AigcTtsResult { + audioUrl: string; + requestId?: string; +} + +/** Parse the TTS result `{ result: "", request_id }`. */ +export function parseAigcTtsResult(inner: Record): AigcTtsResult { + const audioUrl = inner.result; + if (typeof audioUrl !== "string" || audioUrl.length === 0) { + throw new BailianError("MCP TTS result is missing an audio URL.", ExitCode.GENERAL); + } + const requestId = typeof inner.request_id === "string" ? inner.request_id : undefined; + return { audioUrl, ...(requestId !== undefined ? { requestId } : {}) }; +} + +/** Parse a video submit result `{ task_id }` into the task id. */ +export function parseAigcVideoTaskId(inner: Record): string { + const taskId = inner.task_id; + if (typeof taskId !== "string" || taskId.length === 0) { + throw new BailianError("MCP video submit result is missing a task_id.", ExitCode.GENERAL); + } + return taskId; +} + +/** Parsed `bailian_text_to_video_fetch_result` result. */ +export interface AigcVideoTaskResult { + /** RUNNING / SUCCEEDED / FAILED / UNKNOWN (server-provided). */ + taskStatus: string; + videoUrl?: string; + taskId?: string; +} + +/** Parse the video fetch result `{ task_status, video_url, task_id }`. */ +export function parseAigcVideoTaskResult(inner: Record): AigcVideoTaskResult { + const taskStatus = typeof inner.task_status === "string" ? inner.task_status : "UNKNOWN"; + const videoUrl = + typeof inner.video_url === "string" && inner.video_url.length > 0 ? inner.video_url : undefined; + const taskId = typeof inner.task_id === "string" ? inner.task_id : undefined; + return { + taskStatus, + ...(videoUrl !== undefined ? { videoUrl } : {}), + ...(taskId !== undefined ? { taskId } : {}), + }; +} + +/** + * Parse ASR results `{ request_id, results: ["", …] }` into transcription + * text lines. `auto` mode intentionally returns this simplified text (the MCP + * tool exposes none of REST's sentence/speaker/timestamp structure). + */ +export function parseAigcAsrTexts(inner: Record): string[] { + const results = inner.results; + if (!Array.isArray(results)) return []; + return results.filter((entry): entry is string => typeof entry === "string"); +} diff --git a/packages/core/src/client/client.ts b/packages/core/src/client/client.ts index 2a549c89f..482aa28ac 100644 --- a/packages/core/src/client/client.ts +++ b/packages/core/src/client/client.ts @@ -9,9 +9,9 @@ import { bailianMcpPath, bailianMcpSsePath, connectBailianMcpWithFallback, - McpClient, type McpConnectedClient, } from "./mcp.ts"; +import { SdkMcpAdapter } from "./mcp-sdk.ts"; import { callConsoleGateway } from "../console/gateway.ts"; import { refreshAccessToken } from "../auth/refresh-token.ts"; import { maskToken } from "../utils/token.ts"; @@ -184,18 +184,26 @@ export class Client { } /** Open an MCP client. Accepts a path (prepended with the model baseUrl) or an absolute URL. */ - mcp(pathOrUrl: string): McpClient { + mcp(pathOrUrl: string): McpConnectedClient { const url = /^https?:\/\//.test(pathOrUrl) ? pathOrUrl : this.requireApi().baseUrl + pathOrUrl; - return new McpClient(this.http, url, this.deps.apiCred?.token); + return new SdkMcpAdapter({ + deps: this.http, + url, + authToken: this.deps.apiCred?.token, + transport: "streamable", + }); } /** * Connect to a Bailian MCP: try Streamable HTTP, then SSE on 405 (except WebSearch). * `urlOverride` maps to `--url`: Streamable first, then classic SSE on the same URL (405/404). + * `serviceSource` overrides the `X-Dashscope-Service` attribution value (default + * `bailian-cli`); AIGC "auto"-mode MCP calls pass `bailian-cli-call`. */ connectBailianMcp( serverCode: string, urlOverride?: string, + serviceSource?: string, ): Promise<{ client: McpConnectedClient; url: string }> { this.requireApi(); return connectBailianMcpWithFallback({ @@ -205,6 +213,7 @@ export class Client { sseUrl: this.url(bailianMcpSsePath(serverCode)), serverCode, urlOverride, + serviceSource, }); } diff --git a/packages/core/src/client/headers.ts b/packages/core/src/client/headers.ts index 05c066c72..ecac86c77 100644 --- a/packages/core/src/client/headers.ts +++ b/packages/core/src/client/headers.ts @@ -11,6 +11,14 @@ import type { Identity } from "../config/schema.ts"; export const CHANNEL = "bailian-cli"; +/** + * `X-Dashscope-Service` attribution value for AIGC "auto"-mode MCP tool calls, + * letting the gateway separate CLI-originated MCP generation traffic from the + * default {@link CHANNEL}. Only the AIGC auto path opts in; every other request + * (REST, upload, other MCP commands) keeps {@link CHANNEL}. + */ +export const MCP_CALL_SERVICE = "bailian-cli-call"; + /** Static source identifier advertised to the DashScope/Bailian OpenAPI gateway. */ export const OPEN_API_SOURCE = "BailianCLI"; @@ -30,11 +38,18 @@ export function sourceConfig(identity: TrackingIdentity): string { }); } -/** Tracking headers for Bailian/DashScope API requests. */ -export function trackingHeaders(identity: TrackingIdentity): Record { +/** + * Tracking headers for Bailian/DashScope API requests. `service` overrides the + * `X-Dashscope-Service` attribution value (default {@link CHANNEL}); AIGC + * "auto"-mode MCP calls pass {@link MCP_CALL_SERVICE}. + */ +export function trackingHeaders( + identity: TrackingIdentity, + service: string = CHANNEL, +): Record { return { "x-dashscope-source-config": sourceConfig(identity), "x-dashscope-openapisource": OPEN_API_SOURCE, - [DASHSCOPE_SERVICE_HEADER]: CHANNEL, + [DASHSCOPE_SERVICE_HEADER]: service, }; } diff --git a/packages/core/src/client/index.ts b/packages/core/src/client/index.ts index 26b6a9d6b..35d638505 100644 --- a/packages/core/src/client/index.ts +++ b/packages/core/src/client/index.ts @@ -71,6 +71,7 @@ export { export { CHANNEL, DASHSCOPE_SERVICE_HEADER, + MCP_CALL_SERVICE, OPEN_API_SOURCE, sourceConfig, trackingHeaders, @@ -106,12 +107,34 @@ export type { ConnectBailianMcpOptions, } from "./mcp.ts"; export { - McpClient, bailianMcpPath, bailianMcpSsePath, isStreamableHttpUnsupported, isUrlOverrideSseFallbackCandidate, connectBailianMcpWithFallback, } from "./mcp.ts"; +export { + AIGC_MCP_SERVER, + AIGC_MCP_TOOL, + parseAigcToolResult, + buildImageGenArgs, + buildImageEditArgs, + buildTextToVideoArgs, + buildImageToVideoArgs, + buildVideoFetchArgs, + buildTtsArgs, + buildSpeechToTextArgs, + parseAigcImageResults, + parseAigcTtsResult, + parseAigcVideoTaskId, + parseAigcVideoTaskResult, + parseAigcAsrTexts, + type AigcImageGenInput, + type AigcImageEditInput, + type AigcVideoSubmitInput, + type AigcTtsInput, + type AigcTtsResult, + type AigcVideoTaskResult, +} from "./aigc-mcp.ts"; export type { ServerSentEvent } from "./stream.ts"; export { parseSSE } from "./stream.ts"; diff --git a/packages/core/src/client/mcp-sdk.ts b/packages/core/src/client/mcp-sdk.ts new file mode 100644 index 000000000..a31a00e30 --- /dev/null +++ b/packages/core/src/client/mcp-sdk.ts @@ -0,0 +1,306 @@ +/** + * MCP client backed by the official `@modelcontextprotocol/sdk` (v1 line). + * + * Implements the same {@link McpConnectedClient} surface as the retired + * hand-rolled JSON-RPC/SSE pipeline, so the three callers (`Client.mcp()`, + * `connectBailianMcpWithFallback`, and through them `search/web`, `mcp/tools`, + * `mcp/call`) stay unchanged. All SDK-specific code (imports, transports, error + * classes) is confined to this file to keep the v1→v2 upgrade path cheap. + * + * Wire behaviour preserved from the old client: + * - Bearer token + tracking headers + User-Agent on every request (via + * `requestInit.headers`, which the SDK applies to both GET and POST). + * - `MCP request failed: - ` message contract for + * HTTP transport failures, which `isStreamableHttpUnsupported`, + * `isUrlOverrideSseFallbackCandidate` and the MCP-not-activated hint rely on. + * - `MCP error (): ` for JSON-RPC business errors (passthrough). + * - Raw `TypeError` (e.g. ENOTFOUND) propagation so runtime can surface errno. + */ + +import { Client } from "@modelcontextprotocol/sdk/client/index.js"; +import { + StreamableHTTPClientTransport, + StreamableHTTPError, +} from "@modelcontextprotocol/sdk/client/streamableHttp.js"; +import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; +import { ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js"; +import type { FetchLike, Transport } from "@modelcontextprotocol/sdk/shared/transport.js"; + +import { BailianError } from "../errors/base.ts"; +import { ExitCode } from "../errors/codes.ts"; +import { trackingHeaders } from "./headers.ts"; +import type { HttpDeps } from "./http.ts"; +import type { McpConnectedClient, McpTool, McpToolResult } from "./mcp.ts"; + +/** Which transport the adapter drives: Streamable HTTP (/mcp) or classic SSE (/sse). */ +export type SdkMcpTransportKind = "streamable" | "sse"; + +export interface SdkMcpAdapterOptions { + deps: HttpDeps; + /** Full endpoint URL for the chosen transport. */ + url: string; + authToken: string | undefined; + transport: SdkMcpTransportKind; + /** + * Overrides the `X-Dashscope-Service` attribution value (default `bailian-cli`). + * AIGC "auto"-mode MCP calls pass `bailian-cli-call`. + */ + serviceSource?: string; +} + +/** + * Translate an SDK/transport error into the CLI error contract. + * + * - `BailianError` (already ours, produced by the fetch interceptor) passes through. + * - `McpError`: RequestTimeout → TIMEOUT, ConnectionClosed → NETWORK, otherwise a + * server-side JSON-RPC error → GENERAL with the `MCP error (code): message` shape + * (message passed through verbatim per AGENTS.md §3). + * - `StreamableHTTPError` (HTTP status in `.code`) → GENERAL with the + * `MCP request failed: ` shape so the fallback detectors still match. + * - Anything else (e.g. a `TypeError` from `fetch`) is returned unchanged so the + * runtime keeps its errno-specific handling. + */ +export function mapSdkError(error: unknown): unknown { + if (error instanceof BailianError) return error; + + if (error instanceof McpError) { + const raw = rawMcpMessage(error); + if (error.code === ErrorCode.RequestTimeout) { + return new BailianError(raw || "MCP request timed out.", ExitCode.TIMEOUT); + } + if (error.code === ErrorCode.ConnectionClosed) { + return new BailianError(raw || "MCP connection closed.", ExitCode.NETWORK); + } + return new BailianError(`MCP error (${error.code}): ${raw}`, ExitCode.GENERAL); + } + + if (error instanceof StreamableHTTPError) { + const status = error.code; + return new BailianError(`MCP request failed: ${status}`, ExitCode.GENERAL, undefined, { + api: { httpStatus: typeof status === "number" ? status : undefined }, + cause: error, + }); + } + + return error; +} + +/** + * Recover the raw server message from an SDK `McpError`. + * + * The SDK bakes its own `MCP error : ` prefix into `.message` and does not + * retain the original text, so strip that exact prefix to restore the verbatim + * message the old hand-rolled client surfaced (keeping the `MCP error (): …` + * contract and the MCP-not-activated hint's body matching intact). + */ +function rawMcpMessage(error: McpError): string { + const prefix = `MCP error ${error.code}: `; + return error.message.startsWith(prefix) ? error.message.slice(prefix.length) : error.message; +} + +/** + * Build the transport-level fetch. It reproduces the old client's error contract + * for message POSTs and mirrors its `--verbose` wire logging. GET responses are + * passed through untouched so the SDK's own SSE-stream handling (including the + * tolerated 405 on a standalone Streamable GET) stays intact. + */ +function createMcpFetch(deps: HttpDeps): FetchLike { + return async (url, init) => { + const method = init?.method ?? "GET"; + const target = typeof url === "string" ? url : url.href; + + if (deps.settings.verbose) { + console.error(`> ${method} ${target}`); + if (typeof init?.body === "string") { + try { + const parsed = JSON.parse(init.body) as { method?: string }; + if (parsed.method) console.error(`> Method: ${parsed.method}`); + } catch { + /* non-JSON body */ + } + } + } + + const response = await fetch(url, init); + + if (deps.settings.verbose) { + console.error(`< ${response.status} ${response.statusText}`); + } + + if (!response.ok && method === "POST") { + let message = `MCP request failed: ${response.status} ${response.statusText}`; + try { + const errorBody = await response.text(); + if (errorBody) message += ` - ${errorBody.slice(0, 500)}`; + } catch { + /* body already consumed or unreadable */ + } + throw new BailianError(message, ExitCode.GENERAL); + } + + return response; + }; +} + +/** + * `McpConnectedClient` implementation delegating to the official SDK client. + * Construction is lazy: no network until {@link initialize}. + */ +export class SdkMcpAdapter implements McpConnectedClient { + private readonly deps: HttpDeps; + private readonly url: string; + private readonly authToken: string | undefined; + private readonly kind: SdkMcpTransportKind; + private readonly serviceSource: string | undefined; + + private client: Client | undefined; + private transport: Transport | undefined; + private connecting: Promise | undefined; + + constructor(options: SdkMcpAdapterOptions) { + this.deps = options.deps; + this.url = options.url; + this.authToken = options.authToken; + this.kind = options.transport; + this.serviceSource = options.serviceSource; + } + + /** Open the transport and run the initialize handshake. Idempotent. */ + async initialize(): Promise { + if (!this.authToken) { + throw new BailianError("This command needs a model-domain API key.", ExitCode.AUTH); + } + if (!this.connecting) { + this.connecting = this.connect().catch((error) => { + // Allow a later initialize() to retry on the same instance. + this.connecting = undefined; + throw mapSdkError(error); + }); + } + return this.connecting; + } + + async listTools(): Promise { + const client = await this.requireClient(); + try { + const result = await client.listTools(undefined, this.requestOptions()); + return result.tools.map((tool) => ({ + name: tool.name, + ...(tool.description !== undefined ? { description: tool.description } : {}), + ...(tool.inputSchema !== undefined + ? { inputSchema: tool.inputSchema as Record } + : {}), + })); + } catch (error) { + throw mapSdkError(error); + } + } + + async callTool(name: string, args: Record): Promise { + const client = await this.requireClient(); + try { + const result = (await client.callTool( + { name, arguments: args }, + undefined, + this.requestOptions(), + )) as { + content?: Array<{ type: string; text?: string; data?: string; mimeType?: string }>; + isError?: boolean; + }; + // Non-task tools (all Bailian MCP tools) resolve to the `content` shape; + // the task shape carries `toolResult` instead and is out of scope here. + if (!Array.isArray(result.content)) { + throw new BailianError("MCP tool returned an unexpected result shape.", ExitCode.GENERAL); + } + return { + content: result.content.map((part) => mapContentPart(part)), + ...(result.isError !== undefined ? { isError: result.isError } : {}), + }; + } catch (error) { + throw mapSdkError(error); + } + } + + /** Close the transport (fire-and-forget; aborts any background SSE stream). */ + close(): void { + const transport = this.transport; + this.client = undefined; + this.transport = undefined; + this.connecting = undefined; + if (transport) { + void transport.close().catch(() => undefined); + } + } + + // ---- Internal ---- + + private async connect(): Promise { + const headers: Record = { + "User-Agent": `${this.deps.identity.clientName}/${this.deps.identity.version}`, + ...trackingHeaders(this.deps.identity, this.serviceSource), + Authorization: `Bearer ${this.authToken}`, + }; + + const mcpFetch = createMcpFetch(this.deps); + const endpoint = new URL(this.url); + const transport = + this.kind === "sse" + ? new SSEClientTransport(endpoint, { requestInit: { headers }, fetch: mcpFetch }) + : new StreamableHTTPClientTransport(endpoint, { + requestInit: { headers }, + fetch: mcpFetch, + }); + + const client = new Client( + { name: this.deps.identity.clientName, version: this.deps.identity.version }, + { capabilities: {} }, + ); + + await client.connect(transport, this.requestOptions()); + + this.transport = transport; + this.client = client; + + if (this.deps.settings.verbose) { + const label = this.kind === "sse" ? "MCP SSE" : "MCP"; + const session = + transport instanceof StreamableHTTPClientTransport + ? (transport.sessionId ?? "no session") + : "no session"; + console.error(`[${label}] Session initialized: ${session}`); + console.error(`[${label}] Server: ${JSON.stringify(client.getServerVersion() ?? {})}`); + } + } + + private async requireClient(): Promise { + await this.initialize(); + if (!this.client) { + throw new BailianError("MCP client is not connected.", ExitCode.GENERAL); + } + return this.client; + } + + private requestOptions(): { timeout: number } { + return { timeout: this.deps.settings.timeout * 1000 }; + } +} + +/** Map an SDK content part onto the loose {@link McpToolResult} content shape. */ +function mapContentPart(part: { type: string; text?: string; data?: string; mimeType?: string }): { + type: string; + text?: string; + data?: string; + mimeType?: string; +} { + if (part.type === "text" && typeof part.text === "string") { + return { type: "text", text: part.text }; + } + if ((part.type === "image" || part.type === "audio") && typeof part.data === "string") { + return { + type: part.type, + data: part.data, + ...(typeof part.mimeType === "string" ? { mimeType: part.mimeType } : {}), + }; + } + return { type: part.type }; +} diff --git a/packages/core/src/client/mcp-sse.ts b/packages/core/src/client/mcp-sse.ts deleted file mode 100644 index a156557a7..000000000 --- a/packages/core/src/client/mcp-sse.ts +++ /dev/null @@ -1,474 +0,0 @@ -/** - * MCP classic HTTP+SSE client (protocol 2024-11-05 transport). - * - * Flow: GET /sse → endpoint event → POST JSON-RPC to message URL; - * responses arrive as SSE `message` events matched by JSON-RPC id. - */ - -import { BailianError } from "../errors/base.ts"; -import { ExitCode } from "../errors/codes.ts"; -import type { HttpDeps } from "./http.ts"; -import { trackingHeaders } from "./headers.ts"; -import type { McpTool, McpToolResult } from "./mcp.ts"; -import { parseSSE } from "./stream.ts"; - -interface JsonRpcResponse { - jsonrpc: "2.0"; - id?: number | string | null; - result?: unknown; - error?: { code: number; message: string; data?: unknown }; -} - -type PendingResolver = { - resolve: (value: JsonRpcResponse) => void; - reject: (reason: unknown) => void; -}; - -/** Match JSON-RPC ids with string keys (number or string echo from server). */ -function pendingKey(id: number | string): string { - return String(id); -} - -export class McpSseClient { - private sseUrl: string; - private messageUrl: string | undefined; - private nextId = 1; - private deps: HttpDeps; - private authToken: string | undefined; - private abortController: AbortController | undefined; - private pending = new Map(); - private endpointReady: Promise; - private resolveEndpoint: (() => void) | undefined; - private rejectEndpoint: ((reason: unknown) => void) | undefined; - private closed = false; - /** Set when the SSE GET ends without an intentional close(); later RPCs fail fast. */ - private streamEnded = false; - - constructor(deps: HttpDeps, sseUrl: string, authToken?: string) { - this.deps = deps; - this.sseUrl = sseUrl; - this.authToken = authToken; - this.endpointReady = new Promise((resolve, reject) => { - this.resolveEndpoint = resolve; - this.rejectEndpoint = reject; - }); - } - - /** Open the SSE session and run initialize / notifications/initialized. */ - async initialize(): Promise { - if (!this.authToken) { - throw new BailianError("This command needs a model-domain API key.", ExitCode.AUTH); - } - - await this.openSse(); - - const result = await this.rpc("initialize", { - protocolVersion: "2025-03-26", - capabilities: {}, - clientInfo: { - name: this.deps.identity.clientName, - version: this.deps.identity.version, - }, - }); - - if (this.deps.settings.verbose) { - console.error(`[MCP SSE] Session initialized`); - console.error(`[MCP SSE] Server: ${JSON.stringify(result)}`); - } - - await this.notify("notifications/initialized"); - } - - async listTools(): Promise { - const result = (await this.rpc("tools/list")) as { tools: McpTool[] }; - return result.tools || []; - } - - async callTool(name: string, args: Record): Promise { - const result = (await this.rpc("tools/call", { name, arguments: args })) as McpToolResult; - return result; - } - - /** Abort the hanging GET /sse so the CLI process can exit. */ - close(): void { - if (this.closed) return; - this.closed = true; - this.abortController?.abort(); - this.failPending(new BailianError("MCP SSE session closed.", ExitCode.GENERAL)); - this.messageUrl = undefined; - } - - private failPending(reason: unknown): void { - for (const [, waiter] of this.pending) { - waiter.reject(reason); - } - this.pending.clear(); - } - - private markStreamEnded(reason: BailianError): void { - this.streamEnded = true; - this.messageUrl = undefined; - this.failPending(reason); - } - - private async openSse(): Promise { - if (this.abortController) return; - - // One abortController for header/error-body wait; clear timer before the long-lived stream. - this.abortController = new AbortController(); - const timeoutMs = this.deps.settings.timeout * 1000; - let headerTimedOut = false; - const headerTimer = setTimeout(() => { - headerTimedOut = true; - this.abortController?.abort(); - }, timeoutMs); - - const headers: Record = { - Accept: "text/event-stream", - "User-Agent": `${this.deps.identity.clientName}/${this.deps.identity.version}`, - ...trackingHeaders(this.deps.identity), - }; - if (this.authToken) { - headers["Authorization"] = `Bearer ${this.authToken}`; - } - - if (this.deps.settings.verbose) { - console.error(`> GET ${this.sseUrl}`); - } - - let response: Response; - try { - response = await fetch(this.sseUrl, { - method: "GET", - headers, - signal: this.abortController.signal, - }); - } catch (error) { - clearTimeout(headerTimer); - // Allow a later initialize() to openSse again on this instance. - this.abortController = undefined; - if (this.closed) { - throw new BailianError("MCP SSE session closed.", ExitCode.GENERAL); - } - if (headerTimedOut) { - throw new BailianError("MCP SSE timed out waiting for response headers.", ExitCode.TIMEOUT); - } - // Rethrow fetch failures so runtime can surface errno (e.g. ENOTFOUND) in JSON/text. - throw error; - } - - if (this.deps.settings.verbose) { - console.error(`< ${response.status} ${response.statusText}`); - } - - if (!response.ok) { - // Keep headerTimer until error body is read (or times out). - let errMsg = `MCP request failed: ${response.status} ${response.statusText}`; - try { - const errBody = await response.text(); - if (errBody) errMsg += ` - ${errBody.slice(0, 500)}`; - } catch (error) { - clearTimeout(headerTimer); - this.abortController = undefined; - if (this.closed) { - throw new BailianError("MCP SSE session closed.", ExitCode.GENERAL); - } - if (headerTimedOut) { - throw new BailianError( - "MCP SSE timed out reading error response body.", - ExitCode.TIMEOUT, - ); - } - throw new BailianError(errMsg, ExitCode.GENERAL, undefined, { cause: error }); - } - clearTimeout(headerTimer); - this.abortController = undefined; - // Do not rejectEndpoint — openSse never awaits endpointReady on this path. - throw new BailianError(errMsg, ExitCode.GENERAL); - } - - clearTimeout(headerTimer); - - void this.consumeSse(response).catch((error) => { - if (this.closed) return; - const reason = - error instanceof BailianError - ? error - : new BailianError( - `MCP SSE stream failed: ${error instanceof Error ? error.message : String(error)}`, - ExitCode.GENERAL, - ); - this.rejectEndpoint?.(reason); - // consumeSse already markStreamEnded on a clean end; cover parse/read failures here. - if (!this.streamEnded) { - this.markStreamEnded(reason); - } - }); - - const endpointTimeout = cancellableTimeoutReject( - timeoutMs, - "MCP SSE timed out waiting for endpoint event.", - ); - try { - await Promise.race([this.endpointReady, endpointTimeout.promise]); - } finally { - endpointTimeout.cancel(); - } - } - - private async consumeSse(response: Response): Promise { - for await (const event of parseSSE(response)) { - if (this.closed) break; - - // Spec requires event: endpoint; ignore unnamed events so JSON is not treated as a URL. - if (event.event === "endpoint") { - const raw = event.data.trim(); - if (!raw) continue; - // Only accept same-origin message URLs so we never forward the Bearer token cross-origin. - this.messageUrl = resolveSameOriginMessageUrl(this.sseUrl, raw); - this.resolveEndpoint?.(); - this.resolveEndpoint = undefined; - this.rejectEndpoint = undefined; - continue; - } - - // Omitted SSE event type defaults to "message". - if (event.event === "message" || event.event === undefined) { - let payload: JsonRpcResponse; - try { - payload = JSON.parse(event.data) as JsonRpcResponse; - } catch { - continue; - } - if (typeof payload.id !== "number" && typeof payload.id !== "string") continue; - const key = pendingKey(payload.id); - const waiter = this.pending.get(key); - if (!waiter) continue; - this.pending.delete(key); - waiter.resolve(payload); - } - } - - if (this.closed) return; - - if (!this.messageUrl) { - const error = new BailianError( - "MCP SSE stream ended before endpoint event.", - ExitCode.GENERAL, - ); - this.rejectEndpoint?.(error); - throw error; - } - - // After endpoint: mark dead and wake pending; don't throw (avoid unhandledRejection). - this.markStreamEnded(new BailianError("MCP SSE stream ended unexpectedly.", ExitCode.GENERAL)); - } - - private async rpc(method: string, params?: Record): Promise { - if (this.closed || this.streamEnded) { - throw new BailianError("MCP SSE stream ended unexpectedly.", ExitCode.GENERAL); - } - - const id = this.nextId++; - const key = pendingKey(id); - const body = { - jsonrpc: "2.0" as const, - id, - method, - ...(params ? { params } : {}), - }; - - const timeoutMs = this.deps.settings.timeout * 1000; - const responsePromise = new Promise((resolve, reject) => { - this.pending.set(key, { resolve, reject }); - }); - // Stream may end and reject pending before Promise.race; attach catch to avoid unhandledRejection. - void responsePromise.catch(() => undefined); - const responseTimeout = cancellableTimeoutReject( - timeoutMs, - `MCP SSE timed out waiting for response to ${method}.`, - ); - - try { - await this.postMessage(body); - if (this.closed || this.streamEnded) { - throw new BailianError("MCP SSE stream ended unexpectedly.", ExitCode.GENERAL); - } - const data = await Promise.race([responsePromise, responseTimeout.promise]); - if (data.error) { - throw new BailianError( - `MCP error (${data.error.code}): ${data.error.message}`, - ExitCode.GENERAL, - ); - } - return data.result; - } catch (error) { - this.pending.delete(key); - throw error; - } finally { - responseTimeout.cancel(); - } - } - - private async notify(method: string, params?: Record): Promise { - const body = { - jsonrpc: "2.0" as const, - method, - ...(params ? { params } : {}), - }; - await this.postMessage(body); - } - - private async postMessage(body: unknown): Promise { - if (this.closed || this.streamEnded) { - throw new BailianError("MCP SSE stream ended unexpectedly.", ExitCode.GENERAL); - } - if (!this.messageUrl) { - throw new BailianError("MCP SSE message endpoint is not ready.", ExitCode.GENERAL); - } - - const headers: Record = { - "Content-Type": "application/json", - Accept: "application/json, text/event-stream", - "User-Agent": `${this.deps.identity.clientName}/${this.deps.identity.version}`, - ...trackingHeaders(this.deps.identity), - }; - // Bearer is only sent to a messageUrl that already passed the same-origin check. - if (this.authToken) { - headers["Authorization"] = `Bearer ${this.authToken}`; - } - - if (this.deps.settings.verbose) { - console.error(`> POST ${this.messageUrl}`); - console.error(`> Method: ${(body as { method?: string }).method}`); - } - - const timeoutMs = this.deps.settings.timeout * 1000; - // Combine per-RPC timeout with session abort so close() cancels in-flight POSTs. - const requestSignal = createLinkedAbortSignal(timeoutMs, this.abortController?.signal); - let res: Response; - try { - try { - res = await fetch(this.messageUrl, { - method: "POST", - headers, - body: JSON.stringify(body), - signal: requestSignal.signal, - }); - } catch (error) { - if (this.closed) { - throw new BailianError("MCP SSE session closed.", ExitCode.GENERAL); - } - throw error; - } - - if (this.deps.settings.verbose) { - console.error(`< ${res.status} ${res.statusText}`); - } - - if (!res.ok) { - // Keep signal until error body is read (same class of bug as GET openSse). - let errMsg = `MCP request failed: ${res.status} ${res.statusText}`; - try { - const errBody = await res.text(); - if (errBody) errMsg += ` - ${errBody.slice(0, 500)}`; - } catch (error) { - if (this.closed) { - throw new BailianError("MCP SSE session closed.", ExitCode.GENERAL); - } - if (requestSignal.timedOut) { - throw new BailianError( - "MCP SSE timed out reading error response body.", - ExitCode.TIMEOUT, - ); - } - throw new BailianError(errMsg, ExitCode.GENERAL, undefined, { cause: error }); - } - throw new BailianError(errMsg, ExitCode.GENERAL); - } - } finally { - requestSignal.cleanup(); - } - } -} - -/** Resolve the SSE endpoint data to an absolute URL and require same origin as sseUrl. */ -export function resolveSameOriginMessageUrl(sseUrl: string, endpointData: string): string { - let resolved: URL; - let base: URL; - try { - base = new URL(sseUrl); - resolved = new URL(endpointData, sseUrl); - } catch { - throw new BailianError( - `MCP SSE endpoint is not a valid URL: ${endpointData}`, - ExitCode.GENERAL, - ); - } - if (resolved.origin !== base.origin) { - throw new BailianError( - `MCP SSE endpoint origin mismatch: expected ${base.origin}, got ${resolved.origin}`, - ExitCode.GENERAL, - ); - } - return resolved.toString(); -} - -/** - * Cancellable timeout rejection: after Promise.race settles, call cancel() - * to clear the timer and avoid unhandledRejection. - */ -function cancellableTimeoutReject( - timeoutMs: number, - message: string, -): { promise: Promise; cancel: () => void } { - let timer: ReturnType | undefined; - const promise = new Promise((_, reject) => { - timer = setTimeout(() => { - timer = undefined; - reject(new BailianError(message, ExitCode.TIMEOUT)); - }, timeoutMs); - }); - // Swallow late rejects after cancel to avoid unhandledRejection. - void promise.catch(() => undefined); - - return { - promise, - cancel: () => { - if (timer !== undefined) { - clearTimeout(timer); - timer = undefined; - } - }, - }; -} - -/** Timeout + optional parent abort without AbortSignal.any (Node 18). */ -function createLinkedAbortSignal( - timeoutMs: number, - parentSignal?: AbortSignal, -): { signal: AbortSignal; cleanup: () => void; timedOut: boolean } { - const controller = new AbortController(); - const state = { timedOut: false }; - const timeout = setTimeout(() => { - state.timedOut = true; - controller.abort(); - }, timeoutMs); - const abortFromParent = () => controller.abort(parentSignal?.reason); - const cleanup = () => { - clearTimeout(timeout); - parentSignal?.removeEventListener("abort", abortFromParent); - }; - - if (parentSignal?.aborted) abortFromParent(); - else parentSignal?.addEventListener("abort", abortFromParent, { once: true }); - controller.signal.addEventListener("abort", cleanup, { once: true }); - - return { - signal: controller.signal, - cleanup, - get timedOut() { - return state.timedOut; - }, - }; -} diff --git a/packages/core/src/client/mcp.ts b/packages/core/src/client/mcp.ts index c3ffe9e41..280981f42 100644 --- a/packages/core/src/client/mcp.ts +++ b/packages/core/src/client/mcp.ts @@ -1,8 +1,10 @@ /** - * MCP (Model Context Protocol) streamable HTTP client. + * MCP (Model Context Protocol) client surface for Bailian / DashScope. * - * Implements the JSON-RPC 2.0 based MCP protocol over streamable HTTP transport. - * Used by DashScope MCP services like WebSearch and the Bailian marketplace. + * Holds the shared MCP types, the Bailian URL convention, the transport-failure + * detectors, and the Streamable-HTTP → classic-SSE fallback orchestration. The + * wire protocol itself (JSON-RPC over Streamable HTTP / SSE) is delegated to the + * official `@modelcontextprotocol/sdk` via `SdkMcpAdapter` (see `mcp-sdk.ts`). * * Protocol flow: initialize → tools/list → tools/call * @@ -12,27 +14,8 @@ */ import { BailianError } from "../errors/base.ts"; -import { ExitCode } from "../errors/codes.ts"; import type { HttpDeps } from "./http.ts"; -import { trackingHeaders } from "./headers.ts"; -import { McpSseClient } from "./mcp-sse.ts"; -import { parseSSE } from "./stream.ts"; - -// ---- JSON-RPC 2.0 Types ---- - -interface JsonRpcRequest { - jsonrpc: "2.0"; - id: number; - method: string; - params?: Record; -} - -interface JsonRpcResponse { - jsonrpc: "2.0"; - id?: number | string | null; - result?: unknown; - error?: { code: number; message: string; data?: unknown }; -} +import { SdkMcpAdapter } from "./mcp-sdk.ts"; // ---- MCP Tool Types ---- @@ -105,6 +88,11 @@ export type ConnectBailianMcpOptions = { * on 405/404 fall back to classic SSE on the same URL. */ urlOverride?: string; + /** + * Overrides the `X-Dashscope-Service` attribution value on these connections + * (default `bailian-cli`). AIGC "auto"-mode MCP calls pass `bailian-cli-call`. + */ + serviceSource?: string; }; /** @@ -115,10 +103,16 @@ export type ConnectBailianMcpOptions = { export async function connectBailianMcpWithFallback( options: ConnectBailianMcpOptions, ): Promise<{ client: McpConnectedClient; url: string }> { - const { deps, authToken, httpUrl, sseUrl, serverCode, urlOverride } = options; + const { deps, authToken, httpUrl, sseUrl, serverCode, urlOverride, serviceSource } = options; if (urlOverride) { - const httpClient = new McpClient(deps, urlOverride, authToken); + const httpClient = new SdkMcpAdapter({ + deps, + url: urlOverride, + authToken, + transport: "streamable", + serviceSource, + }); try { await httpClient.initialize(); return { client: httpClient, url: urlOverride }; @@ -128,7 +122,13 @@ export async function connectBailianMcpWithFallback( } } - const sseClient = new McpSseClient(deps, urlOverride, authToken); + const sseClient = new SdkMcpAdapter({ + deps, + url: urlOverride, + authToken, + transport: "sse", + serviceSource, + }); try { await sseClient.initialize(); return { client: sseClient, url: urlOverride }; @@ -138,7 +138,13 @@ export async function connectBailianMcpWithFallback( } } - const httpClient = new McpClient(deps, httpUrl, authToken); + const httpClient = new SdkMcpAdapter({ + deps, + url: httpUrl, + authToken, + transport: "streamable", + serviceSource, + }); try { await httpClient.initialize(); return { client: httpClient, url: httpUrl }; @@ -148,7 +154,13 @@ export async function connectBailianMcpWithFallback( } } - const sseClient = new McpSseClient(deps, sseUrl, authToken); + const sseClient = new SdkMcpAdapter({ + deps, + url: sseUrl, + authToken, + transport: "sse", + serviceSource, + }); try { await sseClient.initialize(); return { client: sseClient, url: sseUrl }; @@ -157,174 +169,3 @@ export async function connectBailianMcpWithFallback( throw error; } } - -// ---- MCP Client ---- - -export class McpClient { - private url: string; - private sessionId: string | undefined; - private nextId = 1; - private deps: HttpDeps; - private authToken: string | undefined; - - constructor(deps: HttpDeps, url: string, authToken?: string) { - this.deps = deps; - this.url = url; - this.authToken = authToken; - } - - /** Initialize the MCP session. Must be called before any other method. */ - async initialize(): Promise { - if (!this.authToken) { - throw new BailianError("This command needs a model-domain API key.", ExitCode.AUTH); - } - - const result = await this.rpc("initialize", { - protocolVersion: "2025-03-26", - capabilities: {}, - clientInfo: { - name: this.deps.identity.clientName, - version: this.deps.identity.version, - }, - }); - - if (this.deps.settings.verbose) { - console.error(`[MCP] Session initialized: ${this.sessionId ?? "no session"}`); - console.error(`[MCP] Server: ${JSON.stringify(result)}`); - } - - await this.notify("notifications/initialized"); - } - - async listTools(): Promise { - const result = (await this.rpc("tools/list")) as { tools: McpTool[] }; - return result.tools || []; - } - - async callTool(name: string, args: Record): Promise { - const result = (await this.rpc("tools/call", { name, arguments: args })) as McpToolResult; - return result; - } - - // ---- Internal Methods ---- - - private async rpc(method: string, params?: Record): Promise { - const id = this.nextId++; - const body: JsonRpcRequest = { - jsonrpc: "2.0", - id, - method, - ...(params ? { params } : {}), - }; - - const response = await this.send(body); - const data = await this.readJsonRpcResponse(response, id); - - if (data.error) { - throw new BailianError( - `MCP error (${data.error.code}): ${data.error.message}`, - ExitCode.GENERAL, - ); - } - - return data.result; - } - - private async notify(method: string, params?: Record): Promise { - const body = { - jsonrpc: "2.0" as const, - method, - ...(params ? { params } : {}), - }; - - await this.send(body); - } - - /** - * Read a JSON-RPC response by Content-Type: application/json or text/event-stream. - */ - private async readJsonRpcResponse( - response: Response, - expectedId: number, - ): Promise { - const contentType = response.headers.get("content-type") || ""; - if (contentType.includes("text/event-stream")) { - return await this.readJsonRpcFromSse(response, expectedId); - } - - return (await response.json()) as JsonRpcResponse; - } - - private async readJsonRpcFromSse( - response: Response, - expectedId: number, - ): Promise { - const expectedKey = String(expectedId); - for await (const event of parseSSE(response)) { - if (event.event && event.event !== "message") continue; - let payload: JsonRpcResponse; - try { - payload = JSON.parse(event.data) as JsonRpcResponse; - } catch { - continue; - } - if (payload.id == null) continue; - if (String(payload.id) !== expectedKey) continue; - return payload; - } - throw new BailianError( - "MCP SSE response stream ended without a matching JSON-RPC response.", - ExitCode.GENERAL, - ); - } - - private async send(body: unknown): Promise { - const headers: Record = { - "Content-Type": "application/json", - Accept: "application/json, text/event-stream", - "User-Agent": `${this.deps.identity.clientName}/${this.deps.identity.version}`, - ...trackingHeaders(this.deps.identity), - }; - - if (this.authToken) { - headers["Authorization"] = `Bearer ${this.authToken}`; - } - - if (this.sessionId) { - headers["Mcp-Session-Id"] = this.sessionId; - } - - if (this.deps.settings.verbose) { - console.error(`> POST ${this.url}`); - console.error(`> Method: ${(body as { method?: string }).method}`); - } - - const timeoutMs = this.deps.settings.timeout * 1000; - const res = await fetch(this.url, { - method: "POST", - headers, - body: JSON.stringify(body), - signal: AbortSignal.timeout(timeoutMs), - }); - - if (this.deps.settings.verbose) { - console.error(`< ${res.status} ${res.statusText}`); - } - - const sid = res.headers.get("Mcp-Session-Id") || res.headers.get("mcp-session-id"); - if (sid) this.sessionId = sid; - - if (!res.ok) { - let errMsg = `MCP request failed: ${res.status} ${res.statusText}`; - try { - const errBody = await res.text(); - if (errBody) errMsg += ` - ${errBody.slice(0, 500)}`; - } catch { - /* ignore */ - } - throw new BailianError(errMsg, ExitCode.GENERAL); - } - - return res; - } -} diff --git a/packages/core/src/files/index.ts b/packages/core/src/files/index.ts index cda2ca17d..4e582ec43 100644 --- a/packages/core/src/files/index.ts +++ b/packages/core/src/files/index.ts @@ -3,5 +3,6 @@ export { isLocalFile, resolveFileUrl, imageFileToDataUri, + audioFileToDataUri, redactDataUri, } from "./upload.ts"; diff --git a/packages/core/src/files/upload.ts b/packages/core/src/files/upload.ts index dc81c976e..c5f52b743 100644 --- a/packages/core/src/files/upload.ts +++ b/packages/core/src/files/upload.ts @@ -127,8 +127,26 @@ const IMAGE_MIME_TYPES: Readonly> = { ".webp": "image/webp", }; -/** Encode a local image as a Data URI. */ -export function imageFileToDataUri(filePath: string): string { +const AUDIO_MIME_TYPES: Readonly> = { + ".aac": "audio/aac", + ".amr": "audio/amr", + ".flac": "audio/flac", + ".m4a": "audio/mp4", + ".mp3": "audio/mpeg", + ".oga": "audio/ogg", + ".ogg": "audio/ogg", + ".opus": "audio/opus", + ".wav": "audio/wav", + ".weba": "audio/webm", + ".wma": "audio/x-ms-wma", +}; + +/** Encode a local file as a Data URI, validating its extension against a MIME table. */ +function fileToDataUri( + filePath: string, + mimeTypes: Readonly>, + kind: "image" | "audio", +): string { if (!existsSync(filePath)) { throw new BailianError(`File not found: ${filePath}`, ExitCode.USAGE); } @@ -139,12 +157,12 @@ export function imageFileToDataUri(filePath: string): string { } const extension = extname(filePath).toLowerCase(); - const mimeType = IMAGE_MIME_TYPES[extension]; + const mimeType = mimeTypes[extension]; if (!mimeType) { throw new BailianError( - `Unsupported image format "${extension || "unknown"}".`, + `Unsupported ${kind} format "${extension || "unknown"}".`, ExitCode.USAGE, - "Use an image file with a recognized extension.", + `Use an ${kind} file with a recognized extension.`, ); } @@ -152,6 +170,16 @@ export function imageFileToDataUri(filePath: string): string { return `data:${mimeType};base64,${encoded}`; } +/** Encode a local image as a Data URI. */ +export function imageFileToDataUri(filePath: string): string { + return fileToDataUri(filePath, IMAGE_MIME_TYPES, "image"); +} + +/** Encode a local audio file as a Data URI (used by ASR `auto`/MCP input). */ +export function audioFileToDataUri(filePath: string): string { + return fileToDataUri(filePath, AUDIO_MIME_TYPES, "audio"); +} + /** Keep dry-run output readable and avoid echoing the complete inline image. */ export function redactDataUri(input: string): string { const match = /^data:([^;,]+);base64,/i.exec(input); diff --git a/packages/core/tests/aigc-mcp.test.ts b/packages/core/tests/aigc-mcp.test.ts new file mode 100644 index 000000000..65a74139a --- /dev/null +++ b/packages/core/tests/aigc-mcp.test.ts @@ -0,0 +1,151 @@ +import { describe, expect, test } from "vite-plus/test"; +import { + AIGC_MCP_SERVER, + AIGC_MCP_TOOL, + buildImageEditArgs, + buildImageGenArgs, + buildImageToVideoArgs, + buildSpeechToTextArgs, + buildTextToVideoArgs, + buildTtsArgs, + buildVideoFetchArgs, + parseAigcAsrTexts, + parseAigcImageResults, + parseAigcToolResult, + parseAigcTtsResult, + parseAigcVideoTaskId, + parseAigcVideoTaskResult, +} from "../src/client/aigc-mcp.ts"; +import type { McpToolResult } from "../src/client/mcp.ts"; + +/** Wrap a JSON-serializable payload in the MCP text-content envelope. */ +function textResult(payload: unknown, isError = false): McpToolResult { + return { content: [{ type: "text", text: JSON.stringify(payload) }], isError }; +} + +describe("AIGC MCP server / tool constants", () => { + test("maps each modality to its server code and tool names", () => { + expect(AIGC_MCP_SERVER.image).toBe("TextGenerateImage"); + expect(AIGC_MCP_SERVER.video).toBe("VideoGenerate"); + expect(AIGC_MCP_SERVER.speech).toBe("TextGenerateSpeech"); + expect(AIGC_MCP_SERVER.asr).toBe("SpeechGenerateText"); + expect(AIGC_MCP_TOOL.imageGen).toBe("bailian_image_gen"); + expect(AIGC_MCP_TOOL.videoFetchResult).toBe("bailian_text_to_video_fetch_result"); + }); +}); + +describe("argument builders omit undefined and snake_case optional params", () => { + test("buildImageGenArgs", () => { + expect(buildImageGenArgs({ prompt: "a cat" })).toEqual({ prompt: "a cat" }); + expect( + buildImageGenArgs({ + prompt: "a cat", + size: "1024*1024", + n: 2, + negativePrompt: "blur", + promptExtend: false, + }), + ).toEqual({ + prompt: "a cat", + size: "1024*1024", + n: 2, + negative_prompt: "blur", + prompt_extend: false, + }); + }); + + test("buildImageEditArgs", () => { + expect(buildImageEditArgs({ imageUrl: "https://x/a.png", prompt: "edit" })).toEqual({ + image_url: "https://x/a.png", + prompt: "edit", + }); + expect( + buildImageEditArgs({ + imageUrl: "data:image/png;base64,AA", + prompt: "edit", + negativePrompt: "n", + }), + ).toEqual({ image_url: "data:image/png;base64,AA", prompt: "edit", negative_prompt: "n" }); + }); + + test("buildTextToVideoArgs keeps ratio; buildImageToVideoArgs drops it", () => { + expect( + buildTextToVideoArgs({ prompt: "p", duration: 5, resolution: "1080P", ratio: "16:9" }), + ).toEqual({ prompt: "p", duration: 5, resolution: "1080P", ratio: "16:9" }); + expect( + buildImageToVideoArgs({ + firstFrameUrl: "https://x/f.png", + prompt: "p", + duration: 5, + resolution: "720P", + ratio: "16:9", + }), + ).toEqual({ first_frame_url: "https://x/f.png", prompt: "p", duration: 5, resolution: "720P" }); + }); + + test("buildVideoFetchArgs / buildTtsArgs / buildSpeechToTextArgs", () => { + expect(buildVideoFetchArgs("task-1")).toEqual({ task_id: "task-1" }); + expect(buildTtsArgs({ text: "hi" })).toEqual({ text: "hi" }); + expect(buildTtsArgs({ text: "hi", voice: "longxiaochun" })).toEqual({ + text: "hi", + voice: "longxiaochun", + }); + expect(buildSpeechToTextArgs(["data:audio/wav;base64,AA"])).toEqual({ + file_urls: ["data:audio/wav;base64,AA"], + }); + }); +}); + +describe("parseAigcToolResult envelope handling", () => { + test("parses the JSON text payload", () => { + expect(parseAigcToolResult(textResult({ results: ["u"] }))).toEqual({ results: ["u"] }); + }); + + test("passes a tool-level isError through verbatim", () => { + expect(() => parseAigcToolResult(textResult({ message: "boom" }, true))).toThrow( + /Tool error:.*boom/, + ); + }); + + test("rejects empty, non-JSON, and non-object payloads", () => { + expect(() => parseAigcToolResult({ content: [{ type: "text", text: "" }] })).toThrow( + /no text content/, + ); + expect(() => parseAigcToolResult({ content: [{ type: "text", text: "not json" }] })).toThrow( + /Failed to parse MCP tool result/, + ); + expect(() => parseAigcToolResult(textResult(["array"]))).toThrow(/unexpected payload shape/); + }); +}); + +describe("response parsers", () => { + test("parseAigcImageResults accepts bare strings and { url } objects", () => { + expect(parseAigcImageResults({ results: ["a", "b"] })).toEqual(["a", "b"]); + expect(parseAigcImageResults({ results: [{ url: "a" }, "b"] })).toEqual(["a", "b"]); + expect(parseAigcImageResults({ results: [] })).toEqual([]); + expect(() => parseAigcImageResults({})).toThrow(/missing a `results` array/); + }); + + test("parseAigcTtsResult reads the singular result URL", () => { + expect(parseAigcTtsResult({ result: "https://x/a.wav", request_id: "r1" })).toEqual({ + audioUrl: "https://x/a.wav", + requestId: "r1", + }); + expect(() => parseAigcTtsResult({})).toThrow(/missing an audio URL/); + }); + + test("parseAigcVideoTaskId / parseAigcVideoTaskResult", () => { + expect(parseAigcVideoTaskId({ task_id: "t1" })).toBe("t1"); + expect(() => parseAigcVideoTaskId({})).toThrow(/missing a task_id/); + expect( + parseAigcVideoTaskResult({ task_status: "SUCCEEDED", video_url: "https://x/v.mp4" }), + ).toEqual({ taskStatus: "SUCCEEDED", videoUrl: "https://x/v.mp4" }); + expect(parseAigcVideoTaskResult({})).toEqual({ taskStatus: "UNKNOWN" }); + }); + + test("parseAigcAsrTexts keeps only string entries", () => { + expect(parseAigcAsrTexts({ results: ["hello", "world"] })).toEqual(["hello", "world"]); + expect(parseAigcAsrTexts({ results: ["hello", 42] })).toEqual(["hello"]); + expect(parseAigcAsrTexts({})).toEqual([]); + }); +}); diff --git a/packages/core/tests/index.test.ts b/packages/core/tests/index.test.ts index 620504532..7ba118df9 100644 --- a/packages/core/tests/index.test.ts +++ b/packages/core/tests/index.test.ts @@ -4,7 +4,6 @@ import { BailianError, Client, ExitCode, - McpClient, callConsoleGateway, mapApiError, request, @@ -346,39 +345,6 @@ test("request propagates caller AbortSignal to fetch", async () => { } }); -test("McpClient uses injected client identity for initialize and User-Agent", async () => { - const originalFetch = globalThis.fetch; - const bodies: unknown[] = []; - const userAgents: string[] = []; - - globalThis.fetch = async (_url, init) => { - const headers = init?.headers as Record | undefined; - userAgents.push(headers?.["User-Agent"] ?? ""); - const body = init?.body; - if (typeof body === "string") bodies.push(JSON.parse(body)); - return new Response(JSON.stringify({ jsonrpc: "2.0", id: 1, result: {} }), { - status: 200, - }); - }; - - try { - const client = new McpClient( - testDeps({ clientName: "test-client", version: "9.8.7" }), - "https://mcp.example.test", - "sk-test", - ); - await client.initialize(); - } finally { - globalThis.fetch = originalFetch; - } - - expect(userAgents).toEqual(["test-client/9.8.7", "test-client/9.8.7"]); - expect(bodies[0]).toMatchObject({ - method: "initialize", - params: { clientInfo: { name: "test-client", version: "9.8.7" } }, - }); -}); - test("resolveWatermark uses flag or defaults to true", () => { expect(resolveWatermark("false")).toBe(false); expect(resolveWatermark("true")).toBe(true); diff --git a/packages/core/tests/mcp.test.ts b/packages/core/tests/mcp.test.ts index a502fbf06..51f456255 100644 --- a/packages/core/tests/mcp.test.ts +++ b/packages/core/tests/mcp.test.ts @@ -1,15 +1,17 @@ import { expect, test } from "vite-plus/test"; +import { ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js"; +import { StreamableHTTPError } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; import type { Identity, Settings } from "../src/index.ts"; import { BailianError, + ExitCode, bailianMcpPath, bailianMcpSsePath, connectBailianMcpWithFallback, isStreamableHttpUnsupported, isUrlOverrideSseFallbackCandidate, - McpClient, } from "../src/index.ts"; -import { McpSseClient, resolveSameOriginMessageUrl } from "../src/client/mcp-sse.ts"; +import { SdkMcpAdapter, mapSdkError } from "../src/client/mcp-sdk.ts"; function testDeps(overrides?: Partial): { identity: Identity; settings: Settings } { return { @@ -33,8 +35,22 @@ function testDeps(overrides?: Partial): { identity: Identity; settings }; } -function jsonRpcResult(id: number | string, result: unknown): string { - return `event:message\ndata:${JSON.stringify({ jsonrpc: "2.0", id, result })}\n\n`; +/** A valid initialize result the SDK's InitializeResultSchema accepts. */ +const INIT_RESULT = { + protocolVersion: "2024-11-05", + capabilities: {}, + serverInfo: { name: "test-server", version: "1.0.0" }, +}; + +function jsonRpc(id: number | string, result: unknown): string { + return JSON.stringify({ jsonrpc: "2.0", id, result }); +} + +function jsonResponse(payload: string): Response { + return new Response(payload, { + status: 200, + headers: { "Content-Type": "application/json" }, + }); } function requestUrl(input: string | URL | Request): string { @@ -43,6 +59,12 @@ function requestUrl(input: string | URL | Request): string { return input.url; } +function parseBody(init?: RequestInit): { id?: number | string; method?: string } { + return typeof init?.body === "string" ? (JSON.parse(init.body) as never) : {}; +} + +// ---- Pure helpers (unchanged contract) ---- + test("bailianMcp 路径与 isStreamableHttpUnsupported", () => { expect(bailianMcpPath("WebParser")).toBe("/api/v1/mcps/WebParser/mcp"); expect(bailianMcpSsePath("WebParser")).toBe("/api/v1/mcps/WebParser/sse"); @@ -90,526 +112,334 @@ test("bailianMcp 路径与 isStreamableHttpUnsupported", () => { ).toBe(false); }); -test("resolveSameOriginMessageUrl:同源通过、跨域拒绝", () => { - expect( - resolveSameOriginMessageUrl( - "https://example.test/api/v1/mcps/WebParser/sse", - "/api/v1/mcps/WebParser/message?sessionId=x", - ), - ).toBe("https://example.test/api/v1/mcps/WebParser/message?sessionId=x"); - - expect(() => - resolveSameOriginMessageUrl( - "https://example.test/api/v1/mcps/WebParser/sse", - "https://evil.example/steal", - ), - ).toThrow(/origin mismatch/i); +// ---- mapSdkError ---- + +test("mapSdkError:超时/连接关闭映射 ExitCode;服务端 JSON-RPC 错透传;BailianError 与原生错原样返回", () => { + const timeout = mapSdkError(new McpError(ErrorCode.RequestTimeout, "Request timed out")); + expect(timeout).toBeInstanceOf(BailianError); + expect((timeout as BailianError).exitCode).toBe(ExitCode.TIMEOUT); + + const closed = mapSdkError(new McpError(ErrorCode.ConnectionClosed, "Connection closed")); + expect(closed).toBeInstanceOf(BailianError); + expect((closed as BailianError).exitCode).toBe(ExitCode.NETWORK); + + // Server-side JSON-RPC error: passthrough message with the MCP error shape. + const business = mapSdkError(new McpError(-32601, "Method not found")); + expect(business).toBeInstanceOf(BailianError); + expect((business as BailianError).exitCode).toBe(ExitCode.GENERAL); + expect((business as BailianError).message).toBe("MCP error (-32601): Method not found"); + + // StreamableHTTPError carries the HTTP status in .code. + const http = mapSdkError(new StreamableHTTPError(503, "Service Unavailable")); + expect(http).toBeInstanceOf(BailianError); + expect((http as BailianError).message).toBe("MCP request failed: 503"); + expect((http as BailianError).api?.httpStatus).toBe(503); + + // Already-mapped and native errors pass through by identity. + const original = new BailianError("boom", ExitCode.AUTH); + expect(mapSdkError(original)).toBe(original); + const typeError = new TypeError("fetch failed"); + expect(mapSdkError(typeError)).toBe(typeError); }); -test("connectBailianMcpWithFallback:成功走 Streamable;405 降级 SSE", async () => { +// ---- SdkMcpAdapter (streamable) ---- + +test("SdkMcpAdapter:注入 Authorization / User-Agent / 追踪头,并发送 clientInfo", async () => { const originalFetch = globalThis.fetch; + const seenHeaders: Headers[] = []; + const bodies: Array<{ method?: string; params?: { clientInfo?: unknown } }> = []; - // Streamable success path - globalThis.fetch = async (input, init) => { - const body = typeof init?.body === "string" ? JSON.parse(init.body) : {}; - if (requestUrl(input).includes("/sse")) { - return new Response("should not hit sse", { status: 500 }); - } - if (body.method === "notifications/initialized") { - return new Response(null, { status: 200 }); + globalThis.fetch = async (_input, init) => { + seenHeaders.push(new Headers(init?.headers)); + const body = parseBody(init); + bodies.push(body as never); + if (body.method === "initialize") { + return jsonResponse(jsonRpc(body.id!, INIT_RESULT)); } - return new Response(JSON.stringify({ jsonrpc: "2.0", id: body.id, result: {} }), { - status: 200, - }); + return new Response(null, { status: 200 }); }; try { - const connected = await connectBailianMcpWithFallback({ + const adapter = new SdkMcpAdapter({ deps: testDeps(), + url: "https://example.test/api/v1/mcps/WebParser/mcp", authToken: "sk-test", - httpUrl: "https://example.test/api/v1/mcps/WebParser/mcp", - sseUrl: "https://example.test/api/v1/mcps/WebParser/sse", - serverCode: "WebParser", + transport: "streamable", }); - expect(connected.url).toContain("/mcp"); + await adapter.initialize(); + + expect(seenHeaders.length).toBeGreaterThan(0); + for (const headers of seenHeaders) { + expect(headers.get("Authorization")).toBe("Bearer sk-test"); + expect(headers.get("User-Agent")).toBe("bailian-cli/0.0.0-test"); + expect(headers.get("X-Dashscope-Service")).toBe("bailian-cli"); + expect(headers.get("x-dashscope-openapisource")).toBe("BailianCLI"); + } + expect(bodies[0]).toMatchObject({ + method: "initialize", + params: { clientInfo: { name: "bailian-cli", version: "0.0.0-test" } }, + }); + adapter.close(); } finally { globalThis.fetch = originalFetch; } +}); - // Bare HTTP 405 (no streamableHttp body text) → SSE - let sseController: ReadableStreamDefaultController | undefined; - const encoder = new TextEncoder(); - const urls: string[] = []; - - globalThis.fetch = async (input, init) => { - const url = requestUrl(input); - urls.push(`${init?.method ?? "GET"} ${url}`); - - if (url.endsWith("/mcp")) { - return new Response("Method Not Allowed", { - status: 405, - statusText: "Method Not Allowed", - }); - } - - if (url.endsWith("/sse") && (init?.method ?? "GET") === "GET") { - const stream = new ReadableStream({ - start(controller) { - sseController = controller; - controller.enqueue( - encoder.encode( - "event:endpoint\ndata:/api/v1/mcps/WebParser/message?sessionId=test-session\n\n", - ), - ); - }, - }); - return new Response(stream, { - status: 200, - headers: { "Content-Type": "text/event-stream" }, - }); - } +test("SdkMcpAdapter:serviceSource 覆写 X-Dashscope-Service(AIGC auto → bailian-cli-call)", async () => { + const originalFetch = globalThis.fetch; + const seenHeaders: Headers[] = []; - if (url.includes("/message")) { - const body = typeof init?.body === "string" ? JSON.parse(init.body) : {}; - queueMicrotask(() => { - if (body.id != null && sseController) { - sseController.enqueue(encoder.encode(jsonRpcResult(body.id, {}))); - } - }); - return new Response(null, { status: 200 }); + globalThis.fetch = async (_input, init) => { + seenHeaders.push(new Headers(init?.headers)); + const body = parseBody(init); + if (body.method === "initialize") { + return jsonResponse(jsonRpc(body.id!, INIT_RESULT)); } - - return new Response("unexpected", { status: 500 }); + return new Response(null, { status: 200 }); }; try { - const connected = await connectBailianMcpWithFallback({ + const adapter = new SdkMcpAdapter({ deps: testDeps(), + url: "https://example.test/api/v1/mcps/TextGenerateImage/mcp", authToken: "sk-test", - httpUrl: "https://example.test/api/v1/mcps/WebParser/mcp", - sseUrl: "https://example.test/api/v1/mcps/WebParser/sse", - serverCode: "WebParser", + transport: "streamable", + serviceSource: "bailian-cli-call", }); - expect(connected.url).toContain("/sse"); - expect(urls.some((entry) => entry.includes("GET ") && entry.includes("/sse"))).toBe(true); - connected.client.close?.(); + await adapter.initialize(); + + expect(seenHeaders.length).toBeGreaterThan(0); + for (const headers of seenHeaders) { + // 只有 X-Dashscope-Service 被覆写为来源标识;其余渠道标识保持不变。 + expect(headers.get("X-Dashscope-Service")).toBe("bailian-cli-call"); + expect(headers.get("x-dashscope-openapisource")).toBe("BailianCLI"); + expect(headers.get("x-dashscope-source-config")).toContain('"channel":"bailian-cli"'); + } + adapter.close(); } finally { globalThis.fetch = originalFetch; } }); -test("connectBailianMcpWithFallback:WebSearch 不降级;urlOverride 同 URL 降级 SSE;404 不降级 Bailian 路径", async () => { +test("SdkMcpAdapter:无 token 时 initialize 抛 AUTH(不发请求)", async () => { const originalFetch = globalThis.fetch; - const urls: string[] = []; - - globalThis.fetch = async (input) => { - urls.push(requestUrl(input)); - return new Response("current mcp not support streamableHttp", { - status: 405, - statusText: "Method Not Allowed", - }); + let called = false; + globalThis.fetch = async () => { + called = true; + return new Response(null, { status: 200 }); }; try { - await expect( - connectBailianMcpWithFallback({ - deps: testDeps(), - authToken: "sk-test", - httpUrl: "https://example.test/api/v1/mcps/WebSearch/mcp", - sseUrl: "https://example.test/api/v1/mcps/WebSearch/sse", - serverCode: "WebSearch", - }), - ).rejects.toBeInstanceOf(BailianError); - expect(urls.some((url) => url.includes("/sse"))).toBe(false); + const adapter = new SdkMcpAdapter({ + deps: testDeps(), + url: "https://example.test/mcp", + authToken: undefined, + transport: "streamable", + }); + await expect(adapter.initialize()).rejects.toMatchObject({ exitCode: ExitCode.AUTH }); + expect(called).toBe(false); } finally { globalThis.fetch = originalFetch; } +}); - // urlOverride: after POST 405, fall back with GET SSE on the same URL - urls.length = 0; - let sseController: ReadableStreamDefaultController | undefined; - const encoder = new TextEncoder(); - const overrideUrl = "https://custom.example/mcp"; - - globalThis.fetch = async (input, init) => { - const url = requestUrl(input); - const method = init?.method ?? "GET"; - urls.push(`${method} ${url}`); +test("SdkMcpAdapter:listTools 与 callTool 结果映射回 McpTool / McpToolResult 形状", async () => { + const originalFetch = globalThis.fetch; - if (method === "POST" && url === overrideUrl) { - return new Response("Method Not Allowed", { - status: 405, - statusText: "Method Not Allowed", - }); + globalThis.fetch = async (_input, init) => { + const body = parseBody(init); + if (body.method === "initialize") { + return jsonResponse(jsonRpc(body.id!, INIT_RESULT)); } - - if (method === "GET" && url === overrideUrl) { - const stream = new ReadableStream({ - start(controller) { - sseController = controller; - controller.enqueue(encoder.encode("event:endpoint\ndata:/message?sessionId=x\n\n")); - }, - }); - return new Response(stream, { - status: 200, - headers: { "Content-Type": "text/event-stream" }, - }); + if (body.method === "tools/list") { + return jsonResponse( + jsonRpc(body.id!, { + tools: [ + { + name: "bailian_image_gen", + description: "生成图片", + inputSchema: { type: "object", properties: {}, required: ["prompt"] }, + }, + ], + }), + ); } - - if (url.includes("/message")) { - const body = typeof init?.body === "string" ? JSON.parse(init.body) : {}; - queueMicrotask(() => { - if (body.id != null && sseController) { - sseController.enqueue(encoder.encode(jsonRpcResult(body.id, {}))); - } - }); - return new Response(null, { status: 200 }); + if (body.method === "tools/call") { + return jsonResponse( + jsonRpc(body.id!, { + content: [ + { type: "text", text: JSON.stringify({ results: ["https://x/y.png"] }) }, + { type: "image", data: "AAAA", mimeType: "image/png" }, + ], + isError: false, + }), + ); } - - return new Response("unexpected", { status: 500 }); + return new Response(null, { status: 200 }); }; try { - const connected = await connectBailianMcpWithFallback({ + const adapter = new SdkMcpAdapter({ deps: testDeps(), + url: "https://example.test/mcp", authToken: "sk-test", - httpUrl: "https://example.test/api/v1/mcps/WebParser/mcp", - sseUrl: "https://example.test/api/v1/mcps/WebParser/sse", - serverCode: "WebParser", - urlOverride: overrideUrl, + transport: "streamable", }); - expect(connected.url).toBe(overrideUrl); - expect(urls.some((entry) => entry.startsWith(`GET ${overrideUrl}`))).toBe(true); - connected.client.close?.(); - } finally { - globalThis.fetch = originalFetch; - } - - globalThis.fetch = async () => - new Response("MCP不存在或未开通", { status: 404, statusText: "Not Found" }); + await adapter.initialize(); + + const tools = await adapter.listTools(); + expect(tools).toEqual([ + { + name: "bailian_image_gen", + description: "生成图片", + inputSchema: { type: "object", properties: {}, required: ["prompt"] }, + }, + ]); - try { - await expect( - connectBailianMcpWithFallback({ - deps: testDeps(), - authToken: "sk-test", - httpUrl: "https://example.test/api/v1/mcps/WebParser/mcp", - sseUrl: "https://example.test/api/v1/mcps/WebParser/sse", - serverCode: "WebParser", - }), - ).rejects.toMatchObject({ message: expect.stringContaining("404") }); + const result = await adapter.callTool("bailian_image_gen", { prompt: "a red dot" }); + expect(result.isError).toBe(false); + expect(result.content[0]).toEqual({ + type: "text", + text: JSON.stringify({ results: ["https://x/y.png"] }), + }); + expect(result.content[1]).toEqual({ type: "image", data: "AAAA", mimeType: "image/png" }); + adapter.close(); } finally { globalThis.fetch = originalFetch; } }); -test("McpSseClient:流结束后立刻失败 pending(不干等到 timeout)", async () => { +test("SdkMcpAdapter:HTTP 4xx POST 复刻 `MCP request failed: - ` 文案契约", async () => { const originalFetch = globalThis.fetch; - const encoder = new TextEncoder(); - globalThis.fetch = async (input, init) => { - const url = requestUrl(input); - if ((init?.method ?? "GET") === "GET" || url.endsWith("/sse")) { - // Close the stream immediately after the endpoint event - const stream = new ReadableStream({ - start(controller) { - controller.enqueue( - encoder.encode("event:endpoint\ndata:/api/v1/mcps/WebParser/message?sessionId=x\n\n"), - ); - controller.close(); - }, - }); - return new Response(stream, { - status: 200, - headers: { "Content-Type": "text/event-stream" }, - }); - } - return new Response(null, { status: 200 }); - }; + globalThis.fetch = async () => + new Response("MCP不存在或未开通", { status: 404, statusText: "Not Found" }); try { - const client = new McpSseClient( - testDeps({ timeout: 5 }), - "https://example.test/sse", - "sk-test", - ); - const started = Date.now(); - await expect(client.initialize()).rejects.toThrow(/stream ended unexpectedly/i); - expect(Date.now() - started).toBeLessThan(2000); - client.close(); + const adapter = new SdkMcpAdapter({ + deps: testDeps(), + url: "https://example.test/mcp", + authToken: "sk-test", + transport: "streamable", + }); + const error = await adapter.initialize().catch((reason: unknown) => reason); + expect(error).toBeInstanceOf(BailianError); + expect((error as BailianError).message).toMatch(/^MCP request failed:\s*404\b/); + expect((error as BailianError).message).toContain("MCP不存在或未开通"); } finally { globalThis.fetch = originalFetch; } }); -test("McpSseClient:string JSON-RPC id 可匹配;仅认 event:endpoint", async () => { +// ---- connectBailianMcpWithFallback orchestration ---- + +test("connectBailianMcpWithFallback:成功走 Streamable", async () => { const originalFetch = globalThis.fetch; - let sseController: ReadableStreamDefaultController | undefined; - const encoder = new TextEncoder(); + const urls: string[] = []; globalThis.fetch = async (input, init) => { const url = requestUrl(input); - if ((init?.method ?? "GET") === "GET" || url.endsWith("/sse")) { - const stream = new ReadableStream({ - start(controller) { - sseController = controller; - // Untyped events must not be treated as endpoint - controller.enqueue( - encoder.encode(`data:${JSON.stringify({ jsonrpc: "2.0", id: 99, result: {} })}\n\n`), - ); - controller.enqueue( - encoder.encode("event:endpoint\ndata:/api/v1/mcps/WebParser/message?sessionId=x\n\n"), - ); - }, - }); - return new Response(stream, { - status: 200, - headers: { "Content-Type": "text/event-stream" }, - }); - } - - if (url.includes("/message")) { - const body = typeof init?.body === "string" ? JSON.parse(init.body) : {}; - queueMicrotask(() => { - if (body.id != null && sseController) { - // Echo id as a string - sseController.enqueue(encoder.encode(jsonRpcResult(String(body.id), {}))); - } - }); - return new Response(null, { status: 200 }); + urls.push(`${init?.method ?? "GET"} ${url}`); + if (url.includes("/sse")) { + return new Response("should not hit sse", { status: 500 }); } - - return new Response("unexpected", { status: 500 }); - }; - - try { - const client = new McpSseClient(testDeps(), "https://example.test/sse", "sk-test"); - await client.initialize(); - client.close(); - } finally { - globalThis.fetch = originalFetch; - } -}); - -test("McpClient:支持 text/event-stream 响应体", async () => { - const originalFetch = globalThis.fetch; - const sentHeaders: Headers[] = []; - - globalThis.fetch = async (_input, init) => { - sentHeaders.push(new Headers(init?.headers)); - const body = typeof init?.body === "string" ? JSON.parse(init.body) : {}; - if (body.method === "notifications/initialized") { - return new Response(null, { status: 202 }); + const body = parseBody(init); + if (body.method === "initialize") { + return jsonResponse(jsonRpc(body.id!, INIT_RESULT)); } - const sse = `event: message\ndata: ${JSON.stringify({ - jsonrpc: "2.0", - id: body.id, - result: { - protocolVersion: "2025-03-26", - capabilities: {}, - serverInfo: { name: "x", version: "0" }, - }, - })}\n\n`; - return new Response(sse, { - status: 200, - headers: { "Content-Type": "text/event-stream" }, - }); + return new Response(null, { status: 200 }); }; try { - const client = new McpClient(testDeps(), "https://example.test/mcp", "sk-test"); - await client.initialize(); - expect(sentHeaders.length).toBeGreaterThan(0); - for (const headers of sentHeaders) { - expect(headers.get("X-Dashscope-Service")).toBe("bailian-cli"); - } - } finally { - globalThis.fetch = originalFetch; - } -}); - -test("McpSseClient.close 可中止挂起 GET", async () => { - const originalFetch = globalThis.fetch; - let aborted = false; - - globalThis.fetch = async (_input, init) => { - const signal = init?.signal; - if (signal) { - signal.addEventListener("abort", () => { - aborted = true; - }); - } - const stream = new ReadableStream({ - start(controller) { - controller.enqueue( - new TextEncoder().encode( - "event:endpoint\ndata:/api/v1/mcps/WebParser/message?sessionId=x\n\n", - ), - ); - }, - }); - return new Response(stream, { - status: 200, - headers: { "Content-Type": "text/event-stream" }, + const connected = await connectBailianMcpWithFallback({ + deps: testDeps(), + authToken: "sk-test", + httpUrl: "https://example.test/api/v1/mcps/WebParser/mcp", + sseUrl: "https://example.test/api/v1/mcps/WebParser/sse", + serverCode: "WebParser", }); - }; - - try { - const client = new McpSseClient(testDeps(), "https://example.test/sse", "sk-test"); - const initPromise = client.initialize().catch(() => undefined); - await new Promise((resolve) => setTimeout(resolve, 20)); - client.close(); - await initPromise; - expect(aborted).toBe(true); + expect(connected.url).toContain("/mcp"); + expect(urls.some((entry) => entry.includes("/sse"))).toBe(false); + connected.client.close?.(); } finally { globalThis.fetch = originalFetch; } }); -test("McpSseClient:等待响应头受 --timeout 约束", async () => { +test("connectBailianMcpWithFallback:WebSearch 405 不降级、抛 BailianError、不触达 /sse", async () => { const originalFetch = globalThis.fetch; + const urls: string[] = []; - globalThis.fetch = async (_input, init) => { - const signal = init?.signal; - return new Promise((_resolve, reject) => { - if (!signal) { - reject(new Error("missing signal")); - return; - } - if (signal.aborted) { - reject(new DOMException("This operation was aborted.", "AbortError")); - return; - } - signal.addEventListener( - "abort", - () => reject(new DOMException("This operation was aborted.", "AbortError")), - { once: true }, - ); + globalThis.fetch = async (input) => { + urls.push(requestUrl(input)); + return new Response("current mcp not support streamableHttp", { + status: 405, + statusText: "Method Not Allowed", }); }; try { - const client = new McpSseClient( - testDeps({ timeout: 1 }), - "https://example.test/sse", - "sk-test", - ); - const started = Date.now(); - await expect(client.initialize()).rejects.toThrow(/timed out waiting for response headers/i); - expect(Date.now() - started).toBeLessThan(2500); - client.close(); - } finally { - globalThis.fetch = originalFetch; - } -}); - -test("McpSseClient:非 2xx 不产生 unhandledRejection", async () => { - const originalFetch = globalThis.fetch; - const unhandled: unknown[] = []; - const onUnhandled = (reason: unknown) => { - unhandled.push(reason); - }; - process.on("unhandledRejection", onUnhandled); - - globalThis.fetch = async () => - new Response("boom", { status: 500, statusText: "Internal Server Error" }); - - try { - const client = new McpSseClient(testDeps(), "https://example.test/sse", "sk-test"); - await expect(client.initialize()).rejects.toThrow(/MCP request failed:\s*500/i); - await new Promise((resolve) => setTimeout(resolve, 30)); - expect(unhandled).toEqual([]); - client.close(); - } finally { - process.off("unhandledRejection", onUnhandled); - globalThis.fetch = originalFetch; - } -}); - -test("McpSseClient:非 2xx 读 body 仍受 --timeout 约束", async () => { - const originalFetch = globalThis.fetch; - - globalThis.fetch = async (_input, init) => { - const signal = init?.signal; - return { - ok: false, - status: 500, - statusText: "Internal Server Error", - async text() { - return new Promise((_resolve, reject) => { - if (!signal) { - reject(new Error("missing signal")); - return; - } - if (signal.aborted) { - reject(new DOMException("This operation was aborted.", "AbortError")); - return; - } - signal.addEventListener( - "abort", - () => reject(new DOMException("This operation was aborted.", "AbortError")), - { once: true }, - ); - }); - }, - } as Response; - }; - - try { - const client = new McpSseClient( - testDeps({ timeout: 1 }), - "https://example.test/sse", - "sk-test", - ); - const started = Date.now(); - await expect(client.initialize()).rejects.toThrow(/timed out reading error response body/i); - expect(Date.now() - started).toBeLessThan(2500); - client.close(); + await expect( + connectBailianMcpWithFallback({ + deps: testDeps(), + authToken: "sk-test", + httpUrl: "https://example.test/api/v1/mcps/WebSearch/mcp", + sseUrl: "https://example.test/api/v1/mcps/WebSearch/sse", + serverCode: "WebSearch", + }), + ).rejects.toBeInstanceOf(BailianError); + expect(urls.some((url) => url.includes("/sse"))).toBe(false); } finally { globalThis.fetch = originalFetch; } }); -test("McpSseClient:fetch 失败抛出原始 TypeError(保留 ENOTFOUND)", async () => { +test("connectBailianMcpWithFallback:Bailian 路径 404 不降级,错误含 404", async () => { const originalFetch = globalThis.fetch; - const root = Object.assign(new Error("getaddrinfo ENOTFOUND example.test"), { - code: "ENOTFOUND", - }); - const fetchFailed = new TypeError("fetch failed", { cause: root }); + const urls: string[] = []; - globalThis.fetch = async () => { - throw fetchFailed; + globalThis.fetch = async (input) => { + urls.push(requestUrl(input)); + return new Response("MCP不存在或未开通", { status: 404, statusText: "Not Found" }); }; try { - const client = new McpSseClient(testDeps(), "https://example.test/sse", "sk-test"); - const error = await client.initialize().catch((reason: unknown) => reason); - expect(error).toBe(fetchFailed); - expect((error as TypeError & { cause?: NodeJS.ErrnoException }).cause?.code).toBe("ENOTFOUND"); - client.close(); + await expect( + connectBailianMcpWithFallback({ + deps: testDeps(), + authToken: "sk-test", + httpUrl: "https://example.test/api/v1/mcps/WebParser/mcp", + sseUrl: "https://example.test/api/v1/mcps/WebParser/sse", + serverCode: "WebParser", + }), + ).rejects.toMatchObject({ message: expect.stringContaining("404") }); + expect(urls.some((url) => url.includes("/sse"))).toBe(false); } finally { globalThis.fetch = originalFetch; } }); -test("McpSseClient:fetch 失败后同实例可重新 openSse", async () => { +test("connectBailianMcpWithFallback:405 降级到经典 SSE 并连接成功", async () => { const originalFetch = globalThis.fetch; - let attempt = 0; - let sseController: ReadableStreamDefaultController | undefined; + const urls: string[] = []; const encoder = new TextEncoder(); + let sseController: ReadableStreamDefaultController | undefined; globalThis.fetch = async (input, init) => { const url = requestUrl(input); const method = init?.method ?? "GET"; - if (method === "GET" || url.endsWith("/sse")) { - attempt += 1; - if (attempt === 1) { - throw new TypeError("fetch failed"); - } + urls.push(`${method} ${url}`); + + if (url.endsWith("/mcp")) { + return new Response("Method Not Allowed", { status: 405, statusText: "Method Not Allowed" }); + } + if (url.endsWith("/sse") && method === "GET") { const stream = new ReadableStream({ start(controller) { sseController = controller; - controller.enqueue(encoder.encode("event: endpoint\ndata: /message\n\n")); + controller.enqueue( + encoder.encode("event: endpoint\ndata: /api/v1/mcps/WebParser/message?sessionId=s\n\n"), + ); }, }); return new Response(stream, { @@ -617,37 +447,57 @@ test("McpSseClient:fetch 失败后同实例可重新 openSse", async () => { headers: { "Content-Type": "text/event-stream" }, }); } - const body = typeof init?.body === "string" ? JSON.parse(init.body) : {}; - queueMicrotask(() => { - if (body.id != null && sseController) { - sseController.enqueue(encoder.encode(jsonRpcResult(body.id, {}))); + if (url.includes("/message")) { + const body = parseBody(init); + if (body.id != null) { + const result = body.method === "initialize" ? INIT_RESULT : {}; + queueMicrotask(() => { + sseController?.enqueue( + encoder.encode(`event: message\ndata: ${jsonRpc(body.id!, result)}\n\n`), + ); + }); } - }); - return new Response("{}", { status: 200, headers: { "Content-Type": "application/json" } }); + return new Response(null, { status: 202 }); + } + return new Response("unexpected", { status: 500 }); }; try { - const client = new McpSseClient(testDeps(), "https://example.test/sse", "sk-test"); - await expect(client.initialize()).rejects.toThrow(/fetch failed/i); - await client.initialize(); - client.close(); + const connected = await connectBailianMcpWithFallback({ + deps: testDeps(), + authToken: "sk-test", + httpUrl: "https://example.test/api/v1/mcps/WebParser/mcp", + sseUrl: "https://example.test/api/v1/mcps/WebParser/sse", + serverCode: "WebParser", + }); + expect(connected.url).toContain("/sse"); + expect(urls.some((entry) => entry.startsWith("GET ") && entry.includes("/sse"))).toBe(true); + connected.client.close?.(); } finally { globalThis.fetch = originalFetch; } }); -test("McpSseClient:close 可中止进行中的 POST", async () => { +test("connectBailianMcpWithFallback:--url 覆盖,POST 405 后同 URL GET SSE 降级", async () => { const originalFetch = globalThis.fetch; - let postAborted = false; + const urls: string[] = []; const encoder = new TextEncoder(); + const overrideUrl = "https://custom.example/mcp"; + let sseController: ReadableStreamDefaultController | undefined; globalThis.fetch = async (input, init) => { const url = requestUrl(input); const method = init?.method ?? "GET"; - if (method === "GET" || url.endsWith("/sse")) { + urls.push(`${method} ${url}`); + + if (method === "POST" && url === overrideUrl) { + return new Response("Method Not Allowed", { status: 405, statusText: "Method Not Allowed" }); + } + if (method === "GET" && url === overrideUrl) { const stream = new ReadableStream({ start(controller) { - controller.enqueue(encoder.encode("event: endpoint\ndata: /message\n\n")); + sseController = controller; + controller.enqueue(encoder.encode("event: endpoint\ndata: /message?sessionId=x\n\n")); }, }); return new Response(stream, { @@ -655,88 +505,33 @@ test("McpSseClient:close 可中止进行中的 POST", async () => { headers: { "Content-Type": "text/event-stream" }, }); } - - const signal = init?.signal; - return new Promise((_resolve, reject) => { - if (!signal) { - reject(new Error("missing signal")); - return; - } - const onAbort = () => { - postAborted = true; - reject(new DOMException("This operation was aborted.", "AbortError")); - }; - if (signal.aborted) { - onAbort(); - return; + if (url.includes("/message")) { + const body = parseBody(init); + if (body.id != null) { + const result = body.method === "initialize" ? INIT_RESULT : {}; + queueMicrotask(() => { + sseController?.enqueue( + encoder.encode(`event: message\ndata: ${jsonRpc(body.id!, result)}\n\n`), + ); + }); } - signal.addEventListener("abort", onAbort, { once: true }); - }); - }; - - try { - const client = new McpSseClient( - testDeps({ timeout: 5 }), - "https://example.test/sse", - "sk-test", - ); - const initPromise = client.initialize(); - await new Promise((resolve) => setTimeout(resolve, 30)); - client.close(); - await expect(initPromise).rejects.toThrow(/session closed|aborted/i); - expect(postAborted).toBe(true); - } finally { - globalThis.fetch = originalFetch; - } -}); - -test("McpSseClient:POST 非 2xx 读 body 仍受 --timeout 约束", async () => { - const originalFetch = globalThis.fetch; - const encoder = new TextEncoder(); - - globalThis.fetch = async (input, init) => { - const url = requestUrl(input); - const method = init?.method ?? "GET"; - if (method === "GET" || url.endsWith("/sse")) { - const stream = new ReadableStream({ - start(controller) { - controller.enqueue(encoder.encode("event: endpoint\ndata: /message\n\n")); - }, - }); - return new Response(stream, { - status: 200, - headers: { "Content-Type": "text/event-stream" }, - }); + return new Response(null, { status: 202 }); } - - const signal = init?.signal; - const body = new ReadableStream({ - start(controller) { - if (!signal) return; - const onAbort = () => { - try { - controller.error(new DOMException("This operation was aborted.", "AbortError")); - } catch { - /* ignore */ - } - }; - if (signal.aborted) onAbort(); - else signal.addEventListener("abort", onAbort, { once: true }); - }, - }); - return new Response(body, { status: 500, statusText: "Internal Server Error" }); + return new Response("unexpected", { status: 500 }); }; try { - const client = new McpSseClient( - testDeps({ timeout: 1 }), - "https://example.test/sse", - "sk-test", - ); - const started = Date.now(); - await expect(client.initialize()).rejects.toThrow(/timed out reading error response body/i); - expect(Date.now() - started).toBeLessThan(2500); - client.close(); + const connected = await connectBailianMcpWithFallback({ + deps: testDeps(), + authToken: "sk-test", + httpUrl: "https://example.test/api/v1/mcps/WebParser/mcp", + sseUrl: "https://example.test/api/v1/mcps/WebParser/sse", + serverCode: "WebParser", + urlOverride: overrideUrl, + }); + expect(connected.url).toBe(overrideUrl); + expect(urls.some((entry) => entry.startsWith(`GET ${overrideUrl}`))).toBe(true); + connected.client.close?.(); } finally { globalThis.fetch = originalFetch; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b9d42d57d..6305f688a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,11 +49,6 @@ catalogs: specifier: ^3.4.0 version: 3.4.0 -overrides: - vite: npm:@voidzero-dev/vite-plus-core@0.3.3 - vitest: 4.1.11 - ws@>=8.0.0 <8.21.0: 8.21.3 - importers: .: @@ -76,22 +71,22 @@ importers: version: 4.0.1(@deepseek-ai/cordis-plugin-include@1.0.6)(@deepseek-ai/cordis-plugin-loader@1.0.2) '@deepseek-ai/dsh-agent': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) + version: 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-api-remotes': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(3efff7030edd34682350922988afd2c1) + version: 0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou) '@deepseek-ai/dsh-client-connection': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(47e886c317e93578e9d1303a9c4dd9fb) + version: 0.1.0-rc.8(uegbxiinkg3b3af5xxhuothm4y) '@deepseek-ai/dsh-client-locale': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(86e16fe7bdb0cdc3694c80972d09e7f7) + version: 0.1.0-rc.8(s5gtd5obeihyoqucph6oeuiqfe) '@deepseek-ai/dsh-client-runtime': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(d60c775270b822deee6b25449def3bb9) + version: 0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4) '@deepseek-ai/dsh-client-ui-settings': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(3efff7030edd34682350922988afd2c1))(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(d60c775270b822deee6b25449def3bb9))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1)) + version: 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou))(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1)) '@deepseek-ai/dsh-client-ui-slots': specifier: ^0.1.0-rc.6 version: 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) @@ -103,7 +98,7 @@ importers: version: 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-session': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + version: 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) '@deepseek-ai/dsh-settings': specifier: ^0.1.0-rc.6 version: 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) @@ -112,7 +107,7 @@ importers: version: 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-tools': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(5bda1be499cac5a517847cfe82ab203b) + version: 0.1.0-rc.8(53xifwsgcqiqivitsot3r6a3te) '@deepseek-ai/schemastery': specifier: ^3.18.1 version: 3.18.1 @@ -239,6 +234,9 @@ importers: specifier: 'catalog:' version: 3.4.0 devDependencies: + '@modelcontextprotocol/sdk': + specifier: ^1 + version: 1.32.1(zod@3.25.76) '@types/node': specifier: 'catalog:' version: 24.12.2 @@ -257,6 +255,9 @@ importers: vite-plus: specifier: 'catalog:' version: 0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3) + zod: + specifier: ^3 + version: 3.25.76 packages/e2e: dependencies: @@ -1107,9 +1108,25 @@ packages: cpu: [x64] os: [win32] + '@hono/node-server@2.1.5': + resolution: {integrity: sha512-MgP/I06GdvsilDspMk/qmRzpk8LOUStP6jFAbSRi40W09DhoyUn+Mj7eyKICPqeYKybOjVFLVIAQzvu1bfIa7Q==} + engines: {node: '>=20'} + peerDependencies: + hono: ^4 || ^5.0.0-0 + '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@modelcontextprotocol/sdk@1.32.1': + resolution: {integrity: sha512-2DdE+SJDtzLEEWzY1ZjY7Q+VcPhcV1KisD3zI4u0XZyktsjHum1mwbMI+JaulUBi2OZk+KJAi2uPXzxichPkdw==} + engines: {node: '>=18'} + peerDependencies: + '@cfworker/json-schema': ^4.1.1 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + '@cfworker/json-schema': + optional: true + '@openagentpack/sdk@0.7.1': resolution: {integrity: sha512-OENks8UdfWFanvhJIVbqyUX1+XGavHnrxDiFx4SoJoGRXi45cOgyYtWWbG5VdDI2I5Dpo9eGNaw/JtDnkdxUcg==} engines: {node: '>=18.17.0'} @@ -2007,6 +2024,18 @@ packages: '@yuku-toolchain/types@0.9.5': resolution: {integrity: sha512-KiuLNNgX9uNealaWAR+G3/cMXnRk9x4TY2EkYe/KIag+UPdwiA0RRf1hr1WAxzTP8KGzCTkqUdLPvqh32sEO3w==} + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv@8.20.0: resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} @@ -2088,14 +2117,30 @@ packages: bare-url@2.4.5: resolution: {integrity: sha512-K+y9xF1tN+CdPu4qWwr0QiK1Al07eFPGYK5M2pDXcmHdMdgC/tT/bpmMe1hrmRHaidKLkXrC+cRNYf3XVDUhSQ==} + body-parser@2.3.0: + resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} + engines: {node: '>=18'} + boxen@8.0.1: resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} engines: {node: '>=18'} + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + cac@7.0.0: resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==} engines: {node: '>=20.19.0'} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + camelcase@8.0.0: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} @@ -2112,18 +2157,59 @@ packages: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} + content-disposition@2.0.1: + resolution: {integrity: sha512-e+H0ZXHSWYrENhQzw1LPuP4oF5MzVKmDU6d3hxlvaPEYLLg62MxtQNPRx4SYSuYJSBUgnQIG4HIN2tEtNv7Dog==} + engines: {node: '>=18'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + content-type@2.1.0: + resolution: {integrity: sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==} + engines: {node: '>=18'} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cors@2.8.6: + resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} + engines: {node: '>= 0.10'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + defu@6.1.7: resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -2144,6 +2230,13 @@ packages: oxc-resolver: optional: true + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -2154,24 +2247,65 @@ packages: resolution: {integrity: sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q==} engines: {node: '>=14'} + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + es-module-lexer@2.3.2: resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + esbuild@0.28.1: resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} engines: {node: '>=18'} hasBin: true + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + events-universal@1.0.1: resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} + eventsource-parser@3.1.1: + resolution: {integrity: sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==} + engines: {node: '>=18.0.0'} + + eventsource@3.0.7: + resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} + engines: {node: '>=18.0.0'} + expect-type@1.4.0: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} + express-rate-limit@8.7.1: + resolution: {integrity: sha512-2FXbqkygil3mZiXzEtM0IjE/UBmBNot0J1GEVrJT4JbrvwOSoEtqtO+wHbiMQELWe1eNvHoYRg2dkjOid+6JkA==} + engines: {node: '>= 16'} + peerDependencies: + express: '>= 4.11' + + express@5.3.0: + resolution: {integrity: sha512-qCqy1xSoaugxOD4IVHb1ZWdkvCF2W3aE2okKouWj8VwJ+ztskSiXoBnCSJqfKT+cVPJhuJqe9YLbY425+Zh00g==} + engines: {node: '>= 18'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -2193,22 +2327,69 @@ packages: fflate@0.8.3: resolution: {integrity: sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==} + finalhandler@2.1.1: + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + get-east-asian-width@1.6.0: resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} engines: {node: '>=18'} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + get-tsconfig@5.0.0-beta.5: resolution: {integrity: sha512-/6gFNr0N04nob252sTQxyFLi3eKFRqIg1I87YcqAMT1i6SQrSF6KujUEQrtrjMV0H/eejTCltLdDSTEMzHbnsQ==} engines: {node: '>=20.20.0'} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + hono@4.13.13: + resolution: {integrity: sha512-CQ46U0ZkAGmbT/4UxdzzGJpacP2IeKgY4a5/tOI9AABbpOMfK739wfDXmv1usCk+3RkKj1hQy4/fjhiwa2xlrA==} + engines: {node: '>=16.9.0'} + hookable@6.1.1: resolution: {integrity: sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==} + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + iconv-lite@0.7.3: + resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} + engines: {node: '>=0.10.0'} + immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} @@ -2222,17 +2403,34 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + ip-address@10.7.4: + resolution: {integrity: sha512-DWBMKyeM25D70nrIiTkgQth59/G+naKOTep6huF9j+GmeK3DMD60Zvxg5d5qQnz+38AHgou6ean2LECX+lrKDg==} + engines: {node: '>= 12'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + jose@6.2.12: + resolution: {integrity: sha512-9NiFmJEex0sy2Dk58j2UGBSHgUs2ypF9eZSu4L6vjOX3Dp96Sw1F3uL+H+D1sx02jZZdzUT0HgvCy59CuvXcWw==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2243,6 +2441,9 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema-typed@8.0.2: + resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} + jszip@3.10.1: resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} @@ -2408,19 +2609,61 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + media-typer@1.1.1: + resolution: {integrity: sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==} + engines: {node: '>= 0.8'} + + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + mrmime@2.0.1: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + negotiator@1.1.0: + resolution: {integrity: sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==} + engines: {node: '>=18'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + obug@2.1.4: resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + oxfmt@0.68.0: resolution: {integrity: sha512-Z0XMofcXCGUXbcpBHnWyUiX93BGiw1B+lcHNbQDWEtOhX06ewoFfu4zXkyiLhRrNnMq0twqXRHUcJetf+GsiQQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2454,6 +2697,17 @@ packages: pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-to-regexp@8.4.2: + resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -2467,6 +2721,10 @@ packages: resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} engines: {node: '>=12'} + pkce-challenge@5.0.1: + resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} + engines: {node: '>=16.20.0'} + pngjs@7.0.0: resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} engines: {node: '>=14.19.0'} @@ -2482,9 +2740,25 @@ packages: process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + proxy-addr@2.0.8: + resolution: {integrity: sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==} + engines: {node: '>= 0.10'} + + qs@6.16.1: + resolution: {integrity: sha512-5Px6J7rfHBAGUhNQ3es4YzcOdBBw0SDcVtThJml4RdnKw4tKs2epA0kPZ+K8X+WiHktT93RHVcQ/3ym5aTCgtg==} + engines: {node: '>=0.6'} + quansync@1.0.0: resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} + range-parser@1.3.0: + resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==} + engines: {node: '>= 0.6'} + + raw-body@3.0.2: + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} + engines: {node: '>= 0.10'} + react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} @@ -2526,12 +2800,54 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + send@1.2.1: + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} + engines: {node: '>= 18'} + + serve-static@2.2.1: + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} + engines: {node: '>= 18'} + setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} + engines: {node: '>= 0.4'} + siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -2553,6 +2869,10 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + std-env@4.1.0: resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} @@ -2606,6 +2926,10 @@ packages: resolution: {integrity: sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==} engines: {node: '>=14.0.0'} + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} @@ -2657,6 +2981,10 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} + type-is@2.1.0: + resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} + engines: {node: '>= 18'} + typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} @@ -2680,6 +3008,10 @@ packages: resolution: {integrity: sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==} engines: {node: '>=18.17'} + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + use-sync-external-store@1.2.0: resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} peerDependencies: @@ -2688,6 +3020,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + verkit@0.3.2: resolution: {integrity: sha512-zj/ob3UsvJGN0whEAKFp53REA5X66hvffVqoCtVQAakJKnKlH+/PcOfMoFwIG/o4rElqLv/ycAFlx8ZlXUorCg==} engines: {node: '>=18.12.0'} @@ -2746,6 +3082,11 @@ packages: jsdom: optional: true + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + why-is-node-running@2.3.0: resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} engines: {node: '>=8'} @@ -2759,6 +3100,9 @@ packages: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.21.3: resolution: {integrity: sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==} engines: {node: '>=10.0.0'} @@ -2803,6 +3147,14 @@ packages: yuku-parser@0.9.5: resolution: {integrity: sha512-IBnAdNVMswWbJcM7woPluOudectJzFjJ1N8jVRxP9Uq4CIv5hZdBIcdmtRbFDYF/Ph2j2gVup4YJ4N9mh0jYFA==} + zod-to-json-schema@3.25.2: + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + peerDependencies: + zod: ^3.25.28 || ^4 + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zod@4.4.3: resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} @@ -2868,99 +3220,99 @@ snapshots: '@deepseek-ai/cosmokit@1.8.2': {} - '@deepseek-ai/dsh-agent-default-model@0.1.0-rc.8(d611ebd21e3e0813c50cdd15791bd486)': + '@deepseek-ai/dsh-agent-default-model@0.1.0-rc.8(nu3v65asnhd7nzlags6exbx7cu)': dependencies: '@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.8(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-agent-presets@0.1.0-rc.8(c61da10b37997a0dffc1aedc219daaf2)': + '@deepseek-ai/dsh-agent-presets@0.1.0-rc.8(5y7oeayczjdoxnag4x7zbpuyki)': dependencies: '@deepseek-ai/cordis': 4.0.1(@deepseek-ai/cordis-plugin-include@1.0.6)(@deepseek-ai/cordis-plugin-loader@1.0.2) '@deepseek-ai/cordis-plugin-include': 1.0.6(@deepseek-ai/cordis-plugin-loader@1.0.2)(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/cordis-plugin-loader': 1.0.2(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-atomic-write': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-home-paths': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/schemastery': 3.18.1 js-yaml: 4.3.1 - '@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7)': + '@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4)': dependencies: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-agent@0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7)': + '@deepseek-ai/dsh-agent@0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4)': dependencies: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-api-gateway@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-registry@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))': dependencies: '@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-client-connection': 0.1.0-rc.8(47e886c317e93578e9d1303a9c4dd9fb) + '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(uegbxiinkg3b3af5xxhuothm4y) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-typert-registry': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(3efff7030edd34682350922988afd2c1)': + '@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(gzdtgzznil4onulwxurcvqu5r4)': dependencies: '@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(92f269661ea5e195fab72177f1a12db7) - '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(c61da10b37997a0dffc1aedc219daaf2) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(5y7oeayczjdoxnag4x7zbpuyki) '@deepseek-ai/dsh-api-gateway': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-registry@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-commands': 0.1.0-rc.8(be93aee212d5ee88b81aa983a6ddd927) - '@deepseek-ai/dsh-cordis-host-runner': 0.1.0-rc.8(40da5beb010d686c5e2151e04606e202) + '@deepseek-ai/dsh-commands': 0.1.0-rc.8(s2pue3nldjdjibihazcgqufs5e) + '@deepseek-ai/dsh-cordis-host-runner': 0.1.0-rc.8(7qt3ujxvfyjcos5zt4s3xinfkq) '@deepseek-ai/dsh-credentials': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-file-reference': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-goal': 0.1.0-rc.8(229ab81e42fcff0fcb8cf501dceaea15) + '@deepseek-ai/dsh-file-reference': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-goal': 0.1.0-rc.8(rmioigujzdamkqipym7wzjsjze) '@deepseek-ai/dsh-host-plugin-inventory': 0.1.0-rc.8(@deepseek-ai/cordis-plugin-loader@1.0.2)(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-message-feedback': 0.1.0-rc.8(fa979bf26319855e9b452d904429d004) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session-reference': 0.1.0-rc.8(cf2186381d6c9247540aad69c3158862) + '@deepseek-ai/dsh-message-feedback': 0.1.0-rc.8(bezyjlz3tp3sbbg2tfte3wjx7y) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session-reference': 0.1.0-rc.8(hng7uvyvmivmpc2kgslwtdqzsu) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-typert-registry': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(f49a1a2925da94a3cb3629328aff349c)': + '@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou)': dependencies: '@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.8(92f269661ea5e195fab72177f1a12db7) - '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(c61da10b37997a0dffc1aedc219daaf2) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(5y7oeayczjdoxnag4x7zbpuyki) '@deepseek-ai/dsh-api-gateway': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-registry@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-commands': 0.1.0-rc.8(be93aee212d5ee88b81aa983a6ddd927) - '@deepseek-ai/dsh-cordis-host-runner': 0.1.0-rc.8(40da5beb010d686c5e2151e04606e202) + '@deepseek-ai/dsh-commands': 0.1.0-rc.8(s2pue3nldjdjibihazcgqufs5e) + '@deepseek-ai/dsh-cordis-host-runner': 0.1.0-rc.8(7qt3ujxvfyjcos5zt4s3xinfkq) '@deepseek-ai/dsh-credentials': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-file-reference': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-goal': 0.1.0-rc.8(229ab81e42fcff0fcb8cf501dceaea15) + '@deepseek-ai/dsh-file-reference': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-goal': 0.1.0-rc.8(rmioigujzdamkqipym7wzjsjze) '@deepseek-ai/dsh-host-plugin-inventory': 0.1.0-rc.8(@deepseek-ai/cordis-plugin-loader@1.0.2)(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-message-feedback': 0.1.0-rc.8(fa979bf26319855e9b452d904429d004) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session-reference': 0.1.0-rc.8(cf2186381d6c9247540aad69c3158862) + '@deepseek-ai/dsh-message-feedback': 0.1.0-rc.8(bezyjlz3tp3sbbg2tfte3wjx7y) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session-reference': 0.1.0-rc.8(hng7uvyvmivmpc2kgslwtdqzsu) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-typert-registry': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) @@ -2981,50 +3333,50 @@ snapshots: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-client-connection@0.1.0-rc.8(47e886c317e93578e9d1303a9c4dd9fb)': + '@deepseek-ai/dsh-client-connection@0.1.0-rc.8(uegbxiinkg3b3af5xxhuothm4y)': dependencies: '@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-attachment': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-commands': 0.1.0-rc.8(be93aee212d5ee88b81aa983a6ddd927) - '@deepseek-ai/dsh-host-apiproxy': 0.1.0-rc.8(07f963f74f292eaeb103f0faeee23085) + '@deepseek-ai/dsh-commands': 0.1.0-rc.8(s2pue3nldjdjibihazcgqufs5e) + '@deepseek-ai/dsh-host-apiproxy': 0.1.0-rc.8(zhkmxcibxhrifox3ckn5d23a6e) '@deepseek-ai/dsh-host-webserver': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-tools': 0.1.0-rc.8(5bda1be499cac5a517847cfe82ab203b) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-tools': 0.1.0-rc.8(53xifwsgcqiqivitsot3r6a3te) '@deepseek-ai/schemastery': 3.18.1 ws: 8.21.3 transitivePeerDependencies: - bufferutil - utf-8-validate - '@deepseek-ai/dsh-client-locale@0.1.0-rc.8(86e16fe7bdb0cdc3694c80972d09e7f7)': + '@deepseek-ai/dsh-client-locale@0.1.0-rc.8(s5gtd5obeihyoqucph6oeuiqfe)': dependencies: '@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-api-remotes': 0.1.0-rc.8(3efff7030edd34682350922988afd2c1) - '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(47e886c317e93578e9d1303a9c4dd9fb) - '@deepseek-ai/dsh-client-runtime': 0.1.0-rc.8(d60c775270b822deee6b25449def3bb9) - '@deepseek-ai/dsh-client-ui-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(3efff7030edd34682350922988afd2c1))(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(d60c775270b822deee6b25449def3bb9))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1)) + '@deepseek-ai/dsh-api-remotes': 0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou) + '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(uegbxiinkg3b3af5xxhuothm4y) + '@deepseek-ai/dsh-client-runtime': 0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4) + '@deepseek-ai/dsh-client-ui-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou))(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(d60c775270b822deee6b25449def3bb9)': + '@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4)': dependencies: '@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(92f269661ea5e195fab72177f1a12db7) - '@deepseek-ai/dsh-api-remotes': 0.1.0-rc.8(3efff7030edd34682350922988afd2c1) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-api-remotes': 0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou) '@deepseek-ai/dsh-attachment': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(47e886c317e93578e9d1303a9c4dd9fb) - '@deepseek-ai/dsh-commands': 0.1.0-rc.8(be93aee212d5ee88b81aa983a6ddd927) - '@deepseek-ai/dsh-host-apiproxy': 0.1.0-rc.8(07f963f74f292eaeb103f0faeee23085) + '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(uegbxiinkg3b3af5xxhuothm4y) + '@deepseek-ai/dsh-commands': 0.1.0-rc.8(s2pue3nldjdjibihazcgqufs5e) + '@deepseek-ai/dsh-host-apiproxy': 0.1.0-rc.8(zhkmxcibxhrifox3ckn5d23a6e) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-llm-retry': 0.1.0-rc.8(115581c97b2438036fbd23fd81d77eff) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) - '@deepseek-ai/dsh-session-title': 0.1.0-rc.8(91b31584ff9779c6cd69a9db13c5ad7e) - '@deepseek-ai/dsh-tools': 0.1.0-rc.8(5bda1be499cac5a517847cfe82ab203b) + '@deepseek-ai/dsh-llm-retry': 0.1.0-rc.8(tmyqaedu2prdog3ai5pjncj6ri) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) + '@deepseek-ai/dsh-session-title': 0.1.0-rc.8(jzxfrqgu7wb3xsfjx5ea6eoowi) + '@deepseek-ai/dsh-tools': 0.1.0-rc.8(53xifwsgcqiqivitsot3r6a3te) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-typert-registry': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) immer: 10.2.0 @@ -3033,12 +3385,12 @@ snapshots: - '@types/react' - react - '@deepseek-ai/dsh-client-ui-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(3efff7030edd34682350922988afd2c1))(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(d60c775270b822deee6b25449def3bb9))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1))': + '@deepseek-ai/dsh-client-ui-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou))(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1))': dependencies: '@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-api-remotes': 0.1.0-rc.8(3efff7030edd34682350922988afd2c1) - '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(47e886c317e93578e9d1303a9c4dd9fb) - '@deepseek-ai/dsh-client-runtime': 0.1.0-rc.8(d60c775270b822deee6b25449def3bb9) + '@deepseek-ai/dsh-api-remotes': 0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou) + '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(uegbxiinkg3b3af5xxhuothm4y) + '@deepseek-ai/dsh-client-runtime': 0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/schemastery': 3.18.1 @@ -3053,51 +3405,51 @@ snapshots: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-commands@0.1.0-rc.8(72bbe6fdb3741b872b5fbe4132676802)': + '@deepseek-ai/dsh-commands@0.1.0-rc.8(s2pue3nldjdjibihazcgqufs5e)': dependencies: '@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.8(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-attachment': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) zod: 4.4.3 - '@deepseek-ai/dsh-commands@0.1.0-rc.8(be93aee212d5ee88b81aa983a6ddd927)': + '@deepseek-ai/dsh-commands@0.1.0-rc.8(ypqdi7louiwrwd5bmsaggruoje)': dependencies: '@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(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-attachment': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) zod: 4.4.3 - '@deepseek-ai/dsh-compaction@0.1.0-rc.8(cd54d1dbdb1933253bd594179027c07c)': + '@deepseek-ai/dsh-compaction@0.1.0-rc.8(zcqikh7jjb4nrr3c673hqfu2xu)': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-commands': 0.1.0-rc.8(be93aee212d5ee88b81aa983a6ddd927) + '@deepseek-ai/dsh-commands': 0.1.0-rc.8(s2pue3nldjdjibihazcgqufs5e) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-cordis-host-runner@0.1.0-rc.8(40da5beb010d686c5e2151e04606e202)': + '@deepseek-ai/dsh-cordis-host-runner@0.1.0-rc.8(7qt3ujxvfyjcos5zt4s3xinfkq)': dependencies: '@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(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-tools': 0.1.0-rc.8(5bda1be499cac5a517847cfe82ab203b) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-tools': 0.1.0-rc.8(53xifwsgcqiqivitsot3r6a3te) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 zod: 4.4.3 @@ -3108,38 +3460,38 @@ snapshots: '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-file-reference@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))': + '@deepseek-ai/dsh-file-reference@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))': dependencies: '@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(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) zod: 4.4.3 - '@deepseek-ai/dsh-goal@0.1.0-rc.8(229ab81e42fcff0fcb8cf501dceaea15)': + '@deepseek-ai/dsh-goal@0.1.0-rc.8(hjayf6yjypjiz4wxbwmzjunqfy)': dependencies: '@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(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 zod: 4.4.3 - '@deepseek-ai/dsh-goal@0.1.0-rc.8(ee40b9fe89b358f0d6e7a82951758559)': + '@deepseek-ai/dsh-goal@0.1.0-rc.8(rmioigujzdamkqipym7wzjsjze)': dependencies: '@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.8(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 zod: 4.4.3 @@ -3149,37 +3501,37 @@ snapshots: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-host-apiproxy@0.1.0-rc.8(07f963f74f292eaeb103f0faeee23085)': + '@deepseek-ai/dsh-host-apiproxy@0.1.0-rc.8(zhkmxcibxhrifox3ckn5d23a6e)': dependencies: '@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.8(92f269661ea5e195fab72177f1a12db7) - '@deepseek-ai/dsh-agent-default-model': 0.1.0-rc.8(d611ebd21e3e0813c50cdd15791bd486) - '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(c61da10b37997a0dffc1aedc219daaf2) - '@deepseek-ai/dsh-api-remotes': 0.1.0-rc.8(f49a1a2925da94a3cb3629328aff349c) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent-default-model': 0.1.0-rc.8(nu3v65asnhd7nzlags6exbx7cu) + '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(5y7oeayczjdoxnag4x7zbpuyki) + '@deepseek-ai/dsh-api-remotes': 0.1.0-rc.8(gzdtgzznil4onulwxurcvqu5r4) '@deepseek-ai/dsh-attachment': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-commands': 0.1.0-rc.8(72bbe6fdb3741b872b5fbe4132676802) - '@deepseek-ai/dsh-cordis-host-runner': 0.1.0-rc.8(40da5beb010d686c5e2151e04606e202) + '@deepseek-ai/dsh-commands': 0.1.0-rc.8(ypqdi7louiwrwd5bmsaggruoje) + '@deepseek-ai/dsh-cordis-host-runner': 0.1.0-rc.8(7qt3ujxvfyjcos5zt4s3xinfkq) '@deepseek-ai/dsh-credentials': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-goal': 0.1.0-rc.8(ee40b9fe89b358f0d6e7a82951758559) + '@deepseek-ai/dsh-goal': 0.1.0-rc.8(hjayf6yjypjiz4wxbwmzjunqfy) '@deepseek-ai/dsh-host-directory-picker': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-jobs': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) + '@deepseek-ai/dsh-jobs': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-native-command': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) - '@deepseek-ai/dsh-session-projection-cache': 0.1.0-rc.8(80a7956f091cdf0c220b226dd100fe03) - '@deepseek-ai/dsh-session-query': 0.1.0-rc.8(e87dfefb8b6f6903ab3a7d4d893e4616) - '@deepseek-ai/dsh-session-title': 0.1.0-rc.8(91b31584ff9779c6cd69a9db13c5ad7e) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) + '@deepseek-ai/dsh-session-projection-cache': 0.1.0-rc.8(aecd6ik5xb75vio2al2lw256w4) + '@deepseek-ai/dsh-session-query': 0.1.0-rc.8(o7pujk3q5o2rri5hwyefkmd7xy) + '@deepseek-ai/dsh-session-title': 0.1.0-rc.8(jzxfrqgu7wb3xsfjx5ea6eoowi) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/dsh-skill': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-subagent': 0.1.0-rc.8(42428574dae299167d0987b281167061) - '@deepseek-ai/dsh-tools': 0.1.0-rc.8(68a9dffdb9e9c8636f3b708c6fd1edd1) - '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(380a43f4d6510c4a5dfadf54dc7f17a7) - '@deepseek-ai/dsh-user-questions': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))) - '@deepseek-ai/dsh-workspace': 0.1.0-rc.8(b22e0d48f5e81af272cd56aac64d0d48) + '@deepseek-ai/dsh-subagent': 0.1.0-rc.8(coi676g3ltfbkxbpzz2n5dgy7a) + '@deepseek-ai/dsh-tools': 0.1.0-rc.8(cjphcmfsxr6vrfny2gkyrgolze) + '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(wiirn2jei2nkjmsboxw35on4mm) + '@deepseek-ai/dsh-user-questions': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))) + '@deepseek-ai/dsh-workspace': 0.1.0-rc.8(n3vdmq7iw27i2sgg6iogtmuqei) '@deepseek-ai/schemastery': 3.18.1 fflate: 0.8.3 zod: 4.4.3 @@ -3225,22 +3577,22 @@ snapshots: '@deepseek-ai/cordis': 4.0.1(@deepseek-ai/cordis-plugin-include@1.0.6)(@deepseek-ai/cordis-plugin-loader@1.0.2) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-jobs@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))': + '@deepseek-ai/dsh-jobs@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))': dependencies: '@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(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-llm-retry@0.1.0-rc.8(115581c97b2438036fbd23fd81d77eff)': + '@deepseek-ai/dsh-llm-retry@0.1.0-rc.8(tmyqaedu2prdog3ai5pjncj6ri)': dependencies: '@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(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) '@deepseek-ai/dsh-timeout': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 @@ -3253,14 +3605,14 @@ snapshots: '@deepseek-ai/dsh-timeout': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-message-feedback@0.1.0-rc.8(fa979bf26319855e9b452d904429d004)': + '@deepseek-ai/dsh-message-feedback@0.1.0-rc.8(bezyjlz3tp3sbbg2tfte3wjx7y)': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-storage-domain': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-storage@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 @@ -3281,69 +3633,69 @@ snapshots: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-session-persistence@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))': + '@deepseek-ai/dsh-session-persistence@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) '@deepseek-ai/dsh-timeout': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session-projection-cache@0.1.0-rc.8(80a7956f091cdf0c220b226dd100fe03)': + '@deepseek-ai/dsh-session-projection-cache@0.1.0-rc.8(aecd6ik5xb75vio2al2lw256w4)': dependencies: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) '@deepseek-ai/dsh-storage-domain': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-storage@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/schemastery': 3.18.1 zod: 4.4.3 - '@deepseek-ai/dsh-session-projection@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))': + '@deepseek-ai/dsh-session-projection@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))': dependencies: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) zod: 4.4.3 - '@deepseek-ai/dsh-session-query@0.1.0-rc.8(e87dfefb8b6f6903ab3a7d4d893e4616)': + '@deepseek-ai/dsh-session-query@0.1.0-rc.8(o7pujk3q5o2rri5hwyefkmd7xy)': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-session-title': 0.1.0-rc.8(91b31584ff9779c6cd69a9db13c5ad7e) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session-title': 0.1.0-rc.8(jzxfrqgu7wb3xsfjx5ea6eoowi) optionalDependencies: - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session-reference@0.1.0-rc.8(cf2186381d6c9247540aad69c3158862)': + '@deepseek-ai/dsh-session-reference@0.1.0-rc.8(hng7uvyvmivmpc2kgslwtdqzsu)': dependencies: '@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(92f269661ea5e195fab72177f1a12db7) - '@deepseek-ai/dsh-compaction': 0.1.0-rc.8(cd54d1dbdb1933253bd594179027c07c) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-compaction': 0.1.0-rc.8(zcqikh7jjb4nrr3c673hqfu2xu) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-output-retention': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-session-query': 0.1.0-rc.8(e87dfefb8b6f6903ab3a7d4d893e4616) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session-query': 0.1.0-rc.8(o7pujk3q5o2rri5hwyefkmd7xy) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 zod: 4.4.3 - '@deepseek-ai/dsh-session-title@0.1.0-rc.8(91b31584ff9779c6cd69a9db13c5ad7e)': + '@deepseek-ai/dsh-session-title@0.1.0-rc.8(jzxfrqgu7wb3xsfjx5ea6eoowi)': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) '@deepseek-ai/schemastery': 3.18.1 zod: 4.4.3 - '@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)': + '@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) @@ -3380,24 +3732,24 @@ snapshots: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-subagent@0.1.0-rc.8(42428574dae299167d0987b281167061)': + '@deepseek-ai/dsh-subagent@0.1.0-rc.8(coi676g3ltfbkxbpzz2n5dgy7a)': dependencies: '@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.8(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-tools': 0.1.0-rc.8(5bda1be499cac5a517847cfe82ab203b) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-tools': 0.1.0-rc.8(53xifwsgcqiqivitsot3r6a3te) zod: 4.4.3 optionalDependencies: - '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(c61da10b37997a0dffc1aedc219daaf2) - '@deepseek-ai/dsh-jobs': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) - '@deepseek-ai/dsh-session-projection-cache': 0.1.0-rc.8(80a7956f091cdf0c220b226dd100fe03) - '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(fb0355bbecd49d575c30b602eef27c30) + '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(5y7oeayczjdoxnag4x7zbpuyki) + '@deepseek-ai/dsh-jobs': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) + '@deepseek-ai/dsh-session-projection-cache': 0.1.0-rc.8(aecd6ik5xb75vio2al2lw256w4) + '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(aojav6lden5fwwpraqe7zs3sze) '@deepseek-ai/dsh-system-prompt@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))': dependencies: @@ -3412,30 +3764,30 @@ snapshots: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-tools@0.1.0-rc.8(5bda1be499cac5a517847cfe82ab203b)': + '@deepseek-ai/dsh-tools@0.1.0-rc.8(53xifwsgcqiqivitsot3r6a3te)': dependencies: '@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(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-code-runtime': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(fb0355bbecd49d575c30b602eef27c30) + '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(aojav6lden5fwwpraqe7zs3sze) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-tools@0.1.0-rc.8(68a9dffdb9e9c8636f3b708c6fd1edd1)': + '@deepseek-ai/dsh-tools@0.1.0-rc.8(cjphcmfsxr6vrfny2gkyrgolze)': dependencies: '@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.8(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-code-runtime': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(fb0355bbecd49d575c30b602eef27c30) + '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(aojav6lden5fwwpraqe7zs3sze) '@deepseek-ai/schemastery': 3.18.1 '@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))': @@ -3450,44 +3802,44 @@ snapshots: '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) zod: 4.4.3 - '@deepseek-ai/dsh-user-approval@0.1.0-rc.8(380a43f4d6510c4a5dfadf54dc7f17a7)': + '@deepseek-ai/dsh-user-approval@0.1.0-rc.8(aojav6lden5fwwpraqe7zs3sze)': dependencies: '@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.8(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-user-approval@0.1.0-rc.8(fb0355bbecd49d575c30b602eef27c30)': + '@deepseek-ai/dsh-user-approval@0.1.0-rc.8(wiirn2jei2nkjmsboxw35on4mm)': dependencies: '@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(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-user-questions@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))': + '@deepseek-ai/dsh-user-questions@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))': dependencies: '@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.8(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-workspace@0.1.0-rc.8(b22e0d48f5e81af272cd56aac64d0d48)': + '@deepseek-ai/dsh-workspace@0.1.0-rc.8(n3vdmq7iw27i2sgg6iogtmuqei)': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-storage': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-storage-domain': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-storage@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) zod: 4.4.3 @@ -3575,8 +3927,34 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true + '@hono/node-server@2.1.5(hono@4.13.13)': + dependencies: + hono: 4.13.13 + '@jridgewell/sourcemap-codec@1.5.5': {} + '@modelcontextprotocol/sdk@1.32.1(zod@3.25.76)': + dependencies: + '@hono/node-server': 2.1.5(hono@4.13.13) + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + content-type: 1.0.5 + cors: 2.8.6 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + eventsource-parser: 3.1.1 + express: 5.3.0 + express-rate-limit: 8.7.1(express@5.3.0) + hono: 4.13.13 + jose: 6.2.12 + json-schema-typed: 8.0.2 + pkce-challenge: 5.0.1 + raw-body: 3.0.2 + zod: 3.25.76 + zod-to-json-schema: 3.25.2(zod@3.25.76) + transitivePeerDependencies: + - supports-color + '@openagentpack/sdk@0.7.1': dependencies: jszip: 3.10.1 @@ -3858,6 +4236,42 @@ snapshots: '@typescript/native-preview-win32-arm64': 7.0.0-dev.20260328.1 '@typescript/native-preview-win32-x64': 7.0.0-dev.20260328.1 + '@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))(vitest@4.1.11)': + dependencies: + '@testing-library/dom': 10.4.1 + '@testing-library/user-event': 14.6.6(@testing-library/dom@10.4.1) + '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))(vitest@4.1.11) + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))(vitest@4.1.11)': + dependencies: + '@testing-library/dom': 10.4.1 + '@testing-library/user-event': 14.6.6(@testing-library/dom@10.4.1) + '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))(vitest@4.1.11) + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11)': + dependencies: + '@testing-library/dom': 10.4.1 + '@testing-library/user-event': 14.6.6(@testing-library/dom@10.4.1) + '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + '@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11)': dependencies: '@testing-library/dom': 10.4.1 @@ -3870,6 +4284,57 @@ snapshots: - utf-8-validate - vite + '@vitest/browser@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))(vitest@4.1.11)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) + '@vitest/utils': 4.1.11 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.1 + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) + ws: 8.21.3 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/browser@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))(vitest@4.1.11)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) + '@vitest/utils': 4.1.11 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.1 + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) + ws: 8.21.3 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/browser@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + '@vitest/utils': 4.1.11 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.1 + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + ws: 8.21.3 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + '@vitest/browser@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11)': dependencies: '@blazediff/core': 1.9.1 @@ -3896,6 +4361,30 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.1 + '@vitest/mocker@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))': + dependencies: + '@vitest/spy': 4.1.11 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)' + + '@vitest/mocker@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))': + dependencies: + '@vitest/spy': 4.1.11 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)' + + '@vitest/mocker@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))': + dependencies: + '@vitest/spy': 4.1.11 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' + '@vitest/mocker@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.11 @@ -4200,6 +4689,15 @@ snapshots: '@yuku-toolchain/types@0.9.5': {} + accepts@2.0.0: + dependencies: + mime-types: 3.0.2 + negotiator: 1.1.0 + + ajv-formats@3.0.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 @@ -4260,6 +4758,20 @@ snapshots: dependencies: bare-path: 3.1.1 + body-parser@2.3.0: + dependencies: + bytes: 3.1.2 + content-type: 2.1.0 + debug: 4.4.3 + http-errors: 2.0.1 + iconv-lite: 0.7.3 + on-finished: 2.4.1 + qs: 6.16.1 + raw-body: 3.0.2 + type-is: 2.1.0 + transitivePeerDependencies: + - supports-color + boxen@8.0.1: dependencies: ansi-align: 3.0.1 @@ -4271,8 +4783,20 @@ snapshots: widest-line: 5.0.0 wrap-ansi: 9.0.2 + bytes@3.1.2: {} + cac@7.0.0: {} + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + camelcase@8.0.0: {} chai@6.2.2: {} @@ -4281,14 +4805,41 @@ snapshots: cli-boxes@3.0.0: {} + content-disposition@2.0.1: {} + + content-type@1.0.5: {} + + content-type@2.1.0: {} + convert-source-map@2.0.0: {} + cookie-signature@1.2.2: {} + + cookie@0.7.2: {} + core-util-is@1.0.3: {} + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + csstype@3.2.3: {} + debug@4.4.3: + dependencies: + ms: 2.1.3 + defu@6.1.7: {} + depd@2.0.0: {} + dequal@2.0.3: {} detect-libc@2.1.2: {} @@ -4297,14 +4848,32 @@ snapshots: dts-resolver@3.0.0: {} + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + ee-first@1.1.1: {} + emoji-regex@10.6.0: {} emoji-regex@8.0.0: {} empathic@2.0.1: {} + encodeurl@2.0.0: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + es-module-lexer@2.3.2: {} + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + esbuild@0.28.1: optionalDependencies: '@esbuild/aix-ppc64': 0.28.1 @@ -4334,18 +4903,69 @@ snapshots: '@esbuild/win32-ia32': 0.28.1 '@esbuild/win32-x64': 0.28.1 + escape-html@1.0.3: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 + etag@1.8.1: {} + events-universal@1.0.1: dependencies: bare-events: 2.9.1 transitivePeerDependencies: - bare-abort-controller + eventsource-parser@3.1.1: {} + + eventsource@3.0.7: + dependencies: + eventsource-parser: 3.1.1 + expect-type@1.4.0: {} + express-rate-limit@8.7.1(express@5.3.0): + dependencies: + debug: 4.4.3 + express: 5.3.0 + ip-address: 10.7.4 + transitivePeerDependencies: + - supports-color + + express@5.3.0: + dependencies: + accepts: 2.0.0 + body-parser: 2.3.0 + content-disposition: 2.0.1 + content-type: 2.1.0 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.3 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.1 + fresh: 2.0.0 + http-errors: 2.0.1 + merge-descriptors: 2.0.0 + mime-types: 3.0.2 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.8 + qs: 6.16.1 + range-parser: 1.3.0 + router: 2.2.0 + send: 1.2.1 + serve-static: 2.2.1 + statuses: 2.0.2 + type-is: 2.1.0 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + fast-deep-equal@3.1.3: {} fast-fifo@1.3.2: {} @@ -4358,17 +4978,74 @@ snapshots: fflate@0.8.3: {} + finalhandler@2.1.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + forwarded@0.2.0: {} + + fresh@2.0.0: {} + fsevents@2.3.3: optional: true + function-bind@1.1.2: {} + get-east-asian-width@1.6.0: {} + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + get-tsconfig@5.0.0-beta.5: dependencies: resolve-pkg-maps: 1.0.0 + gopd@1.2.0: {} + + has-symbols@1.1.0: {} + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + hono@4.13.13: {} + hookable@6.1.1: {} + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + iconv-lite@0.7.3: + dependencies: + safer-buffer: 2.1.2 + immediate@3.0.6: {} immer@10.2.0: {} @@ -4377,13 +5054,23 @@ snapshots: inherits@2.0.4: {} + ip-address@10.7.4: {} + + ipaddr.js@1.9.1: {} + is-fullwidth-code-point@3.0.0: {} + is-promise@4.0.0: {} + isarray@1.0.0: {} + isexe@2.0.0: {} + jiti@2.6.1: optional: true + jose@6.2.12: {} + js-tokens@4.0.0: {} js-yaml@4.3.1: @@ -4392,6 +5079,8 @@ snapshots: json-schema-traverse@1.0.0: {} + json-schema-typed@8.0.2: {} + jszip@3.10.1: dependencies: lie: 3.3.0 @@ -4511,12 +5200,42 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + math-intrinsics@1.1.0: {} + + media-typer@1.1.1: {} + + merge-descriptors@2.0.0: {} + + mime-db@1.54.0: {} + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + mrmime@2.0.1: {} + ms@2.1.3: {} + nanoid@3.3.11: {} + negotiator@1.1.0: + dependencies: + content-type: 2.1.0 + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + obug@2.1.4: {} + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + oxfmt@0.68.0(vite-plus@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)): dependencies: tinypool: 2.1.2 @@ -4724,6 +5443,12 @@ snapshots: pako@1.0.11: {} + parseurl@1.3.3: {} + + path-key@3.1.1: {} + + path-to-regexp@8.4.2: {} + pathe@2.0.3: {} pend@1.2.0: {} @@ -4732,6 +5457,8 @@ snapshots: picomatch@4.0.5: {} + pkce-challenge@5.0.1: {} + pngjs@7.0.0: {} postcss@8.5.12: @@ -4748,8 +5475,27 @@ snapshots: process-nextick-args@2.0.1: {} + proxy-addr@2.0.8: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + qs@6.16.1: + dependencies: + es-define-property: 1.0.1 + side-channel: 1.1.1 + quansync@1.0.0: {} + range-parser@1.3.0: {} + + raw-body@3.0.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.7.3 + unpipe: 1.0.0 + react-is@17.0.2: {} react@18.3.1: @@ -4805,10 +5551,83 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.2.5 '@rolldown/binding-win32-x64-msvc': 1.2.5 + router@2.2.0: + dependencies: + debug: 4.4.3 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.4.2 + transitivePeerDependencies: + - supports-color + safe-buffer@5.1.2: {} + safer-buffer@2.1.2: {} + + send@1.2.1: + dependencies: + debug: 4.4.3 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.1 + mime-types: 3.0.2 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.3.0 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serve-static@2.2.1: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.1 + transitivePeerDependencies: + - supports-color + setimmediate@1.0.5: {} + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} sirv@3.0.2: @@ -4825,6 +5644,8 @@ snapshots: stackback@0.0.2: {} + statuses@2.0.2: {} + std-env@4.1.0: {} streamx@2.28.0: @@ -4897,6 +5718,8 @@ snapshots: tinyrainbow@3.1.1: {} + toidentifier@1.0.1: {} + totalist@3.0.1: {} tree-kill@1.2.2: {} @@ -4935,6 +5758,12 @@ snapshots: type-fest@4.41.0: {} + type-is@2.1.0: + dependencies: + content-type: 2.1.0 + media-typer: 1.1.1 + mime-types: 3.0.2 + typescript@5.9.3: {} typescript@6.0.3: {} @@ -4950,22 +5779,26 @@ snapshots: undici@6.27.0: {} + unpipe@1.0.0: {} + use-sync-external-store@1.2.0(react@18.3.1): dependencies: react: 18.3.1 util-deprecate@1.0.2: {} + vary@1.1.2: {} + verkit@0.3.2: {} vite-plus@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3): dependencies: '@oxc-project/types': 0.150.0 '@oxlint/plugins': 1.79.0 - '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) - '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) + '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))(vitest@4.1.11) + '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))(vitest@4.1.11) '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) '@vitest/pretty-format': 4.1.11 '@vitest/runner': 4.1.11 '@vitest/snapshot': 4.1.11 @@ -4975,7 +5808,7 @@ snapshots: oxlint: 1.83.0(oxlint-tsgolint@7.0.2001)(vite-plus@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) oxlint-tsgolint: 7.0.2001 vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)' - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11))(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) optionalDependencies: '@voidzero-dev/vite-plus-darwin-arm64': 0.3.3 '@voidzero-dev/vite-plus-darwin-x64': 0.3.3 @@ -5019,10 +5852,10 @@ snapshots: dependencies: '@oxc-project/types': 0.150.0 '@oxlint/plugins': 1.79.0 - '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) - '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) + '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))(vitest@4.1.11) + '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))(vitest@4.1.11) '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) '@vitest/pretty-format': 4.1.11 '@vitest/runner': 4.1.11 '@vitest/snapshot': 4.1.11 @@ -5032,7 +5865,7 @@ snapshots: oxlint: 1.83.0(oxlint-tsgolint@7.0.2001)(vite-plus@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) oxlint-tsgolint: 7.0.2001 vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)' - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11))(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) optionalDependencies: '@voidzero-dev/vite-plus-darwin-arm64': 0.3.3 '@voidzero-dev/vite-plus-darwin-x64': 0.3.3 @@ -5076,10 +5909,10 @@ snapshots: dependencies: '@oxc-project/types': 0.150.0 '@oxlint/plugins': 1.79.0 - '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) - '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) + '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) + '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.11 '@vitest/runner': 4.1.11 '@vitest/snapshot': 4.1.11 @@ -5089,7 +5922,7 @@ snapshots: oxlint: 1.83.0(oxlint-tsgolint@7.0.2001)(vite-plus@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) oxlint-tsgolint: 7.0.2001 vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11))(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) optionalDependencies: '@voidzero-dev/vite-plus-darwin-arm64': 0.3.3 '@voidzero-dev/vite-plus-darwin-x64': 0.3.3 @@ -5186,10 +6019,10 @@ snapshots: - utf-8-validate - yaml - vitest@4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11))(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)): + vitest@4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) '@vitest/pretty-format': 4.1.11 '@vitest/runner': 4.1.11 '@vitest/snapshot': 4.1.11 @@ -5206,11 +6039,67 @@ snapshots: tinyexec: 1.3.0 tinyglobby: 0.2.17 tinyrainbow: 3.1.1 - vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' + vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)' why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 24.12.2 - '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) + '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))(vitest@4.1.11) + transitivePeerDependencies: + - msw + + vitest@4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)): + dependencies: + '@vitest/expect': 4.1.11 + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.11 + '@vitest/runner': 4.1.11 + '@vitest/snapshot': 4.1.11 + '@vitest/spy': 4.1.11 + '@vitest/utils': 4.1.11 + es-module-lexer: 2.3.2 + expect-type: 1.4.0 + magic-string: 0.30.21 + obug: 2.1.4 + pathe: 2.0.3 + picomatch: 4.0.5 + std-env: 4.1.0 + tinybench: 2.9.0 + tinyexec: 1.3.0 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.1 + vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)' + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.12.2 + '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))(vitest@4.1.11) + transitivePeerDependencies: + - msw + + vitest@4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)): + dependencies: + '@vitest/expect': 4.1.11 + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.11 + '@vitest/runner': 4.1.11 + '@vitest/snapshot': 4.1.11 + '@vitest/spy': 4.1.11 + '@vitest/utils': 4.1.11 + es-module-lexer: 2.3.2 + expect-type: 1.4.0 + magic-string: 0.30.21 + obug: 2.1.4 + pathe: 2.0.3 + picomatch: 4.0.5 + std-env: 4.1.0 + tinybench: 2.9.0 + tinyexec: 1.3.0 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.1 + vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.12.2 + '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) transitivePeerDependencies: - msw @@ -5242,6 +6131,10 @@ snapshots: transitivePeerDependencies: - msw + which@2.0.2: + dependencies: + isexe: 2.0.0 + why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 @@ -5257,6 +6150,8 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.2.0 + wrappy@1.0.2: {} + ws@8.21.3: {} yaml@2.8.3: {} @@ -5345,6 +6240,12 @@ snapshots: '@yuku-parser/binding-win32-arm64': 0.9.5 '@yuku-parser/binding-win32-x64': 0.9.5 + zod-to-json-schema@3.25.2(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod@3.25.76: {} + zod@4.4.3: {} zustand@4.4.7(@types/react@18.3.31)(immer@10.2.0)(react@18.3.1): diff --git a/skills/bailian-gen/reference/image.md b/skills/bailian-gen/reference/image.md index a35c7d298..07c1c6c6d 100644 --- a/skills/bailian-gen/reference/image.md +++ b/skills/bailian-gen/reference/image.md @@ -45,6 +45,10 @@ Index: [index.md](index.md) | `--api-key ` | string | no | API key | | `--base-url ` | string | no | API base URL | +#### Notes + +- Model "auto" (via --model auto or a config default model of "auto") routes to the official Bailian MCP with a reduced parameter set; MCP-incompatible flags fail fast with a usage error instead of falling back to REST. Auto edit accepts a single --image only. + #### Examples ```bash @@ -108,6 +112,10 @@ bl image edit --image ./photo.png --prompt "Replace the background with a beach" | `--api-key ` | string | no | API key | | `--base-url ` | string | no | API base URL | +#### Notes + +- Model "auto" (via --model auto or a config default model of "auto") routes to the official Bailian MCP with a reduced parameter set; MCP-incompatible flags fail fast with a usage error instead of falling back to REST. + #### Examples ```bash diff --git a/skills/bailian-gen/reference/speech.md b/skills/bailian-gen/reference/speech.md index 7bbc5a329..2845c37b1 100644 --- a/skills/bailian-gen/reference/speech.md +++ b/skills/bailian-gen/reference/speech.md @@ -47,6 +47,10 @@ Index: [index.md](index.md) | `--api-key ` | string | no | API key | | `--base-url ` | string | no | API base URL | +#### Notes + +- Model "auto" (via --model auto or a config default model of "auto") routes to the official Bailian MCP with a reduced parameter set and simplified text output; MCP-incompatible flags fail fast with a usage error instead of falling back to REST. + #### Examples ```bash @@ -122,6 +126,10 @@ bl speech recognize --url https://example.com/audio.mp3 --model qwen-audio-3.0-a | `--api-key ` | string | no | API key | | `--base-url ` | string | no | API base URL | +#### Notes + +- Model "auto" (via --model auto or a config default model of "auto") routes to the official Bailian MCP with a reduced parameter set; MCP-incompatible flags fail fast with a usage error instead of falling back to REST. + #### Examples ```bash diff --git a/skills/bailian-gen/reference/video.md b/skills/bailian-gen/reference/video.md index f665c23d8..6ea7e4230 100644 --- a/skills/bailian-gen/reference/video.md +++ b/skills/bailian-gen/reference/video.md @@ -131,6 +131,7 @@ bl video edit --video https://example.com/input.mp4 --prompt "Put clothes on the #### Notes +- Model "auto" (via --model auto or a config default model of "auto") routes to the official Bailian MCP with a reduced parameter set; MCP-incompatible flags fail fast with a usage error instead of falling back to REST. - Prime mode requires an explicit model. - Prime endpoint: configured --base-url, DASHSCOPE_BASE_URL, or profile base_url takes precedence; otherwise workspace is resolved from --workspace-id, BAILIAN_WORKSPACE_ID, then config workspace_id. From bbb37227abc01b712ff1a52d42b53420ee4a8229 Mon Sep 17 00:00:00 2001 From: wangmingxiang Date: Wed, 21 Oct 2026 20:19:06 +0800 Subject: [PATCH 2/6] =?UTF-8?q?chore(deps):=20=E6=9B=B4=E6=96=B0=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E7=89=88=E6=9C=AC=E5=92=8C=E6=B7=BB=E5=8A=A0=E8=A6=86?= =?UTF-8?q?=E7=9B=96=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新多个 @deepseek-ai 相关包的版本 Hash - 添加 vite, vitest 及 ws 的版本覆盖配置 - 标记 yuku-codegen 系列及 yuku-parser 系列的绑定包为弃用 - 更新依赖锁定文件中的版本校验信息 --- .../tests/e2e/aigc-auto-mcp.e2e.test.ts | 105 +++- pnpm-lock.yaml | 586 +++++++----------- 2 files changed, 340 insertions(+), 351 deletions(-) diff --git a/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts b/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts index 2e3ca936a..62bba369e 100644 --- a/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts +++ b/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts @@ -1,7 +1,14 @@ import { writeFileSync } from "node:fs"; import { join } from "node:path"; import { describe, expect, test } from "vite-plus/test"; -import { makeE2eOutputDir, parseStdoutJson, runCommandE2e } from "./helpers.ts"; +import { + isBailianE2EMediaEnabled, + isBailianE2EVideoEnabled, + isDashScopeE2EReady, + makeE2eOutputDir, + parseStdoutJson, + runCommandE2e, +} from "./helpers.ts"; import type { E2eRouteExports } from "./topic-routes.ts"; /** @@ -321,3 +328,99 @@ describe("e2e: aigc auto → mcp", () => { expect(stderr, label).toMatch(pattern); }); }); + +// ---- 真实 MCP 调用(live gated)---- +// +// 以上全部是离线 dry-run。以下三条真实打百炼 AIGC MCP,验证 auto 确实能经 MCP +// 出结果并落地文件。默认 skip:需 BAILIAN_E2E=1 + DASHSCOPE_API_KEY;图像 / 语音 +// 另受媒体开关控制(默认开),视频耗时长、另需 BAILIAN_E2E_VIDEO=1。 +// +// image edit / speech recognize 的真实链路需要合法的图片 / 音频二进制 fixture +// (静音音频会被下游判为“无语音”而 isError),其请求契约已由上面的 dry-run 预览 +// 与 data URI 脱敏覆盖,故 live 只覆盖纯 prompt/text 输入的这三条命令。 + +describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())( + "e2e: aigc auto → mcp(DashScope 媒体,真实调用)", + () => { + test("【auto】image generate 真实经 MCP(bailian_image_gen) 出图并落地", async () => { + const outDir = makeE2eOutputDir("aigc-auto-live-image-generate"); + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "image", + "generate", + "--model", + "auto", + "--prompt", + "一只简笔画小猫,白底", + "--out-dir", + outDir, + "--out-prefix", + "e2e-auto-gen", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson<{ urls?: string[]; saved?: string[]; total?: number }>(stdout); + expect(data.saved?.length ?? 0).toBeGreaterThan(0); + expect(data.saved?.[0]).toContain("e2e-auto-gen"); + expect(data.urls?.length ?? 0).toBeGreaterThan(0); + }, 300_000); + + test("【auto】speech synthesize 真实经 MCP(bailian_tts) 合成并落地", async () => { + const outDir = makeE2eOutputDir("aigc-auto-live-speech-synthesize"); + const outWav = join(outDir, "e2e-auto-tts.wav"); + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "speech", + "synthesize", + "--model", + "auto", + "--text", + "端到端 auto 语音测试", + // voice 原样透传给 MCP,需为服务端音色枚举内的值(与 REST live 用例一致)。 + "--voice", + "longxiaochun_v3", + "--out", + outWav, + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson<{ saved?: string; audio_url?: string; voice?: string }>(stdout); + expect(data.saved).toBe(outWav); + expect(data.audio_url?.length ?? 0).toBeGreaterThan(0); + expect(data.voice).toBe("longxiaochun_v3"); + }, 180_000); + }, +); + +describe.skipIf(!isBailianE2EVideoEnabled() || !isDashScopeE2EReady())( + "e2e: aigc auto → mcp(DashScope 视频,真实调用)", + () => { + test("【auto】video generate(t2v) 真实经 MCP 提交→轮询→下载", async () => { + const outDir = makeE2eOutputDir("aigc-auto-live-video-generate"); + const outMp4 = join(outDir, "e2e-auto-t2v.mp4"); + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "video", + "generate", + "--model", + "auto", + "--prompt", + "海浪拍打礁石,慢镜头", + "--download", + outMp4, + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson<{ + task_id?: string; + video_url?: string; + status?: string; + saved?: string; + }>(stdout); + expect(data.status).toBe("SUCCEEDED"); + expect(data.saved).toBe(outMp4); + expect(data.video_url?.length ?? 0).toBeGreaterThan(0); + expect(data.task_id?.length ?? 0).toBeGreaterThan(0); + }, 600_000); + }, +); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6305f688a..98c0825d2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,6 +49,11 @@ catalogs: specifier: ^3.4.0 version: 3.4.0 +overrides: + vite: npm:@voidzero-dev/vite-plus-core@0.3.3 + vitest: 4.1.11 + ws@>=8.0.0 <8.21.0: 8.21.3 + importers: .: @@ -71,22 +76,22 @@ importers: version: 4.0.1(@deepseek-ai/cordis-plugin-include@1.0.6)(@deepseek-ai/cordis-plugin-loader@1.0.2) '@deepseek-ai/dsh-agent': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) + version: 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-api-remotes': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou) + version: 0.1.0-rc.8(3efff7030edd34682350922988afd2c1) '@deepseek-ai/dsh-client-connection': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(uegbxiinkg3b3af5xxhuothm4y) + version: 0.1.0-rc.8(47e886c317e93578e9d1303a9c4dd9fb) '@deepseek-ai/dsh-client-locale': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(s5gtd5obeihyoqucph6oeuiqfe) + version: 0.1.0-rc.8(86e16fe7bdb0cdc3694c80972d09e7f7) '@deepseek-ai/dsh-client-runtime': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4) + version: 0.1.0-rc.8(d60c775270b822deee6b25449def3bb9) '@deepseek-ai/dsh-client-ui-settings': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou))(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1)) + version: 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(3efff7030edd34682350922988afd2c1))(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(d60c775270b822deee6b25449def3bb9))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1)) '@deepseek-ai/dsh-client-ui-slots': specifier: ^0.1.0-rc.6 version: 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) @@ -98,7 +103,7 @@ importers: version: 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-session': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + version: 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) '@deepseek-ai/dsh-settings': specifier: ^0.1.0-rc.6 version: 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) @@ -107,7 +112,7 @@ importers: version: 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-tools': specifier: ^0.1.0-rc.6 - version: 0.1.0-rc.8(53xifwsgcqiqivitsot3r6a3te) + version: 0.1.0-rc.8(5bda1be499cac5a517847cfe82ab203b) '@deepseek-ai/schemastery': specifier: ^3.18.1 version: 3.18.1 @@ -1758,265 +1763,313 @@ packages: resolution: {integrity: sha512-C/0zV5IhgVdYhGJTwrY0v8dknxlhiKwtVJkMUaexu9/QvRmzlV4vfU3hZlUSgqc2BxQHntL1mCVbDq8j0FRFDw==} cpu: [arm64] os: [android] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-android-arm64@0.9.5': resolution: {integrity: sha512-jrOY5WM+AaAqkv51fHP1x28ifto4WgcZVzodLUyMU1jMWn5Sq+VciRdk/n8E0Ey5w4p4cWWE+m5GfXWOYh7Kzw==} cpu: [arm64] os: [android] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-darwin-arm64@0.8.7': resolution: {integrity: sha512-/u+REDMI4a0/lsJXTM4c53/w31OGZLOReZIyg62uhgLs0kc8NHsj/nOcxTdlQjq5gi0zhdkccD9LaLTXcdzPvw==} cpu: [arm64] os: [darwin] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-darwin-arm64@0.9.5': resolution: {integrity: sha512-4O4lkCQIzPZGjiNB1GORSI6hBECbiiSBS/APZXPvNKYH+nhY4uuqv03LNXA+SET3hoBjvr95P5rIhY8KQaQUBA==} cpu: [arm64] os: [darwin] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-darwin-x64@0.8.7': resolution: {integrity: sha512-sMMzFOwCo4WXR+/6zIBThOocSC50iIIZZdfiIDbaLvj0Ax/rWt/iavyfEAqajyvzydLyCqR/ZItdLWSRlu1umw==} cpu: [x64] os: [darwin] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-darwin-x64@0.9.5': resolution: {integrity: sha512-9EvoUO0SEhD6/d8VHdWuPerepPMSR1y84+UEgz8Un1Ope14Oe7xMvePpEQLTLovoIFZ8Zg3iZ8z8E11pZMqC3g==} cpu: [x64] os: [darwin] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-freebsd-x64@0.8.7': resolution: {integrity: sha512-MpdpKXix9P+Y1rKgjvcNeNtGjXeL1CmttNhYINrWls8kRpm4xM/oBGTmn6w7to8lAlwj5jm8q03dQPl5mRv4Qw==} cpu: [x64] os: [freebsd] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-freebsd-x64@0.9.5': resolution: {integrity: sha512-HqT78WwgHTmp8lwujoUa9CrIortX4DdpuiVC18ZPSGvuuJf4ylpIEI6QrQEM78Zwz3muhAWAOXZ5irdiYY+AyA==} cpu: [x64] os: [freebsd] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-linux-arm-gnu@0.8.7': resolution: {integrity: sha512-rr1srFLlPAmC1vtxfc9C1YLDe3iH09YjfSeeIidBqKhzx1MATjOAq4mjlRUOnhr/L27MotWIYOFKwVsd5JZFOg==} cpu: [arm] os: [linux] libc: [glibc] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-linux-arm-gnu@0.9.5': resolution: {integrity: sha512-QJXwIW6Ms3QIawbcBIedmrmXnfdpuAOjZJ/eAABq5XTzWvSxZ7lutu9W5yIHahlaTaFnBo7ikrVMD1szLTpPUw==} cpu: [arm] os: [linux] libc: [glibc] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-linux-arm-musl@0.8.7': resolution: {integrity: sha512-eAufXh8qBRpiSO6ueaMDL+yyoXIGLhpUce72YbcACtZU2qhExwBIJyEtQf5kH2Ki0X2aqkSjSfog4OPtKXan3Q==} cpu: [arm] os: [linux] libc: [musl] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-linux-arm-musl@0.9.5': resolution: {integrity: sha512-eHbFy3IHGb+IYarrYwAo0yWSEQV3eAmEn6VrsKA6I1Wy1YPJxWqSJlV69JhqsHtJuJlljUIF3ex0y46yaKIu9w==} cpu: [arm] os: [linux] libc: [musl] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-linux-arm64-gnu@0.8.7': resolution: {integrity: sha512-gw4w6wPoHObBrdIC4duVWLmJOvpdE25j5D7yrM5mACNlK4klRz/lv8hK+ssQk9EJHBgZjSaqZIJVFgqNYbfv7A==} cpu: [arm64] os: [linux] libc: [glibc] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-linux-arm64-gnu@0.9.5': resolution: {integrity: sha512-ByoJMbySTaDhjAXSu8q6Lh7HKg3YoesXpcT72aYk0Aiw4PCznmY4ybpLTq0RCvp0RIPhFm/6yECFiGBwyCC1nw==} cpu: [arm64] os: [linux] libc: [glibc] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-linux-arm64-musl@0.8.7': resolution: {integrity: sha512-L68N6Y4XkqcIaKo3Ra88JEvBEH4AHff44A4INcrxeVWZ8CZtu2tCpfVxe3hR8qQQMcvBSQlDn24KpkCKEhVvfA==} cpu: [arm64] os: [linux] libc: [musl] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-linux-arm64-musl@0.9.5': resolution: {integrity: sha512-gD9vfXIoBw1toSxhO9rgmSu/FEfy3PMznJAxVjIuH8DrWEiDKXmJO0pJKfj1Ltbe/TmtWVZR+TjISqeSIGQzMg==} cpu: [arm64] os: [linux] libc: [musl] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-linux-x64-gnu@0.8.7': resolution: {integrity: sha512-dzyAbltJmf3Cqlb8HcFuYIf5Yn0fl1vTr3XJ9HiVNNvOlhqPSArOqtw9vI1p6/VTXTjrMLXlU+s+/kNHiIy/Cw==} cpu: [x64] os: [linux] libc: [glibc] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-linux-x64-gnu@0.9.5': resolution: {integrity: sha512-BARvdnvqMGjOr5Iel2JH+9H5vAIE0R6H0Z2fsT02xrvmI/1ZXNB8lkuX+ZGevPhZb3zJ9WeC/R8JZstrsUOK5g==} cpu: [x64] os: [linux] libc: [glibc] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-linux-x64-musl@0.8.7': resolution: {integrity: sha512-Otw4MH3404q0Bbvl+YTdW9aoUV5vXmUw8260bWvt1XlaoIX/ceSgI4ygheRDMfBPoHt6FDayQaO9OLVUZAgkFA==} cpu: [x64] os: [linux] libc: [musl] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-linux-x64-musl@0.9.5': resolution: {integrity: sha512-x8flcevS1fbb7ESrmpOY/pON4eInSaE/7Ktjqx2udOE2W33BNSZmJuwpyUgo54AoHNqrcaM7szqydyJn5fNvew==} cpu: [x64] os: [linux] libc: [musl] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-win32-arm64@0.8.7': resolution: {integrity: sha512-qo/jyrzryiBuKEsFiuWaBCBe3tRMynQ0qFWFgOEjcCMQeZfBm+wKiVEUEFXXLc7bh8YezguAWp0Mtnhq4ARNyA==} cpu: [arm64] os: [win32] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-win32-arm64@0.9.5': resolution: {integrity: sha512-KOL/rBatWqH4ZpCNoF8ZtSNdOJbAxBJLmk/VeRciepGROPTbPum1A9t67GpFgOU7qrkUWlPJdJ+KHKbvbmOt+w==} cpu: [arm64] os: [win32] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-win32-x64@0.8.7': resolution: {integrity: sha512-D5lDsVDx6m00E6bWySlWdH72Ca4TPSaphDqB6QjU6MpuNLIJqoGoatYyq2rOmBE8Zv/kunot/o58KGL03P3eiA==} cpu: [x64] os: [win32] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-codegen/binding-win32-x64@0.9.5': resolution: {integrity: sha512-FxENahEjWSan59Syh/us/Kf4wNq8qrJLFJ3R2N4Oiwtb6yNdz/rWLNTIoNSssnsp7IoWJdUP6o/Z8ppg7lXMcg==} cpu: [x64] os: [win32] + deprecated: yuku-codegen is pure JavaScript since 0.14 '@yuku-parser/binding-android-arm64@0.8.7': resolution: {integrity: sha512-eGKYiUDX7Y0V7tDTmg+JTVnXnjMqfXXsorZ+EDf5kxwchQ3Or1HS14MzI2fw+jFhHR85fCWt+mtX33Yao73hIQ==} cpu: [arm64] os: [android] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-android-arm64@0.9.5': resolution: {integrity: sha512-A2JCFCSHfnficqYEw4Iujpx7XrkMM3UfFcgJFmYpZSo9zM4nyhmdIIE0FogSduuU60lhM0/UcfuUBXIVNBMlGQ==} cpu: [arm64] os: [android] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-darwin-arm64@0.8.7': resolution: {integrity: sha512-Re0RHelKLnjEURulY2/KxW+Ngb8zuNA4BRZuMwgGQNzVumT6u4U2N2hc01oeYVNVof0i7GrXE4UCNBgbpRRnjQ==} cpu: [arm64] os: [darwin] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-darwin-arm64@0.9.5': resolution: {integrity: sha512-3PiyU+Eare4YuKaQ22N98/yAiROPY5o/NQJHraICzDvk4pgS+m+bgLKOvkGBRn33OnV95Vdv1Mn38b+MQHpULQ==} cpu: [arm64] os: [darwin] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-darwin-x64@0.8.7': resolution: {integrity: sha512-Hn8DROtQkjlA1ACbPgj4a7eP9IuVOI504oiTwpkWPbpaDWD9KdmnVYCqW+1LfenNK/g7O9NhWGpXEdaCNX7lIA==} cpu: [x64] os: [darwin] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-darwin-x64@0.9.5': resolution: {integrity: sha512-blFMAFI7AInI83XaiOF8cIeiRM46Nz9EfpZtZPRLbKxSA9aAr5v8aHYpmfN6NoyXxAv/10pwS4gsAuc1W6fy5Q==} cpu: [x64] os: [darwin] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-freebsd-x64@0.8.7': resolution: {integrity: sha512-bAP2OV8wRuzplX/jYxv9+vvqQT8JxyNphI8fLfXGL054Xs+4/J5u33cIm3y4rxY8rdoLmmdiJs2Tq7r7lrDRfA==} cpu: [x64] os: [freebsd] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-freebsd-x64@0.9.5': resolution: {integrity: sha512-TsNuL4qsZdO0tHp5GW43Y5fHeLPpPHA675wdcPNTcdq2ZO5AvsQWFFoiDg8CH4oBktfsQ9tdvKhjLnLYwKvp4g==} cpu: [x64] os: [freebsd] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-linux-arm-gnu@0.8.7': resolution: {integrity: sha512-kTYwJQQgmZeAWdDIWabiReIZMpmfLueIj1tCmjStUtFGhR1Z0qwxonKVfUC4N7h/VhGGzLZ//7O1kgt1QKqgCg==} cpu: [arm] os: [linux] libc: [glibc] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-linux-arm-gnu@0.9.5': resolution: {integrity: sha512-b0afYK5gHeV8RdmOcqAlgM8ONsye4cax4DMnIBaoJyPMd1UTGvTbpkqQcPVdhmHlcfcGVGMV1laeVovlr/dscw==} cpu: [arm] os: [linux] libc: [glibc] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-linux-arm-musl@0.8.7': resolution: {integrity: sha512-uL4jE8HPT2BLlxAXyD10LqgPuXa9eDa0BKpCdSANmzIJghq/2eZo3/gQNtaxPZMupWoxjYzSad9IXrwu7aYPXQ==} cpu: [arm] os: [linux] libc: [musl] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-linux-arm-musl@0.9.5': resolution: {integrity: sha512-fD3lKzl+r6j6n8DwiMY53qnh5DLqD8KJjCp+NbVud54Nnh3Q9Wprqss3YzyMHP3NSJk663Wlg1E1X5qOuFVFig==} cpu: [arm] os: [linux] libc: [musl] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-linux-arm64-gnu@0.8.7': resolution: {integrity: sha512-3gVN4pWSKZmXiNX7cU164dR9MPvesCHnlH6nPfpK+yQsCuYphjKKplcb4SnZBrhiqmXbgb2HR0c2TS0IZUPhgA==} cpu: [arm64] os: [linux] libc: [glibc] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-linux-arm64-gnu@0.9.5': resolution: {integrity: sha512-aRU/aCphV1MWCl/lvI6NX8LgucHQ68Fx+vz7NBb/5MEr2EuzCxiPOQqeFcMdWh+2AED/p0AvAREch0c+cSnlhA==} cpu: [arm64] os: [linux] libc: [glibc] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-linux-arm64-musl@0.8.7': resolution: {integrity: sha512-S0mwfEjoLpxzXeZw802Wa4RaELsQiPtWqG6INcy8j4GtvNFtl4LCX3eGO1XLn9pyLAISLzTRyU3zUCBUPin8lg==} cpu: [arm64] os: [linux] libc: [musl] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-linux-arm64-musl@0.9.5': resolution: {integrity: sha512-5+Guro0l8H473YXlEjVNBRLN/IbPbJdnQh1zo0OLt49xxnON+XMJRRaEyTOTfkn9QSRg0+BhEKGR4W9Gu2uZJQ==} cpu: [arm64] os: [linux] libc: [musl] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-linux-x64-gnu@0.8.7': resolution: {integrity: sha512-lnbWdPmerE5D1uH1G4IEZKnPzCrWCStRGrtgpSIe1RibAo5bZIjDbbbPYXmMHCEh4F+x/JaJpElh26a3r+BPbg==} cpu: [x64] os: [linux] libc: [glibc] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-linux-x64-gnu@0.9.5': resolution: {integrity: sha512-pwwSyV9q+GlvzSXlsMZBMlgk22L5bud714/vqZCdeUTivzeUVltQzUaf3IQXOGXdpc59JYTeuMCtbGquaAUoCA==} cpu: [x64] os: [linux] libc: [glibc] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-linux-x64-musl@0.8.7': resolution: {integrity: sha512-769uwndMvMzUvATWbAcEvyLHKA+DzhHSCl/obBUrRdYfRo26yxui6S8y3z7uJ+Naup7UKrDxrpK7OnQkxkl9KQ==} cpu: [x64] os: [linux] libc: [musl] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-linux-x64-musl@0.9.5': resolution: {integrity: sha512-z18j6JN3lBHH8vzN7gG1M8fI0nlgItSfnC9PfbmUbt97iHViKfw2iA2G9fGwRMe5LyPRZBrejIlapbygPbpdaw==} cpu: [x64] os: [linux] libc: [musl] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-win32-arm64@0.8.7': resolution: {integrity: sha512-mEB/9PlaAkisJ6KWGz0zvywXoU6+80dTlR2LwS7s/jcXXoU6fm2+sitBZXtqu3+Q4DcDgPxM45uWMCzPs0TSRw==} cpu: [arm64] os: [win32] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-win32-arm64@0.9.5': resolution: {integrity: sha512-s6Gwttb1dQvtPX6Bgkw+UPC9IO3UBDXc6Zezog8MMgvu3UfJBBB9TQqKBX/2quu0Eyh+lLSAyNlIyyecaagUPg==} cpu: [arm64] os: [win32] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-win32-x64@0.8.7': resolution: {integrity: sha512-8vNB2DP0ou61nGb8tc/qfi41gfyDXz1MHr2zqL3nR+cJ6CEbiuWV/l/a/vv151gCgiZLLAyGkQGENpozdg716w==} cpu: [x64] os: [win32] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-parser/binding-win32-x64@0.9.5': resolution: {integrity: sha512-FrERt9YWatY3bJfSUdi4YWY+6iQcyo3MzCC821BxlWM5TFZEHijnpz/bknR79VHlXY/9CvXz8ZlaAGPsTtN3nw==} cpu: [x64] os: [win32] + deprecated: yuku-parser runs on yuku-core since 0.14 '@yuku-toolchain/types@0.8.7': resolution: {integrity: sha512-2Z53dNxAJL6UvFoIrDZvYf3zlO8s4VJK4O2hhaB4mXVwwpX/7ajtss3cmfqKvamlNLWyt9FSWs4eoYdlbxpnHA==} @@ -3220,99 +3273,99 @@ snapshots: '@deepseek-ai/cosmokit@1.8.2': {} - '@deepseek-ai/dsh-agent-default-model@0.1.0-rc.8(nu3v65asnhd7nzlags6exbx7cu)': + '@deepseek-ai/dsh-agent-default-model@0.1.0-rc.8(d611ebd21e3e0813c50cdd15791bd486)': dependencies: '@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.8(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-agent-presets@0.1.0-rc.8(5y7oeayczjdoxnag4x7zbpuyki)': + '@deepseek-ai/dsh-agent-presets@0.1.0-rc.8(c61da10b37997a0dffc1aedc219daaf2)': dependencies: '@deepseek-ai/cordis': 4.0.1(@deepseek-ai/cordis-plugin-include@1.0.6)(@deepseek-ai/cordis-plugin-loader@1.0.2) '@deepseek-ai/cordis-plugin-include': 1.0.6(@deepseek-ai/cordis-plugin-loader@1.0.2)(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/cordis-plugin-loader': 1.0.2(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-agent': 0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-atomic-write': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-home-paths': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/schemastery': 3.18.1 js-yaml: 4.3.1 - '@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4)': + '@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7)': dependencies: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-agent@0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4)': + '@deepseek-ai/dsh-agent@0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7)': dependencies: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-api-gateway@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-registry@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))': dependencies: '@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-client-connection': 0.1.0-rc.8(uegbxiinkg3b3af5xxhuothm4y) + '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(47e886c317e93578e9d1303a9c4dd9fb) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-typert-registry': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(gzdtgzznil4onulwxurcvqu5r4)': + '@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(3efff7030edd34682350922988afd2c1)': dependencies: '@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.8(gq4rxlduqatz4hofhgosja2lu4) - '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(5y7oeayczjdoxnag4x7zbpuyki) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(c61da10b37997a0dffc1aedc219daaf2) '@deepseek-ai/dsh-api-gateway': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-registry@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-commands': 0.1.0-rc.8(s2pue3nldjdjibihazcgqufs5e) - '@deepseek-ai/dsh-cordis-host-runner': 0.1.0-rc.8(7qt3ujxvfyjcos5zt4s3xinfkq) + '@deepseek-ai/dsh-commands': 0.1.0-rc.8(be93aee212d5ee88b81aa983a6ddd927) + '@deepseek-ai/dsh-cordis-host-runner': 0.1.0-rc.8(40da5beb010d686c5e2151e04606e202) '@deepseek-ai/dsh-credentials': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-file-reference': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-goal': 0.1.0-rc.8(rmioigujzdamkqipym7wzjsjze) + '@deepseek-ai/dsh-file-reference': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-goal': 0.1.0-rc.8(229ab81e42fcff0fcb8cf501dceaea15) '@deepseek-ai/dsh-host-plugin-inventory': 0.1.0-rc.8(@deepseek-ai/cordis-plugin-loader@1.0.2)(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-message-feedback': 0.1.0-rc.8(bezyjlz3tp3sbbg2tfte3wjx7y) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session-reference': 0.1.0-rc.8(hng7uvyvmivmpc2kgslwtdqzsu) + '@deepseek-ai/dsh-message-feedback': 0.1.0-rc.8(fa979bf26319855e9b452d904429d004) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session-reference': 0.1.0-rc.8(cf2186381d6c9247540aad69c3158862) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-typert-registry': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou)': + '@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(f49a1a2925da94a3cb3629328aff349c)': dependencies: '@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(gq4rxlduqatz4hofhgosja2lu4) - '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(5y7oeayczjdoxnag4x7zbpuyki) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(c61da10b37997a0dffc1aedc219daaf2) '@deepseek-ai/dsh-api-gateway': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-registry@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-commands': 0.1.0-rc.8(s2pue3nldjdjibihazcgqufs5e) - '@deepseek-ai/dsh-cordis-host-runner': 0.1.0-rc.8(7qt3ujxvfyjcos5zt4s3xinfkq) + '@deepseek-ai/dsh-commands': 0.1.0-rc.8(be93aee212d5ee88b81aa983a6ddd927) + '@deepseek-ai/dsh-cordis-host-runner': 0.1.0-rc.8(40da5beb010d686c5e2151e04606e202) '@deepseek-ai/dsh-credentials': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-file-reference': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-goal': 0.1.0-rc.8(rmioigujzdamkqipym7wzjsjze) + '@deepseek-ai/dsh-file-reference': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-goal': 0.1.0-rc.8(229ab81e42fcff0fcb8cf501dceaea15) '@deepseek-ai/dsh-host-plugin-inventory': 0.1.0-rc.8(@deepseek-ai/cordis-plugin-loader@1.0.2)(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-message-feedback': 0.1.0-rc.8(bezyjlz3tp3sbbg2tfte3wjx7y) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session-reference': 0.1.0-rc.8(hng7uvyvmivmpc2kgslwtdqzsu) + '@deepseek-ai/dsh-message-feedback': 0.1.0-rc.8(fa979bf26319855e9b452d904429d004) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session-reference': 0.1.0-rc.8(cf2186381d6c9247540aad69c3158862) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-typert-registry': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) @@ -3333,50 +3386,50 @@ snapshots: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-client-connection@0.1.0-rc.8(uegbxiinkg3b3af5xxhuothm4y)': + '@deepseek-ai/dsh-client-connection@0.1.0-rc.8(47e886c317e93578e9d1303a9c4dd9fb)': dependencies: '@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-attachment': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-commands': 0.1.0-rc.8(s2pue3nldjdjibihazcgqufs5e) - '@deepseek-ai/dsh-host-apiproxy': 0.1.0-rc.8(zhkmxcibxhrifox3ckn5d23a6e) + '@deepseek-ai/dsh-commands': 0.1.0-rc.8(be93aee212d5ee88b81aa983a6ddd927) + '@deepseek-ai/dsh-host-apiproxy': 0.1.0-rc.8(07f963f74f292eaeb103f0faeee23085) '@deepseek-ai/dsh-host-webserver': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-tools': 0.1.0-rc.8(53xifwsgcqiqivitsot3r6a3te) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-tools': 0.1.0-rc.8(5bda1be499cac5a517847cfe82ab203b) '@deepseek-ai/schemastery': 3.18.1 ws: 8.21.3 transitivePeerDependencies: - bufferutil - utf-8-validate - '@deepseek-ai/dsh-client-locale@0.1.0-rc.8(s5gtd5obeihyoqucph6oeuiqfe)': + '@deepseek-ai/dsh-client-locale@0.1.0-rc.8(86e16fe7bdb0cdc3694c80972d09e7f7)': dependencies: '@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-api-remotes': 0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou) - '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(uegbxiinkg3b3af5xxhuothm4y) - '@deepseek-ai/dsh-client-runtime': 0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4) - '@deepseek-ai/dsh-client-ui-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou))(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1)) + '@deepseek-ai/dsh-api-remotes': 0.1.0-rc.8(3efff7030edd34682350922988afd2c1) + '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(47e886c317e93578e9d1303a9c4dd9fb) + '@deepseek-ai/dsh-client-runtime': 0.1.0-rc.8(d60c775270b822deee6b25449def3bb9) + '@deepseek-ai/dsh-client-ui-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(3efff7030edd34682350922988afd2c1))(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(d60c775270b822deee6b25449def3bb9))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4)': + '@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(d60c775270b822deee6b25449def3bb9)': dependencies: '@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(gq4rxlduqatz4hofhgosja2lu4) - '@deepseek-ai/dsh-api-remotes': 0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-api-remotes': 0.1.0-rc.8(3efff7030edd34682350922988afd2c1) '@deepseek-ai/dsh-attachment': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(uegbxiinkg3b3af5xxhuothm4y) - '@deepseek-ai/dsh-commands': 0.1.0-rc.8(s2pue3nldjdjibihazcgqufs5e) - '@deepseek-ai/dsh-host-apiproxy': 0.1.0-rc.8(zhkmxcibxhrifox3ckn5d23a6e) + '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(47e886c317e93578e9d1303a9c4dd9fb) + '@deepseek-ai/dsh-commands': 0.1.0-rc.8(be93aee212d5ee88b81aa983a6ddd927) + '@deepseek-ai/dsh-host-apiproxy': 0.1.0-rc.8(07f963f74f292eaeb103f0faeee23085) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-llm-retry': 0.1.0-rc.8(tmyqaedu2prdog3ai5pjncj6ri) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) - '@deepseek-ai/dsh-session-title': 0.1.0-rc.8(jzxfrqgu7wb3xsfjx5ea6eoowi) - '@deepseek-ai/dsh-tools': 0.1.0-rc.8(53xifwsgcqiqivitsot3r6a3te) + '@deepseek-ai/dsh-llm-retry': 0.1.0-rc.8(115581c97b2438036fbd23fd81d77eff) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) + '@deepseek-ai/dsh-session-title': 0.1.0-rc.8(91b31584ff9779c6cd69a9db13c5ad7e) + '@deepseek-ai/dsh-tools': 0.1.0-rc.8(5bda1be499cac5a517847cfe82ab203b) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-typert-registry': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) immer: 10.2.0 @@ -3385,12 +3438,12 @@ snapshots: - '@types/react' - react - '@deepseek-ai/dsh-client-ui-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou))(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1))': + '@deepseek-ai/dsh-client-ui-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-api-remotes@0.1.0-rc.8(3efff7030edd34682350922988afd2c1))(@deepseek-ai/dsh-client-connection@0.1.0-rc.8)(@deepseek-ai/dsh-client-runtime@0.1.0-rc.8(d60c775270b822deee6b25449def3bb9))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-settings@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1))': dependencies: '@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-api-remotes': 0.1.0-rc.8(odfv3mcoka3ewohlmu3neujgou) - '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(uegbxiinkg3b3af5xxhuothm4y) - '@deepseek-ai/dsh-client-runtime': 0.1.0-rc.8(hj6psvypnusv2y56337zuje5k4) + '@deepseek-ai/dsh-api-remotes': 0.1.0-rc.8(3efff7030edd34682350922988afd2c1) + '@deepseek-ai/dsh-client-connection': 0.1.0-rc.8(47e886c317e93578e9d1303a9c4dd9fb) + '@deepseek-ai/dsh-client-runtime': 0.1.0-rc.8(d60c775270b822deee6b25449def3bb9) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/schemastery': 3.18.1 @@ -3405,51 +3458,51 @@ snapshots: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-commands@0.1.0-rc.8(s2pue3nldjdjibihazcgqufs5e)': + '@deepseek-ai/dsh-commands@0.1.0-rc.8(72bbe6fdb3741b872b5fbe4132676802)': dependencies: '@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(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-attachment': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) zod: 4.4.3 - '@deepseek-ai/dsh-commands@0.1.0-rc.8(ypqdi7louiwrwd5bmsaggruoje)': + '@deepseek-ai/dsh-commands@0.1.0-rc.8(be93aee212d5ee88b81aa983a6ddd927)': dependencies: '@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.8(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-attachment': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) zod: 4.4.3 - '@deepseek-ai/dsh-compaction@0.1.0-rc.8(zcqikh7jjb4nrr3c673hqfu2xu)': + '@deepseek-ai/dsh-compaction@0.1.0-rc.8(cd54d1dbdb1933253bd594179027c07c)': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-commands': 0.1.0-rc.8(s2pue3nldjdjibihazcgqufs5e) + '@deepseek-ai/dsh-commands': 0.1.0-rc.8(be93aee212d5ee88b81aa983a6ddd927) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-cordis-host-runner@0.1.0-rc.8(7qt3ujxvfyjcos5zt4s3xinfkq)': + '@deepseek-ai/dsh-cordis-host-runner@0.1.0-rc.8(40da5beb010d686c5e2151e04606e202)': dependencies: '@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(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-tools': 0.1.0-rc.8(53xifwsgcqiqivitsot3r6a3te) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-tools': 0.1.0-rc.8(5bda1be499cac5a517847cfe82ab203b) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 zod: 4.4.3 @@ -3460,38 +3513,38 @@ snapshots: '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-file-reference@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))': + '@deepseek-ai/dsh-file-reference@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))': dependencies: '@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(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) zod: 4.4.3 - '@deepseek-ai/dsh-goal@0.1.0-rc.8(hjayf6yjypjiz4wxbwmzjunqfy)': + '@deepseek-ai/dsh-goal@0.1.0-rc.8(229ab81e42fcff0fcb8cf501dceaea15)': dependencies: '@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.8(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 zod: 4.4.3 - '@deepseek-ai/dsh-goal@0.1.0-rc.8(rmioigujzdamkqipym7wzjsjze)': + '@deepseek-ai/dsh-goal@0.1.0-rc.8(ee40b9fe89b358f0d6e7a82951758559)': dependencies: '@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(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 zod: 4.4.3 @@ -3501,37 +3554,37 @@ snapshots: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-host-apiproxy@0.1.0-rc.8(zhkmxcibxhrifox3ckn5d23a6e)': + '@deepseek-ai/dsh-host-apiproxy@0.1.0-rc.8(07f963f74f292eaeb103f0faeee23085)': dependencies: '@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.8(gq4rxlduqatz4hofhgosja2lu4) - '@deepseek-ai/dsh-agent-default-model': 0.1.0-rc.8(nu3v65asnhd7nzlags6exbx7cu) - '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(5y7oeayczjdoxnag4x7zbpuyki) - '@deepseek-ai/dsh-api-remotes': 0.1.0-rc.8(gzdtgzznil4onulwxurcvqu5r4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-agent-default-model': 0.1.0-rc.8(d611ebd21e3e0813c50cdd15791bd486) + '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(c61da10b37997a0dffc1aedc219daaf2) + '@deepseek-ai/dsh-api-remotes': 0.1.0-rc.8(f49a1a2925da94a3cb3629328aff349c) '@deepseek-ai/dsh-attachment': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-commands': 0.1.0-rc.8(ypqdi7louiwrwd5bmsaggruoje) - '@deepseek-ai/dsh-cordis-host-runner': 0.1.0-rc.8(7qt3ujxvfyjcos5zt4s3xinfkq) + '@deepseek-ai/dsh-commands': 0.1.0-rc.8(72bbe6fdb3741b872b5fbe4132676802) + '@deepseek-ai/dsh-cordis-host-runner': 0.1.0-rc.8(40da5beb010d686c5e2151e04606e202) '@deepseek-ai/dsh-credentials': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-goal': 0.1.0-rc.8(hjayf6yjypjiz4wxbwmzjunqfy) + '@deepseek-ai/dsh-goal': 0.1.0-rc.8(ee40b9fe89b358f0d6e7a82951758559) '@deepseek-ai/dsh-host-directory-picker': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-jobs': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) + '@deepseek-ai/dsh-jobs': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-native-command': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) - '@deepseek-ai/dsh-session-projection-cache': 0.1.0-rc.8(aecd6ik5xb75vio2al2lw256w4) - '@deepseek-ai/dsh-session-query': 0.1.0-rc.8(o7pujk3q5o2rri5hwyefkmd7xy) - '@deepseek-ai/dsh-session-title': 0.1.0-rc.8(jzxfrqgu7wb3xsfjx5ea6eoowi) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) + '@deepseek-ai/dsh-session-projection-cache': 0.1.0-rc.8(80a7956f091cdf0c220b226dd100fe03) + '@deepseek-ai/dsh-session-query': 0.1.0-rc.8(e87dfefb8b6f6903ab3a7d4d893e4616) + '@deepseek-ai/dsh-session-title': 0.1.0-rc.8(91b31584ff9779c6cd69a9db13c5ad7e) '@deepseek-ai/dsh-settings': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/schemastery@3.18.1) '@deepseek-ai/dsh-skill': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-subagent': 0.1.0-rc.8(coi676g3ltfbkxbpzz2n5dgy7a) - '@deepseek-ai/dsh-tools': 0.1.0-rc.8(cjphcmfsxr6vrfny2gkyrgolze) - '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(wiirn2jei2nkjmsboxw35on4mm) - '@deepseek-ai/dsh-user-questions': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))) - '@deepseek-ai/dsh-workspace': 0.1.0-rc.8(n3vdmq7iw27i2sgg6iogtmuqei) + '@deepseek-ai/dsh-subagent': 0.1.0-rc.8(42428574dae299167d0987b281167061) + '@deepseek-ai/dsh-tools': 0.1.0-rc.8(68a9dffdb9e9c8636f3b708c6fd1edd1) + '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(380a43f4d6510c4a5dfadf54dc7f17a7) + '@deepseek-ai/dsh-user-questions': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))) + '@deepseek-ai/dsh-workspace': 0.1.0-rc.8(b22e0d48f5e81af272cd56aac64d0d48) '@deepseek-ai/schemastery': 3.18.1 fflate: 0.8.3 zod: 4.4.3 @@ -3577,22 +3630,22 @@ snapshots: '@deepseek-ai/cordis': 4.0.1(@deepseek-ai/cordis-plugin-include@1.0.6)(@deepseek-ai/cordis-plugin-loader@1.0.2) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-jobs@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))': + '@deepseek-ai/dsh-jobs@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))': dependencies: '@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(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) - '@deepseek-ai/dsh-llm-retry@0.1.0-rc.8(tmyqaedu2prdog3ai5pjncj6ri)': + '@deepseek-ai/dsh-llm-retry@0.1.0-rc.8(115581c97b2438036fbd23fd81d77eff)': dependencies: '@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(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) '@deepseek-ai/dsh-timeout': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 @@ -3605,14 +3658,14 @@ snapshots: '@deepseek-ai/dsh-timeout': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-message-feedback@0.1.0-rc.8(bezyjlz3tp3sbbg2tfte3wjx7y)': + '@deepseek-ai/dsh-message-feedback@0.1.0-rc.8(fa979bf26319855e9b452d904429d004)': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-storage-domain': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-storage@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 @@ -3633,69 +3686,69 @@ snapshots: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-session-persistence@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))': + '@deepseek-ai/dsh-session-persistence@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) '@deepseek-ai/dsh-timeout': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session-projection-cache@0.1.0-rc.8(aecd6ik5xb75vio2al2lw256w4)': + '@deepseek-ai/dsh-session-projection-cache@0.1.0-rc.8(80a7956f091cdf0c220b226dd100fe03)': dependencies: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) '@deepseek-ai/dsh-storage-domain': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-storage@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/schemastery': 3.18.1 zod: 4.4.3 - '@deepseek-ai/dsh-session-projection@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))': + '@deepseek-ai/dsh-session-projection@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))': dependencies: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) zod: 4.4.3 - '@deepseek-ai/dsh-session-query@0.1.0-rc.8(o7pujk3q5o2rri5hwyefkmd7xy)': + '@deepseek-ai/dsh-session-query@0.1.0-rc.8(e87dfefb8b6f6903ab3a7d4d893e4616)': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-session-title': 0.1.0-rc.8(jzxfrqgu7wb3xsfjx5ea6eoowi) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session-title': 0.1.0-rc.8(91b31584ff9779c6cd69a9db13c5ad7e) optionalDependencies: - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session-reference@0.1.0-rc.8(hng7uvyvmivmpc2kgslwtdqzsu)': + '@deepseek-ai/dsh-session-reference@0.1.0-rc.8(cf2186381d6c9247540aad69c3158862)': dependencies: '@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(gq4rxlduqatz4hofhgosja2lu4) - '@deepseek-ai/dsh-compaction': 0.1.0-rc.8(zcqikh7jjb4nrr3c673hqfu2xu) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) + '@deepseek-ai/dsh-compaction': 0.1.0-rc.8(cd54d1dbdb1933253bd594179027c07c) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-output-retention': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-session-query': 0.1.0-rc.8(o7pujk3q5o2rri5hwyefkmd7xy) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session-query': 0.1.0-rc.8(e87dfefb8b6f6903ab3a7d4d893e4616) '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/schemastery': 3.18.1 zod: 4.4.3 - '@deepseek-ai/dsh-session-title@0.1.0-rc.8(jzxfrqgu7wb3xsfjx5ea6eoowi)': + '@deepseek-ai/dsh-session-title@0.1.0-rc.8(91b31584ff9779c6cd69a9db13c5ad7e)': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) '@deepseek-ai/schemastery': 3.18.1 zod: 4.4.3 - '@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)': + '@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) @@ -3732,24 +3785,24 @@ snapshots: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-subagent@0.1.0-rc.8(coi676g3ltfbkxbpzz2n5dgy7a)': + '@deepseek-ai/dsh-subagent@0.1.0-rc.8(42428574dae299167d0987b281167061)': dependencies: '@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.8(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-tools': 0.1.0-rc.8(53xifwsgcqiqivitsot3r6a3te) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-tools': 0.1.0-rc.8(5bda1be499cac5a517847cfe82ab203b) zod: 4.4.3 optionalDependencies: - '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(5y7oeayczjdoxnag4x7zbpuyki) - '@deepseek-ai/dsh-jobs': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4)) - '@deepseek-ai/dsh-session-projection-cache': 0.1.0-rc.8(aecd6ik5xb75vio2al2lw256w4) - '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(aojav6lden5fwwpraqe7zs3sze) + '@deepseek-ai/dsh-agent-presets': 0.1.0-rc.8(c61da10b37997a0dffc1aedc219daaf2) + '@deepseek-ai/dsh-jobs': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session-projection': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293)) + '@deepseek-ai/dsh-session-projection-cache': 0.1.0-rc.8(80a7956f091cdf0c220b226dd100fe03) + '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(fb0355bbecd49d575c30b602eef27c30) '@deepseek-ai/dsh-system-prompt@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))': dependencies: @@ -3764,30 +3817,30 @@ snapshots: '@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-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-tools@0.1.0-rc.8(53xifwsgcqiqivitsot3r6a3te)': + '@deepseek-ai/dsh-tools@0.1.0-rc.8(5bda1be499cac5a517847cfe82ab203b)': dependencies: '@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(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-code-runtime': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(aojav6lden5fwwpraqe7zs3sze) + '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(fb0355bbecd49d575c30b602eef27c30) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-tools@0.1.0-rc.8(cjphcmfsxr6vrfny2gkyrgolze)': + '@deepseek-ai/dsh-tools@0.1.0-rc.8(68a9dffdb9e9c8636f3b708c6fd1edd1)': dependencies: '@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.8(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-code-runtime': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(aojav6lden5fwwpraqe7zs3sze) + '@deepseek-ai/dsh-user-approval': 0.1.0-rc.8(fb0355bbecd49d575c30b602eef27c30) '@deepseek-ai/schemastery': 3.18.1 '@deepseek-ai/dsh-typert-protocol@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))': @@ -3802,44 +3855,44 @@ snapshots: '@deepseek-ai/dsh-typert-protocol': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) zod: 4.4.3 - '@deepseek-ai/dsh-user-approval@0.1.0-rc.8(aojav6lden5fwwpraqe7zs3sze)': + '@deepseek-ai/dsh-user-approval@0.1.0-rc.8(380a43f4d6510c4a5dfadf54dc7f17a7)': dependencies: '@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(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-user-approval@0.1.0-rc.8(wiirn2jei2nkjmsboxw35on4mm)': + '@deepseek-ai/dsh-user-approval@0.1.0-rc.8(fb0355bbecd49d575c30b602eef27c30)': dependencies: '@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.8(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-scope': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) '@deepseek-ai/dsh-system-prompt': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))(@deepseek-ai/dsh-scope@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/schemastery': 3.18.1 - '@deepseek-ai/dsh-user-questions@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.8(gq4rxlduqatz4hofhgosja2lu4))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))': + '@deepseek-ai/dsh-user-questions@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-llm@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))))': dependencies: '@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.8(gq4rxlduqatz4hofhgosja2lu4) + '@deepseek-ai/dsh-agent': 0.1.0-rc.8(92f269661ea5e195fab72177f1a12db7) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) '@deepseek-ai/dsh-llm': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) - '@deepseek-ai/dsh-workspace@0.1.0-rc.8(n3vdmq7iw27i2sgg6iogtmuqei)': + '@deepseek-ai/dsh-workspace@0.1.0-rc.8(b22e0d48f5e81af272cd56aac64d0d48)': dependencies: '@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-brand': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-invariants': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1) - '@deepseek-ai/dsh-session': 0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4) - '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(hbvxzxzszrvncqvsihetse6hb4))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-session': 0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293) + '@deepseek-ai/dsh-session-persistence': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-brand@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-session@0.1.0-rc.8(fbdb1d988541b64ff002d18c4ded7293))(@deepseek-ai/dsh-timeout@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) '@deepseek-ai/dsh-storage': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)) '@deepseek-ai/dsh-storage-domain': 0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))(@deepseek-ai/dsh-storage@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-invariants@0.1.0-rc.8(@deepseek-ai/cordis@4.0.1))) zod: 4.4.3 @@ -4236,42 +4289,6 @@ snapshots: '@typescript/native-preview-win32-arm64': 7.0.0-dev.20260328.1 '@typescript/native-preview-win32-x64': 7.0.0-dev.20260328.1 - '@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))(vitest@4.1.11)': - dependencies: - '@testing-library/dom': 10.4.1 - '@testing-library/user-event': 14.6.6(@testing-library/dom@10.4.1) - '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))(vitest@4.1.11) - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - - '@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))(vitest@4.1.11)': - dependencies: - '@testing-library/dom': 10.4.1 - '@testing-library/user-event': 14.6.6(@testing-library/dom@10.4.1) - '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))(vitest@4.1.11) - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - - '@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11)': - dependencies: - '@testing-library/dom': 10.4.1 - '@testing-library/user-event': 14.6.6(@testing-library/dom@10.4.1) - '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - '@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11)': dependencies: '@testing-library/dom': 10.4.1 @@ -4284,57 +4301,6 @@ snapshots: - utf-8-validate - vite - '@vitest/browser@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))(vitest@4.1.11)': - dependencies: - '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) - '@vitest/utils': 4.1.11 - magic-string: 0.30.21 - pngjs: 7.0.0 - sirv: 3.0.2 - tinyrainbow: 3.1.1 - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) - ws: 8.21.3 - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - - '@vitest/browser@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))(vitest@4.1.11)': - dependencies: - '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) - '@vitest/utils': 4.1.11 - magic-string: 0.30.21 - pngjs: 7.0.0 - sirv: 3.0.2 - tinyrainbow: 3.1.1 - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) - ws: 8.21.3 - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - - '@vitest/browser@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11)': - dependencies: - '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) - '@vitest/utils': 4.1.11 - magic-string: 0.30.21 - pngjs: 7.0.0 - sirv: 3.0.2 - tinyrainbow: 3.1.1 - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) - ws: 8.21.3 - transitivePeerDependencies: - - bufferutil - - msw - - utf-8-validate - - vite - '@vitest/browser@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11)': dependencies: '@blazediff/core': 1.9.1 @@ -4361,30 +4327,6 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.1 - '@vitest/mocker@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))': - dependencies: - '@vitest/spy': 4.1.11 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)' - - '@vitest/mocker@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))': - dependencies: - '@vitest/spy': 4.1.11 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)' - - '@vitest/mocker@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))': - dependencies: - '@vitest/spy': 4.1.11 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' - '@vitest/mocker@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.11 @@ -5795,10 +5737,10 @@ snapshots: dependencies: '@oxc-project/types': 0.150.0 '@oxlint/plugins': 1.79.0 - '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))(vitest@4.1.11) - '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))(vitest@4.1.11) + '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) + '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.11 '@vitest/runner': 4.1.11 '@vitest/snapshot': 4.1.11 @@ -5808,7 +5750,7 @@ snapshots: oxlint: 1.83.0(oxlint-tsgolint@7.0.2001)(vite-plus@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) oxlint-tsgolint: 7.0.2001 vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)' - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11))(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) optionalDependencies: '@voidzero-dev/vite-plus-darwin-arm64': 0.3.3 '@voidzero-dev/vite-plus-darwin-x64': 0.3.3 @@ -5852,10 +5794,10 @@ snapshots: dependencies: '@oxc-project/types': 0.150.0 '@oxlint/plugins': 1.79.0 - '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))(vitest@4.1.11) - '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))(vitest@4.1.11) + '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) + '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.11 '@vitest/runner': 4.1.11 '@vitest/snapshot': 4.1.11 @@ -5865,7 +5807,7 @@ snapshots: oxlint: 1.83.0(oxlint-tsgolint@7.0.2001)(vite-plus@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) oxlint-tsgolint: 7.0.2001 vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)' - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11))(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) optionalDependencies: '@voidzero-dev/vite-plus-darwin-arm64': 0.3.3 '@voidzero-dev/vite-plus-darwin-x64': 0.3.3 @@ -5909,10 +5851,10 @@ snapshots: dependencies: '@oxc-project/types': 0.150.0 '@oxlint/plugins': 1.79.0 - '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) - '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) + '@vitest/browser': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) + '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.11 '@vitest/runner': 4.1.11 '@vitest/snapshot': 4.1.11 @@ -5922,7 +5864,7 @@ snapshots: oxlint: 1.83.0(oxlint-tsgolint@7.0.2001)(vite-plus@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) oxlint-tsgolint: 7.0.2001 vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' - vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + vitest: 4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11))(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) optionalDependencies: '@voidzero-dev/vite-plus-darwin-arm64': 0.3.3 '@voidzero-dev/vite-plus-darwin-x64': 0.3.3 @@ -6019,66 +5961,10 @@ snapshots: - utf-8-validate - yaml - vitest@4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)): + vitest@4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11))(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.11 - '@vitest/runner': 4.1.11 - '@vitest/snapshot': 4.1.11 - '@vitest/spy': 4.1.11 - '@vitest/utils': 4.1.11 - es-module-lexer: 2.3.2 - expect-type: 1.4.0 - magic-string: 0.30.21 - obug: 2.1.4 - pathe: 2.0.3 - picomatch: 4.0.5 - std-env: 4.1.0 - tinybench: 2.9.0 - tinyexec: 1.3.0 - tinyglobby: 0.2.17 - tinyrainbow: 3.1.1 - vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3)' - why-is-node-running: 2.3.0 - optionalDependencies: - '@types/node': 24.12.2 - '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.8.3))(vitest@4.1.11) - transitivePeerDependencies: - - msw - - vitest@4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)): - dependencies: - '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)) - '@vitest/pretty-format': 4.1.11 - '@vitest/runner': 4.1.11 - '@vitest/snapshot': 4.1.11 - '@vitest/spy': 4.1.11 - '@vitest/utils': 4.1.11 - es-module-lexer: 2.3.2 - expect-type: 1.4.0 - magic-string: 0.30.21 - obug: 2.1.4 - pathe: 2.0.3 - picomatch: 4.0.5 - std-env: 4.1.0 - tinybench: 2.9.0 - tinyexec: 1.3.0 - tinyglobby: 0.2.17 - tinyrainbow: 3.1.1 - vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)' - why-is-node-running: 2.3.0 - optionalDependencies: - '@types/node': 24.12.2 - '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3))(vitest@4.1.11) - transitivePeerDependencies: - - msw - - vitest@4.1.11(@types/node@24.12.2)(@vitest/browser-preview@4.1.11)(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)): - dependencies: - '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + '@vitest/mocker': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.11 '@vitest/runner': 4.1.11 '@vitest/snapshot': 4.1.11 @@ -6095,11 +5981,11 @@ snapshots: tinyexec: 1.3.0 tinyglobby: 0.2.17 tinyrainbow: 3.1.1 - vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' + vite: '@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 24.12.2 - '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) + '@vitest/browser-preview': 4.1.11(@voidzero-dev/vite-plus-core@0.3.3(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0))(vitest@4.1.11) transitivePeerDependencies: - msw From fec8dc515e203104e12890aea00236851ee0b76d Mon Sep 17 00:00:00 2001 From: wangmingxiang Date: Wed, 28 Oct 2026 14:31:16 +0800 Subject: [PATCH 3/6] =?UTF-8?q?fix(core):=20=E5=A2=9E=E5=8A=A0MCP=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E5=8F=AF=E7=94=A8=E6=80=A7=E6=A3=80=E6=B5=8B=E5=8F=8A?= =?UTF-8?q?=E8=BE=93=E5=85=A5=E6=98=A0=E5=B0=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增断言函数assertAutoMcpAvailable,防止Token Plan连接使用auto模型触发MCP请求 - 增加resolveAutoImageSize函数,实现auto模式--size比例与像素的映射及校验 - 新增assertMcpTtsVoice函数,限制auto模式合成语音使用MCP枚举音色 - 修改Image、Speech、Video等命令,调用断言与输入映射函数提升兼容性和报错提示 - 添加McpClient实现,统一底层SDK适配及初始化流程,支持握手超时及关闭中止 - video任务失败时抛出服务器原始错误信息,带失败任务ID上下文提示 - 在client模块新增usesTokenPlanConnection方法判断连接适用性 - 在测试中覆盖新增断言、解析、映射函数,完善SDK适配器握手超时及中止测试 - 测试用例调整“auto”模式下采用MCP枚举音色及--size比例映射验证,确保正确行为 --- packages/commands/src/commands/image/edit.ts | 2 + .../commands/src/commands/image/generate.ts | 5 +- .../commands/src/commands/shared/aigc-mcp.ts | 67 ++++++ .../commands/src/commands/speech/recognize.ts | 2 + .../src/commands/speech/synthesize.ts | 8 +- .../commands/src/commands/video/generate.ts | 22 +- packages/commands/tests/aigc-mcp-gate.test.ts | 56 ++++- .../tests/e2e/aigc-auto-mcp.e2e.test.ts | 43 +++- packages/core/src/client/aigc-mcp.ts | 60 ++++- packages/core/src/client/client.ts | 15 ++ packages/core/src/client/index.ts | 6 + packages/core/src/client/mcp-sdk.ts | 132 ++++++++--- packages/core/src/client/mcp.ts | 32 ++- packages/core/tests/aigc-mcp.test.ts | 42 ++++ packages/core/tests/image-input.test.ts | 39 ++++ packages/core/tests/mcp.test.ts | 213 +++++++++++++++++- 16 files changed, 689 insertions(+), 55 deletions(-) diff --git a/packages/commands/src/commands/image/edit.ts b/packages/commands/src/commands/image/edit.ts index 4189eace1..1b23d4d31 100644 --- a/packages/commands/src/commands/image/edit.ts +++ b/packages/commands/src/commands/image/edit.ts @@ -37,6 +37,7 @@ import { join } from "path"; import { BOOL_FLAG_PROMPT_EXTEND_CLI_TRUE, BOOL_FLAG_WATERMARK } from "bailian-cli-runtime"; import { isAutoModel, + assertAutoMcpAvailable, assertMcpCompatible, withAigcMcpSession, resolveAutoImageInput, @@ -371,6 +372,7 @@ async function handleAutoMcpMode( rawImages: string[], format: OutputFormat, ): Promise { + assertAutoMcpAvailable(client, localize); assertMcpCompatible("imageEdit", flags, localize); // bailian_image_edit takes a single source image; bailian_image_fusion is out diff --git a/packages/commands/src/commands/image/generate.ts b/packages/commands/src/commands/image/generate.ts index e62387485..00eda1310 100644 --- a/packages/commands/src/commands/image/generate.ts +++ b/packages/commands/src/commands/image/generate.ts @@ -34,7 +34,9 @@ import { resolveImageSize } from "bailian-cli-runtime"; import { BOOL_FLAG_PROMPT_EXTEND_IMAGE_GENERATE, BOOL_FLAG_WATERMARK } from "bailian-cli-runtime"; import { isAutoModel, + assertAutoMcpAvailable, assertMcpCompatible, + resolveAutoImageSize, withAigcMcpSession, type Localize, } from "../shared/aigc-mcp.ts"; @@ -278,12 +280,13 @@ async function handleAutoMcpMode( flags: GenerateFlags, format: string, ): Promise { + assertAutoMcpAvailable(client, localize); assertMcpCompatible("imageGen", flags, localize); const concurrent = getConcurrency(flags); const args = buildImageGenArgs({ prompt: flags.prompt, - size: flags.size || undefined, + size: resolveAutoImageSize(flags.size, localize), n: flags.n, negativePrompt: flags.negativePrompt || undefined, promptExtend: flags.promptExtend, diff --git a/packages/commands/src/commands/shared/aigc-mcp.ts b/packages/commands/src/commands/shared/aigc-mcp.ts index cf9f7d821..58c606dc3 100644 --- a/packages/commands/src/commands/shared/aigc-mcp.ts +++ b/packages/commands/src/commands/shared/aigc-mcp.ts @@ -20,7 +20,10 @@ import { parseAigcToolResult, imageFileToDataUri, audioFileToDataUri, + isMcpTtsVoice, + MCP_TTS_VOICES, MCP_CALL_SERVICE, + resolveMcpImageSize, type Client, type LocalizedText, type McpConnectedClient, @@ -199,6 +202,70 @@ export function mcpSingleImageOnlyError(localize: Localize): BailianError { return new BailianError(message, ExitCode.USAGE, hint); } +// ---- Connection applicability gate ---- + +/** + * Reject `auto` mode up front when the effective connection cannot reach the + * Bailian AIGC MCP servers. Both Token Plan shapes were verified against the + * live gateways: the token-plan endpoint has no `/api/v1/mcps` route at all + * (bare 404, empty body) and plan keys (`sk-sp-`) are refused on the standard + * MCP path (401 InvalidApiKey). Neither server response is self-explanatory, + * and this applicability fact is authoritative on the client side, so it is + * raised before any request instead of passing the opaque error through. + */ +export function assertAutoMcpAvailable(client: Client, localize: Localize): void { + if (!client.usesTokenPlanConnection()) return; + const message = localize({ + "en-US": + "The current model (auto) routes generation through Bailian MCP, which the Token Plan connection (endpoint or API key) does not provide.", + "zh-CN": "当前模型(auto)经百炼 MCP 路由生成,Token Plan 连接(端点或 API Key)不提供该能力。", + }); + const hint = localize({ + "en-US": + "Switch to a config profile with a standard DashScope API key, or pass --model to keep using Token Plan models.", + "zh-CN": + "请切换到含标准 DashScope API Key 的配置,或传入 --model 继续使用 Token Plan 模型。", + }); + throw new BailianError(message, ExitCode.USAGE, hint); +} + +// ---- MCP input value gates (auto mode) ---- + +/** + * Resolve an `auto`-mode `--size` for MCP image generation: ratios map to the + * server's pixel presets and pixel input passes through; values MCP cannot + * accept are rejected up front with the unsupported-parameter USAGE error. + */ +export function resolveAutoImageSize( + size: string | undefined, + localize: Localize, +): string | undefined { + if (size === undefined) return undefined; + const mapped = resolveMcpImageSize(size); + if (mapped === undefined) { + throw mcpUnsupportedError(localize, [`--size ${size}`]); + } + return mapped; +} + +/** + * Reject `auto`-mode TTS voices outside the MCP enum before any request: REST + * voice IDs (e.g. `longxiaochun_v3`) are not accepted by `bailian_tts`. + */ +export function assertMcpTtsVoice(voice: string, localize: Localize): void { + if (isMcpTtsVoice(voice)) return; + const list = MCP_TTS_VOICES.join(", "); + const message = localize({ + "en-US": `The current model (auto) does not support voice "${voice}". MCP TTS voices: ${list}.`, + "zh-CN": `当前模型(auto)不支持音色 "${voice}"。MCP 可选音色:${list}。`, + }); + const hint = localize({ + "en-US": "Pass one of the listed MCP voices, or use --model for the REST system voices.", + "zh-CN": "请传入所列 MCP 音色,或使用 --model 改用 REST 系统音色。", + }); + throw new BailianError(message, ExitCode.USAGE, hint); +} + // ---- Local file input (auto mode inlines files as base64 data URIs) ---- /** diff --git a/packages/commands/src/commands/speech/recognize.ts b/packages/commands/src/commands/speech/recognize.ts index ab9f88a00..f6441fbf7 100644 --- a/packages/commands/src/commands/speech/recognize.ts +++ b/packages/commands/src/commands/speech/recognize.ts @@ -36,6 +36,7 @@ import { poll } from "bailian-cli-runtime"; import { emitResult, emitBare } from "bailian-cli-runtime"; import { isAutoModel, + assertAutoMcpAvailable, assertMcpCompatible, withAigcMcpSession, resolveAutoAudioInput, @@ -351,6 +352,7 @@ async function handleAutoMcpMode( rawUrls: string[], format: OutputFormat, ): Promise { + assertAutoMcpAvailable(client, localize); assertMcpCompatible("asr", flags, localize); if (rawUrls.length === 0) { diff --git a/packages/commands/src/commands/speech/synthesize.ts b/packages/commands/src/commands/speech/synthesize.ts index 6987d7a54..99434b9dc 100644 --- a/packages/commands/src/commands/speech/synthesize.ts +++ b/packages/commands/src/commands/speech/synthesize.ts @@ -31,7 +31,9 @@ import { emitResult, emitBare } from "bailian-cli-runtime"; import { VOICE_TTS_PAGE } from "bailian-cli-runtime"; import { isAutoModel, + assertAutoMcpAvailable, assertMcpCompatible, + assertMcpTtsVoice, withAigcMcpSession, type Localize, } from "../shared/aigc-mcp.ts"; @@ -484,6 +486,7 @@ async function handleAutoMcpMode( flags: SynthesizeFlags, format: OutputFormat, ): Promise { + assertAutoMcpAvailable(client, localize); assertMcpCompatible("tts", flags, localize); // Same text precedence as REST: --text, else --text-file. @@ -496,9 +499,10 @@ async function handleAutoMcpMode( throw new BailianError(`Cannot read text file: ${filePath}`, ExitCode.USAGE); } } - // Voice is passed through verbatim (validate enforces its presence); the MCP - // server validates it against its own voice enum. + // Voice must be one of the MCP enum values; REST voice IDs are rejected up + // front so dry-run never previews a request the server cannot accept. const voice = flags.voice as string; + assertMcpTtsVoice(voice, localize); const args = buildTtsArgs({ text, voice }); if (settings.dryRun) { diff --git a/packages/commands/src/commands/video/generate.ts b/packages/commands/src/commands/video/generate.ts index 5bbcee71c..a56e4eaac 100644 --- a/packages/commands/src/commands/video/generate.ts +++ b/packages/commands/src/commands/video/generate.ts @@ -34,10 +34,12 @@ import { BOOL_FLAG_PROMPT_EXTEND_API_DEFAULT, BOOL_FLAG_WATERMARK } from "bailia import { PRIME_FLAGS, resolvePrimeEndpoint, validatePrimeFlags } from "../shared/prime.ts"; import { isAutoModel, + assertAutoMcpAvailable, assertMcpCompatible, withAigcMcpSession, resolveAutoImageInput, type AigcMcpCallTool, + type Localize, } from "../shared/aigc-mcp.ts"; export default defineCommand({ @@ -214,6 +216,7 @@ export default defineCommand({ // auto model → official AIGC MCP (VideoGenerate); specific models keep the REST path. if (isAutoModel(resolvedModel)) { + assertAutoMcpAvailable(ctx.client, ctx.localize); const imageInput = flags.image; assertMcpCompatible( imageInput !== undefined ? "videoImageToVideo" : "videoTextToVideo", @@ -273,7 +276,9 @@ export default defineCommand({ "tasks", ); return Promise.all( - taskIds.map((taskId) => pollMcpVideoTask(callTool, taskId, settings, pollInterval)), + taskIds.map((taskId) => + pollMcpVideoTask(callTool, taskId, settings, pollInterval, ctx.localize), + ), ); }, ); @@ -519,6 +524,14 @@ export default defineCommand({ }, }); +/** Supplementary context for a failed MCP video task (server message is primary). */ +function videoTaskIdHint(localize: Localize, taskId: string): string { + return localize({ + "en-US": `The failed video task id is ${taskId}.`, + "zh-CN": `失败的视频任务 ID 为 ${taskId}。`, + }); +} + /** * Poll a video task to completion over MCP `bailian_text_to_video_fetch_result`. * Mirrors the REST `poll` UX (spinner + status), but the transport is a repeated @@ -529,6 +542,7 @@ async function pollMcpVideoTask( taskId: string, settings: Settings, pollInterval: number, + localize: Localize, ): Promise<{ taskId: string; videoUrl: string }> { const deadline = Date.now() + settings.timeout * 1000; const spinner = createSpinner("Polling..."); @@ -554,6 +568,12 @@ async function pollMcpVideoTask( if (result.taskStatus === "FAILED") { spinner.stop("Failed."); + // Pass the server's failure reason through verbatim (AGENTS.md §3); + // the task id stays as supplementary context in the hint. + const serverReason = result.message ?? result.code; + if (serverReason) { + throw new BailianError(serverReason, ExitCode.GENERAL, videoTaskIdHint(localize, taskId)); + } throw new BailianError(`Video task failed: ${taskId}`, ExitCode.GENERAL); } diff --git a/packages/commands/tests/aigc-mcp-gate.test.ts b/packages/commands/tests/aigc-mcp-gate.test.ts index daed6b562..e849db572 100644 --- a/packages/commands/tests/aigc-mcp-gate.test.ts +++ b/packages/commands/tests/aigc-mcp-gate.test.ts @@ -1,11 +1,14 @@ import { describe, expect, test } from "vite-plus/test"; -import { BailianError, ExitCode } from "bailian-cli-core"; +import { BailianError, ExitCode, type Client } from "bailian-cli-core"; import { AUTO_MODEL, + assertAutoMcpAvailable, assertMcpCompatible, + assertMcpTtsVoice, isAutoModel, mcpSingleImageOnlyError, mcpUnsupportedError, + resolveAutoImageSize, type AigcMcpOperation, type Localize, } from "../src/commands/shared/aigc-mcp.ts"; @@ -147,3 +150,54 @@ describe("error message builders", () => { expect(singleImageError.message).toContain("single image"); }); }); + +describe("assertAutoMcpAvailable rejects Token Plan connections", () => { + /** Minimal Client stub: only the accessor the applicability gate reads. */ + function stubClient(tokenPlanConnection: boolean): Client { + return { + usesTokenPlanConnection: () => tokenPlanConnection, + } as unknown as Client; + } + + test("Token Plan connection throws USAGE with an actionable hint (en-US)", () => { + const error = captureUsage(() => assertAutoMcpAvailable(stubClient(true), enUS)); + expect(error.message).toContain("Token Plan"); + expect(error.hint).toContain("--model"); + }); + + test("zh-CN localization mentions Token Plan and the model fallback", () => { + const error = captureUsage(() => assertAutoMcpAvailable(stubClient(true), zhCN)); + expect(error.message).toContain("Token Plan"); + expect(error.hint).toContain("Token Plan 模型"); + }); + + test("non-Token-Plan connection passes", () => { + expect(() => assertAutoMcpAvailable(stubClient(false), enUS)).not.toThrow(); + }); +}); + +describe("resolveAutoImageSize maps or rejects --size for MCP", () => { + test("ratios map to pixel presets and pixels pass through", () => { + expect(resolveAutoImageSize("16:9", enUS)).toBe("1664*928"); + expect(resolveAutoImageSize("2048*2048", enUS)).toBe("2048*2048"); + expect(resolveAutoImageSize(undefined, enUS)).toBeUndefined(); + }); + + test("unmappable values throw the unsupported-parameter USAGE error", () => { + const error = captureUsage(() => resolveAutoImageSize("2:3", enUS)); + expect(error.message).toContain("--size 2:3"); + }); +}); + +describe("assertMcpTtsVoice rejects REST voice IDs", () => { + test("enum voices pass", () => { + expect(() => assertMcpTtsVoice("温柔女声", enUS)).not.toThrow(); + }); + + test("REST voice IDs throw USAGE listing the MCP enum", () => { + const error = captureUsage(() => assertMcpTtsVoice("longxiaochun_v3", enUS)); + expect(error.message).toContain("longxiaochun_v3"); + expect(error.message).toContain("温柔女声"); + expect(error.hint).toContain("--model"); + }); +}); diff --git a/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts b/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts index 62bba369e..a86ca113a 100644 --- a/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts +++ b/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts @@ -167,7 +167,7 @@ describe("e2e: aigc auto → mcp", () => { expect(data.arguments?.first_frame_url).toBe("https://example.com/a.png"); }); - test("speech synthesize auto dry-run 预览走 TextGenerateSpeech/bailian_tts(透传 voice)", async () => { + test("speech synthesize auto dry-run 预览走 TextGenerateSpeech/bailian_tts(MCP 枚举音色)", async () => { const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ "speech", "synthesize", @@ -176,7 +176,7 @@ describe("e2e: aigc auto → mcp", () => { "--text", "hello", "--voice", - "longxiaochun_v3", + "温柔女声", "--dry-run", "--output", "json", @@ -187,7 +187,7 @@ describe("e2e: aigc auto → mcp", () => { expect(data.server).toBe("TextGenerateSpeech"); expect(data.tool).toBe("bailian_tts"); expect(data.arguments?.text).toBe("hello"); - expect(data.arguments?.voice).toBe("longxiaochun_v3"); + expect(data.arguments?.voice).toBe("温柔女声"); }); test("speech recognize auto dry-run 预览走 SpeechGenerateText/bailian_speech_to_text", async () => { @@ -231,6 +231,25 @@ describe("e2e: aigc auto → mcp", () => { expect(data.arguments?.file_urls).toEqual(["data:audio/wav;base64,"]); }); + test("image generate auto dry-run 预览把 --size 比例映射为 MCP 宽*高", async () => { + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "image", + "generate", + "--model", + "auto", + "--prompt", + "sunset", + "--size", + "16:9", + "--dry-run", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson(stdout); + expect(data.arguments?.size).toBe("1664*928"); + }); + // auto + MCP 承接不了的 flag → USAGE(2),绝不静默回退 REST。 const gateCases: Array<[string, string[], RegExp]> = [ [ @@ -285,12 +304,22 @@ describe("e2e: aigc auto → mcp", () => { "--text", "x", "--voice", - "longxiaochun_v3", + "温柔女声", "--format", "mp3", ], /--format/, ], + [ + "speech synthesize 非 MCP 枚举音色", + ["speech", "synthesize", "--model", "auto", "--text", "x", "--voice", "longxiaochun_v3"], + /longxiaochun_v3/, + ], + [ + "image generate 不可映射的 --size", + ["image", "generate", "--model", "auto", "--prompt", "x", "--size", "2:3"], + /--size/, + ], [ "speech synthesize --list-voices", ["speech", "synthesize", "--model", "auto", "--list-voices"], @@ -375,9 +404,9 @@ describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())( "auto", "--text", "端到端 auto 语音测试", - // voice 原样透传给 MCP,需为服务端音色枚举内的值(与 REST live 用例一致)。 + // voice 需为 MCP 音色枚举内的值(REST 音色 ID 会被前置校验拒绝)。 "--voice", - "longxiaochun_v3", + "温柔女声", "--out", outWav, "--output", @@ -387,7 +416,7 @@ describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())( const data = parseStdoutJson<{ saved?: string; audio_url?: string; voice?: string }>(stdout); expect(data.saved).toBe(outWav); expect(data.audio_url?.length ?? 0).toBeGreaterThan(0); - expect(data.voice).toBe("longxiaochun_v3"); + expect(data.voice).toBe("温柔女声"); }, 180_000); }, ); diff --git a/packages/core/src/client/aigc-mcp.ts b/packages/core/src/client/aigc-mcp.ts index 27e29fc5b..cb9e62ea8 100644 --- a/packages/core/src/client/aigc-mcp.ts +++ b/packages/core/src/client/aigc-mcp.ts @@ -181,6 +181,54 @@ export function buildSpeechToTextArgs(fileUrls: string[]): Record> = { + "1:1": "1328*1328", + "3:4": "1104*1472", + "4:3": "1472*1104", + "9:16": "928*1664", + "16:9": "1664*928", +}; + +/** + * Resolve an `auto`-mode `--size` value for `bailian_image_gen`: pixel input + * (`W*H`, with `x` normalized to `*`) passes through, ratios map via + * {@link MCP_IMAGE_GEN_RATIO_SIZES}. Returns `undefined` for values MCP cannot + * accept so the command layer can reject them up front. + */ +export function resolveMcpImageSize(size: string): string | undefined { + const pixels = /^(\d+)[*xX](\d+)$/.exec(size.trim()); + if (pixels) return `${pixels[1]}*${pixels[2]}`; + return MCP_IMAGE_GEN_RATIO_SIZES[size.trim()]; +} + +/** `bailian_tts` voice enum, verbatim from the live tool inputSchema. */ +export const MCP_TTS_VOICES: readonly string[] = [ + "电商直播男", + "电商直播女", + "温柔女声", + "沉稳男声", + "英文男声", + "英文女生", + "老年女声", + "老年男声", + "童声男", + "童声女", +]; + +/** True when `voice` is one of the MCP TTS enum values (REST voice IDs are not). */ +export function isMcpTtsVoice(voice: string): boolean { + return MCP_TTS_VOICES.includes(voice); +} + // ---- Response parsers (pure) ---- /** Pull a URL out of a result entry that may be a bare string or `{ url }`. */ @@ -238,18 +286,28 @@ export interface AigcVideoTaskResult { taskStatus: string; videoUrl?: string; taskId?: string; + /** Server-provided failure reason, verbatim (present on FAILED tasks). */ + message?: string; + /** Server-provided failure code, verbatim. */ + code?: string; } -/** Parse the video fetch result `{ task_status, video_url, task_id }`. */ +/** Parse the video fetch result `{ task_status, video_url, task_id }`, keeping + * the server's failure reason (`message` / `code`) verbatim when present. */ export function parseAigcVideoTaskResult(inner: Record): AigcVideoTaskResult { const taskStatus = typeof inner.task_status === "string" ? inner.task_status : "UNKNOWN"; const videoUrl = typeof inner.video_url === "string" && inner.video_url.length > 0 ? inner.video_url : undefined; const taskId = typeof inner.task_id === "string" ? inner.task_id : undefined; + const message = + typeof inner.message === "string" && inner.message.length > 0 ? inner.message : undefined; + const code = typeof inner.code === "string" && inner.code.length > 0 ? inner.code : undefined; return { taskStatus, ...(videoUrl !== undefined ? { videoUrl } : {}), ...(taskId !== undefined ? { taskId } : {}), + ...(message !== undefined ? { message } : {}), + ...(code !== undefined ? { code } : {}), }; } diff --git a/packages/core/src/client/client.ts b/packages/core/src/client/client.ts index 482aa28ac..64a052336 100644 --- a/packages/core/src/client/client.ts +++ b/packages/core/src/client/client.ts @@ -14,6 +14,7 @@ import { import { SdkMcpAdapter } from "./mcp-sdk.ts"; import { callConsoleGateway } from "../console/gateway.ts"; import { refreshAccessToken } from "../auth/refresh-token.ts"; +import { getApiKeyLoginKind } from "../config/profile-presets.ts"; import { maskToken } from "../utils/token.ts"; import { trackingHeaders } from "./headers.ts"; @@ -183,6 +184,20 @@ export class Client { } } + /** + * True when the effective model-domain connection is a Token Plan one: either + * the token-plan endpoint or a plan key (`sk-sp-`). Both shapes are verified + * unable to reach Bailian MCP (the plan gateway has no `/api/v1/mcps` route — + * bare 404 — and plan keys get 401 InvalidApiKey on the standard MCP path), + * so callers routing through MCP (AIGC `auto` mode) reject up front. + */ + usesTokenPlanConnection(): boolean { + return ( + this.usesTokenPlanEndpoint() || + getApiKeyLoginKind(this.deps.apiCred?.token ?? "") === "token-plan" + ); + } + /** Open an MCP client. Accepts a path (prepended with the model baseUrl) or an absolute URL. */ mcp(pathOrUrl: string): McpConnectedClient { const url = /^https?:\/\//.test(pathOrUrl) ? pathOrUrl : this.requireApi().baseUrl + pathOrUrl; diff --git a/packages/core/src/client/index.ts b/packages/core/src/client/index.ts index 35d638505..ed60e4045 100644 --- a/packages/core/src/client/index.ts +++ b/packages/core/src/client/index.ts @@ -103,6 +103,7 @@ export { export type { McpTool, McpToolResult, + McpToolResultContent, McpConnectedClient, ConnectBailianMcpOptions, } from "./mcp.ts"; @@ -113,9 +114,14 @@ export { isUrlOverrideSseFallbackCandidate, connectBailianMcpWithFallback, } from "./mcp.ts"; +export { McpClient } from "./mcp-sdk.ts"; export { AIGC_MCP_SERVER, AIGC_MCP_TOOL, + MCP_IMAGE_GEN_RATIO_SIZES, + MCP_TTS_VOICES, + isMcpTtsVoice, + resolveMcpImageSize, parseAigcToolResult, buildImageGenArgs, buildImageEditArgs, diff --git a/packages/core/src/client/mcp-sdk.ts b/packages/core/src/client/mcp-sdk.ts index a31a00e30..dd7ce9008 100644 --- a/packages/core/src/client/mcp-sdk.ts +++ b/packages/core/src/client/mcp-sdk.ts @@ -32,6 +32,39 @@ import { trackingHeaders } from "./headers.ts"; import type { HttpDeps } from "./http.ts"; import type { McpConnectedClient, McpTool, McpToolResult } from "./mcp.ts"; +/** + * Low-level Streamable HTTP MCP client keeping the constructor and method + * signatures published by earlier `bailian-cli-core` versions; delegates to + * {@link SdkMcpAdapter}. It drives a single transport at a caller-supplied URL + * and token — for the orchestrated entry (URL/credential resolution, + * Streamable→SSE fallback, channel attribution) use `Client.connectBailianMcp` + * / `connectBailianMcpWithFallback`. + */ +export class McpClient implements McpConnectedClient { + private readonly adapter: SdkMcpAdapter; + + constructor(deps: HttpDeps, url: string, authToken?: string) { + this.adapter = new SdkMcpAdapter({ deps, url, authToken, transport: "streamable" }); + } + + /** Initialize the MCP session. Must be called before any other method. */ + initialize(): Promise { + return this.adapter.initialize(); + } + + listTools(): Promise { + return this.adapter.listTools(); + } + + callTool(name: string, args: Record): Promise { + return this.adapter.callTool(name, args); + } + + close(): void { + this.adapter.close(); + } +} + /** Which transport the adapter drives: Streamable HTTP (/mcp) or classic SSE (/sse). */ export type SdkMcpTransportKind = "streamable" | "sse"; @@ -102,7 +135,11 @@ function rawMcpMessage(error: McpError): string { * Build the transport-level fetch. It reproduces the old client's error contract * for message POSTs and mirrors its `--verbose` wire logging. GET responses are * passed through untouched so the SDK's own SSE-stream handling (including the - * tolerated 405 on a standalone Streamable GET) stays intact. + * tolerated 405 on a standalone Streamable GET) stays intact. Redirect responses + * are likewise passed through: the SDK wraps this fetch with its same-origin + * redirect policy (`fetchWithinOrigin`) and must see the 3xx to follow or + * reject it itself — intercepting it here would break same-origin redirects + * the old client's default `redirect: "follow"` used to honor. */ function createMcpFetch(deps: HttpDeps): FetchLike { return async (url, init) => { @@ -127,7 +164,7 @@ function createMcpFetch(deps: HttpDeps): FetchLike { console.error(`< ${response.status} ${response.statusText}`); } - if (!response.ok && method === "POST") { + if (!response.ok && method === "POST" && !isRedirectStatus(response.status)) { let message = `MCP request failed: ${response.status} ${response.statusText}`; try { const errorBody = await response.text(); @@ -142,6 +179,11 @@ function createMcpFetch(deps: HttpDeps): FetchLike { }; } +/** True for 3xx statuses the SDK's same-origin redirect policy handles itself. */ +function isRedirectStatus(status: number): boolean { + return status >= 300 && status < 400; +} + /** * `McpConnectedClient` implementation delegating to the official SDK client. * Construction is lazy: no network until {@link initialize}. @@ -203,25 +245,26 @@ export class SdkMcpAdapter implements McpConnectedClient { { name, arguments: args }, undefined, this.requestOptions(), - )) as { - content?: Array<{ type: string; text?: string; data?: string; mimeType?: string }>; - isError?: boolean; - }; - // Non-task tools (all Bailian MCP tools) resolve to the `content` shape; - // the task shape carries `toolResult` instead and is out of scope here. + )) as McpToolResult; + // The SDK already validates the envelope against CallToolResultSchema; + // only a missing content array is an unexpected shape for our callers. if (!Array.isArray(result.content)) { throw new BailianError("MCP tool returned an unexpected result shape.", ExitCode.GENERAL); } - return { - content: result.content.map((part) => mapContentPart(part)), - ...(result.isError !== undefined ? { isError: result.isError } : {}), - }; + // Returned verbatim (the SDK-validated object): generic consumers such as + // `bl mcp call` keep every standard field (resource / resource_link + // blocks, structuredContent, annotations, …). AIGC-specific extraction + // lives in the business adapter (`aigc-mcp.ts`), not here. + return result; } catch (error) { throw mapSdkError(error); } } - /** Close the transport (fire-and-forget; aborts any background SSE stream). */ + /** + * Close the transport (fire-and-forget; aborts any background SSE stream or + * in-flight handshake, since the transport is published before awaiting). + */ close(): void { const transport = this.transport; this.client = undefined; @@ -256,9 +299,48 @@ export class SdkMcpAdapter implements McpConnectedClient { { capabilities: {} }, ); - await client.connect(transport, this.requestOptions()); - + // Publish the transport before awaiting so close() can abort handshake + // phases the SDK's per-request timeout does not cover (the SSE endpoint + // wait and the initialize/initialized POSTs). this.transport = transport; + + const handshake = client.connect(transport, this.requestOptions()); + // When we give up on the handshake (timeout / close) its later rejection + // must not surface as an unhandled rejection. + handshake.catch(() => undefined); + + let handshakeTimer: ReturnType | undefined; + const handshakeTimeout = new Promise((_, reject) => { + handshakeTimer = setTimeout( + () => + reject( + new BailianError( + `MCP session handshake timed out after ${this.deps.settings.timeout}s.`, + ExitCode.TIMEOUT, + ), + ), + this.deps.settings.timeout * 1000, + ); + }); + + try { + await Promise.race([handshake, handshakeTimeout]); + } catch (error) { + // Cancel the in-flight handshake: abort pending POSTs / SSE streams and + // clear the partial state so a later initialize() starts fresh. + this.transport = undefined; + await transport.close().catch(() => undefined); + throw error; + } finally { + if (handshakeTimer) clearTimeout(handshakeTimer); + } + + if (this.transport !== transport) { + // close() ran while the handshake was finishing; drop the half-open client. + await transport.close().catch(() => undefined); + throw new BailianError("MCP connection was closed during the handshake.", ExitCode.NETWORK); + } + this.client = client; if (this.deps.settings.verbose) { @@ -284,23 +366,3 @@ export class SdkMcpAdapter implements McpConnectedClient { return { timeout: this.deps.settings.timeout * 1000 }; } } - -/** Map an SDK content part onto the loose {@link McpToolResult} content shape. */ -function mapContentPart(part: { type: string; text?: string; data?: string; mimeType?: string }): { - type: string; - text?: string; - data?: string; - mimeType?: string; -} { - if (part.type === "text" && typeof part.text === "string") { - return { type: "text", text: part.text }; - } - if ((part.type === "image" || part.type === "audio") && typeof part.data === "string") { - return { - type: part.type, - data: part.data, - ...(typeof part.mimeType === "string" ? { mimeType: part.mimeType } : {}), - }; - } - return { type: part.type }; -} diff --git a/packages/core/src/client/mcp.ts b/packages/core/src/client/mcp.ts index 280981f42..6fcfb5fad 100644 --- a/packages/core/src/client/mcp.ts +++ b/packages/core/src/client/mcp.ts @@ -25,13 +25,33 @@ export interface McpTool { inputSchema?: Record; } +/** + * One content block of an MCP tool result (text / image / audio / resource / + * resource_link …). Mirrors the standard fields the SDK validation retains; + * the index signature keeps further standard fields visible to consumers. + */ +export interface McpToolResultContent { + type: string; + /** `text` content payload. */ + text?: string; + /** base64 payload of `image` / `audio` content. */ + data?: string; + mimeType?: string; + /** `resource_link` / embedded-resource identifiers. */ + uri?: string; + name?: string; + title?: string; + description?: string; + /** Embedded resource payload of `resource` content. */ + resource?: Record; + annotations?: Record; + [key: string]: unknown; +} + export interface McpToolResult { - content: Array<{ - type: string; - text?: string; - data?: string; - mimeType?: string; - }>; + content: McpToolResultContent[]; + /** Structured tool output carried alongside `content`; preserved verbatim. */ + structuredContent?: Record; isError?: boolean; } diff --git a/packages/core/tests/aigc-mcp.test.ts b/packages/core/tests/aigc-mcp.test.ts index 65a74139a..aaf9d1bf1 100644 --- a/packages/core/tests/aigc-mcp.test.ts +++ b/packages/core/tests/aigc-mcp.test.ts @@ -15,6 +15,10 @@ import { parseAigcTtsResult, parseAigcVideoTaskId, parseAigcVideoTaskResult, + resolveMcpImageSize, + isMcpTtsVoice, + MCP_IMAGE_GEN_RATIO_SIZES, + MCP_TTS_VOICES, } from "../src/client/aigc-mcp.ts"; import type { McpToolResult } from "../src/client/mcp.ts"; @@ -141,6 +145,18 @@ describe("response parsers", () => { parseAigcVideoTaskResult({ task_status: "SUCCEEDED", video_url: "https://x/v.mp4" }), ).toEqual({ taskStatus: "SUCCEEDED", videoUrl: "https://x/v.mp4" }); expect(parseAigcVideoTaskResult({})).toEqual({ taskStatus: "UNKNOWN" }); + // 失败原因原样保留,供命令层透传。 + expect( + parseAigcVideoTaskResult({ + task_status: "FAILED", + task_id: "t1", + message: "boom", + code: "E1", + }), + ).toEqual({ taskStatus: "FAILED", taskId: "t1", message: "boom", code: "E1" }); + expect(parseAigcVideoTaskResult({ task_status: "FAILED", message: "" })).toEqual({ + taskStatus: "FAILED", + }); }); test("parseAigcAsrTexts keeps only string entries", () => { @@ -149,3 +165,29 @@ describe("response parsers", () => { expect(parseAigcAsrTexts({})).toEqual([]); }); }); + +describe("MCP input contract mapping", () => { + test("resolveMcpImageSize maps ratios onto the server pixel presets", () => { + expect(resolveMcpImageSize("16:9")).toBe(MCP_IMAGE_GEN_RATIO_SIZES["16:9"]); + expect(resolveMcpImageSize("1:1")).toBe("1328*1328"); + expect(resolveMcpImageSize("9:16")).toBe("928*1664"); + }); + + test("resolveMcpImageSize passes pixel input through (x normalized to *)", () => { + expect(resolveMcpImageSize("2048*2048")).toBe("2048*2048"); + expect(resolveMcpImageSize("1024x768")).toBe("1024*768"); + }); + + test("resolveMcpImageSize rejects values MCP cannot accept", () => { + expect(resolveMcpImageSize("2:3")).toBeUndefined(); + expect(resolveMcpImageSize("huge")).toBeUndefined(); + expect(resolveMcpImageSize("")).toBeUndefined(); + }); + + test("isMcpTtsVoice accepts only the live schema enum", () => { + expect(MCP_TTS_VOICES).toContain("温柔女声"); + expect(isMcpTtsVoice("温柔女声")).toBe(true); + expect(isMcpTtsVoice("longxiaochun_v3")).toBe(false); + expect(isMcpTtsVoice("")).toBe(false); + }); +}); diff --git a/packages/core/tests/image-input.test.ts b/packages/core/tests/image-input.test.ts index 48214312c..903b27d91 100644 --- a/packages/core/tests/image-input.test.ts +++ b/packages/core/tests/image-input.test.ts @@ -90,3 +90,42 @@ describe("Token Plan image input compatibility", () => { ); }); }); + +describe("Token Plan connection detection", () => { + const STANDARD = "https://dashscope.aliyuncs.com"; + const PLAN = "https://token-plan.cn-beijing.maas.aliyuncs.com"; + + function makeClientWithKey(baseUrl: string, token: string): Client { + return new Client({ + identity: { + binName: "bl", + version: "test", + npmPackage: "bailian-cli", + clientName: "bailian-cli-test", + }, + settings: makeSettings(), + baseUrl, + apiCred: { token, baseUrl, source: "env" }, + }); + } + + test("plan key on a token-plan endpoint is a Token Plan connection", () => { + expect(makeClientWithKey(PLAN, "sk-sp-plan").usesTokenPlanConnection()).toBe(true); + }); + + test("plan key on the standard endpoint is a Token Plan connection", () => { + expect(makeClientWithKey(STANDARD, "sk-sp-plan").usesTokenPlanConnection()).toBe(true); + }); + + test("standard key on a token-plan endpoint is a Token Plan connection", () => { + expect(makeClientWithKey(PLAN, "sk-standard").usesTokenPlanConnection()).toBe(true); + }); + + test("standard key on the standard endpoint is not", () => { + expect(makeClientWithKey(STANDARD, "sk-standard").usesTokenPlanConnection()).toBe(false); + }); + + test("missing credential on the standard endpoint is not", () => { + expect(makeClient(STANDARD).usesTokenPlanConnection()).toBe(false); + }); +}); diff --git a/packages/core/tests/mcp.test.ts b/packages/core/tests/mcp.test.ts index 51f456255..9bb56ae72 100644 --- a/packages/core/tests/mcp.test.ts +++ b/packages/core/tests/mcp.test.ts @@ -11,7 +11,7 @@ import { isStreamableHttpUnsupported, isUrlOverrideSseFallbackCandidate, } from "../src/index.ts"; -import { SdkMcpAdapter, mapSdkError } from "../src/client/mcp-sdk.ts"; +import { McpClient, SdkMcpAdapter, mapSdkError } from "../src/client/mcp-sdk.ts"; function testDeps(overrides?: Partial): { identity: Identity; settings: Settings } { return { @@ -221,6 +221,76 @@ test("SdkMcpAdapter:serviceSource 覆写 X-Dashscope-Service(AIGC auto → b } }); +test("SdkMcpAdapter:握手挂死时整体超时为 TIMEOUT 并清理状态可重试", async () => { + const originalFetch = globalThis.fetch; + let calls = 0; + // 挂死:不 resolve 也不 reject,模拟服务端吞掉 initialize POST。 + globalThis.fetch = () => { + calls += 1; + return new Promise(() => undefined); + }; + + try { + const adapter = new SdkMcpAdapter({ + deps: testDeps({ timeout: 1 }), + url: "https://example.test/api/v1/mcps/WebParser/mcp", + authToken: "sk-test", + transport: "streamable", + }); + const firstError = await adapter.initialize().catch((caught) => caught); + expect(firstError).toBeInstanceOf(BailianError); + expect((firstError as BailianError).exitCode).toBe(ExitCode.TIMEOUT); + expect((firstError as BailianError).message).toContain("handshake timed out"); + expect(calls).toBeGreaterThan(0); + + // 失败后状态已清理:再次 initialize() 重新发起握手,而非复用挂死的 promise。 + const secondError = await adapter.initialize().catch((caught) => caught); + expect((secondError as BailianError).exitCode).toBe(ExitCode.TIMEOUT); + expect(calls).toBeGreaterThan(1); + adapter.close(); + } finally { + globalThis.fetch = originalFetch; + } +}); + +test("SdkMcpAdapter:握手期间 close() abort 在途请求并使 initialize 结束", async () => { + const originalFetch = globalThis.fetch; + const signals: Array = []; + + globalThis.fetch = (_input, init) => + new Promise((_resolve, reject) => { + signals.push(init?.signal); + init?.signal?.addEventListener("abort", () => reject(new Error("fetch aborted")), { + once: true, + }); + }); + + try { + const adapter = new SdkMcpAdapter({ + deps: testDeps({ timeout: 30 }), + url: "https://example.test/api/v1/mcps/WebParser/mcp", + authToken: "sk-test", + transport: "streamable", + }); + const pending = adapter.initialize(); + // 等待首个请求进入 fetch 拦截器。 + for (let tick = 0; tick < 50 && signals.length === 0; tick += 1) { + await new Promise((resolve) => setTimeout(resolve, 5)); + } + expect(signals.length).toBeGreaterThan(0); + + adapter.close(); + + const error = await pending.catch((caught) => caught); + // close() 使 SDK 以 ConnectionClosed 拒绝挂起的握手请求,映射为 NETWORK。 + expect(error).toBeInstanceOf(BailianError); + expect((error as BailianError).exitCode).toBe(ExitCode.NETWORK); + expect(signals.some((signal) => signal?.aborted)).toBe(true); + } finally { + globalThis.fetch = originalFetch; + } +}); + test("SdkMcpAdapter:无 token 时 initialize 抛 AUTH(不发请求)", async () => { const originalFetch = globalThis.fetch; let called = false; @@ -309,6 +379,147 @@ test("SdkMcpAdapter:listTools 与 callTool 结果映射回 McpTool / McpToolRe } }); +test("SdkMcpAdapter:callTool 原样保留 resource / resource_link 与 structuredContent", async () => { + const originalFetch = globalThis.fetch; + + globalThis.fetch = async (_input, init) => { + const body = parseBody(init); + if (body.method === "initialize") { + return jsonResponse(jsonRpc(body.id!, INIT_RESULT)); + } + if (body.method === "tools/call") { + return jsonResponse( + jsonRpc(body.id!, { + content: [ + { type: "text", text: "summary" }, + { type: "resource_link", uri: "https://x/doc", name: "doc", title: "Doc" }, + { + type: "resource", + resource: { uri: "https://x/r", mimeType: "text/plain", text: "body" }, + }, + ], + structuredContent: { total: 1 }, + isError: false, + }), + ); + } + return new Response(null, { status: 200 }); + }; + + try { + const adapter = new SdkMcpAdapter({ + deps: testDeps(), + url: "https://example.test/mcp", + authToken: "sk-test", + transport: "streamable", + }); + await adapter.initialize(); + + const result = await adapter.callTool("some_tool", {}); + expect(result.content).toEqual([ + { type: "text", text: "summary" }, + { type: "resource_link", uri: "https://x/doc", name: "doc", title: "Doc" }, + { + type: "resource", + resource: { uri: "https://x/r", mimeType: "text/plain", text: "body" }, + }, + ]); + expect(result.structuredContent).toEqual({ total: 1 }); + expect(result.isError).toBe(false); + adapter.close(); + } finally { + globalThis.fetch = originalFetch; + } +}); + +test("SdkMcpAdapter:同源 307 重定向交给 SDK 跟随并完成握手", async () => { + const originalFetch = globalThis.fetch; + const seenUrls: string[] = []; + + globalThis.fetch = async (input, init) => { + const url = requestUrl(input); + seenUrls.push(url); + const body = parseBody(init); + if (url.endsWith("/mcp2")) { + if (body.method === "initialize") { + return jsonResponse(jsonRpc(body.id!, INIT_RESULT)); + } + return new Response(null, { status: 202 }); + } + // /mcp:同源 307 到 /mcp2,由 SDK 的同源重定向策略跟随。 + return new Response(null, { + status: 307, + headers: { Location: "https://example.test/mcp2" }, + }); + }; + + try { + const adapter = new SdkMcpAdapter({ + deps: testDeps(), + url: "https://example.test/mcp", + authToken: "sk-test", + transport: "streamable", + }); + await adapter.initialize(); + + expect(seenUrls).toContain("https://example.test/mcp"); + expect(seenUrls).toContain("https://example.test/mcp2"); + adapter.close(); + } finally { + globalThis.fetch = originalFetch; + } +}); + +test("SdkMcpAdapter:跨源 307 不被跟随,保留 `MCP request failed: ` 文案", async () => { + const originalFetch = globalThis.fetch; + + globalThis.fetch = async () => + new Response(null, { + status: 307, + headers: { Location: "https://other.test/mcp" }, + }); + + try { + const adapter = new SdkMcpAdapter({ + deps: testDeps(), + url: "https://example.test/mcp", + authToken: "sk-test", + transport: "streamable", + }); + const error = await adapter.initialize().catch((caught) => caught); + + expect(error).toBeInstanceOf(BailianError); + expect((error as BailianError).message).toMatch(/^MCP request failed: 307/); + } finally { + globalThis.fetch = originalFetch; + } +}); + +test("McpClient 兼容导出:原构造签名委托 SdkMcpAdapter 完成调用", async () => { + const originalFetch = globalThis.fetch; + + globalThis.fetch = async (_input, init) => { + const body = parseBody(init); + if (body.method === "initialize") { + return jsonResponse(jsonRpc(body.id!, INIT_RESULT)); + } + if (body.method === "tools/call") { + return jsonResponse(jsonRpc(body.id!, { content: [{ type: "text", text: "hi" }] })); + } + return new Response(null, { status: 200 }); + }; + + try { + const client = new McpClient(testDeps(), "https://example.test/mcp", "sk-test"); + await client.initialize(); + const result = await client.callTool("some_tool", {}); + expect(result.content[0]).toEqual({ type: "text", text: "hi" }); + client.close(); + } finally { + globalThis.fetch = originalFetch; + } +}); + test("SdkMcpAdapter:HTTP 4xx POST 复刻 `MCP request failed: - ` 文案契约", async () => { const originalFetch = globalThis.fetch; From 460d700a08242a7990bc276a6123f9d1569bc4c3 Mon Sep 17 00:00:00 2001 From: wangmingxiang Date: Thu, 29 Oct 2026 10:19:12 +0800 Subject: [PATCH 4/6] =?UTF-8?q?fix(core):=20=E4=BF=AE=E5=A4=8D=20SSE=20?= =?UTF-8?q?=E6=B5=81=20GET=20=E5=A4=B1=E8=B4=A5=E6=97=B6=E7=9A=84=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E6=B6=88=E6=81=AF=E9=87=8D=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 image/edit.ts 中对 resolveAutoImageInput 的 localize 参数 - 简化 aigc-mcp.ts 中 resolveAutoImageInput 和 resolveAutoAudioInput 的参数,取消 localize - 调整 MCP 错误提示文案,使 "auto" 模型失败时提示更清晰 - core/client/mcp-sdk.ts 中增加对经典 SSE 流 GET 失败的捕获与状态体重建 - mapSdkError 函数支持通过捕获的 SSE GET 失败信息重建错误消息 - SdkMcpAdapter 内部保存并使用 SSE GET 失败信息映射错误 - 在 fetch 拦截中,当 SSE GET 非 2xx 返回时读取响应体并传递供错误重建使用 - 添加多个测试覆盖包括 SseError 结合 SSE GET 失败的错误映射及适配器流程测试 --- packages/commands/src/commands/image/edit.ts | 2 +- .../commands/src/commands/shared/aigc-mcp.ts | 41 +++------ .../commands/src/commands/speech/recognize.ts | 2 +- .../commands/src/commands/video/generate.ts | 2 +- packages/core/src/client/mcp-sdk.ts | 92 ++++++++++++++++--- packages/core/tests/mcp.test.ts | 83 ++++++++++++++++- 6 files changed, 177 insertions(+), 45 deletions(-) diff --git a/packages/commands/src/commands/image/edit.ts b/packages/commands/src/commands/image/edit.ts index 1b23d4d31..e56ee9656 100644 --- a/packages/commands/src/commands/image/edit.ts +++ b/packages/commands/src/commands/image/edit.ts @@ -385,7 +385,7 @@ async function handleAutoMcpMode( throw new BailianError("Provide one --image to edit.", ExitCode.USAGE); } - const imageUrl = resolveAutoImageInput(source, localize); + const imageUrl = resolveAutoImageInput(source); const concurrent = getConcurrency(flags); const args = buildImageEditArgs({ imageUrl, diff --git a/packages/commands/src/commands/shared/aigc-mcp.ts b/packages/commands/src/commands/shared/aigc-mcp.ts index 58c606dc3..81e6175a2 100644 --- a/packages/commands/src/commands/shared/aigc-mcp.ts +++ b/packages/commands/src/commands/shared/aigc-mcp.ts @@ -268,47 +268,30 @@ export function assertMcpTtsVoice(voice: string, localize: Localize): void { // ---- Local file input (auto mode inlines files as base64 data URIs) ---- -/** - * Conservative cap on the inline base64 data-URI size sent through MCP. The - * AIGC MCP servers accept a public http(s) URL or a base64 data URI but reject - * `oss://` and private upload URLs, so `auto` mode inlines local files; an - * oversized payload would bloat the JSON-RPC body and fail obscurely, so it is - * rejected up front with an actionable message. - */ -const MAX_MCP_DATA_URI_BYTES = 10 * 1024 * 1024; - /** True for inputs already carrying a URL / inline scheme (not a local path). */ function isUrlScheme(source: string): boolean { return /^(https?|oss|data):/i.test(source); } -function guardDataUriSize(dataUri: string, kind: "image" | "audio", localize: Localize): string { - if (dataUri.length <= MAX_MCP_DATA_URI_BYTES) return dataUri; - const message = localize({ - "en-US": `The local ${kind} file is too large to inline through MCP in auto mode (limit ~10 MB after base64 encoding). Host it at a public http(s) URL, or switch to a specific --model.`, - "zh-CN": `本地${kind === "image" ? "图片" : "音频"}文件过大,无法在 auto 模式下通过 MCP 内联发送(base64 编码后上限约 10 MB)。请将其托管为公网 http(s) URL,或切换为具体的 --model。`, - }); - const hint = localize({ - "en-US": - "Pass a public http(s) URL instead of a local path, or use --model to switch to the REST path.", - "zh-CN": "请传入公网 http(s) URL 而非本地路径,或使用 --model 切换回 REST。", - }); - throw new BailianError(message, ExitCode.USAGE, hint); -} - /** * Resolve an `auto`-mode image input: local paths are inlined as base64 data * URIs; http(s) URLs and data URIs pass through verbatim. + * + * Files are inlined rather than uploaded because the AIGC MCP servers reject + * `oss://` and cannot fetch private upload URLs. The inline payload is + * deliberately not capped on this side: how large a data URI is acceptable is + * the server's own contract, so an oversized one surfaces as a server error + * passed through verbatim (AGENTS.md §3) instead of a client-side guess. */ -export function resolveAutoImageInput(source: string, localize: Localize): string { +export function resolveAutoImageInput(source: string): string { if (isUrlScheme(source)) return source; - return guardDataUriSize(imageFileToDataUri(source), "image", localize); + return imageFileToDataUri(source); } /** Resolve an `auto`-mode audio input the same way (ASR `file_urls`). */ -export function resolveAutoAudioInput(source: string, localize: Localize): string { +export function resolveAutoAudioInput(source: string): string { if (isUrlScheme(source)) return source; - return guardDataUriSize(audioFileToDataUri(source), "audio", localize); + return audioFileToDataUri(source); } // ---- Shared-session MCP call wrapper ---- @@ -333,9 +316,9 @@ function withAutoModelHint(error: unknown, localize: Localize): never { ) { const hint = localize({ "en-US": - 'MCP generation failed. To use the REST path instead, run with a specific --model (or set a concrete default model instead of "auto").', + "The current model (auto) failed to generate. Retry with a specific --model (or set a concrete default model).", "zh-CN": - 'MCP 生成失败。如需改走 REST,请使用具体的 --model (或将默认模型设为具体值而非 "auto")。', + "当前模型(auto)生成失败,请使用具体的 --model (或将默认模型设为具体值)进行重试。", }); throw new BailianError(error.message, error.exitCode, hint, { cause: error, diff --git a/packages/commands/src/commands/speech/recognize.ts b/packages/commands/src/commands/speech/recognize.ts index f6441fbf7..8b2e46e8d 100644 --- a/packages/commands/src/commands/speech/recognize.ts +++ b/packages/commands/src/commands/speech/recognize.ts @@ -361,7 +361,7 @@ async function handleAutoMcpMode( // Public http(s)/oss URLs pass through; local files become inline base64 data // URIs (the MCP server rejects oss:// and cannot fetch private uploads). - const fileUrls = rawUrls.map((source) => resolveAutoAudioInput(source, localize)); + const fileUrls = rawUrls.map((source) => resolveAutoAudioInput(source)); const args = buildSpeechToTextArgs(fileUrls); if (settings.dryRun) { diff --git a/packages/commands/src/commands/video/generate.ts b/packages/commands/src/commands/video/generate.ts index a56e4eaac..979e5b680 100644 --- a/packages/commands/src/commands/video/generate.ts +++ b/packages/commands/src/commands/video/generate.ts @@ -227,7 +227,7 @@ export default defineCommand({ const duration = flags.duration || undefined; const resolution = flags.resolution || undefined; const firstFrameUrl = - imageInput !== undefined ? resolveAutoImageInput(imageInput, ctx.localize) : undefined; + imageInput !== undefined ? resolveAutoImageInput(imageInput) : undefined; const submitTool = imageInput !== undefined ? AIGC_MCP_TOOL.imageToVideoSubmit diff --git a/packages/core/src/client/mcp-sdk.ts b/packages/core/src/client/mcp-sdk.ts index dd7ce9008..1eeaa6186 100644 --- a/packages/core/src/client/mcp-sdk.ts +++ b/packages/core/src/client/mcp-sdk.ts @@ -13,6 +13,9 @@ * - `MCP request failed: - ` message contract for * HTTP transport failures, which `isStreamableHttpUnsupported`, * `isUrlOverrideSseFallbackCandidate` and the MCP-not-activated hint rely on. + * Classic SSE stream GET failures carry the same contract: `eventsource` + * drops non-200 GET bodies, so the interceptor captures status/body and + * `mapSdkError` rebuilds the message from the SDK's `SseError`. * - `MCP error (): ` for JSON-RPC business errors (passthrough). * - Raw `TypeError` (e.g. ENOTFOUND) propagation so runtime can surface errno. */ @@ -22,7 +25,7 @@ import { StreamableHTTPClientTransport, StreamableHTTPError, } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; -import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; +import { SSEClientTransport, SseError } from "@modelcontextprotocol/sdk/client/sse.js"; import { ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js"; import type { FetchLike, Transport } from "@modelcontextprotocol/sdk/shared/transport.js"; @@ -90,10 +93,16 @@ export interface SdkMcpAdapterOptions { * (message passed through verbatim per AGENTS.md §3). * - `StreamableHTTPError` (HTTP status in `.code`) → GENERAL with the * `MCP request failed: ` shape so the fallback detectors still match. + * - `SseError` (classic SSE): when the fetch interceptor captured the failing + * stream GET (`sseGetFailure` with a matching status), rebuild the + * `MCP request failed: - ` contract — the SDK's + * own message only carries `Non-200 status code ()` and would lose + * the server body the MCP-not-activated hint matches on. Without a captured + * failure (e.g. a mid-stream drop) the error passes through unchanged. * - Anything else (e.g. a `TypeError` from `fetch`) is returned unchanged so the * runtime keeps its errno-specific handling. */ -export function mapSdkError(error: unknown): unknown { +export function mapSdkError(error: unknown, sseGetFailure?: SseGetFailure): unknown { if (error instanceof BailianError) return error; if (error instanceof McpError) { @@ -115,6 +124,15 @@ export function mapSdkError(error: unknown): unknown { }); } + if (error instanceof SseError && sseGetFailure && sseGetFailure.status === error.code) { + let message = `MCP request failed: ${sseGetFailure.status} ${sseGetFailure.statusText}`; + if (sseGetFailure.body) message += ` - ${sseGetFailure.body.slice(0, 500)}`; + return new BailianError(message, ExitCode.GENERAL, undefined, { + api: { httpStatus: sseGetFailure.status }, + cause: error, + }); + } + return error; } @@ -131,17 +149,35 @@ function rawMcpMessage(error: McpError): string { return error.message.startsWith(prefix) ? error.message.slice(prefix.length) : error.message; } +/** + * Server-side failure of a classic SSE stream GET, captured by the fetch + * interceptor before `eventsource` discards the body (it only reports + * `Non-200 status code ()` and never reads the payload). + * `mapSdkError` rebuilds the HTTP-failure contract from it. + */ +export interface SseGetFailure { + status: number; + statusText: string; + body: string; +} + /** * Build the transport-level fetch. It reproduces the old client's error contract * for message POSTs and mirrors its `--verbose` wire logging. GET responses are * passed through untouched so the SDK's own SSE-stream handling (including the - * tolerated 405 on a standalone Streamable GET) stays intact. Redirect responses - * are likewise passed through: the SDK wraps this fetch with its same-origin - * redirect policy (`fetchWithinOrigin`) and must see the 3xx to follow or - * reject it itself — intercepting it here would break same-origin redirects - * the old client's default `redirect: "follow"` used to honor. + * tolerated 405 on a standalone Streamable GET) stays intact — except that a + * failing classic SSE stream GET has its status/body captured first, since + * `eventsource` would drop them. Redirect responses are likewise passed through: + * the SDK wraps this fetch with its same-origin redirect policy + * (`fetchWithinOrigin`) and must see the 3xx to follow or reject it itself — + * intercepting it here would break same-origin redirects the old client's + * default `redirect: "follow"` used to honor. */ -function createMcpFetch(deps: HttpDeps): FetchLike { +function createMcpFetch( + deps: HttpDeps, + kind: SdkMcpTransportKind, + onSseGetFailure?: (failure: SseGetFailure) => void, +): FetchLike { return async (url, init) => { const method = init?.method ?? "GET"; const target = typeof url === "string" ? url : url.href; @@ -175,6 +211,28 @@ function createMcpFetch(deps: HttpDeps): FetchLike { throw new BailianError(message, ExitCode.GENERAL); } + if ( + kind === "sse" && + onSseGetFailure && + !response.ok && + method === "GET" && + !isRedirectStatus(response.status) + ) { + // Classic SSE: this GET *is* the connection stream. `eventsource` fails + // non-200 responses with `Non-200 status code ()` without ever + // reading the body, and the SDK rewraps that as `SseError` — losing the + // server payload (e.g. MCP_IS_INVALID) the not-activated hint matches on. + // Drain it here and hand it to the adapter; returning the drained + // response is safe because neither transport reads a non-2xx GET body. + let body = ""; + try { + body = await response.text(); + } catch { + /* body already consumed or unreadable */ + } + onSseGetFailure({ status: response.status, statusText: response.statusText, body }); + } + return response; }; } @@ -198,6 +256,8 @@ export class SdkMcpAdapter implements McpConnectedClient { private client: Client | undefined; private transport: Transport | undefined; private connecting: Promise | undefined; + /** Last failed classic SSE stream GET, for `SseError` contract reconstruction. */ + private sseGetFailure: SseGetFailure | undefined; constructor(options: SdkMcpAdapterOptions) { this.deps = options.deps; @@ -216,7 +276,7 @@ export class SdkMcpAdapter implements McpConnectedClient { this.connecting = this.connect().catch((error) => { // Allow a later initialize() to retry on the same instance. this.connecting = undefined; - throw mapSdkError(error); + throw this.mapTransportError(error); }); } return this.connecting; @@ -234,7 +294,7 @@ export class SdkMcpAdapter implements McpConnectedClient { : {}), })); } catch (error) { - throw mapSdkError(error); + throw this.mapTransportError(error); } } @@ -257,7 +317,7 @@ export class SdkMcpAdapter implements McpConnectedClient { // lives in the business adapter (`aigc-mcp.ts`), not here. return result; } catch (error) { - throw mapSdkError(error); + throw this.mapTransportError(error); } } @@ -270,6 +330,7 @@ export class SdkMcpAdapter implements McpConnectedClient { this.client = undefined; this.transport = undefined; this.connecting = undefined; + this.sseGetFailure = undefined; if (transport) { void transport.close().catch(() => undefined); } @@ -277,6 +338,11 @@ export class SdkMcpAdapter implements McpConnectedClient { // ---- Internal ---- + /** `mapSdkError` with this adapter's captured classic SSE GET failure. */ + private mapTransportError(error: unknown): unknown { + return mapSdkError(error, this.sseGetFailure); + } + private async connect(): Promise { const headers: Record = { "User-Agent": `${this.deps.identity.clientName}/${this.deps.identity.version}`, @@ -284,7 +350,9 @@ export class SdkMcpAdapter implements McpConnectedClient { Authorization: `Bearer ${this.authToken}`, }; - const mcpFetch = createMcpFetch(this.deps); + const mcpFetch = createMcpFetch(this.deps, this.kind, (failure) => { + this.sseGetFailure = failure; + }); const endpoint = new URL(this.url); const transport = this.kind === "sse" diff --git a/packages/core/tests/mcp.test.ts b/packages/core/tests/mcp.test.ts index 9bb56ae72..795724b20 100644 --- a/packages/core/tests/mcp.test.ts +++ b/packages/core/tests/mcp.test.ts @@ -1,6 +1,7 @@ import { expect, test } from "vite-plus/test"; import { ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js"; import { StreamableHTTPError } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; +import { SseError } from "@modelcontextprotocol/sdk/client/sse.js"; import type { Identity, Settings } from "../src/index.ts"; import { BailianError, @@ -11,7 +12,12 @@ import { isStreamableHttpUnsupported, isUrlOverrideSseFallbackCandidate, } from "../src/index.ts"; -import { McpClient, SdkMcpAdapter, mapSdkError } from "../src/client/mcp-sdk.ts"; +import { + McpClient, + SdkMcpAdapter, + mapSdkError, + type SseGetFailure, +} from "../src/client/mcp-sdk.ts"; function testDeps(overrides?: Partial): { identity: Identity; settings: Settings } { return { @@ -142,6 +148,27 @@ test("mapSdkError:超时/连接关闭映射 ExitCode;服务端 JSON-RPC 错 expect(mapSdkError(typeError)).toBe(typeError); }); +test("mapSdkError:SseError 结合捕获的 SSE GET 失败重建文案契约;无捕获时原样返回", () => { + const sseError = new SseError(404, "Non-200 status code (404)", {} as never); + const failure: SseGetFailure = { + status: 404, + statusText: "Not Found", + body: "MCP不存在或未开通", + }; + const mapped = mapSdkError(sseError, failure); + expect(mapped).toBeInstanceOf(BailianError); + expect((mapped as BailianError).message).toBe( + "MCP request failed: 404 Not Found - MCP不存在或未开通", + ); + expect((mapped as BailianError).exitCode).toBe(ExitCode.GENERAL); + expect((mapped as BailianError).api?.httpStatus).toBe(404); + + // Status mismatch (stale capture) and missing capture pass through untouched. + const stale = mapSdkError(sseError, { status: 500, statusText: "", body: "x" }); + expect(stale).toBe(sseError); + expect(mapSdkError(sseError)).toBe(sseError); +}); + // ---- SdkMcpAdapter (streamable) ---- test("SdkMcpAdapter:注入 Authorization / User-Agent / 追踪头,并发送 clientInfo", async () => { @@ -542,6 +569,29 @@ test("SdkMcpAdapter:HTTP 4xx POST 复刻 `MCP request failed: - { + const originalFetch = globalThis.fetch; + + globalThis.fetch = async () => + new Response("MCP_IS_INVALID", { status: 404, statusText: "Not Found" }); + + try { + const adapter = new SdkMcpAdapter({ + deps: testDeps(), + url: "https://example.test/sse", + authToken: "sk-test", + transport: "sse", + }); + const error = await adapter.initialize().catch((reason: unknown) => reason); + expect(error).toBeInstanceOf(BailianError); + expect((error as BailianError).message).toMatch(/^MCP request failed:\s*404\b/); + expect((error as BailianError).message).toContain("MCP_IS_INVALID"); + expect((error as BailianError).api?.httpStatus).toBe(404); + } finally { + globalThis.fetch = originalFetch; + } +}); + // ---- connectBailianMcpWithFallback orchestration ---- test("connectBailianMcpWithFallback:成功走 Streamable", async () => { @@ -689,6 +739,37 @@ test("connectBailianMcpWithFallback:405 降级到经典 SSE 并连接成功", } }); +test("connectBailianMcpWithFallback:405 降级后经典 SSE GET 4xx 仍保留正文(开通提示契约)", async () => { + const originalFetch = globalThis.fetch; + const urls: string[] = []; + + globalThis.fetch = async (input, init) => { + const url = requestUrl(input); + const method = init?.method ?? "GET"; + urls.push(`${method} ${url}`); + if (url.endsWith("/mcp")) { + return new Response("Method Not Allowed", { status: 405, statusText: "Method Not Allowed" }); + } + return new Response("MCP不存在或未开通", { status: 404, statusText: "Not Found" }); + }; + + try { + const error = await connectBailianMcpWithFallback({ + deps: testDeps(), + authToken: "sk-test", + httpUrl: "https://example.test/api/v1/mcps/WebParser/mcp", + sseUrl: "https://example.test/api/v1/mcps/WebParser/sse", + serverCode: "WebParser", + }).catch((reason: unknown) => reason); + expect(error).toBeInstanceOf(BailianError); + expect((error as BailianError).message).toMatch(/^MCP request failed:\s*404\b/); + expect((error as BailianError).message).toContain("MCP不存在或未开通"); + expect(urls.some((entry) => entry.startsWith("GET ") && entry.includes("/sse"))).toBe(true); + } finally { + globalThis.fetch = originalFetch; + } +}); + test("connectBailianMcpWithFallback:--url 覆盖,POST 405 后同 URL GET SSE 降级", async () => { const originalFetch = globalThis.fetch; const urls: string[] = []; From a1fa4780b955fa77a7bbbd5defd56d20fb201ac9 Mon Sep 17 00:00:00 2001 From: wangmingxiang Date: Thu, 29 Oct 2026 17:01:04 +0800 Subject: [PATCH 5/6] =?UTF-8?q?fix(mcp):=20=E6=AD=A3=E7=A1=AE=E5=85=B3?= =?UTF-8?q?=E9=97=AD=20MCP=20=E8=BF=9E=E6=8E=A5=E5=B9=B6=E6=94=B9=E8=BF=9B?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E6=98=A0=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 search/web 命令中添加 finally 关闭 MCP 客户端,防止进程挂起 - add e2e 测试用例,覆盖 MCP WebSearch 工具调用和 auto 模式图像编辑及语音识别 - 修改 MCP SDK 错误映射,区分本地计时器超时与服务端错误,避免误判重试 - 扩展 McpTool 类型,支持多个新字段以保留服务器行为注解和输出模式 - 更新 MCP 相关测试,确保错误映射逻辑和工具字段校验的准确性 --- packages/commands/src/commands/search/web.ts | 11 +++- .../tests/e2e/aigc-auto-mcp.e2e.test.ts | 61 +++++++++++++++++++ packages/commands/tests/e2e/mcp.e2e.test.ts | 18 ++++++ .../commands/tests/e2e/search-web.e2e.test.ts | 15 +++++ packages/core/src/client/mcp-sdk.ts | 45 ++++++++++---- packages/core/src/client/mcp.ts | 10 +++ packages/core/tests/mcp.test.ts | 40 ++++++++++++ 7 files changed, 187 insertions(+), 13 deletions(-) diff --git a/packages/commands/src/commands/search/web.ts b/packages/commands/src/commands/search/web.ts index eab3e1143..7d3426833 100644 --- a/packages/commands/src/commands/search/web.ts +++ b/packages/commands/src/commands/search/web.ts @@ -4,6 +4,7 @@ import { detectOutputFormat, mcpWebSearchPath, type FlagsDef, + type McpConnectedClient, } from "bailian-cli-core"; import { createSpinner, emitResult } from "bailian-cli-runtime"; import { rethrowWithWebSearchActivateHint } from "./web-activate-hint.ts"; @@ -66,13 +67,18 @@ export default defineCommand({ return; } + let client: McpConnectedClient | undefined; try { - const client = ctx.client.mcp(mcpWebSearchPath()); + client = ctx.client.mcp(mcpWebSearchPath()); await client.initialize(); const tools = await client.listTools(); emitResult({ tools }, format); } catch (error) { rethrowWithWebSearchActivateHint(error); + } finally { + // The SDK transport keeps a live SSE stream / pending sockets open; + // without closing it the process never exits after emitting results. + client?.close?.(); } return; } @@ -152,6 +158,9 @@ export default defineCommand({ } catch (error) { spinner.stop("Failed."); rethrowWithWebSearchActivateHint(error); + } finally { + // Close on both paths: an open transport stream keeps the process alive. + client.close?.(); } }, }); diff --git a/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts b/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts index a86ca113a..8d28cb5cf 100644 --- a/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts +++ b/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts @@ -418,6 +418,67 @@ describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())( expect(data.audio_url?.length ?? 0).toBeGreaterThan(0); expect(data.voice).toBe("温柔女声"); }, 180_000); + + test("【auto】image edit 真实经 MCP(bailian_image_edit) 内联本地图并落地", async () => { + // Self-contained chain: generate a source image first (local path exercises + // the auto-mode base64 data-URI inlining against the live server). + const outDir = makeE2eOutputDir("aigc-auto-live-image-edit"); + const generated = await runCommandE2e(AUTO_ROUTES, [ + "image", + "generate", + "--model", + "auto", + "--prompt", + "一个红色圆点,白底", + "--out-dir", + outDir, + "--out-prefix", + "e2e-auto-edit-src", + "--output", + "json", + ]); + expect(generated.exitCode, generated.stderr).toBe(0); + const sourceImage = parseStdoutJson<{ saved?: string[] }>(generated.stdout).saved?.[0]; + expect(sourceImage).toBeDefined(); + + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "image", + "edit", + "--model", + "auto", + "--image", + sourceImage!, + "--prompt", + "把红色圆点改成蓝色圆点", + "--out-dir", + outDir, + "--out-prefix", + "e2e-auto-edit-out", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson<{ saved?: string[]; total?: number }>(stdout); + expect(data.saved?.length ?? 0).toBeGreaterThan(0); + expect(data.saved?.[0]).toContain("e2e-auto-edit-out"); + }, 600_000); + + test("【auto】speech recognize 真实经 MCP(bailian_speech_to_text) 转写公网音频", async () => { + // The live MCP ASR server only transcribes public http(s) URLs now: + // data-URI input returns an empty transcript without error, so the live + // case feeds the official sample audio instead of a local file. + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "speech", + "recognize", + "--model", + "auto", + "--url", + "https://dashscope.oss-cn-beijing.aliyuncs.com/samples/audio/paraformer/hello_world_female2.wav", + ]); + expect(exitCode, stderr).toBe(0); + // The auto ASR branch emits bare transcript lines on stdout. + expect(stdout).toContain("hello world"); + }, 300_000); }, ); diff --git a/packages/commands/tests/e2e/mcp.e2e.test.ts b/packages/commands/tests/e2e/mcp.e2e.test.ts index 70bc84843..ebbeb7def 100644 --- a/packages/commands/tests/e2e/mcp.e2e.test.ts +++ b/packages/commands/tests/e2e/mcp.e2e.test.ts @@ -437,4 +437,22 @@ describe.skipIf(!isDashScopeE2EReady())("e2e: mcp (live)", () => { expect(data.tools?.length ?? 0).toBeGreaterThan(0); expect(data.tools?.some((t) => t.name === "bailian_web_search")).toBe(true); }, 60_000); + + test("mcp call 真实调用内置 WebSearch 工具并原样返回 content", async () => { + const { stdout, stderr, exitCode } = await runCommandE2e(MCP_ROUTES, [ + "mcp", + "call", + "--target", + "WebSearch.bailian_web_search", + "--query", + "阿里云百炼", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson<{ content?: Array<{ type?: string; text?: string }> }>(stdout); + expect(data.content?.length ?? 0).toBeGreaterThan(0); + expect(data.content?.[0]?.type).toBe("text"); + expect((data.content?.[0]?.text ?? "").length).toBeGreaterThan(0); + }, 120_000); }); diff --git a/packages/commands/tests/e2e/search-web.e2e.test.ts b/packages/commands/tests/e2e/search-web.e2e.test.ts index d0c02789e..c924e10e8 100644 --- a/packages/commands/tests/e2e/search-web.e2e.test.ts +++ b/packages/commands/tests/e2e/search-web.e2e.test.ts @@ -92,4 +92,19 @@ describe.skipIf(!isDashScopeE2EReady())("e2e: search web", () => { expect(pages.length).toBeGreaterThan(0); expect(pages[0]?.url).toBeDefined(); }, 120_000); + + test("--list-tools 真实拉取 WebSearch MCP 工具列表并正常退出", async () => { + // The --list-tools branch opens its own MCP session; a leaked transport + // would hang the subprocess, so a clean exit is part of the contract. + const { stdout, stderr, exitCode } = await runCommandE2e(SEARCH_WEB_ROUTES, [ + "search", + "web", + "--list-tools", + "--output", + "json", + ]); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson<{ tools?: Array<{ name?: string }> }>(stdout); + expect(data.tools?.some((tool) => tool.name === "bailian_web_search")).toBe(true); + }, 60_000); }); diff --git a/packages/core/src/client/mcp-sdk.ts b/packages/core/src/client/mcp-sdk.ts index 1eeaa6186..f44f8f5a2 100644 --- a/packages/core/src/client/mcp-sdk.ts +++ b/packages/core/src/client/mcp-sdk.ts @@ -88,9 +88,14 @@ export interface SdkMcpAdapterOptions { * Translate an SDK/transport error into the CLI error contract. * * - `BailianError` (already ours, produced by the fetch interceptor) passes through. - * - `McpError`: RequestTimeout → TIMEOUT, ConnectionClosed → NETWORK, otherwise a - * server-side JSON-RPC error → GENERAL with the `MCP error (code): message` shape - * (message passed through verbatim per AGENTS.md §3). + * - `McpError`: SDK-local failures only — the protocol timer (`Request timed + * out` / `Maximum total timeout exceeded`, carrying its payload in `data`) → + * TIMEOUT, and the transport-close rejection (`Connection closed`) → NETWORK. + * A server-side JSON-RPC error reusing those codes (-32000 / -32001) carries + * the server's own message, so it falls through to GENERAL with the + * `MCP error (code): message` shape (message passed through verbatim per + * AGENTS.md §3) — the exit code must not mislead callers into retrying a + * business error as a network/timeout failure. * - `StreamableHTTPError` (HTTP status in `.code`) → GENERAL with the * `MCP request failed: ` shape so the fallback detectors still match. * - `SseError` (classic SSE): when the fetch interceptor captured the failing @@ -107,10 +112,10 @@ export function mapSdkError(error: unknown, sseGetFailure?: SseGetFailure): unkn if (error instanceof McpError) { const raw = rawMcpMessage(error); - if (error.code === ErrorCode.RequestTimeout) { + if (error.code === ErrorCode.RequestTimeout && isLocalTimeoutSignature(error, raw)) { return new BailianError(raw || "MCP request timed out.", ExitCode.TIMEOUT); } - if (error.code === ErrorCode.ConnectionClosed) { + if (error.code === ErrorCode.ConnectionClosed && raw === LOCAL_CLOSE_MESSAGE) { return new BailianError(raw || "MCP connection closed.", ExitCode.NETWORK); } return new BailianError(`MCP error (${error.code}): ${raw}`, ExitCode.GENERAL); @@ -149,6 +154,24 @@ function rawMcpMessage(error: McpError): string { return error.message.startsWith(prefix) ? error.message.slice(prefix.length) : error.message; } +/** Fixed message of the SDK's transport-close rejection of pending requests. */ +const LOCAL_CLOSE_MESSAGE = "Connection closed"; + +/** + * True when a `RequestTimeout` McpError came from the SDK's own request timer, + * not from a server JSON-RPC error response reusing code -32001. The protocol + * timer attaches its payload as `data` (`{ timeout }` / `{ maxTotalTimeout, … }`); + * the fixed timer messages are matched as a fallback so the contract survives + * SDK builds that drop the payload. + */ +function isLocalTimeoutSignature(error: McpError, raw: string): boolean { + const data = error.data as Record | undefined; + if (data && (typeof data.timeout === "number" || typeof data.maxTotalTimeout === "number")) { + return true; + } + return raw === "Request timed out" || raw === "Maximum total timeout exceeded"; +} + /** * Server-side failure of a classic SSE stream GET, captured by the fetch * interceptor before `eventsource` discards the body (it only reports @@ -286,13 +309,11 @@ export class SdkMcpAdapter implements McpConnectedClient { const client = await this.requireClient(); try { const result = await client.listTools(undefined, this.requestOptions()); - return result.tools.map((tool) => ({ - name: tool.name, - ...(tool.description !== undefined ? { description: tool.description } : {}), - ...(tool.inputSchema !== undefined - ? { inputSchema: tool.inputSchema as Record } - : {}), - })); + // Returned verbatim (the SDK-validated Tool objects): callers such as + // `bl mcp tools --output json` keep every standard field the server + // declares (outputSchema / annotations / title / `_meta`, …), matching + // the old hand-rolled client's passthrough. + return result.tools as McpTool[]; } catch (error) { throw this.mapTransportError(error); } diff --git a/packages/core/src/client/mcp.ts b/packages/core/src/client/mcp.ts index 6fcfb5fad..fb0577221 100644 --- a/packages/core/src/client/mcp.ts +++ b/packages/core/src/client/mcp.ts @@ -21,8 +21,18 @@ import { SdkMcpAdapter } from "./mcp-sdk.ts"; export interface McpTool { name: string; + /** Human-readable tool title, when the server declares one. */ + title?: string; description?: string; inputSchema?: Record; + /** JSON Schema for the tool output, when the server declares one. */ + outputSchema?: Record; + /** Server-provided behavioral hints (readOnlyHint, destructiveHint, …). */ + annotations?: Record; + /** Reserved extension slot, carried verbatim. */ + _meta?: Record; + /** Further standard fields the SDK validation retains. */ + [key: string]: unknown; } /** diff --git a/packages/core/tests/mcp.test.ts b/packages/core/tests/mcp.test.ts index 795724b20..0bd6723b2 100644 --- a/packages/core/tests/mcp.test.ts +++ b/packages/core/tests/mcp.test.ts @@ -148,6 +148,35 @@ test("mapSdkError:超时/连接关闭映射 ExitCode;服务端 JSON-RPC 错 expect(mapSdkError(typeError)).toBe(typeError); }); +test("mapSdkError:服务端 JSON-RPC 错复用 -32000/-32001 仍按 GENERAL 透传,本地计时器错才判 TIMEOUT/NETWORK", () => { + // Server-authored messages on the locally-interpreted codes must stay GENERAL + // (exit 1) so callers do not retry business errors as network/timeout. + const serverClosed = mapSdkError(new McpError(-32000, "session expired")); + expect(serverClosed).toBeInstanceOf(BailianError); + expect((serverClosed as BailianError).exitCode).toBe(ExitCode.GENERAL); + expect((serverClosed as BailianError).message).toBe("MCP error (-32000): session expired"); + + const serverTimeout = mapSdkError(new McpError(-32001, "tool execution timed out")); + expect((serverTimeout as BailianError).exitCode).toBe(ExitCode.GENERAL); + expect((serverTimeout as BailianError).message).toBe( + "MCP error (-32001): tool execution timed out", + ); + + // The SDK protocol timer attaches its payload as `data` — local signature. + const timer = mapSdkError( + McpError.fromError(ErrorCode.RequestTimeout, "Request timed out", { timeout: 5000 }), + ); + expect((timer as BailianError).exitCode).toBe(ExitCode.TIMEOUT); + + const maxTotal = mapSdkError( + McpError.fromError(ErrorCode.RequestTimeout, "Maximum total timeout exceeded", { + maxTotalTimeout: 1000, + totalElapsed: 1200, + }), + ); + expect((maxTotal as BailianError).exitCode).toBe(ExitCode.TIMEOUT); +}); + test("mapSdkError:SseError 结合捕获的 SSE GET 失败重建文案契约;无捕获时原样返回", () => { const sseError = new SseError(404, "Non-200 status code (404)", {} as never); const failure: SseGetFailure = { @@ -354,8 +383,12 @@ test("SdkMcpAdapter:listTools 与 callTool 结果映射回 McpTool / McpToolRe tools: [ { name: "bailian_image_gen", + title: "图片生成", description: "生成图片", inputSchema: { type: "object", properties: {}, required: ["prompt"] }, + outputSchema: { type: "object", properties: {} }, + annotations: { readOnlyHint: true }, + _meta: { "biz/source": "probe" }, }, ], }), @@ -368,6 +401,9 @@ test("SdkMcpAdapter:listTools 与 callTool 结果映射回 McpTool / McpToolRe { type: "text", text: JSON.stringify({ results: ["https://x/y.png"] }) }, { type: "image", data: "AAAA", mimeType: "image/png" }, ], + // The listed tool declares an outputSchema, so the SDK client + // validates that the call result carries structuredContent. + structuredContent: { results: ["https://x/y.png"] }, isError: false, }), ); @@ -388,8 +424,12 @@ test("SdkMcpAdapter:listTools 与 callTool 结果映射回 McpTool / McpToolRe expect(tools).toEqual([ { name: "bailian_image_gen", + title: "图片生成", description: "生成图片", inputSchema: { type: "object", properties: {}, required: ["prompt"] }, + outputSchema: { type: "object", properties: {} }, + annotations: { readOnlyHint: true }, + _meta: { "biz/source": "probe" }, }, ]); From 05183c1579d55893eade72e238391a883bb49ede Mon Sep 17 00:00:00 2001 From: wangmingxiang Date: Thu, 29 Oct 2026 21:38:54 +0800 Subject: [PATCH 6/6] =?UTF-8?q?fix(mcp):=20=E4=BC=98=E5=8C=96=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=A8=A1=E5=BC=8F=E9=9F=B3=E9=A2=91=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E4=B8=8E=E9=94=99=E8=AF=AF=E6=98=A0=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重命名并改进自动模式音频输入解析函数为 resolveAutoAsrInput - 拒绝非公网 http(s) URL 的本地音频输入并抛出带本地化提示的 USAGE 异常 - speech recognize 命令中替换相关调用为 resolveAutoAsrInput,保证错误前置处理 - 添加 resolveAutoAsrInput 相关单元测试,覆盖 URL 透传和本地路径拒绝情况 - 修改 MCP SDK 中错误映射逻辑,区分本地关闭导致的连接关闭错误映射为 NETWORK - 优化 MCP 适配器,禁用 SDK 内置超时,使用本地超时逻辑抛出明确超时错误 - 在 MCP 适配器中跟踪传输关闭状态以辅助错误类型判定 - 更新 MCP 相关测试代码,覆盖本地关闭状态下错误映射行为 - 调整阶段性测试用例以适配新逻辑和错误消息内容 --- .../commands/src/commands/shared/aigc-mcp.ts | 24 ++++- .../commands/src/commands/speech/recognize.ts | 8 +- packages/commands/tests/aigc-mcp-gate.test.ts | 17 +++ .../tests/e2e/aigc-auto-mcp.e2e.test.ts | 24 ++++- packages/core/src/client/mcp-sdk.ts | 100 +++++++++++------- packages/core/tests/mcp.test.ts | 43 ++++---- 6 files changed, 144 insertions(+), 72 deletions(-) diff --git a/packages/commands/src/commands/shared/aigc-mcp.ts b/packages/commands/src/commands/shared/aigc-mcp.ts index 81e6175a2..1936b2a71 100644 --- a/packages/commands/src/commands/shared/aigc-mcp.ts +++ b/packages/commands/src/commands/shared/aigc-mcp.ts @@ -19,7 +19,6 @@ import { ExitCode, parseAigcToolResult, imageFileToDataUri, - audioFileToDataUri, isMcpTtsVoice, MCP_TTS_VOICES, MCP_CALL_SERVICE, @@ -288,10 +287,25 @@ export function resolveAutoImageInput(source: string): string { return imageFileToDataUri(source); } -/** Resolve an `auto`-mode audio input the same way (ASR `file_urls`). */ -export function resolveAutoAudioInput(source: string): string { - if (isUrlScheme(source)) return source; - return audioFileToDataUri(source); +/** + * Resolve an `auto`-mode ASR input: the live `bailian_speech_to_text` server + * only transcribes public http(s) URLs — data-URI input (including inlined + * local files) comes back as an empty transcript with no error at all — so + * anything else is rejected up front with an actionable USAGE error instead of + * a silent empty result. + */ +export function resolveAutoAsrInput(source: string, localize: Localize): string { + if (/^https?:/i.test(source)) return source; + const message = localize({ + "en-US": `The current model (auto) recognizes audio via Bailian MCP, which only transcribes public http(s) URLs; cannot use "${source}".`, + "zh-CN": `当前模型(auto)经百炼 MCP 识别音频,仅支持公网 http(s) URL,无法使用 "${source}"。`, + }); + const hint = localize({ + "en-US": + "Host the audio at a public http(s) URL, or pass --model to recognize local files with a specific model.", + "zh-CN": "请将音频托管为公网 http(s) URL,或传入 --model 使用指定模型识别本地文件。", + }); + throw new BailianError(message, ExitCode.USAGE, hint); } // ---- Shared-session MCP call wrapper ---- diff --git a/packages/commands/src/commands/speech/recognize.ts b/packages/commands/src/commands/speech/recognize.ts index 8b2e46e8d..7b7e1ac04 100644 --- a/packages/commands/src/commands/speech/recognize.ts +++ b/packages/commands/src/commands/speech/recognize.ts @@ -39,7 +39,7 @@ import { assertAutoMcpAvailable, assertMcpCompatible, withAigcMcpSession, - resolveAutoAudioInput, + resolveAutoAsrInput, type Localize, } from "../shared/aigc-mcp.ts"; @@ -359,9 +359,9 @@ async function handleAutoMcpMode( throw new BailianError("Provide at least one --url to recognize.", ExitCode.USAGE); } - // Public http(s)/oss URLs pass through; local files become inline base64 data - // URIs (the MCP server rejects oss:// and cannot fetch private uploads). - const fileUrls = rawUrls.map((source) => resolveAutoAudioInput(source)); + // The live MCP ASR server only transcribes public http(s) URLs; local files + // and data URIs are rejected up front instead of silently empty results. + const fileUrls = rawUrls.map((source) => resolveAutoAsrInput(source, localize)); const args = buildSpeechToTextArgs(fileUrls); if (settings.dryRun) { diff --git a/packages/commands/tests/aigc-mcp-gate.test.ts b/packages/commands/tests/aigc-mcp-gate.test.ts index e849db572..c63e2de0e 100644 --- a/packages/commands/tests/aigc-mcp-gate.test.ts +++ b/packages/commands/tests/aigc-mcp-gate.test.ts @@ -8,6 +8,7 @@ import { isAutoModel, mcpSingleImageOnlyError, mcpUnsupportedError, + resolveAutoAsrInput, resolveAutoImageSize, type AigcMcpOperation, type Localize, @@ -201,3 +202,19 @@ describe("assertMcpTtsVoice rejects REST voice IDs", () => { expect(error.hint).toContain("--model"); }); }); + +describe("resolveAutoAsrInput only accepts public http(s) URLs", () => { + test("http(s) URLs pass through verbatim", () => { + expect(resolveAutoAsrInput("https://x/a.wav", enUS)).toBe("https://x/a.wav"); + expect(resolveAutoAsrInput("http://x/a.wav", zhCN)).toBe("http://x/a.wav"); + }); + + test("local paths and data URIs throw USAGE with a switch-model hint", () => { + const local = captureUsage(() => resolveAutoAsrInput("./a.wav", enUS)); + expect(local.message).toContain("./a.wav"); + expect(local.hint).toContain("--model"); + const dataUri = captureUsage(() => resolveAutoAsrInput("data:audio/wav;base64,AA==", zhCN)); + expect(dataUri.message).toContain("data:audio/wav"); + expect(dataUri.hint).toContain("--model"); + }); +}); diff --git a/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts b/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts index 8d28cb5cf..ce41ed571 100644 --- a/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts +++ b/packages/commands/tests/e2e/aigc-auto-mcp.e2e.test.ts @@ -210,12 +210,14 @@ describe("e2e: aigc auto → mcp", () => { expect(data.arguments?.file_urls).toEqual(["https://example.com/a.mp3"]); }); - test("speech recognize auto 本地音频内联为脱敏 data URI", async () => { + test("speech recognize auto 拒绝本地音频(服务端仅转写公网 URL)", async () => { + // The live MCP ASR server silently returns an empty transcript for data + // URIs, so local inputs must fail up front with a USAGE error. const configDir = makeE2eOutputDir("aigc-auto-speech-recognize-local"); const audioPath = join(configDir, "input.wav"); writeFileSync(audioPath, Buffer.from([1, 2, 3])); - const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + const { stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ "speech", "recognize", "--model", @@ -226,9 +228,25 @@ describe("e2e: aigc auto → mcp", () => { "--output", "json", ]); + expect(exitCode).toBe(2); + expect(stderr).toMatch(/--model/); + }); + + test("speech recognize auto dry-run 预览公网 URL 透传", async () => { + const { stdout, stderr, exitCode } = await runCommandE2e(AUTO_ROUTES, [ + "speech", + "recognize", + "--model", + "auto", + "--url", + "https://example.com/audio.wav", + "--dry-run", + "--output", + "json", + ]); expect(exitCode, stderr).toBe(0); const data = parseStdoutJson(stdout); - expect(data.arguments?.file_urls).toEqual(["data:audio/wav;base64,"]); + expect(data.arguments?.file_urls).toEqual(["https://example.com/audio.wav"]); }); test("image generate auto dry-run 预览把 --size 比例映射为 MCP 宽*高", async () => { diff --git a/packages/core/src/client/mcp-sdk.ts b/packages/core/src/client/mcp-sdk.ts index f44f8f5a2..95d613236 100644 --- a/packages/core/src/client/mcp-sdk.ts +++ b/packages/core/src/client/mcp-sdk.ts @@ -87,15 +87,14 @@ export interface SdkMcpAdapterOptions { /** * Translate an SDK/transport error into the CLI error contract. * - * - `BailianError` (already ours, produced by the fetch interceptor) passes through. - * - `McpError`: SDK-local failures only — the protocol timer (`Request timed - * out` / `Maximum total timeout exceeded`, carrying its payload in `data`) → - * TIMEOUT, and the transport-close rejection (`Connection closed`) → NETWORK. - * A server-side JSON-RPC error reusing those codes (-32000 / -32001) carries - * the server's own message, so it falls through to GENERAL with the - * `MCP error (code): message` shape (message passed through verbatim per - * AGENTS.md §3) — the exit code must not mislead callers into retrying a - * business error as a network/timeout failure. + * - `BailianError` (already ours, produced by local timeout or the fetch + * interceptor) passes through. + * - `McpError`: treated as a server-side JSON-RPC error by default and mapped to + * `GENERAL` with the `MCP error (): ` shape (message passed + * through verbatim per AGENTS.md §3). Callers that can distinguish local + * transport-close events pass `localCloseFired: true` so that + * `ConnectionClosed` errors arising after the transport has closed are mapped + * to `NETWORK` instead. * - `StreamableHTTPError` (HTTP status in `.code`) → GENERAL with the * `MCP request failed: ` shape so the fallback detectors still match. * - `SseError` (classic SSE): when the fetch interceptor captured the failing @@ -107,15 +106,16 @@ export interface SdkMcpAdapterOptions { * - Anything else (e.g. a `TypeError` from `fetch`) is returned unchanged so the * runtime keeps its errno-specific handling. */ -export function mapSdkError(error: unknown, sseGetFailure?: SseGetFailure): unknown { +export function mapSdkError( + error: unknown, + sseGetFailure?: SseGetFailure, + options?: { localCloseFired?: boolean }, +): unknown { if (error instanceof BailianError) return error; if (error instanceof McpError) { const raw = rawMcpMessage(error); - if (error.code === ErrorCode.RequestTimeout && isLocalTimeoutSignature(error, raw)) { - return new BailianError(raw || "MCP request timed out.", ExitCode.TIMEOUT); - } - if (error.code === ErrorCode.ConnectionClosed && raw === LOCAL_CLOSE_MESSAGE) { + if (error.code === ErrorCode.ConnectionClosed && options?.localCloseFired) { return new BailianError(raw || "MCP connection closed.", ExitCode.NETWORK); } return new BailianError(`MCP error (${error.code}): ${raw}`, ExitCode.GENERAL); @@ -154,24 +154,6 @@ function rawMcpMessage(error: McpError): string { return error.message.startsWith(prefix) ? error.message.slice(prefix.length) : error.message; } -/** Fixed message of the SDK's transport-close rejection of pending requests. */ -const LOCAL_CLOSE_MESSAGE = "Connection closed"; - -/** - * True when a `RequestTimeout` McpError came from the SDK's own request timer, - * not from a server JSON-RPC error response reusing code -32001. The protocol - * timer attaches its payload as `data` (`{ timeout }` / `{ maxTotalTimeout, … }`); - * the fixed timer messages are matched as a fallback so the contract survives - * SDK builds that drop the payload. - */ -function isLocalTimeoutSignature(error: McpError, raw: string): boolean { - const data = error.data as Record | undefined; - if (data && (typeof data.timeout === "number" || typeof data.maxTotalTimeout === "number")) { - return true; - } - return raw === "Request timed out" || raw === "Maximum total timeout exceeded"; -} - /** * Server-side failure of a classic SSE stream GET, captured by the fetch * interceptor before `eventsource` discards the body (it only reports @@ -281,6 +263,12 @@ export class SdkMcpAdapter implements McpConnectedClient { private connecting: Promise | undefined; /** Last failed classic SSE stream GET, for `SseError` contract reconstruction. */ private sseGetFailure: SseGetFailure | undefined; + /** + * Set when the transport's `onclose` callback fires. Used to distinguish + * SDK-generated `ConnectionClosed` errors (local network events) from + * server-authored JSON-RPC errors that reuse code -32000. + */ + private transportClosed = false; constructor(options: SdkMcpAdapterOptions) { this.deps = options.deps; @@ -308,7 +296,9 @@ export class SdkMcpAdapter implements McpConnectedClient { async listTools(): Promise { const client = await this.requireClient(); try { - const result = await client.listTools(undefined, this.requestOptions()); + const result = await this.withLocalTimeout( + client.listTools(undefined, this.requestOptions()), + ); // Returned verbatim (the SDK-validated Tool objects): callers such as // `bl mcp tools --output json` keep every standard field the server // declares (outputSchema / annotations / title / `_meta`, …), matching @@ -322,10 +312,8 @@ export class SdkMcpAdapter implements McpConnectedClient { async callTool(name: string, args: Record): Promise { const client = await this.requireClient(); try { - const result = (await client.callTool( - { name, arguments: args }, - undefined, - this.requestOptions(), + const result = (await this.withLocalTimeout( + client.callTool({ name, arguments: args }, undefined, this.requestOptions()), )) as McpToolResult; // The SDK already validates the envelope against CallToolResultSchema; // only a missing content array is an unexpected shape for our callers. @@ -359,9 +347,9 @@ export class SdkMcpAdapter implements McpConnectedClient { // ---- Internal ---- - /** `mapSdkError` with this adapter's captured classic SSE GET failure. */ + /** `mapSdkError` with this adapter's local transport-close state. */ private mapTransportError(error: unknown): unknown { - return mapSdkError(error, this.sseGetFailure); + return mapSdkError(error, this.sseGetFailure, { localCloseFired: this.transportClosed }); } private async connect(): Promise { @@ -375,6 +363,8 @@ export class SdkMcpAdapter implements McpConnectedClient { this.sseGetFailure = failure; }); const endpoint = new URL(this.url); + this.transportClosed = false; + const transport = this.kind === "sse" ? new SSEClientTransport(endpoint, { requestInit: { headers }, fetch: mcpFetch }) @@ -383,6 +373,14 @@ export class SdkMcpAdapter implements McpConnectedClient { fetch: mcpFetch, }); + // Track local transport close so SDK-generated `ConnectionClosed` errors + // can be reliably distinguished from server-authored -32000 JSON-RPC errors. + // Protocol.connect wraps any pre-existing onclose, so this fires before the + // SDK rejects in-flight requests. + transport.onclose = () => { + this.transportClosed = true; + }; + const client = new Client( { name: this.deps.identity.clientName, version: this.deps.identity.version }, { capabilities: {} }, @@ -452,6 +450,28 @@ export class SdkMcpAdapter implements McpConnectedClient { } private requestOptions(): { timeout: number } { - return { timeout: this.deps.settings.timeout * 1000 }; + // Disable the SDK's own request timer; the adapter enforces the timeout + // locally via `withLocalTimeout` so that timeout failures carry an + // unambiguous local source and are not confused with server JSON-RPC + // errors that may reuse code -32001 or carry `data.timeout`. + // Use Node's maximum setTimeout delay so the SDK timer never wins the race. + return { timeout: 2_147_483_647 }; + } + + private async withLocalTimeout(promise: Promise): Promise { + const timeoutSeconds = this.deps.settings.timeout; + let timer: ReturnType | undefined; + const timeoutPromise = new Promise((_, reject) => { + timer = setTimeout(() => { + reject( + new BailianError(`MCP request timed out after ${timeoutSeconds}s.`, ExitCode.TIMEOUT), + ); + }, timeoutSeconds * 1000); + }); + try { + return await Promise.race([promise, timeoutPromise]); + } finally { + if (timer) clearTimeout(timer); + } } } diff --git a/packages/core/tests/mcp.test.ts b/packages/core/tests/mcp.test.ts index 0bd6723b2..f812ee119 100644 --- a/packages/core/tests/mcp.test.ts +++ b/packages/core/tests/mcp.test.ts @@ -120,14 +120,27 @@ test("bailianMcp 路径与 isStreamableHttpUnsupported", () => { // ---- mapSdkError ---- -test("mapSdkError:超时/连接关闭映射 ExitCode;服务端 JSON-RPC 错透传;BailianError 与原生错原样返回", () => { +test("mapSdkError:McpError 默认按 GENERAL 透传;localCloseFired 才将 ConnectionClosed 映射为 NETWORK", () => { + // SDK-local RequestTimeout is now handled by the adapter's own timer and + // reaches mapSdkError as a BailianError; a bare McpError is server-authored. const timeout = mapSdkError(new McpError(ErrorCode.RequestTimeout, "Request timed out")); expect(timeout).toBeInstanceOf(BailianError); - expect((timeout as BailianError).exitCode).toBe(ExitCode.TIMEOUT); + expect((timeout as BailianError).exitCode).toBe(ExitCode.GENERAL); + // ConnectionClosed without the local-close signal is treated as a server + // JSON-RPC error (e.g. the server returned -32000). const closed = mapSdkError(new McpError(ErrorCode.ConnectionClosed, "Connection closed")); expect(closed).toBeInstanceOf(BailianError); - expect((closed as BailianError).exitCode).toBe(ExitCode.NETWORK); + expect((closed as BailianError).exitCode).toBe(ExitCode.GENERAL); + + // ConnectionClosed after the local transport closed is a network event. + const localClosed = mapSdkError( + new McpError(ErrorCode.ConnectionClosed, "Connection closed"), + undefined, + { localCloseFired: true }, + ); + expect(localClosed).toBeInstanceOf(BailianError); + expect((localClosed as BailianError).exitCode).toBe(ExitCode.NETWORK); // Server-side JSON-RPC error: passthrough message with the MCP error shape. const business = mapSdkError(new McpError(-32601, "Method not found")); @@ -148,7 +161,7 @@ test("mapSdkError:超时/连接关闭映射 ExitCode;服务端 JSON-RPC 错 expect(mapSdkError(typeError)).toBe(typeError); }); -test("mapSdkError:服务端 JSON-RPC 错复用 -32000/-32001 仍按 GENERAL 透传,本地计时器错才判 TIMEOUT/NETWORK", () => { +test("mapSdkError:服务端 JSON-RPC 错复用 -32000/-32001 按 GENERAL 透传,不再推断本地签名", () => { // Server-authored messages on the locally-interpreted codes must stay GENERAL // (exit 1) so callers do not retry business errors as network/timeout. const serverClosed = mapSdkError(new McpError(-32000, "session expired")); @@ -156,25 +169,15 @@ test("mapSdkError:服务端 JSON-RPC 错复用 -32000/-32001 仍按 GENERAL expect((serverClosed as BailianError).exitCode).toBe(ExitCode.GENERAL); expect((serverClosed as BailianError).message).toBe("MCP error (-32000): session expired"); - const serverTimeout = mapSdkError(new McpError(-32001, "tool execution timed out")); + // The server can also return -32001 with data.timeout — this must not be + // mistaken for the SDK's local request timer. + const serverTimeout = mapSdkError( + new McpError(-32001, "backend execution expired", { timeout: 5000 }), + ); expect((serverTimeout as BailianError).exitCode).toBe(ExitCode.GENERAL); expect((serverTimeout as BailianError).message).toBe( - "MCP error (-32001): tool execution timed out", - ); - - // The SDK protocol timer attaches its payload as `data` — local signature. - const timer = mapSdkError( - McpError.fromError(ErrorCode.RequestTimeout, "Request timed out", { timeout: 5000 }), - ); - expect((timer as BailianError).exitCode).toBe(ExitCode.TIMEOUT); - - const maxTotal = mapSdkError( - McpError.fromError(ErrorCode.RequestTimeout, "Maximum total timeout exceeded", { - maxTotalTimeout: 1000, - totalElapsed: 1200, - }), + "MCP error (-32001): backend execution expired", ); - expect((maxTotal as BailianError).exitCode).toBe(ExitCode.TIMEOUT); }); test("mapSdkError:SseError 结合捕获的 SSE GET 失败重建文案契约;无捕获时原样返回", () => {