@hasna/testers 0.0.51 → 0.0.52
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 +1 -1
- package/dist/cli/index.js +210 -11
- package/dist/lib/workflow-fanout.d.ts +26 -0
- package/dist/lib/workflow-fanout.d.ts.map +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/server/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ testers workflow fanout --project alumia --workers 6 --url https://preview.examp
|
|
|
41
41
|
testers workflow fanout wf_abc,wf_def wf_xyz --workers 12 --url https://preview.example.com --json
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
`--workers` is bounded to 1-12 concurrent sandboxes. Use `--dry-run` to inspect the remote commands
|
|
44
|
+
`--workers` is bounded to 1-12 concurrent sandboxes. 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.
|
|
45
45
|
|
|
46
46
|
### Common Flags
|
|
47
47
|
|
package/dist/cli/index.js
CHANGED
|
@@ -60463,8 +60463,11 @@ var exports_workflow_fanout = {};
|
|
|
60463
60463
|
__export(exports_workflow_fanout, {
|
|
60464
60464
|
runWorkflowFanout: () => runWorkflowFanout,
|
|
60465
60465
|
resolveWorkflowFanoutSelection: () => resolveWorkflowFanoutSelection,
|
|
60466
|
-
normalizeFanoutWorkerCount: () => normalizeFanoutWorkerCount
|
|
60466
|
+
normalizeFanoutWorkerCount: () => normalizeFanoutWorkerCount,
|
|
60467
|
+
checkWorkflowFanoutReadiness: () => checkWorkflowFanoutReadiness
|
|
60467
60468
|
});
|
|
60469
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
60470
|
+
import { existsSync as existsSync19, statSync as statSync5 } from "fs";
|
|
60468
60471
|
function splitWorkflowIds(ids) {
|
|
60469
60472
|
return (ids ?? []).flatMap((item) => item.split(",")).map((item) => item.trim()).filter(Boolean);
|
|
60470
60473
|
}
|
|
@@ -60497,6 +60500,89 @@ function resolveWorkflowFanoutSelection(options) {
|
|
|
60497
60500
|
}
|
|
60498
60501
|
return filtered;
|
|
60499
60502
|
}
|
|
60503
|
+
async function checkWorkflowFanoutReadiness(workflows, dependencies = {}) {
|
|
60504
|
+
const checks = [];
|
|
60505
|
+
const env = dependencies.env ?? process.env;
|
|
60506
|
+
for (const [provider, providerWorkflows] of groupWorkflowsByProvider(workflows)) {
|
|
60507
|
+
const envKey = PROVIDER_ENV_KEYS[provider];
|
|
60508
|
+
if (!envKey) {
|
|
60509
|
+
checks.push({
|
|
60510
|
+
name: `provider:${provider}`,
|
|
60511
|
+
ok: true,
|
|
60512
|
+
required: false,
|
|
60513
|
+
message: `No built-in credential preflight for sandbox provider "${provider}"`,
|
|
60514
|
+
workflows: providerWorkflows.map((workflow) => workflow.name)
|
|
60515
|
+
});
|
|
60516
|
+
continue;
|
|
60517
|
+
}
|
|
60518
|
+
const apiKey = await resolveProviderApiKey(provider, env, dependencies.providerApiKeyResolver);
|
|
60519
|
+
checks.push({
|
|
60520
|
+
name: `provider:${provider}`,
|
|
60521
|
+
ok: Boolean(apiKey),
|
|
60522
|
+
required: true,
|
|
60523
|
+
message: apiKey ? `Sandbox provider "${provider}" credential is available` : `Missing sandbox provider credential for "${provider}". Set ${envKey} or configure providers.${provider}.api_key with sandboxes config`,
|
|
60524
|
+
workflows: providerWorkflows.map((workflow) => workflow.name),
|
|
60525
|
+
details: { provider, envKey }
|
|
60526
|
+
});
|
|
60527
|
+
}
|
|
60528
|
+
const needsRsync = workflows.filter((workflow) => (workflow.execution.sandboxSyncStrategy ?? "rsync") === "rsync" || Boolean(workflow.execution.appSourceDir));
|
|
60529
|
+
if (needsRsync.length > 0) {
|
|
60530
|
+
const commandExists = dependencies.commandExists ?? defaultCommandExists;
|
|
60531
|
+
const rsyncOk = commandExists("rsync");
|
|
60532
|
+
checks.push({
|
|
60533
|
+
name: "tool:rsync",
|
|
60534
|
+
ok: rsyncOk,
|
|
60535
|
+
required: true,
|
|
60536
|
+
message: rsyncOk ? "rsync is available for sandbox uploads and app source bundling" : "Missing rsync. Install rsync or use --sandbox-sync archive for workflows without app source bundling",
|
|
60537
|
+
workflows: needsRsync.map((workflow) => workflow.name)
|
|
60538
|
+
});
|
|
60539
|
+
}
|
|
60540
|
+
const missingAppSources = workflows.filter((workflow) => workflow.execution.appSourceDir).filter((workflow) => {
|
|
60541
|
+
const sourceDir = workflow.execution.appSourceDir;
|
|
60542
|
+
return !existsSync19(sourceDir) || !statSync5(sourceDir).isDirectory();
|
|
60543
|
+
});
|
|
60544
|
+
if (missingAppSources.length > 0) {
|
|
60545
|
+
checks.push({
|
|
60546
|
+
name: "app-source",
|
|
60547
|
+
ok: false,
|
|
60548
|
+
required: true,
|
|
60549
|
+
message: "One or more workflow app source directories are missing or are not directories",
|
|
60550
|
+
workflows: missingAppSources.map((workflow) => workflow.name),
|
|
60551
|
+
details: {
|
|
60552
|
+
sources: missingAppSources.map((workflow) => ({
|
|
60553
|
+
workflowId: workflow.id,
|
|
60554
|
+
workflowName: workflow.name,
|
|
60555
|
+
appSourceDir: workflow.execution.appSourceDir
|
|
60556
|
+
}))
|
|
60557
|
+
}
|
|
60558
|
+
});
|
|
60559
|
+
}
|
|
60560
|
+
const { requiredMissing, optionalMissing } = collectMissingSandboxEnvRefs(workflows, env, dependencies.credentialResolver);
|
|
60561
|
+
if (requiredMissing.length > 0) {
|
|
60562
|
+
checks.push({
|
|
60563
|
+
name: "env:required",
|
|
60564
|
+
ok: false,
|
|
60565
|
+
required: true,
|
|
60566
|
+
message: "One or more required sandbox environment references could not be resolved",
|
|
60567
|
+
workflows: [...new Set(requiredMissing.map((item) => item.workflowName))],
|
|
60568
|
+
details: { missing: requiredMissing }
|
|
60569
|
+
});
|
|
60570
|
+
}
|
|
60571
|
+
if (optionalMissing.length > 0) {
|
|
60572
|
+
checks.push({
|
|
60573
|
+
name: "env:optional",
|
|
60574
|
+
ok: false,
|
|
60575
|
+
required: false,
|
|
60576
|
+
message: "One or more optional sandbox environment references are not set and will be omitted",
|
|
60577
|
+
workflows: [...new Set(optionalMissing.map((item) => item.workflowName))],
|
|
60578
|
+
details: { missing: optionalMissing }
|
|
60579
|
+
});
|
|
60580
|
+
}
|
|
60581
|
+
return {
|
|
60582
|
+
ok: checks.every((check) => check.ok || !check.required),
|
|
60583
|
+
checks
|
|
60584
|
+
};
|
|
60585
|
+
}
|
|
60500
60586
|
async function mapWithConcurrency(items, limit, worker) {
|
|
60501
60587
|
const output = new Array(items.length);
|
|
60502
60588
|
let next = 0;
|
|
@@ -60512,7 +60598,38 @@ async function mapWithConcurrency(items, limit, worker) {
|
|
|
60512
60598
|
async function runWorkflowFanout(options, dependencies = {}) {
|
|
60513
60599
|
const workers = normalizeFanoutWorkerCount(options.workers);
|
|
60514
60600
|
const workflows = resolveWorkflowFanoutSelection(options);
|
|
60515
|
-
const {
|
|
60601
|
+
const {
|
|
60602
|
+
runTestingWorkflow: runOne = runTestingWorkflow,
|
|
60603
|
+
preflight: preflightOverride,
|
|
60604
|
+
providerApiKeyResolver,
|
|
60605
|
+
commandExists,
|
|
60606
|
+
credentialResolver,
|
|
60607
|
+
env,
|
|
60608
|
+
...workflowDependencies
|
|
60609
|
+
} = dependencies;
|
|
60610
|
+
const preflight = preflightOverride ? await preflightOverride(workflows) : await checkWorkflowFanoutReadiness(workflows, {
|
|
60611
|
+
providerApiKeyResolver,
|
|
60612
|
+
commandExists,
|
|
60613
|
+
credentialResolver,
|
|
60614
|
+
env
|
|
60615
|
+
});
|
|
60616
|
+
if (!options.dryRun && !preflight.ok) {
|
|
60617
|
+
const error = `Preflight failed: ${summarizePreflightFailures(preflight)}`;
|
|
60618
|
+
return {
|
|
60619
|
+
status: "failed",
|
|
60620
|
+
workers,
|
|
60621
|
+
total: workflows.length,
|
|
60622
|
+
passed: 0,
|
|
60623
|
+
failed: workflows.length,
|
|
60624
|
+
preflight,
|
|
60625
|
+
items: workflows.map((workflow) => ({
|
|
60626
|
+
workflowId: workflow.id,
|
|
60627
|
+
workflowName: workflow.name,
|
|
60628
|
+
status: "failed",
|
|
60629
|
+
error
|
|
60630
|
+
}))
|
|
60631
|
+
};
|
|
60632
|
+
}
|
|
60516
60633
|
const items = await mapWithConcurrency(workflows, workers, async (workflow) => {
|
|
60517
60634
|
try {
|
|
60518
60635
|
const output = await runOne(workflow.id, {
|
|
@@ -60559,12 +60676,81 @@ async function runWorkflowFanout(options, dependencies = {}) {
|
|
|
60559
60676
|
total: items.length,
|
|
60560
60677
|
passed,
|
|
60561
60678
|
failed,
|
|
60562
|
-
items
|
|
60679
|
+
items,
|
|
60680
|
+
preflight
|
|
60563
60681
|
};
|
|
60564
60682
|
}
|
|
60683
|
+
function groupWorkflowsByProvider(workflows) {
|
|
60684
|
+
const byProvider = new Map;
|
|
60685
|
+
for (const workflow of workflows) {
|
|
60686
|
+
const provider = workflow.execution.provider ?? "e2b";
|
|
60687
|
+
byProvider.set(provider, [...byProvider.get(provider) ?? [], workflow]);
|
|
60688
|
+
}
|
|
60689
|
+
return byProvider;
|
|
60690
|
+
}
|
|
60691
|
+
async function resolveProviderApiKey(provider, env, resolver) {
|
|
60692
|
+
if (resolver)
|
|
60693
|
+
return resolver(provider, env);
|
|
60694
|
+
const envKey = PROVIDER_ENV_KEYS[provider];
|
|
60695
|
+
if (envKey && env[envKey])
|
|
60696
|
+
return env[envKey];
|
|
60697
|
+
try {
|
|
60698
|
+
const mod = await import("@hasna/sandboxes");
|
|
60699
|
+
if (provider === "e2b" || provider === "daytona" || provider === "modal") {
|
|
60700
|
+
return mod.getProviderApiKey?.(provider);
|
|
60701
|
+
}
|
|
60702
|
+
} catch {}
|
|
60703
|
+
return;
|
|
60704
|
+
}
|
|
60705
|
+
function defaultCommandExists(command) {
|
|
60706
|
+
const result = spawnSync2(command, ["--version"], { encoding: "utf8" });
|
|
60707
|
+
return !result.error && result.status === 0;
|
|
60708
|
+
}
|
|
60709
|
+
function collectMissingSandboxEnvRefs(workflows, env, credentialResolver) {
|
|
60710
|
+
const requiredMissing = [];
|
|
60711
|
+
const optionalMissing = [];
|
|
60712
|
+
for (const workflow of workflows) {
|
|
60713
|
+
for (const [key, value] of Object.entries(workflow.execution.env ?? {})) {
|
|
60714
|
+
if (value.startsWith("$?")) {
|
|
60715
|
+
const name = value.slice(2).trim();
|
|
60716
|
+
if (name && env[name] === undefined) {
|
|
60717
|
+
optionalMissing.push({ workflowId: workflow.id, workflowName: workflow.name, key, reference: value });
|
|
60718
|
+
}
|
|
60719
|
+
continue;
|
|
60720
|
+
}
|
|
60721
|
+
if (!isResolvableEnvReference(value))
|
|
60722
|
+
continue;
|
|
60723
|
+
if (resolveSandboxEnvReference(value, env, credentialResolver) === null) {
|
|
60724
|
+
requiredMissing.push({ workflowId: workflow.id, workflowName: workflow.name, key, reference: value });
|
|
60725
|
+
}
|
|
60726
|
+
}
|
|
60727
|
+
}
|
|
60728
|
+
return { requiredMissing, optionalMissing };
|
|
60729
|
+
}
|
|
60730
|
+
function isResolvableEnvReference(value) {
|
|
60731
|
+
return value.startsWith("$") || value.startsWith("@secrets:");
|
|
60732
|
+
}
|
|
60733
|
+
function resolveSandboxEnvReference(value, env, credentialResolver) {
|
|
60734
|
+
if (value.startsWith("$")) {
|
|
60735
|
+
const varName = value.slice(1).trim();
|
|
60736
|
+
return varName ? env[varName] ?? null : null;
|
|
60737
|
+
}
|
|
60738
|
+
return (credentialResolver ?? resolveCredential)(value);
|
|
60739
|
+
}
|
|
60740
|
+
function summarizePreflightFailures(preflight) {
|
|
60741
|
+
const requiredFailures = preflight.checks.filter((check) => !check.ok && check.required);
|
|
60742
|
+
return requiredFailures.length > 0 ? requiredFailures.map((check) => check.message).join("; ") : "required checks did not pass";
|
|
60743
|
+
}
|
|
60744
|
+
var PROVIDER_ENV_KEYS;
|
|
60565
60745
|
var init_workflow_fanout = __esm(() => {
|
|
60566
60746
|
init_workflows();
|
|
60567
60747
|
init_workflow_runner();
|
|
60748
|
+
init_secrets_resolver();
|
|
60749
|
+
PROVIDER_ENV_KEYS = {
|
|
60750
|
+
e2b: "E2B_API_KEY",
|
|
60751
|
+
daytona: "DAYTONA_API_KEY",
|
|
60752
|
+
modal: "MODAL_TOKEN_ID"
|
|
60753
|
+
};
|
|
60568
60754
|
});
|
|
60569
60755
|
|
|
60570
60756
|
// node_modules/@ai-sdk/provider/dist/index.mjs
|
|
@@ -95224,7 +95410,7 @@ import chalk6 from "chalk";
|
|
|
95224
95410
|
// package.json
|
|
95225
95411
|
var package_default = {
|
|
95226
95412
|
name: "@hasna/testers",
|
|
95227
|
-
version: "0.0.
|
|
95413
|
+
version: "0.0.52",
|
|
95228
95414
|
description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
|
|
95229
95415
|
type: "module",
|
|
95230
95416
|
main: "dist/index.js",
|
|
@@ -97411,7 +97597,7 @@ init_ci();
|
|
|
97411
97597
|
init_assertions();
|
|
97412
97598
|
init_paths();
|
|
97413
97599
|
init_sessions();
|
|
97414
|
-
import { existsSync as
|
|
97600
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync15 } from "fs";
|
|
97415
97601
|
|
|
97416
97602
|
// src/lib/repo-discovery.ts
|
|
97417
97603
|
init_paths();
|
|
@@ -98440,7 +98626,7 @@ var CONFIG_DIR5 = getTestersDir();
|
|
|
98440
98626
|
var CONFIG_PATH4 = join21(CONFIG_DIR5, "config.json");
|
|
98441
98627
|
function getActiveProject() {
|
|
98442
98628
|
try {
|
|
98443
|
-
if (
|
|
98629
|
+
if (existsSync20(CONFIG_PATH4)) {
|
|
98444
98630
|
const raw = JSON.parse(readFileSync11(CONFIG_PATH4, "utf-8"));
|
|
98445
98631
|
return raw.activeProject ?? undefined;
|
|
98446
98632
|
}
|
|
@@ -99371,7 +99557,7 @@ program2.command("export [format]").description("Export scenarios as JSON (defau
|
|
|
99371
99557
|
return;
|
|
99372
99558
|
}
|
|
99373
99559
|
const outputDir = opts.output ?? ".";
|
|
99374
|
-
if (!
|
|
99560
|
+
if (!existsSync20(outputDir)) {
|
|
99375
99561
|
mkdirSync15(outputDir, { recursive: true });
|
|
99376
99562
|
}
|
|
99377
99563
|
for (const s2 of scenarios) {
|
|
@@ -99574,11 +99760,11 @@ projectCmd.command("export-open <id>").description("Register a testers project i
|
|
|
99574
99760
|
projectCmd.command("use <name>").description("Set active project (find or create)").option("--json", "Output as JSON", false).action((name21, opts) => {
|
|
99575
99761
|
try {
|
|
99576
99762
|
const project = ensureProject(name21, process.cwd());
|
|
99577
|
-
if (!
|
|
99763
|
+
if (!existsSync20(CONFIG_DIR5)) {
|
|
99578
99764
|
mkdirSync15(CONFIG_DIR5, { recursive: true });
|
|
99579
99765
|
}
|
|
99580
99766
|
let config2 = {};
|
|
99581
|
-
if (
|
|
99767
|
+
if (existsSync20(CONFIG_PATH4)) {
|
|
99582
99768
|
try {
|
|
99583
99769
|
config2 = JSON.parse(readFileSync11(CONFIG_PATH4, "utf-8"));
|
|
99584
99770
|
} catch {}
|
|
@@ -100193,7 +100379,7 @@ program2.command("ci [provider]").description("Print or write a CI workflow (def
|
|
|
100193
100379
|
if (opts.output) {
|
|
100194
100380
|
const outPath = resolve5(opts.output);
|
|
100195
100381
|
const outDir = outPath.replace(/\/[^/]*$/, "");
|
|
100196
|
-
if (outDir && !
|
|
100382
|
+
if (outDir && !existsSync20(outDir)) {
|
|
100197
100383
|
mkdirSync15(outDir, { recursive: true });
|
|
100198
100384
|
}
|
|
100199
100385
|
writeFileSync7(outPath, workflow, "utf-8");
|
|
@@ -100228,7 +100414,7 @@ program2.command("init").description("Initialize a new testing project").option(
|
|
|
100228
100414
|
}
|
|
100229
100415
|
if (opts.ci === "github") {
|
|
100230
100416
|
const workflowDir = join21(process.cwd(), ".github", "workflows");
|
|
100231
|
-
if (!
|
|
100417
|
+
if (!existsSync20(workflowDir)) {
|
|
100232
100418
|
mkdirSync15(workflowDir, { recursive: true });
|
|
100233
100419
|
}
|
|
100234
100420
|
const workflowPath = join21(workflowDir, "testers.yml");
|
|
@@ -102004,6 +102190,19 @@ workflowCmd.command("fanout [ids...]").description("Run multiple saved sandbox w
|
|
|
102004
102190
|
if (opts.json || opts.dryRun) {
|
|
102005
102191
|
log(JSON.stringify(result, null, 2));
|
|
102006
102192
|
} else {
|
|
102193
|
+
const preflightChecks = result.preflight?.checks ?? [];
|
|
102194
|
+
const failedRequiredChecks = preflightChecks.filter((check2) => !check2.ok && check2.required);
|
|
102195
|
+
const warnings = preflightChecks.filter((check2) => !check2.ok && !check2.required);
|
|
102196
|
+
if (failedRequiredChecks.length > 0 || warnings.length > 0) {
|
|
102197
|
+
const label = failedRequiredChecks.length > 0 ? chalk6.red("failed") : chalk6.yellow("warnings");
|
|
102198
|
+
log(chalk6.bold(`Preflight ${label}:`));
|
|
102199
|
+
for (const check2 of failedRequiredChecks) {
|
|
102200
|
+
log(` ${chalk6.red("failed")} ${check2.message}`);
|
|
102201
|
+
}
|
|
102202
|
+
for (const check2 of warnings) {
|
|
102203
|
+
log(` ${chalk6.yellow("warning")} ${check2.message}`);
|
|
102204
|
+
}
|
|
102205
|
+
}
|
|
102007
102206
|
const status = result.status === "passed" ? chalk6.green("passed") : chalk6.red("failed");
|
|
102008
102207
|
log(chalk6.bold(`Sandbox workflow fanout ${status}: ${result.passed}/${result.total} passed with ${result.workers} worker(s)`));
|
|
102009
102208
|
for (const item of result.items) {
|
|
@@ -26,11 +26,37 @@ export interface WorkflowFanoutResult {
|
|
|
26
26
|
passed: number;
|
|
27
27
|
failed: number;
|
|
28
28
|
items: WorkflowFanoutItem[];
|
|
29
|
+
preflight?: WorkflowFanoutPreflightResult;
|
|
29
30
|
}
|
|
30
31
|
export interface WorkflowFanoutDependencies extends WorkflowRunnerDependencies {
|
|
31
32
|
runTestingWorkflow?: typeof runTestingWorkflow;
|
|
33
|
+
preflight?: (workflows: TestingWorkflow[]) => WorkflowFanoutPreflightResult | Promise<WorkflowFanoutPreflightResult>;
|
|
34
|
+
providerApiKeyResolver?: (provider: string, env: Record<string, string | undefined>) => string | undefined | Promise<string | undefined>;
|
|
35
|
+
commandExists?: (command: string) => boolean;
|
|
36
|
+
credentialResolver?: (value: string) => string | null;
|
|
37
|
+
env?: Record<string, string | undefined>;
|
|
38
|
+
}
|
|
39
|
+
export interface WorkflowFanoutPreflightCheck {
|
|
40
|
+
name: string;
|
|
41
|
+
ok: boolean;
|
|
42
|
+
required: boolean;
|
|
43
|
+
message: string;
|
|
44
|
+
workflows?: string[];
|
|
45
|
+
details?: Record<string, unknown>;
|
|
46
|
+
}
|
|
47
|
+
export interface WorkflowFanoutPreflightResult {
|
|
48
|
+
ok: boolean;
|
|
49
|
+
checks: WorkflowFanoutPreflightCheck[];
|
|
50
|
+
}
|
|
51
|
+
interface WorkflowFanoutPreflightDependencies {
|
|
52
|
+
providerApiKeyResolver?: WorkflowFanoutDependencies["providerApiKeyResolver"];
|
|
53
|
+
commandExists?: WorkflowFanoutDependencies["commandExists"];
|
|
54
|
+
credentialResolver?: WorkflowFanoutDependencies["credentialResolver"];
|
|
55
|
+
env?: Record<string, string | undefined>;
|
|
32
56
|
}
|
|
33
57
|
export declare function normalizeFanoutWorkerCount(value: number | undefined): number;
|
|
34
58
|
export declare function resolveWorkflowFanoutSelection(options: Pick<WorkflowFanoutOptions, "workflowIds" | "projectId" | "tags" | "includeDisabled">): TestingWorkflow[];
|
|
59
|
+
export declare function checkWorkflowFanoutReadiness(workflows: TestingWorkflow[], dependencies?: WorkflowFanoutPreflightDependencies): Promise<WorkflowFanoutPreflightResult>;
|
|
35
60
|
export declare function runWorkflowFanout(options: WorkflowFanoutOptions, dependencies?: WorkflowFanoutDependencies): Promise<WorkflowFanoutResult>;
|
|
61
|
+
export {};
|
|
36
62
|
//# 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":"
|
|
1
|
+
{"version":3,"file":"workflow-fanout.d.ts","sourceRoot":"","sources":["../../src/lib/workflow-fanout.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.
|
|
55
|
+
version: "0.0.52",
|
|
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",
|
package/dist/server/index.js
CHANGED
|
@@ -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.
|
|
47093
|
+
version: "0.0.52",
|
|
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",
|