@phuetz/code-buddy 0.1.0 → 0.1.2

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 (305) hide show
  1. package/.codebuddy/skills/bundled/brave-search/SKILL.md +490 -0
  2. package/.codebuddy/skills/bundled/exa-search/SKILL.md +1122 -0
  3. package/.codebuddy/skills/bundled/perplexity/SKILL.md +748 -0
  4. package/.codebuddy/skills/bundled/playwright/SKILL.md +520 -0
  5. package/.codebuddy/skills/bundled/puppeteer/SKILL.md +708 -0
  6. package/.codebuddy/skills/bundled/web-fetch/SKILL.md +1003 -0
  7. package/README.md +56 -0
  8. package/dist/agent/agent-state.d.ts +3 -3
  9. package/dist/agent/agent-state.js +6 -6
  10. package/dist/agent/agent-state.js.map +1 -1
  11. package/dist/agent/base-agent.d.ts +4 -4
  12. package/dist/agent/base-agent.js +22 -9
  13. package/dist/agent/base-agent.js.map +1 -1
  14. package/dist/agent/cache-trace.d.ts +56 -0
  15. package/dist/agent/cache-trace.js +98 -0
  16. package/dist/agent/cache-trace.js.map +1 -0
  17. package/dist/agent/codebuddy-agent.js +4 -2
  18. package/dist/agent/codebuddy-agent.js.map +1 -1
  19. package/dist/agent/execution/agent-executor.d.ts +4 -4
  20. package/dist/agent/execution/agent-executor.js +46 -14
  21. package/dist/agent/execution/agent-executor.js.map +1 -1
  22. package/dist/agent/facades/agent-context-facade.js +1 -3
  23. package/dist/agent/facades/agent-context-facade.js.map +1 -1
  24. package/dist/agent/facades/message-history-manager.js +14 -12
  25. package/dist/agent/facades/message-history-manager.js.map +1 -1
  26. package/dist/agent/facades/session-facade.d.ts +3 -3
  27. package/dist/agent/facades/session-facade.js +6 -6
  28. package/dist/agent/facades/session-facade.js.map +1 -1
  29. package/dist/agent/history-repair.d.ts +37 -0
  30. package/dist/agent/history-repair.js +124 -0
  31. package/dist/agent/history-repair.js.map +1 -0
  32. package/dist/agent/index.d.ts +3 -3
  33. package/dist/agent/index.js +3 -3
  34. package/dist/agent/index.js.map +1 -1
  35. package/dist/agent/isolation/agent-workspace.d.ts +1 -0
  36. package/dist/agent/isolation/agent-workspace.js +10 -0
  37. package/dist/agent/isolation/agent-workspace.js.map +1 -1
  38. package/dist/agent/specialized/archive-agent.d.ts +3 -0
  39. package/dist/agent/specialized/archive-agent.js +71 -31
  40. package/dist/agent/specialized/archive-agent.js.map +1 -1
  41. package/dist/agent/specialized/index.d.ts +9 -8
  42. package/dist/agent/specialized/index.js +16 -8
  43. package/dist/agent/specialized/index.js.map +1 -1
  44. package/dist/agent/specialized/security-review/agent.js +19 -8
  45. package/dist/agent/specialized/security-review/agent.js.map +1 -1
  46. package/dist/agent/tool-executor.js +5 -0
  47. package/dist/agent/tool-executor.js.map +1 -1
  48. package/dist/agent/turn-diff-tracker.d.ts +79 -0
  49. package/dist/agent/turn-diff-tracker.js +195 -0
  50. package/dist/agent/turn-diff-tracker.js.map +1 -0
  51. package/dist/browser/controller.js +8 -4
  52. package/dist/browser/controller.js.map +1 -1
  53. package/dist/browser-automation/browser-manager.js +8 -1
  54. package/dist/browser-automation/browser-manager.js.map +1 -1
  55. package/dist/checkpoints/checkpoint-versioning.js +78 -20
  56. package/dist/checkpoints/checkpoint-versioning.js.map +1 -1
  57. package/dist/cli/config-loader.js +2 -4
  58. package/dist/cli/config-loader.js.map +1 -1
  59. package/dist/codebuddy/client.js +70 -11
  60. package/dist/codebuddy/client.js.map +1 -1
  61. package/dist/codebuddy/tools.d.ts +1 -7
  62. package/dist/codebuddy/tools.js +2 -30
  63. package/dist/codebuddy/tools.js.map +1 -1
  64. package/dist/commands/cli/daemon-commands.d.ts +14 -0
  65. package/dist/commands/cli/daemon-commands.js +166 -0
  66. package/dist/commands/cli/daemon-commands.js.map +1 -0
  67. package/dist/commands/cli/speak-command.d.ts +10 -0
  68. package/dist/commands/cli/speak-command.js +97 -0
  69. package/dist/commands/cli/speak-command.js.map +1 -0
  70. package/dist/commands/cli/utility-commands.d.ts +10 -0
  71. package/dist/commands/cli/utility-commands.js +88 -0
  72. package/dist/commands/cli/utility-commands.js.map +1 -0
  73. package/dist/commands/handlers/fcs-handlers.js +1 -1
  74. package/dist/commands/handlers/fcs-handlers.js.map +1 -1
  75. package/dist/commands/handlers/memory-handlers.js +2 -1
  76. package/dist/commands/handlers/memory-handlers.js.map +1 -1
  77. package/dist/commands/handlers/vibe-handlers.js +0 -1
  78. package/dist/commands/handlers/vibe-handlers.js.map +1 -1
  79. package/dist/commands/handlers/worktree-handlers.js +11 -0
  80. package/dist/commands/handlers/worktree-handlers.js.map +1 -1
  81. package/dist/commands/index.d.ts +8 -7
  82. package/dist/commands/index.js +10 -8
  83. package/dist/commands/index.js.map +1 -1
  84. package/dist/commands/mcp.d.ts +1 -0
  85. package/dist/commands/mcp.js +66 -7
  86. package/dist/commands/mcp.js.map +1 -1
  87. package/dist/commands/pipeline.js +25 -13
  88. package/dist/commands/pipeline.js.map +1 -1
  89. package/dist/config/hot-reload/watcher.js +4 -4
  90. package/dist/config/hot-reload/watcher.js.map +1 -1
  91. package/dist/config/model-tools.d.ts +41 -0
  92. package/dist/config/model-tools.js +194 -0
  93. package/dist/config/model-tools.js.map +1 -0
  94. package/dist/context/context-manager-v2.d.ts +2 -1
  95. package/dist/context/context-manager-v2.js +34 -5
  96. package/dist/context/context-manager-v2.js.map +1 -1
  97. package/dist/context/index.d.ts +12 -12
  98. package/dist/context/index.js +25 -12
  99. package/dist/context/index.js.map +1 -1
  100. package/dist/daemon/daemon-manager.js +23 -19
  101. package/dist/daemon/daemon-manager.js.map +1 -1
  102. package/dist/database/database-manager.d.ts +4 -0
  103. package/dist/database/database-manager.js +16 -7
  104. package/dist/database/database-manager.js.map +1 -1
  105. package/dist/desktop-automation/nutjs-provider.js +89 -0
  106. package/dist/desktop-automation/nutjs-provider.js.map +1 -1
  107. package/dist/errors/index.d.ts +4 -4
  108. package/dist/errors/index.js +8 -4
  109. package/dist/errors/index.js.map +1 -1
  110. package/dist/fcs/builtins.d.ts +2 -6
  111. package/dist/fcs/builtins.js +2 -568
  112. package/dist/fcs/builtins.js.map +1 -1
  113. package/dist/fcs/codebuddy-bindings.d.ts +3 -43
  114. package/dist/fcs/codebuddy-bindings.js +2 -606
  115. package/dist/fcs/codebuddy-bindings.js.map +1 -1
  116. package/dist/fcs/index.d.ts +2 -27
  117. package/dist/fcs/index.js +2 -53
  118. package/dist/fcs/index.js.map +1 -1
  119. package/dist/fcs/lexer.d.ts +2 -37
  120. package/dist/fcs/lexer.js +2 -459
  121. package/dist/fcs/lexer.js.map +1 -1
  122. package/dist/fcs/parser.d.ts +2 -68
  123. package/dist/fcs/parser.js +2 -893
  124. package/dist/fcs/parser.js.map +1 -1
  125. package/dist/fcs/runtime.d.ts +2 -59
  126. package/dist/fcs/runtime.js +2 -623
  127. package/dist/fcs/runtime.js.map +1 -1
  128. package/dist/fcs/script-registry.d.ts +3 -69
  129. package/dist/fcs/script-registry.js +2 -219
  130. package/dist/fcs/script-registry.js.map +1 -1
  131. package/dist/fcs/sync-bindings.d.ts +3 -101
  132. package/dist/fcs/sync-bindings.js +2 -410
  133. package/dist/fcs/sync-bindings.js.map +1 -1
  134. package/dist/fcs/types.d.ts +2 -285
  135. package/dist/fcs/types.js +2 -103
  136. package/dist/fcs/types.js.map +1 -1
  137. package/dist/hooks/index.d.ts +4 -4
  138. package/dist/hooks/index.js +4 -4
  139. package/dist/hooks/index.js.map +1 -1
  140. package/dist/hooks/use-input-handler.d.ts +1 -1
  141. package/dist/index.js +20 -330
  142. package/dist/index.js.map +1 -1
  143. package/dist/input/voice-control.js +11 -5
  144. package/dist/input/voice-control.js.map +1 -1
  145. package/dist/integrations/json-rpc/server.d.ts +9 -0
  146. package/dist/integrations/json-rpc/server.js +43 -13
  147. package/dist/integrations/json-rpc/server.js.map +1 -1
  148. package/dist/integrations/mcp/mcp-server.js +1 -1
  149. package/dist/integrations/mcp/mcp-server.js.map +1 -1
  150. package/dist/integrations/notification-integrations.d.ts +1 -0
  151. package/dist/integrations/notification-integrations.js +6 -1
  152. package/dist/integrations/notification-integrations.js.map +1 -1
  153. package/dist/mcp/client.js +2 -1
  154. package/dist/mcp/client.js.map +1 -1
  155. package/dist/mcp/config.js +89 -5
  156. package/dist/mcp/config.js.map +1 -1
  157. package/dist/mcp/mcp-client.js +65 -14
  158. package/dist/mcp/mcp-client.js.map +1 -1
  159. package/dist/mcp/transports.d.ts +0 -1
  160. package/dist/mcp/transports.js +1 -5
  161. package/dist/mcp/transports.js.map +1 -1
  162. package/dist/mcp/types.d.ts +2 -0
  163. package/dist/memory/index.d.ts +2 -2
  164. package/dist/memory/index.js +2 -2
  165. package/dist/memory/index.js.map +1 -1
  166. package/dist/persistence/session-lock.d.ts +42 -0
  167. package/dist/persistence/session-lock.js +165 -0
  168. package/dist/persistence/session-lock.js.map +1 -0
  169. package/dist/persistence/session-store.d.ts +18 -3
  170. package/dist/persistence/session-store.js +90 -21
  171. package/dist/persistence/session-store.js.map +1 -1
  172. package/dist/plugins/conflict-detection.js +2 -1
  173. package/dist/plugins/conflict-detection.js.map +1 -1
  174. package/dist/plugins/index.d.ts +3 -3
  175. package/dist/plugins/index.js +3 -3
  176. package/dist/plugins/index.js.map +1 -1
  177. package/dist/plugins/isolated-plugin-runner.d.ts +6 -0
  178. package/dist/plugins/isolated-plugin-runner.js +19 -1
  179. package/dist/plugins/isolated-plugin-runner.js.map +1 -1
  180. package/dist/providers/local-llm-provider.js +28 -8
  181. package/dist/providers/local-llm-provider.js.map +1 -1
  182. package/dist/sandbox/docker-sandbox.js +7 -4
  183. package/dist/sandbox/docker-sandbox.js.map +1 -1
  184. package/dist/scripting/builtins.d.ts +8 -3
  185. package/dist/scripting/builtins.js +506 -355
  186. package/dist/scripting/builtins.js.map +1 -1
  187. package/dist/scripting/codebuddy-bindings.d.ts +47 -0
  188. package/dist/scripting/codebuddy-bindings.js +488 -0
  189. package/dist/scripting/codebuddy-bindings.js.map +1 -0
  190. package/dist/scripting/index.d.ts +33 -30
  191. package/dist/scripting/index.js +41 -36
  192. package/dist/scripting/index.js.map +1 -1
  193. package/dist/scripting/lexer.d.ts +31 -13
  194. package/dist/scripting/lexer.js +379 -292
  195. package/dist/scripting/lexer.js.map +1 -1
  196. package/dist/scripting/parser.d.ts +63 -44
  197. package/dist/scripting/parser.js +700 -473
  198. package/dist/scripting/parser.js.map +1 -1
  199. package/dist/scripting/runtime.d.ts +55 -24
  200. package/dist/scripting/runtime.js +600 -288
  201. package/dist/scripting/runtime.js.map +1 -1
  202. package/dist/scripting/script-registry.d.ts +54 -0
  203. package/dist/scripting/script-registry.js +202 -0
  204. package/dist/scripting/script-registry.js.map +1 -0
  205. package/dist/scripting/sync-bindings.d.ts +105 -0
  206. package/dist/scripting/sync-bindings.js +353 -0
  207. package/dist/scripting/sync-bindings.js.map +1 -0
  208. package/dist/scripting/types.d.ts +297 -199
  209. package/dist/scripting/types.js +86 -60
  210. package/dist/scripting/types.js.map +1 -1
  211. package/dist/search/usearch-index.js +42 -7
  212. package/dist/search/usearch-index.js.map +1 -1
  213. package/dist/security/bash-parser.d.ts +51 -0
  214. package/dist/security/bash-parser.js +327 -0
  215. package/dist/security/bash-parser.js.map +1 -0
  216. package/dist/security/index.d.ts +7 -5
  217. package/dist/security/index.js +8 -7
  218. package/dist/security/index.js.map +1 -1
  219. package/dist/security/skill-scanner.d.ts +36 -0
  220. package/dist/security/skill-scanner.js +149 -0
  221. package/dist/security/skill-scanner.js.map +1 -0
  222. package/dist/security/trust-folders.d.ts +1 -0
  223. package/dist/security/trust-folders.js +19 -1
  224. package/dist/security/trust-folders.js.map +1 -1
  225. package/dist/server/auth/index.d.ts +2 -2
  226. package/dist/server/auth/index.js +2 -2
  227. package/dist/server/auth/index.js.map +1 -1
  228. package/dist/server/middleware/index.d.ts +5 -5
  229. package/dist/server/middleware/index.js +5 -5
  230. package/dist/server/middleware/index.js.map +1 -1
  231. package/dist/server/middleware/rate-limit.js +15 -3
  232. package/dist/server/middleware/rate-limit.js.map +1 -1
  233. package/dist/server/websocket/handler.js +54 -6
  234. package/dist/server/websocket/handler.js.map +1 -1
  235. package/dist/skills/eligibility.js +26 -4
  236. package/dist/skills/eligibility.js.map +1 -1
  237. package/dist/tasks/background-tasks.js +5 -1
  238. package/dist/tasks/background-tasks.js.map +1 -1
  239. package/dist/tools/apply-patch.d.ts +55 -0
  240. package/dist/tools/apply-patch.js +273 -0
  241. package/dist/tools/apply-patch.js.map +1 -0
  242. package/dist/tools/hooks/default-hooks.d.ts +1 -1
  243. package/dist/tools/hooks/default-hooks.js +2 -1
  244. package/dist/tools/hooks/default-hooks.js.map +1 -1
  245. package/dist/tools/index.d.ts +10 -10
  246. package/dist/tools/index.js +11 -11
  247. package/dist/tools/index.js.map +1 -1
  248. package/dist/tools/registry/bash-tools.js +6 -3
  249. package/dist/tools/registry/bash-tools.js.map +1 -1
  250. package/dist/tools/registry/misc-tools.js +1 -2
  251. package/dist/tools/registry/misc-tools.js.map +1 -1
  252. package/dist/tools/registry/search-tools.js +1 -1
  253. package/dist/tools/registry/search-tools.js.map +1 -1
  254. package/dist/tools/registry/text-editor-tools.js +1 -1
  255. package/dist/tools/registry/text-editor-tools.js.map +1 -1
  256. package/dist/tools/registry/todo-tools.js +37 -5
  257. package/dist/tools/registry/todo-tools.js.map +1 -1
  258. package/dist/tools/registry/tool-registry.js +5 -4
  259. package/dist/tools/registry/tool-registry.js.map +1 -1
  260. package/dist/tools/registry/web-tools.d.ts +1 -1
  261. package/dist/tools/registry/web-tools.js +28 -8
  262. package/dist/tools/registry/web-tools.js.map +1 -1
  263. package/dist/tools/text-editor.d.ts +1 -1
  264. package/dist/tools/text-editor.js +23 -5
  265. package/dist/tools/text-editor.js.map +1 -1
  266. package/dist/tools/web-search.d.ts +52 -37
  267. package/dist/tools/web-search.js +368 -163
  268. package/dist/tools/web-search.js.map +1 -1
  269. package/dist/types/errors.d.ts +1 -1
  270. package/dist/types/errors.js +2 -8
  271. package/dist/types/errors.js.map +1 -1
  272. package/dist/types/index.d.ts +2 -1
  273. package/dist/types/index.js +1 -2
  274. package/dist/types/index.js.map +1 -1
  275. package/dist/ui/components/ChatInterface.d.ts +1 -1
  276. package/dist/ui/index.d.ts +17 -21
  277. package/dist/ui/index.js +25 -22
  278. package/dist/ui/index.js.map +1 -1
  279. package/dist/utils/config-validation/schema.d.ts +15 -15
  280. package/dist/utils/head-tail-truncation.d.ts +34 -0
  281. package/dist/utils/head-tail-truncation.js +98 -0
  282. package/dist/utils/head-tail-truncation.js.map +1 -0
  283. package/dist/utils/logger.js +3 -9
  284. package/dist/utils/logger.js.map +1 -1
  285. package/dist/utils/sanitize.d.ts +5 -0
  286. package/dist/utils/sanitize.js +19 -0
  287. package/dist/utils/sanitize.js.map +1 -1
  288. package/dist/utils/settings-manager.js +4 -4
  289. package/dist/utils/settings-manager.js.map +1 -1
  290. package/dist/workflows/index.d.ts +4 -279
  291. package/dist/workflows/index.js +8 -822
  292. package/dist/workflows/index.js.map +1 -1
  293. package/dist/workflows/state-manager.d.ts +77 -0
  294. package/dist/workflows/state-manager.js +198 -0
  295. package/dist/workflows/state-manager.js.map +1 -0
  296. package/dist/workflows/step-manager.d.ts +39 -0
  297. package/dist/workflows/step-manager.js +196 -0
  298. package/dist/workflows/step-manager.js.map +1 -0
  299. package/dist/workflows/types.d.ts +87 -0
  300. package/dist/workflows/types.js +5 -0
  301. package/dist/workflows/types.js.map +1 -0
  302. package/dist/workflows/workflow-engine.d.ts +34 -0
  303. package/dist/workflows/workflow-engine.js +354 -0
  304. package/dist/workflows/workflow-engine.js.map +1 -0
  305. package/package.json +5 -1
@@ -0,0 +1,708 @@
1
+ ---
2
+ name: puppeteer
3
+ version: 1.0.0
4
+ description: Chrome/Chromium automation for headless browsing, web scraping, PDF generation, and screenshots
5
+ author: Code Buddy
6
+ tags: chrome, automation, scraping, headless, pdf, screenshots, debugging
7
+ env:
8
+ PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: ""
9
+ PUPPETEER_EXECUTABLE_PATH: ""
10
+ PUPPETEER_CACHE_DIR: ""
11
+ ---
12
+
13
+ # Puppeteer Chrome Automation
14
+
15
+ Puppeteer is a Node.js library that provides a high-level API to control Chrome or Chromium over the DevTools Protocol. It's excellent for web scraping, automated testing, screenshot capture, PDF generation, and debugging web applications.
16
+
17
+ ## Direct Control (CLI / API / Scripting)
18
+
19
+ ### Installation
20
+
21
+ ```bash
22
+ # Install Puppeteer (includes Chromium)
23
+ npm install puppeteer
24
+
25
+ # Install puppeteer-core (no Chromium download)
26
+ npm install puppeteer-core
27
+
28
+ # Use system Chrome
29
+ PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true npm install puppeteer-core
30
+
31
+ # Install with specific Chrome version
32
+ PUPPETEER_CHROMIUM_REVISION=1095492 npm install puppeteer
33
+ ```
34
+
35
+ ### Node.js API Examples
36
+
37
+ ```javascript
38
+ const puppeteer = require('puppeteer');
39
+ const fs = require('fs').promises;
40
+
41
+ // Basic page scraping
42
+ async function scrapePage(url) {
43
+ const browser = await puppeteer.launch({
44
+ headless: 'new', // Use new headless mode
45
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
46
+ });
47
+
48
+ const page = await browser.newPage();
49
+ await page.goto(url, { waitUntil: 'networkidle2' });
50
+
51
+ // Extract data
52
+ const data = await page.evaluate(() => {
53
+ return {
54
+ title: document.title,
55
+ description: document.querySelector('meta[name="description"]')?.content,
56
+ headings: Array.from(document.querySelectorAll('h1, h2, h3')).map(h => ({
57
+ level: h.tagName,
58
+ text: h.textContent.trim()
59
+ })),
60
+ links: Array.from(document.querySelectorAll('a')).map(a => ({
61
+ text: a.textContent.trim(),
62
+ href: a.href
63
+ }))
64
+ };
65
+ });
66
+
67
+ await browser.close();
68
+ return data;
69
+ }
70
+
71
+ // Advanced scraping with infinite scroll
72
+ async function scrapeInfiniteScroll(url, scrollLimit = 10) {
73
+ const browser = await puppeteer.launch({ headless: 'new' });
74
+ const page = await browser.newPage();
75
+ await page.goto(url, { waitUntil: 'networkidle2' });
76
+
77
+ let previousHeight;
78
+ let scrollCount = 0;
79
+
80
+ while (scrollCount < scrollLimit) {
81
+ previousHeight = await page.evaluate('document.body.scrollHeight');
82
+
83
+ // Scroll to bottom
84
+ await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
85
+ await page.waitForTimeout(2000);
86
+
87
+ const newHeight = await page.evaluate('document.body.scrollHeight');
88
+ if (newHeight === previousHeight) break;
89
+ scrollCount++;
90
+ }
91
+
92
+ // Extract all items
93
+ const items = await page.evaluate(() => {
94
+ return Array.from(document.querySelectorAll('.item')).map(item => ({
95
+ title: item.querySelector('.title')?.textContent,
96
+ image: item.querySelector('img')?.src,
97
+ price: item.querySelector('.price')?.textContent
98
+ }));
99
+ });
100
+
101
+ await browser.close();
102
+ return items;
103
+ }
104
+
105
+ // Form automation with validation
106
+ async function fillAndSubmitForm(url, formData) {
107
+ const browser = await puppeteer.launch({ headless: false, slowMo: 50 });
108
+ const page = await browser.newPage();
109
+ await page.goto(url);
110
+
111
+ // Wait for form to be ready
112
+ await page.waitForSelector('form');
113
+
114
+ // Fill text inputs
115
+ await page.type('#name', formData.name, { delay: 100 });
116
+ await page.type('#email', formData.email);
117
+ await page.type('#phone', formData.phone);
118
+
119
+ // Select dropdown
120
+ await page.select('#country', formData.country);
121
+
122
+ // Radio buttons
123
+ await page.click(`input[name="gender"][value="${formData.gender}"]`);
124
+
125
+ // Checkboxes
126
+ if (formData.newsletter) {
127
+ await page.click('#newsletter');
128
+ }
129
+
130
+ // File upload
131
+ if (formData.resume) {
132
+ const fileInput = await page.$('#resume');
133
+ await fileInput.uploadFile(formData.resume);
134
+ }
135
+
136
+ // Submit and wait for response
137
+ await Promise.all([
138
+ page.waitForNavigation({ waitUntil: 'networkidle2' }),
139
+ page.click('button[type="submit"]')
140
+ ]);
141
+
142
+ // Check for validation errors
143
+ const errors = await page.$$eval('.error', els => els.map(e => e.textContent));
144
+ const success = await page.$('.success-message');
145
+
146
+ await browser.close();
147
+ return { success: !!success, errors };
148
+ }
149
+
150
+ // Screenshot with full page and element capture
151
+ async function captureScreenshots(url, outputDir) {
152
+ const browser = await puppeteer.launch();
153
+ const page = await browser.newPage();
154
+
155
+ // Set viewport for consistent screenshots
156
+ await page.setViewport({ width: 1920, height: 1080 });
157
+ await page.goto(url, { waitUntil: 'networkidle2' });
158
+
159
+ // Full page screenshot
160
+ await page.screenshot({
161
+ path: `${outputDir}/full-page.png`,
162
+ fullPage: true
163
+ });
164
+
165
+ // Viewport screenshot
166
+ await page.screenshot({
167
+ path: `${outputDir}/viewport.png`
168
+ });
169
+
170
+ // Element screenshot
171
+ const element = await page.$('.hero-section');
172
+ if (element) {
173
+ await element.screenshot({
174
+ path: `${outputDir}/hero.png`
175
+ });
176
+ }
177
+
178
+ // Screenshot with different device emulation
179
+ await page.emulate(puppeteer.KnownDevices['iPhone 13 Pro']);
180
+ await page.screenshot({
181
+ path: `${outputDir}/mobile.png`,
182
+ fullPage: true
183
+ });
184
+
185
+ await browser.close();
186
+ }
187
+
188
+ // PDF generation with custom options
189
+ async function generatePDF(url, outputPath, options = {}) {
190
+ const browser = await puppeteer.launch();
191
+ const page = await browser.newPage();
192
+ await page.goto(url, { waitUntil: 'networkidle2' });
193
+
194
+ // Remove unwanted elements before PDF
195
+ await page.evaluate(() => {
196
+ document.querySelectorAll('.no-print, .advertisement').forEach(el => el.remove());
197
+ });
198
+
199
+ await page.pdf({
200
+ path: outputPath,
201
+ format: options.format || 'A4',
202
+ printBackground: true,
203
+ margin: {
204
+ top: options.marginTop || '1cm',
205
+ right: options.marginRight || '1cm',
206
+ bottom: options.marginBottom || '1cm',
207
+ left: options.marginLeft || '1cm'
208
+ },
209
+ displayHeaderFooter: options.headerFooter || false,
210
+ headerTemplate: options.header || '',
211
+ footerTemplate: options.footer || '<div style="font-size:10px;text-align:center;width:100%;"><span class="pageNumber"></span></div>'
212
+ });
213
+
214
+ await browser.close();
215
+ }
216
+
217
+ // Performance monitoring and metrics
218
+ async function measurePerformance(url) {
219
+ const browser = await puppeteer.launch();
220
+ const page = await browser.newPage();
221
+
222
+ // Enable performance metrics
223
+ await page.setCacheEnabled(false);
224
+
225
+ const startTime = Date.now();
226
+ await page.goto(url, { waitUntil: 'networkidle2' });
227
+ const loadTime = Date.now() - startTime;
228
+
229
+ // Get performance metrics
230
+ const metrics = await page.metrics();
231
+ const performanceTiming = JSON.parse(
232
+ await page.evaluate(() => JSON.stringify(window.performance.timing))
233
+ );
234
+
235
+ // Get resource timings
236
+ const resourceTimings = await page.evaluate(() => {
237
+ return performance.getEntriesByType('resource').map(r => ({
238
+ name: r.name,
239
+ duration: r.duration,
240
+ size: r.transferSize
241
+ }));
242
+ });
243
+
244
+ // Get Core Web Vitals
245
+ const vitals = await page.evaluate(() => {
246
+ return new Promise(resolve => {
247
+ const vitals = {};
248
+ new PerformanceObserver(list => {
249
+ for (const entry of list.getEntries()) {
250
+ if (entry.name === 'first-contentful-paint') {
251
+ vitals.FCP = entry.startTime;
252
+ }
253
+ }
254
+ }).observe({ entryTypes: ['paint'] });
255
+
256
+ setTimeout(() => resolve(vitals), 3000);
257
+ });
258
+ });
259
+
260
+ await browser.close();
261
+
262
+ return {
263
+ loadTime,
264
+ metrics,
265
+ performanceTiming,
266
+ resourceTimings,
267
+ vitals
268
+ };
269
+ }
270
+
271
+ // Request interception and modification
272
+ async function interceptRequests(url, rules) {
273
+ const browser = await puppeteer.launch();
274
+ const page = await browser.newPage();
275
+
276
+ await page.setRequestInterception(true);
277
+
278
+ page.on('request', request => {
279
+ const url = request.url();
280
+ const resourceType = request.resourceType();
281
+
282
+ // Block certain resources
283
+ if (rules.blockTypes?.includes(resourceType)) {
284
+ request.abort();
285
+ return;
286
+ }
287
+
288
+ // Block specific domains
289
+ if (rules.blockDomains?.some(domain => url.includes(domain))) {
290
+ request.abort();
291
+ return;
292
+ }
293
+
294
+ // Modify headers
295
+ if (rules.modifyHeaders) {
296
+ request.continue({
297
+ headers: { ...request.headers(), ...rules.modifyHeaders }
298
+ });
299
+ return;
300
+ }
301
+
302
+ request.continue();
303
+ });
304
+
305
+ // Collect responses
306
+ const responses = [];
307
+ page.on('response', response => {
308
+ responses.push({
309
+ url: response.url(),
310
+ status: response.status(),
311
+ headers: response.headers()
312
+ });
313
+ });
314
+
315
+ await page.goto(url);
316
+ await page.waitForTimeout(3000);
317
+
318
+ await browser.close();
319
+ return responses;
320
+ }
321
+
322
+ // Authentication and session management
323
+ async function authenticateAndScrape(loginUrl, targetUrl, credentials) {
324
+ const browser = await puppeteer.launch({ headless: 'new' });
325
+ const page = await browser.newPage();
326
+
327
+ // Login
328
+ await page.goto(loginUrl);
329
+ await page.type('#username', credentials.username);
330
+ await page.type('#password', credentials.password);
331
+ await Promise.all([
332
+ page.waitForNavigation(),
333
+ page.click('button[type="submit"]')
334
+ ]);
335
+
336
+ // Save cookies
337
+ const cookies = await page.cookies();
338
+ await fs.writeFile('cookies.json', JSON.stringify(cookies));
339
+
340
+ // Navigate to target page with auth
341
+ await page.goto(targetUrl);
342
+ const data = await page.evaluate(() => document.body.textContent);
343
+
344
+ await browser.close();
345
+ return data;
346
+ }
347
+
348
+ // Reuse saved session
349
+ async function reuseSession(url, cookiesPath) {
350
+ const browser = await puppeteer.launch();
351
+ const page = await browser.newPage();
352
+
353
+ // Load saved cookies
354
+ const cookiesString = await fs.readFile(cookiesPath);
355
+ const cookies = JSON.parse(cookiesString);
356
+ await page.setCookie(...cookies);
357
+
358
+ await page.goto(url);
359
+ const isAuthenticated = await page.$('.user-profile');
360
+
361
+ await browser.close();
362
+ return isAuthenticated;
363
+ }
364
+
365
+ // Browser debugging and Chrome DevTools
366
+ async function debugPage(url) {
367
+ const browser = await puppeteer.launch({
368
+ headless: false,
369
+ devtools: true, // Open DevTools automatically
370
+ slowMo: 100 // Slow down by 100ms
371
+ });
372
+
373
+ const page = await browser.newPage();
374
+
375
+ // Listen to console logs
376
+ page.on('console', msg => console.log('PAGE LOG:', msg.text()));
377
+
378
+ // Listen to errors
379
+ page.on('pageerror', error => console.log('PAGE ERROR:', error.message));
380
+
381
+ // Listen to request failures
382
+ page.on('requestfailed', request => {
383
+ console.log('REQUEST FAILED:', request.url(), request.failure().errorText);
384
+ });
385
+
386
+ await page.goto(url);
387
+
388
+ // Keep browser open for debugging
389
+ await new Promise(() => {});
390
+ }
391
+ ```
392
+
393
+ ### Python API (Pyppeteer) Examples
394
+
395
+ ```python
396
+ import asyncio
397
+ from pyppeteer import launch
398
+
399
+ async def scrape_page(url):
400
+ browser = await launch(headless=True)
401
+ page = await browser.newPage()
402
+ await page.goto(url)
403
+
404
+ title = await page.title()
405
+ content = await page.evaluate('() => document.body.textContent')
406
+
407
+ await browser.close()
408
+ return {'title': title, 'content': content}
409
+
410
+ async def take_screenshot(url, output):
411
+ browser = await launch()
412
+ page = await browser.newPage()
413
+ await page.setViewport({'width': 1920, 'height': 1080})
414
+ await page.goto(url)
415
+ await page.screenshot({'path': output, 'fullPage': True})
416
+ await browser.close()
417
+
418
+ # Run async function
419
+ asyncio.run(scrape_page('https://example.com'))
420
+ ```
421
+
422
+ ### CLI Usage
423
+
424
+ ```bash
425
+ # Launch Puppeteer with specific Chrome
426
+ PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome node script.js
427
+
428
+ # Set custom cache directory
429
+ PUPPETEER_CACHE_DIR=~/.cache/puppeteer npm install puppeteer
430
+
431
+ # Use system Chrome (skip download)
432
+ PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true npm install puppeteer-core
433
+
434
+ # Debug script with verbose logging
435
+ DEBUG=puppeteer:* node script.js
436
+ ```
437
+
438
+ ## MCP Server Integration
439
+
440
+ Add to `.codebuddy/mcp.json`:
441
+
442
+ ```json
443
+ {
444
+ "mcpServers": {
445
+ "puppeteer": {
446
+ "command": "npx",
447
+ "args": [
448
+ "-y",
449
+ "@nicholasoxford/puppeteer-mcp"
450
+ ],
451
+ "env": {
452
+ "PUPPETEER_EXECUTABLE_PATH": "/usr/bin/google-chrome"
453
+ }
454
+ }
455
+ }
456
+ }
457
+ ```
458
+
459
+ Or use Anthropic's official server:
460
+
461
+ ```json
462
+ {
463
+ "mcpServers": {
464
+ "puppeteer": {
465
+ "command": "npx",
466
+ "args": [
467
+ "-y",
468
+ "@anthropics/puppeteer-mcp"
469
+ ]
470
+ }
471
+ }
472
+ }
473
+ ```
474
+
475
+ ### Available MCP Tools
476
+
477
+ **From @nicholasoxford/puppeteer-mcp:**
478
+ - `puppeteer_navigate` - Navigate to URL
479
+ - `puppeteer_screenshot` - Capture screenshot (full page or element)
480
+ - `puppeteer_click` - Click element by selector
481
+ - `puppeteer_fill` - Fill input field
482
+ - `puppeteer_select` - Select dropdown option
483
+ - `puppeteer_evaluate` - Execute JavaScript in page
484
+ - `puppeteer_pdf` - Generate PDF from page
485
+
486
+ **From @anthropics/puppeteer-mcp:**
487
+ - `puppeteer_launch` - Launch browser instance
488
+ - `puppeteer_goto` - Navigate to URL with options
489
+ - `puppeteer_click_element` - Click with wait and retry
490
+ - `puppeteer_type_text` - Type text with delay
491
+ - `puppeteer_get_content` - Extract page content
492
+ - `puppeteer_screenshot_full` - Full page screenshot
493
+ - `puppeteer_close_browser` - Close browser instance
494
+
495
+ ## Common Workflows
496
+
497
+ ### 1. E-Commerce Price Monitoring
498
+
499
+ ```javascript
500
+ // Step 1: Launch browser and navigate to product page
501
+ const browser = await puppeteer.launch({ headless: 'new' });
502
+ const page = await browser.newPage();
503
+ await page.goto('https://shop.example.com/product/12345');
504
+
505
+ // Step 2: Wait for price element to load
506
+ await page.waitForSelector('.product-price', { timeout: 10000 });
507
+
508
+ // Step 3: Extract product details
509
+ const productData = await page.evaluate(() => {
510
+ return {
511
+ name: document.querySelector('.product-title')?.textContent.trim(),
512
+ price: document.querySelector('.product-price')?.textContent.trim(),
513
+ availability: document.querySelector('.stock-status')?.textContent.trim(),
514
+ rating: document.querySelector('.rating')?.textContent.trim(),
515
+ reviews: document.querySelector('.review-count')?.textContent.trim()
516
+ };
517
+ });
518
+
519
+ // Step 4: Take screenshot for record
520
+ await page.screenshot({ path: `price-${Date.now()}.png` });
521
+
522
+ // Step 5: Store data and alert if price changed
523
+ await fs.writeFile('price-history.json', JSON.stringify({
524
+ timestamp: new Date(),
525
+ ...productData
526
+ }));
527
+ await browser.close();
528
+ ```
529
+
530
+ ### 2. Automated Testing: Multi-Page Flow
531
+
532
+ ```javascript
533
+ // Step 1: Setup browser and login
534
+ const browser = await puppeteer.launch({ headless: false });
535
+ const page = await browser.newPage();
536
+ await page.goto('https://app.example.com/login');
537
+ await page.type('#email', 'test@example.com');
538
+ await page.type('#password', 'TestPass123');
539
+ await page.click('button[type="submit"]');
540
+ await page.waitForNavigation();
541
+
542
+ // Step 2: Navigate through application
543
+ await page.click('a[href="/dashboard"]');
544
+ await page.waitForSelector('.dashboard-content');
545
+
546
+ // Step 3: Verify dashboard elements
547
+ const dashboardStats = await page.$$eval('.stat-card', cards => {
548
+ return cards.map(card => ({
549
+ label: card.querySelector('.stat-label')?.textContent,
550
+ value: card.querySelector('.stat-value')?.textContent
551
+ }));
552
+ });
553
+ console.log('Dashboard stats:', dashboardStats);
554
+
555
+ // Step 4: Test form submission
556
+ await page.click('button.new-item');
557
+ await page.waitForSelector('form.item-form');
558
+ await page.type('#item-name', 'Test Item');
559
+ await page.type('#item-description', 'This is a test');
560
+ await page.click('button.submit-item');
561
+
562
+ // Step 5: Verify success and cleanup
563
+ await page.waitForSelector('.success-notification');
564
+ const successMessage = await page.$eval('.success-notification', el => el.textContent);
565
+ console.log('Success:', successMessage);
566
+ await browser.close();
567
+ ```
568
+
569
+ ### 3. Data Extraction: Table Scraping
570
+
571
+ ```javascript
572
+ // Step 1: Navigate to page with data table
573
+ const browser = await puppeteer.launch();
574
+ const page = await browser.newPage();
575
+ await page.goto('https://example.com/data-table');
576
+
577
+ // Step 2: Wait for table to load
578
+ await page.waitForSelector('table.data-table');
579
+
580
+ // Step 3: Extract all table data
581
+ const tableData = await page.evaluate(() => {
582
+ const rows = Array.from(document.querySelectorAll('table.data-table tbody tr'));
583
+ return rows.map(row => {
584
+ const cells = Array.from(row.querySelectorAll('td'));
585
+ return {
586
+ id: cells[0]?.textContent.trim(),
587
+ name: cells[1]?.textContent.trim(),
588
+ value: cells[2]?.textContent.trim(),
589
+ status: cells[3]?.textContent.trim(),
590
+ date: cells[4]?.textContent.trim()
591
+ };
592
+ });
593
+ });
594
+
595
+ // Step 4: Handle pagination
596
+ let allData = [...tableData];
597
+ let hasNextPage = await page.$('button.next-page:not([disabled])');
598
+ while (hasNextPage) {
599
+ await page.click('button.next-page');
600
+ await page.waitForTimeout(1000);
601
+ const pageData = await page.evaluate(/* same as step 3 */);
602
+ allData = [...allData, ...pageData];
603
+ hasNextPage = await page.$('button.next-page:not([disabled])');
604
+ }
605
+
606
+ // Step 5: Export data
607
+ await fs.writeFile('table-data.json', JSON.stringify(allData, null, 2));
608
+ await browser.close();
609
+ ```
610
+
611
+ ### 4. Report Generation: Automated PDFs
612
+
613
+ ```javascript
614
+ // Step 1: Navigate to report page
615
+ const browser = await puppeteer.launch();
616
+ const page = await browser.newPage();
617
+ await page.goto('https://analytics.example.com/report?id=123');
618
+
619
+ // Step 2: Wait for all charts to render
620
+ await page.waitForSelector('.chart-container canvas');
621
+ await page.waitForTimeout(2000); // Extra wait for animations
622
+
623
+ // Step 3: Hide unwanted elements
624
+ await page.addStyleTag({
625
+ content: '.no-print { display: none !important; }'
626
+ });
627
+
628
+ // Step 4: Generate PDF with custom styling
629
+ await page.pdf({
630
+ path: 'report.pdf',
631
+ format: 'A4',
632
+ printBackground: true,
633
+ margin: { top: '20mm', bottom: '20mm', left: '15mm', right: '15mm' },
634
+ displayHeaderFooter: true,
635
+ headerTemplate: `
636
+ <div style="font-size:10px;width:100%;text-align:center;">
637
+ <span>Monthly Analytics Report</span>
638
+ </div>
639
+ `,
640
+ footerTemplate: `
641
+ <div style="font-size:10px;width:100%;text-align:center;">
642
+ <span class="pageNumber"></span> / <span class="totalPages"></span>
643
+ </div>
644
+ `
645
+ });
646
+
647
+ // Step 5: Cleanup
648
+ await browser.close();
649
+ console.log('PDF generated: report.pdf');
650
+ ```
651
+
652
+ ### 5. API Testing via Browser
653
+
654
+ ```javascript
655
+ // Step 1: Setup request interception
656
+ const browser = await puppeteer.launch();
657
+ const page = await browser.newPage();
658
+ await page.setRequestInterception(true);
659
+
660
+ const apiCalls = [];
661
+ page.on('request', request => {
662
+ if (request.url().includes('/api/')) {
663
+ apiCalls.push({
664
+ url: request.url(),
665
+ method: request.method(),
666
+ headers: request.headers(),
667
+ postData: request.postData()
668
+ });
669
+ }
670
+ request.continue();
671
+ });
672
+
673
+ const apiResponses = [];
674
+ page.on('response', async response => {
675
+ if (response.url().includes('/api/')) {
676
+ apiResponses.push({
677
+ url: response.url(),
678
+ status: response.status(),
679
+ headers: response.headers(),
680
+ body: await response.text().catch(() => null)
681
+ });
682
+ }
683
+ });
684
+
685
+ // Step 2: Trigger API calls through UI
686
+ await page.goto('https://app.example.com');
687
+ await page.click('button.load-data');
688
+ await page.waitForTimeout(3000);
689
+
690
+ // Step 3: Verify API responses
691
+ const errors = apiResponses.filter(r => r.status >= 400);
692
+ console.log(`Total API calls: ${apiCalls.length}`);
693
+ console.log(`Failed requests: ${errors.length}`);
694
+
695
+ // Step 4: Analyze response times
696
+ const timings = apiResponses.map(r => ({
697
+ url: r.url,
698
+ time: r.timing?.responseEnd - r.timing?.requestStart
699
+ }));
700
+
701
+ // Step 5: Cleanup and report
702
+ await fs.writeFile('api-report.json', JSON.stringify({
703
+ calls: apiCalls,
704
+ responses: apiResponses,
705
+ errors
706
+ }, null, 2));
707
+ await browser.close();
708
+ ```