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,250 @@
|
|
|
1
|
+
"""Initialize a schema world from a connector template or the custom template.
|
|
2
|
+
|
|
3
|
+
Templates are authored ``gateway-world/1`` contracts shipped with the SDK, one
|
|
4
|
+
directory per connector under ``connectors/``. Initializing copies the authored
|
|
5
|
+
files, compiles them, and writes an empty initial batch; the world starts with
|
|
6
|
+
no records and is filled by ingestion or by hand-authored fixture batches.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import shutil
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
from .compiler import Contract, compile_bundle
|
|
16
|
+
from .validation import ContractError, encoded, fail, read_json
|
|
17
|
+
|
|
18
|
+
TEMPLATES = Path(__file__).resolve().parent / "connectors"
|
|
19
|
+
CUSTOM = "custom"
|
|
20
|
+
MANIFEST = """[environment]
|
|
21
|
+
name = "{name}"
|
|
22
|
+
kind = "mock-tools"
|
|
23
|
+
db = "sqlite"
|
|
24
|
+
connector = "{connector}"
|
|
25
|
+
|
|
26
|
+
[schema]
|
|
27
|
+
language = "gateway-world/1"
|
|
28
|
+
|
|
29
|
+
[tools]
|
|
30
|
+
serve = [{serve}]
|
|
31
|
+
|
|
32
|
+
[db]
|
|
33
|
+
engine = "sqlite"
|
|
34
|
+
"""
|
|
35
|
+
VERIFIER = """-- Scores 1.0 once the world holds any {entity} row; edit for real tasks.
|
|
36
|
+
SELECT CASE WHEN COUNT(*) > 0 THEN 1.0 ELSE 0.0 END FROM "{entity}";
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def list_templates() -> list[str]:
|
|
41
|
+
"""Connector slugs that ``init_bundle`` accepts, custom last."""
|
|
42
|
+
slugs = sorted(p.name for p in TEMPLATES.iterdir() if (p / "world.json").is_file())
|
|
43
|
+
return [s for s in slugs if s != CUSTOM] + [CUSTOM]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _slug(value: str, location: str) -> str:
|
|
47
|
+
if not value or any(c not in "abcdefghijklmnopqrstuvwxyz0123456789-_" for c in value):
|
|
48
|
+
fail("identity", "Use lowercase letters, digits, - or _", location)
|
|
49
|
+
return value
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _resource(path: Path) -> Path:
|
|
53
|
+
if path.is_symlink() or path.parent.is_symlink() or not path.is_file():
|
|
54
|
+
fail("template", "Template resources must be regular files, not symlinks", str(path))
|
|
55
|
+
return path
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
SUPPORTING_SUFFIXES = {".json", ".md", ".toml"}
|
|
59
|
+
GENERATED_NAMES = {"base.json", "runtime.json", "lock.json", "README.md", "tool-schemas.json"}
|
|
60
|
+
#: Template files that are not schema artifacts but travel with a workspace connector.
|
|
61
|
+
TEMPLATE_CODE = {"handlers.py", "api/handlers.py"}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def template_digest(files: dict[str, bytes]) -> str:
|
|
65
|
+
"""The same digest the platform computes over an installed template directory:
|
|
66
|
+
sha256 over sorted ``path\0bytes\0``. A workspace connector's commit and an
|
|
67
|
+
installed template with identical files therefore pin identically."""
|
|
68
|
+
import hashlib
|
|
69
|
+
|
|
70
|
+
digest = hashlib.sha256()
|
|
71
|
+
for path in sorted(files):
|
|
72
|
+
digest.update(path.encode("utf-8"))
|
|
73
|
+
digest.update(b"\0")
|
|
74
|
+
digest.update(files[path])
|
|
75
|
+
digest.update(b"\0")
|
|
76
|
+
return digest.hexdigest()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def init_bundle_from_files(
|
|
80
|
+
destination: str | Path, files: dict[str, bytes], *, connector: str, name: str | None = None
|
|
81
|
+
) -> Contract:
|
|
82
|
+
"""Create and compile a schema world from a template held in memory: a workspace
|
|
83
|
+
connector's files (``world.json``, ``connector.toml``, ``provenance.json``,
|
|
84
|
+
``scope.toml``, ``handlers.py``, ``api/handlers.py``, ``scenarios/…``), exactly
|
|
85
|
+
what :func:`init_bundle` reads from an installed template directory.
|
|
86
|
+
|
|
87
|
+
``connector`` names the template for the manifest; ``name`` the world."""
|
|
88
|
+
destination = Path(destination)
|
|
89
|
+
connector = _slug(connector, "/init/connector")
|
|
90
|
+
name = _slug(name if name is not None else f"{connector}-world", "/init/name")
|
|
91
|
+
if destination.exists() and (not destination.is_dir() or any(destination.iterdir())):
|
|
92
|
+
fail("state_exists", "Destination must be a new or empty directory", "/init")
|
|
93
|
+
if "world.json" not in files:
|
|
94
|
+
fail("template", "A connector template needs world.json", "/init/files")
|
|
95
|
+
if not all(isinstance(k, str) and k and not k.startswith("/") and ".." not in k.split("/") for k in files):
|
|
96
|
+
fail("template", "Template paths must be relative and stay inside the template", "/init/files")
|
|
97
|
+
try:
|
|
98
|
+
world = json.loads(files["world.json"].decode("utf-8"))
|
|
99
|
+
except (UnicodeDecodeError, ValueError):
|
|
100
|
+
fail("template", "world.json is not valid JSON", "/init/files/world.json")
|
|
101
|
+
if not isinstance(world, dict) or not isinstance(world.get("x-gateway"), dict):
|
|
102
|
+
fail("template", "world.json is not a gateway-world document", "/init/files/world.json")
|
|
103
|
+
world["x-gateway"]["package"]["id"] = name
|
|
104
|
+
tools = sorted(world["x-gateway"].get("tools", {}))
|
|
105
|
+
try:
|
|
106
|
+
(destination / "schema").mkdir(parents=True)
|
|
107
|
+
(destination / "schema/world.json").write_bytes(_pretty(world))
|
|
108
|
+
shutil.copyfile(_resource(TEMPLATES / "base.json"), destination / "schema/base.json")
|
|
109
|
+
(destination / "tools").mkdir()
|
|
110
|
+
handlers = files.get("handlers.py") or files.get("tools/handlers.py")
|
|
111
|
+
(destination / "tools/handlers.py").write_bytes(handlers if handlers is not None else b"")
|
|
112
|
+
for path, content in sorted(files.items()):
|
|
113
|
+
if path in {"world.json", "handlers.py", "tools/handlers.py"} or path.startswith("__pycache__"):
|
|
114
|
+
continue
|
|
115
|
+
if path == "connector.toml":
|
|
116
|
+
target = destination / "connector.toml"
|
|
117
|
+
elif path.startswith(("api/", "scenarios/")):
|
|
118
|
+
target = destination / path
|
|
119
|
+
elif path.startswith("evidence/") or path.startswith("reports/"):
|
|
120
|
+
continue # authoring evidence stays with the connector, not the world
|
|
121
|
+
elif (
|
|
122
|
+
Path(path).suffix in SUPPORTING_SUFFIXES and Path(path).name not in GENERATED_NAMES and "/" not in path
|
|
123
|
+
):
|
|
124
|
+
target = destination / "schema" / path
|
|
125
|
+
else:
|
|
126
|
+
fail("template", "Unsupported or generated template artifact", f"/init/files/{path}")
|
|
127
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
128
|
+
target.write_bytes(content)
|
|
129
|
+
(destination / "gateway-env.toml").write_text(
|
|
130
|
+
MANIFEST.format(name=name, connector=connector, serve=", ".join(f'"{t}"' for t in tools)),
|
|
131
|
+
encoding="utf-8",
|
|
132
|
+
)
|
|
133
|
+
entities = sorted(world["x-gateway"].get("entities", {}))
|
|
134
|
+
if not entities:
|
|
135
|
+
fail("template", "world.json declares no entities", "/init/files/world.json")
|
|
136
|
+
(destination / "verifiers").mkdir()
|
|
137
|
+
(destination / "verifiers/state_present.sql").write_text(VERIFIER.format(entity=entities[0]), encoding="utf-8")
|
|
138
|
+
contract = compile_bundle(destination)
|
|
139
|
+
(destination / "data").mkdir()
|
|
140
|
+
(destination / "data/records.json").write_bytes(_pretty([]))
|
|
141
|
+
(destination / "data/initial.json").write_bytes(
|
|
142
|
+
encoded(
|
|
143
|
+
{
|
|
144
|
+
"id": f"{name}.initial.v1",
|
|
145
|
+
"target": contract.target,
|
|
146
|
+
"mapping": {"id": "empty", "version": "1"},
|
|
147
|
+
"coverage": "partial",
|
|
148
|
+
"mutations": [],
|
|
149
|
+
}
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
except BaseException:
|
|
153
|
+
shutil.rmtree(destination, ignore_errors=True)
|
|
154
|
+
raise
|
|
155
|
+
return contract
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def init_bundle(destination: str | Path, *, connector: str = CUSTOM, name: str | None = None) -> Contract:
|
|
159
|
+
"""Create and compile a schema world at ``destination`` from a template.
|
|
160
|
+
|
|
161
|
+
The destination must not exist or must be an empty directory. ``name``
|
|
162
|
+
becomes the environment name and package id; the domain ``$id`` stays the
|
|
163
|
+
connector's so worlds built from one connector share a domain identity.
|
|
164
|
+
"""
|
|
165
|
+
destination = Path(destination)
|
|
166
|
+
connector = _slug(connector, "/init/connector")
|
|
167
|
+
if connector not in list_templates():
|
|
168
|
+
fail(
|
|
169
|
+
"template",
|
|
170
|
+
f"Unknown connector template; choose one of {', '.join(list_templates())}",
|
|
171
|
+
"/init/connector",
|
|
172
|
+
)
|
|
173
|
+
name = _slug(name if name is not None else f"{connector}-world", "/init/name")
|
|
174
|
+
if destination.exists() and (not destination.is_dir() or any(destination.iterdir())):
|
|
175
|
+
fail("state_exists", "Destination must be a new or empty directory", "/init")
|
|
176
|
+
template = TEMPLATES / connector
|
|
177
|
+
# Templates may carry sibling schema dependencies and model evidence. Keep
|
|
178
|
+
# every authored artifact in initialized worlds; never silently drop files.
|
|
179
|
+
supporting_files = []
|
|
180
|
+
for path in sorted(template.iterdir()):
|
|
181
|
+
# pip compiles the shipped handler module during installation.
|
|
182
|
+
if path.name == "__pycache__" and path.is_dir() and not path.is_symlink():
|
|
183
|
+
continue
|
|
184
|
+
_resource(path)
|
|
185
|
+
if path.name in {"world.json", "handlers.py"}:
|
|
186
|
+
continue
|
|
187
|
+
if path.suffix not in {".json", ".md", ".toml"} or path.name in {
|
|
188
|
+
"base.json",
|
|
189
|
+
"runtime.json",
|
|
190
|
+
"lock.json",
|
|
191
|
+
"README.md",
|
|
192
|
+
"tool-schemas.json",
|
|
193
|
+
}:
|
|
194
|
+
fail("template", "Unsupported or generated template artifact", str(path))
|
|
195
|
+
supporting_files.append(path)
|
|
196
|
+
world = read_json(_resource(template / "world.json"))
|
|
197
|
+
world["x-gateway"]["package"]["id"] = name
|
|
198
|
+
tools = sorted(world["x-gateway"]["tools"])
|
|
199
|
+
try:
|
|
200
|
+
(destination / "schema").mkdir(parents=True)
|
|
201
|
+
(destination / "schema/world.json").write_bytes(_pretty(world))
|
|
202
|
+
shutil.copyfile(_resource(TEMPLATES / "base.json"), destination / "schema/base.json")
|
|
203
|
+
for path in supporting_files:
|
|
204
|
+
# The connection spec sits at the world root, where `worlds connector` and
|
|
205
|
+
# `worlds serve` look for it; everything else describes the schema.
|
|
206
|
+
target = destination / path.name if path.name == "connector.toml" else destination / "schema" / path.name
|
|
207
|
+
if connector == "slack" and path.name == "capabilities.json":
|
|
208
|
+
from ._slack_fidelity import expand_capabilities
|
|
209
|
+
|
|
210
|
+
target.write_bytes(_pretty(expand_capabilities(read_json(_resource(path)))))
|
|
211
|
+
else:
|
|
212
|
+
shutil.copyfile(_resource(path), target)
|
|
213
|
+
(destination / "tools").mkdir()
|
|
214
|
+
shutil.copyfile(_resource(template / "handlers.py"), destination / "tools/handlers.py")
|
|
215
|
+
(destination / "gateway-env.toml").write_text(
|
|
216
|
+
MANIFEST.format(
|
|
217
|
+
name=name,
|
|
218
|
+
connector=connector,
|
|
219
|
+
serve=", ".join(f'"{t}"' for t in tools),
|
|
220
|
+
),
|
|
221
|
+
encoding="utf-8",
|
|
222
|
+
)
|
|
223
|
+
first_entity = sorted(world["x-gateway"]["entities"])[0]
|
|
224
|
+
(destination / "verifiers").mkdir()
|
|
225
|
+
(destination / "verifiers/state_present.sql").write_text(VERIFIER.format(entity=first_entity), encoding="utf-8")
|
|
226
|
+
contract = compile_bundle(destination)
|
|
227
|
+
(destination / "data").mkdir()
|
|
228
|
+
(destination / "data/records.json").write_bytes(_pretty([]))
|
|
229
|
+
(destination / "data/initial.json").write_bytes(
|
|
230
|
+
encoded(
|
|
231
|
+
{
|
|
232
|
+
"id": f"{name}.initial.v1",
|
|
233
|
+
"target": contract.target,
|
|
234
|
+
"mapping": {"id": "empty", "version": "1"},
|
|
235
|
+
"coverage": "partial",
|
|
236
|
+
"mutations": [],
|
|
237
|
+
}
|
|
238
|
+
)
|
|
239
|
+
)
|
|
240
|
+
except BaseException:
|
|
241
|
+
shutil.rmtree(destination, ignore_errors=True)
|
|
242
|
+
raise
|
|
243
|
+
return contract
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _pretty(value) -> bytes:
|
|
247
|
+
return (json.dumps(value, indent=2) + "\n").encode("utf-8")
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
__all__ = ["CUSTOM", "TEMPLATES", "ContractError", "init_bundle", "list_templates"]
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""The skills shipped with the SDK, so any agent can pick them up.
|
|
2
|
+
|
|
3
|
+
Stdlib only, like the rest of ``environment.schema``: the offline entry point
|
|
4
|
+
(``python -m gatewaysdk.environment.schema skill``) prints and installs them
|
|
5
|
+
from a vendored copy of this subpackage, without the platform client.
|
|
6
|
+
``gatewaysdk.connectors.skill`` re-exports this module.
|
|
7
|
+
|
|
8
|
+
``gateway worlds skill NAME`` prints one; ``--install DIR`` lands it in a
|
|
9
|
+
repository's ``.claude/`` (the skill's files, plus any agent it ships), the
|
|
10
|
+
layout Claude Code, Cursor and Codex read. The files are package data under
|
|
11
|
+
``gatewaysdk/environment/schema/skills/<name>/``; the repository's own copies
|
|
12
|
+
under ``.claude/`` are the source, mirrored there with a "For agents" note on
|
|
13
|
+
top. ``gateway worlds connector skill`` is the connector-authoring skill's
|
|
14
|
+
older spelling and stays.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from dataclasses import dataclass, field
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Dict, List
|
|
22
|
+
|
|
23
|
+
SKILLS = Path(__file__).resolve().parent / "skills"
|
|
24
|
+
SKILL_NAME = "connector-schema-authoring"
|
|
25
|
+
SKILL_FILES = ("SKILL.md", "CONVENTIONS.md", "CONNECTORS.md")
|
|
26
|
+
AGENT_FILE = "connector-template-author.md"
|
|
27
|
+
#: Agents a skill installs beside itself, under ``.claude/agents/``.
|
|
28
|
+
SKILL_AGENTS = {SKILL_NAME: (AGENT_FILE,)}
|
|
29
|
+
NEXT_STEP = "gateway worlds schema init ./<vendor>-world --connector custom"
|
|
30
|
+
NEXT_STEPS = {
|
|
31
|
+
SKILL_NAME: NEXT_STEP,
|
|
32
|
+
"world-data-ingestion": "gateway worlds data import <world> rows.json",
|
|
33
|
+
"worlds-getting-started": "gateway worlds schema init ./my-world --connector custom",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def packaged_skills() -> List[str]:
|
|
38
|
+
"""Every skill the package ships: a directory under ``skills/`` holding a SKILL.md."""
|
|
39
|
+
return sorted(path.parent.name for path in SKILLS.glob("*/SKILL.md"))
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _skill_dir(name: str) -> Path:
|
|
43
|
+
directory = SKILLS / name
|
|
44
|
+
if "/" in name or "\\" in name or not (directory / "SKILL.md").is_file():
|
|
45
|
+
raise KeyError(f"No packaged skill {name!r}; the package ships: {', '.join(packaged_skills())}")
|
|
46
|
+
return directory
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def skill_text(name: str = SKILL_NAME) -> str:
|
|
50
|
+
"""The packaged SKILL.md of ``name``: the checklist an agent follows."""
|
|
51
|
+
return (_skill_dir(name) / "SKILL.md").read_text(encoding="utf-8")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def packaged_files(name: str = SKILL_NAME) -> Dict[str, Path]:
|
|
55
|
+
"""Repository-relative destination → packaged source, for every file the skill installs."""
|
|
56
|
+
directory = _skill_dir(name)
|
|
57
|
+
files = {
|
|
58
|
+
f".claude/skills/{name}/{path.relative_to(directory).as_posix()}": path
|
|
59
|
+
for path in sorted(directory.rglob("*"))
|
|
60
|
+
if path.is_file() and "__pycache__" not in path.parts
|
|
61
|
+
}
|
|
62
|
+
for agent in SKILL_AGENTS.get(name, ()):
|
|
63
|
+
files[f".claude/agents/{agent}"] = SKILLS / "agents" / agent
|
|
64
|
+
return files
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def next_step(name: str = SKILL_NAME) -> str | None:
|
|
68
|
+
"""The command an agent runs once the skill is installed, when the skill has one."""
|
|
69
|
+
return NEXT_STEPS.get(name)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass
|
|
73
|
+
class InstallReport:
|
|
74
|
+
written: List[str] = field(default_factory=list)
|
|
75
|
+
unchanged: List[str] = field(default_factory=list)
|
|
76
|
+
conflicts: List[str] = field(default_factory=list)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def install_skill(destination: str | Path, *, name: str = SKILL_NAME, force: bool = False) -> InstallReport:
|
|
80
|
+
"""Write the skill (and its agents) under ``destination/.claude/``.
|
|
81
|
+
|
|
82
|
+
An existing file with the same content is left alone; one with different
|
|
83
|
+
content is a conflict and nothing is written unless ``force`` — the
|
|
84
|
+
repository's edits are theirs to keep, so the refusal comes before any write.
|
|
85
|
+
"""
|
|
86
|
+
root = Path(destination)
|
|
87
|
+
report = InstallReport()
|
|
88
|
+
planned: Dict[Path, bytes] = {}
|
|
89
|
+
for relative, source in packaged_files(name).items():
|
|
90
|
+
content = source.read_bytes()
|
|
91
|
+
target = root / relative
|
|
92
|
+
if target.exists() and target.read_bytes() == content:
|
|
93
|
+
report.unchanged.append(relative)
|
|
94
|
+
elif target.exists() and not force:
|
|
95
|
+
report.conflicts.append(relative)
|
|
96
|
+
else:
|
|
97
|
+
planned[target] = content
|
|
98
|
+
report.written.append(relative)
|
|
99
|
+
if report.conflicts:
|
|
100
|
+
report.written = []
|
|
101
|
+
return report
|
|
102
|
+
for target, content in planned.items():
|
|
103
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
104
|
+
target.write_bytes(content)
|
|
105
|
+
return report
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
__all__ = [
|
|
109
|
+
"InstallReport",
|
|
110
|
+
"NEXT_STEP",
|
|
111
|
+
"SKILLS",
|
|
112
|
+
"SKILL_NAME",
|
|
113
|
+
"install_skill",
|
|
114
|
+
"next_step",
|
|
115
|
+
"packaged_files",
|
|
116
|
+
"packaged_skills",
|
|
117
|
+
"skill_text",
|
|
118
|
+
]
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: connector-template-author
|
|
3
|
+
model: opus
|
|
4
|
+
description: |
|
|
5
|
+
Implements ONE connector schema template under the unified gateway-world/1
|
|
6
|
+
contract from a brief in .claude/skills/connector-schema-authoring/briefs/.
|
|
7
|
+
Owns exactly one directory (gatewaysdk/environment/schema/connectors/<slug>/)
|
|
8
|
+
plus that connector's rows in the reference tables, and nothing else, so many
|
|
9
|
+
authors run in parallel without overlap. Follows the connector-schema-authoring
|
|
10
|
+
skill checklist and the generation conventions; the conventions test is the
|
|
11
|
+
merge gate.
|
|
12
|
+
|
|
13
|
+
<example>
|
|
14
|
+
Context: Briefs exist for every connector; time to build the templates in parallel.
|
|
15
|
+
user: "Implement the Okta connector template from its brief"
|
|
16
|
+
assistant: "I'll spawn connector-template-author with briefs/okta.md; it owns connectors/okta/ only."
|
|
17
|
+
</example>
|
|
18
|
+
|
|
19
|
+
<example>
|
|
20
|
+
Context: A template exists but was hand-typed before the vendor spec was pinned.
|
|
21
|
+
user: "Re-derive the GitHub template from the published OpenAPI and pin provenance"
|
|
22
|
+
assistant: "I'll spawn connector-template-author with briefs/github.md in re-import mode."
|
|
23
|
+
</example>
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# Connector Template Author
|
|
27
|
+
|
|
28
|
+
## Role Contract
|
|
29
|
+
|
|
30
|
+
You are: A schema author who turns one connector brief into a faithful `gateway-world/1`
|
|
31
|
+
template. The data model is the deliverable. Tools are optional and only what the brief
|
|
32
|
+
asks for.
|
|
33
|
+
|
|
34
|
+
Goal: `gatewaysdk/sdk/src/gatewaysdk/environment/schema/connectors/<slug>/` contains
|
|
35
|
+
`world.json`, `provenance.json`, `scope.toml` (if imported), and `handlers.py` (if the
|
|
36
|
+
brief ships tools), such that `init --connector <slug>` produces a world that compiles,
|
|
37
|
+
checks, runs, and passes `test_committed_templates_follow_the_generation_conventions`
|
|
38
|
+
and the scaffold suite.
|
|
39
|
+
|
|
40
|
+
Constraints:
|
|
41
|
+
- Write ONLY inside your slug's directory, plus the rows the brief names in
|
|
42
|
+
`CONNECTORS.md` (your connector's row in "Status of templates" and your dossier block)
|
|
43
|
+
and your slug's line in the `PREFIXES` table of `test_schema_scaffold.py`.
|
|
44
|
+
- Never touch `base.json`, `scaffold.py`, the compiler, the store, other templates, or
|
|
45
|
+
another connector's rows. If a shared file must change, stop and report it.
|
|
46
|
+
- Never invent vendor facts. Every entity, field, enum, and error comes from the source the
|
|
47
|
+
brief pins; anything you could not confirm is listed under `unverified` in `provenance.json`.
|
|
48
|
+
- Never put vendor or customer data in `data/records.json` or goldens; synthetic only.
|
|
49
|
+
- Keep every scratch file in your OWN subdirectory (`<scratch root>/<slug>/`). Authors run in
|
|
50
|
+
parallel and share one scratch root; generic names like `roundtrip.py` clobber a peer's work.
|
|
51
|
+
- Never bend the model to fit a tool or an MCP surface; report mismatches in the summary.
|
|
52
|
+
|
|
53
|
+
## Work Protocol
|
|
54
|
+
|
|
55
|
+
### Phase 1: Read, then confirm scope
|
|
56
|
+
|
|
57
|
+
1. Read, in order: the brief; `SKILL.md`, `CONVENTIONS.md`, `CONNECTORS.md` in
|
|
58
|
+
`.claude/skills/connector-schema-authoring/`; `documentation/features/world-schema.md`.
|
|
59
|
+
2. Read one existing template of the same shape as a pattern (the brief names it).
|
|
60
|
+
3. Fetch the pinned sources from the brief. Record URL, version, and SHA-256 for
|
|
61
|
+
`provenance.json` before reading them.
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
SCOPE CONFIRMATION:
|
|
65
|
+
- Brief: briefs/<slug>.md
|
|
66
|
+
- Shape: base | mixed | tenant-shaped
|
|
67
|
+
- Prefix: <prefix_> (reserved in PREFIXES)
|
|
68
|
+
- Files I own: connectors/<slug>/*, my rows in CONNECTORS.md, my PREFIXES line
|
|
69
|
+
- Files I will NOT touch: everything else
|
|
70
|
+
- Sources pinned: [url, version, sha256] ...
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Phase 2: Model
|
|
74
|
+
|
|
75
|
+
Build `world.json` entity by entity from the pinned source, in the brief's order:
|
|
76
|
+
|
|
77
|
+
- primary key = the vendor's id; composite keys in containment order
|
|
78
|
+
- relationships on the child, `on_delete: restrict`; membership as its own entity
|
|
79
|
+
- vendor casing on field names; `base.json` primitives by `$ref`
|
|
80
|
+
- nullable vs optional exactly as the vendor documents; enums verbatim, vendor order
|
|
81
|
+
- the error table from the brief's error format
|
|
82
|
+
- for tenant-shaped connectors, the skeleton only: standard objects, and a note in
|
|
83
|
+
`provenance.json` that describe-on-bind is required
|
|
84
|
+
|
|
85
|
+
Write `scope.toml` (imported models) with the allowlist, key overrides, relationship
|
|
86
|
+
hints, `polymorphic`, and the reason for every exclusion.
|
|
87
|
+
|
|
88
|
+
### Phase 2c: Connection and served API (`connector.toml`)
|
|
89
|
+
|
|
90
|
+
When the brief names a vendor API (base URL, auth scheme, operations the agent calls),
|
|
91
|
+
ship `connector.toml` in the template directory. `init` copies it to the world root, where
|
|
92
|
+
`gateway worlds connector capture|ingest`, `gateway worlds serve` and `gateway bench push` read it.
|
|
93
|
+
The format is documented in `SKILL.md` under "Custom connections" and "Serving the vendor's API":
|
|
94
|
+
|
|
95
|
+
- `[connector]` slug and `base_url`; `[auth]` scheme (`header|bearer|basic|query|oauth2|none`),
|
|
96
|
+
`name`, and `secret_env` naming the environment variable, never a value.
|
|
97
|
+
- `[capture]` pacing (`requests_per_minute` low; providers ask us to be sparing), cursor
|
|
98
|
+
pagination when the vendor has it (`cursor_field` in the body or `cursor_header`);
|
|
99
|
+
`[redact]` `hash`/`drop` for every PII field the vendor documents returning, `round` for
|
|
100
|
+
coordinates. Field names keep the vendor's casing.
|
|
101
|
+
- Every operation the vendor's client writes with is a write here: `[operations.api] action`
|
|
102
|
+
`create`/`update`/`delete` with `body`/`defaults`/`generate`, and `action = "handler"` for
|
|
103
|
+
anything computed or stateful (executes, status polls, summaries) in the world's
|
|
104
|
+
`api/handlers.py`. A read-only world is not 1:1; declare `status`, `single`, `envelope`
|
|
105
|
+
and `page` the way the vendor answers.
|
|
106
|
+
- When a vendor OpenAPI exists, `gateway worlds connector conform <world> --openapi <doc>` is the
|
|
107
|
+
definition of done: every documented operation answers the documented status with a body the
|
|
108
|
+
vendor's schema accepts. Seed every entity a by-id route reads; make every create accept the
|
|
109
|
+
minimal body the vendor's request schema requires. Report the summary line.
|
|
110
|
+
- `[[operations]]` for exactly the operations the brief lists as agent-facing: `name`
|
|
111
|
+
(the vendor's operationId where it has one), `method`, `path` with `{args}`, `params`,
|
|
112
|
+
`entity`, and `results` (the dotted path to the row array in the vendor envelope).
|
|
113
|
+
- `[api]` `envelope` matching the vendor's list envelope, and `unauthorized`/`not_found`
|
|
114
|
+
as the vendor's documented error bodies (JSON strings); `[operations.api] filter` mapping
|
|
115
|
+
each path argument to the row field it selects on.
|
|
116
|
+
|
|
117
|
+
Then prove it: `gateway worlds connector validate` on an initialized world, and
|
|
118
|
+
`gateway worlds serve` answering one route from synthetic rows you inserted during
|
|
119
|
+
verification (curl it; check the envelope and the 401 body). Never call the live vendor.
|
|
120
|
+
|
|
121
|
+
### Phase 3: Tools (only if the brief lists them)
|
|
122
|
+
|
|
123
|
+
Generate the default set the brief names (`list_<entities>`, `get_<entity>`, one write)
|
|
124
|
+
with handlers on `gateway_env.store`; raise the vendor's error string where the brief lists
|
|
125
|
+
one. If the brief says "no tools", `x-gateway.tools` is `{}` and there is no `handlers.py`.
|
|
126
|
+
|
|
127
|
+
### Phase 4: Data and verify loop
|
|
128
|
+
|
|
129
|
+
1. Build a handful of synthetic rows per entity, enough to exercise every relationship
|
|
130
|
+
(child-first ordering is fine; the store defers reference checks). A template cannot
|
|
131
|
+
ship `data/records.json` today, so insert them through `store` during verification and
|
|
132
|
+
record the coverage in `provenance.json` rather than committing a fixture file.
|
|
133
|
+
2. In a temp directory: `gateway worlds schema init <tmp> --connector <slug>` then
|
|
134
|
+
`compile`, `check`; `init_from_path`, branch, list every entity, run every tool.
|
|
135
|
+
3. `pytest tests/environment/test_schema_scaffold.py -q` and then the full
|
|
136
|
+
`tests/environment` suite. Iterate until green. Max 3 fix rounds per failure class;
|
|
137
|
+
then document.
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
ITERATION LOG:
|
|
141
|
+
Round 1: [change] → [result]
|
|
142
|
+
Round 2: ...
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Phase 5: Reference rows and provenance
|
|
146
|
+
|
|
147
|
+
- Add or update your row in `CONNECTORS.md` "Status of templates" and your dossier block
|
|
148
|
+
if the brief changed a fact.
|
|
149
|
+
- `provenance.json`: `shape`, `source` (`kind`, `url`, `version`, `sha256`),
|
|
150
|
+
`importer` or `authored_by`, `scope_hash`, `generated_at`, `unverified: []`.
|
|
151
|
+
|
|
152
|
+
### Phase 6: Self-check
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
SELF-CHECK BEFORE FINALIZING:
|
|
156
|
+
|
|
157
|
+
SCOPE:
|
|
158
|
+
[ ] Only my directory, my CONNECTORS.md rows, my PREFIXES line changed
|
|
159
|
+
[ ] No shared file changed (base.json, scaffold, compiler, store, other templates)
|
|
160
|
+
|
|
161
|
+
FIDELITY:
|
|
162
|
+
[ ] Every entity, field, enum, and error traces to a pinned source or is listed unverified
|
|
163
|
+
[ ] Keys, relationships, nullability follow the vendor, not my preference
|
|
164
|
+
[ ] Tenant-shaped: skeleton only, describe-on-bind noted
|
|
165
|
+
[ ] No vendor or customer data anywhere
|
|
166
|
+
|
|
167
|
+
CONVENTIONS:
|
|
168
|
+
[ ] $id, package id, prefix, plural names, verb_noun tools, closed inputs, layout
|
|
169
|
+
[ ] test_committed_templates_follow_the_generation_conventions passes
|
|
170
|
+
[ ] Full tests/environment suite passes
|
|
171
|
+
|
|
172
|
+
REPORT:
|
|
173
|
+
[ ] Summary lists: entities, tools, unverified items, mismatches with any MCP surface,
|
|
174
|
+
anything that needs a shared-file change (not done, reported)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Output
|
|
178
|
+
|
|
179
|
+
A single summary in this shape, nothing else:
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
CONNECTOR: <slug> SHAPE: <shape> PREFIX: <prefix_>
|
|
183
|
+
FILES: connectors/<slug>/{world.json, provenance.json[, scope.toml][, handlers.py][, connector.toml]}
|
|
184
|
+
ENTITIES: name (key) [→ relationships] ...
|
|
185
|
+
TOOLS: none | list ...
|
|
186
|
+
CONNECTION: none | <n> operations, auth <scheme>, served <route> -> <status> during verification
|
|
187
|
+
SOURCES: url@version sha256 ...
|
|
188
|
+
UNVERIFIED: ...
|
|
189
|
+
TESTS: scaffold N passed; environment N passed
|
|
190
|
+
NEEDS ORCHESTRATOR: shared-file changes or conflicts, or "none"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Red Lines
|
|
194
|
+
|
|
195
|
+
1. **One directory.** Writing outside your slug's directory and your named rows breaks
|
|
196
|
+
parallel safety; stop and report instead.
|
|
197
|
+
2. **No invented vendor facts.** Unconfirmed becomes `unverified`, never a guess.
|
|
198
|
+
3. **No vendor or customer data** in the template.
|
|
199
|
+
4. **Never edit generated artifacts** (`db/schema.sql`, `runtime.json`, `README.md`,
|
|
200
|
+
`tool-schemas.json`, `lock.json`); they come from `compile`.
|
|
201
|
+
5. **Never bend the model** to satisfy a tool, a surface, or a test; report the mismatch.
|
|
202
|
+
6. **Never skip the test loop** or finish with a red conventions test.
|