@yinsen/deveco-cli 1.3.3-Test.3 → 1.3.3-Test.4

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 (30) hide show
  1. package/dist/cli.js +4 -4
  2. package/dist/internal/telemetry-upload-background.js +1 -1
  3. package/package.json +56 -56
  4. package/src/resources/aclPermission/aclPermissionsInfo.json +310 -310
  5. package/src/resources/arkts-check.cjs +3642 -3642
  6. package/templates/application/AppScope/app.json5 +10 -10
  7. package/templates/application/AppScope/resources/base/element/string.json +8 -8
  8. package/templates/application/AppScope/resources/base/media/layered_image.json +6 -6
  9. package/templates/application/build-profile.json5 +41 -41
  10. package/templates/application/code-linter.json5 +31 -31
  11. package/templates/application/entry/build-profile.json5 +32 -32
  12. package/templates/application/entry/gitignore.txt +5 -5
  13. package/templates/application/entry/hvigorfile.ts +7 -7
  14. package/templates/application/entry/obfuscation-rules.txt +19 -19
  15. package/templates/application/entry/oh-package.json5 +10 -10
  16. package/templates/application/entry/src/main/ets/entryability/EntryAbility.ets +62 -62
  17. package/templates/application/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +30 -30
  18. package/templates/application/entry/src/main/ets/pages/Index.ets +37 -37
  19. package/templates/application/entry/src/main/module.json5 +49 -49
  20. package/templates/application/entry/src/main/resources/base/element/color.json +7 -7
  21. package/templates/application/entry/src/main/resources/base/element/float.json +8 -8
  22. package/templates/application/entry/src/main/resources/base/element/string.json +15 -15
  23. package/templates/application/entry/src/main/resources/base/media/layered_image.json +6 -6
  24. package/templates/application/entry/src/main/resources/base/profile/backup_config.json +2 -2
  25. package/templates/application/entry/src/main/resources/base/profile/main_pages.json +5 -5
  26. package/templates/application/entry/src/main/resources/dark/element/color.json +7 -7
  27. package/templates/application/gitignore.txt +12 -12
  28. package/templates/application/hvigor/hvigor-config.json5 +23 -23
  29. package/templates/application/hvigorfile.ts +7 -7
  30. package/templates/application/oh-package.json5 +10 -10
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ var Cy=Object.defineProperty;var ky=(r,e)=>{for(var t in e)Cy(r,t,{get:e[t],enum
4
4
  `)}static resolveTimeBounds(e,t,n){let o=e?new Date(n.getTime()-e*1e3):null,i=t?new Date(n.getTime()-t*1e3):null;return o&&i?o<i?[o,i]:[i,o]:o?[o,n]:i?[null,i]:[null,null]}static isWithinBounds(e,t,n){let o=e.getTime(),i=t?Math.floor(t.getTime()/1e3)*1e3:null,s=n?Math.floor(n.getTime()/1e3)*1e3+999:null;return!(i!==null&&o<i||s!==null&&o>s)}static extractTimestampFromLogLine(e,t){let n=e.match(/(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,6}))?/);if(!n)return null;let o=t.getFullYear(),i=Number.parseInt(n[1],10)-1,s=Number.parseInt(n[2],10),a=Number.parseInt(n[3],10),c=Number.parseInt(n[4],10),l=Number.parseInt(n[5],10),d=n[6]??"0",g=Number.parseInt(d.padEnd(3,"0").slice(0,3),10),v=new Date(o,i,s,a,c,l,g);return v.getTime()>t.getTime()+1440*60*1e3&&v.setFullYear(o-1),v}static assertBundleName(e){if(!/^[A-Za-z0-9_.]{1,128}$/.test(e))throw new Error(`Invalid bundleName: ${JSON.stringify(e)}`)}static assertBundleNameStrict(e){if(e.length<7||e.length>128)throw new Error(`Bundle name length must be 7-128 characters. Current: ${e.length}`);if(e.includes(".."))throw new Error('Bundle name cannot contain consecutive dots (e.g., "com..example").');let t=e.split(".");if(t.length<3)throw new Error("Bundle name must contain at least 3 dot-separated segments.");let n=/^[a-zA-Z0-9_]+$/;for(let o=0;o<t.length;o++){let i=t[o];if(!n.test(i))throw new Error(`Segment "${i}" contains invalid characters. Only letters, digits, and underscores allowed.`);if(o===0){if(!/^[a-zA-Z]/.test(i))throw new Error(`First segment "${i}" must start with a letter (a-z, A-Z).`)}else if(!/^[a-zA-Z0-9]/.test(i))throw new Error(`Segment "${i}" must start with a letter or digit.`);if(!/[a-zA-Z0-9]$/.test(i))throw new Error(`Segment "${i}" must end with a letter or digit.`)}}static assertModuleName(e){this.assertSafeName(e,"module name")}static assertAbilityName(e){this.assertSafeName(e,"ability name")}static assertSafeName(e,t){if(!/^[A-Za-z0-9_.]+$/.test(e))throw new Error(`Invalid ${t}: ${JSON.stringify(e)}`)}static assertHilogToken(e,t){if(!/^[A-Za-z0-9_.:\\-]{1,64}$/.test(e))throw new Error(`Invalid ${t}: ${JSON.stringify(e)}`)}static assertHilogKeyword(e){if(e.length===0||e.length>128)throw new Error(`Invalid keyword: ${JSON.stringify(e)}`);if([...e].some(n=>{let o=n.charCodeAt(0);return o<=r.ASCII_CONTROL_MAX||o===r.ASCII_DELETE}))throw new Error(`Invalid keyword: ${JSON.stringify(e)}`)}static quotePosixShellArg(e){let n=`'${e.replace(/'/g,"'\\''")}'`;return u(`quotePosixShellArg: ${e} -> ${n}`),n}static assertCrashFilename(e){if(!/^\w+-[\w.]+-\d+-\d+$/.test(e))throw new Error(`Invalid crash log filename: ${JSON.stringify(e)}`)}static assertHilogLevel(e){if(!/^[DIWEF]$/.test(e))throw new Error(`Invalid log level: ${e}`)}static resolvePathWithinRoot(e,t){if(Se.isAbsolute(t))throw new Error(`Absolute paths are not allowed: ${t}`);let n=Se.resolve(Se.normalize(e),t);return r.ensurePathWithinRoot(e,n)}static ensurePathWithinRoot(e,t){let n=Se.normalize(e),o=Se.relative(n,t);if(o.split(Se.sep)[0]===".."||Se.isAbsolute(o))throw new Error(`Path escapes project root: ${t}`);return t}static isPathEscaping(e){let t=e.replace(/\\/g,"/");return t===".."||t.startsWith("../")||Se.isAbsolute(e)}static isPathContained(e,t){let n=Se.resolve(t,e),o=Se.relative(t,n);return r.isPathEscaping(o)?{contained:!1,reason:`Path traversal project root directory: ${e}`}:{contained:!0}}static isPathContainedWithSymlink(e,t){let n=r.isPathContained(e,t);if(!n.contained)return n;let o;try{o=_a.realpathSync(t)}catch{return{contained:!1,reason:`Project root directory does not exist or cannot be resolved: ${t}`}}let i=Se.resolve(o,e),s;try{s=_a.realpathSync(i)}catch{return{contained:!1,reason:`Path does not exist or cannot be resolved: ${i}`}}return r.isPathContained(s,o)}};import tu from"crypto";import et from"fs";import Ja from"os";import Or from"path";import Ay from"https";var Rd={devecoApiTraceUpload:"https://cn.devecostudio.huawei.com/codeGenie/cli/trace/upload"};var di=class r{static ENDPOINT=Rd.devecoApiTraceUpload;static SENDER="deveco-cli";async upload(e,t){let n={"Content-Type":"application/json",sender:r.SENDER,deviceid:t.replace(/-/g,""),"Content-Length":String(Buffer.byteLength(e,"utf8"))};try{let{body:o}=await this.httpPost(r.ENDPOINT,n,Buffer.from(e,"utf8"),6e4);return r.isSuccess(o)}catch{return!1}}static isSuccess(e){try{let t=JSON.parse(e),n=t?.code??t?.errorCode;return String(n)==="200"}catch{return!1}}async httpPost(e,t,n,o){let i=new URL(e);return new Promise((s,a)=>{let c=Ay.request({protocol:i.protocol,hostname:i.hostname,port:i.port||(i.protocol==="https:"?443:80),path:i.pathname+i.search,method:"POST",headers:t,timeout:o},l=>{let d=[];l.on("data",g=>d.push(g)),l.on("end",()=>{s({code:l.statusCode??0,body:Buffer.concat(d).toString("utf8")})})});c.on("timeout",()=>{c.destroy(new Error("request timeout"))}),c.on("error",a),c.write(n),c.end()})}};var Td={identity:r=>r,camelCase:r=>r,snakeCase:r=>r.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").toLowerCase()},ja=class{constructor(e={}){this.config=e}serialize(e){let t=this.transform(e);return this.config.pretty?JSON.stringify(t,null,2):JSON.stringify(t)}toObject(e){return this.transform(e)}transform(e){if(e==null)return e;if(Array.isArray(e))return e.map(i=>this.transform(i));if(typeof e!="object")return e;let t=this.config.namingStrategy??Td.identity,n=this.config.fieldNames??{},o={};for(let[i,s]of Object.entries(e)){let a=n[i]??t(i);o[a]=this.transform(s)}return o}},xd=new ja({namingStrategy:Td.snakeCase,fieldNames:{}});import to from"crypto";import ui from"fs";import Dy from"path";var pi="aes-256-gcm",Ry=12,Ty="deveco-cli-trace-file",xy="trace-file-secret",Nd=32;function Ld(r){try{let e=ui.readFileSync(r,"utf8").trim();return e&&Buffer.from(e,"base64").length===Nd?e:null}catch{return null}}function Md(r){let e=Dy.join(r,xy),t=Ld(e);if(t)return Fa(t);let n=to.randomBytes(Nd).toString("base64");try{ui.mkdirSync(r,{recursive:!0});try{ui.writeFileSync(e,n,{flag:"wx"})}catch{let o=Ld(e);if(o)return Fa(o);ui.writeFileSync(e,n)}}catch{}return Fa(n)}function Fa(r){return to.createHash("sha256").update(Ty).update(r).digest()}function $a(r,e){let t=to.randomBytes(Ry),n=to.createCipheriv(pi,e,t),o=Buffer.concat([n.update(r,"utf8"),n.final()]),i={version:1,algorithm:pi,ciphertext:o.toString("base64"),iv:t.toString("base64"),authTag:n.getAuthTag().toString("base64")};return JSON.stringify(i)}function Od(r,e){let t;try{t=JSON.parse(r)}catch{return null}if(!Ly(t))return r;try{let n=to.createDecipheriv(pi,e,Buffer.from(t.iv,"base64"));return n.setAuthTag(Buffer.from(t.authTag,"base64")),Buffer.concat([n.update(Buffer.from(t.ciphertext,"base64")),n.final()]).toString("utf8")}catch{return null}}function Ly(r){if(!r||typeof r!="object")return!1;let e=r;return e.version===1&&e.algorithm===pi&&typeof e.ciphertext=="string"&&typeof e.iv=="string"&&typeof e.authTag=="string"}import*as F from"fs";import*as wi from"path";import K from"fs";import*as fi from"os";import*as O from"path";import Ny from"json5";var Ha="Huawei";var Fd=3;function mi(r){if(!K.existsSync(r)||!K.statSync(r).isDirectory())return!1;let e=K.existsSync(O.join(r,"build-profile.json5")),t=K.existsSync(O.join(r,"hvigorfile.js"))||K.existsSync(O.join(r,"hvigorfile.ts"));if(!e||!t)return!1;try{let n=K.readFileSync(O.join(r,"build-profile.json5"),"utf-8");return Ny.parse(n).app!==void 0}catch{return!1}}function Ua(r,e,t){if(e>=t)return null;let n=My(r),o=Oy(n);if(o)return o;for(let i of n){let s=Ua(i,e+1,t);if(s)return s}return null}function My(r){try{let e=K.readdirSync(r,{withFileTypes:!0}),t=[];for(let n of e)n.isDirectory()&&t.push(O.join(r,n.name));return t}catch{return[]}}function Oy(r){for(let e of r)if(mi(e))return e;return null}function Lt(r){if(!r||r.trim()==="")return null;let e=O.resolve(r),t;try{t=K.realpathSync(e)}catch{t=e}if(!K.existsSync(t))return null;if(mi(t))return t;let n=t;for(let o=1;o<=3;o++){let i=O.dirname(n);if(i===n)break;if(mi(i))return i;n=i}if(K.statSync(t).isDirectory()){let o=Ua(t,0,Fd);if(o)return o}return null}function hi(r){if(!r||r.trim()==="")return null;let e=O.resolve(r),t;try{t=K.realpathSync(e)}catch{t=e}return!K.existsSync(t)||!K.statSync(t).isDirectory()?null:mi(t)?t:Ua(t,0,Fd)}var _d="DevEco Studio";function $d(){if(process.platform==="win32"){let r=[O.join("C:\\Program Files",Ha,_d),O.join("C:\\Program Files (x86)",Ha,_d)];return jd(r)}if(process.platform==="darwin"){let r=["/Applications/DevEco Studio.app",O.join(process.env.HOME??"","Applications","DevEco Studio.app")];return jd(r)}return null}function jd(r){for(let e of r)if(K.existsSync(e))return e;return null}function ro(r,e){let t=e?O.join("standardIndex","index.js"):"index.js";return K.existsSync(O.join(r,"ace-server"))?O.join(r,"ace-server","out",t):O.join(r,"out",t)}function gi(r){return K.existsSync(ro(r,!0))}var _y=[".idea",".deveco","cxx","compile_commands.json"];function xr(r){return O.join(r,..._y)}function Hd(r){return new Promise(e=>setTimeout(e,r))}var jy=new Set(["c","cc","cpp","cxx","h","hh","hpp","hxx"]);function Lr(r){let e=O.extname(r).replace(/^\./,"").toLowerCase();return e.length>0&&jy.has(e)}function yi(r){return O.extname(r).replace(/^\./,"").toLowerCase()==="c"?"c":"cpp"}function ge(r){let e=r.replace(/\\/g,"/");return process.platform==="win32"&&/^[a-zA-Z]:/.test(e)&&(e=e[0].toUpperCase()+e.slice(1)),e}function Fy(r){return ge(r)}function Nr(r){let e=Fy(r);return e.startsWith("/")?`file://${e}`:`file:///${e}`}function Kt(){if(process.platform==="win32"){let r=process.env.LOCALAPPDATA??O.join(fi.homedir(),"AppData","Local");return O.join(r,"devecocli-mcp-server","logs")}return process.platform==="darwin"?O.join(fi.homedir(),"Library","Logs","devecocli-mcp-server"):O.join(fi.homedir(),".local","share","devecocli-mcp-server","logs")}function Ud(r,e){let t=$y(e),n=Hy(t,r);if(n!==null)return n;let o=Date.now(),s=`${r.replace(/:/g,"\\:")}=${o}`,a=Uy(t,r,s);return By(e,a),o}function $y(r){let e;try{e=K.readFileSync(r,"utf8")}catch{e=""}return e.length>0?e.split(/\r?\n/):[]}function Hy(r,e){for(let t of r){let n=t.indexOf("=");if(n<=0||t.slice(0,n).replace(/\\:/g,":")!==e)continue;let i=parseInt(t.slice(n+1),10);return Number.isFinite(i)&&i>0?i:null}return null}function Uy(r,e,t){let n=!1,o=r.map(i=>{if(n)return i;let s=i.indexOf("=");return s<=0?i:i.slice(0,s).replace(/\\:/g,":")===e?(n=!0,t):i});return n||o.push(t),o}function By(r,e){try{K.mkdirSync(O.dirname(r),{recursive:!0})}catch{}try{K.writeFileSync(r,e.join(`
5
5
  `)+`
6
6
  `,"utf8")}catch{}}function Ba(r,e,t="[Cleanup]"){try{let n=O.dirname(r);if(!K.existsSync(n))return;let o=Date.now();for(let i of K.readdirSync(n,{withFileTypes:!0}))i.isDirectory()&&Wy(O.join(n,i.name),o,e,t)}catch{}}function Wy(r,e,t,n){try{let{mtimeMs:o}=K.statSync(r);if(e-o<=t)return;K.rmSync(r,{recursive:!0,force:!0});let i=Math.floor((e-o)/1e3);console.error(`${n} Removed expired dir (age ${Math.floor(i/86400)}d ${Math.floor(i%86400/3600)}h): ${r}`)}catch(o){console.error(`${n} Failed to remove expired dir ${r}: ${o}`)}}var Bd="mcp-server.log",Vy="mcp-server",Gy={maxSize:10*1024*1024,maxFiles:4},Wa=class r{fd=null;logDir=null;currentLogFile=null;mode;rotationOptions;currentFileSize=0;currentDate="";isRotating=!1;minLevel;static LEVEL_ORDER={debug:0,info:1,warn:2,error:3};constructor(e,t){this.rotationOptions={...Gy,...t},this.minLevel=e?"debug":"info",e?(this.mode="console",this.logDir=null,this.currentLogFile=null):(this.mode="file",this.logDir=Kt(),this.currentLogFile=wi.join(this.logDir,Bd),F.existsSync(this.logDir)||F.mkdirSync(this.logDir,{recursive:!0}),this.cleanupOrphanLogFiles(),this.openLogFile())}getCurrentDateString(){let e=new Date,t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),o=String(e.getDate()).padStart(2,"0");return`${t}-${n}-${o}`}getRotatedFileName(e,t){return wi.join(this.logDir,`${Vy}-${e}.log.${t}`)}fileExists(e){try{return F.accessSync(e,F.constants.F_OK),!0}catch{return!1}}cleanupOrphanLogFiles(){if(this.logDir)try{let e=F.readdirSync(this.logDir),t=[];for(let o of e)if(o===Bd||/^mcp-server-\d{4}-\d{2}-\d{2}\.log\.\d+$/.test(o)){let i=wi.join(this.logDir,o),s=F.statSync(i);t.push({name:o,mtime:s.mtime,path:i})}t.sort((o,i)=>i.mtime.getTime()-o.mtime.getTime());let n=1+this.rotationOptions.maxFiles;for(let o=n;o<t.length;o++)try{F.unlinkSync(t[o].path)}catch{}}catch{}}rotateLog(){if(!(this.isRotating||!this.logDir||!this.currentLogFile)){this.isRotating=!0;try{if(this.closeLogFile(),!this.fileExists(this.currentLogFile)){this.isRotating=!1,this.openLogFile();return}let e=this.getCurrentDateString(),t=this.getRotatedFileName(e,this.rotationOptions.maxFiles);this.fileExists(t)&&F.unlinkSync(t);for(let o=this.rotationOptions.maxFiles-1;o>=1;o--){let i=this.getRotatedFileName(e,o),s=this.getRotatedFileName(e,o+1);this.fileExists(i)&&F.renameSync(i,s)}let n=this.getRotatedFileName(e,1);F.renameSync(this.currentLogFile,n),this.cleanupOrphanLogFiles(),this.openLogFile()}catch{this.openLogFile()}finally{this.isRotating=!1}}}openLogFile(){if(this.currentLogFile){this.currentDate=this.getCurrentDateString();try{if(this.fileExists(this.currentLogFile)){let e=F.statSync(this.currentLogFile);this.currentFileSize=e.size}else this.currentFileSize=0}catch{this.currentFileSize=0}try{this.fd=F.openSync(this.currentLogFile,"a")}catch{this.fd=null}}}closeLogFile(){if(this.fd!==null){try{F.closeSync(this.fd)}catch{}this.fd=null}}checkRotation(e){let t=this.getCurrentDateString();this.currentDate&&this.currentDate!==t&&(this.rotateLog(),this.currentDate=t),this.currentFileSize+=e,this.currentFileSize>=this.rotationOptions.maxSize&&this.rotateLog()}write(e,t,...n){if(this.mode==="silent"||r.LEVEL_ORDER[e]<r.LEVEL_ORDER[this.minLevel])return;let o=n.map(c=>c instanceof Error?`${c.name}: ${c.message}`:typeof c=="object"?JSON.stringify(c,null,2):String(c)).join(" "),i=o?`${t} ${o}`:t,a=`[${new Date().toLocaleString("sv-SE",{timeZone:"Asia/Shanghai",hour12:!1})+"."+String(new Date().getMilliseconds()).padStart(3,"0")}] [MCP/${e.toUpperCase()}] ${i}
7
- `;if(this.mode==="file"&&this.currentLogFile){if(this.fd===null&&this.openLogFile(),this.fd!==null)try{let c=Buffer.from(a);F.writeSync(this.fd,c),this.checkRotation(c.byteLength)}catch{this.closeLogFile(),this.openLogFile()}}else this.mode==="console"&&process.stderr.write(a)}debug(e,...t){this.write("debug",e,...t)}info(e,...t){this.write("info",e,...t)}warn(e,...t){this.write("warn",e,...t)}error(e,...t){this.write("error",e,...t)}dispose(){this.closeLogFile()}flush(){if(!(this.mode!=="file"||this.fd===null))try{F.fsyncSync(this.fd)}catch{}}getLogFilePath(){return this.currentLogFile}getLogDirectory(){return this.logDir}},Qe=null;function Mr(r=!1){Qe&&Qe.dispose(),Qe=new Wa(r)}function Wd(){Qe&&(Qe.dispose(),Qe=null)}function Vd(){Qe&&Qe.flush()}function Gd(){return Qe?.getLogFilePath()??null}function qd(){return Qe?.getLogDirectory()??null}function vi(){return Qe||Mr(!1),Qe}var h={debug:(r,...e)=>vi().debug(r,...e),info:(r,...e)=>vi().info(r,...e),warn:(r,...e)=>vi().warn(r,...e),error:(r,...e)=>vi().error(r,...e)};import Va from"fs";import zd from"path";var no=300*1e3,oo=3600*1e3,Ga=10080*60*1e3;function Et(){let r=process.env.DEVECO_CLI_DISABLE_TELEMETRY;return r==="1"||r==="true"}var qy="upload-state.json";function Jd(r){return zd.join(r,qy)}function zy(){return{firstEventAt:null,lastUploadAt:null,lastRetryAt:null}}function bi(r){try{let e=Va.readFileSync(Jd(r),"utf8"),t=JSON.parse(e);return{firstEventAt:typeof t.firstEventAt=="number"?t.firstEventAt:null,lastUploadAt:typeof t.lastUploadAt=="number"?t.lastUploadAt:null,lastRetryAt:typeof t.lastRetryAt=="number"?t.lastRetryAt:null}}catch{return zy()}}function qa(r,e){try{Va.writeFileSync(Jd(r),JSON.stringify(e),"utf8")}catch{}}function Yd(r){let e=bi(r);e.firstEventAt===null&&(e.firstEventAt=Date.now(),qa(r,e))}function Kd(r){let e=bi(r);e.lastUploadAt=Date.now(),e.firstEventAt=null,qa(r,e)}function Xd(r){let e=bi(r);e.lastRetryAt=Date.now(),qa(r,e)}function za(r){let e=r.match(/^telemetry-(\d{4})-(\d{2})-(\d{2})\.txt$/);if(!e)return null;let t=Date.parse(`${e[1]}-${e[2]}-${e[3]}T00:00:00`);return Number.isFinite(t)?t:null}function Jy(r,e=Date.now()){let t=zd.join(r,"failed"),n;try{n=Va.readdirSync(t)}catch{return!1}for(let o of n){if(!o.startsWith("telemetry-")||!o.endsWith(".txt"))continue;let i=za(o);if(i!==null&&e-i<=Ga)return!0}return!1}function Zd(r,e=Date.now()){let t=bi(r);return!!(t.firstEventAt!==null&&e-t.firstEventAt>=no||Jy(r,e)&&(t.lastRetryAt===null||e-t.lastRetryAt>=oo))}import Yy from"crypto";import Si from"fs";import Ky from"path";var Xy="install-id";function Zy(r){return Ky.join(r,Xy)}function Qd(r){try{let e=Si.readFileSync(r,"utf8").trim();return Qy(e)?e:null}catch{return null}}function Qy(r){return/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(r)}function eu(r){let e=Zy(r),t=Qd(e);if(t)return t;let n=Yy.randomUUID();try{Si.mkdirSync(r,{recursive:!0});try{Si.writeFileSync(e,n,{flag:"wx"})}catch{let o=Qd(e);if(o)return o;Si.writeFileSync(e,n)}}catch{}return n}var io=class r{static MAX_BATCH=200;static MAX_PAYLOAD_BYTES=Math.floor(1.7*1024*1024);static TRACE_OS_VERSION="1.0";static COUNTRY_CODE="CN";static EVENT_PREFIX="devecocli_";uploader=new di;storageDir="";failedDir="";installId="";disabled=Et();traceFileKey=Buffer.alloc(0);sessionId=tu.randomUUID();cliVersion="";devecoStudioVersion=null;sourceType="";cltVersion=null;nodeVersion="";initialTimer=null;intervalTimer=null;retryInitialTimer=null;retryTimer=null;flushChain=Promise.resolve();constructor(){h.info(`[telemetry] instance created, sessionId=${this.sessionId}`)}init(e){this.storageDir=e,this.failedDir=Or.join(e,"failed"),this.cliVersion="1.3.3-Test.3",this.nodeVersion=process.version,this.installId=eu(e).replace(/-/g,""),this.traceFileKey=Md(e),et.mkdirSync(e,{recursive:!0}),et.mkdirSync(this.failedDir,{recursive:!0}),h.info(`[telemetry] init: dir=${e}, failedDir=${this.failedDir}, cliVersion=${this.cliVersion}, os=${this.resolveOsName()}, arch=${this.resolveOsArch()}, node=${this.nodeVersion}`)}setStudioVersion(e){this.devecoStudioVersion=e,h.info(`[telemetry] studio version set: ${e}`)}setSourceType(e){this.sourceType=e,h.info(`[telemetry] sourceType set: ${e}`)}setCltVersion(e){this.cltVersion=e,h.info(`[telemetry] CLT version set: ${e}`)}async track(e,t){if(this.disabled)return typeof t=="function"?t():void 0;if(!this.storageDir)throw new Error("Telemetry not initialized. Call init() first.");if(!t){await this.record(e,0,!0,null);return}if(typeof t!="function"){let i=t;await this.record(e,i.duration_ms,i.success,i.error_code);return}let n=t,o=Date.now();try{let i=await n(),s=Date.now()-o;return await this.record(e,s,!0,null),i}catch(i){let s=Date.now()-o,a=this.toErrorCode(i);throw await this.record(e,s,!1,a),i}}async record(e,t,n,o){let i=this.buildTraceEvent(e,t,n,o);try{let s=$a(JSON.stringify(i),this.traceFileKey);await et.promises.appendFile(this.currentFile(),s+`
7
+ `;if(this.mode==="file"&&this.currentLogFile){if(this.fd===null&&this.openLogFile(),this.fd!==null)try{let c=Buffer.from(a);F.writeSync(this.fd,c),this.checkRotation(c.byteLength)}catch{this.closeLogFile(),this.openLogFile()}}else this.mode==="console"&&process.stderr.write(a)}debug(e,...t){this.write("debug",e,...t)}info(e,...t){this.write("info",e,...t)}warn(e,...t){this.write("warn",e,...t)}error(e,...t){this.write("error",e,...t)}dispose(){this.closeLogFile()}flush(){if(!(this.mode!=="file"||this.fd===null))try{F.fsyncSync(this.fd)}catch{}}getLogFilePath(){return this.currentLogFile}getLogDirectory(){return this.logDir}},Qe=null;function Mr(r=!1){Qe&&Qe.dispose(),Qe=new Wa(r)}function Wd(){Qe&&(Qe.dispose(),Qe=null)}function Vd(){Qe&&Qe.flush()}function Gd(){return Qe?.getLogFilePath()??null}function qd(){return Qe?.getLogDirectory()??null}function vi(){return Qe||Mr(!1),Qe}var h={debug:(r,...e)=>vi().debug(r,...e),info:(r,...e)=>vi().info(r,...e),warn:(r,...e)=>vi().warn(r,...e),error:(r,...e)=>vi().error(r,...e)};import Va from"fs";import zd from"path";var no=300*1e3,oo=3600*1e3,Ga=10080*60*1e3;function Et(){let r=process.env.DEVECO_CLI_DISABLE_TELEMETRY;return r==="1"||r==="true"}var qy="upload-state.json";function Jd(r){return zd.join(r,qy)}function zy(){return{firstEventAt:null,lastUploadAt:null,lastRetryAt:null}}function bi(r){try{let e=Va.readFileSync(Jd(r),"utf8"),t=JSON.parse(e);return{firstEventAt:typeof t.firstEventAt=="number"?t.firstEventAt:null,lastUploadAt:typeof t.lastUploadAt=="number"?t.lastUploadAt:null,lastRetryAt:typeof t.lastRetryAt=="number"?t.lastRetryAt:null}}catch{return zy()}}function qa(r,e){try{Va.writeFileSync(Jd(r),JSON.stringify(e),"utf8")}catch{}}function Yd(r){let e=bi(r);e.firstEventAt===null&&(e.firstEventAt=Date.now(),qa(r,e))}function Kd(r){let e=bi(r);e.lastUploadAt=Date.now(),e.firstEventAt=null,qa(r,e)}function Xd(r){let e=bi(r);e.lastRetryAt=Date.now(),qa(r,e)}function za(r){let e=r.match(/^telemetry-(\d{4})-(\d{2})-(\d{2})\.txt$/);if(!e)return null;let t=Date.parse(`${e[1]}-${e[2]}-${e[3]}T00:00:00`);return Number.isFinite(t)?t:null}function Jy(r,e=Date.now()){let t=zd.join(r,"failed"),n;try{n=Va.readdirSync(t)}catch{return!1}for(let o of n){if(!o.startsWith("telemetry-")||!o.endsWith(".txt"))continue;let i=za(o);if(i!==null&&e-i<=Ga)return!0}return!1}function Zd(r,e=Date.now()){let t=bi(r);return!!(t.firstEventAt!==null&&e-t.firstEventAt>=no||Jy(r,e)&&(t.lastRetryAt===null||e-t.lastRetryAt>=oo))}import Yy from"crypto";import Si from"fs";import Ky from"path";var Xy="install-id";function Zy(r){return Ky.join(r,Xy)}function Qd(r){try{let e=Si.readFileSync(r,"utf8").trim();return Qy(e)?e:null}catch{return null}}function Qy(r){return/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(r)}function eu(r){let e=Zy(r),t=Qd(e);if(t)return t;let n=Yy.randomUUID();try{Si.mkdirSync(r,{recursive:!0});try{Si.writeFileSync(e,n,{flag:"wx"})}catch{let o=Qd(e);if(o)return o;Si.writeFileSync(e,n)}}catch{}return n}var io=class r{static MAX_BATCH=200;static MAX_PAYLOAD_BYTES=Math.floor(1.7*1024*1024);static TRACE_OS_VERSION="1.0";static COUNTRY_CODE="CN";static EVENT_PREFIX="devecocli_";uploader=new di;storageDir="";failedDir="";installId="";disabled=Et();traceFileKey=Buffer.alloc(0);sessionId=tu.randomUUID();cliVersion="";devecoStudioVersion=null;sourceType="";cltVersion=null;nodeVersion="";initialTimer=null;intervalTimer=null;retryInitialTimer=null;retryTimer=null;flushChain=Promise.resolve();constructor(){h.info(`[telemetry] instance created, sessionId=${this.sessionId}`)}init(e){this.storageDir=e,this.failedDir=Or.join(e,"failed"),this.cliVersion="1.3.3-Test.4",this.nodeVersion=process.version,this.installId=eu(e).replace(/-/g,""),this.traceFileKey=Md(e),et.mkdirSync(e,{recursive:!0}),et.mkdirSync(this.failedDir,{recursive:!0}),h.info(`[telemetry] init: dir=${e}, failedDir=${this.failedDir}, cliVersion=${this.cliVersion}, os=${this.resolveOsName()}, arch=${this.resolveOsArch()}, node=${this.nodeVersion}`)}setStudioVersion(e){this.devecoStudioVersion=e,h.info(`[telemetry] studio version set: ${e}`)}setSourceType(e){this.sourceType=e,h.info(`[telemetry] sourceType set: ${e}`)}setCltVersion(e){this.cltVersion=e,h.info(`[telemetry] CLT version set: ${e}`)}async track(e,t){if(this.disabled)return typeof t=="function"?t():void 0;if(!this.storageDir)throw new Error("Telemetry not initialized. Call init() first.");if(!t){await this.record(e,0,!0,null);return}if(typeof t!="function"){let i=t;await this.record(e,i.duration_ms,i.success,i.error_code);return}let n=t,o=Date.now();try{let i=await n(),s=Date.now()-o;return await this.record(e,s,!0,null),i}catch(i){let s=Date.now()-o,a=this.toErrorCode(i);throw await this.record(e,s,!1,a),i}}async record(e,t,n,o){let i=this.buildTraceEvent(e,t,n,o);try{let s=$a(JSON.stringify(i),this.traceFileKey);await et.promises.appendFile(this.currentFile(),s+`
8
8
  `,"utf8"),Yd(this.storageDir)}catch{}}buildTraceEvent(e,t,n,o){let i=`${r.EVENT_PREFIX}${e.event}`,s=xd.toObject(e);return s&&typeof s=="object"&&delete s.event,{countryCode:r.COUNTRY_CODE,event:i,eventtime:String(Date.now()),properties:{uid:this.installId,trace_uuid:tu.randomUUID(),trace_os_version:r.TRACE_OS_VERSION,os_arch:this.resolveOsArch(),action:i,trace_os_name:this.resolveOsName(),version:`${this.cliVersion}_${this.resolveOsSuffix()}`,deveco_studio_version:this.formatVersion(this.devecoStudioVersion),command_line_version:this.formatVersion(this.cltVersion),source_type:this.sourceType,session_id:this.sessionId,node_version:this.nodeVersion,duration_ms:t,success:n,error_code:o,event_detail:s}}}toErrorCode(e){return e instanceof Error?e.code??e.name:"UnknownError"}resolveOsArch(){let e=Ja.arch();return e==="x64"?"amd64":e}resolveOsName(){switch(process.platform){case"win32":{let e=Ja.release().split(".");return(parseInt(e[e.length-1],10)||0)>=22e3?"Windows 11":"Windows 10"}case"darwin":return"macOS";case"linux":return"Linux";default:return process.platform}}resolveOsSuffix(){switch(process.platform){case"win32":return"windows";case"darwin":return Ja.arch()==="arm64"?"mac_arm":"mac";default:return"linux"}}formatVersion(e){return e?`${e}_${this.resolveOsSuffix()}`:""}dateString(){let e=new Date,t=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${e.getFullYear()}-${t}-${n}`}currentFile(){return Or.join(this.storageDir,`telemetry-${this.dateString()}.txt`)}startScheduler(){if(this.stopScheduler(),this.disabled){h.info("[telemetry] scheduler not started (telemetry disabled)");return}h.info(`[telemetry] scheduler started (flush every ${no/1e3}s, retry failed every ${oo/1e3}s)`),this.initialTimer=setTimeout(()=>{this.flush().catch(()=>{}),this.intervalTimer=setInterval(()=>{this.flush().catch(()=>{})},no)},no),this.retryInitialTimer=setTimeout(()=>{this.retryFailed().catch(()=>{}),this.retryTimer=setInterval(()=>{this.retryFailed().catch(()=>{})},oo)},oo)}stopScheduler(){this.initialTimer&&(clearTimeout(this.initialTimer),this.initialTimer=null),this.intervalTimer&&(clearInterval(this.intervalTimer),this.intervalTimer=null),this.retryInitialTimer&&(clearTimeout(this.retryInitialTimer),this.retryInitialTimer=null),this.retryTimer&&(clearInterval(this.retryTimer),this.retryTimer=null),h.info("[telemetry] scheduler stopped")}async flush(){return this.disabled?!0:this.runExclusive(()=>this.performFlush())}async performFlush(){if(!this.storageDir)throw new Error("Telemetry not initialized. Call init() first.");let e=await this.listPendingFiles(),t=!0;for(let n of e)await this.flushFile(n)||(t=!1);return Kd(this.storageDir),t}async retryFailed(){return this.disabled?!0:this.runExclusive(()=>this.performRetryFailed())}async performRetryFailed(){if(!this.storageDir)throw new Error("Telemetry not initialized. Call init() first.");let e=Date.now(),t;try{t=await et.promises.readdir(this.failedDir)}catch{return!0}let n=t.filter(i=>i.startsWith("telemetry-")&&i.endsWith(".txt")).map(i=>Or.join(this.failedDir,i)),o=!0;for(let i of n){let s=Or.basename(i),a=za(s);if(a!==null){if(e-a>Ga){try{await et.promises.unlink(i)}catch{}continue}await this.flushFile(i)||(o=!1)}}return o||h.warn("[telemetry] retry failed"),Xd(this.storageDir),o}runExclusive(e){let t=()=>e(),n=this.flushChain.then(t,t);return this.flushChain=n.then(()=>{},()=>{}),n}async listPendingFiles(){let e;try{e=await et.promises.readdir(this.storageDir)}catch{return[]}return e.filter(t=>t.startsWith("telemetry-")&&t.endsWith(".txt")).map(t=>Or.join(this.storageDir,t)).sort()}async flushFile(e){let t=e+".pending";try{await et.promises.rename(e,t)}catch{return!1}let n;try{n=await et.promises.readFile(t,"utf8")}catch{return!1}let o=n.split(`
9
9
  `).map(s=>s.trim()).filter(Boolean),i=[];for(let s of o){let a=Od(s,this.traceFileKey);a!==null&&i.push(a)}if(i.length===0){try{await et.promises.unlink(t)}catch{}return!0}return this.uploadInBatches(t,i)}async uploadInBatches(e,t){let n=0;for(;n<t.length;){let o=n,i=[],s=16;for(;n<t.length&&i.length<r.MAX_BATCH;){let d=t[n],g=Buffer.byteLength(d,"utf8")+1;if(i.length>0&&s+g>r.MAX_PAYLOAD_BYTES)break;i.push(d),s+=g,n++}let a=this.buildPayloadItems(i),c=JSON.stringify(a),l=!1;try{l=await this.uploader.upload(c,this.installId)}catch{}if(!l){h.warn("[telemetry] upload failed");let d=t.slice(o).join(`
10
10
  `)+`
@@ -69,7 +69,7 @@ Available runnable modules:
69
69
  Installing artifacts to device ${e}...`),await r.installApp(e,n),o){console.log(`Launching ${t}/${o}...`);let s=await r.launchApp(e,t,o);console.log(wo(`
70
70
  Application '${t}': ${s}`))}else console.log(`
71
71
  Application '${t}' installed successfully (no ability to launch).`)}function _b(r){let e={event:b.CommandExecuted,args:["run",...r.module?["--module"]:[],...r.device?["--device"]:[],...r.product?["--product"]:[],...r.buildMode?["--build-mode"]:[],...r.ability?["--ability"]:[],...r.uninstall?["--uninstall"]:[],...r.skipBuild?["--skip-build"]:[],...r.apply?["--apply"]:[],...r.hotreload?["--hotreload"]:[],...r.hotreloadApply?["--hotreload-apply"]:[]]};return r.buildMode&&(e.build_mode=r.buildMode),r.module&&(e.module_count=r.module.length),e}var jb=new Mb("run").description("Build and run the project on a connected device").option("--module <modules...>","Module(s) to run (format: module or module@target)").option("--device <device>","Target device name or serial").option("--product <product>","Product name (default: default)").option("--build-mode <mode>","Build mode (options: debug, release; default: debug)").option("--ability <ability>","Ability name to launch").option("--uninstall","Uninstall existing app before installation").option("--skip-build","Skip build step and deploy existing artifacts").option("--apply <fileName>","Quick-apply changed files via quickfix (incremental hqf) and restart. <fileName> under project .hvigor/").option("--hotreload [action]",'Start hot-reload mode (build+deploy with daemon, then exit). Use "stop" to shut down the hvigor daemon.').option("--hotreload-apply <fileName>","Hot-reload changed files (.hvigor/<fileName> list) via daemon hot compile + signed hqf + quickfix, without restarting the app.").action(async r=>{let e=_b(r),t=Date.now(),n=!0,o=null;try{let i=await $b(r,e);i&&(i.ohpmMemoryMb&&(e.ohpm_install_memory=i.ohpmMemoryMb),i.syncMemoryMb&&(e.hvigor_sync_memory=i.syncMemoryMb),i.buildMemoryMb&&(e.hvigor_build_memory=i.buildMemoryMb))}catch(i){n=!1,o=q(i),console.error(Ob(i.message)),process.exitCode=1}finally{let i={duration_ms:Date.now()-t,success:n,error_code:o};await I.track(e,i)}});async function Fb(r,e,t,n,o){let i=new cn(e,r.rootDir),s=new ze(e,r.rootDir),a=new Set,c=new Set;for(let{moduleName:P,targetName:ie}of t)for(let B of r.collectNonHarDependentModuleList(P))a.add(`${B}@${ie}`),c.add(B);let l=[...a],d=dc(r,l),g={type:"modules",modulesToBuild:l,moduleTasks:d};for(let P of c)Fi.generate(r.rootDir,P,n,e);let v=await _r(r.rootDir,()=>uc(i,s,n,o,g,r.rootDir),()=>console.log("Another build is already running for this project. Waiting for completion..."));return console.log(`
72
- `+wo("Build completed successfully.")),v}async function $b(r,e){let t=W.discover(process.cwd());console.warn(es("Ensure the project source is trusted before proceeding."));let n=await A.new();if(r.skipBuild||n.assertJava(),e.bundle_name=t.getBundleName(),r.hotreloadApply){await Bb(r,t,n);return}if(r.hotreload){await Ub(r,t,n);return}if(r.apply){await Vb(r,t,n);return}return _p(r,t,n)}async function Hb(r,e,t){r.onSocketDisconnect(()=>{console.log("Daemon disconnected (likely via --hotreload stop). Exiting watch session."),process.exit(0)});let n=new ze(e,t.rootDir),o=setInterval(async()=>{await n.isDaemonAlive()||(clearInterval(o),console.log("Daemon stopped (via --hotreload stop). Exiting watch session."),process.exit(0))},3e3);await new Promise(()=>{})}async function Ub(r,e,t){if(r.hotreload==="stop"){await ap(t,e);return}let o=Rc(e,r.module).map(Dc),{moduleName:i,targetName:s}=o[0];bc(r.module,i);let a=new Ye(t),c=de.from(t),l=await ts(c,r.device),d=l.includes("127.0.0.1")||l.includes("localhost"),g=r.product||"default";e.validateProduct(g);let v=e.getBundleName(g),P=Mp(e,o,r.ability);$i.generate(e.rootDir,i,g,t);let ie=new ze(t,e.rootDir);console.log(wo("Ensuring hvigor daemon is running (via --sync --daemon, no hap build)...")),await ie.ensureDaemonRunning();let B=[`${i}@${g}`];for(let St of e.collectNonHarDependentModuleList(i))B.includes(`${St}@${g}`)||B.push(`${St}@${g}`);console.log(wo("Building hap + starting watch session (socket -> CommonBuild assembleHap --hot-reload-build --watch, kept open)..."));let Ae=new mn(e.rootDir,t);await Ae.startWatchSession({moduleSpecs:B,productName:g});let Ze=sp(e,i,s,d,g);await Op(a,l,v,Ze,P,!!r.uninstall),console.log(wo("Hot-reload watch session active (socket persistent). Edit code, write .hvigor/<file>, then `devecocli run --hotreload-apply <file>` in another terminal. Ctrl+C here to stop.")),await Hb(Ae,t,e)}async function Bb(r,e,t){let n=r.hotreloadApply;if(!n)throw new Error("hotreload-apply requires --hotreload-apply <fileName> (under .hvigor/)");if(bo.basename(n)!==n)throw new Error(`apply file must be a plain file name (under .hvigor/), got: ${n}`);let o=Rc(e,r.module),{moduleName:i}=Dc(o[0]);bc(r.module,i);let s=de.from(t),a=await ts(s,r.device),c=r.product||"default";e.validateProduct(c);let l=e.getBundleName(c);ip(e,i,n);let d=[`${i}@${c}`],g=await op({applyFileName:n,projectPath:e.rootDir,moduleName:i,productName:c,bundleName:l,toolProvider:t,targetDeviceId:a,moduleSpecs:d});if(!g.success)throw new Error(g.message)}function Wb(r,e,t,n){let o=new Set;for(let{moduleName:i,targetName:s}of e)for(let a of r.collectNonHarDependentModuleList(i)){o.add(r.findArtifactPath(a,s,t,n));for(let c of r.findRemoteHspPaths(a,s,n))o.add(c)}return[...o]}async function _p(r,e,t){let o=Rc(e,r.module).map(Dc);for(let{moduleName:B}of o){let Ae=e.getModuleType(B);if(Ae!=="entry"&&Ae!=="feature"&&Ae!=="shared")throw new w(`Module '${B}' '${Ae}' is not runnable. Specify an entry or feature module.`,"Module is not runnable.")}let i=new Ye(t),s=de.from(t),a=await ts(s,r.device),c=a.includes("127.0.0.1")||a.includes("localhost"),l=r.product||"default";e.validateProduct(l);let d=r.buildMode||"debug",g;r.skipBuild||(g=await Fb(e,t,o,l,d));let v=Wb(e,o,c,l),P=e.getBundleName(l),ie=Mp(e,o,r.ability);return await Op(i,a,P,v,ie,!!r.uninstall),ie&&await Ac({toolProvider:t,projectRoot:e.rootDir,hdcAdapter:i,targetDeviceId:a,bundleName:P}),g}async function Vb(r,e,t){let n=r.apply;if(!n)throw new Error("apply requires --apply <fileName> (under .hvigor/)");if(bo.basename(n)!==n)throw new Error(`apply file must be a plain file name (under .hvigor/), got: ${n}`);let o=bo.join(e.rootDir,".hvigor",n),i=de.from(t),s=await ts(i,r.device),a=r.product||"default";e.validateProduct(a);let c=e.getBundleName(a),l=e.profile.modules.find(v=>e.getModuleType(v.name)==="entry")?.name,d=l?e.getMainAbility(l,r.ability):r.ability||"EntryAbility",g=new ji(t,e.rootDir);try{await g.execute({applyFile:o,productName:a,targetDeviceId:s,bundleName:c,abilityName:d})}catch(v){console.warn(es(`[Apply] failed: ${v.message}`)),console.warn(es('[Apply] Falling back to full "devecocli run"...')),await _p(r,e,t);return}console.log(es('[Apply] Done. If changes did not take effect, check <module>/build/config/buildConfig.json for content, or run "devecocli run" for a full build.')),await Ac({toolProvider:t,projectRoot:e.rootDir,targetDeviceId:s,bundleName:c})}var jp=jb;import{Command as fS}from"commander";import*as Jp from"path";import{green as Gp,red as qp,cyan as Nc}from"colorette";import{execa as Oc}from"execa";import{spawn as Yb}from"child_process";import*as Hp from"fs";import*as rs from"path";import{yellow as Kb}from"colorette";import Xb from"proper-lockfile";import*as So from"fs";import*as $p from"path";import{homedir as Gb}from"os";var qb="deveco-cli",Fp,Tc=class extends Error{constructor(e){super(e),this.name="CliDataDirError"}};function zb(){let r=process.env.DEVECO_CLI_DATA_DIR,t=(r===void 0||r===""?"":Za(r))||$p.join(Gb(),".local","share",qb);try{return ki(t)}catch(n){throw new Tc(n instanceof Error?n.message:String(n))}}function Pe(){if(Fp!==void 0)return Fp;let r=zb();try{if(So.existsSync(r))return So.realpathSync(r)}catch{}return r}function Eo(){return"@yinsen/deveco-cli"}function ir(){return"1.3.3-Test.3"}function vn(){return"test"}function wn(){let r=process.env.DEVECO_CLI_DISABLE_UPDATE;return r==="check"||r==="all"?r:"off"}import*as Po from"fs";import*as Co from"path";var Jb={lastCheckedTimestamp:null,latestVersion:null,blockedVersions:[],checkError:null},xc=new Map,sr=class r{static CHECK_WINDOW_HOUR=21;static ONE_DAY_MS=1440*60*1e3;cacheFilePath;lockFilePath;constructor(e){this.cacheFilePath=Co.join(e,"cache.json"),this.lockFilePath=Co.join(e,"check.lock")}async writeSuccess(e,t=[],n,o){await this.write({lastCheckedTimestamp:Date.now(),latestVersion:e,blockedVersions:t,checkError:null,checkedAgainstVersion:n,checkedAgainstTag:o})}async writeError(e){let t=this.read();await this.write({...t,lastCheckedTimestamp:Date.now(),checkError:e})}getLatestVersion(){return this.read().latestVersion}getBlockedVersions(){return[...this.read().blockedVersions]}getCheckedAgainstVersion(){return this.read().checkedAgainstVersion}getCheckedAgainstTag(){return this.read().checkedAgainstTag}isCheckNeeded(){let{lastCheckedTimestamp:e}=this.read();if(!e||e>Date.now())return!0;let t=new Date().setHours(r.CHECK_WINDOW_HOUR,0,0,0),n=t>Date.now()?t-r.ONE_DAY_MS:t;return e<n}getLockPath(){return this.lockFilePath}read(){let e=xc.get(this.cacheFilePath);if(e)return e;try{let t=Po.readFileSync(this.cacheFilePath,"utf-8"),n=JSON.parse(t);return xc.set(this.cacheFilePath,n),n}catch{return{...Jb}}}async write(e){u(()=>`Writing update cache: lastChecked=${e.lastCheckedTimestamp}, latest=${e.latestVersion}, blocked=[${e.blockedVersions.join(",")}], error=${e.checkError}`),await Po.promises.mkdir(Co.dirname(this.cacheFilePath),{recursive:!0}),await Po.promises.writeFile(this.cacheFilePath,JSON.stringify(e,null,2),"utf-8"),xc.set(this.cacheFilePath,e)}};var ko=class{constructor(e){this.actionCommand=e}cache=new sr(rs.join(Pe(),"update"));async checkAndNotify(){if(!this.shouldSkip())try{let e=ir(),t=vn(),n=this.cache.getCheckedAgainstVersion(),o=this.cache.getCheckedAgainstTag(),i=o!=null&&o!==t,s=n!=null&&n!==e,a=i?null:this.cache.getLatestVersion();a&&ru(a,e)>0&&(console.log(),console.log(Kb(`New version ${a} available, run \`devecocli update\` to upgrade`))),(i||s||this.cache.isCheckNeeded())&&await this.spawnBackgroundCheck()}catch(e){u(`Update check failed: ${e instanceof Error?e.message:String(e)}`)}}shouldSkip(){let e=this.actionCommand;for(;e;){if(e.name()==="update")return!0;e=e.parent}return!1}async spawnBackgroundCheck(){if(!process.argv[1]?.endsWith(".ts"))try{await Zb(this.cache.getLockPath(),()=>{let e=[process.argv[1],"update","_check"];u(`Executing: ${process.execPath} ${e.join(" ")}`),Yb(process.execPath,e,{detached:!0,stdio:["ignore","ignore","ignore"],env:{...process.env,DEVECO_CLI_SKIP_VERSION_CHECK:"1"}}).unref()})}catch{u("Update check lock held by another process, skipping")}}};async function Zb(r,e){await Hp.promises.mkdir(rs.dirname(r),{recursive:!0});let t=await Xb.lock(r,{stale:6e4,retries:0,realpath:!1});try{await e()}finally{await t()}}import*as ns from"fs";import*as bn from"path";import{execa as Qb}from"execa";import{yellow as eS}from"colorette";function tS(r){return r?r.endsWith(".ts"):!0}function rS(r,e){let t=bn.join(r,"package.json");try{return JSON.parse(ns.readFileSync(t,"utf8")).name===e}catch{return!1}}function nS(r,e){let t;try{t=bn.dirname(ns.realpathSync(r))}catch{return null}for(let n=0;n<20&&t&&t!==bn.dirname(t);n++){if(rS(t,e))return t;t=bn.dirname(t)}return null}async function oS(){try{u("Executing: npm root -g");let{stdout:r}=await Qb("npm",["root","-g"]);return r.trim()||null}catch(r){return u(`[install-check] npm root -g failed: ${r instanceof Error?r.message:String(r)}`),null}}function iS(r,e){return Xa(r,e)}async function Lc(r){if(process.env.DEVECO_CLI_SKIP_INSTALL_CHECK)return;let e=process.argv[1];if(tS(e))return;let t=await oS();if(!t)return;let n=nS(e,r);if(!n){u("[install-check] running package root not found, skipping");return}iS(n,t)||(console.log(),console.log(eS(`Warning: devecocli is running from
72
+ `+wo("Build completed successfully.")),v}async function $b(r,e){let t=W.discover(process.cwd());console.warn(es("Ensure the project source is trusted before proceeding."));let n=await A.new();if(r.skipBuild||n.assertJava(),e.bundle_name=t.getBundleName(),r.hotreloadApply){await Bb(r,t,n);return}if(r.hotreload){await Ub(r,t,n);return}if(r.apply){await Vb(r,t,n);return}return _p(r,t,n)}async function Hb(r,e,t){r.onSocketDisconnect(()=>{console.log("Daemon disconnected (likely via --hotreload stop). Exiting watch session."),process.exit(0)});let n=new ze(e,t.rootDir),o=setInterval(async()=>{await n.isDaemonAlive()||(clearInterval(o),console.log("Daemon stopped (via --hotreload stop). Exiting watch session."),process.exit(0))},3e3);await new Promise(()=>{})}async function Ub(r,e,t){if(r.hotreload==="stop"){await ap(t,e);return}let o=Rc(e,r.module).map(Dc),{moduleName:i,targetName:s}=o[0];bc(r.module,i);let a=new Ye(t),c=de.from(t),l=await ts(c,r.device),d=l.includes("127.0.0.1")||l.includes("localhost"),g=r.product||"default";e.validateProduct(g);let v=e.getBundleName(g),P=Mp(e,o,r.ability);$i.generate(e.rootDir,i,g,t);let ie=new ze(t,e.rootDir);console.log(wo("Ensuring hvigor daemon is running (via --sync --daemon, no hap build)...")),await ie.ensureDaemonRunning();let B=[`${i}@${g}`];for(let St of e.collectNonHarDependentModuleList(i))B.includes(`${St}@${g}`)||B.push(`${St}@${g}`);console.log(wo("Building hap + starting watch session (socket -> CommonBuild assembleHap --hot-reload-build --watch, kept open)..."));let Ae=new mn(e.rootDir,t);await Ae.startWatchSession({moduleSpecs:B,productName:g});let Ze=sp(e,i,s,d,g);await Op(a,l,v,Ze,P,!!r.uninstall),console.log(wo("Hot-reload watch session active (socket persistent). Edit code, write .hvigor/<file>, then `devecocli run --hotreload-apply <file>` in another terminal. Ctrl+C here to stop.")),await Hb(Ae,t,e)}async function Bb(r,e,t){let n=r.hotreloadApply;if(!n)throw new Error("hotreload-apply requires --hotreload-apply <fileName> (under .hvigor/)");if(bo.basename(n)!==n)throw new Error(`apply file must be a plain file name (under .hvigor/), got: ${n}`);let o=Rc(e,r.module),{moduleName:i}=Dc(o[0]);bc(r.module,i);let s=de.from(t),a=await ts(s,r.device),c=r.product||"default";e.validateProduct(c);let l=e.getBundleName(c);ip(e,i,n);let d=[`${i}@${c}`],g=await op({applyFileName:n,projectPath:e.rootDir,moduleName:i,productName:c,bundleName:l,toolProvider:t,targetDeviceId:a,moduleSpecs:d});if(!g.success)throw new Error(g.message)}function Wb(r,e,t,n){let o=new Set;for(let{moduleName:i,targetName:s}of e)for(let a of r.collectNonHarDependentModuleList(i)){o.add(r.findArtifactPath(a,s,t,n));for(let c of r.findRemoteHspPaths(a,s,n))o.add(c)}return[...o]}async function _p(r,e,t){let o=Rc(e,r.module).map(Dc);for(let{moduleName:B}of o){let Ae=e.getModuleType(B);if(Ae!=="entry"&&Ae!=="feature"&&Ae!=="shared")throw new w(`Module '${B}' '${Ae}' is not runnable. Specify an entry or feature module.`,"Module is not runnable.")}let i=new Ye(t),s=de.from(t),a=await ts(s,r.device),c=a.includes("127.0.0.1")||a.includes("localhost"),l=r.product||"default";e.validateProduct(l);let d=r.buildMode||"debug",g;r.skipBuild||(g=await Fb(e,t,o,l,d));let v=Wb(e,o,c,l),P=e.getBundleName(l),ie=Mp(e,o,r.ability);return await Op(i,a,P,v,ie,!!r.uninstall),ie&&await Ac({toolProvider:t,projectRoot:e.rootDir,hdcAdapter:i,targetDeviceId:a,bundleName:P}),g}async function Vb(r,e,t){let n=r.apply;if(!n)throw new Error("apply requires --apply <fileName> (under .hvigor/)");if(bo.basename(n)!==n)throw new Error(`apply file must be a plain file name (under .hvigor/), got: ${n}`);let o=bo.join(e.rootDir,".hvigor",n),i=de.from(t),s=await ts(i,r.device),a=r.product||"default";e.validateProduct(a);let c=e.getBundleName(a),l=e.profile.modules.find(v=>e.getModuleType(v.name)==="entry")?.name,d=l?e.getMainAbility(l,r.ability):r.ability||"EntryAbility",g=new ji(t,e.rootDir);try{await g.execute({applyFile:o,productName:a,targetDeviceId:s,bundleName:c,abilityName:d})}catch(v){console.warn(es(`[Apply] failed: ${v.message}`)),console.warn(es('[Apply] Falling back to full "devecocli run"...')),await _p(r,e,t);return}console.log(es('[Apply] Done. If changes did not take effect, check <module>/build/config/buildConfig.json for content, or run "devecocli run" for a full build.')),await Ac({toolProvider:t,projectRoot:e.rootDir,targetDeviceId:s,bundleName:c})}var jp=jb;import{Command as fS}from"commander";import*as Jp from"path";import{green as Gp,red as qp,cyan as Nc}from"colorette";import{execa as Oc}from"execa";import{spawn as Yb}from"child_process";import*as Hp from"fs";import*as rs from"path";import{yellow as Kb}from"colorette";import Xb from"proper-lockfile";import*as So from"fs";import*as $p from"path";import{homedir as Gb}from"os";var qb="deveco-cli",Fp,Tc=class extends Error{constructor(e){super(e),this.name="CliDataDirError"}};function zb(){let r=process.env.DEVECO_CLI_DATA_DIR,t=(r===void 0||r===""?"":Za(r))||$p.join(Gb(),".local","share",qb);try{return ki(t)}catch(n){throw new Tc(n instanceof Error?n.message:String(n))}}function Pe(){if(Fp!==void 0)return Fp;let r=zb();try{if(So.existsSync(r))return So.realpathSync(r)}catch{}return r}function Eo(){return"@yinsen/deveco-cli"}function ir(){return"1.3.3-Test.4"}function vn(){return"test"}function wn(){let r=process.env.DEVECO_CLI_DISABLE_UPDATE;return r==="check"||r==="all"?r:"off"}import*as Po from"fs";import*as Co from"path";var Jb={lastCheckedTimestamp:null,latestVersion:null,blockedVersions:[],checkError:null},xc=new Map,sr=class r{static CHECK_WINDOW_HOUR=21;static ONE_DAY_MS=1440*60*1e3;cacheFilePath;lockFilePath;constructor(e){this.cacheFilePath=Co.join(e,"cache.json"),this.lockFilePath=Co.join(e,"check.lock")}async writeSuccess(e,t=[],n,o){await this.write({lastCheckedTimestamp:Date.now(),latestVersion:e,blockedVersions:t,checkError:null,checkedAgainstVersion:n,checkedAgainstTag:o})}async writeError(e){let t=this.read();await this.write({...t,lastCheckedTimestamp:Date.now(),checkError:e})}getLatestVersion(){return this.read().latestVersion}getBlockedVersions(){return[...this.read().blockedVersions]}getCheckedAgainstVersion(){return this.read().checkedAgainstVersion}getCheckedAgainstTag(){return this.read().checkedAgainstTag}isCheckNeeded(){let{lastCheckedTimestamp:e}=this.read();if(!e||e>Date.now())return!0;let t=new Date().setHours(r.CHECK_WINDOW_HOUR,0,0,0),n=t>Date.now()?t-r.ONE_DAY_MS:t;return e<n}getLockPath(){return this.lockFilePath}read(){let e=xc.get(this.cacheFilePath);if(e)return e;try{let t=Po.readFileSync(this.cacheFilePath,"utf-8"),n=JSON.parse(t);return xc.set(this.cacheFilePath,n),n}catch{return{...Jb}}}async write(e){u(()=>`Writing update cache: lastChecked=${e.lastCheckedTimestamp}, latest=${e.latestVersion}, blocked=[${e.blockedVersions.join(",")}], error=${e.checkError}`),await Po.promises.mkdir(Co.dirname(this.cacheFilePath),{recursive:!0}),await Po.promises.writeFile(this.cacheFilePath,JSON.stringify(e,null,2),"utf-8"),xc.set(this.cacheFilePath,e)}};var ko=class{constructor(e){this.actionCommand=e}cache=new sr(rs.join(Pe(),"update"));async checkAndNotify(){if(!this.shouldSkip())try{let e=ir(),t=vn(),n=this.cache.getCheckedAgainstVersion(),o=this.cache.getCheckedAgainstTag(),i=o!=null&&o!==t,s=n!=null&&n!==e,a=i?null:this.cache.getLatestVersion();a&&ru(a,e)>0&&(console.log(),console.log(Kb(`New version ${a} available, run \`devecocli update\` to upgrade`))),(i||s||this.cache.isCheckNeeded())&&await this.spawnBackgroundCheck()}catch(e){u(`Update check failed: ${e instanceof Error?e.message:String(e)}`)}}shouldSkip(){let e=this.actionCommand;for(;e;){if(e.name()==="update")return!0;e=e.parent}return!1}async spawnBackgroundCheck(){if(!process.argv[1]?.endsWith(".ts"))try{await Zb(this.cache.getLockPath(),()=>{let e=[process.argv[1],"update","_check"];u(`Executing: ${process.execPath} ${e.join(" ")}`),Yb(process.execPath,e,{detached:!0,stdio:["ignore","ignore","ignore"],env:{...process.env,DEVECO_CLI_SKIP_VERSION_CHECK:"1"}}).unref()})}catch{u("Update check lock held by another process, skipping")}}};async function Zb(r,e){await Hp.promises.mkdir(rs.dirname(r),{recursive:!0});let t=await Xb.lock(r,{stale:6e4,retries:0,realpath:!1});try{await e()}finally{await t()}}import*as ns from"fs";import*as bn from"path";import{execa as Qb}from"execa";import{yellow as eS}from"colorette";function tS(r){return r?r.endsWith(".ts"):!0}function rS(r,e){let t=bn.join(r,"package.json");try{return JSON.parse(ns.readFileSync(t,"utf8")).name===e}catch{return!1}}function nS(r,e){let t;try{t=bn.dirname(ns.realpathSync(r))}catch{return null}for(let n=0;n<20&&t&&t!==bn.dirname(t);n++){if(rS(t,e))return t;t=bn.dirname(t)}return null}async function oS(){try{u("Executing: npm root -g");let{stdout:r}=await Qb("npm",["root","-g"]);return r.trim()||null}catch(r){return u(`[install-check] npm root -g failed: ${r instanceof Error?r.message:String(r)}`),null}}function iS(r,e){return Xa(r,e)}async function Lc(r){if(process.env.DEVECO_CLI_SKIP_INSTALL_CHECK)return;let e=process.argv[1];if(tS(e))return;let t=await oS();if(!t)return;let n=nS(e,r);if(!n){u("[install-check] running package root not found, skipping");return}iS(n,t)||(console.log(),console.log(eS(`Warning: devecocli is running from
73
73
  ${n}
74
74
  but \`npm\` in PATH installs global packages to
75
75
  ${t}
@@ -1314,7 +1314,7 @@ ${t}`}handleData(t){for(this.buffer=Buffer.concat([this.buffer,t]);;){let n=this
1314
1314
  `):"No valid C/C++ files"}],isError:!0};for(let c of o){await Vk(Bk);try{let l=await this.checkFile(c);n.push(Wk(c,l))}catch(l){t.push(`${c} => wait for diagnostics failed: ${l.message}`)}}let i=t.length>0,s=[];t.length>0&&s.push(t.join(`
1315
1315
  `)),n.length>0&&s.push(n.join(`
1316
1316
  `));let a=s.join(`
1317
- `).trim();return!i&&n.length===0&&(a="No diagnostic information collected"),{content:[{type:"text",text:a}],isError:i}}async checkFile(e){let t=Nr(e),n=await wr.promises.readFile(e,"utf8"),o=yi(e),i=this.manager.registerDiagnosticCallback(t);this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didOpen",params:{textDocument:{uri:t,text:n,languageId:o,version:n.length}}});try{return await i}finally{this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didClose",params:{textDocument:{uri:t}}})}}collectValidFiles(e,t){let n=Qr.resolve(this.manager.projectRoot),o=[];for(let i of e){let s=Qr.resolve(Qr.isAbsolute(i)?i:Qr.join(n,i));if(!wr.existsSync(s)){t.push(`File does not exist: ${i}`);continue}if(!wr.statSync(s).isFile()){t.push(`Not a regular file: ${i}`);continue}if(!Lr(s)){t.push(`Not a supported C/C++ file: ${i}`);continue}try{o.push(wr.realpathSync(s))}catch{o.push(s)}}return o}};function Wk(r,e){if(Array.isArray(e))return e.length===0?`${r} => no diagnostics`:`${r} => Diagnostic: ${JSON.stringify(e)}`;if(e&&typeof e=="object"&&typeof e.errorMessage=="string"){let t=e.errorMessage;return`${r} diagnostic failed, error_message: ${t}`}return`${r} => diagnostic failed, result: ${JSON.stringify(e)}`}function Vk(r){return new Promise(e=>setTimeout(e,r))}import*as Gn from"fs";import*as ia from"path";var Vn=class r{manager;static FEATURE_METHOD_MAP={hover:y.HOVER,definition:y.DEFINITION,declaration:y.DECLARATION,references:y.REFERENCES,implementation:y.IMPLEMENTATION};constructor(e){this.manager=e}async handleLspFeature(e,t){if(!this.manager.ready)return Bn();let n=this.resolveSingleFile(t.file);if(!n)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${t.file}`}],isError:!0};let o=r.FEATURE_METHOD_MAP[e];if(!o)return{content:[{type:"text",text:`Unknown feature: ${e}`}],isError:!0};h.info(`[ClangdLspTool] handleLspFeature: ${e} file=${n} line=${t.line} char=${t.character}`);try{let i=await this.withOpenFile(n,async a=>{let c={textDocument:{uri:a},position:{line:t.line,character:t.character}};return e==="references"&&(c.context={includeDeclaration:!0}),this.manager.sendFeatureRequest(o,c)});return{content:[{type:"text",text:i==null?`${e}: no result`:`${e}: ${JSON.stringify(i,null,2)}`}]}}catch(i){return oa(e,i)}}async handleWorkspaceSymbolRaw(e){if(!this.manager.ready)return null;try{let t=await this.manager.sendFeatureRequest(y.WORKSPACE_SYMBOL,{query:e});return Array.isArray(t)?t:t==null?null:[t]}catch(t){return h.error(`[ClangdLspTool] handleWorkspaceSymbolRaw failed: ${t.message}`),null}}async handleDocumentSymbol(e){if(!this.manager.ready)return Bn();let t=this.resolveSingleFile(e);if(!t)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${e}`}],isError:!0};h.info(`[ClangdLspTool] handleDocumentSymbol: file=${t}`);try{let n=await this.withOpenFile(t,async i=>this.manager.sendFeatureRequest(y.DOCUMENT_SYMBOL,{textDocument:{uri:i}}));return{content:[{type:"text",text:n==null?"documentSymbol: no result":`documentSymbol: ${JSON.stringify(n,null,2)}`}]}}catch(n){return oa("documentSymbol",n)}}async handleCallHierarchy(e){if(!this.manager.ready)return Bn();if(e.direction==="outgoing")return{content:[{type:"text",text:"callHierarchy outgoing is not supported by clangd (incoming only)"}],isError:!0};let t=this.resolveSingleFile(e.file);if(!t)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${e.file}`}],isError:!0};h.info(`[ClangdLspTool] handleCallHierarchy: file=${t} line=${e.line} char=${e.character} direction=${e.direction}`);try{let n=await this.withOpenFile(t,i=>this.fetchCallHierarchyResult(i,e));return{content:[{type:"text",text:`callHierarchy (${e.direction}): ${JSON.stringify(n,null,2)}`}]}}catch(n){return oa("callHierarchy",n)}}async fetchCallHierarchyResult(e,t){let n=await this.manager.sendFeatureRequest(y.PREPARE_CALL_HIERARCHY,{textDocument:{uri:e},position:{line:t.line,character:t.character}}),o=this.normalizeCallHierarchyItems(n);if(o.length===0)return{items:[],calls:[]};let i=await this.collectIncomingCalls(o);return{items:o,calls:i}}normalizeCallHierarchyItems(e){return Array.isArray(e)?e:e?[e]:[]}async collectIncomingCalls(e){let t=[];for(let n of e)t.push(...await this.fetchIncomingCalls(n));return t}async fetchIncomingCalls(e){let t=await this.manager.sendFeatureRequest(y.INCOMING_CALLS,{item:e});return Array.isArray(t)?t:t?[t]:[]}async withOpenFile(e,t){let n=Nr(e),o=await Gn.promises.readFile(e,"utf8"),i=yi(e);h.info(`[ClangdLspTool] withOpenFile didOpen uri=${n} langId=${i} len=${o.length}`),this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didOpen",params:{textDocument:{uri:n,text:o,languageId:i,version:o.length}}});try{return await t(n)}finally{this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didClose",params:{textDocument:{uri:n}}})}}resolveSingleFile(e){let t=ia.isAbsolute(e)?e:ia.join(this.manager.projectRoot,e);return!Gn.existsSync(t)||!Gn.statSync(t).isFile()||!Lr(t)?null:t}};import{spawn as Gk}from"child_process";import*as aa from"fs";import*as Dh from"path";var qk=30*1e3,zk=30*1e3,sa=class{config;client=null;clangdProcess=null;nextRequestId=1;requestCallbacks=new hr;diagnosticWaiters=new Map;lastStartErrorMessage=null;onMessage=()=>{};disposeOnce=null;constructor(e){this.config=e}setOnMessage(e){this.onMessage=e}get clangdPid(){return this.clangdProcess?.pid??null}consumeStartErrorMessage(){let e=this.lastStartErrorMessage;return this.lastStartErrorMessage=null,e}async start(e){let t=!1;try{m.info(`[ClangdLspProxy] clangdPath: ${this.config.clangdPath}`),m.info(`[ClangdLspProxy] workspaceRoot: ${this.config.workspaceRoot}`),m.info(`[ClangdLspProxy] compileCommandsDir: ${this.config.compileCommandsDir}`),this.ensureLogDir(),this.clangdProcess=this.spawnClangd();let n={serverPath:"",logPath:this.config.logPath,indexingDataLocation:this.config.logPath,cwd:this.config.workspaceRoot};this.client=new mr(n),this.client.on("message",i=>this.handleRawMessage(i)),this.client.on("error",i=>this.handleError(i)),this.client.attachProcess(this.clangdProcess,{stderrAsError:!1});let o=this.buildInitializeParams();await this.sendLspRequest(y.INITIALIZE,o,rt),m.info("[ClangdLspProxy] initialize response received"),this.sendNotification(y.INITIALIZED,{}),t=!0}catch(n){this.lastStartErrorMessage=n instanceof Error?n.message:String(n),m.error(`[ClangdLspProxy] initialization failed: ${this.lastStartErrorMessage}`),await this.dispose()}e?.(t)}async hover(e){return this.sendLspRequest(y.HOVER,e)}async definition(e){return this.sendLspRequest(y.DEFINITION,e)}async declaration(e){return this.sendLspRequest(y.DECLARATION,e)}async references(e){return this.sendLspRequest(y.REFERENCES,e)}async implementation(e){return this.sendLspRequest(y.IMPLEMENTATION,e)}async documentSymbol(e){return this.sendLspRequest(y.DOCUMENT_SYMBOL,e)}async workspaceSymbol(e){return this.sendLspRequest(y.WORKSPACE_SYMBOL,e)}async prepareCallHierarchy(e){return this.sendLspRequest(y.PREPARE_CALL_HIERARCHY,e)}async incomingCalls(e){return this.sendLspRequest(y.INCOMING_CALLS,e)}async sendFeatureRequest(e,t){return this.sendLspRequest(e,t)}sendDidOpen(e){this.sendNotification(y.DID_OPEN,e)}sendDidChange(e){this.sendNotification(y.DID_CHANGE,e)}sendDidClose(e){this.sendNotification(y.DID_CLOSE,e)}sendNotification(e,t){if(!this.client){m.warn("[ClangdLspProxy] sendNotification before ready, dropped");return}this.client.sendNotification(e,t)}registerDiagnosticCallback(e){let t=this.normalizeClangdUri(e);if(this.diagnosticWaiters.has(t)){m.warn(`[ClangdLspProxy] overwrite existing diagnostic waiter for ${t}`);let n=this.diagnosticWaiters.get(t);clearTimeout(n.timer),this.diagnosticWaiters.delete(t)}return new Promise((n,o)=>{let i=setTimeout(()=>{this.diagnosticWaiters.delete(t)&&o(new Error(`Wait for clangd diagnostics timeout, uri: ${t}`))},zk);this.diagnosticWaiters.set(t,{resolve:n,reject:o,timer:i})})}async dispose(){return this.disposeOnce||(this.disposeOnce=this.performDispose()),this.disposeOnce}async performDispose(){this.requestCallbacks.rejectAll(new Error("ClangdLspProxy disposing"));for(let[,e]of this.diagnosticWaiters)clearTimeout(e.timer),e.reject(new Error("ClangdLspProxy disposing"));if(this.diagnosticWaiters.clear(),this.client&&this.clangdProcess)try{await this.sendLspRequest(y.SHUTDOWN,null,3e3).catch(e=>{m.warn(`[ClangdLspProxy] shutdown request failed: ${e}`)}),this.sendNotification(y.EXIT,null),await this.client.waitForExitOrTimeout(300)}catch(e){m.warn(`[ClangdLspProxy] dispose error: ${e}`)}if(this.clangdProcess){try{this.clangdProcess.exitCode===null&&this.clangdProcess.signalCode===null&&this.clangdProcess.kill()}catch{}this.clangdProcess=null}this.client=null}spawnClangd(){let e=[`--compile-commands-dir=${z(this.config.compileCommandsDir)}`,"--log=info","--pch-storage=memory","--limit-results=100"];m.info(`[ClangdLspProxy] spawn: ${this.config.clangdPath} ${e.join(" ")}`);let t=Gk(this.config.clangdPath,e,{cwd:this.config.workspaceRoot,stdio:["pipe","pipe","pipe"],windowsHide:!0});if(!t.stdin||!t.stdout||!t.stderr)throw new Error("Failed to spawn clangd: stdio not available");return t}buildInitializeParams(){let e=dn(this.config.workspaceRoot),t=mt(e),n=Dh.basename(e)||"workspace";return{processId:process.pid,clientInfo:{name:"devecocli-mcp-server",version:"1.3.3-Test.3"},rootPath:e,rootUri:t,workspaceFolders:[{uri:t,name:n}],capabilities:this.buildClientCapabilities(),initializationOptions:null}}buildClientCapabilities(){return{textDocument:{synchronization:{didOpen:!0,didChange:!0,didClose:!0,willSave:!1,save:!1},publishDiagnostics:{relatedInformation:!0,versionSupport:!1,tagSupport:{valueSet:[1,2]}},hover:{contentFormat:["markdown","plaintext"]},completion:{contextSupport:!1,completionItemKind:{valueSet:[]}},signatureHelp:{signatureInformation:{documentationFormat:["markdown","plaintext"]}},references:{},declaration:{linkSupport:!0},definition:{linkSupport:!0},implementation:{linkSupport:!0},documentSymbol:{hierarchicalDocumentSymbolSupport:!0,symbolKind:{valueSet:[]}},callHierarchy:{dynamicRegistration:!1}},workspace:{symbol:{symbolKind:{valueSet:[]}},configuration:!1,didChangeWatchedFiles:{dynamicRegistration:!1}}}}sendLspRequest(e,t,n=qk){if(!this.client)return Promise.reject(new Error("[ClangdLspProxy] client not ready"));let o=this.nextRequestId++,i=this.requestCallbacks.registerPending(o,e,n);return this.client.sendRequest(e,t,o),i}handleRawMessage(e){let t;try{t=JSON.parse(e)}catch(n){let o=n instanceof Error?n.message:String(n);m.error(`[ClangdLspProxy] JSON parse error: ${o}, raw: ${e.slice(0,200)}`);return}"id"in t&&("result"in t||"error"in t)?this.handleResponse(t):"method"in t?this.handleNotification(t):m.warn(`[ClangdLspProxy] unrecognized message: ${JSON.stringify(t).slice(0,200)}`)}handleResponse(e){let t=e.id;if(t==null||typeof t!="string"&&typeof t!="number")return;let n=t;if(e.error!==void 0&&e.error!==null){let o=e.error;m.warn(`[ClangdLspProxy] LSP error id=${n}: code=${o.code??-1} message=${o.message??"unknown"}`),this.requestCallbacks.rejectPending(n,new Error(`LSP error ${o.code??-1}: ${o.message??"unknown"}`))}else this.requestCallbacks.resolvePending(n,e.result)}handleNotification(e){let t=e.method;if(t)switch(t){case y.PUBLISH_DIAGNOSTICS:this.handlePublishDiagnostics(e.params);break;case y.PROGRESS:this.onMessage({jsonrpc:T,method:y.PROGRESS,params:e.params});break;case y.WINDOW_SHOW_MESSAGE:m.info(`[ClangdLspProxy] window/showMessage: ${JSON.stringify(e.params)}`);break;case y.WINDOW_LOG_MESSAGE:m.info(`[ClangdLspProxy] window/logMessage: ${JSON.stringify(e.params)}`);break;default:this.onMessage({jsonrpc:T,method:t,params:e.params})}}handlePublishDiagnostics(e){if(!e||!e.uri)return;let t=this.normalizeClangdUri(e.uri),n=this.diagnosticWaiters.get(t);if(!n&&this.diagnosticWaiters.size===1){let s=this.diagnosticWaiters.keys().next().value;n=this.diagnosticWaiters.get(s),n&&this.diagnosticWaiters.delete(s)}else n&&this.diagnosticWaiters.delete(t);if(!n)return;clearTimeout(n.timer);let o=Array.isArray(e.diagnostics)?e.diagnostics:[],i=o.length;m.info(`[ClangdLspProxy] diagnostics received uri=${t} count=${i}`),n.resolve(o)}handleError(e){for(let[,t]of this.diagnosticWaiters)clearTimeout(t.timer),t.reject(e);this.diagnosticWaiters.clear(),this.requestCallbacks.rejectAll(e),this.onMessage({jsonrpc:T,method:y.CPP_ERROR,params:{message:e.message}})}ensureLogDir(){if(this.config.logPath)try{aa.existsSync(this.config.logPath)||aa.mkdirSync(this.config.logPath,{recursive:!0})}catch{}}normalizeClangdUri(e){try{let t=new URL(e);if(t.protocol==="file:"){let n=decodeURIComponent(t.pathname);return process.platform==="win32"&&/^\/[a-zA-Z]:/.test(n)&&(n=n.slice(1)),mt(n)}}catch{}return e}};import*as Ko from"path";import*as Il from"fs";var Xo=class r{config;proxy=null;isInitialized=!1;onMessage=()=>{};disposeOnce=null;initPromise=null;initDeadlineTimer=null;initResolve=null;initReject=null;resolvedRoot="";constructor(e){this.config=e}setOnMessage(e){this.onMessage=e}get ready(){return this.isInitialized&&this.proxy!==null}get clangdPid(){return this.proxy?.clangdPid??null}get projectRoot(){return this.resolvedRoot}async start(){if(!this.isInitialized){if(this.initPromise){await this.initPromise;return}this.initPromise=this.doStart();try{await this.initPromise}catch(e){throw this.initPromise=null,e}}}sendNotification(e){if(!this.proxy){m.warn("[ClangdLspManager] sendNotification before LSP ready, dropped");return}this.dispatchNotification(e)}async sendFeatureRequest(e,t){if(!this.proxy)throw new Error("[ClangdLspManager] LSP not ready");return this.proxy.sendFeatureRequest(e,t)}registerDiagnosticCallback(e){return this.proxy?this.proxy.registerDiagnosticCallback(e):Promise.reject(new Error("[ClangdLspManager] LSP not ready"))}static async handleSyncCppProject(e,t,n,o,i){if(m.info("[ClangdLspManager] Received cpp/syncProject"),!e||!t)return m.error("[ClangdLspManager] handleSyncCppProject: workspaceRoot or sdkPath is empty"),{status:"failed",reason:"workspaceRoot or sdkPath is empty"};if(rr(e).length===0)return m.info("[ClangdLspManager] No C++ modules found, skipping compileNative"),{status:"success"};let a=i?.skipCompileNative===!0,c=await Di(e,a?async()=>(m.info("[ClangdLspManager] compileNative skipped (C++ project up-to-date)"),{status:"success"}):async()=>r.executeCompileNative(e,t,n,o));return c.acquired?c.result:(m.info("[ClangdLspManager] Build lock held by another process, skipping sync"),{status:"skipped",reason:"build lock held by another process"})}static async executeCompileNative(e,t,n,o){try{return await Tu(e,t,n,o),m.info("[ClangdLspManager] compileNative + merge compile_commands completed"),{status:"success"}}catch(i){let s=i instanceof Error?i.message:String(i);return m.error(`[ClangdLspManager] compileNative failed: ${s}`),{status:"failed",reason:s}}}async dispose(){return this.disposeOnce||(this.disposeOnce=this.performDispose()),this.disposeOnce}doStart(){return new Promise((e,t)=>{this.initResolve=e,this.initReject=t,this.armInitTimer(rt);try{this.startProxy()}catch(n){this.failInit(n instanceof Error?n:new Error(String(n)))}})}startProxy(){let e=Lt(this.config.workspaceRoot);this.resolvedRoot=e?ge(e):ge(this.config.workspaceRoot);let t=this.config.logPath??this.getLogPath();Li(t);let n=this.config.clangdPath;if(!n){let s="clangd not found (install DevEco Studio / CLT)";m.error(`[ClangdLspManager] ${s}`),this.failInit(new Error(s));return}let o=Ko.dirname(xr(this.resolvedRoot));try{Il.mkdirSync(o,{recursive:!0})}catch(s){m.warn(`[ClangdLspManager] Failed to create compile_commands dir: ${s}`)}m.info(`[ClangdLspManager] clangdPath: ${n}`),m.info(`[ClangdLspManager] workspaceRoot: ${this.resolvedRoot}`),m.info(`[ClangdLspManager] compileCommandsDir: ${o}`);let i=new sa({clangdPath:n,workspaceRoot:this.resolvedRoot,compileCommandsDir:o,logPath:t});i.setOnMessage(s=>this.handleLspMessage(s)),this.proxy=i,i.start(s=>this.handleProxyInitialized(s)).catch(s=>{let a=s instanceof Error?s:new Error(String(s));this.handleProxyInitialized(!1,a.message)})}handleProxyInitialized=(e,t)=>{if(this.clearInitTimer(),e){this.isInitialized=!0,m.info("[ClangdLspManager] clangd initialized");let n=this.initResolve;this.clearInitHandlers(),n?.()}else{let n=t??this.proxy?.consumeStartErrorMessage()??"unknown error";m.error(`[ClangdLspManager] clangd initialization failed: ${n}`),this.isInitialized=!1,this.proxy=null;let o=this.initReject;this.clearInitHandlers(),o?.(new Error(`C++ LSP initialize failed: ${n}`))}};handleLspMessage(e){this.onMessage(e)}dispatchNotification(e){if(!this.proxy)return;let t=e,n=t.method;if(!n){m.warn("[ClangdLspManager] dispatchNotification: missing method");return}let o=t.params;switch(n){case y.DID_OPEN:this.proxy.sendDidOpen(o);break;case y.DID_CHANGE:this.proxy.sendDidChange(o);break;case y.DID_CLOSE:this.proxy.sendDidClose(o);break;default:this.proxy.sendNotification(n,o)}}armInitTimer(e){this.clearInitTimer(),this.initDeadlineTimer=setTimeout(()=>{this.failInit(new Error("C++ LSP initialize timeout"))},e)}clearInitTimer(){this.initDeadlineTimer&&(clearTimeout(this.initDeadlineTimer),this.initDeadlineTimer=null)}clearInitHandlers(){this.clearInitTimer(),this.initResolve=null,this.initReject=null}failInit(e){let t=this.initReject;this.clearInitHandlers(),t?.(e)}async performDispose(){let e=this.initReject;if(this.clearInitHandlers(),e?.(new Error("ClangdLspManager disposing")),this.proxy){try{await this.proxy.dispose()}catch(t){m.warn(`[ClangdLspManager] proxy dispose error: ${t}`)}this.proxy=null}this.isInitialized=!1,this.initPromise=null}getLogPath(){try{let e=Ko.join(Kt(),"CppCheck"),t=`${Date.now()}${process.hrtime.bigint()%1000000n}`,n=Ko.join(e,"lsp-log",t);return Il.mkdirSync(n,{recursive:!0}),ge(n)}catch{return"auto"}}};function Rh(r){let e=Ti(r);return m.info(`[SyncGuard] ${e.reason}`),e}var Rl=(s=>(s[s.IDLE=0]="IDLE",s[s.DISCOVERING=1]="DISCOVERING",s[s.SYNCING=2]="SYNCING",s[s.INITIALIZING=3]="INITIALIZING",s[s.READY=4]="READY",s[s.ERROR=5]="ERROR",s))(Rl||{}),Th=(s=>(s[s.IDLE_CPP=0]="IDLE_CPP",s[s.DISCOVERING_CPP=1]="DISCOVERING_CPP",s[s.SYNCING_CPP=2]="SYNCING_CPP",s[s.INITIALIZING_CPP=3]="INITIALIZING_CPP",s[s.READY_CPP=4]="READY_CPP",s[s.ERROR_CPP=5]="ERROR_CPP",s))(Th||{}),Tt=3,Al=600*1e3,Dl=100,ca=class{server;toolRouter;config={};arktsCheckTool=null;cppCheckTool=null;cppLspTool=null;cppLspManager=null;projectState=0;workspaceRoot="";sdkPath="";arktsLangServerPath=null;nodePath="";ohpmJsPath="";hvigorJsPath="";clangdPath=null;initPromise=null;needsReinit=!1;initRetryCount=0;originalProjectPath="";configChangedTriggeredResync=!1;syncSkippedDueToLock=!1;syncSkipStartedAt=0;standardProtocolAvailable=!1;cppProjectState=0;cppInitPromise=null;cppNeedsReinit=!1;cppInitRetryCount=0;cppSyncSkippedDueToLock=!1;cppSyncSkipStartedAt=0;cppHasNoCppCode=!1;cppEnabled;constructor(e={}){this.config=e,Mr(e.debug??!1);let t,n=e.projectPath?.trim()??"";this.originalProjectPath=n,n==="."?(t=process.cwd(),h.info(`Constructor: configuredPath is '.', startPath: '${t}'`)):n===""?(t="",h.info("Constructor: configuredPath is empty, startPath remains empty")):(t=n,h.info(`Constructor: using configured path as startPath: '${t}'`));let o=Lt(t);h.info(`Constructor: findHarmonyProject('${t}') => ${o??"null"}`),this.config.projectPath=o??void 0,this.sdkPath=this.config.sdkPath??"",this.arktsLangServerPath=this.config.arktsLangServerPath??null,this.nodePath=this.config.nodePath??"",this.ohpmJsPath=this.config.ohpmJsPath??"",this.hvigorJsPath=this.config.hvigorJsPath??"",this.clangdPath=this.config.clangdPath??null,this.cppEnabled=this.config.cppEnabled??!0,h.info(`Constructor: sdkPath='${this.sdkPath}', arktsLangServerPath='${this.arktsLangServerPath??"(null)"}', cppEnabled=${this.cppEnabled}`),this.server=new Jk({name:"devecocli-mcp-server",version:"0.0.1"}),this.toolRouter=El(e.telemetry,()=>this.arktsCheckTool?.aceServerPid??null,()=>this.config.projectPath??"",()=>this.sdkPath??""),this.standardProtocolAvailable=this.detectStandardProtocolAvailable(),this.registerTools()}registerTools(){this.registerCheckTool(),this.registerLspFeatureTools(),this.registerRestartTool()}registerRestartTool(){this.toolRouter.add({name:"restart",description:"Restart the MCP server in-place: re-sync the project and re-initialize the LSP, without dropping the client connection. Use to recover from a stuck/ERROR state after fixing the root cause, instead of exiting and reopening the agent. Use target to restart one side only (arkts/cpp) or both (all, default). Only callable when the project state is ready/idle/error; during discovery/sync/init (large-project init can take minutes) it returns an error\u2014wait for ready and retry tools instead. Caution: if initialization fails again after a restart, the cause is likely a persistent project/SDK configuration issue\u2014do not call restart repeatedly; ask the user to fix the project first.",inputSchema:he.object({target:he.enum(["arkts","cpp","all"]).default("all").describe('Which backend to restart: "arkts" (ArkTS ace-server), "cpp" (C++ clangd), or "all" (both, default).')})},async e=>this.handleRestartCall(e))}registerCheckTool(){this.toolRouter.add({name:"check",description:"Perform static syntax analysis on HarmonyOS project source files and return structured diagnostics. Supported languages: ArkTS and C/C++.",inputSchema:he.object({files:he.array(he.string()).min(1).describe("List of source file paths to check, relative to the project root (absolute paths within the project are also accepted). Supports ArkTS and C/C++ files in the same call.")})},async e=>this.handleCheckCall(e))}registerLspFeatureTools(){if(!this.standardProtocolAvailable){h.info("Skip registering LSP feature tools (hover/definition/declaration/references/implementation, workspaceSymbol, documentSymbol, callHierarchy): standard LSP protocol unavailable (standardIndex/index.js not found). These tools require a DevEco Studio version that ships the standard LSP server entry.");return}let e=he.object({file:he.string().describe("Source file path, relative to the project root (absolute paths within the project are also accepted). Supports .ets (ArkTS) and C/C++ extensions."),line:he.number().describe("Line number (0-based)"),character:he.number().describe("Character offset in the line (0-based)")});for(let{name:t,description:n,feature:o}of this.getPositionFeatures())this.toolRouter.add({name:t,description:n,inputSchema:e},async i=>this.handleLspFeatureCall(o,i));this.registerSymbolTools(),this.registerCallHierarchyTool()}getPositionFeatures(){return[{name:"hover",description:"Get hover information (type info, documentation) at a specific position in an ArkTS (.ets) or C/C++ file.",feature:"hover"},{name:"definition",description:"Find where the symbol at the given position is defined. Returns file path, line, and character.",feature:"definition"},{name:"declaration",description:"Find the declaration of the symbol at the given position. In ArkTS, this may differ from definition.",feature:"declaration"},{name:"references",description:"Find all references to the symbol at the given position across the HarmonyOS project.",feature:"references"},{name:"implementation",description:"Find implementations of the symbol at the given position (e.g., interface implementations).",feature:"implementation"}]}registerSymbolTools(){this.toolRouter.add({name:"workspaceSymbol",description:"Search for symbols by name across the entire HarmonyOS project.",inputSchema:he.object({query:he.string().describe("Symbol name (or partial) to search for")})},async e=>this.handleWorkspaceSymbolCall(e)),this.toolRouter.add({name:"documentSymbol",description:"Get the symbol tree (functions, classes, variables with ranges) of an ArkTS (.ets) or C/C++ file. Useful for file overview, structured code breakdown, and large file slicing.",inputSchema:he.object({file:he.string().describe("Source file path, relative to the project root (absolute paths within the project are also accepted). Supports .ets and C/C++ extensions.")})},async e=>this.handleDocumentSymbolCall(e))}registerCallHierarchyTool(){this.toolRouter.add({name:"callHierarchy",description:'Query call hierarchy for a function at the given position. Use direction "incoming" to find callers, "outgoing" to find callees. ArkTS supports both directions; C/C++ (clangd) supports incoming only.',inputSchema:he.object({file:he.string().describe("Source file path, relative to the project root (absolute paths within the project are also accepted). Supports .ets and C/C++ extensions."),line:he.number().describe("Line number (0-based)"),character:he.number().describe("Character offset in the line (0-based)"),direction:he.enum(["incoming","outgoing"]).describe('"incoming" = who calls this function, "outgoing" = what this function calls')})},async e=>this.handleCallHierarchyCall(e))}detectStandardProtocolAvailable(){try{let e=this.arktsLangServerPath;if(!e)return h.info("Standard LSP protocol unavailable: arkts-lang-server path not found"),!1;let t=gi(e);return h.info(`ArktsCheck protocol: ${t?"standard LSP":"legacy ace-server"} (standardIndex/index.js exists=${t})`),t}catch(e){return h.warn(`Failed to detect standard LSP protocol availability: ${e}`),!1}}async handleCheckCall(e){let t=Array.isArray(e.files)?e.files.filter(d=>typeof d=="string"):[];if(t.length===0)return h.warn("check tool called with empty files list"),{content:[{type:"text",text:"No files provided"}],isError:!0};if(t.length>Dl)return h.warn(`check tool called with ${t.length} files (max: ${Dl})`),{content:[{type:"text",text:`Too many files: ${t.length}. Maximum allowed is ${Dl}.`}],isError:!0};let{etsFiles:n,cppFiles:o,unsupported:i}=Kk(t);i.length>0&&h.warn(`Unsupported file types in check request: ${i.join(", ")}`);let s=i.map(d=>`Unsupported file type: ${d} (only .ets and C/C++ source/header files are supported)`),a=[];n.length>0&&this.mergeCheckResult(await this.callArktsCheck(n),s,a),o.length>0&&this.mergeCheckResult(await this.callCppCheck(o),s,a);let c=s.length>0;return{content:[{type:"text",text:[a.join(`
1317
+ `).trim();return!i&&n.length===0&&(a="No diagnostic information collected"),{content:[{type:"text",text:a}],isError:i}}async checkFile(e){let t=Nr(e),n=await wr.promises.readFile(e,"utf8"),o=yi(e),i=this.manager.registerDiagnosticCallback(t);this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didOpen",params:{textDocument:{uri:t,text:n,languageId:o,version:n.length}}});try{return await i}finally{this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didClose",params:{textDocument:{uri:t}}})}}collectValidFiles(e,t){let n=Qr.resolve(this.manager.projectRoot),o=[];for(let i of e){let s=Qr.resolve(Qr.isAbsolute(i)?i:Qr.join(n,i));if(!wr.existsSync(s)){t.push(`File does not exist: ${i}`);continue}if(!wr.statSync(s).isFile()){t.push(`Not a regular file: ${i}`);continue}if(!Lr(s)){t.push(`Not a supported C/C++ file: ${i}`);continue}try{o.push(wr.realpathSync(s))}catch{o.push(s)}}return o}};function Wk(r,e){if(Array.isArray(e))return e.length===0?`${r} => no diagnostics`:`${r} => Diagnostic: ${JSON.stringify(e)}`;if(e&&typeof e=="object"&&typeof e.errorMessage=="string"){let t=e.errorMessage;return`${r} diagnostic failed, error_message: ${t}`}return`${r} => diagnostic failed, result: ${JSON.stringify(e)}`}function Vk(r){return new Promise(e=>setTimeout(e,r))}import*as Gn from"fs";import*as ia from"path";var Vn=class r{manager;static FEATURE_METHOD_MAP={hover:y.HOVER,definition:y.DEFINITION,declaration:y.DECLARATION,references:y.REFERENCES,implementation:y.IMPLEMENTATION};constructor(e){this.manager=e}async handleLspFeature(e,t){if(!this.manager.ready)return Bn();let n=this.resolveSingleFile(t.file);if(!n)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${t.file}`}],isError:!0};let o=r.FEATURE_METHOD_MAP[e];if(!o)return{content:[{type:"text",text:`Unknown feature: ${e}`}],isError:!0};h.info(`[ClangdLspTool] handleLspFeature: ${e} file=${n} line=${t.line} char=${t.character}`);try{let i=await this.withOpenFile(n,async a=>{let c={textDocument:{uri:a},position:{line:t.line,character:t.character}};return e==="references"&&(c.context={includeDeclaration:!0}),this.manager.sendFeatureRequest(o,c)});return{content:[{type:"text",text:i==null?`${e}: no result`:`${e}: ${JSON.stringify(i,null,2)}`}]}}catch(i){return oa(e,i)}}async handleWorkspaceSymbolRaw(e){if(!this.manager.ready)return null;try{let t=await this.manager.sendFeatureRequest(y.WORKSPACE_SYMBOL,{query:e});return Array.isArray(t)?t:t==null?null:[t]}catch(t){return h.error(`[ClangdLspTool] handleWorkspaceSymbolRaw failed: ${t.message}`),null}}async handleDocumentSymbol(e){if(!this.manager.ready)return Bn();let t=this.resolveSingleFile(e);if(!t)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${e}`}],isError:!0};h.info(`[ClangdLspTool] handleDocumentSymbol: file=${t}`);try{let n=await this.withOpenFile(t,async i=>this.manager.sendFeatureRequest(y.DOCUMENT_SYMBOL,{textDocument:{uri:i}}));return{content:[{type:"text",text:n==null?"documentSymbol: no result":`documentSymbol: ${JSON.stringify(n,null,2)}`}]}}catch(n){return oa("documentSymbol",n)}}async handleCallHierarchy(e){if(!this.manager.ready)return Bn();if(e.direction==="outgoing")return{content:[{type:"text",text:"callHierarchy outgoing is not supported by clangd (incoming only)"}],isError:!0};let t=this.resolveSingleFile(e.file);if(!t)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${e.file}`}],isError:!0};h.info(`[ClangdLspTool] handleCallHierarchy: file=${t} line=${e.line} char=${e.character} direction=${e.direction}`);try{let n=await this.withOpenFile(t,i=>this.fetchCallHierarchyResult(i,e));return{content:[{type:"text",text:`callHierarchy (${e.direction}): ${JSON.stringify(n,null,2)}`}]}}catch(n){return oa("callHierarchy",n)}}async fetchCallHierarchyResult(e,t){let n=await this.manager.sendFeatureRequest(y.PREPARE_CALL_HIERARCHY,{textDocument:{uri:e},position:{line:t.line,character:t.character}}),o=this.normalizeCallHierarchyItems(n);if(o.length===0)return{items:[],calls:[]};let i=await this.collectIncomingCalls(o);return{items:o,calls:i}}normalizeCallHierarchyItems(e){return Array.isArray(e)?e:e?[e]:[]}async collectIncomingCalls(e){let t=[];for(let n of e)t.push(...await this.fetchIncomingCalls(n));return t}async fetchIncomingCalls(e){let t=await this.manager.sendFeatureRequest(y.INCOMING_CALLS,{item:e});return Array.isArray(t)?t:t?[t]:[]}async withOpenFile(e,t){let n=Nr(e),o=await Gn.promises.readFile(e,"utf8"),i=yi(e);h.info(`[ClangdLspTool] withOpenFile didOpen uri=${n} langId=${i} len=${o.length}`),this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didOpen",params:{textDocument:{uri:n,text:o,languageId:i,version:o.length}}});try{return await t(n)}finally{this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didClose",params:{textDocument:{uri:n}}})}}resolveSingleFile(e){let t=ia.isAbsolute(e)?e:ia.join(this.manager.projectRoot,e);return!Gn.existsSync(t)||!Gn.statSync(t).isFile()||!Lr(t)?null:t}};import{spawn as Gk}from"child_process";import*as aa from"fs";import*as Dh from"path";var qk=30*1e3,zk=30*1e3,sa=class{config;client=null;clangdProcess=null;nextRequestId=1;requestCallbacks=new hr;diagnosticWaiters=new Map;lastStartErrorMessage=null;onMessage=()=>{};disposeOnce=null;constructor(e){this.config=e}setOnMessage(e){this.onMessage=e}get clangdPid(){return this.clangdProcess?.pid??null}consumeStartErrorMessage(){let e=this.lastStartErrorMessage;return this.lastStartErrorMessage=null,e}async start(e){let t=!1;try{m.info(`[ClangdLspProxy] clangdPath: ${this.config.clangdPath}`),m.info(`[ClangdLspProxy] workspaceRoot: ${this.config.workspaceRoot}`),m.info(`[ClangdLspProxy] compileCommandsDir: ${this.config.compileCommandsDir}`),this.ensureLogDir(),this.clangdProcess=this.spawnClangd();let n={serverPath:"",logPath:this.config.logPath,indexingDataLocation:this.config.logPath,cwd:this.config.workspaceRoot};this.client=new mr(n),this.client.on("message",i=>this.handleRawMessage(i)),this.client.on("error",i=>this.handleError(i)),this.client.attachProcess(this.clangdProcess,{stderrAsError:!1});let o=this.buildInitializeParams();await this.sendLspRequest(y.INITIALIZE,o,rt),m.info("[ClangdLspProxy] initialize response received"),this.sendNotification(y.INITIALIZED,{}),t=!0}catch(n){this.lastStartErrorMessage=n instanceof Error?n.message:String(n),m.error(`[ClangdLspProxy] initialization failed: ${this.lastStartErrorMessage}`),await this.dispose()}e?.(t)}async hover(e){return this.sendLspRequest(y.HOVER,e)}async definition(e){return this.sendLspRequest(y.DEFINITION,e)}async declaration(e){return this.sendLspRequest(y.DECLARATION,e)}async references(e){return this.sendLspRequest(y.REFERENCES,e)}async implementation(e){return this.sendLspRequest(y.IMPLEMENTATION,e)}async documentSymbol(e){return this.sendLspRequest(y.DOCUMENT_SYMBOL,e)}async workspaceSymbol(e){return this.sendLspRequest(y.WORKSPACE_SYMBOL,e)}async prepareCallHierarchy(e){return this.sendLspRequest(y.PREPARE_CALL_HIERARCHY,e)}async incomingCalls(e){return this.sendLspRequest(y.INCOMING_CALLS,e)}async sendFeatureRequest(e,t){return this.sendLspRequest(e,t)}sendDidOpen(e){this.sendNotification(y.DID_OPEN,e)}sendDidChange(e){this.sendNotification(y.DID_CHANGE,e)}sendDidClose(e){this.sendNotification(y.DID_CLOSE,e)}sendNotification(e,t){if(!this.client){m.warn("[ClangdLspProxy] sendNotification before ready, dropped");return}this.client.sendNotification(e,t)}registerDiagnosticCallback(e){let t=this.normalizeClangdUri(e);if(this.diagnosticWaiters.has(t)){m.warn(`[ClangdLspProxy] overwrite existing diagnostic waiter for ${t}`);let n=this.diagnosticWaiters.get(t);clearTimeout(n.timer),this.diagnosticWaiters.delete(t)}return new Promise((n,o)=>{let i=setTimeout(()=>{this.diagnosticWaiters.delete(t)&&o(new Error(`Wait for clangd diagnostics timeout, uri: ${t}`))},zk);this.diagnosticWaiters.set(t,{resolve:n,reject:o,timer:i})})}async dispose(){return this.disposeOnce||(this.disposeOnce=this.performDispose()),this.disposeOnce}async performDispose(){this.requestCallbacks.rejectAll(new Error("ClangdLspProxy disposing"));for(let[,e]of this.diagnosticWaiters)clearTimeout(e.timer),e.reject(new Error("ClangdLspProxy disposing"));if(this.diagnosticWaiters.clear(),this.client&&this.clangdProcess)try{await this.sendLspRequest(y.SHUTDOWN,null,3e3).catch(e=>{m.warn(`[ClangdLspProxy] shutdown request failed: ${e}`)}),this.sendNotification(y.EXIT,null),await this.client.waitForExitOrTimeout(300)}catch(e){m.warn(`[ClangdLspProxy] dispose error: ${e}`)}if(this.clangdProcess){try{this.clangdProcess.exitCode===null&&this.clangdProcess.signalCode===null&&this.clangdProcess.kill()}catch{}this.clangdProcess=null}this.client=null}spawnClangd(){let e=[`--compile-commands-dir=${z(this.config.compileCommandsDir)}`,"--log=info","--pch-storage=memory","--limit-results=100"];m.info(`[ClangdLspProxy] spawn: ${this.config.clangdPath} ${e.join(" ")}`);let t=Gk(this.config.clangdPath,e,{cwd:this.config.workspaceRoot,stdio:["pipe","pipe","pipe"],windowsHide:!0});if(!t.stdin||!t.stdout||!t.stderr)throw new Error("Failed to spawn clangd: stdio not available");return t}buildInitializeParams(){let e=dn(this.config.workspaceRoot),t=mt(e),n=Dh.basename(e)||"workspace";return{processId:process.pid,clientInfo:{name:"devecocli-mcp-server",version:"1.3.3-Test.4"},rootPath:e,rootUri:t,workspaceFolders:[{uri:t,name:n}],capabilities:this.buildClientCapabilities(),initializationOptions:null}}buildClientCapabilities(){return{textDocument:{synchronization:{didOpen:!0,didChange:!0,didClose:!0,willSave:!1,save:!1},publishDiagnostics:{relatedInformation:!0,versionSupport:!1,tagSupport:{valueSet:[1,2]}},hover:{contentFormat:["markdown","plaintext"]},completion:{contextSupport:!1,completionItemKind:{valueSet:[]}},signatureHelp:{signatureInformation:{documentationFormat:["markdown","plaintext"]}},references:{},declaration:{linkSupport:!0},definition:{linkSupport:!0},implementation:{linkSupport:!0},documentSymbol:{hierarchicalDocumentSymbolSupport:!0,symbolKind:{valueSet:[]}},callHierarchy:{dynamicRegistration:!1}},workspace:{symbol:{symbolKind:{valueSet:[]}},configuration:!1,didChangeWatchedFiles:{dynamicRegistration:!1}}}}sendLspRequest(e,t,n=qk){if(!this.client)return Promise.reject(new Error("[ClangdLspProxy] client not ready"));let o=this.nextRequestId++,i=this.requestCallbacks.registerPending(o,e,n);return this.client.sendRequest(e,t,o),i}handleRawMessage(e){let t;try{t=JSON.parse(e)}catch(n){let o=n instanceof Error?n.message:String(n);m.error(`[ClangdLspProxy] JSON parse error: ${o}, raw: ${e.slice(0,200)}`);return}"id"in t&&("result"in t||"error"in t)?this.handleResponse(t):"method"in t?this.handleNotification(t):m.warn(`[ClangdLspProxy] unrecognized message: ${JSON.stringify(t).slice(0,200)}`)}handleResponse(e){let t=e.id;if(t==null||typeof t!="string"&&typeof t!="number")return;let n=t;if(e.error!==void 0&&e.error!==null){let o=e.error;m.warn(`[ClangdLspProxy] LSP error id=${n}: code=${o.code??-1} message=${o.message??"unknown"}`),this.requestCallbacks.rejectPending(n,new Error(`LSP error ${o.code??-1}: ${o.message??"unknown"}`))}else this.requestCallbacks.resolvePending(n,e.result)}handleNotification(e){let t=e.method;if(t)switch(t){case y.PUBLISH_DIAGNOSTICS:this.handlePublishDiagnostics(e.params);break;case y.PROGRESS:this.onMessage({jsonrpc:T,method:y.PROGRESS,params:e.params});break;case y.WINDOW_SHOW_MESSAGE:m.info(`[ClangdLspProxy] window/showMessage: ${JSON.stringify(e.params)}`);break;case y.WINDOW_LOG_MESSAGE:m.info(`[ClangdLspProxy] window/logMessage: ${JSON.stringify(e.params)}`);break;default:this.onMessage({jsonrpc:T,method:t,params:e.params})}}handlePublishDiagnostics(e){if(!e||!e.uri)return;let t=this.normalizeClangdUri(e.uri),n=this.diagnosticWaiters.get(t);if(!n&&this.diagnosticWaiters.size===1){let s=this.diagnosticWaiters.keys().next().value;n=this.diagnosticWaiters.get(s),n&&this.diagnosticWaiters.delete(s)}else n&&this.diagnosticWaiters.delete(t);if(!n)return;clearTimeout(n.timer);let o=Array.isArray(e.diagnostics)?e.diagnostics:[],i=o.length;m.info(`[ClangdLspProxy] diagnostics received uri=${t} count=${i}`),n.resolve(o)}handleError(e){for(let[,t]of this.diagnosticWaiters)clearTimeout(t.timer),t.reject(e);this.diagnosticWaiters.clear(),this.requestCallbacks.rejectAll(e),this.onMessage({jsonrpc:T,method:y.CPP_ERROR,params:{message:e.message}})}ensureLogDir(){if(this.config.logPath)try{aa.existsSync(this.config.logPath)||aa.mkdirSync(this.config.logPath,{recursive:!0})}catch{}}normalizeClangdUri(e){try{let t=new URL(e);if(t.protocol==="file:"){let n=decodeURIComponent(t.pathname);return process.platform==="win32"&&/^\/[a-zA-Z]:/.test(n)&&(n=n.slice(1)),mt(n)}}catch{}return e}};import*as Ko from"path";import*as Il from"fs";var Xo=class r{config;proxy=null;isInitialized=!1;onMessage=()=>{};disposeOnce=null;initPromise=null;initDeadlineTimer=null;initResolve=null;initReject=null;resolvedRoot="";constructor(e){this.config=e}setOnMessage(e){this.onMessage=e}get ready(){return this.isInitialized&&this.proxy!==null}get clangdPid(){return this.proxy?.clangdPid??null}get projectRoot(){return this.resolvedRoot}async start(){if(!this.isInitialized){if(this.initPromise){await this.initPromise;return}this.initPromise=this.doStart();try{await this.initPromise}catch(e){throw this.initPromise=null,e}}}sendNotification(e){if(!this.proxy){m.warn("[ClangdLspManager] sendNotification before LSP ready, dropped");return}this.dispatchNotification(e)}async sendFeatureRequest(e,t){if(!this.proxy)throw new Error("[ClangdLspManager] LSP not ready");return this.proxy.sendFeatureRequest(e,t)}registerDiagnosticCallback(e){return this.proxy?this.proxy.registerDiagnosticCallback(e):Promise.reject(new Error("[ClangdLspManager] LSP not ready"))}static async handleSyncCppProject(e,t,n,o,i){if(m.info("[ClangdLspManager] Received cpp/syncProject"),!e||!t)return m.error("[ClangdLspManager] handleSyncCppProject: workspaceRoot or sdkPath is empty"),{status:"failed",reason:"workspaceRoot or sdkPath is empty"};if(rr(e).length===0)return m.info("[ClangdLspManager] No C++ modules found, skipping compileNative"),{status:"success"};let a=i?.skipCompileNative===!0,c=await Di(e,a?async()=>(m.info("[ClangdLspManager] compileNative skipped (C++ project up-to-date)"),{status:"success"}):async()=>r.executeCompileNative(e,t,n,o));return c.acquired?c.result:(m.info("[ClangdLspManager] Build lock held by another process, skipping sync"),{status:"skipped",reason:"build lock held by another process"})}static async executeCompileNative(e,t,n,o){try{return await Tu(e,t,n,o),m.info("[ClangdLspManager] compileNative + merge compile_commands completed"),{status:"success"}}catch(i){let s=i instanceof Error?i.message:String(i);return m.error(`[ClangdLspManager] compileNative failed: ${s}`),{status:"failed",reason:s}}}async dispose(){return this.disposeOnce||(this.disposeOnce=this.performDispose()),this.disposeOnce}doStart(){return new Promise((e,t)=>{this.initResolve=e,this.initReject=t,this.armInitTimer(rt);try{this.startProxy()}catch(n){this.failInit(n instanceof Error?n:new Error(String(n)))}})}startProxy(){let e=Lt(this.config.workspaceRoot);this.resolvedRoot=e?ge(e):ge(this.config.workspaceRoot);let t=this.config.logPath??this.getLogPath();Li(t);let n=this.config.clangdPath;if(!n){let s="clangd not found (install DevEco Studio / CLT)";m.error(`[ClangdLspManager] ${s}`),this.failInit(new Error(s));return}let o=Ko.dirname(xr(this.resolvedRoot));try{Il.mkdirSync(o,{recursive:!0})}catch(s){m.warn(`[ClangdLspManager] Failed to create compile_commands dir: ${s}`)}m.info(`[ClangdLspManager] clangdPath: ${n}`),m.info(`[ClangdLspManager] workspaceRoot: ${this.resolvedRoot}`),m.info(`[ClangdLspManager] compileCommandsDir: ${o}`);let i=new sa({clangdPath:n,workspaceRoot:this.resolvedRoot,compileCommandsDir:o,logPath:t});i.setOnMessage(s=>this.handleLspMessage(s)),this.proxy=i,i.start(s=>this.handleProxyInitialized(s)).catch(s=>{let a=s instanceof Error?s:new Error(String(s));this.handleProxyInitialized(!1,a.message)})}handleProxyInitialized=(e,t)=>{if(this.clearInitTimer(),e){this.isInitialized=!0,m.info("[ClangdLspManager] clangd initialized");let n=this.initResolve;this.clearInitHandlers(),n?.()}else{let n=t??this.proxy?.consumeStartErrorMessage()??"unknown error";m.error(`[ClangdLspManager] clangd initialization failed: ${n}`),this.isInitialized=!1,this.proxy=null;let o=this.initReject;this.clearInitHandlers(),o?.(new Error(`C++ LSP initialize failed: ${n}`))}};handleLspMessage(e){this.onMessage(e)}dispatchNotification(e){if(!this.proxy)return;let t=e,n=t.method;if(!n){m.warn("[ClangdLspManager] dispatchNotification: missing method");return}let o=t.params;switch(n){case y.DID_OPEN:this.proxy.sendDidOpen(o);break;case y.DID_CHANGE:this.proxy.sendDidChange(o);break;case y.DID_CLOSE:this.proxy.sendDidClose(o);break;default:this.proxy.sendNotification(n,o)}}armInitTimer(e){this.clearInitTimer(),this.initDeadlineTimer=setTimeout(()=>{this.failInit(new Error("C++ LSP initialize timeout"))},e)}clearInitTimer(){this.initDeadlineTimer&&(clearTimeout(this.initDeadlineTimer),this.initDeadlineTimer=null)}clearInitHandlers(){this.clearInitTimer(),this.initResolve=null,this.initReject=null}failInit(e){let t=this.initReject;this.clearInitHandlers(),t?.(e)}async performDispose(){let e=this.initReject;if(this.clearInitHandlers(),e?.(new Error("ClangdLspManager disposing")),this.proxy){try{await this.proxy.dispose()}catch(t){m.warn(`[ClangdLspManager] proxy dispose error: ${t}`)}this.proxy=null}this.isInitialized=!1,this.initPromise=null}getLogPath(){try{let e=Ko.join(Kt(),"CppCheck"),t=`${Date.now()}${process.hrtime.bigint()%1000000n}`,n=Ko.join(e,"lsp-log",t);return Il.mkdirSync(n,{recursive:!0}),ge(n)}catch{return"auto"}}};function Rh(r){let e=Ti(r);return m.info(`[SyncGuard] ${e.reason}`),e}var Rl=(s=>(s[s.IDLE=0]="IDLE",s[s.DISCOVERING=1]="DISCOVERING",s[s.SYNCING=2]="SYNCING",s[s.INITIALIZING=3]="INITIALIZING",s[s.READY=4]="READY",s[s.ERROR=5]="ERROR",s))(Rl||{}),Th=(s=>(s[s.IDLE_CPP=0]="IDLE_CPP",s[s.DISCOVERING_CPP=1]="DISCOVERING_CPP",s[s.SYNCING_CPP=2]="SYNCING_CPP",s[s.INITIALIZING_CPP=3]="INITIALIZING_CPP",s[s.READY_CPP=4]="READY_CPP",s[s.ERROR_CPP=5]="ERROR_CPP",s))(Th||{}),Tt=3,Al=600*1e3,Dl=100,ca=class{server;toolRouter;config={};arktsCheckTool=null;cppCheckTool=null;cppLspTool=null;cppLspManager=null;projectState=0;workspaceRoot="";sdkPath="";arktsLangServerPath=null;nodePath="";ohpmJsPath="";hvigorJsPath="";clangdPath=null;initPromise=null;needsReinit=!1;initRetryCount=0;originalProjectPath="";configChangedTriggeredResync=!1;syncSkippedDueToLock=!1;syncSkipStartedAt=0;standardProtocolAvailable=!1;cppProjectState=0;cppInitPromise=null;cppNeedsReinit=!1;cppInitRetryCount=0;cppSyncSkippedDueToLock=!1;cppSyncSkipStartedAt=0;cppHasNoCppCode=!1;cppEnabled;constructor(e={}){this.config=e,Mr(e.debug??!1);let t,n=e.projectPath?.trim()??"";this.originalProjectPath=n,n==="."?(t=process.cwd(),h.info(`Constructor: configuredPath is '.', startPath: '${t}'`)):n===""?(t="",h.info("Constructor: configuredPath is empty, startPath remains empty")):(t=n,h.info(`Constructor: using configured path as startPath: '${t}'`));let o=Lt(t);h.info(`Constructor: findHarmonyProject('${t}') => ${o??"null"}`),this.config.projectPath=o??void 0,this.sdkPath=this.config.sdkPath??"",this.arktsLangServerPath=this.config.arktsLangServerPath??null,this.nodePath=this.config.nodePath??"",this.ohpmJsPath=this.config.ohpmJsPath??"",this.hvigorJsPath=this.config.hvigorJsPath??"",this.clangdPath=this.config.clangdPath??null,this.cppEnabled=this.config.cppEnabled??!0,h.info(`Constructor: sdkPath='${this.sdkPath}', arktsLangServerPath='${this.arktsLangServerPath??"(null)"}', cppEnabled=${this.cppEnabled}`),this.server=new Jk({name:"devecocli-mcp-server",version:"0.0.1"}),this.toolRouter=El(e.telemetry,()=>this.arktsCheckTool?.aceServerPid??null,()=>this.config.projectPath??"",()=>this.sdkPath??""),this.standardProtocolAvailable=this.detectStandardProtocolAvailable(),this.registerTools()}registerTools(){this.registerCheckTool(),this.registerLspFeatureTools(),this.registerRestartTool()}registerRestartTool(){this.toolRouter.add({name:"restart",description:"Restart the MCP server in-place: re-sync the project and re-initialize the LSP, without dropping the client connection. Use to recover from a stuck/ERROR state after fixing the root cause, instead of exiting and reopening the agent. Use target to restart one side only (arkts/cpp) or both (all, default). Only callable when the project state is ready/idle/error; during discovery/sync/init (large-project init can take minutes) it returns an error\u2014wait for ready and retry tools instead. Caution: if initialization fails again after a restart, the cause is likely a persistent project/SDK configuration issue\u2014do not call restart repeatedly; ask the user to fix the project first.",inputSchema:he.object({target:he.enum(["arkts","cpp","all"]).default("all").describe('Which backend to restart: "arkts" (ArkTS ace-server), "cpp" (C++ clangd), or "all" (both, default).')})},async e=>this.handleRestartCall(e))}registerCheckTool(){this.toolRouter.add({name:"check",description:"Perform static syntax analysis on HarmonyOS project source files and return structured diagnostics. Supported languages: ArkTS and C/C++.",inputSchema:he.object({files:he.array(he.string()).min(1).describe("List of source file paths to check, relative to the project root (absolute paths within the project are also accepted). Supports ArkTS and C/C++ files in the same call.")})},async e=>this.handleCheckCall(e))}registerLspFeatureTools(){if(!this.standardProtocolAvailable){h.info("Skip registering LSP feature tools (hover/definition/declaration/references/implementation, workspaceSymbol, documentSymbol, callHierarchy): standard LSP protocol unavailable (standardIndex/index.js not found). These tools require a DevEco Studio version that ships the standard LSP server entry.");return}let e=he.object({file:he.string().describe("Source file path, relative to the project root (absolute paths within the project are also accepted). Supports .ets (ArkTS) and C/C++ extensions."),line:he.number().describe("Line number (0-based)"),character:he.number().describe("Character offset in the line (0-based)")});for(let{name:t,description:n,feature:o}of this.getPositionFeatures())this.toolRouter.add({name:t,description:n,inputSchema:e},async i=>this.handleLspFeatureCall(o,i));this.registerSymbolTools(),this.registerCallHierarchyTool()}getPositionFeatures(){return[{name:"hover",description:"Get hover information (type info, documentation) at a specific position in an ArkTS (.ets) or C/C++ file.",feature:"hover"},{name:"definition",description:"Find where the symbol at the given position is defined. Returns file path, line, and character.",feature:"definition"},{name:"declaration",description:"Find the declaration of the symbol at the given position. In ArkTS, this may differ from definition.",feature:"declaration"},{name:"references",description:"Find all references to the symbol at the given position across the HarmonyOS project.",feature:"references"},{name:"implementation",description:"Find implementations of the symbol at the given position (e.g., interface implementations).",feature:"implementation"}]}registerSymbolTools(){this.toolRouter.add({name:"workspaceSymbol",description:"Search for symbols by name across the entire HarmonyOS project.",inputSchema:he.object({query:he.string().describe("Symbol name (or partial) to search for")})},async e=>this.handleWorkspaceSymbolCall(e)),this.toolRouter.add({name:"documentSymbol",description:"Get the symbol tree (functions, classes, variables with ranges) of an ArkTS (.ets) or C/C++ file. Useful for file overview, structured code breakdown, and large file slicing.",inputSchema:he.object({file:he.string().describe("Source file path, relative to the project root (absolute paths within the project are also accepted). Supports .ets and C/C++ extensions.")})},async e=>this.handleDocumentSymbolCall(e))}registerCallHierarchyTool(){this.toolRouter.add({name:"callHierarchy",description:'Query call hierarchy for a function at the given position. Use direction "incoming" to find callers, "outgoing" to find callees. ArkTS supports both directions; C/C++ (clangd) supports incoming only.',inputSchema:he.object({file:he.string().describe("Source file path, relative to the project root (absolute paths within the project are also accepted). Supports .ets and C/C++ extensions."),line:he.number().describe("Line number (0-based)"),character:he.number().describe("Character offset in the line (0-based)"),direction:he.enum(["incoming","outgoing"]).describe('"incoming" = who calls this function, "outgoing" = what this function calls')})},async e=>this.handleCallHierarchyCall(e))}detectStandardProtocolAvailable(){try{let e=this.arktsLangServerPath;if(!e)return h.info("Standard LSP protocol unavailable: arkts-lang-server path not found"),!1;let t=gi(e);return h.info(`ArktsCheck protocol: ${t?"standard LSP":"legacy ace-server"} (standardIndex/index.js exists=${t})`),t}catch(e){return h.warn(`Failed to detect standard LSP protocol availability: ${e}`),!1}}async handleCheckCall(e){let t=Array.isArray(e.files)?e.files.filter(d=>typeof d=="string"):[];if(t.length===0)return h.warn("check tool called with empty files list"),{content:[{type:"text",text:"No files provided"}],isError:!0};if(t.length>Dl)return h.warn(`check tool called with ${t.length} files (max: ${Dl})`),{content:[{type:"text",text:`Too many files: ${t.length}. Maximum allowed is ${Dl}.`}],isError:!0};let{etsFiles:n,cppFiles:o,unsupported:i}=Kk(t);i.length>0&&h.warn(`Unsupported file types in check request: ${i.join(", ")}`);let s=i.map(d=>`Unsupported file type: ${d} (only .ets and C/C++ source/header files are supported)`),a=[];n.length>0&&this.mergeCheckResult(await this.callArktsCheck(n),s,a),o.length>0&&this.mergeCheckResult(await this.callCppCheck(o),s,a);let c=s.length>0;return{content:[{type:"text",text:[a.join(`
1318
1318
  `),s.join(`
1319
1319
  `)].filter(d=>d.trim().length>0).join(`
1320
1320
  `).trim()||"No diagnostics collected"}],isError:c}}async callArktsCheck(e){switch(this.projectState){case 0:return this.handleIdleCheck();case 1:case 2:return h.warn(`ArkTS check rejected: project is ${Rl[this.projectState]}, files: ${e.join(", ")}`),{content:[{type:"text",text:"Project is syncing, please retry in 10 seconds"}],isError:!0};case 3:return h.warn(`ArkTS check rejected: LSP is initializing, files: ${e.join(", ")}`),{content:[{type:"text",text:"ArkTS LSP is initializing, please retry in 10 seconds"}],isError:!0};case 5:return this.handleErrorCheck();case 4:return this.arktsCheckTool.handleCall({files:e});default:return h.error(`ArkTS check: unknown project state ${this.projectState}, files: ${e.join(", ")}`),{content:[{type:"text",text:`Unknown project state: ${this.projectState}`}],isError:!0}}}async handleLspFeatureCall(e,t){let n=t.file,o=t.line,i=t.character;return typeof n!="string"||typeof o!="number"||typeof i!="number"?{content:[{type:"text",text:"Missing or invalid parameters. Required: file (string), line (number), character (number)."}],isError:!0}:this.routeLspRequest(n,e,async()=>{if(n.endsWith(".ets"))return this.arktsCheckTool.handleLspFeature(e,{file:n,line:o,character:i});let s=e;return this.cppLspTool.handleLspFeature(s,{file:n,line:o,character:i})})}async handleWorkspaceSymbolCall(e){let t=e.query;return typeof t!="string"||t.trim().length===0?{content:[{type:"text",text:"Missing or invalid parameter: query (non-empty string required)."}],isError:!0}:this.routeWorkspaceSymbolRequest(t)}async routeWorkspaceSymbolRequest(e){let t=this.projectState===4&&this.arktsCheckTool!==null,n=this.cppProjectState===4&&!this.cppHasNoCppCode&&this.cppLspTool!==null;if(!t&&!n){let a=this.describeArktsState(),c=this.describeCppState();return h.info(`workspaceSymbol rejected: ArkTS ${a}; C++ ${c}`),{content:[{type:"text",text:`workspaceSymbol: ArkTS ${a}; C++ ${c}`}],isError:!0}}let o=[],i=new Set;if(t)try{this.mergeSymbolItems(await this.arktsCheckTool.handleWorkspaceSymbolRaw(e),i,o)}catch(a){h.warn(`workspaceSymbol ArkTS query failed: ${a.message}`)}if(n)try{this.mergeSymbolItems(await this.cppLspTool.handleWorkspaceSymbolRaw(e),i,o)}catch(a){h.warn(`workspaceSymbol C++ query failed: ${a.message}`)}return{content:[{type:"text",text:o.length===0?"workspaceSymbol: no result":`workspaceSymbol: ${JSON.stringify(o,null,2)}`}]}}symbolDedupKey(e){let t=e,n=t?.location?.uri??"",o=t?.location?.range?.start?.line??0,i=t?.location?.range?.start?.character??0;return`${n}:${o}:${i}`}mergeSymbolItems(e,t,n){if(e)for(let o of e){let i=this.symbolDedupKey(o);t.has(i)||(t.add(i),n.push(o))}}describeArktsState(){switch(this.projectState){case 0:return"idle";case 1:return"discovering";case 2:return"syncing (retry 10s)";case 3:return"initializing (retry 10s)";case 5:return`error (${this.initRetryCount}/${Tt})`;case 4:return"ready";default:return"unknown"}}describeCppState(){switch(this.cppProjectState){case 0:return"idle";case 1:return"discovering";case 2:return"syncing (retry 25s)";case 3:return"initializing (retry 10s)";case 5:return`error (${this.cppInitRetryCount}/${Tt})`;case 4:return this.cppHasNoCppCode?"ready (no C++ code)":"ready";default:return"unknown"}}async handleDocumentSymbolCall(e){let t=e.file;return typeof t!="string"?{content:[{type:"text",text:"Missing or invalid parameter: file (string required)."}],isError:!0}:this.routeLspRequest(t,"documentSymbol",async()=>t.endsWith(".ets")?this.arktsCheckTool.handleDocumentSymbol(t):this.cppLspTool.handleDocumentSymbol(t))}async handleCallHierarchyCall(e){let t=e.file,n=e.line,o=e.character,i=e.direction;return typeof t!="string"||typeof n!="number"||typeof o!="number"?{content:[{type:"text",text:"Missing or invalid parameters. Required: file (string), line (number), character (number)."}],isError:!0}:i!=="incoming"&&i!=="outgoing"?{content:[{type:"text",text:'Parameter direction must be "incoming" or "outgoing".'}],isError:!0}:this.routeLspRequest(t,`callHierarchy(${i})`,async()=>t.endsWith(".ets")?this.arktsCheckTool.handleCallHierarchy({file:t,line:n,character:o,direction:i}):this.cppLspTool.handleCallHierarchy({file:t,line:n,character:o,direction:i}))}async routeArktsRequest(e,t){switch(this.projectState){case 0:return this.handleIdleCheck();case 1:case 2:return h.warn(`ArkTS ${e} rejected: project is ${Rl[this.projectState]}`),{content:[{type:"text",text:"Project is syncing, please retry in 10 seconds"}],isError:!0};case 3:return h.warn(`ArkTS ${e} rejected: LSP is initializing`),{content:[{type:"text",text:"ArkTS LSP is initializing, please retry in 10 seconds"}],isError:!0};case 5:return this.handleErrorCheck();case 4:return t();default:return h.warn(`ArkTS ${e} rejected: unknown project state ${this.projectState}`),{content:[{type:"text",text:"Unknown project state, please retry"}],isError:!0}}}async handleIdleCheck(){if(this.ensureProjectReady(),this.config.projectPath){let e,t;return this.syncSkippedDueToLock?(e=`Another build process is running, sync deferred (waiting ${this.syncSkipStartedAt>0?Math.round((Date.now()-this.syncSkipStartedAt)/1e3):0}s), please retry in 25 seconds`,t="lock contention",this.syncSkippedDueToLock=!1):this.configChangedTriggeredResync?(e="Config file changed, resyncing project, please retry in 10 seconds",t="config changed",this.configChangedTriggeredResync=!1):(e="HarmonyOS project detected, syncing, please retry in 10 seconds",t="initial"),h.info(`Idle check: project '${this.config.projectPath}' already known, triggering init (${t})`),{content:[{type:"text",text:e}],isError:!0}}return this.workspaceRoot||this.originalProjectPath?(h.info(`Idle check: no project path yet, will try from '${this.workspaceRoot}' or '${this.originalProjectPath}'`),{content:[{type:"text",text:"Initializing, please retry in 10 seconds"}],isError:!0}):(h.warn("Idle check: no search candidates available"),{content:[{type:"text",text:"No HarmonyOS project detected. Please verify the project directory or create a project first."}],isError:!0})}async handleErrorCheck(){return this.initRetryCount>=Tt?(h.error(`Init retry limit reached (${this.initRetryCount}/${Tt}), will not auto-retry`),{content:[{type:"text",text:`Project initialization failed repeatedly (auto-retry exhausted: ${this.initRetryCount}/${Tt}). Ask the user to investigate and confirm \`ohpm install\` + \`hvigor\` sync succeed manually. Do NOT call the \`restart\` tool repeatedly \u2014 call it at most once after the user fixes the root cause; if it fails again, stop retrying and escalate to the user.`}],isError:!0}):(h.info(`Error check: auto-retrying (${this.initRetryCount}/${Tt})`),this.ensureProjectReady(),{content:[{type:"text",text:"Project initialization failed, auto-retrying, please retry in 10 seconds"}],isError:!0})}async routeCppRequest(e,t){switch(this.cppProjectState){case 0:return this.handleCppIdleCheck();case 1:case 2:return h.warn(`C++ ${e} rejected: C++ project is ${Th[this.cppProjectState]}`),{content:[{type:"text",text:"C++ project is syncing (compileNative), please retry in 25 seconds"}],isError:!0};case 3:return h.warn(`C++ ${e} rejected: clangd is initializing`),{content:[{type:"text",text:"C++ LSP (clangd) is initializing, please retry in 10 seconds"}],isError:!0};case 5:return this.handleCppErrorCheck();case 4:return this.cppEnabled?this.cppHasNoCppCode?{content:[{type:"text",text:"No C++ code in this project"}],isError:!0}:this.cppLspManager?.ready?t():{content:[{type:"text",text:"C++ LSP is not ready, please retry later"}],isError:!0}:{content:[{type:"text",text:"C++ LSP is disabled. Set DEVECO_CLI_CPP_ENABLED=true to enable."}],isError:!0};default:return h.warn(`C++ ${e} rejected: unknown C++ project state ${this.cppProjectState}`),{content:[{type:"text",text:"Unknown C++ project state, please retry"}],isError:!0}}}async routeLspRequest(e,t,n){return e.endsWith(".ets")?this.routeArktsRequest(t,n):Lr(e)?this.routeCppRequest(t,n):{content:[{type:"text",text:`Unsupported file type: ${e} (only .ets and C/C++ source/header files are supported)`}],isError:!0}}async handleCppIdleCheck(){if(this.ensureCppProjectReady(),this.config.projectPath){let e;return this.cppSyncSkippedDueToLock?(e=`Another build process is running, C++ sync deferred (waiting ${this.cppSyncSkipStartedAt>0?Math.round((Date.now()-this.cppSyncSkipStartedAt)/1e3):0}s), please retry in 25 seconds`,this.cppSyncSkippedDueToLock=!1):e="C++ project detected, syncing (compileNative), please retry in 25 seconds",h.info(`C++ idle check: project '${this.config.projectPath}', triggering C++ init`),{content:[{type:"text",text:e}],isError:!0}}return{content:[{type:"text",text:"No HarmonyOS project detected for C++ tools."}],isError:!0}}async handleCppErrorCheck(){return this.cppInitRetryCount>=Tt?(h.error(`C++ init retry limit reached (${this.cppInitRetryCount}/${Tt}), will not auto-retry`),{content:[{type:"text",text:`C++ project initialization failed repeatedly (auto-retry exhausted: ${this.cppInitRetryCount}/${Tt}). Ask the user to investigate and confirm \`hvigor compileNative\` succeeds manually. Do NOT call the \`restart\` tool repeatedly \u2014 call it at most once after the user fixes the root cause; if it fails again, stop retrying and escalate to the user.`}],isError:!0}):(h.info(`C++ error check: auto-retrying (${this.cppInitRetryCount}/${Tt})`),this.ensureCppProjectReady(),{content:[{type:"text",text:"C++ project initialization failed, auto-retrying, please retry in 25 seconds"}],isError:!0})}async callCppCheck(e){return this.routeCppRequest("check",async()=>this.cppCheckTool.handleCall({files:e}))}mergeCheckResult(e,t,n){let o=e.content.map(i=>i.text).filter(i=>i&&i.trim().length>0).join(`
@@ -1362,4 +1362,4 @@ Run \`devecocli compat versions\` to see all available versions.`)}if(r.sourceVe
1362
1362
  `)){let i=o.trim();if(!i||i.startsWith("[Empty]"))continue;let s=i.split(/\s+/),a=s[0],c=s.length>=2?s[1]:"device";a&&!a.startsWith("[Empty]")&&c.toLowerCase()!=="unauthorized"&&t.push(a)}let n=[];for(let o of t)try{let i=await wT(o,r),s=await bT(o,r);i.length>0&&n.push({id:"",udid:i,deviceName:s})}catch{u(`Failed to get device info for ${o}, skipping`)}return n}async function wT(r,e){let{stdout:t}=await Sd(e,["-t",r,"shell","bm","get","-u"],{stdio:["ignore","pipe","pipe"]}),n=t.trim();if(!n)return"";let o=n.split(`
1363
1363
  `);for(let s=0;s<o.length-1;s++)if(o[s].includes("udid of current device is")){let c=o[s+1].trim().match(/^[A-Fa-f0-9]{64}$/);if(c)return c[0].toUpperCase()}let i=n.match(/[A-Fa-f0-9]{64}/);return i?i[0].toUpperCase():""}async function bT(r,e){let{stdout:t}=await Sd(e,["-c","-t",r,"shell","getprop","hw_sc.build.os.deviceType"],{stdio:["ignore","pipe","pipe"]});return ST(t)}function ST(r){let e=r.trim();return!e||e.includes("inaccessible")?"phone":r.includes("liteWearable")?"liteWearable":r.includes("wearable")?"wearable":r.includes("tv")?"tv":"phone"}import nn from"fs";import{createHash as ET}from"crypto";import{debuglog as Yt}from"util";import{Buffer as py}from"buffer";import{createPublicKey as PT,X509Certificate as Ed}from"crypto";import{readFileSync as CT}from"fs";import on from"node-forge";async function fy(r,e){console.log("Start generating profile");let{productName:t,bundleName:n,projectPath:o,aclPermissionList:i,allDeviceIds:s,certIds:a,keyAlias:c,keyPwd:l}=e;if(s==null||s.length===0)throw new Error(E.DEVICE_LIST_EMPTY);let d=`${ce.BASE_URL}${ce.PROVISION_ADD_TEST_PATH}`,g=kT(t,n),v=await AT(r,d,a||[],n,s,g,i||[]);if(!v||!v.profileInfo||!v.profileInfo.provisionFileUrl)throw Yt("add provision failed, the provision file url is null"),new Error(E.ADD_PROFILE_FAIL);let P=v.profileInfo,B=(await xT(r,P.provisionFileUrl)).urlList,Ae=v.profileInfo.id;if(B&&B.length>0){let Ze=await Wg(t,o),St=Ze.profilePath;if(!await LT(B,St))throw await uy(r,Ae),new Error(E.ERROR_WHILE_DOWNLOAD_PROFILE);if(await uy(r,Ae),nn.existsSync(Ze.certPath)&&nn.existsSync(St)&&nn.existsSync(Ze.p12Path)){let Ma=nn.readFileSync(Ze.certPath,"utf8"),Oa=nn.readFileSync(St,"utf8");return NT(Oa,Ma,Ze.p12Path,c,l)||TT(St),St}}throw new Error(E.ADD_PROFILE_FAIL)}function kT(r,e){let t=r?`${r}_`:"";return`${IT(`${t}${e}_${e}`)}`}function IT(r){return ET("sha256").update(r).digest("hex").substring(0,16)}async function AT(r,e,t,n,o,i,s){DT(n);let a=Cd(r),c={certList:t,packageName:n,deviceList:o,provisionName:i};s.length&&(c.aclPermissionList=s);let l=await L.postAllowFailure(e,{headers:a,params:c});if(!l)throw Yt("add provision failed: response is null"),new Error(E.ADD_PROFILE_FAIL);if(l.statusCode!==200)throw Pd(l.statusCode,l.statusText,l.data);let d=JSON.parse(l.data);if(!d||!d.ret||d.ret.code!==0)throw Yt(`add provision fail: ${l.data}`),RT(l.data,i),new Error(d.ret?.msg||E.ADD_PROFILE_FAIL);let g=d.provisionFileUrl;return{profileInfo:{id:d.id,name:i,provisionFileUrl:g}}}function Pd(r,e,t){return r===vt.FORBIDDEN?e===we.OPENPROXY_BLOCKED_URL?new Error(E.ERR_CERT_NETWORK_ERROR):new Error(E.ERR_FORBIDDEN):r===vt.UNAUTHORIZED?new Error(E.ERR_UNAUTHORIZED):t.includes(we.PROVISION_EXCEEDS_LIMIT_CODE)?new Error(E.TEST_PROVISION_EXCEEDS_LIMIT):new Error(E.ADD_PROFILE_FAIL)}function DT(r){if(!r||r.trim().length===0)throw new Error(E.ERROR_SIGN_BUNDLE_NAME_VALIDATE);if(!Ve.BUNDLE_NAME_REGEX.test(r))throw new Error(E.ERROR_SIGN_BUNDLE_NAME_VALIDATE)}function RT(r,e){if(r.includes(we.PROVISION_EXCEEDS_LIMIT_CODE))throw new Error(E.TEST_PROVISION_EXCEEDS_LIMIT);if(r.includes(we.PROVISION_NAME_REPEAT_CODE)&&e)throw new Error(E.PROFILE_NAME_REPEAT)}async function uy(r,e){if(!e||e.trim().length===0)return;let t=`${ce.BASE_URL}${ce.PROVISION_DELETE_PATH}?id=${e}`,n=await L.deleteAllowFailure(t,{headers:Cd(r)});if(n.statusCode!==200)throw Pd(n.statusCode,n.statusText,n.data);let o=JSON.parse(n.data);(!o||!o.ret||o.ret.code!==0)&&Yt(`delete provision failed: ${n.data}`)}function TT(...r){for(let e of r)try{nn.existsSync(e)&&nn.unlinkSync(e)}catch(t){Yt(`delete local sign file error: ${t.message}`)}}async function xT(r,e){let t=`${ce.BASE_URL}${ce.CERT_DOWNLOAD_URL_PATH}`,n=Cd(r),o={sourceUrls:e},i=await L.postAllowFailure(t,{headers:n,params:o});if(!i)throw Yt("get download list failed: response is null"),new Error(E.ADD_PROFILE_FAIL);if(i.statusCode!==200)throw Pd(i.statusCode,i.statusText,i.data);let s=JSON.parse(i.data);if(!s||!s.urlsInfo||s.urlsInfo.length===0)throw Yt("download: The application does not exist"),new Error(s.ret?.msg||E.ADD_PROFILE_FAIL);return{urlList:s.urlsInfo,hasPermission:!0}}async function LT(r,e){if(!r||r.length===0)return!1;let t=r[0];return await ii(t.newUrl,e,t.sha256),!0}function NT(r,e,t,n,o){return MT(r,e),n=n||Ve.TARGET_FRIENDLY_NAME,o=o||"",OT(e,t,n,o),!0}function MT(r,e){if(e.lastIndexOf(Ve.CERT_BEGIN_HEADER)<0)throw new Error(E.ERROR_WHILE_PARSE_PROFILE);let t=JSON.stringify(e.substring(e.lastIndexOf(Ve.CERT_BEGIN_HEADER))).replace(/\\r/g,"");if(!r.includes(t))throw new Error(E.CERTIFICATION_AND_PROFILE_NOT_INCONSISTENT);return!0}function OT(r,e,t,n){let o=r.matchAll(Ve.CERTIFICATE_PATTERN_GLOBAL),i=[],s=new Date;for(let c of o)try{let l=c[0],d=_T(l),g=new Date(d.validFrom),v=new Date(d.validTo);if(s<g||s>v){let P=`Certificate is not valid, Valid from ${g} to ${v}`;throw console.warn(`checkCertificateInValidityPeriod: ${P}`),new Error(E.CERTIFICATE_HAS_EXPIRED)}i.push(d)}catch(l){throw console.warn(`checkCertificateInValidityPeriod\uFF1A ${l.message}`),new Error(E.CERTIFICATE_HAS_EXPIRED,{cause:l})}if(!i||i.length===0)throw new Error(E.CERTIFICATE_HAS_EXPIRED);if(!FT(e,t,n,i))throw new Error(E.CERTIFICATION_AND_PROFILE_NOT_INCONSISTENT)}function _T(r){let e="-----BEGIN CERTIFICATE-----",t=r.trim();try{if(t.startsWith(e))return new Ed(t);let n=py.from(t,"base64");return new Ed(n)}catch(n){throw new Error("decodeBase64ToX509Certificate",{cause:n})}}function jT(r){if(r.cert){let e=on.pki.publicKeyToPem(r.cert.publicKey);return PT(e).export({type:"spki",format:"der"})}if(r.asn1)try{let e=on.asn1.toDer(r.asn1).getBytes(),t=py.from(e,"binary");return new Ed(t).publicKey.export({type:"spki",format:"der"})}catch(e){return Yt(`Failed to parse cert from asn1: ${e}`),null}return null}function FT(r,e,t,n){try{let o=CT(r),i=on.asn1.fromDer(on.util.createBuffer(o)),c=on.pkcs12.pkcs12FromAsn1(i,t).getBags({bagType:on.pki.oids.certBag})[on.pki.oids.certBag]||[];for(let l of c){let d=l.attributes?.friendlyName?.[0];if(!d||d.toLowerCase()!==e.toLowerCase())continue;let g=jT(l);if(!g)continue;if(n.some(P=>{let ie=P.publicKey.export({type:"spki",format:"der"});return g.equals(ie)}))return!0}return!1}catch(o){let i=o instanceof Error?o.message:String(o);return Yt(`Failed to process P12 file: ${r}, error: ${i}`),!1}}function Cd(r){return{uid:r.uid,teamId:r.teamId,oauth2Token:r.accessToken}}var hy="https://developer.huawei.com",$T={"ohos.permission.SYSTEM_FLOAT_WINDOW":"/consumer/cn/doc/harmonyos-guides/window-pipwindow","ohos.permission.READ_CONTACTS":"/consumer/cn/doc/harmonyos-references/js-apis-contact#contactselectcontacts10","ohos.permission.READ_IMAGEVIDEO":"/consumer/cn/doc/harmonyos-guides/select-user-file#%E9%80%89%E6%8B%A9%E5%9B%BE%E7%89%87%E6%88%96%E8%A7%86%E9%A2%91%E7%B1%BB%E6%96%87%E4%BB%B6","ohos.permission.WRITE_IMAGEVIDEO":"/consumer/cn/doc/harmonyos-guides/savebutton","ohos.permission.READ_AUDIO":"/consumer/cn/doc/harmonyos-guides/select-user-file#%E9%80%89%E6%8B%A9%E9%9F%B3%E9%A2%91%E7%B1%BB%E6%96%87%E4%BB%B6","ohos.permission.WRITE_AUDIO":"/consumer/cn/doc/harmonyos-guides/save-user-file#%E4%BF%9D%E5%AD%98%E9%9F%B3%E9%A2%91%E7%B1%BB%E6%96%87%E4%BB%B6","ohos.permission.READ_PASTEBOARD":"/consumer/cn/doc/harmonyos-guides/pastebutton"},HT="/consumer/cn/doc/harmonyos-guides/restricted-permissions";function UT(r){let e=$T[r];return e?`${hy}${e}`:void 0}function BT(){return`${hy}${HT}`}var WT={"acl.can.apply.text":"Permission Application Scenarios","acl.permissions.warn":"Note: You are applying for restricted ACL permissions: {0} These permissions are subject to review together with your app release. For a faster review process, apply for the following permissions instead, if they are sufficient for your purposes: {1} {2}"};function my(r,e){return(WT[r]??r).replace(/\{(\d+)\}/g,(n,o)=>String(e[Number(o)]??""))}function VT(r){return Array.from(r).join(", ")}function gy(r,e){if(r.size===0)return;let t=Dr.getAclPermissionInfos(e),n=new Set;for(let g of t)r.has(g.permissionName)&&n.add(g);for(let g of n){let v=UT(g.permissionName);v!=null&&(g.permissionHelpUrlKey=v)}let o=new Set;for(let g of n)o.add(g.permissionDisplayName);let i=new Set;for(let g of n)if(g.permissionHelpUrlKey!=null){let v=g.permissionInsteadName??g.permissionDisplayName;i.add(`${v} (${g.permissionHelpUrlKey})`)}let s=BT(),a=my("acl.can.apply.text",[]),c=s?`${a} (${s})`:a,l=i.size>0?Array.from(i).join(", ")+".":"",d=my("acl.permissions.warn",[VT(o),l,c]);console.log(d)}var Da=class{_project=null;get project(){if(!this._project)throw new Error("Project not initialized. Call checkProjectDir first.");return this._project}checkProjectDir(e){try{return this._project=W.discover(process.cwd()),{passed:!0,message:""}}catch(t){return u(`[EnvCheck] Project.discover() failed: ${t.message}`),e(ue.PROJECT_DIR_MISSING)}}checkProduct(e,t){try{return this._project.validateProduct(e),{passed:!0,message:""}}catch(n){return u(`[EnvCheck] Product validation failed: ${n.message}`),t(`Product "${e}" not found.Check the product property in the build-profile.json5 file.`)}}checkBundleName(e,t){try{return this._project.getBundleName(),{passed:!0,message:""}}catch(n){return u(`[EnvCheck] BundleName check failed: ${n.message}`),t(`bundleName was not found under product "${e}".Check the bundleName configuration.`)}}checkAtomicService(){return this._project.isAtomicService()?{passed:!1,message:ue.ATOMIC_SERVICE_UNSUPPORTED}:{passed:!0,message:""}}};import GT from"fs";import yy from"path";var Ra=class{constructor(e){this.toolProvider=e}checkJava(e){try{return this.toolProvider.assertJava(),{passed:!0,message:""}}catch(t){return u(`[EnvCheck] Java check failed: ${t.message}`),e(`${t.message}`)}}checkHapSignTools(e){let t=this.toolProvider.sdkPath,n=yy.join(t,"default","openharmony","toolchains","lib","hap-sign-tool.jar");if(!GT.existsSync(n)){let o=yy.join("sdk","default","openharmony","toolchains","lib","hap_sign_tools.jar");return e(`hap_sign_tools.jar not found.Check whether ${o} exists.`)}return{passed:!0,message:""}}};var Ta=class{_userInfo=null;async ensureUserInfo(){if(!this._userInfo)try{this._userInfo=await Ne.getUserInfo()}catch(e){return u(`[EnvCheck] Failed to load user info: ${e.message}`),null}return this._userInfo}async checkLogin(e){try{return await Ne.isLoggedIn()?(await this.ensureUserInfo(),{passed:!0,message:""}):e(ue.LOGIN_REQUIRED)}catch(t){return u(`[EnvCheck] Login check failed: ${t.message}`),e(ue.LOGIN_REQUIRED)}}async checkTeamInfo(e){if(!await this.ensureUserInfo())return e(ue.TEAM_INFO_FAILED);try{if((await ur()).teamList.length>0)return{passed:!0,message:""}}catch(n){return u(`[EnvCheck] Team API error: ${n.message}`),e(ue.TEAM_INFO_FAILED)}return u("[EnvCheck] No teams found for current user"),e(ue.TEAM_INFO_FAILED)}async checkRealname(e){let t=await this.ensureUserInfo();return t?t.isRealName===!1?e(ue.REALNAME_REQUIRED):t.isRealName!==!0?(u("[EnvCheck] Scenario 3 Real-name check: AGC API did not return realName field"),e(ue.REALNAME_REQUIRED)):{passed:!0,message:""}:e(ue.SESSION_EXPIRED)}async checkTeamId(e){let t=await this.ensureUserInfo();if(!t)return{passed:!0,message:""};let n=e??"";try{let o=await ur();if(n=e??(o.teamList.length>0?o.teamList[0].id:t.userId)??"",!o.teamList.some(s=>s.id===n)){let s=`team-id for ${n} not found.Run devecocli auth team list to view the team to which the logged-in user belongs.`;return u(`[EnvCheck] ${s}`),{passed:!1,message:s}}return{passed:!0,message:""}}catch(o){return u(`[EnvCheck] Team ID check failed: ${o.message}`),{passed:!1,message:`team-id for ${n} not found.Run devecocli auth team list to view the team to which the logged-in user belongs.`}}}async checkRegion(e){let t=await this.ensureUserInfo();return t?t.countryCode?t.countryCode!=="CN"?e(ue.REGION_CHINA_ONLY):{passed:!0,message:""}:(u("[EnvCheck] Scenario 12 Region check: AGC API did not return nationalCode field"),e(ue.REGION_CHINA_ONLY)):e("User session expired or token invalid. Please login again.")}};async function qT(r){try{let{teamList:e}=await ur();if(e.length>0)return e[0].id}catch(e){u(`[EnvCheck] resolveDefaultTeamId failed: ${e.message}`)}return r??""}async function zT(r){let e=await Ne.getUserInfo(),t=await Ne.refreshToken();if(!e||!t?.accessToken)throw new Error("Not logged in");let n=r||await qT(e.userId);if(!n)throw new Error("No team found");let o={uid:e.userId??"",teamId:n,accessToken:t.accessToken};return(await Aa(o)).map(s=>({deviceId:s.udid,deviceName:s.deviceName}))}var xa=class{constructor(e){this.toolProvider=e}async checkDevice(e,t){try{let n=await zT(t);if(n.length>0)return u(`[EnvCheck] Scenario 4 Device check: ${n.length} device(s) found in AGC cloud, skipping local device check`),{passed:!0,message:""};u("[EnvCheck] Scenario 4 Device check: no cloud devices found, falling back to local hdc");let i=await de.from(this.toolProvider).listDevices();return i.length===0?(u("[EnvCheck] Scenario 4 Device check: no local devices found"),e(ue.DEVICE_MISSING)):i.some(a=>It(a.serial))?{passed:!0,message:""}:(u("[EnvCheck] Scenario 4 Device check: local device found but not an emulator"),e(ue.DEVICE_MISSING))}catch(n){return u(`[EnvCheck] Scenario 4 Device check failed: ${n.message}`),e(ue.DEVICE_DETECT_FAILED)}}};var La=class{projectChecker=new Da;toolchainChecker=null;authChecker=new Ta;deviceChecker=null;constructor(){}async preflight(e){let t=n=>this.blockingFail(n);return!(!await this.runAuthChain(e,t)||!await this.initToolchain()||!await this.runDeviceCheck(e,t)||!await this.runProjectChecks(e,t)||!await this.runAuxChecks(e))}async runAuthChain(e,t){let n=i=>(i.passed||this.fail(i),!0),o=[()=>this.authChecker.checkLogin(t),()=>this.authChecker.checkRealname(t),()=>this.authChecker.checkTeamInfo(t)];for(let i of o)if(!n(await i()))return!1;return!(e.teamId&&!n(await this.authChecker.checkTeamId(e.teamId)))}async initToolchain(){try{let e=await A.new();return this.toolchainChecker=new Ra(e),this.deviceChecker=new xa(e),!0}catch(e){throw u(`[EnvCheck] ToolProvider.new() failed: ${e.message}`),new Error(ue.TOOLCHAIN_INIT_FAILED,{cause:e})}}async runDeviceCheck(e,t){return(o=>o.passed?!0:(this.fail(o),!1))(await this.deviceChecker.checkDevice(t,e.teamId))}async runProjectChecks(e,t){let n=i=>i.passed?!0:(this.fail(i),!1);if(!n(this.projectChecker.checkProjectDir(t))||!n(this.projectChecker.checkAtomicService()))return!1;let o=[()=>this.projectChecker.checkProduct(e.productName,t),()=>this.projectChecker.checkBundleName(e.productName,t),()=>this.toolchainChecker.checkJava(t),()=>this.toolchainChecker.checkHapSignTools(t)];for(let i of o)if(!n(i()))return!1;return!0}async runAuxChecks(e){let t=n=>n.passed?!0:(this.fail(n),!1);return!e.teamId&&!t(await this.authChecker.checkTeamId(e.teamId))?!1:(await this.authChecker.checkRegion(n=>this.blockingFail(n)),!0)}blockingFail(e){return{passed:!1,message:e}}fail(e){throw u(`[EnvCheck] FAIL: ${e.message}`),new Error(e.message)}};var vy=5*1024*1024;function KT(r){try{let e=Id.statSync(r);if(e.size>vy)throw new Error(`Profile file too large: ${e.size} bytes (max ${vy} bytes): ${r}`);let t=Id.readFileSync(r,"utf-8");return by.parse(t)}catch(e){if(e.code==="ENOENT")return{app:{signingConfigs:[],products:[]}};throw new Error(`Failed to read profile: ${r}`,{cause:e})}}function XT(r){r.app||(r.app={signingConfigs:[],products:[]}),r.app.signingConfigs||(r.app.signingConfigs=[]),r.app.products||(r.app.products=[])}async function ZT(r){if(r.keyPwd===r.storePassword){let n=await Ar.encryptedPassword(r.keyPwd,r.p12FilePath);return{keyPassword:n,storePassword:n}}let e=await Ar.encryptedPassword(r.keyPwd,r.p12FilePath),t=await Ar.encryptedPassword(r.storePassword,r.p12FilePath);return{keyPassword:e,storePassword:t}}async function QT(r,e,t){let n=wy.join(r,"build-profile.json5"),o=KT(n);XT(o);let i=t??"default",{keyPassword:s,storePassword:a}=await ZT(e),c={name:i,type:"HarmonyOS",material:{certpath:e.cerFilePath,keyAlias:e.keyAlias,keyPassword:s,profile:e.profileFilePath,signAlg:wt.signAlg,storeFile:e.p12FilePath,storePassword:a}},l=o.app?.signingConfigs?.findIndex(g=>g.name===i);l!==void 0&&l>=0?o.app.signingConfigs[l]=c:o.app.signingConfigs.push(c);let d=o.app?.products?.findIndex(g=>g.name===i);d!==void 0&&d>=0?o.app.products[d].signingConfig=i:o.app.products.push({name:i,signingConfig:i}),Id.writeFileSync(n,by.stringify(o,null,2),"utf-8")}async function ex(r){let e=await Ne.getUserInfo(),t=await Ne.refreshToken();if(!e||!t)throw new Error("Failed to obtain login credentials. Run `devecocli auth login` again.");return{uid:e.userId??"",teamId:r.teamId??e.userId??"",accessToken:t.accessToken??""}}async function tx(r){let e=r.product||"default";await new La().preflight({productName:e,teamId:r.teamId}),console.log("Executing signature generate command");let n=await ex(r),o=await A.new(),{shouldRegenerate:i}=await ci.shouldRegenerate({force:r.force??!1,teamId:n.teamId,productName:r.product},o);if(!i){console.log(kd("Signature generation completed successfully."));return}await rx(r,n,o),console.log(kd("Signature generation completed successfully."))}async function rx(r,e,t){let n=await pd(e,r.product),o=nx(r,e,n,t);o.allDeviceIds=await sy(e,t.hdcPath),await fy(e,o);let i=W.discover(process.cwd()).rootDir;await QT(i,n,r.product??"default"),console.log(kd(`Signing config written to ${wy.join(i,"build-profile.json5")}`))}function nx(r,e,t,n){let o=process.cwd(),i=W.discover(o),s=ka(i,n);return gy(s,i),{productName:r.product||"default",bundleName:i.getBundleName(r.product||"default"),projectPath:i.rootDir,teamId:e.teamId,force:r.force||!1,aclPermissionList:[...s],certIds:[t.certId],keyAlias:t.keyAlias,keyPwd:t.keyPwd}}var Sy=new JT("signature").description("Generate application signature.");Sy.command("generate").description("Automatically generate signing materials and write them to the project configuration.").option("--force","Force overwrite existing local signing materials.").option("--team-id <team-id>","Specify the team ID to use.").option("--product <product>","Specify the product. The default value is default.").action(async r=>{let e={event:b.CommandExecuted,args:["signature","generate",...r.force?["--force"]:[],...r.teamId?["--team-id"]:[],...r.product?["--product"]:[]]},t=Date.now(),n=!0,o=null;try{await tx(r)}catch(i){n=!1,o=q(i),console.error(YT(i.message)),process.exitCode=1}finally{let i={duration_ms:Date.now()-t,success:n,error_code:o};await I.track(e,i)}});var Ey=Sy;if(!Et())try{I.init(Na.join(Pe(),"TraceLogData")),I.startScheduler()}catch(r){h.error(`[telemetry] init failed: ${r instanceof Error?r.message:String(r)}`)}(async()=>{if(!Et())try{let r=await A.new();I.setSourceType(r.sourceType);let e=await A.getCltVersion();e&&I.setCltVersion(e);let t=await A.getStudioVersion();t&&I.setStudioVersion(t)}catch(r){h.error(`[telemetry] toolchain info failed: ${r instanceof Error?r.message:String(r)}`)}})();le.name("devecocli").description(`HarmonyOS application development command line tool
1364
1364
 
1365
- Privacy: ${Qn.PRIVACY_URL}`).version("1.3.3-Test.3");var Py=le.options.find(r=>r.long==="--version");Py&&(Py.flags="-V, -v, --version");le.addCommand(Fu);le.addCommand(jp);le.addCommand(Yp);le.addCommand(gf);le.addCommand(Bf);le.addCommand(pm);le.addCommand($m);le.addCommand(Bm);le.addCommand(Qm);le.addCommand(ch);le.addCommand(Mh);le.addCommand(Uh);le.addCommand(Qh);le.addCommand(Og);le.addCommand(Ey);for(let r=2;r<process.argv.length;r++){let e=process.argv[r];if(e==="-v"){process.argv[r]="-V";break}if(!e.startsWith("-"))break}var Ad=process.argv.slice(2);Ad.length>=2&&Ad[Ad.length-1]==="help"&&(process.argv=[...process.argv.slice(0,-1),"--help"]);function ix(r){let e=r;for(;e.parent&&e.parent!==le;)e=e.parent;return e}var sx=new Set(["update","auth","serve"]);le.hook("preAction",async(r,e)=>{let t=ix(e),n=wn();if(t.name()==="update")return;let o=new sr(Na.join(Pe(),"update")),i=ir();if(n==="off"&&o.getBlockedVersions().includes(i))throw new Error(`devecocli ${i} has been disabled, run \`devecocli update\` to upgrade`);process.env.DEVECO_CLI_SKIP_VERSION_CHECK||sx.has(t.name())||await A.checkVersion()});le.hook("postAction",async(r,e)=>{if(process.exitCode||wn()!=="off")return;await new ko(e).checkAndNotify()});le.parseAsync(process.argv).finally(()=>{I.stopScheduler();try{Ya(Na.join(Pe(),"TraceLogData"))}catch(r){h.error(`[telemetry] background upload spawn check failed: ${r instanceof Error?r.message:String(r)}`)}}).catch(r=>{let e=r instanceof Error?r.message:String(r??"Unknown error");console.error(ox(`Error: ${e}`)),process.env.DEVECO_CLI_DEBUG==="1"&&r instanceof Error&&r.stack&&console.error(r.stack),process.exit(1)});
1365
+ Privacy: ${Qn.PRIVACY_URL}`).version("1.3.3-Test.4");var Py=le.options.find(r=>r.long==="--version");Py&&(Py.flags="-V, -v, --version");le.addCommand(Fu);le.addCommand(jp);le.addCommand(Yp);le.addCommand(gf);le.addCommand(Bf);le.addCommand(pm);le.addCommand($m);le.addCommand(Bm);le.addCommand(Qm);le.addCommand(ch);le.addCommand(Mh);le.addCommand(Uh);le.addCommand(Qh);le.addCommand(Og);le.addCommand(Ey);for(let r=2;r<process.argv.length;r++){let e=process.argv[r];if(e==="-v"){process.argv[r]="-V";break}if(!e.startsWith("-"))break}var Ad=process.argv.slice(2);Ad.length>=2&&Ad[Ad.length-1]==="help"&&(process.argv=[...process.argv.slice(0,-1),"--help"]);function ix(r){let e=r;for(;e.parent&&e.parent!==le;)e=e.parent;return e}var sx=new Set(["update","auth","serve"]);le.hook("preAction",async(r,e)=>{let t=ix(e),n=wn();if(t.name()==="update")return;let o=new sr(Na.join(Pe(),"update")),i=ir();if(n==="off"&&o.getBlockedVersions().includes(i))throw new Error(`devecocli ${i} has been disabled, run \`devecocli update\` to upgrade`);process.env.DEVECO_CLI_SKIP_VERSION_CHECK||sx.has(t.name())||await A.checkVersion()});le.hook("postAction",async(r,e)=>{if(process.exitCode||wn()!=="off")return;await new ko(e).checkAndNotify()});le.parseAsync(process.argv).finally(()=>{I.stopScheduler();try{Ya(Na.join(Pe(),"TraceLogData"))}catch(r){h.error(`[telemetry] background upload spawn check failed: ${r instanceof Error?r.message:String(r)}`)}}).catch(r=>{let e=r instanceof Error?r.message:String(r??"Unknown error");console.error(ox(`Error: ${e}`)),process.env.DEVECO_CLI_DEBUG==="1"&&r instanceof Error&&r.stack&&console.error(r.stack),process.exit(1)});
@@ -1,5 +1,5 @@
1
1
  import Nt from"path";import*as S from"fs";import*as Y from"path";import{homedir as gt}from"os";import*as H from"fs";import*as m from"path";function J(r){let t=m.resolve(r),e=[],n=t;for(;;)try{let i=H.realpathSync(n);return e.length===0?i:m.join(i,...e.reverse())}catch(i){if(i.code!=="ENOENT")throw i;let o=m.dirname(n);if(o===n)return t;e.push(m.basename(n)),n=o}}function P(r){let t=r.trim();return(t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'"))&&(t=t.slice(1,-1).trim()),t}function K(r){let t=P(r);if(!t)throw new Error("Path must not be empty.");return J(t)}var ht="deveco-cli",W,N=class extends Error{constructor(t){super(t),this.name="CliDataDirError"}};function yt(){let r=process.env.DEVECO_CLI_DATA_DIR,e=(r===void 0||r===""?"":P(r))||Y.join(gt(),".local","share",ht);try{return K(e)}catch(n){throw new N(n instanceof Error?n.message:String(n))}}function X(){if(W!==void 0)return W;let r=yt();try{if(S.existsSync(r))return S.realpathSync(r)}catch{}return r}import mt from"crypto";import d from"fs";import z from"os";import y from"path";import St from"https";var q={devecoApiTraceUpload:"https://cn.devecostudio.huawei.com/codeGenie/cli/trace/upload"};var D=class r{static ENDPOINT=q.devecoApiTraceUpload;static SENDER="deveco-cli";async upload(t,e){let n={"Content-Type":"application/json",sender:r.SENDER,deviceid:e.replace(/-/g,""),"Content-Length":String(Buffer.byteLength(t,"utf8"))};try{let{body:i}=await this.httpPost(r.ENDPOINT,n,Buffer.from(t,"utf8"),6e4);return r.isSuccess(i)}catch{return!1}}static isSuccess(t){try{let e=JSON.parse(t),n=e?.code??e?.errorCode;return String(n)==="200"}catch{return!1}}async httpPost(t,e,n,i){let o=new URL(t);return new Promise((s,p)=>{let l=St.request({protocol:o.protocol,hostname:o.hostname,port:o.port||(o.protocol==="https:"?443:80),path:o.pathname+o.search,method:"POST",headers:e,timeout:i},v=>{let h=[];v.on("data",w=>h.push(w)),v.on("end",()=>{s({code:v.statusCode??0,body:Buffer.concat(h).toString("utf8")})})});l.on("timeout",()=>{l.destroy(new Error("request timeout"))}),l.on("error",p),l.write(n),l.end()})}};var G={identity:r=>r,camelCase:r=>r,snakeCase:r=>r.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").toLowerCase()},M=class{constructor(t={}){this.config=t}serialize(t){let e=this.transform(t);return this.config.pretty?JSON.stringify(e,null,2):JSON.stringify(e)}toObject(t){return this.transform(t)}transform(t){if(t==null)return t;if(Array.isArray(t))return t.map(o=>this.transform(o));if(typeof t!="object")return t;let e=this.config.namingStrategy??G.identity,n=this.config.fieldNames??{},i={};for(let[o,s]of Object.entries(t)){let p=n[o]??e(o);i[p]=this.transform(s)}return i}},Z=new M({namingStrategy:G.snakeCase,fieldNames:{}});import E from"crypto";import C from"fs";import Et from"path";var L="aes-256-gcm",xt=12,Tt="deveco-cli-trace-file",bt="trace-file-secret",tt=32;function Q(r){try{let t=C.readFileSync(r,"utf8").trim();return t&&Buffer.from(t,"base64").length===tt?t:null}catch{return null}}function et(r){let t=Et.join(r,bt),e=Q(t);if(e)return j(e);let n=E.randomBytes(tt).toString("base64");try{C.mkdirSync(r,{recursive:!0});try{C.writeFileSync(t,n,{flag:"wx"})}catch{let i=Q(t);if(i)return j(i);C.writeFileSync(t,n)}}catch{}return j(n)}function j(r){return E.createHash("sha256").update(Tt).update(r).digest()}function $(r,t){let e=E.randomBytes(xt),n=E.createCipheriv(L,t,e),i=Buffer.concat([n.update(r,"utf8"),n.final()]),o={version:1,algorithm:L,ciphertext:i.toString("base64"),iv:e.toString("base64"),authTag:n.getAuthTag().toString("base64")};return JSON.stringify(o)}function rt(r,t){let e;try{e=JSON.parse(r)}catch{return null}if(!wt(e))return r;try{let n=E.createDecipheriv(L,t,Buffer.from(e.iv,"base64"));return n.setAuthTag(Buffer.from(e.authTag,"base64")),Buffer.concat([n.update(Buffer.from(e.ciphertext,"base64")),n.final()]).toString("utf8")}catch{return null}}function wt(r){if(!r||typeof r!="object")return!1;let t=r;return t.version===1&&t.algorithm===L&&typeof t.ciphertext=="string"&&typeof t.iv=="string"&&typeof t.authTag=="string"}import*as a from"fs";import*as A from"path";import*as _ from"os";import*as g from"path";import ce from"json5";function nt(){if(process.platform==="win32"){let r=process.env.LOCALAPPDATA??g.join(_.homedir(),"AppData","Local");return g.join(r,"devecocli-mcp-server","logs")}return process.platform==="darwin"?g.join(_.homedir(),"Library","Logs","devecocli-mcp-server"):g.join(_.homedir(),".local","share","devecocli-mcp-server","logs")}var it="mcp-server.log",Dt="mcp-server",Ct={maxSize:10*1024*1024,maxFiles:4},B=class r{fd=null;logDir=null;currentLogFile=null;mode;rotationOptions;currentFileSize=0;currentDate="";isRotating=!1;minLevel;static LEVEL_ORDER={debug:0,info:1,warn:2,error:3};constructor(t,e){this.rotationOptions={...Ct,...e},this.minLevel=t?"debug":"info",t?(this.mode="console",this.logDir=null,this.currentLogFile=null):(this.mode="file",this.logDir=nt(),this.currentLogFile=A.join(this.logDir,it),a.existsSync(this.logDir)||a.mkdirSync(this.logDir,{recursive:!0}),this.cleanupOrphanLogFiles(),this.openLogFile())}getCurrentDateString(){let t=new Date,e=t.getFullYear(),n=String(t.getMonth()+1).padStart(2,"0"),i=String(t.getDate()).padStart(2,"0");return`${e}-${n}-${i}`}getRotatedFileName(t,e){return A.join(this.logDir,`${Dt}-${t}.log.${e}`)}fileExists(t){try{return a.accessSync(t,a.constants.F_OK),!0}catch{return!1}}cleanupOrphanLogFiles(){if(this.logDir)try{let t=a.readdirSync(this.logDir),e=[];for(let i of t)if(i===it||/^mcp-server-\d{4}-\d{2}-\d{2}\.log\.\d+$/.test(i)){let o=A.join(this.logDir,i),s=a.statSync(o);e.push({name:i,mtime:s.mtime,path:o})}e.sort((i,o)=>o.mtime.getTime()-i.mtime.getTime());let n=1+this.rotationOptions.maxFiles;for(let i=n;i<e.length;i++)try{a.unlinkSync(e[i].path)}catch{}}catch{}}rotateLog(){if(!(this.isRotating||!this.logDir||!this.currentLogFile)){this.isRotating=!0;try{if(this.closeLogFile(),!this.fileExists(this.currentLogFile)){this.isRotating=!1,this.openLogFile();return}let t=this.getCurrentDateString(),e=this.getRotatedFileName(t,this.rotationOptions.maxFiles);this.fileExists(e)&&a.unlinkSync(e);for(let i=this.rotationOptions.maxFiles-1;i>=1;i--){let o=this.getRotatedFileName(t,i),s=this.getRotatedFileName(t,i+1);this.fileExists(o)&&a.renameSync(o,s)}let n=this.getRotatedFileName(t,1);a.renameSync(this.currentLogFile,n),this.cleanupOrphanLogFiles(),this.openLogFile()}catch{this.openLogFile()}finally{this.isRotating=!1}}}openLogFile(){if(this.currentLogFile){this.currentDate=this.getCurrentDateString();try{if(this.fileExists(this.currentLogFile)){let t=a.statSync(this.currentLogFile);this.currentFileSize=t.size}else this.currentFileSize=0}catch{this.currentFileSize=0}try{this.fd=a.openSync(this.currentLogFile,"a")}catch{this.fd=null}}}closeLogFile(){if(this.fd!==null){try{a.closeSync(this.fd)}catch{}this.fd=null}}checkRotation(t){let e=this.getCurrentDateString();this.currentDate&&this.currentDate!==e&&(this.rotateLog(),this.currentDate=e),this.currentFileSize+=t,this.currentFileSize>=this.rotationOptions.maxSize&&this.rotateLog()}write(t,e,...n){if(this.mode==="silent"||r.LEVEL_ORDER[t]<r.LEVEL_ORDER[this.minLevel])return;let i=n.map(l=>l instanceof Error?`${l.name}: ${l.message}`:typeof l=="object"?JSON.stringify(l,null,2):String(l)).join(" "),o=i?`${e} ${i}`:e,p=`[${new Date().toLocaleString("sv-SE",{timeZone:"Asia/Shanghai",hour12:!1})+"."+String(new Date().getMilliseconds()).padStart(3,"0")}] [MCP/${t.toUpperCase()}] ${o}
2
- `;if(this.mode==="file"&&this.currentLogFile){if(this.fd===null&&this.openLogFile(),this.fd!==null)try{let l=Buffer.from(p);a.writeSync(this.fd,l),this.checkRotation(l.byteLength)}catch{this.closeLogFile(),this.openLogFile()}}else this.mode==="console"&&process.stderr.write(p)}debug(t,...e){this.write("debug",t,...e)}info(t,...e){this.write("info",t,...e)}warn(t,...e){this.write("warn",t,...e)}error(t,...e){this.write("error",t,...e)}dispose(){this.closeLogFile()}flush(){if(!(this.mode!=="file"||this.fd===null))try{a.fsyncSync(this.fd)}catch{}}getLogFilePath(){return this.currentLogFile}getLogDirectory(){return this.logDir}},x=null;function Lt(r=!1){x&&x.dispose(),x=new B(r)}function F(){return x||Lt(!1),x}var f={debug:(r,...t)=>F().debug(r,...t),info:(r,...t)=>F().info(r,...t),warn:(r,...t)=>F().warn(r,...t),error:(r,...t)=>F().error(r,...t)};import ot from"fs";import _t from"path";var k=300*1e3,O=3600*1e3,st=10080*60*1e3;function R(){let r=process.env.DEVECO_CLI_DISABLE_TELEMETRY;return r==="1"||r==="true"}var Ft="upload-state.json";function at(r){return _t.join(r,Ft)}function At(){return{firstEventAt:null,lastUploadAt:null,lastRetryAt:null}}function U(r){try{let t=ot.readFileSync(at(r),"utf8"),e=JSON.parse(t);return{firstEventAt:typeof e.firstEventAt=="number"?e.firstEventAt:null,lastUploadAt:typeof e.lastUploadAt=="number"?e.lastUploadAt:null,lastRetryAt:typeof e.lastRetryAt=="number"?e.lastRetryAt:null}}catch{return At()}}function V(r,t){try{ot.writeFileSync(at(r),JSON.stringify(t),"utf8")}catch{}}function lt(r){let t=U(r);t.firstEventAt===null&&(t.firstEventAt=Date.now(),V(r,t))}function ct(r){let t=U(r);t.lastUploadAt=Date.now(),t.firstEventAt=null,V(r,t)}function ut(r){let t=U(r);t.lastRetryAt=Date.now(),V(r,t)}function pt(r){let t=r.match(/^telemetry-(\d{4})-(\d{2})-(\d{2})\.txt$/);if(!t)return null;let e=Date.parse(`${t[1]}-${t[2]}-${t[3]}T00:00:00`);return Number.isFinite(e)?e:null}import kt from"crypto";import I from"fs";import Ot from"path";var Rt="install-id";function It(r){return Ot.join(r,Rt)}function ft(r){try{let t=I.readFileSync(r,"utf8").trim();return Pt(t)?t:null}catch{return null}}function Pt(r){return/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(r)}function dt(r){let t=It(r),e=ft(t);if(e)return e;let n=kt.randomUUID();try{I.mkdirSync(r,{recursive:!0});try{I.writeFileSync(t,n,{flag:"wx"})}catch{let i=ft(t);if(i)return i;I.writeFileSync(t,n)}}catch{}return n}var T=class r{static MAX_BATCH=200;static MAX_PAYLOAD_BYTES=Math.floor(1.7*1024*1024);static TRACE_OS_VERSION="1.0";static COUNTRY_CODE="CN";static EVENT_PREFIX="devecocli_";uploader=new D;storageDir="";failedDir="";installId="";disabled=R();traceFileKey=Buffer.alloc(0);sessionId=mt.randomUUID();cliVersion="";devecoStudioVersion=null;sourceType="";cltVersion=null;nodeVersion="";initialTimer=null;intervalTimer=null;retryInitialTimer=null;retryTimer=null;flushChain=Promise.resolve();constructor(){f.info(`[telemetry] instance created, sessionId=${this.sessionId}`)}init(t){this.storageDir=t,this.failedDir=y.join(t,"failed"),this.cliVersion="1.3.3-Test.3",this.nodeVersion=process.version,this.installId=dt(t).replace(/-/g,""),this.traceFileKey=et(t),d.mkdirSync(t,{recursive:!0}),d.mkdirSync(this.failedDir,{recursive:!0}),f.info(`[telemetry] init: dir=${t}, failedDir=${this.failedDir}, cliVersion=${this.cliVersion}, os=${this.resolveOsName()}, arch=${this.resolveOsArch()}, node=${this.nodeVersion}`)}setStudioVersion(t){this.devecoStudioVersion=t,f.info(`[telemetry] studio version set: ${t}`)}setSourceType(t){this.sourceType=t,f.info(`[telemetry] sourceType set: ${t}`)}setCltVersion(t){this.cltVersion=t,f.info(`[telemetry] CLT version set: ${t}`)}async track(t,e){if(this.disabled)return typeof e=="function"?e():void 0;if(!this.storageDir)throw new Error("Telemetry not initialized. Call init() first.");if(!e){await this.record(t,0,!0,null);return}if(typeof e!="function"){let o=e;await this.record(t,o.duration_ms,o.success,o.error_code);return}let n=e,i=Date.now();try{let o=await n(),s=Date.now()-i;return await this.record(t,s,!0,null),o}catch(o){let s=Date.now()-i,p=this.toErrorCode(o);throw await this.record(t,s,!1,p),o}}async record(t,e,n,i){let o=this.buildTraceEvent(t,e,n,i);try{let s=$(JSON.stringify(o),this.traceFileKey);await d.promises.appendFile(this.currentFile(),s+`
2
+ `;if(this.mode==="file"&&this.currentLogFile){if(this.fd===null&&this.openLogFile(),this.fd!==null)try{let l=Buffer.from(p);a.writeSync(this.fd,l),this.checkRotation(l.byteLength)}catch{this.closeLogFile(),this.openLogFile()}}else this.mode==="console"&&process.stderr.write(p)}debug(t,...e){this.write("debug",t,...e)}info(t,...e){this.write("info",t,...e)}warn(t,...e){this.write("warn",t,...e)}error(t,...e){this.write("error",t,...e)}dispose(){this.closeLogFile()}flush(){if(!(this.mode!=="file"||this.fd===null))try{a.fsyncSync(this.fd)}catch{}}getLogFilePath(){return this.currentLogFile}getLogDirectory(){return this.logDir}},x=null;function Lt(r=!1){x&&x.dispose(),x=new B(r)}function F(){return x||Lt(!1),x}var f={debug:(r,...t)=>F().debug(r,...t),info:(r,...t)=>F().info(r,...t),warn:(r,...t)=>F().warn(r,...t),error:(r,...t)=>F().error(r,...t)};import ot from"fs";import _t from"path";var k=300*1e3,O=3600*1e3,st=10080*60*1e3;function R(){let r=process.env.DEVECO_CLI_DISABLE_TELEMETRY;return r==="1"||r==="true"}var Ft="upload-state.json";function at(r){return _t.join(r,Ft)}function At(){return{firstEventAt:null,lastUploadAt:null,lastRetryAt:null}}function U(r){try{let t=ot.readFileSync(at(r),"utf8"),e=JSON.parse(t);return{firstEventAt:typeof e.firstEventAt=="number"?e.firstEventAt:null,lastUploadAt:typeof e.lastUploadAt=="number"?e.lastUploadAt:null,lastRetryAt:typeof e.lastRetryAt=="number"?e.lastRetryAt:null}}catch{return At()}}function V(r,t){try{ot.writeFileSync(at(r),JSON.stringify(t),"utf8")}catch{}}function lt(r){let t=U(r);t.firstEventAt===null&&(t.firstEventAt=Date.now(),V(r,t))}function ct(r){let t=U(r);t.lastUploadAt=Date.now(),t.firstEventAt=null,V(r,t)}function ut(r){let t=U(r);t.lastRetryAt=Date.now(),V(r,t)}function pt(r){let t=r.match(/^telemetry-(\d{4})-(\d{2})-(\d{2})\.txt$/);if(!t)return null;let e=Date.parse(`${t[1]}-${t[2]}-${t[3]}T00:00:00`);return Number.isFinite(e)?e:null}import kt from"crypto";import I from"fs";import Ot from"path";var Rt="install-id";function It(r){return Ot.join(r,Rt)}function ft(r){try{let t=I.readFileSync(r,"utf8").trim();return Pt(t)?t:null}catch{return null}}function Pt(r){return/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(r)}function dt(r){let t=It(r),e=ft(t);if(e)return e;let n=kt.randomUUID();try{I.mkdirSync(r,{recursive:!0});try{I.writeFileSync(t,n,{flag:"wx"})}catch{let i=ft(t);if(i)return i;I.writeFileSync(t,n)}}catch{}return n}var T=class r{static MAX_BATCH=200;static MAX_PAYLOAD_BYTES=Math.floor(1.7*1024*1024);static TRACE_OS_VERSION="1.0";static COUNTRY_CODE="CN";static EVENT_PREFIX="devecocli_";uploader=new D;storageDir="";failedDir="";installId="";disabled=R();traceFileKey=Buffer.alloc(0);sessionId=mt.randomUUID();cliVersion="";devecoStudioVersion=null;sourceType="";cltVersion=null;nodeVersion="";initialTimer=null;intervalTimer=null;retryInitialTimer=null;retryTimer=null;flushChain=Promise.resolve();constructor(){f.info(`[telemetry] instance created, sessionId=${this.sessionId}`)}init(t){this.storageDir=t,this.failedDir=y.join(t,"failed"),this.cliVersion="1.3.3-Test.4",this.nodeVersion=process.version,this.installId=dt(t).replace(/-/g,""),this.traceFileKey=et(t),d.mkdirSync(t,{recursive:!0}),d.mkdirSync(this.failedDir,{recursive:!0}),f.info(`[telemetry] init: dir=${t}, failedDir=${this.failedDir}, cliVersion=${this.cliVersion}, os=${this.resolveOsName()}, arch=${this.resolveOsArch()}, node=${this.nodeVersion}`)}setStudioVersion(t){this.devecoStudioVersion=t,f.info(`[telemetry] studio version set: ${t}`)}setSourceType(t){this.sourceType=t,f.info(`[telemetry] sourceType set: ${t}`)}setCltVersion(t){this.cltVersion=t,f.info(`[telemetry] CLT version set: ${t}`)}async track(t,e){if(this.disabled)return typeof e=="function"?e():void 0;if(!this.storageDir)throw new Error("Telemetry not initialized. Call init() first.");if(!e){await this.record(t,0,!0,null);return}if(typeof e!="function"){let o=e;await this.record(t,o.duration_ms,o.success,o.error_code);return}let n=e,i=Date.now();try{let o=await n(),s=Date.now()-i;return await this.record(t,s,!0,null),o}catch(o){let s=Date.now()-i,p=this.toErrorCode(o);throw await this.record(t,s,!1,p),o}}async record(t,e,n,i){let o=this.buildTraceEvent(t,e,n,i);try{let s=$(JSON.stringify(o),this.traceFileKey);await d.promises.appendFile(this.currentFile(),s+`
3
3
  `,"utf8"),lt(this.storageDir)}catch{}}buildTraceEvent(t,e,n,i){let o=`${r.EVENT_PREFIX}${t.event}`,s=Z.toObject(t);return s&&typeof s=="object"&&delete s.event,{countryCode:r.COUNTRY_CODE,event:o,eventtime:String(Date.now()),properties:{uid:this.installId,trace_uuid:mt.randomUUID(),trace_os_version:r.TRACE_OS_VERSION,os_arch:this.resolveOsArch(),action:o,trace_os_name:this.resolveOsName(),version:`${this.cliVersion}_${this.resolveOsSuffix()}`,deveco_studio_version:this.formatVersion(this.devecoStudioVersion),command_line_version:this.formatVersion(this.cltVersion),source_type:this.sourceType,session_id:this.sessionId,node_version:this.nodeVersion,duration_ms:e,success:n,error_code:i,event_detail:s}}}toErrorCode(t){return t instanceof Error?t.code??t.name:"UnknownError"}resolveOsArch(){let t=z.arch();return t==="x64"?"amd64":t}resolveOsName(){switch(process.platform){case"win32":{let t=z.release().split(".");return(parseInt(t[t.length-1],10)||0)>=22e3?"Windows 11":"Windows 10"}case"darwin":return"macOS";case"linux":return"Linux";default:return process.platform}}resolveOsSuffix(){switch(process.platform){case"win32":return"windows";case"darwin":return z.arch()==="arm64"?"mac_arm":"mac";default:return"linux"}}formatVersion(t){return t?`${t}_${this.resolveOsSuffix()}`:""}dateString(){let t=new Date,e=String(t.getMonth()+1).padStart(2,"0"),n=String(t.getDate()).padStart(2,"0");return`${t.getFullYear()}-${e}-${n}`}currentFile(){return y.join(this.storageDir,`telemetry-${this.dateString()}.txt`)}startScheduler(){if(this.stopScheduler(),this.disabled){f.info("[telemetry] scheduler not started (telemetry disabled)");return}f.info(`[telemetry] scheduler started (flush every ${k/1e3}s, retry failed every ${O/1e3}s)`),this.initialTimer=setTimeout(()=>{this.flush().catch(()=>{}),this.intervalTimer=setInterval(()=>{this.flush().catch(()=>{})},k)},k),this.retryInitialTimer=setTimeout(()=>{this.retryFailed().catch(()=>{}),this.retryTimer=setInterval(()=>{this.retryFailed().catch(()=>{})},O)},O)}stopScheduler(){this.initialTimer&&(clearTimeout(this.initialTimer),this.initialTimer=null),this.intervalTimer&&(clearInterval(this.intervalTimer),this.intervalTimer=null),this.retryInitialTimer&&(clearTimeout(this.retryInitialTimer),this.retryInitialTimer=null),this.retryTimer&&(clearInterval(this.retryTimer),this.retryTimer=null),f.info("[telemetry] scheduler stopped")}async flush(){return this.disabled?!0:this.runExclusive(()=>this.performFlush())}async performFlush(){if(!this.storageDir)throw new Error("Telemetry not initialized. Call init() first.");let t=await this.listPendingFiles(),e=!0;for(let n of t)await this.flushFile(n)||(e=!1);return ct(this.storageDir),e}async retryFailed(){return this.disabled?!0:this.runExclusive(()=>this.performRetryFailed())}async performRetryFailed(){if(!this.storageDir)throw new Error("Telemetry not initialized. Call init() first.");let t=Date.now(),e;try{e=await d.promises.readdir(this.failedDir)}catch{return!0}let n=e.filter(o=>o.startsWith("telemetry-")&&o.endsWith(".txt")).map(o=>y.join(this.failedDir,o)),i=!0;for(let o of n){let s=y.basename(o),p=pt(s);if(p!==null){if(t-p>st){try{await d.promises.unlink(o)}catch{}continue}await this.flushFile(o)||(i=!1)}}return i||f.warn("[telemetry] retry failed"),ut(this.storageDir),i}runExclusive(t){let e=()=>t(),n=this.flushChain.then(e,e);return this.flushChain=n.then(()=>{},()=>{}),n}async listPendingFiles(){let t;try{t=await d.promises.readdir(this.storageDir)}catch{return[]}return t.filter(e=>e.startsWith("telemetry-")&&e.endsWith(".txt")).map(e=>y.join(this.storageDir,e)).sort()}async flushFile(t){let e=t+".pending";try{await d.promises.rename(t,e)}catch{return!1}let n;try{n=await d.promises.readFile(e,"utf8")}catch{return!1}let i=n.split(`
4
4
  `).map(s=>s.trim()).filter(Boolean),o=[];for(let s of i){let p=rt(s,this.traceFileKey);p!==null&&o.push(p)}if(o.length===0){try{await d.promises.unlink(e)}catch{}return!0}return this.uploadInBatches(e,o)}async uploadInBatches(t,e){let n=0;for(;n<e.length;){let i=n,o=[],s=16;for(;n<e.length&&o.length<r.MAX_BATCH;){let h=e[n],w=Buffer.byteLength(h,"utf8")+1;if(o.length>0&&s+w>r.MAX_PAYLOAD_BYTES)break;o.push(h),s+=w,n++}let p=this.buildPayloadItems(o),l=JSON.stringify(p),v=!1;try{v=await this.uploader.upload(l,this.installId)}catch{}if(!v){f.warn("[telemetry] upload failed");let h=e.slice(i).join(`
5
5
  `)+`
package/package.json CHANGED
@@ -1,56 +1,56 @@
1
- {
2
- "name": "@yinsen/deveco-cli",
3
- "version": "1.3.3-Test.3",
4
- "description": "HarmonyOS application development command line tool",
5
- "license": "MIT",
6
- "type": "module",
7
- "bin": { "devecocli": "dist/cli.js" },
8
- "files": [
9
- "dist",
10
- "templates",
11
- "src/resources",
12
- "THIRD-PARTY-LICENSES",
13
- "SKILL.md"
14
- ],
15
- "scripts": {
16
- "build": "tsup",
17
- "dev": "tsx watch src/cli.ts",
18
- "start": "tsx src/cli.ts",
19
- "test": "vitest run",
20
- "lint": "eslint \"src/**/*.ts\"",
21
- "lint:fix": "eslint src --fix",
22
- "format": "prettier --write src",
23
- "prepublishOnly": "npm run lint && npm run build"
24
- },
25
- "engines": { "node": ">=22" },
26
- "keywords": ["harmonyos", "deveco", "cli"],
27
- "dependencies": {
28
- "@yinsen/deveco-cli-docs-zh": "*",
29
- "@modelcontextprotocol/sdk": "^1.29.0",
30
- "adm-zip": "0.6.1",
31
- "axios": "1.19.0",
32
- "colorette": "^2.0.20",
33
- "commander": "^13.1.0",
34
- "execa": "^9.6.1",
35
- "fs-extra": "^11.3.4",
36
- "global-agent": "^4.1.3",
37
- "json5": "^2.2.3",
38
- "node-forge": "^1.4.0",
39
- "ora": "^9.4.0",
40
- "p-limit": "^5.0.0",
41
- "proper-lockfile": "^4.1.2",
42
- "regedit": "^5.1.4",
43
- "semver": "^7.8.5",
44
- "smol-toml": "^1.6.1",
45
- "socket.io-client": "^4.7.5",
46
- "zod": "^4.4.3"
47
- },
48
- "devDependencies": {
49
- "@types/adm-zip": "^0.5.8",
50
- "@types/fs-extra": "^11.0.4",
51
- "@types/global-agent": "^3.0.0",
52
- "@types/node-forge": "^1.3.14",
53
- "@types/proper-lockfile": "^4.1.4",
54
- "@types/semver": "^7.7.1"
55
- }
56
- }
1
+ {
2
+ "name": "@yinsen/deveco-cli",
3
+ "version": "1.3.3-Test.4",
4
+ "description": "HarmonyOS application development command line tool",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": { "devecocli": "dist/cli.js" },
8
+ "files": [
9
+ "dist",
10
+ "templates",
11
+ "src/resources",
12
+ "THIRD-PARTY-LICENSES",
13
+ "SKILL.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsup",
17
+ "dev": "tsx watch src/cli.ts",
18
+ "start": "tsx src/cli.ts",
19
+ "test": "vitest run",
20
+ "lint": "eslint \"src/**/*.ts\"",
21
+ "lint:fix": "eslint src --fix",
22
+ "format": "prettier --write src",
23
+ "prepublishOnly": "npm run lint && npm run build"
24
+ },
25
+ "engines": { "node": ">=22" },
26
+ "keywords": ["harmonyos", "deveco", "cli"],
27
+ "dependencies": {
28
+ "@yinsen/deveco-cli-docs-zh": "*",
29
+ "@modelcontextprotocol/sdk": "^1.29.0",
30
+ "adm-zip": "0.6.1",
31
+ "axios": "1.19.0",
32
+ "colorette": "^2.0.20",
33
+ "commander": "^13.1.0",
34
+ "execa": "^9.6.1",
35
+ "fs-extra": "^11.3.4",
36
+ "global-agent": "^4.1.3",
37
+ "json5": "^2.2.3",
38
+ "node-forge": "^1.4.0",
39
+ "ora": "^9.4.0",
40
+ "p-limit": "^5.0.0",
41
+ "proper-lockfile": "^4.1.2",
42
+ "regedit": "^5.1.4",
43
+ "semver": "^7.8.5",
44
+ "smol-toml": "^1.6.1",
45
+ "socket.io-client": "^4.7.5",
46
+ "zod": "^4.4.3"
47
+ },
48
+ "devDependencies": {
49
+ "@types/adm-zip": "^0.5.8",
50
+ "@types/fs-extra": "^11.0.4",
51
+ "@types/global-agent": "^3.0.0",
52
+ "@types/node-forge": "^1.3.14",
53
+ "@types/proper-lockfile": "^4.1.4",
54
+ "@types/semver": "^7.7.1"
55
+ }
56
+ }