restore: bring back all custom UI enhancements from checkpoint

Restored from commit 52be710 (checkpoint before qwen oauth + todo roller):

Enhanced UI Features:
- SMART FIX button with AI code analysis
- APEX (Autonomous Programming EXecution) mode
- SHIELD (Auto-approval) mode
- MULTIX MODE multi-task pipeline interface
- Live streaming token counter
- Thinking indicator with bouncing dots animation

Components restored:
- packages/ui/src/components/chat/multi-task-chat.tsx
- packages/ui/src/components/instance/instance-shell2.tsx
- packages/ui/src/components/settings/OllamaCloudSettings.tsx
- packages/ui/src/components/settings/QwenCodeSettings.tsx
- packages/ui/src/stores/solo-store.ts
- packages/ui/src/stores/task-actions.ts
- packages/ui/src/stores/session-events.ts (autonomous mode)
- packages/server/src/integrations/ollama-cloud.ts
- packages/server/src/server/routes/ollama.ts
- packages/server/src/server/routes/qwen.ts

This ensures all custom features are preserved in source control.
This commit is contained in:
Gemini AI
2025-12-23 13:18:37 +04:00
Unverified
parent 157449a9ad
commit c4ac079660
47 changed files with 4550 additions and 527 deletions

View File

@@ -1,5 +1,6 @@
import { resolvePastedPlaceholders } from "../lib/prompt-placeholders"
import { instances } from "./instances"
import { addTaskMessage } from "./task-actions"
import { addRecentModelPreference, setAgentModelPreference } from "./preferences"
import { sessions, withSession } from "./session-state"
@@ -59,7 +60,8 @@ async function sendMessage(
sessionId: string,
prompt: string,
attachments: any[] = [],
): Promise<void> {
taskId?: string,
): Promise<string> {
const instance = instances().get(instanceId)
if (!instance || !instance.client) {
throw new Error("Instance not ready")
@@ -72,6 +74,22 @@ async function sendMessage(
}
const messageId = createId("msg")
// If taskId is provided, associate this message with the task and set it as active
if (taskId) {
addTaskMessage(instanceId, sessionId, taskId, messageId)
withSession(instanceId, sessionId, (session) => {
session.activeTaskId = taskId
})
} else {
// If no taskId, we might want to clear activeTaskId to go back to global chat
// or keep it if we are still "in" a task view.
// For isolation, it's better to clear it if a global message is sent.
withSession(instanceId, sessionId, (session) => {
session.activeTaskId = undefined
})
}
const textPartId = createId("part")
const resolvedPrompt = resolvePastedPlaceholders(prompt, attachments)
@@ -143,6 +161,8 @@ async function sendMessage(
const store = messageStoreBus.getOrCreate(instanceId)
const createdAt = Date.now()
log.info("sendMessage: upserting optimistic message", { messageId, sessionId, taskId });
store.upsertMessage({
id: messageId,
sessionId,
@@ -177,22 +197,43 @@ async function sendMessage(
requestBody,
})
// Electron diagnostic logging
if (typeof window !== "undefined" && (window as any).electron) {
log.info("Electron environment detected", {
isElectron: true,
userAgent: navigator.userAgent,
origin: window.location.origin
})
}
try {
log.info("session.promptAsync", { instanceId, sessionId, requestBody })
log.info("session.promptAsync starting", { instanceId, sessionId })
const response = await instance.client.session.promptAsync({
path: { id: sessionId },
body: requestBody,
})
log.info("sendMessage response", response)
if (response.error) {
log.error("sendMessage server error", response.error)
throw new Error(JSON.stringify(response.error) || "Failed to send message")
}
} catch (error) {
log.error("Failed to send prompt", error)
log.info("session.promptAsync success", { instanceId, sessionId, response })
return messageId
} catch (error: any) {
log.error("Failed to send prompt", {
instanceId,
sessionId,
error: error?.message || error,
stack: error?.stack,
requestBody
})
// Update message status to error in store
const store = messageStoreBus.getOrCreate(instanceId)
store.upsertMessage({
id: messageId,
sessionId,
status: "error",
updatedAt: Date.now(),
})
throw error
}
}
@@ -363,10 +404,65 @@ async function renameSession(instanceId: string, sessionId: string, nextTitle: s
})
}
async function revertSession(instanceId: string, sessionId: string): Promise<void> {
const instance = instances().get(instanceId)
if (!instance || !instance.client) {
throw new Error("Instance not ready")
}
const session = sessions().get(instanceId)?.get(sessionId)
if (!session) {
throw new Error("Session not found")
}
try {
await instance.client.session.revert({
path: { id: sessionId },
})
} catch (error) {
log.error("Failed to revert session", error)
throw error
}
}
async function forkSession(instanceId: string, sessionId: string): Promise<string> {
const instance = instances().get(instanceId)
if (!instance || !instance.client) {
throw new Error("Instance not ready")
}
const session = sessions().get(instanceId)?.get(sessionId)
if (!session) {
throw new Error("Session not found")
}
try {
const response = await instance.client.session.fork({
path: { id: sessionId },
})
if (response.error) {
throw new Error(JSON.stringify(response.error) || "Failed to fork session")
}
const newSessionId = response.data?.id
if (!newSessionId) {
throw new Error("No session ID returned from fork operation")
}
return newSessionId
} catch (error) {
log.error("Failed to fork session", error)
throw error
}
}
export {
abortSession,
executeCustomCommand,
forkSession,
renameSession,
revertSession,
runShellCommand,
sendMessage,
updateSessionAgent,