Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
1 line
110 KiB
JSON
1 line
110 KiB
JSON
{"repo": "amio-love/amio", "files": {"services/arcade-companion/wrangler.toml": {"b7520d28015f89cfa5976f8d2a08d4f88a9dca1b": {"t": 1785745358.9640944, "n": 967, "h": "07d6a3ad1ea74be3", "c": "name = \"amio-arcade-companion\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-07-16\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[triggers]\ncrons = [\"17 3 * * *\"]\n\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[durable_objects.bindings]]\nname = \"COMPANION_NONCE_GUARD\"\nclass_name = \"CompanionNonceGuardDO\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n[[migrations]]\ntag = \"v2\"\nnew_sqlite_classes = [\"CompanionNonceGuardDO\"]\n\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amio-arcade-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"migrations\"\n\n[secrets]\n# Custom companion-form generation is a shipped authenticated path, so both the\n# request-auth key ring and its text provider key must exist before deployment.\nrequired = [\"COMPANION_SERVICE_AUTH_KEYS\", \"DEEPSEEK_API_KEY\"]\n"}, "3ecb3e21573fa15a4e25e67d70276e9273c9b597": {"t": 1785750681.497527, "n": 967, "h": "07d6a3ad1ea74be3", "c": "name = \"amio-arcade-companion\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-07-16\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[triggers]\ncrons = [\"17 3 * * *\"]\n\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[durable_objects.bindings]]\nname = \"COMPANION_NONCE_GUARD\"\nclass_name = \"CompanionNonceGuardDO\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n[[migrations]]\ntag = \"v2\"\nnew_sqlite_classes = [\"CompanionNonceGuardDO\"]\n\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amio-arcade-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"migrations\"\n\n[secrets]\n# Custom companion-form generation is a shipped authenticated path, so both the\n# request-auth key ring and its text provider key must exist before deployment.\nrequired = [\"COMPANION_SERVICE_AUTH_KEYS\", \"DEEPSEEK_API_KEY\"]\n"}, "6f9b8b0a01c17735848a96bc63ddc654018b1116": {"t": 1785750682.5739498, "n": 1110, "h": "082f19d84a1a9d82", "c": "name = \"amio-arcade-companion\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-07-16\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[triggers]\ncrons = [\"17 3 * * *\"]\n\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[durable_objects.bindings]]\nname = \"COMPANION_NONCE_GUARD\"\nclass_name = \"CompanionNonceGuardDO\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n[[migrations]]\ntag = \"v2\"\nnew_sqlite_classes = [\"CompanionNonceGuardDO\"]\n\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amio-arcade-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"migrations\"\n\n[secrets]\n# DEEPSEEK_API_KEY is optional at runtime (memory-consolidation LLM only) and is\n# not part of the auth / account-registration path. Platform AI provider work is\n# paused via the platform_ai_control row, so the worker must be deployable without\n# a paid provider key; require only the key the request-auth path depends on.\nrequired = [\"COMPANION_SERVICE_AUTH_KEYS\"]\n"}, "e673a659f2af3f7d9da2dfd71fd1022d8e2dc37f": {"t": 1785750683.7267728, "n": 1075, "h": "7baf6d38f63dcaaa", "c": "name = \"amio-arcade-companion\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-07-16\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[durable_objects.bindings]]\nname = \"COMPANION_NONCE_GUARD\"\nclass_name = \"CompanionNonceGuardDO\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n[[migrations]]\ntag = \"v2\"\nnew_sqlite_classes = [\"CompanionNonceGuardDO\"]\n\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amio-arcade-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"migrations\"\n\n[secrets]\n# DEEPSEEK_API_KEY is optional at runtime (memory-consolidation LLM only) and is\n# not part of the auth / account-registration path. Platform AI provider work is\n# paused via the platform_ai_control row, so the worker must be deployable without\n# a paid provider key; require only the key the request-auth path depends on.\nrequired = [\"COMPANION_SERVICE_AUTH_KEYS\"]\n"}, "1e8aaeed3c9e89154683b3a028453fe1a915b2ee": {"t": 1785750685.2314806, "n": 772, "h": "172b58c74135e3df", "c": "name = \"amio-arcade-companion\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-07-16\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[durable_objects.bindings]]\nname = \"COMPANION_NONCE_GUARD\"\nclass_name = \"CompanionNonceGuardDO\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n[[migrations]]\ntag = \"v2\"\nnew_sqlite_classes = [\"CompanionNonceGuardDO\"]\n\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amio-arcade-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"migrations\"\n\n[secrets]\nrequired = [\"COMPANION_SERVICE_AUTH_KEYS\", \"DEEPSEEK_API_KEY\"]\n"}, "7b6bc7faafb01e152fd175f4f589e9bfd69ba8c4": {"t": 1785750686.312383, "n": 752, "h": "ba8d6858ac405277", "c": "name = \"amio-arcade-companion\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-07-16\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[durable_objects.bindings]]\nname = \"COMPANION_NONCE_GUARD\"\nclass_name = \"CompanionNonceGuardDO\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n[[migrations]]\ntag = \"v2\"\nnew_sqlite_classes = [\"CompanionNonceGuardDO\"]\n\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amio-arcade-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"migrations\"\n\n[secrets]\nrequired = [\"COMPANION_SERVICE_AUTH_KEYS\"]\n"}, "7650750e11df000aea54dff23ee42fffd01435f6": {"t": 1785750687.3724687, "n": 743, "h": "7080e6ab94fd9f9a", "c": "name = \"arcade-companion\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-07-16\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[durable_objects.bindings]]\nname = \"COMPANION_NONCE_GUARD\"\nclass_name = \"CompanionNonceGuardDO\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n[[migrations]]\ntag = \"v2\"\nnew_sqlite_classes = [\"CompanionNonceGuardDO\"]\n\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amiclaw-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"migrations\"\n\n[secrets]\nrequired = [\"COMPANION_SERVICE_AUTH_KEYS\"]\n"}, "56d70490eb61f0783588cdec794f34b9b5bc4fb6": {"t": 1785750688.4551408, "n": 689, "h": "a2dd269e438ccbd9", "c": "name = \"arcade-companion\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-07-16\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[durable_objects.bindings]]\nname = \"COMPANION_NONCE_GUARD\"\nclass_name = \"CompanionNonceGuardDO\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n[[migrations]]\ntag = \"v2\"\nnew_sqlite_classes = [\"CompanionNonceGuardDO\"]\n\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amiclaw-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"migrations\"\n"}, "3fa7ac18253a9186265761c1fee31e2aaee60bd3": {"t": 1785750689.5256064, "n": 517, "h": "e93bfdc18591244e", "c": "name = \"arcade-companion\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-07-16\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amiclaw-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"migrations\"\n"}, "d4328c76f9741b6ac101e94bb7bbf5527227651c": {"t": 1785750690.5976079, "n": 517, "h": "49bc92d86d87d608", "c": "name = \"arcade-companion\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-07-17\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amiclaw-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"migrations\"\n"}, "9417362eba04bb16d6a41be46731c35954e909a7": {"t": 1786067354.310909, "n": 1110, "h": "082f19d84a1a9d82", "c": "name = \"amio-arcade-companion\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-07-16\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[triggers]\ncrons = [\"17 3 * * *\"]\n\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[durable_objects.bindings]]\nname = \"COMPANION_NONCE_GUARD\"\nclass_name = \"CompanionNonceGuardDO\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n[[migrations]]\ntag = \"v2\"\nnew_sqlite_classes = [\"CompanionNonceGuardDO\"]\n\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amio-arcade-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"migrations\"\n\n[secrets]\n# DEEPSEEK_API_KEY is optional at runtime (memory-consolidation LLM only) and is\n# not part of the auth / account-registration path. Platform AI provider work is\n# paused via the platform_ai_control row, so the worker must be deployable without\n# a paid provider key; require only the key the request-auth path depends on.\nrequired = [\"COMPANION_SERVICE_AUTH_KEYS\"]\n"}, "454e0fe7b118476af391de94f175c74b42608d5e": {"t": 1786068237.0369346, "n": 967, "h": "07d6a3ad1ea74be3", "c": "name = \"amio-arcade-companion\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-07-16\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[triggers]\ncrons = [\"17 3 * * *\"]\n\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[durable_objects.bindings]]\nname = \"COMPANION_NONCE_GUARD\"\nclass_name = \"CompanionNonceGuardDO\"\n\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n[[migrations]]\ntag = \"v2\"\nnew_sqlite_classes = [\"CompanionNonceGuardDO\"]\n\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amio-arcade-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"migrations\"\n\n[secrets]\n# Custom companion-form generation is a shipped authenticated path, so both the\n# request-auth key ring and its text provider key must exist before deployment.\nrequired = [\"COMPANION_SERVICE_AUTH_KEYS\", \"DEEPSEEK_API_KEY\"]\n"}}, "services/arcade-platform-ai/wrangler.toml": {"b7520d28015f89cfa5976f8d2a08d4f88a9dca1b": {"t": 1785745360.3269517, "n": 8275, "h": "0c87d3659fda3966", "c": "# Platform AI Interface — standalone Cloudflare Worker.\n#\n# This is the repo's first independent Worker deploy unit. It hosts the\n# Durable Object that carries the per-session WebSocket voice pipeline\n# (STT -> LLM -> TTS). The DO/WebSocket server implementation and the real\n# provider adapters land in later rounds (R2/R3); this file pins the\n# deploy-time bindings so those rounds have a stable contract.\n#\n# TOML syntax verified against the current Cloudflare docs (June 2026):\n# - Durable Objects bindings + migrations:\n# https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/\n# - KV namespaces, routes, vars:\n# https://developers.cloudflare.com/workers/wrangler/configuration/\n\nname = \"amio-arcade-platform-ai\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-06-08\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n# --- Observability: capture this Worker's (and its DOs') logs so a single live\n# voice turn's per-hop `turn-trace` lines are queryable in Workers\n# observability. `head_sampling_rate = 1` keeps 100% of invocations — required\n# to read THE one turn being diagnosed (any rate < 1 risks dropping it).\n# https://developers.cloudflare.com/workers/observability/logs/workers-logs/\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n# nodejs_compat is required by the Cloudflare Agents SDK: VoiceSessionDO extends\n# the SDK `Agent` base, which imports `node:async_hooks` (AsyncLocalStorage).\n# The voice provider adapters themselves still target the standard Workers\n# fetch / WebSocket / streams APIs.\n\n# --- Durable Object: per-session voice pipeline state holder ---\n# The DO owns one voice session's conversation history, current phase, and the\n# WebSocket long-connection. Single-point serialization keeps turns ordered.\n# Implementation deferred to R3; the binding + class name are pinned now.\n[[durable_objects.bindings]]\nname = \"VOICE_SESSION\"\nclass_name = \"VoiceSessionDO\"\n\n# SQLite-backed DO storage (the recommended backend for new classes). The\n# migration tag is the ordered changelog of DO class lifecycle events.\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"VoiceSessionDO\"]\n\n# --- Companion service: the sole persistence owner ---\n# Voice session boundaries call this internal RPC binding. Platform AI receives\n# no database or consolidator binding.\n[[services]]\nbinding = \"COMPANION\"\nservice = \"amio-arcade-companion\"\n\n# --- AUTH KV: shared session keyspace owned by auth-session ---\n# The Worker self-binds the auth-session AUTH namespace and reuses the shared\n# session-reader during the WS upgrade handshake and the HTTP intent routes. Those\n# routes also write coarse, non-atomic per-user cost-throttle counters under\n# `ratelimit:shadow-intent:user:*` (shadow-chase) and `ratelimit:proxy-social:user:*`\n# (companion-proxy-social) — independent budgets; neither mutates session records.\n[[kv_namespaces]]\nbinding = \"AUTH\"\nid = \"c4a64d33de2f406e825e6249e828f84d\"\npreview_id = \"5d22a502cb5246408d7f6e5af01a4f7b\"\n\n# --- Optional legacy USAGE KV mirror ---\n# The session DO may flush ONE best-effort record per ended voice session — key\n# `usage:{date}:{user_id}:{session_id}` (UTC date at flush time, session_id a\n# per-session UUID), value legacy session counters. This mirror is neither\n# authoritative nor billing-grade. Unified usage in Companion-owned D1 is the\n# authority. KV absence or write failure must not affect access, quota, usage\n# accounting, or session close. Preview intentionally omits this binding.\n# Dedicated namespace; do not reuse LEADERBOARD or AUTH.\n[[kv_namespaces]]\nbinding = \"USAGE\"\nid = \"5bca263e7860462ea0bef90885b07c1b\"\n\n# --- Same-origin WS route on the canonical zone ---\n# Mounting under arcade.amio.love (same zone as the Platform SPA / /api/*) is the\n# structural prerequisite for the session cookie to ride along on the WS\n# upgrade — a path-prefix route on the existing zone, not a whole-domain custom\n# domain. The /ai-ws/* prefix is pinned at L2 and must not drift.\n[[routes]]\npattern = \"arcade.amio.love/ai-ws/*\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/shadow-chase\"\nzone_name = \"amio.love\"\n\n# Companion-proxy-social bounded intent routes — same-zone, path-exact (mirrors\n# the shadow-chase route above) so the session cookie rides along on the POST.\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/companion-proxy-message\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.love\"\n\n# --- Apex mirror routes (canonical root domain) ---\n# The single Pages app now serves the apex host amio.love as the canonical entry\n# (arcade.amio.love still serves during the transition). Clients build the voice\n# WS/intent URLs SAME-ORIGIN from `location.host` (`buildSessionUrl` in\n# packages/arcade-shared/voice/voice-session-protocol.ts), so an apex-served\n# player opens `wss://amio.love/ai-ws/...`. Every arcade route below is mirrored\n# on the apex host (same zone, same path-exact intent routes) so the voice\n# pipeline is routed on the canonical domain and the session cookie rides along.\n# www.amio.love is intentionally omitted — it 301-redirects to the apex.\n[[routes]]\npattern = \"amio.love/ai-ws/*\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"amio.love/ai-intent/shadow-chase\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"amio.love/ai-intent/companion-proxy-message\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"amio.love/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.love\"\n\n# --- Plain-text vars ---\n[vars]\n# Dev-only auth bypass. When set (dev/preview), the WS handshake's\n# session-reader step is replaced by a fixed dev identity; the prod build\n# compiles this branch out. Mounting point / \"validate-at-handshake, reject if\n# invalid\" shape stays fixed — only the session lookup is stubbed.\nDEV_AUTH_BYPASS = \"false\"\n\n[secrets]\nrequired = [\n \"COMPANION_SUBJECT_ISSUER_SECRET\",\n \"COMPANION_SERVICE_AUTH_KEY_ID\",\n \"COMPANION_SERVICE_AUTH_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"VOLC_API_KEY\",\n \"VOLC_TTS_VOICE_COMPANION_WARM\",\n \"VOLC_TTS_VOICE_COMPANION_BRIGHT\",\n \"VOLC_TTS_VOICE_COMPANION_CALM\",\n]\n\n# --- Secrets (set via `wrangler secret put`, NEVER committed as plaintext) ---\n# Provider API keys and any system-prompt material live only server-side as\n# Cloudflare secrets. Set each with `wrangler secret put <NAME>`:\n# DEEPSEEK_API_KEY — DeepSeek (OpenAI-compatible) LLM key.\n# VOLC_API_KEY — Volcengine (火山) console API key, sent as the single\n# X-Api-Key header (new-console-auth). Grants the Doubao\n# 2.0 speech stack (seedasr ASR 2.0 + Doubao TTS 2.0).\n# VOLC_TTS_VOICE_COMPANION_WARM — Volcengine voice_type for companion-warm.\n# VOLC_TTS_VOICE_COMPANION_BRIGHT — Volcengine voice_type for companion-bright.\n# VOLC_TTS_VOICE_COMPANION_CALM — Volcengine voice_type for companion-calm.\n# COMPANION_SUBJECT_ISSUER_SECRET — stable base64url subject-issuer key shared\n# with the server identity boundary only.\n# COMPANION_SERVICE_AUTH_KEY_ID — active request-signing key id.\n# COMPANION_SERVICE_AUTH_KEY — 32-byte lowercase-hex request-signing key;\n# its value must match one entry in the\n# Companion Worker's auth key ring.\n# These are referenced by the provider adapters; declared here only as\n# documentation so the deploy operator knows what to provision.\n#\n# The legacy VOLC_APP_ID / VOLC_ACCESS_KEY pair is no longer read by the adapter\n# (new-console-auth X-Api-Key replaced it; the old pair had no Doubao 2.0 speech\n# grant). Any existing VOLC_APP_ID / VOLC_ACCESS_KEY secrets are now inert and\n# may be deleted with `wrangler secret delete`.\n#\n# No VOLC_SECRET_KEY: the v3 big-model endpoints this adapter targets — seedasr\n# streaming ASR 2.0 (/api/v3/sauc/bigmodel_async) and Doubao TTS 2.0\n# bidirectional (/api/v3/tts/bidirection) — authenticate purely via the\n# X-Api-Key / X-Api-Resource-Id token headers. They do NOT use the legacy\n# `Authorization: HMAC256` signature scheme, so no secret key is needed. (The\n# secret-key signature path is the older console-auth method for the v1/v2\n# endpoints, which this adapter does not use.)\n"}, "c880186abc4a9de85e5bccdefc3b6cdadd1ef616": {"t": 1785750681.9666476, "n": 8275, "h": "0c87d3659fda3966", "c": "# Platform AI Interface — standalone Cloudflare Worker.\n#\n# This is the repo's first independent Worker deploy unit. It hosts the\n# Durable Object that carries the per-session WebSocket voice pipeline\n# (STT -> LLM -> TTS). The DO/WebSocket server implementation and the real\n# provider adapters land in later rounds (R2/R3); this file pins the\n# deploy-time bindings so those rounds have a stable contract.\n#\n# TOML syntax verified against the current Cloudflare docs (June 2026):\n# - Durable Objects bindings + migrations:\n# https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/\n# - KV namespaces, routes, vars:\n# https://developers.cloudflare.com/workers/wrangler/configuration/\n\nname = \"amio-arcade-platform-ai\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-06-08\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n# --- Observability: capture this Worker's (and its DOs') logs so a single live\n# voice turn's per-hop `turn-trace` lines are queryable in Workers\n# observability. `head_sampling_rate = 1` keeps 100% of invocations — required\n# to read THE one turn being diagnosed (any rate < 1 risks dropping it).\n# https://developers.cloudflare.com/workers/observability/logs/workers-logs/\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n# nodejs_compat is required by the Cloudflare Agents SDK: VoiceSessionDO extends\n# the SDK `Agent` base, which imports `node:async_hooks` (AsyncLocalStorage).\n# The voice provider adapters themselves still target the standard Workers\n# fetch / WebSocket / streams APIs.\n\n# --- Durable Object: per-session voice pipeline state holder ---\n# The DO owns one voice session's conversation history, current phase, and the\n# WebSocket long-connection. Single-point serialization keeps turns ordered.\n# Implementation deferred to R3; the binding + class name are pinned now.\n[[durable_objects.bindings]]\nname = \"VOICE_SESSION\"\nclass_name = \"VoiceSessionDO\"\n\n# SQLite-backed DO storage (the recommended backend for new classes). The\n# migration tag is the ordered changelog of DO class lifecycle events.\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"VoiceSessionDO\"]\n\n# --- Companion service: the sole persistence owner ---\n# Voice session boundaries call this internal RPC binding. Platform AI receives\n# no database or consolidator binding.\n[[services]]\nbinding = \"COMPANION\"\nservice = \"amio-arcade-companion\"\n\n# --- AUTH KV: shared session keyspace owned by auth-session ---\n# The Worker self-binds the auth-session AUTH namespace and reuses the shared\n# session-reader during the WS upgrade handshake and the HTTP intent routes. Those\n# routes also write coarse, non-atomic per-user cost-throttle counters under\n# `ratelimit:shadow-intent:user:*` (shadow-chase) and `ratelimit:proxy-social:user:*`\n# (companion-proxy-social) — independent budgets; neither mutates session records.\n[[kv_namespaces]]\nbinding = \"AUTH\"\nid = \"c4a64d33de2f406e825e6249e828f84d\"\npreview_id = \"5d22a502cb5246408d7f6e5af01a4f7b\"\n\n# --- Optional legacy USAGE KV mirror ---\n# The session DO may flush ONE best-effort record per ended voice session — key\n# `usage:{date}:{user_id}:{session_id}` (UTC date at flush time, session_id a\n# per-session UUID), value legacy session counters. This mirror is neither\n# authoritative nor billing-grade. Unified usage in Companion-owned D1 is the\n# authority. KV absence or write failure must not affect access, quota, usage\n# accounting, or session close. Preview intentionally omits this binding.\n# Dedicated namespace; do not reuse LEADERBOARD or AUTH.\n[[kv_namespaces]]\nbinding = \"USAGE\"\nid = \"5bca263e7860462ea0bef90885b07c1b\"\n\n# --- Same-origin WS route on the canonical zone ---\n# Mounting under arcade.amio.love (same zone as the Platform SPA / /api/*) is the\n# structural prerequisite for the session cookie to ride along on the WS\n# upgrade — a path-prefix route on the existing zone, not a whole-domain custom\n# domain. The /ai-ws/* prefix is pinned at L2 and must not drift.\n[[routes]]\npattern = \"arcade.amio.love/ai-ws/*\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/shadow-chase\"\nzone_name = \"amio.love\"\n\n# Companion-proxy-social bounded intent routes — same-zone, path-exact (mirrors\n# the shadow-chase route above) so the session cookie rides along on the POST.\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/companion-proxy-message\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.love\"\n\n# --- Apex mirror routes (canonical root domain) ---\n# The single Pages app now serves the apex host amio.love as the canonical entry\n# (arcade.amio.love still serves during the transition). Clients build the voice\n# WS/intent URLs SAME-ORIGIN from `location.host` (`buildSessionUrl` in\n# packages/arcade-shared/voice/voice-session-protocol.ts), so an apex-served\n# player opens `wss://amio.love/ai-ws/...`. Every arcade route below is mirrored\n# on the apex host (same zone, same path-exact intent routes) so the voice\n# pipeline is routed on the canonical domain and the session cookie rides along.\n# www.amio.love is intentionally omitted — it 301-redirects to the apex.\n[[routes]]\npattern = \"amio.love/ai-ws/*\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"amio.love/ai-intent/shadow-chase\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"amio.love/ai-intent/companion-proxy-message\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"amio.love/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.love\"\n\n# --- Plain-text vars ---\n[vars]\n# Dev-only auth bypass. When set (dev/preview), the WS handshake's\n# session-reader step is replaced by a fixed dev identity; the prod build\n# compiles this branch out. Mounting point / \"validate-at-handshake, reject if\n# invalid\" shape stays fixed — only the session lookup is stubbed.\nDEV_AUTH_BYPASS = \"false\"\n\n[secrets]\nrequired = [\n \"COMPANION_SUBJECT_ISSUER_SECRET\",\n \"COMPANION_SERVICE_AUTH_KEY_ID\",\n \"COMPANION_SERVICE_AUTH_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"VOLC_API_KEY\",\n \"VOLC_TTS_VOICE_COMPANION_WARM\",\n \"VOLC_TTS_VOICE_COMPANION_BRIGHT\",\n \"VOLC_TTS_VOICE_COMPANION_CALM\",\n]\n\n# --- Secrets (set via `wrangler secret put`, NEVER committed as plaintext) ---\n# Provider API keys and any system-prompt material live only server-side as\n# Cloudflare secrets. Set each with `wrangler secret put <NAME>`:\n# DEEPSEEK_API_KEY — DeepSeek (OpenAI-compatible) LLM key.\n# VOLC_API_KEY — Volcengine (火山) console API key, sent as the single\n# X-Api-Key header (new-console-auth). Grants the Doubao\n# 2.0 speech stack (seedasr ASR 2.0 + Doubao TTS 2.0).\n# VOLC_TTS_VOICE_COMPANION_WARM — Volcengine voice_type for companion-warm.\n# VOLC_TTS_VOICE_COMPANION_BRIGHT — Volcengine voice_type for companion-bright.\n# VOLC_TTS_VOICE_COMPANION_CALM — Volcengine voice_type for companion-calm.\n# COMPANION_SUBJECT_ISSUER_SECRET — stable base64url subject-issuer key shared\n# with the server identity boundary only.\n# COMPANION_SERVICE_AUTH_KEY_ID — active request-signing key id.\n# COMPANION_SERVICE_AUTH_KEY — 32-byte lowercase-hex request-signing key;\n# its value must match one entry in the\n# Companion Worker's auth key ring.\n# These are referenced by the provider adapters; declared here only as\n# documentation so the deploy operator knows what to provision.\n#\n# The legacy VOLC_APP_ID / VOLC_ACCESS_KEY pair is no longer read by the adapter\n# (new-console-auth X-Api-Key replaced it; the old pair had no Doubao 2.0 speech\n# grant). Any existing VOLC_APP_ID / VOLC_ACCESS_KEY secrets are now inert and\n# may be deleted with `wrangler secret delete`.\n#\n# No VOLC_SECRET_KEY: the v3 big-model endpoints this adapter targets — seedasr\n# streaming ASR 2.0 (/api/v3/sauc/bigmodel_async) and Doubao TTS 2.0\n# bidirectional (/api/v3/tts/bidirection) — authenticate purely via the\n# X-Api-Key / X-Api-Resource-Id token headers. They do NOT use the legacy\n# `Authorization: HMAC256` signature scheme, so no secret key is needed. (The\n# secret-key signature path is the older console-auth method for the v1/v2\n# endpoints, which this adapter does not use.)\n"}, "1e8aaeed3c9e89154683b3a028453fe1a915b2ee": {"t": 1785750683.084792, "n": 7272, "h": "c25495c21eb664d6", "c": "# Platform AI Interface — standalone Cloudflare Worker.\n#\n# This is the repo's first independent Worker deploy unit. It hosts the\n# Durable Object that carries the per-session WebSocket voice pipeline\n# (STT -> LLM -> TTS). The DO/WebSocket server implementation and the real\n# provider adapters land in later rounds (R2/R3); this file pins the\n# deploy-time bindings so those rounds have a stable contract.\n#\n# TOML syntax verified against the current Cloudflare docs (June 2026):\n# - Durable Objects bindings + migrations:\n# https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/\n# - KV namespaces, routes, vars:\n# https://developers.cloudflare.com/workers/wrangler/configuration/\n\nname = \"amio-arcade-platform-ai\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-06-08\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n# --- Observability: capture this Worker's (and its DOs') logs so a single live\n# voice turn's per-hop `turn-trace` lines are queryable in Workers\n# observability. `head_sampling_rate = 1` keeps 100% of invocations — required\n# to read THE one turn being diagnosed (any rate < 1 risks dropping it).\n# https://developers.cloudflare.com/workers/observability/logs/workers-logs/\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n# nodejs_compat is required by the Cloudflare Agents SDK: VoiceSessionDO extends\n# the SDK `Agent` base, which imports `node:async_hooks` (AsyncLocalStorage).\n# The voice provider adapters themselves still target the standard Workers\n# fetch / WebSocket / streams APIs.\n\n# --- Durable Object: per-session voice pipeline state holder ---\n# The DO owns one voice session's conversation history, current phase, and the\n# WebSocket long-connection. Single-point serialization keeps turns ordered.\n# Implementation deferred to R3; the binding + class name are pinned now.\n[[durable_objects.bindings]]\nname = \"VOICE_SESSION\"\nclass_name = \"VoiceSessionDO\"\n\n# SQLite-backed DO storage (the recommended backend for new classes). The\n# migration tag is the ordered changelog of DO class lifecycle events.\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"VoiceSessionDO\"]\n\n# --- Companion service: the sole persistence owner ---\n# Voice session boundaries call this internal RPC binding. Platform AI receives\n# no database or consolidator binding.\n[[services]]\nbinding = \"COMPANION\"\nservice = \"amio-arcade-companion\"\n\n# --- AUTH KV: shared session keyspace owned by auth-session ---\n# The Worker self-binds the auth-session AUTH namespace and reuses the shared\n# session-reader during the WS upgrade handshake and the HTTP intent routes. Those\n# routes also write coarse, non-atomic per-user cost-throttle counters under\n# `ratelimit:shadow-intent:user:*` (shadow-chase) and `ratelimit:proxy-social:user:*`\n# (companion-proxy-social) — independent budgets; neither mutates session records.\n[[kv_namespaces]]\nbinding = \"AUTH\"\nid = \"c4a64d33de2f406e825e6249e828f84d\"\npreview_id = \"5d22a502cb5246408d7f6e5af01a4f7b\"\n\n# --- Optional legacy USAGE KV mirror ---\n# The session DO may flush ONE best-effort record per ended voice session — key\n# `usage:{date}:{user_id}:{session_id}` (UTC date at flush time, session_id a\n# per-session UUID), value legacy session counters. This mirror is neither\n# authoritative nor billing-grade. Unified usage in Companion-owned D1 is the\n# authority. KV absence or write failure must not affect access, quota, usage\n# accounting, or session close. Preview intentionally omits this binding.\n# Dedicated namespace; do not reuse LEADERBOARD or AUTH.\n[[kv_namespaces]]\nbinding = \"USAGE\"\nid = \"5bca263e7860462ea0bef90885b07c1b\"\n\n# --- Same-origin WS route on the canonical zone ---\n# Mounting under arcade.amio.love (same zone as the Platform SPA / /api/*) is the\n# structural prerequisite for the session cookie to ride along on the WS\n# upgrade — a path-prefix route on the existing zone, not a whole-domain custom\n# domain. The /ai-ws/* prefix is pinned at L2 and must not drift.\n[[routes]]\npattern = \"arcade.amio.love/ai-ws/*\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/shadow-chase\"\nzone_name = \"amio.love\"\n\n# Companion-proxy-social bounded intent routes — same-zone, path-exact (mirrors\n# the shadow-chase route above) so the session cookie rides along on the POST.\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/companion-proxy-message\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.love\"\n\n# --- Plain-text vars ---\n[vars]\n# Dev-only auth bypass. When set (dev/preview), the WS handshake's\n# session-reader step is replaced by a fixed dev identity; the prod build\n# compiles this branch out. Mounting point / \"validate-at-handshake, reject if\n# invalid\" shape stays fixed — only the session lookup is stubbed.\nDEV_AUTH_BYPASS = \"false\"\n\n[secrets]\nrequired = [\n \"COMPANION_SUBJECT_ISSUER_SECRET\",\n \"COMPANION_SERVICE_AUTH_KEY_ID\",\n \"COMPANION_SERVICE_AUTH_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"VOLC_API_KEY\",\n \"VOLC_TTS_VOICE_COMPANION_WARM\",\n \"VOLC_TTS_VOICE_COMPANION_BRIGHT\",\n \"VOLC_TTS_VOICE_COMPANION_CALM\",\n]\n\n# --- Secrets (set via `wrangler secret put`, NEVER committed as plaintext) ---\n# Provider API keys and any system-prompt material live only server-side as\n# Cloudflare secrets. Set each with `wrangler secret put <NAME>`:\n# DEEPSEEK_API_KEY — DeepSeek (OpenAI-compatible) LLM key.\n# VOLC_API_KEY — Volcengine (火山) console API key, sent as the single\n# X-Api-Key header (new-console-auth). Grants the Doubao\n# 2.0 speech stack (seedasr ASR 2.0 + Doubao TTS 2.0).\n# VOLC_TTS_VOICE_COMPANION_WARM — Volcengine voice_type for companion-warm.\n# VOLC_TTS_VOICE_COMPANION_BRIGHT — Volcengine voice_type for companion-bright.\n# VOLC_TTS_VOICE_COMPANION_CALM — Volcengine voice_type for companion-calm.\n# COMPANION_SUBJECT_ISSUER_SECRET — stable base64url subject-issuer key shared\n# with the server identity boundary only.\n# COMPANION_SERVICE_AUTH_KEY_ID — active request-signing key id.\n# COMPANION_SERVICE_AUTH_KEY — 32-byte lowercase-hex request-signing key;\n# its value must match one entry in the\n# Companion Worker's auth key ring.\n# These are referenced by the provider adapters; declared here only as\n# documentation so the deploy operator knows what to provision.\n#\n# The legacy VOLC_APP_ID / VOLC_ACCESS_KEY pair is no longer read by the adapter\n# (new-console-auth X-Api-Key replaced it; the old pair had no Doubao 2.0 speech\n# grant). Any existing VOLC_APP_ID / VOLC_ACCESS_KEY secrets are now inert and\n# may be deleted with `wrangler secret delete`.\n#\n# No VOLC_SECRET_KEY: the v3 big-model endpoints this adapter targets — seedasr\n# streaming ASR 2.0 (/api/v3/sauc/bigmodel_async) and Doubao TTS 2.0\n# bidirectional (/api/v3/tts/bidirection) — authenticate purely via the\n# X-Api-Key / X-Api-Resource-Id token headers. They do NOT use the legacy\n# `Authorization: HMAC256` signature scheme, so no secret key is needed. (The\n# secret-key signature path is the older console-auth method for the v1/v2\n# endpoints, which this adapter does not use.)\n"}, "7b6bc7faafb01e152fd175f4f589e9bfd69ba8c4": {"t": 1785750684.184523, "n": 7407, "h": "08a01ab11618da00", "c": "# Platform AI Interface — standalone Cloudflare Worker.\n#\n# This is the repo's first independent Worker deploy unit. It hosts the\n# Durable Object that carries the per-session WebSocket voice pipeline\n# (STT -> LLM -> TTS). The DO/WebSocket server implementation and the real\n# provider adapters land in later rounds (R2/R3); this file pins the\n# deploy-time bindings so those rounds have a stable contract.\n#\n# TOML syntax verified against the current Cloudflare docs (June 2026):\n# - Durable Objects bindings + migrations:\n# https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/\n# - KV namespaces, routes, vars:\n# https://developers.cloudflare.com/workers/wrangler/configuration/\n\nname = \"amio-arcade-platform-ai\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-06-08\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n# --- Observability: capture this Worker's (and its DOs') logs so a single live\n# voice turn's per-hop `turn-trace` lines are queryable in Workers\n# observability. `head_sampling_rate = 1` keeps 100% of invocations — required\n# to read THE one turn being diagnosed (any rate < 1 risks dropping it).\n# https://developers.cloudflare.com/workers/observability/logs/workers-logs/\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n# nodejs_compat is required by the Cloudflare Agents SDK: VoiceSessionDO extends\n# the SDK `Agent` base, which imports `node:async_hooks` (AsyncLocalStorage).\n# The voice provider adapters themselves still target the standard Workers\n# fetch / WebSocket / streams APIs.\n\n# --- Durable Object: per-session voice pipeline state holder ---\n# The DO owns one voice session's conversation history, current phase, and the\n# WebSocket long-connection. Single-point serialization keeps turns ordered.\n# Implementation deferred to R3; the binding + class name are pinned now.\n[[durable_objects.bindings]]\nname = \"VOICE_SESSION\"\nclass_name = \"VoiceSessionDO\"\n\n# SQLite-backed DO storage (the recommended backend for new classes). The\n# migration tag is the ordered changelog of DO class lifecycle events.\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"VoiceSessionDO\"]\n\n# --- Companion service: the sole persistence owner ---\n# Voice session boundaries call this internal RPC binding. Platform AI receives\n# no database or consolidator binding.\n[[services]]\nbinding = \"COMPANION\"\nservice = \"amio-arcade-companion\"\n\n# --- AUTH KV: shared session keyspace owned by auth-session ---\n# The Worker self-binds the auth-session AUTH namespace and reuses the shared\n# session-reader during the WS upgrade handshake and the HTTP intent routes. Those\n# routes also write coarse, non-atomic per-user cost-throttle counters under\n# `ratelimit:shadow-intent:user:*` (shadow-chase) and `ratelimit:proxy-social:user:*`\n# (companion-proxy-social) — independent budgets; neither mutates session records.\n[[kv_namespaces]]\nbinding = \"AUTH\"\nid = \"c4a64d33de2f406e825e6249e828f84d\"\npreview_id = \"5d22a502cb5246408d7f6e5af01a4f7b\"\n\n# --- USAGE KV: per-session usage metering records ---\n# The session DO flushes ONE write-once record per ended voice session — key\n# `usage:{date}:{user_id}:{session_id}` (UTC date at flush time, session_id a\n# per-session UUID), value the session's usage counters (LLM tokens + STT/TTS\n# seconds + STT source annotation). Billing-grade data: no TTL. The write is\n# fail-open (a KV failure is logged, never blocks session close) and the\n# binding is OPTIONAL at runtime — a dev/demo config without it just skips the\n# flush. Dedicated namespace; do NOT reuse LEADERBOARD or AUTH. `id` is the\n# production namespace id, filled at deploy wiring time (placeholder until\n# then, same as AUTH above).\n[[kv_namespaces]]\nbinding = \"USAGE\"\nid = \"5bca263e7860462ea0bef90885b07c1b\"\n\n# --- Same-origin WS route on the canonical zone ---\n# Mounting under arcade.amio.love (same zone as the Platform SPA / /api/*) is the\n# structural prerequisite for the session cookie to ride along on the WS\n# upgrade — a path-prefix route on the existing zone, not a whole-domain custom\n# domain. The /ai-ws/* prefix is pinned at L2 and must not drift.\n[[routes]]\npattern = \"arcade.amio.love/ai-ws/*\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/shadow-chase\"\nzone_name = \"amio.love\"\n\n# Companion-proxy-social bounded intent routes — same-zone, path-exact (mirrors\n# the shadow-chase route above) so the session cookie rides along on the POST.\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/companion-proxy-message\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.love\"\n\n# --- Plain-text vars ---\n[vars]\n# Dev-only auth bypass. When set (dev/preview), the WS handshake's\n# session-reader step is replaced by a fixed dev identity; the prod build\n# compiles this branch out. Mounting point / \"validate-at-handshake, reject if\n# invalid\" shape stays fixed — only the session lookup is stubbed.\nDEV_AUTH_BYPASS = \"false\"\n\n[secrets]\nrequired = [\n \"COMPANION_SUBJECT_ISSUER_SECRET\",\n \"COMPANION_SERVICE_AUTH_KEY_ID\",\n \"COMPANION_SERVICE_AUTH_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"VOLC_API_KEY\",\n \"VOLC_TTS_VOICE_COMPANION_WARM\",\n \"VOLC_TTS_VOICE_COMPANION_BRIGHT\",\n \"VOLC_TTS_VOICE_COMPANION_CALM\",\n]\n\n# --- Secrets (set via `wrangler secret put`, NEVER committed as plaintext) ---\n# Provider API keys and any system-prompt material live only server-side as\n# Cloudflare secrets. Set each with `wrangler secret put <NAME>`:\n# DEEPSEEK_API_KEY — DeepSeek (OpenAI-compatible) LLM key.\n# VOLC_API_KEY — Volcengine (火山) console API key, sent as the single\n# X-Api-Key header (new-console-auth). Grants the Doubao\n# 2.0 speech stack (seedasr ASR 2.0 + Doubao TTS 2.0).\n# VOLC_TTS_VOICE_COMPANION_WARM — Volcengine voice_type for companion-warm.\n# VOLC_TTS_VOICE_COMPANION_BRIGHT — Volcengine voice_type for companion-bright.\n# VOLC_TTS_VOICE_COMPANION_CALM — Volcengine voice_type for companion-calm.\n# COMPANION_SUBJECT_ISSUER_SECRET — stable base64url subject-issuer key shared\n# with the server identity boundary only.\n# COMPANION_SERVICE_AUTH_KEY_ID — active request-signing key id.\n# COMPANION_SERVICE_AUTH_KEY — 32-byte lowercase-hex request-signing key;\n# its value must match one entry in the\n# Companion Worker's auth key ring.\n# These are referenced by the provider adapters; declared here only as\n# documentation so the deploy operator knows what to provision.\n#\n# The legacy VOLC_APP_ID / VOLC_ACCESS_KEY pair is no longer read by the adapter\n# (new-console-auth X-Api-Key replaced it; the old pair had no Doubao 2.0 speech\n# grant). Any existing VOLC_APP_ID / VOLC_ACCESS_KEY secrets are now inert and\n# may be deleted with `wrangler secret delete`.\n#\n# No VOLC_SECRET_KEY: the v3 big-model endpoints this adapter targets — seedasr\n# streaming ASR 2.0 (/api/v3/sauc/bigmodel_async) and Doubao TTS 2.0\n# bidirectional (/api/v3/tts/bidirection) — authenticate purely via the\n# X-Api-Key / X-Api-Resource-Id token headers. They do NOT use the legacy\n# `Authorization: HMAC256` signature scheme, so no secret key is needed. (The\n# secret-key signature path is the older console-auth method for the v1/v2\n# endpoints, which this adapter does not use.)\n"}, "7650750e11df000aea54dff23ee42fffd01435f6": {"t": 1785750685.2713761, "n": 7380, "h": "655d0f851b3caa2e", "c": "# Platform AI Interface — standalone Cloudflare Worker.\n#\n# This is the repo's first independent Worker deploy unit. It hosts the\n# Durable Object that carries the per-session WebSocket voice pipeline\n# (STT -> LLM -> TTS). The DO/WebSocket server implementation and the real\n# provider adapters land in later rounds (R2/R3); this file pins the\n# deploy-time bindings so those rounds have a stable contract.\n#\n# TOML syntax verified against the current Cloudflare docs (June 2026):\n# - Durable Objects bindings + migrations:\n# https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/\n# - KV namespaces, routes, vars:\n# https://developers.cloudflare.com/workers/wrangler/configuration/\n\nname = \"platform-ai\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-06-08\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n# --- Observability: capture this Worker's (and its DOs') logs so a single live\n# voice turn's per-hop `turn-trace` lines are queryable in Workers\n# observability. `head_sampling_rate = 1` keeps 100% of invocations — required\n# to read THE one turn being diagnosed (any rate < 1 risks dropping it).\n# https://developers.cloudflare.com/workers/observability/logs/workers-logs/\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n# nodejs_compat is required by the Cloudflare Agents SDK: VoiceSessionDO extends\n# the SDK `Agent` base, which imports `node:async_hooks` (AsyncLocalStorage).\n# The voice provider adapters themselves still target the standard Workers\n# fetch / WebSocket / streams APIs.\n\n# --- Durable Object: per-session voice pipeline state holder ---\n# The DO owns one voice session's conversation history, current phase, and the\n# WebSocket long-connection. Single-point serialization keeps turns ordered.\n# Implementation deferred to R3; the binding + class name are pinned now.\n[[durable_objects.bindings]]\nname = \"VOICE_SESSION\"\nclass_name = \"VoiceSessionDO\"\n\n# SQLite-backed DO storage (the recommended backend for new classes). The\n# migration tag is the ordered changelog of DO class lifecycle events.\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"VoiceSessionDO\"]\n\n# --- Companion service: the sole persistence owner ---\n# Voice session boundaries call this internal RPC binding. Platform AI receives\n# no database or consolidator binding.\n[[services]]\nbinding = \"COMPANION\"\nservice = \"arcade-companion\"\n\n# --- AUTH KV: shared session keyspace owned by auth-session ---\n# The Worker self-binds the auth-session AUTH namespace and reuses the shared\n# session-reader during the WS upgrade handshake and the HTTP intent routes. Those\n# routes also write coarse, non-atomic per-user cost-throttle counters under\n# `ratelimit:shadow-intent:user:*` (shadow-chase) and `ratelimit:proxy-social:user:*`\n# (companion-proxy-social) — independent budgets; neither mutates session records.\n[[kv_namespaces]]\nbinding = \"AUTH\"\nid = \"c4a64d33de2f406e825e6249e828f84d\"\npreview_id = \"5d22a502cb5246408d7f6e5af01a4f7b\"\n\n# --- USAGE KV: per-session usage metering records ---\n# The session DO flushes ONE write-once record per ended voice session — key\n# `usage:{date}:{user_id}:{session_id}` (UTC date at flush time, session_id a\n# per-session UUID), value the session's usage counters (LLM tokens + STT/TTS\n# seconds + STT source annotation). Billing-grade data: no TTL. The write is\n# fail-open (a KV failure is logged, never blocks session close) and the\n# binding is OPTIONAL at runtime — a dev/demo config without it just skips the\n# flush. Dedicated namespace; do NOT reuse LEADERBOARD or AUTH. `id` is the\n# production namespace id, filled at deploy wiring time (placeholder until\n# then, same as AUTH above).\n[[kv_namespaces]]\nbinding = \"USAGE\"\nid = \"5bca263e7860462ea0bef90885b07c1b\"\n\n# --- Same-origin WS route on the canonical zone ---\n# Mounting under claw.amio.fans (same zone as the Platform SPA / /api/*) is the\n# structural prerequisite for the session cookie to ride along on the WS\n# upgrade — a path-prefix route on the existing zone, not a whole-domain custom\n# domain. The /ai-ws/* prefix is pinned at L2 and must not drift.\n[[routes]]\npattern = \"claw.amio.fans/ai-ws/*\"\nzone_name = \"amio.fans\"\n\n[[routes]]\npattern = \"claw.amio.fans/ai-intent/shadow-chase\"\nzone_name = \"amio.fans\"\n\n# Companion-proxy-social bounded intent routes — same-zone, path-exact (mirrors\n# the shadow-chase route above) so the session cookie rides along on the POST.\n[[routes]]\npattern = \"claw.amio.fans/ai-intent/companion-proxy-message\"\nzone_name = \"amio.fans\"\n\n[[routes]]\npattern = \"claw.amio.fans/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.fans\"\n\n# --- Plain-text vars ---\n[vars]\n# Dev-only auth bypass. When set (dev/preview), the WS handshake's\n# session-reader step is replaced by a fixed dev identity; the prod build\n# compiles this branch out. Mounting point / \"validate-at-handshake, reject if\n# invalid\" shape stays fixed — only the session lookup is stubbed.\nDEV_AUTH_BYPASS = \"false\"\n\n[secrets]\nrequired = [\n \"COMPANION_SUBJECT_ISSUER_SECRET\",\n \"COMPANION_SERVICE_AUTH_KEY_ID\",\n \"COMPANION_SERVICE_AUTH_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"VOLC_API_KEY\",\n \"VOLC_TTS_VOICE_COMPANION_WARM\",\n \"VOLC_TTS_VOICE_COMPANION_BRIGHT\",\n \"VOLC_TTS_VOICE_COMPANION_CALM\",\n]\n\n# --- Secrets (set via `wrangler secret put`, NEVER committed as plaintext) ---\n# Provider API keys and any system-prompt material live only server-side as\n# Cloudflare secrets. Set each with `wrangler secret put <NAME>`:\n# DEEPSEEK_API_KEY — DeepSeek (OpenAI-compatible) LLM key.\n# VOLC_API_KEY — Volcengine (火山) console API key, sent as the single\n# X-Api-Key header (new-console-auth). Grants the Doubao\n# 2.0 speech stack (seedasr ASR 2.0 + Doubao TTS 2.0).\n# VOLC_TTS_VOICE_COMPANION_WARM — Volcengine voice_type for companion-warm.\n# VOLC_TTS_VOICE_COMPANION_BRIGHT — Volcengine voice_type for companion-bright.\n# VOLC_TTS_VOICE_COMPANION_CALM — Volcengine voice_type for companion-calm.\n# COMPANION_SUBJECT_ISSUER_SECRET — stable base64url subject-issuer key shared\n# with the server identity boundary only.\n# COMPANION_SERVICE_AUTH_KEY_ID — active request-signing key id.\n# COMPANION_SERVICE_AUTH_KEY — 32-byte lowercase-hex request-signing key;\n# its value must match one entry in the\n# Companion Worker's auth key ring.\n# These are referenced by the provider adapters; declared here only as\n# documentation so the deploy operator knows what to provision.\n#\n# The legacy VOLC_APP_ID / VOLC_ACCESS_KEY pair is no longer read by the adapter\n# (new-console-auth X-Api-Key replaced it; the old pair had no Doubao 2.0 speech\n# grant). Any existing VOLC_APP_ID / VOLC_ACCESS_KEY secrets are now inert and\n# may be deleted with `wrangler secret delete`.\n#\n# No VOLC_SECRET_KEY: the v3 big-model endpoints this adapter targets — seedasr\n# streaming ASR 2.0 (/api/v3/sauc/bigmodel_async) and Doubao TTS 2.0\n# bidirectional (/api/v3/tts/bidirection) — authenticate purely via the\n# X-Api-Key / X-Api-Resource-Id token headers. They do NOT use the legacy\n# `Authorization: HMAC256` signature scheme, so no secret key is needed. (The\n# secret-key signature path is the older console-auth method for the v1/v2\n# endpoints, which this adapter does not use.)\n"}, "320edd1874391bed60c13c6571e5970ce7812e7e": {"t": 1785750686.6062288, "n": 7103, "h": "c0b51510ce6f33db", "c": "# Platform AI Interface — standalone Cloudflare Worker.\n#\n# This is the repo's first independent Worker deploy unit. It hosts the\n# Durable Object that carries the per-session WebSocket voice pipeline\n# (STT -> LLM -> TTS). The DO/WebSocket server implementation and the real\n# provider adapters land in later rounds (R2/R3); this file pins the\n# deploy-time bindings so those rounds have a stable contract.\n#\n# TOML syntax verified against the current Cloudflare docs (June 2026):\n# - Durable Objects bindings + migrations:\n# https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/\n# - KV namespaces, routes, vars:\n# https://developers.cloudflare.com/workers/wrangler/configuration/\n\nname = \"platform-ai\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-06-08\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n# --- Observability: capture this Worker's (and its DOs') logs so a single live\n# voice turn's per-hop `turn-trace` lines are queryable in Workers\n# observability. `head_sampling_rate = 1` keeps 100% of invocations — required\n# to read THE one turn being diagnosed (any rate < 1 risks dropping it).\n# https://developers.cloudflare.com/workers/observability/logs/workers-logs/\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n# nodejs_compat is required by the Cloudflare Agents SDK: VoiceSessionDO extends\n# the SDK `Agent` base, which imports `node:async_hooks` (AsyncLocalStorage).\n# The voice provider adapters themselves still target the standard Workers\n# fetch / WebSocket / streams APIs.\n\n# --- Durable Object: per-session voice pipeline state holder ---\n# The DO owns one voice session's conversation history, current phase, and the\n# WebSocket long-connection. Single-point serialization keeps turns ordered.\n# Implementation deferred to R3; the binding + class name are pinned now.\n[[durable_objects.bindings]]\nname = \"VOICE_SESSION\"\nclass_name = \"VoiceSessionDO\"\n\n# SQLite-backed DO storage (the recommended backend for new classes). The\n# migration tag is the ordered changelog of DO class lifecycle events.\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"VoiceSessionDO\"]\n\n# --- Companion service: the sole persistence owner ---\n# Voice session boundaries call this internal RPC binding. Platform AI receives\n# no database or consolidator binding.\n[[services]]\nbinding = \"COMPANION\"\nservice = \"arcade-companion\"\n\n# --- AUTH KV: shared session keyspace owned by auth-session ---\n# The Worker self-binds the auth-session AUTH namespace and reuses the shared\n# session-reader during the WS upgrade handshake and the HTTP intent routes. Those\n# routes also write coarse, non-atomic per-user cost-throttle counters under\n# `ratelimit:shadow-intent:user:*` (shadow-chase) and `ratelimit:proxy-social:user:*`\n# (companion-proxy-social) — independent budgets; neither mutates session records.\n[[kv_namespaces]]\nbinding = \"AUTH\"\nid = \"c4a64d33de2f406e825e6249e828f84d\"\npreview_id = \"5d22a502cb5246408d7f6e5af01a4f7b\"\n\n# --- USAGE KV: per-session usage metering records ---\n# The session DO flushes ONE write-once record per ended voice session — key\n# `usage:{date}:{user_id}:{session_id}` (UTC date at flush time, session_id a\n# per-session UUID), value the session's usage counters (LLM tokens + STT/TTS\n# seconds + STT source annotation). Billing-grade data: no TTL. The write is\n# fail-open (a KV failure is logged, never blocks session close) and the\n# binding is OPTIONAL at runtime — a dev/demo config without it just skips the\n# flush. Dedicated namespace; do NOT reuse LEADERBOARD or AUTH. `id` is the\n# production namespace id, filled at deploy wiring time (placeholder until\n# then, same as AUTH above).\n[[kv_namespaces]]\nbinding = \"USAGE\"\nid = \"5bca263e7860462ea0bef90885b07c1b\"\n\n# --- Same-origin WS route on the canonical zone ---\n# Mounting under claw.amio.fans (same zone as the Platform SPA / /api/*) is the\n# structural prerequisite for the session cookie to ride along on the WS\n# upgrade — a path-prefix route on the existing zone, not a whole-domain custom\n# domain. The /ai-ws/* prefix is pinned at L2 and must not drift.\n[[routes]]\npattern = \"claw.amio.fans/ai-ws/*\"\nzone_name = \"amio.fans\"\n\n[[routes]]\npattern = \"claw.amio.fans/ai-intent/shadow-chase\"\nzone_name = \"amio.fans\"\n\n# Companion-proxy-social bounded intent routes — same-zone, path-exact (mirrors\n# the shadow-chase route above) so the session cookie rides along on the POST.\n[[routes]]\npattern = \"claw.amio.fans/ai-intent/companion-proxy-message\"\nzone_name = \"amio.fans\"\n\n[[routes]]\npattern = \"claw.amio.fans/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.fans\"\n\n# --- Plain-text vars ---\n[vars]\n# Dev-only auth bypass. When set (dev/preview), the WS handshake's\n# session-reader step is replaced by a fixed dev identity; the prod build\n# compiles this branch out. Mounting point / \"validate-at-handshake, reject if\n# invalid\" shape stays fixed — only the session lookup is stubbed.\nDEV_AUTH_BYPASS = \"false\"\n\n# --- Secrets (set via `wrangler secret put`, NEVER committed as plaintext) ---\n# Provider API keys and any system-prompt material live only server-side as\n# Cloudflare secrets. Set each with `wrangler secret put <NAME>`:\n# DEEPSEEK_API_KEY — DeepSeek (OpenAI-compatible) LLM key.\n# VOLC_API_KEY — Volcengine (火山) console API key, sent as the single\n# X-Api-Key header (new-console-auth). Grants the Doubao\n# 2.0 speech stack (seedasr ASR 2.0 + Doubao TTS 2.0).\n# VOLC_TTS_VOICE_COMPANION_WARM — Volcengine voice_type for companion-warm.\n# VOLC_TTS_VOICE_COMPANION_BRIGHT — Volcengine voice_type for companion-bright.\n# VOLC_TTS_VOICE_COMPANION_CALM — Volcengine voice_type for companion-calm.\n# COMPANION_SUBJECT_ISSUER_SECRET — stable base64url subject-issuer key shared\n# with the server identity boundary only.\n# COMPANION_SERVICE_AUTH_KEY_ID — active request-signing key id.\n# COMPANION_SERVICE_AUTH_KEY — 32-byte lowercase-hex request-signing key;\n# its value must match one entry in the\n# Companion Worker's auth key ring.\n# These are referenced by the provider adapters; declared here only as\n# documentation so the deploy operator knows what to provision.\n#\n# The legacy VOLC_APP_ID / VOLC_ACCESS_KEY pair is no longer read by the adapter\n# (new-console-auth X-Api-Key replaced it; the old pair had no Doubao 2.0 speech\n# grant). Any existing VOLC_APP_ID / VOLC_ACCESS_KEY secrets are now inert and\n# may be deleted with `wrangler secret delete`.\n#\n# No VOLC_SECRET_KEY: the v3 big-model endpoints this adapter targets — seedasr\n# streaming ASR 2.0 (/api/v3/sauc/bigmodel_async) and Doubao TTS 2.0\n# bidirectional (/api/v3/tts/bidirection) — authenticate purely via the\n# X-Api-Key / X-Api-Resource-Id token headers. They do NOT use the legacy\n# `Authorization: HMAC256` signature scheme, so no secret key is needed. (The\n# secret-key signature path is the older console-auth method for the v1/v2\n# endpoints, which this adapter does not use.)\n"}, "d4328c76f9741b6ac101e94bb7bbf5527227651c": {"t": 1785750687.6810308, "n": 6643, "h": "e3fa8d599535cc71", "c": "# Platform AI Interface — standalone Cloudflare Worker.\n#\n# This is the repo's first independent Worker deploy unit. It hosts the\n# Durable Object that carries the per-session WebSocket voice pipeline\n# (STT -> LLM -> TTS). The DO/WebSocket server implementation and the real\n# provider adapters land in later rounds (R2/R3); this file pins the\n# deploy-time bindings so those rounds have a stable contract.\n#\n# TOML syntax verified against the current Cloudflare docs (June 2026):\n# - Durable Objects bindings + migrations:\n# https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/\n# - KV namespaces, routes, vars:\n# https://developers.cloudflare.com/workers/wrangler/configuration/\n\nname = \"platform-ai\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-06-08\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n# --- Observability: capture this Worker's (and its DOs') logs so a single live\n# voice turn's per-hop `turn-trace` lines are queryable in Workers\n# observability. `head_sampling_rate = 1` keeps 100% of invocations — required\n# to read THE one turn being diagnosed (any rate < 1 risks dropping it).\n# https://developers.cloudflare.com/workers/observability/logs/workers-logs/\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n# nodejs_compat is required by the Cloudflare Agents SDK: VoiceSessionDO extends\n# the SDK `Agent` base, which imports `node:async_hooks` (AsyncLocalStorage).\n# The voice provider adapters themselves still target the standard Workers\n# fetch / WebSocket / streams APIs.\n\n# --- Durable Object: per-session voice pipeline state holder ---\n# The DO owns one voice session's conversation history, current phase, and the\n# WebSocket long-connection. Single-point serialization keeps turns ordered.\n# Implementation deferred to R3; the binding + class name are pinned now.\n[[durable_objects.bindings]]\nname = \"VOICE_SESSION\"\nclass_name = \"VoiceSessionDO\"\n\n# SQLite-backed DO storage (the recommended backend for new classes). The\n# migration tag is the ordered changelog of DO class lifecycle events.\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"VoiceSessionDO\"]\n\n# --- Companion service: the sole persistence owner ---\n# Voice session boundaries call this internal RPC binding. Platform AI receives\n# no database or consolidator binding.\n[[services]]\nbinding = \"COMPANION\"\nservice = \"arcade-companion\"\n\n# --- AUTH KV: shared session keyspace owned by auth-session ---\n# The Worker self-binds the auth-session AUTH namespace and reuses the shared\n# session-reader during the WS upgrade handshake and the HTTP intent routes. Those\n# routes also write coarse, non-atomic per-user cost-throttle counters under\n# `ratelimit:shadow-intent:user:*` (shadow-chase) and `ratelimit:proxy-social:user:*`\n# (companion-proxy-social) — independent budgets; neither mutates session records.\n[[kv_namespaces]]\nbinding = \"AUTH\"\nid = \"c4a64d33de2f406e825e6249e828f84d\"\npreview_id = \"5d22a502cb5246408d7f6e5af01a4f7b\"\n\n# --- USAGE KV: per-session usage metering records ---\n# The session DO flushes ONE write-once record per ended voice session — key\n# `usage:{date}:{user_id}:{session_id}` (UTC date at flush time, session_id a\n# per-session UUID), value the session's usage counters (LLM tokens + STT/TTS\n# seconds + STT source annotation). Billing-grade data: no TTL. The write is\n# fail-open (a KV failure is logged, never blocks session close) and the\n# binding is OPTIONAL at runtime — a dev/demo config without it just skips the\n# flush. Dedicated namespace; do NOT reuse LEADERBOARD or AUTH. `id` is the\n# production namespace id, filled at deploy wiring time (placeholder until\n# then, same as AUTH above).\n[[kv_namespaces]]\nbinding = \"USAGE\"\nid = \"5bca263e7860462ea0bef90885b07c1b\"\n\n# --- Same-origin WS route on the canonical zone ---\n# Mounting under claw.amio.fans (same zone as the Platform SPA / /api/*) is the\n# structural prerequisite for the session cookie to ride along on the WS\n# upgrade — a path-prefix route on the existing zone, not a whole-domain custom\n# domain. The /ai-ws/* prefix is pinned at L2 and must not drift.\n[[routes]]\npattern = \"claw.amio.fans/ai-ws/*\"\nzone_name = \"amio.fans\"\n\n[[routes]]\npattern = \"claw.amio.fans/ai-intent/shadow-chase\"\nzone_name = \"amio.fans\"\n\n# Companion-proxy-social bounded intent routes — same-zone, path-exact (mirrors\n# the shadow-chase route above) so the session cookie rides along on the POST.\n[[routes]]\npattern = \"claw.amio.fans/ai-intent/companion-proxy-message\"\nzone_name = \"amio.fans\"\n\n[[routes]]\npattern = \"claw.amio.fans/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.fans\"\n\n# --- Plain-text vars ---\n[vars]\n# Dev-only auth bypass. When set (dev/preview), the WS handshake's\n# session-reader step is replaced by a fixed dev identity; the prod build\n# compiles this branch out. Mounting point / \"validate-at-handshake, reject if\n# invalid\" shape stays fixed — only the session lookup is stubbed.\nDEV_AUTH_BYPASS = \"false\"\n\n# --- Secrets (set via `wrangler secret put`, NEVER committed as plaintext) ---\n# Provider API keys and any system-prompt material live only server-side as\n# Cloudflare secrets. Set each with `wrangler secret put <NAME>`:\n# DEEPSEEK_API_KEY — DeepSeek (OpenAI-compatible) LLM key.\n# VOLC_API_KEY — Volcengine (火山) console API key, sent as the single\n# X-Api-Key header (new-console-auth). Grants the Doubao\n# 2.0 speech stack (seedasr ASR 2.0 + Doubao TTS 2.0).\n# VOLC_TTS_VOICE_COMPANION_WARM — Volcengine voice_type for companion-warm.\n# VOLC_TTS_VOICE_COMPANION_BRIGHT — Volcengine voice_type for companion-bright.\n# VOLC_TTS_VOICE_COMPANION_CALM — Volcengine voice_type for companion-calm.\n# These are referenced by the provider adapters; declared here only as\n# documentation so the deploy operator knows what to provision.\n#\n# The legacy VOLC_APP_ID / VOLC_ACCESS_KEY pair is no longer read by the adapter\n# (new-console-auth X-Api-Key replaced it; the old pair had no Doubao 2.0 speech\n# grant). Any existing VOLC_APP_ID / VOLC_ACCESS_KEY secrets are now inert and\n# may be deleted with `wrangler secret delete`.\n#\n# No VOLC_SECRET_KEY: the v3 big-model endpoints this adapter targets — seedasr\n# streaming ASR 2.0 (/api/v3/sauc/bigmodel_async) and Doubao TTS 2.0\n# bidirectional (/api/v3/tts/bidirection) — authenticate purely via the\n# X-Api-Key / X-Api-Resource-Id token headers. They do NOT use the legacy\n# `Authorization: HMAC256` signature scheme, so no secret key is needed. (The\n# secret-key signature path is the older console-auth method for the v1/v2\n# endpoints, which this adapter does not use.)\n"}, "2ca97a042facfaffca5dee88e565087ca26aecc0": {"t": 1785750688.755464, "n": 7789, "h": "0bcc61b3e0b95a8a", "c": "# Platform AI Interface — standalone Cloudflare Worker.\n#\n# This is the repo's first independent Worker deploy unit. It hosts the\n# Durable Object that carries the per-session WebSocket voice pipeline\n# (STT -> LLM -> TTS). The DO/WebSocket server implementation and the real\n# provider adapters land in later rounds (R2/R3); this file pins the\n# deploy-time bindings so those rounds have a stable contract.\n#\n# TOML syntax verified against the current Cloudflare docs (June 2026):\n# - Durable Objects bindings + migrations:\n# https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/\n# - KV namespaces, routes, vars:\n# https://developers.cloudflare.com/workers/wrangler/configuration/\n\nname = \"platform-ai\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-06-08\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n# --- Observability: capture this Worker's (and its DOs') logs so a single live\n# voice turn's per-hop `turn-trace` lines are queryable in Workers\n# observability. `head_sampling_rate = 1` keeps 100% of invocations — required\n# to read THE one turn being diagnosed (any rate < 1 risks dropping it).\n# https://developers.cloudflare.com/workers/observability/logs/workers-logs/\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n# nodejs_compat is required by the Cloudflare Agents SDK: VoiceSessionDO extends\n# the SDK `Agent` base, which imports `node:async_hooks` (AsyncLocalStorage).\n# The voice provider adapters themselves still target the standard Workers\n# fetch / WebSocket / streams APIs.\n\n# --- Durable Object: per-session voice pipeline state holder ---\n# The DO owns one voice session's conversation history, current phase, and the\n# WebSocket long-connection. Single-point serialization keeps turns ordered.\n# Implementation deferred to R3; the binding + class name are pinned now.\n[[durable_objects.bindings]]\nname = \"VOICE_SESSION\"\nclass_name = \"VoiceSessionDO\"\n\n# SQLite-backed DO storage (the recommended backend for new classes). The\n# migration tag is the ordered changelog of DO class lifecycle events.\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"VoiceSessionDO\"]\n\n# --- Companion-memory consolidator: alarm-driven async consolidation ---\n# Singleton DO (one well-known name) that receives the endSession summary\n# hand-off, writes the idempotent capture row to Companion D1, and runs the\n# LLM consolidation job on a durable alarm — off the session lifecycle, so a\n# slow/failed consolidation can never affect a session end. Chosen over\n# `waitUntil` (parent-request wall-clock bound; LLM distillation can overrun)\n# and Queues (new platform dependency).\n[[durable_objects.bindings]]\nname = \"COMPANION_CONSOLIDATOR\"\nclass_name = \"CompanionConsolidatorDO\"\n\n[[migrations]]\ntag = \"v2\"\nnew_sqlite_classes = [\"CompanionConsolidatorDO\"]\n\n# --- Companion D1: the repo's first relational database ---\n# Owned by the companion-memory component (companion profile, episodic +\n# profile memory, asset ledger, capture inbox). The SAME database is also\n# bound to the Pages project (variable name `COMPANION_DB`) for the\n# /api/companion/* control plane — two binding points, one database.\n# `database_id` is the production id, filled at deploy wiring time\n# (placeholder until then); schema SSOT + migrations live in\n# packages/companion-memory/migrations (see `migrations_dir`).\n[[d1_databases]]\nbinding = \"COMPANION_DB\"\ndatabase_name = \"amiclaw-companion\"\ndatabase_id = \"dd31b70f-03e7-4ed1-9bd0-45393d19c3ad\"\nmigrations_dir = \"../companion-memory/migrations\"\n\n# --- AUTH KV: shared session keyspace owned by auth-session ---\n# The Worker self-binds the auth-session AUTH namespace and reuses the shared\n# session-reader during the WS upgrade handshake and the HTTP intent routes. Those\n# routes also write coarse, non-atomic per-user cost-throttle counters under\n# `ratelimit:shadow-intent:user:*` (shadow-chase) and `ratelimit:proxy-social:user:*`\n# (companion-proxy-social) — independent budgets; neither mutates session records.\n[[kv_namespaces]]\nbinding = \"AUTH\"\nid = \"c4a64d33de2f406e825e6249e828f84d\"\npreview_id = \"5d22a502cb5246408d7f6e5af01a4f7b\"\n\n# --- USAGE KV: per-session usage metering records ---\n# The session DO flushes ONE write-once record per ended voice session — key\n# `usage:{date}:{user_id}:{session_id}` (UTC date at flush time, session_id a\n# per-session UUID), value the session's usage counters (LLM tokens + STT/TTS\n# seconds + STT source annotation). Billing-grade data: no TTL. The write is\n# fail-open (a KV failure is logged, never blocks session close) and the\n# binding is OPTIONAL at runtime — a dev/demo config without it just skips the\n# flush. Dedicated namespace; do NOT reuse LEADERBOARD or AUTH. `id` is the\n# production namespace id, filled at deploy wiring time (placeholder until\n# then, same as AUTH above).\n[[kv_namespaces]]\nbinding = \"USAGE\"\nid = \"5bca263e7860462ea0bef90885b07c1b\"\n\n# --- Same-origin WS route on the canonical zone ---\n# Mounting under claw.amio.fans (same zone as the Platform SPA / /api/*) is the\n# structural prerequisite for the session cookie to ride along on the WS\n# upgrade — a path-prefix route on the existing zone, not a whole-domain custom\n# domain. The /ai-ws/* prefix is pinned at L2 and must not drift.\n[[routes]]\npattern = \"claw.amio.fans/ai-ws/*\"\nzone_name = \"amio.fans\"\n\n[[routes]]\npattern = \"claw.amio.fans/ai-intent/shadow-chase\"\nzone_name = \"amio.fans\"\n\n# Companion-proxy-social bounded intent routes — same-zone, path-exact (mirrors\n# the shadow-chase route above) so the session cookie rides along on the POST.\n[[routes]]\npattern = \"claw.amio.fans/ai-intent/companion-proxy-message\"\nzone_name = \"amio.fans\"\n\n[[routes]]\npattern = \"claw.amio.fans/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.fans\"\n\n# --- Plain-text vars ---\n[vars]\n# Dev-only auth bypass. When set (dev/preview), the WS handshake's\n# session-reader step is replaced by a fixed dev identity; the prod build\n# compiles this branch out. Mounting point / \"validate-at-handshake, reject if\n# invalid\" shape stays fixed — only the session lookup is stubbed.\nDEV_AUTH_BYPASS = \"false\"\n\n# --- Secrets (set via `wrangler secret put`, NEVER committed as plaintext) ---\n# Provider API keys and any system-prompt material live only server-side as\n# Cloudflare secrets. Set each with `wrangler secret put <NAME>`:\n# DEEPSEEK_API_KEY — DeepSeek (OpenAI-compatible) LLM key.\n# VOLC_API_KEY — Volcengine (火山) console API key, sent as the single\n# X-Api-Key header (new-console-auth). Grants the Doubao\n# 2.0 speech stack (seedasr ASR 2.0 + Doubao TTS 2.0).\n# VOLC_TTS_VOICE_COMPANION_WARM — Volcengine voice_type for companion-warm.\n# VOLC_TTS_VOICE_COMPANION_BRIGHT — Volcengine voice_type for companion-bright.\n# VOLC_TTS_VOICE_COMPANION_CALM — Volcengine voice_type for companion-calm.\n# These are referenced by the provider adapters; declared here only as\n# documentation so the deploy operator knows what to provision.\n#\n# The legacy VOLC_APP_ID / VOLC_ACCESS_KEY pair is no longer read by the adapter\n# (new-console-auth X-Api-Key replaced it; the old pair had no Doubao 2.0 speech\n# grant). Any existing VOLC_APP_ID / VOLC_ACCESS_KEY secrets are now inert and\n# may be deleted with `wrangler secret delete`.\n#\n# No VOLC_SECRET_KEY: the v3 big-model endpoints this adapter targets — seedasr\n# streaming ASR 2.0 (/api/v3/sauc/bigmodel_async) and Doubao TTS 2.0\n# bidirectional (/api/v3/tts/bidirection) — authenticate purely via the\n# X-Api-Key / X-Api-Resource-Id token headers. They do NOT use the legacy\n# `Authorization: HMAC256` signature scheme, so no secret key is needed. (The\n# secret-key signature path is the older console-auth method for the v1/v2\n# endpoints, which this adapter does not use.)\n"}, "9417362eba04bb16d6a41be46731c35954e909a7": {"t": 1786067359.309958, "n": 8275, "h": "0c87d3659fda3966", "c": "# Platform AI Interface — standalone Cloudflare Worker.\n#\n# This is the repo's first independent Worker deploy unit. It hosts the\n# Durable Object that carries the per-session WebSocket voice pipeline\n# (STT -> LLM -> TTS). The DO/WebSocket server implementation and the real\n# provider adapters land in later rounds (R2/R3); this file pins the\n# deploy-time bindings so those rounds have a stable contract.\n#\n# TOML syntax verified against the current Cloudflare docs (June 2026):\n# - Durable Objects bindings + migrations:\n# https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/\n# - KV namespaces, routes, vars:\n# https://developers.cloudflare.com/workers/wrangler/configuration/\n\nname = \"amio-arcade-platform-ai\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-06-08\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n# --- Observability: capture this Worker's (and its DOs') logs so a single live\n# voice turn's per-hop `turn-trace` lines are queryable in Workers\n# observability. `head_sampling_rate = 1` keeps 100% of invocations — required\n# to read THE one turn being diagnosed (any rate < 1 risks dropping it).\n# https://developers.cloudflare.com/workers/observability/logs/workers-logs/\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n# nodejs_compat is required by the Cloudflare Agents SDK: VoiceSessionDO extends\n# the SDK `Agent` base, which imports `node:async_hooks` (AsyncLocalStorage).\n# The voice provider adapters themselves still target the standard Workers\n# fetch / WebSocket / streams APIs.\n\n# --- Durable Object: per-session voice pipeline state holder ---\n# The DO owns one voice session's conversation history, current phase, and the\n# WebSocket long-connection. Single-point serialization keeps turns ordered.\n# Implementation deferred to R3; the binding + class name are pinned now.\n[[durable_objects.bindings]]\nname = \"VOICE_SESSION\"\nclass_name = \"VoiceSessionDO\"\n\n# SQLite-backed DO storage (the recommended backend for new classes). The\n# migration tag is the ordered changelog of DO class lifecycle events.\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"VoiceSessionDO\"]\n\n# --- Companion service: the sole persistence owner ---\n# Voice session boundaries call this internal RPC binding. Platform AI receives\n# no database or consolidator binding.\n[[services]]\nbinding = \"COMPANION\"\nservice = \"amio-arcade-companion\"\n\n# --- AUTH KV: shared session keyspace owned by auth-session ---\n# The Worker self-binds the auth-session AUTH namespace and reuses the shared\n# session-reader during the WS upgrade handshake and the HTTP intent routes. Those\n# routes also write coarse, non-atomic per-user cost-throttle counters under\n# `ratelimit:shadow-intent:user:*` (shadow-chase) and `ratelimit:proxy-social:user:*`\n# (companion-proxy-social) — independent budgets; neither mutates session records.\n[[kv_namespaces]]\nbinding = \"AUTH\"\nid = \"c4a64d33de2f406e825e6249e828f84d\"\npreview_id = \"5d22a502cb5246408d7f6e5af01a4f7b\"\n\n# --- Optional legacy USAGE KV mirror ---\n# The session DO may flush ONE best-effort record per ended voice session — key\n# `usage:{date}:{user_id}:{session_id}` (UTC date at flush time, session_id a\n# per-session UUID), value legacy session counters. This mirror is neither\n# authoritative nor billing-grade. Unified usage in Companion-owned D1 is the\n# authority. KV absence or write failure must not affect access, quota, usage\n# accounting, or session close. Preview intentionally omits this binding.\n# Dedicated namespace; do not reuse LEADERBOARD or AUTH.\n[[kv_namespaces]]\nbinding = \"USAGE\"\nid = \"5bca263e7860462ea0bef90885b07c1b\"\n\n# --- Same-origin WS route on the canonical zone ---\n# Mounting under arcade.amio.love (same zone as the Platform SPA / /api/*) is the\n# structural prerequisite for the session cookie to ride along on the WS\n# upgrade — a path-prefix route on the existing zone, not a whole-domain custom\n# domain. The /ai-ws/* prefix is pinned at L2 and must not drift.\n[[routes]]\npattern = \"arcade.amio.love/ai-ws/*\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/shadow-chase\"\nzone_name = \"amio.love\"\n\n# Companion-proxy-social bounded intent routes — same-zone, path-exact (mirrors\n# the shadow-chase route above) so the session cookie rides along on the POST.\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/companion-proxy-message\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.love\"\n\n# --- Apex mirror routes (canonical root domain) ---\n# The single Pages app now serves the apex host amio.love as the canonical entry\n# (arcade.amio.love still serves during the transition). Clients build the voice\n# WS/intent URLs SAME-ORIGIN from `location.host` (`buildSessionUrl` in\n# packages/arcade-shared/voice/voice-session-protocol.ts), so an apex-served\n# player opens `wss://amio.love/ai-ws/...`. Every arcade route below is mirrored\n# on the apex host (same zone, same path-exact intent routes) so the voice\n# pipeline is routed on the canonical domain and the session cookie rides along.\n# www.amio.love is intentionally omitted — it 301-redirects to the apex.\n[[routes]]\npattern = \"amio.love/ai-ws/*\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"amio.love/ai-intent/shadow-chase\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"amio.love/ai-intent/companion-proxy-message\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"amio.love/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.love\"\n\n# --- Plain-text vars ---\n[vars]\n# Dev-only auth bypass. When set (dev/preview), the WS handshake's\n# session-reader step is replaced by a fixed dev identity; the prod build\n# compiles this branch out. Mounting point / \"validate-at-handshake, reject if\n# invalid\" shape stays fixed — only the session lookup is stubbed.\nDEV_AUTH_BYPASS = \"false\"\n\n[secrets]\nrequired = [\n \"COMPANION_SUBJECT_ISSUER_SECRET\",\n \"COMPANION_SERVICE_AUTH_KEY_ID\",\n \"COMPANION_SERVICE_AUTH_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"VOLC_API_KEY\",\n \"VOLC_TTS_VOICE_COMPANION_WARM\",\n \"VOLC_TTS_VOICE_COMPANION_BRIGHT\",\n \"VOLC_TTS_VOICE_COMPANION_CALM\",\n]\n\n# --- Secrets (set via `wrangler secret put`, NEVER committed as plaintext) ---\n# Provider API keys and any system-prompt material live only server-side as\n# Cloudflare secrets. Set each with `wrangler secret put <NAME>`:\n# DEEPSEEK_API_KEY — DeepSeek (OpenAI-compatible) LLM key.\n# VOLC_API_KEY — Volcengine (火山) console API key, sent as the single\n# X-Api-Key header (new-console-auth). Grants the Doubao\n# 2.0 speech stack (seedasr ASR 2.0 + Doubao TTS 2.0).\n# VOLC_TTS_VOICE_COMPANION_WARM — Volcengine voice_type for companion-warm.\n# VOLC_TTS_VOICE_COMPANION_BRIGHT — Volcengine voice_type for companion-bright.\n# VOLC_TTS_VOICE_COMPANION_CALM — Volcengine voice_type for companion-calm.\n# COMPANION_SUBJECT_ISSUER_SECRET — stable base64url subject-issuer key shared\n# with the server identity boundary only.\n# COMPANION_SERVICE_AUTH_KEY_ID — active request-signing key id.\n# COMPANION_SERVICE_AUTH_KEY — 32-byte lowercase-hex request-signing key;\n# its value must match one entry in the\n# Companion Worker's auth key ring.\n# These are referenced by the provider adapters; declared here only as\n# documentation so the deploy operator knows what to provision.\n#\n# The legacy VOLC_APP_ID / VOLC_ACCESS_KEY pair is no longer read by the adapter\n# (new-console-auth X-Api-Key replaced it; the old pair had no Doubao 2.0 speech\n# grant). Any existing VOLC_APP_ID / VOLC_ACCESS_KEY secrets are now inert and\n# may be deleted with `wrangler secret delete`.\n#\n# No VOLC_SECRET_KEY: the v3 big-model endpoints this adapter targets — seedasr\n# streaming ASR 2.0 (/api/v3/sauc/bigmodel_async) and Doubao TTS 2.0\n# bidirectional (/api/v3/tts/bidirection) — authenticate purely via the\n# X-Api-Key / X-Api-Resource-Id token headers. They do NOT use the legacy\n# `Authorization: HMAC256` signature scheme, so no secret key is needed. (The\n# secret-key signature path is the older console-auth method for the v1/v2\n# endpoints, which this adapter does not use.)\n"}, "454e0fe7b118476af391de94f175c74b42608d5e": {"t": 1786068236.590795, "n": 8275, "h": "0c87d3659fda3966", "c": "# Platform AI Interface — standalone Cloudflare Worker.\n#\n# This is the repo's first independent Worker deploy unit. It hosts the\n# Durable Object that carries the per-session WebSocket voice pipeline\n# (STT -> LLM -> TTS). The DO/WebSocket server implementation and the real\n# provider adapters land in later rounds (R2/R3); this file pins the\n# deploy-time bindings so those rounds have a stable contract.\n#\n# TOML syntax verified against the current Cloudflare docs (June 2026):\n# - Durable Objects bindings + migrations:\n# https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/\n# - KV namespaces, routes, vars:\n# https://developers.cloudflare.com/workers/wrangler/configuration/\n\nname = \"amio-arcade-platform-ai\"\nmain = \"src/worker.ts\"\ncompatibility_date = \"2026-06-08\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n# --- Observability: capture this Worker's (and its DOs') logs so a single live\n# voice turn's per-hop `turn-trace` lines are queryable in Workers\n# observability. `head_sampling_rate = 1` keeps 100% of invocations — required\n# to read THE one turn being diagnosed (any rate < 1 risks dropping it).\n# https://developers.cloudflare.com/workers/observability/logs/workers-logs/\n[observability]\nenabled = true\nhead_sampling_rate = 1\n\n# nodejs_compat is required by the Cloudflare Agents SDK: VoiceSessionDO extends\n# the SDK `Agent` base, which imports `node:async_hooks` (AsyncLocalStorage).\n# The voice provider adapters themselves still target the standard Workers\n# fetch / WebSocket / streams APIs.\n\n# --- Durable Object: per-session voice pipeline state holder ---\n# The DO owns one voice session's conversation history, current phase, and the\n# WebSocket long-connection. Single-point serialization keeps turns ordered.\n# Implementation deferred to R3; the binding + class name are pinned now.\n[[durable_objects.bindings]]\nname = \"VOICE_SESSION\"\nclass_name = \"VoiceSessionDO\"\n\n# SQLite-backed DO storage (the recommended backend for new classes). The\n# migration tag is the ordered changelog of DO class lifecycle events.\n[[migrations]]\ntag = \"v1\"\nnew_sqlite_classes = [\"VoiceSessionDO\"]\n\n# --- Companion service: the sole persistence owner ---\n# Voice session boundaries call this internal RPC binding. Platform AI receives\n# no database or consolidator binding.\n[[services]]\nbinding = \"COMPANION\"\nservice = \"amio-arcade-companion\"\n\n# --- AUTH KV: shared session keyspace owned by auth-session ---\n# The Worker self-binds the auth-session AUTH namespace and reuses the shared\n# session-reader during the WS upgrade handshake and the HTTP intent routes. Those\n# routes also write coarse, non-atomic per-user cost-throttle counters under\n# `ratelimit:shadow-intent:user:*` (shadow-chase) and `ratelimit:proxy-social:user:*`\n# (companion-proxy-social) — independent budgets; neither mutates session records.\n[[kv_namespaces]]\nbinding = \"AUTH\"\nid = \"c4a64d33de2f406e825e6249e828f84d\"\npreview_id = \"5d22a502cb5246408d7f6e5af01a4f7b\"\n\n# --- Optional legacy USAGE KV mirror ---\n# The session DO may flush ONE best-effort record per ended voice session — key\n# `usage:{date}:{user_id}:{session_id}` (UTC date at flush time, session_id a\n# per-session UUID), value legacy session counters. This mirror is neither\n# authoritative nor billing-grade. Unified usage in Companion-owned D1 is the\n# authority. KV absence or write failure must not affect access, quota, usage\n# accounting, or session close. Preview intentionally omits this binding.\n# Dedicated namespace; do not reuse LEADERBOARD or AUTH.\n[[kv_namespaces]]\nbinding = \"USAGE\"\nid = \"5bca263e7860462ea0bef90885b07c1b\"\n\n# --- Same-origin WS route on the canonical zone ---\n# Mounting under arcade.amio.love (same zone as the Platform SPA / /api/*) is the\n# structural prerequisite for the session cookie to ride along on the WS\n# upgrade — a path-prefix route on the existing zone, not a whole-domain custom\n# domain. The /ai-ws/* prefix is pinned at L2 and must not drift.\n[[routes]]\npattern = \"arcade.amio.love/ai-ws/*\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/shadow-chase\"\nzone_name = \"amio.love\"\n\n# Companion-proxy-social bounded intent routes — same-zone, path-exact (mirrors\n# the shadow-chase route above) so the session cookie rides along on the POST.\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/companion-proxy-message\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"arcade.amio.love/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.love\"\n\n# --- Apex mirror routes (canonical root domain) ---\n# The single Pages app now serves the apex host amio.love as the canonical entry\n# (arcade.amio.love still serves during the transition). Clients build the voice\n# WS/intent URLs SAME-ORIGIN from `location.host` (`buildSessionUrl` in\n# packages/arcade-shared/voice/voice-session-protocol.ts), so an apex-served\n# player opens `wss://amio.love/ai-ws/...`. Every arcade route below is mirrored\n# on the apex host (same zone, same path-exact intent routes) so the voice\n# pipeline is routed on the canonical domain and the session cookie rides along.\n# www.amio.love is intentionally omitted — it 301-redirects to the apex.\n[[routes]]\npattern = \"amio.love/ai-ws/*\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"amio.love/ai-intent/shadow-chase\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"amio.love/ai-intent/companion-proxy-message\"\nzone_name = \"amio.love\"\n\n[[routes]]\npattern = \"amio.love/ai-intent/companion-proxy-reply\"\nzone_name = \"amio.love\"\n\n# --- Plain-text vars ---\n[vars]\n# Dev-only auth bypass. When set (dev/preview), the WS handshake's\n# session-reader step is replaced by a fixed dev identity; the prod build\n# compiles this branch out. Mounting point / \"validate-at-handshake, reject if\n# invalid\" shape stays fixed — only the session lookup is stubbed.\nDEV_AUTH_BYPASS = \"false\"\n\n[secrets]\nrequired = [\n \"COMPANION_SUBJECT_ISSUER_SECRET\",\n \"COMPANION_SERVICE_AUTH_KEY_ID\",\n \"COMPANION_SERVICE_AUTH_KEY\",\n \"DEEPSEEK_API_KEY\",\n \"VOLC_API_KEY\",\n \"VOLC_TTS_VOICE_COMPANION_WARM\",\n \"VOLC_TTS_VOICE_COMPANION_BRIGHT\",\n \"VOLC_TTS_VOICE_COMPANION_CALM\",\n]\n\n# --- Secrets (set via `wrangler secret put`, NEVER committed as plaintext) ---\n# Provider API keys and any system-prompt material live only server-side as\n# Cloudflare secrets. Set each with `wrangler secret put <NAME>`:\n# DEEPSEEK_API_KEY — DeepSeek (OpenAI-compatible) LLM key.\n# VOLC_API_KEY — Volcengine (火山) console API key, sent as the single\n# X-Api-Key header (new-console-auth). Grants the Doubao\n# 2.0 speech stack (seedasr ASR 2.0 + Doubao TTS 2.0).\n# VOLC_TTS_VOICE_COMPANION_WARM — Volcengine voice_type for companion-warm.\n# VOLC_TTS_VOICE_COMPANION_BRIGHT — Volcengine voice_type for companion-bright.\n# VOLC_TTS_VOICE_COMPANION_CALM — Volcengine voice_type for companion-calm.\n# COMPANION_SUBJECT_ISSUER_SECRET — stable base64url subject-issuer key shared\n# with the server identity boundary only.\n# COMPANION_SERVICE_AUTH_KEY_ID — active request-signing key id.\n# COMPANION_SERVICE_AUTH_KEY — 32-byte lowercase-hex request-signing key;\n# its value must match one entry in the\n# Companion Worker's auth key ring.\n# These are referenced by the provider adapters; declared here only as\n# documentation so the deploy operator knows what to provision.\n#\n# The legacy VOLC_APP_ID / VOLC_ACCESS_KEY pair is no longer read by the adapter\n# (new-console-auth X-Api-Key replaced it; the old pair had no Doubao 2.0 speech\n# grant). Any existing VOLC_APP_ID / VOLC_ACCESS_KEY secrets are now inert and\n# may be deleted with `wrangler secret delete`.\n#\n# No VOLC_SECRET_KEY: the v3 big-model endpoints this adapter targets — seedasr\n# streaming ASR 2.0 (/api/v3/sauc/bigmodel_async) and Doubao TTS 2.0\n# bidirectional (/api/v3/tts/bidirection) — authenticate purely via the\n# X-Api-Key / X-Api-Resource-Id token headers. They do NOT use the legacy\n# `Authorization: HMAC256` signature scheme, so no secret key is needed. (The\n# secret-key signature path is the older console-auth method for the v1/v2\n# endpoints, which this adapter does not use.)\n"}}, "apps/arcade-game-sound-garden/README.md": {"b7520d28015f89cfa5976f8d2a08d4f88a9dca1b": {"t": 1785747270.1532137, "n": 3091, "h": "af4741ddd9571406", "c": "# 声音花园 (Sound Garden) — playability probe\n\nA standalone, playable probe for the **co_build** game \"声音花园\", built on the\n`@amio/arcade-creation` engine (zero engine changes). You and an AI 园丁伙伴 plant a\nsinging garden on an 8-beat timeline: you place pieces on your lane, the partner\nanswers on the other lane, and same-beat pairs score through a hidden harmony\nmatrix. Free-flow, no-fail — reaching the target score makes the garden bloom.\n\n> Standalone by construction: this package is **not** wired into\n> `scripts/assemble-pages.mjs`, so it never reaches production (`arcade.amio.love`).\n\n## Run it\n\n```bash\npnpm --filter @amio/arcade-game-sound-garden dev\n# open the printed http://localhost:<port>/sound-garden/ (Chrome recommended)\n```\n\n- **Chrome is recommended** — the browser voice input (push-to-talk ASR) uses\n Web Speech (`webkitSpeechRecognition`), which is a Chrome/Chromium feature.\n- Tap any piece / the play button to unlock audio (iOS/Chrome autoplay policy).\n- No keys are required to play. Everything below is optional enrichment.\n\n## Optional keys (real AI partner + voice)\n\nCopy `.env.example` to `.env` and fill in either key. They are read\n**server-side only** by the dev API and never reach the browser.\n\n| Key | Enables |\n| ------------------ | ------------------------------------------------- |\n| `DEEPSEEK_API_KEY` | Real LLM partner brain (`/api/partner`, DeepSeek) |\n| `VOLC_API_KEY` | Doubao TTS 2.0 partner voice (`/api/tts`) |\n\nThe client asks `/api/capabilities` at session start and picks its brain + voice\nfrom what is present.\n\n## Degradation chain (always playable)\n\n| Concern | With key | Without key / on failure |\n| ------------- | --------------------------- | ----------------------------------------- |\n| Partner brain | DeepSeek via `/api/partner` | Offline **scripted brain** (per turn) |\n| Partner voice | Doubao TTS via `/api/tts` | Browser **speechSynthesis** → else silent |\n| Player voice | Push-to-talk Web Speech ASR | Mic chip hidden (type-free play) |\n\nEvery online path falls back on the next failure, so a dead key, a dead\nVolcengine grant, or an unsupported browser never blocks play. A production\n`vite build` has no dev server at all — the built preview simply runs fully\noffline (scripted brain + browser voice).\n\n> **Note:** the Doubao TTS path is correct-by-construction (the binary-WS codec\n> is lifted from `packages/platform-ai/src/providers/volcengine.ts`) but is\n> **unverified end-to-end** — the Volcengine grant could not be checked from the\n> repo. speechSynthesis is the load-bearing voice fallback.\n\n## Scripts\n\n| Script | What it does |\n| ------------------- | ------------------------------------ |\n| `dev` | Vite dev server + the dev API routes |\n| `build` | `tsc && vite build` (static SPA) |\n| `typecheck` | `tsc --noEmit` |\n| `test` / `test:run` | Vitest (watch / once) |\n"}, "7b6bc7faafb01e152fd175f4f589e9bfd69ba8c4": {"t": 1785750680.810504, "n": 3091, "h": "af4741ddd9571406", "c": "# 声音花园 (Sound Garden) — playability probe\n\nA standalone, playable probe for the **co_build** game \"声音花园\", built on the\n`@amio/arcade-creation` engine (zero engine changes). You and an AI 园丁伙伴 plant a\nsinging garden on an 8-beat timeline: you place pieces on your lane, the partner\nanswers on the other lane, and same-beat pairs score through a hidden harmony\nmatrix. Free-flow, no-fail — reaching the target score makes the garden bloom.\n\n> Standalone by construction: this package is **not** wired into\n> `scripts/assemble-pages.mjs`, so it never reaches production (`arcade.amio.love`).\n\n## Run it\n\n```bash\npnpm --filter @amio/arcade-game-sound-garden dev\n# open the printed http://localhost:<port>/sound-garden/ (Chrome recommended)\n```\n\n- **Chrome is recommended** — the browser voice input (push-to-talk ASR) uses\n Web Speech (`webkitSpeechRecognition`), which is a Chrome/Chromium feature.\n- Tap any piece / the play button to unlock audio (iOS/Chrome autoplay policy).\n- No keys are required to play. Everything below is optional enrichment.\n\n## Optional keys (real AI partner + voice)\n\nCopy `.env.example` to `.env` and fill in either key. They are read\n**server-side only** by the dev API and never reach the browser.\n\n| Key | Enables |\n| ------------------ | ------------------------------------------------- |\n| `DEEPSEEK_API_KEY` | Real LLM partner brain (`/api/partner`, DeepSeek) |\n| `VOLC_API_KEY` | Doubao TTS 2.0 partner voice (`/api/tts`) |\n\nThe client asks `/api/capabilities` at session start and picks its brain + voice\nfrom what is present.\n\n## Degradation chain (always playable)\n\n| Concern | With key | Without key / on failure |\n| ------------- | --------------------------- | ----------------------------------------- |\n| Partner brain | DeepSeek via `/api/partner` | Offline **scripted brain** (per turn) |\n| Partner voice | Doubao TTS via `/api/tts` | Browser **speechSynthesis** → else silent |\n| Player voice | Push-to-talk Web Speech ASR | Mic chip hidden (type-free play) |\n\nEvery online path falls back on the next failure, so a dead key, a dead\nVolcengine grant, or an unsupported browser never blocks play. A production\n`vite build` has no dev server at all — the built preview simply runs fully\noffline (scripted brain + browser voice).\n\n> **Note:** the Doubao TTS path is correct-by-construction (the binary-WS codec\n> is lifted from `packages/platform-ai/src/providers/volcengine.ts`) but is\n> **unverified end-to-end** — the Volcengine grant could not be checked from the\n> repo. speechSynthesis is the load-bearing voice fallback.\n\n## Scripts\n\n| Script | What it does |\n| ------------------- | ------------------------------------ |\n| `dev` | Vite dev server + the dev API routes |\n| `build` | `tsc && vite build` (static SPA) |\n| `typecheck` | `tsc --noEmit` |\n| `test` / `test:run` | Vitest (watch / once) |\n"}, "d4328c76f9741b6ac101e94bb7bbf5527227651c": {"t": 1785750681.90351, "n": 3089, "h": "511019eded908d92", "c": "# 声音花园 (Sound Garden) — playability probe\n\nA standalone, playable probe for the **co_build** game \"声音花园\", built on the\n`@amio/arcade-creation` engine (zero engine changes). You and an AI 园丁伙伴 plant a\nsinging garden on an 8-beat timeline: you place pieces on your lane, the partner\nanswers on the other lane, and same-beat pairs score through a hidden harmony\nmatrix. Free-flow, no-fail — reaching the target score makes the garden bloom.\n\n> Standalone by construction: this package is **not** wired into\n> `scripts/assemble-pages.mjs`, so it never reaches production (`claw.amio.fans`).\n\n## Run it\n\n```bash\npnpm --filter @amio/arcade-game-sound-garden dev\n# open the printed http://localhost:<port>/sound-garden/ (Chrome recommended)\n```\n\n- **Chrome is recommended** — the browser voice input (push-to-talk ASR) uses\n Web Speech (`webkitSpeechRecognition`), which is a Chrome/Chromium feature.\n- Tap any piece / the play button to unlock audio (iOS/Chrome autoplay policy).\n- No keys are required to play. Everything below is optional enrichment.\n\n## Optional keys (real AI partner + voice)\n\nCopy `.env.example` to `.env` and fill in either key. They are read\n**server-side only** by the dev API and never reach the browser.\n\n| Key | Enables |\n| ------------------ | ------------------------------------------------- |\n| `DEEPSEEK_API_KEY` | Real LLM partner brain (`/api/partner`, DeepSeek) |\n| `VOLC_API_KEY` | Doubao TTS 2.0 partner voice (`/api/tts`) |\n\nThe client asks `/api/capabilities` at session start and picks its brain + voice\nfrom what is present.\n\n## Degradation chain (always playable)\n\n| Concern | With key | Without key / on failure |\n| ------------- | --------------------------- | ----------------------------------------- |\n| Partner brain | DeepSeek via `/api/partner` | Offline **scripted brain** (per turn) |\n| Partner voice | Doubao TTS via `/api/tts` | Browser **speechSynthesis** → else silent |\n| Player voice | Push-to-talk Web Speech ASR | Mic chip hidden (type-free play) |\n\nEvery online path falls back on the next failure, so a dead key, a dead\nVolcengine grant, or an unsupported browser never blocks play. A production\n`vite build` has no dev server at all — the built preview simply runs fully\noffline (scripted brain + browser voice).\n\n> **Note:** the Doubao TTS path is correct-by-construction (the binary-WS codec\n> is lifted from `packages/platform-ai/src/providers/volcengine.ts`) but is\n> **unverified end-to-end** — the Volcengine grant could not be checked from the\n> repo. speechSynthesis is the load-bearing voice fallback.\n\n## Scripts\n\n| Script | What it does |\n| ------------------- | ------------------------------------ |\n| `dev` | Vite dev server + the dev API routes |\n| `build` | `tsc && vite build` (static SPA) |\n| `typecheck` | `tsc --noEmit` |\n| `test` / `test:run` | Vitest (watch / once) |\n"}, "2ca97a042facfaffca5dee88e565087ca26aecc0": {"t": 1785750683.0710223, "n": 3081, "h": "0f85507ac4079cd7", "c": "# 声音花园 (Sound Garden) — playability probe\n\nA standalone, playable probe for the **co_build** game \"声音花园\", built on the\n`@amiclaw/creation` engine (zero engine changes). You and an AI 园丁伙伴 plant a\nsinging garden on an 8-beat timeline: you place pieces on your lane, the partner\nanswers on the other lane, and same-beat pairs score through a hidden harmony\nmatrix. Free-flow, no-fail — reaching the target score makes the garden bloom.\n\n> Standalone by construction: this package is **not** wired into\n> `scripts/assemble-pages.mjs`, so it never reaches production (`claw.amio.fans`).\n\n## Run it\n\n```bash\npnpm --filter @amiclaw/game-sound-garden dev\n# open the printed http://localhost:<port>/sound-garden/ (Chrome recommended)\n```\n\n- **Chrome is recommended** — the browser voice input (push-to-talk ASR) uses\n Web Speech (`webkitSpeechRecognition`), which is a Chrome/Chromium feature.\n- Tap any piece / the play button to unlock audio (iOS/Chrome autoplay policy).\n- No keys are required to play. Everything below is optional enrichment.\n\n## Optional keys (real AI partner + voice)\n\nCopy `.env.example` to `.env` and fill in either key. They are read\n**server-side only** by the dev API and never reach the browser.\n\n| Key | Enables |\n| ------------------ | ------------------------------------------------- |\n| `DEEPSEEK_API_KEY` | Real LLM partner brain (`/api/partner`, DeepSeek) |\n| `VOLC_API_KEY` | Doubao TTS 2.0 partner voice (`/api/tts`) |\n\nThe client asks `/api/capabilities` at session start and picks its brain + voice\nfrom what is present.\n\n## Degradation chain (always playable)\n\n| Concern | With key | Without key / on failure |\n| ------------- | --------------------------- | ----------------------------------------- |\n| Partner brain | DeepSeek via `/api/partner` | Offline **scripted brain** (per turn) |\n| Partner voice | Doubao TTS via `/api/tts` | Browser **speechSynthesis** → else silent |\n| Player voice | Push-to-talk Web Speech ASR | Mic chip hidden (type-free play) |\n\nEvery online path falls back on the next failure, so a dead key, a dead\nVolcengine grant, or an unsupported browser never blocks play. A production\n`vite build` has no dev server at all — the built preview simply runs fully\noffline (scripted brain + browser voice).\n\n> **Note:** the Doubao TTS path is correct-by-construction (the binary-WS codec\n> is lifted from `packages/platform-ai/src/providers/volcengine.ts`) but is\n> **unverified end-to-end** — the Volcengine grant could not be checked from the\n> repo. speechSynthesis is the load-bearing voice fallback.\n\n## Scripts\n\n| Script | What it does |\n| ------------------- | ------------------------------------ |\n| `dev` | Vite dev server + the dev API routes |\n| `build` | `tsc && vite build` (static SPA) |\n| `typecheck` | `tsc --noEmit` |\n| `test` / `test:run` | Vitest (watch / once) |\n"}, "3ecb3e21573fa15a4e25e67d70276e9273c9b597": {"t": 1786068124.7906268, "n": 3091, "h": "af4741ddd9571406", "c": "# 声音花园 (Sound Garden) — playability probe\n\nA standalone, playable probe for the **co_build** game \"声音花园\", built on the\n`@amio/arcade-creation` engine (zero engine changes). You and an AI 园丁伙伴 plant a\nsinging garden on an 8-beat timeline: you place pieces on your lane, the partner\nanswers on the other lane, and same-beat pairs score through a hidden harmony\nmatrix. Free-flow, no-fail — reaching the target score makes the garden bloom.\n\n> Standalone by construction: this package is **not** wired into\n> `scripts/assemble-pages.mjs`, so it never reaches production (`arcade.amio.love`).\n\n## Run it\n\n```bash\npnpm --filter @amio/arcade-game-sound-garden dev\n# open the printed http://localhost:<port>/sound-garden/ (Chrome recommended)\n```\n\n- **Chrome is recommended** — the browser voice input (push-to-talk ASR) uses\n Web Speech (`webkitSpeechRecognition`), which is a Chrome/Chromium feature.\n- Tap any piece / the play button to unlock audio (iOS/Chrome autoplay policy).\n- No keys are required to play. Everything below is optional enrichment.\n\n## Optional keys (real AI partner + voice)\n\nCopy `.env.example` to `.env` and fill in either key. They are read\n**server-side only** by the dev API and never reach the browser.\n\n| Key | Enables |\n| ------------------ | ------------------------------------------------- |\n| `DEEPSEEK_API_KEY` | Real LLM partner brain (`/api/partner`, DeepSeek) |\n| `VOLC_API_KEY` | Doubao TTS 2.0 partner voice (`/api/tts`) |\n\nThe client asks `/api/capabilities` at session start and picks its brain + voice\nfrom what is present.\n\n## Degradation chain (always playable)\n\n| Concern | With key | Without key / on failure |\n| ------------- | --------------------------- | ----------------------------------------- |\n| Partner brain | DeepSeek via `/api/partner` | Offline **scripted brain** (per turn) |\n| Partner voice | Doubao TTS via `/api/tts` | Browser **speechSynthesis** → else silent |\n| Player voice | Push-to-talk Web Speech ASR | Mic chip hidden (type-free play) |\n\nEvery online path falls back on the next failure, so a dead key, a dead\nVolcengine grant, or an unsupported browser never blocks play. A production\n`vite build` has no dev server at all — the built preview simply runs fully\noffline (scripted brain + browser voice).\n\n> **Note:** the Doubao TTS path is correct-by-construction (the binary-WS codec\n> is lifted from `packages/platform-ai/src/providers/volcengine.ts`) but is\n> **unverified end-to-end** — the Volcengine grant could not be checked from the\n> repo. speechSynthesis is the load-bearing voice fallback.\n\n## Scripts\n\n| Script | What it does |\n| ------------------- | ------------------------------------ |\n| `dev` | Vite dev server + the dev API routes |\n| `build` | `tsc && vite build` (static SPA) |\n| `typecheck` | `tsc --noEmit` |\n| `test` / `test:run` | Vitest (watch / once) |\n"}, "454e0fe7b118476af391de94f175c74b42608d5e": {"t": 1786068578.1474285, "n": 3091, "h": "af4741ddd9571406", "c": "# 声音花园 (Sound Garden) — playability probe\n\nA standalone, playable probe for the **co_build** game \"声音花园\", built on the\n`@amio/arcade-creation` engine (zero engine changes). You and an AI 园丁伙伴 plant a\nsinging garden on an 8-beat timeline: you place pieces on your lane, the partner\nanswers on the other lane, and same-beat pairs score through a hidden harmony\nmatrix. Free-flow, no-fail — reaching the target score makes the garden bloom.\n\n> Standalone by construction: this package is **not** wired into\n> `scripts/assemble-pages.mjs`, so it never reaches production (`arcade.amio.love`).\n\n## Run it\n\n```bash\npnpm --filter @amio/arcade-game-sound-garden dev\n# open the printed http://localhost:<port>/sound-garden/ (Chrome recommended)\n```\n\n- **Chrome is recommended** — the browser voice input (push-to-talk ASR) uses\n Web Speech (`webkitSpeechRecognition`), which is a Chrome/Chromium feature.\n- Tap any piece / the play button to unlock audio (iOS/Chrome autoplay policy).\n- No keys are required to play. Everything below is optional enrichment.\n\n## Optional keys (real AI partner + voice)\n\nCopy `.env.example` to `.env` and fill in either key. They are read\n**server-side only** by the dev API and never reach the browser.\n\n| Key | Enables |\n| ------------------ | ------------------------------------------------- |\n| `DEEPSEEK_API_KEY` | Real LLM partner brain (`/api/partner`, DeepSeek) |\n| `VOLC_API_KEY` | Doubao TTS 2.0 partner voice (`/api/tts`) |\n\nThe client asks `/api/capabilities` at session start and picks its brain + voice\nfrom what is present.\n\n## Degradation chain (always playable)\n\n| Concern | With key | Without key / on failure |\n| ------------- | --------------------------- | ----------------------------------------- |\n| Partner brain | DeepSeek via `/api/partner` | Offline **scripted brain** (per turn) |\n| Partner voice | Doubao TTS via `/api/tts` | Browser **speechSynthesis** → else silent |\n| Player voice | Push-to-talk Web Speech ASR | Mic chip hidden (type-free play) |\n\nEvery online path falls back on the next failure, so a dead key, a dead\nVolcengine grant, or an unsupported browser never blocks play. A production\n`vite build` has no dev server at all — the built preview simply runs fully\noffline (scripted brain + browser voice).\n\n> **Note:** the Doubao TTS path is correct-by-construction (the binary-WS codec\n> is lifted from `packages/platform-ai/src/providers/volcengine.ts`) but is\n> **unverified end-to-end** — the Volcengine grant could not be checked from the\n> repo. speechSynthesis is the load-bearing voice fallback.\n\n## Scripts\n\n| Script | What it does |\n| ------------------- | ------------------------------------ |\n| `dev` | Vite dev server + the dev API routes |\n| `build` | `tsc && vite build` (static SPA) |\n| `typecheck` | `tsc --noEmit` |\n| `test` / `test:run` | Vitest (watch / once) |\n"}}}} |