@deveco-test/hmos-deveco-cli 0.3.0-TD.2-alpha2 → 0.3.0-TD.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +785 -785
  3. package/SKILL.md +172 -172
  4. package/dist/cli.js +3 -3
  5. package/index.zip +0 -0
  6. package/package.json +102 -102
  7. package/scripts/install-better-sqlite3.mjs +51 -51
  8. package/scripts/install-jieba-wasm.mjs +47 -47
  9. package/scripts/lib/better-sqlite3-vendor.mjs +128 -128
  10. package/scripts/lib/cli-data-dir.mjs +44 -44
  11. package/scripts/lib/doc-init-log-path.mjs +15 -15
  12. package/scripts/lib/jieba-wasm-vendor.mjs +102 -102
  13. package/scripts/postinstall.mjs +54 -54
  14. package/src/resources/aclPermission/aclPermissionsInfo.json +310 -310
  15. package/templates/application/AppScope/app.json5 +10 -10
  16. package/templates/application/AppScope/resources/base/element/string.json +8 -8
  17. package/templates/application/AppScope/resources/base/media/layered_image.json +6 -6
  18. package/templates/application/build-profile.json5 +41 -41
  19. package/templates/application/code-linter.json5 +31 -31
  20. package/templates/application/entry/build-profile.json5 +32 -32
  21. package/templates/application/entry/gitignore.txt +5 -5
  22. package/templates/application/entry/hvigorfile.ts +7 -7
  23. package/templates/application/entry/obfuscation-rules.txt +19 -19
  24. package/templates/application/entry/oh-package.json5 +10 -10
  25. package/templates/application/entry/src/main/ets/entryability/EntryAbility.ets +62 -62
  26. package/templates/application/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +30 -30
  27. package/templates/application/entry/src/main/ets/pages/Index.ets +37 -37
  28. package/templates/application/entry/src/main/module.json5 +49 -49
  29. package/templates/application/entry/src/main/resources/base/element/color.json +7 -7
  30. package/templates/application/entry/src/main/resources/base/element/float.json +8 -8
  31. package/templates/application/entry/src/main/resources/base/element/string.json +15 -15
  32. package/templates/application/entry/src/main/resources/base/media/layered_image.json +6 -6
  33. package/templates/application/entry/src/main/resources/base/profile/backup_config.json +2 -2
  34. package/templates/application/entry/src/main/resources/base/profile/main_pages.json +5 -5
  35. package/templates/application/entry/src/main/resources/dark/element/color.json +7 -7
  36. package/templates/application/gitignore.txt +11 -11
  37. package/templates/application/hvigor/hvigor-config.json5 +23 -23
  38. package/templates/application/hvigorfile.ts +7 -7
  39. package/templates/application/oh-package.json5 +10 -10
package/dist/cli.js CHANGED
@@ -61,7 +61,7 @@ Available runnable modules:
61
61
  Installing artifacts to device ${e}...`),await n.installApp(e,r),o){console.log(`Launching ${t}/${o}...`);let s=await n.launchApp(e,t,o);console.log(yo(`
62
62
  Application '${t}': ${s}`))}else console.log(`
63
63
  Application '${t}' installed successfully (no ability to launch).`)}var Gc=new lb("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/");b()||Gc.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.");Gc.action(async n=>{try{await mb(n)}catch(e){console.error(db(e.message)),process.exit(1)}});async function ub(n,e,t,r,o){let i=new Xt(e,n.rootDir),s=new ke(e,n.rootDir),a=new Set,c=new Set;for(let{moduleName:w,targetName:S}of t)for(let k of n.collectNonHarDependentModuleList(w))a.add(`${k}@${S}`),c.add(k);let l=[...a],d=uo(n,l),h={type:"modules",modulesToBuild:l,moduleTasks:d};for(let w of c)Xi.generate(n.rootDir,w,r,e);await Rt(n.rootDir,()=>po(i,s,r,o,h,n.rootDir),()=>console.log("Another build is already running for this project. Waiting for completion...")),console.log(`
64
- `+yo("Build completed successfully."))}async function pb(n,e,t,r,o){let i=new xt(t),s=te.from(t),a=r[0]?.moduleName||o[0];await Ap(n,e,t,i,s,a)}function fb(n,e){for(let{moduleName:t}of e){let r=n.getModuleType(t);if(r!=="entry"&&r!=="feature"&&r!=="shared")throw new Error(`Module '${t}' '${r}' is not runnable. Specify an entry or feature module.`)}}async function mb(n){let e=G.discover(process.cwd());console.warn(ss("Ensure the project source is trusted before proceeding."));let t=await I.new();if(n.skipBuild||t.assertJava(),n.hotreloadApply){await gb(n,e,t);return}if(n.hotreload){await hb(n,e,t);return}if(n.apply){await wb(n,e,t);return}await Tp(n,e,t)}async function hb(n,e,t){if(n.hotreload==="stop"){await Pp(t,e);return}let o=Wc(e,n.module).map(Bc),{moduleName:i,targetName:s}=o[0];Fc(n.module,i);let a=new xt(t),c=te.from(t),l=await cs(c,n.device),d=l.includes("127.0.0.1")||l.includes("localhost"),h=n.product||"default";e.validateProduct(h);let w=e.getBundleName(),S=Dp(e,o,n.ability);Zi.generate(e.rootDir,i,h,t);let k=new ke(t,e.rootDir);console.log(yo("Ensuring hvigor daemon is running (via --sync --daemon, no hap build)...")),await k.ensureDaemonRunning();let re=[`${i}@${h}`];for(let Ge of e.collectNonHarDependentModuleList(i))re.includes(`${Ge}@${h}`)||re.push(`${Ge}@${h}`);console.log(yo("Building hap + starting watch session (socket -> CommonBuild assembleHap --hot-reload-build --watch, kept open)..."));let Re=new lr(e.rootDir,t);await Re.startWatchSession({moduleSpecs:re,productName:h});let Pe=Ep(e,i,s,d,h);await Rp(a,l,w,Pe,S,!!n.uninstall),console.log(yo("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.")),Re.onSocketDisconnect(()=>{console.log("Daemon disconnected (likely via --hotreload stop). Exiting watch session."),process.exit(0)}),await new Promise(()=>{})}async function gb(n,e,t){let r=n.hotreloadApply;if(!r)throw new Error("hotreload-apply requires --hotreload-apply <fileName> (under .hvigor/)");let o=Wc(e,n.module),{moduleName:i}=Bc(o[0]);Fc(n.module,i);let s=te.from(t),a=await cs(s,n.device),c=n.product||"default";e.validateProduct(c);let l=e.getBundleName();bp(e,i,r);let d=[`${i}@${c}`],h=await Sp({applyFileName:r,projectPath:e.rootDir,moduleName:i,productName:c,bundleName:l,toolProvider:t,targetDeviceId:a,moduleSpecs:d});if(!h.success)throw new Error(h.message)}function yb(n,e,t,r){let o=new Set;for(let{moduleName:i,targetName:s}of e)for(let a of n.collectNonHarDependentModuleList(i)){o.add(n.findArtifactPath(a,s,t,r));for(let c of n.findRemoteHspPaths(a,s,r))o.add(c)}return[...o]}async function Tp(n,e,t){let r=Wc(e,n.module),o=r.map(Bc),i=te.from(t);if(await Ip(n.device,i)){await pb(n,e,t,o,r);return}fb(e,o);let s=new xt(t),a=await cs(i,n.device),c=a.includes("127.0.0.1")||a.includes("localhost"),l=n.product||"default";e.validateProduct(l);let d=n.buildMode||"debug";n.skipBuild||await ub(e,t,o,l,d);let h=yb(e,o,c,l),w=e.getBundleName(),S=Dp(e,o,n.ability);await Rp(s,a,w,h,S,!!n.uninstall)}async function wb(n,e,t){let r=n.apply;if(!r)throw new Error("apply requires --apply <fileName> (under .hvigor/)");if(as.basename(r)!==r)throw new Error(`apply file must be a plain file name (under .hvigor/), got: ${r}`);let o=as.join(e.rootDir,".hvigor",r),i=te.from(t),s=await cs(i,n.device),a=n.product||"default";e.validateProduct(a);let c=e.getBundleName(),l=e.profile.modules.find(w=>e.getModuleType(w.name)==="entry")?.name,d=l?e.getMainAbility(l,n.ability):n.ability||"EntryAbility",h=new Ki(t,e.rootDir);try{await h.execute({applyFile:o,productName:a,targetDeviceId:s,bundleName:c,abilityName:d}),console.log(ss("[Apply] \u5B8C\u6210\u3002\u82E5\u6539\u52A8\u672A\u751F\u6548\uFF0C\u8BF7\u68C0\u67E5 <module>/build/config/buildConfig.json \u662F\u5426\u6709\u5185\u5BB9\uFF0C\u6216\u6267\u884C devecocli run \u5168\u91CF\u6784\u5EFA\u3002"));return}catch(w){console.warn(ss(`[Apply] \u5931\u8D25\uFF1A${w.message}`)),console.warn(ss("[Apply] \u81EA\u52A8\u56DE\u9000\u5230\u5168\u91CF devecocli run..."))}await Tp(n,e,t)}var kp=Gc;import{Command as vb}from"commander";import{green as xp,red as Np,cyan as zc}from"colorette";import{execa as Lp}from"execa";function Sb(){return"beta"}function bb(){return"@deveco-test/hmos-deveco-cli"}function Eb(){return"0.3.0-TD.2-alpha2"}var Pb=new vb("update").description("Update deveco-cli to latest").action(async()=>{let n=bb(),e=Eb(),t=Sb();console.log(zc("Checking for updates..."));try{let{stdout:r}=await Lp("npm",["view",n,`dist-tags.${t}`]),o=r.trim();if(!o||o===e){console.log(xp(`
64
+ `+yo("Build completed successfully."))}async function pb(n,e,t,r,o){let i=new xt(t),s=te.from(t),a=r[0]?.moduleName||o[0];await Ap(n,e,t,i,s,a)}function fb(n,e){for(let{moduleName:t}of e){let r=n.getModuleType(t);if(r!=="entry"&&r!=="feature"&&r!=="shared")throw new Error(`Module '${t}' '${r}' is not runnable. Specify an entry or feature module.`)}}async function mb(n){let e=G.discover(process.cwd());console.warn(ss("Ensure the project source is trusted before proceeding."));let t=await I.new();if(n.skipBuild||t.assertJava(),n.hotreloadApply){await gb(n,e,t);return}if(n.hotreload){await hb(n,e,t);return}if(n.apply){await wb(n,e,t);return}await Tp(n,e,t)}async function hb(n,e,t){if(n.hotreload==="stop"){await Pp(t,e);return}let o=Wc(e,n.module).map(Bc),{moduleName:i,targetName:s}=o[0];Fc(n.module,i);let a=new xt(t),c=te.from(t),l=await cs(c,n.device),d=l.includes("127.0.0.1")||l.includes("localhost"),h=n.product||"default";e.validateProduct(h);let w=e.getBundleName(),S=Dp(e,o,n.ability);Zi.generate(e.rootDir,i,h,t);let k=new ke(t,e.rootDir);console.log(yo("Ensuring hvigor daemon is running (via --sync --daemon, no hap build)...")),await k.ensureDaemonRunning();let re=[`${i}@${h}`];for(let Ge of e.collectNonHarDependentModuleList(i))re.includes(`${Ge}@${h}`)||re.push(`${Ge}@${h}`);console.log(yo("Building hap + starting watch session (socket -> CommonBuild assembleHap --hot-reload-build --watch, kept open)..."));let Re=new lr(e.rootDir,t);await Re.startWatchSession({moduleSpecs:re,productName:h});let Pe=Ep(e,i,s,d,h);await Rp(a,l,w,Pe,S,!!n.uninstall),console.log(yo("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.")),Re.onSocketDisconnect(()=>{console.log("Daemon disconnected (likely via --hotreload stop). Exiting watch session."),process.exit(0)}),await new Promise(()=>{})}async function gb(n,e,t){let r=n.hotreloadApply;if(!r)throw new Error("hotreload-apply requires --hotreload-apply <fileName> (under .hvigor/)");let o=Wc(e,n.module),{moduleName:i}=Bc(o[0]);Fc(n.module,i);let s=te.from(t),a=await cs(s,n.device),c=n.product||"default";e.validateProduct(c);let l=e.getBundleName();bp(e,i,r);let d=[`${i}@${c}`],h=await Sp({applyFileName:r,projectPath:e.rootDir,moduleName:i,productName:c,bundleName:l,toolProvider:t,targetDeviceId:a,moduleSpecs:d});if(!h.success)throw new Error(h.message)}function yb(n,e,t,r){let o=new Set;for(let{moduleName:i,targetName:s}of e)for(let a of n.collectNonHarDependentModuleList(i)){o.add(n.findArtifactPath(a,s,t,r));for(let c of n.findRemoteHspPaths(a,s,r))o.add(c)}return[...o]}async function Tp(n,e,t){let r=Wc(e,n.module),o=r.map(Bc),i=te.from(t);if(await Ip(n.device,i)){await pb(n,e,t,o,r);return}fb(e,o);let s=new xt(t),a=await cs(i,n.device),c=a.includes("127.0.0.1")||a.includes("localhost"),l=n.product||"default";e.validateProduct(l);let d=n.buildMode||"debug";n.skipBuild||await ub(e,t,o,l,d);let h=yb(e,o,c,l),w=e.getBundleName(),S=Dp(e,o,n.ability);await Rp(s,a,w,h,S,!!n.uninstall)}async function wb(n,e,t){let r=n.apply;if(!r)throw new Error("apply requires --apply <fileName> (under .hvigor/)");if(as.basename(r)!==r)throw new Error(`apply file must be a plain file name (under .hvigor/), got: ${r}`);let o=as.join(e.rootDir,".hvigor",r),i=te.from(t),s=await cs(i,n.device),a=n.product||"default";e.validateProduct(a);let c=e.getBundleName(),l=e.profile.modules.find(w=>e.getModuleType(w.name)==="entry")?.name,d=l?e.getMainAbility(l,n.ability):n.ability||"EntryAbility",h=new Ki(t,e.rootDir);try{await h.execute({applyFile:o,productName:a,targetDeviceId:s,bundleName:c,abilityName:d}),console.log(ss("[Apply] \u5B8C\u6210\u3002\u82E5\u6539\u52A8\u672A\u751F\u6548\uFF0C\u8BF7\u68C0\u67E5 <module>/build/config/buildConfig.json \u662F\u5426\u6709\u5185\u5BB9\uFF0C\u6216\u6267\u884C devecocli run \u5168\u91CF\u6784\u5EFA\u3002"));return}catch(w){console.warn(ss(`[Apply] \u5931\u8D25\uFF1A${w.message}`)),console.warn(ss("[Apply] \u81EA\u52A8\u56DE\u9000\u5230\u5168\u91CF devecocli run..."))}await Tp(n,e,t)}var kp=Gc;import{Command as vb}from"commander";import{green as xp,red as Np,cyan as zc}from"colorette";import{execa as Lp}from"execa";function Sb(){return"beta"}function bb(){return"@deveco-test/hmos-deveco-cli"}function Eb(){return"0.3.0-TD.2"}var Pb=new vb("update").description("Update deveco-cli to latest").action(async()=>{let n=bb(),e=Eb(),t=Sb();console.log(zc("Checking for updates..."));try{let{stdout:r}=await Lp("npm",["view",n,`dist-tags.${t}`]),o=r.trim();if(!o||o===e){console.log(xp(`
65
65
  ${n} is already up to date (v${e}, tag: ${t})`));return}console.log(zc(`
66
66
  New version found: ${o} (current: ${e})`)),console.log(zc(`Updating ${n}...`)),await Lp("npm",["install","-g",`${n}@${t}`],{stdio:"inherit"}),console.log(`
67
67
  `+xp(`${n} updated successfully to version ${o}.`))}catch(r){let o=r;console.error(Np(`Failed to update ${n}`)),o.message&&console.error(Np(o.message)),process.exit(1)}}),Op=Pb;import{Command as Qb}from"commander";import{execa as ds}from"execa";function Se(n){return n.normalize("NFKC").replace(/\s+/g," ").trim()}import{spawn as Cb}from"child_process";var Ib=2500;function Ab(n,e,t,r,o,i){n.once("exit",s=>{if(i())return;clearTimeout(e);let a=t();s===0||s===null?r():o(a||`Emulator process exited with code ${s}`)})}function Db(n,e,t,r){let o=!1,i=()=>o,s=()=>Buffer.concat(e).toString("utf8").trim(),a=()=>{o||(o=!0,clearTimeout(l),n.removeAllListeners(),n.stderr?.removeAllListeners(),n.stderr?.destroy(),n.unref(),t())},c=d=>{if(!o){o=!0,clearTimeout(l),n.removeAllListeners(),n.stderr?.removeAllListeners();try{n.kill()}catch{}r(new Error(d))}},l=setTimeout(a,Ib);n.once("error",d=>c(d.message)),Ab(n,l,s,a,c,i)}function Mp(n,e,t){return m(`Spawning emulator: ${n} ${t.join(" ")}`),new Promise((r,o)=>{let i=[],s=Cb(n,t,{detached:!0,stdio:["ignore","ignore","pipe"],env:{...process.env,DEVECO_SDK_HOME:e},windowsHide:!0});s.stderr?.on("data",a=>i.push(a)),Db(s,i,r,o)})}import*as ur from"path";function Rb(n){let e=new Set,t=[];for(let r of n){let o=JSON.stringify(r);e.has(o)||(e.add(o),t.push(r))}return t}function Tb(n){let e=n.instancePath?.trim();if(e)return ur.dirname(ur.normalize(e)).replace(/\\/g,"/");let t=n.path?.trim();return t?ur.dirname(ur.normalize(t)).replace(/\\/g,"/"):""}function kb(n){let e=[];return n&&e.push(["-imageRoot",n]),e.push([]),e}function _p(n,e){return e?[...n,"-bootmode",e]:n}function xb(n,e,t){let r=[_p(["-start",n],t)],o=Tb(e);if(o)for(let i of kb(e.imageRoot))r.push(_p(["-hvd",n,"-path",o,...i],t));return Rb(r)}async function Fp(n,e,t,r){let o=new Error("No start strategy ran"),i=xb(n,e,r);for(let s of i)try{return await t(s),{ok:!0}}catch(a){o=a}return{ok:!1,lastError:o}}async function qc(n){return(await te.withHdcPath(n).listDevices()).map(t=>t.serial).filter(On)}async function Vc(n){let e=await qc(n);return e.length===0?[]:(await Promise.all(e.map(r=>Yi(n,r,"ohos.qemu.hvd.name")))).filter(r=>!!r)}async function jp(n,e){return(await Vc(n)).includes(e)}import*as fr from"path";import{existsSync as Nb,statSync as Lb}from"fs";function pr(n,e){for(let t of e){let r=n[t];if(typeof r=="string"&&r.trim())return r.trim()}return""}function Ob(n){let e=pr(n,["instancePath","instance_path","InstancePath","instancepath","instanceDir","instance_dir","InstanceDir","deployPath","deploy_path","deployedPath","deployed_path","workPath","work_path","dataPath","data_path"]);if(e)return e;for(let[t,r]of Object.entries(n)){if(typeof r!="string"||!r.trim())continue;let o=t.toLowerCase();if(o.includes("instance")&&(o.includes("path")||o.includes("dir"))||o==="deployedpath")return r.trim()}return""}function Mb(n){return pr(n,["uuid","UUID","Uuid","instanceUuid","instance_uuid","InstanceUuid"])}function _b(n){let e=n.find(r=>r.instancePath?.trim());if(!e?.instancePath?.trim())return;let t=fr.dirname(fr.normalize(e.instancePath));for(let r of n){if(r.instancePath?.trim())continue;let o=fr.join(t,r.name);Nb(o)&&Lb(o).isDirectory()&&(r.instancePath=o.replace(/\\/g,"/"))}}function Fb(n){try{let e=JSON.parse(n);return Array.isArray(e)?e.map(t=>{let r=Mb(t),o=pr(t,["deviceType","DeviceType","devicetype"]),i=pr(t,["os.osVersion","osVersion","OsVersion","OSVersion"]);return{name:t.name||t.Name||"",isRunning:t.isRunning===!0||String(t.isRunning).toLowerCase()==="true",instancePath:Ob(t),path:pr(t,["path","Path","hvdPath","hvd_path"]),imageRoot:pr(t,["imageRoot","image_root","ImageRoot"]),uuid:r||void 0,deviceType:o||void 0,osVersion:i||void 0}}).filter(t=>t.name):null}catch{return null}}function jb(n){let e=[],t=/^(name|isrunning|instancepath|path|imageroot|devicetype|os\.osversion)\s*:\s*(.+)/gim,r=null,o;for(;(o=t.exec(n))!==null;){let[,i,s]=o;if(i.toLowerCase()==="name")r&&e.push(r),r={name:s.trim()};else if(r){let a=i.toLowerCase();a==="isrunning"?r.isRunning=s.trim().toLowerCase()==="true":a==="instancepath"?r.instancePath=s.trim():a==="path"?r.path=s.trim():a==="imageroot"?r.imageRoot=s.trim():a==="devicetype"?r.deviceType=s.trim():a==="os.osversion"&&(r.osVersion=s.trim())}}return r&&e.push(r),e}function Hp(n){let t=Fb(n)??jb(n);return _b(t),t}function Jc(n,e){for(let t of e){let r=n[t];if(typeof r=="string"&&r.trim())return r.trim()}return""}function Hb(n){let e=n.downloaded??n.Downloaded;return e===!0||String(e).toLowerCase()==="true"}function $b(n){if(!Hb(n))return null;let e=Jc(n,["osVersion","OsVersion","OSVersion"]),t=Jc(n,["SoftWareVersion","SoftwareVersion","softwareVersion"]),r=Jc(n,["deviceType","DeviceType"]);return!e&&!t?null:{osVersion:e,softwareVersion:t,deviceType:r}}function ls(n){let e=n.trim();if(!e)return[];try{let t=JSON.parse(e);if(!Array.isArray(t))return[];let r=[];for(let o of t){if(!o||typeof o!="object")continue;let i=$b(o);i&&r.push(i)}return r}catch{return[]}}function $p(n){let t=ls(n).map(r=>r.osVersion).filter(Boolean);return[...new Set(t)]}var Up=/no images are available/i,Ub="7.0.0",Bb={foldable:["open","half-open","close"],"2in1_foldable":["open","vertical-open","half-open","close"],triplefold:["single","double","triple","left-folded-right-half-folded","left-half-folded-right-expanded","left-expanded-right-folded","left-half-folded-right-folded","left-expanded-right-half-folded","left-half-folded-right-half-folded"]};function ct(n){return n.normalize("NFKC").trim().toLowerCase()}function Wb(n,e){let t=n.deviceType?.trim(),r=t?Bb[ct(t)]:void 0;if(!r)throw new Error(`Fold-state control is not supported for emulator "${n.name}" (device type: ${t||"unknown"}).`);if(!r.includes(e))throw new Error(`Fold state "${e}" is not supported by emulator "${n.name}" (device type: ${t}). Available states: ${r.join(", ")}.`)}function Gb(n){let e=n.message||"";return Up.test(e)}function zb(n){return n.normalize("NFKC").match(/(\d+(?:\.\d+){1,3})/)?.[1]}function wo(n,e){return`${n} ${e.join(" ")}`.trim()}function qb(n){switch(n.type){case"gps":return`${n.type}:${n.key}=${n.value}`;case"sensor":return`${n.type}:${n.key}=${n.value}`;case"rotation":case"volume":return`${n.type}:${n.direction}`;case"folded-state":return`${n.type}:${n.state}`;case"battery":return`${n.type}:${n.level}`;case"battery-status":return`${n.type}:${n.status}`;default:return n.type}}var mr=class n{static supportedControlPaths=new Set;emulatorPath;sdkPath;hdcPath;constructor(e,t,r){this.emulatorPath=e,this.sdkPath=t,this.hdcPath=r}static from(e){return new n(e.emulatorPath,e.sdkPath,e.hdcPath)}async executeEmulator(e){return m(`Executing: ${wo(this.emulatorPath,e)}`),ds(this.emulatorPath,e,{stdio:["ignore","pipe","pipe"],env:{...process.env,DEVECO_SDK_HOME:this.sdkPath}})}executeEmulatorDetached(e){return Mp(this.emulatorPath,this.sdkPath,e)}async listEmulators(){let{stdout:e}=await this.executeEmulator(["-list","-details"]);return Hp(e)}async getDeviceTypeByName(){let e=new Map;try{let t=await this.listEmulators();for(let r of t)r.name&&r.deviceType&&e.set(Se(r.name),r.deviceType)}catch{}return e}async startEmulator(e){let t=await this.listEmulators(),r=Se(e),o=t.find(a=>Se(a.name)===r);if(!o)throw new Error(`Emulator "${e}" not found.`);let i=o.name;if(await this.isAlreadyRunning(i,o))return"already-running";await this.assertSystemImageAvailable(o);let s=await Fp(i,o,a=>this.executeEmulatorDetached(a),"snapshot");if(s.ok)return"started";if(await this.isAlreadyRunning(i))return"already-running";throw new Error(`Unable to start emulator "${e}". All methods failed.
@@ -1299,7 +1299,7 @@ ${t}`}handleData(t){for(this.buffer=Buffer.concat([this.buffer,t]);;){let r=this
1299
1299
  `):"No valid C/C++ files"}],isError:!0};this.manager.patchSdkPathInCompileCommands();for(let c of o){await hI(fI);try{let l=await this.checkFile(c);r.push(mI(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(`
1300
1300
  `)),r.length>0&&s.push(r.join(`
1301
1301
  `));let a=s.join(`
1302
- `).trim();return!i&&r.length===0&&(a="No diagnostic information collected"),{content:[{type:"text",text:a}],isError:i}}async checkFile(e){let t=xn(e),r=await ln.promises.readFile(e,"utf8"),o=Ui(e),i=this.manager.registerDiagnosticCallback(t);this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didOpen",params:{textDocument:{uri:t,text:r,languageId:o,version:r.length}}});try{return await i}finally{this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didClose",params:{textDocument:{uri:t}}})}}collectValidFiles(e,t){let r=this.manager.projectRoot,o=[];for(let i of e){let s=Or.resolve(Or.isAbsolute(i)?i:Or.join(r,i));if(!ln.existsSync(s)){t.push(`File does not exist: ${i}`);continue}if(!ln.statSync(s).isFile()){t.push(`Not a regular file: ${i}`);continue}if(!kn(s)){t.push(`Not a supported C/C++ file: ${i}`);continue}try{o.push(ln.realpathSync(s))}catch{o.push(s)}}return o}};function mI(n,e){if(Array.isArray(e))return e.length===0?`${n} => no diagnostics`:`${n} => Diagnostic: ${JSON.stringify(e)}`;if(e&&typeof e=="object"&&typeof e.errorMessage=="string"){let t=e.errorMessage;return`${n} diagnostic failed, error_message: ${t}`}return`${n} => diagnostic failed, result: ${JSON.stringify(e)}`}function hI(n){return new Promise(e=>setTimeout(e,n))}import*as _r from"fs";import*as aa from"path";var Mr=class n{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 Nr();let r=this.resolveSingleFile(t.file);if(!r)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${t.file}`}],isError:!0};let o=n.FEATURE_METHOD_MAP[e];if(!o)return{content:[{type:"text",text:`Unknown feature: ${e}`}],isError:!0};g.info(`[ClangdLspTool] handleLspFeature: ${e} file=${r} line=${t.line} char=${t.character}`);try{let i=await this.withOpenFile(r,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 sa(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 g.error(`[ClangdLspTool] handleWorkspaceSymbolRaw failed: ${t.message}`),null}}async handleDocumentSymbol(e){if(!this.manager.ready)return Nr();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};g.info(`[ClangdLspTool] handleDocumentSymbol: file=${t}`);try{let r=await this.withOpenFile(t,async i=>this.manager.sendFeatureRequest(y.DOCUMENT_SYMBOL,{textDocument:{uri:i}}));return{content:[{type:"text",text:r==null?"documentSymbol: no result":`documentSymbol: ${JSON.stringify(r,null,2)}`}]}}catch(r){return sa("documentSymbol",r)}}async handleCallHierarchy(e){if(!this.manager.ready)return Nr();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};g.info(`[ClangdLspTool] handleCallHierarchy: file=${t} line=${e.line} char=${e.character} direction=${e.direction}`);try{let r=await this.withOpenFile(t,i=>this.fetchCallHierarchyResult(i,e));return{content:[{type:"text",text:`callHierarchy (${e.direction}): ${JSON.stringify(r,null,2)}`}]}}catch(r){return sa("callHierarchy",r)}}async fetchCallHierarchyResult(e,t){let r=await this.manager.sendFeatureRequest(y.PREPARE_CALL_HIERARCHY,{textDocument:{uri:e},position:{line:t.line,character:t.character}}),o=this.normalizeCallHierarchyItems(r);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 r of e)t.push(...await this.fetchIncomingCalls(r));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 r=xn(e),o=await _r.promises.readFile(e,"utf8"),i=Ui(e);g.info(`[ClangdLspTool] withOpenFile didOpen uri=${r} langId=${i} len=${o.length}`),this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didOpen",params:{textDocument:{uri:r,text:o,languageId:i,version:o.length}}});try{return await t(r)}finally{this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didClose",params:{textDocument:{uri:r}}})}}resolveSingleFile(e){let t=aa.isAbsolute(e)?e:aa.join(this.manager.projectRoot,e);return!_r.existsSync(t)||!_r.statSync(t).isFile()||!kn(t)?null:t}};import{spawn as gI}from"child_process";import*as la from"fs";import*as Jm from"path";var yI=30*1e3,wI=30*1e3,ca=class{config;client=null;clangdProcess=null;nextRequestId=1;requestCallbacks=new on;diagnosticWaiters=new Map;lastStartErrorMessage=null;onMessage=()=>{};disposeOnce=null;constructor(e){this.config=e}setOnMessage(e){this.onMessage=e}consumeStartErrorMessage(){let e=this.lastStartErrorMessage;return this.lastStartErrorMessage=null,e}async start(e){let t=!1;try{f.info(`[ClangdLspProxy] clangdPath: ${this.config.clangdPath}`),f.info(`[ClangdLspProxy] workspaceRoot: ${this.config.workspaceRoot}`),f.info(`[ClangdLspProxy] compileCommandsDir: ${this.config.compileCommandsDir}`),this.ensureLogDir(),this.clangdProcess=this.spawnClangd();let r={serverPath:"",logPath:this.config.logPath,indexingDataLocation:this.config.logPath,cwd:this.config.workspaceRoot,nodePath:this.config.nodePath};this.client=new rn(r),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,qe),f.info("[ClangdLspProxy] initialize response received"),this.sendNotification(y.INITIALIZED,{}),t=!0}catch(r){this.lastStartErrorMessage=r instanceof Error?r.message:String(r),f.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){f.warn("[ClangdLspProxy] sendNotification before ready, dropped");return}this.client.sendNotification(e,t)}registerDiagnosticCallback(e){let t=this.normalizeClangdUri(e);if(this.diagnosticWaiters.has(t)){f.warn(`[ClangdLspProxy] overwrite existing diagnostic waiter for ${t}`);let r=this.diagnosticWaiters.get(t);clearTimeout(r.timer),this.diagnosticWaiters.delete(t)}return new Promise((r,o)=>{let i=setTimeout(()=>{this.diagnosticWaiters.delete(t)&&o(new Error(`Wait for clangd diagnostics timeout, uri: ${t}`))},wI);this.diagnosticWaiters.set(t,{resolve:r,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=>{f.warn(`[ClangdLspProxy] shutdown request failed: ${e}`)}),this.sendNotification(y.EXIT,null),await this.client.waitForExitOrTimeout(300)}catch(e){f.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=${U(this.config.compileCommandsDir)}`,"--log=info","--pch-storage=memory","--limit-results=100"];f.info(`[ClangdLspProxy] spawn: ${this.config.clangdPath} ${e.join(" ")}`);let t=gI(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=rr(this.config.workspaceRoot),t=st(e),r=Jm.basename(e)||"workspace";return{processId:process.pid,clientInfo:{name:"devecocli-mcp-server",version:"0.3.0-TD.2-alpha2"},rootPath:e,rootUri:t,workspaceFolders:[{uri:t,name:r}],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,r=yI){if(!this.client)return Promise.reject(new Error("[ClangdLspProxy] client not ready"));let o=this.nextRequestId++,i=this.requestCallbacks.registerPending(o,e,r);return this.client.sendRequest(e,t,o),i}handleRawMessage(e){let t;try{t=JSON.parse(e)}catch(r){let o=r instanceof Error?r.message:String(r);f.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):f.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 r=t;if(e.error!==void 0){let o=e.error;f.warn(`[ClangdLspProxy] LSP error id=${r}: code=${o.code??-1} message=${o.message??"unknown"}`),this.requestCallbacks.rejectPending(r,new Error(`LSP error ${o.code??-1}: ${o.message??"unknown"}`))}else this.requestCallbacks.resolvePending(r,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:R,method:y.PROGRESS,params:e.params});break;case y.WINDOW_SHOW_MESSAGE:f.info(`[ClangdLspProxy] window/showMessage: ${JSON.stringify(e.params)}`);break;case y.WINDOW_LOG_MESSAGE:f.info(`[ClangdLspProxy] window/logMessage: ${JSON.stringify(e.params)}`);break;default:this.onMessage({jsonrpc:R,method:t,params:e.params})}}handlePublishDiagnostics(e){if(!e||!e.uri)return;let t=this.normalizeClangdUri(e.uri),r=this.diagnosticWaiters.get(t);if(!r&&this.diagnosticWaiters.size===1){let s=this.diagnosticWaiters.keys().next().value;r=this.diagnosticWaiters.get(s),r&&this.diagnosticWaiters.delete(s)}else r&&this.diagnosticWaiters.delete(t);if(!r)return;clearTimeout(r.timer);let o=Array.isArray(e.diagnostics)?e.diagnostics:[],i=o.length;f.info(`[ClangdLspProxy] diagnostics received uri=${t} count=${i}`),r.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:R,method:y.CPP_ERROR,params:{message:e.message}})}ensureLogDir(){if(this.config.logPath)try{la.existsSync(this.config.logPath)||la.mkdirSync(this.config.logPath,{recursive:!0})}catch{}}normalizeClangdUri(e){try{let t=new URL(e);if(t.protocol==="file:"){let r=decodeURIComponent(t.pathname);return process.platform==="win32"&&/^\/[a-zA-Z]:/.test(r)&&(r=r.slice(1)),st(r)}}catch{}return e}};import*as zo from"path";import*as $t from"fs";var qo=class{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 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){f.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.patchSdkPathInCompileCommands(),this.proxy.sendFeatureRequest(e,t)}registerDiagnosticCallback(e){return this.proxy?this.proxy.registerDiagnosticCallback(e):Promise.reject(new Error("[ClangdLspManager] LSP not ready"))}patchSdkPathInCompileCommands(){if(!b())return;let e=tr(this.projectRoot);if(!$t.existsSync(e))return;let t=$t.readFileSync(e,"utf8");if(!t.includes(qi))return;let r=t.replaceAll(qi,this.config.toolProvider.sdkPath);$t.writeFileSync(e,r,"utf8"),f.info(`[CppCheck] Patched SDK path in compile_commands.json: ${qi} -> ${this.config.toolProvider.sdkPath}`)}static async handleSyncCppProject(e,t){if(f.info("[ClangdLspManager] Received cpp/syncProject"),!e)return f.error("[ClangdLspManager] handleSyncCppProject: workspaceRoot or devecoPath is empty"),{status:"failed",reason:"workspaceRoot or devecoPath is empty"};if(Ln(e).length===0)return f.info("[ClangdLspManager] No C++ modules found, skipping compileNative"),{status:"success"};let o=await Mi(e,async()=>{try{return await Zu(e,t),f.info("[ClangdLspManager] compileNative + merge compile_commands completed"),{status:"success"}}catch(i){let s=i instanceof Error?i.message:String(i);return f.error(`[ClangdLspManager] compileNative failed: ${s}`),{status:"failed",reason:s}}});return o.acquired?o.result:(f.info("[ClangdLspManager] Build lock held by another process, skipping sync"),{status:"skipped",reason:"build lock held by another process"})}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(qe);try{this.startProxy()}catch(r){this.failInit(r instanceof Error?r:new Error(String(r)))}})}startProxy(){let e=Tt(this.config.workspaceRoot);this.resolvedRoot=e?pe(e):pe(this.config.workspaceRoot);let t=this.config.logPath??this.getLogPath();zi(t);let r=this.config.toolProvider.clangdPath;if(!r){let s="clangd executable not found inside DevEco Studio SDK";f.error(`[ClangdLspManager] ${s}`),this.failInit(new Error(s));return}let o=zo.dirname(tr(this.resolvedRoot));try{$t.mkdirSync(o,{recursive:!0})}catch(s){f.warn(`[ClangdLspManager] Failed to create compile_commands dir: ${s}`)}f.info(`[ClangdLspManager] clangdPath: ${r}`),f.info(`[ClangdLspManager] workspaceRoot: ${this.resolvedRoot}`),f.info(`[ClangdLspManager] compileCommandsDir: ${o}`);let i=new ca({clangdPath:r,workspaceRoot:this.resolvedRoot,compileCommandsDir:o,logPath:t,nodePath:this.config.toolProvider.nodePath});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,f.info("[ClangdLspManager] clangd initialized");let r=this.initResolve;this.clearInitHandlers(),r?.()}else{let r=t??this.proxy?.consumeStartErrorMessage()??"unknown error";f.error(`[ClangdLspManager] clangd initialization failed: ${r}`),this.isInitialized=!1,this.proxy=null;let o=this.initReject;this.clearInitHandlers(),o?.(new Error(`C++ LSP initialize failed: ${r}`))}};handleLspMessage(e){this.onMessage(e)}dispatchNotification(e){if(!this.proxy)return;let t=e,r=t.method;if(!r){f.warn("[ClangdLspManager] dispatchNotification: missing method");return}let o=t.params;switch(r){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(r,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){f.warn(`[ClangdLspManager] proxy dispose error: ${t}`)}this.proxy=null}this.isInitialized=!1,this.initPromise=null}getLogPath(){try{let e=zo.join(Qt(),"CppCheck"),t=`${Date.now()}${process.hrtime.bigint()%1000000n}`,r=zo.join(e,"lsp-log",t);return $t.mkdirSync(r,{recursive:!0}),pe(r)}catch{return"auto"}}};function Ym(n){let e=Fi(n);return f.info(`[SyncGuard] ${e.reason}`),e}var Fl=(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))(Fl||{}),Xm=(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))(Xm||{}),bt=3,Ml=600*1e3,_l=100,da=class{server;toolRouter;config;arktsCheckTool=null;cppCheckTool=null;cppLspTool=null;cppLspManager=null;projectState=0;workspaceRoot="";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;constructor(e){this.config=e,Nn(e.debug??!1);let t,r=e.projectPath?.trim()??"";this.originalProjectPath=r,r==="."?(t=process.cwd(),g.info(`Constructor: configuredPath is '.', startPath: '${t}'`)):r===""?(t="",g.info("Constructor: configuredPath is empty, startPath remains empty")):(t=r,g.info(`Constructor: using configured path as startPath: '${t}'`));let o=Tt(t);g.info(`Constructor: findHarmonyProject('${t}') => ${o??"null"}`),this.config.projectPath=o??void 0,this.server=new vI({name:"devecocli-mcp-server",version:"0.0.1"}),this.toolRouter=xl(),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). 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:de.object({target:de.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:de.object({files:de.array(de.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){g.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=de.object({file:de.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:de.number().describe("Line number (0-based)"),character:de.number().describe("Character offset in the line (0-based)")});for(let{name:t,description:r,feature:o}of this.getPositionFeatures())this.toolRouter.add({name:t,description:r,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:de.object({query:de.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:de.object({file:de.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:de.object({file:de.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:de.number().describe("Line number (0-based)"),character:de.number().describe("Character offset in the line (0-based)"),direction:de.enum(["incoming","outgoing"]).describe('"incoming" = who calls this function, "outgoing" = what this function calls')})},async e=>this.handleCallHierarchyCall(e))}detectStandardProtocolAvailable(){try{let e=this.config.toolProvider.lspServerPath;if(!e)return g.info("Standard LSP protocol unavailable: arkts-lang-server path not found"),!1;let t=dn.join(dn.dirname(e),"standardIndex","index.js"),r=Km.existsSync(t);return g.info(`ArktsCheck protocol: ${r?"standard LSP":"legacy ace-server"} (standardIndex/index.js exists=${r})`),r}catch(e){return g.warn(`Failed to detect standard LSP protocol availability: ${e}`),!1}}validateContainment(e){let t=this.config.projectPath;if(t){let o=[];for(let i of e){let s=D.isPathContainedWithSymlink(i,t);s.contained||(g.warn(`Containment check failed: ${s.reason}`),o.push(s.reason))}return o.length>0?{content:[{type:"text",text:o.join(`
1302
+ `).trim();return!i&&r.length===0&&(a="No diagnostic information collected"),{content:[{type:"text",text:a}],isError:i}}async checkFile(e){let t=xn(e),r=await ln.promises.readFile(e,"utf8"),o=Ui(e),i=this.manager.registerDiagnosticCallback(t);this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didOpen",params:{textDocument:{uri:t,text:r,languageId:o,version:r.length}}});try{return await i}finally{this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didClose",params:{textDocument:{uri:t}}})}}collectValidFiles(e,t){let r=this.manager.projectRoot,o=[];for(let i of e){let s=Or.resolve(Or.isAbsolute(i)?i:Or.join(r,i));if(!ln.existsSync(s)){t.push(`File does not exist: ${i}`);continue}if(!ln.statSync(s).isFile()){t.push(`Not a regular file: ${i}`);continue}if(!kn(s)){t.push(`Not a supported C/C++ file: ${i}`);continue}try{o.push(ln.realpathSync(s))}catch{o.push(s)}}return o}};function mI(n,e){if(Array.isArray(e))return e.length===0?`${n} => no diagnostics`:`${n} => Diagnostic: ${JSON.stringify(e)}`;if(e&&typeof e=="object"&&typeof e.errorMessage=="string"){let t=e.errorMessage;return`${n} diagnostic failed, error_message: ${t}`}return`${n} => diagnostic failed, result: ${JSON.stringify(e)}`}function hI(n){return new Promise(e=>setTimeout(e,n))}import*as _r from"fs";import*as aa from"path";var Mr=class n{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 Nr();let r=this.resolveSingleFile(t.file);if(!r)return{content:[{type:"text",text:`File does not exist or is not a C/C++ file: ${t.file}`}],isError:!0};let o=n.FEATURE_METHOD_MAP[e];if(!o)return{content:[{type:"text",text:`Unknown feature: ${e}`}],isError:!0};g.info(`[ClangdLspTool] handleLspFeature: ${e} file=${r} line=${t.line} char=${t.character}`);try{let i=await this.withOpenFile(r,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 sa(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 g.error(`[ClangdLspTool] handleWorkspaceSymbolRaw failed: ${t.message}`),null}}async handleDocumentSymbol(e){if(!this.manager.ready)return Nr();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};g.info(`[ClangdLspTool] handleDocumentSymbol: file=${t}`);try{let r=await this.withOpenFile(t,async i=>this.manager.sendFeatureRequest(y.DOCUMENT_SYMBOL,{textDocument:{uri:i}}));return{content:[{type:"text",text:r==null?"documentSymbol: no result":`documentSymbol: ${JSON.stringify(r,null,2)}`}]}}catch(r){return sa("documentSymbol",r)}}async handleCallHierarchy(e){if(!this.manager.ready)return Nr();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};g.info(`[ClangdLspTool] handleCallHierarchy: file=${t} line=${e.line} char=${e.character} direction=${e.direction}`);try{let r=await this.withOpenFile(t,i=>this.fetchCallHierarchyResult(i,e));return{content:[{type:"text",text:`callHierarchy (${e.direction}): ${JSON.stringify(r,null,2)}`}]}}catch(r){return sa("callHierarchy",r)}}async fetchCallHierarchyResult(e,t){let r=await this.manager.sendFeatureRequest(y.PREPARE_CALL_HIERARCHY,{textDocument:{uri:e},position:{line:t.line,character:t.character}}),o=this.normalizeCallHierarchyItems(r);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 r of e)t.push(...await this.fetchIncomingCalls(r));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 r=xn(e),o=await _r.promises.readFile(e,"utf8"),i=Ui(e);g.info(`[ClangdLspTool] withOpenFile didOpen uri=${r} langId=${i} len=${o.length}`),this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didOpen",params:{textDocument:{uri:r,text:o,languageId:i,version:o.length}}});try{return await t(r)}finally{this.manager.sendNotification({jsonrpc:"2.0",method:"textDocument/didClose",params:{textDocument:{uri:r}}})}}resolveSingleFile(e){let t=aa.isAbsolute(e)?e:aa.join(this.manager.projectRoot,e);return!_r.existsSync(t)||!_r.statSync(t).isFile()||!kn(t)?null:t}};import{spawn as gI}from"child_process";import*as la from"fs";import*as Jm from"path";var yI=30*1e3,wI=30*1e3,ca=class{config;client=null;clangdProcess=null;nextRequestId=1;requestCallbacks=new on;diagnosticWaiters=new Map;lastStartErrorMessage=null;onMessage=()=>{};disposeOnce=null;constructor(e){this.config=e}setOnMessage(e){this.onMessage=e}consumeStartErrorMessage(){let e=this.lastStartErrorMessage;return this.lastStartErrorMessage=null,e}async start(e){let t=!1;try{f.info(`[ClangdLspProxy] clangdPath: ${this.config.clangdPath}`),f.info(`[ClangdLspProxy] workspaceRoot: ${this.config.workspaceRoot}`),f.info(`[ClangdLspProxy] compileCommandsDir: ${this.config.compileCommandsDir}`),this.ensureLogDir(),this.clangdProcess=this.spawnClangd();let r={serverPath:"",logPath:this.config.logPath,indexingDataLocation:this.config.logPath,cwd:this.config.workspaceRoot,nodePath:this.config.nodePath};this.client=new rn(r),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,qe),f.info("[ClangdLspProxy] initialize response received"),this.sendNotification(y.INITIALIZED,{}),t=!0}catch(r){this.lastStartErrorMessage=r instanceof Error?r.message:String(r),f.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){f.warn("[ClangdLspProxy] sendNotification before ready, dropped");return}this.client.sendNotification(e,t)}registerDiagnosticCallback(e){let t=this.normalizeClangdUri(e);if(this.diagnosticWaiters.has(t)){f.warn(`[ClangdLspProxy] overwrite existing diagnostic waiter for ${t}`);let r=this.diagnosticWaiters.get(t);clearTimeout(r.timer),this.diagnosticWaiters.delete(t)}return new Promise((r,o)=>{let i=setTimeout(()=>{this.diagnosticWaiters.delete(t)&&o(new Error(`Wait for clangd diagnostics timeout, uri: ${t}`))},wI);this.diagnosticWaiters.set(t,{resolve:r,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=>{f.warn(`[ClangdLspProxy] shutdown request failed: ${e}`)}),this.sendNotification(y.EXIT,null),await this.client.waitForExitOrTimeout(300)}catch(e){f.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=${U(this.config.compileCommandsDir)}`,"--log=info","--pch-storage=memory","--limit-results=100"];f.info(`[ClangdLspProxy] spawn: ${this.config.clangdPath} ${e.join(" ")}`);let t=gI(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=rr(this.config.workspaceRoot),t=st(e),r=Jm.basename(e)||"workspace";return{processId:process.pid,clientInfo:{name:"devecocli-mcp-server",version:"0.3.0-TD.2"},rootPath:e,rootUri:t,workspaceFolders:[{uri:t,name:r}],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,r=yI){if(!this.client)return Promise.reject(new Error("[ClangdLspProxy] client not ready"));let o=this.nextRequestId++,i=this.requestCallbacks.registerPending(o,e,r);return this.client.sendRequest(e,t,o),i}handleRawMessage(e){let t;try{t=JSON.parse(e)}catch(r){let o=r instanceof Error?r.message:String(r);f.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):f.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 r=t;if(e.error!==void 0){let o=e.error;f.warn(`[ClangdLspProxy] LSP error id=${r}: code=${o.code??-1} message=${o.message??"unknown"}`),this.requestCallbacks.rejectPending(r,new Error(`LSP error ${o.code??-1}: ${o.message??"unknown"}`))}else this.requestCallbacks.resolvePending(r,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:R,method:y.PROGRESS,params:e.params});break;case y.WINDOW_SHOW_MESSAGE:f.info(`[ClangdLspProxy] window/showMessage: ${JSON.stringify(e.params)}`);break;case y.WINDOW_LOG_MESSAGE:f.info(`[ClangdLspProxy] window/logMessage: ${JSON.stringify(e.params)}`);break;default:this.onMessage({jsonrpc:R,method:t,params:e.params})}}handlePublishDiagnostics(e){if(!e||!e.uri)return;let t=this.normalizeClangdUri(e.uri),r=this.diagnosticWaiters.get(t);if(!r&&this.diagnosticWaiters.size===1){let s=this.diagnosticWaiters.keys().next().value;r=this.diagnosticWaiters.get(s),r&&this.diagnosticWaiters.delete(s)}else r&&this.diagnosticWaiters.delete(t);if(!r)return;clearTimeout(r.timer);let o=Array.isArray(e.diagnostics)?e.diagnostics:[],i=o.length;f.info(`[ClangdLspProxy] diagnostics received uri=${t} count=${i}`),r.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:R,method:y.CPP_ERROR,params:{message:e.message}})}ensureLogDir(){if(this.config.logPath)try{la.existsSync(this.config.logPath)||la.mkdirSync(this.config.logPath,{recursive:!0})}catch{}}normalizeClangdUri(e){try{let t=new URL(e);if(t.protocol==="file:"){let r=decodeURIComponent(t.pathname);return process.platform==="win32"&&/^\/[a-zA-Z]:/.test(r)&&(r=r.slice(1)),st(r)}}catch{}return e}};import*as zo from"path";import*as $t from"fs";var qo=class{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 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){f.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.patchSdkPathInCompileCommands(),this.proxy.sendFeatureRequest(e,t)}registerDiagnosticCallback(e){return this.proxy?this.proxy.registerDiagnosticCallback(e):Promise.reject(new Error("[ClangdLspManager] LSP not ready"))}patchSdkPathInCompileCommands(){if(!b())return;let e=tr(this.projectRoot);if(!$t.existsSync(e))return;let t=$t.readFileSync(e,"utf8");if(!t.includes(qi))return;let r=t.replaceAll(qi,this.config.toolProvider.sdkPath);$t.writeFileSync(e,r,"utf8"),f.info(`[CppCheck] Patched SDK path in compile_commands.json: ${qi} -> ${this.config.toolProvider.sdkPath}`)}static async handleSyncCppProject(e,t){if(f.info("[ClangdLspManager] Received cpp/syncProject"),!e)return f.error("[ClangdLspManager] handleSyncCppProject: workspaceRoot or devecoPath is empty"),{status:"failed",reason:"workspaceRoot or devecoPath is empty"};if(Ln(e).length===0)return f.info("[ClangdLspManager] No C++ modules found, skipping compileNative"),{status:"success"};let o=await Mi(e,async()=>{try{return await Zu(e,t),f.info("[ClangdLspManager] compileNative + merge compile_commands completed"),{status:"success"}}catch(i){let s=i instanceof Error?i.message:String(i);return f.error(`[ClangdLspManager] compileNative failed: ${s}`),{status:"failed",reason:s}}});return o.acquired?o.result:(f.info("[ClangdLspManager] Build lock held by another process, skipping sync"),{status:"skipped",reason:"build lock held by another process"})}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(qe);try{this.startProxy()}catch(r){this.failInit(r instanceof Error?r:new Error(String(r)))}})}startProxy(){let e=Tt(this.config.workspaceRoot);this.resolvedRoot=e?pe(e):pe(this.config.workspaceRoot);let t=this.config.logPath??this.getLogPath();zi(t);let r=this.config.toolProvider.clangdPath;if(!r){let s="clangd executable not found inside DevEco Studio SDK";f.error(`[ClangdLspManager] ${s}`),this.failInit(new Error(s));return}let o=zo.dirname(tr(this.resolvedRoot));try{$t.mkdirSync(o,{recursive:!0})}catch(s){f.warn(`[ClangdLspManager] Failed to create compile_commands dir: ${s}`)}f.info(`[ClangdLspManager] clangdPath: ${r}`),f.info(`[ClangdLspManager] workspaceRoot: ${this.resolvedRoot}`),f.info(`[ClangdLspManager] compileCommandsDir: ${o}`);let i=new ca({clangdPath:r,workspaceRoot:this.resolvedRoot,compileCommandsDir:o,logPath:t,nodePath:this.config.toolProvider.nodePath});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,f.info("[ClangdLspManager] clangd initialized");let r=this.initResolve;this.clearInitHandlers(),r?.()}else{let r=t??this.proxy?.consumeStartErrorMessage()??"unknown error";f.error(`[ClangdLspManager] clangd initialization failed: ${r}`),this.isInitialized=!1,this.proxy=null;let o=this.initReject;this.clearInitHandlers(),o?.(new Error(`C++ LSP initialize failed: ${r}`))}};handleLspMessage(e){this.onMessage(e)}dispatchNotification(e){if(!this.proxy)return;let t=e,r=t.method;if(!r){f.warn("[ClangdLspManager] dispatchNotification: missing method");return}let o=t.params;switch(r){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(r,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){f.warn(`[ClangdLspManager] proxy dispose error: ${t}`)}this.proxy=null}this.isInitialized=!1,this.initPromise=null}getLogPath(){try{let e=zo.join(Qt(),"CppCheck"),t=`${Date.now()}${process.hrtime.bigint()%1000000n}`,r=zo.join(e,"lsp-log",t);return $t.mkdirSync(r,{recursive:!0}),pe(r)}catch{return"auto"}}};function Ym(n){let e=Fi(n);return f.info(`[SyncGuard] ${e.reason}`),e}var Fl=(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))(Fl||{}),Xm=(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))(Xm||{}),bt=3,Ml=600*1e3,_l=100,da=class{server;toolRouter;config;arktsCheckTool=null;cppCheckTool=null;cppLspTool=null;cppLspManager=null;projectState=0;workspaceRoot="";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;constructor(e){this.config=e,Nn(e.debug??!1);let t,r=e.projectPath?.trim()??"";this.originalProjectPath=r,r==="."?(t=process.cwd(),g.info(`Constructor: configuredPath is '.', startPath: '${t}'`)):r===""?(t="",g.info("Constructor: configuredPath is empty, startPath remains empty")):(t=r,g.info(`Constructor: using configured path as startPath: '${t}'`));let o=Tt(t);g.info(`Constructor: findHarmonyProject('${t}') => ${o??"null"}`),this.config.projectPath=o??void 0,this.server=new vI({name:"devecocli-mcp-server",version:"0.0.1"}),this.toolRouter=xl(),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). 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:de.object({target:de.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:de.object({files:de.array(de.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){g.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=de.object({file:de.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:de.number().describe("Line number (0-based)"),character:de.number().describe("Character offset in the line (0-based)")});for(let{name:t,description:r,feature:o}of this.getPositionFeatures())this.toolRouter.add({name:t,description:r,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:de.object({query:de.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:de.object({file:de.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:de.object({file:de.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:de.number().describe("Line number (0-based)"),character:de.number().describe("Character offset in the line (0-based)"),direction:de.enum(["incoming","outgoing"]).describe('"incoming" = who calls this function, "outgoing" = what this function calls')})},async e=>this.handleCallHierarchyCall(e))}detectStandardProtocolAvailable(){try{let e=this.config.toolProvider.lspServerPath;if(!e)return g.info("Standard LSP protocol unavailable: arkts-lang-server path not found"),!1;let t=dn.join(dn.dirname(e),"standardIndex","index.js"),r=Km.existsSync(t);return g.info(`ArktsCheck protocol: ${r?"standard LSP":"legacy ace-server"} (standardIndex/index.js exists=${r})`),r}catch(e){return g.warn(`Failed to detect standard LSP protocol availability: ${e}`),!1}}validateContainment(e){let t=this.config.projectPath;if(t){let o=[];for(let i of e){let s=D.isPathContainedWithSymlink(i,t);s.contained||(g.warn(`Containment check failed: ${s.reason}`),o.push(s.reason))}return o.length>0?{content:[{type:"text",text:o.join(`
1303
1303
  `)}],isError:!0}:null}let r=e.filter(o=>dn.isAbsolute(o));return r.length>0?(g.warn(`Absolute paths rejected (no project root): ${r.join(", ")}`),{content:[{type:"text",text:r.map(o=>`Absolute path is not allowed: ${o}`).join(`
1304
1304
  `)}],isError:!0}):null}async handleCheckCall(e){let t=Array.isArray(e.files)?e.files.filter(d=>typeof d=="string"):[];if(t.length===0)return g.warn("check tool called with empty files list"),{content:[{type:"text",text:"No files provided"}],isError:!0};if(t.length>_l)return g.warn(`check tool called with ${t.length} files (max: ${_l})`),{content:[{type:"text",text:`Too many files: ${t.length}. Maximum allowed is ${_l}.`}],isError:!0};let{etsFiles:r,cppFiles:o,unsupported:i}=bI(t);i.length>0&&g.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=[];r.length>0&&this.mergeCheckResult(await this.callArktsCheck(r),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(`
1305
1305
  `),s.join(`
@@ -1412,4 +1412,4 @@ Run \`devecocli compat versions\` to see all available versions.`)}if(n.sourceVe
1412
1412
  `)){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 r=[];for(let o of t)try{m(`Executing: ${n} -t ${o} shell bm get -u`);let{stdout:i}=await Mw(n,["-t",o,"shell","bm","get","-u"],{stdio:["ignore","pipe","pipe"]}),s=ON(i);s&&r.push(s)}catch{m(`[reGenerateSign] Failed to get UDID for ${o}, skipping`)}return r}function ON(n){let e=n.trim();if(!e)return null;let t=e.split(`
1413
1413
  `);for(let o=0;o<t.length-1;o++)if(t[o].includes("udid of current device is")){let s=t[o+1].trim().match(/^[A-Fa-f0-9]{64}$/);if(s)return s[0].toUpperCase()}let r=e.match(/[A-Fa-f0-9]{64}/);return r?r[0].toUpperCase():null}function Fw(n){let e=[n.storeFile,n.csrFile,n.cerFile,n.profileFile],t=[];for(let r of e)Dn.existsSync(r)||t.push(r);return{allExist:t.length===0,missing:t}}function MN(n,e){let t=[];for(let r of e)n.includes(r)||t.push(r);return{allPresent:t.length===0,missing:t}}function _N(n,e){let t=[...n].sort(),r=[...e].sort();return t.length!==r.length?!1:t.every((o,i)=>o===r[i])}function We(n){let e={force:!1,allFilesExist:!1,missingFiles:[],profileContentNotEmpty:!1,profileNotExpired:!1,bundleNameMatched:!1,teamIdMatched:!1,allDevicesInProfile:!1,missingDeviceUdids:[],aclMatched:!1,cerMatched:!1,cerNotExpired:!1,storePasswordValid:!1};return n.force?{...e,force:!0}:{...e,...n,force:!1}}import{debuglog as lu}from"util";import{execa as du}from"execa";async function $w(n,e){let t=await ic(n);if(!t)throw new Error(E.DEVICE_LIST_EMPTY);let r=await HN(e);if(t.length===0)for(let s of r)await FN(n,s.udid,s.deviceName);else for(let s of r)await jN(n,t,s.udid,s.deviceName);let i=(await ic(n)).map(s=>s.id);if(i.length===0)throw new Error(E.DEVICE_LIST_EMPTY);return i}async function FN(n,e,t){await Ww(n,e,Uw(t))}async function jN(n,e,t,r){for(let o=0;o<e.length;o++){if(t===e[o].udid)return;if(o===e.length-1){await Ww(n,t,Uw(r));return}}}function Uw(n){switch(n){case"liteWearable":return"1";case"wearable":return"2";case"tv":return"3";default:return"4"}}async function Hw(n,e=1,t=100){let r=`${Q.BASE_URL}${Q.DEVICE_LIST_PATH}?encodeFlag=0&start=${e}&pageSize=${t}`,o=Gw(n),i=await N.get(r,{headers:o});if(!i)throw lu("query devices failed: response is null"),new Error(E.ERROR_WHILE_ADD_DEVICE);if(i.statusCode!==200)throw Bw(i.statusCode,i.statusText,i.data);let s=JSON.parse(i.data);if(!s||!s.list)throw lu("query devices failed: response list is null"),new Error(s.ret?.msg||E.ERROR_WHILE_ADD_DEVICE);return{deviceList:s.list,total:s.totalCount||0}}function Bw(n,e,t){return n===ft.FORBIDDEN?e===ye.OPENPROXY_BLOCKED_URL?new Error(E.ERR_CERT_NETWORK_ERROR):new Error(E.ERR_FORBIDDEN):n===ft.UNAUTHORIZED?new Error(E.ERR_UNAUTHORIZED):t.includes(ye.DEVICE_EXCEEDS_LIMIT_CODE)?new Error(E.DEVICE_LIMIT_REACHED):new Error(E.ERROR_WHILE_ADD_DEVICE)}async function ic(n){let t=await Hw(n,1,100);if(!t||!t.deviceList||t.deviceList.length===0)return[];let r=[...t.deviceList],o=t.total,i=Math.floor(o/100)+(o%100===0?0:1);for(let s=2;s<=i;s++){let a=await Hw(n,s,100);if(!a||!a.deviceList||a.deviceList.length===0)break;r.push(...a.deviceList)}return r}async function Ww(n,e,t){let r=`${Q.BASE_URL}${Q.DEVICE_ADD_PATH}`,o=Gw(n),s={deviceName:`auto_sign_device_No.${Math.floor(Math.random()*3e3)}${Date.now()}`,udid:e,deviceType:t},a=await N.postAllowFailure(r,{headers:o,params:s});if(!a)throw lu("add device failed: response is null"),new Error(E.ERROR_WHILE_ADD_DEVICE);if(a.statusCode!==200)throw Bw(a.statusCode,a.statusText,a.data);let c=a.data,l=JSON.parse(a.data);if(!l||!l.ret||l.ret.code!==0)throw c.includes(ye.DEVICE_EXCEEDS_LIMIT_CODE)?new Error(E.DEVICE_LIMIT_REACHED):c.includes(ye.DEVICE_NAME_REPEAT_CODE)?new Error(E.DEVICE_NAME_REPEAT):new Error(E.ERROR_WHILE_ADD_DEVICE)}function Gw(n){return{uid:n.uid,teamId:n.teamId,oauth2Token:n.accessToken}}async function HN(n){let{stdout:e}=await du(n,["list","targets"],{stdio:["ignore","pipe","pipe"]}),t=[];for(let o of e.split(`
1414
1414
  `)){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 r=[];for(let o of t)try{let i=await $N(o,n),s=await UN(o,n);i.length>0&&r.push({id:"",udid:i,deviceName:s})}catch{m(`Failed to get device info for ${o}, skipping`)}return r}async function $N(n,e){let{stdout:t}=await du(e,["-t",n,"shell","bm","get","-u"],{stdio:["ignore","pipe","pipe"]}),r=t.trim();if(!r)return"";let o=r.split(`
1415
- `);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=r.match(/[A-Fa-f0-9]{64}/);return i?i[0].toUpperCase():""}async function UN(n,e){let{stdout:t}=await du(e,["-c","-t",n,"shell","getprop","hw_sc.build.os.deviceType"],{stdio:["ignore","pipe","pipe"]});return BN(t)}function BN(n){let e=n.trim();return!e||e.includes("inaccessible")?"phone":n.includes("liteWearable")?"liteWearable":n.includes("wearable")?"wearable":n.includes("tv")?"tv":"phone"}import Qn from"fs";import{createHash as WN}from"crypto";import{debuglog as Vt}from"util";import{Buffer as qw}from"buffer";import{createPublicKey as GN,X509Certificate as uu}from"crypto";import{readFileSync as zN}from"fs";import er from"node-forge";async function Vw(n,e){console.log("Start generating profile");let{productName:t,bundleName:r,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=`${Q.BASE_URL}${Q.PROVISION_ADD_TEST_PATH}`,h=qN(t,r),w=await JN(n,d,a||[],r,s,h,i||[]);if(!w||!w.profileInfo||!w.profileInfo.provisionFileUrl)throw Vt("add provision failed, the provision file url is null"),new Error(E.ADD_PROFILE_FAIL);let S=w.profileInfo,re=(await ZN(n,S.provisionFileUrl)).urlList,Re=w.profileInfo.id;if(re&&re.length>0){let Pe=await Pw(t,o),Ge=Pe.profilePath;if(!await QN(re,Ge))throw await zw(n,Re),new Error(E.ERROR_WHILE_DOWNLOAD_PROFILE);if(await zw(n,Re),Qn.existsSync(Pe.certPath)&&Qn.existsSync(Ge)&&Qn.existsSync(Pe.p12Path)){let tv=Qn.readFileSync(Pe.certPath,"utf8"),nv=Qn.readFileSync(Ge,"utf8");return eL(nv,tv,Pe.p12Path,c,l)||XN(Ge),Ge}}throw new Error(E.ADD_PROFILE_FAIL)}function qN(n,e){let t=n?`${n}_`:"";return`${VN(`${t}${e}_${e}`)}`}function VN(n){return WN("sha256").update(n).digest("hex").substring(0,16)}async function JN(n,e,t,r,o,i,s){YN(r);let a=fu(n),c={certList:t,packageName:r,deviceList:o,provisionName:i};s.length&&(c.aclPermissionList=s);let l=await N.postAllowFailure(e,{headers:a,params:c});if(!l)throw Vt("add provision failed: response is null"),new Error(E.ADD_PROFILE_FAIL);if(l.statusCode!==200)throw pu(l.statusCode,l.statusText,l.data);let d=JSON.parse(l.data);if(!d||!d.ret||d.ret.code!==0)throw Vt(`add provision fail: ${l.data}`),KN(l.data,i),new Error(d.ret?.msg||E.ADD_PROFILE_FAIL);let h=d.provisionFileUrl;return{profileInfo:{id:d.id,name:i,provisionFileUrl:h}}}function pu(n,e,t){return n===ft.FORBIDDEN?e===ye.OPENPROXY_BLOCKED_URL?new Error(E.ERR_CERT_NETWORK_ERROR):new Error(E.ERR_FORBIDDEN):n===ft.UNAUTHORIZED?new Error(E.ERR_UNAUTHORIZED):t.includes(ye.PROVISION_EXCEEDS_LIMIT_CODE)?new Error(E.TEST_PROVISION_EXCEEDS_LIMIT):new Error(E.ADD_PROFILE_FAIL)}function YN(n){if(!n||n.trim().length===0)throw new Error(E.ERROR_SIGN_BUNDLE_NAME_VALIDATE);if(!je.BUNDLE_NAME_REGEX.test(n))throw new Error(E.ERROR_SIGN_BUNDLE_NAME_VALIDATE)}function KN(n,e){if(n.includes(ye.PROVISION_EXCEEDS_LIMIT_CODE))throw new Error(E.TEST_PROVISION_EXCEEDS_LIMIT);if(n.includes(ye.PROVISION_NAME_REPEAT_CODE)&&e)throw new Error(E.PROFILE_NAME_REPEAT)}async function zw(n,e){if(!e||e.trim().length===0)return;let t=`${Q.BASE_URL}${Q.PROVISION_DELETE_PATH}?id=${e}`,r=await N.deleteAllowFailure(t,{headers:fu(n)});if(r.statusCode!==200)throw pu(r.statusCode,r.statusText,r.data);let o=JSON.parse(r.data);(!o||!o.ret||o.ret.code!==0)&&Vt(`delete provision failed: ${r.data}`)}function XN(...n){for(let e of n)try{Qn.existsSync(e)&&Qn.unlinkSync(e)}catch(t){Vt(`delete local sign file error: ${t.message}`)}}async function ZN(n,e){let t=`${Q.BASE_URL}${Q.CERT_DOWNLOAD_URL_PATH}`,r=fu(n),o={sourceUrls:e},i=await N.postAllowFailure(t,{headers:r,params:o});if(!i)throw Vt("get download list failed: response is null"),new Error(E.ADD_PROFILE_FAIL);if(i.statusCode!==200)throw pu(i.statusCode,i.statusText,i.data);let s=JSON.parse(i.data);if(!s||!s.urlsInfo||s.urlsInfo.length===0)throw Vt("download: The application does not exist"),new Error(s.ret?.msg||E.ADD_PROFILE_FAIL);return{urlList:s.urlsInfo,hasPermission:!0}}async function QN(n,e){if(!n||n.length===0)return!1;let t=n[0].newUrl;return await Ei(t,e),!0}function eL(n,e,t,r,o){return tL(n,e),r=r||je.TARGET_FRIENDLY_NAME,o=o||"",nL(e,t,r,o),!0}function tL(n,e){if(e.lastIndexOf(je.CERT_BEGIN_HEADER)<0)throw new Error(E.ERROR_WHILE_PARSE_PROFILE);let t=JSON.stringify(e.substring(e.lastIndexOf(je.CERT_BEGIN_HEADER))).replace(/\\r/g,"");if(!n.includes(t))throw new Error(E.CERTIFICATION_AND_PROFILE_NOT_INCONSISTENT);return!0}function nL(n,e,t,r){let o=n.matchAll(je.CERTIFICATE_PATTERN_GLOBAL),i=[],s=new Date;for(let c of o)try{let l=c[0],d=rL(l),h=new Date(d.validFrom),w=new Date(d.validTo);if(s<h||s>w){let S=`Certificate is not valid, Valid from ${h} to ${w}`;throw console.warn(`checkCertificateInValidityPeriod: ${S}`),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(!iL(e,t,r,i))throw new Error(E.CERTIFICATION_AND_PROFILE_NOT_INCONSISTENT)}function rL(n){let e="-----BEGIN CERTIFICATE-----",t=n.trim();try{if(t.startsWith(e))return new uu(t);let r=qw.from(t,"base64");return new uu(r)}catch(r){throw new Error("decodeBase64ToX509Certificate",{cause:r})}}function oL(n){if(n.cert){let e=er.pki.publicKeyToPem(n.cert.publicKey);return GN(e).export({type:"spki",format:"der"})}if(n.asn1)try{let e=er.asn1.toDer(n.asn1).getBytes(),t=qw.from(e,"binary");return new uu(t).publicKey.export({type:"spki",format:"der"})}catch(e){return Vt(`Failed to parse cert from asn1: ${e}`),null}return null}function iL(n,e,t,r){try{let o=zN(n),i=er.asn1.fromDer(er.util.createBuffer(o)),c=er.pkcs12.pkcs12FromAsn1(i,t).getBags({bagType:er.pki.oids.certBag})[er.pki.oids.certBag]||[];for(let l of c){let d=l.attributes?.friendlyName?.[0];if(!d||d.toLowerCase()!==e.toLowerCase())continue;let h=oL(l);if(!h)continue;if(r.some(S=>{let k=S.publicKey.export({type:"spki",format:"der"});return h.equals(k)}))return!0}return!1}catch(o){let i=o instanceof Error?o.message:String(o);return Vt(`Failed to process P12 file: ${n}, error: ${i}`),!1}}function fu(n){return{uid:n.uid,teamId:n.teamId,oauth2Token:n.accessToken}}var Yw="https://developer.huawei.com",sL={"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"},aL="/consumer/cn/doc/harmonyos-guides/restricted-permissions";function cL(n){let e=sL[n];return e?`${Yw}${e}`:void 0}function lL(){return`${Yw}${aL}`}var dL={"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 Jw(n,e){return(dL[n]??n).replace(/\{(\d+)\}/g,(r,o)=>String(e[Number(o)]??""))}function uL(n){return Array.from(n).join(", ")}function Kw(n,e){if(n.size===0)return;let t=An.getAclPermissionInfos(e),r=new Set;for(let h of t)n.has(h.permissionName)&&r.add(h);for(let h of r){let w=cL(h.permissionName);w!=null&&(h.permissionHelpUrlKey=w)}let o=new Set;for(let h of r)o.add(h.permissionDisplayName);let i=new Set;for(let h of r)if(h.permissionHelpUrlKey!=null){let w=h.permissionInsteadName??h.permissionDisplayName;i.add(`${w} (${h.permissionHelpUrlKey})`)}let s=lL(),a=Jw("acl.can.apply.text",[]),c=s?`${a} (${s})`:a,l=i.size>0?Array.from(i).join(", ")+".":"",d=Jw("acl.permissions.warn",[uL(o),l,c]);console.log(d)}var sc=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=G.discover(process.cwd()),{passed:!0,message:""}}catch(t){return m(`[EnvCheck] Project.discover() failed: ${t.message}`),e(K.PROJECT_DIR_MISSING)}}checkProduct(e,t){try{return this._project.validateProduct(e),{passed:!0,message:""}}catch(r){return m(`[EnvCheck] Product validation failed: ${r.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(r){return m(`[EnvCheck] BundleName check failed: ${r.message}`),t(`bundleName was not found under product "${e}".Check the bundleName configuration.`)}}checkAtomicService(){return this._project.isAtomicService()?{passed:!1,message:K.ATOMIC_SERVICE_UNSUPPORTED}:{passed:!0,message:""}}};import pL from"fs";import Xw from"path";var ac=class{constructor(e){this.toolProvider=e}toolProvider;checkJava(e){try{return this.toolProvider.assertJava(),{passed:!0,message:""}}catch(t){return m(`[EnvCheck] Java check failed: ${t.message}`),e(K.JAVA_PLATFORM_UNSUPPORTED)}}checkHapSignTools(e){let t=this.toolProvider.sdkPath,r=b()?"hap-sign-tool":"hap-sign-tool.jar",o=Xw.join(t,"default","openharmony","toolchains","lib",r);if(!pL.existsSync(o)){let i=Xw.join("sdk","default","openharmony","toolchains","lib",r);return e(`${r} not found.Check whether ${i} exists.`)}return{passed:!0,message:""}}};var cc=class{_userInfo=null;async ensureUserInfo(){if(!this._userInfo)try{this._userInfo=await ae.getUserInfo()}catch(e){return m(`[EnvCheck] Failed to load user info: ${e.message}`),null}return this._userInfo}async checkLogin(e){try{return await ae.isLoggedIn()?(await this.ensureUserInfo(),{passed:!0,message:""}):e(K.LOGIN_REQUIRED)}catch(t){return m(`[EnvCheck] Login check failed: ${t.message}`),e(K.LOGIN_REQUIRED)}}async checkTeamInfo(e){if(!await this.ensureUserInfo())return e(K.TEAM_INFO_FAILED);try{if((await tn()).teamList.length>0)return{passed:!0,message:""}}catch(r){return m(`[EnvCheck] Team API error: ${r.message}`),e(K.TEAM_INFO_FAILED)}return m("[EnvCheck] No teams found for current user"),e(K.TEAM_INFO_FAILED)}async checkRealname(e){let t=await this.ensureUserInfo();return t?t.isRealName===!1?e(K.REALNAME_REQUIRED):t.isRealName!==!0?(m("[EnvCheck] Scenario 3 Real-name check: AGC API did not return realName field"),e(K.REALNAME_REQUIRED)):{passed:!0,message:""}:e(K.SESSION_EXPIRED)}async checkTeamId(e){let t=await this.ensureUserInfo();if(!t)return{passed:!0,message:""};let r=e??"";try{let o=await tn();if(r=e??(o.teamList.length>0?o.teamList[0].id:t.userId)??"",!o.teamList.some(s=>s.id===r)){let s=`team-id for ${r} not found.Run devecocli auth team list to view the team to which the logged-in user belongs.`;return m(`[EnvCheck] ${s}`),{passed:!1,message:s}}return{passed:!0,message:""}}catch(o){return m(`[EnvCheck] Team ID check failed: ${o.message}`),{passed:!1,message:`team-id for ${r} 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(K.REGION_CHINA_ONLY):{passed:!0,message:""}:(m("[EnvCheck] Scenario 12 Region check: AGC API did not return nationalCode field"),e(K.REGION_CHINA_ONLY)):e("User session expired or token invalid. Please login again.")}};async function fL(n){try{let{teamList:e}=await tn();if(e.length>0)return e[0].id}catch(e){m(`[EnvCheck] resolveDefaultTeamId failed: ${e.message}`)}return n??""}async function mL(n){let e=await ae.getUserInfo(),t=await ae.refreshToken();if(!e||!t?.accessToken)throw new Error("Not logged in");let r=n||await fL(e.userId);if(!r)throw new Error("No team found");let o={uid:e.userId??"",teamId:r,accessToken:t.accessToken};return(await ic(o)).map(s=>({deviceId:s.udid,deviceName:s.deviceName}))}var lc=class{constructor(e){this.toolProvider=e}toolProvider;async checkDevice(e,t){try{let r=await mL(t);if(r.length>0)return m(`[EnvCheck] Scenario 4 Device check: ${r.length} device(s) found in AGC cloud, skipping local device check`),{passed:!0,message:""};m("[EnvCheck] Scenario 4 Device check: no cloud devices found, falling back to local hdc");let i=await te.from(this.toolProvider).listDevices();return i.length===0?(m("[EnvCheck] Scenario 4 Device check: no local devices found"),e(K.DEVICE_MISSING)):i.some(a=>On(a.serial))?{passed:!0,message:""}:(m("[EnvCheck] Scenario 4 Device check: local device found but not an emulator"),e(K.DEVICE_MISSING))}catch(r){return m(`[EnvCheck] Scenario 4 Device check failed: ${r.message}`),e(K.DEVICE_DETECT_FAILED)}}};var dc=class{projectChecker=new sc;toolchainChecker=null;authChecker=new cc;deviceChecker=null;constructor(){}async preflight(e){let t=r=>this.blockingFail(r);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 r=i=>(i.passed||this.fail(i),!0),o=[()=>this.authChecker.checkLogin(t),()=>this.authChecker.checkTeamInfo(t),()=>this.authChecker.checkRealname(t)];for(let i of o)if(!r(await i()))return!1;return!(e.teamId&&!r(await this.authChecker.checkTeamId(e.teamId)))}async initToolchain(){try{let e=await I.new();return this.toolchainChecker=new ac(e),this.deviceChecker=new lc(e),!0}catch(e){throw m(`[EnvCheck] ToolProvider.new() failed: ${e.message}`),new Error(K.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 r=i=>i.passed?!0:(this.fail(i),!1);if(!r(this.projectChecker.checkProjectDir(t))||!r(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(!r(i()))return!1;return!0}async runAuxChecks(e){let t=r=>r.passed?!0:(this.fail(r),!1);return!e.teamId&&!t(await this.authChecker.checkTeamId(e.teamId))?!1:(await this.authChecker.checkRegion(r=>this.blockingFail(r)),!0)}blockingFail(e){return{passed:!1,message:e}}fail(e){throw m(`[EnvCheck] FAIL: ${e.message}`),new Error(e.message)}};function wL(n){if(hu.existsSync(n)){let e=hu.readFileSync(n,"utf-8");return yL.parse(e)}return{app:{signingConfigs:[],products:[]}}}function vL(n){n.app||(n.app={signingConfigs:[],products:[]}),n.app.signingConfigs||(n.app.signingConfigs=[]),n.app.products||(n.app.products=[])}async function SL(n){if(n.keyPwd===n.storePassword){let r=await In.encryptedPassword(n.keyPwd,n.p12FilePath);return{keyPassword:r,storePassword:r}}let e=await In.encryptedPassword(n.keyPwd,n.p12FilePath),t=await In.encryptedPassword(n.storePassword,n.p12FilePath);return{keyPassword:e,storePassword:t}}async function bL(n,e,t){let r=Zw.join(n,"build-profile.json5"),o=wL(r);vL(o);let i=t??"default",{keyPassword:s,storePassword:a}=await SL(e),c={name:i,type:"HarmonyOS",material:{certpath:e.cerFilePath,keyAlias:e.keyAlias,keyPassword:s,profile:e.profileFilePath,signAlg:mt.signAlg,storeFile:e.p12FilePath,storePassword:a}},l=o.app?.signingConfigs?.findIndex(h=>h.name===i);l!==void 0&&l>=0?o.app.signingConfigs[l]=c:o.app.signingConfigs.push(c);let d=o.app?.products?.findIndex(h=>h.name===i);d!==void 0&&d>=0?o.app.products[d].signingConfig=i:o.app.products.push({name:i,signingConfig:i}),hu.writeFileSync(r,JSON.stringify(o,null,2),"utf-8")}async function EL(n){let e=await ae.getUserInfo(),t=await ae.refreshToken();if(!e||!t)throw new Error("Failed to obtain login credentials. Run `devecocli login` again.");return{uid:e.userId??"",teamId:n.teamId??e.userId??"",accessToken:t.accessToken??""}}async function PL(n){let e=n.product||"default";await new dc().preflight({productName:e,teamId:n.teamId}),console.log("Executing signature generate command");let r=await EL(n),o=await I.new(),{shouldRegenerate:i}=await Ii.shouldRegenerate({force:n.force??!1,teamId:r.teamId,productName:n.product},o);if(!i){console.log(mu("Signature generation completed successfully."));return}await CL(n,r,o),console.log(mu("Signature generation completed successfully."))}async function CL(n,e,t){let r=await tu(e,n.product),o=IL(n,e,r,t);o.allDeviceIds=await $w(e,t.hdcPath),await Vw(e,o);let i=G.discover(process.cwd()).rootDir;await bL(i,r,n.product??"default"),console.log(mu(`Signing config written to ${Zw.join(i,"build-profile.json5")}`))}function IL(n,e,t,r){let o=process.cwd(),i=G.discover(o),s=rc(i,r);return Kw(s,i),{productName:n.product||"default",bundleName:i.getBundleName(),projectPath:i.rootDir,teamId:e.teamId,force:n.force||!1,aclPermissionList:[...s],certIds:[t.certId],keyAlias:t.keyAlias,keyPwd:t.keyPwd}}var Qw=new hL("signature").description("Generate application signature.");Qw.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 n=>{try{await PL(n)}catch(e){console.error(gL(e.message)),process.exit(1)}});var ev=Qw;process.env.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE="";AL();ie.name("devecocli").description("HarmonyOS application development command line tool").version("0.3.0-TD.2-alpha2");ie.addCommand(ep);ie.addCommand(kp);ie.addCommand(Op);ie.addCommand(Vp);ie.addCommand(Bf);ie.addCommand(fm);ie.addCommand(ym);ie.addCommand(Dm);ie.addCommand(Mm);ie.addCommand(th);ie.addCommand(py);ie.addCommand(ev);ie.addCommand(hw);ie.addCommand(Fy);b()||ie.addCommand(bf);var gu=process.argv.slice(2);gu.length>=2&&gu[gu.length-1]==="help"&&(process.argv=[...process.argv.slice(0,-1),"--help"]);var RL=new Set(["update","auth"]);ie.hook("preAction",async(n,e)=>{if(process.env.DEVECO_CLI_SKIP_VERSION_CHECK)return;let t=e;for(;t.parent&&t.parent!==ie;)t=t.parent;RL.has(t.name())||await I.checkVersion()});ie.parseAsync(process.argv).catch(n=>{let e=n instanceof Error?n.message:String(n??"Unknown error");console.error(DL(`Error: ${e}`)),process.env.DEVECO_CLI_DEBUG==="1"&&n instanceof Error&&n.stack&&console.error(n.stack),process.exit(1)});
1415
+ `);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=r.match(/[A-Fa-f0-9]{64}/);return i?i[0].toUpperCase():""}async function UN(n,e){let{stdout:t}=await du(e,["-c","-t",n,"shell","getprop","hw_sc.build.os.deviceType"],{stdio:["ignore","pipe","pipe"]});return BN(t)}function BN(n){let e=n.trim();return!e||e.includes("inaccessible")?"phone":n.includes("liteWearable")?"liteWearable":n.includes("wearable")?"wearable":n.includes("tv")?"tv":"phone"}import Qn from"fs";import{createHash as WN}from"crypto";import{debuglog as Vt}from"util";import{Buffer as qw}from"buffer";import{createPublicKey as GN,X509Certificate as uu}from"crypto";import{readFileSync as zN}from"fs";import er from"node-forge";async function Vw(n,e){console.log("Start generating profile");let{productName:t,bundleName:r,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=`${Q.BASE_URL}${Q.PROVISION_ADD_TEST_PATH}`,h=qN(t,r),w=await JN(n,d,a||[],r,s,h,i||[]);if(!w||!w.profileInfo||!w.profileInfo.provisionFileUrl)throw Vt("add provision failed, the provision file url is null"),new Error(E.ADD_PROFILE_FAIL);let S=w.profileInfo,re=(await ZN(n,S.provisionFileUrl)).urlList,Re=w.profileInfo.id;if(re&&re.length>0){let Pe=await Pw(t,o),Ge=Pe.profilePath;if(!await QN(re,Ge))throw await zw(n,Re),new Error(E.ERROR_WHILE_DOWNLOAD_PROFILE);if(await zw(n,Re),Qn.existsSync(Pe.certPath)&&Qn.existsSync(Ge)&&Qn.existsSync(Pe.p12Path)){let tv=Qn.readFileSync(Pe.certPath,"utf8"),nv=Qn.readFileSync(Ge,"utf8");return eL(nv,tv,Pe.p12Path,c,l)||XN(Ge),Ge}}throw new Error(E.ADD_PROFILE_FAIL)}function qN(n,e){let t=n?`${n}_`:"";return`${VN(`${t}${e}_${e}`)}`}function VN(n){return WN("sha256").update(n).digest("hex").substring(0,16)}async function JN(n,e,t,r,o,i,s){YN(r);let a=fu(n),c={certList:t,packageName:r,deviceList:o,provisionName:i};s.length&&(c.aclPermissionList=s);let l=await N.postAllowFailure(e,{headers:a,params:c});if(!l)throw Vt("add provision failed: response is null"),new Error(E.ADD_PROFILE_FAIL);if(l.statusCode!==200)throw pu(l.statusCode,l.statusText,l.data);let d=JSON.parse(l.data);if(!d||!d.ret||d.ret.code!==0)throw Vt(`add provision fail: ${l.data}`),KN(l.data,i),new Error(d.ret?.msg||E.ADD_PROFILE_FAIL);let h=d.provisionFileUrl;return{profileInfo:{id:d.id,name:i,provisionFileUrl:h}}}function pu(n,e,t){return n===ft.FORBIDDEN?e===ye.OPENPROXY_BLOCKED_URL?new Error(E.ERR_CERT_NETWORK_ERROR):new Error(E.ERR_FORBIDDEN):n===ft.UNAUTHORIZED?new Error(E.ERR_UNAUTHORIZED):t.includes(ye.PROVISION_EXCEEDS_LIMIT_CODE)?new Error(E.TEST_PROVISION_EXCEEDS_LIMIT):new Error(E.ADD_PROFILE_FAIL)}function YN(n){if(!n||n.trim().length===0)throw new Error(E.ERROR_SIGN_BUNDLE_NAME_VALIDATE);if(!je.BUNDLE_NAME_REGEX.test(n))throw new Error(E.ERROR_SIGN_BUNDLE_NAME_VALIDATE)}function KN(n,e){if(n.includes(ye.PROVISION_EXCEEDS_LIMIT_CODE))throw new Error(E.TEST_PROVISION_EXCEEDS_LIMIT);if(n.includes(ye.PROVISION_NAME_REPEAT_CODE)&&e)throw new Error(E.PROFILE_NAME_REPEAT)}async function zw(n,e){if(!e||e.trim().length===0)return;let t=`${Q.BASE_URL}${Q.PROVISION_DELETE_PATH}?id=${e}`,r=await N.deleteAllowFailure(t,{headers:fu(n)});if(r.statusCode!==200)throw pu(r.statusCode,r.statusText,r.data);let o=JSON.parse(r.data);(!o||!o.ret||o.ret.code!==0)&&Vt(`delete provision failed: ${r.data}`)}function XN(...n){for(let e of n)try{Qn.existsSync(e)&&Qn.unlinkSync(e)}catch(t){Vt(`delete local sign file error: ${t.message}`)}}async function ZN(n,e){let t=`${Q.BASE_URL}${Q.CERT_DOWNLOAD_URL_PATH}`,r=fu(n),o={sourceUrls:e},i=await N.postAllowFailure(t,{headers:r,params:o});if(!i)throw Vt("get download list failed: response is null"),new Error(E.ADD_PROFILE_FAIL);if(i.statusCode!==200)throw pu(i.statusCode,i.statusText,i.data);let s=JSON.parse(i.data);if(!s||!s.urlsInfo||s.urlsInfo.length===0)throw Vt("download: The application does not exist"),new Error(s.ret?.msg||E.ADD_PROFILE_FAIL);return{urlList:s.urlsInfo,hasPermission:!0}}async function QN(n,e){if(!n||n.length===0)return!1;let t=n[0].newUrl;return await Ei(t,e),!0}function eL(n,e,t,r,o){return tL(n,e),r=r||je.TARGET_FRIENDLY_NAME,o=o||"",nL(e,t,r,o),!0}function tL(n,e){if(e.lastIndexOf(je.CERT_BEGIN_HEADER)<0)throw new Error(E.ERROR_WHILE_PARSE_PROFILE);let t=JSON.stringify(e.substring(e.lastIndexOf(je.CERT_BEGIN_HEADER))).replace(/\\r/g,"");if(!n.includes(t))throw new Error(E.CERTIFICATION_AND_PROFILE_NOT_INCONSISTENT);return!0}function nL(n,e,t,r){let o=n.matchAll(je.CERTIFICATE_PATTERN_GLOBAL),i=[],s=new Date;for(let c of o)try{let l=c[0],d=rL(l),h=new Date(d.validFrom),w=new Date(d.validTo);if(s<h||s>w){let S=`Certificate is not valid, Valid from ${h} to ${w}`;throw console.warn(`checkCertificateInValidityPeriod: ${S}`),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(!iL(e,t,r,i))throw new Error(E.CERTIFICATION_AND_PROFILE_NOT_INCONSISTENT)}function rL(n){let e="-----BEGIN CERTIFICATE-----",t=n.trim();try{if(t.startsWith(e))return new uu(t);let r=qw.from(t,"base64");return new uu(r)}catch(r){throw new Error("decodeBase64ToX509Certificate",{cause:r})}}function oL(n){if(n.cert){let e=er.pki.publicKeyToPem(n.cert.publicKey);return GN(e).export({type:"spki",format:"der"})}if(n.asn1)try{let e=er.asn1.toDer(n.asn1).getBytes(),t=qw.from(e,"binary");return new uu(t).publicKey.export({type:"spki",format:"der"})}catch(e){return Vt(`Failed to parse cert from asn1: ${e}`),null}return null}function iL(n,e,t,r){try{let o=zN(n),i=er.asn1.fromDer(er.util.createBuffer(o)),c=er.pkcs12.pkcs12FromAsn1(i,t).getBags({bagType:er.pki.oids.certBag})[er.pki.oids.certBag]||[];for(let l of c){let d=l.attributes?.friendlyName?.[0];if(!d||d.toLowerCase()!==e.toLowerCase())continue;let h=oL(l);if(!h)continue;if(r.some(S=>{let k=S.publicKey.export({type:"spki",format:"der"});return h.equals(k)}))return!0}return!1}catch(o){let i=o instanceof Error?o.message:String(o);return Vt(`Failed to process P12 file: ${n}, error: ${i}`),!1}}function fu(n){return{uid:n.uid,teamId:n.teamId,oauth2Token:n.accessToken}}var Yw="https://developer.huawei.com",sL={"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"},aL="/consumer/cn/doc/harmonyos-guides/restricted-permissions";function cL(n){let e=sL[n];return e?`${Yw}${e}`:void 0}function lL(){return`${Yw}${aL}`}var dL={"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 Jw(n,e){return(dL[n]??n).replace(/\{(\d+)\}/g,(r,o)=>String(e[Number(o)]??""))}function uL(n){return Array.from(n).join(", ")}function Kw(n,e){if(n.size===0)return;let t=An.getAclPermissionInfos(e),r=new Set;for(let h of t)n.has(h.permissionName)&&r.add(h);for(let h of r){let w=cL(h.permissionName);w!=null&&(h.permissionHelpUrlKey=w)}let o=new Set;for(let h of r)o.add(h.permissionDisplayName);let i=new Set;for(let h of r)if(h.permissionHelpUrlKey!=null){let w=h.permissionInsteadName??h.permissionDisplayName;i.add(`${w} (${h.permissionHelpUrlKey})`)}let s=lL(),a=Jw("acl.can.apply.text",[]),c=s?`${a} (${s})`:a,l=i.size>0?Array.from(i).join(", ")+".":"",d=Jw("acl.permissions.warn",[uL(o),l,c]);console.log(d)}var sc=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=G.discover(process.cwd()),{passed:!0,message:""}}catch(t){return m(`[EnvCheck] Project.discover() failed: ${t.message}`),e(K.PROJECT_DIR_MISSING)}}checkProduct(e,t){try{return this._project.validateProduct(e),{passed:!0,message:""}}catch(r){return m(`[EnvCheck] Product validation failed: ${r.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(r){return m(`[EnvCheck] BundleName check failed: ${r.message}`),t(`bundleName was not found under product "${e}".Check the bundleName configuration.`)}}checkAtomicService(){return this._project.isAtomicService()?{passed:!1,message:K.ATOMIC_SERVICE_UNSUPPORTED}:{passed:!0,message:""}}};import pL from"fs";import Xw from"path";var ac=class{constructor(e){this.toolProvider=e}toolProvider;checkJava(e){try{return this.toolProvider.assertJava(),{passed:!0,message:""}}catch(t){return m(`[EnvCheck] Java check failed: ${t.message}`),e(K.JAVA_PLATFORM_UNSUPPORTED)}}checkHapSignTools(e){let t=this.toolProvider.sdkPath,r=b()?"hap-sign-tool":"hap-sign-tool.jar",o=Xw.join(t,"default","openharmony","toolchains","lib",r);if(!pL.existsSync(o)){let i=Xw.join("sdk","default","openharmony","toolchains","lib",r);return e(`${r} not found.Check whether ${i} exists.`)}return{passed:!0,message:""}}};var cc=class{_userInfo=null;async ensureUserInfo(){if(!this._userInfo)try{this._userInfo=await ae.getUserInfo()}catch(e){return m(`[EnvCheck] Failed to load user info: ${e.message}`),null}return this._userInfo}async checkLogin(e){try{return await ae.isLoggedIn()?(await this.ensureUserInfo(),{passed:!0,message:""}):e(K.LOGIN_REQUIRED)}catch(t){return m(`[EnvCheck] Login check failed: ${t.message}`),e(K.LOGIN_REQUIRED)}}async checkTeamInfo(e){if(!await this.ensureUserInfo())return e(K.TEAM_INFO_FAILED);try{if((await tn()).teamList.length>0)return{passed:!0,message:""}}catch(r){return m(`[EnvCheck] Team API error: ${r.message}`),e(K.TEAM_INFO_FAILED)}return m("[EnvCheck] No teams found for current user"),e(K.TEAM_INFO_FAILED)}async checkRealname(e){let t=await this.ensureUserInfo();return t?t.isRealName===!1?e(K.REALNAME_REQUIRED):t.isRealName!==!0?(m("[EnvCheck] Scenario 3 Real-name check: AGC API did not return realName field"),e(K.REALNAME_REQUIRED)):{passed:!0,message:""}:e(K.SESSION_EXPIRED)}async checkTeamId(e){let t=await this.ensureUserInfo();if(!t)return{passed:!0,message:""};let r=e??"";try{let o=await tn();if(r=e??(o.teamList.length>0?o.teamList[0].id:t.userId)??"",!o.teamList.some(s=>s.id===r)){let s=`team-id for ${r} not found.Run devecocli auth team list to view the team to which the logged-in user belongs.`;return m(`[EnvCheck] ${s}`),{passed:!1,message:s}}return{passed:!0,message:""}}catch(o){return m(`[EnvCheck] Team ID check failed: ${o.message}`),{passed:!1,message:`team-id for ${r} 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(K.REGION_CHINA_ONLY):{passed:!0,message:""}:(m("[EnvCheck] Scenario 12 Region check: AGC API did not return nationalCode field"),e(K.REGION_CHINA_ONLY)):e("User session expired or token invalid. Please login again.")}};async function fL(n){try{let{teamList:e}=await tn();if(e.length>0)return e[0].id}catch(e){m(`[EnvCheck] resolveDefaultTeamId failed: ${e.message}`)}return n??""}async function mL(n){let e=await ae.getUserInfo(),t=await ae.refreshToken();if(!e||!t?.accessToken)throw new Error("Not logged in");let r=n||await fL(e.userId);if(!r)throw new Error("No team found");let o={uid:e.userId??"",teamId:r,accessToken:t.accessToken};return(await ic(o)).map(s=>({deviceId:s.udid,deviceName:s.deviceName}))}var lc=class{constructor(e){this.toolProvider=e}toolProvider;async checkDevice(e,t){try{let r=await mL(t);if(r.length>0)return m(`[EnvCheck] Scenario 4 Device check: ${r.length} device(s) found in AGC cloud, skipping local device check`),{passed:!0,message:""};m("[EnvCheck] Scenario 4 Device check: no cloud devices found, falling back to local hdc");let i=await te.from(this.toolProvider).listDevices();return i.length===0?(m("[EnvCheck] Scenario 4 Device check: no local devices found"),e(K.DEVICE_MISSING)):i.some(a=>On(a.serial))?{passed:!0,message:""}:(m("[EnvCheck] Scenario 4 Device check: local device found but not an emulator"),e(K.DEVICE_MISSING))}catch(r){return m(`[EnvCheck] Scenario 4 Device check failed: ${r.message}`),e(K.DEVICE_DETECT_FAILED)}}};var dc=class{projectChecker=new sc;toolchainChecker=null;authChecker=new cc;deviceChecker=null;constructor(){}async preflight(e){let t=r=>this.blockingFail(r);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 r=i=>(i.passed||this.fail(i),!0),o=[()=>this.authChecker.checkLogin(t),()=>this.authChecker.checkTeamInfo(t),()=>this.authChecker.checkRealname(t)];for(let i of o)if(!r(await i()))return!1;return!(e.teamId&&!r(await this.authChecker.checkTeamId(e.teamId)))}async initToolchain(){try{let e=await I.new();return this.toolchainChecker=new ac(e),this.deviceChecker=new lc(e),!0}catch(e){throw m(`[EnvCheck] ToolProvider.new() failed: ${e.message}`),new Error(K.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 r=i=>i.passed?!0:(this.fail(i),!1);if(!r(this.projectChecker.checkProjectDir(t))||!r(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(!r(i()))return!1;return!0}async runAuxChecks(e){let t=r=>r.passed?!0:(this.fail(r),!1);return!e.teamId&&!t(await this.authChecker.checkTeamId(e.teamId))?!1:(await this.authChecker.checkRegion(r=>this.blockingFail(r)),!0)}blockingFail(e){return{passed:!1,message:e}}fail(e){throw m(`[EnvCheck] FAIL: ${e.message}`),new Error(e.message)}};function wL(n){if(hu.existsSync(n)){let e=hu.readFileSync(n,"utf-8");return yL.parse(e)}return{app:{signingConfigs:[],products:[]}}}function vL(n){n.app||(n.app={signingConfigs:[],products:[]}),n.app.signingConfigs||(n.app.signingConfigs=[]),n.app.products||(n.app.products=[])}async function SL(n){if(n.keyPwd===n.storePassword){let r=await In.encryptedPassword(n.keyPwd,n.p12FilePath);return{keyPassword:r,storePassword:r}}let e=await In.encryptedPassword(n.keyPwd,n.p12FilePath),t=await In.encryptedPassword(n.storePassword,n.p12FilePath);return{keyPassword:e,storePassword:t}}async function bL(n,e,t){let r=Zw.join(n,"build-profile.json5"),o=wL(r);vL(o);let i=t??"default",{keyPassword:s,storePassword:a}=await SL(e),c={name:i,type:"HarmonyOS",material:{certpath:e.cerFilePath,keyAlias:e.keyAlias,keyPassword:s,profile:e.profileFilePath,signAlg:mt.signAlg,storeFile:e.p12FilePath,storePassword:a}},l=o.app?.signingConfigs?.findIndex(h=>h.name===i);l!==void 0&&l>=0?o.app.signingConfigs[l]=c:o.app.signingConfigs.push(c);let d=o.app?.products?.findIndex(h=>h.name===i);d!==void 0&&d>=0?o.app.products[d].signingConfig=i:o.app.products.push({name:i,signingConfig:i}),hu.writeFileSync(r,JSON.stringify(o,null,2),"utf-8")}async function EL(n){let e=await ae.getUserInfo(),t=await ae.refreshToken();if(!e||!t)throw new Error("Failed to obtain login credentials. Run `devecocli login` again.");return{uid:e.userId??"",teamId:n.teamId??e.userId??"",accessToken:t.accessToken??""}}async function PL(n){let e=n.product||"default";await new dc().preflight({productName:e,teamId:n.teamId}),console.log("Executing signature generate command");let r=await EL(n),o=await I.new(),{shouldRegenerate:i}=await Ii.shouldRegenerate({force:n.force??!1,teamId:r.teamId,productName:n.product},o);if(!i){console.log(mu("Signature generation completed successfully."));return}await CL(n,r,o),console.log(mu("Signature generation completed successfully."))}async function CL(n,e,t){let r=await tu(e,n.product),o=IL(n,e,r,t);o.allDeviceIds=await $w(e,t.hdcPath),await Vw(e,o);let i=G.discover(process.cwd()).rootDir;await bL(i,r,n.product??"default"),console.log(mu(`Signing config written to ${Zw.join(i,"build-profile.json5")}`))}function IL(n,e,t,r){let o=process.cwd(),i=G.discover(o),s=rc(i,r);return Kw(s,i),{productName:n.product||"default",bundleName:i.getBundleName(),projectPath:i.rootDir,teamId:e.teamId,force:n.force||!1,aclPermissionList:[...s],certIds:[t.certId],keyAlias:t.keyAlias,keyPwd:t.keyPwd}}var Qw=new hL("signature").description("Generate application signature.");Qw.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 n=>{try{await PL(n)}catch(e){console.error(gL(e.message)),process.exit(1)}});var ev=Qw;process.env.GLOBAL_AGENT_ENVIRONMENT_VARIABLE_NAMESPACE="";AL();ie.name("devecocli").description("HarmonyOS application development command line tool").version("0.3.0-TD.2");ie.addCommand(ep);ie.addCommand(kp);ie.addCommand(Op);ie.addCommand(Vp);ie.addCommand(Bf);ie.addCommand(fm);ie.addCommand(ym);ie.addCommand(Dm);ie.addCommand(Mm);ie.addCommand(th);ie.addCommand(py);ie.addCommand(ev);ie.addCommand(hw);ie.addCommand(Fy);b()||ie.addCommand(bf);var gu=process.argv.slice(2);gu.length>=2&&gu[gu.length-1]==="help"&&(process.argv=[...process.argv.slice(0,-1),"--help"]);var RL=new Set(["update","auth"]);ie.hook("preAction",async(n,e)=>{if(process.env.DEVECO_CLI_SKIP_VERSION_CHECK)return;let t=e;for(;t.parent&&t.parent!==ie;)t=t.parent;RL.has(t.name())||await I.checkVersion()});ie.parseAsync(process.argv).catch(n=>{let e=n instanceof Error?n.message:String(n??"Unknown error");console.error(DL(`Error: ${e}`)),process.env.DEVECO_CLI_DEBUG==="1"&&n instanceof Error&&n.stack&&console.error(n.stack),process.exit(1)});
package/index.zip CHANGED
Binary file
package/package.json CHANGED
@@ -1,102 +1,102 @@
1
- {
2
- "name": "@deveco-test/hmos-deveco-cli",
3
- "version": "0.3.0-TD.2-alpha2",
4
- "description": "HarmonyOS application development command line tool",
5
- "license": "MIT",
6
- "type": "module",
7
- "bin": {
8
- "devecocli": "dist/cli.js"
9
- },
10
- "files": [
11
- "dist",
12
- "scripts/postinstall.mjs",
13
- "scripts/install-better-sqlite3.mjs",
14
- "scripts/install-jieba-wasm.mjs",
15
- "scripts/lib/better-sqlite3-vendor.mjs",
16
- "scripts/lib/jieba-wasm-vendor.mjs",
17
- "scripts/lib/cli-data-dir.mjs",
18
- "scripts/lib/doc-init-log-path.mjs",
19
- "templates",
20
- "src/resources",
21
- "THIRD-PARTY-LICENSES",
22
- "SKILL.md",
23
- "docs.zip",
24
- "index.zip"
25
- ],
26
- "scripts": {
27
- "prepare": "husky",
28
- "postinstall": "node scripts/postinstall.mjs",
29
- "build": "tsup",
30
- "build:index": "tsx index/build-index-bundle.ts",
31
- "dev": "tsx watch src/cli.ts",
32
- "start": "tsx src/cli.ts",
33
- "lint": "eslint src",
34
- "lint:fix": "eslint src --fix",
35
- "format": "prettier --write src",
36
- "license": "generate-license-file --input package.json --output THIRD-PARTY-LICENSES --overwrite --ci",
37
- "prepublishOnly": "npm run lint && npm run license && npm run build"
38
- },
39
- "engines": {
40
- "node": ">=18"
41
- },
42
- "keywords": [
43
- "harmonyos",
44
- "deveco",
45
- "cli"
46
- ],
47
- "devDependencies": {
48
- "@eslint/js": "^10.0.1",
49
- "@types/adm-zip": "^0.5.8",
50
- "@types/better-sqlite3": "^7.6.13",
51
- "@types/fs-extra": "^11.0.4",
52
- "@types/global-agent": "^3.0.0",
53
- "@types/node": "^25.6.0",
54
- "@types/turndown": "^5.0.5",
55
- "@types/yauzl": "^2.10.3",
56
- "eslint": "^10.2.1",
57
- "generate-license-file": "^4.2.1",
58
- "husky": "^9.1.7",
59
- "prettier": "^3.8.3",
60
- "tsup": "^8.5.1",
61
- "tsx": "^4.21.0",
62
- "turndown": "^7.2.4",
63
- "typescript": "^6.0.3",
64
- "@types/node-forge": "^1.3.14",
65
- "typescript-eslint": "^8.59.1"
66
- },
67
- "dependencies": {
68
- "@modelcontextprotocol/sdk": "^1.29.0",
69
- "@sqlite.org/sqlite-wasm": "^3.49.1-build4",
70
- "adm-zip": "^0.5.17",
71
- "axios": "1.17.0",
72
- "colorette": "^2.0.20",
73
- "commander": "^13.1.0",
74
- "execa": "^9.6.1",
75
- "fs-extra": "^11.3.4",
76
- "global-agent": "^4.1.3",
77
- "jieba-wasm": "^2.4.0",
78
- "json5": "^2.2.3",
79
- "mdast-util-to-string": "^4.0.0",
80
- "ora": "^8.2.0",
81
- "p-limit": "^5.0.0",
82
- "proper-lockfile": "^4.1.2",
83
- "regedit": "^5.1.4",
84
- "remark-gfm": "^4.0.1",
85
- "socket.io-client": "^4.7.5",
86
- "remark-parse": "^11.0.0",
87
- "smol-toml": "^1.6.1",
88
- "unified": "^11.0.5",
89
- "xdg-basedir": "^5.1.0",
90
- "yauzl": "^3.2.0",
91
- "node-forge": "^1.4.0",
92
- "zod": "^4.4.3"
93
- },
94
- "optionalDependencies": {
95
- "@node-rs/jieba": "^2.0.1",
96
- "better-sqlite3": "^12.11.1",
97
- "@node-rs/jieba-wasm32-wasi": "2.0.1"
98
- },
99
- "overrides": {
100
- "dotenv": "16.4.7"
101
- }
102
- }
1
+ {
2
+ "name": "@deveco-test/hmos-deveco-cli",
3
+ "version": "0.3.0-TD.2",
4
+ "description": "HarmonyOS application development command line tool",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "devecocli": "dist/cli.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "scripts/postinstall.mjs",
13
+ "scripts/install-better-sqlite3.mjs",
14
+ "scripts/install-jieba-wasm.mjs",
15
+ "scripts/lib/better-sqlite3-vendor.mjs",
16
+ "scripts/lib/jieba-wasm-vendor.mjs",
17
+ "scripts/lib/cli-data-dir.mjs",
18
+ "scripts/lib/doc-init-log-path.mjs",
19
+ "templates",
20
+ "src/resources",
21
+ "THIRD-PARTY-LICENSES",
22
+ "SKILL.md",
23
+ "docs.zip",
24
+ "index.zip"
25
+ ],
26
+ "scripts": {
27
+ "prepare": "husky",
28
+ "postinstall": "node scripts/postinstall.mjs",
29
+ "build": "tsup",
30
+ "build:index": "tsx index/build-index-bundle.ts",
31
+ "dev": "tsx watch src/cli.ts",
32
+ "start": "tsx src/cli.ts",
33
+ "lint": "eslint src",
34
+ "lint:fix": "eslint src --fix",
35
+ "format": "prettier --write src",
36
+ "license": "generate-license-file --input package.json --output THIRD-PARTY-LICENSES --overwrite --ci",
37
+ "prepublishOnly": "npm run lint && npm run license && npm run build"
38
+ },
39
+ "engines": {
40
+ "node": ">=18"
41
+ },
42
+ "keywords": [
43
+ "harmonyos",
44
+ "deveco",
45
+ "cli"
46
+ ],
47
+ "devDependencies": {
48
+ "@eslint/js": "^10.0.1",
49
+ "@types/adm-zip": "^0.5.8",
50
+ "@types/better-sqlite3": "^7.6.13",
51
+ "@types/fs-extra": "^11.0.4",
52
+ "@types/global-agent": "^3.0.0",
53
+ "@types/node": "^25.6.0",
54
+ "@types/turndown": "^5.0.5",
55
+ "@types/yauzl": "^2.10.3",
56
+ "eslint": "^10.2.1",
57
+ "generate-license-file": "^4.2.1",
58
+ "husky": "^9.1.7",
59
+ "prettier": "^3.8.3",
60
+ "tsup": "^8.5.1",
61
+ "tsx": "^4.21.0",
62
+ "turndown": "^7.2.4",
63
+ "typescript": "^6.0.3",
64
+ "@types/node-forge": "^1.3.14",
65
+ "typescript-eslint": "^8.59.1"
66
+ },
67
+ "dependencies": {
68
+ "@modelcontextprotocol/sdk": "^1.29.0",
69
+ "@sqlite.org/sqlite-wasm": "^3.49.1-build4",
70
+ "adm-zip": "^0.5.17",
71
+ "axios": "1.17.0",
72
+ "colorette": "^2.0.20",
73
+ "commander": "^13.1.0",
74
+ "execa": "^9.6.1",
75
+ "fs-extra": "^11.3.4",
76
+ "global-agent": "^4.1.3",
77
+ "jieba-wasm": "^2.4.0",
78
+ "json5": "^2.2.3",
79
+ "mdast-util-to-string": "^4.0.0",
80
+ "ora": "^8.2.0",
81
+ "p-limit": "^5.0.0",
82
+ "proper-lockfile": "^4.1.2",
83
+ "regedit": "^5.1.4",
84
+ "remark-gfm": "^4.0.1",
85
+ "socket.io-client": "^4.7.5",
86
+ "remark-parse": "^11.0.0",
87
+ "smol-toml": "^1.6.1",
88
+ "unified": "^11.0.5",
89
+ "xdg-basedir": "^5.1.0",
90
+ "yauzl": "^3.2.0",
91
+ "node-forge": "^1.4.0",
92
+ "zod": "^4.4.3"
93
+ },
94
+ "optionalDependencies": {
95
+ "@node-rs/jieba": "^2.0.1",
96
+ "better-sqlite3": "^12.11.1",
97
+ "@node-rs/jieba-wasm32-wasi": "2.0.1"
98
+ },
99
+ "overrides": {
100
+ "dotenv": "16.4.7"
101
+ }
102
+ }
@@ -1,51 +1,51 @@
1
- /*
2
- * Copyright (c) 2026 Huawei Device Co., Ltd.
3
- * SPDX-License-Identifier: MIT
4
- */
5
-
6
- import { appendFile, mkdir } from 'fs/promises';
7
- import { dirname } from 'path';
8
- import { getDocInitLogPath } from './lib/doc-init-log-path.mjs';
9
- import {
10
- installBetterSqlite3ViaNpm,
11
- isBetterSqlite3Loadable,
12
- resolveTargetVersion,
13
- } from './lib/better-sqlite3-vendor.mjs';
14
-
15
- async function appendInstallLog(message) {
16
- try {
17
- const logPath = getDocInitLogPath();
18
- await mkdir(dirname(logPath), { recursive: true });
19
- await appendFile(
20
- logPath,
21
- `${new Date().toISOString()} [better-sqlite3] ${message}\n`
22
- );
23
- } catch {
24
- // ignore logging failures
25
- }
26
- }
27
-
28
- /** @deprecated Use installBetterSqlite3ViaNpm */
29
- export const ensureBetterSqlite3NativeBinary = installBetterSqlite3ViaNpm;
30
-
31
- export async function ensureBetterSqlite3ForDocs() {
32
- const targetVersion = resolveTargetVersion();
33
- await appendInstallLog(
34
- `ensure better-sqlite3@${targetVersion} for Node ${process.version} via npm install`
35
- );
36
-
37
- if (await isBetterSqlite3Loadable()) {
38
- await appendInstallLog('skip: better-sqlite3 already loadable');
39
- return { ok: true, skipped: true, reason: 'already-installed' };
40
- }
41
-
42
- const result = await installBetterSqlite3ViaNpm();
43
- if (result.ok) {
44
- await appendInstallLog(`installed better-sqlite3@${targetVersion} via npm`);
45
- } else {
46
- await appendInstallLog(
47
- `npm install failed (${result.reason}): ${result.error ?? 'unknown error'}`
48
- );
49
- }
50
- return result;
51
- }
1
+ /*
2
+ * Copyright (c) 2026 Huawei Device Co., Ltd.
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { appendFile, mkdir } from 'fs/promises';
7
+ import { dirname } from 'path';
8
+ import { getDocInitLogPath } from './lib/doc-init-log-path.mjs';
9
+ import {
10
+ installBetterSqlite3ViaNpm,
11
+ isBetterSqlite3Loadable,
12
+ resolveTargetVersion,
13
+ } from './lib/better-sqlite3-vendor.mjs';
14
+
15
+ async function appendInstallLog(message) {
16
+ try {
17
+ const logPath = getDocInitLogPath();
18
+ await mkdir(dirname(logPath), { recursive: true });
19
+ await appendFile(
20
+ logPath,
21
+ `${new Date().toISOString()} [better-sqlite3] ${message}\n`
22
+ );
23
+ } catch {
24
+ // ignore logging failures
25
+ }
26
+ }
27
+
28
+ /** @deprecated Use installBetterSqlite3ViaNpm */
29
+ export const ensureBetterSqlite3NativeBinary = installBetterSqlite3ViaNpm;
30
+
31
+ export async function ensureBetterSqlite3ForDocs() {
32
+ const targetVersion = resolveTargetVersion();
33
+ await appendInstallLog(
34
+ `ensure better-sqlite3@${targetVersion} for Node ${process.version} via npm install`
35
+ );
36
+
37
+ if (await isBetterSqlite3Loadable()) {
38
+ await appendInstallLog('skip: better-sqlite3 already loadable');
39
+ return { ok: true, skipped: true, reason: 'already-installed' };
40
+ }
41
+
42
+ const result = await installBetterSqlite3ViaNpm();
43
+ if (result.ok) {
44
+ await appendInstallLog(`installed better-sqlite3@${targetVersion} via npm`);
45
+ } else {
46
+ await appendInstallLog(
47
+ `npm install failed (${result.reason}): ${result.error ?? 'unknown error'}`
48
+ );
49
+ }
50
+ return result;
51
+ }