@tangle-network/browser-agent-driver 0.23.0 → 0.24.1
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 +357 -126
- package/dist/brain/index.d.ts +6 -0
- package/dist/brain/index.d.ts.map +1 -1
- package/dist/brain/index.js +43 -12
- package/dist/brain/index.js.map +1 -1
- package/dist/memory/knowledge.d.ts +6 -0
- package/dist/memory/knowledge.d.ts.map +1 -1
- package/dist/memory/knowledge.js +15 -0
- package/dist/memory/knowledge.js.map +1 -1
- package/dist/run-state.d.ts +4 -0
- package/dist/run-state.d.ts.map +1 -1
- package/dist/run-state.js +2 -0
- package/dist/run-state.js.map +1 -1
- package/dist/runner/goal-decomposer.d.ts +38 -0
- package/dist/runner/goal-decomposer.d.ts.map +1 -0
- package/dist/runner/goal-decomposer.js +125 -0
- package/dist/runner/goal-decomposer.js.map +1 -0
- package/dist/runner/parallel-runner.d.ts +61 -0
- package/dist/runner/parallel-runner.d.ts.map +1 -0
- package/dist/runner/parallel-runner.js +133 -0
- package/dist/runner/parallel-runner.js.map +1 -0
- package/dist/runner/pattern-extractor.d.ts +40 -0
- package/dist/runner/pattern-extractor.d.ts.map +1 -0
- package/dist/runner/pattern-extractor.js +122 -0
- package/dist/runner/pattern-extractor.js.map +1 -0
- package/dist/runner/runner.d.ts.map +1 -1
- package/dist/runner/runner.js +109 -6
- package/dist/runner/runner.js.map +1 -1
- package/dist/types.d.ts +32 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Goal Decomposer — detects compound goals and splits them into
|
|
3
|
+
* parallel-executable sub-goals.
|
|
4
|
+
*
|
|
5
|
+
* Gen 21: the intelligence layer for parallel tab exploration.
|
|
6
|
+
* One cheap LLM call classifies the goal and splits if needed.
|
|
7
|
+
* Conservative by default — only splits when the pattern is clear.
|
|
8
|
+
*/
|
|
9
|
+
import { generateText } from 'ai';
|
|
10
|
+
import { resolveProviderApiKey, resolveProviderModelName, } from '../provider-defaults.js';
|
|
11
|
+
// Fast regex pre-filter — skip the LLM call entirely for obviously simple goals
|
|
12
|
+
const SIMPLE_PATTERNS = [
|
|
13
|
+
/^(?:find|search|look up|open|navigate|go to|check|tell me)\b[^,]*$/i,
|
|
14
|
+
/^what (?:is|are)\b/i,
|
|
15
|
+
/^how (?:do|can|to)\b/i,
|
|
16
|
+
];
|
|
17
|
+
const COMPOUND_SIGNALS = [
|
|
18
|
+
/\bcompare\b/i,
|
|
19
|
+
/\bvs\.?\b|\bversus\b/i,
|
|
20
|
+
/\band (?:also|then|additionally)\b/i,
|
|
21
|
+
/\bfind (?:the )?\d+\b/i,
|
|
22
|
+
/\blist (?:the )?\d+\b/i,
|
|
23
|
+
/\btop \d+\b/i,
|
|
24
|
+
/\b\d+ (?:different|separate|distinct)\b/i,
|
|
25
|
+
/\bboth\b.*\band\b/i,
|
|
26
|
+
];
|
|
27
|
+
const DECOMPOSE_PROMPT = `You decide whether a web browsing goal should be split into parallel sub-tasks.
|
|
28
|
+
|
|
29
|
+
RULES:
|
|
30
|
+
- "compare X vs Y" → split into sub-tasks, one per item to compare
|
|
31
|
+
- "find N items matching criteria" → KEEP AS ONE task (the agent searches once and collects)
|
|
32
|
+
- "do X and also do Y" on different sites → split
|
|
33
|
+
- "do X and also do Y" on the same site → keep as one (sequential is fine)
|
|
34
|
+
- Simple extraction, navigation, or single-site tasks → always "simple"
|
|
35
|
+
- When in doubt, return "simple" — false splits waste resources
|
|
36
|
+
|
|
37
|
+
Respond with ONLY a JSON object:
|
|
38
|
+
{
|
|
39
|
+
"type": "simple" | "compound",
|
|
40
|
+
"reasoning": "one sentence why",
|
|
41
|
+
"subGoals": [
|
|
42
|
+
{"goal": "sub-goal description", "startUrl": "https://..." or null, "budgetFraction": 0.5}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
subGoals is required only when type is "compound". budgetFractions must sum to 1.0.
|
|
47
|
+
Each sub-goal should be self-contained — the sub-agent won't see the other sub-goals.`;
|
|
48
|
+
/**
|
|
49
|
+
* Analyze a goal and decide whether to decompose it into parallel sub-goals.
|
|
50
|
+
*
|
|
51
|
+
* Uses a fast regex pre-filter to skip the LLM call for obviously simple goals.
|
|
52
|
+
* Only calls the LLM when compound signals are detected.
|
|
53
|
+
*/
|
|
54
|
+
export async function decomposeGoal(goal, startUrl, options) {
|
|
55
|
+
// Fast path: obviously simple goals skip the LLM call
|
|
56
|
+
if (SIMPLE_PATTERNS.some(p => p.test(goal)) && !COMPOUND_SIGNALS.some(p => p.test(goal))) {
|
|
57
|
+
return { type: 'simple', originalGoal: goal, reasoning: 'simple pattern match' };
|
|
58
|
+
}
|
|
59
|
+
// No compound signals → simple
|
|
60
|
+
if (!COMPOUND_SIGNALS.some(p => p.test(goal))) {
|
|
61
|
+
return { type: 'simple', originalGoal: goal, reasoning: 'no compound signals' };
|
|
62
|
+
}
|
|
63
|
+
// LLM classification for ambiguous cases
|
|
64
|
+
try {
|
|
65
|
+
const provider = options.provider;
|
|
66
|
+
const modelName = options.model || 'gpt-4.1-mini';
|
|
67
|
+
const apiKey = options.apiKey || resolveProviderApiKey(provider);
|
|
68
|
+
const resolvedModel = resolveProviderModelName(provider, modelName);
|
|
69
|
+
// Dynamic import to avoid circular deps
|
|
70
|
+
const providerMod = provider === 'anthropic'
|
|
71
|
+
? await import('@ai-sdk/anthropic')
|
|
72
|
+
: provider === 'google'
|
|
73
|
+
? await import('@ai-sdk/google')
|
|
74
|
+
: await import('@ai-sdk/openai');
|
|
75
|
+
const createModel = 'createOpenAI' in providerMod
|
|
76
|
+
? providerMod.createOpenAI
|
|
77
|
+
: 'createAnthropic' in providerMod
|
|
78
|
+
? providerMod.createAnthropic
|
|
79
|
+
: providerMod.createGoogleGenerativeAI;
|
|
80
|
+
const client = createModel({
|
|
81
|
+
apiKey,
|
|
82
|
+
...(options.baseUrl ? { baseURL: options.baseUrl } : {}),
|
|
83
|
+
});
|
|
84
|
+
const model = client.languageModel(resolvedModel);
|
|
85
|
+
const result = await generateText({
|
|
86
|
+
model,
|
|
87
|
+
system: DECOMPOSE_PROMPT,
|
|
88
|
+
messages: [
|
|
89
|
+
{ role: 'user', content: `GOAL: ${goal}\nSTART URL: ${startUrl}` },
|
|
90
|
+
],
|
|
91
|
+
maxOutputTokens: 300,
|
|
92
|
+
});
|
|
93
|
+
const raw = result.text.trim();
|
|
94
|
+
const parsed = JSON.parse(raw.replace(/^```json\s*/, '').replace(/\s*```$/, ''));
|
|
95
|
+
if (parsed.type === 'compound' && Array.isArray(parsed.subGoals) && parsed.subGoals.length >= 2) {
|
|
96
|
+
const subGoals = parsed.subGoals.map((sg) => ({
|
|
97
|
+
goal: String(sg.goal || ''),
|
|
98
|
+
startUrl: sg.startUrl || startUrl,
|
|
99
|
+
budgetFraction: Number(sg.budgetFraction) || (1 / parsed.subGoals.length),
|
|
100
|
+
}));
|
|
101
|
+
// Normalize budget fractions to sum to 1.0
|
|
102
|
+
const totalBudget = subGoals.reduce((s, sg) => s + sg.budgetFraction, 0);
|
|
103
|
+
if (totalBudget > 0) {
|
|
104
|
+
for (const sg of subGoals)
|
|
105
|
+
sg.budgetFraction /= totalBudget;
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
type: 'compound',
|
|
109
|
+
originalGoal: goal,
|
|
110
|
+
subGoals,
|
|
111
|
+
reasoning: parsed.reasoning || 'LLM classified as compound',
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
type: 'simple',
|
|
116
|
+
originalGoal: goal,
|
|
117
|
+
reasoning: parsed.reasoning || 'LLM classified as simple',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// LLM call failed — fall back to simple (safe default)
|
|
122
|
+
return { type: 'simple', originalGoal: goal, reasoning: 'decomposer error, defaulting to simple' };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=goal-decomposer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goal-decomposer.js","sourceRoot":"","sources":["../../src/runner/goal-decomposer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parallel Runner — executes compound goals across multiple browser tabs.
|
|
3
|
+
*
|
|
4
|
+
* Gen 21: takes decomposed sub-goals from GoalDecomposer, creates one
|
|
5
|
+
* BrowserAgent per sub-goal in separate Pages (shared BrowserContext),
|
|
6
|
+
* runs them concurrently, and merges results via EvidenceMerger.
|
|
7
|
+
*
|
|
8
|
+
* Uses the same PlaywrightDriver + BrowserAgent stack as single-page runs.
|
|
9
|
+
* The parallel execution layer is thin — the intelligence is in the
|
|
10
|
+
* GoalDecomposer (split) and EvidenceMerger (combine).
|
|
11
|
+
*/
|
|
12
|
+
import type { BrowserContext } from 'playwright';
|
|
13
|
+
import type { PlaywrightDriverOptions } from '../drivers/playwright.js';
|
|
14
|
+
import type { Scenario, AgentConfig, AgentResult, Turn } from '../types.js';
|
|
15
|
+
import type { SubGoal } from './goal-decomposer.js';
|
|
16
|
+
import type { ProjectStore } from '../memory/project-store.js';
|
|
17
|
+
export interface ParallelRunOptions {
|
|
18
|
+
/** Browser context to create new pages in */
|
|
19
|
+
context: BrowserContext;
|
|
20
|
+
/** Agent config (shared across sub-agents) */
|
|
21
|
+
config: AgentConfig;
|
|
22
|
+
/** The original compound goal */
|
|
23
|
+
originalGoal: string;
|
|
24
|
+
/** Decomposed sub-goals */
|
|
25
|
+
subGoals: SubGoal[];
|
|
26
|
+
/** Original scenario (for timeout, memory, etc.) */
|
|
27
|
+
scenario: Scenario;
|
|
28
|
+
/** Per-turn callback with sub-agent label */
|
|
29
|
+
onTurn?: (label: string, turn: Turn) => void;
|
|
30
|
+
/** Driver options */
|
|
31
|
+
driverOptions?: PlaywrightDriverOptions;
|
|
32
|
+
/** Project store for memory */
|
|
33
|
+
projectStore?: ProjectStore;
|
|
34
|
+
/** Total timeout in ms (default: 600000) */
|
|
35
|
+
timeoutMs?: number;
|
|
36
|
+
/** Total token budget (will be split across sub-agents) */
|
|
37
|
+
totalTokenBudget?: number;
|
|
38
|
+
}
|
|
39
|
+
export interface ParallelRunResult {
|
|
40
|
+
/** Merged final result text */
|
|
41
|
+
mergedResult: string;
|
|
42
|
+
/** Whether the overall goal was achieved */
|
|
43
|
+
success: boolean;
|
|
44
|
+
/** Per-sub-agent results */
|
|
45
|
+
subResults: Array<{
|
|
46
|
+
subGoal: SubGoal;
|
|
47
|
+
result: AgentResult;
|
|
48
|
+
}>;
|
|
49
|
+
/** Total tokens across all sub-agents */
|
|
50
|
+
totalTokens: number;
|
|
51
|
+
/** Total wall time */
|
|
52
|
+
totalMs: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Run sub-goals in parallel across separate browser tabs.
|
|
56
|
+
*
|
|
57
|
+
* Creates one Page + PlaywrightDriver + BrowserAgent per sub-goal,
|
|
58
|
+
* runs them concurrently with per-agent timeouts, and collects results.
|
|
59
|
+
*/
|
|
60
|
+
export declare function runParallel(options: ParallelRunOptions): Promise<ParallelRunResult>;
|
|
61
|
+
//# sourceMappingURL=parallel-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parallel-runner.d.ts","sourceRoot":"","sources":["../../src/runner/parallel-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAEvE,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAE9D,MAAM,WAAW,kBAAkB;IACjC,6CAA6C;IAC7C,OAAO,EAAE,cAAc,CAAA;IACvB,8CAA8C;IAC9C,MAAM,EAAE,WAAW,CAAA;IACnB,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAA;IACpB,2BAA2B;IAC3B,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,oDAAoD;IACpD,QAAQ,EAAE,QAAQ,CAAA;IAClB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;IAC5C,qBAAqB;IACrB,aAAa,CAAC,EAAE,uBAAuB,CAAA;IACvC,+BAA+B;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAA;IACpB,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAA;IAChB,4BAA4B;IAC5B,UAAU,EAAE,KAAK,CAAC;QAChB,OAAO,EAAE,OAAO,CAAA;QAChB,MAAM,EAAE,WAAW,CAAA;KACpB,CAAC,CAAA;IACF,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAA;IACnB,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA8FzF"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parallel Runner — executes compound goals across multiple browser tabs.
|
|
3
|
+
*
|
|
4
|
+
* Gen 21: takes decomposed sub-goals from GoalDecomposer, creates one
|
|
5
|
+
* BrowserAgent per sub-goal in separate Pages (shared BrowserContext),
|
|
6
|
+
* runs them concurrently, and merges results via EvidenceMerger.
|
|
7
|
+
*
|
|
8
|
+
* Uses the same PlaywrightDriver + BrowserAgent stack as single-page runs.
|
|
9
|
+
* The parallel execution layer is thin — the intelligence is in the
|
|
10
|
+
* GoalDecomposer (split) and EvidenceMerger (combine).
|
|
11
|
+
*/
|
|
12
|
+
import { PlaywrightDriver } from '../drivers/playwright.js';
|
|
13
|
+
import { BrowserAgent } from './runner.js';
|
|
14
|
+
/**
|
|
15
|
+
* Run sub-goals in parallel across separate browser tabs.
|
|
16
|
+
*
|
|
17
|
+
* Creates one Page + PlaywrightDriver + BrowserAgent per sub-goal,
|
|
18
|
+
* runs them concurrently with per-agent timeouts, and collects results.
|
|
19
|
+
*/
|
|
20
|
+
export async function runParallel(options) {
|
|
21
|
+
const startTime = Date.now();
|
|
22
|
+
const { context, config, subGoals, scenario, onTurn } = options;
|
|
23
|
+
// Per-sub-agent timeout: split the total timeout proportionally
|
|
24
|
+
const totalTimeout = options.timeoutMs || 600_000;
|
|
25
|
+
const perAgentTimeout = Math.floor(totalTimeout * 0.85); // 85% of total, leave room for merge
|
|
26
|
+
// Create and run sub-agents in parallel
|
|
27
|
+
const subPromises = subGoals.map(async (subGoal, index) => {
|
|
28
|
+
const label = `sub-${index}`;
|
|
29
|
+
let page;
|
|
30
|
+
try {
|
|
31
|
+
page = await context.newPage();
|
|
32
|
+
const driver = new PlaywrightDriver(page, {
|
|
33
|
+
...options.driverOptions,
|
|
34
|
+
showCursor: false, // no cursor overlay on parallel tabs
|
|
35
|
+
});
|
|
36
|
+
// Set up resource blocking if configured
|
|
37
|
+
const blocking = config.resourceBlocking;
|
|
38
|
+
if (blocking) {
|
|
39
|
+
await driver.setupResourceBlocking(blocking);
|
|
40
|
+
}
|
|
41
|
+
const subConfig = {
|
|
42
|
+
...config,
|
|
43
|
+
// Scale token budget by sub-goal's budget fraction
|
|
44
|
+
tokenBudget: options.totalTokenBudget
|
|
45
|
+
? Math.floor(options.totalTokenBudget * subGoal.budgetFraction)
|
|
46
|
+
: undefined,
|
|
47
|
+
};
|
|
48
|
+
const agent = new BrowserAgent({
|
|
49
|
+
driver,
|
|
50
|
+
config: subConfig,
|
|
51
|
+
onTurn: onTurn ? (turn) => onTurn(label, turn) : undefined,
|
|
52
|
+
projectStore: options.projectStore,
|
|
53
|
+
// extensions passed through if available
|
|
54
|
+
});
|
|
55
|
+
const subScenario = {
|
|
56
|
+
...scenario,
|
|
57
|
+
goal: subGoal.goal,
|
|
58
|
+
startUrl: subGoal.startUrl || scenario.startUrl,
|
|
59
|
+
// Scale max turns by budget fraction
|
|
60
|
+
maxTurns: Math.max(10, Math.floor((scenario.maxTurns || 30) * subGoal.budgetFraction * 1.5)),
|
|
61
|
+
};
|
|
62
|
+
const result = await Promise.race([
|
|
63
|
+
agent.run(subScenario),
|
|
64
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`Sub-agent ${label} timed out`)), perAgentTimeout)),
|
|
65
|
+
]);
|
|
66
|
+
return { subGoal, result };
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
// Sub-agent failed — return a failure result
|
|
70
|
+
return {
|
|
71
|
+
subGoal,
|
|
72
|
+
result: {
|
|
73
|
+
success: false,
|
|
74
|
+
reason: `Sub-agent error: ${err instanceof Error ? err.message : String(err)}`,
|
|
75
|
+
turns: [],
|
|
76
|
+
totalMs: Date.now() - startTime,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
// Close the page but not the context (shared with other sub-agents)
|
|
82
|
+
if (page && !page.isClosed()) {
|
|
83
|
+
await page.close().catch(() => { });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
const subResults = await Promise.all(subPromises);
|
|
88
|
+
// Merge results
|
|
89
|
+
const mergedResult = mergeEvidence(options.originalGoal, subResults);
|
|
90
|
+
const totalTokens = subResults.reduce((sum, sr) => {
|
|
91
|
+
const tokens = sr.result.totalTokensUsed || 0;
|
|
92
|
+
return sum + tokens;
|
|
93
|
+
}, 0);
|
|
94
|
+
return {
|
|
95
|
+
mergedResult: mergedResult.text,
|
|
96
|
+
success: mergedResult.success,
|
|
97
|
+
subResults,
|
|
98
|
+
totalTokens,
|
|
99
|
+
totalMs: Date.now() - startTime,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Merge evidence from parallel sub-agents into one coherent answer.
|
|
104
|
+
*
|
|
105
|
+
* For now: deterministic merge (concatenate results with labels).
|
|
106
|
+
* Future: LLM-based synthesis for complex comparisons.
|
|
107
|
+
*/
|
|
108
|
+
function mergeEvidence(originalGoal, subResults) {
|
|
109
|
+
const successCount = subResults.filter(sr => sr.result.success).length;
|
|
110
|
+
const allSucceeded = successCount === subResults.length;
|
|
111
|
+
const anySucceeded = successCount > 0;
|
|
112
|
+
// Build merged result text
|
|
113
|
+
const parts = [`Goal: ${originalGoal}`, ''];
|
|
114
|
+
for (const { subGoal, result } of subResults) {
|
|
115
|
+
const status = result.success ? 'COMPLETED' : 'FAILED';
|
|
116
|
+
parts.push(`[${status}] ${subGoal.goal}:`);
|
|
117
|
+
if (result.reason) {
|
|
118
|
+
parts.push(result.reason);
|
|
119
|
+
}
|
|
120
|
+
parts.push('');
|
|
121
|
+
}
|
|
122
|
+
if (!anySucceeded) {
|
|
123
|
+
parts.push('None of the sub-goals could be completed.');
|
|
124
|
+
}
|
|
125
|
+
else if (!allSucceeded) {
|
|
126
|
+
parts.push(`${successCount}/${subResults.length} sub-goals completed.`);
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
text: parts.join('\n'),
|
|
130
|
+
success: anySucceeded, // succeed if at least one sub-goal worked
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=parallel-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parallel-runner.js","sourceRoot":"","sources":["../../src/runner/parallel-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern Extractor — learns reusable navigation patterns from completed runs.
|
|
3
|
+
*
|
|
4
|
+
* Gen 26b: after a successful run, mechanically extract domain-level patterns
|
|
5
|
+
* from the turn log and record them as AppKnowledge facts. No LLM call needed —
|
|
6
|
+
* patterns are detected by observing action/state sequences.
|
|
7
|
+
*
|
|
8
|
+
* Extracted patterns:
|
|
9
|
+
* - Cookie/consent banner dismissal (which action dismissed it, on which turn)
|
|
10
|
+
* - Page load timing (how long the site takes to settle)
|
|
11
|
+
* - Form structure (which refs are used for key form fields)
|
|
12
|
+
* - Navigation paths (effective URL patterns for search/results)
|
|
13
|
+
* - Blockers encountered (modals, auth walls, rate limits)
|
|
14
|
+
*
|
|
15
|
+
* Design constraints:
|
|
16
|
+
* - No bloat: only records patterns with clear signal (not every action)
|
|
17
|
+
* - Cleanable: all facts have confidence scores; low-confidence facts auto-prune
|
|
18
|
+
* - Workspace-isolated: patterns stored per-domain in the knowledge store
|
|
19
|
+
* - Smart: confirms patterns on repeat observation, decays on contradiction
|
|
20
|
+
*/
|
|
21
|
+
import type { Turn } from '../types.js';
|
|
22
|
+
import type { AppKnowledge, Fact } from '../memory/knowledge.js';
|
|
23
|
+
interface ExtractedPattern {
|
|
24
|
+
type: Fact['type'];
|
|
25
|
+
key: string;
|
|
26
|
+
value: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Extract reusable patterns from a completed run's turns.
|
|
30
|
+
* Only extracts from SUCCESSFUL runs — failed runs produce unreliable patterns.
|
|
31
|
+
*/
|
|
32
|
+
export declare function extractPatterns(turns: Turn[], domain: string, success: boolean): ExtractedPattern[];
|
|
33
|
+
/**
|
|
34
|
+
* Record extracted patterns into the knowledge store.
|
|
35
|
+
* Respects the existing confidence system — repeated patterns gain confidence,
|
|
36
|
+
* contradicted patterns decay.
|
|
37
|
+
*/
|
|
38
|
+
export declare function recordPatterns(knowledge: AppKnowledge, patterns: ExtractedPattern[]): void;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=pattern-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-extractor.d.ts","sourceRoot":"","sources":["../../src/runner/pattern-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAA;AAEhE,UAAU,gBAAgB;IACxB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IAClB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,IAAI,EAAE,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,GACf,gBAAgB,EAAE,CA6FpB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,YAAY,EACvB,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,IAAI,CAIN"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern Extractor — learns reusable navigation patterns from completed runs.
|
|
3
|
+
*
|
|
4
|
+
* Gen 26b: after a successful run, mechanically extract domain-level patterns
|
|
5
|
+
* from the turn log and record them as AppKnowledge facts. No LLM call needed —
|
|
6
|
+
* patterns are detected by observing action/state sequences.
|
|
7
|
+
*
|
|
8
|
+
* Extracted patterns:
|
|
9
|
+
* - Cookie/consent banner dismissal (which action dismissed it, on which turn)
|
|
10
|
+
* - Page load timing (how long the site takes to settle)
|
|
11
|
+
* - Form structure (which refs are used for key form fields)
|
|
12
|
+
* - Navigation paths (effective URL patterns for search/results)
|
|
13
|
+
* - Blockers encountered (modals, auth walls, rate limits)
|
|
14
|
+
*
|
|
15
|
+
* Design constraints:
|
|
16
|
+
* - No bloat: only records patterns with clear signal (not every action)
|
|
17
|
+
* - Cleanable: all facts have confidence scores; low-confidence facts auto-prune
|
|
18
|
+
* - Workspace-isolated: patterns stored per-domain in the knowledge store
|
|
19
|
+
* - Smart: confirms patterns on repeat observation, decays on contradiction
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Extract reusable patterns from a completed run's turns.
|
|
23
|
+
* Only extracts from SUCCESSFUL runs — failed runs produce unreliable patterns.
|
|
24
|
+
*/
|
|
25
|
+
export function extractPatterns(turns, domain, success) {
|
|
26
|
+
if (!success || turns.length < 2)
|
|
27
|
+
return [];
|
|
28
|
+
const patterns = [];
|
|
29
|
+
// 1. Cookie/consent banner dismissal
|
|
30
|
+
// Look for early turns where the agent clicked something that looks like
|
|
31
|
+
// cookie/consent/accept and then proceeded normally
|
|
32
|
+
for (let i = 0; i < Math.min(turns.length, 5); i++) {
|
|
33
|
+
const turn = turns[i];
|
|
34
|
+
const action = turn.action;
|
|
35
|
+
if (action.action === 'click' || action.action === 'clickAt' || action.action === 'clickLabel') {
|
|
36
|
+
const reasoning = turn.reasoning?.toLowerCase() || '';
|
|
37
|
+
const snapshot = turn.state?.snapshot?.toLowerCase() || '';
|
|
38
|
+
if (/cookie|consent|accept.*cookie|gdpr|privacy/i.test(reasoning + snapshot)) {
|
|
39
|
+
const selector = 'selector' in action ? action.selector : `clickAt(${action.x},${action.y})`;
|
|
40
|
+
patterns.push({
|
|
41
|
+
type: 'pattern',
|
|
42
|
+
key: 'cookie-dismiss',
|
|
43
|
+
value: `Turn ${i + 1}: ${action.action} ${selector}`,
|
|
44
|
+
});
|
|
45
|
+
break; // only record the first one
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// 2. Page load timing — how many turns before first meaningful action
|
|
50
|
+
const firstMeaningfulTurn = turns.findIndex(t => t.action.action !== 'wait' && t.action.action !== 'scroll' &&
|
|
51
|
+
!t.error && t.action.action !== 'navigate');
|
|
52
|
+
if (firstMeaningfulTurn >= 2) {
|
|
53
|
+
patterns.push({
|
|
54
|
+
type: 'timing',
|
|
55
|
+
key: 'first-meaningful-action',
|
|
56
|
+
value: `Turn ${firstMeaningfulTurn + 1} (${firstMeaningfulTurn} setup turns)`,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// 3. Effective search/navigation URL pattern
|
|
60
|
+
// If the agent used navigate with URL params, record the pattern
|
|
61
|
+
for (const turn of turns) {
|
|
62
|
+
if (turn.action.action === 'navigate' && turn.action.url) {
|
|
63
|
+
try {
|
|
64
|
+
const url = new URL(turn.action.url);
|
|
65
|
+
if (url.hostname.includes(domain) && url.search.length > 5) {
|
|
66
|
+
// Generalize: replace specific values with placeholders
|
|
67
|
+
const pattern = url.pathname + url.search
|
|
68
|
+
.replace(/=[^&]+/g, '={value}')
|
|
69
|
+
.slice(0, 100);
|
|
70
|
+
patterns.push({
|
|
71
|
+
type: 'pattern',
|
|
72
|
+
key: 'search-url',
|
|
73
|
+
value: pattern,
|
|
74
|
+
});
|
|
75
|
+
break; // only record the first effective search URL
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch { /* invalid URL, skip */ }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// 4. Turn efficiency — how many turns the task took
|
|
82
|
+
patterns.push({
|
|
83
|
+
type: 'timing',
|
|
84
|
+
key: 'typical-turns',
|
|
85
|
+
value: `${turns.length} turns`,
|
|
86
|
+
});
|
|
87
|
+
// 5. Form fields used — record which refs were used for form filling
|
|
88
|
+
const fillTurns = turns.filter(t => t.action.action === 'fill' || t.action.action === 'type');
|
|
89
|
+
if (fillTurns.length >= 2) {
|
|
90
|
+
const fields = fillTurns
|
|
91
|
+
.map(t => {
|
|
92
|
+
if (t.action.action === 'fill' && 'fields' in t.action && t.action.fields) {
|
|
93
|
+
return Object.keys(t.action.fields).join(',');
|
|
94
|
+
}
|
|
95
|
+
if (t.action.action === 'type' && 'selector' in t.action) {
|
|
96
|
+
return t.action.selector;
|
|
97
|
+
}
|
|
98
|
+
return '';
|
|
99
|
+
})
|
|
100
|
+
.filter(Boolean)
|
|
101
|
+
.slice(0, 5);
|
|
102
|
+
if (fields.length > 0) {
|
|
103
|
+
patterns.push({
|
|
104
|
+
type: 'selector',
|
|
105
|
+
key: 'form-fields',
|
|
106
|
+
value: fields.join(' → '),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return patterns;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Record extracted patterns into the knowledge store.
|
|
114
|
+
* Respects the existing confidence system — repeated patterns gain confidence,
|
|
115
|
+
* contradicted patterns decay.
|
|
116
|
+
*/
|
|
117
|
+
export function recordPatterns(knowledge, patterns) {
|
|
118
|
+
for (const p of patterns) {
|
|
119
|
+
knowledge.recordFact(p.type, p.key, p.value);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=pattern-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-extractor.js","sourceRoot":"","sources":["../../src/runner/pattern-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/runner/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAkC,MAAM,aAAa,CAAC;AAKvH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAuB/D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAa,MAAM,aAAa,CAAC;AAGtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAiDzF;AA4CD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC9B,wDAAwD;IACxD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACnG,wDAAwD;IACxD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sEAAsE;IACtE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,sDAAsD;IACtD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAgB3D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CA2BtF;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAC,CAAuB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAqF;IAC3G,OAAO,CAAC,mBAAmB,CAAC,CAAS;IACrC,OAAO,CAAC,YAAY,CAAC,CAAe;IACpC,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,SAAS,CAAC,CAAe;IACjC,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,eAAe,CAAwB;IAC/C,OAAO,CAAC,GAAG,CAAe;IAC1B,OAAO,CAAC,YAAY,CAAM;IAK1B,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,UAAU,CAAC,CAAqB;gBAE5B,OAAO,EAAE,mBAAmB;IAyBlC,GAAG,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/runner/runner.ts"],"names":[],"mappings":"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"}
|