@hover-dev/core 0.2.0 → 0.2.3
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/agents/claude.d.ts.map +1 -1
- package/dist/agents/claude.js +25 -17
- package/dist/agents/codex.d.ts +19 -0
- package/dist/agents/codex.d.ts.map +1 -0
- package/dist/agents/codex.js +210 -0
- package/dist/agents/detect.d.ts +27 -1
- package/dist/agents/detect.d.ts.map +1 -1
- package/dist/agents/detect.js +46 -3
- package/dist/agents/invoke.d.ts.map +1 -1
- package/dist/agents/invoke.js +21 -7
- package/dist/agents/registry.d.ts +10 -5
- package/dist/agents/registry.d.ts.map +1 -1
- package/dist/agents/registry.js +14 -5
- package/dist/agents/types.d.ts +71 -1
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/playwright/cdpStatus.d.ts.map +1 -1
- package/dist/playwright/cdpStatus.js +32 -9
- package/dist/playwright/raiseWindow.d.ts +10 -0
- package/dist/playwright/raiseWindow.d.ts.map +1 -0
- package/dist/playwright/raiseWindow.js +124 -0
- package/dist/service/cdpHandlers.d.ts +39 -0
- package/dist/service/cdpHandlers.d.ts.map +1 -0
- package/dist/service/cdpHandlers.js +82 -0
- package/dist/service/cdpHint.d.ts +20 -0
- package/dist/service/cdpHint.d.ts.map +1 -0
- package/dist/service/cdpHint.js +86 -0
- package/dist/service/saveHandlers.d.ts +55 -0
- package/dist/service/saveHandlers.d.ts.map +1 -0
- package/dist/service/saveHandlers.js +80 -0
- package/dist/service/types.d.ts +41 -0
- package/dist/service/types.d.ts.map +1 -0
- package/dist/service/types.js +14 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +141 -235
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ pnpm smoke http://localhost:5173/ "log in then add a todo named 'verify hover'"
|
|
|
43
43
|
Environment variables:
|
|
44
44
|
|
|
45
45
|
- `HOVER_CDP` — CDP URL (default `http://localhost:9222`)
|
|
46
|
-
- `HOVER_AGENT` — agent id (
|
|
46
|
+
- `HOVER_AGENT` — agent id (omit to auto-detect; tries the user's stated preference, then the first installed agent in registry order — `claude` → `codex` today)
|
|
47
47
|
- `HOVER_MODEL` — model for the agent (default `sonnet`, much cheaper than opus)
|
|
48
48
|
|
|
49
49
|
## Sandboxing (what the smoke test enforces)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAA2C,MAAM,YAAY,CAAC;AAsF3F,eAAO,MAAM,WAAW,EAAE,eAoHzB,CAAC"}
|
package/dist/agents/claude.js
CHANGED
|
@@ -30,20 +30,27 @@ function estimateCostUsd(modelHint, usage) {
|
|
|
30
30
|
(usage.cache_creation_input_tokens ?? 0) * tier.cacheCreate +
|
|
31
31
|
(usage.cache_read_input_tokens ?? 0) * tier.cacheRead) / 1_000_000;
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
function claudeState(state) {
|
|
34
|
+
// First touch on this state object — seed the keys we read below.
|
|
35
|
+
if (typeof state.runningCost !== 'number') {
|
|
36
|
+
state.runningCost = 0;
|
|
37
|
+
state.runningTurns = 0;
|
|
38
|
+
state.runningModel = undefined;
|
|
39
|
+
}
|
|
40
|
+
return state;
|
|
41
|
+
}
|
|
42
42
|
export const claudeAgent = {
|
|
43
43
|
id: 'claude',
|
|
44
44
|
binName: 'claude',
|
|
45
45
|
protocol: 'argv',
|
|
46
46
|
streamFormat: 'stream-json',
|
|
47
|
+
sandboxStrength: 'hard',
|
|
48
|
+
display: {
|
|
49
|
+
label: 'Claude Code',
|
|
50
|
+
tagline: 'Anthropic — best-in-class browser driving, hard tool sandbox',
|
|
51
|
+
homepage: 'https://docs.claude.com/claude-code',
|
|
52
|
+
installHint: 'npm install -g @anthropic-ai/claude-code',
|
|
53
|
+
},
|
|
47
54
|
buildArgs(opts) {
|
|
48
55
|
const args = ['-p', opts.prompt];
|
|
49
56
|
args.push('--output-format', 'stream-json', '--verbose');
|
|
@@ -71,7 +78,7 @@ export const claudeAgent = {
|
|
|
71
78
|
}
|
|
72
79
|
return args;
|
|
73
80
|
},
|
|
74
|
-
parseEvent(line) {
|
|
81
|
+
parseEvent(line, state = {}) {
|
|
75
82
|
if (!line.trim())
|
|
76
83
|
return [];
|
|
77
84
|
let ev;
|
|
@@ -81,12 +88,13 @@ export const claudeAgent = {
|
|
|
81
88
|
catch {
|
|
82
89
|
return [{ kind: 'raw', line }];
|
|
83
90
|
}
|
|
91
|
+
const s = claudeState(state);
|
|
84
92
|
const out = [];
|
|
85
93
|
if (ev.type === 'system' && ev.subtype === 'init') {
|
|
86
94
|
// Fresh session — reset the cost/turn accumulator.
|
|
87
|
-
runningCost = 0;
|
|
88
|
-
runningTurns = 0;
|
|
89
|
-
runningModel = ev.model;
|
|
95
|
+
s.runningCost = 0;
|
|
96
|
+
s.runningTurns = 0;
|
|
97
|
+
s.runningModel = ev.model;
|
|
90
98
|
if (ev.session_id) {
|
|
91
99
|
out.push({ kind: 'session_start', sessionId: ev.session_id, model: ev.model });
|
|
92
100
|
}
|
|
@@ -96,18 +104,18 @@ export const claudeAgent = {
|
|
|
96
104
|
return out;
|
|
97
105
|
}
|
|
98
106
|
if (ev.type === 'assistant') {
|
|
99
|
-
runningTurns += 1;
|
|
107
|
+
s.runningTurns += 1;
|
|
100
108
|
// Claude Code sometimes carries `total_cost_usd` on intermediate events;
|
|
101
109
|
// when present it's authoritative (server-computed, includes anything
|
|
102
110
|
// we'd miss). When absent, estimate from this turn's usage so the widget
|
|
103
111
|
// still shows a growing $ counter on long runs.
|
|
104
112
|
if (typeof ev.total_cost_usd === 'number') {
|
|
105
|
-
runningCost = ev.total_cost_usd;
|
|
113
|
+
s.runningCost = ev.total_cost_usd;
|
|
106
114
|
}
|
|
107
115
|
else if (ev.message?.usage) {
|
|
108
|
-
runningCost += estimateCostUsd(runningModel ?? ev.message.model, ev.message.usage);
|
|
116
|
+
s.runningCost += estimateCostUsd(s.runningModel ?? ev.message.model, ev.message.usage);
|
|
109
117
|
}
|
|
110
|
-
out.push({ kind: 'usage', costUsd: runningCost, turns: runningTurns });
|
|
118
|
+
out.push({ kind: 'usage', costUsd: s.runningCost, turns: s.runningTurns });
|
|
111
119
|
for (const block of ev.message?.content ?? []) {
|
|
112
120
|
if (block.type === 'tool_use') {
|
|
113
121
|
const name = block.name ?? '';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AgentDescriptor, ParserState } from './types.js';
|
|
2
|
+
export declare const codexAgent: AgentDescriptor;
|
|
3
|
+
/**
|
|
4
|
+
* Test-only escape hatches. Tests pass a state object in and get the
|
|
5
|
+
* accumulated counters back — same shape as the parser sees during a real
|
|
6
|
+
* invocation, just driven by the test instead of by invokeAgent.
|
|
7
|
+
*/
|
|
8
|
+
export declare const __testing: {
|
|
9
|
+
freshState: () => ParserState;
|
|
10
|
+
resetCounters: (state: ParserState) => void;
|
|
11
|
+
getState: (state: ParserState) => {
|
|
12
|
+
runningCost: number;
|
|
13
|
+
runningTurns: number;
|
|
14
|
+
runningSessionId: string | undefined;
|
|
15
|
+
lastAgentMessage: string | undefined;
|
|
16
|
+
sawErrorEvent: boolean;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=codex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAA8B,WAAW,EAAE,MAAM,YAAY,CAAC;AAmK3F,eAAO,MAAM,UAAU,EAAE,eAyJxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS;sBACJ,WAAW;2BACJ,WAAW;sBAChB,WAAW;;;;;;;CAU9B,CAAC"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pricing per million tokens. Keep in lockstep with claude.ts's table —
|
|
3
|
+
* approximate published OpenAI rates as of 2026. We are deliberately
|
|
4
|
+
* conservative (no cache-hit discount); cost shown to the user is therefore
|
|
5
|
+
* a high-water estimate, which is the right error direction for a "should
|
|
6
|
+
* I hit Stop now" UI signal.
|
|
7
|
+
*/
|
|
8
|
+
const PRICE_PER_M_USD = {
|
|
9
|
+
// gpt-5.5 / gpt-5.4 / gpt-5 — public per-million pricing is similar to
|
|
10
|
+
// claude opus; tune empirically when OpenAI publishes a stable price table
|
|
11
|
+
// for the Codex tier specifically.
|
|
12
|
+
'gpt-5.5': { in: 5, out: 25 },
|
|
13
|
+
'gpt-5.4': { in: 5, out: 25 },
|
|
14
|
+
'gpt-5': { in: 5, out: 25 },
|
|
15
|
+
// gpt-4.x kept for users on legacy --model
|
|
16
|
+
'gpt-4o': { in: 2.5, out: 10 },
|
|
17
|
+
'gpt-4': { in: 30, out: 60 },
|
|
18
|
+
};
|
|
19
|
+
function estimateCostUsd(modelHint, usage) {
|
|
20
|
+
const m = (modelHint ?? 'gpt-5.5').toLowerCase();
|
|
21
|
+
// Match by longest-prefix so 'gpt-5.5-mini' picks up the 'gpt-5.5' tier.
|
|
22
|
+
const tier = Object.entries(PRICE_PER_M_USD).find(([key]) => m.startsWith(key))?.[1] ??
|
|
23
|
+
PRICE_PER_M_USD['gpt-5.5'];
|
|
24
|
+
return ((usage.input_tokens ?? 0) * tier.in +
|
|
25
|
+
(usage.output_tokens ?? 0) * tier.out) / 1_000_000;
|
|
26
|
+
}
|
|
27
|
+
function codexState(state) {
|
|
28
|
+
if (typeof state.runningCost !== 'number') {
|
|
29
|
+
state.runningCost = 0;
|
|
30
|
+
state.runningTurns = 0;
|
|
31
|
+
state.runningModel = undefined;
|
|
32
|
+
state.runningSessionId = undefined;
|
|
33
|
+
state.lastAgentMessage = undefined;
|
|
34
|
+
state.sawErrorEvent = false;
|
|
35
|
+
state.itemTypeById = new Map();
|
|
36
|
+
}
|
|
37
|
+
return state;
|
|
38
|
+
}
|
|
39
|
+
function resetCodexCounters(s) {
|
|
40
|
+
s.runningCost = 0;
|
|
41
|
+
s.runningTurns = 0;
|
|
42
|
+
s.runningModel = undefined;
|
|
43
|
+
s.runningSessionId = undefined;
|
|
44
|
+
s.lastAgentMessage = undefined;
|
|
45
|
+
s.sawErrorEvent = false;
|
|
46
|
+
s.itemTypeById.clear();
|
|
47
|
+
}
|
|
48
|
+
/** Cap surfaced as a constraint in the system prompt — codex has no CLI flag. */
|
|
49
|
+
const CODEX_DEVELOPER_INSTRUCTIONS = [
|
|
50
|
+
'You are operating in Hover, a browser-testing tool.',
|
|
51
|
+
'Use ONLY the MCP playwright tools (prefixed `mcp__playwright__` / `mcp__hover-playwright__`) to drive the browser.',
|
|
52
|
+
'Do NOT call shell, file-edit, web-search, or any other built-in tool.',
|
|
53
|
+
'Do NOT navigate to a URL the user is already on; check the page state via `browser_snapshot` first.',
|
|
54
|
+
'When the task is complete, emit a short agent_message summary and stop.',
|
|
55
|
+
].join(' ');
|
|
56
|
+
export const codexAgent = {
|
|
57
|
+
id: 'codex',
|
|
58
|
+
binName: 'codex',
|
|
59
|
+
protocol: 'argv',
|
|
60
|
+
streamFormat: 'json-lines',
|
|
61
|
+
sandboxStrength: 'soft',
|
|
62
|
+
display: {
|
|
63
|
+
label: 'OpenAI Codex',
|
|
64
|
+
tagline: 'OpenAI — soft sandbox (no built-in tool deny-list)',
|
|
65
|
+
homepage: 'https://developers.openai.com/codex',
|
|
66
|
+
installHint: 'npm install -g @openai/codex',
|
|
67
|
+
},
|
|
68
|
+
buildArgs(opts) {
|
|
69
|
+
const args = ['exec'];
|
|
70
|
+
// Resume must come BEFORE the prompt positional. `codex exec resume <id>
|
|
71
|
+
// [prompt]` is the documented shape.
|
|
72
|
+
if (opts.sessionId) {
|
|
73
|
+
args.push('resume', opts.sessionId);
|
|
74
|
+
}
|
|
75
|
+
args.push(opts.prompt);
|
|
76
|
+
// JSONL streaming output.
|
|
77
|
+
args.push('--json');
|
|
78
|
+
// Never prompt for approval in headless mode.
|
|
79
|
+
args.push('--ask-for-approval', 'never');
|
|
80
|
+
// Soft sandbox: prevent shell side-effects on disk / network even when
|
|
81
|
+
// the agent tries to call its built-in shell. read-only is the strictest
|
|
82
|
+
// documented level.
|
|
83
|
+
args.push('--sandbox', 'read-only');
|
|
84
|
+
if (opts.model) {
|
|
85
|
+
args.push('--model', opts.model);
|
|
86
|
+
}
|
|
87
|
+
// System-prompt injection. Codex has no --append-system-prompt; we route
|
|
88
|
+
// through `-c developer_instructions='...'`. Concatenate the standing
|
|
89
|
+
// Hover-mode instructions with whatever the caller passes (e.g. "user is
|
|
90
|
+
// already on http://localhost:5173/").
|
|
91
|
+
const sysPrompt = opts.appendSystemPrompt && opts.appendSystemPrompt.trim().length > 0
|
|
92
|
+
? `${CODEX_DEVELOPER_INSTRUCTIONS} ${opts.appendSystemPrompt}`
|
|
93
|
+
: CODEX_DEVELOPER_INSTRUCTIONS;
|
|
94
|
+
args.push('-c', `developer_instructions=${JSON.stringify(sysPrompt)}`);
|
|
95
|
+
// MCP servers are configured in ~/.codex/config.toml at install time,
|
|
96
|
+
// not per-invocation. If the user passed an mcpConfig path, we don't
|
|
97
|
+
// have a way to forward it to codex — log a warning to stderr from the
|
|
98
|
+
// invoker so the user knows. (See invoke.ts wiring.)
|
|
99
|
+
// No equivalent for --max-budget-usd or --allowedTools.
|
|
100
|
+
return args;
|
|
101
|
+
},
|
|
102
|
+
parseEvent(line, state = {}) {
|
|
103
|
+
if (!line.trim())
|
|
104
|
+
return [];
|
|
105
|
+
let ev;
|
|
106
|
+
try {
|
|
107
|
+
ev = JSON.parse(line);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return [{ kind: 'raw', line }];
|
|
111
|
+
}
|
|
112
|
+
const s = codexState(state);
|
|
113
|
+
const out = [];
|
|
114
|
+
if (ev.type === 'thread.started') {
|
|
115
|
+
resetCodexCounters(s);
|
|
116
|
+
if (ev.thread_id) {
|
|
117
|
+
s.runningSessionId = ev.thread_id;
|
|
118
|
+
out.push({ kind: 'session_start', sessionId: ev.thread_id, model: ev.model });
|
|
119
|
+
}
|
|
120
|
+
return out;
|
|
121
|
+
}
|
|
122
|
+
if (ev.type === 'item.started' && ev.item) {
|
|
123
|
+
const it = ev.item;
|
|
124
|
+
if (it.id && it.type)
|
|
125
|
+
s.itemTypeById.set(it.id, it.type);
|
|
126
|
+
if (it.type === 'mcp_tool_call') {
|
|
127
|
+
// The exact field names aren't published. Read defensively: prefer
|
|
128
|
+
// `name`, fall back to `tool`. Same for input.
|
|
129
|
+
const rawName = it.name ?? it.tool ?? '';
|
|
130
|
+
const tool = rawName.replace(/^mcp__playwright__/, '').replace(/^mcp__hover-playwright__/, '');
|
|
131
|
+
out.push({ kind: 'tool_use', tool, input: it.input ?? it.arguments });
|
|
132
|
+
}
|
|
133
|
+
else if (it.type === 'command_execution') {
|
|
134
|
+
// We DISCOURAGED this in developer_instructions but the agent can
|
|
135
|
+
// still try. Surface it so the user sees it happen.
|
|
136
|
+
out.push({ kind: 'tool_use', tool: 'shell', input: { command: it.command } });
|
|
137
|
+
}
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
if (ev.type === 'item.completed' && ev.item) {
|
|
141
|
+
const it = ev.item;
|
|
142
|
+
const recordedType = (it.id && s.itemTypeById.get(it.id)) || it.type;
|
|
143
|
+
if (recordedType === 'agent_message') {
|
|
144
|
+
const text = it.text?.trim();
|
|
145
|
+
if (text) {
|
|
146
|
+
s.lastAgentMessage = text;
|
|
147
|
+
out.push({ kind: 'text', text });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else if (recordedType === 'mcp_tool_call' || recordedType === 'command_execution') {
|
|
151
|
+
const isError = it.is_error === true ||
|
|
152
|
+
(typeof it.status === 'string' && /error|fail/i.test(it.status));
|
|
153
|
+
out.push({ kind: 'tool_result', isError });
|
|
154
|
+
}
|
|
155
|
+
return out;
|
|
156
|
+
}
|
|
157
|
+
if (ev.type === 'turn.completed') {
|
|
158
|
+
s.runningTurns += 1;
|
|
159
|
+
if (ev.usage) {
|
|
160
|
+
s.runningCost += estimateCostUsd(s.runningModel, ev.usage);
|
|
161
|
+
}
|
|
162
|
+
out.push({ kind: 'usage', costUsd: s.runningCost, turns: s.runningTurns });
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
// Codex emits various error envelopes; we conservatively match anything
|
|
166
|
+
// whose `type` contains 'error' or carries a top-level message string.
|
|
167
|
+
if (ev.type && /error/i.test(ev.type)) {
|
|
168
|
+
s.sawErrorEvent = true;
|
|
169
|
+
if (ev.message) {
|
|
170
|
+
out.push({ kind: 'text', text: `[codex] ${ev.message}` });
|
|
171
|
+
}
|
|
172
|
+
return out;
|
|
173
|
+
}
|
|
174
|
+
return [];
|
|
175
|
+
},
|
|
176
|
+
/**
|
|
177
|
+
* Codex doesn't emit a `session_end` line — the child process simply
|
|
178
|
+
* exits after the final `turn.completed`. We synthesize the terminator
|
|
179
|
+
* here so the widget sees the same shape it sees from claude.
|
|
180
|
+
*/
|
|
181
|
+
onStreamEnd(exitCode, state = {}) {
|
|
182
|
+
const s = codexState(state);
|
|
183
|
+
return {
|
|
184
|
+
kind: 'session_end',
|
|
185
|
+
turns: s.runningTurns,
|
|
186
|
+
costUsd: s.runningCost,
|
|
187
|
+
isError: s.sawErrorEvent || (exitCode != null && exitCode !== 0),
|
|
188
|
+
summary: s.lastAgentMessage,
|
|
189
|
+
};
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* Test-only escape hatches. Tests pass a state object in and get the
|
|
194
|
+
* accumulated counters back — same shape as the parser sees during a real
|
|
195
|
+
* invocation, just driven by the test instead of by invokeAgent.
|
|
196
|
+
*/
|
|
197
|
+
export const __testing = {
|
|
198
|
+
freshState: () => ({}),
|
|
199
|
+
resetCounters: (state) => resetCodexCounters(codexState(state)),
|
|
200
|
+
getState: (state) => {
|
|
201
|
+
const s = codexState(state);
|
|
202
|
+
return {
|
|
203
|
+
runningCost: s.runningCost,
|
|
204
|
+
runningTurns: s.runningTurns,
|
|
205
|
+
runningSessionId: s.runningSessionId,
|
|
206
|
+
lastAgentMessage: s.lastAgentMessage,
|
|
207
|
+
sawErrorEvent: s.sawErrorEvent,
|
|
208
|
+
};
|
|
209
|
+
},
|
|
210
|
+
};
|
package/dist/agents/detect.d.ts
CHANGED
|
@@ -10,7 +10,33 @@ export interface DetectedAgent {
|
|
|
10
10
|
binPath: string;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
* Scan PATH for every agent in the registry. Returns only the ones found
|
|
13
|
+
* Scan PATH for every agent in the registry. Returns only the ones found,
|
|
14
|
+
* in registry insertion order.
|
|
14
15
|
*/
|
|
15
16
|
export declare function detectAgents(): Promise<DetectedAgent[]>;
|
|
17
|
+
export interface AgentAvailability {
|
|
18
|
+
id: string;
|
|
19
|
+
label: string;
|
|
20
|
+
tagline?: string;
|
|
21
|
+
sandboxStrength: 'hard' | 'soft';
|
|
22
|
+
installed: boolean;
|
|
23
|
+
binPath?: string;
|
|
24
|
+
homepage?: string;
|
|
25
|
+
installHint?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Like `detectAgents`, but also includes registered-but-not-installed agents
|
|
29
|
+
* so the widget can render them dimmed with an install hint. Order matches
|
|
30
|
+
* the registry.
|
|
31
|
+
*/
|
|
32
|
+
export declare function listAgentAvailability(): Promise<AgentAvailability[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Pick the agent we should default to when the user / Vite plugin didn't
|
|
35
|
+
* specify one. Prefer the explicit hint if it's installed; otherwise the
|
|
36
|
+
* first registered agent that's installed; finally null if nothing matches.
|
|
37
|
+
*
|
|
38
|
+
* `preferredId` is typically `process.env.HOVER_AGENT` or the value the user
|
|
39
|
+
* picked in the widget last session (persisted by the widget to localStorage).
|
|
40
|
+
*/
|
|
41
|
+
export declare function pickPrimaryAgent(preferredId?: string): Promise<DetectedAgent | null>;
|
|
16
42
|
//# sourceMappingURL=detect.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/agents/detect.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAIlD;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAS3E;AAED,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE5F;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/agents/detect.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAIlD;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAS3E;AAED,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE5F;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAO7D;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAgB1E;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAU1F"}
|
package/dist/agents/detect.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
2
|
import { promisify } from 'node:util';
|
|
3
|
-
import { AGENTS } from './registry.js';
|
|
3
|
+
import { AGENTS, listAgents } from './registry.js';
|
|
4
4
|
const execFileAsync = promisify(execFile);
|
|
5
5
|
/**
|
|
6
6
|
* Find a binary on PATH. Returns absolute path or null.
|
|
@@ -21,14 +21,57 @@ export async function resolveBinForAgent(descriptor) {
|
|
|
21
21
|
return resolveOnPath(descriptor.binName);
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
|
-
* Scan PATH for every agent in the registry. Returns only the ones found
|
|
24
|
+
* Scan PATH for every agent in the registry. Returns only the ones found,
|
|
25
|
+
* in registry insertion order.
|
|
25
26
|
*/
|
|
26
27
|
export async function detectAgents() {
|
|
27
28
|
const detected = [];
|
|
28
|
-
for (const descriptor of
|
|
29
|
+
for (const descriptor of listAgents()) {
|
|
29
30
|
const binPath = await resolveBinForAgent(descriptor);
|
|
30
31
|
if (binPath)
|
|
31
32
|
detected.push({ descriptor, binPath });
|
|
32
33
|
}
|
|
33
34
|
return detected;
|
|
34
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Like `detectAgents`, but also includes registered-but-not-installed agents
|
|
38
|
+
* so the widget can render them dimmed with an install hint. Order matches
|
|
39
|
+
* the registry.
|
|
40
|
+
*/
|
|
41
|
+
export async function listAgentAvailability() {
|
|
42
|
+
const result = [];
|
|
43
|
+
for (const descriptor of listAgents()) {
|
|
44
|
+
const binPath = await resolveBinForAgent(descriptor);
|
|
45
|
+
result.push({
|
|
46
|
+
id: descriptor.id,
|
|
47
|
+
label: descriptor.display.label,
|
|
48
|
+
tagline: descriptor.display.tagline,
|
|
49
|
+
sandboxStrength: descriptor.sandboxStrength,
|
|
50
|
+
installed: binPath != null,
|
|
51
|
+
binPath: binPath ?? undefined,
|
|
52
|
+
homepage: descriptor.display.homepage,
|
|
53
|
+
installHint: descriptor.display.installHint,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Pick the agent we should default to when the user / Vite plugin didn't
|
|
60
|
+
* specify one. Prefer the explicit hint if it's installed; otherwise the
|
|
61
|
+
* first registered agent that's installed; finally null if nothing matches.
|
|
62
|
+
*
|
|
63
|
+
* `preferredId` is typically `process.env.HOVER_AGENT` or the value the user
|
|
64
|
+
* picked in the widget last session (persisted by the widget to localStorage).
|
|
65
|
+
*/
|
|
66
|
+
export async function pickPrimaryAgent(preferredId) {
|
|
67
|
+
if (preferredId) {
|
|
68
|
+
const descriptor = AGENTS[preferredId];
|
|
69
|
+
if (descriptor) {
|
|
70
|
+
const binPath = await resolveBinForAgent(descriptor);
|
|
71
|
+
if (binPath)
|
|
72
|
+
return { descriptor, binPath };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const detected = await detectAgents();
|
|
76
|
+
return detected[0] ?? null;
|
|
77
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invoke.d.ts","sourceRoot":"","sources":["../../src/agents/invoke.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,
|
|
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;;;;;;GAMG;AACH,wBAAuB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,CAAC,WAAW,CAAC,CAuElF"}
|
package/dist/agents/invoke.js
CHANGED
|
@@ -50,9 +50,13 @@ export async function* invokeAgent(opts) {
|
|
|
50
50
|
}
|
|
51
51
|
const rl = createInterface({ input: child.stdout });
|
|
52
52
|
const exitPromise = new Promise(res => child.on('exit', c => res(c ?? -1)));
|
|
53
|
+
// Fresh parser state per invocation. Threaded into both parseEvent and
|
|
54
|
+
// onStreamEnd so descriptors don't have to reach for module globals
|
|
55
|
+
// (which would smear across concurrent invocations).
|
|
56
|
+
const state = {};
|
|
53
57
|
let sawSessionEnd = false;
|
|
54
58
|
for await (const line of rl) {
|
|
55
|
-
for (const ev of descriptor.parseEvent(line)) {
|
|
59
|
+
for (const ev of descriptor.parseEvent(line, state)) {
|
|
56
60
|
if (ev.kind === 'session_end')
|
|
57
61
|
sawSessionEnd = true;
|
|
58
62
|
yield ev;
|
|
@@ -60,11 +64,21 @@ export async function* invokeAgent(opts) {
|
|
|
60
64
|
}
|
|
61
65
|
const code = await exitPromise;
|
|
62
66
|
opts.signal?.removeEventListener('abort', onAbort);
|
|
63
|
-
if (!sawSessionEnd &&
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
if (!sawSessionEnd && !opts.signal?.aborted) {
|
|
68
|
+
// Give the descriptor a chance to synthesize its own terminator from
|
|
69
|
+
// accumulated state (codex does this — its stream never emits a
|
|
70
|
+
// session_end). Falls back to a generic error session_end if the
|
|
71
|
+
// descriptor declines and the child exited non-zero.
|
|
72
|
+
const synthetic = descriptor.onStreamEnd?.(code, state);
|
|
73
|
+
if (synthetic) {
|
|
74
|
+
yield synthetic;
|
|
75
|
+
}
|
|
76
|
+
else if (code !== 0) {
|
|
77
|
+
yield {
|
|
78
|
+
kind: 'session_end',
|
|
79
|
+
isError: true,
|
|
80
|
+
summary: `agent exited with code ${code}`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
69
83
|
}
|
|
70
84
|
}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import type { AgentDescriptor } from './types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Registry of agents Hover can drive.
|
|
3
|
+
* Registry of agents Hover can drive.
|
|
4
4
|
*
|
|
5
|
-
* To add support for another agent (e.g.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* To add support for another agent (e.g. cursor-agent, aider, gemini, cline,
|
|
6
|
+
* continue, qwen, kilo), implement its AgentDescriptor in its own file and
|
|
7
|
+
* register it here. The rest of the system — detect, argv, invoke, service,
|
|
8
|
+
* widget — works without further changes.
|
|
9
|
+
*
|
|
10
|
+
* Insertion order is the order shown in the widget's agent dropdown, so put
|
|
11
|
+
* the recommended primary first.
|
|
9
12
|
*/
|
|
10
13
|
export declare const AGENTS: Record<string, AgentDescriptor>;
|
|
11
14
|
export declare function getAgent(id: string): AgentDescriptor | undefined;
|
|
15
|
+
/** Stable, insertion-ordered list of all registered agents. */
|
|
16
|
+
export declare function listAgents(): AgentDescriptor[];
|
|
12
17
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -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;AAIlD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAGlD,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,15 +1,24 @@
|
|
|
1
1
|
import { claudeAgent } from './claude.js';
|
|
2
|
+
import { codexAgent } from './codex.js';
|
|
2
3
|
/**
|
|
3
|
-
* Registry of agents Hover can drive.
|
|
4
|
+
* Registry of agents Hover can drive.
|
|
4
5
|
*
|
|
5
|
-
* To add support for another agent (e.g.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* To add support for another agent (e.g. cursor-agent, aider, gemini, cline,
|
|
7
|
+
* continue, qwen, kilo), implement its AgentDescriptor in its own file and
|
|
8
|
+
* register it here. The rest of the system — detect, argv, invoke, service,
|
|
9
|
+
* widget — works without further changes.
|
|
10
|
+
*
|
|
11
|
+
* Insertion order is the order shown in the widget's agent dropdown, so put
|
|
12
|
+
* the recommended primary first.
|
|
9
13
|
*/
|
|
10
14
|
export const AGENTS = {
|
|
11
15
|
[claudeAgent.id]: claudeAgent,
|
|
16
|
+
[codexAgent.id]: codexAgent,
|
|
12
17
|
};
|
|
13
18
|
export function getAgent(id) {
|
|
14
19
|
return AGENTS[id];
|
|
15
20
|
}
|
|
21
|
+
/** Stable, insertion-ordered list of all registered agents. */
|
|
22
|
+
export function listAgents() {
|
|
23
|
+
return Object.values(AGENTS);
|
|
24
|
+
}
|
package/dist/agents/types.d.ts
CHANGED
|
@@ -77,12 +77,82 @@ export type InvokeEvent = {
|
|
|
77
77
|
kind: 'raw';
|
|
78
78
|
line: string;
|
|
79
79
|
};
|
|
80
|
+
/**
|
|
81
|
+
* How tightly the agent's tool surface can be locked down per invocation.
|
|
82
|
+
*
|
|
83
|
+
* 'hard' — the agent CLI accepts a deny-list / allow-list that effectively
|
|
84
|
+
* removes built-in tools (shell, file edit, etc.) so the only
|
|
85
|
+
* callable surface is whatever MCP servers we configure. Claude
|
|
86
|
+
* Code's `--strict-mcp-config` + `--allowedTools mcp__playwright`
|
|
87
|
+
* + `--disallowedTools <every built-in>` is the canonical example.
|
|
88
|
+
*
|
|
89
|
+
* 'soft' — the agent CLI does not expose a way to disable its built-in
|
|
90
|
+
* tools (shell, fs). We can constrain side-effects via OS-level
|
|
91
|
+
* sandbox flags (e.g. codex's `--sandbox read-only`) and we lean
|
|
92
|
+
* on a strict `developer_instructions` system-prompt to nudge the
|
|
93
|
+
* agent toward MCP-only behavior, but a determined / hallucinating
|
|
94
|
+
* agent COULD still try a built-in shell call. The widget should
|
|
95
|
+
* mark this agent with a warning indicator.
|
|
96
|
+
*/
|
|
97
|
+
export type SandboxStrength = 'hard' | 'soft';
|
|
98
|
+
/**
|
|
99
|
+
* Human-facing metadata for the widget's agent picker. None of these affect
|
|
100
|
+
* agent invocation — they only shape how the agent is presented in the UI.
|
|
101
|
+
*/
|
|
102
|
+
export interface AgentDisplay {
|
|
103
|
+
/** Pretty name for the dropdown ("Claude Code", "OpenAI Codex"). */
|
|
104
|
+
label: string;
|
|
105
|
+
/** One-line tagline shown under the label. */
|
|
106
|
+
tagline?: string;
|
|
107
|
+
/** Vendor / source URL — clicking the agent name in the widget can open
|
|
108
|
+
* this in a new tab when the agent isn't installed. */
|
|
109
|
+
homepage?: string;
|
|
110
|
+
/** Shell command the user can run to install (copy-paste from a tooltip
|
|
111
|
+
* in the widget when the agent is listed but not on PATH). */
|
|
112
|
+
installHint?: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Per-invocation parser state. A fresh object is created by `invokeAgent`
|
|
116
|
+
* for each spawn and passed to both `parseEvent` and `onStreamEnd`.
|
|
117
|
+
*
|
|
118
|
+
* Descriptors that need to accumulate state across lines (cost, turn count,
|
|
119
|
+
* last agent message for synthesized session_end, etc.) read and write
|
|
120
|
+
* their own keys on this object. There is no shared shape — each agent
|
|
121
|
+
* uses whatever fields it needs.
|
|
122
|
+
*
|
|
123
|
+
* Why: module-level state in claude.ts / codex.ts worked only because the
|
|
124
|
+
* service enforces one in-flight invocation per Node process. Two concurrent
|
|
125
|
+
* agent runs (future: tests in parallel, in-process workers) would silently
|
|
126
|
+
* smear their cost accumulators together. Threading the state object per
|
|
127
|
+
* invocation removes that hazard at zero runtime cost.
|
|
128
|
+
*/
|
|
129
|
+
export type ParserState = Record<string, unknown>;
|
|
80
130
|
export interface AgentDescriptor {
|
|
81
131
|
id: string;
|
|
82
132
|
binName: string;
|
|
83
133
|
protocol: AgentProtocol;
|
|
84
134
|
streamFormat: StreamFormat;
|
|
135
|
+
sandboxStrength: SandboxStrength;
|
|
136
|
+
display: AgentDisplay;
|
|
85
137
|
buildArgs(opts: InvokeOptions): string[];
|
|
86
|
-
|
|
138
|
+
/**
|
|
139
|
+
* Parse a single line of agent stdout into normalised InvokeEvents.
|
|
140
|
+
* `state` is a per-invocation scratch pad (see ParserState). Optional
|
|
141
|
+
* for callers that don't accumulate across lines (and for unit tests
|
|
142
|
+
* that don't care about cost / turn carry-over) — descriptors that
|
|
143
|
+
* DO accumulate must check / initialise the state object themselves.
|
|
144
|
+
*/
|
|
145
|
+
parseEvent(line: string, state?: ParserState): InvokeEvent[];
|
|
146
|
+
/**
|
|
147
|
+
* Optional. Called once after the agent's stream closes, with the child's
|
|
148
|
+
* exit code (or null if it was aborted). Lets agents whose protocol does
|
|
149
|
+
* NOT emit an explicit session-terminating event synthesize one from
|
|
150
|
+
* accumulated parser state. Returns `null` if the agent's own `parseEvent`
|
|
151
|
+
* already emitted a `session_end` and nothing further is needed.
|
|
152
|
+
*
|
|
153
|
+
* Used by codex.ts (no native session_end). Claude does not implement
|
|
154
|
+
* this — `result` events terminate naturally.
|
|
155
|
+
*/
|
|
156
|
+
onStreamEnd?(exitCode: number | null, state?: ParserState): InvokeEvent | null;
|
|
87
157
|
}
|
|
88
158
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -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;6EACyE;IACzE,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAChC;;;qEAGqE;GACnE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9F;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,aAAa,CAAC;IACxB,YAAY,EAAE,YAAY,CAAC;IAC3B,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,EAAE,CAAC;IACzC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cdpStatus.d.ts","sourceRoot":"","sources":["../../src/playwright/cdpStatus.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cdpStatus.d.ts","sourceRoot":"","sources":["../../src/playwright/cdpStatus.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,QAAQ,GAAG,aAAa,GAAG,cAAc,GAAG,QAAQ,CAAC;AAEjE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,QAAQ,CAAC;IAChB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAeD,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,CAAC,CA4B1B;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA8C3E"}
|