v0.5.0: Binary-Free Mode - No OpenCode binary required

 Major Features:
- Native session management without OpenCode binary
- Provider routing: OpenCode Zen (free), Qwen OAuth, Z.AI
- Streaming chat with tool execution loop
- Mode detection API (/api/meta/mode)
- MCP integration fix (resolved infinite loading)
- NomadArch Native option in UI with comparison info

🆓 Free Models (No API Key):
- GPT-5 Nano (400K context)
- Grok Code Fast 1 (256K context)
- GLM-4.7 (205K context)
- Doubao Seed Code (256K context)
- Big Pickle (200K context)

📦 New Files:
- session-store.ts: Native session persistence
- native-sessions.ts: REST API for sessions
- lite-mode.ts: UI mode detection client
- native-sessions.ts (UI): SolidJS store

🔧 Updated:
- All installers: Optional binary download
- All launchers: Mode detection display
- Binary selector: Added NomadArch Native option
- README: Binary-Free Mode documentation
This commit is contained in:
Gemini AI
2025-12-26 02:08:13 +04:00
Unverified
parent 8dddf4d0cf
commit 4bd2893864
83 changed files with 10678 additions and 1290 deletions

View File

@@ -154,8 +154,21 @@ function withSession(instanceId: string, sessionId: string, updater: (session: S
return next
})
// Persist session tasks to storage
persistSessionTasks(instanceId)
// Persist session tasks to storage (DEBOUNCED)
schedulePersist(instanceId)
}
// Debounce map for persistence
const persistTimers = new Map<string, ReturnType<typeof setTimeout>>()
function schedulePersist(instanceId: string) {
const existing = persistTimers.get(instanceId)
if (existing) clearTimeout(existing)
const timer = setTimeout(() => {
persistTimers.delete(instanceId)
persistSessionTasks(instanceId)
}, 2000)
persistTimers.set(instanceId, timer)
}
async function persistSessionTasks(instanceId: string) {
@@ -312,7 +325,7 @@ async function isBlankSession(session: Session, instanceId: string, fetchIfNeede
}
// For a more thorough deep clean, we need to look at actual messages
const instance = instances().get(instanceId)
if (!instance?.client) {
return isFreshSession
@@ -335,23 +348,23 @@ async function isBlankSession(session: Session, instanceId: string, fetchIfNeede
// Subagent: "blank" (really: finished doing its job) if actually blank...
// ... OR no streaming, no pending perms, no tool parts
if (messages.length === 0) return true
const hasStreaming = messages.some((msg) => {
const info = msg.info.status || msg.status
return info === "streaming" || info === "sending"
})
const lastMessage = messages[messages.length - 1]
const lastParts = lastMessage?.parts || []
const hasToolPart = lastParts.some((part: any) =>
const hasToolPart = lastParts.some((part: any) =>
part.type === "tool" || part.data?.type === "tool"
)
return !hasStreaming && !session.pendingPermission && !hasToolPart
} else {
// Fork: blank if somehow has no messages or at revert point
if (messages.length === 0) return true
const lastMessage = messages[messages.length - 1]
const lastInfo = lastMessage?.info || lastMessage
return lastInfo?.id === session.revert?.messageID
@@ -429,7 +442,7 @@ export {
setSessionCompactionState,
setSessionPendingPermission,
setActiveSession,
setActiveParentSession,
clearActiveParentSession,