From 9e9911aa866a880cd658dfc4173d37032a70ad3e Mon Sep 17 00:00:00 2001 From: "lisheng.lisheng" Date: Sat, 15 Aug 2026 01:44:28 +0800 Subject: [PATCH 1/4] feat(dsh): add bailian-cli-dsh plugin bundle for DeepSeek Harness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expose Bailian capabilities to dsh through its service seams as one package with six subpath plugin entries and a `dsh.bundle` patch: - TokenPlan as an LLM provider - bailian_vision_describe / bailian_image_generate tools over `bl` - knowledge-base retrieval as a WebSearchProvider (`bailian-kb`) - cross-session memory: tools, pre-step recall, turn-close persist - managed-agent as a SubagentProvider TokenPlan configures the base bundle's existing pi-ai row rather than mounting a second `dsh-llm-pi-ai` instance. A second instance cannot work: pi-ai re-declares its entire built-in provider catalog to `registerConfigurableProviders`, and that directory is global, so boot fails with a duplicate on `amazon-bedrock`. Routes and vision support were probed against the live gateway. qwen3.8-max, qwen3.7-plus, qwen3.6-flash and glm-5.2 read images; qwen3.7-max rejects them with HTTP 400; the DeepSeek routes accept image content without erroring yet stay blind. The DeepSeek entries therefore do not declare image input — claiming it would turn a clean refusal into a silently wrong answer — and `bailian_vision_describe` serves them by returning text instead. Also fix `bl memory` against the v2 API, each verified live: - `profile get` used /profiles, which returns HTTP 500. The documented and working endpoint is /user_profile. - `add` read `response.memory_ids`, which the service never returns. It returns `memory_nodes`, so text output always printed "IDs: none". - `MemoryNode.created_at`/`updated_at` are unix seconds, not strings, and `UserProfileResponse.profile` did not match the wire shape. - Add the missing request parameters: --meta-data, --project-id, --project-ids, --min-score, --enable-rerank, --plan-version, --enable-judge, --enable-rewrite, --timestamp. - Add `memory profile list|detail|update|delete`, covering the four v2 profile-schema operations the CLI was missing. `plan_version: lite` is ignored by the service and still bills pro; `enable_rerank: false` is what actually selects lite, which is ~50x cheaper per search. The CLI flag and the memory plugin both send the parameter that works. Disable pnpm's autoInstallPeers: the @deepseek-ai/dsh-* rc line peers on three packages that were never published to npm, which 404s the whole workspace install. Verified the existing packages still build. Co-Authored-By: Claude --- .gitignore | 3 + packages/cli/src/commands.ts | 8 + packages/commands/src/commands/memory/add.ts | 30 +- packages/commands/src/commands/memory/list.ts | 6 + .../src/commands/memory/profile-delete.ts | 44 + .../src/commands/memory/profile-detail.ts | 52 + .../src/commands/memory/profile-list.ts | 55 + .../src/commands/memory/profile-update.ts | 81 + .../commands/src/commands/memory/search.ts | 48 + .../commands/src/commands/memory/update.ts | 20 + packages/commands/src/index.ts | 4 + packages/commands/tests/e2e/topic-routes.ts | 4 + packages/core/src/client/endpoints.ts | 6 +- packages/core/src/client/index.ts | 1 + packages/core/src/types/api.ts | 89 +- packages/dsh/README.md | 253 ++ packages/dsh/cordis.patch.yml | 97 + packages/dsh/package.json | 111 + packages/dsh/src/index.ts | 9 + packages/dsh/src/memory/index.ts | 369 +++ packages/dsh/src/shared/bl.ts | 161 ++ packages/dsh/src/shared/http.ts | 98 + .../dsh/src/subagent-managed-agent/index.ts | 205 ++ packages/dsh/src/tool-image/index.ts | 239 ++ packages/dsh/src/tool-vision/index.ts | 135 + packages/dsh/src/web-search-rag/index.ts | 161 ++ packages/dsh/tsconfig.json | 20 + packages/dsh/vite.config.ts | 27 + pnpm-lock.yaml | 2209 ++++++++++++++--- pnpm-workspace.yaml | 4 + skills/bailian-cli/reference/index.md | 48 +- skills/bailian-cli/reference/memory.md | 221 +- 32 files changed, 4408 insertions(+), 410 deletions(-) create mode 100644 packages/commands/src/commands/memory/profile-delete.ts create mode 100644 packages/commands/src/commands/memory/profile-detail.ts create mode 100644 packages/commands/src/commands/memory/profile-list.ts create mode 100644 packages/commands/src/commands/memory/profile-update.ts create mode 100644 packages/dsh/README.md create mode 100644 packages/dsh/cordis.patch.yml create mode 100644 packages/dsh/package.json create mode 100644 packages/dsh/src/index.ts create mode 100644 packages/dsh/src/memory/index.ts create mode 100644 packages/dsh/src/shared/bl.ts create mode 100644 packages/dsh/src/shared/http.ts create mode 100644 packages/dsh/src/subagent-managed-agent/index.ts create mode 100644 packages/dsh/src/tool-image/index.ts create mode 100644 packages/dsh/src/tool-vision/index.ts create mode 100644 packages/dsh/src/web-search-rag/index.ts create mode 100644 packages/dsh/tsconfig.json create mode 100644 packages/dsh/vite.config.ts diff --git a/.gitignore b/.gitignore index 97b43669..0afb45a4 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,6 @@ packages/cli/scene/**/outputs/ # Local scratch / plan drafts (never commit) .scratch/ + +# pnpm pack output +*.tgz diff --git a/packages/cli/src/commands.ts b/packages/cli/src/commands.ts index 652da452..b601159a 100644 --- a/packages/cli/src/commands.ts +++ b/packages/cli/src/commands.ts @@ -30,6 +30,10 @@ import { memoryDelete, memoryProfileCreate, memoryProfileGet, + memoryProfileList, + memoryProfileDetail, + memoryProfileUpdate, + memoryProfileDelete, knowledgeRetrieve, knowledgeSearch, knowledgeChat, @@ -149,6 +153,10 @@ export const commands: Record = { "memory delete": memoryDelete, "memory profile create": memoryProfileCreate, "memory profile get": memoryProfileGet, + "memory profile list": memoryProfileList, + "memory profile detail": memoryProfileDetail, + "memory profile update": memoryProfileUpdate, + "memory profile delete": memoryProfileDelete, "knowledge retrieve": knowledgeRetrieve, "knowledge search": knowledgeSearch, "knowledge chat": knowledgeChat, diff --git a/packages/commands/src/commands/memory/add.ts b/packages/commands/src/commands/memory/add.ts index 160999fc..8b1b0537 100644 --- a/packages/commands/src/commands/memory/add.ts +++ b/packages/commands/src/commands/memory/add.ts @@ -28,6 +28,16 @@ const ADD_FLAGS = { valueHint: "", description: "Memory library ID (isolate memory space)", }, + projectId: { + type: "string", + valueHint: "", + description: "Memory extraction rule ID (defaults to the library's default rule)", + }, + metaData: { + type: "string", + valueHint: "", + description: 'Custom metadata JSON object: {"location":"Beijing"}', + }, } satisfies FlagsDef; type AddFlags = ParsedFlags; @@ -40,6 +50,7 @@ export default defineCommand({ '--user-id user1 --content "The user likes Python programming"', '--user-id user1 --messages \'[{"role":"user","content":"I like traveling"}]\'', '--user-id user1 --content "Lives in Beijing" --profile-schema schema_xxx', + '--user-id user1 --content "Lives in Beijing" --meta-data \'{"source":"onboarding"}\'', ], validate: (f: AddFlags) => !f.messages && !f.content ? "Provide --messages or --content." : undefined, @@ -63,6 +74,15 @@ export default defineCommand({ if (flags.profileSchema) body.profile_schema = flags.profileSchema; if (flags.memoryLibraryId) body.memory_library_id = flags.memoryLibraryId; + if (flags.projectId) body.project_id = flags.projectId; + + if (flags.metaData) { + try { + body.meta_data = JSON.parse(flags.metaData); + } catch { + throw new UsageError("--meta-data must be valid JSON object"); + } + } const format = detectOutputFormat(settings.output); @@ -78,8 +98,14 @@ export default defineCommand({ }); if (settings.quiet || format === "text") { - const ids = response.memory_ids?.join(", ") || "none"; - emitBare(`Memory added. IDs: ${ids}`); + const nodes = response.memory_nodes ?? []; + if (nodes.length === 0) { + emitBare("No memory fragments were extracted."); + } else { + for (const node of nodes) { + emitBare(`[${node.event ?? "ADD"}] ${node.memory_node_id} ${node.content}`); + } + } } else { emitResult(response, format); } diff --git a/packages/commands/src/commands/memory/list.ts b/packages/commands/src/commands/memory/list.ts index 6757fe6a..79e08d74 100644 --- a/packages/commands/src/commands/memory/list.ts +++ b/packages/commands/src/commands/memory/list.ts @@ -24,6 +24,11 @@ export default defineCommand({ }, page: { type: "number", valueHint: "", description: "Page number (default: 1)" }, memoryLibraryId: { type: "string", valueHint: "", description: "Memory library ID" }, + projectId: { + type: "string", + valueHint: "", + description: "Memory extraction rule ID (defaults to the library's default rule)", + }, }, exampleArgs: ["--user-id user1", "--user-id user1 --page-size 20 --page 2"], async run(ctx) { @@ -36,6 +41,7 @@ export default defineCommand({ if (flags.pageSize !== undefined) params.set("page_size", String(flags.pageSize)); if (flags.page !== undefined) params.set("page_num", String(flags.page)); if (flags.memoryLibraryId) params.set("memory_library_id", flags.memoryLibraryId); + if (flags.projectId) params.set("project_id", flags.projectId); const path = `${memoryListPath()}?${params.toString()}`; diff --git a/packages/commands/src/commands/memory/profile-delete.ts b/packages/commands/src/commands/memory/profile-delete.ts new file mode 100644 index 00000000..4cc78c7b --- /dev/null +++ b/packages/commands/src/commands/memory/profile-delete.ts @@ -0,0 +1,44 @@ +import { defineCommand, profileSchemaItemPath, detectOutputFormat } from "bailian-cli-core"; +import { emitResult, emitBare } from "bailian-cli-runtime"; + +export default defineCommand({ + description: "Delete a profile schema", + auth: "apiKey", + usageArgs: "--schema-id [flags]", + flags: { + schemaId: { + type: "string", + valueHint: "", + description: "Profile schema ID (required)", + required: true, + }, + memoryLibraryId: { type: "string", valueHint: "", description: "Memory library ID" }, + }, + exampleArgs: ["--schema-id schema_xxx"], + async run(ctx) { + const { settings, flags } = ctx; + const format = detectOutputFormat(settings.output); + + const params = new URLSearchParams(); + if (flags.memoryLibraryId) params.set("memory_library_id", flags.memoryLibraryId); + const query = params.toString(); + const base = profileSchemaItemPath(flags.schemaId); + const path = query ? `${base}?${query}` : base; + + if (settings.dryRun) { + emitResult({ endpoint: ctx.client.url(path), method: "DELETE" }, format); + return; + } + + const response = await ctx.client.requestJson<{ request_id: string }>({ + path, + method: "DELETE", + }); + + if (settings.quiet || format === "text") { + emitBare(`Profile schema ${flags.schemaId} deleted.`); + } else { + emitResult(response, format); + } + }, +}); diff --git a/packages/commands/src/commands/memory/profile-detail.ts b/packages/commands/src/commands/memory/profile-detail.ts new file mode 100644 index 00000000..0eefc4bb --- /dev/null +++ b/packages/commands/src/commands/memory/profile-detail.ts @@ -0,0 +1,52 @@ +import { + defineCommand, + profileSchemaItemPath, + detectOutputFormat, + type ProfileSchemaGetResponse, +} from "bailian-cli-core"; +import { emitResult, emitBare } from "bailian-cli-runtime"; + +export default defineCommand({ + description: "Show a profile schema and its attribute IDs", + auth: "apiKey", + usageArgs: "--schema-id [flags]", + flags: { + schemaId: { + type: "string", + valueHint: "", + description: "Profile schema ID (required)", + required: true, + }, + memoryLibraryId: { type: "string", valueHint: "", description: "Memory library ID" }, + }, + exampleArgs: ["--schema-id schema_xxx"], + async run(ctx) { + const { settings, flags } = ctx; + const format = detectOutputFormat(settings.output); + + const params = new URLSearchParams(); + if (flags.memoryLibraryId) params.set("memory_library_id", flags.memoryLibraryId); + const query = params.toString(); + const base = profileSchemaItemPath(flags.schemaId); + const path = query ? `${base}?${query}` : base; + + if (settings.dryRun) { + emitResult({ endpoint: ctx.client.url(path), method: "GET" }, format); + return; + } + + const response = await ctx.client.requestJson({ + path, + method: "GET", + }); + + if (settings.quiet || format === "text") { + emitBare(`${response.name}${response.description ? ` — ${response.description}` : ""}`); + for (const attribute of response.attributes ?? []) { + emitBare(` [${attribute.attribute_id}] ${attribute.name}`); + } + } else { + emitResult(response, format); + } + }, +}); diff --git a/packages/commands/src/commands/memory/profile-list.ts b/packages/commands/src/commands/memory/profile-list.ts new file mode 100644 index 00000000..990503b7 --- /dev/null +++ b/packages/commands/src/commands/memory/profile-list.ts @@ -0,0 +1,55 @@ +import { + defineCommand, + profileSchemaPath, + detectOutputFormat, + type ProfileSchemaListResponse, +} from "bailian-cli-core"; +import { emitResult, emitBare } from "bailian-cli-runtime"; + +export default defineCommand({ + description: "List profile schemas", + auth: "apiKey", + usageArgs: "[flags]", + flags: { + memoryLibraryId: { type: "string", valueHint: "", description: "Memory library ID" }, + pageSize: { type: "number", valueHint: "", description: "Results per page (default: 10)" }, + page: { type: "number", valueHint: "", description: "Page number (default: 1)" }, + }, + exampleArgs: ["", "--page-size 20 --page 2"], + async run(ctx) { + const { settings, flags } = ctx; + const format = detectOutputFormat(settings.output); + + const params = new URLSearchParams(); + if (flags.memoryLibraryId) params.set("memory_library_id", flags.memoryLibraryId); + if (flags.pageSize !== undefined) params.set("page_size", String(flags.pageSize)); + if (flags.page !== undefined) params.set("page_num", String(flags.page)); + + const query = params.toString(); + const path = query ? `${profileSchemaPath()}?${query}` : profileSchemaPath(); + + if (settings.dryRun) { + emitResult({ endpoint: ctx.client.url(path), method: "GET" }, format); + return; + } + + const response = await ctx.client.requestJson({ + path, + method: "GET", + }); + + if (settings.quiet || format === "text") { + const schemas = response.profile_schemas ?? []; + if (schemas.length === 0) { + emitBare("No profile schemas found."); + } else { + for (const schema of schemas) { + emitBare(`[${schema.profile_schema_id}] ${schema.name}`); + } + if (response.total !== undefined) emitBare(`\nTotal: ${response.total}`); + } + } else { + emitResult(response, format); + } + }, +}); diff --git a/packages/commands/src/commands/memory/profile-update.ts b/packages/commands/src/commands/memory/profile-update.ts new file mode 100644 index 00000000..7283fd22 --- /dev/null +++ b/packages/commands/src/commands/memory/profile-update.ts @@ -0,0 +1,81 @@ +import { + defineCommand, + UsageError, + profileSchemaItemPath, + detectOutputFormat, + type ProfileSchemaUpdateRequest, +} from "bailian-cli-core"; +import { emitResult, emitBare } from "bailian-cli-runtime"; +import type { FlagsDef, ParsedFlags } from "bailian-cli-core"; + +const UPDATE_FLAGS = { + schemaId: { + type: "string", + valueHint: "", + description: "Profile schema ID (required)", + required: true, + }, + name: { type: "string", valueHint: "", description: "New schema name" }, + description: { type: "string", valueHint: "", description: "New schema description" }, + attributeOps: { + type: "string", + valueHint: "", + description: + 'Attribute operations JSON array: [{"op":"add","name":"plan"},{"op":"delete","attribute_id":"attr_1"}]', + }, + memoryLibraryId: { type: "string", valueHint: "", description: "Memory library ID" }, +} satisfies FlagsDef; +type UpdateFlags = ParsedFlags; + +export default defineCommand({ + description: "Update a profile schema's name, description, or attributes", + auth: "apiKey", + usageArgs: "--schema-id [--name ] [--attribute-ops ] [flags]", + flags: UPDATE_FLAGS, + notes: ["Attribute IDs for update/delete operations come from `memory profile detail`."], + exampleArgs: [ + '--schema-id schema_xxx --name "user_basic_v2"', + '--schema-id schema_xxx --attribute-ops \'[{"op":"add","name":"plan","description":"subscription plan"}]\'', + '--schema-id schema_xxx --attribute-ops \'[{"op":"delete","attribute_id":"attr_1"}]\'', + ], + validate: (f: UpdateFlags) => + !f.name && !f.description && !f.attributeOps + ? "Provide --name, --description, or --attribute-ops." + : undefined, + async run(ctx) { + const { settings, flags } = ctx; + const format = detectOutputFormat(settings.output); + + const body: ProfileSchemaUpdateRequest = {}; + if (flags.name) body.name = flags.name; + if (flags.description) body.description = flags.description; + if (flags.memoryLibraryId) body.memory_library_id = flags.memoryLibraryId; + + if (flags.attributeOps) { + try { + body.attributes_operations = JSON.parse(flags.attributeOps); + } catch { + throw new UsageError("--attribute-ops must be valid JSON array"); + } + } + + const path = profileSchemaItemPath(flags.schemaId); + + if (settings.dryRun) { + emitResult({ endpoint: ctx.client.url(path), method: "PATCH", request: body }, format); + return; + } + + const response = await ctx.client.requestJson<{ request_id: string }>({ + path, + method: "PATCH", + body, + }); + + if (settings.quiet || format === "text") { + emitBare(`Profile schema ${flags.schemaId} updated.`); + } else { + emitResult(response, format); + } + }, +}); diff --git a/packages/commands/src/commands/memory/search.ts b/packages/commands/src/commands/memory/search.ts index 6abccb4e..d29815be 100644 --- a/packages/commands/src/commands/memory/search.ts +++ b/packages/commands/src/commands/memory/search.ts @@ -24,6 +24,38 @@ const SEARCH_FLAGS = { description: "Number of results to return (default: 10)", }, memoryLibraryId: { type: "string", valueHint: "", description: "Memory library ID" }, + projectIds: { + type: "array", + valueHint: "", + description: "Memory extraction rule ID for hybrid retrieval (repeatable)", + }, + minScore: { + type: "number", + valueHint: "", + description: "Minimum similarity score, 0-1 (default: 0.3)", + }, + enableRerank: { + type: "boolean", + valueHint: "", + description: + "Rerank results. Also selects the billing tier: false bills lite, true bills pro (~50x). (default: true)", + }, + planVersion: { + type: "string", + valueHint: "", + description: + "Documented billing tier. The service currently honors --enable-rerank instead, so prefer that flag", + }, + enableJudge: { + type: "boolean", + valueHint: "", + description: "Enable the intent-discrimination callback (default: false)", + }, + enableRewrite: { + type: "boolean", + valueHint: "", + description: "Enable query rewriting (default: false)", + }, } satisfies FlagsDef; type SearchFlags = ParsedFlags; @@ -35,6 +67,7 @@ export default defineCommand({ exampleArgs: [ '--user-id user1 --query "programming preferences"', '--user-id user1 --messages \'[{"role":"user","content":"recommend a book"}]\' --top-k 5', + '--user-id user1 --query "preferences" --enable-rerank false --min-score 0.5', ], validate: (f: SearchFlags) => !f.query && !f.messages ? "Provide --query or --messages." : undefined, @@ -61,6 +94,21 @@ export default defineCommand({ if (flags.topK !== undefined) body.top_k = flags.topK; if (flags.memoryLibraryId) body.memory_library_id = flags.memoryLibraryId; + if (flags.projectIds && flags.projectIds.length > 0) body.project_ids = flags.projectIds; + if (flags.minScore !== undefined) body.min_score = flags.minScore; + if (flags.enableRerank !== undefined) body.enable_rerank = flags.enableRerank; + if (flags.enableJudge !== undefined) body.enable_judge = flags.enableJudge; + if (flags.enableRewrite !== undefined) body.enable_rewrite = flags.enableRewrite; + + if (flags.planVersion) { + if (flags.planVersion !== "lite" && flags.planVersion !== "pro") { + throw new UsageError("--plan-version must be lite or pro"); + } + body.plan_version = flags.planVersion; + // The service ignores plan_version on its own, so mirror the intent onto + // the flag it does honor unless the caller set that one explicitly. + if (flags.enableRerank === undefined) body.enable_rerank = flags.planVersion === "pro"; + } const format = detectOutputFormat(settings.output); diff --git a/packages/commands/src/commands/memory/update.ts b/packages/commands/src/commands/memory/update.ts index 14cd3e99..a9ad5de9 100644 --- a/packages/commands/src/commands/memory/update.ts +++ b/packages/commands/src/commands/memory/update.ts @@ -1,5 +1,6 @@ import { defineCommand, + UsageError, memoryNodePath, detectOutputFormat, type MemoryNodeUpdateRequest, @@ -34,6 +35,16 @@ export default defineCommand({ valueHint: "", description: "Memory library ID (non-default library)", }, + timestamp: { + type: "number", + valueHint: "", + description: "When the remembered event happened (default: now)", + }, + metaData: { + type: "string", + valueHint: "", + description: 'Custom metadata JSON object, merged incrementally: {"source":"manual"}', + }, }, exampleArgs: ['--node-id node_xxx --user-id user1 --content "updated memory content"'], async run(ctx) { @@ -47,6 +58,15 @@ export default defineCommand({ custom_content: content, }; if (flags.memoryLibraryId) body.memory_library_id = flags.memoryLibraryId; + if (flags.timestamp !== undefined) body.timestamp = flags.timestamp; + + if (flags.metaData) { + try { + body.meta_data = JSON.parse(flags.metaData); + } catch { + throw new UsageError("--meta-data must be valid JSON object"); + } + } const format = detectOutputFormat(settings.output); diff --git a/packages/commands/src/index.ts b/packages/commands/src/index.ts index a5af82d1..3c62602b 100644 --- a/packages/commands/src/index.ts +++ b/packages/commands/src/index.ts @@ -33,6 +33,10 @@ export { default as memoryUpdate } from "./commands/memory/update.ts"; export { default as memoryDelete } from "./commands/memory/delete.ts"; export { default as memoryProfileCreate } from "./commands/memory/profile-create.ts"; export { default as memoryProfileGet } from "./commands/memory/profile-get.ts"; +export { default as memoryProfileList } from "./commands/memory/profile-list.ts"; +export { default as memoryProfileDetail } from "./commands/memory/profile-detail.ts"; +export { default as memoryProfileUpdate } from "./commands/memory/profile-update.ts"; +export { default as memoryProfileDelete } from "./commands/memory/profile-delete.ts"; export { default as knowledgeRetrieve } from "./commands/knowledge/retrieve.ts"; export { default as knowledgeSearch } from "./commands/knowledge/search.ts"; export { default as knowledgeChat } from "./commands/knowledge/chat.ts"; diff --git a/packages/commands/tests/e2e/topic-routes.ts b/packages/commands/tests/e2e/topic-routes.ts index 84761f4a..9e18bf7b 100644 --- a/packages/commands/tests/e2e/topic-routes.ts +++ b/packages/commands/tests/e2e/topic-routes.ts @@ -33,6 +33,10 @@ export const MEMORY_ROUTES: E2eRouteExports = { "memory delete": "memoryDelete", "memory profile create": "memoryProfileCreate", "memory profile get": "memoryProfileGet", + "memory profile list": "memoryProfileList", + "memory profile detail": "memoryProfileDetail", + "memory profile update": "memoryProfileUpdate", + "memory profile delete": "memoryProfileDelete", }; export const KNOWLEDGE_ROUTES: E2eRouteExports = { diff --git a/packages/core/src/client/endpoints.ts b/packages/core/src/client/endpoints.ts index 119c7bda..a9be6f15 100644 --- a/packages/core/src/client/endpoints.ts +++ b/packages/core/src/client/endpoints.ts @@ -75,7 +75,11 @@ export function profileSchemaPath(): string { } export function userProfilePath(schemaId: string): string { - return `/api/v2/apps/memory/profile_schemas/${encodeURIComponent(schemaId)}/profiles`; + return `/api/v2/apps/memory/profile_schemas/${encodeURIComponent(schemaId)}/user_profile`; +} + +export function profileSchemaItemPath(schemaId: string): string { + return `/api/v2/apps/memory/profile_schemas/${encodeURIComponent(schemaId)}`; } // ---- Knowledge Base Retrieve (DashScope) ---- diff --git a/packages/core/src/client/index.ts b/packages/core/src/client/index.ts index 31bd04a7..6b66adc2 100644 --- a/packages/core/src/client/index.ts +++ b/packages/core/src/client/index.ts @@ -13,6 +13,7 @@ export { memoryNodePath, memorySearchPath, mcpWebSearchPath, + profileSchemaItemPath, profileSchemaPath, speechRecognizePath, speechSynthesizePath, diff --git a/packages/core/src/types/api.ts b/packages/core/src/types/api.ts index c6c00ec0..cf98552b 100644 --- a/packages/core/src/types/api.ts +++ b/packages/core/src/types/api.ts @@ -305,11 +305,22 @@ export interface MemoryAddRequest { custom_content?: string; profile_schema?: string; memory_library_id?: string; + project_id?: string; + meta_data?: Record; +} + +/** 变更的记忆片段;`event` 为 ADD / UPDATE / DELETE。 */ +export interface MemoryAddNode { + memory_node_id: string; + content: string; + event?: string; + /** 仅 `event` 为 UPDATE 时有效。 */ + old_content?: string; } export interface MemoryAddResponse { request_id: string; - memory_ids?: string[]; + memory_nodes?: MemoryAddNode[]; } export interface MemorySearchRequest { @@ -318,6 +329,17 @@ export interface MemorySearchRequest { query?: string; top_k?: number; memory_library_id?: string; + project_ids?: string[]; + min_score?: number; + /** + * 计费档位的**有效**开关。服务端当前忽略单独传入的 `plan_version`, + * 只有 `enable_rerank: false` 才会按 lite 计费(pro 约为 lite 的 50 倍)。 + */ + enable_rerank?: boolean; + /** 文档所述的档位字段;当前服务端未按文档生效,与 `enable_rerank` 一起传。 */ + plan_version?: "lite" | "pro"; + enable_judge?: boolean; + enable_rewrite?: boolean; } export interface MemoryNode { @@ -325,13 +347,19 @@ export interface MemoryNode { content: string; user_id?: string; meta_data?: Record; - created_at?: string; - updated_at?: string; + project_id?: string; + /** 秒级 Unix 时间戳。 */ + created_at?: number; + /** 秒级 Unix 时间戳。 */ + updated_at?: number; + timestamp?: number; } export interface MemorySearchResponse { request_id: string; memory_nodes: MemoryNode[]; + /** 本次检索实际计费的档位。 */ + billing_plan?: string; } export interface MemoryNodeListResponse { @@ -347,13 +375,18 @@ export interface MemoryNodeUpdateRequest { custom_content: string; /** 非默认记忆库时必填(与控制台记忆库 ID 一致) */ memory_library_id?: string; + /** 记忆片段对应事件发生时的秒级 Unix 时间戳。 */ + timestamp?: number; + /** 增量更新。 */ + meta_data?: Record; } // ---- Memory Profile (DashScope v2) ---- export interface ProfileAttribute { name: string; - description: string; + description?: string; + default_value?: string; value?: string; } @@ -361,6 +394,8 @@ export interface ProfileSchemaCreateRequest { name: string; description?: string; attributes: ProfileAttribute[]; + memory_library_id?: string; + plan_version?: "lite" | "pro"; } export interface ProfileSchemaCreateResponse { @@ -368,12 +403,52 @@ export interface ProfileSchemaCreateResponse { profile_schema_id: string; } +export interface ProfileSchemaSummary { + profile_schema_id: string; + name: string; + description?: string; +} + +export interface ProfileSchemaListResponse { + request_id: string; + profile_schemas: ProfileSchemaSummary[]; + total?: number; +} + +/** 画像模板详情;`attributes[].attribute_id` 是更新/删除属性时的定位键。 */ +export interface ProfileSchemaGetResponse { + request_id: string; + name: string; + description?: string; + attributes: Array; +} + +export interface ProfileSchemaAttributeOperation { + op: "add" | "update" | "delete"; + /** `update` / `delete` 必填。 */ + attribute_id?: string; + /** `add` 必填。 */ + name?: string; + description?: string; + default_value?: string | null; +} + +export interface ProfileSchemaUpdateRequest { + name?: string; + description?: string; + memory_library_id?: string; + attributes_operations?: ProfileSchemaAttributeOperation[]; +} + +/** + * 用户画像。服务端返回的是模板名称/描述与属性值,不回传 schema_id / user_id。 + */ export interface UserProfileResponse { request_id: string; profile: { - schema_id: string; - user_id: string; - attributes: ProfileAttribute[]; + schema_name?: string; + schema_description?: string; + attributes: Array<{ id: string; name: string; value?: string }>; }; } diff --git a/packages/dsh/README.md b/packages/dsh/README.md new file mode 100644 index 00000000..d0908be7 --- /dev/null +++ b/packages/dsh/README.md @@ -0,0 +1,253 @@ +# bailian-cli-dsh + +把阿里云百炼(Model Studio)的能力接入 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(`dsh`)的 profile bundle。 + +一个包提供 5 个插件行,外加对 base bundle 的 `llm-pi-ai` 行做一次配置覆盖: + +| row id | 能力 | 默认 | 依赖 | +| -------------------------------- | --------------------------------------------------------------- | ---- | --------------------- | +| `llm-pi-ai`(覆盖 base 行) | 把百炼 TokenPlan 网关注册成 LLM provider(`bailian-tokenplan`) | 启用 | TokenPlan Key | +| `bailian-tool-vision` | `bailian_vision_describe`:图片/视频理解 | 启用 | `bl` | +| `bailian-tool-image` | `bailian_image_generate`:文生图 | 启用 | `bl` | +| `bailian-web-search-rag` | 百炼知识库检索,注册为 `web_search` 的后端 | 停用 | 按量付费 Key + 知识库 | +| `bailian-memory` | 跨会话长期记忆(tools + 自动检索/落库) | 停用 | 按量付费 Key | +| `bailian-subagent-managed-agent` | 子 agent 跑在百炼托管运行时 | 停用 | `bl` + `agents.yaml` | + +后三个默认停用是有意的:它们要么需要部署方特有的资源 ID,要么按次计费,不该在用户没配置时就生效。 + +--- + +## 1. 前置条件 + +- Node ≥ 22.19(`dsh` 的要求) +- `bl`(vision / image / subagent 三个插件通过子进程调它) + + ```sh + npm install -g bailian-cli + ``` + +- 百炼 API Key。**注意有两类且不可混用**: + + | 类型 | 前缀 | 能访问 | 不能访问 | + | --------- | -------- | --------------------------------------- | -------------- | + | TokenPlan | `sk-sp-` | TokenPlan 网关(LLM / vision / 文生图) | 记忆库、知识库 | + | 按量付费 | `sk-ws-` | 记忆库、知识库、DashScope 全量接口 | TokenPlan 网关 | + + 两者互相返回 `401 InvalidApiKey`,所以本包用**两个不同的环境变量**,不会互相踩: + + ```sh + export BAILIAN_TOKENPLAN_API_KEY=sk-sp-xxx # 只给 bailian-tokenplan provider + export DASHSCOPE_API_KEY=sk-ws-xxx # 给 bl、memory、RAG + ``` + + 只有一类 Key 也能用,只是能力范围相应缩小。若只有 TokenPlan Key: + + ```sh + export BAILIAN_TOKENPLAN_API_KEY=sk-sp-xxx + export DASHSCOPE_API_KEY=sk-sp-xxx + export DASHSCOPE_BASE_URL=https://token-plan.cn-beijing.maas.aliyuncs.com + ``` + + 这样 LLM / vision / 文生图可用,memory 与 RAG 不可用(保持停用即可)。 + +--- + +## 2. 安装到 `web` profile + +`npx @deepseek-ai/dsh web` 是 `dsh --profile web` 的别名,所以要装进**名为 `web` 的 profile**,配置目录是 `~/.dsh/profiles/web/`(`$DSH_HOME` 可覆盖)。 + +本包尚未发布到 npm,先在本仓库打包: + +```sh +pnpm -F bailian-cli-dsh build +cd packages/dsh && pnpm pack # 产出 bailian-cli-dsh-.tgz +``` + +装入 profile(`dsh plugin` 是 pnpm 的转发器,接受本地路径 / tarball / npm 包名 / git): + +```sh +npx @deepseek-ai/dsh plugin --profile web add /absolute/path/to/bailian-cli-dsh-1.14.2.tgz +``` + +因为 `package.json` 声明了 `dsh.bundle`,安装后会自动加入该 profile 的 bundle 层,无需手动改 `cordis.patch.yml`。 + +确认 5 个插入行都在,且 TokenPlan provider 已配到 `llm-pi-ai` 上: + +```sh +npx @deepseek-ai/dsh --profile web --dump-config | grep -E 'bailian|tokenplan' +``` + +启动: + +```sh +npx @deepseek-ai/dsh web +``` + +Web UI 在 http://127.0.0.1:3080。 + +> 发布到 npm 后直接 `npx @deepseek-ai/dsh plugin --profile web add bailian-cli-dsh`,跳过打包步骤。 + +--- + +## 3. 开箱能用的部分 + +装完不做任何配置就生效: + +**LLM provider** — 模型选择器里出现 `bailian-tokenplan`,可选模型(已逐个实测): + +| 模型 | 读图 | +| ------------------------ | ------------------ | +| `qwen3.8-max` | 是 | +| `qwen3.7-plus` | 是 | +| `qwen3.6-flash` | 是 | +| `glm-5.2` | 是 | +| `qwen3.7-max` | 否(传图直接 400) | +| `deepseek-v4-pro` | 否 | +| `deepseek-v4-flash-0731` | 否 | + +**两个工具** — `bailian_vision_describe`、`bailian_image_generate`。 + +### 关于看图,有个坑值得知道 + +dsh 会在两处**提前**拦截图片:Web UI 粘图前会查当前模型的输入模态,`read_image` 也有同样的门禁。所以主模型选 DeepSeek 时,图片根本进不到对话里。 + +- 主模型选 `qwen3.8-max` 等标着"是"的 → 直接粘图,原生看图,不需要任何工具 +- 主模型选 DeepSeek → 让它调 `bailian_vision_describe`,工具返回**文字描述**,绕过模态门禁 + +DeepSeek 那两个模型在 TokenPlan 网关上传图**不报错但也看不见**(实测会回答 "None"),所以本包坚决没给它们声明 `input: [image]`——否则会从"明确拒绝"退化成"静默失明",更难排查。 + +`bailian_image_generate` 同理:模型能看图时返回内联图片,不能看图时降级为返回落盘路径,你可以接着用 vision 工具读它。文件不会被删除,正是为了这个衔接。 + +--- + +## 4. 开启可选插件 + +用户层配置写在 `~/.dsh/profiles/web/cordis.patch.yml`,按 row `id` 覆盖 bundle 的默认值。 + +> **一个必须记住的语义**:patch 是按 row **整体替换 `config`**,不是深合并。所以覆盖一行时要把该行完整的 config 重写一遍。 + +### 知识库检索(RAG) + +注册 id 为 `bailian-kb` 的搜索后端,模型用它熟悉的 `web_search` 就能检索私域文档。 + +```yaml +- id: bailian-web-search-rag + disabled: false + config: + workspaceId: llm-xxxxxxxx # 百炼控制台工作空间 ID + agentId: aid-xxxxxxxx # 知识库"检索服务"ID + maxResults: 10 + # apiKey 省略则读 $DASHSCOPE_API_KEY +``` + +一个实例对一个知识库(`WebSearchRequest` 只带 `query` / `maxResults`,agentId 只能来自配置)。要多个知识库就插多行不同 `id`。 + +**如果 profile 里还有别的搜索 provider**(base bundle 默认带 `web-search-deepseek`),必须显式指定用哪个,否则 dsh 报 `WEB_PROVIDER_AMBIGUOUS`: + +```yaml +- id: web + config: + searchProvider: bailian-kb +``` + +### 长期记忆 + +dsh 自身没有跨会话记忆(`ctx.compaction` 只在单会话内压缩上下文)。开启后:两个工具 `bailian_memory_search` / `bailian_memory_add`,加上每个会话首轮自动检索注入、每轮结束自动落库。 + +```yaml +- id: bailian-memory + disabled: false + config: + userId: your-name # 省略则读 $BAILIAN_MEMORY_USER_ID,再退到系统用户名 + planVersion: lite + topK: 10 + autoInject: true + injectEveryTurn: false # 开启会变成每轮一次检索,成本相应上升 + autoPersist: true +``` + +**费用**:记忆库自 2026-08-20 起商业化,add 与 search 按次计费,pro 档约为 lite 档的 50 倍。 + +实测发现一个与文档不符的地方:单独传 `plan_version: lite` 会被服务端忽略、仍按 pro 计费,真正生效的开关是 `enable_rerank: false`。本插件已按此处理——`planVersion: lite`(默认)会同时下发 `enable_rerank: false`,所以默认就是便宜的那档。 + +不想要自动行为、只保留手动工具: + +```yaml +- id: bailian-memory + disabled: false + config: + userId: your-name + autoInject: false + autoPersist: false +``` + +### 托管子 agent + +把 dsh 的子 agent 派发到百炼云端运行,不占本地资源。 + +先在工作目录准备好清单并应用: + +```sh +bl managed-agent init +bl managed-agent apply --yes +``` + +再开启: + +```yaml +- id: bailian-subagent-managed-agent + disabled: false + config: + file: agents.yaml + agent: assistant + provider: bailian + timeoutMs: 600000 +``` + +两个已知限制:CLI 在会话结束时才一次性输出 JSON,所以**中途没有增量进度**,被取消时也拿不到部分输出;`prepareContinuable` 未实现,即只支持一次性委派,不支持多轮续聊。 + +--- + +## 5. 验证 + +```sh +# 配置是否被正确合成(改完 patch 后先看这个) +npx @deepseek-ai/dsh --profile web --dump-config | grep -A5 bailian-memory + +# bl 是否就绪 +bl auth status +``` + +启动后逐项试: + +- **LLM**:切到 `bailian-tokenplan / qwen3.8-max`,随便发一句 +- **原生看图**:同上模型,直接粘一张图提问 +- **间接看图**:切到 `deepseek-v4-pro`,让它用 `bailian_vision_describe` 读同一张图 +- **文生图**:让模型生成一张图 +- **RAG**:问一个只有知识库里才有答案的问题 +- **记忆**:会话 A 告诉它一个事实 → 关掉 → 新开会话 B 提问,看是否命中 +- **子 agent**:派发一个子任务 + +--- + +## 6. 常见问题 + +| 现象 | 原因 | +| -------------------------------------- | ---------------------------------------------------------------------- | +| LLM 路由 `401 InvalidApiKey` | `BAILIAN_TOKENPLAN_API_KEY` 没设,或误填了 `sk-ws-` 的按量付费 Key | +| memory / RAG `401 InvalidApiKey` | `DASHSCOPE_API_KEY` 误填了 `sk-sp-` 的 TokenPlan Key | +| `WEB_PROVIDER_AMBIGUOUS` | 有多个搜索 provider,需在 `web` 行 pin `searchProvider` | +| 粘图报 `MODEL_DOES_NOT_SUPPORT_IMAGES` | 当前模型不支持图片输入,换成上表标"是"的,或改用 vision 工具 | +| 工具报找不到 `bl` | `bl` 不在 PATH:`npm install -g bailian-cli` | +| 改了 patch 但没生效 | `config` 是整体替换,检查是否漏写了原有字段;再用 `--dump-config` 确认 | +| `memoryLibraryId does not exist` | 记忆库 ID 属于另一个账号,与当前 Key 不匹配 | + +--- + +## 7. 卸载 + +```sh +npx @deepseek-ai/dsh plugin --profile web remove bailian-cli-dsh +``` + +移除后 bundle 层会自动从 `dsh.profile.bundles` 摘掉;`~/.dsh/profiles/web/cordis.patch.yml` 里你手写的覆盖行需要自己清理。 diff --git a/packages/dsh/cordis.patch.yml b/packages/dsh/cordis.patch.yml new file mode 100644 index 00000000..f36f0ee2 --- /dev/null +++ b/packages/dsh/cordis.patch.yml @@ -0,0 +1,97 @@ +# bailian-cli-dsh — Aliyun Model Studio (Bailian) as a dsh profile bundle. +# +# Applied over whatever the earlier layers composed: one config override of the +# base bundle's dormant pi-ai adapter, then one insert of the Bailian tool rows. +# Every inserted id is `bailian-`-prefixed so a user profile can address, +# reconfigure, or disable any single capability without touching the others. +# Remember that a later patch REPLACES a row's whole `config` rather than +# merging into it, so restate the complete config when overriding. + +# TokenPlan configures the base bundle's existing `llm-pi-ai` row instead of +# inserting a second @deepseek-ai/dsh-llm-pi-ai instance. That plugin declares +# pi-ai's entire built-in provider catalog to +# `ctx.llm.registerConfigurableProviders` on every apply, and that registry +# refuses an already-declared provider, so a second instance always fails the +# whole tree with DUPLICATE_DIRECTORY on `amazon-bedrock`. Only adapter routes +# are per-instance; the configurable-provider directory is global. +# +# Replacing this row's whole `config` costs nothing: the base mounts it dormant +# with no config of its own. A profile that needs to drop or re-aim TokenPlan +# restates this row's config rather than disabling an id. +- id: llm-pi-ai + config: + providers: + bailian-tokenplan: + displayName: Aliyun Bailian TokenPlan + api: openai-completions + baseURL: https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1 + # A dedicated name, not DASHSCOPE_API_KEY. TokenPlan keys (sk-sp-) + # and pay-as-you-go keys (sk-ws-) are not interchangeable: this + # gateway 401s a pay-as-you-go key, and the memory / knowledge-base + # endpoints 401 a TokenPlan key. Sharing one variable would make + # whichever plugin loses silently fail to authenticate. + apiKeyEnv: BAILIAN_TOKENPLAN_API_KEY + compat: + thinkingFormat: qwen + supportsReasoningEffort: true + # Verified against GET /compatible-mode/v1/models plus a per-model + # image probe on 2026-08-14. Only `id` is required; context window + # and max tokens fall back to this provider's defaults. + # + # `input: [text, image]` is a claim about the endpoint, not a + # checked fact, and it is what opens the Web UI paste path and + # `read_image`. Every entry carrying it answered a colour question + # about a test PNG correctly. The DeepSeek routes deliberately do + # NOT carry it: they accept image content without erroring and then + # answer "None", so declaring vision would turn a clean refusal + # into a silently blind reply. Use `bailian_vision_describe` there. + # + # Omitted on purpose: wan2.7-image / wan2.7-image-pro are + # generation-only (reach them through `bailian_image_generate`) and + # qwen-audio-3.0-* are audio endpoints, not chat completions. + models: + - id: qwen3.8-max + input: [text, image] + - id: qwen3.7-plus + input: [text, image] + - id: qwen3.6-flash + input: [text, image] + # Rejects image content outright with HTTP 400. + - id: qwen3.7-max + - id: glm-5.2 + input: [text, image] + compat: + thinkingFormat: deepseek + - id: deepseek-v4-pro + compat: + thinkingFormat: deepseek + - id: deepseek-v4-flash-0731 + compat: + thinkingFormat: deepseek + +- insert: + - id: bailian-tool-vision + name: bailian-cli-dsh/tool-vision + + - id: bailian-tool-image + name: bailian-cli-dsh/tool-image + + # Disabled by default: the knowledge base to query is deployment-specific, + # and an enabled provider with no agentId would make `web_search` ambiguous + # for everyone. Set workspaceId + agentId and flip `disabled` to use it. + - id: bailian-web-search-rag + name: bailian-cli-dsh/web-search-rag + disabled: true + config: {} + + # Disabled by default: memory add/search are billed per call. + - id: bailian-memory + name: bailian-cli-dsh/memory + disabled: true + config: {} + + # Disabled by default: requires an applied `agents.yaml` in the workspace. + - id: bailian-subagent-managed-agent + name: bailian-cli-dsh/subagent-managed-agent + disabled: true + config: {} diff --git a/packages/dsh/package.json b/packages/dsh/package.json new file mode 100644 index 00000000..f4f1450a --- /dev/null +++ b/packages/dsh/package.json @@ -0,0 +1,111 @@ +{ + "name": "bailian-cli-dsh", + "version": "1.14.2", + "description": "Aliyun Model Studio (Bailian) plugin bundle for DeepSeek Harness (dsh): TokenPlan LLM provider, knowledge-base RAG search, vision, image generation, long-term memory, and managed-agent subagents.", + "homepage": "https://bailian.console.aliyun.com/cli", + "bugs": { + "url": "https://github.com/modelstudioai/cli/issues" + }, + "license": "Apache-2.0", + "author": "Aliyun Model Studio", + "repository": { + "type": "git", + "url": "git+https://github.com/modelstudioai/cli.git", + "directory": "packages/dsh" + }, + "files": [ + "README.md", + "dist", + "cordis.patch.yml" + ], + "type": "module", + "types": "./dist/index.d.mts", + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + }, + "./tool-vision": { + "types": "./src/tool-vision/index.ts", + "default": "./src/tool-vision/index.ts" + }, + "./tool-image": { + "types": "./src/tool-image/index.ts", + "default": "./src/tool-image/index.ts" + }, + "./web-search-rag": { + "types": "./src/web-search-rag/index.ts", + "default": "./src/web-search-rag/index.ts" + }, + "./memory": { + "types": "./src/memory/index.ts", + "default": "./src/memory/index.ts" + }, + "./subagent-managed-agent": { + "types": "./src/subagent-managed-agent/index.ts", + "default": "./src/subagent-managed-agent/index.ts" + }, + "./cordis.patch.yml": "./cordis.patch.yml", + "./package.json": "./package.json" + }, + "publishConfig": { + "access": "public", + "exports": { + ".": "./dist/index.mjs", + "./tool-vision": "./dist/tool-vision/index.mjs", + "./tool-image": "./dist/tool-image/index.mjs", + "./web-search-rag": "./dist/web-search-rag/index.mjs", + "./memory": "./dist/memory/index.mjs", + "./subagent-managed-agent": "./dist/subagent-managed-agent/index.mjs", + "./cordis.patch.yml": "./cordis.patch.yml", + "./package.json": "./package.json" + }, + "registry": "https://registry.npmjs.org/" + }, + "scripts": { + "build": "vp pack", + "dev": "vp pack --watch", + "test": "vp test", + "check": "vp check" + }, + "dependencies": { + "@deepseek-ai/schemastery": "^3.18.1" + }, + "devDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", + "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", + "@deepseek-ai/dsh-fs": "^0.1.0-rc.6", + "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", + "@deepseek-ai/dsh-session": "^0.1.0-rc.6", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", + "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", + "@deepseek-ai/dsh-web": "^0.1.0-rc.6", + "@types/node": "catalog:", + "typescript": "^6.0.2", + "vite-plus": "catalog:" + }, + "peerDependencies": { + "@deepseek-ai/cordis": "^4.0.1", + "@deepseek-ai/dsh-agent": "^0.1.0-rc.6", + "@deepseek-ai/dsh-attachment": "^0.1.0-rc.6", + "@deepseek-ai/dsh-fs": "^0.1.0-rc.6", + "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.6", + "@deepseek-ai/dsh-llm": "^0.1.0-rc.6", + "@deepseek-ai/dsh-session": "^0.1.0-rc.6", + "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6", + "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6", + "@deepseek-ai/dsh-tools": "^0.1.0-rc.6", + "@deepseek-ai/dsh-web": "^0.1.0-rc.6" + }, + "engines": { + "node": ">=22.19.0" + }, + "dsh": { + "bundle": { + "patch": "./cordis.patch.yml" + } + } +} diff --git a/packages/dsh/src/index.ts b/packages/dsh/src/index.ts new file mode 100644 index 00000000..a60d7312 --- /dev/null +++ b/packages/dsh/src/index.ts @@ -0,0 +1,9 @@ +/** + * bailian-cli-dsh — Aliyun Model Studio capabilities as a DeepSeek Harness + * profile bundle. The package's substance is `cordis.patch.yml`, declared by + * the `dsh.bundle.patch` manifest field and resolved by the profile composer + * through that field; this module carries no runtime API. + * @module bailian-cli-dsh + */ + +export {}; diff --git a/packages/dsh/src/memory/index.ts b/packages/dsh/src/memory/index.ts new file mode 100644 index 00000000..67e98585 --- /dev/null +++ b/packages/dsh/src/memory/index.ts @@ -0,0 +1,369 @@ +/** + * `bailian-cli-dsh/memory`: cross-session long-term memory backed by Bailian's + * hosted memory library. + * + * dsh has no memory seam — `ctx.compaction` only summarizes within one + * session's context window and never writes across sessions — so this plugin + * supplies the whole capability: two tools for deliberate reads and writes, + * plus automatic retrieval and persistence around each turn. + * + * Calls go straight to DashScope rather than through `bl memory`, because the + * v2 API exposes retrieval controls (`min_score`, `plan_version`, + * `enable_rerank`, `meta_data`) the CLI does not surface. + * + * BILLING: add and search are charged per call, and `pro` costs roughly fifty + * times `lite` per search. Automatic behaviour therefore defaults to `lite`, + * retrieves once per session rather than once per turn, and never requests + * profile extraction unless a schema is configured. + * + * @module bailian-cli-dsh/memory + */ +import { userInfo } from "node:os"; +import type { Context } from "@deepseek-ai/cordis"; +import type { Agent, PreStepDecision } from "@deepseek-ai/dsh-agent"; +import type {} from "@deepseek-ai/dsh-agent"; +import type { ContentBlock, Message } from "@deepseek-ai/dsh-llm"; +import { createUserMessage } from "@deepseek-ai/dsh-llm"; +import { defineTool } from "@deepseek-ai/dsh-tools"; +import z from "@deepseek-ai/schemastery"; +import { dashScopeFetch, resolveApiKey, resolveBaseUrl } from "../shared/http.ts"; + +/** Cordis plugin name used by loader diagnostics. */ +export const name = "bailian-memory"; + +/** Seams this plugin registers into. */ +export const inject = ["tools", "agents"]; + +export interface Config { + apiKey?: string; + baseUrl?: string; + /** Memory entity id. Falls back to `$BAILIAN_MEMORY_USER_ID`, then the OS user. */ + userId?: string; + memoryLibraryId?: string; + projectId?: string; + /** Profile template id; omitting it skips profile extraction (and its cost). */ + profileSchema?: string; + /** `lite` disables rerank and is ~50x cheaper per search. */ + planVersion?: "lite" | "pro"; + topK?: number; + minScore?: number; + /** Retrieve relevant memories and inject them into the conversation. */ + autoInject?: boolean; + /** Retrieve on every turn instead of once per session. Costs one search per turn. */ + injectEveryTurn?: boolean; + /** Persist each turn's new messages when the turn closes. */ + autoPersist?: boolean; +} + +export const Config: z = z.object({ + apiKey: z.string().role("secret").description("DashScope key; defaults to $DASHSCOPE_API_KEY."), + baseUrl: z.string().description("DashScope base URL override."), + userId: z.string().description("Memory entity id owning these memories."), + memoryLibraryId: z.string().description("Memory library id; defaults to the account default."), + projectId: z.string().description("Memory extraction rule id."), + profileSchema: z.string().description("Profile template id; enables profile extraction."), + planVersion: z + .union(["lite", "pro"] as const) + .description("Search strategy; pro enables rerank at ~50x the cost."), + topK: z.natural().description("Maximum memories to recall (1-100)."), + minScore: z.number().description("Minimum similarity score, 0-1."), + autoInject: z.boolean().description("Inject recalled memories automatically."), + injectEveryTurn: z.boolean().description("Retrieve every turn instead of once per session."), + autoPersist: z.boolean().description("Persist new messages when a turn closes."), +}); + +const DEFAULT_TOP_K = 10; +const DEFAULT_PLAN_VERSION = "lite"; +const MEMORY_PATH = "/api/v2/apps/memory"; + +interface MemoryNode { + memory_node_id?: string; + content?: string; + event?: string; + old_content?: string; + created_at?: number; + updated_at?: number; +} + +interface MemoryResponse { + request_id?: string; + memory_nodes?: readonly MemoryNode[]; +} + +interface ChatTurn { + role: "user" | "assistant"; + content: string; +} + +/** Resolution order: explicit config, then environment, then the OS user. */ +function resolveUserId(ctx: Context, config: Config): string { + if (config.userId !== undefined && config.userId.length > 0) return config.userId; + const fromEnv = ctx.get("launchEnvironment")?.get("BAILIAN_MEMORY_USER_ID")?.value; + if (fromEnv !== undefined && fromEnv.length > 0) return fromEnv; + return userInfo().username; +} + +function textOf(content: readonly ContentBlock[]): string { + return content + .filter((block): block is Extract => block.type === "text") + .map((block) => block.text) + .join("\n") + .trim(); +} + +/** Plain user/assistant exchanges; tool traffic and injected context are not memories. */ +function conversationTurns(messages: readonly Message[]): ChatTurn[] { + const turns: ChatTurn[] = []; + for (const message of messages) { + if (message.role !== "user" && message.role !== "assistant") continue; + if (message.role === "user" && message.source.kind !== "user") continue; + const text = textOf(message.content); + if (text.length > 0) turns.push({ role: message.role, content: text }); + } + return turns; +} + +class MemoryClient { + constructor( + private readonly apiKey: string, + private readonly baseUrl: string, + private readonly config: Config, + private readonly userId: string, + ) {} + + private shared(): Record { + return { + user_id: this.userId, + ...(this.config.memoryLibraryId !== undefined + ? { memory_library_id: this.config.memoryLibraryId } + : {}), + }; + } + + async add( + messages: readonly ChatTurn[], + signal: AbortSignal | undefined, + overrides?: { customContent?: string; metaData?: Record }, + ): Promise { + return dashScopeFetch({ + url: `${this.baseUrl}${MEMORY_PATH}/add`, + method: "POST", + apiKey: this.apiKey, + signal, + body: { + ...this.shared(), + ...(overrides?.customContent !== undefined + ? { custom_content: overrides.customContent } + : { messages }), + ...(this.config.projectId !== undefined ? { project_id: this.config.projectId } : {}), + ...(this.config.profileSchema !== undefined + ? { profile_schema: this.config.profileSchema } + : {}), + ...(overrides?.metaData !== undefined ? { meta_data: overrides.metaData } : {}), + }, + }); + } + + async search( + messages: readonly ChatTurn[], + signal: AbortSignal | undefined, + overrides?: { topK?: number; minScore?: number; planVersion?: "lite" | "pro" }, + ): Promise { + const planVersion = overrides?.planVersion ?? this.config.planVersion ?? DEFAULT_PLAN_VERSION; + return dashScopeFetch({ + url: `${this.baseUrl}${MEMORY_PATH}/memory_nodes/search`, + method: "POST", + apiKey: this.apiKey, + signal, + body: { + ...this.shared(), + messages, + top_k: overrides?.topK ?? this.config.topK ?? DEFAULT_TOP_K, + ...((overrides?.minScore ?? this.config.minScore) !== undefined + ? { min_score: overrides?.minScore ?? this.config.minScore } + : {}), + // `enable_rerank` is what actually selects the billing tier. Sending + // `plan_version: lite` alone still bills `pro` (verified against the + // live API), despite the documented precedence, and pro costs ~50x + // more per search. Send both: the flag that works, plus the + // documented field in case the server-side precedence is fixed. + enable_rerank: planVersion === "pro", + plan_version: planVersion, + ...(this.config.projectId !== undefined ? { project_ids: [this.config.projectId] } : {}), + }, + }); + } +} + +function renderMemories(nodes: readonly MemoryNode[]): string { + const lines = nodes + .map((node) => node.content?.trim()) + .filter((content): content is string => content !== undefined && content.length > 0) + .map((content) => `- ${content}`); + return `What you remember about this user from earlier sessions:\n${lines.join("\n")}`; +} + +function registerTools(ctx: Context, client: MemoryClient): void { + ctx.tools.register( + defineTool({ + name: "bailian_memory_search", + description: + "Recall facts stored about this user in earlier sessions. Use when the user refers " + + "to prior context, preferences, or decisions you have no record of in this session.", + parameters: { + query: { type: "string", required: true, description: "What to recall." }, + top_k: { type: "integer", description: "Maximum memories to return (1-100)." }, + min_score: { type: "number", description: "Minimum similarity score, 0-1." }, + }, + output: { + schema: { + type: "object", + additionalProperties: false, + properties: { + memories: { + type: "array", + required: true, + items: { + type: "object", + additionalProperties: false, + properties: { + id: { type: "string", required: true }, + content: { type: "string", required: true }, + }, + }, + }, + }, + }, + render: (_args, value) => [ + { + type: "text", + text: + value.memories.length === 0 + ? "No relevant memories." + : value.memories.map((memory) => `- ${memory.content}`).join("\n"), + }, + ], + }, + isConcurrencySafe: () => true, + async execute(args, exec) { + const response = await client.search([{ role: "user", content: args.query }], exec.signal, { + ...(args.top_k !== undefined ? { topK: args.top_k } : {}), + ...(args.min_score !== undefined ? { minScore: args.min_score } : {}), + }); + return { + memories: (response.memory_nodes ?? []).map((node) => ({ + id: node.memory_node_id ?? "", + content: node.content ?? "", + })), + }; + }, + }), + ); + + ctx.tools.register( + defineTool({ + name: "bailian_memory_add", + description: + "Store a durable fact about this user so later sessions can recall it. Use for stable " + + "preferences, decisions, and context — not for transient task state.", + parameters: { + content: { type: "string", required: true, description: "The fact to remember." }, + }, + output: { + schema: { + type: "object", + additionalProperties: false, + properties: { stored: { type: "integer", required: true } }, + }, + render: (_args, value) => [ + { type: "text", text: `Stored ${value.stored} memory fragment(s).` }, + ], + }, + async execute(args, exec) { + const response = await client.add([], exec.signal, { customContent: args.content }); + return { stored: (response.memory_nodes ?? []).length }; + }, + }), + ); +} + +function registerLifecycle(ctx: Context, client: MemoryClient, config: Config): void { + const injected = new WeakSet(); + const persistedUpTo = new WeakMap(); + + if (config.autoInject !== false) { + ctx.on( + "agent/pre-step", + async ({ agent, messages, signal }, next): Promise => { + const decision = await next(); + if (decision.kind !== "enter") return decision; + if (injected.has(agent) && config.injectEveryTurn !== true) return decision; + + const query = textOf(messages.flatMap((message) => message.content)); + if (query.length === 0) return decision; + + let nodes: readonly MemoryNode[]; + try { + const response = await client.search([{ role: "user", content: query }], signal); + nodes = response.memory_nodes ?? []; + } catch { + // Recall is an enhancement; a memory-service outage must not stop the turn. + return decision; + } + injected.add(agent); + if (nodes.length === 0) return decision; + + const text = renderMemories(nodes); + return { + ...decision, + messages: [ + ...decision.messages, + createUserMessage({ + content: [{ type: "text", text }], + source: { + kind: "plugin", + plugin: name, + form: "snapshot", + sections: [{ name, text }], + }, + }), + ], + }; + }, + { prepend: true }, + ); + } + + if (config.autoPersist !== false) { + ctx.on("agent/turn-stopping", async ({ agent, signal }): Promise => { + const turns = conversationTurns(agent.session.deriveMessages()); + const from = persistedUpTo.get(agent) ?? 0; + const fresh = turns.slice(from); + if (fresh.length === 0) return; + persistedUpTo.set(agent, turns.length); + try { + await client.add(fresh, signal); + } catch { + // Persistence is best-effort; never fail a turn over it. + persistedUpTo.set(agent, from); + } + }); + } +} + +export function apply(ctx: Context, config: Config): void { + const apiKey = resolveApiKey(ctx, config.apiKey); + if (apiKey === undefined) { + throw new Error( + "bailian-memory: no DashScope API key. Set $DASHSCOPE_API_KEY or configure `apiKey`.", + ); + } + const client = new MemoryClient( + apiKey, + resolveBaseUrl(ctx, config.baseUrl), + config, + resolveUserId(ctx, config), + ); + registerTools(ctx, client); + registerLifecycle(ctx, client, config); +} diff --git a/packages/dsh/src/shared/bl.ts b/packages/dsh/src/shared/bl.ts new file mode 100644 index 00000000..9f556ad7 --- /dev/null +++ b/packages/dsh/src/shared/bl.ts @@ -0,0 +1,161 @@ +/** + * Shared `bl` invocation for the plugins that delegate to the Bailian CLI + * rather than calling DashScope directly — the ones whose CLI implementation + * carries real substance (async task polling, artifact download, SSE session + * streaming, `agents.yaml` resolution) that a plugin should not restate. + * @module bailian-cli-dsh/shared/bl + */ +import type { Context } from "@deepseek-ai/cordis"; +import type { SubprocessSpawnSpec } from "@deepseek-ai/dsh-subprocess"; +import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment"; + +const DEFAULT_STDOUT_MAX_BYTES = 4 * 1024 * 1024; +const DEFAULT_STDERR_MAX_BYTES = 64 * 1024; +const DEFAULT_GRACE_MS = 5_000; + +/** + * Environment names `bl` reads for credentials, endpoint routing, and profile + * selection. `scrubbedParentEnv()` strips credential-shaped names from every + * harness child, so the key would never reach `bl` unless forwarded here. + */ +const FORWARDED_ENV_NAMES = [ + "DASHSCOPE_API_KEY", + "DASHSCOPE_BASE_URL", + "DASHSCOPE_TIMEOUT", + "BAILIAN_WORKSPACE_ID", + "BAILIAN_CONFIG_DIR", + "ALIBABA_CLOUD_ACCESS_KEY_ID", + "ALIBABA_CLOUD_ACCESS_KEY_SECRET", + "ALIBABA_CLOUD_SECURITY_TOKEN", +] as const; + +/** A `bl` invocation that exited non-zero or produced unreadable output. */ +export class BlError extends Error { + constructor( + message: string, + readonly detail: { argv: readonly string[]; exitCode: number | null; stderr: string }, + options?: { cause?: unknown }, + ) { + super(message, options); + this.name = "BlError"; + } +} + +export interface RunBlOptions { + /** Working directory for the child; callers pass the session cwd. */ + cwd: string; + signal: AbortSignal; + /** Extra entries layered after the forwarded Bailian names. */ + env?: NodeJS.ProcessEnv; + stdoutMaxBytes?: number; + graceMs?: number; +} + +export interface BlOutcome { + stdout: string; + stderr: string; + exitCode: number | null; + terminatedBy: NodeJS.Signals | null; +} + +function abortError(): DOMException { + return new DOMException("bl invocation aborted", "AbortError"); +} + +function forwardedEnv(ctx: Context, extra: NodeJS.ProcessEnv | undefined): NodeJS.ProcessEnv { + const launchEnvironment = launchEnvironmentOf(ctx); + const env: NodeJS.ProcessEnv = {}; + for (const name of FORWARDED_ENV_NAMES) { + const entry = launchEnvironment.get(name); + if (entry !== undefined) env[name] = entry.value; + } + return { ...env, ...extra }; +} + +/** + * Run `bl` to completion and collect its output. + * @throws {BlError} when the executable cannot be resolved. + * @throws {DOMException} `AbortError` when the caller's signal fires. + */ +export async function runBl( + ctx: Context, + argv: readonly string[], + options: RunBlOptions, +): Promise { + if (options.signal.aborted) throw abortError(); + + const env = forwardedEnv(ctx, options.env); + let executable: string; + try { + executable = await ctx.subprocess.resolveExecutable( + "bl", + env as Readonly>, + options.signal, + ); + } catch (error) { + throw new BlError( + "the `bl` executable was not found on PATH; install it with `npm install -g bailian-cli`", + { argv, exitCode: null, stderr: "" }, + { cause: error }, + ); + } + + const spec: SubprocessSpawnSpec = { + argv: [executable, ...argv], + cwd: options.cwd, + stdio: { + stdin: "ignore", + stdout: { maxBytes: options.stdoutMaxBytes ?? DEFAULT_STDOUT_MAX_BYTES }, + stderr: { maxBytes: DEFAULT_STDERR_MAX_BYTES }, + }, + graceMs: options.graceMs ?? DEFAULT_GRACE_MS, + signal: options.signal, + env, + }; + + const handle = ctx.subprocess.spawn(spec); + if (options.signal.aborted) throw abortError(); + + const outcome = await handle.done; + if (options.signal.aborted) throw abortError(); + + return { + stdout: handle.collected.stdout?.readFrom(0).text ?? "", + stderr: handle.collected.stderr?.readFrom(0).text ?? "", + exitCode: outcome.exitCode, + terminatedBy: outcome.signal, + }; +} + +/** + * Run `bl … --output json` and parse stdout. + * @throws {BlError} on non-zero exit or unparseable stdout. + */ +export async function runBlJson( + ctx: Context, + argv: readonly string[], + options: RunBlOptions, +): Promise { + const withJson = [...argv, "--output", "json"]; + const outcome = await runBl(ctx, withJson, options); + + if (outcome.exitCode !== 0) { + // bl passes service errors through verbatim; surface them unchanged. + const reason = outcome.stderr.trim() || outcome.stdout.trim() || "no diagnostics on stderr"; + throw new BlError(`bl ${argv.join(" ")} failed: ${reason}`, { + argv: withJson, + exitCode: outcome.exitCode, + stderr: outcome.stderr, + }); + } + + try { + return JSON.parse(outcome.stdout) as T; + } catch (error) { + throw new BlError( + `bl ${argv.join(" ")} did not emit JSON on stdout`, + { argv: withJson, exitCode: outcome.exitCode, stderr: outcome.stderr }, + { cause: error }, + ); + } +} diff --git a/packages/dsh/src/shared/http.ts b/packages/dsh/src/shared/http.ts new file mode 100644 index 00000000..24fa6e1c --- /dev/null +++ b/packages/dsh/src/shared/http.ts @@ -0,0 +1,98 @@ +/** + * Direct DashScope HTTP for the plugins whose CLI counterpart does not expose + * the full parameter surface (long-term memory, knowledge-base retrieval). + * Service errors pass through verbatim — this layer classifies nothing. + * @module bailian-cli-dsh/shared/http + */ +import type { Context } from "@deepseek-ai/cordis"; +import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment"; + +export const DASHSCOPE_DEFAULT_BASE_URL = "https://dashscope.aliyuncs.com"; + +/** A non-2xx DashScope response, carrying the server's own wording. */ +export class DashScopeError extends Error { + constructor( + message: string, + readonly detail: { status: number; code?: string; requestId?: string }, + options?: { cause?: unknown }, + ) { + super(message, options); + this.name = "DashScopeError"; + } +} + +/** + * Resolve the DashScope key from explicit config, then the launch environment + * (process env, project `.env`, harness-home `.env`). + */ +export function resolveApiKey(ctx: Context, explicit?: string): string | undefined { + if (explicit !== undefined && explicit.length > 0) return explicit; + const entry = launchEnvironmentOf(ctx).get("DASHSCOPE_API_KEY"); + return entry !== undefined && entry.value.length > 0 ? entry.value : undefined; +} + +export function resolveBaseUrl(ctx: Context, explicit?: string): string { + if (explicit !== undefined && explicit.length > 0) return explicit; + const entry = launchEnvironmentOf(ctx).get("DASHSCOPE_BASE_URL"); + return entry !== undefined && entry.value.length > 0 ? entry.value : DASHSCOPE_DEFAULT_BASE_URL; +} + +export interface DashScopeRequest { + url: string; + method: "GET" | "POST" | "PATCH" | "DELETE"; + apiKey: string; + body?: unknown; + signal?: AbortSignal | undefined; +} + +interface DashScopeErrorBody { + code?: string; + message?: string; + request_id?: string; + error?: { code?: string; message?: string }; +} + +/** + * Issue one DashScope request and parse its JSON body. + * @throws {DashScopeError} on a non-2xx response or an unreadable body. + */ +export async function dashScopeFetch(request: DashScopeRequest): Promise { + const response = await fetch(request.url, { + method: request.method, + headers: { + Authorization: `Bearer ${request.apiKey}`, + "Content-Type": "application/json", + }, + ...(request.body !== undefined ? { body: JSON.stringify(request.body) } : {}), + ...(request.signal !== undefined ? { signal: request.signal } : {}), + redirect: "error", + }); + + const text = await response.text(); + + if (!response.ok) { + let parsed: DashScopeErrorBody = {}; + try { + parsed = JSON.parse(text) as DashScopeErrorBody; + } catch { + // A non-JSON error body is still worth surfacing as-is. + } + const code = parsed.code ?? parsed.error?.code; + const message = parsed.message ?? parsed.error?.message ?? text.trim(); + throw new DashScopeError(message.length > 0 ? message : `HTTP ${response.status}`, { + status: response.status, + ...(code !== undefined ? { code } : {}), + ...(parsed.request_id !== undefined ? { requestId: parsed.request_id } : {}), + }); + } + + try { + return JSON.parse(text) as T; + } catch (error) { + throw new DashScopeError( + "DashScope returned a non-JSON success body", + { status: response.status }, + { cause: error }, + ); + } +} diff --git a/packages/dsh/src/subagent-managed-agent/index.ts b/packages/dsh/src/subagent-managed-agent/index.ts new file mode 100644 index 00000000..bab0a5b2 --- /dev/null +++ b/packages/dsh/src/subagent-managed-agent/index.ts @@ -0,0 +1,205 @@ +/** + * `bailian-cli-dsh/subagent-managed-agent`: runs child agents on Bailian's + * hosted managed-agent runtime instead of in this process, through + * `bl managed-agent session run`. + * + * Out-of-process delegation is an established shape here — `subagent-acp` and + * `subagent-codex` do the same over their own transports. Going through the + * CLI keeps `agents.yaml` resolution, provider selection, and SSE decoding in + * one place. + * + * Two honest limits. The CLI buffers the whole session and emits it at exit, + * so no incremental progress reaches the parent and a cancelled run yields no + * partial output. And `prepareContinuable` is deliberately absent: method + * presence IS the continuable capability, and multi-turn continuation is not + * wired up yet. + * + * @module bailian-cli-dsh/subagent-managed-agent + */ +import type { Context } from "@deepseek-ai/cordis"; +import type { ContentBlock } from "@deepseek-ai/dsh-llm"; +import { SessionId } from "@deepseek-ai/dsh-session"; +import type { + ResolvedSubagentStartRequest, + SubagentCapabilities, + SubagentProvider, + SubagentResult, + SubagentRun, +} from "@deepseek-ai/dsh-subagent"; +import type {} from "@deepseek-ai/dsh-fs"; +import z from "@deepseek-ai/schemastery"; +import { runBlJson } from "../shared/bl.ts"; + +/** Cordis plugin name used by loader diagnostics. */ +export const name = "bailian-subagent-managed-agent"; + +/** Seams this plugin registers into. */ +export const inject = ["subagents", "subprocess", "fs"]; + +/** Registry name callers select this transport by. */ +export const BAILIAN_MANAGED_AGENT_PROVIDER = "bailian-managed-agent"; + +export interface Config { + /** Manifest passed as `--file`; must already be applied. */ + file?: string; + /** Agent name within the manifest. */ + agent?: string; + /** Backing provider understood by `bl managed-agent`. */ + provider?: string; + /** Cooperative budget for one hosted run. */ + timeoutMs?: number; +} + +export const Config: z = z.object({ + file: z.string().description("Path to agents.yaml; defaults to the CLI's own default."), + agent: z.string().description("Agent name declared in the manifest."), + provider: z.string().description("Managed-agent backing provider."), + timeoutMs: z.natural().description("Cooperative timeout budget in milliseconds."), +}); + +const DEFAULT_MANIFEST = "agents.yaml"; +const DEFAULT_TIMEOUT_MS = 600_000; + +/** A one-shot transport supports none of the start-time features. */ +const CAPABILITIES: SubagentCapabilities = { + outputSchema: false, + depthLimit: false, + toolFilter: false, + persona: false, +}; + +interface SessionEvent { + type?: string; + content?: unknown; + role?: string; +} + +interface SessionRunResponse { + session_id?: string; + events?: readonly SessionEvent[]; +} + +function promptText(blocks: readonly ContentBlock[]): string { + return blocks + .filter((block): block is Extract => block.type === "text") + .map((block) => block.text) + .join("\n") + .trim(); +} + +/** Assistant-visible text of a finished hosted session. */ +function assistantOutput(events: readonly SessionEvent[]): ContentBlock[] { + const text = events + .filter((event) => event.type === "message" && typeof event.content === "string") + .map((event) => event.content as string) + .join("\n") + .trim(); + return text.length > 0 ? [{ type: "text", text }] : []; +} + +function isAbort(error: unknown): boolean { + return error instanceof DOMException && error.name === "AbortError"; +} + +class BailianManagedAgentProvider implements SubagentProvider { + readonly name = BAILIAN_MANAGED_AGENT_PROVIDER; + readonly capabilities = CAPABILITIES; + readonly inheritsParentContext = false; + + constructor( + private readonly ctx: Context, + private readonly config: Config, + ) {} + + async start(request: ResolvedSubagentStartRequest): Promise { + const cwd = request.parent.session.header.cwd ?? process.cwd(); + const manifest = this.config.file ?? DEFAULT_MANIFEST; + + // Pre-publication: a missing manifest is the common misconfiguration and + // deserves a start-time rejection rather than a failed run. + const target = await this.ctx.fs.resolve(manifest, { cwd, signal: request.signal }); + const info = await this.ctx.fs.stat(target, request.signal); + if (info === undefined) { + throw new Error( + `bailian-managed-agent: no manifest at "${target.displayPath}". Create one with ` + + `\`bl managed-agent init\` and apply it with \`bl managed-agent apply --yes\`.`, + ); + } + + const prompt = promptText(request.prompt); + if (prompt.length === 0) { + throw new Error("bailian-managed-agent: the prompt carried no text content."); + } + + const argv = ["managed-agent", "session", "run", "--prompt", prompt, "--file", manifest]; + if (this.config.agent !== undefined) argv.push("--agent", this.config.agent); + if (this.config.provider !== undefined) argv.push("--provider", this.config.provider); + + const controller = new AbortController(); + const abort = (): void => controller.abort(); + request.signal.addEventListener("abort", abort, { once: true }); + + // The seam has no deadline of its own — cancellation arrives only through + // the caller's signal — so the transport owns one, or a wedged hosted + // session never settles. + const deadline = AbortSignal.timeout(this.config.timeoutMs ?? DEFAULT_TIMEOUT_MS); + const combined = AbortSignal.any([controller.signal, deadline]); + + // Ownership transfers on fulfillment, so every later failure settles + // through `result` — which must not reject for child-level problems. + const result = this.execute(argv, cwd, combined, deadline).finally(() => { + request.signal.removeEventListener("abort", abort); + }); + + let disposal: Promise | undefined; + return { + id: SessionId(`bailian-managed-agent:${crypto.randomUUID()}`), + localAgent: undefined, + result, + dispose: (): Promise => { + disposal ??= (async (): Promise => { + controller.abort(); + await result; + })(); + return disposal; + }, + }; + } + + private async execute( + argv: readonly string[], + cwd: string, + signal: AbortSignal, + deadline: AbortSignal, + ): Promise { + try { + const response = await runBlJson(this.ctx, argv, { + cwd, + signal, + graceMs: 10_000, + }); + return { output: assistantOutput(response.events ?? []), stopReason: "completed" }; + } catch (error) { + if (deadline.aborted) { + return { + output: [ + { + type: "text", + text: `the hosted session exceeded ${this.config.timeoutMs ?? DEFAULT_TIMEOUT_MS}ms and was terminated`, + }, + ], + stopReason: "error", + }; + } + // The CLI emits its JSON envelope only at exit, so a cancelled run has + // no partial output to salvage. + if (isAbort(error) || signal.aborted) return { output: [], stopReason: "aborted" }; + const reason = error instanceof Error ? error.message : String(error); + return { output: [{ type: "text", text: reason }], stopReason: "error" }; + } + } +} + +export function apply(ctx: Context, config: Config): void { + ctx.subagents.registerProvider(new BailianManagedAgentProvider(ctx, config)); +} diff --git a/packages/dsh/src/tool-image/index.ts b/packages/dsh/src/tool-image/index.ts new file mode 100644 index 00000000..6c1982f3 --- /dev/null +++ b/packages/dsh/src/tool-image/index.ts @@ -0,0 +1,239 @@ +/** + * `bailian-cli-dsh/tool-image`: image generation through `bl image generate`. + * + * Delegating to the CLI keeps the async-task polling, model-to-endpoint + * routing, and artifact download in one place rather than restating them here. + * + * Generated files are committed to `ctx.attachments` and returned as + * `ImageBlock`s when the calling route declares image input. When it does not + * — DeepSeek routes never do — the tool degrades to reporting the saved paths + * instead of failing, so the model can hand one to `bailian_vision_describe`. + * For that fallback to work the files must survive the call, so this tool + * deliberately does not delete what the CLI wrote. + * + * @module bailian-cli-dsh/tool-image + */ +import type { Context } from "@deepseek-ai/cordis"; +import type { ImageAttachmentRef, ImageMediaType } from "@deepseek-ai/dsh-attachment"; +import { AttachmentId } from "@deepseek-ai/dsh-attachment"; +import type { ContentBlock } from "@deepseek-ai/dsh-llm"; +import type {} from "@deepseek-ai/dsh-fs"; +import { defineTool } from "@deepseek-ai/dsh-tools"; +import type { ToolExecution } from "@deepseek-ai/dsh-tools"; +import z from "@deepseek-ai/schemastery"; +import { runBlJson } from "../shared/bl.ts"; + +/** Cordis plugin name used by loader diagnostics. */ +export const name = "bailian-tool-image"; + +/** Seams this plugin registers into. */ +export const inject = ["tools", "subprocess", "fs"]; + +export interface Config { + /** Image model passed to `bl image generate --model`. */ + model?: string; + /** Directory for generated files; defaults to the CLI's own output dir. */ + outDir?: string; + /** Cooperative budget; async models poll until the task succeeds. */ + timeoutMs?: number; +} + +export const Config: z = z.object({ + model: z.string().description("Image model; defaults to the CLI's own default."), + outDir: z.string().description("Directory for generated files."), + timeoutMs: z.natural().description("Cooperative timeout budget in milliseconds."), +}); + +const DEFAULT_TIMEOUT_MS = 300_000; +const MAX_IMAGES = 6; + +const MEDIA_TYPE_BY_EXTENSION: Readonly> = { + png: "image/png", + jpg: "image/jpeg", + jpeg: "image/jpeg", + webp: "image/webp", + gif: "image/gif", +}; + +interface ImageGenerateResponse { + urls?: readonly string[]; + saved?: readonly string[]; + total?: number; +} + +/** One committed image, stored as plain JSON so `render` stays pure. */ +interface CommittedImage { + attachmentId: string; + mediaType: ImageMediaType; + bytes: number; + width: number; + height: number; + path: string; +} + +function mediaTypeOf(path: string): ImageMediaType | undefined { + const extension = path.split(".").pop()?.toLowerCase(); + return extension === undefined ? undefined : MEDIA_TYPE_BY_EXTENSION[extension]; +} + +function attachmentRefOf(image: CommittedImage): ImageAttachmentRef { + return { + attachmentId: AttachmentId(image.attachmentId), + mediaType: image.mediaType, + bytes: image.bytes, + width: image.width, + height: image.height, + }; +} + +/** + * Whether the calling route declares image input. Unlike `read_image`'s hard + * gate this only reports, because an unroutable or text-only model is a reason + * to fall back to paths rather than to refuse generating anything. + */ +async function routeAcceptsImages(ctx: Context, exec: ToolExecution): Promise { + const routed = exec.agent?.session.requestHeader()?.config; + const provider = routed?.provider ?? exec.agent?.options.provider; + const model = routed?.model ?? exec.agent?.options.model; + const llm = ctx.get("llm"); + if (provider === undefined || model === undefined || llm === undefined) return false; + try { + const active = await llm.resolveModelInfo(provider, model, exec.signal); + return active.inputModalities?.includes("image") === true; + } catch { + return false; + } +} + +export function apply(ctx: Context, config: Config): void { + ctx.tools.register( + defineTool({ + name: "bailian_image_generate", + description: + "Generate images from a text prompt using Aliyun Bailian (Qwen-Image / Wan). " + + "Files are written to disk and returned inline when the active model can view " + + "images; otherwise the saved paths are reported and you can inspect one with " + + "`bailian_vision_describe`.", + parameters: { + prompt: { + type: "string", + required: true, + description: "What to depict. Be specific about subject, style, and composition.", + }, + model: { type: "string", description: "Override the configured image model." }, + size: { + type: "string", + description: 'Aspect ratio such as "1:1" / "16:9", or explicit pixels as "1024*1024".', + }, + n: { + type: "integer", + description: `How many images to generate (1-${MAX_IMAGES}).`, + }, + negative_prompt: { type: "string", description: "What to avoid depicting." }, + seed: { type: "integer", description: "Seed for reproducible generation." }, + }, + output: { + schema: { + type: "object", + additionalProperties: false, + properties: { + images: { + type: "array", + required: true, + items: { + type: "object", + additionalProperties: false, + properties: { + attachmentId: { type: "string", required: true }, + mediaType: { type: "string", required: true }, + bytes: { type: "integer", required: true }, + width: { type: "integer", required: true }, + height: { type: "integer", required: true }, + path: { type: "string", required: true }, + }, + }, + }, + paths: { type: "array", required: true, items: { type: "string" } }, + urls: { type: "array", required: true, items: { type: "string" } }, + }, + }, + render: (_args, value) => { + const paths = value.paths.join("\n"); + if (value.images.length === 0) { + return [ + { + type: "text", + text: + `Generated ${value.paths.length} image(s); the active model cannot view ` + + `images, so they are on disk only. Use bailian_vision_describe to inspect ` + + `one.\n${paths}`, + }, + ]; + } + const blocks: ContentBlock[] = [ + { type: "text", text: `Generated ${value.images.length} image(s):\n${paths}` }, + ]; + for (const image of value.images) { + blocks.push({ type: "image", attachment: attachmentRefOf(image as CommittedImage) }); + } + return blocks; + }, + }, + timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS, + async execute(args, exec) { + if (args.n !== undefined && (args.n < 1 || args.n > MAX_IMAGES)) { + throw new Error(`bailian_image_generate accepts n between 1 and ${MAX_IMAGES}.`); + } + + const cwd = exec.agent?.session.header.cwd ?? process.cwd(); + const argv = ["image", "generate", "--prompt", args.prompt]; + const model = args.model ?? config.model; + if (model !== undefined) argv.push("--model", model); + if (args.size !== undefined) argv.push("--size", args.size); + if (args.n !== undefined) argv.push("--n", String(args.n)); + if (args.negative_prompt !== undefined) + argv.push("--negative-prompt", args.negative_prompt); + if (args.seed !== undefined) argv.push("--seed", String(args.seed)); + if (config.outDir !== undefined) argv.push("--out-dir", config.outDir); + + const response = await runBlJson(ctx, argv, { + cwd, + signal: exec.signal, + }); + + const paths = [...(response.saved ?? [])]; + const urls = [...(response.urls ?? [])]; + if (paths.length === 0) { + throw new Error("bl image generate reported no saved files."); + } + + const attachments = ctx.get("attachments"); + const images: CommittedImage[] = []; + if (attachments !== undefined && (await routeAcceptsImages(ctx, exec))) { + const byteCap = Math.min( + attachments.imageLimits.maxImageBytes, + attachments.imageLimits.maxMessageImageBytes, + ); + for (const path of paths) { + const mediaType = mediaTypeOf(path); + if (mediaType === undefined || !attachments.imageLimits.mediaTypes.includes(mediaType)) + continue; + const target = await ctx.fs.resolve(path, { cwd, signal: exec.signal }); + const data = await ctx.fs.readBytes(target, exec.signal, byteCap); + const ref = await attachments.saveImage({ data, mediaType, name: target.displayPath }); + images.push({ + attachmentId: ref.attachmentId, + mediaType: ref.mediaType, + bytes: ref.bytes, + width: ref.width, + height: ref.height, + path, + }); + } + } + + return { images, paths, urls }; + }, + }), + ); +} diff --git a/packages/dsh/src/tool-vision/index.ts b/packages/dsh/src/tool-vision/index.ts new file mode 100644 index 00000000..f703179c --- /dev/null +++ b/packages/dsh/src/tool-vision/index.ts @@ -0,0 +1,135 @@ +/** + * `bailian-cli-dsh/tool-vision`: image and video understanding through + * `bl vision describe` (Qwen-VL). + * + * The tool returns TEXT, never an `ImageBlock` — that is deliberate. dsh gates + * image content on the active route's declared input modalities in two places + * before a plugin ever sees it (the Web UI paste pre-check and `read_image`), + * so a text-only main model such as DeepSeek cannot receive pictures at all. + * Handing back a description instead gives those routes vision indirectly. + * A genuinely multimodal route does not need this tool and should paste images + * directly. + * + * @module bailian-cli-dsh/tool-vision + */ +import type { Context } from "@deepseek-ai/cordis"; +import { defineTool } from "@deepseek-ai/dsh-tools"; +import type {} from "@deepseek-ai/dsh-tools"; +import z from "@deepseek-ai/schemastery"; +import { runBlJson } from "../shared/bl.ts"; + +/** Cordis plugin name used by loader diagnostics. */ +export const name = "bailian-tool-vision"; + +/** Seams this plugin registers into. */ +export const inject = ["tools", "subprocess"]; + +export interface Config { + /** Vision model passed to `bl vision describe --model`. */ + model?: string; + /** Cooperative budget; video understanding uploads and is slow. */ + timeoutMs?: number; +} + +export const Config: z = z.object({ + model: z.string().description("Vision model; defaults to the CLI's own default."), + timeoutMs: z.natural().description("Cooperative timeout budget in milliseconds."), +}); + +const DEFAULT_TIMEOUT_MS = 180_000; + +/** The OpenAI-shaped body `bl vision describe --output json` passes through. */ +interface VisionResponse { + model?: string; + request_id?: string; + choices?: readonly { + message?: { content?: unknown }; + }[]; +} + +/** Chat content is a string or an array of typed parts; keep only the text. */ +function readContent(content: unknown): string { + if (typeof content === "string") return content; + if (!Array.isArray(content)) return ""; + return content + .map((part) => + typeof part === "object" && part !== null && "text" in part + ? String((part as { text: unknown }).text) + : "", + ) + .join("") + .trim(); +} + +export function apply(ctx: Context, config: Config): void { + ctx.tools.register( + defineTool({ + name: "bailian_vision_describe", + description: + "Understand an image or video using Aliyun Bailian's Qwen-VL models. " + + "Accepts a local file path or a URL and returns a text description, so it works " + + "even when the active model cannot take image input. Ask a specific question " + + "through `prompt` (for example OCR, chart reading, or object identification) " + + "instead of relying on the generic default.", + parameters: { + image: { + type: "string", + description: "Local image path or http(s)/oss URL. Provide this or `video`.", + }, + video: { + type: "array", + items: { type: "string" }, + description: + "Video file paths or URLs (mp4/mov/avi/mkv/webm). Local files are uploaded first.", + }, + prompt: { + type: "string", + description: "Question about the content. Defaults to a plain description request.", + }, + model: { + type: "string", + description: "Override the configured vision model.", + }, + }, + output: { + schema: { + type: "object", + additionalProperties: false, + properties: { + description: { type: "string", required: true }, + model: { type: "string", required: true }, + }, + }, + render: (_args, value) => [{ type: "text", text: value.description }], + }, + timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS, + isConcurrencySafe: () => true, + async execute(args, exec) { + const videos = args.video ?? []; + if (args.image === undefined && videos.length === 0) { + throw new Error("bailian_vision_describe requires `image` or `video`."); + } + + const argv = ["vision", "describe"]; + if (args.image !== undefined) argv.push("--image", args.image); + for (const video of videos) argv.push("--video", video); + if (args.prompt !== undefined) argv.push("--prompt", args.prompt); + + const model = args.model ?? config.model; + if (model !== undefined) argv.push("--model", model); + + const response = await runBlJson(ctx, argv, { + cwd: exec.agent?.session.header.cwd ?? process.cwd(), + signal: exec.signal, + }); + + const description = readContent(response.choices?.[0]?.message?.content); + if (description.length === 0) { + throw new Error("Qwen-VL returned an empty description."); + } + + return { description, model: response.model ?? model ?? "" }; + }, + }), + ); +} diff --git a/packages/dsh/src/web-search-rag/index.ts b/packages/dsh/src/web-search-rag/index.ts new file mode 100644 index 00000000..1d312645 --- /dev/null +++ b/packages/dsh/src/web-search-rag/index.ts @@ -0,0 +1,161 @@ +/** + * `bailian-cli-dsh/web-search-rag`: registers a Bailian knowledge-base + * `WebSearchProvider` with `ctx.web`. + * + * Retrieval is modelled as a search provider rather than a bespoke tool so the + * model reaches private corpora through the `web_search` it already knows — + * no new tool, no new prompting. Calls go straight to DashScope because the + * seam needs per-call control the CLI does not surface. + * + * One instance serves one knowledge base: `WebSearchRequest` carries only + * `query` and `maxResults`, so the agent id has to come from config. Insert + * additional rows with distinct ids to expose more than one. + * + * @module bailian-cli-dsh/web-search-rag + */ +import type { Context } from "@deepseek-ai/cordis"; +import type { + WebSearchProvider, + WebSearchRequest, + WebSearchResult, + WebSearchSource, +} from "@deepseek-ai/dsh-web"; +import { WebError } from "@deepseek-ai/dsh-web"; +import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment"; +import z from "@deepseek-ai/schemastery"; +import { dashScopeFetch, resolveApiKey } from "../shared/http.ts"; + +/** Cordis plugin name used by loader diagnostics. */ +export const name = "bailian-web-search-rag"; + +/** The web seam this provider registers into. */ +export const inject = ["web"]; + +/** Stable provider id; pin it as `searchProvider` to disambiguate. */ +export const BAILIAN_KB_PROVIDER_ID = "bailian-kb"; + +export interface Config { + /** DashScope key; falls back to `DASHSCOPE_API_KEY`. */ + apiKey?: string; + /** Workspace id; also the retrieval host prefix. Falls back to `BAILIAN_WORKSPACE_ID`. */ + workspaceId?: string; + /** Retrieval service id from the console's knowledge retrieval page. */ + agentId?: string; + /** Default upper bound when the caller sets none. */ + maxResults?: number; +} + +export const Config: z = z.object({ + apiKey: z + .string() + .role("secret") + .description("DashScope API key; defaults to $DASHSCOPE_API_KEY."), + workspaceId: z.string().description("Bailian workspace id; defaults to $BAILIAN_WORKSPACE_ID."), + agentId: z.string().description("Retrieval service (agent) id identifying the knowledge base."), + maxResults: z.natural().description("Default source cap when the caller sets none."), +}); + +const DEFAULT_MAX_RESULTS = 10; + +interface KnowledgeSearchNode { + score?: number; + text?: string; + metadata?: { + title?: string; + doc_id?: string; + doc_name?: string; + doc_url?: string; + page_number?: number; + }; +} + +interface KnowledgeSearchResponse { + data?: { total?: number; nodes?: readonly KnowledgeSearchNode[] }; +} + +export interface BailianKbProviderOptions { + apiKey: string; + workspaceId: string; + agentId: string; + maxResults: number; +} + +function isAbort(error: unknown): boolean { + return error instanceof DOMException && error.name === "AbortError"; +} + +/** The seam requires a URL; documents without one still deserve a stable identity. */ +function sourceUrl(node: KnowledgeSearchNode, index: number): string { + const url = node.metadata?.doc_url; + if (url !== undefined && url.length > 0) return url; + return `bailian-kb://${node.metadata?.doc_id ?? `node-${index}`}`; +} + +export class BailianKbSearchProvider implements WebSearchProvider { + readonly id = BAILIAN_KB_PROVIDER_ID; + + constructor(private readonly options: BailianKbProviderOptions) {} + + available(): boolean { + return ( + this.options.apiKey.length > 0 && + this.options.workspaceId.length > 0 && + this.options.agentId.length > 0 + ); + } + + async search(request: WebSearchRequest, signal?: AbortSignal): Promise { + const limit = request.maxResults ?? this.options.maxResults; + let response: KnowledgeSearchResponse; + try { + response = await dashScopeFetch({ + url: `https://${this.options.workspaceId}.cn-beijing.maas.aliyuncs.com/api/v1/indices/knowledge/search`, + method: "POST", + apiKey: this.options.apiKey, + body: { query: request.query, agent_id: this.options.agentId }, + signal, + }); + } catch (error) { + if (isAbort(error)) + throw new WebError("knowledge base search aborted", "WEB_ABORTED", { cause: error }); + const reason = error instanceof Error ? error.message : String(error); + throw new WebError(`knowledge base search failed: ${reason}`, "WEB_PROVIDER_ERROR", { + cause: error, + }); + } + + const nodes = (response.data?.nodes ?? []).slice(0, limit); + const sources: WebSearchSource[] = nodes.map((node, index) => { + const metadata = node.metadata ?? {}; + const title = metadata.doc_name ?? metadata.title; + const text = node.text ?? ""; + return { + url: sourceUrl(node, index), + ...(title !== undefined ? { title } : {}), + ...(text.length > 0 ? { snippet: text } : {}), + }; + }); + + const content = nodes + .map((node) => node.text ?? "") + .filter((text) => text.length > 0) + .join("\n\n"); + + // Truncation is the seam's job; report what this provider returned. + return { ...(content.length > 0 ? { content } : {}), sources, truncated: false }; + } +} + +export function apply(ctx: Context, config: Config): void { + const workspaceId = + config.workspaceId ?? launchEnvironmentOf(ctx).get("BAILIAN_WORKSPACE_ID")?.value ?? ""; + + ctx.web.registerSearchProvider( + new BailianKbSearchProvider({ + apiKey: resolveApiKey(ctx, config.apiKey) ?? "", + workspaceId, + agentId: config.agentId ?? "", + maxResults: config.maxResults ?? DEFAULT_MAX_RESULTS, + }), + ); +} diff --git a/packages/dsh/tsconfig.json b/packages/dsh/tsconfig.json new file mode 100644 index 00000000..ff4adab5 --- /dev/null +++ b/packages/dsh/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "esnext", + "lib": ["es2023"], + "moduleDetection": "force", + "module": "nodenext", + "moduleResolution": "nodenext", + "resolveJsonModule": true, + "types": ["node"], + "strict": true, + "noUnusedLocals": true, + "declaration": true, + "noEmit": true, + "allowImportingTsExtensions": true, + "esModuleInterop": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "skipLibCheck": true + } +} diff --git a/packages/dsh/vite.config.ts b/packages/dsh/vite.config.ts new file mode 100644 index 00000000..2dd837d3 --- /dev/null +++ b/packages/dsh/vite.config.ts @@ -0,0 +1,27 @@ +import { defineConfig } from "vite-plus"; + +export default defineConfig({ + pack: { + // One entry per `exports` subpath: each dsh plugin row imports its own + // module specifier, so they cannot share a bundle. + entry: [ + "src/index.ts", + "src/tool-vision/index.ts", + "src/tool-image/index.ts", + "src/web-search-rag/index.ts", + "src/memory/index.ts", + "src/subagent-managed-agent/index.ts", + ], + minify: true, + dts: { + tsgo: true, + }, + }, + lint: { + options: { + typeAware: true, + typeCheck: true, + }, + }, + fmt: {}, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb698a35..b7f2b35d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,7 +1,7 @@ lockfileVersion: '9.0' settings: - autoInstallPeers: true + autoInstallPeers: false excludeLinksFromLockfile: false catalogs: @@ -24,12 +24,12 @@ catalogs: chalk: specifier: ^5.6.2 version: 5.6.2 - tar-stream: - specifier: ^3.2.0 - version: 3.2.0 smol-toml: specifier: ^1.4.2 version: 1.7.0 + tar-stream: + specifier: ^3.2.0 + version: 3.2.0 tsx: specifier: ^4.23.0 version: 4.23.0 @@ -59,7 +59,7 @@ importers: version: 4.23.0 vite-plus: specifier: 'catalog:' - version: 0.1.22(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.9.0))(yaml@2.9.0) + version: 0.1.22(@types/node@25.6.0)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) packages/cli: dependencies: @@ -105,7 +105,7 @@ importers: version: 6.27.0 vite-plus: specifier: 0.1.22 - version: 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.8.3))(yaml@2.8.3) + version: 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3) yaml: specifier: 'catalog:' version: 2.8.3 @@ -148,7 +148,7 @@ importers: version: 6.0.3 vite-plus: specifier: 0.1.22 - version: 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.8.3))(yaml@2.8.3) + version: 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3) packages/core: dependencies: @@ -179,7 +179,56 @@ importers: version: 6.0.3 vite-plus: specifier: 'catalog:' - version: 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.8.3))(yaml@2.8.3) + version: 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3) + + packages/dsh: + dependencies: + '@deepseek-ai/schemastery': + specifier: ^3.18.1 + version: 3.18.1 + devDependencies: + '@deepseek-ai/cordis': + specifier: ^4.0.1 + version: 4.0.1 + '@deepseek-ai/dsh-agent': + specifier: ^0.1.0-rc.6 + version: 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-session@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))) + '@deepseek-ai/dsh-attachment': + specifier: ^0.1.0-rc.6 + version: 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1) + '@deepseek-ai/dsh-fs': + specifier: ^0.1.0-rc.6 + version: 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-launch-environment': + specifier: ^0.1.0-rc.6 + version: 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1) + '@deepseek-ai/dsh-llm': + specifier: ^0.1.0-rc.6 + version: 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)) + '@deepseek-ai/dsh-session': + specifier: ^0.1.0-rc.6 + version: 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-subagent': + specifier: ^0.1.0-rc.6 + version: 0.1.0-rc.6(ce53bf32bdd7023a9119d219810dbe10) + '@deepseek-ai/dsh-subprocess': + specifier: ^0.1.0-rc.6 + version: 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1) + '@deepseek-ai/dsh-tools': + specifier: ^0.1.0-rc.6 + version: 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-session@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))))(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-session@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))) + '@deepseek-ai/dsh-web': + specifier: ^0.1.0-rc.6 + version: 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1))) + '@types/node': + specifier: 'catalog:' + version: 24.12.2 + typescript: + specifier: ^6.0.2 + version: 6.0.3 + vite-plus: + specifier: 'catalog:' + version: 0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) packages/e2e: dependencies: @@ -195,7 +244,7 @@ importers: version: 6.0.3 vite-plus: specifier: 0.1.22 - version: 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.9.0))(yaml@2.9.0) + version: 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) packages/kscli: dependencies: @@ -238,7 +287,7 @@ importers: version: 6.27.0 vite-plus: specifier: 0.1.22 - version: 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.8.3))(yaml@2.8.3) + version: 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3) yaml: specifier: 'catalog:' version: 2.8.3 @@ -278,13 +327,28 @@ importers: version: 6.0.3 vite-plus: specifier: 0.1.22 - version: 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.8.3))(yaml@2.8.3) + version: 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3) yaml: specifier: 'catalog:' version: 2.8.3 packages: + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} + engines: {node: '>=6.9.0'} + + '@blazediff/core@1.9.1': + resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==} + '@clack/core@0.3.5': resolution: {integrity: sha512-5cfhQNH+1VQ2xLQlmzXMqUoiaH0lRBq9/CLW9lTyMbuKLC3+xEK01tHVvyut++mLOn5urSHmkm6I0Lg9MaJSTQ==} @@ -293,14 +357,138 @@ packages: bundledDependencies: - is-unicode-supported - '@emnapi/core@1.10.0': - resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + '@deepseek-ai/cordis@4.0.1': + resolution: {integrity: sha512-YBdskTU2Po1kru3GgcUWUbkTsPMA9LkSQDAY8rBkFJeajdgcQad3QPJZE26JyK99Xb6HaASvoXg2DSUTeN/0Nw==} + hasBin: true + peerDependencies: + '@deepseek-ai/cordis-plugin-include': ^1.0.6 + '@deepseek-ai/cordis-plugin-loader': ^1.0.2 + peerDependenciesMeta: + '@deepseek-ai/cordis-plugin-include': + optional: true + '@deepseek-ai/cordis-plugin-loader': + optional: true + + '@deepseek-ai/cosmokit@1.8.2': + resolution: {integrity: sha512-muBOKtSrUKU5m/xpq8ZXWL6hQ/jgd4PhU2PqH97bcxIiLEJfNwZOGQEx4t/aS/GgxRAR+ra9pMHPMtTHU4sqqA==} + + '@deepseek-ai/dsh-agent@0.1.0-rc.6': + resolution: {integrity: sha512-vtqq2pWTrzn0dKfj5kREZRpP82AwtGjGx9V1lYnKvF+Uc/a8zyWbSvjDE7V1d3YQAQJzs2cWO31hURWDekDXIA==} + peerDependencies: + '@deepseek-ai/cordis': ^4.0.1 + '@deepseek-ai/dsh-invariants': ^0.1.0-rc.6 + '@deepseek-ai/dsh-llm': ^0.1.0-rc.6 + '@deepseek-ai/dsh-scope': ^0.1.0-rc.6 + '@deepseek-ai/dsh-session': ^0.1.0-rc.6 + '@deepseek-ai/dsh-system-prompt': ^0.1.0-rc.6 + '@deepseek-ai/dsh-typert-protocol': ^0.1.0-rc.6 + + '@deepseek-ai/dsh-attachment@0.1.0-rc.6': + resolution: {integrity: sha512-3P6N17NQ8jqSQGzeCs+svCIqArU8oq0YmgEAo+axN9aVuUDferWU4DLRSX59UGpmyldX4LQn81toA+c+DqMcHg==} + peerDependencies: + '@deepseek-ai/cordis': ^4.0.1 + '@deepseek-ai/dsh-brand': ^0.1.0-rc.6 + '@deepseek-ai/dsh-invariants': ^0.1.0-rc.6 + + '@deepseek-ai/dsh-fs@0.1.0-rc.6': + resolution: {integrity: sha512-OTkwb4QsZgmjtA/8ZEPh1FapmrBr3N989/G4Wmo1JkAvKbMxkYty6LxjckOawTTz7GJTfUoZCrw9uopDfIMMNw==} + peerDependencies: + '@deepseek-ai/cordis': ^4.0.1 + '@deepseek-ai/dsh-brand': ^0.1.0-rc.6 + '@deepseek-ai/dsh-invariants': ^0.1.0-rc.6 + '@deepseek-ai/dsh-llm': ^0.1.0-rc.6 + '@deepseek-ai/dsh-sandbox': ^0.1.0-rc.6 + + '@deepseek-ai/dsh-launch-environment@0.1.0-rc.6': + resolution: {integrity: sha512-tTRJ1464PJUDe1Em1qq0mfdgGREzGGWo3JSqP6xeYDoX+MRXVP9/ChsZ5k6VBMjARAxw0HGBf7WR6VcupHbMZg==} + peerDependencies: + '@deepseek-ai/cordis': ^4.0.1 + '@deepseek-ai/dsh-invariants': ^0.1.0-rc.6 + + '@deepseek-ai/dsh-llm@0.1.0-rc.6': + resolution: {integrity: sha512-kuFGC8bHlzGTwlRxQhXjf3CYWl8M4NzH+EYIkrW8rri4iMc9W53xrdvkil5No/DUlMm8g1u7GdeiWYFy0TMvtA==} + peerDependencies: + '@deepseek-ai/cordis': ^4.0.1 + '@deepseek-ai/dsh-attachment': ^0.1.0-rc.6 + '@deepseek-ai/dsh-brand': ^0.1.0-rc.6 + '@deepseek-ai/dsh-invariants': ^0.1.0-rc.6 + '@deepseek-ai/dsh-timeout': ^0.1.0-rc.6 + + '@deepseek-ai/dsh-session@0.1.0-rc.6': + resolution: {integrity: sha512-8tu8I6VWC7050GAUXWhcEWQw4pakALQc8TlhKr52m7Y4+kIKeNt3FBgP86PaGPBtpK0p5zUPRQNkFpzZbBdxyw==} + peerDependencies: + '@deepseek-ai/cordis': ^4.0.1 + '@deepseek-ai/dsh-brand': ^0.1.0-rc.6 + '@deepseek-ai/dsh-invariants': ^0.1.0-rc.6 + '@deepseek-ai/dsh-llm': ^0.1.0-rc.6 + '@deepseek-ai/dsh-scope': ^0.1.0-rc.6 + '@deepseek-ai/dsh-typert-protocol': ^0.1.0-rc.6 + + '@deepseek-ai/dsh-subagent@0.1.0-rc.6': + resolution: {integrity: sha512-vROmBDAlaFAzzSlTBOlvg/7fO55zxhUztnLtB3lKmN5RevrNQBjTsbeIMDQ8ow5ZplxEOnLU+sikFoA5JaoH8A==} + peerDependencies: + '@deepseek-ai/cordis': ^4.0.1 + '@deepseek-ai/dsh-agent': ^0.1.0-rc.6 + '@deepseek-ai/dsh-agent-presets': ^0.1.0-rc.6 + '@deepseek-ai/dsh-brand': ^0.1.0-rc.6 + '@deepseek-ai/dsh-invariants': ^0.1.0-rc.6 + '@deepseek-ai/dsh-jobs': ^0.1.0-rc.6 + '@deepseek-ai/dsh-llm': ^0.1.0-rc.6 + '@deepseek-ai/dsh-sandbox': ^0.1.0-rc.6 + '@deepseek-ai/dsh-sandbox-policy': ^0.1.0-rc.6 + '@deepseek-ai/dsh-scope': ^0.1.0-rc.6 + '@deepseek-ai/dsh-session': ^0.1.0-rc.6 + '@deepseek-ai/dsh-session-persistence': ^0.1.0-rc.6 + '@deepseek-ai/dsh-session-projection': ^0.1.0-rc.6 + '@deepseek-ai/dsh-session-projection-cache': ^0.1.0-rc.6 + '@deepseek-ai/dsh-tools': ^0.1.0-rc.6 + '@deepseek-ai/dsh-user-approval': ^0.1.0-rc.6 + peerDependenciesMeta: + '@deepseek-ai/dsh-agent-presets': + optional: true + '@deepseek-ai/dsh-jobs': + optional: true + '@deepseek-ai/dsh-sandbox': + optional: true + '@deepseek-ai/dsh-sandbox-policy': + optional: true + '@deepseek-ai/dsh-session-persistence': + optional: true + '@deepseek-ai/dsh-session-projection': + optional: true + '@deepseek-ai/dsh-session-projection-cache': + optional: true + '@deepseek-ai/dsh-user-approval': + optional: true + + '@deepseek-ai/dsh-subprocess@0.1.0-rc.6': + resolution: {integrity: sha512-nZaZRjSnE1he+GAd14vURAH7n3Fw5eGx3nzMbkB96Y6Qx+oQB/7PTuXxKVxlCh8TSfMJTf851ahwWb1eALjKlw==} + peerDependencies: + '@deepseek-ai/cordis': ^4.0.1 + '@deepseek-ai/dsh-invariants': ^0.1.0-rc.6 - '@emnapi/runtime@1.10.0': - resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + '@deepseek-ai/dsh-tools@0.1.0-rc.6': + resolution: {integrity: sha512-Tu08EPK3JyK0iNjH4FGzu/1uADynNSS6SmwOLdfytUN0YNqwNuKFSt2OJUg19famNlTgy992DcHfDu0T+gLXFg==} + peerDependencies: + '@deepseek-ai/cordis': ^4.0.1 + '@deepseek-ai/dsh-agent': ^0.1.0-rc.6 + '@deepseek-ai/dsh-code-runtime': ^0.1.0-rc.6 + '@deepseek-ai/dsh-invariants': ^0.1.0-rc.6 + '@deepseek-ai/dsh-llm': ^0.1.0-rc.6 + '@deepseek-ai/dsh-scope': ^0.1.0-rc.6 + '@deepseek-ai/dsh-session': ^0.1.0-rc.6 + '@deepseek-ai/dsh-system-prompt': ^0.1.0-rc.6 + '@deepseek-ai/dsh-user-approval': ^0.1.0-rc.6 + + '@deepseek-ai/dsh-web@0.1.0-rc.6': + resolution: {integrity: sha512-ABFbyDgo+DGaCtdRnjYG7Rz2K4dFlPA+xCEIt5MDobK/9CRQNpdZ4YrhHiq0nxwl1oxEM1Zw48ylFt+PwtS9ug==} + peerDependencies: + '@deepseek-ai/cordis': ^4.0.1 + '@deepseek-ai/dsh-invariants': ^0.1.0-rc.6 + '@deepseek-ai/dsh-llm': ^0.1.0-rc.6 - '@emnapi/wasi-threads@1.2.1': - resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + '@deepseek-ai/schemastery@3.18.1': + resolution: {integrity: sha512-Qn0FCSwCQnpnj6SB31I6i2sIKgKWnkbJM8O0EU91Gv2UsYVvtZTl6IA0sCwk2e2MZf5S8w5hpq9QkeVvK9qwxg==} '@esbuild/aix-ppc64@0.28.1': resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} @@ -458,11 +646,8 @@ packages: cpu: [x64] os: [win32] - '@napi-rs/wasm-runtime@1.1.4': - resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} - peerDependencies: - '@emnapi/core': ^1.7.1 - '@emnapi/runtime': ^1.7.1 + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} '@openagentpack/sdk@0.3.1': resolution: {integrity: sha512-/5LDwtNSjd9wyYGK4Lg7soqMyoI98BxhUGL3wzN5qO5HfmZBJP0YyElOnjhHyPHbLRWF7RYmfeVdA/oyEBJWTg==} @@ -472,54 +657,107 @@ packages: resolution: {integrity: sha512-0+S67blQakgeNqoKGozOUp5rQBrz2ynXZ2QIINXZPiafsD0YL0UogB9hAWc1S7k6VSNwKYC/N7MqT0V6IzpHkQ==} engines: {node: ^20.19.0 || >=22.12.0} - '@oxc-project/types@0.127.0': - resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==} + '@oxc-project/runtime@0.133.0': + resolution: {integrity: sha512-PkvjA1Lq5++V5S1E6Patr92ZVcieE6EalDr1VJTqv4BnjZdOUC4W3p8k1wMXSd5/2aFP4b/A6N5sg2Bkzcr9vQ==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@oxc-project/runtime@0.143.0': + resolution: {integrity: sha512-zIuXUf+YGIgsPk0xlQmzTY8NCSc8jE/pSfDodlQ9H3EGZABmr+AtIjXRrnpQAXuXzhDSNqZz9cuhud8hDDLvpg==} + engines: {node: ^20.19.0 || >=22.12.0} '@oxc-project/types@0.129.0': resolution: {integrity: sha512-3oz8m3FGdr2nDXVqmFUw7jolKliC4MoyXYIG2c7gpjBnzUWQpUGIYcXYKxTdTi+N2jusvt610ckTMkxdwHkYEg==} + '@oxc-project/types@0.133.0': + resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + + '@oxc-project/types@0.143.0': + resolution: {integrity: sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==} + '@oxfmt/binding-android-arm-eabi@0.48.0': resolution: {integrity: sha512-uwqk+/KhQvBIpULD8SMM/zAafMRC/+DV/xsEQjkkIsJ/kLmEI/2bxonVowcYTiXqqZ/a0FEW8DPkZY3VvwELDA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] + '@oxfmt/binding-android-arm-eabi@0.62.0': + resolution: {integrity: sha512-pdsv0C4gPjJ8H1+sd8u0BDx+yLACTL+rgeMIOL1ln4ihSnhw8CWXtYWgvcSkyTfgGBIzFKab+d8rx9Xl4en/Kw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + '@oxfmt/binding-android-arm64@0.48.0': resolution: {integrity: sha512-VUCiKuXK5+McVssgHEJdrcGK7hRJzrRb36zm9/jwzMholyYt4BgXhw5Nm1V1DX6Ce717Zi/1jk432b/tgmQgtQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] + '@oxfmt/binding-android-arm64@0.62.0': + resolution: {integrity: sha512-WC3YQ7uS/KtDrjmqwBviwFKe9qeoi+eXx8aX1z/ffG23Md75myjrJaQqTuJvdOLPoa4EYTjDWH0dHXfwulCVog==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@oxfmt/binding-darwin-arm64@0.48.0': resolution: {integrity: sha512-IkKp8rnIyQLW6Jt+6jragCbUVYSayk55lapiprLjIVvt4NczLyO/nwX2GgefLQ5iaBdfS8UEAFgCs/pLO6Cl0w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] + '@oxfmt/binding-darwin-arm64@0.62.0': + resolution: {integrity: sha512-GM8Yf3LjjaR1I8PD0SfeoIlwhsh9GvSF+cQ8sf624Yxnjsyumn95aFzYfKJVefblfDIiOAnZ7QVm2sa21Er/0Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@oxfmt/binding-darwin-x64@0.48.0': resolution: {integrity: sha512-+aFuhsGIuvnoOjXyKVHMhPKJZR1kQkAl8QyrKoMlA7yJsSTC3N0Asl53La8TChSHhW8epToQ/Q0nvLmEmfNmLg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] + '@oxfmt/binding-darwin-x64@0.62.0': + resolution: {integrity: sha512-d5THp7F8bCxLqNogEXDORRsQD6dosf3EyFtnXfBer6v+8tGdcWIjoDX9WaXrrF/26zOmL8qHpPTKCEvpBDmZkQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@oxfmt/binding-freebsd-x64@0.48.0': resolution: {integrity: sha512-fbqzQL8FjI9gGnktI7RIo0dksDziTAYBy7xlI7jU7eID5fxLF/25fS4Xj6GydD8Y5oWHL83U4NK160QaOAxtyg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] + '@oxfmt/binding-freebsd-x64@0.62.0': + resolution: {integrity: sha512-1DnrtXGZooOZ0fHgAXZUaDQzBVh1CM2MNW4oBXyQ2aWKvCHjyljvT9fgBkOM0fEOb96X5eqtcfJ0YUVt9jj66g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@oxfmt/binding-linux-arm-gnueabihf@0.48.0': resolution: {integrity: sha512-hn4i0zhAyTiB3ZHjQfYUZkDvrbVkohw1S7pySWxWUoZ87HnkDoTFThj7QTxk40hNPOTUP0vHbPRNamFIv1HBJQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@oxfmt/binding-linux-arm-gnueabihf@0.62.0': + resolution: {integrity: sha512-4pQDHOYRH+Huqe0StIaWyvk2CVl/aTaqSrbZpA3/pLS2xH24ME7lBgYprhQF2fRkHBzhGGGKliwxFsDdHwx59g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@oxfmt/binding-linux-arm-musleabihf@0.48.0': resolution: {integrity: sha512-R4WBD9qF3QM9hqgdAa+fBGXmquTvDUujrPQ36t2Sjk8RPOSKGHDeN7l/khr10hqbQaOq9KCgPHG9ubNET/X/RQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@oxfmt/binding-linux-arm-musleabihf@0.62.0': + resolution: {integrity: sha512-X0jAaZJFMCVKhB6YyWVTQ/wN2DLsBcZKSMqTS76bF6riT+XZdtg2FPEdjDvdVbunO9cG+tWiVaEs4Zs38lxYog==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@oxfmt/binding-linux-arm64-gnu@0.48.0': resolution: {integrity: sha512-5bVdwSwlm1M8wbYCorLOxWxUBw/8tBvHYyQNIfwWVPwOJaj5vg1APSGJQVpwJfV5VNE9PSrR91UKEpoNwHhqUA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -527,6 +765,13 @@ packages: os: [linux] libc: [glibc] + '@oxfmt/binding-linux-arm64-gnu@0.62.0': + resolution: {integrity: sha512-682Z8T5s8T5ATArYtsejKvbIfd8LEAXyyDkKkoZVq8HND7Vx8TYLlrDjDSeYfodMeVwHOgkj13lJYR8cj6vUSg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@oxfmt/binding-linux-arm64-musl@0.48.0': resolution: {integrity: sha512-vCS3Fk7gFslTqE1lUE2IlroyVV7u/9SmMA/uBqDoshuck2psGWcjW0ePyPZI3rM3+qtf2pDaMVIKMHozraifuw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -534,6 +779,13 @@ packages: os: [linux] libc: [musl] + '@oxfmt/binding-linux-arm64-musl@0.62.0': + resolution: {integrity: sha512-lk25fAl7KWaLWVJcW0CHEXB7QlQZtx5eDkjpaGMK0hzXTjUe0Wmlu8IKuFHoviSOcEJedRTs4VE/506VqGxGew==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@oxfmt/binding-linux-ppc64-gnu@0.48.0': resolution: {integrity: sha512-gKtfFfueUClXDumyoHUbymqRf7prHejOOyzJK0eIJn93GF9JBdFHdo60TM1ZBHxkEwZvjuOgHmKtneKbEOc/Eg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -541,6 +793,13 @@ packages: os: [linux] libc: [glibc] + '@oxfmt/binding-linux-ppc64-gnu@0.62.0': + resolution: {integrity: sha512-SFyNqHQLwySceWNLhiSldx7wPXRAzP0L0WcW9GegP3uWrpZGJiZlQO85NbHAFPEfxR9PhZ9qSnZryEh7+v+4Gw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@oxfmt/binding-linux-riscv64-gnu@0.48.0': resolution: {integrity: sha512-SYt0UhOvZD/UwZz9sXq6J2uAw8o24f5VZpLB2DH01f6MevshmlgakQlZe2lwek2sZJkd07eLu7mZa0g7yeiw7Q==} engines: {node: ^20.19.0 || >=22.12.0} @@ -548,6 +807,13 @@ packages: os: [linux] libc: [glibc] + '@oxfmt/binding-linux-riscv64-gnu@0.62.0': + resolution: {integrity: sha512-KYj55C1ywJfHo6+aKDuEmUtVEdJALsC5GwayDGsI6FGz2GxFqNr/mA8nxVsNbJzm7sE5MRqTQ9ziImSzhYXysA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + '@oxfmt/binding-linux-riscv64-musl@0.48.0': resolution: {integrity: sha512-JLbrwck2AopG4ud/XklZO5N+qxGC7cS7ROvXZVNfx0MCLDDL2kGOLvzuWORkVjnjAM0CMAfIMU2zNBtQbM+4dw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -555,6 +821,13 @@ packages: os: [linux] libc: [musl] + '@oxfmt/binding-linux-riscv64-musl@0.62.0': + resolution: {integrity: sha512-BhZDNo5GOU5nC378RhD0/XpvaEBHsH3HLgJp8YZX3A0InC7oivzA63HsRmiXFLtLSHAstEVrDf6fbC7Rs8Jh/A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + '@oxfmt/binding-linux-s390x-gnu@0.48.0': resolution: {integrity: sha512-mdxt5L8OQLxkQH+JVpdC/lknZNe0lX4hlO3d8+xvw2wToo+iDrid9tiGOd5bmHfUVd5wVhrUry0qlu5vq66NkQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -562,6 +835,13 @@ packages: os: [linux] libc: [glibc] + '@oxfmt/binding-linux-s390x-gnu@0.62.0': + resolution: {integrity: sha512-UyAFmyHkgSgUJ/wOM4p3U8AC2yAFvRH5PNBs7TnK0fObTT/XSWcdr/lAzPSWaekHaZFaMeFZyk9n93Joq3J93A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@oxfmt/binding-linux-x64-gnu@0.48.0': resolution: {integrity: sha512-oEz1BQwMrV7OMEFx/3VPDU3n9TM0AnxpktDYXjEg5i6nTX87wo18wSfBvkl4tzAICdKtoAQAdBIl7Y7hsPlx5w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -569,6 +849,13 @@ packages: os: [linux] libc: [glibc] + '@oxfmt/binding-linux-x64-gnu@0.62.0': + resolution: {integrity: sha512-1iYMP0leytWazFubD/WnINJuIrzRPuoL1aWEJdlGezEzDbTxcd29R4r8IUzP2oWeKst5V02uMJgR2NILlPlG6w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@oxfmt/binding-linux-x64-musl@0.48.0': resolution: {integrity: sha512-g2SKTTurP5mWjd8Ecait0erYqmltL4IqW1EwttM25BxM6NiTt4ubobJYMR1uox1V2QgG4UfHH10CGRvWlUixjw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -576,102 +863,205 @@ packages: os: [linux] libc: [musl] + '@oxfmt/binding-linux-x64-musl@0.62.0': + resolution: {integrity: sha512-4rA/URtJSTVNVAQz6Q8wf7SaRvOXVy+TizriT9hs/Y1XhLR/R+92uWKRQG8yFWRAIEBbFHJ6WevQcl/G9SXEfw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@oxfmt/binding-openharmony-arm64@0.48.0': resolution: {integrity: sha512-CIg24VgheEpvolHL2gQuax5qcQ602bRMHrJ9g8XsQr3iVj9aSPgopigBKuMqrXsupwkrU+RQCn5cG8PgFntR6w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] + '@oxfmt/binding-openharmony-arm64@0.62.0': + resolution: {integrity: sha512-mSZuFHU2ar1KLUjXpI2QBQcJ1VsOB3mOCgQXuXCpKs19dgh4u+OaovNfrWDfiJb+ihJ2+f7YFcaO9bS2dlTCXA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@oxfmt/binding-win32-arm64-msvc@0.48.0': resolution: {integrity: sha512-zeaWkcxcEULwkGF3I/HgEvcDPN8buYDrxibBUa/IFh5Vmwyge+KpLO+hEwSovW349H0O/C0Z2kaFmEzEDm00/Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] + '@oxfmt/binding-win32-arm64-msvc@0.62.0': + resolution: {integrity: sha512-OfwuhkcjDlqC4EgDojtiV9mzpLqeB9KqTOWPOjLEYBVdDCVSxqW3qzp/xcIxsbtI0UgGCnKvAqYKyY25kf5JZw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@oxfmt/binding-win32-ia32-msvc@0.48.0': resolution: {integrity: sha512-yiEKnIAGvx5CyZQOlMaNlZkAbwT7/Quk0j3WLt+PR5hK+qYjPTRRJYDfD77wCBPLvEYAG41v4KG3iL0H+uxoxg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] + '@oxfmt/binding-win32-ia32-msvc@0.62.0': + resolution: {integrity: sha512-P9uDDNFRzghO3X8QAzhkjKhK7JvtABsVn8UYtFX7uor12IAnwNt8nNIctvfWj1JkQU/kE+fmLRPiw7XlrIHsZw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + '@oxfmt/binding-win32-x64-msvc@0.48.0': resolution: {integrity: sha512-GSD2+7t2UoVMV2NgxXypa4bKewflPMAjYnF0Xw9/ht82ZfafAHhb8STwrEd7wlH2PFogt5zw3WVCxYJaHUdbeQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] + '@oxfmt/binding-win32-x64-msvc@0.62.0': + resolution: {integrity: sha512-dlI5SY7XYQCiCBafntWagCR6HcAJB/NpsLtdlPx8x08+Osz8Ok1HHz1GZuusegCe/VoJ6pAnF5a4pd5OZAq7qQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@oxlint-tsgolint/darwin-arm64@0.22.1': resolution: {integrity: sha512-4150Lpgc1YM09GcjA6GSrra1JoPjC7aOpfywLjWEY4vW0Sd1qKzqHF1WRaiw0/qUZ40OATYdv3aRd7ipPkWQbw==} cpu: [arm64] os: [darwin] + '@oxlint-tsgolint/darwin-arm64@7.0.2001': + resolution: {integrity: sha512-CUJEdbSZ54+Xy9OXqOhWLTKZKV0BBiV7C2i/ygyVmXtkUNXx5YCzN8DpSSshTAKktoL7S+tnQ/ftFG/i7X896w==} + cpu: [arm64] + os: [darwin] + '@oxlint-tsgolint/darwin-x64@0.22.1': resolution: {integrity: sha512-vFWcPWYOgZs4HWcgS1EjUZg33NLcNfEYU49KGImmCfZWkflENrmBYV4HN/C0YeAPum6ZZ/goPSvQrB/cOD+NfA==} cpu: [x64] os: [darwin] + '@oxlint-tsgolint/darwin-x64@7.0.2001': + resolution: {integrity: sha512-pXfBb5BqONCcgrXQNUZWXgiYmRSWJzd97S8i41VVOh6ut0tyo+cJ5FKFpczDHxiVNfj/3e7c9B4MtztNdpIVCw==} + cpu: [x64] + os: [darwin] + '@oxlint-tsgolint/linux-arm64@0.22.1': resolution: {integrity: sha512-6LiUpP0Zir3+29FvBm7Y28q/dBjSHqTZ5MhG1Ckw4fGhI4cAvbcwXaKvbjx1TP7rRmBNOoq/M5xdpHjTb+GAew==} cpu: [arm64] os: [linux] + '@oxlint-tsgolint/linux-arm64@7.0.2001': + resolution: {integrity: sha512-roP7zujb/QDPzDwEKsFFpzNHHy91/Y7oX9vQXk78ekyZtcQj1QXDIMH33gjDdHBfRl4K9pZ36xhRgrP4Zr+R8A==} + cpu: [arm64] + os: [linux] + '@oxlint-tsgolint/linux-x64@0.22.1': resolution: {integrity: sha512-fuX1hEQfpHauUbXADsfqVhRzrUrGabzGXbj5wsp2vKhV5uk/Rze8Mba9GdjFGECzvXudMGqHqxB4r6jGRdhxVA==} cpu: [x64] os: [linux] + '@oxlint-tsgolint/linux-x64@7.0.2001': + resolution: {integrity: sha512-UDezNqdECVmngu2TPnjaS1YoAmcTaBoI5lV9vk3VahBxoi+I5r9k3iJTT7qZoYWOXTD/7T7bNcwRgrocR6BscQ==} + cpu: [x64] + os: [linux] + '@oxlint-tsgolint/win32-arm64@0.22.1': resolution: {integrity: sha512-8SZidAj+jrbZf9ZjBEYW0tiNZ+KasqB2zgW26qdiPpQSF/DzURnPmXz651IeA9YsmbVdHGIooEHUmev6QJdquA==} cpu: [arm64] os: [win32] + '@oxlint-tsgolint/win32-arm64@7.0.2001': + resolution: {integrity: sha512-uJZhqB6pdXLuN+AD1F5082byyQti/NPmJA77GtcFlmT2HzRelqbNls3SaIqxpjdFgvSBF9g0yOKGBkGFg7kX8Q==} + cpu: [arm64] + os: [win32] + '@oxlint-tsgolint/win32-x64@0.22.1': resolution: {integrity: sha512-QweSk9H5lFh5Y+WUf2Kq/OAN88V6+62ZwGhP38gqdRotI90luXSMkruFTj7Q2rYrzH4ZVNaSqx7NY8JpSfIzqg==} cpu: [x64] os: [win32] + '@oxlint-tsgolint/win32-x64@7.0.2001': + resolution: {integrity: sha512-FkDRm8hx9OwzGQqyWG1tO5QrTLRApff9DzSgpz9QZau37BR8d1VYKOxMLGf6shPZntJFoTwIIJYT68VndYDCog==} + cpu: [x64] + os: [win32] + '@oxlint/binding-android-arm-eabi@1.63.0': resolution: {integrity: sha512-A9xLtQt7i0OA1PoB/meog6kikXI9CdwEp7ZwQqmgnpKn3G3b1orvTDy8CQ6T7w1HvDrgWGB78PkFKcWgibcTCg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] + '@oxlint/binding-android-arm-eabi@1.77.0': + resolution: {integrity: sha512-E06sKWS6PiI6HRxS1wyQg22HvApt01hI7fV+T3wUk3OSbaaP4a3hYGY/MIQDmASqCiRjBdpRQYkgMkqH82cWmQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + '@oxlint/binding-android-arm64@1.63.0': resolution: {integrity: sha512-SQo+ZMvdR9l3CxZp5W5gFNxSiDxclY6lOzzNpKYLF8asESpm3Pwumx0gER5T7aHLF1/2BAAtLD3DiDkdgy4V1A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] + '@oxlint/binding-android-arm64@1.77.0': + resolution: {integrity: sha512-NvsKz0KZxTp9cYWPLf+FXaSZwB3oO3peAjtukpOMBgse2vhQSoIIVqeO1yR0lEo/UcdZIDL18uq+kL0LzQ0ytA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@oxlint/binding-darwin-arm64@1.63.0': resolution: {integrity: sha512-6W82XjJDTmMnjg30427l0dufpnyLoq7wEukKdM6/g2VIybRVuQiBVh43EA4b+UxZ3+tLcKm+Or/pXGNgLCEU8g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] + '@oxlint/binding-darwin-arm64@1.77.0': + resolution: {integrity: sha512-bgjTn6nW4bQCFBvSvuHCpDD+sONvmpo4lGI4PxzMt1quBA+xYxhczk6RiCn3GZ9gY8uhaBbwhj9MdKGfu6T9DA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@oxlint/binding-darwin-x64@1.63.0': resolution: {integrity: sha512-CnWd/YCuVG5W1BYkjJEVbJG11o526O9qAwBEQM+nh8K19CRFUkFdROXCyYkGmroHEYQe4vgQ6+lh3550Lp35Xw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] + '@oxlint/binding-darwin-x64@1.77.0': + resolution: {integrity: sha512-aotaIttH1R6j1Rwhx0M0htgeZyGtVQqYNTVEYMN/UcgHPquGA6kmk9OyuDc3a2GKUQBC+3C3GVQCcrRPMYqAFA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@oxlint/binding-freebsd-x64@1.63.0': resolution: {integrity: sha512-a4eZAqrmtajqcxfdAzC+l7g3PaE3V8hpAYqqeD3fTxLXOMFdK3eNTZrU80n4dDEVm0JXy1aL5PqvqWldBl6zYA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] + '@oxlint/binding-freebsd-x64@1.77.0': + resolution: {integrity: sha512-nNx/wta7ksRAdYvq+l4AWjXkLxEXHALhENxjj2cYbQAIR4ybaA5L+hCbE63HOmft5czQ6ks+hb8vmEAnn7YGPg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@oxlint/binding-linux-arm-gnueabihf@1.63.0': resolution: {integrity: sha512-tYUtU9TdbU3uXF5D62g5zXJ13iniFGhXQx5vp9cyEjGdbSAY3VdFBSaldYvyoDmgMZ0ZYuwQP1Y4t2Fhejwa0w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@oxlint/binding-linux-arm-gnueabihf@1.77.0': + resolution: {integrity: sha512-tMLLjM7xXtzXisVCzkOTXNCy9bZVId2wteNwjohlFDR/jY6WagpEDA1c1wu4xRc20Hojaxj+V6DSR7gbKxijWA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@oxlint/binding-linux-arm-musleabihf@1.63.0': resolution: {integrity: sha512-I5r3twFf776UZg9dmRo2xbrKt00tTkORXEVe0ctg4vdTkQvJAjiCHxnbAU2HL1AiJ9cqADA76MAliuilsAWnvg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@oxlint/binding-linux-arm-musleabihf@1.77.0': + resolution: {integrity: sha512-MiAFDFaqR0tmHTAyo0YDcZ5hyLREdYw/RQhc2R3cbT+8O3tB+zqPM2th9TTQ+Uo3jn/embS+DO+HyX9ztCPkOQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@oxlint/binding-linux-arm64-gnu@1.63.0': resolution: {integrity: sha512-t7ltUkg6FFh4b564QyGir8xIj/QZbXu8FlcRkcyW9+ztr/mfRHlvUOFd95pJCXi9s/L5DrUeWWgpXRS+V+6igQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -679,6 +1069,13 @@ packages: os: [linux] libc: [glibc] + '@oxlint/binding-linux-arm64-gnu@1.77.0': + resolution: {integrity: sha512-/xqQ3B16i1T4cyt/9Mn+4CpzhUXoBXp7kVpIwzOXNFLj5JmK1bIjsbSnX296Gg8A/o7oDtKWikFgBx0SLwztkw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@oxlint/binding-linux-arm64-musl@1.63.0': resolution: {integrity: sha512-Q5mmZy/XWjuYFUuQyYjOvZ5U/JkKEwnpir6hGxhh6HcdP0V/BKxLo8dqkfF/t7r7AguB17dfS/8+go5AQDRR6g==} engines: {node: ^20.19.0 || >=22.12.0} @@ -686,6 +1083,13 @@ packages: os: [linux] libc: [musl] + '@oxlint/binding-linux-arm64-musl@1.77.0': + resolution: {integrity: sha512-LSbwuRKiNCenPDcbARqAZ5RfBy7gmj7vOvfJRLeCDU3gFtSxWbhv/+VTlaUqzUhNj1gFLHB8h7ALnxa/Az6z6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@oxlint/binding-linux-ppc64-gnu@1.63.0': resolution: {integrity: sha512-uBGtuZ0TzLB4x5wVa82HGNvYqY8buwDhyCnCP0R0gkk9szqVsP0MeTtD5HX7EsEuFIt+aYmYxuxeVxs3nTSwtQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -693,6 +1097,13 @@ packages: os: [linux] libc: [glibc] + '@oxlint/binding-linux-ppc64-gnu@1.77.0': + resolution: {integrity: sha512-QWdcH31mXEUe5Nq1s0CfCpceaKjIo9uZtwDjAuL681g1axf+5x8xrg/eXWaw//4NCxYZ4V4e5Hu5tvdR+pTBlg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@oxlint/binding-linux-riscv64-gnu@1.63.0': resolution: {integrity: sha512-h4s6FwxE+9MeA181o0dnDwHP32Y/bG8EiB/vrD6Ib+AMt6haigDc/0bUtI/sLmQDBMJnUfaCmtSSrEAqjtEVrA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -700,6 +1111,13 @@ packages: os: [linux] libc: [glibc] + '@oxlint/binding-linux-riscv64-gnu@1.77.0': + resolution: {integrity: sha512-GnOfYgJxbcElOiPZaDFDl406ONddwvOWk2jvAAAEjwAl4GofNoHF+/HHUIBYa6bFCArlcGPi0XjC4cU1pkgF/Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + '@oxlint/binding-linux-riscv64-musl@1.63.0': resolution: {integrity: sha512-2EaNcCBR8Mcjl5ARtuN3BdEpVkX7KpjSjMGZ/mJMIeaXgTtdz5ytg2VwygMSStA/k0ixfvZFoZOfjDEcouV5vQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -707,6 +1125,13 @@ packages: os: [linux] libc: [musl] + '@oxlint/binding-linux-riscv64-musl@1.77.0': + resolution: {integrity: sha512-AyEMTUCf0xY+hHF+IxqXFQIX0yQOIR8ykpY0lJNOw9xYqOzUX8dyZfRvlG0RfXwuQn2eonf/8NrMmDSZJjdqsA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + '@oxlint/binding-linux-s390x-gnu@1.63.0': resolution: {integrity: sha512-p4hlf/fd7TrYYl3QrWWD0GocqJefwMu3cHQhmi2FvEB/YOvFb5DZN3SMBaPi7B1TM5DeypkEtrVib674q1KKPg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -714,6 +1139,13 @@ packages: os: [linux] libc: [glibc] + '@oxlint/binding-linux-s390x-gnu@1.77.0': + resolution: {integrity: sha512-sPLzEcNvxd/oyVQ5oZo92CiHkFkpBeRop13E/P3TPY+hZfXHKCOWKI70TE2RYwMKFJDc20EMjH16L7NZICtKTw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@oxlint/binding-linux-x64-gnu@1.63.0': resolution: {integrity: sha512-Vgq9rkRVcPcjbcH+ihYTfpeR7vCXfqpd+z5ItTGc0yYUV59L5ceHYN1iV4H9bKGV7Rn5hkVc7x3mSvHegduENA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -721,6 +1153,13 @@ packages: os: [linux] libc: [glibc] + '@oxlint/binding-linux-x64-gnu@1.77.0': + resolution: {integrity: sha512-1Oh2ssH2L7lwyvkdSqaMUfsGfwU2Wfvew+obBUYjRVqhpBcUpwnsPSEr1IzVi9XqkuY10geiLsNKecqaZC34Dw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@oxlint/binding-linux-x64-musl@1.63.0': resolution: {integrity: sha512-3/Lkq/ncooA61rorrC+ZQed1Bc4VpGj+WnGsp58zmxKgvZ2vhreu+dcVyr3mX8NUpq7mfZ4gDDTou/yrF1Pd7A==} engines: {node: ^20.19.0 || >=22.12.0} @@ -728,140 +1167,87 @@ packages: os: [linux] libc: [musl] + '@oxlint/binding-linux-x64-musl@1.77.0': + resolution: {integrity: sha512-0j/2wRgNGO+Qj/M1uu/p57h/hFTTWWcfie0ufkbabeus2s5+/QqkCflnMOwLLN5m2GsNeWp4xdl4cPa4n7QCOQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@oxlint/binding-openharmony-arm64@1.63.0': resolution: {integrity: sha512-0/EdD/6hDkx5Mfd769PTjvEM8mZ/6Dfukp1dBCL/2PjlIVGEtYdNZyok6ChqYPsT9JcFnlQnUeQzO0/1L/oC9w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] + '@oxlint/binding-openharmony-arm64@1.77.0': + resolution: {integrity: sha512-BJ/j54qS0usEnyDkLYURMj2iiD9h5Cyy+ppzeMSXBGRXaGRNWnj1Mw14NqWMR5E/PzdgB30OOCCzLzbRoduafw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@oxlint/binding-win32-arm64-msvc@1.63.0': resolution: {integrity: sha512-wb0CUkN8ngwPiRQBjD1Cj0LsHeNvm+Xt6YBHDMtj2DVQVD6Oj8Ri7g6BD+KICf6LaBqZlmzOvy6nF9E/8yyGOg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] + '@oxlint/binding-win32-arm64-msvc@1.77.0': + resolution: {integrity: sha512-Yh8w+g2Lpx7StrvtYkoz9JJvXjB9wxgFChFNb85nrXm/wj/XTwGWS1hve9+900HL7llrntYB3YP+y32E3tRqzA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@oxlint/binding-win32-ia32-msvc@1.63.0': resolution: {integrity: sha512-BX5iq+ovdNlVYhSn5qPMUIT0uwAwt2lmEnCnzK+Gkhw4DovIvhGb96OFhV8yzQNUnQxn/xGkOR+X+BLrLDNm8w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] + '@oxlint/binding-win32-ia32-msvc@1.77.0': + resolution: {integrity: sha512-zja5b7+6a7UsRFgAQSrnax5vrzliEyNPLCjfXONu/vTWswaIVZGFajJZptaeRvPE4LghtFdAzVFlexTm7MVTGA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + '@oxlint/binding-win32-x64-msvc@1.63.0': resolution: {integrity: sha512-QeN/WELOfsXMeYwxvfgQrl6CbVftYUCZsGXHjXQd5Trccm8+i4gmtxaOui4xbJQaiDlviF8F3yLSBloQUeFsfA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] + '@oxlint/binding-win32-x64-msvc@1.77.0': + resolution: {integrity: sha512-+teyvPDZ2RjUvo+SuCqS/UhaJl1QtdW5fWT5NJTV61V5MIuIS90Db9LixmtEGvXixyttiK62P96MSu3UlpviBw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@oxlint/plugins@1.61.0': resolution: {integrity: sha512-nkOyZEF1vH527CkdQtOp1HMrVFEM4ResURvI2JFeGoup+h+43J/k/FgdOR9b9Isxg+Yae7qVDa7y3nssE8b3TQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@oxlint/plugins@1.73.0': + resolution: {integrity: sha512-OhgMQeMmZA0dcFcX4/priaJZWdFECxiClgq6mRX6aatZEcV9PbKC3P3/v8U1hVjviT1i5U+vR8lAtBV6m4FXAA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} - '@rolldown/binding-android-arm64@1.0.0-rc.17': - resolution: {integrity: sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [android] + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - '@rolldown/binding-darwin-arm64@1.0.0-rc.17': - resolution: {integrity: sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] + '@testing-library/dom@10.4.1': + resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} + engines: {node: '>=18'} - '@rolldown/binding-darwin-x64@1.0.0-rc.17': - resolution: {integrity: sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] - - '@rolldown/binding-freebsd-x64@1.0.0-rc.17': - resolution: {integrity: sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [freebsd] - - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': - resolution: {integrity: sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': - resolution: {integrity: sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': - resolution: {integrity: sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': - resolution: {integrity: sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': - resolution: {integrity: sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': - resolution: {integrity: sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': - resolution: {integrity: sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [musl] - - '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': - resolution: {integrity: sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [openharmony] - - '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': - resolution: {integrity: sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [wasm32] - - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': - resolution: {integrity: sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] - - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': - resolution: {integrity: sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] - - '@rolldown/pluginutils@1.0.0-rc.17': - resolution: {integrity: sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==} - - '@standard-schema/spec@1.1.0': - resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@testing-library/user-event@14.6.4': + resolution: {integrity: sha512-QCGwP6QrjypBLwyj5cuyfVamkaIEy/XGY+1VDehbtbQqOggYmTFpFOdWR5mPz14vX8vXLMVjDHlRNBcClyO9ew==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' - '@tybys/wasm-util@0.10.1': - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} @@ -869,6 +1255,9 @@ packages: '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/node@24.12.2': resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} @@ -920,6 +1309,38 @@ packages: resolution: {integrity: sha512-e2f1LaETJ1wFIZSZAJwsAumWixGaRslUjESf0nSrZGUensq3ZwXddoDJPPoDLkSAr/Fa3v5aff+dJ39UbNfbNQ==} hasBin: true + '@vitest/browser-preview@4.1.10': + resolution: {integrity: sha512-14MJrL59ZFkqXLjwfSk6RzTDy5Czf9UG4+8q8L6Gxjs2aPjEce/cVNYV14bXAc2BvMjUNu904+ZEZA1Xc1wtvQ==} + + '@vitest/browser@4.1.10': + resolution: {integrity: sha512-UDwuWGwXj646CBx/bQHOaJSX7np0I8JL/UKQYa1e4QrVHH8VdWtx8eaOuf8sy0ShwDgR6NjJAsp5eF6vjF6qng==} + + '@vitest/expect@4.1.10': + resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} + + '@vitest/mocker@4.1.10': + resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} + peerDependencies: + msw: ^2.4.9 + peerDependenciesMeta: + msw: + optional: true + + '@vitest/pretty-format@4.1.10': + resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} + + '@vitest/runner@4.1.10': + resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} + + '@vitest/snapshot@4.1.10': + resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} + + '@vitest/spy@4.1.10': + resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} + + '@vitest/utils@4.1.10': + resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} + '@voidzero-dev/vite-plus-core@0.1.22': resolution: {integrity: sha512-OC7tChagbJCoY7YKzD5MuyxJO1km5IF42B3ltZoQ9Twc8UuPrMuWZrVoP984tJKYd/gFJuQFM/lrbNtBm9kyDg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -983,18 +1404,150 @@ packages: yaml: optional: true + '@voidzero-dev/vite-plus-core@0.1.24': + resolution: {integrity: sha512-iXPGBABnQnrDMx89H6MOCGcTZp+QW+3rY4YMVKdE6ydchSvPk2O3MI2vgaRVfOtWJ2IjnxSnf1n2yjP67ZBRFQ==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@arethetypeswrong/core': ^0.18.1 + '@tsdown/css': 0.22.1 + '@tsdown/exe': 0.22.1 + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.18 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + publint: ^0.3.8 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + typescript: ^5.0.0 || ^6.0.0 + unplugin-unused: ^0.5.0 + unrun: '*' + yaml: ^2.4.2 + peerDependenciesMeta: + '@arethetypeswrong/core': + optional: true + '@tsdown/css': + optional: true + '@tsdown/exe': + optional: true + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + publint: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + typescript: + optional: true + unplugin-unused: + optional: true + unrun: + optional: true + yaml: + optional: true + + '@voidzero-dev/vite-plus-core@0.2.9': + resolution: {integrity: sha512-dWqScAAwa8h/i9jCiGAMs7YarzQWInHZ5gCJNbQkHXA6Zp6A2T2anN9YMFVPpb7CwVFwkI2iPF5yl/DXtq+zUA==} + engines: {node: ^20.19.0 || ^22.18.0 || >=24.11.0} + peerDependencies: + '@arethetypeswrong/core': ^0.18.1 + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.4.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + publint: ^0.3.8 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + typescript: ^5.0.0 || ^6.0.0 || ^7.0.0 + unplugin-unused: ^0.5.0 + unrun: '*' + yaml: ^2.4.2 + peerDependenciesMeta: + '@arethetypeswrong/core': + optional: true + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + publint: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + typescript: + optional: true + unplugin-unused: + optional: true + unrun: + optional: true + yaml: + optional: true + '@voidzero-dev/vite-plus-darwin-arm64@0.1.22': resolution: {integrity: sha512-+6sRVGCAQSpO96WC0EZtSLJ01VzNiZL/eQUQ8NLVl1oH+0+KgHF2UXyqUXGCGf/JCu34egEwBEjDU3WUwN2mxg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] + '@voidzero-dev/vite-plus-darwin-arm64@0.2.9': + resolution: {integrity: sha512-/qJHqMfyy/LiCJk4UYZfFW6Comsfm8zDuy4P8UFWnFqRjmefYvZbMK4ThYNM87tKNWYWjsnClzssjJOmDTAc8w==} + engines: {node: '>=20.0.0'} + cpu: [arm64] + os: [darwin] + '@voidzero-dev/vite-plus-darwin-x64@0.1.22': resolution: {integrity: sha512-rqsCW/Brt2froW7VhLE+gVHKtGniyLdHlfcmTLfuM5vnd5skdQlymibRw/lviJU+mSl0x8pGcXZbvA4TLHbCoA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] + '@voidzero-dev/vite-plus-darwin-x64@0.2.9': + resolution: {integrity: sha512-3MGnNeazgYAqQTaC7JIbZyrTHmxSXTWFr9G1yAdeItKasB1R8HKIkCS1Qnr49Ge4S/cyOODivdbcpqFkrT93ng==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [darwin] + '@voidzero-dev/vite-plus-linux-arm64-gnu@0.1.22': resolution: {integrity: sha512-OL/WT6pvJpFS1L+hWe8g2LCEHCJfEBSgxV0vbSoQDdfTuilUJaVK8rljVWgtIVjUQSjIx8jKfPsl/I8iEBh0GQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1002,6 +1555,13 @@ packages: os: [linux] libc: [glibc] + '@voidzero-dev/vite-plus-linux-arm64-gnu@0.2.9': + resolution: {integrity: sha512-6LmukER8qD4UBIRqMNv4Ilq7CxfRhngLUXlMv8vbTupeLRWPJSKvKEHyRxCwr6JP57Gxfr8KrX1ye42WzcZF0g==} + engines: {node: '>=20.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@voidzero-dev/vite-plus-linux-arm64-musl@0.1.22': resolution: {integrity: sha512-SdZLL2aXm9XlbNfygsIifxhTjnRa2gI5oXNCh9QmLmXN36yhXt816I5Tl5IQ5DJwxhnG1+5Uqp2D6tHaT5g6nQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1009,6 +1569,13 @@ packages: os: [linux] libc: [musl] + '@voidzero-dev/vite-plus-linux-arm64-musl@0.2.9': + resolution: {integrity: sha512-cBs626GWkyJlwKP0nsdHlMWpuTl9xOWRxAUoqtxXPtw80bVy4WM5eNS4SXPC5pX10jR7DRIkRpzNAsy7fv8Faw==} + engines: {node: '>=20.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + '@voidzero-dev/vite-plus-linux-x64-gnu@0.1.22': resolution: {integrity: sha512-Qn6WPTn61A47ZBCPm+v8kCrMgXlI5p10pllKYkce2PFeCotN6v1bqu2GBZIkLVSi534ywGqdkiG1kaesM9e1vw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1016,6 +1583,13 @@ packages: os: [linux] libc: [glibc] + '@voidzero-dev/vite-plus-linux-x64-gnu@0.2.9': + resolution: {integrity: sha512-2Iy8x4PCPMNzXeu3pREevlggoeK8PwtdUiCpoSybAZBtR/aqMxsJREyt/eKv45F8lsiNlA8PbIWEvPxLSgzFLQ==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + '@voidzero-dev/vite-plus-linux-x64-musl@0.1.22': resolution: {integrity: sha512-DsVE09IgvYBR2PY2Bohd08tScYDa8K8KJkIGc8Y6uRXR14NEldoufmWJdCmEsGLA8puRv5HV3ZheWFFjmw5Liw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1023,6 +1597,13 @@ packages: os: [linux] libc: [musl] + '@voidzero-dev/vite-plus-linux-x64-musl@0.2.9': + resolution: {integrity: sha512-zuGx+eRotWPd9cmh1X9AfsC2tN/Ad9Hk6LAzlxoKJUjEkTsY3WjVJ6Da0z48SAUFuenI0JkdqXnMCrePtGvWHg==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + '@voidzero-dev/vite-plus-test@0.1.22': resolution: {integrity: sha512-6VKDNXH+ygDyTXpBYn+g+2a9j3zuAZRlP2ZSx0RcjPMdGUMpX6Mox4CmdK8SkZUvi+f6a1siX50ZnCOcQoTgmQ==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -1035,7 +1616,36 @@ packages: '@vitest/ui': 4.1.6 happy-dom: '*' jsdom: '*' - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + '@voidzero-dev/vite-plus-test@0.1.24': + resolution: {integrity: sha512-9NiG6UadG0iOaPL1AMsO5sDKkx6MADHw4/mMOmHWZUhhUwqzfVtnnptMK37vD71e6KyR7yAscx19FrtOWWtjvA==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/coverage-istanbul': 4.1.8 + '@vitest/coverage-v8': 4.1.8 + '@vitest/ui': 4.1.8 + happy-dom: '*' + jsdom: '*' peerDependenciesMeta: '@edge-runtime/vm': optional: true @@ -1060,12 +1670,149 @@ packages: cpu: [arm64] os: [win32] + '@voidzero-dev/vite-plus-win32-arm64-msvc@0.2.9': + resolution: {integrity: sha512-kaKb5Q8ReYTBfvLgUhdpLJG3aoNF8HOVJpf8qBm+THsd4WRrkRwsBHp2ITsU8oXl2gnDjFGhPDaURegd/z6Wxw==} + engines: {node: '>=20.0.0'} + cpu: [arm64] + os: [win32] + '@voidzero-dev/vite-plus-win32-x64-msvc@0.1.22': resolution: {integrity: sha512-GITqtIWeTaWZ7mo1799sIB6XhhSAL1TmuJvrtBz8e3SAUpjDsIYACDYumUDhowPdIHRO3rasyJg9jJZA82BjKQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] + '@voidzero-dev/vite-plus-win32-x64-msvc@0.2.9': + resolution: {integrity: sha512-/fEk3gbQTJknCiYM/GTL/L++Azsav8rCAjmtKrjmCbqEif5IMzqTfvM68n+PiLB3JVoQJGF/mg2niODr0IE/2w==} + engines: {node: '>=20.0.0'} + cpu: [x64] + os: [win32] + + '@yuku-codegen/binding-darwin-arm64@0.5.48': + resolution: {integrity: sha512-yo96Oef12WzqnphInfz/eexVse3+kWgfGS5g2S3rFS3dcGn1ENW9xLFDZUP9rh+yP76DOq38wBoFi1+I9+6qBg==} + cpu: [arm64] + os: [darwin] + + '@yuku-codegen/binding-darwin-x64@0.5.48': + resolution: {integrity: sha512-aRCTw0EZC4bVosmw//0OMYP5tGWFE0Cu5yUBFkUbhXx/iBzvORcJ2xPNlOp/vtCCo9Ys4vp8b0DigJV6uOVb2g==} + cpu: [x64] + os: [darwin] + + '@yuku-codegen/binding-freebsd-x64@0.5.48': + resolution: {integrity: sha512-CA0AQAEApDkbw51PdLWMtKPJ41/7rvXsS3SJs+phG7fHJI+MuFzWuLbkucZfZoEOiDscmcsfYIdgL8BsfuyKKQ==} + cpu: [x64] + os: [freebsd] + + '@yuku-codegen/binding-linux-arm-gnu@0.5.48': + resolution: {integrity: sha512-DuSQlk8bH4gpmW3/00P0NLagAcMv8jOxjT40cQmxKRkktr+SUOALCfkT89tdDq3qtY95NR2GXOZ7AjNh7KKqCw==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@yuku-codegen/binding-linux-arm-musl@0.5.48': + resolution: {integrity: sha512-bxj4Ee+wlaJcWJwft2ReJXWw5sfl1qavDz6+dlRdU1xfTEtjPSNiAWhiCHnJR0R4Ygd57DnzSQmAVGvFv6RcGw==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@yuku-codegen/binding-linux-arm64-gnu@0.5.48': + resolution: {integrity: sha512-mk5JVWh+0JOe5ue8k17kbYX8uGBoKt3ZqoCyxNh4nYAAcX7+X1tFUiU7jbjctu4vHeejCBFSTdQ021+V31cUCQ==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@yuku-codegen/binding-linux-arm64-musl@0.5.48': + resolution: {integrity: sha512-4q3vkrNghbllyxOm2KesFLxCPKHF7r3JyQ7BWZccY1j2Y05yKoIFhoWCqIuQ2W/dpte9RI0+OVfwyxnrKg6fkA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@yuku-codegen/binding-linux-x64-gnu@0.5.48': + resolution: {integrity: sha512-csd4M1EVrGaohM8acM6gq1zpUA/Rwe2ulUMBKUcwQXm/k6n7cq1A++qdew78SOVb4do3JH1WE+WFwoGQAcWc1w==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@yuku-codegen/binding-linux-x64-musl@0.5.48': + resolution: {integrity: sha512-KcDuEOT+GFoVKdvAWOv1v9iYjwnmvMZlO+j1Rw+5PYdeFLGWGzv/DD11y4SAAdwXIFcil4T0hibeIaF82WStMg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@yuku-codegen/binding-win32-arm64@0.5.48': + resolution: {integrity: sha512-HI8qNrI8dWM5BuqIMKsqornRvTNFrE6sm5zToIJ9YIa9zt5+29P7fJ7Nr39EVf6dAWSb6q7JSpScJnRsQ+FgZA==} + cpu: [arm64] + os: [win32] + + '@yuku-codegen/binding-win32-x64@0.5.48': + resolution: {integrity: sha512-X5YWJLO6EfBZpeBqO0AYESnUizbpFDWArcvVD61w0PEWQ3CaFRLnbQXs+kpM4ZZfGMfIE22zfA08QSY67q7TNQ==} + cpu: [x64] + os: [win32] + + '@yuku-parser/binding-darwin-arm64@0.5.48': + resolution: {integrity: sha512-If8mb7HH3vqghJ2NNZ8SuHfhsnjVzOxJpB8xcNOXS5WjYrs2mUhHIh5KOIvK13hDOzh0htGeGK3A6MsiEqE7HQ==} + cpu: [arm64] + os: [darwin] + + '@yuku-parser/binding-darwin-x64@0.5.48': + resolution: {integrity: sha512-EimvPXfspzxf1K11eB6tCW5oiQEXB8g84T2wP1TwzQagdDKo33bkmmVF0B32vTIpXnk/Ifu5IB61izZ1MylljA==} + cpu: [x64] + os: [darwin] + + '@yuku-parser/binding-freebsd-x64@0.5.48': + resolution: {integrity: sha512-0GcUMrumLHheThY9r5Tp46gaZYzn0irWPS1Zba6WY+vVQfhUtzGiWgXxI6tuXX0N32kEaaEVRpkKctvo6Kx3aQ==} + cpu: [x64] + os: [freebsd] + + '@yuku-parser/binding-linux-arm-gnu@0.5.48': + resolution: {integrity: sha512-8S5T5wjCC73dmmpQeZ49aYsSunIUM3D4Fc6rdK96c+Ayg/p3FmeSPF3xuLZHejcTmqJIIvnbfPlUF+rB6DITjQ==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@yuku-parser/binding-linux-arm-musl@0.5.48': + resolution: {integrity: sha512-tTmbxvnUHcK2/crS9547vk2SMmsajH1yqJ8ltXhIuHJgqR1v+d9n9KT+kSayo/5CS76LegeYxhMFjEivBH2hFA==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@yuku-parser/binding-linux-arm64-gnu@0.5.48': + resolution: {integrity: sha512-KGYCBMqI2zfwyhgq5tpPVNe7jpUeYTBm8DhjdS+zqWNumde/PEC170QE5RHxcOAlsirIDeIUk0jqx+r/axoFSw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@yuku-parser/binding-linux-arm64-musl@0.5.48': + resolution: {integrity: sha512-2wTSMsCSXLTc2lZUjMAuU5X4cje55u205WJqfV5NWNF6j9pW/tXyxr15dJeekj8ziLqBXzIsj4DbRh4sY/WcjA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@yuku-parser/binding-linux-x64-gnu@0.5.48': + resolution: {integrity: sha512-d/6v9UnGglVu1WC2JQyv/5aWSi5fXZeGSlidCfmHp4+N65N1GDKUnFtys5MK5eAPeAjTgSHGGtOc/yCcKTlv3A==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@yuku-parser/binding-linux-x64-musl@0.5.48': + resolution: {integrity: sha512-gX19gw6u4ApPy7SYMPKfFlEkrtj6WlORvrTKK3sBQqjyV+8+mUAkQgxXNjHw4RnOiAmVYg7TOlZcg8d+Qqod9A==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@yuku-parser/binding-win32-arm64@0.5.48': + resolution: {integrity: sha512-w6cQQLbqj3Jcom5Q7ifm103NUOQ9d+Cb4VU5lkrZDjMnwVJ9Hzzg1vCQR7miJuF44vhCXldbme5UryE3giEKlA==} + cpu: [arm64] + os: [win32] + + '@yuku-parser/binding-win32-x64@0.5.48': + resolution: {integrity: sha512-4gO0HmG7fzFxrw1rs0dUdnnaY9YgennjETqDWrTSp7x9fmTUOAoN4VsMfP7YyliQeG1WJJHc55O+rOhmsLppow==} + cpu: [x64] + os: [win32] + + '@yuku-toolchain/types@0.5.43': + resolution: {integrity: sha512-kSpvPntnXw5+lYjO71ffBEnQ5ycQ74KGIYknh0TS4xeyCuBkOqxyJumxZkMhLBBUCLjDAbx2+Icnr3Zh4ftjpQ==} + ajv@8.20.0: resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} @@ -1080,10 +1827,17 @@ packages: resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.3: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -1141,6 +1895,10 @@ packages: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + chalk@5.6.2: resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} @@ -1149,13 +1907,23 @@ packages: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -1170,6 +1938,9 @@ packages: engines: {node: '>=18'} hasBin: true + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + events-universal@1.0.1: resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} @@ -1213,9 +1984,8 @@ packages: isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - jiti@2.6.1: - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} - hasBin: true + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} @@ -1232,30 +2002,60 @@ packages: cpu: [arm64] os: [android] + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + lightningcss-darwin-arm64@1.32.0: resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + lightningcss-darwin-x64@1.32.0: resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + lightningcss-freebsd-x64@1.32.0: resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + lightningcss-linux-arm-gnueabihf@1.32.0: resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + lightningcss-linux-arm64-gnu@1.32.0: resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} engines: {node: '>= 12.0.0'} @@ -1263,6 +2063,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} @@ -1270,6 +2077,13 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} @@ -1277,6 +2091,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} @@ -1284,22 +2105,52 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + lightningcss-win32-x64-msvc@1.32.0: resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + lightningcss@1.32.0: resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + mrmime@2.0.1: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} @@ -1317,10 +2168,27 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + oxfmt@0.62.0: + resolution: {integrity: sha512-vxgGHTmnDU9j4CX7dDBLzxgmHxfda/yPcgJkGCMUSCwRmz+euo/V08xXLNgXTeqAB9Fhf3Pe2nO1RNKLCVgphQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + svelte: ^5.0.0 + vite-plus: '*' + peerDependenciesMeta: + svelte: + optional: true + vite-plus: + optional: true + oxlint-tsgolint@0.22.1: resolution: {integrity: sha512-YUSGSLUnoolsu8gxISEDio3q1rtsCozwfOzASUn3DT2mR2EeQ93uEEnen7s+6LpF+lyTQFln1pQfqwBh/fsVEg==} hasBin: true + oxlint-tsgolint@7.0.2001: + resolution: {integrity: sha512-KjK/XLcXr1DSyonKhsuFqJRiuKqcyG9j3LJ8nkOsrLzGvodBPqzHOKauy10asLMDI0sUpvb+1sxlzff3udZvfg==} + hasBin: true + oxlint@1.63.0: resolution: {integrity: sha512-9TGXetdjgIHOJ9OiReomP7nnrMkV9HxC1xM2ramJSLQpzxjsAJtQwa4wqkJN2f/uCrqZuJseFuSlWDdvcruveg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1331,9 +2199,25 @@ packages: oxlint-tsgolint: optional: true + oxlint@1.77.0: + resolution: {integrity: sha512-qnGh8XJHaQ0dprrDXNQZgS0FgjI6v+V3+X8DwmaV++5Aamy6jGKfDdQ1TUvhUxtmKFAbEf4/WeO5QZX+5WSngg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + oxlint-tsgolint: '>=7.0.2001' + vite-plus: '*' + peerDependenciesMeta: + oxlint-tsgolint: + optional: true + vite-plus: + optional: true + pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} @@ -1356,9 +2240,16 @@ packages: resolution: {integrity: sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==} engines: {node: ^10 || ^12 || >=14} + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} @@ -1366,11 +2257,6 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - rolldown@1.0.0-rc.17: - resolution: {integrity: sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -1441,13 +2327,14 @@ packages: resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==} engines: {node: ^20.0.0 || >=22.0.0} + tinyrainbow@3.1.1: + resolution: {integrity: sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==} + engines: {node: '>=14.0.0'} + totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.23.0: resolution: {integrity: sha512-eUdUIaCr963q2h5u3+QwvYp0+eqPvn+egeqZUm0hwERCqqx1E3kK5ehbGCvqSE5MQAULr67ww0cA3jKc3YkM1w==} engines: {node: '>=18.0.0'} @@ -1478,49 +2365,19 @@ packages: vite-plus@0.1.22: resolution: {integrity: sha512-fCCmEKjI+Hv74PdL/MKcrBkdYPHFNcqD5568KxwN0sa4SGxtcbs55i/577LxKs0w5zIjuLRZZ0zQPu9MO+9itg==} engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - - vite@8.0.10: - resolution: {integrity: sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.1.0 - esbuild: ^0.27.0 || ^0.28.0 - jiti: '>=1.21.0' - less: ^4.0.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: '>=0.54.8' - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - '@vitejs/devtools': - optional: true - esbuild: - optional: true - jiti: - optional: true - less: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: + hasBin: true + + vite-plus@0.2.9: + resolution: {integrity: sha512-8uRNqAxh9no3AU4Lep8BEYhkim07+3NO+mhuxTWiN0k30syGT/2+ue/DtWYhtzQ7yi2f2WKpjOhoI4/QkWWbUg==} + engines: {node: ^20.19.0 || ^22.18.0 || >=24.11.0} + hasBin: true + peerDependencies: + '@vitest/browser-playwright': 4.1.10 + '@vitest/browser-webdriverio': 4.1.10 + peerDependenciesMeta: + '@vitest/browser-playwright': optional: true - yaml: + '@vitest/browser-webdriverio': optional: true widest-line@5.0.0: @@ -1557,11 +2414,29 @@ packages: resolution: {integrity: sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==} engines: {node: '>=12'} + yuku-codegen@0.5.48: + resolution: {integrity: sha512-p7HxD5Xl4jzDzqMrGePAOeSHmRY4g58h4HuGq15weQFPxuPWd/W6e7nqp/+Lea6JfpOdBwJOAyXFqIZ/J9Zfnw==} + + yuku-parser@0.5.48: + resolution: {integrity: sha512-OWBfhrpgK9+/4+IXG9oT8Bao4AhViQA7vdyNNH7EUg8dQYgwa70XtIBWTpCEme1P1ECyoDNYkn0wT63f8XRcVA==} + zod@4.4.3: resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} snapshots: + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/runtime@7.29.7': {} + + '@blazediff/core@1.9.1': {} + '@clack/core@0.3.5': dependencies: picocolors: 1.1.1 @@ -1573,21 +2448,74 @@ snapshots: picocolors: 1.1.1 sisteransi: 1.0.5 - '@emnapi/core@1.10.0': + '@deepseek-ai/cordis@4.0.1': dependencies: - '@emnapi/wasi-threads': 1.2.1 - tslib: 2.8.1 - optional: true + '@deepseek-ai/cosmokit': 1.8.2 + '@standard-schema/spec': 1.1.0 - '@emnapi/runtime@1.10.0': + '@deepseek-ai/cosmokit@1.8.2': {} + + '@deepseek-ai/dsh-agent@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-session@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1))))': dependencies: - tslib: 2.8.1 - optional: true + '@deepseek-ai/cordis': 4.0.1 + '@deepseek-ai/dsh-llm': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)) + '@deepseek-ai/dsh-session': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1))) - '@emnapi/wasi-threads@1.2.1': + '@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)': dependencies: - tslib: 2.8.1 - optional: true + '@deepseek-ai/cordis': 4.0.1 + + '@deepseek-ai/dsh-fs@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))': + dependencies: + '@deepseek-ai/cordis': 4.0.1 + '@deepseek-ai/dsh-llm': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)) + + '@deepseek-ai/dsh-launch-environment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)': + dependencies: + '@deepseek-ai/cordis': 4.0.1 + + '@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1))': + dependencies: + '@deepseek-ai/cordis': 4.0.1 + '@deepseek-ai/dsh-attachment': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1) + '@deepseek-ai/schemastery': 3.18.1 + + '@deepseek-ai/dsh-session@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))': + dependencies: + '@deepseek-ai/cordis': 4.0.1 + '@deepseek-ai/dsh-llm': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)) + + '@deepseek-ai/dsh-subagent@0.1.0-rc.6(ce53bf32bdd7023a9119d219810dbe10)': + dependencies: + '@deepseek-ai/cordis': 4.0.1 + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-session@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))) + '@deepseek-ai/dsh-llm': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)) + '@deepseek-ai/dsh-session': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/dsh-tools': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-session@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))))(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-session@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))) + zod: 4.4.3 + + '@deepseek-ai/dsh-subprocess@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)': + dependencies: + '@deepseek-ai/cordis': 4.0.1 + + '@deepseek-ai/dsh-tools@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-agent@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-session@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))))(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-session@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1))))': + dependencies: + '@deepseek-ai/cordis': 4.0.1 + '@deepseek-ai/dsh-agent': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))(@deepseek-ai/dsh-session@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))) + '@deepseek-ai/dsh-llm': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)) + '@deepseek-ai/dsh-session': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1))) + '@deepseek-ai/schemastery': 3.18.1 + + '@deepseek-ai/dsh-web@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-llm@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)))': + dependencies: + '@deepseek-ai/cordis': 4.0.1 + '@deepseek-ai/dsh-llm': 0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)(@deepseek-ai/dsh-attachment@0.1.0-rc.6(@deepseek-ai/cordis@4.0.1)) + '@deepseek-ai/schemastery': 3.18.1 + + '@deepseek-ai/schemastery@3.18.1': + dependencies: + '@deepseek-ai/cosmokit': 1.8.2 + '@standard-schema/spec': 1.1.0 '@esbuild/aix-ppc64@0.28.1': optional: true @@ -1667,12 +2595,7 @@ snapshots: '@esbuild/win32-x64@0.28.1': optional: true - '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': - dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@tybys/wasm-util': 0.10.1 - optional: true + '@jridgewell/sourcemap-codec@1.5.5': {} '@openagentpack/sdk@0.3.1': dependencies: @@ -1682,203 +2605,304 @@ snapshots: '@oxc-project/runtime@0.129.0': {} - '@oxc-project/types@0.127.0': {} + '@oxc-project/runtime@0.133.0': {} + + '@oxc-project/runtime@0.143.0': {} '@oxc-project/types@0.129.0': {} + '@oxc-project/types@0.133.0': {} + + '@oxc-project/types@0.143.0': {} + '@oxfmt/binding-android-arm-eabi@0.48.0': optional: true + '@oxfmt/binding-android-arm-eabi@0.62.0': + optional: true + '@oxfmt/binding-android-arm64@0.48.0': optional: true + '@oxfmt/binding-android-arm64@0.62.0': + optional: true + '@oxfmt/binding-darwin-arm64@0.48.0': optional: true + '@oxfmt/binding-darwin-arm64@0.62.0': + optional: true + '@oxfmt/binding-darwin-x64@0.48.0': optional: true + '@oxfmt/binding-darwin-x64@0.62.0': + optional: true + '@oxfmt/binding-freebsd-x64@0.48.0': optional: true + '@oxfmt/binding-freebsd-x64@0.62.0': + optional: true + '@oxfmt/binding-linux-arm-gnueabihf@0.48.0': optional: true + '@oxfmt/binding-linux-arm-gnueabihf@0.62.0': + optional: true + '@oxfmt/binding-linux-arm-musleabihf@0.48.0': optional: true + '@oxfmt/binding-linux-arm-musleabihf@0.62.0': + optional: true + '@oxfmt/binding-linux-arm64-gnu@0.48.0': optional: true + '@oxfmt/binding-linux-arm64-gnu@0.62.0': + optional: true + '@oxfmt/binding-linux-arm64-musl@0.48.0': optional: true + '@oxfmt/binding-linux-arm64-musl@0.62.0': + optional: true + '@oxfmt/binding-linux-ppc64-gnu@0.48.0': optional: true + '@oxfmt/binding-linux-ppc64-gnu@0.62.0': + optional: true + '@oxfmt/binding-linux-riscv64-gnu@0.48.0': optional: true + '@oxfmt/binding-linux-riscv64-gnu@0.62.0': + optional: true + '@oxfmt/binding-linux-riscv64-musl@0.48.0': optional: true + '@oxfmt/binding-linux-riscv64-musl@0.62.0': + optional: true + '@oxfmt/binding-linux-s390x-gnu@0.48.0': optional: true + '@oxfmt/binding-linux-s390x-gnu@0.62.0': + optional: true + '@oxfmt/binding-linux-x64-gnu@0.48.0': optional: true + '@oxfmt/binding-linux-x64-gnu@0.62.0': + optional: true + '@oxfmt/binding-linux-x64-musl@0.48.0': optional: true + '@oxfmt/binding-linux-x64-musl@0.62.0': + optional: true + '@oxfmt/binding-openharmony-arm64@0.48.0': optional: true + '@oxfmt/binding-openharmony-arm64@0.62.0': + optional: true + '@oxfmt/binding-win32-arm64-msvc@0.48.0': optional: true + '@oxfmt/binding-win32-arm64-msvc@0.62.0': + optional: true + '@oxfmt/binding-win32-ia32-msvc@0.48.0': optional: true + '@oxfmt/binding-win32-ia32-msvc@0.62.0': + optional: true + '@oxfmt/binding-win32-x64-msvc@0.48.0': optional: true + '@oxfmt/binding-win32-x64-msvc@0.62.0': + optional: true + '@oxlint-tsgolint/darwin-arm64@0.22.1': optional: true + '@oxlint-tsgolint/darwin-arm64@7.0.2001': + optional: true + '@oxlint-tsgolint/darwin-x64@0.22.1': optional: true + '@oxlint-tsgolint/darwin-x64@7.0.2001': + optional: true + '@oxlint-tsgolint/linux-arm64@0.22.1': optional: true + '@oxlint-tsgolint/linux-arm64@7.0.2001': + optional: true + '@oxlint-tsgolint/linux-x64@0.22.1': optional: true + '@oxlint-tsgolint/linux-x64@7.0.2001': + optional: true + '@oxlint-tsgolint/win32-arm64@0.22.1': optional: true + '@oxlint-tsgolint/win32-arm64@7.0.2001': + optional: true + '@oxlint-tsgolint/win32-x64@0.22.1': optional: true + '@oxlint-tsgolint/win32-x64@7.0.2001': + optional: true + '@oxlint/binding-android-arm-eabi@1.63.0': optional: true + '@oxlint/binding-android-arm-eabi@1.77.0': + optional: true + '@oxlint/binding-android-arm64@1.63.0': optional: true + '@oxlint/binding-android-arm64@1.77.0': + optional: true + '@oxlint/binding-darwin-arm64@1.63.0': optional: true - '@oxlint/binding-darwin-x64@1.63.0': + '@oxlint/binding-darwin-arm64@1.77.0': optional: true - '@oxlint/binding-freebsd-x64@1.63.0': + '@oxlint/binding-darwin-x64@1.63.0': optional: true - '@oxlint/binding-linux-arm-gnueabihf@1.63.0': + '@oxlint/binding-darwin-x64@1.77.0': optional: true - '@oxlint/binding-linux-arm-musleabihf@1.63.0': + '@oxlint/binding-freebsd-x64@1.63.0': optional: true - '@oxlint/binding-linux-arm64-gnu@1.63.0': + '@oxlint/binding-freebsd-x64@1.77.0': optional: true - '@oxlint/binding-linux-arm64-musl@1.63.0': + '@oxlint/binding-linux-arm-gnueabihf@1.63.0': optional: true - '@oxlint/binding-linux-ppc64-gnu@1.63.0': + '@oxlint/binding-linux-arm-gnueabihf@1.77.0': optional: true - '@oxlint/binding-linux-riscv64-gnu@1.63.0': + '@oxlint/binding-linux-arm-musleabihf@1.63.0': optional: true - '@oxlint/binding-linux-riscv64-musl@1.63.0': + '@oxlint/binding-linux-arm-musleabihf@1.77.0': optional: true - '@oxlint/binding-linux-s390x-gnu@1.63.0': + '@oxlint/binding-linux-arm64-gnu@1.63.0': optional: true - '@oxlint/binding-linux-x64-gnu@1.63.0': + '@oxlint/binding-linux-arm64-gnu@1.77.0': optional: true - '@oxlint/binding-linux-x64-musl@1.63.0': + '@oxlint/binding-linux-arm64-musl@1.63.0': optional: true - '@oxlint/binding-openharmony-arm64@1.63.0': + '@oxlint/binding-linux-arm64-musl@1.77.0': optional: true - '@oxlint/binding-win32-arm64-msvc@1.63.0': + '@oxlint/binding-linux-ppc64-gnu@1.63.0': optional: true - '@oxlint/binding-win32-ia32-msvc@1.63.0': + '@oxlint/binding-linux-ppc64-gnu@1.77.0': optional: true - '@oxlint/binding-win32-x64-msvc@1.63.0': + '@oxlint/binding-linux-riscv64-gnu@1.63.0': optional: true - '@oxlint/plugins@1.61.0': {} + '@oxlint/binding-linux-riscv64-gnu@1.77.0': + optional: true - '@polka/url@1.0.0-next.29': {} + '@oxlint/binding-linux-riscv64-musl@1.63.0': + optional: true - '@rolldown/binding-android-arm64@1.0.0-rc.17': + '@oxlint/binding-linux-riscv64-musl@1.77.0': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-rc.17': + '@oxlint/binding-linux-s390x-gnu@1.63.0': optional: true - '@rolldown/binding-darwin-x64@1.0.0-rc.17': + '@oxlint/binding-linux-s390x-gnu@1.77.0': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-rc.17': + '@oxlint/binding-linux-x64-gnu@1.63.0': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': + '@oxlint/binding-linux-x64-gnu@1.77.0': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': + '@oxlint/binding-linux-x64-musl@1.63.0': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': + '@oxlint/binding-linux-x64-musl@1.77.0': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': + '@oxlint/binding-openharmony-arm64@1.63.0': optional: true - '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': + '@oxlint/binding-openharmony-arm64@1.77.0': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': + '@oxlint/binding-win32-arm64-msvc@1.63.0': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': + '@oxlint/binding-win32-arm64-msvc@1.77.0': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': + '@oxlint/binding-win32-ia32-msvc@1.63.0': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': - dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + '@oxlint/binding-win32-ia32-msvc@1.77.0': optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': + '@oxlint/binding-win32-x64-msvc@1.63.0': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': + '@oxlint/binding-win32-x64-msvc@1.77.0': optional: true - '@rolldown/pluginutils@1.0.0-rc.17': {} + '@oxlint/plugins@1.61.0': {} + + '@oxlint/plugins@1.73.0': {} + + '@polka/url@1.0.0-next.29': {} '@standard-schema/spec@1.1.0': {} - '@tybys/wasm-util@0.10.1': + '@testing-library/dom@10.4.1': dependencies: - tslib: 2.8.1 - optional: true + '@babel/code-frame': 7.29.7 + '@babel/runtime': 7.29.7 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + picocolors: 1.1.1 + pretty-format: 27.5.1 + + '@testing-library/user-event@14.6.4(@testing-library/dom@10.4.1)': + dependencies: + '@testing-library/dom': 10.4.1 + + '@types/aria-query@5.0.4': {} '@types/chai@5.2.3': dependencies: @@ -1887,6 +2911,8 @@ snapshots: '@types/deep-eql@4.0.2': {} + '@types/estree@1.0.9': {} + '@types/node@24.12.2': dependencies: undici-types: 7.16.0 @@ -1934,7 +2960,158 @@ snapshots: '@typescript/native-preview-win32-arm64': 7.0.0-dev.20260328.1 '@typescript/native-preview-win32-x64': 7.0.0-dev.20260328.1 - '@voidzero-dev/vite-plus-core@0.1.22(@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/browser-preview@4.1.10(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)': + dependencies: + '@testing-library/dom': 10.4.1 + '@testing-library/user-event': 14.6.4(@testing-library/dom@10.4.1) + '@vitest/browser': 4.1.10(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) + vitest: '@voidzero-dev/vite-plus-test@0.1.24(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@edge-runtime/vm' + - '@opentelemetry/api' + - '@tsdown/css' + - '@tsdown/exe' + - '@types/node' + - '@vitejs/devtools' + - '@vitest/coverage-istanbul' + - '@vitest/coverage-v8' + - '@vitest/ui' + - bufferutil + - esbuild + - happy-dom + - jiti + - jsdom + - less + - msw + - publint + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - utf-8-validate + - yaml + + '@vitest/browser@4.1.10(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.10(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) + '@vitest/utils': 4.1.10 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.1 + vitest: '@voidzero-dev/vite-plus-test@0.1.24(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' + ws: 8.20.0 + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@edge-runtime/vm' + - '@opentelemetry/api' + - '@tsdown/css' + - '@tsdown/exe' + - '@types/node' + - '@vitejs/devtools' + - '@vitest/coverage-istanbul' + - '@vitest/coverage-v8' + - '@vitest/ui' + - bufferutil + - esbuild + - happy-dom + - jiti + - jsdom + - less + - msw + - publint + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - utf-8-validate + - yaml + + '@vitest/expect@4.1.10': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + chai: 6.2.2 + tinyrainbow: 3.1.1 + + '@vitest/mocker@4.1.10(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)': + dependencies: + '@vitest/spy': 4.1.10 + estree-walker: 3.0.3 + magic-string: 0.30.21 + vite: '@voidzero-dev/vite-plus-core@0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@types/node' + - '@vitejs/devtools' + - esbuild + - jiti + - less + - publint + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - yaml + + '@vitest/pretty-format@4.1.10': + dependencies: + tinyrainbow: 3.1.1 + + '@vitest/runner@4.1.10': + dependencies: + '@vitest/utils': 4.1.10 + pathe: 2.0.3 + + '@vitest/snapshot@4.1.10': + dependencies: + '@vitest/pretty-format': 4.1.10 + '@vitest/utils': 4.1.10 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.1.10': {} + + '@vitest/utils@4.1.10': + dependencies: + '@vitest/pretty-format': 4.1.10 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.1 + + '@voidzero-dev/vite-plus-core@0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)': + dependencies: + '@oxc-project/runtime': 0.129.0 + '@oxc-project/types': 0.129.0 + lightningcss: 1.32.0 + postcss: 8.5.12 + optionalDependencies: + '@types/node': 24.12.2 + esbuild: 0.28.1 + fsevents: 2.3.3 + tsx: 4.23.0 + typescript: 6.0.3 + yaml: 2.8.3 + + '@voidzero-dev/vite-plus-core@0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)': dependencies: '@oxc-project/runtime': 0.129.0 '@oxc-project/types': 0.129.0 @@ -1944,37 +3121,106 @@ snapshots: '@types/node': 24.12.2 esbuild: 0.28.1 fsevents: 2.3.3 - jiti: 2.6.1 tsx: 4.23.0 typescript: 6.0.3 - yaml: 2.8.3 + yaml: 2.9.0 - '@voidzero-dev/vite-plus-core@0.1.22(@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)': + '@voidzero-dev/vite-plus-core@0.1.22(@types/node@25.6.0)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)': dependencies: '@oxc-project/runtime': 0.129.0 '@oxc-project/types': 0.129.0 lightningcss: 1.32.0 postcss: 8.5.12 + optionalDependencies: + '@types/node': 25.6.0 + esbuild: 0.28.1 + fsevents: 2.3.3 + tsx: 4.23.0 + typescript: 6.0.3 + yaml: 2.9.0 + + '@voidzero-dev/vite-plus-core@0.1.24(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)': + dependencies: + '@oxc-project/runtime': 0.133.0 + '@oxc-project/types': 0.133.0 + lightningcss: 1.33.0 + postcss: 8.5.12 optionalDependencies: '@types/node': 24.12.2 esbuild: 0.28.1 fsevents: 2.3.3 - jiti: 2.6.1 tsx: 4.23.0 typescript: 6.0.3 yaml: 2.9.0 - '@voidzero-dev/vite-plus-core@0.1.22(@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)': + '@voidzero-dev/vite-plus-core@0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)': dependencies: - '@oxc-project/runtime': 0.129.0 - '@oxc-project/types': 0.129.0 - lightningcss: 1.32.0 + '@oxc-project/runtime': 0.143.0 + '@oxc-project/types': 0.143.0 + lightningcss: 1.33.0 + postcss: 8.5.12 + yuku-codegen: 0.5.48 + yuku-parser: 0.5.48 + optionalDependencies: + '@types/node': 24.12.2 + '@voidzero-dev/vite-plus-darwin-arm64': 0.2.9 + '@voidzero-dev/vite-plus-darwin-x64': 0.2.9 + '@voidzero-dev/vite-plus-linux-arm64-gnu': 0.2.9 + '@voidzero-dev/vite-plus-linux-arm64-musl': 0.2.9 + '@voidzero-dev/vite-plus-linux-x64-gnu': 0.2.9 + '@voidzero-dev/vite-plus-linux-x64-musl': 0.2.9 + '@voidzero-dev/vite-plus-win32-arm64-msvc': 0.2.9 + '@voidzero-dev/vite-plus-win32-x64-msvc': 0.2.9 + esbuild: 0.28.1 + fsevents: 2.3.3 + tsx: 4.23.0 + typescript: 6.0.3 + yaml: 2.8.3 + + '@voidzero-dev/vite-plus-core@0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)': + dependencies: + '@oxc-project/runtime': 0.143.0 + '@oxc-project/types': 0.143.0 + lightningcss: 1.33.0 + postcss: 8.5.12 + yuku-codegen: 0.5.48 + yuku-parser: 0.5.48 + optionalDependencies: + '@types/node': 24.12.2 + '@voidzero-dev/vite-plus-darwin-arm64': 0.2.9 + '@voidzero-dev/vite-plus-darwin-x64': 0.2.9 + '@voidzero-dev/vite-plus-linux-arm64-gnu': 0.2.9 + '@voidzero-dev/vite-plus-linux-arm64-musl': 0.2.9 + '@voidzero-dev/vite-plus-linux-x64-gnu': 0.2.9 + '@voidzero-dev/vite-plus-linux-x64-musl': 0.2.9 + '@voidzero-dev/vite-plus-win32-arm64-msvc': 0.2.9 + '@voidzero-dev/vite-plus-win32-x64-msvc': 0.2.9 + esbuild: 0.28.1 + fsevents: 2.3.3 + tsx: 4.23.0 + typescript: 6.0.3 + yaml: 2.9.0 + + '@voidzero-dev/vite-plus-core@0.2.9(@types/node@25.6.0)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)': + dependencies: + '@oxc-project/runtime': 0.143.0 + '@oxc-project/types': 0.143.0 + lightningcss: 1.33.0 postcss: 8.5.12 + yuku-codegen: 0.5.48 + yuku-parser: 0.5.48 optionalDependencies: '@types/node': 25.6.0 + '@voidzero-dev/vite-plus-darwin-arm64': 0.2.9 + '@voidzero-dev/vite-plus-darwin-x64': 0.2.9 + '@voidzero-dev/vite-plus-linux-arm64-gnu': 0.2.9 + '@voidzero-dev/vite-plus-linux-arm64-musl': 0.2.9 + '@voidzero-dev/vite-plus-linux-x64-gnu': 0.2.9 + '@voidzero-dev/vite-plus-linux-x64-musl': 0.2.9 + '@voidzero-dev/vite-plus-win32-arm64-msvc': 0.2.9 + '@voidzero-dev/vite-plus-win32-x64-msvc': 0.2.9 esbuild: 0.28.1 fsevents: 2.3.3 - jiti: 2.6.1 tsx: 4.23.0 typescript: 6.0.3 yaml: 2.9.0 @@ -1982,26 +3228,44 @@ snapshots: '@voidzero-dev/vite-plus-darwin-arm64@0.1.22': optional: true + '@voidzero-dev/vite-plus-darwin-arm64@0.2.9': + optional: true + '@voidzero-dev/vite-plus-darwin-x64@0.1.22': optional: true + '@voidzero-dev/vite-plus-darwin-x64@0.2.9': + optional: true + '@voidzero-dev/vite-plus-linux-arm64-gnu@0.1.22': optional: true + '@voidzero-dev/vite-plus-linux-arm64-gnu@0.2.9': + optional: true + '@voidzero-dev/vite-plus-linux-arm64-musl@0.1.22': optional: true + '@voidzero-dev/vite-plus-linux-arm64-musl@0.2.9': + optional: true + '@voidzero-dev/vite-plus-linux-x64-gnu@0.1.22': optional: true + '@voidzero-dev/vite-plus-linux-x64-gnu@0.2.9': + optional: true + '@voidzero-dev/vite-plus-linux-x64-musl@0.1.22': optional: true - '@voidzero-dev/vite-plus-test@0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.8.3))(yaml@2.8.3)': + '@voidzero-dev/vite-plus-linux-x64-musl@0.2.9': + optional: true + + '@voidzero-dev/vite-plus-test@0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@voidzero-dev/vite-plus-core': 0.1.22(@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) + '@voidzero-dev/vite-plus-core': 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3) es-module-lexer: 1.7.0 obug: 2.1.1 pixelmatch: 7.2.0 @@ -2011,7 +3275,7 @@ snapshots: tinybench: 2.9.0 tinyexec: 1.1.2 tinyglobby: 0.2.16 - vite: 8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.8.3) + vite: '@voidzero-dev/vite-plus-core@0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3)' ws: 8.20.0 optionalDependencies: '@types/node': 24.12.2 @@ -2037,11 +3301,11 @@ snapshots: - utf-8-validate - yaml - '@voidzero-dev/vite-plus-test@0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.9.0))(yaml@2.9.0)': + '@voidzero-dev/vite-plus-test@0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@voidzero-dev/vite-plus-core': 0.1.22(@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) + '@voidzero-dev/vite-plus-core': 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) es-module-lexer: 1.7.0 obug: 2.1.1 pixelmatch: 7.2.0 @@ -2051,7 +3315,7 @@ snapshots: tinybench: 2.9.0 tinyexec: 1.1.2 tinyglobby: 0.2.16 - vite: 8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.9.0) + vite: '@voidzero-dev/vite-plus-core@0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' ws: 8.20.0 optionalDependencies: '@types/node': 24.12.2 @@ -2077,11 +3341,11 @@ snapshots: - utf-8-validate - yaml - '@voidzero-dev/vite-plus-test@0.1.22(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.9.0))(yaml@2.9.0)': + '@voidzero-dev/vite-plus-test@0.1.22(@types/node@25.6.0)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@voidzero-dev/vite-plus-core': 0.1.22(@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) + '@voidzero-dev/vite-plus-core': 0.1.22(@types/node@25.6.0)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) es-module-lexer: 1.7.0 obug: 2.1.1 pixelmatch: 7.2.0 @@ -2091,7 +3355,7 @@ snapshots: tinybench: 2.9.0 tinyexec: 1.1.2 tinyglobby: 0.2.16 - vite: 8.0.10(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.9.0) + vite: '@voidzero-dev/vite-plus-core@0.2.9(@types/node@25.6.0)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' ws: 8.20.0 optionalDependencies: '@types/node': 25.6.0 @@ -2117,12 +3381,126 @@ snapshots: - utf-8-validate - yaml + '@voidzero-dev/vite-plus-test@0.1.24(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@voidzero-dev/vite-plus-core': 0.1.24(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) + es-module-lexer: 1.7.0 + obug: 2.1.1 + pixelmatch: 7.2.0 + pngjs: 7.0.0 + sirv: 3.0.2 + std-env: 4.1.0 + tinybench: 2.9.0 + tinyexec: 1.1.2 + tinyglobby: 0.2.16 + vite: '@voidzero-dev/vite-plus-core@0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' + ws: 8.20.0 + optionalDependencies: + '@types/node': 24.12.2 + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@tsdown/css' + - '@tsdown/exe' + - '@vitejs/devtools' + - bufferutil + - esbuild + - jiti + - less + - publint + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - utf-8-validate + - yaml + '@voidzero-dev/vite-plus-win32-arm64-msvc@0.1.22': optional: true + '@voidzero-dev/vite-plus-win32-arm64-msvc@0.2.9': + optional: true + '@voidzero-dev/vite-plus-win32-x64-msvc@0.1.22': optional: true + '@voidzero-dev/vite-plus-win32-x64-msvc@0.2.9': + optional: true + + '@yuku-codegen/binding-darwin-arm64@0.5.48': + optional: true + + '@yuku-codegen/binding-darwin-x64@0.5.48': + optional: true + + '@yuku-codegen/binding-freebsd-x64@0.5.48': + optional: true + + '@yuku-codegen/binding-linux-arm-gnu@0.5.48': + optional: true + + '@yuku-codegen/binding-linux-arm-musl@0.5.48': + optional: true + + '@yuku-codegen/binding-linux-arm64-gnu@0.5.48': + optional: true + + '@yuku-codegen/binding-linux-arm64-musl@0.5.48': + optional: true + + '@yuku-codegen/binding-linux-x64-gnu@0.5.48': + optional: true + + '@yuku-codegen/binding-linux-x64-musl@0.5.48': + optional: true + + '@yuku-codegen/binding-win32-arm64@0.5.48': + optional: true + + '@yuku-codegen/binding-win32-x64@0.5.48': + optional: true + + '@yuku-parser/binding-darwin-arm64@0.5.48': + optional: true + + '@yuku-parser/binding-darwin-x64@0.5.48': + optional: true + + '@yuku-parser/binding-freebsd-x64@0.5.48': + optional: true + + '@yuku-parser/binding-linux-arm-gnu@0.5.48': + optional: true + + '@yuku-parser/binding-linux-arm-musl@0.5.48': + optional: true + + '@yuku-parser/binding-linux-arm64-gnu@0.5.48': + optional: true + + '@yuku-parser/binding-linux-arm64-musl@0.5.48': + optional: true + + '@yuku-parser/binding-linux-x64-gnu@0.5.48': + optional: true + + '@yuku-parser/binding-linux-x64-musl@0.5.48': + optional: true + + '@yuku-parser/binding-win32-arm64@0.5.48': + optional: true + + '@yuku-parser/binding-win32-x64@0.5.48': + optional: true + + '@yuku-toolchain/types@0.5.43': {} + ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 @@ -2138,8 +3516,14 @@ snapshots: ansi-regex@6.2.2: {} + ansi-styles@5.2.0: {} + ansi-styles@6.2.3: {} + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + assertion-error@2.0.1: {} b4a@1.8.1: {} @@ -2186,14 +3570,22 @@ snapshots: camelcase@8.0.0: {} + chai@6.2.2: {} + chalk@5.6.2: {} cli-boxes@3.0.0: {} + convert-source-map@2.0.0: {} + core-util-is@1.0.3: {} + dequal@2.0.3: {} + detect-libc@2.1.2: {} + dom-accessibility-api@0.5.16: {} + emoji-regex@10.6.0: {} emoji-regex@8.0.0: {} @@ -2229,6 +3621,10 @@ snapshots: '@esbuild/win32-ia32': 0.28.1 '@esbuild/win32-x64': 0.28.1 + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + events-universal@1.0.1: dependencies: bare-events: 2.9.1 @@ -2258,8 +3654,7 @@ snapshots: isarray@1.0.0: {} - jiti@2.6.1: - optional: true + js-tokens@4.0.0: {} json-schema-traverse@1.0.0: {} @@ -2277,36 +3672,69 @@ snapshots: lightningcss-android-arm64@1.32.0: optional: true + lightningcss-android-arm64@1.33.0: + optional: true + lightningcss-darwin-arm64@1.32.0: optional: true + lightningcss-darwin-arm64@1.33.0: + optional: true + lightningcss-darwin-x64@1.32.0: optional: true + lightningcss-darwin-x64@1.33.0: + optional: true + lightningcss-freebsd-x64@1.32.0: optional: true + lightningcss-freebsd-x64@1.33.0: + optional: true + lightningcss-linux-arm-gnueabihf@1.32.0: optional: true + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + lightningcss-linux-arm64-gnu@1.32.0: optional: true + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + lightningcss-linux-arm64-musl@1.32.0: optional: true + lightningcss-linux-arm64-musl@1.33.0: + optional: true + lightningcss-linux-x64-gnu@1.32.0: optional: true + lightningcss-linux-x64-gnu@1.33.0: + optional: true + lightningcss-linux-x64-musl@1.32.0: optional: true + lightningcss-linux-x64-musl@1.33.0: + optional: true + lightningcss-win32-arm64-msvc@1.32.0: optional: true + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + lightningcss-win32-x64-msvc@1.32.0: optional: true + lightningcss-win32-x64-msvc@1.33.0: + optional: true + lightningcss@1.32.0: dependencies: detect-libc: 2.1.2 @@ -2323,6 +3751,28 @@ snapshots: lightningcss-win32-arm64-msvc: 1.32.0 lightningcss-win32-x64-msvc: 1.32.0 + lightningcss@1.33.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + + lz-string@1.5.0: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + mrmime@2.0.1: {} nanoid@3.3.11: {} @@ -2353,6 +3803,31 @@ snapshots: '@oxfmt/binding-win32-ia32-msvc': 0.48.0 '@oxfmt/binding-win32-x64-msvc': 0.48.0 + oxfmt@0.62.0(vite-plus@0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)): + dependencies: + tinypool: 2.1.0 + optionalDependencies: + '@oxfmt/binding-android-arm-eabi': 0.62.0 + '@oxfmt/binding-android-arm64': 0.62.0 + '@oxfmt/binding-darwin-arm64': 0.62.0 + '@oxfmt/binding-darwin-x64': 0.62.0 + '@oxfmt/binding-freebsd-x64': 0.62.0 + '@oxfmt/binding-linux-arm-gnueabihf': 0.62.0 + '@oxfmt/binding-linux-arm-musleabihf': 0.62.0 + '@oxfmt/binding-linux-arm64-gnu': 0.62.0 + '@oxfmt/binding-linux-arm64-musl': 0.62.0 + '@oxfmt/binding-linux-ppc64-gnu': 0.62.0 + '@oxfmt/binding-linux-riscv64-gnu': 0.62.0 + '@oxfmt/binding-linux-riscv64-musl': 0.62.0 + '@oxfmt/binding-linux-s390x-gnu': 0.62.0 + '@oxfmt/binding-linux-x64-gnu': 0.62.0 + '@oxfmt/binding-linux-x64-musl': 0.62.0 + '@oxfmt/binding-openharmony-arm64': 0.62.0 + '@oxfmt/binding-win32-arm64-msvc': 0.62.0 + '@oxfmt/binding-win32-ia32-msvc': 0.62.0 + '@oxfmt/binding-win32-x64-msvc': 0.62.0 + vite-plus: 0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) + oxlint-tsgolint@0.22.1: optionalDependencies: '@oxlint-tsgolint/darwin-arm64': 0.22.1 @@ -2362,6 +3837,15 @@ snapshots: '@oxlint-tsgolint/win32-arm64': 0.22.1 '@oxlint-tsgolint/win32-x64': 0.22.1 + oxlint-tsgolint@7.0.2001: + optionalDependencies: + '@oxlint-tsgolint/darwin-arm64': 7.0.2001 + '@oxlint-tsgolint/darwin-x64': 7.0.2001 + '@oxlint-tsgolint/linux-arm64': 7.0.2001 + '@oxlint-tsgolint/linux-x64': 7.0.2001 + '@oxlint-tsgolint/win32-arm64': 7.0.2001 + '@oxlint-tsgolint/win32-x64': 7.0.2001 + oxlint@1.63.0(oxlint-tsgolint@0.22.1): optionalDependencies: '@oxlint/binding-android-arm-eabi': 1.63.0 @@ -2385,8 +3869,34 @@ snapshots: '@oxlint/binding-win32-x64-msvc': 1.63.0 oxlint-tsgolint: 0.22.1 + oxlint@1.77.0(oxlint-tsgolint@7.0.2001)(vite-plus@0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)): + optionalDependencies: + '@oxlint/binding-android-arm-eabi': 1.77.0 + '@oxlint/binding-android-arm64': 1.77.0 + '@oxlint/binding-darwin-arm64': 1.77.0 + '@oxlint/binding-darwin-x64': 1.77.0 + '@oxlint/binding-freebsd-x64': 1.77.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.77.0 + '@oxlint/binding-linux-arm-musleabihf': 1.77.0 + '@oxlint/binding-linux-arm64-gnu': 1.77.0 + '@oxlint/binding-linux-arm64-musl': 1.77.0 + '@oxlint/binding-linux-ppc64-gnu': 1.77.0 + '@oxlint/binding-linux-riscv64-gnu': 1.77.0 + '@oxlint/binding-linux-riscv64-musl': 1.77.0 + '@oxlint/binding-linux-s390x-gnu': 1.77.0 + '@oxlint/binding-linux-x64-gnu': 1.77.0 + '@oxlint/binding-linux-x64-musl': 1.77.0 + '@oxlint/binding-openharmony-arm64': 1.77.0 + '@oxlint/binding-win32-arm64-msvc': 1.77.0 + '@oxlint/binding-win32-ia32-msvc': 1.77.0 + '@oxlint/binding-win32-x64-msvc': 1.77.0 + oxlint-tsgolint: 7.0.2001 + vite-plus: 0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) + pako@1.0.11: {} + pathe@2.0.3: {} + pend@1.2.0: {} picocolors@1.1.1: {} @@ -2405,8 +3915,16 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + process-nextick-args@2.0.1: {} + react-is@17.0.2: {} + readable-stream@2.3.8: dependencies: core-util-is: 1.0.3 @@ -2419,27 +3937,6 @@ snapshots: require-from-string@2.0.2: {} - rolldown@1.0.0-rc.17: - dependencies: - '@oxc-project/types': 0.127.0 - '@rolldown/pluginutils': 1.0.0-rc.17 - optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-rc.17 - '@rolldown/binding-darwin-arm64': 1.0.0-rc.17 - '@rolldown/binding-darwin-x64': 1.0.0-rc.17 - '@rolldown/binding-freebsd-x64': 1.0.0-rc.17 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.17 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.17 - '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.17 - '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.17 - '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.17 - '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.17 - '@rolldown/binding-linux-x64-musl': 1.0.0-rc.17 - '@rolldown/binding-openharmony-arm64': 1.0.0-rc.17 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.17 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.17 - '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.17 - safe-buffer@5.1.2: {} setimmediate@1.0.5: {} @@ -2526,10 +4023,9 @@ snapshots: tinypool@2.1.0: {} - totalist@3.0.1: {} + tinyrainbow@3.1.1: {} - tslib@2.8.1: - optional: true + totalist@3.0.1: {} tsx@4.23.0: dependencies: @@ -2549,12 +4045,12 @@ snapshots: util-deprecate@1.0.2: {} - vite-plus@0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.8.3))(yaml@2.8.3): + vite-plus@0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3): dependencies: '@oxc-project/types': 0.129.0 '@oxlint/plugins': 1.61.0 - '@voidzero-dev/vite-plus-core': 0.1.22(@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) - '@voidzero-dev/vite-plus-test': 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.8.3))(yaml@2.8.3) + '@voidzero-dev/vite-plus-core': 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3) + '@voidzero-dev/vite-plus-test': 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.8.3) oxfmt: 0.48.0 oxlint: 1.63.0(oxlint-tsgolint@0.22.1) oxlint-tsgolint: 0.22.1 @@ -2595,15 +4091,14 @@ snapshots: - unplugin-unused - unrun - utf-8-validate - - vite - yaml - vite-plus@0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.9.0))(yaml@2.9.0): + vite-plus@0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0): dependencies: '@oxc-project/types': 0.129.0 '@oxlint/plugins': 1.61.0 - '@voidzero-dev/vite-plus-core': 0.1.22(@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) - '@voidzero-dev/vite-plus-test': 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.9.0))(yaml@2.9.0) + '@voidzero-dev/vite-plus-core': 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) + '@voidzero-dev/vite-plus-test': 0.1.22(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) oxfmt: 0.48.0 oxlint: 1.63.0(oxlint-tsgolint@0.22.1) oxlint-tsgolint: 0.22.1 @@ -2644,15 +4139,14 @@ snapshots: - unplugin-unused - unrun - utf-8-validate - - vite - yaml - vite-plus@0.1.22(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.9.0))(yaml@2.9.0): + vite-plus@0.1.22(@types/node@25.6.0)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0): dependencies: '@oxc-project/types': 0.129.0 '@oxlint/plugins': 1.61.0 - '@voidzero-dev/vite-plus-core': 0.1.22(@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) - '@voidzero-dev/vite-plus-test': 0.1.22(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(typescript@6.0.3)(vite@8.0.10(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.9.0))(yaml@2.9.0) + '@voidzero-dev/vite-plus-core': 0.1.22(@types/node@25.6.0)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) + '@voidzero-dev/vite-plus-test': 0.1.22(@types/node@25.6.0)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) oxfmt: 0.48.0 oxlint: 1.63.0(oxlint-tsgolint@0.22.1) oxlint-tsgolint: 0.22.1 @@ -2693,53 +4187,66 @@ snapshots: - unplugin-unused - unrun - utf-8-validate - - vite - yaml - vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.8.3): - dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.12 - rolldown: 1.0.0-rc.17 - tinyglobby: 0.2.16 - optionalDependencies: - '@types/node': 24.12.2 - esbuild: 0.28.1 - fsevents: 2.3.3 - jiti: 2.6.1 - tsx: 4.23.0 - yaml: 2.8.3 - - vite@8.0.10(@types/node@24.12.2)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.9.0): - dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.12 - rolldown: 1.0.0-rc.17 - tinyglobby: 0.2.16 - optionalDependencies: - '@types/node': 24.12.2 - esbuild: 0.28.1 - fsevents: 2.3.3 - jiti: 2.6.1 - tsx: 4.23.0 - yaml: 2.9.0 - - vite@8.0.10(@types/node@25.6.0)(esbuild@0.28.1)(jiti@2.6.1)(tsx@4.23.0)(yaml@2.9.0): + vite-plus@0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0): dependencies: - lightningcss: 1.32.0 - picomatch: 4.0.4 - postcss: 8.5.12 - rolldown: 1.0.0-rc.17 - tinyglobby: 0.2.16 + '@oxc-project/types': 0.143.0 + '@oxlint/plugins': 1.73.0 + '@vitest/browser': 4.1.10(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) + '@vitest/browser-preview': 4.1.10(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + '@voidzero-dev/vite-plus-core': 0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0) + oxfmt: 0.62.0(vite-plus@0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + oxlint: 1.77.0(oxlint-tsgolint@7.0.2001)(vite-plus@0.2.9(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)) + oxlint-tsgolint: 7.0.2001 + vitest: '@voidzero-dev/vite-plus-test@0.1.24(@types/node@24.12.2)(esbuild@0.28.1)(tsx@4.23.0)(typescript@6.0.3)(yaml@2.9.0)' optionalDependencies: - '@types/node': 25.6.0 - esbuild: 0.28.1 - fsevents: 2.3.3 - jiti: 2.6.1 - tsx: 4.23.0 - yaml: 2.9.0 + '@voidzero-dev/vite-plus-darwin-arm64': 0.2.9 + '@voidzero-dev/vite-plus-darwin-x64': 0.2.9 + '@voidzero-dev/vite-plus-linux-arm64-gnu': 0.2.9 + '@voidzero-dev/vite-plus-linux-arm64-musl': 0.2.9 + '@voidzero-dev/vite-plus-linux-x64-gnu': 0.2.9 + '@voidzero-dev/vite-plus-linux-x64-musl': 0.2.9 + '@voidzero-dev/vite-plus-win32-arm64-msvc': 0.2.9 + '@voidzero-dev/vite-plus-win32-x64-msvc': 0.2.9 + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@edge-runtime/vm' + - '@opentelemetry/api' + - '@tsdown/css' + - '@tsdown/exe' + - '@types/node' + - '@vitejs/devtools' + - '@vitest/coverage-istanbul' + - '@vitest/coverage-v8' + - '@vitest/ui' + - bufferutil + - esbuild + - happy-dom + - jiti + - jsdom + - less + - msw + - publint + - sass + - sass-embedded + - stylus + - sugarss + - svelte + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - utf-8-validate + - yaml widest-line@5.0.0: dependencies: @@ -2761,4 +4268,36 @@ snapshots: dependencies: pend: 1.2.0 + yuku-codegen@0.5.48: + dependencies: + '@yuku-toolchain/types': 0.5.43 + optionalDependencies: + '@yuku-codegen/binding-darwin-arm64': 0.5.48 + '@yuku-codegen/binding-darwin-x64': 0.5.48 + '@yuku-codegen/binding-freebsd-x64': 0.5.48 + '@yuku-codegen/binding-linux-arm-gnu': 0.5.48 + '@yuku-codegen/binding-linux-arm-musl': 0.5.48 + '@yuku-codegen/binding-linux-arm64-gnu': 0.5.48 + '@yuku-codegen/binding-linux-arm64-musl': 0.5.48 + '@yuku-codegen/binding-linux-x64-gnu': 0.5.48 + '@yuku-codegen/binding-linux-x64-musl': 0.5.48 + '@yuku-codegen/binding-win32-arm64': 0.5.48 + '@yuku-codegen/binding-win32-x64': 0.5.48 + + yuku-parser@0.5.48: + dependencies: + '@yuku-toolchain/types': 0.5.43 + optionalDependencies: + '@yuku-parser/binding-darwin-arm64': 0.5.48 + '@yuku-parser/binding-darwin-x64': 0.5.48 + '@yuku-parser/binding-freebsd-x64': 0.5.48 + '@yuku-parser/binding-linux-arm-gnu': 0.5.48 + '@yuku-parser/binding-linux-arm-musl': 0.5.48 + '@yuku-parser/binding-linux-arm64-gnu': 0.5.48 + '@yuku-parser/binding-linux-arm64-musl': 0.5.48 + '@yuku-parser/binding-linux-x64-gnu': 0.5.48 + '@yuku-parser/binding-linux-x64-musl': 0.5.48 + '@yuku-parser/binding-win32-arm64': 0.5.48 + '@yuku-parser/binding-win32-x64': 0.5.48 + zod@4.4.3: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 611df313..8d4ef52d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -24,6 +24,10 @@ catalogMode: prefer overrides: vite: "catalog:" vitest: "catalog:" +# The @deepseek-ai/dsh-* rc line (used only by bailian-cli-dsh) peers on +# packages that were never published: dsh-type-meta, dsh-environment, +# dsh-tasks. Auto-installing peers therefore 404s the whole workspace. +autoInstallPeers: false peerDependencyRules: allowAny: - vite diff --git a/skills/bailian-cli/reference/index.md b/skills/bailian-cli/reference/index.md index c4dd1cd4..12d1410b 100644 --- a/skills/bailian-cli/reference/index.md +++ b/skills/bailian-cli/reference/index.md @@ -36,7 +36,11 @@ Use this index for the skill-scoped quick index and global flags. | `bl memory delete` | Delete a memory node | [memory.md](memory.md) | | `bl memory list` | List memory nodes for a user | [memory.md](memory.md) | | `bl memory profile create` | Create a user profile schema for memory profiling | [memory.md](memory.md) | +| `bl memory profile delete` | Delete a profile schema | [memory.md](memory.md) | +| `bl memory profile detail` | Show a profile schema and its attribute IDs | [memory.md](memory.md) | | `bl memory profile get` | Get user profile by schema ID and user ID | [memory.md](memory.md) | +| `bl memory profile list` | List profile schemas | [memory.md](memory.md) | +| `bl memory profile update` | Update a profile schema's name, description, or attributes | [memory.md](memory.md) | | `bl memory search` | Search memory nodes by query or messages | [memory.md](memory.md) | | `bl memory update` | Update a memory node content | [memory.md](memory.md) | | `bl model list` | Browse model families or show detailed model info in the Bailian model marketplace | [model.md](model.md) | @@ -71,28 +75,28 @@ Use this index for the skill-scoped quick index and global flags. ## By group -| Group | Commands | Reference | -| ------------ | ---------------------------------------------------------------------------- | ------------------------------ | -| `advisor` | `recommend` | [advisor.md](advisor.md) | -| `app` | `call`, `list` | [app.md](app.md) | -| `auth` | `generate-access-token`, `login`, `logout`, `status` | [auth.md](auth.md) | -| `config` | `agent`, `list`, `set`, `show`, `ui`, `use` | [config.md](config.md) | -| `console` | `call` | [console.md](console.md) | -| `file` | `upload` | [file.md](file.md) | -| `knowledge` | `chat`, `retrieve`, `search` | [knowledge.md](knowledge.md) | -| `mcp` | `call`, `list`, `tools` | [mcp.md](mcp.md) | -| `memory` | `add`, `delete`, `list`, `profile create`, `profile get`, `search`, `update` | [memory.md](memory.md) | -| `model` | `list` | [model.md](model.md) | -| `pipeline` | `run`, `validate` | [pipeline.md](pipeline.md) | -| `plugin` | `install`, `link`, `list`, `remove` | [plugin.md](plugin.md) | -| `quota` | `check`, `history`, `list`, `request` | [quota.md](quota.md) | -| `search` | `web` | [search.md](search.md) | -| `skill` | `add`, `init`, `list`, `remove`, `update` | [skill.md](skill.md) | -| `text` | `chat` | [text.md](text.md) | -| `token-plan` | `add-member`, `assign-seats`, `create-key`, `list-seats` | [token-plan.md](token-plan.md) | -| `update` | `(root)` | [update.md](update.md) | -| `usage` | `free`, `freetier`, `stats`, `summary` | [usage.md](usage.md) | -| `workspace` | `init`, `list` | [workspace.md](workspace.md) | +| Group | Commands | Reference | +| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | +| `advisor` | `recommend` | [advisor.md](advisor.md) | +| `app` | `call`, `list` | [app.md](app.md) | +| `auth` | `generate-access-token`, `login`, `logout`, `status` | [auth.md](auth.md) | +| `config` | `agent`, `list`, `set`, `show`, `ui`, `use` | [config.md](config.md) | +| `console` | `call` | [console.md](console.md) | +| `file` | `upload` | [file.md](file.md) | +| `knowledge` | `chat`, `retrieve`, `search` | [knowledge.md](knowledge.md) | +| `mcp` | `call`, `list`, `tools` | [mcp.md](mcp.md) | +| `memory` | `add`, `delete`, `list`, `profile create`, `profile delete`, `profile detail`, `profile get`, `profile list`, `profile update`, `search`, `update` | [memory.md](memory.md) | +| `model` | `list` | [model.md](model.md) | +| `pipeline` | `run`, `validate` | [pipeline.md](pipeline.md) | +| `plugin` | `install`, `link`, `list`, `remove` | [plugin.md](plugin.md) | +| `quota` | `check`, `history`, `list`, `request` | [quota.md](quota.md) | +| `search` | `web` | [search.md](search.md) | +| `skill` | `add`, `init`, `list`, `remove`, `update` | [skill.md](skill.md) | +| `text` | `chat` | [text.md](text.md) | +| `token-plan` | `add-member`, `assign-seats`, `create-key`, `list-seats` | [token-plan.md](token-plan.md) | +| `update` | `(root)` | [update.md](update.md) | +| `usage` | `free`, `freetier`, `stats`, `summary` | [usage.md](usage.md) | +| `workspace` | `init`, `list` | [workspace.md](workspace.md) | ## Global flags diff --git a/skills/bailian-cli/reference/memory.md b/skills/bailian-cli/reference/memory.md index 91431cb6..dc537f2f 100644 --- a/skills/bailian-cli/reference/memory.md +++ b/skills/bailian-cli/reference/memory.md @@ -7,15 +7,19 @@ Index: [index.md](index.md) ## Commands in this group -| Command | Description | -| -------------------------- | ------------------------------------------------- | -| `bl memory add` | Add memory from messages or custom content | -| `bl memory delete` | Delete a memory node | -| `bl memory list` | List memory nodes for a user | -| `bl memory profile create` | Create a user profile schema for memory profiling | -| `bl memory profile get` | Get user profile by schema ID and user ID | -| `bl memory search` | Search memory nodes by query or messages | -| `bl memory update` | Update a memory node content | +| Command | Description | +| -------------------------- | ---------------------------------------------------------- | +| `bl memory add` | Add memory from messages or custom content | +| `bl memory delete` | Delete a memory node | +| `bl memory list` | List memory nodes for a user | +| `bl memory profile create` | Create a user profile schema for memory profiling | +| `bl memory profile delete` | Delete a profile schema | +| `bl memory profile detail` | Show a profile schema and its attribute IDs | +| `bl memory profile get` | Get user profile by schema ID and user ID | +| `bl memory profile list` | List profile schemas | +| `bl memory profile update` | Update a profile schema's name, description, or attributes | +| `bl memory search` | Search memory nodes by query or messages | +| `bl memory update` | Update a memory node content | ## Command details @@ -29,15 +33,17 @@ Index: [index.md](index.md) #### Flags -| Flag | Type | Required | Description | -| -------------------------- | ------ | -------- | ---------------------------------------------------------- | -| `--user-id ` | string | yes | User ID (required) | -| `--messages ` | string | no | Messages JSON array: [{"role":"user","content":"..."},...] | -| `--content ` | string | no | Custom content text to memorize | -| `--profile-schema ` | string | no | Profile schema ID for user profiling | -| `--memory-library-id ` | string | no | Memory library ID (isolate memory space) | -| `--api-key ` | string | no | API key | -| `--base-url ` | string | no | API base URL | +| Flag | Type | Required | Description | +| -------------------------- | ------ | -------- | ------------------------------------------------------------------ | +| `--user-id ` | string | yes | User ID (required) | +| `--messages ` | string | no | Messages JSON array: [{"role":"user","content":"..."},...] | +| `--content ` | string | no | Custom content text to memorize | +| `--profile-schema ` | string | no | Profile schema ID for user profiling | +| `--memory-library-id ` | string | no | Memory library ID (isolate memory space) | +| `--project-id ` | string | no | Memory extraction rule ID (defaults to the library's default rule) | +| `--meta-data ` | string | no | Custom metadata JSON object: {"location":"Beijing"} | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | #### Examples @@ -53,6 +59,10 @@ bl memory add --user-id user1 --messages '[{"role":"user","content":"I like trav bl memory add --user-id user1 --content "Lives in Beijing" --profile-schema schema_xxx ``` +```bash +bl memory add --user-id user1 --content "Lives in Beijing" --meta-data '{"source":"onboarding"}' +``` + ### `bl memory delete` | Field | Value | @@ -87,14 +97,15 @@ bl memory delete --node-id node_xxx --user-id user1 #### Flags -| Flag | Type | Required | Description | -| -------------------------- | ------ | -------- | ------------------------------ | -| `--user-id ` | string | yes | User ID (required) | -| `--page-size ` | number | no | Results per page (default: 10) | -| `--page ` | number | no | Page number (default: 1) | -| `--memory-library-id ` | string | no | Memory library ID | -| `--api-key ` | string | no | API key | -| `--base-url ` | string | no | API base URL | +| Flag | Type | Required | Description | +| -------------------------- | ------ | -------- | ------------------------------------------------------------------ | +| `--user-id ` | string | yes | User ID (required) | +| `--page-size ` | number | no | Results per page (default: 10) | +| `--page ` | number | no | Page number (default: 1) | +| `--memory-library-id ` | string | no | Memory library ID | +| `--project-id ` | string | no | Memory extraction rule ID (defaults to the library's default rule) | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | #### Examples @@ -130,6 +141,52 @@ bl memory list --user-id user1 --page-size 20 --page 2 bl memory profile create --name "user_basic" --attributes '[{"name":"age","description":"age"},{"name":"hobby","description":"hobby"}]' ``` +### `bl memory profile delete` + +| Field | Value | +| --------------- | --------------------------------------------------- | +| **Name** | `memory profile delete` | +| **Description** | Delete a profile schema | +| **Usage** | `bl memory profile delete --schema-id [flags]` | + +#### Flags + +| Flag | Type | Required | Description | +| -------------------------- | ------ | -------- | ---------------------------- | +| `--schema-id ` | string | yes | Profile schema ID (required) | +| `--memory-library-id ` | string | no | Memory library ID | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | + +#### Examples + +```bash +bl memory profile delete --schema-id schema_xxx +``` + +### `bl memory profile detail` + +| Field | Value | +| --------------- | --------------------------------------------------- | +| **Name** | `memory profile detail` | +| **Description** | Show a profile schema and its attribute IDs | +| **Usage** | `bl memory profile detail --schema-id [flags]` | + +#### Flags + +| Flag | Type | Required | Description | +| -------------------------- | ------ | -------- | ---------------------------- | +| `--schema-id ` | string | yes | Profile schema ID (required) | +| `--memory-library-id ` | string | no | Memory library ID | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | + +#### Examples + +```bash +bl memory profile detail --schema-id schema_xxx +``` + ### `bl memory profile get` | Field | Value | @@ -153,6 +210,72 @@ bl memory profile create --name "user_basic" --attributes '[{"name":"age","descr bl memory profile get --schema-id schema_xxx --user-id user1 ``` +### `bl memory profile list` + +| Field | Value | +| --------------- | -------------------------------- | +| **Name** | `memory profile list` | +| **Description** | List profile schemas | +| **Usage** | `bl memory profile list [flags]` | + +#### Flags + +| Flag | Type | Required | Description | +| -------------------------- | ------ | -------- | ------------------------------ | +| `--memory-library-id ` | string | no | Memory library ID | +| `--page-size ` | number | no | Results per page (default: 10) | +| `--page ` | number | no | Page number (default: 1) | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | + +#### Examples + +```bash +bl memory profile list +``` + +```bash +bl memory profile list --page-size 20 --page 2 +``` + +### `bl memory profile update` + +| Field | Value | +| --------------- | -------------------------------------------------------------------------------------------- | +| **Name** | `memory profile update` | +| **Description** | Update a profile schema's name, description, or attributes | +| **Usage** | `bl memory profile update --schema-id [--name ] [--attribute-ops ] [flags]` | + +#### Flags + +| Flag | Type | Required | Description | +| -------------------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------- | +| `--schema-id ` | string | yes | Profile schema ID (required) | +| `--name ` | string | no | New schema name | +| `--description ` | string | no | New schema description | +| `--attribute-ops ` | string | no | Attribute operations JSON array: [{"op":"add","name":"plan"},{"op":"delete","attribute_id":"attr_1"}] | +| `--memory-library-id ` | string | no | Memory library ID | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | + +#### Notes + +- Attribute IDs for update/delete operations come from `memory profile detail`. + +#### Examples + +```bash +bl memory profile update --schema-id schema_xxx --name "user_basic_v2" +``` + +```bash +bl memory profile update --schema-id schema_xxx --attribute-ops '[{"op":"add","name":"plan","description":"subscription plan"}]' +``` + +```bash +bl memory profile update --schema-id schema_xxx --attribute-ops '[{"op":"delete","attribute_id":"attr_1"}]' +``` + ### `bl memory search` | Field | Value | @@ -163,15 +286,21 @@ bl memory profile get --schema-id schema_xxx --user-id user1 #### Flags -| Flag | Type | Required | Description | -| -------------------------- | ------ | -------- | -------------------------------------------- | -| `--user-id ` | string | yes | User ID (required) | -| `--query ` | string | no | Search query text | -| `--messages ` | string | no | Messages JSON array for context-based search | -| `--top-k ` | number | no | Number of results to return (default: 10) | -| `--memory-library-id ` | string | no | Memory library ID | -| `--api-key ` | string | no | API key | -| `--base-url ` | string | no | API base URL | +| Flag | Type | Required | Description | +| ---------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------- | +| `--user-id ` | string | yes | User ID (required) | +| `--query ` | string | no | Search query text | +| `--messages ` | string | no | Messages JSON array for context-based search | +| `--top-k ` | number | no | Number of results to return (default: 10) | +| `--memory-library-id ` | string | no | Memory library ID | +| `--project-ids ` | array | no | Memory extraction rule ID for hybrid retrieval (repeatable) | +| `--min-score ` | number | no | Minimum similarity score, 0-1 (default: 0.3) | +| `--enable-rerank ` | boolean | no | Rerank results. Also selects the billing tier: false bills lite, true bills pro (~50x). (default: true) | +| `--plan-version ` | string | no | Documented billing tier. The service currently honors --enable-rerank instead, so prefer that flag | +| `--enable-judge ` | boolean | no | Enable the intent-discrimination callback (default: false) | +| `--enable-rewrite ` | boolean | no | Enable query rewriting (default: false) | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | #### Examples @@ -183,6 +312,10 @@ bl memory search --user-id user1 --query "programming preferences" bl memory search --user-id user1 --messages '[{"role":"user","content":"recommend a book"}]' --top-k 5 ``` +```bash +bl memory search --user-id user1 --query "preferences" --enable-rerank false --min-score 0.5 +``` + ### `bl memory update` | Field | Value | @@ -193,14 +326,16 @@ bl memory search --user-id user1 --messages '[{"role":"user","content":"recommen #### Flags -| Flag | Type | Required | Description | -| -------------------------- | ------ | -------- | ------------------------------------------ | -| `--node-id ` | string | yes | Memory node ID (required) | -| `--user-id ` | string | yes | User ID (required) | -| `--content ` | string | yes | New content for the memory node (required) | -| `--memory-library-id ` | string | no | Memory library ID (non-default library) | -| `--api-key ` | string | no | API key | -| `--base-url ` | string | no | API base URL | +| Flag | Type | Required | Description | +| ---------------------------- | ------ | -------- | ---------------------------------------------------------------------- | +| `--node-id ` | string | yes | Memory node ID (required) | +| `--user-id ` | string | yes | User ID (required) | +| `--content ` | string | yes | New content for the memory node (required) | +| `--memory-library-id ` | string | no | Memory library ID (non-default library) | +| `--timestamp ` | number | no | When the remembered event happened (default: now) | +| `--meta-data ` | string | no | Custom metadata JSON object, merged incrementally: {"source":"manual"} | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | #### Examples From f919ebae3c6c41ab406f313803ad9da5f17599af Mon Sep 17 00:00:00 2001 From: "lisheng.lisheng" Date: Sat, 15 Aug 2026 10:29:24 +0800 Subject: [PATCH 2/4] feat(dsh): remote managed-agent as on-demand tool + bl managed-agent run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework the managed-agent integration so a dsh user can, in plain language, have a Bailian cloud agent created and run a task — no hand-written agents.yaml, no prior apply. New `bl managed-agent run --prompt [--instructions] [--model] [--agent]`: one step that idempotently materializes a cloud agent + its environment, then opens a session and streams the result. It mirrors the OpenAgentPack webui backend's ensure+run recipe (resolveProjectConfigFrom Object → syncAgentResourcesWithStateBackend → readProjectRuntime + startSessionRun) from an in-memory config, reusing the existing credential spine in _engine/credentials.ts. State persists under the bl config dir (~/.bailian/managed-agent//), never the user's cwd, so repeat runs with the same --agent reuse the materialized agent. Unlike apply it provisions without --yes, since running is the intent. dsh side: replace the SubagentProvider with a plain tool `bailian_run_remote_task` (packages/dsh/src/tool-managed-agent). The subagent seam did not fit: in the web profile every tool-subagent row is disabled in the host plane (delegation lives in agent presets), a provider fixes one agent identity in config, and the default numeric maxDepth would fail-mount a no-depthLimit provider. As a tool the model calls it directly and fills `instructions` from the user's intent, so the remote agent's role is defined per task. Enabled by default — it creates nothing at load, only on invocation. LLM row: configure the base bundle's existing llm-pi-ai row instead of mounting a second pi-ai instance (a second instance re-declares pi-ai's global configurable-provider catalog and fails boot on a duplicate amazon-bedrock). TokenPlan reads a dedicated BAILIAN_TOKENPLAN_API_KEY, not DASHSCOPE_API_KEY: TokenPlan (sk-sp-) and pay-as-you-go (sk-ws-) keys 401 each other's endpoints, so sharing one var would silently break whichever plugin lost. Note: the ensure+run happy path could not be verified end-to-end on the available account — agentstudio returns 404 there, and the existing `managed-agent apply` 404s identically against the same endpoint/key, so the failure is account/service provisioning, not this change. Command wiring, dry-run, config assembly, credential injection and URL construction were all verified. Co-Authored-By: Claude --- packages/cli/src/commands.ts | 2 + .../managed-agent/_engine/inline-runtime.ts | 122 +++++++++++ .../src/commands/managed-agent/run.ts | 137 ++++++++++++ packages/commands/src/index.ts | 1 + packages/commands/tests/e2e/topic-routes.ts | 1 + packages/dsh/README.md | 69 +++--- packages/dsh/cordis.patch.yml | 12 +- packages/dsh/package.json | 10 +- .../dsh/src/subagent-managed-agent/index.ts | 205 ------------------ packages/dsh/src/tool-managed-agent/index.ts | 131 +++++++++++ packages/dsh/vite.config.ts | 2 +- .../bailian-managed-agent/reference/index.md | 45 ++-- .../reference/managed-agent.md | 76 +++++-- 13 files changed, 519 insertions(+), 294 deletions(-) create mode 100644 packages/commands/src/commands/managed-agent/_engine/inline-runtime.ts create mode 100644 packages/commands/src/commands/managed-agent/run.ts delete mode 100644 packages/dsh/src/subagent-managed-agent/index.ts create mode 100644 packages/dsh/src/tool-managed-agent/index.ts diff --git a/packages/cli/src/commands.ts b/packages/cli/src/commands.ts index b601159a..4027ae66 100644 --- a/packages/cli/src/commands.ts +++ b/packages/cli/src/commands.ts @@ -102,6 +102,7 @@ import { managedAgentValidate, managedAgentPlan, managedAgentApply, + managedAgentRun, managedAgentDestroy, managedAgentStateList, managedAgentStateShow, @@ -225,6 +226,7 @@ export const commands: Record = { "managed-agent validate": managedAgentValidate, "managed-agent plan": managedAgentPlan, "managed-agent apply": managedAgentApply, + "managed-agent run": managedAgentRun, "managed-agent destroy": managedAgentDestroy, "managed-agent state list": managedAgentStateList, "managed-agent state show": managedAgentStateShow, diff --git a/packages/commands/src/commands/managed-agent/_engine/inline-runtime.ts b/packages/commands/src/commands/managed-agent/_engine/inline-runtime.ts new file mode 100644 index 00000000..a892c767 --- /dev/null +++ b/packages/commands/src/commands/managed-agent/_engine/inline-runtime.ts @@ -0,0 +1,122 @@ +import { mkdirSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { + type BackendRuntimeInput, + LocalFileStateBackend, + resolveProjectConfigFromObject, +} from "@openagentpack/sdk"; +import { getConfigDir } from "bailian-cli-core"; +import { + assertProviderCredentials, + type CredentialHost, + injectProviderCredentials, + normalizeInterpolatedProviderBlocks, + prepareProviderEnv, + scrubCredentialEnv, +} from "./credentials.ts"; +import { type HostContext, installSdkTransport } from "./transport.ts"; + +/** Default agent identity `bl managed-agent run` materializes and reuses. */ +export const DEFAULT_INLINE_AGENT = "dsh-remote-runner"; + +/** Default model for the materialized agent. */ +export const DEFAULT_INLINE_MODEL = "qwen3.8-max"; + +/** Default role when the caller supplies no `--instructions`. */ +export const DEFAULT_INLINE_INSTRUCTIONS = "You are a helpful assistant. Complete the task."; + +/** Environment name declared in the inline config; one cloud env per agent. */ +const INLINE_ENVIRONMENT = "cloud"; + +export interface InlineAgentOptions { + agentName: string; + instructions: string; + model: string; + /** Override the persisted state location (defaults under the bl config dir). */ + statePath?: string; +} + +/** + * Slugify an agent name into a filesystem- and project-id-safe token. The state + * for each distinct agent lives in its own directory so repeat runs reuse the + * same materialized remote agent. + */ +function slugify(agentName: string): string { + const slug = agentName + .toLowerCase() + .replace(/[^a-z0-9._-]+/g, "-") + .replace(/^-+|-+$/g, ""); + return slug.length > 0 ? slug : "agent"; +} + +/** Where a materialized agent's state is persisted (not the user's cwd). */ +export function inlineStatePath(agentName: string): string { + return join(getConfigDir(), "managed-agent", slugify(agentName), "state.json"); +} + +/** + * The minimal in-memory project config that materializes into one cloud agent. + * `providers.bailian` carries empty `api_key`/`base_url` placeholders so + * {@link injectProviderCredentials} fills them from bl's auth chain (it only + * writes fields the block already declares). + */ +export function buildInlineConfig(opts: InlineAgentOptions): Record { + return { + version: "1", + providers: { + bailian: { api_key: "", base_url: "" }, + }, + defaults: { provider: "bailian" }, + environments: { + [INLINE_ENVIRONMENT]: { + description: "Bailian CLI cloud environment", + config: { type: "cloud", networking: { type: "unrestricted" } }, + }, + }, + agents: { + [opts.agentName]: { + description: opts.agentName, + model: opts.model, + instructions: opts.instructions, + environment: INLINE_ENVIRONMENT, + provider: "bailian", + }, + }, + }; +} + +/** + * Build the `BackendRuntimeInput` shared by ensure (`syncAgentResourcesWith + * StateBackend`) and run (`readProjectRuntime` + `startSessionRun`). Mirrors the + * credential spine of {@link buildAgentRuntime} but sources config from an + * in-memory object instead of a file, so no `agents.yaml` or `apply` is required. + */ +export async function buildInlineBackendInput( + host: HostContext & CredentialHost, + opts: InlineAgentOptions, +): Promise { + installSdkTransport(host); + prepareProviderEnv(); + + const rawConfig = buildInlineConfig(opts); + const { config, projectName } = await resolveProjectConfigFromObject(rawConfig, { + projectName: slugify(opts.agentName), + }); + + normalizeInterpolatedProviderBlocks(config.providers); + injectProviderCredentials(config.providers, host); + scrubCredentialEnv(); + assertProviderCredentials(config.providers); + + const statePath = opts.statePath ?? inlineStatePath(opts.agentName); + mkdirSync(dirname(statePath), { recursive: true }); + const stateBackend = new LocalFileStateBackend({ statePath }); + + return { + projectName, + config, + stateBackend, + stateScope: { projectId: slugify(opts.agentName) }, + providers: config.providers, + }; +} diff --git a/packages/commands/src/commands/managed-agent/run.ts b/packages/commands/src/commands/managed-agent/run.ts new file mode 100644 index 00000000..5cdfc587 --- /dev/null +++ b/packages/commands/src/commands/managed-agent/run.ts @@ -0,0 +1,137 @@ +import { + BailianError, + defineCommand, + detectOutputFormat, + ExitCode, + type FlagsDef, +} from "bailian-cli-core"; +import { emitResult } from "bailian-cli-runtime"; +import { + readProjectRuntime, + startSessionRun, + startSessionRunPolling, + syncAgentResourcesWithStateBackend, +} from "@openagentpack/sdk"; +import { CREDENTIALS_NOTE } from "./_engine/config-loader.ts"; +import { withStdoutProtected } from "./_engine/console-capture.ts"; +import { withAgentErrors } from "./_engine/errors.ts"; +import { + buildInlineBackendInput, + DEFAULT_INLINE_AGENT, + DEFAULT_INLINE_INSTRUCTIONS, + DEFAULT_INLINE_MODEL, +} from "./_engine/inline-runtime.ts"; +import { renderCollectedEvents, streamAndRenderEvents } from "./_engine/session-render.ts"; + +const RUN_FLAGS = { + prompt: { + type: "string", + valueHint: "", + description: "Task to run (required)", + required: true, + }, + instructions: { + type: "string", + valueHint: "", + description: "Role/system instructions for the remote agent (default: generic assistant)", + }, + model: { + type: "string", + valueHint: "", + description: `Model for the remote agent (default: ${DEFAULT_INLINE_MODEL})`, + }, + agent: { + type: "string", + valueHint: "", + description: `Agent identity to create/reuse (default: ${DEFAULT_INLINE_AGENT})`, + }, + noStream: { + type: "switch", + description: "Use polling instead of SSE streaming", + }, +} satisfies FlagsDef; + +export default defineCommand({ + description: "Provision (if needed) a cloud agent and run a task in one step", + auth: "apiKey", + usageArgs: "--prompt [--instructions ] [--model ] [--agent ]", + flags: RUN_FLAGS, + exampleArgs: [ + '--prompt "Summarize the latest AI news"', + '--prompt "Audit this dependency tree" --instructions "You are a security expert" --model qwen3.8-max', + ], + notes: [ + ...CREDENTIALS_NOTE, + "Unlike `apply`, this creates/updates the cloud agent + environment on demand without --yes. The first run provisions cloud resources (may incur cost and take longer to start); later runs with the same --agent reuse them.", + ], + async run(ctx) { + const { settings, flags } = ctx; + const format = detectOutputFormat(settings.output); + const asJson = format === "json"; + + const agentName = flags.agent ?? DEFAULT_INLINE_AGENT; + const model = flags.model ?? DEFAULT_INLINE_MODEL; + const instructions = flags.instructions ?? DEFAULT_INLINE_INSTRUCTIONS; + + if (settings.dryRun) { + emitResult( + { + would_run: { + prompt: flags.prompt, + agent: agentName, + model, + instructions, + mode: flags.noStream ? "polling" : "streaming", + }, + }, + format, + ); + return; + } + + await withAgentErrors(() => + withStdoutProtected(async () => { + const input = await buildInlineBackendInput(ctx, { agentName, instructions, model }); + + // Ensure the remote agent + its cloud environment exist. Idempotent: + // a repeat run with the same agent name reuses the materialized state. + if (!asJson) process.stderr.write(`Ensuring cloud agent "${agentName}"…\n`); + const sync = await syncAgentResourcesWithStateBackend(input, agentName, { + policy: "force", + quiet: true, + }); + if (sync.status !== "completed") { + const detail = + sync.error ?? + sync.diagnostics.find((diag) => diag.severity === "error")?.message ?? + `provisioning ended with status "${sync.status}"`; + throw new BailianError( + `Failed to provision cloud agent "${agentName}": ${detail}`, + ExitCode.GENERAL, + ); + } + + // Run the task inside a runtime bound to the just-materialized state. + await readProjectRuntime(input, async (runtime) => { + if (flags.noStream) { + const run = await startSessionRunPolling(runtime, flags.prompt, { agent: agentName }); + if (!asJson) process.stderr.write(`Session created: ${run.session.id}\n`); + renderCollectedEvents(run, asJson, { + session_id: run.session.id, + provider: run.provider, + agent: run.agentName, + }); + } else { + const run = await startSessionRun(runtime, flags.prompt, { agent: agentName }); + if (!asJson) process.stderr.write(`Session created: ${run.session.id}\n`); + await streamAndRenderEvents(run.events, asJson, { + session_id: run.session.id, + provider: run.provider, + agent: run.agentName, + }); + } + }); + }), + ); + }, +}); diff --git a/packages/commands/src/index.ts b/packages/commands/src/index.ts index 3c62602b..03418e9f 100644 --- a/packages/commands/src/index.ts +++ b/packages/commands/src/index.ts @@ -99,6 +99,7 @@ export { default as managedAgentInit } from "./commands/managed-agent/init.ts"; export { default as managedAgentValidate } from "./commands/managed-agent/validate.ts"; export { default as managedAgentPlan } from "./commands/managed-agent/plan.ts"; export { default as managedAgentApply } from "./commands/managed-agent/apply.ts"; +export { default as managedAgentRun } from "./commands/managed-agent/run.ts"; export { default as managedAgentDestroy } from "./commands/managed-agent/destroy.ts"; export { default as managedAgentStateList } from "./commands/managed-agent/state-list.ts"; export { default as managedAgentStateShow } from "./commands/managed-agent/state-show.ts"; diff --git a/packages/commands/tests/e2e/topic-routes.ts b/packages/commands/tests/e2e/topic-routes.ts index 9e18bf7b..3e24704c 100644 --- a/packages/commands/tests/e2e/topic-routes.ts +++ b/packages/commands/tests/e2e/topic-routes.ts @@ -177,6 +177,7 @@ export const MANAGED_AGENT_ROUTES: E2eRouteExports = { "managed-agent validate": "managedAgentValidate", "managed-agent plan": "managedAgentPlan", "managed-agent apply": "managedAgentApply", + "managed-agent run": "managedAgentRun", "managed-agent destroy": "managedAgentDestroy", "managed-agent state list": "managedAgentStateList", "managed-agent state rm": "managedAgentStateRm", diff --git a/packages/dsh/README.md b/packages/dsh/README.md index d0908be7..c52dae36 100644 --- a/packages/dsh/README.md +++ b/packages/dsh/README.md @@ -4,23 +4,23 @@ 一个包提供 5 个插件行,外加对 base bundle 的 `llm-pi-ai` 行做一次配置覆盖: -| row id | 能力 | 默认 | 依赖 | -| -------------------------------- | --------------------------------------------------------------- | ---- | --------------------- | -| `llm-pi-ai`(覆盖 base 行) | 把百炼 TokenPlan 网关注册成 LLM provider(`bailian-tokenplan`) | 启用 | TokenPlan Key | -| `bailian-tool-vision` | `bailian_vision_describe`:图片/视频理解 | 启用 | `bl` | -| `bailian-tool-image` | `bailian_image_generate`:文生图 | 启用 | `bl` | -| `bailian-web-search-rag` | 百炼知识库检索,注册为 `web_search` 的后端 | 停用 | 按量付费 Key + 知识库 | -| `bailian-memory` | 跨会话长期记忆(tools + 自动检索/落库) | 停用 | 按量付费 Key | -| `bailian-subagent-managed-agent` | 子 agent 跑在百炼托管运行时 | 停用 | `bl` + `agents.yaml` | +| row id | 能力 | 默认 | 依赖 | +| ---------------------------- | --------------------------------------------------------------- | ---- | --------------------- | +| `llm-pi-ai`(覆盖 base 行) | 把百炼 TokenPlan 网关注册成 LLM provider(`bailian-tokenplan`) | 启用 | TokenPlan Key | +| `bailian-tool-vision` | `bailian_vision_describe`:图片/视频理解 | 启用 | `bl` | +| `bailian-tool-image` | `bailian_image_generate`:文生图 | 启用 | `bl` | +| `bailian-tool-managed-agent` | `bailian_run_remote_task`:按需在云端创建 agent 并跑任务 | 启用 | `bl` + 按量付费 Key | +| `bailian-web-search-rag` | 百炼知识库检索,注册为 `web_search` 的后端 | 停用 | 按量付费 Key + 知识库 | +| `bailian-memory` | 跨会话长期记忆(tools + 自动检索/落库) | 停用 | 按量付费 Key | -后三个默认停用是有意的:它们要么需要部署方特有的资源 ID,要么按次计费,不该在用户没配置时就生效。 +`web-search-rag` 与 `memory` 默认停用是有意的:它们要么需要部署方特有的资源 ID,要么按次计费,不该在用户没配置时就生效。`tool-managed-agent` 默认启用——它加载时不建任何资源,只有模型真正调用时才在云端创建 agent。 --- ## 1. 前置条件 - Node ≥ 22.19(`dsh` 的要求) -- `bl`(vision / image / subagent 三个插件通过子进程调它) +- `bl`(vision / image / 远程任务 三个工具通过子进程调它) ```sh npm install -g bailian-cli @@ -105,7 +105,9 @@ Web UI 在 http://127.0.0.1:3080。 | `deepseek-v4-pro` | 否 | | `deepseek-v4-flash-0731` | 否 | -**两个工具** — `bailian_vision_describe`、`bailian_image_generate`。 +**三个工具** — `bailian_vision_describe`、`bailian_image_generate`、`bailian_run_remote_task`。 + +前两个走 TokenPlan(vision/image)。`bailian_run_remote_task` 见 [§3.1](#31-远程任务-bailian_run_remote_task)——它默认启用但用的是**按量付费 Key + dashscope 端点**,与 TokenPlan 那两个不同。 ### 关于看图,有个坑值得知道 @@ -118,6 +120,24 @@ DeepSeek 那两个模型在 TokenPlan 网关上传图**不报错但也看不见* `bailian_image_generate` 同理:模型能看图时返回内联图片,不能看图时降级为返回落盘路径,你可以接着用 vision 工具读它。文件不会被删除,正是为了这个衔接。 +### 3.1 远程任务(`bailian_run_remote_task`) + +把一个任务甩到百炼云端的托管 agent 上跑,不占本地会话。**无需预先写 `agents.yaml` 或 `apply`**:工具首次被调用时,`bl managed-agent run` 会在你的账号里幂等创建一个 agent + cloud environment,之后复用。 + +- 模型自己按用户意图填 `instructions`(远程 agent 的角色),`task` 是要它做的事。例如你说「在云端帮我审计这个依赖树,它该懂安全」→ 模型调 `bailian_run_remote_task(task="审计依赖树", instructions="你是安全专家")`。 +- **前提**:这条路走的是 managed-agent(agentstudio)服务,需要**按量付费 Key**(`sk-ws-`)+ dashscope 端点,且账号已开通 managed-agent。TokenPlan Key 不适用。若 `DASHSCOPE_API_KEY`/端点没配好,首次调用会返回 `Bailian API 404`。 +- 首次会创建云资源(可能计费、启动有延迟);同名 agent 后续复用。默认 agent 名 `dsh-remote-runner`,可在配置里改。 + +需要非默认的 agent 名 / 模型时: + +```yaml +- id: bailian-tool-managed-agent + config: + agent: my-runner + model: qwen3.8-max + timeoutMs: 600000 +``` + --- ## 4. 开启可选插件 @@ -181,30 +201,7 @@ dsh 自身没有跨会话记忆(`ctx.compaction` 只在单会话内压缩上 autoPersist: false ``` -### 托管子 agent - -把 dsh 的子 agent 派发到百炼云端运行,不占本地资源。 - -先在工作目录准备好清单并应用: - -```sh -bl managed-agent init -bl managed-agent apply --yes -``` - -再开启: - -```yaml -- id: bailian-subagent-managed-agent - disabled: false - config: - file: agents.yaml - agent: assistant - provider: bailian - timeoutMs: 600000 -``` - -两个已知限制:CLI 在会话结束时才一次性输出 JSON,所以**中途没有增量进度**,被取消时也拿不到部分输出;`prepareContinuable` 未实现,即只支持一次性委派,不支持多轮续聊。 +> 远程任务(`bailian_run_remote_task`)默认启用,配置见 [§3.1](#31-远程任务-bailian_run_remote_task)。 --- @@ -226,7 +223,7 @@ bl auth status - **文生图**:让模型生成一张图 - **RAG**:问一个只有知识库里才有答案的问题 - **记忆**:会话 A 告诉它一个事实 → 关掉 → 新开会话 B 提问,看是否命中 -- **子 agent**:派发一个子任务 +- **远程任务**:说「在云端帮我跑一个任务:,它该擅长 」→ 确认模型调用 `bailian_run_remote_task`(`instructions` 由模型按 role 填)→ 首次触发云端创建 → 返回远程会话结果(需按量付费 Key + 已开通 agentstudio) --- diff --git a/packages/dsh/cordis.patch.yml b/packages/dsh/cordis.patch.yml index f36f0ee2..eaca60c0 100644 --- a/packages/dsh/cordis.patch.yml +++ b/packages/dsh/cordis.patch.yml @@ -76,6 +76,12 @@ - id: bailian-tool-image name: bailian-cli-dsh/tool-image + # Enabled by default: the tool creates no resources at load time. It only + # provisions a cloud agent when the model actually calls it, and reuses it + # after — no deployment-specific ID to configure up front. + - id: bailian-tool-managed-agent + name: bailian-cli-dsh/tool-managed-agent + # Disabled by default: the knowledge base to query is deployment-specific, # and an enabled provider with no agentId would make `web_search` ambiguous # for everyone. Set workspaceId + agentId and flip `disabled` to use it. @@ -89,9 +95,3 @@ name: bailian-cli-dsh/memory disabled: true config: {} - - # Disabled by default: requires an applied `agents.yaml` in the workspace. - - id: bailian-subagent-managed-agent - name: bailian-cli-dsh/subagent-managed-agent - disabled: true - config: {} diff --git a/packages/dsh/package.json b/packages/dsh/package.json index f4f1450a..43121443 100644 --- a/packages/dsh/package.json +++ b/packages/dsh/package.json @@ -33,6 +33,10 @@ "types": "./src/tool-image/index.ts", "default": "./src/tool-image/index.ts" }, + "./tool-managed-agent": { + "types": "./src/tool-managed-agent/index.ts", + "default": "./src/tool-managed-agent/index.ts" + }, "./web-search-rag": { "types": "./src/web-search-rag/index.ts", "default": "./src/web-search-rag/index.ts" @@ -41,10 +45,6 @@ "types": "./src/memory/index.ts", "default": "./src/memory/index.ts" }, - "./subagent-managed-agent": { - "types": "./src/subagent-managed-agent/index.ts", - "default": "./src/subagent-managed-agent/index.ts" - }, "./cordis.patch.yml": "./cordis.patch.yml", "./package.json": "./package.json" }, @@ -54,9 +54,9 @@ ".": "./dist/index.mjs", "./tool-vision": "./dist/tool-vision/index.mjs", "./tool-image": "./dist/tool-image/index.mjs", + "./tool-managed-agent": "./dist/tool-managed-agent/index.mjs", "./web-search-rag": "./dist/web-search-rag/index.mjs", "./memory": "./dist/memory/index.mjs", - "./subagent-managed-agent": "./dist/subagent-managed-agent/index.mjs", "./cordis.patch.yml": "./cordis.patch.yml", "./package.json": "./package.json" }, diff --git a/packages/dsh/src/subagent-managed-agent/index.ts b/packages/dsh/src/subagent-managed-agent/index.ts deleted file mode 100644 index bab0a5b2..00000000 --- a/packages/dsh/src/subagent-managed-agent/index.ts +++ /dev/null @@ -1,205 +0,0 @@ -/** - * `bailian-cli-dsh/subagent-managed-agent`: runs child agents on Bailian's - * hosted managed-agent runtime instead of in this process, through - * `bl managed-agent session run`. - * - * Out-of-process delegation is an established shape here — `subagent-acp` and - * `subagent-codex` do the same over their own transports. Going through the - * CLI keeps `agents.yaml` resolution, provider selection, and SSE decoding in - * one place. - * - * Two honest limits. The CLI buffers the whole session and emits it at exit, - * so no incremental progress reaches the parent and a cancelled run yields no - * partial output. And `prepareContinuable` is deliberately absent: method - * presence IS the continuable capability, and multi-turn continuation is not - * wired up yet. - * - * @module bailian-cli-dsh/subagent-managed-agent - */ -import type { Context } from "@deepseek-ai/cordis"; -import type { ContentBlock } from "@deepseek-ai/dsh-llm"; -import { SessionId } from "@deepseek-ai/dsh-session"; -import type { - ResolvedSubagentStartRequest, - SubagentCapabilities, - SubagentProvider, - SubagentResult, - SubagentRun, -} from "@deepseek-ai/dsh-subagent"; -import type {} from "@deepseek-ai/dsh-fs"; -import z from "@deepseek-ai/schemastery"; -import { runBlJson } from "../shared/bl.ts"; - -/** Cordis plugin name used by loader diagnostics. */ -export const name = "bailian-subagent-managed-agent"; - -/** Seams this plugin registers into. */ -export const inject = ["subagents", "subprocess", "fs"]; - -/** Registry name callers select this transport by. */ -export const BAILIAN_MANAGED_AGENT_PROVIDER = "bailian-managed-agent"; - -export interface Config { - /** Manifest passed as `--file`; must already be applied. */ - file?: string; - /** Agent name within the manifest. */ - agent?: string; - /** Backing provider understood by `bl managed-agent`. */ - provider?: string; - /** Cooperative budget for one hosted run. */ - timeoutMs?: number; -} - -export const Config: z = z.object({ - file: z.string().description("Path to agents.yaml; defaults to the CLI's own default."), - agent: z.string().description("Agent name declared in the manifest."), - provider: z.string().description("Managed-agent backing provider."), - timeoutMs: z.natural().description("Cooperative timeout budget in milliseconds."), -}); - -const DEFAULT_MANIFEST = "agents.yaml"; -const DEFAULT_TIMEOUT_MS = 600_000; - -/** A one-shot transport supports none of the start-time features. */ -const CAPABILITIES: SubagentCapabilities = { - outputSchema: false, - depthLimit: false, - toolFilter: false, - persona: false, -}; - -interface SessionEvent { - type?: string; - content?: unknown; - role?: string; -} - -interface SessionRunResponse { - session_id?: string; - events?: readonly SessionEvent[]; -} - -function promptText(blocks: readonly ContentBlock[]): string { - return blocks - .filter((block): block is Extract => block.type === "text") - .map((block) => block.text) - .join("\n") - .trim(); -} - -/** Assistant-visible text of a finished hosted session. */ -function assistantOutput(events: readonly SessionEvent[]): ContentBlock[] { - const text = events - .filter((event) => event.type === "message" && typeof event.content === "string") - .map((event) => event.content as string) - .join("\n") - .trim(); - return text.length > 0 ? [{ type: "text", text }] : []; -} - -function isAbort(error: unknown): boolean { - return error instanceof DOMException && error.name === "AbortError"; -} - -class BailianManagedAgentProvider implements SubagentProvider { - readonly name = BAILIAN_MANAGED_AGENT_PROVIDER; - readonly capabilities = CAPABILITIES; - readonly inheritsParentContext = false; - - constructor( - private readonly ctx: Context, - private readonly config: Config, - ) {} - - async start(request: ResolvedSubagentStartRequest): Promise { - const cwd = request.parent.session.header.cwd ?? process.cwd(); - const manifest = this.config.file ?? DEFAULT_MANIFEST; - - // Pre-publication: a missing manifest is the common misconfiguration and - // deserves a start-time rejection rather than a failed run. - const target = await this.ctx.fs.resolve(manifest, { cwd, signal: request.signal }); - const info = await this.ctx.fs.stat(target, request.signal); - if (info === undefined) { - throw new Error( - `bailian-managed-agent: no manifest at "${target.displayPath}". Create one with ` + - `\`bl managed-agent init\` and apply it with \`bl managed-agent apply --yes\`.`, - ); - } - - const prompt = promptText(request.prompt); - if (prompt.length === 0) { - throw new Error("bailian-managed-agent: the prompt carried no text content."); - } - - const argv = ["managed-agent", "session", "run", "--prompt", prompt, "--file", manifest]; - if (this.config.agent !== undefined) argv.push("--agent", this.config.agent); - if (this.config.provider !== undefined) argv.push("--provider", this.config.provider); - - const controller = new AbortController(); - const abort = (): void => controller.abort(); - request.signal.addEventListener("abort", abort, { once: true }); - - // The seam has no deadline of its own — cancellation arrives only through - // the caller's signal — so the transport owns one, or a wedged hosted - // session never settles. - const deadline = AbortSignal.timeout(this.config.timeoutMs ?? DEFAULT_TIMEOUT_MS); - const combined = AbortSignal.any([controller.signal, deadline]); - - // Ownership transfers on fulfillment, so every later failure settles - // through `result` — which must not reject for child-level problems. - const result = this.execute(argv, cwd, combined, deadline).finally(() => { - request.signal.removeEventListener("abort", abort); - }); - - let disposal: Promise | undefined; - return { - id: SessionId(`bailian-managed-agent:${crypto.randomUUID()}`), - localAgent: undefined, - result, - dispose: (): Promise => { - disposal ??= (async (): Promise => { - controller.abort(); - await result; - })(); - return disposal; - }, - }; - } - - private async execute( - argv: readonly string[], - cwd: string, - signal: AbortSignal, - deadline: AbortSignal, - ): Promise { - try { - const response = await runBlJson(this.ctx, argv, { - cwd, - signal, - graceMs: 10_000, - }); - return { output: assistantOutput(response.events ?? []), stopReason: "completed" }; - } catch (error) { - if (deadline.aborted) { - return { - output: [ - { - type: "text", - text: `the hosted session exceeded ${this.config.timeoutMs ?? DEFAULT_TIMEOUT_MS}ms and was terminated`, - }, - ], - stopReason: "error", - }; - } - // The CLI emits its JSON envelope only at exit, so a cancelled run has - // no partial output to salvage. - if (isAbort(error) || signal.aborted) return { output: [], stopReason: "aborted" }; - const reason = error instanceof Error ? error.message : String(error); - return { output: [{ type: "text", text: reason }], stopReason: "error" }; - } - } -} - -export function apply(ctx: Context, config: Config): void { - ctx.subagents.registerProvider(new BailianManagedAgentProvider(ctx, config)); -} diff --git a/packages/dsh/src/tool-managed-agent/index.ts b/packages/dsh/src/tool-managed-agent/index.ts new file mode 100644 index 00000000..942ac6a8 --- /dev/null +++ b/packages/dsh/src/tool-managed-agent/index.ts @@ -0,0 +1,131 @@ +/** + * `bailian-cli-dsh/tool-managed-agent`: run a task on a Bailian-hosted managed + * agent, provisioned on demand, through `bl managed-agent run`. + * + * A plain tool rather than a `SubagentProvider`: in dsh's `web` profile every + * `tool-subagent` row is disabled in the host plane (delegation tools live in + * agent presets), and a subagent provider fixes one agent identity in config — + * neither fits "the model describes an intent and a remote agent is created for + * it". As a tool the model calls it directly and fills `instructions` from the + * user's intent, so the remote agent's role is defined per task. + * + * The CLI does ensure+run in one step: it materializes (idempotently) a cloud + * agent + environment under the given `agent` name on first use and reuses them + * after, so no `agents.yaml` or prior `apply` is required. First use provisions + * cloud resources — it may incur cost and take longer to start. + * + * @module bailian-cli-dsh/tool-managed-agent + */ +import type { Context } from "@deepseek-ai/cordis"; +import { defineTool } from "@deepseek-ai/dsh-tools"; +import type {} from "@deepseek-ai/dsh-tools"; +import z from "@deepseek-ai/schemastery"; +import { runBlJson } from "../shared/bl.ts"; + +/** Cordis plugin name used by loader diagnostics. */ +export const name = "bailian-tool-managed-agent"; + +/** Seams this plugin registers into. */ +export const inject = ["tools", "subprocess"]; + +/** Default agent identity provisioned and reused across calls. */ +const DEFAULT_AGENT = "dsh-remote-runner"; + +export interface Config { + /** Agent identity to create/reuse; distinct names get distinct remote agents. */ + agent?: string; + /** Model for the remote agent. */ + model?: string; + /** Cooperative budget; first-run provisioning of a cloud environment is slow. */ + timeoutMs?: number; +} + +export const Config: z = z.object({ + agent: z.string().description("Remote agent identity to create/reuse."), + model: z.string().description("Model for the remote agent."), + timeoutMs: z.natural().description("Cooperative timeout budget in milliseconds."), +}); + +const DEFAULT_TIMEOUT_MS = 600_000; + +/** The `bl managed-agent run --output json` envelope: a session-event list. */ +interface SessionRunResponse { + session_id?: string; + agent?: string; + events?: readonly { type?: string; content?: unknown; role?: string }[]; +} + +/** Assistant-visible text of a finished remote session. */ +function assistantText(response: SessionRunResponse): string { + return (response.events ?? []) + .filter((event) => event.type === "message" && typeof event.content === "string") + .map((event) => event.content as string) + .join("\n") + .trim(); +} + +export function apply(ctx: Context, config: Config): void { + ctx.tools.register( + defineTool({ + name: "bailian_run_remote_task", + description: + "Run a task on a Bailian-hosted cloud agent. Use for long-running or isolated work you " + + "want executed remotely rather than in this session. A remote agent is created on demand " + + "(and reused) — describe the role it should play through `instructions`, and the concrete " + + "task through `task`. Returns the remote agent's final answer.", + parameters: { + task: { + type: "string", + required: true, + description: "The concrete task for the remote agent to carry out.", + }, + instructions: { + type: "string", + description: + "Role/system instructions defining what the remote agent is good at. " + + "Defaults to a generic assistant.", + }, + model: { + type: "string", + description: "Override the configured model for this task.", + }, + }, + output: { + schema: { + type: "object", + additionalProperties: false, + properties: { + answer: { type: "string", required: true }, + sessionId: { type: "string", required: true }, + }, + }, + render: (_args, value) => [{ type: "text", text: value.answer }], + }, + timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS, + async execute(args, exec) { + const argv = [ + "managed-agent", + "run", + "--prompt", + args.task, + "--agent", + config.agent ?? DEFAULT_AGENT, + ]; + if (args.instructions !== undefined) argv.push("--instructions", args.instructions); + const model = args.model ?? config.model; + if (model !== undefined) argv.push("--model", model); + + const response = await runBlJson(ctx, argv, { + cwd: exec.agent?.session.header.cwd ?? process.cwd(), + signal: exec.signal, + }); + + const answer = assistantText(response); + if (answer.length === 0) { + throw new Error("the remote agent produced no assistant output."); + } + return { answer, sessionId: response.session_id ?? "" }; + }, + }), + ); +} diff --git a/packages/dsh/vite.config.ts b/packages/dsh/vite.config.ts index 2dd837d3..c7ae8a56 100644 --- a/packages/dsh/vite.config.ts +++ b/packages/dsh/vite.config.ts @@ -8,9 +8,9 @@ export default defineConfig({ "src/index.ts", "src/tool-vision/index.ts", "src/tool-image/index.ts", + "src/tool-managed-agent/index.ts", "src/web-search-rag/index.ts", "src/memory/index.ts", - "src/subagent-managed-agent/index.ts", ], minify: true, dts: { diff --git a/skills/bailian-managed-agent/reference/index.md b/skills/bailian-managed-agent/reference/index.md index 24067d2c..aaf43713 100644 --- a/skills/bailian-managed-agent/reference/index.md +++ b/skills/bailian-managed-agent/reference/index.md @@ -9,31 +9,32 @@ Use this index for the skill-scoped quick index and global flags. ## Quick index -| Command | Description | Detail | -| --------------------------------- | ------------------------------------------------------------- | ------------------------------------ | -| `bl managed-agent apply` | Apply planned changes to create/update/delete agent resources | [managed-agent.md](managed-agent.md) | -| `bl managed-agent destroy` | Destroy all managed agent resources tracked in state | [managed-agent.md](managed-agent.md) | -| `bl managed-agent init` | Create a new agents.yaml template | [managed-agent.md](managed-agent.md) | -| `bl managed-agent plan` | Show what changes would be applied to agent infrastructure | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session create` | Create a new session for an agent | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session delete` | Delete a session | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session events` | List event history for a session | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session get` | Get details of a session | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session list` | List sessions from the provider | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session run` | Create a session, send a message, and stream the response | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session send` | Send a message to an existing session and stream the response | [managed-agent.md](managed-agent.md) | -| `bl managed-agent skill-list` | List skills from the provider's skill catalog | [managed-agent.md](managed-agent.md) | -| `bl managed-agent state import` | Import an existing remote resource into agents state | [managed-agent.md](managed-agent.md) | -| `bl managed-agent state list` | List resources tracked in agents state | [managed-agent.md](managed-agent.md) | -| `bl managed-agent state rm` | Remove a resource from state without destroying it remotely | [managed-agent.md](managed-agent.md) | -| `bl managed-agent state show` | Show details of a resource in agents state | [managed-agent.md](managed-agent.md) | -| `bl managed-agent validate` | Validate an agents.yaml configuration (offline) | [managed-agent.md](managed-agent.md) | +| Command | Description | Detail | +| --------------------------------- | -------------------------------------------------------------- | ------------------------------------ | +| `bl managed-agent apply` | Apply planned changes to create/update/delete agent resources | [managed-agent.md](managed-agent.md) | +| `bl managed-agent destroy` | Destroy all managed agent resources tracked in state | [managed-agent.md](managed-agent.md) | +| `bl managed-agent init` | Create a new agents.yaml template | [managed-agent.md](managed-agent.md) | +| `bl managed-agent plan` | Show what changes would be applied to agent infrastructure | [managed-agent.md](managed-agent.md) | +| `bl managed-agent run` | Provision (if needed) a cloud agent and run a task in one step | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session create` | Create a new session for an agent | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session delete` | Delete a session | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session events` | List event history for a session | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session get` | Get details of a session | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session list` | List sessions from the provider | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session run` | Create a session, send a message, and stream the response | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session send` | Send a message to an existing session and stream the response | [managed-agent.md](managed-agent.md) | +| `bl managed-agent skill-list` | List skills from the provider's skill catalog | [managed-agent.md](managed-agent.md) | +| `bl managed-agent state import` | Import an existing remote resource into agents state | [managed-agent.md](managed-agent.md) | +| `bl managed-agent state list` | List resources tracked in agents state | [managed-agent.md](managed-agent.md) | +| `bl managed-agent state rm` | Remove a resource from state without destroying it remotely | [managed-agent.md](managed-agent.md) | +| `bl managed-agent state show` | Show details of a resource in agents state | [managed-agent.md](managed-agent.md) | +| `bl managed-agent validate` | Validate an agents.yaml configuration (offline) | [managed-agent.md](managed-agent.md) | ## By group -| Group | Commands | Reference | -| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | -| `managed-agent` | `apply`, `destroy`, `init`, `plan`, `session create`, `session delete`, `session events`, `session get`, `session list`, `session run`, `session send`, `skill-list`, `state import`, `state list`, `state rm`, `state show`, `validate` | [managed-agent.md](managed-agent.md) | +| Group | Commands | Reference | +| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | +| `managed-agent` | `apply`, `destroy`, `init`, `plan`, `run`, `session create`, `session delete`, `session events`, `session get`, `session list`, `session run`, `session send`, `skill-list`, `state import`, `state list`, `state rm`, `state show`, `validate` | [managed-agent.md](managed-agent.md) | ## Global flags diff --git a/skills/bailian-managed-agent/reference/managed-agent.md b/skills/bailian-managed-agent/reference/managed-agent.md index db5e29e6..67d52422 100644 --- a/skills/bailian-managed-agent/reference/managed-agent.md +++ b/skills/bailian-managed-agent/reference/managed-agent.md @@ -7,25 +7,26 @@ Index: [index.md](index.md) ## Commands in this group -| Command | Description | -| --------------------------------- | ------------------------------------------------------------- | -| `bl managed-agent apply` | Apply planned changes to create/update/delete agent resources | -| `bl managed-agent destroy` | Destroy all managed agent resources tracked in state | -| `bl managed-agent init` | Create a new agents.yaml template | -| `bl managed-agent plan` | Show what changes would be applied to agent infrastructure | -| `bl managed-agent session create` | Create a new session for an agent | -| `bl managed-agent session delete` | Delete a session | -| `bl managed-agent session events` | List event history for a session | -| `bl managed-agent session get` | Get details of a session | -| `bl managed-agent session list` | List sessions from the provider | -| `bl managed-agent session run` | Create a session, send a message, and stream the response | -| `bl managed-agent session send` | Send a message to an existing session and stream the response | -| `bl managed-agent skill-list` | List skills from the provider's skill catalog | -| `bl managed-agent state import` | Import an existing remote resource into agents state | -| `bl managed-agent state list` | List resources tracked in agents state | -| `bl managed-agent state rm` | Remove a resource from state without destroying it remotely | -| `bl managed-agent state show` | Show details of a resource in agents state | -| `bl managed-agent validate` | Validate an agents.yaml configuration (offline) | +| Command | Description | +| --------------------------------- | -------------------------------------------------------------- | +| `bl managed-agent apply` | Apply planned changes to create/update/delete agent resources | +| `bl managed-agent destroy` | Destroy all managed agent resources tracked in state | +| `bl managed-agent init` | Create a new agents.yaml template | +| `bl managed-agent plan` | Show what changes would be applied to agent infrastructure | +| `bl managed-agent run` | Provision (if needed) a cloud agent and run a task in one step | +| `bl managed-agent session create` | Create a new session for an agent | +| `bl managed-agent session delete` | Delete a session | +| `bl managed-agent session events` | List event history for a session | +| `bl managed-agent session get` | Get details of a session | +| `bl managed-agent session list` | List sessions from the provider | +| `bl managed-agent session run` | Create a session, send a message, and stream the response | +| `bl managed-agent session send` | Send a message to an existing session and stream the response | +| `bl managed-agent skill-list` | List skills from the provider's skill catalog | +| `bl managed-agent state import` | Import an existing remote resource into agents state | +| `bl managed-agent state list` | List resources tracked in agents state | +| `bl managed-agent state rm` | Remove a resource from state without destroying it remotely | +| `bl managed-agent state show` | Show details of a resource in agents state | +| `bl managed-agent validate` | Validate an agents.yaml configuration (offline) | ## Command details @@ -170,6 +171,43 @@ bl managed-agent plan --provider bailian bl managed-agent plan --no-refresh ``` +### `bl managed-agent run` + +| Field | Value | +| --------------- | ---------------------------------------------------------------------------------------------- | +| **Name** | `managed-agent run` | +| **Description** | Provision (if needed) a cloud agent and run a task in one step | +| **Usage** | `bl managed-agent run --prompt [--instructions ] [--model ] [--agent ]` | + +#### Flags + +| Flag | Type | Required | Description | +| ----------------------- | ------ | -------- | -------------------------------------------------------------------------- | +| `--prompt ` | string | yes | Task to run (required) | +| `--instructions ` | string | no | Role/system instructions for the remote agent (default: generic assistant) | +| `--model ` | string | no | Model for the remote agent (default: qwen3.8-max) | +| `--agent ` | string | no | Agent identity to create/reuse (default: dsh-remote-runner) | +| `--no-stream` | switch | no | Use polling instead of SSE streaming | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | + +#### Notes + +- Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. +- Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. +- Unlike `apply`, this creates/updates the cloud agent + environment on demand without --yes. The first run provisions cloud resources (may incur cost and take longer to start); later runs with the same --agent reuse them. + +#### Examples + +```bash +bl managed-agent run --prompt "Summarize the latest AI news" +``` + +```bash +bl managed-agent run --prompt "Audit this dependency tree" --instructions "You are a security expert" --model qwen3.8-max +``` + ### `bl managed-agent session create` | Field | Value | From 50ed680ade89db4cebe8559a319ed7f17bbba0a3 Mon Sep 17 00:00:00 2001 From: "lisheng.lisheng" Date: Sat, 15 Aug 2026 16:50:08 +0800 Subject: [PATCH 3/4] feat: enhance credential handling for managed-agent and memory APIs - Updated README.md to clarify API key usage and access restrictions for TokenPlan and pay-as-you-go keys. - Introduced shared credential validation logic to prevent TokenPlan keys from being used in incompatible contexts. - Enhanced error messaging for credential resolution failures in managed-agent and memory plugins. - Added tests for credential classification and workspace endpoint composition. - Updated documentation to reflect changes in credential handling and workspace-scoped agentstudio endpoint requirements. --- .../managed-agent/_engine/credentials.ts | 50 ++++-- .../managed-agent/_engine/inline-runtime.ts | 10 +- .../commands/tests/credentials-bridge.test.ts | 44 ++++- packages/dsh/README.md | 51 ++++-- packages/dsh/cordis.patch.yml | 15 ++ packages/dsh/src/memory/index.ts | 14 +- packages/dsh/src/shared/credentials.ts | 93 +++++++++++ packages/dsh/src/shared/http.ts | 9 +- packages/dsh/src/tool-managed-agent/index.ts | 156 +++++++++++++++++- packages/dsh/src/web-search-rag/index.ts | 14 +- packages/dsh/tests/credentials.test.ts | 57 +++++++ .../reference/managed-agent.md | 13 ++ 12 files changed, 476 insertions(+), 50 deletions(-) create mode 100644 packages/dsh/src/shared/credentials.ts create mode 100644 packages/dsh/tests/credentials.test.ts diff --git a/packages/commands/src/commands/managed-agent/_engine/credentials.ts b/packages/commands/src/commands/managed-agent/_engine/credentials.ts index cf0212cc..c3ba746a 100644 --- a/packages/commands/src/commands/managed-agent/_engine/credentials.ts +++ b/packages/commands/src/commands/managed-agent/_engine/credentials.ts @@ -50,6 +50,7 @@ export interface CredentialHost { */ export const CREDENTIALS_NOTE = [ "Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile).", + "The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace.", "Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json.", "Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env.", ]; @@ -85,13 +86,19 @@ export function prepareProviderEnv(): void { * the block references them and the interpolated value is empty (a literal in * agents.yaml is respected). * - * `base_url` carries {@link AGENTSTUDIO_API_PATH} because the SDK appends resource - * paths onto it verbatim; a value already ending in the suffix is left as-is. - * It is filled even without a credential — `client.baseUrl` is readable - * credential-less (defaults to the CLI's model-domain base URL) — so offline - * commands (which skip the credential assert) still satisfy the SDK's - * "workspace_id or base_url" schema. With no credential the `api_key` is left - * untouched: online commands reject it via {@link assertProviderCredentials}. + * `base_url` is composed from the workspace when one is known — block + * `workspace_id` (agents.yaml literal or interpolated `${BAILIAN_WORKSPACE_ID}`) + * first, then bl's configured `workspace_id` — because agentstudio is served + * only on the workspace-scoped host; the bare model-domain origin 404s it + * (managed-agents API overview: `https://{workspace_id}.cn-beijing.maas. + * aliyuncs.com/api/v1/agentstudio`, region cn-beijing only). Only with no + * workspace at all does the model-domain origin get {@link AGENTSTUDIO_API_PATH} + * suffixed. A value already ending in the suffix is left as-is. base_url is + * filled even without a credential — `client.baseUrl` is readable + * credential-less — so offline commands (which skip the credential assert) + * still satisfy the SDK's "workspace_id or base_url" schema. With no + * credential the `api_key` is left untouched: online commands reject it via + * {@link assertProviderCredentials}. */ export function injectProviderCredentials( providers: Record, @@ -103,16 +110,27 @@ export function injectProviderCredentials( const cred = host.client.exportApiCredential(); if (cred) block.api_key = cred.token; - if ("base_url" in block && !block.base_url) { - // Defensive normalization: the auth chain already normalizes base_url to - // an origin, but never let a trailing slash produce "//api/v1/agentstudio". - const origin = host.client.baseUrl.replace(/\/+$/, ""); - block.base_url = origin.endsWith(AGENTSTUDIO_API_PATH) - ? origin - : `${origin}${AGENTSTUDIO_API_PATH}`; + if ("workspace_id" in block && !block.workspace_id) { + // agents.yaml interpolation already replaced `${BAILIAN_WORKSPACE_ID}` in + // file-based flows; the inline runtime passes an object config that never + // interpolates, so read the env var here too (prepareProviderEnv + // placeholders it to "" when unset). bl's configured workspace_id is the + // last resort. + block.workspace_id = + process.env.BAILIAN_WORKSPACE_ID?.trim() || host.settings.workspaceId || ""; } - if ("workspace_id" in block && !block.workspace_id && host.settings.workspaceId) { - block.workspace_id = host.settings.workspaceId; + if ("base_url" in block && !block.base_url) { + const workspaceId = typeof block.workspace_id === "string" ? block.workspace_id.trim() : ""; + if (workspaceId) { + block.base_url = `https://${workspaceId}.cn-beijing.maas.aliyuncs.com${AGENTSTUDIO_API_PATH}`; + } else { + // Defensive normalization: the auth chain already normalizes base_url to + // an origin, but never let a trailing slash produce "//api/v1/agentstudio". + const origin = host.client.baseUrl.replace(/\/+$/, ""); + block.base_url = origin.endsWith(AGENTSTUDIO_API_PATH) + ? origin + : `${origin}${AGENTSTUDIO_API_PATH}`; + } } } diff --git a/packages/commands/src/commands/managed-agent/_engine/inline-runtime.ts b/packages/commands/src/commands/managed-agent/_engine/inline-runtime.ts index a892c767..8515a5e2 100644 --- a/packages/commands/src/commands/managed-agent/_engine/inline-runtime.ts +++ b/packages/commands/src/commands/managed-agent/_engine/inline-runtime.ts @@ -56,15 +56,17 @@ export function inlineStatePath(agentName: string): string { /** * The minimal in-memory project config that materializes into one cloud agent. - * `providers.bailian` carries empty `api_key`/`base_url` placeholders so - * {@link injectProviderCredentials} fills them from bl's auth chain (it only - * writes fields the block already declares). + * `providers.bailian` carries empty `api_key`/`base_url`/`workspace_id` + * placeholders so {@link injectProviderCredentials} fills them from bl's auth + * chain and workspace sources (it only writes fields the block already + * declares). `workspace_id` lets injection compose the workspace-scoped + * agentstudio host instead of the model-domain origin. */ export function buildInlineConfig(opts: InlineAgentOptions): Record { return { version: "1", providers: { - bailian: { api_key: "", base_url: "" }, + bailian: { api_key: "", base_url: "", workspace_id: "" }, }, defaults: { provider: "bailian" }, environments: { diff --git a/packages/commands/tests/credentials-bridge.test.ts b/packages/commands/tests/credentials-bridge.test.ts index 3a1fb982..f2bb81d0 100644 --- a/packages/commands/tests/credentials-bridge.test.ts +++ b/packages/commands/tests/credentials-bridge.test.ts @@ -124,7 +124,8 @@ test("inject:已带后缀且尾斜杠的 base_url 去斜杠后原样保留", () expect(providers.bailian.base_url).toBe("https://x.maas.aliyuncs.com/api/v1/agentstudio"); }); -test("inject:workspace_id 引用且为空时用 settings 填充;有字面量则保留", () => { +test("inject:workspace_id 引用且为空时按 env > settings 填充;有字面量则保留", () => { + delete process.env.BAILIAN_WORKSPACE_ID; const empty = { bailian: { api_key: "", workspace_id: "" } }; injectProviderCredentials( empty, @@ -132,6 +133,16 @@ test("inject:workspace_id 引用且为空时用 settings 填充;有字面量则 ); expect(empty.bailian.workspace_id).toBe("ws-settings"); + // 内联运行时(对象配置)不做 ${} 插值,env 变量在此补读。 + process.env.BAILIAN_WORKSPACE_ID = "ws-env"; + const fromEnv = { bailian: { api_key: "", workspace_id: "" } }; + injectProviderCredentials( + fromEnv, + makeHost({ apiCred: bailianCred(), workspaceId: "ws-settings" }), + ); + expect(fromEnv.bailian.workspace_id).toBe("ws-env"); + delete process.env.BAILIAN_WORKSPACE_ID; + const literal = { bailian: { api_key: "", workspace_id: "ws-yaml" } }; injectProviderCredentials( literal, @@ -140,6 +151,37 @@ test("inject:workspace_id 引用且为空时用 settings 填充;有字面量则 expect(literal.bailian.workspace_id).toBe("ws-yaml"); }); +test("inject:workspace 已知时 base_url 拼工作空间主机,而非模型域 origin", () => { + // agents.yaml 字面量 workspace_id + 空 base_url。 + const literal = { bailian: { api_key: "", base_url: "", workspace_id: "ws-yaml" } }; + injectProviderCredentials(literal, makeHost({ apiCred: bailianCred() })); + expect(literal.bailian.base_url).toBe( + "https://ws-yaml.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio", + ); + + // 内联块:workspace_id 由 settings 填充后同样走工作空间主机。 + const inline = { bailian: { api_key: "", base_url: "", workspace_id: "" } }; + injectProviderCredentials( + inline, + makeHost({ apiCred: bailianCred(), workspaceId: "ws-settings" }), + ); + expect(inline.bailian.workspace_id).toBe("ws-settings"); + expect(inline.bailian.base_url).toBe( + "https://ws-settings.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio", + ); + + // 显式 base_url 字面量永远优先于拼装。 + const explicit = { + bailian: { + api_key: "", + base_url: "https://custom.example.com/api/v1/agentstudio", + workspace_id: "ws-yaml", + }, + }; + injectProviderCredentials(explicit, makeHost({ apiCred: bailianCred() })); + expect(explicit.bailian.base_url).toBe("https://custom.example.com/api/v1/agentstudio"); +}); + test("inject:无凭证时 api_key 保持不变,base_url 仍用 client 默认域名补齐(离线/范围外 schema 可用)", () => { const providers = { bailian: { api_key: "", base_url: "" } }; injectProviderCredentials(providers, makeHost({})); diff --git a/packages/dsh/README.md b/packages/dsh/README.md index c52dae36..ced4aef5 100644 --- a/packages/dsh/README.md +++ b/packages/dsh/README.md @@ -28,16 +28,16 @@ - 百炼 API Key。**注意有两类且不可混用**: - | 类型 | 前缀 | 能访问 | 不能访问 | - | --------- | -------- | --------------------------------------- | -------------- | - | TokenPlan | `sk-sp-` | TokenPlan 网关(LLM / vision / 文生图) | 记忆库、知识库 | - | 按量付费 | `sk-ws-` | 记忆库、知识库、DashScope 全量接口 | TokenPlan 网关 | + | 类型 | 前缀 | 能访问 | 不能访问 | + | --------- | -------- | ----------------------------------------------------------- | ------------------------ | + | TokenPlan | `sk-sp-` | TokenPlan 网关(LLM / vision / 文生图) | 记忆库、知识库、远程任务 | + | 按量付费 | `sk-ws-` | 记忆库、知识库、远程任务(agentstudio)、DashScope 全量接口 | TokenPlan 网关 | 两者互相返回 `401 InvalidApiKey`,所以本包用**两个不同的环境变量**,不会互相踩: ```sh export BAILIAN_TOKENPLAN_API_KEY=sk-sp-xxx # 只给 bailian-tokenplan provider - export DASHSCOPE_API_KEY=sk-ws-xxx # 给 bl、memory、RAG + export DASHSCOPE_API_KEY=sk-ws-xxx # 给 bl、memory、RAG、远程任务 ``` 只有一类 Key 也能用,只是能力范围相应缩小。若只有 TokenPlan Key: @@ -48,7 +48,13 @@ export DASHSCOPE_BASE_URL=https://token-plan.cn-beijing.maas.aliyuncs.com ``` - 这样 LLM / vision / 文生图可用,memory 与 RAG 不可用(保持停用即可)。 + 这样 LLM / vision / 文生图可用(后两者经 `bl` 走 TokenPlan 网关);memory 与 RAG 保持停用即可。**远程任务仍可注册**,但它的凭证解析会看出这是 TokenPlan Key / 网关,调用 `bailian_run_remote_task` 时直接给出带修复指引的报错,而不是以前的 `Bailian API 404`。 + + **按量付费 Key 的解析顺序**(memory / RAG / 远程任务三处一致):行内 `config.apiKey` → `$DASHSCOPE_API_KEY`。 + + **远程任务的端点**另有讲究:managed-agent(agentstudio)API **只**在工作空间前缀主机上提供——`https://{workspaceId}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio`(普通 dashscope 主机与 TokenPlan 网关都 404),且 Key 只能访问**自己归属的工作空间**(不匹配时 403 `Endpoint.AccessDenied`)。端点解析顺序:行内 `baseUrl` → `$DASHSCOPE_BASE_URL` → 行内 `workspaceId` → `$BAILIAN_WORKSPACE_ID`(后两者自动拼成工作空间主机)。workspace ID 在百炼控制台右上角的工作空间下拉里看。 + + memory / RAG 是显式开启的插件,Key 缺失或误填 `sk-sp-` 会在启动期报错;远程任务默认启用,为避免拖垮 TokenPlan-only 环境,改为调用时报错。 --- @@ -125,10 +131,12 @@ DeepSeek 那两个模型在 TokenPlan 网关上传图**不报错但也看不见* 把一个任务甩到百炼云端的托管 agent 上跑,不占本地会话。**无需预先写 `agents.yaml` 或 `apply`**:工具首次被调用时,`bl managed-agent run` 会在你的账号里幂等创建一个 agent + cloud environment,之后复用。 - 模型自己按用户意图填 `instructions`(远程 agent 的角色),`task` 是要它做的事。例如你说「在云端帮我审计这个依赖树,它该懂安全」→ 模型调 `bailian_run_remote_task(task="审计依赖树", instructions="你是安全专家")`。 -- **前提**:这条路走的是 managed-agent(agentstudio)服务,需要**按量付费 Key**(`sk-ws-`)+ dashscope 端点,且账号已开通 managed-agent。TokenPlan Key 不适用。若 `DASHSCOPE_API_KEY`/端点没配好,首次调用会返回 `Bailian API 404`。 +- **前提**:这条路走的是 managed-agent(agentstudio)服务,需要**按量付费 Key**(`sk-ws-`)+ **工作空间端点**,且账号已开通 managed-agent。TokenPlan Key 不适用。 +- **凭证解析**:Key 为 `config.apiKey` → `$DASHSCOPE_API_KEY`;端点为 `config.baseUrl` → `$DASHSCOPE_BASE_URL` → `config.workspaceId` → `$BAILIAN_WORKSPACE_ID`(后两者自动拼成 `https://{workspaceId}.cn-beijing.maas.aliyuncs.com`)。凡是解析出来的,都会显式下发给 `bl`,不会落到 `bl` 活动 config profile 的端点上——这正是旧版 `Bailian API 404` 的根因:agentstudio **只**在工作空间前缀主机上提供,TokenPlan 网关与普通 dashscope 主机都 404。 +- **两个高频报错**:`404`=端点不是工作空间主机;`403 Endpoint.AccessDenied`=主机对了但这个 Key 不属于该工作空间。二者都会附带具体修复指引。Key 归属的工作空间在百炼控制台右上角下拉里看。 - 首次会创建云资源(可能计费、启动有延迟);同名 agent 后续复用。默认 agent 名 `dsh-remote-runner`,可在配置里改。 -需要非默认的 agent 名 / 模型时: +需要非默认的 agent 名 / 模型 / 凭证时: ```yaml - id: bailian-tool-managed-agent @@ -136,6 +144,10 @@ DeepSeek 那两个模型在 TokenPlan 网关上传图**不报错但也看不见* agent: my-runner model: qwen3.8-max timeoutMs: 600000 + # 可选凭证(省略则按上面的解析顺序找): + # apiKey: sk-ws-xxxxxxxx + # workspaceId: llm-xxxxxxxx # 推荐:自动拼成工作空间端点 + # baseUrl: https://llm-xxxxxxxx.cn-beijing.maas.aliyuncs.com # 或用完整端点 ``` --- @@ -157,7 +169,7 @@ DeepSeek 那两个模型在 TokenPlan 网关上传图**不报错但也看不见* workspaceId: llm-xxxxxxxx # 百炼控制台工作空间 ID agentId: aid-xxxxxxxx # 知识库"检索服务"ID maxResults: 10 - # apiKey 省略则读 $DASHSCOPE_API_KEY + # apiKey 省略则读 $DASHSCOPE_API_KEY(须为按量付费 sk-ws-;误填 sk-sp- 会在启动期报错) ``` 一个实例对一个知识库(`WebSearchRequest` 只带 `query` / `maxResults`,agentId 只能来自配置)。要多个知识库就插多行不同 `id`。 @@ -229,15 +241,18 @@ bl auth status ## 6. 常见问题 -| 现象 | 原因 | -| -------------------------------------- | ---------------------------------------------------------------------- | -| LLM 路由 `401 InvalidApiKey` | `BAILIAN_TOKENPLAN_API_KEY` 没设,或误填了 `sk-ws-` 的按量付费 Key | -| memory / RAG `401 InvalidApiKey` | `DASHSCOPE_API_KEY` 误填了 `sk-sp-` 的 TokenPlan Key | -| `WEB_PROVIDER_AMBIGUOUS` | 有多个搜索 provider,需在 `web` 行 pin `searchProvider` | -| 粘图报 `MODEL_DOES_NOT_SUPPORT_IMAGES` | 当前模型不支持图片输入,换成上表标"是"的,或改用 vision 工具 | -| 工具报找不到 `bl` | `bl` 不在 PATH:`npm install -g bailian-cli` | -| 改了 patch 但没生效 | `config` 是整体替换,检查是否漏写了原有字段;再用 `--dump-config` 确认 | -| `memoryLibraryId does not exist` | 记忆库 ID 属于另一个账号,与当前 Key 不匹配 | +| 现象 | 原因 | +| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LLM 路由 `401 InvalidApiKey` | `BAILIAN_TOKENPLAN_API_KEY` 没设,或误填了 `sk-ws-` 的按量付费 Key | +| memory / RAG 启动期报 TokenPlan Key | `DASHSCOPE_API_KEY` / `apiKey` 误填了 `sk-sp-` 的 TokenPlan Key | +| 远程任务 `Bailian API 404` | 端点不是工作空间前缀主机(TokenPlan 网关 / 普通 dashscope 主机都不提供 agentstudio);给该行配 `workspaceId`(或 `baseUrl`),或导出 `BAILIAN_WORKSPACE_ID` / `DASHSCOPE_BASE_URL` | +| 远程任务 `403 Endpoint.AccessDenied` | 主机是工作空间主机,但这个 Key 不属于该工作空间;换成 Key 归属工作空间的 ID(控制台右上角下拉),或用属于该工作空间的 Key | +| 远程任务调用即报 TokenPlan 提示 | `$DASHSCOPE_API_KEY` 是 `sk-sp-`;换按量付费 Key 或在行内配 `apiKey` | +| `WEB_PROVIDER_AMBIGUOUS` | 有多个搜索 provider,需在 `web` 行 pin `searchProvider` | +| 粘图报 `MODEL_DOES_NOT_SUPPORT_IMAGES` | 当前模型不支持图片输入,换成上表标"是"的,或改用 vision 工具 | +| 工具报找不到 `bl` | `bl` 不在 PATH:`npm install -g bailian-cli` | +| 改了 patch 但没生效 | `config` 是整体替换,检查是否漏写了原有字段;再用 `--dump-config` 确认 | +| `memoryLibraryId does not exist` | 记忆库 ID 属于另一个账号,与当前 Key 不匹配 | --- diff --git a/packages/dsh/cordis.patch.yml b/packages/dsh/cordis.patch.yml index eaca60c0..0ae0a518 100644 --- a/packages/dsh/cordis.patch.yml +++ b/packages/dsh/cordis.patch.yml @@ -79,18 +79,33 @@ # Enabled by default: the tool creates no resources at load time. It only # provisions a cloud agent when the model actually calls it, and reuses it # after — no deployment-specific ID to configure up front. + # + # Credentials: needs a pay-as-you-go key (sk-ws-), resolved from row config + # `apiKey`, then $DASHSCOPE_API_KEY. The agentstudio API is served only on + # the workspace-scoped host, so the endpoint resolves from row `baseUrl`, + # then $DASHSCOPE_BASE_URL, then row `workspaceId` / $BAILIAN_WORKSPACE_ID + # composed into https://{workspace}.cn-beijing.maas.aliyuncs.com — whatever + # resolves ships to bl explicitly, never leaving the endpoint to bl's + # active-profile base_url (a TokenPlan or bare model-domain origin 404s + # agentstudio). The key must belong to that workspace. A resolved TokenPlan + # key or TokenPlan endpoint rejects at call time with guidance (this row is + # enabled by default and must not break boot for TokenPlan-only setups). - id: bailian-tool-managed-agent name: bailian-cli-dsh/tool-managed-agent # Disabled by default: the knowledge base to query is deployment-specific, # and an enabled provider with no agentId would make `web_search` ambiguous # for everyone. Set workspaceId + agentId and flip `disabled` to use it. + # Key: row config `apiKey`, then $DASHSCOPE_API_KEY (pay-as-you-go sk-ws-; + # a TokenPlan key is rejected at boot). - id: bailian-web-search-rag name: bailian-cli-dsh/web-search-rag disabled: true config: {} # Disabled by default: memory add/search are billed per call. + # Key: row config `apiKey`, then $DASHSCOPE_API_KEY (pay-as-you-go sk-ws-; + # a missing key or a TokenPlan key fails the boot with an actionable message). - id: bailian-memory name: bailian-cli-dsh/memory disabled: true diff --git a/packages/dsh/src/memory/index.ts b/packages/dsh/src/memory/index.ts index 67e98585..5193dc58 100644 --- a/packages/dsh/src/memory/index.ts +++ b/packages/dsh/src/memory/index.ts @@ -26,6 +26,7 @@ import type { ContentBlock, Message } from "@deepseek-ai/dsh-llm"; import { createUserMessage } from "@deepseek-ai/dsh-llm"; import { defineTool } from "@deepseek-ai/dsh-tools"; import z from "@deepseek-ai/schemastery"; +import { isTokenPlanKey, tokenPlanKeyRejection } from "../shared/credentials.ts"; import { dashScopeFetch, resolveApiKey, resolveBaseUrl } from "../shared/http.ts"; /** Cordis plugin name used by loader diagnostics. */ @@ -56,7 +57,12 @@ export interface Config { } export const Config: z = z.object({ - apiKey: z.string().role("secret").description("DashScope key; defaults to $DASHSCOPE_API_KEY."), + apiKey: z + .string() + .role("secret") + .description( + "Pay-as-you-go DashScope key (sk-ws-); defaults to $DASHSCOPE_API_KEY. TokenPlan keys are rejected.", + ), baseUrl: z.string().description("DashScope base URL override."), userId: z.string().description("Memory entity id owning these memories."), memoryLibraryId: z.string().description("Memory library id; defaults to the account default."), @@ -355,9 +361,13 @@ export function apply(ctx: Context, config: Config): void { const apiKey = resolveApiKey(ctx, config.apiKey); if (apiKey === undefined) { throw new Error( - "bailian-memory: no DashScope API key. Set $DASHSCOPE_API_KEY or configure `apiKey`.", + "bailian-memory: no DashScope API key. Set `apiKey` in this row's config or export " + + "$DASHSCOPE_API_KEY (a pay-as-you-go sk-ws- key; the memory API 401s TokenPlan keys).", ); } + if (isTokenPlanKey(apiKey)) { + throw new Error(tokenPlanKeyRejection(name, "the memory API")); + } const client = new MemoryClient( apiKey, resolveBaseUrl(ctx, config.baseUrl), diff --git a/packages/dsh/src/shared/credentials.ts b/packages/dsh/src/shared/credentials.ts new file mode 100644 index 00000000..628fe719 --- /dev/null +++ b/packages/dsh/src/shared/credentials.ts @@ -0,0 +1,93 @@ +/** + * Pure credential classification and pairing shared by the plugins that call + * pay-as-you-go DashScope APIs directly (memory, knowledge base) or through + * `bl managed-agent` (agentstudio). No runtime imports — this module is safe + * to load from tests and its rules are locked by `tests/credentials.test.ts`. + * + * TokenPlan keys (`sk-sp-`) and pay-as-you-go keys (`sk-ws-`) are not + * interchangeable: the TokenPlan gateway 401s a pay-as-you-go key, and the + * service APIs this package calls 401 or 404 a TokenPlan key. The LLM + * provider row keeps its TokenPlan key under a dedicated env name + * (`BAILIAN_TOKENPLAN_API_KEY`); every other plugin needs a pay-as-you-go key + * and rejects a TokenPlan one up front instead of failing at request time. + * + * @module bailian-cli-dsh/shared/credentials + */ + +/** + * Standard DashScope model-domain endpoint. It serves the model APIs plus the + * memory v2 and knowledge indices the plugins call directly — but NOT + * `/api/v1/agentstudio`, which lives on the workspace-scoped host. + */ +export const DASHSCOPE_DEFAULT_BASE_URL = "https://dashscope.aliyuncs.com"; + +/** Key prefix that marks a TokenPlan key (which service APIs reject). */ +export const TOKEN_PLAN_KEY_PREFIX = "sk-sp-"; + +/** Whether a key is shaped like a TokenPlan key (which service APIs reject). */ +export function isTokenPlanKey(apiKey: string): boolean { + return apiKey.startsWith(TOKEN_PLAN_KEY_PREFIX); +} + +/** + * Whether a base URL points at the TokenPlan gateway. That gateway serves the + * model-inference routes only — none of the service APIs this package calls, + * including `/api/v1/agentstudio`, so requests to it 404. + */ +export function isTokenPlanEndpoint(baseUrl: string): boolean { + try { + return new URL(baseUrl).hostname.startsWith("token-plan."); + } catch { + // An unparseable URL fails the request later with its own diagnostics; + // this check only classifies well-formed endpoints. + return false; + } +} + +/** + * The standard error wording every plugin uses when it resolves a TokenPlan + * key, so all three surfaces fail with one recognizable, actionable message. + */ +export function tokenPlanKeyRejection(plugin: string, capability: string): string { + return ( + `${plugin}: the resolved API key is a TokenPlan key (${TOKEN_PLAN_KEY_PREFIX}…), which ` + + `${capability} rejects. Use a pay-as-you-go key (sk-ws-): set \`apiKey\` in this row's ` + + "config or $DASHSCOPE_API_KEY. TokenPlan keys belong on $BAILIAN_TOKENPLAN_API_KEY, " + + "which only the `bailian-tokenplan` LLM provider reads." + ); +} + +/** + * Build the `--api-key` / `--base-url` flags handed to `bl managed-agent run`. + * Each resolved half ships independently: + * + * - A resolved key becomes `--api-key`, overriding bl's auth chain so an + * active TokenPlan profile cannot substitute its own key. + * - A resolved endpoint becomes `--base-url`, overriding the ACTIVE PROFILE's + * base_url — the half that fixes the classic `Bailian API 404`, where a + * TokenPlan (or bare model-domain) origin does not serve + * `/api/v1/agentstudio`. + * + * There is deliberately NO fallback endpoint: agentstudio is only served on + * the workspace-scoped host (see {@link workspaceEndpoint}), and an unknown + * workspace is a configuration gap, not a defaultable value. Unresolved halves + * emit nothing and bl's own auth chain decides them. + */ +export function credentialFlags(apiKey: string | undefined, baseUrl: string | undefined): string[] { + const flags: string[] = []; + if (baseUrl !== undefined && baseUrl.length > 0) flags.push("--base-url", baseUrl); + if (apiKey !== undefined && apiKey.length > 0) flags.push("--api-key", apiKey); + return flags; +} + +/** + * Compose the workspace-scoped agentstudio host for a workspace id. The + * managed-agent API is served only from + * `https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio` + * (bl/the SDK append the resource path onto this origin); the plain + * dashscope origin 404s it, and a key only unlocks its own workspace's host + * (a mismatched one 403s `Endpoint.AccessDenied`). + */ +export function workspaceEndpoint(workspaceId: string): string { + return `https://${workspaceId}.cn-beijing.maas.aliyuncs.com`; +} diff --git a/packages/dsh/src/shared/http.ts b/packages/dsh/src/shared/http.ts index 24fa6e1c..6ee6815c 100644 --- a/packages/dsh/src/shared/http.ts +++ b/packages/dsh/src/shared/http.ts @@ -6,8 +6,9 @@ */ import type { Context } from "@deepseek-ai/cordis"; import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment"; +import { DASHSCOPE_DEFAULT_BASE_URL } from "./credentials.ts"; -export const DASHSCOPE_DEFAULT_BASE_URL = "https://dashscope.aliyuncs.com"; +export { DASHSCOPE_DEFAULT_BASE_URL } from "./credentials.ts"; /** A non-2xx DashScope response, carrying the server's own wording. */ export class DashScopeError extends Error { @@ -22,8 +23,10 @@ export class DashScopeError extends Error { } /** - * Resolve the DashScope key from explicit config, then the launch environment - * (process env, project `.env`, harness-home `.env`). + * Resolve the DashScope key: explicit row config first, then the launch + * environment (process env, project `.env`, harness-home `.env`). Callers + * that get `undefined` decide their own failure mode — opt-in plugins reject + * at boot, the managed-agent tool falls through to bl's own auth chain. */ export function resolveApiKey(ctx: Context, explicit?: string): string | undefined { if (explicit !== undefined && explicit.length > 0) return explicit; diff --git a/packages/dsh/src/tool-managed-agent/index.ts b/packages/dsh/src/tool-managed-agent/index.ts index 942ac6a8..31bcbc63 100644 --- a/packages/dsh/src/tool-managed-agent/index.ts +++ b/packages/dsh/src/tool-managed-agent/index.ts @@ -14,13 +14,34 @@ * after, so no `agents.yaml` or prior `apply` is required. First use provisions * cloud resources — it may incur cost and take longer to start. * + * Credentials: agentstudio is a pay-as-you-go DashScope API served ONLY on the + * workspace-scoped host `https://{workspace}.cn-beijing.maas.aliyuncs.com` + * (the plain dashscope origin and the TokenPlan gateway both 404 it, and a key + * only unlocks its own workspace's host). `bl` resolves the key as + * `--api-key` > `$DASHSCOPE_API_KEY` > the active config profile, but a + * profile's `base_url` is NOT paired with an env-resolved key — an active + * TokenPlan profile therefore aims agentstudio at the TokenPlan gateway. So + * whenever this plugin resolves a key or an endpoint (row config, then launch + * env), it passes them explicitly; see {@link credentialFlags}. Endpoint + * resolution is `baseUrl`, then `$DASHSCOPE_BASE_URL`, then `workspaceId` + * composed into the workspace host (same for `$BAILIAN_WORKSPACE_ID`). With + * nothing resolvable here both halves are left to bl's own auth chain. + * * @module bailian-cli-dsh/tool-managed-agent */ import type { Context } from "@deepseek-ai/cordis"; +import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment"; import { defineTool } from "@deepseek-ai/dsh-tools"; import type {} from "@deepseek-ai/dsh-tools"; import z from "@deepseek-ai/schemastery"; import { runBlJson } from "../shared/bl.ts"; +import { + credentialFlags, + isTokenPlanEndpoint, + isTokenPlanKey, + tokenPlanKeyRejection, + workspaceEndpoint, +} from "../shared/credentials.ts"; /** Cordis plugin name used by loader diagnostics. */ export const name = "bailian-tool-managed-agent"; @@ -36,6 +57,15 @@ export interface Config { agent?: string; /** Model for the remote agent. */ model?: string; + /** Pay-as-you-go DashScope key; defaults to `$DASHSCOPE_API_KEY`. */ + apiKey?: string; + /** + * Workspace id the key belongs to; composed into the agentstudio host. + * Read from the console's top-right workspace switcher. + */ + workspaceId?: string; + /** Full agentstudio origin; wins over `workspaceId`. */ + baseUrl?: string; /** Cooperative budget; first-run provisioning of a cloud environment is slow. */ timeoutMs?: number; } @@ -43,11 +73,54 @@ export interface Config { export const Config: z = z.object({ agent: z.string().description("Remote agent identity to create/reuse."), model: z.string().description("Model for the remote agent."), + apiKey: z + .string() + .role("secret") + .description( + "Pay-as-you-go DashScope key (sk-ws-); defaults to $DASHSCOPE_API_KEY. TokenPlan keys are rejected.", + ), + workspaceId: z + .string() + .description( + "Workspace the key belongs to (console top-right switcher); defaults to $BAILIAN_WORKSPACE_ID. " + + "Composed into https://{workspaceId}.cn-beijing.maas.aliyuncs.com.", + ), + baseUrl: z + .string() + .description( + "Full agentstudio origin; overrides workspaceId. Defaults to $DASHSCOPE_BASE_URL.", + ), timeoutMs: z.natural().description("Cooperative timeout budget in milliseconds."), }); const DEFAULT_TIMEOUT_MS = 600_000; +/** + * Resolve the managed-agent credentials: row config first, then the launch + * environment. Endpoint resolution: `baseUrl` (explicit origin) beats + * `workspaceId` (composed into the workspace-scoped host); env names mirror + * the same split. Agentstudio is only served on the workspace-scoped host, so + * an unresolved endpoint is left unset for bl to resolve (and the failure + * hints below explain the gap when bl cannot either). + */ +function resolveCredentials(ctx: Context, config: Config): { apiKey?: string; baseUrl?: string } { + const launchEnvironment = launchEnvironmentOf(ctx); + const env = (varName: string): string | undefined => { + const value = launchEnvironment.get(varName)?.value; + return value !== undefined && value.length > 0 ? value : undefined; + }; + const apiKey = config.apiKey ?? env("DASHSCOPE_API_KEY"); + const workspaceId = config.workspaceId ?? env("BAILIAN_WORKSPACE_ID"); + const baseUrl = + config.baseUrl ?? + env("DASHSCOPE_BASE_URL") ?? + (workspaceId !== undefined ? workspaceEndpoint(workspaceId) : undefined); + return { + ...(apiKey !== undefined ? { apiKey } : {}), + ...(baseUrl !== undefined ? { baseUrl } : {}), + }; +} + /** The `bl managed-agent run --output json` envelope: a session-event list. */ interface SessionRunResponse { session_id?: string; @@ -65,6 +138,26 @@ function assistantText(response: SessionRunResponse): string { } export function apply(ctx: Context, config: Config): void { + // Resolve credentials at boot so misconfigurations surface as one clear + // message instead of a cryptic 401/404 mid-task. This row is ENABLED BY + // DEFAULT, though, and TokenPlan-only setups legitimately keep + // $DASHSCOPE_API_KEY / $DASHSCOPE_BASE_URL aimed at the TokenPlan gateway + // for the vision/image tools — so a TokenPlan key or endpoint is not a boot + // error here: it becomes a per-call rejection with guidance, and everything + // else keeps working. (Opt-in plugins like bailian-memory reject at boot.) + const credentials = resolveCredentials(ctx, config); + const rejection = + credentials.apiKey !== undefined && isTokenPlanKey(credentials.apiKey) + ? tokenPlanKeyRejection(name, "the managed-agent (agentstudio) API") + : credentials.baseUrl !== undefined && isTokenPlanEndpoint(credentials.baseUrl) + ? `${name}: the resolved endpoint ${credentials.baseUrl} is the TokenPlan gateway, ` + + "which does not serve /api/v1/agentstudio (requests 404). Agentstudio lives on the " + + "workspace-scoped host: set `workspaceId` (the workspace your key belongs to, from " + + "the console's top-right switcher) or `baseUrl` in this row's config, or export " + + "BAILIAN_WORKSPACE_ID / DASHSCOPE_BASE_URL." + : undefined; + const credentialArgv = credentialFlags(credentials.apiKey, credentials.baseUrl); + ctx.tools.register( defineTool({ name: "bailian_run_remote_task", @@ -103,6 +196,7 @@ export function apply(ctx: Context, config: Config): void { }, timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS, async execute(args, exec) { + if (rejection !== undefined) throw new Error(rejection); const argv = [ "managed-agent", "run", @@ -114,11 +208,22 @@ export function apply(ctx: Context, config: Config): void { if (args.instructions !== undefined) argv.push("--instructions", args.instructions); const model = args.model ?? config.model; if (model !== undefined) argv.push("--model", model); + // Atomic credential pair: never let bl pair a key with its active + // profile's base_url (a TokenPlan profile 404s agentstudio). + argv.push(...credentialArgv); - const response = await runBlJson(ctx, argv, { - cwd: exec.agent?.session.header.cwd ?? process.cwd(), - signal: exec.signal, - }); + let response: SessionRunResponse; + try { + response = await runBlJson(ctx, argv, { + cwd: exec.agent?.session.header.cwd ?? process.cwd(), + signal: exec.signal, + }); + } catch (error) { + throw enrichProvisioningError(error, { + fellThroughToBlChain: credentials.apiKey === undefined, + endpointResolved: credentials.baseUrl !== undefined, + }); + } const answer = assistantText(response); if (answer.length === 0) { @@ -129,3 +234,46 @@ export function apply(ctx: Context, config: Config): void { }), ); } + +/** + * Attach an actionable hint to the classic misconfiguration signatures. + * Agentstudio is only served on the workspace-scoped host, and a key only + * unlocks its own workspace, so the three failure modes each get targeted + * guidance: 404 = endpoint is not a workspace host; 403 `Endpoint. + * AccessDenied` = right shape of host but the wrong workspace for this key; + * 401 = TokenPlan key on a pay-as-you-go API. Anything else passes through. + */ +function enrichProvisioningError( + error: unknown, + context: { fellThroughToBlChain: boolean; endpointResolved: boolean }, +): unknown { + if (!(error instanceof Error)) return error; + const message = error.message; + const workspaceHint = + "Agentstudio is served only on the workspace-scoped host " + + "https://{workspaceId}.cn-beijing.maas.aliyuncs.com, and a key only unlocks its own " + + "workspace. Set `workspaceId` (the workspace your key belongs to, from the console's " + + "top-right switcher) or `baseUrl` on the bailian-tool-managed-agent row, or export " + + "BAILIAN_WORKSPACE_ID / DASHSCOPE_BASE_URL."; + + let hint: string | undefined; + if (message.includes("Endpoint.AccessDenied") || message.includes("403")) { + hint = `The host is workspace-scoped but this key belongs to a different workspace. ${workspaceHint}`; + } else if (message.includes("404")) { + hint = context.endpointResolved + ? `The endpoint rejected /api/v1/agentstudio. ${workspaceHint}` + : context.fellThroughToBlChain + ? "No key/endpoint resolved from this row's config or the environment, so bl used its " + + "own auth chain — its active profile endpoint is not the workspace host agentstudio " + + `needs. ${workspaceHint}` + : `The endpoint rejected /api/v1/agentstudio. ${workspaceHint}`; + } else if (message.includes("401")) { + hint = + "The managed-agent API rejected the key. It needs a pay-as-you-go key (sk-ws-); " + + "TokenPlan keys (sk-sp-) only serve the TokenPlan LLM gateway."; + } + + if (hint === undefined) return error; + error.message = `${error.message}\n${hint}`; + return error; +} diff --git a/packages/dsh/src/web-search-rag/index.ts b/packages/dsh/src/web-search-rag/index.ts index 1d312645..d66dc1e5 100644 --- a/packages/dsh/src/web-search-rag/index.ts +++ b/packages/dsh/src/web-search-rag/index.ts @@ -23,6 +23,7 @@ import type { import { WebError } from "@deepseek-ai/dsh-web"; import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment"; import z from "@deepseek-ai/schemastery"; +import { isTokenPlanKey, tokenPlanKeyRejection } from "../shared/credentials.ts"; import { dashScopeFetch, resolveApiKey } from "../shared/http.ts"; /** Cordis plugin name used by loader diagnostics. */ @@ -49,7 +50,9 @@ export const Config: z = z.object({ apiKey: z .string() .role("secret") - .description("DashScope API key; defaults to $DASHSCOPE_API_KEY."), + .description( + "Pay-as-you-go DashScope key (sk-ws-); defaults to $DASHSCOPE_API_KEY. TokenPlan keys are rejected.", + ), workspaceId: z.string().description("Bailian workspace id; defaults to $BAILIAN_WORKSPACE_ID."), agentId: z.string().description("Retrieval service (agent) id identifying the knowledge base."), maxResults: z.natural().description("Default source cap when the caller sets none."), @@ -147,12 +150,19 @@ export class BailianKbSearchProvider implements WebSearchProvider { } export function apply(ctx: Context, config: Config): void { + const apiKey = resolveApiKey(ctx, config.apiKey); + // A TokenPlan key would register a provider that looks available and then 401s + // on every search; reject it at boot instead. An absent key stays soft: + // `available()` returns false and dsh falls back to another provider. + if (apiKey !== undefined && isTokenPlanKey(apiKey)) { + throw new Error(tokenPlanKeyRejection(name, "the knowledge-base API")); + } const workspaceId = config.workspaceId ?? launchEnvironmentOf(ctx).get("BAILIAN_WORKSPACE_ID")?.value ?? ""; ctx.web.registerSearchProvider( new BailianKbSearchProvider({ - apiKey: resolveApiKey(ctx, config.apiKey) ?? "", + apiKey: apiKey ?? "", workspaceId, agentId: config.agentId ?? "", maxResults: config.maxResults ?? DEFAULT_MAX_RESULTS, diff --git a/packages/dsh/tests/credentials.test.ts b/packages/dsh/tests/credentials.test.ts new file mode 100644 index 00000000..acd97b76 --- /dev/null +++ b/packages/dsh/tests/credentials.test.ts @@ -0,0 +1,57 @@ +import { expect, test } from "vite-plus/test"; +import { + credentialFlags, + DASHSCOPE_DEFAULT_BASE_URL, + isTokenPlanEndpoint, + isTokenPlanKey, + workspaceEndpoint, +} from "../src/shared/credentials.ts"; + +// 行为锁定:两类 Key(sk-sp- TokenPlan / sk-ws- 按量付费)不可混用,三个直连服务 +// 模块(memory / RAG / managed-agent)都会拦下 TokenPlan Key,而不是等请求时 +// 拿到难懂的 401/404。managed-agent 的凭证两半独立下发:解析出 key 就显式 +// --api-key(不让 bl 用活动 profile 的 key),解析出端点就显式 --base-url +// (不让 bl 用活动 profile 的端点)。agentstudio 只在工作空间前缀主机上提供, +// 因此绝不存在"默认端点"——工作空间未知就是配置缺口,该报错而不是猜。 + +test("isTokenPlanKey classifies by prefix", () => { + expect(isTokenPlanKey("sk-sp-abc123")).toBe(true); + expect(isTokenPlanKey("sk-ws-abc123")).toBe(false); + expect(isTokenPlanKey("")).toBe(false); +}); + +test("isTokenPlanEndpoint classifies the gateway host", () => { + expect(isTokenPlanEndpoint("https://token-plan.cn-beijing.maas.aliyuncs.com")).toBe(true); + expect( + isTokenPlanEndpoint("https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1"), + ).toBe(true); + expect(isTokenPlanEndpoint(DASHSCOPE_DEFAULT_BASE_URL)).toBe(false); + expect(isTokenPlanEndpoint(workspaceEndpoint("llm-x"))).toBe(false); + // 不可解析的 URL 交给后续请求自己报错,这里只做形状分类。 + expect(isTokenPlanEndpoint("not a url")).toBe(false); +}); + +test("workspaceEndpoint composes the workspace-scoped agentstudio host", () => { + expect(workspaceEndpoint("llm-kpgesh4vqzf5gzv9")).toBe( + "https://llm-kpgesh4vqzf5gzv9.cn-beijing.maas.aliyuncs.com", + ); + expect(workspaceEndpoint("ws_abc")).toBe("https://ws_abc.cn-beijing.maas.aliyuncs.com"); +}); + +test("credentialFlags: each resolved half ships independently, no defaults", () => { + expect(credentialFlags(undefined, undefined)).toEqual([]); + expect(credentialFlags("", "")).toEqual([]); + // 只有 key:端点留给 bl 解析,绝不塞一个会 404 的默认主机。 + expect(credentialFlags("sk-ws-abc", undefined)).toEqual(["--api-key", "sk-ws-abc"]); + // 只有端点:也下发,key 留给 bl 的 auth chain。 + expect(credentialFlags(undefined, "https://ws.example.com")).toEqual([ + "--base-url", + "https://ws.example.com", + ]); + expect(credentialFlags("sk-ws-abc", "https://ws.example.com")).toEqual([ + "--base-url", + "https://ws.example.com", + "--api-key", + "sk-ws-abc", + ]); +}); diff --git a/skills/bailian-managed-agent/reference/managed-agent.md b/skills/bailian-managed-agent/reference/managed-agent.md index 67d52422..1ceabb5b 100644 --- a/skills/bailian-managed-agent/reference/managed-agent.md +++ b/skills/bailian-managed-agent/reference/managed-agent.md @@ -53,6 +53,7 @@ Index: [index.md](index.md) #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. @@ -87,6 +88,7 @@ bl managed-agent apply --provider bailian --yes #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. @@ -153,6 +155,7 @@ bl managed-agent init --provider all #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. - --no-refresh and --dry-run plan offline from local config and state: no remote requests, no state writes, provider keys are not checked. @@ -194,6 +197,7 @@ bl managed-agent plan --no-refresh #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. - Unlike `apply`, this creates/updates the cloud agent + environment on demand without --yes. The first run provisions cloud resources (may incur cost and take longer to start); later runs with the same --agent reuse them. @@ -233,6 +237,7 @@ bl managed-agent run --prompt "Audit this dependency tree" --instructions "You a #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. @@ -271,6 +276,7 @@ bl managed-agent session create --agent assistant --title 'debug run' #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. @@ -303,6 +309,7 @@ bl managed-agent session delete --session-id sess_abc123 #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. @@ -337,6 +344,7 @@ bl managed-agent session events --session-id sess_abc123 --all #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. @@ -368,6 +376,7 @@ bl managed-agent session get --session-id sess_abc123 #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. @@ -412,6 +421,7 @@ bl managed-agent session list --all #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. - --output json emits one envelope: { session_id, provider, agent, events } — read session_id to chain `session send/get/events/delete`. @@ -449,6 +459,7 @@ bl managed-agent session run --agent assistant --prompt "summarize this repo" #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. @@ -479,6 +490,7 @@ bl managed-agent session send --session-id sess_abc123 --message "continue" #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. - Providers without a skill listing API (e.g. ark) return an empty list. @@ -525,6 +537,7 @@ bl managed-agent skill-list --source custom --provider bailian #### Notes - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- The agentstudio endpoint is workspace-scoped: the base URL is composed from the workspace id (agents.yaml workspace_id > $BAILIAN_WORKSPACE_ID > bl's configured workspace_id) as https://{workspace}.cn-beijing.maas.aliyuncs.com/api/v1/agentstudio, and the key must belong to that workspace. - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. From 9ba4a9d1a3649caa00c888dfd904d98b96a5af84 Mon Sep 17 00:00:00 2001 From: "lisheng.lisheng" Date: Sun, 16 Aug 2026 11:23:57 +0800 Subject: [PATCH 4/4] feat(dsh): add Responses-API route for TokenPlan Qwen models and enhance event text handling --- packages/dsh/cordis.patch.yml | 48 ++++++++++++++++++++ packages/dsh/src/tool-managed-agent/index.ts | 31 +++++++++++-- 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/packages/dsh/cordis.patch.yml b/packages/dsh/cordis.patch.yml index 0ae0a518..4d515f8a 100644 --- a/packages/dsh/cordis.patch.yml +++ b/packages/dsh/cordis.patch.yml @@ -69,6 +69,54 @@ compat: thinkingFormat: deepseek + # Responses-API route for the TokenPlan Qwen thinking models: same + # gateway and key as bailian-tokenplan, but OpenAI Responses protocol + # (`/responses`) instead of chat/completions. Reasoning arrives as + # native `reasoning` output items; the gateway's + # `response.reasoning_text.delta` SSE event is one pi-ai's + # openai-responses adapter explicitly consumes. The three models stay + # listed on the completions provider above, so both routes remain + # selectable; delete them there to make Responses the only route. + # + # No `thinkingFormat: qwen` here — that compat maps the completions + # `reasoning_content` field, pi-ai types it only for + # openai-completions, and resolution rejects such switches on this + # protocol. Reasoning effort instead goes through each model's + # `reasoningEfforts`, whose wire spellings land in the gateway's + # `reasoning.effort` request parameter. The four levels below were the + # only ones probed; xhigh/max were not offered to the gateway. + # + # Verified on 2026-08-15 per model against /responses: non-stream and + # stream bodies, one function call, and a colour question about a test + # PNG. qwen3.7-max rejects image content with HTTP 400, so it carries + # no `input: [text, image]`. + bailian-tokenplan-responses: + displayName: Aliyun Bailian TokenPlan (Responses) + api: openai-responses + baseURL: https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1 + apiKeyEnv: BAILIAN_TOKENPLAN_API_KEY + models: + - id: qwen3.8-max + input: [text, image] + reasoningEfforts: + minimal: minimal + low: low + medium: medium + high: high + - id: qwen3.7-plus + input: [text, image] + reasoningEfforts: + minimal: minimal + low: low + medium: medium + high: high + - id: qwen3.7-max + reasoningEfforts: + minimal: minimal + low: low + medium: medium + high: high + - insert: - id: bailian-tool-vision name: bailian-cli-dsh/tool-vision diff --git a/packages/dsh/src/tool-managed-agent/index.ts b/packages/dsh/src/tool-managed-agent/index.ts index 31bcbc63..931c65ff 100644 --- a/packages/dsh/src/tool-managed-agent/index.ts +++ b/packages/dsh/src/tool-managed-agent/index.ts @@ -128,11 +128,36 @@ interface SessionRunResponse { events?: readonly { type?: string; content?: unknown; role?: string }[]; } -/** Assistant-visible text of a finished remote session. */ +/** + * Text of one sanitized envelope event. `bl --output json` emits the SDK's + * sanitized `SessionEvent` shape, where `content` is an ARRAY of content + * blocks (`[{ type: "text", text }]`) — never a plain string — and `type` is + * the provider's raw event type. Tolerate a legacy string `content` too. + */ +function eventText(content: unknown): string { + if (typeof content === "string") return content; + if (!Array.isArray(content)) return ""; + return content + .map((block) => + block !== null && + typeof block === "object" && + typeof (block as { text?: unknown }).text === "string" + ? (block as { text: string }).text + : "", + ) + .join(""); +} + +/** + * Assistant-visible text of a finished remote session. The envelope echoes + * the user prompt as `type: "message", role: "user"`, so keep only non-user + * message events and join their text blocks. + */ function assistantText(response: SessionRunResponse): string { return (response.events ?? []) - .filter((event) => event.type === "message" && typeof event.content === "string") - .map((event) => event.content as string) + .filter((event) => event.type === "message" && event.role !== "user") + .map((event) => eventText(event.content)) + .filter((text) => text.length > 0) .join("\n") .trim(); }