@autoview/cli 0.1.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/LICENSE +661 -0
- package/README.md +407 -0
- package/lib/AutoViewAgent.d.ts +109 -0
- package/lib/AutoViewAgent.js +123 -0
- package/lib/AutoViewAgent.js.map +1 -0
- package/lib/agent/emitMcpServer.d.ts +15 -0
- package/lib/agent/emitMcpServer.js +157 -0
- package/lib/agent/emitMcpServer.js.map +1 -0
- package/lib/agent/emitReport.d.ts +14 -0
- package/lib/agent/emitReport.js +85 -0
- package/lib/agent/emitReport.js.map +1 -0
- package/lib/agent/toolSurface.d.ts +130 -0
- package/lib/agent/toolSurface.js +342 -0
- package/lib/agent/toolSurface.js.map +1 -0
- package/lib/agent/verifyAgentTasks.d.ts +87 -0
- package/lib/agent/verifyAgentTasks.js +126 -0
- package/lib/agent/verifyAgentTasks.js.map +1 -0
- package/lib/cli/main.d.ts +2 -0
- package/lib/cli/main.js +295 -0
- package/lib/cli/main.js.map +1 -0
- package/lib/compiler/AutoViewInterfaceCompiler.d.ts +27 -0
- package/lib/compiler/AutoViewInterfaceCompiler.js +68 -0
- package/lib/compiler/AutoViewInterfaceCompiler.js.map +1 -0
- package/lib/constants/AutoViewFrontendTemplate.d.ts +1 -0
- package/lib/constants/AutoViewFrontendTemplate.js +46 -0
- package/lib/constants/AutoViewFrontendTemplate.js.map +1 -0
- package/lib/constants/AutoViewSystemPromptConstant.d.ts +5 -0
- package/lib/constants/AutoViewSystemPromptConstant.js +4 -0
- package/lib/constants/AutoViewSystemPromptConstant.js.map +1 -0
- package/lib/context/IAutoViewAgentContext.d.ts +60 -0
- package/lib/context/IAutoViewAgentContext.js +3 -0
- package/lib/context/IAutoViewAgentContext.js.map +1 -0
- package/lib/fromSwagger.d.ts +53 -0
- package/lib/fromSwagger.js +513 -0
- package/lib/fromSwagger.js.map +1 -0
- package/lib/generateDeterministic.d.ts +26 -0
- package/lib/generateDeterministic.js +75 -0
- package/lib/generateDeterministic.js.map +1 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.js +41 -0
- package/lib/index.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoView.d.ts +17 -0
- package/lib/orchestrate/orchestrateAutoView.js +491 -0
- package/lib/orchestrate/orchestrateAutoView.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoViewProductPlan.d.ts +37 -0
- package/lib/orchestrate/orchestrateAutoViewProductPlan.js +109 -0
- package/lib/orchestrate/orchestrateAutoViewProductPlan.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoViewRender.d.ts +133 -0
- package/lib/orchestrate/orchestrateAutoViewRender.js +943 -0
- package/lib/orchestrate/orchestrateAutoViewRender.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoViewRenderDeterministic.d.ts +24 -0
- package/lib/orchestrate/orchestrateAutoViewRenderDeterministic.js +92 -0
- package/lib/orchestrate/orchestrateAutoViewRenderDeterministic.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoViewReview.d.ts +48 -0
- package/lib/orchestrate/orchestrateAutoViewReview.js +328 -0
- package/lib/orchestrate/orchestrateAutoViewReview.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoViewScaffold.d.ts +45 -0
- package/lib/orchestrate/orchestrateAutoViewScaffold.js +586 -0
- package/lib/orchestrate/orchestrateAutoViewScaffold.js.map +1 -0
- package/lib/orchestrate/orchestrateAutoViewSdkStudy.d.ts +26 -0
- package/lib/orchestrate/orchestrateAutoViewSdkStudy.js +85 -0
- package/lib/orchestrate/orchestrateAutoViewSdkStudy.js.map +1 -0
- package/lib/orchestrate/structures/IAutoViewProductPlan.d.ts +96 -0
- package/lib/orchestrate/structures/IAutoViewProductPlan.js +3 -0
- package/lib/orchestrate/structures/IAutoViewProductPlan.js.map +1 -0
- package/lib/orchestrate/structures/IAutoViewProductPlanApplication.d.ts +38 -0
- package/lib/orchestrate/structures/IAutoViewProductPlanApplication.js +3 -0
- package/lib/orchestrate/structures/IAutoViewProductPlanApplication.js.map +1 -0
- package/lib/orchestrate/structures/IAutoViewRenderApplication.d.ts +38 -0
- package/lib/orchestrate/structures/IAutoViewRenderApplication.js +3 -0
- package/lib/orchestrate/structures/IAutoViewRenderApplication.js.map +1 -0
- package/lib/orchestrate/structures/IAutoViewReviewApplication.d.ts +40 -0
- package/lib/orchestrate/structures/IAutoViewReviewApplication.js +3 -0
- package/lib/orchestrate/structures/IAutoViewReviewApplication.js.map +1 -0
- package/lib/orchestrate/structures/IAutoViewSdkMap.d.ts +63 -0
- package/lib/orchestrate/structures/IAutoViewSdkMap.js +3 -0
- package/lib/orchestrate/structures/IAutoViewSdkMap.js.map +1 -0
- package/lib/orchestrate/structures/IAutoViewSdkStudyApplication.d.ts +37 -0
- package/lib/orchestrate/structures/IAutoViewSdkStudyApplication.js +3 -0
- package/lib/orchestrate/structures/IAutoViewSdkStudyApplication.js.map +1 -0
- package/lib/orchestrate/utils/HistoryMessage.d.ts +10 -0
- package/lib/orchestrate/utils/HistoryMessage.js +25 -0
- package/lib/orchestrate/utils/HistoryMessage.js.map +1 -0
- package/lib/orchestrate/utils/auditFrontendRuntime.d.ts +53 -0
- package/lib/orchestrate/utils/auditFrontendRuntime.js +362 -0
- package/lib/orchestrate/utils/auditFrontendRuntime.js.map +1 -0
- package/lib/orchestrate/utils/buildDeterministicPlan.d.ts +4 -0
- package/lib/orchestrate/utils/buildDeterministicPlan.js +233 -0
- package/lib/orchestrate/utils/buildDeterministicPlan.js.map +1 -0
- package/lib/orchestrate/utils/buildDeterministicSdkMap.d.ts +22 -0
- package/lib/orchestrate/utils/buildDeterministicSdkMap.js +154 -0
- package/lib/orchestrate/utils/buildDeterministicSdkMap.js.map +1 -0
- package/lib/orchestrate/utils/cacheNodeModules.d.ts +31 -0
- package/lib/orchestrate/utils/cacheNodeModules.js +134 -0
- package/lib/orchestrate/utils/cacheNodeModules.js.map +1 -0
- package/lib/orchestrate/utils/describeEndpointPropsShape.d.ts +37 -0
- package/lib/orchestrate/utils/describeEndpointPropsShape.js +192 -0
- package/lib/orchestrate/utils/describeEndpointPropsShape.js.map +1 -0
- package/lib/orchestrate/utils/describeEndpointRequestBodyShape.d.ts +22 -0
- package/lib/orchestrate/utils/describeEndpointRequestBodyShape.js +29 -0
- package/lib/orchestrate/utils/describeEndpointRequestBodyShape.js.map +1 -0
- package/lib/orchestrate/utils/describeEndpointResponseShape.d.ts +19 -0
- package/lib/orchestrate/utils/describeEndpointResponseShape.js +30 -0
- package/lib/orchestrate/utils/describeEndpointResponseShape.js.map +1 -0
- package/lib/orchestrate/utils/executeCachedBatch.d.ts +22 -0
- package/lib/orchestrate/utils/executeCachedBatch.js +64 -0
- package/lib/orchestrate/utils/executeCachedBatch.js.map +1 -0
- package/lib/orchestrate/utils/loadShoppingFixture.d.ts +33 -0
- package/lib/orchestrate/utils/loadShoppingFixture.js +17 -0
- package/lib/orchestrate/utils/loadShoppingFixture.js.map +1 -0
- package/lib/orchestrate/utils/normalizeProductPlanPaths.d.ts +24 -0
- package/lib/orchestrate/utils/normalizeProductPlanPaths.js +77 -0
- package/lib/orchestrate/utils/normalizeProductPlanPaths.js.map +1 -0
- package/lib/orchestrate/utils/renderJsonSchema.d.ts +23 -0
- package/lib/orchestrate/utils/renderJsonSchema.js +122 -0
- package/lib/orchestrate/utils/renderJsonSchema.js.map +1 -0
- package/lib/orchestrate/utils/renderResourcePage.d.ts +36 -0
- package/lib/orchestrate/utils/renderResourcePage.js +1415 -0
- package/lib/orchestrate/utils/renderResourcePage.js.map +1 -0
- package/lib/orchestrate/utils/validateFrontendTypecheck.d.ts +109 -0
- package/lib/orchestrate/utils/validateFrontendTypecheck.js +274 -0
- package/lib/orchestrate/utils/validateFrontendTypecheck.js.map +1 -0
- package/lib/preview/renderPreview.d.ts +22 -0
- package/lib/preview/renderPreview.js +198 -0
- package/lib/preview/renderPreview.js.map +1 -0
- package/lib/typings/compiler.d.ts +39 -0
- package/lib/typings/compiler.js +3 -0
- package/lib/typings/compiler.js.map +1 -0
- package/lib/typings/events.d.ts +106 -0
- package/lib/typings/events.js +3 -0
- package/lib/typings/events.js.map +1 -0
- package/lib/typings/index.d.ts +10 -0
- package/lib/typings/index.js +27 -0
- package/lib/typings/index.js.map +1 -0
- package/lib/typings/misc.d.ts +78 -0
- package/lib/typings/misc.js +3 -0
- package/lib/typings/misc.js.map +1 -0
- package/lib/utils/ArrayUtil.d.ts +8 -0
- package/lib/utils/ArrayUtil.js +30 -0
- package/lib/utils/ArrayUtil.js.map +1 -0
- package/lib/utils/StringUtil.d.ts +11 -0
- package/lib/utils/StringUtil.js +28 -0
- package/lib/utils/StringUtil.js.map +1 -0
- package/lib/utils/classifyEndpoints.d.ts +62 -0
- package/lib/utils/classifyEndpoints.js +216 -0
- package/lib/utils/classifyEndpoints.js.map +1 -0
- package/lib/utils/endpointFilter.d.ts +26 -0
- package/lib/utils/endpointFilter.js +0 -0
- package/lib/utils/endpointFilter.js.map +1 -0
- package/lib/utils/extractFields.d.ts +85 -0
- package/lib/utils/extractFields.js +231 -0
- package/lib/utils/extractFields.js.map +1 -0
- package/lib/utils/index.d.ts +13 -0
- package/lib/utils/index.js +30 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/normalizeForNestia.d.ts +34 -0
- package/lib/utils/normalizeForNestia.js +133 -0
- package/lib/utils/normalizeForNestia.js.map +1 -0
- package/lib/utils/resourcePlan.d.ts +39 -0
- package/lib/utils/resourcePlan.js +95 -0
- package/lib/utils/resourcePlan.js.map +1 -0
- package/lib/utils/sliceDocument.d.ts +17 -0
- package/lib/utils/sliceDocument.js +114 -0
- package/lib/utils/sliceDocument.js.map +1 -0
- package/lib/utils/toEndpoints.d.ts +90 -0
- package/lib/utils/toEndpoints.js +227 -0
- package/lib/utils/toEndpoints.js.map +1 -0
- package/lib/verify/runWorkflows.d.ts +25 -0
- package/lib/verify/runWorkflows.js +366 -0
- package/lib/verify/runWorkflows.js.map +1 -0
- package/lib/verify/workflows.d.ts +53 -0
- package/lib/verify/workflows.js +107 -0
- package/lib/verify/workflows.js.map +1 -0
- package/package.json +82 -0
- package/prompts/AUTOVIEW_RENDER.md +398 -0
- package/prompts/AUTOVIEW_REVIEW.md +60 -0
- package/prompts/AUTOVIEW_SDK_STUDY.md +89 -0
- package/src/AutoViewAgent.ts +222 -0
- package/src/agent/emitMcpServer.integration.test.ts +168 -0
- package/src/agent/emitMcpServer.test.ts +51 -0
- package/src/agent/emitMcpServer.ts +178 -0
- package/src/agent/emitReport.ts +117 -0
- package/src/agent/toolSurface.test.ts +243 -0
- package/src/agent/toolSurface.ts +501 -0
- package/src/agent/verifyAgentTasks.test.ts +106 -0
- package/src/agent/verifyAgentTasks.ts +171 -0
- package/src/cli/main.ts +363 -0
- package/src/compiler/AutoViewInterfaceCompiler.ts +69 -0
- package/src/constants/AutoViewFrontendTemplate.ts +42 -0
- package/src/constants/AutoViewSystemPromptConstant.ts +6 -0
- package/src/context/IAutoViewAgentContext.ts +84 -0
- package/src/fromSwagger.test.ts +269 -0
- package/src/fromSwagger.ts +500 -0
- package/src/generateDeterministic.test.ts +39 -0
- package/src/generateDeterministic.ts +77 -0
- package/src/index.ts +30 -0
- package/src/orchestrate/orchestrateAutoView.ts +590 -0
- package/src/orchestrate/orchestrateAutoViewProductPlan.ts +121 -0
- package/src/orchestrate/orchestrateAutoViewRender.ts +1117 -0
- package/src/orchestrate/orchestrateAutoViewRenderDeterministic.ts +101 -0
- package/src/orchestrate/orchestrateAutoViewReview.ts +272 -0
- package/src/orchestrate/orchestrateAutoViewScaffold.ts +627 -0
- package/src/orchestrate/orchestrateAutoViewSdkStudy.ts +90 -0
- package/src/orchestrate/renderNavTs.test.ts +74 -0
- package/src/orchestrate/structures/IAutoViewProductPlan.ts +119 -0
- package/src/orchestrate/structures/IAutoViewProductPlanApplication.ts +41 -0
- package/src/orchestrate/structures/IAutoViewRenderApplication.ts +40 -0
- package/src/orchestrate/structures/IAutoViewReviewApplication.ts +42 -0
- package/src/orchestrate/structures/IAutoViewSdkMap.ts +72 -0
- package/src/orchestrate/structures/IAutoViewSdkStudyApplication.ts +40 -0
- package/src/orchestrate/utils/HistoryMessage.ts +41 -0
- package/src/orchestrate/utils/auditFrontendRuntime.test.ts +18 -0
- package/src/orchestrate/utils/auditFrontendRuntime.ts +454 -0
- package/src/orchestrate/utils/buildDeterministicPlan.test.ts +170 -0
- package/src/orchestrate/utils/buildDeterministicPlan.ts +289 -0
- package/src/orchestrate/utils/buildDeterministicSdkMap.test.ts +90 -0
- package/src/orchestrate/utils/buildDeterministicSdkMap.ts +169 -0
- package/src/orchestrate/utils/cacheNodeModules.ts +136 -0
- package/src/orchestrate/utils/describeEndpointPropsShape.test.ts +86 -0
- package/src/orchestrate/utils/describeEndpointPropsShape.ts +202 -0
- package/src/orchestrate/utils/describeEndpointRequestBodyShape.test.ts +87 -0
- package/src/orchestrate/utils/describeEndpointRequestBodyShape.ts +31 -0
- package/src/orchestrate/utils/describeEndpointResponseShape.test.ts +70 -0
- package/src/orchestrate/utils/describeEndpointResponseShape.ts +32 -0
- package/src/orchestrate/utils/executeCachedBatch.ts +59 -0
- package/src/orchestrate/utils/loadShoppingFixture.ts +52 -0
- package/src/orchestrate/utils/normalizeProductPlanPaths.ts +92 -0
- package/src/orchestrate/utils/renderJsonSchema.test.ts +162 -0
- package/src/orchestrate/utils/renderJsonSchema.ts +133 -0
- package/src/orchestrate/utils/renderResourcePage.test.ts +468 -0
- package/src/orchestrate/utils/renderResourcePage.ts +1624 -0
- package/src/orchestrate/utils/validateFrontendTypecheck.test.ts +32 -0
- package/src/orchestrate/utils/validateFrontendTypecheck.ts +335 -0
- package/src/preview/renderPreview.ts +273 -0
- package/src/typings/compiler.ts +47 -0
- package/src/typings/events.ts +155 -0
- package/src/typings/index.ts +10 -0
- package/src/typings/misc.ts +93 -0
- package/src/utils/ArrayUtil.ts +16 -0
- package/src/utils/StringUtil.ts +29 -0
- package/src/utils/classifyEndpoints.test.ts +86 -0
- package/src/utils/classifyEndpoints.ts +291 -0
- package/src/utils/endpointFilter.test.ts +50 -0
- package/src/utils/endpointFilter.ts +0 -0
- package/src/utils/extractFields.test.ts +82 -0
- package/src/utils/extractFields.ts +306 -0
- package/src/utils/index.ts +13 -0
- package/src/utils/normalizeForNestia.test.ts +93 -0
- package/src/utils/normalizeForNestia.ts +139 -0
- package/src/utils/resourcePlan.test.ts +104 -0
- package/src/utils/resourcePlan.ts +180 -0
- package/src/utils/sliceDocument.test.ts +85 -0
- package/src/utils/sliceDocument.ts +119 -0
- package/src/utils/toEndpoints.test.ts +251 -0
- package/src/utils/toEndpoints.ts +343 -0
- package/src/verify/runWorkflows.ts +403 -0
- package/src/verify/workflows.test.ts +117 -0
- package/src/verify/workflows.ts +154 -0
- package/template/CLAUDE.md +140 -0
- package/template/Dockerfile +31 -0
- package/template/PROMPT.md +80 -0
- package/template/SANDBOX.md +70 -0
- package/template/app/api/health/route.ts +10 -0
- package/template/app/globals.css +97 -0
- package/template/app/layout.tsx +30 -0
- package/template/app/page.tsx +19 -0
- package/template/components/AppShell.tsx +114 -0
- package/template/components/auto/CatalogGrid.tsx +159 -0
- package/template/components/auto/ConfirmButton.tsx +67 -0
- package/template/components/auto/EmbeddedCollection.tsx +144 -0
- package/template/components/auto/ResourceDashboard.tsx +104 -0
- package/template/components/auto/ResourceDetail.tsx +93 -0
- package/template/components/auto/ResourceForm.tsx +235 -0
- package/template/components/auto/ResourceIcon.tsx +88 -0
- package/template/components/auto/ResourceLanding.tsx +155 -0
- package/template/components/auto/ResourceTable.tsx +223 -0
- package/template/components/auto/formatValue.tsx +186 -0
- package/template/components/auto/types.ts +42 -0
- package/template/components/ui/badge.tsx +40 -0
- package/template/components/ui/button.tsx +57 -0
- package/template/components/ui/card.tsx +86 -0
- package/template/components/ui/dialog.tsx +119 -0
- package/template/components/ui/input.tsx +23 -0
- package/template/components/ui/label.tsx +24 -0
- package/template/components/ui/pagination.tsx +117 -0
- package/template/components/ui/select.tsx +92 -0
- package/template/components/ui/sheet.tsx +135 -0
- package/template/components/ui/skeleton.tsx +15 -0
- package/template/components/ui/table.tsx +120 -0
- package/template/components/ui/tabs.tsx +55 -0
- package/template/lib/utils.ts +35 -0
- package/template/next.config.mjs +52 -0
- package/template/package.json +46 -0
- package/template/postcss.config.js +6 -0
- package/template/scripts/start-shopping-backend.sh +56 -0
- package/template/tailwind.config.ts +96 -0
- package/template/tsconfig.json +29 -0
|
@@ -0,0 +1,943 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.orchestrateAutoViewRender = orchestrateAutoViewRender;
|
|
49
|
+
exports.rerenderScreenForTypecheck = rerenderScreenForTypecheck;
|
|
50
|
+
exports.rerenderScreenForRuntime = rerenderScreenForRuntime;
|
|
51
|
+
exports.screenPathToFile = screenPathToFile;
|
|
52
|
+
exports.fileToScreenPath = fileToScreenPath;
|
|
53
|
+
const __typia_transform__validateReport = __importStar(require("typia/lib/internal/_validateReport"));
|
|
54
|
+
const __typia_transform__llmApplicationFinalize = __importStar(require("typia/lib/internal/_llmApplicationFinalize"));
|
|
55
|
+
const utils_1 = require("../utils");
|
|
56
|
+
const tstl_1 = require("tstl");
|
|
57
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
58
|
+
const typia_1 = __importDefault(require("typia"));
|
|
59
|
+
const uuid_1 = require("uuid");
|
|
60
|
+
const HistoryMessage_1 = require("./utils/HistoryMessage");
|
|
61
|
+
const describeEndpointPropsShape_1 = require("./utils/describeEndpointPropsShape");
|
|
62
|
+
const describeEndpointRequestBodyShape_1 = require("./utils/describeEndpointRequestBodyShape");
|
|
63
|
+
const describeEndpointResponseShape_1 = require("./utils/describeEndpointResponseShape");
|
|
64
|
+
const executeCachedBatch_1 = require("./utils/executeCachedBatch");
|
|
65
|
+
// Five tries (one initial + four retries). The earlier limit of two
|
|
66
|
+
// retries silently dropped landing pages with multiple orthogonal
|
|
67
|
+
// defects — TC39 mix, unclosed JSX, regex escapes — because the model
|
|
68
|
+
// only managed to fix the first issue per attempt. Five tries gives
|
|
69
|
+
// the retry loop enough budget to converge on common LLM mistakes
|
|
70
|
+
// without ballooning per-page latency past ~30s.
|
|
71
|
+
const MAX_PARSE_RETRIES = 4;
|
|
72
|
+
function orchestrateAutoViewRender(ctx, props) {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
const total = props.productPlan.screens.length;
|
|
75
|
+
const completed = { value: 0 };
|
|
76
|
+
const files = {};
|
|
77
|
+
const screens = [];
|
|
78
|
+
// Pre-compute the list of frontend routes the plan declared so the
|
|
79
|
+
// render prompt can teach the LLM which `<Link href=...>` targets
|
|
80
|
+
// actually exist. Without this the model routinely linked to SDK
|
|
81
|
+
// accessor paths (`/shoppings/customers/systematic/channels`) that
|
|
82
|
+
// 404 the moment the user clicks them.
|
|
83
|
+
const allScreenPaths = props.productPlan.screens.map((s) => s.path);
|
|
84
|
+
const semaphoreCap = typeof ctx.vendor.semaphore === "number"
|
|
85
|
+
? ctx.vendor.semaphore
|
|
86
|
+
: ctx.vendor.semaphore !== undefined
|
|
87
|
+
? ctx.vendor.semaphore.max()
|
|
88
|
+
: 8;
|
|
89
|
+
yield (0, executeCachedBatch_1.executeCachedBatch)(semaphoreCap, props.productPlan.screens.map((screen) => (promptCacheKey) => __awaiter(this, void 0, void 0, function* () {
|
|
90
|
+
const counter = new tstl_1.Singleton(() => ++completed.value);
|
|
91
|
+
const result = yield renderOneScreen(ctx, {
|
|
92
|
+
screen,
|
|
93
|
+
document: props.document,
|
|
94
|
+
sdkMap: props.sdkMap,
|
|
95
|
+
designTheme: props.designTheme,
|
|
96
|
+
promptCacheKey,
|
|
97
|
+
allScreenPaths,
|
|
98
|
+
});
|
|
99
|
+
const filePath = screenPathToFile(screen.path);
|
|
100
|
+
files[filePath] = result.tsx;
|
|
101
|
+
// Preserve the LLM's final raw attempt next to the wiki when the
|
|
102
|
+
// page fell back to the placeholder. Without this the operator
|
|
103
|
+
// (and future render-prompt iterations) cannot see what the model
|
|
104
|
+
// actually emitted — only the placeholder text — so the same
|
|
105
|
+
// class of defect keeps recurring across archives.
|
|
106
|
+
if (!result.ok && result.lastAttemptTsx.length > 0) {
|
|
107
|
+
const slug = screen.path.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "") ||
|
|
108
|
+
"root";
|
|
109
|
+
files[`wiki/render-failed/${slug}.tsx`] = result.lastAttemptTsx;
|
|
110
|
+
}
|
|
111
|
+
screens.push({
|
|
112
|
+
pagePath: screen.path,
|
|
113
|
+
uiPattern: screen.uiPattern,
|
|
114
|
+
actor: screen.actor,
|
|
115
|
+
rationale: result.rationale,
|
|
116
|
+
attempts: result.attempts,
|
|
117
|
+
ok: result.ok,
|
|
118
|
+
diagnostic: result.diagnostic,
|
|
119
|
+
});
|
|
120
|
+
ctx.dispatch({
|
|
121
|
+
type: "autoViewRenderPage",
|
|
122
|
+
id: (0, uuid_1.v7)(),
|
|
123
|
+
created_at: new Date().toISOString(),
|
|
124
|
+
step: props.step,
|
|
125
|
+
total,
|
|
126
|
+
completed: counter.get(),
|
|
127
|
+
pagePath: screen.path,
|
|
128
|
+
uiPattern: screen.uiPattern,
|
|
129
|
+
attempts: result.attempts,
|
|
130
|
+
ok: result.ok,
|
|
131
|
+
tokenUsage: result.tokenUsage,
|
|
132
|
+
metric: result.metric,
|
|
133
|
+
});
|
|
134
|
+
})));
|
|
135
|
+
return { files, screens };
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Re-render a single screen after the typecheck phase reported diagnostics on
|
|
140
|
+
* its file. Reuses the parser-driven retry loop inside the per-screen render —
|
|
141
|
+
* the first attempt uses {@link buildTypecheckRetryHistories} (which surfaces
|
|
142
|
+
* the diagnostics + previous TSX), and any subsequent retries fall back to
|
|
143
|
+
* {@link buildRetryHistories} so the model still benefits from the deterministic
|
|
144
|
+
* `??`/`||` auto-fix and the syntax retry budget.
|
|
145
|
+
*
|
|
146
|
+
* Returns `null` when the model could not produce parser-valid TSX after the
|
|
147
|
+
* full retry budget; the caller should leave the existing (broken) file in
|
|
148
|
+
* place and report the failure so the operator still gets some output.
|
|
149
|
+
*/
|
|
150
|
+
function rerenderScreenForTypecheck(ctx, args) {
|
|
151
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
152
|
+
var _a;
|
|
153
|
+
const relevantOperations = (0, utils_1.toEndpoints)(args.document).filter((op) => { var _a; return args.screen.endpoints.includes(((_a = op.accessor) !== null && _a !== void 0 ? _a : []).join(".")); });
|
|
154
|
+
let previousTsx = args.previousTsx;
|
|
155
|
+
let lastParseError = null;
|
|
156
|
+
let attempt = 0;
|
|
157
|
+
for (; attempt <= MAX_PARSE_RETRIES; attempt++) {
|
|
158
|
+
const pointer = {
|
|
159
|
+
value: null,
|
|
160
|
+
};
|
|
161
|
+
const histories = attempt === 0
|
|
162
|
+
? buildTypecheckRetryHistories(Object.assign(Object.assign({}, args), { relevantOperations,
|
|
163
|
+
previousTsx, typecheckErrors: args.typecheckErrors }))
|
|
164
|
+
: buildRetryHistories(Object.assign(Object.assign({}, args), { relevantOperations, lastTsx: previousTsx, lastError: lastParseError !== null && lastParseError !== void 0 ? lastParseError : "" }));
|
|
165
|
+
const userMessage = attempt === 0
|
|
166
|
+
? `Fix the typecheck errors on ${args.screen.path}. Re-emit the entire page TSX with the corrections. Call \`renderPage\` once.`
|
|
167
|
+
: `The corrected attempt failed TypeScript parsing: ${lastParseError}. Regenerate the entire page TSX with the fix applied.`;
|
|
168
|
+
try {
|
|
169
|
+
yield ctx.conversate({
|
|
170
|
+
source: "autoViewRenderPage",
|
|
171
|
+
target: args.screen.path,
|
|
172
|
+
controller: createController({
|
|
173
|
+
build: (next) => {
|
|
174
|
+
pointer.value = next;
|
|
175
|
+
},
|
|
176
|
+
}),
|
|
177
|
+
enforceFunctionCall: true,
|
|
178
|
+
promptCacheKey: args.promptCacheKey,
|
|
179
|
+
histories,
|
|
180
|
+
userMessage,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
// Vendor-side failure during the typecheck-driven retry. Don't let
|
|
185
|
+
// it reject the whole retry batch — record and retry, falling
|
|
186
|
+
// through to `null` if the budget runs out so the caller keeps the
|
|
187
|
+
// previously-rendered (typecheck-broken) file instead of aborting
|
|
188
|
+
// the entire run.
|
|
189
|
+
lastParseError = error instanceof Error ? error.message : String(error);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (pointer.value === null) {
|
|
193
|
+
// Model refused to call renderPage on this attempt — escalate to
|
|
194
|
+
// the parser-retry pathway with the previous TSX still in scope.
|
|
195
|
+
lastParseError = "model did not call renderPage";
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
const candidate = (_a = autoWrapNullishCoalescingMix(pointer.value.tsx)) !== null && _a !== void 0 ? _a : pointer.value.tsx;
|
|
199
|
+
const parseError = findSyntaxError(candidate);
|
|
200
|
+
if (parseError === null) {
|
|
201
|
+
return {
|
|
202
|
+
tsx: candidate,
|
|
203
|
+
ok: true,
|
|
204
|
+
diagnostic: "",
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
previousTsx = candidate;
|
|
208
|
+
lastParseError = parseError;
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
function renderOneScreen(ctx, args) {
|
|
214
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
215
|
+
var _a;
|
|
216
|
+
// Restrict the SDK context to the schemas the screen actually
|
|
217
|
+
// composes; the full document would blow the prompt budget on
|
|
218
|
+
// larger projects.
|
|
219
|
+
const relevantOperations = (0, utils_1.toEndpoints)(args.document).filter((op) => { var _a; return args.screen.endpoints.includes(((_a = op.accessor) !== null && _a !== void 0 ? _a : []).join(".")); });
|
|
220
|
+
let lastTsx = null;
|
|
221
|
+
let lastError = null;
|
|
222
|
+
let lastRationale = "";
|
|
223
|
+
let attempts = 0;
|
|
224
|
+
let lastTokenUsage = null;
|
|
225
|
+
let lastMetric = null;
|
|
226
|
+
for (let attempt = 0; attempt <= MAX_PARSE_RETRIES; attempt++) {
|
|
227
|
+
attempts = attempt + 1;
|
|
228
|
+
const pointer = {
|
|
229
|
+
value: null,
|
|
230
|
+
};
|
|
231
|
+
const histories = attempt === 0
|
|
232
|
+
? buildInitialHistories(Object.assign(Object.assign({}, args), { relevantOperations }))
|
|
233
|
+
: buildRetryHistories(Object.assign(Object.assign({}, args), { relevantOperations, lastTsx: lastTsx !== null && lastTsx !== void 0 ? lastTsx : "", lastError: lastError !== null && lastError !== void 0 ? lastError : "" }));
|
|
234
|
+
const userMessage = attempt === 0
|
|
235
|
+
? `Render the page for ${args.screen.path} (${args.screen.uiPattern}). Call \`renderPage\` once.`
|
|
236
|
+
: `The previous attempt failed TypeScript parsing: ${lastError}. Regenerate the entire page TSX with the fix applied. Pay attention to: escaping \`/\` inside regex literals as \`\\/\`, wrapping mixed \`??\` and \`||\` with parentheses, and closing every \`{\` opened inside JSX.`;
|
|
237
|
+
try {
|
|
238
|
+
const { metric, tokenUsage } = yield ctx.conversate({
|
|
239
|
+
source: "autoViewRenderPage",
|
|
240
|
+
target: args.screen.path,
|
|
241
|
+
controller: createController({
|
|
242
|
+
build: (next) => {
|
|
243
|
+
pointer.value = next;
|
|
244
|
+
},
|
|
245
|
+
}),
|
|
246
|
+
enforceFunctionCall: true,
|
|
247
|
+
promptCacheKey: args.promptCacheKey,
|
|
248
|
+
histories,
|
|
249
|
+
userMessage,
|
|
250
|
+
});
|
|
251
|
+
lastTokenUsage = tokenUsage;
|
|
252
|
+
lastMetric = metric;
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
// Vendor-side failure (connection drop / undici `terminated`, 5xx,
|
|
256
|
+
// rate limit). On larger SDKs the per-screen render fan-out keeps
|
|
257
|
+
// dozens of LLM calls in flight and one dropped socket would
|
|
258
|
+
// otherwise reject the whole `executeCachedBatch` and abort every
|
|
259
|
+
// other screen mid-flight. Treat it like a failed attempt: record
|
|
260
|
+
// the reason, let the retry loop try again, and fall back to the
|
|
261
|
+
// placeholder if the budget runs out — the project still ships.
|
|
262
|
+
lastError =
|
|
263
|
+
error instanceof Error
|
|
264
|
+
? `vendor error: ${error.message}`
|
|
265
|
+
: `vendor error: ${String(error)}`;
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
if (pointer.value === null) {
|
|
269
|
+
// No function call. Treat as fatal — break to the placeholder.
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
// Deterministic auto-fix: LLMs reliably re-emit `a ?? b || c` /
|
|
273
|
+
// `a || b ?? c` even with hard rules in the prompt. Walk the AST,
|
|
274
|
+
// parenthesize every nullish-coalescing branch nested inside a
|
|
275
|
+
// logical-or / logical-and (and vice versa), and re-check. This
|
|
276
|
+
// costs zero extra LLM calls and turns a guaranteed placeholder
|
|
277
|
+
// into a working page.
|
|
278
|
+
const candidate = (_a = autoWrapNullishCoalescingMix(pointer.value.tsx)) !== null && _a !== void 0 ? _a : pointer.value.tsx;
|
|
279
|
+
lastTsx = candidate;
|
|
280
|
+
lastRationale = pointer.value.rationale;
|
|
281
|
+
const parseError = findSyntaxError(candidate);
|
|
282
|
+
if (parseError === null) {
|
|
283
|
+
return {
|
|
284
|
+
tsx: candidate,
|
|
285
|
+
rationale: lastRationale,
|
|
286
|
+
attempts,
|
|
287
|
+
ok: true,
|
|
288
|
+
diagnostic: "",
|
|
289
|
+
lastAttemptTsx: "",
|
|
290
|
+
tokenUsage: lastTokenUsage,
|
|
291
|
+
metric: lastMetric,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
lastError = parseError;
|
|
295
|
+
}
|
|
296
|
+
// Exhausted retries — ship a placeholder so the rest of the project
|
|
297
|
+
// still compiles. Surface the reason inline.
|
|
298
|
+
return {
|
|
299
|
+
tsx: buildPlaceholderPage(args.screen, lastError !== null && lastError !== void 0 ? lastError : "no rendering"),
|
|
300
|
+
rationale: lastRationale,
|
|
301
|
+
attempts,
|
|
302
|
+
ok: false,
|
|
303
|
+
diagnostic: lastError !== null && lastError !== void 0 ? lastError : "model did not call renderPage",
|
|
304
|
+
lastAttemptTsx: lastTsx !== null && lastTsx !== void 0 ? lastTsx : "",
|
|
305
|
+
tokenUsage: lastTokenUsage !== null && lastTokenUsage !== void 0 ? lastTokenUsage : zeroTokenUsage(),
|
|
306
|
+
metric: lastMetric !== null && lastMetric !== void 0 ? lastMetric : zeroMetric(),
|
|
307
|
+
};
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
function zeroTokenUsage() {
|
|
311
|
+
return {
|
|
312
|
+
total: 0,
|
|
313
|
+
input: { total: 0, cached: 0 },
|
|
314
|
+
output: {
|
|
315
|
+
total: 0,
|
|
316
|
+
reasoning: 0,
|
|
317
|
+
accepted_prediction: 0,
|
|
318
|
+
rejected_prediction: 0,
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
function zeroMetric() {
|
|
323
|
+
return {
|
|
324
|
+
attempt: 0,
|
|
325
|
+
success: 0,
|
|
326
|
+
invalidJson: 0,
|
|
327
|
+
validationFailure: 0,
|
|
328
|
+
consent: 0,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function buildInitialHistories(args) {
|
|
332
|
+
var _a;
|
|
333
|
+
// Deterministic per-endpoint `props` shape. The LLM has repeatedly
|
|
334
|
+
// flattened body fields into the top level of `props` (e.g.
|
|
335
|
+
// `index(connection, { limit: 24 })` instead of
|
|
336
|
+
// `index(connection, { body: { limit: 24 } })`), which makes the
|
|
337
|
+
// simulator return a masked 400 and the page renders the empty
|
|
338
|
+
// state. Pre-computing the exact shape kills that whole class of
|
|
339
|
+
// defect at zero LLM cost. Parameterless endpoints render as
|
|
340
|
+
// `(connection)` because the Nestia SDK omits the second arg
|
|
341
|
+
// entirely when there are no path params or body — emitting
|
|
342
|
+
// `(connection, {})` here teaches the LLM a signature that fails
|
|
343
|
+
// `npm run typecheck` with "Expected 1 arguments, but got 2".
|
|
344
|
+
const propsSignatures = args.relevantOperations
|
|
345
|
+
.map((op) => {
|
|
346
|
+
var _a;
|
|
347
|
+
const accessor = ((_a = op.accessor) !== null && _a !== void 0 ? _a : []).join(".");
|
|
348
|
+
const propsShape = (0, describeEndpointPropsShape_1.describeEndpointPropsShape)(op);
|
|
349
|
+
const signature = propsShape === "{}"
|
|
350
|
+
? `api.functional.${accessor}(connection)`
|
|
351
|
+
: `api.functional.${accessor}(connection, ${propsShape})`;
|
|
352
|
+
return `- \`${signature}\``;
|
|
353
|
+
})
|
|
354
|
+
.join("\n");
|
|
355
|
+
// Per-endpoint required-fields hint + sample body literal. Stops the
|
|
356
|
+
// model from sending `{ body: {} }` to endpoints with required fields
|
|
357
|
+
// (cart create, etc.) — which used to come back as a typia validation
|
|
358
|
+
// 400 the user sees as "Unable to load …" with no actionable signal.
|
|
359
|
+
const bodyHints = args.relevantOperations
|
|
360
|
+
.map((op) => {
|
|
361
|
+
var _a;
|
|
362
|
+
const hint = (0, describeEndpointPropsShape_1.describeRequestBodyHint)(op, args.document);
|
|
363
|
+
if (hint.length === 0)
|
|
364
|
+
return null;
|
|
365
|
+
const accessor = ((_a = op.accessor) !== null && _a !== void 0 ? _a : []).join(".");
|
|
366
|
+
return `- \`${accessor}\` → ${hint}`;
|
|
367
|
+
})
|
|
368
|
+
.filter((line) => line !== null)
|
|
369
|
+
.join("\n");
|
|
370
|
+
// Per-endpoint return-type shape, fully expanded one or two levels. The LLM
|
|
371
|
+
// has the raw OpenAPI JSON below, but routinely invents plausible-sounding
|
|
372
|
+
// properties (`auth.member.email` on an `IAuthorized` whose real shape is
|
|
373
|
+
// `{ id, created_at, token }`). Spelling out the actual fields up front
|
|
374
|
+
// anchors the render against the SDK return type instead of the model's
|
|
375
|
+
// domain priors.
|
|
376
|
+
const responseShapes = args.relevantOperations
|
|
377
|
+
.map((op) => {
|
|
378
|
+
var _a;
|
|
379
|
+
const accessor = ((_a = op.accessor) !== null && _a !== void 0 ? _a : []).join(".");
|
|
380
|
+
const shape = (0, describeEndpointResponseShape_1.describeEndpointResponseShape)(op, args.document);
|
|
381
|
+
return `### \`api.functional.${accessor}\` → Promise<${shape}>`;
|
|
382
|
+
})
|
|
383
|
+
.join("\n\n");
|
|
384
|
+
// Symmetric input-side expansion. The one-line `bodyHints` block above shows
|
|
385
|
+
// required keys + a sample literal but stops short of nested union / array
|
|
386
|
+
// shapes, which is exactly where the LLM hallucinates (sort grammars as
|
|
387
|
+
// `{ field, direction }[]` instead of `("created_at.asc" | ...)[]`, or
|
|
388
|
+
// invented top-level `title` fields on search request types). Surfacing the
|
|
389
|
+
// full body shape closes that gap without changing any other prompt
|
|
390
|
+
// mechanics.
|
|
391
|
+
const requestShapes = args.relevantOperations
|
|
392
|
+
.map((op) => {
|
|
393
|
+
var _a;
|
|
394
|
+
const shape = (0, describeEndpointRequestBodyShape_1.describeEndpointRequestBodyShape)(op, args.document);
|
|
395
|
+
if (shape === null)
|
|
396
|
+
return null;
|
|
397
|
+
const accessor = ((_a = op.accessor) !== null && _a !== void 0 ? _a : []).join(".");
|
|
398
|
+
return `### \`api.functional.${accessor}\` body shape\n\n\`\`\`ts\n${shape}\n\`\`\``;
|
|
399
|
+
})
|
|
400
|
+
.filter((line) => line !== null)
|
|
401
|
+
.join("\n\n");
|
|
402
|
+
return [
|
|
403
|
+
HistoryMessage_1.HistoryMessage.system("<!--\nfilename: AUTOVIEW_RENDER.md\n-->\nYou are the Render phase of the AutoView agent.\n\nYou receive one screen from the product plan and produce a complete,\nrunnable Next.js page (TSX) that composes the SDK endpoints listed for\nthat screen into a single coherent UI. You are not redesigning the\nproduct, choosing the actor, or inventing endpoints \u2014 those decisions\nwere already made by the Product Plan phase. You translate the plan\ninto TSX.\n\n## Stack\n\n- Next.js 15 App Router. Output a single TSX file with `export default\n function Page()`.\n- React 18 client component by default. Start the file with\n `\"use client\";` because every page calls the SDK from the browser.\n- shadcn/ui primitives, already vendored under `@/components/ui/*`.\n Common primitives available: `Button`, `Card` (with `CardHeader`,\n `CardTitle`, `CardDescription`, `CardContent`, `CardFooter`),\n `Input`, `Label`, `Table` (`TableHeader`, `TableBody`, `TableHead`,\n `TableRow`, `TableCell`, `TableCaption`), `Dialog`, `Sheet`,\n `Tabs`, `Select`, `Pagination`, `Badge`, `Skeleton`. Compose them.\n- Tailwind utilities for layout and spacing. The CSS variables behind\n shadcn (`--background`, `--foreground`, `--primary`, \u2026) are\n configured in `globals.css`. Stick to the design tokens unless the\n design theme asks for otherwise.\n- TypeScript strict. No `any` cast that isn't justified by the SDK\n surface. Use the SDK's exported types directly.\n\n## SDK access\n\nThe bundled SDK adapter exposes the AutoBE-generated API like this:\n\n```ts\nimport api from \"@/src/api\";\nimport { connection } from \"@/src/lib/connection\";\n```\n\nEvery accessor takes **`(connection, props)`**. The shape of `props` is\nfixed by Nestia and **must** match the operation's path parameters and\nrequest body. Getting this wrong is the single most common AutoView\nruntime defect, so read this section carefully before writing any\nfetch.\n\n### Nestia `props` shape \u2014 derive it from the operation, never guess\n\nFor each operation listed in the screen's `endpoints`, the operation\npayload (passed to you in the prompt) carries `parameters` (path\nparameters) and `requestBody` (body schema). Translate them into\n`props` deterministically:\n\n| Operation shape | `props` shape |\n| ------------------------------------------------------------- | ---------------------------------------------- |\n| Path parameters only (GET / DELETE, e.g. `at`, `erase`) | `{ paramA, paramB }` |\n| Body only (POST / PATCH / PUT at root, e.g. `index`, `create` at `/sales`) | `{ body: { ... } }` |\n| Path + body (PUT / PATCH / POST under `/.../:id`) | `{ id, body: { ... } }` |\n| Multiple path params + body | `{ saleId, questionId, body: { ... } }` |\n| No params, no body | `{}` (rare; only when `parameters` is empty AND `requestBody` is `null`) |\n\nConcrete examples that match the real shopping SDK exactly:\n\n```ts\n// PATCH /sales (list). `requestBody` is `IShoppingSale.IRequest`,\n// `parameters` is empty \u2192 wrap the search fields under `body`.\nconst sales = await api.functional.shoppings.customers.sales.index(\n connection,\n { body: { page: 1, limit: 24, search: { title: \"macbook\" } } },\n);\n\n// GET /sales/:id. `parameters` has `id`, `requestBody` is null \u2192\n// pass the path param at the top level, no `body`.\nconst sale = await api.functional.shoppings.customers.sales.at(\n connection,\n { id: saleId },\n);\n\n// POST /sales/:saleId/reviews. `parameters` has `saleId`,\n// `requestBody` is `IShoppingReview.ICreate` \u2192 both at the top.\nconst review = await api.functional.shoppings.customers.sales.reviews.create(\n connection,\n { saleId, body: { score: 5, title: \"great\", body: \"loved it\" } },\n);\n```\n\n**Never** put body fields at the top level of `props`. Writing\n`api.functional.sales.index(connection, { limit: 24 })` looks intuitive\nbut passes `undefined` as `props.body`; in simulate mode the SDK's\ntypia.assert rejects the call, the simulator returns a 400 error\nmasked as the success Response shape, and the UI silently renders the\nempty state because `.data` ends up as an error object whose `.length`\nis undefined. Always wrap.\n\nLikewise, **never** pass `{}` (or `{ body: {} }`) to an endpoint whose\n`requestBody` schema declares required fields. The prompt context\nincludes a \"Body required-fields hint\" block that lists every required\nkey per endpoint plus a sample literal \u2014 copy the sample shape as the\nstarting `body` and only override the fields you actually need:\n\n- `cart create` requires `commodity_ids` and `pseudos` \u2014 pass\n `{ body: { commodity_ids: [], pseudos: [] } }` when the user has not\n added anything yet, then mutate as they click \"Add to cart\". Never\n send an empty body that fails validation immediately on mount.\n- List endpoints (`index`) with required `page` / `limit` \u2014 pass\n `{ body: { page: 1, limit: 24 } }`. Even when you do not want a\n filter, the body has to satisfy the schema.\n\nIf a required field is genuinely unknown at the call site (e.g. an\nopaque id the user has not selected yet), do not issue the SDK call \u2014\ngate it behind the user action that produces the id, and render an\ninformative empty state until then.\n\nUse exactly the accessor paths listed in the screen's `endpoints` array\n\u2014 do not invent helpers or new accessors. The connection has\n`simulate: true` wired by default, so the calls will work offline.\n\n## Data fetching\n\n- `useEffect` + `useState`. Each `endpoints[]` entry maps to one async\n call. Run them in parallel with `Promise.all` unless one depends on\n another.\n- Always handle four states: `loading`, `error`, `empty`, and `data`.\n Show a `Skeleton` block during loading, a destructive `Card` for\n errors with a `Retry` button, an empty state with a one-line\n explanation when the list comes back empty, and the real UI when\n data is present.\n- Surface server error messages from `instanceof HttpError`-style\n catches. Never silently swallow.\n\n### Use SDK types directly \u2014 infer them, never hand-write them\n\nThe SDK's returned objects are typia-validated and exactly match the\ngenerated types. When `simulate: true`, `typia.random<T>()` produces\nmocks that follow those types byte-for-byte. The trap is that AutoBE's\nOpenAPI inverter sometimes emits the page shape as a **monomorphized**\ntype (e.g. `IPageIShoppingSale.ISummary`) instead of a generic\n`IPage<T>`. Importing `IPage` and writing `IPage<IShoppingSale.ISummary>`\nwill compile but `IPage` resolves to an empty namespace at runtime, so\n`useState<IPage<...> | null>(null)` produces a mock whose `.data`\nfield is `undefined` and the page crashes with\n`.filter is not a function`.\n\nThe bulletproof pattern is to let TypeScript infer the response type\nfrom the SDK function itself, not to hand-write the type name:\n\n```ts\ntype SalesResponse = Awaited<\n ReturnType<typeof api.functional.shoppings.customers.sales.index>\n>;\nconst [sales, setSales] = useState<SalesResponse | null>(null);\n// ...\nuseEffect(() => {\n api.functional.shoppings.customers.sales\n .index(connection, { body: { page: 1, limit: 24 } })\n .then(setSales);\n}, []);\n// `sales.data` is now correctly typed as `IShoppingSale.ISummary[]`\n// regardless of whether the SDK names the page `IPage<T>` or\n// `IPageIShoppingSale.ISummary`.\n```\n\nUse the `Awaited<ReturnType<typeof api.functional.xxx>>` pattern for\nevery SDK call \u2014 list endpoints and detail endpoints alike. It is\nrobust against the inverter's naming choices.\n\nOther ironclad rules:\n\n- Do not hand-type the response as `IPage<X>` unless you have\n confirmed via the inference pattern that the SDK actually exposes\n that generic. In most AutoBE-generated archives it does not.\n- Never widen with `as AnyPage<T>` / `as Record<string, unknown>` /\n `as { data?: T[] }` etc. Broad casts lose the type and push you\n into runtime guard code that crashes when the mock shape does not\n match your guess.\n- Never write fallback chains like\n `page?.data ?? page?.items ?? page?.rows ?? []`. The SDK never\n returns `items` or `rows` \u2014 only `data`. The fallback only fires\n when your type assumption is already wrong, and it hides the real\n defect behind a `.filter is not a function` runtime error.\n- Never wrap a response in a helper that returns `unknown[]`. Type\n the state with the inferred response type and call\n `.data.filter(...)` / `.data.map(...)` directly.\n- Never write `as never`, `as unknown as X`, or `as any` to push a\n value past the type checker. These casts lie about the SDK shape\n and always break at runtime. The only allowed escape is `as const`\n on inline literals.\n- Never combine optional chaining with a direct method call:\n `sale?.units.find(...)`, `cart?.items.map(...)`, `page?.data.reduce(...)`.\n When `sale` is `undefined` the whole expression evaluates to\n `undefined`, but TypeScript stops checking the `.units` access at\n the `?.` and lets the `.find` slip through. At runtime the page\n crashes with `Cannot read properties of undefined (reading 'find')`\n even though `tsc --noEmit` was green. The two safe shapes are\n `(sale?.units ?? []).find(...)` (when you want the empty fallback)\n and `sale?.units?.find(...)` (when you want the whole expression\n to short-circuit to `undefined`). Use the empty-array form for any\n array you immediately render or count; use the `?.` form when the\n result feeds another optional chain. The same rule covers\n `.map / .filter / .reduce / .some / .every / .forEach / .slice /\n .sort / .at` on arrays and `Object.keys / Object.entries /\n Object.values` on objects: `(obj?.things ?? {})` before\n `Object.keys`.\n- The same rule applies to **multi-step** property chains:\n `order?.summary.ticket_payments[0]` crashes when `summary` is\n `undefined` because the optional chain stops at `order?.` and the\n `.summary.ticket_payments[0]` access slips through. Apply `?.` to\n every nullable hop, not just the first: write\n `order?.summary?.ticket_payments?.[0]` (note the `?.[` for the\n index), or guard the parent once with\n `const summary = order?.summary; if (summary === undefined) return \u2026;`\n before the array read. The runtime audit catches dozens of these\n per shopping run when the rule is only applied to the first hop.\n- Never call a `setState` (`setX(...)`, `dispatch(...)`,\n `useTransition` start, etc.) directly inside the render body. React\n throws \"Cannot update a component while rendering a different\n component\" and the page crashes after the first render. Common\n triggers and fixes:\n - Computing derived state? Use `useMemo`, not `setState` inside the\n body.\n - Reacting to a prop change? Use `useEffect(() => { setX(...); },\n [prop])`.\n - Bailing out early on bad data? Render a fallback `<>...</>`\n directly \u2014 do **not** call `setError(...)` mid-render.\n - Need to sync with an external store? Use `useSyncExternalStore`\n or move the side effect into `useEffect`.\n Setter calls are always either inside an event handler, inside a\n `useEffect` (or its return), or inside a `useMemo`/`useCallback`\n dependency-aware factory \u2014 never at the top level of the component\n function.\n\nIf the screen's accessor returns a single object (not a page), the\nsame inference pattern works \u2014 `type SaleResponse = Awaited<ReturnType<\ntypeof api.functional.shoppings.customers.sales.at>>` and\n`useState<SaleResponse | null>(null)`.\n\n### Retry, refetch, and pagination handlers must produce new values\n\nState setters in click handlers must change the state. Patterns like\n`onClick={() => setPage((p) => p)}` or `onClick={() => setData(data)}`\ndo nothing \u2014 the user clicks \"Retry\" and the page does not reset.\nConcrete rules:\n\n- Retry buttons reset to the initial state and re-run the load\n effect: `setError(null); setLoading(true); setPage(1); refresh();`.\n- Pagination buttons update to the new page: `setPage(page + 1)` /\n `setPage(page - 1)`. Never `setPage((p) => p)`.\n- Refresh / refetch buttons should trigger the same `useEffect` that\n the initial load uses \u2014 either via a bumped `refreshKey` state or a\n dedicated `refresh()` callback.\n\n## Rendering SDK objects \u2014 never dump, always pick named fields\n\nThe SDK returns typed objects. Render only the fields you can name\nfrom the operation's `responseBody` and the schema (`name`, `title`,\n`code`, `nickname`, `status`, `price`, `summary`, `created_at`, \u2026). If\nyou do not know which field to show, choose `name ?? title ?? code ??\nid` and stop \u2014 never reach for the whole object.\n\n**Strict ban on object dumps in JSX**. The model has a strong tendency\nto escape unknown shapes by writing `{JSON.stringify(item)}` (or\n`item.toString()`, or `<pre>{JSON.stringify(item, null, 2)}</pre>`)\nstraight into a `Card` / `TableCell` / `div`. This is forbidden in\nevery form, including:\n\n- `<div>{JSON.stringify(channel)}</div>`\n- `<TableCell>{JSON.stringify(sale).slice(0, 60)}</TableCell>`\n- `<pre>{JSON.stringify(channel, null, 2)}</pre>`\n- `<span>{String(item)}</span>` for any non-primitive `item`\n- `{`${item.id}: ${JSON.stringify(item)}`}`\n\nThe rendered page is a product surface, not a debug view. A page that\ndumps JSON looks broken even when the data flowed correctly.\n\nAllowed substitutes when the data is unfamiliar mock content:\n\n- Pick the most identifying string field from the schema (`name`,\n `title`, `nickname`, `code`) and show that.\n- If multiple objects share the same shape, render them in a `Table`\n with one column per known field plus a trailing \"Details\" link that\n navigates to the detail page declared in the product plan.\n- For truly opaque payloads (rare; only when the schema is `unknown`\n or `Record<string, never>`), render a single muted line such as\n \"Imported entry \u00B7 click Inspect to view raw fields\" rather than the\n JSON itself.\n\n**Long string overflow**. Mock data from `typia.random()` regularly\nproduces 50+ character UUIDs, slugs, and base64-like values for `code`\n/ `name` / `description` fields. Every string element you render from\nthe SDK must be wrapped with overflow controls so it cannot blow out\nthe column:\n\n- Single-line cells / headers: add `truncate` (single line, ellipsis).\n- Multi-line descriptions: add `line-clamp-2` or `line-clamp-3`.\n- Free-form text inside cards: add `break-words` so long words wrap.\n- Inside `<TableCell>`: combine `max-w-xs truncate` (or wider) so the\n table layout stays within the container.\n\nSkipping these classes produces the \"horizontal scroll bar of doom\"\nthat pushes the search bar and pagination buttons off-screen.\n\n## Routing\n\n- Dynamic params come from `useParams()` from `next/navigation`.\n- Internal navigation uses `Link` from `next/link` or\n `useRouter().push()`. No external links unless the SDK returns them\n explicitly.\n\n## Responsive shape\n\n- Mobile-first. The page must be usable at 360px width.\n- Use Tailwind responsive prefixes (`sm:`, `md:`, `lg:`) when laying\n out grids, tables, or sidebars.\n- Tables collapse to stacked cards on `sm` and below for shopping /\n catalog-style flows; admin tables can stay tabular if the design\n theme says enterprise.\n\n## Forms\n\n- `react-hook-form` is available \u2014 use it for any input with two or\n more fields. Wire `Input` / `Select` / `Label` to the form state.\n- Validate on submit, not on every keystroke (avoid flicker).\n- Disable the submit button while the SDK call is in flight.\n- Toast the result with a `Card` or inline `Badge` rather than\n `alert()`.\n\n## What the produced TSX MUST contain\n\n- `\"use client\";` at the top.\n- A single default export named `Page`.\n- All imports resolved against `@/...` (alias for repo root) or\n `next/*`.\n- Real data wiring through the listed SDK endpoints, not fake static\n arrays.\n- All four UI states (loading / error / empty / data).\n- Tailwind classes that satisfy the design theme. Empty design theme\n means prototype-first, content-first defaults.\n\n## What you must NOT produce\n\n- Do not invent SDK accessors. Use what `endpoints[]` declares.\n- Do not flatten request bodies into the top level of `props`. List\n endpoints take `{ body: { page, limit, search, sort } }`, not\n `{ page, limit, search, sort }`. Passing the flat shape causes the\n simulator to return a masked 400 and the page renders the empty\n state instead of data \u2014 see the \"Nestia `props` shape\" subsection.\n- Do not pass an empty `{}` to a list endpoint. List endpoints have a\n required `body`; the minimum is `{ body: { page: 1, limit: 24 } }`.\n- Do not dump SDK objects with `JSON.stringify(item)`,\n `String(item)`, `item.toString()`, or `<pre>{JSON.stringify(item,\n null, 2)}</pre>` inside JSX. The page is a product surface, not a\n debug view \u2014 see the \"Rendering SDK objects\" section above for the\n allowed alternatives.\n- Do not omit overflow controls on SDK-derived strings. Every\n `<TableCell>` / `<div>` / `<span>` that prints a mock string needs\n `truncate`, `line-clamp-N`, or `break-words` so a 60-character UUID\n cannot push the layout off-screen.\n- Do not import shadcn primitives the project does not ship. Stick to\n the list above.\n- Do not declare local `AnyPage<T>` / `AnyResponse` aliases or\n `getItems()` helpers \u2014 see the \"Use SDK types directly\" rule above.\n Import the SDK type and reach into `.data` straight away.\n- Do not write `as never`, `as any`, or `as unknown as X`. These casts\n silently break the SDK type contract and crash at runtime. The one\n allowed escape is `as const` on inline literals.\n- Do not write identity state updates like `setPage((p) => p)` or\n `setData(data)` in retry / refetch / pagination handlers. Every\n setter call must produce a new value \u2014 see the \"Retry, refetch,\n and pagination\" rules under Data fetching.\n- Do not write `a ?? b || c` or `a || b ?? c`. TC39 forbids mixing\n `??` with `||` / `&&` without parentheses, and the parser will\n reject the page. If you really need both, parenthesize explicitly:\n `(a ?? b) || c`. Same rule applies inside JSX attribute values.\n Easier: **avoid `??` in any expression that already contains `||`\n or `&&`**. Use a ternary instead (e.g.\n `(a !== null && a !== undefined) ? a : (b || c)`) or just chain\n `||` everywhere. The retry loop will not save you here; pages that\n mix `??` with `||` consistently get dropped to an error\n placeholder.\n- Do not link to backend / SDK accessor paths from `<Link>` or\n `router.push()`. Those paths (e.g.\n `/shoppings/customers/systematic/channels`, `/shoppings/customers/sales/:id`)\n are HTTP endpoints, not Next.js routes. The product plan lists\n every real frontend route in `screen.path`. Use only those \u2014\n `/catalog`, `/cart`, `/orders/[id]`, `/admin`, etc. Internal links\n to anything else 404 the moment a user clicks them.\n- Do not render `<Image />` from `next/image` for URLs the SDK\n returns. The SDK mocks emit arbitrary hostnames and the optimizer\n rejects them. Use a plain `<img />` tag for SDK-provided URLs, or\n pass `unoptimized` on the `<Image />` element.\n- Do not write Korean.\n- Do not output anything except the function-call payload.\n\n## Output\n\nCall `renderPage` exactly once with the complete TSX source code as a\nsingle string. The orchestrator runs the result through the TypeScript\nparser; if it fails, you will be invoked again with the diagnostic and\na chance to repair it. Take the repair seriously \u2014 the most common LLM\nerrors are `??` mixed with `||` without parentheses, regex literals\nwith unescaped slashes, and unclosed JSX expression braces." /* AutoViewSystemPromptConstant.AUTOVIEW_RENDER */),
|
|
404
|
+
HistoryMessage_1.HistoryMessage.assistant `
|
|
405
|
+
Here is the screen to render and everything you need to compose
|
|
406
|
+
it.
|
|
407
|
+
|
|
408
|
+
## Screen
|
|
409
|
+
|
|
410
|
+
\`\`\`json
|
|
411
|
+
${JSON.stringify(args.screen, null, 2)}
|
|
412
|
+
\`\`\`
|
|
413
|
+
|
|
414
|
+
## Allowed internal route paths (use only these in \`<Link href=...>\` / \`router.push()\`)
|
|
415
|
+
|
|
416
|
+
${args.allScreenPaths.map((p) => `- \`${p}\``).join("\n")}
|
|
417
|
+
|
|
418
|
+
## SDK call signatures (use these \`props\` shapes verbatim)
|
|
419
|
+
|
|
420
|
+
${propsSignatures}
|
|
421
|
+
|
|
422
|
+
## Body required-fields hint (start each \`body: { ... }\` with at least these keys)
|
|
423
|
+
|
|
424
|
+
${bodyHints.length > 0 ? bodyHints : "(no endpoints with a request body)"}
|
|
425
|
+
|
|
426
|
+
## SDK return type shapes (use these exact field names + nesting — do not invent properties)
|
|
427
|
+
|
|
428
|
+
${responseShapes.length > 0 ? responseShapes : "(no endpoints with a response body)"}
|
|
429
|
+
|
|
430
|
+
## SDK request body shapes (use these exact field names + nesting — do not invent properties)
|
|
431
|
+
|
|
432
|
+
${requestShapes.length > 0 ? requestShapes : "(no endpoints with a request body)"}
|
|
433
|
+
|
|
434
|
+
## SDK endpoints used by this screen (full operation payloads)
|
|
435
|
+
|
|
436
|
+
\`\`\`json
|
|
437
|
+
${JSON.stringify(args.relevantOperations, null, 2)}
|
|
438
|
+
\`\`\`
|
|
439
|
+
|
|
440
|
+
## Design theme
|
|
441
|
+
|
|
442
|
+
${args.designTheme.length > 0 ? args.designTheme : "(none — prototype-first, content-first defaults)"}
|
|
443
|
+
|
|
444
|
+
## Actor context (from the SDK map)
|
|
445
|
+
|
|
446
|
+
\`\`\`json
|
|
447
|
+
${JSON.stringify((_a = args.sdkMap.actors.find((a) => a.name === args.screen.actor)) !== null && _a !== void 0 ? _a : null, null, 2)}
|
|
448
|
+
\`\`\`
|
|
449
|
+
`,
|
|
450
|
+
];
|
|
451
|
+
}
|
|
452
|
+
function buildRetryHistories(args) {
|
|
453
|
+
return [
|
|
454
|
+
...buildInitialHistories(args),
|
|
455
|
+
HistoryMessage_1.HistoryMessage.assistant `
|
|
456
|
+
My previous attempt failed TypeScript syntax check.
|
|
457
|
+
|
|
458
|
+
## Previous TSX
|
|
459
|
+
|
|
460
|
+
\`\`\`tsx
|
|
461
|
+
${args.lastTsx}
|
|
462
|
+
\`\`\`
|
|
463
|
+
|
|
464
|
+
## Syntax error reported by the compiler
|
|
465
|
+
|
|
466
|
+
\`\`\`
|
|
467
|
+
${args.lastError}
|
|
468
|
+
\`\`\`
|
|
469
|
+
`,
|
|
470
|
+
];
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* History builder for the typecheck-driven retry pass. Differs from
|
|
474
|
+
* {@link buildRetryHistories} in that it lists every `tsc --noEmit` diagnostic
|
|
475
|
+
* on this file (not a single parser error) and explicitly anchors the LLM to
|
|
476
|
+
* the SDK-shape sections from the initial history — the typical failure mode is
|
|
477
|
+
* the model inventing property names that look plausible against domain priors
|
|
478
|
+
* instead of reading the schema we already spelled out.
|
|
479
|
+
*/
|
|
480
|
+
function buildTypecheckRetryHistories(args) {
|
|
481
|
+
const lines = args.typecheckErrors
|
|
482
|
+
.map((e) => `- L${e.line}:${e.column} \`${e.code}\` — ${e.message}`)
|
|
483
|
+
.join("\n");
|
|
484
|
+
return [
|
|
485
|
+
...buildInitialHistories(args),
|
|
486
|
+
HistoryMessage_1.HistoryMessage.assistant `
|
|
487
|
+
My previous attempt compiled cleanly but failed \`tsc --noEmit\` against
|
|
488
|
+
the assembled project. The errors all anchor on the SDK boundary — they
|
|
489
|
+
are caused by accessing properties, calling functions, or passing values
|
|
490
|
+
whose shape does not match what the SDK actually exposes.
|
|
491
|
+
|
|
492
|
+
## Previous TSX
|
|
493
|
+
|
|
494
|
+
\`\`\`tsx
|
|
495
|
+
${args.previousTsx}
|
|
496
|
+
\`\`\`
|
|
497
|
+
|
|
498
|
+
## TypeScript errors on this file
|
|
499
|
+
|
|
500
|
+
${lines}
|
|
501
|
+
|
|
502
|
+
Re-emit the entire page TSX with these errors fixed. Use only field
|
|
503
|
+
names and call signatures that match the "SDK return type shapes" and
|
|
504
|
+
"SDK request body shapes" sections above — do not invent properties,
|
|
505
|
+
do not assume snake_case when the schema uses camelCase, and do not add
|
|
506
|
+
a second argument to a parameterless endpoint.
|
|
507
|
+
`,
|
|
508
|
+
];
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* History builder for the Phase 6 runtime-driven retry pass. The Playwright
|
|
512
|
+
* audit captures console errors, uncaught page exceptions, and navigation
|
|
513
|
+
* failures that the parser + typecheck gates cannot see — typically
|
|
514
|
+
* `obj?.array.method(...)` undefined-access on simulator data, react render
|
|
515
|
+
* crashes against missing optional fields, or hydration mismatches. Surfacing
|
|
516
|
+
* the captured messages back into the render prompt lets the LLM rewrite the
|
|
517
|
+
* page against the actual failure mode instead of guessing.
|
|
518
|
+
*/
|
|
519
|
+
function buildRuntimeRetryHistories(args) {
|
|
520
|
+
const lines = args.runtimeErrors
|
|
521
|
+
.map((e) => `- \`${e.type}\` — ${e.message}`)
|
|
522
|
+
.join("\n");
|
|
523
|
+
return [
|
|
524
|
+
...buildInitialHistories(args),
|
|
525
|
+
HistoryMessage_1.HistoryMessage.assistant `
|
|
526
|
+
My previous attempt typechecked cleanly but crashed at runtime when
|
|
527
|
+
Playwright loaded it under \`next dev\` (simulator mode). The errors
|
|
528
|
+
below are the live console / uncaught exception / navigation
|
|
529
|
+
diagnostics — typescript could not see them because the access pattern
|
|
530
|
+
uses optional chaining that short-circuits past the unsafe call site.
|
|
531
|
+
|
|
532
|
+
## Previous TSX
|
|
533
|
+
|
|
534
|
+
\`\`\`tsx
|
|
535
|
+
${args.previousTsx}
|
|
536
|
+
\`\`\`
|
|
537
|
+
|
|
538
|
+
## Runtime errors on this page
|
|
539
|
+
|
|
540
|
+
${lines}
|
|
541
|
+
|
|
542
|
+
Re-emit the entire page TSX with these errors fixed. Common causes:
|
|
543
|
+
- \`obj?.array.method(...)\` — fix by writing \`(obj?.array ?? []).method(...)\`
|
|
544
|
+
or \`obj?.array?.method(...)\` so the short-circuit covers the call.
|
|
545
|
+
- Property access on a value that can be \`null\`/\`undefined\` in
|
|
546
|
+
simulator data — narrow with explicit guards before reading.
|
|
547
|
+
- Components that crash on empty arrays — render an empty state when
|
|
548
|
+
the SDK returns \`[]\`.
|
|
549
|
+
Use only field names and shapes from the "SDK return type shapes" and
|
|
550
|
+
"SDK request body shapes" sections above. Do not invent properties.
|
|
551
|
+
`,
|
|
552
|
+
];
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Re-render a single screen after the Phase 6 runtime audit reported broken
|
|
556
|
+
* navigation / console / pageerror diagnostics on its page. Identical
|
|
557
|
+
* retry-loop shape to {@link rerenderScreenForTypecheck}: the first attempt uses
|
|
558
|
+
* {@link buildRuntimeRetryHistories} (which surfaces the live runtime errors +
|
|
559
|
+
* previous TSX) and any subsequent retries fall back to
|
|
560
|
+
* {@link buildRetryHistories} so the parser-driven safety net still applies.
|
|
561
|
+
*
|
|
562
|
+
* Returns `null` when the model could not produce parser-valid TSX after the
|
|
563
|
+
* full retry budget; the caller should leave the existing (broken) file in
|
|
564
|
+
* place.
|
|
565
|
+
*/
|
|
566
|
+
function rerenderScreenForRuntime(ctx, args) {
|
|
567
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
568
|
+
var _a;
|
|
569
|
+
const relevantOperations = (0, utils_1.toEndpoints)(args.document).filter((op) => { var _a; return args.screen.endpoints.includes(((_a = op.accessor) !== null && _a !== void 0 ? _a : []).join(".")); });
|
|
570
|
+
let previousTsx = args.previousTsx;
|
|
571
|
+
let lastParseError = null;
|
|
572
|
+
for (let attempt = 0; attempt <= MAX_PARSE_RETRIES; attempt++) {
|
|
573
|
+
const pointer = {
|
|
574
|
+
value: null,
|
|
575
|
+
};
|
|
576
|
+
const histories = attempt === 0
|
|
577
|
+
? buildRuntimeRetryHistories(Object.assign(Object.assign({}, args), { relevantOperations,
|
|
578
|
+
previousTsx, runtimeErrors: args.runtimeErrors }))
|
|
579
|
+
: buildRetryHistories(Object.assign(Object.assign({}, args), { relevantOperations, lastTsx: previousTsx, lastError: lastParseError !== null && lastParseError !== void 0 ? lastParseError : "" }));
|
|
580
|
+
const userMessage = attempt === 0
|
|
581
|
+
? `Fix the runtime errors on ${args.screen.path}. Re-emit the entire page TSX with the corrections. Call \`renderPage\` once.`
|
|
582
|
+
: `The corrected attempt failed TypeScript parsing: ${lastParseError}. Regenerate the entire page TSX with the fix applied.`;
|
|
583
|
+
try {
|
|
584
|
+
yield ctx.conversate({
|
|
585
|
+
source: "autoViewRenderPage",
|
|
586
|
+
target: args.screen.path,
|
|
587
|
+
controller: createController({
|
|
588
|
+
build: (next) => {
|
|
589
|
+
pointer.value = next;
|
|
590
|
+
},
|
|
591
|
+
}),
|
|
592
|
+
enforceFunctionCall: true,
|
|
593
|
+
promptCacheKey: args.promptCacheKey,
|
|
594
|
+
histories,
|
|
595
|
+
userMessage,
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
catch (error) {
|
|
599
|
+
// Vendor-side failure during the runtime-driven retry. Same policy
|
|
600
|
+
// as the typecheck retry: record, retry, and fall through to `null`
|
|
601
|
+
// so the caller keeps the previous file rather than aborting.
|
|
602
|
+
lastParseError = error instanceof Error ? error.message : String(error);
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
if (pointer.value === null) {
|
|
606
|
+
lastParseError = "model did not call renderPage";
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
609
|
+
const candidate = (_a = autoWrapNullishCoalescingMix(pointer.value.tsx)) !== null && _a !== void 0 ? _a : pointer.value.tsx;
|
|
610
|
+
const parseError = findSyntaxError(candidate);
|
|
611
|
+
if (parseError === null) {
|
|
612
|
+
return { tsx: candidate, ok: true, diagnostic: "" };
|
|
613
|
+
}
|
|
614
|
+
previousTsx = candidate;
|
|
615
|
+
lastParseError = parseError;
|
|
616
|
+
}
|
|
617
|
+
return null;
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
/* -------------------------------------------------------------------------- */
|
|
621
|
+
/* syntax validation */
|
|
622
|
+
/* -------------------------------------------------------------------------- */
|
|
623
|
+
/**
|
|
624
|
+
* Run the rendered TSX through TypeScript's tolerant parser plus a focused
|
|
625
|
+
* regex for `??` / `||` mixing — the model's most common grammar error that the
|
|
626
|
+
* parser flags only post-parse.
|
|
627
|
+
*/
|
|
628
|
+
/**
|
|
629
|
+
* Walk the TypeScript AST and parenthesize every `??` branch that sits directly
|
|
630
|
+
* inside a `||` / `&&` expression, and vice versa. TC39 forbids mixing the two
|
|
631
|
+
* without explicit parens, and even with the prompt rule the model keeps
|
|
632
|
+
* re-emitting `a ?? b || c`. Doing it deterministically after the LLM call
|
|
633
|
+
* costs no extra inference and avoids the retry budget being burned on
|
|
634
|
+
* grammar-only defects.
|
|
635
|
+
*
|
|
636
|
+
* Returns the rewritten source when at least one fix landed, `null` when
|
|
637
|
+
* nothing needed changing or the rewrite failed validation (so the caller can
|
|
638
|
+
* fall back to the original text).
|
|
639
|
+
*/
|
|
640
|
+
const NULLISH_MIX_REGEX = /\?\?[^()?|]{0,400}\|\||\|\|[^()|?]{0,400}\?\?|\?\?[^()?&]{0,400}&&|&&[^()&?]{0,400}\?\?/;
|
|
641
|
+
/**
|
|
642
|
+
* Last-resort textual rewrite for the cases the AST visitor below cannot reach
|
|
643
|
+
* (parser bails out at the diagnostic, printer optimizes the parens away,
|
|
644
|
+
* etc.). Iteratively wraps every `??`-pair adjacent to a `||` or `&&` token.
|
|
645
|
+
* Pattern recognizes identifiers, dotted property access, subscript access,
|
|
646
|
+
* function calls with no nested parens, and template literals — enough to
|
|
647
|
+
* handle the LLM's typical landing-page expressions.
|
|
648
|
+
*
|
|
649
|
+
* Conservative on purpose: complex expressions where the operands cross parens
|
|
650
|
+
* or another operator are left alone, so the retry loop still has the original
|
|
651
|
+
* code to repair from.
|
|
652
|
+
*/
|
|
653
|
+
function regexWrapNullishMix(code) {
|
|
654
|
+
// An "atom" the wrapper is comfortable picking up as one of the
|
|
655
|
+
// `??` operands. Covers:
|
|
656
|
+
// - identifiers and dotted chains (`obj.foo.bar`)
|
|
657
|
+
// - optional chains (`obj?.foo?.bar`)
|
|
658
|
+
// - subscript access (`arr[i]`, single-level)
|
|
659
|
+
// - balanced function calls (`fn(...)`, single nesting level)
|
|
660
|
+
// - type-cast wrappers (`(value as Type)` and `(value as Type).prop`)
|
|
661
|
+
// - string / number / boolean / null literals
|
|
662
|
+
// - empty / shallow array / object literals (`[]`, `{}`)
|
|
663
|
+
// Anything more exotic falls back to the AST visitor or the retry
|
|
664
|
+
// budget — but this covers ~95% of LLM-generated landing-page code.
|
|
665
|
+
const ID = String.raw `[A-Za-z_$][\w$]*`;
|
|
666
|
+
const CAST = String.raw `\(\s*${ID}(?:\.${ID})*\s+as\s+[A-Za-z_$][\w$<>.,\s\[\]?|&]*?\s*\)`;
|
|
667
|
+
const LITERAL = String.raw `"[^"\n]{0,80}"|'[^'\n]{0,80}'|\d+(?:\.\d+)?|true|false|null|undefined|\[\s*\]|\{\s*\}`;
|
|
668
|
+
const HEAD = String.raw `(?:${LITERAL}|${CAST}|${ID})`;
|
|
669
|
+
const TAIL = String.raw `(?:\??\.${ID}|\[[^\[\]\n]{1,80}\]|\([^()\n]{0,200}\))*`;
|
|
670
|
+
const ATOM = `${HEAD}${TAIL}`;
|
|
671
|
+
const pairs = [
|
|
672
|
+
[
|
|
673
|
+
new RegExp(`(?<![\\w(])(${ATOM}\\s*\\?\\?\\s*${ATOM})(\\s*(?:\\|\\||&&))`, "g"),
|
|
674
|
+
"($1)$2",
|
|
675
|
+
],
|
|
676
|
+
[
|
|
677
|
+
new RegExp(`((?:\\|\\||&&)\\s*)(${ATOM}\\s*\\?\\?\\s*${ATOM})(?![\\w)])`, "g"),
|
|
678
|
+
"$1($2)",
|
|
679
|
+
],
|
|
680
|
+
];
|
|
681
|
+
let prev = "";
|
|
682
|
+
let curr = code;
|
|
683
|
+
let iterations = 0;
|
|
684
|
+
while (prev !== curr && iterations < 10) {
|
|
685
|
+
prev = curr;
|
|
686
|
+
for (const [re, replacement] of pairs) {
|
|
687
|
+
curr = curr.replace(re, replacement);
|
|
688
|
+
}
|
|
689
|
+
iterations++;
|
|
690
|
+
}
|
|
691
|
+
return curr;
|
|
692
|
+
}
|
|
693
|
+
function autoWrapNullishCoalescingMix(code) {
|
|
694
|
+
const source = typescript_1.default.createSourceFile("Page.tsx", code, typescript_1.default.ScriptTarget.ES2022,
|
|
695
|
+
/*setParentNodes*/ true, typescript_1.default.ScriptKind.TSX);
|
|
696
|
+
let changed = false;
|
|
697
|
+
const isNullish = (n) => typescript_1.default.isBinaryExpression(n) &&
|
|
698
|
+
n.operatorToken.kind === typescript_1.default.SyntaxKind.QuestionQuestionToken;
|
|
699
|
+
const isLogical = (n) => typescript_1.default.isBinaryExpression(n) &&
|
|
700
|
+
(n.operatorToken.kind === typescript_1.default.SyntaxKind.BarBarToken ||
|
|
701
|
+
n.operatorToken.kind === typescript_1.default.SyntaxKind.AmpersandAmpersandToken);
|
|
702
|
+
const transformer = (context) => {
|
|
703
|
+
const visit = (node) => {
|
|
704
|
+
const visited = typescript_1.default.visitEachChild(node, visit, context);
|
|
705
|
+
if (!typescript_1.default.isBinaryExpression(visited))
|
|
706
|
+
return visited;
|
|
707
|
+
const wrap = (child) => {
|
|
708
|
+
changed = true;
|
|
709
|
+
return typescript_1.default.factory.createParenthesizedExpression(child);
|
|
710
|
+
};
|
|
711
|
+
const op = visited.operatorToken.kind;
|
|
712
|
+
if (op === typescript_1.default.SyntaxKind.BarBarToken ||
|
|
713
|
+
op === typescript_1.default.SyntaxKind.AmpersandAmpersandToken) {
|
|
714
|
+
return typescript_1.default.factory.updateBinaryExpression(visited, isNullish(visited.left) ? wrap(visited.left) : visited.left, visited.operatorToken, isNullish(visited.right) ? wrap(visited.right) : visited.right);
|
|
715
|
+
}
|
|
716
|
+
if (op === typescript_1.default.SyntaxKind.QuestionQuestionToken) {
|
|
717
|
+
return typescript_1.default.factory.updateBinaryExpression(visited, isLogical(visited.left) ? wrap(visited.left) : visited.left, visited.operatorToken, isLogical(visited.right) ? wrap(visited.right) : visited.right);
|
|
718
|
+
}
|
|
719
|
+
return visited;
|
|
720
|
+
};
|
|
721
|
+
return (root) => typescript_1.default.visitNode(root, visit);
|
|
722
|
+
};
|
|
723
|
+
const result = typescript_1.default.transform(source, [transformer]);
|
|
724
|
+
const printer = typescript_1.default.createPrinter({
|
|
725
|
+
newLine: typescript_1.default.NewLineKind.LineFeed,
|
|
726
|
+
removeComments: false,
|
|
727
|
+
});
|
|
728
|
+
let printed = changed ? printer.printFile(result.transformed[0]) : code;
|
|
729
|
+
result.dispose();
|
|
730
|
+
// Fallback for cases the AST visitor cannot reach (TS parser bails
|
|
731
|
+
// out at the diagnostic, the printer optimizes the parens away,
|
|
732
|
+
// etc.). Iteratively wrap remaining `?? ||` / `?? &&` pairs with a
|
|
733
|
+
// textual rewrite limited to atomic operands. Brute force but
|
|
734
|
+
// reliable for the LLM's typical landing-page expressions.
|
|
735
|
+
if (NULLISH_MIX_REGEX.test(printed)) {
|
|
736
|
+
const swept = regexWrapNullishMix(printed);
|
|
737
|
+
if (swept !== printed) {
|
|
738
|
+
printed = swept;
|
|
739
|
+
changed = true;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
if (!changed)
|
|
743
|
+
return null;
|
|
744
|
+
// Safety net: only return the rewrite when it actually clears the
|
|
745
|
+
// grammar-error regex. If both AST and the textual fallback gave up,
|
|
746
|
+
// leave the original alone so the retry loop still has a shot.
|
|
747
|
+
if (NULLISH_MIX_REGEX.test(printed)) {
|
|
748
|
+
return null;
|
|
749
|
+
}
|
|
750
|
+
return printed;
|
|
751
|
+
}
|
|
752
|
+
function findSyntaxError(code) {
|
|
753
|
+
var _a;
|
|
754
|
+
const source = typescript_1.default.createSourceFile("Page.tsx", code, typescript_1.default.ScriptTarget.ES2022,
|
|
755
|
+
/*setParentNodes*/ false, typescript_1.default.ScriptKind.TSX);
|
|
756
|
+
const diagnostics = (_a = source
|
|
757
|
+
.parseDiagnostics) !== null && _a !== void 0 ? _a : [];
|
|
758
|
+
if (diagnostics.length > 0) {
|
|
759
|
+
const first = diagnostics[0];
|
|
760
|
+
const message = typeof first.messageText === "string"
|
|
761
|
+
? first.messageText
|
|
762
|
+
: first.messageText.messageText;
|
|
763
|
+
if (first.start !== undefined) {
|
|
764
|
+
const { line, character } = source.getLineAndCharacterOfPosition(first.start);
|
|
765
|
+
// Line + column alone is not enough for the model to fix the
|
|
766
|
+
// error — it cannot see the source, so it tends to repeat the
|
|
767
|
+
// same defect. Include a small slice of the surrounding code so
|
|
768
|
+
// the retry attempt has concrete context.
|
|
769
|
+
const lines = code.split("\n");
|
|
770
|
+
const start = Math.max(0, line - 2);
|
|
771
|
+
const end = Math.min(lines.length, line + 3);
|
|
772
|
+
const snippet = lines
|
|
773
|
+
.slice(start, end)
|
|
774
|
+
.map((text, idx) => {
|
|
775
|
+
const lineNo = start + idx + 1;
|
|
776
|
+
const marker = lineNo === line + 1 ? ">" : " ";
|
|
777
|
+
return `${marker} ${lineNo.toString().padStart(4, " ")} | ${text}`;
|
|
778
|
+
})
|
|
779
|
+
.join("\n");
|
|
780
|
+
return `Line ${line + 1}, column ${character + 1}: ${message}\n\n${snippet}`;
|
|
781
|
+
}
|
|
782
|
+
return message;
|
|
783
|
+
}
|
|
784
|
+
if (NULLISH_MIX_REGEX.test(code)) {
|
|
785
|
+
return "Mixing `??` with `||` / `&&` is a TC39 grammar error — wrap the nullish-coalescing branch in parentheses (e.g. `(a ?? b) || c`).";
|
|
786
|
+
}
|
|
787
|
+
return null;
|
|
788
|
+
}
|
|
789
|
+
/* -------------------------------------------------------------------------- */
|
|
790
|
+
/* path mapping + placeholder fallback */
|
|
791
|
+
/* -------------------------------------------------------------------------- */
|
|
792
|
+
/**
|
|
793
|
+
* Map a planner-emitted screen path (`/`, `/cart`, `/todos/[id]/edit`) to the
|
|
794
|
+
* Next.js app-router file the scaffold writes for it. Exposed so the
|
|
795
|
+
* typecheck-driven retry loop can look up which screen owns a given broken file
|
|
796
|
+
* and re-render it directly.
|
|
797
|
+
*/
|
|
798
|
+
function screenPathToFile(routePath) {
|
|
799
|
+
const trimmed = routePath.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
800
|
+
if (trimmed.length === 0)
|
|
801
|
+
return "app/page.tsx";
|
|
802
|
+
return `app/${trimmed}/page.tsx`;
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Inverse of {@link screenPathToFile}. Returns `null` when the path does not
|
|
806
|
+
* match the `app/.../page.tsx` shape the scaffold writes — e.g. for shared
|
|
807
|
+
* components or wiki files, which are not screen-owned and therefore cannot be
|
|
808
|
+
* fixed by re-rendering a single screen.
|
|
809
|
+
*/
|
|
810
|
+
function fileToScreenPath(filePath) {
|
|
811
|
+
if (filePath === "app/page.tsx")
|
|
812
|
+
return "/";
|
|
813
|
+
const match = /^app\/(.+)\/page\.tsx$/.exec(filePath);
|
|
814
|
+
if (match === null)
|
|
815
|
+
return null;
|
|
816
|
+
return `/${match[1]}`;
|
|
817
|
+
}
|
|
818
|
+
function buildPlaceholderPage(screen, reason) {
|
|
819
|
+
const title = JSON.stringify(screen.title);
|
|
820
|
+
const purpose = JSON.stringify(screen.purpose);
|
|
821
|
+
const pattern = JSON.stringify(screen.uiPattern);
|
|
822
|
+
const actor = JSON.stringify(screen.actor);
|
|
823
|
+
const endpointsArrayLit = JSON.stringify(screen.endpoints);
|
|
824
|
+
const reasonLit = JSON.stringify(reason);
|
|
825
|
+
return `"use client";
|
|
826
|
+
|
|
827
|
+
// AutoView Render: this page failed to generate cleanly after the
|
|
828
|
+
// retry budget. The placeholder keeps \`next build\` green; check
|
|
829
|
+
// \`wiki/sdk-feedback.md\` for the root cause.
|
|
830
|
+
|
|
831
|
+
export default function Page() {
|
|
832
|
+
const endpoints: readonly string[] = ${endpointsArrayLit};
|
|
833
|
+
return (
|
|
834
|
+
<main className="container mx-auto py-10">
|
|
835
|
+
<p className="text-xs uppercase tracking-wide text-destructive">
|
|
836
|
+
AutoView render failed · {${pattern}}
|
|
837
|
+
</p>
|
|
838
|
+
<h1 className="mt-2 text-3xl font-bold tracking-tight">{${title}}</h1>
|
|
839
|
+
<p className="mt-3 text-muted-foreground">{${purpose}}</p>
|
|
840
|
+
<p className="mt-2 text-xs text-muted-foreground">
|
|
841
|
+
Actor: <span className="font-mono">{${actor}}</span>
|
|
842
|
+
</p>
|
|
843
|
+
{endpoints.length > 0 ? (
|
|
844
|
+
<div className="mt-4 rounded-md border bg-muted/30 p-3">
|
|
845
|
+
<p className="text-xs font-medium uppercase tracking-wide text-muted-foreground">
|
|
846
|
+
Planned SDK endpoints
|
|
847
|
+
</p>
|
|
848
|
+
<ul className="mt-2 space-y-1 text-xs font-mono">
|
|
849
|
+
{endpoints.map((accessor) => (
|
|
850
|
+
<li key={accessor}>{accessor}</li>
|
|
851
|
+
))}
|
|
852
|
+
</ul>
|
|
853
|
+
</div>
|
|
854
|
+
) : null}
|
|
855
|
+
<details className="mt-6 rounded-lg border border-destructive/40 bg-destructive/5 p-4">
|
|
856
|
+
<summary className="cursor-pointer text-sm font-medium text-destructive">Show parser diagnostic</summary>
|
|
857
|
+
<pre className="mt-2 whitespace-pre-wrap text-xs text-muted-foreground">{${reasonLit}}</pre>
|
|
858
|
+
</details>
|
|
859
|
+
</main>
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
`;
|
|
863
|
+
}
|
|
864
|
+
/* -------------------------------------------------------------------------- */
|
|
865
|
+
/* controller wiring */
|
|
866
|
+
/* -------------------------------------------------------------------------- */
|
|
867
|
+
function createController(props) {
|
|
868
|
+
const application = __typia_transform__llmApplicationFinalize._llmApplicationFinalize({
|
|
869
|
+
functions: [
|
|
870
|
+
{
|
|
871
|
+
name: "renderPage",
|
|
872
|
+
parameters: {
|
|
873
|
+
description: "Current Type: {@link IAutoViewRenderApplication.IProps}",
|
|
874
|
+
type: "object",
|
|
875
|
+
properties: {
|
|
876
|
+
rationale: {
|
|
877
|
+
description: "One-line rationale explaining the rendering choices for this screen \u2014\nwhich shadcn primitives were composed, why pagination vs. infinite\nscroll, etc. Surfaced in the `autoViewRenderPage` event so the operator\ncan audit decisions without reading every TSX file.",
|
|
878
|
+
type: "string"
|
|
879
|
+
},
|
|
880
|
+
tsx: {
|
|
881
|
+
description: "Complete TSX source for the page. Starts with `\"use client\";` and exports\na single default `Page` function.",
|
|
882
|
+
type: "string"
|
|
883
|
+
}
|
|
884
|
+
},
|
|
885
|
+
required: [
|
|
886
|
+
"rationale",
|
|
887
|
+
"tsx"
|
|
888
|
+
],
|
|
889
|
+
additionalProperties: false,
|
|
890
|
+
$defs: {}
|
|
891
|
+
},
|
|
892
|
+
description: "Emit the complete TSX source for one Next.js page.\n\nCall this exactly once per screen. The returned source must include `\"use\nclient\";`, a single default `Page` export, every import the file uses, and\nexplicit handling of the four UI states (loading / error / empty / data).",
|
|
893
|
+
validate: (() => { const _io0 = input => "string" === typeof input.rationale && "string" === typeof input.tsx; const _vo0 = (input, _path, _exceptionable = true) => ["string" === typeof input.rationale || _report(_exceptionable, {
|
|
894
|
+
path: _path + ".rationale",
|
|
895
|
+
expected: "string",
|
|
896
|
+
value: input.rationale
|
|
897
|
+
}), "string" === typeof input.tsx || _report(_exceptionable, {
|
|
898
|
+
path: _path + ".tsx",
|
|
899
|
+
expected: "string",
|
|
900
|
+
value: input.tsx
|
|
901
|
+
})].every(flag => flag); const __is = input => "object" === typeof input && null !== input && _io0(input); let errors; let _report; return input => {
|
|
902
|
+
if (false === __is(input)) {
|
|
903
|
+
errors = [];
|
|
904
|
+
_report = __typia_transform__validateReport._validateReport(errors);
|
|
905
|
+
((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
|
|
906
|
+
path: _path + "",
|
|
907
|
+
expected: "IAutoViewRenderApplication.IProps",
|
|
908
|
+
value: input
|
|
909
|
+
})) && _vo0(input, _path + "", true) || _report(true, {
|
|
910
|
+
path: _path + "",
|
|
911
|
+
expected: "IAutoViewRenderApplication.IProps",
|
|
912
|
+
value: input
|
|
913
|
+
}))(input, "$input", true);
|
|
914
|
+
const success = 0 === errors.length;
|
|
915
|
+
return success ? {
|
|
916
|
+
success,
|
|
917
|
+
data: input
|
|
918
|
+
} : {
|
|
919
|
+
success,
|
|
920
|
+
errors,
|
|
921
|
+
data: input
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
return {
|
|
925
|
+
success: true,
|
|
926
|
+
data: input
|
|
927
|
+
};
|
|
928
|
+
}; })()
|
|
929
|
+
}
|
|
930
|
+
]
|
|
931
|
+
});
|
|
932
|
+
return {
|
|
933
|
+
protocol: "class",
|
|
934
|
+
name: "autoViewRenderPage",
|
|
935
|
+
application,
|
|
936
|
+
execute: {
|
|
937
|
+
renderPage: (next) => {
|
|
938
|
+
props.build(next);
|
|
939
|
+
},
|
|
940
|
+
},
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
//# sourceMappingURL=orchestrateAutoViewRender.js.map
|