world-model-optimizer 0.2.0__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.
- llm_waterfall/LICENSE +21 -0
- llm_waterfall/__init__.py +53 -0
- llm_waterfall/adapters/__init__.py +36 -0
- llm_waterfall/adapters/anthropic.py +105 -0
- llm_waterfall/adapters/aws_mantle.py +47 -0
- llm_waterfall/adapters/azure_openai.py +71 -0
- llm_waterfall/adapters/base.py +51 -0
- llm_waterfall/adapters/bedrock.py +309 -0
- llm_waterfall/adapters/openai.py +130 -0
- llm_waterfall/classify.py +184 -0
- llm_waterfall/pricing.py +110 -0
- llm_waterfall/py.typed +0 -0
- llm_waterfall/types.py +295 -0
- llm_waterfall/waterfall.py +255 -0
- wmo/__init__.py +38 -0
- wmo/agents/__init__.py +7 -0
- wmo/agents/default.py +29 -0
- wmo/agents/meta.py +55 -0
- wmo/agents/optimizer.py +55 -0
- wmo/agents/project.py +928 -0
- wmo/cli/__init__.py +5 -0
- wmo/cli/agent_session.py +1123 -0
- wmo/cli/app.py +2489 -0
- wmo/cli/e2b_cmds.py +212 -0
- wmo/cli/eval_closed_loop.py +207 -0
- wmo/cli/harness_app.py +1147 -0
- wmo/cli/harness_distill.py +659 -0
- wmo/cli/hosted_session.py +880 -0
- wmo/cli/ingest_cmd.py +165 -0
- wmo/cli/model_roles.py +82 -0
- wmo/cli/platform_cmds.py +372 -0
- wmo/cli/route_app.py +274 -0
- wmo/cli/session_state.py +243 -0
- wmo/cli/ui.py +1107 -0
- wmo/cli/workspace_sync.py +504 -0
- wmo/config/__init__.py +60 -0
- wmo/config/card.py +129 -0
- wmo/config/config.py +367 -0
- wmo/config/dotenv.py +67 -0
- wmo/config/settings.py +128 -0
- wmo/config/store.py +177 -0
- wmo/conftest.py +19 -0
- wmo/connect/__init__.py +88 -0
- wmo/connect/apps.py +78 -0
- wmo/connect/brave.py +284 -0
- wmo/connect/connector.py +79 -0
- wmo/connect/credentials.py +164 -0
- wmo/connect/github.py +321 -0
- wmo/connect/google.py +627 -0
- wmo/connect/notion.py +790 -0
- wmo/connect/oauth.py +461 -0
- wmo/connect/slack.py +555 -0
- wmo/connect/store.py +199 -0
- wmo/connect/types.py +156 -0
- wmo/core/__init__.py +21 -0
- wmo/core/parsing.py +281 -0
- wmo/core/render.py +271 -0
- wmo/core/text.py +40 -0
- wmo/core/types.py +116 -0
- wmo/distill/__init__.py +14 -0
- wmo/distill/agents.py +140 -0
- wmo/distill/config.py +1006 -0
- wmo/distill/cost.py +437 -0
- wmo/distill/data.py +921 -0
- wmo/distill/deadlines.py +254 -0
- wmo/distill/fake_tinker.py +734 -0
- wmo/distill/gate.py +122 -0
- wmo/distill/loop.py +3499 -0
- wmo/distill/renderers.py +399 -0
- wmo/distill/rendering.py +620 -0
- wmo/distill/rollouts.py +726 -0
- wmo/distill/samples.py +195 -0
- wmo/distill/store.py +829 -0
- wmo/distill/teacher.py +714 -0
- wmo/distill/tokens.py +535 -0
- wmo/distill/tracking.py +552 -0
- wmo/distill/tripwire.py +411 -0
- wmo/distill/xtoken/byte_offsets.py +152 -0
- wmo/distill/xtoken/chunks.py +457 -0
- wmo/distill/xtoken/prompt_logprobs.py +475 -0
- wmo/distill/xtoken/teacher_render.py +346 -0
- wmo/engine/__init__.py +28 -0
- wmo/engine/autoconfig.py +367 -0
- wmo/engine/build.py +346 -0
- wmo/engine/demo.py +77 -0
- wmo/engine/eval_suites.py +245 -0
- wmo/engine/grounding.py +491 -0
- wmo/engine/knowledge.py +291 -0
- wmo/engine/loader.py +36 -0
- wmo/engine/play.py +92 -0
- wmo/engine/prompts.py +99 -0
- wmo/engine/replay.py +443 -0
- wmo/engine/reporting.py +58 -0
- wmo/engine/workspace.py +468 -0
- wmo/engine/world_model.py +568 -0
- wmo/env/__init__.py +22 -0
- wmo/env/base.py +121 -0
- wmo/env/closed_loop.py +229 -0
- wmo/env/episode.py +107 -0
- wmo/env/llm_agent.py +93 -0
- wmo/env/scenarios.py +73 -0
- wmo/evals/__init__.py +52 -0
- wmo/evals/agreement.py +110 -0
- wmo/evals/base.py +45 -0
- wmo/evals/closed_loop.py +480 -0
- wmo/evals/failover.py +96 -0
- wmo/evals/gold.py +127 -0
- wmo/evals/grid.py +394 -0
- wmo/evals/grid_plot.py +205 -0
- wmo/evals/harbor/__init__.py +27 -0
- wmo/evals/harbor/agent.py +573 -0
- wmo/evals/harbor/ctrf.py +171 -0
- wmo/evals/harbor/e2b_environment.py +587 -0
- wmo/evals/harbor/e2b_template_policy.py +144 -0
- wmo/evals/harbor/scorer.py +875 -0
- wmo/evals/harbor/tasks.py +140 -0
- wmo/evals/open_loop.py +194 -0
- wmo/evals/tasks.py +53 -0
- wmo/harness/__init__.py +51 -0
- wmo/harness/code_runtime.py +288 -0
- wmo/harness/create.py +1191 -0
- wmo/harness/delta.py +220 -0
- wmo/harness/doc.py +556 -0
- wmo/harness/e2b_ledger.py +342 -0
- wmo/harness/e2b_reap.py +476 -0
- wmo/harness/e2b_sandbox.py +350 -0
- wmo/harness/environment.py +35 -0
- wmo/harness/live_session.py +543 -0
- wmo/harness/mutate.py +343 -0
- wmo/harness/pi_e2b.py +1710 -0
- wmo/harness/pi_entry/entry.ts +268 -0
- wmo/harness/pi_entry/runner_frames.ts +92 -0
- wmo/harness/pi_entry/runner_live.ts +587 -0
- wmo/harness/pi_entry/runner_service.ts +270 -0
- wmo/harness/pi_entry/runner_stdio.ts +374 -0
- wmo/harness/pi_entry/runner_termination.ts +142 -0
- wmo/harness/pi_local.py +262 -0
- wmo/harness/pi_runtime.py +495 -0
- wmo/harness/pi_vendor.py +65 -0
- wmo/harness/population.py +509 -0
- wmo/harness/project_proposer.py +569 -0
- wmo/harness/proposer.py +977 -0
- wmo/harness/runner_link.py +619 -0
- wmo/harness/runtime.py +389 -0
- wmo/harness/scoring.py +247 -0
- wmo/harness/skills.py +116 -0
- wmo/harness/source_tree.py +319 -0
- wmo/harness/store.py +176 -0
- wmo/harness/tools.py +105 -0
- wmo/harness/vendor/manifest.sha256 +58 -0
- wmo/harness/vendor/pi-agent/CHANGELOG.md +556 -0
- wmo/harness/vendor/pi-agent/LICENSE +21 -0
- wmo/harness/vendor/pi-agent/README.md +488 -0
- wmo/harness/vendor/pi-agent/VENDOR.md +39 -0
- wmo/harness/vendor/pi-agent/docs/agent-harness.md +486 -0
- wmo/harness/vendor/pi-agent/docs/durable-harness.md +212 -0
- wmo/harness/vendor/pi-agent/docs/hooks.md +445 -0
- wmo/harness/vendor/pi-agent/docs/models.md +966 -0
- wmo/harness/vendor/pi-agent/docs/observability.md +376 -0
- wmo/harness/vendor/pi-agent/package.json +60 -0
- wmo/harness/vendor/pi-agent/src/agent-loop.ts +748 -0
- wmo/harness/vendor/pi-agent/src/agent.ts +575 -0
- wmo/harness/vendor/pi-agent/src/harness/agent-harness.ts +1029 -0
- wmo/harness/vendor/pi-agent/src/harness/compaction/branch-summarization.ts +261 -0
- wmo/harness/vendor/pi-agent/src/harness/compaction/compaction.ts +747 -0
- wmo/harness/vendor/pi-agent/src/harness/compaction/utils.ts +144 -0
- wmo/harness/vendor/pi-agent/src/harness/env/nodejs.ts +550 -0
- wmo/harness/vendor/pi-agent/src/harness/messages.ts +164 -0
- wmo/harness/vendor/pi-agent/src/harness/prompt-templates.ts +267 -0
- wmo/harness/vendor/pi-agent/src/harness/session/jsonl-repo.ts +177 -0
- wmo/harness/vendor/pi-agent/src/harness/session/jsonl-storage.ts +293 -0
- wmo/harness/vendor/pi-agent/src/harness/session/memory-repo.ts +50 -0
- wmo/harness/vendor/pi-agent/src/harness/session/memory-storage.ts +131 -0
- wmo/harness/vendor/pi-agent/src/harness/session/repo-utils.ts +51 -0
- wmo/harness/vendor/pi-agent/src/harness/session/session.ts +267 -0
- wmo/harness/vendor/pi-agent/src/harness/session/uuid.ts +54 -0
- wmo/harness/vendor/pi-agent/src/harness/skills.ts +375 -0
- wmo/harness/vendor/pi-agent/src/harness/system-prompt.ts +34 -0
- wmo/harness/vendor/pi-agent/src/harness/types.ts +836 -0
- wmo/harness/vendor/pi-agent/src/harness/utils/shell-output.ts +135 -0
- wmo/harness/vendor/pi-agent/src/harness/utils/truncate.ts +344 -0
- wmo/harness/vendor/pi-agent/src/index.ts +44 -0
- wmo/harness/vendor/pi-agent/src/node.ts +2 -0
- wmo/harness/vendor/pi-agent/src/proxy.ts +367 -0
- wmo/harness/vendor/pi-agent/src/types.ts +428 -0
- wmo/harness/vendor/pi-agent/test/agent-loop.test.ts +1351 -0
- wmo/harness/vendor/pi-agent/test/agent.test.ts +699 -0
- wmo/harness/vendor/pi-agent/test/e2e.test.ts +404 -0
- wmo/harness/vendor/pi-agent/test/harness/agent-harness-stream.test.ts +213 -0
- wmo/harness/vendor/pi-agent/test/harness/agent-harness.test.ts +608 -0
- wmo/harness/vendor/pi-agent/test/harness/compaction.test.ts +655 -0
- wmo/harness/vendor/pi-agent/test/harness/nodejs-env.test.ts +321 -0
- wmo/harness/vendor/pi-agent/test/harness/prompt-templates.test.ts +90 -0
- wmo/harness/vendor/pi-agent/test/harness/repo.test.ts +68 -0
- wmo/harness/vendor/pi-agent/test/harness/resource-formatting.test.ts +24 -0
- wmo/harness/vendor/pi-agent/test/harness/session-test-utils.ts +55 -0
- wmo/harness/vendor/pi-agent/test/harness/session-uuid.test.ts +50 -0
- wmo/harness/vendor/pi-agent/test/harness/session.test.ts +156 -0
- wmo/harness/vendor/pi-agent/test/harness/skills.test.ts +116 -0
- wmo/harness/vendor/pi-agent/test/harness/storage.test.ts +299 -0
- wmo/harness/vendor/pi-agent/test/harness/system-prompt.test.ts +66 -0
- wmo/harness/vendor/pi-agent/test/harness/truncate.test.ts +169 -0
- wmo/harness/vendor/pi-agent/test/scratch/simple.ts +72 -0
- wmo/harness/vendor/pi-agent/test/utils/calculate.ts +32 -0
- wmo/harness/vendor/pi-agent/test/utils/get-current-time.ts +46 -0
- wmo/harness/vendor/pi-agent/tsconfig.build.json +13 -0
- wmo/harness/vendor/pi-agent/vitest.config.ts +19 -0
- wmo/harness/vendor/pi-agent/vitest.harness.config.ts +28 -0
- wmo/harness/vendor/vendor_pi.sh +59 -0
- wmo/harness/workspace_patch.py +270 -0
- wmo/ingest/__init__.py +47 -0
- wmo/ingest/adapter.py +72 -0
- wmo/ingest/base.py +114 -0
- wmo/ingest/braintrust.py +339 -0
- wmo/ingest/detect.py +126 -0
- wmo/ingest/langfuse.py +291 -0
- wmo/ingest/langsmith.py +444 -0
- wmo/ingest/mastra.py +330 -0
- wmo/ingest/messages.py +170 -0
- wmo/ingest/normalize.py +679 -0
- wmo/ingest/otel_genai.py +69 -0
- wmo/ingest/otel_writer.py +100 -0
- wmo/ingest/phoenix.py +150 -0
- wmo/ingest/postgres.py +246 -0
- wmo/ingest/posthog.py +320 -0
- wmo/ingest/quality.py +28 -0
- wmo/ingest/stream.py +209 -0
- wmo/ingest/testdata/sample_otlp.json +60 -0
- wmo/ingest/testdata/sample_spans.jsonl +3 -0
- wmo/optimize/__init__.py +25 -0
- wmo/optimize/base.py +143 -0
- wmo/optimize/gepa.py +806 -0
- wmo/optimize/judge.py +262 -0
- wmo/optimize/judge_quality.py +359 -0
- wmo/optimize/knn.py +468 -0
- wmo/optimize/numeric.py +152 -0
- wmo/optimize/outcomes.py +103 -0
- wmo/optimize/policy.py +669 -0
- wmo/optimize/report.py +231 -0
- wmo/optimize/reward.py +129 -0
- wmo/optimize/routing.py +373 -0
- wmo/platform/__init__.py +6 -0
- wmo/platform/auth.py +115 -0
- wmo/platform/client.py +551 -0
- wmo/platform/credentials.py +126 -0
- wmo/platform/transfer.py +158 -0
- wmo/providers/__init__.py +40 -0
- wmo/providers/_bedrock_chat.py +155 -0
- wmo/providers/_openai_common.py +182 -0
- wmo/providers/_responses_common.py +472 -0
- wmo/providers/anthropic.py +134 -0
- wmo/providers/azure_openai.py +296 -0
- wmo/providers/base.py +300 -0
- wmo/providers/bedrock.py +312 -0
- wmo/providers/models.py +205 -0
- wmo/providers/openai.py +143 -0
- wmo/providers/openai_responses.py +240 -0
- wmo/providers/pool.py +170 -0
- wmo/providers/registry.py +73 -0
- wmo/providers/retry.py +151 -0
- wmo/providers/tinker.py +936 -0
- wmo/providers/waterfall.py +336 -0
- wmo/research/__init__.py +81 -0
- wmo/research/ablation.py +133 -0
- wmo/research/concurrency_plot.py +523 -0
- wmo/research/concurrency_run.py +240 -0
- wmo/research/concurrency_scaling.py +270 -0
- wmo/research/gepa_scaling.py +274 -0
- wmo/research/pipeline.py +198 -0
- wmo/research/scaling_split.py +82 -0
- wmo/research/scenario_fidelity.py +198 -0
- wmo/research/scenario_recovery.py +92 -0
- wmo/research/seed_stability.py +90 -0
- wmo/research/trace_scaling.py +348 -0
- wmo/retrieval/__init__.py +6 -0
- wmo/retrieval/embedders.py +105 -0
- wmo/retrieval/leakfree.py +52 -0
- wmo/retrieval/retriever.py +173 -0
- wmo/scenarios/__init__.py +58 -0
- wmo/scenarios/builder.py +152 -0
- wmo/scenarios/mining/__init__.py +27 -0
- wmo/scenarios/mining/clustering.py +171 -0
- wmo/scenarios/mining/facets.py +226 -0
- wmo/scenarios/mining/selection.py +220 -0
- wmo/scenarios/synthesis/__init__.py +6 -0
- wmo/scenarios/synthesis/scenario_set.py +63 -0
- wmo/scenarios/synthesis/synthesizer.py +85 -0
- wmo/scenarios/verification/__init__.py +17 -0
- wmo/scenarios/verification/judge.py +97 -0
- wmo/scenarios/verification/verify.py +135 -0
- wmo/serving/__init__.py +5 -0
- wmo/serving/builds.py +451 -0
- wmo/serving/chat.py +878 -0
- wmo/serving/endpoint_config.py +64 -0
- wmo/serving/savings.py +250 -0
- wmo/serving/server.py +553 -0
- wmo/serving/traces_source.py +206 -0
- wmo/telemetry.py +213 -0
- wmo/tracking/__init__.py +36 -0
- wmo/tracking/clock.py +24 -0
- wmo/tracking/metered.py +125 -0
- wmo/tracking/pricing.py +99 -0
- wmo/tracking/store.py +31 -0
- wmo/tracking/tracker.py +149 -0
- world_model_optimizer-0.2.0.dist-info/METADATA +203 -0
- world_model_optimizer-0.2.0.dist-info/RECORD +308 -0
- world_model_optimizer-0.2.0.dist-info/WHEEL +4 -0
- world_model_optimizer-0.2.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""Stable identity for WMO-built Harbor E2B task templates.
|
|
2
|
+
|
|
3
|
+
The template alias replaces harbor's content-only name with a resource-complete identity:
|
|
4
|
+
harbor's native naming has no resource qualification, so two tasks sharing environment content
|
|
5
|
+
but differing in cpu/memory would collide on one alias. The digest input is FROZEN: a fleet of
|
|
6
|
+
templates already exists on the E2B account under this exact derivation, and byte-identical
|
|
7
|
+
naming is what lets a new run reuse them instead of re-paying every build.
|
|
8
|
+
|
|
9
|
+
Everything here imports harbor but never the e2b SDK at module scope, so the scorer can import
|
|
10
|
+
the environment routing constant on a docker-only install (`wmo[harbor]` without `e2b`).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import hashlib
|
|
16
|
+
import json
|
|
17
|
+
import re
|
|
18
|
+
from dataclasses import dataclass
|
|
19
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
20
|
+
from typing import Literal
|
|
21
|
+
|
|
22
|
+
import harbor
|
|
23
|
+
from harbor.environments.definition import SNAPSHOT_HASH_LEN
|
|
24
|
+
|
|
25
|
+
# Version marker inside the frozen digest payload. Bumping it renames every derived alias and
|
|
26
|
+
# orphans all existing prebuilt templates; do not change it without that intent.
|
|
27
|
+
E2B_TEMPLATE_POLICY_VERSION = "1"
|
|
28
|
+
# At most this many template builds run concurrently (the E2B account limit is 20; half leaves
|
|
29
|
+
# headroom for sandbox operations and other processes).
|
|
30
|
+
E2B_TEMPLATE_BUILD_CONCURRENCY = 10
|
|
31
|
+
E2B_TEMPLATE_BUILD_STATUS_POLL_INTERVAL_MS = 1_000
|
|
32
|
+
# Fixed backoff for retrying the idempotent build-status GET only (never the submission).
|
|
33
|
+
E2B_TEMPLATE_BUILD_STATUS_RETRY_DELAYS_MS = (250, 500, 1_000, 2_000, 4_000)
|
|
34
|
+
E2B_DEFAULT_CPU_COUNT = 2
|
|
35
|
+
E2B_DEFAULT_MEMORY_MB = 1024
|
|
36
|
+
WMO_HARBOR_E2B_ENVIRONMENT_IMPORT_PATH = "wmo.evals.harbor.e2b_environment:WmoE2BEnvironment"
|
|
37
|
+
_HARBOR_ENVIRONMENT_ID_PATTERN = re.compile(r"^[0-9a-f]{32}$")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass(frozen=True)
|
|
41
|
+
class E2BTemplateResources:
|
|
42
|
+
"""Normalized resources passed explicitly to E2B template builds."""
|
|
43
|
+
|
|
44
|
+
cpu_count: int
|
|
45
|
+
memory_mb: int
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def resolve_e2b_template_resources(
|
|
49
|
+
*,
|
|
50
|
+
cpu_count: int | None,
|
|
51
|
+
memory_mb: int | None,
|
|
52
|
+
) -> E2BTemplateResources:
|
|
53
|
+
"""Resolve omitted Harbor values to the pinned E2B numeric defaults."""
|
|
54
|
+
if any(
|
|
55
|
+
isinstance(value, bool) or not isinstance(value, int)
|
|
56
|
+
for value in (cpu_count, memory_mb)
|
|
57
|
+
if value is not None
|
|
58
|
+
):
|
|
59
|
+
raise ValueError("E2B template CPU and memory values must be integers")
|
|
60
|
+
resolved_cpu = E2B_DEFAULT_CPU_COUNT if cpu_count is None else cpu_count
|
|
61
|
+
resolved_memory = E2B_DEFAULT_MEMORY_MB if memory_mb is None else memory_mb
|
|
62
|
+
if resolved_cpu < 1 or resolved_memory < 128:
|
|
63
|
+
raise ValueError("E2B template CPU must be positive and memory must be at least 128 MiB")
|
|
64
|
+
return E2BTemplateResources(cpu_count=resolved_cpu, memory_mb=resolved_memory)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def e2b_sdk_version() -> str:
|
|
68
|
+
"""Return the installed E2B SDK version embedded in template identity."""
|
|
69
|
+
try:
|
|
70
|
+
return version("e2b")
|
|
71
|
+
except PackageNotFoundError as error:
|
|
72
|
+
raise RuntimeError(
|
|
73
|
+
"the harbor E2B task backend needs the e2b extra; run `uv sync --extra e2b`"
|
|
74
|
+
) from error
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def harbor_version() -> str:
|
|
78
|
+
"""Return the Harbor version whose build semantics define template identity."""
|
|
79
|
+
return harbor.__version__
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def e2b_template_resource_payload(
|
|
83
|
+
*,
|
|
84
|
+
environment_id: str,
|
|
85
|
+
build_source_kind: Literal["docker_image", "dockerfile"],
|
|
86
|
+
build_source_reference: str,
|
|
87
|
+
resources: E2BTemplateResources,
|
|
88
|
+
) -> dict[str, int | str]:
|
|
89
|
+
"""Return the canonical resource-complete cache identity used by E2B (frozen bytes)."""
|
|
90
|
+
if not environment_id:
|
|
91
|
+
raise ValueError("Harbor environment_id must be nonempty")
|
|
92
|
+
if not build_source_reference:
|
|
93
|
+
raise ValueError("E2B template build source must be nonempty")
|
|
94
|
+
return {
|
|
95
|
+
"schema_version": E2B_TEMPLATE_POLICY_VERSION,
|
|
96
|
+
"harbor_environment_id": environment_id,
|
|
97
|
+
"build_source_kind": build_source_kind,
|
|
98
|
+
"build_source_reference": build_source_reference,
|
|
99
|
+
"cpu_count": resources.cpu_count,
|
|
100
|
+
"memory_mb": resources.memory_mb,
|
|
101
|
+
"harbor_version": harbor_version(),
|
|
102
|
+
"e2b_sdk_version": e2b_sdk_version(),
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def e2b_template_resource_digest(
|
|
107
|
+
*,
|
|
108
|
+
environment_id: str,
|
|
109
|
+
build_source_kind: Literal["docker_image", "dockerfile"],
|
|
110
|
+
build_source_reference: str,
|
|
111
|
+
resources: E2BTemplateResources,
|
|
112
|
+
) -> str:
|
|
113
|
+
"""Hash one canonical Harbor-content and E2B-resource identity."""
|
|
114
|
+
payload = e2b_template_resource_payload(
|
|
115
|
+
environment_id=environment_id,
|
|
116
|
+
build_source_kind=build_source_kind,
|
|
117
|
+
build_source_reference=build_source_reference,
|
|
118
|
+
resources=resources,
|
|
119
|
+
)
|
|
120
|
+
encoded = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode()
|
|
121
|
+
return hashlib.sha256(encoded).hexdigest()
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def qualify_harbor_e2b_template_name(
|
|
125
|
+
base_name: str,
|
|
126
|
+
*,
|
|
127
|
+
environment_id: str,
|
|
128
|
+
build_source_kind: Literal["docker_image", "dockerfile"],
|
|
129
|
+
build_source_reference: str,
|
|
130
|
+
resources: E2BTemplateResources,
|
|
131
|
+
) -> str:
|
|
132
|
+
"""Replace Harbor's content-only name with a fixed-safe complete identity."""
|
|
133
|
+
if _HARBOR_ENVIRONMENT_ID_PATTERN.fullmatch(environment_id) is None:
|
|
134
|
+
raise ValueError("Harbor environment_id must be 32 lowercase hexadecimal characters")
|
|
135
|
+
inherited_suffix = environment_id[:SNAPSHOT_HASH_LEN]
|
|
136
|
+
if not base_name.endswith(inherited_suffix):
|
|
137
|
+
raise ValueError("Harbor E2B template name does not match its environment_id")
|
|
138
|
+
digest = e2b_template_resource_digest(
|
|
139
|
+
environment_id=environment_id,
|
|
140
|
+
build_source_kind=build_source_kind,
|
|
141
|
+
build_source_reference=build_source_reference,
|
|
142
|
+
resources=resources,
|
|
143
|
+
)
|
|
144
|
+
return f"wmo-hb-v1-{digest}"
|