@shepai/cli 1.37.0 → 1.37.1
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-worker.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +1 -3
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.js +2 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.js +4 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +2 -1
- package/dist/src/presentation/cli/commands/feat/show.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/show.command.js +21 -2
- 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/cache/.previewinfo +1 -1
- package/web/.next/cache/.rscinfo +1 -1
- package/web/.next/cache/config.json +3 -3
- 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/_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/chunks/ssr/[root-of-the-server]__f12b60be._.js +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 +1 -1
- package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__f12b60be._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +1 -1
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- /package/web/.next/static/{zoaB52IxAh-lSl8Qreb0t → UemLwbVtqCGOm4FHNOp05}/_buildManifest.js +0 -0
- /package/web/.next/static/{zoaB52IxAh-lSl8Qreb0t → UemLwbVtqCGOm4FHNOp05}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{zoaB52IxAh-lSl8Qreb0t → UemLwbVtqCGOm4FHNOp05}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-agent-worker.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAEH,OAAO,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"feature-agent-worker.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAEH,OAAO,kBAAkB,CAAC;AAqB1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA6C1D;AAgCD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA0J/D"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js
CHANGED
|
@@ -19,7 +19,7 @@ import { AgentRunStatus } from '../../../../domain/generated/output.js';
|
|
|
19
19
|
import { initializeSettings } from '../../../services/settings.service.js';
|
|
20
20
|
import { InitializeSettingsUseCase } from '../../../../application/use-cases/settings/initialize-settings.use-case.js';
|
|
21
21
|
import { setHeartbeatContext } from './heartbeat.js';
|
|
22
|
-
import { setPhaseTimingContext
|
|
22
|
+
import { setPhaseTimingContext } from './phase-timing-context.js';
|
|
23
23
|
import { setLifecycleContext } from './lifecycle-context.js';
|
|
24
24
|
import { generatePrYaml } from './nodes/pr-yaml-generator.js';
|
|
25
25
|
/**
|
|
@@ -193,8 +193,6 @@ export async function runWorker(args) {
|
|
|
193
193
|
// Check if graph was interrupted (human-in-the-loop approval needed)
|
|
194
194
|
const interruptPayload = result.__interrupt__;
|
|
195
195
|
if (interruptPayload && interruptPayload.length > 0) {
|
|
196
|
-
// Record approval wait start on the last phase timing
|
|
197
|
-
await recordApprovalWaitStart(getLastTimingId());
|
|
198
196
|
const now = new Date();
|
|
199
197
|
await runRepository.updateStatus(args.runId, AgentRunStatus.waitingApproval, {
|
|
200
198
|
updatedAt: now,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"implement.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"implement.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAqErD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,IAG5C,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAgL7E"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/implement.node.js
CHANGED
|
@@ -12,7 +12,7 @@ import { join } from 'node:path';
|
|
|
12
12
|
import { interrupt, isGraphBubbleUp } from '@langchain/langgraph';
|
|
13
13
|
import { createNodeLogger, readSpecFile, buildExecutorOptions, shouldInterrupt, safeYamlLoad, retryExecute, getCompletedPhases, markPhaseComplete, } from './node-helpers.js';
|
|
14
14
|
import { reportNodeStart } from '../heartbeat.js';
|
|
15
|
-
import { recordPhaseStart, recordPhaseEnd } from '../phase-timing-context.js';
|
|
15
|
+
import { recordPhaseStart, recordPhaseEnd, recordApprovalWaitStart, } from '../phase-timing-context.js';
|
|
16
16
|
import { updateNodeLifecycle } from '../lifecycle-context.js';
|
|
17
17
|
import { buildImplementPhasePrompt, } from './prompts/implement.prompt.js';
|
|
18
18
|
/**
|
|
@@ -145,6 +145,7 @@ export function createImplementNode(executor) {
|
|
|
145
145
|
await recordPhaseEnd(implementTimingId, Date.now() - startTime);
|
|
146
146
|
if (shouldInterrupt('implement', state.approvalGates)) {
|
|
147
147
|
log.info('Interrupting for human approval');
|
|
148
|
+
await recordApprovalWaitStart(implementTimingId);
|
|
148
149
|
interrupt({
|
|
149
150
|
node: 'implement',
|
|
150
151
|
message: `Implementation complete: ${totalTasks} tasks across ${totalPhases} phases. Approve to finish.`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iEAAiE,CAAC;AACrG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;
|
|
1
|
+
{"version":3,"file":"merge.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iEAAiE,CAAC;AACrG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;AAWlH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,aAAa,CAAC;IAC5B,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IAChF,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;CACpE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,IAGnC,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAwJ7E"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.js
CHANGED
|
@@ -13,7 +13,7 @@ import { interrupt, isGraphBubbleUp } from '@langchain/langgraph';
|
|
|
13
13
|
import { SdlcLifecycle, PrStatus } from '../../../../../domain/generated/output.js';
|
|
14
14
|
import { createNodeLogger, shouldInterrupt } from './node-helpers.js';
|
|
15
15
|
import { reportNodeStart } from '../heartbeat.js';
|
|
16
|
-
import { recordPhaseStart, recordPhaseEnd } from '../phase-timing-context.js';
|
|
16
|
+
import { recordPhaseStart, recordPhaseEnd, recordApprovalWaitStart, } from '../phase-timing-context.js';
|
|
17
17
|
import { updateNodeLifecycle } from '../lifecycle-context.js';
|
|
18
18
|
/**
|
|
19
19
|
* Factory that creates the merge node function.
|
|
@@ -82,6 +82,9 @@ export function createMergeNode(deps) {
|
|
|
82
82
|
// --- Step 4: Merge approval gate ---
|
|
83
83
|
if (shouldInterrupt('merge', state.approvalGates)) {
|
|
84
84
|
log.info('Interrupting for merge approval');
|
|
85
|
+
// Close timing before interrupt so the pre-approval work has a duration
|
|
86
|
+
await recordPhaseEnd(mergeTimingId, Date.now() - startTime);
|
|
87
|
+
await recordApprovalWaitStart(mergeTimingId);
|
|
85
88
|
const diffSummary = await gitPrService.getPrDiffSummary(cwd, baseBranch);
|
|
86
89
|
interrupt({
|
|
87
90
|
node: 'merge',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-helpers.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,+DAA+D,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"node-helpers.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,+DAA+D,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AASrD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM;kBAE/B,MAAM,GAAG,IAAI;mBAIZ,MAAM,GAAG,IAAI;EAK/B;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE7D;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMtE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,qBAAqB,CAMpF;AAeD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAQrD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAS3F;AAMD,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG,mBAAmB,GAAG,eAAe,GAAG,SAAS,CAAC;AAMhG;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,CAKjE;AAED,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,qBAAqB,EAC9B,SAAS,CAAC,EAAE,YAAY,GACvB,OAAO,CAAC,oBAAoB,CAAC,CA6B/B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAW5D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAwB1F;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,UAAU,KAAK,MAAM,GACjE,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAiFnE"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js
CHANGED
|
@@ -9,7 +9,7 @@ import { readFileSync, writeFileSync } from 'node:fs';
|
|
|
9
9
|
import { join } from 'node:path';
|
|
10
10
|
import { interrupt, isGraphBubbleUp } from '@langchain/langgraph';
|
|
11
11
|
import { reportNodeStart } from '../heartbeat.js';
|
|
12
|
-
import { recordPhaseStart, recordPhaseEnd } from '../phase-timing-context.js';
|
|
12
|
+
import { recordPhaseStart, recordPhaseEnd, recordApprovalWaitStart, } from '../phase-timing-context.js';
|
|
13
13
|
import { updateNodeLifecycle } from '../lifecycle-context.js';
|
|
14
14
|
/**
|
|
15
15
|
* Create a scoped logger that prefixes messages with the node name.
|
|
@@ -245,6 +245,7 @@ export function executeNode(nodeName, executor, buildPrompt) {
|
|
|
245
245
|
// Human-in-the-loop: interrupt after node execution for review
|
|
246
246
|
if (shouldInterrupt(nodeName, state.approvalGates)) {
|
|
247
247
|
log.info('Interrupting for human approval');
|
|
248
|
+
await recordApprovalWaitStart(timingId);
|
|
248
249
|
interrupt({
|
|
249
250
|
node: nodeName,
|
|
250
251
|
result: result.result.slice(0, 500),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"show.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/show.command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmFpC,wBAAgB,iBAAiB,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"show.command.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/cli/commands/feat/show.command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmFpC,wBAAgB,iBAAiB,IAAI,OAAO,CAwP3C"}
|
|
@@ -131,7 +131,9 @@ export function createShowCommand() {
|
|
|
131
131
|
if (t.completedAt && t.durationMs != null) {
|
|
132
132
|
const ms = Number(t.durationMs);
|
|
133
133
|
const secs = (ms / 1000).toFixed(1);
|
|
134
|
-
const barLen = maxDurationMs > 0
|
|
134
|
+
const barLen = maxDurationMs > 0
|
|
135
|
+
? Math.min(MAX_BAR, Math.max(1, Math.round((ms / maxDurationMs) * MAX_BAR)))
|
|
136
|
+
: 1;
|
|
135
137
|
const bar = `${colors.success('\u2588'.repeat(barLen))}${colors.muted('\u2591'.repeat(MAX_BAR - barLen))}`;
|
|
136
138
|
lines.push(`${label} ${bar} ${secs}s`);
|
|
137
139
|
}
|
|
@@ -151,13 +153,30 @@ export function createShowCommand() {
|
|
|
151
153
|
}
|
|
152
154
|
// Show approval wait time under gated phases
|
|
153
155
|
if (t.approvalWaitMs != null && Number(t.approvalWaitMs) > 0) {
|
|
156
|
+
// Completed approval wait - show final duration
|
|
154
157
|
const waitMs = Number(t.approvalWaitMs);
|
|
155
158
|
const waitSecs = (waitMs / 1000).toFixed(1);
|
|
156
159
|
const waitLabel = ' \u21b3 approval'.padEnd(16);
|
|
157
|
-
const waitBarLen = maxDurationMs > 0
|
|
160
|
+
const waitBarLen = maxDurationMs > 0
|
|
161
|
+
? Math.min(MAX_BAR, Math.max(1, Math.round((waitMs / maxDurationMs) * MAX_BAR)))
|
|
162
|
+
: 1;
|
|
158
163
|
const waitBar = `${colors.warning('\u2588'.repeat(waitBarLen))}${colors.muted('\u2591'.repeat(MAX_BAR - waitBarLen))}`;
|
|
159
164
|
lines.push(`${waitLabel} ${waitBar} ${waitSecs}s`);
|
|
160
165
|
}
|
|
166
|
+
else if (isLast && isWaiting && t.waitingApprovalAt) {
|
|
167
|
+
// Live approval wait - show elapsed time
|
|
168
|
+
const waitStart = t.waitingApprovalAt instanceof Date
|
|
169
|
+
? t.waitingApprovalAt.getTime()
|
|
170
|
+
: Number(t.waitingApprovalAt);
|
|
171
|
+
const waitElapsedMs = Math.max(0, Date.now() - waitStart);
|
|
172
|
+
const waitSecs = (waitElapsedMs / 1000).toFixed(1);
|
|
173
|
+
const waitLabel = ' \u21b3 approval'.padEnd(16);
|
|
174
|
+
const waitBarLen = maxDurationMs > 0
|
|
175
|
+
? Math.min(MAX_BAR, Math.max(1, Math.round((waitElapsedMs / maxDurationMs) * MAX_BAR)))
|
|
176
|
+
: 1;
|
|
177
|
+
const waitBar = `${colors.warning('\u2588'.repeat(waitBarLen))}${colors.muted('\u2591'.repeat(MAX_BAR - waitBarLen))}`;
|
|
178
|
+
lines.push(`${waitLabel} ${waitBar} ${waitSecs}s (waiting)`);
|
|
179
|
+
}
|
|
161
180
|
}
|
|
162
181
|
// Summary totals
|
|
163
182
|
const totalExecMs = timings.reduce((sum, t) => sum + (t.durationMs != null ? Number(t.durationMs) : 0), 0);
|