feat: unlock 1M context window and configurable reasoning effort for Muse Spark 1.3

This commit is contained in:
John Smith committed 2026-10-07 00:05:15 -04:00
1 parent 11cf9c0066
commit c138a9c8f3
9 files changed
+171 -13

No files matched your search

+28
View File
@@ -5,6 +5,8 @@ A standalone plugin and native provider bridge for [OpenClaude](https://github.c
Features:
- **Authentic OpenCode v2 Harness Reverse Engineering**: Generates authentic 30-character descending session identifiers (`ses_<timestamp_base62>`), client affinity tracking, and full harness request headers (`User-Agent`, `x-opencode-client`, `x-opencode-session`, `x-opencode-project`, `x-session-affinity`).
- **Seamless Protocol Translation**: OpenClaude talks standard OpenAI `/v1/chat/completions`. Upstream models like **`muse-spark-1.3-contributor`** require OpenAI `/responses` API. The bridge transparently translates requests and bi-directionally streams Server-Sent Events (SSE).
- **1M Native Context Window**: Automatically configures OpenClaude for the full 1,048,576 token context window on `muse-spark-1.3-contributor` instead of falling back to 128K.
- **Configurable Reasoning Effort**: Unlocks OpenClaude's native `/effort` selector (`low`, `medium`, `high`, `xhigh`) and translates effort parameters into upstream OpenCode Go reasoning structures.
- **Target Default Model**: Defaults to **`muse-spark-1.3-contributor`** with verified support for **`space-bunny`** and all 36+ OpenCode Go models.
- **Model Name Normalizer**: Strips any client prefixes (`opencode-unlocked-*`, `opencode-go-*`) to prevent upstream rejection.
- **Zero-Secret Distribution**: The repository contains no hardcoded keys or `.env` files. Users provide their key via environment variable, interactive command, or local config.
@@ -88,12 +90,38 @@ Manage the background bridge daemon using `./bin/opencode-unlocked`:
# Switch active default model
./bin/opencode-unlocked switch space-bunny
# View or set reasoning effort (low, medium, high, xhigh)
./bin/opencode-unlocked effort high
# Run live connectivity verification
./bin/opencode-unlocked test
```
---
## 1M Context Window & Reasoning Effort
### 1,048,576 Token Context Window
OpenCode Go's `muse-spark-1.3-contributor` natively supports a **1M (1,048,576 tokens)** context window. Normally, OpenClaude falls back to a 128,000 token limit on unknown OpenAI-compatible endpoints.
Opencode Unlocked automatically configures:
- OpenClaude provider limits (`maxContextLength: 1048576`)
- `CLAUDE_CODE_OPENAI_CONTEXT_WINDOWS` environment mapping
- OpenClaude `modelLimits` in `settings.json`
### Multi-Level Reasoning Effort
OpenCode Go `/responses` models support four levels of reasoning: `low`, `medium`, `high`, and `xhigh`.
You can adjust reasoning effort in two ways:
1. **In OpenClaude Interactively**:
Use the native `/effort` slash command or the interactive picker to select `low`, `medium`, `high`, or `xhigh`.
2. **Via Plugin CLI**:
```bash
./bin/opencode-unlocked effort medium
```
---
## Supported Models
All 36+ OpenCode Go models are available, including:
+26 -2
View File
@@ -109,6 +109,8 @@ async function printStatus() {
console.log(`Gateway Status : ${running ? "🟢 ONLINE" : "🔴 OFFLINE"}`);
console.log(`Gateway URL : http://${CONFIG.HOST}:${CONFIG.PORT}/v1`);
console.log(`Default Model : ${config.defaultModel || CONFIG.DEFAULT_MODEL}`);
console.log(`Context Window : 1,048,576 tokens (1M native)`);
console.log(`Reasoning Effort: ${config.reasoningEffort || "auto (low, medium, high, xhigh supported)"}`);
console.log(`API Key Loaded : ${apiKey ? `✔ Configured (${apiKey.slice(0, 8)}...)` : "❌ Missing"}`);
console.log(`Config Path : ${getUserConfigPath()}`);
@@ -156,6 +158,23 @@ async function setModel(modelName) {
console.log(`✔ Default model updated to: ${modelName}`);
}
async function setEffort(effortLevel) {
if (!effortLevel) {
const config = loadUserConfig();
console.log(`Current reasoning effort: ${config.reasoningEffort || "auto (model default)"}`);
console.log("Supported levels: low, medium, high, xhigh, auto");
return;
}
const valid = ["low", "medium", "high", "xhigh", "auto"];
const normalized = effortLevel.toLowerCase();
if (!valid.includes(normalized)) {
console.error(`Invalid effort level "${effortLevel}". Valid options: ${valid.join(", ")}`);
process.exit(1);
}
saveUserConfig({ reasoningEffort: normalized });
console.log(`✔ Default reasoning effort updated to: ${normalized}`);
}
async function runTests() {
console.log("Running live verification suite...");
const child = spawn(process.execPath, [path.join(ROOT_DIR, "test", "live-models.test.mjs")], {
@@ -192,6 +211,10 @@ switch (command) {
case "set-model":
await setModel(args[1]);
break;
case "effort":
case "reasoning":
await setEffort(args[1]);
break;
case "test":
await runTests();
break;
@@ -210,12 +233,13 @@ Commands:
start Start the local bridge daemon
stop Stop the running daemon
restart Restart the daemon
status Display daemon health, active model, and token usage
status Display daemon health, active model, context window, and token usage
models List all 36+ available OpenCode Go models
switch <model> Change default model (e.g. space-bunny, muse-spark-1.3-contributor)
effort [level] View or set reasoning effort (low, medium, high, xhigh, auto)
set-key <key> Save OpenCode API key securely to user configuration
test Run live verification on muse-spark and space-bunny
setup Configure OpenClaude provider profile to use this gateway
setup Configure OpenClaude provider profile to use this gateway (1M context & effort enabled)
help Show this help dialog
`);
break;
+43 -3
View File
@@ -41,6 +41,7 @@ export function configureOpenClaudeProfile(options = {}) {
provider: "openai",
baseUrl,
model: targetModel,
maxContextLength: 1048576,
apiKey: "opencode-unlocked"
};
@@ -55,19 +56,51 @@ export function configureOpenClaudeProfile(options = {}) {
// Register model options cache for picker UI
globalConfig.openaiAdditionalModelOptionsCacheByProfile = globalConfig.openaiAdditionalModelOptionsCacheByProfile || {};
globalConfig.openaiAdditionalModelOptionsCacheByProfile[PROVIDER_ID] = [
{ value: "muse-spark-1.3-contributor", label: "Muse Spark 1.3 Contributor", description: "Default Reasoning Model" },
{ value: "muse-spark-1.3-contributor", label: "Muse Spark 1.3 Contributor", description: "Default Reasoning Model (1M Context, Multi-Level Effort)" },
{ value: "space-bunny", label: "Space Bunny", description: "Lightweight Chat & Code Model" },
{ value: "deepseek-v4-flash", label: "DeepSeek V4 Flash", description: "High-Throughput Model" },
{ value: "glm-5.3", label: "GLM 5.3", description: "General Language Model" }
];
fs.writeFileSync(globalConfigPath, JSON.stringify(globalConfig, null, 2), "utf-8");
console.log(`✔ Updated ~/.openclaude.json (active provider set to: ${PROVIDER_NAME})`);
console.log(`✔ Updated ~/.openclaude.json (active provider set to: ${PROVIDER_NAME}, maxContextLength: 1M)`);
} catch (err) {
console.warn(`⚠ Could not update ~/.openclaude.json: ${err.message}`);
}
}
// 2. Configure modelLimits and reasoning effort in ~/.openclaude/settings.json
const settingsPath = path.join(openclaudeDir, "settings.json");
if (fs.existsSync(settingsPath)) {
try {
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
settings.env = settings.env || {};
settings.env.CLAUDE_CODE_ALWAYS_ENABLE_EFFORT = "1";
settings.env.CLAUDE_CODE_OPENAI_CONTEXT_WINDOWS = JSON.stringify({
"muse-spark-1.3-contributor": 1048576,
"muse-spark-1.2-contributor": 1048576,
"muse-spark": 1048576
});
settings.modelLimits = settings.modelLimits || {};
settings.modelLimits["muse-spark-1.3-contributor"] = {
contextWindow: 1048576,
maxOutputTokens: 65536
};
settings.modelLimits["muse-spark-1.2-contributor"] = {
contextWindow: 1048576,
maxOutputTokens: 65536
};
settings.modelLimits["muse-spark"] = {
contextWindow: 1048576,
maxOutputTokens: 65536
};
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
console.log(`✔ Configured 1M context limits & reasoning effort in ~/.openclaude/settings.json`);
} catch (err) {
console.warn(`⚠ Could not update ~/.openclaude/settings.json: ${err.message}`);
}
}
// 2. Configure legacy mirror ~/.openclaude/.openclaude-profile.json
if (!fs.existsSync(openclaudeDir)) {
fs.mkdirSync(openclaudeDir, { recursive: true });
@@ -80,10 +113,17 @@ export function configureOpenClaudeProfile(options = {}) {
const legacyProfile = {
profile: "openai",
maxContextLength: 1048576,
env: {
OPENAI_BASE_URL: baseUrl,
OPENAI_MODEL: targetModel,
OPENAI_API_KEY: "opencode-unlocked"
OPENAI_API_KEY: "opencode-unlocked",
CLAUDE_CODE_ALWAYS_ENABLE_EFFORT: "1",
CLAUDE_CODE_OPENAI_CONTEXT_WINDOWS: JSON.stringify({
"muse-spark-1.3-contributor": 1048576,
"muse-spark-1.2-contributor": 1048576,
"muse-spark": 1048576
})
},
displayName: PROVIDER_NAME,
createdAt: new Date().toISOString()
+3 -2
View File
@@ -1,11 +1,12 @@
---
description: Manage Opencode Unlocked bridge, switch models, or configure keys
argument-hint: "[models|switch <model>|key <key>|test]"
description: Manage Opencode Unlocked bridge, switch models, configure keys, or set effort
argument-hint: "[models|switch <model>|effort <level>|key <key>|test]"
---
Manage Opencode Unlocked:
- If argument is `models`: Run `${CLAUDE_PLUGIN_ROOT}/bin/opencode-unlocked models` to list all 36+ available models.
- If argument is `switch <model>`: Run `${CLAUDE_PLUGIN_ROOT}/bin/opencode-unlocked switch $1` to change the default model.
- If argument is `effort <level>`: Run `${CLAUDE_PLUGIN_ROOT}/bin/opencode-unlocked effort $1` to set reasoning effort (low, medium, high, xhigh, auto).
- If argument is `key <key>`: Run `${CLAUDE_PLUGIN_ROOT}/bin/opencode-unlocked set-key $1` to securely store your OpenCode API key.
- If argument is `test`: Run `${CLAUDE_PLUGIN_ROOT}/bin/opencode-unlocked test` to test live connectivity to Muse Spark 1.3 Contributor and Space Bunny.
- Otherwise, run `${CLAUDE_PLUGIN_ROOT}/bin/opencode-unlocked status`.
+3 -1
View File
@@ -42,6 +42,8 @@ export OPENAI_BASE_URL="${GATEWAY_URL}/v1"
if [ -z "\$OPENAI_MODEL" ]; then
export OPENAI_MODEL="muse-spark-1.3-contributor"
fi
export CLAUDE_CODE_ALWAYS_ENABLE_EFFORT="1"
export CLAUDE_CODE_OPENAI_CONTEXT_WINDOWS='{"muse-spark-1.3-contributor":1048576,"muse-spark-1.2-contributor":1048576,"muse-spark":1048576}'
EOF
fi
@@ -50,7 +52,7 @@ cat << EOF
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "Opencode Unlocked active at ${GATEWAY_URL}/v1. Default model: muse-spark-1.3-contributor (Space Bunny and 36+ models available)."
"additionalContext": "Opencode Unlocked active at ${GATEWAY_URL}/v1. Default model: muse-spark-1.3-contributor (1M context window, multi-level reasoning effort)."
}
}
EOF
+8
View File
@@ -123,6 +123,14 @@ export function chatCompletionsToResponsesBody(body) {
if (typeof max_output_tokens === "number") responsesPayload.max_output_tokens = max_output_tokens;
else if (typeof max_tokens === "number") responsesPayload.max_output_tokens = max_tokens;
// Translate reasoning_effort (OpenAI Chat Completions) to reasoning: { effort } (Responses API)
const incomingEffort = body.reasoning_effort || (typeof body.reasoning === "object" ? body.reasoning?.effort : undefined);
if (incomingEffort && incomingEffort !== "auto" && incomingEffort !== "none") {
responsesPayload.reasoning = {
effort: incomingEffort
};
}
if (Array.isArray(tools)) {
responsesPayload.tools = tools.map((t) => {
if (t.type === "function" && t.function) {
+4 -3
View File
@@ -14,7 +14,7 @@ OpenCode Go hosts 36+ cutting-edge models behind strict harness fingerprinting.
3. **Model Prefix Stripping**: Normalizes prefix variations (`opencode-unlocked-*` -> `*`).
## Primary Models
- **`muse-spark-1.3-contributor`** (Default): High-capability reasoning and coding model. Requires `/responses` protocol; translated automatically by the bridge.
- **`muse-spark-1.3-contributor`** (Default): High-capability reasoning and coding model with a full **1M (1,048,576 token)** context window. Supports configurable reasoning effort (`low`, `medium`, `high`, `xhigh`). Requires `/responses` protocol; translated automatically by the bridge.
- **`space-bunny`**: Fast, lightweight general and coding model. Native `/chat/completions`.
- **`deepseek-v4-flash`**: High-throughput flash model.
- **`glm-5.3`**: General language model.
@@ -25,5 +25,6 @@ OpenCode Go hosts 36+ cutting-edge models behind strict harness fingerprinting.
## Operational Commands
- Check daemon health and usage: `/opencode-unlocked:status`
- Manage models and keys: `/opencode-unlocked:unlocked`
- CLI Management: `opencode-unlocked [start|stop|restart|status|models|test|set-key]`
- Manage models, keys, and effort: `/opencode-unlocked:unlocked [models|switch <model>|effort <level>|key <key>|test]`
- Adjust reasoning effort directly: `/effort [low|medium|high|xhigh|auto]`
- CLI Management: `opencode-unlocked [start|stop|restart|status|models|switch|effort|test|set-key|setup]`
+23 -2
View File
@@ -64,11 +64,32 @@ server.listen(TEST_PORT, "127.0.0.1", async () => {
const spaceDuration = ((Date.now() - spaceStart) / 1000).toFixed(2);
console.log(`✔ Space Bunny responded in ${spaceDuration}s:`);
console.log(` Output: "${spaceReply}"`);
console.log(` Usage: ${JSON.stringify(spaceJson.usage)}`);
assert.ok(spaceReply && /yellow/i.test(spaceReply), "Space Bunny should correctly reply with yellow");
// 3. Verify Reasoning Effort with Muse Spark 1.3 Contributor
console.log("\n[3/3] Verifying Configurable Reasoning Effort: Muse Spark 1.3 with reasoning_effort='high'...");
const effortStart = Date.now();
const effortRes = await fetch(`${baseUrl}/chat/completions`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "muse-spark-1.3-contributor",
messages: [{ role: "user", content: "Is 97 prime? Reply yes or no only." }],
reasoning_effort: "high",
stream: false
})
});
assert.equal(effortRes.status, 200, `Muse Spark with reasoning_effort should be 200 (was ${effortRes.status})`);
const effortJson = await effortRes.json();
const effortReply = effortJson.choices?.[0]?.message?.content?.trim();
const effortDuration = ((Date.now() - effortStart) / 1000).toFixed(2);
console.log(`✔ Muse Spark with reasoning_effort='high' responded in ${effortDuration}s:`);
console.log(` Output: "${effortReply}"`);
assert.ok(effortReply && /yes/i.test(effortReply), "Muse Spark should answer yes for prime 97");
console.log("\n==================================================");
console.log("✔ LIVE VERIFICATION PASSED FOR BOTH MODELS!");
console.log("✔ LIVE VERIFICATION PASSED FOR ALL MODELS & REASONING!");
console.log("==================================================");
} catch (err) {
console.error("\n❌ Live model verification failed:", err);
+33
View File
@@ -36,6 +36,39 @@ assert.equal(responsesPayload.input.length, 2);
assert.equal(responsesPayload.input[0].role, "system");
assert.equal(responsesPayload.input[1].content, "Hello world");
// 2b. Verify reasoning effort translation
const effortHighReq = {
model: "muse-spark-1.3-contributor",
messages: [{ role: "user", content: "Hi" }],
reasoning_effort: "high"
};
const effortHighPayload = chatCompletionsToResponsesBody(effortHighReq);
assert.deepEqual(effortHighPayload.reasoning, { effort: "high" });
const effortXHighReq = {
model: "muse-spark-1.3-contributor",
messages: [{ role: "user", content: "Hi" }],
reasoning_effort: "xhigh"
};
const effortXHighPayload = chatCompletionsToResponsesBody(effortXHighReq);
assert.deepEqual(effortXHighPayload.reasoning, { effort: "xhigh" });
const effortNoneReq = {
model: "muse-spark-1.3-contributor",
messages: [{ role: "user", content: "Hi" }],
reasoning_effort: "none"
};
const effortNonePayload = chatCompletionsToResponsesBody(effortNoneReq);
assert.equal(effortNonePayload.reasoning, undefined);
const effortNestedReq = {
model: "muse-spark-1.3-contributor",
messages: [{ role: "user", content: "Hi" }],
reasoning: { effort: "low" }
};
const effortNestedPayload = chatCompletionsToResponsesBody(effortNestedReq);
assert.deepEqual(effortNestedPayload.reasoning, { effort: "low" });
// 3. Responses API non-streaming JSON -> Chat Completions JSON
const rawResponsesResp = {
id: "resp_1234567890",