@arclabs561/ai-visual-test 0.5.1 → 0.7.3

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 (74) hide show
  1. package/CHANGELOG.md +102 -11
  2. package/DEPLOYMENT.md +225 -9
  3. package/README.md +71 -80
  4. package/index.d.ts +862 -3
  5. package/package.json +10 -51
  6. package/src/batch-optimizer.mjs +39 -0
  7. package/src/cache.mjs +241 -16
  8. package/src/config.mjs +33 -91
  9. package/src/constants.mjs +54 -0
  10. package/src/convenience.mjs +113 -10
  11. package/src/cost-optimization.mjs +1 -0
  12. package/src/cost-tracker.mjs +134 -2
  13. package/src/data-extractor.mjs +36 -7
  14. package/src/dynamic-few-shot.mjs +69 -11
  15. package/src/errors.mjs +6 -2
  16. package/src/experience-propagation.mjs +12 -0
  17. package/src/experience-tracer.mjs +12 -3
  18. package/src/game-player.mjs +222 -43
  19. package/src/graceful-shutdown.mjs +126 -0
  20. package/src/helpers/playwright.mjs +22 -8
  21. package/src/human-validation-manager.mjs +99 -2
  22. package/src/index.mjs +48 -3
  23. package/src/integrations/playwright.mjs +140 -0
  24. package/src/judge.mjs +697 -24
  25. package/src/load-env.mjs +2 -1
  26. package/src/logger.mjs +31 -3
  27. package/src/model-tier-selector.mjs +1 -221
  28. package/src/natural-language-specs.mjs +31 -3
  29. package/src/persona-enhanced.mjs +4 -2
  30. package/src/persona-experience.mjs +1 -1
  31. package/src/pricing.mjs +28 -0
  32. package/src/prompt-composer.mjs +162 -5
  33. package/src/provider-data.mjs +115 -0
  34. package/src/render-change-detector.mjs +5 -0
  35. package/src/research-enhanced-validation.mjs +7 -5
  36. package/src/retry.mjs +21 -7
  37. package/src/rubrics.mjs +4 -0
  38. package/src/safe-logger.mjs +71 -0
  39. package/src/session-cost-tracker.mjs +320 -0
  40. package/src/smart-validator.mjs +8 -8
  41. package/src/spec-templates.mjs +52 -6
  42. package/src/startup-validation.mjs +127 -0
  43. package/src/temporal-adaptive.mjs +2 -2
  44. package/src/temporal-decision-manager.mjs +1 -271
  45. package/src/temporal-logic.mjs +104 -0
  46. package/src/temporal-note-pruner.mjs +119 -0
  47. package/src/temporal-preprocessor.mjs +1 -543
  48. package/src/temporal.mjs +681 -79
  49. package/src/utils/action-hallucination-detector.mjs +301 -0
  50. package/src/utils/baseline-validator.mjs +82 -0
  51. package/src/utils/cache-stats.mjs +104 -0
  52. package/src/utils/cached-llm.mjs +164 -0
  53. package/src/utils/capability-stratifier.mjs +108 -0
  54. package/src/utils/counterfactual-tester.mjs +83 -0
  55. package/src/utils/error-recovery.mjs +117 -0
  56. package/src/utils/explainability-scorer.mjs +119 -0
  57. package/src/utils/exploratory-automation.mjs +131 -0
  58. package/src/utils/index.mjs +10 -0
  59. package/src/utils/intent-recognizer.mjs +201 -0
  60. package/src/utils/log-sanitizer.mjs +165 -0
  61. package/src/utils/path-validator.mjs +88 -0
  62. package/src/utils/performance-logger.mjs +316 -0
  63. package/src/utils/performance-measurement.mjs +280 -0
  64. package/src/utils/prompt-sanitizer.mjs +213 -0
  65. package/src/utils/rate-limiter.mjs +144 -0
  66. package/src/validation-framework.mjs +24 -20
  67. package/src/validation-result-normalizer.mjs +27 -1
  68. package/src/validation.mjs +75 -25
  69. package/src/validators/accessibility-validator.mjs +144 -0
  70. package/src/validators/hybrid-validator.mjs +48 -4
  71. package/api/health.js +0 -34
  72. package/api/validate.js +0 -252
  73. package/public/index.html +0 -149
  74. package/vercel.json +0 -27
@@ -171,3 +171,122 @@ export function selectTopWeightedNotes(notes, options = {}) {
171
171
  .map(w => w.note);
172
172
  }
173
173
 
174
+ /**
175
+ * Select representative screenshots from sequence for context window management
176
+ *
177
+ * @param {Array<{path: string, timestamp: number, elapsed?: number}>} screenshots - Screenshot array
178
+ * @param {Array<Object>} evaluations - Corresponding evaluation results
179
+ * @param {Object} options - Selection options
180
+ * @param {number} [options.maxScreenshots=10] - Maximum screenshots to select
181
+ * @param {string} [options.strategy='diversity'] - 'diversity', 'keyframes', 'uniform'
182
+ * @returns {Array} Selected screenshots
183
+ */
184
+ export function selectRepresentativeScreenshots(screenshots, evaluations = [], options = {}) {
185
+ const {
186
+ maxScreenshots = 10,
187
+ strategy = 'diversity'
188
+ } = options;
189
+
190
+ if (screenshots.length <= maxScreenshots) {
191
+ return screenshots;
192
+ }
193
+
194
+ switch (strategy) {
195
+ case 'keyframes':
196
+ return selectKeyframes(screenshots, evaluations, maxScreenshots);
197
+ case 'uniform':
198
+ return selectUniform(screenshots, maxScreenshots);
199
+ case 'diversity':
200
+ default:
201
+ return selectByDiversity(screenshots, evaluations, maxScreenshots);
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Select keyframes (significant state changes)
207
+ */
208
+ function selectKeyframes(screenshots, evaluations, maxScreenshots) {
209
+ const keyframes = [screenshots[0]]; // Always include first
210
+
211
+ // Detect significant state changes
212
+ for (let i = 1; i < evaluations.length; i++) {
213
+ const prevScore = evaluations[i-1]?.score || 0;
214
+ const currScore = evaluations[i]?.score || 0;
215
+ const scoreChange = Math.abs(currScore - prevScore);
216
+
217
+ if (scoreChange > 2.0) { // Significant change threshold
218
+ keyframes.push(screenshots[i]);
219
+ }
220
+ }
221
+
222
+ keyframes.push(screenshots[screenshots.length - 1]); // Always include last
223
+
224
+ // If still too many, sample uniformly
225
+ if (keyframes.length > maxScreenshots) {
226
+ return sampleUniform(keyframes, maxScreenshots);
227
+ }
228
+
229
+ return keyframes;
230
+ }
231
+
232
+ /**
233
+ * Select by diversity (maximize visual difference)
234
+ */
235
+ function selectByDiversity(screenshots, evaluations, maxScreenshots) {
236
+ const selected = [screenshots[0]]; // Always include first
237
+ const remaining = screenshots.slice(1, -1);
238
+ const last = screenshots[screenshots.length - 1];
239
+
240
+ // Calculate score variance for diversity
241
+ const scores = evaluations.map(e => e.score || 0).filter(s => s !== null);
242
+ if (scores.length === 0) {
243
+ return selectUniform(screenshots, maxScreenshots);
244
+ }
245
+
246
+ const mean = scores.reduce((a, b) => a + b, 0) / scores.length;
247
+ const variance = scores.map(s => Math.abs(s - mean));
248
+
249
+ // Select indices with highest variance (most different states)
250
+ const indexed = variance.map((v, i) => ({ index: i, variance: v }));
251
+ indexed.sort((a, b) => b.variance - a.variance);
252
+
253
+ const diverseIndices = indexed.slice(0, maxScreenshots - 2).map(item => item.index);
254
+ selected.push(...diverseIndices.map(i => remaining[i]).filter(Boolean));
255
+ selected.push(last);
256
+
257
+ return selected.slice(0, maxScreenshots);
258
+ }
259
+
260
+ /**
261
+ * Select uniformly spaced screenshots
262
+ */
263
+ function selectUniform(screenshots, maxScreenshots) {
264
+ const step = Math.floor(screenshots.length / maxScreenshots);
265
+ const selected = [];
266
+
267
+ for (let i = 0; i < screenshots.length; i += step) {
268
+ selected.push(screenshots[i]);
269
+ if (selected.length >= maxScreenshots) break;
270
+ }
271
+
272
+ // Always include last
273
+ if (selected[selected.length - 1] !== screenshots[screenshots.length - 1]) {
274
+ selected[selected.length - 1] = screenshots[screenshots.length - 1];
275
+ }
276
+
277
+ return selected;
278
+ }
279
+
280
+ /**
281
+ * Sample uniformly from array
282
+ */
283
+ function sampleUniform(array, count) {
284
+ const step = Math.floor(array.length / count);
285
+ const sampled = [];
286
+ for (let i = 0; i < array.length; i += step) {
287
+ sampled.push(array[i]);
288
+ if (sampled.length >= count) break;
289
+ }
290
+ return sampled;
291
+ }
292
+