@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,171 @@
1
+ import { OpenApi } from "@typia/interface";
2
+
3
+ import { buildToolSurface, IAgentTool } from "./toolSurface";
4
+
5
+ /**
6
+ * Behavioral verification of an agent tool surface — the trust layer.
7
+ *
8
+ * The consumability report proves the surface is *structurally* navigable
9
+ * (every id has a producer). This proves it *behaviorally*: a real agent, given
10
+ * the tools, completes named tasks end-to-end against the live backend. It is
11
+ * how "the API works for an agent" is demonstrated rather than asserted — the
12
+ * agent analogue of the frontend's workflow verifier.
13
+ *
14
+ * The deterministic parts (tool conversion + HTTP execution) are pure and
15
+ * unit-tested; the agent loop is driven by a configurable model (the operator's
16
+ * choice via env / opts), since which model an API's agents will use is the
17
+ * operator's call, not ours.
18
+ */
19
+
20
+ /** OpenAI / OpenRouter function-calling tool shape. */
21
+ export interface IFunctionTool {
22
+ type: "function";
23
+ function: { name: string; description: string; parameters: object };
24
+ }
25
+
26
+ /** OpenAI function names allow only `[a-zA-Z0-9_-]` — the dotted accessor (fine
27
+ * for MCP) is not valid, so sanitize for the function-calling path. */
28
+ export const functionName = (toolName: string): string =>
29
+ toolName.replace(/[^A-Za-z0-9_-]/g, "_");
30
+
31
+ /** Convert the agent tool surface to OpenAI function-calling tools. */
32
+ export function toFunctionTools(tools: IAgentTool[]): IFunctionTool[] {
33
+ return tools.map((t) => ({
34
+ type: "function",
35
+ function: {
36
+ name: functionName(t.name),
37
+ description: t.description,
38
+ parameters: t.inputSchema,
39
+ },
40
+ }));
41
+ }
42
+
43
+ /**
44
+ * Execute one tool call against a live backend: substitute path params, attach
45
+ * query / body, issue the HTTP request, return the response text. Pure aside
46
+ * from the network call — deterministic in how it maps a call to a request.
47
+ */
48
+ export async function executeToolCall(
49
+ tools: IAgentTool[],
50
+ name: string,
51
+ args: Record<string, unknown>,
52
+ opts: { baseUrl: string; auth?: string },
53
+ ): Promise<{ ok: boolean; text: string }> {
54
+ const tool = tools.find((t) => t.name === name);
55
+ if (tool === undefined) return { ok: false, text: `unknown tool: ${name}` };
56
+ let path = tool.operation.path;
57
+ for (const p of tool.operation.pathParams) {
58
+ path = path.replace(`{${p}}`, encodeURIComponent(String(args[p] ?? "")));
59
+ }
60
+ const url = new URL(opts.baseUrl.replace(/\/$/, "") + path);
61
+ if (tool.operation.hasQuery && args.query && typeof args.query === "object") {
62
+ for (const [k, v] of Object.entries(args.query as Record<string, unknown>)) {
63
+ if (v !== undefined && v !== null) url.searchParams.set(k, String(v));
64
+ }
65
+ }
66
+ const method = tool.operation.method;
67
+ try {
68
+ const res = await fetch(url, {
69
+ method,
70
+ headers: { "content-type": "application/json", ...(opts.auth ? { authorization: opts.auth } : {}) },
71
+ body: ["GET", "HEAD", "DELETE"].includes(method) ? undefined : JSON.stringify(args.body ?? {}),
72
+ });
73
+ const text = await res.text();
74
+ return { ok: res.ok, text };
75
+ } catch (err) {
76
+ return { ok: false, text: `request failed: ${err instanceof Error ? err.message : String(err)}` };
77
+ }
78
+ }
79
+
80
+ export interface IAgentTask {
81
+ id: string;
82
+ prompt: string;
83
+ /** Optional success predicate over the agent's final answer (e.g. contains a known value). */
84
+ expect?: (answer: string) => boolean;
85
+ }
86
+
87
+ export interface IAgentTaskResult {
88
+ id: string;
89
+ answer: string;
90
+ toolCalls: string[];
91
+ passed: boolean | null;
92
+ }
93
+
94
+ /** Minimal OpenAI-compatible client surface this verifier needs (so the SDK is injected, not imported). */
95
+ export interface IChatClient {
96
+ chat: {
97
+ completions: {
98
+ create(req: unknown): Promise<{
99
+ choices: Array<{
100
+ message: {
101
+ content: string | null;
102
+ tool_calls?: Array<{ id: string; function: { name: string; arguments: string } }>;
103
+ };
104
+ }>;
105
+ }>;
106
+ };
107
+ };
108
+ }
109
+
110
+ /**
111
+ * Run the agent through each task against the tool surface + backend. The chat
112
+ * client and model are injected by the caller (configurable, e.g. from `.env`).
113
+ */
114
+ export async function verifyAgentTasks(
115
+ document: OpenApi.IDocument,
116
+ opts: {
117
+ client: IChatClient;
118
+ model: string;
119
+ baseUrl: string;
120
+ auth?: string;
121
+ tasks: IAgentTask[];
122
+ maxTurns?: number;
123
+ },
124
+ ): Promise<IAgentTaskResult[]> {
125
+ const tools = buildToolSurface(document);
126
+ const fnTools = toFunctionTools(tools);
127
+ // function-calling sanitizes dotted names → map the sanitized name the model
128
+ // calls back to the real tool for execution.
129
+ const byFnName = new Map(tools.map((t) => [functionName(t.name), t.name]));
130
+ const maxTurns = opts.maxTurns ?? 10;
131
+ const results: IAgentTaskResult[] = [];
132
+
133
+ for (const task of opts.tasks) {
134
+ const messages: Array<Record<string, unknown>> = [
135
+ { role: "system", content: "You are an API agent. Use the provided tools to complete the task, then reply in plain text with the answer. Never ask the user questions." },
136
+ { role: "user", content: task.prompt },
137
+ ];
138
+ const toolCalls: string[] = [];
139
+ let answer = "(no answer)";
140
+ for (let turn = 0; turn < maxTurns; turn++) {
141
+ const resp = await opts.client.chat.completions.create({
142
+ model: opts.model,
143
+ messages,
144
+ tools: fnTools,
145
+ tool_choice: "auto",
146
+ temperature: 0,
147
+ });
148
+ const msg = resp.choices[0]!.message;
149
+ messages.push(msg as Record<string, unknown>);
150
+ if (msg.tool_calls === undefined || msg.tool_calls.length === 0) {
151
+ answer = msg.content ?? "";
152
+ break;
153
+ }
154
+ for (const tc of msg.tool_calls) {
155
+ let args: Record<string, unknown> = {};
156
+ try { args = JSON.parse(tc.function.arguments || "{}"); } catch { /* keep {} */ }
157
+ const realName = byFnName.get(tc.function.name) ?? tc.function.name;
158
+ const result = await executeToolCall(tools, realName, args, { baseUrl: opts.baseUrl, auth: opts.auth });
159
+ toolCalls.push(realName);
160
+ messages.push({ role: "tool", tool_call_id: tc.id, content: result.text.slice(0, 2500) });
161
+ }
162
+ }
163
+ results.push({
164
+ id: task.id,
165
+ answer,
166
+ toolCalls,
167
+ passed: task.expect ? task.expect(answer) : null,
168
+ });
169
+ }
170
+ return results;
171
+ }
@@ -0,0 +1,363 @@
1
+ #!/usr/bin/env node
2
+ import { IAgenticaVendor } from "@agentica/core";
3
+ import fs from "fs/promises";
4
+ import OpenAI from "openai";
5
+ import path from "path";
6
+
7
+ import { AutoViewAgent } from "../AutoViewAgent";
8
+ import { generateDeterministic } from "../generateDeterministic";
9
+ import { emitMcpServer } from "../agent/emitMcpServer";
10
+ import { emitConsumabilityReport } from "../agent/emitReport";
11
+ import { extractBackendFromSwaggerFile, fromSwaggerFile } from "../fromSwagger";
12
+ import { renderPreviewHtml } from "../preview/renderPreview";
13
+
14
+ interface ICliOptions {
15
+ swaggerPath: string;
16
+ outDir: string;
17
+ model: string;
18
+ apiKey: string;
19
+ baseURL?: string;
20
+ designTheme?: string;
21
+ semaphore?: number;
22
+ /**
23
+ * Explicit `--backend <url>` flag value. `undefined` when not given so the
24
+ * CLI can fall back to the swagger's `servers[0].url` and then to simulator
25
+ * mode. Empty string means the user passed `--backend ""` which counts as
26
+ * "force simulator mode".
27
+ */
28
+ backendOverride: string | undefined;
29
+ /** Opt into the Phase 6 Playwright runtime audit. Defaults to false. */
30
+ runtimeAudit: boolean;
31
+ /** Opt into workflow verification (`--verify`). Defaults to false. */
32
+ verify: boolean;
33
+ /**
34
+ * `--preview`: LLM-free READ-layer explorer. Skips the whole generation
35
+ * pipeline (and the --model / --api-key requirement), parses the swagger, and
36
+ * writes a single self-contained `preview.html` so the operator can inspect
37
+ * how AutoView read their swagger before paying for a full run.
38
+ */
39
+ preview: boolean;
40
+ /**
41
+ * `--emit mcp`: deterministic, LLM-free. Instead of the frontend, generate a
42
+ * runnable MCP server (agent tool surface) from the swagger and stop.
43
+ */
44
+ emit?: string;
45
+ /**
46
+ * `--no-llm`: generate the frontend deterministically, with NO model/key. The
47
+ * render is already deterministic; this skips the optional LLM typecheck-
48
+ * recovery / runtime-audit / review passes the full agent would run.
49
+ */
50
+ noLlm: boolean;
51
+ /** Path globs to KEEP (comma-separated `--include`). Slices a large swagger. */
52
+ include?: string[];
53
+ /** Path globs to DROP (comma-separated `--exclude`). */
54
+ exclude?: string[];
55
+ }
56
+
57
+ /**
58
+ * Tiny argv parser — supports `--key value` and `--key=value`. Avoids pulling a
59
+ * CLI parsing library so the package install stays lean.
60
+ */
61
+ function parseArgs(argv: string[]): ICliOptions {
62
+ const positional: string[] = [];
63
+ const flags = new Map<string, string>();
64
+ for (let i = 0; i < argv.length; i++) {
65
+ const arg = argv[i]!;
66
+ if (arg.startsWith("--")) {
67
+ const eq = arg.indexOf("=");
68
+ if (eq !== -1) {
69
+ flags.set(arg.slice(2, eq), arg.slice(eq + 1));
70
+ } else {
71
+ const key = arg.slice(2);
72
+ const next = argv[i + 1];
73
+ if (next !== undefined && !next.startsWith("--")) {
74
+ flags.set(key, next);
75
+ i++;
76
+ } else {
77
+ flags.set(key, "true");
78
+ }
79
+ }
80
+ } else {
81
+ positional.push(arg);
82
+ }
83
+ }
84
+ const swaggerPath = positional[0];
85
+ const outDir = flags.get("out") ?? "./frontend";
86
+ const model = flags.get("model") ?? process.env.AUTOVIEW_MODEL ?? "";
87
+ const apiKey =
88
+ flags.get("api-key") ??
89
+ process.env.AUTOVIEW_API_KEY ??
90
+ process.env.OPENAI_API_KEY ??
91
+ "";
92
+ const baseURL = flags.get("base-url") ?? process.env.AUTOVIEW_BASE_URL;
93
+ const emit = flags.get("emit");
94
+ const designTheme = flags.get("design-theme");
95
+ const semaphoreRaw = flags.get("semaphore");
96
+ const semaphore =
97
+ semaphoreRaw !== undefined ? parseInt(semaphoreRaw, 10) : undefined;
98
+ const backendOverride = flags.get("backend") ?? process.env.AUTOVIEW_BACKEND;
99
+ const preview = flags.get("preview") === "true";
100
+ const noLlm = flags.get("no-llm") === "true";
101
+ const splitGlobs = (raw: string | undefined): string[] | undefined => {
102
+ if (raw === undefined) return undefined;
103
+ const parts = raw
104
+ .split(",")
105
+ .map((s) => s.trim())
106
+ .filter((s) => s.length > 0);
107
+ return parts.length > 0 ? parts : undefined;
108
+ };
109
+ const include = splitGlobs(flags.get("include"));
110
+ const exclude = splitGlobs(flags.get("exclude"));
111
+ if (swaggerPath === undefined) {
112
+ throw new Error(usage("Missing positional argument: <swagger.json>"));
113
+ }
114
+ // --preview, --emit, and --no-llm are LLM-free, so model / api-key are optional.
115
+ const llmFree = preview || emit !== undefined || noLlm;
116
+ if (!llmFree && model === "") {
117
+ throw new Error(
118
+ usage(
119
+ "Missing --model (or AUTOVIEW_MODEL env). Example: --model openai/gpt-5.4",
120
+ ),
121
+ );
122
+ }
123
+ if (!llmFree && apiKey === "") {
124
+ throw new Error(
125
+ usage("Missing --api-key (or AUTOVIEW_API_KEY / OPENAI_API_KEY env)."),
126
+ );
127
+ }
128
+ const runtimeAuditRaw =
129
+ flags.get("runtime-audit") ?? process.env.AUTOVIEW_RUNTIME_AUDIT ?? "";
130
+ const runtimeAudit =
131
+ runtimeAuditRaw === "true" ||
132
+ runtimeAuditRaw === "1" ||
133
+ runtimeAuditRaw === "yes";
134
+ const verify = flags.get("verify") === "true";
135
+ return {
136
+ swaggerPath,
137
+ outDir,
138
+ model,
139
+ apiKey,
140
+ baseURL,
141
+ designTheme,
142
+ semaphore: Number.isFinite(semaphore) ? semaphore : undefined,
143
+ backendOverride,
144
+ runtimeAudit,
145
+ verify,
146
+ preview,
147
+ emit,
148
+ noLlm,
149
+ include,
150
+ exclude,
151
+ };
152
+ }
153
+
154
+ function usage(extra?: string): string {
155
+ const head = extra !== undefined ? `${extra}\n\n` : "";
156
+ return (
157
+ head +
158
+ [
159
+ "Usage: autoview <swagger.json> --model <name> --api-key <key> [options]",
160
+ "",
161
+ "Options:",
162
+ " --out <dir> Output directory (default: ./frontend)",
163
+ " --model <name> LLM model identifier, e.g. openai/gpt-5.4",
164
+ " --api-key <key> Vendor API key (or AUTOVIEW_API_KEY / OPENAI_API_KEY env)",
165
+ " --base-url <url> OpenAI-compatible endpoint (default: OpenAI)",
166
+ " --design-theme <txt> Optional design direction",
167
+ " --semaphore <n> Render concurrency cap (default: 8)",
168
+ " --backend <url> Live backend host for connection.ts (simulate:false).",
169
+ " Auto-extracted from swagger servers[] when omitted.",
170
+ ' Pass --backend="" to force simulator mode.',
171
+ " --runtime-audit Opt into Phase 6 Playwright runtime audit (adds",
172
+ " ~10-20min; installs Playwright + Chromium).",
173
+ " --verify Verify the generated app in a real headless browser:",
174
+ " walk the user workflows (list → detail, forms) and",
175
+ " write wiki/verification.md. Installs Chromium.",
176
+ " --no-llm Generate the frontend deterministically — NO model",
177
+ " / api-key. The render is deterministic; this skips",
178
+ " the optional LLM typecheck-recovery / audit / review.",
179
+ " --preview LLM-free: parse the swagger and write preview.html",
180
+ " (endpoint tree + schemas + READ report). No --model",
181
+ " / --api-key needed. Inspect before a full run.",
182
+ " --emit mcp LLM-free: generate a runnable MCP server (agent tool",
183
+ " surface — read/write annotated, producer hints) instead",
184
+ " of the frontend. Set API_HOST to run it.",
185
+ " --emit report LLM-free: write consumability-report.md — can this API",
186
+ " be driven as a product? (navigable graph + orphan ids).",
187
+ " --include <globs> Comma-separated path globs to KEEP — slice a large",
188
+ ' swagger, e.g. --include "shoppings/customers/**".',
189
+ " --exclude <globs> Comma-separated path globs to DROP after include,",
190
+ ' e.g. --exclude "**/monitors/**".',
191
+ "",
192
+ "Environment fallbacks:",
193
+ " AUTOVIEW_MODEL, AUTOVIEW_API_KEY (or OPENAI_API_KEY),",
194
+ " AUTOVIEW_BASE_URL, AUTOVIEW_BACKEND, AUTOVIEW_RUNTIME_AUDIT",
195
+ ].join("\n")
196
+ );
197
+ }
198
+
199
+ async function writeAll(
200
+ outDir: string,
201
+ files: Record<string, string>,
202
+ ): Promise<void> {
203
+ await fs.mkdir(outDir, { recursive: true });
204
+ for (const [relative, content] of Object.entries(files)) {
205
+ const full = path.join(outDir, relative);
206
+ await fs.mkdir(path.dirname(full), { recursive: true });
207
+ await fs.writeFile(full, content, "utf-8");
208
+ }
209
+ }
210
+
211
+ async function main(): Promise<void> {
212
+ const options = parseArgs(process.argv.slice(2));
213
+ const document = await fromSwaggerFile(options.swaggerPath);
214
+
215
+ // --preview: LLM-free READ-layer explorer. Parse, render a self-contained
216
+ // HTML, and stop — no model call, no generation.
217
+ if (options.preview) {
218
+ const serverUrl =
219
+ (await extractBackendFromSwaggerFile(options.swaggerPath))?.host ?? null;
220
+ const html = renderPreviewHtml(
221
+ document,
222
+ {
223
+ title: document.info?.title ?? "API",
224
+ version: document.info?.version ?? "—",
225
+ serverUrl,
226
+ },
227
+ { include: options.include, exclude: options.exclude },
228
+ );
229
+ await fs.mkdir(options.outDir, { recursive: true });
230
+ const out = path.join(options.outDir, "preview.html");
231
+ await fs.writeFile(out, html, "utf-8");
232
+ // eslint-disable-next-line no-console
233
+ console.log(
234
+ `[autoview] preview written to ${out} (LLM-free). Open it in a browser.`,
235
+ );
236
+ return;
237
+ }
238
+
239
+ // --emit mcp: LLM-free. Generate a runnable MCP server (agent tool surface)
240
+ // from the swagger and stop. No frontend, no model call.
241
+ if (options.emit === "mcp") {
242
+ const host =
243
+ options.backendOverride ??
244
+ (await extractBackendFromSwaggerFile(options.swaggerPath))?.host ??
245
+ null;
246
+ const files = emitMcpServer(document, {
247
+ backend: host,
248
+ title: document.info?.title,
249
+ });
250
+ await writeAll(options.outDir, files);
251
+ // eslint-disable-next-line no-console
252
+ console.log(
253
+ `[autoview] MCP server written to ${options.outDir} (LLM-free). cd in, npm install, set API_HOST, npm start.`,
254
+ );
255
+ return;
256
+ }
257
+ // --emit report: LLM-free. Write a consumability report (can this API be
258
+ // driven as a product? navigable graph + orphan inputs) and stop.
259
+ if (options.emit === "report") {
260
+ const md = emitConsumabilityReport(document);
261
+ await fs.mkdir(options.outDir, { recursive: true });
262
+ const out = path.join(options.outDir, "consumability-report.md");
263
+ await fs.writeFile(out, md, "utf-8");
264
+ // eslint-disable-next-line no-console
265
+ console.log(`[autoview] consumability report written to ${out} (LLM-free).`);
266
+ return;
267
+ }
268
+ if (options.emit !== undefined) {
269
+ throw new Error(usage(`Unknown --emit target "${options.emit}". Supported: mcp, report.`));
270
+ }
271
+
272
+ // Resolve backend host: explicit --backend flag wins; otherwise read the
273
+ // swagger's `servers[0].url` so the generated frontend defaults to
274
+ // `simulate:false` against the real backend. `--backend=""` is treated as
275
+ // "force simulator mode" — the operator can opt out without editing files.
276
+ const backend: { host: string } | null = await (async () => {
277
+ if (options.backendOverride !== undefined) {
278
+ return options.backendOverride.length > 0
279
+ ? { host: options.backendOverride }
280
+ : null;
281
+ }
282
+ return extractBackendFromSwaggerFile(options.swaggerPath);
283
+ })();
284
+ // eslint-disable-next-line no-console
285
+ console.log(
286
+ backend === null
287
+ ? `[autoview] backend: (none) — frontend will boot in simulator mode (typia-random data)`
288
+ : `[autoview] backend: ${backend.host} — frontend will boot in live mode (simulate:false)`,
289
+ );
290
+
291
+ // --no-llm: deterministic frontend, no model/key. Skips the agent's optional
292
+ // LLM polish (typecheck-recovery / runtime-audit / review).
293
+ if (options.noLlm) {
294
+ const files = await generateDeterministic(document, {
295
+ backend: backend ?? { host: null },
296
+ filter: { include: options.include, exclude: options.exclude },
297
+ semaphore: options.semaphore,
298
+ });
299
+ await writeAll(options.outDir, files);
300
+ // eslint-disable-next-line no-console
301
+ console.log(
302
+ `[autoview] wrote ${Object.keys(files).length} files to ${options.outDir} (deterministic, LLM-free).`,
303
+ );
304
+ return;
305
+ }
306
+
307
+ const openai = new OpenAI({
308
+ apiKey: options.apiKey,
309
+ baseURL: options.baseURL,
310
+ });
311
+ const vendor: IAgenticaVendor = {
312
+ model: options.model,
313
+ api: openai,
314
+ };
315
+
316
+ const agent = new AutoViewAgent({
317
+ document,
318
+ vendor,
319
+ designTheme: options.designTheme,
320
+ semaphore: options.semaphore,
321
+ backend,
322
+ runtimeAudit: options.runtimeAudit,
323
+ verify: options.verify,
324
+ include: options.include,
325
+ exclude: options.exclude,
326
+ onEvent: (event) => {
327
+ const summary = (() => {
328
+ switch (event.type) {
329
+ case "autoViewStart":
330
+ return `start (source=${event.source})`;
331
+ case "autoViewSdkStudy":
332
+ return `sdk-study (${event.resources} resources, ${event.actors} actors)`;
333
+ case "autoViewProductPlan":
334
+ return `product-plan (${event.pages} pages)`;
335
+ case "autoViewScaffold":
336
+ return `scaffold (${event.files} files)`;
337
+ case "autoViewRenderPage":
338
+ return `render ${event.completed}/${event.total} → ${event.pagePath} (${event.ok ? "ok" : "failed"})`;
339
+ case "autoViewReview":
340
+ return `review (${event.broken} broken, ${event.recovered} recovered)`;
341
+ case "autoViewComplete":
342
+ return `complete (${event.pages} pages, ${Object.keys(event.files).length} files, ${(event.elapsed / 1000).toFixed(1)}s)`;
343
+ }
344
+ })();
345
+ // eslint-disable-next-line no-console
346
+ console.log(`[autoview] ${summary}`);
347
+ },
348
+ });
349
+
350
+ const { files } = await agent.run();
351
+ await writeAll(options.outDir, files);
352
+ // eslint-disable-next-line no-console
353
+ console.log(
354
+ `[autoview] wrote ${Object.keys(files).length} files to ${options.outDir}`,
355
+ );
356
+ }
357
+
358
+ main().catch((err: unknown) => {
359
+ const message = err instanceof Error ? err.message : String(err);
360
+ // eslint-disable-next-line no-console
361
+ console.error(`\n[autoview] ${message}`);
362
+ process.exit(1);
363
+ });
@@ -0,0 +1,69 @@
1
+ import { NestiaMigrateApplication } from "@nestia/migrate";
2
+ import { OpenApi } from "@typia/interface";
3
+
4
+ import { IAutoBeInterfaceCompiler } from "../typings";
5
+ import { ArrayUtil } from "../utils";
6
+ import { normalizeForNestia } from "../utils/normalizeForNestia";
7
+
8
+ /**
9
+ * Self-defined interface compiler — Step 3 of the AutoBE-independence track.
10
+ *
11
+ * Replaces `@autobe/compiler`'s `AutoBeCompiler`. AutoView only ever calls
12
+ * `compiler.interface.write(document, exclude)` to materialize the typed SDK it
13
+ * shows the LLM (SDK Study) and bundles into the scaffold, so only that surface
14
+ * is reproduced here. TypeScript only — the Java path and the realize/test
15
+ * listener plumbing AutoBE carries are dropped.
16
+ *
17
+ * Under the hood this is the same `@nestia/migrate` call the AutoBE compiler
18
+ * makes; `@nestia/migrate` is a samchon-ecosystem package, not an AutoBE one,
19
+ * so depending on it directly keeps the package free of `@autobe/*`. Swapping
20
+ * NestiaMigrate for a standard-OpenAPI SDK generator (the "Nestia tphase-out"
21
+ * from the design meeting) is a later iteration that happens behind this seam.
22
+ *
23
+ * Prettier beautification (AutoBE's `FilePrinter.beautify`) is intentionally
24
+ * skipped: it pulled in prettier + sort-imports + jsdoc plugins purely for
25
+ * cosmetics, and the render phase reads SDK *types*, not formatting.
26
+ */
27
+ export class AutoViewInterfaceCompiler implements IAutoBeInterfaceCompiler {
28
+ public async write(
29
+ document: OpenApi.IDocument,
30
+ options:
31
+ | string[]
32
+ | {
33
+ language: "typescript" | "java";
34
+ exclude: string[];
35
+ },
36
+ ): Promise<Record<string, string>> {
37
+ const exclude: string[] = Array.isArray(options)
38
+ ? options
39
+ : options.exclude;
40
+ // swagger 직접 nestia — invert/transform AST 왕복 없음, query 보존.
41
+ // normalizeForNestia: nestia mis-handles two real-world shapes — a route
42
+ // whose query has >1 object param (Apideck list endpoints) is dropped, and a
43
+ // GET/HEAD carrying a requestBody (Notion's comments/users) yields an SDK
44
+ // function its own fetcher rejects. Normalizing both keeps the SDK in lockstep
45
+ // with the screen plan, which applies the same pass via toEndpoints.
46
+ const migrate: NestiaMigrateApplication = new NestiaMigrateApplication(
47
+ normalizeForNestia(document),
48
+ );
49
+ const files: Record<string, string> = migrate.nest({
50
+ keyword: true,
51
+ simulate: true,
52
+ e2e: true,
53
+ author: {
54
+ tag: "autoview",
55
+ value: "Generated by AutoView - https://github.com/wrtnlabs/AutoView-Legacy",
56
+ },
57
+ });
58
+ return Object.fromEntries([
59
+ ...(await ArrayUtil.asyncMap(
60
+ Object.entries(files).filter(([key]) => exclude.includes(key) === false),
61
+ async ([key, value]) => [key, value] as const,
62
+ )),
63
+ [
64
+ "packages/api/swagger.json",
65
+ JSON.stringify(migrate.getData().document(), null, 2),
66
+ ],
67
+ ]);
68
+ }
69
+ }