waypoi 0.0.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 (260) hide show
  1. package/.github/instructions/ui.instructions.md +42 -0
  2. package/.github/workflows/ci.yml +35 -0
  3. package/.github/workflows/publish.yml +71 -0
  4. package/.github/workflows/release.yml +48 -0
  5. package/.playwright-mcp/console-2026-04-04T01-41-10-746Z.log +2 -0
  6. package/.playwright-mcp/console-2026-04-04T01-41-28-799Z.log +3 -0
  7. package/.playwright-mcp/console-2026-04-05T02-26-51-909Z.log +76 -0
  8. package/.playwright-mcp/page-2026-04-04T01-41-10-816Z.yml +1 -0
  9. package/.playwright-mcp/page-2026-04-04T01-41-29-141Z.yml +77 -0
  10. package/.playwright-mcp/page-2026-04-04T01-41-42-633Z.yml +190 -0
  11. package/.playwright-mcp/page-2026-04-04T01-42-03-929Z.yml +262 -0
  12. package/.playwright-mcp/page-2026-04-04T02-12-54-813Z.yml +6 -0
  13. package/.playwright-mcp/page-2026-04-04T02-14-58-600Z.yml +190 -0
  14. package/.playwright-mcp/page-2026-04-04T02-15-03-923Z.yml +190 -0
  15. package/.playwright-mcp/page-2026-04-04T02-15-07-426Z.yml +190 -0
  16. package/.playwright-mcp/page-2026-04-04T02-15-25-729Z.yml +262 -0
  17. package/.playwright-mcp/page-2026-04-04T02-16-22-984Z.yml +262 -0
  18. package/.playwright-mcp/page-2026-04-04T02-17-00-599Z.yml +190 -0
  19. package/.playwright-mcp/page-2026-04-04T02-17-50-874Z.yml +190 -0
  20. package/.playwright-mcp/page-2026-04-05T02-26-55-570Z.yml +6 -0
  21. package/AGENTS.md +48 -0
  22. package/CHANGELOG.md +131 -0
  23. package/README.md +552 -0
  24. package/assets/agent-mode.png +0 -0
  25. package/assets/categorize.png +0 -0
  26. package/assets/dashboard.png +0 -0
  27. package/assets/endpoint-proxy.png +0 -0
  28. package/assets/icon.png +0 -0
  29. package/assets/mcp-generate-image.png +0 -0
  30. package/assets/mcp-understand-image.png +0 -0
  31. package/assets/peek-token-flow.png +0 -0
  32. package/assets/playground.png +0 -0
  33. package/assets/sankey.png +0 -0
  34. package/cli/index.ts +2805 -0
  35. package/cli/legacyRewrite.ts +108 -0
  36. package/cli/modelRef.ts +24 -0
  37. package/dist/cli/index.js +2536 -0
  38. package/dist/cli/legacyRewrite.js +92 -0
  39. package/dist/cli/modelRef.js +20 -0
  40. package/dist/src/benchmark/artifacts.js +131 -0
  41. package/dist/src/benchmark/capabilityClassifier.js +81 -0
  42. package/dist/src/benchmark/capabilityStore.js +144 -0
  43. package/dist/src/benchmark/config.js +238 -0
  44. package/dist/src/benchmark/gates.js +118 -0
  45. package/dist/src/benchmark/jobs.js +252 -0
  46. package/dist/src/benchmark/runner.js +1847 -0
  47. package/dist/src/benchmark/schema.js +353 -0
  48. package/dist/src/benchmark/suites.js +314 -0
  49. package/dist/src/benchmark/tinyQaDataset.js +422 -0
  50. package/dist/src/benchmark/types.js +25 -0
  51. package/dist/src/config.js +47 -0
  52. package/dist/src/index.js +178 -0
  53. package/dist/src/mcp/client.js +215 -0
  54. package/dist/src/mcp/discovery.js +226 -0
  55. package/dist/src/mcp/policy.js +65 -0
  56. package/dist/src/mcp/registry.js +129 -0
  57. package/dist/src/mcp/service.js +460 -0
  58. package/dist/src/middleware/auth.js +179 -0
  59. package/dist/src/middleware/requestCapture.js +192 -0
  60. package/dist/src/middleware/requestStats.js +118 -0
  61. package/dist/src/pools/builder.js +132 -0
  62. package/dist/src/pools/repository.js +69 -0
  63. package/dist/src/pools/scheduler.js +360 -0
  64. package/dist/src/pools/types.js +2 -0
  65. package/dist/src/protocols/adapters/dashscope.js +267 -0
  66. package/dist/src/protocols/adapters/inferenceV2.js +346 -0
  67. package/dist/src/protocols/adapters/openai.js +27 -0
  68. package/dist/src/protocols/registry.js +99 -0
  69. package/dist/src/protocols/types.js +2 -0
  70. package/dist/src/providers/health.js +153 -0
  71. package/dist/src/providers/importer.js +289 -0
  72. package/dist/src/providers/modelRegistry.js +313 -0
  73. package/dist/src/providers/repository.js +361 -0
  74. package/dist/src/providers/types.js +2 -0
  75. package/dist/src/routes/admin.js +531 -0
  76. package/dist/src/routes/audio.js +295 -0
  77. package/dist/src/routes/chat.js +240 -0
  78. package/dist/src/routes/embeddings.js +157 -0
  79. package/dist/src/routes/images.js +288 -0
  80. package/dist/src/routes/mcp.js +256 -0
  81. package/dist/src/routes/mcpService.js +100 -0
  82. package/dist/src/routes/models.js +48 -0
  83. package/dist/src/routes/responses.js +711 -0
  84. package/dist/src/routes/sessions.js +450 -0
  85. package/dist/src/routes/stats.js +270 -0
  86. package/dist/src/routes/ui.js +97 -0
  87. package/dist/src/routes/videos.js +107 -0
  88. package/dist/src/routing/router.js +338 -0
  89. package/dist/src/services/imageGeneration.js +280 -0
  90. package/dist/src/services/imageUnderstanding.js +352 -0
  91. package/dist/src/services/videoGeneration.js +79 -0
  92. package/dist/src/storage/captureRepository.js +1591 -0
  93. package/dist/src/storage/files.js +157 -0
  94. package/dist/src/storage/imageCache.js +346 -0
  95. package/dist/src/storage/repositories.js +388 -0
  96. package/dist/src/storage/sessionRepository.js +370 -0
  97. package/dist/src/storage/statsRepository.js +204 -0
  98. package/dist/src/transport/httpClient.js +126 -0
  99. package/dist/src/types.js +2 -0
  100. package/dist/src/utils/messageMedia.js +285 -0
  101. package/dist/src/utils/modelCapabilities.js +108 -0
  102. package/dist/src/utils/modelDiscovery.js +170 -0
  103. package/dist/src/version.js +5 -0
  104. package/dist/src/workers/captureRetention.js +25 -0
  105. package/dist/src/workers/configWatcher.js +91 -0
  106. package/dist/src/workers/healthChecker.js +21 -0
  107. package/dist/src/workers/statsRotation.js +41 -0
  108. package/docs/LLM/output_schema.md +312 -0
  109. package/docs/benchmark.md +208 -0
  110. package/docs/mcp-guidelines.md +125 -0
  111. package/docs/mcp-service.md +178 -0
  112. package/docs/opencode.md +86 -0
  113. package/docs/providers.md +79 -0
  114. package/examples/benchmark.config.yaml +28 -0
  115. package/examples/providers/alibaba-dashscope.yaml +88 -0
  116. package/examples/providers/alibaba-llm.yaml +64 -0
  117. package/examples/providers/alibaba-registry.yaml +7 -0
  118. package/examples/providers/inference-v2-ray.yaml +29 -0
  119. package/examples/scenarios/assets/omni-call-sample.wav +0 -0
  120. package/examples/scenarios/custom.jsonl +5 -0
  121. package/examples/scenarios/custom.yaml +40 -0
  122. package/model-form-v2.png +0 -0
  123. package/package.json +66 -0
  124. package/provider-form-v2.png +0 -0
  125. package/provider-form.png +0 -0
  126. package/scripts/manual-test.sh +11 -0
  127. package/scripts/version-from-git.js +23 -0
  128. package/src/benchmark/artifacts.ts +149 -0
  129. package/src/benchmark/capabilityClassifier.ts +99 -0
  130. package/src/benchmark/capabilityStore.ts +174 -0
  131. package/src/benchmark/config.ts +337 -0
  132. package/src/benchmark/gates.ts +164 -0
  133. package/src/benchmark/jobs.ts +312 -0
  134. package/src/benchmark/runner.ts +2519 -0
  135. package/src/benchmark/schema.ts +443 -0
  136. package/src/benchmark/suites.ts +323 -0
  137. package/src/benchmark/tinyQaDataset.ts +428 -0
  138. package/src/benchmark/types.ts +442 -0
  139. package/src/config.ts +44 -0
  140. package/src/index.ts +195 -0
  141. package/src/mcp/client.ts +305 -0
  142. package/src/mcp/discovery.ts +266 -0
  143. package/src/mcp/policy.ts +105 -0
  144. package/src/mcp/registry.ts +164 -0
  145. package/src/mcp/service.ts +611 -0
  146. package/src/middleware/auth.ts +251 -0
  147. package/src/middleware/requestCapture.ts +245 -0
  148. package/src/middleware/requestStats.ts +163 -0
  149. package/src/pools/builder.ts +159 -0
  150. package/src/pools/repository.ts +71 -0
  151. package/src/pools/scheduler.ts +425 -0
  152. package/src/pools/types.ts +117 -0
  153. package/src/protocols/adapters/dashscope.ts +335 -0
  154. package/src/protocols/adapters/inferenceV2.ts +428 -0
  155. package/src/protocols/adapters/openai.ts +32 -0
  156. package/src/protocols/registry.ts +117 -0
  157. package/src/protocols/types.ts +81 -0
  158. package/src/providers/health.ts +207 -0
  159. package/src/providers/importer.ts +402 -0
  160. package/src/providers/modelRegistry.ts +415 -0
  161. package/src/providers/repository.ts +439 -0
  162. package/src/providers/types.ts +113 -0
  163. package/src/routes/admin.ts +666 -0
  164. package/src/routes/audio.ts +372 -0
  165. package/src/routes/chat.ts +301 -0
  166. package/src/routes/embeddings.ts +197 -0
  167. package/src/routes/images.ts +356 -0
  168. package/src/routes/mcp.ts +320 -0
  169. package/src/routes/mcpService.ts +114 -0
  170. package/src/routes/models.ts +50 -0
  171. package/src/routes/responses.ts +872 -0
  172. package/src/routes/sessions.ts +558 -0
  173. package/src/routes/stats.ts +312 -0
  174. package/src/routes/ui.ts +96 -0
  175. package/src/routes/videos.ts +132 -0
  176. package/src/routing/router.ts +501 -0
  177. package/src/services/imageGeneration.ts +396 -0
  178. package/src/services/imageUnderstanding.ts +449 -0
  179. package/src/services/videoGeneration.ts +127 -0
  180. package/src/storage/captureRepository.ts +1835 -0
  181. package/src/storage/files.ts +178 -0
  182. package/src/storage/imageCache.ts +405 -0
  183. package/src/storage/repositories.ts +494 -0
  184. package/src/storage/sessionRepository.ts +419 -0
  185. package/src/storage/statsRepository.ts +238 -0
  186. package/src/transport/httpClient.ts +145 -0
  187. package/src/types.ts +322 -0
  188. package/src/utils/messageMedia.ts +293 -0
  189. package/src/utils/modelCapabilities.ts +161 -0
  190. package/src/utils/modelDiscovery.ts +203 -0
  191. package/src/workers/captureRetention.ts +25 -0
  192. package/src/workers/configWatcher.ts +115 -0
  193. package/src/workers/healthChecker.ts +22 -0
  194. package/src/workers/statsRotation.ts +49 -0
  195. package/tests/benchmarkAdminRoutes.test.ts +82 -0
  196. package/tests/benchmarkBasics.test.ts +116 -0
  197. package/tests/captureAdminRoutes.test.ts +420 -0
  198. package/tests/captureRepository.test.ts +797 -0
  199. package/tests/cliLegacyRewrite.test.ts +45 -0
  200. package/tests/imageGeneration.service.test.ts +107 -0
  201. package/tests/imageUnderstanding.service.test.ts +123 -0
  202. package/tests/mcpPolicy.test.ts +105 -0
  203. package/tests/mcpService.test.ts +1245 -0
  204. package/tests/modelRef.test.ts +23 -0
  205. package/tests/modelsRoutes.test.ts +154 -0
  206. package/tests/sessionMediaCache.test.ts +167 -0
  207. package/tests/statsRoutes.test.ts +323 -0
  208. package/tsconfig.json +15 -0
  209. package/ui/index.html +16 -0
  210. package/ui/package-lock.json +8521 -0
  211. package/ui/package.json +52 -0
  212. package/ui/postcss.config.js +6 -0
  213. package/ui/public/assets/apple-touch-icon.png +0 -0
  214. package/ui/public/assets/favicon-16.png +0 -0
  215. package/ui/public/assets/favicon-32.png +0 -0
  216. package/ui/public/assets/icon-192.png +0 -0
  217. package/ui/public/assets/icon-512.png +0 -0
  218. package/ui/src/App.tsx +27 -0
  219. package/ui/src/api/client.ts +1503 -0
  220. package/ui/src/components/EndpointUsageGuide.tsx +361 -0
  221. package/ui/src/components/Layout.tsx +124 -0
  222. package/ui/src/components/MessageContent.tsx +365 -0
  223. package/ui/src/components/ToolCallMessage.tsx +179 -0
  224. package/ui/src/components/ToolPicker.tsx +442 -0
  225. package/ui/src/components/messageContentParser.test.ts +41 -0
  226. package/ui/src/components/messageContentParser.ts +73 -0
  227. package/ui/src/components/thinkingPreview.test.ts +27 -0
  228. package/ui/src/components/thinkingPreview.ts +15 -0
  229. package/ui/src/components/toMermaidSankey.test.ts +78 -0
  230. package/ui/src/components/toMermaidSankey.ts +56 -0
  231. package/ui/src/components/ui/button.tsx +58 -0
  232. package/ui/src/components/ui/input.tsx +21 -0
  233. package/ui/src/components/ui/textarea.tsx +21 -0
  234. package/ui/src/lib/utils.ts +6 -0
  235. package/ui/src/main.tsx +9 -0
  236. package/ui/src/pages/AgentPlayground.tsx +2010 -0
  237. package/ui/src/pages/Benchmark.tsx +988 -0
  238. package/ui/src/pages/Dashboard.tsx +581 -0
  239. package/ui/src/pages/Peek.tsx +962 -0
  240. package/ui/src/pages/Settings.tsx +2013 -0
  241. package/ui/src/pages/agentPlaygroundPayload.test.ts +109 -0
  242. package/ui/src/pages/agentPlaygroundPayload.ts +97 -0
  243. package/ui/src/pages/agentThinkingContent.test.ts +50 -0
  244. package/ui/src/pages/agentThinkingContent.ts +57 -0
  245. package/ui/src/pages/dashboardTokenUsage.test.ts +66 -0
  246. package/ui/src/pages/dashboardTokenUsage.ts +36 -0
  247. package/ui/src/pages/imageUpload.test.ts +39 -0
  248. package/ui/src/pages/imageUpload.ts +71 -0
  249. package/ui/src/pages/peekFilters.test.ts +29 -0
  250. package/ui/src/pages/peekFilters.ts +13 -0
  251. package/ui/src/pages/peekMedia.test.ts +58 -0
  252. package/ui/src/pages/peekMedia.ts +148 -0
  253. package/ui/src/pages/sessionAutoTitle.test.ts +128 -0
  254. package/ui/src/pages/sessionAutoTitle.ts +106 -0
  255. package/ui/src/stores/settings.ts +58 -0
  256. package/ui/src/styles/globals.css +223 -0
  257. package/ui/src/vite-env.d.ts +8 -0
  258. package/ui/tailwind.config.js +106 -0
  259. package/ui/tsconfig.json +32 -0
  260. package/ui/vite.config.ts +37 -0
@@ -0,0 +1,442 @@
1
+ import { ModelModality } from "../types";
2
+
3
+ export type BenchmarkMode =
4
+ | "chat"
5
+ | "agent"
6
+ | "responses"
7
+ | "embeddings"
8
+ | "image_generation"
9
+ | "audio_transcription"
10
+ | "audio_speech"
11
+ | "omni_call";
12
+
13
+ export type BenchmarkExecutionMode = "showcase" | "diagnostic";
14
+
15
+ export type BenchmarkExampleSource = "opencode" | "builtin" | "file" | "huggingface";
16
+
17
+ export type BenchmarkCapabilityKey =
18
+ | "chat_basic"
19
+ | "chat_streaming"
20
+ | "chat_tool_calls"
21
+ | "chat_vision_input"
22
+ | "images_generation"
23
+ | "images_edit"
24
+ | "embeddings"
25
+ | "audio_transcription"
26
+ | "audio_speech"
27
+ | "responses_compat";
28
+
29
+ export type BenchmarkCapabilityStatus =
30
+ | "supported"
31
+ | "unsupported"
32
+ | "unknown"
33
+ | "misconfigured";
34
+
35
+ export type BenchmarkCapabilityFreshness = "fresh" | "stale";
36
+
37
+ export interface BenchmarkAssertions {
38
+ contains?: string[];
39
+ notContains?: string[];
40
+ requiredToolNames?: string[];
41
+ minToolCalls?: number;
42
+ maxToolCalls?: number;
43
+ maxLatencyMs?: number;
44
+ statusCode: number;
45
+ minItems?: number;
46
+ minVectorLength?: number;
47
+ minImages?: number;
48
+ containsText?: string[];
49
+ notContainsText?: string[];
50
+ minBytes?: number;
51
+ contentType?: string;
52
+ }
53
+
54
+ export interface BenchmarkScenario {
55
+ id: string;
56
+ mode: BenchmarkMode;
57
+ title?: string;
58
+ summary?: string;
59
+ userVisibleGoal?: string;
60
+ exampleSource?: BenchmarkExampleSource;
61
+ inputPreview?: string;
62
+ successCriteria?: string;
63
+ expectedHighlights?: string[];
64
+ capability?: BenchmarkCapabilityKey;
65
+ model?: string;
66
+ timeoutMs?: number;
67
+ requiresAvailableTools?: boolean;
68
+ assertions: BenchmarkAssertions;
69
+
70
+ // chat / agent
71
+ prompt?: string;
72
+ tools?: string[];
73
+ maxIterations?: number;
74
+ temperature?: number;
75
+ top_p?: number;
76
+ max_tokens?: number;
77
+ presence_penalty?: number;
78
+ frequency_penalty?: number;
79
+ seed?: number;
80
+ stop?: string | string[];
81
+
82
+ // embeddings
83
+ input?: string | string[];
84
+
85
+ // image generation
86
+ n?: number;
87
+ size?: string;
88
+
89
+ // audio transcription
90
+ audioFile?: string;
91
+
92
+ // audio speech
93
+ inputText?: string;
94
+ voice?: string;
95
+ response_format?: string;
96
+ }
97
+
98
+ export interface BenchmarkCliOptions {
99
+ suite?: string;
100
+ exampleId?: string;
101
+ scenarioPath?: string;
102
+ modelOverride?: string;
103
+ outPath?: string;
104
+ configPath?: string;
105
+ profile?: string;
106
+ baselinePath?: string;
107
+ executionMode?: BenchmarkExecutionMode;
108
+ listExamples?: boolean;
109
+ updateCapCache?: boolean;
110
+ capTtlDays?: number;
111
+ temperature?: number;
112
+ top_p?: number;
113
+ max_tokens?: number;
114
+ presence_penalty?: number;
115
+ frequency_penalty?: number;
116
+ seed?: number;
117
+ stop?: string | string[];
118
+ }
119
+
120
+ export interface BenchmarkDefaults {
121
+ requestTimeoutMs: number;
122
+ toolTimeoutMs: number;
123
+ maxIterations: number;
124
+ temperature: number;
125
+ top_p: number;
126
+ max_tokens: number;
127
+ presence_penalty: number;
128
+ frequency_penalty: number;
129
+ seed?: number;
130
+ stop?: string | string[];
131
+ }
132
+
133
+ export interface BenchmarkProfileSettings {
134
+ warmupRuns: number;
135
+ measuredRuns: number;
136
+ minScenarioPassRate: number;
137
+ }
138
+
139
+ export interface BenchmarkGateHardConfig {
140
+ smokeMinSuccessRate: number;
141
+ }
142
+
143
+ export interface BenchmarkGateSoftConfig {
144
+ maxP95RegressionPct: number;
145
+ maxThroughputDropPct: number;
146
+ }
147
+
148
+ export interface BenchmarkGateConfig {
149
+ hard: BenchmarkGateHardConfig;
150
+ soft: BenchmarkGateSoftConfig;
151
+ }
152
+
153
+ export interface BenchmarkConfigFile {
154
+ version?: number;
155
+ defaults?: Partial<BenchmarkDefaults>;
156
+ profiles?: Record<string, Partial<BenchmarkProfileSettings>>;
157
+ gates?: {
158
+ hard?: Partial<BenchmarkGateHardConfig>;
159
+ soft?: Partial<BenchmarkGateSoftConfig>;
160
+ };
161
+ run?: {
162
+ suite?: string;
163
+ exampleId?: string;
164
+ scenarioPath?: string;
165
+ model?: string;
166
+ outPath?: string;
167
+ profile?: string;
168
+ baselinePath?: string;
169
+ executionMode?: BenchmarkExecutionMode;
170
+ listExamples?: boolean;
171
+ updateCapCache?: boolean;
172
+ capTtlDays?: number;
173
+ temperature?: number;
174
+ top_p?: number;
175
+ max_tokens?: number;
176
+ presence_penalty?: number;
177
+ frequency_penalty?: number;
178
+ seed?: number;
179
+ stop?: string | string[];
180
+ };
181
+ }
182
+
183
+ export interface BenchmarkRunPlan {
184
+ suite?: string;
185
+ exampleId?: string;
186
+ scenarioPath?: string;
187
+ modelOverride?: string;
188
+ outPath?: string;
189
+ baselinePath?: string;
190
+ executionMode?: BenchmarkExecutionMode;
191
+ listExamples?: boolean;
192
+ updateCapCache?: boolean;
193
+ capTtlDays?: number;
194
+ temperature?: number;
195
+ top_p?: number;
196
+ max_tokens?: number;
197
+ presence_penalty?: number;
198
+ frequency_penalty?: number;
199
+ seed?: number;
200
+ stop?: string | string[];
201
+ }
202
+
203
+ export interface EffectiveBenchmarkConfig {
204
+ version: number;
205
+ profile: string;
206
+ defaults: BenchmarkDefaults;
207
+ profileSettings: BenchmarkProfileSettings;
208
+ gates: BenchmarkGateConfig;
209
+ run: BenchmarkRunPlan;
210
+ configSource?: string;
211
+ }
212
+
213
+ export interface ValidationOutcome {
214
+ scenarios: BenchmarkScenario[];
215
+ warnings: string[];
216
+ }
217
+
218
+ export interface ScenarioRunSample {
219
+ runIndex: number;
220
+ success: boolean;
221
+ latencyMs: number;
222
+ statusCode: number;
223
+ tokens: number;
224
+ toolCalls: number;
225
+ throughputTokensPerSec: number;
226
+ finalOutput: string;
227
+ outputPreview: string;
228
+ verdict: string;
229
+ usedToolNames: string[];
230
+ error?: string;
231
+ candidateAttempts?: number;
232
+ failovers?: number;
233
+ rateLimitSwitches?: number;
234
+ distinctProviders?: number;
235
+ distinctModels?: number;
236
+ audioOutputPresent?: boolean;
237
+ }
238
+
239
+ export interface ScenarioResult {
240
+ id: string;
241
+ mode: BenchmarkMode;
242
+ title?: string;
243
+ summary?: string;
244
+ userVisibleGoal?: string;
245
+ exampleSource?: BenchmarkExampleSource;
246
+ inputPreview?: string;
247
+ successCriteria?: string;
248
+ expectedHighlights?: string[];
249
+ model: string;
250
+ status: "passed" | "failed" | "skipped";
251
+ success: boolean;
252
+ skippedReason?: string;
253
+ passRate: number;
254
+ passedRuns: number;
255
+ failedRuns: number;
256
+ avgLatencyMs: number;
257
+ p50LatencyMs: number;
258
+ p95LatencyMs: number;
259
+ p99LatencyMs: number;
260
+ totalTokens: number;
261
+ totalToolCalls: number;
262
+ avgThroughputTokensPerSec: number;
263
+ candidateAttempts: number;
264
+ failovers: number;
265
+ rateLimitSwitches: number;
266
+ distinctProviders: number;
267
+ distinctModels: number;
268
+ audioOutputRuns: number;
269
+ usedToolNames: string[];
270
+ verdict: string;
271
+ errorReasons: string[];
272
+ outputPreview: string;
273
+ }
274
+
275
+ export interface BenchmarkScenarioSummary {
276
+ id: string;
277
+ suite: string;
278
+ mode: BenchmarkMode;
279
+ title: string;
280
+ summary: string;
281
+ userVisibleGoal: string;
282
+ exampleSource: BenchmarkExampleSource;
283
+ inputPreview: string;
284
+ successCriteria: string;
285
+ expectedHighlights: string[];
286
+ requiresAvailableTools: boolean;
287
+ model?: string;
288
+ }
289
+
290
+ export interface BenchmarkToolTraceStep {
291
+ kind: "tool_call" | "tool_result";
292
+ toolName: string;
293
+ toolCallId?: string;
294
+ argumentsText?: string;
295
+ contentText?: string;
296
+ }
297
+
298
+ export interface BenchmarkExchangeSummary {
299
+ timestamp?: string;
300
+ mode: BenchmarkMode;
301
+ model: string;
302
+ requestPath: string;
303
+ statusCode: number;
304
+ contentType: string;
305
+ requestSanitized: unknown;
306
+ responseSanitized: unknown;
307
+ requestRaw?: unknown;
308
+ responseRaw?: unknown;
309
+ requestPreview: string;
310
+ responsePreview: string;
311
+ endpointId?: string;
312
+ endpointName?: string;
313
+ upstreamModel?: string;
314
+ toolTrace: BenchmarkToolTraceStep[];
315
+ }
316
+
317
+ export interface BenchmarkScenarioDetail {
318
+ id: string;
319
+ suite?: string;
320
+ example?: BenchmarkScenarioSummary;
321
+ model: string;
322
+ status: "passed" | "failed" | "skipped";
323
+ verdict: string;
324
+ exchanges: BenchmarkExchangeSummary[];
325
+ finalResponsePreview: string;
326
+ usedToolNames: string[];
327
+ }
328
+
329
+ export interface BenchmarkGateResult {
330
+ passed: boolean;
331
+ messages: string[];
332
+ }
333
+
334
+ export interface BenchmarkGateResults {
335
+ hard: BenchmarkGateResult;
336
+ soft: BenchmarkGateResult;
337
+ }
338
+
339
+ export interface BenchmarkReport {
340
+ id: string;
341
+ createdAt: string;
342
+ profile: string;
343
+ executionMode: BenchmarkExecutionMode;
344
+ suite?: string;
345
+ exampleId?: string;
346
+ scenarioPath?: string;
347
+ modelOverride?: string;
348
+ configSource?: string;
349
+ total: number;
350
+ executed: number;
351
+ skipped: number;
352
+ succeeded: number;
353
+ failed: number;
354
+ successRate: number;
355
+ totalTokens: number;
356
+ totalToolCalls: number;
357
+ avgLatencyMs: number;
358
+ p50LatencyMs: number;
359
+ p95LatencyMs: number;
360
+ p99LatencyMs: number;
361
+ avgThroughputTokensPerSec: number;
362
+ modeSummary: Record<
363
+ BenchmarkMode,
364
+ { total: number; executed: number; skipped: number; passed: number; failed: number }
365
+ >;
366
+ effectiveConfig: {
367
+ defaults: BenchmarkDefaults;
368
+ profileSettings: BenchmarkProfileSettings;
369
+ gates: BenchmarkGateConfig;
370
+ };
371
+ results: ScenarioResult[];
372
+ scenarioDetails: BenchmarkScenarioDetail[];
373
+ scenarioRuns: Array<{ id: string; samples: ScenarioRunSample[] }>;
374
+ gateResults: BenchmarkGateResults;
375
+ warnings: string[];
376
+ topFailureReasons: Array<{ reason: string; count: number }>;
377
+ capabilityMatrix?: BenchmarkCapabilityMatrix;
378
+ }
379
+
380
+ export interface BenchmarkRunOutput {
381
+ report: BenchmarkReport;
382
+ artifactPath: string;
383
+ textArtifactPath: string;
384
+ }
385
+
386
+ export const BENCHMARK_MODES: BenchmarkMode[] = [
387
+ "chat",
388
+ "agent",
389
+ "responses",
390
+ "embeddings",
391
+ "image_generation",
392
+ "audio_transcription",
393
+ "audio_speech",
394
+ "omni_call",
395
+ ];
396
+
397
+ export const BENCHMARK_CAPABILITY_KEYS: BenchmarkCapabilityKey[] = [
398
+ "chat_basic",
399
+ "chat_streaming",
400
+ "chat_tool_calls",
401
+ "chat_vision_input",
402
+ "images_generation",
403
+ "images_edit",
404
+ "embeddings",
405
+ "audio_transcription",
406
+ "audio_speech",
407
+ "responses_compat",
408
+ ];
409
+
410
+ export interface BenchmarkCapabilityFinding {
411
+ capability: BenchmarkCapabilityKey;
412
+ status: BenchmarkCapabilityStatus;
413
+ confidence: number;
414
+ evidence: string;
415
+ scenarioId?: string;
416
+ statusCode?: number;
417
+ observedAt: string;
418
+ }
419
+
420
+ export interface BenchmarkModelCapabilitySnapshot {
421
+ model: string;
422
+ providerId: string;
423
+ modelId: string;
424
+ configFingerprint: string;
425
+ confidence: number;
426
+ lastVerifiedAt: string;
427
+ expiresAt: string;
428
+ freshness: BenchmarkCapabilityFreshness;
429
+ findings: Record<BenchmarkCapabilityKey, BenchmarkCapabilityFinding>;
430
+ }
431
+
432
+ export interface BenchmarkCapabilityMatrix {
433
+ generatedAt: string;
434
+ ttlDays: number;
435
+ models: BenchmarkModelCapabilitySnapshot[];
436
+ }
437
+
438
+ export interface BenchmarkModeRequirements {
439
+ requiredInput: ModelModality[];
440
+ requiredOutput: ModelModality[];
441
+ preferredEndpointType?: "llm" | "diffusion" | "audio" | "embedding";
442
+ }
package/src/config.ts ADDED
@@ -0,0 +1,44 @@
1
+ import path from "path";
2
+
3
+ function resolveBinaryName(): string {
4
+ if (process.argv.length >= 2) {
5
+ const bin = path.basename(process.argv[1]);
6
+ if (bin === "waypoi" || bin === "waypoi-dev") return bin;
7
+ }
8
+ if (process.env.WAYPOI_DEV === "1") return "waypoi-dev";
9
+ return "waypoi";
10
+ }
11
+
12
+ function isDev(): boolean {
13
+ return resolveBinaryName() === "waypoi-dev";
14
+ }
15
+
16
+ function resolvePort(): number {
17
+ if (process.env.PORT) return Number(process.env.PORT);
18
+ return isDev() ? 9470 : 9469;
19
+ }
20
+
21
+ function resolveStorageDir(): string {
22
+ if (process.env.WAYPOI_DIR) return process.env.WAYPOI_DIR;
23
+ if (isDev()) {
24
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? ".";
25
+ return path.join(home, ".config", "waypoi-dev");
26
+ }
27
+ return "";
28
+ }
29
+
30
+ function resolvePidFileName(): string {
31
+ return isDev() ? "waypoi-dev.pid" : "waypoi.pid";
32
+ }
33
+
34
+ function resolveAppName(): string {
35
+ return isDev() ? "waypoi-dev" : "waypoi";
36
+ }
37
+
38
+ export const appConfig = {
39
+ isDev: isDev(),
40
+ port: resolvePort(),
41
+ appName: resolveAppName(),
42
+ storageDirOverride: resolveStorageDir(),
43
+ pidFileName: resolvePidFileName(),
44
+ };
package/src/index.ts ADDED
@@ -0,0 +1,195 @@
1
+ import Fastify from "fastify";
2
+ import { registerChatRoutes } from "./routes/chat";
3
+ import { registerEmbeddingsRoutes } from "./routes/embeddings";
4
+ import { registerModelsRoutes } from "./routes/models";
5
+ import { registerAdminRoutes } from "./routes/admin";
6
+ import { registerImageRoutes } from "./routes/images";
7
+ import { registerVideoRoutes } from "./routes/videos";
8
+ import { registerAudioRoutes } from "./routes/audio";
9
+ import { registerResponsesRoutes } from "./routes/responses";
10
+ import { registerStatsRoutes } from "./routes/stats";
11
+ import { registerSessionRoutes } from "./routes/sessions";
12
+ import { registerMcpRoutes } from "./routes/mcp";
13
+ import { closeMcpServiceRoutes, registerMcpServiceRoutes } from "./routes/mcpService";
14
+ import { registerUiRoutes } from "./routes/ui";
15
+ import { registerRequestStatsMiddleware } from "./middleware/requestStats";
16
+ import { registerRequestCaptureMiddleware } from "./middleware/requestCapture";
17
+ import { registerAuthHooks, loadAuthConfig, updateAuthConfig } from "./middleware/auth";
18
+ import { startHealthChecker, stopHealthChecker } from "./workers/healthChecker";
19
+ import { startStatsRotation, stopStatsRotation } from "./workers/statsRotation";
20
+ import { startConfigWatcher, stopConfigWatcher } from "./workers/configWatcher";
21
+ import { startCaptureRetentionWorker, stopCaptureRetentionWorker } from "./workers/captureRetention";
22
+ import { ensureStorageDir, resolveStoragePaths } from "./storage/files";
23
+ import { invalidateConfigCache } from "./storage/repositories";
24
+ import { discoverAllTools, disconnectAllServers, summarizeMcpError, discoverBuiltinTools } from "./mcp/discovery";
25
+ import { listProviders } from "./providers/repository";
26
+ import { listModelsForApi } from "./providers/modelRegistry";
27
+ import { listPools } from "./pools/repository";
28
+ import { rebuildDefaultPools } from "./pools/builder";
29
+ import { appConfig } from "./config";
30
+ import { VERSION } from "./version.js";
31
+
32
+ if (!process.env.WAYPOI_DIR && appConfig.storageDirOverride) {
33
+ process.env.WAYPOI_DIR = appConfig.storageDirOverride;
34
+ }
35
+
36
+ const PORT = appConfig.port;
37
+ const ADMIN_TOKEN = process.env.ADMIN_TOKEN;
38
+ const APP_NAME = appConfig.appName;
39
+
40
+ async function start(): Promise<void> {
41
+ const app = Fastify({ logger: true });
42
+ const paths = resolveStoragePaths();
43
+ await ensureStorageDir(paths);
44
+ try {
45
+ await rebuildDefaultPools(paths);
46
+ } catch (error) {
47
+ console.error(`[${APP_NAME}] Failed to rebuild smart pool: ${(error as Error).message}`);
48
+ if (process.env.WAYPOI_DEBUG_ERRORS === "1") {
49
+ console.error(error);
50
+ }
51
+ }
52
+
53
+ // Register middleware
54
+ await registerRequestStatsMiddleware(app, paths);
55
+ await registerRequestCaptureMiddleware(app, paths);
56
+
57
+ // Register auth hooks (no-op by default, enable via config.authEnabled)
58
+ await registerAuthHooks(app, paths, ["/admin", "/ui"]);
59
+
60
+ // OpenAI-compatible routes
61
+ await registerChatRoutes(app, paths);
62
+ await registerEmbeddingsRoutes(app, paths);
63
+ await registerModelsRoutes(app, paths);
64
+ await registerImageRoutes(app, paths);
65
+ await registerVideoRoutes(app, paths);
66
+ await registerAudioRoutes(app, paths);
67
+ await registerResponsesRoutes(app, paths);
68
+
69
+ // Admin routes
70
+ await registerAdminRoutes(app, paths, { adminToken: ADMIN_TOKEN, version: VERSION });
71
+ await registerStatsRoutes(app, paths);
72
+ await registerSessionRoutes(app);
73
+ await registerMcpRoutes(app, paths);
74
+ await registerMcpServiceRoutes(app, paths);
75
+
76
+ // UI routes (serve React frontend)
77
+ await registerUiRoutes(app);
78
+
79
+ // Start background workers
80
+ startHealthChecker(paths);
81
+ startStatsRotation(paths);
82
+ startCaptureRetentionWorker(paths);
83
+
84
+ // Auto-connect to enabled MCP servers and discover tools
85
+ discoverAllTools(paths).then((tools) => {
86
+ if (tools.length > 0) {
87
+ console.log(`[${APP_NAME}] Connected to MCP servers, discovered ${tools.length} tools`);
88
+ }
89
+ }).catch((error) => {
90
+ console.error(`[${APP_NAME}] Failed to auto-connect to MCP servers: ${summarizeMcpError(error)}`);
91
+ if (process.env.WAYPOI_DEBUG_ERRORS === "1") {
92
+ console.error(error);
93
+ }
94
+ });
95
+
96
+ // Print model capability source summary for operators.
97
+ try {
98
+ const models = await listModelsForApi(paths);
99
+ const configured = models.filter((model) => model.capabilities.source === "configured").length;
100
+ const inferred = models.filter((model) => model.capabilities.source === "inferred").length;
101
+ const enabledModels = models.filter((model) => model.enabled).length;
102
+ console.log(
103
+ `[${APP_NAME}] Models: total=${models.length}, enabled=${enabledModels}, configured=${configured}, inferred=${inferred}`
104
+ );
105
+ } catch (error) {
106
+ console.error(`[${APP_NAME}] Failed to summarize model capabilities: ${(error as Error).message}`);
107
+ if (process.env.WAYPOI_DEBUG_ERRORS === "1") {
108
+ console.error(error);
109
+ }
110
+ }
111
+
112
+ try {
113
+ const providers = await listProviders(paths);
114
+ const pools = await listPools(paths);
115
+ const enabledProviders = providers.filter((provider) => provider.enabled).length;
116
+ const byProtocol = providers.reduce<Record<string, number>>((acc, provider) => {
117
+ const protocol = provider.protocolRaw ?? provider.protocol;
118
+ acc[protocol] = (acc[protocol] ?? 0) + 1;
119
+ return acc;
120
+ }, {});
121
+ console.log(
122
+ `[${APP_NAME}] Providers: total=${providers.length}, enabled=${enabledProviders}, pools=${pools.length}`
123
+ );
124
+ console.log(`[${APP_NAME}] Provider protocols: ${JSON.stringify(byProtocol)}`);
125
+ } catch (error) {
126
+ console.error(`[${APP_NAME}] Failed to summarize providers: ${(error as Error).message}`);
127
+ if (process.env.WAYPOI_DEBUG_ERRORS === "1") {
128
+ console.error(error);
129
+ }
130
+ }
131
+
132
+ // Start config watcher for hot-reload
133
+ const configWatcher = startConfigWatcher(paths);
134
+ configWatcher.on("config:updated", async () => {
135
+ invalidateConfigCache();
136
+ // Reload auth config on config change
137
+ const authConfig = await loadAuthConfig(paths);
138
+ updateAuthConfig(authConfig);
139
+ console.log("[${APP_NAME}] Config reloaded - no restart needed");
140
+ });
141
+
142
+ // Graceful shutdown
143
+ let shuttingDown = false;
144
+ const shutdown = async (signal: string) => {
145
+ if (shuttingDown) {
146
+ console.log(`\n[${signal}] Forced exit.`);
147
+ process.exit(1);
148
+ }
149
+ shuttingDown = true;
150
+ console.log(`\n[${signal}] Shutting down gracefully...`);
151
+
152
+ // Force exit after 5 seconds if graceful shutdown stalls
153
+ const forceTimer = setTimeout(() => {
154
+ console.error("[shutdown] Timed out, forcing exit.");
155
+ process.exit(1);
156
+ }, 5_000);
157
+ forceTimer.unref();
158
+
159
+ stopConfigWatcher();
160
+ stopHealthChecker();
161
+ stopStatsRotation();
162
+ stopCaptureRetentionWorker();
163
+ await closeMcpServiceRoutes();
164
+ await disconnectAllServers();
165
+ await app.close();
166
+ clearTimeout(forceTimer);
167
+ process.exit(0);
168
+ };
169
+
170
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
171
+ process.on("SIGINT", () => shutdown("SIGINT"));
172
+
173
+ await app.listen({ port: PORT, host: "0.0.0.0" });
174
+
175
+ // Auto-connect to the built-in /mcp endpoint so playground tools are available by default
176
+ discoverBuiltinTools(paths, `http://localhost:${PORT}/mcp`).then((tools) => {
177
+ console.log(`[${APP_NAME}] Built-in MCP connected: ${tools.map((t) => t.name).join(", ") || "no tools"}`);
178
+ }).catch((error) => {
179
+ console.error(`[${APP_NAME}] Failed to connect to built-in MCP: ${summarizeMcpError(error)}`);
180
+ if (process.env.WAYPOI_DEBUG_ERRORS === "1") {
181
+ console.error(error);
182
+ }
183
+ });
184
+
185
+ console.log(`\n🚀 ${APP_NAME} running on http://localhost:${PORT}`);
186
+ console.log(` Endpoints: /v1/chat/completions, /v1/embeddings, /v1/images/*, /v1/videos/*, /v1/audio/*`);
187
+ console.log(` MCP Service: /mcp`);
188
+ console.log(` Admin: /admin/*, /admin/stats, /admin/sessions, /admin/mcp, /admin/benchmarks/runs`);
189
+ console.log(` UI: http://localhost:${PORT}/ui\n`);
190
+ }
191
+
192
+ start().catch((error) => {
193
+ console.error(error);
194
+ process.exit(1);
195
+ });