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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user