@hover-dev/core 0.2.3 → 0.3.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/dist/agents/claude.d.ts.map +1 -1
- package/dist/agents/claude.js +6 -1
- package/dist/agents/codex.js +2 -2
- package/dist/agents/detect.d.ts +5 -1
- package/dist/agents/detect.d.ts.map +1 -1
- package/dist/agents/detect.js +18 -15
- package/dist/agents/invoke.d.ts +5 -3
- package/dist/agents/invoke.d.ts.map +1 -1
- package/dist/agents/invoke.js +35 -32
- package/dist/agents/types.d.ts +1 -0
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/playwright/launchChrome.d.ts.map +1 -1
- package/dist/playwright/launchChrome.js +5 -2
- package/dist/playwright/preflight.d.ts.map +1 -1
- package/dist/playwright/preflight.js +8 -2
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +38 -1
- package/dist/skills/writeSkill.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,eAyHzB,CAAC"}
|
package/dist/agents/claude.js
CHANGED
|
@@ -120,7 +120,12 @@ export const claudeAgent = {
|
|
|
120
120
|
if (block.type === 'tool_use') {
|
|
121
121
|
const name = block.name ?? '';
|
|
122
122
|
const tool = name.replace(/^mcp__playwright__/, '');
|
|
123
|
-
out.push({
|
|
123
|
+
out.push({
|
|
124
|
+
kind: 'tool_use',
|
|
125
|
+
tool,
|
|
126
|
+
input: block.input,
|
|
127
|
+
costUsdSnapshot: s.runningCost,
|
|
128
|
+
});
|
|
124
129
|
}
|
|
125
130
|
else if (block.type === 'text') {
|
|
126
131
|
const text = block.text?.trim();
|
package/dist/agents/codex.js
CHANGED
|
@@ -128,12 +128,12 @@ export const codexAgent = {
|
|
|
128
128
|
// `name`, fall back to `tool`. Same for input.
|
|
129
129
|
const rawName = it.name ?? it.tool ?? '';
|
|
130
130
|
const tool = rawName.replace(/^mcp__playwright__/, '').replace(/^mcp__hover-playwright__/, '');
|
|
131
|
-
out.push({ kind: 'tool_use', tool, input: it.input ?? it.arguments });
|
|
131
|
+
out.push({ kind: 'tool_use', tool, input: it.input ?? it.arguments, costUsdSnapshot: s.runningCost });
|
|
132
132
|
}
|
|
133
133
|
else if (it.type === 'command_execution') {
|
|
134
134
|
// We DISCOURAGED this in developer_instructions but the agent can
|
|
135
135
|
// still try. Surface it so the user sees it happen.
|
|
136
|
-
out.push({ kind: 'tool_use', tool: 'shell', input: { command: it.command } });
|
|
136
|
+
out.push({ kind: 'tool_use', tool: 'shell', input: { command: it.command }, costUsdSnapshot: s.runningCost });
|
|
137
137
|
}
|
|
138
138
|
return out;
|
|
139
139
|
}
|
package/dist/agents/detect.d.ts
CHANGED
|
@@ -12,6 +12,10 @@ export interface DetectedAgent {
|
|
|
12
12
|
/**
|
|
13
13
|
* Scan PATH for every agent in the registry. Returns only the ones found,
|
|
14
14
|
* in registry insertion order.
|
|
15
|
+
*
|
|
16
|
+
* Probes all agents in parallel — each `which`/`where` call is ~50-200ms
|
|
17
|
+
* and the registry's growth target is 7-10 agents, so serial would noticeably
|
|
18
|
+
* lag the first widget hello / agent-dropdown open.
|
|
15
19
|
*/
|
|
16
20
|
export declare function detectAgents(): Promise<DetectedAgent[]>;
|
|
17
21
|
export interface AgentAvailability {
|
|
@@ -27,7 +31,7 @@ export interface AgentAvailability {
|
|
|
27
31
|
/**
|
|
28
32
|
* Like `detectAgents`, but also includes registered-but-not-installed agents
|
|
29
33
|
* so the widget can render them dimmed with an install hint. Order matches
|
|
30
|
-
* the registry.
|
|
34
|
+
* the registry. Probes run in parallel — see `detectAgents`.
|
|
31
35
|
*/
|
|
32
36
|
export declare function listAgentAvailability(): Promise<AgentAvailability[]>;
|
|
33
37
|
/**
|
|
@@ -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;;;;;;;GAOG;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
|
@@ -23,26 +23,30 @@ export async function resolveBinForAgent(descriptor) {
|
|
|
23
23
|
/**
|
|
24
24
|
* Scan PATH for every agent in the registry. Returns only the ones found,
|
|
25
25
|
* in registry insertion order.
|
|
26
|
+
*
|
|
27
|
+
* Probes all agents in parallel — each `which`/`where` call is ~50-200ms
|
|
28
|
+
* and the registry's growth target is 7-10 agents, so serial would noticeably
|
|
29
|
+
* lag the first widget hello / agent-dropdown open.
|
|
26
30
|
*/
|
|
27
31
|
export async function detectAgents() {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
return detected;
|
|
32
|
+
const descriptors = listAgents();
|
|
33
|
+
const paths = await Promise.all(descriptors.map(d => resolveBinForAgent(d)));
|
|
34
|
+
return descriptors.flatMap((descriptor, i) => {
|
|
35
|
+
const binPath = paths[i];
|
|
36
|
+
return binPath ? [{ descriptor, binPath }] : [];
|
|
37
|
+
});
|
|
35
38
|
}
|
|
36
39
|
/**
|
|
37
40
|
* Like `detectAgents`, but also includes registered-but-not-installed agents
|
|
38
41
|
* so the widget can render them dimmed with an install hint. Order matches
|
|
39
|
-
* the registry.
|
|
42
|
+
* the registry. Probes run in parallel — see `detectAgents`.
|
|
40
43
|
*/
|
|
41
44
|
export async function listAgentAvailability() {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
const descriptors = listAgents();
|
|
46
|
+
const paths = await Promise.all(descriptors.map(d => resolveBinForAgent(d)));
|
|
47
|
+
return descriptors.map((descriptor, i) => {
|
|
48
|
+
const binPath = paths[i];
|
|
49
|
+
return {
|
|
46
50
|
id: descriptor.id,
|
|
47
51
|
label: descriptor.display.label,
|
|
48
52
|
tagline: descriptor.display.tagline,
|
|
@@ -51,9 +55,8 @@ export async function listAgentAvailability() {
|
|
|
51
55
|
binPath: binPath ?? undefined,
|
|
52
56
|
homepage: descriptor.display.homepage,
|
|
53
57
|
installHint: descriptor.display.installHint,
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return result;
|
|
58
|
+
};
|
|
59
|
+
});
|
|
57
60
|
}
|
|
58
61
|
/**
|
|
59
62
|
* Pick the agent we should default to when the user / Vite plugin didn't
|
package/dist/agents/invoke.d.ts
CHANGED
|
@@ -2,9 +2,11 @@ import type { InvokeEvent, InvokeOptions } from './types.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* Spawn an agent and yield normalized InvokeEvents as they arrive.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Lifecycle: the generator owns the child process. Iterating to completion
|
|
6
|
+
* drains stdout; breaking early (e.g. WS disconnect) runs the finally block
|
|
7
|
+
* which closes readline and SIGTERMs the child, so we never leak orphan
|
|
8
|
+
* agent processes that would keep driving the browser (and burning tokens)
|
|
9
|
+
* after the user has navigated away.
|
|
8
10
|
*/
|
|
9
11
|
export declare function invokeAgent(opts: InvokeOptions): AsyncIterable<InvokeEvent>;
|
|
10
12
|
//# sourceMappingURL=invoke.d.ts.map
|
|
@@ -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
|
|
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,CAsElF"}
|
package/dist/agents/invoke.js
CHANGED
|
@@ -10,9 +10,11 @@ import { AgentNotInstalledError, UnsupportedAgentProtocolError, } from './types.
|
|
|
10
10
|
/**
|
|
11
11
|
* Spawn an agent and yield normalized InvokeEvents as they arrive.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Lifecycle: the generator owns the child process. Iterating to completion
|
|
14
|
+
* drains stdout; breaking early (e.g. WS disconnect) runs the finally block
|
|
15
|
+
* which closes readline and SIGTERMs the child, so we never leak orphan
|
|
16
|
+
* agent processes that would keep driving the browser (and burning tokens)
|
|
17
|
+
* after the user has navigated away.
|
|
16
18
|
*/
|
|
17
19
|
export async function* invokeAgent(opts) {
|
|
18
20
|
const descriptor = getAgent(opts.agentId);
|
|
@@ -31,9 +33,6 @@ export async function* invokeAgent(opts) {
|
|
|
31
33
|
// doesn't trip the nested-session guard. Harmless for other agents.
|
|
32
34
|
env: { ...process.env, CLAUDECODE: '' },
|
|
33
35
|
});
|
|
34
|
-
// Wire abort: when the caller signals (e.g. WS disconnect), terminate the
|
|
35
|
-
// child so we don't leak orphan agent processes that keep driving the
|
|
36
|
-
// browser after the user has navigated away.
|
|
37
36
|
const onAbort = () => {
|
|
38
37
|
if (!child.killed)
|
|
39
38
|
child.kill('SIGTERM');
|
|
@@ -50,35 +49,39 @@ export async function* invokeAgent(opts) {
|
|
|
50
49
|
}
|
|
51
50
|
const rl = createInterface({ input: child.stdout });
|
|
52
51
|
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
52
|
const state = {};
|
|
57
53
|
let sawSessionEnd = false;
|
|
58
|
-
|
|
59
|
-
for (const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
try {
|
|
55
|
+
for await (const line of rl) {
|
|
56
|
+
for (const ev of descriptor.parseEvent(line, state)) {
|
|
57
|
+
if (ev.kind === 'session_end')
|
|
58
|
+
sawSessionEnd = true;
|
|
59
|
+
yield ev;
|
|
60
|
+
}
|
|
63
61
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
};
|
|
62
|
+
const code = await exitPromise;
|
|
63
|
+
if (!sawSessionEnd && !opts.signal?.aborted) {
|
|
64
|
+
// Give the descriptor a chance to synthesize its own terminator from
|
|
65
|
+
// accumulated state (codex does this — its stream never emits a
|
|
66
|
+
// session_end). Falls back to a generic error session_end if the
|
|
67
|
+
// descriptor declines and the child exited non-zero.
|
|
68
|
+
const synthetic = descriptor.onStreamEnd?.(code, state);
|
|
69
|
+
if (synthetic) {
|
|
70
|
+
yield synthetic;
|
|
71
|
+
}
|
|
72
|
+
else if (code !== 0) {
|
|
73
|
+
yield {
|
|
74
|
+
kind: 'session_end',
|
|
75
|
+
isError: true,
|
|
76
|
+
summary: `agent exited with code ${code}`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
82
79
|
}
|
|
83
80
|
}
|
|
81
|
+
finally {
|
|
82
|
+
rl.close();
|
|
83
|
+
if (!child.killed)
|
|
84
|
+
child.kill('SIGTERM');
|
|
85
|
+
opts.signal?.removeEventListener('abort', onAbort);
|
|
86
|
+
}
|
|
84
87
|
}
|
package/dist/agents/types.d.ts
CHANGED
|
@@ -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,
|
|
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":"launchChrome.d.ts","sourceRoot":"","sources":["../../src/playwright/launchChrome.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,cAAc,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAMlC,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CA0ChD;
|
|
1
|
+
{"version":3,"file":"launchChrome.d.ts","sourceRoot":"","sources":["../../src/playwright/launchChrome.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,cAAc,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAMlC,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CA0ChD;AAiCD;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAwDvF"}
|
|
@@ -75,8 +75,11 @@ function clearStaleProfileLock(dir) {
|
|
|
75
75
|
try {
|
|
76
76
|
unlinkSync(p);
|
|
77
77
|
}
|
|
78
|
-
catch {
|
|
79
|
-
|
|
78
|
+
catch (err) {
|
|
79
|
+
// Don't bail — Chrome may still launch despite a stale lock — but
|
|
80
|
+
// log so a downstream launch failure can be traced back to here.
|
|
81
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
82
|
+
console.warn(`[hover] couldn't clear ${p}: ${msg}`);
|
|
80
83
|
}
|
|
81
84
|
}
|
|
82
85
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../../src/playwright/preflight.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ1E;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,EAAE,CAAA;CAAE,GACjD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,SAAS,SAAO,GACf,OAAO,CAAC,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../../src/playwright/preflight.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ1E;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,EAAE,CAAA;CAAE,GACjD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,SAAS,SAAO,GACf,OAAO,CAAC,kBAAkB,CAAC,CAiD7B"}
|
|
@@ -59,9 +59,15 @@ export async function preflightCDP(cdpUrl, timeoutMs = 2000) {
|
|
|
59
59
|
.map(t => ({ url: t.url ?? '', title: t.title, type: t.type }))
|
|
60
60
|
.filter(t => t.url.length > 0);
|
|
61
61
|
}
|
|
62
|
+
else {
|
|
63
|
+
// /json/version was healthy but /json/list wasn't — surface it so the
|
|
64
|
+
// agent's system prompt isn't silently built from an empty tab list.
|
|
65
|
+
console.warn(`[hover] CDP /json/list returned HTTP ${listRes.status}; agent tab hint will be empty`);
|
|
66
|
+
}
|
|
62
67
|
}
|
|
63
|
-
catch {
|
|
64
|
-
|
|
68
|
+
catch (err) {
|
|
69
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
70
|
+
console.warn(`[hover] CDP /json/list failed: ${msg}; agent tab hint will be empty`);
|
|
65
71
|
}
|
|
66
72
|
return {
|
|
67
73
|
ok: true,
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAmEA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;6EAGyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B;4EACwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAiDD,wBAAsB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAmEA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;6EAGyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B;4EACwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAiDD,wBAAsB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAwV/E"}
|
package/dist/service.js
CHANGED
|
@@ -141,6 +141,38 @@ export async function startService(opts) {
|
|
|
141
141
|
}
|
|
142
142
|
return agentAvailabilityCache;
|
|
143
143
|
};
|
|
144
|
+
// Cache the CDP preflight result for a short window. preflightCDP() does
|
|
145
|
+
// two HTTP roundtrips to Chrome's debug endpoint (/json/version +
|
|
146
|
+
// /json/list); on a multi-turn session that's 100-300ms of latency before
|
|
147
|
+
// every follow-up — directly observable as a pause between hitting send
|
|
148
|
+
// and the agent starting work. A 5s TTL is comfortably shorter than the
|
|
149
|
+
// time it takes a user to type+send another message, but long enough that
|
|
150
|
+
// back-to-back commands skip the roundtrip. Failures are NOT cached so
|
|
151
|
+
// the user gets immediate feedback when they fix the underlying issue
|
|
152
|
+
// (e.g. start Chrome). Cache is invalidated whenever an invocation fails
|
|
153
|
+
// (defensive: if MCP somehow spawned its own Chromium we want the next
|
|
154
|
+
// preflight to re-probe).
|
|
155
|
+
const PREFLIGHT_TTL_MS = 5000;
|
|
156
|
+
let cachedPreflight = null;
|
|
157
|
+
let cachedPreflightAt = 0;
|
|
158
|
+
const getPreflight = async () => {
|
|
159
|
+
const now = Date.now();
|
|
160
|
+
if (cachedPreflight?.ok && now - cachedPreflightAt < PREFLIGHT_TTL_MS) {
|
|
161
|
+
return cachedPreflight;
|
|
162
|
+
}
|
|
163
|
+
const result = await preflightCDP(cdpUrl);
|
|
164
|
+
if (result.ok) {
|
|
165
|
+
cachedPreflight = result;
|
|
166
|
+
cachedPreflightAt = now;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
cachedPreflight = null;
|
|
170
|
+
}
|
|
171
|
+
return result;
|
|
172
|
+
};
|
|
173
|
+
const invalidatePreflight = () => {
|
|
174
|
+
cachedPreflight = null;
|
|
175
|
+
};
|
|
144
176
|
const broadcastAgents = async () => {
|
|
145
177
|
const available = await getAvailability(false);
|
|
146
178
|
const payload = { current: currentAgentId, available };
|
|
@@ -292,7 +324,7 @@ export async function startService(opts) {
|
|
|
292
324
|
// Playwright MCP server would silently launch its own Chromium —
|
|
293
325
|
// and Hover's premise is to drive the user's existing Chrome (with
|
|
294
326
|
// their dev state, cookies, devtools open), never spawn a fresh one.
|
|
295
|
-
const cdp = await
|
|
327
|
+
const cdp = await getPreflight();
|
|
296
328
|
if (!cdp.ok) {
|
|
297
329
|
send(ws, {
|
|
298
330
|
type: 'event',
|
|
@@ -375,6 +407,11 @@ export async function startService(opts) {
|
|
|
375
407
|
if (ws.readyState === WebSocket.OPEN) {
|
|
376
408
|
send(ws, { type: 'event', payload: errorEvent });
|
|
377
409
|
}
|
|
410
|
+
// Force the next command to re-probe CDP. The error could be from
|
|
411
|
+
// Chrome dying, MCP spawning a stray Chromium, the user closing
|
|
412
|
+
// their debug window — anything that would make a cached "all
|
|
413
|
+
// healthy" result lie.
|
|
414
|
+
invalidatePreflight();
|
|
378
415
|
}
|
|
379
416
|
finally {
|
|
380
417
|
busy = false;
|
|
@@ -5,7 +5,7 @@ export declare class SkillExistsError extends Error {
|
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
7
|
* Serialized message shape from the widget's localStorage. Matches the
|
|
8
|
-
* `state.messages` schema in packages/
|
|
8
|
+
* `state.messages` schema in packages/widget-bootstrap/src/widget/client.js.
|
|
9
9
|
*/
|
|
10
10
|
export interface SkillStep {
|
|
11
11
|
kind: 'user' | 'system' | 'step' | 'ai' | 'done';
|