@doubao-dev/cli 0.0.37 → 0.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/dist/1272.js +3 -12
  2. package/dist/2168~0.js +1 -1
  3. package/dist/4315~0.js +1 -1
  4. package/dist/@inquirer/confirm.js +1 -0
  5. package/dist/assets/web-sdk-debugger/assets/framework/doubao-apps-api.template.js +0 -0
  6. package/dist/assets/web-sdk-debugger/assets/framework/doubao-apps-framework.template.js +0 -0
  7. package/dist/assets/web-sdk-debugger/index.html +1 -1
  8. package/dist/assets/web-sdk-debugger/static/js/491.26cad27284.js +1836 -0
  9. package/dist/assets/web-sdk-debugger/static/js/index.cefeab0b95.js +44 -0
  10. package/dist/build.js +2 -2
  11. package/dist/check.js +1 -1
  12. package/dist/dev-config.js +2 -2
  13. package/dist/dev.js +7 -7
  14. package/dist/inquirer.js +1 -1
  15. package/dist/sdk.js +71 -71
  16. package/dist/template-starter/package.json +0 -1
  17. package/package.json +2 -2
  18. package/skills/doubao-agentic-service-development/SKILL.md +2 -0
  19. package/skills/doubao-agentic-service-development/references/frontend/doubao-agentic-service-api/30-/346/227/245/345/216/206.md +141 -0
  20. package/skills/doubao-agentic-service-development/references/frontend/doubao-agentic-service-api/groups.md +1 -1
  21. package/skills/doubao-agentic-service-development/references/frontend/doubao-agentic-service-api/quick-reference.md +2 -1
  22. package/dist/assets/web-sdk-debugger/static/js/13.6b014d5621.js +0 -1836
  23. package/dist/assets/web-sdk-debugger/static/js/index.01a86a6f8b.js +0 -44
  24. package/dist/dist~2.js +0 -2
  25. /package/dist/assets/web-sdk-debugger/static/js/{13.6b014d5621.js.LICENSE.txt → 491.26cad27284.js.LICENSE.txt} +0 -0
package/dist/build.js CHANGED
@@ -1,2 +1,2 @@
1
- import"node:module";import{__webpack_require__ as e}from"./rslib-runtime~0.js";import"./qrcode.js";import"./9652~0.js";import{promises_namespaceObject as t}from"./628~0.js";import{getMiniAppVersionArtifact as o,createPreviewShortLink as r,listMiniAppVersions as i,normalizeAppVersionTag as n}from"./app.js";import{source as a}from"./5610~0.js";import{parsePositiveInteger as s,option_Option as _,command_Command as l,getLastHttpResponseLogId as d}from"./4315~0.js";import{withCliErrorCode as u,CliUsageError as c,runCommand as p,CliError as f}from"./2168~0.js";import{runFrontendBuildCheck as g,resolveProjectAppId as m,uploadArtifacts as b,miniAppDetailUrl as v,miniAppVersionDetailUrl as w}from"./1272.js";import{ora as h}from"./ora.js";var E={};e.r(E),e.d(E,{default:()=>H});let $=e("../../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/index.js");async function D(e,t,o=!1){if(!e.json&&"succeeded"===t.status)try{let i=AbortSignal.timeout(1e4),n=await y(t.app_id,t.version_tag,i),s=String(n?.artifact_version_code??"");if(!s.trim())throw Error("构建产物尚未就绪");let _={app_key:t.app_id,app_version_tag:t.version_tag,artifact_version_code:s,debug_switch:!0},{data:l}=await r(`doubaoapp://debug?debugInfo=${encodeURIComponent(JSON.stringify(_))}`,i);if("string"!=typeof l?.token||!l.token.trim())throw Error("服务端未返回有效 token");let d=await S(`doubaoapp://debug?short_token=${encodeURIComponent(l.token)}`,o);if(!d)return void e.warn("终端宽度不足,请拉宽窗口后重试,或通过版本详情页扫码。");e.log();let u=o?"":a.dim("(无法扫码时加 --qr full)");e.log(`${a.blue.bold(" 豆包扫码预览")}${u}`),e.log(),e.log(d)}catch{e.warn("预览二维码暂不可用,请通过版本详情页扫码。")}}async function S(e,t){let{modules:o}=$.create(e),r=t?(o.size+2)*2:o.size+4;if(process.stdout.columns&&r+2>process.stdout.columns)return;if(!t)return(await $.toString(e,{type:"utf8",margin:2})).split("\n").map(e=>` \x1b[38;2;0;0;0m\x1b[48;2;255;255;255m${e}\x1b[0m`).join("\n");let i=Array.from({length:o.size+2},(e,t)=>t-1);return i.map(e=>{let t=i.map(t=>{let r=t>=0&&e>=0&&t<o.size&&e<o.size&&o.get(e,t);return`\x1b[48;2;${r?"0;0;0":"255;255;255"}m `}).join("");return` ${t}\x1b[0m`}).join("\n")}async function y(e,t,o){for(let r=1;;r++){let{data:n}=await i(e,{page:r,page_size:100},o),a=n?.version_list??[],s=a.find(e=>e.version_tag===t);if(s)return s;if(!a.length||(n?.total===void 0?a.length<100:100*r>=n.total))return}}let A=e("node:fs"),C=e("node:os"),I=e("node:path"),U={queued:"排队中",building:"构建中",succeeded:"成功",failed:"失败",unknown:"未知"},N={1:{name:"PENDING_BUILD",description:"等待云构建开始"},2:{name:"BUILD_STARTED",description:"云构建已开始"},3:{name:"CODE_READY",description:"源码包已就绪"},4:{name:"COMPILING",description:"正在编译前端代码"},5:{name:"COMPILE_SUCCEEDED",description:"编译成功,等待上传或最终打包"},6:{name:"UPLOADING",description:"正在上传构建产物"},7:{name:"BUILD_SUCCEEDED",description:"云构建成功"},8:{name:"BUILD_FAILED",description:"云构建失败"}};function R(e,t){let o=function(e){let t=e.artifact_build_error_info;if(t){var o,r;let i;return o=t,r=e.error_info_file,i=o.error_code||"构建产物失败",r?`${i}; 错误详情已写入 ${r}`:o.error_info?o.error_info:o.error_code?o.error_code:"number"==typeof o.last_status_before_failed?`构建产物在状态 ${o.last_status_before_failed} 后失败`:"构建产物失败"}let i=e.artifact_status;if(8===i){let e=k(i);return`artifact_status=${i} (${e.name})`}}(t);if(o)for(let r of(e.log(a.red(`失败原因: ${o}`)),function(e,t){if(!e)return[];let o=[];if(e.error_code&&o.push(`错误码: ${e.error_code}`),t?(o.push(`错误详情文件: ${t}`),o.push("错误详情:已写入临时文件,可供 Agent 诊断")):e.error_info&&o.push(`错误详情: ${e.error_info}`),"number"==typeof e.last_status_before_failed){let t=k(e.last_status_before_failed);o.push(`失败前状态: ${e.last_status_before_failed} (${t.name})`),o.push(`失败前状态说明: ${t.description}`)}return o}(t.artifact_build_error_info,t.error_info_file)))e.log(r)}function K(e,t){"succeeded"===t.status&&(e.log(),e.log(` 调试前,将手机豆包账号的 UID 加入应用的${a.yellow("「体验白名单」")}`),t.app_detail_url&&e.log(a.dim(` ${t.app_detail_url}#experience-whitelist`)),e.log(),t.version_detail_url&&(e.log(" 版本详情"),e.log(a.dim(` ${t.version_detail_url}`))),e.log())}async function O(e,t,r){var i,n,a,s;let _,l,u,c=await o(e,t),p=c.data,f=k(p?.artifact_status),g=(i=p,8===(_=i?.artifact_status)||i?.artifact_build_error_info?"failed":7===_?"succeeded":1===_?"queued":"number"==typeof _&&_>=2&&_<=6?"building":"unknown"),m="failed"===g&&p?.artifact_build_error_info?.error_info?(n=e,a=p?.version_tag||t,s=p.artifact_build_error_info.error_info,l=(0,I.join)((0,C.tmpdir)(),"dbx-artifact-build-errors"),(0,A.mkdirSync)(l,{recursive:!0}),u=(0,I.join)(l,`${P(n)}-${P(a)}-${Date.now()}-${process.pid}.log`),(0,A.writeFileSync)(u,s.endsWith("\n")?s:`${s}
2
- `,"utf8"),u):void 0,b=p?.artifact_build_error_info?function(e,t){if(!t)return e;let{error_info:o,...r}=e;return r}(p.artifact_build_error_info,!!m):void 0;return{app_id:e,version_tag:p?.version_tag||t,artifact_status:p?.artifact_status,artifact_status_name:f.name,artifact_status_description:f.description,status:g,...b?{artifact_build_error_info:b}:{},...m?{error_info_file:m}:{},attempt:r,..."succeeded"===g?{version_detail_url:w(e,p?.version_tag||t),app_detail_url:v(e),doubao_debug_conversation_url:"https://inhouse.doubao.com/bot/2xgttdEs"}:{},log_id:c.log_id??d()??""}}async function j(e,o,r,i=5,n=O){let a=Date.now(),s=0,_=await n(e,o,s);for(;"succeeded"!==_.status&&"failed"!==_.status;){if(Date.now()-a>=1e3*r){var l;throw function(e,t,o="DBX_BUILD_FAILED"){return new f(e,{code:o,details:t,logId:d()})}("轮询构建产物状态超时",{...l=_,status:"succeeded"===l.status?"success":"queued"===l.status||"unknown"===l.status&&"number"==typeof l.artifact_status?"building":l.status},"DBX_WAIT_TIMEOUT")}await (0,t.setTimeout)(1e3*i),s+=1,_=await n(e,o,s)}return _}function k(e){return"number"!=typeof e?{name:"UNKNOWN",description:"服务端未返回构建产物状态"}:N[e]??{name:"UNKNOWN",description:`无法识别的构建产物状态:${e}`}}function P(e){return e.trim().replace(/[^a-zA-Z0-9._-]+/g,"_")||"unknown"}async function L(e,t,o=b,r=j){let i=m(t.project);e.targetAppId=i;let n=e.json?void 0:h("正在校验配置并准备构建...").start(),a=await u("DBX_UPLOAD_FAILED",()=>o(e,{appId:i,project:t.project,release:!!t.release,appVersionTag:"string"==typeof t.release?t.release:void 0,quiet:!0,env:t.env,secretEnv:t.secretEnv})).finally(()=>n?.stop()),s=a.version_tag;if(!s)throw new f("构建已提交,但平台未返回版本号,暂时无法查询构建进度",{code:"DBX_UPLOAD_FAILED"});let _={operation:"build",card_check:a.card_check,app_id:i,version_tag:s,version_kind:t.release?"release":"test",state:"queued",terminal:!1,uploaded_artifacts:a.uploaded_artifacts,packages:a.packages,config_sync_results:a.uploaded_artifacts.includes("business_templates")?[{config_type:"business-templates",scope:"app",state:"succeeded",rolled_back_with_version:!1,result:a.business_template_sync_result}]:[],version_detail_url:a.next?.version_detail_url,next_actions:[{purpose:"check_build_status",argv:["dbx","--json","build","status",s,"--project",t.project]}],log_id:a.log_id};if(!t.wait)return q(e,_),_;n?.start("正在等待云端构建...");let l=await u("DBX_REMOTE_ERROR",()=>r(i,s,t.timeoutSeconds)).finally(()=>n?.stop()),d={..._,...B(l),version_detail_url:l.version_detail_url??_.version_detail_url,next_actions:[]};if(q(e,d),R(e,l),await D(e,l,"full"===t.qr),K(e,l),"failed"===d.state)throw new f("云构建失败",{code:"DBX_BUILD_FAILED",details:d,logId:l.log_id});return d}async function M(e,t,o,r=O,i=!1){let n=m(t);e.targetAppId=n;let a=await u("DBX_REMOTE_ERROR",()=>r(n,o,0)),s={operation:"build.status",...B(a)};return q(e,s),R(e,a),await D(e,a,i),K(e,a),s}function x(e){try{let t=n(e);if(t)return t}catch{}throw new c(`正式版本号 ${JSON.stringify(e.trim())} 格式不正确。请使用三段纯数字,例如 1.2.3;不要添加 v 前缀或预发布后缀。`,"DBX_VERSION_TAG_INVALID")}function B(e){let t=e.status;return{app_id:e.app_id,version_tag:e.version_tag,state:t,terminal:"succeeded"===t||"failed"===t,provider_status:e.artifact_status,status_description:e.artifact_status_description,version_detail_url:e.version_detail_url,app_detail_url:e.app_detail_url,doubao_debug_conversation_url:e.doubao_debug_conversation_url,build_error:e.artifact_build_error_info,error_info_file:e.error_info_file,log_id:e.log_id}}function q(e,t){if("succeeded"===t.state)e.log(),e.log(a.green("✓ 构建成功")),e.log(` AppID ${t.app_id}`),e.log(` 版本号 ${t.version_tag}`);else{let o=`构建状态: ${U[t.state]??t.state}`;e.log("failed"===t.state?a.red(o):o),e.log(`AppID: ${t.app_id}`),e.log(`版本号: ${t.version_tag}`)}t.log_id&&(e.verbose||"succeeded"!==t.state)&&e.log("succeeded"===t.state?` ${a.dim("log_id")} ${t.log_id}`:`log_id: ${t.log_id}`),"succeeded"!==t.state&&t.version_detail_url&&e.log(`版本详情: ${t.version_detail_url}`),t.config_sync_results?.length&&e.log(a.dim(" 平台配置已同步(不随版本回滚)"))}function H(){let e=T(new l("build").description("上传并触发云构建")).addOption(new _("--release [version]","构建正式版本,可指定版本号(如 1.2.3)").argParser(x)).option("--no-wait","提交后直接返回,不等待构建完成").option("--env <path>","构建变量文件;真实文件名须以 .env 开头,相对 --project 解析").option("--secret-env <path>","秘密构建变量文件;覆盖 --env 中的同名变量").addOption(new _("--timeout-seconds <seconds>","等待构建的最长时间(秒)").default(300).argParser(s)).addHelpText("after","\n仅本地编译使用 dbx build local;默认构建测试版本,加 --release 构建正式版本,版本号留空时自动生成。\n构建不会自动提审或发布。平台配置会一并同步,不随版本回滚。\n").action(async(e,t)=>p(t,o=>((function(e,t){if(!t.wait&&"cli"===e.getOptionValueSourceWithGlobals("timeoutSeconds"))throw new c("--timeout-seconds 不能与 --no-wait 同时使用")})(t,e),L(o,e))));return e.addCommand(T(new l("status").description("查看构建状态").argument("<version>","版本号")).action(async(e,t,o)=>p(o,t=>{let r=o.optsWithGlobals();return M(t,r.project,e,void 0,"full"===r.qr)}))),e.addCommand(new l("local").description("仅本地编译前端,不上传或触发云构建").option("--project <path>","待编译的前端项目目录(默认当前目录)").option("--env-mode <mode>","加载 .env.[mode] 环境变量").action(async(e,t)=>p(t,async e=>{let o=t.optsWithGlobals();if(["release","wait","env","secretEnv","timeoutSeconds","qr"].some(e=>"cli"===t.getOptionValueSourceWithGlobals(e)))throw new c("local 不能使用云构建选项;环境模式请使用 --env-mode");let r=await g((0,I.resolve)(o.project),{envMode:o.envMode});return e.log(`本地编译完成:${r.cwd}`),{operation:"build_local",...r}}))),e}function T(e){return e.option("--project <path>","项目目录",".").addOption(new _("--qr <mode>","二维码样式(默认 compact;扫码困难时用 full)").choices(["compact","full"]))}export{E as build_namespaceObject};
1
+ import"node:module";import{__webpack_require__ as e}from"./rslib-runtime~0.js";import"./9652~0.js";import"./qrcode.js";import{promises_namespaceObject as t}from"./628~0.js";import{CliUsageError as o,withCliErrorCode as r,runCommand as i,CliError as n}from"./2168~0.js";import{atomicWriteJson as a}from"./json-file.js";import{resolveProjectLayout as s}from"./project-layout.js";import{dist as _}from"./@inquirer/confirm.js";import{dist as l}from"./5343~0.js";import{isRecord as d,parsePositiveInteger as c,option_Option as u,command_Command as p,getLastHttpResponseLogId as f}from"./4315~0.js";import{getMiniAppVersionArtifact as m,createPreviewShortLink as g,listMiniAppVersions as w,normalizeAppVersionTag as b}from"./app.js";import{source as v}from"./5610~0.js";import{runFrontendBuildCheck as h,resolveProjectAppId as S,uploadArtifacts as E,miniAppDetailUrl as $,miniAppVersionDetailUrl as D}from"./1272.js";import{ora as C}from"./ora.js";var y={};e.r(y),e.d(y,{default:()=>V});let A=e("node:fs");var I=e.n(A);let K=e("node:path");var U=e.n(K);async function N(e,t){let r;if(e.json||process.env.CI||!process.stdin.isTTY||!process.stderr.isTTY)throw new o("--root-deps 需要交互终端,不能在 CI、非 TTY 或 --json 模式使用");let i=s(t),n=U().resolve(i.root,i.frontendDirectory);if(!I().statSync(n,{throwIfNoEntry:!1})?.isDirectory())throw new o(`前端目录不存在或不是目录:${n}`);let{getRootDependencyOptions:c}=await import("./sdk.js"),u=await c(n),p=u.choices.some(e=>!e.disabled);if(e.log(`根依赖配置保存位置:${u.packageJsonPath}`),!p&&!u.selected.length)return void e.log(u.choices.map(e=>`${e.name}:${e.disabled}`).join("\n")||"没有可补充的根依赖");try{if(p)r=await l({message:"选择云构建需要携带的根依赖(确认空列表可清除配置)",choices:u.choices.map(e=>({name:`${e.name} ${e.field} ${e.version??"未锁定"}`,value:e.name,checked:!e.disabled&&u.selected.includes(e.name),disabled:e.disabled}))});else{if(!await _({message:"根依赖已不可用,清除已保存的选择?",default:!1}))return;r=[]}}catch(e){if(e instanceof Error&&"ExitPromptError"===e.name)return;throw e}if(r.some(e=>!u.choices.some(t=>t.name===e&&!t.disabled)))throw new o("选中的根依赖不可用,请重新选择");let f=await c(n);if(f.inputDigest!==u.inputDigest)throw new o("项目配置或 lock 已变更,请重新执行 --root-deps");let m=I().readFileSync(f.packageJsonPath,"utf8");if(m!==f.packageJsonContent)throw new o("package.json 已变更,请重新执行 --root-deps");let g=JSON.parse(m);if(!d(g)||void 0!==g.dbx&&!d(g.dbx))throw new o("package.json 的 dbx 必须是对象");let w=g.dbx??{};if(void 0!==w.cloudBuild&&!d(w.cloudBuild))throw new o("package.json 的 dbx.cloudBuild 必须是对象");a(f.packageJsonPath,{...g,dbx:{...w,cloudBuild:{...w.cloudBuild,rootDependencies:r}}}),e.log(`根依赖选择已保存:${f.packageJsonPath}`)}let k=e("../../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/index.js");async function P(e,t,o=!1){if(!e.json&&"succeeded"===t.status)try{let r=AbortSignal.timeout(1e4),i=await j(t.app_id,t.version_tag,r),n=String(i?.artifact_version_code??"");if(!n.trim())throw Error("构建产物尚未就绪");let a={app_key:t.app_id,app_version_tag:t.version_tag,artifact_version_code:n,debug_switch:!0},{data:s}=await g(`doubaoapp://debug?debugInfo=${encodeURIComponent(JSON.stringify(a))}`,r);if("string"!=typeof s?.token||!s.token.trim())throw Error("服务端未返回有效 token");let _=await R(`doubaoapp://debug?short_token=${encodeURIComponent(s.token)}`,o);if(!_)return void e.warn("终端宽度不足,请拉宽窗口后重试,或通过版本详情页扫码。");e.log();let l=o?"":v.dim("(无法扫码时加 --qr full)");e.log(`${v.blue.bold(" 豆包扫码预览")}${l}`),e.log(),e.log(_)}catch{e.warn("预览二维码暂不可用,请通过版本详情页扫码。")}}async function R(e,t){let{modules:o}=k.create(e),r=t?(o.size+2)*2:o.size+4;if(process.stdout.columns&&r+2>process.stdout.columns)return;if(!t)return(await k.toString(e,{type:"utf8",margin:2})).split("\n").map(e=>` \x1b[38;2;0;0;0m\x1b[48;2;255;255;255m${e}\x1b[0m`).join("\n");let i=Array.from({length:o.size+2},(e,t)=>t-1);return i.map(e=>{let t=i.map(t=>{let r=t>=0&&e>=0&&t<o.size&&e<o.size&&o.get(e,t);return`\x1b[48;2;${r?"0;0;0":"255;255;255"}m `}).join("");return` ${t}\x1b[0m`}).join("\n")}async function j(e,t,o){for(let r=1;;r++){let{data:i}=await w(e,{page:r,page_size:100},o),n=i?.version_list??[],a=n.find(e=>e.version_tag===t);if(a)return a;if(!n.length||(i?.total===void 0?n.length<100:100*r>=i.total))return}}let O=e("node:os"),x={queued:"排队中",building:"构建中",succeeded:"成功",failed:"失败",unknown:"未知"},M={1:{name:"PENDING_BUILD",description:"等待云构建开始"},2:{name:"BUILD_STARTED",description:"云构建已开始"},3:{name:"CODE_READY",description:"源码包已就绪"},4:{name:"COMPILING",description:"正在编译前端代码"},5:{name:"COMPILE_SUCCEEDED",description:"编译成功,等待上传或最终打包"},6:{name:"UPLOADING",description:"正在上传构建产物"},7:{name:"BUILD_SUCCEEDED",description:"云构建成功"},8:{name:"BUILD_FAILED",description:"云构建失败"}};function B(e,t){let o=function(e){let t=e.artifact_build_error_info;if(t){var o,r;let i;return o=t,r=e.error_info_file,i=o.error_code||"构建产物失败",r?`${i}; 错误详情已写入 ${r}`:o.error_info?o.error_info:o.error_code?o.error_code:"number"==typeof o.last_status_before_failed?`构建产物在状态 ${o.last_status_before_failed} 后失败`:"构建产物失败"}let i=e.artifact_status;if(8===i){let e=q(i);return`artifact_status=${i} (${e.name})`}}(t);if(o)for(let r of(e.log(v.red(`失败原因: ${o}`)),function(e,t){if(!e)return[];let o=[];if(e.error_code&&o.push(`错误码: ${e.error_code}`),t?(o.push(`错误详情文件: ${t}`),o.push("错误详情:已写入临时文件,可供 Agent 诊断")):e.error_info&&o.push(`错误详情: ${e.error_info}`),"number"==typeof e.last_status_before_failed){let t=q(e.last_status_before_failed);o.push(`失败前状态: ${e.last_status_before_failed} (${t.name})`),o.push(`失败前状态说明: ${t.description}`)}return o}(t.artifact_build_error_info,t.error_info_file)))e.log(r)}function L(e,t){"succeeded"===t.status&&(e.log(),e.log(` 调试前,将手机豆包账号的 UID 加入应用的${v.yellow("「体验白名单」")}`),t.app_detail_url&&e.log(v.dim(` ${t.app_detail_url}#experience-whitelist`)),e.log(),t.version_detail_url&&(e.log(" 版本详情"),e.log(v.dim(` ${t.version_detail_url}`))),e.log())}async function T(e,t,o){var r,i,n,a;let s,_,l,d=await m(e,t),c=d.data,u=q(c?.artifact_status),p=(r=c,8===(s=r?.artifact_status)||r?.artifact_build_error_info?"failed":7===s?"succeeded":1===s?"queued":"number"==typeof s&&s>=2&&s<=6?"building":"unknown"),g="failed"===p&&c?.artifact_build_error_info?.error_info?(i=e,n=c?.version_tag||t,a=c.artifact_build_error_info.error_info,_=(0,K.join)((0,O.tmpdir)(),"dbx-artifact-build-errors"),(0,A.mkdirSync)(_,{recursive:!0}),l=(0,K.join)(_,`${G(i)}-${G(n)}-${Date.now()}-${process.pid}.log`),(0,A.writeFileSync)(l,a.endsWith("\n")?a:`${a}
2
+ `,"utf8"),l):void 0,w=c?.artifact_build_error_info?function(e,t){if(!t)return e;let{error_info:o,...r}=e;return r}(c.artifact_build_error_info,!!g):void 0;return{app_id:e,version_tag:c?.version_tag||t,artifact_status:c?.artifact_status,artifact_status_name:u.name,artifact_status_description:u.description,status:p,...w?{artifact_build_error_info:w}:{},...g?{error_info_file:g}:{},attempt:o,..."succeeded"===p?{version_detail_url:D(e,c?.version_tag||t),app_detail_url:$(e),doubao_debug_conversation_url:"https://inhouse.doubao.com/bot/2xgttdEs"}:{},log_id:d.log_id??f()??""}}async function H(e,o,r,i=5,a=T){let s=Date.now(),_=0,l=await a(e,o,_);for(;"succeeded"!==l.status&&"failed"!==l.status;){if(Date.now()-s>=1e3*r){var d;throw function(e,t,o="DBX_BUILD_FAILED"){return new n(e,{code:o,details:t,logId:f()})}("轮询构建产物状态超时",{...d=l,status:"succeeded"===d.status?"success":"queued"===d.status||"unknown"===d.status&&"number"==typeof d.artifact_status?"building":d.status},"DBX_WAIT_TIMEOUT")}await (0,t.setTimeout)(1e3*i),_+=1,l=await a(e,o,_)}return l}function q(e){return"number"!=typeof e?{name:"UNKNOWN",description:"服务端未返回构建产物状态"}:M[e]??{name:"UNKNOWN",description:`无法识别的构建产物状态:${e}`}}function G(e){return e.trim().replace(/[^a-zA-Z0-9._-]+/g,"_")||"unknown"}async function W(e,t,o=E,i=H){let a=S(t.project);e.targetAppId=a;let s=e.json?void 0:C("正在校验配置并准备构建...").start(),_={...e,warn(t,o){s?.clear(),e.warn(t,o),s?.isSpinning&&s.render()}},l=await r("DBX_UPLOAD_FAILED",()=>o(_,{appId:a,project:t.project,release:!!t.release,appVersionTag:"string"==typeof t.release?t.release:void 0,quiet:!0,env:t.env,secretEnv:t.secretEnv})).finally(()=>s?.stop()),d=l.version_tag;if(!d)throw new n("构建已提交,但平台未返回版本号,暂时无法查询构建进度",{code:"DBX_UPLOAD_FAILED"});let c={operation:"build",card_check:l.card_check,app_id:a,version_tag:d,version_kind:t.release?"release":"test",state:"queued",terminal:!1,uploaded_artifacts:l.uploaded_artifacts,packages:l.packages,config_sync_results:l.uploaded_artifacts.includes("business_templates")?[{config_type:"business-templates",scope:"app",state:"succeeded",rolled_back_with_version:!1,result:l.business_template_sync_result}]:[],version_detail_url:l.next?.version_detail_url,next_actions:[{purpose:"check_build_status",argv:["dbx","--json","build","status",d,"--project",t.project]}],log_id:l.log_id};if(!t.wait)return F(e,c),c;s?.start("正在等待云端构建...");let u=await r("DBX_REMOTE_ERROR",()=>i(a,d,t.timeoutSeconds)).finally(()=>s?.stop()),p={...c,...z(u),version_detail_url:u.version_detail_url??c.version_detail_url,next_actions:[]};if(F(e,p),B(e,u),await P(e,u,"full"===t.qr),L(e,u),"failed"===p.state)throw new n("云构建失败",{code:"DBX_BUILD_FAILED",details:p,logId:u.log_id});return p}async function J(e,t,o,i=T,n=!1){let a=S(t);e.targetAppId=a;let s=await r("DBX_REMOTE_ERROR",()=>i(a,o,0)),_={operation:"build.status",...z(s)};return F(e,_),B(e,s),await P(e,s,n),L(e,s),_}function X(e){try{let t=b(e);if(t)return t}catch{}throw new o(`正式版本号 ${JSON.stringify(e.trim())} 格式不正确。请使用三段纯数字,例如 1.2.3;不要添加 v 前缀或预发布后缀。`,"DBX_VERSION_TAG_INVALID")}function z(e){let t=e.status;return{app_id:e.app_id,version_tag:e.version_tag,state:t,terminal:"succeeded"===t||"failed"===t,provider_status:e.artifact_status,status_description:e.artifact_status_description,version_detail_url:e.version_detail_url,app_detail_url:e.app_detail_url,doubao_debug_conversation_url:e.doubao_debug_conversation_url,build_error:e.artifact_build_error_info,error_info_file:e.error_info_file,log_id:e.log_id}}function F(e,t){if("succeeded"===t.state)e.log(),e.log(v.green("✓ 构建成功")),e.log(` AppID ${t.app_id}`),e.log(` 版本号 ${t.version_tag}`);else{let o=`构建状态: ${x[t.state]??t.state}`;e.log("failed"===t.state?v.red(o):o),e.log(`AppID: ${t.app_id}`),e.log(`版本号: ${t.version_tag}`)}t.log_id&&(e.verbose||"succeeded"!==t.state)&&e.log("succeeded"===t.state?` ${v.dim("log_id")} ${t.log_id}`:`log_id: ${t.log_id}`),"succeeded"!==t.state&&t.version_detail_url&&e.log(`版本详情: ${t.version_detail_url}`),t.config_sync_results?.length&&e.log(v.dim(" 平台配置已同步(不随版本回滚)"))}function V(){let e=Y(new p("build").description("上传并触发云构建")).addOption(new u("--release [version]","构建正式版本,可指定版本号(如 1.2.3)").argParser(X)).option("--no-wait","提交后直接返回,不等待构建完成").option("--root-deps","交互选择并保存云构建的根依赖,不提交构建").option("--env <path>","构建变量文件;真实文件名须以 .env 开头,相对 --project 解析").option("--secret-env <path>","秘密构建变量文件;覆盖 --env 中的同名变量").addOption(new u("--timeout-seconds <seconds>","等待构建的最长时间(秒)").default(300).argParser(c)).addHelpText("after","\n仅本地编译使用 dbx build local;默认构建测试版本,加 --release 构建正式版本,版本号留空时自动生成。\n构建不会自动提审或发布。平台配置会一并同步,不随版本回滚。\n").action(async(e,t)=>i(t,async r=>{if(e.rootDeps){if(["release","wait","env","secretEnv","timeoutSeconds","qr"].some(e=>"cli"===t.getOptionValueSourceWithGlobals(e)))throw new o("--root-deps 不能与云构建选项同时使用");return N(r,e.project)}return function(e,t){if(!t.wait&&"cli"===e.getOptionValueSourceWithGlobals("timeoutSeconds"))throw new o("--timeout-seconds 不能与 --no-wait 同时使用")}(t,e),W(r,e)}));return e.addCommand(Y(new p("status").description("查看构建状态").argument("<version>","版本号")).action(async(e,t,r)=>i(r,t=>{if(r.optsWithGlobals().rootDeps)throw new o("status 不能使用 --root-deps");let i=r.optsWithGlobals();return J(t,i.project,e,void 0,"full"===i.qr)}))),e.addCommand(new p("local").description("仅本地编译前端,不上传或触发云构建").option("--project <path>","待编译的前端项目目录(默认当前目录)").option("--env-mode <mode>","加载 .env.[mode] 环境变量").action(async(e,t)=>i(t,async e=>{let r=t.optsWithGlobals();if(["release","wait","env","secretEnv","timeoutSeconds","qr","rootDeps"].some(e=>"cli"===t.getOptionValueSourceWithGlobals(e)))throw new o("local 不能使用云构建选项;环境模式请使用 --env-mode");let i=await h((0,K.resolve)(r.project),{envMode:r.envMode});return e.log(`本地编译完成:${i.cwd}`),{operation:"build_local",...i}}))),e}function Y(e){return e.option("--project <path>","项目目录",".").addOption(new u("--qr <mode>","二维码样式(默认 compact;扫码困难时用 full)").choices(["compact","full"]))}export{y as build_namespaceObject};
package/dist/check.js CHANGED
@@ -1 +1 @@
1
- import"node:module";import{__webpack_require__ as e}from"./rslib-runtime~0.js";import"./9652~0.js";import"./yaml.js";import{DBX_DEMO_NAMES as t,getDBXDemo as r,startMCPDemoServer as o}from"./demo-server.js";import{resolveProjectLayout as s,resolveRuntimeSkillLayout as i}from"./project-layout.js";import{readAppManifest as n}from"./manifest-yaml-generator.js";import{http_getApiBaseUrl as l,parseInteger as a,option_Option as c,stringField as _,command_Command as m,isRecord as d}from"./4315~0.js";import{extractMCPHeadersFromManifest as u}from"./manifest-headers.js";import{verifyYAML as p,compactValidationIssues as g}from"./app.js";import{connectMCPClient as f}from"./client.js";import{safeParseJSON as h,SimulatorStreamError as y,runSimulatorStream as v}from"./client~1.js";import{CliError as S,runCommand as $}from"./2168~0.js";import{source as w}from"./5610~0.js";var C={};e.r(C),e.d(C,{default:()=>J,executeCheck:()=>B,resolveYAMLType:()=>X});let x=e("node:fs");var b=e.n(x);let k=e("node:path");var P=e.n(k);let A=e("../../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/index.js"),M=new Set(["USER","ASSISTANT","TOOL"]);function E(e){let t=i(e);if("resolved"!==t.layout)throw q("missing"===t.layout?"skill_layout_missing":"skill_layout_invalid",t.error??`Skill 目录中没有可用的运行时 Skill: ${e}`,"请在选定目录任意层级放置至少一个普通文件 SKILL.md;符号链接不会被加载。");return t.entries.map(e=>e.content)}function I(e){if(!b().existsSync(e))throw q("manifest_file_not_found",`未找到 manifest 文件: ${e}`,"请检查 --manifest 路径;相对路径会按 --project 解析。");if(!b().statSync(e).isFile())throw q("manifest_path_not_file",`manifest 路径必须是文件: ${e}`,"请检查 --manifest 路径,不能传目录。");return n(e)}function q(e,t,r){let o=Error(t);return o.details={code:e,message:t,suggestion:r},o}function j(e,t){return P().isAbsolute(e)?e:P().resolve(t,e)}function T(e){return"string"==typeof e&&e.trim()?e:void 0}function O(e){var t,r;let o=[],s=e.preflight.filter(e=>"error"===e.level);for(let i of(o.push(...s),o.push(...(t=e.result.trace_events,r=e.result.request_id,t.filter(e=>e.error).map(e=>({code:String(e.error?.code||"trace_error"),level:"error",message:String(e.error?.user_message||e.error?.message||e.summary||"调用轨迹错误"),suggestion:K(e.error?.code,r),details:e.error})))),e.result.stream_errors??[]))o.push(function(e){var t;let r=String(e?.message||"流式响应错误"),o=String(e?.code||"stream_error");return{code:o,level:"error",message:r,suggestion:"string"==typeof e?.suggestion?e.suggestion:K(o,"")||((t=r).includes("exceeded max step")?"模型在最大步数内没有收口。请检查 skill 是否让模型重复查询/重复调用工具,或临时调大 --max-step 辅助定位。":t.includes("mcp tool invalid response")?"MCP 工具返回未通过 context post-hook。请对照 manifest 检查 tool_name、entity_type、主键字段和 structuredContent。":void 0),details:e?.details??e}}(i));if(!o.some(e=>"error"===e.level)){let t=e.cardExpectation??"auto";o.push(...function(e,t,r){let o=[];for(let t of e){let e=t.result_preview||"";(t.result_error||e.includes("MCP error")||e.includes("Input validation error"))&&o.push({code:"mcp_tool_result_error",level:"error",message:`MCP 工具 ${t.tool_name} 返回错误结果`,suggestion:"工具已被模型调用,但 MCP tools/call 返回业务/参数错误。请检查 Agent Flow 里的 args 与工具入参 schema 是否一致;常见问题是模型传了字符串数字,可在 MCP server 用 z.coerce.number() 或自行兼容转换。",details:{tool_name:t.tool_name,tool_call_id:t.tool_call_id,arguments:t.arguments,result_preview:e}})}return"auto"===r&&e.length>0&&0===t&&0===o.length&&o.push({code:"tool_called_but_no_card",level:"warn",message:"工具调用已完成,但未输出 card_delta",suggestion:"如果这是出卡工具,请检查工具 result 是否包含 structuredContent.entities、entity_type 是否在 manifest.entities 声明、tool_card_binding 是否绑定该工具。"}),o}(e.result.tool_calls,e.result.cards.length,t));let r=e.result.tool_calls.map(e=>e.tool_name),s=e.evalCase.expect?.tool_calls??[];s.length>0&&!function(e,t){let r=0;for(let o of t)if(o===e[r]&&(r+=1),r===e.length)return!0;return 0===e.length}(s,r)&&o.push({code:"expectation_tool_chain_mismatch",level:"error",message:`期望工具调用链为 ${s.join(" -> ")},实际为 ${r.join(" -> ")||"-"}`,suggestion:"请检查 skill 的工具流程描述、query 是否表达了对应意图,以及 MCP tools 是否暴露了这些工具。"});let i=e.evalCase.expect?.card;if(i||"required"===t){let t=i?.min_count??1,r=i?.widget_id?e.result.cards.filter(e=>e.widget_id===i.widget_id):e.result.cards;r.length<t&&o.push({code:"card_not_emitted",level:"error",message:i?.widget_id?`期望至少 ${t} 张 widget_id 为 ${i.widget_id} 的卡片,实际为 ${r.length} 张`:`期望至少 ${t} 张卡片,实际为 ${e.result.cards.length} 张`,suggestion:"如果工具已成功,重点检查 manifest.tools、entities.*.tool_card_binding、MCP result structuredContent.entities 和模型是否在工具后触发出卡。"})}for(let r of("none"===t&&e.result.cards.length>0&&o.push({code:"unexpected_card_emitted",level:"error",message:`期望不输出卡片,实际输出 ${e.result.cards.length} 张`,suggestion:"如果当前用例不应出卡,请检查工具是否返回了非空 structuredContent.entities,或检查 manifest 中该工具的 tool_card_binding。"}),e.result.tool_calls))!e.manifest.tools[r.tool_name]&&e.manifest.cardBindings[r.tool_name]&&o.push({code:"card_tool_not_declared",level:"error",message:`${r.tool_name} 已绑定卡片,但未在 manifest.tools 中声明`,suggestion:`请在 manifest.tools.${r.tool_name} 中声明 output.entity_types。`})}let i=function(e){let t=new Set,r=[];for(let o of e){if(function(e,t){return"SIMULATOR_STREAM_ERROR"===e.code&&t.some(t=>{if(t.code===e.code)return!1;if(e.message.includes(t.message))return!0;let r=_(function(e,t){if(!d(e))return;let r=e[t];return d(r)?r:void 0}(t.details,"details"),"raw_error")||_(t.details,"raw_error");return void 0!==r&&e.message.includes(r)})}(o,r))continue;let e=`${o.level}\u0000${o.code}\u0000${o.message}`;t.has(e)||(t.add(e),r.push(o))}return r}(o),n=0===i.filter(e=>"error"===e.level).length;return{ok:n,verdict:n?"PASS":"FAIL",case:e.evalCase,context:{history_count:e.evalCase.history_messages?.length??0,query:e.evalCase.query,mcp_url:e.evalCase.mcp.url,gateway_origin:e.gatewayOrigin,max_step:e.evalCase.max_step},preflight:e.preflight,errors:i,...e.result}}function K(e,t){return"miniapp_mcp_result_invalid"===e?"MCP 工具返回未通过应用插件协议校验。请检查返回 JSON 是否包含 content/structuredContent,entity_type 是否在 manifest.entities 中声明,实体主键字段是否匹配 is_entity_id。":"agent_run_failed"===e?`Agent 运行失败。请查看 request_id=${t||"-"} 对应 trace,重点关注是否重复 tool call、max_step 不足或模型没有触发卡片输出。`:"tool_call_or_report_failed"===e?"工具调用或结果上报失败。请检查 MCP tools/call 是否可用,以及返回的 structuredContent/entities 是否符合 manifest 声明。":void 0}function U(e,t){return{code:e,level:"info",message:t}}function L(e,t,r){return{code:e,level:"warn",message:t,suggestion:r}}function N(e,t,r){return{code:e,level:"error",message:t,suggestion:r}}async function R(e){let o;try{let i,n=function(e){let o=P().resolve(e.projectPath),i=s(o),n={...e.demo?function(e){try{return r(e).evalCase}catch{throw Error(`未知 dbx check 示例:${e}。支持的示例: ${t.join(", ")}`)}}(e.demo):{},...e.query?{query:e.query}:{},...void 0!==e.maxStep?{max_step:e.maxStep}:{}};if(e.historyPath&&(n.history_messages=function(e){if(!b().existsSync(e))throw q("history_file_not_found",`未找到历史消息文件: ${e}`,"请检查 --history 路径;历史文件应为消息数组。");let t=function(e,t,r){try{return t.endsWith(".json")?JSON.parse(e):A.qg(e)}catch(e){throw q(`${r}_file_parse_failed`,`${r} 文件解析失败: ${e?.message||String(e)}`,`请检查 ${t} 的语法和缩进。`)}}(b().readFileSync(e,"utf8"),e,"history");if(!Array.isArray(t))throw q("history_file_invalid","历史消息文件必须是数组","请把 history 文件写成数组,例如 [{ role: USER, content: hello }]。");return t}(j(e.historyPath,o))),e.skillsDirectory?n.skills=E(j(e.skillsDirectory,o)):n.skills||(n.skills=E(i.skillDirectory)),e.manifestPath)n.manifest=I(j(e.manifestPath,o));else{var l;if(n.manifest&&((l=n.manifest).includes("/")||l.endsWith(".json")||l.endsWith(".yaml")||l.endsWith(".yml")))n.manifest=I(j(n.manifest,o));else if(!n.manifest){let e=i.manifestPath;b().existsSync(e)&&(n.manifest=I(e))}}if(e.mcpUrl&&(n.manifest=function(e,t){if("string"!=typeof e)return;if(!e.trim())return e;let r=A.Tp(e);return r.setIn(["mcp_server","end_point"],t),r.setIn(["mcp_server","mcp_config","protocol"],"Streamable"),r.toString()}(n.manifest,e.mcpUrl)),function(e){if(!e.query||"string"!=typeof e.query||!e.query.trim())throw q("query_required","dbx check 需要 query","请通过 --query 传入本轮用户问题。");if(!Array.isArray(e.skills)||0===e.skills.length||e.skills.some(e=>"string"!=typeof e))throw q("skill_required","dbx check 至少需要一个 Skill","请在项目 skill/ 中放置至少一个 SKILL.md,或通过 --skill 传入 Skill 目录。");if(!e.manifest||"string"!=typeof e.manifest)throw q("manifest_required","dbx check 需要 manifest YAML 文本或文件路径","请在项目 manifest.yaml 放置 Manifest,或通过 --manifest 传入路径。")}(n),n.history_messages=(n.history_messages??[]).map((e,t)=>{if(!e||"object"!=typeof e)throw q("history_message_invalid",`history_messages[${t}] 必须是对象`,"请把每条历史消息写成 { role: USER|ASSISTANT|TOOL, content: string }。");let r=String(e.role||"").toUpperCase();if(!M.has(r))throw q("history_message_role_invalid",`history_messages[${t}].role 必须为 USER、ASSISTANT 或 TOOL`,"请把 role 改成 USER、ASSISTANT 或 TOOL。");if("string"!=typeof e.content||!e.content.trim())throw q("history_message_content_invalid",`history_messages[${t}].content 必须是非空字符串`,"请为该历史消息补充非空 content。");return{role:r,content:e.content}}),n.max_step=n.max_step??15,!Number.isInteger(n.max_step)||n.max_step<=0)throw q("max_step_invalid","max_step 必须是正整数","请删除 max_step 使用默认值 15,或通过 --max-step 传入正整数。");return n}(e),a=await p(n.manifest,"compatible");if(!a.data?.success||!a.data.manifest)throw new Y("manifest 校验失败",{code:"manifest_validation_failed",message:"manifest 校验失败",errors:a.data?.errors??[],warnings:a.data?.warnings??[],log_id:a.log_id});let c=function(e,t){if(!d(t))throw q("manifest_parse_result_missing","dbx check 需要 YAML 校验接口返回解析后的 manifest","请先确认后端 /yaml/verify 返回 data.manifest。");let r=d(t.mcp_server)?t.mcp_server:void 0,o=T(t.app_key),s=T(r?.end_point);if(!o)throw q("app_id_required","dbx check 需要 manifest AppID","请在 manifest.yaml 配置 app_key(该字段对外称 AppID)。");if(!s)throw q("mcp_url_required","dbx check 需要 manifest 中的 mcp_server.end_point","请在 manifest.yaml 配置 mcp_server.end_point。");return function(e,t,r){try{let t=new URL(e);if("http:"===t.protocol||"https:"===t.protocol)return}catch{}throw q(t,`${r} 必须是 http(s) URL: ${e}`,`请把 ${r} 配置为 http:// 或 https:// 开头的 MCP endpoint。`)}(s,"mcp_url_invalid","manifest.mcp_server.end_point"),{...e,app_key:o,app_name:T(t.name),mcp:{url:s,description:T(r?.description),headers:u(t)}}}(n,a.data.manifest),m=function(e){if(!d(e)){var t;let e;throw t="manifest 必须是已解析的对象",(e=Error(t)).details={code:"manifest_yaml_invalid",message:t,suggestion:"请先运行 `dbx check --file <manifest.yaml>`,确认后端能解析 manifest。"},e}let r=d(e.tools)?e.tools:{},o=d(e.entities)?e.entities:{},s={};for(let e of Object.values(o))if(d(e)&&d(e.tool_card_binding))for(let[t,r]of Object.entries(e.tool_card_binding))"string"==typeof r&&(s[t]=r);return{raw:e,appKey:"string"==typeof e.app_key?e.app_key:void 0,tools:r,entities:o,cardBindings:s}}(a.data.manifest),g={...(o=await f(c.mcp.url,c.app_key,c.mcp.headers).catch(e=>{var t,r,o;let s,i,n,l,a,_=(t=e,r=c.mcp.url,(a=(o=l=String(t?.message||t),i=(s=o.match(/<pre>([\s\S]*?)<\/pre>/i)?.[1])?s.replace(/<br\s*\/?>/gi,"\n").replace(/&nbsp;/g," ").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&"):o,(n=i.match(/(?:TypeError|ReferenceError|SyntaxError|Error):[^\n<]+/)?.[0])?n.trim():/HTTP 5\d\d/.test(o)?"MCP 服务器返回 HTTP 5xx":void 0))?{code:"mcp_server_internal_error",message:`MCP 服务器处理 initialize/tools/list 时发生内部错误: ${a}`,suggestion:"CLI 已连上 MCP server,但 MCP server 在 initialize 或 tools/list 内部报错。请查看 MCP server 终端日志和报错堆栈,优先修 server 代码。",details:{url:r,raw_error:l,server_error:a}}:{code:"mcp_unreachable",message:l,suggestion:"请先启动标准 MCP server,并确认 manifest.mcp_server.end_point 指向 CLI 当前运行环境可访问的 Streamable HTTP /mcp 或 SSE /sse 地址;不要求公网 URL。",details:{url:r,raw_error:l}});throw new Y(`MCP server unreachable: ${c.mcp.url}`,_)})).tools,server_id:c.mcp.server_id||o.tools.server_id,name:c.mcp.name||o.tools.name,description:c.mcp.description||o.tools.description},S=[...function(e){let t=[],{evalCase:r,manifest:o,mcp:s}=e,i=new Set(s.tools.map(e=>e.name).filter(Boolean)),n=Object.keys(o.tools),l=new Set(n);if(o.appKey===r.app_key?t.push(U("manifest_app_id_match",`manifest AppID 与请求 AppID 一致(${r.app_key})`)):t.push(N("manifest_app_id_mismatch",`manifest AppID(${o.appKey||"-"})与请求 AppID(${r.app_key})不一致`,"请保持请求 AppID 与 manifest.app_key 一致;如果走特殊测试链路会改写 AppID,需要确认后端映射规则。")),s.tools.length>0){let e="sse"===s.protocol?"SSE /sse":"Streamable HTTP /mcp";t.push(U("mcp_tools_loaded",`MCP 通过 ${e} 提供了 ${s.tools.length} 个工具`))}else t.push(N("mcp_tools_empty","MCP 未提供任何工具","请检查标准 MCP tools/list 是否返回 tools。Streamable HTTP 传 /mcp,SSE 传 /sse。"));for(let e of n)i.has(e)||t.push(N("manifest_tool_missing_in_mcp",`manifest.tools 声明了 ${e},但 MCP 未提供此工具`,"请确保会出卡的 tool 同时存在于 MCP tools 与 manifest.tools。"));for(let e of r.expect?.tool_calls??[])l.has(e)||t.push(N("expected_tool_missing_in_manifest",`expect.tool_calls 声明了 ${e},但 manifest.tools 未声明此工具`,`请在 manifest.tools.${e} 中声明该工具;非出卡工具也需要配置 output.kind,例如 execution_result。`)),i.has(e)||t.push(N("expected_tool_missing_in_mcp",`expect.tool_calls 声明了 ${e},但 MCP 未提供此工具`,"请确认 MCP tools/list 返回了期望调用的工具,或修正内置 demo 的 expect.tool_calls。"));let a=Object.keys(o.cardBindings);if(a.length>0)t.push(U("card_binding_found",`已找到卡片绑定: ${a.map(e=>`${e} -> ${o.cardBindings[e]}`).join(", ")}`));else{var c,_;let e=(c=r,_=o,c.expect?.card||Object.values(_.tools).some(e=>d(e)&&d(e.output)&&"entities"===e.output.kind))?N:L;t.push(e("card_binding_missing","manifest.entities 中没有 tool_card_binding","如果期望出卡,请在对应 entity 下配置 tool_card_binding,例如 Taxi_order: tpl.taxi_order。"))}for(let[e,r]of Object.entries(o.entities))d(r)&&d(r.schema)&&0===Object.entries(r.schema).filter(([,e])=>d(e)&&!0===e.is_entity_id).length&&t.push(N("entity_id_missing",`manifest.entities.${e}.schema 中没有标记 is_entity_id 的字段`,"请为实体配置一个稳定主键字段,例如 product_id: { type: string, is_entity_id: true }。"));return t}({evalCase:c,manifest:m,mcp:g}),...function(e){let t=[];for(let r of e.tools){let e=h(r.input_schema_json);if(e)for(let o of function e(t,r){let o=[];if(!d(t))return o;for(let e of["exclusiveMinimum","exclusiveMaximum"]){let s=t[e];"number"==typeof s&&o.push({path:`${r}/${e}`,value:s,message:`${e} 为数值 ${s},但模拟器后端要求布尔值`,suggestion:"如果使用 zod,避免 z.number().positive()/min()/max() 生成数值型 exclusiveMinimum/exclusiveMaximum;可改为 z.coerce.number() 并在工具内部校验业务范围。"})}for(let[s,i]of Object.entries(t))d(i)&&o.push(...e(i,`${r}/${s}`)),Array.isArray(i)&&i.forEach((t,i)=>{o.push(...e(t,`${r}/${s}/${i}`))});return o}(e,`tools/${r.name}/inputSchema`))t.push({code:"mcp_tool_schema_incompatible",level:"error",message:`MCP 工具 ${r.name} 的 inputSchema 不兼容: ${o.message}`,suggestion:o.suggestion,details:{tool_name:r.name,path:o.path,value:o.value}})}return t}(g)],$=e.gatewayOrigin||l(),w={evalCase:c,manifest:m,preflight:S,gatewayOrigin:$,cardExpectation:e.cardExpectation};if(!e.force&&S.some(e=>"error"===e.level))return O({...w,result:D()});try{i=await v({evalCase:c,manifestYAML:c.manifest,mcp:g,gatewayOrigin:$,callbacks:{onToolCall:async(e,t)=>{var r,s;return o.callTool((r=c,s=e,{request_id:t,app_key:s.app_key||r.app_key,server_id:s.server_id||r.mcp?.server_id||"",tool_call_id:s.tool_call_id,tool_name:s.tool_name,arguments:h(s.arguments_json)||{},arguments_json:s.arguments_json||"{}"}))}}})}catch(e){if(e instanceof y)return O({...w,result:H(e.state,[F(e)])});return O({...w,result:{...D(),log_id:_(e,"logId")||_(e,"log_id"),stream_errors:[F(e)]}})}return O({...w,result:H(i)})}finally{o?.close()}}function D(){return{request_id:"",tool_calls:[],cards:[],answer:"",trace_events:[],stream_errors:[]}}function H(e,t=[]){return{request_id:e.requestID,log_id:e.logID,trace_id:e.traceID,tool_calls:e.toolCalls.map(e=>{var t;return{tool_name:e.toolCall.tool_name,tool_call_id:e.toolCall.tool_call_id,app_key:e.toolCall.app_key,server_id:e.toolCall.server_id,arguments:h(e.toolCall.arguments_json)??e.toolCall.arguments_json,report_code:"number"==typeof e.report?.code?e.report.code:void 0,report_message:"string"==typeof e.report?.message?e.report.message:void 0,result_error:e.result?.is_error,result_preview:(t=e.result?.raw_result_text||e.result?.content||"").length>240?`${t.slice(0,240)}...`:t}}),cards:e.cards,answer:e.answer,trace_events:e.traceEvents,stream_errors:[...e.streamErrors,...t]}}function F(e){var t;let r=e instanceof Error?e.message:String(e);return{code:_(e,"code")||"simulator_eval_runtime_error",level:"error",message:r,suggestion:(t=r).includes("fetch failed")||t.includes("ECONNREFUSED")||t.includes("ENOTFOUND")||t.includes("timed out")||t.includes("超时")?"无法连接 Simulator gateway。请检查 --gateway-origin、网络/PPE 泳道、登录环境和代理配置。":t.includes("HTTP 400")||t.includes("HTTP 422")?"请求被 gateway 或 agent 拒绝。请检查 manifest YAML、mcp tools、AppID 和 query 是否匹配;可加 --verbose 查看更多 trace。":t.includes("HTTP 5")?"Simulator 服务端异常。请保留 log_id/request_id 给服务端排查。":t.includes("tool report failed")||t.includes("工具结果上报失败")?"工具结果上报失败。请检查 MCP 返回的 structuredContent/entities 是否符合 manifest 声明。":void 0,details:d(e)?{...e,message:r}:r}}class Y extends Error{details;constructor(e,t){super(e),this.details=t}}let z={runSimulator:R,startDemoServer:o,validateFile:V};function J(){return new m("check").description("校验配置文件或检查 Agentic Service Simulator 链路").option("--file <file>","校验 manifest.yaml 或 business-templates.yaml").option("--project <path>","dbx 项目路径;相对路径参数会基于该目录解析",".").addOption(new c("--demo <name>","运行内置示例").choices([...t])).option("--query <query>","当前轮用户输入").option("--history <path>","历史消息文件,支持 JSON/YAML 数组").option("--skill <path>","Skill 目录路径;显式目录优先,相对路径按 --project 解析;未传默认 skill/,递归加载所有 SKILL.md").option("--manifest <path>","Manifest YAML 文件路径;默认按项目布局自动解析").option("--gateway-origin <url>","模拟器网关地址;默认使用 CLI 构建配置中的 apiBaseUrl").addOption(new c("--max-step <count>","Agent 最大循环步数").argParser(a)).addOption(new c("--expect-card <expectation>","当前评测是否期望出卡;required 要求至少一张卡,none 要求不出卡,auto 使用默认诊断").choices(["auto","required","none"]).default("auto")).option("--force","即使预检查发现配置错误也继续请求模拟器",!1).option("--verbose","输出更多执行轨迹和工具结果摘要",!1).action(async(e,t)=>$(t,t=>B({...e,verbose:t.verbose},t)))}async function B(e,t,r=z){let o;if(e.file){var s;return((s=e).demo||s.query||s.history||s.skill||s.manifest||s.gatewayOrigin||void 0!==s.maxStep||s.force||"auto"!==s.expectCard)&&t.error("--file 不能与模拟器检查选项同时使用"),r.validateFile(t,(0,k.resolve)(e.project,e.file),(0,k.resolve)(e.project,"tools.json"))}e.demo||e.query||t.error('check 需要指定 --file、--demo 或 --query。示例: dbx check --file manifest.yaml; dbx check --demo taxi; dbx check --query "..."');try{return e.demo&&(o=await r.startDemoServer({demo:e.demo,host:"127.0.0.1",port:0,log:t.log})),await W(t,e,r.runSimulator,o?.streamableUrl)}finally{if(o)try{await o.close()}catch(e){t.warn(`停止示例 MCP 服务失败:${String(e)}`)}}}async function W(e,t,r,o){let s;try{e.targetAppId=(s=await r({projectPath:t.project,demo:t.demo,mcpUrl:o,query:t.query,historyPath:t.history,skillsDirectory:t.skill,manifestPath:t.manifest,gatewayOrigin:t.gatewayOrigin,maxStep:t.maxStep,cardExpectation:t.expectCard,force:t.force,verbose:t.verbose})).case.app_key}catch(l){var i,n;let t,r,o;if(e.json)throw l;let s=(t=d(i=l)?i.details:void 0,{code:_(r=d(t)?t:void 0,"code"),message:_(r,"message")||(i instanceof Error&&i.message?i.message:String(i)),suggestion:_(r,"suggestion"),logId:_(r,"log_id")||_(r,"logId")||_(i,"log_id")||_(i,"logId"),details:t});throw new S((o=["Agentic Service 检查失败,未能运行诊断","","错误",...(n=s).code?[`- 错误码:${n.code}`]:[],`- 错误信息:${n.message}`,...n.logId?[`- log_id: ${n.logId}`]:[],...n.suggestion?[`- 修复建议:${n.suggestion}`]:[]],void 0!==n.details&&o.push("","详细信息",G(n.details)),o.join("\n")),{details:s.details,logId:s.logId})}if(e.json||function(e,t,r){let o=t.ok?w.green("通过"):w.red("未通过");if(e.log(`${w.bold("Agentic Service 检查")} ${o}`),e.log(""),e.log(w.bold("输入")),e.log(`- app_id: ${t.case.app_key}`),e.log(`- 用户输入:${t.context.query}`),e.log(`- 历史消息数:${t.context.history_count}`),e.log(`- MCP 地址:${t.context.mcp_url||"-"}`),e.log(`- 网关地址:${t.context.gateway_origin||"-"}`),e.log(`- 最大步数:${t.context.max_step??"-"}`),e.log(`- 请求 ID:${t.request_id||"-"}`),e.log(`- log_id: ${t.log_id||"-"}`),e.log(""),Q(e,"预检查",t.preflight,r),e.log(""),e.log(w.bold("Agent Flow")),0===t.tool_calls.length?e.log("- 未调用工具"):t.tool_calls.forEach((t,o)=>{e.log(`${o+1}. ${w.cyan(t.tool_name)} ${0===t.report_code?w.green("已上报"):w.yellow(`上报状态码=${t.report_code??"-"}`)}`),e.log(` 工具调用 ID:${t.tool_call_id}`),t.app_key&&e.log(` app_id: ${t.app_key}`),e.log(` 参数:${JSON.stringify(t.arguments??{})}`),r&&t.result_preview&&e.log(` 结果:${t.result_preview}`)}),e.log(""),e.log(w.bold("卡片")),0===t.cards.length?e.log("- 未输出卡片"):t.cards.forEach((t,r)=>{e.log(`${r+1}. 组件 ID=${t.widget_id||"-"} 实体 ID=${t.entity_id||"-"} 模板=${t.template||"-"}`)}),e.log(""),t.answer&&(e.log(w.bold("回复")),e.log(t.answer),e.log("")),r&&t.trace_events.length>0){for(let r of(e.log(w.bold("执行轨迹")),t.trace_events))e.log(`- ${r.name||"-"} ${r.status||"-"} ${r.tool_name||""} ${r.summary||""}`);e.log("")}Q(e,"诊断结果",t.errors,r),e.log(""),e.log(`${w.bold("结论")}: ${o}`)}(e,s,t.verbose),!s.ok)throw new S("检查失败",{json:s,logId:s.log_id});return s}function G(e){return"string"==typeof e?e:JSON.stringify(e,null,2)}function Q(e,t,r,o){if(e.log(w.bold(t)),0===r.length)return void e.log("- 无");for(let t of r){let r="error"===t.level?w.red("✗"):"warn"===t.level?w.yellow("!"):w.green("✓");e.log(`${r} ${t.code}: ${t.message}`),t.suggestion&&e.log(` 修复建议:${t.suggestion}`),o&&void 0!==t.details&&e.log(` 详细信息:${G(t.details)}`)}}async function V(e,t,r){(0,x.existsSync)(t)&&(0,x.statSync)(t).isFile()||e.error(`未找到 YAML 文件:${t}`);let o=X(t,e),s="manifest"===o?n(t,r):(0,x.readFileSync)(t,"utf8"),i=await p(s,"compatible",o),l=i.data,a={valid:!!l?.success,manifest:l?.manifest,errors:g(l?.errors??[]),warnings:g(l?.warnings??[]),log_id:i.log_id??""};if("manifest"===o&&d(a.manifest)&&"string"==typeof a.manifest.app_key&&(e.targetAppId=a.manifest.app_key.trim()||void 0),e.log(`${o} 校验:${a.valid?"通过":"失败"}`),e.log(JSON.stringify(a,null,2)),!a.valid)throw new S(`${o} 校验失败`,{json:a,logId:a.log_id});return a}function X(e,t){switch((0,k.basename)(e).toLowerCase()){case"manifest.yaml":return"manifest";case"business-templates.yaml":return"business_templates";default:t.error(`无法根据文件名“${(0,k.basename)(e)}”确定 YAML 类型,请使用 manifest.yaml 或 business-templates.yaml。`)}}export{C as check_namespaceObject};
1
+ import"node:module";import{__webpack_require__ as e}from"./rslib-runtime~0.js";import"./9652~0.js";import"./yaml.js";import{DBX_DEMO_NAMES as t,getDBXDemo as r,startMCPDemoServer as o}from"./demo-server.js";import{resolveProjectLayout as s,resolveRuntimeSkillLayout as i}from"./project-layout.js";import{http_getApiBaseUrl as n,parseInteger as l,option_Option as a,stringField as c,command_Command as _,isRecord as m}from"./4315~0.js";import{extractMCPHeadersFromManifest as d}from"./manifest-headers.js";import{verifyYAML as u,compactValidationIssues as p}from"./app.js";import{connectMCPClient as g}from"./client.js";import{safeParseJSON as f,SimulatorStreamError as h,runSimulatorStream as y}from"./client~1.js";import{CliError as v,runCommand as S}from"./2168~0.js";import{source as $}from"./5610~0.js";var w={};e.r(w),e.d(w,{default:()=>z,executeCheck:()=>J,resolveYAMLType:()=>V});let C=e("node:fs");var x=e.n(C);let b=e("node:path");var k=e.n(b);let P=e("../../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/index.js"),A=new Set(["USER","ASSISTANT","TOOL"]);function M(e){let t=i(e);if("resolved"!==t.layout)throw I("missing"===t.layout?"skill_layout_missing":"skill_layout_invalid",t.error??`Skill 目录中没有可用的运行时 Skill: ${e}`,"请在选定目录任意层级放置至少一个普通文件 SKILL.md;符号链接不会被加载。");return t.entries.map(e=>e.content)}function E(e){if(!x().existsSync(e))throw I("manifest_file_not_found",`未找到 manifest 文件: ${e}`,"请检查 --manifest 路径;相对路径会按 --project 解析。");if(!x().statSync(e).isFile())throw I("manifest_path_not_file",`manifest 路径必须是文件: ${e}`,"请检查 --manifest 路径,不能传目录。");return x().readFileSync(e,"utf8")}function I(e,t,r){let o=Error(t);return o.details={code:e,message:t,suggestion:r},o}function q(e,t){return k().isAbsolute(e)?e:k().resolve(t,e)}function T(e){return"string"==typeof e&&e.trim()?e:void 0}function O(e){var t,r;let o=[],s=e.preflight.filter(e=>"error"===e.level);for(let i of(o.push(...s),o.push(...(t=e.result.trace_events,r=e.result.request_id,t.filter(e=>e.error).map(e=>({code:String(e.error?.code||"trace_error"),level:"error",message:String(e.error?.user_message||e.error?.message||e.summary||"调用轨迹错误"),suggestion:j(e.error?.code,r),details:e.error})))),e.result.stream_errors??[]))o.push(function(e){var t;let r=String(e?.message||"流式响应错误"),o=String(e?.code||"stream_error");return{code:o,level:"error",message:r,suggestion:"string"==typeof e?.suggestion?e.suggestion:j(o,"")||((t=r).includes("exceeded max step")?"模型在最大步数内没有收口。请检查 skill 是否让模型重复查询/重复调用工具,或临时调大 --max-step 辅助定位。":t.includes("mcp tool invalid response")?"MCP 工具返回未通过 context post-hook。请对照 manifest 检查 tool_name、entity_type、主键字段和 structuredContent。":void 0),details:e?.details??e}}(i));if(!o.some(e=>"error"===e.level)){let t=e.cardExpectation??"auto";o.push(...function(e,t,r){let o=[];for(let t of e){let e=t.result_preview||"";(t.result_error||e.includes("MCP error")||e.includes("Input validation error"))&&o.push({code:"mcp_tool_result_error",level:"error",message:`MCP 工具 ${t.tool_name} 返回错误结果`,suggestion:"工具已被模型调用,但 MCP tools/call 返回业务/参数错误。请检查 Agent Flow 里的 args 与工具入参 schema 是否一致;常见问题是模型传了字符串数字,可在 MCP server 用 z.coerce.number() 或自行兼容转换。",details:{tool_name:t.tool_name,tool_call_id:t.tool_call_id,arguments:t.arguments,result_preview:e}})}return"auto"===r&&e.length>0&&0===t&&0===o.length&&o.push({code:"tool_called_but_no_card",level:"warn",message:"工具调用已完成,但未输出 card_delta",suggestion:"如果这是出卡工具,请检查工具 result 是否包含 structuredContent.entities、entity_type 是否在 manifest.entities 声明、tool_card_binding 是否绑定该工具。"}),o}(e.result.tool_calls,e.result.cards.length,t));let r=e.result.tool_calls.map(e=>e.tool_name),s=e.evalCase.expect?.tool_calls??[];s.length>0&&!function(e,t){let r=0;for(let o of t)if(o===e[r]&&(r+=1),r===e.length)return!0;return 0===e.length}(s,r)&&o.push({code:"expectation_tool_chain_mismatch",level:"error",message:`期望工具调用链为 ${s.join(" -> ")},实际为 ${r.join(" -> ")||"-"}`,suggestion:"请检查 skill 的工具流程描述、query 是否表达了对应意图,以及 MCP tools 是否暴露了这些工具。"});let i=e.evalCase.expect?.card;if(i||"required"===t){let t=i?.min_count??1,r=i?.widget_id?e.result.cards.filter(e=>e.widget_id===i.widget_id):e.result.cards;r.length<t&&o.push({code:"card_not_emitted",level:"error",message:i?.widget_id?`期望至少 ${t} 张 widget_id 为 ${i.widget_id} 的卡片,实际为 ${r.length} 张`:`期望至少 ${t} 张卡片,实际为 ${e.result.cards.length} 张`,suggestion:"如果工具已成功,重点检查 manifest.tools、entities.*.tool_card_binding、MCP result structuredContent.entities 和模型是否在工具后触发出卡。"})}for(let r of("none"===t&&e.result.cards.length>0&&o.push({code:"unexpected_card_emitted",level:"error",message:`期望不输出卡片,实际输出 ${e.result.cards.length} 张`,suggestion:"如果当前用例不应出卡,请检查工具是否返回了非空 structuredContent.entities,或检查 manifest 中该工具的 tool_card_binding。"}),e.result.tool_calls))!e.manifest.tools[r.tool_name]&&e.manifest.cardBindings[r.tool_name]&&o.push({code:"card_tool_not_declared",level:"error",message:`${r.tool_name} 已绑定卡片,但未在 manifest.tools 中声明`,suggestion:`请在 manifest.tools.${r.tool_name} 中声明 output.entity_types。`})}let i=function(e){let t=new Set,r=[];for(let o of e){if(function(e,t){return"SIMULATOR_STREAM_ERROR"===e.code&&t.some(t=>{if(t.code===e.code)return!1;if(e.message.includes(t.message))return!0;let r=c(function(e,t){if(!m(e))return;let r=e[t];return m(r)?r:void 0}(t.details,"details"),"raw_error")||c(t.details,"raw_error");return void 0!==r&&e.message.includes(r)})}(o,r))continue;let e=`${o.level}\u0000${o.code}\u0000${o.message}`;t.has(e)||(t.add(e),r.push(o))}return r}(o),n=0===i.filter(e=>"error"===e.level).length;return{ok:n,verdict:n?"PASS":"FAIL",case:e.evalCase,context:{history_count:e.evalCase.history_messages?.length??0,query:e.evalCase.query,mcp_url:e.evalCase.mcp.url,gateway_origin:e.gatewayOrigin,max_step:e.evalCase.max_step},preflight:e.preflight,errors:i,...e.result}}function j(e,t){return"miniapp_mcp_result_invalid"===e?"MCP 工具返回未通过应用插件协议校验。请检查返回 JSON 是否包含 content/structuredContent,entity_type 是否在 manifest.entities 中声明,实体主键字段是否匹配 is_entity_id。":"agent_run_failed"===e?`Agent 运行失败。请查看 request_id=${t||"-"} 对应 trace,重点关注是否重复 tool call、max_step 不足或模型没有触发卡片输出。`:"tool_call_or_report_failed"===e?"工具调用或结果上报失败。请检查 MCP tools/call 是否可用,以及返回的 structuredContent/entities 是否符合 manifest 声明。":void 0}function K(e,t){return{code:e,level:"info",message:t}}function L(e,t,r){return{code:e,level:"warn",message:t,suggestion:r}}function U(e,t,r){return{code:e,level:"error",message:t,suggestion:r}}async function N(e){let o;try{let i,l=function(e){let o=k().resolve(e.projectPath),i=s(o),n={...e.demo?function(e){try{return r(e).evalCase}catch{throw Error(`未知 dbx check 示例:${e}。支持的示例: ${t.join(", ")}`)}}(e.demo):{},...e.query?{query:e.query}:{},...void 0!==e.maxStep?{max_step:e.maxStep}:{}};if(e.historyPath&&(n.history_messages=function(e){if(!x().existsSync(e))throw I("history_file_not_found",`未找到历史消息文件: ${e}`,"请检查 --history 路径;历史文件应为消息数组。");let t=function(e,t,r){try{return t.endsWith(".json")?JSON.parse(e):P.qg(e)}catch(e){throw I(`${r}_file_parse_failed`,`${r} 文件解析失败: ${e?.message||String(e)}`,`请检查 ${t} 的语法和缩进。`)}}(x().readFileSync(e,"utf8"),e,"history");if(!Array.isArray(t))throw I("history_file_invalid","历史消息文件必须是数组","请把 history 文件写成数组,例如 [{ role: USER, content: hello }]。");return t}(q(e.historyPath,o))),e.skillsDirectory?n.skills=M(q(e.skillsDirectory,o)):n.skills||(n.skills=M(i.skillDirectory)),e.manifestPath)n.manifest=E(q(e.manifestPath,o));else{var l;if(n.manifest&&((l=n.manifest).includes("/")||l.endsWith(".json")||l.endsWith(".yaml")||l.endsWith(".yml")))n.manifest=E(q(n.manifest,o));else if(!n.manifest){let e=i.manifestPath;x().existsSync(e)&&(n.manifest=E(e))}}if(e.mcpUrl&&(n.manifest=function(e,t){if("string"!=typeof e)return;if(!e.trim())return e;let r=P.Tp(e);return r.setIn(["mcp_server","end_point"],t),r.setIn(["mcp_server","mcp_config","protocol"],"Streamable"),r.toString()}(n.manifest,e.mcpUrl)),function(e){if(!e.query||"string"!=typeof e.query||!e.query.trim())throw I("query_required","dbx check 需要 query","请通过 --query 传入本轮用户问题。");if(!Array.isArray(e.skills)||0===e.skills.length||e.skills.some(e=>"string"!=typeof e))throw I("skill_required","dbx check 至少需要一个 Skill","请在项目 skill/ 中放置至少一个 SKILL.md,或通过 --skill 传入 Skill 目录。");if(!e.manifest||"string"!=typeof e.manifest)throw I("manifest_required","dbx check 需要 manifest YAML 文本或文件路径","请在项目 manifest.yaml 放置 Manifest,或通过 --manifest 传入路径。")}(n),n.history_messages=(n.history_messages??[]).map((e,t)=>{if(!e||"object"!=typeof e)throw I("history_message_invalid",`history_messages[${t}] 必须是对象`,"请把每条历史消息写成 { role: USER|ASSISTANT|TOOL, content: string }。");let r=String(e.role||"").toUpperCase();if(!A.has(r))throw I("history_message_role_invalid",`history_messages[${t}].role 必须为 USER、ASSISTANT 或 TOOL`,"请把 role 改成 USER、ASSISTANT 或 TOOL。");if("string"!=typeof e.content||!e.content.trim())throw I("history_message_content_invalid",`history_messages[${t}].content 必须是非空字符串`,"请为该历史消息补充非空 content。");return{role:r,content:e.content}}),n.max_step=n.max_step??15,!Number.isInteger(n.max_step)||n.max_step<=0)throw I("max_step_invalid","max_step 必须是正整数","请删除 max_step 使用默认值 15,或通过 --max-step 传入正整数。");return n}(e),a=await u(l.manifest,"compatible");if(!a.data?.success||!a.data.manifest)throw new F("manifest 校验失败",{code:"manifest_validation_failed",message:"manifest 校验失败",errors:a.data?.errors??[],warnings:a.data?.warnings??[],log_id:a.log_id});let _=function(e,t){if(!m(t))throw I("manifest_parse_result_missing","dbx check 需要 YAML 校验接口返回解析后的 manifest","请先确认后端 /yaml/verify 返回 data.manifest。");let r=m(t.mcp_server)?t.mcp_server:void 0,o=T(t.app_key),s=T(r?.end_point);if(!o)throw I("app_id_required","dbx check 需要 manifest AppID","请在 manifest.yaml 配置 app_key(该字段对外称 AppID)。");if(!s)throw I("mcp_url_required","dbx check 需要 manifest 中的 mcp_server.end_point","请在 manifest.yaml 配置 mcp_server.end_point。");return function(e,t,r){try{let t=new URL(e);if("http:"===t.protocol||"https:"===t.protocol)return}catch{}throw I(t,`${r} 必须是 http(s) URL: ${e}`,`请把 ${r} 配置为 http:// 或 https:// 开头的 MCP endpoint。`)}(s,"mcp_url_invalid","manifest.mcp_server.end_point"),{...e,app_key:o,app_name:T(t.name),mcp:{url:s,description:T(r?.description),headers:d(t)}}}(l,a.data.manifest),p=function(e){if(!m(e)){var t;let e;throw t="manifest 必须是已解析的对象",(e=Error(t)).details={code:"manifest_yaml_invalid",message:t,suggestion:"请先运行 `dbx check --file <manifest.yaml>`,确认后端能解析 manifest。"},e}let r=m(e.tools)?e.tools:{},o=m(e.entities)?e.entities:{},s={};for(let e of Object.values(o))if(m(e)&&m(e.tool_card_binding))for(let[t,r]of Object.entries(e.tool_card_binding))"string"==typeof r&&(s[t]=r);return{raw:e,appKey:"string"==typeof e.app_key?e.app_key:void 0,tools:r,entities:o,cardBindings:s}}(a.data.manifest),v={...(o=await g(_.mcp.url,_.app_key,_.mcp.headers).catch(e=>{var t,r,o;let s,i,n,l,a,c=(t=e,r=_.mcp.url,(a=(o=l=String(t?.message||t),i=(s=o.match(/<pre>([\s\S]*?)<\/pre>/i)?.[1])?s.replace(/<br\s*\/?>/gi,"\n").replace(/&nbsp;/g," ").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&"):o,(n=i.match(/(?:TypeError|ReferenceError|SyntaxError|Error):[^\n<]+/)?.[0])?n.trim():/HTTP 5\d\d/.test(o)?"MCP 服务器返回 HTTP 5xx":void 0))?{code:"mcp_server_internal_error",message:`MCP 服务器处理 initialize/tools/list 时发生内部错误: ${a}`,suggestion:"CLI 已连上 MCP server,但 MCP server 在 initialize 或 tools/list 内部报错。请查看 MCP server 终端日志和报错堆栈,优先修 server 代码。",details:{url:r,raw_error:l,server_error:a}}:{code:"mcp_unreachable",message:l,suggestion:"请先启动标准 MCP server,并确认 manifest.mcp_server.end_point 指向 CLI 当前运行环境可访问的 Streamable HTTP /mcp 或 SSE /sse 地址;不要求公网 URL。",details:{url:r,raw_error:l}});throw new F(`MCP server unreachable: ${_.mcp.url}`,c)})).tools,server_id:_.mcp.server_id||o.tools.server_id,name:_.mcp.name||o.tools.name,description:_.mcp.description||o.tools.description},S=[...function(e){let t=[],{evalCase:r,manifest:o,mcp:s}=e,i=new Set(s.tools.map(e=>e.name).filter(Boolean)),n=Object.keys(o.tools),l=new Set(n);if(o.appKey===r.app_key?t.push(K("manifest_app_id_match",`manifest AppID 与请求 AppID 一致(${r.app_key})`)):t.push(U("manifest_app_id_mismatch",`manifest AppID(${o.appKey||"-"})与请求 AppID(${r.app_key})不一致`,"请保持请求 AppID 与 manifest.app_key 一致;如果走特殊测试链路会改写 AppID,需要确认后端映射规则。")),s.tools.length>0){let e="sse"===s.protocol?"SSE /sse":"Streamable HTTP /mcp";t.push(K("mcp_tools_loaded",`MCP 通过 ${e} 提供了 ${s.tools.length} 个工具`))}else t.push(U("mcp_tools_empty","MCP 未提供任何工具","请检查标准 MCP tools/list 是否返回 tools。Streamable HTTP 传 /mcp,SSE 传 /sse。"));for(let e of n)i.has(e)||t.push(U("manifest_tool_missing_in_mcp",`manifest.tools 声明了 ${e},但 MCP 未提供此工具`,"请确保会出卡的 tool 同时存在于 MCP tools 与 manifest.tools。"));for(let e of r.expect?.tool_calls??[])l.has(e)||t.push(U("expected_tool_missing_in_manifest",`expect.tool_calls 声明了 ${e},但 manifest.tools 未声明此工具`,`请在 manifest.tools.${e} 中声明该工具;非出卡工具也需要配置 output.kind,例如 execution_result。`)),i.has(e)||t.push(U("expected_tool_missing_in_mcp",`expect.tool_calls 声明了 ${e},但 MCP 未提供此工具`,"请确认 MCP tools/list 返回了期望调用的工具,或修正内置 demo 的 expect.tool_calls。"));let a=Object.keys(o.cardBindings);if(a.length>0)t.push(K("card_binding_found",`已找到卡片绑定: ${a.map(e=>`${e} -> ${o.cardBindings[e]}`).join(", ")}`));else{var c,_;let e=(c=r,_=o,c.expect?.card||Object.values(_.tools).some(e=>m(e)&&m(e.output)&&"entities"===e.output.kind))?U:L;t.push(e("card_binding_missing","manifest.entities 中没有 tool_card_binding","如果期望出卡,请在对应 entity 下配置 tool_card_binding,例如 Taxi_order: tpl.taxi_order。"))}for(let[e,r]of Object.entries(o.entities))m(r)&&m(r.schema)&&0===Object.entries(r.schema).filter(([,e])=>m(e)&&!0===e.is_entity_id).length&&t.push(U("entity_id_missing",`manifest.entities.${e}.schema 中没有标记 is_entity_id 的字段`,"请为实体配置一个稳定主键字段,例如 product_id: { type: string, is_entity_id: true }。"));return t}({evalCase:_,manifest:p,mcp:v}),...function(e){let t=[];for(let r of e.tools){let e=f(r.input_schema_json);if(e)for(let o of function e(t,r){let o=[];if(!m(t))return o;for(let e of["exclusiveMinimum","exclusiveMaximum"]){let s=t[e];"number"==typeof s&&o.push({path:`${r}/${e}`,value:s,message:`${e} 为数值 ${s},但模拟器后端要求布尔值`,suggestion:"如果使用 zod,避免 z.number().positive()/min()/max() 生成数值型 exclusiveMinimum/exclusiveMaximum;可改为 z.coerce.number() 并在工具内部校验业务范围。"})}for(let[s,i]of Object.entries(t))m(i)&&o.push(...e(i,`${r}/${s}`)),Array.isArray(i)&&i.forEach((t,i)=>{o.push(...e(t,`${r}/${s}/${i}`))});return o}(e,`tools/${r.name}/inputSchema`))t.push({code:"mcp_tool_schema_incompatible",level:"error",message:`MCP 工具 ${r.name} 的 inputSchema 不兼容: ${o.message}`,suggestion:o.suggestion,details:{tool_name:r.name,path:o.path,value:o.value}})}return t}(v)],$=e.gatewayOrigin||n(),w={evalCase:_,manifest:p,preflight:S,gatewayOrigin:$,cardExpectation:e.cardExpectation};if(!e.force&&S.some(e=>"error"===e.level))return O({...w,result:R()});try{i=await y({evalCase:_,manifestYAML:_.manifest,mcp:v,gatewayOrigin:$,callbacks:{onToolCall:async(e,t)=>{var r,s;return o.callTool((r=_,s=e,{request_id:t,app_key:s.app_key||r.app_key,server_id:s.server_id||r.mcp?.server_id||"",tool_call_id:s.tool_call_id,tool_name:s.tool_name,arguments:f(s.arguments_json)||{},arguments_json:s.arguments_json||"{}"}))}}})}catch(e){if(e instanceof h)return O({...w,result:D(e.state,[H(e)])});return O({...w,result:{...R(),log_id:c(e,"logId")||c(e,"log_id"),stream_errors:[H(e)]}})}return O({...w,result:D(i)})}finally{o?.close()}}function R(){return{request_id:"",tool_calls:[],cards:[],answer:"",trace_events:[],stream_errors:[]}}function D(e,t=[]){return{request_id:e.requestID,log_id:e.logID,trace_id:e.traceID,tool_calls:e.toolCalls.map(e=>{var t;return{tool_name:e.toolCall.tool_name,tool_call_id:e.toolCall.tool_call_id,app_key:e.toolCall.app_key,server_id:e.toolCall.server_id,arguments:f(e.toolCall.arguments_json)??e.toolCall.arguments_json,report_code:"number"==typeof e.report?.code?e.report.code:void 0,report_message:"string"==typeof e.report?.message?e.report.message:void 0,result_error:e.result?.is_error,result_preview:(t=e.result?.raw_result_text||e.result?.content||"").length>240?`${t.slice(0,240)}...`:t}}),cards:e.cards,answer:e.answer,trace_events:e.traceEvents,stream_errors:[...e.streamErrors,...t]}}function H(e){var t;let r=e instanceof Error?e.message:String(e);return{code:c(e,"code")||"simulator_eval_runtime_error",level:"error",message:r,suggestion:(t=r).includes("fetch failed")||t.includes("ECONNREFUSED")||t.includes("ENOTFOUND")||t.includes("timed out")||t.includes("超时")?"无法连接 Simulator gateway。请检查 --gateway-origin、网络/PPE 泳道、登录环境和代理配置。":t.includes("HTTP 400")||t.includes("HTTP 422")?"请求被 gateway 或 agent 拒绝。请检查 manifest YAML、mcp tools、AppID 和 query 是否匹配;可加 --verbose 查看更多 trace。":t.includes("HTTP 5")?"Simulator 服务端异常。请保留 log_id/request_id 给服务端排查。":t.includes("tool report failed")||t.includes("工具结果上报失败")?"工具结果上报失败。请检查 MCP 返回的 structuredContent/entities 是否符合 manifest 声明。":void 0,details:m(e)?{...e,message:r}:r}}class F extends Error{details;constructor(e,t){super(e),this.details=t}}let Y={runSimulator:N,startDemoServer:o,validateFile:Q};function z(){return new _("check").description("校验配置文件或检查 Agentic Service Simulator 链路").option("--file <file>","校验 manifest.yaml 或 business-templates.yaml").option("--project <path>","dbx 项目路径;相对路径参数会基于该目录解析",".").addOption(new a("--demo <name>","运行内置示例").choices([...t])).option("--query <query>","当前轮用户输入").option("--history <path>","历史消息文件,支持 JSON/YAML 数组").option("--skill <path>","Skill 目录路径;显式目录优先,相对路径按 --project 解析;未传默认 skill/,递归加载所有 SKILL.md").option("--manifest <path>","Manifest YAML 文件路径;默认按项目布局自动解析").option("--gateway-origin <url>","模拟器网关地址;默认使用 CLI 构建配置中的 apiBaseUrl").addOption(new a("--max-step <count>","Agent 最大循环步数").argParser(l)).addOption(new a("--expect-card <expectation>","当前评测是否期望出卡;required 要求至少一张卡,none 要求不出卡,auto 使用默认诊断").choices(["auto","required","none"]).default("auto")).option("--force","即使预检查发现配置错误也继续请求模拟器",!1).option("--verbose","输出更多执行轨迹和工具结果摘要",!1).action(async(e,t)=>S(t,t=>J({...e,verbose:t.verbose},t)))}async function J(e,t,r=Y){let o;if(e.file){var s;return((s=e).demo||s.query||s.history||s.skill||s.manifest||s.gatewayOrigin||void 0!==s.maxStep||s.force||"auto"!==s.expectCard)&&t.error("--file 不能与模拟器检查选项同时使用"),r.validateFile(t,(0,b.resolve)(e.project,e.file))}e.demo||e.query||t.error('check 需要指定 --file、--demo 或 --query。示例: dbx check --file manifest.yaml; dbx check --demo taxi; dbx check --query "..."');try{return e.demo&&(o=await r.startDemoServer({demo:e.demo,host:"127.0.0.1",port:0,log:t.log})),await B(t,e,r.runSimulator,o?.streamableUrl)}finally{if(o)try{await o.close()}catch(e){t.warn(`停止示例 MCP 服务失败:${String(e)}`)}}}async function B(e,t,r,o){let s;try{e.targetAppId=(s=await r({projectPath:t.project,demo:t.demo,mcpUrl:o,query:t.query,historyPath:t.history,skillsDirectory:t.skill,manifestPath:t.manifest,gatewayOrigin:t.gatewayOrigin,maxStep:t.maxStep,cardExpectation:t.expectCard,force:t.force,verbose:t.verbose})).case.app_key}catch(l){var i,n;let t,r,o;if(e.json)throw l;let s=(t=m(i=l)?i.details:void 0,{code:c(r=m(t)?t:void 0,"code"),message:c(r,"message")||(i instanceof Error&&i.message?i.message:String(i)),suggestion:c(r,"suggestion"),logId:c(r,"log_id")||c(r,"logId")||c(i,"log_id")||c(i,"logId"),details:t});throw new v((o=["Agentic Service 检查失败,未能运行诊断","","错误",...(n=s).code?[`- 错误码:${n.code}`]:[],`- 错误信息:${n.message}`,...n.logId?[`- log_id: ${n.logId}`]:[],...n.suggestion?[`- 修复建议:${n.suggestion}`]:[]],void 0!==n.details&&o.push("","详细信息",W(n.details)),o.join("\n")),{details:s.details,logId:s.logId})}if(e.json||function(e,t,r){let o=t.ok?$.green("通过"):$.red("未通过");if(e.log(`${$.bold("Agentic Service 检查")} ${o}`),e.log(""),e.log($.bold("输入")),e.log(`- app_id: ${t.case.app_key}`),e.log(`- 用户输入:${t.context.query}`),e.log(`- 历史消息数:${t.context.history_count}`),e.log(`- MCP 地址:${t.context.mcp_url||"-"}`),e.log(`- 网关地址:${t.context.gateway_origin||"-"}`),e.log(`- 最大步数:${t.context.max_step??"-"}`),e.log(`- 请求 ID:${t.request_id||"-"}`),e.log(`- log_id: ${t.log_id||"-"}`),e.log(""),G(e,"预检查",t.preflight,r),e.log(""),e.log($.bold("Agent Flow")),0===t.tool_calls.length?e.log("- 未调用工具"):t.tool_calls.forEach((t,o)=>{e.log(`${o+1}. ${$.cyan(t.tool_name)} ${0===t.report_code?$.green("已上报"):$.yellow(`上报状态码=${t.report_code??"-"}`)}`),e.log(` 工具调用 ID:${t.tool_call_id}`),t.app_key&&e.log(` app_id: ${t.app_key}`),e.log(` 参数:${JSON.stringify(t.arguments??{})}`),r&&t.result_preview&&e.log(` 结果:${t.result_preview}`)}),e.log(""),e.log($.bold("卡片")),0===t.cards.length?e.log("- 未输出卡片"):t.cards.forEach((t,r)=>{e.log(`${r+1}. 组件 ID=${t.widget_id||"-"} 实体 ID=${t.entity_id||"-"} 模板=${t.template||"-"}`)}),e.log(""),t.answer&&(e.log($.bold("回复")),e.log(t.answer),e.log("")),r&&t.trace_events.length>0){for(let r of(e.log($.bold("执行轨迹")),t.trace_events))e.log(`- ${r.name||"-"} ${r.status||"-"} ${r.tool_name||""} ${r.summary||""}`);e.log("")}G(e,"诊断结果",t.errors,r),e.log(""),e.log(`${$.bold("结论")}: ${o}`)}(e,s,t.verbose),!s.ok)throw new v("检查失败",{json:s,logId:s.log_id});return s}function W(e){return"string"==typeof e?e:JSON.stringify(e,null,2)}function G(e,t,r,o){if(e.log($.bold(t)),0===r.length)return void e.log("- 无");for(let t of r){let r="error"===t.level?$.red("✗"):"warn"===t.level?$.yellow("!"):$.green("✓");e.log(`${r} ${t.code}: ${t.message}`),t.suggestion&&e.log(` 修复建议:${t.suggestion}`),o&&void 0!==t.details&&e.log(` 详细信息:${W(t.details)}`)}}async function Q(e,t){(0,C.existsSync)(t)&&(0,C.statSync)(t).isFile()||e.error(`未找到 YAML 文件:${t}`);let r=V(t,e),o=(0,C.readFileSync)(t,"utf8"),s=await u(o,"compatible",r),i=s.data,n={valid:!!i?.success,manifest:i?.manifest,errors:p(i?.errors??[]),warnings:p(i?.warnings??[]),log_id:s.log_id??""};if("manifest"===r&&m(n.manifest)&&"string"==typeof n.manifest.app_key&&(e.targetAppId=n.manifest.app_key.trim()||void 0),e.log(`${r} 校验:${n.valid?"通过":"失败"}`),e.log(JSON.stringify(n,null,2)),!n.valid)throw new v(`${r} 校验失败`,{json:n,logId:n.log_id});return n}function V(e,t){switch((0,b.basename)(e).toLowerCase()){case"manifest.yaml":return"manifest";case"business-templates.yaml":return"business_templates";default:t.error(`无法根据文件名“${(0,b.basename)(e)}”确定 YAML 类型,请使用 manifest.yaml 或 business-templates.yaml。`)}}export{w as check_namespaceObject};
@@ -1,2 +1,2 @@
1
- import"node:module";import{__webpack_require__ as e}from"./rslib-runtime~0.js";import"./9652~0.js";import"./yaml.js";import{isRecord as t}from"./4315~0.js";import{GatewayResponseError as s,verifyYAML as i}from"./app.js";import"./2168~0.js";import{resolveProjectLayout as r,resolveRuntimeSkillLayout as a}from"./project-layout.js";import{precheckBusinessTemplatesPersonalInformation as n}from"./business-template-personal-information.js";import{readAppManifest as o}from"./manifest-yaml-generator.js";function l(e){if(t(e))switch(e.code){case"NOT_LOGGED_IN":return"尚未登录豆包开发者平台,请运行 `dbx auth login` 后重试。";case"TOKEN_EXPIRED":return"豆包开发者平台登录已过期,请运行 `dbx auth login` 后重试。";default:return}}class d extends Error{exitCode=1;logId;details;constructor(e){let t,s;super((s=(t=e.errors[0])?`: ${t.message}`:"",`dbx dev Manifest 校验失败${s}`)),this.name="DevManifestValidationError",this.logId=e.log_id;let{manifest:i,...r}=e;this.details=r}}class m extends Error{exitCode=1;logId;details;constructor(e){let t=e.errors[0],s=t?`: ${t.message}`:"";super(`dbx dev 业务模板校验失败${s}`),this.name="DevBusinessTemplatesValidationError",this.logId=e.log_id;let{manifest:i,...r}=e;this.details=r}}let f={"dev.manifest.parse_failed":e=>`Manifest 无法解析:${e.path??"未知路径"};将跳过模拟器的 Manifest 配置并继续启动`,"dev.manifest.invalid_root":e=>`Manifest 内容必须是对象:${e.path??"未知路径"};将跳过模拟器的 Manifest 配置并继续启动`,"dev.manifest.app_key_missing":e=>`Manifest 未配置 app_key:${e.path??"未知路径"};将由 Kit 从前端工程配置解析 AppID`,"dev.manifest.not_found":e=>`未找到 Manifest 文件:${e.path??"未知路径"};将跳过模拟器的 Manifest 配置并继续启动`,"dev.manifest.validation_failed":e=>`Manifest 校验未通过${e.message?`:${e.message}`:""}`,"dev.manifest.validation_http_error":e=>{var t,s;return`Manifest 校验服务异常${void 0===(t=e.httpStatus)?"":`(HTTP ${t})`}${(s=e.logId)?`,log_id: ${s}`:""}`},"dev.manifest.validation_service_error":e=>{var t;return`${e.message??"Manifest 校验服务返回错误"}${void 0===(t=e.serviceCode)?"":`(错误码 ${t})`}`}};function p(e){if(0!==e.length)return`启动提醒:${e.map(c).join(";")}`}function c(e){let t=f[e.code];return t?t(e):e.message?e.message:`${e.source} 警告(${e.code})`}let u=e("node:fs"),_=e("node:path"),v=e("../../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/index.js"),h="DOUBAO_SIMULATOR_MCP_ENDPOINT";function g(e){if(!Object.prototype.hasOwnProperty.call(e??{},"permissions"))return;let s=e?.permissions;return t(s)?Object.values(s).filter(t).flatMap(e=>{let t=e.scope_name,s=e.description;return"string"==typeof t&&"string"==typeof s?[{scope_name:t,description:s}]:[]}):[]}async function S(e,s){let i,r=u.readFileSync(e,"utf8");if(!r.trim())throw Error(`business-templates.yaml 内容为空:${e}`);try{i=v.qg(r)}catch(s){let t=s instanceof Error?s.message:String(s);throw Error(`business-templates.yaml 无效:${e}: ${t}`)}if(!t(i))throw Error(`business-templates.yaml 内容必须是对象:${e}`);await w(e);let a=n(s,i);return{file:e,validated:!0,warnings:a?[a]:[]}}async function y(e){let i;try{i=v.qg(u.readFileSync(e,"utf8"))}catch{return{usable:!1,warnings:[{code:"dev.manifest.parse_failed",source:"manifest",path:e}]}}if(!t(i))return{usable:!1,warnings:[{code:"dev.manifest.invalid_root",source:"manifest",path:e}]};let r=[],a="string"==typeof i.app_key?i.app_key.trim():void 0;a||r.push({code:"dev.manifest.app_key_missing",source:"manifest",path:e});let n=i;try{n=v.qg(o(e));let s=await E(e);t(s.manifest)&&(n=s.manifest)}catch(e){r.push(function(e){var t;let i=l(e);if(i)return{code:"dev.manifest.auth_failed",source:"manifest",message:i};if(e instanceof s)return{code:void 0!==e.httpStatus?"dev.manifest.validation_http_error":"dev.manifest.validation_service_error",source:"manifest",serviceCode:e.serviceCode,httpStatus:e.httpStatus,message:e.serviceMessage,logId:e.logId};let r=e instanceof d?e.details.errors[0]:void 0;return r?{source:"manifest",code:r.code,path:r.path,message:r.message}:{code:"dev.manifest.validation_failed",source:"manifest",message:(t=e)instanceof Error?t.message:String(t)}}(e))}return{...a?{appId:a}:{},manifest:n,usable:!0,warnings:r}}function M(e){let t=r(e.projectPath),s=e.manifest?.trim(),i=s?b(e.projectPath,s):t.manifestPath,n=e.skill,o=void 0!==n?b(e.projectPath,n):t.skillDirectory,l=[],d=[],m=u.existsSync(i),f=_.join(_.dirname(i),"business-templates.yaml"),p=u.existsSync(f),c=void 0!==n?a(o):t.skillResolution;if(m?u.statSync(i).isFile()||l.push(`Manifest 路径必须指向文件:${i}`):d.push({code:"dev.manifest.not_found",source:"manifest",path:i}),p&&!u.statSync(f).isFile()&&l.push(`业务模板路径必须指向文件:${f}`),void 0!==n&&"missing"===c.layout?l.push(`Skill 目录中未找到运行时 Skill:${o}; 请在所选目录或其子目录中添加至少一个名为 SKILL.md 的普通文件`):"invalid"===c.layout&&l.push(c.error??`Skill 目录结构无效:${o}`),l.length>0)throw Error(`dbx dev 路径检查失败:
2
- ${l.join("\n")}`);return{...p?{businessTemplatesPath:f}:{},...m?{simulatorManifestPath:i}:{},..."resolved"===c.layout?{skillsDirectory:o}:{},warnings:d}}async function $(e=process.env,t,s,i){let r=t?.trim();if(r)return K(r,"--mcp-endpoint");let a=e[h]?.trim();return a?K(a,h):s?C(s,i):void 0}async function E(e){let t=await i(o(e),"compatible"),s=t.data,r={file:e,valid:!!s?.success,manifest:s?.manifest,errors:P(s?.errors??[]),warnings:P(s?.warnings??[]),log_id:t.log_id??""};if(!r.valid)throw new d(r);return r}async function w(e){let t=await i(u.readFileSync(e,"utf8"),"compatible","business_templates"),s=t.data,r={file:e,valid:!!s?.success,errors:P(s?.errors??[]),warnings:P(s?.warnings??[]),log_id:t.log_id??""};if(!r.valid)throw new m(r);return r}async function C(e,s){let i=s??(await E(e)).manifest,r=t(i)&&t(i.mcp_server)?i.mcp_server:void 0,a=r?.end_point;if("string"==typeof a&&a.trim())return K(a.trim(),"manifest.mcp_server.end_point")}function P(e){return e.map(e=>({code:e.code,path:e.path,message:e.message}))}function K(e,t){let s=URL.parse(e);if(s?.protocol==="http:"||s?.protocol==="https:")return e;throw Error(`dbx dev ${t} 必须是 HTTP 或 HTTPS 地址:${e}`)}function b(e,t){let s=t.trim();if(!s)throw Error("路径不能为空");return _.resolve(e,s)}export{g as extractDevPermissions,p as formatFinalDevWarnings,l as getAuthErrorMessage,S as prepareDevBusinessTemplates,y as prepareDevManifest,$ as resolveDevMcpEndpoint,M as resolveDevSimulatorPaths,E as validateDevManifest};
1
+ import"node:module";import{__webpack_require__ as e}from"./rslib-runtime~0.js";import"./9652~0.js";import"./yaml.js";import{isRecord as t}from"./4315~0.js";import{GatewayResponseError as s,verifyYAML as i}from"./app.js";import"./2168~0.js";import{resolveProjectLayout as r,resolveRuntimeSkillLayout as a}from"./project-layout.js";import{precheckBusinessTemplatesPersonalInformation as n}from"./business-template-personal-information.js";function o(e){if(t(e))switch(e.code){case"NOT_LOGGED_IN":return"尚未登录豆包开发者平台,请运行 `dbx auth login` 后重试。";case"TOKEN_EXPIRED":return"豆包开发者平台登录已过期,请运行 `dbx auth login` 后重试。";default:return}}class l extends Error{exitCode=1;logId;details;constructor(e){let t,s;super((s=(t=e.errors[0])?`: ${t.message}`:"",`dbx dev Manifest 校验失败${s}`)),this.name="DevManifestValidationError",this.logId=e.log_id;let{manifest:i,...r}=e;this.details=r}}class d extends Error{exitCode=1;logId;details;constructor(e){let t=e.errors[0],s=t?`: ${t.message}`:"";super(`dbx dev 业务模板校验失败${s}`),this.name="DevBusinessTemplatesValidationError",this.logId=e.log_id;let{manifest:i,...r}=e;this.details=r}}let m={"dev.manifest.parse_failed":e=>`Manifest 无法解析:${e.path??"未知路径"};将跳过模拟器的 Manifest 配置并继续启动`,"dev.manifest.invalid_root":e=>`Manifest 内容必须是对象:${e.path??"未知路径"};将跳过模拟器的 Manifest 配置并继续启动`,"dev.manifest.app_key_missing":e=>`Manifest 未配置 app_key:${e.path??"未知路径"};将由 Kit 从前端工程配置解析 AppID`,"dev.manifest.not_found":e=>`未找到 Manifest 文件:${e.path??"未知路径"};将跳过模拟器的 Manifest 配置并继续启动`,"dev.manifest.validation_failed":e=>`Manifest 校验未通过${e.message?`:${e.message}`:""}`,"dev.manifest.validation_http_error":e=>{var t,s;return`Manifest 校验服务异常${void 0===(t=e.httpStatus)?"":`(HTTP ${t})`}${(s=e.logId)?`,log_id: ${s}`:""}`},"dev.manifest.validation_service_error":e=>{var t;return`${e.message??"Manifest 校验服务返回错误"}${void 0===(t=e.serviceCode)?"":`(错误码 ${t})`}`}};function f(e){if(0!==e.length)return`启动提醒:${e.map(c).join(";")}`}function c(e){let t=m[e.code];return t?t(e):e.message?e.message:`${e.source} 警告(${e.code})`}let p=e("node:fs"),u=e("node:path"),_=e("../../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/index.js"),v="DOUBAO_SIMULATOR_MCP_ENDPOINT";function h(e){if(!Object.prototype.hasOwnProperty.call(e??{},"permissions"))return;let s=e?.permissions;return t(s)?Object.values(s).filter(t).flatMap(e=>{let t=e.scope_name,s=e.description;return"string"==typeof t&&"string"==typeof s?[{scope_name:t,description:s}]:[]}):[]}async function g(e,s){let i,r=p.readFileSync(e,"utf8");if(!r.trim())throw Error(`business-templates.yaml 内容为空:${e}`);try{i=_.qg(r)}catch(s){let t=s instanceof Error?s.message:String(s);throw Error(`business-templates.yaml 无效:${e}: ${t}`)}if(!t(i))throw Error(`business-templates.yaml 内容必须是对象:${e}`);await E(e);let a=n(s,i);return{file:e,validated:!0,warnings:a?[a]:[]}}async function y(e){let i;try{i=_.qg(p.readFileSync(e,"utf8"))}catch{return{usable:!1,warnings:[{code:"dev.manifest.parse_failed",source:"manifest",path:e}]}}if(!t(i))return{usable:!1,warnings:[{code:"dev.manifest.invalid_root",source:"manifest",path:e}]};let r=[],a="string"==typeof i.app_key?i.app_key.trim():void 0;a||r.push({code:"dev.manifest.app_key_missing",source:"manifest",path:e});let n=i;try{let s=await M(e);t(s.manifest)&&(n=s.manifest)}catch(e){r.push(function(e){var t;let i=o(e);if(i)return{code:"dev.manifest.auth_failed",source:"manifest",message:i};if(e instanceof s)return{code:void 0!==e.httpStatus?"dev.manifest.validation_http_error":"dev.manifest.validation_service_error",source:"manifest",serviceCode:e.serviceCode,httpStatus:e.httpStatus,message:e.serviceMessage,logId:e.logId};let r=e instanceof l?e.details.errors[0]:void 0;return r?{source:"manifest",code:r.code,path:r.path,message:r.message}:{code:"dev.manifest.validation_failed",source:"manifest",message:(t=e)instanceof Error?t.message:String(t)}}(e))}return{...a?{appId:a}:{},manifest:n,usable:!0,warnings:r}}function S(e){let t=r(e.projectPath),s=e.manifest?.trim(),i=s?b(e.projectPath,s):t.manifestPath,n=e.skill,o=void 0!==n?b(e.projectPath,n):t.skillDirectory,l=[],d=[],m=p.existsSync(i),f=u.join(u.dirname(i),"business-templates.yaml"),c=p.existsSync(f),_=void 0!==n?a(o):t.skillResolution;if(m?p.statSync(i).isFile()||l.push(`Manifest 路径必须指向文件:${i}`):d.push({code:"dev.manifest.not_found",source:"manifest",path:i}),c&&!p.statSync(f).isFile()&&l.push(`业务模板路径必须指向文件:${f}`),void 0!==n&&"missing"===_.layout?l.push(`Skill 目录中未找到运行时 Skill:${o}; 请在所选目录或其子目录中添加至少一个名为 SKILL.md 的普通文件`):"invalid"===_.layout&&l.push(_.error??`Skill 目录结构无效:${o}`),l.length>0)throw Error(`dbx dev 路径检查失败:
2
+ ${l.join("\n")}`);return{...c?{businessTemplatesPath:f}:{},...m?{simulatorManifestPath:i}:{},..."resolved"===_.layout?{skillsDirectory:o}:{},warnings:d}}async function $(e=process.env,t,s,i){let r=t?.trim();if(r)return C(r,"--mcp-endpoint");let a=e[v]?.trim();return a?C(a,v):s?w(s,i):void 0}async function M(e){let t=await i(p.readFileSync(e,"utf8"),"compatible"),s=t.data,r={file:e,valid:!!s?.success,manifest:s?.manifest,errors:P(s?.errors??[]),warnings:P(s?.warnings??[]),log_id:t.log_id??""};if(!r.valid)throw new l(r);return r}async function E(e){let t=await i(p.readFileSync(e,"utf8"),"compatible","business_templates"),s=t.data,r={file:e,valid:!!s?.success,errors:P(s?.errors??[]),warnings:P(s?.warnings??[]),log_id:t.log_id??""};if(!r.valid)throw new d(r);return r}async function w(e,s){let i=s??(await M(e)).manifest,r=t(i)&&t(i.mcp_server)?i.mcp_server:void 0,a=r?.end_point;if("string"==typeof a&&a.trim())return C(a.trim(),"manifest.mcp_server.end_point")}function P(e){return e.map(e=>({code:e.code,path:e.path,message:e.message}))}function C(e,t){let s=URL.parse(e);if(s?.protocol==="http:"||s?.protocol==="https:")return e;throw Error(`dbx dev ${t} 必须是 HTTP 或 HTTPS 地址:${e}`)}function b(e,t){let s=t.trim();if(!s)throw Error("路径不能为空");return u.resolve(e,s)}export{h as extractDevPermissions,f as formatFinalDevWarnings,o as getAuthErrorMessage,g as prepareDevBusinessTemplates,y as prepareDevManifest,$ as resolveDevMcpEndpoint,S as resolveDevSimulatorPaths,M as validateDevManifest};