@xagent-ai/cli 1.2.2 → 1.3.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 (568) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  3. package/.github/workflows/ci.yml +72 -0
  4. package/.github/workflows/release.yml +109 -0
  5. package/.gitmodules +3 -3
  6. package/README.md +326 -280
  7. package/README_CN.md +325 -279
  8. package/dist/ai-client/factory.d.ts +52 -0
  9. package/dist/ai-client/factory.d.ts.map +1 -0
  10. package/dist/ai-client/factory.js +132 -0
  11. package/dist/ai-client/factory.js.map +1 -0
  12. package/dist/ai-client/index.d.ts +20 -0
  13. package/dist/ai-client/index.d.ts.map +1 -0
  14. package/dist/ai-client/index.js +49 -0
  15. package/dist/ai-client/index.js.map +1 -0
  16. package/dist/ai-client/providers/anthropic.d.ts +57 -0
  17. package/dist/ai-client/providers/anthropic.d.ts.map +1 -0
  18. package/dist/ai-client/providers/anthropic.js +400 -0
  19. package/dist/ai-client/providers/anthropic.js.map +1 -0
  20. package/dist/ai-client/providers/openai.d.ts +57 -0
  21. package/dist/ai-client/providers/openai.d.ts.map +1 -0
  22. package/dist/ai-client/providers/openai.js +286 -0
  23. package/dist/ai-client/providers/openai.js.map +1 -0
  24. package/dist/ai-client/providers/remote.d.ts +111 -0
  25. package/dist/ai-client/providers/remote.d.ts.map +1 -0
  26. package/dist/ai-client/providers/remote.js +351 -0
  27. package/dist/ai-client/providers/remote.js.map +1 -0
  28. package/dist/ai-client/registry.d.ts +51 -0
  29. package/dist/ai-client/registry.d.ts.map +1 -0
  30. package/dist/ai-client/registry.js +81 -0
  31. package/dist/ai-client/registry.js.map +1 -0
  32. package/dist/ai-client/types.d.ts +260 -0
  33. package/dist/ai-client/types.d.ts.map +1 -0
  34. package/dist/ai-client/types.js +73 -0
  35. package/dist/ai-client/types.js.map +1 -0
  36. package/dist/ai-client-factory.d.ts +62 -0
  37. package/dist/ai-client-factory.d.ts.map +1 -0
  38. package/dist/ai-client-factory.js +157 -0
  39. package/dist/ai-client-factory.js.map +1 -0
  40. package/dist/auth.d.ts +23 -1
  41. package/dist/auth.d.ts.map +1 -1
  42. package/dist/auth.js +160 -168
  43. package/dist/auth.js.map +1 -1
  44. package/dist/cancellation.d.ts +5 -4
  45. package/dist/cancellation.d.ts.map +1 -1
  46. package/dist/cancellation.js +55 -32
  47. package/dist/cancellation.js.map +1 -1
  48. package/dist/checkpoint.d.ts +1 -1
  49. package/dist/checkpoint.d.ts.map +1 -1
  50. package/dist/checkpoint.js +2 -2
  51. package/dist/checkpoint.js.map +1 -1
  52. package/dist/cli.js +626 -13
  53. package/dist/cli.js.map +1 -1
  54. package/dist/config.d.ts +10 -4
  55. package/dist/config.d.ts.map +1 -1
  56. package/dist/config.js +62 -25
  57. package/dist/config.js.map +1 -1
  58. package/dist/context-compressor.d.ts +81 -16
  59. package/dist/context-compressor.d.ts.map +1 -1
  60. package/dist/context-compressor.js +712 -153
  61. package/dist/context-compressor.js.map +1 -1
  62. package/dist/gui-subagent/action-parser/actionParser.d.ts.map +1 -1
  63. package/dist/gui-subagent/action-parser/actionParser.js +4 -2
  64. package/dist/gui-subagent/action-parser/actionParser.js.map +1 -1
  65. package/dist/gui-subagent/agent/gui-agent.d.ts +29 -2
  66. package/dist/gui-subagent/agent/gui-agent.d.ts.map +1 -1
  67. package/dist/gui-subagent/agent/gui-agent.js +87 -45
  68. package/dist/gui-subagent/agent/gui-agent.js.map +1 -1
  69. package/dist/gui-subagent/index.d.ts +16 -1
  70. package/dist/gui-subagent/index.d.ts.map +1 -1
  71. package/dist/gui-subagent/index.js +4 -0
  72. package/dist/gui-subagent/index.js.map +1 -1
  73. package/dist/gui-subagent/operator/base-operator.d.ts.map +1 -1
  74. package/dist/gui-subagent/operator/base-operator.js +0 -1
  75. package/dist/gui-subagent/operator/base-operator.js.map +1 -1
  76. package/dist/gui-subagent/operator/computer-operator.d.ts.map +1 -1
  77. package/dist/gui-subagent/operator/computer-operator.js +29 -8
  78. package/dist/gui-subagent/operator/computer-operator.js.map +1 -1
  79. package/dist/gui-subagent/types/actions.d.ts +1 -1
  80. package/dist/gui-subagent/types/actions.d.ts.map +1 -1
  81. package/dist/gui-subagent/types/actions.js +0 -1
  82. package/dist/gui-subagent/types/actions.js.map +1 -1
  83. package/dist/gui-subagent/types/operator.d.ts +1 -1
  84. package/dist/gui-subagent/types/operator.d.ts.map +1 -1
  85. package/dist/index.d.ts +1 -2
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +1 -2
  88. package/dist/index.js.map +1 -1
  89. package/dist/input-processor.d.ts.map +1 -1
  90. package/dist/input-processor.js +6 -3
  91. package/dist/input-processor.js.map +1 -1
  92. package/dist/mcp.d.ts +5 -0
  93. package/dist/mcp.d.ts.map +1 -1
  94. package/dist/mcp.js +81 -35
  95. package/dist/mcp.js.map +1 -1
  96. package/dist/ripgrep.d.ts +29 -0
  97. package/dist/ripgrep.d.ts.map +1 -0
  98. package/dist/ripgrep.js +292 -0
  99. package/dist/ripgrep.js.map +1 -0
  100. package/dist/session.d.ts +23 -7
  101. package/dist/session.d.ts.map +1 -1
  102. package/dist/session.js +624 -243
  103. package/dist/session.js.map +1 -1
  104. package/dist/shell.d.ts +33 -0
  105. package/dist/shell.d.ts.map +1 -0
  106. package/dist/shell.js +125 -0
  107. package/dist/shell.js.map +1 -0
  108. package/dist/skill-installer.d.ts +38 -0
  109. package/dist/skill-installer.d.ts.map +1 -0
  110. package/dist/skill-installer.js +447 -0
  111. package/dist/skill-installer.js.map +1 -0
  112. package/dist/skill-invoker.d.ts +7 -1
  113. package/dist/skill-invoker.d.ts.map +1 -1
  114. package/dist/skill-invoker.js +34 -13
  115. package/dist/skill-invoker.js.map +1 -1
  116. package/dist/skill-loader.d.ts +8 -3
  117. package/dist/skill-loader.d.ts.map +1 -1
  118. package/dist/skill-loader.js +46 -44
  119. package/dist/skill-loader.js.map +1 -1
  120. package/dist/skill-manager.d.ts +85 -0
  121. package/dist/skill-manager.d.ts.map +1 -0
  122. package/dist/skill-manager.js +340 -0
  123. package/dist/skill-manager.js.map +1 -0
  124. package/dist/slash-commands.d.ts +38 -1
  125. package/dist/slash-commands.d.ts.map +1 -1
  126. package/dist/slash-commands.js +912 -296
  127. package/dist/slash-commands.js.map +1 -1
  128. package/dist/smart-approval.d.ts.map +1 -1
  129. package/dist/smart-approval.js +67 -55
  130. package/dist/smart-approval.js.map +1 -1
  131. package/dist/system-prompt-generator.d.ts +6 -0
  132. package/dist/system-prompt-generator.d.ts.map +1 -1
  133. package/dist/system-prompt-generator.js +84 -34
  134. package/dist/system-prompt-generator.js.map +1 -1
  135. package/dist/terminal.d.ts +28 -0
  136. package/dist/terminal.d.ts.map +1 -0
  137. package/dist/terminal.js +82 -0
  138. package/dist/terminal.js.map +1 -0
  139. package/dist/tools.d.ts +23 -7
  140. package/dist/tools.d.ts.map +1 -1
  141. package/dist/tools.js +797 -437
  142. package/dist/tools.js.map +1 -1
  143. package/dist/truncate.d.ts +55 -0
  144. package/dist/truncate.d.ts.map +1 -0
  145. package/dist/truncate.js +130 -0
  146. package/dist/truncate.js.map +1 -0
  147. package/dist/types.d.ts +27 -9
  148. package/dist/types.d.ts.map +1 -1
  149. package/dist/update.d.ts.map +1 -1
  150. package/dist/update.js +17 -28
  151. package/dist/update.js.map +1 -1
  152. package/dist/workflow.d.ts +5 -1
  153. package/dist/workflow.d.ts.map +1 -1
  154. package/dist/workflow.js +60 -47
  155. package/dist/workflow.js.map +1 -1
  156. package/docs/architecture/mcp-integration-guide.md +304 -194
  157. package/docs/architecture/overview.md +169 -169
  158. package/docs/architecture/tool-system-design.md +134 -134
  159. package/docs/cli/commands.md +349 -238
  160. package/docs/smart-mode.md +281 -281
  161. package/docs/third-party-models.md +439 -439
  162. package/find-skills/SKILL.md +133 -0
  163. package/package.json +89 -90
  164. package/scripts/install-ripgrep.js +241 -0
  165. package/src/ai-client/factory.ts +151 -0
  166. package/src/ai-client/index.ts +61 -0
  167. package/src/ai-client/providers/anthropic.ts +466 -0
  168. package/src/ai-client/providers/openai.ts +342 -0
  169. package/src/ai-client/providers/remote.ts +436 -0
  170. package/src/ai-client/registry.ts +97 -0
  171. package/src/ai-client/types.ts +345 -0
  172. package/src/ai-client-factory.ts +204 -0
  173. package/src/auth.ts +663 -614
  174. package/src/cancellation.ts +205 -176
  175. package/src/checkpoint.ts +219 -219
  176. package/src/cli.ts +1406 -743
  177. package/src/config.ts +341 -297
  178. package/src/context-compressor.ts +982 -290
  179. package/src/conversation.ts +288 -288
  180. package/src/gui-subagent/action-parser/actionParser.ts +318 -315
  181. package/src/gui-subagent/action-parser/constants.ts +14 -14
  182. package/src/gui-subagent/action-parser/index.ts +8 -8
  183. package/src/gui-subagent/action-parser/types.ts +31 -31
  184. package/src/gui-subagent/agent/gui-agent.ts +1151 -1089
  185. package/src/gui-subagent/agent/index.ts +5 -5
  186. package/src/gui-subagent/index.ts +177 -163
  187. package/src/gui-subagent/operator/base-operator.ts +244 -245
  188. package/src/gui-subagent/operator/computer-operator.ts +540 -520
  189. package/src/gui-subagent/operator/index.ts +6 -6
  190. package/src/gui-subagent/types/actions.ts +260 -262
  191. package/src/gui-subagent/types/index.ts +6 -6
  192. package/src/gui-subagent/types/operator.ts +106 -106
  193. package/src/gui-subagent/utils.ts +51 -51
  194. package/src/index.ts +17 -18
  195. package/src/input-processor.ts +6 -3
  196. package/src/logger.ts +438 -438
  197. package/src/mcp.ts +730 -682
  198. package/src/memory.ts +344 -344
  199. package/src/ripgrep.ts +368 -0
  200. package/src/session-manager.ts +308 -308
  201. package/src/session.ts +948 -386
  202. package/src/shell.ts +133 -0
  203. package/src/skill-installer.ts +518 -0
  204. package/src/skill-invoker.ts +960 -935
  205. package/src/skill-loader.ts +501 -496
  206. package/src/skill-manager.ts +384 -0
  207. package/src/slash-commands.ts +2181 -1389
  208. package/src/smart-approval.ts +117 -73
  209. package/src/system-prompt-generator.ts +89 -34
  210. package/src/terminal.ts +96 -0
  211. package/src/theme.ts +738 -738
  212. package/src/tools.ts +1336 -773
  213. package/src/truncate.ts +173 -0
  214. package/src/types.ts +219 -198
  215. package/src/update.ts +22 -32
  216. package/src/workflow.ts +523 -508
  217. package/tsconfig.json +22 -22
  218. package/vitest.config.ts +19 -19
  219. package/dist/ai-client.d.ts +0 -86
  220. package/dist/ai-client.d.ts.map +0 -1
  221. package/dist/ai-client.js +0 -1372
  222. package/dist/ai-client.js.map +0 -1
  223. package/dist/gui-subagent/operator/browser-operator.d.ts +0 -36
  224. package/dist/gui-subagent/operator/browser-operator.d.ts.map +0 -1
  225. package/dist/gui-subagent/operator/browser-operator.js +0 -306
  226. package/dist/gui-subagent/operator/browser-operator.js.map +0 -1
  227. package/dist/gui-subagent/operator/desktop-operator.d.ts +0 -55
  228. package/dist/gui-subagent/operator/desktop-operator.d.ts.map +0 -1
  229. package/dist/gui-subagent/operator/desktop-operator.js +0 -527
  230. package/dist/gui-subagent/operator/desktop-operator.js.map +0 -1
  231. package/dist/hook.d.ts +0 -73
  232. package/dist/hook.d.ts.map +0 -1
  233. package/dist/hook.js +0 -156
  234. package/dist/hook.js.map +0 -1
  235. package/dist/input-history.d.ts +0 -24
  236. package/dist/input-history.d.ts.map +0 -1
  237. package/dist/input-history.js +0 -94
  238. package/dist/input-history.js.map +0 -1
  239. package/dist/keyboard-manager.d.ts +0 -151
  240. package/dist/keyboard-manager.d.ts.map +0 -1
  241. package/dist/keyboard-manager.js +0 -396
  242. package/dist/keyboard-manager.js.map +0 -1
  243. package/dist/print-system-prompt.d.ts +0 -2
  244. package/dist/print-system-prompt.d.ts.map +0 -1
  245. package/dist/print-system-prompt.js +0 -40
  246. package/dist/print-system-prompt.js.map +0 -1
  247. package/dist/remote-ai-client.d.ts +0 -104
  248. package/dist/remote-ai-client.d.ts.map +0 -1
  249. package/dist/remote-ai-client.js +0 -552
  250. package/dist/remote-ai-client.js.map +0 -1
  251. package/dist/sdk-output-adapter.d.ts +0 -232
  252. package/dist/sdk-output-adapter.d.ts.map +0 -1
  253. package/dist/sdk-output-adapter.js +0 -636
  254. package/dist/sdk-output-adapter.js.map +0 -1
  255. package/dist/sdk-session-v2.d.ts +0 -13
  256. package/dist/sdk-session-v2.d.ts.map +0 -1
  257. package/dist/sdk-session-v2.js +0 -46
  258. package/dist/sdk-session-v2.js.map +0 -1
  259. package/dist/sdk-session.d.ts +0 -13
  260. package/dist/sdk-session.d.ts.map +0 -1
  261. package/dist/sdk-session.js +0 -48
  262. package/dist/sdk-session.js.map +0 -1
  263. package/dist/test-boundary-conditions.d.ts.map +0 -1
  264. package/dist/test-boundary-conditions.js.map +0 -1
  265. package/dist/test-cancellation-fix.d.ts.map +0 -1
  266. package/dist/test-cancellation-fix.js.map +0 -1
  267. package/dist/test-input-history.d.ts.map +0 -1
  268. package/dist/test-input-history.js.map +0 -1
  269. package/dist/test-interaction-flow.d.ts.map +0 -1
  270. package/dist/test-interaction-flow.js.map +0 -1
  271. package/dist/test-quick.d.ts.map +0 -1
  272. package/dist/test-quick.js.map +0 -1
  273. package/dist/test-user-interaction.d.ts.map +0 -1
  274. package/dist/test-user-interaction.js.map +0 -1
  275. package/dist/tools/edit-diff.d.ts +0 -32
  276. package/dist/tools/edit-diff.d.ts.map +0 -1
  277. package/dist/tools/edit-diff.js +0 -185
  278. package/dist/tools/edit-diff.js.map +0 -1
  279. package/dist/tools/edit.d.ts +0 -11
  280. package/dist/tools/edit.d.ts.map +0 -1
  281. package/dist/tools/edit.js +0 -129
  282. package/dist/tools/edit.js.map +0 -1
  283. package/dist/unified-session.d.ts +0 -42
  284. package/dist/unified-session.d.ts.map +0 -1
  285. package/dist/unified-session.js +0 -271
  286. package/dist/unified-session.js.map +0 -1
  287. package/skills/.claude-plugin/marketplace.json +0 -45
  288. package/skills/README.md +0 -94
  289. package/skills/THIRD_PARTY_NOTICES.md +0 -405
  290. package/skills/skills/algorithmic-art/LICENSE.txt +0 -202
  291. package/skills/skills/algorithmic-art/SKILL.md +0 -405
  292. package/skills/skills/algorithmic-art/templates/generator_template.js +0 -223
  293. package/skills/skills/algorithmic-art/templates/viewer.html +0 -599
  294. package/skills/skills/brand-guidelines/LICENSE.txt +0 -202
  295. package/skills/skills/brand-guidelines/SKILL.md +0 -73
  296. package/skills/skills/canvas-design/LICENSE.txt +0 -202
  297. package/skills/skills/canvas-design/SKILL.md +0 -130
  298. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
  299. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  300. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  301. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
  302. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  303. package/skills/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
  304. package/skills/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  305. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  306. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
  307. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  308. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  309. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  310. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
  311. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  312. package/skills/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
  313. package/skills/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  314. package/skills/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
  315. package/skills/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  316. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  317. package/skills/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
  318. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  319. package/skills/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
  320. package/skills/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  321. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  322. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
  323. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  324. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  325. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  326. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  327. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  328. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  329. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  330. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  331. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
  332. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  333. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  334. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  335. package/skills/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
  336. package/skills/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  337. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  338. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
  339. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  340. package/skills/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  341. package/skills/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  342. package/skills/skills/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
  343. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
  344. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  345. package/skills/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  346. package/skills/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  347. package/skills/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  348. package/skills/skills/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
  349. package/skills/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  350. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  351. package/skills/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
  352. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  353. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
  354. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  355. package/skills/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  356. package/skills/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
  357. package/skills/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  358. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  359. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
  360. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
  361. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  362. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  363. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
  364. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  365. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
  366. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  367. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  368. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
  369. package/skills/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  370. package/skills/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
  371. package/skills/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  372. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  373. package/skills/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  374. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  375. package/skills/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
  376. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  377. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
  378. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  379. package/skills/skills/doc-coauthoring/SKILL.md +0 -375
  380. package/skills/skills/docx/LICENSE.txt +0 -30
  381. package/skills/skills/docx/SKILL.md +0 -197
  382. package/skills/skills/docx/docx-js.md +0 -350
  383. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  384. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  385. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  386. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  387. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  388. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  389. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  390. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  391. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  392. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  393. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  394. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  395. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  396. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  397. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  398. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  399. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  400. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  401. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  402. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  403. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  404. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  405. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  406. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  407. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  408. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  409. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  410. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  411. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  412. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  413. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  414. package/skills/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
  415. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  416. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  417. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  418. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  419. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  420. package/skills/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  421. package/skills/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  422. package/skills/skills/docx/ooxml/scripts/pack.py +0 -159
  423. package/skills/skills/docx/ooxml/scripts/unpack.py +0 -29
  424. package/skills/skills/docx/ooxml/scripts/validate.py +0 -69
  425. package/skills/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
  426. package/skills/skills/docx/ooxml/scripts/validation/base.py +0 -951
  427. package/skills/skills/docx/ooxml/scripts/validation/docx.py +0 -274
  428. package/skills/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
  429. package/skills/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
  430. package/skills/skills/docx/ooxml.md +0 -610
  431. package/skills/skills/docx/scripts/__init__.py +0 -1
  432. package/skills/skills/docx/scripts/document.py +0 -1276
  433. package/skills/skills/docx/scripts/templates/comments.xml +0 -3
  434. package/skills/skills/docx/scripts/templates/commentsExtended.xml +0 -3
  435. package/skills/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
  436. package/skills/skills/docx/scripts/templates/commentsIds.xml +0 -3
  437. package/skills/skills/docx/scripts/templates/people.xml +0 -3
  438. package/skills/skills/docx/scripts/utilities.py +0 -374
  439. package/skills/skills/frontend-design/LICENSE.txt +0 -177
  440. package/skills/skills/frontend-design/SKILL.md +0 -42
  441. package/skills/skills/internal-comms/LICENSE.txt +0 -202
  442. package/skills/skills/internal-comms/SKILL.md +0 -32
  443. package/skills/skills/internal-comms/examples/3p-updates.md +0 -47
  444. package/skills/skills/internal-comms/examples/company-newsletter.md +0 -65
  445. package/skills/skills/internal-comms/examples/faq-answers.md +0 -30
  446. package/skills/skills/internal-comms/examples/general-comms.md +0 -16
  447. package/skills/skills/mcp-builder/LICENSE.txt +0 -202
  448. package/skills/skills/mcp-builder/SKILL.md +0 -236
  449. package/skills/skills/mcp-builder/reference/evaluation.md +0 -602
  450. package/skills/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  451. package/skills/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  452. package/skills/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  453. package/skills/skills/mcp-builder/scripts/connections.py +0 -151
  454. package/skills/skills/mcp-builder/scripts/evaluation.py +0 -373
  455. package/skills/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  456. package/skills/skills/mcp-builder/scripts/requirements.txt +0 -2
  457. package/skills/skills/pdf/LICENSE.txt +0 -30
  458. package/skills/skills/pdf/SKILL.md +0 -294
  459. package/skills/skills/pdf/forms.md +0 -205
  460. package/skills/skills/pdf/reference.md +0 -612
  461. package/skills/skills/pdf/scripts/check_bounding_boxes.py +0 -70
  462. package/skills/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
  463. package/skills/skills/pdf/scripts/check_fillable_fields.py +0 -12
  464. package/skills/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
  465. package/skills/skills/pdf/scripts/create_validation_image.py +0 -41
  466. package/skills/skills/pdf/scripts/extract_form_field_info.py +0 -152
  467. package/skills/skills/pdf/scripts/fill_fillable_fields.py +0 -114
  468. package/skills/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
  469. package/skills/skills/pptx/LICENSE.txt +0 -30
  470. package/skills/skills/pptx/SKILL.md +0 -484
  471. package/skills/skills/pptx/html2pptx.md +0 -625
  472. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  473. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  474. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  475. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  476. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  477. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  478. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  479. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  480. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  481. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  482. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  483. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  484. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  485. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  486. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  487. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  488. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  489. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  490. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  491. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  492. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  493. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  494. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  495. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  496. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  497. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  498. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  499. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  500. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  501. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  502. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  503. package/skills/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
  504. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  505. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  506. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  507. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  508. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  509. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  510. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  511. package/skills/skills/pptx/ooxml/scripts/pack.py +0 -159
  512. package/skills/skills/pptx/ooxml/scripts/unpack.py +0 -29
  513. package/skills/skills/pptx/ooxml/scripts/validate.py +0 -69
  514. package/skills/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
  515. package/skills/skills/pptx/ooxml/scripts/validation/base.py +0 -951
  516. package/skills/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
  517. package/skills/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
  518. package/skills/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
  519. package/skills/skills/pptx/ooxml.md +0 -427
  520. package/skills/skills/pptx/scripts/html2pptx.js +0 -979
  521. package/skills/skills/pptx/scripts/inventory.py +0 -1020
  522. package/skills/skills/pptx/scripts/rearrange.py +0 -231
  523. package/skills/skills/pptx/scripts/replace.py +0 -385
  524. package/skills/skills/pptx/scripts/thumbnail.py +0 -450
  525. package/skills/skills/skill-creator/LICENSE.txt +0 -202
  526. package/skills/skills/skill-creator/SKILL.md +0 -356
  527. package/skills/skills/skill-creator/references/output-patterns.md +0 -82
  528. package/skills/skills/skill-creator/references/workflows.md +0 -28
  529. package/skills/skills/skill-creator/scripts/init_skill.py +0 -303
  530. package/skills/skills/skill-creator/scripts/package_skill.py +0 -110
  531. package/skills/skills/skill-creator/scripts/quick_validate.py +0 -95
  532. package/skills/skills/slack-gif-creator/LICENSE.txt +0 -202
  533. package/skills/skills/slack-gif-creator/SKILL.md +0 -254
  534. package/skills/skills/slack-gif-creator/core/easing.py +0 -234
  535. package/skills/skills/slack-gif-creator/core/frame_composer.py +0 -176
  536. package/skills/skills/slack-gif-creator/core/gif_builder.py +0 -269
  537. package/skills/skills/slack-gif-creator/core/validators.py +0 -136
  538. package/skills/skills/slack-gif-creator/requirements.txt +0 -4
  539. package/skills/skills/theme-factory/LICENSE.txt +0 -202
  540. package/skills/skills/theme-factory/SKILL.md +0 -59
  541. package/skills/skills/theme-factory/theme-showcase.pdf +0 -0
  542. package/skills/skills/theme-factory/themes/arctic-frost.md +0 -19
  543. package/skills/skills/theme-factory/themes/botanical-garden.md +0 -19
  544. package/skills/skills/theme-factory/themes/desert-rose.md +0 -19
  545. package/skills/skills/theme-factory/themes/forest-canopy.md +0 -19
  546. package/skills/skills/theme-factory/themes/golden-hour.md +0 -19
  547. package/skills/skills/theme-factory/themes/midnight-galaxy.md +0 -19
  548. package/skills/skills/theme-factory/themes/modern-minimalist.md +0 -19
  549. package/skills/skills/theme-factory/themes/ocean-depths.md +0 -19
  550. package/skills/skills/theme-factory/themes/sunset-boulevard.md +0 -19
  551. package/skills/skills/theme-factory/themes/tech-innovation.md +0 -19
  552. package/skills/skills/web-artifacts-builder/LICENSE.txt +0 -202
  553. package/skills/skills/web-artifacts-builder/SKILL.md +0 -74
  554. package/skills/skills/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
  555. package/skills/skills/web-artifacts-builder/scripts/init-artifact.sh +0 -322
  556. package/skills/skills/webapp-testing/LICENSE.txt +0 -202
  557. package/skills/skills/webapp-testing/SKILL.md +0 -96
  558. package/skills/skills/webapp-testing/examples/console_logging.py +0 -35
  559. package/skills/skills/webapp-testing/examples/element_discovery.py +0 -40
  560. package/skills/skills/webapp-testing/examples/static_html_automation.py +0 -33
  561. package/skills/skills/webapp-testing/scripts/with_server.py +0 -106
  562. package/skills/skills/xlsx/LICENSE.txt +0 -30
  563. package/skills/skills/xlsx/SKILL.md +0 -289
  564. package/skills/skills/xlsx/recalc.py +0 -178
  565. package/skills/spec/agent-skills-spec.md +0 -3
  566. package/skills/template/SKILL.md +0 -6
  567. package/src/ai-client.ts +0 -1560
  568. package/src/remote-ai-client.ts +0 -664
@@ -1,226 +0,0 @@
1
- import unittest
2
- import json
3
- import io
4
- from check_bounding_boxes import get_bounding_box_messages
5
-
6
-
7
- # Currently this is not run automatically in CI; it's just for documentation and manual checking.
8
- class TestGetBoundingBoxMessages(unittest.TestCase):
9
-
10
- def create_json_stream(self, data):
11
- """Helper to create a JSON stream from data"""
12
- return io.StringIO(json.dumps(data))
13
-
14
- def test_no_intersections(self):
15
- """Test case with no bounding box intersections"""
16
- data = {
17
- "form_fields": [
18
- {
19
- "description": "Name",
20
- "page_number": 1,
21
- "label_bounding_box": [10, 10, 50, 30],
22
- "entry_bounding_box": [60, 10, 150, 30]
23
- },
24
- {
25
- "description": "Email",
26
- "page_number": 1,
27
- "label_bounding_box": [10, 40, 50, 60],
28
- "entry_bounding_box": [60, 40, 150, 60]
29
- }
30
- ]
31
- }
32
-
33
- stream = self.create_json_stream(data)
34
- messages = get_bounding_box_messages(stream)
35
- self.assertTrue(any("SUCCESS" in msg for msg in messages))
36
- self.assertFalse(any("FAILURE" in msg for msg in messages))
37
-
38
- def test_label_entry_intersection_same_field(self):
39
- """Test intersection between label and entry of the same field"""
40
- data = {
41
- "form_fields": [
42
- {
43
- "description": "Name",
44
- "page_number": 1,
45
- "label_bounding_box": [10, 10, 60, 30],
46
- "entry_bounding_box": [50, 10, 150, 30] # Overlaps with label
47
- }
48
- ]
49
- }
50
-
51
- stream = self.create_json_stream(data)
52
- messages = get_bounding_box_messages(stream)
53
- self.assertTrue(any("FAILURE" in msg and "intersection" in msg for msg in messages))
54
- self.assertFalse(any("SUCCESS" in msg for msg in messages))
55
-
56
- def test_intersection_between_different_fields(self):
57
- """Test intersection between bounding boxes of different fields"""
58
- data = {
59
- "form_fields": [
60
- {
61
- "description": "Name",
62
- "page_number": 1,
63
- "label_bounding_box": [10, 10, 50, 30],
64
- "entry_bounding_box": [60, 10, 150, 30]
65
- },
66
- {
67
- "description": "Email",
68
- "page_number": 1,
69
- "label_bounding_box": [40, 20, 80, 40], # Overlaps with Name's boxes
70
- "entry_bounding_box": [160, 10, 250, 30]
71
- }
72
- ]
73
- }
74
-
75
- stream = self.create_json_stream(data)
76
- messages = get_bounding_box_messages(stream)
77
- self.assertTrue(any("FAILURE" in msg and "intersection" in msg for msg in messages))
78
- self.assertFalse(any("SUCCESS" in msg for msg in messages))
79
-
80
- def test_different_pages_no_intersection(self):
81
- """Test that boxes on different pages don't count as intersecting"""
82
- data = {
83
- "form_fields": [
84
- {
85
- "description": "Name",
86
- "page_number": 1,
87
- "label_bounding_box": [10, 10, 50, 30],
88
- "entry_bounding_box": [60, 10, 150, 30]
89
- },
90
- {
91
- "description": "Email",
92
- "page_number": 2,
93
- "label_bounding_box": [10, 10, 50, 30], # Same coordinates but different page
94
- "entry_bounding_box": [60, 10, 150, 30]
95
- }
96
- ]
97
- }
98
-
99
- stream = self.create_json_stream(data)
100
- messages = get_bounding_box_messages(stream)
101
- self.assertTrue(any("SUCCESS" in msg for msg in messages))
102
- self.assertFalse(any("FAILURE" in msg for msg in messages))
103
-
104
- def test_entry_height_too_small(self):
105
- """Test that entry box height is checked against font size"""
106
- data = {
107
- "form_fields": [
108
- {
109
- "description": "Name",
110
- "page_number": 1,
111
- "label_bounding_box": [10, 10, 50, 30],
112
- "entry_bounding_box": [60, 10, 150, 20], # Height is 10
113
- "entry_text": {
114
- "font_size": 14 # Font size larger than height
115
- }
116
- }
117
- ]
118
- }
119
-
120
- stream = self.create_json_stream(data)
121
- messages = get_bounding_box_messages(stream)
122
- self.assertTrue(any("FAILURE" in msg and "height" in msg for msg in messages))
123
- self.assertFalse(any("SUCCESS" in msg for msg in messages))
124
-
125
- def test_entry_height_adequate(self):
126
- """Test that adequate entry box height passes"""
127
- data = {
128
- "form_fields": [
129
- {
130
- "description": "Name",
131
- "page_number": 1,
132
- "label_bounding_box": [10, 10, 50, 30],
133
- "entry_bounding_box": [60, 10, 150, 30], # Height is 20
134
- "entry_text": {
135
- "font_size": 14 # Font size smaller than height
136
- }
137
- }
138
- ]
139
- }
140
-
141
- stream = self.create_json_stream(data)
142
- messages = get_bounding_box_messages(stream)
143
- self.assertTrue(any("SUCCESS" in msg for msg in messages))
144
- self.assertFalse(any("FAILURE" in msg for msg in messages))
145
-
146
- def test_default_font_size(self):
147
- """Test that default font size is used when not specified"""
148
- data = {
149
- "form_fields": [
150
- {
151
- "description": "Name",
152
- "page_number": 1,
153
- "label_bounding_box": [10, 10, 50, 30],
154
- "entry_bounding_box": [60, 10, 150, 20], # Height is 10
155
- "entry_text": {} # No font_size specified, should use default 14
156
- }
157
- ]
158
- }
159
-
160
- stream = self.create_json_stream(data)
161
- messages = get_bounding_box_messages(stream)
162
- self.assertTrue(any("FAILURE" in msg and "height" in msg for msg in messages))
163
- self.assertFalse(any("SUCCESS" in msg for msg in messages))
164
-
165
- def test_no_entry_text(self):
166
- """Test that missing entry_text doesn't cause height check"""
167
- data = {
168
- "form_fields": [
169
- {
170
- "description": "Name",
171
- "page_number": 1,
172
- "label_bounding_box": [10, 10, 50, 30],
173
- "entry_bounding_box": [60, 10, 150, 20] # Small height but no entry_text
174
- }
175
- ]
176
- }
177
-
178
- stream = self.create_json_stream(data)
179
- messages = get_bounding_box_messages(stream)
180
- self.assertTrue(any("SUCCESS" in msg for msg in messages))
181
- self.assertFalse(any("FAILURE" in msg for msg in messages))
182
-
183
- def test_multiple_errors_limit(self):
184
- """Test that error messages are limited to prevent excessive output"""
185
- fields = []
186
- # Create many overlapping fields
187
- for i in range(25):
188
- fields.append({
189
- "description": f"Field{i}",
190
- "page_number": 1,
191
- "label_bounding_box": [10, 10, 50, 30], # All overlap
192
- "entry_bounding_box": [20, 15, 60, 35] # All overlap
193
- })
194
-
195
- data = {"form_fields": fields}
196
-
197
- stream = self.create_json_stream(data)
198
- messages = get_bounding_box_messages(stream)
199
- # Should abort after ~20 messages
200
- self.assertTrue(any("Aborting" in msg for msg in messages))
201
- # Should have some FAILURE messages but not hundreds
202
- failure_count = sum(1 for msg in messages if "FAILURE" in msg)
203
- self.assertGreater(failure_count, 0)
204
- self.assertLess(len(messages), 30) # Should be limited
205
-
206
- def test_edge_touching_boxes(self):
207
- """Test that boxes touching at edges don't count as intersecting"""
208
- data = {
209
- "form_fields": [
210
- {
211
- "description": "Name",
212
- "page_number": 1,
213
- "label_bounding_box": [10, 10, 50, 30],
214
- "entry_bounding_box": [50, 10, 150, 30] # Touches at x=50
215
- }
216
- ]
217
- }
218
-
219
- stream = self.create_json_stream(data)
220
- messages = get_bounding_box_messages(stream)
221
- self.assertTrue(any("SUCCESS" in msg for msg in messages))
222
- self.assertFalse(any("FAILURE" in msg for msg in messages))
223
-
224
-
225
- if __name__ == '__main__':
226
- unittest.main()
@@ -1,12 +0,0 @@
1
- import sys
2
- from pypdf import PdfReader
3
-
4
-
5
- # Script for Claude to run to determine whether a PDF has fillable form fields. See forms.md.
6
-
7
-
8
- reader = PdfReader(sys.argv[1])
9
- if (reader.get_fields()):
10
- print("This PDF has fillable form fields")
11
- else:
12
- print("This PDF does not have fillable form fields; you will need to visually determine where to enter data")
@@ -1,35 +0,0 @@
1
- import os
2
- import sys
3
-
4
- from pdf2image import convert_from_path
5
-
6
-
7
- # Converts each page of a PDF to a PNG image.
8
-
9
-
10
- def convert(pdf_path, output_dir, max_dim=1000):
11
- images = convert_from_path(pdf_path, dpi=200)
12
-
13
- for i, image in enumerate(images):
14
- # Scale image if needed to keep width/height under `max_dim`
15
- width, height = image.size
16
- if width > max_dim or height > max_dim:
17
- scale_factor = min(max_dim / width, max_dim / height)
18
- new_width = int(width * scale_factor)
19
- new_height = int(height * scale_factor)
20
- image = image.resize((new_width, new_height))
21
-
22
- image_path = os.path.join(output_dir, f"page_{i+1}.png")
23
- image.save(image_path)
24
- print(f"Saved page {i+1} as {image_path} (size: {image.size})")
25
-
26
- print(f"Converted {len(images)} pages to PNG images")
27
-
28
-
29
- if __name__ == "__main__":
30
- if len(sys.argv) != 3:
31
- print("Usage: convert_pdf_to_images.py [input pdf] [output directory]")
32
- sys.exit(1)
33
- pdf_path = sys.argv[1]
34
- output_directory = sys.argv[2]
35
- convert(pdf_path, output_directory)
@@ -1,41 +0,0 @@
1
- import json
2
- import sys
3
-
4
- from PIL import Image, ImageDraw
5
-
6
-
7
- # Creates "validation" images with rectangles for the bounding box information that
8
- # Claude creates when determining where to add text annotations in PDFs. See forms.md.
9
-
10
-
11
- def create_validation_image(page_number, fields_json_path, input_path, output_path):
12
- # Input file should be in the `fields.json` format described in forms.md.
13
- with open(fields_json_path, 'r') as f:
14
- data = json.load(f)
15
-
16
- img = Image.open(input_path)
17
- draw = ImageDraw.Draw(img)
18
- num_boxes = 0
19
-
20
- for field in data["form_fields"]:
21
- if field["page_number"] == page_number:
22
- entry_box = field['entry_bounding_box']
23
- label_box = field['label_bounding_box']
24
- # Draw red rectangle over entry bounding box and blue rectangle over the label.
25
- draw.rectangle(entry_box, outline='red', width=2)
26
- draw.rectangle(label_box, outline='blue', width=2)
27
- num_boxes += 2
28
-
29
- img.save(output_path)
30
- print(f"Created validation image at {output_path} with {num_boxes} bounding boxes")
31
-
32
-
33
- if __name__ == "__main__":
34
- if len(sys.argv) != 5:
35
- print("Usage: create_validation_image.py [page number] [fields.json file] [input image path] [output image path]")
36
- sys.exit(1)
37
- page_number = int(sys.argv[1])
38
- fields_json_path = sys.argv[2]
39
- input_image_path = sys.argv[3]
40
- output_image_path = sys.argv[4]
41
- create_validation_image(page_number, fields_json_path, input_image_path, output_image_path)
@@ -1,152 +0,0 @@
1
- import json
2
- import sys
3
-
4
- from pypdf import PdfReader
5
-
6
-
7
- # Extracts data for the fillable form fields in a PDF and outputs JSON that
8
- # Claude uses to fill the fields. See forms.md.
9
-
10
-
11
- # This matches the format used by PdfReader `get_fields` and `update_page_form_field_values` methods.
12
- def get_full_annotation_field_id(annotation):
13
- components = []
14
- while annotation:
15
- field_name = annotation.get('/T')
16
- if field_name:
17
- components.append(field_name)
18
- annotation = annotation.get('/Parent')
19
- return ".".join(reversed(components)) if components else None
20
-
21
-
22
- def make_field_dict(field, field_id):
23
- field_dict = {"field_id": field_id}
24
- ft = field.get('/FT')
25
- if ft == "/Tx":
26
- field_dict["type"] = "text"
27
- elif ft == "/Btn":
28
- field_dict["type"] = "checkbox" # radio groups handled separately
29
- states = field.get("/_States_", [])
30
- if len(states) == 2:
31
- # "/Off" seems to always be the unchecked value, as suggested by
32
- # https://opensource.adobe.com/dc-acrobat-sdk-docs/standards/pdfstandards/pdf/PDF32000_2008.pdf#page=448
33
- # It can be either first or second in the "/_States_" list.
34
- if "/Off" in states:
35
- field_dict["checked_value"] = states[0] if states[0] != "/Off" else states[1]
36
- field_dict["unchecked_value"] = "/Off"
37
- else:
38
- print(f"Unexpected state values for checkbox `${field_id}`. Its checked and unchecked values may not be correct; if you're trying to check it, visually verify the results.")
39
- field_dict["checked_value"] = states[0]
40
- field_dict["unchecked_value"] = states[1]
41
- elif ft == "/Ch":
42
- field_dict["type"] = "choice"
43
- states = field.get("/_States_", [])
44
- field_dict["choice_options"] = [{
45
- "value": state[0],
46
- "text": state[1],
47
- } for state in states]
48
- else:
49
- field_dict["type"] = f"unknown ({ft})"
50
- return field_dict
51
-
52
-
53
- # Returns a list of fillable PDF fields:
54
- # [
55
- # {
56
- # "field_id": "name",
57
- # "page": 1,
58
- # "type": ("text", "checkbox", "radio_group", or "choice")
59
- # // Per-type additional fields described in forms.md
60
- # },
61
- # ]
62
- def get_field_info(reader: PdfReader):
63
- fields = reader.get_fields()
64
-
65
- field_info_by_id = {}
66
- possible_radio_names = set()
67
-
68
- for field_id, field in fields.items():
69
- # Skip if this is a container field with children, except that it might be
70
- # a parent group for radio button options.
71
- if field.get("/Kids"):
72
- if field.get("/FT") == "/Btn":
73
- possible_radio_names.add(field_id)
74
- continue
75
- field_info_by_id[field_id] = make_field_dict(field, field_id)
76
-
77
- # Bounding rects are stored in annotations in page objects.
78
-
79
- # Radio button options have a separate annotation for each choice;
80
- # all choices have the same field name.
81
- # See https://westhealth.github.io/exploring-fillable-forms-with-pdfrw.html
82
- radio_fields_by_id = {}
83
-
84
- for page_index, page in enumerate(reader.pages):
85
- annotations = page.get('/Annots', [])
86
- for ann in annotations:
87
- field_id = get_full_annotation_field_id(ann)
88
- if field_id in field_info_by_id:
89
- field_info_by_id[field_id]["page"] = page_index + 1
90
- field_info_by_id[field_id]["rect"] = ann.get('/Rect')
91
- elif field_id in possible_radio_names:
92
- try:
93
- # ann['/AP']['/N'] should have two items. One of them is '/Off',
94
- # the other is the active value.
95
- on_values = [v for v in ann["/AP"]["/N"] if v != "/Off"]
96
- except KeyError:
97
- continue
98
- if len(on_values) == 1:
99
- rect = ann.get("/Rect")
100
- if field_id not in radio_fields_by_id:
101
- radio_fields_by_id[field_id] = {
102
- "field_id": field_id,
103
- "type": "radio_group",
104
- "page": page_index + 1,
105
- "radio_options": [],
106
- }
107
- # Note: at least on macOS 15.7, Preview.app doesn't show selected
108
- # radio buttons correctly. (It does if you remove the leading slash
109
- # from the value, but that causes them not to appear correctly in
110
- # Chrome/Firefox/Acrobat/etc).
111
- radio_fields_by_id[field_id]["radio_options"].append({
112
- "value": on_values[0],
113
- "rect": rect,
114
- })
115
-
116
- # Some PDFs have form field definitions without corresponding annotations,
117
- # so we can't tell where they are. Ignore these fields for now.
118
- fields_with_location = []
119
- for field_info in field_info_by_id.values():
120
- if "page" in field_info:
121
- fields_with_location.append(field_info)
122
- else:
123
- print(f"Unable to determine location for field id: {field_info.get('field_id')}, ignoring")
124
-
125
- # Sort by page number, then Y position (flipped in PDF coordinate system), then X.
126
- def sort_key(f):
127
- if "radio_options" in f:
128
- rect = f["radio_options"][0]["rect"] or [0, 0, 0, 0]
129
- else:
130
- rect = f.get("rect") or [0, 0, 0, 0]
131
- adjusted_position = [-rect[1], rect[0]]
132
- return [f.get("page"), adjusted_position]
133
-
134
- sorted_fields = fields_with_location + list(radio_fields_by_id.values())
135
- sorted_fields.sort(key=sort_key)
136
-
137
- return sorted_fields
138
-
139
-
140
- def write_field_info(pdf_path: str, json_output_path: str):
141
- reader = PdfReader(pdf_path)
142
- field_info = get_field_info(reader)
143
- with open(json_output_path, "w") as f:
144
- json.dump(field_info, f, indent=2)
145
- print(f"Wrote {len(field_info)} fields to {json_output_path}")
146
-
147
-
148
- if __name__ == "__main__":
149
- if len(sys.argv) != 3:
150
- print("Usage: extract_form_field_info.py [input pdf] [output json]")
151
- sys.exit(1)
152
- write_field_info(sys.argv[1], sys.argv[2])
@@ -1,114 +0,0 @@
1
- import json
2
- import sys
3
-
4
- from pypdf import PdfReader, PdfWriter
5
-
6
- from extract_form_field_info import get_field_info
7
-
8
-
9
- # Fills fillable form fields in a PDF. See forms.md.
10
-
11
-
12
- def fill_pdf_fields(input_pdf_path: str, fields_json_path: str, output_pdf_path: str):
13
- with open(fields_json_path) as f:
14
- fields = json.load(f)
15
- # Group by page number.
16
- fields_by_page = {}
17
- for field in fields:
18
- if "value" in field:
19
- field_id = field["field_id"]
20
- page = field["page"]
21
- if page not in fields_by_page:
22
- fields_by_page[page] = {}
23
- fields_by_page[page][field_id] = field["value"]
24
-
25
- reader = PdfReader(input_pdf_path)
26
-
27
- has_error = False
28
- field_info = get_field_info(reader)
29
- fields_by_ids = {f["field_id"]: f for f in field_info}
30
- for field in fields:
31
- existing_field = fields_by_ids.get(field["field_id"])
32
- if not existing_field:
33
- has_error = True
34
- print(f"ERROR: `{field['field_id']}` is not a valid field ID")
35
- elif field["page"] != existing_field["page"]:
36
- has_error = True
37
- print(f"ERROR: Incorrect page number for `{field['field_id']}` (got {field['page']}, expected {existing_field['page']})")
38
- else:
39
- if "value" in field:
40
- err = validation_error_for_field_value(existing_field, field["value"])
41
- if err:
42
- print(err)
43
- has_error = True
44
- if has_error:
45
- sys.exit(1)
46
-
47
- writer = PdfWriter(clone_from=reader)
48
- for page, field_values in fields_by_page.items():
49
- writer.update_page_form_field_values(writer.pages[page - 1], field_values, auto_regenerate=False)
50
-
51
- # This seems to be necessary for many PDF viewers to format the form values correctly.
52
- # It may cause the viewer to show a "save changes" dialog even if the user doesn't make any changes.
53
- writer.set_need_appearances_writer(True)
54
-
55
- with open(output_pdf_path, "wb") as f:
56
- writer.write(f)
57
-
58
-
59
- def validation_error_for_field_value(field_info, field_value):
60
- field_type = field_info["type"]
61
- field_id = field_info["field_id"]
62
- if field_type == "checkbox":
63
- checked_val = field_info["checked_value"]
64
- unchecked_val = field_info["unchecked_value"]
65
- if field_value != checked_val and field_value != unchecked_val:
66
- return f'ERROR: Invalid value "{field_value}" for checkbox field "{field_id}". The checked value is "{checked_val}" and the unchecked value is "{unchecked_val}"'
67
- elif field_type == "radio_group":
68
- option_values = [opt["value"] for opt in field_info["radio_options"]]
69
- if field_value not in option_values:
70
- return f'ERROR: Invalid value "{field_value}" for radio group field "{field_id}". Valid values are: {option_values}'
71
- elif field_type == "choice":
72
- choice_values = [opt["value"] for opt in field_info["choice_options"]]
73
- if field_value not in choice_values:
74
- return f'ERROR: Invalid value "{field_value}" for choice field "{field_id}". Valid values are: {choice_values}'
75
- return None
76
-
77
-
78
- # pypdf (at least version 5.7.0) has a bug when setting the value for a selection list field.
79
- # In _writer.py around line 966:
80
- #
81
- # if field.get(FA.FT, "/Tx") == "/Ch" and field_flags & FA.FfBits.Combo == 0:
82
- # txt = "\n".join(annotation.get_inherited(FA.Opt, []))
83
- #
84
- # The problem is that for selection lists, `get_inherited` returns a list of two-element lists like
85
- # [["value1", "Text 1"], ["value2", "Text 2"], ...]
86
- # This causes `join` to throw a TypeError because it expects an iterable of strings.
87
- # The horrible workaround is to patch `get_inherited` to return a list of the value strings.
88
- # We call the original method and adjust the return value only if the argument to `get_inherited`
89
- # is `FA.Opt` and if the return value is a list of two-element lists.
90
- def monkeypatch_pydpf_method():
91
- from pypdf.generic import DictionaryObject
92
- from pypdf.constants import FieldDictionaryAttributes
93
-
94
- original_get_inherited = DictionaryObject.get_inherited
95
-
96
- def patched_get_inherited(self, key: str, default = None):
97
- result = original_get_inherited(self, key, default)
98
- if key == FieldDictionaryAttributes.Opt:
99
- if isinstance(result, list) and all(isinstance(v, list) and len(v) == 2 for v in result):
100
- result = [r[0] for r in result]
101
- return result
102
-
103
- DictionaryObject.get_inherited = patched_get_inherited
104
-
105
-
106
- if __name__ == "__main__":
107
- if len(sys.argv) != 4:
108
- print("Usage: fill_fillable_fields.py [input pdf] [field_values.json] [output pdf]")
109
- sys.exit(1)
110
- monkeypatch_pydpf_method()
111
- input_pdf = sys.argv[1]
112
- fields_json = sys.argv[2]
113
- output_pdf = sys.argv[3]
114
- fill_pdf_fields(input_pdf, fields_json, output_pdf)