feat(dsh): 新增 bailian-cli-dsh 插件包,并修复 bl memory 与 v2 API 的偏差 - #159
Open
lishengzxc wants to merge 3 commits into
Open
feat(dsh): 新增 bailian-cli-dsh 插件包,并修复 bl memory 与 v2 API 的偏差#159lishengzxc wants to merge 3 commits into
lishengzxc wants to merge 3 commits into
Conversation
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 <noreply@anthropic.com>
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 <task> [--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/<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 <noreply@anthropic.com>
- 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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
DeepSeek Harness(
dsh)是「万物皆插件」的 Cordis 架构 agent harness,暴露了若干真正可插拔的 service seam。本 PR 把百炼的能力接到这些 seam 上,并顺带修掉bl memory与长期记忆 v2 API 之间的偏差。新增
packages/dsh(bailian-cli-dsh)单包 + 6 个 subpath 入口 + 一个
dsh.bundlepatch。默认启用前三项,后三项需要部署方特有的资源 ID 或按次计费,故默认停用。llm-pi-ai(覆盖)bailian-tool-visionbailian_vision_describe(图片/视频)bailian-tool-imagebailian_image_generatebailian-web-search-ragweb_searchbailian-memorybailian-subagent-managed-agent调用方式是混合的:managed-agent 与 image/vision 走
bl子进程(复用它的轮询、下载、SSE、agents.yaml解析),memory 与 RAG 直连 HTTP(v2 API 有一批 CLI 没暴露的参数)。用法见
packages/dsh/README.md。实测得到的三个非显然结论
1. 不能挂第二个 pi-ai 实例。 最初的做法是新起一个 row id 再挂一个
dsh-llm-pi-ai,理由是registerAdapter只在重复 route 时报错。实际启动直接失败:pi-ai 每次 apply 都会把自己内建的整个 provider 目录注册到
ctx.llm.registerConfigurableProviders,而那个目录是全局的。只有 adapter route 是按实例隔离的。所以改成覆盖 base bundle 已有的llm-pi-ai行——它在 base 里是空配置挂载的,整体替换不丢东西。2. 模型清单和视觉能力是逐个探出来的,不是照文档抄的。 TokenPlan 网关
GET /models返回 11 个模型,文档里提到的qwen3-vl-plus并不存在。用一张纯色 PNG 逐个问颜色:qwen3.8-max/qwen3.7-plus/qwen3.6-flash/glm-5.2qwen3.7-maxdeepseek-v4-pro/deepseek-v4-flash-0731DeepSeek 那两个是静默失明。所以它们故意不声明
input: [text, image]——声明了会把「明确拒绝」退化成「静默错答」,更难排查。这也正是bailian_vision_describe存在的理由:它返回文字,绕过 dsh 的模态门禁(api-proxy粘图预检和read_image都在agent/pre-step之前拦截,纯文本路由下图片根本进不了对话)。3.
plan_version是失效的,计费差 50 倍。billing_planplan_version: "lite"enable_rerank: false文档说
plan_version优先级高于enable_rerank,实际单独传 lite 会被忽略。CLI flag 和 memory 插件现在都下发真正生效的那个参数。修复
bl memory(均已线上验证)两处偏差都是 CLI 的 bug,不是文档过时:
profile get是坏的:走/profiles返回HTTP 500 InternalError,正确路径是/user_profileadd的返回字段读错:读response.memory_ids,服务端实际返回memory_nodes,导致文本模式恒打印Memory added. IDs: noneMemoryNode.created_at/updated_at是秒级数字不是字符串;UserProfileResponse.profile的字段名与实际报文完全对不上补齐 v2 API 缺失的面:
--meta-data--project-id--project-ids--min-score--enable-rerank--plan-version--enable-judge--enable-rewrite--timestampmemory profile list|detail|update|delete(v2 的四个 profile-schema 操作原先全缺)memory profile detail会打印attribute_id,那是profile update定位属性的必需键。工程改动
pnpm-workspace.yaml关闭autoInstallPeers:@deepseek-ai/dsh-*的 rc 依赖图 peer 了三个从未发布到 npm 的包(dsh-type-meta/dsh-environment/dsh-tasks),开着的话整个 workspace 装不上。已验证既有包构建不受影响。依赖统一钉
^0.1.0-rc.6—— npm 的latesttag 指向残缺的0.0.1-rc.1线,而0.1.0-rc.6才是与@deepseek-ai/dsh@0.1.0-rc.6配套的版本。验证情况
已真实调用验证
bl vision describe:本地 PNG →content: "Blue",插件的readContent()取的正是该字段profile create/list/detail/get/update/delete+add/search/delete,逐个跑通并清理干净--enable-rerank false→ 响应billing_plan: "lite"vp check0 error(3 个 warning 是既有代码的)pnpm pack产物结构正确未验证
agents.yaml,只做了类型与打包验证memory.e2e.test.ts有 1 个 live 测试失败,原因是它硬编码了别属账号的记忆库 ID(memoryLibraryId does not exist),与本次改动无关;可用BAILIAN_E2E_MEMORY_LIBRARY_ID覆盖待确认
packages/dsh尚未纳入tools/release/lib/packages.mjs的发布清单,目前只能本地pnpm pack安装。是否要纳入发版流程请评审时定。🤖 Generated with Claude Code