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.
- procesio_cli/__init__.py +18 -0
- procesio_cli/_cli.py +71 -0
- procesio_cli/agents/__init__.py +0 -0
- procesio_cli/agents/_lib/__init__.py +0 -0
- procesio_cli/agents/_lib/actiondef.py +24 -0
- procesio_cli/agents/_lib/errors.py +40 -0
- procesio_cli/agents/_lib/reversibility.py +236 -0
- procesio_cli/agents/_lib/toolrunner.py +141 -0
- procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-PLAYBOOK.md +62 -0
- procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-PROCESIO-INTEROP.md +76 -0
- procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-TROUBLESHOOTING.md +60 -0
- procesio_cli/agents/connector-builder/README.md +51 -0
- procesio_cli/agents/connector-builder/agent.yaml +61 -0
- procesio_cli/agents/connector-builder/context.py +19 -0
- procesio_cli/agents/connector-builder/handlers/__init__.py +1 -0
- procesio_cli/agents/connector-builder/handlers/checklist.py +71 -0
- procesio_cli/agents/connector-builder/handlers/guidance.py +37 -0
- procesio_cli/agents/connector-builder/handlers/nextstep.py +221 -0
- procesio_cli/agents/connector-builder/handlers/status.py +35 -0
- procesio_cli/agents/connector-builder/knowledge.py +47 -0
- procesio_cli/agents/connector-builder/main.py +93 -0
- procesio_cli/agents/connector-builder/tests/conftest.py +95 -0
- procesio_cli/agents/connector-builder/tests/test_cba_agent.py +148 -0
- procesio_cli/agents/orchestrator/__init__.py +0 -0
- procesio_cli/agents/orchestrator/bootstraplib.py +166 -0
- procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/00-INDEX.md +60 -0
- procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/01-PROCESSES.md +230 -0
- procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/02-FORMS.md +287 -0
- procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/03-INTEGRATIONS.md +384 -0
- procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/04-DATABASE.md +293 -0
- procesio_cli/agents/procesio/PROCESIO-API-RELIABILITY-DOCTRINE.md +113 -0
- procesio_cli/agents/procesio/PROCESIO-BEST-PRACTICES.md +316 -0
- procesio_cli/agents/procesio/PROCESIO-BUILD-AND-TEST-PLAYBOOK.md +217 -0
- procesio_cli/agents/procesio/PROCESIO-DATASTORE.md +72 -0
- procesio_cli/agents/procesio/PROCESIO-ENVIRONMENTS.md +62 -0
- procesio_cli/agents/procesio/PROCESIO-SCHEDULING.md +47 -0
- procesio_cli/agents/procesio/PROCESIO-VISUAL-ORGANIZATION.md +175 -0
- procesio_cli/agents/procesio/README.md +97 -0
- procesio_cli/agents/procesio/__init__.py +0 -0
- procesio_cli/agents/procesio/agent.yaml +73 -0
- procesio_cli/agents/procesio/audit.py +226 -0
- procesio_cli/agents/procesio/checklist.py +135 -0
- procesio_cli/agents/procesio/context.py +19 -0
- procesio_cli/agents/procesio/handlers/__init__.py +0 -0
- procesio_cli/agents/procesio/handlers/audit.py +39 -0
- procesio_cli/agents/procesio/handlers/checklist.py +34 -0
- procesio_cli/agents/procesio/handlers/guidance.py +36 -0
- procesio_cli/agents/procesio/handlers/status.py +33 -0
- procesio_cli/agents/procesio/handlers/verify.py +39 -0
- procesio_cli/agents/procesio/knowledge.py +115 -0
- procesio_cli/agents/procesio/main.py +89 -0
- procesio_cli/agents/procesio/tests/__init__.py +0 -0
- procesio_cli/agents/procesio/tests/conftest.py +62 -0
- procesio_cli/agents/procesio/tests/test_audit.py +91 -0
- procesio_cli/agents/procesio/tests/test_checklist.py +28 -0
- procesio_cli/agents/procesio/tests/test_guidance.py +78 -0
- procesio_cli/agents/procesio/tests/test_manifest_sync.py +48 -0
- procesio_cli/agents/procesio/tests/test_verify.py +134 -0
- procesio_cli/agents/procesio/tests/test_workspace_scope.py +97 -0
- procesio_cli/agents/procesio/verifylib.py +222 -0
- procesio_cli/dashboard/README.md +117 -0
- procesio_cli/dashboard/__init__.py +18 -0
- procesio_cli/dashboard/serve.py +98 -0
- procesio_cli/dashboard/server/__init__.py +1 -0
- procesio_cli/dashboard/server/config_schemas.py +92 -0
- procesio_cli/dashboard/server/google.py +103 -0
- procesio_cli/dashboard/server/handler.py +160 -0
- procesio_cli/dashboard/server/inventory.py +213 -0
- procesio_cli/dashboard/server/jobs.py +118 -0
- procesio_cli/dashboard/server/llmtest.py +181 -0
- procesio_cli/dashboard/server/procesio_env.py +94 -0
- procesio_cli/dashboard/server/routes.py +74 -0
- procesio_cli/dashboard/server/runner.py +150 -0
- procesio_cli/dashboard/server/security.py +29 -0
- procesio_cli/dashboard/server/setup.py +211 -0
- procesio_cli/dashboard/server/validate.py +152 -0
- procesio_cli/dashboard/tests/conftest.py +16 -0
- procesio_cli/dashboard/tests/test_dashboard.py +225 -0
- procesio_cli/dashboard/tests/test_procesio_env.py +159 -0
- procesio_cli/dashboard/web/actions.js +274 -0
- procesio_cli/dashboard/web/api.js +79 -0
- procesio_cli/dashboard/web/app.js +385 -0
- procesio_cli/dashboard/web/copilot.js +72 -0
- procesio_cli/dashboard/web/google.js +121 -0
- procesio_cli/dashboard/web/index.html +67 -0
- procesio_cli/dashboard/web/procesio_env.js +187 -0
- procesio_cli/dashboard/web/styles.css +207 -0
- procesio_cli/registry.py +370 -0
- procesio_cli/scripts/build-router.py +249 -0
- procesio_cli/scripts/build-tool-skill.py +202 -0
- procesio_cli/scripts/check-requirements.py +131 -0
- procesio_cli/scripts/check-skill-governance.py +174 -0
- procesio_cli/scripts/evaluate-skill-routing.py +217 -0
- procesio_cli/scripts/evaluate-skills.py +316 -0
- procesio_cli/scripts/get-skill.py +122 -0
- procesio_cli/scripts/list-skills.py +68 -0
- procesio_cli/scripts/list-tools.py +73 -0
- procesio_cli/scripts/run-agent.py +59 -0
- procesio_cli/scripts/run-tool.py +123 -0
- procesio_cli/scripts/secret_scan.py +584 -0
- procesio_cli/scripts/set-credential.py +126 -0
- procesio_cli/scripts/validate-skills.py +530 -0
- procesio_cli/skills/PORTFOLIO.md +134 -0
- procesio_cli/skills/__init__.py +6 -0
- procesio_cli/skills/agent-skill-engineer/SKILL.md +226 -0
- procesio_cli/skills/agent-skill-engineer/evals/evals.json +422 -0
- procesio_cli/skills/agent-skill-engineer/references/authoring-standard.md +178 -0
- procesio_cli/skills/agent-skill-engineer/references/decision-framework.md +107 -0
- procesio_cli/skills/agent-skill-engineer/references/domain-evidence-protocol.md +248 -0
- procesio_cli/skills/agent-skill-engineer/references/evaluation-standard.md +191 -0
- procesio_cli/skills/agent-skill-engineer/references/expert-lenses.md +167 -0
- procesio_cli/skills/agent-skill-engineer/references/field-gate-standard.md +231 -0
- procesio_cli/skills/agent-skill-engineer/references/optimization-protocol.md +233 -0
- procesio_cli/skills/agent-skill-engineer/references/optimizer-contract.md +268 -0
- procesio_cli/skills/agent-skill-engineer/references/portability-standard.md +99 -0
- procesio_cli/skills/agent-skill-engineer/references/research-basis.md +128 -0
- procesio_cli/skills/agent-skill-engineer/references/review-standard.md +143 -0
- procesio_cli/skills/agent-skill-engineer/scripts/audit_skill.py +959 -0
- procesio_cli/skills/agent-skill-engineer/scripts/optimize_skill.py +891 -0
- procesio_cli/skills/agent-skill-engineer/scripts/scaffold_skill.py +397 -0
- procesio_cli/skills/evals/baseline-catalog.json +14 -0
- procesio_cli/skills/evals/baseline-routing-v2.json +38 -0
- procesio_cli/skills/evals/baseline.json +37 -0
- procesio_cli/skills/evals/behavioral.json +367 -0
- procesio_cli/skills/evals/field-boundary-development-v1.json +126 -0
- procesio_cli/skills/evals/field-closeout-correction-development-v1.json +23 -0
- procesio_cli/skills/evals/field-closeout-development-v1.json +89 -0
- procesio_cli/skills/evals/portfolio-pressure-training-v1.json +83 -0
- procesio_cli/skills/evals/routing.json +363 -0
- procesio_cli/skills/evals/validation-baseline.json +4 -0
- procesio_cli/skills/procesio-cli/SKILL.md +134 -0
- procesio_cli/skills/procesio-cli/evals/evals.json +111 -0
- procesio_cli/skills/procesio-cli/evals/workflows.json +16 -0
- procesio_cli/skills/procesio-cli/references/connector-lifecycle.md +47 -0
- procesio_cli/skills/procesio-cli/references/credentials-admin.md +113 -0
- procesio_cli/skills/procesio-cli/references/data-verification.md +71 -0
- procesio_cli/skills/procesio-cli/references/documents-files.md +44 -0
- procesio_cli/skills/procesio-cli/references/form-e2e.md +57 -0
- procesio_cli/skills/procesio-cli/references/operation-contract.md +138 -0
- procesio_cli/skills/procesio-cli/references/process-debugging.md +65 -0
- procesio_cli/skills/procesio-cli/references/process-lifecycle.md +88 -0
- procesio_cli/skills/procesio-cli/references/schedules-webhooks.md +58 -0
- procesio_cli/skills/procesio-cli/references/transport-environments.md +53 -0
- procesio_cli/skills/procesio-cli-maintainer/SKILL.md +84 -0
- procesio_cli/skills/procesio-cli-maintainer/evals/evals.json +116 -0
- procesio_cli/skills/procesio-cli-maintainer/references/change-contract.md +34 -0
- procesio_cli/skills/procesio-cli-maintainer/references/mcp-compatibility.md +13 -0
- procesio_cli/skills/procesio-cli-maintainer/references/skill-authoring.md +51 -0
- procesio_cli/skills/procesio-platform-advisor/SKILL.md +82 -0
- procesio_cli/skills/procesio-platform-advisor/evals/evals.json +116 -0
- procesio_cli/skills/procesio-platform-advisor/references/capability-map.md +22 -0
- procesio_cli/skills/procesio-platform-advisor/references/fit-framework.md +35 -0
- procesio_cli/skills/procesio-platform-advisor/references/freshness-policy.md +25 -0
- procesio_cli/skills/procesio-platform-advisor/references/sizing-method.md +70 -0
- procesio_cli/skills/procesio-platform-advisor/scripts/estimate_capacity.py +99 -0
- procesio_cli/skills/procesio-setup/SKILL.md +180 -0
- procesio_cli/skills/sql-server-optimizer/SKILL.md +86 -0
- procesio_cli/skills/sql-server-optimizer/evals/evals.json +116 -0
- procesio_cli/skills/sql-server-optimizer/references/db-context.md +44 -0
- procesio_cli/skills/sql-server-optimizer/references/generic-mode.md +32 -0
- procesio_cli/skills/sql-server-optimizer/references/procesio-mode.md +40 -0
- procesio_cli/skills/sql-server-optimizer/references/sql-rules.md +43 -0
- procesio_cli/skills/sql-server-optimizer/scripts/export-indexes.sql +178 -0
- procesio_cli/skills/sql-server-optimizer/scripts/export-procs-and-functions.sql +118 -0
- procesio_cli/skills/sql-server-optimizer/scripts/export-tables.sql +367 -0
- procesio_cli/skills/tests/__init__.py +0 -0
- procesio_cli/skills/tests/test_agent_skill_engineer.py +240 -0
- procesio_cli/skills/tests/test_auth_failure_stop.py +25 -0
- procesio_cli/skills/tests/test_capacity_estimator.py +85 -0
- procesio_cli/skills/tests/test_field_boundary_learning.py +100 -0
- procesio_cli/skills/tests/test_field_closeout_learning.py +123 -0
- procesio_cli/skills/tests/test_field_gate_standard.py +76 -0
- procesio_cli/skills/tests/test_operational_playbooks.py +51 -0
- procesio_cli/skills/tests/test_portfolio_pressure_training.py +35 -0
- procesio_cli/skills/tests/test_process_lifecycle_single_run.py +25 -0
- procesio_cli/skills/tests/test_skill_evaluator.py +67 -0
- procesio_cli/skills/tests/test_skill_optimizer.py +473 -0
- procesio_cli/skills/tests/test_skill_portfolio_review.py +70 -0
- procesio_cli/skills/tests/test_skill_release_binding.py +204 -0
- procesio_cli/skills/tests/test_skill_routing.py +74 -0
- procesio_cli/skills/tests/test_skill_scaffold_v2.py +116 -0
- procesio_cli/skills/tests/test_validate_skills.py +115 -0
- procesio_cli/tools/__init__.py +0 -0
- procesio_cli/tools/_lib/README.md +119 -0
- procesio_cli/tools/_lib/__init__.py +0 -0
- procesio_cli/tools/_lib/accounting.py +120 -0
- procesio_cli/tools/_lib/contacts.py +544 -0
- procesio_cli/tools/_lib/creds.py +83 -0
- procesio_cli/tools/_lib/creds_backends.py +578 -0
- procesio_cli/tools/_lib/dbprofiles.py +147 -0
- procesio_cli/tools/_lib/dbquery.py +286 -0
- procesio_cli/tools/_lib/dbschema.py +225 -0
- procesio_cli/tools/_lib/io.py +54 -0
- procesio_cli/tools/_lib/manifest.py +297 -0
- procesio_cli/tools/_lib/skill_release.py +127 -0
- procesio_cli/tools/_lib/skill_resources.py +118 -0
- procesio_cli/tools/_lib/userdata.py +228 -0
- procesio_cli/tools/_lib/webserialize/__init__.py +16 -0
- procesio_cli/tools/_lib/webserialize/admin.py +61 -0
- procesio_cli/tools/_lib/webserialize/client.py +264 -0
- procesio_cli/tools/_lib/webserialize/config.py +96 -0
- procesio_cli/tools/_lib/webserialize/errors.py +27 -0
- procesio_cli/tools/_lib/webserialize/framing.py +45 -0
- procesio_cli/tools/_lib/webserialize/registry.py +47 -0
- procesio_cli/tools/_lib/webserialize/runtime.py +61 -0
- procesio_cli/tools/_lib/webserialize/server.py +510 -0
- procesio_cli/tools/_lib/websession.py +194 -0
- procesio_cli/tools/connector-builder/CONNECTOR-BUILDER-API-NOTES.md +91 -0
- procesio_cli/tools/connector-builder/README.md +101 -0
- procesio_cli/tools/connector-builder/SKILL.md +248 -0
- procesio_cli/tools/connector-builder/__init__.py +7 -0
- procesio_cli/tools/connector-builder/actiondef.py +24 -0
- procesio_cli/tools/connector-builder/client.py +251 -0
- procesio_cli/tools/connector-builder/errors.py +44 -0
- procesio_cli/tools/connector-builder/gen_manifest.py +142 -0
- procesio_cli/tools/connector-builder/handlers/__init__.py +1 -0
- procesio_cli/tools/connector-builder/handlers/admin.py +182 -0
- procesio_cli/tools/connector-builder/handlers/auth.py +74 -0
- procesio_cli/tools/connector-builder/handlers/builds.py +396 -0
- procesio_cli/tools/connector-builder/handlers/common.py +104 -0
- procesio_cli/tools/connector-builder/handlers/files.py +111 -0
- procesio_cli/tools/connector-builder/handlers/raw.py +38 -0
- procesio_cli/tools/connector-builder/handlers/telemetry.py +39 -0
- procesio_cli/tools/connector-builder/main.py +94 -0
- procesio_cli/tools/connector-builder/tests/conftest.py +146 -0
- procesio_cli/tools/connector-builder/tests/test_cb_client.py +86 -0
- procesio_cli/tools/connector-builder/tests/test_cb_dispatch.py +105 -0
- procesio_cli/tools/connector-builder/tests/test_cb_manifest_sync.py +76 -0
- procesio_cli/tools/connector-builder/tests/test_cb_wait.py +123 -0
- procesio_cli/tools/connector-builder/tool.yaml +671 -0
- procesio_cli/tools/framework-map/.gitattributes +2 -0
- procesio_cli/tools/framework-map/README.md +98 -0
- procesio_cli/tools/framework-map/SKILL.md +30 -0
- procesio_cli/tools/framework-map/app.js +188 -0
- procesio_cli/tools/framework-map/fm_builder.py +476 -0
- procesio_cli/tools/framework-map/fm_catalog.py +19 -0
- procesio_cli/tools/framework-map/fm_ro_catalog.py +94 -0
- procesio_cli/tools/framework-map/fm_strings.py +101 -0
- procesio_cli/tools/framework-map/main.py +95 -0
- procesio_cli/tools/framework-map/styles.css +214 -0
- procesio_cli/tools/framework-map/tests/conftest.py +33 -0
- procesio_cli/tools/framework-map/tests/test_fm_build.py +126 -0
- procesio_cli/tools/framework-map/tests/test_fm_manifest_sync.py +63 -0
- procesio_cli/tools/framework-map/tests/test_fm_store_tree.py +75 -0
- procesio_cli/tools/framework-map/tool.yaml +61 -0
- procesio_cli/tools/mysql/MOVED-TO-CENTRAL.md +29 -0
- procesio_cli/tools/mysql/README.md +196 -0
- procesio_cli/tools/mysql/SKILL.md +37 -0
- procesio_cli/tools/mysql/__init__.py +0 -0
- procesio_cli/tools/mysql/connection.py +191 -0
- procesio_cli/tools/mysql/main.py +487 -0
- procesio_cli/tools/mysql/profiles.template.json +1 -0
- procesio_cli/tools/mysql/schema.py +434 -0
- procesio_cli/tools/mysql/tests/__init__.py +0 -0
- procesio_cli/tools/mysql/tests/conftest.py +21 -0
- procesio_cli/tools/mysql/tests/test_manifest_sync.py +68 -0
- procesio_cli/tools/mysql/tests/test_mysql.py +201 -0
- procesio_cli/tools/mysql/tests/test_mysql_schema.py +337 -0
- procesio_cli/tools/mysql/tool.yaml +112 -0
- procesio_cli/tools/procesio/DTO-SUBTOOLS-NOTE.md +360 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/00-INDEX.md +67 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/01-ANATOMY.md +209 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/02-CODE-INJECTION.md +309 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/03-DOM-CONTRACT.md +370 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/04-INTERACTION-RECIPES.md +600 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/05-STEPPER-AND-MOTION.md +426 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/06-PROCESS-INTEGRATION.md +347 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/07-DEPLOY-WORKFLOW.md +294 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/08-PITFALLS.md +569 -0
- procesio_cli/tools/procesio/FORM-DEV-GUIDE/09-NAVIGATION-AND-HOSTING.md +308 -0
- procesio_cli/tools/procesio/PHASE4-E2E-NOTES.md +594 -0
- procesio_cli/tools/procesio/PROCESIO-API-CORRECTIONS.md +295 -0
- procesio_cli/tools/procesio/PROCESIO-API-NOTES.md +6976 -0
- procesio_cli/tools/procesio/PROCESIO-AUTH-NOTES.md +226 -0
- procesio_cli/tools/procesio/PROCESIO-CARD-BUILD-NOTES.md +183 -0
- procesio_cli/tools/procesio/PROCESIO-CONNECTORS-NOTES.md +141 -0
- procesio_cli/tools/procesio/PROCESIO-CUSTOM-ACTION-NOTES.md +179 -0
- procesio_cli/tools/procesio/PROCESIO-DOCS-FIX-REPORT.md +123 -0
- procesio_cli/tools/procesio/PROCESIO-ENVIRONMENTS-NOTES.md +94 -0
- procesio_cli/tools/procesio/PROCESIO-FE-VALIDATION-NOTES.md +107 -0
- procesio_cli/tools/procesio/PROCESIO-FOREACH-NOTES.md +199 -0
- procesio_cli/tools/procesio/PROCESIO-FORM-API-HANG-NOTE.md +101 -0
- procesio_cli/tools/procesio/PROCESIO-FORM-SUBMISSION-NOTES.md +172 -0
- procesio_cli/tools/procesio/PROCESIO-HTML-TO-DOCX-NOTES.md +110 -0
- procesio_cli/tools/procesio/PROCESIO-INSTANCE-HISTORY-NOTES.md +242 -0
- procesio_cli/tools/procesio/PROCESIO-METERING-NOTES.md +201 -0
- procesio_cli/tools/procesio/PROCESIO-NODE-CODE-NOTES.md +279 -0
- procesio_cli/tools/procesio/PROCESIO-NODE-MODULE-WHITELIST.md +113 -0
- procesio_cli/tools/procesio/PROCESIO-PYTHON-ACTION-NOTES.md +165 -0
- procesio_cli/tools/procesio/PROCESIO-QUERY-STORE-NOTES.md +826 -0
- procesio_cli/tools/procesio/PROCESIO-RECONCILIATION-PATTERNS.md +104 -0
- procesio_cli/tools/procesio/PROCESIO-RESOURCE-MODEL-NOTES.md +1100 -0
- procesio_cli/tools/procesio/PROCESIO-SEND-EMAIL-CRED-OPTIONALITY.md +45 -0
- procesio_cli/tools/procesio/PROCESIO-SEND-EMAIL-NOTES.md +252 -0
- procesio_cli/tools/procesio/PROCESIO-SQL-ACTIONS-NOTES.md +284 -0
- procesio_cli/tools/procesio/PROCESIO-USAGE-GUIDE.md +219 -0
- procesio_cli/tools/procesio/README.md +341 -0
- procesio_cli/tools/procesio/SCHEDULE-INPUT-SECURITY-NOTES.md +63 -0
- procesio_cli/tools/procesio/SKILL.md +694 -0
- procesio_cli/tools/procesio/__init__.py +1 -0
- procesio_cli/tools/procesio/actiondef.py +27 -0
- procesio_cli/tools/procesio/assets/html2docx/html2docx.js +2155 -0
- procesio_cli/tools/procesio/auth.py +354 -0
- procesio_cli/tools/procesio/autogen.py +121 -0
- procesio_cli/tools/procesio/client.py +355 -0
- procesio_cli/tools/procesio/config.py +96 -0
- procesio_cli/tools/procesio/data/endpoints.json +2901 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/01-authentication.md +180 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/02-conventions.md +116 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/ANONYMOUS-SURFACE.md +51 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/README.md +104 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/SYMBOL-INDEX.md +444 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/03-auth-users-workspaces.md +731 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/04-processes.md +913 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/05-actions.md +605 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/06-files.md +237 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/07-forms-documents.md +985 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/08-credentials.md +532 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/09-datastore-datatypes.md +830 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/10-custom-urls.md +319 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/11-subscriptions-resources-analytics.md +455 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/12-webhooks-notifications-misc.md +519 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/13-realtime-signalr.md +153 -0
- procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/99-internal-and-other-services.md +52 -0
- procesio_cli/tools/procesio/docs_info/FormBuilder mock.ts +5725 -0
- procesio_cli/tools/procesio/docs_info/Procesio Platform Actions.json +30219 -0
- procesio_cli/tools/procesio/docs_info/form-config-enums.ts +92 -0
- procesio_cli/tools/procesio/docs_info/form-theme.ts +1603 -0
- procesio_cli/tools/procesio/docs_info/process-validation-reference-1.md +2739 -0
- procesio_cli/tools/procesio/dto/__init__.py +13 -0
- procesio_cli/tools/procesio/dto/credential/builder.py +179 -0
- procesio_cli/tools/procesio/dto/credential/config.schema.json +19 -0
- procesio_cli/tools/procesio/dto/credential/description.md +193 -0
- procesio_cli/tools/procesio/dto/credential/fixtures/rest.config.json +11 -0
- procesio_cli/tools/procesio/dto/credential/fixtures/rest.dto.json +28 -0
- procesio_cli/tools/procesio/dto/credential/fixtures/rest.template.json +44 -0
- procesio_cli/tools/procesio/dto/credential/template.dto.json +16 -0
- procesio_cli/tools/procesio/dto/data/_refresh.py +147 -0
- procesio_cli/tools/procesio/dto/data/action_catalog.json +30825 -0
- procesio_cli/tools/procesio/dto/data/action_families.json +55 -0
- procesio_cli/tools/procesio/dto/data/platform_types.json +182 -0
- procesio_cli/tools/procesio/dto/datatype/builder.py +223 -0
- procesio_cli/tools/procesio/dto/datatype/config.schema.json +47 -0
- procesio_cli/tools/procesio/dto/datatype/description.md +85 -0
- procesio_cli/tools/procesio/dto/datatype/fixtures/customer.config.json +41 -0
- procesio_cli/tools/procesio/dto/datatype/fixtures/customer.dto.json +164 -0
- procesio_cli/tools/procesio/dto/datatype/template.dto.json +37 -0
- procesio_cli/tools/procesio/dto/document/builder.py +193 -0
- procesio_cli/tools/procesio/dto/document/config.schema.json +33 -0
- procesio_cli/tools/procesio/dto/document/description.md +124 -0
- procesio_cli/tools/procesio/dto/document/fixtures/invoice.config.json +16 -0
- procesio_cli/tools/procesio/dto/document/fixtures/invoice.dto.json +32 -0
- procesio_cli/tools/procesio/dto/document/template.dto.json +14 -0
- procesio_cli/tools/procesio/dto/form/FORM-STYLING-NOTES.md +142 -0
- procesio_cli/tools/procesio/dto/form/GOLDEN-DRIFT-NOTES.md +72 -0
- procesio_cli/tools/procesio/dto/form/RUN-PROCESS-RESULT-NOTES.md +80 -0
- procesio_cli/tools/procesio/dto/form/addelement.py +277 -0
- procesio_cli/tools/procesio/dto/form/builder.py +1009 -0
- procesio_cli/tools/procesio/dto/form/capture_goldens.py +106 -0
- procesio_cli/tools/procesio/dto/form/code_cipher.py +67 -0
- procesio_cli/tools/procesio/dto/form/config.schema.json +76 -0
- procesio_cli/tools/procesio/dto/form/data_shell.json +1 -0
- procesio_cli/tools/procesio/dto/form/description.md +346 -0
- procesio_cli/tools/procesio/dto/form/elements/approval.json +259 -0
- procesio_cli/tools/procesio/dto/form/elements/assignee.json +137 -0
- procesio_cli/tools/procesio/dto/form/elements/button.json +125 -0
- procesio_cli/tools/procesio/dto/form/elements/chart.json +341 -0
- procesio_cli/tools/procesio/dto/form/elements/chat.json +199 -0
- procesio_cli/tools/procesio/dto/form/elements/checkbox.json +153 -0
- procesio_cli/tools/procesio/dto/form/elements/column.json +77 -0
- procesio_cli/tools/procesio/dto/form/elements/columns.json +78 -0
- procesio_cli/tools/procesio/dto/form/elements/datetime-input.json +304 -0
- procesio_cli/tools/procesio/dto/form/elements/divider.json +54 -0
- procesio_cli/tools/procesio/dto/form/elements/dropdown.json +130 -0
- procesio_cli/tools/procesio/dto/form/elements/dynamic-table-row.json +253 -0
- procesio_cli/tools/procesio/dto/form/elements/file-upload.json +196 -0
- procesio_cli/tools/procesio/dto/form/elements/file-viewer.json +169 -0
- procesio_cli/tools/procesio/dto/form/elements/heading.json +79 -0
- procesio_cli/tools/procesio/dto/form/elements/icon.json +107 -0
- procesio_cli/tools/procesio/dto/form/elements/image.json +174 -0
- procesio_cli/tools/procesio/dto/form/elements/input.json +206 -0
- procesio_cli/tools/procesio/dto/form/elements/list.json +202 -0
- procesio_cli/tools/procesio/dto/form/elements/number-input.json +202 -0
- procesio_cli/tools/procesio/dto/form/elements/paragraph.json +79 -0
- procesio_cli/tools/procesio/dto/form/elements/radiobox.json +174 -0
- procesio_cli/tools/procesio/dto/form/elements/section.json +114 -0
- procesio_cli/tools/procesio/dto/form/elements/select.json +217 -0
- procesio_cli/tools/procesio/dto/form/elements/side-panel.json +146 -0
- procesio_cli/tools/procesio/dto/form/elements/signature-pad.json +141 -0
- procesio_cli/tools/procesio/dto/form/elements/static-table-row.json +84 -0
- procesio_cli/tools/procesio/dto/form/elements/step.json +105 -0
- procesio_cli/tools/procesio/dto/form/elements/stepper.json +126 -0
- procesio_cli/tools/procesio/dto/form/elements/tab.json +77 -0
- procesio_cli/tools/procesio/dto/form/elements/table.json +279 -0
- procesio_cli/tools/procesio/dto/form/elements/tabs.json +114 -0
- procesio_cli/tools/procesio/dto/form/elements/textarea.json +213 -0
- procesio_cli/tools/procesio/dto/form/enum_map.json +68 -0
- procesio_cli/tools/procesio/dto/form/fieldpath.py +284 -0
- procesio_cli/tools/procesio/dto/form/fixtures/reg.config.json +32 -0
- procesio_cli/tools/procesio/dto/form/fixtures/reg.elements.json +638 -0
- procesio_cli/tools/procesio/dto/form/sync_from_mock.py +386 -0
- procesio_cli/tools/procesio/dto/framework.py +125 -0
- procesio_cli/tools/procesio/dto/process/builder.py +1991 -0
- procesio_cli/tools/procesio/dto/process/config.schema.json +159 -0
- procesio_cli/tools/procesio/dto/process/description.md +218 -0
- procesio_cli/tools/procesio/dto/process/fixtures/greet.config.json +32 -0
- procesio_cli/tools/procesio/dto/process/fixtures/greet.dto.json +317 -0
- procesio_cli/tools/procesio/dto/process/naming.py +305 -0
- procesio_cli/tools/procesio/dto/process/normalize.py +74 -0
- procesio_cli/tools/procesio/dto/process/template.dto.json +32 -0
- procesio_cli/tools/procesio/dto/refdata.py +87 -0
- procesio_cli/tools/procesio/dto/registry.py +27 -0
- procesio_cli/tools/procesio/dto/webhook/builder.py +142 -0
- procesio_cli/tools/procesio/dto/webhook/config.schema.json +25 -0
- procesio_cli/tools/procesio/dto/webhook/description.md +92 -0
- procesio_cli/tools/procesio/dto/webhook/fixtures/order.config.json +10 -0
- procesio_cli/tools/procesio/dto/webhook/fixtures/order.dto.json +25 -0
- procesio_cli/tools/procesio/dto/webhook/template.dto.json +14 -0
- procesio_cli/tools/procesio/environments.py +264 -0
- procesio_cli/tools/procesio/errors.py +166 -0
- procesio_cli/tools/procesio/flowmodel/README.md +37 -0
- procesio_cli/tools/procesio/flowmodel/__init__.py +14 -0
- procesio_cli/tools/procesio/flowmodel/digest.py +223 -0
- procesio_cli/tools/procesio/flowmodel/families.py +34 -0
- procesio_cli/tools/procesio/flowmodel/fevalidation.py +1098 -0
- procesio_cli/tools/procesio/flowmodel/formdigest.py +232 -0
- procesio_cli/tools/procesio/flowmodel/inspect.py +78 -0
- procesio_cli/tools/procesio/flowmodel/model.py +82 -0
- procesio_cli/tools/procesio/flowmodel/nodeparam.py +871 -0
- procesio_cli/tools/procesio/flowmodel/reader.py +191 -0
- procesio_cli/tools/procesio/flowmodel/sqlparam.py +410 -0
- procesio_cli/tools/procesio/form_code_keys.py +50 -0
- procesio_cli/tools/procesio/formlint.py +292 -0
- procesio_cli/tools/procesio/gen_manifest.py +118 -0
- procesio_cli/tools/procesio/handlers/__init__.py +1 -0
- procesio_cli/tools/procesio/handlers/auth_actions.py +103 -0
- procesio_cli/tools/procesio/handlers/catalog.py +147 -0
- procesio_cli/tools/procesio/handlers/common.py +90 -0
- procesio_cli/tools/procesio/handlers/customaction_ops.py +146 -0
- procesio_cli/tools/procesio/handlers/datastore_ops.py +482 -0
- procesio_cli/tools/procesio/handlers/datatype_ops.py +275 -0
- procesio_cli/tools/procesio/handlers/dto_actions.py +258 -0
- procesio_cli/tools/procesio/handlers/environment_admin.py +146 -0
- procesio_cli/tools/procesio/handlers/fevalidate.py +236 -0
- procesio_cli/tools/procesio/handlers/files.py +141 -0
- procesio_cli/tools/procesio/handlers/flowgraph.py +229 -0
- procesio_cli/tools/procesio/handlers/flowlint.py +269 -0
- procesio_cli/tools/procesio/handlers/form_chains.py +336 -0
- procesio_cli/tools/procesio/handlers/form_code.py +277 -0
- procesio_cli/tools/procesio/handlers/form_element.py +199 -0
- procesio_cli/tools/procesio/handlers/form_events.py +441 -0
- procesio_cli/tools/procesio/handlers/form_update.py +270 -0
- procesio_cli/tools/procesio/handlers/formprocess.py +211 -0
- procesio_cli/tools/procesio/handlers/generic.py +135 -0
- procesio_cli/tools/procesio/handlers/layout.py +137 -0
- procesio_cli/tools/procesio/handlers/nodeparams.py +1018 -0
- procesio_cli/tools/procesio/handlers/process_layout.py +189 -0
- procesio_cli/tools/procesio/handlers/process_naming.py +213 -0
- procesio_cli/tools/procesio/handlers/processes.py +416 -0
- procesio_cli/tools/procesio/handlers/profile_admin.py +184 -0
- procesio_cli/tools/procesio/handlers/resource_ops.py +447 -0
- procesio_cli/tools/procesio/handlers/schedules.py +320 -0
- procesio_cli/tools/procesio/handlers/sqlactions.py +232 -0
- procesio_cli/tools/procesio/handlers/transport.py +463 -0
- procesio_cli/tools/procesio/handlers/usageguide.py +222 -0
- procesio_cli/tools/procesio/layout/README.md +196 -0
- procesio_cli/tools/procesio/layout/__init__.py +11 -0
- procesio_cli/tools/procesio/layout/adapter.py +736 -0
- procesio_cli/tools/procesio/layout/cycles.py +186 -0
- procesio_cli/tools/procesio/layout/dispatch.py +39 -0
- procesio_cli/tools/procesio/layout/elk/elk_runner.mjs +50 -0
- procesio_cli/tools/procesio/layout/elk/package-lock.json +21 -0
- procesio_cli/tools/procesio/layout/elk/package.json +11 -0
- procesio_cli/tools/procesio/layout/elk_engine.py +568 -0
- procesio_cli/tools/procesio/layout/engine.py +1311 -0
- procesio_cli/tools/procesio/layout/report.py +187 -0
- procesio_cli/tools/procesio/main.py +179 -0
- procesio_cli/tools/procesio/profiles.py +193 -0
- procesio_cli/tools/procesio/reliability.py +193 -0
- procesio_cli/tools/procesio/sqlformat.py +167 -0
- procesio_cli/tools/procesio/swagger.py +51 -0
- procesio_cli/tools/procesio/tests/__init__.py +0 -0
- procesio_cli/tools/procesio/tests/conftest.py +129 -0
- procesio_cli/tools/procesio/tests/test_auth.py +200 -0
- procesio_cli/tools/procesio/tests/test_autogen.py +78 -0
- procesio_cli/tools/procesio/tests/test_builder_attrpath_sqlbind.py +180 -0
- procesio_cli/tools/procesio/tests/test_builder_custom_action_catalog.py +72 -0
- procesio_cli/tools/procesio/tests/test_client.py +114 -0
- procesio_cli/tools/procesio/tests/test_client_reliability.py +139 -0
- procesio_cli/tools/procesio/tests/test_customaction.py +103 -0
- procesio_cli/tools/procesio/tests/test_customaction_test.py +80 -0
- procesio_cli/tools/procesio/tests/test_cycles.py +69 -0
- procesio_cli/tools/procesio/tests/test_datastore.py +378 -0
- procesio_cli/tools/procesio/tests/test_datastore_node.py +94 -0
- procesio_cli/tools/procesio/tests/test_dispatch.py +170 -0
- procesio_cli/tools/procesio/tests/test_document_page_size.py +19 -0
- procesio_cli/tools/procesio/tests/test_dto.py +734 -0
- procesio_cli/tools/procesio/tests/test_edit_dryrun_preview.py +96 -0
- procesio_cli/tools/procesio/tests/test_elk_layout.py +221 -0
- procesio_cli/tools/procesio/tests/test_environments.py +214 -0
- procesio_cli/tools/procesio/tests/test_fevalidate_gate.py +104 -0
- procesio_cli/tools/procesio/tests/test_fevalidation.py +317 -0
- procesio_cli/tools/procesio/tests/test_fieldpath_variables.py +87 -0
- procesio_cli/tools/procesio/tests/test_files.py +72 -0
- procesio_cli/tools/procesio/tests/test_flow_digest.py +202 -0
- procesio_cli/tools/procesio/tests/test_flowlint.py +114 -0
- procesio_cli/tools/procesio/tests/test_flowmodel.py +158 -0
- procesio_cli/tools/procesio/tests/test_form_add_element.py +256 -0
- procesio_cli/tools/procesio/tests/test_form_approval_gaps.py +319 -0
- procesio_cli/tools/procesio/tests/test_form_auto_names.py +60 -0
- procesio_cli/tools/procesio/tests/test_form_chains.py +217 -0
- procesio_cli/tools/procesio/tests/test_form_code_actions.py +188 -0
- procesio_cli/tools/procesio/tests/test_form_code_keys.py +92 -0
- procesio_cli/tools/procesio/tests/test_form_code_style.py +178 -0
- procesio_cli/tools/procesio/tests/test_form_delete_element.py +99 -0
- procesio_cli/tools/procesio/tests/test_form_element_config.py +141 -0
- procesio_cli/tools/procesio/tests/test_form_event_maps.py +135 -0
- procesio_cli/tools/procesio/tests/test_form_event_ops.py +376 -0
- procesio_cli/tools/procesio/tests/test_form_event_replace.py +86 -0
- procesio_cli/tools/procesio/tests/test_form_events.py +92 -0
- procesio_cli/tools/procesio/tests/test_form_parity.py +171 -0
- procesio_cli/tools/procesio/tests/test_form_select_source.py +74 -0
- procesio_cli/tools/procesio/tests/test_form_sync.py +35 -0
- procesio_cli/tools/procesio/tests/test_form_update.py +133 -0
- procesio_cli/tools/procesio/tests/test_formlint.py +155 -0
- procesio_cli/tools/procesio/tests/test_formlint_css_scope.py +38 -0
- procesio_cli/tools/procesio/tests/test_formlint_field_names.py +83 -0
- procesio_cli/tools/procesio/tests/test_guards.py +110 -0
- procesio_cli/tools/procesio/tests/test_hidden_setting_types.py +39 -0
- procesio_cli/tools/procesio/tests/test_html2docx_asset.py +132 -0
- procesio_cli/tools/procesio/tests/test_key_handle_terminology.py +45 -0
- procesio_cli/tools/procesio/tests/test_layout.py +574 -0
- procesio_cli/tools/procesio/tests/test_layout_report.py +88 -0
- procesio_cli/tools/procesio/tests/test_manifest_sync.py +68 -0
- procesio_cli/tools/procesio/tests/test_nodedelete.py +151 -0
- procesio_cli/tools/procesio/tests/test_nodeparam.py +826 -0
- procesio_cli/tools/procesio/tests/test_normalize.py +70 -0
- procesio_cli/tools/procesio/tests/test_payload_docs.py +86 -0
- procesio_cli/tools/procesio/tests/test_process_action_naming.py +170 -0
- procesio_cli/tools/procesio/tests/test_process_call_api_seed.py +46 -0
- procesio_cli/tools/procesio/tests/test_process_ext.py +373 -0
- procesio_cli/tools/procesio/tests/test_process_invariants.py +183 -0
- procesio_cli/tools/procesio/tests/test_process_layout.py +117 -0
- procesio_cli/tools/procesio/tests/test_process_naming.py +188 -0
- procesio_cli/tools/procesio/tests/test_process_query_store.py +172 -0
- procesio_cli/tools/procesio/tests/test_processinfo_variable.py +56 -0
- procesio_cli/tools/procesio/tests/test_profiles.py +127 -0
- procesio_cli/tools/procesio/tests/test_put_projects.py +41 -0
- procesio_cli/tools/procesio/tests/test_reliability.py +107 -0
- procesio_cli/tools/procesio/tests/test_removal_gate.py +95 -0
- procesio_cli/tools/procesio/tests/test_resource_ops.py +173 -0
- procesio_cli/tools/procesio/tests/test_save_validity.py +207 -0
- procesio_cli/tools/procesio/tests/test_schedule_cron_shape.py +111 -0
- procesio_cli/tools/procesio/tests/test_schedules.py +309 -0
- procesio_cli/tools/procesio/tests/test_sqlconvert.py +234 -0
- procesio_cli/tools/procesio/tests/test_sqlformat.py +83 -0
- procesio_cli/tools/procesio/tests/test_sqlparam.py +187 -0
- procesio_cli/tools/procesio/tests/test_superseded_actions.py +54 -0
- procesio_cli/tools/procesio/tests/test_surgical_concurrency.py +156 -0
- procesio_cli/tools/procesio/tests/test_tier4.py +123 -0
- procesio_cli/tools/procesio/tests/test_transport.py +147 -0
- procesio_cli/tools/procesio/tests/test_transport_data_stores.py +168 -0
- procesio_cli/tools/procesio/tests/test_transport_mapper_repair.py +150 -0
- procesio_cli/tools/procesio/tests/test_transport_webhook_strip.py +253 -0
- procesio_cli/tools/procesio/tests/test_usage_guide.py +96 -0
- procesio_cli/tools/procesio/tool.yaml +12486 -0
- procesio_cli/tools/sqlserver/MOVED-TO-CENTRAL.md +29 -0
- procesio_cli/tools/sqlserver/README.md +192 -0
- procesio_cli/tools/sqlserver/SKILL.md +37 -0
- procesio_cli/tools/sqlserver/SQLSERVER-SCHEMA-NOTES.md +284 -0
- procesio_cli/tools/sqlserver/__init__.py +0 -0
- procesio_cli/tools/sqlserver/connection.py +242 -0
- procesio_cli/tools/sqlserver/main.py +521 -0
- procesio_cli/tools/sqlserver/profiles.template.json +1 -0
- procesio_cli/tools/sqlserver/schema.py +600 -0
- procesio_cli/tools/sqlserver/tests/__init__.py +0 -0
- procesio_cli/tools/sqlserver/tests/conftest.py +21 -0
- procesio_cli/tools/sqlserver/tests/test_connection.py +75 -0
- procesio_cli/tools/sqlserver/tests/test_dbprofiles.py +92 -0
- procesio_cli/tools/sqlserver/tests/test_dbquery.py +220 -0
- procesio_cli/tools/sqlserver/tests/test_manifest_sync.py +68 -0
- procesio_cli/tools/sqlserver/tests/test_sqlserver.py +326 -0
- procesio_cli/tools/sqlserver/tests/test_sqlserver_schema.py +488 -0
- procesio_cli/tools/sqlserver/tool.yaml +123 -0
- procesio_cli/tools/web/README.md +381 -0
- procesio_cli/tools/web/SKILL.md +37 -0
- procesio_cli/tools/web/WEB-AUTOMATION-NOTES.md +277 -0
- procesio_cli/tools/web/__init__.py +21 -0
- procesio_cli/tools/web/actiondef.py +24 -0
- procesio_cli/tools/web/api.py +444 -0
- procesio_cli/tools/web/brokered.py +107 -0
- procesio_cli/tools/web/driver.py +839 -0
- procesio_cli/tools/web/drivercontract.py +44 -0
- procesio_cli/tools/web/errors.py +54 -0
- procesio_cli/tools/web/handlers/__init__.py +1 -0
- procesio_cli/tools/web/handlers/archive.py +367 -0
- procesio_cli/tools/web/handlers/browse.py +182 -0
- procesio_cli/tools/web/handlers/contacts.py +74 -0
- procesio_cli/tools/web/handlers/sessmgmt.py +120 -0
- procesio_cli/tools/web/main.py +128 -0
- procesio_cli/tools/web/sessions.py +253 -0
- procesio_cli/tools/web/steps.py +162 -0
- procesio_cli/tools/web/tests/__init__.py +0 -0
- procesio_cli/tools/web/tests/conftest.py +197 -0
- procesio_cli/tools/web/tests/test_api.py +330 -0
- procesio_cli/tools/web/tests/test_archive.py +190 -0
- procesio_cli/tools/web/tests/test_brokered.py +138 -0
- procesio_cli/tools/web/tests/test_dispatch.py +132 -0
- procesio_cli/tools/web/tests/test_errors.py +60 -0
- procesio_cli/tools/web/tests/test_manifest_sync.py +76 -0
- procesio_cli/tools/web/tests/test_page_contacts.py +68 -0
- procesio_cli/tools/web/tests/test_sessions.py +145 -0
- procesio_cli/tools/web/tests/test_steps.py +210 -0
- procesio_cli/tools/web/tool.yaml +184 -0
- procesio_cli/tools/xlsx/README.md +34 -0
- procesio_cli/tools/xlsx/SKILL.md +28 -0
- procesio_cli/tools/xlsx/__init__.py +0 -0
- procesio_cli/tools/xlsx/main.py +129 -0
- procesio_cli/tools/xlsx/reader.py +91 -0
- procesio_cli/tools/xlsx/tests/__init__.py +0 -0
- procesio_cli/tools/xlsx/tests/conftest.py +39 -0
- procesio_cli/tools/xlsx/tests/test_xlsx.py +103 -0
- procesio_cli/tools/xlsx/tool.yaml +30 -0
- procesio_cli/webplatform/aat_mcp/AAT-MCP-NOTES.md +244 -0
- procesio_cli/webplatform/aat_mcp/README.md +78 -0
- procesio_cli/webplatform/aat_mcp/bridge.py +705 -0
- procesio_cli/webplatform/aat_mcp/chat_server.py +194 -0
- procesio_cli/webplatform/aat_mcp/chat_surface.snapshot.json +668 -0
- procesio_cli/webplatform/aat_mcp/chat_surface.yaml +372 -0
- procesio_cli/webplatform/aat_mcp/gate.py +68 -0
- procesio_cli/webplatform/aat_mcp/http_server.py +139 -0
- procesio_cli/webplatform/aat_mcp/protocol.py +175 -0
- procesio_cli/webplatform/aat_mcp/server.py +306 -0
- procesio_cli/webplatform/aat_mcp/tests/conftest.py +8 -0
- procesio_cli/webplatform/aat_mcp/tests/test_aat_mcp.py +255 -0
- procesio_cli/webplatform/aat_mcp/tests/test_chat_surface.py +247 -0
- procesio_cli/webplatform/aat_mcp/tests/test_discovery.py +489 -0
- procesio_cli/webplatform/aat_mcp/tests/test_multiuser.py +86 -0
- procesio_cli/webplatform/aat_mcp/tests/test_progressive_discovery.py +89 -0
- procesio_cli/webplatform/aat_mcp/tests/test_protocol.py +180 -0
- procesio_cli/webplatform/aat_mcp/tests/test_skill_discovery.py +23 -0
- procesio_cli-0.1.1.dist-info/METADATA +467 -0
- procesio_cli-0.1.1.dist-info/RECORD +647 -0
- procesio_cli-0.1.1.dist-info/WHEEL +4 -0
- procesio_cli-0.1.1.dist-info/entry_points.txt +7 -0
- procesio_cli-0.1.1.dist-info/licenses/LICENSE +201 -0
- procesio_cli-0.1.1.dist-info/licenses/NOTICE +5 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""page-contacts - the contact details a public page publishes, without a browser.
|
|
2
|
+
|
|
3
|
+
For link-in-bio pages (Linktree, Beacons, Stan, ...) and personal sites: one plain
|
|
4
|
+
HTTP GET with a browser User-Agent, then the shared extractor
|
|
5
|
+
(tools._lib.contacts) over mailto links, anchors, visible text and the profile
|
|
6
|
+
links that link-in-bio services embed as JSON. No session, no login, nothing is
|
|
7
|
+
clicked or submitted, and no address is guessed - only what the page shows.
|
|
8
|
+
|
|
9
|
+
A page that answers 4xx/5xx is a normal outcome when scanning many creators, so it
|
|
10
|
+
comes back as ``reachable: false`` rather than an error. A network failure (DNS,
|
|
11
|
+
timeout, TLS) is an error.
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
|
|
17
|
+
from tools._lib import contacts as extractor
|
|
18
|
+
from tools.web.actiondef import ActionDef
|
|
19
|
+
from tools.web.errors import UsageError
|
|
20
|
+
from tools.web.handlers.archive import _HEADERS
|
|
21
|
+
|
|
22
|
+
MAX_BYTES = 2_000_000
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _fetch(url: str, timeout: int) -> tuple[str, int, str, str]:
|
|
26
|
+
"""GET url. Returns (text, status, content_type, final_url)."""
|
|
27
|
+
import requests
|
|
28
|
+
try:
|
|
29
|
+
resp = requests.get(url, headers=_HEADERS, timeout=timeout, allow_redirects=True)
|
|
30
|
+
except Exception as exc: # noqa: BLE001 - network shape varies by failure
|
|
31
|
+
raise UsageError(f"fetch failed for {url!r}: {exc}")
|
|
32
|
+
body = resp.content[:MAX_BYTES]
|
|
33
|
+
encoding = resp.encoding or "utf-8"
|
|
34
|
+
try:
|
|
35
|
+
text = body.decode(encoding, errors="replace")
|
|
36
|
+
except LookupError:
|
|
37
|
+
text = body.decode("utf-8", errors="replace")
|
|
38
|
+
return text, resp.status_code, resp.headers.get("Content-Type", ""), resp.url
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def page_contacts(args) -> dict:
|
|
42
|
+
url = (args.url or "").strip()
|
|
43
|
+
if not url:
|
|
44
|
+
raise UsageError("--url is required")
|
|
45
|
+
if not url.lower().startswith(("http://", "https://")):
|
|
46
|
+
url = "https://" + url
|
|
47
|
+
text, status, content_type, final_url = _fetch(url, args.timeout)
|
|
48
|
+
out = {"url": url, "final_url": final_url, "status": status,
|
|
49
|
+
"content_type": content_type, "reachable": 200 <= status < 400}
|
|
50
|
+
if not out["reachable"]:
|
|
51
|
+
out.update(extractor.empty_result())
|
|
52
|
+
out["title"] = ""
|
|
53
|
+
return out
|
|
54
|
+
ctype = content_type.lower()
|
|
55
|
+
if "html" in ctype or "<html" in text[:2000].lower():
|
|
56
|
+
out.update(extractor.extract_html(text, base_url=final_url))
|
|
57
|
+
else:
|
|
58
|
+
out.update(extractor.extract(text))
|
|
59
|
+
out["title"] = ""
|
|
60
|
+
return out
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _args(p: argparse.ArgumentParser) -> None:
|
|
64
|
+
p.add_argument("--url", required=True, help="Public page to read (link-in-bio, personal site)")
|
|
65
|
+
p.add_argument("--timeout", type=int, default=20, help="Request timeout in seconds (default 20)")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
ACTIONS = {
|
|
69
|
+
"page-contacts": ActionDef(
|
|
70
|
+
page_contacts, _args, needs_driver=False,
|
|
71
|
+
description=("Emails, profile links and affiliate links a public page "
|
|
72
|
+
"publishes (one plain GET; no browser, no session)."),
|
|
73
|
+
),
|
|
74
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""Session-management handlers: save-session, list-sessions, delete-session.
|
|
2
|
+
|
|
3
|
+
These do NOT receive an injected driver (``needs_driver=False``):
|
|
4
|
+
* ``save-session`` is interactive - it launches its own HEADED browser via the
|
|
5
|
+
public API and blocks for a human ENTER before saving storageState.
|
|
6
|
+
* ``list-sessions`` / ``delete-session`` only touch the sessions directory.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import argparse
|
|
11
|
+
|
|
12
|
+
from tools.web import api, sessions
|
|
13
|
+
from tools.web.actiondef import ActionDef
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _release_owning_broker(name: str) -> str | None:
|
|
17
|
+
"""If a serializing broker owns this session (whatsapp/ryver/fgo/mirro),
|
|
18
|
+
stop it first: its warm browser may hold the profile, and capturing or
|
|
19
|
+
deleting a session under it would race the broker. Returns the owning
|
|
20
|
+
tool's name when a running broker was stopped, else None. Best-effort —
|
|
21
|
+
a broker that cannot be reached must not block a login capture."""
|
|
22
|
+
try:
|
|
23
|
+
from tools._lib.webserialize import client as ws_client
|
|
24
|
+
from tools._lib.webserialize import registry as ws_registry
|
|
25
|
+
except Exception: # noqa: BLE001 - lib unavailable must never block
|
|
26
|
+
return None
|
|
27
|
+
cfg = ws_registry.owner_of_session(name)
|
|
28
|
+
if cfg is None:
|
|
29
|
+
return None
|
|
30
|
+
try:
|
|
31
|
+
if ws_client.ping(cfg) is None:
|
|
32
|
+
return None
|
|
33
|
+
ws_client.stop(cfg)
|
|
34
|
+
return cfg.tool
|
|
35
|
+
except Exception: # noqa: BLE001
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def save_session(args) -> dict:
|
|
40
|
+
"""Capture a login session interactively (headed browser + ENTER signal)."""
|
|
41
|
+
stopped = _release_owning_broker(args.name)
|
|
42
|
+
out = api.save_session(args.name, args.url, channel=args.channel,
|
|
43
|
+
persistent=args.persistent,
|
|
44
|
+
wait_seconds=getattr(args, "wait_seconds", None),
|
|
45
|
+
wait_until_url_excludes=getattr(
|
|
46
|
+
args, "wait_until_url_excludes", None))
|
|
47
|
+
if stopped:
|
|
48
|
+
out["broker_stopped"] = stopped
|
|
49
|
+
out["note"] = (f"the {stopped} serializing broker was stopped to free "
|
|
50
|
+
"the session; it auto-restarts on that tool's next command")
|
|
51
|
+
return out
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _save_session_args(p: argparse.ArgumentParser) -> None:
|
|
55
|
+
p.add_argument("--name", required=True,
|
|
56
|
+
help="Session name (letters/digits/._-; how you'll reference it later)")
|
|
57
|
+
p.add_argument("--url", required=True,
|
|
58
|
+
help="Login URL to open in the headed browser")
|
|
59
|
+
p.add_argument("--channel", default=None,
|
|
60
|
+
help="Optional Chromium channel: 'chrome' or 'msedge' "
|
|
61
|
+
"(use a real browser instead of the bundled Chromium)")
|
|
62
|
+
p.add_argument("--persistent", action="store_true",
|
|
63
|
+
help="Save a PERSISTENT browser profile (user-data-dir) instead "
|
|
64
|
+
"of a storageState snapshot. Required for IndexedDB-auth "
|
|
65
|
+
"sites like WhatsApp Web whose login a snapshot can't restore.")
|
|
66
|
+
p.add_argument("--wait-seconds", type=int, default=None,
|
|
67
|
+
help="Wait this long for the login instead of blocking on ENTER. "
|
|
68
|
+
"REQUIRED when an agent launches this flow: agent stdin is "
|
|
69
|
+
"EOF, so the ENTER wait returns instantly and saves a "
|
|
70
|
+
"half-authenticated profile.")
|
|
71
|
+
p.add_argument("--wait-until-url-excludes", default=None,
|
|
72
|
+
help="With --wait-seconds, finish as soon as the address bar "
|
|
73
|
+
"leaves this host (e.g. 'accounts.google.com'), instead of "
|
|
74
|
+
"waiting the full time.")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def list_sessions(args) -> dict:
|
|
78
|
+
items = sessions.list_all()
|
|
79
|
+
return {
|
|
80
|
+
"sessions": items,
|
|
81
|
+
"count": len(items),
|
|
82
|
+
"dir": str(sessions.sessions_dir()),
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def delete_session(args) -> dict:
|
|
87
|
+
sessions.validate_name(args.name)
|
|
88
|
+
confirm = getattr(args, "confirm", False)
|
|
89
|
+
# Only disturb the broker when we are actually going to delete; a preview
|
|
90
|
+
# must not have side effects.
|
|
91
|
+
stopped = _release_owning_broker(args.name) if confirm else None
|
|
92
|
+
out = sessions.delete(args.name, confirm=confirm)
|
|
93
|
+
if stopped:
|
|
94
|
+
out["broker_stopped"] = stopped
|
|
95
|
+
return out
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _delete_session_args(p: argparse.ArgumentParser) -> None:
|
|
99
|
+
p.add_argument("--name", required=True, help="Session name to delete")
|
|
100
|
+
p.add_argument("--confirm", action="store_true",
|
|
101
|
+
help="Actually delete. Without it this only PREVIEWS what "
|
|
102
|
+
"would be removed - deleting a session destroys a login "
|
|
103
|
+
"that only a human at a browser can re-establish.")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
ACTIONS = {
|
|
107
|
+
"save-session": ActionDef(
|
|
108
|
+
save_session, _save_session_args, needs_driver=False,
|
|
109
|
+
description="Interactively capture a login session (headed browser; press ENTER to save).",
|
|
110
|
+
),
|
|
111
|
+
"list-sessions": ActionDef(
|
|
112
|
+
list_sessions, needs_driver=False,
|
|
113
|
+
description="List saved sessions (names + metadata only, never contents).",
|
|
114
|
+
),
|
|
115
|
+
"delete-session": ActionDef(
|
|
116
|
+
delete_session, _delete_session_args, needs_driver=False,
|
|
117
|
+
description="Delete ALL of a saved session's artifacts (storageState + "
|
|
118
|
+
"persistent profile + cookie sidecar). Previews unless --confirm.",
|
|
119
|
+
),
|
|
120
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""web tool entrypoint - action dispatch (Playwright-driven, no HTTP API).
|
|
2
|
+
|
|
3
|
+
Drives web apps that have no API, reusing saved login sessions (Playwright
|
|
4
|
+
storageState). Sessions are sensitive auth material stored in the central
|
|
5
|
+
git-ignored user-data folder (context-state-knowledge/sessions/) - see
|
|
6
|
+
sessions.py and tools/web/sessions/README.md.
|
|
7
|
+
|
|
8
|
+
Actions:
|
|
9
|
+
save-session capture a login session interactively (headed browser)
|
|
10
|
+
list-sessions list saved sessions (metadata only)
|
|
11
|
+
delete-session remove a saved session
|
|
12
|
+
run run a declarative step list against a saved session
|
|
13
|
+
get-text load a session, open a URL, return visible text
|
|
14
|
+
screenshot load a session, open a URL, save a screenshot
|
|
15
|
+
archive-document capture a published document (original + self-contained + extraction)
|
|
16
|
+
|
|
17
|
+
Playwright is imported lazily (inside the driver) so this tool and its tests
|
|
18
|
+
load even before the browser binaries are installed.
|
|
19
|
+
"""
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import sys
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
|
|
25
|
+
TOOL_ROOT = Path(__file__).resolve().parent
|
|
26
|
+
FRAMEWORK_ROOT = TOOL_ROOT.parents[1]
|
|
27
|
+
_VENV_PY = FRAMEWORK_ROOT / ".venv" / "Scripts" / "python.exe"
|
|
28
|
+
if _VENV_PY.exists() and Path(sys.executable).resolve() != _VENV_PY.resolve():
|
|
29
|
+
import subprocess
|
|
30
|
+
sys.exit(subprocess.run([str(_VENV_PY), __file__, *sys.argv[1:]]).returncode)
|
|
31
|
+
|
|
32
|
+
import argparse # noqa: E402
|
|
33
|
+
|
|
34
|
+
if str(FRAMEWORK_ROOT) not in sys.path:
|
|
35
|
+
sys.path.insert(0, str(FRAMEWORK_ROOT))
|
|
36
|
+
|
|
37
|
+
from tools._lib.io import emit, fail # noqa: E402
|
|
38
|
+
from tools.web import errors # noqa: E402
|
|
39
|
+
from tools.web.actiondef import ActionDef # noqa: E402
|
|
40
|
+
from tools.web.driver import PlaywrightDriver # noqa: E402
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class _Parser(argparse.ArgumentParser):
|
|
44
|
+
def error(self, message: str):
|
|
45
|
+
raise errors.UsageError(message)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def collect_actions() -> dict[str, ActionDef]:
|
|
49
|
+
actions: dict[str, ActionDef] = {}
|
|
50
|
+
from tools.web.handlers import archive, browse, contacts, sessmgmt
|
|
51
|
+
actions.update(sessmgmt.ACTIONS)
|
|
52
|
+
actions.update(browse.ACTIONS)
|
|
53
|
+
actions.update(archive.ACTIONS)
|
|
54
|
+
actions.update(contacts.ACTIONS)
|
|
55
|
+
return actions
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
ACTIONS = collect_actions()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _default_driver_factory(*, storage_state=None, headless=True, channel=None,
|
|
62
|
+
user_data_dir=None, extra_args=None):
|
|
63
|
+
"""Production factory injected into driver-based handlers. Returns an
|
|
64
|
+
UNSTARTED PlaywrightDriver; the API layer calls .start().
|
|
65
|
+
|
|
66
|
+
Accepts ``user_data_dir`` so the API layer can drive a PERSISTENT profile
|
|
67
|
+
session (auto-detected from a ``<name>.profile`` dir) through the CLI, not
|
|
68
|
+
just storageState sessions. Also accepts ``extra_args`` because the
|
|
69
|
+
persistent-profile path in ``api.open_session`` forwards it to the factory
|
|
70
|
+
(matches ``api._default_factory``); without it, ``web run/get-text/screenshot``
|
|
71
|
+
on any persistent profile raised an unexpected-keyword TypeError."""
|
|
72
|
+
return PlaywrightDriver(storage_state=storage_state, headless=headless,
|
|
73
|
+
channel=channel, user_data_dir=user_data_dir,
|
|
74
|
+
extra_args=extra_args)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def dispatch(action: str, argv: list[str], *, driver_factory=None,
|
|
78
|
+
allow_service: bool = True) -> dict:
|
|
79
|
+
if action not in ACTIONS:
|
|
80
|
+
raise errors.UsageError(
|
|
81
|
+
f"unknown action: {action}. Known: {', '.join(sorted(ACTIONS))}"
|
|
82
|
+
)
|
|
83
|
+
defn = ACTIONS[action]
|
|
84
|
+
parser = _Parser(prog=f"web {action}", description=defn.description)
|
|
85
|
+
defn.add_args(parser)
|
|
86
|
+
parsed = parser.parse_args(argv)
|
|
87
|
+
|
|
88
|
+
# BROKER-OWNED SESSIONS: when the target session belongs to a serializing
|
|
89
|
+
# broker (whatsapp/ryver/fgo/mirro — see tools/_lib/webserialize/registry),
|
|
90
|
+
# the generic browser actions are translated to a step list and executed
|
|
91
|
+
# INSIDE that broker, serialized with the owning tool's own commands. A
|
|
92
|
+
# direct run against an owned profile could race the broker's warm browser
|
|
93
|
+
# and invalidate the session. Unowned sessions behave exactly as before.
|
|
94
|
+
if defn.needs_driver:
|
|
95
|
+
from tools.web import brokered
|
|
96
|
+
cfg = brokered.eligible(parsed, driver_factory=driver_factory,
|
|
97
|
+
allow_service=allow_service)
|
|
98
|
+
if cfg is not None:
|
|
99
|
+
return brokered.route(
|
|
100
|
+
cfg, action, parsed,
|
|
101
|
+
dispatch_direct=lambda: dispatch(action, argv,
|
|
102
|
+
allow_service=False),
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
if defn.needs_driver:
|
|
106
|
+
factory = driver_factory or _default_driver_factory
|
|
107
|
+
return defn.func(factory, parsed)
|
|
108
|
+
return defn.func(parsed)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def main(argv=None) -> None:
|
|
112
|
+
argv = list(sys.argv[1:] if argv is None else argv)
|
|
113
|
+
if not argv or argv[0] in ("-h", "--help"):
|
|
114
|
+
print("Actions:", file=sys.stderr)
|
|
115
|
+
for name in sorted(ACTIONS):
|
|
116
|
+
print(f" {name:<16} {ACTIONS[name].description}", file=sys.stderr)
|
|
117
|
+
sys.exit(0)
|
|
118
|
+
action, rest = argv[0], argv[1:]
|
|
119
|
+
try:
|
|
120
|
+
result = dispatch(action, rest)
|
|
121
|
+
except Exception as exc: # noqa: BLE001
|
|
122
|
+
code, message, details, exit_code = errors.classify(exc)
|
|
123
|
+
fail(code, message, details, exit_code)
|
|
124
|
+
emit(result)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
if __name__ == "__main__":
|
|
128
|
+
main()
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"""Saved-session storage for the web tool.
|
|
2
|
+
|
|
3
|
+
A *session* is a Playwright ``storageState`` JSON file (cookies + localStorage)
|
|
4
|
+
captured after a human logged in once. It lets later headless runs reuse that
|
|
5
|
+
authentication. These files contain live auth material and are therefore
|
|
6
|
+
**sensitive**:
|
|
7
|
+
|
|
8
|
+
* They live under ``context-state-knowledge/sessions/<name>.json`` - the
|
|
9
|
+
central, git-ignored user-data folder (framework/user-data separation;
|
|
10
|
+
moved from tools/web/sessions/ on 2026-07-05).
|
|
11
|
+
* That folder is never committed (see the repo .gitignore).
|
|
12
|
+
* They are never printed or logged. ``list-sessions`` reports names and
|
|
13
|
+
metadata (size, mtime) only - never file contents.
|
|
14
|
+
|
|
15
|
+
Session names are validated to a safe charset so a name can never escape the
|
|
16
|
+
sessions directory (no path traversal, no separators).
|
|
17
|
+
"""
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
import re
|
|
22
|
+
import shutil
|
|
23
|
+
import time
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
from tools.web.errors import SessionError, UsageError
|
|
27
|
+
from tools._lib import userdata
|
|
28
|
+
|
|
29
|
+
# Saved sessions are USER data (live auth for the user's accounts), so they live
|
|
30
|
+
# in the central user-data folder - context-state-knowledge/sessions/ - not in
|
|
31
|
+
# the tool dir (framework/user-data separation; migrated 2026-07-05, see
|
|
32
|
+
# tools/web/sessions/README.md breadcrumb). Resolved via tools/_lib/userdata.py,
|
|
33
|
+
# relocatable with AAT_USERDATA_DIR.
|
|
34
|
+
SESSIONS_DIR = userdata.sessions_dir()
|
|
35
|
+
|
|
36
|
+
_NAME_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def validate_name(name: str) -> str:
|
|
40
|
+
"""Return the name if it is a safe session identifier, else raise UsageError.
|
|
41
|
+
|
|
42
|
+
Allowed: letters, digits, dot, dash, underscore; must start alphanumeric;
|
|
43
|
+
1-64 chars. This blocks path traversal ('..', '/', '\\') by construction.
|
|
44
|
+
"""
|
|
45
|
+
if not isinstance(name, str) or not _NAME_RE.match(name):
|
|
46
|
+
raise UsageError(
|
|
47
|
+
f"invalid session name {name!r}: use 1-64 chars of "
|
|
48
|
+
"letters/digits/._- starting with a letter or digit"
|
|
49
|
+
)
|
|
50
|
+
return name
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def sessions_dir() -> Path:
|
|
54
|
+
SESSIONS_DIR.mkdir(parents=True, exist_ok=True)
|
|
55
|
+
return SESSIONS_DIR
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def session_path(name: str) -> Path:
|
|
59
|
+
"""Absolute path to a session file. Validates the name first."""
|
|
60
|
+
validate_name(name)
|
|
61
|
+
return sessions_dir() / f"{name}.json"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def exists(name: str) -> bool:
|
|
65
|
+
return session_path(name).exists()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# --- persistent browser profiles ------------------------------------------
|
|
69
|
+
# Some sites (notably WhatsApp Web) keep their auth in IndexedDB, which a
|
|
70
|
+
# storageState snapshot cannot reliably restore — WhatsApp rejects a
|
|
71
|
+
# deserialized copy with "a database error occurred". For those, the web tool
|
|
72
|
+
# uses a PERSISTENT browser profile (a Chromium user-data-dir): the native
|
|
73
|
+
# on-disk profile is reused as-is, so the login survives across runs.
|
|
74
|
+
|
|
75
|
+
def profile_dir(name: str) -> Path:
|
|
76
|
+
"""Absolute path to a session's persistent browser-profile directory."""
|
|
77
|
+
validate_name(name)
|
|
78
|
+
return sessions_dir() / f"{name}.profile"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def profile_exists(name: str) -> bool:
|
|
82
|
+
"""True if a non-empty persistent profile directory exists for the name."""
|
|
83
|
+
d = profile_dir(name)
|
|
84
|
+
return d.is_dir() and any(d.iterdir())
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def require_profile(name: str) -> Path:
|
|
88
|
+
"""Return an existing persistent profile dir or raise SessionError."""
|
|
89
|
+
if not profile_exists(name):
|
|
90
|
+
raise SessionError(
|
|
91
|
+
f"no persistent profile for {name!r}. Capture one with: "
|
|
92
|
+
f"python scripts/run-tool.py web save-session --name {name} "
|
|
93
|
+
f"--url <login-url> --persistent"
|
|
94
|
+
)
|
|
95
|
+
return profile_dir(name)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def require(name: str) -> Path:
|
|
99
|
+
"""Return the path to an existing session or raise SessionError."""
|
|
100
|
+
p = session_path(name)
|
|
101
|
+
if not p.exists():
|
|
102
|
+
raise SessionError(
|
|
103
|
+
f"no saved session named {name!r}. Capture one with: "
|
|
104
|
+
f"python scripts/run-tool.py web save-session --name {name} --url <login-url>"
|
|
105
|
+
)
|
|
106
|
+
return p
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def load_state(name: str) -> dict:
|
|
110
|
+
"""Read and parse a session's storageState JSON. Raises SessionError on
|
|
111
|
+
a missing or corrupt file. The returned dict is the Playwright storage_state."""
|
|
112
|
+
p = require(name)
|
|
113
|
+
try:
|
|
114
|
+
# utf-8-sig tolerates a stray BOM if a session file was hand-edited.
|
|
115
|
+
return json.loads(p.read_text(encoding="utf-8-sig"))
|
|
116
|
+
except (ValueError, OSError) as exc:
|
|
117
|
+
raise SessionError(f"session {name!r} is unreadable/corrupt: {exc}") from exc
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def write_state(name: str, state: dict) -> Path:
|
|
121
|
+
"""Persist a storageState dict to the session file. Returns the path."""
|
|
122
|
+
p = session_path(name)
|
|
123
|
+
p.write_text(json.dumps(state, ensure_ascii=False), encoding="utf-8")
|
|
124
|
+
return p
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def artifacts(name: str) -> list[tuple[str, Path]]:
|
|
128
|
+
"""Every on-disk artifact belonging to a session, as (kind, path).
|
|
129
|
+
|
|
130
|
+
A session is up to THREE files, not one: the storageState snapshot, the
|
|
131
|
+
persistent browser profile, and the cookie sidecar. Anything that forgets
|
|
132
|
+
the last two leaves a stale login behind - ``open_session`` auto-detects
|
|
133
|
+
``<name>.profile`` and will silently reuse it.
|
|
134
|
+
"""
|
|
135
|
+
validate_name(name)
|
|
136
|
+
return [
|
|
137
|
+
("state", session_path(name)),
|
|
138
|
+
("profile", profile_dir(name)),
|
|
139
|
+
("cookies", cookies_path(name)),
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def present_artifacts(name: str) -> list[str]:
|
|
144
|
+
"""Kinds that actually exist on disk for ``name``."""
|
|
145
|
+
out = []
|
|
146
|
+
for kind, path in artifacts(name):
|
|
147
|
+
if (profile_exists(name) if kind == "profile" else path.exists()):
|
|
148
|
+
out.append(kind)
|
|
149
|
+
return out
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def delete(name: str, *, confirm: bool = False) -> dict:
|
|
153
|
+
"""Delete ALL of a session's artifacts (state + profile + cookie sidecar).
|
|
154
|
+
|
|
155
|
+
Deleting a session destroys a real login that only a human at a browser can
|
|
156
|
+
re-establish, so this REFUSES to act unless ``confirm=True``. Without it the
|
|
157
|
+
call is a non-destructive preview reporting ``would_remove`` - which also
|
|
158
|
+
serves as the dry run. Returns a report; never raises for a missing session.
|
|
159
|
+
"""
|
|
160
|
+
validate_name(name)
|
|
161
|
+
present = present_artifacts(name)
|
|
162
|
+
if not present:
|
|
163
|
+
return {"session": name, "deleted": False, "existed": False, "removed": []}
|
|
164
|
+
if not confirm:
|
|
165
|
+
return {"session": name, "deleted": False, "existed": True, "removed": [],
|
|
166
|
+
"would_remove": present, "confirmation_required": True}
|
|
167
|
+
|
|
168
|
+
removed: list[str] = []
|
|
169
|
+
failed: dict[str, str] = {}
|
|
170
|
+
for kind, path in artifacts(name):
|
|
171
|
+
if kind not in present:
|
|
172
|
+
continue
|
|
173
|
+
try:
|
|
174
|
+
if kind == "profile":
|
|
175
|
+
shutil.rmtree(path)
|
|
176
|
+
else:
|
|
177
|
+
path.unlink()
|
|
178
|
+
removed.append(kind)
|
|
179
|
+
except OSError as exc: # e.g. Windows lock: a browser still has the profile
|
|
180
|
+
failed[kind] = str(exc)
|
|
181
|
+
|
|
182
|
+
out = {"session": name, "existed": True, "removed": removed,
|
|
183
|
+
"deleted": bool(removed) and not failed}
|
|
184
|
+
if failed:
|
|
185
|
+
out["failed"] = failed
|
|
186
|
+
out["note"] = ("some artifacts could not be removed - a browser or "
|
|
187
|
+
"serializing broker may still hold the profile; close it "
|
|
188
|
+
"and retry")
|
|
189
|
+
return out
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
# --- cookie sidecar (for persistent profiles) ------------------------------
|
|
193
|
+
# A persistent Chromium profile persists localStorage + IndexedDB to disk, but
|
|
194
|
+
# Chromium NEVER writes *session-scoped* cookies (no Expires/Max-Age) to the
|
|
195
|
+
# profile — they live in memory and vanish when the browser closes. Apps that
|
|
196
|
+
# authenticate with a session cookie (e.g. Ryver) therefore appear logged-out on
|
|
197
|
+
# every reopen of an otherwise-valid profile. The fix: at save time, while the
|
|
198
|
+
# browser is still alive, snapshot ALL cookies (session ones included) to this
|
|
199
|
+
# sidecar; at open time, re-inject them into the fresh context before navigating.
|
|
200
|
+
# The file holds live auth material — same sensitivity/gitignore as the profile.
|
|
201
|
+
|
|
202
|
+
def cookies_path(name: str) -> Path:
|
|
203
|
+
"""Absolute path to a persistent session's cookie sidecar JSON."""
|
|
204
|
+
validate_name(name)
|
|
205
|
+
return sessions_dir() / f"{name}.cookies.json"
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def cookies_exist(name: str) -> bool:
|
|
209
|
+
return cookies_path(name).exists()
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def write_cookies(name: str, cookies: list[dict]) -> Path:
|
|
213
|
+
"""Persist a list of Playwright cookie dicts. Returns the path."""
|
|
214
|
+
p = cookies_path(name)
|
|
215
|
+
p.write_text(json.dumps(cookies, ensure_ascii=False), encoding="utf-8")
|
|
216
|
+
return p
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def load_cookies(name: str) -> list[dict]:
|
|
220
|
+
"""Read a session's cookie sidecar. Returns [] if absent or unreadable
|
|
221
|
+
(best-effort: a corrupt sidecar must not block opening the profile)."""
|
|
222
|
+
p = cookies_path(name)
|
|
223
|
+
if not p.exists():
|
|
224
|
+
return []
|
|
225
|
+
try:
|
|
226
|
+
data = json.loads(p.read_text(encoding="utf-8-sig"))
|
|
227
|
+
return data if isinstance(data, list) else []
|
|
228
|
+
except (ValueError, OSError):
|
|
229
|
+
return []
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def _meta(p: Path, *, persistent: bool = False) -> dict:
|
|
233
|
+
st = p.stat()
|
|
234
|
+
return {
|
|
235
|
+
"name": p.stem,
|
|
236
|
+
"bytes": st.st_size,
|
|
237
|
+
"modified": time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime(st.st_mtime)),
|
|
238
|
+
"persistent": persistent,
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def list_all() -> list[dict]:
|
|
243
|
+
"""List saved sessions (metadata only, never contents). Sorted by name.
|
|
244
|
+
|
|
245
|
+
Includes BOTH storageState sessions (``<name>.json``) and persistent browser
|
|
246
|
+
profiles (``<name>.profile/``); the ``persistent`` flag tells them apart.
|
|
247
|
+
Without the profiles, a session saved via ``--persistent`` would be invisible
|
|
248
|
+
here even though it exists and is usable.
|
|
249
|
+
"""
|
|
250
|
+
d = sessions_dir()
|
|
251
|
+
items = [_meta(p) for p in d.glob("*.json")]
|
|
252
|
+
items += [_meta(p, persistent=True) for p in d.glob("*.profile") if p.is_dir()]
|
|
253
|
+
return sorted(items, key=lambda i: i["name"])
|