usertester 0.1.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.
- package/LICENSE +21 -0
- package/README.md +219 -0
- package/dist/browser/agent.d.ts +33 -0
- package/dist/browser/agent.js +393 -0
- package/dist/browser/agent.js.map +1 -0
- package/dist/cli/cleanup.d.ts +5 -0
- package/dist/cli/cleanup.js +75 -0
- package/dist/cli/cleanup.js.map +1 -0
- package/dist/cli/harness.d.ts +10 -0
- package/dist/cli/harness.js +108 -0
- package/dist/cli/harness.js.map +1 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.js +31 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/kill.d.ts +5 -0
- package/dist/cli/kill.js +46 -0
- package/dist/cli/kill.js.map +1 -0
- package/dist/cli/logs.d.ts +5 -0
- package/dist/cli/logs.js +64 -0
- package/dist/cli/logs.js.map +1 -0
- package/dist/cli/profiles.d.ts +5 -0
- package/dist/cli/profiles.js +67 -0
- package/dist/cli/profiles.js.map +1 -0
- package/dist/cli/send.d.ts +5 -0
- package/dist/cli/send.js +46 -0
- package/dist/cli/send.js.map +1 -0
- package/dist/cli/setup.d.ts +6 -0
- package/dist/cli/setup.js +168 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli/spawn.d.ts +5 -0
- package/dist/cli/spawn.js +52 -0
- package/dist/cli/spawn.js.map +1 -0
- package/dist/cli/status.d.ts +5 -0
- package/dist/cli/status.js +85 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/harness/applier.d.ts +38 -0
- package/dist/harness/applier.js +152 -0
- package/dist/harness/applier.js.map +1 -0
- package/dist/harness/index.d.ts +14 -0
- package/dist/harness/index.js +110 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/harness/patterns.d.ts +14 -0
- package/dist/harness/patterns.js +96 -0
- package/dist/harness/patterns.js.map +1 -0
- package/dist/harness/proposer.d.ts +26 -0
- package/dist/harness/proposer.js +181 -0
- package/dist/harness/proposer.js.map +1 -0
- package/dist/harness/traces.d.ts +29 -0
- package/dist/harness/traces.js +65 -0
- package/dist/harness/traces.js.map +1 -0
- package/dist/harness/validator.d.ts +6 -0
- package/dist/harness/validator.js +112 -0
- package/dist/harness/validator.js.map +1 -0
- package/dist/inbox/agentmail.d.ts +11 -0
- package/dist/inbox/agentmail.js +36 -0
- package/dist/inbox/agentmail.js.map +1 -0
- package/dist/llm/provider.d.ts +15 -0
- package/dist/llm/provider.js +65 -0
- package/dist/llm/provider.js.map +1 -0
- package/dist/orchestrator/agent.d.ts +17 -0
- package/dist/orchestrator/agent.js +195 -0
- package/dist/orchestrator/agent.js.map +1 -0
- package/dist/orchestrator/index.d.ts +7 -0
- package/dist/orchestrator/index.js +92 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/retry.d.ts +27 -0
- package/dist/orchestrator/retry.js +145 -0
- package/dist/orchestrator/retry.js.map +1 -0
- package/dist/orchestrator/session.d.ts +13 -0
- package/dist/orchestrator/session.js +55 -0
- package/dist/orchestrator/session.js.map +1 -0
- package/dist/output/events.d.ts +12 -0
- package/dist/output/events.js +81 -0
- package/dist/output/events.js.map +1 -0
- package/dist/profiles/learner.d.ts +4 -0
- package/dist/profiles/learner.js +168 -0
- package/dist/profiles/learner.js.map +1 -0
- package/dist/tools/captcha.d.ts +19 -0
- package/dist/tools/captcha.js +76 -0
- package/dist/tools/captcha.js.map +1 -0
- package/dist/tools/inbox.d.ts +30 -0
- package/dist/tools/inbox.js +65 -0
- package/dist/tools/inbox.js.map +1 -0
- package/dist/types.d.ts +121 -0
- package/dist/types.js +30 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
- package/tasks.example.json +5 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* readInboxEmail tool — lets the browser agent read emails via AgentMail API
|
|
3
|
+
* instead of trying to navigate to a web inbox (which fails DNS).
|
|
4
|
+
*
|
|
5
|
+
* Used by the retry loop when it detects a CAPABILITY_GAP around email reading.
|
|
6
|
+
* Injected into Stagehand via stagehand.agent({ tools: { readInboxEmail } })
|
|
7
|
+
*/
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { AgentMailClient } from 'agentmail';
|
|
10
|
+
const inboxParams = z.object({
|
|
11
|
+
inboxId: z.string().describe('The full inbox email address, e.g. ut-abc123@agentmail.to'),
|
|
12
|
+
subjectContains: z.string().optional().describe('Optional: filter by subject keyword, e.g. "verification" or "code"'),
|
|
13
|
+
waitMinutes: z.number().optional().describe('How many minutes to wait for the email to arrive. Default: 2.'),
|
|
14
|
+
});
|
|
15
|
+
export const readInboxEmail = {
|
|
16
|
+
description: `Read emails from an AgentMail inbox using the API.
|
|
17
|
+
Use this when you need to retrieve a verification code, magic link, or any email sent to your inbox.
|
|
18
|
+
Do NOT try to navigate to a web-based email client — use this tool instead.
|
|
19
|
+
Returns the email subject, body snippet, and any 6-digit codes found.`,
|
|
20
|
+
inputSchema: inboxParams,
|
|
21
|
+
execute: async ({ inboxId, subjectContains, waitMinutes = 2 }) => {
|
|
22
|
+
const apiKey = process.env.AGENTMAIL_API_KEY;
|
|
23
|
+
if (!apiKey)
|
|
24
|
+
return { found: false, error: 'AGENTMAIL_API_KEY not set' };
|
|
25
|
+
const client = new AgentMailClient({ apiKey });
|
|
26
|
+
const deadline = Date.now() + waitMinutes * 60 * 1000;
|
|
27
|
+
while (Date.now() < deadline) {
|
|
28
|
+
try {
|
|
29
|
+
const threads = await client.inboxes.threads.list(inboxId);
|
|
30
|
+
// AgentMail API returns { count, threads: [...] }
|
|
31
|
+
const items = (threads.threads ?? threads.items ?? []);
|
|
32
|
+
for (const thread of items) {
|
|
33
|
+
if (subjectContains && !thread.subject?.toLowerCase().includes(subjectContains.toLowerCase())) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
// Fetch full thread to get message HTML (snippet is often undefined)
|
|
37
|
+
const detail = await client.inboxes.threads.get(inboxId, thread.threadId);
|
|
38
|
+
const msg = detail.messages?.[0];
|
|
39
|
+
const fullText = JSON.stringify(msg ?? '');
|
|
40
|
+
// Extract 6-digit verification codes — filter out obvious template placeholders
|
|
41
|
+
const allCodes = fullText.match(/\b\d{6}\b/g) ?? [];
|
|
42
|
+
// De-duplicate and filter repeated filler codes (e.g. 333333, 666666)
|
|
43
|
+
const codes = [...new Set(allCodes)].filter(c => !/^(\d)\1{5}$/.test(c));
|
|
44
|
+
return {
|
|
45
|
+
found: true,
|
|
46
|
+
subject: thread.subject,
|
|
47
|
+
snippet: (msg?.extractedHtml ?? msg?.html ?? '').slice(0, 200),
|
|
48
|
+
verificationCodes: codes,
|
|
49
|
+
primaryCode: codes[0] ?? null,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
return { found: false, error: String(err) };
|
|
55
|
+
}
|
|
56
|
+
// Wait 5 seconds before polling again
|
|
57
|
+
await new Promise(r => setTimeout(r, 5000));
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
found: false,
|
|
61
|
+
message: `No email found in ${inboxId} after ${waitMinutes} minutes`,
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=inbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../src/tools/inbox.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for usertester-agent
|
|
3
|
+
*/
|
|
4
|
+
export type AgentStatus = 'QUEUED' | 'SPAWNING' | 'INBOX_READY' | 'SIGNING_UP' | 'RUNNING' | 'WAITING' | 'DONE' | 'FAILED' | 'CANCELLED';
|
|
5
|
+
export interface AgentState {
|
|
6
|
+
id: string;
|
|
7
|
+
status: AgentStatus;
|
|
8
|
+
inboxId?: string;
|
|
9
|
+
currentMessage?: string;
|
|
10
|
+
startedAt?: number;
|
|
11
|
+
updatedAt: number;
|
|
12
|
+
error?: string;
|
|
13
|
+
lastScreenshot?: string;
|
|
14
|
+
retryCount: number;
|
|
15
|
+
}
|
|
16
|
+
export interface SessionState {
|
|
17
|
+
sessionId: string;
|
|
18
|
+
url: string;
|
|
19
|
+
agents: AgentState[];
|
|
20
|
+
startedAt: number;
|
|
21
|
+
completedAt?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface ActionRecord {
|
|
24
|
+
ts: number;
|
|
25
|
+
action: string;
|
|
26
|
+
selector?: string;
|
|
27
|
+
result: 'success' | 'failed' | 'skipped';
|
|
28
|
+
observation?: string;
|
|
29
|
+
url?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface RecoveryTip {
|
|
32
|
+
url: string;
|
|
33
|
+
scenario: string;
|
|
34
|
+
failedApproaches: string[];
|
|
35
|
+
successApproach: string;
|
|
36
|
+
toolsUsed: string[];
|
|
37
|
+
finalUrl: string;
|
|
38
|
+
confidence: number;
|
|
39
|
+
ts: number;
|
|
40
|
+
}
|
|
41
|
+
export interface SessionMemory {
|
|
42
|
+
taskDescription: string;
|
|
43
|
+
startUrl: string;
|
|
44
|
+
actions: ActionRecord[];
|
|
45
|
+
archivedActionCount: number;
|
|
46
|
+
recoveryTips: RecoveryTip[];
|
|
47
|
+
}
|
|
48
|
+
export interface HarnessHint {
|
|
49
|
+
observation: string;
|
|
50
|
+
confidence: number;
|
|
51
|
+
addedAt: number;
|
|
52
|
+
}
|
|
53
|
+
export interface ProfileFacts {
|
|
54
|
+
url: string;
|
|
55
|
+
scenario: string;
|
|
56
|
+
harnessHints: HarnessHint[];
|
|
57
|
+
runCount: number;
|
|
58
|
+
lastRunAt: number;
|
|
59
|
+
}
|
|
60
|
+
export type UsertesterEvent = {
|
|
61
|
+
event: 'session_start';
|
|
62
|
+
sessionId: string;
|
|
63
|
+
url: string;
|
|
64
|
+
n: number;
|
|
65
|
+
ts: string;
|
|
66
|
+
} | {
|
|
67
|
+
event: 'spawned';
|
|
68
|
+
agent: string;
|
|
69
|
+
inbox: string;
|
|
70
|
+
ts: string;
|
|
71
|
+
} | {
|
|
72
|
+
event: 'state';
|
|
73
|
+
agent: string;
|
|
74
|
+
from: AgentStatus;
|
|
75
|
+
to: AgentStatus;
|
|
76
|
+
message?: string;
|
|
77
|
+
ts: string;
|
|
78
|
+
} | {
|
|
79
|
+
event: 'ready';
|
|
80
|
+
agent: string;
|
|
81
|
+
message_completed: string;
|
|
82
|
+
summary: string;
|
|
83
|
+
screenshot?: string;
|
|
84
|
+
ts: string;
|
|
85
|
+
} | {
|
|
86
|
+
event: 'failed';
|
|
87
|
+
agent: string;
|
|
88
|
+
error: string;
|
|
89
|
+
ts: string;
|
|
90
|
+
} | {
|
|
91
|
+
event: 'session_complete';
|
|
92
|
+
sessionId: string;
|
|
93
|
+
ts: string;
|
|
94
|
+
};
|
|
95
|
+
export interface AgentCommand {
|
|
96
|
+
type: 'send' | 'kill';
|
|
97
|
+
message?: string;
|
|
98
|
+
issuedAt: number;
|
|
99
|
+
}
|
|
100
|
+
export interface UsertesterConfig {
|
|
101
|
+
agentmail_api_key?: string;
|
|
102
|
+
anthropic_api_key?: string;
|
|
103
|
+
openrouter_api_key?: string;
|
|
104
|
+
openai_api_key?: string;
|
|
105
|
+
/** Customer-specific secret for Cloudflare WAF bypass. Never hardcoded — read from env only. */
|
|
106
|
+
bypass_token?: string;
|
|
107
|
+
browserbase_api_key?: string;
|
|
108
|
+
browserbase_project_id?: string;
|
|
109
|
+
cua_backend: 'stagehand';
|
|
110
|
+
max_agents: number;
|
|
111
|
+
cua_concurrency_limit: number;
|
|
112
|
+
agent_timeout_ms: number;
|
|
113
|
+
screenshot_interval_ms: number;
|
|
114
|
+
results_dir: string;
|
|
115
|
+
rlm_recent_actions: number;
|
|
116
|
+
rlm_max_failed_actions: number;
|
|
117
|
+
orchestrator_model: string;
|
|
118
|
+
cua_model: string;
|
|
119
|
+
proposer_model: string;
|
|
120
|
+
}
|
|
121
|
+
export declare const DEFAULT_CONFIG: UsertesterConfig;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for usertester-agent
|
|
3
|
+
*/
|
|
4
|
+
export const DEFAULT_CONFIG = {
|
|
5
|
+
agentmail_api_key: process.env.AGENTMAIL_API_KEY,
|
|
6
|
+
anthropic_api_key: process.env.ANTHROPIC_API_KEY,
|
|
7
|
+
openrouter_api_key: process.env.OPENROUTER_API_KEY,
|
|
8
|
+
openai_api_key: process.env.OPENAI_API_KEY,
|
|
9
|
+
bypass_token: process.env.USERTESTER_BYPASS_TOKEN,
|
|
10
|
+
browserbase_api_key: process.env.BROWSERBASE_API_KEY,
|
|
11
|
+
browserbase_project_id: process.env.BROWSERBASE_PROJECT_ID,
|
|
12
|
+
cua_backend: 'stagehand',
|
|
13
|
+
max_agents: 20,
|
|
14
|
+
cua_concurrency_limit: 5,
|
|
15
|
+
agent_timeout_ms: 300_000,
|
|
16
|
+
screenshot_interval_ms: 2_000,
|
|
17
|
+
results_dir: `${process.env.HOME}/.usertester`,
|
|
18
|
+
rlm_recent_actions: 10,
|
|
19
|
+
rlm_max_failed_actions: 5,
|
|
20
|
+
orchestrator_model: process.env.OPENROUTER_API_KEY
|
|
21
|
+
? 'openrouter/openai/gpt-5.4-mini'
|
|
22
|
+
: 'anthropic/claude-haiku-4-5-20251001',
|
|
23
|
+
cua_model: process.env.OPENROUTER_API_KEY
|
|
24
|
+
? 'openrouter/anthropic/claude-opus-4-6'
|
|
25
|
+
: 'anthropic/claude-opus-4-6',
|
|
26
|
+
proposer_model: process.env.OPENROUTER_API_KEY
|
|
27
|
+
? 'openrouter/anthropic/claude-opus-4-6'
|
|
28
|
+
: 'anthropic/claude-opus-4-6',
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AA2HH,MAAM,CAAC,MAAM,cAAc,GAAqB;IAC9C,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;IAChD,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;IAChD,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;IAClD,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;IAC1C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB;IACjD,mBAAmB,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB;IACpD,sBAAsB,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB;IAC1D,WAAW,EAAE,WAAW;IACxB,UAAU,EAAE,EAAE;IACd,qBAAqB,EAAE,CAAC;IACxB,gBAAgB,EAAE,OAAO;IACzB,sBAAsB,EAAE,KAAK;IAC7B,WAAW,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,cAAc;IAC9C,kBAAkB,EAAE,EAAE;IACtB,sBAAsB,EAAE,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAChD,CAAC,CAAC,gCAAgC;QAClC,CAAC,CAAC,qCAAqC;IACzC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;QACvC,CAAC,CAAC,sCAAsC;QACxC,CAAC,CAAC,2BAA2B;IAC/B,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAC5C,CAAC,CAAC,sCAAsC;QACxC,CAAC,CAAC,2BAA2B;CAChC,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "usertester",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Spawn N AI agents as simulated users to test web app flows",
|
|
5
|
+
"author": "Vishal Tandale",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/vishaltandale00/usertester.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/vishaltandale00/usertester#readme",
|
|
12
|
+
"bugs": "https://github.com/vishaltandale00/usertester/issues",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"testing",
|
|
15
|
+
"ai-agents",
|
|
16
|
+
"browser-automation",
|
|
17
|
+
"user-testing",
|
|
18
|
+
"qa",
|
|
19
|
+
"stagehand",
|
|
20
|
+
"e2e-testing",
|
|
21
|
+
"web-testing"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"bin": {
|
|
25
|
+
"usertester": "./dist/cli/index.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist/",
|
|
29
|
+
"tasks.example.json",
|
|
30
|
+
"README.md",
|
|
31
|
+
"LICENSE"
|
|
32
|
+
],
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=20"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc && node -e \"require('fs').chmodSync('dist/cli/index.js',0o755)\" && echo 'bin ready: dist/cli/index.js'",
|
|
38
|
+
"dev": "tsx src/cli/index.ts",
|
|
39
|
+
"prepublishOnly": "npm run build",
|
|
40
|
+
"spike:stagehand": "tsx src/spikes/stagehand.ts",
|
|
41
|
+
"spike:agentmail": "tsx src/spikes/agentmail.ts",
|
|
42
|
+
"spike:rlm": "tsx src/spikes/rlm.ts"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@anthropic-ai/sdk": "^0.54.0",
|
|
46
|
+
"@browserbasehq/stagehand": "^3.0.0",
|
|
47
|
+
"@captcha-libs/capsolver": "^2.1.1",
|
|
48
|
+
"@openrouter/ai-sdk-provider": "^1.5.0",
|
|
49
|
+
"agentmail": "^0.1.0",
|
|
50
|
+
"commander": "^12.0.0",
|
|
51
|
+
"dotenv": "^16.0.0",
|
|
52
|
+
"jiti": "^2.0.0",
|
|
53
|
+
"zod": "^4.3.6"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/node": "^22.0.0",
|
|
57
|
+
"tsx": "^4.0.0",
|
|
58
|
+
"typescript": "^5.0.0"
|
|
59
|
+
}
|
|
60
|
+
}
|