File size: 5,217 Bytes
eee14a2
 
 
 
 
 
 
 
 
 
 
 
8f6b7b7
 
 
 
 
 
 
cd0a5b6
 
 
eee14a2
 
 
8f6b7b7
cd0a5b6
 
eee14a2
 
 
8f6b7b7
cd0a5b6
 
 
 
 
 
 
 
 
 
 
 
 
eee14a2
 
8f6b7b7
 
 
eee14a2
 
cd0a5b6
eee14a2
 
 
cd0a5b6
 
 
 
 
 
 
 
eee14a2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
"""OpenCode configuration for remote, keyless Minecraft supervision."""
from __future__ import annotations

import json
import os
from pathlib import Path
from typing import Any

OPENCODE_VERSION = "1.18.34"
MINE_BASE = "https://erinaldordso-mine.hf.space/v1"
MAIN_MODEL = "qwen3-coder-30b-a3b-instruct"
AUX_MODEL = "granite-4.0-h-tiny"
# Coach-only model: high-level supervision runs SOLELY on the free OpenCode
# Muse model. No Mine provider is configured here; other bots/Spaces that use
# the Mine Space keep their own wiring and are unaffected.
MUSE_MODEL_ID = "muse-spark-1.3-contributor-free"
MUSE_MODEL = "opencode/" + MUSE_MODEL_ID
COACH_PROMPT = """You supervise the upstream AltoClef Minecraft survival speedrun bot.
AltoClef performs real movement, gear progression, stronghold search, portal
activation and dragon combat on difficulty Normal. You are a text decider, not
a file/shell executor: use no tools, run no commands, edit nothing. Observe
only the supplied telemetry and reply ONLY with one compact JSON object:
{"action":"continue","reason":"brief factual explanation"}.
Allowed actions: start, continue, resume. Start/resume runs AltoClef @gamer only
when its task is inactive. Prefer continue while a task is active. Never invent
world observations or success. Naldo plays Survival with a retained pre-existing
inventory (assisted run). Credits observed after entering the End are required
to claim completion. Keep reason under 25 words.
"""


def configuration() -> dict[str, Any]:
    # Supported Zen free-tier shape (probed 2026-10-03, opencode 1.18.33,
    # keyless isolated HOME, empty stdin): NO custom agent at all. Upstream
    # request.ts uses `agent.prompt OR SystemPrompt.provider(model)`, and Zen
    # rejects the tested override shapes with
    # `FreeTierError: ... can only be used from within OpenCode` (403):
    # prompt override, tools lockdown, blanket permission deny, and even a
    # read-only permission shape (*-deny + read/glob/grep-allow +
    # external_directory-deny) each reproduce it. Bare description+mode and the
    # built-ins (build, plan) succeed. The built-in `plan` agent is used:
    # official Muse system prompt intact, read-only by design
    # ("Plan mode. Disallows all edit tools"). All coach instructions live at
    # user level (COACH_PROMPT + telemetry in the run message). There is
    # intentionally no Mine provider either, so nothing falls back to Mine.
    return {
        "$schema": "https://opencode.ai/config.json",
        "enabled_providers": ["opencode"],
        "model": MUSE_MODEL,
        "small_model": MUSE_MODEL,
        "share": "disabled",
        "autoupdate": False,
        "default_agent": "plan",
    }


def coach_user_message(telemetry: dict[str, Any]) -> str:
    """Build the user-level run message: instructions + real telemetry."""
    compact = {key: telemetry.get(key) for key in [
        "connected", "dimension", "position", "creative", "task_active",
        "tasks", "entered_end", "credits_observed", "error"]}
    return COACH_PROMPT + "\nReal telemetry: " + json.dumps(compact)


def child_environment(root: Path) -> dict[str, str]:
    # Independent configuration/data prevents inheriting other CLI credentials
    # or reading the Xbox relay directory. Models are reached without a key.
    env = dict(os.environ)
    for name in list(env):
        if name.endswith("API_KEY") or name.startswith("GEMINI_BOT_KEY_") or name in {
            "HF_TOKEN", "HUGGING_FACE_HUB_TOKEN", "VOYAGER_API_KEY", "GITHUB_TOKEN", "GH_TOKEN"
        }:
            env.pop(name, None)
    env.update({
        "XDG_CONFIG_HOME": str(root / "config"),
        "XDG_DATA_HOME": str(root / "data"),
        "XDG_CACHE_HOME": str(root / "cache"),
        "OPENCODE_CONFIG": str(root / "opencode.json"),
        "OPENCODE_DISABLE_AUTOUPDATE": "true",
        "OPENCODE_DISABLE_DEFAULT_PLUGINS": "true",
        "OPENCODE_DISABLE_SHARE": "true",
    })
    return env


def parse_decision(output: str) -> dict[str, str]:
    texts: list[str] = []
    for line in output.splitlines():
        try:
            event = json.loads(line)
        except (ValueError, TypeError):
            continue
        if event.get("type") == "error":
            raise RuntimeError(str(event.get("error") or event)[:300])
        part = event.get("part") or {}
        if event.get("type") == "text" and part.get("text"):
            texts.append(part["text"])
    raw = "\n".join(texts).strip()
    if raw.startswith("```"):
        raw = "\n".join(raw.splitlines()[1:-1]).strip()
    try:
        decision = json.loads(raw)
    except ValueError as exc:
        raise RuntimeError("OpenCode did not return a valid decision: " + raw[:200]) from exc
    if not isinstance(decision, dict) or decision.get("action") not in {"start", "continue", "resume"}:
        raise RuntimeError("Unsupported OpenCode decision")
    return {"action": decision["action"], "reason": str(decision.get("reason") or "")[:240]}


def goal_completed(observation: dict[str, Any]) -> bool:
    # A disappearing/unloaded dragon or an inactive task never means victory.
    return bool(observation.get("entered_end") and observation.get("credits_observed"))