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
procesio_cli/registry.py
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
"""Auto-discovery for tools and agents.
|
|
2
|
+
|
|
3
|
+
Walks tools/*/tool.yaml and agents/*/agent.yaml, validates manifests, and
|
|
4
|
+
returns a unified registry. Used by:
|
|
5
|
+
- scripts/list-tools.py and scripts/run-tool.py
|
|
6
|
+
- Agents (when they ship) to introspect available tools without hardcoding.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from tools._lib import creds
|
|
16
|
+
from tools._lib.manifest import load_agent, load_skill, load_tool
|
|
17
|
+
|
|
18
|
+
ROOT = Path(__file__).parent
|
|
19
|
+
TOOLS_DIR = ROOT / "tools"
|
|
20
|
+
AGENTS_DIR = ROOT / "agents"
|
|
21
|
+
SKILLS_DIR = ROOT / "skills"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def hidden_tools() -> set[str]:
|
|
25
|
+
"""Tool names this session must not see, by directory name.
|
|
26
|
+
|
|
27
|
+
A scoped tool surface. Two sources, env first so a single run can override the
|
|
28
|
+
persisted setting:
|
|
29
|
+
|
|
30
|
+
AAT_TOOLS_HIDE=a,b (env, comma-separated)
|
|
31
|
+
context-state-knowledge/config/registry/hidden-tools.json -> {"hide": [...]}
|
|
32
|
+
|
|
33
|
+
Hiding is REGISTRY-level only: the directory keeps its name and stays a normal
|
|
34
|
+
Python package, so a tool that imports another one directly keeps working, and
|
|
35
|
+
`get_tool(..., respect_hidden=False)` still resolves it for the framework's own
|
|
36
|
+
plumbing. That separation is what let an A/B run swap the surface a session was
|
|
37
|
+
offered without renaming anything or editing the code under test.
|
|
38
|
+
|
|
39
|
+
Never raises: an unreadable config must not take the whole registry down."""
|
|
40
|
+
raw = os.environ.get("AAT_TOOLS_HIDE")
|
|
41
|
+
if raw is not None:
|
|
42
|
+
return {n.strip() for n in raw.split(",") if n.strip()}
|
|
43
|
+
try:
|
|
44
|
+
from tools._lib import userdata
|
|
45
|
+
cfg = Path(userdata.config_dir("registry")) / "hidden-tools.json"
|
|
46
|
+
if cfg.exists():
|
|
47
|
+
data = json.loads(cfg.read_text(encoding="utf-8"))
|
|
48
|
+
return {str(n) for n in data.get("hide", [])}
|
|
49
|
+
except Exception: # noqa: BLE001 - scoping is a convenience, never a blocker
|
|
50
|
+
pass
|
|
51
|
+
return set()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _has_secret(tool_name: str, secret_name: str) -> bool:
|
|
55
|
+
"""Check secret presence. Supports `namespace:name` for shared secrets,
|
|
56
|
+
e.g. `google:oauth-client` -> agents-and-tools:google:oauth-client.
|
|
57
|
+
|
|
58
|
+
Never raises. Readiness is a REPORT, and a machine with no reachable
|
|
59
|
+
credential store still has to be able to list what is installed: a headless
|
|
60
|
+
Linux box has no session keyring at all, so constructing the backend there
|
|
61
|
+
throws and would otherwise take down the whole registry, the router build and
|
|
62
|
+
the dashboard with it. Unreachable is reported the same as absent, which is
|
|
63
|
+
the honest answer to "is this tool ready" - it is not, and the store error
|
|
64
|
+
says why the moment anyone actually calls creds.get, which still raises.
|
|
65
|
+
"""
|
|
66
|
+
if ":" in secret_name:
|
|
67
|
+
ns, _, name = secret_name.partition(":")
|
|
68
|
+
return creds.has_for_report(ns, name)
|
|
69
|
+
return creds.has_for_report(tool_name, secret_name)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _oauth_scope_gap(tool_dir: Path) -> list[str] | None:
|
|
73
|
+
"""Scopes a tool declares that the stored OAuth token does not carry.
|
|
74
|
+
|
|
75
|
+
`ready` used to mean only "every declared secret is present". The whole
|
|
76
|
+
google-* family shares one client + one token, so the moment ANY of them
|
|
77
|
+
finished its OAuth flow all of them flipped ready - carrying only the
|
|
78
|
+
scopes that one flow had requested. Seven tools reported ready and then
|
|
79
|
+
answered 403 "insufficient authentication scopes" on first use.
|
|
80
|
+
|
|
81
|
+
Returns None when the tool has no OAuth scope surface at all, so "no gap"
|
|
82
|
+
and "not applicable" stay distinguishable. Never raises: readiness
|
|
83
|
+
reporting must not be able to take the registry down.
|
|
84
|
+
"""
|
|
85
|
+
auth_py = tool_dir / "auth.py"
|
|
86
|
+
if not auth_py.exists():
|
|
87
|
+
return None
|
|
88
|
+
try:
|
|
89
|
+
if "register_scopes" not in auth_py.read_text(encoding="utf-8"):
|
|
90
|
+
return None
|
|
91
|
+
import importlib
|
|
92
|
+
|
|
93
|
+
mod = importlib.import_module(f"tools.{tool_dir.name}.auth")
|
|
94
|
+
declared = set(getattr(mod, "SCOPES", None) or [])
|
|
95
|
+
if not declared:
|
|
96
|
+
return None
|
|
97
|
+
from tools._lib import google_auth
|
|
98
|
+
|
|
99
|
+
token = google_auth._load_token()
|
|
100
|
+
if token is None:
|
|
101
|
+
# No token at all is already reported as a missing secret; saying
|
|
102
|
+
# it twice, as ten missing scopes, buries the actual instruction.
|
|
103
|
+
return None
|
|
104
|
+
held = set(token.get("scopes") or [])
|
|
105
|
+
return sorted(declared - held)
|
|
106
|
+
except Exception: # noqa: BLE001 - see docstring
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def list_tools() -> list[dict[str, Any]]:
|
|
111
|
+
out: list[dict[str, Any]] = []
|
|
112
|
+
if not TOOLS_DIR.exists():
|
|
113
|
+
return out
|
|
114
|
+
hidden = hidden_tools()
|
|
115
|
+
for manifest_path in sorted(TOOLS_DIR.glob("*/tool.yaml")):
|
|
116
|
+
dir_name = manifest_path.parent.name
|
|
117
|
+
if dir_name.startswith("_") or dir_name in hidden:
|
|
118
|
+
continue
|
|
119
|
+
try:
|
|
120
|
+
m = load_tool(manifest_path)
|
|
121
|
+
except Exception as e:
|
|
122
|
+
out.append({
|
|
123
|
+
"name": dir_name,
|
|
124
|
+
"error": f"manifest load failed: {e}",
|
|
125
|
+
"ready": False,
|
|
126
|
+
})
|
|
127
|
+
continue
|
|
128
|
+
absent = [s for s in m.secrets if not _has_secret(m.name, s.name)]
|
|
129
|
+
missing = [s.name for s in absent if not s.optional]
|
|
130
|
+
missing_optional = [s.name for s in absent if s.optional]
|
|
131
|
+
missing_scopes = _oauth_scope_gap(manifest_path.parent) or []
|
|
132
|
+
# Three outcomes, one boolean plus a label. `ready` stays a bool so no
|
|
133
|
+
# existing consumer breaks, but "authorized, just not for this tool" is
|
|
134
|
+
# the normal state during incremental setup, not an error - and it
|
|
135
|
+
# needs a different instruction ("re-run auth-login") from a missing
|
|
136
|
+
# credential ("store the secret"), so the label carries which.
|
|
137
|
+
if missing:
|
|
138
|
+
readiness = "needs-credentials"
|
|
139
|
+
elif missing_scopes:
|
|
140
|
+
readiness = "needs-scopes"
|
|
141
|
+
else:
|
|
142
|
+
readiness = "ready"
|
|
143
|
+
out.append({
|
|
144
|
+
"name": m.name,
|
|
145
|
+
"description": m.description,
|
|
146
|
+
"version": m.version,
|
|
147
|
+
"tier": m.tier,
|
|
148
|
+
"path": str(m.path),
|
|
149
|
+
"entrypoint": m.entrypoint,
|
|
150
|
+
"args": [a.model_dump(by_alias=True) for a in m.args],
|
|
151
|
+
"actions": [
|
|
152
|
+
# examples/output_schema ride along when a manifest declares them: they
|
|
153
|
+
# are what makes a structured argument usable without trial and error,
|
|
154
|
+
# and a consumer that only sees name/description/args cannot recover them.
|
|
155
|
+
{
|
|
156
|
+
"name": a.name,
|
|
157
|
+
"description": a.description,
|
|
158
|
+
"args": [arg.model_dump(by_alias=True) for arg in a.args],
|
|
159
|
+
**({"examples": a.examples} if a.examples else {}),
|
|
160
|
+
**({"output_schema": a.output_schema} if a.output_schema else {}),
|
|
161
|
+
}
|
|
162
|
+
for a in m.actions
|
|
163
|
+
],
|
|
164
|
+
"secrets": [s.model_dump() for s in m.secrets],
|
|
165
|
+
"routing": m.routing.model_dump() if m.routing else None,
|
|
166
|
+
"healthcheck": m.healthcheck.model_dump() if m.healthcheck else None,
|
|
167
|
+
"web_session": m.web_session.model_dump() if m.web_session else None,
|
|
168
|
+
"missing_secrets": missing,
|
|
169
|
+
# Absent but not blocking: shown so setup can still offer them,
|
|
170
|
+
# never counted against readiness.
|
|
171
|
+
"missing_optional_secrets": missing_optional,
|
|
172
|
+
"missing_scopes": missing_scopes,
|
|
173
|
+
"readiness": readiness,
|
|
174
|
+
"ready": readiness == "ready",
|
|
175
|
+
})
|
|
176
|
+
return out
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def get_tool(name: str, *, respect_hidden: bool = True):
|
|
180
|
+
"""Resolve a tool manifest by name.
|
|
181
|
+
|
|
182
|
+
``respect_hidden=False`` bypasses the scoped surface. Agents pass it: hiding
|
|
183
|
+
is meant to shrink what a SESSION is offered, not to amputate the framework
|
|
184
|
+
underneath it. Hiding a tool used to disable every agent that drives it -
|
|
185
|
+
`procesio audit` died with "no registered tool named 'procesio'" the moment
|
|
186
|
+
that tool was scoped out for an experiment - which is a silent, confusing
|
|
187
|
+
failure a long way from its cause."""
|
|
188
|
+
import sys
|
|
189
|
+
hidden = hidden_tools() if respect_hidden else set()
|
|
190
|
+
if name in hidden:
|
|
191
|
+
raise KeyError(f"tool not found: {name}")
|
|
192
|
+
for manifest_path in TOOLS_DIR.glob("*/tool.yaml"):
|
|
193
|
+
if manifest_path.parent.name.startswith("_") or manifest_path.parent.name in hidden:
|
|
194
|
+
continue
|
|
195
|
+
try:
|
|
196
|
+
m = load_tool(manifest_path)
|
|
197
|
+
except Exception as exc: # noqa: BLE001
|
|
198
|
+
# A broken/transiently-unreadable SIBLING manifest must not block the
|
|
199
|
+
# requested tool. Re-raise only if it's the tool we were asked for.
|
|
200
|
+
if manifest_path.parent.name == name:
|
|
201
|
+
raise
|
|
202
|
+
print(f"warning: skipping unloadable tool manifest "
|
|
203
|
+
f"'{manifest_path.parent.name}': {exc}", file=sys.stderr)
|
|
204
|
+
continue
|
|
205
|
+
if m.name == name:
|
|
206
|
+
return m
|
|
207
|
+
raise KeyError(f"tool not found: {name}")
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def list_agents(tool_index: dict[str, dict] | None = None) -> list[dict[str, Any]]:
|
|
211
|
+
out: list[dict[str, Any]] = []
|
|
212
|
+
if not AGENTS_DIR.exists():
|
|
213
|
+
return out
|
|
214
|
+
# Index every tool ONCE (name -> its list_tools() entry, which already carries
|
|
215
|
+
# ready/missing_secrets). Previously each driven-tool lookup called get_tool(),
|
|
216
|
+
# which re-globbed and re-parsed all tool manifests - O(agents x tools) YAML
|
|
217
|
+
# parses that made this call take tens of seconds on a large registry. A caller
|
|
218
|
+
# that has already built the tool list (e.g. the dashboard) can pass it in to
|
|
219
|
+
# avoid a second full scan.
|
|
220
|
+
if tool_index is None:
|
|
221
|
+
tool_index = {t["name"]: t for t in list_tools()}
|
|
222
|
+
for manifest_path in sorted(AGENTS_DIR.glob("*/agent.yaml")):
|
|
223
|
+
dir_name = manifest_path.parent.name
|
|
224
|
+
if dir_name.startswith("_"):
|
|
225
|
+
continue
|
|
226
|
+
try:
|
|
227
|
+
m = load_agent(manifest_path)
|
|
228
|
+
except Exception as e:
|
|
229
|
+
out.append({"name": dir_name, "error": str(e), "ready": False})
|
|
230
|
+
continue
|
|
231
|
+
missing = [s.name for s in m.secrets if not _has_secret(m.name, s.name)]
|
|
232
|
+
# An agent is "ready" only if its own secrets AND every tool it drives
|
|
233
|
+
# are present and ready. Surface unready tools so gaps are visible.
|
|
234
|
+
tool_status = {}
|
|
235
|
+
for tname in m.tools:
|
|
236
|
+
t = tool_index.get(tname)
|
|
237
|
+
if t is not None and not t.get("error"):
|
|
238
|
+
tool_status[tname] = {"present": True, "ready": bool(t.get("ready")),
|
|
239
|
+
"missing_secrets": t.get("missing_secrets", [])}
|
|
240
|
+
else:
|
|
241
|
+
tool_status[tname] = {"present": False, "ready": False,
|
|
242
|
+
"missing_secrets": []}
|
|
243
|
+
out.append({
|
|
244
|
+
"name": m.name,
|
|
245
|
+
"description": m.description,
|
|
246
|
+
"version": m.version,
|
|
247
|
+
"tier": m.tier,
|
|
248
|
+
"path": str(m.path),
|
|
249
|
+
"entrypoint": m.entrypoint,
|
|
250
|
+
"tools": m.tools,
|
|
251
|
+
"tool_status": tool_status,
|
|
252
|
+
"actions": [
|
|
253
|
+
{"name": a.name, "description": a.description,
|
|
254
|
+
"args": [arg.model_dump(by_alias=True) for arg in a.args],
|
|
255
|
+
**({"examples": a.examples} if a.examples else {}),
|
|
256
|
+
**({"output_schema": a.output_schema} if a.output_schema else {})}
|
|
257
|
+
for a in m.actions
|
|
258
|
+
],
|
|
259
|
+
"secrets": [s.model_dump() for s in m.secrets],
|
|
260
|
+
"routing": m.routing.model_dump() if m.routing else None,
|
|
261
|
+
"healthcheck": m.healthcheck.model_dump() if m.healthcheck else None,
|
|
262
|
+
"missing_secrets": missing,
|
|
263
|
+
# An agent is ready only when its own secrets AND every tool it drives
|
|
264
|
+
# are ready (matches the docstring above). own_ready is surfaced too so
|
|
265
|
+
# a UI can distinguish "agent's own creds are set" from "a driven tool
|
|
266
|
+
# is missing creds".
|
|
267
|
+
"own_ready": len(missing) == 0,
|
|
268
|
+
"ready": len(missing) == 0 and all(
|
|
269
|
+
st["ready"] for st in tool_status.values()),
|
|
270
|
+
})
|
|
271
|
+
return out
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def get_agent(name: str):
|
|
275
|
+
for manifest_path in AGENTS_DIR.glob("*/agent.yaml"):
|
|
276
|
+
if manifest_path.parent.name.startswith("_"):
|
|
277
|
+
continue
|
|
278
|
+
m = load_agent(manifest_path)
|
|
279
|
+
if m.name == name:
|
|
280
|
+
return m
|
|
281
|
+
raise KeyError(f"agent not found: {name}")
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def list_skills() -> list[dict[str, Any]]:
|
|
285
|
+
"""Discover skills. A skill's `SKILL.md` frontmatter is its manifest; skills
|
|
286
|
+
carry no secrets, so a successfully-loaded skill is always ready."""
|
|
287
|
+
out: list[dict[str, Any]] = []
|
|
288
|
+
if not SKILLS_DIR.exists():
|
|
289
|
+
return out
|
|
290
|
+
for skill_md in sorted(SKILLS_DIR.glob("*/SKILL.md")):
|
|
291
|
+
dir_name = skill_md.parent.name
|
|
292
|
+
if dir_name.startswith("_") or dir_name == "tests":
|
|
293
|
+
continue
|
|
294
|
+
try:
|
|
295
|
+
m = load_skill(skill_md)
|
|
296
|
+
except Exception as e:
|
|
297
|
+
out.append({
|
|
298
|
+
"name": dir_name,
|
|
299
|
+
"error": f"manifest load failed: {e}",
|
|
300
|
+
"ready": False,
|
|
301
|
+
})
|
|
302
|
+
continue
|
|
303
|
+
entry = {
|
|
304
|
+
"name": m.name,
|
|
305
|
+
"description": m.description,
|
|
306
|
+
"version": m.version,
|
|
307
|
+
"path": str(m.path),
|
|
308
|
+
"routing": m.routing.model_dump() if m.routing else None,
|
|
309
|
+
"ready": True,
|
|
310
|
+
}
|
|
311
|
+
# Non-fatal hygiene signal: folder name should match the manifest name.
|
|
312
|
+
if m.name != dir_name:
|
|
313
|
+
entry["warning"] = f"folder '{dir_name}' != skill name '{m.name}'"
|
|
314
|
+
out.append(entry)
|
|
315
|
+
return out
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def get_skill(name: str):
|
|
319
|
+
for skill_md in SKILLS_DIR.glob("*/SKILL.md"):
|
|
320
|
+
if skill_md.parent.name.startswith("_") or skill_md.parent.name == "tests":
|
|
321
|
+
continue
|
|
322
|
+
m = load_skill(skill_md)
|
|
323
|
+
if m.name == name:
|
|
324
|
+
return m
|
|
325
|
+
raise KeyError(f"skill not found: {name}")
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def resolve_catalog(entries: list[dict[str, Any]],
|
|
329
|
+
ws_overrides: dict[str, dict] | None = None) -> list[dict[str, Any]]:
|
|
330
|
+
"""Effective per-workspace catalog under the official/template/custom + copy-on-write
|
|
331
|
+
model (spec P0.0-06 / D11). Pure function over registry entries + a per-workspace
|
|
332
|
+
override map (name -> the workspace's own copy/custom); the override STORE is the
|
|
333
|
+
platform's job (object storage / a package feed), so this stays testable and
|
|
334
|
+
storage-agnostic.
|
|
335
|
+
|
|
336
|
+
Rules:
|
|
337
|
+
- official : always present, from the shared registry; a workspace CANNOT override
|
|
338
|
+
it (users can't change official).
|
|
339
|
+
- template : the workspace's override if it forked one (copy-on-write), else the
|
|
340
|
+
shared template. An untouched workspace holds ZERO copies (conserve resources).
|
|
341
|
+
- custom : the workspace's own entries (overrides that don't shadow an official).
|
|
342
|
+
|
|
343
|
+
Each returned entry carries `effective_tier` in
|
|
344
|
+
{official, template, custom-copy, custom}. `ws_overrides` unset = the shared catalog
|
|
345
|
+
unchanged (exactly the single-tenant local behaviour)."""
|
|
346
|
+
ws_overrides = dict(ws_overrides or {})
|
|
347
|
+
by_name = {e["name"]: e for e in entries}
|
|
348
|
+
out: dict[str, dict] = {}
|
|
349
|
+
|
|
350
|
+
for e in entries:
|
|
351
|
+
tier = e.get("tier", "template")
|
|
352
|
+
if tier == "official":
|
|
353
|
+
out[e["name"]] = {**e, "effective_tier": "official"}
|
|
354
|
+
elif tier == "template":
|
|
355
|
+
if e["name"] in ws_overrides:
|
|
356
|
+
out[e["name"]] = {**ws_overrides[e["name"]],
|
|
357
|
+
"name": e["name"], "effective_tier": "custom-copy"}
|
|
358
|
+
else:
|
|
359
|
+
out[e["name"]] = {**e, "effective_tier": "template"}
|
|
360
|
+
# a 'custom'-tier entry shipped in the base registry is unusual; customs are
|
|
361
|
+
# expected to arrive via ws_overrides, handled below.
|
|
362
|
+
|
|
363
|
+
for name, ov in ws_overrides.items():
|
|
364
|
+
base = by_name.get(name)
|
|
365
|
+
if base is not None and base.get("tier") == "official":
|
|
366
|
+
continue # official is immutable per-workspace
|
|
367
|
+
if name not in out:
|
|
368
|
+
out[name] = {**ov, "name": name, "effective_tier": "custom"}
|
|
369
|
+
|
|
370
|
+
return list(out.values())
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"""Generate the Capability Router block inside CLAUDE.md from the registry.
|
|
2
|
+
|
|
3
|
+
The router is a compact request->tool/agent map that auto-loads every session
|
|
4
|
+
(because CLAUDE.md is injected as project instructions). It lets a request be
|
|
5
|
+
matched to the right tool with zero discovery steps.
|
|
6
|
+
|
|
7
|
+
Source of truth is the registry (manifests). A tool can curate its own routing
|
|
8
|
+
via a `routing:` block in tool.yaml (triggers / primary_action / example); when
|
|
9
|
+
absent, this script falls back to the description and a heuristic primary action.
|
|
10
|
+
|
|
11
|
+
The block is a pure function of the manifests. Nothing machine-specific goes in
|
|
12
|
+
it - notably NOT which credentials the generating machine happens to hold, which
|
|
13
|
+
used to land here and made the committed CLAUDE.md differ per person (so the
|
|
14
|
+
sync test could only pass for whoever regenerated last). Live readiness belongs
|
|
15
|
+
to `list-tools.py` and the dashboard; here it is a stderr warning.
|
|
16
|
+
|
|
17
|
+
Usage:
|
|
18
|
+
python scripts/build-router.py # rewrite the block in CLAUDE.md
|
|
19
|
+
python scripts/build-router.py --print # print the block to stdout, write nothing
|
|
20
|
+
python scripts/build-router.py --check # exit 1 if CLAUDE.md is out of date (CI guard)
|
|
21
|
+
"""
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import argparse
|
|
25
|
+
import sys
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
|
|
28
|
+
# Auto-switch to the project's .venv Python if launched with a different one.
|
|
29
|
+
_PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|
30
|
+
# .venv layout is per-OS: Scripts/python.exe on Windows, bin/python everywhere
|
|
31
|
+
# else. Hardcoding the Windows path made this a silent no-op on macOS/Linux,
|
|
32
|
+
# where the script then ran on whatever interpreter happened to invoke it.
|
|
33
|
+
_VENV_PY = (_PROJECT_ROOT / ".venv" / "Scripts" / "python.exe" if sys.platform == "win32"
|
|
34
|
+
else _PROJECT_ROOT / ".venv" / "bin" / "python")
|
|
35
|
+
if _VENV_PY.exists() and Path(sys.executable).resolve() != _VENV_PY.resolve():
|
|
36
|
+
import subprocess
|
|
37
|
+
sys.exit(subprocess.run([str(_VENV_PY), __file__, *sys.argv[1:]]).returncode)
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
41
|
+
except (AttributeError, ValueError):
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
sys.path.insert(0, str(_PROJECT_ROOT))
|
|
45
|
+
|
|
46
|
+
from registry import list_agents, list_skills, list_tools # noqa: E402
|
|
47
|
+
|
|
48
|
+
START = "<!-- CAPABILITY-ROUTER:START — generated by scripts/build-router.py; rerun after adding/removing a tool. Do not hand-edit. -->"
|
|
49
|
+
END = "<!-- CAPABILITY-ROUTER:END -->"
|
|
50
|
+
|
|
51
|
+
# Actions that never make a good "first thing to reach for".
|
|
52
|
+
_AUTH_ACTIONS = {"auth-status", "auth-login", "auth-logout", "login", "auth", "web-login", "web-status"}
|
|
53
|
+
|
|
54
|
+
# Skills registered in this project (skills/<name>/) are generated from the
|
|
55
|
+
# registry below. This residual pointer covers harness-only skills that auto-
|
|
56
|
+
# trigger but are NOT bundled in this repo, so the router still routes to them.
|
|
57
|
+
# Keep terse. When a skill here gets imported into skills/, drop its line.
|
|
58
|
+
_HARNESS_SKILLS_POINTER = globals().get("_HARNESS_SKILLS_POINTER", [])
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _first_sentence(text: str, cap: int = 110) -> str:
|
|
62
|
+
text = " ".join((text or "").split())
|
|
63
|
+
for sep in (". ", " — ", "; "):
|
|
64
|
+
if sep in text:
|
|
65
|
+
text = text.split(sep, 1)[0]
|
|
66
|
+
break
|
|
67
|
+
return (text[: cap - 1] + "…") if len(text) > cap else text
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _primary_action(entry: dict) -> str:
|
|
71
|
+
routing = entry.get("routing") or {}
|
|
72
|
+
if routing.get("primary_action"):
|
|
73
|
+
return routing["primary_action"]
|
|
74
|
+
actions = [a["name"] for a in entry.get("actions", [])]
|
|
75
|
+
non_auth = [a for a in actions if a not in _AUTH_ACTIONS]
|
|
76
|
+
return (non_auth or actions or [""])[0]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _trigger(entry: dict) -> str:
|
|
80
|
+
routing = entry.get("routing") or {}
|
|
81
|
+
if routing.get("triggers"):
|
|
82
|
+
return "; ".join(routing["triggers"])
|
|
83
|
+
return _first_sentence(entry.get("description", ""))
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _example(entry: dict, runner: str) -> str:
|
|
87
|
+
routing = entry.get("routing") or {}
|
|
88
|
+
if routing.get("example"):
|
|
89
|
+
return routing["example"]
|
|
90
|
+
action = _primary_action(entry)
|
|
91
|
+
return f"{entry['name']} {action}".strip()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _line(entry: dict, runner: str) -> str:
|
|
95
|
+
return f"- **{entry['name']}** — {_trigger(entry)} → `{_example(entry, runner)}`"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _skill_line(entry: dict) -> str:
|
|
99
|
+
return f"- **{entry['name']}** — {_trigger(entry)} → `get-skill.py {entry['name']}`"
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def build_block() -> tuple[str, list[str]]:
|
|
103
|
+
"""Return (markdown_block, warnings)."""
|
|
104
|
+
warnings: list[str] = []
|
|
105
|
+
tools = list_tools()
|
|
106
|
+
agents = list_agents()
|
|
107
|
+
|
|
108
|
+
# Listed by MANIFEST validity, not by local credential state. Filtering the
|
|
109
|
+
# listing on `ready` was the same per-machine leak as the readiness line
|
|
110
|
+
# below, only larger: a checkout that had not stored a tool's secret yet
|
|
111
|
+
# silently dropped that tool from the router, so the agent stopped routing
|
|
112
|
+
# to a capability that exists - and the committed file differed per person.
|
|
113
|
+
# Whether YOU can run it is a live question (list-tools.py, the dashboard);
|
|
114
|
+
# whether it EXISTS is a manifest question, and only that belongs here.
|
|
115
|
+
listed = [t for t in tools if "error" not in t]
|
|
116
|
+
not_ready = [t for t in tools if not t.get("ready") and "error" not in t]
|
|
117
|
+
errored = [t for t in tools if "error" in t]
|
|
118
|
+
|
|
119
|
+
for t in listed:
|
|
120
|
+
if not t.get("routing"):
|
|
121
|
+
warnings.append(f"tool '{t['name']}' has no curated routing: block (using description fallback)")
|
|
122
|
+
|
|
123
|
+
lines = [START, ""]
|
|
124
|
+
lines.append("### Tools — run with `python scripts/run-tool.py <tool> <action> [--args]`")
|
|
125
|
+
lines.append("")
|
|
126
|
+
for t in sorted(listed, key=lambda x: x["name"]):
|
|
127
|
+
lines.append(_line(t, "run-tool.py"))
|
|
128
|
+
lines.append("")
|
|
129
|
+
|
|
130
|
+
# Deliberately NOT written into the block: which secrets are stored is a
|
|
131
|
+
# property of one machine, and CLAUDE.md is version-controlled and shared
|
|
132
|
+
# by two teams. Emitting it here made the generated file differ per person,
|
|
133
|
+
# so the sync test could only pass on whoever committed last, and it put
|
|
134
|
+
# user-specific data in a framework file the same document forbids it in.
|
|
135
|
+
# The live answer belongs to `list-tools.py` and the dashboard; here it is
|
|
136
|
+
# a stderr warning, so the information survives without being published.
|
|
137
|
+
for t in sorted(not_ready, key=lambda x: x["name"]):
|
|
138
|
+
miss = ",".join(t.get("missing_secrets", [])) or "credentials"
|
|
139
|
+
warnings.append(f"tool '{t['name']}' needs credentials on this machine ({miss}) - not written to CLAUDE.md")
|
|
140
|
+
|
|
141
|
+
if errored:
|
|
142
|
+
bits = [t["name"] for t in errored]
|
|
143
|
+
lines.append(f"❌ **Manifest errors** (fix before use): {', '.join(bits)}")
|
|
144
|
+
lines.append("")
|
|
145
|
+
|
|
146
|
+
if agents:
|
|
147
|
+
lines.append("### Agents — run with `python scripts/run-agent.py <agent> <action> [--args]`")
|
|
148
|
+
lines.append("")
|
|
149
|
+
for a in sorted(agents, key=lambda x: x["name"]):
|
|
150
|
+
if "error" in a:
|
|
151
|
+
continue
|
|
152
|
+
lines.append(_line(a, "run-agent.py"))
|
|
153
|
+
lines.append("")
|
|
154
|
+
|
|
155
|
+
skills = list_skills()
|
|
156
|
+
skills_ready = [s for s in skills if "error" not in s]
|
|
157
|
+
skills_errored = [s for s in skills if "error" in s]
|
|
158
|
+
|
|
159
|
+
if skills or _HARNESS_SKILLS_POINTER:
|
|
160
|
+
lines.append("### Skills")
|
|
161
|
+
lines.append("")
|
|
162
|
+
lines.append(
|
|
163
|
+
"Claude **auto-triggers** these from their descriptions — do NOT run-tool them. "
|
|
164
|
+
"Project agents discover them via the registry and load one's full content with "
|
|
165
|
+
"`python scripts/get-skill.py <name> --content`."
|
|
166
|
+
)
|
|
167
|
+
lines.append("")
|
|
168
|
+
|
|
169
|
+
if skills:
|
|
170
|
+
lines.append("**Registered in this project** — run `python scripts/list-skills.py` (`skills/<name>/`):")
|
|
171
|
+
lines.append("")
|
|
172
|
+
for s in sorted(skills_ready, key=lambda x: x["name"]):
|
|
173
|
+
lines.append(_skill_line(s))
|
|
174
|
+
if not s.get("routing"):
|
|
175
|
+
warnings.append(f"skill '{s['name']}' has no curated routing: block (using description fallback)")
|
|
176
|
+
lines.append("")
|
|
177
|
+
if skills_errored:
|
|
178
|
+
bits = [s["name"] for s in skills_errored]
|
|
179
|
+
lines.append(f"❌ **Skill manifest errors** (fix before use): {', '.join(bits)}")
|
|
180
|
+
lines.append("")
|
|
181
|
+
|
|
182
|
+
if _HARNESS_SKILLS_POINTER:
|
|
183
|
+
lines.append("**Other harness skills** (auto-trigger; not bundled in this repo):")
|
|
184
|
+
lines.append("")
|
|
185
|
+
for s in _HARNESS_SKILLS_POINTER:
|
|
186
|
+
lines.append(f"- {s}")
|
|
187
|
+
lines.append("")
|
|
188
|
+
lines.append(END)
|
|
189
|
+
return "\n".join(lines), warnings
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def splice(claude_md: str, block: str) -> str:
|
|
193
|
+
if START in claude_md and END in claude_md:
|
|
194
|
+
pre = claude_md.split(START, 1)[0].rstrip("\n")
|
|
195
|
+
post = claude_md.split(END, 1)[1].lstrip("\n")
|
|
196
|
+
return f"{pre}\n\n{block}\n\n{post}".rstrip() + "\n"
|
|
197
|
+
# No markers yet: append a section at the end.
|
|
198
|
+
return claude_md.rstrip() + "\n\n## Capability Router (auto-generated)\n\n" + block + "\n"
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def main() -> int:
|
|
202
|
+
# argparse, not `in sys.argv`: without it the no-argument path IS the
|
|
203
|
+
# destructive one, so `build-router.py --help` rewrote CLAUDE.md instead of
|
|
204
|
+
# explaining itself - a surprising way to dirty a clean working copy.
|
|
205
|
+
parser = argparse.ArgumentParser(
|
|
206
|
+
description="Regenerate the Capability Router block in CLAUDE.md from the "
|
|
207
|
+
"tool and agent manifests. With no flags it REWRITES CLAUDE.md.",
|
|
208
|
+
epilog="The block is a pure function of the manifests: it carries no "
|
|
209
|
+
"per-machine state, so every checkout generates the same bytes.",
|
|
210
|
+
)
|
|
211
|
+
group = parser.add_mutually_exclusive_group()
|
|
212
|
+
group.add_argument("--print", action="store_true",
|
|
213
|
+
help="Write the block to stdout and change nothing.")
|
|
214
|
+
group.add_argument("--check", action="store_true",
|
|
215
|
+
help="Exit 1 if CLAUDE.md is out of date. Changes nothing.")
|
|
216
|
+
args = parser.parse_args()
|
|
217
|
+
|
|
218
|
+
block, warnings = build_block()
|
|
219
|
+
claude_path = _PROJECT_ROOT / "CLAUDE.md"
|
|
220
|
+
|
|
221
|
+
if args.print:
|
|
222
|
+
print(block)
|
|
223
|
+
for w in warnings:
|
|
224
|
+
print(f"warning: {w}", file=sys.stderr)
|
|
225
|
+
return 0
|
|
226
|
+
|
|
227
|
+
current = claude_path.read_text(encoding="utf-8") if claude_path.exists() else ""
|
|
228
|
+
updated = splice(current, block)
|
|
229
|
+
|
|
230
|
+
if args.check:
|
|
231
|
+
if current != updated:
|
|
232
|
+
print("CLAUDE.md Capability Router is out of date — run scripts/build-router.py", file=sys.stderr)
|
|
233
|
+
return 1
|
|
234
|
+
print("CLAUDE.md Capability Router is up to date.")
|
|
235
|
+
return 0
|
|
236
|
+
|
|
237
|
+
# newline="\n" because on Windows write_text() would translate every \n to \r\n.
|
|
238
|
+
# CLAUDE.md is LF in version control, so without this each run rewrites all ~370
|
|
239
|
+
# lines and buries a real two-line change in a whole-file diff - which the git<->svn
|
|
240
|
+
# mirror then has to resolve line by line. Same reason build-tool-skill.py does it.
|
|
241
|
+
claude_path.write_text(updated, encoding="utf-8", newline="\n")
|
|
242
|
+
print(f"Wrote Capability Router to {claude_path} ({len(updated)} bytes).")
|
|
243
|
+
for w in warnings:
|
|
244
|
+
print(f"warning: {w}", file=sys.stderr)
|
|
245
|
+
return 0
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
if __name__ == "__main__":
|
|
249
|
+
raise SystemExit(main())
|