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,228 @@
|
|
|
1
|
+
"""Single resolver for WHERE user-specific data lives.
|
|
2
|
+
|
|
3
|
+
North star: the framework (tools/, agents/, skills/, scripts/) carries ZERO
|
|
4
|
+
user-specific data. Everything user-specific - config, runtime state, knowledge,
|
|
5
|
+
resources, preferences, decisions, run history, saved sessions - lives under one
|
|
6
|
+
folder, ``context-state-knowledge/`` at the repo root. That folder is never
|
|
7
|
+
git-versioned (see .gitignore) and is safe to wipe: delete it and the framework
|
|
8
|
+
runs clean for a brand-new user.
|
|
9
|
+
|
|
10
|
+
This module is the ONE place that knows that path, so tools AND agents resolve
|
|
11
|
+
user-data locations the same way and a future move needs a single change here.
|
|
12
|
+
Agents already import ``tools._lib`` (creds, io), so this lives here rather than
|
|
13
|
+
in ``agents/_lib`` to be importable by both without a cross-package dependency.
|
|
14
|
+
|
|
15
|
+
Relocatable: set ``AAT_USERDATA_DIR`` to move the whole user-data root to another
|
|
16
|
+
path or laptop with no code change (serves the LLM-agnostic / portable direction).
|
|
17
|
+
|
|
18
|
+
Installed rather than cloned: when this ships inside a wheel there IS no repo root to
|
|
19
|
+
sit beside, so user data goes to the platform's per-user data directory instead. It must
|
|
20
|
+
never land inside the installation: that directory is replaced on upgrade (taking the
|
|
21
|
+
credentials config and run history with it), can need admin rights to write on a
|
|
22
|
+
system-wide install, and is shared by every account on the machine.
|
|
23
|
+
|
|
24
|
+
Layout under the base:
|
|
25
|
+
|
|
26
|
+
context-state-knowledge/
|
|
27
|
+
store.db # SQLite (context-store tool)
|
|
28
|
+
state/<component>/ # per-agent/tool runtime state
|
|
29
|
+
config/<component>/ # per-agent/tool user config
|
|
30
|
+
prompts/<component>/# per-user prompt copies (base+personal, agents/_lib/prompts.py)
|
|
31
|
+
sessions/ # relocated web login profiles
|
|
32
|
+
exports/ # human-readable dumps
|
|
33
|
+
|
|
34
|
+
Pure path resolution + ensure-exists. Seeding docs/DB schema is the job of the
|
|
35
|
+
context-store tool and the curator/orchestrator agents, not this module.
|
|
36
|
+
"""
|
|
37
|
+
from __future__ import annotations
|
|
38
|
+
|
|
39
|
+
import os
|
|
40
|
+
import re
|
|
41
|
+
import sys
|
|
42
|
+
from pathlib import Path
|
|
43
|
+
|
|
44
|
+
# tools/_lib/userdata.py -> parents[2] == repo root
|
|
45
|
+
_REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
46
|
+
_ENV_VAR = "AAT_USERDATA_DIR"
|
|
47
|
+
_USER_ENV = "AAT_USER_ID"
|
|
48
|
+
_WORKSPACE_ENV = "AAT_WORKSPACE_ID"
|
|
49
|
+
_DEFAULT_DIRNAME = "context-state-knowledge"
|
|
50
|
+
|
|
51
|
+
_SAFE = re.compile(r"[^0-9A-Za-z._-]+")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _safe_component(name: str) -> str:
|
|
55
|
+
"""Sanitize a component name into a single safe path segment.
|
|
56
|
+
|
|
57
|
+
Prevents path traversal (no separators, no ``..``) so a caller-supplied
|
|
58
|
+
agent/tool name can never escape the user-data root.
|
|
59
|
+
"""
|
|
60
|
+
if not name or not str(name).strip():
|
|
61
|
+
raise ValueError("component name must be a non-empty string")
|
|
62
|
+
seg = _SAFE.sub("-", str(name).strip()).strip("-._")
|
|
63
|
+
if not seg or seg in (".", ".."):
|
|
64
|
+
raise ValueError(f"invalid component name: {name!r}")
|
|
65
|
+
return seg
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _is_checkout() -> bool:
|
|
69
|
+
"""True when running from a clone rather than an installed package.
|
|
70
|
+
|
|
71
|
+
A checkout carries its own ``pyproject.toml`` beside the tree; a wheel installs the
|
|
72
|
+
tree without it. That is the cheapest honest signal - matching on "site-packages" in
|
|
73
|
+
the path guesses at a layout that varies by installer, platform and editable install.
|
|
74
|
+
"""
|
|
75
|
+
return (_REPO_ROOT / "pyproject.toml").is_file()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _platform_data_dir() -> Path:
|
|
79
|
+
"""The per-user data directory, by platform convention. Standard library only."""
|
|
80
|
+
if os.name == "nt":
|
|
81
|
+
base = os.environ.get("LOCALAPPDATA") or r"~\AppData\Local"
|
|
82
|
+
elif sys.platform == "darwin":
|
|
83
|
+
base = "~/Library/Application Support"
|
|
84
|
+
else:
|
|
85
|
+
base = os.environ.get("XDG_DATA_HOME") or "~/.local/share"
|
|
86
|
+
return Path(base).expanduser() / "procesio-cli"
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _root() -> Path:
|
|
90
|
+
override = os.environ.get(_ENV_VAR)
|
|
91
|
+
if override:
|
|
92
|
+
return Path(override).expanduser()
|
|
93
|
+
if _is_checkout():
|
|
94
|
+
return _REPO_ROOT / _DEFAULT_DIRNAME
|
|
95
|
+
return _platform_data_dir()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def current_user() -> str | None:
|
|
99
|
+
"""The active user id (``AAT_USER_ID``), sanitized to a single safe path segment,
|
|
100
|
+
or None in single-user mode. The multi-user web platform sets this per request
|
|
101
|
+
(server-established from the authenticated session, never from model output)."""
|
|
102
|
+
uid = os.environ.get(_USER_ENV)
|
|
103
|
+
return _safe_component(uid) if uid and str(uid).strip() else None
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def current_workspace() -> str | None:
|
|
107
|
+
"""The active workspace id (``AAT_WORKSPACE_ID``), sanitized to a single safe path
|
|
108
|
+
segment, or None. The multi-tenant PROCESIO module sets this per request alongside
|
|
109
|
+
``AAT_USER_ID`` (server-established from the authenticated session, never from model
|
|
110
|
+
output). Unset = no workspace dimension, exactly the historical single-workspace
|
|
111
|
+
behaviour, so local Claude Code is unaffected. Personal-workspace semantics
|
|
112
|
+
(PROCESIO ``Guid.Empty``) are the caller's concern - this resolver only sees an id."""
|
|
113
|
+
ws = os.environ.get(_WORKSPACE_ENV)
|
|
114
|
+
return _safe_component(ws) if ws and str(ws).strip() else None
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def base() -> Path:
|
|
118
|
+
"""The user-data root. Honors ``AAT_USERDATA_DIR`` (the root) and ``AAT_USER_ID``
|
|
119
|
+
(a per-user subdir under it, for the multi-user web platform). Defaults to the
|
|
120
|
+
repo's ``context-state-knowledge/``. **Unset AAT_USER_ID = single-user, exactly as
|
|
121
|
+
before** - so local Claude Code is unaffected. Every other resolver here derives
|
|
122
|
+
from ``base()``, so per-user isolation is automatic (store.db, state, config,
|
|
123
|
+
prompts, sessions, schedule, exports all move under the user's subdir). Created on
|
|
124
|
+
first access.
|
|
125
|
+
|
|
126
|
+
**Workspace dimension (``AAT_WORKSPACE_ID``):** when set, a ``ws/<ws>`` segment is
|
|
127
|
+
inserted BEFORE the user segment, so the data root is ``<root>/ws/<ws>/<user>`` -
|
|
128
|
+
isolating per ``(workspace, user)`` for the multi-tenant PROCESIO module. **Unset =
|
|
129
|
+
exactly today's paths** (``<root>`` or ``<root>/<user>``), so nothing local moves."""
|
|
130
|
+
root = _root()
|
|
131
|
+
ws = current_workspace()
|
|
132
|
+
if ws:
|
|
133
|
+
root = root / "ws" / ws
|
|
134
|
+
uid = current_user()
|
|
135
|
+
if uid:
|
|
136
|
+
root = root / uid
|
|
137
|
+
root.mkdir(parents=True, exist_ok=True)
|
|
138
|
+
return root
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def store_db_path() -> Path:
|
|
142
|
+
"""Path to the SQLite store file (parent ensured, file not created here)."""
|
|
143
|
+
base() # ensure root exists
|
|
144
|
+
return base() / "store.db"
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def state_dir(component: str) -> Path:
|
|
148
|
+
"""Per-component runtime state dir, e.g. state_dir('email-classifier')."""
|
|
149
|
+
p = base() / "state" / _safe_component(component)
|
|
150
|
+
p.mkdir(parents=True, exist_ok=True)
|
|
151
|
+
return p
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def config_dir(component: str) -> Path:
|
|
155
|
+
"""Per-component user config dir, e.g. config_dir('mysql')."""
|
|
156
|
+
p = base() / "config" / _safe_component(component)
|
|
157
|
+
p.mkdir(parents=True, exist_ok=True)
|
|
158
|
+
return p
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def prompts_dir(component: str, *, create: bool = True) -> Path:
|
|
162
|
+
"""Per-agent personal prompt copies live here (base+personal versioning;
|
|
163
|
+
agents/_lib/prompts.py). Wipe = agents fall back to their framework base
|
|
164
|
+
prompts. ``create=False`` for read paths so resolving a prompt never leaves
|
|
165
|
+
an empty dir behind."""
|
|
166
|
+
p = base() / "prompts" / _safe_component(component)
|
|
167
|
+
if create:
|
|
168
|
+
p.mkdir(parents=True, exist_ok=True)
|
|
169
|
+
return p
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def sessions_dir() -> Path:
|
|
173
|
+
"""Relocated web login profiles / broker state live here."""
|
|
174
|
+
p = base() / "sessions"
|
|
175
|
+
p.mkdir(parents=True, exist_ok=True)
|
|
176
|
+
return p
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def exports_dir() -> Path:
|
|
180
|
+
"""Human-readable dumps written by the curator live here."""
|
|
181
|
+
p = base() / "exports"
|
|
182
|
+
p.mkdir(parents=True, exist_ok=True)
|
|
183
|
+
return p
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def schedule_dir() -> Path:
|
|
187
|
+
"""The user's recurring-work schedule (schedule/*.yaml declarative entries +
|
|
188
|
+
machine-owned state.json/log.jsonl). Read and executed by the orchestrator's
|
|
189
|
+
schedule-tick; user data like everything else here - wipe = no scheduled work."""
|
|
190
|
+
p = base() / "schedule"
|
|
191
|
+
p.mkdir(parents=True, exist_ok=True)
|
|
192
|
+
return p
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def describe() -> dict:
|
|
196
|
+
"""Small status view for orchestrator/curator health reporting."""
|
|
197
|
+
b = base()
|
|
198
|
+
return {
|
|
199
|
+
"base": str(b),
|
|
200
|
+
"overridden": bool(os.environ.get(_ENV_VAR)),
|
|
201
|
+
"env_var": _ENV_VAR,
|
|
202
|
+
"user": current_user(),
|
|
203
|
+
"multi_user": current_user() is not None,
|
|
204
|
+
"workspace": current_workspace(),
|
|
205
|
+
"multi_tenant": current_workspace() is not None,
|
|
206
|
+
"store_db": str(b / "store.db"),
|
|
207
|
+
"store_db_exists": (b / "store.db").exists(),
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def scan() -> dict:
|
|
212
|
+
"""File counts across the user-data areas. This is how agents detect a fresh
|
|
213
|
+
start: a wiped folder never breaks the framework - it just scans as empty and
|
|
214
|
+
the orchestrator/curator prompt the user to start building (templates live
|
|
215
|
+
beside each component as <name>.template.json; `orchestrator bootstrap` seeds)."""
|
|
216
|
+
b = base()
|
|
217
|
+
|
|
218
|
+
def count(p: Path) -> int:
|
|
219
|
+
return sum(1 for x in p.rglob("*") if x.is_file()) if p.exists() else 0
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
"store_db_exists": (b / "store.db").exists(),
|
|
223
|
+
"config_files": count(b / "config"),
|
|
224
|
+
"state_files": count(b / "state"),
|
|
225
|
+
"session_files": count(b / "sessions"),
|
|
226
|
+
"export_files": count(b / "exports"),
|
|
227
|
+
"readme_exists": (b / "README.md").exists(),
|
|
228
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""webserialize — per-tool serializing brokers for persistent web profiles.
|
|
2
|
+
|
|
3
|
+
Two processes driving the same browser profile concurrently corrupt/invalidate
|
|
4
|
+
the web app's session (Chromium SingletonLock). This lib gives each tool ONE
|
|
5
|
+
broker process that owns its profile and executes commands strictly one at a
|
|
6
|
+
time; clients (the tool's own dispatch, and the generic web tool) submit over
|
|
7
|
+
a tiny local JSONL protocol.
|
|
8
|
+
|
|
9
|
+
Reference integration: tools/whatsapp-personal (v0.2.0 originated the pattern,
|
|
10
|
+
now a thin adapter over this lib). Registry of brokers/ports/owned sessions:
|
|
11
|
+
tools/_lib/webserialize/registry.py.
|
|
12
|
+
"""
|
|
13
|
+
from tools._lib.webserialize.config import HOST, PROTO, BrokerConfig # noqa: F401
|
|
14
|
+
from tools._lib.webserialize.errors import ( # noqa: F401
|
|
15
|
+
ServiceError, ServiceRemoteError,
|
|
16
|
+
)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""The three service-admin actions every broker-backed tool exposes.
|
|
2
|
+
|
|
3
|
+
These are plain functions over a BrokerConfig; each tool wraps them in its own
|
|
4
|
+
ActionDef (needs_driver/needs_client False) so they never route and always
|
|
5
|
+
work — even when the service is wedged.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from tools._lib.webserialize import client, runtime
|
|
10
|
+
from tools._lib.webserialize.config import BrokerConfig
|
|
11
|
+
from tools._lib.webserialize.errors import ServiceError
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def service_status(cfg: BrokerConfig) -> dict:
|
|
15
|
+
pong = client.ping(cfg)
|
|
16
|
+
if pong is None:
|
|
17
|
+
return {
|
|
18
|
+
"running": False,
|
|
19
|
+
"tool": cfg.tool,
|
|
20
|
+
"port": cfg.effective_port(),
|
|
21
|
+
"note": "no service is listening; it auto-starts on the next "
|
|
22
|
+
"browser action (or run service-start)",
|
|
23
|
+
"stale_state_file": runtime.read_state(cfg),
|
|
24
|
+
"log": str(cfg.log_path),
|
|
25
|
+
}
|
|
26
|
+
status = client.request_status(cfg) or {}
|
|
27
|
+
status.setdefault("running", True)
|
|
28
|
+
status["port"] = cfg.effective_port()
|
|
29
|
+
status["code_current"] = pong.get("code_stamp") == runtime.code_stamp(cfg)
|
|
30
|
+
if not status["code_current"]:
|
|
31
|
+
status["note"] = ("service runs STALE code (tool edited since it "
|
|
32
|
+
"started); the next routed command restarts it "
|
|
33
|
+
"automatically, or run service-stop + service-start")
|
|
34
|
+
return status
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def service_start(cfg: BrokerConfig) -> dict:
|
|
38
|
+
pong = client.ensure_running(cfg)
|
|
39
|
+
if pong is None:
|
|
40
|
+
raise ServiceError(
|
|
41
|
+
f"could not start the {cfg.tool} service; check "
|
|
42
|
+
f"{cfg.spawn_err_path} and {cfg.log_path}"
|
|
43
|
+
)
|
|
44
|
+
status = client.request_status(cfg) or {}
|
|
45
|
+
return {"running": True, "pid": pong.get("pid"),
|
|
46
|
+
"port": cfg.effective_port(), "status": status}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def service_stop(cfg: BrokerConfig, *, wait_s: float = 60) -> dict:
|
|
50
|
+
was_running = client.ping(cfg) is not None
|
|
51
|
+
stopped = client.stop(cfg, wait_s=wait_s)
|
|
52
|
+
out = {"was_running": was_running, "stopped": stopped,
|
|
53
|
+
"tool": cfg.tool, "port": cfg.effective_port()}
|
|
54
|
+
if not stopped:
|
|
55
|
+
out["note"] = ("service did not exit within the wait window "
|
|
56
|
+
"(a long command may be mid-flight); re-run, or check "
|
|
57
|
+
f"{cfg.log_path}")
|
|
58
|
+
else:
|
|
59
|
+
out["note"] = ("profile released — safe to log in "
|
|
60
|
+
"(web save-session) or use --direct")
|
|
61
|
+
return out
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"""Client side of a serializing broker. Every function takes the tool's
|
|
2
|
+
BrokerConfig first; tools call these from their dispatch routing.
|
|
3
|
+
|
|
4
|
+
Safety rules (they matter for message/state-changing commands):
|
|
5
|
+
|
|
6
|
+
* FALLBACK TO DIRECT happens ONLY when the request was never submitted —
|
|
7
|
+
no service answered and one could not be started. Running direct then is
|
|
8
|
+
safe because the failed service never opened a browser.
|
|
9
|
+
* Once a request has been SENT, a lost connection NEVER falls back: the
|
|
10
|
+
command may be mid-flight, and re-running could double-send.
|
|
11
|
+
* A running service built from STALE code (the tool was edited since it
|
|
12
|
+
started) is detected via ``code_stamp`` and transparently restarted.
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import socket
|
|
18
|
+
import subprocess
|
|
19
|
+
import sys
|
|
20
|
+
import time
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
from tools._lib.webserialize import framing, runtime
|
|
24
|
+
from tools._lib.webserialize.config import HOST, PROTO, FRAMEWORK_ROOT, BrokerConfig
|
|
25
|
+
from tools._lib.webserialize.errors import ServiceError, ServiceRemoteError
|
|
26
|
+
|
|
27
|
+
_CONNECT_TIMEOUT_S = 5
|
|
28
|
+
_SPAWN_WAIT_S = 25
|
|
29
|
+
_STOP_WAIT_S = 60
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# --------------------------------------------------------------------------- #
|
|
33
|
+
# Routing decision
|
|
34
|
+
# --------------------------------------------------------------------------- #
|
|
35
|
+
def enabled(cfg: BrokerConfig) -> bool:
|
|
36
|
+
"""Routing is ON unless explicitly disabled or we ARE the service worker."""
|
|
37
|
+
if runtime.env_truthy(cfg.direct_env):
|
|
38
|
+
return False
|
|
39
|
+
if runtime.env_truthy(cfg.worker_env):
|
|
40
|
+
return False
|
|
41
|
+
return True
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# --------------------------------------------------------------------------- #
|
|
45
|
+
# Wire helpers
|
|
46
|
+
# --------------------------------------------------------------------------- #
|
|
47
|
+
def _request(cfg: BrokerConfig, obj: dict, *, read_timeout: float,
|
|
48
|
+
port: int | None = None) -> dict:
|
|
49
|
+
"""Send one framed request, wait for the one framed response.
|
|
50
|
+
|
|
51
|
+
Connect+send failures raise OSError (caller may safely fall back: nothing
|
|
52
|
+
was accepted). After the request is on the wire, read failures raise
|
|
53
|
+
ServiceError (NOT safe to fall back)."""
|
|
54
|
+
port = port or cfg.effective_port()
|
|
55
|
+
s = socket.create_connection((HOST, port), timeout=_CONNECT_TIMEOUT_S)
|
|
56
|
+
try:
|
|
57
|
+
s.sendall(framing.encode(obj)) # OSError here -> not submitted
|
|
58
|
+
s.settimeout(read_timeout)
|
|
59
|
+
try:
|
|
60
|
+
raw = framing.recv_line(s)
|
|
61
|
+
except (OSError, ValueError) as exc:
|
|
62
|
+
raise ServiceError(
|
|
63
|
+
f"lost the {cfg.tool} service mid-request "
|
|
64
|
+
f"({exc.__class__.__name__}: {exc}). The command MAY still be "
|
|
65
|
+
"executing — check `service-status` and the target system "
|
|
66
|
+
"before retrying a state-changing command."
|
|
67
|
+
) from exc
|
|
68
|
+
if not raw.strip():
|
|
69
|
+
raise ServiceError(
|
|
70
|
+
f"the {cfg.tool} service closed the connection without a "
|
|
71
|
+
"response. The command MAY have executed — verify before retrying."
|
|
72
|
+
)
|
|
73
|
+
return framing.decode(raw)
|
|
74
|
+
finally:
|
|
75
|
+
try:
|
|
76
|
+
s.close()
|
|
77
|
+
except OSError:
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def ping(cfg: BrokerConfig, *, timeout: float = 2.0,
|
|
82
|
+
port: int | None = None) -> dict | None:
|
|
83
|
+
try:
|
|
84
|
+
resp = _request(cfg, {"op": "ping"}, read_timeout=timeout, port=port)
|
|
85
|
+
except (OSError, ServiceError, ValueError):
|
|
86
|
+
return None
|
|
87
|
+
if resp.get("ok") and (resp.get("result") or {}).get("pong"):
|
|
88
|
+
return resp["result"]
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def request_status(cfg: BrokerConfig, *, port: int | None = None) -> dict | None:
|
|
93
|
+
try:
|
|
94
|
+
resp = _request(cfg, {"op": "status"}, read_timeout=10, port=port)
|
|
95
|
+
except (OSError, ServiceError, ValueError):
|
|
96
|
+
return None
|
|
97
|
+
return resp.get("result") if resp.get("ok") else None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def stop(cfg: BrokerConfig, *, wait_s: float = _STOP_WAIT_S,
|
|
101
|
+
port: int | None = None) -> bool:
|
|
102
|
+
"""Ask the service to stop; True when it is gone (or was never running)."""
|
|
103
|
+
if ping(cfg, port=port) is None:
|
|
104
|
+
return True
|
|
105
|
+
try:
|
|
106
|
+
_request(cfg, {"op": "stop"}, read_timeout=10, port=port)
|
|
107
|
+
except (OSError, ServiceError, ValueError):
|
|
108
|
+
pass
|
|
109
|
+
deadline = time.time() + wait_s
|
|
110
|
+
while time.time() < deadline:
|
|
111
|
+
if ping(cfg, port=port) is None:
|
|
112
|
+
return True
|
|
113
|
+
time.sleep(0.3)
|
|
114
|
+
return False
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
# --------------------------------------------------------------------------- #
|
|
118
|
+
# Lifecycle
|
|
119
|
+
# --------------------------------------------------------------------------- #
|
|
120
|
+
def spawn(cfg: BrokerConfig) -> int:
|
|
121
|
+
"""Start the tool's service DETACHED. Startup errors land in
|
|
122
|
+
.service/spawn-err.log; runtime logs in service.log."""
|
|
123
|
+
py = runtime.venv_python() or Path(sys.executable)
|
|
124
|
+
cfg.service_dir.mkdir(parents=True, exist_ok=True)
|
|
125
|
+
err = open(cfg.spawn_err_path, "ab")
|
|
126
|
+
kwargs: dict = dict(stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
|
|
127
|
+
stderr=err, close_fds=True, cwd=str(FRAMEWORK_ROOT))
|
|
128
|
+
if os.name == "nt":
|
|
129
|
+
# CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP
|
|
130
|
+
kwargs["creationflags"] = 0x08000000 | 0x00000200
|
|
131
|
+
else:
|
|
132
|
+
kwargs["start_new_session"] = True
|
|
133
|
+
try:
|
|
134
|
+
proc = subprocess.Popen([str(py), str(cfg.service_py)], **kwargs)
|
|
135
|
+
finally:
|
|
136
|
+
err.close()
|
|
137
|
+
return proc.pid
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def ensure_running(cfg: BrokerConfig, *, port: int | None = None) -> dict | None:
|
|
141
|
+
"""Make sure a CURRENT-code service is up. Returns its ping payload, or
|
|
142
|
+
None when one could not be started (caller falls back to direct)."""
|
|
143
|
+
pong = ping(cfg, port=port)
|
|
144
|
+
if pong is not None:
|
|
145
|
+
stale = (pong.get("proto") != PROTO
|
|
146
|
+
or pong.get("code_stamp") != runtime.code_stamp(cfg))
|
|
147
|
+
if not stale:
|
|
148
|
+
return pong
|
|
149
|
+
# Stale daemon: restart. If it will not die, keep using it (it still
|
|
150
|
+
# serializes correctly; it just runs older code).
|
|
151
|
+
if not stop(cfg, port=port):
|
|
152
|
+
return pong
|
|
153
|
+
try:
|
|
154
|
+
spawn(cfg)
|
|
155
|
+
except OSError:
|
|
156
|
+
return None
|
|
157
|
+
deadline = time.time() + _SPAWN_WAIT_S
|
|
158
|
+
while time.time() < deadline:
|
|
159
|
+
pong = ping(cfg, port=port)
|
|
160
|
+
if pong is not None:
|
|
161
|
+
return pong
|
|
162
|
+
time.sleep(0.25)
|
|
163
|
+
return None
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# --------------------------------------------------------------------------- #
|
|
167
|
+
# The calls used by tool dispatchers
|
|
168
|
+
# --------------------------------------------------------------------------- #
|
|
169
|
+
def _timeout_for(cfg: BrokerConfig, parsed) -> float:
|
|
170
|
+
"""Generous per-request wait: the action's own waits plus queue allowance
|
|
171
|
+
(other sessions' commands run first). Env override wins."""
|
|
172
|
+
raw = os.environ.get(cfg.timeout_env, "")
|
|
173
|
+
if raw.strip():
|
|
174
|
+
try:
|
|
175
|
+
return float(raw)
|
|
176
|
+
except ValueError:
|
|
177
|
+
pass
|
|
178
|
+
wait_ms = getattr(parsed, "wait", 0) or 0
|
|
179
|
+
reply_ms = getattr(parsed, "timeout", 0) or 0
|
|
180
|
+
est = 120 + 2 * (wait_ms / 1000.0) + (reply_ms / 1000.0)
|
|
181
|
+
return max(900.0, est + 600.0)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _tag(result, resp: dict, via: str):
|
|
185
|
+
if isinstance(result, dict):
|
|
186
|
+
result.setdefault("via", via)
|
|
187
|
+
if "queue_wait_ms" in resp:
|
|
188
|
+
result.setdefault("service_queue_wait_ms", resp["queue_wait_ms"])
|
|
189
|
+
return result
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _raise_remote(resp: dict):
|
|
193
|
+
err = resp.get("error") or {}
|
|
194
|
+
raise ServiceRemoteError(
|
|
195
|
+
err.get("code") or "error",
|
|
196
|
+
err.get("message") or "service reported an error",
|
|
197
|
+
err.get("details") or {},
|
|
198
|
+
int(resp.get("exit_code") or 1),
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def call(cfg: BrokerConfig, action: str, argv: list[str], parsed, *,
|
|
203
|
+
dispatch_direct) -> dict:
|
|
204
|
+
"""Run a TOOL ACTION through the broker. ``dispatch_direct(action, argv)``
|
|
205
|
+
is the in-process fallback, used ONLY when nothing was ever submitted."""
|
|
206
|
+
pong = ensure_running(cfg)
|
|
207
|
+
if pong is None:
|
|
208
|
+
result = dispatch_direct(action, argv)
|
|
209
|
+
if isinstance(result, dict):
|
|
210
|
+
result.setdefault("via", "direct-fallback")
|
|
211
|
+
result.setdefault(
|
|
212
|
+
"service_fallback",
|
|
213
|
+
f"the {cfg.tool} serializing service could not be started; "
|
|
214
|
+
f"executed in-process instead (see {cfg.spawn_err_path})")
|
|
215
|
+
return result
|
|
216
|
+
try:
|
|
217
|
+
resp = _request(cfg, {"op": "run", "action": action, "argv": list(argv)},
|
|
218
|
+
read_timeout=_timeout_for(cfg, parsed))
|
|
219
|
+
except OSError as exc:
|
|
220
|
+
# Connect/send failed AFTER a good ping — the service just died and
|
|
221
|
+
# nothing was submitted, so direct is still safe.
|
|
222
|
+
result = dispatch_direct(action, argv)
|
|
223
|
+
if isinstance(result, dict):
|
|
224
|
+
result.setdefault("via", "direct-fallback")
|
|
225
|
+
result.setdefault("service_fallback",
|
|
226
|
+
f"service vanished before accepting the request "
|
|
227
|
+
f"({exc.__class__.__name__}); executed in-process")
|
|
228
|
+
return result
|
|
229
|
+
if resp.get("ok"):
|
|
230
|
+
return _tag(resp.get("result"), resp, "service")
|
|
231
|
+
_raise_remote(resp)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def web_steps(cfg: BrokerConfig, session: str, steps: list, *, url=None,
|
|
235
|
+
headless: bool = True, read_timeout: float | None = None,
|
|
236
|
+
dispatch_direct=None) -> dict:
|
|
237
|
+
"""Run a GENERIC web-tool step list through the broker owning ``session``
|
|
238
|
+
(how `web run/get-text/screenshot` stay serialized). Same fallback rules
|
|
239
|
+
as ``call``: ``dispatch_direct()`` (no args) only when never submitted."""
|
|
240
|
+
pong = ensure_running(cfg)
|
|
241
|
+
if pong is None:
|
|
242
|
+
if dispatch_direct is None:
|
|
243
|
+
raise ServiceError(
|
|
244
|
+
f"the {cfg.tool} service (owner of session {session!r}) could "
|
|
245
|
+
f"not be started; see {cfg.spawn_err_path}")
|
|
246
|
+
result = dispatch_direct()
|
|
247
|
+
if isinstance(result, dict):
|
|
248
|
+
result.setdefault("via", "direct-fallback")
|
|
249
|
+
return result
|
|
250
|
+
req = {"op": "web-steps", "session": session, "steps": steps,
|
|
251
|
+
"url": url, "headless": headless}
|
|
252
|
+
try:
|
|
253
|
+
resp = _request(cfg, req, read_timeout=read_timeout or 900.0)
|
|
254
|
+
except OSError:
|
|
255
|
+
if dispatch_direct is None:
|
|
256
|
+
raise ServiceError(
|
|
257
|
+
f"the {cfg.tool} service vanished before accepting the request")
|
|
258
|
+
result = dispatch_direct()
|
|
259
|
+
if isinstance(result, dict):
|
|
260
|
+
result.setdefault("via", "direct-fallback")
|
|
261
|
+
return result
|
|
262
|
+
if resp.get("ok"):
|
|
263
|
+
return _tag(resp.get("result"), resp, "service")
|
|
264
|
+
_raise_remote(resp)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""BrokerConfig — everything that parameterizes one tool's serializing broker.
|
|
2
|
+
|
|
3
|
+
One broker per tool, one fixed localhost port per broker (binding the port IS
|
|
4
|
+
the single-instance guard), one `.service/` runtime dir under the tool root.
|
|
5
|
+
The env-var names are derived from ``env_prefix`` so every tool gets the same
|
|
6
|
+
knobs (`<PREFIX>_DIRECT`, `<PREFIX>_SERVICE_PORT`, ...) — for
|
|
7
|
+
``whatsapp-personal`` the prefix is ``WHATSAPP``, which keeps the original
|
|
8
|
+
variable names working unchanged.
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
from dataclasses import dataclass, field
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
PROTO = 1
|
|
17
|
+
HOST = "127.0.0.1"
|
|
18
|
+
|
|
19
|
+
DEFAULT_IDLE_CLOSE_S = 120 # close the warm browser after this much idle
|
|
20
|
+
DEFAULT_EXIT_IDLE_S = 86400 # exit the service process after this much idle
|
|
21
|
+
|
|
22
|
+
# tools/_lib/webserialize/config.py -> repo root
|
|
23
|
+
FRAMEWORK_ROOT = Path(__file__).resolve().parents[3]
|
|
24
|
+
TOOLS_ROOT = FRAMEWORK_ROOT / "tools"
|
|
25
|
+
LIB_DIR = Path(__file__).resolve().parent
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass(frozen=True)
|
|
29
|
+
class BrokerConfig:
|
|
30
|
+
tool: str # registry key, e.g. "whatsapp-personal"
|
|
31
|
+
port: int # fixed default port (env can override)
|
|
32
|
+
env_prefix: str # "WHATSAPP" -> WHATSAPP_DIRECT, ...
|
|
33
|
+
sessions: tuple[str, ...] # persistent-profile session names it OWNS
|
|
34
|
+
code_dirs: tuple[Path, ...] = field(default=()) # *.py dirs for code_stamp
|
|
35
|
+
|
|
36
|
+
# --- paths --------------------------------------------------------------
|
|
37
|
+
@property
|
|
38
|
+
def tool_root(self) -> Path:
|
|
39
|
+
return TOOLS_ROOT / self.tool
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def service_py(self) -> Path:
|
|
43
|
+
return self.tool_root / "service.py"
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def service_dir(self) -> Path:
|
|
47
|
+
return self.tool_root / ".service"
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def state_path(self) -> Path:
|
|
51
|
+
return self.service_dir / "state.json"
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def log_path(self) -> Path:
|
|
55
|
+
return self.service_dir / "service.log"
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def spawn_err_path(self) -> Path:
|
|
59
|
+
return self.service_dir / "spawn-err.log"
|
|
60
|
+
|
|
61
|
+
# --- env knobs ------------------------------------------------------------
|
|
62
|
+
@property
|
|
63
|
+
def direct_env(self) -> str:
|
|
64
|
+
return f"{self.env_prefix}_DIRECT"
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def worker_env(self) -> str:
|
|
68
|
+
return f"{self.env_prefix}_SERVICE_WORKER"
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def port_env(self) -> str:
|
|
72
|
+
return f"{self.env_prefix}_SERVICE_PORT"
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def timeout_env(self) -> str:
|
|
76
|
+
return f"{self.env_prefix}_SERVICE_TIMEOUT_S"
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def idle_close_env(self) -> str:
|
|
80
|
+
return f"{self.env_prefix}_SERVICE_IDLE_S"
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def exit_idle_env(self) -> str:
|
|
84
|
+
return f"{self.env_prefix}_SERVICE_EXIT_S"
|
|
85
|
+
|
|
86
|
+
def effective_port(self) -> int:
|
|
87
|
+
raw = os.environ.get(self.port_env, "")
|
|
88
|
+
try:
|
|
89
|
+
return int(raw) if raw.strip() else self.port
|
|
90
|
+
except ValueError:
|
|
91
|
+
return self.port
|
|
92
|
+
|
|
93
|
+
def stamp_dirs(self) -> tuple[Path, ...]:
|
|
94
|
+
"""Dirs whose *.py mtimes form the code stamp. The lib itself is always
|
|
95
|
+
included: a webserialize change must restart every broker."""
|
|
96
|
+
return tuple(self.code_dirs) + (LIB_DIR,)
|