harnery 0.0.1 → 0.2.1

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 (445) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -2
  3. package/bin/agent-coord +42 -0
  4. package/bin/agent-hook +44 -0
  5. package/bin/harn +40 -0
  6. package/dist/cli.d.ts +9 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +18 -0
  9. package/dist/commander.d.ts +128 -0
  10. package/dist/commander.d.ts.map +1 -0
  11. package/dist/commander.js +126 -0
  12. package/dist/commands/agents.d.ts +18 -0
  13. package/dist/commands/agents.d.ts.map +1 -0
  14. package/dist/commands/agents.js +3946 -0
  15. package/dist/commands/backup.d.ts +22 -0
  16. package/dist/commands/backup.d.ts.map +1 -0
  17. package/dist/commands/backup.js +262 -0
  18. package/dist/commands/browse-ai.d.ts +4 -0
  19. package/dist/commands/browse-ai.d.ts.map +1 -0
  20. package/dist/commands/browse-ai.js +156 -0
  21. package/dist/commands/browse.d.ts +4 -0
  22. package/dist/commands/browse.d.ts.map +1 -0
  23. package/dist/commands/browse.js +590 -0
  24. package/dist/commands/callers.d.ts +4 -0
  25. package/dist/commands/callers.d.ts.map +1 -0
  26. package/dist/commands/callers.js +276 -0
  27. package/dist/commands/completion.d.ts +17 -0
  28. package/dist/commands/completion.d.ts.map +1 -0
  29. package/dist/commands/completion.js +158 -0
  30. package/dist/commands/config-get.d.ts +4 -0
  31. package/dist/commands/config-get.d.ts.map +1 -0
  32. package/dist/commands/config-get.js +131 -0
  33. package/dist/commands/context.d.ts +11 -0
  34. package/dist/commands/context.d.ts.map +1 -0
  35. package/dist/commands/context.js +185 -0
  36. package/dist/commands/cookies.d.ts +4 -0
  37. package/dist/commands/cookies.d.ts.map +1 -0
  38. package/dist/commands/cookies.js +140 -0
  39. package/dist/commands/docs.d.ts +4 -0
  40. package/dist/commands/docs.d.ts.map +1 -0
  41. package/dist/commands/docs.js +137 -0
  42. package/dist/commands/doctor.d.ts +25 -0
  43. package/dist/commands/doctor.d.ts.map +1 -0
  44. package/dist/commands/doctor.js +200 -0
  45. package/dist/commands/edit-batch.d.ts +18 -0
  46. package/dist/commands/edit-batch.d.ts.map +1 -0
  47. package/dist/commands/edit-batch.js +172 -0
  48. package/dist/commands/eml.d.ts +4 -0
  49. package/dist/commands/eml.d.ts.map +1 -0
  50. package/dist/commands/eml.js +428 -0
  51. package/dist/commands/env.d.ts +4 -0
  52. package/dist/commands/env.d.ts.map +1 -0
  53. package/dist/commands/env.js +201 -0
  54. package/dist/commands/fetch.d.ts +4 -0
  55. package/dist/commands/fetch.d.ts.map +1 -0
  56. package/dist/commands/fetch.js +99 -0
  57. package/dist/commands/file-history.d.ts +4 -0
  58. package/dist/commands/file-history.d.ts.map +1 -0
  59. package/dist/commands/file-history.js +152 -0
  60. package/dist/commands/grep.d.ts +4 -0
  61. package/dist/commands/grep.d.ts.map +1 -0
  62. package/dist/commands/grep.js +317 -0
  63. package/dist/commands/init.d.ts +82 -0
  64. package/dist/commands/init.d.ts.map +1 -0
  65. package/dist/commands/init.js +288 -0
  66. package/dist/commands/outline.d.ts +4 -0
  67. package/dist/commands/outline.d.ts.map +1 -0
  68. package/dist/commands/outline.js +509 -0
  69. package/dist/commands/presence.d.ts +12 -0
  70. package/dist/commands/presence.d.ts.map +1 -0
  71. package/dist/commands/presence.js +123 -0
  72. package/dist/commands/read.d.ts +7 -0
  73. package/dist/commands/read.d.ts.map +1 -0
  74. package/dist/commands/read.js +46 -0
  75. package/dist/commands/scratch.d.ts +4 -0
  76. package/dist/commands/scratch.d.ts.map +1 -0
  77. package/dist/commands/scratch.js +426 -0
  78. package/dist/commands/session.d.ts +4 -0
  79. package/dist/commands/session.d.ts.map +1 -0
  80. package/dist/commands/session.js +162 -0
  81. package/dist/commands/sync.d.ts +24 -0
  82. package/dist/commands/sync.d.ts.map +1 -0
  83. package/dist/commands/sync.js +275 -0
  84. package/dist/commands/toc.d.ts +5 -0
  85. package/dist/commands/toc.d.ts.map +1 -0
  86. package/dist/commands/toc.js +153 -0
  87. package/dist/commands/tokens.d.ts +4 -0
  88. package/dist/commands/tokens.d.ts.map +1 -0
  89. package/dist/commands/tokens.js +48 -0
  90. package/dist/commands/tunnel.d.ts +4 -0
  91. package/dist/commands/tunnel.d.ts.map +1 -0
  92. package/dist/commands/tunnel.js +513 -0
  93. package/dist/commands/uninstall.d.ts +22 -0
  94. package/dist/commands/uninstall.d.ts.map +1 -0
  95. package/dist/commands/uninstall.js +126 -0
  96. package/dist/commands/web.d.ts +4 -0
  97. package/dist/commands/web.d.ts.map +1 -0
  98. package/dist/commands/web.js +165 -0
  99. package/dist/core/agents/canonical-emit.d.ts +27 -0
  100. package/dist/core/agents/canonical-emit.d.ts.map +1 -0
  101. package/dist/core/agents/canonical-emit.js +72 -0
  102. package/dist/core/agents/cli-emit.d.ts +27 -0
  103. package/dist/core/agents/cli-emit.d.ts.map +1 -0
  104. package/dist/core/agents/cli-emit.js +57 -0
  105. package/dist/core/agents/cli.d.ts +10 -0
  106. package/dist/core/agents/cli.d.ts.map +1 -0
  107. package/dist/core/agents/cli.js +757 -0
  108. package/dist/core/agents/codex-replay.d.ts +29 -0
  109. package/dist/core/agents/codex-replay.d.ts.map +1 -0
  110. package/dist/core/agents/codex-replay.js +138 -0
  111. package/dist/core/agents/coord-client.d.ts +98 -0
  112. package/dist/core/agents/coord-client.d.ts.map +1 -0
  113. package/dist/core/agents/coord-client.js +212 -0
  114. package/dist/core/agents/events/consume.d.ts +59 -0
  115. package/dist/core/agents/events/consume.d.ts.map +1 -0
  116. package/dist/core/agents/events/consume.js +147 -0
  117. package/dist/core/agents/events/emit.d.ts +42 -0
  118. package/dist/core/agents/events/emit.d.ts.map +1 -0
  119. package/dist/core/agents/events/emit.js +70 -0
  120. package/dist/core/agents/events/ulid.d.ts +11 -0
  121. package/dist/core/agents/events/ulid.d.ts.map +1 -0
  122. package/dist/core/agents/events/ulid.js +47 -0
  123. package/dist/core/agents/index.d.ts +14 -0
  124. package/dist/core/agents/index.d.ts.map +1 -0
  125. package/dist/core/agents/index.js +13 -0
  126. package/dist/core/agents/paths.d.ts +6 -0
  127. package/dist/core/agents/paths.d.ts.map +1 -0
  128. package/dist/core/agents/paths.js +17 -0
  129. package/dist/core/agents/render/prompt-context.d.ts +43 -0
  130. package/dist/core/agents/render/prompt-context.d.ts.map +1 -0
  131. package/dist/core/agents/render/prompt-context.js +335 -0
  132. package/dist/core/agents/render/session-context.d.ts +39 -0
  133. package/dist/core/agents/render/session-context.d.ts.map +1 -0
  134. package/dist/core/agents/render/session-context.js +283 -0
  135. package/dist/core/agents/rules/claim-conflict.d.ts +35 -0
  136. package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -0
  137. package/dist/core/agents/rules/claim-conflict.js +244 -0
  138. package/dist/core/agents/rules/commit-conflict.d.ts +59 -0
  139. package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -0
  140. package/dist/core/agents/rules/commit-conflict.js +244 -0
  141. package/dist/core/agents/rules/stop-hook.d.ts +44 -0
  142. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -0
  143. package/dist/core/agents/rules/stop-hook.js +161 -0
  144. package/dist/core/agents/session-events.d.ts +41 -0
  145. package/dist/core/agents/session-events.d.ts.map +1 -0
  146. package/dist/core/agents/session-events.js +205 -0
  147. package/dist/core/agents/state/activity-log.d.ts +18 -0
  148. package/dist/core/agents/state/activity-log.d.ts.map +1 -0
  149. package/dist/core/agents/state/activity-log.js +34 -0
  150. package/dist/core/agents/state/council.d.ts +39 -0
  151. package/dist/core/agents/state/council.d.ts.map +1 -0
  152. package/dist/core/agents/state/council.js +216 -0
  153. package/dist/core/agents/state/heartbeat-projector.d.ts +59 -0
  154. package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -0
  155. package/dist/core/agents/state/heartbeat-projector.js +436 -0
  156. package/dist/core/agents/state/heartbeat-writer.d.ts +64 -0
  157. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -0
  158. package/dist/core/agents/state/heartbeat-writer.js +271 -0
  159. package/dist/core/agents/state/names.d.ts +35 -0
  160. package/dist/core/agents/state/names.d.ts.map +1 -0
  161. package/dist/core/agents/state/names.js +376 -0
  162. package/dist/core/agents/state/pidmap.d.ts +11 -0
  163. package/dist/core/agents/state/pidmap.d.ts.map +1 -0
  164. package/dist/core/agents/state/pidmap.js +32 -0
  165. package/dist/core/agents/state/scratch.d.ts +27 -0
  166. package/dist/core/agents/state/scratch.d.ts.map +1 -0
  167. package/dist/core/agents/state/scratch.js +90 -0
  168. package/dist/core/agents/state/shell-mutation.d.ts +17 -0
  169. package/dist/core/agents/state/shell-mutation.d.ts.map +1 -0
  170. package/dist/core/agents/state/shell-mutation.js +41 -0
  171. package/dist/core/agents/state/stale-sweep.d.ts +16 -0
  172. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -0
  173. package/dist/core/agents/state/stale-sweep.js +166 -0
  174. package/dist/core/config.d.ts +29 -0
  175. package/dist/core/config.d.ts.map +1 -0
  176. package/dist/core/config.js +108 -0
  177. package/dist/core/hooks/cli.d.ts +21 -0
  178. package/dist/core/hooks/cli.d.ts.map +1 -0
  179. package/dist/core/hooks/cli.js +1123 -0
  180. package/dist/core/hooks/effects/image-capture.d.ts +43 -0
  181. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -0
  182. package/dist/core/hooks/effects/image-capture.js +288 -0
  183. package/dist/core/hooks/effects/index.d.ts +64 -0
  184. package/dist/core/hooks/effects/index.d.ts.map +1 -0
  185. package/dist/core/hooks/effects/index.js +197 -0
  186. package/dist/core/hooks/events/emit.d.ts +31 -0
  187. package/dist/core/hooks/events/emit.d.ts.map +1 -0
  188. package/dist/core/hooks/events/emit.js +89 -0
  189. package/dist/core/hooks/events/schema.d.ts +235 -0
  190. package/dist/core/hooks/events/schema.d.ts.map +1 -0
  191. package/dist/core/hooks/events/schema.js +12 -0
  192. package/dist/core/hooks/events/ulid.d.ts +10 -0
  193. package/dist/core/hooks/events/ulid.d.ts.map +1 -0
  194. package/dist/core/hooks/events/ulid.js +47 -0
  195. package/dist/core/hooks/harness/detect.d.ts +9 -0
  196. package/dist/core/hooks/harness/detect.d.ts.map +1 -0
  197. package/dist/core/hooks/harness/detect.js +29 -0
  198. package/dist/core/hooks/harness/events.d.ts +45 -0
  199. package/dist/core/hooks/harness/events.d.ts.map +1 -0
  200. package/dist/core/hooks/harness/events.js +71 -0
  201. package/dist/core/hooks/harness/output.d.ts +46 -0
  202. package/dist/core/hooks/harness/output.d.ts.map +1 -0
  203. package/dist/core/hooks/harness/output.js +87 -0
  204. package/dist/core/hooks/harness/parse.d.ts +67 -0
  205. package/dist/core/hooks/harness/parse.d.ts.map +1 -0
  206. package/dist/core/hooks/harness/parse.js +132 -0
  207. package/dist/core/hooks/index.d.ts +8 -0
  208. package/dist/core/hooks/index.d.ts.map +1 -0
  209. package/dist/core/hooks/index.js +7 -0
  210. package/dist/core/hooks/resolve/anchor.d.ts +37 -0
  211. package/dist/core/hooks/resolve/anchor.d.ts.map +1 -0
  212. package/dist/core/hooks/resolve/anchor.js +48 -0
  213. package/dist/core/hooks/resolve/coord-root.d.ts +6 -0
  214. package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -0
  215. package/dist/core/hooks/resolve/coord-root.js +27 -0
  216. package/dist/core/hooks/resolve/intent.d.ts +33 -0
  217. package/dist/core/hooks/resolve/intent.d.ts.map +1 -0
  218. package/dist/core/hooks/resolve/intent.js +79 -0
  219. package/dist/core/hooks/resolve/owner.d.ts +42 -0
  220. package/dist/core/hooks/resolve/owner.d.ts.map +1 -0
  221. package/dist/core/hooks/resolve/owner.js +140 -0
  222. package/dist/core/hooks/resolve/transcript.d.ts +26 -0
  223. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -0
  224. package/dist/core/hooks/resolve/transcript.js +73 -0
  225. package/dist/index.d.ts +15 -0
  226. package/dist/index.d.ts.map +1 -0
  227. package/dist/index.js +13 -0
  228. package/dist/lib/agent-browser/client.d.ts +99 -0
  229. package/dist/lib/agent-browser/client.d.ts.map +1 -0
  230. package/dist/lib/agent-browser/client.js +177 -0
  231. package/dist/lib/agent-browser/index.d.ts +2 -0
  232. package/dist/lib/agent-browser/index.d.ts.map +1 -0
  233. package/dist/lib/agent-browser/index.js +1 -0
  234. package/dist/lib/browser/client.d.ts +193 -0
  235. package/dist/lib/browser/client.d.ts.map +1 -0
  236. package/dist/lib/browser/client.js +325 -0
  237. package/dist/lib/browser/dev-overlay.d.ts +23 -0
  238. package/dist/lib/browser/dev-overlay.d.ts.map +1 -0
  239. package/dist/lib/browser/dev-overlay.js +153 -0
  240. package/dist/lib/browser/index.d.ts +5 -0
  241. package/dist/lib/browser/index.d.ts.map +1 -0
  242. package/dist/lib/browser/index.js +2 -0
  243. package/dist/lib/browser/layout.d.ts +79 -0
  244. package/dist/lib/browser/layout.d.ts.map +1 -0
  245. package/dist/lib/browser/layout.js +220 -0
  246. package/dist/lib/browser/visibility.d.ts +86 -0
  247. package/dist/lib/browser/visibility.d.ts.map +1 -0
  248. package/dist/lib/browser/visibility.js +333 -0
  249. package/dist/lib/browser/visual-diff.d.ts +38 -0
  250. package/dist/lib/browser/visual-diff.d.ts.map +1 -0
  251. package/dist/lib/browser/visual-diff.js +107 -0
  252. package/dist/lib/completion/bash.d.ts +25 -0
  253. package/dist/lib/completion/bash.d.ts.map +1 -0
  254. package/dist/lib/completion/bash.js +284 -0
  255. package/dist/lib/completion/fish.d.ts +16 -0
  256. package/dist/lib/completion/fish.d.ts.map +1 -0
  257. package/dist/lib/completion/fish.js +118 -0
  258. package/dist/lib/completion/index.d.ts +5 -0
  259. package/dist/lib/completion/index.d.ts.map +1 -0
  260. package/dist/lib/completion/index.js +4 -0
  261. package/dist/lib/completion/walk.d.ts +68 -0
  262. package/dist/lib/completion/walk.d.ts.map +1 -0
  263. package/dist/lib/completion/walk.js +102 -0
  264. package/dist/lib/completion/zsh.d.ts +13 -0
  265. package/dist/lib/completion/zsh.d.ts.map +1 -0
  266. package/dist/lib/completion/zsh.js +249 -0
  267. package/dist/lib/context/index.d.ts +107 -0
  268. package/dist/lib/context/index.d.ts.map +1 -0
  269. package/dist/lib/context/index.js +275 -0
  270. package/dist/lib/cookies/client.d.ts +131 -0
  271. package/dist/lib/cookies/client.d.ts.map +1 -0
  272. package/dist/lib/cookies/client.js +239 -0
  273. package/dist/lib/cookies/index.d.ts +2 -0
  274. package/dist/lib/cookies/index.d.ts.map +1 -0
  275. package/dist/lib/cookies/index.js +1 -0
  276. package/dist/lib/council/index.d.ts +266 -0
  277. package/dist/lib/council/index.d.ts.map +1 -0
  278. package/dist/lib/council/index.js +674 -0
  279. package/dist/lib/docs-index.d.ts +28 -0
  280. package/dist/lib/docs-index.d.ts.map +1 -0
  281. package/dist/lib/docs-index.js +169 -0
  282. package/dist/lib/docs-lint.d.ts +26 -0
  283. package/dist/lib/docs-lint.d.ts.map +1 -0
  284. package/dist/lib/docs-lint.js +378 -0
  285. package/dist/lib/docs-sweep.d.ts +34 -0
  286. package/dist/lib/docs-sweep.d.ts.map +1 -0
  287. package/dist/lib/docs-sweep.js +304 -0
  288. package/dist/lib/docs.d.ts +27 -0
  289. package/dist/lib/docs.d.ts.map +1 -0
  290. package/dist/lib/docs.js +142 -0
  291. package/dist/lib/env.d.ts +11 -0
  292. package/dist/lib/env.d.ts.map +1 -0
  293. package/dist/lib/env.js +12 -0
  294. package/dist/lib/exec.d.ts +32 -0
  295. package/dist/lib/exec.d.ts.map +1 -0
  296. package/dist/lib/exec.js +54 -0
  297. package/dist/lib/format.d.ts +29 -0
  298. package/dist/lib/format.d.ts.map +1 -0
  299. package/dist/lib/format.js +139 -0
  300. package/dist/lib/http/client.d.ts +56 -0
  301. package/dist/lib/http/client.d.ts.map +1 -0
  302. package/dist/lib/http/client.js +160 -0
  303. package/dist/lib/http/index.d.ts +2 -0
  304. package/dist/lib/http/index.d.ts.map +1 -0
  305. package/dist/lib/http/index.js +1 -0
  306. package/dist/lib/identities/index.d.ts +77 -0
  307. package/dist/lib/identities/index.d.ts.map +1 -0
  308. package/dist/lib/identities/index.js +190 -0
  309. package/dist/lib/machine.d.ts +19 -0
  310. package/dist/lib/machine.d.ts.map +1 -0
  311. package/dist/lib/machine.js +61 -0
  312. package/dist/lib/presence.d.ts +48 -0
  313. package/dist/lib/presence.d.ts.map +1 -0
  314. package/dist/lib/presence.js +123 -0
  315. package/dist/lib/readability/client.d.ts +39 -0
  316. package/dist/lib/readability/client.d.ts.map +1 -0
  317. package/dist/lib/readability/client.js +121 -0
  318. package/dist/lib/readability/index.d.ts +2 -0
  319. package/dist/lib/readability/index.d.ts.map +1 -0
  320. package/dist/lib/readability/index.js +1 -0
  321. package/dist/lib/scratch/index.d.ts +74 -0
  322. package/dist/lib/scratch/index.d.ts.map +1 -0
  323. package/dist/lib/scratch/index.js +393 -0
  324. package/dist/lib/tunnel/gate.d.ts +12 -0
  325. package/dist/lib/tunnel/gate.d.ts.map +1 -0
  326. package/dist/lib/tunnel/gate.js +101 -0
  327. package/dist/lib/tunnel/state.d.ts +34 -0
  328. package/dist/lib/tunnel/state.d.ts.map +1 -0
  329. package/dist/lib/tunnel/state.js +132 -0
  330. package/package.json +160 -8
  331. package/schemas/.gitkeep +0 -0
  332. package/schemas/config.schema.json +109 -0
  333. package/src/cli.ts +22 -0
  334. package/src/commander.ts +242 -0
  335. package/src/commands/.gitkeep +0 -0
  336. package/src/commands/agents.ts +4567 -0
  337. package/src/commands/backup.ts +305 -0
  338. package/src/commands/browse-ai.ts +198 -0
  339. package/src/commands/browse.ts +849 -0
  340. package/src/commands/callers.ts +363 -0
  341. package/src/commands/completion.ts +193 -0
  342. package/src/commands/config-get.ts +161 -0
  343. package/src/commands/context.ts +209 -0
  344. package/src/commands/cookies.ts +198 -0
  345. package/src/commands/docs.ts +174 -0
  346. package/src/commands/doctor.ts +231 -0
  347. package/src/commands/edit-batch.ts +233 -0
  348. package/src/commands/eml.ts +519 -0
  349. package/src/commands/env.ts +254 -0
  350. package/src/commands/fetch.ts +136 -0
  351. package/src/commands/file-history.ts +202 -0
  352. package/src/commands/grep.ts +371 -0
  353. package/src/commands/init.ts +335 -0
  354. package/src/commands/outline.ts +583 -0
  355. package/src/commands/presence.ts +152 -0
  356. package/src/commands/read.ts +64 -0
  357. package/src/commands/scratch.ts +445 -0
  358. package/src/commands/session.ts +187 -0
  359. package/src/commands/sync.ts +306 -0
  360. package/src/commands/toc.ts +218 -0
  361. package/src/commands/tokens.ts +79 -0
  362. package/src/commands/tunnel.ts +633 -0
  363. package/src/commands/uninstall.ts +144 -0
  364. package/src/commands/web.ts +193 -0
  365. package/src/core/agents/canonical-emit.ts +77 -0
  366. package/src/core/agents/cli-emit.ts +64 -0
  367. package/src/core/agents/cli.ts +838 -0
  368. package/src/core/agents/codex-replay.ts +163 -0
  369. package/src/core/agents/coord-client.ts +249 -0
  370. package/src/core/agents/events/consume.ts +196 -0
  371. package/src/core/agents/events/emit.ts +108 -0
  372. package/src/core/agents/events/ulid.ts +51 -0
  373. package/src/core/agents/index.ts +14 -0
  374. package/src/core/agents/paths.ts +16 -0
  375. package/src/core/agents/render/prompt-context.ts +401 -0
  376. package/src/core/agents/render/session-context.ts +341 -0
  377. package/src/core/agents/rules/claim-conflict.ts +282 -0
  378. package/src/core/agents/rules/commit-conflict.ts +303 -0
  379. package/src/core/agents/rules/stop-hook.ts +229 -0
  380. package/src/core/agents/session-events.ts +228 -0
  381. package/src/core/agents/state/activity-log.ts +33 -0
  382. package/src/core/agents/state/council.ts +265 -0
  383. package/src/core/agents/state/heartbeat-projector.ts +488 -0
  384. package/src/core/agents/state/heartbeat-writer.ts +333 -0
  385. package/src/core/agents/state/names.ts +399 -0
  386. package/src/core/agents/state/pidmap.ts +38 -0
  387. package/src/core/agents/state/scratch.ts +121 -0
  388. package/src/core/agents/state/shell-mutation.ts +44 -0
  389. package/src/core/agents/state/stale-sweep.ts +190 -0
  390. package/src/core/config.ts +111 -0
  391. package/src/core/hooks/cli.ts +1247 -0
  392. package/src/core/hooks/effects/image-capture.ts +330 -0
  393. package/src/core/hooks/effects/index.ts +210 -0
  394. package/src/core/hooks/events/emit.ts +120 -0
  395. package/src/core/hooks/events/schema.ts +430 -0
  396. package/src/core/hooks/events/ulid.ts +51 -0
  397. package/src/core/hooks/harness/detect.ts +30 -0
  398. package/src/core/hooks/harness/events.ts +102 -0
  399. package/src/core/hooks/harness/output.ts +100 -0
  400. package/src/core/hooks/harness/parse.ts +180 -0
  401. package/src/core/hooks/index.ts +16 -0
  402. package/src/core/hooks/resolve/anchor.ts +51 -0
  403. package/src/core/hooks/resolve/coord-root.ts +25 -0
  404. package/src/core/hooks/resolve/intent.ts +89 -0
  405. package/src/core/hooks/resolve/owner.ts +140 -0
  406. package/src/core/hooks/resolve/transcript.ts +72 -0
  407. package/src/hooks/.gitkeep +0 -0
  408. package/src/index.ts +15 -0
  409. package/src/lib/agent-browser/client.ts +239 -0
  410. package/src/lib/agent-browser/index.ts +1 -0
  411. package/src/lib/browser/client.ts +449 -0
  412. package/src/lib/browser/dev-overlay.ts +207 -0
  413. package/src/lib/browser/index.ts +24 -0
  414. package/src/lib/browser/layout.ts +288 -0
  415. package/src/lib/browser/visibility.ts +419 -0
  416. package/src/lib/browser/visual-diff.ts +150 -0
  417. package/src/lib/completion/bash.ts +291 -0
  418. package/src/lib/completion/fish.ts +134 -0
  419. package/src/lib/completion/index.ts +10 -0
  420. package/src/lib/completion/walk.ts +184 -0
  421. package/src/lib/completion/zsh.ts +262 -0
  422. package/src/lib/context/index.ts +386 -0
  423. package/src/lib/cookies/client.ts +301 -0
  424. package/src/lib/cookies/index.ts +13 -0
  425. package/src/lib/council/index.ts +803 -0
  426. package/src/lib/docs-index.ts +216 -0
  427. package/src/lib/docs-lint.ts +413 -0
  428. package/src/lib/docs-sweep.ts +348 -0
  429. package/src/lib/docs.ts +199 -0
  430. package/src/lib/env.ts +12 -0
  431. package/src/lib/exec.ts +74 -0
  432. package/src/lib/format.ts +147 -0
  433. package/src/lib/http/client.ts +211 -0
  434. package/src/lib/http/index.ts +1 -0
  435. package/src/lib/identities/index.ts +210 -0
  436. package/src/lib/machine.ts +61 -0
  437. package/src/lib/presence.ts +154 -0
  438. package/src/lib/readability/client.ts +169 -0
  439. package/src/lib/readability/index.ts +5 -0
  440. package/src/lib/readability/turndown-plugin-gfm.d.ts +10 -0
  441. package/src/lib/scratch/index.ts +470 -0
  442. package/src/lib/tunnel/gate.ts +113 -0
  443. package/src/lib/tunnel/state.ts +167 -0
  444. package/src/web/.gitkeep +0 -0
  445. package/index.js +0 -1
@@ -0,0 +1,193 @@
1
+ import { type Page } from "playwright";
2
+ import type { CookieJar } from "../cookies/index.js";
3
+ import { type OverflowResult, type WidthResult } from "./layout.js";
4
+ import { type CheckVisibilityOptions, type VisibilityResult } from "./visibility.js";
5
+ /**
6
+ * Headless-Chromium wrapper for the `browse` command.
7
+ *
8
+ * Two persistence layers:
9
+ * 1. Persistent profile (Playwright's `launchPersistentContext`) keeps
10
+ * browser state (localStorage, IndexedDB, login session) across runs.
11
+ * 2. Optional cookie jar, shared with `fetch`/`cookies` so a session
12
+ * built up in one tool is visible to the others.
13
+ *
14
+ * Designed to be opened, used for one or more navigations, and closed.
15
+ * It is not a long-lived service. For multi-step workflows, the caller drives
16
+ * `navigate`/`click`/`fill` directly between `open()` and `close()`.
17
+ */
18
+ export interface BrowserOptions {
19
+ /** Persistent profile dir. Default `~/.cache/harnery/browser-profile/`. Created if missing. */
20
+ profileDir?: string;
21
+ /** Launch headed (visible window). Default false. */
22
+ headed?: boolean;
23
+ /** Cookie jar to seed/sync with. Pass `null` to skip jar entirely. */
24
+ jar?: CookieJar | null;
25
+ /** Viewport. Default 1280x800. */
26
+ viewport?: {
27
+ width: number;
28
+ height: number;
29
+ };
30
+ /** Default navigation timeout in ms. Default 30000. */
31
+ navigationTimeout?: number;
32
+ /**
33
+ * `wait_until` strategy for `navigate`. Default `"load"`.
34
+ * Use `"domcontentloaded"` for sites with long-running analytics scripts
35
+ * that never let `"load"` fire.
36
+ */
37
+ waitUntil?: "load" | "domcontentloaded" | "networkidle" | "commit";
38
+ /**
39
+ * If set, record network traffic to a HAR file at this absolute path.
40
+ * The HAR is finalized when `close()` is called.
41
+ */
42
+ recordHarPath?: string;
43
+ /**
44
+ * Optional callback returning extra headers to attach to every request,
45
+ * keyed by request URL. Consumers can inject extra HTTP headers per-URL
46
+ * via this callback (e.g., a Cloudflare-bypass header for specific zones).
47
+ */
48
+ extraHeaders?: (url: string) => Record<string, string>;
49
+ }
50
+ export interface NavigateResult {
51
+ url: string;
52
+ title: string;
53
+ status: number | null;
54
+ }
55
+ export interface ConsoleEvent {
56
+ type: string;
57
+ text: string;
58
+ location?: {
59
+ url: string;
60
+ lineNumber?: number;
61
+ columnNumber?: number;
62
+ };
63
+ }
64
+ export interface PageErrorEvent {
65
+ message: string;
66
+ stack?: string;
67
+ }
68
+ export interface FailedRequest {
69
+ url: string;
70
+ method: string;
71
+ failure: string;
72
+ resourceType: string;
73
+ }
74
+ export interface Diagnostics {
75
+ consoleEvents: ConsoleEvent[];
76
+ consoleErrors: ConsoleEvent[];
77
+ pageErrors: PageErrorEvent[];
78
+ failedRequests: FailedRequest[];
79
+ viewport: {
80
+ width: number;
81
+ height: number;
82
+ } | null;
83
+ }
84
+ export declare class Browser {
85
+ private opts;
86
+ private context;
87
+ private page;
88
+ readonly profileDir: string;
89
+ private consoleEvents;
90
+ private pageErrors;
91
+ private failedRequests;
92
+ constructor(opts?: BrowserOptions);
93
+ /** Lazy: caller-side helper to find the active page if mid-flow. */
94
+ get currentPage(): Page;
95
+ open(): Promise<void>;
96
+ /**
97
+ * Hook console + pageerror + requestfailed events. Called on `open()`
98
+ * before any navigation so we don't miss early-fired events.
99
+ */
100
+ private attachDiagnosticListeners;
101
+ /**
102
+ * Snapshot of every event captured since `open()`. Returned objects are
103
+ * copies, so callers can safely store them after `close()`.
104
+ */
105
+ diagnostics(): Diagnostics;
106
+ navigate(url: string): Promise<NavigateResult>;
107
+ /**
108
+ * Reload the current page. Preserves cookies + sessionStorage so callers can
109
+ * reproduce sessionStorage-restored UI state (e.g. drawers/modals that open
110
+ * automatically on reload, where Dialog auto-focus + Tooltip-on-focus may
111
+ * interact differently than the click-to-open path).
112
+ */
113
+ reload(): Promise<NavigateResult>;
114
+ /** Full-page PNG screenshot. Returns the byte count written. */
115
+ screenshot(path: string, opts?: {
116
+ fullPage?: boolean;
117
+ }): Promise<number>;
118
+ /**
119
+ * Plain-text snapshot of the document body. Suitable as a coarse "what's
120
+ * on screen" signal for LLM iteration loops. For richer extraction, use
121
+ * `htmlContent()` and pipe through a readability filter.
122
+ */
123
+ textSnapshot(): Promise<string>;
124
+ /** Raw outer HTML of the page (or a selector if provided). */
125
+ htmlContent(selector?: string): Promise<string>;
126
+ click(selector: string): Promise<void>;
127
+ fill(selector: string, value: string): Promise<void>;
128
+ press(key: string): Promise<void>;
129
+ waitForSelector(selector: string, timeout?: number): Promise<void>;
130
+ /** Evaluate JS in the page context. Caller is responsible for safety. */
131
+ evaluate<T = unknown>(script: string): Promise<T>;
132
+ /**
133
+ * Read the system clipboard via the page context. Grants `clipboard-read`
134
+ * to the page's origin first because Chromium gates `navigator.clipboard
135
+ * .readText()` behind a user-gesture + permission check; in headless
136
+ * Playwright there is no user gesture, so the permission grant is the
137
+ * substitute. Returns an empty string if the read returns nullish or
138
+ * throws (insecure context, focus race). Used by `browse --batch
139
+ * clipboard ...` to verify a UI Copy action end-to-end.
140
+ */
141
+ readClipboard(): Promise<string>;
142
+ /**
143
+ * Run occlusion checks on one or more selectors. For each, samples a grid
144
+ * of points inside the element's bounding rect and uses
145
+ * `document.elementFromPoint` to detect whether the target is the topmost
146
+ * paintable element at each sample. Catches the class of UI bugs where
147
+ * an element's rect IS in-viewport but a higher-z-index sibling is
148
+ * painting over it.
149
+ */
150
+ checkVisibility(selectors: string[], opts?: CheckVisibilityOptions): Promise<VisibilityResult[]>;
151
+ /** Inject annotation overlays for visibility results. Used before screenshot. */
152
+ annotateVisibility(results: VisibilityResult[]): Promise<void>;
153
+ /** Remove visibility annotation overlays. */
154
+ clearVisibilityAnnotations(): Promise<void>;
155
+ /**
156
+ * Measure each selector's bounding rect + viewport-fill + parent-fill
157
+ * ratios. Catches the class of mobile-layout bug where a table sits at
158
+ * (say) 85% viewport fill because of stacked padding: every per-element
159
+ * check passes, but the user sees too-narrow content.
160
+ */
161
+ checkWidth(selectors: string[]): Promise<WidthResult[]>;
162
+ /**
163
+ * Detect horizontal overflow at the document level. Returns viewport size,
164
+ * `document.scrollWidth`, and the top N elements protruding past the
165
+ * viewport's right edge. Catches the class of bug where a nav/table is
166
+ * wider than the viewport, forcing horizontal scroll on mobile.
167
+ */
168
+ checkOverflow(opts?: {
169
+ sampleLimit?: number;
170
+ }): Promise<OverflowResult>;
171
+ /** Inject annotation overlays for width + overflow results. Used before screenshot. */
172
+ annotateLayout(args: {
173
+ widths: WidthResult[];
174
+ overflow: OverflowResult | null;
175
+ widthThreshold: number;
176
+ }): Promise<void>;
177
+ /** Remove layout annotation overlays. */
178
+ clearLayoutAnnotations(): Promise<void>;
179
+ /**
180
+ * Inject a script that runs in every page context before page scripts
181
+ * execute. Useful for seeding localStorage before an SSR/CSR comparison;
182
+ * without this, state-dependent hydration mismatches are invisible to a
183
+ * clean-profile probe. Must be called after `open()` and before
184
+ * `navigate()`.
185
+ */
186
+ addInitScript(script: string): Promise<void>;
187
+ /**
188
+ * Sync cookies from the live context back into the jar (if one was provided),
189
+ * then tear everything down. Safe to call multiple times.
190
+ */
191
+ close(): Promise<void>;
192
+ }
193
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,325 @@
1
+ import { mkdirSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { resolve } from "node:path";
4
+ import { chromium, } from "playwright";
5
+ import { buildClearLayoutAnnotationsScript, buildLayoutAnnotateScript, buildOverflowCheck, buildWidthCheck, } from "./layout.js";
6
+ import { buildAnnotateScript, buildClearAnnotationsScript, buildVisibilityCheck, } from "./visibility.js";
7
+ const DEFAULT_PROFILE = resolve(homedir(), ".cache", "harnery", "browser-profile");
8
+ export class Browser {
9
+ opts;
10
+ context = null;
11
+ page = null;
12
+ profileDir;
13
+ consoleEvents = [];
14
+ pageErrors = [];
15
+ failedRequests = [];
16
+ constructor(opts = {}) {
17
+ this.opts = opts;
18
+ this.profileDir = opts.profileDir ?? DEFAULT_PROFILE;
19
+ }
20
+ /** Lazy: caller-side helper to find the active page if mid-flow. */
21
+ get currentPage() {
22
+ if (!this.page) {
23
+ throw new Error("Browser not opened. Call open() first.");
24
+ }
25
+ return this.page;
26
+ }
27
+ async open() {
28
+ if (this.context)
29
+ return;
30
+ mkdirSync(this.profileDir, { recursive: true });
31
+ this.context = await chromium.launchPersistentContext(this.profileDir, {
32
+ headless: !this.opts.headed,
33
+ viewport: this.opts.viewport ?? { width: 1280, height: 800 },
34
+ ...(this.opts.recordHarPath
35
+ ? { recordHar: { path: this.opts.recordHarPath, mode: "full" } }
36
+ : {}),
37
+ });
38
+ this.context.setDefaultNavigationTimeout(this.opts.navigationTimeout ?? 30_000);
39
+ if (this.opts.jar) {
40
+ const jarCookies = this.opts.jar.list();
41
+ if (jarCookies.length > 0) {
42
+ await this.context.addCookies(jarCookies.map(toPWCookie));
43
+ }
44
+ }
45
+ // Caller-injected extraHeaders callback (e.g., for Cloudflare-bypass
46
+ // or custom auth headers). Per-request route handler so headers only
47
+ // attach when the callback returns non-empty.
48
+ const headersCb = this.opts.extraHeaders;
49
+ if (headersCb) {
50
+ await this.context.route("**/*", async (route, request) => {
51
+ const extra = headersCb(request.url());
52
+ if (Object.keys(extra).length === 0)
53
+ return route.continue();
54
+ const headers = { ...request.headers(), ...extra };
55
+ return route.continue({ headers });
56
+ });
57
+ }
58
+ const pages = this.context.pages();
59
+ this.page = pages[0] ?? (await this.context.newPage());
60
+ this.attachDiagnosticListeners(this.page);
61
+ }
62
+ /**
63
+ * Hook console + pageerror + requestfailed events. Called on `open()`
64
+ * before any navigation so we don't miss early-fired events.
65
+ */
66
+ attachDiagnosticListeners(page) {
67
+ page.on("console", (msg) => {
68
+ const loc = msg.location();
69
+ this.consoleEvents.push({
70
+ type: msg.type(),
71
+ text: msg.text(),
72
+ location: loc.url
73
+ ? { url: loc.url, lineNumber: loc.lineNumber, columnNumber: loc.columnNumber }
74
+ : undefined,
75
+ });
76
+ });
77
+ page.on("pageerror", (err) => {
78
+ this.pageErrors.push({ message: err.message, stack: err.stack });
79
+ });
80
+ page.on("requestfailed", (req) => {
81
+ this.failedRequests.push({
82
+ url: req.url(),
83
+ method: req.method(),
84
+ failure: req.failure()?.errorText ?? "unknown",
85
+ resourceType: req.resourceType(),
86
+ });
87
+ });
88
+ }
89
+ /**
90
+ * Snapshot of every event captured since `open()`. Returned objects are
91
+ * copies, so callers can safely store them after `close()`.
92
+ */
93
+ diagnostics() {
94
+ return {
95
+ consoleEvents: [...this.consoleEvents],
96
+ consoleErrors: this.consoleEvents.filter((e) => e.type === "error"),
97
+ pageErrors: [...this.pageErrors],
98
+ failedRequests: [...this.failedRequests],
99
+ viewport: this.page?.viewportSize() ?? null,
100
+ };
101
+ }
102
+ async navigate(url) {
103
+ const page = this.currentPage;
104
+ const response = await page.goto(url, { waitUntil: this.opts.waitUntil ?? "load" });
105
+ return {
106
+ url: page.url(),
107
+ title: await page.title(),
108
+ status: response?.status() ?? null,
109
+ };
110
+ }
111
+ /**
112
+ * Reload the current page. Preserves cookies + sessionStorage so callers can
113
+ * reproduce sessionStorage-restored UI state (e.g. drawers/modals that open
114
+ * automatically on reload, where Dialog auto-focus + Tooltip-on-focus may
115
+ * interact differently than the click-to-open path).
116
+ */
117
+ async reload() {
118
+ const page = this.currentPage;
119
+ const response = await page.reload({ waitUntil: this.opts.waitUntil ?? "load" });
120
+ return {
121
+ url: page.url(),
122
+ title: await page.title(),
123
+ status: response?.status() ?? null,
124
+ };
125
+ }
126
+ /** Full-page PNG screenshot. Returns the byte count written. */
127
+ async screenshot(path, opts = {}) {
128
+ const page = this.currentPage;
129
+ const buf = await page.screenshot({ path, fullPage: opts.fullPage ?? true, type: "png" });
130
+ return buf.length;
131
+ }
132
+ /**
133
+ * Plain-text snapshot of the document body. Suitable as a coarse "what's
134
+ * on screen" signal for LLM iteration loops. For richer extraction, use
135
+ * `htmlContent()` and pipe through a readability filter.
136
+ */
137
+ async textSnapshot() {
138
+ const page = this.currentPage;
139
+ return await page.evaluate(() => document.body?.innerText ?? "");
140
+ }
141
+ /** Raw outer HTML of the page (or a selector if provided). */
142
+ async htmlContent(selector) {
143
+ const page = this.currentPage;
144
+ if (selector) {
145
+ const el = await page.$(selector);
146
+ if (!el)
147
+ throw new Error(`Selector matched nothing: ${selector}`);
148
+ return await el.evaluate((node) => node.outerHTML);
149
+ }
150
+ return await page.content();
151
+ }
152
+ async click(selector) {
153
+ await this.currentPage.click(selector);
154
+ }
155
+ async fill(selector, value) {
156
+ await this.currentPage.fill(selector, value);
157
+ }
158
+ async press(key) {
159
+ await this.currentPage.keyboard.press(key);
160
+ }
161
+ async waitForSelector(selector, timeout) {
162
+ await this.currentPage.waitForSelector(selector, timeout ? { timeout } : undefined);
163
+ }
164
+ /** Evaluate JS in the page context. Caller is responsible for safety. */
165
+ async evaluate(script) {
166
+ return await this.currentPage.evaluate(script);
167
+ }
168
+ /**
169
+ * Read the system clipboard via the page context. Grants `clipboard-read`
170
+ * to the page's origin first because Chromium gates `navigator.clipboard
171
+ * .readText()` behind a user-gesture + permission check; in headless
172
+ * Playwright there is no user gesture, so the permission grant is the
173
+ * substitute. Returns an empty string if the read returns nullish or
174
+ * throws (insecure context, focus race). Used by `browse --batch
175
+ * clipboard ...` to verify a UI Copy action end-to-end.
176
+ */
177
+ async readClipboard() {
178
+ if (!this.context)
179
+ throw new Error("Browser not opened. Call open() first.");
180
+ const url = this.currentPage.url();
181
+ try {
182
+ const origin = new URL(url).origin;
183
+ await this.context.grantPermissions(["clipboard-read"], { origin });
184
+ }
185
+ catch {
186
+ /* about:blank / data: URL, skip permission; evaluate may still work */
187
+ }
188
+ return await this.currentPage.evaluate(async () => {
189
+ try {
190
+ const text = await navigator.clipboard.readText();
191
+ return typeof text === "string" ? text : "";
192
+ }
193
+ catch {
194
+ return "";
195
+ }
196
+ });
197
+ }
198
+ /**
199
+ * Run occlusion checks on one or more selectors. For each, samples a grid
200
+ * of points inside the element's bounding rect and uses
201
+ * `document.elementFromPoint` to detect whether the target is the topmost
202
+ * paintable element at each sample. Catches the class of UI bugs where
203
+ * an element's rect IS in-viewport but a higher-z-index sibling is
204
+ * painting over it.
205
+ */
206
+ async checkVisibility(selectors, opts = {}) {
207
+ return await this.currentPage.evaluate(buildVisibilityCheck(), {
208
+ selectors,
209
+ sampleGrid: opts.sampleGrid ?? 3,
210
+ });
211
+ }
212
+ /** Inject annotation overlays for visibility results. Used before screenshot. */
213
+ async annotateVisibility(results) {
214
+ await this.currentPage.evaluate(buildAnnotateScript(), { results });
215
+ }
216
+ /** Remove visibility annotation overlays. */
217
+ async clearVisibilityAnnotations() {
218
+ await this.currentPage.evaluate(buildClearAnnotationsScript());
219
+ }
220
+ /**
221
+ * Measure each selector's bounding rect + viewport-fill + parent-fill
222
+ * ratios. Catches the class of mobile-layout bug where a table sits at
223
+ * (say) 85% viewport fill because of stacked padding: every per-element
224
+ * check passes, but the user sees too-narrow content.
225
+ */
226
+ async checkWidth(selectors) {
227
+ return await this.currentPage.evaluate(buildWidthCheck(), { selectors });
228
+ }
229
+ /**
230
+ * Detect horizontal overflow at the document level. Returns viewport size,
231
+ * `document.scrollWidth`, and the top N elements protruding past the
232
+ * viewport's right edge. Catches the class of bug where a nav/table is
233
+ * wider than the viewport, forcing horizontal scroll on mobile.
234
+ */
235
+ async checkOverflow(opts = {}) {
236
+ return await this.currentPage.evaluate(buildOverflowCheck(), {
237
+ sampleLimit: opts.sampleLimit ?? 5,
238
+ });
239
+ }
240
+ /** Inject annotation overlays for width + overflow results. Used before screenshot. */
241
+ async annotateLayout(args) {
242
+ await this.currentPage.evaluate(buildLayoutAnnotateScript(), args);
243
+ }
244
+ /** Remove layout annotation overlays. */
245
+ async clearLayoutAnnotations() {
246
+ await this.currentPage.evaluate(buildClearLayoutAnnotationsScript());
247
+ }
248
+ /**
249
+ * Inject a script that runs in every page context before page scripts
250
+ * execute. Useful for seeding localStorage before an SSR/CSR comparison;
251
+ * without this, state-dependent hydration mismatches are invisible to a
252
+ * clean-profile probe. Must be called after `open()` and before
253
+ * `navigate()`.
254
+ */
255
+ async addInitScript(script) {
256
+ if (!this.context)
257
+ throw new Error("Browser not opened. Call open() first.");
258
+ await this.context.addInitScript(script);
259
+ }
260
+ /**
261
+ * Sync cookies from the live context back into the jar (if one was provided),
262
+ * then tear everything down. Safe to call multiple times.
263
+ */
264
+ async close() {
265
+ if (!this.context)
266
+ return;
267
+ if (this.opts.jar) {
268
+ try {
269
+ const live = await this.context.cookies();
270
+ for (const c of live) {
271
+ this.opts.jar.set(toJarCookie(c));
272
+ }
273
+ }
274
+ catch {
275
+ // Cookie persist is best-effort; never block close on it.
276
+ }
277
+ }
278
+ await this.context.close().catch(() => { });
279
+ this.context = null;
280
+ this.page = null;
281
+ }
282
+ }
283
+ // ---------------------------------------------------------------------------
284
+ // Cookie shape conversion
285
+ // ---------------------------------------------------------------------------
286
+ function toPWCookie(c) {
287
+ // Playwright's PWCookie type requires sameSite to be a literal; undefined
288
+ // is not allowed. Default to "Lax" (matches Chromium's modern default).
289
+ return {
290
+ name: c.name,
291
+ value: c.value,
292
+ domain: c.domain,
293
+ path: c.path,
294
+ expires: c.expires,
295
+ httpOnly: c.httpOnly,
296
+ secure: c.secure,
297
+ sameSite: normalizeSameSite(c.sameSite) ?? "Lax",
298
+ };
299
+ }
300
+ function toJarCookie(c) {
301
+ return {
302
+ name: c.name,
303
+ value: c.value,
304
+ domain: c.domain,
305
+ path: c.path,
306
+ expires: c.expires,
307
+ httpOnly: c.httpOnly,
308
+ secure: c.secure,
309
+ sameSite: c.sameSite ?? undefined,
310
+ session: c.expires <= 0,
311
+ size: c.name.length + c.value.length,
312
+ };
313
+ }
314
+ function normalizeSameSite(s) {
315
+ if (!s)
316
+ return undefined;
317
+ const lower = s.toLowerCase();
318
+ if (lower === "strict")
319
+ return "Strict";
320
+ if (lower === "lax")
321
+ return "Lax";
322
+ if (lower === "none")
323
+ return "None";
324
+ return undefined;
325
+ }
@@ -0,0 +1,23 @@
1
+ import type { Page } from "playwright";
2
+ export interface DevOverlayError {
3
+ index: number;
4
+ kind: string;
5
+ code: string | null;
6
+ message: string;
7
+ callStack: string[];
8
+ }
9
+ export interface DevOverlayResult {
10
+ detected: boolean;
11
+ issuesCount: number;
12
+ errors: DevOverlayError[];
13
+ }
14
+ /**
15
+ * Detect a Next.js dev overlay on the current page and, if present, capture
16
+ * every queued issue. Idempotent, safe to call multiple times. The function
17
+ * closes the overlay on exit; if it crashes partway, the overlay may be left
18
+ * open (subsequent calls will recover).
19
+ */
20
+ export declare function captureDevOverlay(page: Page, opts?: {
21
+ stepDelayMs?: number;
22
+ }): Promise<DevOverlayResult>;
23
+ //# sourceMappingURL=dev-overlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-overlay.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/dev-overlay.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAWD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,IAAI,EACV,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,OAAO,CAAC,gBAAgB,CAAC,CAsG3B"}