@tbox.cn/app-cli 0.4.1 → 0.4.2

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 (2) hide show
  1. package/dist/index.js +52 -49
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,18 +1,21 @@
1
1
  #!/usr/bin/env node
2
- import{a as Ee,b as Pr,c as Re,d as Lr,e as Fr,f as _r,g as Nr,h as Vr,i as Jr,j as zr,k as Ur,l as Br,m as Hr,n as Wr,o as Kr,p as Ne,q as nt,r as Kt,s as z,t as ue}from"./chunk-GY4SXKTS.js";import{d as rt}from"./chunk-SGF4P5YN.js";import{Command as lp}from"commander";import{createRequire as pp}from"module";import{fileURLToPath as up}from"url";import{realpathSync as ui}from"fs";import{existsSync as Y,readdirSync as ct,realpathSync as at,statSync as Yt,chmodSync as bi}from"fs";import{appendFile as ki,cp as Xt,readFile as xi,rename as sn,writeFile as Si}from"fs/promises";import T from"path";function B(e){return Nr(e)}async function te(e,t){_r(e,t)}function Gr(e,t){return Vr(e,t)}function qr(e,t){return Jr(e,t)}function Xr(e,t){return zr(e,t)}function Yr(e,t,r){return Ur(e,t,r)}function ke(e,t){Br(e,t)}import{existsSync as di}from"fs";import{execFileSync as fi}from"child_process";import mi from"path";function De(e){if(!di(mi.join(e,"pnpm-lock.yaml")))return!1;try{return fi("pnpm",["install","--lockfile-only"],{cwd:e,stdio:"pipe",encoding:"utf8"}),!0}catch{return console.warn(" ⚠️ lockfile 刷新失败(pnpm install --lockfile-only)——请手动 pnpm install 后提交 pnpm-lock.yaml"),!1}}import{existsSync as ot,readFileSync as en,mkdtempSync as tn,rmSync as rn}from"fs";import{execFileSync as yi}from"child_process";import{tmpdir as it}from"os";import{readFile as hi,readdir as vi,stat as Tp}from"fs/promises";import K from"path";import{execFileSync as st}from"child_process";import Zr from"path";var Ve=null;function Gt(e){if(e?.startsWith("@tbox.cn/"))try{let r=st("pnpm",["config","get","@tbox.cn:registry"],{encoding:"utf8"}).trim().split(/\r?\n/).pop()??"";if(r)return r}catch{}if(Ve)return Ve;try{Ve=st("pnpm",["config","get","registry"],{encoding:"utf8"}).trim().split(/\r?\n/).pop()??"https://registry.npmjs.org/"}catch{Ve="https://registry.npmjs.org/"}return Ve}function Ce(e){return/^@[^/]+\/[^@/]+(@.+)?$/.test(e)}function gi(e){return e.replace(/@[^/]+$/,"")}function Qr(e,t,r){let n=r??Gt(gi(e)),s=["view",e,"dist.tarball"];r&&s.push("--registry",r);let o=st("pnpm",s,{encoding:"utf8"}).trim().split(/\r?\n/).pop()??"";if(!o)throw new Error(`registry 拉取失败:${e} 无 dist.tarball(registry=${n})`);let a=o.split("/").pop()??`${e.replace(/^@/,"").replace(/\//g,"-").split("@")[0]}.tgz`,c=Zr.join(Zr.resolve(t),a);return st("curl",["-fsSL","-o",c,o],{stdio:"ignore"}),c}var wi=new Set(["node_modules","dist","dist-ssr",".git",".tbox"]);async function nn(e,t,r){let n=await vi(e,{withFileTypes:!0});for(let s of n){let i=K.join(e,s.name),o=K.relative(t,i).split(K.sep).join("/");if(s.isDirectory()){if(wi.has(s.name))continue;await nn(i,t,r)}else s.isFile()&&r.push(o)}}var re=class{constructor(t){this.dir=t;this.name=K.basename(K.resolve(t))}dir;name;getDir(){return this.dir}async listFiles(){let t=[];return await nn(this.dir,this.dir,t),t.sort()}async readFile(t){return hi(K.join(this.dir,t),"utf8")}static isUsable(t){return ot(K.join(t,"package.json"))}resolveVersion(){return qt(this.dir).version}};function qt(e){let t;try{t=en(K.join(e,"package.json"),"utf8")}catch{return{version:"0.0.0"}}try{let r=JSON.parse(t);return{name:r?.name,version:r?.version??"0.0.0"}}catch{return{version:"0.0.0"}}}var de=class{constructor(t,r){this.spec=t;this.registry=r;this.name=t,this.packDir=tn(K.join(it(),"tbox-reg-"))}spec;registry;name;inner=null;packDir;resolvedName="";resolvedVersion="";resolve(){if(this.inner)return this.inner;let t=this.spec.replace(/@[^/]+$/,""),r=this.registry??Gt(t);console.log(`📦 从 registry 拉取 ${this.spec}(${r})`);let n=Qr(this.spec,this.packDir,this.registry);this.inner=new U(n);let s,i="";try{let o=JSON.parse(en(K.join(this.inner.getDir(),"package.json"),"utf8"));s=o.name,i=o.version??""}catch{}return this.resolvedName=s??this.spec,this.resolvedVersion=i,console.log(` → ${this.resolvedName}@${this.resolvedVersion}`),this.inner}listFiles(){return Promise.resolve(this.resolve()).then(t=>t.listFiles())}readFile(t){return Promise.resolve(this.resolve()).then(r=>r.readFile(t))}resolveVersion(){return this.resolve(),this.resolvedVersion}getDir(){return this.resolve().getDir()}get resolvedPackage(){return{name:this.resolvedName,version:this.resolvedVersion}}dispose(){this.inner&&this.inner.dispose();try{this.packDir.startsWith(it())&&rn(this.packDir,{recursive:!0,force:!0})}catch{}}};function fe(e,t){if(e.endsWith(".tgz")&&ot(e)){let r=new U(e);return{sourceDir:r.getDir(),source:r}}if(!ot(e)&&Ce(e)){let r=new de(e,t);return{sourceDir:r.getDir(),source:r}}return{sourceDir:e,source:new re(e)}}var U=class{name;inner;tmpRoot;constructor(t){let r=K.resolve(t);this.name=K.basename(r,".tgz"),this.tmpRoot=tn(K.join(it(),"tbox-tgz-")),yi("tar",["-xzf",r,"-C",this.tmpRoot],{stdio:"ignore"});let n=K.join(this.tmpRoot,"package");this.inner=new re(ot(n)?n:this.tmpRoot)}getDir(){return this.inner.getDir()}listFiles(){return this.inner.listFiles()}readFile(t){return this.inner.readFile(t)}resolveVersion(){return this.inner.resolveVersion()}dispose(){try{this.tmpRoot.startsWith(it())&&rn(this.tmpRoot,{recursive:!0,force:!0})}catch{}}};var $i=new Set(["node_modules","dist","dist-ssr",".git",".DS_Store"]),ji=new Set(["pnpm-lock.yaml"]),Ei="pnpm-workspace.template.yaml",on="pnpm-workspace.yaml",Ri="pnpm-lock.template.yaml",Di="pnpm-lock.yaml";function Ci(e,t){let r=ct(e).filter(o=>/^tbox\.cn-app-(sdk|toolkit|contracts)-.+\.tgz$/.test(o)).sort();if(r.length===0)return null;let n=at(t),s=new Set,i=[];for(let o of r){let a=o.replace(/^tbox\.cn-app-/,"").replace(/\.tgz$/,""),c=a.lastIndexOf("-"),l="@tbox.cn/app-"+a.slice(0,c);if(s.has(l))throw new Error(`--local-deps 目录含同一平台包多版本(overrides 重复 key 歧义,须单版本目录): ${l}`);s.add(l);let p=T.relative(n,at(T.join(e,o)));i.push(` ${JSON.stringify(l)}: ${JSON.stringify(`file:${p}`)}`)}return`
2
+ import{a as Ee,b as _r,c as Re,d as Nr,e as Vr,f as Jr,g as zr,h as Ur,i as Br,j as Wr,k as Hr,l as Kr,m as Gr,n as qr,o as Xr,p as Ne,q as nt,r as qt,s as z,t as ue}from"./chunk-GY4SXKTS.js";import{d as rt}from"./chunk-SGF4P5YN.js";import{Command as fp}from"commander";import{createRequire as mp}from"module";import{fileURLToPath as gp}from"url";import{realpathSync as gi}from"fs";import{existsSync as Y,readdirSync as pt,realpathSync as lt,statSync as er,chmodSync as $i}from"fs";import{appendFile as ji,cp as Qt,readFile as Ei,rename as ln,writeFile as Ri}from"fs/promises";import T from"path";function B(e){return zr(e)}async function te(e,t){Jr(e,t)}function Yr(e,t){return Ur(e,t)}function Zr(e,t){return Br(e,t)}function Qr(e,t){return Wr(e,t)}function en(e,t,r){return Hr(e,t,r)}function ke(e,t){Kr(e,t)}import{existsSync as st,readFileSync as Xt,writeFileSync as yi}from"fs";import{execFileSync as hi}from"child_process";import ot from"path";function De(e){if(!st(ot.join(e,"pnpm-lock.yaml")))return!1;try{return hi("pnpm",["install","--lockfile-only"],{cwd:e,stdio:"pipe",encoding:"utf8"}),!0}catch{return console.warn(" ⚠️ lockfile 刷新失败(pnpm install --lockfile-only)——请手动 pnpm install 后提交 pnpm-lock.yaml"),!1}}function tn(e){let t=ot.join(e,"pnpm-lock.yaml"),r=ot.join(e,"pnpm-workspace.yaml"),n=ot.join(e,"package.json");if(!st(t)||!st(r)||!st(n))return 0;try{let s=JSON.parse(Xt(n,"utf8")),i=new Map;for(let f of[s.dependencies,s.devDependencies,s.optionalDependencies])for(let[g,m]of Object.entries(f??{}))m!=="catalog:"&&!m.startsWith("workspace:")&&!m.startsWith("file:")&&i.set(g,m);if(i.size===0)return 0;let o=vi(Xt(r,"utf8")),a=Xt(t,"utf8").split(`
3
+ `),c=!1,l=!1,p=!1,u=null,d=0;for(let f=0;f<a.length;f++){let g=a[f];if(!g.trim()||g.startsWith("#"))continue;if(!/^ /.test(g)){c=/^importers:/.test(g),l=!1,p=!1,u=null;continue}if(!c)continue;if(/^ {2}\S/.test(g)){l=/^ {2}\.:\s*$/.test(g),p=!1,u=null;continue}if(!l)continue;if(/^ {4}\S/.test(g)){p=/^( {4})(dependencies|devDependencies|optionalDependencies):\s*$/.test(g),u=null;continue}if(!p)continue;let m=g.match(/^ {6}['"]?([^'":\s]+)['"]?:\s*$/);if(m){u=m[1];continue}if(g.match(/^ {8}specifier:\s*['"]?catalog:['"]?\s*$/)&&u){if(i.has(u)){let v=o.get(u);v!==void 0&&(a[f]=g.replace(/^( {8}specifier:\s*)['"]?catalog:['"]?(\s*)$/,`$1${v}$2`),d++)}u=null}}return d>0&&yi(t,a.join(`
4
+ `)),d}catch(s){return console.warn(` ⚠️ 携带锁 specifiers 对齐失败(降级跳过——frozen install 如失败请手动 pnpm install): ${s.message}`),-1}}function vi(e){let t=new Map,r=!1;for(let n of e.split(`
5
+ `)){let s=n.replace(/\r$/,"");if(!s.trim()||s.trimStart().startsWith("#"))continue;if(!/^ /.test(s)){r=/^catalog\s*:/.test(s);continue}if(!r)continue;let i=s.match(/^\s+["']?([^"':#\s]+)["']?\s*:\s*(.+?)\s*(?:#.*)?$/);i&&t.set(i[1],i[2].replace(/^['"]|['"]$/g,""))}return t}import{existsSync as at,readFileSync as sn,mkdtempSync as on,rmSync as an}from"fs";import{execFileSync as bi}from"child_process";import{tmpdir as ct}from"os";import{readFile as ki,readdir as xi,stat as Op}from"fs/promises";import K from"path";import{execFileSync as it}from"child_process";import rn from"path";var Ve=null;function Yt(e){if(e?.startsWith("@tbox.cn/"))try{let r=it("pnpm",["config","get","@tbox.cn:registry"],{encoding:"utf8"}).trim().split(/\r?\n/).pop()??"";if(r)return r}catch{}if(Ve)return Ve;try{Ve=it("pnpm",["config","get","registry"],{encoding:"utf8"}).trim().split(/\r?\n/).pop()??"https://registry.npmjs.org/"}catch{Ve="https://registry.npmjs.org/"}return Ve}function Ce(e){return/^@[^/]+\/[^@/]+(@.+)?$/.test(e)}function wi(e){return e.replace(/@[^/]+$/,"")}function nn(e,t,r){let n=r??Yt(wi(e)),s=["view",e,"dist.tarball"];r&&s.push("--registry",r);let o=it("pnpm",s,{encoding:"utf8"}).trim().split(/\r?\n/).pop()??"";if(!o)throw new Error(`registry 拉取失败:${e} 无 dist.tarball(registry=${n})`);let a=o.split("/").pop()??`${e.replace(/^@/,"").replace(/\//g,"-").split("@")[0]}.tgz`,c=rn.join(rn.resolve(t),a);return it("curl",["-fsSL","-o",c,o],{stdio:"ignore"}),c}var Si=new Set(["node_modules","dist","dist-ssr",".git",".tbox"]);async function cn(e,t,r){let n=await xi(e,{withFileTypes:!0});for(let s of n){let i=K.join(e,s.name),o=K.relative(t,i).split(K.sep).join("/");if(s.isDirectory()){if(Si.has(s.name))continue;await cn(i,t,r)}else s.isFile()&&r.push(o)}}var re=class{constructor(t){this.dir=t;this.name=K.basename(K.resolve(t))}dir;name;getDir(){return this.dir}async listFiles(){let t=[];return await cn(this.dir,this.dir,t),t.sort()}async readFile(t){return ki(K.join(this.dir,t),"utf8")}static isUsable(t){return at(K.join(t,"package.json"))}resolveVersion(){return Zt(this.dir).version}};function Zt(e){let t;try{t=sn(K.join(e,"package.json"),"utf8")}catch{return{version:"0.0.0"}}try{let r=JSON.parse(t);return{name:r?.name,version:r?.version??"0.0.0"}}catch{return{version:"0.0.0"}}}var de=class{constructor(t,r){this.spec=t;this.registry=r;this.name=t,this.packDir=on(K.join(ct(),"tbox-reg-"))}spec;registry;name;inner=null;packDir;resolvedName="";resolvedVersion="";resolve(){if(this.inner)return this.inner;let t=this.spec.replace(/@[^/]+$/,""),r=this.registry??Yt(t);console.log(`📦 从 registry 拉取 ${this.spec}(${r})`);let n=nn(this.spec,this.packDir,this.registry);this.inner=new U(n);let s,i="";try{let o=JSON.parse(sn(K.join(this.inner.getDir(),"package.json"),"utf8"));s=o.name,i=o.version??""}catch{}return this.resolvedName=s??this.spec,this.resolvedVersion=i,console.log(` → ${this.resolvedName}@${this.resolvedVersion}`),this.inner}listFiles(){return Promise.resolve(this.resolve()).then(t=>t.listFiles())}readFile(t){return Promise.resolve(this.resolve()).then(r=>r.readFile(t))}resolveVersion(){return this.resolve(),this.resolvedVersion}getDir(){return this.resolve().getDir()}get resolvedPackage(){return{name:this.resolvedName,version:this.resolvedVersion}}dispose(){this.inner&&this.inner.dispose();try{this.packDir.startsWith(ct())&&an(this.packDir,{recursive:!0,force:!0})}catch{}}};function fe(e,t){if(e.endsWith(".tgz")&&at(e)){let r=new U(e);return{sourceDir:r.getDir(),source:r}}if(!at(e)&&Ce(e)){let r=new de(e,t);return{sourceDir:r.getDir(),source:r}}return{sourceDir:e,source:new re(e)}}var U=class{name;inner;tmpRoot;constructor(t){let r=K.resolve(t);this.name=K.basename(r,".tgz"),this.tmpRoot=on(K.join(ct(),"tbox-tgz-")),bi("tar",["-xzf",r,"-C",this.tmpRoot],{stdio:"ignore"});let n=K.join(this.tmpRoot,"package");this.inner=new re(at(n)?n:this.tmpRoot)}getDir(){return this.inner.getDir()}listFiles(){return this.inner.listFiles()}readFile(t){return this.inner.readFile(t)}resolveVersion(){return this.inner.resolveVersion()}dispose(){try{this.tmpRoot.startsWith(ct())&&an(this.tmpRoot,{recursive:!0,force:!0})}catch{}}};var Di=new Set(["node_modules","dist","dist-ssr",".git",".DS_Store"]),Ci=new Set(["pnpm-lock.yaml"]),Ti="pnpm-workspace.template.yaml",pn="pnpm-workspace.yaml",Mi="pnpm-lock.template.yaml",Ii="pnpm-lock.yaml";function Ai(e,t){let r=pt(e).filter(o=>/^tbox\.cn-app-(sdk|toolkit|contracts)-.+\.tgz$/.test(o)).sort();if(r.length===0)return null;let n=lt(t),s=new Set,i=[];for(let o of r){let a=o.replace(/^tbox\.cn-app-/,"").replace(/\.tgz$/,""),c=a.lastIndexOf("-"),l="@tbox.cn/app-"+a.slice(0,c);if(s.has(l))throw new Error(`--local-deps 目录含同一平台包多版本(overrides 重复 key 歧义,须单版本目录): ${l}`);s.add(l);let p=T.relative(n,lt(T.join(e,o)));i.push(` ${JSON.stringify(l)}: ${JSON.stringify(`file:${p}`)}`)}return`
3
6
  # create --local-deps 注入:平台包经 file: 本地发布态 tgz 消费(005 v0.4.0 验证态;生产 B 档移除本块走 registry)
4
7
  overrides:
5
8
  `+i.join(`
6
9
  `)+`
7
- `}function Ti(e){let t=ct(e).filter(n=>/^tbox\.cn-app-(sdk|contracts)-.+\.tgz$/.test(n));if(t.length===0)throw new Error(`--local-deps 目录无平台包产物(缺 sdk/contracts tgz): ${e}`);let r=new Set;for(let n of t){let s=n.replace(/^tbox\.cn-app-/,"").replace(/\.tgz$/,""),i=s.lastIndexOf("-"),o="@tbox.cn/app-"+s.slice(0,i);if(r.has(o))throw new Error(`--local-deps 目录含同一平台包多版本(overrides 重复 key 歧义,须单版本目录): ${o}`);r.add(o)}}function an(e){let t=0;for(let r of ct(e,{withFileTypes:!0}))r.name===".DS_Store"||r.name==="node_modules"||(r.isDirectory()?t+=an(T.join(e,r.name)):t+=1);return t}function Mi(e){if(!Y(e)||!Yt(e).isDirectory())throw new Error(`--config-dir 不是目录: ${e}`);if(an(e)===0)throw new Error(`--config-dir 目录为空(无任何文件可合并): ${e}`)}var Ii=/^(?:@[a-z0-9._-]+\/)?[a-z0-9][a-z0-9._-]*$/;function Ai(e){let t=T.join(e,"scripts");if(!Y(t))return;function r(n){for(let s of ct(n,{withFileTypes:!0})){let i=T.join(n,s.name);s.isDirectory()?r(i):s.isFile()&&bi(i,493)}}r(t)}function Oi(e){if(!Ii.test(e))throw new Error(`应用包名无效: ${e}(需为 npm 包名;使用 --name 指定)`)}function Pi(e){return e===T.resolve(process.cwd())}function Li(e,t){let r=T.relative(e,t);return r!==""&&r!==".."&&!r.startsWith(`..${T.sep}`)&&!T.isAbsolute(r)}function Fi(e,t){if(!Y(e))return;let r=Yt(e),n=at(e),s=Y(t)?at(t):T.resolve(t);if(n===s||r.isDirectory()&&Li(n,s))throw new Error(`模板源与目标目录重合或目标位于模板源内,无法初始化: ${e}`)}async function cn(e){let t=T.resolve(process.cwd(),e.name),r=Y(t),n=Pi(t);if(r&&!Yt(t).isDirectory())throw new Error(`目标不是目录: ${e.name}`);if(r&&!n&&!e.force)throw new Error(`目录已存在: ${e.name}(加 --force 覆盖)`);if(n&&Y(T.join(t,".tbox","app.json"))&&!e.force)throw new Error("当前目录已有 tbox-app 应用(存在 .tbox/app.json;重新初始化请加 --force)");let s=e.appName??(n?T.basename(t):e.name);if(!s)throw new Error("无法从目标目录推导应用包名,请使用 --name 指定");e.appName&&Oi(s);let i=Array.isArray(e.configDir)?e.configDir:e.configDir?[e.configDir]:[],o=e.source,a=T.resolve(o),c=!Y(a)&&Ce(o),l=a.endsWith(".tgz");if(!c&&!l&&!re.isUsable(a))throw new Error(`模板源无效(缺 package.json): ${a}`);if(!c&&l&&!Y(a))throw new Error(`模板源无效(tgz 不存在): ${a}`);if(Fi(a,t),c&&e.localDeps)throw new Error("registry 源(--source @scope/pkg)与 --local-deps 互斥:registry 安装无需/不允许本地依赖注入");e.localDeps&&Ti(T.resolve(e.localDeps));for(let d of i)Mi(T.resolve(d));let p=fe(c?o:a,e.registry),u=p.sourceDir;try{let d=B(u);if(!d)throw new Error(`模板结构异常: ${a} 的 .tbox/app.json 缺失、损坏或缺少 templateVersion(出生版本)字段`);await Xt(u,t,{recursive:!0,force:!0,filter:S=>{let $=T.basename(S);return!(ji.has($)||$i.has($))}}),Ai(t);let f=T.join(t,Ei);Y(f)&&await sn(f,T.join(t,on));let g=T.join(t,Ri),m=Y(g);if(m&&await sn(g,T.join(t,Di)),e.localDeps){let S=Ci(T.resolve(e.localDeps),t);await ki(T.join(t,on),S,"utf8"),m&&De(t)}for(let S of i)await Xt(T.resolve(S),T.join(t,"config"),{recursive:!0,force:!0,filter:$=>T.basename($)!==".DS_Store"&&T.basename($)!=="node_modules"});e.envFile&&await Xt(T.resolve(e.envFile),T.join(t,"config","env.sh"),{force:!0});let h=T.join(t,"package.json");if(Y(h)){let S=JSON.parse(await xi(h,"utf8"));S.name=s,await Si(h,JSON.stringify(S,null,2)+`
8
- `,"utf8")}let v={templateVersion:d.templateVersion,npmModules:[]};await te(t,v),console.log(`✅ 已创建应用 ${s}`),console.log(c?` ⚡ 已从 registry 模板包 ${p.source.name} 展开(发布态)`:l?` ⚡ 已从模板包 ${T.basename(a)} 展开(发布态)`:" ⚡ 已从模板目录展开(本地开发源)"),e.localDeps?(console.log(` ⚡ 已注入平台 overrides(--local-deps: ${e.localDeps},install 离线消费本地发布态产物)`),m&&console.log(" 🔒 携带锁已增量刷新为 file: 形态(仅平台三包换形态,间接依赖保钉)——B 档移除 overrides 块后 plain install 回 registry 形态、frozen 恢复可用")):m&&console.log(" 🔒 依赖已由 pnpm-lock.yaml 冻结(直接+间接全精确)——请随应用提交,安装可 --frozen-lockfile"),i.length>0&&console.log(` ⚡ 已合并应用配置(--config-dir: ${i.join(" + ")} → config/)`),console.log(" ⚡ 已生成 pnpm-workspace.yaml(应用 workspace)"),console.log(n?" 下一步: pnpm install":` 下一步: cd ${e.name} && pnpm install`),console.log(" 📱 支付宝小程序壳: tbox-app miniapp-container init(web-view 承载 H5 + JSAPI 桥代理)"),console.log(" 🔐 鉴权(006): 生产请由平台注入 AUTH_TOKEN_SECRET 且确保 NODE_ENV=production(dev-login 强制关闭);"),console.log(" 本地开发默认开启 dev-login(非 production);如需关闭设 AUTH_DEV_LOGIN_DISABLED=true。")}finally{p.source instanceof U&&p.source.dispose()}}import{existsSync as ve,readFileSync as yr,readdirSync as sc}from"fs";import Q from"path";import{copyFile as Gi,mkdir as wt,rm as vn,writeFile as ne}from"fs/promises";import H from"path";import{existsSync as ze,readFileSync as dt}from"fs";import{readFile as pt,readdir as Vi,writeFile as Ji}from"fs/promises";import _ from"path";import V from"typescript";var _i=/^@tbox\.cn\/app-(?:sdk|toolkit|contracts(?:-|$))/,Ni=new Set(["@tbox.cn/app-contracts-mall"]);function lt(e){return _i.test(e)}function Je(e){return Ni.has(e)}var pn=["dependencies","optionalDependencies","peerDependencies","devDependencies"],zi=new Set(["name","version","private","exports"]),ft=/\.(?:ts|tsx|mts|cts|js|jsx|mjs|cjs)$/,Ui=new Set(["node_modules","dist",".git",".tbox"]),Bi=new Map([["@tbox.cn/app-contracts-mall",{exports:{".":{types:"./src/index.ts",import:"./src/runtime.ts"},"./server":{types:"./src/server/index.ts",import:"./src/server/index.ts"},"./package.json":"./package.json"},files:{"src/index.ts":`export * from '@tbox.cn/app-contracts-mall';
10
+ `}function Oi(e){let t=pt(e).filter(n=>/^tbox\.cn-app-(sdk|contracts)-.+\.tgz$/.test(n));if(t.length===0)throw new Error(`--local-deps 目录无平台包产物(缺 sdk/contracts tgz): ${e}`);let r=new Set;for(let n of t){let s=n.replace(/^tbox\.cn-app-/,"").replace(/\.tgz$/,""),i=s.lastIndexOf("-"),o="@tbox.cn/app-"+s.slice(0,i);if(r.has(o))throw new Error(`--local-deps 目录含同一平台包多版本(overrides 重复 key 歧义,须单版本目录): ${o}`);r.add(o)}}function un(e){let t=0;for(let r of pt(e,{withFileTypes:!0}))r.name===".DS_Store"||r.name==="node_modules"||(r.isDirectory()?t+=un(T.join(e,r.name)):t+=1);return t}function Pi(e){if(!Y(e)||!er(e).isDirectory())throw new Error(`--config-dir 不是目录: ${e}`);if(un(e)===0)throw new Error(`--config-dir 目录为空(无任何文件可合并): ${e}`)}var Li=/^(?:@[a-z0-9._-]+\/)?[a-z0-9][a-z0-9._-]*$/;function Fi(e){let t=T.join(e,"scripts");if(!Y(t))return;function r(n){for(let s of pt(n,{withFileTypes:!0})){let i=T.join(n,s.name);s.isDirectory()?r(i):s.isFile()&&$i(i,493)}}r(t)}function _i(e){if(!Li.test(e))throw new Error(`应用包名无效: ${e}(需为 npm 包名;使用 --name 指定)`)}function Ni(e){return e===T.resolve(process.cwd())}function Vi(e,t){let r=T.relative(e,t);return r!==""&&r!==".."&&!r.startsWith(`..${T.sep}`)&&!T.isAbsolute(r)}function Ji(e,t){if(!Y(e))return;let r=er(e),n=lt(e),s=Y(t)?lt(t):T.resolve(t);if(n===s||r.isDirectory()&&Vi(n,s))throw new Error(`模板源与目标目录重合或目标位于模板源内,无法初始化: ${e}`)}async function dn(e){let t=T.resolve(process.cwd(),e.name),r=Y(t),n=Ni(t);if(r&&!er(t).isDirectory())throw new Error(`目标不是目录: ${e.name}`);if(r&&!n&&!e.force)throw new Error(`目录已存在: ${e.name}(加 --force 覆盖)`);if(n&&Y(T.join(t,".tbox","app.json"))&&!e.force)throw new Error("当前目录已有 tbox-app 应用(存在 .tbox/app.json;重新初始化请加 --force)");let s=e.appName??(n?T.basename(t):e.name);if(!s)throw new Error("无法从目标目录推导应用包名,请使用 --name 指定");e.appName&&_i(s);let i=Array.isArray(e.configDir)?e.configDir:e.configDir?[e.configDir]:[],o=e.source,a=T.resolve(o),c=!Y(a)&&Ce(o),l=a.endsWith(".tgz");if(!c&&!l&&!re.isUsable(a))throw new Error(`模板源无效(缺 package.json): ${a}`);if(!c&&l&&!Y(a))throw new Error(`模板源无效(tgz 不存在): ${a}`);if(Ji(a,t),c&&e.localDeps)throw new Error("registry 源(--source @scope/pkg)与 --local-deps 互斥:registry 安装无需/不允许本地依赖注入");e.localDeps&&Oi(T.resolve(e.localDeps));for(let d of i)Pi(T.resolve(d));let p=fe(c?o:a,e.registry),u=p.sourceDir;try{let d=B(u);if(!d)throw new Error(`模板结构异常: ${a} 的 .tbox/app.json 缺失、损坏或缺少 templateVersion(出生版本)字段`);await Qt(u,t,{recursive:!0,force:!0,filter:S=>{let $=T.basename(S);return!(Ci.has($)||Di.has($))}}),Fi(t);let f=T.join(t,Ti);Y(f)&&await ln(f,T.join(t,pn));let g=T.join(t,Mi),m=Y(g);if(m){await ln(g,T.join(t,Ii));let S=tn(t);S>0&&console.log(` 🔒 携带锁 specifiers 已对齐 registry 归一态(${S} 项 catalog: → 字面量)`)}if(e.localDeps){let S=Ai(T.resolve(e.localDeps),t);await ji(T.join(t,pn),S,"utf8"),m&&De(t)}for(let S of i)await Qt(T.resolve(S),T.join(t,"config"),{recursive:!0,force:!0,filter:$=>T.basename($)!==".DS_Store"&&T.basename($)!=="node_modules"});e.envFile&&await Qt(T.resolve(e.envFile),T.join(t,"config","env.sh"),{force:!0});let h=T.join(t,"package.json");if(Y(h)){let S=JSON.parse(await Ei(h,"utf8"));S.name=s,await Ri(h,JSON.stringify(S,null,2)+`
11
+ `,"utf8")}let v={templateVersion:d.templateVersion,npmModules:[]};await te(t,v),console.log(`✅ 已创建应用 ${s}`),console.log(c?` ⚡ 已从 registry 模板包 ${p.source.name} 展开(发布态)`:l?` ⚡ 已从模板包 ${T.basename(a)} 展开(发布态)`:" ⚡ 已从模板目录展开(本地开发源)"),e.localDeps?(console.log(` ⚡ 已注入平台 overrides(--local-deps: ${e.localDeps},install 离线消费本地发布态产物)`),m&&console.log(" 🔒 携带锁已增量刷新为 file: 形态(仅平台三包换形态,间接依赖保钉)——B 档移除 overrides 块后 plain install 回 registry 形态、frozen 恢复可用")):m&&console.log(" 🔒 依赖已由 pnpm-lock.yaml 冻结(直接+间接全精确)——请随应用提交,安装可 --frozen-lockfile"),i.length>0&&console.log(` ⚡ 已合并应用配置(--config-dir: ${i.join(" + ")} → config/)`),console.log(" ⚡ 已生成 pnpm-workspace.yaml(应用 workspace)"),console.log(n?" 下一步: pnpm install":` 下一步: cd ${e.name} && pnpm install`),console.log(" 📱 支付宝小程序壳: tbox-app miniapp-container init(web-view 承载 H5 + JSAPI 桥代理)"),console.log(" 🔐 鉴权(006): 生产请由平台注入 AUTH_TOKEN_SECRET 且确保 NODE_ENV=production(dev-login 强制关闭);"),console.log(" 本地开发默认开启 dev-login(非 production);如需关闭设 AUTH_DEV_LOGIN_DISABLED=true。")}finally{p.source instanceof U&&p.source.dispose()}}import{existsSync as ve,readFileSync as wr,readdirSync as cc}from"fs";import Q from"path";import{copyFile as Zi,mkdir as kt,rm as xn,writeFile as ne}from"fs/promises";import W from"path";import{existsSync as ze,readFileSync as mt}from"fs";import{readFile as dt,readdir as Bi,writeFile as Wi}from"fs/promises";import _ from"path";import V from"typescript";var zi=/^@tbox\.cn\/app-(?:sdk|toolkit|contracts(?:-|$))/,Ui=new Set(["@tbox.cn/app-contracts-mall"]);function ut(e){return zi.test(e)}function Je(e){return Ui.has(e)}var mn=["dependencies","optionalDependencies","peerDependencies","devDependencies"],Hi=new Set(["name","version","private","exports"]),gt=/\.(?:ts|tsx|mts|cts|js|jsx|mjs|cjs)$/,Ki=new Set(["node_modules","dist",".git",".tbox"]),Gi=new Map([["@tbox.cn/app-contracts-mall",{exports:{".":{types:"./src/index.ts",import:"./src/runtime.ts"},"./server":{types:"./src/server/index.ts",import:"./src/server/index.ts"},"./package.json":"./package.json"},files:{"src/index.ts":`export * from '@tbox.cn/app-contracts-mall';
9
12
  `,"src/runtime.ts":`export * from '@tbox.cn/app-contracts-mall';
10
13
  `,"src/server/index.ts":`export * from '@tbox.cn/app-contracts-mall/server';
11
- `}}]]);function mt(e){return`@app/${e}`}function un(e,t){return Je(e)||t?"codegen":"sdk"}function xe(e){return{id:e.id,publicName:e.package,localName:mt(e.id),version:e.version}}function Hi(e){let t=new Map;for(let r of e?.npmModules??[]){if(r.mode!=="codegen")continue;let n=xe(r);t.set(n.publicName,n)}return t}function dn(e,t){let r=new Map(e);return r.set(t.publicName,t),r}function Se(e){return Hi(B(e))}function gt(e){try{return JSON.parse(dt(_.join(e,"package.json"),"utf8")).tboxCodegenShim===!0}catch{return!1}}function Wi(e,t,r){let n=[...t].sort((s,i)=>{let o=r==="local"?s.publicName:s.localName;return(r==="local"?i.publicName:i.localName).length-o.length});for(let s of n){let i=r==="local"?s.publicName:s.localName,o=r==="local"?s.localName:s.publicName;if(e===i)return o;if(e.startsWith(`${i}/`))return`${o}${e.slice(i.length)}`}return e}function Ue(e,t,r,n="local"){let s=[...r];if(s.length===0)return e;let i=t.endsWith(".tsx")?V.ScriptKind.TSX:t.endsWith(".jsx")?V.ScriptKind.JSX:t.endsWith(".json")?V.ScriptKind.JSON:V.ScriptKind.TS,o=V.createSourceFile(t,e,V.ScriptTarget.Latest,!0,i),a=[];function c(u){let d=Wi(u.text,s,n);if(d===u.text)return;let f=e.slice(u.getStart(o),u.end),g=f[0];(g==="'"||g==='"'||g==="`")&&f.at(-1)===g&&a.push({start:u.getStart(o),end:u.end,value:`${g}${d}${g}`})}function l(u){if(V.isImportDeclaration(u)&&V.isStringLiteralLike(u.moduleSpecifier))c(u.moduleSpecifier);else if(V.isExportDeclaration(u)&&u.moduleSpecifier&&V.isStringLiteralLike(u.moduleSpecifier))c(u.moduleSpecifier);else if(V.isImportTypeNode(u)&&V.isLiteralTypeNode(u.argument)&&V.isStringLiteralLike(u.argument.literal))c(u.argument.literal);else if(V.isCallExpression(u)&&u.arguments.length>0&&V.isStringLiteralLike(u.arguments[0])){let d=u.expression.kind===V.SyntaxKind.ImportKeyword,f=V.isIdentifier(u.expression)&&u.expression.text==="loadModuleSkills";(d||f)&&c(u.arguments[0])}else if(V.isPropertyAssignment(u)&&V.isArrayLiteralExpression(u.initializer)){let d=u.name.getText(o).replace(/["']/g,"");if(d==="external"||d==="noExternal")for(let f of u.initializer.elements)V.isStringLiteralLike(f)&&c(f)}V.forEachChild(u,l)}l(o);let p=e;for(let u of a.sort((d,f)=>f.start-d.start))p=p.slice(0,u.start)+u.value+p.slice(u.end);return p}function fn(e,t,r,n){let s=[...t];for(let i of pn){let o=e[i];if(!o||typeof o!="object"||Array.isArray(o))continue;let a={...o};for(let c of s){let l=r==="local"?c.publicName:c.localName,p=r==="local"?c.localName:c.publicName;l in a&&(delete a[l],a[p]=r==="local"?"workspace:*":"catalog:")}for(let c of Object.keys(a))lt(c)?a[c]="catalog:":a[c]==="catalog:"&&n?.has(c)&&(a[c]=n.get(c));e[i]=a}}function Ki(e){if(e==="./package.json"||!e.startsWith("./dist/"))return e;let t=e.replace(/^\.\/dist\//,"./src/");return t.endsWith(".d.ts")?`${t.slice(0,-5)}.ts`:t.endsWith(".js")?`${t.slice(0,-3)}.ts`:t}function Zt(e){return typeof e=="string"?Ki(e):Array.isArray(e)?e.map(Zt):!e||typeof e!="object"?e:Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Zt(r)]))}function mn(e){if(!e.exports||typeof e.exports!="object")return;let t=Zt(e.exports);"./package.json"in t||(t["./package.json"]="./package.json"),e.exports=t}function Te(e,t,r,n){let s=JSON.parse(JSON.stringify(e));return s.name=mt(t.id),s.private=!0,fn(s,r,"local",n),mn(s),s}function ce(e){let t=/^\s+["']?([^"':#\s]+)["']?\s*:\s*(.+?)\s*(?:#.*)?$/,r=_.resolve(e);for(;;){let n=_.join(r,"pnpm-workspace.yaml");if(ze(n)){let i=new Map,o=!1;for(let a of dt(n,"utf8").split(`
12
- `)){let c=a.replace(/\r$/,"");if(/^\S/.test(c)){o=/^catalog\s*:/.test(c);continue}if(!o)continue;let l=c.match(t);l&&i.set(l[1],l[2].replace(/^['"]|['"]$/g,""))}return i.size>0?i:void 0}let s=_.dirname(r);if(s===r)return;r=s}}function ln(e,t){return JSON.stringify(e)===JSON.stringify(t)}function gn(e,t,r,n={}){let s={},i=new Set([...Object.keys(e),...Object.keys(t),...Object.keys(r)]);for(let o of i){if(zi.has(o)){let a=n.ours?t[o]:r[o];a!==void 0&&(s[o]=a);continue}if(n.ours){t[o]!==void 0&&(s[o]=t[o]);continue}if(n.theirs){r[o]!==void 0&&(s[o]=r[o]);continue}ln(t[o],e[o])?r[o]!==void 0&&(s[o]=r[o]):ln(r[o],e[o])?t[o]!==void 0&&(s[o]=t[o]):r[o]!==void 0?s[o]=r[o]:t[o]!==void 0&&(s[o]=t[o])}return s}function yt(e){if(!ze(_.join(e,"package.json")))throw new Error(`codegen 源无效(缺 package.json): ${e}`);let t;try{t=JSON.parse(dt(_.join(e,"package.json"),"utf8")).name}catch{throw new Error(`codegen 源 package.json 无法解析: ${e}`)}if(t&&Je(t)&&!ze(_.join(e,"src","index.ts")))throw new Error(`codegen 源缺少 src/index.ts:请使用包含源码载荷的契约包版本(${e})`)}function ht(e,t){let r=[...t];return new Map([...e].map(([n,s])=>[n,ft.test(n)?Ue(s,n,r):s]))}async function yn(e,t){let r=Bi.get(t.publicName);if(!r)return!1;let n=_.join(e,"packages",t.id),{mkdir:s,rm:i,writeFile:o}=await import("fs/promises");await i(n,{recursive:!0,force:!0}),await s(n,{recursive:!0});let a={name:t.localName,version:"0.0.0",private:!0,type:"module",exports:r.exports,scripts:{typecheck:"tsc --noEmit",test:"vitest run --passWithNoTests"},dependencies:{[t.publicName]:"catalog:"},devDependencies:{"@types/node":"catalog:",typescript:"catalog:",vitest:"catalog:"},tboxCodegenShim:!0};await o(_.join(n,"package.json"),JSON.stringify(a,null,2)+`
13
- `,"utf8");for(let[c,l]of Object.entries(r.files)){let p=_.join(n,c);await s(_.dirname(p),{recursive:!0}),await o(p,l,"utf8")}return!0}async function ut(e,t){if(ze(e))for(let r of await Vi(e,{withFileTypes:!0})){if(Ui.has(r.name))continue;let n=_.join(e,r.name);r.isDirectory()?await ut(n,t):r.isFile()&&(ft.test(r.name)||r.name==="package.json")&&t.push(n)}}async function vt(e,t,r="local"){let n=[...t],s=ce(e),i=[];await ut(_.join(e,"packages"),i);let o=[];for(let a of i){let c=_.relative(e,a).split(_.sep).join("/"),l=await pt(a,"utf8"),p=l;if(_.basename(a)==="package.json")try{let u=JSON.parse(l);fn(u,n,r,s),p=JSON.stringify(u,null,2)+`
14
- `}catch{continue}else p=Ue(l,c,n,r);p!==l&&(await Ji(a,p,"utf8"),o.push(c))}return o}async function hn(e){let t=Se(e),r=[],n=[];await ut(_.join(e,"apps"),n),await ut(_.join(e,"packages"),n);for(let s of t.values()){let i=_.join(e,"packages",s.id);if(!ze(i))r.push(`packages/${s.id}: codegen 包缺失`);else{let o=_.join(i,"package.json");try{JSON.parse(await pt(o,"utf8")).name!==s.localName&&r.push(`packages/${s.id}/package.json: name 应为 ${s.localName}`)}catch{r.push(`packages/${s.id}/package.json: 无法解析`)}}}for(let s of n){let i=_.relative(e,s).split(_.sep).join("/");if(_.basename(s)==="package.json"){try{let a=JSON.parse(await pt(s,"utf8"));for(let c of pn){let l=a[c];if(!l||typeof l!="object"||Array.isArray(l))continue;let p=l;for(let u of t.values())(u.publicName in p||u.localName in p&&p[u.localName]!=="workspace:*")&&r.push(`${i}: codegen 依赖未归一为 ${u.localName}: workspace:*`)}}catch{}continue}let o=await pt(s,"utf8");Ue(o,i,t.values())!==o&&r.push(`${i}: 源码仍引用 codegen 发布包名`)}return[...new Set(r)]}function Be(e){return JSON.parse(dt(_.join(e,"package.json"),"utf8"))}function wn(e){return e.replace(/^@tbox\.cn\/app-/,"").replace(/^@[^/]+\//,"")}async function bn(e,t,r,n=[]){let s=new re(t),i=H.join(e,"packages",r.id);await vn(i,{recursive:!0,force:!0}),await wt(i,{recursive:!0});let o=Be(t),a=typeof o.name=="string"?o.name:r.package,c=xe({id:r.id,package:a,version:r.version}),l=dn(new Map([...n].map(u=>[u.publicName,u])),c);for(let u of await s.listFiles()){if(u==="package.json")continue;let d=H.join(i,u);if(await wt(H.dirname(d),{recursive:!0}),!ft.test(u)){await Gi(H.join(t,u),d);continue}let f=await s.readFile(u);await ne(d,Ue(f,u,l.values()))}let p=Te(o,r,l.values(),ce(t));await ne(H.join(i,"package.json"),JSON.stringify(p,null,2)+`
15
- `,"utf8")}var qi=e=>`import type { ServerContext, ServerModule } from '@tbox.cn/app-sdk/server';
14
+ `}}]]);function yt(e){return`@app/${e}`}function gn(e,t){return Je(e)||t?"codegen":"sdk"}function xe(e){return{id:e.id,publicName:e.package,localName:yt(e.id),version:e.version}}function qi(e){let t=new Map;for(let r of e?.npmModules??[]){if(r.mode!=="codegen")continue;let n=xe(r);t.set(n.publicName,n)}return t}function yn(e,t){let r=new Map(e);return r.set(t.publicName,t),r}function Se(e){return qi(B(e))}function ht(e){try{return JSON.parse(mt(_.join(e,"package.json"),"utf8")).tboxCodegenShim===!0}catch{return!1}}function Xi(e,t,r){let n=[...t].sort((s,i)=>{let o=r==="local"?s.publicName:s.localName;return(r==="local"?i.publicName:i.localName).length-o.length});for(let s of n){let i=r==="local"?s.publicName:s.localName,o=r==="local"?s.localName:s.publicName;if(e===i)return o;if(e.startsWith(`${i}/`))return`${o}${e.slice(i.length)}`}return e}function Ue(e,t,r,n="local"){let s=[...r];if(s.length===0)return e;let i=t.endsWith(".tsx")?V.ScriptKind.TSX:t.endsWith(".jsx")?V.ScriptKind.JSX:t.endsWith(".json")?V.ScriptKind.JSON:V.ScriptKind.TS,o=V.createSourceFile(t,e,V.ScriptTarget.Latest,!0,i),a=[];function c(u){let d=Xi(u.text,s,n);if(d===u.text)return;let f=e.slice(u.getStart(o),u.end),g=f[0];(g==="'"||g==='"'||g==="`")&&f.at(-1)===g&&a.push({start:u.getStart(o),end:u.end,value:`${g}${d}${g}`})}function l(u){if(V.isImportDeclaration(u)&&V.isStringLiteralLike(u.moduleSpecifier))c(u.moduleSpecifier);else if(V.isExportDeclaration(u)&&u.moduleSpecifier&&V.isStringLiteralLike(u.moduleSpecifier))c(u.moduleSpecifier);else if(V.isImportTypeNode(u)&&V.isLiteralTypeNode(u.argument)&&V.isStringLiteralLike(u.argument.literal))c(u.argument.literal);else if(V.isCallExpression(u)&&u.arguments.length>0&&V.isStringLiteralLike(u.arguments[0])){let d=u.expression.kind===V.SyntaxKind.ImportKeyword,f=V.isIdentifier(u.expression)&&u.expression.text==="loadModuleSkills";(d||f)&&c(u.arguments[0])}else if(V.isPropertyAssignment(u)&&V.isArrayLiteralExpression(u.initializer)){let d=u.name.getText(o).replace(/["']/g,"");if(d==="external"||d==="noExternal")for(let f of u.initializer.elements)V.isStringLiteralLike(f)&&c(f)}V.forEachChild(u,l)}l(o);let p=e;for(let u of a.sort((d,f)=>f.start-d.start))p=p.slice(0,u.start)+u.value+p.slice(u.end);return p}function hn(e,t,r,n){let s=[...t];for(let i of mn){let o=e[i];if(!o||typeof o!="object"||Array.isArray(o))continue;let a={...o};for(let c of s){let l=r==="local"?c.publicName:c.localName,p=r==="local"?c.localName:c.publicName;l in a&&(delete a[l],a[p]=r==="local"?"workspace:*":"catalog:")}for(let c of Object.keys(a))ut(c)?a[c]="catalog:":a[c]==="catalog:"&&n?.has(c)&&(a[c]=n.get(c));e[i]=a}}function Yi(e){if(e==="./package.json"||!e.startsWith("./dist/"))return e;let t=e.replace(/^\.\/dist\//,"./src/");return t.endsWith(".d.ts")?`${t.slice(0,-5)}.ts`:t.endsWith(".js")?`${t.slice(0,-3)}.ts`:t}function tr(e){return typeof e=="string"?Yi(e):Array.isArray(e)?e.map(tr):!e||typeof e!="object"?e:Object.fromEntries(Object.entries(e).map(([t,r])=>[t,tr(r)]))}function vn(e){if(!e.exports||typeof e.exports!="object")return;let t=tr(e.exports);"./package.json"in t||(t["./package.json"]="./package.json"),e.exports=t}function Te(e,t,r,n){let s=JSON.parse(JSON.stringify(e));return s.name=yt(t.id),s.private=!0,hn(s,r,"local",n),vn(s),s}function ce(e){let t=/^\s+["']?([^"':#\s]+)["']?\s*:\s*(.+?)\s*(?:#.*)?$/,r=_.resolve(e);for(;;){let n=_.join(r,"pnpm-workspace.yaml");if(ze(n)){let i=new Map,o=!1;for(let a of mt(n,"utf8").split(`
15
+ `)){let c=a.replace(/\r$/,"");if(/^\S/.test(c)){o=/^catalog\s*:/.test(c);continue}if(!o)continue;let l=c.match(t);l&&i.set(l[1],l[2].replace(/^['"]|['"]$/g,""))}return i.size>0?i:void 0}let s=_.dirname(r);if(s===r)return;r=s}}function fn(e,t){return JSON.stringify(e)===JSON.stringify(t)}function wn(e,t,r,n={}){let s={},i=new Set([...Object.keys(e),...Object.keys(t),...Object.keys(r)]);for(let o of i){if(Hi.has(o)){let a=n.ours?t[o]:r[o];a!==void 0&&(s[o]=a);continue}if(n.ours){t[o]!==void 0&&(s[o]=t[o]);continue}if(n.theirs){r[o]!==void 0&&(s[o]=r[o]);continue}fn(t[o],e[o])?r[o]!==void 0&&(s[o]=r[o]):fn(r[o],e[o])?t[o]!==void 0&&(s[o]=t[o]):r[o]!==void 0?s[o]=r[o]:t[o]!==void 0&&(s[o]=t[o])}return s}function vt(e){if(!ze(_.join(e,"package.json")))throw new Error(`codegen 源无效(缺 package.json): ${e}`);let t;try{t=JSON.parse(mt(_.join(e,"package.json"),"utf8")).name}catch{throw new Error(`codegen 源 package.json 无法解析: ${e}`)}if(t&&Je(t)&&!ze(_.join(e,"src","index.ts")))throw new Error(`codegen 源缺少 src/index.ts:请使用包含源码载荷的契约包版本(${e})`)}function wt(e,t){let r=[...t];return new Map([...e].map(([n,s])=>[n,gt.test(n)?Ue(s,n,r):s]))}async function bn(e,t){let r=Gi.get(t.publicName);if(!r)return!1;let n=_.join(e,"packages",t.id),{mkdir:s,rm:i,writeFile:o}=await import("fs/promises");await i(n,{recursive:!0,force:!0}),await s(n,{recursive:!0});let a={name:t.localName,version:"0.0.0",private:!0,type:"module",exports:r.exports,scripts:{typecheck:"tsc --noEmit",test:"vitest run --passWithNoTests"},dependencies:{[t.publicName]:"catalog:"},devDependencies:{"@types/node":"catalog:",typescript:"catalog:",vitest:"catalog:"},tboxCodegenShim:!0};await o(_.join(n,"package.json"),JSON.stringify(a,null,2)+`
16
+ `,"utf8");for(let[c,l]of Object.entries(r.files)){let p=_.join(n,c);await s(_.dirname(p),{recursive:!0}),await o(p,l,"utf8")}return!0}async function ft(e,t){if(ze(e))for(let r of await Bi(e,{withFileTypes:!0})){if(Ki.has(r.name))continue;let n=_.join(e,r.name);r.isDirectory()?await ft(n,t):r.isFile()&&(gt.test(r.name)||r.name==="package.json")&&t.push(n)}}async function bt(e,t,r="local"){let n=[...t],s=ce(e),i=[];await ft(_.join(e,"packages"),i);let o=[];for(let a of i){let c=_.relative(e,a).split(_.sep).join("/"),l=await dt(a,"utf8"),p=l;if(_.basename(a)==="package.json")try{let u=JSON.parse(l);hn(u,n,r,s),p=JSON.stringify(u,null,2)+`
17
+ `}catch{continue}else p=Ue(l,c,n,r);p!==l&&(await Wi(a,p,"utf8"),o.push(c))}return o}async function kn(e){let t=Se(e),r=[],n=[];await ft(_.join(e,"apps"),n),await ft(_.join(e,"packages"),n);for(let s of t.values()){let i=_.join(e,"packages",s.id);if(!ze(i))r.push(`packages/${s.id}: codegen 包缺失`);else{let o=_.join(i,"package.json");try{JSON.parse(await dt(o,"utf8")).name!==s.localName&&r.push(`packages/${s.id}/package.json: name 应为 ${s.localName}`)}catch{r.push(`packages/${s.id}/package.json: 无法解析`)}}}for(let s of n){let i=_.relative(e,s).split(_.sep).join("/");if(_.basename(s)==="package.json"){try{let a=JSON.parse(await dt(s,"utf8"));for(let c of mn){let l=a[c];if(!l||typeof l!="object"||Array.isArray(l))continue;let p=l;for(let u of t.values())(u.publicName in p||u.localName in p&&p[u.localName]!=="workspace:*")&&r.push(`${i}: codegen 依赖未归一为 ${u.localName}: workspace:*`)}}catch{}continue}let o=await dt(s,"utf8");Ue(o,i,t.values())!==o&&r.push(`${i}: 源码仍引用 codegen 发布包名`)}return[...new Set(r)]}function Be(e){return JSON.parse(mt(_.join(e,"package.json"),"utf8"))}function Sn(e){return e.replace(/^@tbox\.cn\/app-/,"").replace(/^@[^/]+\//,"")}async function $n(e,t,r,n=[]){let s=new re(t),i=W.join(e,"packages",r.id);await xn(i,{recursive:!0,force:!0}),await kt(i,{recursive:!0});let o=Be(t),a=typeof o.name=="string"?o.name:r.package,c=xe({id:r.id,package:a,version:r.version}),l=yn(new Map([...n].map(u=>[u.publicName,u])),c);for(let u of await s.listFiles()){if(u==="package.json")continue;let d=W.join(i,u);if(await kt(W.dirname(d),{recursive:!0}),!gt.test(u)){await Zi(W.join(t,u),d);continue}let f=await s.readFile(u);await ne(d,Ue(f,u,l.values()))}let p=Te(o,r,l.values(),ce(t));await ne(W.join(i,"package.json"),JSON.stringify(p,null,2)+`
18
+ `,"utf8")}var Qi=e=>`import type { ServerContext, ServerModule } from '@tbox.cn/app-sdk/server';
16
19
 
17
20
  /**
18
21
  * ${e} 本地模块(local 模式,app 自有包)注册入口。
@@ -31,11 +34,11 @@ export const serverModule = {
31
34
  // _ctx.services.register('member', member);
32
35
  },
33
36
  } satisfies ServerModule;
34
- `,Xi=`/**
37
+ `,ea=`/**
35
38
  * Service 层(业务专属实现,直接 import 或经 ctx.services 注册供跨模块消费)。
36
39
  */
37
40
  export {};
38
- `,Yi=`/**
41
+ `,ta=`/**
39
42
  * Handler 定义(001 §3.2)。
40
43
  */
41
44
  import type { HandlerDefinition } from '@tbox.cn/app-sdk/server';
@@ -44,7 +47,7 @@ export const exampleHandler: HandlerDefinition = {
44
47
  id: 'example',
45
48
  handle: async () => ({ cards: [], text: '本地模块示例' }),
46
49
  };
47
- `,Zi=`/**
50
+ `,ra=`/**
48
51
  * 客户端入口:导出 clientModule(CLI sync 装配读取;与 serverModule 逐行对称)。
49
52
  * cards map 的 key 约定 = cardType;无卡片模块写空 map。
50
53
  */
@@ -59,13 +62,13 @@ export const clientModule = {
59
62
  // _ctx.cards.registerMap(cards);
60
63
  },
61
64
  } satisfies ClientModule;
62
- `,Qi=`/**
65
+ `,na=`/**
63
66
  * 本地模块主入口(package.json exports "." 指向)。
64
67
  * 消费方通常走 ./server / ./client 子路径;主入口聚合导出便于直接引用。
65
68
  */
66
69
  export * from './server';
67
70
  export * from './client';
68
- `,ea=`{
71
+ `,sa=`{
69
72
  "extends": "../../tsconfig.base.json",
70
73
  "compilerOptions": {
71
74
  "jsx": "react-jsx",
@@ -73,35 +76,35 @@ export * from './client';
73
76
  },
74
77
  "include": ["src"]
75
78
  }
76
- `;async function kn(e,t){let r=t.startsWith("module-")?t:`module-${t}`,n=H.join(e,"packages",r);await vn(n,{recursive:!0,force:!0}),await wt(H.join(n,"src/server"),{recursive:!0}),await wt(H.join(n,"src/client"),{recursive:!0});let s={name:`@app/${r}`,version:"0.1.0",private:!0,type:"module",exports:{".":{types:"./src/index.ts",import:"./src/index.ts"},"./server":{types:"./src/server/index.ts",import:"./src/server/index.ts"},"./client":{types:"./src/client/index.ts",import:"./src/client/index.ts"},"./package.json":"./package.json"},scripts:{typecheck:"tsc --noEmit",test:"vitest run --passWithNoTests"},dependencies:{"@tbox.cn/app-sdk":"catalog:","@tbox.cn/app-contracts":"catalog:"},peerDependencies:{zod:"catalog:",react:"catalog:","@mastra/core":"catalog:"},devDependencies:{typescript:"catalog:",vitest:"catalog:","@types/react":"catalog:","@types/node":"catalog:"}},i={schemaVersion:1,name:r,version:"0.1.0",kind:"business",risk:{level:"low",writeBoundary:"source"},distribution:{defaultMode:"local"},contributes:{handlers:[],tools:[],cards:[],routes:[],pages:[],tabs:[],resources:[]},dependencies:{modules:[]},env:[]};return await ne(H.join(n,"package.json"),JSON.stringify(s,null,2)+`
77
- `,"utf8"),await ne(H.join(n,"tbox.module.json"),JSON.stringify(i,null,2)+`
78
- `,"utf8"),await ne(H.join(n,"tsconfig.json"),ea,"utf8"),await ne(H.join(n,"src/server/index.ts"),qi(r),"utf8"),await ne(H.join(n,"src/server/service.ts"),Xi,"utf8"),await ne(H.join(n,"src/server/handler.ts"),Yi,"utf8"),await ne(H.join(n,"src/client/index.ts"),Zi,"utf8"),await ne(H.join(n,"src/index.ts"),Qi,"utf8"),r}import{existsSync as xn}from"fs";import{readFileSync as ta}from"fs";import{writeFile as ra}from"fs/promises";import Sn from"path";var na=["apps/server/package.json","apps/client/package.json"];async function He(e,t,r){let n=!1;for(let s of na){let i=Sn.join(e,s);if(!xn(i))continue;let o=JSON.parse(ta(i,"utf8")),a=o.dependencies??={};r==="add"&&!a[t]?(a[t]="workspace:*",n=!0):r==="remove"&&a[t]&&(delete a[t],n=!0),n&&await ra(i,JSON.stringify(o,null,2)+`
79
- `,"utf8")}return n}async function $n(e,t){let r=Sn.join(e,"packages",t);if(!xn(r))return!1;let{rm:n}=await import("fs/promises");return await n(r,{recursive:!0,force:!0}),!0}import{existsSync as sr,readFileSync as pa}from"fs";import{readFile as ua,writeFile as da}from"fs/promises";import or from"path";var se=[{path:"apps/server/src/modules.ts",kind:"server-modules"},{path:"apps/client/src/modules.ts",kind:"client-modules"}];function sa(e){return e.split(/[^A-Za-z0-9]+/).filter(Boolean).map((t,r)=>r===0?t.toLowerCase():t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}function bt(e,t){return sa(t)}function St(e,t){return $t[e].contributes(t)}function kt(e){return e.replace(/^@[^/]+\//,"").replace(/\/(server|client)$/,"").replace(/\/$/,"")}var $t={"server-modules":{mapMarker:"register",importExport:"serverModule",importSuffix:"server",entryPattern:/^\s*([A-Za-z_$][\w$]*),\s*$/,header:"const modules = [",footer:"];",contributes:e=>e.hasServerEntry},"client-modules":{mapMarker:"register",importExport:"clientModule",importSuffix:"client",entryPattern:/^\s*([A-Za-z_$][\w$]*),\s*$/,header:"const modules = [",footer:"];",contributes:e=>e.hasClientEntry&&e.hasCards}},rr=/^import\s*\{\s*([\w$]+)\s+as\s+([\w$]+)\s*\}\s*from\s*['"]([^'"]+)['"];\s*$/,nr=/^\]\s*(?:as\s+const)?;\s*$/;function xt(e,t){let r=`// @tbox:${t}-begin`,n=`// @tbox:${t}-end`,s=e.indexOf(r);if(s===-1)return null;let i=e.indexOf(n,s);if(i===-1)return null;let o=s+r.length;return{block:e.slice(o,i),start:o,end:i}}function Qt(e,t,r){return e.slice(0,t.start)+r+e.slice(t.end)}function En(e,t){let r=$t[t],n=[],s=[],i=[],o=xt(e,"imports");if(o)for(let p of o.block.split(/\r?\n/)){let u=p.match(rr);u?n.push(kt(u[3])):p.trim()&&s.push(`imports: ${p.trim()}`)}else i.push("imports");let a=xt(e,r.mapMarker);if(a){let p=a.block.split(/\r?\n/),u=p.findIndex(g=>g.trim().startsWith(r.header)),d=[...p].reverse().findIndex(g=>nr.test(g.trim())),f=d===-1?-1:p.length-1-d;if(u===-1||f<=u)i.push(r.mapMarker);else for(let g of p.slice(u+1,f))!g.match(r.entryPattern)&&g.trim()&&s.push(`${r.mapMarker}: ${g.trim()}`)}else i.push(r.mapMarker);let c=new Map;if(o)for(let p of o.block.split(/\r?\n/)){let u=p.match(rr);u&&c.set(u[2],kt(u[3]))}let l=[];if(a){let p=a.block.split(/\r?\n/),u=p.findIndex(g=>g.trim().startsWith(r.header)),d=[...p].reverse().findIndex(g=>nr.test(g.trim())),f=d===-1?-1:p.length-1-d;if(u!==-1&&f>u)for(let g of p.slice(u+1,f)){let m=g.match(r.entryPattern);if(m){let h=c.get(m[1]);h&&l.push(h)}}}return{moduleIds:[...new Set([...n,...l])],nonStandardLines:s,broken:i}}function jt(e,t,r,n=!1){let s=$t[t],i=[],o=r.filter(s.contributes),a=new Map(o.map(w=>[bt(t,w.id),w])),c=e,l=!1,p=xt(c,"imports");if(!p)return i.push(`[${t}] imports 锚区缺失/破坏,跳过`),{content:c,changed:l,warnings:i,moduleIds:[]};let u=p.block.split(/\r?\n/),d=[];for(let w of u){let D=w.match(rr);if(!D){if(w.trim()==="")continue;n||i.push(`[${t}] imports 锚区非标行保留: ${w.trim()}`),n||d.push(w);continue}let M=D[2],b=D[3],k=a.get(M);k&&kt(k.pkg)===kt(b)?d.push(w):(k&&d.push(jn(t,M,k.pkg)),l=!0)}for(let w of o){let D=bt(t,w.id);d.some(M=>M.includes(`as ${D} } from`))||(d.push(jn(t,D,w.pkg)),l=!0)}let f=er(d.join(`
80
- `));f!==p.block&&(c=Qt(c,p,f),l=!0);let g=xt(c,s.mapMarker);if(!g)return i.push(`[${t}] ${s.mapMarker} 锚区缺失/破坏,跳过`),{content:c,changed:l,warnings:i,moduleIds:[]};let m=g.block.split(/\r?\n/),h=m.findIndex(w=>w.trim().startsWith(s.header)),v=[...m].reverse().findIndex(w=>nr.test(w.trim())),S=v===-1?-1:m.length-1-v;if(h===-1||S<=h){if(n){let w=er([s.header,...o.map(D=>tr(t,bt(t,D.id))),s.footer].join(`
81
- `));return w!==g.block&&(c=Qt(c,g,w),l=!0),{content:c,changed:l,warnings:i,moduleIds:o.map(D=>D.id)}}return i.push(`[${t}] ${s.mapMarker} 锚区结构不符合预期,降级为告警不覆盖`),{content:c,changed:l,warnings:i,moduleIds:[]}}let $=m.slice(0,h),R=m.slice(S+1),F=m.slice(h+1,S),A=[];for(let w of F){let D=w.match(s.entryPattern);if(!D){if(w.trim()==="")continue;n||i.push(`[${t}] ${s.mapMarker} 锚区非标行保留: ${w.trim()}`),n||A.push(w);continue}let M=D[1];a.has(M)?A.push(tr(t,M)):l=!0}for(let w of o){let D=bt(t,w.id);A.some(M=>M.includes(D))||(A.push(tr(t,D)),l=!0)}let N=m[S],P=er([...$,s.header,...A,N,...R].join(`
82
- `));return P!==g.block&&(c=Qt(c,g,P),l=!0),{content:c,changed:l,warnings:i,moduleIds:o.map(w=>w.id)}}function er(e){let t=e.split(/\r?\n/);for(;t.length>0&&t[0].trim()==="";)t.shift();for(;t.length>0&&t[t.length-1].trim()==="";)t.pop();return`
79
+ `;async function jn(e,t){let r=t.startsWith("module-")?t:`module-${t}`,n=W.join(e,"packages",r);await xn(n,{recursive:!0,force:!0}),await kt(W.join(n,"src/server"),{recursive:!0}),await kt(W.join(n,"src/client"),{recursive:!0});let s={name:`@app/${r}`,version:"0.1.0",private:!0,type:"module",exports:{".":{types:"./src/index.ts",import:"./src/index.ts"},"./server":{types:"./src/server/index.ts",import:"./src/server/index.ts"},"./client":{types:"./src/client/index.ts",import:"./src/client/index.ts"},"./package.json":"./package.json"},scripts:{typecheck:"tsc --noEmit",test:"vitest run --passWithNoTests"},dependencies:{"@tbox.cn/app-sdk":"catalog:","@tbox.cn/app-contracts":"catalog:"},peerDependencies:{zod:"catalog:",react:"catalog:","@mastra/core":"catalog:"},devDependencies:{typescript:"catalog:",vitest:"catalog:","@types/react":"catalog:","@types/node":"catalog:"}},i={schemaVersion:1,name:r,version:"0.1.0",kind:"business",risk:{level:"low",writeBoundary:"source"},distribution:{defaultMode:"local"},contributes:{handlers:[],tools:[],cards:[],routes:[],pages:[],tabs:[],resources:[]},dependencies:{modules:[]},env:[]};return await ne(W.join(n,"package.json"),JSON.stringify(s,null,2)+`
80
+ `,"utf8"),await ne(W.join(n,"tbox.module.json"),JSON.stringify(i,null,2)+`
81
+ `,"utf8"),await ne(W.join(n,"tsconfig.json"),sa,"utf8"),await ne(W.join(n,"src/server/index.ts"),Qi(r),"utf8"),await ne(W.join(n,"src/server/service.ts"),ea,"utf8"),await ne(W.join(n,"src/server/handler.ts"),ta,"utf8"),await ne(W.join(n,"src/client/index.ts"),ra,"utf8"),await ne(W.join(n,"src/index.ts"),na,"utf8"),r}import{existsSync as En}from"fs";import{readFileSync as oa}from"fs";import{writeFile as ia}from"fs/promises";import Rn from"path";var aa=["apps/server/package.json","apps/client/package.json"];async function We(e,t,r){let n=!1;for(let s of aa){let i=Rn.join(e,s);if(!En(i))continue;let o=JSON.parse(oa(i,"utf8")),a=o.dependencies??={};r==="add"&&!a[t]?(a[t]="workspace:*",n=!0):r==="remove"&&a[t]&&(delete a[t],n=!0),n&&await ia(i,JSON.stringify(o,null,2)+`
82
+ `,"utf8")}return n}async function Dn(e,t){let r=Rn.join(e,"packages",t);if(!En(r))return!1;let{rm:n}=await import("fs/promises");return await n(r,{recursive:!0,force:!0}),!0}import{existsSync as ar,readFileSync as ma}from"fs";import{readFile as ga,writeFile as ya}from"fs/promises";import cr from"path";var se=[{path:"apps/server/src/modules.ts",kind:"server-modules"},{path:"apps/client/src/modules.ts",kind:"client-modules"}];function ca(e){return e.split(/[^A-Za-z0-9]+/).filter(Boolean).map((t,r)=>r===0?t.toLowerCase():t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}function xt(e,t){return ca(t)}function jt(e,t){return Et[e].contributes(t)}function St(e){return e.replace(/^@[^/]+\//,"").replace(/\/(server|client)$/,"").replace(/\/$/,"")}var Et={"server-modules":{mapMarker:"register",importExport:"serverModule",importSuffix:"server",entryPattern:/^\s*([A-Za-z_$][\w$]*),\s*$/,header:"const modules = [",footer:"];",contributes:e=>e.hasServerEntry},"client-modules":{mapMarker:"register",importExport:"clientModule",importSuffix:"client",entryPattern:/^\s*([A-Za-z_$][\w$]*),\s*$/,header:"const modules = [",footer:"];",contributes:e=>e.hasClientEntry&&e.hasCards}},or=/^import\s*\{\s*([\w$]+)\s+as\s+([\w$]+)\s*\}\s*from\s*['"]([^'"]+)['"];\s*$/,ir=/^\]\s*(?:as\s+const)?;\s*$/;function $t(e,t){let r=`// @tbox:${t}-begin`,n=`// @tbox:${t}-end`,s=e.indexOf(r);if(s===-1)return null;let i=e.indexOf(n,s);if(i===-1)return null;let o=s+r.length;return{block:e.slice(o,i),start:o,end:i}}function rr(e,t,r){return e.slice(0,t.start)+r+e.slice(t.end)}function Tn(e,t){let r=Et[t],n=[],s=[],i=[],o=$t(e,"imports");if(o)for(let p of o.block.split(/\r?\n/)){let u=p.match(or);u?n.push(St(u[3])):p.trim()&&s.push(`imports: ${p.trim()}`)}else i.push("imports");let a=$t(e,r.mapMarker);if(a){let p=a.block.split(/\r?\n/),u=p.findIndex(g=>g.trim().startsWith(r.header)),d=[...p].reverse().findIndex(g=>ir.test(g.trim())),f=d===-1?-1:p.length-1-d;if(u===-1||f<=u)i.push(r.mapMarker);else for(let g of p.slice(u+1,f))!g.match(r.entryPattern)&&g.trim()&&s.push(`${r.mapMarker}: ${g.trim()}`)}else i.push(r.mapMarker);let c=new Map;if(o)for(let p of o.block.split(/\r?\n/)){let u=p.match(or);u&&c.set(u[2],St(u[3]))}let l=[];if(a){let p=a.block.split(/\r?\n/),u=p.findIndex(g=>g.trim().startsWith(r.header)),d=[...p].reverse().findIndex(g=>ir.test(g.trim())),f=d===-1?-1:p.length-1-d;if(u!==-1&&f>u)for(let g of p.slice(u+1,f)){let m=g.match(r.entryPattern);if(m){let h=c.get(m[1]);h&&l.push(h)}}}return{moduleIds:[...new Set([...n,...l])],nonStandardLines:s,broken:i}}function Rt(e,t,r,n=!1){let s=Et[t],i=[],o=r.filter(s.contributes),a=new Map(o.map(w=>[xt(t,w.id),w])),c=e,l=!1,p=$t(c,"imports");if(!p)return i.push(`[${t}] imports 锚区缺失/破坏,跳过`),{content:c,changed:l,warnings:i,moduleIds:[]};let u=p.block.split(/\r?\n/),d=[];for(let w of u){let D=w.match(or);if(!D){if(w.trim()==="")continue;n||i.push(`[${t}] imports 锚区非标行保留: ${w.trim()}`),n||d.push(w);continue}let M=D[2],b=D[3],k=a.get(M);k&&St(k.pkg)===St(b)?d.push(w):(k&&d.push(Cn(t,M,k.pkg)),l=!0)}for(let w of o){let D=xt(t,w.id);d.some(M=>M.includes(`as ${D} } from`))||(d.push(Cn(t,D,w.pkg)),l=!0)}let f=nr(d.join(`
83
+ `));f!==p.block&&(c=rr(c,p,f),l=!0);let g=$t(c,s.mapMarker);if(!g)return i.push(`[${t}] ${s.mapMarker} 锚区缺失/破坏,跳过`),{content:c,changed:l,warnings:i,moduleIds:[]};let m=g.block.split(/\r?\n/),h=m.findIndex(w=>w.trim().startsWith(s.header)),v=[...m].reverse().findIndex(w=>ir.test(w.trim())),S=v===-1?-1:m.length-1-v;if(h===-1||S<=h){if(n){let w=nr([s.header,...o.map(D=>sr(t,xt(t,D.id))),s.footer].join(`
84
+ `));return w!==g.block&&(c=rr(c,g,w),l=!0),{content:c,changed:l,warnings:i,moduleIds:o.map(D=>D.id)}}return i.push(`[${t}] ${s.mapMarker} 锚区结构不符合预期,降级为告警不覆盖`),{content:c,changed:l,warnings:i,moduleIds:[]}}let $=m.slice(0,h),R=m.slice(S+1),F=m.slice(h+1,S),A=[];for(let w of F){let D=w.match(s.entryPattern);if(!D){if(w.trim()==="")continue;n||i.push(`[${t}] ${s.mapMarker} 锚区非标行保留: ${w.trim()}`),n||A.push(w);continue}let M=D[1];a.has(M)?A.push(sr(t,M)):l=!0}for(let w of o){let D=xt(t,w.id);A.some(M=>M.includes(D))||(A.push(sr(t,D)),l=!0)}let N=m[S],P=nr([...$,s.header,...A,N,...R].join(`
85
+ `));return P!==g.block&&(c=rr(c,g,P),l=!0),{content:c,changed:l,warnings:i,moduleIds:o.map(w=>w.id)}}function nr(e){let t=e.split(/\r?\n/);for(;t.length>0&&t[0].trim()==="";)t.shift();for(;t.length>0&&t[t.length-1].trim()==="";)t.pop();return`
83
86
  `+t.join(`
84
87
  `)+`
85
- `}function jn(e,t,r){let n=$t[e];return`import { ${n.importExport} as ${t} } from '${r}/${n.importSuffix}';`}function tr(e,t){return` ${t},`}import{writeFile as oa}from"fs/promises";import ia from"path";import{readFileSync as ca}from"fs";function aa(e){try{return JSON.parse(la(e)??"{}")}catch{return null}}async function Cn(e,t,r){let n=ia.join(e,t),s=aa(n)??{},i=s.dependencies??{},o={},a=[];for(let[c,l]of Object.entries(r)){if(lt(c)||l==="workspace:*"||l.startsWith("catalog:"))continue;let p=i[c];if(!p){i[c]=l,o[c]=l;continue}if(p===l)continue;if(p==="catalog:"){let d=ce(e)?.get(c);d&&!Rn(d,l)&&a.push(`${c}: 应用 catalog ${d} 与模块要求 ${l} 无交集`);continue}let u=Rn(p,l);u?u!==p&&(i[c]=u,o[c]=u):a.push(`${c}: 已有 ${p},模块要求 ${l}`)}return s.dependencies=i,await oa(n,JSON.stringify(s,null,2)+`
86
- `,"utf8"),{merged:o,conflicts:a}}function Rn(e,t){let r=Dn(e),n=Dn(t);if(!r||!n||r.lower.major!==n.lower.major)return null;let s=(a,c)=>a.major-c.major||a.minor-c.minor||a.patch-c.patch,i=s(r.lower,n.lower)>=0?r.lower:n.lower,o=s(r.upper,n.upper)<=0?r.upper:n.upper;return s(i,o)>=0?null:s(r.lower,n.lower)>0?e:s(n.lower,r.lower)>0?t:s(r.upper,n.upper)<=0?e:t}function Dn(e){let t=e.match(/^([\^~]?)(\d+)\.(\d+)(?:\.(\d+))?/);if(!t)return null;let r={major:Number(t[2]),minor:Number(t[3]),patch:Number(t[4]??0)},n;return t[1]==="~"?n={major:r.major,minor:r.minor+1,patch:0}:t[1]==="^"?n=r.major===0?{major:0,minor:r.minor+1,patch:0}:{major:r.major+1,minor:0,patch:0}:n={...r,patch:r.patch+1},{lower:r,upper:n}}function la(e){try{return ca(e,"utf8")}catch{return}}async function me(e,t={}){let r=await ue(e),n=[],s=[],i=[];for(let c of se){let l=or.join(e,c.path);if(!sr(l)){n.push(`缺少装配文件 ${c.path}`);continue}let p=await ua(l,"utf8"),u=jt(p,c.kind,r,t.force??!1);n.push(...u.warnings.map(d=>`${c.path}: ${d}`)),u.changed&&(await da(l,u.content,"utf8"),s.push(c.path))}let o=["apps/server/package.json","apps/client/package.json"];for(let c of r){let l=or.join(e,"packages",c.id,"package.json");if(!sr(l))continue;let p={};try{p=JSON.parse(pa(l,"utf8")).dependencies??{}}catch{continue}for(let u of o){if(!sr(or.join(e,u)))continue;let d=await Cn(e,u,p);i.push(...d.conflicts.map(f=>`${c.id} → ${u}: ${f}`))}}let a=De(e);return{declared:r,changedFiles:s,warnings:n,depConflicts:i,lockfileRefreshed:a}}import{existsSync as fa}from"fs";import{readFile as ma}from"fs/promises";import ga from"path";async function G(e){let t={};for(let r of se){let n=ga.join(e,r.path);if(!fa(n)){t[r.kind]={moduleIds:[],nonStandardLines:[],broken:["missing-file"]};continue}let s=await ma(n,"utf8"),i=En(s,r.kind);t[r.kind]={moduleIds:i.moduleIds,nonStandardLines:i.nonStandardLines,broken:i.broken}}return t}import{existsSync as Mn}from"fs";import{readdir as ba}from"fs/promises";import ir from"path";import{readFileSync as ya}from"fs";import{readFile as ha,readdir as va}from"fs/promises";import Et from"path";async function $e(e,t,r){let n=await va(e,{withFileTypes:!0});for(let s of n){if(s.name==="node_modules"||s.name==="dist"||s.name===".git")continue;let i=Et.join(e,s.name);s.isDirectory()?await $e(i,t,r):s.isFile()&&/\.(ts|tsx|mjs|js)$/.test(s.name)&&r.push(Et.relative(t,i).split(Et.sep).join("/"))}}async function L(e){try{return await ha(e,"utf8")}catch{return""}}function wa(e){try{return JSON.parse(ya(e,"utf8"))}catch{return null}}function Z(e){return wa(Et.join(e,"package.json"))}function Rt(e,t){let r=Tn(e),n=Tn(t);if(!r||!n||r.lower.major!==n.lower.major)return null;let s=(a,c)=>a.major-c.major||a.minor-c.minor||a.patch-c.patch,i=s(r.lower,n.lower)>=0?r.lower:n.lower,o=s(r.upper,n.upper)<=0?r.upper:n.upper;return s(i,o)>=0?null:s(r.lower,n.lower)>0?e:s(n.lower,r.lower)>0?t:s(r.upper,n.upper)<=0?e:t}function Tn(e){let t=e.match(/^([\^~]?)(\d+)\.(\d+)(?:\.(\d+))?/);if(!t)return null;let r={major:Number(t[2]),minor:Number(t[3]),patch:Number(t[4]??0)},n;return t[1]==="~"?n={major:r.major,minor:r.minor+1,patch:0}:t[1]==="^"?n=r.major===0?{major:0,minor:r.minor+1,patch:0}:{major:r.major+1,minor:0,patch:0}:n={...r,patch:r.patch+1},{lower:r,upper:n}}async function In(e){let t=[],r=ir.join(e.appDir,"packages");if(!Mn(r))return t;for(let n of await ba(r,{withFileTypes:!0})){if(!n.isDirectory())continue;let s=ir.join(r,n.name);if(!Mn(ir.join(s,"tbox.module.json")))continue;let i=/^provider-/.test(n.name),o=Z(s),a={...o?.dependencies??{},...o?.peerDependencies??{}};for(let c of Object.keys(a))(/^@app\/(module|scenario)-/.test(c)||/^@tbox\.cn\/app-(module|scenario)-/.test(c))&&t.push({rule:"workspace-dag",level:"error",message:`${n.name} 依赖业务模块 ${c}(module 不得依赖 module/scenario)`}),i&&(/^@app\/(module|scenario)-/.test(c)||/^@tbox\.cn\/app-(module|scenario)-/.test(c))&&t.push({rule:"workspace-dag",level:"error",message:`${n.name} 依赖业务模块 ${c}(provider 不得依赖 module/scenario——实现自持)`})}return t}import{existsSync as Fn}from"fs";import{readdir as xa}from"fs/promises";import _n from"path";import C from"typescript";function oe(e){return C.createSourceFile("entry.ts",e,C.ScriptTarget.Latest,!0,C.ScriptKind.TS)}function An(e){return e&&(C.isAsExpression(e)||C.isSatisfiesExpression(e)?e.expression:e)}function ka(e,t){let r=oe(e),n=null;function s(i){if(!n){if(C.isFunctionDeclaration(i)&&i.name?.text===t&&i.body){n=i.body;return}if(C.isVariableStatement(i)&&i.declarationList.declarations.some(o=>C.isIdentifier(o.name)&&o.name.text===t)){let o=i.declarationList.declarations.find(l=>C.isIdentifier(l.name)&&l.name.text===t),a=An(o.initializer);if(a&&C.isArrowFunction(a)&&a.body&&C.isBlock(a.body)){n=a.body;return}let c=On(a,"register");if(c){n=c;return}}C.forEachChild(i,s)}}return s(r),n}function On(e,t){if(!e||!C.isObjectLiteralExpression(e))return null;for(let r of e.properties){if(C.isMethodDeclaration(r)&&r.name.getText()===t&&r.body)return r.body;if(C.isPropertyAssignment(r)&&r.name.getText()===t&&r.initializer){let n=r.initializer;if(C.isArrowFunction(n)&&n.body&&C.isBlock(n.body)||C.isFunctionExpression(n)&&n.body)return n.body}}return null}function We(e,t){let r=oe(e),n=null;function s(i){if(!n){if(C.isVariableStatement(i)&&i.declarationList.declarations.some(o=>C.isIdentifier(o.name)&&o.name.text===t)){let o=i.declarationList.declarations.find(c=>C.isIdentifier(c.name)&&c.name.text===t),a=On(An(o.initializer),"register");if(a){n=a;return}}C.forEachChild(i,s)}}return s(r),n??ka(e,"registerServer")}function Pn(e){let t=!1;function r(n){if(!t&&!C.isArrowFunction(n)){if(C.isCallExpression(n)){let s=n.expression;if(C.isIdentifier(s)&&s.text==="resolveService"){t=!0;return}let i=s.getText();if(i==="ctx.resolveService"||i.endsWith(".services.resolve")){t=!0;return}}C.forEachChild(n,r)}}return r(e),t}function ar(e){let t=!1;function r(n){if(!t){if(C.isCallExpression(n)){let s=n.expression.getText();if(s.endsWith(".cards.registerMap")||s.endsWith(".cards.register")){t=!0;return}}C.forEachChild(n,r)}}return r(e),t}function Ln(e){let t=oe(e),r=[];function n(s){if(C.isCallExpression(s)&&s.expression.getText().endsWith(".cards.register")){let o=s.arguments[0];o&&r.push(o.getText().replace(/['"]/g,""))}C.forEachChild(s,n)}return n(t),r}function cr(e){let t=oe(e),r={};function n(s){if(C.isImportDeclaration(s)&&C.isStringLiteral(s.moduleSpecifier)){let i=s.moduleSpecifier.text;if(i.startsWith("./")||i.startsWith("../")){let o=s.importClause;o?.name&&(r[o.name.text]=i)}}C.forEachChild(s,n)}return n(t),r}async function Nn(e){let t=[],r=_n.join(e.appDir,"packages");if(!Fn(r))return t;for(let n of await xa(r,{withFileTypes:!0})){if(!n.isDirectory())continue;let s=_n.join(r,n.name,"src/server/index.ts");if(!Fn(s))continue;let i=await L(s),o=We(i,"serverModule");o&&Pn(o)&&t.push({rule:"register-pure",level:"error",message:`${n.name}: 注册入口(serverModule.register)内出现 resolveService(只允许在 handle/事件回调内)`})}return t}import{existsSync as Ge}from"fs";import ye from"path";import E from"typescript";function ge(e){return E.isAsExpression(e)||E.isSatisfiesExpression(e)?e.expression:e}function Ct(e,t){let r=oe(e),n=null;function s(i){let o={};for(let a of i.properties){if(!E.isPropertyAssignment(a))continue;let c=a.name,l=E.isIdentifier(c)||E.isStringLiteral(c)?c.text:"";l&&(o[l]=a.initializer)}return o}for(let i of r.statements)if(E.isVariableStatement(i)){for(let o of i.declarationList.declarations)if(!(!E.isIdentifier(o.name)||!o.initializer)){if(o.name.text==="cards"){let a=ge(o.initializer);if(E.isObjectLiteralExpression(a))return n=s(a),n}if(t&&o.name.text===t){let a=ge(o.initializer);if(E.isObjectLiteralExpression(a)){for(let c of a.properties)if(E.isPropertyAssignment(c)&&E.isIdentifier(c.name)&&c.name.text==="cards"){let l=ge(c.initializer);if(E.isObjectLiteralExpression(l))return n=s(l),n}}}}}return n}function Sa(e){let t=Ct(e,"clientModule");return t?Object.keys(t):[]}function Ke(e){let t=e.match(/cardType:\s*['"]([^'"]+)['"]/),r=e.match(/schemaVersion:\s*(\d+)/);return{cardType:t?.[1],schemaVersion:r?Number(r[1]):void 0}}function Jn(e,t){let r=[t,`${t}.ts`,`${t}.tsx`,`${t}/index.ts`,`${t}/index.tsx`];for(let n of r)if(Ge(ye.join(e,n)))return ye.join(e,n);return null}function zn(e,t,r){let n=ge(e);if(E.isObjectLiteralExpression(n)){let s=Ke(n.getText());return{cardType:s.cardType,schemaVersion:s.schemaVersion}}if(E.isStringLiteral(n))return{cardType:n.text};if(E.isIdentifier(n)){let s=t[n.text];if(!s)return null;let i=Jn(r,s.replace(/^\.\//,""));return i?{resolved:i}:null}return null}async function $a(e){let t=ye.join(e,"src/server/index.ts");if(!Ge(t))return{cardTypes:[],schemaVersions:{},keyMismatches:[],registerMissing:!1};let r=await L(t),n=cr(r),s=ye.join(e,"src/server"),i=[],o={},a=[],c=Ct(r,"serverModule");if(c){let l=!1;if(Object.keys(c).length>0){let p=We(r,"serverModule");l=!p||!ar(p)}for(let[p,u]of Object.entries(c)){let d=zn(u,n,s);if(d)if(d.resolved){let f=await L(d.resolved),g=Ke(f);g.cardType&&(i.push(g.cardType),g.schemaVersion&&(o[g.cardType]=g.schemaVersion),p!==g.cardType&&a.push({key:p,cardType:g.cardType}))}else d.cardType&&(i.push(d.cardType),d.schemaVersion&&(o[d.cardType]=d.schemaVersion),p!==d.cardType&&a.push({key:p,cardType:d.cardType}))}return{cardTypes:[...new Set(i)],schemaVersions:o,keyMismatches:a,registerMissing:l}}for(let l of Ln(r)){if(l.includes("cardType:")){let g=Ke(l);g.cardType&&(i.push(g.cardType),g.schemaVersion&&(o[g.cardType]=g.schemaVersion));continue}if(/^[a-zA-Z0-9][\w-]*$/.test(l)&&!n[l]){i.push(l);continue}let p=n[l];if(!p)continue;let u=Jn(s,p.replace(/^\.\//,""));if(!u)continue;let d=await L(u),f=Ke(d);f.cardType&&(i.push(f.cardType),f.schemaVersion&&(o[f.cardType]=f.schemaVersion))}return{cardTypes:[...new Set(i)],schemaVersions:o,keyMismatches:a,registerMissing:!1}}function ja(e,t){return oe(e).statements.some(n=>E.isVariableStatement(n)&&n.declarationList.declarations.some(s=>E.isIdentifier(s.name)&&s.name.text===t))}async function Ea(e){let t=ye.join(e,"src/client/index.ts");if(!Ge(t))return!1;let r=await L(t);if(!ja(r,"clientModule"))return!1;let n=Ct(r,"clientModule");if(!n||Object.keys(n).length===0)return!1;let s=We(r,"clientModule");return!s||!ar(s)}async function qe(e){let t=await z(e.appDir),r=[];for(let n of t){let s={};for(let c of n.descriptor.contributes.cards??[])s[c.cardType]=c.schemaVersion??1;let i=ye.join(n.dir,"src/client/index.ts"),o=Ge(i)?Sa(await L(i)):[],a=await $a(n.dir);r.push({id:n.id,declared:s,clientMap:o,serverRegistered:a.cardTypes,serverSchemaVersions:a.schemaVersions,serverKeyMismatches:a.keyMismatches,serverRegisterMissing:a.registerMissing,clientRegisterMissing:await Ea(n.dir)})}return r}function Dt(e){return E.isStringLiteral(e)||E.isNumericLiteral(e)||e.kind===E.SyntaxKind.NullKeyword||e.kind===E.SyntaxKind.TrueKeyword||e.kind===E.SyntaxKind.FalseKeyword?!0:E.isPrefixUnaryExpression(e)&&e.operator===E.SyntaxKind.MinusToken?Dt(e.operand):E.isArrayLiteralExpression(e)?e.elements.every(t=>E.isOmittedExpression(t)||Dt(t)):E.isObjectLiteralExpression(e)?e.properties.every(t=>E.isPropertyAssignment(t)&&Dt(t.initializer)):!1}function Vn(e){for(let t of e.properties)if(E.isPropertyAssignment(t)&&E.isIdentifier(t.name)&&t.name.text==="sampleData"){let r=ge(t.initializer);return E.isObjectLiteralExpression(r)?r.properties.length===0?"empty":Dt(r)?"ok":"non-literal":"non-literal"}return"missing"}function Ra(e){let t=oe(e),r={};for(let n of t.statements){if(E.isVariableStatement(n)){for(let s of n.declarationList.declarations)if(E.isIdentifier(s.name)&&s.initializer){let i=ge(s.initializer);E.isObjectLiteralExpression(i)&&(r[s.name.text]=i)}}if(E.isExportAssignment(n)&&!n.isExportEquals){let s=ge(n.expression);if(E.isObjectLiteralExpression(s))return s;if(E.isIdentifier(s)&&r[s.text])return r[s.text]}}return null}async function Un(e){let t=ye.join(e,"src/server/index.ts");if(!Ge(t))return[];let r=await L(t),n=cr(r),s=ye.join(e,"src/server"),i=Ct(r,"serverModule");if(!i)return[];let o=[];for(let[a,c]of Object.entries(i)){let l=zn(c,n,s);if(l){if(l.resolved){let p=await L(l.resolved),u=Ke(p).cardType??a,d=Ra(p);o.push({cardType:u,status:d?Vn(d):"missing",source:l.resolved})}else if(l.cardType){let p=ge(c),u=E.isObjectLiteralExpression(p)?Vn(p):"missing";o.push({cardType:l.cardType,status:u,source:"inline"})}}}return o}async function Bn(e){let t=[];for(let r of await qe(e)){let n=Object.keys(r.declared);if(n.length===0&&r.serverKeyMismatches.length===0&&!r.serverRegisterMissing&&!r.clientRegisterMissing)continue;for(let c of r.serverKeyMismatches)t.push({rule:"card-type-consistent",level:"error",message:`${r.id}: serverModule.cards key "${c.key}" !== meta.cardType "${c.cardType}"(key 约定 = cardType)`});r.serverRegisterMissing&&t.push({rule:"card-type-consistent",level:"error",message:`${r.id}: serverModule 声明了 cards 但 register 内未调用 ctx.cards.registerMap(cards)(注册动作缺失,运行时缺卡)`}),r.clientRegisterMissing&&t.push({rule:"card-type-consistent",level:"error",message:`${r.id}: clientModule 声明了 cards 但 register 内未调用 ctx.cards.registerMap(cards)(注册动作缺失,运行时缺卡)`});let s=n.filter(c=>!r.clientMap.includes(c));s.length>0&&t.push({rule:"card-type-consistent",level:"error",message:`${r.id}: 声明卡片 ${s.join(",")} 未在客户端 cards map 导出`});let i=n.filter(c=>!r.serverRegistered.includes(c));i.length>0&&t.push({rule:"card-type-consistent",level:"error",message:`${r.id}: 声明卡片 ${i.join(",")} 未在服务端注册(serverModule.cards meta / cards.register)`});let o=r.clientMap.filter(c=>!n.includes(c));o.length>0&&t.push({rule:"card-type-consistent",level:"warning",message:`${r.id}: 客户端导出未声明的卡片 ${o.join(",")}`});let a=r.serverRegistered.filter(c=>!n.includes(c));a.length>0&&t.push({rule:"card-type-consistent",level:"warning",message:`${r.id}: 服务端注册未声明的卡片 ${a.join(",")}`})}return t}async function Hn(e){let t=[],r=await qe(e),n={};for(let i of r)for(let o of i.serverRegistered)o in n?n[o]+=`,${i.id}`:n[o]=i.id;if(Object.keys(n).length===0)return t;let s=new Set;for(let i of r)for(let o of i.clientMap)s.add(o);for(let[i,o]of Object.entries(n))s.has(i)||t.push({rule:"client-card-cover",level:"error",message:`服务端注册卡片 ${i}(模块 ${o})未出现在应用客户端装配(漏装配)`});return t}import{existsSync as lr}from"fs";import{readdir as pr,stat as Da}from"fs/promises";import Me from"path";async function Wn(e){let t=[],r=Me.join(e.appDir,"packages");if(!lr(r))return t;let n=new Map;for(let i of await pr(r,{withFileTypes:!0})){if(!i.isDirectory())continue;let o=Z(Me.join(r,i.name));o?.name&&o.name.startsWith("@tbox.cn/app-contracts")&&n.set(o.name,o.version??"0.0.0")}let s=Me.join(e.appDir,"node_modules","@tbox.cn");if(lr(s))for(let i of await pr(s,{withFileTypes:!0})){let o=Me.join(s,i.name),a=i.isDirectory();if(!a&&i.isSymbolicLink())try{a=(await Da(o)).isDirectory()}catch{a=!1}if(!a)continue;let c=Z(o);c?.name&&c.name.startsWith("@tbox.cn/app-contracts")&&n.set(c.name,c.version??"0.0.0")}for(let i of await pr(r,{withFileTypes:!0})){if(!i.isDirectory())continue;let o=Me.join(r,i.name);if(!lr(Me.join(o,"tbox.module.json")))continue;let a=Z(o),c={...a?.dependencies??{},...a?.peerDependencies??{}};for(let[l,p]of Object.entries(c)){if(!l.startsWith("@tbox.cn/app-contracts"))continue;let u=n.get(l);if(!u||p==="*"||p.startsWith("workspace:")||p.startsWith("catalog:")||p.replace(/^[\^~]/,"")===u)continue;Rt(p,u)||t.push({rule:"contract-version",level:"error",message:`${i.name}: 契约 ${l} 范围 ${p} 与实装 ${u} 无交集`})}}return t}import{existsSync as Ca}from"fs";import{readdir as Ta}from"fs/promises";import Ma from"path";async function Kn(e){let t=[],r=new Set,n=Ma.join(e.appDir,"packages");if(Ca(n))for(let f of await Ta(n,{withFileTypes:!0}))f.isDirectory()&&r.add(f.name);for(let f of e.declared)r.add(f.id);let s=new Set;for(let f of se)for(let g of e.actual[f.kind]?.moduleIds??[])s.add(g);let i=new Map,o=await z(e.appDir);for(let f of o){let g=(f.descriptor.dependencies?.modules??[]).map(m=>m.id);i.set(f.id,g)}let a=0,c=1,l=2,p=new Map,u=[];function d(f,g){p.set(f,c),g.push(f);for(let m of i.get(f)??[]){let h=p.get(m)??a;if(h===c){let v=g.indexOf(m);v>=0&&u.push([...g.slice(v),m])}else h===a&&d(m,g)}g.pop(),p.set(f,l)}for(let f of i.keys())(p.get(f)??a)===a&&d(f,[]);for(let f of u)t.push({rule:"module-deps-assembled",level:"error",message:`dependencies.modules 声明层存在循环依赖:${f.join(" → ")}`});for(let f of o)for(let g of f.descriptor.dependencies?.modules??[]){if(g.required&&!r.has(g.id)){t.push({rule:"module-deps-assembled",level:"error",message:`${f.id}: 依赖模块 ${g.id} 未安装(缺失 packages/${g.id} 或 npm 清单)`});continue}o.some(h=>h.id===g.id)&&g.required&&!s.has(g.id)&&t.push({rule:"module-deps-assembled",level:"error",message:`${f.id}: 依赖业务模块 ${g.id} 已安装但未装配(modules.ts 缺行,运行 sync)`})}return t}import{existsSync as ur}from"fs";import{readdir as Ia}from"fs/promises";import{createRequire as Aa}from"module";import{realpathSync as Oa}from"fs";import Ie from"path";async function Gn(e){let t=[],r=["react","zod","@mastra/core"],n=["apps/client","apps/server","packages/app-sdk","packages/contracts"],s=Ie.join(e.appDir,"packages");if(ur(s))for(let i of await Ia(s,{withFileTypes:!0}))i.isDirectory()&&ur(Ie.join(s,i.name,"package.json"))&&n.push(Ie.join("packages",i.name));for(let i of r){let o=new Map;for(let a of n){let c=Ie.join(e.appDir,a);if(!ur(Ie.join(c,"package.json")))continue;let l=Pa(c,i);if(l){let p=o.get(l)??[];p.push(a),o.set(l,p)}}o.size>1&&t.push({rule:"singleton",level:"error",message:`${i} 解析结果不唯一:${[...o.entries()].map(([a,c])=>`${a}(${c.join(",")})`).join(" vs ")}`})}return t}function Pa(e,t){try{let r=Aa(Ie.join(e,"__noop__.js"));return Oa(r.resolve(t))}catch{return null}}import{existsSync as qn}from"fs";import dr from"path";var La=new Set(["@tbox.cn/app-sdk","@tbox.cn/app-sdk/server","@tbox.cn/app-sdk/client","@tbox.cn/app-sdk/platform","@tbox.cn/app-sdk/platform/code-inspect"]),Fa=[{re:/^@mastra\/core/,label:"@mastra/core*(框架内部,改经 @tbox.cn/app-sdk)"},{re:/^@ag-ui\//,label:"@ag-ui/*(框架内部,改经 @tbox.cn/app-sdk)"},{re:/^@ai-sdk\//,label:"@ai-sdk/*(框架内部)"},{re:/^ai$/,label:"ai(框架内部)"},{re:/^zustand$/,label:"zustand(框架内部)"}];async function Xn(e){let t=[],r=["apps","packages"];for(let n of r){let s=dr.join(e.appDir,n);if(!qn(s))continue;let i=[];await $e(s,e.appDir,i);for(let o of i){if(o.startsWith("packages/app-sdk/")||o.startsWith("packages/contracts/"))continue;let a=await L(dr.join(e.appDir,o));for(let c of a.matchAll(/from\s+['"]([^'"]+)['"]/g)){let l=c[1];if(l.startsWith("@tbox.cn/app-sdk/")&&!La.has(l))t.push({rule:"sdk-internal-import",level:"error",message:`${o}: 不允许 import SDK 内部路径 ${l}`});else if(l.startsWith("@tbox.cn/app-contracts/"))t.push({rule:"sdk-internal-import",level:"error",message:`${o}: 不允许 import 契约子路径 ${l}(仅 @tbox.cn/app-contracts)`});else if(_a(e.appDir,o))for(let p of Fa)p.re.test(l)&&t.push({rule:"sdk-internal-import",level:"error",message:`${o}: 模块不允许直接 import ${p.label}`})}}}return t}function _a(e,t){let r=t.match(/^packages\/([^/]+)\//);return r?qn(dr.join(e,"packages",r[1],"tbox.module.json")):!1}function Yn(e){let t=[];for(let r of se){let n=new Set(e.declared.filter(c=>St(r.kind,c)).map(c=>c.id)),s=new Set(e.actual[r.kind]?.moduleIds??[]),i=[...n].filter(c=>!s.has(c)),o=[...s].filter(c=>!n.has(c));i.length>0&&t.push({rule:"assembly-drift",level:"warning",message:`${r.path}: 已声明未装配 → ${i.join(", ")}`}),o.length>0&&t.push({rule:"assembly-drift",level:"warning",message:`${r.path}: 已装配未声明 → ${o.join(", ")}`});let a=e.actual[r.kind]?.broken??[];a.length>0&&t.push({rule:"assembly-drift",level:"warning",message:`${r.path}: 锚区破坏 → ${a.join(", ")}`})}return t}async function Zn(e){let t=[];for(let r of await qe(e))for(let[n,s]of Object.entries(r.declared)){let i=r.serverSchemaVersions[n]??1;i!==s&&t.push({rule:"schema-version",level:"error",message:`${r.id}: 卡片 ${n} contributes.schemaVersion=${s} 与 meta schemaVersion=${i} 不一致`})}return t}import{existsSync as Na}from"fs";import Qn from"path";var Va=["/webhook","/upload","/demo","/run"];async function es(e){let t=[];for(let r of await z(e.appDir)){let n=Qn.join(r.dir,"src/server");if(!Na(n))continue;let s=[];await $e(n,r.dir,s);for(let i of s){let o=await L(Qn.join(r.dir,i));for(let a of o.matchAll(/\.(?:post|put|patch|delete)\(\s*['"]([^'"]+)['"]/g)){let c=a[1];if(!c.startsWith("/"))continue;Va.some(p=>c.startsWith(p))||t.push({rule:"naked-write-route",level:"warning",message:`${r.id}/${i}: 裸写路由 ${a[0].replace("("," (")} 建议改走 ctx.actions.registerAction(全局动作分发器)`})}}}return t}import{existsSync as ts}from"fs";import{readdir as Ja}from"fs/promises";import rs from"path";async function ns(e){let t=[],r=rs.join(e.appDir,"packages");if(!ts(r))return t;for(let n of await Ja(r,{withFileTypes:!0})){if(!n.isDirectory())continue;let s=rs.join(r,n.name,"tbox.module.json");if(ts(s))try{let i=Ee(JSON.parse(await L(s)));i.ok||t.push({rule:"descriptor-schema",level:"error",message:`${n.name}/tbox.module.json: ${i.errors.join("; ")}`})}catch{t.push({rule:"descriptor-schema",level:"error",message:`${n.name}/tbox.module.json: JSON 解析失败`})}}return t}import{existsSync as ss}from"fs";import{readdir as za}from"fs/promises";import Xe from"path";async function os(e){let t=[];if(ss(Xe.join(e.appDir,"pnpm-workspace.template.yaml")))return t;let r=new Map;for(let n of["apps","packages"]){let s=Xe.join(e.appDir,n);if(ss(s))for(let i of await za(s,{withFileTypes:!0})){if(!i.isDirectory())continue;let o=Xe.join(s,i.name),a=Z(o);a?.name&&r.set(a.name,Xe.join(n,i.name))}}if(r.size===0)return t;for(let[n,s]of r){let i=Z(Xe.join(e.appDir,s));if(i)for(let o of["dependencies","peerDependencies","devDependencies"]){let a=i[o];if(!(!a||typeof a!="object"))for(let[c,l]of Object.entries(a))typeof l!="string"||!l.startsWith("workspace:")||r.has(c)||t.push({rule:"workspace-ref-resolved",level:"error",message:`${s}: workspace:* 引用 ${c} 未命中任何成员(packages/ 或 apps/)`})}}return t}import{existsSync as Ua}from"fs";import Ba from"path";var Ha=["apps/server/src/auth","apps/server/src/agent","apps/server/src/gateway","apps/server/src/http","apps/server/src/plugins/integration.ts","apps/server/src/config/tts-config.ts","apps/server/src/config/model-providers.ts","apps/client/src/env","apps/client/src/bridge","apps/client/src/adapters","apps/client/src/services/http.ts","apps/client/src/services/auth-client.ts","apps/client/src/services/user-id.ts","apps/client/src/services/tbox-session.ts"];function is(e){let t=[];for(let r of Ha)Ua(Ba.join(e.appDir,r))&&t.push({rule:"legacy-platform-files",level:"error",message:`${r} 为旧形态平台文件(007:平台能力已下沉 @tbox.cn/app-sdk)。请删除并改用 SDK API(server: createAuthRuntime/createPlatformApiRouter/createTtsProxy/createModelProvider/createPluginIntegration;client: createAuthClient/createPlatformAdapters/createPlatformApi/configureRuntime),详见 .agents/notes/archived/architecture/2026-08-12-platform-capabilities-sink.md。`});return t}import{existsSync as as,readFileSync as Wa}from"fs";import{readdir as Ka}from"fs/promises";import{createRequire as Ga}from"module";import Ye from"path";function cs(e,t){try{let n=Ga(Ye.join(e.appDir,"package.json")).resolve(`${t}/package.json`);return Ye.dirname(n)}catch{return}}function qa(e){let t=[Ye.join(e,"src/server/index.ts"),Ye.join(e,"src/server/index.tsx")];for(let r of t)if(as(r))return Wa(r,"utf8");return""}function Xa(e){let t=[];for(let r of e.matchAll(/patterns\s*:\s*\[([^\]]*)\]/g))for(let n of r[1].matchAll(/['"]([^'"]+)['"]/g))t.push(n[1]);return t}async function ls(e){let t=[],r=new Map;for(let n of e.declared){if(!n.hasServerEntry)continue;let s=cs(e,n.pkg);if(!s)continue;let i=Xa(qa(s));for(let o of i){let a=r.get(o)??[];a.push(n.id),r.set(o,a)}}for(let[n,s]of r)s.length>1&&t.push({rule:"intent-overlap",level:"warning",message:`意图词 "${n}" 在多个模块声明(${s.join(", ")})——先注册先命中`});return t}async function ps(e){let t=[],r=new Map;for(let n of e.declared){if(!n.hasServerEntry)continue;let s=cs(e,n.pkg);if(!s)continue;let i=Ye.join(s,"skills");if(as(i))try{let o=(await Ka(i,{withFileTypes:!0})).filter(a=>a.isDirectory()).map(a=>a.name);for(let a of o){let c=r.get(a)??[];c.push(n.id),r.set(a,c)}}catch{}}for(let[n,s]of r)s.length>1&&t.push({rule:"skill-name-conflict",level:"warning",message:`skill "${n}" 在多个模块声明(${s.join(", ")})——后注册覆盖`});return t}async function us(e){let t=[];for(let r of await z(e.appDir))for(let n of await Un(r.dir)){if(n.status==="ok")continue;let s=n.status==="missing"?"缺失(dev 卡片预览页 / 模块单测不可用)":n.status==="empty"?"为空对象(至少一组可展示数据)":"非字面量(引用常量/函数调用,AST 无法离线求值——静态检查无法求值,运行时预览不受影响)";t.push({rule:"sample-data-valid",level:"warning",message:`${r.id}/${n.cardType}: sampleData ${s}`})}return t}import{existsSync as ds}from"fs";import{readdir as fs}from"fs/promises";import Tt from"path";async function ms(e){let t=[],r=Tt.join(e.appDir,"packages");if(!ds(r))return t;for(let n of await fs(r,{withFileTypes:!0})){if(!n.isDirectory()||n.name.startsWith("contracts-"))continue;let s=Tt.join(r,n.name,"src");if(!ds(s))continue;let i=[];await gs(s,s,i),i.length>0&&t.push({rule:"module-console-logger",level:"warning",message:`${n.name}: 源码含裸 console 调用 ${i.length} 处(${i.slice(0,3).join("、")}${i.length>3?"…":""})——建议改用 ctx.logger(见 docs/reference/modules.md 模块日志规范)`})}return t}async function gs(e,t,r){for(let n of await fs(e,{withFileTypes:!0})){let s=Tt.join(e,n.name);if(n.isDirectory()){if(n.name==="__tests__"||n.name==="node_modules")continue;await gs(s,t,r);continue}if(!/\.tsx?$/.test(n.name)||/\.test\.tsx?$/.test(n.name))continue;let i=await L(s),o=Tt.relative(t,s);i.split(`
87
- `).forEach((c,l)=>{/console\.(log|warn|error|info|debug)\s*\(/.test(c)&&r.push(`${o}:${l+1}`)})}}import{existsSync as ys}from"fs";import{readdir as hs}from"fs/promises";import Mt from"path";async function vs(e){let t=[],r=Mt.join(e.appDir,"packages");if(!ys(r))return t;for(let n of await hs(r,{withFileTypes:!0})){if(!n.isDirectory()||n.name.startsWith("contracts-"))continue;let s=Mt.join(r,n.name,"src");if(!ys(s))continue;let i=[];await ws(s,s,i),i.length>0&&t.push({rule:"module-mall-scope",level:"warning",message:`${n.name}: 源码含手解 attributes.mall ${i.length} 处(${i.slice(0,3).join("、")}${i.length>3?"…":""})——改用 parseMallScope/extractMallScope/withMallScopeFromQuery(见 docs/reference/modules.md 读取入口族)`})}return t}var Ya=/\.attributes\??\.?\bmall\b|\.attributes\??\.?\[\s*['"]mall['"]\s*\]/,Za=/as\s*\{[^}]*\bmall\b/,Qa=/^\s*(\*|\/\/|\/\*)/;async function ws(e,t,r){for(let n of await hs(e,{withFileTypes:!0})){let s=Mt.join(e,n.name);if(n.isDirectory()){if(n.name==="__tests__"||n.name==="node_modules")continue;await ws(s,t,r);continue}if(!/\.tsx?$/.test(n.name)||/\.test\.tsx?$/.test(n.name))continue;let i=await L(s),o=Mt.relative(t,s);i.split(`
88
- `).forEach((c,l)=>{Qa.test(c)||(Ya.test(c)||Za.test(c))&&r.push(`${o}:${l+1}`)})}}import{existsSync as bs,readFileSync as ks}from"fs";import xs from"path";function ec(e,t=process.env,r="<config>"){let n=Pr(e,t);if(n.missing.length>0)throw new Error(`配置文件 ${r} 引用的环境变量缺失:${n.missing.join("、")}(先 source .real-env/env.sh <vendor>[-<variant>] 后重试)`);return n.text??e}async function Ss(e){let t=xs.join(e.appDir,"config","deployments","development.json");if(bs(t))try{let m=JSON.parse(ks(t,"utf8"));if(m&&typeof m=="object"&&"malls"in m)return[{rule:"integration-services",level:"error",message:"config/deployments/development.json 已退役(部署控制面并入 config/integrations.json 的 instances 注册表 + defaultInstanceId)——迁移后删除该文件(malls → instances[].id/attributes,defaultMallId → defaultInstanceId)"}]}catch{}let r=xs.join(e.appDir,"config","integrations.json");if(!bs(r))return[];let n=await rt(e.appDir);if(!n.strictValidation){let m=n.version===null;return[{rule:"integration-services",level:m?"warning":"error",message:m?"integrations: contracts 未安装——pnpm install 后重试(安装后启用严格校验与求值诊断)":`integrations: contracts 严格校验面不可用(${n.version},需 ≥0.9)——${n.notes[0]??"升级应用 @tbox.cn/app-contracts 依赖后可用"}`}]}let{resolveEffectiveService:s,buildSupplyLookup:i,moduleDomainOf:o,normalizeInstances:a,RESOURCE_TYPE_IDS:c}=n.module,l;try{l=JSON.parse(ec(ks(r,"utf8"),process.env,r))}catch(m){return[{rule:"integration-services",level:"error",message:`config/integrations.json 非法 JSON:${m.message}`}]}let p=l?.services;if(!p||typeof p!="object"||Array.isArray(p))return[{rule:"integration-services",level:"error",message:"config/integrations.json 缺 services(Record<service, {provider, instances}>)"}];let u=Hr(e.appDir),d=i(Wr(e.appDir)),f=Fr(e.appDir,u,l,process.env);return Lr({contracts:{resolveEffectiveService:s,buildSupplyLookup:i,moduleDomainOf:o,normalizeInstances:a,RESOURCE_TYPE_IDS:c},integrations:l,supplies:d,...f}).map(m=>({rule:"integration-services",level:m.severity,message:m.message,...m.code!==void 0?{code:m.code}:{},...m.service!==void 0?{service:m.service}:{},...m.module!==void 0?{module:m.module}:{},...m.instance!==void 0?{instance:m.instance}:{}}))}async function $s(e){return(await hn(e.appDir)).map(r=>({rule:"codegen-ref-resolved",level:"error",message:r}))}import{existsSync as js}from"fs";import{readdir as Es}from"fs/promises";import It from"path";async function Rs(e){let t=[],r=It.join(e.appDir,"packages");if(!js(r))return t;for(let n of await Es(r,{withFileTypes:!0})){if(!n.isDirectory()||n.name.startsWith("contracts-"))continue;let s=It.join(r,n.name,"src");if(!js(s))continue;let i=[];await Ds(s,s,i),i.length>0&&t.push({rule:"module-auth-context",level:"error",message:`${n.name}: 源码读 ctx.auth 全局单例 ${i.length} 处(${i.slice(0,3).join("、")}${i.length>3?"…":""})——ctx.auth 已于 app-sdk 0.11.0 拆除,改用显式通道(handle 第四参 reqCtx / getToolRequestContext,见 docs/reference/modules.md)`})}return t}async function Ds(e,t,r){for(let n of await Es(e,{withFileTypes:!0})){let s=It.join(e,n.name);if(n.isDirectory()){if(n.name==="__tests__"||n.name==="node_modules")continue;await Ds(s,t,r);continue}if(!/\.tsx?$/.test(n.name)||/\.test\.tsx?$/.test(n.name))continue;let i=await L(s),o=It.relative(t,s);i.split(`
89
- `).forEach((c,l)=>{/ctx\.auth\.(getContext|setContext|requireIdentity|isAnonymous)\s*\(/.test(c)&&r.push(`${o}:${l+1}`)})}}import fr from"path";import he from"typescript";var Cs="presentation",Ts="labelsEmbedded",tc=new Set([".ts",".tsx"]);function rc(e){let t;try{t=oe(e)}catch{return[]}let r=[],n=s=>{if(he.isPropertyAssignment(s)&&(he.isIdentifier(s.name)||he.isStringLiteral(s.name))&&s.name.text===Cs&&he.isObjectLiteralExpression(s.initializer)){let i=s.initializer.properties.some(c=>c.name!==void 0&&he.isIdentifier(c.name)&&c.name.text==="variant"),o=s.initializer.properties.some(c=>c.name!==void 0&&he.isIdentifier(c.name)&&c.name.text===Ts),a=s.initializer.properties.some(he.isSpreadAssignment);i&&!o&&!a&&r.push(t.getLineAndCharacterOfPosition(s.getStart(t)).line+1)}he.forEachChild(s,n)};return n(t),r}async function Ms(e){let t=[];for(let r of await z(e.appDir)){let n=fr.join(r.dir,"src"),s=[];await $e(n,n,s);for(let i of s){if(!tc.has(fr.extname(i)))continue;let o=await L(fr.join(n,i));if(o.includes(Cs))for(let a of rc(o))t.push({rule:"card-face-labels",level:"error",message:`${r.id}: src/${i}:${String(a)} 的 presentation 缺 ${Ts}——卡面图自带卡名与「我的积分」字样,缺省时前端会再叠一层导致文字重叠;卡图确实无字请显式写 false`})}}return t}import{existsSync as Is}from"fs";import{readdir as As}from"fs/promises";import mr from"path";async function Os(e){let t=[],r=mr.join(e.appDir,"packages");if(!Is(r))return t;for(let n of await As(r,{withFileTypes:!0})){if(!n.isDirectory()||n.name.startsWith("contracts-"))continue;let s=mr.join(r,n.name,"src");if(!Is(s))continue;let i=await Ps(s);if(i.length===0)continue;let o=i.map(u=>u.text).join(`
90
- `),a=new Set;for(let u of o.matchAll(/internalTool\s*\(\s*(\w+)\s*\)/g))a.add(u[1]);let c=[...o.matchAll(/const\s+(\w+)\s*=\s*createTool\s*\(/g)],l=[],p=[];for(let u=0;u<c.length;u++){let d=c[u],f=d[1],g=d.index??0,m=u+1<c.length?c[u+1].index??g+4e3:g+4e3,v=o.slice(g,Math.min(m,g+8e3)).includes("模型勿调用"),S=a.has(f);v&&!S?l.push(f):S&&!v&&p.push(f)}l.length>0&&t.push({rule:"module-internal-tool",level:"warning",message:`${n.name}: 工具 description 含「模型勿调用」但未 internalTool 标记(${l.join("、")})——模型面照常可见,撑大静态前缀且有幻觉调用面(见 docs/reference/modules.md 内部工具规约)`}),p.length>0&&t.push({rule:"module-internal-tool",level:"warning",message:`${n.name}: internalTool 标记的工具 description 缺「模型勿调用」标注(${p.join("、")})——标注是 doctor 静态面唯一可查锚点,补齐描述`})}return t}async function Ps(e,t=""){let r=[];for(let n of await As(e,{withFileTypes:!0})){let s=mr.join(e,n.name),i=t?`${t}/${n.name}`:n.name;if(n.isDirectory()){if(n.name==="__tests__"||n.name==="node_modules")continue;r.push(...await Ps(s,i));continue}/\.tsx?$/.test(n.name)&&(/\.test\.tsx?$/.test(n.name)||r.push({rel:i,text:await L(s)}))}return r}var nc=[{name:"workspace-dag",run:In},{name:"register-pure",run:Nn},{name:"card-type-consistent",run:Bn},{name:"client-card-cover",run:Hn},{name:"contract-version",run:Wn},{name:"module-deps-assembled",run:Kn},{name:"singleton",run:Gn},{name:"sdk-internal-import",run:Xn},{name:"assembly-drift",run:Yn},{name:"schema-version",run:Zn},{name:"naked-write-route",run:es},{name:"descriptor-schema",run:ns},{name:"workspace-ref-resolved",run:os},{name:"legacy-platform-files",run:is},{name:"intent-overlap",run:ls},{name:"skill-name-conflict",run:ps},{name:"sample-data-valid",run:us},{name:"module-console-logger",run:ms},{name:"module-mall-scope",run:vs},{name:"integration-services",run:Ss},{name:"codegen-ref-resolved",run:$s},{name:"module-auth-context",run:Rs},{name:"card-face-labels",run:Ms},{name:"module-internal-tool",run:Os}];async function q(e,t){let r=[],n=t?.only?.length?new Set(t.only):null,s=new Set(t?.skip??[]);for(let i of nc)if(!(n&&!n.has(i.name))&&!s.has(i.name))try{r.push(...await i.run(e))}catch(o){r.push({rule:i.name,level:"error",message:`规则执行异常: ${o?.message??String(o)}`})}return r}function Ls(e,t){return!t.has(e)||e.startsWith("contracts-")}async function Fs(e,t,r,n=[]){let s=await z(e),i=new Set(s.map(b=>b.id)),o=new Set(r?.map(b=>b.id)??[]),a=new Map;for(let b of s)a.set(b.id,b.descriptor.version??"0.0.0");let c=new Map(n.map(b=>[b.id,b.deps])),l=new Set,p=[],u=[...t,...n.map(b=>b.id)];for(;u.length>0;){let b=u.shift();if(l.has(b))continue;l.add(b);let k=s.find(j=>j.id===b),O=c.get(b)??k?.descriptor.dependencies?.modules??[];for(let j of O)p.push(j),!l.has(j.id)&&(i.has(j.id)||c.has(j.id))&&u.push(j.id)}let d=0,f=1,g=2,m=new Map,h=[];function v(b,k){m.set(b,f),k.push(b);for(let O of S.get(b)??[]){let j=m.get(O)??d;if(j===f){let ee=k.indexOf(O);ee>=0&&h.push([...k.slice(ee),O])}else j===d&&v(O,k)}k.pop(),m.set(b,g)}let S=new Map,$=new Map(s.map(b=>[b.id,b]));for(let b of l){let k=$.get(b),O=c.get(b)??k?.descriptor.dependencies?.modules??[];S.set(b,O.filter(j=>l.has(j.id)).map(j=>j.id))}for(let b of l)(m.get(b)??d)===d&&v(b,[]);let R=[...l].filter(b=>!o.has(b)),F=new Map;for(let b of R)F.set(b,0);let A=new Map;for(let b of R)for(let k of S.get(b)??[])if(F.has(k)){F.set(b,(F.get(b)??0)+1);let O=A.get(k);O?O.push(b):A.set(k,[b])}let N=R.filter(b=>(F.get(b)??0)===0),P=[];for(;N.length>0;){let b=N.shift();P.push(b);for(let k of A.get(b)??[]){let O=(F.get(k)??0)-1;F.set(k,O),O===0&&N.push(k)}}P.length,R.length;let w=new Set,D=new Set,M=[];for(let b of p){let k=b.id;if((!o.has(k)||!a.has(k))&&(Ls(k,i)?w.add(k):Ls(k,i)||D.add(k)),b.range&&a.has(k)){let O=a.get(k);b.range!=="*"&&!b.range.startsWith("workspace:")&&(Rt(b.range,O)||M.push(`${k}: 依赖范围 ${b.range} 与目标版本 ${O} 无交集`))}}return{order:P,contracts:[...w],business:[...D],cycles:h,conflicts:M}}function oc(e){let t=Q.join(e,"tbox.module.json");if(!ve(t))return null;try{let r=Ee(JSON.parse(yr(t,"utf8")));return r.ok?r.value:null}catch{return null}}function ic(e,t){if(!e)return null;let r=Q.dirname(e),n=Q.join(r,t);if(ve(Q.join(n,"package.json")))return n;try{let s=sc(r).find(i=>i.endsWith(".tgz")&&i.includes(`-${t}-`));if(s)return Q.join(r,s)}catch{}return null}function gr(e,t){let r=Q.join(e,"packages",t);return ve(r)&&!gt(r)?!0:B(e)?.npmModules.some(s=>s.id===t&&s.mode==="sdk")??!1}async function _s(e){await Ns(e,new Set,!1)}async function Ns(e,t,r){let n=[];try{await ac(e,t,r,n)}finally{for(let s of n)s.dispose()}}async function ac(e,t,r,n){let s=process.cwd();if(!B(s))throw new Error("当前目录不是 tbox-app 应用(缺 .tbox/app.json)");let i,o=null,a=null,c=!!e.source&&Ce(e.source);if(e.mode==="local"){let h=e.pkg;i=h.startsWith("module-")?h:`module-${h}`,ke(i,`--mode local ${e.pkg}`)}else{if(!e.source)throw new Error(`--mode ${e.mode} 需要 --source <目录或 tgz 或 registry 包>`);if(!(c&&!ve(Q.resolve(e.source)))&&!e.source.endsWith(".tgz")&&!re.isUsable(e.source))throw new Error(`模块源无效(缺 package.json): ${e.source}`);a=fe(e.source,e.registry),(a.source instanceof U||a.source instanceof de)&&n.push(a.source);let v=e.pkg.replace(/@[^/]+$/,"");i=wn(v),ke(i,`--mode ${e.mode} ${e.pkg}`),o=oc(a.sourceDir)}if(r&&gr(s,i)){console.log(` ⚠️ 依赖 ${i} 已安装,跳过`);return}if(!r&&gr(s,i)){let h=ve(Q.join(s,"packages",i))?`packages/${i}`:"manifest 已登记(sdk 包,无本地目录)";throw new Error(`模块 ${i} 已存在(${h})。若要重新展开请先 remove 或手动处理;装配唯一覆盖入口为 sync --force`)}if(t.has(i))return;if(t.add(i),!e.noDeps){let h=o?.dependencies?.modules??[],v=await Fs(s,[],void 0,[{id:i,deps:h}]);if(v.cycles.length>0)throw new Error(`依赖环:${v.cycles.map($=>$.join(" → ")).join(";")}`);for(let $ of v.conflicts)console.warn(` ⚠️ 依赖版本冲突: ${$}`);let S=[...v.contracts,...v.order].filter($=>$!==i&&!gr(s,$));for(let $ of[...new Set(S)]){let R=/^(module|scenario|contracts|provider)-/.test($)?`@tbox.cn/app-${$}`:`@tbox.cn/${$}`,F=c?R:ic(e.source,$);if(!F){console.warn(` ⚠️ 依赖 ${$} 未安装且未找到源(--source 兄弟目录/tgz),可 --no-deps 跳过`);continue}let A=fe(F,e.registry);(A.source instanceof U||A.source instanceof de)&&n.push(A.source);let N=ve(Q.join(A.sourceDir,"tbox.module.json")),P=un(R,N);await Ns({pkg:R,mode:P,source:F,registry:e.registry},t,!0)}}let l;if(e.mode==="local"){let h=e.pkg,v=h.startsWith("module-")?h:`module-${h}`;await kn(s,h),l={id:v,package:`@app/${v}`,version:"0.1.0",mode:"local"},await He(s,`@app/${v}`,"add")}else{let h=a.sourceDir,v=a.source.resolveVersion();e.mode==="codegen"&&(yt(h),await bn(s,h,{id:i,package:e.pkg.replace(/@[^/]+$/,""),version:v,mode:"codegen",baseVersion:v},Se(s).values()),await He(s,mt(i),"add")),l={id:i,package:e.pkg.replace(/@[^/]+$/,""),version:v,mode:e.mode,...e.mode==="codegen"?{baseVersion:v}:{}}}let p=B(s);if(await te(s,Gr(p,l)),l.mode==="codegen"){let h=await vt(s,Se(s).values());h.length>0&&console.log(` codegen 引用同步: ${h.join(", ")}`)}let u=await me(s);u.changedFiles.length>0&&console.log(` 装配更新: ${u.changedFiles.join(", ")}`);for(let h of u.warnings)console.warn(` ⚠️ ${h}`);for(let h of u.depConflicts)console.warn(` ⚠️ 依赖冲突: ${h}`);let d=await G(s),g=(await q({appDir:s,declared:u.declared,actual:d},{skip:["integration-services"]})).filter(h=>h.level==="error");if(g.length>0){console.error("❌ doctor 错误:");for(let h of g)console.error(` - [${h.rule}] ${h.message}`);process.exitCode=1}let m=await Ne(s);m.generated?console.log(` ⚡ 已生成 mock 槽绑定(config/integrations.json:${m.services.join(", ")})`):m.reason==="in-place"&&console.log(" ℹ config/integrations.json 已在场,跳过 mock 绑定生成"),console.log(`✅ 已安装 ${l.package}(mode=${e.mode}${r?", 依赖":""})`),cc(s,l.id),e.mode!=="local"&&console.log(" 下一步: pnpm install && tbox-app module doctor")}function cc(e,t){try{let r=Q.join(e,"packages",t,"package.json");if(!ve(r))return;let s=JSON.parse(yr(r,"utf8")).dependencies?.["@tbox.cn/app-contracts-mall"],i=typeof s=="string"?s.replace(/[\^~]/,""):void 0;if(!i)return;let o=Q.join(e,"pnpm-workspace.yaml");if(!ve(o))return;let l=yr(o,"utf8").match(/['"]?@tbox\.cn\/app-contracts-mall['"]?\s*:\s*['"]([^'"]+)['"]/)?.[1]?.replace(/[\^~]/,"");if(!l)return;lc(i,l)>0&&console.warn(` ⚠️ 版本配套:${t} 依赖 contracts-mall ${i}+,当前应用 catalog 为 ${l}——请升级模板或应用 catalog(015 W1)`)}catch{}}function lc(e,t){let r=e.split(".").map(Number),n=t.split(".").map(Number),s=(r[0]??0)-(n[0]??0);return Math.sign(s!==0?s:(r[1]??0)-(n[1]??0))}import pc from"path";async function Vs(e,t={}){let r=process.cwd();ke(e,"remove 参数");let n=B(r);if(!n)throw new Error("当前目录不是 tbox-app 应用(缺 .tbox/app.json)");if(!t.force){let m=[];for(let h of await z(r)){if(h.id===e)continue;let v=(h.descriptor.dependencies?.modules??[]).find(S=>S.id===e);v&&v.required&&m.push(h.id)}if(m.length>0)throw new Error(`模块 ${e} 被依赖,无法移除:${m.join(", ")}(--force 忽略)`)}let s=n.npmModules.find(m=>m.id===e),i=!!s;i&&await te(r,qr(n,e));let o=pc.join(r,"packages",e),c=gt(o)&&(s?.mode==="sdk"||!s);(c?!1:await $n(r,e))?console.log(` 已删除 packages/${e}`):c?console.log(" 已移除 manifest 登记(保留 contracts-mall SDK shim)"):s?.mode==="sdk"&&console.log(" 已移除 manifest 登记(sdk 包,无本地目录)");let p=s?.mode==="codegen"&&Je(s.package)?await yn(r,xe(s)):!1;p&&console.log(" 已恢复 contracts-mall SDK shim(@app/contracts-mall)"),!p&&!c&&(s?.mode==="codegen"||s?.mode==="local"||!i)&&await He(r,`@app/${e}`,"remove");let u=await me(r);u.changedFiles.length>0&&console.log(` 装配更新: ${u.changedFiles.join(", ")}`);for(let m of u.warnings)console.warn(` ⚠️ ${m}`);for(let m of u.depConflicts)console.warn(` ⚠️ 依赖冲突: ${m}`);let d=await G(r),g=(await q({appDir:r,declared:u.declared,actual:d})).filter(m=>m.level==="error");if(g.length>0){console.error("❌ doctor 错误:");for(let m of g)console.error(` - [${m.rule}] ${m.message}`);process.exitCode=1}console.log(c&&!i?`✅ ${e} 未登记,保留 SDK shim`:`✅ 已移除 ${e}`)}async function Js(e={}){let t=process.cwd(),r=await me(t,{force:e.force??!1});r.changedFiles.length===0?console.log("装配已同步,无变更"):console.log(`已更新装配文件: ${r.changedFiles.join(", ")}`);for(let o of r.warnings)console.warn(` ⚠️ ${o}`);for(let o of r.depConflicts)console.warn(` ⚠️ 依赖冲突: ${o}`);let n=await G(t),s=await q({appDir:t,declared:r.declared,actual:n}),i=s.filter(o=>o.level==="error");if(i.length>0){console.error("❌ doctor 错误:");for(let o of i)console.error(` - [${o.rule}] ${o.message}`);process.exitCode=1}else console.log("✅ doctor 无错误");for(let o of s.filter(a=>a.level==="warning"))console.warn(` ⚠️ [${o.rule}] ${o.message}`)}async function zs(){let e=process.cwd(),t=B(e),r=await ue(e);if(console.log(`模板版本: ${t?.templateVersion??"未知"}`),r.length===0){console.log("(无已装模块)");return}for(let i of r)console.log(` ${i.id.padEnd(28)} ${i.pkg} [${i.mode}]`);let n=new Set((t?.npmModules??[]).map(i=>i.id)),s=(await z(e)).filter(i=>!n.has(i.id));if(s.length>0){console.log(" 本地模块(未在 app.json 登记):");for(let i of s)console.log(` ${i.id}`)}}async function Us(e){let t=process.cwd(),r=await ue(t),n=await G(t),s=!1;for(let i of se){let o=i.kind,a=r.filter(g=>St(o,g)).map(g=>g.id),c=n[o]?.moduleIds??[],l=a.filter(g=>!c.includes(g)),p=c.filter(g=>!a.includes(g));e&&(l=l.filter(g=>g===e),p=p.filter(g=>g===e));let u=n[o]?.broken??[],d=n[o]?.nonStandardLines??[],f=[];u.length>0&&f.push(`⚠️ 锚区破坏: ${u.join(", ")}`),l.length>0&&f.push(` - 已声明未装配: ${l.join(", ")}`),p.length>0&&f.push(` + 已装配未声明: ${p.join(", ")}`);for(let g of d)f.push(` ? 非标行: ${g}`);if(f.length>0){s=!0,console.log(`${i.path}`);for(let g of f)console.log(` ${g}`)}}s||console.log("无漂移:声明集合与实际装配集合一致")}async function Bs(e={}){let t=process.cwd(),r=await ue(t),n=await G(t),s=await q({appDir:t,declared:r,actual:n},{only:e.only?e.only.split(",").map(a=>a.trim()).filter(Boolean):void 0,skip:e.skip?e.skip.split(",").map(a=>a.trim()).filter(Boolean):void 0}),i=s.filter(a=>a.level==="error"),o=s.filter(a=>a.level==="warning");if(e.json)return console.log(JSON.stringify({errors:i,warnings:o,rules:s},null,2)),i.length>0&&(process.exitCode=1),{issues:s};if(s.length===0)console.log("✅ doctor 全绿(结构校验通过)");else{for(let a of i)console.error(`❌ [${a.rule}] ${a.message}`);for(let a of o)console.warn(`⚠️ [${a.rule}] ${a.message}`);i.length>0?(console.error(`doctor 失败: ${i.length} 个错误`),process.exitCode=1):console.log(`doctor 通过(${o.length} 个告警)`)}return{issues:s}}import{existsSync as vr}from"fs";import{readdir as dc,readFile as Gs,unlink as fc,writeFile as mc}from"fs/promises";import Ae from"path";import{diffArrays as uc}from"diff";function Hs(e,t){let r=uc(e,t),n=[],s=0,i=null;for(let o of r)o.removed?(i?i.oldLines.push(...o.value):i={start:s,oldLines:[...o.value],newLines:[]},s+=o.value.length):o.added?i?i.newLines.push(...o.value):i={start:s,oldLines:[],newLines:[...o.value]}:(i&&(n.push(i),i=null),s+=o.value.length);return i&&n.push(i),n}function Ws(e,t,r){let n=e===""?[]:e.split(`
88
+ `}function Cn(e,t,r){let n=Et[e];return`import { ${n.importExport} as ${t} } from '${r}/${n.importSuffix}';`}function sr(e,t){return` ${t},`}import{writeFile as la}from"fs/promises";import pa from"path";import{readFileSync as da}from"fs";function ua(e){try{return JSON.parse(fa(e)??"{}")}catch{return null}}async function An(e,t,r){let n=pa.join(e,t),s=ua(n)??{},i=s.dependencies??{},o={},a=[];for(let[c,l]of Object.entries(r)){if(ut(c)||l==="workspace:*"||l.startsWith("catalog:"))continue;let p=i[c];if(!p){i[c]=l,o[c]=l;continue}if(p===l)continue;if(p==="catalog:"){let d=ce(e)?.get(c);d&&!Mn(d,l)&&a.push(`${c}: 应用 catalog ${d} 与模块要求 ${l} 无交集`);continue}let u=Mn(p,l);u?u!==p&&(i[c]=u,o[c]=u):a.push(`${c}: 已有 ${p},模块要求 ${l}`)}return s.dependencies=i,await la(n,JSON.stringify(s,null,2)+`
89
+ `,"utf8"),{merged:o,conflicts:a}}function Mn(e,t){let r=In(e),n=In(t);if(!r||!n||r.lower.major!==n.lower.major)return null;let s=(a,c)=>a.major-c.major||a.minor-c.minor||a.patch-c.patch,i=s(r.lower,n.lower)>=0?r.lower:n.lower,o=s(r.upper,n.upper)<=0?r.upper:n.upper;return s(i,o)>=0?null:s(r.lower,n.lower)>0?e:s(n.lower,r.lower)>0?t:s(r.upper,n.upper)<=0?e:t}function In(e){let t=e.match(/^([\^~]?)(\d+)\.(\d+)(?:\.(\d+))?/);if(!t)return null;let r={major:Number(t[2]),minor:Number(t[3]),patch:Number(t[4]??0)},n;return t[1]==="~"?n={major:r.major,minor:r.minor+1,patch:0}:t[1]==="^"?n=r.major===0?{major:0,minor:r.minor+1,patch:0}:{major:r.major+1,minor:0,patch:0}:n={...r,patch:r.patch+1},{lower:r,upper:n}}function fa(e){try{return da(e,"utf8")}catch{return}}async function me(e,t={}){let r=await ue(e),n=[],s=[],i=[];for(let c of se){let l=cr.join(e,c.path);if(!ar(l)){n.push(`缺少装配文件 ${c.path}`);continue}let p=await ga(l,"utf8"),u=Rt(p,c.kind,r,t.force??!1);n.push(...u.warnings.map(d=>`${c.path}: ${d}`)),u.changed&&(await ya(l,u.content,"utf8"),s.push(c.path))}let o=["apps/server/package.json","apps/client/package.json"];for(let c of r){let l=cr.join(e,"packages",c.id,"package.json");if(!ar(l))continue;let p={};try{p=JSON.parse(ma(l,"utf8")).dependencies??{}}catch{continue}for(let u of o){if(!ar(cr.join(e,u)))continue;let d=await An(e,u,p);i.push(...d.conflicts.map(f=>`${c.id} → ${u}: ${f}`))}}let a=De(e);return{declared:r,changedFiles:s,warnings:n,depConflicts:i,lockfileRefreshed:a}}import{existsSync as ha}from"fs";import{readFile as va}from"fs/promises";import wa from"path";async function G(e){let t={};for(let r of se){let n=wa.join(e,r.path);if(!ha(n)){t[r.kind]={moduleIds:[],nonStandardLines:[],broken:["missing-file"]};continue}let s=await va(n,"utf8"),i=Tn(s,r.kind);t[r.kind]={moduleIds:i.moduleIds,nonStandardLines:i.nonStandardLines,broken:i.broken}}return t}import{existsSync as Pn}from"fs";import{readdir as $a}from"fs/promises";import lr from"path";import{readFileSync as ba}from"fs";import{readFile as ka,readdir as xa}from"fs/promises";import Dt from"path";async function $e(e,t,r){let n=await xa(e,{withFileTypes:!0});for(let s of n){if(s.name==="node_modules"||s.name==="dist"||s.name===".git")continue;let i=Dt.join(e,s.name);s.isDirectory()?await $e(i,t,r):s.isFile()&&/\.(ts|tsx|mjs|js)$/.test(s.name)&&r.push(Dt.relative(t,i).split(Dt.sep).join("/"))}}async function L(e){try{return await ka(e,"utf8")}catch{return""}}function Sa(e){try{return JSON.parse(ba(e,"utf8"))}catch{return null}}function Z(e){return Sa(Dt.join(e,"package.json"))}function Ct(e,t){let r=On(e),n=On(t);if(!r||!n||r.lower.major!==n.lower.major)return null;let s=(a,c)=>a.major-c.major||a.minor-c.minor||a.patch-c.patch,i=s(r.lower,n.lower)>=0?r.lower:n.lower,o=s(r.upper,n.upper)<=0?r.upper:n.upper;return s(i,o)>=0?null:s(r.lower,n.lower)>0?e:s(n.lower,r.lower)>0?t:s(r.upper,n.upper)<=0?e:t}function On(e){let t=e.match(/^([\^~]?)(\d+)\.(\d+)(?:\.(\d+))?/);if(!t)return null;let r={major:Number(t[2]),minor:Number(t[3]),patch:Number(t[4]??0)},n;return t[1]==="~"?n={major:r.major,minor:r.minor+1,patch:0}:t[1]==="^"?n=r.major===0?{major:0,minor:r.minor+1,patch:0}:{major:r.major+1,minor:0,patch:0}:n={...r,patch:r.patch+1},{lower:r,upper:n}}async function Ln(e){let t=[],r=lr.join(e.appDir,"packages");if(!Pn(r))return t;for(let n of await $a(r,{withFileTypes:!0})){if(!n.isDirectory())continue;let s=lr.join(r,n.name);if(!Pn(lr.join(s,"tbox.module.json")))continue;let i=/^provider-/.test(n.name),o=Z(s),a={...o?.dependencies??{},...o?.peerDependencies??{}};for(let c of Object.keys(a))(/^@app\/(module|scenario)-/.test(c)||/^@tbox\.cn\/app-(module|scenario)-/.test(c))&&t.push({rule:"workspace-dag",level:"error",message:`${n.name} 依赖业务模块 ${c}(module 不得依赖 module/scenario)`}),i&&(/^@app\/(module|scenario)-/.test(c)||/^@tbox\.cn\/app-(module|scenario)-/.test(c))&&t.push({rule:"workspace-dag",level:"error",message:`${n.name} 依赖业务模块 ${c}(provider 不得依赖 module/scenario——实现自持)`})}return t}import{existsSync as Jn}from"fs";import{readdir as Ea}from"fs/promises";import zn from"path";import C from"typescript";function oe(e){return C.createSourceFile("entry.ts",e,C.ScriptTarget.Latest,!0,C.ScriptKind.TS)}function Fn(e){return e&&(C.isAsExpression(e)||C.isSatisfiesExpression(e)?e.expression:e)}function ja(e,t){let r=oe(e),n=null;function s(i){if(!n){if(C.isFunctionDeclaration(i)&&i.name?.text===t&&i.body){n=i.body;return}if(C.isVariableStatement(i)&&i.declarationList.declarations.some(o=>C.isIdentifier(o.name)&&o.name.text===t)){let o=i.declarationList.declarations.find(l=>C.isIdentifier(l.name)&&l.name.text===t),a=Fn(o.initializer);if(a&&C.isArrowFunction(a)&&a.body&&C.isBlock(a.body)){n=a.body;return}let c=_n(a,"register");if(c){n=c;return}}C.forEachChild(i,s)}}return s(r),n}function _n(e,t){if(!e||!C.isObjectLiteralExpression(e))return null;for(let r of e.properties){if(C.isMethodDeclaration(r)&&r.name.getText()===t&&r.body)return r.body;if(C.isPropertyAssignment(r)&&r.name.getText()===t&&r.initializer){let n=r.initializer;if(C.isArrowFunction(n)&&n.body&&C.isBlock(n.body)||C.isFunctionExpression(n)&&n.body)return n.body}}return null}function He(e,t){let r=oe(e),n=null;function s(i){if(!n){if(C.isVariableStatement(i)&&i.declarationList.declarations.some(o=>C.isIdentifier(o.name)&&o.name.text===t)){let o=i.declarationList.declarations.find(c=>C.isIdentifier(c.name)&&c.name.text===t),a=_n(Fn(o.initializer),"register");if(a){n=a;return}}C.forEachChild(i,s)}}return s(r),n??ja(e,"registerServer")}function Nn(e){let t=!1;function r(n){if(!t&&!C.isArrowFunction(n)){if(C.isCallExpression(n)){let s=n.expression;if(C.isIdentifier(s)&&s.text==="resolveService"){t=!0;return}let i=s.getText();if(i==="ctx.resolveService"||i.endsWith(".services.resolve")){t=!0;return}}C.forEachChild(n,r)}}return r(e),t}function pr(e){let t=!1;function r(n){if(!t){if(C.isCallExpression(n)){let s=n.expression.getText();if(s.endsWith(".cards.registerMap")||s.endsWith(".cards.register")){t=!0;return}}C.forEachChild(n,r)}}return r(e),t}function Vn(e){let t=oe(e),r=[];function n(s){if(C.isCallExpression(s)&&s.expression.getText().endsWith(".cards.register")){let o=s.arguments[0];o&&r.push(o.getText().replace(/['"]/g,""))}C.forEachChild(s,n)}return n(t),r}function ur(e){let t=oe(e),r={};function n(s){if(C.isImportDeclaration(s)&&C.isStringLiteral(s.moduleSpecifier)){let i=s.moduleSpecifier.text;if(i.startsWith("./")||i.startsWith("../")){let o=s.importClause;o?.name&&(r[o.name.text]=i)}}C.forEachChild(s,n)}return n(t),r}async function Un(e){let t=[],r=zn.join(e.appDir,"packages");if(!Jn(r))return t;for(let n of await Ea(r,{withFileTypes:!0})){if(!n.isDirectory())continue;let s=zn.join(r,n.name,"src/server/index.ts");if(!Jn(s))continue;let i=await L(s),o=He(i,"serverModule");o&&Nn(o)&&t.push({rule:"register-pure",level:"error",message:`${n.name}: 注册入口(serverModule.register)内出现 resolveService(只允许在 handle/事件回调内)`})}return t}import{existsSync as Ge}from"fs";import ye from"path";import E from"typescript";function ge(e){return E.isAsExpression(e)||E.isSatisfiesExpression(e)?e.expression:e}function Mt(e,t){let r=oe(e),n=null;function s(i){let o={};for(let a of i.properties){if(!E.isPropertyAssignment(a))continue;let c=a.name,l=E.isIdentifier(c)||E.isStringLiteral(c)?c.text:"";l&&(o[l]=a.initializer)}return o}for(let i of r.statements)if(E.isVariableStatement(i)){for(let o of i.declarationList.declarations)if(!(!E.isIdentifier(o.name)||!o.initializer)){if(o.name.text==="cards"){let a=ge(o.initializer);if(E.isObjectLiteralExpression(a))return n=s(a),n}if(t&&o.name.text===t){let a=ge(o.initializer);if(E.isObjectLiteralExpression(a)){for(let c of a.properties)if(E.isPropertyAssignment(c)&&E.isIdentifier(c.name)&&c.name.text==="cards"){let l=ge(c.initializer);if(E.isObjectLiteralExpression(l))return n=s(l),n}}}}}return n}function Ra(e){let t=Mt(e,"clientModule");return t?Object.keys(t):[]}function Ke(e){let t=e.match(/cardType:\s*['"]([^'"]+)['"]/),r=e.match(/schemaVersion:\s*(\d+)/);return{cardType:t?.[1],schemaVersion:r?Number(r[1]):void 0}}function Wn(e,t){let r=[t,`${t}.ts`,`${t}.tsx`,`${t}/index.ts`,`${t}/index.tsx`];for(let n of r)if(Ge(ye.join(e,n)))return ye.join(e,n);return null}function Hn(e,t,r){let n=ge(e);if(E.isObjectLiteralExpression(n)){let s=Ke(n.getText());return{cardType:s.cardType,schemaVersion:s.schemaVersion}}if(E.isStringLiteral(n))return{cardType:n.text};if(E.isIdentifier(n)){let s=t[n.text];if(!s)return null;let i=Wn(r,s.replace(/^\.\//,""));return i?{resolved:i}:null}return null}async function Da(e){let t=ye.join(e,"src/server/index.ts");if(!Ge(t))return{cardTypes:[],schemaVersions:{},keyMismatches:[],registerMissing:!1};let r=await L(t),n=ur(r),s=ye.join(e,"src/server"),i=[],o={},a=[],c=Mt(r,"serverModule");if(c){let l=!1;if(Object.keys(c).length>0){let p=He(r,"serverModule");l=!p||!pr(p)}for(let[p,u]of Object.entries(c)){let d=Hn(u,n,s);if(d)if(d.resolved){let f=await L(d.resolved),g=Ke(f);g.cardType&&(i.push(g.cardType),g.schemaVersion&&(o[g.cardType]=g.schemaVersion),p!==g.cardType&&a.push({key:p,cardType:g.cardType}))}else d.cardType&&(i.push(d.cardType),d.schemaVersion&&(o[d.cardType]=d.schemaVersion),p!==d.cardType&&a.push({key:p,cardType:d.cardType}))}return{cardTypes:[...new Set(i)],schemaVersions:o,keyMismatches:a,registerMissing:l}}for(let l of Vn(r)){if(l.includes("cardType:")){let g=Ke(l);g.cardType&&(i.push(g.cardType),g.schemaVersion&&(o[g.cardType]=g.schemaVersion));continue}if(/^[a-zA-Z0-9][\w-]*$/.test(l)&&!n[l]){i.push(l);continue}let p=n[l];if(!p)continue;let u=Wn(s,p.replace(/^\.\//,""));if(!u)continue;let d=await L(u),f=Ke(d);f.cardType&&(i.push(f.cardType),f.schemaVersion&&(o[f.cardType]=f.schemaVersion))}return{cardTypes:[...new Set(i)],schemaVersions:o,keyMismatches:a,registerMissing:!1}}function Ca(e,t){return oe(e).statements.some(n=>E.isVariableStatement(n)&&n.declarationList.declarations.some(s=>E.isIdentifier(s.name)&&s.name.text===t))}async function Ta(e){let t=ye.join(e,"src/client/index.ts");if(!Ge(t))return!1;let r=await L(t);if(!Ca(r,"clientModule"))return!1;let n=Mt(r,"clientModule");if(!n||Object.keys(n).length===0)return!1;let s=He(r,"clientModule");return!s||!pr(s)}async function qe(e){let t=await z(e.appDir),r=[];for(let n of t){let s={};for(let c of n.descriptor.contributes.cards??[])s[c.cardType]=c.schemaVersion??1;let i=ye.join(n.dir,"src/client/index.ts"),o=Ge(i)?Ra(await L(i)):[],a=await Da(n.dir);r.push({id:n.id,declared:s,clientMap:o,serverRegistered:a.cardTypes,serverSchemaVersions:a.schemaVersions,serverKeyMismatches:a.keyMismatches,serverRegisterMissing:a.registerMissing,clientRegisterMissing:await Ta(n.dir)})}return r}function Tt(e){return E.isStringLiteral(e)||E.isNumericLiteral(e)||e.kind===E.SyntaxKind.NullKeyword||e.kind===E.SyntaxKind.TrueKeyword||e.kind===E.SyntaxKind.FalseKeyword?!0:E.isPrefixUnaryExpression(e)&&e.operator===E.SyntaxKind.MinusToken?Tt(e.operand):E.isArrayLiteralExpression(e)?e.elements.every(t=>E.isOmittedExpression(t)||Tt(t)):E.isObjectLiteralExpression(e)?e.properties.every(t=>E.isPropertyAssignment(t)&&Tt(t.initializer)):!1}function Bn(e){for(let t of e.properties)if(E.isPropertyAssignment(t)&&E.isIdentifier(t.name)&&t.name.text==="sampleData"){let r=ge(t.initializer);return E.isObjectLiteralExpression(r)?r.properties.length===0?"empty":Tt(r)?"ok":"non-literal":"non-literal"}return"missing"}function Ma(e){let t=oe(e),r={};for(let n of t.statements){if(E.isVariableStatement(n)){for(let s of n.declarationList.declarations)if(E.isIdentifier(s.name)&&s.initializer){let i=ge(s.initializer);E.isObjectLiteralExpression(i)&&(r[s.name.text]=i)}}if(E.isExportAssignment(n)&&!n.isExportEquals){let s=ge(n.expression);if(E.isObjectLiteralExpression(s))return s;if(E.isIdentifier(s)&&r[s.text])return r[s.text]}}return null}async function Kn(e){let t=ye.join(e,"src/server/index.ts");if(!Ge(t))return[];let r=await L(t),n=ur(r),s=ye.join(e,"src/server"),i=Mt(r,"serverModule");if(!i)return[];let o=[];for(let[a,c]of Object.entries(i)){let l=Hn(c,n,s);if(l){if(l.resolved){let p=await L(l.resolved),u=Ke(p).cardType??a,d=Ma(p);o.push({cardType:u,status:d?Bn(d):"missing",source:l.resolved})}else if(l.cardType){let p=ge(c),u=E.isObjectLiteralExpression(p)?Bn(p):"missing";o.push({cardType:l.cardType,status:u,source:"inline"})}}}return o}async function Gn(e){let t=[];for(let r of await qe(e)){let n=Object.keys(r.declared);if(n.length===0&&r.serverKeyMismatches.length===0&&!r.serverRegisterMissing&&!r.clientRegisterMissing)continue;for(let c of r.serverKeyMismatches)t.push({rule:"card-type-consistent",level:"error",message:`${r.id}: serverModule.cards key "${c.key}" !== meta.cardType "${c.cardType}"(key 约定 = cardType)`});r.serverRegisterMissing&&t.push({rule:"card-type-consistent",level:"error",message:`${r.id}: serverModule 声明了 cards 但 register 内未调用 ctx.cards.registerMap(cards)(注册动作缺失,运行时缺卡)`}),r.clientRegisterMissing&&t.push({rule:"card-type-consistent",level:"error",message:`${r.id}: clientModule 声明了 cards 但 register 内未调用 ctx.cards.registerMap(cards)(注册动作缺失,运行时缺卡)`});let s=n.filter(c=>!r.clientMap.includes(c));s.length>0&&t.push({rule:"card-type-consistent",level:"error",message:`${r.id}: 声明卡片 ${s.join(",")} 未在客户端 cards map 导出`});let i=n.filter(c=>!r.serverRegistered.includes(c));i.length>0&&t.push({rule:"card-type-consistent",level:"error",message:`${r.id}: 声明卡片 ${i.join(",")} 未在服务端注册(serverModule.cards meta / cards.register)`});let o=r.clientMap.filter(c=>!n.includes(c));o.length>0&&t.push({rule:"card-type-consistent",level:"warning",message:`${r.id}: 客户端导出未声明的卡片 ${o.join(",")}`});let a=r.serverRegistered.filter(c=>!n.includes(c));a.length>0&&t.push({rule:"card-type-consistent",level:"warning",message:`${r.id}: 服务端注册未声明的卡片 ${a.join(",")}`})}return t}async function qn(e){let t=[],r=await qe(e),n={};for(let i of r)for(let o of i.serverRegistered)o in n?n[o]+=`,${i.id}`:n[o]=i.id;if(Object.keys(n).length===0)return t;let s=new Set;for(let i of r)for(let o of i.clientMap)s.add(o);for(let[i,o]of Object.entries(n))s.has(i)||t.push({rule:"client-card-cover",level:"error",message:`服务端注册卡片 ${i}(模块 ${o})未出现在应用客户端装配(漏装配)`});return t}import{existsSync as dr}from"fs";import{readdir as fr,stat as Ia}from"fs/promises";import Me from"path";async function Xn(e){let t=[],r=Me.join(e.appDir,"packages");if(!dr(r))return t;let n=new Map;for(let i of await fr(r,{withFileTypes:!0})){if(!i.isDirectory())continue;let o=Z(Me.join(r,i.name));o?.name&&o.name.startsWith("@tbox.cn/app-contracts")&&n.set(o.name,o.version??"0.0.0")}let s=Me.join(e.appDir,"node_modules","@tbox.cn");if(dr(s))for(let i of await fr(s,{withFileTypes:!0})){let o=Me.join(s,i.name),a=i.isDirectory();if(!a&&i.isSymbolicLink())try{a=(await Ia(o)).isDirectory()}catch{a=!1}if(!a)continue;let c=Z(o);c?.name&&c.name.startsWith("@tbox.cn/app-contracts")&&n.set(c.name,c.version??"0.0.0")}for(let i of await fr(r,{withFileTypes:!0})){if(!i.isDirectory())continue;let o=Me.join(r,i.name);if(!dr(Me.join(o,"tbox.module.json")))continue;let a=Z(o),c={...a?.dependencies??{},...a?.peerDependencies??{}};for(let[l,p]of Object.entries(c)){if(!l.startsWith("@tbox.cn/app-contracts"))continue;let u=n.get(l);if(!u||p==="*"||p.startsWith("workspace:")||p.startsWith("catalog:")||p.replace(/^[\^~]/,"")===u)continue;Ct(p,u)||t.push({rule:"contract-version",level:"error",message:`${i.name}: 契约 ${l} 范围 ${p} 与实装 ${u} 无交集`})}}return t}import{existsSync as Aa}from"fs";import{readdir as Oa}from"fs/promises";import Pa from"path";async function Yn(e){let t=[],r=new Set,n=Pa.join(e.appDir,"packages");if(Aa(n))for(let f of await Oa(n,{withFileTypes:!0}))f.isDirectory()&&r.add(f.name);for(let f of e.declared)r.add(f.id);let s=new Set;for(let f of se)for(let g of e.actual[f.kind]?.moduleIds??[])s.add(g);let i=new Map,o=await z(e.appDir);for(let f of o){let g=(f.descriptor.dependencies?.modules??[]).map(m=>m.id);i.set(f.id,g)}let a=0,c=1,l=2,p=new Map,u=[];function d(f,g){p.set(f,c),g.push(f);for(let m of i.get(f)??[]){let h=p.get(m)??a;if(h===c){let v=g.indexOf(m);v>=0&&u.push([...g.slice(v),m])}else h===a&&d(m,g)}g.pop(),p.set(f,l)}for(let f of i.keys())(p.get(f)??a)===a&&d(f,[]);for(let f of u)t.push({rule:"module-deps-assembled",level:"error",message:`dependencies.modules 声明层存在循环依赖:${f.join(" → ")}`});for(let f of o)for(let g of f.descriptor.dependencies?.modules??[]){if(g.required&&!r.has(g.id)){t.push({rule:"module-deps-assembled",level:"error",message:`${f.id}: 依赖模块 ${g.id} 未安装(缺失 packages/${g.id} 或 npm 清单)`});continue}o.some(h=>h.id===g.id)&&g.required&&!s.has(g.id)&&t.push({rule:"module-deps-assembled",level:"error",message:`${f.id}: 依赖业务模块 ${g.id} 已安装但未装配(modules.ts 缺行,运行 sync)`})}return t}import{existsSync as mr}from"fs";import{readdir as La}from"fs/promises";import{createRequire as Fa}from"module";import{realpathSync as _a}from"fs";import Ie from"path";async function Zn(e){let t=[],r=["react","zod","@mastra/core"],n=["apps/client","apps/server","packages/app-sdk","packages/contracts"],s=Ie.join(e.appDir,"packages");if(mr(s))for(let i of await La(s,{withFileTypes:!0}))i.isDirectory()&&mr(Ie.join(s,i.name,"package.json"))&&n.push(Ie.join("packages",i.name));for(let i of r){let o=new Map;for(let a of n){let c=Ie.join(e.appDir,a);if(!mr(Ie.join(c,"package.json")))continue;let l=Na(c,i);if(l){let p=o.get(l)??[];p.push(a),o.set(l,p)}}o.size>1&&t.push({rule:"singleton",level:"error",message:`${i} 解析结果不唯一:${[...o.entries()].map(([a,c])=>`${a}(${c.join(",")})`).join(" vs ")}`})}return t}function Na(e,t){try{let r=Fa(Ie.join(e,"__noop__.js"));return _a(r.resolve(t))}catch{return null}}import{existsSync as Qn}from"fs";import gr from"path";var Va=new Set(["@tbox.cn/app-sdk","@tbox.cn/app-sdk/server","@tbox.cn/app-sdk/client","@tbox.cn/app-sdk/platform","@tbox.cn/app-sdk/platform/code-inspect"]),Ja=[{re:/^@mastra\/core/,label:"@mastra/core*(框架内部,改经 @tbox.cn/app-sdk)"},{re:/^@ag-ui\//,label:"@ag-ui/*(框架内部,改经 @tbox.cn/app-sdk)"},{re:/^@ai-sdk\//,label:"@ai-sdk/*(框架内部)"},{re:/^ai$/,label:"ai(框架内部)"},{re:/^zustand$/,label:"zustand(框架内部)"}];async function es(e){let t=[],r=["apps","packages"];for(let n of r){let s=gr.join(e.appDir,n);if(!Qn(s))continue;let i=[];await $e(s,e.appDir,i);for(let o of i){if(o.startsWith("packages/app-sdk/")||o.startsWith("packages/contracts/"))continue;let a=await L(gr.join(e.appDir,o));for(let c of a.matchAll(/from\s+['"]([^'"]+)['"]/g)){let l=c[1];if(l.startsWith("@tbox.cn/app-sdk/")&&!Va.has(l))t.push({rule:"sdk-internal-import",level:"error",message:`${o}: 不允许 import SDK 内部路径 ${l}`});else if(l.startsWith("@tbox.cn/app-contracts/"))t.push({rule:"sdk-internal-import",level:"error",message:`${o}: 不允许 import 契约子路径 ${l}(仅 @tbox.cn/app-contracts)`});else if(za(e.appDir,o))for(let p of Ja)p.re.test(l)&&t.push({rule:"sdk-internal-import",level:"error",message:`${o}: 模块不允许直接 import ${p.label}`})}}}return t}function za(e,t){let r=t.match(/^packages\/([^/]+)\//);return r?Qn(gr.join(e,"packages",r[1],"tbox.module.json")):!1}function ts(e){let t=[];for(let r of se){let n=new Set(e.declared.filter(c=>jt(r.kind,c)).map(c=>c.id)),s=new Set(e.actual[r.kind]?.moduleIds??[]),i=[...n].filter(c=>!s.has(c)),o=[...s].filter(c=>!n.has(c));i.length>0&&t.push({rule:"assembly-drift",level:"warning",message:`${r.path}: 已声明未装配 → ${i.join(", ")}`}),o.length>0&&t.push({rule:"assembly-drift",level:"warning",message:`${r.path}: 已装配未声明 → ${o.join(", ")}`});let a=e.actual[r.kind]?.broken??[];a.length>0&&t.push({rule:"assembly-drift",level:"warning",message:`${r.path}: 锚区破坏 → ${a.join(", ")}`})}return t}async function rs(e){let t=[];for(let r of await qe(e))for(let[n,s]of Object.entries(r.declared)){let i=r.serverSchemaVersions[n]??1;i!==s&&t.push({rule:"schema-version",level:"error",message:`${r.id}: 卡片 ${n} contributes.schemaVersion=${s} 与 meta schemaVersion=${i} 不一致`})}return t}import{existsSync as Ua}from"fs";import ns from"path";var Ba=["/webhook","/upload","/demo","/run"];async function ss(e){let t=[];for(let r of await z(e.appDir)){let n=ns.join(r.dir,"src/server");if(!Ua(n))continue;let s=[];await $e(n,r.dir,s);for(let i of s){let o=await L(ns.join(r.dir,i));for(let a of o.matchAll(/\.(?:post|put|patch|delete)\(\s*['"]([^'"]+)['"]/g)){let c=a[1];if(!c.startsWith("/"))continue;Ba.some(p=>c.startsWith(p))||t.push({rule:"naked-write-route",level:"warning",message:`${r.id}/${i}: 裸写路由 ${a[0].replace("("," (")} 建议改走 ctx.actions.registerAction(全局动作分发器)`})}}}return t}import{existsSync as os}from"fs";import{readdir as Wa}from"fs/promises";import is from"path";async function as(e){let t=[],r=is.join(e.appDir,"packages");if(!os(r))return t;for(let n of await Wa(r,{withFileTypes:!0})){if(!n.isDirectory())continue;let s=is.join(r,n.name,"tbox.module.json");if(os(s))try{let i=Ee(JSON.parse(await L(s)));i.ok||t.push({rule:"descriptor-schema",level:"error",message:`${n.name}/tbox.module.json: ${i.errors.join("; ")}`})}catch{t.push({rule:"descriptor-schema",level:"error",message:`${n.name}/tbox.module.json: JSON 解析失败`})}}return t}import{existsSync as cs}from"fs";import{readdir as Ha}from"fs/promises";import Xe from"path";async function ls(e){let t=[];if(cs(Xe.join(e.appDir,"pnpm-workspace.template.yaml")))return t;let r=new Map;for(let n of["apps","packages"]){let s=Xe.join(e.appDir,n);if(cs(s))for(let i of await Ha(s,{withFileTypes:!0})){if(!i.isDirectory())continue;let o=Xe.join(s,i.name),a=Z(o);a?.name&&r.set(a.name,Xe.join(n,i.name))}}if(r.size===0)return t;for(let[n,s]of r){let i=Z(Xe.join(e.appDir,s));if(i)for(let o of["dependencies","peerDependencies","devDependencies"]){let a=i[o];if(!(!a||typeof a!="object"))for(let[c,l]of Object.entries(a))typeof l!="string"||!l.startsWith("workspace:")||r.has(c)||t.push({rule:"workspace-ref-resolved",level:"error",message:`${s}: workspace:* 引用 ${c} 未命中任何成员(packages/ 或 apps/)`})}}return t}import{existsSync as Ka}from"fs";import Ga from"path";var qa=["apps/server/src/auth","apps/server/src/agent","apps/server/src/gateway","apps/server/src/http","apps/server/src/plugins/integration.ts","apps/server/src/config/tts-config.ts","apps/server/src/config/model-providers.ts","apps/client/src/env","apps/client/src/bridge","apps/client/src/adapters","apps/client/src/services/http.ts","apps/client/src/services/auth-client.ts","apps/client/src/services/user-id.ts","apps/client/src/services/tbox-session.ts"];function ps(e){let t=[];for(let r of qa)Ka(Ga.join(e.appDir,r))&&t.push({rule:"legacy-platform-files",level:"error",message:`${r} 为旧形态平台文件(007:平台能力已下沉 @tbox.cn/app-sdk)。请删除并改用 SDK API(server: createAuthRuntime/createPlatformApiRouter/createTtsProxy/createModelProvider/createPluginIntegration;client: createAuthClient/createPlatformAdapters/createPlatformApi/configureRuntime),详见 .agents/notes/archived/architecture/2026-08-12-platform-capabilities-sink.md。`});return t}import{existsSync as us,readFileSync as Xa}from"fs";import{readdir as Ya}from"fs/promises";import{createRequire as Za}from"module";import Ye from"path";function ds(e,t){try{let n=Za(Ye.join(e.appDir,"package.json")).resolve(`${t}/package.json`);return Ye.dirname(n)}catch{return}}function Qa(e){let t=[Ye.join(e,"src/server/index.ts"),Ye.join(e,"src/server/index.tsx")];for(let r of t)if(us(r))return Xa(r,"utf8");return""}function ec(e){let t=[];for(let r of e.matchAll(/patterns\s*:\s*\[([^\]]*)\]/g))for(let n of r[1].matchAll(/['"]([^'"]+)['"]/g))t.push(n[1]);return t}async function fs(e){let t=[],r=new Map;for(let n of e.declared){if(!n.hasServerEntry)continue;let s=ds(e,n.pkg);if(!s)continue;let i=ec(Qa(s));for(let o of i){let a=r.get(o)??[];a.push(n.id),r.set(o,a)}}for(let[n,s]of r)s.length>1&&t.push({rule:"intent-overlap",level:"warning",message:`意图词 "${n}" 在多个模块声明(${s.join(", ")})——先注册先命中`});return t}async function ms(e){let t=[],r=new Map;for(let n of e.declared){if(!n.hasServerEntry)continue;let s=ds(e,n.pkg);if(!s)continue;let i=Ye.join(s,"skills");if(us(i))try{let o=(await Ya(i,{withFileTypes:!0})).filter(a=>a.isDirectory()).map(a=>a.name);for(let a of o){let c=r.get(a)??[];c.push(n.id),r.set(a,c)}}catch{}}for(let[n,s]of r)s.length>1&&t.push({rule:"skill-name-conflict",level:"warning",message:`skill "${n}" 在多个模块声明(${s.join(", ")})——后注册覆盖`});return t}async function gs(e){let t=[];for(let r of await z(e.appDir))for(let n of await Kn(r.dir)){if(n.status==="ok")continue;let s=n.status==="missing"?"缺失(dev 卡片预览页 / 模块单测不可用)":n.status==="empty"?"为空对象(至少一组可展示数据)":"非字面量(引用常量/函数调用,AST 无法离线求值——静态检查无法求值,运行时预览不受影响)";t.push({rule:"sample-data-valid",level:"warning",message:`${r.id}/${n.cardType}: sampleData ${s}`})}return t}import{existsSync as ys}from"fs";import{readdir as hs}from"fs/promises";import It from"path";async function vs(e){let t=[],r=It.join(e.appDir,"packages");if(!ys(r))return t;for(let n of await hs(r,{withFileTypes:!0})){if(!n.isDirectory()||n.name.startsWith("contracts-"))continue;let s=It.join(r,n.name,"src");if(!ys(s))continue;let i=[];await ws(s,s,i),i.length>0&&t.push({rule:"module-console-logger",level:"warning",message:`${n.name}: 源码含裸 console 调用 ${i.length} 处(${i.slice(0,3).join("、")}${i.length>3?"…":""})——建议改用 ctx.logger(见 docs/reference/modules.md 模块日志规范)`})}return t}async function ws(e,t,r){for(let n of await hs(e,{withFileTypes:!0})){let s=It.join(e,n.name);if(n.isDirectory()){if(n.name==="__tests__"||n.name==="node_modules")continue;await ws(s,t,r);continue}if(!/\.tsx?$/.test(n.name)||/\.test\.tsx?$/.test(n.name))continue;let i=await L(s),o=It.relative(t,s);i.split(`
90
+ `).forEach((c,l)=>{/console\.(log|warn|error|info|debug)\s*\(/.test(c)&&r.push(`${o}:${l+1}`)})}}import{existsSync as bs}from"fs";import{readdir as ks}from"fs/promises";import At from"path";async function xs(e){let t=[],r=At.join(e.appDir,"packages");if(!bs(r))return t;for(let n of await ks(r,{withFileTypes:!0})){if(!n.isDirectory()||n.name.startsWith("contracts-"))continue;let s=At.join(r,n.name,"src");if(!bs(s))continue;let i=[];await Ss(s,s,i),i.length>0&&t.push({rule:"module-mall-scope",level:"warning",message:`${n.name}: 源码含手解 attributes.mall ${i.length} 处(${i.slice(0,3).join("、")}${i.length>3?"…":""})——改用 parseMallScope/extractMallScope/withMallScopeFromQuery(见 docs/reference/modules.md 读取入口族)`})}return t}var tc=/\.attributes\??\.?\bmall\b|\.attributes\??\.?\[\s*['"]mall['"]\s*\]/,rc=/as\s*\{[^}]*\bmall\b/,nc=/^\s*(\*|\/\/|\/\*)/;async function Ss(e,t,r){for(let n of await ks(e,{withFileTypes:!0})){let s=At.join(e,n.name);if(n.isDirectory()){if(n.name==="__tests__"||n.name==="node_modules")continue;await Ss(s,t,r);continue}if(!/\.tsx?$/.test(n.name)||/\.test\.tsx?$/.test(n.name))continue;let i=await L(s),o=At.relative(t,s);i.split(`
91
+ `).forEach((c,l)=>{nc.test(c)||(tc.test(c)||rc.test(c))&&r.push(`${o}:${l+1}`)})}}import{existsSync as $s,readFileSync as js}from"fs";import Es from"path";function sc(e,t=process.env,r="<config>"){let n=_r(e,t);if(n.missing.length>0)throw new Error(`配置文件 ${r} 引用的环境变量缺失:${n.missing.join("、")}(先 source .real-env/env.sh <vendor>[-<variant>] 后重试)`);return n.text??e}async function Rs(e){let t=Es.join(e.appDir,"config","deployments","development.json");if($s(t))try{let m=JSON.parse(js(t,"utf8"));if(m&&typeof m=="object"&&"malls"in m)return[{rule:"integration-services",level:"error",message:"config/deployments/development.json 已退役(部署控制面并入 config/integrations.json 的 instances 注册表 + defaultInstanceId)——迁移后删除该文件(malls → instances[].id/attributes,defaultMallId → defaultInstanceId)"}]}catch{}let r=Es.join(e.appDir,"config","integrations.json");if(!$s(r))return[];let n=await rt(e.appDir);if(!n.strictValidation){let m=n.version===null;return[{rule:"integration-services",level:m?"warning":"error",message:m?"integrations: contracts 未安装——pnpm install 后重试(安装后启用严格校验与求值诊断)":`integrations: contracts 严格校验面不可用(${n.version},需 ≥0.9)——${n.notes[0]??"升级应用 @tbox.cn/app-contracts 依赖后可用"}`}]}let{resolveEffectiveService:s,buildSupplyLookup:i,moduleDomainOf:o,normalizeInstances:a,RESOURCE_TYPE_IDS:c}=n.module,l;try{l=JSON.parse(sc(js(r,"utf8"),process.env,r))}catch(m){return[{rule:"integration-services",level:"error",message:`config/integrations.json 非法 JSON:${m.message}`}]}let p=l?.services;if(!p||typeof p!="object"||Array.isArray(p))return[{rule:"integration-services",level:"error",message:"config/integrations.json 缺 services(Record<service, {provider, instances}>)"}];let u=Gr(e.appDir),d=i(qr(e.appDir)),f=Vr(e.appDir,u,l,process.env);return Nr({contracts:{resolveEffectiveService:s,buildSupplyLookup:i,moduleDomainOf:o,normalizeInstances:a,RESOURCE_TYPE_IDS:c},integrations:l,supplies:d,...f}).map(m=>({rule:"integration-services",level:m.severity,message:m.message,...m.code!==void 0?{code:m.code}:{},...m.service!==void 0?{service:m.service}:{},...m.module!==void 0?{module:m.module}:{},...m.instance!==void 0?{instance:m.instance}:{}}))}async function Ds(e){return(await kn(e.appDir)).map(r=>({rule:"codegen-ref-resolved",level:"error",message:r}))}import{existsSync as Cs}from"fs";import{readdir as Ts}from"fs/promises";import Ot from"path";async function Ms(e){let t=[],r=Ot.join(e.appDir,"packages");if(!Cs(r))return t;for(let n of await Ts(r,{withFileTypes:!0})){if(!n.isDirectory()||n.name.startsWith("contracts-"))continue;let s=Ot.join(r,n.name,"src");if(!Cs(s))continue;let i=[];await Is(s,s,i),i.length>0&&t.push({rule:"module-auth-context",level:"error",message:`${n.name}: 源码读 ctx.auth 全局单例 ${i.length} 处(${i.slice(0,3).join("、")}${i.length>3?"…":""})——ctx.auth 已于 app-sdk 0.11.0 拆除,改用显式通道(handle 第四参 reqCtx / getToolRequestContext,见 docs/reference/modules.md)`})}return t}async function Is(e,t,r){for(let n of await Ts(e,{withFileTypes:!0})){let s=Ot.join(e,n.name);if(n.isDirectory()){if(n.name==="__tests__"||n.name==="node_modules")continue;await Is(s,t,r);continue}if(!/\.tsx?$/.test(n.name)||/\.test\.tsx?$/.test(n.name))continue;let i=await L(s),o=Ot.relative(t,s);i.split(`
92
+ `).forEach((c,l)=>{/ctx\.auth\.(getContext|setContext|requireIdentity|isAnonymous)\s*\(/.test(c)&&r.push(`${o}:${l+1}`)})}}import yr from"path";import he from"typescript";var As="presentation",Os="labelsEmbedded",oc=new Set([".ts",".tsx"]);function ic(e){let t;try{t=oe(e)}catch{return[]}let r=[],n=s=>{if(he.isPropertyAssignment(s)&&(he.isIdentifier(s.name)||he.isStringLiteral(s.name))&&s.name.text===As&&he.isObjectLiteralExpression(s.initializer)){let i=s.initializer.properties.some(c=>c.name!==void 0&&he.isIdentifier(c.name)&&c.name.text==="variant"),o=s.initializer.properties.some(c=>c.name!==void 0&&he.isIdentifier(c.name)&&c.name.text===Os),a=s.initializer.properties.some(he.isSpreadAssignment);i&&!o&&!a&&r.push(t.getLineAndCharacterOfPosition(s.getStart(t)).line+1)}he.forEachChild(s,n)};return n(t),r}async function Ps(e){let t=[];for(let r of await z(e.appDir)){let n=yr.join(r.dir,"src"),s=[];await $e(n,n,s);for(let i of s){if(!oc.has(yr.extname(i)))continue;let o=await L(yr.join(n,i));if(o.includes(As))for(let a of ic(o))t.push({rule:"card-face-labels",level:"error",message:`${r.id}: src/${i}:${String(a)} 的 presentation 缺 ${Os}——卡面图自带卡名与「我的积分」字样,缺省时前端会再叠一层导致文字重叠;卡图确实无字请显式写 false`})}}return t}import{existsSync as Ls}from"fs";import{readdir as Fs}from"fs/promises";import hr from"path";async function _s(e){let t=[],r=hr.join(e.appDir,"packages");if(!Ls(r))return t;for(let n of await Fs(r,{withFileTypes:!0})){if(!n.isDirectory()||n.name.startsWith("contracts-"))continue;let s=hr.join(r,n.name,"src");if(!Ls(s))continue;let i=await Ns(s);if(i.length===0)continue;let o=i.map(u=>u.text).join(`
93
+ `),a=new Set;for(let u of o.matchAll(/internalTool\s*\(\s*(\w+)\s*\)/g))a.add(u[1]);let c=[...o.matchAll(/const\s+(\w+)\s*=\s*createTool\s*\(/g)],l=[],p=[];for(let u=0;u<c.length;u++){let d=c[u],f=d[1],g=d.index??0,m=u+1<c.length?c[u+1].index??g+4e3:g+4e3,v=o.slice(g,Math.min(m,g+8e3)).includes("模型勿调用"),S=a.has(f);v&&!S?l.push(f):S&&!v&&p.push(f)}l.length>0&&t.push({rule:"module-internal-tool",level:"warning",message:`${n.name}: 工具 description 含「模型勿调用」但未 internalTool 标记(${l.join("、")})——模型面照常可见,撑大静态前缀且有幻觉调用面(见 docs/reference/modules.md 内部工具规约)`}),p.length>0&&t.push({rule:"module-internal-tool",level:"warning",message:`${n.name}: internalTool 标记的工具 description 缺「模型勿调用」标注(${p.join("、")})——标注是 doctor 静态面唯一可查锚点,补齐描述`})}return t}async function Ns(e,t=""){let r=[];for(let n of await Fs(e,{withFileTypes:!0})){let s=hr.join(e,n.name),i=t?`${t}/${n.name}`:n.name;if(n.isDirectory()){if(n.name==="__tests__"||n.name==="node_modules")continue;r.push(...await Ns(s,i));continue}/\.tsx?$/.test(n.name)&&(/\.test\.tsx?$/.test(n.name)||r.push({rel:i,text:await L(s)}))}return r}var ac=[{name:"workspace-dag",run:Ln},{name:"register-pure",run:Un},{name:"card-type-consistent",run:Gn},{name:"client-card-cover",run:qn},{name:"contract-version",run:Xn},{name:"module-deps-assembled",run:Yn},{name:"singleton",run:Zn},{name:"sdk-internal-import",run:es},{name:"assembly-drift",run:ts},{name:"schema-version",run:rs},{name:"naked-write-route",run:ss},{name:"descriptor-schema",run:as},{name:"workspace-ref-resolved",run:ls},{name:"legacy-platform-files",run:ps},{name:"intent-overlap",run:fs},{name:"skill-name-conflict",run:ms},{name:"sample-data-valid",run:gs},{name:"module-console-logger",run:vs},{name:"module-mall-scope",run:xs},{name:"integration-services",run:Rs},{name:"codegen-ref-resolved",run:Ds},{name:"module-auth-context",run:Ms},{name:"card-face-labels",run:Ps},{name:"module-internal-tool",run:_s}];async function q(e,t){let r=[],n=t?.only?.length?new Set(t.only):null,s=new Set(t?.skip??[]);for(let i of ac)if(!(n&&!n.has(i.name))&&!s.has(i.name))try{r.push(...await i.run(e))}catch(o){r.push({rule:i.name,level:"error",message:`规则执行异常: ${o?.message??String(o)}`})}return r}function Vs(e,t){return!t.has(e)||e.startsWith("contracts-")}async function Js(e,t,r,n=[]){let s=await z(e),i=new Set(s.map(b=>b.id)),o=new Set(r?.map(b=>b.id)??[]),a=new Map;for(let b of s)a.set(b.id,b.descriptor.version??"0.0.0");let c=new Map(n.map(b=>[b.id,b.deps])),l=new Set,p=[],u=[...t,...n.map(b=>b.id)];for(;u.length>0;){let b=u.shift();if(l.has(b))continue;l.add(b);let k=s.find(j=>j.id===b),O=c.get(b)??k?.descriptor.dependencies?.modules??[];for(let j of O)p.push(j),!l.has(j.id)&&(i.has(j.id)||c.has(j.id))&&u.push(j.id)}let d=0,f=1,g=2,m=new Map,h=[];function v(b,k){m.set(b,f),k.push(b);for(let O of S.get(b)??[]){let j=m.get(O)??d;if(j===f){let ee=k.indexOf(O);ee>=0&&h.push([...k.slice(ee),O])}else j===d&&v(O,k)}k.pop(),m.set(b,g)}let S=new Map,$=new Map(s.map(b=>[b.id,b]));for(let b of l){let k=$.get(b),O=c.get(b)??k?.descriptor.dependencies?.modules??[];S.set(b,O.filter(j=>l.has(j.id)).map(j=>j.id))}for(let b of l)(m.get(b)??d)===d&&v(b,[]);let R=[...l].filter(b=>!o.has(b)),F=new Map;for(let b of R)F.set(b,0);let A=new Map;for(let b of R)for(let k of S.get(b)??[])if(F.has(k)){F.set(b,(F.get(b)??0)+1);let O=A.get(k);O?O.push(b):A.set(k,[b])}let N=R.filter(b=>(F.get(b)??0)===0),P=[];for(;N.length>0;){let b=N.shift();P.push(b);for(let k of A.get(b)??[]){let O=(F.get(k)??0)-1;F.set(k,O),O===0&&N.push(k)}}P.length,R.length;let w=new Set,D=new Set,M=[];for(let b of p){let k=b.id;if((!o.has(k)||!a.has(k))&&(Vs(k,i)?w.add(k):Vs(k,i)||D.add(k)),b.range&&a.has(k)){let O=a.get(k);b.range!=="*"&&!b.range.startsWith("workspace:")&&(Ct(b.range,O)||M.push(`${k}: 依赖范围 ${b.range} 与目标版本 ${O} 无交集`))}}return{order:P,contracts:[...w],business:[...D],cycles:h,conflicts:M}}function lc(e){let t=Q.join(e,"tbox.module.json");if(!ve(t))return null;try{let r=Ee(JSON.parse(wr(t,"utf8")));return r.ok?r.value:null}catch{return null}}function pc(e,t){if(!e)return null;let r=Q.dirname(e),n=Q.join(r,t);if(ve(Q.join(n,"package.json")))return n;try{let s=cc(r).find(i=>i.endsWith(".tgz")&&i.includes(`-${t}-`));if(s)return Q.join(r,s)}catch{}return null}function vr(e,t){let r=Q.join(e,"packages",t);return ve(r)&&!ht(r)?!0:B(e)?.npmModules.some(s=>s.id===t&&s.mode==="sdk")??!1}async function zs(e){await Us(e,new Set,!1)}async function Us(e,t,r){let n=[];try{await uc(e,t,r,n)}finally{for(let s of n)s.dispose()}}async function uc(e,t,r,n){let s=process.cwd();if(!B(s))throw new Error("当前目录不是 tbox-app 应用(缺 .tbox/app.json)");let i,o=null,a=null,c=!!e.source&&Ce(e.source);if(e.mode==="local"){let h=e.pkg;i=h.startsWith("module-")?h:`module-${h}`,ke(i,`--mode local ${e.pkg}`)}else{if(!e.source)throw new Error(`--mode ${e.mode} 需要 --source <目录或 tgz 或 registry 包>`);if(!(c&&!ve(Q.resolve(e.source)))&&!e.source.endsWith(".tgz")&&!re.isUsable(e.source))throw new Error(`模块源无效(缺 package.json): ${e.source}`);a=fe(e.source,e.registry),(a.source instanceof U||a.source instanceof de)&&n.push(a.source);let v=e.pkg.replace(/@[^/]+$/,"");i=Sn(v),ke(i,`--mode ${e.mode} ${e.pkg}`),o=lc(a.sourceDir)}if(r&&vr(s,i)){console.log(` ⚠️ 依赖 ${i} 已安装,跳过`);return}if(!r&&vr(s,i)){let h=ve(Q.join(s,"packages",i))?`packages/${i}`:"manifest 已登记(sdk 包,无本地目录)";throw new Error(`模块 ${i} 已存在(${h})。若要重新展开请先 remove 或手动处理;装配唯一覆盖入口为 sync --force`)}if(t.has(i))return;if(t.add(i),!e.noDeps){let h=o?.dependencies?.modules??[],v=await Js(s,[],void 0,[{id:i,deps:h}]);if(v.cycles.length>0)throw new Error(`依赖环:${v.cycles.map($=>$.join(" → ")).join(";")}`);for(let $ of v.conflicts)console.warn(` ⚠️ 依赖版本冲突: ${$}`);let S=[...v.contracts,...v.order].filter($=>$!==i&&!vr(s,$));for(let $ of[...new Set(S)]){let R=/^(module|scenario|contracts|provider)-/.test($)?`@tbox.cn/app-${$}`:`@tbox.cn/${$}`,F=c?R:pc(e.source,$);if(!F){console.warn(` ⚠️ 依赖 ${$} 未安装且未找到源(--source 兄弟目录/tgz),可 --no-deps 跳过`);continue}let A=fe(F,e.registry);(A.source instanceof U||A.source instanceof de)&&n.push(A.source);let N=ve(Q.join(A.sourceDir,"tbox.module.json")),P=gn(R,N);await Us({pkg:R,mode:P,source:F,registry:e.registry},t,!0)}}let l;if(e.mode==="local"){let h=e.pkg,v=h.startsWith("module-")?h:`module-${h}`;await jn(s,h),l={id:v,package:`@app/${v}`,version:"0.1.0",mode:"local"},await We(s,`@app/${v}`,"add")}else{let h=a.sourceDir,v=a.source.resolveVersion();e.mode==="codegen"&&(vt(h),await $n(s,h,{id:i,package:e.pkg.replace(/@[^/]+$/,""),version:v,mode:"codegen",baseVersion:v},Se(s).values()),await We(s,yt(i),"add")),l={id:i,package:e.pkg.replace(/@[^/]+$/,""),version:v,mode:e.mode,...e.mode==="codegen"?{baseVersion:v}:{}}}let p=B(s);if(await te(s,Yr(p,l)),l.mode==="codegen"){let h=await bt(s,Se(s).values());h.length>0&&console.log(` codegen 引用同步: ${h.join(", ")}`)}let u=await me(s);u.changedFiles.length>0&&console.log(` 装配更新: ${u.changedFiles.join(", ")}`);for(let h of u.warnings)console.warn(` ⚠️ ${h}`);for(let h of u.depConflicts)console.warn(` ⚠️ 依赖冲突: ${h}`);let d=await G(s),g=(await q({appDir:s,declared:u.declared,actual:d},{skip:["integration-services"]})).filter(h=>h.level==="error");if(g.length>0){console.error("❌ doctor 错误:");for(let h of g)console.error(` - [${h.rule}] ${h.message}`);process.exitCode=1}let m=await Ne(s);m.generated?console.log(` ⚡ 已生成 mock 槽绑定(config/integrations.json:${m.services.join(", ")})`):m.reason==="in-place"&&console.log(" ℹ config/integrations.json 已在场,跳过 mock 绑定生成"),console.log(`✅ 已安装 ${l.package}(mode=${e.mode}${r?", 依赖":""})`),dc(s,l.id),e.mode!=="local"&&console.log(" 下一步: pnpm install && tbox-app module doctor")}function dc(e,t){try{let r=Q.join(e,"packages",t,"package.json");if(!ve(r))return;let s=JSON.parse(wr(r,"utf8")).dependencies?.["@tbox.cn/app-contracts-mall"],i=typeof s=="string"?s.replace(/[\^~]/,""):void 0;if(!i)return;let o=Q.join(e,"pnpm-workspace.yaml");if(!ve(o))return;let l=wr(o,"utf8").match(/['"]?@tbox\.cn\/app-contracts-mall['"]?\s*:\s*['"]([^'"]+)['"]/)?.[1]?.replace(/[\^~]/,"");if(!l)return;fc(i,l)>0&&console.warn(` ⚠️ 版本配套:${t} 依赖 contracts-mall ${i}+,当前应用 catalog 为 ${l}——请升级模板或应用 catalog(015 W1)`)}catch{}}function fc(e,t){let r=e.split(".").map(Number),n=t.split(".").map(Number),s=(r[0]??0)-(n[0]??0);return Math.sign(s!==0?s:(r[1]??0)-(n[1]??0))}import mc from"path";async function Bs(e,t={}){let r=process.cwd();ke(e,"remove 参数");let n=B(r);if(!n)throw new Error("当前目录不是 tbox-app 应用(缺 .tbox/app.json)");if(!t.force){let m=[];for(let h of await z(r)){if(h.id===e)continue;let v=(h.descriptor.dependencies?.modules??[]).find(S=>S.id===e);v&&v.required&&m.push(h.id)}if(m.length>0)throw new Error(`模块 ${e} 被依赖,无法移除:${m.join(", ")}(--force 忽略)`)}let s=n.npmModules.find(m=>m.id===e),i=!!s;i&&await te(r,Zr(n,e));let o=mc.join(r,"packages",e),c=ht(o)&&(s?.mode==="sdk"||!s);(c?!1:await Dn(r,e))?console.log(` 已删除 packages/${e}`):c?console.log(" 已移除 manifest 登记(保留 contracts-mall SDK shim)"):s?.mode==="sdk"&&console.log(" 已移除 manifest 登记(sdk 包,无本地目录)");let p=s?.mode==="codegen"&&Je(s.package)?await bn(r,xe(s)):!1;p&&console.log(" 已恢复 contracts-mall SDK shim(@app/contracts-mall)"),!p&&!c&&(s?.mode==="codegen"||s?.mode==="local"||!i)&&await We(r,`@app/${e}`,"remove");let u=await me(r);u.changedFiles.length>0&&console.log(` 装配更新: ${u.changedFiles.join(", ")}`);for(let m of u.warnings)console.warn(` ⚠️ ${m}`);for(let m of u.depConflicts)console.warn(` ⚠️ 依赖冲突: ${m}`);let d=await G(r),g=(await q({appDir:r,declared:u.declared,actual:d})).filter(m=>m.level==="error");if(g.length>0){console.error("❌ doctor 错误:");for(let m of g)console.error(` - [${m.rule}] ${m.message}`);process.exitCode=1}console.log(c&&!i?`✅ ${e} 未登记,保留 SDK shim`:`✅ 已移除 ${e}`)}async function Ws(e={}){let t=process.cwd(),r=await me(t,{force:e.force??!1});r.changedFiles.length===0?console.log("装配已同步,无变更"):console.log(`已更新装配文件: ${r.changedFiles.join(", ")}`);for(let o of r.warnings)console.warn(` ⚠️ ${o}`);for(let o of r.depConflicts)console.warn(` ⚠️ 依赖冲突: ${o}`);let n=await G(t),s=await q({appDir:t,declared:r.declared,actual:n}),i=s.filter(o=>o.level==="error");if(i.length>0){console.error("❌ doctor 错误:");for(let o of i)console.error(` - [${o.rule}] ${o.message}`);process.exitCode=1}else console.log("✅ doctor 无错误");for(let o of s.filter(a=>a.level==="warning"))console.warn(` ⚠️ [${o.rule}] ${o.message}`)}async function Hs(){let e=process.cwd(),t=B(e),r=await ue(e);if(console.log(`模板版本: ${t?.templateVersion??"未知"}`),r.length===0){console.log("(无已装模块)");return}for(let i of r)console.log(` ${i.id.padEnd(28)} ${i.pkg} [${i.mode}]`);let n=new Set((t?.npmModules??[]).map(i=>i.id)),s=(await z(e)).filter(i=>!n.has(i.id));if(s.length>0){console.log(" 本地模块(未在 app.json 登记):");for(let i of s)console.log(` ${i.id}`)}}async function Ks(e){let t=process.cwd(),r=await ue(t),n=await G(t),s=!1;for(let i of se){let o=i.kind,a=r.filter(g=>jt(o,g)).map(g=>g.id),c=n[o]?.moduleIds??[],l=a.filter(g=>!c.includes(g)),p=c.filter(g=>!a.includes(g));e&&(l=l.filter(g=>g===e),p=p.filter(g=>g===e));let u=n[o]?.broken??[],d=n[o]?.nonStandardLines??[],f=[];u.length>0&&f.push(`⚠️ 锚区破坏: ${u.join(", ")}`),l.length>0&&f.push(` - 已声明未装配: ${l.join(", ")}`),p.length>0&&f.push(` + 已装配未声明: ${p.join(", ")}`);for(let g of d)f.push(` ? 非标行: ${g}`);if(f.length>0){s=!0,console.log(`${i.path}`);for(let g of f)console.log(` ${g}`)}}s||console.log("无漂移:声明集合与实际装配集合一致")}async function Gs(e={}){let t=process.cwd(),r=await ue(t),n=await G(t),s=await q({appDir:t,declared:r,actual:n},{only:e.only?e.only.split(",").map(a=>a.trim()).filter(Boolean):void 0,skip:e.skip?e.skip.split(",").map(a=>a.trim()).filter(Boolean):void 0}),i=s.filter(a=>a.level==="error"),o=s.filter(a=>a.level==="warning");if(e.json)return console.log(JSON.stringify({errors:i,warnings:o,rules:s},null,2)),i.length>0&&(process.exitCode=1),{issues:s};if(s.length===0)console.log("✅ doctor 全绿(结构校验通过)");else{for(let a of i)console.error(`❌ [${a.rule}] ${a.message}`);for(let a of o)console.warn(`⚠️ [${a.rule}] ${a.message}`);i.length>0?(console.error(`doctor 失败: ${i.length} 个错误`),process.exitCode=1):console.log(`doctor 通过(${o.length} 个告警)`)}return{issues:s}}import{existsSync as kr}from"fs";import{readdir as yc,readFile as Zs,unlink as hc,writeFile as vc}from"fs/promises";import Ae from"path";import{diffArrays as gc}from"diff";function qs(e,t){let r=gc(e,t),n=[],s=0,i=null;for(let o of r)o.removed?(i?i.oldLines.push(...o.value):i={start:s,oldLines:[...o.value],newLines:[]},s+=o.value.length):o.added?i?i.newLines.push(...o.value):i={start:s,oldLines:[],newLines:[...o.value]}:(i&&(n.push(i),i=null),s+=o.value.length);return i&&n.push(i),n}function Xs(e,t,r){let n=e===""?[]:e.split(`
91
94
  `),s=t===""?[]:t.split(`
92
95
  `),i=r===""?[]:r.split(`
93
- `),o=Hs(n,s),a=Hs(n,i),c=new Map;for(let m of o)c.set(m.start,{ours:m});for(let m of a){let h=c.get(m.start);h?h.theirs=m:c.set(m.start,{theirs:m})}let l=[],p=[],u=new Set,d=(m,h)=>{let v=Math.max(m?.oldLines.length??0,h?.oldLines.length??0);return m&&h?JSON.stringify(m.oldLines)===JSON.stringify(h.oldLines)&&JSON.stringify(m.newLines)===JSON.stringify(h.newLines)?l.push(...m.newLines):(p.push([...m.newLines,"--",...h.newLines].join(`
96
+ `),o=qs(n,s),a=qs(n,i),c=new Map;for(let m of o)c.set(m.start,{ours:m});for(let m of a){let h=c.get(m.start);h?h.theirs=m:c.set(m.start,{theirs:m})}let l=[],p=[],u=new Set,d=(m,h)=>{let v=Math.max(m?.oldLines.length??0,h?.oldLines.length??0);return m&&h?JSON.stringify(m.oldLines)===JSON.stringify(h.oldLines)&&JSON.stringify(m.newLines)===JSON.stringify(h.newLines)?l.push(...m.newLines):(p.push([...m.newLines,"--",...h.newLines].join(`
94
97
  `)),l.push("<<<<<<< ours",...m.newLines,"=======",...h.newLines,">>>>>>> theirs")):m?l.push(...m.newLines):l.push(...h.newLines),v},f=0;for(;f<n.length;){let m=c.get(f);if(!m||u.has(f)){l.push(n[f]),f++;continue}u.add(f);let h=d(m.ours,m.theirs);h>0&&(f+=h)}let g=c.get(n.length);return g&&!u.has(n.length)&&d(g.ours,g.theirs),{merged:l.join(`
95
- `),conflicts:p}}var gc=new Set(["node_modules","dist",".git",".tbox"]);function Ks(e){if(e.endsWith(".tgz")&&vr(e)){let t=new U(e);return{dir:t.getDir(),tarball:t}}return{dir:Ae.resolve(e),tarball:null}}async function hr(e){let t=new Map;async function r(n){let s=Ae.join(e,n),i=await dc(s,{withFileTypes:!0});for(let o of i){if(gc.has(o.name))continue;let a=n?`${n}/${o.name}`:o.name,c=Ae.join(s,o.name);if(o.isDirectory())await r(a);else try{t.set(a,await Gs(c,"utf8"))}catch{}}}return await r(""),t}async function qs(e){let t=process.cwd(),r=B(t);if(!r)throw new Error("当前目录不是 tbox-app 应用(缺 .tbox/app.json)");let n=r.npmModules.find(a=>a.id===e.module);if(!n)throw new Error(`模块 ${e.module} 未在 .tbox/app.json 登记`);if(n.mode==="sdk"){if(e.dryRun){console.log(`[dry-run] pnpm update ${n.package}`);return}let{execFileSync:a}=await import("child_process");a("pnpm",["update",n.package],{stdio:"inherit",cwd:t}),console.log(`✅ 已升级 ${n.package}(sdk 模式)`);return}let s=Ae.join(t,"packages",e.module);if(!vr(s))throw new Error(`缺少 packages/${e.module}`);let i=await hr(s),o=[];try{let a,c,l;if(e.source){let k=Ks(e.source);k.tarball&&o.push(k.tarball),n.mode==="codegen"&&yt(k.dir),l=k.dir,a=await hr(k.dir),c=k.tarball?k.tarball.resolveVersion():Z(k.dir)?.version??n.version}else throw new Error("codegen 升级需要 --source <新版本地目录或 tgz>(npm 拉取为 manual,真实发布后回落)");let p=Se(t),u=n.mode==="codegen"?xe(n):null,d=u?new Map([...p,[u.publicName,u]]):p,f=Be(l),g=Be(s),m=ce(l),h=n.mode==="codegen"&&f?Te(f,n,d.values(),m):f,v=new Map,S=null;if(e.baseSource){let k=Ks(e.baseSource);k.tarball&&o.push(k.tarball),S=k.dir,v=await hr(k.dir)}let $=n.mode==="codegen"?ht(i,d.values()):i,R=n.mode==="codegen"?ht(v,d.values()):v,F=n.mode==="codegen"?ht(a,d.values()):a,A=new Set([...R.keys(),...$.keys(),...F.keys()]);A.delete("package.json");let N=new Map,P=[];for(let k of A){let O=R.get(k)??"",j=$.get(k)??"",ee=F.get(k)??"";if(e.ours){j&&N.set(k,j);continue}if(e.theirs){ee&&N.set(k,ee);continue}let Wt=Ws(O,j,ee);N.set(k,Wt.merged),Wt.conflicts.length>0&&P.push(`${k}: ${Wt.conflicts.length} 处冲突`)}if(n.mode==="codegen"&&h){let k={};try{k=JSON.parse(v.get("package.json")??"{}")}catch{k={}}let O=Te(k,n,d.values(),S?ce(S):void 0),j=Te(g,n,d.values(),ce(t)),ee=gn(O,j,h,{ours:e.ours,theirs:e.theirs});N.set("package.json",JSON.stringify(ee,null,2)+`
96
- `)}else N.set("package.json",await Gs(Ae.join(s,"package.json"),"utf8"));if(e.dryRun){console.log(`[dry-run] ${e.module}: ${A.size} 文件合并,冲突 ${P.length} 处`);for(let k of P)console.log(` ⚠️ ${k}`);return}for(let[k,O]of N){let j=Ae.join(s,k);if(O===""&&vr(j)){await fc(j),console.log(` 🗑 已删除 ${k}(升级源删除该文件)`);continue}await mc(j,O,"utf8")}await te(t,Yr(r,e.module,{baseVersion:c,version:c})),n.mode==="codegen"&&await vt(t,Se(t).values());let w=await me(t),D=await G(t),b=(await q({appDir:t,declared:w.declared,actual:D})).filter(k=>k.level==="error");if(b.length>0){console.error("❌ doctor 错误:");for(let k of b)console.error(` - [${k.rule}] ${k.message}`);process.exitCode=1}if(P.length>0){console.warn("⚠️ 升级完成,存在冲突标记(<<<<<<< ours / >>>>>>> theirs),请人工/Agent 解决后运行 doctor:");for(let k of P)console.warn(` - ${k}`)}else console.log(`✅ 已升级 ${e.module} → ${c}`)}finally{for(let a of o)a.dispose()}}import{existsSync as xr,readFileSync as xc,mkdtempSync as eo,rmSync as Sc}from"fs";import{tmpdir as to}from"os";import le from"path";import{existsSync as ie,readFileSync as Xs,readdirSync as yc}from"fs";import{execFileSync as hc}from"child_process";import J from"path";function Ys(e,t){return`${e.replace(/^@/,"").replace("/","-")}-${t}.tgz`}function vc(e){if(!ie(e)||!ie(J.join(e,"package.json")))throw new Error(`模块目录无效(缺 package.json): ${e}`);let t;try{t=JSON.parse(Xs(J.join(e,"package.json"),"utf8"))}catch{throw new Error(`package.json 解析失败: ${J.join(e,"package.json")}`)}let r=typeof t.name=="string"?t.name:"";if(!/^@tbox\.cn\//.test(r))throw new Error(`发布包名必须为 @tbox.cn/* scope: ${r||"(缺失)"}`);let n=typeof t.version=="string"?t.version:"";if(!/^\d+\.\d+\.\d+/.test(n))throw new Error(`版本号无效(需 semver x.y.z): ${n||"(缺失)"}`);return{name:r,version:n}}function wr(e,t){let{name:r,version:n}=vc(e),s=J.resolve(t);return hc("pnpm",["pack","--pack-destination",s],{stdio:"inherit",cwd:e}),J.join(s,Ys(r,n))}function Zs(e,t){return ie(J.join(e,"pnpm-workspace.template.yaml"))?"template":ie(J.join(e,"tbox.module.json"))?"module":/^@[^/]+\/app-contracts(?:-|$)/.test(t)?"contract":"generic"}function wc(e){let t=[];function r(n){let s=J.join(e,n);for(let i of yc(s,{withFileTypes:!0})){if(i.name==="node_modules"||i.name===".git")continue;let o=n?`${n}/${i.name}`:i.name;i.isDirectory()?r(o):t.push(o)}}return r(""),t}function bc(e){let t=[],r=n=>{typeof n=="string"&&t.push(n)};if(typeof e=="string")r(e);else if(e&&typeof e=="object"){for(let n of Object.values(e))if(typeof n=="string")r(n);else if(n&&typeof n=="object")for(let s of Object.values(n))r(s)}return t}function kc(e,t){let r=[],n=J.join(e,"package.json"),s;try{s=JSON.parse(Xs(n,"utf8"))}catch{return r.push({rule:"pack-manifest",level:"error",message:"产物缺少可解析的 package.json"}),r}let i=t??Zs(e,s.name??""),o=wc(e);for(let p of["dependencies","optionalDependencies","peerDependencies","devDependencies"]){let u=s[p];if(!(!u||typeof u!="object"))for(let[d,f]of Object.entries(u))typeof f=="string"&&/^(workspace:|catalog:)/.test(f)&&r.push({rule:"pack-protocol-residue",level:"error",message:`${d}: 发布态残留 pnpm 私有协议 "${f}"(应已归一化为实装版本)`})}if(s.exports!==void 0)for(let p of bc(s.exports))p.includes("/src/")||p==="src"?r.push({rule:"pack-exports",level:"error",message:`exports 指向开发态源码 "${p}"(发布态应指向 dist/)`}):p.startsWith("./")&&!ie(J.join(e,p))&&r.push({rule:"pack-exports",level:"error",message:`exports 目标缺失(产物内不存在): ${p}`});let a=s.files;if(Array.isArray(a)&&a.length>0){let p=new Set([...a.map(d=>String(d)),"package.json"]),u=o.filter(d=>![...p].some(f=>d===f||d.startsWith(`${f}/`)));u.length>0&&r.push({rule:"pack-whitelist",level:"error",message:`产物含白名单外文件: ${u.slice(0,5).join(", ")}${u.length>5?` 等 ${u.length} 个`:""}`})}else r.push({rule:"pack-whitelist",level:"warning",message:"未声明 files 白名单,产物范围不可控(建议声明 files 限制打包内容)"});let c=o.filter(p=>/(^|\/)\.env$/.test(p)||/(^|\/)\.npmrc$/.test(p));if(c.length>0&&r.push({rule:"pack-leak",level:"error",message:`产物含敏感文件: ${c.join(", ")}`}),i==="module")for(let p of["src","dist","tbox.module.json"])!o.includes(p)&&!ie(J.join(e,p))&&r.push({rule:"pack-files",level:"error",message:`业务模块产物缺少 ${p}`});else if(i==="template"){for(let p of["package.json","pnpm-workspace.template.yaml","apps/server/package.json","apps/client/package.json",".tbox/app.json"])ie(J.join(e,p))||r.push({rule:"pack-files",level:"error",message:`模板产物缺少 ${p}`});for(let p of["pnpm-workspace.yaml","pnpm-lock.yaml"])ie(J.join(e,p))&&r.push({rule:"pack-files",level:"error",message:`模板产物泄漏 ${p}(应仅含 pnpm-workspace.template.yaml / pnpm-lock.template.yaml)`});ie(J.join(e,"pnpm-lock.template.yaml"))||r.push({rule:"pack-files",level:"warning",message:"模板产物未携带 pnpm-lock.template.yaml(间接依赖未冻结——平台包发布后跑 sync-template-lockfile 生成)"})}else if(i==="contract")o.filter(u=>u.startsWith("dist/")&&u.endsWith(".d.ts")).length===0&&r.push({rule:"pack-files",level:"error",message:"契约包产物缺少 dist/*.d.ts"}),s.name==="@tbox.cn/app-contracts-mall"&&!ie(J.join(e,"src","index.ts"))&&r.push({rule:"pack-files",level:"error",message:"contracts-mall codegen 载荷缺少 src/index.ts"});else{let p=s.bin,u=typeof p=="string"?[p]:p&&typeof p=="object"?Object.values(p):[];for(let d of u)typeof d=="string"&&!o.includes(d)&&r.push({rule:"pack-files",level:"error",message:`bin 指向文件缺失: ${d}`})}let l=Array.isArray(a)&&a.length>0;for(let p of["LICENSE","README.md"])o.includes(p)||r.push({rule:"pack-docs",level:"warning",message:`产物缺少 ${p}${l?"(files 白名单已声明;发布完备性 backlog)":"(建议补充以完备发布元数据)"}`});return r}async function br(e){let t=new U(e);try{let r=t.getDir(),n=JSON.parse(await t.readFile("package.json")),s=Zs(r,n.name??""),i=kc(r,s);if(n.name&&n.version){let o=Ys(n.name,n.version);J.basename(e)!==o&&i.push({rule:"pack-filename",level:"error",message:`tgz 文件名 ${J.basename(e)} 与包 ${n.name}@${n.version} 期望 ${o} 不一致`})}return i}finally{t.dispose()}}function kr(e){for(let t of e)console.log(` ${t.level==="error"?"❌":"⚠️"} [${t.rule}] ${t.message}`)}async function Qs(e){let t=J.resolve(process.cwd(),e.module),r=wr(t,e.out);if(console.log(`✅ 已打包 ${J.basename(r)} → ${J.resolve(e.out)}`),e.check){let n=await br(r);kr(n),n.some(s=>s.level==="error")&&(process.exitCode=1)}}async function ro(e){let t=process.cwd(),r=le.resolve(t,e.module);if(!xr(r)||!xr(le.join(r,"package.json")))throw new Error(`模块目录无效(缺 package.json): ${e.module}`);let n=(()=>{try{return JSON.parse(xc(le.join(r,"package.json"),"utf8"))}catch{throw new Error(`模块 package.json 解析失败: ${e.module}`)}})();if(n.private===!0)throw new Error(`模块 ${e.module}(${n.name??"?"})声明 private:true——防误发布门禁拦截(本地 tgz/目录分发;恢复发布见仓库 docs/reference/operations.md 版本策略)`);let s,i=null;if(e.tgz){if(s=le.resolve(e.tgz),!xr(s))throw new Error(`tgz 产物不存在: ${e.tgz}`);let o=new U(s);try{let a=JSON.parse(await o.readFile("package.json"));if(a.name!==n.name)throw new Error(`--tgz 包名 ${a.name??"(未知)"} 与模块 ${n.name??"(未知)"} 不一致(请确认 --tgz 与模块匹配)`);if(a.private===!0)throw new Error(`--tgz 产物 ${le.basename(s)} 标记 private:true——防误发布门禁拦截`)}finally{o.dispose()}}else i=eo(le.join(to(),"tbox-publish-")),s=wr(r,i);try{let o=await br(s);o.length>0&&kr(o);let a=o.filter(p=>p.level==="error");if(a.length>0)throw new Error(`产物门禁失败(${a.length} 处 error),已中止发布: ${le.basename(s)}`);i||(i=eo(le.join(to(),"tbox-publish-")));let{execFileSync:c}=await import("child_process"),l=e.registry?["--registry",e.registry]:[];c("pnpm",["publish",s,"--access",e.access??"public",...l,...e.dryRun?["--dry-run"]:[]],{stdio:"inherit",cwd:i}),console.log(`✅ 已发布 ${le.basename(s)}${e.registry?` → ${e.registry}`:""}${e.dryRun?"(dry-run)":""}`)}finally{if(i)try{Sc(i,{recursive:!0,force:!0})}catch{}}}import{existsSync as At}from"fs";import{cp as $c,readFile as jc,rm as Ec,writeFile as Rc}from"fs/promises";import Oe from"path";function Dc(e){return At(Oe.join(e,"mini.project.json"))&&At(Oe.join(e,"app.json"))&&At(Oe.join(e,"pages"))}async function no(e){let t=e.platform??"alipay";ke(t,"miniapp-container init");let r=process.cwd(),n=B(r);if(!n)throw new Error("当前目录不是 tbox-app 应用(缺 .tbox/app.json)");let s=`@tbox.cn/app-miniapp-container-${t}`,i;if(e.source)i=fe(e.source,e.registry);else try{i=fe(s,e.registry)}catch(o){throw new Error(`未找到 ${s}(registry 拉取失败:${o.message})。离线场景用 --source <容器目录或 tgz>`)}try{let o=i.sourceDir;if(!Dc(o))throw new Error(`源不是小程序容器工程(缺 mini.project.json/app.json/pages): ${e.source??s}`);let a=Oe.join(r,"apps",`miniapp-container-${t}`);if(At(a)){if(!e.force)throw new Error(`容器已存在: apps/miniapp-container-${t}(--force 删除重展开)`);await Ec(a,{recursive:!0,force:!0})}await $c(o,a,{recursive:!0,force:!0,filter:d=>{let f=Oe.basename(d);return!["node_modules","dist",".git",".DS_Store",".tbox"].includes(f)}});let c=Oe.join(a,"package.json"),l=JSON.parse(await jc(c,"utf8")),p=typeof l.name=="string"?l.name:s;l.name=`@app/miniapp-container-${t}`,l.private=!0,await Rc(c,JSON.stringify(l,null,2)+`
97
- `,"utf8");let u=qt(o);await te(r,Xr(n,{id:t,package:u.name??s,version:i.source.resolveVersion()||u.version,dir:`apps/miniapp-container-${t}`})),De(r),console.log(`✅ 已初始化容器 @app/miniapp-container-${t}(v${i.source.resolveVersion()||u.version},源 ${p})`),console.log(` ⚡ 展开至 apps/miniapp-container-${t}(workspace apps/* 自动纳管)`),console.log(` 下一步: pnpm install && pnpm --filter @app/miniapp-container-${t} dev`)}finally{(i.source instanceof U||i.source instanceof de)&&i.source.dispose()}}import{existsSync as so,readFileSync as Cc}from"fs";import Ze from"path";function Sr(e){return Ze.join(e,"config","integrations.json")}async function oo(e){if(so(Sr(e)))return;let t=await Ne(e);t.generated?console.log(` ⚡ 已生成 mock 槽绑定(config/integrations.json:${t.services.join(", ")})`):(Re(Sr(e),JSON.stringify({services:{}},null,2)+`
98
- `),console.log(" ⚡ 已创建 config/integrations.json 空骨架(无 local 供给可派生 mock 绑定)"))}function Ot(e){let t=Sr(e);if(!so(t))throw new Error("config/integrations.json 不存在(provider bind 需已初始化的槽位配置面——create 产物或手动创建)");let r=Kr(e);if(r===null){try{JSON.parse(Cc(t,"utf8"))}catch(n){throw new Error(`config/integrations.json 解析失败:${n.message}`)}throw new Error("config/integrations.json 解析失败")}if(!r.services||typeof r.services!="object")throw new Error("integrations.json 缺 services");return r}async function we(e,t){await nt(e).writeIntegrationsConfig(t)}async function Pt(e){let{collectDeclared:t}=await import("./declared-4SBML2FU.js"),r=await t(e),n=await G(e),s=await q({appDir:e,declared:r,actual:n},{only:["integration-services"]}),i=s.filter(o=>o.level==="error");for(let o of i)console.error(` ❌ [${o.rule}] ${o.message}`);for(let o of s.filter(a=>a.level==="warning"))console.warn(` ⚠️ [${o.rule}] ${o.message}`);i.length>0&&(process.exitCode=1)}async function Lt(e){let t=await rt(e);if(!t.strictValidation){let r=t.notes[0]??"升级应用 @tbox.cn/app-contracts 依赖后可用";throw new Error(`integrations: contracts 严格校验面不可用(${t.version??"未安装"},需 ≥0.9)——${r}`)}}async function io(e,t,r,n={}){let s=Ze.resolve(n.appDir??process.cwd());await Lt(s),await oo(s);let i=Ot(s);if(n.instance){let o=i.services[e]??{instances:{}};o.instances??={};let a={...o.instances[n.instance],provider:t};r?a.implementation=r:delete a.implementation,o.instances[n.instance]=a,i.services[e]=o,await we(s,i),console.log(r?`✅ 已绑定 ${e}@${n.instance} → ${t}/${r}(实例覆盖位)`:`✅ 已绑定 ${e}@${n.instance} → ${t}(实例覆盖位——implementation 派生:catalog 唯一供给)`)}else{let o=i.services[e];o?(o.provider=t,r?o.implementation=r:delete o.implementation):i.services[e]=r?{provider:t,implementation:r}:{provider:t},await we(s,i),console.log(r?`✅ 已绑定 ${e} → ${t}/${r}${o?"(实例集保留)":"(新槽——instances 缺席 = 通配激活,立即生效;限定实例集请补 instances 显式键)"}`:`✅ 已绑定 ${e} → ${t}(implementation 派生:catalog 唯一供给)${o?"(实例集保留)":"(新槽——instances 缺席 = 通配激活,立即生效;限定实例集请补 instances 显式键)"}`)}await Pt(s)}async function ao(e,t={}){let r=Ze.resolve(t.appDir??process.cwd());await Lt(r),await oo(r);let n=Ot(r);if(t.domain)n.domains??={},n.domains[t.domain]={...n.domains[t.domain],provider:e},await we(r,n),console.log(`✅ 域默认厂商 ${t.domain} → ${e}(该域全部槽生效——槽级显式绑定除外)`);else{n.provider=e,await we(r,n),console.log(`✅ 应用默认厂商 → ${e}(全部未显式绑定槽生效——instances 缺席槽即通配激活)`);let s=Object.entries(n.domains??{}).filter(([,i])=>typeof i.provider=="string"&&i.provider!==e).map(([i])=>i);s.length>0&&console.log(` ℹ 域级覆盖仍优先生效:${s.join(", ")}`)}await Pt(r)}async function co(e={}){let t=Ze.resolve(e.appDir??process.cwd());await Lt(t);let r=Ot(t);if(e.domain){let n=r.domains?.[e.domain];if(!n||n.provider===void 0)throw new Error(`域 ${e.domain} 无默认厂商(无可删项)`);delete n.provider,Object.keys(n).length===0&&delete r.domains?.[e.domain],r.domains&&Object.keys(r.domains).length===0&&delete r.domains,await we(t,r),console.log(`✅ 已清除域默认厂商 ${e.domain}(该域槽回落槽级/root 继承)`)}else{if(r.provider===void 0)throw new Error("root 无默认厂商(无可删项——provider use 设置)");delete r.provider,await we(t,r),console.log("✅ 已清除应用默认厂商(未显式绑定槽将 binding-unresolved——doctor 即时反馈)")}await Pt(t)}async function lo(e,t={}){let r=Ze.resolve(t.appDir??process.cwd());await Lt(r);let n=Ot(r),s=n.services[e];if(!s)throw new Error(`服务槽 ${e} 未配置(无可解绑项)`);if(t.instance){if(!s.instances?.[t.instance])throw new Error(`服务槽 ${e} 无实例 ${t.instance}(无可解绑项)`);delete s.instances[t.instance],await we(r,n),console.log(`✅ 已解绑 ${e}@${t.instance}(实例覆盖删除——回落槽级默认)`)}else delete n.services[e],await we(r,n),console.log(`✅ 已解绑 ${e}(槽与实例集删除——模块走降级链)`);await Pt(r)}import{existsSync as po,readFileSync as uo}from"fs";import je from"path";async function Tc(e){let t=new Map,r=s=>{typeof s.provider!="string"||typeof s.implementation!="string"||t.set(`${s.provider}-${s.implementation}`,{provider:s.provider,implementation:s.implementation})};for(let s of await z(e))for(let i of s.descriptor.contributes.providers?.slots??[])r(i);let n=je.join(e,".tbox","app.json");if(po(n))try{let s=JSON.parse(uo(n,"utf8"));for(let i of s.npmModules??[]){if(typeof i.id!="string"||typeof i.package!="string")continue;let o=Kt(je.join(e,"packages",i.id))??Kt(je.join(Mc(e),...i.package.split("/")));for(let a of o?.contributes.providers?.slots??[])r(a)}}catch{}return t}function Mc(e){return je.join(e,"node_modules")}function Ic(e,t){return t.get(e)}async function fo(e={}){let t=je.resolve(e.appDir??process.cwd()),r=je.join(t,"config","integrations.json");if(!po(r))throw new Error(`config/integrations.json 不存在:${r}`);let n=JSON.parse(uo(r,"utf8"));if(!n.services||typeof n.services!="object")throw new Error("integrations.json 缺 services");let s=await Tc(t),i=[],o=[],a=0,c=(l,p)=>{let u=Ic(p,s);return u?(i.push(` ${l}: '${p}' → provider='${u.provider}', implementation='${u.implementation}'`),a++):o.push(`${l}: '${p}'`),u};for(let[l,p]of Object.entries(n.services)){if(typeof p.provider=="string"&&p.provider){let u=c(`services.${l}.provider`,p.provider);u&&(p.provider=u.provider,p.implementation=u.implementation)}else if(p.provider&&typeof p.provider=="object"){let u=p.provider;typeof u.providerId=="string"&&(u.provider=u.providerId,delete u.providerId,i.push(` services.${l}.provider: 内联声明 providerId → provider(直译)`),a++)}for(let[u,d]of Object.entries(p.instances??{})){if(typeof d.provider=="string"&&d.provider){let f=c(`services.${l}.instances.${u}.provider`,d.provider);f&&(d.provider=f.provider,d.implementation=f.implementation)}d.enabled===!0&&delete d.enabled}}console.log(`provider migrate:${a} 项迁移(反查表 ${s.size} 条)`);for(let l of i)console.log(l);if(o.length>0){console.warn("⚠️ 未命中反查表(人工处理,保留原值):");for(let l of o)console.warn(` ${l}`);process.exitCode=1}e.write?(await nt(t).writeIntegrationsConfig(n),console.log(`✅ 已写回 ${je.relative(process.cwd(),r)||r}`)):console.log("(dry-run:加 --write 落盘)")}import{spawn as Ac}from"child_process";import{existsSync as I,mkdirSync as $r,readFileSync as X,realpathSync as ae,readdirSync as Oc,rmSync as Pc,symlinkSync as Lc,unlinkSync as bo,writeFileSync as Ft}from"fs";import{createHash as Fc}from"crypto";import x from"path";import{fileURLToPath as _c}from"url";var Pe=".tbox-dev.local",mo="templates/template-agent-mall",Nc=["apps","server"],Vc=8e3;function Jc(e){let t=x.join(e,".real-env","config");return I(t)?Oc(t).filter(r=>I(x.join(t,r,"integrations.json"))).sort():[]}var go="'../../.tbox-dev.local/vite-override.mjs'",zc="TBOX_CONFIG_DIR";function Uc(){if(process.env.NODE_ENV==="test"&&process.env.TBOX_DEV_REPO_ROOT)return ae(process.env.TBOX_DEV_REPO_ROOT);let e=x.dirname(_c(import.meta.url));for(let t=0;t<10;t++){if(I(x.join(e,"pnpm-workspace.yaml")))return e;let r=x.dirname(e);if(r===e)break;e=r}throw new Error("未能定位仓库根(缺少 pnpm-workspace.yaml)——请在仓库内执行 tbox-app dev")}function Bc(e){let t=x.join(e,"package.json");if(!I(t))throw new Error(`目录缺 package.json:${e}`);try{let r=JSON.parse(X(t,"utf8"));if(typeof r.name!="string"||!r.name)throw new Error("name 缺失");return{name:r.name,version:String(r.version??"0.0.0")}}catch(r){throw new Error(`package.json 解析失败(${e}):${r.message}`)}}function Hc(e){let t=x.join(e,"tbox.module.json");if(!I(t))throw new Error(`目录缺 tbox.module.json:${e}(是否传了非模块目录?)`);let r=Ee(JSON.parse(X(t,"utf8")));if(!r.ok)throw new Error(`tbox.module.json 校验失败(${e}):
98
+ `),conflicts:p}}var wc=new Set(["node_modules","dist",".git",".tbox"]);function Ys(e){if(e.endsWith(".tgz")&&kr(e)){let t=new U(e);return{dir:t.getDir(),tarball:t}}return{dir:Ae.resolve(e),tarball:null}}async function br(e){let t=new Map;async function r(n){let s=Ae.join(e,n),i=await yc(s,{withFileTypes:!0});for(let o of i){if(wc.has(o.name))continue;let a=n?`${n}/${o.name}`:o.name,c=Ae.join(s,o.name);if(o.isDirectory())await r(a);else try{t.set(a,await Zs(c,"utf8"))}catch{}}}return await r(""),t}async function Qs(e){let t=process.cwd(),r=B(t);if(!r)throw new Error("当前目录不是 tbox-app 应用(缺 .tbox/app.json)");let n=r.npmModules.find(a=>a.id===e.module);if(!n)throw new Error(`模块 ${e.module} 未在 .tbox/app.json 登记`);if(n.mode==="sdk"){if(e.dryRun){console.log(`[dry-run] pnpm update ${n.package}`);return}let{execFileSync:a}=await import("child_process");a("pnpm",["update",n.package],{stdio:"inherit",cwd:t}),console.log(`✅ 已升级 ${n.package}(sdk 模式)`);return}let s=Ae.join(t,"packages",e.module);if(!kr(s))throw new Error(`缺少 packages/${e.module}`);let i=await br(s),o=[];try{let a,c,l;if(e.source){let k=Ys(e.source);k.tarball&&o.push(k.tarball),n.mode==="codegen"&&vt(k.dir),l=k.dir,a=await br(k.dir),c=k.tarball?k.tarball.resolveVersion():Z(k.dir)?.version??n.version}else throw new Error("codegen 升级需要 --source <新版本地目录或 tgz>(npm 拉取为 manual,真实发布后回落)");let p=Se(t),u=n.mode==="codegen"?xe(n):null,d=u?new Map([...p,[u.publicName,u]]):p,f=Be(l),g=Be(s),m=ce(l),h=n.mode==="codegen"&&f?Te(f,n,d.values(),m):f,v=new Map,S=null;if(e.baseSource){let k=Ys(e.baseSource);k.tarball&&o.push(k.tarball),S=k.dir,v=await br(k.dir)}let $=n.mode==="codegen"?wt(i,d.values()):i,R=n.mode==="codegen"?wt(v,d.values()):v,F=n.mode==="codegen"?wt(a,d.values()):a,A=new Set([...R.keys(),...$.keys(),...F.keys()]);A.delete("package.json");let N=new Map,P=[];for(let k of A){let O=R.get(k)??"",j=$.get(k)??"",ee=F.get(k)??"";if(e.ours){j&&N.set(k,j);continue}if(e.theirs){ee&&N.set(k,ee);continue}let Gt=Xs(O,j,ee);N.set(k,Gt.merged),Gt.conflicts.length>0&&P.push(`${k}: ${Gt.conflicts.length} 处冲突`)}if(n.mode==="codegen"&&h){let k={};try{k=JSON.parse(v.get("package.json")??"{}")}catch{k={}}let O=Te(k,n,d.values(),S?ce(S):void 0),j=Te(g,n,d.values(),ce(t)),ee=wn(O,j,h,{ours:e.ours,theirs:e.theirs});N.set("package.json",JSON.stringify(ee,null,2)+`
99
+ `)}else N.set("package.json",await Zs(Ae.join(s,"package.json"),"utf8"));if(e.dryRun){console.log(`[dry-run] ${e.module}: ${A.size} 文件合并,冲突 ${P.length} 处`);for(let k of P)console.log(` ⚠️ ${k}`);return}for(let[k,O]of N){let j=Ae.join(s,k);if(O===""&&kr(j)){await hc(j),console.log(` 🗑 已删除 ${k}(升级源删除该文件)`);continue}await vc(j,O,"utf8")}await te(t,en(r,e.module,{baseVersion:c,version:c})),n.mode==="codegen"&&await bt(t,Se(t).values());let w=await me(t),D=await G(t),b=(await q({appDir:t,declared:w.declared,actual:D})).filter(k=>k.level==="error");if(b.length>0){console.error("❌ doctor 错误:");for(let k of b)console.error(` - [${k.rule}] ${k.message}`);process.exitCode=1}if(P.length>0){console.warn("⚠️ 升级完成,存在冲突标记(<<<<<<< ours / >>>>>>> theirs),请人工/Agent 解决后运行 doctor:");for(let k of P)console.warn(` - ${k}`)}else console.log(`✅ 已升级 ${e.module} → ${c}`)}finally{for(let a of o)a.dispose()}}import{existsSync as jr,readFileSync as Ec,mkdtempSync as so,rmSync as Rc}from"fs";import{tmpdir as oo}from"os";import le from"path";import{existsSync as ie,readFileSync as eo,readdirSync as bc}from"fs";import{execFileSync as kc}from"child_process";import J from"path";function to(e,t){return`${e.replace(/^@/,"").replace("/","-")}-${t}.tgz`}function xc(e){if(!ie(e)||!ie(J.join(e,"package.json")))throw new Error(`模块目录无效(缺 package.json): ${e}`);let t;try{t=JSON.parse(eo(J.join(e,"package.json"),"utf8"))}catch{throw new Error(`package.json 解析失败: ${J.join(e,"package.json")}`)}let r=typeof t.name=="string"?t.name:"";if(!/^@tbox\.cn\//.test(r))throw new Error(`发布包名必须为 @tbox.cn/* scope: ${r||"(缺失)"}`);let n=typeof t.version=="string"?t.version:"";if(!/^\d+\.\d+\.\d+/.test(n))throw new Error(`版本号无效(需 semver x.y.z): ${n||"(缺失)"}`);return{name:r,version:n}}function xr(e,t){let{name:r,version:n}=xc(e),s=J.resolve(t);return kc("pnpm",["pack","--pack-destination",s],{stdio:"inherit",cwd:e}),J.join(s,to(r,n))}function ro(e,t){return ie(J.join(e,"pnpm-workspace.template.yaml"))?"template":ie(J.join(e,"tbox.module.json"))?"module":/^@[^/]+\/app-contracts(?:-|$)/.test(t)?"contract":"generic"}function Sc(e){let t=[];function r(n){let s=J.join(e,n);for(let i of bc(s,{withFileTypes:!0})){if(i.name==="node_modules"||i.name===".git")continue;let o=n?`${n}/${i.name}`:i.name;i.isDirectory()?r(o):t.push(o)}}return r(""),t}function $c(e){let t=[],r=n=>{typeof n=="string"&&t.push(n)};if(typeof e=="string")r(e);else if(e&&typeof e=="object"){for(let n of Object.values(e))if(typeof n=="string")r(n);else if(n&&typeof n=="object")for(let s of Object.values(n))r(s)}return t}function jc(e,t){let r=[],n=J.join(e,"package.json"),s;try{s=JSON.parse(eo(n,"utf8"))}catch{return r.push({rule:"pack-manifest",level:"error",message:"产物缺少可解析的 package.json"}),r}let i=t??ro(e,s.name??""),o=Sc(e);for(let p of["dependencies","optionalDependencies","peerDependencies","devDependencies"]){let u=s[p];if(!(!u||typeof u!="object"))for(let[d,f]of Object.entries(u))typeof f=="string"&&/^(workspace:|catalog:)/.test(f)&&r.push({rule:"pack-protocol-residue",level:"error",message:`${d}: 发布态残留 pnpm 私有协议 "${f}"(应已归一化为实装版本)`})}if(s.exports!==void 0)for(let p of $c(s.exports))p.includes("/src/")||p==="src"?r.push({rule:"pack-exports",level:"error",message:`exports 指向开发态源码 "${p}"(发布态应指向 dist/)`}):p.startsWith("./")&&!ie(J.join(e,p))&&r.push({rule:"pack-exports",level:"error",message:`exports 目标缺失(产物内不存在): ${p}`});let a=s.files;if(Array.isArray(a)&&a.length>0){let p=new Set([...a.map(d=>String(d)),"package.json"]),u=o.filter(d=>![...p].some(f=>d===f||d.startsWith(`${f}/`)));u.length>0&&r.push({rule:"pack-whitelist",level:"error",message:`产物含白名单外文件: ${u.slice(0,5).join(", ")}${u.length>5?` 等 ${u.length} 个`:""}`})}else r.push({rule:"pack-whitelist",level:"warning",message:"未声明 files 白名单,产物范围不可控(建议声明 files 限制打包内容)"});let c=o.filter(p=>/(^|\/)\.env$/.test(p)||/(^|\/)\.npmrc$/.test(p));if(c.length>0&&r.push({rule:"pack-leak",level:"error",message:`产物含敏感文件: ${c.join(", ")}`}),i==="module")for(let p of["src","dist","tbox.module.json"])!o.includes(p)&&!ie(J.join(e,p))&&r.push({rule:"pack-files",level:"error",message:`业务模块产物缺少 ${p}`});else if(i==="template"){for(let p of["package.json","pnpm-workspace.template.yaml","apps/server/package.json","apps/client/package.json",".tbox/app.json"])ie(J.join(e,p))||r.push({rule:"pack-files",level:"error",message:`模板产物缺少 ${p}`});for(let p of["pnpm-workspace.yaml","pnpm-lock.yaml"])ie(J.join(e,p))&&r.push({rule:"pack-files",level:"error",message:`模板产物泄漏 ${p}(应仅含 pnpm-workspace.template.yaml / pnpm-lock.template.yaml)`});ie(J.join(e,"pnpm-lock.template.yaml"))||r.push({rule:"pack-files",level:"warning",message:"模板产物未携带 pnpm-lock.template.yaml(间接依赖未冻结——平台包发布后跑 sync-template-lockfile 生成)"})}else if(i==="contract")o.filter(u=>u.startsWith("dist/")&&u.endsWith(".d.ts")).length===0&&r.push({rule:"pack-files",level:"error",message:"契约包产物缺少 dist/*.d.ts"}),s.name==="@tbox.cn/app-contracts-mall"&&!ie(J.join(e,"src","index.ts"))&&r.push({rule:"pack-files",level:"error",message:"contracts-mall codegen 载荷缺少 src/index.ts"});else{let p=s.bin,u=typeof p=="string"?[p]:p&&typeof p=="object"?Object.values(p):[];for(let d of u)typeof d=="string"&&!o.includes(d)&&r.push({rule:"pack-files",level:"error",message:`bin 指向文件缺失: ${d}`})}let l=Array.isArray(a)&&a.length>0;for(let p of["LICENSE","README.md"])o.includes(p)||r.push({rule:"pack-docs",level:"warning",message:`产物缺少 ${p}${l?"(files 白名单已声明;发布完备性 backlog)":"(建议补充以完备发布元数据)"}`});return r}async function Sr(e){let t=new U(e);try{let r=t.getDir(),n=JSON.parse(await t.readFile("package.json")),s=ro(r,n.name??""),i=jc(r,s);if(n.name&&n.version){let o=to(n.name,n.version);J.basename(e)!==o&&i.push({rule:"pack-filename",level:"error",message:`tgz 文件名 ${J.basename(e)} 与包 ${n.name}@${n.version} 期望 ${o} 不一致`})}return i}finally{t.dispose()}}function $r(e){for(let t of e)console.log(` ${t.level==="error"?"❌":"⚠️"} [${t.rule}] ${t.message}`)}async function no(e){let t=J.resolve(process.cwd(),e.module),r=xr(t,e.out);if(console.log(`✅ 已打包 ${J.basename(r)} → ${J.resolve(e.out)}`),e.check){let n=await Sr(r);$r(n),n.some(s=>s.level==="error")&&(process.exitCode=1)}}async function io(e){let t=process.cwd(),r=le.resolve(t,e.module);if(!jr(r)||!jr(le.join(r,"package.json")))throw new Error(`模块目录无效(缺 package.json): ${e.module}`);let n=(()=>{try{return JSON.parse(Ec(le.join(r,"package.json"),"utf8"))}catch{throw new Error(`模块 package.json 解析失败: ${e.module}`)}})();if(n.private===!0)throw new Error(`模块 ${e.module}(${n.name??"?"})声明 private:true——防误发布门禁拦截(本地 tgz/目录分发;恢复发布见仓库 docs/reference/operations.md 版本策略)`);let s,i=null;if(e.tgz){if(s=le.resolve(e.tgz),!jr(s))throw new Error(`tgz 产物不存在: ${e.tgz}`);let o=new U(s);try{let a=JSON.parse(await o.readFile("package.json"));if(a.name!==n.name)throw new Error(`--tgz 包名 ${a.name??"(未知)"} 与模块 ${n.name??"(未知)"} 不一致(请确认 --tgz 与模块匹配)`);if(a.private===!0)throw new Error(`--tgz 产物 ${le.basename(s)} 标记 private:true——防误发布门禁拦截`)}finally{o.dispose()}}else i=so(le.join(oo(),"tbox-publish-")),s=xr(r,i);try{let o=await Sr(s);o.length>0&&$r(o);let a=o.filter(p=>p.level==="error");if(a.length>0)throw new Error(`产物门禁失败(${a.length} 处 error),已中止发布: ${le.basename(s)}`);i||(i=so(le.join(oo(),"tbox-publish-")));let{execFileSync:c}=await import("child_process"),l=e.registry?["--registry",e.registry]:[];c("pnpm",["publish",s,"--access",e.access??"public",...l,...e.dryRun?["--dry-run"]:[]],{stdio:"inherit",cwd:i}),console.log(`✅ 已发布 ${le.basename(s)}${e.registry?` → ${e.registry}`:""}${e.dryRun?"(dry-run)":""}`)}finally{if(i)try{Rc(i,{recursive:!0,force:!0})}catch{}}}import{existsSync as Pt}from"fs";import{cp as Dc,readFile as Cc,rm as Tc,writeFile as Mc}from"fs/promises";import Oe from"path";function Ic(e){return Pt(Oe.join(e,"mini.project.json"))&&Pt(Oe.join(e,"app.json"))&&Pt(Oe.join(e,"pages"))}async function ao(e){let t=e.platform??"alipay";ke(t,"miniapp-container init");let r=process.cwd(),n=B(r);if(!n)throw new Error("当前目录不是 tbox-app 应用(缺 .tbox/app.json)");let s=`@tbox.cn/app-miniapp-container-${t}`,i;if(e.source)i=fe(e.source,e.registry);else try{i=fe(s,e.registry)}catch(o){throw new Error(`未找到 ${s}(registry 拉取失败:${o.message})。离线场景用 --source <容器目录或 tgz>`)}try{let o=i.sourceDir;if(!Ic(o))throw new Error(`源不是小程序容器工程(缺 mini.project.json/app.json/pages): ${e.source??s}`);let a=Oe.join(r,"apps",`miniapp-container-${t}`);if(Pt(a)){if(!e.force)throw new Error(`容器已存在: apps/miniapp-container-${t}(--force 删除重展开)`);await Tc(a,{recursive:!0,force:!0})}await Dc(o,a,{recursive:!0,force:!0,filter:d=>{let f=Oe.basename(d);return!["node_modules","dist",".git",".DS_Store",".tbox"].includes(f)}});let c=Oe.join(a,"package.json"),l=JSON.parse(await Cc(c,"utf8")),p=typeof l.name=="string"?l.name:s;l.name=`@app/miniapp-container-${t}`,l.private=!0,await Mc(c,JSON.stringify(l,null,2)+`
100
+ `,"utf8");let u=Zt(o);await te(r,Qr(n,{id:t,package:u.name??s,version:i.source.resolveVersion()||u.version,dir:`apps/miniapp-container-${t}`})),De(r),console.log(`✅ 已初始化容器 @app/miniapp-container-${t}(v${i.source.resolveVersion()||u.version},源 ${p})`),console.log(` ⚡ 展开至 apps/miniapp-container-${t}(workspace apps/* 自动纳管)`),console.log(` 下一步: pnpm install && pnpm --filter @app/miniapp-container-${t} dev`)}finally{(i.source instanceof U||i.source instanceof de)&&i.source.dispose()}}import{existsSync as co,readFileSync as Ac}from"fs";import Ze from"path";function Er(e){return Ze.join(e,"config","integrations.json")}async function lo(e){if(co(Er(e)))return;let t=await Ne(e);t.generated?console.log(` ⚡ 已生成 mock 槽绑定(config/integrations.json:${t.services.join(", ")})`):(Re(Er(e),JSON.stringify({services:{}},null,2)+`
101
+ `),console.log(" ⚡ 已创建 config/integrations.json 空骨架(无 local 供给可派生 mock 绑定)"))}function Lt(e){let t=Er(e);if(!co(t))throw new Error("config/integrations.json 不存在(provider bind 需已初始化的槽位配置面——create 产物或手动创建)");let r=Xr(e);if(r===null){try{JSON.parse(Ac(t,"utf8"))}catch(n){throw new Error(`config/integrations.json 解析失败:${n.message}`)}throw new Error("config/integrations.json 解析失败")}if(!r.services||typeof r.services!="object")throw new Error("integrations.json 缺 services");return r}async function we(e,t){await nt(e).writeIntegrationsConfig(t)}async function Ft(e){let{collectDeclared:t}=await import("./declared-4SBML2FU.js"),r=await t(e),n=await G(e),s=await q({appDir:e,declared:r,actual:n},{only:["integration-services"]}),i=s.filter(o=>o.level==="error");for(let o of i)console.error(` ❌ [${o.rule}] ${o.message}`);for(let o of s.filter(a=>a.level==="warning"))console.warn(` ⚠️ [${o.rule}] ${o.message}`);i.length>0&&(process.exitCode=1)}async function _t(e){let t=await rt(e);if(!t.strictValidation){let r=t.notes[0]??"升级应用 @tbox.cn/app-contracts 依赖后可用";throw new Error(`integrations: contracts 严格校验面不可用(${t.version??"未安装"},需 ≥0.9)——${r}`)}}async function po(e,t,r,n={}){let s=Ze.resolve(n.appDir??process.cwd());await _t(s),await lo(s);let i=Lt(s);if(n.instance){let o=i.services[e]??{instances:{}};o.instances??={};let a={...o.instances[n.instance],provider:t};r?a.implementation=r:delete a.implementation,o.instances[n.instance]=a,i.services[e]=o,await we(s,i),console.log(r?`✅ 已绑定 ${e}@${n.instance} → ${t}/${r}(实例覆盖位)`:`✅ 已绑定 ${e}@${n.instance} → ${t}(实例覆盖位——implementation 派生:catalog 唯一供给)`)}else{let o=i.services[e];o?(o.provider=t,r?o.implementation=r:delete o.implementation):i.services[e]=r?{provider:t,implementation:r}:{provider:t},await we(s,i),console.log(r?`✅ 已绑定 ${e} → ${t}/${r}${o?"(实例集保留)":"(新槽——instances 缺席 = 通配激活,立即生效;限定实例集请补 instances 显式键)"}`:`✅ 已绑定 ${e} → ${t}(implementation 派生:catalog 唯一供给)${o?"(实例集保留)":"(新槽——instances 缺席 = 通配激活,立即生效;限定实例集请补 instances 显式键)"}`)}await Ft(s)}async function uo(e,t={}){let r=Ze.resolve(t.appDir??process.cwd());await _t(r),await lo(r);let n=Lt(r);if(t.domain)n.domains??={},n.domains[t.domain]={...n.domains[t.domain],provider:e},await we(r,n),console.log(`✅ 域默认厂商 ${t.domain} → ${e}(该域全部槽生效——槽级显式绑定除外)`);else{n.provider=e,await we(r,n),console.log(`✅ 应用默认厂商 → ${e}(全部未显式绑定槽生效——instances 缺席槽即通配激活)`);let s=Object.entries(n.domains??{}).filter(([,i])=>typeof i.provider=="string"&&i.provider!==e).map(([i])=>i);s.length>0&&console.log(` ℹ 域级覆盖仍优先生效:${s.join(", ")}`)}await Ft(r)}async function fo(e={}){let t=Ze.resolve(e.appDir??process.cwd());await _t(t);let r=Lt(t);if(e.domain){let n=r.domains?.[e.domain];if(!n||n.provider===void 0)throw new Error(`域 ${e.domain} 无默认厂商(无可删项)`);delete n.provider,Object.keys(n).length===0&&delete r.domains?.[e.domain],r.domains&&Object.keys(r.domains).length===0&&delete r.domains,await we(t,r),console.log(`✅ 已清除域默认厂商 ${e.domain}(该域槽回落槽级/root 继承)`)}else{if(r.provider===void 0)throw new Error("root 无默认厂商(无可删项——provider use 设置)");delete r.provider,await we(t,r),console.log("✅ 已清除应用默认厂商(未显式绑定槽将 binding-unresolved——doctor 即时反馈)")}await Ft(t)}async function mo(e,t={}){let r=Ze.resolve(t.appDir??process.cwd());await _t(r);let n=Lt(r),s=n.services[e];if(!s)throw new Error(`服务槽 ${e} 未配置(无可解绑项)`);if(t.instance){if(!s.instances?.[t.instance])throw new Error(`服务槽 ${e} 无实例 ${t.instance}(无可解绑项)`);delete s.instances[t.instance],await we(r,n),console.log(`✅ 已解绑 ${e}@${t.instance}(实例覆盖删除——回落槽级默认)`)}else delete n.services[e],await we(r,n),console.log(`✅ 已解绑 ${e}(槽与实例集删除——模块走降级链)`);await Ft(r)}import{existsSync as go,readFileSync as yo}from"fs";import je from"path";async function Oc(e){let t=new Map,r=s=>{typeof s.provider!="string"||typeof s.implementation!="string"||t.set(`${s.provider}-${s.implementation}`,{provider:s.provider,implementation:s.implementation})};for(let s of await z(e))for(let i of s.descriptor.contributes.providers?.slots??[])r(i);let n=je.join(e,".tbox","app.json");if(go(n))try{let s=JSON.parse(yo(n,"utf8"));for(let i of s.npmModules??[]){if(typeof i.id!="string"||typeof i.package!="string")continue;let o=qt(je.join(e,"packages",i.id))??qt(je.join(Pc(e),...i.package.split("/")));for(let a of o?.contributes.providers?.slots??[])r(a)}}catch{}return t}function Pc(e){return je.join(e,"node_modules")}function Lc(e,t){return t.get(e)}async function ho(e={}){let t=je.resolve(e.appDir??process.cwd()),r=je.join(t,"config","integrations.json");if(!go(r))throw new Error(`config/integrations.json 不存在:${r}`);let n=JSON.parse(yo(r,"utf8"));if(!n.services||typeof n.services!="object")throw new Error("integrations.json 缺 services");let s=await Oc(t),i=[],o=[],a=0,c=(l,p)=>{let u=Lc(p,s);return u?(i.push(` ${l}: '${p}' → provider='${u.provider}', implementation='${u.implementation}'`),a++):o.push(`${l}: '${p}'`),u};for(let[l,p]of Object.entries(n.services)){if(typeof p.provider=="string"&&p.provider){let u=c(`services.${l}.provider`,p.provider);u&&(p.provider=u.provider,p.implementation=u.implementation)}else if(p.provider&&typeof p.provider=="object"){let u=p.provider;typeof u.providerId=="string"&&(u.provider=u.providerId,delete u.providerId,i.push(` services.${l}.provider: 内联声明 providerId → provider(直译)`),a++)}for(let[u,d]of Object.entries(p.instances??{})){if(typeof d.provider=="string"&&d.provider){let f=c(`services.${l}.instances.${u}.provider`,d.provider);f&&(d.provider=f.provider,d.implementation=f.implementation)}d.enabled===!0&&delete d.enabled}}console.log(`provider migrate:${a} 项迁移(反查表 ${s.size} 条)`);for(let l of i)console.log(l);if(o.length>0){console.warn("⚠️ 未命中反查表(人工处理,保留原值):");for(let l of o)console.warn(` ${l}`);process.exitCode=1}e.write?(await nt(t).writeIntegrationsConfig(n),console.log(`✅ 已写回 ${je.relative(process.cwd(),r)||r}`)):console.log("(dry-run:加 --write 落盘)")}import{spawn as Fc}from"child_process";import{existsSync as I,mkdirSync as Rr,readFileSync as X,realpathSync as ae,readdirSync as _c,rmSync as Nc,symlinkSync as Vc,unlinkSync as $o,writeFileSync as Nt}from"fs";import{createHash as Jc}from"crypto";import x from"path";import{fileURLToPath as zc}from"url";var Pe=".tbox-dev.local",vo="templates/template-agent-mall",Uc=["apps","server"],Bc=8e3;function Wc(e){let t=x.join(e,".real-env","config");return I(t)?_c(t).filter(r=>I(x.join(t,r,"integrations.json"))).sort():[]}var wo="'../../.tbox-dev.local/vite-override.mjs'",Hc="TBOX_CONFIG_DIR";function Kc(){if(process.env.NODE_ENV==="test"&&process.env.TBOX_DEV_REPO_ROOT)return ae(process.env.TBOX_DEV_REPO_ROOT);let e=x.dirname(zc(import.meta.url));for(let t=0;t<10;t++){if(I(x.join(e,"pnpm-workspace.yaml")))return e;let r=x.dirname(e);if(r===e)break;e=r}throw new Error("未能定位仓库根(缺少 pnpm-workspace.yaml)——请在仓库内执行 tbox-app dev")}function Gc(e){let t=x.join(e,"package.json");if(!I(t))throw new Error(`目录缺 package.json:${e}`);try{let r=JSON.parse(X(t,"utf8"));if(typeof r.name!="string"||!r.name)throw new Error("name 缺失");return{name:r.name,version:String(r.version??"0.0.0")}}catch(r){throw new Error(`package.json 解析失败(${e}):${r.message}`)}}function qc(e){let t=x.join(e,"tbox.module.json");if(!I(t))throw new Error(`目录缺 tbox.module.json:${e}(是否传了非模块目录?)`);let r=Ee(JSON.parse(X(t,"utf8")));if(!r.ok)throw new Error(`tbox.module.json 校验失败(${e}):
99
102
  ${r.errors.join(`
100
- `)}`);return r.value}function yo(e,t,r){let n=x.join(e,"src",t,"index.ts");if(!I(n))return!1;try{return new RegExp(`export\\s+const\\s+${r}\\b`).test(X(n,"utf8"))}catch{return!1}}function Wc(e){let t=x.join(e,"apps","client","vite.config.ts"),r=x.join(e,"apps","server","src","index.ts");if(!I(t))throw new Error(`模板缺 apps/client/vite.config.ts:${e}`);if(!I(r))throw new Error(`模板缺 apps/server/src/index.ts:${e}`);if(!X(t,"utf8").includes(go))throw new Error(`模板 vite.config.ts 缺 dev 能力探测标记("${go}")——模板过旧,请升级模板后重试`);let n=x.join(e,"apps","server","src","app.ts"),s=[X(r,"utf8"),...I(n)?[X(n,"utf8")]:[]].join(`
101
- `);if((s.includes("registerAppConfig")||s.includes("loadChatConfig"))&&!s.includes(zc))throw new Error("模板 server 装配源(apps/server/src/index.ts|app.ts)缺 TBOX_CONFIG_DIR 锚点——模板过旧,请升级模板后重试");if(!I(x.join(e,"apps","server","src","modules.ts")))throw new Error(`模板缺 apps/server/src/modules.ts 装配文件:${e}`);if(!I(x.join(e,"apps","client","src","modules.ts")))throw new Error(`模板缺 apps/client/src/modules.ts 装配文件:${e}`)}function Kc(e){if((e==="wanda"||e==="joycity")&&!process.env.TBOX_API_KEY)throw new Error(`选择真实档 --real-env ${e} 但环境缺 TBOX_API_KEY —— 请先 source .real-env/env.sh 再运行`)}function ko(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch{return!1}}var Gc=new Set(["contracts-mall"]);function qc(e,t){return{id:e,pkg:`@tbox.cn/app-${e}`,version:"",dir:t,skeleton:!0,descriptor:{schemaVersion:1,name:e,version:"0.0.0",kind:"business",risk:{level:"low",writeBoundary:"source"},distribution:{defaultMode:"codegen"},contributes:{handlers:[],tools:[],cards:[],routes:[],pages:[],tabs:[],providers:{slots:[]},services:[],resources:[]},dependencies:{modules:[]},env:[]}}}function Xc(e,t,r){let n=new Map,s=[],i=c=>{let l=Bc(c),p=Hc(c);if(n.has(p.name))return n.get(p.name);let u={id:p.name,pkg:l.name,version:l.version,dir:c,descriptor:p};return n.set(p.name,u),u},o=(c,l,p)=>{if(n.has(l))return n.get(l);if(Gc.has(l)){let d=I(x.join(r,"packages",l))?ae(x.join(r,"packages",l)):x.join(t,"modules",l);if(!I(d)){if(!p)return null;throw new Error(`依赖契约包 "${l}" 真源缺席(模板 packages/ 与 modules/ 均无该目录)`)}let f=qc(l,d);return n.set(l,f),f}let u=x.join(t,"modules",l);if(!I(u)){if(!p)return null;throw new Error(`依赖模块 <${c.id}> 声明依赖 "${l}",但仓库无 <repoRoot>/modules/${l}——请确认目录名或先 clone 对应模块`)}return i(ae(u))},a=c=>{if(s.includes(c.id))throw new Error(`模块依赖环:${[...s.slice(s.indexOf(c.id)),c.id].join(" → ")}`);s=[...s,c.id];for(let l of c.descriptor.dependencies.modules)a(o(c,l.id,l.required)??c);s=s.slice(0,-1)};for(let c of e){if(!I(c))throw new Error(`--module 目录不存在:${c}(相对路径按仓库根解析)`);a(i(ae(c)))}return[...n.values()]}function Yc(e){return{id:e.id,pkg:e.pkg,mode:"local",hasServerEntry:yo(e.dir,"server","serverModule"),hasClientEntry:yo(e.dir,"client","clientModule"),hasCards:e.descriptor.contributes.cards.length>0}}function Zc(e,t,r){let n=t.map(Yc),s=[],i=[["server-modules",x.join(e,"apps","server","src","modules.ts"),"modules.server.ts"],["client-modules",x.join(e,"apps","client","src","modules.ts"),"modules.client.ts"]];for(let[o,a,c]of i){let l=X(a,"utf8"),p=l;try{let u=jt(l,o,n);p=u.content,s.push(...u.warnings)}catch(u){s.push(`[${o}] 锚点变换异常,原文兜底:${u.message}`)}Ft(x.join(r,c),p,"utf8")}return s}function Qc(e,t,r,n){let s={},i=(o,a)=>{s[o]=x.relative(t,a).split(x.sep).join("/")};for(let o of r)o.skeleton||(i(o.pkg,o.dir),i(`@app/${o.id}`,o.dir));i("@tbox.cn/app-sdk",x.join(e,"packages","app-sdk")),i("@tbox.cn/app-contracts",x.join(e,"packages","contracts"));for(let[o,a]of Object.entries(s))if(!I(x.resolve(t,a)))throw new Error(`redirect 目标缺失:${o} → ${a}`);return s}function ho(e,t,r){let n=[],s=0;for(let[i,o]of Object.entries(r)){let a=ae(x.resolve(x.join(e,Pe),o)),c=i.split("/"),l=x.join(e,"node_modules",c[0]),p=x.join(l,c[1]);if(!(()=>{if(!I(p))return!0;let d=ae(p);return d===a?!1:d.startsWith(x.join(t,"modules")+x.sep)||x.join(t,"modules")===d})()){s++;continue}if(I(p)){let d=ae(p);if(!d.startsWith(x.join(t,"modules")))throw new Error(`refuse 覆盖非 dev 管理的既有链接:${p} → ${d}(疑为 workspace/依赖原生链接;请人工确认)`)}$r(l,{recursive:!0}),Lc(x.relative(l,a),p),n.push(i)}return{planted:n,skipped:s}}function el(e){let t=JSON.parse(X(e,"utf8")),r=new Set;typeof t.provider=="string"&&t.provider&&r.add(t.provider);for(let n of Object.values(t.domains??{}))typeof n?.provider=="string"&&n.provider&&r.add(n.provider);for(let n of Object.values(t.services??{})){let s=typeof n.provider=="string"?n.provider:n.provider?.provider;typeof s=="string"&&s&&r.add(s)}return r}function tl(e,t,r,n,s=[]){if(n){for(let a of["packages/app-sdk","packages/contracts"])if(!I(x.join(e,a)))throw new Error(`--link-sdk 要求平台真源在场:<repoRoot>/${a}`)}let i={},o;for(let a of s){let c=x.isAbsolute(a)?a:x.resolve(e,a);if(!I(c))throw new Error(`独立配置档目录不存在:${c}(--config-dir 须为存在的目录)`);o=c}if(r){let a=r.includes("-")?r.slice(0,r.indexOf("-")):r,c=x.join(e,".real-env","config",a);if(!I(c))throw new Error(`档位目录不存在:${c}(可用:${Jc(e).join("/")})`);o||(o=c)}if(o){let a=x.join(o,"integrations.json");if(I(a)){let c=el(a),l=new Set;for(let u of t)for(let d of u.descriptor.contributes.providers.slots)l.add(d.provider);let p=[...c].filter(u=>!l.has(u));if(p.length>0)throw new Error(`一致性校验失败:provider ${p.join(", ")} 被 ${x.relative(e,o)||o} 档 integrations.json 引用但未随 dev 挂载——请追加 --module modules/provider-… 或更换 --config-dir / --real-env 档位`);i.TBOX_INTEGRATIONS_FILE=a}i.TBOX_CONFIG_DIR=o}return i}function rl(e,t,r,n,s){let i=JSON.stringify({templateDir:e,tier:s.tier??null,linkSdk:!!s.linkSdk,port:s.port??null,redirects:Object.fromEntries(Object.entries(t).sort(([o],[a])=>o<a?-1:1)),configs:Object.fromEntries(Object.entries(r).sort(([o],[a])=>o<a?-1:1)),modules:n.map(o=>`${o.id}@${o.version}`).sort()});return Fc("sha256").update(i).digest("hex").slice(0,16)}var nl=`// tbox-app dev 生成态构件(勿手改;regenerated by 'tbox-app dev')
103
+ `)}`);return r.value}function bo(e,t,r){let n=x.join(e,"src",t,"index.ts");if(!I(n))return!1;try{return new RegExp(`export\\s+const\\s+${r}\\b`).test(X(n,"utf8"))}catch{return!1}}function Xc(e){let t=x.join(e,"apps","client","vite.config.ts"),r=x.join(e,"apps","server","src","index.ts");if(!I(t))throw new Error(`模板缺 apps/client/vite.config.ts:${e}`);if(!I(r))throw new Error(`模板缺 apps/server/src/index.ts:${e}`);if(!X(t,"utf8").includes(wo))throw new Error(`模板 vite.config.ts 缺 dev 能力探测标记("${wo}")——模板过旧,请升级模板后重试`);let n=x.join(e,"apps","server","src","app.ts"),s=[X(r,"utf8"),...I(n)?[X(n,"utf8")]:[]].join(`
104
+ `);if((s.includes("registerAppConfig")||s.includes("loadChatConfig"))&&!s.includes(Hc))throw new Error("模板 server 装配源(apps/server/src/index.ts|app.ts)缺 TBOX_CONFIG_DIR 锚点——模板过旧,请升级模板后重试");if(!I(x.join(e,"apps","server","src","modules.ts")))throw new Error(`模板缺 apps/server/src/modules.ts 装配文件:${e}`);if(!I(x.join(e,"apps","client","src","modules.ts")))throw new Error(`模板缺 apps/client/src/modules.ts 装配文件:${e}`)}function Yc(e){if((e==="wanda"||e==="joycity")&&!process.env.TBOX_API_KEY)throw new Error(`选择真实档 --real-env ${e} 但环境缺 TBOX_API_KEY —— 请先 source .real-env/env.sh 再运行`)}function jo(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch{return!1}}var Zc=new Set(["contracts-mall"]);function Qc(e,t){return{id:e,pkg:`@tbox.cn/app-${e}`,version:"",dir:t,skeleton:!0,descriptor:{schemaVersion:1,name:e,version:"0.0.0",kind:"business",risk:{level:"low",writeBoundary:"source"},distribution:{defaultMode:"codegen"},contributes:{handlers:[],tools:[],cards:[],routes:[],pages:[],tabs:[],providers:{slots:[]},services:[],resources:[]},dependencies:{modules:[]},env:[]}}}function el(e,t,r){let n=new Map,s=[],i=c=>{let l=Gc(c),p=qc(c);if(n.has(p.name))return n.get(p.name);let u={id:p.name,pkg:l.name,version:l.version,dir:c,descriptor:p};return n.set(p.name,u),u},o=(c,l,p)=>{if(n.has(l))return n.get(l);if(Zc.has(l)){let d=I(x.join(r,"packages",l))?ae(x.join(r,"packages",l)):x.join(t,"modules",l);if(!I(d)){if(!p)return null;throw new Error(`依赖契约包 "${l}" 真源缺席(模板 packages/ 与 modules/ 均无该目录)`)}let f=Qc(l,d);return n.set(l,f),f}let u=x.join(t,"modules",l);if(!I(u)){if(!p)return null;throw new Error(`依赖模块 <${c.id}> 声明依赖 "${l}",但仓库无 <repoRoot>/modules/${l}——请确认目录名或先 clone 对应模块`)}return i(ae(u))},a=c=>{if(s.includes(c.id))throw new Error(`模块依赖环:${[...s.slice(s.indexOf(c.id)),c.id].join(" → ")}`);s=[...s,c.id];for(let l of c.descriptor.dependencies.modules)a(o(c,l.id,l.required)??c);s=s.slice(0,-1)};for(let c of e){if(!I(c))throw new Error(`--module 目录不存在:${c}(相对路径按仓库根解析)`);a(i(ae(c)))}return[...n.values()]}function tl(e){return{id:e.id,pkg:e.pkg,mode:"local",hasServerEntry:bo(e.dir,"server","serverModule"),hasClientEntry:bo(e.dir,"client","clientModule"),hasCards:e.descriptor.contributes.cards.length>0}}function rl(e,t,r){let n=t.map(tl),s=[],i=[["server-modules",x.join(e,"apps","server","src","modules.ts"),"modules.server.ts"],["client-modules",x.join(e,"apps","client","src","modules.ts"),"modules.client.ts"]];for(let[o,a,c]of i){let l=X(a,"utf8"),p=l;try{let u=Rt(l,o,n);p=u.content,s.push(...u.warnings)}catch(u){s.push(`[${o}] 锚点变换异常,原文兜底:${u.message}`)}Nt(x.join(r,c),p,"utf8")}return s}function nl(e,t,r,n){let s={},i=(o,a)=>{s[o]=x.relative(t,a).split(x.sep).join("/")};for(let o of r)o.skeleton||(i(o.pkg,o.dir),i(`@app/${o.id}`,o.dir));i("@tbox.cn/app-sdk",x.join(e,"packages","app-sdk")),i("@tbox.cn/app-contracts",x.join(e,"packages","contracts"));for(let[o,a]of Object.entries(s))if(!I(x.resolve(t,a)))throw new Error(`redirect 目标缺失:${o} → ${a}`);return s}function ko(e,t,r){let n=[],s=0;for(let[i,o]of Object.entries(r)){let a=ae(x.resolve(x.join(e,Pe),o)),c=i.split("/"),l=x.join(e,"node_modules",c[0]),p=x.join(l,c[1]);if(!(()=>{if(!I(p))return!0;let d=ae(p);return d===a?!1:d.startsWith(x.join(t,"modules")+x.sep)||x.join(t,"modules")===d})()){s++;continue}if(I(p)){let d=ae(p);if(!d.startsWith(x.join(t,"modules")))throw new Error(`refuse 覆盖非 dev 管理的既有链接:${p} → ${d}(疑为 workspace/依赖原生链接;请人工确认)`)}Rr(l,{recursive:!0}),Vc(x.relative(l,a),p),n.push(i)}return{planted:n,skipped:s}}function sl(e){let t=JSON.parse(X(e,"utf8")),r=new Set;typeof t.provider=="string"&&t.provider&&r.add(t.provider);for(let n of Object.values(t.domains??{}))typeof n?.provider=="string"&&n.provider&&r.add(n.provider);for(let n of Object.values(t.services??{})){let s=typeof n.provider=="string"?n.provider:n.provider?.provider;typeof s=="string"&&s&&r.add(s)}return r}function ol(e,t,r,n,s=[]){if(n){for(let a of["packages/app-sdk","packages/contracts"])if(!I(x.join(e,a)))throw new Error(`--link-sdk 要求平台真源在场:<repoRoot>/${a}`)}let i={},o;for(let a of s){let c=x.isAbsolute(a)?a:x.resolve(e,a);if(!I(c))throw new Error(`独立配置档目录不存在:${c}(--config-dir 须为存在的目录)`);o=c}if(r){let a=r.includes("-")?r.slice(0,r.indexOf("-")):r,c=x.join(e,".real-env","config",a);if(!I(c))throw new Error(`档位目录不存在:${c}(可用:${Wc(e).join("/")})`);o||(o=c)}if(o){let a=x.join(o,"integrations.json");if(I(a)){let c=sl(a),l=new Set;for(let u of t)for(let d of u.descriptor.contributes.providers.slots)l.add(d.provider);let p=[...c].filter(u=>!l.has(u));if(p.length>0)throw new Error(`一致性校验失败:provider ${p.join(", ")} 被 ${x.relative(e,o)||o} 档 integrations.json 引用但未随 dev 挂载——请追加 --module modules/provider-… 或更换 --config-dir / --real-env 档位`);i.TBOX_INTEGRATIONS_FILE=a}i.TBOX_CONFIG_DIR=o}return i}function il(e,t,r,n,s){let i=JSON.stringify({templateDir:e,tier:s.tier??null,linkSdk:!!s.linkSdk,port:s.port??null,redirects:Object.fromEntries(Object.entries(t).sort(([o],[a])=>o<a?-1:1)),configs:Object.fromEntries(Object.entries(r).sort(([o],[a])=>o<a?-1:1)),modules:n.map(o=>`${o.id}@${o.version}`).sort()});return Jc("sha256").update(i).digest("hex").slice(0,16)}var al=`// tbox-app dev 生成态构件(勿手改;regenerated by 'tbox-app dev')
102
105
  import { register } from 'node:module';
103
106
  register('./hook-core.mjs', import.meta.url);
104
- `,sl=`// tbox-app dev 生成态构件(勿手改;regenerated by 'tbox-app dev')。
107
+ `,cl=`// tbox-app dev 生成态构件(勿手改;regenerated by 'tbox-app dev')。
105
108
  // resolve 钩子:① 相对 modules.js/modules.ts/modules → 物化装配 ② manifest 前缀重定向(mini exports)。
106
109
  import { existsSync, readFileSync } from 'node:fs';
107
110
  import { fileURLToPath, pathToFileURL } from 'node:url';
@@ -155,7 +158,7 @@ export async function resolve(specifier, context, nextResolve) {
155
158
  }
156
159
  return nextResolve(specifier, context);
157
160
  }
158
- `,ol=`// tbox-app dev 生成态构件(勿手改;regenerated by 'tbox-app dev')。
161
+ `,ll=`// tbox-app dev 生成态构件(勿手改;regenerated by 'tbox-app dev')。
159
162
  // Vite 插件:client 装配改指物化构件 + manifest 前缀重定向 + fs 门面扩容。
160
163
  import { existsSync, readFileSync } from 'node:fs';
161
164
  import { fileURLToPath } from 'node:url';
@@ -229,23 +232,23 @@ export default function tboxDevOverride() {
229
232
  },
230
233
  };
231
234
  }
232
- `;async function xo(e){let t=Uc();if(e.prune){let m=e.template?x.resolve(t,e.template):x.resolve(t,mo);if(!I(m))throw new Error(`--template 目录不存在:${m}`);await al(ae(m),t);return}Kc(e.realEnv);let r=ae(e.template?x.resolve(t,e.template):x.resolve(t,mo));if(!I(x.join(r,".tbox","app.json")))throw new Error(`--template 目录缺 .tbox/app.json(不是应用/模板根?):${r}`);Wc(r);let n=x.join(r,Pe),s=x.join(n,"session.lock"),i=x.join(n,"dev-manifest.json"),o=(e.module??[]).map(m=>x.resolve(t,m)),a=Xc(o,t,r);if(a.length===0)throw new Error("未指定任何模块:请传 --module modules/<id>(至少一个);或使用 scripts/dev-mall-agent.sh 快速开始");let c=Qc(t,n,a,!!e.linkSdk),l=tl(t,a,e.realEnv,!!e.linkSdk,e.configDir??[]),p=rl(r,c,l,a,e),u={version:1,templateDir:r,repoRoot:t,tier:e.realEnv,linkSdk:!!e.linkSdk,redirects:c,modules:a.map(m=>({id:m.id,pkg:m.pkg,dir:x.relative(t,m.dir),kind:m.descriptor.kind})),configs:l};if(I(s)){let m=null;try{m=JSON.parse(X(s,"utf8"))}catch{}if(m&&ko(m.pid)&&m.pid!==process.pid){if(m.hash===p){console.log(`↩︎ 检测到同集合 dev 会话(pid=${m.pid})——attach 模式,直接拉起进程`),$r(n,{recursive:!0});let h=ho(r,t,c);console.log(`🔗 链接断言:planted=${h.planted.length} skipped=${h.skipped}`),await vo(r,l,e.port,s,c);return}throw new Error(`已有不同集合的 dev 会话运行中(pid=${m.pid},集合 ${m.hash} ≠ 本次 ${p})——并发会话会互相覆盖 .tbox-dev.local/ 构件。请先停掉对方或运行 'tbox-app dev --prune'`)}console.log("🧹 吸收残留死锁(pid 已不存在)")}$r(n,{recursive:!0});let d=Zc(r,a,n);for(let m of d)console.warn(`⚠️ ${m}`);let f=ho(r,t,c);console.log(`🔗 链接种植:planted=${f.planted.length} skipped=${f.skipped}`),Re(x.join(n,"package.json"),JSON.stringify({type:"module"},null,2)+`
233
- `),Ft(x.join(n,"boot.mjs"),nl,"utf8"),Ft(x.join(n,"hook-core.mjs"),sl,"utf8"),Ft(x.join(n,"vite-override.mjs"),ol,"utf8"),Re(i,JSON.stringify(u,null,2)+`
235
+ `;async function Eo(e){let t=Kc();if(e.prune){let m=e.template?x.resolve(t,e.template):x.resolve(t,vo);if(!I(m))throw new Error(`--template 目录不存在:${m}`);await ul(ae(m),t);return}Yc(e.realEnv);let r=ae(e.template?x.resolve(t,e.template):x.resolve(t,vo));if(!I(x.join(r,".tbox","app.json")))throw new Error(`--template 目录缺 .tbox/app.json(不是应用/模板根?):${r}`);Xc(r);let n=x.join(r,Pe),s=x.join(n,"session.lock"),i=x.join(n,"dev-manifest.json"),o=(e.module??[]).map(m=>x.resolve(t,m)),a=el(o,t,r);if(a.length===0)throw new Error("未指定任何模块:请传 --module modules/<id>(至少一个);或使用 scripts/dev-mall-agent.sh 快速开始");let c=nl(t,n,a,!!e.linkSdk),l=ol(t,a,e.realEnv,!!e.linkSdk,e.configDir??[]),p=il(r,c,l,a,e),u={version:1,templateDir:r,repoRoot:t,tier:e.realEnv,linkSdk:!!e.linkSdk,redirects:c,modules:a.map(m=>({id:m.id,pkg:m.pkg,dir:x.relative(t,m.dir),kind:m.descriptor.kind})),configs:l};if(I(s)){let m=null;try{m=JSON.parse(X(s,"utf8"))}catch{}if(m&&jo(m.pid)&&m.pid!==process.pid){if(m.hash===p){console.log(`↩︎ 检测到同集合 dev 会话(pid=${m.pid})——attach 模式,直接拉起进程`),Rr(n,{recursive:!0});let h=ko(r,t,c);console.log(`🔗 链接断言:planted=${h.planted.length} skipped=${h.skipped}`),await xo(r,l,e.port,s,c);return}throw new Error(`已有不同集合的 dev 会话运行中(pid=${m.pid},集合 ${m.hash} ≠ 本次 ${p})——并发会话会互相覆盖 .tbox-dev.local/ 构件。请先停掉对方或运行 'tbox-app dev --prune'`)}console.log("🧹 吸收残留死锁(pid 已不存在)")}Rr(n,{recursive:!0});let d=rl(r,a,n);for(let m of d)console.warn(`⚠️ ${m}`);let f=ko(r,t,c);console.log(`🔗 链接种植:planted=${f.planted.length} skipped=${f.skipped}`),Re(x.join(n,"package.json"),JSON.stringify({type:"module"},null,2)+`
236
+ `),Nt(x.join(n,"boot.mjs"),al,"utf8"),Nt(x.join(n,"hook-core.mjs"),cl,"utf8"),Nt(x.join(n,"vite-override.mjs"),ll,"utf8"),Re(i,JSON.stringify(u,null,2)+`
234
237
  `),Re(s,JSON.stringify({pid:process.pid,cmd:"tbox-app dev",hash:p,ts:new Date().toISOString()},null,2)+`
235
- `);let g=e.port??Vc;console.log("─".repeat(64)),console.log(`📦 dev 模块集:${a.map(m=>m.id).join(", ")}`),Object.keys(l).length>0?(console.log(`🗂 integrations=${l.TBOX_INTEGRATIONS_FILE??"— (absent:登录将落内置换码器,缺 ALIPAY_* 凭证即 503)"}`),console.log(`🗂 config-dir=${l.TBOX_CONFIG_DIR??"—"}`)):console.log("🗂 configs:无注入(未指定 --real-env / --config-dir;裸跑形态)"),console.log(`🚀 dev ready → http://127.0.0.1:${g}`),console.log("ℹ️ dev 链接形态 ≠ codegen 发布态(L2≠L3):发布判据仍以 verify-cli 为准"),console.log("─".repeat(64)),await vo(r,l,e.port,s,c)}async function vo(e,t,r,n,s={}){let i=x.join(e,...Nc),a=JSON.parse(X(x.join(i,"package.json"),"utf8")).scripts?.dev??"",c=a.split(/\s+/);if(c[0]!=="tsx"||c[1]!=="watch"||c.length<3)throw new Error(`apps/server scripts.dev 形态不受支持(需 "tsx watch … <entry>"):"${a}"——请升级模板`);let l=c[c.length-1],p=x.join(e,Pe,"boot.mjs"),u=[...new Set(Object.values(s).map(h=>x.resolve(x.join(e,Pe),h)))],d=["--watch-path=./src",`--watch-path=${x.join(e,Pe)}`,...u.map(h=>`--watch-path=${h}`)],f={...process.env,...t,...r!==void 0?{PORT:String(r)}:{}},g=Ac("node",[...d,"--watch","--import","tsx","--import",p,l],{cwd:i,env:f,stdio:"inherit",detached:!0});_t=g.pid,il();let m=await new Promise(h=>{let v=!1,S=$=>{v||(v=!0,_t=void 0,h($))};g.on("exit",($,R)=>S($??(R?130:1))),g.on("error",$=>{console.error("❌ dev 子进程启动失败:",$),S(1)})});try{bo(n)}catch{}process.exitCode=m??1}var _t,wo=!1;function il(){if(wo)return;wo=!0;let e=t=>{if(_t)try{process.kill(-_t,t)}catch{}};process.on("SIGINT",()=>e("SIGINT")),process.on("SIGTERM",()=>e("SIGTERM"))}async function al(e,t){let r=x.join(e,Pe),n=x.join(r,"dev-manifest.json"),s=x.join(r,"session.lock");if(!I(r)){console.log("✨ 构件区不存在,无需清理");return}if(I(s))try{let o=JSON.parse(X(s,"utf8"));if(o.pid!==process.pid&&ko(o.pid))throw new Error(`dev 会话仍在运行(pid=${o.pid})——请先 Ctrl+C 停止再 --prune`)}catch(o){if(o.message.startsWith("dev 会话"))throw o}let i=0;if(I(n))try{let o=JSON.parse(X(n,"utf8"));for(let a of Object.keys(o.redirects??{})){let c=a.split("/"),l=x.join(e,"node_modules",c[0],c[1]);if(!I(l))continue;let p=ae(l);[x.join(t,"modules"),x.join(t,"packages")].some(d=>p===d||p.startsWith(d+x.sep))&&(bo(l),i++)}}catch{}Pc(r,{recursive:!0,force:!0}),console.log(`✨ prune 完成:构件区已清、种植链接回收 ${i} 条(模板:${x.relative(t,e)})`)}import{readFileSync as cl}from"fs";var Nt=[{type:"agent",description:"通用 AI Agent 应用(Base 模板)",templatePackage:"@tbox.cn/app-template-agent",documentFile:"agent.md"},{type:"agent-mall",description:"商圈 AI Agent 应用(Mall 模板)",templatePackage:"@tbox.cn/app-template-agent-mall",documentFile:"agent-mall.md"},{type:"agent-support",description:"客服支持 AI Agent 应用(Support 模板)",templatePackage:"@tbox.cn/app-template-agent-support",documentFile:"agent-support.md"}];function ll(e){return cl(new URL(`../starter/${e}`,import.meta.url),"utf8")}function pl(e){let t=Nt.map(({type:r,description:n,templatePackage:s})=>({type:r,description:n,templatePackage:s}));return e?JSON.stringify({starters:t},null,2)+`
236
- `:["可用 starter 类型:",...t.map(r=>` ${r.type.padEnd(11)} ${r.description}(${r.templatePackage})`),"",`查询文档: tbox-app starter --type <${Nt.map(r=>r.type).join("|")}>`].join(`
238
+ `);let g=e.port??Bc;console.log("─".repeat(64)),console.log(`📦 dev 模块集:${a.map(m=>m.id).join(", ")}`),Object.keys(l).length>0?(console.log(`🗂 integrations=${l.TBOX_INTEGRATIONS_FILE??"— (absent:登录将落内置换码器,缺 ALIPAY_* 凭证即 503)"}`),console.log(`🗂 config-dir=${l.TBOX_CONFIG_DIR??"—"}`)):console.log("🗂 configs:无注入(未指定 --real-env / --config-dir;裸跑形态)"),console.log(`🚀 dev ready → http://127.0.0.1:${g}`),console.log("ℹ️ dev 链接形态 ≠ codegen 发布态(L2≠L3):发布判据仍以 verify-cli 为准"),console.log("─".repeat(64)),await xo(r,l,e.port,s,c)}async function xo(e,t,r,n,s={}){let i=x.join(e,...Uc),a=JSON.parse(X(x.join(i,"package.json"),"utf8")).scripts?.dev??"",c=a.split(/\s+/);if(c[0]!=="tsx"||c[1]!=="watch"||c.length<3)throw new Error(`apps/server scripts.dev 形态不受支持(需 "tsx watch … <entry>"):"${a}"——请升级模板`);let l=c[c.length-1],p=x.join(e,Pe,"boot.mjs"),u=[...new Set(Object.values(s).map(h=>x.resolve(x.join(e,Pe),h)))],d=["--watch-path=./src",`--watch-path=${x.join(e,Pe)}`,...u.map(h=>`--watch-path=${h}`)],f={...process.env,...t,...r!==void 0?{PORT:String(r)}:{}},g=Fc("node",[...d,"--watch","--import","tsx","--import",p,l],{cwd:i,env:f,stdio:"inherit",detached:!0});Vt=g.pid,pl();let m=await new Promise(h=>{let v=!1,S=$=>{v||(v=!0,Vt=void 0,h($))};g.on("exit",($,R)=>S($??(R?130:1))),g.on("error",$=>{console.error("❌ dev 子进程启动失败:",$),S(1)})});try{$o(n)}catch{}process.exitCode=m??1}var Vt,So=!1;function pl(){if(So)return;So=!0;let e=t=>{if(Vt)try{process.kill(-Vt,t)}catch{}};process.on("SIGINT",()=>e("SIGINT")),process.on("SIGTERM",()=>e("SIGTERM"))}async function ul(e,t){let r=x.join(e,Pe),n=x.join(r,"dev-manifest.json"),s=x.join(r,"session.lock");if(!I(r)){console.log("✨ 构件区不存在,无需清理");return}if(I(s))try{let o=JSON.parse(X(s,"utf8"));if(o.pid!==process.pid&&jo(o.pid))throw new Error(`dev 会话仍在运行(pid=${o.pid})——请先 Ctrl+C 停止再 --prune`)}catch(o){if(o.message.startsWith("dev 会话"))throw o}let i=0;if(I(n))try{let o=JSON.parse(X(n,"utf8"));for(let a of Object.keys(o.redirects??{})){let c=a.split("/"),l=x.join(e,"node_modules",c[0],c[1]);if(!I(l))continue;let p=ae(l);[x.join(t,"modules"),x.join(t,"packages")].some(d=>p===d||p.startsWith(d+x.sep))&&($o(l),i++)}}catch{}Nc(r,{recursive:!0,force:!0}),console.log(`✨ prune 完成:构件区已清、种植链接回收 ${i} 条(模板:${x.relative(t,e)})`)}import{readFileSync as dl}from"fs";var Jt=[{type:"agent",description:"通用 AI Agent 应用(Base 模板)",templatePackage:"@tbox.cn/app-template-agent",documentFile:"agent.md"},{type:"agent-mall",description:"商圈 AI Agent 应用(Mall 模板)",templatePackage:"@tbox.cn/app-template-agent-mall",documentFile:"agent-mall.md"},{type:"agent-support",description:"客服支持 AI Agent 应用(Support 模板)",templatePackage:"@tbox.cn/app-template-agent-support",documentFile:"agent-support.md"}];function fl(e){return dl(new URL(`../starter/${e}`,import.meta.url),"utf8")}function ml(e){let t=Jt.map(({type:r,description:n,templatePackage:s})=>({type:r,description:n,templatePackage:s}));return e?JSON.stringify({starters:t},null,2)+`
239
+ `:["可用 starter 类型:",...t.map(r=>` ${r.type.padEnd(11)} ${r.description}(${r.templatePackage})`),"",`查询文档: tbox-app starter --type <${Jt.map(r=>r.type).join("|")}>`].join(`
237
240
  `)+`
238
- `}function So(e){if(e.type&&e.list)throw new Error("--type 与 --list 互斥");if(e.json&&!e.list)throw new Error("--json 仅配合 --list 使用");if(!e.type||e.list){process.stdout.write(pl(!!e.json));return}let t=Nt.find(r=>r.type===e.type);if(!t)throw new Error(`未知 starter 类型: ${e.type}(可用:${Nt.map(r=>r.type).join("、")};使用 --list 查看)`);process.stdout.write(ll(t.documentFile))}import{createHash as fl}from"crypto";import{readdir as ml,readFile as gl,stat as yl}from"fs/promises";import{join as Le,relative as hl,basename as Do}from"path";import{parse as vl}from"yaml";import{z as et}from"zod";import{z as y}from"zod";var jr=y.object({version:y.literal(1),name:y.string().min(1),description:y.string().default(""),defaultTurnTimeoutMs:y.number().int().min(5e3).default(15e4),driver:y.enum(["agui","support"]).optional()}).strict(),Er=y.object({version:y.literal(1),description:y.string().default(""),standards:y.array(y.string().min(1)).min(1)}).strict(),$o=y.union([y.string().min(1),y.array(y.string().min(1)).min(1)]),Eo=y.union([$o,y.object({any_of:y.array($o).min(1)}).strict()]),ul=Eo;function jo(e){let t=r=>r==="none"||r==="direct-out"?[]:[r];return typeof e=="string"?t(e):Array.isArray(e)?e:e.any_of.flatMap(r=>typeof r=="string"?t(r):r)}var dl=y.object({expect:Eo,optional:y.array(y.string().min(1)).default([]),forbid:y.array(y.string().min(1)).default([]),pre:y.array(y.string().min(1)).default([]),mode:y.enum(["strict","soft"]).default("strict")}).strict().refine(e=>e.expect!=="direct-out"||e.pre.length===0,{message:"direct-out 与 pre 互斥(direct-out 断言零模型调用,pre 断言走 preTool 轨)"}).refine(e=>e.optional.every(t=>!jo(e.expect).includes(t)),{message:"optional 与 expect 重叠(optional 豁免会使 expect 永不满足)"}).refine(e=>e.forbid.every(t=>!jo(e.expect).includes(t)),{message:"forbid 与 expect 重叠(契约自相矛盾,恒 fail)"}),Rr=y.object({id:y.string().regex(/^[A-Za-z0-9][A-Za-z0-9-]{2,50}$/),priority:y.enum(["P0","P1","P2"]),tags:y.array(y.string().min(1)).default([]),skip:y.string().min(1).optional(),turns:y.array(y.object({text:y.string().trim().min(1,"不能为空白"),newSession:y.boolean().default(!1)}).strict()).min(1),tools:dl,cards:y.object({expect:ul}).strict().optional(),assertions:y.array(y.string().trim().min(1,"不能为空白")).min(1),judge_hints:y.array(y.string().min(1)).default([])}).strict(),Yg=y.object({suite:jr,rubric:Er,cases:y.array(Rr).min(1)}).strict(),Qe=y.object({version:y.literal(1),runId:y.string(),startedAt:y.string(),finishedAt:y.string(),dataset:y.object({name:y.string(),hash:y.string(),caseCount:y.number().int()}),rubricHash:y.string(),judgeModel:y.string().nullable(),instance:y.object({baseUrl:y.string(),pid:y.number().nullable(),startedAt:y.string().nullable(),journalRoot:y.string().nullable(),degraded:y.boolean()}),devUserPrefix:y.string(),dimensions:y.record(y.string(),y.object({pass:y.number(),fail:y.number(),na:y.number()})),cases:y.array(y.object({id:y.string(),status:y.enum(["pass","fail","inconclusive","skipped"]),skipReason:y.string().optional(),dims:y.record(y.string(),y.enum(["pass","fail","warning","na"])),failures:y.array(y.string()).default([])})),slices:y.record(y.string(),y.record(y.string(),y.object({pass:y.number(),total:y.number()}))),ops:y.object({durationMs:y.number(),turnCount:y.number(),infraErrors:y.number(),aborted:y.boolean(),llmTokens:y.number().nullable(),judgeFailures:y.number().int().default(0)})}).strict(),Ro=y.object({version:y.literal(1),pid:y.number().int(),port:y.number().int(),baseUrl:y.string(),journalRoot:y.string(),startedAt:y.string(),detached:y.boolean()}).strict();var wl=et.object({tools:et.array(et.string().min(1)).min(1),cards:et.array(et.string().min(1)).min(1)}).strict(),bl=/^[a-zA-Z][a-zA-Z0-9_-]*$/,kl=new Set(["none","direct-out"]);function Dr(e){return typeof e=="string"?[e]:Array.isArray(e)?e:e.any_of.flatMap(Dr)}function xl(e){return[...Dr(e.expect),...e.optional,...e.forbid,...e.pre]}function To(e,t){return e<t?-1:e>t?1:0}var Sl=(e,t)=>To(e.name,t.name);function Co(e){return fl("sha256").update(e.join(`
241
+ `}function Ro(e){if(e.type&&e.list)throw new Error("--type 与 --list 互斥");if(e.json&&!e.list)throw new Error("--json 仅配合 --list 使用");if(!e.type||e.list){process.stdout.write(ml(!!e.json));return}let t=Jt.find(r=>r.type===e.type);if(!t)throw new Error(`未知 starter 类型: ${e.type}(可用:${Jt.map(r=>r.type).join("、")};使用 --list 查看)`);process.stdout.write(fl(t.documentFile))}import{createHash as hl}from"crypto";import{readdir as vl,readFile as wl,stat as bl}from"fs/promises";import{join as Le,relative as kl,basename as Io}from"path";import{parse as xl}from"yaml";import{z as et}from"zod";import{z as y}from"zod";var Dr=y.object({version:y.literal(1),name:y.string().min(1),description:y.string().default(""),defaultTurnTimeoutMs:y.number().int().min(5e3).default(15e4),driver:y.enum(["agui","support"]).optional()}).strict(),Cr=y.object({version:y.literal(1),description:y.string().default(""),standards:y.array(y.string().min(1)).min(1)}).strict(),Do=y.union([y.string().min(1),y.array(y.string().min(1)).min(1)]),To=y.union([Do,y.object({any_of:y.array(Do).min(1)}).strict()]),gl=To;function Co(e){let t=r=>r==="none"||r==="direct-out"?[]:[r];return typeof e=="string"?t(e):Array.isArray(e)?e:e.any_of.flatMap(r=>typeof r=="string"?t(r):r)}var yl=y.object({expect:To,optional:y.array(y.string().min(1)).default([]),forbid:y.array(y.string().min(1)).default([]),pre:y.array(y.string().min(1)).default([]),mode:y.enum(["strict","soft"]).default("strict")}).strict().refine(e=>e.expect!=="direct-out"||e.pre.length===0,{message:"direct-out 与 pre 互斥(direct-out 断言零模型调用,pre 断言走 preTool 轨)"}).refine(e=>e.optional.every(t=>!Co(e.expect).includes(t)),{message:"optional 与 expect 重叠(optional 豁免会使 expect 永不满足)"}).refine(e=>e.forbid.every(t=>!Co(e.expect).includes(t)),{message:"forbid 与 expect 重叠(契约自相矛盾,恒 fail)"}),Tr=y.object({id:y.string().regex(/^[A-Za-z0-9][A-Za-z0-9-]{2,50}$/),priority:y.enum(["P0","P1","P2"]),tags:y.array(y.string().min(1)).default([]),skip:y.string().min(1).optional(),turns:y.array(y.object({text:y.string().trim().min(1,"不能为空白"),newSession:y.boolean().default(!1)}).strict()).min(1),tools:yl,cards:y.object({expect:gl}).strict().optional(),assertions:y.array(y.string().trim().min(1,"不能为空白")).min(1),judge_hints:y.array(y.string().min(1)).default([])}).strict(),ty=y.object({suite:Dr,rubric:Cr,cases:y.array(Tr).min(1)}).strict(),Qe=y.object({version:y.literal(1),runId:y.string(),startedAt:y.string(),finishedAt:y.string(),dataset:y.object({name:y.string(),hash:y.string(),caseCount:y.number().int()}),rubricHash:y.string(),judgeModel:y.string().nullable(),instance:y.object({baseUrl:y.string(),pid:y.number().nullable(),startedAt:y.string().nullable(),journalRoot:y.string().nullable(),degraded:y.boolean()}),devUserPrefix:y.string(),dimensions:y.record(y.string(),y.object({pass:y.number(),fail:y.number(),na:y.number()})),cases:y.array(y.object({id:y.string(),status:y.enum(["pass","fail","inconclusive","skipped"]),skipReason:y.string().optional(),dims:y.record(y.string(),y.enum(["pass","fail","warning","na"])),failures:y.array(y.string()).default([])})),slices:y.record(y.string(),y.record(y.string(),y.object({pass:y.number(),total:y.number()}))),ops:y.object({durationMs:y.number(),turnCount:y.number(),infraErrors:y.number(),aborted:y.boolean(),llmTokens:y.number().nullable(),judgeFailures:y.number().int().default(0)})}).strict(),Mo=y.object({version:y.literal(1),pid:y.number().int(),port:y.number().int(),baseUrl:y.string(),journalRoot:y.string(),startedAt:y.string(),detached:y.boolean()}).strict();var Sl=et.object({tools:et.array(et.string().min(1)).min(1),cards:et.array(et.string().min(1)).min(1)}).strict(),$l=/^[a-zA-Z][a-zA-Z0-9_-]*$/,jl=new Set(["none","direct-out"]);function Mr(e){return typeof e=="string"?[e]:Array.isArray(e)?e:e.any_of.flatMap(Mr)}function El(e){return[...Mr(e.expect),...e.optional,...e.forbid,...e.pre]}function Oo(e,t){return e<t?-1:e>t?1:0}var Rl=(e,t)=>Oo(e.name,t.name);function Ao(e){return hl("sha256").update(e.join(`
239
242
  \0
240
- `)).digest("hex")}async function Vt(e,t,r){let n;try{n=await gl(e,"utf-8")}catch(o){throw new Error(`读取 ${r} 失败(${e}): ${o.message}`)}let s;try{s=vl(n)}catch(o){throw new Error(`${r} YAML 语法错误(${e}): ${o.message}`)}let i=t.safeParse(s);if(!i.success){let o=i.error.issues.map(a=>` - ${a.path.join(".")||"<root>"}: ${a.message}`).join(`
243
+ `)).digest("hex")}async function zt(e,t,r){let n;try{n=await wl(e,"utf-8")}catch(o){throw new Error(`读取 ${r} 失败(${e}): ${o.message}`)}let s;try{s=xl(n)}catch(o){throw new Error(`${r} YAML 语法错误(${e}): ${o.message}`)}let i=t.safeParse(s);if(!i.success){let o=i.error.issues.map(a=>` - ${a.path.join(".")||"<root>"}: ${a.message}`).join(`
241
244
  `);throw new Error(`${r} 契约校验失败(${e}):
242
- ${o}`)}return i.data}async function $l(e){let t=[],r=async n=>{let s;try{s=await ml(n,{withFileTypes:!0})}catch{return}for(let i of s.sort(Sl)){let o=Le(n,i.name);i.isDirectory()?await r(o):i.isFile()&&(i.name.endsWith(".yaml")||i.name.endsWith(".yml"))&&t.push(o)}};return await r(e),t.sort()}async function Jt(e){let t=Le(e,"suite.yaml"),r=Le(e,"rubric.yaml"),n=await Vt(t,jr,"suite.yaml"),s=await Vt(r,Er,"rubric.yaml"),i=await $l(Le(e,"cases"));if(i.length===0)throw new Error(`数据集为空:${Le(e,"cases")} 下未发现任何 .yaml 用例`);let o=[],a=[],c=new Map;for(let v of i){let S=hl(e,v);try{let $=await Vt(v,Rr,"case");Do(v).replace(/\.ya?ml$/,"")!==$.id&&a.push(` - ${S}: 文件名与用例 id 不符(文件 ${Do(v)},id ${$.id})`),o.push($),c.set($.id,S)}catch($){a.push(` - ${S}: ${$.message.split(`
243
- `).slice(1).join(";")||$.message}`)}}let l=new Map;for(let v of o)l.set(v.id,(l.get(v.id)??0)+1);let p=[...l.entries()].filter(([,v])=>v>1);if(p.length>0&&a.push(` - 用例 id 重复: ${p.map(([v,S])=>`${v}×${S}`).join(", ")}`),n.driver==="support")for(let v of o)v.turns.some(S=>S.newSession)&&a.push(` - ${c.get(v.id)??`cases/${v.id}.yaml`}: driver=support 暂不支持 newSession(support 会话绑定连接)`);let u=null,d=Le(e,"tools-manifest.yaml"),f=!1;try{f=(await yl(d)).isFile()}catch{f=!1}if(f){let v=await Vt(d,wl,"tools-manifest.yaml");u={tools:new Set(v.tools),cards:new Set(v.cards)};for(let S of o){let $=c.get(S.id)??`cases/${S.id}.yaml`;for(let R of xl(S.tools))kl.has(R)||(bl.test(R)?u.tools.has(R)||a.push(` - ${$}: 工具引用 '${R}' 不在词表(tools-manifest.yaml)——检查拼写或更新词表`):a.push(` - ${$}: 工具引用 '${R}' 非法形态(须 ^[a-zA-Z][a-zA-Z0-9_-]*$)——疑似期望文案粘连进 DSL`));if(S.cards)for(let R of Dr(S.cards.expect))u.cards.has(R)||a.push(` - ${$}: 卡片引用 '${R}' 不在词表(tools-manifest.yaml cards 节)`)}}if(a.length>0)throw new Error(`数据集校验失败(${e},${a.length} 处):
245
+ ${o}`)}return i.data}async function Dl(e){let t=[],r=async n=>{let s;try{s=await vl(n,{withFileTypes:!0})}catch{return}for(let i of s.sort(Rl)){let o=Le(n,i.name);i.isDirectory()?await r(o):i.isFile()&&(i.name.endsWith(".yaml")||i.name.endsWith(".yml"))&&t.push(o)}};return await r(e),t.sort()}async function Ut(e){let t=Le(e,"suite.yaml"),r=Le(e,"rubric.yaml"),n=await zt(t,Dr,"suite.yaml"),s=await zt(r,Cr,"rubric.yaml"),i=await Dl(Le(e,"cases"));if(i.length===0)throw new Error(`数据集为空:${Le(e,"cases")} 下未发现任何 .yaml 用例`);let o=[],a=[],c=new Map;for(let v of i){let S=kl(e,v);try{let $=await zt(v,Tr,"case");Io(v).replace(/\.ya?ml$/,"")!==$.id&&a.push(` - ${S}: 文件名与用例 id 不符(文件 ${Io(v)},id ${$.id})`),o.push($),c.set($.id,S)}catch($){a.push(` - ${S}: ${$.message.split(`
246
+ `).slice(1).join(";")||$.message}`)}}let l=new Map;for(let v of o)l.set(v.id,(l.get(v.id)??0)+1);let p=[...l.entries()].filter(([,v])=>v>1);if(p.length>0&&a.push(` - 用例 id 重复: ${p.map(([v,S])=>`${v}×${S}`).join(", ")}`),n.driver==="support")for(let v of o)v.turns.some(S=>S.newSession)&&a.push(` - ${c.get(v.id)??`cases/${v.id}.yaml`}: driver=support 暂不支持 newSession(support 会话绑定连接)`);let u=null,d=Le(e,"tools-manifest.yaml"),f=!1;try{f=(await bl(d)).isFile()}catch{f=!1}if(f){let v=await zt(d,Sl,"tools-manifest.yaml");u={tools:new Set(v.tools),cards:new Set(v.cards)};for(let S of o){let $=c.get(S.id)??`cases/${S.id}.yaml`;for(let R of El(S.tools))jl.has(R)||($l.test(R)?u.tools.has(R)||a.push(` - ${$}: 工具引用 '${R}' 不在词表(tools-manifest.yaml)——检查拼写或更新词表`):a.push(` - ${$}: 工具引用 '${R}' 非法形态(须 ^[a-zA-Z][a-zA-Z0-9_-]*$)——疑似期望文案粘连进 DSL`));if(S.cards)for(let R of Mr(S.cards.expect))u.cards.has(R)||a.push(` - ${$}: 卡片引用 '${R}' 不在词表(tools-manifest.yaml cards 节)`)}}if(a.length>0)throw new Error(`数据集校验失败(${e},${a.length} 处):
244
247
  ${a.join(`
245
- `)}`);let g=Co([JSON.stringify(s)]),m=[...o].sort((v,S)=>To(v.id,S.id)),h=Co([JSON.stringify(n),JSON.stringify(s),...m.map(v=>JSON.stringify(v))]);return{dir:e,suite:n,rubric:s,cases:o,datasetHash:h,rubricHash:g,manifest:u}}function Mo(e){let t={},r={},n={},s={},i=0,o=0;for(let a of e.cases){a.skip&&(t[a.skip]=(t[a.skip]??0)+1),r[a.priority]=(r[a.priority]??0)+1;let c=a.tags[2]??"<none>";n[c]=(n[c]??0)+1;let l=1;for(let p of a.turns)p.newSession&&(l+=1);s[String(l)]=(s[String(l)]??0)+1,a.turns.length>1&&(i+=1),a.tools.mode==="soft"&&(o+=1)}return{total:e.cases.length,evaluated:e.cases.filter(a=>!a.skip).length,skippedByReason:t,byPriority:r,byCaseType:n,sessionHistogram:s,multiTurnCases:i,softModeCases:o}}import{randomBytes as tp}from"crypto";import{mkdir as rp,readFile as si}from"fs/promises";import{join as Or}from"path";import{readdir as Io,readFile as Po}from"fs/promises";import{join as Ao}from"path";var W=class extends Error{constructor(t){super(t),this.name="InfraError"}},Oo=400,jl=1e4,El=1500,Rl=300;async function Cr(e,t,r){let n=r??fetch,s;try{s=await n(`${e}/api/auth/dev-login`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({devUser:t})})}catch(o){throw new W(`dev-login 请求失败(${e}): ${o.message}`)}if(!s.ok)throw new W(`dev-login 失败 HTTP ${s.status}(devUser=${t};prod 档会 403——检查实例启动语义)`);let i=await s.json().catch(()=>{});if(!i?.token)throw new W("dev-login 响应缺 token");return i.token}function Dl(e){if(e==null)return;let t=typeof e=="string"?e:JSON.stringify(e);return t.length>Oo?`${t.slice(0,Oo)}…`:t}function Cl(e,t){let r=e.type;if(!t.started){if(r==="RUN_FINISHED"||r==="RUN_ERROR")return;t.started=!0}let n=e.toolCallId;switch(r){case"TEXT_MESSAGE_CONTENT":t.reply+=e.delta??"";break;case"TOOL_CALL_START":{let s=e.toolCallName;s==="__tbox_pretool"?t.preTools.set(n??`pre-${t.preTools.size}`,{}):t.toolCalls.set(n??`tool-${t.toolCalls.size}`,{name:s,argsBuf:""});break}case"TOOL_CALL_ARGS":{if(n===void 0)break;let s=t.toolCalls.get(n);if(s){s.argsBuf=(s.argsBuf??"")+(e.delta??"");break}let i=t.preTools.get(n);i&&(i.argsRaw=(i.argsRaw??"")+(e.delta??""));break}case"TOOL_CALL_RESULT":{if(n===void 0)break;let s=t.toolCalls.get(n);if(s){e.isError===!0&&(s.isError=!0),s.resultSummary=Dl(e.content);break}let i=t.preTools.get(n);i&&(i.resultRaw=typeof e.content=="string"?e.content:JSON.stringify(e.content??""));break}case"CUSTOM":if(e.name==="tbox:card"){let s=e.value;s?.cardType&&t.cards.push({cardType:s.cardType,status:s.status??"ready"})}break;case"RUN_FINISHED":t.runStatus="finished";break;case"RUN_ERROR":t.runStatus="error";break;case"SUPPORT_ERROR":t.runStatus="error";break;default:break}}function Tl(e,t,r,n,s){let i=[];for(let a of e.toolCalls.values()){let c;if(a.argsBuf)try{c=JSON.parse(a.argsBuf)}catch{c=void 0}i.push({name:a.name,...c!==void 0?{args:c}:{},...a.isError?{isError:!0}:{},...a.resultSummary!==void 0?{resultSummary:a.resultSummary}:{}})}let o=[];for(let a of e.preTools.values()){let c=a.toolName,l;try{a.argsRaw&&(c=JSON.parse(a.argsRaw).toolName??c)}catch{}try{a.resultRaw&&(l=JSON.parse(a.resultRaw).status)}catch{}c&&o.push({name:c,outcome:l==="error"?"error":l==="done"?"ok":l??"ok"})}return{index:t,conversationId:r,userText:n,reply:e.reply,toolCalls:i,preTools:o,cards:e.cards,runStatus:e.runStatus,durationMs:s}}function Ml(e){let t=e.WebSocketCtor??globalThis.WebSocket;if(typeof t!="function")throw new W("当前 Node 缺少全局 WebSocket:评测驱动需要 Node ≥22(仓库基准 Node 24)");return t}async function Lo(e,t,r,n,s){let i=await Cr(e.baseUrl,r,e.fetchFn),o=`${e.baseUrl.replace(/^http/,"ws")}/ws`,a=Ml(e),c=await new Promise((f,g)=>{let m,h=setTimeout(()=>g(new W(`WS 连接超时(${o})`)),jl);try{m=new a(o)}catch(R){clearTimeout(h),g(new W(`WS 创建失败: ${R.message}`));return}let v=()=>{$(),f(m)},S=()=>{$(),g(new W(`WS 连接失败(${o})`))},$=()=>{clearTimeout(h),m.removeEventListener("open",v),m.removeEventListener("error",S)};m.addEventListener("open",v),m.addEventListener("error",S)}),l=[],p=()=>{},u=f=>{p(`WS 传输层故障(${f.type})`)};c.addEventListener("error",u),c.addEventListener("close",u);let d=e.driver??"agui";try{let f;if(await new Promise((v,S)=>{let $=A=>{let N=A.data;try{let P=JSON.parse(N);if(P.type==="HELLO_ACK"){let w=P.supportSession;typeof w?.publicConversationId=="string"&&(f=w.publicConversationId)}["RUN_STARTED","HELLO_ACK","TEXT_MESSAGE_START"].includes(P.type)&&(R(),v())}catch{}},R=()=>{clearTimeout(F),c.removeEventListener("message",$)},F=setTimeout(()=>{R(),v()},El);c.addEventListener("message",$);try{c.send(JSON.stringify({type:"HELLO",token:i}))}catch(A){R(),S(new W(`WS send 失败(连接已关闭?): ${A.message}`))}}),d==="support"&&f===void 0)throw new W("support 驱动未取得服务端会话 id(HELLO_ACK 缺席或无 supportSession.publicConversationId)");let g=1,m=d==="support"?f:`evalconv-${n}-${t.id}-s${g}`,h=!1;for(let v=0;v<t.turns.length;v++){let S=t.turns[v];if(v>0&&S.newSession){if(d==="support")throw new W(`support 驱动暂不支持 newSession(用例 ${t.id})——会话绑定在连接上,跨会话需重连握手`);g+=1,m=`evalconv-${n}-${t.id}-s${g}`}let $={reply:"",toolCalls:new Map,preTools:new Map,cards:[],runStatus:"timeout",started:!h},R=Date.now();await new Promise((F,A)=>{p=M=>{w(),A(new W(M))};let P=M=>{try{let b=JSON.parse(M.data);Cl(b,$),$.runStatus!=="timeout"&&(w(),F())}catch{}},w=()=>{clearTimeout(D),c.removeEventListener("message",P),p=()=>{}},D=setTimeout(()=>{w(),F()},s);c.addEventListener("message",P);try{c.send(JSON.stringify({type:"SEND_MESSAGE",content:S.text,conversationId:m}))}catch(M){w(),A(new W(`WS send 失败(连接已关闭?): ${M.message}`))}}),l.push(Tl($,v,m,S.text,Date.now()-R)),h=$.runStatus==="timeout",d==="support"&&v<t.turns.length-1&&await new Promise(F=>setTimeout(F,Rl))}}finally{p=()=>{};try{c.removeEventListener("error",u),c.removeEventListener("close",u),c.close()}catch{}}return{caseId:t.id,devUser:r,turns:l}}async function Il(e,t){let r;try{r=await Io(e)}catch{return}for(let n of r){let s;try{s=await Io(Ao(e,n))}catch{continue}for(let i of s){let o=Ao(e,n,i,"conversations",t,"journal.jsonl");try{return await Po(o,"utf-8"),o}catch{continue}}}}async function Fo(e,t){try{let r={},n=[...new Set(e.turns.map(s=>s.conversationId))];for(let s of n){let i=await Il(t,s);if(!i)continue;let o=await Po(i,"utf-8");for(let a of o.split(`
246
- `)){if(!a.trim())continue;let c;try{c=JSON.parse(a)}catch{continue}if(c.type==="intent_route"&&c.data?.continued===!1&&(r.intentDirectOut=!0),c.type==="run_end"){let l=c.data?.llm;l&&(r.inputTokens=(r.inputTokens??0)+(l.inputTokens??0),r.outputTokens=(r.outputTokens??0)+(l.outputTokens??0))}}}return{...e,...Object.keys(r).length>0?{journal:r}:{}}}catch(r){return console.warn(`[eval] journal 富化跳过: ${r.message}`),e}}var Al="__tbox_",Ol="agent-ui-cards";function zt(e){return!e.startsWith(Al)&&!e.startsWith(Ol)}function No(e,t,r="agui"){let n=r==="support"?{dim:"tools",status:"na",detail:["support 驱动:TOOL_CALL_* 不出边界,tools 维不判定"]}:_l(e.tools,t);return[Pl(t),n,Vl(e,t)]}function Pl(e){let t=e.turns.filter(r=>r.runStatus!=="finished");return t.length===0?{dim:"run",status:"pass",detail:[]}:{dim:"run",status:"fail",detail:t.map(r=>`第 ${r.index+1} 轮 runStatus=${r.runStatus}`)}}function Vo(e){return typeof e=="string"?e:Array.isArray(e)?`[${e.join(" + ")}]`:`any_of(${e.any_of.map(Vo).join(" | ")})`}function Ll(e){let t=new Set;for(let r of e.turns)for(let n of r.toolCalls)zt(n.name)&&t.add(n.name);return t}function Fl(e){let t=new Set;for(let r of e.turns)for(let n of r.preTools)n.outcome!=="skip"&&t.add(n.name);return t}function Jo(e,t,r){return typeof e=="string"?_o(e,t,r):Array.isArray(e)?e.every(n=>_o(n,t,r)):e.any_of.some(n=>Jo(n,t,r))}function _o(e,t,r){return e==="none"||e==="direct-out"?t.size===0:t.has(e)||r.has(e)}function zo(e){return typeof e=="string"?e==="none"||e==="direct-out"?[]:[e]:Array.isArray(e)?e:e.any_of.flatMap(t=>zo(t))}function _l(e,t){let r=Ll(t),n=Fl(t),s=new Set(e.optional),i=new Set([...r].filter(f=>!s.has(f))),o=new Set([...r,...n]),a=[],c=!1,l=zo(e.expect).filter(f=>!r.has(f)&&n.has(f));Jo(e.expect,i,o)?l.length>0&&a.push(`note: expect 经 preTool 预执行命中 [${l.sort().join(", ")}](模型侧未显式调用)`):(c=!0,a.push(`期望 ${Vo(e.expect)},实际业务调用 [${[...r].sort().join(", ")||"无"}] / preTool [${[...n].sort().join(", ")||"无"}]`)),e.expect==="direct-out"&&i.size===0&&t.journal?.intentDirectOut!==!0&&a.push("degraded: journal 缺席或无 intent_route 佐证,direct-out 退化为 none 判定");let u=e.forbid.filter(f=>i.has(f));u.length>0&&(c=!0,a.push(`禁用工具被调用: [${u.join(", ")}]`));let d=e.pre.filter(f=>!n.has(f));return d.length>0&&(c=!0,a.push(`期望 preTool [${d.join(", ")}] 未命中,实际 preTool [${[...n].sort().join(", ")||"无"}]`)),c?{dim:"tools",status:e.mode==="soft"?"warning":"fail",detail:a}:{dim:"tools",status:"pass",detail:a}}function Nl(e){let t=new Set;for(let r of e.turns)for(let n of r.cards)n.status!=="error"&&t.add(n.cardType);return t}function Vl(e,t){if(!e.cards)return{dim:"cards",status:"na",detail:[]};let r=e.cards.expect,n=typeof r=="string"?[r]:Array.isArray(r)?r:r.any_of.flatMap(o=>typeof o=="string"?[o]:o),s=Nl(t);return(Array.isArray(r)||typeof r=="string"?n.every(o=>s.has(o)):n.some(o=>s.has(o)))?{dim:"cards",status:"pass",detail:[]}:{dim:"cards",status:"fail",detail:[`期望卡片 [${n.join(", ")}] 未齐,实际出卡 [${[...s].sort().join(", ")||"无"}]`]}}import{mkdir as Uo,writeFile as Ut}from"fs/promises";import{join as Fe}from"path";function Bo(e){let t={},r={priority:{},primary_category:{},case_type:{}},n=[],s=0,i=(c,l)=>{let p=t[c]??{pass:0,fail:0,na:0};l==="pass"||l==="warning"?p.pass+=1:l==="fail"?p.fail+=1:p.na+=1,t[c]=p},o=(c,l,p)=>{let u=r[c][l]??{pass:0,total:0};u.total+=1,p&&(u.pass+=1),r[c][l]=u};for(let c of e.results){if(c.spec.skip){n.push({id:c.spec.id,status:"skipped",skipReason:c.spec.skip,dims:{},failures:[]});continue}s+=c.trace?.turns.length??0;let l={},p=[];for(let g of c.dims)l[g.dim]=g.status,i(g.dim,g.status),g.status==="fail"&&p.push(`${g.dim}: ${g.detail.join(";")}`);let u=c.textStatus;l.text=u==="pass"?"pass":u==="fail"?"fail":"na",u==="pass"?i("text","pass"):u==="fail"?(i("text","fail"),p.push(...c.textFailures&&c.textFailures.length>0?c.textFailures:["text: LLM 判定失败(无明细)"])):i("text","na");let d;c.notExecuted?(d="inconclusive",p.push("未执行:infra-aborted 熔断中止")):p.length>0?d="fail":u==="inconclusive"?(d="inconclusive",p.push("text: 全部断言 unclear(judge 无法判定)")):d="pass",n.push({id:c.spec.id,status:d,dims:l,failures:p});let f=d==="pass";o("priority",c.spec.priority,f),o("primary_category",c.spec.tags[0]??"<none>",f),o("case_type",c.spec.tags[2]??"<none>",f)}let a={version:1,runId:e.runId,startedAt:e.startedAt,finishedAt:e.finishedAt,dataset:{name:e.datasetName,hash:e.datasetHash,caseCount:e.results.length},rubricHash:e.rubricHash,judgeModel:e.judgeModel,instance:e.instance,devUserPrefix:e.devUserPrefix,dimensions:t,cases:n.sort((c,l)=>c.id<l.id?-1:c.id>l.id?1:0),slices:r,ops:{durationMs:new Date(e.finishedAt).getTime()-new Date(e.startedAt).getTime(),turnCount:s,infraErrors:e.ops.infraErrors,aborted:e.ops.aborted,llmTokens:e.ops.llmTokens,judgeFailures:e.ops.judgeFailures}};return Qe.parse(a)}function Ho(e,t){let r=new Map(t.cases.map(i=>[i.id,i.status])),n=new Map(e.cases.map(i=>[i.id,i.status])),s={newFailed:[],fixed:[],flipped:[]};for(let[i,o]of n){let a=r.get(i);a===void 0||a===o||(a!=="fail"&&o==="fail"?s.newFailed.push(i):a==="fail"&&o!=="fail"?s.fixed.push(i):s.flipped.push({id:i,from:a,to:o}))}return s}async function Wo(e,t,r,n){await Uo(Fe(e,"traces"),{recursive:!0}),await Ut(Fe(e,"report.json"),JSON.stringify(t,null,2),"utf-8"),await Ut(Fe(e,"report.md"),zl(t),"utf-8");for(let[s,i]of r)await Ut(Fe(e,"traces",`${s}.json`),JSON.stringify(i,null,2),"utf-8");if(n.size>0){await Uo(Fe(e,"judge"),{recursive:!0});for(let[s,i]of n)await Ut(Fe(e,"judge",`${s}.md`),i,"utf-8")}}function Jl(e){return e.sort((t,r)=>r[1].total-t[1].total).map(([t,r])=>`${t} ${r.pass}/${r.total}`).join(" · ")}function zl(e,t){let r=c=>e.cases.filter(l=>l.status===c),n=r("fail"),s=r("inconclusive"),i=r("skipped"),o=[];o.push(`# 评测报告 ${e.runId}`,""),o.push(`- 数据集: ${e.dataset.name}(${e.dataset.caseCount} 例,hash ${e.dataset.hash.slice(0,12)})`),o.push(`- 实例: ${e.instance.baseUrl}${e.instance.degraded?"(degraded:journal 不可达)":""}`),o.push(`- judge: ${e.judgeModel??"未启用"} rubric: ${e.rubricHash.slice(0,12)}`);let a=["pass","fail","inconclusive","skipped"].map(c=>`${c}=${r(c).length}`).join(" ");o.push(`- 结果: ${a} 用时 ${(e.ops.durationMs/1e3).toFixed(0)}s turns=${e.ops.turnCount}${e.ops.aborted?" ⚠️ infra-aborted(熔断)":""}${e.ops.judgeFailures>0?` ⚠️ judge 失败 ${e.ops.judgeFailures} 例(text 维降级,需人工复核)`:""}`,""),o.push("## 维度","");for(let[c,l]of Object.entries(e.dimensions))o.push(`- ${c}: pass=${l.pass} fail=${l.fail} na=${l.na}`);o.push("","## 切片","");for(let[c,l]of Object.entries(e.slices))o.push(`- ${c}: ${Jl(Object.entries(l))}`);if(t&&(o.push("","## 基线对比",""),o.push(`- 新失败: ${t.newFailed.length>0?t.newFailed.join(", "):"无"}`),o.push(`- 已修复: ${t.fixed.length>0?t.fixed.join(", "):"无"}`),t.flipped.length>0&&o.push(`- 翻转: ${t.flipped.map(c=>`${c.id} ${c.from}→${c.to}`).join(", ")}`)),n.length>0){o.push("","## 失败用例","");for(let c of n){o.push(`### ${c.id}(${Object.entries(c.dims).filter(([,l])=>l==="fail").map(([l])=>l).join("+")||"?"})`);for(let l of c.failures)o.push(`- ${l}`);o.push("")}}if(s.length>0){o.push("## Inconclusive(judge 全 unclear,不计失败)","");for(let c of s)o.push(`- ${c.id}`);o.push("")}if(i.length>0){o.push("## Skipped","");for(let c of i)o.push(`- ${c.id}(${c.skipReason})`);o.push("")}return o.join(`
247
- `)}function Ko(e){return{userText:e.userText,reply:e.reply.length>4e3?`${e.reply.slice(0,4e3)}…`:e.reply,tools:e.toolCalls.filter(t=>zt(t.name)).map(t=>({name:t.name,...t.resultSummary!==void 0?{result:t.resultSummary}:{}})),framework:e.toolCalls.filter(t=>!zt(t.name)).map(t=>t.name),preTools:e.preTools.map(t=>`${t.name}(${t.outcome})`),cards:e.cards.map(t=>({cardType:t.cardType,status:t.status})),runStatus:e.runStatus}}import{z as _e}from"zod";function Go(e){let t=e.EVAL_JUDGE_BASE_URL??e.APP_AI_BASE_URL,r=e.EVAL_JUDGE_API_KEY??e.APP_AI_API_KEY,n=e.EVAL_JUDGE_MODEL??e.APP_AI_MODEL_NAME;if(!t||!r||!n)throw new Error(`评测 judge 配置缺失(需 EVAL_JUDGE_BASE_URL/API_KEY/MODEL,或回退 APP_AI_BASE_URL/API_KEY/MODEL_NAME;缺: ${[!t&&"BASE_URL",!r&&"API_KEY",!n&&"MODEL"].filter(Boolean).join(", ")})`);return{baseUrl:t.replace(/\/$/,""),apiKey:r,model:n}}function Ul(e){let t=e.match(/```(?:json)?\s*([\s\S]*?)\s*```/);return t?t[1]:e}async function qo(e,t,r,n,s){let i=s?.fetchFn??fetch,o=[{role:"system",content:t},{role:"user",content:r}],a="",c=3;for(let l=0;l<c;l++){l>0&&await new Promise(f=>setTimeout(f,800*l));let p=l===0?r:`${r}
248
+ `)}`);let g=Ao([JSON.stringify(s)]),m=[...o].sort((v,S)=>Oo(v.id,S.id)),h=Ao([JSON.stringify(n),JSON.stringify(s),...m.map(v=>JSON.stringify(v))]);return{dir:e,suite:n,rubric:s,cases:o,datasetHash:h,rubricHash:g,manifest:u}}function Po(e){let t={},r={},n={},s={},i=0,o=0;for(let a of e.cases){a.skip&&(t[a.skip]=(t[a.skip]??0)+1),r[a.priority]=(r[a.priority]??0)+1;let c=a.tags[2]??"<none>";n[c]=(n[c]??0)+1;let l=1;for(let p of a.turns)p.newSession&&(l+=1);s[String(l)]=(s[String(l)]??0)+1,a.turns.length>1&&(i+=1),a.tools.mode==="soft"&&(o+=1)}return{total:e.cases.length,evaluated:e.cases.filter(a=>!a.skip).length,skippedByReason:t,byPriority:r,byCaseType:n,sessionHistogram:s,multiTurnCases:i,softModeCases:o}}import{randomBytes as op}from"crypto";import{mkdir as ip,readFile as ci}from"fs/promises";import{join as Fr}from"path";import{readdir as Lo,readFile as No}from"fs/promises";import{join as Fo}from"path";var H=class extends Error{constructor(t){super(t),this.name="InfraError"}},_o=400,Cl=1e4,Tl=1500,Ml=300;async function Ir(e,t,r){let n=r??fetch,s;try{s=await n(`${e}/api/auth/dev-login`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({devUser:t})})}catch(o){throw new H(`dev-login 请求失败(${e}): ${o.message}`)}if(!s.ok)throw new H(`dev-login 失败 HTTP ${s.status}(devUser=${t};prod 档会 403——检查实例启动语义)`);let i=await s.json().catch(()=>{});if(!i?.token)throw new H("dev-login 响应缺 token");return i.token}function Il(e){if(e==null)return;let t=typeof e=="string"?e:JSON.stringify(e);return t.length>_o?`${t.slice(0,_o)}…`:t}function Al(e,t){let r=e.type;if(!t.started){if(r==="RUN_FINISHED"||r==="RUN_ERROR")return;t.started=!0}let n=e.toolCallId;switch(r){case"TEXT_MESSAGE_CONTENT":t.reply+=e.delta??"";break;case"TOOL_CALL_START":{let s=e.toolCallName;s==="__tbox_pretool"?t.preTools.set(n??`pre-${t.preTools.size}`,{}):t.toolCalls.set(n??`tool-${t.toolCalls.size}`,{name:s,argsBuf:""});break}case"TOOL_CALL_ARGS":{if(n===void 0)break;let s=t.toolCalls.get(n);if(s){s.argsBuf=(s.argsBuf??"")+(e.delta??"");break}let i=t.preTools.get(n);i&&(i.argsRaw=(i.argsRaw??"")+(e.delta??""));break}case"TOOL_CALL_RESULT":{if(n===void 0)break;let s=t.toolCalls.get(n);if(s){e.isError===!0&&(s.isError=!0),s.resultSummary=Il(e.content);break}let i=t.preTools.get(n);i&&(i.resultRaw=typeof e.content=="string"?e.content:JSON.stringify(e.content??""));break}case"CUSTOM":if(e.name==="tbox:card"){let s=e.value;s?.cardType&&t.cards.push({cardType:s.cardType,status:s.status??"ready"})}break;case"RUN_FINISHED":t.runStatus="finished";break;case"RUN_ERROR":t.runStatus="error";break;case"SUPPORT_ERROR":t.runStatus="error";break;default:break}}function Ol(e,t,r,n,s){let i=[];for(let a of e.toolCalls.values()){let c;if(a.argsBuf)try{c=JSON.parse(a.argsBuf)}catch{c=void 0}i.push({name:a.name,...c!==void 0?{args:c}:{},...a.isError?{isError:!0}:{},...a.resultSummary!==void 0?{resultSummary:a.resultSummary}:{}})}let o=[];for(let a of e.preTools.values()){let c=a.toolName,l;try{a.argsRaw&&(c=JSON.parse(a.argsRaw).toolName??c)}catch{}try{a.resultRaw&&(l=JSON.parse(a.resultRaw).status)}catch{}c&&o.push({name:c,outcome:l==="error"?"error":l==="done"?"ok":l??"ok"})}return{index:t,conversationId:r,userText:n,reply:e.reply,toolCalls:i,preTools:o,cards:e.cards,runStatus:e.runStatus,durationMs:s}}function Pl(e){let t=e.WebSocketCtor??globalThis.WebSocket;if(typeof t!="function")throw new H("当前 Node 缺少全局 WebSocket:评测驱动需要 Node ≥22(仓库基准 Node 24)");return t}async function Vo(e,t,r,n,s){let i=await Ir(e.baseUrl,r,e.fetchFn),o=`${e.baseUrl.replace(/^http/,"ws")}/ws`,a=Pl(e),c=await new Promise((f,g)=>{let m,h=setTimeout(()=>g(new H(`WS 连接超时(${o})`)),Cl);try{m=new a(o)}catch(R){clearTimeout(h),g(new H(`WS 创建失败: ${R.message}`));return}let v=()=>{$(),f(m)},S=()=>{$(),g(new H(`WS 连接失败(${o})`))},$=()=>{clearTimeout(h),m.removeEventListener("open",v),m.removeEventListener("error",S)};m.addEventListener("open",v),m.addEventListener("error",S)}),l=[],p=()=>{},u=f=>{p(`WS 传输层故障(${f.type})`)};c.addEventListener("error",u),c.addEventListener("close",u);let d=e.driver??"agui";try{let f;if(await new Promise((v,S)=>{let $=A=>{let N=A.data;try{let P=JSON.parse(N);if(P.type==="HELLO_ACK"){let w=P.supportSession;typeof w?.publicConversationId=="string"&&(f=w.publicConversationId)}["RUN_STARTED","HELLO_ACK","TEXT_MESSAGE_START"].includes(P.type)&&(R(),v())}catch{}},R=()=>{clearTimeout(F),c.removeEventListener("message",$)},F=setTimeout(()=>{R(),v()},Tl);c.addEventListener("message",$);try{c.send(JSON.stringify({type:"HELLO",token:i}))}catch(A){R(),S(new H(`WS send 失败(连接已关闭?): ${A.message}`))}}),d==="support"&&f===void 0)throw new H("support 驱动未取得服务端会话 id(HELLO_ACK 缺席或无 supportSession.publicConversationId)");let g=1,m=d==="support"?f:`evalconv-${n}-${t.id}-s${g}`,h=!1;for(let v=0;v<t.turns.length;v++){let S=t.turns[v];if(v>0&&S.newSession){if(d==="support")throw new H(`support 驱动暂不支持 newSession(用例 ${t.id})——会话绑定在连接上,跨会话需重连握手`);g+=1,m=`evalconv-${n}-${t.id}-s${g}`}let $={reply:"",toolCalls:new Map,preTools:new Map,cards:[],runStatus:"timeout",started:!h},R=Date.now();await new Promise((F,A)=>{p=M=>{w(),A(new H(M))};let P=M=>{try{let b=JSON.parse(M.data);Al(b,$),$.runStatus!=="timeout"&&(w(),F())}catch{}},w=()=>{clearTimeout(D),c.removeEventListener("message",P),p=()=>{}},D=setTimeout(()=>{w(),F()},s);c.addEventListener("message",P);try{c.send(JSON.stringify({type:"SEND_MESSAGE",content:S.text,conversationId:m}))}catch(M){w(),A(new H(`WS send 失败(连接已关闭?): ${M.message}`))}}),l.push(Ol($,v,m,S.text,Date.now()-R)),h=$.runStatus==="timeout",d==="support"&&v<t.turns.length-1&&await new Promise(F=>setTimeout(F,Ml))}}finally{p=()=>{};try{c.removeEventListener("error",u),c.removeEventListener("close",u),c.close()}catch{}}return{caseId:t.id,devUser:r,turns:l}}async function Ll(e,t){let r;try{r=await Lo(e)}catch{return}for(let n of r){let s;try{s=await Lo(Fo(e,n))}catch{continue}for(let i of s){let o=Fo(e,n,i,"conversations",t,"journal.jsonl");try{return await No(o,"utf-8"),o}catch{continue}}}}async function Jo(e,t){try{let r={},n=[...new Set(e.turns.map(s=>s.conversationId))];for(let s of n){let i=await Ll(t,s);if(!i)continue;let o=await No(i,"utf-8");for(let a of o.split(`
249
+ `)){if(!a.trim())continue;let c;try{c=JSON.parse(a)}catch{continue}if(c.type==="intent_route"&&c.data?.continued===!1&&(r.intentDirectOut=!0),c.type==="run_end"){let l=c.data?.llm;l&&(r.inputTokens=(r.inputTokens??0)+(l.inputTokens??0),r.outputTokens=(r.outputTokens??0)+(l.outputTokens??0))}}}return{...e,...Object.keys(r).length>0?{journal:r}:{}}}catch(r){return console.warn(`[eval] journal 富化跳过: ${r.message}`),e}}var Fl="__tbox_",_l="agent-ui-cards";function Bt(e){return!e.startsWith(Fl)&&!e.startsWith(_l)}function Uo(e,t,r="agui"){let n=r==="support"?{dim:"tools",status:"na",detail:["support 驱动:TOOL_CALL_* 不出边界,tools 维不判定"]}:zl(e.tools,t);return[Nl(t),n,Bl(e,t)]}function Nl(e){let t=e.turns.filter(r=>r.runStatus!=="finished");return t.length===0?{dim:"run",status:"pass",detail:[]}:{dim:"run",status:"fail",detail:t.map(r=>`第 ${r.index+1} 轮 runStatus=${r.runStatus}`)}}function Bo(e){return typeof e=="string"?e:Array.isArray(e)?`[${e.join(" + ")}]`:`any_of(${e.any_of.map(Bo).join(" | ")})`}function Vl(e){let t=new Set;for(let r of e.turns)for(let n of r.toolCalls)Bt(n.name)&&t.add(n.name);return t}function Jl(e){let t=new Set;for(let r of e.turns)for(let n of r.preTools)n.outcome!=="skip"&&t.add(n.name);return t}function Wo(e,t,r){return typeof e=="string"?zo(e,t,r):Array.isArray(e)?e.every(n=>zo(n,t,r)):e.any_of.some(n=>Wo(n,t,r))}function zo(e,t,r){return e==="none"||e==="direct-out"?t.size===0:t.has(e)||r.has(e)}function Ho(e){return typeof e=="string"?e==="none"||e==="direct-out"?[]:[e]:Array.isArray(e)?e:e.any_of.flatMap(t=>Ho(t))}function zl(e,t){let r=Vl(t),n=Jl(t),s=new Set(e.optional),i=new Set([...r].filter(f=>!s.has(f))),o=new Set([...r,...n]),a=[],c=!1,l=Ho(e.expect).filter(f=>!r.has(f)&&n.has(f));Wo(e.expect,i,o)?l.length>0&&a.push(`note: expect 经 preTool 预执行命中 [${l.sort().join(", ")}](模型侧未显式调用)`):(c=!0,a.push(`期望 ${Bo(e.expect)},实际业务调用 [${[...r].sort().join(", ")||"无"}] / preTool [${[...n].sort().join(", ")||"无"}]`)),e.expect==="direct-out"&&i.size===0&&t.journal?.intentDirectOut!==!0&&a.push("degraded: journal 缺席或无 intent_route 佐证,direct-out 退化为 none 判定");let u=e.forbid.filter(f=>i.has(f));u.length>0&&(c=!0,a.push(`禁用工具被调用: [${u.join(", ")}]`));let d=e.pre.filter(f=>!n.has(f));return d.length>0&&(c=!0,a.push(`期望 preTool [${d.join(", ")}] 未命中,实际 preTool [${[...n].sort().join(", ")||"无"}]`)),c?{dim:"tools",status:e.mode==="soft"?"warning":"fail",detail:a}:{dim:"tools",status:"pass",detail:a}}function Ul(e){let t=new Set;for(let r of e.turns)for(let n of r.cards)n.status!=="error"&&t.add(n.cardType);return t}function Bl(e,t){if(!e.cards)return{dim:"cards",status:"na",detail:[]};let r=e.cards.expect,n=typeof r=="string"?[r]:Array.isArray(r)?r:r.any_of.flatMap(o=>typeof o=="string"?[o]:o),s=Ul(t);return(Array.isArray(r)||typeof r=="string"?n.every(o=>s.has(o)):n.some(o=>s.has(o)))?{dim:"cards",status:"pass",detail:[]}:{dim:"cards",status:"fail",detail:[`期望卡片 [${n.join(", ")}] 未齐,实际出卡 [${[...s].sort().join(", ")||"无"}]`]}}import{mkdir as Ko,writeFile as Wt}from"fs/promises";import{join as Fe}from"path";function Go(e){let t={},r={priority:{},primary_category:{},case_type:{}},n=[],s=0,i=(c,l)=>{let p=t[c]??{pass:0,fail:0,na:0};l==="pass"||l==="warning"?p.pass+=1:l==="fail"?p.fail+=1:p.na+=1,t[c]=p},o=(c,l,p)=>{let u=r[c][l]??{pass:0,total:0};u.total+=1,p&&(u.pass+=1),r[c][l]=u};for(let c of e.results){if(c.spec.skip){n.push({id:c.spec.id,status:"skipped",skipReason:c.spec.skip,dims:{},failures:[]});continue}s+=c.trace?.turns.length??0;let l={},p=[];for(let g of c.dims)l[g.dim]=g.status,i(g.dim,g.status),g.status==="fail"&&p.push(`${g.dim}: ${g.detail.join(";")}`);let u=c.textStatus;l.text=u==="pass"?"pass":u==="fail"?"fail":"na",u==="pass"?i("text","pass"):u==="fail"?(i("text","fail"),p.push(...c.textFailures&&c.textFailures.length>0?c.textFailures:["text: LLM 判定失败(无明细)"])):i("text","na");let d;c.notExecuted?(d="inconclusive",p.push("未执行:infra-aborted 熔断中止")):p.length>0?d="fail":u==="inconclusive"?(d="inconclusive",p.push("text: 全部断言 unclear(judge 无法判定)")):d="pass",n.push({id:c.spec.id,status:d,dims:l,failures:p});let f=d==="pass";o("priority",c.spec.priority,f),o("primary_category",c.spec.tags[0]??"<none>",f),o("case_type",c.spec.tags[2]??"<none>",f)}let a={version:1,runId:e.runId,startedAt:e.startedAt,finishedAt:e.finishedAt,dataset:{name:e.datasetName,hash:e.datasetHash,caseCount:e.results.length},rubricHash:e.rubricHash,judgeModel:e.judgeModel,instance:e.instance,devUserPrefix:e.devUserPrefix,dimensions:t,cases:n.sort((c,l)=>c.id<l.id?-1:c.id>l.id?1:0),slices:r,ops:{durationMs:new Date(e.finishedAt).getTime()-new Date(e.startedAt).getTime(),turnCount:s,infraErrors:e.ops.infraErrors,aborted:e.ops.aborted,llmTokens:e.ops.llmTokens,judgeFailures:e.ops.judgeFailures}};return Qe.parse(a)}function qo(e,t){let r=new Map(t.cases.map(i=>[i.id,i.status])),n=new Map(e.cases.map(i=>[i.id,i.status])),s={newFailed:[],fixed:[],flipped:[]};for(let[i,o]of n){let a=r.get(i);a===void 0||a===o||(a!=="fail"&&o==="fail"?s.newFailed.push(i):a==="fail"&&o!=="fail"?s.fixed.push(i):s.flipped.push({id:i,from:a,to:o}))}return s}async function Xo(e,t,r,n){await Ko(Fe(e,"traces"),{recursive:!0}),await Wt(Fe(e,"report.json"),JSON.stringify(t,null,2),"utf-8"),await Wt(Fe(e,"report.md"),Hl(t),"utf-8");for(let[s,i]of r)await Wt(Fe(e,"traces",`${s}.json`),JSON.stringify(i,null,2),"utf-8");if(n.size>0){await Ko(Fe(e,"judge"),{recursive:!0});for(let[s,i]of n)await Wt(Fe(e,"judge",`${s}.md`),i,"utf-8")}}function Wl(e){return e.sort((t,r)=>r[1].total-t[1].total).map(([t,r])=>`${t} ${r.pass}/${r.total}`).join(" · ")}function Hl(e,t){let r=c=>e.cases.filter(l=>l.status===c),n=r("fail"),s=r("inconclusive"),i=r("skipped"),o=[];o.push(`# 评测报告 ${e.runId}`,""),o.push(`- 数据集: ${e.dataset.name}(${e.dataset.caseCount} 例,hash ${e.dataset.hash.slice(0,12)})`),o.push(`- 实例: ${e.instance.baseUrl}${e.instance.degraded?"(degraded:journal 不可达)":""}`),o.push(`- judge: ${e.judgeModel??"未启用"} rubric: ${e.rubricHash.slice(0,12)}`);let a=["pass","fail","inconclusive","skipped"].map(c=>`${c}=${r(c).length}`).join(" ");o.push(`- 结果: ${a} 用时 ${(e.ops.durationMs/1e3).toFixed(0)}s turns=${e.ops.turnCount}${e.ops.aborted?" ⚠️ infra-aborted(熔断)":""}${e.ops.judgeFailures>0?` ⚠️ judge 失败 ${e.ops.judgeFailures} 例(text 维降级,需人工复核)`:""}`,""),o.push("## 维度","");for(let[c,l]of Object.entries(e.dimensions))o.push(`- ${c}: pass=${l.pass} fail=${l.fail} na=${l.na}`);o.push("","## 切片","");for(let[c,l]of Object.entries(e.slices))o.push(`- ${c}: ${Wl(Object.entries(l))}`);if(t&&(o.push("","## 基线对比",""),o.push(`- 新失败: ${t.newFailed.length>0?t.newFailed.join(", "):"无"}`),o.push(`- 已修复: ${t.fixed.length>0?t.fixed.join(", "):"无"}`),t.flipped.length>0&&o.push(`- 翻转: ${t.flipped.map(c=>`${c.id} ${c.from}→${c.to}`).join(", ")}`)),n.length>0){o.push("","## 失败用例","");for(let c of n){o.push(`### ${c.id}(${Object.entries(c.dims).filter(([,l])=>l==="fail").map(([l])=>l).join("+")||"?"})`);for(let l of c.failures)o.push(`- ${l}`);o.push("")}}if(s.length>0){o.push("## Inconclusive(judge 全 unclear,不计失败)","");for(let c of s)o.push(`- ${c.id}`);o.push("")}if(i.length>0){o.push("## Skipped","");for(let c of i)o.push(`- ${c.id}(${c.skipReason})`);o.push("")}return o.join(`
250
+ `)}function Yo(e){return{userText:e.userText,reply:e.reply.length>4e3?`${e.reply.slice(0,4e3)}…`:e.reply,tools:e.toolCalls.filter(t=>Bt(t.name)).map(t=>({name:t.name,...t.resultSummary!==void 0?{result:t.resultSummary}:{}})),framework:e.toolCalls.filter(t=>!Bt(t.name)).map(t=>t.name),preTools:e.preTools.map(t=>`${t.name}(${t.outcome})`),cards:e.cards.map(t=>({cardType:t.cardType,status:t.status})),runStatus:e.runStatus}}import{z as _e}from"zod";function Zo(e){let t=e.EVAL_JUDGE_BASE_URL??e.APP_AI_BASE_URL,r=e.EVAL_JUDGE_API_KEY??e.APP_AI_API_KEY,n=e.EVAL_JUDGE_MODEL??e.APP_AI_MODEL_NAME;if(!t||!r||!n)throw new Error(`评测 judge 配置缺失(需 EVAL_JUDGE_BASE_URL/API_KEY/MODEL,或回退 APP_AI_BASE_URL/API_KEY/MODEL_NAME;缺: ${[!t&&"BASE_URL",!r&&"API_KEY",!n&&"MODEL"].filter(Boolean).join(", ")})`);return{baseUrl:t.replace(/\/$/,""),apiKey:r,model:n}}function Kl(e){let t=e.match(/```(?:json)?\s*([\s\S]*?)\s*```/);return t?t[1]:e}async function Qo(e,t,r,n,s){let i=s?.fetchFn??fetch,o=[{role:"system",content:t},{role:"user",content:r}],a="",c=3;for(let l=0;l<c;l++){l>0&&await new Promise(f=>setTimeout(f,800*l));let p=l===0?r:`${r}
248
251
 
249
- (上次输出无法解析为 JSON,请只输出 JSON,不要任何其他文字)`,u;try{u=await i(`${e.baseUrl}/chat/completions`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.apiKey}`,"accept-encoding":"identity"},body:JSON.stringify({model:e.model,temperature:0,messages:l===0?o:[o[0],{role:"user",content:p}]})})}catch(f){throw new Error(`judge LLM 请求失败: ${f.message}`)}if(!u.ok){let f=await u.text().catch(()=>"");throw new Error(`judge LLM HTTP ${u.status}: ${f.slice(0,300)}`)}if(a=(await u.json().catch(()=>{}))?.choices?.[0]?.message?.content??"",!!a.trim())try{return{parsed:n.parse(JSON.parse(Ul(a))),raw:a}}catch{}}throw new Error(`judge 输出无法解析为 JSON(${c} 次尝试): ${a.slice(0,300)||"<空响应>"}`)}var Bl=_e.object({assertions:_e.array(_e.object({text:_e.string().min(1),verdict:_e.enum(["pass","fail","unclear"]),reason:_e.string().min(1)})).min(1)});function Hl(e,t,r){let n=["你是智能体行为评测裁判。依据评审标准,对每条断言独立判定 pass/fail/unclear。","判定基于证据中的实际回复与工具出参(判「如实」而非「应然」)。","证据轨别:tools 是模型主动调用;preTools 是系统预执行(非模型决策);__tbox_ 前缀是框架伪工具。判定「模型是否调用/误路由」类断言时只依据 tools。","断言按语义满足判定,不逐字匹配文案;断言与评审标准冲突、或断言前提在当前对话不成立时(如要求重试建议但重试已成功),以评审标准和实际行为为准。","证据不足或断言在当前对话中无法验证时判 unclear,不要猜测。",'只输出 JSON:{"assertions":[{"text":"断言原文","verdict":"pass|fail|unclear","reason":"判定理由"}]}',"","评审标准:",...r.standards.map((o,a)=>/^\d+[.、.]\s*/.test(o)?o:`${a+1}. ${o}`)].join(`
250
- `),s=t.turns.map((o,a)=>({turn:a+1,...Ko(o)})),i=[`用例 ${e.id}(priority=${e.priority})`,`证据:${JSON.stringify(s)}`,"断言:",...e.assertions.map((o,a)=>`${a+1}. ${o}`)];return e.judge_hints.length>0&&i.push("评审备注(附加上下文,优先级低于评审标准):",...e.judge_hints.map(o=>`- ${o}`)),i.push("逐条输出判定 JSON。"),{system:n,user:i.join(`
251
- `)}}function Xo(e){let t=e.some(n=>n.verdict==="fail"),r=e.some(n=>n.verdict==="pass");return t?{status:"fail",failures:e.filter(n=>n.verdict==="fail").map(n=>`${n.text} —— ${n.reason}`)}:r?{status:"pass",failures:[]}:{status:"inconclusive",failures:[]}}async function Yo(e,t,r,n,s){let{system:i,user:o}=Hl(r,n,t),{parsed:a,raw:c}=await qo(e,i,o,Bl,s),l=new Map(a.assertions.map(u=>[u.text.trim(),u]));return{verdicts:r.assertions.map(u=>l.get(u.trim())??{text:u,verdict:"unclear",reason:"judge 输出缺失该断言"}),raw:c}}import{spawn as Zo,spawnSync as Wl}from"child_process";import{existsSync as ei,openSync as Kl,readFileSync as Gl}from"fs";import{rm as ql,writeFile as Xl}from"fs/promises";import{join as be}from"path";var Mr="apps/server",Tr="dist/index.js",Ir=".tbox-server.json",Qo=".tbox-server.log",ti=60,Yl=1e3;function Ar(e){return ei(be(e,Mr,"package.json"))?e:null}function tt(e){let t;try{t=Gl(be(e,Ir),"utf-8")}catch{return null}try{return Ro.parse(JSON.parse(t))}catch{return null}}async function Zl(e,t){await Xl(be(e,Ir),JSON.stringify(t,null,2),"utf-8")}async function Ht(e){await ql(be(e,Ir),{force:!0})}function Ql(e){return`${e.replace(/\/$/,"")}/api/health`}async function Bt(e,t){let r=t?.attempts??ti,n=t?.intervalMs??Yl;for(let s=0;s<r;s++){try{if((await fetch(Ql(e))).ok)return!0}catch{}await new Promise(i=>setTimeout(i,n))}return!1}async function ri(e){if(!Ar(e.appDir))throw new Error(`当前目录不是应用根(缺 ${Mr}/package.json): ${e.appDir}`);let t=be(e.appDir,Mr),r=be(t,Tr);if(e.build){let l=Wl("pnpm",["--filter","@app/server","build"],{cwd:e.appDir,stdio:"inherit"});if(l.status!==0)throw new Error(`构建失败(pnpm --filter @app/server build,exit=${l.status})`)}if(!ei(r))throw new Error("应用未构建:先 --build,或使用 `tbox-app eval run --base-url` 评测外部实例");let n=tt(e.appDir);if(n&&await Bt(n.baseUrl,{attempts:2,intervalMs:500}))throw new Error(`已在运行 ${n.baseUrl}(pid=${n.pid});tbox-app stop 后再启动`);await Ht(e.appDir);let s=e.port??8e3,i=be(e.appDir,".eval-journal"),o={version:1,pid:0,port:s,baseUrl:`http://127.0.0.1:${s}`,journalRoot:i,startedAt:new Date().toISOString(),detached:e.detached},a;if(e.detached){let l=Kl(be(e.appDir,Qo),"a");a=Zo("node",[Tr],{cwd:t,env:{...process.env,PORT:String(s),TBOX_LOCAL_LOG:"on",TBOX_LOCAL_LOG_DIR:i,TBOX_APP_ID:"eval"},stdio:["ignore",l,l],detached:!0}),a.unref()}else a=Zo("node",[Tr],{cwd:t,env:{...process.env,PORT:String(s),TBOX_LOCAL_LOG:"on",TBOX_LOCAL_LOG_DIR:i,TBOX_APP_ID:"eval"},stdio:"inherit"});if(o.pid=a.pid??0,!await Bt(o.baseUrl)){try{e.detached?process.kill(-o.pid,"SIGKILL"):a.kill("SIGKILL")}catch{}throw new Error(`server ${ti}s 未就绪(${o.baseUrl};日志 ${Qo})`)}if(!(()=>{try{return process.kill(o.pid,0),!0}catch{return!1}})()||!e.detached&&a.exitCode!==null)throw new Error(`端口 ${s} 已被其他进程占用(health 来自占用者);--port 换端口后重试`);return await Zl(e.appDir,o),{child:a,state:o}}async function ni(e,t){await ep(t.pid,t.detached,void 0),await Ht(e)}async function ep(e,t,r){let n=()=>{try{return process.kill(e,0),!0}catch{return!1}};if(!n())return;if(t)try{process.kill(-e,"SIGTERM")}catch{}else{r?.kill("SIGTERM");try{process.kill(e,"SIGTERM")}catch{}}let s=Date.now()+2e3;for(;n()&&Date.now()<s;)await new Promise(i=>setTimeout(i,100));if(n())try{t?process.kill(-e,"SIGKILL"):process.kill(e,"SIGKILL")}catch{}}var oi=5;function pe(e,t){e||console.log(`[eval] ${t}`)}function np(e,t){if(t.length===0)return e;let r=new Map;for(let s of t){let i=s.indexOf("=");if(i<=0)throw new Error(`--filter 形状非法: "${s}"(应为 key=value)`);let o=s.slice(0,i),a=s.slice(i+1);if(!["priority","tag","id","skip"].includes(o))throw new Error(`--filter 未知键: "${o}"(支持 priority/tag/id/skip)`);let c=r.get(o)??[];c.push({key:o,value:a}),r.set(o,c)}let n=(s,i,o)=>{switch(i){case"priority":return s.priority===o;case"id":return s.id===o;case"tag":return s.tags.includes(o);case"skip":return s.skip===o;default:return!1}};return e.filter(s=>[...r.values()].every(i=>i.some(o=>n(s,o.key,o.value))))}async function ii(e){if(e.max!==void 0&&(!Number.isInteger(e.max)||e.max<1))throw new Error("--max 需为 ≥1 的整数");if(!Number.isInteger(e.concurrency)||e.concurrency<1)throw new Error("--concurrency 需为 ≥1 的整数");let t=await Jt(e.dataset),r=np(t.cases,e.filters);if(e.rerunFailedDir){let w=await si(Or(e.rerunFailedDir,"report.json"),"utf-8"),D=Qe.parse(JSON.parse(w)),M=new Set(D.cases.filter(b=>b.status==="fail"||b.status==="inconclusive").map(b=>b.id));r=r.filter(b=>M.has(b.id)),r.length===0&&pe(e.quiet,"--rerun-failed: 上次无 fail/inconclusive 用例,空跑")}e.max!==void 0&&(r=r.slice(0,e.max));let n,s=null,i=null,o=e.journalRoot??null;if(e.baseUrl)n=e.baseUrl.replace(/\/$/,"");else{let w=tt(e.cwd);if(!w)throw new Error("未发现可用实例:先 `tbox-app start -d`(状态文件 .tbox-server.json)或传 --base-url <url>");if(!await Bt(w.baseUrl,{attempts:3,intervalMs:500}))throw new Error(`状态文件实例不可达(${w.baseUrl}):实例可能已退出,重新 start -d 或传 --base-url`);n=w.baseUrl,s=w.pid,i=w.startedAt,o=o??w.journalRoot}let a=e.judge?Go(process.env):null,c=tp(4).toString("hex"),l=`eval-${c}`,p=e.outDir??Or(e.cwd,".eval","runs",`${op()}-${c}`),u=new Date().toISOString();pe(e.quiet,`runId=${c} dataset=${t.suite.name} cases=${r.length} concurrency=${e.concurrency} judge=${a?a.model:"off"}`),pe(e.quiet,`instance=${n}${o?` journal=${o}`:"(journal 缺席,direct-out 降级)"}`);let d=[];for(let w of r)w.skip&&d.push({spec:w,dims:[]});let f=new Map,g=new Map,m=0,h=0,v=!1,S=0,$=r.filter(w=>!w.skip),R=[...$],F=async()=>{for(;;){if(v)return;let w=R.shift();if(!w)return;let D=`eval-${c}-${w.id}`,M,b;try{M=await Lo({baseUrl:n,driver:t.suite.driver??"agui",...e.deps},w,D,c,t.suite.defaultTurnTimeoutMs),o&&(M=await Fo(M,o)),f.set(w.id,M)}catch(j){if(j instanceof W){m+=1,h+=1,h>=oi&&(v=!0),d.push({spec:w,dims:[{dim:"run",status:"fail",detail:[j.message]}]}),pe(e.quiet,`✗ ${w.id} infra: ${j.message}`),v&&pe(e.quiet,`熔断(连续 ${oi} 个 infra 错误),中止余量 ${R.length} 例`);continue}throw j}h=0;let k=No(w,M,t.suite.driver??"agui");if(a)try{let{verdicts:j,raw:ee}=await Yo(a,t.rubric,w,M,e.deps);g.set(w.id,ee),b=Xo(j)}catch(j){S+=1,b={status:"inconclusive",failures:[`judge 调用失败: ${j.message}`]},pe(e.quiet,`⚠ ${w.id} judge 失败: ${j.message}`)}d.push({spec:w,trace:M,dims:k,textStatus:b?.status,textFailures:b?.failures});let O=k.filter(j=>j.status==="fail").map(j=>j.dim);pe(e.quiet,`${O.length>0||b?.status==="fail"?"✗":"✓"} ${w.id}${O.length>0?` (${O.join(",")}${b?.status==="fail"?",text":""})`:""}`)}};await Promise.all(Array.from({length:Math.max(1,Math.min(e.concurrency,16))},F));for(let w of $)d.some(D=>D.spec.id===w.id)||d.push({spec:w,dims:[],notExecuted:!0});let A=[...f.values()].reduce((w,D)=>w+(D.journal?.inputTokens??0)+(D.journal?.outputTokens??0),0);await sp(n,$.map(w=>`eval-${c}-${w.id}`),e.deps?.fetchFn,e.quiet);let N=Bo({runId:c,startedAt:u,finishedAt:new Date().toISOString(),datasetName:t.suite.name,datasetHash:t.datasetHash,rubricHash:t.rubricHash,judgeModel:a?.model??null,instance:{baseUrl:n,pid:s,startedAt:i,journalRoot:o,degraded:!o},devUserPrefix:l,results:d,ops:{infraErrors:m,aborted:v,llmTokens:A>0?A:null,judgeFailures:S}}),P;if(e.baselinePath){let w=await si(e.baselinePath,"utf-8"),D=Qe.parse(JSON.parse(w));P=Ho(N,D)}return await rp(p,{recursive:!0}),await Wo(p,N,f,g),console.log(`报告: ${Or(p,"report.md")}`),process.env.EVAL_REPORT==="json"&&console.log(JSON.stringify(N)),P&&pe(e.quiet,`基线对比: 新失败=${P.newFailed.length} 已修复=${P.fixed.length} 翻转=${P.flipped.length}`),{exitCode:v?2:0,runDir:p,report:N}}async function sp(e,t,r,n){let s=r??fetch;for(let i of t)try{let o=await Cr(e,i,s),a=await s(`${e}/api/memory`,{headers:{authorization:`Bearer ${o}`}});if(!a.ok)continue;let l=((await a.json().catch(()=>{}))?.records??[]).map(p=>p.id).filter(p=>typeof p=="string");for(let p of l)await s(`${e}/api/memory/${encodeURIComponent(p)}`,{method:"DELETE",headers:{authorization:`Bearer ${o}`}}).catch(()=>{});l.length>0&&pe(n??!1,`KB 清理 ${i}: ${l.length} 条`)}catch(o){console.warn(`[eval] KB 清理跳过 ${i}: ${o.message}`)}}function op(){let e=new Date,t=(r,n=2)=>String(r).padStart(n,"0");return`${e.getFullYear()}${t(e.getMonth()+1)}${t(e.getDate())}-${t(e.getHours())}${t(e.getMinutes())}${t(e.getSeconds())}`}async function ai(e){let t=await Jt(e.dataset),r=Mo(t);console.log(`✅ 数据集校验通过: ${t.suite.name}(${t.dir})`),console.log(` datasetHash: ${t.datasetHash.slice(0,12)} rubricHash: ${t.rubricHash.slice(0,12)}`),console.log(` 词表: ${t.manifest?`tools=${t.manifest.tools.size} cards=${t.manifest.cards.size}(tools-manifest.yaml)`:"未提供(跳过词表校验)"}`),console.log(` 用例: ${r.total}(参评 ${r.evaluated}) 多轮: ${r.multiTurnCases} soft 模式: ${r.softModeCases}`);let n=Object.entries(r.skippedByReason);n.length>0&&console.log(` skip: ${n.map(([a,c])=>`${a}=${c}`).join(" ")}`);let s=Object.entries(r.byPriority).sort(([a],[c])=>a.localeCompare(c));console.log(` priority: ${s.map(([a,c])=>`${a}=${c}`).join(" ")}`);let i=Object.entries(r.sessionHistogram).sort(([a],[c])=>Number(a)-Number(c));console.log(` 会话数分布: ${i.map(([a,c])=>`${a}会话=${c}`).join(" ")}`);let o=Object.entries(r.byCaseType).sort(([a],[c])=>a.localeCompare(c));console.log(` case_type: ${o.map(([a,c])=>`${a}=${c}`).join(" ")}`)}async function ci(e){let t=await ii({...e,cwd:process.cwd()});process.exitCode=t.exitCode}async function li(e){let t=process.cwd();if(!Ar(t))throw new Error("当前目录不是应用根(缺 apps/server/package.json);请在生成应用目录执行");let r=await ri({appDir:t,port:e.port,build:e.build,detached:e.detached===!0});if(e.detached){console.log(`✅ server 运行中 ${r.state.baseUrl}(pid=${r.state.pid},日志 .tbox-server.log,journal .eval-journal/)`),console.log(" 停止: tbox-app stop 评测: tbox-app eval run --dataset <dir>");return}let n=r.child,s=i=>{n.kill(i)};process.on("SIGINT",()=>s("SIGINT")),process.on("SIGTERM",()=>s("SIGTERM")),console.log(`✅ server 运行中 ${r.state.baseUrl}(前台,Ctrl+C 停止)`),await new Promise(i=>{n.on("exit",()=>i())}),await Ht(t),console.log("server 已退出")}import{spawnSync as ip}from"child_process";import{existsSync as ap}from"fs";import{join as cp}from"path";async function pi(){let e=process.cwd(),t=tt(e);if(t){if(t.detached)await ni(e,t);else{console.log(`server 运行中(前台 pid=${t.pid},${t.baseUrl})——在其终端 Ctrl+C 停止`);return}console.log(`✅ 已停止(pid=${t.pid})`);return}let r=cp(e,"scripts","stop.sh");if(ap(r)){let n=ip("bash",["scripts/stop.sh"],{stdio:"inherit"});if(n.status!==0)throw new Error(`scripts/stop.sh 退出码 ${n.status}`);return}console.log("未发现运行中的 server(无 .tbox-server.json)")}function dp(){let e=new lp,t=pp(import.meta.url)("../package.json");e.name("tbox-app").description("tbox 组件化应用 CLI:starter / create / module add|remove|list|sync|diff|doctor / start|stop|eval").version(t.version),e.command("create <target>").description("从模板生成多包 workspace 应用骨架").option("--name <package-name>","生成应用 package.json.name(当前目录初始化时建议显式指定)").option("--source <路径>","模板源(本地目录 / 模板 pack tgz / registry 包 @scope/pkg[@version])").option("--local-deps <tgz目录>","注入平台 overrides(file: 本地发布态 tgz,install 离线验证态;生产 B 档不传)").option("--config-dir <目录>","合并应用配置目录进应用 config/(同名覆盖/异名保留;可重复传,后者覆盖前者同名文件——独立完整配置档单目录注入为主流用法;通用能力,与模板/registry 源正交)",(o,a)=>[...a,o],[]).option("--env-file <路径>","环境变量文件(结合 --config-dir 使用:拷入应用 config/env.sh——启动脚本 source 的档位环境;镜像部署链 build-app-image 使用)",o=>o).option("--registry <url>","拉取 registry(registry 源时生效;缺省自动解析环境镜像)").option("--force","覆盖已存在目录").action(async(o,a)=>{try{await cn({name:o,appName:a.name,source:a.source??"",force:a.force,localDeps:a.localDeps,configDir:a.configDir,envFile:a.envFile,registry:a.registry})}catch(c){console.error("❌",c.message),process.exitCode=1}}),e.command("starter").description("查询 starter 文档与可用类型").option("--type <agent|agent-mall|agent-support>","starter 类型").option("--list","列出可用 starter 类型").option("--json","以 JSON 输出(仅配合 --list)").action(o=>{try{So(o)}catch(a){console.error("❌",a.message),process.exitCode=1}});let r=e.command("module").description("模块管理(add/remove/list/sync/diff/doctor/update/publish/pack)");r.command("add <pkg>").description("安装/展开模块(--mode local|codegen|sdk;--source 支持目录/tgz/registry 包)").option("--mode <local|codegen|sdk>","分发模式","codegen").option("--source <路径>","模块源(本地目录/tgz/registry 包 @scope/pkg[@version])").option("--registry <url>","拉取 registry(registry 源时生效;缺省自动解析环境镜像)").option("--no-deps","跳过依赖自动解析(P3 W3-B 逃生门)").action(async(o,a)=>{try{await _s({pkg:o,mode:a.mode,source:a.source,registry:a.registry,noDeps:!a.deps})}catch(c){console.error("❌",c.message),process.exitCode=1}}),r.command("remove <id>").description("卸载模块(删包 + 清理装配)").option("--force","忽略反向依赖检查强制移除").action(async(o,a)=>{try{await Vs(o,{force:a.force})}catch(c){console.error("❌",c.message),process.exitCode=1}}),r.command("list").description("列出已装模块").action(async()=>{try{await zs()}catch(o){console.error("❌",o.message),process.exitCode=1}}),r.command("sync").description("增量装配 4 文件(不覆盖;结构破坏降级为告警)").option("--force","全量覆盖装配文件(002 §6.5:唯一覆盖入口)").action(async o=>{try{await Js({force:o.force})}catch(a){console.error("❌",a.message),process.exitCode=1}}),r.command("diff [module]").description("装配漂移双向 diff(module 可指定,默认全部)").action(async o=>{try{await Us(o)}catch(a){console.error("❌",a.message),process.exitCode=1}}),r.command("doctor").description("结构校验(doctor 完整版 20 条规则)").option("--json","只输出 JSON 结果").option("--only <规则列表>","只运行指定规则(逗号分隔)").option("--skip <规则列表>","跳过指定规则(逗号分隔)").action(async o=>{try{await Bs(o)}catch(a){console.error("❌",a.message),process.exitCode=1}}),r.command("update <module>").description("升级组件(codegen→3-way merge;sdk→pnpm update)").option("--dry-run","只打印合并结果不写回").option("--ours","冲突快速取本地版本").option("--theirs","冲突快速取新版版本").option("--source <路径>","新版本地源目录或 tgz").option("--base-source <路径>","base 本地源目录或 tgz").action(async(o,a)=>{try{await qs({module:o,...a})}catch(c){console.error("❌",c.message),process.exitCode=1}}),r.command("pack <module>").description("本地打包不发布(模块目录如 modules/module-member;pnpm pack 内建归一化 → 发布态 tgz)").requiredOption("--out <dir>","产物目录(pnpm 自动创建,同名覆盖写)").option("--check","产物断言(协议残留 / exports / 白名单 / 泄漏 / 文件一致性)").action(async(o,a)=>{try{await Qs({module:o,out:a.out,check:a.check})}catch(c){console.error("❌",c.message),process.exitCode=1}}),r.command("publish <module>").description("模块晋升 npm(模块目录如 modules/module-member;校验 + 打包 + 产物门禁 + pnpm publish <tgz>)").option("--tgz <path>","复用已验证产物(缺省现场 pack 到临时目录)").option("--dry-run","校验 + 门禁 + 打印,不真实发布").option("--access <public|restricted>","npm access","public").option("--registry <url>","发布 registry(缺省 pnpm 配置解析:@tbox.cn scope 优先)").action(async(o,a)=>{try{await ro({module:o,tgz:a.tgz,dryRun:a.dryRun,access:a.access,registry:a.registry})}catch(c){console.error("❌",c.message),process.exitCode=1}});let n=e.command("miniapp-container").description("小程序容器管理(init)");e.command("dev").description("原地快速开发调试(真源直挂:装配物化 + 包身份种植 + 配置面注入;改源码即热重启)").option("--template <dir>","模板/应用根目录(相对仓库根;缺省 mall 模板)").option("--module <dir>","仓库模块目录,可多次传入(依赖闭包自动展开)",(o,a)=>[...a,o],[]).option("--real-env <tier>","real-env 档位(wanda|joycity|mock):config 重定向 + provider 纳入 + env 防呆").option("--config-dir <目录>","独立完整配置档:三路配置(integrations/deployments/config dir)独占注入该目录,不与档位主档叠加(可重复传,后者覆盖前者)。常用 .real-env/config/wanda-intranet 切内网端点",(o,a)=>[...a,o],[]).option("--link-sdk","平台真源在场断言(重定向总表恒含 app-sdk/contracts 兜底;本旗标为显式 identity 强化)").option("--port <n>","服务端口(缺省 8000)",o=>Number(o)).option("--prune","清理构件区与种植链接后退出").action(async o=>{try{await xo(o)}catch(a){console.error("❌",a.message),process.exitCode=1}});let s=e.command("provider").description("Provider 绑定管理(bind/unbind/use/unuse/migrate——写 config/integrations.json)");s.command("bind <service> <provider> [implementation]").description("绑定服务槽:三参精确钉版(parking.query joycity joycity-c-parking@1);两参派生(implementation 经 catalog 唯一供给推导)").option("--instance <mallId>","per-instance 覆盖位键(mall 场景 = mallId);缺省写槽级默认位").action(async(o,a,c,l)=>{try{await io(o,a,c,{instance:l.instance})}catch(p){console.error("❌",p.message),process.exitCode=1}}),s.command("use <provider>").description("设置默认厂商:root(应用全局)或 --domain(域级);implementation 恒派生,激活仍需槽 instances 在场").option("--domain <domain>","写域级默认(domains.<域前缀>.provider);缺省写应用全局 root.provider").action(async(o,a)=>{try{await ao(o,{domain:a.domain})}catch(c){console.error("❌",c.message),process.exitCode=1}}),s.command("unuse").description("清除默认厂商:root 或 --domain(空域对象/空 domains 一并清除)").option("--domain <domain>","仅清除该域级默认;缺省清除应用全局 root.provider").action(async o=>{try{await co({domain:o.domain})}catch(a){console.error("❌",a.message),process.exitCode=1}}),s.command("unbind <service>").description("解绑服务槽(--instance 删实例覆盖位;缺省槽与实例集删除)").option("--instance <mallId>","仅删除该实例覆盖位(回落槽级默认)").action(async(o,a)=>{try{await lo(o,{instance:a.instance})}catch(c){console.error("❌",c.message),process.exitCode=1}}),s.command("migrate").description("integrations v2 一次性迁移:旧单串 providerId → 双字段(缺省 dry-run,--write 落盘)").option("--write","落盘(缺省 dry-run 仅报告)").action(async o=>{try{await fo({write:o.write})}catch(a){console.error("❌",a.message),process.exitCode=1}}),n.command("init [platform]").description("初始化小程序容器到 apps/(缺省 alipay;--source 支持目录/tgz/registry 包)").option("--source <source>","容器源:目录 / tgz / registry 包(缺省 @tbox.cn/app-miniapp-container-<platform>)").option("--registry <registry>","拉取 registry(registry 源时生效;缺省自动解析环境镜像)").option("--force","已存在时删除重展开").action(async(o,a)=>{try{await no({platform:o,source:a.source,registry:a.registry,force:a.force})}catch(c){console.error("❌",c.message),process.exitCode=1}}),e.command("start").description("启动本应用 server(编排语义;前台或 -d 后台;不设 NODE_ENV=production)").option("-d","后台运行(日志 .tbox-server.log,状态 .tbox-server.json)").option("--port <n>","端口(缺省 8000)","8000").option("--build","先构建 apps/server(tsup)").action(async o=>{try{await li({detached:o.d,port:Number(o.port),build:o.build})}catch(a){console.error("❌",a.message),process.exitCode=1}}),e.command("stop").description("停止本应用 server(状态文件优先,scripts/stop.sh 兜底;幂等)").action(async()=>{try{await pi()}catch(o){console.error("❌",o.message),process.exitCode=1}});let i=e.command("eval").description("智能体行为评测(validate 契约校验 | run 评测编排)");return i.command("validate").description("校验评测数据集契约(零网络零进程;迁移 QA 与 nightly 候选)").requiredOption("--dataset <dir>","数据集目录(含 suite.yaml/rubric.yaml/cases/)").action(async o=>{try{await ai({dataset:o.dataset})}catch(a){console.error("❌",a.message),process.exitCode=1}}),i.command("run").description("执行评测(纯客户端;实例经 --base-url 或 .tbox-server.json 发现)").requiredOption("--dataset <dir>","数据集目录(必传——显式优于聪明)").option("--base-url <url>","外部实例地址(缺省读 <cwd>/.tbox-server.json)").option("--filter <k=v>","过滤用例(priority=P0 / tag=memory / id=<id>;可重复,AND)",(o,a)=>[...a,o],[]).option("--concurrency <n>","并发用例数(缺省 2;wanda 沙箱限速未知时保守起步)","2").option("--no-judge","跳过 text 维 LLM 判定(纯路由快速回路)").option("--baseline <report.json>","基线报告对比(新失败/已修复/翻转)").option("--rerun-failed <runDir>","只重跑上次 run 中 fail+inconclusive 的用例").option("--journal-root <dir>","显式 journal 根(--base-url 模式的 ingest 供给;缺席则降级)").option("--out <dir>","报告目录覆盖(缺省 <cwd>/.eval/runs/<ts>-<runId>)").option("--max <n>","截断用例数(调试用)").option("--quiet","静默进度输出").action(async o=>{try{await ci({dataset:o.dataset,baseUrl:o.baseUrl,filters:o.filter,concurrency:Number(o.concurrency),judge:o.judge,baselinePath:o.baseline,rerunFailedDir:o.rerunFailed,journalRoot:o.journalRoot,outDir:o.out,max:o.max?Number(o.max):void 0,quiet:o.quiet??!1})}catch(a){console.error("❌",a.message),process.exitCode=1}}),e}var fp=typeof process.argv[1]=="string"&&ui(up(import.meta.url))===ui(process.argv[1]);fp&&dp().parseAsync(process.argv);export{dp as createProgram};
252
+ (上次输出无法解析为 JSON,请只输出 JSON,不要任何其他文字)`,u;try{u=await i(`${e.baseUrl}/chat/completions`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${e.apiKey}`,"accept-encoding":"identity"},body:JSON.stringify({model:e.model,temperature:0,messages:l===0?o:[o[0],{role:"user",content:p}]})})}catch(f){throw new Error(`judge LLM 请求失败: ${f.message}`)}if(!u.ok){let f=await u.text().catch(()=>"");throw new Error(`judge LLM HTTP ${u.status}: ${f.slice(0,300)}`)}if(a=(await u.json().catch(()=>{}))?.choices?.[0]?.message?.content??"",!!a.trim())try{return{parsed:n.parse(JSON.parse(Kl(a))),raw:a}}catch{}}throw new Error(`judge 输出无法解析为 JSON(${c} 次尝试): ${a.slice(0,300)||"<空响应>"}`)}var Gl=_e.object({assertions:_e.array(_e.object({text:_e.string().min(1),verdict:_e.enum(["pass","fail","unclear"]),reason:_e.string().min(1)})).min(1)});function ql(e,t,r){let n=["你是智能体行为评测裁判。依据评审标准,对每条断言独立判定 pass/fail/unclear。","判定基于证据中的实际回复与工具出参(判「如实」而非「应然」)。","证据轨别:tools 是模型主动调用;preTools 是系统预执行(非模型决策);__tbox_ 前缀是框架伪工具。判定「模型是否调用/误路由」类断言时只依据 tools。","断言按语义满足判定,不逐字匹配文案;断言与评审标准冲突、或断言前提在当前对话不成立时(如要求重试建议但重试已成功),以评审标准和实际行为为准。","证据不足或断言在当前对话中无法验证时判 unclear,不要猜测。",'只输出 JSON:{"assertions":[{"text":"断言原文","verdict":"pass|fail|unclear","reason":"判定理由"}]}',"","评审标准:",...r.standards.map((o,a)=>/^\d+[.、.]\s*/.test(o)?o:`${a+1}. ${o}`)].join(`
253
+ `),s=t.turns.map((o,a)=>({turn:a+1,...Yo(o)})),i=[`用例 ${e.id}(priority=${e.priority})`,`证据:${JSON.stringify(s)}`,"断言:",...e.assertions.map((o,a)=>`${a+1}. ${o}`)];return e.judge_hints.length>0&&i.push("评审备注(附加上下文,优先级低于评审标准):",...e.judge_hints.map(o=>`- ${o}`)),i.push("逐条输出判定 JSON。"),{system:n,user:i.join(`
254
+ `)}}function ei(e){let t=e.some(n=>n.verdict==="fail"),r=e.some(n=>n.verdict==="pass");return t?{status:"fail",failures:e.filter(n=>n.verdict==="fail").map(n=>`${n.text} —— ${n.reason}`)}:r?{status:"pass",failures:[]}:{status:"inconclusive",failures:[]}}async function ti(e,t,r,n,s){let{system:i,user:o}=ql(r,n,t),{parsed:a,raw:c}=await Qo(e,i,o,Gl,s),l=new Map(a.assertions.map(u=>[u.text.trim(),u]));return{verdicts:r.assertions.map(u=>l.get(u.trim())??{text:u,verdict:"unclear",reason:"judge 输出缺失该断言"}),raw:c}}import{spawn as ri,spawnSync as Xl}from"child_process";import{existsSync as si,openSync as Yl,readFileSync as Zl}from"fs";import{rm as Ql,writeFile as ep}from"fs/promises";import{join as be}from"path";var Or="apps/server",Ar="dist/index.js",Pr=".tbox-server.json",ni=".tbox-server.log",oi=60,tp=1e3;function Lr(e){return si(be(e,Or,"package.json"))?e:null}function tt(e){let t;try{t=Zl(be(e,Pr),"utf-8")}catch{return null}try{return Mo.parse(JSON.parse(t))}catch{return null}}async function rp(e,t){await ep(be(e,Pr),JSON.stringify(t,null,2),"utf-8")}async function Kt(e){await Ql(be(e,Pr),{force:!0})}function np(e){return`${e.replace(/\/$/,"")}/api/health`}async function Ht(e,t){let r=t?.attempts??oi,n=t?.intervalMs??tp;for(let s=0;s<r;s++){try{if((await fetch(np(e))).ok)return!0}catch{}await new Promise(i=>setTimeout(i,n))}return!1}async function ii(e){if(!Lr(e.appDir))throw new Error(`当前目录不是应用根(缺 ${Or}/package.json): ${e.appDir}`);let t=be(e.appDir,Or),r=be(t,Ar);if(e.build){let l=Xl("pnpm",["--filter","@app/server","build"],{cwd:e.appDir,stdio:"inherit"});if(l.status!==0)throw new Error(`构建失败(pnpm --filter @app/server build,exit=${l.status})`)}if(!si(r))throw new Error("应用未构建:先 --build,或使用 `tbox-app eval run --base-url` 评测外部实例");let n=tt(e.appDir);if(n&&await Ht(n.baseUrl,{attempts:2,intervalMs:500}))throw new Error(`已在运行 ${n.baseUrl}(pid=${n.pid});tbox-app stop 后再启动`);await Kt(e.appDir);let s=e.port??8e3,i=be(e.appDir,".eval-journal"),o={version:1,pid:0,port:s,baseUrl:`http://127.0.0.1:${s}`,journalRoot:i,startedAt:new Date().toISOString(),detached:e.detached},a;if(e.detached){let l=Yl(be(e.appDir,ni),"a");a=ri("node",[Ar],{cwd:t,env:{...process.env,PORT:String(s),TBOX_LOCAL_LOG:"on",TBOX_LOCAL_LOG_DIR:i,TBOX_APP_ID:"eval"},stdio:["ignore",l,l],detached:!0}),a.unref()}else a=ri("node",[Ar],{cwd:t,env:{...process.env,PORT:String(s),TBOX_LOCAL_LOG:"on",TBOX_LOCAL_LOG_DIR:i,TBOX_APP_ID:"eval"},stdio:"inherit"});if(o.pid=a.pid??0,!await Ht(o.baseUrl)){try{e.detached?process.kill(-o.pid,"SIGKILL"):a.kill("SIGKILL")}catch{}throw new Error(`server ${oi}s 未就绪(${o.baseUrl};日志 ${ni})`)}if(!(()=>{try{return process.kill(o.pid,0),!0}catch{return!1}})()||!e.detached&&a.exitCode!==null)throw new Error(`端口 ${s} 已被其他进程占用(health 来自占用者);--port 换端口后重试`);return await rp(e.appDir,o),{child:a,state:o}}async function ai(e,t){await sp(t.pid,t.detached,void 0),await Kt(e)}async function sp(e,t,r){let n=()=>{try{return process.kill(e,0),!0}catch{return!1}};if(!n())return;if(t)try{process.kill(-e,"SIGTERM")}catch{}else{r?.kill("SIGTERM");try{process.kill(e,"SIGTERM")}catch{}}let s=Date.now()+2e3;for(;n()&&Date.now()<s;)await new Promise(i=>setTimeout(i,100));if(n())try{t?process.kill(-e,"SIGKILL"):process.kill(e,"SIGKILL")}catch{}}var li=5;function pe(e,t){e||console.log(`[eval] ${t}`)}function ap(e,t){if(t.length===0)return e;let r=new Map;for(let s of t){let i=s.indexOf("=");if(i<=0)throw new Error(`--filter 形状非法: "${s}"(应为 key=value)`);let o=s.slice(0,i),a=s.slice(i+1);if(!["priority","tag","id","skip"].includes(o))throw new Error(`--filter 未知键: "${o}"(支持 priority/tag/id/skip)`);let c=r.get(o)??[];c.push({key:o,value:a}),r.set(o,c)}let n=(s,i,o)=>{switch(i){case"priority":return s.priority===o;case"id":return s.id===o;case"tag":return s.tags.includes(o);case"skip":return s.skip===o;default:return!1}};return e.filter(s=>[...r.values()].every(i=>i.some(o=>n(s,o.key,o.value))))}async function pi(e){if(e.max!==void 0&&(!Number.isInteger(e.max)||e.max<1))throw new Error("--max 需为 ≥1 的整数");if(!Number.isInteger(e.concurrency)||e.concurrency<1)throw new Error("--concurrency 需为 ≥1 的整数");let t=await Ut(e.dataset),r=ap(t.cases,e.filters);if(e.rerunFailedDir){let w=await ci(Fr(e.rerunFailedDir,"report.json"),"utf-8"),D=Qe.parse(JSON.parse(w)),M=new Set(D.cases.filter(b=>b.status==="fail"||b.status==="inconclusive").map(b=>b.id));r=r.filter(b=>M.has(b.id)),r.length===0&&pe(e.quiet,"--rerun-failed: 上次无 fail/inconclusive 用例,空跑")}e.max!==void 0&&(r=r.slice(0,e.max));let n,s=null,i=null,o=e.journalRoot??null;if(e.baseUrl)n=e.baseUrl.replace(/\/$/,"");else{let w=tt(e.cwd);if(!w)throw new Error("未发现可用实例:先 `tbox-app start -d`(状态文件 .tbox-server.json)或传 --base-url <url>");if(!await Ht(w.baseUrl,{attempts:3,intervalMs:500}))throw new Error(`状态文件实例不可达(${w.baseUrl}):实例可能已退出,重新 start -d 或传 --base-url`);n=w.baseUrl,s=w.pid,i=w.startedAt,o=o??w.journalRoot}let a=e.judge?Zo(process.env):null,c=op(4).toString("hex"),l=`eval-${c}`,p=e.outDir??Fr(e.cwd,".eval","runs",`${lp()}-${c}`),u=new Date().toISOString();pe(e.quiet,`runId=${c} dataset=${t.suite.name} cases=${r.length} concurrency=${e.concurrency} judge=${a?a.model:"off"}`),pe(e.quiet,`instance=${n}${o?` journal=${o}`:"(journal 缺席,direct-out 降级)"}`);let d=[];for(let w of r)w.skip&&d.push({spec:w,dims:[]});let f=new Map,g=new Map,m=0,h=0,v=!1,S=0,$=r.filter(w=>!w.skip),R=[...$],F=async()=>{for(;;){if(v)return;let w=R.shift();if(!w)return;let D=`eval-${c}-${w.id}`,M,b;try{M=await Vo({baseUrl:n,driver:t.suite.driver??"agui",...e.deps},w,D,c,t.suite.defaultTurnTimeoutMs),o&&(M=await Jo(M,o)),f.set(w.id,M)}catch(j){if(j instanceof H){m+=1,h+=1,h>=li&&(v=!0),d.push({spec:w,dims:[{dim:"run",status:"fail",detail:[j.message]}]}),pe(e.quiet,`✗ ${w.id} infra: ${j.message}`),v&&pe(e.quiet,`熔断(连续 ${li} 个 infra 错误),中止余量 ${R.length} 例`);continue}throw j}h=0;let k=Uo(w,M,t.suite.driver??"agui");if(a)try{let{verdicts:j,raw:ee}=await ti(a,t.rubric,w,M,e.deps);g.set(w.id,ee),b=ei(j)}catch(j){S+=1,b={status:"inconclusive",failures:[`judge 调用失败: ${j.message}`]},pe(e.quiet,`⚠ ${w.id} judge 失败: ${j.message}`)}d.push({spec:w,trace:M,dims:k,textStatus:b?.status,textFailures:b?.failures});let O=k.filter(j=>j.status==="fail").map(j=>j.dim);pe(e.quiet,`${O.length>0||b?.status==="fail"?"✗":"✓"} ${w.id}${O.length>0?` (${O.join(",")}${b?.status==="fail"?",text":""})`:""}`)}};await Promise.all(Array.from({length:Math.max(1,Math.min(e.concurrency,16))},F));for(let w of $)d.some(D=>D.spec.id===w.id)||d.push({spec:w,dims:[],notExecuted:!0});let A=[...f.values()].reduce((w,D)=>w+(D.journal?.inputTokens??0)+(D.journal?.outputTokens??0),0);await cp(n,$.map(w=>`eval-${c}-${w.id}`),e.deps?.fetchFn,e.quiet);let N=Go({runId:c,startedAt:u,finishedAt:new Date().toISOString(),datasetName:t.suite.name,datasetHash:t.datasetHash,rubricHash:t.rubricHash,judgeModel:a?.model??null,instance:{baseUrl:n,pid:s,startedAt:i,journalRoot:o,degraded:!o},devUserPrefix:l,results:d,ops:{infraErrors:m,aborted:v,llmTokens:A>0?A:null,judgeFailures:S}}),P;if(e.baselinePath){let w=await ci(e.baselinePath,"utf-8"),D=Qe.parse(JSON.parse(w));P=qo(N,D)}return await ip(p,{recursive:!0}),await Xo(p,N,f,g),console.log(`报告: ${Fr(p,"report.md")}`),process.env.EVAL_REPORT==="json"&&console.log(JSON.stringify(N)),P&&pe(e.quiet,`基线对比: 新失败=${P.newFailed.length} 已修复=${P.fixed.length} 翻转=${P.flipped.length}`),{exitCode:v?2:0,runDir:p,report:N}}async function cp(e,t,r,n){let s=r??fetch;for(let i of t)try{let o=await Ir(e,i,s),a=await s(`${e}/api/memory`,{headers:{authorization:`Bearer ${o}`}});if(!a.ok)continue;let l=((await a.json().catch(()=>{}))?.records??[]).map(p=>p.id).filter(p=>typeof p=="string");for(let p of l)await s(`${e}/api/memory/${encodeURIComponent(p)}`,{method:"DELETE",headers:{authorization:`Bearer ${o}`}}).catch(()=>{});l.length>0&&pe(n??!1,`KB 清理 ${i}: ${l.length} 条`)}catch(o){console.warn(`[eval] KB 清理跳过 ${i}: ${o.message}`)}}function lp(){let e=new Date,t=(r,n=2)=>String(r).padStart(n,"0");return`${e.getFullYear()}${t(e.getMonth()+1)}${t(e.getDate())}-${t(e.getHours())}${t(e.getMinutes())}${t(e.getSeconds())}`}async function ui(e){let t=await Ut(e.dataset),r=Po(t);console.log(`✅ 数据集校验通过: ${t.suite.name}(${t.dir})`),console.log(` datasetHash: ${t.datasetHash.slice(0,12)} rubricHash: ${t.rubricHash.slice(0,12)}`),console.log(` 词表: ${t.manifest?`tools=${t.manifest.tools.size} cards=${t.manifest.cards.size}(tools-manifest.yaml)`:"未提供(跳过词表校验)"}`),console.log(` 用例: ${r.total}(参评 ${r.evaluated}) 多轮: ${r.multiTurnCases} soft 模式: ${r.softModeCases}`);let n=Object.entries(r.skippedByReason);n.length>0&&console.log(` skip: ${n.map(([a,c])=>`${a}=${c}`).join(" ")}`);let s=Object.entries(r.byPriority).sort(([a],[c])=>a.localeCompare(c));console.log(` priority: ${s.map(([a,c])=>`${a}=${c}`).join(" ")}`);let i=Object.entries(r.sessionHistogram).sort(([a],[c])=>Number(a)-Number(c));console.log(` 会话数分布: ${i.map(([a,c])=>`${a}会话=${c}`).join(" ")}`);let o=Object.entries(r.byCaseType).sort(([a],[c])=>a.localeCompare(c));console.log(` case_type: ${o.map(([a,c])=>`${a}=${c}`).join(" ")}`)}async function di(e){let t=await pi({...e,cwd:process.cwd()});process.exitCode=t.exitCode}async function fi(e){let t=process.cwd();if(!Lr(t))throw new Error("当前目录不是应用根(缺 apps/server/package.json);请在生成应用目录执行");let r=await ii({appDir:t,port:e.port,build:e.build,detached:e.detached===!0});if(e.detached){console.log(`✅ server 运行中 ${r.state.baseUrl}(pid=${r.state.pid},日志 .tbox-server.log,journal .eval-journal/)`),console.log(" 停止: tbox-app stop 评测: tbox-app eval run --dataset <dir>");return}let n=r.child,s=i=>{n.kill(i)};process.on("SIGINT",()=>s("SIGINT")),process.on("SIGTERM",()=>s("SIGTERM")),console.log(`✅ server 运行中 ${r.state.baseUrl}(前台,Ctrl+C 停止)`),await new Promise(i=>{n.on("exit",()=>i())}),await Kt(t),console.log("server 已退出")}import{spawnSync as pp}from"child_process";import{existsSync as up}from"fs";import{join as dp}from"path";async function mi(){let e=process.cwd(),t=tt(e);if(t){if(t.detached)await ai(e,t);else{console.log(`server 运行中(前台 pid=${t.pid},${t.baseUrl})——在其终端 Ctrl+C 停止`);return}console.log(`✅ 已停止(pid=${t.pid})`);return}let r=dp(e,"scripts","stop.sh");if(up(r)){let n=pp("bash",["scripts/stop.sh"],{stdio:"inherit"});if(n.status!==0)throw new Error(`scripts/stop.sh 退出码 ${n.status}`);return}console.log("未发现运行中的 server(无 .tbox-server.json)")}function yp(){let e=new fp,t=mp(import.meta.url)("../package.json");e.name("tbox-app").description("tbox 组件化应用 CLI:starter / create / module add|remove|list|sync|diff|doctor / start|stop|eval").version(t.version),e.command("create <target>").description("从模板生成多包 workspace 应用骨架").option("--name <package-name>","生成应用 package.json.name(当前目录初始化时建议显式指定)").option("--source <路径>","模板源(本地目录 / 模板 pack tgz / registry 包 @scope/pkg[@version])").option("--local-deps <tgz目录>","注入平台 overrides(file: 本地发布态 tgz,install 离线验证态;生产 B 档不传)").option("--config-dir <目录>","合并应用配置目录进应用 config/(同名覆盖/异名保留;可重复传,后者覆盖前者同名文件——独立完整配置档单目录注入为主流用法;通用能力,与模板/registry 源正交)",(o,a)=>[...a,o],[]).option("--env-file <路径>","环境变量文件(结合 --config-dir 使用:拷入应用 config/env.sh——启动脚本 source 的档位环境;镜像部署链 build-app-image 使用)",o=>o).option("--registry <url>","拉取 registry(registry 源时生效;缺省自动解析环境镜像)").option("--force","覆盖已存在目录").action(async(o,a)=>{try{await dn({name:o,appName:a.name,source:a.source??"",force:a.force,localDeps:a.localDeps,configDir:a.configDir,envFile:a.envFile,registry:a.registry})}catch(c){console.error("❌",c.message),process.exitCode=1}}),e.command("starter").description("查询 starter 文档与可用类型").option("--type <agent|agent-mall|agent-support>","starter 类型").option("--list","列出可用 starter 类型").option("--json","以 JSON 输出(仅配合 --list)").action(o=>{try{Ro(o)}catch(a){console.error("❌",a.message),process.exitCode=1}});let r=e.command("module").description("模块管理(add/remove/list/sync/diff/doctor/update/publish/pack)");r.command("add <pkg>").description("安装/展开模块(--mode local|codegen|sdk;--source 支持目录/tgz/registry 包)").option("--mode <local|codegen|sdk>","分发模式","codegen").option("--source <路径>","模块源(本地目录/tgz/registry 包 @scope/pkg[@version])").option("--registry <url>","拉取 registry(registry 源时生效;缺省自动解析环境镜像)").option("--no-deps","跳过依赖自动解析(P3 W3-B 逃生门)").action(async(o,a)=>{try{await zs({pkg:o,mode:a.mode,source:a.source,registry:a.registry,noDeps:!a.deps})}catch(c){console.error("❌",c.message),process.exitCode=1}}),r.command("remove <id>").description("卸载模块(删包 + 清理装配)").option("--force","忽略反向依赖检查强制移除").action(async(o,a)=>{try{await Bs(o,{force:a.force})}catch(c){console.error("❌",c.message),process.exitCode=1}}),r.command("list").description("列出已装模块").action(async()=>{try{await Hs()}catch(o){console.error("❌",o.message),process.exitCode=1}}),r.command("sync").description("增量装配 4 文件(不覆盖;结构破坏降级为告警)").option("--force","全量覆盖装配文件(002 §6.5:唯一覆盖入口)").action(async o=>{try{await Ws({force:o.force})}catch(a){console.error("❌",a.message),process.exitCode=1}}),r.command("diff [module]").description("装配漂移双向 diff(module 可指定,默认全部)").action(async o=>{try{await Ks(o)}catch(a){console.error("❌",a.message),process.exitCode=1}}),r.command("doctor").description("结构校验(doctor 完整版 20 条规则)").option("--json","只输出 JSON 结果").option("--only <规则列表>","只运行指定规则(逗号分隔)").option("--skip <规则列表>","跳过指定规则(逗号分隔)").action(async o=>{try{await Gs(o)}catch(a){console.error("❌",a.message),process.exitCode=1}}),r.command("update <module>").description("升级组件(codegen→3-way merge;sdk→pnpm update)").option("--dry-run","只打印合并结果不写回").option("--ours","冲突快速取本地版本").option("--theirs","冲突快速取新版版本").option("--source <路径>","新版本地源目录或 tgz").option("--base-source <路径>","base 本地源目录或 tgz").action(async(o,a)=>{try{await Qs({module:o,...a})}catch(c){console.error("❌",c.message),process.exitCode=1}}),r.command("pack <module>").description("本地打包不发布(模块目录如 modules/module-member;pnpm pack 内建归一化 → 发布态 tgz)").requiredOption("--out <dir>","产物目录(pnpm 自动创建,同名覆盖写)").option("--check","产物断言(协议残留 / exports / 白名单 / 泄漏 / 文件一致性)").action(async(o,a)=>{try{await no({module:o,out:a.out,check:a.check})}catch(c){console.error("❌",c.message),process.exitCode=1}}),r.command("publish <module>").description("模块晋升 npm(模块目录如 modules/module-member;校验 + 打包 + 产物门禁 + pnpm publish <tgz>)").option("--tgz <path>","复用已验证产物(缺省现场 pack 到临时目录)").option("--dry-run","校验 + 门禁 + 打印,不真实发布").option("--access <public|restricted>","npm access","public").option("--registry <url>","发布 registry(缺省 pnpm 配置解析:@tbox.cn scope 优先)").action(async(o,a)=>{try{await io({module:o,tgz:a.tgz,dryRun:a.dryRun,access:a.access,registry:a.registry})}catch(c){console.error("❌",c.message),process.exitCode=1}});let n=e.command("miniapp-container").description("小程序容器管理(init)");e.command("dev").description("原地快速开发调试(真源直挂:装配物化 + 包身份种植 + 配置面注入;改源码即热重启)").option("--template <dir>","模板/应用根目录(相对仓库根;缺省 mall 模板)").option("--module <dir>","仓库模块目录,可多次传入(依赖闭包自动展开)",(o,a)=>[...a,o],[]).option("--real-env <tier>","real-env 档位(wanda|joycity|mock):config 重定向 + provider 纳入 + env 防呆").option("--config-dir <目录>","独立完整配置档:三路配置(integrations/deployments/config dir)独占注入该目录,不与档位主档叠加(可重复传,后者覆盖前者)。常用 .real-env/config/wanda-intranet 切内网端点",(o,a)=>[...a,o],[]).option("--link-sdk","平台真源在场断言(重定向总表恒含 app-sdk/contracts 兜底;本旗标为显式 identity 强化)").option("--port <n>","服务端口(缺省 8000)",o=>Number(o)).option("--prune","清理构件区与种植链接后退出").action(async o=>{try{await Eo(o)}catch(a){console.error("❌",a.message),process.exitCode=1}});let s=e.command("provider").description("Provider 绑定管理(bind/unbind/use/unuse/migrate——写 config/integrations.json)");s.command("bind <service> <provider> [implementation]").description("绑定服务槽:三参精确钉版(parking.query joycity joycity-c-parking@1);两参派生(implementation 经 catalog 唯一供给推导)").option("--instance <mallId>","per-instance 覆盖位键(mall 场景 = mallId);缺省写槽级默认位").action(async(o,a,c,l)=>{try{await po(o,a,c,{instance:l.instance})}catch(p){console.error("❌",p.message),process.exitCode=1}}),s.command("use <provider>").description("设置默认厂商:root(应用全局)或 --domain(域级);implementation 恒派生,激活仍需槽 instances 在场").option("--domain <domain>","写域级默认(domains.<域前缀>.provider);缺省写应用全局 root.provider").action(async(o,a)=>{try{await uo(o,{domain:a.domain})}catch(c){console.error("❌",c.message),process.exitCode=1}}),s.command("unuse").description("清除默认厂商:root 或 --domain(空域对象/空 domains 一并清除)").option("--domain <domain>","仅清除该域级默认;缺省清除应用全局 root.provider").action(async o=>{try{await fo({domain:o.domain})}catch(a){console.error("❌",a.message),process.exitCode=1}}),s.command("unbind <service>").description("解绑服务槽(--instance 删实例覆盖位;缺省槽与实例集删除)").option("--instance <mallId>","仅删除该实例覆盖位(回落槽级默认)").action(async(o,a)=>{try{await mo(o,{instance:a.instance})}catch(c){console.error("❌",c.message),process.exitCode=1}}),s.command("migrate").description("integrations v2 一次性迁移:旧单串 providerId → 双字段(缺省 dry-run,--write 落盘)").option("--write","落盘(缺省 dry-run 仅报告)").action(async o=>{try{await ho({write:o.write})}catch(a){console.error("❌",a.message),process.exitCode=1}}),n.command("init [platform]").description("初始化小程序容器到 apps/(缺省 alipay;--source 支持目录/tgz/registry 包)").option("--source <source>","容器源:目录 / tgz / registry 包(缺省 @tbox.cn/app-miniapp-container-<platform>)").option("--registry <registry>","拉取 registry(registry 源时生效;缺省自动解析环境镜像)").option("--force","已存在时删除重展开").action(async(o,a)=>{try{await ao({platform:o,source:a.source,registry:a.registry,force:a.force})}catch(c){console.error("❌",c.message),process.exitCode=1}}),e.command("start").description("启动本应用 server(编排语义;前台或 -d 后台;不设 NODE_ENV=production)").option("-d","后台运行(日志 .tbox-server.log,状态 .tbox-server.json)").option("--port <n>","端口(缺省 8000)","8000").option("--build","先构建 apps/server(tsup)").action(async o=>{try{await fi({detached:o.d,port:Number(o.port),build:o.build})}catch(a){console.error("❌",a.message),process.exitCode=1}}),e.command("stop").description("停止本应用 server(状态文件优先,scripts/stop.sh 兜底;幂等)").action(async()=>{try{await mi()}catch(o){console.error("❌",o.message),process.exitCode=1}});let i=e.command("eval").description("智能体行为评测(validate 契约校验 | run 评测编排)");return i.command("validate").description("校验评测数据集契约(零网络零进程;迁移 QA 与 nightly 候选)").requiredOption("--dataset <dir>","数据集目录(含 suite.yaml/rubric.yaml/cases/)").action(async o=>{try{await ui({dataset:o.dataset})}catch(a){console.error("❌",a.message),process.exitCode=1}}),i.command("run").description("执行评测(纯客户端;实例经 --base-url 或 .tbox-server.json 发现)").requiredOption("--dataset <dir>","数据集目录(必传——显式优于聪明)").option("--base-url <url>","外部实例地址(缺省读 <cwd>/.tbox-server.json)").option("--filter <k=v>","过滤用例(priority=P0 / tag=memory / id=<id>;可重复,AND)",(o,a)=>[...a,o],[]).option("--concurrency <n>","并发用例数(缺省 2;wanda 沙箱限速未知时保守起步)","2").option("--no-judge","跳过 text 维 LLM 判定(纯路由快速回路)").option("--baseline <report.json>","基线报告对比(新失败/已修复/翻转)").option("--rerun-failed <runDir>","只重跑上次 run 中 fail+inconclusive 的用例").option("--journal-root <dir>","显式 journal 根(--base-url 模式的 ingest 供给;缺席则降级)").option("--out <dir>","报告目录覆盖(缺省 <cwd>/.eval/runs/<ts>-<runId>)").option("--max <n>","截断用例数(调试用)").option("--quiet","静默进度输出").action(async o=>{try{await di({dataset:o.dataset,baseUrl:o.baseUrl,filters:o.filter,concurrency:Number(o.concurrency),judge:o.judge,baselinePath:o.baseline,rerunFailedDir:o.rerunFailed,journalRoot:o.journalRoot,outDir:o.out,max:o.max?Number(o.max):void 0,quiet:o.quiet??!1})}catch(a){console.error("❌",a.message),process.exitCode=1}}),e}var hp=typeof process.argv[1]=="string"&&gi(gp(import.meta.url))===gi(process.argv[1]);hp&&yp().parseAsync(process.argv);export{yp as createProgram};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tbox.cn/app-cli",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "type": "module",
5
5
  "description": "tbox-app CLI:create / module add|remove|list|sync|diff|doctor|update|publish / start|stop|eval 智能体评测(纯函数核心 + commander 薄壳)。",
6
6
  "bin": {