Compare commits

..

4 Commits

Author SHA1 Message Date
github-actions[bot]
491df05b63 release: v3.2.1 2026-02-01 12:28:11 +00:00
YeonGyu-Kim
25dcd2a3f2 fix(background-agent): prevent concurrency slot leaks on task startup failures
Unify slot ownership: processKey() owns the slot until task.concurrencyKey is set.
Previously, startTask() released the slot on errors (session.create catch,
createResult.error), but processKey() catch block didn't release, causing slot
leaks when errors occurred between acquire() and task.concurrencyKey assignment.

Changes:
- Remove all pre-transfer release() calls in startTask()
- Add conditional release in processKey() catch: only if task.concurrencyKey not set
- Add validation for createResult.data?.id to catch malformed API responses

This fixes 'Task failed to start within timeout' errors caused by exhausted
concurrency slots that were never released.
2026-02-01 21:24:52 +09:00
YeonGyu-Kim
613610308c fix(cli): add -preview suffix for GitHub Copilot Gemini model names
GitHub Copilot uses gemini-3-pro-preview and gemini-3-flash-preview as
the official model identifiers. The CLI installer was generating config
with incorrect names (gemini-3-pro, gemini-3-flash).

Reported by user: the install command was creating config with wrong
model names that don't work with GitHub Copilot API.
2026-02-01 21:23:52 +09:00
YeonGyu-Kim
62c8a671ee fix(ci): add shell: bash to retry action for Windows compatibility 2026-02-01 19:58:23 +09:00
12 changed files with 43 additions and 35 deletions

View File

@@ -89,6 +89,7 @@ jobs:
timeout_minutes: 5
max_attempts: 5
retry_wait_seconds: 10
shell: bash
command: |
PLATFORM="${{ matrix.platform }}"
case "$PLATFORM" in

View File

@@ -1,6 +1,6 @@
{
"name": "oh-my-opencode",
"version": "3.2.0",
"version": "3.2.1",
"description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -74,13 +74,13 @@
"typescript": "^5.7.3"
},
"optionalDependencies": {
"oh-my-opencode-darwin-arm64": "3.2.0",
"oh-my-opencode-darwin-x64": "3.2.0",
"oh-my-opencode-linux-arm64": "3.2.0",
"oh-my-opencode-linux-arm64-musl": "3.2.0",
"oh-my-opencode-linux-x64": "3.2.0",
"oh-my-opencode-linux-x64-musl": "3.2.0",
"oh-my-opencode-windows-x64": "3.2.0"
"oh-my-opencode-darwin-arm64": "3.2.1",
"oh-my-opencode-darwin-x64": "3.2.1",
"oh-my-opencode-linux-arm64": "3.2.1",
"oh-my-opencode-linux-arm64-musl": "3.2.1",
"oh-my-opencode-linux-x64": "3.2.1",
"oh-my-opencode-linux-x64-musl": "3.2.1",
"oh-my-opencode-windows-x64": "3.2.1"
},
"trustedDependencies": [
"@ast-grep/cli",

View File

@@ -1,6 +1,6 @@
{
"name": "oh-my-opencode-darwin-arm64",
"version": "3.2.0",
"version": "3.2.1",
"description": "Platform-specific binary for oh-my-opencode (darwin-arm64)",
"license": "MIT",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "oh-my-opencode-darwin-x64",
"version": "3.2.0",
"version": "3.2.1",
"description": "Platform-specific binary for oh-my-opencode (darwin-x64)",
"license": "MIT",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "oh-my-opencode-linux-arm64-musl",
"version": "3.2.0",
"version": "3.2.1",
"description": "Platform-specific binary for oh-my-opencode (linux-arm64-musl)",
"license": "MIT",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "oh-my-opencode-linux-arm64",
"version": "3.2.0",
"version": "3.2.1",
"description": "Platform-specific binary for oh-my-opencode (linux-arm64)",
"license": "MIT",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "oh-my-opencode-linux-x64-musl",
"version": "3.2.0",
"version": "3.2.1",
"description": "Platform-specific binary for oh-my-opencode (linux-x64-musl)",
"license": "MIT",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "oh-my-opencode-linux-x64",
"version": "3.2.0",
"version": "3.2.1",
"description": "Platform-specific binary for oh-my-opencode (linux-x64)",
"license": "MIT",
"repository": {

View File

@@ -1,6 +1,6 @@
{
"name": "oh-my-opencode-windows-x64",
"version": "3.2.0",
"version": "3.2.1",
"description": "Platform-specific binary for oh-my-opencode (windows-x64)",
"license": "MIT",
"repository": {

View File

@@ -760,7 +760,7 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when
"variant": "medium",
},
"multimodal-looker": {
"model": "github-copilot/gemini-3-flash",
"model": "github-copilot/gemini-3-flash-preview",
},
"oracle": {
"model": "github-copilot/gpt-5.2",
@@ -777,7 +777,7 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when
},
"categories": {
"artistry": {
"model": "github-copilot/gemini-3-pro",
"model": "github-copilot/gemini-3-pro-preview",
"variant": "max",
},
"deep": {
@@ -798,10 +798,10 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when
"model": "github-copilot/claude-sonnet-4.5",
},
"visual-engineering": {
"model": "github-copilot/gemini-3-pro",
"model": "github-copilot/gemini-3-pro-preview",
},
"writing": {
"model": "github-copilot/gemini-3-flash",
"model": "github-copilot/gemini-3-flash-preview",
},
},
}
@@ -833,7 +833,7 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with
"variant": "medium",
},
"multimodal-looker": {
"model": "github-copilot/gemini-3-flash",
"model": "github-copilot/gemini-3-flash-preview",
},
"oracle": {
"model": "github-copilot/gpt-5.2",
@@ -850,7 +850,7 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with
},
"categories": {
"artistry": {
"model": "github-copilot/gemini-3-pro",
"model": "github-copilot/gemini-3-pro-preview",
"variant": "max",
},
"deep": {
@@ -872,10 +872,10 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with
"model": "github-copilot/claude-sonnet-4.5",
},
"visual-engineering": {
"model": "github-copilot/gemini-3-pro",
"model": "github-copilot/gemini-3-pro-preview",
},
"writing": {
"model": "github-copilot/gemini-3-flash",
"model": "github-copilot/gemini-3-flash-preview",
},
},
}
@@ -1090,7 +1090,7 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb
"variant": "medium",
},
"multimodal-looker": {
"model": "github-copilot/gemini-3-flash",
"model": "github-copilot/gemini-3-flash-preview",
},
"oracle": {
"model": "openai/gpt-5.2",
@@ -1107,7 +1107,7 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb
},
"categories": {
"artistry": {
"model": "github-copilot/gemini-3-pro",
"model": "github-copilot/gemini-3-pro-preview",
"variant": "max",
},
"deep": {
@@ -1128,10 +1128,10 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb
"model": "github-copilot/claude-sonnet-4.5",
},
"visual-engineering": {
"model": "github-copilot/gemini-3-pro",
"model": "github-copilot/gemini-3-pro-preview",
},
"writing": {
"model": "github-copilot/gemini-3-flash",
"model": "github-copilot/gemini-3-flash-preview",
},
},
}
@@ -1290,7 +1290,7 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider
"variant": "medium",
},
"multimodal-looker": {
"model": "github-copilot/gemini-3-flash",
"model": "github-copilot/gemini-3-flash-preview",
},
"oracle": {
"model": "github-copilot/gpt-5.2",
@@ -1307,7 +1307,7 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider
},
"categories": {
"artistry": {
"model": "github-copilot/gemini-3-pro",
"model": "github-copilot/gemini-3-pro-preview",
"variant": "max",
},
"deep": {
@@ -1328,10 +1328,10 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider
"model": "github-copilot/claude-sonnet-4.5",
},
"visual-engineering": {
"model": "github-copilot/gemini-3-pro",
"model": "github-copilot/gemini-3-pro-preview",
},
"writing": {
"model": "github-copilot/gemini-3-flash",
"model": "github-copilot/gemini-3-flash-preview",
},
},
}

View File

@@ -75,6 +75,8 @@ function transformModelForProvider(provider: string, model: string): string {
.replace("claude-sonnet-4-5", "claude-sonnet-4.5")
.replace("claude-haiku-4-5", "claude-haiku-4.5")
.replace("claude-sonnet-4", "claude-sonnet-4")
.replace("gemini-3-pro", "gemini-3-pro-preview")
.replace("gemini-3-flash", "gemini-3-flash-preview")
}
return model
}

View File

@@ -200,6 +200,11 @@ export class BackgroundManager {
await this.startTask(item)
} catch (error) {
log("[background-agent] Error starting task:", error)
// Release concurrency slot if startTask failed and didn't release it itself
// This prevents slot leaks when errors occur after acquire but before task.concurrencyKey is set
if (!item.task.concurrencyKey) {
this.concurrencyManager.release(key)
}
}
queue.shift()
@@ -240,16 +245,16 @@ export class BackgroundManager {
query: {
directory: parentDirectory,
},
}).catch((error) => {
this.concurrencyManager.release(concurrencyKey)
throw error
})
if (createResult.error) {
this.concurrencyManager.release(concurrencyKey)
throw new Error(`Failed to create background session: ${createResult.error}`)
}
if (!createResult.data?.id) {
throw new Error("Failed to create background session: API returned no session ID")
}
const sessionID = createResult.data.id
subagentSessions.add(sessionID)