@shepai/cli 1.170.0 → 1.171.0

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 (182) hide show
  1. package/dist/packages/core/src/application/use-cases/upgrade/upgrade-cli.use-case.d.ts +1 -0
  2. package/dist/packages/core/src/application/use-cases/upgrade/upgrade-cli.use-case.d.ts.map +1 -1
  3. package/dist/packages/core/src/application/use-cases/upgrade/upgrade-cli.use-case.js +59 -2
  4. package/dist/src/presentation/cli/commands/upgrade.command.d.ts.map +1 -1
  5. package/dist/src/presentation/cli/commands/upgrade.command.js +68 -3
  6. package/dist/translations/ar/cli.json +2 -0
  7. package/dist/translations/de/cli.json +2 -0
  8. package/dist/translations/en/cli.json +2 -0
  9. package/dist/translations/es/cli.json +2 -0
  10. package/dist/translations/fr/cli.json +2 -0
  11. package/dist/translations/he/cli.json +2 -0
  12. package/dist/translations/pt/cli.json +2 -0
  13. package/dist/translations/ru/cli.json +2 -0
  14. package/dist/tsconfig.build.tsbuildinfo +1 -1
  15. package/package.json +1 -1
  16. package/web/.next/BUILD_ID +1 -1
  17. package/web/.next/build-manifest.json +2 -2
  18. package/web/.next/fallback-build-manifest.json +2 -2
  19. package/web/.next/prerender-manifest.json +3 -3
  20. package/web/.next/required-server-files.js +2 -2
  21. package/web/.next/required-server-files.json +2 -2
  22. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +29 -29
  23. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  24. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  25. package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +27 -27
  26. package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
  27. package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
  28. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +30 -30
  29. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  30. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  31. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +38 -38
  32. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  33. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  34. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +38 -38
  35. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  36. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  37. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
  38. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  39. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  40. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
  41. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  42. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  43. package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +27 -27
  44. package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
  45. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
  46. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +30 -30
  47. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  48. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  49. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +38 -38
  50. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  51. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  52. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +38 -38
  53. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  54. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  55. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +27 -27
  56. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  57. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  58. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
  59. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  60. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  61. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
  62. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  63. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  64. package/web/.next/server/app/_global-error.html +2 -2
  65. package/web/.next/server/app/_global-error.rsc +1 -1
  66. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  67. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  68. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  69. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  70. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  71. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +6 -6
  72. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  73. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  74. package/web/.next/server/app/features/page/server-reference-manifest.json +6 -6
  75. package/web/.next/server/app/features/page.js.nft.json +1 -1
  76. package/web/.next/server/app/features/page_client-reference-manifest.js +1 -1
  77. package/web/.next/server/app/settings/page/server-reference-manifest.json +9 -9
  78. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  79. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  80. package/web/.next/server/app/skills/page/server-reference-manifest.json +13 -13
  81. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  82. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  83. package/web/.next/server/app/tools/page/server-reference-manifest.json +11 -11
  84. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  85. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  86. package/web/.next/server/app/version/page/server-reference-manifest.json +6 -6
  87. package/web/.next/server/app/version/page.js.nft.json +1 -1
  88. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  89. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  90. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  91. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  92. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +2 -2
  93. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js.map +1 -1
  94. package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js +1 -1
  95. package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js.map +1 -1
  96. package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js +1 -1
  97. package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js.map +1 -1
  98. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  99. package/web/.next/server/chunks/ssr/[root-of-the-server]__4fb81977._.js +1 -1
  100. package/web/.next/server/chunks/ssr/[root-of-the-server]__4fb81977._.js.map +1 -1
  101. package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js +1 -1
  102. package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js.map +1 -1
  103. package/web/.next/server/chunks/ssr/[root-of-the-server]__7dcd0917._.js +1 -1
  104. package/web/.next/server/chunks/ssr/[root-of-the-server]__7dcd0917._.js.map +1 -1
  105. package/web/.next/server/chunks/ssr/[root-of-the-server]__92ffd5ee._.js +2 -2
  106. package/web/.next/server/chunks/ssr/[root-of-the-server]__92ffd5ee._.js.map +1 -1
  107. package/web/.next/server/chunks/ssr/[root-of-the-server]__b020c17d._.js +2 -2
  108. package/web/.next/server/chunks/ssr/[root-of-the-server]__b020c17d._.js.map +1 -1
  109. package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js +1 -1
  110. package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js.map +1 -1
  111. package/web/.next/server/chunks/ssr/[root-of-the-server]__ba7f5873._.js +1 -1
  112. package/web/.next/server/chunks/ssr/[root-of-the-server]__ba7f5873._.js.map +1 -1
  113. package/web/.next/server/chunks/ssr/[root-of-the-server]__c5e09f6f._.js +1 -1
  114. package/web/.next/server/chunks/ssr/[root-of-the-server]__c5e09f6f._.js.map +1 -1
  115. package/web/.next/server/chunks/ssr/_02e01240._.js +1 -1
  116. package/web/.next/server/chunks/ssr/_02e01240._.js.map +1 -1
  117. package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
  118. package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
  119. package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
  120. package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
  121. package/web/.next/server/chunks/ssr/_18886033._.js +1 -1
  122. package/web/.next/server/chunks/ssr/_18886033._.js.map +1 -1
  123. package/web/.next/server/chunks/ssr/_22e00a14._.js +1 -1
  124. package/web/.next/server/chunks/ssr/_22e00a14._.js.map +1 -1
  125. package/web/.next/server/chunks/ssr/{_deabc145._.js → _49447b3c._.js} +2 -2
  126. package/web/.next/server/chunks/ssr/{_deabc145._.js.map → _49447b3c._.js.map} +1 -1
  127. package/web/.next/server/chunks/ssr/_4cbb7f95._.js +1 -1
  128. package/web/.next/server/chunks/ssr/_4cbb7f95._.js.map +1 -1
  129. package/web/.next/server/chunks/ssr/_56b9d60f._.js +1 -1
  130. package/web/.next/server/chunks/ssr/_56b9d60f._.js.map +1 -1
  131. package/web/.next/server/chunks/ssr/_a5a5901d._.js +1 -1
  132. package/web/.next/server/chunks/ssr/_a5a5901d._.js.map +1 -1
  133. package/web/.next/server/chunks/ssr/_ad09f271._.js +1 -1
  134. package/web/.next/server/chunks/ssr/_ad09f271._.js.map +1 -1
  135. package/web/.next/server/chunks/ssr/_c3f595c6._.js +1 -1
  136. package/web/.next/server/chunks/ssr/_c3f595c6._.js.map +1 -1
  137. package/web/.next/server/chunks/ssr/{_0d7dd23b._.js → _d50cde79._.js} +2 -2
  138. package/web/.next/server/chunks/ssr/{_0d7dd23b._.js.map → _d50cde79._.js.map} +1 -1
  139. package/web/.next/server/chunks/ssr/_df737cce._.js +1 -1
  140. package/web/.next/server/chunks/ssr/_ea9e1556._.js +1 -1
  141. package/web/.next/server/chunks/ssr/_ea9e1556._.js.map +1 -1
  142. package/web/.next/server/chunks/ssr/_f1ba9be6._.js +2 -2
  143. package/web/.next/server/chunks/ssr/_f1ba9be6._.js.map +1 -1
  144. package/web/.next/server/chunks/ssr/_f33cd07e._.js +2 -2
  145. package/web/.next/server/chunks/ssr/_f33cd07e._.js.map +1 -1
  146. package/web/.next/server/chunks/ssr/{_77ae079a._.js → _f778f3ef._.js} +2 -2
  147. package/web/.next/server/chunks/ssr/{_77ae079a._.js.map → _f778f3ef._.js.map} +1 -1
  148. package/web/.next/server/chunks/ssr/_f8b45233._.js +1 -1
  149. package/web/.next/server/chunks/ssr/_f8b45233._.js.map +1 -1
  150. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  151. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  152. package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js +1 -1
  153. package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js.map +1 -1
  154. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
  155. package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js +1 -1
  156. package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js.map +1 -1
  157. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  158. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  159. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.js +1 -1
  160. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.js.map +1 -1
  161. package/web/.next/server/pages/500.html +2 -2
  162. package/web/.next/server/server-reference-manifest.js +1 -1
  163. package/web/.next/server/server-reference-manifest.json +50 -50
  164. package/web/.next/static/chunks/{a3802d6f8677cd04.js → 02fe1303471793b9.js} +2 -2
  165. package/web/.next/static/chunks/{06a86173379e6c51.js → 0ce50b34df07306b.js} +1 -1
  166. package/web/.next/static/chunks/{16ed73f9880b7d63.js → 18d4601f068c700d.js} +1 -1
  167. package/web/.next/static/chunks/{8e12deeabf6624e9.js → 24dd6b3021c2d849.js} +1 -1
  168. package/web/.next/static/chunks/{74e5b5c7950efbc1.js → 3d182168cdc4c15c.js} +1 -1
  169. package/web/.next/static/chunks/{f51250616da82bd2.js → 4383bcae769740e7.js} +1 -1
  170. package/web/.next/static/chunks/{2b2f3a70ebd6ac1c.js → 5983ef48d50d2d2a.js} +1 -1
  171. package/web/.next/static/chunks/{f9da308b3033c57a.js → 67a430796dea42a7.js} +1 -1
  172. package/web/.next/static/chunks/{ca23a8642f750548.js → 6ee5d45de67d3547.js} +2 -2
  173. package/web/.next/static/chunks/{7a6854bb07182777.js → 9705f2a5695a4995.js} +1 -1
  174. package/web/.next/static/chunks/a80bbfca8ee3d79b.js +1 -0
  175. package/web/.next/static/chunks/{3d1df5c349d855eb.js → aa077ab14015a8fd.js} +1 -1
  176. package/web/.next/static/chunks/{c5a0b452afc8fe47.js → b93a918712cd4987.js} +1 -1
  177. package/web/.next/static/chunks/{f29814a72404ea2b.js → bb962a996814718a.js} +1 -1
  178. package/web/.next/static/chunks/{b0a6fce5425f8d3a.js → eff45ffddd85918c.js} +1 -1
  179. package/web/.next/static/chunks/9c6f8f49799efd3a.js +0 -1
  180. /package/web/.next/static/{0KDwNT3AGQmFGIwjHx99r → akDn2qFk1krSwrjt4345P}/_buildManifest.js +0 -0
  181. /package/web/.next/static/{0KDwNT3AGQmFGIwjHx99r → akDn2qFk1krSwrjt4345P}/_clientMiddlewareManifest.json +0 -0
  182. /package/web/.next/static/{0KDwNT3AGQmFGIwjHx99r → akDn2qFk1krSwrjt4345P}/_ssgManifest.js +0 -0
@@ -24,6 +24,7 @@ export declare class UpgradeCliUseCase {
24
24
  constructor(versionService: IVersionService, daemonService: IDaemonService);
25
25
  execute(onOutput?: (data: string) => void): Promise<UpgradeResult>;
26
26
  private getLatestVersion;
27
+ private preDownloadPackage;
27
28
  /**
28
29
  * Schedule a daemon self-restart after upgrade.
29
30
  * Reads the current daemon port, spawns a new daemon process with the
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade-cli.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/upgrade/upgrade-cli.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0DAA0D,CAAC;AAChG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yDAAyD,CAAC;AAE9F,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAOD,qBACa,iBAAiB;IAG1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAFb,cAAc,EAAE,eAAe,EAE/B,aAAa,EAAE,cAAc;IAG1C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC;IAkCxE,OAAO,CAAC,gBAAgB;IA6CxB;;;;OAIG;IACG,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B5C,OAAO,CAAC,aAAa;CAuBtB"}
1
+ {"version":3,"file":"upgrade-cli.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/upgrade/upgrade-cli.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0DAA0D,CAAC;AAChG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yDAAyD,CAAC;AAE9F,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAQD,qBACa,iBAAiB;IAG1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAFb,cAAc,EAAE,eAAe,EAE/B,aAAa,EAAE,cAAc;IAG1C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC;IAyCxE,OAAO,CAAC,gBAAgB;IA6CxB,OAAO,CAAC,kBAAkB;IAwD1B;;;;OAIG;IACG,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B5C,OAAO,CAAC,aAAa;CAuBtB"}
@@ -24,7 +24,11 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
24
24
  };
25
25
  import { injectable, inject } from 'tsyringe';
26
26
  import { spawn } from 'node:child_process';
27
+ import { mkdtempSync, rmSync } from 'node:fs';
28
+ import { tmpdir } from 'node:os';
29
+ import { join } from 'node:path';
27
30
  const VERSION_CHECK_TIMEOUT_MS = 10_000;
31
+ const NPM_CACHE_ADD_TIMEOUT_MS = 120_000;
28
32
  /** Delay (ms) before the current process exits to allow the SSE response to flush. */
29
33
  const SELF_RESTART_DELAY_MS = 1_000;
30
34
  let UpgradeCliUseCase = class UpgradeCliUseCase {
@@ -43,8 +47,14 @@ let UpgradeCliUseCase = class UpgradeCliUseCase {
43
47
  onOutput?.(`Already up to date (v${currentVersion})\n`);
44
48
  return { status: 'up-to-date', currentVersion, latestVersion };
45
49
  }
46
- // 3. Run upgrade
50
+ // 3. Pre-download the package into npm cache before install
47
51
  const target = latestVersion ? `v${latestVersion}` : 'latest';
52
+ onOutput?.(`Downloading @shepai/cli@latest...\n`);
53
+ const cached = await this.preDownloadPackage();
54
+ if (!cached) {
55
+ onOutput?.('Pre-download did not complete — proceeding with install...\n');
56
+ }
57
+ // 4. Run install (fast if cached)
48
58
  onOutput?.(`Upgrading from v${currentVersion} to ${target}...\n`);
49
59
  try {
50
60
  const exitCode = await this.runNpmInstall(onOutput);
@@ -104,6 +114,53 @@ let UpgradeCliUseCase = class UpgradeCliUseCase {
104
114
  });
105
115
  });
106
116
  }
117
+ preDownloadPackage() {
118
+ let tmpDir;
119
+ try {
120
+ tmpDir = mkdtempSync(join(tmpdir(), 'shep-upgrade-'));
121
+ }
122
+ catch {
123
+ return Promise.resolve(false);
124
+ }
125
+ const cleanup = () => {
126
+ try {
127
+ rmSync(tmpDir, { recursive: true, force: true });
128
+ }
129
+ catch {
130
+ /* best-effort */
131
+ }
132
+ };
133
+ return new Promise((resolve) => {
134
+ let settled = false;
135
+ const child = spawn('npm', ['install', '--prefix', tmpDir, '--ignore-scripts', '@shepai/cli@latest'], {
136
+ stdio: ['ignore', 'ignore', 'pipe'],
137
+ });
138
+ const timeout = setTimeout(() => {
139
+ if (!settled) {
140
+ settled = true;
141
+ child.kill();
142
+ cleanup();
143
+ resolve(false);
144
+ }
145
+ }, NPM_CACHE_ADD_TIMEOUT_MS);
146
+ child.on('close', (code) => {
147
+ if (!settled) {
148
+ settled = true;
149
+ clearTimeout(timeout);
150
+ cleanup();
151
+ resolve(code === 0);
152
+ }
153
+ });
154
+ child.on('error', () => {
155
+ if (!settled) {
156
+ settled = true;
157
+ clearTimeout(timeout);
158
+ cleanup();
159
+ resolve(false);
160
+ }
161
+ });
162
+ });
163
+ }
107
164
  /**
108
165
  * Schedule a daemon self-restart after upgrade.
109
166
  * Reads the current daemon port, spawns a new daemon process with the
@@ -130,7 +187,7 @@ let UpgradeCliUseCase = class UpgradeCliUseCase {
130
187
  }
131
188
  runNpmInstall(onOutput) {
132
189
  return new Promise((resolve, reject) => {
133
- const child = spawn('npm', ['i', '-g', '@shepai/cli@latest'], {
190
+ const child = spawn('npm', ['i', '-g', '@shepai/cli@latest', '--prefer-offline'], {
134
191
  stdio: ['ignore', 'pipe', 'pipe'],
135
192
  });
136
193
  child.stdout?.on('data', (data) => {
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/upgrade.command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,IAAI,YAAY,EAAqB,MAAM,oBAAoB,CAAC;AAS9E,KAAK,OAAO,GAAG,OAAO,YAAY,CAAC;AA8EnC;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,OAAsB,GAAG,OAAO,CAqE7E"}
1
+ {"version":3,"file":"upgrade.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/upgrade.command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,IAAI,YAAY,EAAqB,MAAM,oBAAoB,CAAC;AAY9E,KAAK,OAAO,GAAG,OAAO,YAAY,CAAC;AA8InC;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,OAAsB,GAAG,OAAO,CA6E7E"}
@@ -8,12 +8,16 @@
8
8
  */
9
9
  import { Command } from 'commander';
10
10
  import { spawn as defaultSpawn } from 'node:child_process';
11
+ import { mkdtempSync, rmSync } from 'node:fs';
12
+ import { tmpdir } from 'node:os';
13
+ import { join } from 'node:path';
11
14
  import { container } from '../../../../packages/core/src/infrastructure/di/container.js';
12
15
  import { messages } from '../ui/index.js';
13
16
  import { getCliI18n } from '../i18n.js';
14
17
  import { stopDaemon } from './daemon/stop-daemon.js';
15
18
  import { startDaemon } from './daemon/start-daemon.js';
16
19
  const VERSION_CHECK_TIMEOUT_MS = 10_000;
20
+ const NPM_CACHE_ADD_TIMEOUT_MS = 120_000;
17
21
  /** On Windows, npm is a .cmd batch file — spawn() needs shell: true to resolve it. */
18
22
  const IS_WINDOWS = process.platform === 'win32';
19
23
  /**
@@ -61,13 +65,67 @@ function getLatestVersion(spawnFn) {
61
65
  });
62
66
  });
63
67
  }
68
+ /**
69
+ * Pre-download the package AND all transitive dependencies into npm's cache.
70
+ * Uses `npm install --prefix <tmpdir>` which resolves the full dependency tree
71
+ * and populates the cache. The temp directory is cleaned up afterwards.
72
+ * Returns true if the pre-download succeeded, false otherwise (fail-open).
73
+ */
74
+ function preDownloadPackage(spawnFn) {
75
+ let tmpDir;
76
+ try {
77
+ tmpDir = mkdtempSync(join(tmpdir(), 'shep-upgrade-'));
78
+ }
79
+ catch {
80
+ return Promise.resolve(false);
81
+ }
82
+ const cleanup = () => {
83
+ try {
84
+ rmSync(tmpDir, { recursive: true, force: true });
85
+ }
86
+ catch {
87
+ /* best-effort */
88
+ }
89
+ };
90
+ return new Promise((resolve) => {
91
+ let settled = false;
92
+ const child = spawnFn('npm', ['install', '--prefix', tmpDir, '--ignore-scripts', '@shepai/cli@latest'], {
93
+ stdio: ['ignore', 'ignore', 'pipe'],
94
+ ...(IS_WINDOWS && { shell: true }),
95
+ });
96
+ const timeout = setTimeout(() => {
97
+ if (!settled) {
98
+ settled = true;
99
+ child.kill();
100
+ cleanup();
101
+ resolve(false);
102
+ }
103
+ }, NPM_CACHE_ADD_TIMEOUT_MS);
104
+ child.on('close', (code) => {
105
+ if (!settled) {
106
+ settled = true;
107
+ clearTimeout(timeout);
108
+ cleanup();
109
+ resolve(code === 0);
110
+ }
111
+ });
112
+ child.on('error', () => {
113
+ if (!settled) {
114
+ settled = true;
115
+ clearTimeout(timeout);
116
+ cleanup();
117
+ resolve(false);
118
+ }
119
+ });
120
+ });
121
+ }
64
122
  /**
65
123
  * Run npm i -g @shepai/cli@latest with inherited stdio.
66
124
  * Returns the exit code, or rejects on spawn error.
67
125
  */
68
126
  function runNpmInstall(spawnFn) {
69
127
  return new Promise((resolve, reject) => {
70
- const child = spawnFn('npm', ['i', '-g', '@shepai/cli@latest'], {
128
+ const child = spawnFn('npm', ['i', '-g', '@shepai/cli@latest', '--prefer-offline'], {
71
129
  stdio: 'inherit',
72
130
  ...(IS_WINDOWS && { shell: true }),
73
131
  });
@@ -107,7 +165,14 @@ export function createUpgradeCommand(spawnFn = defaultSpawn) {
107
165
  else {
108
166
  messages.info(t('cli:commands.upgrade.upgradingToLatest', { current: currentVersion }));
109
167
  }
110
- // 4. Check daemon state before install (FR-1)
168
+ // 4. Pre-download the package into npm cache BEFORE stopping the daemon.
169
+ // This minimizes downtime — the actual install will read from cache.
170
+ messages.info(t('cli:commands.upgrade.downloadingPackage'));
171
+ const cached = await preDownloadPackage(spawnFn);
172
+ if (!cached) {
173
+ messages.warning(t('cli:commands.upgrade.downloadFailed'));
174
+ }
175
+ // 5. Check daemon state and stop if running
111
176
  const daemonService = container.resolve('IDaemonService');
112
177
  const daemonState = await daemonService.read();
113
178
  const daemonWasRunning = daemonState !== null && daemonService.isAlive(daemonState.pid);
@@ -116,7 +181,7 @@ export function createUpgradeCommand(spawnFn = defaultSpawn) {
116
181
  messages.info(t('cli:commands.upgrade.stoppingDaemon'));
117
182
  await stopDaemon(daemonService);
118
183
  }
119
- // 5. Run npm i -g @shepai/cli@latest; always restore daemon in finally (FR-2, FR-3)
184
+ // 6. Run npm i -g @shepai/cli@latest; always restore daemon in finally
120
185
  let installExitCode = 1;
121
186
  try {
122
187
  installExitCode = await runNpmInstall(spawnFn);
@@ -567,6 +567,8 @@
567
567
  "alreadyUpToDate": "محدّث بالفعل (v{{version}})",
568
568
  "upgradingFromTo": "الترقية من v{{current}} إلى v{{latest}}",
569
569
  "upgradingToLatest": "الترقية من v{{current}} إلى الأحدث",
570
+ "downloadingPackage": "جارٍ تنزيل الإصدار الجديد...",
571
+ "downloadFailed": "لم يكتمل التنزيل المسبق — المتابعة بالتثبيت",
570
572
  "stoppingDaemon": "جارٍ إيقاف الخدمة الخلفية قبل الترقية...",
571
573
  "restartingDaemon": "جارٍ إعادة تشغيل الخدمة الخلفية...",
572
574
  "daemonRestarted": "تمت إعادة تشغيل الخدمة الخلفية بنجاح.",
@@ -567,6 +567,8 @@
567
567
  "alreadyUpToDate": "Bereits aktuell (v{{version}})",
568
568
  "upgradingFromTo": "Aktualisierung von v{{current}} auf v{{latest}}",
569
569
  "upgradingToLatest": "Aktualisierung von v{{current}} auf die neueste Version",
570
+ "downloadingPackage": "Neue Version wird heruntergeladen...",
571
+ "downloadFailed": "Vorab-Download nicht abgeschlossen — Installation wird fortgesetzt",
570
572
  "stoppingDaemon": "Dienst wird vor Aktualisierung gestoppt...",
571
573
  "restartingDaemon": "Dienst wird neu gestartet...",
572
574
  "daemonRestarted": "Dienst erfolgreich neu gestartet.",
@@ -567,6 +567,8 @@
567
567
  "alreadyUpToDate": "Already up to date (v{{version}})",
568
568
  "upgradingFromTo": "Upgrading from v{{current}} to v{{latest}}",
569
569
  "upgradingToLatest": "Upgrading from v{{current}} to latest",
570
+ "downloadingPackage": "Downloading new version...",
571
+ "downloadFailed": "Pre-download did not complete — proceeding with install",
570
572
  "stoppingDaemon": "Stopping daemon before upgrade...",
571
573
  "restartingDaemon": "Restarting daemon...",
572
574
  "daemonRestarted": "Daemon restarted successfully.",
@@ -567,6 +567,8 @@
567
567
  "alreadyUpToDate": "Ya está actualizado (v{{version}})",
568
568
  "upgradingFromTo": "Actualizando de v{{current}} a v{{latest}}",
569
569
  "upgradingToLatest": "Actualizando de v{{current}} a la última versión",
570
+ "downloadingPackage": "Descargando nueva versión...",
571
+ "downloadFailed": "La descarga previa no se completó — continuando con la instalación",
570
572
  "stoppingDaemon": "Deteniendo el demonio antes de actualizar...",
571
573
  "restartingDaemon": "Reiniciando el demonio...",
572
574
  "daemonRestarted": "Demonio reiniciado exitosamente.",
@@ -567,6 +567,8 @@
567
567
  "alreadyUpToDate": "Déjà à jour (v{{version}})",
568
568
  "upgradingFromTo": "Mise à jour de v{{current}} vers v{{latest}}",
569
569
  "upgradingToLatest": "Mise à jour de v{{current}} vers la dernière version",
570
+ "downloadingPackage": "Téléchargement de la nouvelle version...",
571
+ "downloadFailed": "Le pré-téléchargement n'a pas abouti — poursuite de l'installation",
570
572
  "stoppingDaemon": "Arrêt du démon avant la mise à jour...",
571
573
  "restartingDaemon": "Redémarrage du démon...",
572
574
  "daemonRestarted": "Démon redémarré avec succès.",
@@ -567,6 +567,8 @@
567
567
  "alreadyUpToDate": "כבר מעודכן (v{{version}})",
568
568
  "upgradingFromTo": "משדרג מ-v{{current}} ל-v{{latest}}",
569
569
  "upgradingToLatest": "משדרג מ-v{{current}} לגרסה האחרונה",
570
+ "downloadingPackage": "מוריד גרסה חדשה...",
571
+ "downloadFailed": "ההורדה המוקדמת לא הושלמה — ממשיך בהתקנה",
570
572
  "stoppingDaemon": "עוצר תהליך לפני שדרוג...",
571
573
  "restartingDaemon": "מפעיל מחדש תהליך...",
572
574
  "daemonRestarted": "התהליך הופעל מחדש בהצלחה.",
@@ -567,6 +567,8 @@
567
567
  "alreadyUpToDate": "Já está atualizado (v{{version}})",
568
568
  "upgradingFromTo": "Atualizando de v{{current}} para v{{latest}}",
569
569
  "upgradingToLatest": "Atualizando de v{{current}} para a mais recente",
570
+ "downloadingPackage": "Baixando nova versão...",
571
+ "downloadFailed": "Download prévio não concluído — prosseguindo com a instalação",
570
572
  "stoppingDaemon": "Parando daemon antes da atualização...",
571
573
  "restartingDaemon": "Reiniciando daemon...",
572
574
  "daemonRestarted": "Daemon reiniciado com sucesso.",
@@ -567,6 +567,8 @@
567
567
  "alreadyUpToDate": "Уже актуальная версия (v{{version}})",
568
568
  "upgradingFromTo": "Обновление с v{{current}} до v{{latest}}",
569
569
  "upgradingToLatest": "Обновление с v{{current}} до последней версии",
570
+ "downloadingPackage": "Загрузка новой версии...",
571
+ "downloadFailed": "Предварительная загрузка не завершена — продолжение установки",
570
572
  "stoppingDaemon": "Остановка демона перед обновлением...",
571
573
  "restartingDaemon": "Перезапуск демона...",
572
574
  "daemonRestarted": "Демон успешно перезапущен.",