@shepai/cli 1.122.1-pr392.8612976 → 1.122.1-pr393.8ed1eb1
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 +21 -4
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.d.ts +7 -1
- 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 +24 -2
- 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 +31 -109
- 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 +0 -13
- 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 +9 -18
- 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/[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]__9f155c0e._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9f155c0e._.js.map +1 -0
- 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/_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/_2f6f48b8._.js +1 -1
- package/web/.next/server/chunks/ssr/_2f6f48b8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_aa2a163b._.js +3 -0
- package/web/.next/server/chunks/ssr/{_8f86134e._.js.map → _aa2a163b._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_4add9b32._.js → _c22f1789._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_4add9b32._.js.map → _c22f1789._.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/_e780bf76._.js +3 -0
- package/web/.next/server/chunks/ssr/_e780bf76._.js.map +1 -0
- 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_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/0d2af96e64960ef5.css +1 -0
- package/web/.next/static/chunks/{069f58f292c9a367.js → 0e929482605bf7a3.js} +1 -1
- package/web/.next/static/chunks/{b594cfa83ec8e3a2.js → 11725323dd771a46.js} +1 -1
- package/web/.next/static/chunks/{034865d710214279.js → 130a5a47de39ce2a.js} +2 -2
- package/web/.next/static/chunks/{244cc6630f2e89bc.js → 24e75f8b85c6b407.js} +1 -1
- package/web/.next/static/chunks/4562ee849ea13c3a.js +1 -0
- package/web/.next/static/chunks/bade06227dd989fe.js +1 -0
- package/web/.next/static/chunks/c3766a94e1f1a737.js +1 -0
- package/web/.next/static/chunks/{56988de8873d91af.js → d12d9c2b63ba55ae.js} +1 -1
- package/web/.next/static/chunks/{265136c24ace4a21.js → d5df2b1ccce98bac.js} +1 -1
- package/web/.next/static/chunks/{f9a9aa7ae61e1970.js → e0792df86c0d1199.js} +1 -1
- package/web/.next/static/chunks/{94914bb9bb05e4ff.js → f787295ccd547994.js} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f646b99a._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f646b99a._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_8f86134e._.js +0 -3
- package/web/.next/server/chunks/ssr/_b47480f5._.js +0 -3
- package/web/.next/server/chunks/ssr/_b47480f5._.js.map +0 -1
- package/web/.next/static/chunks/3911a7175044e784.js +0 -1
- package/web/.next/static/chunks/7bc84f759ffdbe35.css +0 -1
- package/web/.next/static/chunks/cc143b8e68876dd6.js +0 -1
- package/web/.next/static/chunks/f30b72428e344008.js +0 -1
- /package/web/.next/static/{hFXA8ZILtXYiolGrD00nW → Ccr3PUpkfiWUbqNMEsiOS}/_buildManifest.js +0 -0
- /package/web/.next/static/{hFXA8ZILtXYiolGrD00nW → Ccr3PUpkfiWUbqNMEsiOS}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{hFXA8ZILtXYiolGrD00nW → Ccr3PUpkfiWUbqNMEsiOS}/_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;AAclF,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;AAwID;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,qBAAqB,GAAG,cAAc,EACtD,YAAY,CAAC,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAgFnC"}
|
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 } from './nodes/node-helpers.js';
|
|
14
|
+
import { readSpecFile, safeYamlLoad, createNodeLogger, getCompletedPhases, } from './nodes/node-helpers.js';
|
|
15
15
|
// Re-export state types for consumers
|
|
16
16
|
export { FeatureAgentAnnotation } from './state.js';
|
|
17
17
|
/**
|
|
@@ -54,6 +54,18 @@ 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
|
+
}
|
|
57
69
|
log.info('Validating plan.yaml and tasks.yaml');
|
|
58
70
|
const allErrors = [];
|
|
59
71
|
// Validate plan.yaml
|
|
@@ -145,9 +157,14 @@ export function createFeatureAgentGraph(depsOrExecutor, checkpointer) {
|
|
|
145
157
|
.addNode('plan', createPlanNode(executor))
|
|
146
158
|
.addNode('implement', createImplementNode(executor))
|
|
147
159
|
// --- Validate nodes ---
|
|
148
|
-
|
|
149
|
-
.
|
|
150
|
-
|
|
160
|
+
// Each validate node receives its SUCCESSOR phase name (the phase that runs
|
|
161
|
+
// after validation passes). On resume, validation is skipped only when the
|
|
162
|
+
// successor is already completed — proving this validation already passed.
|
|
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'))
|
|
151
168
|
.addNode('validate_plan_tasks', createPlanTasksValidator())
|
|
152
169
|
// --- Repair nodes ---
|
|
153
170
|
.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,7 +6,13 @@ 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.
|
|
9
15
|
*/
|
|
10
|
-
export declare function createValidateNode(filename: string, schema: SchemaValidator): (state: FeatureAgentState) => Promise<Partial<FeatureAgentState>>;
|
|
16
|
+
export declare function createValidateNode(filename: string, schema: SchemaValidator, successorPhase?: string): (state: FeatureAgentState) => Promise<Partial<FeatureAgentState>>;
|
|
11
17
|
export {};
|
|
12
18
|
//# 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;AAQhE,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,gBAAgB,CAAC;AAE3D;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,eAAe,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAyEnE"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/validate.node.js
CHANGED
|
@@ -1,14 +1,36 @@
|
|
|
1
|
-
import { readSpecFile, safeYamlLoad, createNodeLogger } from './node-helpers.js';
|
|
1
|
+
import { readSpecFile, safeYamlLoad, createNodeLogger, getCompletedPhases, } 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.
|
|
7
13
|
*/
|
|
8
|
-
export function createValidateNode(filename, schema) {
|
|
14
|
+
export function createValidateNode(filename, schema, successorPhase) {
|
|
9
15
|
const log = createNodeLogger(`validate:${filename}`);
|
|
10
16
|
return async (state) => {
|
|
11
17
|
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
|
+
}
|
|
12
34
|
log.info(`Validating ${filename}`);
|
|
13
35
|
const content = readSpecFile(state.specDir, filename);
|
|
14
36
|
if (!content) {
|
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":"AAIA,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACtB,MAAM,yCAAyC,CAAC;AA4DjD,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;AA6BD;;;;;;;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;AAMD,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 } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useEffect, useRef } from 'react';
|
|
4
|
-
import { Loader2, AlertCircle, Clock, Zap, DollarSign
|
|
4
|
+
import { Loader2, AlertCircle, Clock, Zap, DollarSign } 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,13 +51,6 @@ 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
|
-
}
|
|
61
54
|
/** Format a USD cost with appropriate precision. */
|
|
62
55
|
function formatCost(usd) {
|
|
63
56
|
if (usd >= 1)
|
|
@@ -75,48 +68,13 @@ const NODE_TO_PHASE = {
|
|
|
75
68
|
merge: 'Merging',
|
|
76
69
|
};
|
|
77
70
|
const LIFECYCLE_EVENTS = {
|
|
78
|
-
'run:started': {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
},
|
|
84
|
-
'run:
|
|
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
|
-
},
|
|
71
|
+
'run:started': { label: 'started', colorClass: 'text-blue-600' },
|
|
72
|
+
'run:resumed': { label: 'resumed', colorClass: 'text-blue-600' },
|
|
73
|
+
'run:completed': { label: 'completed', colorClass: 'text-emerald-600' },
|
|
74
|
+
'run:failed': { label: 'failed', colorClass: 'text-red-600' },
|
|
75
|
+
'run:stopped': { label: 'stopped', colorClass: 'text-amber-600' },
|
|
76
|
+
'run:crashed': { label: 'crashed', colorClass: 'text-red-600' },
|
|
77
|
+
'run:rejected': { label: 'rejected', colorClass: 'text-orange-600' },
|
|
120
78
|
};
|
|
121
79
|
function isLifecycleEvent(phase) {
|
|
122
80
|
return phase.startsWith('run:');
|
|
@@ -188,26 +146,6 @@ export function buildLifecycleTimeline(timings, feedback) {
|
|
|
188
146
|
}
|
|
189
147
|
return iterations;
|
|
190
148
|
}
|
|
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
|
-
}
|
|
211
149
|
/* ---------------------------------------------------------------------------
|
|
212
150
|
* Component
|
|
213
151
|
* ------------------------------------------------------------------------- */
|
|
@@ -217,10 +155,10 @@ export function ActivityTab({ timings, loading, error, rejectionFeedback }) {
|
|
|
217
155
|
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" }) }));
|
|
218
156
|
}
|
|
219
157
|
if (error) {
|
|
220
|
-
return (_jsxs("div", { className: "flex items-center gap-2 p-4 text-
|
|
158
|
+
return (_jsxs("div", { className: "flex items-center gap-2 p-4 text-sm text-red-600", children: [_jsx(AlertCircle, { className: "h-4 w-4 shrink-0" }), _jsx("span", { children: error })] }));
|
|
221
159
|
}
|
|
222
160
|
if (!timings || timings.length === 0) {
|
|
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-
|
|
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-sm", children: "No activity recorded yet" })] }));
|
|
224
162
|
}
|
|
225
163
|
const nodeTimings = timings.filter((t) => !isLifecycleEvent(t.phase));
|
|
226
164
|
const maxDurationMs = Math.max(...nodeTimings.map((t) => getEffectiveDuration(t, now)), ...nodeTimings.map((t) => t.approvalWaitMs ?? 0), 0);
|
|
@@ -231,49 +169,44 @@ export function ActivityTab({ timings, loading, error, rejectionFeedback }) {
|
|
|
231
169
|
const totalInputTokens = nodeTimings.reduce((sum, t) => sum + (t.inputTokens ?? 0), 0);
|
|
232
170
|
const totalOutputTokens = nodeTimings.reduce((sum, t) => sum + (t.outputTokens ?? 0), 0);
|
|
233
171
|
const totalCostUsd = nodeTimings.reduce((sum, t) => sum + (t.costUsd ?? 0), 0);
|
|
234
|
-
return (_jsxs("div", { className: "flex flex-col gap-
|
|
172
|
+
return (_jsxs("div", { className: "flex flex-col gap-4 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] }));
|
|
235
173
|
}
|
|
236
174
|
/* ---------------------------------------------------------------------------
|
|
237
175
|
* Iteration group — one cycle of work
|
|
238
176
|
* ------------------------------------------------------------------------- */
|
|
239
177
|
function IterationGroup({ iteration, showHeader, maxDurationMs, now, }) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
178
|
+
return (_jsxs("div", { "data-testid": `iteration-${iteration.number}`, className: "flex flex-col gap-1.5", children: [showHeader ? (_jsxs("div", { className: "text-muted-foreground text-xs font-medium", children: ["Iteration ", iteration.number] })) : null, iteration.timings.map((t) => {
|
|
179
|
+
if (isLifecycleEvent(t.phase)) {
|
|
180
|
+
// For run:rejected, the message comes from the iteration, not a separate map
|
|
181
|
+
const isRejection = t.phase === 'run:rejected';
|
|
182
|
+
return (_jsx(LifecycleEventRow, { timing: t, message: isRejection ? iteration.rejectionMessage : undefined, attachments: isRejection ? iteration.rejectionAttachments : undefined }, `${t.agentRunId}-${t.phase}-${t.startedAt}`));
|
|
183
|
+
}
|
|
184
|
+
return (_jsx(NodeTimingRow, { timing: t, maxDurationMs: maxDurationMs, now: now }, `${t.agentRunId}-${t.phase}-${t.startedAt}`));
|
|
185
|
+
})] }));
|
|
248
186
|
}
|
|
249
187
|
/* ---------------------------------------------------------------------------
|
|
250
188
|
* Row components
|
|
251
189
|
* ------------------------------------------------------------------------- */
|
|
252
|
-
function LifecycleEventRow({ timing, message, attachments,
|
|
190
|
+
function LifecycleEventRow({ timing, message, attachments, }) {
|
|
253
191
|
const event = LIFECYCLE_EVENTS[timing.phase];
|
|
254
192
|
if (!event)
|
|
255
193
|
return null;
|
|
256
194
|
const hasAttachments = attachments && attachments.length > 0;
|
|
257
|
-
|
|
258
|
-
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 &&
|
|
259
|
-
!(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 ? (_jsxs("div", { className: "ml-[26px] flex items-start gap-1.5 rounded-md bg-orange-50/50 px-2 py-1.5 dark:bg-orange-950/20", children: [_jsx(MessageSquare, { className: "mt-0.5 h-3.5 w-3.5 shrink-0 text-orange-400" }), _jsxs("span", { "data-testid": "rejection-feedback-text", className: "text-muted-foreground text-xs leading-relaxed italic", children: ["\u2014 ", message] })] })) : null, hasAttachments ? (_jsx("div", { "data-testid": "rejection-feedback-attachments", className: "ml-[26px]", children: _jsx(InlineAttachments, { text: "", attachmentPaths: attachments }) })) : null] }));
|
|
195
|
+
return (_jsxs("div", { className: `text-xs ${event.colorClass}`, children: [_jsx("span", { children: event.label }), message ? (_jsxs("span", { "data-testid": "rejection-feedback-text", className: "text-muted-foreground ml-2 font-normal italic", children: ["\u2014 ", message] })) : null, hasAttachments ? (_jsx("div", { "data-testid": "rejection-feedback-attachments", className: "mt-1.5 ml-2", children: _jsx(InlineAttachments, { text: "", attachmentPaths: attachments }) })) : null] }));
|
|
260
196
|
}
|
|
261
197
|
function NodeTimingRow({ timing, maxDurationMs, now, }) {
|
|
262
|
-
const base = timing.phase.includes(':') ? timing.phase.split(':')[0] : timing.phase;
|
|
263
198
|
const suffix = timing.phase.includes(':') ? timing.phase.split(':')[1] : null;
|
|
264
199
|
const isSubPhase = suffix !== null;
|
|
200
|
+
// Distinguish implementation sub-phases (phase-1, phase-2) from rejection retries (2, 3)
|
|
265
201
|
const isImplPhase = suffix?.startsWith('phase-') ?? false;
|
|
266
|
-
const baseName = NODE_TO_PHASE[base] ?? base;
|
|
267
202
|
const label = isImplPhase
|
|
268
203
|
? `Phase ${suffix.replace('phase-', '')}`
|
|
269
204
|
: suffix !== null
|
|
270
|
-
?
|
|
271
|
-
:
|
|
205
|
+
? `retry #${suffix}`
|
|
206
|
+
: (NODE_TO_PHASE[timing.phase] ?? timing.phase);
|
|
272
207
|
const durationMs = getEffectiveDuration(timing, now);
|
|
208
|
+
const barPercent = maxDurationMs > 0 ? Math.max(2, (durationMs / maxDurationMs) * 100) : 2;
|
|
273
209
|
const isRunning = !timing.completedAt && !!timing.startedAt;
|
|
274
|
-
// Running phases get a minimum 15% bar so they're always visually prominent
|
|
275
|
-
const minPercent = isRunning ? 15 : 2;
|
|
276
|
-
const barPercent = maxDurationMs > 0 ? Math.max(minPercent, (durationMs / maxDurationMs) * 100) : minPercent;
|
|
277
210
|
const barColorClass = timing.completedAt
|
|
278
211
|
? isImplPhase
|
|
279
212
|
? 'bg-emerald-400'
|
|
@@ -284,28 +217,17 @@ function NodeTimingRow({ timing, maxDurationMs, now, }) {
|
|
|
284
217
|
const totalTokens = timing.inputTokens != null || timing.outputTokens != null
|
|
285
218
|
? (timing.inputTokens ?? 0) + (timing.outputTokens ?? 0)
|
|
286
219
|
: null;
|
|
287
|
-
return (_jsxs("div", { className:
|
|
288
|
-
? 'bg-blue-500'
|
|
289
|
-
: timing.completedAt
|
|
290
|
-
? 'bg-emerald-500'
|
|
291
|
-
: '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: {
|
|
292
|
-
backgroundImage: 'linear-gradient(90deg, transparent 0%, rgb(59 130 246) 50%, transparent 100%)',
|
|
293
|
-
backgroundSize: '200% 100%',
|
|
294
|
-
animation: 'shimmer 1.5s ease-in-out infinite',
|
|
295
|
-
} })) : (_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] }));
|
|
220
|
+
return (_jsxs("div", { className: isSubPhase ? 'flex flex-col gap-1 pl-6' : 'flex flex-col gap-1', children: [_jsxs("div", { "data-testid": `timing-bar-${timing.phase}`, className: "flex items-center gap-2", children: [_jsx("span", { className: `text-muted-foreground shrink-0 text-xs ${isSubPhase ? 'w-18' : 'w-24'}`, children: label }), _jsx("div", { className: `bg-muted min-w-0 flex-1 overflow-hidden rounded-full ${isSubPhase ? 'h-2.5' : 'h-3'}`, children: _jsx("div", { className: `h-full rounded-full ${barColorClass}${isRunning ? 'animate-pulse' : ''}`, style: { width: `${Math.min(barPercent, 100)}%` } }) }), _jsx("span", { className: "text-muted-foreground w-10 shrink-0 text-right text-xs tabular-nums", children: formatDuration(durationMs) }), _jsx("span", { className: "text-muted-foreground w-12 shrink-0 text-right text-[10px] tabular-nums", children: totalTokens != null && totalTokens > 0 ? (_jsxs("span", { className: "inline-flex items-center gap-0.5", children: [_jsx(Zap, { className: "h-2 w-2 opacity-50" }), formatTokens(totalTokens)] })) : null }), _jsx("span", { className: "text-muted-foreground w-14 shrink-0 text-right text-[10px] tabular-nums", children: timing.costUsd != null && timing.costUsd > 0 ? (_jsxs("span", { className: "inline-flex items-center gap-0.5", children: [_jsx(DollarSign, { className: "h-2 w-2 opacity-50" }), formatCost(timing.costUsd)] })) : null })] }), timing.approvalWaitMs != null && timing.approvalWaitMs > 0 ? (_jsx(ApprovalWaitRow, { timing: timing, maxDurationMs: maxDurationMs })) : null] }));
|
|
296
221
|
}
|
|
297
222
|
function ApprovalWaitRow({ timing, maxDurationMs, }) {
|
|
298
223
|
const waitMs = timing.approvalWaitMs ?? 0;
|
|
299
224
|
const barPercent = maxDurationMs > 0 ? Math.max(2, (waitMs / maxDurationMs) * 100) : 2;
|
|
300
|
-
return (_jsxs("div", { "data-testid": `approval-wait-${timing.phase}`, className: "
|
|
225
|
+
return (_jsxs("div", { "data-testid": `approval-wait-${timing.phase}`, className: "flex items-center gap-2 pl-4", children: [_jsx("span", { className: "text-muted-foreground w-20 shrink-0 text-xs", children: "approval" }), _jsx("div", { className: "bg-muted h-2.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-10 shrink-0 text-right text-xs tabular-nums", children: formatDuration(waitMs) }), _jsx("span", { className: "w-12 shrink-0" }), _jsx("span", { className: "w-14 shrink-0" })] }));
|
|
301
226
|
}
|
|
302
227
|
function SummaryTotals({ totalExecMs, totalWaitMs, totalInputTokens, totalOutputTokens, totalCostUsd, }) {
|
|
303
228
|
const totalTokens = totalInputTokens + totalOutputTokens;
|
|
304
|
-
return (_jsxs("div", { "data-testid": "activity-summary", className: "border-border
|
|
305
|
-
? formatDuration(totalExecMs + totalWaitMs)
|
|
306
|
-
: 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" }))] })] })] }));
|
|
229
|
+
return (_jsxs("div", { "data-testid": "activity-summary", className: "border-border flex flex-col gap-1.5 border-t pt-3", children: [_jsx(SummaryRow, { label: "Total execution", value: formatDuration(totalExecMs) }), totalWaitMs > 0 ? (_jsxs(_Fragment, { children: [_jsx(SummaryRow, { label: "Total wait", value: formatDuration(totalWaitMs) }), _jsx(SummaryRow, { label: "Total wall-clock", value: formatDuration(totalExecMs + totalWaitMs) })] })) : null, totalTokens > 0 ? (_jsx(SummaryRow, { label: "Total tokens", value: `${formatTokens(totalTokens)} (${formatTokens(totalInputTokens)} in · ${formatTokens(totalOutputTokens)} out)` })) : null, totalCostUsd > 0 ? _jsx(SummaryRow, { label: "Total cost", value: formatCost(totalCostUsd) }) : null] }));
|
|
307
230
|
}
|
|
308
|
-
function
|
|
309
|
-
|
|
310
|
-
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 })] }));
|
|
231
|
+
function SummaryRow({ label, value }) {
|
|
232
|
+
return (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: label }), _jsx("span", { className: "text-xs font-medium", children: value })] }));
|
|
311
233
|
}
|
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,2CAiUxB"}
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.js
CHANGED
|
@@ -220,19 +220,6 @@ 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]);
|
|
236
223
|
const handleTabChange = useCallback((value) => {
|
|
237
224
|
const tab = value;
|
|
238
225
|
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,CAmG1B"}
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.js
CHANGED
|
@@ -54,16 +54,11 @@ 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.
|
|
60
57
|
if (mountedRef.current) {
|
|
61
|
-
setTabStates((prev) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return { ...prev, [tab]: { ...prev[tab], loading: true, error: null } };
|
|
66
|
-
});
|
|
58
|
+
setTabStates((prev) => ({
|
|
59
|
+
...prev,
|
|
60
|
+
[tab]: { ...prev[tab], loading: true, error: null },
|
|
61
|
+
}));
|
|
67
62
|
}
|
|
68
63
|
try {
|
|
69
64
|
const data = await fetcher(currentFeatureId);
|
|
@@ -76,15 +71,11 @@ export function useTabDataFetch(featureId, fetchers) {
|
|
|
76
71
|
}
|
|
77
72
|
catch (error) {
|
|
78
73
|
if (mountedRef.current) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
...prev,
|
|
85
|
-
[tab]: { data: existingData, loading: false, error: existingData ? null : message },
|
|
86
|
-
};
|
|
87
|
-
});
|
|
74
|
+
const message = error instanceof Error ? error.message : 'Failed to fetch tab data';
|
|
75
|
+
setTabStates((prev) => ({
|
|
76
|
+
...prev,
|
|
77
|
+
[tab]: { data: null, loading: false, error: message },
|
|
78
|
+
}));
|
|
88
79
|
}
|
|
89
80
|
}
|
|
90
81
|
}, []);
|