@shepai/cli 1.122.1-pr361.35a9abd → 1.122.1-pr392.3d141b4
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/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.js +4 -21
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.d.ts +1 -7
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.js +2 -24
- package/dist/src/presentation/web/app/actions/get-feature-phase-timings.d.ts +2 -0
- package/dist/src/presentation/web/app/actions/get-feature-phase-timings.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/get-feature-phase-timings.js +2 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.js +130 -31
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.js +13 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.js +18 -9
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +11 -53
- package/dist/src/presentation/web/hooks/use-viewport-persistence.d.ts +0 -2
- package/dist/src/presentation/web/hooks/use-viewport-persistence.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-viewport-persistence.js +6 -19
- package/dist/src/presentation/web/lib/layout-with-dagre.d.ts.map +1 -1
- package/dist/src/presentation/web/lib/layout-with-dagre.js +2 -11
- 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 +1 -1
- package/web/.next/required-server-files.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +22 -22
- 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 +28 -28
- 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 +28 -28
- 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 +20 -20
- 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 +22 -22
- 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 +28 -28
- 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 +28 -28
- 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 +20 -20
- 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 +20 -20
- 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 +6 -6
- 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 +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/[root-of-the-server]__a402b567._.js +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_f30d0343.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_f30d0343.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__06fef644._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2698e9f4._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2698e9f4._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8c553503._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8e3bf5d7._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8e3bf5d7._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a022445f._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c07f9f79._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c07f9f79._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c605a375._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c605a375._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f646b99a._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f646b99a._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_0dc2cfd3._.js +1 -1
- package/web/.next/server/chunks/ssr/_0dc2cfd3._.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/{_132dd4b8._.js → _16c9ad39._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_132dd4b8._.js.map → _16c9ad39._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_2f6f48b8._.js +1 -1
- package/web/.next/server/chunks/ssr/_2f6f48b8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_30c9af21._.js → _3608239e._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_30c9af21._.js.map → _3608239e._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_8a2ce912._.js +3 -0
- package/web/.next/server/chunks/ssr/_8a2ce912._.js.map +1 -0
- 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_5f039db1._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_5f039db1._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.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_c4337169._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_c4337169._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.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_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/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +34 -34
- package/web/.next/static/chunks/0614fc7ba4ab5a8d.js +1 -0
- package/web/.next/static/chunks/0a53e43382b2e356.css +1 -0
- package/web/.next/static/chunks/{ab24252e992d6b8c.js → 0f22d1364a238a3d.js} +1 -1
- package/web/.next/static/chunks/{0cd4694791225f54.js → 115420b828393351.js} +2 -2
- package/web/.next/static/chunks/37e6e2ae609060bc.js +1 -0
- package/web/.next/static/chunks/3911a7175044e784.js +1 -0
- package/web/.next/static/chunks/52be053c5d383e0a.js +1 -0
- package/web/.next/static/chunks/{c7bd0ef3d9b78f56.js → 545a792b9c112c0e.js} +1 -1
- package/web/.next/static/chunks/619e58de25e38f82.js +1 -0
- package/web/.next/static/chunks/{1b819d33e9d131dc.js → 66b1c29f3433d763.js} +2 -2
- package/web/.next/static/chunks/{717af1bcb9dadef9.js → 8335d9f3f8f62db3.js} +1 -1
- package/web/.next/static/chunks/de93dd99119c9eee.js +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9f155c0e._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9f155c0e._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_32c5c20d._.js +0 -3
- package/web/.next/server/chunks/ssr/_32c5c20d._.js.map +0 -1
- package/web/.next/static/chunks/0d2af96e64960ef5.css +0 -1
- package/web/.next/static/chunks/1a71a1628a38996f.js +0 -1
- package/web/.next/static/chunks/4562ee849ea13c3a.js +0 -1
- package/web/.next/static/chunks/56a5153f06d64eca.js +0 -1
- package/web/.next/static/chunks/82f917cc65ec7d42.js +0 -1
- package/web/.next/static/chunks/a8704e79171c33bf.js +0 -1
- package/web/.next/static/chunks/d0cdb752198e0ce2.js +0 -1
- /package/web/.next/static/{HLY1lOE_eWQBTqZqPvvsU → ifBL824Rz9BwA5KgNAqe8}/_buildManifest.js +0 -0
- /package/web/.next/static/{HLY1lOE_eWQBTqZqPvvsU → ifBL824Rz9BwA5KgNAqe8}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{HLY1lOE_eWQBTqZqPvvsU → ifBL824Rz9BwA5KgNAqe8}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-agent-graph.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AAOpG,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"feature-agent-graph.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AAOpG,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AASlF,OAAO,EAAE,sBAAsB,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,cAAc,CAAC;IACzB,aAAa,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;CACjD;AA0HD;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,qBAAqB,GAAG,cAAc,EACtD,YAAY,CAAC,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAwEnC"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.js
CHANGED
|
@@ -11,7 +11,7 @@ import { createRepairNode } from './nodes/repair.node.js';
|
|
|
11
11
|
import { validateSpecAnalyze, validateSpecRequirements } from './nodes/schemas/spec.schema.js';
|
|
12
12
|
import { validateResearch } from './nodes/schemas/research.schema.js';
|
|
13
13
|
import { validatePlan, validateTasks } from './nodes/schemas/plan.schema.js';
|
|
14
|
-
import { readSpecFile, safeYamlLoad, createNodeLogger
|
|
14
|
+
import { readSpecFile, safeYamlLoad, createNodeLogger } from './nodes/node-helpers.js';
|
|
15
15
|
// Re-export state types for consumers
|
|
16
16
|
export { FeatureAgentAnnotation } from './state.js';
|
|
17
17
|
/**
|
|
@@ -54,18 +54,6 @@ function createPlanTasksValidator() {
|
|
|
54
54
|
const log = createNodeLogger('validate:plan+tasks');
|
|
55
55
|
return async (state) => {
|
|
56
56
|
log.activate();
|
|
57
|
-
// Skip validation when the successor phase (implement) is already completed.
|
|
58
|
-
// This proves validation already passed and the pipeline progressed beyond it.
|
|
59
|
-
// Same logic as createValidateNode's successorPhase guard.
|
|
60
|
-
if (getCompletedPhases(state.specDir).includes('implement')) {
|
|
61
|
-
log.info("Successor phase 'implement' already completed, skipping validation");
|
|
62
|
-
return {
|
|
63
|
-
lastValidationTarget: 'plan.yaml+tasks.yaml',
|
|
64
|
-
lastValidationErrors: [],
|
|
65
|
-
validationRetries: 0,
|
|
66
|
-
messages: ["[validate:plan+tasks] SKIP (successor 'implement' already completed)"],
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
57
|
log.info('Validating plan.yaml and tasks.yaml');
|
|
70
58
|
const allErrors = [];
|
|
71
59
|
// Validate plan.yaml
|
|
@@ -157,14 +145,9 @@ export function createFeatureAgentGraph(depsOrExecutor, checkpointer) {
|
|
|
157
145
|
.addNode('plan', createPlanNode(executor))
|
|
158
146
|
.addNode('implement', createImplementNode(executor))
|
|
159
147
|
// --- Validate nodes ---
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
// Using the successor (not the producer) avoids skipping validation when the
|
|
164
|
-
// producer ran successfully but validation itself failed.
|
|
165
|
-
.addNode('validate_spec_analyze', createValidateNode('spec.yaml', validateSpecAnalyze, 'requirements'))
|
|
166
|
-
.addNode('validate_spec_requirements', createValidateNode('spec.yaml', validateSpecRequirements, 'research'))
|
|
167
|
-
.addNode('validate_research', createValidateNode('research.yaml', validateResearch, 'plan'))
|
|
148
|
+
.addNode('validate_spec_analyze', createValidateNode('spec.yaml', validateSpecAnalyze))
|
|
149
|
+
.addNode('validate_spec_requirements', createValidateNode('spec.yaml', validateSpecRequirements))
|
|
150
|
+
.addNode('validate_research', createValidateNode('research.yaml', validateResearch))
|
|
168
151
|
.addNode('validate_plan_tasks', createPlanTasksValidator())
|
|
169
152
|
// --- Repair nodes ---
|
|
170
153
|
.addNode('repair_spec_analyze', createRepairNode('spec.yaml', executor))
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.d.ts
CHANGED
|
@@ -6,13 +6,7 @@ type SchemaValidator = (data: unknown) => ValidationResult;
|
|
|
6
6
|
*
|
|
7
7
|
* On success: resets validationRetries to 0, clears errors.
|
|
8
8
|
* On failure: increments validationRetries, sets errors for repair node.
|
|
9
|
-
*
|
|
10
|
-
* @param successorPhase - The phase that runs AFTER this validation passes.
|
|
11
|
-
* If provided, skip validation when the successor is already completed — this
|
|
12
|
-
* proves the validation already passed in a prior run and the pipeline progressed
|
|
13
|
-
* beyond it. Checking the successor (not the producer) avoids skipping validation
|
|
14
|
-
* when the producer ran but validation itself failed.
|
|
15
9
|
*/
|
|
16
|
-
export declare function createValidateNode(filename: string, schema: SchemaValidator
|
|
10
|
+
export declare function createValidateNode(filename: string, schema: SchemaValidator): (state: FeatureAgentState) => Promise<Partial<FeatureAgentState>>;
|
|
17
11
|
export {};
|
|
18
12
|
//# sourceMappingURL=validate.node.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"validate.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,gBAAgB,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,eAAe,GACtB,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAuDnE"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.js
CHANGED
|
@@ -1,36 +1,14 @@
|
|
|
1
|
-
import { readSpecFile, safeYamlLoad, createNodeLogger
|
|
1
|
+
import { readSpecFile, safeYamlLoad, createNodeLogger } from './node-helpers.js';
|
|
2
2
|
/**
|
|
3
3
|
* Factory that creates a validate node for a specific YAML file.
|
|
4
4
|
*
|
|
5
5
|
* On success: resets validationRetries to 0, clears errors.
|
|
6
6
|
* On failure: increments validationRetries, sets errors for repair node.
|
|
7
|
-
*
|
|
8
|
-
* @param successorPhase - The phase that runs AFTER this validation passes.
|
|
9
|
-
* If provided, skip validation when the successor is already completed — this
|
|
10
|
-
* proves the validation already passed in a prior run and the pipeline progressed
|
|
11
|
-
* beyond it. Checking the successor (not the producer) avoids skipping validation
|
|
12
|
-
* when the producer ran but validation itself failed.
|
|
13
7
|
*/
|
|
14
|
-
export function createValidateNode(filename, schema
|
|
8
|
+
export function createValidateNode(filename, schema) {
|
|
15
9
|
const log = createNodeLogger(`validate:${filename}`);
|
|
16
10
|
return async (state) => {
|
|
17
11
|
log.activate();
|
|
18
|
-
// Skip validation when the successor phase is already completed.
|
|
19
|
-
// This means: the validation already passed in a prior run AND the next phase
|
|
20
|
-
// ran successfully. On resume, LangGraph replays nodes from the last checkpoint.
|
|
21
|
-
// The producer node skips (via getCompletedPhases), but if we only checked the
|
|
22
|
-
// producer we'd also skip validation when it previously FAILED (since
|
|
23
|
-
// markPhaseComplete runs before validation). Checking the successor is safe:
|
|
24
|
-
// if the successor completed, this validation must have passed to get there.
|
|
25
|
-
if (successorPhase && getCompletedPhases(state.specDir).includes(successorPhase)) {
|
|
26
|
-
log.info(`Successor phase '${successorPhase}' already completed, skipping validation`);
|
|
27
|
-
return {
|
|
28
|
-
lastValidationTarget: filename,
|
|
29
|
-
lastValidationErrors: [],
|
|
30
|
-
validationRetries: 0,
|
|
31
|
-
messages: [`[validate:${filename}] SKIP (successor '${successorPhase}' already completed)`],
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
12
|
log.info(`Validating ${filename}`);
|
|
35
13
|
const content = readSpecFile(state.specDir, filename);
|
|
36
14
|
if (!content) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-feature-phase-timings.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-feature-phase-timings.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"get-feature-phase-timings.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-feature-phase-timings.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,KAAK,qBAAqB,GACtB;IAAE,OAAO,EAAE,eAAe,EAAE,CAAC;IAAC,iBAAiB,EAAE,qBAAqB,EAAE,CAAA;CAAE,GAC1E;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtB,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAsC9F"}
|
|
@@ -22,6 +22,8 @@ export async function getFeaturePhaseTimings(featureId) {
|
|
|
22
22
|
costUsd: t.costUsd != null ? Number(t.costUsd) : undefined,
|
|
23
23
|
numTurns: t.numTurns ?? undefined,
|
|
24
24
|
durationApiMs: t.durationApiMs != null ? Number(t.durationApiMs) : undefined,
|
|
25
|
+
exitCode: t.exitCode ?? undefined,
|
|
26
|
+
errorMessage: t.errorMessage ?? undefined,
|
|
25
27
|
}));
|
|
26
28
|
// Read rejection feedback from spec.yaml
|
|
27
29
|
const rejectionFeedback = await readRejectionFeedback(featureId);
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/activity-tab.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"activity-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/activity-tab.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACtB,MAAM,yCAAyC,CAAC;AAmEjD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iBAAiB,CAAC,EAAE,qBAAqB,EAAE,CAAC;CAC7C;AAmED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,eAAe,EAAE,EAC1B,QAAQ,CAAC,EAAE,qBAAqB,EAAE,GACjC,iBAAiB,EAAE,CAgErB;AA6BD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,gBAAgB,2CAqE3F"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useEffect, useRef } from 'react';
|
|
4
|
-
import { Loader2, AlertCircle, Clock, Zap, DollarSign } from 'lucide-react';
|
|
4
|
+
import { Loader2, AlertCircle, Clock, Zap, DollarSign, Play, RotateCcw, CheckCircle2, XCircle, Square, Ban, MessageSquare, Timer, ArrowDownToLine, ArrowUpFromLine, } from 'lucide-react';
|
|
5
5
|
import { InlineAttachments } from '../../common/inline-attachments/index.js';
|
|
6
6
|
import { formatDuration } from '../../../lib/format-duration.js';
|
|
7
7
|
/**
|
|
@@ -51,6 +51,13 @@ function formatTokens(count) {
|
|
|
51
51
|
return `${(count / 1_000).toFixed(1)}K`;
|
|
52
52
|
return String(count);
|
|
53
53
|
}
|
|
54
|
+
/** Format a timestamp to a short local time string (e.g. "10:05:30 AM"). */
|
|
55
|
+
function formatTimestamp(value) {
|
|
56
|
+
const d = value instanceof Date ? value : new Date(String(value));
|
|
57
|
+
if (Number.isNaN(d.getTime()))
|
|
58
|
+
return '';
|
|
59
|
+
return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
|
60
|
+
}
|
|
54
61
|
/** Format a USD cost with appropriate precision. */
|
|
55
62
|
function formatCost(usd) {
|
|
56
63
|
if (usd >= 1)
|
|
@@ -68,13 +75,48 @@ const NODE_TO_PHASE = {
|
|
|
68
75
|
merge: 'Merging',
|
|
69
76
|
};
|
|
70
77
|
const LIFECYCLE_EVENTS = {
|
|
71
|
-
'run:started': {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
'run:
|
|
78
|
+
'run:started': {
|
|
79
|
+
label: 'started',
|
|
80
|
+
colorClass: 'text-blue-600',
|
|
81
|
+
bgClass: 'bg-blue-50 dark:bg-blue-950/30',
|
|
82
|
+
icon: Play,
|
|
83
|
+
},
|
|
84
|
+
'run:resumed': {
|
|
85
|
+
label: 'resumed',
|
|
86
|
+
colorClass: 'text-blue-600',
|
|
87
|
+
bgClass: 'bg-blue-50 dark:bg-blue-950/30',
|
|
88
|
+
icon: RotateCcw,
|
|
89
|
+
},
|
|
90
|
+
'run:completed': {
|
|
91
|
+
label: 'completed',
|
|
92
|
+
colorClass: 'text-emerald-600',
|
|
93
|
+
bgClass: 'bg-emerald-50 dark:bg-emerald-950/30',
|
|
94
|
+
icon: CheckCircle2,
|
|
95
|
+
},
|
|
96
|
+
'run:failed': {
|
|
97
|
+
label: 'failed',
|
|
98
|
+
colorClass: 'text-red-600',
|
|
99
|
+
bgClass: 'bg-red-50 dark:bg-red-950/30',
|
|
100
|
+
icon: XCircle,
|
|
101
|
+
},
|
|
102
|
+
'run:stopped': {
|
|
103
|
+
label: 'stopped',
|
|
104
|
+
colorClass: 'text-amber-600',
|
|
105
|
+
bgClass: 'bg-amber-50 dark:bg-amber-950/30',
|
|
106
|
+
icon: Square,
|
|
107
|
+
},
|
|
108
|
+
'run:crashed': {
|
|
109
|
+
label: 'crashed',
|
|
110
|
+
colorClass: 'text-red-600',
|
|
111
|
+
bgClass: 'bg-red-50 dark:bg-red-950/30',
|
|
112
|
+
icon: XCircle,
|
|
113
|
+
},
|
|
114
|
+
'run:rejected': {
|
|
115
|
+
label: 'rejected',
|
|
116
|
+
colorClass: 'text-orange-600',
|
|
117
|
+
bgClass: 'bg-orange-50 dark:bg-orange-950/30',
|
|
118
|
+
icon: Ban,
|
|
119
|
+
},
|
|
78
120
|
};
|
|
79
121
|
function isLifecycleEvent(phase) {
|
|
80
122
|
return phase.startsWith('run:');
|
|
@@ -146,6 +188,26 @@ export function buildLifecycleTimeline(timings, feedback) {
|
|
|
146
188
|
}
|
|
147
189
|
return iterations;
|
|
148
190
|
}
|
|
191
|
+
/** Determine the outcome status of an iteration */
|
|
192
|
+
function getIterationOutcome(iteration) {
|
|
193
|
+
const lastLifecycle = [...iteration.timings].reverse().find((t) => isLifecycleEvent(t.phase));
|
|
194
|
+
if (!lastLifecycle)
|
|
195
|
+
return null;
|
|
196
|
+
switch (lastLifecycle.phase) {
|
|
197
|
+
case 'run:rejected':
|
|
198
|
+
return { label: 'Rejected', colorClass: 'text-orange-600', dotClass: 'bg-orange-500' };
|
|
199
|
+
case 'run:completed':
|
|
200
|
+
return { label: 'Completed', colorClass: 'text-emerald-600', dotClass: 'bg-emerald-500' };
|
|
201
|
+
case 'run:failed':
|
|
202
|
+
return { label: 'Failed', colorClass: 'text-red-600', dotClass: 'bg-red-500' };
|
|
203
|
+
case 'run:crashed':
|
|
204
|
+
return { label: 'Crashed', colorClass: 'text-red-600', dotClass: 'bg-red-500' };
|
|
205
|
+
case 'run:stopped':
|
|
206
|
+
return { label: 'Stopped', colorClass: 'text-amber-600', dotClass: 'bg-amber-500' };
|
|
207
|
+
default:
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
149
211
|
/* ---------------------------------------------------------------------------
|
|
150
212
|
* Component
|
|
151
213
|
* ------------------------------------------------------------------------- */
|
|
@@ -155,10 +217,10 @@ export function ActivityTab({ timings, loading, error, rejectionFeedback }) {
|
|
|
155
217
|
return (_jsx("div", { "data-testid": "activity-tab-loading", className: "flex items-center justify-center p-8", children: _jsx(Loader2, { className: "text-muted-foreground h-6 w-6 animate-spin" }) }));
|
|
156
218
|
}
|
|
157
219
|
if (error) {
|
|
158
|
-
return (_jsxs("div", { className: "flex items-center gap-2 p-4 text-
|
|
220
|
+
return (_jsxs("div", { className: "flex items-center gap-2 p-4 text-base text-red-600", children: [_jsx(AlertCircle, { className: "h-4 w-4 shrink-0" }), _jsx("span", { children: error })] }));
|
|
159
221
|
}
|
|
160
222
|
if (!timings || timings.length === 0) {
|
|
161
|
-
return (_jsxs("div", { className: "flex flex-col items-center justify-center gap-2 p-8", children: [_jsx(Clock, { className: "text-muted-foreground h-8 w-8" }), _jsx("p", { className: "text-muted-foreground text-
|
|
223
|
+
return (_jsxs("div", { className: "flex flex-col items-center justify-center gap-2 p-8", children: [_jsx(Clock, { className: "text-muted-foreground h-8 w-8" }), _jsx("p", { className: "text-muted-foreground text-base", children: "No activity recorded yet" })] }));
|
|
162
224
|
}
|
|
163
225
|
const nodeTimings = timings.filter((t) => !isLifecycleEvent(t.phase));
|
|
164
226
|
const maxDurationMs = Math.max(...nodeTimings.map((t) => getEffectiveDuration(t, now)), ...nodeTimings.map((t) => t.approvalWaitMs ?? 0), 0);
|
|
@@ -169,44 +231,70 @@ export function ActivityTab({ timings, loading, error, rejectionFeedback }) {
|
|
|
169
231
|
const totalInputTokens = nodeTimings.reduce((sum, t) => sum + (t.inputTokens ?? 0), 0);
|
|
170
232
|
const totalOutputTokens = nodeTimings.reduce((sum, t) => sum + (t.outputTokens ?? 0), 0);
|
|
171
233
|
const totalCostUsd = nodeTimings.reduce((sum, t) => sum + (t.costUsd ?? 0), 0);
|
|
172
|
-
return (_jsxs("div", { className: "flex flex-col gap-
|
|
234
|
+
return (_jsxs("div", { className: "flex flex-col gap-3 p-4", children: [_jsx("div", { "data-testid": "activity-timings", className: "flex flex-col gap-3", children: iterations.map((iteration) => (_jsx(IterationGroup, { iteration: iteration, showHeader: hasMultipleIterations, maxDurationMs: maxDurationMs, now: now }, iteration.number))) }), totalExecMs > 0 ? (_jsx(SummaryTotals, { totalExecMs: totalExecMs, totalWaitMs: totalWaitMs, totalInputTokens: totalInputTokens, totalOutputTokens: totalOutputTokens, totalCostUsd: totalCostUsd })) : null] }));
|
|
173
235
|
}
|
|
174
236
|
/* ---------------------------------------------------------------------------
|
|
175
237
|
* Iteration group — one cycle of work
|
|
176
238
|
* ------------------------------------------------------------------------- */
|
|
177
239
|
function IterationGroup({ iteration, showHeader, maxDurationMs, now, }) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
240
|
+
const outcome = getIterationOutcome(iteration);
|
|
241
|
+
return (_jsxs("div", { "data-testid": `iteration-${iteration.number}`, className: "border-border/50 bg-card/50 flex flex-col overflow-hidden rounded-lg border", children: [showHeader ? (_jsxs("div", { className: "bg-muted/30 border-border/50 flex items-center justify-between border-b px-3 py-1.5", children: [_jsxs("span", { className: "text-muted-foreground text-sm font-semibold tracking-wide", children: ["Iteration ", iteration.number] }), outcome ? (_jsxs("span", { className: `flex items-center gap-1 text-xs font-medium ${outcome.colorClass}`, children: [_jsx("span", { className: `inline-block h-1.5 w-1.5 rounded-full ${outcome.dotClass}` }), outcome.label] })) : null] })) : null, _jsxs("div", { className: "relative flex flex-col", children: [_jsx("div", { className: "bg-border/60 absolute top-4 bottom-4 left-[21.5px] w-px" }), iteration.timings.map((t, idx) => {
|
|
242
|
+
if (isLifecycleEvent(t.phase)) {
|
|
243
|
+
const isRejection = t.phase === 'run:rejected';
|
|
244
|
+
const isFailure = t.phase === 'run:failed' || t.phase === 'run:crashed' || t.phase === 'run:stopped';
|
|
245
|
+
// For failures, find the last phase with an error message in this iteration
|
|
246
|
+
let message;
|
|
247
|
+
if (isRejection) {
|
|
248
|
+
message = iteration.rejectionMessage;
|
|
249
|
+
}
|
|
250
|
+
else if (isFailure) {
|
|
251
|
+
const lastErrorPhase = [...iteration.timings]
|
|
252
|
+
.reverse()
|
|
253
|
+
.find((p) => !isLifecycleEvent(p.phase) && p.errorMessage);
|
|
254
|
+
message = lastErrorPhase?.errorMessage ?? t.errorMessage;
|
|
255
|
+
}
|
|
256
|
+
return (_jsx(LifecycleEventRow, { timing: t, message: message, attachments: isRejection ? iteration.rejectionAttachments : undefined, isFirst: idx === 0, isLast: idx === iteration.timings.length - 1 }, `${t.agentRunId}-${t.phase}-${t.startedAt}`));
|
|
257
|
+
}
|
|
258
|
+
return (_jsx(NodeTimingRow, { timing: t, maxDurationMs: maxDurationMs, now: now }, `${t.agentRunId}-${t.phase}-${t.startedAt}`));
|
|
259
|
+
})] })] }));
|
|
186
260
|
}
|
|
187
261
|
/* ---------------------------------------------------------------------------
|
|
188
262
|
* Row components
|
|
189
263
|
* ------------------------------------------------------------------------- */
|
|
190
|
-
function LifecycleEventRow({ timing, message, attachments, }) {
|
|
264
|
+
function LifecycleEventRow({ timing, message, attachments, isFirst, isLast, }) {
|
|
191
265
|
const event = LIFECYCLE_EVENTS[timing.phase];
|
|
192
266
|
if (!event)
|
|
193
267
|
return null;
|
|
194
268
|
const hasAttachments = attachments && attachments.length > 0;
|
|
195
|
-
|
|
269
|
+
const Icon = event.icon;
|
|
270
|
+
return (_jsxs("div", { className: `relative flex flex-col gap-1 px-3 ${isFirst ? 'pt-2' : 'pt-1'} ${isLast ? 'pb-2' : 'pb-1'}`, children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: `relative z-10 flex h-5 w-5 shrink-0 items-center justify-center rounded-full ${event.bgClass}`, children: _jsx(Icon, { className: `h-3 w-3 ${event.colorClass}` }) }), _jsx("span", { className: `text-sm font-medium ${event.colorClass}`, children: event.label }), timing.startedAt &&
|
|
271
|
+
!(typeof timing.startedAt === 'string' && timing.startedAt.startsWith('synthetic')) ? (_jsx("span", { className: "text-muted-foreground/60 ml-auto text-xs tabular-nums", children: formatTimestamp(String(timing.startedAt)) })) : null] }), message
|
|
272
|
+
? (() => {
|
|
273
|
+
const isError = timing.phase === 'run:failed' ||
|
|
274
|
+
timing.phase === 'run:crashed' ||
|
|
275
|
+
timing.phase === 'run:stopped';
|
|
276
|
+
return (_jsxs("div", { className: `ml-[26px] flex items-start gap-1.5 rounded-md px-2 py-1.5 ${isError
|
|
277
|
+
? 'bg-red-50/50 dark:bg-red-950/20'
|
|
278
|
+
: 'bg-orange-50/50 dark:bg-orange-950/20'}`, children: [isError ? (_jsx(AlertCircle, { className: "mt-0.5 h-3.5 w-3.5 shrink-0 text-red-400" })) : (_jsx(MessageSquare, { className: "mt-0.5 h-3.5 w-3.5 shrink-0 text-orange-400" })), _jsxs("span", { "data-testid": isError ? 'error-message-text' : 'rejection-feedback-text', className: "text-muted-foreground text-xs leading-relaxed italic", children: ["\u2014 ", message] })] }));
|
|
279
|
+
})()
|
|
280
|
+
: null, hasAttachments ? (_jsx("div", { "data-testid": "rejection-feedback-attachments", className: "ml-[26px]", children: _jsx(InlineAttachments, { text: "", attachmentPaths: attachments }) })) : null] }));
|
|
196
281
|
}
|
|
197
282
|
function NodeTimingRow({ timing, maxDurationMs, now, }) {
|
|
283
|
+
const base = timing.phase.includes(':') ? timing.phase.split(':')[0] : timing.phase;
|
|
198
284
|
const suffix = timing.phase.includes(':') ? timing.phase.split(':')[1] : null;
|
|
199
285
|
const isSubPhase = suffix !== null;
|
|
200
|
-
// Distinguish implementation sub-phases (phase-1, phase-2) from rejection retries (2, 3)
|
|
201
286
|
const isImplPhase = suffix?.startsWith('phase-') ?? false;
|
|
287
|
+
const baseName = NODE_TO_PHASE[base] ?? base;
|
|
202
288
|
const label = isImplPhase
|
|
203
289
|
? `Phase ${suffix.replace('phase-', '')}`
|
|
204
290
|
: suffix !== null
|
|
205
|
-
?
|
|
206
|
-
:
|
|
291
|
+
? `${baseName} #${suffix}`
|
|
292
|
+
: baseName;
|
|
207
293
|
const durationMs = getEffectiveDuration(timing, now);
|
|
208
|
-
const barPercent = maxDurationMs > 0 ? Math.max(2, (durationMs / maxDurationMs) * 100) : 2;
|
|
209
294
|
const isRunning = !timing.completedAt && !!timing.startedAt;
|
|
295
|
+
// Running phases get a minimum 15% bar so they're always visually prominent
|
|
296
|
+
const minPercent = isRunning ? 15 : 2;
|
|
297
|
+
const barPercent = maxDurationMs > 0 ? Math.max(minPercent, (durationMs / maxDurationMs) * 100) : minPercent;
|
|
210
298
|
const barColorClass = timing.completedAt
|
|
211
299
|
? isImplPhase
|
|
212
300
|
? 'bg-emerald-400'
|
|
@@ -217,17 +305,28 @@ function NodeTimingRow({ timing, maxDurationMs, now, }) {
|
|
|
217
305
|
const totalTokens = timing.inputTokens != null || timing.outputTokens != null
|
|
218
306
|
? (timing.inputTokens ?? 0) + (timing.outputTokens ?? 0)
|
|
219
307
|
: null;
|
|
220
|
-
return (_jsxs("div", { className:
|
|
308
|
+
return (_jsxs("div", { className: `relative flex flex-col gap-0.5 px-3 py-1.5 ${isSubPhase ? 'ml-4' : ''}`, children: [_jsxs("div", { "data-testid": `timing-bar-${timing.phase}`, className: "flex items-center gap-2", children: [_jsx("div", { className: "relative z-10 flex h-5 w-5 shrink-0 items-center justify-center", children: _jsx("div", { className: `rounded-full ${isRunning ? 'h-3 w-3 animate-pulse' : 'h-2.5 w-2.5'} ${isRunning
|
|
309
|
+
? 'bg-blue-500'
|
|
310
|
+
: timing.completedAt
|
|
311
|
+
? 'bg-emerald-500'
|
|
312
|
+
: 'bg-muted-foreground/30'}` }) }), _jsx("span", { className: `w-28 shrink-0 truncate text-sm font-medium ${isSubPhase ? 'text-muted-foreground' : 'text-foreground/80'}`, children: label }), _jsx("div", { className: `bg-muted relative min-w-0 flex-1 overflow-hidden rounded-full ${isSubPhase ? 'h-1.5' : 'h-2'}`, children: isRunning ? (_jsx("div", { className: "absolute inset-0 rounded-full bg-blue-500/30", style: {
|
|
313
|
+
backgroundImage: 'linear-gradient(90deg, transparent 0%, rgb(59 130 246) 50%, transparent 100%)',
|
|
314
|
+
backgroundSize: '200% 100%',
|
|
315
|
+
animation: 'shimmer 1.5s ease-in-out infinite',
|
|
316
|
+
} })) : (_jsx("div", { className: `h-full rounded-full transition-all duration-300 ${barColorClass}`, style: { width: `${Math.min(barPercent, 100)}%` } })) }), _jsx("span", { className: "text-muted-foreground w-14 shrink-0 text-right text-sm font-medium tabular-nums", children: formatDuration(durationMs) })] }), _jsxs("div", { className: "ml-[28px] flex items-center gap-3 text-xs", children: [timing.startedAt ? (_jsx("span", { className: "text-muted-foreground/60 tabular-nums", children: formatTimestamp(timing.startedAt) })) : null, totalTokens != null && totalTokens > 0 ? (_jsxs("span", { className: "text-muted-foreground/70 inline-flex items-center gap-0.5", children: [_jsx(Zap, { className: "h-3 w-3 opacity-50" }), formatTokens(totalTokens)] })) : null, timing.costUsd != null && timing.costUsd > 0 ? (_jsxs("span", { className: "text-muted-foreground/70 inline-flex items-center gap-0.5", children: [_jsx(DollarSign, { className: "h-3 w-3 opacity-50" }), formatCost(timing.costUsd)] })) : null] }), timing.approvalWaitMs != null && timing.approvalWaitMs > 0 ? (_jsx(ApprovalWaitRow, { timing: timing, maxDurationMs: maxDurationMs })) : null] }));
|
|
221
317
|
}
|
|
222
318
|
function ApprovalWaitRow({ timing, maxDurationMs, }) {
|
|
223
319
|
const waitMs = timing.approvalWaitMs ?? 0;
|
|
224
320
|
const barPercent = maxDurationMs > 0 ? Math.max(2, (waitMs / maxDurationMs) * 100) : 2;
|
|
225
|
-
return (_jsxs("div", { "data-testid": `approval-wait-${timing.phase}`, className: "flex items-center gap-2
|
|
321
|
+
return (_jsxs("div", { "data-testid": `approval-wait-${timing.phase}`, className: "ml-[26px] flex items-center gap-2 rounded-md bg-amber-50/50 px-1.5 py-1 dark:bg-amber-950/20", children: [_jsx(Timer, { className: "h-3.5 w-3.5 shrink-0 text-amber-500" }), _jsx("span", { className: "text-muted-foreground w-16 shrink-0 text-xs", children: "approval" }), _jsx("div", { className: "bg-muted h-1.5 min-w-0 flex-1 overflow-hidden rounded-full", children: _jsx("div", { className: "h-full rounded-full bg-amber-500", style: { width: `${Math.min(barPercent, 100)}%` } }) }), _jsx("span", { className: "text-muted-foreground w-14 shrink-0 text-right text-xs tabular-nums", children: formatDuration(waitMs) })] }));
|
|
226
322
|
}
|
|
227
323
|
function SummaryTotals({ totalExecMs, totalWaitMs, totalInputTokens, totalOutputTokens, totalCostUsd, }) {
|
|
228
324
|
const totalTokens = totalInputTokens + totalOutputTokens;
|
|
229
|
-
return (_jsxs("div", { "data-testid": "activity-summary", className: "border-border flex flex-col gap-
|
|
325
|
+
return (_jsxs("div", { "data-testid": "activity-summary", className: "border-border bg-card/30 flex flex-col gap-2 rounded-lg border p-3", children: [_jsx("div", { className: "text-muted-foreground mb-1 text-xs font-semibold tracking-wider uppercase", children: "Summary" }), _jsxs("div", { className: "grid grid-cols-2 gap-x-4 gap-y-3", children: [_jsx(SummaryCell, { icon: Clock, label: "Execution", value: formatDuration(totalExecMs) }), _jsx(SummaryCell, { icon: Timer, label: "Wait", value: totalWaitMs > 0 ? formatDuration(totalWaitMs) : 'n/a' }), _jsx(SummaryCell, { icon: Clock, label: "Wall-clock", value: totalWaitMs > 0
|
|
326
|
+
? formatDuration(totalExecMs + totalWaitMs)
|
|
327
|
+
: formatDuration(totalExecMs) }), _jsx(SummaryCell, { icon: DollarSign, label: "Cost", value: totalCostUsd > 0 ? formatCost(totalCostUsd) : 'n/a' }), _jsxs("div", { className: "col-span-2 flex flex-col gap-0.5", children: [_jsxs("span", { className: "text-muted-foreground flex items-center gap-1 text-xs", children: [_jsx(Zap, { className: "h-3 w-3 opacity-40" }), "Tokens"] }), totalTokens > 0 ? (_jsxs("span", { className: "flex items-center gap-2.5 text-sm tabular-nums", children: [_jsx("span", { children: formatTokens(totalTokens) }), _jsxs("span", { className: "text-muted-foreground flex items-center gap-3 text-xs", title: "Input tokens / Output tokens", children: [_jsxs("span", { className: "flex items-center gap-0.5", children: [_jsx(ArrowDownToLine, { className: "h-3 w-3 text-blue-500 opacity-60" }), formatTokens(totalInputTokens)] }), _jsxs("span", { className: "flex items-center gap-0.5", children: [_jsx(ArrowUpFromLine, { className: "h-3 w-3 text-emerald-500 opacity-60" }), formatTokens(totalOutputTokens)] })] })] })) : (_jsx("span", { className: "text-muted-foreground/40 text-sm italic tabular-nums", children: "n/a" }))] })] })] }));
|
|
230
328
|
}
|
|
231
|
-
function
|
|
232
|
-
|
|
329
|
+
function SummaryCell({ icon: Icon, label, value, className = '', }) {
|
|
330
|
+
const isNA = value === 'n/a';
|
|
331
|
+
return (_jsxs("div", { className: `flex flex-col gap-0.5 ${className}`, children: [_jsxs("span", { className: "text-muted-foreground flex items-center gap-1 text-xs", children: [_jsx(Icon, { className: "h-3 w-3 opacity-40" }), label] }), _jsx("span", { className: `text-sm tabular-nums ${isNA ? 'text-muted-foreground/40 italic' : ''}`, children: value })] }));
|
|
233
332
|
}
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-drawer-tabs.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAS9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAMxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAQ9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uDAAuD,CAAC;AA8C3F,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,gFAAgF;IAChF,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,mFAAmF;IACnF,SAAS,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAGzC,OAAO,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,QAAQ,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,WAAW,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAGjD,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC5E,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAwBD,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,SAAS,EACT,UAAU,EACV,MAAM,EACN,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,SAAS,GACV,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"feature-drawer-tabs.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAS9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAMxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAQ9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uDAAuD,CAAC;AA8C3F,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,gFAAgF;IAChF,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,mFAAmF;IACnF,SAAS,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAGzC,OAAO,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,QAAQ,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,WAAW,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAGjD,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC5E,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAwBD,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,SAAS,EACT,UAAU,EACV,MAAM,EACN,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,SAAS,GACV,EAAE,sBAAsB,2CA8UxB"}
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.js
CHANGED
|
@@ -220,6 +220,19 @@ export function FeatureDrawerTabs({ featureNode, featureId, initialTab, urlTab,
|
|
|
220
220
|
refreshTab(current);
|
|
221
221
|
}
|
|
222
222
|
}, [sseEvents, featureId, refreshTab]);
|
|
223
|
+
// Poll activity data while the feature is actively running.
|
|
224
|
+
// SSE events only fire on state transitions (phase completed, lifecycle changed),
|
|
225
|
+
// so during a long-running phase there are no events and the data goes stale.
|
|
226
|
+
// Poll every 5s when the feature is in a working state to keep data fresh.
|
|
227
|
+
const isFeatureActive = featureNode.state === 'running' || featureNode.state === 'creating';
|
|
228
|
+
useEffect(() => {
|
|
229
|
+
if (!isFeatureActive)
|
|
230
|
+
return;
|
|
231
|
+
const interval = setInterval(() => {
|
|
232
|
+
refreshTab('activity');
|
|
233
|
+
}, 5000);
|
|
234
|
+
return () => clearInterval(interval);
|
|
235
|
+
}, [isFeatureActive, refreshTab]);
|
|
223
236
|
const handleTabChange = useCallback((value) => {
|
|
224
237
|
const tab = value;
|
|
225
238
|
isUserInteraction.current = true;
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-tab-data-fetch.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.ts"],"names":[],"mappings":"AAIA,yDAAyD;AACzD,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,OAAO;IACnC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,iEAAiE;AACjE,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAExE,kDAAkD;AAClD,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,IAAI,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AAElE,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,MAAM;IACrD,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC1B,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,iDAAiD;IACjD,UAAU,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAMD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAC9C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,GACvB,qBAAqB,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"use-tab-data-fetch.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.ts"],"names":[],"mappings":"AAIA,yDAAyD;AACzD,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,OAAO;IACnC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,iEAAiE;AACjE,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAExE,kDAAkD;AAClD,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,IAAI,MAAM,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AAElE,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,MAAM;IACrD,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC1B,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,iDAAiD;IACjD,UAAU,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAMD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAC9C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,GACvB,qBAAqB,CAAC,CAAC,CAAC,CA2G1B"}
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.js
CHANGED
|
@@ -54,11 +54,16 @@ export function useTabDataFetch(featureId, fetchers) {
|
|
|
54
54
|
const currentFeatureId = featureIdRef.current;
|
|
55
55
|
if (!fetcher)
|
|
56
56
|
return;
|
|
57
|
+
// Only show loading spinner when there's no existing data.
|
|
58
|
+
// On refresh (data already present), keep showing stale data while fetching
|
|
59
|
+
// to avoid flickering the entire tab on every poll cycle.
|
|
57
60
|
if (mountedRef.current) {
|
|
58
|
-
setTabStates((prev) =>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
setTabStates((prev) => {
|
|
62
|
+
const hasData = prev[tab]?.data !== null;
|
|
63
|
+
if (hasData)
|
|
64
|
+
return prev; // Keep stale data visible — no loading flash
|
|
65
|
+
return { ...prev, [tab]: { ...prev[tab], loading: true, error: null } };
|
|
66
|
+
});
|
|
62
67
|
}
|
|
63
68
|
try {
|
|
64
69
|
const data = await fetcher(currentFeatureId);
|
|
@@ -71,11 +76,15 @@ export function useTabDataFetch(featureId, fetchers) {
|
|
|
71
76
|
}
|
|
72
77
|
catch (error) {
|
|
73
78
|
if (mountedRef.current) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
[tab]
|
|
78
|
-
|
|
79
|
+
setTabStates((prev) => {
|
|
80
|
+
const message = error instanceof Error ? error.message : 'Failed to fetch tab data';
|
|
81
|
+
// On refresh failure, keep existing data instead of clearing it
|
|
82
|
+
const existingData = prev[tab]?.data ?? null;
|
|
83
|
+
return {
|
|
84
|
+
...prev,
|
|
85
|
+
[tab]: { data: existingData, loading: false, error: existingData ? null : message },
|
|
86
|
+
};
|
|
87
|
+
});
|
|
79
88
|
}
|
|
80
89
|
}
|
|
81
90
|
}, []);
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAuB5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAuB5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CA2UzF"}
|