onbuzz 4.9.13 → 4.10.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 (451) hide show
  1. package/node_modules/glob/README.md +31 -5
  2. package/node_modules/glob/dist/commonjs/glob.d.ts +8 -0
  3. package/node_modules/glob/dist/commonjs/glob.d.ts.map +1 -1
  4. package/node_modules/glob/dist/commonjs/glob.js +2 -1
  5. package/node_modules/glob/dist/commonjs/glob.js.map +1 -1
  6. package/node_modules/glob/dist/commonjs/index.min.js +3 -3
  7. package/node_modules/glob/dist/commonjs/index.min.js.map +4 -4
  8. package/node_modules/glob/dist/commonjs/pattern.d.ts +3 -0
  9. package/node_modules/glob/dist/commonjs/pattern.d.ts.map +1 -1
  10. package/node_modules/glob/dist/commonjs/pattern.js +4 -0
  11. package/node_modules/glob/dist/commonjs/pattern.js.map +1 -1
  12. package/node_modules/glob/dist/esm/glob.d.ts +8 -0
  13. package/node_modules/glob/dist/esm/glob.d.ts.map +1 -1
  14. package/node_modules/glob/dist/esm/glob.js +2 -1
  15. package/node_modules/glob/dist/esm/glob.js.map +1 -1
  16. package/node_modules/glob/dist/esm/index.min.js +3 -3
  17. package/node_modules/glob/dist/esm/index.min.js.map +4 -4
  18. package/node_modules/glob/dist/esm/pattern.d.ts +3 -0
  19. package/node_modules/glob/dist/esm/pattern.d.ts.map +1 -1
  20. package/node_modules/glob/dist/esm/pattern.js +4 -0
  21. package/node_modules/glob/dist/esm/pattern.js.map +1 -1
  22. package/node_modules/{@isaacs → glob/node_modules}/balanced-match/README.md +7 -10
  23. package/node_modules/{@isaacs → glob/node_modules}/balanced-match/package.json +7 -18
  24. package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/README.md +3 -6
  25. package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/commonjs/index.js +6 -4
  26. package/node_modules/glob/node_modules/brace-expansion/dist/commonjs/index.js.map +1 -0
  27. package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/esm/index.js +6 -4
  28. package/node_modules/glob/node_modules/brace-expansion/dist/esm/index.js.map +1 -0
  29. package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/package.json +11 -7
  30. package/node_modules/glob/node_modules/minimatch/README.md +76 -1
  31. package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts +1 -1
  32. package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts.map +1 -1
  33. package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js.map +1 -1
  34. package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.d.ts +4 -2
  35. package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.d.ts.map +1 -1
  36. package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.js +309 -55
  37. package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.js.map +1 -1
  38. package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts.map +1 -1
  39. package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.js +2 -4
  40. package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.js.map +1 -1
  41. package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.d.ts +1 -1
  42. package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.d.ts.map +1 -1
  43. package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.js +4 -4
  44. package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.js.map +1 -1
  45. package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.d.ts +81 -1
  46. package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.d.ts.map +1 -1
  47. package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.js +232 -134
  48. package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.js.map +1 -1
  49. package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.d.ts +1 -1
  50. package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.d.ts.map +1 -1
  51. package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.js +8 -8
  52. package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.js.map +1 -1
  53. package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts +1 -1
  54. package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts.map +1 -1
  55. package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.js.map +1 -1
  56. package/node_modules/glob/node_modules/minimatch/dist/esm/ast.d.ts +4 -2
  57. package/node_modules/glob/node_modules/minimatch/dist/esm/ast.d.ts.map +1 -1
  58. package/node_modules/glob/node_modules/minimatch/dist/esm/ast.js +309 -55
  59. package/node_modules/glob/node_modules/minimatch/dist/esm/ast.js.map +1 -1
  60. package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.d.ts.map +1 -1
  61. package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.js +2 -4
  62. package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.js.map +1 -1
  63. package/node_modules/glob/node_modules/minimatch/dist/esm/escape.d.ts +1 -1
  64. package/node_modules/glob/node_modules/minimatch/dist/esm/escape.d.ts.map +1 -1
  65. package/node_modules/glob/node_modules/minimatch/dist/esm/escape.js +4 -4
  66. package/node_modules/glob/node_modules/minimatch/dist/esm/escape.js.map +1 -1
  67. package/node_modules/glob/node_modules/minimatch/dist/esm/index.d.ts +81 -1
  68. package/node_modules/glob/node_modules/minimatch/dist/esm/index.d.ts.map +1 -1
  69. package/node_modules/glob/node_modules/minimatch/dist/esm/index.js +232 -134
  70. package/node_modules/glob/node_modules/minimatch/dist/esm/index.js.map +1 -1
  71. package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.d.ts +1 -1
  72. package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.d.ts.map +1 -1
  73. package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.js +8 -8
  74. package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.js.map +1 -1
  75. package/node_modules/glob/node_modules/minimatch/package.json +17 -11
  76. package/node_modules/glob/package.json +10 -13
  77. package/node_modules/minipass/LICENSE.md +55 -0
  78. package/node_modules/minipass/dist/commonjs/index.d.ts +12 -16
  79. package/node_modules/minipass/dist/commonjs/index.d.ts.map +1 -1
  80. package/node_modules/minipass/dist/commonjs/index.js +13 -3
  81. package/node_modules/minipass/dist/commonjs/index.js.map +1 -1
  82. package/node_modules/minipass/dist/esm/index.d.ts +12 -16
  83. package/node_modules/minipass/dist/esm/index.d.ts.map +1 -1
  84. package/node_modules/minipass/dist/esm/index.js +3 -1
  85. package/node_modules/minipass/dist/esm/index.js.map +1 -1
  86. package/node_modules/minipass/package.json +9 -14
  87. package/node_modules/path-scurry/node_modules/lru-cache/README.md +96 -10
  88. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel-browser.d.ts.map +1 -0
  89. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel-browser.js.map +1 -0
  90. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel.d.ts +5 -0
  91. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel.js +7 -0
  92. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.d.ts +1400 -0
  93. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.d.ts.map +1 -0
  94. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.js +1726 -0
  95. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.js.map +1 -0
  96. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.min.js +2 -0
  97. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.min.js.map +7 -0
  98. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.d.ts +12 -0
  99. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.d.ts.map +1 -0
  100. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.js +10 -0
  101. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.js.map +1 -0
  102. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel-cjs.cjs.map +1 -0
  103. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel-cjs.d.cts.map +1 -0
  104. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel.d.ts +5 -0
  105. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel.js +7 -0
  106. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.d.ts +109 -32
  107. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.d.ts.map +1 -1
  108. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js +334 -197
  109. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js.map +1 -1
  110. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js +1 -1
  111. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js.map +4 -4
  112. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel-node.d.ts.map +1 -0
  113. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel-node.js.map +1 -0
  114. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel.d.ts +5 -0
  115. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel.js +9 -0
  116. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.d.ts +1400 -0
  117. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.d.ts.map +1 -0
  118. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.js +1726 -0
  119. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.js.map +1 -0
  120. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.min.js +2 -0
  121. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.min.js.map +7 -0
  122. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.d.ts +12 -0
  123. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.d.ts.map +1 -0
  124. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.js +10 -0
  125. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.js.map +1 -0
  126. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.d.ts +12 -0
  127. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.d.ts.map +1 -0
  128. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.js +10 -0
  129. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.js.map +1 -0
  130. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel-browser.d.ts.map +1 -0
  131. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel-browser.js.map +1 -0
  132. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.d.ts +5 -0
  133. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.js +4 -0
  134. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.d.ts +1400 -0
  135. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.d.ts.map +1 -0
  136. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.js +1722 -0
  137. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.js.map +1 -0
  138. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.min.js +2 -0
  139. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.min.js.map +7 -0
  140. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.d.ts +12 -0
  141. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.d.ts.map +1 -0
  142. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.js +7 -0
  143. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.js.map +1 -0
  144. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel-esm.d.mts.map +1 -0
  145. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel-esm.mjs.map +1 -0
  146. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel.d.ts +5 -0
  147. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel.js +19 -0
  148. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.d.ts +109 -32
  149. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.d.ts.map +1 -1
  150. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js +333 -196
  151. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js.map +1 -1
  152. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js +1 -1
  153. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js.map +4 -4
  154. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel-node.d.ts.map +1 -0
  155. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel-node.js.map +1 -0
  156. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel.d.ts +5 -0
  157. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel.js +6 -0
  158. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.d.ts +1400 -0
  159. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.d.ts.map +1 -0
  160. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.js +1722 -0
  161. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.js.map +1 -0
  162. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.min.js +2 -0
  163. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.min.js.map +7 -0
  164. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.d.ts +12 -0
  165. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.d.ts.map +1 -0
  166. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.js +7 -0
  167. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.js.map +1 -0
  168. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.d.ts +12 -0
  169. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.d.ts.map +1 -0
  170. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.js +7 -0
  171. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.js.map +1 -0
  172. package/node_modules/path-scurry/node_modules/lru-cache/package.json +71 -18
  173. package/node_modules/path-scurry/package.json +8 -24
  174. package/package.json +1 -1
  175. package/scripts/debug-balance-probe.mjs +35 -35
  176. package/scripts/push-image.sh +43 -43
  177. package/scripts/setup-acr.sh +65 -65
  178. package/scripts/verify-optional-deps.js +96 -1
  179. package/src/__tests__/composioCliFlags.test.js +239 -239
  180. package/src/analyzers/CSSAnalyzer.js +298 -297
  181. package/src/analyzers/ConfigValidator.js +691 -690
  182. package/src/analyzers/ESLintAnalyzer.js +320 -320
  183. package/src/analyzers/JavaScriptAnalyzer.js +260 -261
  184. package/src/analyzers/PrettierFormatter.js +246 -247
  185. package/src/analyzers/PythonAnalyzer.js +283 -283
  186. package/src/analyzers/SecurityAnalyzer.js +729 -729
  187. package/src/analyzers/SparrowAnalyzer.js +341 -341
  188. package/src/analyzers/TypeScriptAnalyzer.js +247 -247
  189. package/src/analyzers/__tests__/CSSAnalyzer.test.js +41 -41
  190. package/src/analyzers/__tests__/ConfigValidator.test.js +362 -362
  191. package/src/analyzers/__tests__/JavaScriptAnalyzer.test.js +40 -40
  192. package/src/analyzers/__tests__/PythonAnalyzer.test.js +205 -208
  193. package/src/analyzers/__tests__/SecurityAnalyzer.test.js +303 -303
  194. package/src/analyzers/__tests__/TypeScriptAnalyzer.test.js +187 -187
  195. package/src/analyzers/codeCloneDetector/analyzer.js +344 -344
  196. package/src/analyzers/codeCloneDetector/detector.js +250 -250
  197. package/src/analyzers/codeCloneDetector/index.js +194 -192
  198. package/src/analyzers/codeCloneDetector/parser.js +199 -199
  199. package/src/core/__tests__/agentPool.test.js +866 -866
  200. package/src/core/__tests__/agentPoolAutoResume.test.js +209 -209
  201. package/src/core/__tests__/agentPoolWakeOnMessage.test.js +315 -315
  202. package/src/core/__tests__/agentScheduler.emptyResponseChatStall.test.js +213 -213
  203. package/src/core/__tests__/agentScheduler.errorCategorisation.test.js +246 -246
  204. package/src/core/__tests__/agentScheduler.firstChunkTimeout.test.js +138 -138
  205. package/src/core/__tests__/agentScheduler.modeTransitions.test.js +233 -233
  206. package/src/core/__tests__/agentScheduler.nativePromptPick.test.js +319 -319
  207. package/src/core/__tests__/agentScheduler.taskLifecycleInstruction.test.js +78 -78
  208. package/src/core/__tests__/agentScheduler.visualizer.test.js +258 -258
  209. package/src/core/__tests__/flowCheckpointStore.test.js +140 -140
  210. package/src/core/__tests__/flowEndToEnd.test.js +565 -565
  211. package/src/core/__tests__/flowFieldMapping.test.js +188 -189
  212. package/src/core/__tests__/flowLintClientMirror.test.js +96 -98
  213. package/src/core/__tests__/flowSavePayload.test.js +170 -169
  214. package/src/core/__tests__/flowTemplates.test.js +311 -311
  215. package/src/core/__tests__/flowVersionStore.test.js +123 -123
  216. package/src/core/__tests__/messageProcessor.test.js +669 -669
  217. package/src/core/__tests__/stateManager.test.js +0 -1
  218. package/src/core/agentPool.js +2474 -2475
  219. package/src/core/agentScheduler.js +1 -4
  220. package/src/core/contextManager.js +708 -708
  221. package/src/core/flowExecutor.js +1510 -1510
  222. package/src/core/flowFieldMapping.js +136 -138
  223. package/src/core/messageProcessor.js +953 -954
  224. package/src/core/orchestrator.js +593 -595
  225. package/src/core/stateManager.js +1765 -1752
  226. package/src/index.js +1221 -1221
  227. package/src/interfaces/__tests__/archivedAgentDelete.test.js +207 -207
  228. package/src/interfaces/__tests__/bulkAgentRoute.test.js +361 -361
  229. package/src/interfaces/__tests__/imageServing.test.js +228 -228
  230. package/src/interfaces/__tests__/remoteSessionAuth.test.js +308 -308
  231. package/src/interfaces/__tests__/videoJobsRoutes.test.js +178 -179
  232. package/src/interfaces/__tests__/webServer.marketplace.test.js +629 -629
  233. package/src/interfaces/schedulerRoutes.js +50 -50
  234. package/src/interfaces/terminal/__tests__/smoke/connection.test.js +341 -350
  235. package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +156 -156
  236. package/src/interfaces/terminal/__tests__/smoke/imports.test.js +325 -330
  237. package/src/interfaces/terminal/__tests__/smoke/tools.test.js +385 -388
  238. package/src/interfaces/terminal/api/session.js +265 -266
  239. package/src/interfaces/terminal/api/websocket.js +496 -497
  240. package/src/interfaces/terminal/components/AgentCreator.js +691 -705
  241. package/src/interfaces/terminal/components/AgentEditor.js +676 -678
  242. package/src/interfaces/terminal/components/AgentSwitcher.js +331 -330
  243. package/src/interfaces/terminal/components/ErrorPanel.js +263 -264
  244. package/src/interfaces/terminal/components/Header.js +28 -28
  245. package/src/interfaces/terminal/components/Layout.js +598 -603
  246. package/src/interfaces/terminal/components/MessageList.js +280 -281
  247. package/src/interfaces/terminal/components/SettingsPanel.js +410 -415
  248. package/src/interfaces/terminal/components/StatusBar.js +2 -0
  249. package/src/interfaces/terminal/index.js +168 -168
  250. package/src/interfaces/terminal/state/useAgentControl.js +496 -496
  251. package/src/interfaces/terminal/state/useAgents.js +537 -537
  252. package/src/interfaces/terminal/state/useMessages.js +629 -630
  253. package/src/interfaces/terminal/state/useTools.js +554 -554
  254. package/src/interfaces/terminal/utils/debugLogger.js +44 -44
  255. package/src/interfaces/terminal/utils/settingsStorage.js +232 -232
  256. package/src/interfaces/webServer.js +7578 -7579
  257. package/src/interfaces/webServer.js.bak +7046 -7046
  258. package/src/modules/fileExplorer/__tests__/zipDownload.test.js +237 -237
  259. package/src/modules/fileExplorer/controller.js +470 -469
  260. package/src/modules/fileExplorer/routes.js +285 -286
  261. package/src/modules/widget/__tests__/isDisabled.test.js +41 -41
  262. package/src/modules/widget/__tests__/routes.test.js +677 -678
  263. package/src/modules/widget/__tests__/runtime.test.js +401 -401
  264. package/src/modules/widget/__tests__/versioning.test.js +309 -309
  265. package/src/modules/widget/__tests__/webComponentRuntime.test.js +565 -565
  266. package/src/modules/widget/__tests__/widgetTool.test.js +316 -316
  267. package/src/modules/widget/routes.js +435 -435
  268. package/src/modules/widget/runtime/bundle.js +640 -640
  269. package/src/modules/widget/runtime/webComponentBundle.js +470 -470
  270. package/src/modules/widget/schema.js +182 -181
  271. package/src/modules/widget/widgetTool.js +1389 -1389
  272. package/src/services/__tests__/agentActivityService.test.js +401 -402
  273. package/src/services/__tests__/benchmarkService.test.js +184 -184
  274. package/src/services/__tests__/contextInjectionService.test.js +246 -246
  275. package/src/services/__tests__/conversationQuery.test.js +721 -723
  276. package/src/services/__tests__/credentialVault.test.js +469 -469
  277. package/src/services/__tests__/discordService.integration.test.js +638 -639
  278. package/src/services/__tests__/flowContextService.test.js +590 -590
  279. package/src/services/__tests__/memoryService.test.js +1 -1
  280. package/src/services/__tests__/messageSource.test.js +380 -380
  281. package/src/services/__tests__/modelRouterNaming.test.js +111 -111
  282. package/src/services/__tests__/projectDetector.test.js +34 -34
  283. package/src/services/__tests__/promptService.test.js +242 -242
  284. package/src/services/__tests__/telegramService.test.js +941 -941
  285. package/src/services/__tests__/tokenCountingService.test.js +48 -48
  286. package/src/services/agentActivityService.js +419 -420
  287. package/src/services/aiService.js +2997 -3001
  288. package/src/services/apiKeyManager.js +359 -359
  289. package/src/services/benchmarkService.js +196 -196
  290. package/src/services/codebaseKnowledgeService.js +2 -2
  291. package/src/services/composioService.js +738 -738
  292. package/src/services/conversationCompactionService.js +1258 -1257
  293. package/src/services/credentialVault.js +685 -685
  294. package/src/services/discordService.js +792 -793
  295. package/src/services/embeddings/__tests__/azureCustomProvider.test.js +232 -232
  296. package/src/services/embeddings/__tests__/embeddingService.test.js +417 -417
  297. package/src/services/embeddings/__tests__/localProvider.test.js +263 -263
  298. package/src/services/embeddings/autoRecall.js +218 -219
  299. package/src/services/embeddings/indexers/__tests__/agentIndexer.test.js +232 -232
  300. package/src/services/embeddings/indexers/__tests__/memoryIndexer.test.js +418 -418
  301. package/src/services/embeddings/indexers/__tests__/reminisceIndexer.test.js +356 -357
  302. package/src/services/embeddings/indexers/__tests__/skillsIndexer.test.js +145 -145
  303. package/src/services/embeddings/indexers/__tests__/taskIndexer.test.js +146 -146
  304. package/src/services/embeddings/indexers/composioIndexer.js +279 -279
  305. package/src/services/embeddings/providerInterface.js +206 -206
  306. package/src/services/embeddings/providers/localProvider.js +11 -7
  307. package/src/services/embeddings/providers/openaiProvider.js +101 -101
  308. package/src/services/embeddings/vectorStore/inMemoryJsonStore.js +356 -356
  309. package/src/services/errorHandler.js +809 -809
  310. package/src/services/flowContextService.js +586 -586
  311. package/src/services/grounding/MockAdapter.js +125 -125
  312. package/src/services/modelRouterService.js +26 -31
  313. package/src/services/modelsService.js +322 -322
  314. package/src/services/ollamaService.js +452 -452
  315. package/src/services/projectDetector.js +403 -404
  316. package/src/services/promptService.js +418 -418
  317. package/src/services/qualityInspector.js +795 -795
  318. package/src/services/scheduleService.js +726 -726
  319. package/src/services/serviceRegistry.js +386 -386
  320. package/src/services/telegrafBot.js +174 -174
  321. package/src/services/telegramService.js +1972 -1972
  322. package/src/services/visualEditorBridge.js +1033 -1033
  323. package/src/services/visualEditorServer.js +1769 -1774
  324. package/src/services/whatsappService.js +667 -668
  325. package/src/tools/__tests__/agentCommunicationTool.findAgent.test.js +226 -226
  326. package/src/tools/__tests__/agentCommunicationTool.test.js +3 -3
  327. package/src/tools/__tests__/agentDelayTool.test.js +342 -342
  328. package/src/tools/__tests__/baseTool.test.js +3 -3
  329. package/src/tools/__tests__/codeMapTool.test.js +915 -915
  330. package/src/tools/__tests__/fileContentReplaceTool.test.js +309 -309
  331. package/src/tools/__tests__/fileTreeTool.test.js +274 -274
  332. package/src/tools/__tests__/filesystemTool.test.js +815 -815
  333. package/src/tools/__tests__/foundryWebSearchTool.test.js +252 -252
  334. package/src/tools/__tests__/imageTool.validator.test.js +194 -194
  335. package/src/tools/__tests__/jobDoneTool.test.js +580 -581
  336. package/src/tools/__tests__/memoryTool.forgetStale.test.js +272 -272
  337. package/src/tools/__tests__/memoryTool.reminisce.test.js +2 -2
  338. package/src/tools/__tests__/memoryTool.reminisceSemanticSearch.test.js +301 -301
  339. package/src/tools/__tests__/memoryTool.semanticSearch.test.js +405 -405
  340. package/src/tools/__tests__/memoryTool.teamPool.test.js +293 -293
  341. package/src/tools/__tests__/memoryTool.test.js +1 -1
  342. package/src/tools/__tests__/seekTool.test.js +282 -282
  343. package/src/tools/__tests__/skillsTool.search.test.js +164 -164
  344. package/src/tools/__tests__/skillsTool.test.js +226 -226
  345. package/src/tools/__tests__/staticAnalysisTool.test.js +509 -509
  346. package/src/tools/__tests__/taskManagerTool.discipline.test.js +137 -137
  347. package/src/tools/__tests__/taskManagerTool.search.test.js +143 -143
  348. package/src/tools/__tests__/taskManagerTool.test.js +866 -866
  349. package/src/tools/__tests__/terminalTool.test.js +448 -448
  350. package/src/tools/__tests__/toolShapeForgiveness.test.js +259 -260
  351. package/src/tools/__tests__/userPromptTool.test.js +297 -297
  352. package/src/tools/__tests__/videoTool.jobs.test.js +147 -147
  353. package/src/tools/__tests__/webTool.e2e.test.js +609 -603
  354. package/src/tools/__tests__/webTool.unit.test.js +195 -195
  355. package/src/tools/__tests__/webTool.visionModel.test.js +75 -75
  356. package/src/tools/agentCommunicationTool.js +8 -10
  357. package/src/tools/agentDelayTool.js +496 -497
  358. package/src/tools/asyncToolManager.js +602 -603
  359. package/src/tools/baseTool.js +12 -11
  360. package/src/tools/cloneDetectionTool.js +576 -581
  361. package/src/tools/codeMapTool.js +0 -6
  362. package/src/tools/composioTool.js +617 -617
  363. package/src/tools/dependencyResolverTool.js +1211 -1212
  364. package/src/tools/desktop/DesktopTool.js +629 -638
  365. package/src/tools/desktop/__tests__/DesktopTool.e2e.test.js +306 -306
  366. package/src/tools/desktop/__tests__/DesktopTool.test.js +507 -507
  367. package/src/tools/desktop/__tests__/osController.test.js +364 -364
  368. package/src/tools/desktop/osController.js +491 -491
  369. package/src/tools/docxTool.js +623 -623
  370. package/src/tools/excelTool.js +636 -636
  371. package/src/tools/fileContentReplaceTool.js +5 -7
  372. package/src/tools/fileSystemTool.js +12 -19
  373. package/src/tools/fileTreeTool.js +840 -840
  374. package/src/tools/foundryWebSearchTool.js +273 -273
  375. package/src/tools/helpTool.js +198 -198
  376. package/src/tools/imageTool.js +1397 -1397
  377. package/src/tools/importAnalyzerTool.js +1056 -1056
  378. package/src/tools/jobDoneTool.js +495 -495
  379. package/src/tools/memoryTool.js +1 -1
  380. package/src/tools/office/pres/__tests__/presSystem.test.js +365 -365
  381. package/src/tools/office/pres/archetypes/agenda.js +61 -61
  382. package/src/tools/office/pres/archetypes/bentoGrid.js +218 -219
  383. package/src/tools/office/pres/archetypes/bigStat.js +140 -142
  384. package/src/tools/office/pres/archetypes/closing.js +70 -70
  385. package/src/tools/office/pres/archetypes/hero.js +70 -70
  386. package/src/tools/office/pres/archetypes/productHero.js +93 -94
  387. package/src/tools/office/pres/archetypes/table.js +73 -74
  388. package/src/tools/office/pres/backgrounds/orb.js +66 -66
  389. package/src/tools/office/pres/components.js +422 -423
  390. package/src/tools/officeTool.js +441 -441
  391. package/src/tools/pdfTool.js +625 -627
  392. package/src/tools/platformControlTool.js +1081 -1081
  393. package/src/tools/seekTool.js +917 -918
  394. package/src/tools/skillsTool.js +1 -1
  395. package/src/tools/staticAnalysisTool.js +2143 -2146
  396. package/src/tools/taskManagerTool.js +3324 -3324
  397. package/src/tools/terminalTool.js +2615 -2618
  398. package/src/tools/videoTool.js +1303 -1303
  399. package/src/tools/visionTool.js +508 -508
  400. package/src/tools/visualEditorTool.js +1289 -1290
  401. package/src/tools/webTool.js +3368 -3368
  402. package/src/tools/whatsappTool.js +464 -464
  403. package/src/types/__tests__/agent.test.js +499 -499
  404. package/src/types/__tests__/contextReference.test.js +606 -606
  405. package/src/types/__tests__/conversation.test.js +555 -555
  406. package/src/types/__tests__/toolCommand.test.js +584 -584
  407. package/src/types/contextReference.js +974 -971
  408. package/src/types/conversation.js +729 -729
  409. package/src/types/toolCommand.js +746 -746
  410. package/src/utilities/__tests__/attachmentValidator.test.js +80 -80
  411. package/src/utilities/__tests__/auditReport.test.js +328 -328
  412. package/src/utilities/__tests__/directoryAccessManager.test.js +388 -388
  413. package/src/utilities/__tests__/jsonRepair.test.js +103 -104
  414. package/src/utilities/__tests__/modeTransitionReasons.test.js +105 -105
  415. package/src/utilities/__tests__/platformUtils.test.js +80 -87
  416. package/src/utilities/__tests__/structuredFileValidator.test.js +261 -263
  417. package/src/utilities/__tests__/toolConstants.test.js +92 -94
  418. package/src/utilities/__tests__/useIsTouchDevice.detect.test.js +114 -114
  419. package/src/utilities/__tests__/webUiUtilSync.test.js +117 -117
  420. package/src/utilities/attachmentValidator.js +284 -288
  421. package/src/utilities/authCache.js.backup-1779570472481 +121 -121
  422. package/src/utilities/browserStealth.js +631 -630
  423. package/src/utilities/configManager.js +616 -617
  424. package/src/utilities/directoryAccessManager.js +564 -565
  425. package/src/utilities/fileProcessor.js +308 -307
  426. package/src/utilities/humanBehavior.js +454 -453
  427. package/src/utilities/logger.js +479 -479
  428. package/src/utilities/structuredFileValidator.js +696 -699
  429. package/src/utilities/tagParser.js +5 -10
  430. package/src/utilities/userDataDir.js +308 -308
  431. package/node_modules/@isaacs/brace-expansion/dist/commonjs/index.js.map +0 -1
  432. package/node_modules/@isaacs/brace-expansion/dist/esm/index.js.map +0 -1
  433. package/node_modules/minipass/LICENSE +0 -15
  434. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/LICENSE.md +0 -0
  435. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/index.d.ts +0 -0
  436. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/index.d.ts.map +0 -0
  437. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/index.js +0 -0
  438. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/index.js.map +0 -0
  439. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/package.json +0 -0
  440. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/index.d.ts +0 -0
  441. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/index.d.ts.map +0 -0
  442. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/index.js +0 -0
  443. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/index.js.map +0 -0
  444. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/package.json +0 -0
  445. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/LICENSE +0 -0
  446. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/commonjs/index.d.ts +0 -0
  447. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/commonjs/index.d.ts.map +0 -0
  448. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/commonjs/package.json +0 -0
  449. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/esm/index.d.ts +0 -0
  450. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/esm/index.d.ts.map +0 -0
  451. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/esm/package.json +0 -0
@@ -1,627 +1,625 @@
1
- /**
2
- * PDF Tool - Read, extract, and create PDF files
3
- *
4
- * Purpose:
5
- * - Get PDF metadata (page count, info)
6
- * - Extract text content from specific page ranges
7
- * - Create PDF files from HTML content using Puppeteer
8
- * - Provide structured access to PDF documents
9
- */
10
-
11
- import { BaseTool } from './baseTool.js';
12
- import TagParser from '../utilities/tagParser.js';
13
- import fs from 'fs/promises';
14
- import path from 'path';
15
-
16
- // Dynamic import for pdf2json
17
- let PDFParser = null;
18
-
19
- // Dynamic import for puppeteer (used for PDF creation)
20
- let puppeteerModule = null;
21
-
22
- class PdfTool extends BaseTool {
23
- constructor(config = {}, logger = null) {
24
- super(config, logger);
25
- this.id = 'pdf';
26
- this.name = 'PDF Tool';
27
- this.description = 'Read, extract, and create PDF files';
28
- this.version = '2.0.0';
29
- this.capabilities = ['pdf-read', 'pdf-info', 'pdf-create'];
30
- this.requiresProject = false;
31
- this.isAsync = false;
32
- this.pdfParserLoaded = false;
33
- this.pdfParserError = null;
34
- this.puppeteerLoaded = false;
35
- this.puppeteerError = null;
36
- }
37
-
38
- /**
39
- * Lazily load pdf2json module
40
- * @returns {Promise<boolean>} Whether loading succeeded
41
- */
42
- async loadPdfParser() {
43
- if (this.pdfParserLoaded) return true;
44
- if (this.pdfParserError) return false;
45
-
46
- try {
47
- const module = await import('pdf2json');
48
- PDFParser = module.default;
49
- this.pdfParserLoaded = true;
50
- return true;
51
- } catch (error) {
52
- this.pdfParserError = error.message;
53
- this.logger?.error('Failed to load pdf2json', { error: error.message });
54
- return false;
55
- }
56
- }
57
-
58
- /**
59
- * Lazily load puppeteer module for PDF creation
60
- * @returns {Promise<boolean>} Whether loading succeeded
61
- */
62
- async loadPuppeteer() {
63
- if (this.puppeteerLoaded) return true;
64
- if (this.puppeteerError) return false;
65
-
66
- try {
67
- const module = await import('puppeteer');
68
- puppeteerModule = module.default;
69
- this.puppeteerLoaded = true;
70
- return true;
71
- } catch (error) {
72
- this.puppeteerError = error.message;
73
- this.logger?.error('Failed to load puppeteer', { error: error.message });
74
- return false;
75
- }
76
- }
77
-
78
- /**
79
- * Get tool description for LLM consumption
80
- * @returns {string} Tool description
81
- */
82
- getDescription() {
83
- return `
84
- PDF Tool: Read, extract, and create PDF files.
85
-
86
- USAGE:
87
- \`\`\`json
88
- {
89
- "toolId": "pdf",
90
- "actions": [{
91
- "action": "get-info",
92
- "filePath": "/path/to/document.pdf"
93
- }]
94
- }
95
- \`\`\`
96
-
97
- ACTIONS:
98
-
99
- 1. **get-info** - Get PDF metadata (page count, title, author, etc.)
100
- - filePath: Path to PDF file (required)
101
-
102
- 2. **read-pages** - Extract text content from specific pages
103
- - filePath: Path to PDF file (required)
104
- - startPage: First page to read, 1-indexed, inclusive (default: 1)
105
- - endPage: Last page to read, exclusive (default: startPage + 10)
106
- - IMPORTANT: Read max 10 pages at once for optimal performance
107
-
108
- 3. **create-pdf** - Create a PDF from HTML content
109
- - outputPath: Output file path (required, relative to project dir or absolute)
110
- - htmlContent: Full HTML string to render (required)
111
- - pageSize: Page size - A4 (default), Letter, Legal, Tabloid, A3, A5
112
- - orientation: portrait (default) or landscape
113
- - margins: Object with top, right, bottom, left in CSS units (default: 1cm each)
114
- - printBackground: Whether to print background colors/images (default: true)
115
- - displayHeaderFooter: Show header/footer (default: false)
116
- - headerTemplate: HTML template for header
117
- - footerTemplate: HTML template for footer
118
-
119
- EXAMPLES:
120
-
121
- 1. Get PDF info:
122
- \`\`\`json
123
- {
124
- "toolId": "pdf",
125
- "actions": [{
126
- "action": "get-info",
127
- "filePath": "documents/report.pdf"
128
- }]
129
- }
130
- \`\`\`
131
-
132
- 2. Read pages 1-10:
133
- \`\`\`json
134
- {
135
- "toolId": "pdf",
136
- "actions": [{
137
- "action": "read-pages",
138
- "filePath": "documents/report.pdf",
139
- "startPage": 1,
140
- "endPage": 11
141
- }]
142
- }
143
- \`\`\`
144
-
145
- 3. Create a PDF from HTML:
146
- \`\`\`json
147
- {
148
- "toolId": "pdf",
149
- "actions": [{
150
- "action": "create-pdf",
151
- "outputPath": "output/report.pdf",
152
- "htmlContent": "<html><head><style>body{font-family:Arial;margin:2cm}h1{color:#333}</style></head><body><h1>Report</h1><p>Content here...</p></body></html>",
153
- "pageSize": "A4",
154
- "orientation": "portrait"
155
- }]
156
- }
157
- \`\`\`
158
-
159
- 4. Create a landscape PDF with custom margins:
160
- \`\`\`json
161
- {
162
- "toolId": "pdf",
163
- "actions": [{
164
- "action": "create-pdf",
165
- "outputPath": "output/wide-report.pdf",
166
- "htmlContent": "<html><body><h1>Wide Report</h1><table>...</table></body></html>",
167
- "pageSize": "Letter",
168
- "orientation": "landscape",
169
- "margins": { "top": "2cm", "right": "1.5cm", "bottom": "2cm", "left": "1.5cm" }
170
- }]
171
- }
172
- \`\`\`
173
-
174
- NOTES:
175
- - Page numbers are 1-indexed (first page is 1)
176
- - endPage is exclusive (like Python range)
177
- - Recommend reading max 10 pages at a time to avoid token limits
178
- - For create-pdf: Design full HTML with CSS styling for best results
179
- - The HTML is rendered in a headless browser, so all CSS features are supported
180
- - Use inline styles or <style> blocks in the HTML for styling
181
- `.trim();
182
- }
183
-
184
- /**
185
- * Parse parameters from tool command content
186
- * @param {string} content - Raw tool command content
187
- * @returns {Object} Parsed parameters object
188
- */
189
- parseParameters(content) {
190
- try {
191
- // Try to extract structured content using TagParser
192
- const actionMatches = TagParser.extractContent(content, 'action');
193
- const filePathMatches = TagParser.extractContent(content, 'filePath');
194
- const startPageMatches = TagParser.extractContent(content, 'startPage');
195
- const endPageMatches = TagParser.extractContent(content, 'endPage');
196
-
197
- const action = actionMatches.length > 0 ? actionMatches[0].trim() : 'get-info';
198
- const filePath = filePathMatches.length > 0 ? filePathMatches[0].trim() : '';
199
- const startPage = startPageMatches.length > 0 ? parseInt(startPageMatches[0], 10) : 1;
200
- const endPage = endPageMatches.length > 0 ? parseInt(endPageMatches[0], 10) : startPage + 10;
201
-
202
- return {
203
- actions: [{
204
- action,
205
- filePath,
206
- startPage,
207
- endPage
208
- }]
209
- };
210
- } catch (error) {
211
- throw new Error(`Failed to parse PDF tool parameters: ${error.message}`);
212
- }
213
- }
214
-
215
- /**
216
- * Get supported actions
217
- * @returns {Array<string>}
218
- */
219
- getSupportedActions() {
220
- return ['get-info', 'read-pages', 'create-pdf'];
221
- }
222
-
223
- /**
224
- * Execute PDF tool action
225
- * @param {Object} params - Parsed parameters
226
- * @param {Object} context - Execution context
227
- * @returns {Promise<Object>} Execution result
228
- */
229
- async execute(params, context) {
230
- const { actions } = params;
231
-
232
- if (!actions || actions.length === 0) {
233
- return {
234
- success: false,
235
- error: 'No actions provided',
236
- output: 'Please specify an action (get-info, read-pages, or create-pdf)'
237
- };
238
- }
239
-
240
- const action = actions[0];
241
- const { projectDir } = context;
242
-
243
- // Handle create-pdf early (it doesn't need read-oriented validation)
244
- if (action.action === 'create-pdf') {
245
- try {
246
- return await this.createPdf(action, context);
247
- } catch (error) {
248
- this.logger?.error('PDF creation error', { error: error.message });
249
- return {
250
- success: false,
251
- error: error.message,
252
- output: `Failed to create PDF: ${error.message}`
253
- };
254
- }
255
- }
256
-
257
- // --- Read-oriented actions below: require filePath, file existence, pdf2json ---
258
-
259
- // Resolve file path
260
- let filePath = action.filePath;
261
- if (!filePath) {
262
- return {
263
- success: false,
264
- error: 'File path is required',
265
- output: 'Please provide a filePath parameter'
266
- };
267
- }
268
-
269
- // Make path absolute if relative
270
- if (!path.isAbsolute(filePath)) {
271
- filePath = path.resolve(projectDir || process.cwd(), filePath);
272
- }
273
-
274
- // Check file exists
275
- try {
276
- await fs.access(filePath);
277
- } catch {
278
- return {
279
- success: false,
280
- error: `File not found: ${filePath}`,
281
- output: `The PDF file does not exist: ${filePath}`
282
- };
283
- }
284
-
285
- // Check file extension
286
- if (!filePath.toLowerCase().endsWith('.pdf')) {
287
- return {
288
- success: false,
289
- error: 'Not a PDF file',
290
- output: `The file must have a .pdf extension: ${filePath}`
291
- };
292
- }
293
-
294
- // Load pdf2json module
295
- const loaded = await this.loadPdfParser();
296
- if (!loaded) {
297
- return {
298
- success: false,
299
- error: 'PDF parsing not available',
300
- output: `PDF parsing module could not be loaded: ${this.pdfParserError}`
301
- };
302
- }
303
-
304
- try {
305
- switch (action.action) {
306
- case 'get-info':
307
- return await this.getInfo(filePath);
308
- case 'read-pages':
309
- return await this.readPages(filePath, action.startPage, action.endPage);
310
- default:
311
- return {
312
- success: false,
313
- error: `Unknown action: ${action.action}`,
314
- output: `Supported actions: get-info, read-pages, create-pdf`
315
- };
316
- }
317
- } catch (error) {
318
- this.logger?.error('PDF tool error', { action: action.action, filePath, error: error.message });
319
- return {
320
- success: false,
321
- error: error.message,
322
- output: `Failed to process PDF: ${error.message}`
323
- };
324
- }
325
- }
326
-
327
- /**
328
- * Parse PDF file using pdf2json
329
- * @param {string} filePath - Path to PDF file
330
- * @returns {Promise<Object>} Parsed PDF data
331
- */
332
- async parsePdf(filePath) {
333
- return new Promise((resolve, reject) => {
334
- const pdfParser = new PDFParser();
335
-
336
- pdfParser.on('pdfParser_dataError', (errData) => {
337
- reject(new Error(errData.parserError || 'PDF parsing failed'));
338
- });
339
-
340
- pdfParser.on('pdfParser_dataReady', (pdfData) => {
341
- resolve(pdfData);
342
- });
343
-
344
- pdfParser.loadPDF(filePath);
345
- });
346
- }
347
-
348
- /**
349
- * Extract text from a PDF page
350
- * @param {Object} page - Page data from pdf2json
351
- * @returns {string} Extracted text
352
- */
353
- extractPageText(page) {
354
- if (!page || !page.Texts) return '';
355
-
356
- const texts = [];
357
- for (const textItem of page.Texts) {
358
- if (textItem.R) {
359
- for (const run of textItem.R) {
360
- if (run.T) {
361
- // Decode URI-encoded text
362
- texts.push(decodeURIComponent(run.T));
363
- }
364
- }
365
- }
366
- }
367
- return texts.join(' ');
368
- }
369
-
370
- /**
371
- * Get PDF info (page count, metadata)
372
- * @param {string} filePath - Path to PDF file
373
- * @returns {Promise<Object>} PDF info
374
- */
375
- async getInfo(filePath) {
376
- const pdfData = await this.parsePdf(filePath);
377
-
378
- const pageCount = pdfData.Pages ? pdfData.Pages.length : 0;
379
- const meta = pdfData.Meta || {};
380
-
381
- const info = {
382
- pageCount,
383
- title: meta.Title || null,
384
- author: meta.Author || null,
385
- subject: meta.Subject || null,
386
- creator: meta.Creator || null,
387
- producer: meta.Producer || null,
388
- creationDate: meta.CreationDate || null,
389
- modificationDate: meta.ModDate || null
390
- };
391
-
392
- // Build output message
393
- let output = `PDF Info for: ${path.basename(filePath)}\n`;
394
- output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`;
395
- output += `Pages: ${info.pageCount}\n`;
396
- if (info.title) output += `Title: ${info.title}\n`;
397
- if (info.author) output += `Author: ${info.author}\n`;
398
- if (info.subject) output += `Subject: ${info.subject}\n`;
399
- if (info.creator) output += `Creator: ${info.creator}\n`;
400
- if (info.creationDate) output += `Created: ${info.creationDate}\n`;
401
-
402
- return {
403
- success: true,
404
- action: 'get-info',
405
- filePath,
406
- info,
407
- output,
408
- message: `PDF has ${info.pageCount} pages`
409
- };
410
- }
411
-
412
- /**
413
- * Create a PDF from HTML content using Puppeteer
414
- * @param {Object} action - Action parameters
415
- * @param {Object} context - Execution context
416
- * @returns {Promise<Object>} Creation result
417
- */
418
- async createPdf(action, context) {
419
- const { projectDir } = context;
420
- const { outputPath, htmlContent, pageSize, orientation, margins, printBackground, displayHeaderFooter, headerTemplate, footerTemplate } = action;
421
-
422
- // Validate required parameters
423
- if (!outputPath) {
424
- return {
425
- success: false,
426
- error: 'Output path is required',
427
- output: 'Please provide an outputPath parameter for the PDF file'
428
- };
429
- }
430
-
431
- if (!htmlContent) {
432
- return {
433
- success: false,
434
- error: 'HTML content is required',
435
- output: 'Please provide htmlContent parameter with the HTML to render as PDF'
436
- };
437
- }
438
-
439
- // Resolve output path
440
- let resolvedPath = outputPath;
441
- if (!path.isAbsolute(resolvedPath)) {
442
- resolvedPath = path.resolve(projectDir || process.cwd(), resolvedPath);
443
- }
444
-
445
- // Security: prevent path traversal
446
- const baseDir = projectDir || process.cwd();
447
- const normalizedPath = path.normalize(resolvedPath);
448
- if (!normalizedPath.startsWith(path.normalize(baseDir))) {
449
- return {
450
- success: false,
451
- error: 'Path traversal detected',
452
- output: 'Output path must be within the project directory'
453
- };
454
- }
455
-
456
- // Ensure output directory exists
457
- const outputDir = path.dirname(resolvedPath);
458
- await fs.mkdir(outputDir, { recursive: true });
459
-
460
- // Ensure .pdf extension
461
- if (!resolvedPath.toLowerCase().endsWith('.pdf')) {
462
- resolvedPath += '.pdf';
463
- }
464
-
465
- // Load puppeteer
466
- const loaded = await this.loadPuppeteer();
467
- if (!loaded) {
468
- return {
469
- success: false,
470
- error: 'Puppeteer not available',
471
- output: `Puppeteer could not be loaded for PDF creation: ${this.puppeteerError}`
472
- };
473
- }
474
-
475
- // Map page size names to Puppeteer format
476
- const pageSizeMap = {
477
- 'A4': 'A4',
478
- 'A3': 'A3',
479
- 'A5': 'A5',
480
- 'Letter': 'Letter',
481
- 'Legal': 'Legal',
482
- 'Tabloid': 'Tabloid'
483
- };
484
-
485
- const format = pageSizeMap[pageSize] || 'A4';
486
- const landscape = orientation === 'landscape';
487
- const defaultMargin = '1cm';
488
- const pdfMargins = {
489
- top: margins?.top || defaultMargin,
490
- right: margins?.right || defaultMargin,
491
- bottom: margins?.bottom || defaultMargin,
492
- left: margins?.left || defaultMargin
493
- };
494
-
495
- let browser = null;
496
- try {
497
- browser = await puppeteerModule.launch({
498
- headless: true,
499
- args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage']
500
- });
501
-
502
- const page = await browser.newPage();
503
- await page.setContent(htmlContent, { waitUntil: 'networkidle0', timeout: 30000 });
504
-
505
- const pdfOptions = {
506
- path: resolvedPath,
507
- format,
508
- landscape,
509
- margin: pdfMargins,
510
- printBackground: printBackground !== false,
511
- displayHeaderFooter: displayHeaderFooter || false
512
- };
513
-
514
- if (displayHeaderFooter) {
515
- if (headerTemplate) pdfOptions.headerTemplate = headerTemplate;
516
- if (footerTemplate) pdfOptions.footerTemplate = footerTemplate;
517
- }
518
-
519
- await page.pdf(pdfOptions);
520
- await browser.close();
521
- browser = null;
522
-
523
- // Get file stats
524
- const stats = await fs.stat(resolvedPath);
525
-
526
- const output = `PDF created successfully!\n` +
527
- `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` +
528
- `File: ${resolvedPath}\n` +
529
- `Size: ${(stats.size / 1024).toFixed(1)} KB\n` +
530
- `Page size: ${format}\n` +
531
- `Orientation: ${landscape ? 'landscape' : 'portrait'}\n` +
532
- `Margins: ${pdfMargins.top} / ${pdfMargins.right} / ${pdfMargins.bottom} / ${pdfMargins.left}`;
533
-
534
- return {
535
- success: true,
536
- action: 'create-pdf',
537
- outputPath: resolvedPath,
538
- fileSize: stats.size,
539
- format,
540
- landscape,
541
- output,
542
- message: `PDF created: ${resolvedPath} (${(stats.size / 1024).toFixed(1)} KB)`
543
- };
544
-
545
- } catch (error) {
546
- throw error;
547
- } finally {
548
- if (browser) {
549
- try { await browser.close(); } catch { /* ignore close errors */ }
550
- }
551
- }
552
- }
553
-
554
- /**
555
- * Read text content from specific pages
556
- * @param {string} filePath - Path to PDF file
557
- * @param {number} startPage - Start page (1-indexed, inclusive)
558
- * @param {number} endPage - End page (exclusive)
559
- * @returns {Promise<Object>} Page content
560
- */
561
- async readPages(filePath, startPage = 1, endPage = null) {
562
- const pdfData = await this.parsePdf(filePath);
563
-
564
- const totalPages = pdfData.Pages ? pdfData.Pages.length : 0;
565
-
566
- // Validate page range
567
- if (startPage < 1) startPage = 1;
568
- if (endPage === null) endPage = Math.min(startPage + 10, totalPages + 1);
569
- if (endPage > totalPages + 1) endPage = totalPages + 1;
570
- if (startPage > totalPages) {
571
- return {
572
- success: false,
573
- error: `Start page ${startPage} exceeds total pages ${totalPages}`,
574
- output: `The PDF only has ${totalPages} pages. Cannot start from page ${startPage}.`
575
- };
576
- }
577
-
578
- // Warn if requesting more than 10 pages
579
- const pageCount = endPage - startPage;
580
- const warnings = [];
581
- if (pageCount > 10) {
582
- warnings.push(`Reading ${pageCount} pages. Consider reading max 10 pages at a time for better performance.`);
583
- }
584
-
585
- // Extract requested pages (convert to 0-indexed)
586
- const requestedPages = [];
587
- for (let i = startPage - 1; i < Math.min(endPage - 1, totalPages); i++) {
588
- const page = pdfData.Pages[i];
589
- const content = this.extractPageText(page);
590
- requestedPages.push({
591
- pageNumber: i + 1,
592
- content: content.trim() || ''
593
- });
594
- }
595
-
596
- // Build output
597
- let output = `PDF Content: ${path.basename(filePath)}\n`;
598
- output += `Pages ${startPage} to ${endPage - 1} of ${totalPages}\n`;
599
- output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n`;
600
-
601
- for (const page of requestedPages) {
602
- output += `── Page ${page.pageNumber} ──\n`;
603
- output += page.content || '(No text content on this page)';
604
- output += '\n\n';
605
- }
606
-
607
- if (warnings.length > 0) {
608
- output += `\n⚠️ Warnings:\n${warnings.map(w => `- ${w}`).join('\n')}`;
609
- }
610
-
611
- return {
612
- success: true,
613
- action: 'read-pages',
614
- filePath,
615
- totalPages,
616
- startPage,
617
- endPage,
618
- pagesRead: requestedPages.length,
619
- pages: requestedPages,
620
- warnings,
621
- output,
622
- message: `Read ${requestedPages.length} pages (${startPage}-${endPage - 1}) of ${totalPages} total`
623
- };
624
- }
625
- }
626
-
627
- export default PdfTool;
1
+ /**
2
+ * PDF Tool - Read, extract, and create PDF files
3
+ *
4
+ * Purpose:
5
+ * - Get PDF metadata (page count, info)
6
+ * - Extract text content from specific page ranges
7
+ * - Create PDF files from HTML content using Puppeteer
8
+ * - Provide structured access to PDF documents
9
+ */
10
+
11
+ import { BaseTool } from './baseTool.js';
12
+ import TagParser from '../utilities/tagParser.js';
13
+ import fs from 'fs/promises';
14
+ import path from 'path';
15
+
16
+ // Dynamic import for pdf2json
17
+ let PDFParser = null;
18
+
19
+ // Dynamic import for puppeteer (used for PDF creation)
20
+ let puppeteerModule = null;
21
+
22
+ class PdfTool extends BaseTool {
23
+ constructor(config = {}, logger = null) {
24
+ super(config, logger);
25
+ this.id = 'pdf';
26
+ this.name = 'PDF Tool';
27
+ this.description = 'Read, extract, and create PDF files';
28
+ this.version = '2.0.0';
29
+ this.capabilities = ['pdf-read', 'pdf-info', 'pdf-create'];
30
+ this.requiresProject = false;
31
+ this.isAsync = false;
32
+ this.pdfParserLoaded = false;
33
+ this.pdfParserError = null;
34
+ this.puppeteerLoaded = false;
35
+ this.puppeteerError = null;
36
+ }
37
+
38
+ /**
39
+ * Lazily load pdf2json module
40
+ * @returns {Promise<boolean>} Whether loading succeeded
41
+ */
42
+ async loadPdfParser() {
43
+ if (this.pdfParserLoaded) return true;
44
+ if (this.pdfParserError) return false;
45
+
46
+ try {
47
+ const module = await import('pdf2json');
48
+ PDFParser = module.default;
49
+ this.pdfParserLoaded = true;
50
+ return true;
51
+ } catch (error) {
52
+ this.pdfParserError = error.message;
53
+ this.logger?.error('Failed to load pdf2json', { error: error.message });
54
+ return false;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Lazily load puppeteer module for PDF creation
60
+ * @returns {Promise<boolean>} Whether loading succeeded
61
+ */
62
+ async loadPuppeteer() {
63
+ if (this.puppeteerLoaded) return true;
64
+ if (this.puppeteerError) return false;
65
+
66
+ try {
67
+ const module = await import('puppeteer');
68
+ puppeteerModule = module.default;
69
+ this.puppeteerLoaded = true;
70
+ return true;
71
+ } catch (error) {
72
+ this.puppeteerError = error.message;
73
+ this.logger?.error('Failed to load puppeteer', { error: error.message });
74
+ return false;
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Get tool description for LLM consumption
80
+ * @returns {string} Tool description
81
+ */
82
+ getDescription() {
83
+ return `
84
+ PDF Tool: Read, extract, and create PDF files.
85
+
86
+ USAGE:
87
+ \`\`\`json
88
+ {
89
+ "toolId": "pdf",
90
+ "actions": [{
91
+ "action": "get-info",
92
+ "filePath": "/path/to/document.pdf"
93
+ }]
94
+ }
95
+ \`\`\`
96
+
97
+ ACTIONS:
98
+
99
+ 1. **get-info** - Get PDF metadata (page count, title, author, etc.)
100
+ - filePath: Path to PDF file (required)
101
+
102
+ 2. **read-pages** - Extract text content from specific pages
103
+ - filePath: Path to PDF file (required)
104
+ - startPage: First page to read, 1-indexed, inclusive (default: 1)
105
+ - endPage: Last page to read, exclusive (default: startPage + 10)
106
+ - IMPORTANT: Read max 10 pages at once for optimal performance
107
+
108
+ 3. **create-pdf** - Create a PDF from HTML content
109
+ - outputPath: Output file path (required, relative to project dir or absolute)
110
+ - htmlContent: Full HTML string to render (required)
111
+ - pageSize: Page size - A4 (default), Letter, Legal, Tabloid, A3, A5
112
+ - orientation: portrait (default) or landscape
113
+ - margins: Object with top, right, bottom, left in CSS units (default: 1cm each)
114
+ - printBackground: Whether to print background colors/images (default: true)
115
+ - displayHeaderFooter: Show header/footer (default: false)
116
+ - headerTemplate: HTML template for header
117
+ - footerTemplate: HTML template for footer
118
+
119
+ EXAMPLES:
120
+
121
+ 1. Get PDF info:
122
+ \`\`\`json
123
+ {
124
+ "toolId": "pdf",
125
+ "actions": [{
126
+ "action": "get-info",
127
+ "filePath": "documents/report.pdf"
128
+ }]
129
+ }
130
+ \`\`\`
131
+
132
+ 2. Read pages 1-10:
133
+ \`\`\`json
134
+ {
135
+ "toolId": "pdf",
136
+ "actions": [{
137
+ "action": "read-pages",
138
+ "filePath": "documents/report.pdf",
139
+ "startPage": 1,
140
+ "endPage": 11
141
+ }]
142
+ }
143
+ \`\`\`
144
+
145
+ 3. Create a PDF from HTML:
146
+ \`\`\`json
147
+ {
148
+ "toolId": "pdf",
149
+ "actions": [{
150
+ "action": "create-pdf",
151
+ "outputPath": "output/report.pdf",
152
+ "htmlContent": "<html><head><style>body{font-family:Arial;margin:2cm}h1{color:#333}</style></head><body><h1>Report</h1><p>Content here...</p></body></html>",
153
+ "pageSize": "A4",
154
+ "orientation": "portrait"
155
+ }]
156
+ }
157
+ \`\`\`
158
+
159
+ 4. Create a landscape PDF with custom margins:
160
+ \`\`\`json
161
+ {
162
+ "toolId": "pdf",
163
+ "actions": [{
164
+ "action": "create-pdf",
165
+ "outputPath": "output/wide-report.pdf",
166
+ "htmlContent": "<html><body><h1>Wide Report</h1><table>...</table></body></html>",
167
+ "pageSize": "Letter",
168
+ "orientation": "landscape",
169
+ "margins": { "top": "2cm", "right": "1.5cm", "bottom": "2cm", "left": "1.5cm" }
170
+ }]
171
+ }
172
+ \`\`\`
173
+
174
+ NOTES:
175
+ - Page numbers are 1-indexed (first page is 1)
176
+ - endPage is exclusive (like Python range)
177
+ - Recommend reading max 10 pages at a time to avoid token limits
178
+ - For create-pdf: Design full HTML with CSS styling for best results
179
+ - The HTML is rendered in a headless browser, so all CSS features are supported
180
+ - Use inline styles or <style> blocks in the HTML for styling
181
+ `.trim();
182
+ }
183
+
184
+ /**
185
+ * Parse parameters from tool command content
186
+ * @param {string} content - Raw tool command content
187
+ * @returns {Object} Parsed parameters object
188
+ */
189
+ parseParameters(content) {
190
+ try {
191
+ // Try to extract structured content using TagParser
192
+ const actionMatches = TagParser.extractContent(content, 'action');
193
+ const filePathMatches = TagParser.extractContent(content, 'filePath');
194
+ const startPageMatches = TagParser.extractContent(content, 'startPage');
195
+ const endPageMatches = TagParser.extractContent(content, 'endPage');
196
+
197
+ const action = actionMatches.length > 0 ? actionMatches[0].trim() : 'get-info';
198
+ const filePath = filePathMatches.length > 0 ? filePathMatches[0].trim() : '';
199
+ const startPage = startPageMatches.length > 0 ? parseInt(startPageMatches[0], 10) : 1;
200
+ const endPage = endPageMatches.length > 0 ? parseInt(endPageMatches[0], 10) : startPage + 10;
201
+
202
+ return {
203
+ actions: [{
204
+ action,
205
+ filePath,
206
+ startPage,
207
+ endPage
208
+ }]
209
+ };
210
+ } catch (error) {
211
+ throw new Error(`Failed to parse PDF tool parameters: ${error.message}`, { cause: error });
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Get supported actions
217
+ * @returns {Array<string>}
218
+ */
219
+ getSupportedActions() {
220
+ return ['get-info', 'read-pages', 'create-pdf'];
221
+ }
222
+
223
+ /**
224
+ * Execute PDF tool action
225
+ * @param {Object} params - Parsed parameters
226
+ * @param {Object} context - Execution context
227
+ * @returns {Promise<Object>} Execution result
228
+ */
229
+ async execute(params, context) {
230
+ const { actions } = params;
231
+
232
+ if (!actions || actions.length === 0) {
233
+ return {
234
+ success: false,
235
+ error: 'No actions provided',
236
+ output: 'Please specify an action (get-info, read-pages, or create-pdf)'
237
+ };
238
+ }
239
+
240
+ const action = actions[0];
241
+ const { projectDir } = context;
242
+
243
+ // Handle create-pdf early (it doesn't need read-oriented validation)
244
+ if (action.action === 'create-pdf') {
245
+ try {
246
+ return await this.createPdf(action, context);
247
+ } catch (error) {
248
+ this.logger?.error('PDF creation error', { error: error.message });
249
+ return {
250
+ success: false,
251
+ error: error.message,
252
+ output: `Failed to create PDF: ${error.message}`
253
+ };
254
+ }
255
+ }
256
+
257
+ // --- Read-oriented actions below: require filePath, file existence, pdf2json ---
258
+
259
+ // Resolve file path
260
+ let filePath = action.filePath;
261
+ if (!filePath) {
262
+ return {
263
+ success: false,
264
+ error: 'File path is required',
265
+ output: 'Please provide a filePath parameter'
266
+ };
267
+ }
268
+
269
+ // Make path absolute if relative
270
+ if (!path.isAbsolute(filePath)) {
271
+ filePath = path.resolve(projectDir || process.cwd(), filePath);
272
+ }
273
+
274
+ // Check file exists
275
+ try {
276
+ await fs.access(filePath);
277
+ } catch {
278
+ return {
279
+ success: false,
280
+ error: `File not found: ${filePath}`,
281
+ output: `The PDF file does not exist: ${filePath}`
282
+ };
283
+ }
284
+
285
+ // Check file extension
286
+ if (!filePath.toLowerCase().endsWith('.pdf')) {
287
+ return {
288
+ success: false,
289
+ error: 'Not a PDF file',
290
+ output: `The file must have a .pdf extension: ${filePath}`
291
+ };
292
+ }
293
+
294
+ // Load pdf2json module
295
+ const loaded = await this.loadPdfParser();
296
+ if (!loaded) {
297
+ return {
298
+ success: false,
299
+ error: 'PDF parsing not available',
300
+ output: `PDF parsing module could not be loaded: ${this.pdfParserError}`
301
+ };
302
+ }
303
+
304
+ try {
305
+ switch (action.action) {
306
+ case 'get-info':
307
+ return await this.getInfo(filePath);
308
+ case 'read-pages':
309
+ return await this.readPages(filePath, action.startPage, action.endPage);
310
+ default:
311
+ return {
312
+ success: false,
313
+ error: `Unknown action: ${action.action}`,
314
+ output: `Supported actions: get-info, read-pages, create-pdf`
315
+ };
316
+ }
317
+ } catch (error) {
318
+ this.logger?.error('PDF tool error', { action: action.action, filePath, error: error.message });
319
+ return {
320
+ success: false,
321
+ error: error.message,
322
+ output: `Failed to process PDF: ${error.message}`
323
+ };
324
+ }
325
+ }
326
+
327
+ /**
328
+ * Parse PDF file using pdf2json
329
+ * @param {string} filePath - Path to PDF file
330
+ * @returns {Promise<Object>} Parsed PDF data
331
+ */
332
+ async parsePdf(filePath) {
333
+ return new Promise((resolve, reject) => {
334
+ const pdfParser = new PDFParser();
335
+
336
+ pdfParser.on('pdfParser_dataError', (errData) => {
337
+ reject(new Error(errData.parserError || 'PDF parsing failed'));
338
+ });
339
+
340
+ pdfParser.on('pdfParser_dataReady', (pdfData) => {
341
+ resolve(pdfData);
342
+ });
343
+
344
+ pdfParser.loadPDF(filePath);
345
+ });
346
+ }
347
+
348
+ /**
349
+ * Extract text from a PDF page
350
+ * @param {Object} page - Page data from pdf2json
351
+ * @returns {string} Extracted text
352
+ */
353
+ extractPageText(page) {
354
+ if (!page || !page.Texts) return '';
355
+
356
+ const texts = [];
357
+ for (const textItem of page.Texts) {
358
+ if (textItem.R) {
359
+ for (const run of textItem.R) {
360
+ if (run.T) {
361
+ // Decode URI-encoded text
362
+ texts.push(decodeURIComponent(run.T));
363
+ }
364
+ }
365
+ }
366
+ }
367
+ return texts.join(' ');
368
+ }
369
+
370
+ /**
371
+ * Get PDF info (page count, metadata)
372
+ * @param {string} filePath - Path to PDF file
373
+ * @returns {Promise<Object>} PDF info
374
+ */
375
+ async getInfo(filePath) {
376
+ const pdfData = await this.parsePdf(filePath);
377
+
378
+ const pageCount = pdfData.Pages ? pdfData.Pages.length : 0;
379
+ const meta = pdfData.Meta || {};
380
+
381
+ const info = {
382
+ pageCount,
383
+ title: meta.Title || null,
384
+ author: meta.Author || null,
385
+ subject: meta.Subject || null,
386
+ creator: meta.Creator || null,
387
+ producer: meta.Producer || null,
388
+ creationDate: meta.CreationDate || null,
389
+ modificationDate: meta.ModDate || null
390
+ };
391
+
392
+ // Build output message
393
+ let output = `PDF Info for: ${path.basename(filePath)}\n`;
394
+ output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`;
395
+ output += `Pages: ${info.pageCount}\n`;
396
+ if (info.title) output += `Title: ${info.title}\n`;
397
+ if (info.author) output += `Author: ${info.author}\n`;
398
+ if (info.subject) output += `Subject: ${info.subject}\n`;
399
+ if (info.creator) output += `Creator: ${info.creator}\n`;
400
+ if (info.creationDate) output += `Created: ${info.creationDate}\n`;
401
+
402
+ return {
403
+ success: true,
404
+ action: 'get-info',
405
+ filePath,
406
+ info,
407
+ output,
408
+ message: `PDF has ${info.pageCount} pages`
409
+ };
410
+ }
411
+
412
+ /**
413
+ * Create a PDF from HTML content using Puppeteer
414
+ * @param {Object} action - Action parameters
415
+ * @param {Object} context - Execution context
416
+ * @returns {Promise<Object>} Creation result
417
+ */
418
+ async createPdf(action, context) {
419
+ const { projectDir } = context;
420
+ const { outputPath, htmlContent, pageSize, orientation, margins, printBackground, displayHeaderFooter, headerTemplate, footerTemplate } = action;
421
+
422
+ // Validate required parameters
423
+ if (!outputPath) {
424
+ return {
425
+ success: false,
426
+ error: 'Output path is required',
427
+ output: 'Please provide an outputPath parameter for the PDF file'
428
+ };
429
+ }
430
+
431
+ if (!htmlContent) {
432
+ return {
433
+ success: false,
434
+ error: 'HTML content is required',
435
+ output: 'Please provide htmlContent parameter with the HTML to render as PDF'
436
+ };
437
+ }
438
+
439
+ // Resolve output path
440
+ let resolvedPath = outputPath;
441
+ if (!path.isAbsolute(resolvedPath)) {
442
+ resolvedPath = path.resolve(projectDir || process.cwd(), resolvedPath);
443
+ }
444
+
445
+ // Security: prevent path traversal
446
+ const baseDir = projectDir || process.cwd();
447
+ const normalizedPath = path.normalize(resolvedPath);
448
+ if (!normalizedPath.startsWith(path.normalize(baseDir))) {
449
+ return {
450
+ success: false,
451
+ error: 'Path traversal detected',
452
+ output: 'Output path must be within the project directory'
453
+ };
454
+ }
455
+
456
+ // Ensure output directory exists
457
+ const outputDir = path.dirname(resolvedPath);
458
+ await fs.mkdir(outputDir, { recursive: true });
459
+
460
+ // Ensure .pdf extension
461
+ if (!resolvedPath.toLowerCase().endsWith('.pdf')) {
462
+ resolvedPath += '.pdf';
463
+ }
464
+
465
+ // Load puppeteer
466
+ const loaded = await this.loadPuppeteer();
467
+ if (!loaded) {
468
+ return {
469
+ success: false,
470
+ error: 'Puppeteer not available',
471
+ output: `Puppeteer could not be loaded for PDF creation: ${this.puppeteerError}`
472
+ };
473
+ }
474
+
475
+ // Map page size names to Puppeteer format
476
+ const pageSizeMap = {
477
+ 'A4': 'A4',
478
+ 'A3': 'A3',
479
+ 'A5': 'A5',
480
+ 'Letter': 'Letter',
481
+ 'Legal': 'Legal',
482
+ 'Tabloid': 'Tabloid'
483
+ };
484
+
485
+ const format = pageSizeMap[pageSize] || 'A4';
486
+ const landscape = orientation === 'landscape';
487
+ const defaultMargin = '1cm';
488
+ const pdfMargins = {
489
+ top: margins?.top || defaultMargin,
490
+ right: margins?.right || defaultMargin,
491
+ bottom: margins?.bottom || defaultMargin,
492
+ left: margins?.left || defaultMargin
493
+ };
494
+
495
+ let browser = null;
496
+ try {
497
+ browser = await puppeteerModule.launch({
498
+ headless: true,
499
+ args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage']
500
+ });
501
+
502
+ const page = await browser.newPage();
503
+ await page.setContent(htmlContent, { waitUntil: 'networkidle0', timeout: 30000 });
504
+
505
+ const pdfOptions = {
506
+ path: resolvedPath,
507
+ format,
508
+ landscape,
509
+ margin: pdfMargins,
510
+ printBackground: printBackground !== false,
511
+ displayHeaderFooter: displayHeaderFooter || false
512
+ };
513
+
514
+ if (displayHeaderFooter) {
515
+ if (headerTemplate) pdfOptions.headerTemplate = headerTemplate;
516
+ if (footerTemplate) pdfOptions.footerTemplate = footerTemplate;
517
+ }
518
+
519
+ await page.pdf(pdfOptions);
520
+ await browser.close();
521
+ browser = null;
522
+
523
+ // Get file stats
524
+ const stats = await fs.stat(resolvedPath);
525
+
526
+ const output = `PDF created successfully!\n` +
527
+ `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` +
528
+ `File: ${resolvedPath}\n` +
529
+ `Size: ${(stats.size / 1024).toFixed(1)} KB\n` +
530
+ `Page size: ${format}\n` +
531
+ `Orientation: ${landscape ? 'landscape' : 'portrait'}\n` +
532
+ `Margins: ${pdfMargins.top} / ${pdfMargins.right} / ${pdfMargins.bottom} / ${pdfMargins.left}`;
533
+
534
+ return {
535
+ success: true,
536
+ action: 'create-pdf',
537
+ outputPath: resolvedPath,
538
+ fileSize: stats.size,
539
+ format,
540
+ landscape,
541
+ output,
542
+ message: `PDF created: ${resolvedPath} (${(stats.size / 1024).toFixed(1)} KB)`
543
+ };
544
+
545
+ } finally {
546
+ if (browser) {
547
+ try { await browser.close(); } catch { /* ignore close errors */ }
548
+ }
549
+ }
550
+ }
551
+
552
+ /**
553
+ * Read text content from specific pages
554
+ * @param {string} filePath - Path to PDF file
555
+ * @param {number} startPage - Start page (1-indexed, inclusive)
556
+ * @param {number} endPage - End page (exclusive)
557
+ * @returns {Promise<Object>} Page content
558
+ */
559
+ async readPages(filePath, startPage = 1, endPage = null) {
560
+ const pdfData = await this.parsePdf(filePath);
561
+
562
+ const totalPages = pdfData.Pages ? pdfData.Pages.length : 0;
563
+
564
+ // Validate page range
565
+ if (startPage < 1) startPage = 1;
566
+ if (endPage === null) endPage = Math.min(startPage + 10, totalPages + 1);
567
+ if (endPage > totalPages + 1) endPage = totalPages + 1;
568
+ if (startPage > totalPages) {
569
+ return {
570
+ success: false,
571
+ error: `Start page ${startPage} exceeds total pages ${totalPages}`,
572
+ output: `The PDF only has ${totalPages} pages. Cannot start from page ${startPage}.`
573
+ };
574
+ }
575
+
576
+ // Warn if requesting more than 10 pages
577
+ const pageCount = endPage - startPage;
578
+ const warnings = [];
579
+ if (pageCount > 10) {
580
+ warnings.push(`Reading ${pageCount} pages. Consider reading max 10 pages at a time for better performance.`);
581
+ }
582
+
583
+ // Extract requested pages (convert to 0-indexed)
584
+ const requestedPages = [];
585
+ for (let i = startPage - 1; i < Math.min(endPage - 1, totalPages); i++) {
586
+ const page = pdfData.Pages[i];
587
+ const content = this.extractPageText(page);
588
+ requestedPages.push({
589
+ pageNumber: i + 1,
590
+ content: content.trim() || ''
591
+ });
592
+ }
593
+
594
+ // Build output
595
+ let output = `PDF Content: ${path.basename(filePath)}\n`;
596
+ output += `Pages ${startPage} to ${endPage - 1} of ${totalPages}\n`;
597
+ output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n`;
598
+
599
+ for (const page of requestedPages) {
600
+ output += `── Page ${page.pageNumber} ──\n`;
601
+ output += page.content || '(No text content on this page)';
602
+ output += '\n\n';
603
+ }
604
+
605
+ if (warnings.length > 0) {
606
+ output += `\n⚠️ Warnings:\n${warnings.map(w => `- ${w}`).join('\n')}`;
607
+ }
608
+
609
+ return {
610
+ success: true,
611
+ action: 'read-pages',
612
+ filePath,
613
+ totalPages,
614
+ startPage,
615
+ endPage,
616
+ pagesRead: requestedPages.length,
617
+ pages: requestedPages,
618
+ warnings,
619
+ output,
620
+ message: `Read ${requestedPages.length} pages (${startPage}-${endPage - 1}) of ${totalPages} total`
621
+ };
622
+ }
623
+ }
624
+
625
+ export default PdfTool;