gatewaysdk 0.3.2__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.
- gatewaysdk/__init__.py +540 -0
- gatewaysdk/adapter/__init__.py +15 -0
- gatewaysdk/adapter/base.py +94 -0
- gatewaysdk/adapter/messages.py +270 -0
- gatewaysdk/adapter/triplet.py +1026 -0
- gatewaysdk/algorithm/__init__.py +39 -0
- gatewaysdk/algorithm/apo/__init__.py +5 -0
- gatewaysdk/algorithm/apo/apo.py +898 -0
- gatewaysdk/algorithm/apo/prompts/apply_edit_variant01.poml +22 -0
- gatewaysdk/algorithm/apo/prompts/apply_edit_variant02.poml +18 -0
- gatewaysdk/algorithm/apo/prompts/text_gradient_variant01.poml +18 -0
- gatewaysdk/algorithm/apo/prompts/text_gradient_variant02.poml +16 -0
- gatewaysdk/algorithm/apo/prompts/text_gradient_variant03.poml +107 -0
- gatewaysdk/algorithm/base.py +262 -0
- gatewaysdk/algorithm/decorator.py +264 -0
- gatewaysdk/algorithm/evals/__init__.py +7 -0
- gatewaysdk/algorithm/evals/evals.py +217 -0
- gatewaysdk/algorithm/fast.py +250 -0
- gatewaysdk/algorithm/gepa/__init__.py +61 -0
- gatewaysdk/algorithm/gepa/adapter.py +495 -0
- gatewaysdk/algorithm/gepa/gepa.py +570 -0
- gatewaysdk/algorithm/gepa/lib/__init__.py +18 -0
- gatewaysdk/algorithm/gepa/lib/adapters/README.md +12 -0
- gatewaysdk/algorithm/gepa/lib/adapters/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/README.md +341 -0
- gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/__init__.py +1 -0
- gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
- gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/requirements.txt +1 -0
- gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/README.md +0 -0
- gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/default_adapter.py +209 -0
- gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/README.md +7 -0
- gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/dspy_adapter.py +307 -0
- gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/README.md +99 -0
- gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
- gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/full_program_adapter.py +268 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/GEPA_RAG.md +621 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/__init__.py +56 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
- gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
- gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/README.md +552 -0
- gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/__init__.py +37 -0
- gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_adapter.py +699 -0
- gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_client.py +364 -0
- gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/README.md +9 -0
- gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
- gatewaysdk/algorithm/gepa/lib/api.py +382 -0
- gatewaysdk/algorithm/gepa/lib/core/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/core/adapter.py +180 -0
- gatewaysdk/algorithm/gepa/lib/core/data_loader.py +74 -0
- gatewaysdk/algorithm/gepa/lib/core/engine.py +379 -0
- gatewaysdk/algorithm/gepa/lib/core/result.py +233 -0
- gatewaysdk/algorithm/gepa/lib/core/state.py +636 -0
- gatewaysdk/algorithm/gepa/lib/examples/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/examples/aime.py +24 -0
- gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/eval_default.py +111 -0
- gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/instruction_prompt.txt +9 -0
- gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/optimal_prompt.txt +24 -0
- gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/train_anymaths.py +177 -0
- gatewaysdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/arc_agi.ipynb +25705 -0
- gatewaysdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/example.ipynb +348 -0
- gatewaysdk/algorithm/gepa/lib/examples/mcp_adapter/__init__.py +4 -0
- gatewaysdk/algorithm/gepa/lib/examples/mcp_adapter/mcp_optimization_example.py +456 -0
- gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/RAG_GUIDE.md +613 -0
- gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/__init__.py +9 -0
- gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/rag_optimization.py +820 -0
- gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/requirements-rag.txt +29 -0
- gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/instruction_prompt.txt +16 -0
- gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/terminus.txt +9 -0
- gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/train_terminus.py +161 -0
- gatewaysdk/algorithm/gepa/lib/gepa_utils.py +117 -0
- gatewaysdk/algorithm/gepa/lib/logging/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/logging/experiment_tracker.py +187 -0
- gatewaysdk/algorithm/gepa/lib/logging/logger.py +75 -0
- gatewaysdk/algorithm/gepa/lib/logging/utils.py +103 -0
- gatewaysdk/algorithm/gepa/lib/proposer/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/proposer/base.py +31 -0
- gatewaysdk/algorithm/gepa/lib/proposer/merge.py +357 -0
- gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/base.py +49 -0
- gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/reflective_mutation.py +176 -0
- gatewaysdk/algorithm/gepa/lib/py.typed +0 -0
- gatewaysdk/algorithm/gepa/lib/strategies/__init__.py +0 -0
- gatewaysdk/algorithm/gepa/lib/strategies/batch_sampler.py +77 -0
- gatewaysdk/algorithm/gepa/lib/strategies/candidate_selector.py +50 -0
- gatewaysdk/algorithm/gepa/lib/strategies/component_selector.py +36 -0
- gatewaysdk/algorithm/gepa/lib/strategies/eval_policy.py +64 -0
- gatewaysdk/algorithm/gepa/lib/strategies/instruction_proposal.py +126 -0
- gatewaysdk/algorithm/gepa/lib/utils/__init__.py +10 -0
- gatewaysdk/algorithm/gepa/lib/utils/stop_condition.py +196 -0
- gatewaysdk/algorithm/gepa/tracing.py +105 -0
- gatewaysdk/algorithm/utils.py +177 -0
- gatewaysdk/algorithm/verl/__init__.py +5 -0
- gatewaysdk/algorithm/verl/interface.py +202 -0
- gatewaysdk/automations.py +111 -0
- gatewaysdk/benchmark_hub/README.md +88 -0
- gatewaysdk/benchmark_hub/__init__.py +119 -0
- gatewaysdk/benchmark_hub/_archive.py +189 -0
- gatewaysdk/benchmark_hub/_tar.py +6 -0
- gatewaysdk/benchmark_hub/client.py +992 -0
- gatewaysdk/benchmark_hub/dispatch_shard.py +34 -0
- gatewaysdk/benchmark_hub/eval_config.py +20 -0
- gatewaysdk/benchmark_hub/evals.py +351 -0
- gatewaysdk/benchmark_hub/harbor_adapter.py +673 -0
- gatewaysdk/benchmark_hub/path_utils.py +81 -0
- gatewaysdk/benchmark_hub/save_utils.py +101 -0
- gatewaysdk/benchmark_hub/verifiers_adapter.py +327 -0
- gatewaysdk/benchmark_hub/versioning.py +72 -0
- gatewaysdk/build.py +515 -0
- gatewaysdk/cli/__init__.py +58 -0
- gatewaysdk/cli/agent_runner.py +132 -0
- gatewaysdk/cli/http_client.py +115 -0
- gatewaysdk/cli/platform.py +4086 -0
- gatewaysdk/cli/prometheus.py +115 -0
- gatewaysdk/cli/release_gate.py +215 -0
- gatewaysdk/cli/store.py +131 -0
- gatewaysdk/cli/vllm.py +29 -0
- gatewaysdk/client.py +406 -0
- gatewaysdk/config.py +348 -0
- gatewaysdk/connectors/__init__.py +25 -0
- gatewaysdk/connectors/client.py +203 -0
- gatewaysdk/connectors/skill.py +25 -0
- gatewaysdk/connectors/template.py +106 -0
- gatewaysdk/context.py +606 -0
- gatewaysdk/emitter/__init__.py +43 -0
- gatewaysdk/emitter/annotation.py +370 -0
- gatewaysdk/emitter/exception.py +54 -0
- gatewaysdk/emitter/message.py +61 -0
- gatewaysdk/emitter/object.py +117 -0
- gatewaysdk/emitter/reward.py +320 -0
- gatewaysdk/env_var.py +156 -0
- gatewaysdk/environment/__init__.py +108 -0
- gatewaysdk/environment/_bundle.py +281 -0
- gatewaysdk/environment/_harbor.py +276 -0
- gatewaysdk/environment/_materialize.py +97 -0
- gatewaysdk/environment/_tar.py +33 -0
- gatewaysdk/environment/_world.py +346 -0
- gatewaysdk/environment/core.py +527 -0
- gatewaysdk/environment/errors.py +58 -0
- gatewaysdk/environment/runtime.py +150 -0
- gatewaysdk/environment/schema/__init__.py +35 -0
- gatewaysdk/environment/schema/__main__.py +225 -0
- gatewaysdk/environment/schema/_slack_fidelity.py +116 -0
- gatewaysdk/environment/schema/_slack_scenario.py +183 -0
- gatewaysdk/environment/schema/api.py +1628 -0
- gatewaysdk/environment/schema/batch.py +755 -0
- gatewaysdk/environment/schema/compiler.py +615 -0
- gatewaysdk/environment/schema/conform.py +428 -0
- gatewaysdk/environment/schema/connector.py +777 -0
- gatewaysdk/environment/schema/connectors/apple-business-manager/handlers.py +17 -0
- gatewaysdk/environment/schema/connectors/apple-business-manager/parity.json +28 -0
- gatewaysdk/environment/schema/connectors/apple-business-manager/provenance.json +233 -0
- gatewaysdk/environment/schema/connectors/apple-business-manager/scope.toml +112 -0
- gatewaysdk/environment/schema/connectors/apple-business-manager/world.json +1380 -0
- gatewaysdk/environment/schema/connectors/base.json +28 -0
- gatewaysdk/environment/schema/connectors/custom/handlers.py +18 -0
- gatewaysdk/environment/schema/connectors/custom/world.json +123 -0
- gatewaysdk/environment/schema/connectors/github/handlers.py +81 -0
- gatewaysdk/environment/schema/connectors/github/parity.json +37 -0
- gatewaysdk/environment/schema/connectors/github/provenance.json +134 -0
- gatewaysdk/environment/schema/connectors/github/scope.toml +158 -0
- gatewaysdk/environment/schema/connectors/github/world.json +5869 -0
- gatewaysdk/environment/schema/connectors/google-calendar/handlers.py +23 -0
- gatewaysdk/environment/schema/connectors/google-calendar/world.json +209 -0
- gatewaysdk/environment/schema/connectors/google-drive/handlers.py +18 -0
- gatewaysdk/environment/schema/connectors/google-drive/world.json +286 -0
- gatewaysdk/environment/schema/connectors/jamf/handlers.py +34 -0
- gatewaysdk/environment/schema/connectors/jamf/parity.json +49 -0
- gatewaysdk/environment/schema/connectors/jamf/provenance.json +181 -0
- gatewaysdk/environment/schema/connectors/jamf/scope.toml +128 -0
- gatewaysdk/environment/schema/connectors/jamf/world.json +2218 -0
- gatewaysdk/environment/schema/connectors/jira/handlers.py +28 -0
- gatewaysdk/environment/schema/connectors/jira/world.json +389 -0
- gatewaysdk/environment/schema/connectors/kandji/handlers.py +38 -0
- gatewaysdk/environment/schema/connectors/kandji/parity.json +29 -0
- gatewaysdk/environment/schema/connectors/kandji/provenance.json +152 -0
- gatewaysdk/environment/schema/connectors/kandji/scope.toml +120 -0
- gatewaysdk/environment/schema/connectors/kandji/world.json +765 -0
- gatewaysdk/environment/schema/connectors/linear/handlers.py +20 -0
- gatewaysdk/environment/schema/connectors/linear/world.json +363 -0
- gatewaysdk/environment/schema/connectors/microsoft-teams/fidelity.json +45 -0
- gatewaysdk/environment/schema/connectors/microsoft-teams/handlers.py +1 -0
- gatewaysdk/environment/schema/connectors/microsoft-teams/provenance.json +851 -0
- gatewaysdk/environment/schema/connectors/microsoft-teams/scope.md +231 -0
- gatewaysdk/environment/schema/connectors/microsoft-teams/teams-types.json +1710 -0
- gatewaysdk/environment/schema/connectors/microsoft-teams/world.json +858 -0
- gatewaysdk/environment/schema/connectors/netsuite/handlers.py +32 -0
- gatewaysdk/environment/schema/connectors/netsuite/parity.json +50 -0
- gatewaysdk/environment/schema/connectors/netsuite/provenance.json +137 -0
- gatewaysdk/environment/schema/connectors/netsuite/scope.toml +78 -0
- gatewaysdk/environment/schema/connectors/netsuite/world.json +16243 -0
- gatewaysdk/environment/schema/connectors/salesforce/handlers.py +806 -0
- gatewaysdk/environment/schema/connectors/salesforce/parity.json +46 -0
- gatewaysdk/environment/schema/connectors/salesforce/provenance.json +143 -0
- gatewaysdk/environment/schema/connectors/salesforce/scope.toml +174 -0
- gatewaysdk/environment/schema/connectors/salesforce/world.json +4695 -0
- gatewaysdk/environment/schema/connectors/slack/MODEL.md +236 -0
- gatewaysdk/environment/schema/connectors/slack/capabilities.json +1039 -0
- gatewaysdk/environment/schema/connectors/slack/handlers.py +762 -0
- gatewaysdk/environment/schema/connectors/slack/parity.json +65 -0
- gatewaysdk/environment/schema/connectors/slack/provenance.json +294 -0
- gatewaysdk/environment/schema/connectors/slack/scope.toml +44 -0
- gatewaysdk/environment/schema/connectors/slack/world.json +4993 -0
- gatewaysdk/environment/schema/connectors/workday/handlers.py +75 -0
- gatewaysdk/environment/schema/connectors/workday/parity.json +36 -0
- gatewaysdk/environment/schema/connectors/workday/provenance.json +179 -0
- gatewaysdk/environment/schema/connectors/workday/scope.toml +180 -0
- gatewaysdk/environment/schema/connectors/workday/world.json +806 -0
- gatewaysdk/environment/schema/data.py +593 -0
- gatewaysdk/environment/schema/extract.py +263 -0
- gatewaysdk/environment/schema/host.py +2437 -0
- gatewaysdk/environment/schema/host_surfaces.py +275 -0
- gatewaysdk/environment/schema/platform.py +1272 -0
- gatewaysdk/environment/schema/scaffold.py +250 -0
- gatewaysdk/environment/schema/skill.py +118 -0
- gatewaysdk/environment/schema/skills/agents/connector-template-author.md +202 -0
- gatewaysdk/environment/schema/skills/connector-schema-authoring/CONNECTORS.md +331 -0
- gatewaysdk/environment/schema/skills/connector-schema-authoring/CONVENTIONS.md +100 -0
- gatewaysdk/environment/schema/skills/connector-schema-authoring/SKILL.md +313 -0
- gatewaysdk/environment/schema/skills/world-data-ingestion/ROWS.md +223 -0
- gatewaysdk/environment/schema/skills/world-data-ingestion/SKILL.md +293 -0
- gatewaysdk/environment/schema/skills/worlds-getting-started/SKILL.md +390 -0
- gatewaysdk/environment/schema/slack.py +757 -0
- gatewaysdk/environment/schema/snapshot.py +479 -0
- gatewaysdk/environment/schema/store.py +904 -0
- gatewaysdk/environment/schema/tasks.py +525 -0
- gatewaysdk/environment/schema/tools_world.py +322 -0
- gatewaysdk/environment/schema/validation.py +577 -0
- gatewaysdk/environment/schema/worker.py +78 -0
- gatewaysdk/environment/schema/workers.py +500 -0
- gatewaysdk/environment/schema/world_tests.py +336 -0
- gatewaysdk/environments/__init__.py +24 -0
- gatewaysdk/environments/client.py +486 -0
- gatewaysdk/environments/types.py +318 -0
- gatewaysdk/execution/__init__.py +15 -0
- gatewaysdk/execution/base.py +64 -0
- gatewaysdk/execution/client_server.py +443 -0
- gatewaysdk/execution/events.py +69 -0
- gatewaysdk/execution/inter_process.py +16 -0
- gatewaysdk/execution/shared_memory.py +282 -0
- gatewaysdk/experiments/__init__.py +90 -0
- gatewaysdk/experiments/assignment.py +177 -0
- gatewaysdk/experiments/client.py +877 -0
- gatewaysdk/experiments/exposure.py +222 -0
- gatewaysdk/experiments/types.py +81 -0
- gatewaysdk/importers/__init__.py +49 -0
- gatewaysdk/importers/_normalize.py +91 -0
- gatewaysdk/importers/builder.py +173 -0
- gatewaysdk/importers/client.py +95 -0
- gatewaysdk/importers/langsmith.py +196 -0
- gatewaysdk/importers/recipes.py +249 -0
- gatewaysdk/instrumentation/__init__.py +300 -0
- gatewaysdk/instrumentation/agentops.py +314 -0
- gatewaysdk/instrumentation/agentops_langchain.py +45 -0
- gatewaysdk/instrumentation/base.py +119 -0
- gatewaysdk/instrumentation/litellm.py +83 -0
- gatewaysdk/instrumentation/registry.py +273 -0
- gatewaysdk/instrumentation/vllm.py +81 -0
- gatewaysdk/instrumentation/weave.py +500 -0
- gatewaysdk/integrations/__init__.py +15 -0
- gatewaysdk/integrations/gateway/__init__.py +11 -0
- gatewaysdk/integrations/gateway/client.py +171 -0
- gatewaysdk/integrations/tool_access.py +549 -0
- gatewaysdk/litagent/__init__.py +11 -0
- gatewaysdk/litagent/decorator.py +536 -0
- gatewaysdk/litagent/litagent.py +252 -0
- gatewaysdk/llm_proxy.py +1742 -0
- gatewaysdk/logging.py +370 -0
- gatewaysdk/memory.py +278 -0
- gatewaysdk/personas.py +186 -0
- gatewaysdk/platform/__init__.py +17 -0
- gatewaysdk/platform/builder.py +221 -0
- gatewaysdk/platform/compatibility.py +67 -0
- gatewaysdk/platform/manifest.py +185 -0
- gatewaysdk/platform/orchestrator.py +901 -0
- gatewaysdk/platform/registry.py +122 -0
- gatewaysdk/platform/worker.py +864 -0
- gatewaysdk/replay/__init__.py +1032 -0
- gatewaysdk/replay/pytest.py +56 -0
- gatewaysdk/reward.py +7 -0
- gatewaysdk/run.py +1781 -0
- gatewaysdk/runner/__init__.py +11 -0
- gatewaysdk/runner/agent.py +878 -0
- gatewaysdk/runner/base.py +182 -0
- gatewaysdk/runner/legacy.py +309 -0
- gatewaysdk/security.py +700 -0
- gatewaysdk/semconv.py +170 -0
- gatewaysdk/server.py +399 -0
- gatewaysdk/sessions.py +282 -0
- gatewaysdk/store/__init__.py +45 -0
- gatewaysdk/store/base.py +908 -0
- gatewaysdk/store/client_server.py +2093 -0
- gatewaysdk/store/collection/__init__.py +30 -0
- gatewaysdk/store/collection/base.py +587 -0
- gatewaysdk/store/collection/memory.py +970 -0
- gatewaysdk/store/collection/mongo.py +1412 -0
- gatewaysdk/store/collection_based.py +1823 -0
- gatewaysdk/store/gateway.py +983 -0
- gatewaysdk/store/gateway_listener.py +465 -0
- gatewaysdk/store/listener.py +58 -0
- gatewaysdk/store/memory.py +396 -0
- gatewaysdk/store/mongo.py +165 -0
- gatewaysdk/store/redis_stream.py +517 -0
- gatewaysdk/store/sqlite.py +3 -0
- gatewaysdk/store/threading.py +370 -0
- gatewaysdk/store/utils.py +142 -0
- gatewaysdk/tracer/__init__.py +14 -0
- gatewaysdk/tracer/base.py +286 -0
- gatewaysdk/tracer/dummy.py +106 -0
- gatewaysdk/tracer/otel.py +559 -0
- gatewaysdk/tracing/__init__.py +110 -0
- gatewaysdk/tracing/api.py +808 -0
- gatewaysdk/tracing/attributes.py +9 -0
- gatewaysdk/tracing/context.py +272 -0
- gatewaysdk/tracing/exporters/__init__.py +10 -0
- gatewaysdk/tracing/exporters/gateway.py +228 -0
- gatewaysdk/tracing/identity.py +288 -0
- gatewaysdk/tracing/init.py +620 -0
- gatewaysdk/tracing/instrumentors/__init__.py +15 -0
- gatewaysdk/tracing/instrumentors/claude_agent_sdk.py +766 -0
- gatewaysdk/tracing/instrumentors/instrumentation_principles.md +294 -0
- gatewaysdk/tracing/instrumentors/registry.py +352 -0
- gatewaysdk/tracing/mapping.py +729 -0
- gatewaysdk/tracing/processors.py +393 -0
- gatewaysdk/tracing/push.py +617 -0
- gatewaysdk/tracing/push_models.py +247 -0
- gatewaysdk/tracing/semconv.py +294 -0
- gatewaysdk/tracing/span_builder.py +356 -0
- gatewaysdk/trainer/__init__.py +6 -0
- gatewaysdk/trainer/init_utils.py +263 -0
- gatewaysdk/trainer/legacy.py +359 -0
- gatewaysdk/trainer/registry.py +12 -0
- gatewaysdk/trainer/trainer.py +638 -0
- gatewaysdk/types/__init__.py +63 -0
- gatewaysdk/types/core.py +556 -0
- gatewaysdk/types/resources.py +204 -0
- gatewaysdk/types/tracer.py +515 -0
- gatewaysdk/types/tracing.py +162 -0
- gatewaysdk/users.py +251 -0
- gatewaysdk/utils/__init__.py +1 -0
- gatewaysdk/utils/id.py +18 -0
- gatewaysdk/utils/metrics.py +1025 -0
- gatewaysdk/utils/otel.py +550 -0
- gatewaysdk/utils/otlp.py +556 -0
- gatewaysdk/utils/redact.py +22 -0
- gatewaysdk/utils/server_launcher.py +1045 -0
- gatewaysdk/utils/system_snapshot.py +90 -0
- gatewaysdk/verl/__init__.py +8 -0
- gatewaysdk/verl/__main__.py +6 -0
- gatewaysdk/verl/async_server.py +46 -0
- gatewaysdk/verl/config.yaml +27 -0
- gatewaysdk/verl/daemon.py +1154 -0
- gatewaysdk/verl/dataset.py +44 -0
- gatewaysdk/verl/entrypoint.py +248 -0
- gatewaysdk/verl/trainer.py +549 -0
- gatewaysdk/world_browser.py +748 -0
- gatewaysdk/world_data.py +453 -0
- gatewaysdk/world_sessions.py +978 -0
- gatewaysdk/world_tasks.py +285 -0
- gatewaysdk/world_tools.py +115 -0
- gatewaysdk/worlds.py +639 -0
- gatewaysdk-0.3.2.dist-info/METADATA +236 -0
- gatewaysdk-0.3.2.dist-info/RECORD +376 -0
- gatewaysdk-0.3.2.dist-info/WHEEL +4 -0
- gatewaysdk-0.3.2.dist-info/entry_points.txt +5 -0
- gatewaysdk-0.3.2.dist-info/licenses/LICENSE +19 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""The ``gateway_env`` handler runtime — the module bundle handlers import.
|
|
2
|
+
|
|
3
|
+
Generated (or hand-written) ``mock-tools`` handlers are written against this
|
|
4
|
+
FIXED contract::
|
|
5
|
+
|
|
6
|
+
from gateway_env import tool, db
|
|
7
|
+
|
|
8
|
+
@tool(name="create_refund")
|
|
9
|
+
def handle(order_id, amount):
|
|
10
|
+
order = db.one("SELECT * FROM orders WHERE id = ?", order_id)
|
|
11
|
+
rid = db.insert("refunds", order_id=order_id, amount=amount)
|
|
12
|
+
return {"ok": True, "refund_id": rid}
|
|
13
|
+
|
|
14
|
+
``gateway_env`` is importable ONLY while a bundle's handler modules are being
|
|
15
|
+
loaded — the loader injects this module into ``sys.modules`` under that name
|
|
16
|
+
for the duration of the load and restores it after (never globally installed).
|
|
17
|
+
``db`` operations bind to the ACTIVE world's sqlite connection at call time via
|
|
18
|
+
a contextvar, so the same handler object serves every world/branch.
|
|
19
|
+
|
|
20
|
+
Handlers may also be plain ``def <tool_name>(...)`` functions — the loader
|
|
21
|
+
falls back to discovery by function name == served tool name.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import re
|
|
27
|
+
import sqlite3
|
|
28
|
+
from contextvars import ContextVar
|
|
29
|
+
from typing import Any, Callable, Dict, Optional
|
|
30
|
+
|
|
31
|
+
__all__ = ["tool", "db", "store"]
|
|
32
|
+
|
|
33
|
+
#: The active world's sqlite connection. Set by ``World.execute`` around each
|
|
34
|
+
#: handler invocation; ``db`` reads it at call time.
|
|
35
|
+
_active_connection: ContextVar[Optional[sqlite3.Connection]] = ContextVar(
|
|
36
|
+
"gateway_env_active_connection", default=None
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
#: The registry the loader is currently filling. ``@tool`` registers into it
|
|
40
|
+
#: at module-exec time; outside a bundle load the decorator is a no-op tagger.
|
|
41
|
+
_load_registry: ContextVar[Optional[Dict[str, Callable[..., Any]]]] = ContextVar(
|
|
42
|
+
"gateway_env_load_registry", default=None
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
_active_store: ContextVar[Any] = ContextVar("gateway_env_active_store", default=None)
|
|
46
|
+
_strict_registration: ContextVar[bool] = ContextVar("gateway_env_strict_registration", default=False)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class _Store:
|
|
50
|
+
"""Entity operations bind to the currently executing schema-backed world."""
|
|
51
|
+
|
|
52
|
+
def __getattr__(self, name):
|
|
53
|
+
if name not in {"get", "list", "insert", "update", "delete", "apply_batch", "lineage"}:
|
|
54
|
+
raise AttributeError(name)
|
|
55
|
+
active = _active_store.get()
|
|
56
|
+
if active is None:
|
|
57
|
+
raise RuntimeError("gateway_env.store requires an active schema-backed world")
|
|
58
|
+
return getattr(active, name)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
store = _Store()
|
|
62
|
+
|
|
63
|
+
_IDENTIFIER_RE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _connection() -> sqlite3.Connection:
|
|
67
|
+
conn = _active_connection.get()
|
|
68
|
+
if conn is None:
|
|
69
|
+
raise RuntimeError(
|
|
70
|
+
"gateway_env.db has no active world — db.* is only usable while a "
|
|
71
|
+
"tool handler executes inside a world (world.execute / with env:)."
|
|
72
|
+
)
|
|
73
|
+
return conn
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _identifier(name: str, what: str) -> str:
|
|
77
|
+
if not _IDENTIFIER_RE.match(name):
|
|
78
|
+
raise ValueError(f"invalid {what} name for db.insert: {name!r}")
|
|
79
|
+
return name
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class _Db:
|
|
83
|
+
"""Tiny sqlite facade bound to the active world (rows are ``sqlite3.Row``,
|
|
84
|
+
dict-like: ``row["col"]`` and ``dict(row)`` both work)."""
|
|
85
|
+
|
|
86
|
+
def one(self, sql: str, *params: Any) -> Optional[sqlite3.Row]:
|
|
87
|
+
"""First row of the query, or ``None``."""
|
|
88
|
+
return _connection().execute(sql, params).fetchone()
|
|
89
|
+
|
|
90
|
+
def all(self, sql: str, *params: Any) -> list[sqlite3.Row]:
|
|
91
|
+
"""Every row of the query."""
|
|
92
|
+
return list(_connection().execute(sql, params).fetchall())
|
|
93
|
+
|
|
94
|
+
def insert(self, table: str, **cols: Any) -> int:
|
|
95
|
+
"""INSERT one row, returning its rowid. Table/column names are
|
|
96
|
+
validated as identifiers (values are always bound parameters)."""
|
|
97
|
+
if _active_store.get() is not None:
|
|
98
|
+
from .schema import ContractError
|
|
99
|
+
|
|
100
|
+
raise ContractError("raw_write", "Use gateway_env.store.insert for schema-backed mutations")
|
|
101
|
+
if not cols:
|
|
102
|
+
raise ValueError("db.insert needs at least one column")
|
|
103
|
+
table_sql = _identifier(table, "table")
|
|
104
|
+
col_sql = ", ".join(_identifier(col, "column") for col in cols)
|
|
105
|
+
placeholders = ", ".join("?" for _ in cols)
|
|
106
|
+
cursor = _connection().execute(
|
|
107
|
+
f"INSERT INTO {table_sql} ({col_sql}) VALUES ({placeholders})",
|
|
108
|
+
tuple(cols.values()),
|
|
109
|
+
)
|
|
110
|
+
return int(cursor.lastrowid or 0)
|
|
111
|
+
|
|
112
|
+
def execute(self, sql: str, *params: Any) -> int:
|
|
113
|
+
"""Run any statement (UPDATE/DELETE/DDL…), returning the affected
|
|
114
|
+
rowcount (-1 for non-DML per sqlite3 semantics)."""
|
|
115
|
+
if _active_store.get() is not None:
|
|
116
|
+
from .schema import ContractError
|
|
117
|
+
|
|
118
|
+
raise ContractError("raw_write", "Use gateway_env.store for schema-backed mutations")
|
|
119
|
+
return _connection().execute(sql, params).rowcount
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
db = _Db()
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def tool(fn: Optional[Callable[..., Any]] = None, *, name: Optional[str] = None):
|
|
126
|
+
"""Register a handler for a served tool.
|
|
127
|
+
|
|
128
|
+
Usable bare (``@tool`` — tool name is the function name) or with an
|
|
129
|
+
explicit name (``@tool(name="crm.lookup")`` — required when the tool name
|
|
130
|
+
is not a valid Python identifier). Returns the function unchanged.
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
def register(handler: Callable[..., Any], tool_name: str) -> Callable[..., Any]:
|
|
134
|
+
handler.__gateway_env_tool__ = tool_name # type: ignore[attr-defined]
|
|
135
|
+
registry = _load_registry.get()
|
|
136
|
+
if registry is not None:
|
|
137
|
+
if _strict_registration.get() and tool_name in registry:
|
|
138
|
+
from .schema import ContractError
|
|
139
|
+
|
|
140
|
+
raise ContractError("tool", "Duplicate tool handler registration")
|
|
141
|
+
registry[tool_name] = handler
|
|
142
|
+
return handler
|
|
143
|
+
|
|
144
|
+
if fn is not None and callable(fn):
|
|
145
|
+
return register(fn, fn.__name__)
|
|
146
|
+
|
|
147
|
+
def decorator(handler: Callable[..., Any]) -> Callable[..., Any]:
|
|
148
|
+
return register(handler, name or handler.__name__)
|
|
149
|
+
|
|
150
|
+
return decorator
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Offline executable world contracts: compile, validate, and store state."""
|
|
2
|
+
|
|
3
|
+
from .compiler import (
|
|
4
|
+
Contract,
|
|
5
|
+
bundle_mode,
|
|
6
|
+
check_bundle,
|
|
7
|
+
compile_bundle,
|
|
8
|
+
describe_bundle,
|
|
9
|
+
)
|
|
10
|
+
from .connector import capture as capture_connection
|
|
11
|
+
from .connector import ingest as ingest_captures
|
|
12
|
+
from .connector import load_spec as load_connection
|
|
13
|
+
from .scaffold import init_bundle, list_templates
|
|
14
|
+
from .store import IngestConnection, SQLiteStore
|
|
15
|
+
from .api import build_api_bundle
|
|
16
|
+
from .api import serve as serve_api
|
|
17
|
+
from .validation import ContractError
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"Contract",
|
|
21
|
+
"ContractError",
|
|
22
|
+
"IngestConnection",
|
|
23
|
+
"SQLiteStore",
|
|
24
|
+
"build_api_bundle",
|
|
25
|
+
"bundle_mode",
|
|
26
|
+
"capture_connection",
|
|
27
|
+
"check_bundle",
|
|
28
|
+
"compile_bundle",
|
|
29
|
+
"describe_bundle",
|
|
30
|
+
"ingest_captures",
|
|
31
|
+
"init_bundle",
|
|
32
|
+
"list_templates",
|
|
33
|
+
"load_connection",
|
|
34
|
+
"serve_api",
|
|
35
|
+
]
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"""Lean CLI, dependency-free: python -m gatewaysdk.environment.schema <command> PATH.
|
|
2
|
+
|
|
3
|
+
init | templates | compile | check | describe the world contract
|
|
4
|
+
connector-validate | connector-capture | connector-ingest | conform its vendor connection
|
|
5
|
+
data-show | data-import the rows a local world seeds with
|
|
6
|
+
serve | api-bundle the vendor's API served from the world
|
|
7
|
+
skill the packaged skills, printed or installed
|
|
8
|
+
|
|
9
|
+
Every command is offline and local: it never reads GATEWAY_* keys or reaches a
|
|
10
|
+
host. The platform's sandboxed `run_gateway_cli` runs exactly this module.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import json
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from . import (
|
|
18
|
+
ContractError,
|
|
19
|
+
build_api_bundle,
|
|
20
|
+
capture_connection,
|
|
21
|
+
check_bundle,
|
|
22
|
+
describe_bundle,
|
|
23
|
+
ingest_captures,
|
|
24
|
+
init_bundle,
|
|
25
|
+
list_templates,
|
|
26
|
+
load_connection,
|
|
27
|
+
serve_api,
|
|
28
|
+
)
|
|
29
|
+
from .conform import conform
|
|
30
|
+
from .data import entity_counts, entity_rows, import_rows, parse_rows, world_kind
|
|
31
|
+
from .skill import install_skill, next_step, packaged_skills, skill_text
|
|
32
|
+
|
|
33
|
+
COMMANDS = (
|
|
34
|
+
"init",
|
|
35
|
+
"templates",
|
|
36
|
+
"compile",
|
|
37
|
+
"check",
|
|
38
|
+
"describe",
|
|
39
|
+
"connector-validate",
|
|
40
|
+
"connector-capture",
|
|
41
|
+
"connector-ingest",
|
|
42
|
+
"conform",
|
|
43
|
+
"data-show",
|
|
44
|
+
"data-import",
|
|
45
|
+
"serve",
|
|
46
|
+
"api-bundle",
|
|
47
|
+
"skill",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
NO_BUNDLE = ("templates", "skill")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _pairs(values):
|
|
54
|
+
out = {}
|
|
55
|
+
for item in values or []:
|
|
56
|
+
if "=" not in item:
|
|
57
|
+
raise SystemExit(f"expected name=value, got {item!r}")
|
|
58
|
+
key, value = item.split("=", 1)
|
|
59
|
+
out[key.strip()] = value
|
|
60
|
+
return out
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _installed_connector(value):
|
|
64
|
+
"""This entry point is offline; a workspace connector needs the platform CLI."""
|
|
65
|
+
if value.startswith("workspace:"):
|
|
66
|
+
raise argparse.ArgumentTypeError(
|
|
67
|
+
"workspace connectors live on the platform; use "
|
|
68
|
+
"`gateway worlds schema init PATH --connector workspace:<slug>` with GATEWAY_* keys set"
|
|
69
|
+
)
|
|
70
|
+
return value
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _skill(name, *, list_skills, install, force):
|
|
74
|
+
"""Mirror of ``gateway worlds skill``: list, print, or ``--install DIR`` a packaged skill."""
|
|
75
|
+
if list_skills or name is None:
|
|
76
|
+
print(json.dumps({"status": "ok", "skills": packaged_skills()}, sort_keys=True))
|
|
77
|
+
return
|
|
78
|
+
if install is None:
|
|
79
|
+
print(skill_text(name), end="")
|
|
80
|
+
return
|
|
81
|
+
report = install_skill(install, name=name, force=force)
|
|
82
|
+
out = {
|
|
83
|
+
"status": "rejected" if report.conflicts else "ok",
|
|
84
|
+
"skill": name,
|
|
85
|
+
"written": report.written,
|
|
86
|
+
"unchanged": report.unchanged,
|
|
87
|
+
"conflicts": report.conflicts,
|
|
88
|
+
"next": next_step(name),
|
|
89
|
+
}
|
|
90
|
+
print(json.dumps(out, sort_keys=True))
|
|
91
|
+
if report.conflicts:
|
|
92
|
+
raise SystemExit(1)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def main(argv=None):
|
|
96
|
+
parser = argparse.ArgumentParser(description="Offline Gateway world schema contracts")
|
|
97
|
+
parser.add_argument("command", choices=COMMANDS)
|
|
98
|
+
parser.add_argument("bundle", nargs="?", help="world directory (every command but templates and skill); skill: the skill name")
|
|
99
|
+
parser.add_argument("rows", nargs="*", help="data-import: rows files ({entity: [rows]} JSON, {entity,row} JSONL, or bare rows)")
|
|
100
|
+
parser.add_argument(
|
|
101
|
+
"--connector",
|
|
102
|
+
default="custom",
|
|
103
|
+
type=_installed_connector,
|
|
104
|
+
choices=list_templates(),
|
|
105
|
+
help="init only: connector template to start from (default: custom)",
|
|
106
|
+
)
|
|
107
|
+
parser.add_argument("--name", default=None, help="init only: environment name and package id")
|
|
108
|
+
parser.add_argument("--op", default=None, help="connector-capture: operation name")
|
|
109
|
+
parser.add_argument("--arg", action="append", help="connector-capture: path argument name=value")
|
|
110
|
+
parser.add_argument("--param", action="append", help="connector-capture: query parameter name=value")
|
|
111
|
+
parser.add_argument("--max-pages", type=int, default=None, help="connector-capture: page limit")
|
|
112
|
+
parser.add_argument("--batch-id", default=None, help="connector-ingest | data-import: batch id")
|
|
113
|
+
parser.add_argument("--openapi", action="append", help="conform: the vendor's OpenAPI document; repeatable")
|
|
114
|
+
parser.add_argument("--limit", type=int, default=None, help="conform: check only the first N operations")
|
|
115
|
+
parser.add_argument("--entity", default=None, help="data-show: print this entity's rows; data-import: the entity bare-row files hold")
|
|
116
|
+
parser.add_argument("--mode", default="append", help="data-import: append (upsert by primary key) | replace (named entities)")
|
|
117
|
+
parser.add_argument("--port", type=int, default=8080, help="serve: port")
|
|
118
|
+
parser.add_argument("--api-key", default=None, help="serve: pin the accepted credential")
|
|
119
|
+
parser.add_argument("--scenario", default=None, help="serve: start in one of the world's scenarios/<name>")
|
|
120
|
+
parser.add_argument("--out", default=None, help="api-bundle: empty output directory; conform: write the full report as JSON here")
|
|
121
|
+
parser.add_argument("--list", action="store_true", help="skill: list the packaged skills and exit")
|
|
122
|
+
parser.add_argument("--install", default=None, help="skill: repository to install the skill into, under its .claude/")
|
|
123
|
+
parser.add_argument("--force", action="store_true", help="skill --install: overwrite files whose content differs")
|
|
124
|
+
args = parser.parse_args(argv)
|
|
125
|
+
if args.command == "skill":
|
|
126
|
+
if args.rows:
|
|
127
|
+
parser.error("skill takes at most one positional argument")
|
|
128
|
+
elif args.command in NO_BUNDLE:
|
|
129
|
+
if args.bundle or args.rows:
|
|
130
|
+
parser.error(f"{args.command} takes no positional argument")
|
|
131
|
+
elif not args.bundle:
|
|
132
|
+
parser.error(f"{args.command} needs a world directory")
|
|
133
|
+
elif args.rows and args.command != "data-import":
|
|
134
|
+
parser.error(f"{args.command} takes one positional argument")
|
|
135
|
+
try:
|
|
136
|
+
if args.command == "templates":
|
|
137
|
+
print(json.dumps({"status": "ok", "templates": list_templates()}, sort_keys=True))
|
|
138
|
+
return
|
|
139
|
+
if args.command == "skill":
|
|
140
|
+
_skill(args.bundle, list_skills=args.list, install=args.install, force=args.force)
|
|
141
|
+
return
|
|
142
|
+
if args.command == "describe":
|
|
143
|
+
print(describe_bundle(args.bundle), end="")
|
|
144
|
+
return
|
|
145
|
+
if args.command == "init":
|
|
146
|
+
contract = init_bundle(args.bundle, connector=args.connector, name=args.name)
|
|
147
|
+
elif args.command == "compile":
|
|
148
|
+
from .compiler import compile_world
|
|
149
|
+
|
|
150
|
+
contract, snapshots = compile_world(args.bundle)
|
|
151
|
+
print(json.dumps({"status": "ok", "domain": contract.target, "snapshots": snapshots}, sort_keys=True))
|
|
152
|
+
return
|
|
153
|
+
elif args.command == "check":
|
|
154
|
+
contract = check_bundle(args.bundle)
|
|
155
|
+
elif args.command == "connector-validate":
|
|
156
|
+
spec = load_connection(args.bundle)
|
|
157
|
+
print(
|
|
158
|
+
json.dumps({"status": "ok", "slug": spec.slug, "operations": sorted(spec.operations)}, sort_keys=True)
|
|
159
|
+
)
|
|
160
|
+
return
|
|
161
|
+
elif args.command == "connector-capture":
|
|
162
|
+
if not args.op:
|
|
163
|
+
raise SystemExit("connector-capture needs --op")
|
|
164
|
+
files = capture_connection(
|
|
165
|
+
args.bundle, args.op, _pairs(args.arg), _pairs(args.param), max_pages=args.max_pages
|
|
166
|
+
)
|
|
167
|
+
print(json.dumps({"status": "ok", "files": [str(f) for f in files]}, sort_keys=True))
|
|
168
|
+
return
|
|
169
|
+
elif args.command == "connector-ingest":
|
|
170
|
+
print(json.dumps({"status": "ok", **ingest_captures(args.bundle, batch_id=args.batch_id)}, sort_keys=True))
|
|
171
|
+
return
|
|
172
|
+
elif args.command == "conform":
|
|
173
|
+
if not args.openapi:
|
|
174
|
+
raise SystemExit("conform needs at least one --openapi document")
|
|
175
|
+
report = conform(args.bundle, args.openapi, max_operations=args.limit)
|
|
176
|
+
if args.out:
|
|
177
|
+
Path(args.out).write_text(json.dumps(report.to_json(), indent=2, sort_keys=True) + "\n")
|
|
178
|
+
print(json.dumps({"status": "ok", **report.to_json()}, sort_keys=True))
|
|
179
|
+
summary = report.summary
|
|
180
|
+
if summary["status_mismatch"] or summary["schema_violations"]:
|
|
181
|
+
raise SystemExit(1)
|
|
182
|
+
return
|
|
183
|
+
elif args.command == "data-show":
|
|
184
|
+
out = {"status": "ok", "kind": world_kind(args.bundle)}
|
|
185
|
+
if args.entity is None:
|
|
186
|
+
out["entity_counts"] = entity_counts(args.bundle)
|
|
187
|
+
else:
|
|
188
|
+
out["entity"] = args.entity
|
|
189
|
+
out["rows"] = entity_rows(args.bundle, args.entity)
|
|
190
|
+
print(json.dumps(out, sort_keys=True))
|
|
191
|
+
return
|
|
192
|
+
elif args.command == "data-import":
|
|
193
|
+
if not args.rows:
|
|
194
|
+
raise SystemExit("data-import needs at least one rows file")
|
|
195
|
+
parsed = parse_rows(args.rows, entity=args.entity)
|
|
196
|
+
result = import_rows(args.bundle, parsed, mode=args.mode, batch_id=args.batch_id)
|
|
197
|
+
print(json.dumps({"status": "ok", **result}, sort_keys=True))
|
|
198
|
+
return
|
|
199
|
+
elif args.command == "serve":
|
|
200
|
+
server = serve_api(args.bundle, port=args.port, api_key=args.api_key, scenario=args.scenario)
|
|
201
|
+
try:
|
|
202
|
+
server.serve_forever()
|
|
203
|
+
finally:
|
|
204
|
+
server.server_close()
|
|
205
|
+
server.world_state.close()
|
|
206
|
+
return
|
|
207
|
+
elif args.command == "api-bundle":
|
|
208
|
+
if not args.out:
|
|
209
|
+
raise SystemExit("api-bundle needs --out")
|
|
210
|
+
print(json.dumps({"status": "ok", "bundle": str(build_api_bundle(args.bundle, args.out))}, sort_keys=True))
|
|
211
|
+
return
|
|
212
|
+
print(json.dumps({"status": "ok", "domain": contract.target}, sort_keys=True))
|
|
213
|
+
except ContractError as error:
|
|
214
|
+
print(json.dumps({"status": "rejected", "error": error.detail}, sort_keys=True))
|
|
215
|
+
raise SystemExit(1)
|
|
216
|
+
except KeyError as error:
|
|
217
|
+
print(json.dumps({"status": "rejected", "error": {"message": str(error.args[0])}}, sort_keys=True))
|
|
218
|
+
raise SystemExit(1)
|
|
219
|
+
except (OSError, ValueError) as error:
|
|
220
|
+
print(json.dumps({"status": "rejected", "error": {"message": str(error)}}, sort_keys=True))
|
|
221
|
+
raise SystemExit(1)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
if __name__ == "__main__":
|
|
225
|
+
main()
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Slack capability authoring and version-bound coverage reports.
|
|
2
|
+
|
|
3
|
+
Authoring has exactly two shallow defaults maps. Published entries are expanded,
|
|
4
|
+
so consumers never implement inheritance or infer collection from vendor URLs.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from copy import deepcopy
|
|
8
|
+
import hashlib
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from .validation import encoded, fail, read_json
|
|
12
|
+
|
|
13
|
+
TEMPLATE = Path(__file__).with_name("connectors") / "slack"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def expand_capabilities(document: dict) -> dict:
|
|
17
|
+
"""Expand v2 author metadata to self-contained v1 entries; overrides replace.
|
|
18
|
+
|
|
19
|
+
A list/dictionary override replaces the entire default value. There is no
|
|
20
|
+
recursive merge, multi-level inheritance, or mutation of the authored input.
|
|
21
|
+
Already expanded v1 documents remain usable.
|
|
22
|
+
"""
|
|
23
|
+
result = deepcopy(document)
|
|
24
|
+
if result.get("format") == "gateway-slack-capabilities/1":
|
|
25
|
+
return result
|
|
26
|
+
if result.get("format") != "gateway-slack-capabilities/2":
|
|
27
|
+
fail("slack_capabilities", "Unsupported capability format", "/capabilities/format")
|
|
28
|
+
defaults = result.pop("defaults", {})
|
|
29
|
+
if not isinstance(defaults, dict) or set(defaults) - {"entities", "operations"}:
|
|
30
|
+
fail("slack_capabilities", "Expected entity and operation defaults", "/capabilities/defaults")
|
|
31
|
+
for kind in ("entities", "operations"):
|
|
32
|
+
common = defaults.get(kind, {})
|
|
33
|
+
entries = result.get(kind)
|
|
34
|
+
if not isinstance(common, dict) or not isinstance(entries, dict):
|
|
35
|
+
fail("slack_capabilities", "Expected named capability objects", f"/capabilities/{kind}")
|
|
36
|
+
for name, entry in entries.items():
|
|
37
|
+
if not isinstance(entry, dict):
|
|
38
|
+
fail("slack_capabilities", "Expected a capability object", f"/capabilities/{kind}/{name}")
|
|
39
|
+
entries[name] = {**deepcopy(common), **entry}
|
|
40
|
+
result["format"] = "gateway-slack-capabilities/1"
|
|
41
|
+
return result
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def load_capabilities() -> dict:
|
|
45
|
+
return expand_capabilities(read_json(TEMPLATE / "capabilities.json"))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def slack_template_digest() -> str:
|
|
49
|
+
"""Match the platform's path-NUL-bytes-NUL hash over shipped Slack files."""
|
|
50
|
+
root = TEMPLATE
|
|
51
|
+
digest = hashlib.sha256()
|
|
52
|
+
for path in sorted(root.rglob("*"), key=lambda p: p.relative_to(root).as_posix()):
|
|
53
|
+
if not path.is_file() or path.is_symlink() or "__pycache__" in path.parts:
|
|
54
|
+
continue
|
|
55
|
+
digest.update(path.relative_to(root).as_posix().encode("utf-8"))
|
|
56
|
+
digest.update(b"\0")
|
|
57
|
+
digest.update(path.read_bytes())
|
|
58
|
+
digest.update(b"\0")
|
|
59
|
+
return digest.hexdigest()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def fidelity_report(contract, evidence, batch, diagnostics=None, *, mapping):
|
|
63
|
+
synthetic = evidence.get("synthetic") is True
|
|
64
|
+
capabilities = load_capabilities()
|
|
65
|
+
counts = {entity: 0 for entity in contract.entities}
|
|
66
|
+
for mutation in batch["mutations"]:
|
|
67
|
+
counts[mutation["entity"]] += 1
|
|
68
|
+
return {
|
|
69
|
+
"format": "gateway-slack-fidelity/1",
|
|
70
|
+
"shape": "base",
|
|
71
|
+
"label": "synthetic" if synthetic else "subset",
|
|
72
|
+
"source_hash": hashlib.sha256(encoded(evidence)).hexdigest(),
|
|
73
|
+
"template_digest": slack_template_digest(),
|
|
74
|
+
"contract_target": contract.target,
|
|
75
|
+
"package": contract.lock["package"],
|
|
76
|
+
"lock_digest": hashlib.sha256(encoded(contract.lock)).hexdigest(),
|
|
77
|
+
"mapping": mapping,
|
|
78
|
+
"coverage": evidence.get("coverage", {"complete": False}),
|
|
79
|
+
"capture_policy": {
|
|
80
|
+
"methods": capabilities["capture_methods"],
|
|
81
|
+
"description": (
|
|
82
|
+
"platform_capture describes the hosted connector pipeline, independent of observed counts. "
|
|
83
|
+
"collected means a directly requested entity; derived means an association or embedded object "
|
|
84
|
+
"from projected responses. Both remain bounded by selected scope and available fields. "
|
|
85
|
+
"capture_source is a vendor source reference, not proof the connector calls that method. "
|
|
86
|
+
"observed_mutations counts this import batch; synthetic_fixture_mutations identifies its invented rows."
|
|
87
|
+
),
|
|
88
|
+
},
|
|
89
|
+
"checks": {
|
|
90
|
+
"schema_artifacts": "passed",
|
|
91
|
+
"initial_state": "passed",
|
|
92
|
+
"reference_closure": "passed",
|
|
93
|
+
"live_comparison": "skipped",
|
|
94
|
+
},
|
|
95
|
+
"entities": {
|
|
96
|
+
entity: {
|
|
97
|
+
**capabilities["entities"][entity],
|
|
98
|
+
"observed_mutations": counts[entity],
|
|
99
|
+
"synthetic_fixture_mutations": counts[entity] if synthetic else 0,
|
|
100
|
+
}
|
|
101
|
+
for entity in sorted(contract.entities)
|
|
102
|
+
},
|
|
103
|
+
"live_replay": {
|
|
104
|
+
"status": "skipped",
|
|
105
|
+
"score": None,
|
|
106
|
+
"reason": "No live response comparison performed by this offline mapper.",
|
|
107
|
+
},
|
|
108
|
+
"drift": {
|
|
109
|
+
"status": "reported",
|
|
110
|
+
"unknown_fields": sorted(
|
|
111
|
+
{name for observation in evidence["observations"] for name in observation.get("unknownFields", [])}
|
|
112
|
+
),
|
|
113
|
+
"unmapped_fields": sorted((diagnostics or {}).get("unmapped_fields", [])),
|
|
114
|
+
},
|
|
115
|
+
"limitations": capabilities["limitations"],
|
|
116
|
+
}
|