feat(dsh): 新增 bailian-cli-dsh(feature catalog + 设置页 + 长期记忆),修复 bl memory 与 v2 API 偏差 - #159
Open
lishengzxc wants to merge 8 commits into
Open
feat(dsh): 新增 bailian-cli-dsh(feature catalog + 设置页 + 长期记忆),修复 bl memory 与 v2 API 偏差#159lishengzxc wants to merge 8 commits into
lishengzxc wants to merge 8 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.
…nce event text handling
- Deleted the `tool-image`, `tool-managed-agent`, `tool-vision`, and `web-search-rag` modules from the codebase. - Updated the Vite configuration to remove entries for the deleted tools and added a new entry for `tokenplan-usage`. - Adjusted tests to reflect the removal of TokenPlan key handling logic from the now-deleted tools.
- Updated build process to include a new script for building the client bundle in ModuleLoader format. - Introduced `build-client.mjs` to handle client-side bundling with esbuild. - Added `client.ts` to implement the DSH web UI, including settings and usage pages. - Registered new settings section for managing credentials and token usage. - Refactored API routes to remove `/api` prefix for consistency. - Cleaned up Vite configuration by removing unused client entry.
…n commands
Add a feature catalog (`packages/dsh/src/features.ts`) that drives two entry
points from one declaration: a model tool per feature (natural-language
entry) and a card-click webServer route (UI entry). Each feature declares
its `bl` argv, optional parameter flags, and a `summarize` projection, so
adding a capability means adding one catalog entry rather than wiring a
tool and a route separately.
New CLI commands backing the TokenPlan usage panel:
- `bl token-plan personal-usage` — 5h/1w usage percentage, subscription
state, and addon credits, unwrapping the console gateway's nested
`data.DataV2.data.data` envelope.
- `bl token-plan personal-key` — the masked personal-edition API key.
Both are `auth: "console"` and registered per the command checklist
(library export, `bl` product map, e2e topic routes, generated reference).
Two type fixes in the tool registration path:
- The parameter map was typed `Record<string, { type: string; ... }>`,
which widens `FeatureParam["type"]` to `string` and is then unassignable
to `ParameterSchemaSpec` (it needs the literal union). Keep the literal.
- `invokeFeature` returned `Promise<unknown>`, so the tool's `{ summary,
data }` value failed `Record<string, JsonValue>`. It parses
`bl --output json` output, so its return type is `JsonValue` — narrowing
the signature is more honest than casting at the call site.
Co-Authored-By: Claude <noreply@anthropic.com>
Clicking a welcome card used to POST /bailian/console and render the raw feature result inline — a dead end: the user saw a summary with no way to follow up, and the agent never learned the question was asked. Now each feature declares a `query` (natural-language phrasing) and the card drops it into the conversation input, then submits. The agent routes it to the matching tool itself, can AskUserQuestion for missing params, and the whole exchange stays in the transcript where the user can ask follow-ups. This removes the inline result panel and its loading state. Drop the `apikey` feature: it only echoed a masked key, which the settings page already shows. `bl token-plan personal-key` stays as a CLI command. Co-Authored-By: Claude <noreply@anthropic.com>
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。本 PR 新增packages/dsh(bailian-cli-dsh),把百炼能力接入 dsh 的 webui 与插件 seam;并顺带修掉bl memory与长期记忆 v2 API 之间的多处偏差。演进中形态收敛过两次:最初做了 6 个独立模型工具(vision / image / managed-agent / RAG / memory / TokenPlan LLM),实测后砍掉——工具太多会污染 tool 列表,多数百炼能力用
bl命令行直接调更顺手。最终收敛为 feature catalog + 设置页 + 长期记忆。交付内容
1. Feature catalog:一份声明,两个入口
packages/dsh/src/features.ts是核心抽象。每个 feature 声明blargv、可选参数 flag、summarize投影、以及一句自然语言query,然后自动获得两个入口:bailian_<id>),模型按intent判断何时调用query填进对话输入框并提交卡片这条路径值得说明:最初实现是点击后直接 POST 后端路由、把结果渲染在卡片下方。那是个死胡同——用户看到一段摘要但无法追问,agent 也完全不知道这个问题被问过。改成投递自然语言后,由 agent 自己路由到对应工具、缺参数时可以
AskUserQuestion,整个交互留在对话记录里可继续追问。加能力只需加一条 catalog 条目,不用分别接工具和路由。
2. Bailian 设置页 + 跨会话长期记忆
bl的dsh专属 profile)+ TokenPlan 用量展示 + 记忆库参数配置dsh 的 host/client 双半模式:
src/tokenplan-usage/index.ts):inject: ['subprocess'],通过bl console call --config dsh调控制台接口src/client.ts→client.bundle.js):声明dsh.client,注册settings.section与conversation.input.docksrc/memory/index.ts):agent/pre-step自动检索注入、agent/turn-stopping自动落库凭证隔离用
--config dsh专属 profile,避免和用户主 profile 的 token 互相踩。用法见
packages/dsh/README.md。3. 客户端 bundle 改为构建产物
dsh 的 web shell 只加载调用
window.__ModuleLoader__.load({ id, factory })的客户端插件,externals(react)通过注入的require解析。而vp pack只产出普通 ESM——格式不对,加载不了。所以客户端单独用 esbuild 构建(CJS + browser platform + react external + ModuleLoader banner/footer),见
scripts/build-client.mjs;build脚本是vp pack && node scripts/build-client.mjs。client.bundle.js早期手写维护(曾因此引入两处语法错误,会让 webui 直接加载失败),现为构建产物并加入.gitignore。4. 新增 CLI 命令
TokenPlan 个人版(支撑设置页用量面板与 feature catalog):
bl token-plan personal-usage— 5 小时/1 周用量百分比、套餐状态、额外用量包 credits;负责解开控制台网关嵌套的data.DataV2.data.data信封bl token-plan personal-key— 个人版 API key(脱敏)managed-agent:
bl managed-agent run— 一步 ensure+run:幂等物化云端 agent + environment,然后开 session 跑任务,无需预先写agents.yaml或apply。照搬 OpenAgentPack webui 后端的配方(resolveProjectConfigFromObject→syncAgentResourcesWithStateBackend→startSessionRun),state 存在~/.bailian/managed-agent/而非用户 cwd均按仓库命令清单完成注册(命令库导出、
bl产品 map、e2e topic routes、生成 reference)。5. 修复
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 操作原先全缺)实测得到的几个非显然结论
1.
plan_version是失效的,计费差 50 倍billing_planplan_version: "lite"enable_rerank: false文档说
plan_version优先级高于enable_rerank,实际单独传 lite 会被忽略。CLI flag 和 memory 插件现在都下发真正生效的那个参数。2. 不能挂第二个 pi-ai 实例
最初想新起一个 row id 再挂一个
dsh-llm-pi-ai,理由是registerAdapter只在重复 route 时报错。实际启动直接失败:pi-ai 每次 apply 都会把内建的整个 provider 目录注册到
ctx.llm.registerConfigurableProviders,而那个目录是全局的。只有 adapter route 按实例隔离。3. TokenPlan 与按量付费 Key 不可混用
TokenPlan(
sk-sp-)和按量付费(sk-ws-)互相 401 对方的端点。所以两者用不同环境变量,不共享DASHSCOPE_API_KEY。4. agentstudio 只在 workspace 专属域提供
https://{workspace}.cn-beijing.maas.aliyuncs.com——dashscope 主域和 TokenPlan 网关都 404。工程改动
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线。验证情况
已真实验证
profile create/list/detail/get/update/delete+add/search/delete逐个真实调用并清理干净--enable-rerank false→ 响应billing_plan: "lite"webprofile:--dump-config退出码 0、无amazon-bedrock报错、行都在vp check0 error(剩 5 个 warning 均为既有代码)pnpm -F bailian-cli-dsh build跑通,client.bundle.js(48.6KB)通过node --check未验证 — webui 相关部分整体未经真实运行
sendQuery对conversation.input的 shell 获取做了多路兼容(inputHub.for(scope)/inputHub.shell(id))并在失败时静默返回 false——这几条分支哪条真正生效未经验证,若都不匹配则卡片点击无反应bl token-plan personal-usage/personal-key:未用真实 console 凭证调通(信封解包逻辑基于接口结构推导)bl managed-agent run成功路径:手上账号 agentstudio 返回 404,且现有managed-agent apply用相同端点/key 同样 404,说明是账号未开通而非本次改动引入agent/pre-step/agent/turn-stopping)未在真实会话中触发待确认
packages/dsh尚未纳入tools/release/lib/packages.mjs发布清单,目前只能本地pnpm pack安装。是否纳入发版流程请评审时定——若纳入,需确保发布流程先跑pnpm build以生成client.bundle.js。🤖 Generated with Claude Code