@hasna/testers 0.0.37 → 0.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -18137,6 +18137,7 @@ __export(exports_runner, {
18137
18137
  runByFilter: () => runByFilter,
18138
18138
  runBatch: () => runBatch,
18139
18139
  resolveScenariosForRun: () => resolveScenariosForRun,
18140
+ resolveAgentMaxTurns: () => resolveAgentMaxTurns,
18140
18141
  resolveAgentApiKeyForModel: () => resolveAgentApiKeyForModel,
18141
18142
  onRunEvent: () => onRunEvent,
18142
18143
  applyStructuredAssertionsToResult: () => applyStructuredAssertionsToResult
@@ -18154,6 +18155,14 @@ function emit(event) {
18154
18155
  function resolveAgentApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
18155
18156
  return resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey);
18156
18157
  }
18158
+ function resolveAgentMaxTurns(options) {
18159
+ if (options.maxTurns !== undefined) {
18160
+ const parsed = Math.floor(options.maxTurns);
18161
+ if (Number.isFinite(parsed) && parsed > 0)
18162
+ return parsed;
18163
+ }
18164
+ return options.minimal ? 10 : 30;
18165
+ }
18157
18166
  function assertionDescription(result) {
18158
18167
  return result.assertion.description || `${result.assertion.type}${result.assertion.selector ? ` ${result.assertion.selector}` : ""}`;
18159
18168
  }
@@ -18373,7 +18382,7 @@ async function runSingleScenario(scenario, runId, options) {
18373
18382
  runId,
18374
18383
  sessionId: result.id,
18375
18384
  baseUrl: options.url,
18376
- maxTurns: effectiveOptions.minimal ? 10 : 30,
18385
+ maxTurns: resolveAgentMaxTurns(effectiveOptions),
18377
18386
  a11y: effectiveOptions.a11y,
18378
18387
  persona: persona ? {
18379
18388
  name: persona.name,
@@ -93980,7 +93989,7 @@ import chalk6 from "chalk";
93980
93989
  // package.json
93981
93990
  var package_default = {
93982
93991
  name: "@hasna/testers",
93983
- version: "0.0.37",
93992
+ version: "0.0.38",
93984
93993
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
93985
93994
  type: "module",
93986
93995
  main: "dist/index.js",
@@ -94558,6 +94567,7 @@ function formatSmokeReport(result) {
94558
94567
 
94559
94568
  // src/lib/quick-qa.ts
94560
94569
  init_health_scan();
94570
+ var DEFAULT_QUICK_QA_OVERALL_TIMEOUT_MS = 120000;
94561
94571
  var DEFAULT_QUICK_QA_SCANNERS = [
94562
94572
  "console",
94563
94573
  "network",
@@ -94608,7 +94618,17 @@ function resolveQuickQaSelection(options = {}) {
94608
94618
  }
94609
94619
  async function runQuickQa(options) {
94610
94620
  const start = Date.now();
94611
- const health = await runHealthScan({
94621
+ const timeoutMs = options.overallTimeoutMs ?? DEFAULT_QUICK_QA_OVERALL_TIMEOUT_MS;
94622
+ return withQuickQaTimeout(runQuickQaUnbounded(options, start), {
94623
+ url: options.url,
94624
+ start,
94625
+ timeoutMs
94626
+ });
94627
+ }
94628
+ async function runQuickQaUnbounded(options, start) {
94629
+ const healthScanner = options.healthScanner ?? runHealthScan;
94630
+ const smokeRunner = options.smokeRunner ?? runSmoke;
94631
+ const health = await healthScanner({
94612
94632
  url: options.url,
94613
94633
  pages: options.pages,
94614
94634
  projectId: options.projectId,
@@ -94618,7 +94638,7 @@ async function runQuickQa(options) {
94618
94638
  maxPages: options.maxPages,
94619
94639
  wcagLevel: options.wcagLevel
94620
94640
  });
94621
- const smoke = options.includeSmoke === false ? null : await runSmoke({
94641
+ const smoke = options.includeSmoke === false ? null : await smokeRunner({
94622
94642
  url: options.url,
94623
94643
  model: options.model,
94624
94644
  headed: options.headed,
@@ -94632,6 +94652,62 @@ async function runQuickQa(options) {
94632
94652
  durationMs: Date.now() - start
94633
94653
  });
94634
94654
  }
94655
+ function withQuickQaTimeout(promise, options) {
94656
+ if (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0)
94657
+ return promise;
94658
+ return new Promise((resolve, reject) => {
94659
+ const timer = setTimeout(() => {
94660
+ resolve(buildQuickQaTimeoutResult({
94661
+ url: options.url,
94662
+ start: options.start,
94663
+ timeoutMs: options.timeoutMs
94664
+ }));
94665
+ }, options.timeoutMs);
94666
+ promise.then((result) => {
94667
+ clearTimeout(timer);
94668
+ resolve(result);
94669
+ }, (error) => {
94670
+ clearTimeout(timer);
94671
+ reject(error);
94672
+ });
94673
+ });
94674
+ }
94675
+ function buildQuickQaTimeoutResult(input) {
94676
+ const now2 = new Date;
94677
+ const durationMs = Math.max(0, Date.now() - input.start);
94678
+ const message = `Quick QA timed out after ${input.timeoutMs}ms before all checks finished. Increase --overall-timeout or skip slow checks.`;
94679
+ const health = {
94680
+ url: input.url,
94681
+ scannedAt: now2.toISOString(),
94682
+ durationMs,
94683
+ totalIssues: 1,
94684
+ newIssues: 1,
94685
+ regressedIssues: 0,
94686
+ existingIssues: 0,
94687
+ results: [{
94688
+ url: input.url,
94689
+ pages: [input.url],
94690
+ scannedAt: now2.toISOString(),
94691
+ durationMs,
94692
+ issues: [{
94693
+ type: "performance",
94694
+ severity: "high",
94695
+ pageUrl: input.url,
94696
+ message,
94697
+ detail: {
94698
+ check: "quick-qa",
94699
+ timeoutMs: input.timeoutMs
94700
+ }
94701
+ }]
94702
+ }]
94703
+ };
94704
+ return buildQuickQaResult({
94705
+ url: input.url,
94706
+ health,
94707
+ smoke: null,
94708
+ durationMs
94709
+ });
94710
+ }
94635
94711
  function buildQuickQaResult(input) {
94636
94712
  const healthActionable = input.health.newIssues + input.health.regressedIssues;
94637
94713
  const smokeIssues = input.smoke?.issuesFound.length ?? 0;
@@ -97476,7 +97552,7 @@ program2.command("remove <id>").alias("uninstall").description("Remove a scenari
97476
97552
  program2.command("run [url] [description]").alias("test").description("Run test scenarios against a URL").option("-t, --tag <tag>", "Filter by tag (repeatable)", (val, acc) => {
97477
97553
  acc.push(val);
97478
97554
  return acc;
97479
- }, []).option("-s, --scenario <id>", "Run specific scenario ID").option("-p, --priority <level>", "Filter by priority").option("--headed", "Run browser in headed mode", false).option("-m, --model <model>", "AI model to use").option("--parallel <n>", "Number of parallel browsers", "1").option("--json", "Output results as JSON", false).option("-o, --output <filepath>", "Write JSON results to file").option("--timeout <ms>", "Timeout in milliseconds").option("--from-todos", "Import scenarios from todos before running", false).option("--project <id>", "Project ID").option("-b, --background", "Start run in background and return immediately", false).option("--browser <engine>", "Browser engine: playwright (default), lightpanda (9x faster, no screenshots), or bun (native WKWebView, 11x faster, Bun canary required)", "playwright").option("--env <name>", "Use a named environment for the URL").option("--dry-run", "Print what would run without launching browser", false).option("--retry <n>", "Retry failed scenarios up to n times", "0").option("--samples <n>", "Run each scenario N times and report flakiness (pass rate)", "1").option("--flakiness-threshold <n>", "Pass rate threshold below which a scenario is marked flaky (0-1)", "0.95").option("--a11y [level]", "Run axe-core WCAG accessibility scan after each navigation (level: A, AA, AAA \u2014 default AA)").option("--self-heal", "Enable AI-powered selector repair when elements can't be found (requires judgeModel or ANTHROPIC_API_KEY)", false).option("--verbose", "Show per-step timing and full tool results", false).option("--watch-results", "When used with --background, poll and display live results table until run completes", false).option("--failed-only", "Only show failed/error scenarios in output (passed count shown as summary)", false).option("--smoke", "Run only smoke-tagged scenarios (fast validation suite, <2 min)", false).option("--minimal", "Fastest possible run: cheapest model, max parallelism, min turns (ideal for CI)", false).option("--github-comment", "Post pass/fail summary as a GitHub PR comment (requires GITHUB_TOKEN env var)", false).option("--pr <number>", "GitHub PR number (auto-detected from GITHUB_REF if not provided)").option("--persona <id>", "Override persona for this run (comma-separated IDs for divergence testing)").option("--max-cost <dollars>", "Hard budget cap in dollars \u2014 abort if estimated cost exceeds this (e.g. 0.50 for 50 cents)").option("--cache-max-age <seconds>", "Skip scenarios that passed at the same URL within this many seconds (0 = disabled)", "0").option("--diff", "Auto-detect changed files from git diff and run only relevant scenarios", false).option("--auto-generate", "If no scenarios exist, crawl the URL and generate scenarios automatically (enabled by default when a URL is given as the first arg)").option("--no-auto-generate", "Disable automatic scenario generation when no scenarios exist").option("--overall-timeout <ms>", "Hard overall timeout for the whole run in milliseconds (default 10 minutes)").option("-y, --yes", "Skip confirmation prompts (e.g. proceed past budget warnings)", false).action(async (urlArg, description, opts) => {
97555
+ }, []).option("-s, --scenario <id>", "Run specific scenario ID").option("-p, --priority <level>", "Filter by priority").option("--headed", "Run browser in headed mode", false).option("-m, --model <model>", "AI model to use").option("--parallel <n>", "Number of parallel browsers", "1").option("--json", "Output results as JSON", false).option("-o, --output <filepath>", "Write JSON results to file").option("--timeout <ms>", "Timeout in milliseconds").option("--from-todos", "Import scenarios from todos before running", false).option("--project <id>", "Project ID").option("-b, --background", "Start run in background and return immediately", false).option("--browser <engine>", "Browser engine: playwright (default), lightpanda (9x faster, no screenshots), or bun (native WKWebView, 11x faster, Bun canary required)", "playwright").option("--env <name>", "Use a named environment for the URL").option("--dry-run", "Print what would run without launching browser", false).option("--retry <n>", "Retry failed scenarios up to n times", "0").option("--samples <n>", "Run each scenario N times and report flakiness (pass rate)", "1").option("--flakiness-threshold <n>", "Pass rate threshold below which a scenario is marked flaky (0-1)", "0.95").option("--a11y [level]", "Run axe-core WCAG accessibility scan after each navigation (level: A, AA, AAA \u2014 default AA)").option("--self-heal", "Enable AI-powered selector repair when elements can't be found (requires judgeModel or ANTHROPIC_API_KEY)", false).option("--verbose", "Show per-step timing and full tool results", false).option("--watch-results", "When used with --background, poll and display live results table until run completes", false).option("--failed-only", "Only show failed/error scenarios in output (passed count shown as summary)", false).option("--smoke", "Run only smoke-tagged scenarios (fast validation suite, <2 min)", false).option("--minimal", "Fastest possible run: cheapest model, max parallelism, min turns (ideal for CI)", false).option("--max-turns <n>", "Maximum AI browser-agent turns before reporting an error").option("--github-comment", "Post pass/fail summary as a GitHub PR comment (requires GITHUB_TOKEN env var)", false).option("--pr <number>", "GitHub PR number (auto-detected from GITHUB_REF if not provided)").option("--persona <id>", "Override persona for this run (comma-separated IDs for divergence testing)").option("--max-cost <dollars>", "Hard budget cap in dollars \u2014 abort if estimated cost exceeds this (e.g. 0.50 for 50 cents)").option("--cache-max-age <seconds>", "Skip scenarios that passed at the same URL within this many seconds (0 = disabled)", "0").option("--diff", "Auto-detect changed files from git diff and run only relevant scenarios", false).option("--auto-generate", "If no scenarios exist, crawl the URL and generate scenarios automatically (enabled by default when a URL is given as the first arg)").option("--no-auto-generate", "Disable automatic scenario generation when no scenarios exist").option("--overall-timeout <ms>", "Hard overall timeout for the whole run in milliseconds (default 10 minutes)").option("-y, --yes", "Skip confirmation prompts (e.g. proceed past budget warnings)", false).action(async (urlArg, description, opts) => {
97480
97556
  try {
97481
97557
  const projectId = resolveProject2(opts.project);
97482
97558
  let url2 = urlArg;
@@ -97626,6 +97702,7 @@ program2.command("run [url] [description]").alias("test").description("Run test
97626
97702
  headed: opts.headed,
97627
97703
  parallel: parseInt(opts.parallel, 10),
97628
97704
  timeout: opts.timeout ? parseInt(opts.timeout, 10) : undefined,
97705
+ maxTurns: opts.maxTurns ? parseInt(opts.maxTurns, 10) : undefined,
97629
97706
  projectId,
97630
97707
  engine: opts.browser
97631
97708
  });
@@ -97744,6 +97821,7 @@ program2.command("run [url] [description]").alias("test").description("Run test
97744
97821
  headed: opts.headed,
97745
97822
  parallel: parseInt(opts.parallel, 10),
97746
97823
  timeout: opts.timeout ? parseInt(opts.timeout, 10) : undefined,
97824
+ maxTurns: opts.maxTurns ? parseInt(opts.maxTurns, 10) : undefined,
97747
97825
  retry: parseInt(opts.retry ?? "0", 10),
97748
97826
  projectId,
97749
97827
  engine: opts.browser,
@@ -97848,6 +97926,7 @@ program2.command("run [url] [description]").alias("test").description("Run test
97848
97926
  headed: opts.headed,
97849
97927
  parallel: parseInt(opts.parallel, 10),
97850
97928
  timeout: opts.timeout ? parseInt(opts.timeout, 10) : undefined,
97929
+ maxTurns: opts.maxTurns ? parseInt(opts.maxTurns, 10) : undefined,
97851
97930
  retry: parseInt(opts.retry ?? "0", 10),
97852
97931
  projectId,
97853
97932
  engine: opts.browser,
@@ -99145,7 +99224,7 @@ program2.command("quick-qa <url>").alias("quick-check").description("Run a fast
99145
99224
  }, []).option("--max-pages <n>", "Max pages to crawl for link checks", "20").option("--skip <check>", "Skip a check: console|network|links|perf|smoke|a11y (repeatable)", (v2, acc) => {
99146
99225
  acc.push(v2);
99147
99226
  return acc;
99148
- }, []).option("--a11y [level]", "Include WCAG accessibility scan at A, AA, or AAA (default AA)").option("--no-smoke", "Skip autonomous smoke exploration").option("-m, --model <model>", "AI model for autonomous smoke", "quick").option("--headed", "Run browser checks in headed mode", false).option("--timeout <ms>", "Navigation timeout per page in ms", "15000").option("--project <id>", "Project ID for issue tracking").option("--json", "Output results as JSON", false).option("-o, --output <file>", "Write JSON results to a file").action(async (url2, opts) => {
99227
+ }, []).option("--a11y [level]", "Include WCAG accessibility scan at A, AA, or AAA (default AA)").option("--no-smoke", "Skip autonomous smoke exploration").option("-m, --model <model>", "AI model for autonomous smoke", "quick").option("--headed", "Run browser checks in headed mode", false).option("--timeout <ms>", "Navigation timeout per page in ms", "15000").option("--overall-timeout <ms>", "Hard overall timeout for the quick QA run in milliseconds", String(DEFAULT_QUICK_QA_OVERALL_TIMEOUT_MS)).option("--project <id>", "Project ID for issue tracking").option("--json", "Output results as JSON", false).option("-o, --output <file>", "Write JSON results to a file").action(async (url2, opts) => {
99149
99228
  try {
99150
99229
  const projectId = resolveProject2(opts.project);
99151
99230
  const includeA11y = opts.a11y !== undefined;
@@ -99166,6 +99245,7 @@ program2.command("quick-qa <url>").alias("quick-check").description("Run a fast
99166
99245
  projectId,
99167
99246
  headed: opts.headed,
99168
99247
  timeoutMs: parseInt(opts.timeout, 10),
99248
+ overallTimeoutMs: parseInt(opts.overallTimeout, 10),
99169
99249
  maxPages: parseInt(opts.maxPages, 10),
99170
99250
  scanners: selection.scanners,
99171
99251
  includeSmoke: selection.includeSmoke,
package/dist/index.js CHANGED
@@ -16452,6 +16452,14 @@ function emit(event) {
16452
16452
  function resolveAgentApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
16453
16453
  return resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey);
16454
16454
  }
16455
+ function resolveAgentMaxTurns(options) {
16456
+ if (options.maxTurns !== undefined) {
16457
+ const parsed = Math.floor(options.maxTurns);
16458
+ if (Number.isFinite(parsed) && parsed > 0)
16459
+ return parsed;
16460
+ }
16461
+ return options.minimal ? 10 : 30;
16462
+ }
16455
16463
  function assertionDescription(result) {
16456
16464
  return result.assertion.description || `${result.assertion.type}${result.assertion.selector ? ` ${result.assertion.selector}` : ""}`;
16457
16465
  }
@@ -16671,7 +16679,7 @@ async function runSingleScenario(scenario, runId, options) {
16671
16679
  runId,
16672
16680
  sessionId: result.id,
16673
16681
  baseUrl: options.url,
16674
- maxTurns: effectiveOptions.minimal ? 10 : 30,
16682
+ maxTurns: resolveAgentMaxTurns(effectiveOptions),
16675
16683
  a11y: effectiveOptions.a11y,
16676
16684
  persona: persona ? {
16677
16685
  name: persona.name,
@@ -19135,6 +19143,7 @@ async function notifyHealthScan(url, counts) {
19135
19143
  }
19136
19144
 
19137
19145
  // src/lib/quick-qa.ts
19146
+ var DEFAULT_QUICK_QA_OVERALL_TIMEOUT_MS = 120000;
19138
19147
  var DEFAULT_QUICK_QA_SCANNERS = [
19139
19148
  "console",
19140
19149
  "network",
@@ -19185,7 +19194,17 @@ function resolveQuickQaSelection(options = {}) {
19185
19194
  }
19186
19195
  async function runQuickQa(options) {
19187
19196
  const start = Date.now();
19188
- const health = await runHealthScan({
19197
+ const timeoutMs = options.overallTimeoutMs ?? DEFAULT_QUICK_QA_OVERALL_TIMEOUT_MS;
19198
+ return withQuickQaTimeout(runQuickQaUnbounded(options, start), {
19199
+ url: options.url,
19200
+ start,
19201
+ timeoutMs
19202
+ });
19203
+ }
19204
+ async function runQuickQaUnbounded(options, start) {
19205
+ const healthScanner = options.healthScanner ?? runHealthScan;
19206
+ const smokeRunner = options.smokeRunner ?? runSmoke;
19207
+ const health = await healthScanner({
19189
19208
  url: options.url,
19190
19209
  pages: options.pages,
19191
19210
  projectId: options.projectId,
@@ -19195,7 +19214,7 @@ async function runQuickQa(options) {
19195
19214
  maxPages: options.maxPages,
19196
19215
  wcagLevel: options.wcagLevel
19197
19216
  });
19198
- const smoke = options.includeSmoke === false ? null : await runSmoke({
19217
+ const smoke = options.includeSmoke === false ? null : await smokeRunner({
19199
19218
  url: options.url,
19200
19219
  model: options.model,
19201
19220
  headed: options.headed,
@@ -19209,6 +19228,62 @@ async function runQuickQa(options) {
19209
19228
  durationMs: Date.now() - start
19210
19229
  });
19211
19230
  }
19231
+ function withQuickQaTimeout(promise, options) {
19232
+ if (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0)
19233
+ return promise;
19234
+ return new Promise((resolve, reject) => {
19235
+ const timer = setTimeout(() => {
19236
+ resolve(buildQuickQaTimeoutResult({
19237
+ url: options.url,
19238
+ start: options.start,
19239
+ timeoutMs: options.timeoutMs
19240
+ }));
19241
+ }, options.timeoutMs);
19242
+ promise.then((result) => {
19243
+ clearTimeout(timer);
19244
+ resolve(result);
19245
+ }, (error) => {
19246
+ clearTimeout(timer);
19247
+ reject(error);
19248
+ });
19249
+ });
19250
+ }
19251
+ function buildQuickQaTimeoutResult(input) {
19252
+ const now2 = new Date;
19253
+ const durationMs = Math.max(0, Date.now() - input.start);
19254
+ const message = `Quick QA timed out after ${input.timeoutMs}ms before all checks finished. Increase --overall-timeout or skip slow checks.`;
19255
+ const health = {
19256
+ url: input.url,
19257
+ scannedAt: now2.toISOString(),
19258
+ durationMs,
19259
+ totalIssues: 1,
19260
+ newIssues: 1,
19261
+ regressedIssues: 0,
19262
+ existingIssues: 0,
19263
+ results: [{
19264
+ url: input.url,
19265
+ pages: [input.url],
19266
+ scannedAt: now2.toISOString(),
19267
+ durationMs,
19268
+ issues: [{
19269
+ type: "performance",
19270
+ severity: "high",
19271
+ pageUrl: input.url,
19272
+ message,
19273
+ detail: {
19274
+ check: "quick-qa",
19275
+ timeoutMs: input.timeoutMs
19276
+ }
19277
+ }]
19278
+ }]
19279
+ };
19280
+ return buildQuickQaResult({
19281
+ url: input.url,
19282
+ health,
19283
+ smoke: null,
19284
+ durationMs
19285
+ });
19286
+ }
19212
19287
  function buildQuickQaResult(input) {
19213
19288
  const healthActionable = input.health.newIssues + input.health.regressedIssues;
19214
19289
  const smokeIssues = input.smoke?.issuesFound.length ?? 0;
@@ -1,8 +1,9 @@
1
- import { type HealthScanOptions, type HealthScanSummary } from "./health-scan.js";
2
- import { type SmokeResult } from "./smoke.js";
1
+ import { runHealthScan, type HealthScanOptions, type HealthScanSummary } from "./health-scan.js";
2
+ import { runSmoke, type SmokeResult } from "./smoke.js";
3
3
  export type QuickQaScanner = NonNullable<HealthScanOptions["scanners"]>[number];
4
4
  export type QuickQaSkipTarget = QuickQaScanner | "smoke";
5
5
  export type QuickQaStatus = "passed" | "warn" | "failed";
6
+ export declare const DEFAULT_QUICK_QA_OVERALL_TIMEOUT_MS = 120000;
6
7
  export declare const DEFAULT_QUICK_QA_SCANNERS: QuickQaScanner[];
7
8
  export interface QuickQaSelection {
8
9
  scanners: QuickQaScanner[];
@@ -15,11 +16,14 @@ export interface QuickQaOptions {
15
16
  projectId?: string;
16
17
  headed?: boolean;
17
18
  timeoutMs?: number;
19
+ overallTimeoutMs?: number;
18
20
  maxPages?: number;
19
21
  scanners?: QuickQaScanner[];
20
22
  includeSmoke?: boolean;
21
23
  model?: string;
22
24
  wcagLevel?: "A" | "AA" | "AAA";
25
+ healthScanner?: typeof runHealthScan;
26
+ smokeRunner?: typeof runSmoke;
23
27
  }
24
28
  export interface QuickQaCheckSummary {
25
29
  name: "health" | "smoke";
@@ -50,6 +54,11 @@ export declare function resolveQuickQaSelection(options?: {
50
54
  scanners?: QuickQaScanner[];
51
55
  }): QuickQaSelection;
52
56
  export declare function runQuickQa(options: QuickQaOptions): Promise<QuickQaResult>;
57
+ export declare function buildQuickQaTimeoutResult(input: {
58
+ url: string;
59
+ start: number;
60
+ timeoutMs: number;
61
+ }): QuickQaResult;
53
62
  export declare function buildQuickQaResult(input: {
54
63
  url: string;
55
64
  health: HealthScanSummary;
@@ -1 +1 @@
1
- {"version":3,"file":"quick-qa.d.ts","sourceRoot":"","sources":["../../src/lib/quick-qa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACjG,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAExD,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAChF,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,OAAO,CAAC;AACzD,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEzD,eAAO,MAAM,yBAAyB,EAAE,cAAc,EAKrD,CAAC;AAgBF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,GAAG,GAAG,IAAI,GAAG,KAAK,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,WAAW,EAAE;QACX,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,GAAG,GAAG,IAAI,GAAG,KAAK,CAK5E;AAED,wBAAgB,uBAAuB,CAAC,OAAO,GAAE;IAC/C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;CACxB,GAAG,gBAAgB,CAwBxB;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA6BhF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,aAAa,CA2DhB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAEhE;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CA8CjE"}
1
+ {"version":3,"file":"quick-qa.d.ts","sourceRoot":"","sources":["../../src/lib/quick-qa.ts"],"names":[],"mappings":"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"}
@@ -23,6 +23,7 @@ export interface RunOptions {
23
23
  skipBudgetCheck?: boolean;
24
24
  cacheMaxAgeMs?: number;
25
25
  minimal?: boolean;
26
+ maxTurns?: number;
26
27
  recordVideo?: boolean;
27
28
  }
28
29
  export interface RunEvent {
@@ -47,6 +48,7 @@ export interface RunEvent {
47
48
  export type RunEventHandler = (event: RunEvent) => void;
48
49
  export declare function onRunEvent(handler: RunEventHandler): void;
49
50
  export declare function resolveAgentApiKeyForModel(model: string, explicitApiKey?: string, configuredAnthropicApiKey?: string): string | undefined;
51
+ export declare function resolveAgentMaxTurns(options: Pick<RunOptions, "minimal" | "maxTurns">): number;
50
52
  type AgentScenarioStatus = Extract<ResultStatus, "passed" | "failed" | "error">;
51
53
  export interface StructuredAssertionOutcome {
52
54
  status: AgentScenarioStatus;
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lib/runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/lib/runner.ts"],"names":[],"mappings":"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"}
package/dist/mcp/index.js CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "@hasna/testers",
55
- version: "0.0.37",
55
+ version: "0.0.38",
56
56
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
57
57
  type: "module",
58
58
  main: "dist/index.js",
@@ -21180,6 +21180,7 @@ __export(exports_runner, {
21180
21180
  runByFilter: () => runByFilter,
21181
21181
  runBatch: () => runBatch,
21182
21182
  resolveScenariosForRun: () => resolveScenariosForRun,
21183
+ resolveAgentMaxTurns: () => resolveAgentMaxTurns,
21183
21184
  resolveAgentApiKeyForModel: () => resolveAgentApiKeyForModel,
21184
21185
  onRunEvent: () => onRunEvent,
21185
21186
  applyStructuredAssertionsToResult: () => applyStructuredAssertionsToResult
@@ -21197,6 +21198,14 @@ function emit(event) {
21197
21198
  function resolveAgentApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
21198
21199
  return resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey);
21199
21200
  }
21201
+ function resolveAgentMaxTurns(options) {
21202
+ if (options.maxTurns !== undefined) {
21203
+ const parsed = Math.floor(options.maxTurns);
21204
+ if (Number.isFinite(parsed) && parsed > 0)
21205
+ return parsed;
21206
+ }
21207
+ return options.minimal ? 10 : 30;
21208
+ }
21200
21209
  function assertionDescription(result) {
21201
21210
  return result.assertion.description || `${result.assertion.type}${result.assertion.selector ? ` ${result.assertion.selector}` : ""}`;
21202
21211
  }
@@ -21416,7 +21425,7 @@ async function runSingleScenario(scenario, runId, options) {
21416
21425
  runId,
21417
21426
  sessionId: result.id,
21418
21427
  baseUrl: options.url,
21419
- maxTurns: effectiveOptions.minimal ? 10 : 30,
21428
+ maxTurns: resolveAgentMaxTurns(effectiveOptions),
21420
21429
  a11y: effectiveOptions.a11y,
21421
21430
  persona: persona ? {
21422
21431
  name: persona.name,
@@ -46910,7 +46910,7 @@ import { join as join14 } from "path";
46910
46910
  // package.json
46911
46911
  var package_default = {
46912
46912
  name: "@hasna/testers",
46913
- version: "0.0.37",
46913
+ version: "0.0.38",
46914
46914
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
46915
46915
  type: "module",
46916
46916
  main: "dist/index.js",
@@ -49404,6 +49404,14 @@ function emit(event) {
49404
49404
  function resolveAgentApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey) {
49405
49405
  return resolveProviderApiKeyForModel(model, explicitApiKey, configuredAnthropicApiKey);
49406
49406
  }
49407
+ function resolveAgentMaxTurns(options) {
49408
+ if (options.maxTurns !== undefined) {
49409
+ const parsed = Math.floor(options.maxTurns);
49410
+ if (Number.isFinite(parsed) && parsed > 0)
49411
+ return parsed;
49412
+ }
49413
+ return options.minimal ? 10 : 30;
49414
+ }
49407
49415
  function assertionDescription(result) {
49408
49416
  return result.assertion.description || `${result.assertion.type}${result.assertion.selector ? ` ${result.assertion.selector}` : ""}`;
49409
49417
  }
@@ -49623,7 +49631,7 @@ async function runSingleScenario(scenario, runId, options) {
49623
49631
  runId,
49624
49632
  sessionId: result.id,
49625
49633
  baseUrl: options.url,
49626
- maxTurns: effectiveOptions.minimal ? 10 : 30,
49634
+ maxTurns: resolveAgentMaxTurns(effectiveOptions),
49627
49635
  a11y: effectiveOptions.a11y,
49628
49636
  persona: persona ? {
49629
49637
  name: persona.name,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/testers",
3
- "version": "0.0.37",
3
+ "version": "0.0.38",
4
4
  "description": "AI-powered QA testing CLI — spawns cheap AI agents to test web apps with headless browsers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",