@shepai/cli 1.47.0 → 1.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apis/json-schema/ApprovalGateDefaults.yaml +26 -0
- package/apis/json-schema/Feature.yaml +3 -0
- package/apis/json-schema/Repository.yaml +16 -0
- package/apis/json-schema/Settings.yaml +5 -0
- package/apis/json-schema/WorkflowConfig.yaml +4 -20
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts +17 -0
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/worktree-service.interface.d.ts +11 -1
- package/dist/packages/core/src/application/ports/output/services/worktree-service.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts +3 -1
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +11 -4
- package/dist/packages/core/src/application/use-cases/features/get-plan-artifact.use-case.d.ts +19 -0
- package/dist/packages/core/src/application/use-cases/features/get-plan-artifact.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/features/get-plan-artifact.use-case.js +52 -0
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +5 -0
- 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 +2 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge.node.d.ts +2 -0
- 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 +10 -3
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.js +15 -7
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts +2 -0
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +41 -0
- package/dist/packages/core/src/infrastructure/services/git/worktree.service.d.ts +2 -1
- package/dist/packages/core/src/infrastructure/services/git/worktree.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/worktree.service.js +29 -4
- package/dist/src/presentation/cli/ui/messages.d.ts.map +1 -1
- package/dist/src/presentation/cli/ui/messages.js +1 -7
- package/dist/src/presentation/web/app/actions/get-merge-review-data.d.ts +7 -0
- package/dist/src/presentation/web/app/actions/get-merge-review-data.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/get-merge-review-data.js +49 -0
- package/dist/src/presentation/web/app/page.d.ts.map +1 -1
- package/dist/src/presentation/web/app/page.js +1 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.js +8 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts +1 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.js +22 -1
- package/dist/src/presentation/web/components/common/merge-review/index.d.ts +4 -0
- package/dist/src/presentation/web/components/common/merge-review/index.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/merge-review/index.js +2 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts +75 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review-config.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review-config.js +1 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review-drawer.d.ts +3 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review-drawer.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review-drawer.js +7 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts +3 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review.js +36 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.d.ts +32 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review.stories.js +165 -0
- 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 +55 -1
- package/dist/src/presentation/web/components/features/control-center/control-center.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center.stories.js +15 -0
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +37 -15
- 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/.tsbuildinfo +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/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/page/server-reference-manifest.json +39 -24
- package/web/.next/server/app/page.js +1 -1
- package/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +4 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js +9 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
- package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/_3ac3601c._.js → server/chunks/ssr/_1fafa9db._.js} +2 -2
- package/web/.next/server/chunks/ssr/_1fafa9db._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.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 +40 -25
- 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/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +39 -24
- package/web/.next/standalone/src/presentation/web/.next/server/app/page.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +4 -4
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__19d52794._.js +9 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
- package/web/.next/{server/chunks/ssr/_3ac3601c._.js → standalone/src/presentation/web/.next/server/chunks/ssr/_1fafa9db._.js} +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_ed0934e5._.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 +40 -25
- package/web/.next/standalone/src/presentation/web/app/actions/get-merge-review-data.ts +64 -0
- package/web/.next/standalone/src/presentation/web/app/page.tsx +1 -0
- package/web/.next/standalone/src/presentation/web/components/common/feature-node/feature-node.stories.tsx +23 -1
- package/web/.next/standalone/src/presentation/web/components/common/feature-node/feature-node.tsx +6 -1
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/index.ts +7 -0
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review-config.ts +81 -0
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review-drawer.tsx +34 -0
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.stories.tsx +240 -0
- package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.tsx +252 -0
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +82 -1
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center.stories.tsx +15 -0
- package/web/.next/standalone/src/presentation/web/components/features/control-center/use-control-center-state.ts +47 -17
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/static/chunks/{9f8e71029fb04681.js → 0da7a9860fa6ae05.js} +2 -2
- package/web/.next/static/chunks/22f30ce91a3c79c1.js +1 -0
- package/web/.next/static/chunks/66378a6c055c4e67.js +10 -0
- package/web/.next/static/chunks/8668962d3e682263.css +2 -0
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d6d75c22._.js +0 -9
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d6d75c22._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_3ac3601c._.js.map +0 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__d6d75c22._.js +0 -9
- package/web/.next/static/chunks/779c99975c85389e.js +0 -10
- package/web/.next/static/chunks/83ff3b6bbee54bce.js +0 -1
- package/web/.next/static/chunks/b7b7abe79e05b229.css +0 -2
- /package/web/.next/static/{wQ3vPV9I8JeacVNyp4HFg → 1kZFDMQ0i-Y8dy1KkHlzv}/_buildManifest.js +0 -0
- /package/web/.next/static/{wQ3vPV9I8JeacVNyp4HFg → 1kZFDMQ0i-Y8dy1KkHlzv}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{wQ3vPV9I8JeacVNyp4HFg → 1kZFDMQ0i-Y8dy1KkHlzv}/_ssgManifest.js +0 -0
package/web/.next/standalone/src/presentation/web/components/common/merge-review/merge-review.tsx
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import {
|
|
5
|
+
CheckCircle2,
|
|
6
|
+
ExternalLink,
|
|
7
|
+
GitMerge,
|
|
8
|
+
Loader2,
|
|
9
|
+
XCircle,
|
|
10
|
+
AlertTriangle,
|
|
11
|
+
FileDiff,
|
|
12
|
+
GitCommitHorizontal,
|
|
13
|
+
GitBranch,
|
|
14
|
+
ArrowRight,
|
|
15
|
+
Layers,
|
|
16
|
+
Send,
|
|
17
|
+
} from 'lucide-react';
|
|
18
|
+
import { CiStatus } from '@shepai/core/domain/generated/output';
|
|
19
|
+
import { Badge } from '@/components/ui/badge';
|
|
20
|
+
import { Button } from '@/components/ui/button';
|
|
21
|
+
import { Input } from '@/components/ui/input';
|
|
22
|
+
import type { MergeReviewProps, MergeReviewPhase } from './merge-review-config';
|
|
23
|
+
|
|
24
|
+
function CiStatusBadge({ status }: { status: CiStatus }) {
|
|
25
|
+
switch (status) {
|
|
26
|
+
case CiStatus.Success:
|
|
27
|
+
return (
|
|
28
|
+
<Badge className="border-transparent bg-green-50 text-green-700 hover:bg-green-50">
|
|
29
|
+
<CheckCircle2 className="mr-1 h-3.5 w-3.5" />
|
|
30
|
+
Passing
|
|
31
|
+
</Badge>
|
|
32
|
+
);
|
|
33
|
+
case CiStatus.Pending:
|
|
34
|
+
return (
|
|
35
|
+
<Badge className="border-transparent bg-yellow-50 text-yellow-700 hover:bg-yellow-50">
|
|
36
|
+
<Loader2 className="mr-1 h-3.5 w-3.5 animate-spin" />
|
|
37
|
+
Pending
|
|
38
|
+
</Badge>
|
|
39
|
+
);
|
|
40
|
+
case CiStatus.Failure:
|
|
41
|
+
return (
|
|
42
|
+
<Badge className="border-transparent bg-red-50 text-red-700 hover:bg-red-50">
|
|
43
|
+
<XCircle className="mr-1 h-3.5 w-3.5" />
|
|
44
|
+
Failing
|
|
45
|
+
</Badge>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function PhaseList({ phases }: { phases: MergeReviewPhase[] }) {
|
|
51
|
+
return (
|
|
52
|
+
<div className="border-border rounded-lg border">
|
|
53
|
+
<div className="px-4 py-3">
|
|
54
|
+
<div className="mb-3 flex items-center gap-2">
|
|
55
|
+
<Layers className="text-muted-foreground h-4 w-4" />
|
|
56
|
+
<span className="text-foreground text-xs font-semibold">Implementation Phases</span>
|
|
57
|
+
</div>
|
|
58
|
+
<ol className="space-y-2">
|
|
59
|
+
{phases.map((phase, i) => (
|
|
60
|
+
<li key={phase.id} className="flex items-start gap-2.5">
|
|
61
|
+
<span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-emerald-100 text-[10px] font-bold text-emerald-700">
|
|
62
|
+
{i + 1}
|
|
63
|
+
</span>
|
|
64
|
+
<div className="min-w-0">
|
|
65
|
+
<span className="text-foreground text-xs font-medium">{phase.name}</span>
|
|
66
|
+
{phase.description ? (
|
|
67
|
+
<p className="text-muted-foreground mt-0.5 text-[11px] leading-relaxed">
|
|
68
|
+
{phase.description}
|
|
69
|
+
</p>
|
|
70
|
+
) : null}
|
|
71
|
+
</div>
|
|
72
|
+
</li>
|
|
73
|
+
))}
|
|
74
|
+
</ol>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function MergeReview({ data, onApprove, onRefine, isProcessing = false }: MergeReviewProps) {
|
|
81
|
+
const { pr, diffSummary, phases, branch, warning } = data;
|
|
82
|
+
const [chatInput, setChatInput] = useState('');
|
|
83
|
+
|
|
84
|
+
function handleSubmit(e: { preventDefault: () => void }) {
|
|
85
|
+
e.preventDefault();
|
|
86
|
+
const text = chatInput.trim();
|
|
87
|
+
if (!text) return;
|
|
88
|
+
onRefine(text);
|
|
89
|
+
setChatInput('');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div className="flex h-full flex-col">
|
|
94
|
+
<div className="flex-1 space-y-4 overflow-y-auto p-4">
|
|
95
|
+
{/* Header */}
|
|
96
|
+
<div className="flex items-start gap-3">
|
|
97
|
+
<div className="mt-1.5 h-2.5 w-2.5 shrink-0 rounded-full bg-emerald-500" />
|
|
98
|
+
<div className="flex-1">
|
|
99
|
+
<h2 className="text-foreground text-sm font-bold">Merge Review</h2>
|
|
100
|
+
<p className="text-muted-foreground mt-1 text-xs leading-relaxed">
|
|
101
|
+
{pr
|
|
102
|
+
? 'Review the pull request details and approve to merge.'
|
|
103
|
+
: 'Review the changes and approve to merge.'}
|
|
104
|
+
</p>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
{/* Branch merge direction (GitHub-like) */}
|
|
109
|
+
{branch ? (
|
|
110
|
+
<div className="border-border rounded-lg border">
|
|
111
|
+
<div className="flex items-center gap-2 px-4 py-3">
|
|
112
|
+
<GitBranch className="text-muted-foreground h-4 w-4 shrink-0" />
|
|
113
|
+
<Badge variant="secondary" className="font-mono text-[11px]">
|
|
114
|
+
{branch.source}
|
|
115
|
+
</Badge>
|
|
116
|
+
<ArrowRight className="text-muted-foreground h-3.5 w-3.5 shrink-0" />
|
|
117
|
+
<Badge variant="outline" className="font-mono text-[11px]">
|
|
118
|
+
{branch.target}
|
|
119
|
+
</Badge>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
) : null}
|
|
123
|
+
|
|
124
|
+
{/* PR metadata card */}
|
|
125
|
+
{pr ? (
|
|
126
|
+
<div className="border-border rounded-lg border">
|
|
127
|
+
<div className="space-y-3 px-4 py-3">
|
|
128
|
+
{/* PR number + link */}
|
|
129
|
+
<div className="flex items-center justify-between">
|
|
130
|
+
<a
|
|
131
|
+
href={pr.url}
|
|
132
|
+
target="_blank"
|
|
133
|
+
rel="noopener noreferrer"
|
|
134
|
+
className="text-primary flex items-center gap-1.5 text-sm font-semibold underline underline-offset-2"
|
|
135
|
+
>
|
|
136
|
+
PR #{pr.number}
|
|
137
|
+
<ExternalLink className="h-3.5 w-3.5" />
|
|
138
|
+
</a>
|
|
139
|
+
<Badge variant="outline" className="text-xs">
|
|
140
|
+
{pr.status}
|
|
141
|
+
</Badge>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
{/* CI status */}
|
|
145
|
+
{pr.ciStatus ? (
|
|
146
|
+
<div className="flex items-center justify-between">
|
|
147
|
+
<span className="text-muted-foreground text-xs font-medium">CI Status</span>
|
|
148
|
+
<CiStatusBadge status={pr.ciStatus} />
|
|
149
|
+
</div>
|
|
150
|
+
) : null}
|
|
151
|
+
|
|
152
|
+
{/* Commit hash */}
|
|
153
|
+
{pr.commitHash ? (
|
|
154
|
+
<div className="flex items-center justify-between">
|
|
155
|
+
<span className="text-muted-foreground text-xs font-medium">Commit</span>
|
|
156
|
+
<div className="flex items-center gap-1.5">
|
|
157
|
+
<GitCommitHorizontal className="text-muted-foreground h-3.5 w-3.5" />
|
|
158
|
+
<code className="bg-muted text-foreground rounded-md px-1.5 py-0.5 font-mono text-[11px]">
|
|
159
|
+
{pr.commitHash.slice(0, 7)}
|
|
160
|
+
</code>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
) : null}
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
) : null}
|
|
167
|
+
|
|
168
|
+
{/* Diff summary */}
|
|
169
|
+
{diffSummary ? (
|
|
170
|
+
<div className="border-border rounded-lg border">
|
|
171
|
+
<div className="px-4 py-3">
|
|
172
|
+
<div className="mb-3 flex items-center gap-2">
|
|
173
|
+
<FileDiff className="text-muted-foreground h-4 w-4" />
|
|
174
|
+
<span className="text-foreground text-xs font-semibold">Changes</span>
|
|
175
|
+
</div>
|
|
176
|
+
<div className="grid grid-cols-4 gap-3">
|
|
177
|
+
<div className="text-center">
|
|
178
|
+
<div className="text-foreground text-sm font-bold">
|
|
179
|
+
{diffSummary.filesChanged}
|
|
180
|
+
</div>
|
|
181
|
+
<div className="text-muted-foreground text-[10px]">files</div>
|
|
182
|
+
</div>
|
|
183
|
+
<div className="text-center">
|
|
184
|
+
<div className="text-sm font-bold text-green-600">+{diffSummary.additions}</div>
|
|
185
|
+
<div className="text-muted-foreground text-[10px]">additions</div>
|
|
186
|
+
</div>
|
|
187
|
+
<div className="text-center">
|
|
188
|
+
<div className="text-sm font-bold text-red-600">-{diffSummary.deletions}</div>
|
|
189
|
+
<div className="text-muted-foreground text-[10px]">deletions</div>
|
|
190
|
+
</div>
|
|
191
|
+
<div className="text-center">
|
|
192
|
+
<div className="text-foreground text-sm font-bold">{diffSummary.commitCount}</div>
|
|
193
|
+
<div className="text-muted-foreground text-[10px]">commits</div>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
</div>
|
|
197
|
+
</div>
|
|
198
|
+
) : warning ? (
|
|
199
|
+
<div className="border-border rounded-lg border">
|
|
200
|
+
<div className="flex items-center gap-2 px-4 py-3">
|
|
201
|
+
<AlertTriangle className="text-muted-foreground h-4 w-4 shrink-0" />
|
|
202
|
+
<span className="text-muted-foreground text-xs">{warning}</span>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
) : null}
|
|
206
|
+
|
|
207
|
+
{/* Implementation phases */}
|
|
208
|
+
{phases && phases.length > 0 ? <PhaseList phases={phases} /> : null}
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
{/* Action bar: chat + approve */}
|
|
212
|
+
<div className="border-border shrink-0 border-t">
|
|
213
|
+
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-4 pb-2">
|
|
214
|
+
<Input
|
|
215
|
+
type="text"
|
|
216
|
+
placeholder="Ask AI to revise before merging..."
|
|
217
|
+
aria-label="Ask AI to revise before merging"
|
|
218
|
+
disabled={isProcessing}
|
|
219
|
+
value={chatInput}
|
|
220
|
+
onChange={(e) => setChatInput(e.target.value)}
|
|
221
|
+
className="flex-1"
|
|
222
|
+
/>
|
|
223
|
+
<Button
|
|
224
|
+
type="submit"
|
|
225
|
+
variant="secondary"
|
|
226
|
+
size="icon"
|
|
227
|
+
aria-label="Send"
|
|
228
|
+
disabled={isProcessing}
|
|
229
|
+
>
|
|
230
|
+
<Send />
|
|
231
|
+
</Button>
|
|
232
|
+
</form>
|
|
233
|
+
<div className="px-4 pt-2 pb-4">
|
|
234
|
+
<Button
|
|
235
|
+
type="button"
|
|
236
|
+
className="w-full"
|
|
237
|
+
disabled={isProcessing}
|
|
238
|
+
onClick={onApprove}
|
|
239
|
+
aria-label="Approve Merge"
|
|
240
|
+
>
|
|
241
|
+
{isProcessing ? (
|
|
242
|
+
<Loader2 className="mr-1.5 h-4 w-4 animate-spin" />
|
|
243
|
+
) : (
|
|
244
|
+
<GitMerge className="mr-1.5 h-4 w-4" />
|
|
245
|
+
)}
|
|
246
|
+
Approve Merge
|
|
247
|
+
</Button>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
);
|
|
252
|
+
}
|
|
@@ -8,13 +8,16 @@ import { getFeatureArtifact } from '@/app/actions/get-feature-artifact';
|
|
|
8
8
|
import { getResearchArtifact } from '@/app/actions/get-research-artifact';
|
|
9
9
|
import { getWorkflowDefaults } from '@/app/actions/get-workflow-defaults';
|
|
10
10
|
import type { WorkflowDefaults } from '@/app/actions/get-workflow-defaults';
|
|
11
|
+
import { getMergeReviewData } from '@/app/actions/get-merge-review-data';
|
|
11
12
|
import type { TechDecisionsReviewData } from '@/components/common/tech-decisions-review';
|
|
13
|
+
import type { MergeReviewData } from '@/components/common/merge-review';
|
|
12
14
|
import { FeaturesCanvas } from '@/components/features/features-canvas';
|
|
13
15
|
import type { CanvasNodeType } from '@/components/features/features-canvas';
|
|
14
16
|
import { FeatureDrawer, FeatureCreateDrawer } from '@/components/common';
|
|
15
17
|
import { PrdQuestionnaireDrawer } from '@/components/common/prd-questionnaire';
|
|
16
18
|
import type { PrdQuestionnaireData } from '@/components/common/prd-questionnaire';
|
|
17
19
|
import { TechDecisionsDrawer } from '@/components/common/tech-decisions-review';
|
|
20
|
+
import { MergeReviewDrawer } from '@/components/common/merge-review';
|
|
18
21
|
import { NotificationPermissionBanner } from '@/components/common/notification-permission-banner';
|
|
19
22
|
import { ControlCenterEmptyState } from './control-center-empty-state';
|
|
20
23
|
import { useControlCenterState } from './use-control-center-state';
|
|
@@ -66,12 +69,19 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
|
|
|
66
69
|
const [techDecisionsData, setTechDecisionsData] = useState<TechDecisionsReviewData | null>(null);
|
|
67
70
|
const [isLoadingTechDecisions, setIsLoadingTechDecisions] = useState(false);
|
|
68
71
|
|
|
72
|
+
// Merge review drawer state
|
|
73
|
+
const [mergeReviewData, setMergeReviewData] = useState<MergeReviewData | null>(null);
|
|
74
|
+
const [isLoadingMergeReview, setIsLoadingMergeReview] = useState(false);
|
|
75
|
+
|
|
69
76
|
const showPrdDrawer =
|
|
70
77
|
selectedNode?.lifecycle === 'requirements' && selectedNode?.state === 'action-required';
|
|
71
78
|
|
|
72
79
|
const showTechDecisionsDrawer =
|
|
73
80
|
selectedNode?.lifecycle === 'implementation' && selectedNode?.state === 'action-required';
|
|
74
81
|
|
|
82
|
+
const showMergeReviewDrawer =
|
|
83
|
+
selectedNode?.lifecycle === 'review' && selectedNode?.state === 'action-required';
|
|
84
|
+
|
|
75
85
|
const handlePrdSelect = useCallback((questionId: string, optionId: string) => {
|
|
76
86
|
setPrdSelections((prev) => ({ ...prev, [questionId]: optionId }));
|
|
77
87
|
}, []);
|
|
@@ -125,6 +135,28 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
|
|
|
125
135
|
clearSelection();
|
|
126
136
|
}, [selectedNode?.featureId, clearSelection]);
|
|
127
137
|
|
|
138
|
+
const handleMergeApprove = useCallback(async () => {
|
|
139
|
+
const featureId = selectedNode?.featureId;
|
|
140
|
+
if (!featureId) return;
|
|
141
|
+
|
|
142
|
+
const result = await approveFeature(featureId);
|
|
143
|
+
|
|
144
|
+
if (!result.approved) {
|
|
145
|
+
toast.error(result.error ?? 'Failed to approve merge');
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
toast.success('Merge approved — agent resuming');
|
|
150
|
+
clearSelection();
|
|
151
|
+
}, [selectedNode?.featureId, clearSelection]);
|
|
152
|
+
|
|
153
|
+
const handleMergeRefine = useCallback(async (_text: string) => {
|
|
154
|
+
setIsLoadingMergeReview(true);
|
|
155
|
+
// TODO: Call API to refine merge
|
|
156
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
157
|
+
setIsLoadingMergeReview(false);
|
|
158
|
+
}, []);
|
|
159
|
+
|
|
128
160
|
// Fetch questionnaire data and reset selections when a different feature is selected
|
|
129
161
|
const prdFeatureId = showPrdDrawer ? selectedNode?.featureId : null;
|
|
130
162
|
useEffect(() => {
|
|
@@ -197,6 +229,36 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
|
|
|
197
229
|
};
|
|
198
230
|
}, [techDecisionsFeatureId]);
|
|
199
231
|
|
|
232
|
+
// Fetch merge review data when a feature is in review + action-required
|
|
233
|
+
const mergeFeatureId = showMergeReviewDrawer ? selectedNode?.featureId : null;
|
|
234
|
+
useEffect(() => {
|
|
235
|
+
setMergeReviewData(null);
|
|
236
|
+
|
|
237
|
+
if (!mergeFeatureId) return;
|
|
238
|
+
|
|
239
|
+
let cancelled = false;
|
|
240
|
+
setIsLoadingMergeReview(true);
|
|
241
|
+
getMergeReviewData(mergeFeatureId)
|
|
242
|
+
.then((result) => {
|
|
243
|
+
if (cancelled) return;
|
|
244
|
+
if ('error' in result) {
|
|
245
|
+
toast.error(result.error);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
setMergeReviewData(result);
|
|
249
|
+
})
|
|
250
|
+
.catch(() => {
|
|
251
|
+
if (!cancelled) toast.error('Failed to load merge review data');
|
|
252
|
+
})
|
|
253
|
+
.finally(() => {
|
|
254
|
+
if (!cancelled) setIsLoadingMergeReview(false);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
return () => {
|
|
258
|
+
cancelled = true;
|
|
259
|
+
};
|
|
260
|
+
}, [mergeFeatureId]);
|
|
261
|
+
|
|
200
262
|
const hasRepositories = nodes.some((n) => n.type === 'repositoryNode');
|
|
201
263
|
|
|
202
264
|
// Listen for global "open create drawer" events from the sidebar
|
|
@@ -240,7 +302,9 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
|
|
|
240
302
|
emptyState={<ControlCenterEmptyState onRepositorySelect={handleAddRepository} />}
|
|
241
303
|
/>
|
|
242
304
|
<FeatureDrawer
|
|
243
|
-
selectedNode={
|
|
305
|
+
selectedNode={
|
|
306
|
+
showPrdDrawer || showTechDecisionsDrawer || showMergeReviewDrawer ? null : selectedNode
|
|
307
|
+
}
|
|
244
308
|
onClose={clearSelection}
|
|
245
309
|
onDelete={handleDeleteFeature}
|
|
246
310
|
isDeleting={isDeleting}
|
|
@@ -282,6 +346,23 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
|
|
|
282
346
|
isProcessing={isLoadingTechDecisions}
|
|
283
347
|
/>
|
|
284
348
|
) : null}
|
|
349
|
+
{mergeReviewData ? (
|
|
350
|
+
<MergeReviewDrawer
|
|
351
|
+
open={showMergeReviewDrawer}
|
|
352
|
+
onClose={clearSelection}
|
|
353
|
+
featureName={selectedNode?.name ?? ''}
|
|
354
|
+
featureId={selectedNode?.featureId}
|
|
355
|
+
repositoryPath={selectedNode?.repositoryPath}
|
|
356
|
+
branch={selectedNode?.branch}
|
|
357
|
+
specPath={selectedNode?.specPath}
|
|
358
|
+
data={mergeReviewData}
|
|
359
|
+
onApprove={handleMergeApprove}
|
|
360
|
+
onRefine={handleMergeRefine}
|
|
361
|
+
onDelete={handleDeleteFeature}
|
|
362
|
+
isDeleting={isDeleting}
|
|
363
|
+
isProcessing={isLoadingMergeReview}
|
|
364
|
+
/>
|
|
365
|
+
) : null}
|
|
285
366
|
<FeatureCreateDrawer
|
|
286
367
|
open={isCreateDrawerOpen}
|
|
287
368
|
onClose={closeCreateDrawer}
|
|
@@ -75,6 +75,21 @@ const featureNodes: FeatureNodeType[] = [
|
|
|
75
75
|
branch: 'feat/api-gateway',
|
|
76
76
|
},
|
|
77
77
|
},
|
|
78
|
+
{
|
|
79
|
+
id: 'feat-4',
|
|
80
|
+
type: 'featureNode',
|
|
81
|
+
position: { x: 800, y: 345 },
|
|
82
|
+
data: {
|
|
83
|
+
name: 'Merge Review',
|
|
84
|
+
description: 'PR ready for merge approval',
|
|
85
|
+
featureId: '#f4',
|
|
86
|
+
lifecycle: 'review',
|
|
87
|
+
state: 'action-required',
|
|
88
|
+
progress: 90,
|
|
89
|
+
repositoryPath: '/home/user/my-repo',
|
|
90
|
+
branch: 'feat/merge-review',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
78
93
|
];
|
|
79
94
|
|
|
80
95
|
const repoNode: RepositoryNodeType = {
|
|
@@ -351,8 +351,19 @@ export function useControlCenterState(
|
|
|
351
351
|
}
|
|
352
352
|
|
|
353
353
|
setSelectedNode(null);
|
|
354
|
-
setNodes((
|
|
355
|
-
|
|
354
|
+
setNodes((currentNodes) => {
|
|
355
|
+
const remainingNodes = currentNodes.filter((n) => n.id !== featureId);
|
|
356
|
+
const remainingEdges = edges.filter(
|
|
357
|
+
(e) => e.source !== featureId && e.target !== featureId
|
|
358
|
+
);
|
|
359
|
+
const result = layoutWithDagre(remainingNodes, remainingEdges, {
|
|
360
|
+
direction: 'LR',
|
|
361
|
+
ranksep: 200,
|
|
362
|
+
nodesep: 60,
|
|
363
|
+
});
|
|
364
|
+
setEdges(result.edges);
|
|
365
|
+
return result.nodes;
|
|
366
|
+
});
|
|
356
367
|
toast.success('Feature deleted successfully');
|
|
357
368
|
router.refresh();
|
|
358
369
|
} catch {
|
|
@@ -361,7 +372,7 @@ export function useControlCenterState(
|
|
|
361
372
|
setIsDeleting(false);
|
|
362
373
|
}
|
|
363
374
|
},
|
|
364
|
-
[router]
|
|
375
|
+
[router, edges]
|
|
365
376
|
);
|
|
366
377
|
|
|
367
378
|
const handleDeleteRepository = useCallback(
|
|
@@ -430,23 +441,23 @@ export function useControlCenterState(
|
|
|
430
441
|
.pop() ?? path;
|
|
431
442
|
|
|
432
443
|
// Optimistic UI: add node immediately
|
|
444
|
+
let savedAddRepoY = 0;
|
|
433
445
|
setNodes((currentNodes) => {
|
|
434
446
|
const repoNodes = currentNodes.filter((n) => n.type === 'repositoryNode');
|
|
435
447
|
const addRepoNode = currentNodes.find((n) => n.type === 'addRepositoryNode');
|
|
436
448
|
|
|
437
|
-
//
|
|
449
|
+
// Save addRepoNode's original Y for rollback on error
|
|
450
|
+
if (addRepoNode) savedAddRepoY = addRepoNode.position.y;
|
|
451
|
+
|
|
452
|
+
// Place in the repo column, at the addRepoNode's current position
|
|
438
453
|
const repoX = repoNodes[0]?.position.x ?? addRepoNode?.position.x ?? 50;
|
|
439
454
|
const repoHeight = 50; // repositoryNode height
|
|
440
455
|
const gap = 15; // match dagre nodesep
|
|
441
456
|
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
? addRepoNode.position.y
|
|
447
|
-
: 0;
|
|
448
|
-
|
|
449
|
-
const position = { x: repoX, y: lastRepoBottomY + gap };
|
|
457
|
+
const position = {
|
|
458
|
+
x: repoX,
|
|
459
|
+
y: addRepoNode ? addRepoNode.position.y : 0,
|
|
460
|
+
};
|
|
450
461
|
|
|
451
462
|
const newNode = {
|
|
452
463
|
id: tempId,
|
|
@@ -455,8 +466,10 @@ export function useControlCenterState(
|
|
|
455
466
|
data: { name: repoName, repositoryPath: path, id: tempId },
|
|
456
467
|
} as CanvasNodeType;
|
|
457
468
|
|
|
458
|
-
//
|
|
459
|
-
const addRepoY =
|
|
469
|
+
// Shift addRepo button down by exactly one slot
|
|
470
|
+
const addRepoY = addRepoNode
|
|
471
|
+
? addRepoNode.position.y + repoHeight + gap
|
|
472
|
+
: position.y + repoHeight + gap;
|
|
460
473
|
|
|
461
474
|
return currentNodes
|
|
462
475
|
.map((n) =>
|
|
@@ -469,8 +482,16 @@ export function useControlCenterState(
|
|
|
469
482
|
addRepository({ path, name: repoName })
|
|
470
483
|
.then((result) => {
|
|
471
484
|
if (result.error) {
|
|
472
|
-
// Rollback optimistic node
|
|
473
|
-
setNodes((prev) =>
|
|
485
|
+
// Rollback optimistic node and restore addRepoNode position
|
|
486
|
+
setNodes((prev) =>
|
|
487
|
+
prev
|
|
488
|
+
.filter((n) => n.id !== tempId)
|
|
489
|
+
.map((n) =>
|
|
490
|
+
n.type === 'addRepositoryNode'
|
|
491
|
+
? { ...n, position: { ...n.position, y: savedAddRepoY } }
|
|
492
|
+
: n
|
|
493
|
+
)
|
|
494
|
+
);
|
|
474
495
|
toast.error(result.error);
|
|
475
496
|
return;
|
|
476
497
|
}
|
|
@@ -501,7 +522,16 @@ export function useControlCenterState(
|
|
|
501
522
|
router.refresh();
|
|
502
523
|
})
|
|
503
524
|
.catch(() => {
|
|
504
|
-
|
|
525
|
+
// Rollback optimistic node and restore addRepoNode position
|
|
526
|
+
setNodes((prev) =>
|
|
527
|
+
prev
|
|
528
|
+
.filter((n) => n.id !== tempId)
|
|
529
|
+
.map((n) =>
|
|
530
|
+
n.type === 'addRepositoryNode'
|
|
531
|
+
? { ...n, position: { ...n.position, y: savedAddRepoY } }
|
|
532
|
+
: n
|
|
533
|
+
)
|
|
534
|
+
);
|
|
505
535
|
toast.error('Failed to add repository');
|
|
506
536
|
});
|
|
507
537
|
},
|
|
@@ -15,7 +15,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
|
|
|
15
15
|
const hostname = process.env.HOSTNAME || '0.0.0.0'
|
|
16
16
|
|
|
17
17
|
let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
|
|
18
|
-
const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.
|
|
18
|
+
const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.47.0","NEXT_PUBLIC_SHEP_PACKAGE_NAME":"@shepai/cli","NEXT_PUBLIC_SHEP_DESCRIPTION":"Autonomous AI Native SDLC Platform - Automate the development cycle from idea to deploy"},"webpack":null,"typescript":{"ignoreBuildErrors":false},"typedRoutes":true,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/cli/cli","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"dynamicOnHover":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"imgOptSkipMetadata":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":false,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":false,"lockDistDir":true,"isolatedDevBuild":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":false,"optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","turbopack":{"root":"/home/runner/work/cli/cli"},"serverExternalPackages":["tsyringe","reflect-metadata","better-sqlite3"],"distDirRoot":".next"}
|
|
19
19
|
|
|
20
20
|
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
|
|
21
21
|
|