@shepai/cli 1.108.0 → 1.109.0-pr333.db60eb7
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.
- package/apis/json-schema/NotificationEventConfig.yaml +5 -0
- package/apis/json-schema/NotificationEventType.yaml +1 -0
- package/dist/packages/core/src/application/use-cases/upgrade/upgrade-cli.use-case.d.ts +9 -1
- package/dist/packages/core/src/application/use-cases/upgrade/upgrade-cli.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/upgrade/upgrade-cli.use-case.js +31 -2
- package/dist/packages/core/src/domain/factories/settings-defaults.factory.d.ts.map +1 -1
- package/dist/packages/core/src/domain/factories/settings-defaults.factory.js +1 -0
- package/dist/packages/core/src/domain/generated/output.d.ts +6 -1
- package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
- package/dist/packages/core/src/domain/generated/output.js +1 -0
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +8 -4
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +2 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.js +28 -0
- package/dist/packages/core/src/infrastructure/platform.d.ts +7 -0
- package/dist/packages/core/src/infrastructure/platform.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/platform.js +6 -0
- package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.js +12 -0
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.js +2 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.js +7 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.js +14 -0
- package/dist/packages/core/src/infrastructure/services/git/worktree.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/worktree.service.js +2 -1
- package/dist/packages/core/src/infrastructure/services/notifications/notification-watcher.service.d.ts +2 -0
- package/dist/packages/core/src/infrastructure/services/notifications/notification-watcher.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/notifications/notification-watcher.service.js +35 -1
- package/dist/packages/core/src/infrastructure/services/notifications/notification.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/notifications/notification.service.js +1 -0
- package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.d.ts +13 -2
- package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js +80 -3
- package/dist/packages/core/src/infrastructure/services/web-server.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/web-server.service.js +15 -0
- package/dist/src/presentation/cli/commands/ui.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/ui.command.js +3 -1
- package/dist/src/presentation/web/app/actions/get-feature-drawer-data.d.ts +3 -0
- package/dist/src/presentation/web/app/actions/get-feature-drawer-data.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/get-feature-drawer-data.js +7 -32
- package/dist/src/presentation/web/app/api/agent-events/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/agent-events/route.js +20 -1
- package/dist/src/presentation/web/app/api/cli-upgrade/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/cli-upgrade/route.js +14 -1
- package/dist/src/presentation/web/app/api/tools/[id]/launch/route.js +1 -1
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.js +2 -0
- package/dist/src/presentation/web/components/common/version-badge/version-badge.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/version-badge/version-badge.js +6 -1
- package/dist/src/presentation/web/components/common/version-badge/version-badge.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/version-badge/version-badge.stories.js +7 -0
- package/dist/src/presentation/web/components/features/settings/notification-settings-section.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/notification-settings-section.js +1 -0
- package/dist/src/presentation/web/components/features/settings/notification-settings-section.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/notification-settings-section.stories.js +2 -0
- package/dist/src/presentation/web/dev-server.js +3 -1
- package/dist/src/presentation/web/hooks/use-cli-upgrade.d.ts +1 -1
- package/dist/src/presentation/web/hooks/use-cli-upgrade.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-cli-upgrade.js +40 -1
- package/dist/src/presentation/web/hooks/use-notifications.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-notifications.js +7 -3
- package/dist/src/presentation/web/lib/skills.js +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +3 -3
- package/web/.next/required-server-files.json +3 -3
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +20 -20
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +20 -20
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +18 -18
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +18 -18
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +2 -2
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__7d5492a0._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__7d5492a0._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__b4102cc7._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__b4102cc7._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__d2c18946._.js +7 -4
- package/web/.next/server/chunks/[root-of-the-server]__d2c18946._.js.map +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__039967e3._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__039967e3._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__07a39ff2._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2773312c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2773312c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cbd8062c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cbd8062c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e70c5627._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e70c5627._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_a2f904c8._.js → _0624ebcd._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_a2f904c8._.js.map → _0624ebcd._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_091ab7f5._.js → _0ed59e22._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_091ab7f5._.js.map → _0ed59e22._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_8affa5ab._.js → _1b5acc7e._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_8affa5ab._.js.map → _1b5acc7e._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_1bb131c4._.js +1 -1
- package/web/.next/server/chunks/ssr/_1bb131c4._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_250a63ae._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_3a4c94e3._.js +1 -1
- package/web/.next/server/chunks/ssr/_3a4c94e3._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
- package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js.map +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +31 -31
- package/web/.next/static/chunks/{b48405e5d661490f.js → 3590127e07396566.js} +1 -1
- package/web/.next/static/chunks/{41ad7066036d3e01.js → 37e937603c1b585a.js} +1 -1
- package/web/.next/static/chunks/5543614d36607aef.js +1 -0
- package/web/.next/static/chunks/{d7817aae0db61e25.js → 7f06b766fcb6d8b1.js} +1 -1
- package/web/.next/static/chunks/{1e5bd91d971ede3c.js → 860393fe87514d4e.js} +1 -1
- package/web/.next/static/chunks/{2946ec503df0563c.js → a7614b68a2b9df0d.js} +1 -1
- package/web/.next/static/chunks/{55e50bf848962a77.js → b8469d4a1c789862.js} +1 -1
- package/web/.next/static/chunks/{089b3c720afef02f.js → da9dc6b3e3f22c81.js} +2 -2
- package/web/.next/static/chunks/{3ac71f5bdd986ebf.js → eb9caf4f6ad20ced.js} +1 -1
- package/web/.next/static/chunks/{3fc0c2bdfd985563.js → f294966570d82c47.js} +1 -1
- package/web/.next/static/chunks/{fecdfab54bbebc7f.js → f84a3d8a01fd0998.js} +1 -1
- package/web/.next/static/chunks/{0102ce60a2a42fab.js → fcde0cbb2976b933.js} +1 -1
- package/web/.next/static/chunks/3bb35e0689e8b6b7.js +0 -1
- /package/web/.next/static/{9T2DFw6aFI0waogTIo2px → MTL4o8t-B0wwLjYHqHZTw}/_buildManifest.js +0 -0
- /package/web/.next/static/{9T2DFw6aFI0waogTIo2px → MTL4o8t-B0wwLjYHqHZTw}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{9T2DFw6aFI0waogTIo2px → MTL4o8t-B0wwLjYHqHZTw}/_ssgManifest.js +0 -0
package/dist/packages/core/src/infrastructure/services/notifications/notification-watcher.service.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Design decision: Uses DB polling instead of IPC because the worker
|
|
13
13
|
* process is spawned detached with IPC disconnected.
|
|
14
14
|
*/
|
|
15
|
-
import { AgentRunStatus, NotificationEventType, NotificationSeverity, } from '../../../domain/generated/output.js';
|
|
15
|
+
import { AgentRunStatus, NotificationEventType, NotificationSeverity, SdlcLifecycle, } from '../../../domain/generated/output.js';
|
|
16
16
|
const DEFAULT_POLL_INTERVAL_MS = 3000;
|
|
17
17
|
const ACTIVE_STATUSES = new Set([
|
|
18
18
|
AgentRunStatus.pending,
|
|
@@ -56,6 +56,7 @@ export class NotificationWatcherService {
|
|
|
56
56
|
notificationService;
|
|
57
57
|
pollIntervalMs;
|
|
58
58
|
trackedRuns = new Map();
|
|
59
|
+
trackedFeatureLifecycles = new Map();
|
|
59
60
|
intervalId = null;
|
|
60
61
|
// Suppresses notifications on the first poll to avoid replaying historical state
|
|
61
62
|
isBootstrapped = false;
|
|
@@ -92,6 +93,13 @@ export class NotificationWatcherService {
|
|
|
92
93
|
catch {
|
|
93
94
|
// DB not ready or query failed — skip this poll cycle
|
|
94
95
|
}
|
|
96
|
+
try {
|
|
97
|
+
const features = await this.featureRepository.list();
|
|
98
|
+
this.checkFeatureLifecycles(features);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// DB not ready or query failed — skip this poll cycle
|
|
102
|
+
}
|
|
95
103
|
}
|
|
96
104
|
async processRuns(runs) {
|
|
97
105
|
const currentRunIds = new Set();
|
|
@@ -182,6 +190,32 @@ export class NotificationWatcherService {
|
|
|
182
190
|
}
|
|
183
191
|
}
|
|
184
192
|
}
|
|
193
|
+
checkFeatureLifecycles(features) {
|
|
194
|
+
for (const feature of features) {
|
|
195
|
+
const prevLifecycle = this.trackedFeatureLifecycles.get(feature.id);
|
|
196
|
+
this.trackedFeatureLifecycles.set(feature.id, feature.lifecycle);
|
|
197
|
+
// Emit notification when a feature transitions TO Review from a known previous state.
|
|
198
|
+
// Skip when prevLifecycle is undefined (first observation / bootstrap seeding) or
|
|
199
|
+
// when the watcher hasn't completed its first poll yet.
|
|
200
|
+
if (this.isBootstrapped &&
|
|
201
|
+
prevLifecycle !== undefined &&
|
|
202
|
+
feature.lifecycle === SdlcLifecycle.Review &&
|
|
203
|
+
prevLifecycle !== SdlcLifecycle.Review) {
|
|
204
|
+
const prUrl = feature.pr?.url;
|
|
205
|
+
const message = prUrl ? `Ready for merge review — PR: ${prUrl}` : 'Ready for merge review';
|
|
206
|
+
const event = {
|
|
207
|
+
eventType: NotificationEventType.MergeReviewReady,
|
|
208
|
+
agentRunId: feature.agentRunId ?? '',
|
|
209
|
+
featureId: feature.id,
|
|
210
|
+
featureName: feature.name,
|
|
211
|
+
message,
|
|
212
|
+
severity: NotificationSeverity.Info,
|
|
213
|
+
timestamp: new Date().toISOString(),
|
|
214
|
+
};
|
|
215
|
+
this.notificationService.notify(event);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
185
219
|
async resolveFeatureIdentity(run) {
|
|
186
220
|
if (run.featureId) {
|
|
187
221
|
try {
|
package/dist/packages/core/src/infrastructure/services/notifications/notification.service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/notifications/notification.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,iBAAiB,EAElB,MAAM,qCAAqC,CAAC;AAE7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8EAA8E,CAAC;AAEzH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"notification.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/notifications/notification.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,iBAAiB,EAElB,MAAM,qCAAqC,CAAC;AAE7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8EAA8E,CAAC;AAEzH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAgB7D,qBAAa,mBAAoB,YAAW,oBAAoB;IAC9D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;gBAEtC,GAAG,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe;IAKlE,MAAM,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;CAiBvC"}
|
package/dist/packages/core/src/infrastructure/services/notifications/notification.service.js
CHANGED
|
@@ -21,6 +21,7 @@ const EVENT_TYPE_TO_CONFIG_KEY = {
|
|
|
21
21
|
[NotificationEventType.PrChecksPassed]: 'prChecksPassed',
|
|
22
22
|
[NotificationEventType.PrChecksFailed]: 'prChecksFailed',
|
|
23
23
|
[NotificationEventType.PrBlocked]: 'prBlocked',
|
|
24
|
+
[NotificationEventType.MergeReviewReady]: 'mergeReviewReady',
|
|
24
25
|
};
|
|
25
26
|
export class NotificationService {
|
|
26
27
|
bus;
|
|
@@ -13,6 +13,7 @@ import type { IFeatureRepository } from '../../../application/ports/output/repos
|
|
|
13
13
|
import type { IAgentRunRepository } from '../../../application/ports/output/agents/agent-run-repository.interface.js';
|
|
14
14
|
import type { IGitPrService } from '../../../application/ports/output/services/git-pr-service.interface.js';
|
|
15
15
|
import type { INotificationService } from '../../../application/ports/output/services/notification-service.interface.js';
|
|
16
|
+
import type Database from 'better-sqlite3';
|
|
16
17
|
export declare class PrSyncWatcherService {
|
|
17
18
|
private readonly featureRepo;
|
|
18
19
|
private readonly agentRunRepo;
|
|
@@ -21,12 +22,22 @@ export declare class PrSyncWatcherService {
|
|
|
21
22
|
private readonly pollIntervalMs;
|
|
22
23
|
private readonly trackedFeatures;
|
|
23
24
|
private readonly skippedRepos;
|
|
25
|
+
private readonly rateLimitedUntil;
|
|
26
|
+
private readonly db;
|
|
27
|
+
private readonly processId;
|
|
24
28
|
private intervalId;
|
|
25
|
-
|
|
29
|
+
private pollCycle;
|
|
30
|
+
constructor(featureRepo: IFeatureRepository, agentRunRepo: IAgentRunRepository, gitPrService: IGitPrService, notificationService: INotificationService, pollIntervalMs?: number, db?: Database.Database | null);
|
|
26
31
|
isRunning(): boolean;
|
|
27
32
|
start(): void;
|
|
28
33
|
stop(): void;
|
|
34
|
+
/** Attempt to acquire the cross-process poll lock. Returns true if acquired. */
|
|
35
|
+
private tryAcquireLock;
|
|
36
|
+
/** Check if a feature should be polled this cycle based on its unchanged cycles count. */
|
|
37
|
+
private shouldPollFeature;
|
|
29
38
|
private poll;
|
|
39
|
+
private isRateLimited;
|
|
40
|
+
private handleRateLimitError;
|
|
30
41
|
private processRepository;
|
|
31
42
|
private processFeature;
|
|
32
43
|
/** Mark associated agent run as completed so the UI reflects "done" state. */
|
|
@@ -39,7 +50,7 @@ export declare class PrSyncWatcherService {
|
|
|
39
50
|
*
|
|
40
51
|
* @throws Error if the watcher is already initialized
|
|
41
52
|
*/
|
|
42
|
-
export declare function initializePrSyncWatcher(featureRepo: IFeatureRepository, agentRunRepo: IAgentRunRepository, gitPrService: IGitPrService, notificationService: INotificationService, pollIntervalMs?: number): void;
|
|
53
|
+
export declare function initializePrSyncWatcher(featureRepo: IFeatureRepository, agentRunRepo: IAgentRunRepository, gitPrService: IGitPrService, notificationService: INotificationService, pollIntervalMs?: number, db?: Database.Database | null): void;
|
|
43
54
|
/**
|
|
44
55
|
* Get the PR sync watcher singleton.
|
|
45
56
|
*
|
package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pr-sync-watcher.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gFAAgF,CAAC;AACzH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4EAA4E,CAAC;AACtH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wEAAwE,CAAC;AAK5G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8EAA8E,CAAC;
|
|
1
|
+
{"version":3,"file":"pr-sync-watcher.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gFAAgF,CAAC;AACzH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4EAA4E,CAAC;AACtH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wEAAwE,CAAC;AAK5G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8EAA8E,CAAC;AACzH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAqB3C,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IACnD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAC7C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAuB;IAC3D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqC;IACrE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA6B;IAC9D,OAAO,CAAC,QAAQ,CAAC,EAAE,CAA2B;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,SAAS,CAAK;gBAGpB,WAAW,EAAE,kBAAkB,EAC/B,YAAY,EAAE,mBAAmB,EACjC,YAAY,EAAE,aAAa,EAC3B,mBAAmB,EAAE,oBAAoB,EACzC,cAAc,GAAE,MAAiC,EACjD,EAAE,GAAE,QAAQ,CAAC,QAAQ,GAAG,IAAW;IAWrC,SAAS,IAAI,OAAO;IAIpB,KAAK,IAAI,IAAI;IAcb,IAAI,IAAI,IAAI;IASZ,gFAAgF;IAChF,OAAO,CAAC,cAAc;IAiBtB,0FAA0F;IAC1F,OAAO,CAAC,iBAAiB;YAUX,IAAI;IA6ClB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,oBAAoB;YAYd,iBAAiB;YA+CjB,cAAc;IAoL5B,8EAA8E;YAChE,gBAAgB;IAW9B,OAAO,CAAC,gBAAgB;CAoBzB;AAMD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,kBAAkB,EAC/B,YAAY,EAAE,mBAAmB,EACjC,YAAY,EAAE,aAAa,EAC3B,mBAAmB,EAAE,oBAAoB,EACzC,cAAc,CAAC,EAAE,MAAM,EACvB,EAAE,CAAC,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,GAC5B,IAAI,CAaN;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,oBAAoB,CAQvD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAKzC"}
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { SdlcLifecycle, PrStatus, CiStatus, AgentRunStatus, NotificationEventType, NotificationSeverity, } from '../../../domain/generated/output.js';
|
|
13
13
|
const DEFAULT_POLL_INTERVAL_MS = 30_000;
|
|
14
|
+
const LOCK_TTL_MS = 60_000;
|
|
15
|
+
const RATE_LIMIT_BACKOFF_MS = 5 * 60_000;
|
|
14
16
|
const TAG = '[PrSyncWatcher]';
|
|
15
17
|
const CI_STATUS_MAP = {
|
|
16
18
|
success: CiStatus.Success,
|
|
@@ -25,13 +27,19 @@ export class PrSyncWatcherService {
|
|
|
25
27
|
pollIntervalMs;
|
|
26
28
|
trackedFeatures = new Map();
|
|
27
29
|
skippedRepos = new Set();
|
|
30
|
+
rateLimitedUntil = new Map();
|
|
31
|
+
db;
|
|
32
|
+
processId;
|
|
28
33
|
intervalId = null;
|
|
29
|
-
|
|
34
|
+
pollCycle = 0;
|
|
35
|
+
constructor(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs = DEFAULT_POLL_INTERVAL_MS, db = null) {
|
|
30
36
|
this.featureRepo = featureRepo;
|
|
31
37
|
this.agentRunRepo = agentRunRepo;
|
|
32
38
|
this.gitPrService = gitPrService;
|
|
33
39
|
this.notificationService = notificationService;
|
|
34
40
|
this.pollIntervalMs = pollIntervalMs;
|
|
41
|
+
this.db = db;
|
|
42
|
+
this.processId = `${process.pid}-${Date.now()}`;
|
|
35
43
|
}
|
|
36
44
|
isRunning() {
|
|
37
45
|
return this.intervalId !== null;
|
|
@@ -55,8 +63,40 @@ export class PrSyncWatcherService {
|
|
|
55
63
|
console.log(`${TAG} Stopped`);
|
|
56
64
|
}
|
|
57
65
|
}
|
|
66
|
+
/** Attempt to acquire the cross-process poll lock. Returns true if acquired. */
|
|
67
|
+
tryAcquireLock() {
|
|
68
|
+
if (!this.db)
|
|
69
|
+
return true; // no DB → single-process mode, always proceed
|
|
70
|
+
const now = Date.now();
|
|
71
|
+
const expiresAt = now + LOCK_TTL_MS;
|
|
72
|
+
const stmt = this.db.prepare(`
|
|
73
|
+
INSERT OR REPLACE INTO pr_sync_lock (id, locked_by, locked_at, expires_at)
|
|
74
|
+
SELECT 1, ?, ?, ?
|
|
75
|
+
WHERE NOT EXISTS (
|
|
76
|
+
SELECT 1 FROM pr_sync_lock WHERE id = 1 AND locked_by != ? AND expires_at > ?
|
|
77
|
+
)
|
|
78
|
+
`);
|
|
79
|
+
const result = stmt.run(this.processId, now, expiresAt, this.processId, now);
|
|
80
|
+
return result.changes > 0;
|
|
81
|
+
}
|
|
82
|
+
/** Check if a feature should be polled this cycle based on its unchanged cycles count. */
|
|
83
|
+
shouldPollFeature(featureId) {
|
|
84
|
+
const tracked = this.trackedFeatures.get(featureId);
|
|
85
|
+
if (!tracked)
|
|
86
|
+
return true; // new feature, always poll
|
|
87
|
+
const uc = tracked.unchangedCycles;
|
|
88
|
+
if (uc <= 2)
|
|
89
|
+
return true; // poll every cycle
|
|
90
|
+
if (uc <= 5)
|
|
91
|
+
return this.pollCycle % 2 === 0; // poll every 2nd cycle
|
|
92
|
+
return this.pollCycle % 4 === 0; // poll every 4th cycle
|
|
93
|
+
}
|
|
58
94
|
async poll() {
|
|
59
95
|
try {
|
|
96
|
+
if (!this.tryAcquireLock()) {
|
|
97
|
+
return; // another process holds the lock — skip this cycle
|
|
98
|
+
}
|
|
99
|
+
this.pollCycle++;
|
|
60
100
|
const allFeatures = await this.featureRepo.list({ lifecycle: SdlcLifecycle.Review });
|
|
61
101
|
// Include features with a valid repositoryPath (with or without PR data)
|
|
62
102
|
const features = allFeatures.filter((f) => f.repositoryPath);
|
|
@@ -89,9 +129,32 @@ export class PrSyncWatcherService {
|
|
|
89
129
|
console.warn(`${TAG} Poll failed: ${msg}`);
|
|
90
130
|
}
|
|
91
131
|
}
|
|
132
|
+
isRateLimited(repoPath) {
|
|
133
|
+
const until = this.rateLimitedUntil.get(repoPath);
|
|
134
|
+
if (until === undefined)
|
|
135
|
+
return false;
|
|
136
|
+
if (Date.now() >= until) {
|
|
137
|
+
this.rateLimitedUntil.delete(repoPath);
|
|
138
|
+
// eslint-disable-next-line no-console
|
|
139
|
+
console.log(`${TAG} Rate limit backoff expired for ${repoPath}`);
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
handleRateLimitError(repoPath, error) {
|
|
145
|
+
const msg = error.message;
|
|
146
|
+
if (msg.includes('API rate limit exceeded') || msg.includes('rate limit')) {
|
|
147
|
+
const backoffUntil = Date.now() + RATE_LIMIT_BACKOFF_MS;
|
|
148
|
+
this.rateLimitedUntil.set(repoPath, backoffUntil);
|
|
149
|
+
// eslint-disable-next-line no-console
|
|
150
|
+
console.warn(`${TAG} Rate limited for ${repoPath}, backing off until ${new Date(backoffUntil).toISOString()}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
92
153
|
async processRepository(repoPath, features) {
|
|
93
154
|
if (this.skippedRepos.has(repoPath))
|
|
94
155
|
return;
|
|
156
|
+
if (this.isRateLimited(repoPath))
|
|
157
|
+
return;
|
|
95
158
|
// Skip repos without a git remote — gh pr list will always fail
|
|
96
159
|
try {
|
|
97
160
|
if (!(await this.gitPrService.hasRemote(repoPath))) {
|
|
@@ -110,6 +173,8 @@ export class PrSyncWatcherService {
|
|
|
110
173
|
}
|
|
111
174
|
catch (error) {
|
|
112
175
|
const msg = error instanceof Error ? error.message : String(error);
|
|
176
|
+
if (error instanceof Error)
|
|
177
|
+
this.handleRateLimitError(repoPath, error);
|
|
113
178
|
// eslint-disable-next-line no-console
|
|
114
179
|
console.warn(`${TAG} listPrStatuses failed for ${repoPath}: ${msg}`);
|
|
115
180
|
return;
|
|
@@ -153,10 +218,15 @@ export class PrSyncWatcherService {
|
|
|
153
218
|
ciStatus: undefined,
|
|
154
219
|
mergeable: undefined,
|
|
155
220
|
featureName: feature.name,
|
|
221
|
+
unchangedCycles: 0,
|
|
156
222
|
});
|
|
157
223
|
await this.featureRepo.update(feature);
|
|
158
224
|
return;
|
|
159
225
|
}
|
|
226
|
+
// Check exponential backoff — skip features that haven't changed recently
|
|
227
|
+
if (!this.shouldPollFeature(feature.id)) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
160
230
|
const pr = feature.pr;
|
|
161
231
|
const prStatusInfo = statusByNumber.get(pr.number);
|
|
162
232
|
let needsUpdate = false;
|
|
@@ -169,6 +239,7 @@ export class PrSyncWatcherService {
|
|
|
169
239
|
ciStatus: pr.ciStatus,
|
|
170
240
|
mergeable: pr.mergeable,
|
|
171
241
|
featureName: feature.name,
|
|
242
|
+
unchangedCycles: 0,
|
|
172
243
|
});
|
|
173
244
|
}
|
|
174
245
|
const tracked = this.trackedFeatures.get(feature.id);
|
|
@@ -223,12 +294,18 @@ export class PrSyncWatcherService {
|
|
|
223
294
|
}
|
|
224
295
|
catch (error) {
|
|
225
296
|
const msg = error instanceof Error ? error.message : String(error);
|
|
297
|
+
if (error instanceof Error)
|
|
298
|
+
this.handleRateLimitError(feature.repositoryPath, error);
|
|
226
299
|
// eslint-disable-next-line no-console
|
|
227
300
|
console.warn(`${TAG} getCiStatus failed for "${feature.name}": ${msg}`);
|
|
228
301
|
}
|
|
229
302
|
if (needsUpdate) {
|
|
303
|
+
tracked.unchangedCycles = 0;
|
|
230
304
|
await this.featureRepo.update(feature);
|
|
231
305
|
}
|
|
306
|
+
else {
|
|
307
|
+
tracked.unchangedCycles++;
|
|
308
|
+
}
|
|
232
309
|
}
|
|
233
310
|
/** Mark associated agent run as completed so the UI reflects "done" state. */
|
|
234
311
|
async completeAgentRun(feature) {
|
|
@@ -264,11 +341,11 @@ let watcherInstance = null;
|
|
|
264
341
|
*
|
|
265
342
|
* @throws Error if the watcher is already initialized
|
|
266
343
|
*/
|
|
267
|
-
export function initializePrSyncWatcher(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs) {
|
|
344
|
+
export function initializePrSyncWatcher(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs, db) {
|
|
268
345
|
if (watcherInstance !== null) {
|
|
269
346
|
throw new Error('PR sync watcher already initialized. Cannot re-initialize.');
|
|
270
347
|
}
|
|
271
|
-
watcherInstance = new PrSyncWatcherService(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs);
|
|
348
|
+
watcherInstance = new PrSyncWatcherService(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs, db ?? null);
|
|
272
349
|
}
|
|
273
350
|
/**
|
|
274
351
|
* Get the PR sync watcher singleton.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-server.service.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/services/web-server.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yEAAyE,CAAC;
|
|
1
|
+
{"version":3,"file":"web-server.service.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/services/web-server.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yEAAyE,CAAC;AAKjH,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,OAAO,IAAI,CAAC;IAC3B,gBAAgB,EAAE,OAAO,IAAI,CAAC,YAAY,CAAC;CAC5C;AAOD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,IAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAsB7D;AAED,qBACa,gBAAiB,YAAW,iBAAiB;IACxD,OAAO,CAAC,GAAG,CAAwB;IACnC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;gBAEzB,IAAI,GAAE,OAAO,CAAC,aAAa,CAAM;IAI7C;;;;;OAKG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA0CjE;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAuB5B"}
|
|
@@ -22,6 +22,7 @@ import next from 'next';
|
|
|
22
22
|
import http from 'node:http';
|
|
23
23
|
import path from 'node:path';
|
|
24
24
|
import fs from 'node:fs';
|
|
25
|
+
import { IS_WINDOWS } from '../platform.js';
|
|
25
26
|
const defaultDeps = {
|
|
26
27
|
createNextApp: next,
|
|
27
28
|
createHttpServer: http.createServer,
|
|
@@ -70,6 +71,20 @@ let WebServerService = class WebServerService {
|
|
|
70
71
|
* @param dev - Whether to run in development mode (default: auto-detect)
|
|
71
72
|
*/
|
|
72
73
|
async start(port, dir, dev = true) {
|
|
74
|
+
// On Windows, Next.js uses path.relative(CWD, dir) internally then
|
|
75
|
+
// reconstructs with path.join(CWD, relative). When CWD and dir are on
|
|
76
|
+
// different drives (e.g. D:\project vs C:\...\web), path.relative returns
|
|
77
|
+
// the absolute path (can't compute relative across drives), and path.join
|
|
78
|
+
// produces a mangled path like D:\project\C:\...\web\. Fix by ensuring
|
|
79
|
+
// CWD is on the same drive as dir.
|
|
80
|
+
if (IS_WINDOWS) {
|
|
81
|
+
const getDriveLetter = (p) => p.match(/^[a-zA-Z]:/)?.[0]?.toUpperCase();
|
|
82
|
+
const cwdDrive = getDriveLetter(process.cwd());
|
|
83
|
+
const dirDrive = getDriveLetter(dir);
|
|
84
|
+
if (cwdDrive && dirDrive && cwdDrive !== dirDrive) {
|
|
85
|
+
process.chdir(dir);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
73
88
|
const app = this.deps.createNextApp({
|
|
74
89
|
dev,
|
|
75
90
|
dir,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/ui.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"ui.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/ui.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AAgC1D;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CA0FzC"}
|
|
@@ -21,6 +21,7 @@ import { setVersionEnvVars } from '../../../../packages/core/src/infrastructure/
|
|
|
21
21
|
import { resolveWebDir } from '../../../../packages/core/src/infrastructure/services/web-server.service.js';
|
|
22
22
|
import { initializeNotificationWatcher, getNotificationWatcher, } from '../../../../packages/core/src/infrastructure/services/notifications/notification-watcher.service.js';
|
|
23
23
|
import { initializePrSyncWatcher, getPrSyncWatcher, } from '../../../../packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js';
|
|
24
|
+
import { getExistingConnection } from '../../../../packages/core/src/infrastructure/persistence/sqlite/connection.js';
|
|
24
25
|
import { BrowserOpenerService } from '../../../../packages/core/src/infrastructure/services/browser-opener.service.js';
|
|
25
26
|
import { colors, fmt, messages } from '../ui/index.js';
|
|
26
27
|
function parsePort(value) {
|
|
@@ -66,7 +67,8 @@ Examples:
|
|
|
66
67
|
getNotificationWatcher().start();
|
|
67
68
|
// Start PR sync watcher to detect PR/CI status transitions on GitHub
|
|
68
69
|
const gitPrService = container.resolve('IGitPrService');
|
|
69
|
-
|
|
70
|
+
const db = getExistingConnection();
|
|
71
|
+
initializePrSyncWatcher(featureRepo, runRepo, gitPrService, notificationService, undefined, db);
|
|
70
72
|
getPrSyncWatcher().start();
|
|
71
73
|
const url = `http://localhost:${port}`;
|
|
72
74
|
messages.success(`Server ready at ${fmt.code(url)}`);
|
|
@@ -3,6 +3,9 @@ import type { FeatureNodeData } from '../../components/common/feature-node/index
|
|
|
3
3
|
* Fetches full FeatureNodeData for a given feature ID.
|
|
4
4
|
* Used by the drawer for targeted data syncing without triggering
|
|
5
5
|
* a full router.refresh() / server component re-render.
|
|
6
|
+
*
|
|
7
|
+
* CI status and mergeable status are read from the DB (already updated
|
|
8
|
+
* by PrSyncWatcherService) instead of making duplicate GitHub API calls.
|
|
6
9
|
*/
|
|
7
10
|
export declare function getFeatureDrawerData(featureId: string): Promise<FeatureNodeData | null>;
|
|
8
11
|
//# sourceMappingURL=get-feature-drawer-data.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-feature-drawer-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-feature-drawer-data.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-feature-drawer-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-feature-drawer-data.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAExE;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAgC7F"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
import { resolve } from '../../lib/server-container.js';
|
|
3
|
-
import { CiStatus } from '../../../../../packages/core/src/domain/generated/output.js';
|
|
4
3
|
import { buildFeatureNodeData } from '../build-feature-node-data.js';
|
|
5
|
-
const CI_STATUS_MAP = {
|
|
6
|
-
success: CiStatus.Success,
|
|
7
|
-
failure: CiStatus.Failure,
|
|
8
|
-
pending: CiStatus.Pending,
|
|
9
|
-
};
|
|
10
4
|
/**
|
|
11
5
|
* Fetches full FeatureNodeData for a given feature ID.
|
|
12
6
|
* Used by the drawer for targeted data syncing without triggering
|
|
13
7
|
* a full router.refresh() / server component re-render.
|
|
8
|
+
*
|
|
9
|
+
* CI status and mergeable status are read from the DB (already updated
|
|
10
|
+
* by PrSyncWatcherService) instead of making duplicate GitHub API calls.
|
|
14
11
|
*/
|
|
15
12
|
export async function getFeatureDrawerData(featureId) {
|
|
16
13
|
try {
|
|
@@ -23,37 +20,15 @@ export async function getFeatureDrawerData(featureId) {
|
|
|
23
20
|
if (!feature)
|
|
24
21
|
return null;
|
|
25
22
|
const run = feature.agentRunId ? await agentRunRepo.findById(feature.agentRunId) : null;
|
|
26
|
-
|
|
23
|
+
// CI status and mergeable status are read from the feature record (updated by
|
|
24
|
+
// PrSyncWatcherService every 30s) — no duplicate GitHub API calls needed.
|
|
25
|
+
// Only getDefaultBranch and getRemoteUrl are kept as they are local git operations.
|
|
26
|
+
const [repo, baseBranch, artifact, remoteUrl] = await Promise.all([
|
|
27
27
|
repoRepo.findByPath(feature.repositoryPath).catch(() => null),
|
|
28
28
|
gitPrService.getDefaultBranch(feature.repositoryPath).catch(() => 'main'),
|
|
29
29
|
getArtifact.execute(featureId).catch(() => null),
|
|
30
30
|
gitPrService.getRemoteUrl(feature.repositoryPath).catch(() => null),
|
|
31
|
-
feature.pr?.number
|
|
32
|
-
? gitPrService
|
|
33
|
-
.getMergeableStatus(feature.repositoryPath, feature.pr.number)
|
|
34
|
-
.catch(() => undefined)
|
|
35
|
-
: Promise.resolve(undefined),
|
|
36
|
-
feature.branch
|
|
37
|
-
? gitPrService.getCiStatus(feature.repositoryPath, feature.branch).catch(() => undefined)
|
|
38
|
-
: Promise.resolve(undefined),
|
|
39
31
|
]);
|
|
40
|
-
// Merge live PR status into feature data
|
|
41
|
-
if (feature.pr) {
|
|
42
|
-
const liveCiStatus = liveCiResult
|
|
43
|
-
? (CI_STATUS_MAP[liveCiResult.status] ?? CiStatus.Pending)
|
|
44
|
-
: undefined;
|
|
45
|
-
const updates = {};
|
|
46
|
-
if (liveMergeable !== undefined)
|
|
47
|
-
updates.mergeable = liveMergeable;
|
|
48
|
-
if (liveCiStatus !== undefined)
|
|
49
|
-
updates.ciStatus = liveCiStatus;
|
|
50
|
-
if (Object.keys(updates).length > 0) {
|
|
51
|
-
feature.pr = { ...feature.pr, ...updates };
|
|
52
|
-
featureRepo.update(feature).catch(() => {
|
|
53
|
-
/* best-effort persist */
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
32
|
return buildFeatureNodeData(feature, run, {
|
|
58
33
|
repositoryName: repo?.name,
|
|
59
34
|
baseBranch,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/agent-events/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAqEvC,wBAAgB,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/agent-events/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAqEvC,wBAAgB,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CA4R9C"}
|
|
@@ -191,9 +191,28 @@ export function GET(request) {
|
|
|
191
191
|
}
|
|
192
192
|
// Check for lifecycle change (agent stays "running" but moves through phases)
|
|
193
193
|
if (prev.lifecycle !== feature.lifecycle) {
|
|
194
|
+
const prevLifecycle = prev.lifecycle;
|
|
194
195
|
prev.lifecycle = feature.lifecycle;
|
|
195
196
|
const nodeName = LIFECYCLE_TO_NODE[feature.lifecycle];
|
|
196
|
-
|
|
197
|
+
// Emit MergeReviewReady when lifecycle transitions TO Review
|
|
198
|
+
if (feature.lifecycle === SdlcLifecycle.Review &&
|
|
199
|
+
prevLifecycle !== SdlcLifecycle.Review) {
|
|
200
|
+
const prUrl = feature.pr?.url;
|
|
201
|
+
const message = prUrl
|
|
202
|
+
? `Ready for merge review — PR: ${prUrl}`
|
|
203
|
+
: 'Ready for merge review';
|
|
204
|
+
emitEvent({
|
|
205
|
+
eventType: NotificationEventType.MergeReviewReady,
|
|
206
|
+
agentRunId: run.id,
|
|
207
|
+
featureId: feature.id,
|
|
208
|
+
featureName: feature.name,
|
|
209
|
+
phaseName: 'merge',
|
|
210
|
+
message,
|
|
211
|
+
severity: NotificationSeverity.Info,
|
|
212
|
+
timestamp: new Date().toISOString(),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
else if (nodeName) {
|
|
197
216
|
emitEvent({
|
|
198
217
|
eventType: NotificationEventType.PhaseCompleted,
|
|
199
218
|
agentRunId: run.id,
|
|
@@ -1 +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,
|
|
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,CA4C9C"}
|
|
@@ -11,13 +11,26 @@ export async function POST() {
|
|
|
11
11
|
controller.enqueue(encoder.encode(`data: ${chunk.replace(/\n/g, '\ndata: ')}\n\n`));
|
|
12
12
|
});
|
|
13
13
|
controller.enqueue(encoder.encode(`event: done\ndata: ${JSON.stringify(result)}\n\n`));
|
|
14
|
+
// If the upgrade succeeded, schedule a daemon self-restart so the
|
|
15
|
+
// new version is loaded automatically — no manual restart needed.
|
|
16
|
+
if (result.status === 'upgraded') {
|
|
17
|
+
controller.enqueue(encoder.encode(`event: restarting\ndata: restarting\n\n`));
|
|
18
|
+
controller.close();
|
|
19
|
+
await useCase.scheduleDaemonRestart();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
14
22
|
}
|
|
15
23
|
catch (error) {
|
|
16
24
|
const message = error instanceof Error ? error.message : 'Upgrade failed';
|
|
17
25
|
controller.enqueue(encoder.encode(`event: done\ndata: ${JSON.stringify({ status: 'error', currentVersion: '', latestVersion: null, errorMessage: message })}\n\n`));
|
|
18
26
|
}
|
|
19
27
|
finally {
|
|
20
|
-
|
|
28
|
+
try {
|
|
29
|
+
controller.close();
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Already closed (e.g. after restart path)
|
|
33
|
+
}
|
|
21
34
|
}
|
|
22
35
|
},
|
|
23
36
|
});
|
|
@@ -6,7 +6,7 @@ export async function POST(_request, { params }) {
|
|
|
6
6
|
const useCase = resolve('LaunchToolUseCase');
|
|
7
7
|
const result = await useCase.execute({
|
|
8
8
|
toolId: id,
|
|
9
|
-
directoryPath: process.cwd(),
|
|
9
|
+
directoryPath: process.env.NEXT_PUBLIC_SHEP_INSTANCE_PATH ?? process.cwd(),
|
|
10
10
|
headless: true,
|
|
11
11
|
});
|
|
12
12
|
if (result.ok) {
|
package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derive-feature-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/derive-feature-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAIL,qBAAqB,EACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAE3F;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,EAC1B,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,gBAAgB,CAkDlB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAYvD;AAED,oGAAoG;AACpG,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,qBAAqB,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"derive-feature-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/derive-feature-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAIL,qBAAqB,EACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAE3F;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,EAC1B,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,gBAAgB,CAkDlB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAYvD;AAED,oGAAoG;AACpG,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,qBAAqB,GAAG,gBAAgB,CAsBtF;AAED,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAOlE,CAAC;AAcF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,GAAG,qBAAqB,CAQ7F;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpC,SAAS,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAC7C,SAAS,EAAE,qBAAqB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,qBAAqB,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,GAC7F,cAAc,EAAE,CAmBlB;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,qBAAqB,GAAG,SAAS,CAGnC"}
|
|
@@ -99,6 +99,8 @@ export function mapEventTypeToState(eventType) {
|
|
|
99
99
|
return 'action-required';
|
|
100
100
|
case NotificationEventType.PrBlocked:
|
|
101
101
|
return 'blocked';
|
|
102
|
+
case NotificationEventType.MergeReviewReady:
|
|
103
|
+
return 'action-required';
|
|
102
104
|
}
|
|
103
105
|
}
|
|
104
106
|
/** Map domain SdlcLifecycle enum values to UI FeatureLifecyclePhase. */
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,2CAyFnB"}
|
|
@@ -10,9 +10,14 @@ export function VersionBadge({ version, branch, commitHash, isDev = false, packa
|
|
|
10
10
|
// In dev mode show "1.92.2-dev", in production show "v1.92.2"
|
|
11
11
|
const displayVersion = isDev ? `${version}-dev` : `v${version}`;
|
|
12
12
|
const isUpgrading = upgradeStatus === 'upgrading';
|
|
13
|
+
const isRestarting = upgradeStatus === 'restarting';
|
|
13
14
|
const didUpgrade = upgradeStatus === 'upgraded';
|
|
14
15
|
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] }),
|
|
16
|
+
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 && !isRestarting ? (_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] }), isRestarting ? (_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-restarting", children: "Restarting..." }) })) : 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" }) })) : 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 || isRestarting, 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
|
|
17
|
+
? 'Upgrading...'
|
|
18
|
+
: isRestarting
|
|
19
|
+
? 'Restarting...'
|
|
20
|
+
: `Upgrade to v${latest}` }) })) : null] })] }) }));
|
|
16
21
|
}
|
|
17
22
|
function Row({ label, value, highlight, mono, }) {
|
|
18
23
|
return (_jsxs("div", { className: "flex items-center justify-between gap-4 text-[10px]", children: [_jsx("span", { className: "opacity-60", children: label }), _jsx("span", { className: [
|
package/dist/src/presentation/web/components/common/version-badge/version-badge.stories.d.ts.map
CHANGED
|
@@ -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;
|
|
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;AA+D/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"}
|
|
@@ -22,6 +22,7 @@ function withNpmVersion(latest) {
|
|
|
22
22
|
controller.enqueue(encoder.encode(`data: Upgrading to v${latest}...\n\n`));
|
|
23
23
|
setTimeout(() => {
|
|
24
24
|
controller.enqueue(encoder.encode(`event: done\ndata: ${JSON.stringify({ status: 'upgraded', currentVersion: '1.90.0', latestVersion: latest })}\n\n`));
|
|
25
|
+
controller.enqueue(encoder.encode(`event: restarting\ndata: restarting\n\n`));
|
|
25
26
|
controller.close();
|
|
26
27
|
}, 1000);
|
|
27
28
|
},
|
|
@@ -31,6 +32,12 @@ function withNpmVersion(latest) {
|
|
|
31
32
|
headers: { 'Content-Type': 'text/event-stream' },
|
|
32
33
|
});
|
|
33
34
|
}
|
|
35
|
+
if (url.includes('/api/version')) {
|
|
36
|
+
return new Response(JSON.stringify({ version: latest }), {
|
|
37
|
+
status: 200,
|
|
38
|
+
headers: { 'Content-Type': 'application/json' },
|
|
39
|
+
});
|
|
40
|
+
}
|
|
34
41
|
return originalFetch(input, init);
|
|
35
42
|
});
|
|
36
43
|
return _jsx(Story, {});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification-settings-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/notification-settings-section.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"notification-settings-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/notification-settings-section.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAmBpF,MAAM,WAAW,gCAAgC;IAC/C,aAAa,EAAE,uBAAuB,CAAC;CACxC;AAED,wBAAgB,2BAA2B,CAAC,EAAE,aAAa,EAAE,EAAE,gCAAgC,2CAkJ9F"}
|
package/dist/src/presentation/web/components/features/settings/notification-settings-section.js
CHANGED
|
@@ -16,6 +16,7 @@ const AGENT_EVENT_TOGGLES = [
|
|
|
16
16
|
{ key: 'agentFailed', label: 'Agent Failed' },
|
|
17
17
|
];
|
|
18
18
|
const PR_EVENT_TOGGLES = [
|
|
19
|
+
{ key: 'mergeReviewReady', label: 'Merge Review Ready' },
|
|
19
20
|
{ key: 'prMerged', label: 'PR Merged' },
|
|
20
21
|
{ key: 'prClosed', label: 'PR Closed' },
|
|
21
22
|
{ key: 'prChecksPassed', label: 'PR Checks Passed' },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification-settings-section.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/notification-settings-section.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAE9E,QAAA,MAAM,IAAI;;;;;;;CAO0C,CAAC;AAErD,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"notification-settings-section.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/notification-settings-section.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAE9E,QAAA,MAAM,IAAI;;;;;;;CAO0C,CAAC;AAErD,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AA8BnC,eAAO,MAAM,OAAO,EAAE,KASrB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KASxB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KASzB,CAAC"}
|