@hover-dev/core 0.16.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.
Files changed (154) hide show
  1. package/README.md +26 -55
  2. package/dist/agentDirectives.d.ts +55 -0
  3. package/dist/agentDirectives.d.ts.map +1 -0
  4. package/dist/agentDirectives.js +276 -0
  5. package/dist/agents/claude.d.ts.map +1 -1
  6. package/dist/agents/claude.js +28 -3
  7. package/dist/agents/codex.d.ts.map +1 -1
  8. package/dist/agents/codex.js +29 -14
  9. package/dist/agents/invoke.d.ts.map +1 -1
  10. package/dist/agents/invoke.js +3 -6
  11. package/dist/agents/registry.d.ts.map +1 -1
  12. package/dist/agents/registry.js +0 -4
  13. package/dist/agents/types.d.ts +19 -11
  14. package/dist/agents/types.d.ts.map +1 -1
  15. package/dist/engine.d.ts +53 -0
  16. package/dist/engine.d.ts.map +1 -0
  17. package/dist/engine.js +78 -0
  18. package/dist/mcp/actuateServer.d.ts +3 -0
  19. package/dist/mcp/actuateServer.d.ts.map +1 -0
  20. package/dist/mcp/actuateServer.js +594 -0
  21. package/dist/mcp/sourceFence.d.ts.map +1 -1
  22. package/dist/mcp/sourceFence.js +4 -0
  23. package/dist/mcp/sourceServer.js +75 -0
  24. package/dist/memory/businessMemory.d.ts +29 -0
  25. package/dist/memory/businessMemory.d.ts.map +1 -0
  26. package/dist/memory/businessMemory.js +125 -0
  27. package/dist/modes.d.ts +39 -0
  28. package/dist/modes.d.ts.map +1 -0
  29. package/dist/modes.js +34 -0
  30. package/dist/playwright/cdpStatus.d.ts +0 -15
  31. package/dist/playwright/cdpStatus.d.ts.map +1 -1
  32. package/dist/playwright/cdpStatus.js +0 -67
  33. package/dist/playwright/launchChrome.d.ts +18 -0
  34. package/dist/playwright/launchChrome.d.ts.map +1 -1
  35. package/dist/playwright/launchChrome.js +46 -3
  36. package/dist/playwright/resolveMcpConfig.d.ts +7 -1
  37. package/dist/playwright/resolveMcpConfig.d.ts.map +1 -1
  38. package/dist/playwright/resolveMcpConfig.js +22 -4
  39. package/dist/plugin-api.d.ts +28 -26
  40. package/dist/plugin-api.d.ts.map +1 -1
  41. package/dist/plugin-api.js +2 -2
  42. package/dist/qa/candidates.d.ts +32 -0
  43. package/dist/qa/candidates.d.ts.map +1 -0
  44. package/dist/qa/candidates.js +20 -0
  45. package/dist/qa/classify.d.ts +38 -0
  46. package/dist/qa/classify.d.ts.map +1 -0
  47. package/dist/qa/classify.js +138 -0
  48. package/dist/qa/intensity.d.ts +33 -0
  49. package/dist/qa/intensity.d.ts.map +1 -0
  50. package/dist/qa/intensity.js +25 -0
  51. package/dist/qa/qaReport.d.ts +19 -0
  52. package/dist/qa/qaReport.d.ts.map +1 -0
  53. package/dist/qa/qaReport.js +50 -0
  54. package/dist/runSession.d.ts +14 -3
  55. package/dist/runSession.d.ts.map +1 -1
  56. package/dist/runSession.js +26 -11
  57. package/dist/service/cdpHandlers.d.ts +1 -21
  58. package/dist/service/cdpHandlers.d.ts.map +1 -1
  59. package/dist/service/cdpHandlers.js +4 -39
  60. package/dist/service/cdpHint.d.ts +21 -28
  61. package/dist/service/cdpHint.d.ts.map +1 -1
  62. package/dist/service/cdpHint.js +106 -164
  63. package/dist/service/relayHandlers.d.ts +28 -0
  64. package/dist/service/relayHandlers.d.ts.map +1 -0
  65. package/dist/service/relayHandlers.js +105 -0
  66. package/dist/service/saveHandlers.d.ts +1 -3
  67. package/dist/service/saveHandlers.d.ts.map +1 -1
  68. package/dist/service/saveHandlers.js +17 -15
  69. package/dist/service/types.d.ts +108 -8
  70. package/dist/service/types.d.ts.map +1 -1
  71. package/dist/service.d.ts +7 -3
  72. package/dist/service.d.ts.map +1 -1
  73. package/dist/service.js +907 -200
  74. package/dist/sessions/sessions.d.ts +125 -0
  75. package/dist/sessions/sessions.d.ts.map +1 -0
  76. package/dist/sessions/sessions.js +175 -0
  77. package/dist/specs/authFixture.d.ts +30 -0
  78. package/dist/specs/authFixture.d.ts.map +1 -0
  79. package/dist/specs/authFixture.js +145 -0
  80. package/dist/specs/businessMap.d.ts +29 -0
  81. package/dist/specs/businessMap.d.ts.map +1 -0
  82. package/dist/specs/businessMap.js +95 -0
  83. package/dist/specs/detectSharedFlows.d.ts +1 -1
  84. package/dist/specs/detectSharedFlows.d.ts.map +1 -1
  85. package/dist/specs/detectSharedFlows.js +20 -21
  86. package/dist/specs/generatePageObject.d.ts +1 -1
  87. package/dist/specs/generatePageObject.d.ts.map +1 -1
  88. package/dist/specs/healPrompt.d.ts +19 -0
  89. package/dist/specs/healPrompt.d.ts.map +1 -0
  90. package/dist/specs/healPrompt.js +48 -0
  91. package/dist/specs/humanSteps.d.ts +4 -8
  92. package/dist/specs/humanSteps.d.ts.map +1 -1
  93. package/dist/specs/humanSteps.js +6 -1
  94. package/dist/specs/optimizeSpec.d.ts +15 -8
  95. package/dist/specs/optimizeSpec.d.ts.map +1 -1
  96. package/dist/specs/optimizeSpec.js +71 -41
  97. package/dist/specs/optimizeSpecWithAgent.d.ts +0 -2
  98. package/dist/specs/optimizeSpecWithAgent.d.ts.map +1 -1
  99. package/dist/specs/optimizeSpecWithAgent.js +0 -1
  100. package/dist/specs/pageObjectManifest.d.ts +3 -1
  101. package/dist/specs/pageObjectManifest.d.ts.map +1 -1
  102. package/dist/specs/pageObjectManifest.js +13 -9
  103. package/dist/specs/replayGrounded.d.ts +45 -0
  104. package/dist/specs/replayGrounded.d.ts.map +1 -0
  105. package/dist/specs/replayGrounded.js +155 -0
  106. package/dist/specs/runFailures.d.ts +34 -0
  107. package/dist/specs/runFailures.d.ts.map +1 -0
  108. package/dist/specs/runFailures.js +93 -0
  109. package/dist/specs/seeds.d.ts +16 -15
  110. package/dist/specs/seeds.d.ts.map +1 -1
  111. package/dist/specs/seeds.js +86 -54
  112. package/dist/specs/sidecar.d.ts +34 -6
  113. package/dist/specs/sidecar.d.ts.map +1 -1
  114. package/dist/specs/sidecar.js +79 -9
  115. package/dist/specs/specStep.d.ts +21 -0
  116. package/dist/specs/specStep.d.ts.map +1 -0
  117. package/dist/specs/specStep.js +1 -0
  118. package/dist/specs/text.d.ts +8 -6
  119. package/dist/specs/text.d.ts.map +1 -1
  120. package/dist/specs/text.js +10 -7
  121. package/dist/specs/writeSpec.d.ts +62 -1
  122. package/dist/specs/writeSpec.d.ts.map +1 -1
  123. package/dist/specs/writeSpec.js +596 -21
  124. package/package.json +6 -9
  125. package/dist/agents/aider.d.ts +0 -16
  126. package/dist/agents/aider.d.ts.map +0 -1
  127. package/dist/agents/aider.js +0 -161
  128. package/dist/agents/cursor.d.ts +0 -18
  129. package/dist/agents/cursor.d.ts.map +0 -1
  130. package/dist/agents/cursor.js +0 -220
  131. package/dist/playwright/raiseWindow.d.ts +0 -10
  132. package/dist/playwright/raiseWindow.d.ts.map +0 -1
  133. package/dist/playwright/raiseWindow.js +0 -158
  134. package/dist/scripts/bench-multi-tab.d.ts +0 -2
  135. package/dist/scripts/bench-multi-tab.d.ts.map +0 -1
  136. package/dist/scripts/bench-multi-tab.js +0 -192
  137. package/dist/scripts/bench-ttfb.d.ts +0 -2
  138. package/dist/scripts/bench-ttfb.d.ts.map +0 -1
  139. package/dist/scripts/bench-ttfb.js +0 -127
  140. package/dist/scripts/start-chrome.d.ts +0 -3
  141. package/dist/scripts/start-chrome.d.ts.map +0 -1
  142. package/dist/scripts/start-chrome.js +0 -23
  143. package/dist/skills/writeSkill.d.ts +0 -27
  144. package/dist/skills/writeSkill.d.ts.map +0 -1
  145. package/dist/skills/writeSkill.js +0 -13
  146. package/dist/specs/listSpecs.d.ts +0 -52
  147. package/dist/specs/listSpecs.d.ts.map +0 -1
  148. package/dist/specs/listSpecs.js +0 -139
  149. package/dist/specs/optimizationSuggestion.d.ts +0 -26
  150. package/dist/specs/optimizationSuggestion.d.ts.map +0 -1
  151. package/dist/specs/optimizationSuggestion.js +0 -28
  152. package/dist/specs/writeCaseCsv.d.ts +0 -28
  153. package/dist/specs/writeCaseCsv.d.ts.map +0 -1
  154. package/dist/specs/writeCaseCsv.js +0 -134
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Stateless relay message handlers, split out of startService's message switch.
3
+ *
4
+ * These message types only ROUTE messages between the connected sockets (the
5
+ * editor, the in-page client, and the MCP server sockets) — they never read or
6
+ * reassign the run's mutable state (currentMode/agent/model/activeRun/…), so
7
+ * they extract cleanly with a small explicit dependency bundle instead of the
8
+ * whole service closure:
9
+ * - reveal-source page → editor (F2 element→source)
10
+ * - source-approval-request source MCP → editor consent gate
11
+ * - source-approval-response editor decision → source MCP
12
+ * - ask-user-request control MCP → every other client
13
+ * - ask-user-response a client's answer → the asking MCP
14
+ */
15
+ import { WebSocket } from 'ws';
16
+ import { send, sendIfOpen } from './types.js';
17
+ /** Handle a stateless relay message. Returns true if `msg` was one of the relay
18
+ * types (and is now fully handled — the caller should stop), false otherwise. */
19
+ export function handleRelayMessage(ws, msg, deps) {
20
+ const { wss, pendingApprovals, pendingAsks } = deps;
21
+ if (msg.type === 'reveal-source') {
22
+ // F2 page→editor transport: relay a clicked element's `data-hover-source`
23
+ // to every OTHER client; the VSCode extension opens <rel-path>:<line>:<col>.
24
+ const source = msg.payload?.source;
25
+ if (typeof source !== 'string' || !source)
26
+ return true;
27
+ for (const client of wss.clients) {
28
+ if (client !== ws && client.readyState === WebSocket.OPEN) {
29
+ send(client, { type: 'reveal-source', payload: { source } });
30
+ }
31
+ }
32
+ return true;
33
+ }
34
+ // Source-read approval gate (codeContext 'ask' mode): relay to the editor and
35
+ // route its decision back. No editor → default allow (read-only fenced reader;
36
+ // the gate is consent UX, never hang the run on it).
37
+ if (msg.type === 'source-approval-request') {
38
+ const id = msg.payload?.approvalId;
39
+ if (typeof id !== 'string')
40
+ return true;
41
+ const editor = deps.activeRunClient();
42
+ if (editor && editor.readyState === WebSocket.OPEN) {
43
+ pendingApprovals.set(id, ws);
44
+ send(editor, {
45
+ type: 'source-approval-request',
46
+ payload: { approvalId: id, sourcePath: msg.payload?.sourcePath, sourceKind: msg.payload?.sourceKind },
47
+ });
48
+ }
49
+ else {
50
+ sendIfOpen(ws, { type: 'source-approval-response', payload: { approvalId: id, allow: true } });
51
+ }
52
+ return true;
53
+ }
54
+ if (msg.type === 'source-approval-response') {
55
+ const id = msg.payload?.approvalId;
56
+ if (typeof id !== 'string')
57
+ return true;
58
+ const asker = pendingApprovals.get(id);
59
+ pendingApprovals.delete(id);
60
+ if (asker)
61
+ sendIfOpen(asker, { type: 'source-approval-response', payload: { approvalId: id, allow: msg.payload?.allow === true } });
62
+ return true;
63
+ }
64
+ // ask_user: the control MCP asks the human mid-run; forward to EVERY connected
65
+ // client except the asking MCP (robust to a stale activeRun.client in the
66
+ // reconnecting multi-host pool); route the answer back. No client → cancel so
67
+ // the agent continues rather than hanging on the 5-min timeout.
68
+ if (msg.type === 'ask-user-request') {
69
+ const id = msg.payload?.askId;
70
+ if (typeof id !== 'string')
71
+ return true;
72
+ const payload = {
73
+ askId: id,
74
+ question: msg.payload?.question,
75
+ options: msg.payload?.options,
76
+ allowFreeText: msg.payload?.allowFreeText,
77
+ };
78
+ let delivered = 0;
79
+ for (const client of wss.clients) {
80
+ if (client === ws)
81
+ continue;
82
+ if (client.readyState === WebSocket.OPEN) {
83
+ send(client, { type: 'ask-user-request', payload });
84
+ delivered++;
85
+ }
86
+ }
87
+ process.stderr.write(`[hover/ask] askId=${id} delivered to ${delivered} client(s)\n`);
88
+ if (delivered > 0)
89
+ pendingAsks.set(id, ws);
90
+ else
91
+ sendIfOpen(ws, { type: 'ask-user-response', payload: { askId: id, cancelled: true } });
92
+ return true;
93
+ }
94
+ if (msg.type === 'ask-user-response') {
95
+ const id = msg.payload?.askId;
96
+ if (typeof id !== 'string')
97
+ return true;
98
+ const asker = pendingAsks.get(id);
99
+ pendingAsks.delete(id);
100
+ if (asker)
101
+ sendIfOpen(asker, { type: 'ask-user-response', payload: msg.payload });
102
+ return true;
103
+ }
104
+ return false;
105
+ }
@@ -9,9 +9,8 @@
9
9
  * post-write tail.)
10
10
  */
11
11
  import type { WebSocket } from 'ws';
12
- import { type SkillStep } from '../skills/writeSkill.js';
12
+ import { type SkillStep } from '../specs/specStep.js';
13
13
  import { writeSpec, type SpecAssertion } from '../specs/writeSpec.js';
14
- import { writeCaseCsv } from '../specs/writeCaseCsv.js';
15
14
  import { type ClientMessage } from './types.js';
16
15
  interface SaveArtifactConfig<TWriteResult extends {
17
16
  slug: string;
@@ -47,6 +46,5 @@ export declare function handleSaveArtifact<TWriteResult extends {
47
46
  path: string;
48
47
  }>(ws: WebSocket, msg: ClientMessage, devRoot: string, cfg: SaveArtifactConfig<TWriteResult>): Promise<void>;
49
48
  export declare const SPEC_CONFIG: SaveArtifactConfig<Awaited<ReturnType<typeof writeSpec>>>;
50
- export declare const CASE_CSV_CONFIG: SaveArtifactConfig<Awaited<ReturnType<typeof writeCaseCsv>>>;
51
49
  export {};
52
50
  //# sourceMappingURL=saveHandlers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"saveHandlers.d.ts","sourceRoot":"","sources":["../../src/service/saveHandlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAmB,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,YAAY,EAAsB,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAQ,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAEtD,UAAU,kBAAkB,CAAC,YAAY,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;IAC9E,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB;+EAC2E;IAC3E,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,0EAA0E;IAC1E,WAAW,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,KAAK,CAAC;IAC9E,wEAAwE;IACxE,KAAK,EAAE,CAAC,IAAI,EAAE;QACZ,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,SAAS,EAAE,CAAC;QACnB,UAAU,EAAE,aAAa,EAAE,CAAC;QAC5B,OAAO,EAAE,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;QAC/C,SAAS,EAAE,OAAO,CAAC;KACpB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CAC7B;AAED,wBAAsB,kBAAkB,CAAC,YAAY,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC1F,EAAE,EAAE,SAAS,EACb,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,kBAAkB,CAAC,YAAY,CAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CA0Cf;AAED,eAAO,MAAM,WAAW,EAAE,kBAAkB,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAOjF,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,kBAAkB,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAYxF,CAAC"}
1
+ {"version":3,"file":"saveHandlers.d.ts","sourceRoot":"","sources":["../../src/service/saveHandlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAmB,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAQ,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAEtD,UAAU,kBAAkB,CAAC,YAAY,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;IAC9E,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB;+EAC2E;IAC3E,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,0EAA0E;IAC1E,WAAW,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,KAAK,CAAC;IAC9E,wEAAwE;IACxE,KAAK,EAAE,CAAC,IAAI,EAAE;QACZ,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,SAAS,EAAE,CAAC;QACnB,UAAU,EAAE,aAAa,EAAE,CAAC;QAC5B,OAAO,EAAE,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;QAC/C,SAAS,EAAE,OAAO,CAAC;KACpB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CAC7B;AAED,wBAAsB,kBAAkB,CAAC,YAAY,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC1F,EAAE,EAAE,SAAS,EACb,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,kBAAkB,CAAC,YAAY,CAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CAyDf;AAED,eAAO,MAAM,WAAW,EAAE,kBAAkB,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAOjF,CAAC"}
@@ -9,7 +9,6 @@
9
9
  * post-write tail.)
10
10
  */
11
11
  import { writeSpec, SpecExistsError } from '../specs/writeSpec.js';
12
- import { writeCaseCsv, CaseCsvExistsError } from '../specs/writeCaseCsv.js';
13
12
  import { send } from './types.js';
14
13
  export async function handleSaveArtifact(ws, msg, devRoot, cfg) {
15
14
  const name = msg.payload?.name;
@@ -41,7 +40,22 @@ export async function handleSaveArtifact(ws, msg, devRoot, cfg) {
41
40
  send(ws, { type: 'error', payload: { message: `${cfg.requestName} failed: ${message}` } });
42
41
  return;
43
42
  }
44
- send(ws, { type: cfg.savedType, payload: { name: result.slug, path: result.path } });
43
+ // When the run was split into several feature files, report all their slugs
44
+ // so the widget can confirm "Saved 3 specs: login, checkout, …".
45
+ const files = result.files;
46
+ // Auth-as-fixture (debt 3): a login was detected but a user playwright.config
47
+ // exists — forward the proposed config edit so the extension can offer it for
48
+ // approval (Stage 4b). Absent on a normal save.
49
+ const authFixtureOffer = result.authFixtureOffer;
50
+ send(ws, {
51
+ type: cfg.savedType,
52
+ payload: {
53
+ name: result.slug,
54
+ path: result.path,
55
+ ...(files && files.length > 1 ? { files: files.map((f) => f.slug) } : {}),
56
+ ...(authFixtureOffer ? { authFixtureOffer } : {}),
57
+ },
58
+ });
45
59
  // The artifact is already on disk; an onSaved failure (e.g. a follow-up
46
60
  // list re-scan) shouldn't surface as if the save itself failed — log on.
47
61
  if (cfg.onSaved) {
@@ -59,17 +73,5 @@ export const SPEC_CONFIG = {
59
73
  savedType: 'spec-saved',
60
74
  existsType: 'spec-exists',
61
75
  ExistsError: SpecExistsError,
62
- write: ({ devRoot, name, description, steps, assertions, overwrite }) => writeSpec({ devRoot, name, description, steps, assertions, overwrite }),
63
- };
64
- export const CASE_CSV_CONFIG = {
65
- requestName: 'save-case-csv',
66
- savedType: 'case-csv-saved',
67
- existsType: 'case-csv-exists',
68
- ExistsError: CaseCsvExistsError,
69
- write: ({ devRoot, name, description, steps, assertions, payload, overwrite }) => writeCaseCsv({
70
- devRoot, name, description, steps, assertions,
71
- jiraProjectKey: payload.jiraProjectKey,
72
- labels: payload.labels,
73
- overwrite,
74
- }),
76
+ write: ({ devRoot, name, description, steps, assertions, payload, overwrite }) => writeSpec({ devRoot, name, description, steps, assertions, overwrite, redactions: payload.redactions, resetRecipe: payload.resetRecipe, authFixture: payload.authFixture }),
75
77
  };
@@ -10,36 +10,136 @@
10
10
  * one place.
11
11
  */
12
12
  import { WebSocket } from 'ws';
13
- import type { SkillStep } from '../skills/writeSkill.js';
13
+ import type { SkillStep } from '../specs/specStep.js';
14
14
  import type { SpecAssertion } from '../specs/writeSpec.js';
15
15
  export interface ClientMessage {
16
16
  type: string;
17
17
  payload?: {
18
18
  text?: string;
19
19
  sessionId?: string;
20
+ /** The chat conversation a run belongs to — groups its run folders under
21
+ * `.hover/runs/<conversationId>/`. */
22
+ conversationId?: string;
20
23
  name?: string;
21
24
  description?: string;
22
25
  steps?: SkillStep[];
23
26
  assertions?: SpecAssertion[];
24
27
  overwrite?: boolean;
25
- /** save-case-csv only — passed through to writeCaseCsv as extra
26
- * fields on the test case's Labels column. */
27
- jiraProjectKey?: string;
28
- labels?: string;
28
+ /** save-spec only — credentials to parameterize into process.env.<envVar>
29
+ * references so secrets never land in the spec / sidecar. */
30
+ redactions?: {
31
+ value: string;
32
+ envVar: string;
33
+ }[];
34
+ /** save-spec only — the active env's recon-discovered reset recipe (debt-2).
35
+ * A tier-1 recipe makes the spec generate + call a resetState() beforeEach. */
36
+ resetRecipe?: {
37
+ tier: number;
38
+ storageKeys?: string[];
39
+ hook?: string;
40
+ };
41
+ /** save-spec only — auth-as-fixture (debt 3). The user approved Hover editing
42
+ * their existing playwright.config; engage the fixture (lift login into
43
+ * auth.setup.ts) and apply the setup-project edit. Absent on a normal save. */
44
+ authFixture?: boolean;
45
+ /** command only — test accounts the prompt referenced via @label. Injected
46
+ * into the agent's system prompt (ephemeral, not the saved transcript) so
47
+ * it can log in; the recorded fill values get redacted on save. */
48
+ accounts?: {
49
+ label: string;
50
+ username?: string;
51
+ password?: string;
52
+ role?: string;
53
+ }[];
54
+ /** command only — ask the agent to run state-reset recon this run (debt-2
55
+ * reproducible-state-isolation). Off unless the extension sets it (e.g. the
56
+ * active env has no reset recipe yet); recon clears client state, so it must
57
+ * be opt-in, never on a plain Flow recording. */
58
+ reconReset?: boolean;
29
59
  /** check-cdp / launch-chrome / focus-debug — the widget's
30
60
  * window.location.href so service can compare origins or navigate the
31
61
  * newly-launched debug Chrome to the same URL. */
32
62
  pageUrl?: string;
33
63
  /** switch-agent only — id of the agent to switch the service to. */
34
64
  agentId?: string;
65
+ /** set-model only — the model id to use for subsequent runs (e.g. opus). */
66
+ model?: string;
67
+ /** optimize-spec only — override model for the F7 refinement pass (the
68
+ * `hover.optimizeModel` setting). Empty → the agent's cheap default. */
69
+ optimizeModel?: string;
70
+ /** heal-spec only — the failing spec's source, so the engine can build the
71
+ * heal prompt without guessing the spec's path. */
72
+ specSource?: string;
73
+ /** set-effort only — reasoning-effort level for subsequent runs (empty
74
+ * string clears it → agent/model default). */
75
+ effort?: string;
76
+ /** set-local-endpoint only — base URL of the user's self-hosted
77
+ * OpenAI-compatible endpoint for the Local LLM agent. */
78
+ baseUrl?: string;
79
+ /** set-byok only — bring-your-own-key model config (protocol + key + base
80
+ * URL + model injected into the protocol's matching CLI), or null to clear
81
+ * and fall back to the local-CLI agent's own auth. */
82
+ config?: {
83
+ protocol: string;
84
+ baseUrl: string;
85
+ model: string;
86
+ maxTokens: number;
87
+ apiKey: string;
88
+ } | null;
35
89
  /** set-mode only — id of the plugin-contributed mode to activate,
36
90
  * or null to return to normal (unmoded) operation. */
37
91
  modeId?: string | null;
38
92
  /** optimize-spec / promote-optimized / discard-optimized — the spec slug. */
39
93
  slug?: string;
40
- /** set-api-key only — the model API key to inject into the spawned CLI's
41
- * env (or empty/missing to clear it). Held in memory only, never logged. */
42
- key?: string;
94
+ /** launch-chrome only — launch the debug Chrome headless (silent mode). */
95
+ headless?: boolean;
96
+ /** launch-chrome only — close any existing debug Chrome first, then
97
+ * relaunch (so a headless↔visible switch / "reopen browser" takes effect). */
98
+ force?: boolean;
99
+ /** reveal-source only — a `data-hover-source` value (`<rel-path>:<line>:<col>`)
100
+ * an in-page client (widget) captured from a clicked element. The service
101
+ * relays it to every OTHER connected client; the VSCode extension listens
102
+ * for it and jumps the editor to that location (F2 page→editor transport). */
103
+ source?: string;
104
+ /** command only — the editor's source-read grant for this run:
105
+ * 'always' (skip the gate), 'ask' (gate each read), 'deny' (no source MCP).
106
+ * Default 'ask' when absent. */
107
+ sourceAccess?: 'always' | 'ask' | 'deny';
108
+ /** command only — run the agent in an isolated cwd so it loads none of the
109
+ * user's CLAUDE.md / Claude Code auto-memory (Memory = "isolated"). */
110
+ isolateContext?: boolean;
111
+ /** command only — the active environment, recorded in the session ledger. */
112
+ env?: {
113
+ id?: string;
114
+ name?: string;
115
+ };
116
+ /** source-approval-request (from the source MCP) / -response (from the
117
+ * editor): a correlation id, the requested repo-relative path + kind, and
118
+ * the user's allow/deny decision. */
119
+ approvalId?: string;
120
+ sourcePath?: string;
121
+ sourceKind?: string;
122
+ allow?: boolean;
123
+ /** ask-user-request (from the control MCP) / -response (from the editor):
124
+ * a correlation id, the question + offered choices, and the user's answer. */
125
+ askId?: string;
126
+ question?: string;
127
+ options?: {
128
+ label: string;
129
+ description?: string;
130
+ }[];
131
+ allowFreeText?: boolean;
132
+ value?: string;
133
+ cancelled?: boolean;
134
+ /** record-fact (from the control MCP, QA/API modes only): a business RULE
135
+ * the agent learned/confirmed, to persist into `.hover/memory/` so it isn't
136
+ * re-asked next run. RULES only — never secrets/PII (the tool + directive
137
+ * enforce this; the engine also ignores it outside QA/API). */
138
+ fact?: {
139
+ title: string;
140
+ rule: string;
141
+ type?: string;
142
+ };
43
143
  };
44
144
  }
45
145
  export declare function send(ws: WebSocket, message: {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/service/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;QACpB,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;QAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB;uDAC+C;QAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB;;2DAEmD;QACnD,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,oEAAoE;QACpE,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB;+DACuD;QACvD,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,6EAA6E;QAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;QACd;qFAC6E;QAC7E,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAEtF;AAED;;;;sEAIsE;AACtE,wBAAgB,UAAU,CACxB,EAAE,EAAE,SAAS,EACb,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3C,OAAO,CAIT"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/service/types.ts"],"names":[],"mappings":"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"}
package/dist/service.d.ts CHANGED
@@ -3,13 +3,17 @@ export interface ServiceOptions {
3
3
  port: number;
4
4
  agentId?: string;
5
5
  model?: string;
6
+ /** Initial reasoning-effort level (set-effort overrides at runtime). */
7
+ effort?: string;
6
8
  maxBudgetUsd?: number;
7
- /** How the optimization pass (F7) surfaces in the widget. Default 'suggest'.
8
- * 'off' = no nudge, 'suggest' = ✦ hint, 'on' = auto-run after Save-as-spec. */
9
- optimizeMode?: 'off' | 'suggest' | 'on';
10
9
  mcpConfig?: string;
11
10
  /** CDP URL to preflight before each command (default http://localhost:9222). */
12
11
  cdpUrl?: string;
12
+ /** Isolated Chrome user-data-dir for this service's debug Chrome (default
13
+ * `<tmpdir>/hover-chrome`). Set per-service so several engine hosts (one per
14
+ * chat session) each drive their OWN Chrome profile — distinct logins, no
15
+ * profile-lock contention. Paired with a distinct `cdpUrl` port. */
16
+ userDataDir?: string;
13
17
  /** Working directory for the spawned agent. Also the root under which saved
14
18
  * specs (`__vibe_tests__/`), sidecars + seeds (`.hover/`) live. Defaults to
15
19
  * process.cwd(); in Vite plugin context, set to `server.config.root` so the
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AA+EA,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,iBAAiB,CAAC;AAQzB,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;oFACgF;IAChF,YAAY,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;gFAG4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;uBAImB;IACnB,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAChC;;;;;;uEAMmE;IACnE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;iFAI6E;IAC7E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;wDAEoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B;4EACwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAiED,wBAAsB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA49B/E"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAqFA,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,iBAAiB,CAAC;AAqCzB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;yEAGqE;IACrE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;gFAG4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;uBAImB;IACnB,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAChC;;;;;;uEAMmE;IACnE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;iFAI6E;IAC7E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;wDAEoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B;4EACwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAkFD,wBAAsB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAglD/E"}