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,489 @@
|
|
|
1
|
+
"""Targeted capability discovery: one action, keyword search, and the size degrade.
|
|
2
|
+
|
|
3
|
+
Why this exists: dumping a big tool's full schema (procesio: ~369 KB / 379 actions)
|
|
4
|
+
is not a large answer, it is NO answer - the driver truncates it to a single-line
|
|
5
|
+
file that read/grep/bash cannot open, and the turn is lost. Measured against real
|
|
6
|
+
transcripts, 27% of all tool calls in an autonomous run were the model guessing
|
|
7
|
+
argument names. These tests pin the four doors that replace the guessing.
|
|
8
|
+
|
|
9
|
+
The registry is faked so the assertions are about behaviour, not about whichever
|
|
10
|
+
tools happen to be installed; one test runs against the real manifests to prove
|
|
11
|
+
the threshold actually trips on the tool that motivated it.
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
|
|
17
|
+
import bridge
|
|
18
|
+
import pytest
|
|
19
|
+
import registry
|
|
20
|
+
import server
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _tool(name, actions, description="a tool"):
|
|
24
|
+
return {"name": name, "description": description, "ready": True,
|
|
25
|
+
"missing_secrets": [], "actions": actions, "args": [],
|
|
26
|
+
"routing": {"primary_action": "", "example": ""}}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _action(name, description="", args=()):
|
|
30
|
+
return {"name": name, "description": description,
|
|
31
|
+
"args": [{"name": a, "type": "string", "required": r,
|
|
32
|
+
"description": ""} for a, r in args]}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
FAKE_TOOLS = [
|
|
36
|
+
_tool("bigtool", [
|
|
37
|
+
_action("datastore-create", "Create a Data Store.",
|
|
38
|
+
[("payload", True), ("workspace-id", False)]),
|
|
39
|
+
_action("datastore-update", "Update a Data Store's columns.",
|
|
40
|
+
[("payload", True)]),
|
|
41
|
+
_action("datastore-get-rows", "Read rows from a Data Store.",
|
|
42
|
+
[("id", True)]),
|
|
43
|
+
_action("export", "Export a process as a .procesio bundle.",
|
|
44
|
+
[("process-id", True), ("out", False)]),
|
|
45
|
+
_action("list-processes", "List processes."),
|
|
46
|
+
]),
|
|
47
|
+
_tool("smalltool", [_action("ping", "Ping.", [("host", True)])]),
|
|
48
|
+
]
|
|
49
|
+
FAKE_AGENTS = [
|
|
50
|
+
_tool("bigagent", [_action("guidance", "Serve the playbook.", [("topic", False)])]),
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@pytest.fixture(autouse=True)
|
|
55
|
+
def fake_registry(monkeypatch):
|
|
56
|
+
monkeypatch.setattr(bridge, "_scan_registry",
|
|
57
|
+
lambda: (FAKE_TOOLS, FAKE_AGENTS, []))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# --- door 1: one action's schema -----------------------------------------
|
|
61
|
+
|
|
62
|
+
def test_name_plus_action_returns_only_that_action():
|
|
63
|
+
out = bridge.capabilities(name="bigtool", action="datastore-create")
|
|
64
|
+
cap = out["capability"]
|
|
65
|
+
assert cap["name"] == "bigtool"
|
|
66
|
+
assert cap["action"]["name"] == "datastore-create"
|
|
67
|
+
assert [a["name"] for a in cap["action"]["args"]] == ["payload", "workspace-id"]
|
|
68
|
+
assert [a["name"] for a in cap["action"]["args"] if a["required"]] == ["payload"]
|
|
69
|
+
# No sibling actions leak in - that is the whole point.
|
|
70
|
+
assert "export" not in json.dumps(out)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_one_action_payload_stays_small():
|
|
74
|
+
out = bridge.capabilities(name="bigtool", action="datastore-create")
|
|
75
|
+
assert len(json.dumps(out)) < 2000
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_one_action_carries_the_literal_call_shape():
|
|
79
|
+
cap = bridge.capabilities(name="bigtool", action="export")["capability"]
|
|
80
|
+
assert cap["call"]["aat_run_tool"]["tool"] == "bigtool"
|
|
81
|
+
assert cap["call"]["aat_run_tool"]["action"] == "export"
|
|
82
|
+
assert "hyphens" in cap["hint"]
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_agent_action_names_the_agent_runner():
|
|
86
|
+
cap = bridge.capabilities(name="bigagent", action="guidance")["capability"]
|
|
87
|
+
assert cap["kind"] == "agent"
|
|
88
|
+
assert "aat_run_agent" in cap["call"]
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_unknown_action_suggests_close_names():
|
|
92
|
+
out = bridge.capabilities(name="bigtool", action="datastore-crate")
|
|
93
|
+
assert out["unknown_action"] == "datastore-crate"
|
|
94
|
+
assert "datastore-create" in out["did_you_mean"]
|
|
95
|
+
assert out["action_count"] == 5
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_suggestion_survives_word_order_and_plurals():
|
|
99
|
+
"""The mistake a model actually makes: right words, wrong order (`credential-list`
|
|
100
|
+
for `list-credentials`). Edit distance alone scores those as far apart."""
|
|
101
|
+
names = ["list-credentials", "credential-test", "credential-get", "run-process"]
|
|
102
|
+
assert bridge._suggest("credential-list", names)[0] == "list-credentials"
|
|
103
|
+
assert bridge._suggest("instances-list", ["list-instances"])[0] == "list-instances"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_suggestion_ignores_unrelated_names():
|
|
107
|
+
assert bridge._suggest("datastore-create", ["send-email", "run-process"]) == []
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_unknown_capability_still_raises():
|
|
111
|
+
with pytest.raises(KeyError):
|
|
112
|
+
bridge.capabilities(name="ghost")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# --- door 2: keyword search ----------------------------------------------
|
|
116
|
+
|
|
117
|
+
def test_search_finds_actions_across_capabilities():
|
|
118
|
+
out = bridge.capabilities(search="datastore")
|
|
119
|
+
names = {m["action"] for m in out["matches"]}
|
|
120
|
+
assert names == {"datastore-create", "datastore-update", "datastore-get-rows"}
|
|
121
|
+
assert all("args" not in m for m in out["matches"]) # compact, not schemas
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def test_search_is_and_not_or():
|
|
125
|
+
out = bridge.capabilities(search="datastore rows")
|
|
126
|
+
assert [m["action"] for m in out["matches"]] == ["datastore-get-rows"]
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_search_matches_description_too():
|
|
130
|
+
out = bridge.capabilities(search="bundle")
|
|
131
|
+
assert [m["action"] for m in out["matches"]] == ["export"]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def test_search_ranks_name_matches_above_description_matches():
|
|
135
|
+
out = bridge.capabilities(search="export")
|
|
136
|
+
assert out["matches"][0]["action"] == "export"
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def test_search_can_be_scoped_to_one_capability():
|
|
140
|
+
assert bridge.capabilities(search="guidance", name="bigtool")["count"] == 0
|
|
141
|
+
assert bridge.capabilities(search="guidance", name="bigagent")["count"] == 1
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def test_search_can_be_scoped_by_kind():
|
|
145
|
+
out = bridge.capabilities(search="guidance", kind="tool")
|
|
146
|
+
assert out["count"] == 0
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def test_search_reports_total_when_capped(monkeypatch):
|
|
150
|
+
out = bridge._search_actions("datastore", limit=2)
|
|
151
|
+
assert len(out["matches"]) == 2
|
|
152
|
+
assert out["total_matches"] == 3
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def test_empty_search_is_a_readable_error():
|
|
156
|
+
with pytest.raises(KeyError):
|
|
157
|
+
bridge.capabilities(search=" ")
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# --- door 2b: a strict-AND miss relaxes instead of dead-ending -------------
|
|
161
|
+
#
|
|
162
|
+
# A caller's words come from the TARGET system's vocabulary, not ours, so one wrong
|
|
163
|
+
# word must not hide the whole family. Live cost of the empty answer: a search for
|
|
164
|
+
# "form create template" returned 0 because no description says "template"; the run
|
|
165
|
+
# abandoned the curated create action, fell back to the raw HTTP endpoint, tripped
|
|
166
|
+
# the irreversibility gate and blocked on step 0 having built nothing.
|
|
167
|
+
|
|
168
|
+
def test_one_unmatched_word_still_returns_the_family():
|
|
169
|
+
out = bridge.capabilities(search="datastore create template")
|
|
170
|
+
assert out["matches"], "a strict miss must not come back empty"
|
|
171
|
+
assert out["matches"][0]["action"] == "datastore-create"
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def test_relaxed_result_says_which_word_it_ignored():
|
|
175
|
+
out = bridge.capabilities(search="datastore create template")
|
|
176
|
+
assert out["relaxed"] is True
|
|
177
|
+
assert out["dropped_terms"] == ["template"]
|
|
178
|
+
assert set(out["matched_terms"]) == {"datastore", "create"}
|
|
179
|
+
assert "template" in out["hint"]
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def test_a_result_that_matches_every_word_is_not_marked_relaxed():
|
|
183
|
+
out = bridge.capabilities(search="datastore rows")
|
|
184
|
+
assert "relaxed" not in out
|
|
185
|
+
assert "dropped_terms" not in out
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def test_dropped_terms_are_measured_against_the_top_match():
|
|
189
|
+
"""Different matches cover different words, so a set-wide calculation reports
|
|
190
|
+
'relaxed, dropped nothing' — a contradiction that says nothing about the action
|
|
191
|
+
the caller is about to read."""
|
|
192
|
+
out = bridge.capabilities(search="datastore export bundle")
|
|
193
|
+
top = out["matches"][0]
|
|
194
|
+
hay = f"{top['name']}.{top['action']} {top['description']}".lower()
|
|
195
|
+
for term in out["dropped_terms"]:
|
|
196
|
+
assert term not in hay
|
|
197
|
+
for term in out["matched_terms"]:
|
|
198
|
+
assert term in hay
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def test_scoping_word_does_not_make_every_action_a_match():
|
|
202
|
+
"""Scoped by name, a token equal to the capability is free for all of its actions.
|
|
203
|
+
Left in the scoring, a query whose real words all miss would still score 1
|
|
204
|
+
everywhere and hand back the whole catalog — worse than the empty answer this
|
|
205
|
+
relaxation exists to fix."""
|
|
206
|
+
out = bridge.capabilities(name="bigtool", search="bigtool zzzz qqqq")
|
|
207
|
+
assert out["count"] == 0
|
|
208
|
+
assert out["total_matches"] == 0
|
|
209
|
+
assert "conclusive" in out["hint"].lower()
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def test_nothing_matches_at_all_is_conclusive_and_says_so():
|
|
213
|
+
out = bridge.capabilities(search="zzzz qqqq wwww")
|
|
214
|
+
assert out["matches"] == []
|
|
215
|
+
assert "list-actions-catalog" in out["hint"] # points at the other catalog
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def test_a_relaxed_search_does_not_lead_with_a_destructive_action(monkeypatch):
|
|
219
|
+
"""'generate form' and 'delete form' match the same one word. Offering the
|
|
220
|
+
deletion first is how a near-miss becomes an incident."""
|
|
221
|
+
tools = [_tool("t", [_action("form-delete", "Delete a form."),
|
|
222
|
+
_action("form-create", "Create a form.")])]
|
|
223
|
+
monkeypatch.setattr(bridge, "_scan_registry", lambda: (tools, [], []))
|
|
224
|
+
out = bridge.capabilities(search="form generate")
|
|
225
|
+
assert out["matches"][0]["action"] == "form-create"
|
|
226
|
+
# …but a caller who DID ask to delete still gets it.
|
|
227
|
+
out = bridge.capabilities(search="form delete")
|
|
228
|
+
assert out["matches"][0]["action"] == "form-delete"
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def test_a_relaxation_surviving_only_on_the_capability_name_is_conclusive():
|
|
232
|
+
"""Unscoped, the tool's name cannot be stripped up front (naming the tool is how you
|
|
233
|
+
narrow there), so a query whose substantive words all miss stays alive on that one
|
|
234
|
+
token and answers with the tool's whole catalog. Live: 405 rows, none of them about
|
|
235
|
+
what was asked."""
|
|
236
|
+
out = bridge.capabilities(search="bigtool nosuchthing")
|
|
237
|
+
assert out["matches"] == []
|
|
238
|
+
assert out["total_matches"] == 0
|
|
239
|
+
assert out["dropped_terms"] == ["nosuchthing"]
|
|
240
|
+
assert "conclusive" in out["hint"].lower()
|
|
241
|
+
assert "list-actions-catalog" in out["hint"]
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def test_a_relaxation_that_explains_nothing_says_it_is_too_vague(monkeypatch):
|
|
245
|
+
tools = [_tool("t", [_action(f"form-op-{i}", "About a form.") for i in range(70)])]
|
|
246
|
+
monkeypatch.setattr(bridge, "_scan_registry", lambda: (tools, [], []))
|
|
247
|
+
out = bridge.capabilities(search="form nosuchword")
|
|
248
|
+
assert out["relaxed"] is True
|
|
249
|
+
assert "too vague" in out["hint"].lower()
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def test_action_without_name_falls_back_to_search():
|
|
253
|
+
out = bridge.capabilities(action="datastore-create")
|
|
254
|
+
assert out["matches"][0]["action"] == "datastore-create"
|
|
255
|
+
assert out["matches"][0]["name"] == "bigtool"
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
# --- door 3: the size degrade --------------------------------------------
|
|
259
|
+
|
|
260
|
+
def test_full_schema_returned_when_under_the_limit(monkeypatch):
|
|
261
|
+
monkeypatch.setenv("AAT_CAPABILITIES_MAX_BYTES", "100000")
|
|
262
|
+
cap = bridge.capabilities(name="bigtool")["capability"]
|
|
263
|
+
assert "truncated" not in cap
|
|
264
|
+
assert len(cap["actions"]) == 5
|
|
265
|
+
assert isinstance(cap["actions"][0], dict) # full entries, with args
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def test_oversized_schema_degrades_to_the_action_index(monkeypatch):
|
|
269
|
+
monkeypatch.setenv("AAT_CAPABILITIES_MAX_BYTES", "200")
|
|
270
|
+
cap = bridge.capabilities(name="bigtool")["capability"]
|
|
271
|
+
assert cap["truncated"] is True
|
|
272
|
+
assert cap["action_count"] == 5
|
|
273
|
+
assert cap["actions"] == ["datastore-create", "datastore-update",
|
|
274
|
+
"datastore-get-rows", "export", "list-processes"]
|
|
275
|
+
assert "action='<one of actions>'" in cap["hint"]
|
|
276
|
+
assert "grep" in cap["hint"]
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def test_degrade_names_the_sizes_so_the_reason_is_legible(monkeypatch):
|
|
280
|
+
monkeypatch.setenv("AAT_CAPABILITIES_MAX_BYTES", "200")
|
|
281
|
+
cap = bridge.capabilities(name="bigtool")["capability"]
|
|
282
|
+
assert "200-byte limit" in cap["reason"]
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def test_degrade_drops_the_index_when_even_that_is_too_big(monkeypatch):
|
|
286
|
+
monkeypatch.setenv("AAT_CAPABILITIES_MAX_BYTES", "10")
|
|
287
|
+
cap = bridge.capabilities(name="bigtool")["capability"]
|
|
288
|
+
assert "actions" not in cap
|
|
289
|
+
assert "search=" in cap["hint"]
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def test_small_tool_is_never_degraded(monkeypatch):
|
|
293
|
+
monkeypatch.setenv("AAT_CAPABILITIES_MAX_BYTES", str(bridge._DEFAULT_MAX_BYTES))
|
|
294
|
+
cap = bridge.capabilities(name="smalltool")["capability"]
|
|
295
|
+
assert "truncated" not in cap
|
|
296
|
+
assert cap["actions"][0]["args"][0]["name"] == "host"
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def test_limit_zero_disables_the_degrade(monkeypatch):
|
|
300
|
+
monkeypatch.setenv("AAT_CAPABILITIES_MAX_BYTES", "0")
|
|
301
|
+
assert "truncated" not in bridge.capabilities(name="bigtool")["capability"]
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def test_bad_limit_env_falls_back_to_the_default(monkeypatch):
|
|
305
|
+
monkeypatch.setenv("AAT_CAPABILITIES_MAX_BYTES", "not-a-number")
|
|
306
|
+
assert bridge._max_bytes() == bridge._DEFAULT_MAX_BYTES
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def test_compact_list_is_unchanged_by_any_of_this():
|
|
310
|
+
out = bridge.capabilities()
|
|
311
|
+
assert out["count"] == 3
|
|
312
|
+
assert {c["name"] for c in out["capabilities"]} == {"bigtool", "smalltool", "bigagent"}
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
# --- door 0: usage errors answer themselves -------------------------------
|
|
316
|
+
|
|
317
|
+
def test_action_help_lists_valid_args():
|
|
318
|
+
help_ = bridge.action_help("bigtool", "datastore-create")
|
|
319
|
+
assert [a["name"] for a in help_["valid_args"]] == ["payload", "workspace-id"]
|
|
320
|
+
assert help_["valid_args"][0]["required"] is True
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def test_action_help_suggests_names_for_an_invented_action():
|
|
324
|
+
help_ = bridge.action_help("bigtool", "datastore-crate")
|
|
325
|
+
assert help_["unknown_action"] == "datastore-crate"
|
|
326
|
+
assert "datastore-create" in help_["did_you_mean"]
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def test_action_help_is_none_for_an_unknown_capability():
|
|
330
|
+
assert bridge.action_help("ghost", "whatever") is None
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def _run_call(tool, action, error_message):
|
|
334
|
+
"""Drive server._run with a tool that fails with `error_message`."""
|
|
335
|
+
def fake(target, act, args):
|
|
336
|
+
return {"ok": False, "error": {"code": "invalid_argument",
|
|
337
|
+
"message": error_message}}
|
|
338
|
+
return fake
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def test_usage_error_is_enriched_with_the_valid_args(monkeypatch):
|
|
342
|
+
monkeypatch.setattr(server.bridge, "run_tool",
|
|
343
|
+
_run_call("bigtool", "datastore-create",
|
|
344
|
+
"unrecognized arguments: --workspace_id x"))
|
|
345
|
+
payload, is_error = server._run(
|
|
346
|
+
"tool", {"tool": "bigtool", "action": "datastore-create",
|
|
347
|
+
"args": {"workspace_id": "x"}}, confirmed=False)
|
|
348
|
+
assert is_error is True
|
|
349
|
+
assert [a["name"] for a in payload["schema"]["valid_args"]] == ["payload", "workspace-id"]
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def test_unknown_action_error_is_enriched_with_did_you_mean(monkeypatch):
|
|
353
|
+
monkeypatch.setattr(server.bridge, "run_tool",
|
|
354
|
+
_run_call("bigtool", "datastore-crate",
|
|
355
|
+
"unknown action: datastore-crate. Known: a, b, c"))
|
|
356
|
+
payload, _ = server._run("tool", {"tool": "bigtool", "action": "datastore-crate"},
|
|
357
|
+
confirmed=False)
|
|
358
|
+
assert "datastore-create" in payload["schema"]["did_you_mean"]
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def test_missing_required_arg_error_is_enriched(monkeypatch):
|
|
362
|
+
monkeypatch.setattr(server.bridge, "run_tool",
|
|
363
|
+
_run_call("bigtool", "datastore-create",
|
|
364
|
+
"the following arguments are required: --payload"))
|
|
365
|
+
payload, _ = server._run("tool", {"tool": "bigtool", "action": "datastore-create"},
|
|
366
|
+
confirmed=False)
|
|
367
|
+
assert payload["schema"]["action"] == "datastore-create"
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def test_remote_api_error_is_not_enriched(monkeypatch):
|
|
371
|
+
"""A 403 from the remote system is real feedback, not a naming problem - adding
|
|
372
|
+
a schema there would just be noise."""
|
|
373
|
+
monkeypatch.setattr(server.bridge, "run_tool",
|
|
374
|
+
_run_call("bigtool", "export", "HTTP 500"))
|
|
375
|
+
payload, _ = server._run("tool", {"tool": "bigtool", "action": "export"},
|
|
376
|
+
confirmed=False)
|
|
377
|
+
assert "schema" not in payload
|
|
378
|
+
assert "hint" in payload
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def test_enrichment_never_masks_the_original_error(monkeypatch):
|
|
382
|
+
monkeypatch.setattr(server.bridge, "action_help",
|
|
383
|
+
lambda *a, **k: (_ for _ in ()).throw(RuntimeError("boom")))
|
|
384
|
+
monkeypatch.setattr(server.bridge, "run_tool",
|
|
385
|
+
_run_call("bigtool", "export", "unknown action: nope"))
|
|
386
|
+
payload, is_error = server._run("tool", {"tool": "bigtool", "action": "nope"},
|
|
387
|
+
confirmed=False)
|
|
388
|
+
assert is_error is True
|
|
389
|
+
assert payload["error"]["message"] == "unknown action: nope"
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def test_hint_points_at_the_narrow_doors(monkeypatch):
|
|
393
|
+
monkeypatch.setattr(server.bridge, "run_tool",
|
|
394
|
+
_run_call("bigtool", "export", "HTTP 500"))
|
|
395
|
+
payload, _ = server._run("tool", {"tool": "bigtool", "action": "export"},
|
|
396
|
+
confirmed=False)
|
|
397
|
+
assert "action='export'" in payload["hint"]
|
|
398
|
+
assert "search=" in payload["hint"]
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
# --- the MCP surface ------------------------------------------------------
|
|
402
|
+
|
|
403
|
+
def test_capabilities_schema_advertises_action_and_search():
|
|
404
|
+
resp = server.handle({"jsonrpc": "2.0", "id": 1, "method": "tools/list"})
|
|
405
|
+
caps = next(t for t in resp["result"]["tools"] if t["name"] == "capabilities")
|
|
406
|
+
# `full` trims the NO-NAME listing; the doors below narrow the WITH-NAME lookup.
|
|
407
|
+
assert set(caps["inputSchema"]["properties"]) == {"kind", "name", "action", "search", "full"}
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def test_capabilities_call_threads_action_and_search_through():
|
|
411
|
+
resp = server.handle({"jsonrpc": "2.0", "id": 1, "method": "tools/call",
|
|
412
|
+
"params": {"name": "capabilities",
|
|
413
|
+
"arguments": {"search": "datastore rows"}}})
|
|
414
|
+
payload = json.loads(resp["result"]["content"][0]["text"])
|
|
415
|
+
assert payload["matches"][0]["action"] == "datastore-get-rows"
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
# --- against the real manifests ------------------------------------------
|
|
419
|
+
|
|
420
|
+
@pytest.mark.parametrize("tool_name", ["procesio"])
|
|
421
|
+
def test_real_oversized_tool_degrades_and_stays_usable(monkeypatch, tool_name):
|
|
422
|
+
"""The case that motivated all of this: the full schema is ~369 KB, which the
|
|
423
|
+
driver cannot read back. It must come back as an index instead."""
|
|
424
|
+
monkeypatch.undo() # drop the fake registry for this one
|
|
425
|
+
tools = registry.list_tools()
|
|
426
|
+
if not any(t.get("name") == tool_name for t in tools):
|
|
427
|
+
pytest.skip(f"{tool_name} is not registered on this machine")
|
|
428
|
+
|
|
429
|
+
full = bridge.capabilities(name=tool_name)["capability"]
|
|
430
|
+
assert full["truncated"] is True
|
|
431
|
+
assert full["action_count"] > 100
|
|
432
|
+
assert len(json.dumps(full, ensure_ascii=False)) < 60_000
|
|
433
|
+
|
|
434
|
+
# ...and the narrow door still answers, in about a kilobyte.
|
|
435
|
+
one = bridge.capabilities(name=tool_name, action=full["actions"][0])
|
|
436
|
+
assert len(json.dumps(one, ensure_ascii=False)) < 6_000
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
# --- managed turn: no competing orchestration loop -----------------------
|
|
440
|
+
|
|
441
|
+
def test_orchestrator_drive_refused_during_a_managed_turn(monkeypatch):
|
|
442
|
+
monkeypatch.setattr(bridge.runner, "run_agent",
|
|
443
|
+
lambda *a, **k: (_ for _ in ()).throw(AssertionError("executed!")))
|
|
444
|
+
token = bridge.set_managed_turn(True)
|
|
445
|
+
try:
|
|
446
|
+
res = bridge.run_agent("orchestrator", "drive", {"run-id": "r1"})
|
|
447
|
+
finally:
|
|
448
|
+
bridge.reset_managed_turn(token)
|
|
449
|
+
assert res["ok"] is False
|
|
450
|
+
assert res["refused"]["reason"] == "managed_turn"
|
|
451
|
+
assert "second orchestration loop" in res["refused"]["message"]
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def test_orchestrator_drive_allowed_outside_a_managed_turn(monkeypatch):
|
|
455
|
+
monkeypatch.setattr(bridge.runner, "run_agent",
|
|
456
|
+
lambda agent, argv, **k: {"ok": True, "data": {"ran": agent}})
|
|
457
|
+
assert bridge.run_agent("orchestrator", "drive", {"run-id": "r1"})["data"]["ran"] == "orchestrator"
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def test_managed_turn_still_allows_the_rest_of_the_orchestrator(monkeypatch):
|
|
461
|
+
"""Only the competing DRIVER is refused: intake/route/record stay available so a managed step
|
|
462
|
+
keeps the doctrine and the run ledger."""
|
|
463
|
+
monkeypatch.setattr(bridge.runner, "run_agent",
|
|
464
|
+
lambda agent, argv, **k: {"ok": True, "data": {"argv": argv}})
|
|
465
|
+
token = bridge.set_managed_turn(True)
|
|
466
|
+
try:
|
|
467
|
+
for action in ("intake", "route", "record", "guidance"):
|
|
468
|
+
assert bridge.run_agent("orchestrator", action, {})["ok"] is True
|
|
469
|
+
finally:
|
|
470
|
+
bridge.reset_managed_turn(token)
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def test_managed_turn_blocklist_is_configurable(monkeypatch):
|
|
474
|
+
monkeypatch.setenv("AAT_MCP_MANAGED_TURN_BLOCK", "orchestrator:drive,deputy:decide")
|
|
475
|
+
monkeypatch.setattr(bridge.runner, "run_agent",
|
|
476
|
+
lambda *a, **k: {"ok": True, "data": {}})
|
|
477
|
+
token = bridge.set_managed_turn(True)
|
|
478
|
+
try:
|
|
479
|
+
assert bridge.run_agent("deputy", "decide", {})["ok"] is False
|
|
480
|
+
assert bridge.run_agent("deputy", "digest", {})["ok"] is True
|
|
481
|
+
finally:
|
|
482
|
+
bridge.reset_managed_turn(token)
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def test_managed_turn_flag_does_not_leak_between_requests(monkeypatch):
|
|
486
|
+
monkeypatch.setattr(bridge.runner, "run_agent", lambda *a, **k: {"ok": True, "data": {}})
|
|
487
|
+
token = bridge.set_managed_turn(True)
|
|
488
|
+
bridge.reset_managed_turn(token)
|
|
489
|
+
assert bridge.run_agent("orchestrator", "drive", {})["ok"] is True
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Multi-user isolation seams (spec 08): per-request user threading + per-user
|
|
2
|
+
userdata + per-user file credentials. No real subprocess."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import bridge # adds repo root to sys.path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_bridge_threads_user_into_subprocess_env(monkeypatch):
|
|
9
|
+
seen = {}
|
|
10
|
+
monkeypatch.delenv("AAT_HOST_RUNNER_URL", raising=False) # force the local path
|
|
11
|
+
monkeypatch.setattr(bridge.runner, "run_tool",
|
|
12
|
+
lambda tool, argv, **k: seen.update(env=k.get("env")) or {"ok": True, "data": {}})
|
|
13
|
+
tok = bridge.set_user("alice")
|
|
14
|
+
try:
|
|
15
|
+
bridge.run_tool("hello-world", None, {"name": "X"})
|
|
16
|
+
assert seen["env"] == {"AAT_USER_ID": "alice"}
|
|
17
|
+
finally:
|
|
18
|
+
bridge.reset_user(tok)
|
|
19
|
+
# after reset -> single-user (no per-user env)
|
|
20
|
+
seen.clear()
|
|
21
|
+
bridge.run_tool("hello-world", None, {"name": "X"})
|
|
22
|
+
assert seen["env"] is None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_delegation_forwards_user_header(monkeypatch):
|
|
26
|
+
captured = {}
|
|
27
|
+
|
|
28
|
+
class _Resp:
|
|
29
|
+
def __enter__(self): return self
|
|
30
|
+
def __exit__(self, *a): return False
|
|
31
|
+
def read(self): return b'{"ok": true, "data": {}}'
|
|
32
|
+
|
|
33
|
+
def fake_urlopen(req, timeout=None):
|
|
34
|
+
captured["headers"] = {k.lower(): v for k, v in req.header_items()}
|
|
35
|
+
return _Resp()
|
|
36
|
+
|
|
37
|
+
monkeypatch.setenv("AAT_HOST_RUNNER_URL", "http://host.docker.internal:8904")
|
|
38
|
+
monkeypatch.setenv("AAT_HOST_RUNNER_TOKEN", "rtok")
|
|
39
|
+
monkeypatch.setattr(bridge.urllib.request, "urlopen", fake_urlopen)
|
|
40
|
+
tok = bridge.set_user("bob")
|
|
41
|
+
try:
|
|
42
|
+
bridge.run_tool("web", "get-text", {"url": "https://example.com"})
|
|
43
|
+
finally:
|
|
44
|
+
bridge.reset_user(tok)
|
|
45
|
+
assert captured["headers"].get("x-aat-user") == "bob"
|
|
46
|
+
assert captured["headers"].get("authorization") == "Bearer rtok"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_userdata_isolates_per_user(monkeypatch, tmp_path):
|
|
50
|
+
from tools._lib import userdata
|
|
51
|
+
monkeypatch.setenv("AAT_USERDATA_DIR", str(tmp_path))
|
|
52
|
+
monkeypatch.setenv("AAT_USER_ID", "alice")
|
|
53
|
+
a = userdata.base()
|
|
54
|
+
monkeypatch.setenv("AAT_USER_ID", "bob")
|
|
55
|
+
b = userdata.base()
|
|
56
|
+
assert a == tmp_path / "alice"
|
|
57
|
+
assert b == tmp_path / "bob"
|
|
58
|
+
assert a != b
|
|
59
|
+
monkeypatch.delenv("AAT_USER_ID")
|
|
60
|
+
assert userdata.base() == tmp_path # single-user root, unchanged behaviour
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_userdata_rejects_traversal(monkeypatch, tmp_path):
|
|
64
|
+
from tools._lib import userdata
|
|
65
|
+
monkeypatch.setenv("AAT_USERDATA_DIR", str(tmp_path))
|
|
66
|
+
monkeypatch.setenv("AAT_USER_ID", "../evil")
|
|
67
|
+
# sanitized to a safe single segment under the root - never escapes
|
|
68
|
+
assert tmp_path in userdata.base().parents or userdata.base().parent == tmp_path
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_file_creds_isolate_per_user(monkeypatch, tmp_path):
|
|
72
|
+
from tools._lib import creds_backends
|
|
73
|
+
(tmp_path / "alice").mkdir()
|
|
74
|
+
(tmp_path / "bob").mkdir()
|
|
75
|
+
(tmp_path / "alice" / "hello__key").write_text("AAA", encoding="utf-8")
|
|
76
|
+
(tmp_path / "bob" / "hello__key").write_text("BBB", encoding="utf-8")
|
|
77
|
+
(tmp_path / "hello__shared").write_text("SHARED", encoding="utf-8")
|
|
78
|
+
monkeypatch.setenv("AAT_SECRETS_DIR", str(tmp_path))
|
|
79
|
+
be = creds_backends.FileSecretBackend()
|
|
80
|
+
monkeypatch.setenv("AAT_USER_ID", "alice")
|
|
81
|
+
assert be.get_optional("hello", "key") == "AAA"
|
|
82
|
+
monkeypatch.setenv("AAT_USER_ID", "bob")
|
|
83
|
+
assert be.get_optional("hello", "key") == "BBB"
|
|
84
|
+
# a secret only in the shared dir resolves for any user (fallback)
|
|
85
|
+
assert be.get_optional("hello", "shared") == "SHARED"
|
|
86
|
+
assert be.get_optional("hello", "missing") is None
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import bridge
|
|
6
|
+
import server
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _payload(response):
|
|
10
|
+
return json.loads(response["result"]["content"][0]["text"])
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _call(name, arguments):
|
|
14
|
+
return server.handle({"jsonrpc": "2.0", "id": 1, "method": "tools/call",
|
|
15
|
+
"params": {"name": name, "arguments": arguments}})
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_get_skill_without_resource_preserves_original_operation(monkeypatch):
|
|
19
|
+
monkeypatch.setattr(server.bridge, "get_skill",
|
|
20
|
+
lambda name: {"name": name, "content": "# Skill", "resources": {}})
|
|
21
|
+
response = _call("get_skill", {"name": "demo"})
|
|
22
|
+
assert _payload(response)["content"] == "# Skill"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_get_skill_resource_uses_index_path(monkeypatch):
|
|
26
|
+
monkeypatch.setattr(server.bridge, "get_skill_resource",
|
|
27
|
+
lambda name, path: {"name": name, "resource": {"path": path}})
|
|
28
|
+
response = _call("get_skill", {"name": "demo", "resource": "references/guide.md"})
|
|
29
|
+
assert _payload(response)["resource"]["path"] == "references/guide.md"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_get_skill_resource_failure_is_structured(monkeypatch):
|
|
33
|
+
def fail(name, path):
|
|
34
|
+
raise ValueError("resource path must stay inside the skill")
|
|
35
|
+
monkeypatch.setattr(server.bridge, "get_skill_resource", fail)
|
|
36
|
+
response = _call("get_skill", {"name": "demo", "resource": "../secret"})
|
|
37
|
+
assert response["result"]["isError"] is True
|
|
38
|
+
assert "stay inside" in _payload(response)["error"]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_optional_fields_are_advertised_without_new_tools():
|
|
42
|
+
response = server.handle({"jsonrpc": "2.0", "id": 1, "method": "tools/list"})
|
|
43
|
+
schemas = {t["name"]: t["inputSchema"] for t in response["result"]["tools"]}
|
|
44
|
+
assert len(schemas) == 6
|
|
45
|
+
assert schemas["get_skill"]["required"] == ["name"]
|
|
46
|
+
assert "resource" in schemas["get_skill"]["properties"]
|
|
47
|
+
# capability search is provided by the existing `search` param (see bridge._search_actions);
|
|
48
|
+
# get_skill's resource retrieval adds no new MCP tool.
|
|
49
|
+
assert "search" in schemas["capabilities"]["properties"]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_real_installed_skill_and_sql_script_resource():
|
|
53
|
+
response = _call("get_skill", {"name": "sql-server-optimizer"})
|
|
54
|
+
assert response["result"]["isError"] is False
|
|
55
|
+
skill = _payload(response)
|
|
56
|
+
root = bridge.registry.get_skill("sql-server-optimizer").path
|
|
57
|
+
assert skill["content"] == (root / "SKILL.md").read_text(encoding="utf-8")
|
|
58
|
+
# The SQL exporters live directly under scripts/ (the portfolio migration moved
|
|
59
|
+
# them out of the deprecated references/scripts/ nesting), so they surface in the
|
|
60
|
+
# scripts category and retrieve cleanly.
|
|
61
|
+
path = "scripts/export-indexes.sql"
|
|
62
|
+
assert path in skill["resources"]["scripts"]
|
|
63
|
+
result = _call("get_skill", {"name": "sql-server-optimizer", "resource": path})
|
|
64
|
+
assert result["result"]["isError"] is False
|
|
65
|
+
assert _payload(result)["resource"]["content"] == (root / path).read_text(encoding="utf-8")
|
|
66
|
+
assert "content" not in _payload(result)
|
|
67
|
+
# export-tables.sql was converted to UTF-8 in the same migration, so it now reads
|
|
68
|
+
# back cleanly too; UTF-8 rejection is covered by the tmp-fixture test below.
|
|
69
|
+
tables = "scripts/export-tables.sql"
|
|
70
|
+
assert tables in skill["resources"]["scripts"]
|
|
71
|
+
ok = _call("get_skill", {"name": "sql-server-optimizer", "resource": tables})
|
|
72
|
+
assert ok["result"]["isError"] is False
|
|
73
|
+
assert _payload(ok)["resource"]["content"] == (root / tables).read_text(encoding="utf-8")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_real_resource_rejections_at_protocol_boundary(monkeypatch, tmp_path):
|
|
77
|
+
root = tmp_path / "demo"
|
|
78
|
+
(root / "assets").mkdir(parents=True)
|
|
79
|
+
(root / "SKILL.md").write_text("---\nname: demo\ndescription: Demo\n---\n# Demo\n")
|
|
80
|
+
(root / "assets" / "binary.bin").write_bytes(b"\xff\xfe")
|
|
81
|
+
(root / "assets" / "large.txt").write_bytes(b"x" * 512_001)
|
|
82
|
+
monkeypatch.setattr(bridge.registry, "SKILLS_DIR", tmp_path)
|
|
83
|
+
for path in ("../outside", "/outside", "", "assets/missing", "assets/binary.bin",
|
|
84
|
+
"assets/large.txt", "assets/" + "x" * 256, "assets/\x00"):
|
|
85
|
+
response = _call("get_skill", {"name": "demo", "resource": path})
|
|
86
|
+
assert response["result"]["isError"] is True, path
|
|
87
|
+
payload = _payload(response)
|
|
88
|
+
assert "error" in payload and "content" not in payload
|
|
89
|
+
assert str(tmp_path) not in payload["error"]
|