procesio-cli 0.1.1__py3-none-any.whl

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 (647) hide show
  1. procesio_cli/__init__.py +18 -0
  2. procesio_cli/_cli.py +71 -0
  3. procesio_cli/agents/__init__.py +0 -0
  4. procesio_cli/agents/_lib/__init__.py +0 -0
  5. procesio_cli/agents/_lib/actiondef.py +24 -0
  6. procesio_cli/agents/_lib/errors.py +40 -0
  7. procesio_cli/agents/_lib/reversibility.py +236 -0
  8. procesio_cli/agents/_lib/toolrunner.py +141 -0
  9. procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-PLAYBOOK.md +62 -0
  10. procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-PROCESIO-INTEROP.md +76 -0
  11. procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-TROUBLESHOOTING.md +60 -0
  12. procesio_cli/agents/connector-builder/README.md +51 -0
  13. procesio_cli/agents/connector-builder/agent.yaml +61 -0
  14. procesio_cli/agents/connector-builder/context.py +19 -0
  15. procesio_cli/agents/connector-builder/handlers/__init__.py +1 -0
  16. procesio_cli/agents/connector-builder/handlers/checklist.py +71 -0
  17. procesio_cli/agents/connector-builder/handlers/guidance.py +37 -0
  18. procesio_cli/agents/connector-builder/handlers/nextstep.py +221 -0
  19. procesio_cli/agents/connector-builder/handlers/status.py +35 -0
  20. procesio_cli/agents/connector-builder/knowledge.py +47 -0
  21. procesio_cli/agents/connector-builder/main.py +93 -0
  22. procesio_cli/agents/connector-builder/tests/conftest.py +95 -0
  23. procesio_cli/agents/connector-builder/tests/test_cba_agent.py +148 -0
  24. procesio_cli/agents/orchestrator/__init__.py +0 -0
  25. procesio_cli/agents/orchestrator/bootstraplib.py +166 -0
  26. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/00-INDEX.md +60 -0
  27. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/01-PROCESSES.md +230 -0
  28. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/02-FORMS.md +287 -0
  29. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/03-INTEGRATIONS.md +384 -0
  30. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/04-DATABASE.md +293 -0
  31. procesio_cli/agents/procesio/PROCESIO-API-RELIABILITY-DOCTRINE.md +113 -0
  32. procesio_cli/agents/procesio/PROCESIO-BEST-PRACTICES.md +316 -0
  33. procesio_cli/agents/procesio/PROCESIO-BUILD-AND-TEST-PLAYBOOK.md +217 -0
  34. procesio_cli/agents/procesio/PROCESIO-DATASTORE.md +72 -0
  35. procesio_cli/agents/procesio/PROCESIO-ENVIRONMENTS.md +62 -0
  36. procesio_cli/agents/procesio/PROCESIO-SCHEDULING.md +47 -0
  37. procesio_cli/agents/procesio/PROCESIO-VISUAL-ORGANIZATION.md +175 -0
  38. procesio_cli/agents/procesio/README.md +97 -0
  39. procesio_cli/agents/procesio/__init__.py +0 -0
  40. procesio_cli/agents/procesio/agent.yaml +73 -0
  41. procesio_cli/agents/procesio/audit.py +226 -0
  42. procesio_cli/agents/procesio/checklist.py +135 -0
  43. procesio_cli/agents/procesio/context.py +19 -0
  44. procesio_cli/agents/procesio/handlers/__init__.py +0 -0
  45. procesio_cli/agents/procesio/handlers/audit.py +39 -0
  46. procesio_cli/agents/procesio/handlers/checklist.py +34 -0
  47. procesio_cli/agents/procesio/handlers/guidance.py +36 -0
  48. procesio_cli/agents/procesio/handlers/status.py +33 -0
  49. procesio_cli/agents/procesio/handlers/verify.py +39 -0
  50. procesio_cli/agents/procesio/knowledge.py +115 -0
  51. procesio_cli/agents/procesio/main.py +89 -0
  52. procesio_cli/agents/procesio/tests/__init__.py +0 -0
  53. procesio_cli/agents/procesio/tests/conftest.py +62 -0
  54. procesio_cli/agents/procesio/tests/test_audit.py +91 -0
  55. procesio_cli/agents/procesio/tests/test_checklist.py +28 -0
  56. procesio_cli/agents/procesio/tests/test_guidance.py +78 -0
  57. procesio_cli/agents/procesio/tests/test_manifest_sync.py +48 -0
  58. procesio_cli/agents/procesio/tests/test_verify.py +134 -0
  59. procesio_cli/agents/procesio/tests/test_workspace_scope.py +97 -0
  60. procesio_cli/agents/procesio/verifylib.py +222 -0
  61. procesio_cli/dashboard/README.md +117 -0
  62. procesio_cli/dashboard/__init__.py +18 -0
  63. procesio_cli/dashboard/serve.py +98 -0
  64. procesio_cli/dashboard/server/__init__.py +1 -0
  65. procesio_cli/dashboard/server/config_schemas.py +92 -0
  66. procesio_cli/dashboard/server/google.py +103 -0
  67. procesio_cli/dashboard/server/handler.py +160 -0
  68. procesio_cli/dashboard/server/inventory.py +213 -0
  69. procesio_cli/dashboard/server/jobs.py +118 -0
  70. procesio_cli/dashboard/server/llmtest.py +181 -0
  71. procesio_cli/dashboard/server/procesio_env.py +94 -0
  72. procesio_cli/dashboard/server/routes.py +74 -0
  73. procesio_cli/dashboard/server/runner.py +150 -0
  74. procesio_cli/dashboard/server/security.py +29 -0
  75. procesio_cli/dashboard/server/setup.py +211 -0
  76. procesio_cli/dashboard/server/validate.py +152 -0
  77. procesio_cli/dashboard/tests/conftest.py +16 -0
  78. procesio_cli/dashboard/tests/test_dashboard.py +225 -0
  79. procesio_cli/dashboard/tests/test_procesio_env.py +159 -0
  80. procesio_cli/dashboard/web/actions.js +274 -0
  81. procesio_cli/dashboard/web/api.js +79 -0
  82. procesio_cli/dashboard/web/app.js +385 -0
  83. procesio_cli/dashboard/web/copilot.js +72 -0
  84. procesio_cli/dashboard/web/google.js +121 -0
  85. procesio_cli/dashboard/web/index.html +67 -0
  86. procesio_cli/dashboard/web/procesio_env.js +187 -0
  87. procesio_cli/dashboard/web/styles.css +207 -0
  88. procesio_cli/registry.py +370 -0
  89. procesio_cli/scripts/build-router.py +249 -0
  90. procesio_cli/scripts/build-tool-skill.py +202 -0
  91. procesio_cli/scripts/check-requirements.py +131 -0
  92. procesio_cli/scripts/check-skill-governance.py +174 -0
  93. procesio_cli/scripts/evaluate-skill-routing.py +217 -0
  94. procesio_cli/scripts/evaluate-skills.py +316 -0
  95. procesio_cli/scripts/get-skill.py +122 -0
  96. procesio_cli/scripts/list-skills.py +68 -0
  97. procesio_cli/scripts/list-tools.py +73 -0
  98. procesio_cli/scripts/run-agent.py +59 -0
  99. procesio_cli/scripts/run-tool.py +123 -0
  100. procesio_cli/scripts/secret_scan.py +584 -0
  101. procesio_cli/scripts/set-credential.py +126 -0
  102. procesio_cli/scripts/validate-skills.py +530 -0
  103. procesio_cli/skills/PORTFOLIO.md +134 -0
  104. procesio_cli/skills/__init__.py +6 -0
  105. procesio_cli/skills/agent-skill-engineer/SKILL.md +226 -0
  106. procesio_cli/skills/agent-skill-engineer/evals/evals.json +422 -0
  107. procesio_cli/skills/agent-skill-engineer/references/authoring-standard.md +178 -0
  108. procesio_cli/skills/agent-skill-engineer/references/decision-framework.md +107 -0
  109. procesio_cli/skills/agent-skill-engineer/references/domain-evidence-protocol.md +248 -0
  110. procesio_cli/skills/agent-skill-engineer/references/evaluation-standard.md +191 -0
  111. procesio_cli/skills/agent-skill-engineer/references/expert-lenses.md +167 -0
  112. procesio_cli/skills/agent-skill-engineer/references/field-gate-standard.md +231 -0
  113. procesio_cli/skills/agent-skill-engineer/references/optimization-protocol.md +233 -0
  114. procesio_cli/skills/agent-skill-engineer/references/optimizer-contract.md +268 -0
  115. procesio_cli/skills/agent-skill-engineer/references/portability-standard.md +99 -0
  116. procesio_cli/skills/agent-skill-engineer/references/research-basis.md +128 -0
  117. procesio_cli/skills/agent-skill-engineer/references/review-standard.md +143 -0
  118. procesio_cli/skills/agent-skill-engineer/scripts/audit_skill.py +959 -0
  119. procesio_cli/skills/agent-skill-engineer/scripts/optimize_skill.py +891 -0
  120. procesio_cli/skills/agent-skill-engineer/scripts/scaffold_skill.py +397 -0
  121. procesio_cli/skills/evals/baseline-catalog.json +14 -0
  122. procesio_cli/skills/evals/baseline-routing-v2.json +38 -0
  123. procesio_cli/skills/evals/baseline.json +37 -0
  124. procesio_cli/skills/evals/behavioral.json +367 -0
  125. procesio_cli/skills/evals/field-boundary-development-v1.json +126 -0
  126. procesio_cli/skills/evals/field-closeout-correction-development-v1.json +23 -0
  127. procesio_cli/skills/evals/field-closeout-development-v1.json +89 -0
  128. procesio_cli/skills/evals/portfolio-pressure-training-v1.json +83 -0
  129. procesio_cli/skills/evals/routing.json +363 -0
  130. procesio_cli/skills/evals/validation-baseline.json +4 -0
  131. procesio_cli/skills/procesio-cli/SKILL.md +134 -0
  132. procesio_cli/skills/procesio-cli/evals/evals.json +111 -0
  133. procesio_cli/skills/procesio-cli/evals/workflows.json +16 -0
  134. procesio_cli/skills/procesio-cli/references/connector-lifecycle.md +47 -0
  135. procesio_cli/skills/procesio-cli/references/credentials-admin.md +113 -0
  136. procesio_cli/skills/procesio-cli/references/data-verification.md +71 -0
  137. procesio_cli/skills/procesio-cli/references/documents-files.md +44 -0
  138. procesio_cli/skills/procesio-cli/references/form-e2e.md +57 -0
  139. procesio_cli/skills/procesio-cli/references/operation-contract.md +138 -0
  140. procesio_cli/skills/procesio-cli/references/process-debugging.md +65 -0
  141. procesio_cli/skills/procesio-cli/references/process-lifecycle.md +88 -0
  142. procesio_cli/skills/procesio-cli/references/schedules-webhooks.md +58 -0
  143. procesio_cli/skills/procesio-cli/references/transport-environments.md +53 -0
  144. procesio_cli/skills/procesio-cli-maintainer/SKILL.md +84 -0
  145. procesio_cli/skills/procesio-cli-maintainer/evals/evals.json +116 -0
  146. procesio_cli/skills/procesio-cli-maintainer/references/change-contract.md +34 -0
  147. procesio_cli/skills/procesio-cli-maintainer/references/mcp-compatibility.md +13 -0
  148. procesio_cli/skills/procesio-cli-maintainer/references/skill-authoring.md +51 -0
  149. procesio_cli/skills/procesio-platform-advisor/SKILL.md +82 -0
  150. procesio_cli/skills/procesio-platform-advisor/evals/evals.json +116 -0
  151. procesio_cli/skills/procesio-platform-advisor/references/capability-map.md +22 -0
  152. procesio_cli/skills/procesio-platform-advisor/references/fit-framework.md +35 -0
  153. procesio_cli/skills/procesio-platform-advisor/references/freshness-policy.md +25 -0
  154. procesio_cli/skills/procesio-platform-advisor/references/sizing-method.md +70 -0
  155. procesio_cli/skills/procesio-platform-advisor/scripts/estimate_capacity.py +99 -0
  156. procesio_cli/skills/procesio-setup/SKILL.md +180 -0
  157. procesio_cli/skills/sql-server-optimizer/SKILL.md +86 -0
  158. procesio_cli/skills/sql-server-optimizer/evals/evals.json +116 -0
  159. procesio_cli/skills/sql-server-optimizer/references/db-context.md +44 -0
  160. procesio_cli/skills/sql-server-optimizer/references/generic-mode.md +32 -0
  161. procesio_cli/skills/sql-server-optimizer/references/procesio-mode.md +40 -0
  162. procesio_cli/skills/sql-server-optimizer/references/sql-rules.md +43 -0
  163. procesio_cli/skills/sql-server-optimizer/scripts/export-indexes.sql +178 -0
  164. procesio_cli/skills/sql-server-optimizer/scripts/export-procs-and-functions.sql +118 -0
  165. procesio_cli/skills/sql-server-optimizer/scripts/export-tables.sql +367 -0
  166. procesio_cli/skills/tests/__init__.py +0 -0
  167. procesio_cli/skills/tests/test_agent_skill_engineer.py +240 -0
  168. procesio_cli/skills/tests/test_auth_failure_stop.py +25 -0
  169. procesio_cli/skills/tests/test_capacity_estimator.py +85 -0
  170. procesio_cli/skills/tests/test_field_boundary_learning.py +100 -0
  171. procesio_cli/skills/tests/test_field_closeout_learning.py +123 -0
  172. procesio_cli/skills/tests/test_field_gate_standard.py +76 -0
  173. procesio_cli/skills/tests/test_operational_playbooks.py +51 -0
  174. procesio_cli/skills/tests/test_portfolio_pressure_training.py +35 -0
  175. procesio_cli/skills/tests/test_process_lifecycle_single_run.py +25 -0
  176. procesio_cli/skills/tests/test_skill_evaluator.py +67 -0
  177. procesio_cli/skills/tests/test_skill_optimizer.py +473 -0
  178. procesio_cli/skills/tests/test_skill_portfolio_review.py +70 -0
  179. procesio_cli/skills/tests/test_skill_release_binding.py +204 -0
  180. procesio_cli/skills/tests/test_skill_routing.py +74 -0
  181. procesio_cli/skills/tests/test_skill_scaffold_v2.py +116 -0
  182. procesio_cli/skills/tests/test_validate_skills.py +115 -0
  183. procesio_cli/tools/__init__.py +0 -0
  184. procesio_cli/tools/_lib/README.md +119 -0
  185. procesio_cli/tools/_lib/__init__.py +0 -0
  186. procesio_cli/tools/_lib/accounting.py +120 -0
  187. procesio_cli/tools/_lib/contacts.py +544 -0
  188. procesio_cli/tools/_lib/creds.py +83 -0
  189. procesio_cli/tools/_lib/creds_backends.py +578 -0
  190. procesio_cli/tools/_lib/dbprofiles.py +147 -0
  191. procesio_cli/tools/_lib/dbquery.py +286 -0
  192. procesio_cli/tools/_lib/dbschema.py +225 -0
  193. procesio_cli/tools/_lib/io.py +54 -0
  194. procesio_cli/tools/_lib/manifest.py +297 -0
  195. procesio_cli/tools/_lib/skill_release.py +127 -0
  196. procesio_cli/tools/_lib/skill_resources.py +118 -0
  197. procesio_cli/tools/_lib/userdata.py +228 -0
  198. procesio_cli/tools/_lib/webserialize/__init__.py +16 -0
  199. procesio_cli/tools/_lib/webserialize/admin.py +61 -0
  200. procesio_cli/tools/_lib/webserialize/client.py +264 -0
  201. procesio_cli/tools/_lib/webserialize/config.py +96 -0
  202. procesio_cli/tools/_lib/webserialize/errors.py +27 -0
  203. procesio_cli/tools/_lib/webserialize/framing.py +45 -0
  204. procesio_cli/tools/_lib/webserialize/registry.py +47 -0
  205. procesio_cli/tools/_lib/webserialize/runtime.py +61 -0
  206. procesio_cli/tools/_lib/webserialize/server.py +510 -0
  207. procesio_cli/tools/_lib/websession.py +194 -0
  208. procesio_cli/tools/connector-builder/CONNECTOR-BUILDER-API-NOTES.md +91 -0
  209. procesio_cli/tools/connector-builder/README.md +101 -0
  210. procesio_cli/tools/connector-builder/SKILL.md +248 -0
  211. procesio_cli/tools/connector-builder/__init__.py +7 -0
  212. procesio_cli/tools/connector-builder/actiondef.py +24 -0
  213. procesio_cli/tools/connector-builder/client.py +251 -0
  214. procesio_cli/tools/connector-builder/errors.py +44 -0
  215. procesio_cli/tools/connector-builder/gen_manifest.py +142 -0
  216. procesio_cli/tools/connector-builder/handlers/__init__.py +1 -0
  217. procesio_cli/tools/connector-builder/handlers/admin.py +182 -0
  218. procesio_cli/tools/connector-builder/handlers/auth.py +74 -0
  219. procesio_cli/tools/connector-builder/handlers/builds.py +396 -0
  220. procesio_cli/tools/connector-builder/handlers/common.py +104 -0
  221. procesio_cli/tools/connector-builder/handlers/files.py +111 -0
  222. procesio_cli/tools/connector-builder/handlers/raw.py +38 -0
  223. procesio_cli/tools/connector-builder/handlers/telemetry.py +39 -0
  224. procesio_cli/tools/connector-builder/main.py +94 -0
  225. procesio_cli/tools/connector-builder/tests/conftest.py +146 -0
  226. procesio_cli/tools/connector-builder/tests/test_cb_client.py +86 -0
  227. procesio_cli/tools/connector-builder/tests/test_cb_dispatch.py +105 -0
  228. procesio_cli/tools/connector-builder/tests/test_cb_manifest_sync.py +76 -0
  229. procesio_cli/tools/connector-builder/tests/test_cb_wait.py +123 -0
  230. procesio_cli/tools/connector-builder/tool.yaml +671 -0
  231. procesio_cli/tools/framework-map/.gitattributes +2 -0
  232. procesio_cli/tools/framework-map/README.md +98 -0
  233. procesio_cli/tools/framework-map/SKILL.md +30 -0
  234. procesio_cli/tools/framework-map/app.js +188 -0
  235. procesio_cli/tools/framework-map/fm_builder.py +476 -0
  236. procesio_cli/tools/framework-map/fm_catalog.py +19 -0
  237. procesio_cli/tools/framework-map/fm_ro_catalog.py +94 -0
  238. procesio_cli/tools/framework-map/fm_strings.py +101 -0
  239. procesio_cli/tools/framework-map/main.py +95 -0
  240. procesio_cli/tools/framework-map/styles.css +214 -0
  241. procesio_cli/tools/framework-map/tests/conftest.py +33 -0
  242. procesio_cli/tools/framework-map/tests/test_fm_build.py +126 -0
  243. procesio_cli/tools/framework-map/tests/test_fm_manifest_sync.py +63 -0
  244. procesio_cli/tools/framework-map/tests/test_fm_store_tree.py +75 -0
  245. procesio_cli/tools/framework-map/tool.yaml +61 -0
  246. procesio_cli/tools/mysql/MOVED-TO-CENTRAL.md +29 -0
  247. procesio_cli/tools/mysql/README.md +196 -0
  248. procesio_cli/tools/mysql/SKILL.md +37 -0
  249. procesio_cli/tools/mysql/__init__.py +0 -0
  250. procesio_cli/tools/mysql/connection.py +191 -0
  251. procesio_cli/tools/mysql/main.py +487 -0
  252. procesio_cli/tools/mysql/profiles.template.json +1 -0
  253. procesio_cli/tools/mysql/schema.py +434 -0
  254. procesio_cli/tools/mysql/tests/__init__.py +0 -0
  255. procesio_cli/tools/mysql/tests/conftest.py +21 -0
  256. procesio_cli/tools/mysql/tests/test_manifest_sync.py +68 -0
  257. procesio_cli/tools/mysql/tests/test_mysql.py +201 -0
  258. procesio_cli/tools/mysql/tests/test_mysql_schema.py +337 -0
  259. procesio_cli/tools/mysql/tool.yaml +112 -0
  260. procesio_cli/tools/procesio/DTO-SUBTOOLS-NOTE.md +360 -0
  261. procesio_cli/tools/procesio/FORM-DEV-GUIDE/00-INDEX.md +67 -0
  262. procesio_cli/tools/procesio/FORM-DEV-GUIDE/01-ANATOMY.md +209 -0
  263. procesio_cli/tools/procesio/FORM-DEV-GUIDE/02-CODE-INJECTION.md +309 -0
  264. procesio_cli/tools/procesio/FORM-DEV-GUIDE/03-DOM-CONTRACT.md +370 -0
  265. procesio_cli/tools/procesio/FORM-DEV-GUIDE/04-INTERACTION-RECIPES.md +600 -0
  266. procesio_cli/tools/procesio/FORM-DEV-GUIDE/05-STEPPER-AND-MOTION.md +426 -0
  267. procesio_cli/tools/procesio/FORM-DEV-GUIDE/06-PROCESS-INTEGRATION.md +347 -0
  268. procesio_cli/tools/procesio/FORM-DEV-GUIDE/07-DEPLOY-WORKFLOW.md +294 -0
  269. procesio_cli/tools/procesio/FORM-DEV-GUIDE/08-PITFALLS.md +569 -0
  270. procesio_cli/tools/procesio/FORM-DEV-GUIDE/09-NAVIGATION-AND-HOSTING.md +308 -0
  271. procesio_cli/tools/procesio/PHASE4-E2E-NOTES.md +594 -0
  272. procesio_cli/tools/procesio/PROCESIO-API-CORRECTIONS.md +295 -0
  273. procesio_cli/tools/procesio/PROCESIO-API-NOTES.md +6976 -0
  274. procesio_cli/tools/procesio/PROCESIO-AUTH-NOTES.md +226 -0
  275. procesio_cli/tools/procesio/PROCESIO-CARD-BUILD-NOTES.md +183 -0
  276. procesio_cli/tools/procesio/PROCESIO-CONNECTORS-NOTES.md +141 -0
  277. procesio_cli/tools/procesio/PROCESIO-CUSTOM-ACTION-NOTES.md +179 -0
  278. procesio_cli/tools/procesio/PROCESIO-DOCS-FIX-REPORT.md +123 -0
  279. procesio_cli/tools/procesio/PROCESIO-ENVIRONMENTS-NOTES.md +94 -0
  280. procesio_cli/tools/procesio/PROCESIO-FE-VALIDATION-NOTES.md +107 -0
  281. procesio_cli/tools/procesio/PROCESIO-FOREACH-NOTES.md +199 -0
  282. procesio_cli/tools/procesio/PROCESIO-FORM-API-HANG-NOTE.md +101 -0
  283. procesio_cli/tools/procesio/PROCESIO-FORM-SUBMISSION-NOTES.md +172 -0
  284. procesio_cli/tools/procesio/PROCESIO-HTML-TO-DOCX-NOTES.md +110 -0
  285. procesio_cli/tools/procesio/PROCESIO-INSTANCE-HISTORY-NOTES.md +242 -0
  286. procesio_cli/tools/procesio/PROCESIO-METERING-NOTES.md +201 -0
  287. procesio_cli/tools/procesio/PROCESIO-NODE-CODE-NOTES.md +279 -0
  288. procesio_cli/tools/procesio/PROCESIO-NODE-MODULE-WHITELIST.md +113 -0
  289. procesio_cli/tools/procesio/PROCESIO-PYTHON-ACTION-NOTES.md +165 -0
  290. procesio_cli/tools/procesio/PROCESIO-QUERY-STORE-NOTES.md +826 -0
  291. procesio_cli/tools/procesio/PROCESIO-RECONCILIATION-PATTERNS.md +104 -0
  292. procesio_cli/tools/procesio/PROCESIO-RESOURCE-MODEL-NOTES.md +1100 -0
  293. procesio_cli/tools/procesio/PROCESIO-SEND-EMAIL-CRED-OPTIONALITY.md +45 -0
  294. procesio_cli/tools/procesio/PROCESIO-SEND-EMAIL-NOTES.md +252 -0
  295. procesio_cli/tools/procesio/PROCESIO-SQL-ACTIONS-NOTES.md +284 -0
  296. procesio_cli/tools/procesio/PROCESIO-USAGE-GUIDE.md +219 -0
  297. procesio_cli/tools/procesio/README.md +341 -0
  298. procesio_cli/tools/procesio/SCHEDULE-INPUT-SECURITY-NOTES.md +63 -0
  299. procesio_cli/tools/procesio/SKILL.md +694 -0
  300. procesio_cli/tools/procesio/__init__.py +1 -0
  301. procesio_cli/tools/procesio/actiondef.py +27 -0
  302. procesio_cli/tools/procesio/assets/html2docx/html2docx.js +2155 -0
  303. procesio_cli/tools/procesio/auth.py +354 -0
  304. procesio_cli/tools/procesio/autogen.py +121 -0
  305. procesio_cli/tools/procesio/client.py +355 -0
  306. procesio_cli/tools/procesio/config.py +96 -0
  307. procesio_cli/tools/procesio/data/endpoints.json +2901 -0
  308. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/01-authentication.md +180 -0
  309. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/02-conventions.md +116 -0
  310. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/ANONYMOUS-SURFACE.md +51 -0
  311. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/README.md +104 -0
  312. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/SYMBOL-INDEX.md +444 -0
  313. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/03-auth-users-workspaces.md +731 -0
  314. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/04-processes.md +913 -0
  315. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/05-actions.md +605 -0
  316. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/06-files.md +237 -0
  317. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/07-forms-documents.md +985 -0
  318. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/08-credentials.md +532 -0
  319. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/09-datastore-datatypes.md +830 -0
  320. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/10-custom-urls.md +319 -0
  321. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/11-subscriptions-resources-analytics.md +455 -0
  322. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/12-webhooks-notifications-misc.md +519 -0
  323. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/13-realtime-signalr.md +153 -0
  324. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/99-internal-and-other-services.md +52 -0
  325. procesio_cli/tools/procesio/docs_info/FormBuilder mock.ts +5725 -0
  326. procesio_cli/tools/procesio/docs_info/Procesio Platform Actions.json +30219 -0
  327. procesio_cli/tools/procesio/docs_info/form-config-enums.ts +92 -0
  328. procesio_cli/tools/procesio/docs_info/form-theme.ts +1603 -0
  329. procesio_cli/tools/procesio/docs_info/process-validation-reference-1.md +2739 -0
  330. procesio_cli/tools/procesio/dto/__init__.py +13 -0
  331. procesio_cli/tools/procesio/dto/credential/builder.py +179 -0
  332. procesio_cli/tools/procesio/dto/credential/config.schema.json +19 -0
  333. procesio_cli/tools/procesio/dto/credential/description.md +193 -0
  334. procesio_cli/tools/procesio/dto/credential/fixtures/rest.config.json +11 -0
  335. procesio_cli/tools/procesio/dto/credential/fixtures/rest.dto.json +28 -0
  336. procesio_cli/tools/procesio/dto/credential/fixtures/rest.template.json +44 -0
  337. procesio_cli/tools/procesio/dto/credential/template.dto.json +16 -0
  338. procesio_cli/tools/procesio/dto/data/_refresh.py +147 -0
  339. procesio_cli/tools/procesio/dto/data/action_catalog.json +30825 -0
  340. procesio_cli/tools/procesio/dto/data/action_families.json +55 -0
  341. procesio_cli/tools/procesio/dto/data/platform_types.json +182 -0
  342. procesio_cli/tools/procesio/dto/datatype/builder.py +223 -0
  343. procesio_cli/tools/procesio/dto/datatype/config.schema.json +47 -0
  344. procesio_cli/tools/procesio/dto/datatype/description.md +85 -0
  345. procesio_cli/tools/procesio/dto/datatype/fixtures/customer.config.json +41 -0
  346. procesio_cli/tools/procesio/dto/datatype/fixtures/customer.dto.json +164 -0
  347. procesio_cli/tools/procesio/dto/datatype/template.dto.json +37 -0
  348. procesio_cli/tools/procesio/dto/document/builder.py +193 -0
  349. procesio_cli/tools/procesio/dto/document/config.schema.json +33 -0
  350. procesio_cli/tools/procesio/dto/document/description.md +124 -0
  351. procesio_cli/tools/procesio/dto/document/fixtures/invoice.config.json +16 -0
  352. procesio_cli/tools/procesio/dto/document/fixtures/invoice.dto.json +32 -0
  353. procesio_cli/tools/procesio/dto/document/template.dto.json +14 -0
  354. procesio_cli/tools/procesio/dto/form/FORM-STYLING-NOTES.md +142 -0
  355. procesio_cli/tools/procesio/dto/form/GOLDEN-DRIFT-NOTES.md +72 -0
  356. procesio_cli/tools/procesio/dto/form/RUN-PROCESS-RESULT-NOTES.md +80 -0
  357. procesio_cli/tools/procesio/dto/form/addelement.py +277 -0
  358. procesio_cli/tools/procesio/dto/form/builder.py +1009 -0
  359. procesio_cli/tools/procesio/dto/form/capture_goldens.py +106 -0
  360. procesio_cli/tools/procesio/dto/form/code_cipher.py +67 -0
  361. procesio_cli/tools/procesio/dto/form/config.schema.json +76 -0
  362. procesio_cli/tools/procesio/dto/form/data_shell.json +1 -0
  363. procesio_cli/tools/procesio/dto/form/description.md +346 -0
  364. procesio_cli/tools/procesio/dto/form/elements/approval.json +259 -0
  365. procesio_cli/tools/procesio/dto/form/elements/assignee.json +137 -0
  366. procesio_cli/tools/procesio/dto/form/elements/button.json +125 -0
  367. procesio_cli/tools/procesio/dto/form/elements/chart.json +341 -0
  368. procesio_cli/tools/procesio/dto/form/elements/chat.json +199 -0
  369. procesio_cli/tools/procesio/dto/form/elements/checkbox.json +153 -0
  370. procesio_cli/tools/procesio/dto/form/elements/column.json +77 -0
  371. procesio_cli/tools/procesio/dto/form/elements/columns.json +78 -0
  372. procesio_cli/tools/procesio/dto/form/elements/datetime-input.json +304 -0
  373. procesio_cli/tools/procesio/dto/form/elements/divider.json +54 -0
  374. procesio_cli/tools/procesio/dto/form/elements/dropdown.json +130 -0
  375. procesio_cli/tools/procesio/dto/form/elements/dynamic-table-row.json +253 -0
  376. procesio_cli/tools/procesio/dto/form/elements/file-upload.json +196 -0
  377. procesio_cli/tools/procesio/dto/form/elements/file-viewer.json +169 -0
  378. procesio_cli/tools/procesio/dto/form/elements/heading.json +79 -0
  379. procesio_cli/tools/procesio/dto/form/elements/icon.json +107 -0
  380. procesio_cli/tools/procesio/dto/form/elements/image.json +174 -0
  381. procesio_cli/tools/procesio/dto/form/elements/input.json +206 -0
  382. procesio_cli/tools/procesio/dto/form/elements/list.json +202 -0
  383. procesio_cli/tools/procesio/dto/form/elements/number-input.json +202 -0
  384. procesio_cli/tools/procesio/dto/form/elements/paragraph.json +79 -0
  385. procesio_cli/tools/procesio/dto/form/elements/radiobox.json +174 -0
  386. procesio_cli/tools/procesio/dto/form/elements/section.json +114 -0
  387. procesio_cli/tools/procesio/dto/form/elements/select.json +217 -0
  388. procesio_cli/tools/procesio/dto/form/elements/side-panel.json +146 -0
  389. procesio_cli/tools/procesio/dto/form/elements/signature-pad.json +141 -0
  390. procesio_cli/tools/procesio/dto/form/elements/static-table-row.json +84 -0
  391. procesio_cli/tools/procesio/dto/form/elements/step.json +105 -0
  392. procesio_cli/tools/procesio/dto/form/elements/stepper.json +126 -0
  393. procesio_cli/tools/procesio/dto/form/elements/tab.json +77 -0
  394. procesio_cli/tools/procesio/dto/form/elements/table.json +279 -0
  395. procesio_cli/tools/procesio/dto/form/elements/tabs.json +114 -0
  396. procesio_cli/tools/procesio/dto/form/elements/textarea.json +213 -0
  397. procesio_cli/tools/procesio/dto/form/enum_map.json +68 -0
  398. procesio_cli/tools/procesio/dto/form/fieldpath.py +284 -0
  399. procesio_cli/tools/procesio/dto/form/fixtures/reg.config.json +32 -0
  400. procesio_cli/tools/procesio/dto/form/fixtures/reg.elements.json +638 -0
  401. procesio_cli/tools/procesio/dto/form/sync_from_mock.py +386 -0
  402. procesio_cli/tools/procesio/dto/framework.py +125 -0
  403. procesio_cli/tools/procesio/dto/process/builder.py +1991 -0
  404. procesio_cli/tools/procesio/dto/process/config.schema.json +159 -0
  405. procesio_cli/tools/procesio/dto/process/description.md +218 -0
  406. procesio_cli/tools/procesio/dto/process/fixtures/greet.config.json +32 -0
  407. procesio_cli/tools/procesio/dto/process/fixtures/greet.dto.json +317 -0
  408. procesio_cli/tools/procesio/dto/process/naming.py +305 -0
  409. procesio_cli/tools/procesio/dto/process/normalize.py +74 -0
  410. procesio_cli/tools/procesio/dto/process/template.dto.json +32 -0
  411. procesio_cli/tools/procesio/dto/refdata.py +87 -0
  412. procesio_cli/tools/procesio/dto/registry.py +27 -0
  413. procesio_cli/tools/procesio/dto/webhook/builder.py +142 -0
  414. procesio_cli/tools/procesio/dto/webhook/config.schema.json +25 -0
  415. procesio_cli/tools/procesio/dto/webhook/description.md +92 -0
  416. procesio_cli/tools/procesio/dto/webhook/fixtures/order.config.json +10 -0
  417. procesio_cli/tools/procesio/dto/webhook/fixtures/order.dto.json +25 -0
  418. procesio_cli/tools/procesio/dto/webhook/template.dto.json +14 -0
  419. procesio_cli/tools/procesio/environments.py +264 -0
  420. procesio_cli/tools/procesio/errors.py +166 -0
  421. procesio_cli/tools/procesio/flowmodel/README.md +37 -0
  422. procesio_cli/tools/procesio/flowmodel/__init__.py +14 -0
  423. procesio_cli/tools/procesio/flowmodel/digest.py +223 -0
  424. procesio_cli/tools/procesio/flowmodel/families.py +34 -0
  425. procesio_cli/tools/procesio/flowmodel/fevalidation.py +1098 -0
  426. procesio_cli/tools/procesio/flowmodel/formdigest.py +232 -0
  427. procesio_cli/tools/procesio/flowmodel/inspect.py +78 -0
  428. procesio_cli/tools/procesio/flowmodel/model.py +82 -0
  429. procesio_cli/tools/procesio/flowmodel/nodeparam.py +871 -0
  430. procesio_cli/tools/procesio/flowmodel/reader.py +191 -0
  431. procesio_cli/tools/procesio/flowmodel/sqlparam.py +410 -0
  432. procesio_cli/tools/procesio/form_code_keys.py +50 -0
  433. procesio_cli/tools/procesio/formlint.py +292 -0
  434. procesio_cli/tools/procesio/gen_manifest.py +118 -0
  435. procesio_cli/tools/procesio/handlers/__init__.py +1 -0
  436. procesio_cli/tools/procesio/handlers/auth_actions.py +103 -0
  437. procesio_cli/tools/procesio/handlers/catalog.py +147 -0
  438. procesio_cli/tools/procesio/handlers/common.py +90 -0
  439. procesio_cli/tools/procesio/handlers/customaction_ops.py +146 -0
  440. procesio_cli/tools/procesio/handlers/datastore_ops.py +482 -0
  441. procesio_cli/tools/procesio/handlers/datatype_ops.py +275 -0
  442. procesio_cli/tools/procesio/handlers/dto_actions.py +258 -0
  443. procesio_cli/tools/procesio/handlers/environment_admin.py +146 -0
  444. procesio_cli/tools/procesio/handlers/fevalidate.py +236 -0
  445. procesio_cli/tools/procesio/handlers/files.py +141 -0
  446. procesio_cli/tools/procesio/handlers/flowgraph.py +229 -0
  447. procesio_cli/tools/procesio/handlers/flowlint.py +269 -0
  448. procesio_cli/tools/procesio/handlers/form_chains.py +336 -0
  449. procesio_cli/tools/procesio/handlers/form_code.py +277 -0
  450. procesio_cli/tools/procesio/handlers/form_element.py +199 -0
  451. procesio_cli/tools/procesio/handlers/form_events.py +441 -0
  452. procesio_cli/tools/procesio/handlers/form_update.py +270 -0
  453. procesio_cli/tools/procesio/handlers/formprocess.py +211 -0
  454. procesio_cli/tools/procesio/handlers/generic.py +135 -0
  455. procesio_cli/tools/procesio/handlers/layout.py +137 -0
  456. procesio_cli/tools/procesio/handlers/nodeparams.py +1018 -0
  457. procesio_cli/tools/procesio/handlers/process_layout.py +189 -0
  458. procesio_cli/tools/procesio/handlers/process_naming.py +213 -0
  459. procesio_cli/tools/procesio/handlers/processes.py +416 -0
  460. procesio_cli/tools/procesio/handlers/profile_admin.py +184 -0
  461. procesio_cli/tools/procesio/handlers/resource_ops.py +447 -0
  462. procesio_cli/tools/procesio/handlers/schedules.py +320 -0
  463. procesio_cli/tools/procesio/handlers/sqlactions.py +232 -0
  464. procesio_cli/tools/procesio/handlers/transport.py +463 -0
  465. procesio_cli/tools/procesio/handlers/usageguide.py +222 -0
  466. procesio_cli/tools/procesio/layout/README.md +196 -0
  467. procesio_cli/tools/procesio/layout/__init__.py +11 -0
  468. procesio_cli/tools/procesio/layout/adapter.py +736 -0
  469. procesio_cli/tools/procesio/layout/cycles.py +186 -0
  470. procesio_cli/tools/procesio/layout/dispatch.py +39 -0
  471. procesio_cli/tools/procesio/layout/elk/elk_runner.mjs +50 -0
  472. procesio_cli/tools/procesio/layout/elk/package-lock.json +21 -0
  473. procesio_cli/tools/procesio/layout/elk/package.json +11 -0
  474. procesio_cli/tools/procesio/layout/elk_engine.py +568 -0
  475. procesio_cli/tools/procesio/layout/engine.py +1311 -0
  476. procesio_cli/tools/procesio/layout/report.py +187 -0
  477. procesio_cli/tools/procesio/main.py +179 -0
  478. procesio_cli/tools/procesio/profiles.py +193 -0
  479. procesio_cli/tools/procesio/reliability.py +193 -0
  480. procesio_cli/tools/procesio/sqlformat.py +167 -0
  481. procesio_cli/tools/procesio/swagger.py +51 -0
  482. procesio_cli/tools/procesio/tests/__init__.py +0 -0
  483. procesio_cli/tools/procesio/tests/conftest.py +129 -0
  484. procesio_cli/tools/procesio/tests/test_auth.py +200 -0
  485. procesio_cli/tools/procesio/tests/test_autogen.py +78 -0
  486. procesio_cli/tools/procesio/tests/test_builder_attrpath_sqlbind.py +180 -0
  487. procesio_cli/tools/procesio/tests/test_builder_custom_action_catalog.py +72 -0
  488. procesio_cli/tools/procesio/tests/test_client.py +114 -0
  489. procesio_cli/tools/procesio/tests/test_client_reliability.py +139 -0
  490. procesio_cli/tools/procesio/tests/test_customaction.py +103 -0
  491. procesio_cli/tools/procesio/tests/test_customaction_test.py +80 -0
  492. procesio_cli/tools/procesio/tests/test_cycles.py +69 -0
  493. procesio_cli/tools/procesio/tests/test_datastore.py +378 -0
  494. procesio_cli/tools/procesio/tests/test_datastore_node.py +94 -0
  495. procesio_cli/tools/procesio/tests/test_dispatch.py +170 -0
  496. procesio_cli/tools/procesio/tests/test_document_page_size.py +19 -0
  497. procesio_cli/tools/procesio/tests/test_dto.py +734 -0
  498. procesio_cli/tools/procesio/tests/test_edit_dryrun_preview.py +96 -0
  499. procesio_cli/tools/procesio/tests/test_elk_layout.py +221 -0
  500. procesio_cli/tools/procesio/tests/test_environments.py +214 -0
  501. procesio_cli/tools/procesio/tests/test_fevalidate_gate.py +104 -0
  502. procesio_cli/tools/procesio/tests/test_fevalidation.py +317 -0
  503. procesio_cli/tools/procesio/tests/test_fieldpath_variables.py +87 -0
  504. procesio_cli/tools/procesio/tests/test_files.py +72 -0
  505. procesio_cli/tools/procesio/tests/test_flow_digest.py +202 -0
  506. procesio_cli/tools/procesio/tests/test_flowlint.py +114 -0
  507. procesio_cli/tools/procesio/tests/test_flowmodel.py +158 -0
  508. procesio_cli/tools/procesio/tests/test_form_add_element.py +256 -0
  509. procesio_cli/tools/procesio/tests/test_form_approval_gaps.py +319 -0
  510. procesio_cli/tools/procesio/tests/test_form_auto_names.py +60 -0
  511. procesio_cli/tools/procesio/tests/test_form_chains.py +217 -0
  512. procesio_cli/tools/procesio/tests/test_form_code_actions.py +188 -0
  513. procesio_cli/tools/procesio/tests/test_form_code_keys.py +92 -0
  514. procesio_cli/tools/procesio/tests/test_form_code_style.py +178 -0
  515. procesio_cli/tools/procesio/tests/test_form_delete_element.py +99 -0
  516. procesio_cli/tools/procesio/tests/test_form_element_config.py +141 -0
  517. procesio_cli/tools/procesio/tests/test_form_event_maps.py +135 -0
  518. procesio_cli/tools/procesio/tests/test_form_event_ops.py +376 -0
  519. procesio_cli/tools/procesio/tests/test_form_event_replace.py +86 -0
  520. procesio_cli/tools/procesio/tests/test_form_events.py +92 -0
  521. procesio_cli/tools/procesio/tests/test_form_parity.py +171 -0
  522. procesio_cli/tools/procesio/tests/test_form_select_source.py +74 -0
  523. procesio_cli/tools/procesio/tests/test_form_sync.py +35 -0
  524. procesio_cli/tools/procesio/tests/test_form_update.py +133 -0
  525. procesio_cli/tools/procesio/tests/test_formlint.py +155 -0
  526. procesio_cli/tools/procesio/tests/test_formlint_css_scope.py +38 -0
  527. procesio_cli/tools/procesio/tests/test_formlint_field_names.py +83 -0
  528. procesio_cli/tools/procesio/tests/test_guards.py +110 -0
  529. procesio_cli/tools/procesio/tests/test_hidden_setting_types.py +39 -0
  530. procesio_cli/tools/procesio/tests/test_html2docx_asset.py +132 -0
  531. procesio_cli/tools/procesio/tests/test_key_handle_terminology.py +45 -0
  532. procesio_cli/tools/procesio/tests/test_layout.py +574 -0
  533. procesio_cli/tools/procesio/tests/test_layout_report.py +88 -0
  534. procesio_cli/tools/procesio/tests/test_manifest_sync.py +68 -0
  535. procesio_cli/tools/procesio/tests/test_nodedelete.py +151 -0
  536. procesio_cli/tools/procesio/tests/test_nodeparam.py +826 -0
  537. procesio_cli/tools/procesio/tests/test_normalize.py +70 -0
  538. procesio_cli/tools/procesio/tests/test_payload_docs.py +86 -0
  539. procesio_cli/tools/procesio/tests/test_process_action_naming.py +170 -0
  540. procesio_cli/tools/procesio/tests/test_process_call_api_seed.py +46 -0
  541. procesio_cli/tools/procesio/tests/test_process_ext.py +373 -0
  542. procesio_cli/tools/procesio/tests/test_process_invariants.py +183 -0
  543. procesio_cli/tools/procesio/tests/test_process_layout.py +117 -0
  544. procesio_cli/tools/procesio/tests/test_process_naming.py +188 -0
  545. procesio_cli/tools/procesio/tests/test_process_query_store.py +172 -0
  546. procesio_cli/tools/procesio/tests/test_processinfo_variable.py +56 -0
  547. procesio_cli/tools/procesio/tests/test_profiles.py +127 -0
  548. procesio_cli/tools/procesio/tests/test_put_projects.py +41 -0
  549. procesio_cli/tools/procesio/tests/test_reliability.py +107 -0
  550. procesio_cli/tools/procesio/tests/test_removal_gate.py +95 -0
  551. procesio_cli/tools/procesio/tests/test_resource_ops.py +173 -0
  552. procesio_cli/tools/procesio/tests/test_save_validity.py +207 -0
  553. procesio_cli/tools/procesio/tests/test_schedule_cron_shape.py +111 -0
  554. procesio_cli/tools/procesio/tests/test_schedules.py +309 -0
  555. procesio_cli/tools/procesio/tests/test_sqlconvert.py +234 -0
  556. procesio_cli/tools/procesio/tests/test_sqlformat.py +83 -0
  557. procesio_cli/tools/procesio/tests/test_sqlparam.py +187 -0
  558. procesio_cli/tools/procesio/tests/test_superseded_actions.py +54 -0
  559. procesio_cli/tools/procesio/tests/test_surgical_concurrency.py +156 -0
  560. procesio_cli/tools/procesio/tests/test_tier4.py +123 -0
  561. procesio_cli/tools/procesio/tests/test_transport.py +147 -0
  562. procesio_cli/tools/procesio/tests/test_transport_data_stores.py +168 -0
  563. procesio_cli/tools/procesio/tests/test_transport_mapper_repair.py +150 -0
  564. procesio_cli/tools/procesio/tests/test_transport_webhook_strip.py +253 -0
  565. procesio_cli/tools/procesio/tests/test_usage_guide.py +96 -0
  566. procesio_cli/tools/procesio/tool.yaml +12486 -0
  567. procesio_cli/tools/sqlserver/MOVED-TO-CENTRAL.md +29 -0
  568. procesio_cli/tools/sqlserver/README.md +192 -0
  569. procesio_cli/tools/sqlserver/SKILL.md +37 -0
  570. procesio_cli/tools/sqlserver/SQLSERVER-SCHEMA-NOTES.md +284 -0
  571. procesio_cli/tools/sqlserver/__init__.py +0 -0
  572. procesio_cli/tools/sqlserver/connection.py +242 -0
  573. procesio_cli/tools/sqlserver/main.py +521 -0
  574. procesio_cli/tools/sqlserver/profiles.template.json +1 -0
  575. procesio_cli/tools/sqlserver/schema.py +600 -0
  576. procesio_cli/tools/sqlserver/tests/__init__.py +0 -0
  577. procesio_cli/tools/sqlserver/tests/conftest.py +21 -0
  578. procesio_cli/tools/sqlserver/tests/test_connection.py +75 -0
  579. procesio_cli/tools/sqlserver/tests/test_dbprofiles.py +92 -0
  580. procesio_cli/tools/sqlserver/tests/test_dbquery.py +220 -0
  581. procesio_cli/tools/sqlserver/tests/test_manifest_sync.py +68 -0
  582. procesio_cli/tools/sqlserver/tests/test_sqlserver.py +326 -0
  583. procesio_cli/tools/sqlserver/tests/test_sqlserver_schema.py +488 -0
  584. procesio_cli/tools/sqlserver/tool.yaml +123 -0
  585. procesio_cli/tools/web/README.md +381 -0
  586. procesio_cli/tools/web/SKILL.md +37 -0
  587. procesio_cli/tools/web/WEB-AUTOMATION-NOTES.md +277 -0
  588. procesio_cli/tools/web/__init__.py +21 -0
  589. procesio_cli/tools/web/actiondef.py +24 -0
  590. procesio_cli/tools/web/api.py +444 -0
  591. procesio_cli/tools/web/brokered.py +107 -0
  592. procesio_cli/tools/web/driver.py +839 -0
  593. procesio_cli/tools/web/drivercontract.py +44 -0
  594. procesio_cli/tools/web/errors.py +54 -0
  595. procesio_cli/tools/web/handlers/__init__.py +1 -0
  596. procesio_cli/tools/web/handlers/archive.py +367 -0
  597. procesio_cli/tools/web/handlers/browse.py +182 -0
  598. procesio_cli/tools/web/handlers/contacts.py +74 -0
  599. procesio_cli/tools/web/handlers/sessmgmt.py +120 -0
  600. procesio_cli/tools/web/main.py +128 -0
  601. procesio_cli/tools/web/sessions.py +253 -0
  602. procesio_cli/tools/web/steps.py +162 -0
  603. procesio_cli/tools/web/tests/__init__.py +0 -0
  604. procesio_cli/tools/web/tests/conftest.py +197 -0
  605. procesio_cli/tools/web/tests/test_api.py +330 -0
  606. procesio_cli/tools/web/tests/test_archive.py +190 -0
  607. procesio_cli/tools/web/tests/test_brokered.py +138 -0
  608. procesio_cli/tools/web/tests/test_dispatch.py +132 -0
  609. procesio_cli/tools/web/tests/test_errors.py +60 -0
  610. procesio_cli/tools/web/tests/test_manifest_sync.py +76 -0
  611. procesio_cli/tools/web/tests/test_page_contacts.py +68 -0
  612. procesio_cli/tools/web/tests/test_sessions.py +145 -0
  613. procesio_cli/tools/web/tests/test_steps.py +210 -0
  614. procesio_cli/tools/web/tool.yaml +184 -0
  615. procesio_cli/tools/xlsx/README.md +34 -0
  616. procesio_cli/tools/xlsx/SKILL.md +28 -0
  617. procesio_cli/tools/xlsx/__init__.py +0 -0
  618. procesio_cli/tools/xlsx/main.py +129 -0
  619. procesio_cli/tools/xlsx/reader.py +91 -0
  620. procesio_cli/tools/xlsx/tests/__init__.py +0 -0
  621. procesio_cli/tools/xlsx/tests/conftest.py +39 -0
  622. procesio_cli/tools/xlsx/tests/test_xlsx.py +103 -0
  623. procesio_cli/tools/xlsx/tool.yaml +30 -0
  624. procesio_cli/webplatform/aat_mcp/AAT-MCP-NOTES.md +244 -0
  625. procesio_cli/webplatform/aat_mcp/README.md +78 -0
  626. procesio_cli/webplatform/aat_mcp/bridge.py +705 -0
  627. procesio_cli/webplatform/aat_mcp/chat_server.py +194 -0
  628. procesio_cli/webplatform/aat_mcp/chat_surface.snapshot.json +668 -0
  629. procesio_cli/webplatform/aat_mcp/chat_surface.yaml +372 -0
  630. procesio_cli/webplatform/aat_mcp/gate.py +68 -0
  631. procesio_cli/webplatform/aat_mcp/http_server.py +139 -0
  632. procesio_cli/webplatform/aat_mcp/protocol.py +175 -0
  633. procesio_cli/webplatform/aat_mcp/server.py +306 -0
  634. procesio_cli/webplatform/aat_mcp/tests/conftest.py +8 -0
  635. procesio_cli/webplatform/aat_mcp/tests/test_aat_mcp.py +255 -0
  636. procesio_cli/webplatform/aat_mcp/tests/test_chat_surface.py +247 -0
  637. procesio_cli/webplatform/aat_mcp/tests/test_discovery.py +489 -0
  638. procesio_cli/webplatform/aat_mcp/tests/test_multiuser.py +86 -0
  639. procesio_cli/webplatform/aat_mcp/tests/test_progressive_discovery.py +89 -0
  640. procesio_cli/webplatform/aat_mcp/tests/test_protocol.py +180 -0
  641. procesio_cli/webplatform/aat_mcp/tests/test_skill_discovery.py +23 -0
  642. procesio_cli-0.1.1.dist-info/METADATA +467 -0
  643. procesio_cli-0.1.1.dist-info/RECORD +647 -0
  644. procesio_cli-0.1.1.dist-info/WHEEL +4 -0
  645. procesio_cli-0.1.1.dist-info/entry_points.txt +7 -0
  646. procesio_cli-0.1.1.dist-info/licenses/LICENSE +201 -0
  647. procesio_cli-0.1.1.dist-info/licenses/NOTICE +5 -0
@@ -0,0 +1,44 @@
1
+ """Check a test double against the BrowserDriver contract.
2
+
3
+ Several tools drive a browser through `tools/web/steps.run_steps`, and each
4
+ keeps its own `FakeDriver` test double. When the real driver gains a parameter -
5
+ `click(..., force=...)` was the one that bit - every double that does not accept
6
+ it starts raising TypeError, and the break surfaces in an unrelated tool's suite
7
+ hours later, looking like that tool's bug.
8
+
9
+ A double is deliberately allowed to implement only the subset of methods its own
10
+ tests exercise. What it may NOT do is implement a method with a signature the
11
+ step runner cannot call. That is the only thing checked here.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import inspect
16
+
17
+ from tools.web.driver import BrowserDriver
18
+
19
+
20
+ def signature_mismatches(double: type) -> list[str]:
21
+ """Parameters BrowserDriver defines that `double` could not accept.
22
+
23
+ Returns one readable line per problem, empty when the double is callable
24
+ everywhere the real driver is. A double taking **kwargs is exempt: it can
25
+ absorb anything, at the cost of not asserting on it.
26
+ """
27
+ problems: list[str] = []
28
+ for name, proto_fn in inspect.getmembers(BrowserDriver, inspect.isfunction):
29
+ if name.startswith("_"):
30
+ continue
31
+ fake_fn = getattr(double, name, None)
32
+ if fake_fn is None:
33
+ continue # implementing a subset is fine
34
+ fake_params = inspect.signature(fake_fn).parameters
35
+ if any(p.kind is inspect.Parameter.VAR_KEYWORD
36
+ for p in fake_params.values()):
37
+ continue
38
+ for pname in inspect.signature(proto_fn).parameters:
39
+ if pname == "self" or pname in fake_params:
40
+ continue
41
+ problems.append(
42
+ f"{double.__name__}.{name}() cannot accept {pname!r}, which "
43
+ f"BrowserDriver.{name}() defines")
44
+ return problems
@@ -0,0 +1,54 @@
1
+ """Map exceptions to the framework error envelope: (code, message, details, exit_code).
2
+
3
+ The web tool raises:
4
+ - UsageError bad/missing CLI args or a malformed step -> invalid_argument, exit 2
5
+ - SessionError a named session file is missing/corrupt -> session_not_found, exit 1
6
+ - BrowserError Playwright failed (nav timeout, missing -> browser_error, exit 1
7
+ browser binary, selector not found, etc.)
8
+ Anything else -> generic 'error', exit 1.
9
+
10
+ Playwright is imported lazily everywhere so this module (and the tests) load
11
+ even when the browser binaries are not installed yet.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ from typing import Any
16
+
17
+
18
+ class UsageError(Exception):
19
+ """Bad/invalid arguments or step schema. Maps to 'invalid_argument', exit 2."""
20
+
21
+
22
+ class SessionError(Exception):
23
+ """A named session is missing or its storageState file is unreadable.
24
+
25
+ Maps to 'session_not_found', exit 1.
26
+ """
27
+
28
+
29
+ class BrowserError(Exception):
30
+ """A Playwright operation failed (navigation, selector, missing binary, ...).
31
+
32
+ ``details`` is surfaced under the error envelope's details when present.
33
+ """
34
+
35
+ def __init__(self, message: str, details: dict[str, Any] | None = None):
36
+ self.details = details or {}
37
+ super().__init__(message)
38
+
39
+
40
+ def classify(exc: Exception) -> tuple[str, str, dict, int]:
41
+ if isinstance(exc, UsageError):
42
+ return "invalid_argument", str(exc), {}, 2
43
+ if isinstance(exc, SessionError):
44
+ return "session_not_found", str(exc), {}, 1
45
+ if isinstance(exc, BrowserError):
46
+ return "browser_error", str(exc) or exc.__class__.__name__, exc.details, 1
47
+ # Playwright raises its own Error/TimeoutError types. Map them generically
48
+ # to browser_error by class-name sniffing so we never import playwright here.
49
+ cls = exc.__class__.__name__
50
+ if cls in {"Error", "TimeoutError"} and "playwright" in (
51
+ type(exc).__module__ or ""
52
+ ):
53
+ return "browser_error", str(exc) or cls, {}, 1
54
+ return "error", str(exc) or cls, {}, 1
@@ -0,0 +1 @@
1
+ """Action handlers for the web tool."""
@@ -0,0 +1,367 @@
1
+ """archive-document - capture a published document as a reviewable evidence set.
2
+
3
+ WHY THIS EXISTS. A published document (a terms page, a subscription agreement,
4
+ a policy PDF) is evidence. Quoting it later is only safe if three things are
5
+ kept together: the bytes exactly as the publisher served them, a rendering a
6
+ human can open without a network, and a text form that can be searched and
7
+ quoted. Screenshots lose the text, a markdown conversion loses the clause
8
+ numbering and pagination that a reader relies on, and a bare URL loses
9
+ everything the moment the publisher edits the page.
10
+
11
+ So every capture writes THREE artefacts into one folder named for the document:
12
+
13
+ <name>.html / .pdf the ORIGINAL response body, byte for byte. Never
14
+ rewritten. The sha256 in the manifest is this
15
+ file's hash, so a later capture of the same URL
16
+ can be compared against it to prove whether the
17
+ publisher changed the document.
18
+ <name>.self-contained.html (HTML only) the same markup with every stylesheet
19
+ fetched and inlined, so the document opens with
20
+ its layout intact on a machine with no network
21
+ and no repository access. The markup is otherwise
22
+ untouched.
23
+ <name>.md a text extraction for searching and quoting,
24
+ carrying a provenance header: title, the date the
25
+ document states about itself, source URL, fetch
26
+ timestamp, and the sha256 of the original.
27
+
28
+ PROVENANCE IS NOT OPTIONAL. Both readable artefacts carry the same header
29
+ block, because an extraction that travels without its source URL and fetch date
30
+ becomes an unattributable quote the first time someone copies it into a brief.
31
+
32
+ DATES. ``document_date_candidates`` reports date-like strings the document
33
+ states about ITSELF (near "last updated", "effective", "version", "revised").
34
+ They are CANDIDATES, reported in the order found and never reconciled: a page
35
+ that says two different things about its own date is a finding about the page,
36
+ not a defect to be quietly resolved here.
37
+
38
+ LOGIN-GATED PAGES ARE OUT OF SCOPE by design. This action performs an
39
+ unauthenticated fetch. A document behind a login is a fact worth recording as
40
+ unreachable, not one to be silently substituted with a summary; capture those
41
+ through ``web run`` / ``web get-text`` with a saved session instead.
42
+ """
43
+ from __future__ import annotations
44
+
45
+ import argparse
46
+ import hashlib
47
+ import re
48
+ from datetime import datetime, timezone
49
+ from pathlib import Path
50
+ from urllib.parse import urljoin, urlparse
51
+
52
+ from tools.web.actiondef import ActionDef
53
+ from tools.web.errors import UsageError
54
+
55
+ # A publisher's edge (Cloudflare and friends) may serve a challenge page to a
56
+ # default urllib/requests agent. A real browser agent gets the document itself.
57
+ _UA = ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
58
+ "(KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36")
59
+
60
+ _HEADERS = {
61
+ "User-Agent": _UA,
62
+ "Accept": "text/html,application/xhtml+xml,application/pdf,*/*;q=0.8",
63
+ "Accept-Language": "en-GB,en;q=0.9",
64
+ }
65
+
66
+ # Date-ish strings a document uses to state its own version. Deliberately broad:
67
+ # over-reporting a candidate is cheap, missing the one date counsel needs is not.
68
+ _DATE_PATTERNS = [
69
+ r"\b\d{1,2}[./-]\d{1,2}[./-]\d{4}\b",
70
+ r"\b\d{4}-\d{2}-\d{2}\b",
71
+ r"\b\d{1,2}\s+(?:January|February|March|April|May|June|July|August|September|October|November|December)\s+\d{4}\b",
72
+ r"\b(?:January|February|March|April|May|June|July|August|September|October|November|December)\s+\d{1,2},?\s+\d{4}\b",
73
+ ]
74
+ _DATE_CONTEXT = re.compile(
75
+ r"(last\s+updated|last\s+revised|effective|version|revised|updated|"
76
+ r"in\s+effect|as\s+of|dated|valabil|actualizat)", re.I)
77
+
78
+
79
+ def _sha256(data: bytes) -> str:
80
+ return hashlib.sha256(data).hexdigest()
81
+
82
+
83
+ def _fetch(url: str, timeout: int) -> tuple[bytes, int, str, str]:
84
+ """GET url with a browser agent. Returns (body, status, content_type, final_url)."""
85
+ import requests
86
+ try:
87
+ resp = requests.get(url, headers=_HEADERS, timeout=timeout,
88
+ allow_redirects=True)
89
+ except Exception as exc: # noqa: BLE001 - network shape varies by failure
90
+ raise UsageError(f"fetch failed for {url!r}: {exc}")
91
+ return (resp.content, resp.status_code,
92
+ resp.headers.get("Content-Type", ""), resp.url)
93
+
94
+
95
+ def _is_pdf(body: bytes, content_type: str, url: str) -> bool:
96
+ return (body[:5] == b"%PDF-"
97
+ or "application/pdf" in content_type.lower()
98
+ or urlparse(url).path.lower().endswith(".pdf"))
99
+
100
+
101
+ def _soup(html: bytes):
102
+ from bs4 import BeautifulSoup
103
+ return BeautifulSoup(html, "lxml")
104
+
105
+
106
+ def _extract_title(soup, fallback: str) -> str:
107
+ for getter in (lambda: soup.title.get_text(strip=True) if soup.title else None,
108
+ lambda: soup.h1.get_text(strip=True) if soup.h1 else None):
109
+ try:
110
+ value = getter()
111
+ except Exception: # noqa: BLE001 - malformed markup must not abort a capture
112
+ value = None
113
+ if value:
114
+ return value
115
+ return fallback
116
+
117
+
118
+ def _html_to_text(soup) -> str:
119
+ """Visible text with block structure preserved.
120
+
121
+ Only script/style/noscript/template are dropped - they carry no text a
122
+ reader would quote. Nothing else is filtered: a navigation or footer line
123
+ in the extraction is noise, but silently dropping a region risks dropping
124
+ a clause that happens to sit in one.
125
+ """
126
+ from bs4 import BeautifulSoup # noqa: F401 (soup already built by caller)
127
+ clone = _soup(str(soup).encode("utf-8"))
128
+ for tag in clone(["script", "style", "noscript", "template"]):
129
+ tag.decompose()
130
+ text = clone.get_text("\n")
131
+ lines = [ln.strip() for ln in text.splitlines()]
132
+ out: list[str] = []
133
+ for line in lines:
134
+ if line:
135
+ out.append(line)
136
+ elif out and out[-1] != "":
137
+ out.append("")
138
+ return "\n".join(out).strip()
139
+
140
+
141
+ def _pdf_to_text(path: Path) -> str:
142
+ try:
143
+ import fitz
144
+ with fitz.open(path) as doc:
145
+ return "\n\n".join(
146
+ f"--- page {i + 1} ---\n{page.get_text()}"
147
+ for i, page in enumerate(doc)
148
+ ).strip()
149
+ except Exception: # noqa: BLE001 - fall through to the second engine
150
+ pass
151
+ try:
152
+ from pypdf import PdfReader
153
+ reader = PdfReader(str(path))
154
+ return "\n\n".join(
155
+ f"--- page {i + 1} ---\n{(pg.extract_text() or '')}"
156
+ for i, pg in enumerate(reader.pages)
157
+ ).strip()
158
+ except Exception as exc: # noqa: BLE001
159
+ return f"[extraction failed: {exc}]"
160
+
161
+
162
+ def _date_candidates(text: str, limit: int = 12) -> list[dict]:
163
+ """Date strings the document states about itself, with their context line.
164
+
165
+ Reported in document order and NEVER de-conflicted. Two different dates on
166
+ one document is a finding, not an error to resolve.
167
+ """
168
+ found: list[dict] = []
169
+ seen: set[tuple[str, str]] = set()
170
+ for line in text.splitlines():
171
+ if not _DATE_CONTEXT.search(line):
172
+ continue
173
+ for pattern in _DATE_PATTERNS:
174
+ for match in re.findall(pattern, line):
175
+ key = (match, line[:80])
176
+ if key in seen:
177
+ continue
178
+ seen.add(key)
179
+ found.append({"date": match, "context": line.strip()[:200]})
180
+ if len(found) >= limit:
181
+ return found
182
+ return found
183
+
184
+
185
+ def _inline_stylesheets(soup, base_url: str, timeout: int) -> int:
186
+ """Fetch every <link rel=stylesheet> and inline it as <style>.
187
+
188
+ Makes the capture open with its layout on a machine with no network. The
189
+ markup is not otherwise touched: only the link element is swapped for the
190
+ stylesheet it pointed at, and a comment records where each came from so the
191
+ substitution stays auditable.
192
+ """
193
+ import requests
194
+ inlined = 0
195
+ for link in list(soup.find_all("link")):
196
+ rel = " ".join(link.get("rel") or []).lower()
197
+ href = link.get("href")
198
+ if "stylesheet" not in rel or not href:
199
+ continue
200
+ css_url = urljoin(base_url, href)
201
+ try:
202
+ resp = requests.get(css_url, headers=_HEADERS, timeout=timeout)
203
+ if resp.status_code != 200:
204
+ continue
205
+ css = resp.text
206
+ except Exception: # noqa: BLE001 - a missing stylesheet degrades, never aborts
207
+ continue
208
+ # url(...) inside the CSS is relative to the STYLESHEET, not the page,
209
+ # so rewrite to absolute or the inlined copy loses its fonts and images.
210
+ css = re.sub(
211
+ r"url\(\s*(['\"]?)(?!data:|https?:|//)([^)'\"]+)\1\s*\)",
212
+ lambda m: f"url({m.group(1)}{urljoin(css_url, m.group(2))}{m.group(1)})",
213
+ css)
214
+ style = soup.new_tag("style")
215
+ style.string = f"/* inlined from {css_url} */\n{css}"
216
+ link.replace_with(style)
217
+ inlined += 1
218
+ return inlined
219
+
220
+
221
+ def _header(fmt: str, meta: dict) -> str:
222
+ """Provenance block prepended to every readable artefact."""
223
+ dates = meta["document_date_candidates"]
224
+ date_line = ("; ".join(f"{d['date']} ({d['context'][:60]})" for d in dates)
225
+ if dates else "NONE STATED ON THE DOCUMENT")
226
+ rows = [
227
+ ("Document title (as published)", meta["title"]),
228
+ ("Date stated on the document", date_line),
229
+ ("Source URL", meta["url"]),
230
+ ("Final URL after redirects", meta["final_url"]),
231
+ ("HTTP status", str(meta["status"])),
232
+ ("Fetched at (UTC)", meta["fetched_at"]),
233
+ ("Original file", meta["original_name"]),
234
+ ("SHA-256 of original", meta["sha256_original"]),
235
+ ("Original size (bytes)", str(meta["bytes"])),
236
+ ("Captured by", "web archive-document (Agents-and-Tools)"),
237
+ ]
238
+ if fmt == "md":
239
+ body = "\n".join(f"| {k} | {v} |" for k, v in rows)
240
+ return (
241
+ f"# {meta['title']}\n\n"
242
+ "> **Working copy for review. The original is the authority.**\n"
243
+ "> This extraction is the document's text only; clause numbering, "
244
+ "layout and pagination live in the original file beside it.\n\n"
245
+ "| Field | Value |\n|---|---|\n" + body + "\n\n---\n\n"
246
+ )
247
+ return ""
248
+
249
+
250
+ def archive_document(args) -> dict:
251
+ if bool(args.url) == bool(args.file):
252
+ raise UsageError("provide exactly one of --url or --file")
253
+
254
+ out_dir = Path(args.out_dir).expanduser()
255
+ name = args.name.strip()
256
+ if not name or "/" in name or "\\" in name:
257
+ raise UsageError("--name must be a single folder-safe token")
258
+ folder = out_dir / name
259
+ folder.mkdir(parents=True, exist_ok=True)
260
+
261
+ fetched_at = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
262
+
263
+ if args.url:
264
+ body, status, content_type, final_url = _fetch(args.url, args.timeout)
265
+ source = args.url
266
+ else:
267
+ src = Path(args.file).expanduser()
268
+ if not src.is_file():
269
+ raise UsageError(f"--file not found: {src}")
270
+ body = src.read_bytes()
271
+ status, content_type, final_url = 200, "", src.as_uri()
272
+ source = args.source_url or src.as_uri()
273
+
274
+ is_pdf = _is_pdf(body, content_type, final_url)
275
+ ext = "pdf" if is_pdf else "html"
276
+ original = folder / f"{name}.{ext}"
277
+ original.write_bytes(body) # byte for byte, never rewritten
278
+
279
+ meta = {
280
+ "title": args.title or name,
281
+ "url": source,
282
+ "final_url": final_url,
283
+ "status": status,
284
+ "fetched_at": fetched_at,
285
+ "original_name": original.name,
286
+ "sha256_original": _sha256(body),
287
+ "bytes": len(body),
288
+ "document_date_candidates": [],
289
+ }
290
+
291
+ self_contained: Path | None = None
292
+ inlined = 0
293
+ if is_pdf:
294
+ text = _pdf_to_text(original)
295
+ else:
296
+ soup = _soup(body)
297
+ meta["title"] = args.title or _extract_title(soup, name)
298
+ text = _html_to_text(soup)
299
+ if not args.no_self_contained:
300
+ sc_soup = _soup(body)
301
+ inlined = _inline_stylesheets(sc_soup, final_url, args.timeout)
302
+ if sc_soup.head:
303
+ base = sc_soup.new_tag("base", href=final_url)
304
+ sc_soup.head.insert(0, base)
305
+ self_contained = folder / f"{name}.self-contained.html"
306
+ self_contained.write_text(str(sc_soup), encoding="utf-8")
307
+
308
+ meta["document_date_candidates"] = _date_candidates(text)
309
+
310
+ extraction = folder / f"{name}.md"
311
+ extraction.write_text(_header("md", meta) + text, encoding="utf-8")
312
+
313
+ files = {"original": str(original), "extraction": str(extraction)}
314
+ hashes = {
315
+ "original": meta["sha256_original"],
316
+ "extraction": _sha256(extraction.read_bytes()),
317
+ }
318
+ if self_contained is not None:
319
+ files["self_contained"] = str(self_contained)
320
+ hashes["self_contained"] = _sha256(self_contained.read_bytes())
321
+
322
+ return {
323
+ "name": name,
324
+ "dir": str(folder),
325
+ "url": source,
326
+ "final_url": final_url,
327
+ "status": status,
328
+ "content_type": content_type,
329
+ "kind": "pdf" if is_pdf else "html",
330
+ "title": meta["title"],
331
+ "fetched_at": fetched_at,
332
+ "bytes": len(body),
333
+ "stylesheets_inlined": inlined,
334
+ "chars_extracted": len(text),
335
+ "document_date_candidates": meta["document_date_candidates"],
336
+ "files": files,
337
+ "sha256": hashes,
338
+ }
339
+
340
+
341
+ def _archive_args(p: argparse.ArgumentParser) -> None:
342
+ p.add_argument("--url", default=None,
343
+ help="URL of the document to capture (exactly one of --url/--file)")
344
+ p.add_argument("--file", default=None,
345
+ help="Local file to archive instead of fetching (already-downloaded original)")
346
+ p.add_argument("--source-url", default=None,
347
+ help="With --file: the URL the file came from, recorded in the header")
348
+ p.add_argument("--out-dir", required=True,
349
+ help="Base directory; a subfolder named --name is created inside it")
350
+ p.add_argument("--name", required=True,
351
+ help="Folder and file basename for the document (a slug, not a URL)")
352
+ p.add_argument("--title", default=None,
353
+ help="Published title override; default reads <title>/<h1>")
354
+ p.add_argument("--timeout", type=int, default=60,
355
+ help="Per-request timeout in seconds (default 60)")
356
+ p.add_argument("--no-self-contained", action="store_true",
357
+ help="Skip the stylesheet-inlined copy (original + extraction only)")
358
+
359
+
360
+ ACTIONS = {
361
+ "archive-document": ActionDef(
362
+ archive_document, _archive_args, needs_driver=False,
363
+ description=("Capture a published document as original bytes + a "
364
+ "self-contained rendering + a text extraction, each with "
365
+ "a provenance header and sha256."),
366
+ ),
367
+ }
@@ -0,0 +1,182 @@
1
+ """Browser-action handlers: run, get-text, screenshot.
2
+
3
+ Each receives a ``driver_factory`` (injected by the dispatcher) as its first
4
+ argument, then the parsed args. The factory builds a BrowserDriver from kwargs
5
+ (``storage_state=``, ``headless=``, ``channel=``); in production it is
6
+ ``PlaywrightDriver``, in tests it is a FakeDriver constructor. The handlers call
7
+ into ``tools.web.api`` passing the factory through, so the whole flow is
8
+ exercised without a real browser.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import argparse
13
+ import json
14
+
15
+ from tools.web import api
16
+ from tools.web.actiondef import ActionDef
17
+ from tools.web.errors import UsageError
18
+
19
+
20
+ def _load_steps(args) -> list:
21
+ """Resolve the step list from --actions (inline JSON) or --actions-file."""
22
+ if args.actions and args.actions_file:
23
+ raise UsageError("provide either --actions or --actions-file, not both")
24
+ raw = None
25
+ if args.actions:
26
+ raw = args.actions
27
+ elif args.actions_file:
28
+ try:
29
+ with open(args.actions_file, encoding="utf-8") as fh:
30
+ raw = fh.read()
31
+ except OSError as exc:
32
+ raise UsageError(f"cannot read --actions-file {args.actions_file!r}: {exc}")
33
+ else:
34
+ raise UsageError("provide --actions (JSON array) or --actions-file")
35
+ try:
36
+ steps = json.loads(raw)
37
+ except ValueError as exc:
38
+ raise UsageError(f"--actions is not valid JSON: {exc}")
39
+ if not isinstance(steps, list):
40
+ raise UsageError("--actions must be a JSON array of step objects")
41
+ return steps
42
+
43
+
44
+ def run(driver_factory, args) -> dict:
45
+ steps = _load_steps(args)
46
+ return api.run_steps(
47
+ args.session, steps, url=args.url,
48
+ headless=not args.headed, channel=args.channel,
49
+ hold_seconds=args.hold_seconds,
50
+ hold_until_selector=args.hold_until_selector,
51
+ hold_until_url_excludes=args.hold_until_url_excludes,
52
+ driver_factory=driver_factory,
53
+ )
54
+
55
+
56
+ def _run_args(p: argparse.ArgumentParser) -> None:
57
+ p.add_argument("--session", required=True, help="Saved session name to load")
58
+ p.add_argument("--url", default=None,
59
+ help="Optional URL to visit before running the steps")
60
+ p.add_argument("--actions", default=None,
61
+ help="Inline JSON array of steps (see README for the step schema)")
62
+ p.add_argument("--actions-file", default=None,
63
+ help="Path to a JSON file containing the steps array")
64
+ p.add_argument("--headed", action="store_true",
65
+ help="Show the browser window (default: headless)")
66
+ p.add_argument("--channel", default=None,
67
+ help="Chromium channel: 'chrome' or 'msedge'")
68
+ p.add_argument("--hold-seconds", type=int, default=None,
69
+ help="After the last step, keep the (headed) browser open up "
70
+ "to N seconds so a human can review and complete the "
71
+ "action themselves. Requires --headed. A hold that "
72
+ "expires is still a successful run")
73
+ p.add_argument("--hold-until-selector", default=None,
74
+ help="End the hold early once this selector appears (i.e. "
75
+ "the human acted). Requires --hold-seconds")
76
+ p.add_argument("--hold-until-url-excludes", default=None,
77
+ help="End the hold early once the address bar leaves this "
78
+ "host. Requires --hold-seconds")
79
+ p.add_argument("--direct", action="store_true",
80
+ help="Bypass the owning tool's serializing broker and drive "
81
+ "the browser in-process (backup; only safe when that "
82
+ "broker is stopped / idle-closed)")
83
+
84
+
85
+ def get_text(driver_factory, args) -> dict:
86
+ return api.get_text(
87
+ args.session, args.url, selector=args.selector, wait=args.wait,
88
+ headless=not args.headed, channel=args.channel,
89
+ driver_factory=driver_factory,
90
+ )
91
+
92
+
93
+ def _get_text_args(p: argparse.ArgumentParser) -> None:
94
+ p.add_argument("--session", required=True, help="Saved session name to load")
95
+ p.add_argument("--url", required=True, help="URL to navigate to")
96
+ p.add_argument("--selector", default=None,
97
+ help="Optional CSS selector; default reads the whole page body")
98
+ p.add_argument("--wait", default=None,
99
+ help="Optional selector to await before reading (for SPAs)")
100
+ p.add_argument("--headed", action="store_true", help="Show the browser window")
101
+ p.add_argument("--channel", default=None, help="Chromium channel: 'chrome'|'msedge'")
102
+ p.add_argument("--direct", action="store_true",
103
+ help="Bypass the owning tool's serializing broker and drive "
104
+ "the browser in-process (backup; only safe when that "
105
+ "broker is stopped / idle-closed)")
106
+
107
+
108
+ def screenshot(driver_factory, args) -> dict:
109
+ return api.screenshot(
110
+ args.session, args.url, args.out, full_page=not args.viewport_only,
111
+ wait=args.wait, headless=not args.headed, channel=args.channel,
112
+ driver_factory=driver_factory,
113
+ )
114
+
115
+
116
+ def _screenshot_args(p: argparse.ArgumentParser) -> None:
117
+ p.add_argument("--session", required=True, help="Saved session name to load")
118
+ p.add_argument("--url", required=True, help="URL to capture")
119
+ p.add_argument("--out", required=True, help="Output image path (.png)")
120
+ p.add_argument("--viewport-only", action="store_true",
121
+ help="Capture only the viewport (default: full page)")
122
+ p.add_argument("--wait", default=None, help="Optional selector to await first")
123
+ p.add_argument("--headed", action="store_true", help="Show the browser window")
124
+ p.add_argument("--channel", default=None, help="Chromium channel: 'chrome'|'msedge'")
125
+ p.add_argument("--direct", action="store_true",
126
+ help="Bypass the owning tool's serializing broker and drive "
127
+ "the browser in-process (backup; only safe when that "
128
+ "broker is stopped / idle-closed)")
129
+
130
+
131
+ def render_pdf(driver_factory, args) -> dict:
132
+ if bool(args.html) == bool(args.html_file):
133
+ raise UsageError("provide exactly one of --html or --html-file")
134
+ if args.html_file:
135
+ try:
136
+ with open(args.html_file, encoding="utf-8") as fh:
137
+ html = fh.read()
138
+ except OSError as exc:
139
+ raise UsageError(f"cannot read --html-file {args.html_file!r}: {exc}")
140
+ else:
141
+ html = args.html
142
+ if bool(args.width) != bool(args.height):
143
+ raise UsageError("--width and --height go together (a custom sheet needs both)")
144
+ return api.render_pdf(html, args.out, fmt=args.format,
145
+ width=args.width, height=args.height, margin=args.margin,
146
+ driver_factory=driver_factory)
147
+
148
+
149
+ def _render_pdf_args(p: argparse.ArgumentParser) -> None:
150
+ p.add_argument("--html", default=None, help="Inline HTML string to render")
151
+ p.add_argument("--html-file", dest="html_file", default=None,
152
+ help="Path to an HTML file to render")
153
+ p.add_argument("--out", required=True, help="Output PDF path (.pdf)")
154
+ p.add_argument("--format", default="A4",
155
+ help="Paper size: A4 (default) / Letter / Legal ...")
156
+ p.add_argument("--width", default=None,
157
+ help="Custom page width as a CSS length (e.g. 1000mm); needs --height, overrides --format")
158
+ p.add_argument("--height", default=None,
159
+ help="Custom page height as a CSS length (e.g. 2000mm); needs --width")
160
+ p.add_argument("--margin", default=None,
161
+ help="One CSS length for all four margins (0 for full-bleed artwork); "
162
+ "default keeps the document margins 12/14/12/12 mm")
163
+
164
+
165
+ ACTIONS = {
166
+ "run": ActionDef(
167
+ run, _run_args,
168
+ description="Load a session and run a declarative step list; return collected JSON.",
169
+ ),
170
+ "render-pdf": ActionDef(
171
+ render_pdf, _render_pdf_args,
172
+ description="Render an HTML string/file to a PDF (session-less, headless Chromium).",
173
+ ),
174
+ "get-text": ActionDef(
175
+ get_text, _get_text_args,
176
+ description="Load a session, open a URL, return visible text (whole page or a selector).",
177
+ ),
178
+ "screenshot": ActionDef(
179
+ screenshot, _screenshot_args,
180
+ description="Load a session, open a URL, save a screenshot.",
181
+ ),
182
+ }