feat(deploy): swap retired Hetzner suppliers for Qwen3.8-27B pair

Hetzner Inference dropped Kimi-K2.7-Code, GLM-5.2-NVFP4 and
DeepSeek-V4-Flash-0731 from /v1/models; the 6 suppliers serving them are
deregistered (adverts retired on-chain 2026-08-21, containers removed):

  kimi-code          3f37082166faf2b2220e6476235bae8723af9a3434a6aaf60277366ff1f62bfb
  kimi-code-chat     3d1b43645c00bdb7b429f29ced798bc4af206c9dc56074e955d84b603b64f50c
  glm                bf3ee48addb32e2b0726066f1806b9d84ad64b86c7d41d379abd4b439c522696
  glm-chat           b910327023edb6a3f31696b7feaa9448a151c671c2ff303c4c3dd5a07d03c6b5
  ds-flash-htz       61dd30deb1cd3d6c3f73792bda46ecea6890735237d8329ade2b8449d298f24e
  ds-flash-htz-chat  348a278c81a2bf664ea65705a6245df31e81f64c0ffa6e04a59b248fcdae3d9f

New qwen38 + qwen38-chat suppliers serve Hetzner's new Qwen3.8-27B
(ctx 262144; ping + tools round-trip verified 2026-08-21), reusing the
retired kimi-code / kimi-code-chat wallets. Adverts:

  qwen38       bb8a7078098dc5e60b3f97b040e38f05e6cca662497d4bea471e1dff19c1e1ae#0
  qwen38-chat  31e3a6e258ceaa0d1eaabe61fa3fbe3abcbbb400a7b885e05c8dbcdcf4924eda#0
This commit is contained in:
david
2026-08-21 13:46:03 +02:00
parent bb18578ae9
commit e8261d9500
8 changed files with 87 additions and 441 deletions

View File

@@ -132,6 +132,20 @@ const OPERATOR_SOURCES: OperatorSource[] = [
keyVar: "SUPPLIER_PRIV_KEY_HEX", keyVar: "SUPPLIER_PRIV_KEY_HEX",
role: "supplier", role: "supplier",
}, },
{
label: "supplier-qwen38@vector-marketplace",
host: "root@91.98.147.172",
envPath: "/root/agents-marketplace/supplier/.env.qwen38",
keyVar: "SUPPLIER_PRIV_KEY_HEX",
role: "supplier",
},
{
label: "supplier-qwen38-chat@vector-marketplace",
host: "root@91.98.147.172",
envPath: "/root/agents-marketplace/supplier/.env.qwen38-chat",
keyVar: "SUPPLIER_PRIV_KEY_HEX",
role: "supplier",
},
{ {
label: "supplier-local@inference-proxy", label: "supplier-local@inference-proxy",
host: "inference-proxy", host: "inference-proxy",

View File

@@ -1,89 +0,0 @@
# deploy/mainnet/docker-compose.supplier-ds-flash-htz.yml — Supplier — MAINNET
# (Hetzner Inference / DeepSeek-V4-Flash-0731 — one-off `llm.text.generate.v1`)
#
# Hetzner-backed supplier. LLM_BACKEND=openai pointed directly at Hetzner's
# hosted inference API (OpenAI-compatible at https://inference.hetzner.com/api).
# No local proxy container — reachable over public HTTPS.
#
# One of 8 Hetzner-backed suppliers (4 models x {one-off, chat-session});
# fleet runbook: docs/HETZNER_SETUP.md.
#
# Pre-flight:
# 1. DNS: mp-suppliers-ds-flash-htz.vector.apexfusion.org → host
# (individual DNS-only A record → 91.98.147.172; NO wildcard exists —
# letsencrypt HTTP-01 issuance needs the unproxied direct record)
# 2. supplier/.env.ds-flash-htz written on host (chmod 600) with at minimum:
# SUPPLIER_PRIV_KEY_HEX, SUPPLIER_ADDRESS, SUPPLIER_PKH,
# SUPPLIER_PUB_KEY_HEX, OPENAI_API_KEY, OGMIOS_URL, NETWORK_ID=1,
# VECTOR_ZERO_TIME_MS, ESCROW_REF_UTXO, ADVERT_REF_UTXO, ADVERT_REF,
# LIVE_CHAIN=1
# 3. Networks already exist (created by the canonical supplier compose):
# docker network create marketplace-mainnet-net # one-shot
# # traefik-net is created by the Traefik project
name: marketplace-mainnet-supplier-ds-flash-htz
services:
supplier:
build:
context: ../..
dockerfile: supplier/Dockerfile
container_name: marketplace-mainnet-supplier-ds-flash-htz
restart: unless-stopped
env_file:
# Self-contained env for this Hetzner-backed variant. Holds this
# supplier's distinct SUPPLIER_PRIV_KEY_HEX (+ derived wallet vars),
# ADVERT_REF, the shared Hetzner OPENAI_API_KEY, and the shared mainnet
# plumbing duplicated in full (NETWORK_ID, OGMIOS_URL, VECTOR_ZERO_TIME_MS,
# ref-script UTxOs, LIVE_CHAIN). No env_file ordering / override magic.
- path: ../../supplier/.env.ds-flash-htz
required: false
environment:
LLM_BACKEND: openai
# No /v1 suffix — supplier/src/openai.ts appends /v1/chat/completions
# (Hetzner serves at https://inference.hetzner.com/api/v1/...).
OPENAI_BASE_URL: https://inference.hetzner.com/api
# Reasoning-style models can be slow; matches the advert's
# max_processing_ms (300000).
OPENAI_TIMEOUT_MS: "300000"
# OPENAI_MAX_TOKENS intentionally unset: no max_tokens forwarded upstream,
# the provider grants context − prompt. Advert cap = model context length.
PORT: "8080"
# Enable LiveOgmiosProvider so submitTx/awaitTx actually broadcast.
LIVE_CHAIN: "1"
# NETWORK_ID and OGMIOS_URL intentionally not pinned here — they MUST
# come from the operator-provided supplier/.env.ds-flash-htz on a mainnet host.
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/healthz >/dev/null || exit 1"]
interval: 20s
timeout: 5s
retries: 3
start_period: 15s
networks:
- marketplace-mainnet-net
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-net"
- "traefik.http.routers.mp-suppliers-ds-flash-htz-mainnet.entrypoints=web"
- "traefik.http.routers.mp-suppliers-ds-flash-htz-mainnet.rule=Host(`mp-suppliers-ds-flash-htz.vector.apexfusion.org`)"
- "traefik.http.routers.mp-suppliers-ds-flash-htz-mainnet.middlewares=mp-suppliers-ds-flash-htz-mainnet-https"
- "traefik.http.middlewares.mp-suppliers-ds-flash-htz-mainnet-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.mp-suppliers-ds-flash-htz-mainnet-https.redirectscheme.permanent=true"
- "traefik.http.routers.mp-suppliers-ds-flash-htz-mainnet-tls.entrypoints=websecure"
- "traefik.http.routers.mp-suppliers-ds-flash-htz-mainnet-tls.rule=Host(`mp-suppliers-ds-flash-htz.vector.apexfusion.org`)"
- "traefik.http.routers.mp-suppliers-ds-flash-htz-mainnet-tls.tls.certresolver=letsencrypt"
- "traefik.http.services.mp-suppliers-ds-flash-htz-mainnet.loadbalancer.server.port=8080"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
networks:
marketplace-mainnet-net:
external: true
name: marketplace-mainnet-net
traefik-net:
external: true
name: traefik-net

View File

@@ -1,101 +0,0 @@
# deploy/mainnet/docker-compose.supplier-glm-chat.yml — Supplier — MAINNET
# (Hetzner Inference / GLM-5.2-NVFP4 — MULTI-TURN CHAT capability `llm.chat.v1`)
#
# The chat-session sibling of docker-compose.supplier-glm.yml. Same
# image, same Hetzner backend (GLM-5.2-NVFP4), but CAPABILITY_KIND=chat-session so
# it mounts /v1/chat/{start,message,end} (escrow bookends, off-chain streaming
# turns) instead of the one-off /v1/chat/completions route.
#
# A SEPARATE process/advert from the one-off supplier on purpose: the chat
# session holds the supplier's single-slot lock for the whole conversation
# (minutes), which would starve one-off traffic if co-hosted.
#
# One of 8 Hetzner-backed suppliers (4 models x {one-off, chat-session});
# fleet runbook: docs/HETZNER_SETUP.md.
#
# Pre-flight:
# 1. DNS: mp-suppliers-glm-chat.vector.apexfusion.org → host
# (individual DNS-only A record → 91.98.147.172; NO wildcard exists —
# letsencrypt HTTP-01 issuance needs the unproxied direct record)
# 2. supplier/.env.glm-chat written on host (chmod 600) with at minimum:
# SUPPLIER_PRIV_KEY_HEX, SUPPLIER_ADDRESS, SUPPLIER_PKH,
# SUPPLIER_PUB_KEY_HEX, OPENAI_API_KEY, OGMIOS_URL, NETWORK_ID=1,
# VECTOR_ZERO_TIME_MS, ESCROW_REF_UTXO, ADVERT_REF_UTXO, ADVERT_REF,
# LIVE_CHAIN=1
# The advert must be posted with --capability-id llm.chat.v1 and a large
# --max-processing-ms (~1800000) so Claim+Submit both land before deliver_by.
# 3. Networks already exist (created by the canonical supplier compose):
# docker network create marketplace-mainnet-net # one-shot
# # traefik-net is created by the Traefik project
name: marketplace-mainnet-supplier-glm-chat
services:
supplier:
build:
context: ../..
dockerfile: supplier/Dockerfile
container_name: marketplace-mainnet-supplier-glm-chat
restart: unless-stopped
env_file:
# Self-contained env for this Hetzner-backed variant. Holds this
# supplier's distinct SUPPLIER_PRIV_KEY_HEX (+ derived wallet vars),
# ADVERT_REF, the shared Hetzner OPENAI_API_KEY, and the shared mainnet
# plumbing duplicated in full (NETWORK_ID, OGMIOS_URL, VECTOR_ZERO_TIME_MS,
# ref-script UTxOs, LIVE_CHAIN). No env_file ordering / override magic.
- path: ../../supplier/.env.glm-chat
required: false
environment:
# Multi-turn chat session capability (mounts /v1/chat/{start,message,end}).
CAPABILITY_KIND: chat-session
LLM_BACKEND: openai
# No /v1 suffix — supplier/src/openai.ts appends /v1/chat/completions
# (Hetzner serves at https://inference.hetzner.com/api/v1/...).
OPENAI_BASE_URL: https://inference.hetzner.com/api
# Reasoning-style models can be slow; mirror the one-off compose.
OPENAI_TIMEOUT_MS: "300000"
# Idle end (supplier Submits the transcript): single-slot suppliers must
# free up quickly (the gateway transparently reopens a session on the
# next turn). Mirrors the kimi-chat fleet.
CHAT_IDLE_TIMEOUT_MS: "900000"
CHAT_SETTLE_MODE: ticket
MAX_CHAT_SESSIONS: "8"
PORT: "8080"
# Enable LiveOgmiosProvider so Claim/Submit actually broadcast.
LIVE_CHAIN: "1"
# NETWORK_ID and OGMIOS_URL intentionally not pinned here — they MUST
# come from the operator-provided supplier/.env.glm-chat on a mainnet host.
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/healthz >/dev/null || exit 1"]
interval: 20s
timeout: 5s
retries: 3
start_period: 15s
networks:
- marketplace-mainnet-net
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-net"
- "traefik.http.routers.mp-suppliers-glm-chat-mainnet.entrypoints=web"
- "traefik.http.routers.mp-suppliers-glm-chat-mainnet.rule=Host(`mp-suppliers-glm-chat.vector.apexfusion.org`)"
- "traefik.http.routers.mp-suppliers-glm-chat-mainnet.middlewares=mp-suppliers-glm-chat-mainnet-https"
- "traefik.http.middlewares.mp-suppliers-glm-chat-mainnet-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.mp-suppliers-glm-chat-mainnet-https.redirectscheme.permanent=true"
- "traefik.http.routers.mp-suppliers-glm-chat-mainnet-tls.entrypoints=websecure"
- "traefik.http.routers.mp-suppliers-glm-chat-mainnet-tls.rule=Host(`mp-suppliers-glm-chat.vector.apexfusion.org`)"
- "traefik.http.routers.mp-suppliers-glm-chat-mainnet-tls.tls.certresolver=letsencrypt"
- "traefik.http.services.mp-suppliers-glm-chat-mainnet.loadbalancer.server.port=8080"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
networks:
marketplace-mainnet-net:
external: true
name: marketplace-mainnet-net
traefik-net:
external: true
name: traefik-net

View File

@@ -1,89 +0,0 @@
# deploy/mainnet/docker-compose.supplier-glm.yml — Supplier — MAINNET
# (Hetzner Inference / GLM-5.2-NVFP4 — one-off `llm.text.generate.v1`)
#
# Hetzner-backed supplier. LLM_BACKEND=openai pointed directly at Hetzner's
# hosted inference API (OpenAI-compatible at https://inference.hetzner.com/api).
# No local proxy container — reachable over public HTTPS.
#
# One of 8 Hetzner-backed suppliers (4 models x {one-off, chat-session});
# fleet runbook: docs/HETZNER_SETUP.md.
#
# Pre-flight:
# 1. DNS: mp-suppliers-glm.vector.apexfusion.org → host
# (individual DNS-only A record → 91.98.147.172; NO wildcard exists —
# letsencrypt HTTP-01 issuance needs the unproxied direct record)
# 2. supplier/.env.glm written on host (chmod 600) with at minimum:
# SUPPLIER_PRIV_KEY_HEX, SUPPLIER_ADDRESS, SUPPLIER_PKH,
# SUPPLIER_PUB_KEY_HEX, OPENAI_API_KEY, OGMIOS_URL, NETWORK_ID=1,
# VECTOR_ZERO_TIME_MS, ESCROW_REF_UTXO, ADVERT_REF_UTXO, ADVERT_REF,
# LIVE_CHAIN=1
# 3. Networks already exist (created by the canonical supplier compose):
# docker network create marketplace-mainnet-net # one-shot
# # traefik-net is created by the Traefik project
name: marketplace-mainnet-supplier-glm
services:
supplier:
build:
context: ../..
dockerfile: supplier/Dockerfile
container_name: marketplace-mainnet-supplier-glm
restart: unless-stopped
env_file:
# Self-contained env for this Hetzner-backed variant. Holds this
# supplier's distinct SUPPLIER_PRIV_KEY_HEX (+ derived wallet vars),
# ADVERT_REF, the shared Hetzner OPENAI_API_KEY, and the shared mainnet
# plumbing duplicated in full (NETWORK_ID, OGMIOS_URL, VECTOR_ZERO_TIME_MS,
# ref-script UTxOs, LIVE_CHAIN). No env_file ordering / override magic.
- path: ../../supplier/.env.glm
required: false
environment:
LLM_BACKEND: openai
# No /v1 suffix — supplier/src/openai.ts appends /v1/chat/completions
# (Hetzner serves at https://inference.hetzner.com/api/v1/...).
OPENAI_BASE_URL: https://inference.hetzner.com/api
# Reasoning-style models can be slow; matches the advert's
# max_processing_ms (300000).
OPENAI_TIMEOUT_MS: "300000"
# OPENAI_MAX_TOKENS intentionally unset: no max_tokens forwarded upstream,
# the provider grants context − prompt. Advert cap = model context length.
PORT: "8080"
# Enable LiveOgmiosProvider so submitTx/awaitTx actually broadcast.
LIVE_CHAIN: "1"
# NETWORK_ID and OGMIOS_URL intentionally not pinned here — they MUST
# come from the operator-provided supplier/.env.glm on a mainnet host.
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/healthz >/dev/null || exit 1"]
interval: 20s
timeout: 5s
retries: 3
start_period: 15s
networks:
- marketplace-mainnet-net
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-net"
- "traefik.http.routers.mp-suppliers-glm-mainnet.entrypoints=web"
- "traefik.http.routers.mp-suppliers-glm-mainnet.rule=Host(`mp-suppliers-glm.vector.apexfusion.org`)"
- "traefik.http.routers.mp-suppliers-glm-mainnet.middlewares=mp-suppliers-glm-mainnet-https"
- "traefik.http.middlewares.mp-suppliers-glm-mainnet-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.mp-suppliers-glm-mainnet-https.redirectscheme.permanent=true"
- "traefik.http.routers.mp-suppliers-glm-mainnet-tls.entrypoints=websecure"
- "traefik.http.routers.mp-suppliers-glm-mainnet-tls.rule=Host(`mp-suppliers-glm.vector.apexfusion.org`)"
- "traefik.http.routers.mp-suppliers-glm-mainnet-tls.tls.certresolver=letsencrypt"
- "traefik.http.services.mp-suppliers-glm-mainnet.loadbalancer.server.port=8080"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
networks:
marketplace-mainnet-net:
external: true
name: marketplace-mainnet-net
traefik-net:
external: true
name: traefik-net

View File

@@ -1,101 +0,0 @@
# deploy/mainnet/docker-compose.supplier-kimi-code-chat.yml — Supplier — MAINNET
# (Hetzner Inference / Kimi-K2.7-Code — MULTI-TURN CHAT capability `llm.chat.v1`)
#
# The chat-session sibling of docker-compose.supplier-kimi-code.yml. Same
# image, same Hetzner backend (Kimi-K2.7-Code), but CAPABILITY_KIND=chat-session so
# it mounts /v1/chat/{start,message,end} (escrow bookends, off-chain streaming
# turns) instead of the one-off /v1/chat/completions route.
#
# A SEPARATE process/advert from the one-off supplier on purpose: the chat
# session holds the supplier's single-slot lock for the whole conversation
# (minutes), which would starve one-off traffic if co-hosted.
#
# One of 8 Hetzner-backed suppliers (4 models x {one-off, chat-session});
# fleet runbook: docs/HETZNER_SETUP.md.
#
# Pre-flight:
# 1. DNS: mp-suppliers-kimi-code-chat.vector.apexfusion.org → host
# (individual DNS-only A record → 91.98.147.172; NO wildcard exists —
# letsencrypt HTTP-01 issuance needs the unproxied direct record)
# 2. supplier/.env.kimi-code-chat written on host (chmod 600) with at minimum:
# SUPPLIER_PRIV_KEY_HEX, SUPPLIER_ADDRESS, SUPPLIER_PKH,
# SUPPLIER_PUB_KEY_HEX, OPENAI_API_KEY, OGMIOS_URL, NETWORK_ID=1,
# VECTOR_ZERO_TIME_MS, ESCROW_REF_UTXO, ADVERT_REF_UTXO, ADVERT_REF,
# LIVE_CHAIN=1
# The advert must be posted with --capability-id llm.chat.v1 and a large
# --max-processing-ms (~1800000) so Claim+Submit both land before deliver_by.
# 3. Networks already exist (created by the canonical supplier compose):
# docker network create marketplace-mainnet-net # one-shot
# # traefik-net is created by the Traefik project
name: marketplace-mainnet-supplier-kimi-code-chat
services:
supplier:
build:
context: ../..
dockerfile: supplier/Dockerfile
container_name: marketplace-mainnet-supplier-kimi-code-chat
restart: unless-stopped
env_file:
# Self-contained env for this Hetzner-backed variant. Holds this
# supplier's distinct SUPPLIER_PRIV_KEY_HEX (+ derived wallet vars),
# ADVERT_REF, the shared Hetzner OPENAI_API_KEY, and the shared mainnet
# plumbing duplicated in full (NETWORK_ID, OGMIOS_URL, VECTOR_ZERO_TIME_MS,
# ref-script UTxOs, LIVE_CHAIN). No env_file ordering / override magic.
- path: ../../supplier/.env.kimi-code-chat
required: false
environment:
# Multi-turn chat session capability (mounts /v1/chat/{start,message,end}).
CAPABILITY_KIND: chat-session
LLM_BACKEND: openai
# No /v1 suffix — supplier/src/openai.ts appends /v1/chat/completions
# (Hetzner serves at https://inference.hetzner.com/api/v1/...).
OPENAI_BASE_URL: https://inference.hetzner.com/api
# Reasoning-style models can be slow; mirror the one-off compose.
OPENAI_TIMEOUT_MS: "300000"
# Idle end (supplier Submits the transcript): single-slot suppliers must
# free up quickly (the gateway transparently reopens a session on the
# next turn). Mirrors the kimi-chat fleet.
CHAT_IDLE_TIMEOUT_MS: "900000"
CHAT_SETTLE_MODE: ticket
MAX_CHAT_SESSIONS: "8"
PORT: "8080"
# Enable LiveOgmiosProvider so Claim/Submit actually broadcast.
LIVE_CHAIN: "1"
# NETWORK_ID and OGMIOS_URL intentionally not pinned here — they MUST
# come from the operator-provided supplier/.env.kimi-code-chat on a mainnet host.
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/healthz >/dev/null || exit 1"]
interval: 20s
timeout: 5s
retries: 3
start_period: 15s
networks:
- marketplace-mainnet-net
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-net"
- "traefik.http.routers.mp-suppliers-kimi-code-chat-mainnet.entrypoints=web"
- "traefik.http.routers.mp-suppliers-kimi-code-chat-mainnet.rule=Host(`mp-suppliers-kimi-code-chat.vector.apexfusion.org`)"
- "traefik.http.routers.mp-suppliers-kimi-code-chat-mainnet.middlewares=mp-suppliers-kimi-code-chat-mainnet-https"
- "traefik.http.middlewares.mp-suppliers-kimi-code-chat-mainnet-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.mp-suppliers-kimi-code-chat-mainnet-https.redirectscheme.permanent=true"
- "traefik.http.routers.mp-suppliers-kimi-code-chat-mainnet-tls.entrypoints=websecure"
- "traefik.http.routers.mp-suppliers-kimi-code-chat-mainnet-tls.rule=Host(`mp-suppliers-kimi-code-chat.vector.apexfusion.org`)"
- "traefik.http.routers.mp-suppliers-kimi-code-chat-mainnet-tls.tls.certresolver=letsencrypt"
- "traefik.http.services.mp-suppliers-kimi-code-chat-mainnet.loadbalancer.server.port=8080"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
networks:
marketplace-mainnet-net:
external: true
name: marketplace-mainnet-net
traefik-net:
external: true
name: traefik-net

View File

@@ -1,8 +1,8 @@
# deploy/mainnet/docker-compose.supplier-ds-flash-htz-chat.yml — Supplier — MAINNET # deploy/mainnet/docker-compose.supplier-qwen38-chat.yml — Supplier — MAINNET
# (Hetzner Inference / DeepSeek-V4-Flash-0731 — MULTI-TURN CHAT capability `llm.chat.v1`) # (Hetzner Inference / Qwen3.8-27B — MULTI-TURN CHAT capability `llm.chat.v1`)
# #
# The chat-session sibling of docker-compose.supplier-ds-flash-htz.yml. Same # The chat-session sibling of docker-compose.supplier-qwen38.yml. Same
# image, same Hetzner backend (DeepSeek-V4-Flash-0731), but CAPABILITY_KIND=chat-session so # image, same Hetzner backend (Qwen3.8-27B), but CAPABILITY_KIND=chat-session so
# it mounts /v1/chat/{start,message,end} (escrow bookends, off-chain streaming # it mounts /v1/chat/{start,message,end} (escrow bookends, off-chain streaming
# turns) instead of the one-off /v1/chat/completions route. # turns) instead of the one-off /v1/chat/completions route.
# #
@@ -10,14 +10,16 @@
# session holds the supplier's single-slot lock for the whole conversation # session holds the supplier's single-slot lock for the whole conversation
# (minutes), which would starve one-off traffic if co-hosted. # (minutes), which would starve one-off traffic if co-hosted.
# #
# One of 8 Hetzner-backed suppliers (4 models x {one-off, chat-session}); # One of the Hetzner-backed suppliers (models x {one-off, chat-session});
# fleet runbook: docs/HETZNER_SETUP.md. # fleet runbook: docs/HETZNER_SETUP.md. Wallet reused from the retired
# kimi-code-chat supplier (Hetzner dropped Kimi-K2.7-Code on 2026-08; advert
# retired 2026-08-21, tx 3d1b43645c00bdb7b429f29ced798bc4af206c9dc56074e955d84b603b64f50c).
# #
# Pre-flight: # Pre-flight:
# 1. DNS: mp-suppliers-ds-flash-htz-chat.vector.apexfusion.org → host # 1. DNS: mp-suppliers-qwen38-chat.vector.apexfusion.org → host
# (individual DNS-only A record → 91.98.147.172; NO wildcard exists — # (individual DNS-only A record → 91.98.147.172; NO wildcard exists —
# letsencrypt HTTP-01 issuance needs the unproxied direct record) # letsencrypt HTTP-01 issuance needs the unproxied direct record)
# 2. supplier/.env.ds-flash-htz-chat written on host (chmod 600) with at minimum: # 2. supplier/.env.qwen38-chat written on host (chmod 600) with at minimum:
# SUPPLIER_PRIV_KEY_HEX, SUPPLIER_ADDRESS, SUPPLIER_PKH, # SUPPLIER_PRIV_KEY_HEX, SUPPLIER_ADDRESS, SUPPLIER_PKH,
# SUPPLIER_PUB_KEY_HEX, OPENAI_API_KEY, OGMIOS_URL, NETWORK_ID=1, # SUPPLIER_PUB_KEY_HEX, OPENAI_API_KEY, OGMIOS_URL, NETWORK_ID=1,
# VECTOR_ZERO_TIME_MS, ESCROW_REF_UTXO, ADVERT_REF_UTXO, ADVERT_REF, # VECTOR_ZERO_TIME_MS, ESCROW_REF_UTXO, ADVERT_REF_UTXO, ADVERT_REF,
@@ -28,14 +30,14 @@
# docker network create marketplace-mainnet-net # one-shot # docker network create marketplace-mainnet-net # one-shot
# # traefik-net is created by the Traefik project # # traefik-net is created by the Traefik project
name: marketplace-mainnet-supplier-ds-flash-htz-chat name: marketplace-mainnet-supplier-qwen38-chat
services: services:
supplier: supplier:
build: build:
context: ../.. context: ../..
dockerfile: supplier/Dockerfile dockerfile: supplier/Dockerfile
container_name: marketplace-mainnet-supplier-ds-flash-htz-chat container_name: marketplace-mainnet-supplier-qwen38-chat
restart: unless-stopped restart: unless-stopped
env_file: env_file:
# Self-contained env for this Hetzner-backed variant. Holds this # Self-contained env for this Hetzner-backed variant. Holds this
@@ -43,7 +45,7 @@ services:
# ADVERT_REF, the shared Hetzner OPENAI_API_KEY, and the shared mainnet # ADVERT_REF, the shared Hetzner OPENAI_API_KEY, and the shared mainnet
# plumbing duplicated in full (NETWORK_ID, OGMIOS_URL, VECTOR_ZERO_TIME_MS, # plumbing duplicated in full (NETWORK_ID, OGMIOS_URL, VECTOR_ZERO_TIME_MS,
# ref-script UTxOs, LIVE_CHAIN). No env_file ordering / override magic. # ref-script UTxOs, LIVE_CHAIN). No env_file ordering / override magic.
- path: ../../supplier/.env.ds-flash-htz-chat - path: ../../supplier/.env.qwen38-chat
required: false required: false
environment: environment:
# Multi-turn chat session capability (mounts /v1/chat/{start,message,end}). # Multi-turn chat session capability (mounts /v1/chat/{start,message,end}).
@@ -64,7 +66,7 @@ services:
# Enable LiveOgmiosProvider so Claim/Submit actually broadcast. # Enable LiveOgmiosProvider so Claim/Submit actually broadcast.
LIVE_CHAIN: "1" LIVE_CHAIN: "1"
# NETWORK_ID and OGMIOS_URL intentionally not pinned here — they MUST # NETWORK_ID and OGMIOS_URL intentionally not pinned here — they MUST
# come from the operator-provided supplier/.env.ds-flash-htz-chat on a mainnet host. # come from the operator-provided supplier/.env.qwen38-chat on a mainnet host.
healthcheck: healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/healthz >/dev/null || exit 1"] test: ["CMD-SHELL", "wget -qO- http://localhost:8080/healthz >/dev/null || exit 1"]
interval: 20s interval: 20s
@@ -77,15 +79,15 @@ services:
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.docker.network=traefik-net" - "traefik.docker.network=traefik-net"
- "traefik.http.routers.mp-suppliers-ds-flash-htz-chat-mainnet.entrypoints=web" - "traefik.http.routers.mp-suppliers-qwen38-chat-mainnet.entrypoints=web"
- "traefik.http.routers.mp-suppliers-ds-flash-htz-chat-mainnet.rule=Host(`mp-suppliers-ds-flash-htz-chat.vector.apexfusion.org`)" - "traefik.http.routers.mp-suppliers-qwen38-chat-mainnet.rule=Host(`mp-suppliers-qwen38-chat.vector.apexfusion.org`)"
- "traefik.http.routers.mp-suppliers-ds-flash-htz-chat-mainnet.middlewares=mp-suppliers-ds-flash-htz-chat-mainnet-https" - "traefik.http.routers.mp-suppliers-qwen38-chat-mainnet.middlewares=mp-suppliers-qwen38-chat-mainnet-https"
- "traefik.http.middlewares.mp-suppliers-ds-flash-htz-chat-mainnet-https.redirectscheme.scheme=https" - "traefik.http.middlewares.mp-suppliers-qwen38-chat-mainnet-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.mp-suppliers-ds-flash-htz-chat-mainnet-https.redirectscheme.permanent=true" - "traefik.http.middlewares.mp-suppliers-qwen38-chat-mainnet-https.redirectscheme.permanent=true"
- "traefik.http.routers.mp-suppliers-ds-flash-htz-chat-mainnet-tls.entrypoints=websecure" - "traefik.http.routers.mp-suppliers-qwen38-chat-mainnet-tls.entrypoints=websecure"
- "traefik.http.routers.mp-suppliers-ds-flash-htz-chat-mainnet-tls.rule=Host(`mp-suppliers-ds-flash-htz-chat.vector.apexfusion.org`)" - "traefik.http.routers.mp-suppliers-qwen38-chat-mainnet-tls.rule=Host(`mp-suppliers-qwen38-chat.vector.apexfusion.org`)"
- "traefik.http.routers.mp-suppliers-ds-flash-htz-chat-mainnet-tls.tls.certresolver=letsencrypt" - "traefik.http.routers.mp-suppliers-qwen38-chat-mainnet-tls.tls.certresolver=letsencrypt"
- "traefik.http.services.mp-suppliers-ds-flash-htz-chat-mainnet.loadbalancer.server.port=8080" - "traefik.http.services.mp-suppliers-qwen38-chat-mainnet.loadbalancer.server.port=8080"
logging: logging:
driver: json-file driver: json-file
options: options:

View File

@@ -1,18 +1,20 @@
# deploy/mainnet/docker-compose.supplier-kimi-code.yml — Supplier — MAINNET # deploy/mainnet/docker-compose.supplier-qwen38.yml — Supplier — MAINNET
# (Hetzner Inference / Kimi-K2.7-Code — one-off `llm.text.generate.v1`) # (Hetzner Inference / Qwen3.8-27B — one-off `llm.text.generate.v1`)
# #
# Hetzner-backed supplier. LLM_BACKEND=openai pointed directly at Hetzner's # Hetzner-backed supplier. LLM_BACKEND=openai pointed directly at Hetzner's
# hosted inference API (OpenAI-compatible at https://inference.hetzner.com/api). # hosted inference API (OpenAI-compatible at https://inference.hetzner.com/api).
# No local proxy container — reachable over public HTTPS. # No local proxy container — reachable over public HTTPS.
# #
# One of 8 Hetzner-backed suppliers (4 models x {one-off, chat-session}); # One of the Hetzner-backed suppliers (models x {one-off, chat-session});
# fleet runbook: docs/HETZNER_SETUP.md. # fleet runbook: docs/HETZNER_SETUP.md. Wallet reused from the retired
# kimi-code supplier (Hetzner dropped Kimi-K2.7-Code on 2026-08; advert
# retired 2026-08-21, tx 3f37082166faf2b2220e6476235bae8723af9a3434a6aaf60277366ff1f62bfb).
# #
# Pre-flight: # Pre-flight:
# 1. DNS: mp-suppliers-kimi-code.vector.apexfusion.org → host # 1. DNS: mp-suppliers-qwen38.vector.apexfusion.org → host
# (individual DNS-only A record → 91.98.147.172; NO wildcard exists — # (individual DNS-only A record → 91.98.147.172; NO wildcard exists —
# letsencrypt HTTP-01 issuance needs the unproxied direct record) # letsencrypt HTTP-01 issuance needs the unproxied direct record)
# 2. supplier/.env.kimi-code written on host (chmod 600) with at minimum: # 2. supplier/.env.qwen38 written on host (chmod 600) with at minimum:
# SUPPLIER_PRIV_KEY_HEX, SUPPLIER_ADDRESS, SUPPLIER_PKH, # SUPPLIER_PRIV_KEY_HEX, SUPPLIER_ADDRESS, SUPPLIER_PKH,
# SUPPLIER_PUB_KEY_HEX, OPENAI_API_KEY, OGMIOS_URL, NETWORK_ID=1, # SUPPLIER_PUB_KEY_HEX, OPENAI_API_KEY, OGMIOS_URL, NETWORK_ID=1,
# VECTOR_ZERO_TIME_MS, ESCROW_REF_UTXO, ADVERT_REF_UTXO, ADVERT_REF, # VECTOR_ZERO_TIME_MS, ESCROW_REF_UTXO, ADVERT_REF_UTXO, ADVERT_REF,
@@ -21,14 +23,14 @@
# docker network create marketplace-mainnet-net # one-shot # docker network create marketplace-mainnet-net # one-shot
# # traefik-net is created by the Traefik project # # traefik-net is created by the Traefik project
name: marketplace-mainnet-supplier-kimi-code name: marketplace-mainnet-supplier-qwen38
services: services:
supplier: supplier:
build: build:
context: ../.. context: ../..
dockerfile: supplier/Dockerfile dockerfile: supplier/Dockerfile
container_name: marketplace-mainnet-supplier-kimi-code container_name: marketplace-mainnet-supplier-qwen38
restart: unless-stopped restart: unless-stopped
env_file: env_file:
# Self-contained env for this Hetzner-backed variant. Holds this # Self-contained env for this Hetzner-backed variant. Holds this
@@ -36,7 +38,7 @@ services:
# ADVERT_REF, the shared Hetzner OPENAI_API_KEY, and the shared mainnet # ADVERT_REF, the shared Hetzner OPENAI_API_KEY, and the shared mainnet
# plumbing duplicated in full (NETWORK_ID, OGMIOS_URL, VECTOR_ZERO_TIME_MS, # plumbing duplicated in full (NETWORK_ID, OGMIOS_URL, VECTOR_ZERO_TIME_MS,
# ref-script UTxOs, LIVE_CHAIN). No env_file ordering / override magic. # ref-script UTxOs, LIVE_CHAIN). No env_file ordering / override magic.
- path: ../../supplier/.env.kimi-code - path: ../../supplier/.env.qwen38
required: false required: false
environment: environment:
LLM_BACKEND: openai LLM_BACKEND: openai
@@ -52,7 +54,7 @@ services:
# Enable LiveOgmiosProvider so submitTx/awaitTx actually broadcast. # Enable LiveOgmiosProvider so submitTx/awaitTx actually broadcast.
LIVE_CHAIN: "1" LIVE_CHAIN: "1"
# NETWORK_ID and OGMIOS_URL intentionally not pinned here — they MUST # NETWORK_ID and OGMIOS_URL intentionally not pinned here — they MUST
# come from the operator-provided supplier/.env.kimi-code on a mainnet host. # come from the operator-provided supplier/.env.qwen38 on a mainnet host.
healthcheck: healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/healthz >/dev/null || exit 1"] test: ["CMD-SHELL", "wget -qO- http://localhost:8080/healthz >/dev/null || exit 1"]
interval: 20s interval: 20s
@@ -65,15 +67,15 @@ services:
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.docker.network=traefik-net" - "traefik.docker.network=traefik-net"
- "traefik.http.routers.mp-suppliers-kimi-code-mainnet.entrypoints=web" - "traefik.http.routers.mp-suppliers-qwen38-mainnet.entrypoints=web"
- "traefik.http.routers.mp-suppliers-kimi-code-mainnet.rule=Host(`mp-suppliers-kimi-code.vector.apexfusion.org`)" - "traefik.http.routers.mp-suppliers-qwen38-mainnet.rule=Host(`mp-suppliers-qwen38.vector.apexfusion.org`)"
- "traefik.http.routers.mp-suppliers-kimi-code-mainnet.middlewares=mp-suppliers-kimi-code-mainnet-https" - "traefik.http.routers.mp-suppliers-qwen38-mainnet.middlewares=mp-suppliers-qwen38-mainnet-https"
- "traefik.http.middlewares.mp-suppliers-kimi-code-mainnet-https.redirectscheme.scheme=https" - "traefik.http.middlewares.mp-suppliers-qwen38-mainnet-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.mp-suppliers-kimi-code-mainnet-https.redirectscheme.permanent=true" - "traefik.http.middlewares.mp-suppliers-qwen38-mainnet-https.redirectscheme.permanent=true"
- "traefik.http.routers.mp-suppliers-kimi-code-mainnet-tls.entrypoints=websecure" - "traefik.http.routers.mp-suppliers-qwen38-mainnet-tls.entrypoints=websecure"
- "traefik.http.routers.mp-suppliers-kimi-code-mainnet-tls.rule=Host(`mp-suppliers-kimi-code.vector.apexfusion.org`)" - "traefik.http.routers.mp-suppliers-qwen38-mainnet-tls.rule=Host(`mp-suppliers-qwen38.vector.apexfusion.org`)"
- "traefik.http.routers.mp-suppliers-kimi-code-mainnet-tls.tls.certresolver=letsencrypt" - "traefik.http.routers.mp-suppliers-qwen38-mainnet-tls.tls.certresolver=letsencrypt"
- "traefik.http.services.mp-suppliers-kimi-code-mainnet.loadbalancer.server.port=8080" - "traefik.http.services.mp-suppliers-qwen38-mainnet.loadbalancer.server.port=8080"
logging: logging:
driver: json-file driver: json-file
options: options:

View File

@@ -1,8 +1,13 @@
# Hetzner Inference Supplier Fleet — Setup Runbook # Hetzner Inference Supplier Fleet — Setup Runbook
> **Status:** shipped. Configures 8 mainnet supplier nodes that use **Hetzner > **Status:** shipped; fleet trimmed 2026-08-21. Hetzner retired
> Inference** (`https://inference.hetzner.com`) as their **compute backend** for > `Kimi-K2.7-Code`, `GLM-5.2-NVFP4`, and `DeepSeek-V4-Flash-0731` from
> bonded inference work commissioned on Vector. Config only — no code changes. > Inference (gone from `/v1/models`), so the 6 suppliers serving them were
> deregistered (adverts retired on-chain, containers removed). `Qwen3.8-27B`
> was added in their place, reusing the retired kimi-code wallets. Configures
> mainnet supplier nodes that use **Hetzner Inference**
> (`https://inference.hetzner.com`) as their **compute backend** for bonded
> inference work commissioned on Vector. Config only — no code changes.
--- ---
@@ -15,19 +20,21 @@ upstream client (`supplier/src/openai.ts`) already speaks plain
This is the same pattern as the DeepSeek-direct and OpenRouter suppliers, and This is the same pattern as the DeepSeek-direct and OpenRouter suppliers, and
the direct sibling of `docs/HUGGINGFACE_ROUTER_SETUP.md`. the direct sibling of `docs/HUGGINGFACE_ROUTER_SETUP.md`.
One supplier per (model × capability) — 4 models, both the one-off One supplier per (model × capability) — both the one-off
`llm.text.generate.v1` and the multi-turn `llm.chat.v1` capability: `llm.text.generate.v1` and the multi-turn `llm.chat.v1` capability:
| Supplier name | Model (on-chain + API param, verbatim) | Capability | Advert max_output_tokens | | Supplier name | Model (on-chain + API param, verbatim) | Capability | Advert max_output_tokens |
|---|---|---|---| |---|---|---|---|
| `kimi-code` | `Kimi-K2.7-Code` | `llm.text.generate.v1` | 262144 |
| `kimi-code-chat` | `Kimi-K2.7-Code` | `llm.chat.v1` | 262144 |
| `glm` | `GLM-5.2-NVFP4` | `llm.text.generate.v1` | 512000 |
| `glm-chat` | `GLM-5.2-NVFP4` | `llm.chat.v1` | 512000 |
| `ds-flash-htz` | `DeepSeek-V4-Flash-0731` | `llm.text.generate.v1` | 512000 |
| `ds-flash-htz-chat` | `DeepSeek-V4-Flash-0731` | `llm.chat.v1` | 512000 |
| `qwen35b` | `Qwen/Qwen3.6-35B-A3B-FP8` | `llm.text.generate.v1` | 262144 | | `qwen35b` | `Qwen/Qwen3.6-35B-A3B-FP8` | `llm.text.generate.v1` | 262144 |
| `qwen35b-chat` | `Qwen/Qwen3.6-35B-A3B-FP8` | `llm.chat.v1` | 262144 | | `qwen35b-chat` | `Qwen/Qwen3.6-35B-A3B-FP8` | `llm.chat.v1` | 262144 |
| `qwen38` | `Qwen3.8-27B` | `llm.text.generate.v1` | 262144 |
| `qwen38-chat` | `Qwen3.8-27B` | `llm.chat.v1` | 262144 |
Deregistered 2026-08-21 (models dropped by Hetzner): `kimi-code`,
`kimi-code-chat` (`Kimi-K2.7-Code`), `glm`, `glm-chat` (`GLM-5.2-NVFP4`),
`ds-flash-htz`, `ds-flash-htz-chat` (`DeepSeek-V4-Flash-0731`). The qwen38
pair reuses the kimi-code / kimi-code-chat wallets; the other four wallets
still hold funds and their env files remain on the host.
Shared advert parameters: price **200000 lovelace (0.2 AP3X)** flat per job, Shared advert parameters: price **200000 lovelace (0.2 AP3X)** flat per job,
bonds **1000000 lovelace (1 AP3X)** both sides, `max_processing_ms` **300000** bonds **1000000 lovelace (1 AP3X)** both sides, `max_processing_ms` **300000**
@@ -36,18 +43,18 @@ for one-off / **1800000** for chat (the session spans the whole conversation).
forwarded upstream (`OPENAI_MAX_TOKENS` unset), so the advert value only gates forwarded upstream (`OPENAI_MAX_TOKENS` unset), so the advert value only gates
what buyers may request. what buyers may request.
Names follow the brand-by-model convention; `ds-flash-htz` carries a `-htz` Names follow the brand-by-model convention; the retired `ds-flash-htz`
suffix only because `deepseek-flash-*` was already taken by the OpenRouter carried a `-htz` suffix only because `deepseek-flash-*` was already taken by
fleet serving `deepseek/deepseek-v4-flash`. the OpenRouter fleet serving `deepseek/deepseek-v4-flash`.
## 2. Prerequisites ## 2. Prerequisites
1. A Hetzner account with Inference access and an API key (usage-based billing 1. A Hetzner account with Inference access and an API key (usage-based billing
to you as the node operator — the flat 0.2 AP3X job price is a business to you as the node operator — the flat 0.2 AP3X job price is a business
choice, not cost-derived). One key is shared by all 8 suppliers; Hetzner choice, not cost-derived). One key is shared by all suppliers; Hetzner
rate limits apply to the aggregate. rate limits apply to the aggregate.
2. Eight funded supplier wallets (50 AP3X each recommended; bonds are 1 AP3X 2. One funded supplier wallet per supplier (50 AP3X each recommended; bonds
per in-flight job and returned on completion). are 1 AP3X per in-flight job and returned on completion).
3. The usual mainnet supplier deploy prerequisites (`deploy/README.md`). 3. The usual mainnet supplier deploy prerequisites (`deploy/README.md`).
4. **DNS**: one A record per supplier — `mp-suppliers-<name>.vector.apexfusion.org` 4. **DNS**: one A record per supplier — `mp-suppliers-<name>.vector.apexfusion.org`
→ `91.98.147.172`, **DNS-only/unproxied**. There is NO wildcard for → `91.98.147.172`, **DNS-only/unproxied**. There is NO wildcard for
@@ -58,24 +65,25 @@ fleet serving `deepseek/deepseek-v4-flash`.
## 3. Verify the backend before spending on-chain ## 3. Verify the backend before spending on-chain
The four model ids come from `GET https://inference.hetzner.com/api/v1/models` The model ids come from `GET https://inference.hetzner.com/api/v1/models`
(this list changes — Hetzner retires models; re-check before any advert)
and are sent **verbatim** as the upstream `model` param (the runtime uses and are sent **verbatim** as the upstream `model` param (the runtime uses
`advert.model`). Before posting adverts, smoke-test each model: `advert.model`). Before posting adverts, smoke-test each model:
```bash ```bash
curl -sS -X POST https://inference.hetzner.com/api/v1/chat/completions \ curl -sS -X POST https://inference.hetzner.com/api/v1/chat/completions \
-H "Authorization: Bearer $HETZNER_KEY" -H "Content-Type: application/json" \ -H "Authorization: Bearer $HETZNER_KEY" -H "Content-Type: application/json" \
-d '{"model":"GLM-5.2-NVFP4","messages":[{"role":"user","content":"ping"}]}' \ -d '{"model":"Qwen3.8-27B","messages":[{"role":"user","content":"ping"}]}' \
| jq '.choices[0].message.content' | jq '.choices[0].message.content'
``` ```
`choices[0].message.content` must be a non-empty string with **no `max_tokens` `choices[0].message.content` must be a non-empty string with **no `max_tokens`
sent** (matches runtime config) — the supplier throws `openai_malformed` sent** (matches runtime config) — the supplier throws `openai_malformed`
otherwise and forfeits its 1 AP3X bond per failed job. For chat suppliers also otherwise and forfeits its 1 AP3X bond per failed job. For chat suppliers also
verify a `tools`/`tool_choice` round-trip. All four models passed both checks verify a `tools`/`tool_choice` round-trip. The original four models passed
on 2026-08-11. both checks on 2026-08-11; `Qwen3.8-27B` passed both on 2026-08-21.
## 4. Per-supplier bring-up (repeat ×8) ## 4. Per-supplier bring-up (repeat per supplier)
```bash ```bash
# 1. wallet — prints privateKeyHex, publicKeyHex, pubKeyHash, address # 1. wallet — prints privateKeyHex, publicKeyHex, pubKeyHash, address