@shepai/cli 1.103.1-pr297.1d67d7d → 1.103.1-pr309.f0bca17

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 (188) 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/src/presentation/cli/ui/symbols.d.ts +1 -1
  7. package/dist/src/presentation/web/app/api/cli-upgrade/route.d.ts +3 -0
  8. package/dist/src/presentation/web/app/api/cli-upgrade/route.d.ts.map +1 -0
  9. package/dist/src/presentation/web/app/api/cli-upgrade/route.js +31 -0
  10. package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.d.ts +5 -0
  11. package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.d.ts.map +1 -0
  12. package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.js +113 -0
  13. package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.stories.d.ts +18 -0
  14. package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.stories.d.ts.map +1 -0
  15. package/dist/src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.stories.js +88 -0
  16. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.d.ts.map +1 -1
  17. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.js +10 -2
  18. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.d.ts +5 -3
  19. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.d.ts.map +1 -1
  20. package/dist/src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.js +92 -9
  21. package/dist/src/presentation/web/components/common/version-badge/version-badge.d.ts.map +1 -1
  22. package/dist/src/presentation/web/components/common/version-badge/version-badge.js +6 -2
  23. package/dist/src/presentation/web/components/common/version-badge/version-badge.stories.d.ts +2 -2
  24. package/dist/src/presentation/web/components/common/version-badge/version-badge.stories.d.ts.map +1 -1
  25. package/dist/src/presentation/web/components/common/version-badge/version-badge.stories.js +20 -3
  26. package/dist/src/presentation/web/hooks/use-cli-upgrade.d.ts +11 -0
  27. package/dist/src/presentation/web/hooks/use-cli-upgrade.d.ts.map +1 -0
  28. package/dist/src/presentation/web/hooks/use-cli-upgrade.js +73 -0
  29. package/dist/src/presentation/web/lib/parse-log-line.d.ts +49 -0
  30. package/dist/src/presentation/web/lib/parse-log-line.d.ts.map +1 -0
  31. package/dist/src/presentation/web/lib/parse-log-line.js +126 -0
  32. package/dist/tsconfig.build.tsbuildinfo +1 -1
  33. package/package.json +1 -1
  34. package/web/.next/BUILD_ID +1 -1
  35. package/web/.next/app-path-routes-manifest.json +1 -0
  36. package/web/.next/build-manifest.json +2 -2
  37. package/web/.next/fallback-build-manifest.json +2 -2
  38. package/web/.next/prerender-manifest.json +3 -3
  39. package/web/.next/required-server-files.js +1 -1
  40. package/web/.next/required-server-files.json +1 -1
  41. package/web/.next/routes-manifest.json +6 -0
  42. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +20 -20
  43. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  44. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  45. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +25 -25
  46. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  47. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  48. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +25 -25
  49. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  50. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  51. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
  52. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  53. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  54. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +20 -20
  55. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  56. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  57. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +25 -25
  58. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  59. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  60. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +25 -25
  61. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  62. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  63. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +18 -18
  64. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  65. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  66. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
  67. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  68. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  69. package/web/.next/server/app/_global-error.html +2 -2
  70. package/web/.next/server/app/_global-error.rsc +1 -1
  71. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  72. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  73. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  74. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  75. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  76. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  77. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  78. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  79. package/web/.next/server/app/api/cli-upgrade/route/app-paths-manifest.json +3 -0
  80. package/web/.next/server/app/api/cli-upgrade/route/build-manifest.json +11 -0
  81. package/web/.next/server/app/api/cli-upgrade/route/server-reference-manifest.json +4 -0
  82. package/web/.next/server/app/api/cli-upgrade/route.js +6 -0
  83. package/web/.next/server/app/api/cli-upgrade/route.js.map +5 -0
  84. package/web/.next/server/app/api/cli-upgrade/route.js.nft.json +1 -0
  85. package/web/.next/server/app/api/cli-upgrade/route_client-reference-manifest.js +2 -0
  86. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  87. package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
  88. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  89. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  90. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  91. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  92. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  93. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  94. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  95. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  96. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  97. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  98. package/web/.next/server/app-paths-manifest.json +1 -0
  99. package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_cli-upgrade_route_actions_dc509b52.js +3 -0
  100. package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_cli-upgrade_route_actions_dc509b52.js.map +1 -0
  101. package/web/.next/server/chunks/[root-of-the-server]__d2c18946._.js +11 -0
  102. package/web/.next/server/chunks/[root-of-the-server]__d2c18946._.js.map +1 -0
  103. package/web/.next/server/chunks/[root-of-the-server]__f47bb8a5._.js +1 -1
  104. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  105. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  106. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_0a7546ed.js +1 -1
  107. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_0a7546ed.js.map +1 -1
  108. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_978cbb4c.js +1 -1
  109. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_978cbb4c.js.map +1 -1
  110. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
  111. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
  112. package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +2 -2
  113. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  114. package/web/.next/server/chunks/ssr/[root-of-the-server]__51fc98b0._.js +1 -1
  115. package/web/.next/server/chunks/ssr/[root-of-the-server]__51fc98b0._.js.map +1 -1
  116. package/web/.next/server/chunks/ssr/[root-of-the-server]__57f37786._.js +1 -1
  117. package/web/.next/server/chunks/ssr/[root-of-the-server]__57f37786._.js.map +1 -1
  118. package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
  119. package/web/.next/server/chunks/ssr/[root-of-the-server]__708dcad1._.js +1 -1
  120. package/web/.next/server/chunks/ssr/[root-of-the-server]__708dcad1._.js.map +1 -1
  121. package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js +1 -1
  122. package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js.map +1 -1
  123. package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js +2 -2
  124. package/web/.next/server/chunks/ssr/[root-of-the-server]__8e002910._.js +1 -1
  125. package/web/.next/server/chunks/ssr/[root-of-the-server]__8e002910._.js.map +1 -1
  126. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
  127. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  128. package/web/.next/server/chunks/ssr/[root-of-the-server]__b1e68e34._.js +3 -0
  129. package/web/.next/server/chunks/ssr/{[root-of-the-server]__d91fdd51._.js.map → [root-of-the-server]__b1e68e34._.js.map} +1 -1
  130. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
  131. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
  132. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  133. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  134. package/web/.next/server/chunks/ssr/{_80fc856a._.js → _299324d0._.js} +2 -2
  135. package/web/.next/server/chunks/ssr/{_80fc856a._.js.map → _299324d0._.js.map} +1 -1
  136. package/web/.next/server/chunks/ssr/{_7129cff0._.js → _601a084c._.js} +2 -2
  137. package/web/.next/server/chunks/ssr/{_7129cff0._.js.map → _601a084c._.js.map} +1 -1
  138. package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
  139. package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
  140. package/web/.next/server/chunks/ssr/{_2381749d._.js → _c205e198._.js} +2 -2
  141. package/web/.next/server/chunks/ssr/{_2381749d._.js.map → _c205e198._.js.map} +1 -1
  142. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  143. package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
  144. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  145. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  146. package/web/.next/server/chunks/ssr/src_presentation_web_7275ce5d._.js +2 -2
  147. package/web/.next/server/chunks/ssr/src_presentation_web_7275ce5d._.js.map +1 -1
  148. package/web/.next/server/chunks/ssr/src_presentation_web_758dfa10._.js +2 -2
  149. package/web/.next/server/chunks/ssr/src_presentation_web_758dfa10._.js.map +1 -1
  150. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_84803221.js +1 -1
  151. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_84803221.js.map +1 -1
  152. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  153. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  154. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  155. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  156. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
  157. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js.map +1 -1
  158. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
  159. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js.map +1 -1
  160. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  161. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  162. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  163. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  164. package/web/.next/server/pages/500.html +2 -2
  165. package/web/.next/server/server-reference-manifest.js +1 -1
  166. package/web/.next/server/server-reference-manifest.json +30 -30
  167. package/web/.next/static/chunks/{deb64031250a421f.js → 09fe794bed5a0077.js} +1 -1
  168. package/web/.next/static/chunks/{e1199a4481977a1d.js → 20f5682099fbb10c.js} +1 -1
  169. package/web/.next/static/chunks/{074f5910ba53b9a9.js → 2a63561f9716d615.js} +1 -1
  170. package/web/.next/static/chunks/3bb35e0689e8b6b7.js +1 -0
  171. package/web/.next/static/chunks/3bba99704fc1d30c.js +1 -0
  172. package/web/.next/static/chunks/3fa3006034a0add8.css +1 -0
  173. package/web/.next/static/chunks/{f2d47cc7f90ea785.js → 47387a05a4f0f22b.js} +1 -1
  174. package/web/.next/static/chunks/{03dca61cab65a6d6.js → 4873b5f96cfdffb9.js} +1 -1
  175. package/web/.next/static/chunks/{dbf1dbf895bb3b2b.js → 8c4731c87b599597.js} +1 -1
  176. package/web/.next/static/chunks/{77a6011b9ecff04e.js → 994e46e475fb78f9.js} +2 -2
  177. package/web/.next/static/chunks/a8eceddc883b57bb.js +1 -0
  178. package/web/.next/static/chunks/b1f3c0e8e9872ef8.js +1 -0
  179. package/web/.next/static/chunks/{3df97cf6d9bb267d.js → e7abc4f19da20094.js} +1 -1
  180. package/web/.next/server/chunks/ssr/[root-of-the-server]__d91fdd51._.js +0 -3
  181. package/web/.next/static/chunks/07b853e29af1e5f2.js +0 -1
  182. package/web/.next/static/chunks/2a6f05312c4f37ce.js +0 -1
  183. package/web/.next/static/chunks/93058c22968e2fef.css +0 -1
  184. package/web/.next/static/chunks/c38c8ef1091abf1b.js +0 -1
  185. package/web/.next/static/chunks/d6d49d0239bf3f10.js +0 -1
  186. /package/web/.next/static/{8bFxxZyznRJ9YrunDv0xj → vSr396p_Rdr92qmX9fzqd}/_buildManifest.js +0 -0
  187. /package/web/.next/static/{8bFxxZyznRJ9YrunDv0xj → vSr396p_Rdr92qmX9fzqd}/_clientMiddlewareManifest.json +0 -0
  188. /package/web/.next/static/{8bFxxZyznRJ9YrunDv0xj → vSr396p_Rdr92qmX9fzqd}/_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
  }
@@ -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
+ }
@@ -0,0 +1,5 @@
1
+ export interface EventLogViewerProps {
2
+ content: string;
3
+ }
4
+ export declare function EventLogViewer({ content }: EventLogViewerProps): import("react/jsx-runtime").JSX.Element | null;
5
+ //# sourceMappingURL=event-log-viewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-log-viewer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.tsx"],"names":[],"mappings":"AAwBA,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,EAAE,mBAAmB,kDAY9D"}
@@ -0,0 +1,113 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useMemo } from 'react';
4
+ import { FileText, Terminal, MessageSquare, CheckCircle2, Coins, Server, FileCode, } from 'lucide-react';
5
+ import { parseLogContent, parseToolCall, parseResultMessage, parseTokensMessage, } from '../../../lib/parse-log-line.js';
6
+ export function EventLogViewer({ content }) {
7
+ const lines = useMemo(() => parseLogContent(content), [content]);
8
+ if (lines.length === 0)
9
+ return null;
10
+ return (_jsx("div", { className: "flex flex-col", children: lines.map((line) => (_jsx(LogLineRow, { line: line }, line.raw))) }));
11
+ }
12
+ /* ---------------------------------------------------------------------------
13
+ * Line router
14
+ * ------------------------------------------------------------------------- */
15
+ function LogLineRow({ line }) {
16
+ switch (line.tag) {
17
+ case 'tool':
18
+ return _jsx(ToolCallRow, { line: line });
19
+ case 'text':
20
+ return _jsx(TextRow, { line: line });
21
+ case 'result':
22
+ return _jsx(ResultRow, { line: line });
23
+ case 'tokens':
24
+ return _jsx(TokensRow, { line: line });
25
+ case 'worker':
26
+ return _jsx(WorkerRow, { line: line });
27
+ case 'info':
28
+ return _jsx(InfoRow, { line: line });
29
+ case 'raw':
30
+ default:
31
+ return _jsx(RawRow, { line: line });
32
+ }
33
+ }
34
+ /* ---------------------------------------------------------------------------
35
+ * Shared helpers
36
+ * ------------------------------------------------------------------------- */
37
+ function Timestamp({ value }) {
38
+ if (!value)
39
+ return null;
40
+ const time = value.replace(/^.*T/, '').replace('Z', '');
41
+ return (_jsx("span", { className: "text-muted-foreground/60 w-20 shrink-0 font-mono text-[10px]", children: time }));
42
+ }
43
+ function PhaseBadge({ phase }) {
44
+ if (!phase)
45
+ return null;
46
+ return (_jsx("span", { className: "bg-muted text-muted-foreground shrink-0 rounded px-1.5 py-0.5 font-mono text-[10px] font-medium", children: phase }));
47
+ }
48
+ /* ---------------------------------------------------------------------------
49
+ * Event-specific rows
50
+ * ------------------------------------------------------------------------- */
51
+ function ToolCallRow({ line }) {
52
+ const { toolName, args } = parseToolCall(line.message);
53
+ // Try to extract a key detail from args for common tools
54
+ const detail = getToolDetail(toolName, args);
55
+ return (_jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-2 border-b border-transparent px-3 py-1.5 transition-colors", children: [_jsx(Timestamp, { value: line.timestamp }), _jsx(PhaseBadge, { phase: line.phase }), _jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-1.5", children: [_jsx(ToolIcon, { toolName: toolName }), _jsx("span", { className: "text-xs font-semibold text-violet-600 dark:text-violet-400", children: toolName }), detail ? (_jsx("span", { className: "text-muted-foreground min-w-0 truncate font-mono text-xs", children: detail })) : null] })] }));
56
+ }
57
+ function ToolIcon({ toolName }) {
58
+ const lower = toolName.toLowerCase();
59
+ if (lower === 'bash')
60
+ return _jsx(Terminal, { className: "mt-0.5 h-3 w-3 shrink-0 text-violet-500" });
61
+ if (lower === 'read' || lower === 'glob' || lower === 'grep')
62
+ return _jsx(FileText, { className: "mt-0.5 h-3 w-3 shrink-0 text-violet-500" });
63
+ if (lower === 'write' || lower === 'edit')
64
+ return _jsx(FileCode, { className: "mt-0.5 h-3 w-3 shrink-0 text-violet-500" });
65
+ return _jsx(Terminal, { className: "mt-0.5 h-3 w-3 shrink-0 text-violet-500" });
66
+ }
67
+ function getToolDetail(toolName, args) {
68
+ try {
69
+ const parsed = JSON.parse(args);
70
+ if (toolName === 'Read' && parsed.file_path)
71
+ return parsed.file_path;
72
+ if (toolName === 'Write' && parsed.file_path)
73
+ return parsed.file_path;
74
+ if (toolName === 'Edit' && parsed.file_path)
75
+ return parsed.file_path;
76
+ if (toolName === 'Glob' && parsed.pattern)
77
+ return parsed.pattern;
78
+ if (toolName === 'Grep' && parsed.pattern)
79
+ return parsed.pattern;
80
+ if (toolName === 'Bash' && parsed.command) {
81
+ const cmd = parsed.command;
82
+ return cmd.length > 80 ? `${cmd.slice(0, 80)}...` : cmd;
83
+ }
84
+ if (toolName === 'Task' && parsed.description)
85
+ return parsed.description;
86
+ }
87
+ catch {
88
+ // Not JSON — show truncated raw args
89
+ if (args.length > 0)
90
+ return args.length > 80 ? `${args.slice(0, 80)}...` : args;
91
+ }
92
+ return null;
93
+ }
94
+ function TextRow({ line }) {
95
+ return (_jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-2 px-3 py-1.5 transition-colors", children: [_jsx(Timestamp, { value: line.timestamp }), _jsx(PhaseBadge, { phase: line.phase }), _jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-1.5", children: [_jsx(MessageSquare, { className: "mt-0.5 h-3 w-3 shrink-0 text-blue-500" }), _jsx("span", { className: "text-foreground/80 min-w-0 text-xs leading-relaxed", children: line.message })] })] }));
96
+ }
97
+ function ResultRow({ line }) {
98
+ const { chars } = parseResultMessage(line.message);
99
+ return (_jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-2 px-3 py-1.5 transition-colors", children: [_jsx(Timestamp, { value: line.timestamp }), _jsx(PhaseBadge, { phase: line.phase }), _jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-1.5", children: [_jsx(CheckCircle2, { className: "mt-0.5 h-3 w-3 shrink-0 text-emerald-500" }), _jsxs("span", { className: "text-xs font-medium text-emerald-600 dark:text-emerald-400", children: ["Result: ", chars.toLocaleString(), " chars"] })] })] }));
100
+ }
101
+ function TokensRow({ line }) {
102
+ const { inputTokens, outputTokens } = parseTokensMessage(line.message);
103
+ return (_jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-2 px-3 py-1.5 transition-colors", children: [_jsx(Timestamp, { value: line.timestamp }), _jsx(PhaseBadge, { phase: line.phase }), _jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-1.5", children: [_jsx(Coins, { className: "mt-0.5 h-3 w-3 shrink-0 text-amber-500" }), _jsxs("span", { className: "text-muted-foreground text-xs", children: [_jsx("span", { className: "text-amber-600 dark:text-amber-400", children: inputTokens.toLocaleString() }), ' in / ', _jsx("span", { className: "text-amber-600 dark:text-amber-400", children: outputTokens.toLocaleString() }), ' out'] })] })] }));
104
+ }
105
+ function WorkerRow({ line }) {
106
+ return (_jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-2 bg-zinc-50 px-3 py-1.5 transition-colors dark:bg-zinc-900/50", children: [_jsx(Timestamp, { value: line.timestamp }), _jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-1.5", children: [_jsx(Server, { className: "mt-0.5 h-3 w-3 shrink-0 text-zinc-500" }), _jsx("span", { className: "text-muted-foreground text-xs font-medium", children: line.message })] })] }));
107
+ }
108
+ function InfoRow({ line }) {
109
+ return (_jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-2 px-3 py-1.5 transition-colors", children: [_jsx(Timestamp, { value: line.timestamp }), _jsx(PhaseBadge, { phase: line.phase }), _jsx("span", { className: "text-muted-foreground min-w-0 text-xs", children: line.message })] }));
110
+ }
111
+ function RawRow({ line }) {
112
+ return (_jsx("div", { className: "px-3 py-0.5", children: _jsx("span", { className: "text-muted-foreground/70 font-mono text-[11px] break-all whitespace-pre-wrap", children: line.raw }) }));
113
+ }
@@ -0,0 +1,18 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { EventLogViewer } from './event-log-viewer.js';
3
+ declare const meta: Meta<typeof EventLogViewer>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof EventLogViewer>;
6
+ /** ToolCalls — various tool call types */
7
+ export declare const ToolCalls: Story;
8
+ /** TextMessages — agent thinking/analysis */
9
+ export declare const TextMessages: Story;
10
+ /** WorkerLifecycle — worker bootstrap and shutdown */
11
+ export declare const WorkerLifecycle: Story;
12
+ /** ResultsAndTokens — completion summaries */
13
+ export declare const ResultsAndTokens: Story;
14
+ /** MixedContent — all event types including raw fallback */
15
+ export declare const MixedContent: Story;
16
+ /** EmptyContent — no content */
17
+ export declare const EmptyContent: Story;
18
+ //# sourceMappingURL=event-log-viewer.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-log-viewer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/event-log-viewer.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,cAAc,CAqBrC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,cAAc,CAAC,CAAC;AAsD7C,0CAA0C;AAC1C,eAAO,MAAM,SAAS,EAAE,KAEvB,CAAC;AAEF,6CAA6C;AAC7C,eAAO,MAAM,YAAY,EAAE,KAE1B,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,eAAe,EAAE,KAE7B,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,gBAAgB,EAAE,KAE9B,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,YAAY,EAAE,KAE1B,CAAC;AAEF,gCAAgC;AAChC,eAAO,MAAM,YAAY,EAAE,KAE1B,CAAC"}
@@ -0,0 +1,88 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { EventLogViewer } from './event-log-viewer.js';
3
+ const meta = {
4
+ title: 'Drawers/Feature/Tabs/EventLogViewer',
5
+ component: EventLogViewer,
6
+ tags: ['autodocs'],
7
+ parameters: {
8
+ layout: 'fullscreen',
9
+ },
10
+ decorators: [
11
+ (Story) => (_jsx("div", { style: {
12
+ height: '600px',
13
+ width: '480px',
14
+ border: '1px solid var(--color-border)',
15
+ overflow: 'auto',
16
+ }, children: _jsx(Story, {}) })),
17
+ ],
18
+ };
19
+ export default meta;
20
+ /* ---------------------------------------------------------------------------
21
+ * Fixtures
22
+ * ------------------------------------------------------------------------- */
23
+ const toolEvents = `[2026-03-08T10:00:08.234Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Read {"file_path": "src/main.ts"}
24
+ [2026-03-08T10:00:10.345Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Glob {"pattern": "src/**/*.ts"}
25
+ [2026-03-08T10:00:12.567Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Grep {"pattern": "interface.*Auth", "path": "src/"}
26
+ [2026-03-08T10:00:14.789Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Bash {"command": "find src -name '*.test.ts' | wc -l"}
27
+ [2026-03-08T10:00:16.012Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Write {"file_path": "src/auth/oauth-provider.ts"}
28
+ [2026-03-08T10:00:18.234Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Edit {"file_path": "src/auth/index.ts"}
29
+ [2026-03-08T10:00:20.456Z] [implement] [claude-code|claude-sonnet-4-6] [tool] Task {"description": "Run integration tests"}`;
30
+ const textEvents = `[2026-03-08T10:00:10.345Z] [requirements] [claude-code|claude-sonnet-4-6] [text] Analyzing the codebase structure and identifying key entry points for the authentication module
31
+ [2026-03-08T10:00:18.234Z] [requirements] [claude-code|claude-sonnet-4-6] [text] The project uses a clean architecture pattern with dependency injection
32
+ [2026-03-08T10:02:38.200Z] [plan] [claude-code|claude-sonnet-4-6] [text] Creating implementation plan with TDD approach as required by project conventions
33
+ [2026-03-08T10:05:30.000Z] [implement] [claude-code|claude-sonnet-4-6] [text] All 14 unit tests passing. Moving to integration tests`;
34
+ const workerEvents = `[2026-03-08T10:00:01.000Z] [claude-code|claude-sonnet-4-6] [WORKER] Starting worker — full command:
35
+ [2026-03-08T10:00:01.001Z] [claude-code|claude-sonnet-4-6] [WORKER] feature-agent-worker --feature-id auth-module --run-id run-123
36
+ [2026-03-08T10:00:01.010Z] [claude-code|claude-sonnet-4-6] [WORKER] Initializing container...
37
+ [2026-03-08T10:00:01.050Z] [claude-code|claude-sonnet-4-6] [WORKER] Creating executor from pinned agent type: claude-code
38
+ [2026-03-08T10:00:01.100Z] [claude-code|claude-sonnet-4-6] [WORKER] Updating status to running (PID 54321)...
39
+ [2026-03-08T10:06:00.000Z] [claude-code|claude-sonnet-4-6] [WORKER] Graph invocation completed. Error: none
40
+ [2026-03-08T10:06:00.100Z] [claude-code|claude-sonnet-4-6] [WORKER] Run marked as completed
41
+ [2026-03-08T10:06:00.200Z] [claude-code|claude-sonnet-4-6] [WORKER] Worker completed successfully, exiting.`;
42
+ const resultAndTokenEvents = `[2026-03-08T10:00:45.789Z] [requirements] [claude-code|claude-sonnet-4-6] [result] 8920 chars, session=sess-abc123def456
43
+ [2026-03-08T10:00:45.790Z] [requirements] [claude-code|claude-sonnet-4-6] [tokens] 2450 in / 4560 out
44
+ [2026-03-08T10:03:15.234Z] [plan] [claude-code|claude-sonnet-4-6] [result] 12345 chars, session=sess-abc123def456
45
+ [2026-03-08T10:03:15.235Z] [plan] [claude-code|claude-sonnet-4-6] [tokens] 8900 in / 3456 out
46
+ [2026-03-08T10:05:55.000Z] [implement] [claude-code|claude-sonnet-4-6] [result] 24560 chars, session=sess-abc123def456
47
+ [2026-03-08T10:05:55.001Z] [implement] [claude-code|claude-sonnet-4-6] [tokens] 15200 in / 9360 out`;
48
+ const mixedContent = `[2026-03-08T10:00:01.000Z] [claude-code|claude-sonnet-4-6] [WORKER] Starting worker — full command:
49
+ [2026-03-08T10:00:01.010Z] [claude-code|claude-sonnet-4-6] [WORKER] Initializing container...
50
+ [2026-03-08T10:00:05.000Z] [requirements] [claude-code|claude-sonnet-4-6] Starting...
51
+ [2026-03-08T10:00:08.234Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Read {"file_path": "src/main.ts"}
52
+ [2026-03-08T10:00:10.345Z] [requirements] [claude-code|claude-sonnet-4-6] [text] Analyzing the codebase structure
53
+ [2026-03-08T10:00:12.567Z] [requirements] [claude-code|claude-sonnet-4-6] [tool] Bash {"command": "pnpm test:unit"}
54
+ [2026-03-08T10:00:45.789Z] [requirements] [claude-code|claude-sonnet-4-6] [result] 8920 chars, session=sess-abc123
55
+ [2026-03-08T10:00:45.790Z] [requirements] [claude-code|claude-sonnet-4-6] [tokens] 2450 in / 4560 out
56
+ Some unstructured output that doesn't match the format
57
+ Another raw line from stderr
58
+ [2026-03-08T10:02:30.100Z] [plan] [claude-code|claude-sonnet-4-6] Starting...
59
+ [2026-03-08T10:02:35.100Z] [plan] [claude-code|claude-sonnet-4-6] [tool] Write {"file_path": "specs/001-auth/plan.yaml"}
60
+ [2026-03-08T10:03:15.234Z] [plan] [claude-code|claude-sonnet-4-6] [result] 12345 chars, session=sess-abc123
61
+ [2026-03-08T10:03:15.235Z] [plan] [claude-code|claude-sonnet-4-6] [tokens] 8900 in / 3456 out`;
62
+ /* ---------------------------------------------------------------------------
63
+ * Stories
64
+ * ------------------------------------------------------------------------- */
65
+ /** ToolCalls — various tool call types */
66
+ export const ToolCalls = {
67
+ args: { content: toolEvents },
68
+ };
69
+ /** TextMessages — agent thinking/analysis */
70
+ export const TextMessages = {
71
+ args: { content: textEvents },
72
+ };
73
+ /** WorkerLifecycle — worker bootstrap and shutdown */
74
+ export const WorkerLifecycle = {
75
+ args: { content: workerEvents },
76
+ };
77
+ /** ResultsAndTokens — completion summaries */
78
+ export const ResultsAndTokens = {
79
+ args: { content: resultAndTokenEvents },
80
+ };
81
+ /** MixedContent — all event types including raw fallback */
82
+ export const MixedContent = {
83
+ args: { content: mixedContent },
84
+ };
85
+ /** EmptyContent — no content */
86
+ export const EmptyContent = {
87
+ args: { content: '' },
88
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"log-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/log-tab.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAgB,MAAM,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,WAAW,2CA6ElE"}
1
+ {"version":3,"file":"log-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/log-tab.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAID,wBAAgB,MAAM,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,WAAW,2CAgHlE"}
@@ -1,10 +1,12 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useRef, useEffect, useState, useCallback } from 'react';
4
- import { AlertCircle, Terminal, ArrowDown } from 'lucide-react';
4
+ import { AlertCircle, Terminal, ArrowDown, Code, FileText } from 'lucide-react';
5
+ import { EventLogViewer } from './event-log-viewer.js';
5
6
  export function LogTab({ content, isConnected, error }) {
6
7
  const containerRef = useRef(null);
7
8
  const [autoScroll, setAutoScroll] = useState(true);
9
+ const [viewMode, setViewMode] = useState('structured');
8
10
  const handleScroll = useCallback(() => {
9
11
  const el = containerRef.current;
10
12
  if (!el)
@@ -31,5 +33,11 @@ export function LogTab({ content, isConnected, error }) {
31
33
  if (!content) {
32
34
  return (_jsxs("div", { className: "flex flex-col items-center justify-center gap-2 p-8", children: [_jsx(Terminal, { className: "text-muted-foreground h-8 w-8" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "No log output yet" }), isConnected ? (_jsx("p", { className: "text-muted-foreground text-xs", children: "Waiting for log data..." })) : null] }));
33
35
  }
34
- return (_jsxs("div", { className: "flex h-full flex-col", "data-testid": "log-tab", children: [_jsxs("div", { className: "flex items-center gap-2 border-b px-3 py-1.5", children: [_jsx("span", { className: `h-2 w-2 rounded-full ${isConnected ? 'bg-emerald-500' : 'bg-zinc-400'}` }), _jsx("span", { className: "text-muted-foreground text-xs", children: isConnected ? 'Live' : 'Disconnected' }), !autoScroll ? (_jsxs("button", { type: "button", onClick: jumpToBottom, className: "text-muted-foreground hover:text-foreground ml-auto flex items-center gap-1 text-xs", children: [_jsx(ArrowDown, { className: "h-3 w-3" }), "Jump to bottom"] })) : null] }), _jsx("div", { ref: containerRef, onScroll: handleScroll, className: "flex-1 overflow-y-auto bg-zinc-950 p-3 font-mono text-xs leading-relaxed break-all whitespace-pre-wrap text-zinc-300", children: content })] }));
36
+ return (_jsxs("div", { className: "flex h-full flex-col", "data-testid": "log-tab", children: [_jsxs("div", { className: "flex items-center gap-2 border-b px-3 py-1.5", children: [_jsx("span", { className: `h-2 w-2 rounded-full ${isConnected ? 'bg-emerald-500' : 'bg-zinc-400'}` }), _jsx("span", { className: "text-muted-foreground text-xs", children: isConnected ? 'Live' : 'Disconnected' }), _jsxs("div", { className: "ml-auto flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: () => setViewMode('structured'), className: `rounded p-1 transition-colors ${viewMode === 'structured'
37
+ ? 'bg-muted text-foreground'
38
+ : 'text-muted-foreground hover:text-foreground'}`, title: "Structured view", children: _jsx(FileText, { className: "h-3.5 w-3.5" }) }), _jsx("button", { type: "button", onClick: () => setViewMode('raw'), className: `rounded p-1 transition-colors ${viewMode === 'raw'
39
+ ? 'bg-muted text-foreground'
40
+ : 'text-muted-foreground hover:text-foreground'}`, title: "Raw view", children: _jsx(Code, { className: "h-3.5 w-3.5" }) }), !autoScroll ? (_jsxs("button", { type: "button", onClick: jumpToBottom, className: "text-muted-foreground hover:text-foreground ml-1 flex items-center gap-1 text-xs", children: [_jsx(ArrowDown, { className: "h-3 w-3" }), "Jump to bottom"] })) : null] })] }), _jsx("div", { ref: containerRef, onScroll: handleScroll, className: `flex-1 overflow-y-auto ${viewMode === 'raw'
41
+ ? 'bg-zinc-950 p-3 font-mono text-xs leading-relaxed break-all whitespace-pre-wrap text-zinc-300'
42
+ : 'bg-background'}`, children: viewMode === 'structured' ? _jsx(EventLogViewer, { content: content }) : content })] }));
35
43
  }
@@ -3,10 +3,12 @@ import { LogTab } from './log-tab.js';
3
3
  declare const meta: Meta<typeof LogTab>;
4
4
  export default meta;
5
5
  type Story = StoryObj<typeof LogTab>;
6
- /** Default — typical agent log output with live connection. */
6
+ /** Default — structured agent log output with live connection (claude-code). */
7
7
  export declare const Default: Story;
8
- /** LongLog200 lines of log output to test scrolling behavior. */
9
- export declare const LongLog: Story;
8
+ /** LongStructured100 structured events to test scrolling behavior. */
9
+ export declare const LongStructured: Story;
10
+ /** RawFallback — unstructured log content falls back gracefully. */
11
+ export declare const RawFallback: Story;
10
12
  /** Disconnected — log content present but connection is lost. */
11
13
  export declare const Disconnected: Story;
12
14
  /** Empty — no log content yet, connected and waiting. */
@@ -1 +1 @@
1
- {"version":3,"file":"log-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,MAAM,CAc7B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,MAAM,CAAC,CAAC;AAqCrC,+DAA+D;AAC/D,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,oEAAoE;AACpE,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,iBAAiB,EAAE,KAM/B,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC"}
1
+ {"version":3,"file":"log-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/log-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,MAAM,CAc7B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,MAAM,CAAC,CAAC;AA6GrC,gFAAgF;AAChF,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,cAAc,EAAE,KAM5B,CAAC;AAEF,oEAAoE;AACpE,eAAO,MAAM,WAAW,EAAE,KAMzB,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,iBAAiB,EAAE,KAM/B,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,KAAK,EAAE,KAMnB,CAAC"}