@hasna/testers 0.0.57 → 0.0.59

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/README.md CHANGED
@@ -40,9 +40,10 @@ testers workflow create "Projects CRUD" \
40
40
  testers workflow fanout --project alumia --workers 6 --url https://preview.example.com
41
41
  testers workflow fanout wf_abc,wf_def wf_xyz --workers 12 --url https://preview.example.com --json
42
42
  testers workflow fanout --project alumia --tag action-specific --workers 6 --batch-size 12 --batch 1 --url https://preview.example.com
43
+ testers workflow fanout --project alumia --tag action-specific --workers 6 --batch-size 12 --all-batches --url https://preview.example.com
43
44
  ```
44
45
 
45
- `--workers` is bounded to 1-12 concurrent sandboxes. Use `--batch-size` with a 1-based `--batch` to run large workflow corpora in deterministic waves, or `--offset` for a manual selected-workflow cursor. Fanout preflights provider credentials, required sandbox environment references, `rsync`, and app source directories before launching workers. Use `--dry-run` to inspect the remote commands, upload plans, and preflight checks without spawning sandboxes.
46
+ `--workers` is bounded to 1-12 concurrent sandboxes. Use `--batch-size` with a 1-based `--batch` to run large workflow corpora in deterministic waves, or `--all-batches` with optional `--from-batch` / `--to-batch` to run a staged range in one command. `--offset` is available for a manual selected-workflow cursor. Fanout preflights provider credentials, required sandbox environment references, `rsync`, and app source directories before launching workers. Use `--dry-run` to inspect the remote commands, upload plans, and preflight checks without spawning sandboxes.
46
47
 
47
48
  ### Next.js Route and Action Inventory
48
49
 
@@ -64,7 +65,7 @@ testers inventory next /path/to/app \
64
65
  --sandbox-app-wait-url http://127.0.0.1:3000/health \
65
66
  --sandbox-env-optional OPENAI_API_KEY
66
67
 
67
- testers workflow fanout --project alumia --tag action-specific --workers 6 --batch-size 12 --batch 1 --url https://preview.example.com --dry-run
68
+ testers workflow fanout --project alumia --tag action-specific --workers 6 --batch-size 12 --all-batches --from-batch 1 --to-batch 3 --url https://preview.example.com --dry-run
68
69
  ```
69
70
 
70
71
  Use `--action-workflow-grouping action` for one workflow per discovered action, `route` for route-specific workflows, or `area-kind` for broader workflows such as commerce buttons or admin API methods. Add the `--sandbox-app-*` flags when the sandbox should rsync, install, start, and test the app source instead of only testing an already-running URL.
package/dist/cli/index.js CHANGED
@@ -27482,9 +27482,9 @@ async function runViaSandbox(plan, dependencies) {
27482
27482
  image: plan.sandbox.image,
27483
27483
  sandboxTimeout: plan.sandbox.timeoutMs,
27484
27484
  commandTimeoutMs: plan.sandbox.timeoutMs,
27485
- projectId: plan.workflow.projectId ?? undefined,
27486
27485
  config: {
27487
27486
  source: "testers",
27487
+ testersProjectId: plan.workflow.projectId ?? undefined,
27488
27488
  workflowId: plan.workflow.id,
27489
27489
  workflowName: plan.workflow.name
27490
27490
  },
@@ -60626,8 +60626,10 @@ var init_agents = __esm(() => {
60626
60626
  // src/lib/workflow-fanout.ts
60627
60627
  var exports_workflow_fanout = {};
60628
60628
  __export(exports_workflow_fanout, {
60629
+ runWorkflowFanoutBatches: () => runWorkflowFanoutBatches,
60629
60630
  runWorkflowFanout: () => runWorkflowFanout,
60630
60631
  resolveWorkflowFanoutSelection: () => resolveWorkflowFanoutSelection,
60632
+ resolveWorkflowFanoutBatchRange: () => resolveWorkflowFanoutBatchRange,
60631
60633
  resolveWorkflowFanoutBatch: () => resolveWorkflowFanoutBatch,
60632
60634
  normalizeFanoutWorkerCount: () => normalizeFanoutWorkerCount,
60633
60635
  checkWorkflowFanoutReadiness: () => checkWorkflowFanoutReadiness
@@ -60671,6 +60673,28 @@ function resolveWorkflowFanoutBatch(workflows, options = {}) {
60671
60673
  }
60672
60674
  };
60673
60675
  }
60676
+ function resolveWorkflowFanoutBatchRange(matched, options) {
60677
+ const batchSize = normalizeOptionalPositiveInteger(options.batchSize, "workflow fanout batch size");
60678
+ if (batchSize === undefined) {
60679
+ throw new Error("workflow fanout batch range requires batch size");
60680
+ }
60681
+ if (matched < 1) {
60682
+ throw new Error("workflow fanout batch range requires at least one matched workflow");
60683
+ }
60684
+ const totalBatches = Math.ceil(matched / batchSize);
60685
+ const batchStart = normalizeOptionalPositiveInteger(options.batchStart, "workflow fanout start batch") ?? 1;
60686
+ const batchEnd = normalizeOptionalPositiveInteger(options.batchEnd, "workflow fanout end batch") ?? totalBatches;
60687
+ if (batchStart > batchEnd) {
60688
+ throw new Error("workflow fanout start batch must be less than or equal to end batch");
60689
+ }
60690
+ if (batchStart > totalBatches) {
60691
+ throw new Error(`workflow fanout start batch ${batchStart} exceeds total batches ${totalBatches}`);
60692
+ }
60693
+ if (batchEnd > totalBatches) {
60694
+ throw new Error(`workflow fanout end batch ${batchEnd} exceeds total batches ${totalBatches}`);
60695
+ }
60696
+ return { batchSize, batchStart, batchEnd, totalBatches };
60697
+ }
60674
60698
  function resolveWorkflowFanoutSelection(options) {
60675
60699
  const ids = splitWorkflowIds(options.workflowIds);
60676
60700
  const workflows = ids.length > 0 ? ids.map((id) => {
@@ -60876,6 +60900,49 @@ async function runWorkflowFanout(options, dependencies = {}) {
60876
60900
  preflight
60877
60901
  };
60878
60902
  }
60903
+ async function runWorkflowFanoutBatches(options, dependencies = {}) {
60904
+ if (options.batch !== undefined || options.offset !== undefined) {
60905
+ throw new Error("workflow fanout all-batches cannot be combined with batch or offset");
60906
+ }
60907
+ const workers = normalizeFanoutWorkerCount(options.workers);
60908
+ const matchedWorkflows = resolveWorkflowFanoutSelection(options);
60909
+ const { batchSize, batchStart, batchEnd, totalBatches } = resolveWorkflowFanoutBatchRange(matchedWorkflows.length, options);
60910
+ const batches = [];
60911
+ let stoppedEarly = false;
60912
+ for (let batch = batchStart;batch <= batchEnd; batch++) {
60913
+ const result = await runWorkflowFanout({
60914
+ ...options,
60915
+ batchSize,
60916
+ batch,
60917
+ batchStart: undefined,
60918
+ batchEnd: undefined,
60919
+ offset: undefined
60920
+ }, dependencies);
60921
+ batches.push(result);
60922
+ if (result.status === "failed" && !options.continueOnFailure) {
60923
+ stoppedEarly = batch < batchEnd;
60924
+ break;
60925
+ }
60926
+ }
60927
+ const total = batches.reduce((sum, batch) => sum + batch.total, 0);
60928
+ const passed = batches.reduce((sum, batch) => sum + batch.passed, 0);
60929
+ const failed = batches.reduce((sum, batch) => sum + batch.failed, 0);
60930
+ const dryRun = options.dryRun === true;
60931
+ return {
60932
+ status: dryRun ? "dry-run" : failed > 0 || stoppedEarly ? "failed" : "passed",
60933
+ workers,
60934
+ matched: matchedWorkflows.length,
60935
+ batchSize,
60936
+ batchStart,
60937
+ batchEnd,
60938
+ totalBatches,
60939
+ stoppedEarly,
60940
+ total,
60941
+ passed,
60942
+ failed,
60943
+ batches
60944
+ };
60945
+ }
60879
60946
  function groupWorkflowsByProvider(workflows) {
60880
60947
  const byProvider = new Map;
60881
60948
  for (const workflow of workflows) {
@@ -95624,7 +95691,7 @@ import chalk6 from "chalk";
95624
95691
  // package.json
95625
95692
  var package_default = {
95626
95693
  name: "@hasna/testers",
95627
- version: "0.0.57",
95694
+ version: "0.0.59",
95628
95695
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
95629
95696
  type: "module",
95630
95697
  main: "dist/index.js",
@@ -102409,10 +102476,9 @@ workflowCmd.command("run <id>").description("Run a saved testing workflow").requ
102409
102476
  workflowCmd.command("fanout [ids...]").description("Run multiple saved sandbox workflows concurrently").requiredOption("-u, --url <url>", "Target URL").option("--project <id>", "Project ID").option("--tag <tag>", "Workflow scenario tag filter (repeatable)", (val, acc) => {
102410
102477
  acc.push(val);
102411
102478
  return acc;
102412
- }, []).option("--all", "Include disabled workflows when selecting by project/tag", false).option("--workers <n>", "Concurrent sandboxes, 1-12 (default: 6)", "6").option("--batch-size <n>", "Limit this run to a batch of selected workflows").option("--batch <n>", "1-based batch number to run with --batch-size").option("--offset <n>", "0-based selected-workflow offset for staged fanout").option("-m, --model <model>", "AI model").option("--headed", "Run headed", false).option("--parallel <n>", "Parallel browser workers inside each sandbox").option("--timeout <ms>", "Override workflow timeout").option("--dry-run", "Print resolved sandbox plans without spawning sandboxes", false).option("--json", "Output as JSON", false).action(async (ids, opts) => {
102479
+ }, []).option("--all", "Include disabled workflows when selecting by project/tag", false).option("--workers <n>", "Concurrent sandboxes, 1-12 (default: 6)", "6").option("--batch-size <n>", "Limit this run to a batch of selected workflows").option("--batch <n>", "1-based batch number to run with --batch-size").option("--offset <n>", "0-based selected-workflow offset for staged fanout").option("--all-batches", "Run all selected workflow batches sequentially with --batch-size", false).option("--from-batch <n>", "First batch to run when using --all-batches").option("--to-batch <n>", "Last batch to run when using --all-batches").option("--continue-on-failure", "Continue later batches after a failed batch", false).option("-m, --model <model>", "AI model").option("--headed", "Run headed", false).option("--parallel <n>", "Parallel browser workers inside each sandbox").option("--timeout <ms>", "Override workflow timeout").option("--dry-run", "Print resolved sandbox plans without spawning sandboxes", false).option("--json", "Output as JSON", false).action(async (ids, opts) => {
102413
102480
  try {
102414
- const { runWorkflowFanout: runWorkflowFanout2 } = await Promise.resolve().then(() => (init_workflow_fanout(), exports_workflow_fanout));
102415
- const result = await runWorkflowFanout2({
102481
+ const fanoutOptions = {
102416
102482
  workflowIds: ids,
102417
102483
  projectId: opts.project ? resolveProject2(opts.project) : undefined,
102418
102484
  tags: opts.tag,
@@ -102421,13 +102487,47 @@ workflowCmd.command("fanout [ids...]").description("Run multiple saved sandbox w
102421
102487
  batchSize: opts.batchSize ? parseInt(opts.batchSize, 10) : undefined,
102422
102488
  batch: opts.batch ? parseInt(opts.batch, 10) : undefined,
102423
102489
  offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
102490
+ batchStart: opts.fromBatch ? parseInt(opts.fromBatch, 10) : undefined,
102491
+ batchEnd: opts.toBatch ? parseInt(opts.toBatch, 10) : undefined,
102492
+ continueOnFailure: opts.continueOnFailure,
102424
102493
  url: opts.url,
102425
102494
  model: opts.model,
102426
102495
  headed: opts.headed,
102427
102496
  parallel: opts.parallel ? parseInt(opts.parallel, 10) : undefined,
102428
102497
  timeout: opts.timeout ? parseInt(opts.timeout, 10) : undefined,
102429
102498
  dryRun: opts.dryRun
102430
- });
102499
+ };
102500
+ const runAllBatches = opts.allBatches || opts.fromBatch !== undefined || opts.toBatch !== undefined;
102501
+ if (runAllBatches) {
102502
+ const { runWorkflowFanoutBatches: runWorkflowFanoutBatches2 } = await Promise.resolve().then(() => (init_workflow_fanout(), exports_workflow_fanout));
102503
+ const result2 = await runWorkflowFanoutBatches2(fanoutOptions);
102504
+ if (opts.json || opts.dryRun) {
102505
+ log(JSON.stringify(result2, null, 2));
102506
+ } else {
102507
+ const status = result2.status === "passed" ? chalk6.green("passed") : chalk6.red("failed");
102508
+ const stop = result2.stoppedEarly ? chalk6.yellow(" stopped early") : "";
102509
+ log(chalk6.bold(`Sandbox workflow fanout batches ${status}: ${result2.passed}/${result2.total} passed across ${result2.batches.length} batch(es)${stop}`));
102510
+ log(chalk6.dim(`Selected ${result2.matched} workflow(s), batch size ${result2.batchSize}, running batch ${result2.batchStart}-${result2.batchEnd}/${result2.totalBatches} with ${result2.workers} worker(s).`));
102511
+ for (const batch of result2.batches) {
102512
+ const batchStatus = batch.status === "passed" ? chalk6.green(batch.status) : batch.status === "dry-run" ? chalk6.yellow(batch.status) : chalk6.red(batch.status);
102513
+ const batchNumber = batch.selection.batch ?? "?";
102514
+ log(` ${batchStatus} batch ${batchNumber}/${batch.selection.totalBatches ?? result2.totalBatches}: ${batch.passed}/${batch.total} passed`);
102515
+ const failedItems = batch.items.filter((item) => item.status === "failed").slice(0, 5);
102516
+ for (const item of failedItems) {
102517
+ const error40 = item.error ? chalk6.dim(` ${item.error}`) : "";
102518
+ log(` ${chalk6.red("failed")} ${item.workflowName}${error40}`);
102519
+ }
102520
+ if (batch.items.filter((item) => item.status === "failed").length > failedItems.length) {
102521
+ log(chalk6.dim(` ... ${batch.items.filter((item) => item.status === "failed").length - failedItems.length} more failure(s)`));
102522
+ }
102523
+ }
102524
+ }
102525
+ if (result2.status === "failed")
102526
+ process.exit(1);
102527
+ return;
102528
+ }
102529
+ const { runWorkflowFanout: runWorkflowFanout2 } = await Promise.resolve().then(() => (init_workflow_fanout(), exports_workflow_fanout));
102530
+ const result = await runWorkflowFanout2(fanoutOptions);
102431
102531
  if (opts.json || opts.dryRun) {
102432
102532
  log(JSON.stringify(result, null, 2));
102433
102533
  } else {
package/dist/index.js CHANGED
@@ -17597,9 +17597,9 @@ async function runViaSandbox(plan, dependencies) {
17597
17597
  image: plan.sandbox.image,
17598
17598
  sandboxTimeout: plan.sandbox.timeoutMs,
17599
17599
  commandTimeoutMs: plan.sandbox.timeoutMs,
17600
- projectId: plan.workflow.projectId ?? undefined,
17601
17600
  config: {
17602
17601
  source: "testers",
17602
+ testersProjectId: plan.workflow.projectId ?? undefined,
17603
17603
  workflowId: plan.workflow.id,
17604
17604
  workflowName: plan.workflow.name
17605
17605
  },
@@ -9,6 +9,9 @@ export interface WorkflowFanoutOptions extends WorkflowRunOptions {
9
9
  batchSize?: number;
10
10
  batch?: number;
11
11
  offset?: number;
12
+ batchStart?: number;
13
+ batchEnd?: number;
14
+ continueOnFailure?: boolean;
12
15
  }
13
16
  export interface WorkflowFanoutItem {
14
17
  workflowId: string;
@@ -32,6 +35,20 @@ export interface WorkflowFanoutResult {
32
35
  items: WorkflowFanoutItem[];
33
36
  preflight?: WorkflowFanoutPreflightResult;
34
37
  }
38
+ export interface WorkflowFanoutBatchesResult {
39
+ status: "passed" | "failed" | "dry-run";
40
+ workers: number;
41
+ matched: number;
42
+ batchSize: number;
43
+ batchStart: number;
44
+ batchEnd: number;
45
+ totalBatches: number;
46
+ stoppedEarly: boolean;
47
+ total: number;
48
+ passed: number;
49
+ failed: number;
50
+ batches: WorkflowFanoutResult[];
51
+ }
35
52
  export interface WorkflowFanoutDependencies extends WorkflowRunnerDependencies {
36
53
  runTestingWorkflow?: typeof runTestingWorkflow;
37
54
  preflight?: (workflows: TestingWorkflow[]) => WorkflowFanoutPreflightResult | Promise<WorkflowFanoutPreflightResult>;
@@ -71,8 +88,15 @@ export declare function resolveWorkflowFanoutBatch(workflows: TestingWorkflow[],
71
88
  workflows: TestingWorkflow[];
72
89
  selection: WorkflowFanoutSelection;
73
90
  };
91
+ export declare function resolveWorkflowFanoutBatchRange(matched: number, options: Pick<WorkflowFanoutOptions, "batchSize" | "batchStart" | "batchEnd">): {
92
+ batchSize: number;
93
+ batchStart: number;
94
+ batchEnd: number;
95
+ totalBatches: number;
96
+ };
74
97
  export declare function resolveWorkflowFanoutSelection(options: Pick<WorkflowFanoutOptions, "workflowIds" | "projectId" | "tags" | "includeDisabled">): TestingWorkflow[];
75
98
  export declare function checkWorkflowFanoutReadiness(workflows: TestingWorkflow[], dependencies?: WorkflowFanoutPreflightDependencies): Promise<WorkflowFanoutPreflightResult>;
76
99
  export declare function runWorkflowFanout(options: WorkflowFanoutOptions, dependencies?: WorkflowFanoutDependencies): Promise<WorkflowFanoutResult>;
100
+ export declare function runWorkflowFanoutBatches(options: WorkflowFanoutOptions, dependencies?: WorkflowFanoutDependencies): Promise<WorkflowFanoutBatchesResult>;
77
101
  export {};
78
102
  //# sourceMappingURL=workflow-fanout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-fanout.d.ts","sourceRoot":"","sources":["../../src/lib/workflow-fanout.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workflow-fanout.d.ts","sourceRoot":"","sources":["../../src/lib/workflow-fanout.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEpH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB;IAC/D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,uBAAuB,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,6BAA6B,CAAC;CAC3C;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,oBAAoB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,0BAA2B,SAAQ,0BAA0B;IAC5E,kBAAkB,CAAC,EAAE,OAAO,kBAAkB,CAAC;IAC/C,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,eAAe,EAAE,KAAK,6BAA6B,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAAC;IACrH,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KAAK,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACzI,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7C,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,6BAA6B;IAC5C,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,4BAA4B,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,mCAAmC;IAC3C,sBAAsB,CAAC,EAAE,0BAA0B,CAAC,wBAAwB,CAAC,CAAC;IAC9E,aAAa,CAAC,EAAE,0BAA0B,CAAC,eAAe,CAAC,CAAC;IAC5D,kBAAkB,CAAC,EAAE,0BAA0B,CAAC,oBAAoB,CAAC,CAAC;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1C;AAeD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAM5E;AAED,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,eAAe,EAAE,EAC5B,OAAO,GAAE,IAAI,CAAC,qBAAqB,EAAE,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAM,GAC1E;IAAE,SAAS,EAAE,eAAe,EAAE,CAAC;IAAC,SAAS,EAAE,uBAAuB,CAAA;CAAE,CAgCtE;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,WAAW,GAAG,YAAY,GAAG,UAAU,CAAC,GAC5E;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAwBnF;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAE,aAAa,GAAG,WAAW,GAAG,MAAM,GAAG,iBAAiB,CAAC,GAAG,eAAe,EAAE,CA8BhK;AAED,wBAAsB,4BAA4B,CAChD,SAAS,EAAE,eAAe,EAAE,EAC5B,YAAY,GAAE,mCAAwC,GACrD,OAAO,CAAC,6BAA6B,CAAC,CAiGxC;AAuBD,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,qBAAqB,EAC9B,YAAY,GAAE,0BAA+B,GAC5C,OAAO,CAAC,oBAAoB,CAAC,CA+F/B;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,qBAAqB,EAC9B,YAAY,GAAE,0BAA+B,GAC5C,OAAO,CAAC,2BAA2B,CAAC,CA+CtC"}
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.57",
55
+ version: "0.0.59",
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",
@@ -23873,9 +23873,9 @@ async function runViaSandbox(plan, dependencies) {
23873
23873
  image: plan.sandbox.image,
23874
23874
  sandboxTimeout: plan.sandbox.timeoutMs,
23875
23875
  commandTimeoutMs: plan.sandbox.timeoutMs,
23876
- projectId: plan.workflow.projectId ?? undefined,
23877
23876
  config: {
23878
23877
  source: "testers",
23878
+ testersProjectId: plan.workflow.projectId ?? undefined,
23879
23879
  workflowId: plan.workflow.id,
23880
23880
  workflowName: plan.workflow.name
23881
23881
  },
@@ -47090,7 +47090,7 @@ import { join as join14 } from "path";
47090
47090
  // package.json
47091
47091
  var package_default = {
47092
47092
  name: "@hasna/testers",
47093
- version: "0.0.57",
47093
+ version: "0.0.59",
47094
47094
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
47095
47095
  type: "module",
47096
47096
  main: "dist/index.js",
@@ -51713,9 +51713,9 @@ async function runViaSandbox(plan, dependencies) {
51713
51713
  image: plan.sandbox.image,
51714
51714
  sandboxTimeout: plan.sandbox.timeoutMs,
51715
51715
  commandTimeoutMs: plan.sandbox.timeoutMs,
51716
- projectId: plan.workflow.projectId ?? undefined,
51717
51716
  config: {
51718
51717
  source: "testers",
51718
+ testersProjectId: plan.workflow.projectId ?? undefined,
51719
51719
  workflowId: plan.workflow.id,
51720
51720
  workflowName: plan.workflow.name
51721
51721
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/testers",
3
- "version": "0.0.57",
3
+ "version": "0.0.59",
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",