@shepai/cli 1.103.0 → 1.103.1-pr308.436876d

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 (166) hide show
  1. package/dist/packages/core/src/application/use-cases/upgrade/upgrade-cli.use-case.d.ts +27 -0
  2. package/dist/packages/core/src/application/use-cases/upgrade/upgrade-cli.use-case.d.ts.map +1 -0
  3. package/dist/packages/core/src/application/use-cases/upgrade/upgrade-cli.use-case.js +128 -0
  4. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  5. package/dist/packages/core/src/infrastructure/di/container.js +5 -0
  6. package/dist/packages/core/src/infrastructure/services/git/worktree.service.d.ts.map +1 -1
  7. package/dist/packages/core/src/infrastructure/services/git/worktree.service.js +1 -3
  8. package/dist/src/presentation/cli/ui/symbols.d.ts +1 -1
  9. package/dist/src/presentation/web/app/api/cli-upgrade/route.d.ts +3 -0
  10. package/dist/src/presentation/web/app/api/cli-upgrade/route.d.ts.map +1 -0
  11. package/dist/src/presentation/web/app/api/cli-upgrade/route.js +31 -0
  12. package/dist/src/presentation/web/components/common/version-badge/version-badge.d.ts.map +1 -1
  13. package/dist/src/presentation/web/components/common/version-badge/version-badge.js +6 -2
  14. package/dist/src/presentation/web/components/common/version-badge/version-badge.stories.d.ts +2 -2
  15. package/dist/src/presentation/web/components/common/version-badge/version-badge.stories.d.ts.map +1 -1
  16. package/dist/src/presentation/web/components/common/version-badge/version-badge.stories.js +20 -3
  17. package/dist/src/presentation/web/hooks/use-cli-upgrade.d.ts +11 -0
  18. package/dist/src/presentation/web/hooks/use-cli-upgrade.d.ts.map +1 -0
  19. package/dist/src/presentation/web/hooks/use-cli-upgrade.js +73 -0
  20. package/dist/tsconfig.build.tsbuildinfo +1 -1
  21. package/package.json +1 -1
  22. package/web/.next/BUILD_ID +1 -1
  23. package/web/.next/app-path-routes-manifest.json +1 -0
  24. package/web/.next/build-manifest.json +2 -2
  25. package/web/.next/fallback-build-manifest.json +2 -2
  26. package/web/.next/prerender-manifest.json +3 -3
  27. package/web/.next/required-server-files.js +3 -3
  28. package/web/.next/required-server-files.json +3 -3
  29. package/web/.next/routes-manifest.json +6 -0
  30. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +20 -20
  31. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  32. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  33. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +25 -25
  34. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  35. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  36. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +25 -25
  37. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  38. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  39. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
  40. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  41. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  42. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +20 -20
  43. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  44. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  45. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +25 -25
  46. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  47. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  48. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +25 -25
  49. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  50. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  51. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +18 -18
  52. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  53. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  54. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
  55. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  56. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  57. package/web/.next/server/app/_global-error.html +2 -2
  58. package/web/.next/server/app/_global-error.rsc +1 -1
  59. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  60. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  61. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  62. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  63. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  64. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  65. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  66. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  67. package/web/.next/server/app/api/cli-upgrade/route/app-paths-manifest.json +3 -0
  68. package/web/.next/server/app/api/cli-upgrade/route/build-manifest.json +11 -0
  69. package/web/.next/server/app/api/cli-upgrade/route/server-reference-manifest.json +4 -0
  70. package/web/.next/server/app/api/cli-upgrade/route.js +6 -0
  71. package/web/.next/server/app/api/cli-upgrade/route.js.map +5 -0
  72. package/web/.next/server/app/api/cli-upgrade/route.js.nft.json +1 -0
  73. package/web/.next/server/app/api/cli-upgrade/route_client-reference-manifest.js +2 -0
  74. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  75. package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
  76. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  77. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  78. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  79. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  80. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  81. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  82. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  83. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  84. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  85. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  86. package/web/.next/server/app-paths-manifest.json +1 -0
  87. package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_cli-upgrade_route_actions_dc509b52.js +3 -0
  88. package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_cli-upgrade_route_actions_dc509b52.js.map +1 -0
  89. package/web/.next/server/chunks/[root-of-the-server]__d2c18946._.js +11 -0
  90. package/web/.next/server/chunks/[root-of-the-server]__d2c18946._.js.map +1 -0
  91. package/web/.next/server/chunks/[root-of-the-server]__f47bb8a5._.js +1 -1
  92. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  93. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  94. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_0a7546ed.js +1 -1
  95. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_0a7546ed.js.map +1 -1
  96. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_978cbb4c.js +1 -1
  97. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_978cbb4c.js.map +1 -1
  98. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
  99. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
  100. package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +2 -2
  101. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  102. package/web/.next/server/chunks/ssr/[root-of-the-server]__51fc98b0._.js +1 -1
  103. package/web/.next/server/chunks/ssr/[root-of-the-server]__51fc98b0._.js.map +1 -1
  104. package/web/.next/server/chunks/ssr/[root-of-the-server]__57f37786._.js +1 -1
  105. package/web/.next/server/chunks/ssr/[root-of-the-server]__57f37786._.js.map +1 -1
  106. package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
  107. package/web/.next/server/chunks/ssr/[root-of-the-server]__708dcad1._.js +1 -1
  108. package/web/.next/server/chunks/ssr/[root-of-the-server]__708dcad1._.js.map +1 -1
  109. package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js +1 -1
  110. package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js.map +1 -1
  111. package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js +2 -2
  112. package/web/.next/server/chunks/ssr/[root-of-the-server]__8e002910._.js +1 -1
  113. package/web/.next/server/chunks/ssr/[root-of-the-server]__8e002910._.js.map +1 -1
  114. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
  115. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  116. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
  117. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
  118. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  119. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  120. package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
  121. package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
  122. package/web/.next/server/chunks/ssr/{_43bc1b22._.js → _a09fb04a._.js} +2 -2
  123. package/web/.next/server/chunks/ssr/{_43bc1b22._.js.map → _a09fb04a._.js.map} +1 -1
  124. package/web/.next/server/chunks/ssr/{_6225647a._.js → _afa40e06._.js} +2 -2
  125. package/web/.next/server/chunks/ssr/{_6225647a._.js.map → _afa40e06._.js.map} +1 -1
  126. package/web/.next/server/chunks/ssr/{_798dcca3._.js → _baab52a9._.js} +2 -2
  127. package/web/.next/server/chunks/ssr/{_798dcca3._.js.map → _baab52a9._.js.map} +1 -1
  128. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  129. package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
  130. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  131. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  132. package/web/.next/server/chunks/ssr/src_presentation_web_7275ce5d._.js +2 -2
  133. package/web/.next/server/chunks/ssr/src_presentation_web_7275ce5d._.js.map +1 -1
  134. package/web/.next/server/chunks/ssr/src_presentation_web_758dfa10._.js +2 -2
  135. package/web/.next/server/chunks/ssr/src_presentation_web_758dfa10._.js.map +1 -1
  136. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_84803221.js +1 -1
  137. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_84803221.js.map +1 -1
  138. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  139. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  140. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  141. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  142. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
  143. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
  144. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  145. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  146. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  147. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  148. package/web/.next/server/pages/500.html +2 -2
  149. package/web/.next/server/server-reference-manifest.js +1 -1
  150. package/web/.next/server/server-reference-manifest.json +30 -30
  151. package/web/.next/static/chunks/{790f576eb41aedc6.js → 2549eb5f74129ce6.js} +1 -1
  152. package/web/.next/static/chunks/{87ce4933c46c0c18.js → 2f3dedf11842dbb9.js} +1 -1
  153. package/web/.next/static/chunks/{f37993a7b6f87fcb.js → 3b5a1f399be3c204.js} +1 -1
  154. package/web/.next/static/chunks/3bb35e0689e8b6b7.js +1 -0
  155. package/web/.next/static/chunks/5a850475e2b3e8d7.js +2 -0
  156. package/web/.next/static/chunks/{28aa6c032562c065.js → 5b52afbeb6af43f8.js} +1 -1
  157. package/web/.next/static/chunks/{a39402a05bf12912.js → 6f16220ca6a15488.js} +1 -1
  158. package/web/.next/static/chunks/{3ff4c5790bf84403.js → c72a9bffb0609ccb.js} +1 -1
  159. package/web/.next/static/chunks/{12f2e950ef2c1a25.js → d7acdf8831c942f1.js} +1 -1
  160. package/web/.next/static/chunks/{27b176706ec35488.js → f164721e9111efd2.js} +2 -2
  161. package/web/.next/static/chunks/{5981cd90d8cbdad7.js → f8a27920b2acfead.js} +1 -1
  162. package/web/.next/static/chunks/2a6f05312c4f37ce.js +0 -1
  163. package/web/.next/static/chunks/8f9956f5871a8cdb.js +0 -2
  164. /package/web/.next/static/{YTwpzFRHYkkE5cDxaRlDQ → Bn9oiHUSrxNyoG9stevwc}/_buildManifest.js +0 -0
  165. /package/web/.next/static/{YTwpzFRHYkkE5cDxaRlDQ → Bn9oiHUSrxNyoG9stevwc}/_clientMiddlewareManifest.json +0 -0
  166. /package/web/.next/static/{YTwpzFRHYkkE5cDxaRlDQ → Bn9oiHUSrxNyoG9stevwc}/_ssgManifest.js +0 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * UpgradeCliUseCase
3
+ *
4
+ * Executes a self-upgrade of @shepai/cli to the latest published version.
5
+ * Mirrors the CLI upgrade command logic but designed for use from the web layer.
6
+ *
7
+ * Flow:
8
+ * 1. Check latest version from npm registry (fail-open)
9
+ * 2. Compare with current version — return early if up to date
10
+ * 3. Run `npm i -g @shepai/cli@latest` with streamed output
11
+ * 4. Return result with old/new version info
12
+ */
13
+ import type { IVersionService } from '../../ports/output/services/version-service.interface.js';
14
+ export interface UpgradeResult {
15
+ status: 'up-to-date' | 'upgraded' | 'error';
16
+ currentVersion: string;
17
+ latestVersion: string | null;
18
+ errorMessage?: string;
19
+ }
20
+ export declare class UpgradeCliUseCase {
21
+ private readonly versionService;
22
+ constructor(versionService: IVersionService);
23
+ execute(onOutput?: (data: string) => void): Promise<UpgradeResult>;
24
+ private getLatestVersion;
25
+ private runNpmInstall;
26
+ }
27
+ //# sourceMappingURL=upgrade-cli.use-case.d.ts.map
@@ -0,0 +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;AAEhG,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;AAID,qBACa,iBAAiB;IAG1B,OAAO,CAAC,QAAQ,CAAC,cAAc;gBAAd,cAAc,EAAE,eAAe;IAG5C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC;IAkCxE,OAAO,CAAC,gBAAgB;IA6CxB,OAAO,CAAC,aAAa;CAuBtB"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * UpgradeCliUseCase
3
+ *
4
+ * Executes a self-upgrade of @shepai/cli to the latest published version.
5
+ * Mirrors the CLI upgrade command logic but designed for use from the web layer.
6
+ *
7
+ * Flow:
8
+ * 1. Check latest version from npm registry (fail-open)
9
+ * 2. Compare with current version — return early if up to date
10
+ * 3. Run `npm i -g @shepai/cli@latest` with streamed output
11
+ * 4. Return result with old/new version info
12
+ */
13
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
14
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
15
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
16
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
17
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
18
+ };
19
+ var __metadata = (this && this.__metadata) || function (k, v) {
20
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
21
+ };
22
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
23
+ return function (target, key) { decorator(target, key, paramIndex); }
24
+ };
25
+ import { injectable, inject } from 'tsyringe';
26
+ import { spawn } from 'node:child_process';
27
+ const VERSION_CHECK_TIMEOUT_MS = 10_000;
28
+ let UpgradeCliUseCase = class UpgradeCliUseCase {
29
+ versionService;
30
+ constructor(versionService) {
31
+ this.versionService = versionService;
32
+ }
33
+ async execute(onOutput) {
34
+ const { version: currentVersion } = this.versionService.getVersion();
35
+ // 1. Check latest version (fail-open)
36
+ const latestVersion = await this.getLatestVersion(onOutput);
37
+ // 2. Already up to date
38
+ if (latestVersion && latestVersion === currentVersion) {
39
+ onOutput?.(`Already up to date (v${currentVersion})\n`);
40
+ return { status: 'up-to-date', currentVersion, latestVersion };
41
+ }
42
+ // 3. Run upgrade
43
+ const target = latestVersion ? `v${latestVersion}` : 'latest';
44
+ onOutput?.(`Upgrading from v${currentVersion} to ${target}...\n`);
45
+ try {
46
+ const exitCode = await this.runNpmInstall(onOutput);
47
+ if (exitCode === 0) {
48
+ onOutput?.(`Successfully upgraded to ${target}\n`);
49
+ return { status: 'upgraded', currentVersion, latestVersion };
50
+ }
51
+ else {
52
+ const msg = `npm install exited with code ${exitCode}`;
53
+ onOutput?.(`Error: ${msg}\n`);
54
+ return { status: 'error', currentVersion, latestVersion, errorMessage: msg };
55
+ }
56
+ }
57
+ catch (error) {
58
+ const msg = error instanceof Error ? error.message : 'Installation failed';
59
+ onOutput?.(`Error: ${msg}\n`);
60
+ return { status: 'error', currentVersion, latestVersion, errorMessage: msg };
61
+ }
62
+ }
63
+ getLatestVersion(onOutput) {
64
+ return new Promise((resolve) => {
65
+ let output = '';
66
+ let settled = false;
67
+ const child = spawn('npm', ['view', '@shepai/cli', 'version'], {
68
+ stdio: ['ignore', 'pipe', 'pipe'],
69
+ });
70
+ const timeout = setTimeout(() => {
71
+ if (!settled) {
72
+ settled = true;
73
+ child.kill();
74
+ onOutput?.('Version check timed out, proceeding with upgrade...\n');
75
+ resolve(null);
76
+ }
77
+ }, VERSION_CHECK_TIMEOUT_MS);
78
+ child.stdout?.on('data', (data) => {
79
+ output += data.toString();
80
+ });
81
+ child.on('close', (code) => {
82
+ if (!settled) {
83
+ settled = true;
84
+ clearTimeout(timeout);
85
+ if (code === 0 && output.trim()) {
86
+ resolve(output.trim());
87
+ }
88
+ else {
89
+ resolve(null);
90
+ }
91
+ }
92
+ });
93
+ child.on('error', () => {
94
+ if (!settled) {
95
+ settled = true;
96
+ clearTimeout(timeout);
97
+ onOutput?.('Could not check latest version\n');
98
+ resolve(null);
99
+ }
100
+ });
101
+ });
102
+ }
103
+ runNpmInstall(onOutput) {
104
+ return new Promise((resolve, reject) => {
105
+ const child = spawn('npm', ['i', '-g', '@shepai/cli@latest'], {
106
+ stdio: ['ignore', 'pipe', 'pipe'],
107
+ });
108
+ child.stdout?.on('data', (data) => {
109
+ onOutput?.(data.toString());
110
+ });
111
+ child.stderr?.on('data', (data) => {
112
+ onOutput?.(data.toString());
113
+ });
114
+ child.on('close', (code) => {
115
+ resolve(code ?? 1);
116
+ });
117
+ child.on('error', (err) => {
118
+ reject(err);
119
+ });
120
+ });
121
+ }
122
+ };
123
+ UpgradeCliUseCase = __decorate([
124
+ injectable(),
125
+ __param(0, inject('IVersionService')),
126
+ __metadata("design:paramtypes", [Object])
127
+ ], UpgradeCliUseCase);
128
+ export { UpgradeCliUseCase };
@@ -1 +1 @@
1
- {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/di/container.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAiHrC;;;;;;GAMG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,SAAS,CAAC,CA0SrE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/di/container.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAkHrC;;;;;;GAMG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,SAAS,CAAC,CA8SrE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -77,6 +77,7 @@ import { DeleteRepositoryUseCase } from '../../application/use-cases/repositorie
77
77
  import { CheckAndUnblockFeaturesUseCase } from '../../application/use-cases/features/check-and-unblock-features.use-case.js';
78
78
  import { UpdateFeatureLifecycleUseCase } from '../../application/use-cases/features/update/update-feature-lifecycle.use-case.js';
79
79
  import { CleanupFeatureWorktreeUseCase } from '../../application/use-cases/features/cleanup-feature-worktree.use-case.js';
80
+ import { UpgradeCliUseCase } from '../../application/use-cases/upgrade/upgrade-cli.use-case.js';
80
81
  // Session listing
81
82
  import { ClaudeCodeSessionRepository } from '../services/agents/sessions/claude-code-session.repository.js';
82
83
  import { StubSessionRepository } from '../services/agents/sessions/stub-session.repository.js';
@@ -279,6 +280,7 @@ export async function initializeContainer() {
279
280
  container.registerSingleton(CheckAndUnblockFeaturesUseCase);
280
281
  container.registerSingleton(UpdateFeatureLifecycleUseCase);
281
282
  container.registerSingleton(CleanupFeatureWorktreeUseCase);
283
+ container.registerSingleton(UpgradeCliUseCase);
282
284
  // Session repositories (per-AgentType string tokens)
283
285
  container.register(`IAgentSessionRepository:${AgentType.ClaudeCode}`, {
284
286
  useFactory: () => new ClaudeCodeSessionRepository(),
@@ -360,6 +362,9 @@ export async function initializeContainer() {
360
362
  container.register('CleanupFeatureWorktreeUseCase', {
361
363
  useFactory: (c) => c.resolve(CleanupFeatureWorktreeUseCase),
362
364
  });
365
+ container.register('UpgradeCliUseCase', {
366
+ useFactory: (c) => c.resolve(UpgradeCliUseCase),
367
+ });
363
368
  _initialized = true;
364
369
  return container;
365
370
  }
@@ -1 +1 @@
1
- {"version":3,"file":"worktree.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/git/worktree.service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACb,MAAM,0EAA0E,CAAC;AAOlF;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEjD,qBACa,eAAgB,YAAW,gBAAgB;IAClB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,YAAY;IAErE,MAAM,CACV,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC;IAqBlB,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAW5D,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtC,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAO/C,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK1D,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWhE,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWtE,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmC1D,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAMzD,OAAO,CAAC,mBAAmB;IA2B3B,OAAO,CAAC,aAAa;IAgCrB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,qBAAqB;CAU9B"}
1
+ {"version":3,"file":"worktree.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/git/worktree.service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACb,MAAM,0EAA0E,CAAC;AAOlF;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEjD,qBACa,eAAgB,YAAW,gBAAgB;IAClB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,YAAY;IAErE,MAAM,CACV,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,CAAC;IAqBlB,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAW5D,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtC,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAO/C,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK1D,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWhE,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWtE,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqC1D,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAMzD,OAAO,CAAC,mBAAmB;IA2B3B,OAAO,CAAC,aAAa;IAgCrB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,qBAAqB;CAU9B"}
@@ -127,9 +127,7 @@ let WorktreeService = class WorktreeService {
127
127
  }
128
128
  await this.execFile('git', ['config', 'user.name', GIT_AUTO_INIT_USER], { cwd: repoPath });
129
129
  await this.execFile('git', ['config', 'user.email', GIT_AUTO_INIT_EMAIL], { cwd: repoPath });
130
- await this.execFile('git', ['commit', '--allow-empty', '-m', 'Initial commit'], {
131
- cwd: repoPath,
132
- });
130
+ await this.execFile('git', ['commit', '--allow-empty', '--no-gpg-sign', '-m', 'Initial commit'], { cwd: repoPath });
133
131
  }
134
132
  catch (error) {
135
133
  throw this.parseGitError(error);
@@ -19,7 +19,7 @@ export declare const symbols: {
19
19
  /** Warning triangle */
20
20
  readonly warning: "⚠" | "‼";
21
21
  /** Info circle */
22
- readonly info: "" | "i";
22
+ readonly info: "i" | "";
23
23
  /** Arrow/pointer */
24
24
  readonly arrow: "→" | "->";
25
25
  /** Bullet point */
@@ -0,0 +1,3 @@
1
+ export declare const dynamic = "force-dynamic";
2
+ export declare function POST(): Promise<Response>;
3
+ //# sourceMappingURL=route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/cli-upgrade/route.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAEvC,wBAAsB,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,CA+B9C"}
@@ -0,0 +1,31 @@
1
+ import { resolve } from '../../../lib/server-container.js';
2
+ // Force dynamic — SSE streams must never be statically optimized or cached
3
+ export const dynamic = 'force-dynamic';
4
+ export async function POST() {
5
+ const useCase = resolve('UpgradeCliUseCase');
6
+ const encoder = new TextEncoder();
7
+ const stream = new ReadableStream({
8
+ async start(controller) {
9
+ try {
10
+ const result = await useCase.execute((chunk) => {
11
+ controller.enqueue(encoder.encode(`data: ${chunk.replace(/\n/g, '\ndata: ')}\n\n`));
12
+ });
13
+ controller.enqueue(encoder.encode(`event: done\ndata: ${JSON.stringify(result)}\n\n`));
14
+ }
15
+ catch (error) {
16
+ const message = error instanceof Error ? error.message : 'Upgrade failed';
17
+ controller.enqueue(encoder.encode(`event: done\ndata: ${JSON.stringify({ status: 'error', currentVersion: '', latestVersion: null, errorMessage: message })}\n\n`));
18
+ }
19
+ finally {
20
+ controller.close();
21
+ }
22
+ },
23
+ });
24
+ return new Response(stream, {
25
+ headers: {
26
+ 'Content-Type': 'text/event-stream',
27
+ 'Cache-Control': 'no-cache',
28
+ Connection: 'keep-alive',
29
+ },
30
+ });
31
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"version-badge.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/version-badge/version-badge.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,MAAM,EACN,UAAU,EACV,KAAa,EACb,WAA2B,EAC3B,WAAW,EACX,YAAY,GACb,EAAE,iBAAiB,2CAyDnB"}
1
+ {"version":3,"file":"version-badge.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/version-badge/version-badge.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,MAAM,EACN,UAAU,EACV,KAAa,EACb,WAA2B,EAC3B,WAAW,EACX,YAAY,GACb,EAAE,iBAAiB,2CA2EnB"}
@@ -2,13 +2,17 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
4
4
  import { useNpmVersionCheck } from '../../../hooks/use-npm-version-check.js';
5
+ import { useCliUpgrade } from '../../../hooks/use-cli-upgrade.js';
5
6
  export function VersionBadge({ version, branch, commitHash, isDev = false, packageName = '@shepai/cli', description, instancePath, }) {
6
7
  const shortHash = commitHash?.slice(0, 7);
7
8
  const { latest, updateAvailable } = useNpmVersionCheck(version);
9
+ const { status: upgradeStatus, startUpgrade } = useCliUpgrade();
8
10
  // In dev mode show "1.92.2-dev", in production show "v1.92.2"
9
11
  const displayVersion = isDev ? `${version}-dev` : `v${version}`;
10
- const npmUrl = `https://www.npmjs.com/package/${packageName}`;
11
- return (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("span", { className: "text-muted-foreground/80 hover:text-muted-foreground relative cursor-default text-[11px] leading-tight transition-colors", "data-testid": "version-label", children: [displayVersion, updateAvailable ? (_jsx("span", { className: "absolute -top-0.5 -right-1.5 size-1.5 rounded-full bg-emerald-400", "data-testid": "update-dot" })) : null] }) }), _jsxs(TooltipContent, { side: "right", className: "max-w-[280px] space-y-1 p-3 text-left", children: [_jsx("div", { className: "mb-1.5 text-xs font-semibold", children: packageName }), description ? (_jsx("div", { className: "text-[10px] leading-snug opacity-70", children: description })) : null, _jsxs("div", { className: "border-t border-white/10 pt-1.5", children: [_jsx(Row, { label: "Version", value: displayVersion }), isDev && branch ? _jsx(Row, { label: "Branch", value: branch }) : null, isDev && shortHash ? _jsx(Row, { label: "Commit", value: shortHash, mono: true }) : null, isDev && instancePath ? _jsx(Row, { label: "Path", value: instancePath, mono: true }) : null, latest ? (_jsx(Row, { label: "Latest", value: `v${latest}`, highlight: updateAvailable })) : null] }), updateAvailable ? (_jsx("div", { className: "border-t border-white/10 pt-1.5", children: _jsxs("a", { href: npmUrl, target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center gap-1 text-[10px] font-medium text-emerald-400 transition-colors hover:text-emerald-300", "data-testid": "upgrade-link", children: ["Upgrade to v", latest, " \u2192"] }) })) : null] })] }) }));
12
+ const isUpgrading = upgradeStatus === 'upgrading';
13
+ const didUpgrade = upgradeStatus === 'upgraded';
14
+ const upgradeError = upgradeStatus === 'error';
15
+ return (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("span", { className: "text-muted-foreground/80 hover:text-muted-foreground relative cursor-default text-[11px] leading-tight transition-colors", "data-testid": "version-label", children: [displayVersion, updateAvailable && !didUpgrade ? (_jsx("span", { className: "absolute -top-0.5 -right-1.5 size-1.5 rounded-full bg-emerald-400", "data-testid": "update-dot" })) : null] }) }), _jsxs(TooltipContent, { side: "right", className: "max-w-[280px] space-y-1 p-3 text-left", children: [_jsx("div", { className: "mb-1.5 text-xs font-semibold", children: packageName }), description ? (_jsx("div", { className: "text-[10px] leading-snug opacity-70", children: description })) : null, _jsxs("div", { className: "border-t border-white/10 pt-1.5", children: [_jsx(Row, { label: "Version", value: displayVersion }), isDev && branch ? _jsx(Row, { label: "Branch", value: branch }) : null, isDev && shortHash ? _jsx(Row, { label: "Commit", value: shortHash, mono: true }) : null, isDev && instancePath ? _jsx(Row, { label: "Path", value: instancePath, mono: true }) : null, latest ? (_jsx(Row, { label: "Latest", value: `v${latest}`, highlight: updateAvailable })) : null] }), didUpgrade ? (_jsx("div", { className: "border-t border-white/10 pt-1.5", children: _jsx("span", { className: "text-[10px] font-medium text-emerald-400", "data-testid": "upgrade-success", children: "Upgraded successfully \u2014 restart to apply" }) })) : upgradeError ? (_jsx("div", { className: "border-t border-white/10 pt-1.5", children: _jsx("span", { className: "text-[10px] font-medium text-red-400", "data-testid": "upgrade-error", children: "Upgrade failed" }) })) : updateAvailable ? (_jsx("div", { className: "border-t border-white/10 pt-1.5", children: _jsx("button", { type: "button", onClick: startUpgrade, disabled: isUpgrading, className: "inline-flex items-center gap-1 text-[10px] font-medium text-emerald-400 transition-colors hover:text-emerald-300 disabled:opacity-50", "data-testid": "upgrade-button", children: isUpgrading ? 'Upgrading...' : `Upgrade to v${latest}` }) })) : null] })] }) }));
12
16
  }
13
17
  function Row({ label, value, highlight, mono, }) {
14
18
  return (_jsxs("div", { className: "flex items-center justify-between gap-4 text-[10px]", children: [_jsx("span", { className: "opacity-60", children: label }), _jsx("span", { className: [
@@ -11,9 +11,9 @@ export declare const Development: Story;
11
11
  export declare const LongBranch: Story;
12
12
  /** Minimal info — no optional fields. */
13
13
  export declare const Minimal: Story;
14
- /** Update available — green dot appears, tooltip shows "Upgrade to v2.0.0" link. */
14
+ /** Update available — green dot appears, tooltip shows "Upgrade to v2.0.0" button. */
15
15
  export declare const UpdateAvailable: Story;
16
- /** Update available in dev mode — green dot + upgrade link alongside dev info. */
16
+ /** Update available in dev mode — green dot + upgrade button alongside dev info. */
17
17
  export declare const UpdateAvailableDev: Story;
18
18
  /** Fetch error — no update info shown, badge behaves normally. */
19
19
  export declare const FetchError: Story;
@@ -1 +1 @@
1
- {"version":3,"file":"version-badge.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/version-badge/version-badge.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAa,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAmC/C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,YAAY,CAOnC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,YAAY,CAAC,CAAC;AAE3C,mFAAmF;AACnF,eAAO,MAAM,UAAU,EAAE,KAOxB,CAAC;AAEF,wFAAwF;AACxF,eAAO,MAAM,WAAW,EAAE,KAWzB,CAAC;AAEF,mEAAmE;AACnE,eAAO,MAAM,UAAU,EAAE,KAWxB,CAAC;AAEF,yCAAyC;AACzC,eAAO,MAAM,OAAO,EAAE,KAKrB,CAAC;AAEF,oFAAoF;AACpF,eAAO,MAAM,eAAe,EAAE,KAO7B,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,EAAE,KAWhC,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,UAAU,EAAE,KAOxB,CAAC"}
1
+ {"version":3,"file":"version-badge.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/version-badge/version-badge.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAa,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAwD/C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,YAAY,CAOnC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,YAAY,CAAC,CAAC;AAE3C,mFAAmF;AACnF,eAAO,MAAM,UAAU,EAAE,KAOxB,CAAC;AAEF,wFAAwF;AACxF,eAAO,MAAM,WAAW,EAAE,KAWzB,CAAC;AAEF,mEAAmE;AACnE,eAAO,MAAM,UAAU,EAAE,KAWxB,CAAC;AAEF,yCAAyC;AACzC,eAAO,MAAM,OAAO,EAAE,KAKrB,CAAC;AAEF,sFAAsF;AACtF,eAAO,MAAM,eAAe,EAAE,KAO7B,CAAC;AAEF,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,EAAE,KAWhC,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,UAAU,EAAE,KAOxB,CAAC"}
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { VersionBadge } from './version-badge.js';
3
3
  /**
4
- * Decorator that mocks the /api/npm-version endpoint to return a specific latest version.
4
+ * Decorator that mocks the /api/npm-version endpoint to return a specific latest version
5
+ * and the /api/cli-upgrade endpoint to simulate an upgrade.
5
6
  */
6
7
  function withNpmVersion(latest) {
7
8
  return (Story) => {
@@ -14,6 +15,22 @@ function withNpmVersion(latest) {
14
15
  headers: { 'Content-Type': 'application/json' },
15
16
  });
16
17
  }
18
+ if (url.includes('/api/cli-upgrade')) {
19
+ const encoder = new TextEncoder();
20
+ const stream = new ReadableStream({
21
+ start(controller) {
22
+ controller.enqueue(encoder.encode(`data: Upgrading to v${latest}...\n\n`));
23
+ setTimeout(() => {
24
+ controller.enqueue(encoder.encode(`event: done\ndata: ${JSON.stringify({ status: 'upgraded', currentVersion: '1.90.0', latestVersion: latest })}\n\n`));
25
+ controller.close();
26
+ }, 1000);
27
+ },
28
+ });
29
+ return new Response(stream, {
30
+ status: 200,
31
+ headers: { 'Content-Type': 'text/event-stream' },
32
+ });
33
+ }
17
34
  return originalFetch(input, init);
18
35
  });
19
36
  return _jsx(Story, {});
@@ -82,7 +99,7 @@ export const Minimal = {
82
99
  version: '1.0.0',
83
100
  },
84
101
  };
85
- /** Update available — green dot appears, tooltip shows "Upgrade to v2.0.0" link. */
102
+ /** Update available — green dot appears, tooltip shows "Upgrade to v2.0.0" button. */
86
103
  export const UpdateAvailable = {
87
104
  decorators: [withNpmVersion('2.0.0')],
88
105
  args: {
@@ -91,7 +108,7 @@ export const UpdateAvailable = {
91
108
  description: 'Autonomous AI Native SDLC Platform',
92
109
  },
93
110
  };
94
- /** Update available in dev mode — green dot + upgrade link alongside dev info. */
111
+ /** Update available in dev mode — green dot + upgrade button alongside dev info. */
95
112
  export const UpdateAvailableDev = {
96
113
  decorators: [withNpmVersion('2.0.0')],
97
114
  args: {
@@ -0,0 +1,11 @@
1
+ export type UpgradeStatus = 'idle' | 'upgrading' | 'upgraded' | 'up-to-date' | 'error';
2
+ export interface CliUpgradeState {
3
+ status: UpgradeStatus;
4
+ output: string;
5
+ errorMessage?: string;
6
+ }
7
+ export interface CliUpgradeActions {
8
+ startUpgrade: () => void;
9
+ }
10
+ export declare function useCliUpgrade(): CliUpgradeState & CliUpgradeActions;
11
+ //# sourceMappingURL=use-cli-upgrade.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-cli-upgrade.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-cli-upgrade.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,OAAO,CAAC;AAEvF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,wBAAgB,aAAa,IAAI,eAAe,GAAG,iBAAiB,CA6EnE"}
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+ import { useCallback, useRef, useState } from 'react';
3
+ export function useCliUpgrade() {
4
+ const [status, setStatus] = useState('idle');
5
+ const [output, setOutput] = useState('');
6
+ const [errorMessage, setErrorMessage] = useState();
7
+ const abortRef = useRef(null);
8
+ const startUpgrade = useCallback(() => {
9
+ if (status === 'upgrading')
10
+ return;
11
+ setStatus('upgrading');
12
+ setOutput('');
13
+ setErrorMessage(undefined);
14
+ const controller = new AbortController();
15
+ abortRef.current = controller;
16
+ fetch('/api/cli-upgrade', { method: 'POST', signal: controller.signal })
17
+ .then(async (response) => {
18
+ if (!response.ok || !response.body) {
19
+ setStatus('error');
20
+ setErrorMessage(`Server returned ${response.status}`);
21
+ return;
22
+ }
23
+ const reader = response.body.getReader();
24
+ const decoder = new TextDecoder();
25
+ let buffer = '';
26
+ while (true) {
27
+ const { done, value } = await reader.read();
28
+ if (done)
29
+ break;
30
+ buffer += decoder.decode(value, { stream: true });
31
+ const lines = buffer.split('\n');
32
+ buffer = lines.pop() ?? '';
33
+ for (const line of lines) {
34
+ if (line.startsWith('event: done')) {
35
+ // Next data line contains the final result
36
+ continue;
37
+ }
38
+ if (line.startsWith('data: ')) {
39
+ const payload = line.slice(6);
40
+ // Try to parse as final JSON result
41
+ try {
42
+ const result = JSON.parse(payload);
43
+ if (result.status === 'upgraded') {
44
+ setStatus('upgraded');
45
+ }
46
+ else if (result.status === 'up-to-date') {
47
+ setStatus('up-to-date');
48
+ }
49
+ else if (result.status === 'error') {
50
+ setStatus('error');
51
+ setErrorMessage(result.errorMessage);
52
+ }
53
+ }
54
+ catch {
55
+ // Regular output line
56
+ setOutput((prev) => prev + payload);
57
+ }
58
+ }
59
+ }
60
+ }
61
+ })
62
+ .catch((err) => {
63
+ if (err instanceof DOMException && err.name === 'AbortError')
64
+ return;
65
+ setStatus('error');
66
+ setErrorMessage(err instanceof Error ? err.message : 'Upgrade failed');
67
+ });
68
+ return () => {
69
+ controller.abort();
70
+ };
71
+ }, [status]);
72
+ return { status, output, errorMessage, startUpgrade };
73
+ }