@hover-dev/core 0.16.0 → 0.18.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 (181) 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/engine.d.ts +28 -0
  6. package/dist/engine.d.ts.map +1 -0
  7. package/dist/engine.js +27 -0
  8. package/dist/memory/businessMemory.d.ts +29 -0
  9. package/dist/memory/businessMemory.d.ts.map +1 -0
  10. package/dist/memory/businessMemory.js +125 -0
  11. package/dist/playwright/launchChrome.d.ts +18 -0
  12. package/dist/playwright/launchChrome.d.ts.map +1 -1
  13. package/dist/playwright/launchChrome.js +46 -3
  14. package/dist/qa/candidates.d.ts +32 -0
  15. package/dist/qa/candidates.d.ts.map +1 -0
  16. package/dist/qa/candidates.js +20 -0
  17. package/dist/qa/intensity.d.ts +33 -0
  18. package/dist/qa/intensity.d.ts.map +1 -0
  19. package/dist/qa/intensity.js +25 -0
  20. package/dist/qa/qaReport.d.ts +19 -0
  21. package/dist/qa/qaReport.d.ts.map +1 -0
  22. package/dist/qa/qaReport.js +50 -0
  23. package/dist/sessions/sessions.d.ts +125 -0
  24. package/dist/sessions/sessions.d.ts.map +1 -0
  25. package/dist/sessions/sessions.js +175 -0
  26. package/dist/specs/authFixture.d.ts +30 -0
  27. package/dist/specs/authFixture.d.ts.map +1 -0
  28. package/dist/specs/authFixture.js +145 -0
  29. package/dist/specs/detectSharedFlows.d.ts +1 -1
  30. package/dist/specs/detectSharedFlows.d.ts.map +1 -1
  31. package/dist/specs/detectSharedFlows.js +20 -21
  32. package/dist/specs/generatePageObject.d.ts +1 -1
  33. package/dist/specs/generatePageObject.d.ts.map +1 -1
  34. package/dist/specs/healPrompt.d.ts +19 -0
  35. package/dist/specs/healPrompt.d.ts.map +1 -0
  36. package/dist/specs/healPrompt.js +48 -0
  37. package/dist/specs/humanSteps.d.ts +4 -8
  38. package/dist/specs/humanSteps.d.ts.map +1 -1
  39. package/dist/specs/humanSteps.js +6 -1
  40. package/dist/specs/optimizeSpec.d.ts +15 -8
  41. package/dist/specs/optimizeSpec.d.ts.map +1 -1
  42. package/dist/specs/optimizeSpec.js +71 -41
  43. package/dist/specs/pageObjectManifest.d.ts +3 -1
  44. package/dist/specs/pageObjectManifest.d.ts.map +1 -1
  45. package/dist/specs/pageObjectManifest.js +24 -19
  46. package/dist/specs/replayGrounded.d.ts +45 -0
  47. package/dist/specs/replayGrounded.d.ts.map +1 -0
  48. package/dist/specs/replayGrounded.js +155 -0
  49. package/dist/specs/runFailures.d.ts +34 -0
  50. package/dist/specs/runFailures.d.ts.map +1 -0
  51. package/dist/specs/runFailures.js +93 -0
  52. package/dist/specs/seeds.d.ts +16 -15
  53. package/dist/specs/seeds.d.ts.map +1 -1
  54. package/dist/specs/seeds.js +86 -54
  55. package/dist/specs/sidecar.d.ts +34 -6
  56. package/dist/specs/sidecar.d.ts.map +1 -1
  57. package/dist/specs/sidecar.js +79 -9
  58. package/dist/specs/specStep.d.ts +21 -0
  59. package/dist/specs/specStep.d.ts.map +1 -0
  60. package/dist/specs/specStep.js +1 -0
  61. package/dist/specs/text.d.ts +8 -6
  62. package/dist/specs/text.d.ts.map +1 -1
  63. package/dist/specs/text.js +10 -7
  64. package/dist/specs/writeSpec.d.ts +62 -1
  65. package/dist/specs/writeSpec.d.ts.map +1 -1
  66. package/dist/specs/writeSpec.js +596 -21
  67. package/package.json +9 -29
  68. package/dist/agents/aider.d.ts +0 -16
  69. package/dist/agents/aider.d.ts.map +0 -1
  70. package/dist/agents/aider.js +0 -161
  71. package/dist/agents/argv.d.ts +0 -11
  72. package/dist/agents/argv.d.ts.map +0 -1
  73. package/dist/agents/argv.js +0 -23
  74. package/dist/agents/claude.d.ts +0 -3
  75. package/dist/agents/claude.d.ts.map +0 -1
  76. package/dist/agents/claude.js +0 -195
  77. package/dist/agents/codex.d.ts +0 -19
  78. package/dist/agents/codex.d.ts.map +0 -1
  79. package/dist/agents/codex.js +0 -216
  80. package/dist/agents/cursor.d.ts +0 -18
  81. package/dist/agents/cursor.d.ts.map +0 -1
  82. package/dist/agents/cursor.js +0 -220
  83. package/dist/agents/detect.d.ts +0 -46
  84. package/dist/agents/detect.d.ts.map +0 -1
  85. package/dist/agents/detect.js +0 -80
  86. package/dist/agents/gemini.d.ts +0 -17
  87. package/dist/agents/gemini.d.ts.map +0 -1
  88. package/dist/agents/gemini.js +0 -186
  89. package/dist/agents/index.d.ts +0 -6
  90. package/dist/agents/index.d.ts.map +0 -1
  91. package/dist/agents/index.js +0 -5
  92. package/dist/agents/invoke.d.ts +0 -12
  93. package/dist/agents/invoke.d.ts.map +0 -1
  94. package/dist/agents/invoke.js +0 -96
  95. package/dist/agents/qwen.d.ts +0 -17
  96. package/dist/agents/qwen.d.ts.map +0 -1
  97. package/dist/agents/qwen.js +0 -172
  98. package/dist/agents/registry.d.ts +0 -19
  99. package/dist/agents/registry.d.ts.map +0 -1
  100. package/dist/agents/registry.js +0 -34
  101. package/dist/agents/shared.d.ts +0 -28
  102. package/dist/agents/shared.d.ts.map +0 -1
  103. package/dist/agents/shared.js +0 -35
  104. package/dist/agents/types.d.ts +0 -186
  105. package/dist/agents/types.d.ts.map +0 -1
  106. package/dist/agents/types.js +0 -23
  107. package/dist/index.d.ts +0 -3
  108. package/dist/index.d.ts.map +0 -1
  109. package/dist/index.js +0 -2
  110. package/dist/mcp/sourceFence.d.ts +0 -23
  111. package/dist/mcp/sourceFence.d.ts.map +0 -1
  112. package/dist/mcp/sourceFence.js +0 -75
  113. package/dist/mcp/sourceServer.d.ts +0 -3
  114. package/dist/mcp/sourceServer.d.ts.map +0 -1
  115. package/dist/mcp/sourceServer.js +0 -116
  116. package/dist/playwright/cdpStatus.d.ts +0 -29
  117. package/dist/playwright/cdpStatus.d.ts.map +0 -1
  118. package/dist/playwright/cdpStatus.js +0 -119
  119. package/dist/playwright/preflight.d.ts +0 -31
  120. package/dist/playwright/preflight.d.ts.map +0 -1
  121. package/dist/playwright/preflight.js +0 -82
  122. package/dist/playwright/preflightCache.d.ts +0 -27
  123. package/dist/playwright/preflightCache.d.ts.map +0 -1
  124. package/dist/playwright/preflightCache.js +0 -21
  125. package/dist/playwright/raiseWindow.d.ts +0 -10
  126. package/dist/playwright/raiseWindow.d.ts.map +0 -1
  127. package/dist/playwright/raiseWindow.js +0 -158
  128. package/dist/playwright/resolveMcpConfig.d.ts +0 -55
  129. package/dist/playwright/resolveMcpConfig.d.ts.map +0 -1
  130. package/dist/playwright/resolveMcpConfig.js +0 -66
  131. package/dist/plugin-api.d.ts +0 -235
  132. package/dist/plugin-api.d.ts.map +0 -1
  133. package/dist/plugin-api.js +0 -52
  134. package/dist/runSession.d.ts +0 -42
  135. package/dist/runSession.d.ts.map +0 -1
  136. package/dist/runSession.js +0 -81
  137. package/dist/scripts/bench-multi-tab.d.ts +0 -2
  138. package/dist/scripts/bench-multi-tab.d.ts.map +0 -1
  139. package/dist/scripts/bench-multi-tab.js +0 -192
  140. package/dist/scripts/bench-ttfb.d.ts +0 -2
  141. package/dist/scripts/bench-ttfb.d.ts.map +0 -1
  142. package/dist/scripts/bench-ttfb.js +0 -127
  143. package/dist/scripts/start-chrome.d.ts +0 -3
  144. package/dist/scripts/start-chrome.d.ts.map +0 -1
  145. package/dist/scripts/start-chrome.js +0 -23
  146. package/dist/service/cdpHandlers.d.ts +0 -44
  147. package/dist/service/cdpHandlers.d.ts.map +0 -1
  148. package/dist/service/cdpHandlers.js +0 -85
  149. package/dist/service/cdpHint.d.ts +0 -48
  150. package/dist/service/cdpHint.d.ts.map +0 -1
  151. package/dist/service/cdpHint.js +0 -216
  152. package/dist/service/conventions.d.ts +0 -8
  153. package/dist/service/conventions.d.ts.map +0 -1
  154. package/dist/service/conventions.js +0 -42
  155. package/dist/service/saveHandlers.d.ts +0 -52
  156. package/dist/service/saveHandlers.d.ts.map +0 -1
  157. package/dist/service/saveHandlers.js +0 -75
  158. package/dist/service/types.d.ts +0 -58
  159. package/dist/service/types.d.ts.map +0 -1
  160. package/dist/service/types.js +0 -26
  161. package/dist/service.d.ts +0 -50
  162. package/dist/service.d.ts.map +0 -1
  163. package/dist/service.js +0 -1065
  164. package/dist/skills/writeSkill.d.ts +0 -27
  165. package/dist/skills/writeSkill.d.ts.map +0 -1
  166. package/dist/skills/writeSkill.js +0 -13
  167. package/dist/specs/extractPageObjects.d.ts +0 -18
  168. package/dist/specs/extractPageObjects.d.ts.map +0 -1
  169. package/dist/specs/extractPageObjects.js +0 -98
  170. package/dist/specs/listSpecs.d.ts +0 -52
  171. package/dist/specs/listSpecs.d.ts.map +0 -1
  172. package/dist/specs/listSpecs.js +0 -139
  173. package/dist/specs/optimizationSuggestion.d.ts +0 -26
  174. package/dist/specs/optimizationSuggestion.d.ts.map +0 -1
  175. package/dist/specs/optimizationSuggestion.js +0 -28
  176. package/dist/specs/optimizeSpecWithAgent.d.ts +0 -11
  177. package/dist/specs/optimizeSpecWithAgent.d.ts.map +0 -1
  178. package/dist/specs/optimizeSpecWithAgent.js +0 -40
  179. package/dist/specs/writeCaseCsv.d.ts +0 -28
  180. package/dist/specs/writeCaseCsv.d.ts.map +0 -1
  181. package/dist/specs/writeCaseCsv.js +0 -134
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hover-dev/core",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "Hover's local Node service: agent invocation, Playwright CDP preflight, WebSocket bridge.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Hyperyond",
@@ -20,37 +20,25 @@
20
20
  "claude"
21
21
  ],
22
22
  "type": "module",
23
- "main": "dist/index.js",
24
- "types": "dist/index.d.ts",
23
+ "main": "dist/engine.js",
24
+ "types": "dist/engine.d.ts",
25
25
  "exports": {
26
26
  ".": {
27
- "types": "./dist/index.d.ts",
28
- "import": "./dist/index.js"
27
+ "types": "./dist/engine.d.ts",
28
+ "import": "./dist/engine.js"
29
29
  },
30
- "./agents": {
31
- "types": "./dist/agents/index.d.ts",
32
- "import": "./dist/agents/index.js"
33
- },
34
- "./service": {
35
- "types": "./dist/service.d.ts",
36
- "import": "./dist/service.js"
37
- },
38
- "./launch-chrome": {
39
- "types": "./dist/playwright/launchChrome.d.ts",
40
- "import": "./dist/playwright/launchChrome.js"
41
- },
42
- "./plugin-api": {
43
- "types": "./dist/plugin-api.d.ts",
44
- "import": "./dist/plugin-api.js"
30
+ "./engine": {
31
+ "types": "./dist/engine.d.ts",
32
+ "import": "./dist/engine.js"
45
33
  }
46
34
  },
47
35
  "files": [
48
36
  "dist",
37
+ "seeds",
49
38
  "README.md"
50
39
  ],
51
40
  "dependencies": {
52
41
  "@modelcontextprotocol/sdk": "^1.29.0",
53
- "@playwright/mcp": "0.0.75",
54
42
  "cross-spawn": "^7.0.6",
55
43
  "playwright-core": "^1.50.0",
56
44
  "ts-morph": "^28.0.0",
@@ -70,14 +58,6 @@
70
58
  "build": "tsc -p tsconfig.build.json",
71
59
  "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput",
72
60
  "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
73
- "smoke": "tsx src/smoke.ts",
74
- "smoke:chrome": "tsx src/scripts/start-chrome.ts",
75
- "detect": "tsx src/scripts/detect-cli.ts",
76
- "verify-widget": "tsx src/scripts/verify-widget.ts",
77
- "verify-spec": "tsx src/scripts/verify-spec.ts",
78
- "ws-smoke": "tsx src/scripts/ws-smoke.ts",
79
- "bench-ttfb": "tsx src/scripts/bench-ttfb.ts",
80
- "bench-multi-tab": "tsx src/scripts/bench-multi-tab.ts",
81
61
  "test": "vitest run",
82
62
  "test:watch": "vitest"
83
63
  },
@@ -1,16 +0,0 @@
1
- import type { AgentDescriptor, ParserState } from './types.js';
2
- export declare const aiderAgent: AgentDescriptor;
3
- /**
4
- * Test-only escape hatches, same pattern as cursor.ts / codex.ts.
5
- */
6
- export declare const __testing: {
7
- freshState: () => ParserState;
8
- resetCounters: (state: ParserState) => void;
9
- getState: (state: ParserState) => {
10
- runningLines: number;
11
- runningSessionId: string | undefined;
12
- collectedText: string[];
13
- sawErrorEvent: boolean;
14
- };
15
- };
16
- //# sourceMappingURL=aider.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"aider.d.ts","sourceRoot":"","sources":["../../src/agents/aider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAA8B,WAAW,EAAE,MAAM,YAAY,CAAC;AA8G3F,eAAO,MAAM,UAAU,EAAE,eA0GxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS;sBACJ,WAAW;2BACJ,WAAW;sBAChB,WAAW;;;;;;CAS9B,CAAC"}
@@ -1,161 +0,0 @@
1
- import { HOVER_PROMPT_PREFACE } from './shared.js';
2
- function aiderState(state) {
3
- if (typeof state.runningLines !== 'number') {
4
- state.runningLines = 0;
5
- state.collectedText = [];
6
- state.sawErrorEvent = false;
7
- state.runningSessionId = undefined;
8
- }
9
- return state;
10
- }
11
- function resetAiderCounters(s) {
12
- s.runningLines = 0;
13
- s.collectedText = [];
14
- s.sawErrorEvent = false;
15
- s.runningSessionId = undefined;
16
- }
17
- // Aider has no system-prompt flag, so we prepend the standing HOVER-mode
18
- // preface (HOVER_PROMPT_PREFACE, from shared.ts) to the user prompt (same
19
- // approach as cursor.ts). The agent treats it as the leading user-message text.
20
- /**
21
- * Lines we treat as noise and drop instead of surfacing as text events.
22
- * Aider chatters with status lines that would clutter the widget panel.
23
- * Conservative list — anything we don't explicitly skip falls through.
24
- */
25
- function isNoiseLine(line) {
26
- const t = line.trim();
27
- if (!t)
28
- return true;
29
- // Common aider boilerplate / banner lines.
30
- if (/^Aider v\d/i.test(t))
31
- return true;
32
- if (/^Main model:/i.test(t))
33
- return true;
34
- if (/^Weak model:/i.test(t))
35
- return true;
36
- if (/^Git repo:/i.test(t))
37
- return true;
38
- if (/^Repo-map:/i.test(t))
39
- return true;
40
- if (/^VSCode terminal detected/i.test(t))
41
- return true;
42
- if (/^Use \/help/i.test(t))
43
- return true;
44
- if (/^Tokens:.*sent.*received/i.test(t))
45
- return true;
46
- if (/^─{3,}$/.test(t))
47
- return true; // horizontal rule
48
- return false;
49
- }
50
- function detectErrorLine(line) {
51
- // Aider prints errors / API failures with a leading marker.
52
- return /^(error|fatal|api error|litellm.*error)/i.test(line.trim());
53
- }
54
- export const aiderAgent = {
55
- id: 'aider',
56
- binName: 'aider',
57
- protocol: 'argv',
58
- streamFormat: 'plain-text',
59
- sandboxStrength: 'soft',
60
- display: {
61
- label: 'Aider',
62
- tagline: 'Aider — soft sandbox, plain-text stream, no MCP support',
63
- homepage: 'https://aider.chat',
64
- installHint: 'pipx install aider-chat',
65
- },
66
- buildArgs(opts) {
67
- // Prepend HOVER-mode preface plus any caller-supplied appendSystemPrompt
68
- // to the prompt. Aider has no --append-system-prompt flag, so this is
69
- // the closest functional analogue (same trick as cursor.ts).
70
- const preface = opts.appendSystemPrompt && opts.appendSystemPrompt.trim().length > 0
71
- ? `${HOVER_PROMPT_PREFACE} ${opts.appendSystemPrompt}`
72
- : HOVER_PROMPT_PREFACE;
73
- const finalPrompt = `${preface}\n\n${opts.prompt}`;
74
- const args = ['--message', finalPrompt];
75
- // Auto-confirm every prompt so the run doesn't hang.
76
- args.push('--yes-always');
77
- // Make stdout line-buffered instead of character-streamed; friendlier
78
- // for our per-line parseEvent loop.
79
- args.push('--no-stream');
80
- // Defang git side-effects. Aider's default behaviour is to auto-commit
81
- // every edit it makes; for a browser-driving agent that should never
82
- // edit files this is still a hazard if cwd is a stale repo.
83
- args.push('--no-auto-commits');
84
- args.push('--no-git');
85
- if (opts.model) {
86
- args.push('--model', opts.model);
87
- }
88
- // Aider's `--restore-chat-history` is a boolean (no session-id form);
89
- // we deliberately do NOT pass it. `opts.sessionId` is ignored because
90
- // there is no way to select a specific past session by ID.
91
- // No equivalents for --max-budget-usd / --allowedTools / --mcp-config /
92
- // --append-system-prompt — all four are absent from aider.
93
- return args;
94
- },
95
- parseEvent(line, state = {}) {
96
- const s = aiderState(state);
97
- const out = [];
98
- // Emit a synthetic session_start on the very first non-empty line so
99
- // the widget gets the same shape it expects from JSON-based agents.
100
- if (!s.runningSessionId) {
101
- // Cheap unique id; aider has no real session_id we can echo. The
102
- // Math.random() suffix is load-bearing — two states created in the
103
- // same millisecond would otherwise collide and break per-invocation
104
- // session tracking.
105
- const rand = Math.random().toString(36).slice(2, 8);
106
- s.runningSessionId = `aider-${Date.now().toString(36)}-${rand}`;
107
- out.push({ kind: 'session_start', sessionId: s.runningSessionId });
108
- }
109
- if (isNoiseLine(line))
110
- return out;
111
- if (detectErrorLine(line)) {
112
- s.sawErrorEvent = true;
113
- out.push({ kind: 'text', text: line.trim() });
114
- return out;
115
- }
116
- // Treat everything else as assistant text. Aider has no per-tool events
117
- // so we cannot emit tool_use / tool_result — see file-header doc comment.
118
- s.runningLines += 1;
119
- s.collectedText.push(line.trim());
120
- out.push({ kind: 'text', text: line.trim() });
121
- return out;
122
- },
123
- /**
124
- * Aider doesn't emit a terminal event — the child process simply exits
125
- * after the final printed line. Synthesize session_end from accumulated
126
- * state, same pattern as codex.ts.
127
- */
128
- onStreamEnd(exitCode, state = {}) {
129
- const s = aiderState(state);
130
- // The "summary" is the last non-empty text line, which is typically
131
- // aider's final answer. If we collected nothing, leave it undefined
132
- // rather than fabricating.
133
- const lastText = s.collectedText.length > 0
134
- ? s.collectedText[s.collectedText.length - 1]
135
- : undefined;
136
- return {
137
- kind: 'session_end',
138
- turns: s.runningLines,
139
- // costUsd intentionally undefined — aider's "Tokens:" status line is
140
- // ad-hoc text, not a stable API. We don't fabricate a number.
141
- isError: s.sawErrorEvent || (exitCode != null && exitCode !== 0),
142
- summary: lastText,
143
- };
144
- },
145
- };
146
- /**
147
- * Test-only escape hatches, same pattern as cursor.ts / codex.ts.
148
- */
149
- export const __testing = {
150
- freshState: () => ({}),
151
- resetCounters: (state) => resetAiderCounters(aiderState(state)),
152
- getState: (state) => {
153
- const s = aiderState(state);
154
- return {
155
- runningLines: s.runningLines,
156
- runningSessionId: s.runningSessionId,
157
- collectedText: [...s.collectedText],
158
- sawErrorEvent: s.sawErrorEvent,
159
- };
160
- },
161
- };
@@ -1,11 +0,0 @@
1
- import type { AgentDescriptor, InvokeOptions } from './types.js';
2
- /**
3
- * Build argv for spawning an agent.
4
- *
5
- * Per-agent argument logic lives on the descriptor (e.g. claude.ts owns its
6
- * own `--mcp-config`, `--permission-mode` etc.). This dispatcher only
7
- * gates by protocol — `acp` and `pi-rpc` are not yet implemented because
8
- * they require a long-lived bidirectional channel rather than argv.
9
- */
10
- export declare function buildArgv(descriptor: AgentDescriptor, opts: InvokeOptions): string[];
11
- //# sourceMappingURL=argv.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"argv.d.ts","sourceRoot":"","sources":["../../src/agents/argv.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGjE;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,eAAe,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,EAAE,CAepF"}
@@ -1,23 +0,0 @@
1
- import { UnsupportedAgentProtocolError } from './types.js';
2
- /**
3
- * Build argv for spawning an agent.
4
- *
5
- * Per-agent argument logic lives on the descriptor (e.g. claude.ts owns its
6
- * own `--mcp-config`, `--permission-mode` etc.). This dispatcher only
7
- * gates by protocol — `acp` and `pi-rpc` are not yet implemented because
8
- * they require a long-lived bidirectional channel rather than argv.
9
- */
10
- export function buildArgv(descriptor, opts) {
11
- switch (descriptor.protocol) {
12
- case 'argv':
13
- case 'stdin':
14
- return descriptor.buildArgs(opts);
15
- case 'acp':
16
- case 'pi-rpc':
17
- throw new UnsupportedAgentProtocolError(`Agent protocol "${descriptor.protocol}" is not yet implemented (agent: ${descriptor.id})`);
18
- default: {
19
- const exhaustive = descriptor.protocol;
20
- throw new UnsupportedAgentProtocolError(`Unknown protocol: ${String(exhaustive)}`);
21
- }
22
- }
23
- }
@@ -1,3 +0,0 @@
1
- import type { AgentDescriptor } from './types.js';
2
- export declare const claudeAgent: AgentDescriptor;
3
- //# sourceMappingURL=claude.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAA2C,MAAM,YAAY,CAAC;AA0H3F,eAAO,MAAM,WAAW,EAAE,eA2HzB,CAAC"}
@@ -1,195 +0,0 @@
1
- /**
2
- * Running-cost accumulator across one parser lifecycle. Claude Code's
3
- * stream-json sometimes carries `total_cost_usd` on intermediate events; when
4
- * it does we just forward it. When it doesn't, we estimate from token usage
5
- * using public per-million pricing. Hardcoded rates because they change
6
- * rarely and we'd rather not network-fetch a price table from a sandbox.
7
- *
8
- * The estimate is empirically about 1.5–2× the authoritative
9
- * `total_cost_usd` that arrives on the final `result` event (overhead from
10
- * tool-definition tokens we don't see + Claude's actual cache hit ratios
11
- * vs. our pessimistic accounting). That's fine for the widget's purpose:
12
- * give the user a signal of cost direction and order-of-magnitude so they
13
- * know when to hit Stop. The done card displays the final authoritative
14
- * number from `total_cost_usd`, so the user always sees the ground truth.
15
- */
16
- const PRICE_PER_M_USD = {
17
- // claude-sonnet-4 / 4.5 / 4.6 / 4.7 — all priced the same as of 2026
18
- sonnet: { in: 3, out: 15, cacheCreate: 3.75, cacheRead: 0.3 },
19
- opus: { in: 15, out: 75, cacheCreate: 18.75, cacheRead: 1.5 },
20
- haiku: { in: 1, out: 5, cacheCreate: 1.25, cacheRead: 0.1 },
21
- };
22
- function estimateCostUsd(modelHint, usage) {
23
- // Match the most specific tier by substring. e.g. 'claude-sonnet-4-6' → sonnet.
24
- const m = (modelHint ?? 'sonnet').toLowerCase();
25
- const tier = m.includes('opus') ? PRICE_PER_M_USD.opus :
26
- m.includes('haiku') ? PRICE_PER_M_USD.haiku :
27
- PRICE_PER_M_USD.sonnet;
28
- return ((usage.input_tokens ?? 0) * tier.in +
29
- (usage.output_tokens ?? 0) * tier.out +
30
- (usage.cache_creation_input_tokens ?? 0) * tier.cacheCreate +
31
- (usage.cache_read_input_tokens ?? 0) * tier.cacheRead) / 1_000_000;
32
- }
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
- /** Every built-in claude-code tool that has nothing to do with driving a
43
- * browser. Combined with `--strict-mcp-config` + an allow-list of mcp__*
44
- * ids, this leaves Claude with only the Playwright MCP (plus any
45
- * plugin-contributed MCPs) as a usable tool surface. */
46
- const CLAUDE_DEFAULT_DISALLOWED_TOOLS = [
47
- // file / shell / data access — never appropriate for browser driving
48
- 'Bash', 'BashOutput', 'KillBash',
49
- 'Edit', 'MultiEdit', 'Write', 'Read', 'NotebookEdit',
50
- 'Grep', 'Glob', 'Task', 'TodoWrite',
51
- 'WebFetch', 'WebSearch',
52
- // plan / worktree / cron / notification — irrelevant in -p mode
53
- 'EnterPlanMode', 'ExitPlanMode',
54
- 'EnterWorktree', 'ExitWorktree',
55
- 'CronCreate', 'CronDelete', 'CronList',
56
- 'PushNotification', 'RemoteTrigger',
57
- // task & tool introspection added in claude 2.1.x — let through and
58
- // the agent will burn turns exploring instead of executing
59
- 'ToolSearch',
60
- 'Monitor', 'TaskOutput', 'TaskStop',
61
- 'AskUserQuestion',
62
- 'ShareOnboardingGuide',
63
- // Skills are loaded independently of the --allowedTools allow-list, so an
64
- // allow-list of `mcp__playwright` does NOT block the `Skill` tool. Left
65
- // through, the agent burns a turn "checking for a project skill first" and
66
- // pollutes the crystallized spec with a junk `When · Skill` step. Deny it.
67
- 'Skill',
68
- // Playwright MCP's arbitrary-JS tools. browser_run_code_unsafe /
69
- // browser_evaluate run any JS in the page — a real prompt-injection exfil
70
- // path (fetch a token out, read localStorage) that punches through the
71
- // "Playwright MCP only" sandbox, and their output can't be translated into
72
- // a deterministic Playwright spec anyway (it lands as a `// TODO`). Agents
73
- // drive via click/fill/select and read state via snapshot instead.
74
- 'mcp__playwright__browser_run_code_unsafe',
75
- 'mcp__playwright__browser_evaluate',
76
- ];
77
- export const claudeAgent = {
78
- id: 'claude',
79
- binName: 'claude',
80
- protocol: 'argv',
81
- streamFormat: 'stream-json',
82
- sandboxStrength: 'hard',
83
- defaultDisallowedTools: CLAUDE_DEFAULT_DISALLOWED_TOOLS,
84
- apiKeyEnv: 'ANTHROPIC_API_KEY',
85
- display: {
86
- label: 'Claude Code',
87
- tagline: 'Anthropic — best-in-class browser driving, hard tool sandbox',
88
- homepage: 'https://docs.claude.com/claude-code',
89
- installHint: 'npm install -g @anthropic-ai/claude-code',
90
- },
91
- buildArgs(opts) {
92
- const args = ['-p', opts.prompt];
93
- args.push('--output-format', 'stream-json', '--verbose');
94
- args.push('--permission-mode', 'dontAsk');
95
- if (opts.mcpConfig) {
96
- args.push('--mcp-config', opts.mcpConfig, '--strict-mcp-config');
97
- }
98
- if (opts.allowedTools?.length) {
99
- args.push('--allowedTools', ...opts.allowedTools);
100
- }
101
- if (opts.disallowedTools?.length) {
102
- args.push('--disallowedTools', ...opts.disallowedTools);
103
- }
104
- if (opts.maxBudgetUsd != null) {
105
- args.push('--max-budget-usd', String(opts.maxBudgetUsd));
106
- }
107
- if (opts.model) {
108
- args.push('--model', opts.model);
109
- }
110
- if (opts.sessionId) {
111
- args.push('--resume', opts.sessionId);
112
- }
113
- if (opts.appendSystemPrompt && opts.appendSystemPrompt.trim().length > 0) {
114
- args.push('--append-system-prompt', opts.appendSystemPrompt);
115
- }
116
- return args;
117
- },
118
- parseEvent(line, state = {}) {
119
- if (!line.trim())
120
- return [];
121
- let ev;
122
- try {
123
- ev = JSON.parse(line);
124
- }
125
- catch {
126
- return [{ kind: 'raw', line }];
127
- }
128
- const s = claudeState(state);
129
- const out = [];
130
- if (ev.type === 'system' && ev.subtype === 'init') {
131
- // Fresh session — reset the cost/turn accumulator.
132
- s.runningCost = 0;
133
- s.runningTurns = 0;
134
- s.runningModel = ev.model;
135
- if (ev.session_id) {
136
- out.push({ kind: 'session_start', sessionId: ev.session_id, model: ev.model });
137
- }
138
- for (const server of ev.mcp_servers ?? []) {
139
- out.push({ kind: 'mcp_status', server: server.name, status: server.status });
140
- }
141
- return out;
142
- }
143
- if (ev.type === 'assistant') {
144
- s.runningTurns += 1;
145
- // Claude Code sometimes carries `total_cost_usd` on intermediate events;
146
- // when present it's authoritative (server-computed, includes anything
147
- // we'd miss). When absent, estimate from this turn's usage so the widget
148
- // still shows a growing $ counter on long runs.
149
- if (typeof ev.total_cost_usd === 'number') {
150
- s.runningCost = ev.total_cost_usd;
151
- }
152
- else if (ev.message?.usage) {
153
- s.runningCost += estimateCostUsd(s.runningModel ?? ev.message.model, ev.message.usage);
154
- }
155
- out.push({ kind: 'usage', costUsd: s.runningCost, turns: s.runningTurns });
156
- for (const block of ev.message?.content ?? []) {
157
- if (block.type === 'tool_use') {
158
- const name = block.name ?? '';
159
- const tool = name.replace(/^mcp__playwright__/, '');
160
- out.push({
161
- kind: 'tool_use',
162
- tool,
163
- input: block.input,
164
- costUsdSnapshot: s.runningCost,
165
- });
166
- }
167
- else if (block.type === 'text') {
168
- const text = block.text?.trim();
169
- if (text)
170
- out.push({ kind: 'text', text });
171
- }
172
- }
173
- return out;
174
- }
175
- if (ev.type === 'user') {
176
- for (const block of ev.message?.content ?? []) {
177
- if (block.type === 'tool_result') {
178
- out.push({ kind: 'tool_result', isError: block.is_error });
179
- }
180
- }
181
- return out;
182
- }
183
- if (ev.type === 'result') {
184
- out.push({
185
- kind: 'session_end',
186
- turns: ev.num_turns,
187
- costUsd: ev.total_cost_usd,
188
- isError: ev.is_error,
189
- summary: ev.result,
190
- });
191
- return out;
192
- }
193
- return [];
194
- },
195
- };
@@ -1,19 +0,0 @@
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
@@ -1 +0,0 @@
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;AAoK3F,eAAO,MAAM,UAAU,EAAE,eA6JxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS;sBACJ,WAAW;2BACJ,WAAW;sBAChB,WAAW;;;;;;;CAU9B,CAAC"}