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,103 @@
|
|
|
1
|
+
"""Google multi-account (profile) management for the dashboard.
|
|
2
|
+
|
|
3
|
+
The 8 Google tools share one OAuth credential set under the `google:` namespace
|
|
4
|
+
and support MULTIPLE accounts, each keyed by an arbitrary lowercase LABEL
|
|
5
|
+
(`default`, `personal`, `work`, ...) - NOT by email. Only `google-mail` (and
|
|
6
|
+
`google-contacts`) expose the `--account` surface + `auth-accounts`, and the token
|
|
7
|
+
they write is shared by every Google tool, so we drive ALL account operations
|
|
8
|
+
through `google-mail`.
|
|
9
|
+
|
|
10
|
+
list -> google-mail auth-accounts (+ best-effort email via get-profile)
|
|
11
|
+
add /
|
|
12
|
+
re-auth-> google-mail auth-login --account (BLOCKS on browser consent -> a job)
|
|
13
|
+
remove -> google-mail auth-logout --account (fast)
|
|
14
|
+
|
|
15
|
+
The OAuth CLIENT (google:oauth-client) is a precondition the user provisions as a
|
|
16
|
+
normal credential (the card's client-key row); we only manage the per-account
|
|
17
|
+
tokens here.
|
|
18
|
+
"""
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import re
|
|
22
|
+
from typing import Any
|
|
23
|
+
|
|
24
|
+
from . import inventory, jobs, runner
|
|
25
|
+
|
|
26
|
+
_DRIVER = "google-mail"
|
|
27
|
+
_LABEL_RE = re.compile(r"^[a-z0-9._-]+$")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _valid_label(label: str) -> bool:
|
|
31
|
+
return bool(_LABEL_RE.match(label))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _account_args(action_argv: list[str], label: str) -> list[str]:
|
|
35
|
+
"""--account goes AFTER the action (a global flag stripped by the tool)."""
|
|
36
|
+
argv = list(action_argv)
|
|
37
|
+
if label:
|
|
38
|
+
argv += ["--account", label]
|
|
39
|
+
return argv
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def accounts(req) -> Any:
|
|
43
|
+
"""List connected Google profiles - fast (labels only, no network). The email
|
|
44
|
+
for each is fetched lazily by the UI via /api/google/email so the list appears
|
|
45
|
+
instantly instead of blocking on a get-profile call per account."""
|
|
46
|
+
r = runner.run_tool(_DRIVER, ["auth-accounts"], timeout=30)
|
|
47
|
+
if not r["ok"]:
|
|
48
|
+
# Most common cause: the OAuth client isn't stored yet.
|
|
49
|
+
st = runner.run_tool(_DRIVER, ["auth-status"], timeout=20)
|
|
50
|
+
has_client = bool(st["ok"] and (st["data"] or {}).get("has_client"))
|
|
51
|
+
return {"ok": False, "has_client": has_client,
|
|
52
|
+
"accounts": [], "error": r["error"]}
|
|
53
|
+
data = r["data"] or {}
|
|
54
|
+
active = data.get("active")
|
|
55
|
+
out = [{"account": a.get("account"), "has_token": bool(a.get("has_token")),
|
|
56
|
+
"active": a.get("account") == active}
|
|
57
|
+
for a in data.get("accounts", [])]
|
|
58
|
+
return {"ok": True, "active": active, "accounts": out}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def email(req) -> Any:
|
|
62
|
+
"""Resolve one account's email address (a live get-profile call). Lazy, so a
|
|
63
|
+
slow or failing account never blocks the account list."""
|
|
64
|
+
label = (req.q("account") or "").strip().lower()
|
|
65
|
+
if not label or not _valid_label(label):
|
|
66
|
+
return (400, {"error": "invalid account"})
|
|
67
|
+
pr = runner.run_tool(_DRIVER, ["get-profile", "--account", label], timeout=25)
|
|
68
|
+
if pr["ok"] and isinstance(pr["data"], dict):
|
|
69
|
+
return {"account": label,
|
|
70
|
+
"email": pr["data"].get("emailAddress") or pr["data"].get("email")}
|
|
71
|
+
return {"account": label, "email": None,
|
|
72
|
+
"error": (pr.get("error") or {}).get("message")}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def login(req) -> Any:
|
|
76
|
+
"""Add a new profile or re-authorize an existing one (same command). Runs as a
|
|
77
|
+
job because auth-login opens a browser and blocks until the user consents."""
|
|
78
|
+
label = (req.body.get("account") or "default").strip().lower()
|
|
79
|
+
if not _valid_label(label):
|
|
80
|
+
return (400, {"error": "invalid label",
|
|
81
|
+
"message": "Use a short label like 'personal' or 'work' "
|
|
82
|
+
"(lowercase letters, digits, . _ - ). Not an email."})
|
|
83
|
+
argv = ["run-tool.py", _DRIVER] + _account_args(["auth-login"],
|
|
84
|
+
"" if label == "default" else label)
|
|
85
|
+
job = jobs.create("google-oauth", argv, stdin_signal=False)
|
|
86
|
+
snap = job.snapshot()
|
|
87
|
+
snap["account"] = label
|
|
88
|
+
return snap
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def remove(req) -> Any:
|
|
92
|
+
"""Remove ONE profile's token (leaves the shared oauth-client intact)."""
|
|
93
|
+
label = (req.body.get("account") or "").strip().lower()
|
|
94
|
+
if not label:
|
|
95
|
+
return (400, {"error": "account label is required"})
|
|
96
|
+
if not _valid_label(label):
|
|
97
|
+
return (400, {"error": "invalid label"})
|
|
98
|
+
argv = _account_args(["auth-logout"], "" if label == "default" else label)
|
|
99
|
+
r = runner.run_tool(_DRIVER, argv, timeout=30)
|
|
100
|
+
if r["ok"]:
|
|
101
|
+
inventory.invalidate()
|
|
102
|
+
return {"ok": True, "account": label, "data": r["data"]}
|
|
103
|
+
return {"ok": False, "account": label, "error": r["error"]}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""HTTP request handler: routing, token gate, JSON + SSE + static serving.
|
|
2
|
+
|
|
3
|
+
Stdlib only. Domain logic lives in inventory/validate/setup/llmtest; this module
|
|
4
|
+
just parses the request, enforces the loopback token on /api/*, dispatches, and
|
|
5
|
+
serializes the response. Route handlers are imported lazily inside each branch so
|
|
6
|
+
the server boots even while later-milestone modules are still being added.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import traceback
|
|
12
|
+
from http.server import BaseHTTPRequestHandler
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from urllib.parse import parse_qs, urlparse
|
|
15
|
+
|
|
16
|
+
from . import security
|
|
17
|
+
|
|
18
|
+
WEB_DIR = Path(__file__).resolve().parents[1] / "web"
|
|
19
|
+
|
|
20
|
+
_CTYPES = {".html": "text/html; charset=utf-8",
|
|
21
|
+
".js": "application/javascript; charset=utf-8",
|
|
22
|
+
".css": "text/css; charset=utf-8",
|
|
23
|
+
".svg": "image/svg+xml", ".ico": "image/x-icon"}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Req:
|
|
27
|
+
"""Minimal parsed-request view passed to route handlers."""
|
|
28
|
+
def __init__(self, method: str, path: str, query: dict, body: dict | None):
|
|
29
|
+
self.method = method
|
|
30
|
+
self.path = path
|
|
31
|
+
self.query = query
|
|
32
|
+
self.body = body or {}
|
|
33
|
+
|
|
34
|
+
def q(self, name: str, default=None):
|
|
35
|
+
v = self.query.get(name)
|
|
36
|
+
return v[0] if isinstance(v, list) and v else default
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class Handler(BaseHTTPRequestHandler):
|
|
40
|
+
server_version = "AATDashboard/0.1"
|
|
41
|
+
protocol_version = "HTTP/1.1"
|
|
42
|
+
|
|
43
|
+
# ---- low-level response helpers -------------------------------------
|
|
44
|
+
def _send_json(self, obj, status: int = 200):
|
|
45
|
+
payload = json.dumps(obj, ensure_ascii=False, default=str).encode("utf-8")
|
|
46
|
+
self.send_response(status)
|
|
47
|
+
self.send_header("Content-Type", "application/json; charset=utf-8")
|
|
48
|
+
self.send_header("Content-Length", str(len(payload)))
|
|
49
|
+
self.send_header("Cache-Control", "no-store")
|
|
50
|
+
self.end_headers()
|
|
51
|
+
self.wfile.write(payload)
|
|
52
|
+
|
|
53
|
+
def _send_bytes(self, data: bytes, ctype: str, status: int = 200):
|
|
54
|
+
self.send_response(status)
|
|
55
|
+
self.send_header("Content-Type", ctype)
|
|
56
|
+
self.send_header("Content-Length", str(len(data)))
|
|
57
|
+
self.send_header("Cache-Control", "no-store") # local tool - always fresh
|
|
58
|
+
self.end_headers()
|
|
59
|
+
self.wfile.write(data)
|
|
60
|
+
|
|
61
|
+
def _sse_open(self):
|
|
62
|
+
self.send_response(200)
|
|
63
|
+
self.send_header("Content-Type", "text/event-stream; charset=utf-8")
|
|
64
|
+
self.send_header("Cache-Control", "no-store")
|
|
65
|
+
self.send_header("Connection", "keep-alive")
|
|
66
|
+
self.end_headers()
|
|
67
|
+
|
|
68
|
+
def _sse_send(self, event: str, data: dict):
|
|
69
|
+
chunk = f"event: {event}\ndata: {json.dumps(data, default=str)}\n\n"
|
|
70
|
+
self.wfile.write(chunk.encode("utf-8"))
|
|
71
|
+
self.wfile.flush()
|
|
72
|
+
|
|
73
|
+
# ---- auth -----------------------------------------------------------
|
|
74
|
+
def _authed(self, query: dict) -> bool:
|
|
75
|
+
tok = self.headers.get("X-Dashboard-Token")
|
|
76
|
+
if not tok:
|
|
77
|
+
q = query.get("token")
|
|
78
|
+
tok = q[0] if isinstance(q, list) and q else None
|
|
79
|
+
return security.token_ok(tok)
|
|
80
|
+
|
|
81
|
+
# ---- static ---------------------------------------------------------
|
|
82
|
+
def _serve_static(self, path: str):
|
|
83
|
+
rel = "index.html" if path in ("/", "") else path.lstrip("/")
|
|
84
|
+
if rel.startswith("static/"):
|
|
85
|
+
rel = rel[len("static/"):]
|
|
86
|
+
target = (WEB_DIR / rel).resolve()
|
|
87
|
+
if WEB_DIR.resolve() not in target.parents and target != WEB_DIR.resolve():
|
|
88
|
+
self._send_json({"error": "forbidden"}, 403)
|
|
89
|
+
return
|
|
90
|
+
if not target.is_file():
|
|
91
|
+
self._send_json({"error": "not found", "path": path}, 404)
|
|
92
|
+
return
|
|
93
|
+
ctype = _CTYPES.get(target.suffix, "application/octet-stream")
|
|
94
|
+
self._send_bytes(target.read_bytes(), ctype)
|
|
95
|
+
|
|
96
|
+
# ---- dispatch -------------------------------------------------------
|
|
97
|
+
def do_GET(self):
|
|
98
|
+
parsed = urlparse(self.path)
|
|
99
|
+
path, query = parsed.path, parse_qs(parsed.query)
|
|
100
|
+
if not path.startswith("/api/"):
|
|
101
|
+
return self._serve_static(path)
|
|
102
|
+
if not self._authed(query):
|
|
103
|
+
return self._send_json({"error": "unauthorized"}, 401)
|
|
104
|
+
if path == "/api/validate/all":
|
|
105
|
+
return self._route_sse(Req("GET", path, query, None))
|
|
106
|
+
return self._route(Req("GET", path, query, None))
|
|
107
|
+
|
|
108
|
+
def do_POST(self):
|
|
109
|
+
parsed = urlparse(self.path)
|
|
110
|
+
path, query = parsed.path, parse_qs(parsed.query)
|
|
111
|
+
if not self._authed(query):
|
|
112
|
+
return self._send_json({"error": "unauthorized"}, 401)
|
|
113
|
+
body = self._read_body()
|
|
114
|
+
return self._route(Req("POST", path, query, body))
|
|
115
|
+
|
|
116
|
+
def _read_body(self) -> dict | None:
|
|
117
|
+
length = int(self.headers.get("Content-Length") or 0)
|
|
118
|
+
if not length:
|
|
119
|
+
return None
|
|
120
|
+
raw = self.rfile.read(length)
|
|
121
|
+
try:
|
|
122
|
+
return json.loads(raw.decode("utf-8"))
|
|
123
|
+
except (ValueError, UnicodeDecodeError):
|
|
124
|
+
return None
|
|
125
|
+
|
|
126
|
+
def _route(self, req: Req):
|
|
127
|
+
try:
|
|
128
|
+
from . import routes
|
|
129
|
+
fn = routes.resolve(req.method, req.path)
|
|
130
|
+
if fn is None:
|
|
131
|
+
return self._send_json({"error": "no such route",
|
|
132
|
+
"path": req.path}, 404)
|
|
133
|
+
result = fn(req)
|
|
134
|
+
if isinstance(result, tuple):
|
|
135
|
+
status, obj = result
|
|
136
|
+
return self._send_json(obj, status)
|
|
137
|
+
return self._send_json(result)
|
|
138
|
+
except Exception as e: # noqa: BLE001 - surface as JSON, never 500-crash
|
|
139
|
+
return self._send_json(
|
|
140
|
+
{"error": "handler_exception", "message": str(e),
|
|
141
|
+
"trace": traceback.format_exc().splitlines()[-6:]}, 500)
|
|
142
|
+
|
|
143
|
+
def _route_sse(self, req: Req):
|
|
144
|
+
try:
|
|
145
|
+
from . import validate
|
|
146
|
+
self._sse_open()
|
|
147
|
+
for event, data in validate.stream_all(req):
|
|
148
|
+
self._sse_send(event, data)
|
|
149
|
+
self._sse_send("done", {"ok": True})
|
|
150
|
+
except BrokenPipeError:
|
|
151
|
+
pass
|
|
152
|
+
except Exception as e: # noqa: BLE001
|
|
153
|
+
try:
|
|
154
|
+
self._sse_send("error", {"message": str(e)})
|
|
155
|
+
except Exception:
|
|
156
|
+
pass
|
|
157
|
+
|
|
158
|
+
def log_message(self, fmt, *args):
|
|
159
|
+
# Quiet by default; the launcher prints a startup banner instead.
|
|
160
|
+
pass
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"""The read model: assemble the full dashboard picture from the live registry.
|
|
2
|
+
|
|
3
|
+
Reads are in-process (import registry / userdata / bootstraplib) so the inventory
|
|
4
|
+
is fast and always reflects the real folder + Credential Manager state. The only
|
|
5
|
+
subprocess reads here are the store stats and llm providers (they belong to tools
|
|
6
|
+
that own their own config/DB).
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import sqlite3
|
|
12
|
+
import threading
|
|
13
|
+
import time
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
import registry
|
|
17
|
+
from agents.orchestrator import bootstraplib
|
|
18
|
+
from tools._lib import creds, userdata
|
|
19
|
+
|
|
20
|
+
# A full build scans every manifest (a few seconds on a large registry). Cache it
|
|
21
|
+
# briefly and serialize builds so a page reload, a validation reconnect, or two
|
|
22
|
+
# concurrent requests never stack N full scans. Mutations (credential/config
|
|
23
|
+
# writes) call invalidate() so the next read reflects the change immediately.
|
|
24
|
+
_INV_TTL = 4.0
|
|
25
|
+
_INV_LOCK = threading.Lock()
|
|
26
|
+
_INV_CACHE: dict[str, Any] = {"ts": 0.0, "data": None}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def invalidate() -> None:
|
|
30
|
+
with _INV_LOCK:
|
|
31
|
+
_INV_CACHE["ts"] = 0.0
|
|
32
|
+
_INV_CACHE["data"] = None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _probe_kind(entry: dict[str, Any]) -> str | None:
|
|
36
|
+
"""What live-validation path exists for this capability: an explicit
|
|
37
|
+
healthcheck, else a conventional auth-status action, else nothing."""
|
|
38
|
+
if entry.get("healthcheck"):
|
|
39
|
+
return "healthcheck"
|
|
40
|
+
action_names = {a["name"] for a in entry.get("actions", [])}
|
|
41
|
+
if "auth-status" in action_names:
|
|
42
|
+
return "auth-status"
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _present_sessions() -> set[str]:
|
|
47
|
+
"""Base names of saved web sessions (X.json / X.profile / X.cookies.json)."""
|
|
48
|
+
d = userdata.sessions_dir()
|
|
49
|
+
names: set[str] = set()
|
|
50
|
+
if not d.exists():
|
|
51
|
+
return names
|
|
52
|
+
for p in d.iterdir():
|
|
53
|
+
for suf in (".cookies.json", ".json", ".profile"):
|
|
54
|
+
if p.name.endswith(suf):
|
|
55
|
+
names.add(p.name[: -len(suf)])
|
|
56
|
+
break
|
|
57
|
+
return names
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _annotate(entry: dict[str, Any], kind: str,
|
|
61
|
+
present_sessions: set[str] | None = None) -> dict[str, Any]:
|
|
62
|
+
entry["kind"] = kind
|
|
63
|
+
missing = set(entry.get("missing_secrets", []))
|
|
64
|
+
# OAuth tools carry oauth-token/oauth-accounts secrets that are PRODUCED by the
|
|
65
|
+
# sign-in flow (auth-login), not entered by hand. Hide them from the card so a
|
|
66
|
+
# newcomer sees "Connect (sign in)" instead of confusing set/delete rows for a
|
|
67
|
+
# token they can't type. The oauth CLIENT key (which the user does provide) stays.
|
|
68
|
+
has_oauth = any(a.get("name") == "auth-login" for a in entry.get("actions", []))
|
|
69
|
+
|
|
70
|
+
def _oauth_output(nm: str) -> bool:
|
|
71
|
+
return has_oauth and (nm.endswith("oauth-token") or nm.endswith("oauth-accounts"))
|
|
72
|
+
|
|
73
|
+
entry["secrets_status"] = [
|
|
74
|
+
{"name": s["name"], "description": s.get("description", ""),
|
|
75
|
+
"present": s["name"] not in missing}
|
|
76
|
+
for s in entry.get("secrets", []) if not _oauth_output(s["name"])
|
|
77
|
+
]
|
|
78
|
+
entry["probe"] = _probe_kind(entry)
|
|
79
|
+
# A tool may need a saved web login instead of (or on top of) a credential.
|
|
80
|
+
ws = entry.get("web_session")
|
|
81
|
+
session_missing = False
|
|
82
|
+
if ws:
|
|
83
|
+
present = ws["name"] in (present_sessions or set())
|
|
84
|
+
entry["web_session_status"] = {
|
|
85
|
+
"name": ws["name"], "login_url": ws.get("login_url", ""),
|
|
86
|
+
"persistent": ws.get("persistent", False), "channel": ws.get("channel", ""),
|
|
87
|
+
"label": ws.get("label", ""), "present": present}
|
|
88
|
+
session_missing = not present
|
|
89
|
+
entry["needs_setup"] = bool(missing) or session_missing or (
|
|
90
|
+
kind == "agent" and not entry.get("ready", False))
|
|
91
|
+
return entry
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def store_stats() -> dict[str, Any] | None:
|
|
95
|
+
"""Record/run counts read straight from the SQLite store (read-only), so the
|
|
96
|
+
dashboard never shells out to the context-store tool for a simple count -
|
|
97
|
+
faster, and immune to the keyring-import hang that afflicts subprocesses
|
|
98
|
+
spawned from a detached parent."""
|
|
99
|
+
p = userdata.store_db_path()
|
|
100
|
+
if not p.exists():
|
|
101
|
+
return None
|
|
102
|
+
try:
|
|
103
|
+
con = sqlite3.connect(f"file:{p}?mode=ro", uri=True, timeout=5)
|
|
104
|
+
except sqlite3.Error:
|
|
105
|
+
return None
|
|
106
|
+
try:
|
|
107
|
+
rec = con.execute("SELECT count(*) FROM records").fetchone()[0]
|
|
108
|
+
runs = con.execute("SELECT count(*) FROM runs").fetchone()[0]
|
|
109
|
+
openruns = con.execute(
|
|
110
|
+
"SELECT count(*) FROM runs WHERE status IN ('open','active')").fetchone()[0]
|
|
111
|
+
return {"records": rec, "runs": runs, "open_runs": openruns}
|
|
112
|
+
except sqlite3.Error:
|
|
113
|
+
return None # schema not initialized yet (fresh install)
|
|
114
|
+
finally:
|
|
115
|
+
con.close()
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def providers() -> dict[str, Any]:
|
|
119
|
+
"""llm provider config + key presence (NEVER a key value), read in-process
|
|
120
|
+
from providers.json + Credential Manager. Mirrors the llm tool's
|
|
121
|
+
list-providers shape without importing that tool's provider adapters (which
|
|
122
|
+
require its own sys.path) or spawning a subprocess."""
|
|
123
|
+
p = userdata.config_dir("llm") / "providers.json"
|
|
124
|
+
if not p.exists():
|
|
125
|
+
return {"default": None, "providers": [],
|
|
126
|
+
"error": {"code": "no_config", "message": "no providers.json yet"}}
|
|
127
|
+
try:
|
|
128
|
+
cfg = json.loads(p.read_text(encoding="utf-8"))
|
|
129
|
+
except ValueError as e:
|
|
130
|
+
return {"default": None, "providers": [],
|
|
131
|
+
"error": {"code": "bad_config", "message": str(e)}}
|
|
132
|
+
default = cfg.get("default")
|
|
133
|
+
out = []
|
|
134
|
+
for name, pc in (cfg.get("providers") or {}).items():
|
|
135
|
+
out.append({
|
|
136
|
+
"name": name,
|
|
137
|
+
"adapter": pc.get("adapter", "openai_compat"),
|
|
138
|
+
"base_url": pc.get("base_url"),
|
|
139
|
+
"model": pc.get("model"),
|
|
140
|
+
"auth_style": pc.get("auth_style", "bearer"),
|
|
141
|
+
"config": {k: v for k, v in pc.items() if k != "api_key"},
|
|
142
|
+
"key_present": creds.has_for_report("llm", name),
|
|
143
|
+
"is_default": name == default,
|
|
144
|
+
})
|
|
145
|
+
return {"default": default, "providers": out}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def build(force: bool = False) -> dict[str, Any]:
|
|
149
|
+
"""Cached, single-flight inventory build."""
|
|
150
|
+
with _INV_LOCK:
|
|
151
|
+
fresh = (_INV_CACHE["data"] is not None
|
|
152
|
+
and (time.time() - _INV_CACHE["ts"]) < _INV_TTL)
|
|
153
|
+
if fresh and not force:
|
|
154
|
+
return _INV_CACHE["data"]
|
|
155
|
+
data = _build()
|
|
156
|
+
_INV_CACHE["ts"] = time.time()
|
|
157
|
+
_INV_CACHE["data"] = data
|
|
158
|
+
return data
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _build() -> dict[str, Any]:
|
|
162
|
+
tool_entries = registry.list_tools()
|
|
163
|
+
tool_index = {t["name"]: t for t in tool_entries}
|
|
164
|
+
sessions = _present_sessions()
|
|
165
|
+
tools = [_annotate(t, "tool", sessions) for t in tool_entries]
|
|
166
|
+
agents = [_annotate(a, "agent", sessions)
|
|
167
|
+
for a in registry.list_agents(tool_index=tool_index)]
|
|
168
|
+
skills = registry.list_skills()
|
|
169
|
+
for s in skills:
|
|
170
|
+
s["kind"] = "skill"
|
|
171
|
+
|
|
172
|
+
store = store_stats()
|
|
173
|
+
fresh = bootstraplib.freshness(store)
|
|
174
|
+
prov = providers()
|
|
175
|
+
llm_ready = any(p.get("key_present") for p in prov.get("providers", []))
|
|
176
|
+
|
|
177
|
+
def cnt(items, pred):
|
|
178
|
+
return sum(1 for x in items if pred(x))
|
|
179
|
+
|
|
180
|
+
def is_ready(x): # truly set up: no missing secrets, no missing session, loads
|
|
181
|
+
return not x.get("needs_setup") and not x.get("error")
|
|
182
|
+
|
|
183
|
+
summary = {
|
|
184
|
+
"tools": {
|
|
185
|
+
"total": len(tools),
|
|
186
|
+
"ready": cnt(tools, is_ready),
|
|
187
|
+
"needs_setup": cnt(tools, lambda t: t.get("needs_setup")),
|
|
188
|
+
"errored": cnt(tools, lambda t: t.get("error")),
|
|
189
|
+
},
|
|
190
|
+
"agents": {
|
|
191
|
+
"total": len(agents),
|
|
192
|
+
"ready": cnt(agents, is_ready),
|
|
193
|
+
"needs_setup": cnt(agents, lambda a: a.get("needs_setup")),
|
|
194
|
+
"errored": cnt(agents, lambda a: a.get("error")),
|
|
195
|
+
},
|
|
196
|
+
"skills": {"total": len(skills)},
|
|
197
|
+
"llm_ready": llm_ready,
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
"summary": summary,
|
|
202
|
+
"tools": tools,
|
|
203
|
+
"agents": agents,
|
|
204
|
+
"skills": skills,
|
|
205
|
+
"providers": prov,
|
|
206
|
+
"store": store,
|
|
207
|
+
"userdata": {
|
|
208
|
+
**userdata.describe(),
|
|
209
|
+
"scan": fresh["scan"],
|
|
210
|
+
},
|
|
211
|
+
"fresh_start": fresh["fresh_start"],
|
|
212
|
+
"onboarding": bootstraplib.onboarding_hint() if fresh["fresh_start"] else None,
|
|
213
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Background jobs for interactive setup steps that outlive one request.
|
|
2
|
+
|
|
3
|
+
Two shapes:
|
|
4
|
+
* a plain job that runs a script to completion and streams its output
|
|
5
|
+
(OAuth login: the tool opens a browser and self-completes on the localhost
|
|
6
|
+
redirect), and
|
|
7
|
+
* a signal job that launches a script which blocks for a stdin ENTER
|
|
8
|
+
(web save-session: a headed browser opens, the human logs in, then the UI
|
|
9
|
+
sends the signal to persist the session).
|
|
10
|
+
|
|
11
|
+
Jobs live in memory only. The dashboard is single-user and local; a restart just
|
|
12
|
+
drops in-flight logins, which the user re-runs.
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import subprocess
|
|
17
|
+
import threading
|
|
18
|
+
import time
|
|
19
|
+
import uuid
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
from . import runner
|
|
23
|
+
|
|
24
|
+
_JOBS: dict[str, "Job"] = {}
|
|
25
|
+
_LOCK = threading.Lock()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Job:
|
|
29
|
+
def __init__(self, kind: str, argv: list[str], *, stdin_signal: bool):
|
|
30
|
+
self.id = uuid.uuid4().hex[:12]
|
|
31
|
+
self.kind = kind
|
|
32
|
+
self.argv = argv
|
|
33
|
+
self.stdin_signal = stdin_signal
|
|
34
|
+
self.status = "starting" # starting|awaiting_signal|running|done|failed
|
|
35
|
+
self.logs: list[str] = []
|
|
36
|
+
self.result: dict | None = None
|
|
37
|
+
self.error: str | None = None
|
|
38
|
+
self.created = time.time()
|
|
39
|
+
self._proc: subprocess.Popen | None = None
|
|
40
|
+
self._lock = threading.Lock()
|
|
41
|
+
|
|
42
|
+
def _log(self, line: str):
|
|
43
|
+
with self._lock:
|
|
44
|
+
self.logs.append(line.rstrip("\n"))
|
|
45
|
+
if len(self.logs) > 400:
|
|
46
|
+
self.logs = self.logs[-400:]
|
|
47
|
+
|
|
48
|
+
def start(self):
|
|
49
|
+
cmd = [runner.python_exe(), str(runner.PROJECT_ROOT / "scripts" / self.argv[0]),
|
|
50
|
+
*self.argv[1:]]
|
|
51
|
+
try:
|
|
52
|
+
self._proc = subprocess.Popen(
|
|
53
|
+
cmd, cwd=str(runner.PROJECT_ROOT), text=True, encoding="utf-8",
|
|
54
|
+
errors="replace", bufsize=1,
|
|
55
|
+
stdin=subprocess.PIPE if self.stdin_signal else subprocess.DEVNULL,
|
|
56
|
+
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
57
|
+
except Exception as e: # noqa: BLE001
|
|
58
|
+
self.status = "failed"
|
|
59
|
+
self.error = f"could not launch: {e}"
|
|
60
|
+
return
|
|
61
|
+
self.status = "awaiting_signal" if self.stdin_signal else "running"
|
|
62
|
+
threading.Thread(target=self._pump, daemon=True).start()
|
|
63
|
+
|
|
64
|
+
def _pump(self):
|
|
65
|
+
assert self._proc is not None
|
|
66
|
+
for line in self._proc.stdout: # blocks until each line / EOF
|
|
67
|
+
self._log(line)
|
|
68
|
+
self._proc.wait()
|
|
69
|
+
result = runner._parse_json("\n".join(self.logs))
|
|
70
|
+
if self._proc.returncode == 0 and isinstance(result, dict) and "error" not in result:
|
|
71
|
+
self.status = "done"
|
|
72
|
+
self.result = result
|
|
73
|
+
else:
|
|
74
|
+
self.status = "failed"
|
|
75
|
+
if isinstance(result, dict) and "error" in result:
|
|
76
|
+
self.error = result["error"].get("message") if isinstance(
|
|
77
|
+
result["error"], dict) else str(result["error"])
|
|
78
|
+
else:
|
|
79
|
+
self.error = (self.logs[-1] if self.logs else
|
|
80
|
+
f"exited with code {self._proc.returncode}")
|
|
81
|
+
|
|
82
|
+
def signal(self) -> bool:
|
|
83
|
+
"""Send the ENTER that a save-session subprocess is blocking on."""
|
|
84
|
+
if not (self._proc and self._proc.stdin and self.status == "awaiting_signal"):
|
|
85
|
+
return False
|
|
86
|
+
try:
|
|
87
|
+
self._proc.stdin.write("\n")
|
|
88
|
+
self._proc.stdin.flush()
|
|
89
|
+
self.status = "running"
|
|
90
|
+
return True
|
|
91
|
+
except Exception: # noqa: BLE001
|
|
92
|
+
return False
|
|
93
|
+
|
|
94
|
+
def wait(self, timeout: float) -> None:
|
|
95
|
+
if self._proc:
|
|
96
|
+
try:
|
|
97
|
+
self._proc.wait(timeout=timeout)
|
|
98
|
+
except subprocess.TimeoutExpired:
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
def snapshot(self) -> dict[str, Any]:
|
|
102
|
+
with self._lock:
|
|
103
|
+
return {"id": self.id, "kind": self.kind, "status": self.status,
|
|
104
|
+
"logs": list(self.logs[-40:]), "result": self.result,
|
|
105
|
+
"error": self.error}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def create(kind: str, argv: list[str], *, stdin_signal: bool = False) -> Job:
|
|
109
|
+
job = Job(kind, argv, stdin_signal=stdin_signal)
|
|
110
|
+
with _LOCK:
|
|
111
|
+
_JOBS[job.id] = job
|
|
112
|
+
job.start()
|
|
113
|
+
return job
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def get(job_id: str) -> Job | None:
|
|
117
|
+
with _LOCK:
|
|
118
|
+
return _JOBS.get(job_id)
|