@xagent-ai/cli 1.2.2 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (602) 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/release.yml +76 -0
  4. package/.github/workflows/ci.yml +75 -0
  5. package/.github/workflows/release.yml +103 -0
  6. package/.gitmodules +3 -3
  7. package/README.md +326 -280
  8. package/README_CN.md +325 -279
  9. package/dist/agents.d.ts.map +1 -1
  10. package/dist/agents.js +7 -3
  11. package/dist/agents.js.map +1 -1
  12. package/dist/ai-client/factory.d.ts +40 -0
  13. package/dist/ai-client/factory.d.ts.map +1 -0
  14. package/dist/ai-client/factory.js +100 -0
  15. package/dist/ai-client/factory.js.map +1 -0
  16. package/dist/ai-client/index.d.ts +20 -0
  17. package/dist/ai-client/index.d.ts.map +1 -0
  18. package/dist/ai-client/index.js +49 -0
  19. package/dist/ai-client/index.js.map +1 -0
  20. package/dist/ai-client/providers/anthropic.d.ts +57 -0
  21. package/dist/ai-client/providers/anthropic.d.ts.map +1 -0
  22. package/dist/ai-client/providers/anthropic.js +406 -0
  23. package/dist/ai-client/providers/anthropic.js.map +1 -0
  24. package/dist/ai-client/providers/openai.d.ts +57 -0
  25. package/dist/ai-client/providers/openai.d.ts.map +1 -0
  26. package/dist/ai-client/providers/openai.js +290 -0
  27. package/dist/ai-client/providers/openai.js.map +1 -0
  28. package/dist/ai-client/providers/remote.d.ts +110 -0
  29. package/dist/ai-client/providers/remote.d.ts.map +1 -0
  30. package/dist/ai-client/providers/remote.js +352 -0
  31. package/dist/ai-client/providers/remote.js.map +1 -0
  32. package/dist/ai-client/registry.d.ts +51 -0
  33. package/dist/ai-client/registry.d.ts.map +1 -0
  34. package/dist/ai-client/registry.js +81 -0
  35. package/dist/ai-client/registry.js.map +1 -0
  36. package/dist/ai-client/types.d.ts +274 -0
  37. package/dist/ai-client/types.d.ts.map +1 -0
  38. package/dist/ai-client/types.js +90 -0
  39. package/dist/ai-client/types.js.map +1 -0
  40. package/dist/ai-client-factory.d.ts +62 -0
  41. package/dist/ai-client-factory.d.ts.map +1 -0
  42. package/dist/ai-client-factory.js +157 -0
  43. package/dist/ai-client-factory.js.map +1 -0
  44. package/dist/auth.d.ts +23 -1
  45. package/dist/auth.d.ts.map +1 -1
  46. package/dist/auth.js +164 -174
  47. package/dist/auth.js.map +1 -1
  48. package/dist/cancellation.d.ts +5 -4
  49. package/dist/cancellation.d.ts.map +1 -1
  50. package/dist/cancellation.js +53 -32
  51. package/dist/cancellation.js.map +1 -1
  52. package/dist/checkpoint.d.ts +2 -1
  53. package/dist/checkpoint.d.ts.map +1 -1
  54. package/dist/checkpoint.js +39 -6
  55. package/dist/checkpoint.js.map +1 -1
  56. package/dist/cli.js +742 -29
  57. package/dist/cli.js.map +1 -1
  58. package/dist/config.d.ts +10 -4
  59. package/dist/config.d.ts.map +1 -1
  60. package/dist/config.js +62 -25
  61. package/dist/config.js.map +1 -1
  62. package/dist/context-compressor.d.ts +82 -18
  63. package/dist/context-compressor.d.ts.map +1 -1
  64. package/dist/context-compressor.js +718 -154
  65. package/dist/context-compressor.js.map +1 -1
  66. package/dist/conversation.d.ts +1 -1
  67. package/dist/conversation.d.ts.map +1 -1
  68. package/dist/conversation.js +8 -7
  69. package/dist/conversation.js.map +1 -1
  70. package/dist/gui-subagent/action-parser/actionParser.d.ts.map +1 -1
  71. package/dist/gui-subagent/action-parser/actionParser.js +6 -4
  72. package/dist/gui-subagent/action-parser/actionParser.js.map +1 -1
  73. package/dist/gui-subagent/agent/gui-agent.d.ts +39 -2
  74. package/dist/gui-subagent/agent/gui-agent.d.ts.map +1 -1
  75. package/dist/gui-subagent/agent/gui-agent.js +189 -74
  76. package/dist/gui-subagent/agent/gui-agent.js.map +1 -1
  77. package/dist/gui-subagent/index.d.ts +23 -1
  78. package/dist/gui-subagent/index.d.ts.map +1 -1
  79. package/dist/gui-subagent/index.js +6 -0
  80. package/dist/gui-subagent/index.js.map +1 -1
  81. package/dist/gui-subagent/operator/base-operator.d.ts.map +1 -1
  82. package/dist/gui-subagent/operator/base-operator.js +0 -1
  83. package/dist/gui-subagent/operator/base-operator.js.map +1 -1
  84. package/dist/gui-subagent/operator/computer-operator.d.ts.map +1 -1
  85. package/dist/gui-subagent/operator/computer-operator.js +31 -8
  86. package/dist/gui-subagent/operator/computer-operator.js.map +1 -1
  87. package/dist/gui-subagent/types/actions.d.ts +1 -1
  88. package/dist/gui-subagent/types/actions.d.ts.map +1 -1
  89. package/dist/gui-subagent/types/actions.js +0 -1
  90. package/dist/gui-subagent/types/actions.js.map +1 -1
  91. package/dist/gui-subagent/types/operator.d.ts +1 -1
  92. package/dist/gui-subagent/types/operator.d.ts.map +1 -1
  93. package/dist/index.d.ts +1 -2
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +1 -2
  96. package/dist/index.js.map +1 -1
  97. package/dist/input-processor.d.ts.map +1 -1
  98. package/dist/input-processor.js +8 -5
  99. package/dist/input-processor.js.map +1 -1
  100. package/dist/logger.d.ts.map +1 -1
  101. package/dist/logger.js +1 -1
  102. package/dist/logger.js.map +1 -1
  103. package/dist/mcp.d.ts +7 -1
  104. package/dist/mcp.d.ts.map +1 -1
  105. package/dist/mcp.js +157 -49
  106. package/dist/mcp.js.map +1 -1
  107. package/dist/memory.d.ts.map +1 -1
  108. package/dist/memory.js +3 -3
  109. package/dist/memory.js.map +1 -1
  110. package/dist/output-util.d.ts +27 -0
  111. package/dist/output-util.d.ts.map +1 -0
  112. package/dist/output-util.js +74 -0
  113. package/dist/output-util.js.map +1 -0
  114. package/dist/retry.js +1 -1
  115. package/dist/retry.js.map +1 -1
  116. package/dist/ripgrep.d.ts +29 -0
  117. package/dist/ripgrep.d.ts.map +1 -0
  118. package/dist/ripgrep.js +294 -0
  119. package/dist/ripgrep.js.map +1 -0
  120. package/dist/sdk-output-adapter.d.ts +34 -1
  121. package/dist/sdk-output-adapter.d.ts.map +1 -1
  122. package/dist/sdk-output-adapter.js +67 -2
  123. package/dist/sdk-output-adapter.js.map +1 -1
  124. package/dist/sdk-session.d.ts.map +1 -1
  125. package/dist/sdk-session.js +2 -0
  126. package/dist/sdk-session.js.map +1 -1
  127. package/dist/session-manager.js +3 -3
  128. package/dist/session-manager.js.map +1 -1
  129. package/dist/session.d.ts +116 -6
  130. package/dist/session.d.ts.map +1 -1
  131. package/dist/session.js +1416 -448
  132. package/dist/session.js.map +1 -1
  133. package/dist/shell.d.ts +33 -0
  134. package/dist/shell.d.ts.map +1 -0
  135. package/dist/shell.js +126 -0
  136. package/dist/shell.js.map +1 -0
  137. package/dist/skill-installer.d.ts +38 -0
  138. package/dist/skill-installer.d.ts.map +1 -0
  139. package/dist/skill-installer.js +447 -0
  140. package/dist/skill-installer.js.map +1 -0
  141. package/dist/skill-invoker.d.ts +8 -2
  142. package/dist/skill-invoker.d.ts.map +1 -1
  143. package/dist/skill-invoker.js +36 -15
  144. package/dist/skill-invoker.js.map +1 -1
  145. package/dist/skill-loader.d.ts +8 -3
  146. package/dist/skill-loader.d.ts.map +1 -1
  147. package/dist/skill-loader.js +51 -48
  148. package/dist/skill-loader.js.map +1 -1
  149. package/dist/skill-manager.d.ts +85 -0
  150. package/dist/skill-manager.d.ts.map +1 -0
  151. package/dist/skill-manager.js +341 -0
  152. package/dist/skill-manager.js.map +1 -0
  153. package/dist/slash-commands.d.ts +39 -2
  154. package/dist/slash-commands.d.ts.map +1 -1
  155. package/dist/slash-commands.js +934 -305
  156. package/dist/slash-commands.js.map +1 -1
  157. package/dist/smart-approval.d.ts +20 -1
  158. package/dist/smart-approval.d.ts.map +1 -1
  159. package/dist/smart-approval.js +125 -56
  160. package/dist/smart-approval.js.map +1 -1
  161. package/dist/system-prompt-generator.d.ts +6 -0
  162. package/dist/system-prompt-generator.d.ts.map +1 -1
  163. package/dist/system-prompt-generator.js +86 -36
  164. package/dist/system-prompt-generator.js.map +1 -1
  165. package/dist/terminal.d.ts +28 -0
  166. package/dist/terminal.d.ts.map +1 -0
  167. package/dist/terminal.js +82 -0
  168. package/dist/terminal.js.map +1 -0
  169. package/dist/theme.d.ts.map +1 -1
  170. package/dist/theme.js +8 -7
  171. package/dist/theme.js.map +1 -1
  172. package/dist/tools.d.ts +38 -7
  173. package/dist/tools.d.ts.map +1 -1
  174. package/dist/tools.js +1249 -617
  175. package/dist/tools.js.map +1 -1
  176. package/dist/truncate.d.ts +55 -0
  177. package/dist/truncate.d.ts.map +1 -0
  178. package/dist/truncate.js +130 -0
  179. package/dist/truncate.js.map +1 -0
  180. package/dist/types.d.ts +84 -9
  181. package/dist/types.d.ts.map +1 -1
  182. package/dist/types.js +49 -0
  183. package/dist/types.js.map +1 -1
  184. package/dist/update.d.ts.map +1 -1
  185. package/dist/update.js +28 -36
  186. package/dist/update.js.map +1 -1
  187. package/dist/workflow.d.ts +5 -1
  188. package/dist/workflow.d.ts.map +1 -1
  189. package/dist/workflow.js +61 -49
  190. package/dist/workflow.js.map +1 -1
  191. package/docs/architecture/mcp-integration-guide.md +304 -194
  192. package/docs/architecture/overview.md +169 -169
  193. package/docs/architecture/tool-system-design.md +134 -134
  194. package/docs/cli/commands.md +349 -238
  195. package/docs/smart-mode.md +281 -281
  196. package/docs/third-party-models.md +440 -439
  197. package/find-skills/SKILL.md +133 -0
  198. package/package.json +91 -90
  199. package/scripts/install-ripgrep.js +241 -0
  200. package/src/agents.ts +7 -3
  201. package/src/ai-client/factory.ts +116 -0
  202. package/src/ai-client/index.ts +61 -0
  203. package/src/ai-client/providers/anthropic.ts +475 -0
  204. package/src/ai-client/providers/openai.ts +348 -0
  205. package/src/ai-client/providers/remote.ts +439 -0
  206. package/src/ai-client/registry.ts +97 -0
  207. package/src/ai-client/types.ts +364 -0
  208. package/src/ai-client-factory.ts +204 -0
  209. package/src/auth.ts +661 -614
  210. package/src/cancellation.ts +202 -176
  211. package/src/checkpoint.ts +255 -219
  212. package/src/cli.ts +1523 -743
  213. package/src/config.ts +341 -297
  214. package/src/context-compressor.ts +987 -290
  215. package/src/conversation.ts +290 -288
  216. package/src/gui-subagent/action-parser/actionParser.ts +318 -315
  217. package/src/gui-subagent/action-parser/constants.ts +14 -14
  218. package/src/gui-subagent/action-parser/index.ts +8 -8
  219. package/src/gui-subagent/action-parser/types.ts +31 -31
  220. package/src/gui-subagent/agent/gui-agent.ts +1234 -1089
  221. package/src/gui-subagent/agent/index.ts +5 -5
  222. package/src/gui-subagent/index.ts +185 -163
  223. package/src/gui-subagent/operator/base-operator.ts +244 -245
  224. package/src/gui-subagent/operator/computer-operator.ts +541 -520
  225. package/src/gui-subagent/operator/index.ts +6 -6
  226. package/src/gui-subagent/types/actions.ts +260 -262
  227. package/src/gui-subagent/types/index.ts +6 -6
  228. package/src/gui-subagent/types/operator.ts +106 -106
  229. package/src/gui-subagent/utils.ts +51 -51
  230. package/src/index.ts +17 -18
  231. package/src/input-processor.ts +8 -5
  232. package/src/logger.ts +436 -438
  233. package/src/mcp.ts +793 -682
  234. package/src/memory.ts +343 -344
  235. package/src/output-util.ts +80 -0
  236. package/src/retry.ts +1 -1
  237. package/src/ripgrep.ts +370 -0
  238. package/src/sdk-output-adapter.ts +842 -0
  239. package/src/sdk-session.ts +62 -0
  240. package/src/session-manager.ts +308 -308
  241. package/src/session.ts +1775 -573
  242. package/src/shell.ts +134 -0
  243. package/src/skill-installer.ts +518 -0
  244. package/src/skill-invoker.ts +959 -935
  245. package/src/skill-loader.ts +501 -496
  246. package/src/skill-manager.ts +385 -0
  247. package/src/slash-commands.ts +2189 -1389
  248. package/src/smart-approval.ts +193 -74
  249. package/src/system-prompt-generator.ts +91 -36
  250. package/src/terminal.ts +96 -0
  251. package/src/theme.ts +739 -738
  252. package/src/tools.ts +1790 -931
  253. package/src/truncate.ts +173 -0
  254. package/src/types.ts +337 -198
  255. package/src/update.ts +33 -40
  256. package/src/workflow.ts +521 -508
  257. package/test/cli-launch.test.ts +279 -0
  258. package/tsconfig.json +22 -22
  259. package/vitest.config.ts +21 -19
  260. package/dist/ai-client.d.ts +0 -86
  261. package/dist/ai-client.d.ts.map +0 -1
  262. package/dist/ai-client.js +0 -1372
  263. package/dist/ai-client.js.map +0 -1
  264. package/dist/gui-subagent/operator/browser-operator.d.ts +0 -36
  265. package/dist/gui-subagent/operator/browser-operator.d.ts.map +0 -1
  266. package/dist/gui-subagent/operator/browser-operator.js +0 -306
  267. package/dist/gui-subagent/operator/browser-operator.js.map +0 -1
  268. package/dist/gui-subagent/operator/desktop-operator.d.ts +0 -55
  269. package/dist/gui-subagent/operator/desktop-operator.d.ts.map +0 -1
  270. package/dist/gui-subagent/operator/desktop-operator.js +0 -527
  271. package/dist/gui-subagent/operator/desktop-operator.js.map +0 -1
  272. package/dist/hook.d.ts +0 -73
  273. package/dist/hook.d.ts.map +0 -1
  274. package/dist/hook.js +0 -156
  275. package/dist/hook.js.map +0 -1
  276. package/dist/input-history.d.ts +0 -24
  277. package/dist/input-history.d.ts.map +0 -1
  278. package/dist/input-history.js +0 -94
  279. package/dist/input-history.js.map +0 -1
  280. package/dist/keyboard-manager.d.ts +0 -151
  281. package/dist/keyboard-manager.d.ts.map +0 -1
  282. package/dist/keyboard-manager.js +0 -396
  283. package/dist/keyboard-manager.js.map +0 -1
  284. package/dist/print-system-prompt.d.ts +0 -2
  285. package/dist/print-system-prompt.d.ts.map +0 -1
  286. package/dist/print-system-prompt.js +0 -40
  287. package/dist/print-system-prompt.js.map +0 -1
  288. package/dist/remote-ai-client.d.ts +0 -104
  289. package/dist/remote-ai-client.d.ts.map +0 -1
  290. package/dist/remote-ai-client.js +0 -552
  291. package/dist/remote-ai-client.js.map +0 -1
  292. package/dist/sdk-session-v2.d.ts +0 -13
  293. package/dist/sdk-session-v2.d.ts.map +0 -1
  294. package/dist/sdk-session-v2.js +0 -46
  295. package/dist/sdk-session-v2.js.map +0 -1
  296. package/dist/test-boundary-conditions.d.ts.map +0 -1
  297. package/dist/test-boundary-conditions.js.map +0 -1
  298. package/dist/test-cancellation-fix.d.ts.map +0 -1
  299. package/dist/test-cancellation-fix.js.map +0 -1
  300. package/dist/test-input-history.d.ts.map +0 -1
  301. package/dist/test-input-history.js.map +0 -1
  302. package/dist/test-interaction-flow.d.ts.map +0 -1
  303. package/dist/test-interaction-flow.js.map +0 -1
  304. package/dist/test-quick.d.ts.map +0 -1
  305. package/dist/test-quick.js.map +0 -1
  306. package/dist/test-user-interaction.d.ts.map +0 -1
  307. package/dist/test-user-interaction.js.map +0 -1
  308. package/dist/tools/edit-diff.d.ts +0 -32
  309. package/dist/tools/edit-diff.d.ts.map +0 -1
  310. package/dist/tools/edit-diff.js +0 -185
  311. package/dist/tools/edit-diff.js.map +0 -1
  312. package/dist/tools/edit.d.ts +0 -11
  313. package/dist/tools/edit.d.ts.map +0 -1
  314. package/dist/tools/edit.js +0 -129
  315. package/dist/tools/edit.js.map +0 -1
  316. package/dist/unified-session.d.ts +0 -42
  317. package/dist/unified-session.d.ts.map +0 -1
  318. package/dist/unified-session.js +0 -271
  319. package/dist/unified-session.js.map +0 -1
  320. package/skills/.claude-plugin/marketplace.json +0 -45
  321. package/skills/README.md +0 -94
  322. package/skills/THIRD_PARTY_NOTICES.md +0 -405
  323. package/skills/skills/algorithmic-art/LICENSE.txt +0 -202
  324. package/skills/skills/algorithmic-art/SKILL.md +0 -405
  325. package/skills/skills/algorithmic-art/templates/generator_template.js +0 -223
  326. package/skills/skills/algorithmic-art/templates/viewer.html +0 -599
  327. package/skills/skills/brand-guidelines/LICENSE.txt +0 -202
  328. package/skills/skills/brand-guidelines/SKILL.md +0 -73
  329. package/skills/skills/canvas-design/LICENSE.txt +0 -202
  330. package/skills/skills/canvas-design/SKILL.md +0 -130
  331. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
  332. package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  333. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  334. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
  335. package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  336. package/skills/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
  337. package/skills/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  338. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  339. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
  340. package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  341. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  342. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  343. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
  344. package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  345. package/skills/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
  346. package/skills/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  347. package/skills/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
  348. package/skills/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  349. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  350. package/skills/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
  351. package/skills/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  352. package/skills/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
  353. package/skills/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  354. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  355. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
  356. package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  357. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  358. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  359. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  360. package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  361. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  362. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  363. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  364. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
  365. package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  366. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  367. package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  368. package/skills/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
  369. package/skills/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  370. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  371. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
  372. package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  373. package/skills/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  374. package/skills/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  375. package/skills/skills/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
  376. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
  377. package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  378. package/skills/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  379. package/skills/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  380. package/skills/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  381. package/skills/skills/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
  382. package/skills/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  383. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  384. package/skills/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
  385. package/skills/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  386. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
  387. package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  388. package/skills/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  389. package/skills/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
  390. package/skills/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  391. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  392. package/skills/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
  393. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
  394. package/skills/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  395. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  396. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
  397. package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  398. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
  399. package/skills/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  400. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  401. package/skills/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
  402. package/skills/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  403. package/skills/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
  404. package/skills/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  405. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  406. package/skills/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  407. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  408. package/skills/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
  409. package/skills/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  410. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
  411. package/skills/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  412. package/skills/skills/doc-coauthoring/SKILL.md +0 -375
  413. package/skills/skills/docx/LICENSE.txt +0 -30
  414. package/skills/skills/docx/SKILL.md +0 -197
  415. package/skills/skills/docx/docx-js.md +0 -350
  416. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  417. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  418. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  419. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  420. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  421. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  422. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  423. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  424. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  425. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  426. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  427. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  428. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  429. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  430. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  431. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  432. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  433. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  434. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  435. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  436. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  437. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  438. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  439. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  440. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  441. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  442. package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  443. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  444. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  445. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  446. package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  447. package/skills/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
  448. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  449. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  450. package/skills/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  451. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  452. package/skills/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  453. package/skills/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  454. package/skills/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  455. package/skills/skills/docx/ooxml/scripts/pack.py +0 -159
  456. package/skills/skills/docx/ooxml/scripts/unpack.py +0 -29
  457. package/skills/skills/docx/ooxml/scripts/validate.py +0 -69
  458. package/skills/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
  459. package/skills/skills/docx/ooxml/scripts/validation/base.py +0 -951
  460. package/skills/skills/docx/ooxml/scripts/validation/docx.py +0 -274
  461. package/skills/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
  462. package/skills/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
  463. package/skills/skills/docx/ooxml.md +0 -610
  464. package/skills/skills/docx/scripts/__init__.py +0 -1
  465. package/skills/skills/docx/scripts/document.py +0 -1276
  466. package/skills/skills/docx/scripts/templates/comments.xml +0 -3
  467. package/skills/skills/docx/scripts/templates/commentsExtended.xml +0 -3
  468. package/skills/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
  469. package/skills/skills/docx/scripts/templates/commentsIds.xml +0 -3
  470. package/skills/skills/docx/scripts/templates/people.xml +0 -3
  471. package/skills/skills/docx/scripts/utilities.py +0 -374
  472. package/skills/skills/frontend-design/LICENSE.txt +0 -177
  473. package/skills/skills/frontend-design/SKILL.md +0 -42
  474. package/skills/skills/internal-comms/LICENSE.txt +0 -202
  475. package/skills/skills/internal-comms/SKILL.md +0 -32
  476. package/skills/skills/internal-comms/examples/3p-updates.md +0 -47
  477. package/skills/skills/internal-comms/examples/company-newsletter.md +0 -65
  478. package/skills/skills/internal-comms/examples/faq-answers.md +0 -30
  479. package/skills/skills/internal-comms/examples/general-comms.md +0 -16
  480. package/skills/skills/mcp-builder/LICENSE.txt +0 -202
  481. package/skills/skills/mcp-builder/SKILL.md +0 -236
  482. package/skills/skills/mcp-builder/reference/evaluation.md +0 -602
  483. package/skills/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  484. package/skills/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  485. package/skills/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  486. package/skills/skills/mcp-builder/scripts/connections.py +0 -151
  487. package/skills/skills/mcp-builder/scripts/evaluation.py +0 -373
  488. package/skills/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  489. package/skills/skills/mcp-builder/scripts/requirements.txt +0 -2
  490. package/skills/skills/pdf/LICENSE.txt +0 -30
  491. package/skills/skills/pdf/SKILL.md +0 -294
  492. package/skills/skills/pdf/forms.md +0 -205
  493. package/skills/skills/pdf/reference.md +0 -612
  494. package/skills/skills/pdf/scripts/check_bounding_boxes.py +0 -70
  495. package/skills/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
  496. package/skills/skills/pdf/scripts/check_fillable_fields.py +0 -12
  497. package/skills/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
  498. package/skills/skills/pdf/scripts/create_validation_image.py +0 -41
  499. package/skills/skills/pdf/scripts/extract_form_field_info.py +0 -152
  500. package/skills/skills/pdf/scripts/fill_fillable_fields.py +0 -114
  501. package/skills/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
  502. package/skills/skills/pptx/LICENSE.txt +0 -30
  503. package/skills/skills/pptx/SKILL.md +0 -484
  504. package/skills/skills/pptx/html2pptx.md +0 -625
  505. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  506. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  507. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  508. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  509. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  510. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  511. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  512. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  513. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  514. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  515. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  516. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  517. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  518. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  519. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  520. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  521. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  522. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  523. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  524. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  525. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  526. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  527. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  528. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  529. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  530. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  531. package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  532. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  533. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  534. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  535. package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  536. package/skills/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
  537. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  538. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  539. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  540. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  541. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  542. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  543. package/skills/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  544. package/skills/skills/pptx/ooxml/scripts/pack.py +0 -159
  545. package/skills/skills/pptx/ooxml/scripts/unpack.py +0 -29
  546. package/skills/skills/pptx/ooxml/scripts/validate.py +0 -69
  547. package/skills/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
  548. package/skills/skills/pptx/ooxml/scripts/validation/base.py +0 -951
  549. package/skills/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
  550. package/skills/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
  551. package/skills/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
  552. package/skills/skills/pptx/ooxml.md +0 -427
  553. package/skills/skills/pptx/scripts/html2pptx.js +0 -979
  554. package/skills/skills/pptx/scripts/inventory.py +0 -1020
  555. package/skills/skills/pptx/scripts/rearrange.py +0 -231
  556. package/skills/skills/pptx/scripts/replace.py +0 -385
  557. package/skills/skills/pptx/scripts/thumbnail.py +0 -450
  558. package/skills/skills/skill-creator/LICENSE.txt +0 -202
  559. package/skills/skills/skill-creator/SKILL.md +0 -356
  560. package/skills/skills/skill-creator/references/output-patterns.md +0 -82
  561. package/skills/skills/skill-creator/references/workflows.md +0 -28
  562. package/skills/skills/skill-creator/scripts/init_skill.py +0 -303
  563. package/skills/skills/skill-creator/scripts/package_skill.py +0 -110
  564. package/skills/skills/skill-creator/scripts/quick_validate.py +0 -95
  565. package/skills/skills/slack-gif-creator/LICENSE.txt +0 -202
  566. package/skills/skills/slack-gif-creator/SKILL.md +0 -254
  567. package/skills/skills/slack-gif-creator/core/easing.py +0 -234
  568. package/skills/skills/slack-gif-creator/core/frame_composer.py +0 -176
  569. package/skills/skills/slack-gif-creator/core/gif_builder.py +0 -269
  570. package/skills/skills/slack-gif-creator/core/validators.py +0 -136
  571. package/skills/skills/slack-gif-creator/requirements.txt +0 -4
  572. package/skills/skills/theme-factory/LICENSE.txt +0 -202
  573. package/skills/skills/theme-factory/SKILL.md +0 -59
  574. package/skills/skills/theme-factory/theme-showcase.pdf +0 -0
  575. package/skills/skills/theme-factory/themes/arctic-frost.md +0 -19
  576. package/skills/skills/theme-factory/themes/botanical-garden.md +0 -19
  577. package/skills/skills/theme-factory/themes/desert-rose.md +0 -19
  578. package/skills/skills/theme-factory/themes/forest-canopy.md +0 -19
  579. package/skills/skills/theme-factory/themes/golden-hour.md +0 -19
  580. package/skills/skills/theme-factory/themes/midnight-galaxy.md +0 -19
  581. package/skills/skills/theme-factory/themes/modern-minimalist.md +0 -19
  582. package/skills/skills/theme-factory/themes/ocean-depths.md +0 -19
  583. package/skills/skills/theme-factory/themes/sunset-boulevard.md +0 -19
  584. package/skills/skills/theme-factory/themes/tech-innovation.md +0 -19
  585. package/skills/skills/web-artifacts-builder/LICENSE.txt +0 -202
  586. package/skills/skills/web-artifacts-builder/SKILL.md +0 -74
  587. package/skills/skills/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
  588. package/skills/skills/web-artifacts-builder/scripts/init-artifact.sh +0 -322
  589. package/skills/skills/webapp-testing/LICENSE.txt +0 -202
  590. package/skills/skills/webapp-testing/SKILL.md +0 -96
  591. package/skills/skills/webapp-testing/examples/console_logging.py +0 -35
  592. package/skills/skills/webapp-testing/examples/element_discovery.py +0 -40
  593. package/skills/skills/webapp-testing/examples/static_html_automation.py +0 -33
  594. package/skills/skills/webapp-testing/scripts/with_server.py +0 -106
  595. package/skills/skills/xlsx/LICENSE.txt +0 -30
  596. package/skills/skills/xlsx/SKILL.md +0 -289
  597. package/skills/skills/xlsx/recalc.py +0 -178
  598. package/skills/spec/agent-skills-spec.md +0 -3
  599. package/skills/template/SKILL.md +0 -6
  600. package/src/ai-client.ts +0 -1560
  601. package/src/remote-ai-client.ts +0 -664
  602. /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
@@ -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)