@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.
Files changed (297) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +407 -0
  3. package/lib/AutoViewAgent.d.ts +109 -0
  4. package/lib/AutoViewAgent.js +123 -0
  5. package/lib/AutoViewAgent.js.map +1 -0
  6. package/lib/agent/emitMcpServer.d.ts +15 -0
  7. package/lib/agent/emitMcpServer.js +157 -0
  8. package/lib/agent/emitMcpServer.js.map +1 -0
  9. package/lib/agent/emitReport.d.ts +14 -0
  10. package/lib/agent/emitReport.js +85 -0
  11. package/lib/agent/emitReport.js.map +1 -0
  12. package/lib/agent/toolSurface.d.ts +130 -0
  13. package/lib/agent/toolSurface.js +342 -0
  14. package/lib/agent/toolSurface.js.map +1 -0
  15. package/lib/agent/verifyAgentTasks.d.ts +87 -0
  16. package/lib/agent/verifyAgentTasks.js +126 -0
  17. package/lib/agent/verifyAgentTasks.js.map +1 -0
  18. package/lib/cli/main.d.ts +2 -0
  19. package/lib/cli/main.js +295 -0
  20. package/lib/cli/main.js.map +1 -0
  21. package/lib/compiler/AutoViewInterfaceCompiler.d.ts +27 -0
  22. package/lib/compiler/AutoViewInterfaceCompiler.js +68 -0
  23. package/lib/compiler/AutoViewInterfaceCompiler.js.map +1 -0
  24. package/lib/constants/AutoViewFrontendTemplate.d.ts +1 -0
  25. package/lib/constants/AutoViewFrontendTemplate.js +46 -0
  26. package/lib/constants/AutoViewFrontendTemplate.js.map +1 -0
  27. package/lib/constants/AutoViewSystemPromptConstant.d.ts +5 -0
  28. package/lib/constants/AutoViewSystemPromptConstant.js +4 -0
  29. package/lib/constants/AutoViewSystemPromptConstant.js.map +1 -0
  30. package/lib/context/IAutoViewAgentContext.d.ts +60 -0
  31. package/lib/context/IAutoViewAgentContext.js +3 -0
  32. package/lib/context/IAutoViewAgentContext.js.map +1 -0
  33. package/lib/fromSwagger.d.ts +53 -0
  34. package/lib/fromSwagger.js +513 -0
  35. package/lib/fromSwagger.js.map +1 -0
  36. package/lib/generateDeterministic.d.ts +26 -0
  37. package/lib/generateDeterministic.js +75 -0
  38. package/lib/generateDeterministic.js.map +1 -0
  39. package/lib/index.d.ts +15 -0
  40. package/lib/index.js +41 -0
  41. package/lib/index.js.map +1 -0
  42. package/lib/orchestrate/orchestrateAutoView.d.ts +17 -0
  43. package/lib/orchestrate/orchestrateAutoView.js +491 -0
  44. package/lib/orchestrate/orchestrateAutoView.js.map +1 -0
  45. package/lib/orchestrate/orchestrateAutoViewProductPlan.d.ts +37 -0
  46. package/lib/orchestrate/orchestrateAutoViewProductPlan.js +109 -0
  47. package/lib/orchestrate/orchestrateAutoViewProductPlan.js.map +1 -0
  48. package/lib/orchestrate/orchestrateAutoViewRender.d.ts +133 -0
  49. package/lib/orchestrate/orchestrateAutoViewRender.js +943 -0
  50. package/lib/orchestrate/orchestrateAutoViewRender.js.map +1 -0
  51. package/lib/orchestrate/orchestrateAutoViewRenderDeterministic.d.ts +24 -0
  52. package/lib/orchestrate/orchestrateAutoViewRenderDeterministic.js +92 -0
  53. package/lib/orchestrate/orchestrateAutoViewRenderDeterministic.js.map +1 -0
  54. package/lib/orchestrate/orchestrateAutoViewReview.d.ts +48 -0
  55. package/lib/orchestrate/orchestrateAutoViewReview.js +328 -0
  56. package/lib/orchestrate/orchestrateAutoViewReview.js.map +1 -0
  57. package/lib/orchestrate/orchestrateAutoViewScaffold.d.ts +45 -0
  58. package/lib/orchestrate/orchestrateAutoViewScaffold.js +586 -0
  59. package/lib/orchestrate/orchestrateAutoViewScaffold.js.map +1 -0
  60. package/lib/orchestrate/orchestrateAutoViewSdkStudy.d.ts +26 -0
  61. package/lib/orchestrate/orchestrateAutoViewSdkStudy.js +85 -0
  62. package/lib/orchestrate/orchestrateAutoViewSdkStudy.js.map +1 -0
  63. package/lib/orchestrate/structures/IAutoViewProductPlan.d.ts +96 -0
  64. package/lib/orchestrate/structures/IAutoViewProductPlan.js +3 -0
  65. package/lib/orchestrate/structures/IAutoViewProductPlan.js.map +1 -0
  66. package/lib/orchestrate/structures/IAutoViewProductPlanApplication.d.ts +38 -0
  67. package/lib/orchestrate/structures/IAutoViewProductPlanApplication.js +3 -0
  68. package/lib/orchestrate/structures/IAutoViewProductPlanApplication.js.map +1 -0
  69. package/lib/orchestrate/structures/IAutoViewRenderApplication.d.ts +38 -0
  70. package/lib/orchestrate/structures/IAutoViewRenderApplication.js +3 -0
  71. package/lib/orchestrate/structures/IAutoViewRenderApplication.js.map +1 -0
  72. package/lib/orchestrate/structures/IAutoViewReviewApplication.d.ts +40 -0
  73. package/lib/orchestrate/structures/IAutoViewReviewApplication.js +3 -0
  74. package/lib/orchestrate/structures/IAutoViewReviewApplication.js.map +1 -0
  75. package/lib/orchestrate/structures/IAutoViewSdkMap.d.ts +63 -0
  76. package/lib/orchestrate/structures/IAutoViewSdkMap.js +3 -0
  77. package/lib/orchestrate/structures/IAutoViewSdkMap.js.map +1 -0
  78. package/lib/orchestrate/structures/IAutoViewSdkStudyApplication.d.ts +37 -0
  79. package/lib/orchestrate/structures/IAutoViewSdkStudyApplication.js +3 -0
  80. package/lib/orchestrate/structures/IAutoViewSdkStudyApplication.js.map +1 -0
  81. package/lib/orchestrate/utils/HistoryMessage.d.ts +10 -0
  82. package/lib/orchestrate/utils/HistoryMessage.js +25 -0
  83. package/lib/orchestrate/utils/HistoryMessage.js.map +1 -0
  84. package/lib/orchestrate/utils/auditFrontendRuntime.d.ts +53 -0
  85. package/lib/orchestrate/utils/auditFrontendRuntime.js +362 -0
  86. package/lib/orchestrate/utils/auditFrontendRuntime.js.map +1 -0
  87. package/lib/orchestrate/utils/buildDeterministicPlan.d.ts +4 -0
  88. package/lib/orchestrate/utils/buildDeterministicPlan.js +233 -0
  89. package/lib/orchestrate/utils/buildDeterministicPlan.js.map +1 -0
  90. package/lib/orchestrate/utils/buildDeterministicSdkMap.d.ts +22 -0
  91. package/lib/orchestrate/utils/buildDeterministicSdkMap.js +154 -0
  92. package/lib/orchestrate/utils/buildDeterministicSdkMap.js.map +1 -0
  93. package/lib/orchestrate/utils/cacheNodeModules.d.ts +31 -0
  94. package/lib/orchestrate/utils/cacheNodeModules.js +134 -0
  95. package/lib/orchestrate/utils/cacheNodeModules.js.map +1 -0
  96. package/lib/orchestrate/utils/describeEndpointPropsShape.d.ts +37 -0
  97. package/lib/orchestrate/utils/describeEndpointPropsShape.js +192 -0
  98. package/lib/orchestrate/utils/describeEndpointPropsShape.js.map +1 -0
  99. package/lib/orchestrate/utils/describeEndpointRequestBodyShape.d.ts +22 -0
  100. package/lib/orchestrate/utils/describeEndpointRequestBodyShape.js +29 -0
  101. package/lib/orchestrate/utils/describeEndpointRequestBodyShape.js.map +1 -0
  102. package/lib/orchestrate/utils/describeEndpointResponseShape.d.ts +19 -0
  103. package/lib/orchestrate/utils/describeEndpointResponseShape.js +30 -0
  104. package/lib/orchestrate/utils/describeEndpointResponseShape.js.map +1 -0
  105. package/lib/orchestrate/utils/executeCachedBatch.d.ts +22 -0
  106. package/lib/orchestrate/utils/executeCachedBatch.js +64 -0
  107. package/lib/orchestrate/utils/executeCachedBatch.js.map +1 -0
  108. package/lib/orchestrate/utils/loadShoppingFixture.d.ts +33 -0
  109. package/lib/orchestrate/utils/loadShoppingFixture.js +17 -0
  110. package/lib/orchestrate/utils/loadShoppingFixture.js.map +1 -0
  111. package/lib/orchestrate/utils/normalizeProductPlanPaths.d.ts +24 -0
  112. package/lib/orchestrate/utils/normalizeProductPlanPaths.js +77 -0
  113. package/lib/orchestrate/utils/normalizeProductPlanPaths.js.map +1 -0
  114. package/lib/orchestrate/utils/renderJsonSchema.d.ts +23 -0
  115. package/lib/orchestrate/utils/renderJsonSchema.js +122 -0
  116. package/lib/orchestrate/utils/renderJsonSchema.js.map +1 -0
  117. package/lib/orchestrate/utils/renderResourcePage.d.ts +36 -0
  118. package/lib/orchestrate/utils/renderResourcePage.js +1415 -0
  119. package/lib/orchestrate/utils/renderResourcePage.js.map +1 -0
  120. package/lib/orchestrate/utils/validateFrontendTypecheck.d.ts +109 -0
  121. package/lib/orchestrate/utils/validateFrontendTypecheck.js +274 -0
  122. package/lib/orchestrate/utils/validateFrontendTypecheck.js.map +1 -0
  123. package/lib/preview/renderPreview.d.ts +22 -0
  124. package/lib/preview/renderPreview.js +198 -0
  125. package/lib/preview/renderPreview.js.map +1 -0
  126. package/lib/typings/compiler.d.ts +39 -0
  127. package/lib/typings/compiler.js +3 -0
  128. package/lib/typings/compiler.js.map +1 -0
  129. package/lib/typings/events.d.ts +106 -0
  130. package/lib/typings/events.js +3 -0
  131. package/lib/typings/events.js.map +1 -0
  132. package/lib/typings/index.d.ts +10 -0
  133. package/lib/typings/index.js +27 -0
  134. package/lib/typings/index.js.map +1 -0
  135. package/lib/typings/misc.d.ts +78 -0
  136. package/lib/typings/misc.js +3 -0
  137. package/lib/typings/misc.js.map +1 -0
  138. package/lib/utils/ArrayUtil.d.ts +8 -0
  139. package/lib/utils/ArrayUtil.js +30 -0
  140. package/lib/utils/ArrayUtil.js.map +1 -0
  141. package/lib/utils/StringUtil.d.ts +11 -0
  142. package/lib/utils/StringUtil.js +28 -0
  143. package/lib/utils/StringUtil.js.map +1 -0
  144. package/lib/utils/classifyEndpoints.d.ts +62 -0
  145. package/lib/utils/classifyEndpoints.js +216 -0
  146. package/lib/utils/classifyEndpoints.js.map +1 -0
  147. package/lib/utils/endpointFilter.d.ts +26 -0
  148. package/lib/utils/endpointFilter.js +0 -0
  149. package/lib/utils/endpointFilter.js.map +1 -0
  150. package/lib/utils/extractFields.d.ts +85 -0
  151. package/lib/utils/extractFields.js +231 -0
  152. package/lib/utils/extractFields.js.map +1 -0
  153. package/lib/utils/index.d.ts +13 -0
  154. package/lib/utils/index.js +30 -0
  155. package/lib/utils/index.js.map +1 -0
  156. package/lib/utils/normalizeForNestia.d.ts +34 -0
  157. package/lib/utils/normalizeForNestia.js +133 -0
  158. package/lib/utils/normalizeForNestia.js.map +1 -0
  159. package/lib/utils/resourcePlan.d.ts +39 -0
  160. package/lib/utils/resourcePlan.js +95 -0
  161. package/lib/utils/resourcePlan.js.map +1 -0
  162. package/lib/utils/sliceDocument.d.ts +17 -0
  163. package/lib/utils/sliceDocument.js +114 -0
  164. package/lib/utils/sliceDocument.js.map +1 -0
  165. package/lib/utils/toEndpoints.d.ts +90 -0
  166. package/lib/utils/toEndpoints.js +227 -0
  167. package/lib/utils/toEndpoints.js.map +1 -0
  168. package/lib/verify/runWorkflows.d.ts +25 -0
  169. package/lib/verify/runWorkflows.js +366 -0
  170. package/lib/verify/runWorkflows.js.map +1 -0
  171. package/lib/verify/workflows.d.ts +53 -0
  172. package/lib/verify/workflows.js +107 -0
  173. package/lib/verify/workflows.js.map +1 -0
  174. package/package.json +82 -0
  175. package/prompts/AUTOVIEW_RENDER.md +398 -0
  176. package/prompts/AUTOVIEW_REVIEW.md +60 -0
  177. package/prompts/AUTOVIEW_SDK_STUDY.md +89 -0
  178. package/src/AutoViewAgent.ts +222 -0
  179. package/src/agent/emitMcpServer.integration.test.ts +168 -0
  180. package/src/agent/emitMcpServer.test.ts +51 -0
  181. package/src/agent/emitMcpServer.ts +178 -0
  182. package/src/agent/emitReport.ts +117 -0
  183. package/src/agent/toolSurface.test.ts +243 -0
  184. package/src/agent/toolSurface.ts +501 -0
  185. package/src/agent/verifyAgentTasks.test.ts +106 -0
  186. package/src/agent/verifyAgentTasks.ts +171 -0
  187. package/src/cli/main.ts +363 -0
  188. package/src/compiler/AutoViewInterfaceCompiler.ts +69 -0
  189. package/src/constants/AutoViewFrontendTemplate.ts +42 -0
  190. package/src/constants/AutoViewSystemPromptConstant.ts +6 -0
  191. package/src/context/IAutoViewAgentContext.ts +84 -0
  192. package/src/fromSwagger.test.ts +269 -0
  193. package/src/fromSwagger.ts +500 -0
  194. package/src/generateDeterministic.test.ts +39 -0
  195. package/src/generateDeterministic.ts +77 -0
  196. package/src/index.ts +30 -0
  197. package/src/orchestrate/orchestrateAutoView.ts +590 -0
  198. package/src/orchestrate/orchestrateAutoViewProductPlan.ts +121 -0
  199. package/src/orchestrate/orchestrateAutoViewRender.ts +1117 -0
  200. package/src/orchestrate/orchestrateAutoViewRenderDeterministic.ts +101 -0
  201. package/src/orchestrate/orchestrateAutoViewReview.ts +272 -0
  202. package/src/orchestrate/orchestrateAutoViewScaffold.ts +627 -0
  203. package/src/orchestrate/orchestrateAutoViewSdkStudy.ts +90 -0
  204. package/src/orchestrate/renderNavTs.test.ts +74 -0
  205. package/src/orchestrate/structures/IAutoViewProductPlan.ts +119 -0
  206. package/src/orchestrate/structures/IAutoViewProductPlanApplication.ts +41 -0
  207. package/src/orchestrate/structures/IAutoViewRenderApplication.ts +40 -0
  208. package/src/orchestrate/structures/IAutoViewReviewApplication.ts +42 -0
  209. package/src/orchestrate/structures/IAutoViewSdkMap.ts +72 -0
  210. package/src/orchestrate/structures/IAutoViewSdkStudyApplication.ts +40 -0
  211. package/src/orchestrate/utils/HistoryMessage.ts +41 -0
  212. package/src/orchestrate/utils/auditFrontendRuntime.test.ts +18 -0
  213. package/src/orchestrate/utils/auditFrontendRuntime.ts +454 -0
  214. package/src/orchestrate/utils/buildDeterministicPlan.test.ts +170 -0
  215. package/src/orchestrate/utils/buildDeterministicPlan.ts +289 -0
  216. package/src/orchestrate/utils/buildDeterministicSdkMap.test.ts +90 -0
  217. package/src/orchestrate/utils/buildDeterministicSdkMap.ts +169 -0
  218. package/src/orchestrate/utils/cacheNodeModules.ts +136 -0
  219. package/src/orchestrate/utils/describeEndpointPropsShape.test.ts +86 -0
  220. package/src/orchestrate/utils/describeEndpointPropsShape.ts +202 -0
  221. package/src/orchestrate/utils/describeEndpointRequestBodyShape.test.ts +87 -0
  222. package/src/orchestrate/utils/describeEndpointRequestBodyShape.ts +31 -0
  223. package/src/orchestrate/utils/describeEndpointResponseShape.test.ts +70 -0
  224. package/src/orchestrate/utils/describeEndpointResponseShape.ts +32 -0
  225. package/src/orchestrate/utils/executeCachedBatch.ts +59 -0
  226. package/src/orchestrate/utils/loadShoppingFixture.ts +52 -0
  227. package/src/orchestrate/utils/normalizeProductPlanPaths.ts +92 -0
  228. package/src/orchestrate/utils/renderJsonSchema.test.ts +162 -0
  229. package/src/orchestrate/utils/renderJsonSchema.ts +133 -0
  230. package/src/orchestrate/utils/renderResourcePage.test.ts +468 -0
  231. package/src/orchestrate/utils/renderResourcePage.ts +1624 -0
  232. package/src/orchestrate/utils/validateFrontendTypecheck.test.ts +32 -0
  233. package/src/orchestrate/utils/validateFrontendTypecheck.ts +335 -0
  234. package/src/preview/renderPreview.ts +273 -0
  235. package/src/typings/compiler.ts +47 -0
  236. package/src/typings/events.ts +155 -0
  237. package/src/typings/index.ts +10 -0
  238. package/src/typings/misc.ts +93 -0
  239. package/src/utils/ArrayUtil.ts +16 -0
  240. package/src/utils/StringUtil.ts +29 -0
  241. package/src/utils/classifyEndpoints.test.ts +86 -0
  242. package/src/utils/classifyEndpoints.ts +291 -0
  243. package/src/utils/endpointFilter.test.ts +50 -0
  244. package/src/utils/endpointFilter.ts +0 -0
  245. package/src/utils/extractFields.test.ts +82 -0
  246. package/src/utils/extractFields.ts +306 -0
  247. package/src/utils/index.ts +13 -0
  248. package/src/utils/normalizeForNestia.test.ts +93 -0
  249. package/src/utils/normalizeForNestia.ts +139 -0
  250. package/src/utils/resourcePlan.test.ts +104 -0
  251. package/src/utils/resourcePlan.ts +180 -0
  252. package/src/utils/sliceDocument.test.ts +85 -0
  253. package/src/utils/sliceDocument.ts +119 -0
  254. package/src/utils/toEndpoints.test.ts +251 -0
  255. package/src/utils/toEndpoints.ts +343 -0
  256. package/src/verify/runWorkflows.ts +403 -0
  257. package/src/verify/workflows.test.ts +117 -0
  258. package/src/verify/workflows.ts +154 -0
  259. package/template/CLAUDE.md +140 -0
  260. package/template/Dockerfile +31 -0
  261. package/template/PROMPT.md +80 -0
  262. package/template/SANDBOX.md +70 -0
  263. package/template/app/api/health/route.ts +10 -0
  264. package/template/app/globals.css +97 -0
  265. package/template/app/layout.tsx +30 -0
  266. package/template/app/page.tsx +19 -0
  267. package/template/components/AppShell.tsx +114 -0
  268. package/template/components/auto/CatalogGrid.tsx +159 -0
  269. package/template/components/auto/ConfirmButton.tsx +67 -0
  270. package/template/components/auto/EmbeddedCollection.tsx +144 -0
  271. package/template/components/auto/ResourceDashboard.tsx +104 -0
  272. package/template/components/auto/ResourceDetail.tsx +93 -0
  273. package/template/components/auto/ResourceForm.tsx +235 -0
  274. package/template/components/auto/ResourceIcon.tsx +88 -0
  275. package/template/components/auto/ResourceLanding.tsx +155 -0
  276. package/template/components/auto/ResourceTable.tsx +223 -0
  277. package/template/components/auto/formatValue.tsx +186 -0
  278. package/template/components/auto/types.ts +42 -0
  279. package/template/components/ui/badge.tsx +40 -0
  280. package/template/components/ui/button.tsx +57 -0
  281. package/template/components/ui/card.tsx +86 -0
  282. package/template/components/ui/dialog.tsx +119 -0
  283. package/template/components/ui/input.tsx +23 -0
  284. package/template/components/ui/label.tsx +24 -0
  285. package/template/components/ui/pagination.tsx +117 -0
  286. package/template/components/ui/select.tsx +92 -0
  287. package/template/components/ui/sheet.tsx +135 -0
  288. package/template/components/ui/skeleton.tsx +15 -0
  289. package/template/components/ui/table.tsx +120 -0
  290. package/template/components/ui/tabs.tsx +55 -0
  291. package/template/lib/utils.ts +35 -0
  292. package/template/next.config.mjs +52 -0
  293. package/template/package.json +46 -0
  294. package/template/postcss.config.js +6 -0
  295. package/template/scripts/start-shopping-backend.sh +56 -0
  296. package/template/tailwind.config.ts +96 -0
  297. package/template/tsconfig.json +29 -0
@@ -0,0 +1,60 @@
1
+ You are the UI Review phase of the AutoView agent.
2
+
3
+ You receive the product plan, the SDK domain map, and per-screen
4
+ metadata from the Render phase (rationale, attempt count, whether
5
+ parsing eventually succeeded). Your single job is to produce one
6
+ markdown file — `wiki/sdk-feedback.md` — that captures the honest,
7
+ operator-facing assessment of what the SDK is like to build a frontend
8
+ on top of. The whole reason AutoView exists is to surface API quality
9
+ problems through the act of consuming the API; this is where that
10
+ signal lands.
11
+
12
+ You do not see screenshots and you do not run the application. Visual
13
+ verification happens later, by the operator on the Sandbox deploy. Your
14
+ review is a code-and-spec audit, not a visual audit.
15
+
16
+ ## What "sdk-feedback" must contain
17
+
18
+ A markdown document with these sections in order:
19
+
20
+ 1. **Summary** — 2–4 sentences in the operator's voice. What kind of
21
+ product is this, how cleanly did the SDK shape it, and is the API
22
+ ready to ship to a human?
23
+ 2. **What worked well** — bullets. Concrete instances where the SDK
24
+ made a flow easy: well-named resources, clear pagination, sane
25
+ defaults, helpful JSDoc.
26
+ 3. **What's awkward** — bullets. The whole point of the document.
27
+ Each bullet calls out one specific API decision that made the
28
+ frontend awkward: redundant endpoints, missing list filters,
29
+ inconsistent naming, types that force casts, flows that require
30
+ round-trips the UI shouldn't need, missing pagination, unclear
31
+ actor boundaries. Be specific — name the resource or accessor.
32
+ 4. **What's missing** — bullets. Functionality the product needed but
33
+ the SDK does not expose. Reference the intentional-omission list
34
+ from the product plan and add anything new the Render phase
35
+ stumbled on.
36
+ 5. **Pages that broke** — bullets. List every screen where
37
+ `ok === false` in the render metadata. One bullet each:
38
+ path, ui pattern, attempts spent, the parser diagnostic. These
39
+ are the pages the operator should look at first when deploying
40
+ to Sandbox.
41
+
42
+ If a section has nothing to report, write "None observed" — do not
43
+ delete the section.
44
+
45
+ ## Mindset
46
+
47
+ - Be specific and short. Operator-facing markdown, not LLM prose.
48
+ - Name resources and accessors. "shoppings.customers.orders.create
49
+ forces a two-step round-trip because…" is signal. "Some endpoints
50
+ felt awkward" is noise.
51
+ - Do not invent problems. If the SDK is clean, write "the API is
52
+ clean; the awkwardness is in the product, not the platform."
53
+ - Do not write Korean. The Sandbox operator reading this is the
54
+ same team that reads the rest of `wiki/`.
55
+
56
+ ## Output
57
+
58
+ Call `writeSdkFeedback` exactly once with the complete markdown body
59
+ and a one-sentence narrative summary. The orchestrator drops the
60
+ markdown into `frontend/wiki/sdk-feedback.md` verbatim.
@@ -0,0 +1,89 @@
1
+ You are the SDK Study phase of the AutoView agent.
2
+
3
+ Your single job is to read an entire TypeScript SDK and produce a domain
4
+ map that the downstream Product Plan phase can use to design a real
5
+ frontend product. You are not designing screens, components, or user
6
+ flows yet — only mapping the surface area honestly.
7
+
8
+ ## Inputs you will receive
9
+
10
+ - A list of TypeScript files from the SDK (paths + contents), generated
11
+ by AutoBE (or `@samchon/shopping-api` when the agent is exercised
12
+ against the bundled reference).
13
+ - Every JSDoc comment in those files is authoritative — treat it as the
14
+ source of truth for purpose, constraints, and actor expectations.
15
+ - An OpenAPI document derived from the SDK, attached for cross-reference
16
+ only. When the SDK and the OpenAPI disagree, the SDK wins.
17
+
18
+ ## What "resources" mean
19
+
20
+ A resource is a coherent group of endpoints organized around the same
21
+ namespace prefix and the same noun. `shoppings.customers.sales.*` is one
22
+ resource (`sales`) viewed by the customer actor. `shoppings.admins.sales.*`
23
+ is the same resource viewed by the admin actor — list them as one
24
+ resource and record both actor views.
25
+
26
+ For each resource, record:
27
+
28
+ - `name`: short noun (e.g. `sales`, `orders`, `channels`, `categories`).
29
+ - `namespace`: dotted accessor path (e.g. `shoppings.customers.sales`).
30
+ If the resource is exposed under multiple namespaces (per actor),
31
+ list the customer-facing one first and mention the others in
32
+ `notes`.
33
+ - `purpose`: one short sentence in the operator's voice. **Why** does
34
+ this resource exist in the product? Not "CRUD on Sale" — "Browse and
35
+ buy products that sellers have published".
36
+ - `actorsInvolved`: subset of the actors you identified.
37
+ - `notes`: anything subtle worth carrying into the product plan —
38
+ pagination shape, multi-actor exposure, soft-delete semantics, etc.
39
+
40
+ ## What "actors" mean
41
+
42
+ Actors are roles the SDK serves. Infer them from:
43
+
44
+ 1. Namespace segmentation (`customers`, `sellers`, `admins`, `guests`).
45
+ 2. Authentication shape (`IAuthorized<"customer">` vs. `IAuthorized<"admin">`).
46
+ 3. JSDoc references to operator types.
47
+
48
+ Common actors: `customer`, `seller`, `administrator`, `guest`. Do not
49
+ invent actors the SDK does not support. If only one actor is present,
50
+ record exactly one.
51
+
52
+ For each actor, record:
53
+
54
+ - `name`: lower-case role identifier (e.g. `customer`).
55
+ - `journeys`: 1–5 end-to-end goals this actor accomplishes by
56
+ composing several endpoints. Phrase each as an arrow chain
57
+ (`sign up → browse catalog → add to cart → checkout`). These are the
58
+ raw material the Product Plan phase uses to decide which screens
59
+ exist.
60
+
61
+ ## What "notable constraints" mean
62
+
63
+ Things a frontend developer needs to know up-front that are not
64
+ obvious from a single endpoint signature:
65
+
66
+ - Soft-delete vs. hard-delete behavior.
67
+ - Pagination conventions (cursor vs. offset; default page size).
68
+ - Authentication scopes and where they are required.
69
+ - Idempotency keys, optimistic-concurrency tokens, or audit fields.
70
+ - Anything the SDK comments call out as a footgun.
71
+
72
+ List these as standalone strings. One sentence each. Do not
73
+ fabricate constraints you cannot point to in the SDK.
74
+
75
+ ## What you must NOT do
76
+
77
+ - Do **not** design screens. No "Catalog page", "Cart page", or
78
+ navigation. That is the Product Plan phase's job.
79
+ - Do **not** invent endpoints the SDK does not expose.
80
+ - Do **not** drop resources that look noisy. Record them all; the
81
+ Product Plan phase decides what to omit.
82
+ - Do **not** write Korean — output is consumed by downstream prompts
83
+ and must stay in English.
84
+
85
+ ## Output
86
+
87
+ Call the `buildSdkMap` function exactly once with the full domain map.
88
+ The next phase reads the map verbatim — make it complete, accurate, and
89
+ brief.
@@ -0,0 +1,222 @@
1
+ import { OpenApi } from "@typia/interface";
2
+ import { IAgenticaVendor, MicroAgentica } from "@agentica/core";
3
+
4
+ import {
5
+ AutoBeFunctionCallingMetric,
6
+ IAutoBeCompiler,
7
+ IAutoBeTokenUsageJson,
8
+ } from "./typings";
9
+
10
+ import { AutoViewInterfaceCompiler } from "./compiler/AutoViewInterfaceCompiler";
11
+ import {
12
+ AutoViewDispatchEvent,
13
+ IAutoViewAgentContext,
14
+ IAutoViewConversateProps,
15
+ IAutoViewConversateResult,
16
+ } from "./context/IAutoViewAgentContext";
17
+ import { orchestrateAutoView } from "./orchestrate/orchestrateAutoView";
18
+
19
+ /**
20
+ * Standalone entry point for the AutoView agent.
21
+ *
22
+ * Generates a runnable Next.js + shadcn/ui frontend from any
23
+ * {@link OpenApi.IDocument} — typically produced by passing a third party
24
+ * `swagger.json` through `@autobe/utils.invertOpenApiDocument`. Does not
25
+ * require `@autobe/agent`; the only requirement is an {@link IAgenticaVendor}
26
+ * (model + API key) and a compiler instance for SDK writing.
27
+ *
28
+ * Backward compat: `@autobe/agent`'s `AutoBeAgent.runAutoView()` still works as
29
+ * before — it bypasses this class and hands its own context to the same
30
+ * `orchestrateAutoView` directly.
31
+ */
32
+ export interface IAutoViewAgentProps {
33
+ /**
34
+ * The OpenAPI document the frontend will be generated against. For a
35
+ * third-party Swagger payload, run it through `invertOpenApiDocument` from
36
+ * `@autobe/utils` first.
37
+ */
38
+ document: OpenApi.IDocument;
39
+
40
+ /**
41
+ * Agentica vendor — model + API key + optional semaphore. Same shape
42
+ * `@autobe/agent` accepts; the agent's quota-tracker / mistral-shim helpers
43
+ * are not wired here because they are AutoBE-specific.
44
+ */
45
+ vendor: IAgenticaVendor;
46
+
47
+ /**
48
+ * Optional design theme passed through to the Product Plan + Render phases.
49
+ * Empty / undefined means "prototype-first, content-first defaults".
50
+ */
51
+ designTheme?: string;
52
+
53
+ /**
54
+ * Compiler instance used to write the SDK files. Falls back to a fresh
55
+ * `AutoBeCompiler` when not provided. Pass your own instance if you want to
56
+ * share one across multiple AutoViewAgent runs in the same process.
57
+ */
58
+ compiler?: IAutoBeCompiler;
59
+
60
+ /** Concurrency cap for the per-screen render batch. Defaults to 8. */
61
+ semaphore?: number;
62
+
63
+ /**
64
+ * Live backend the generated frontend should connect to. When given, the
65
+ * scaffold wires `connection.ts` with `simulate: false` so the dev server
66
+ * renders real data on first boot — the standalone CLI's reason to exist.
67
+ *
68
+ * Omit to fall back to simulator mode (only useful for swaggers that
69
+ * genuinely have no backend). `extractBackendFromSwagger(payload)` in this
70
+ * package is a small helper for pulling the URL out of a swagger's
71
+ * `servers[0].url` field automatically.
72
+ */
73
+ backend?: { host: string } | null;
74
+
75
+ /**
76
+ * Opt into Phase 6 runtime audit: after typecheck, boot `next dev`, walk
77
+ * every page with Playwright, and re-render any page that console-errored /
78
+ * crashed / failed to navigate. Catches the class of bugs `tsc --noEmit`
79
+ * cannot see (`obj?.array.method(...)` undefined-access, react render crashes
80
+ * on simulator data).
81
+ *
82
+ * Defaults to `false` because it installs Playwright + Chromium (~150MB) and
83
+ * boots `next dev` twice per agent run, adding ~10–20 minutes.
84
+ */
85
+ runtimeAudit?: boolean;
86
+
87
+ /**
88
+ * Opt into workflow verification: after typecheck, boot the generated app in
89
+ * a real headless browser and walk the derived user workflows, writing
90
+ * `wiki/verification.md`. Proves the app works for a user, not just compiles.
91
+ * Heavy (Chromium + `next dev`); defaults to `false`.
92
+ */
93
+ verify?: boolean;
94
+
95
+ /**
96
+ * Path globs to KEEP — only endpoints whose path matches become screens.
97
+ * Slices a large swagger to one actor surface, e.g.
98
+ * `["shoppings/customers/**"]`. Empty/absent means "all".
99
+ */
100
+ include?: string[];
101
+
102
+ /** Path globs to DROP after include, e.g. `["**​/monitors/**"]`. */
103
+ exclude?: string[];
104
+
105
+ /**
106
+ * Optional callback for every event the orchestrators dispatch
107
+ * (`autoViewStart`, `autoViewSdkStudy`, `autoViewProductPlan`,
108
+ * `autoViewScaffold`, per-page `autoViewRenderPage`, `autoViewReview`,
109
+ * `autoViewComplete`). Useful for progress bars, structured logging, etc.
110
+ */
111
+ onEvent?: (event: AutoViewDispatchEvent) => void;
112
+ }
113
+
114
+ /** Public result of {@link AutoViewAgent.run}. */
115
+ export interface IAutoViewAgentResult {
116
+ /** Path → content map of the generated frontend project. */
117
+ files: Record<string, string>;
118
+ }
119
+
120
+ export class AutoViewAgent {
121
+ public constructor(private readonly props: IAutoViewAgentProps) {}
122
+
123
+ /**
124
+ * Drive every AutoView phase end-to-end and return the assembled frontend
125
+ * project as a flat `path → content` map.
126
+ *
127
+ * Mutates nothing on disk; serialize the map to ZIP, push it to a Sandbox, or
128
+ * write it out directly with `@autobe/filesystem` — your choice. The CLI
129
+ * binary (`bin/autoview`) does the disk-write step.
130
+ */
131
+ public async run(): Promise<IAutoViewAgentResult> {
132
+ const compiler: IAutoBeCompiler = this.props.compiler ?? {
133
+ interface: new AutoViewInterfaceCompiler(),
134
+ };
135
+ let captured: Record<string, string> = {};
136
+ const ctx: IAutoViewAgentContext = {
137
+ state: () => ({
138
+ interface: { document: this.props.document, step: 0 },
139
+ }),
140
+ compiler: async () => compiler,
141
+ vendor: { semaphore: this.props.semaphore ?? 8 },
142
+ dispatch: (event: AutoViewDispatchEvent) => {
143
+ if (event.type === "autoViewComplete") {
144
+ captured = event.files;
145
+ }
146
+ this.props.onEvent?.(event);
147
+ return event;
148
+ },
149
+ conversate: (cprops) => this.conversate(cprops),
150
+ };
151
+ await orchestrateAutoView(ctx, {
152
+ source: "interface",
153
+ designTheme: this.props.designTheme,
154
+ backend: this.props.backend ?? null,
155
+ runtimeAudit: this.props.runtimeAudit ?? false,
156
+ verify: this.props.verify ?? false,
157
+ include: this.props.include,
158
+ exclude: this.props.exclude,
159
+ });
160
+ return { files: captured };
161
+ }
162
+
163
+ private async conversate(
164
+ cprops: IAutoViewConversateProps,
165
+ ): Promise<IAutoViewConversateResult> {
166
+ // Minimal agentica wiring — no quota tracker, no vendor-specific
167
+ // shims, no compaction. The full AutoBE agent layers those on for
168
+ // its own concerns; the standalone path keeps things thin so it
169
+ // works against any OpenAI-compatible endpoint that supports tool
170
+ // calling.
171
+ const agent = new MicroAgentica({
172
+ vendor: this.props.vendor,
173
+ config: {
174
+ executor: { describe: false },
175
+ stream: cprops.enforceFunctionCall === false,
176
+ },
177
+ histories: cprops.histories,
178
+ controllers: [cprops.controller],
179
+ });
180
+ let tokenUsage: IAutoBeTokenUsageJson.IComponent = zeroTokenUsage();
181
+ const metric: AutoBeFunctionCallingMetric = {
182
+ attempt: 0,
183
+ success: 0,
184
+ invalidJson: 0,
185
+ validationFailure: 0,
186
+ consent: 0,
187
+ };
188
+ agent.on("call", () => {
189
+ metric.attempt++;
190
+ });
191
+ agent.on("execute", () => {
192
+ metric.success++;
193
+ });
194
+ agent.on("jsonParseError", () => {
195
+ metric.invalidJson++;
196
+ });
197
+ agent.on("validate", () => {
198
+ metric.validationFailure++;
199
+ });
200
+ await agent.conversate(cprops.userMessage);
201
+ const usage = agent.getTokenUsage().aggregate;
202
+ tokenUsage = {
203
+ total: usage.total,
204
+ input: usage.input,
205
+ output: usage.output,
206
+ };
207
+ return { metric, tokenUsage };
208
+ }
209
+ }
210
+
211
+ function zeroTokenUsage(): IAutoBeTokenUsageJson.IComponent {
212
+ return {
213
+ total: 0,
214
+ input: { total: 0, cached: 0 },
215
+ output: {
216
+ total: 0,
217
+ reasoning: 0,
218
+ accepted_prediction: 0,
219
+ rejected_prediction: 0,
220
+ },
221
+ };
222
+ }
@@ -0,0 +1,168 @@
1
+ import { spawnSync } from "child_process";
2
+ import { mkdtempSync, rmSync, writeFileSync } from "fs";
3
+ import http from "http";
4
+ import { join } from "path";
5
+
6
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
7
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
8
+ import { OpenApiConverter } from "@typia/utils";
9
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
10
+
11
+ import { emitMcpServer } from "./emitMcpServer";
12
+
13
+ /**
14
+ * End-to-end proof that the emitted MCP server speaks the real MCP protocol:
15
+ * spawn it over stdio, drive it with an actual MCP `Client` (listTools +
16
+ * callTool), and exercise the producer→consumer chain (list → take an id from
17
+ * the response → detail) against a LOCAL mock backend (deterministic, no
18
+ * network). Distinct from the string-shape unit tests in emitMcpServer.test.ts.
19
+ */
20
+ function doc(paths: Record<string, unknown>, schemas: Record<string, unknown> = {}) {
21
+ return OpenApiConverter.upgradeDocument({
22
+ openapi: "3.0.0", info: { title: "Shop", version: "1.0.0" }, paths, components: { schemas },
23
+ } as never);
24
+ }
25
+
26
+ const param = (n: string) => ({ name: n, in: "path", required: true, schema: { type: "string" } });
27
+ const fixture = doc(
28
+ {
29
+ "/sales": { get: { operationId: "index", summary: "List sales.", responses: { 200: { description: "ok", content: { "application/json": { schema: { type: "array", items: { $ref: "#/components/schemas/Sale" } } } } } } } },
30
+ "/sales/{saleId}": { get: { operationId: "at", summary: "Get a sale.", parameters: [param("saleId")], responses: { 200: { description: "ok", content: { "application/json": { schema: { $ref: "#/components/schemas/Sale" } } } } } } },
31
+ // a nested resource — its id is produced by the questions list, which itself
32
+ // needs the saleId produced by the sales list (a genuine 2-hop chain).
33
+ "/sales/{saleId}/questions": { get: { operationId: "qIndex", summary: "List questions on a sale.", parameters: [param("saleId")], responses: { 200: { description: "ok", content: { "application/json": { schema: { type: "array", items: { $ref: "#/components/schemas/Question" } } } } } } } },
34
+ "/sales/{saleId}/questions/{questionId}": { get: { operationId: "qAt", summary: "Get one question.", parameters: [param("saleId"), param("questionId")], responses: { 200: { description: "ok", content: { "application/json": { schema: { $ref: "#/components/schemas/Question" } } } } } } },
35
+ },
36
+ {
37
+ Sale: { type: "object", properties: { id: { type: "string" }, title: { type: "string" } }, required: ["id"] },
38
+ Question: { type: "object", properties: { id: { type: "string" }, body: { type: "string" } }, required: ["id"] },
39
+ },
40
+ );
41
+
42
+ const SALES = [{ id: "sale_1", title: "MacBook" }, { id: "sale_2", title: "iPhone" }];
43
+ const QUESTIONS: Record<string, Array<{ id: string; body: string }>> = {
44
+ sale_2: [{ id: "q_9", body: "Is the iPhone unlocked?" }],
45
+ };
46
+
47
+ describe("emitMcpServer — real MCP protocol round-trip", () => {
48
+ let backend: http.Server;
49
+ let base = "";
50
+ let client: Client;
51
+ let transport: StdioClientTransport;
52
+ const tmpDirs: string[] = [];
53
+
54
+ // Temp dirs live UNDER the repo so the spawned ESM server resolves this repo's
55
+ // @modelcontextprotocol/sdk by walking up to node_modules (ESM ignores NODE_PATH).
56
+ const mkTmp = (prefix: string): string => {
57
+ const dir = mkdtempSync(join(process.cwd(), prefix));
58
+ tmpDirs.push(dir);
59
+ return dir;
60
+ };
61
+
62
+ beforeAll(async () => {
63
+ // 1. local mock backend
64
+ backend = http.createServer((req, res) => {
65
+ const u = (req.url ?? "").split("?")[0];
66
+ res.writeHead(200, { "content-type": "application/json" });
67
+ if (u === "/sales") return res.end(JSON.stringify(SALES));
68
+ const qOne = u!.match(/^\/sales\/([^/]+)\/questions\/([^/]+)$/);
69
+ if (qOne) return res.end(JSON.stringify((QUESTIONS[qOne[1]!] ?? []).find((q) => q.id === qOne[2]) ?? {}));
70
+ const qList = u!.match(/^\/sales\/([^/]+)\/questions$/);
71
+ if (qList) return res.end(JSON.stringify(QUESTIONS[qList[1]!] ?? []));
72
+ const one = u!.match(/^\/sales\/([^/]+)$/);
73
+ return res.end(JSON.stringify(one ? SALES.find((s) => s.id === one[1]) ?? {} : {}));
74
+ });
75
+ await new Promise<void>((ok) => backend.listen(0, "127.0.0.1", () => ok()));
76
+ base = `http://127.0.0.1:${(backend.address() as { port: number }).port}`;
77
+
78
+ // 2. write the emitted server to a temp dir under the repo
79
+ const dir = mkTmp(".tmp-mcp-");
80
+ const files = emitMcpServer(fixture, { backend: base, title: "Shop" });
81
+ for (const [name, content] of Object.entries(files)) writeFileSync(join(dir, name), content);
82
+
83
+ // 3. spawn it as a real MCP server over stdio and connect a real MCP client.
84
+ transport = new StdioClientTransport({
85
+ command: process.execPath,
86
+ args: [join(dir, "server.mjs")],
87
+ env: { ...process.env, API_HOST: base },
88
+ });
89
+ client = new Client({ name: "test", version: "1.0.0" }, { capabilities: {} });
90
+ await client.connect(transport);
91
+ }, 30000);
92
+
93
+ afterAll(async () => {
94
+ await client?.close();
95
+ backend?.close();
96
+ for (const d of tmpDirs) rmSync(d, { recursive: true, force: true });
97
+ });
98
+
99
+ it("listTools returns the surface with read/write annotations over MCP", async () => {
100
+ const { tools } = await client.listTools();
101
+ expect(tools.length).toBeGreaterThan(0);
102
+ const list = tools.find((t) => t.name === "sales.get");
103
+ expect(list).toBeDefined();
104
+ expect(list!.annotations?.readOnlyHint).toBe(true);
105
+ });
106
+
107
+ it("callTool executes the live API and drives a producer→consumer chain", async () => {
108
+ // list
109
+ const listRes = (await client.callTool({ name: "sales.get", arguments: {} })) as {
110
+ content: Array<{ text: string }>;
111
+ isError?: boolean;
112
+ };
113
+ expect(listRes.isError ?? false).toBe(false);
114
+ const sales = JSON.parse(listRes.content[0]!.text) as Array<{ id: string; title: string }>;
115
+ expect(sales.length).toBe(2);
116
+
117
+ // take an id from the list response, call detail with it
118
+ const detailRes = (await client.callTool({
119
+ name: "sales.getBySaleid",
120
+ arguments: { saleId: sales[1]!.id },
121
+ })) as { content: Array<{ text: string }>; isError?: boolean };
122
+ expect(detailRes.isError ?? false).toBe(false);
123
+ const sale = JSON.parse(detailRes.content[0]!.text) as { title: string };
124
+ expect(sale.title).toBe("iPhone");
125
+ });
126
+
127
+ it("drives a 2-hop nested chain, threading two path params from prior responses", async () => {
128
+ const call = async (name: string, args: Record<string, unknown>) =>
129
+ (await client.callTool({ name, arguments: args })) as {
130
+ content: Array<{ text: string }>;
131
+ isError?: boolean;
132
+ };
133
+
134
+ // hop 0: list sales → saleId
135
+ const sales = JSON.parse((await call("sales.get", {})).content[0]!.text) as Array<{ id: string }>;
136
+ const saleId = sales[1]!.id; // sale_2
137
+
138
+ // hop 1: list that sale's questions (needs saleId) → questionId
139
+ const qList = await call("sales.questions.getBySaleid", { saleId });
140
+ expect(qList.isError ?? false).toBe(false);
141
+ const questions = JSON.parse(qList.content[0]!.text) as Array<{ id: string }>;
142
+ expect(questions.length).toBe(1);
143
+ const questionId = questions[0]!.id; // q_9
144
+
145
+ // hop 2: get the question detail (needs BOTH saleId and questionId)
146
+ const qDetail = await call("sales.questions.getBySaleidAndQuestionid", { saleId, questionId });
147
+ expect(qDetail.isError ?? false).toBe(false);
148
+ const question = JSON.parse(qDetail.content[0]!.text) as { body: string };
149
+ expect(question.body).toContain("iPhone");
150
+ });
151
+
152
+ it("declares the multi-hop producer chain on the nested tool", async () => {
153
+ const { tools } = await client.listTools();
154
+ const nested = tools.find((t) => t.name === "sales.questions.getBySaleidAndQuestionid");
155
+ expect(nested).toBeDefined();
156
+ // both path params are required inputs
157
+ expect(nested!.inputSchema).toMatchObject({ required: expect.arrayContaining(["saleId", "questionId"]) });
158
+ });
159
+
160
+ it("the generated server.mjs is valid JS (node --check)", () => {
161
+ const dir = mkTmp(".tmp-mcp-chk-");
162
+ const files = emitMcpServer(fixture, { backend: base, title: "Shop" });
163
+ const path = join(dir, "server.mjs");
164
+ writeFileSync(path, files["server.mjs"]!);
165
+ const r = spawnSync(process.execPath, ["--check", path], { encoding: "utf8" });
166
+ expect(r.status).toBe(0);
167
+ });
168
+ });
@@ -0,0 +1,51 @@
1
+ import { OpenApiConverter } from "@typia/utils";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import { emitMcpServer } from "./emitMcpServer";
5
+
6
+ function doc(paths: Record<string, unknown>, schemas: Record<string, unknown> = {}) {
7
+ return OpenApiConverter.upgradeDocument({
8
+ openapi: "3.0.0",
9
+ info: { title: "Shop", version: "1.0.0" },
10
+ paths,
11
+ components: { schemas },
12
+ } as never);
13
+ }
14
+
15
+ const fixture = doc(
16
+ {
17
+ "/sales": {
18
+ get: { operationId: "index", summary: "List sales.", responses: { 200: { description: "ok", content: { "application/json": { schema: { type: "array", items: { $ref: "#/components/schemas/Sale" } } } } } } },
19
+ },
20
+ "/sales/{saleId}": {
21
+ get: { operationId: "at", summary: "Get a sale.", parameters: [{ name: "saleId", in: "path", required: true, schema: { type: "string" } }], responses: { 200: { description: "ok", content: { "application/json": { schema: { $ref: "#/components/schemas/Sale" } } } } } },
22
+ },
23
+ },
24
+ { Sale: { type: "object", properties: { id: { type: "string" }, title: { type: "string" } }, required: ["id"] } },
25
+ );
26
+
27
+ describe("emitMcpServer", () => {
28
+ const files = emitMcpServer(fixture, { backend: "http://127.0.0.1:37001", title: "Shop" });
29
+
30
+ it("emits a runnable MCP project", () => {
31
+ expect(Object.keys(files).sort()).toEqual(["README.md", "package.json", "server.mjs"]);
32
+ const pkg = JSON.parse(files["package.json"]!);
33
+ expect(pkg.dependencies["@modelcontextprotocol/sdk"]).toBeDefined();
34
+ expect(pkg.type).toBe("module");
35
+ });
36
+
37
+ it("server wires the MCP request handlers and bakes the tools + backend", () => {
38
+ const server = files["server.mjs"]!;
39
+ expect(server).toContain("ListToolsRequestSchema");
40
+ expect(server).toContain("CallToolRequestSchema");
41
+ expect(server).toContain("StdioServerTransport");
42
+ // the tool surface is baked in, with the default backend and an HTTP executor
43
+ expect(server).toContain('"sales.get"');
44
+ expect(server).toContain("http://127.0.0.1:37001");
45
+ expect(server).toContain("await fetch(url");
46
+ });
47
+
48
+ it("is deterministic", () => {
49
+ expect(emitMcpServer(fixture, { backend: null })).toEqual(emitMcpServer(fixture, { backend: null }));
50
+ });
51
+ });