@hover-dev/core 0.15.0 → 0.17.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/README.md +26 -55
- package/dist/agentDirectives.d.ts +55 -0
- package/dist/agentDirectives.d.ts.map +1 -0
- package/dist/agentDirectives.js +276 -0
- package/dist/agents/claude.d.ts.map +1 -1
- package/dist/agents/claude.js +28 -3
- package/dist/agents/codex.d.ts.map +1 -1
- package/dist/agents/codex.js +38 -18
- package/dist/agents/gemini.d.ts.map +1 -1
- package/dist/agents/gemini.js +3 -14
- package/dist/agents/invoke.d.ts.map +1 -1
- package/dist/agents/invoke.js +3 -6
- package/dist/agents/qwen.d.ts.map +1 -1
- package/dist/agents/qwen.js +3 -14
- package/dist/agents/registry.d.ts.map +1 -1
- package/dist/agents/registry.js +0 -4
- package/dist/agents/shared.d.ts +28 -0
- package/dist/agents/shared.d.ts.map +1 -0
- package/dist/agents/shared.js +35 -0
- package/dist/agents/types.d.ts +19 -11
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/engine.d.ts +53 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +78 -0
- package/dist/mcp/actuateServer.d.ts +3 -0
- package/dist/mcp/actuateServer.d.ts.map +1 -0
- package/dist/mcp/actuateServer.js +594 -0
- package/dist/mcp/sourceFence.d.ts +23 -0
- package/dist/mcp/sourceFence.d.ts.map +1 -0
- package/dist/mcp/sourceFence.js +79 -0
- package/dist/mcp/sourceServer.d.ts +3 -0
- package/dist/mcp/sourceServer.d.ts.map +1 -0
- package/dist/mcp/sourceServer.js +191 -0
- package/dist/memory/businessMemory.d.ts +29 -0
- package/dist/memory/businessMemory.d.ts.map +1 -0
- package/dist/memory/businessMemory.js +125 -0
- package/dist/modes.d.ts +39 -0
- package/dist/modes.d.ts.map +1 -0
- package/dist/modes.js +34 -0
- package/dist/playwright/cdpStatus.d.ts +0 -15
- package/dist/playwright/cdpStatus.d.ts.map +1 -1
- package/dist/playwright/cdpStatus.js +0 -67
- package/dist/playwright/launchChrome.d.ts +18 -0
- package/dist/playwright/launchChrome.d.ts.map +1 -1
- package/dist/playwright/launchChrome.js +46 -3
- package/dist/playwright/preflight.d.ts.map +1 -1
- package/dist/playwright/preflight.js +6 -1
- package/dist/playwright/resolveMcpConfig.d.ts +12 -0
- package/dist/playwright/resolveMcpConfig.d.ts.map +1 -1
- package/dist/playwright/resolveMcpConfig.js +36 -5
- package/dist/plugin-api.d.ts +35 -26
- package/dist/plugin-api.d.ts.map +1 -1
- package/dist/plugin-api.js +2 -2
- package/dist/qa/candidates.d.ts +32 -0
- package/dist/qa/candidates.d.ts.map +1 -0
- package/dist/qa/candidates.js +20 -0
- package/dist/qa/classify.d.ts +38 -0
- package/dist/qa/classify.d.ts.map +1 -0
- package/dist/qa/classify.js +138 -0
- package/dist/qa/intensity.d.ts +33 -0
- package/dist/qa/intensity.d.ts.map +1 -0
- package/dist/qa/intensity.js +25 -0
- package/dist/qa/qaReport.d.ts +19 -0
- package/dist/qa/qaReport.d.ts.map +1 -0
- package/dist/qa/qaReport.js +50 -0
- package/dist/runSession.d.ts +14 -3
- package/dist/runSession.d.ts.map +1 -1
- package/dist/runSession.js +31 -11
- package/dist/service/cdpHandlers.d.ts +3 -27
- package/dist/service/cdpHandlers.d.ts.map +1 -1
- package/dist/service/cdpHandlers.js +6 -53
- package/dist/service/cdpHint.d.ts +21 -28
- package/dist/service/cdpHint.d.ts.map +1 -1
- package/dist/service/cdpHint.js +106 -164
- package/dist/service/relayHandlers.d.ts +28 -0
- package/dist/service/relayHandlers.d.ts.map +1 -0
- package/dist/service/relayHandlers.js +105 -0
- package/dist/service/saveHandlers.d.ts +1 -3
- package/dist/service/saveHandlers.d.ts.map +1 -1
- package/dist/service/saveHandlers.js +17 -15
- package/dist/service/types.d.ts +108 -8
- package/dist/service/types.d.ts.map +1 -1
- package/dist/service.d.ts +13 -3
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +1022 -236
- package/dist/sessions/sessions.d.ts +125 -0
- package/dist/sessions/sessions.d.ts.map +1 -0
- package/dist/sessions/sessions.js +175 -0
- package/dist/specs/authFixture.d.ts +30 -0
- package/dist/specs/authFixture.d.ts.map +1 -0
- package/dist/specs/authFixture.js +145 -0
- package/dist/specs/businessMap.d.ts +29 -0
- package/dist/specs/businessMap.d.ts.map +1 -0
- package/dist/specs/businessMap.js +95 -0
- package/dist/specs/detectSharedFlows.d.ts +1 -1
- package/dist/specs/detectSharedFlows.d.ts.map +1 -1
- package/dist/specs/detectSharedFlows.js +20 -21
- package/dist/specs/generatePageObject.d.ts +1 -1
- package/dist/specs/generatePageObject.d.ts.map +1 -1
- package/dist/specs/healPrompt.d.ts +19 -0
- package/dist/specs/healPrompt.d.ts.map +1 -0
- package/dist/specs/healPrompt.js +48 -0
- package/dist/specs/humanSteps.d.ts +4 -8
- package/dist/specs/humanSteps.d.ts.map +1 -1
- package/dist/specs/humanSteps.js +6 -1
- package/dist/specs/optimizeSpec.d.ts +15 -8
- package/dist/specs/optimizeSpec.d.ts.map +1 -1
- package/dist/specs/optimizeSpec.js +98 -46
- package/dist/specs/optimizeSpecWithAgent.d.ts +0 -2
- package/dist/specs/optimizeSpecWithAgent.d.ts.map +1 -1
- package/dist/specs/optimizeSpecWithAgent.js +0 -1
- package/dist/specs/pageObjectManifest.d.ts +3 -1
- package/dist/specs/pageObjectManifest.d.ts.map +1 -1
- package/dist/specs/pageObjectManifest.js +13 -9
- package/dist/specs/replayGrounded.d.ts +45 -0
- package/dist/specs/replayGrounded.d.ts.map +1 -0
- package/dist/specs/replayGrounded.js +155 -0
- package/dist/specs/runFailures.d.ts +34 -0
- package/dist/specs/runFailures.d.ts.map +1 -0
- package/dist/specs/runFailures.js +93 -0
- package/dist/specs/seeds.d.ts +16 -15
- package/dist/specs/seeds.d.ts.map +1 -1
- package/dist/specs/seeds.js +86 -54
- package/dist/specs/sidecar.d.ts +34 -6
- package/dist/specs/sidecar.d.ts.map +1 -1
- package/dist/specs/sidecar.js +79 -9
- package/dist/specs/softBatch.d.ts +14 -0
- package/dist/specs/softBatch.d.ts.map +1 -0
- package/dist/specs/softBatch.js +177 -0
- package/dist/specs/specStep.d.ts +21 -0
- package/dist/specs/specStep.d.ts.map +1 -0
- package/dist/specs/specStep.js +1 -0
- package/dist/specs/text.d.ts +19 -0
- package/dist/specs/text.d.ts.map +1 -0
- package/dist/specs/text.js +27 -0
- package/dist/specs/writeSpec.d.ts +62 -1
- package/dist/specs/writeSpec.d.ts.map +1 -1
- package/dist/specs/writeSpec.js +598 -30
- package/package.json +10 -10
- package/dist/agents/aider.d.ts +0 -16
- package/dist/agents/aider.d.ts.map +0 -1
- package/dist/agents/aider.js +0 -169
- package/dist/agents/cursor.d.ts +0 -18
- package/dist/agents/cursor.d.ts.map +0 -1
- package/dist/agents/cursor.js +0 -229
- package/dist/playwright/raiseWindow.d.ts +0 -10
- package/dist/playwright/raiseWindow.d.ts.map +0 -1
- package/dist/playwright/raiseWindow.js +0 -139
- package/dist/scripts/bench-multi-tab.d.ts +0 -2
- package/dist/scripts/bench-multi-tab.d.ts.map +0 -1
- package/dist/scripts/bench-multi-tab.js +0 -192
- package/dist/scripts/bench-ttfb.d.ts +0 -2
- package/dist/scripts/bench-ttfb.d.ts.map +0 -1
- package/dist/scripts/bench-ttfb.js +0 -127
- package/dist/scripts/start-chrome.d.ts +0 -3
- package/dist/scripts/start-chrome.d.ts.map +0 -1
- package/dist/scripts/start-chrome.js +0 -23
- package/dist/skills/writeSkill.d.ts +0 -27
- package/dist/skills/writeSkill.d.ts.map +0 -1
- package/dist/skills/writeSkill.js +0 -13
- package/dist/specs/listSpecs.d.ts +0 -52
- package/dist/specs/listSpecs.d.ts.map +0 -1
- package/dist/specs/listSpecs.js +0 -139
- package/dist/specs/optimizationSuggestion.d.ts +0 -26
- package/dist/specs/optimizationSuggestion.d.ts.map +0 -1
- package/dist/specs/optimizationSuggestion.js +0 -28
- package/dist/specs/writeCaseCsv.d.ts +0 -28
- package/dist/specs/writeCaseCsv.d.ts.map +0 -1
- package/dist/specs/writeCaseCsv.js +0 -140
package/dist/agents/codex.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { stripMcpPrefix } from './shared.js';
|
|
1
2
|
/**
|
|
2
3
|
* Pricing per million tokens. Keep in lockstep with claude.ts's table —
|
|
3
4
|
* approximate published OpenAI rates as of 2026. We are deliberately
|
|
@@ -16,6 +17,9 @@ const PRICE_PER_M_USD = {
|
|
|
16
17
|
'gpt-4o': { in: 2.5, out: 10 },
|
|
17
18
|
'gpt-4': { in: 30, out: 60 },
|
|
18
19
|
};
|
|
20
|
+
// `modelHint` is currently always passed as undefined — the parser can't see
|
|
21
|
+
// the invocation's --model — so the default tier below is what gets used. The
|
|
22
|
+
// parameter is kept so a future caller that does have the model id can pass it.
|
|
19
23
|
function estimateCostUsd(modelHint, usage) {
|
|
20
24
|
const m = (modelHint ?? 'gpt-5.5').toLowerCase();
|
|
21
25
|
// Match by longest-prefix so 'gpt-5.5-mini' picks up the 'gpt-5.5' tier.
|
|
@@ -28,7 +32,7 @@ function codexState(state) {
|
|
|
28
32
|
if (typeof state.runningCost !== 'number') {
|
|
29
33
|
state.runningCost = 0;
|
|
30
34
|
state.runningTurns = 0;
|
|
31
|
-
state.
|
|
35
|
+
state.runningTokens = 0;
|
|
32
36
|
state.runningSessionId = undefined;
|
|
33
37
|
state.lastAgentMessage = undefined;
|
|
34
38
|
state.sawErrorEvent = false;
|
|
@@ -39,27 +43,32 @@ function codexState(state) {
|
|
|
39
43
|
function resetCodexCounters(s) {
|
|
40
44
|
s.runningCost = 0;
|
|
41
45
|
s.runningTurns = 0;
|
|
42
|
-
s.
|
|
46
|
+
s.runningTokens = 0;
|
|
43
47
|
s.runningSessionId = undefined;
|
|
44
48
|
s.lastAgentMessage = undefined;
|
|
45
49
|
s.sawErrorEvent = false;
|
|
46
50
|
s.itemTypeById.clear();
|
|
47
51
|
}
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
/** The tool-restriction is codex's only sandbox (no --allowedTools flag), so it
|
|
53
|
+
* must mirror the hard-sandbox allow-list the service computes per mode — NOT a
|
|
54
|
+
* hardcoded "playwright only", which made codex refuse the active mode's plugin
|
|
55
|
+
* tools (api_request, replay_flow, hover-control, …). Built from opts.allowedTools. */
|
|
56
|
+
function codexDeveloperInstructions(allowedTools) {
|
|
57
|
+
const prefixes = (allowedTools && allowedTools.length ? allowedTools : ['mcp__playwright']).map((p) => `${p}__*`);
|
|
58
|
+
return [
|
|
59
|
+
'You are operating in Hover, a browser- and API-testing tool.',
|
|
60
|
+
`Use ONLY MCP tools whose name starts with one of these prefixes: ${prefixes.join(', ')}. They cover driving the browser, the Hover control + API-request tools, and reading source — everything the task needs.`,
|
|
61
|
+
'Do NOT call shell, file-edit, web-search, or any other built-in tool.',
|
|
62
|
+
'Do NOT navigate to a URL the user is already on; check the page state via `browser_snapshot` first.',
|
|
63
|
+
'When the task is complete, emit a short agent_message summary and stop.',
|
|
64
|
+
].join(' ');
|
|
65
|
+
}
|
|
56
66
|
export const codexAgent = {
|
|
57
67
|
id: 'codex',
|
|
58
68
|
binName: 'codex',
|
|
59
69
|
protocol: 'argv',
|
|
60
70
|
streamFormat: 'json-lines',
|
|
61
71
|
sandboxStrength: 'soft',
|
|
62
|
-
apiKeyEnv: 'OPENAI_API_KEY',
|
|
63
72
|
display: {
|
|
64
73
|
label: 'OpenAI Codex',
|
|
65
74
|
tagline: 'OpenAI — soft sandbox (no built-in tool deny-list)',
|
|
@@ -85,13 +94,19 @@ export const codexAgent = {
|
|
|
85
94
|
if (opts.model) {
|
|
86
95
|
args.push('--model', opts.model);
|
|
87
96
|
}
|
|
97
|
+
// Reasoning effort → the API's reasoning_effort, set via the `-c` TOML
|
|
98
|
+
// override (no stable long flag exists). Sits alongside the other -c keys.
|
|
99
|
+
if (opts.effort) {
|
|
100
|
+
args.push('-c', `model_reasoning_effort=${opts.effort}`);
|
|
101
|
+
}
|
|
88
102
|
// System-prompt injection. Codex has no --append-system-prompt; we route
|
|
89
103
|
// through `-c developer_instructions='...'`. Concatenate the standing
|
|
90
104
|
// Hover-mode instructions with whatever the caller passes (e.g. "user is
|
|
91
105
|
// already on http://localhost:5173/").
|
|
106
|
+
const base = codexDeveloperInstructions(opts.allowedTools);
|
|
92
107
|
const sysPrompt = opts.appendSystemPrompt && opts.appendSystemPrompt.trim().length > 0
|
|
93
|
-
? `${
|
|
94
|
-
:
|
|
108
|
+
? `${base} ${opts.appendSystemPrompt}`
|
|
109
|
+
: base;
|
|
95
110
|
args.push('-c', `developer_instructions=${JSON.stringify(sysPrompt)}`);
|
|
96
111
|
// MCP servers are configured in ~/.codex/config.toml at install time,
|
|
97
112
|
// not per-invocation. If the user passed an mcpConfig path, we don't
|
|
@@ -128,13 +143,13 @@ export const codexAgent = {
|
|
|
128
143
|
// The exact field names aren't published. Read defensively: prefer
|
|
129
144
|
// `name`, fall back to `tool`. Same for input.
|
|
130
145
|
const rawName = it.name ?? it.tool ?? '';
|
|
131
|
-
const tool = rawName
|
|
132
|
-
out.push({ kind: 'tool_use', tool, input: it.input ?? it.arguments, costUsdSnapshot: s.runningCost });
|
|
146
|
+
const tool = stripMcpPrefix(rawName);
|
|
147
|
+
out.push({ kind: 'tool_use', tool, input: it.input ?? it.arguments, costUsdSnapshot: s.runningCost, tokensSnapshot: s.runningTokens });
|
|
133
148
|
}
|
|
134
149
|
else if (it.type === 'command_execution') {
|
|
135
150
|
// We DISCOURAGED this in developer_instructions but the agent can
|
|
136
151
|
// still try. Surface it so the user sees it happen.
|
|
137
|
-
out.push({ kind: 'tool_use', tool: 'shell', input: { command: it.command }, costUsdSnapshot: s.runningCost });
|
|
152
|
+
out.push({ kind: 'tool_use', tool: 'shell', input: { command: it.command }, costUsdSnapshot: s.runningCost, tokensSnapshot: s.runningTokens });
|
|
138
153
|
}
|
|
139
154
|
return out;
|
|
140
155
|
}
|
|
@@ -158,9 +173,13 @@ export const codexAgent = {
|
|
|
158
173
|
if (ev.type === 'turn.completed') {
|
|
159
174
|
s.runningTurns += 1;
|
|
160
175
|
if (ev.usage) {
|
|
161
|
-
|
|
176
|
+
// The parser has no access to the invocation's --model, so we let
|
|
177
|
+
// estimateCostUsd fall back to its fixed default tier. Cost is a
|
|
178
|
+
// high-water "should I hit Stop now" signal, not an invoice.
|
|
179
|
+
s.runningCost += estimateCostUsd(undefined, ev.usage);
|
|
180
|
+
s.runningTokens += (ev.usage.input_tokens ?? 0) + (ev.usage.output_tokens ?? 0);
|
|
162
181
|
}
|
|
163
|
-
out.push({ kind: 'usage', costUsd: s.runningCost, turns: s.runningTurns });
|
|
182
|
+
out.push({ kind: 'usage', costUsd: s.runningCost, turns: s.runningTurns, tokens: s.runningTokens });
|
|
164
183
|
return out;
|
|
165
184
|
}
|
|
166
185
|
// Codex emits various error envelopes; we conservatively match anything
|
|
@@ -185,6 +204,7 @@ export const codexAgent = {
|
|
|
185
204
|
kind: 'session_end',
|
|
186
205
|
turns: s.runningTurns,
|
|
187
206
|
costUsd: s.runningCost,
|
|
207
|
+
tokens: s.runningTokens,
|
|
188
208
|
isError: s.sawErrorEvent || (exitCode != null && exitCode !== 0),
|
|
189
209
|
summary: s.lastAgentMessage,
|
|
190
210
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/agents/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAA8B,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/agents/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAA8B,WAAW,EAAE,MAAM,YAAY,CAAC;AA+J3F,eAAO,MAAM,WAAW,EAAE,eAiJzB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS;sBACJ,WAAW;2BACJ,WAAW;sBAChB,WAAW;;;;;;;CAU9B,CAAC"}
|
package/dist/agents/gemini.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HOVER_PROMPT_PREFACE, stripMcpPrefix } from './shared.js';
|
|
1
2
|
function geminiState(state) {
|
|
2
3
|
if (typeof state.runningTurns !== 'number') {
|
|
3
4
|
state.runningTurns = 0;
|
|
@@ -17,11 +18,6 @@ function resetGeminiCounters(s) {
|
|
|
17
18
|
s.sawErrorEvent = false;
|
|
18
19
|
s.toolNameByUseId.clear();
|
|
19
20
|
}
|
|
20
|
-
/** Strip the `mcp__playwright__` / `mcp__hover-playwright__` prefix so tool
|
|
21
|
-
* names match the normalised names claude / codex / cursor / qwen emit. */
|
|
22
|
-
function stripMcpPrefix(raw) {
|
|
23
|
-
return raw.replace(/^mcp__playwright__/, '').replace(/^mcp__hover-playwright__/, '');
|
|
24
|
-
}
|
|
25
21
|
/**
|
|
26
22
|
* Extract assistant text from a `message` event whose `content` may be a
|
|
27
23
|
* plain string OR an array of `{type:'text', text}` content blocks. Gemini's
|
|
@@ -41,13 +37,6 @@ function extractMessageText(ev) {
|
|
|
41
37
|
}
|
|
42
38
|
return undefined;
|
|
43
39
|
}
|
|
44
|
-
const GEMINI_PROMPT_PREFACE = [
|
|
45
|
-
'You are operating in Hover, a browser-testing tool.',
|
|
46
|
-
'Use ONLY the MCP playwright tools (prefixed `mcp__playwright__` / `mcp__hover-playwright__`) to drive the browser.',
|
|
47
|
-
'Do NOT use shell, file-edit, web-search, or any other built-in tool.',
|
|
48
|
-
'Do NOT navigate to a URL the user is already on; check the page state via `browser_snapshot` first.',
|
|
49
|
-
'When the task is complete, emit a short summary and stop.',
|
|
50
|
-
].join(' ');
|
|
51
40
|
export const geminiAgent = {
|
|
52
41
|
id: 'gemini',
|
|
53
42
|
binName: 'gemini',
|
|
@@ -65,8 +54,8 @@ export const geminiAgent = {
|
|
|
65
54
|
// GEMINI_SYSTEM_MD env var which writes a file). Prepend the HOVER-mode
|
|
66
55
|
// preface to the prompt instead — same pattern as cursor.ts / aider.ts.
|
|
67
56
|
const preface = opts.appendSystemPrompt && opts.appendSystemPrompt.trim().length > 0
|
|
68
|
-
? `${
|
|
69
|
-
:
|
|
57
|
+
? `${HOVER_PROMPT_PREFACE} ${opts.appendSystemPrompt}`
|
|
58
|
+
: HOVER_PROMPT_PREFACE;
|
|
70
59
|
const finalPrompt = `${preface}\n\n${opts.prompt}`;
|
|
71
60
|
const args = ['-p', finalPrompt];
|
|
72
61
|
// NDJSON streaming output.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invoke.d.ts","sourceRoot":"","sources":["../../src/agents/invoke.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAe,MAAM,YAAY,CAAC;AAE1E;;;;;;;;GAQG;AACH,wBAAuB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"invoke.d.ts","sourceRoot":"","sources":["../../src/agents/invoke.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAe,MAAM,YAAY,CAAC;AAE1E;;;;;;;;GAQG;AACH,wBAAuB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,CAAC,WAAW,CAAC,CA4ElF"}
|
package/dist/agents/invoke.js
CHANGED
|
@@ -31,15 +31,12 @@ export async function* invokeAgent(opts) {
|
|
|
31
31
|
cwd: opts.cwd,
|
|
32
32
|
// Clear CLAUDECODE so spawning `claude` from inside a Claude Code session
|
|
33
33
|
// doesn't trip the nested-session guard. Harmless for other agents.
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
// The key lives only in this child's env — never logged, never persisted.
|
|
34
|
+
// The CLI authenticates via its own logged-in subscription (or inherits any
|
|
35
|
+
// key already in process.env); opts.env carries the Local LLM endpoint vars.
|
|
37
36
|
env: {
|
|
38
37
|
...process.env,
|
|
39
38
|
CLAUDECODE: '',
|
|
40
|
-
...(opts.
|
|
41
|
-
? { [descriptor.apiKeyEnv]: opts.apiKey }
|
|
42
|
-
: {}),
|
|
39
|
+
...(opts.env ?? {}),
|
|
43
40
|
},
|
|
44
41
|
});
|
|
45
42
|
const onAbort = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qwen.d.ts","sourceRoot":"","sources":["../../src/agents/qwen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAA8B,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"qwen.d.ts","sourceRoot":"","sources":["../../src/agents/qwen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAA8B,WAAW,EAAE,MAAM,YAAY,CAAC;AAoJ3F,eAAO,MAAM,SAAS,EAAE,eAqJvB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS;sBACJ,WAAW;2BACJ,WAAW;sBAChB,WAAW;;;;;;;CAU9B,CAAC"}
|
package/dist/agents/qwen.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HOVER_PROMPT_PREFACE, stripMcpPrefix } from './shared.js';
|
|
1
2
|
function qwenState(state) {
|
|
2
3
|
if (typeof state.runningTurns !== 'number') {
|
|
3
4
|
state.runningTurns = 0;
|
|
@@ -17,18 +18,6 @@ function resetQwenCounters(s) {
|
|
|
17
18
|
s.sawErrorEvent = false;
|
|
18
19
|
s.toolNameByUseId.clear();
|
|
19
20
|
}
|
|
20
|
-
/** Strip the `mcp__playwright__` / `mcp__hover-playwright__` prefix so tool
|
|
21
|
-
* names match the normalised names claude / codex / cursor emit. */
|
|
22
|
-
function stripMcpPrefix(raw) {
|
|
23
|
-
return raw.replace(/^mcp__playwright__/, '').replace(/^mcp__hover-playwright__/, '');
|
|
24
|
-
}
|
|
25
|
-
const QWEN_PROMPT_PREFACE = [
|
|
26
|
-
'You are operating in Hover, a browser-testing tool.',
|
|
27
|
-
'Use ONLY the MCP playwright tools (prefixed `mcp__playwright__` / `mcp__hover-playwright__`) to drive the browser.',
|
|
28
|
-
'Do NOT use shell, file-edit, web-search, or any other built-in tool.',
|
|
29
|
-
'Do NOT navigate to a URL the user is already on; check the page state via `browser_snapshot` first.',
|
|
30
|
-
'When the task is complete, emit a short summary and stop.',
|
|
31
|
-
].join(' ');
|
|
32
21
|
export const qwenAgent = {
|
|
33
22
|
id: 'qwen',
|
|
34
23
|
binName: 'qwen',
|
|
@@ -62,8 +51,8 @@ export const qwenAgent = {
|
|
|
62
51
|
// prepending to the user prompt. Concatenate the standing Hover-mode
|
|
63
52
|
// preface with whatever the caller appended.
|
|
64
53
|
const sysPrompt = opts.appendSystemPrompt && opts.appendSystemPrompt.trim().length > 0
|
|
65
|
-
? `${
|
|
66
|
-
:
|
|
54
|
+
? `${HOVER_PROMPT_PREFACE} ${opts.appendSystemPrompt}`
|
|
55
|
+
: HOVER_PROMPT_PREFACE;
|
|
67
56
|
args.push('--append-system-prompt', sysPrompt);
|
|
68
57
|
// MCP servers configured in ~/.qwen/settings.json — no per-invocation
|
|
69
58
|
// --mcp-config equivalent. Same constraint as cursor / codex.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/agents/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/agents/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAMlD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAKlD,CAAC;AAEF,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEhE;AAED,+DAA+D;AAC/D,wBAAgB,UAAU,IAAI,eAAe,EAAE,CAE9C"}
|
package/dist/agents/registry.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { claudeAgent } from './claude.js';
|
|
2
2
|
import { codexAgent } from './codex.js';
|
|
3
|
-
import { cursorAgent } from './cursor.js';
|
|
4
|
-
import { aiderAgent } from './aider.js';
|
|
5
3
|
import { geminiAgent } from './gemini.js';
|
|
6
4
|
import { qwenAgent } from './qwen.js';
|
|
7
5
|
/**
|
|
@@ -20,8 +18,6 @@ import { qwenAgent } from './qwen.js';
|
|
|
20
18
|
export const AGENTS = {
|
|
21
19
|
[claudeAgent.id]: claudeAgent,
|
|
22
20
|
[codexAgent.id]: codexAgent,
|
|
23
|
-
[cursorAgent.id]: cursorAgent,
|
|
24
|
-
[aiderAgent.id]: aiderAgent,
|
|
25
21
|
[geminiAgent.id]: geminiAgent,
|
|
26
22
|
[qwenAgent.id]: qwenAgent,
|
|
27
23
|
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-agent helpers shared by the soft-sandbox descriptors
|
|
3
|
+
* (codex / cursor / gemini / qwen / aider).
|
|
4
|
+
*
|
|
5
|
+
* These agents all need the same two things:
|
|
6
|
+
* 1. A standing "HOVER-mode" instruction preface that tells the agent to
|
|
7
|
+
* drive the browser via the Playwright MCP tools only and not to touch
|
|
8
|
+
* its built-in shell / file-edit tools. Each agent injects it through a
|
|
9
|
+
* different channel (cursor / gemini / aider prepend it to the prompt,
|
|
10
|
+
* qwen passes it via --append-system-prompt, codex via
|
|
11
|
+
* `-c developer_instructions=`), so this module owns only the *text*, not
|
|
12
|
+
* the injection.
|
|
13
|
+
* 2. Normalising the `mcp__playwright__` / `mcp__hover-playwright__` prefix
|
|
14
|
+
* off a raw tool name so the emitted tool names line up across agents.
|
|
15
|
+
*
|
|
16
|
+
* codex deliberately does NOT use HOVER_PROMPT_PREFACE — it keeps its own
|
|
17
|
+
* wording ("Do NOT call …", "emit a short agent_message summary …") that is
|
|
18
|
+
* tuned to codex's event vocabulary. See codex.ts.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* The standing HOVER-mode instruction shared by cursor / gemini / qwen / aider.
|
|
22
|
+
* codex carries a near-identical but intentionally different variant inline.
|
|
23
|
+
*/
|
|
24
|
+
export declare const HOVER_PROMPT_PREFACE: string;
|
|
25
|
+
/** Strip the `mcp__playwright__` / `mcp__hover-playwright__` prefix so tool
|
|
26
|
+
* names match the normalised names every agent emits. */
|
|
27
|
+
export declare function stripMcpPrefix(raw: string): string;
|
|
28
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/agents/shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;GAGG;AACH,eAAO,MAAM,oBAAoB,QAMtB,CAAC;AAEZ;0DAC0D;AAC1D,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAElD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-agent helpers shared by the soft-sandbox descriptors
|
|
3
|
+
* (codex / cursor / gemini / qwen / aider).
|
|
4
|
+
*
|
|
5
|
+
* These agents all need the same two things:
|
|
6
|
+
* 1. A standing "HOVER-mode" instruction preface that tells the agent to
|
|
7
|
+
* drive the browser via the Playwright MCP tools only and not to touch
|
|
8
|
+
* its built-in shell / file-edit tools. Each agent injects it through a
|
|
9
|
+
* different channel (cursor / gemini / aider prepend it to the prompt,
|
|
10
|
+
* qwen passes it via --append-system-prompt, codex via
|
|
11
|
+
* `-c developer_instructions=`), so this module owns only the *text*, not
|
|
12
|
+
* the injection.
|
|
13
|
+
* 2. Normalising the `mcp__playwright__` / `mcp__hover-playwright__` prefix
|
|
14
|
+
* off a raw tool name so the emitted tool names line up across agents.
|
|
15
|
+
*
|
|
16
|
+
* codex deliberately does NOT use HOVER_PROMPT_PREFACE — it keeps its own
|
|
17
|
+
* wording ("Do NOT call …", "emit a short agent_message summary …") that is
|
|
18
|
+
* tuned to codex's event vocabulary. See codex.ts.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* The standing HOVER-mode instruction shared by cursor / gemini / qwen / aider.
|
|
22
|
+
* codex carries a near-identical but intentionally different variant inline.
|
|
23
|
+
*/
|
|
24
|
+
export const HOVER_PROMPT_PREFACE = [
|
|
25
|
+
'You are operating in Hover, a browser-testing tool.',
|
|
26
|
+
'Use ONLY the MCP playwright tools (prefixed `mcp__playwright__` / `mcp__hover-playwright__`) to drive the browser.',
|
|
27
|
+
'Do NOT use shell, file-edit, web-search, or any other built-in tool.',
|
|
28
|
+
'Do NOT navigate to a URL the user is already on; check the page state via `browser_snapshot` first.',
|
|
29
|
+
'When the task is complete, emit a short summary and stop.',
|
|
30
|
+
].join(' ');
|
|
31
|
+
/** Strip the `mcp__playwright__` / `mcp__hover-playwright__` prefix so tool
|
|
32
|
+
* names match the normalised names every agent emits. */
|
|
33
|
+
export function stripMcpPrefix(raw) {
|
|
34
|
+
return raw.replace(/^mcp__playwright__/, '').replace(/^mcp__hover-playwright__/, '');
|
|
35
|
+
}
|
package/dist/agents/types.d.ts
CHANGED
|
@@ -23,7 +23,15 @@ export interface InvokeOptions {
|
|
|
23
23
|
allowedTools?: string[];
|
|
24
24
|
disallowedTools?: string[];
|
|
25
25
|
maxBudgetUsd?: number;
|
|
26
|
+
/** Hard ceiling on agent turns (~steps) — claude `--max-turns`. Used by QA
|
|
27
|
+
* intensity to bound an exploratory run by step count. */
|
|
28
|
+
maxTurns?: number;
|
|
26
29
|
model?: string;
|
|
30
|
+
/** Reasoning-effort level for the run. claude → `--effort <level>` (low /
|
|
31
|
+
* medium / high / xhigh / max); codex → `-c model_reasoning_effort=<level>`
|
|
32
|
+
* (minimal / low / medium / high / xhigh). The caller is responsible for
|
|
33
|
+
* passing a level the chosen model actually supports. */
|
|
34
|
+
effort?: string;
|
|
27
35
|
cwd?: string;
|
|
28
36
|
sessionId?: string;
|
|
29
37
|
/** Extra text appended to the agent's system prompt (claude: via
|
|
@@ -31,11 +39,10 @@ export interface InvokeOptions {
|
|
|
31
39
|
* "the user's current Chrome tab is already on http://localhost:5173/,
|
|
32
40
|
* don't browser_navigate there". */
|
|
33
41
|
appendSystemPrompt?: string;
|
|
34
|
-
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
|
|
38
|
-
apiKey?: string;
|
|
42
|
+
/** Extra environment variables for the spawned CLI (merged over process.env).
|
|
43
|
+
* Used for the "Local LLM" path: qwen-code reads OPENAI_BASE_URL /
|
|
44
|
+
* OPENAI_API_KEY to target a user's self-hosted OpenAI-compatible endpoint. */
|
|
45
|
+
env?: Record<string, string>;
|
|
39
46
|
/** Aborts the spawned child if signaled. Used to stop an orphan run when
|
|
40
47
|
* the WebSocket caller disconnects (e.g. user reloads the dev page). */
|
|
41
48
|
signal?: AbortSignal;
|
|
@@ -57,6 +64,7 @@ export type InvokeEvent = {
|
|
|
57
64
|
tool: string;
|
|
58
65
|
input: unknown;
|
|
59
66
|
costUsdSnapshot?: number;
|
|
67
|
+
tokensSnapshot?: number;
|
|
60
68
|
} | {
|
|
61
69
|
kind: 'tool_result';
|
|
62
70
|
isError?: boolean;
|
|
@@ -73,6 +81,7 @@ export type InvokeEvent = {
|
|
|
73
81
|
kind: 'usage';
|
|
74
82
|
costUsd?: number;
|
|
75
83
|
turns?: number;
|
|
84
|
+
tokens?: number;
|
|
76
85
|
}
|
|
77
86
|
/** End-of-session event. Three terminal states the widget renders distinctly:
|
|
78
87
|
*
|
|
@@ -87,6 +96,7 @@ export type InvokeEvent = {
|
|
|
87
96
|
kind: 'session_end';
|
|
88
97
|
turns?: number;
|
|
89
98
|
costUsd?: number;
|
|
99
|
+
tokens?: number;
|
|
90
100
|
isError?: boolean;
|
|
91
101
|
cancelled?: boolean;
|
|
92
102
|
summary?: string;
|
|
@@ -156,12 +166,10 @@ export interface AgentDescriptor {
|
|
|
156
166
|
* per-CLI deny list live alongside its descriptor instead of as a magic
|
|
157
167
|
* array in the service. Soft-sandbox agents leave this undefined. */
|
|
158
168
|
defaultDisallowedTools?: readonly string[];
|
|
159
|
-
/**
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
|
|
163
|
-
* Undefined for agents that have no API-key env path. */
|
|
164
|
-
apiKeyEnv?: string;
|
|
169
|
+
/** A cheap/fast model id for non-interactive refinement work (the F7 optimize
|
|
170
|
+
* pass) where the big model isn't worth the cost. Used when the user hasn't
|
|
171
|
+
* set `hover.optimizeModel`; undefined → fall back to the session model. */
|
|
172
|
+
cheapModel?: string;
|
|
165
173
|
buildArgs(opts: InvokeOptions): string[];
|
|
166
174
|
/**
|
|
167
175
|
* Parse a single line of agent stdout into normalised InvokeEvents.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,OAAO,GACP,KAAK,GACL,QAAQ,CAAC;AAEb,MAAM,MAAM,YAAY,GACpB,aAAa,GACb,KAAK,GACL,YAAY,GACZ,YAAY,CAAC;AAEjB,qBAAa,6BAA8B,SAAQ,KAAK;gBAC1C,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,sBAAuB,SAAQ,KAAK;aACnB,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM;CAI5C;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;yCAGqC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export { runSession } from './runSession.js';
|
|
2
|
+
export type { RunSessionOptions, RunSessionResult } from './runSession.js';
|
|
3
|
+
export { writeSpec } from './specs/writeSpec.js';
|
|
4
|
+
export type { WriteSpecOptions, WriteSpecResult, Redaction } from './specs/writeSpec.js';
|
|
5
|
+
export type { SkillStep } from './specs/specStep.js';
|
|
6
|
+
export { replayGroundedSteps, replayOnPage, applyGroundedStep, groundedLocate } from './specs/replayGrounded.js';
|
|
7
|
+
export type { ReplayResult, ReplayFailure, ReplayStep, GroundedTarget } from './specs/replayGrounded.js';
|
|
8
|
+
export { resolveMcpConfig, mcpToolPrefix } from './playwright/resolveMcpConfig.js';
|
|
9
|
+
export { launchDebugChrome, closeDebugChrome, findChromeBinary } from './playwright/launchChrome.js';
|
|
10
|
+
export type { LaunchOptions, LaunchResult } from './playwright/launchChrome.js';
|
|
11
|
+
export { GROUNDED_ACTUATION_DENY, GROUNDED_ACTUATION_DIRECTIVE } from './agentDirectives.js';
|
|
12
|
+
export { loadMemory, formatMemoryForPrompt, writeFact, memoryDir } from './memory/businessMemory.js';
|
|
13
|
+
export type { BusinessFact } from './memory/businessMemory.js';
|
|
14
|
+
export { RECON_DIRECTIVE, QA_EXPLORATION_DIRECTIVE } from './agentDirectives.js';
|
|
15
|
+
export { QA_INTENSITY, DEFAULT_QA_INTENSITY, asQaIntensity, qaBudgetDirective } from './qa/intensity.js';
|
|
16
|
+
export type { QaIntensity, QaIntensitySpec } from './qa/intensity.js';
|
|
17
|
+
/**
|
|
18
|
+
* The always-on control-actuation MCP server id. Alphanumeric on purpose — a
|
|
19
|
+
* hyphen would make the hard-sandbox allow prefix (`mcp__hovercontrol`) fail to
|
|
20
|
+
* match the tool names (`mcp__hovercontrol__click_control`), so every grounded
|
|
21
|
+
* actuation would be denied. (Same constant + reasoning as service.ts.)
|
|
22
|
+
*/
|
|
23
|
+
export declare const CONTROL_MCP_ID = "hovercontrol";
|
|
24
|
+
/** The hard-sandbox allow prefix for the control server — pass in
|
|
25
|
+
* `runSession({ allowedToolsExtra: [CONTROL_MCP_TOOL_PREFIX] })`. */
|
|
26
|
+
export declare const CONTROL_MCP_TOOL_PREFIX: string;
|
|
27
|
+
export interface GroundedMcpOptions {
|
|
28
|
+
/** CDP endpoint of the debug Chrome the agent drives. */
|
|
29
|
+
cdpUrl: string;
|
|
30
|
+
/** Port used only to namespace the generated config filename. */
|
|
31
|
+
port: number;
|
|
32
|
+
/** Project root — where the control server resolves relative paths / writes
|
|
33
|
+
* its placeholder upload fixture, and where `@playwright/mcp` resolves from. */
|
|
34
|
+
devRoot: string;
|
|
35
|
+
/** The dev-server origin the run targets (defaults to `cdpUrl`). */
|
|
36
|
+
devUrl?: string;
|
|
37
|
+
/** WS port the control server's back-channel (`ask_user` / `record_*`)
|
|
38
|
+
* connects to. Omit when there's no listener — actuation still works; the
|
|
39
|
+
* back-channel features silently no-op (actuateServer fails soft). */
|
|
40
|
+
approvalPort?: number;
|
|
41
|
+
/** Directory the Playwright MCP + control screenshots write into. */
|
|
42
|
+
outputDir?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Build an MCP config mirroring the service's grounded/normal mode: the
|
|
46
|
+
* Playwright MCP over CDP PLUS the hover-control actuation server. Pair it in
|
|
47
|
+
* `runSession` with `allowedToolsExtra: [CONTROL_MCP_TOOL_PREFIX]`,
|
|
48
|
+
* `disallowedToolsExtra: GROUNDED_ACTUATION_DENY`, and append
|
|
49
|
+
* `GROUNDED_ACTUATION_DIRECTIVE` to the system prompt — then the selectors the
|
|
50
|
+
* agent actuates with are the ones crystallized (record==replay).
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildGroundedMcpConfig(opts: GroundedMcpOptions): string;
|
|
53
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACzF,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACjH,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAGzG,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrG,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAGhF,OAAO,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAG7F,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACrG,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAM/D,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzG,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAE7C;sEACsE;AACtE,eAAO,MAAM,uBAAuB,QAAgC,CAAC;AAMrE,MAAM,WAAW,kBAAkB;IACjC,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb;qFACiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;2EAEuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAqBvE"}
|
package/dist/engine.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process engine surface for non-service consumers — the `hover` CLI and the
|
|
3
|
+
* `@hover-dev/mcp` server. The VS Code extension drives core through the WS
|
|
4
|
+
* service (`./service`); a standalone process instead calls `runSession`
|
|
5
|
+
* directly. This barrel exposes the same building blocks the service composes —
|
|
6
|
+
* the session run, the GROUNDED MCP config (so a CLI-authored spec gets the
|
|
7
|
+
* record==replay fidelity the extension does), and spec crystallization —
|
|
8
|
+
* without the WebSocket layer.
|
|
9
|
+
*
|
|
10
|
+
* Keep this a thin re-export + the one `buildGroundedMcpConfig` helper. The
|
|
11
|
+
* grounded path here MUST stay in lock-step with `service.ts`'s normal-mode
|
|
12
|
+
* assembly (the control-actuation server + `GROUNDED_ACTUATION_DENY` /
|
|
13
|
+
* `GROUNDED_ACTUATION_DIRECTIVE`), or CLI specs would drift from extension specs.
|
|
14
|
+
*/
|
|
15
|
+
import { resolve, dirname } from 'node:path';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
import { resolveMcpConfig, mcpToolPrefix } from './playwright/resolveMcpConfig.js';
|
|
18
|
+
// ── in-process session + crystallization ─────────────────────────────────────
|
|
19
|
+
export { runSession } from './runSession.js';
|
|
20
|
+
export { writeSpec } from './specs/writeSpec.js';
|
|
21
|
+
// Creation-verification: replay a flow's grounded steps over CDP (no playwright test).
|
|
22
|
+
export { replayGroundedSteps, replayOnPage, applyGroundedStep, groundedLocate } from './specs/replayGrounded.js';
|
|
23
|
+
// ── browser / MCP plumbing ───────────────────────────────────────────────────
|
|
24
|
+
export { resolveMcpConfig, mcpToolPrefix } from './playwright/resolveMcpConfig.js';
|
|
25
|
+
export { launchDebugChrome, closeDebugChrome, findChromeBinary } from './playwright/launchChrome.js';
|
|
26
|
+
// ── grounded-actuation knobs (must match service.ts) ─────────────────────────
|
|
27
|
+
export { GROUNDED_ACTUATION_DENY, GROUNDED_ACTUATION_DIRECTIVE } from './agentDirectives.js';
|
|
28
|
+
// ── business memory (ask → remember loop; shared with the extension's QA mode) ─
|
|
29
|
+
export { loadMemory, formatMemoryForPrompt, writeFact, memoryDir } from './memory/businessMemory.js';
|
|
30
|
+
// ── autonomous-exploration directives (QA mode reuse) ────────────────────────
|
|
31
|
+
// The CLI's "explore → discover business flows → record_candidate" loop is the
|
|
32
|
+
// same mechanism QA mode drives the agent with; reuse the directives verbatim
|
|
33
|
+
// so behaviour stays in lock-step.
|
|
34
|
+
export { RECON_DIRECTIVE, QA_EXPLORATION_DIRECTIVE } from './agentDirectives.js';
|
|
35
|
+
export { QA_INTENSITY, DEFAULT_QA_INTENSITY, asQaIntensity, qaBudgetDirective } from './qa/intensity.js';
|
|
36
|
+
/**
|
|
37
|
+
* The always-on control-actuation MCP server id. Alphanumeric on purpose — a
|
|
38
|
+
* hyphen would make the hard-sandbox allow prefix (`mcp__hovercontrol`) fail to
|
|
39
|
+
* match the tool names (`mcp__hovercontrol__click_control`), so every grounded
|
|
40
|
+
* actuation would be denied. (Same constant + reasoning as service.ts.)
|
|
41
|
+
*/
|
|
42
|
+
export const CONTROL_MCP_ID = 'hovercontrol';
|
|
43
|
+
/** The hard-sandbox allow prefix for the control server — pass in
|
|
44
|
+
* `runSession({ allowedToolsExtra: [CONTROL_MCP_TOOL_PREFIX] })`. */
|
|
45
|
+
export const CONTROL_MCP_TOOL_PREFIX = mcpToolPrefix(CONTROL_MCP_ID);
|
|
46
|
+
// dist/engine.js sits beside dist/service.js, so mcp/actuateServer.js resolves
|
|
47
|
+
// the same way it does from service.ts.
|
|
48
|
+
const CONTROL_MCP_SCRIPT = resolve(dirname(fileURLToPath(import.meta.url)), 'mcp', 'actuateServer.js');
|
|
49
|
+
/**
|
|
50
|
+
* Build an MCP config mirroring the service's grounded/normal mode: the
|
|
51
|
+
* Playwright MCP over CDP PLUS the hover-control actuation server. Pair it in
|
|
52
|
+
* `runSession` with `allowedToolsExtra: [CONTROL_MCP_TOOL_PREFIX]`,
|
|
53
|
+
* `disallowedToolsExtra: GROUNDED_ACTUATION_DENY`, and append
|
|
54
|
+
* `GROUNDED_ACTUATION_DIRECTIVE` to the system prompt — then the selectors the
|
|
55
|
+
* agent actuates with are the ones crystallized (record==replay).
|
|
56
|
+
*/
|
|
57
|
+
export function buildGroundedMcpConfig(opts) {
|
|
58
|
+
return resolveMcpConfig({
|
|
59
|
+
cdpUrl: opts.cdpUrl,
|
|
60
|
+
port: opts.port,
|
|
61
|
+
cwd: opts.devRoot,
|
|
62
|
+
outputDir: opts.outputDir,
|
|
63
|
+
extra: [
|
|
64
|
+
{
|
|
65
|
+
id: CONTROL_MCP_ID,
|
|
66
|
+
command: process.execPath,
|
|
67
|
+
args: [CONTROL_MCP_SCRIPT],
|
|
68
|
+
env: {
|
|
69
|
+
HOVER_CDP_URL: opts.cdpUrl,
|
|
70
|
+
HOVER_DEV_URL: opts.devUrl ?? opts.cdpUrl,
|
|
71
|
+
HOVER_PROJECT_ROOT: opts.devRoot,
|
|
72
|
+
...(opts.approvalPort ? { HOVER_APPROVAL_PORT: String(opts.approvalPort) } : {}),
|
|
73
|
+
...(opts.outputDir ? { HOVER_SHOT_DIR: opts.outputDir } : {}),
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actuateServer.d.ts","sourceRoot":"","sources":["../../src/mcp/actuateServer.ts"],"names":[],"mappings":""}
|