Backup before continuing from Codex 5.2 session - User storage, compaction suggestions, streaming improvements
This commit is contained in:
@@ -66,6 +66,7 @@ import { formatTokenTotal } from "../../lib/formatters"
|
||||
import { sseManager } from "../../lib/sse-manager"
|
||||
import { getLogger } from "../../lib/logger"
|
||||
import AdvancedSettingsModal from "../advanced-settings-modal"
|
||||
import { showConfirmDialog } from "../../stores/alerts"
|
||||
import {
|
||||
getSoloState,
|
||||
toggleAutonomous,
|
||||
@@ -103,6 +104,7 @@ const LEFT_DRAWER_STORAGE_KEY = "opencode-session-sidebar-width-v8"
|
||||
const RIGHT_DRAWER_STORAGE_KEY = "opencode-session-right-drawer-width-v1"
|
||||
const LEFT_PIN_STORAGE_KEY = "opencode-session-left-drawer-pinned-v1"
|
||||
const RIGHT_PIN_STORAGE_KEY = "opencode-session-right-drawer-pinned-v1"
|
||||
const BUILD_PREVIEW_EVENT = "opencode:build-preview"
|
||||
|
||||
|
||||
|
||||
@@ -150,6 +152,8 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
||||
const [terminalOpen, setTerminalOpen] = createSignal(false)
|
||||
const [rightPanelExpandedItems, setRightPanelExpandedItems] = createSignal<string[]>(["lsp", "mcp", "plan"])
|
||||
const [currentFile, setCurrentFile] = createSignal<FileNode | null>(null)
|
||||
const [centerTab, setCenterTab] = createSignal<"code" | "preview">("code")
|
||||
const [previewUrl, setPreviewUrl] = createSignal<string | null>(null)
|
||||
const [isSoloOpen, setIsSoloOpen] = createSignal(true)
|
||||
const [showAdvancedSettings, setShowAdvancedSettings] = createSignal(false)
|
||||
const [selectedBinary, setSelectedBinary] = createSignal("opencode")
|
||||
@@ -284,6 +288,25 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
||||
onCleanup(() => window.removeEventListener("open-advanced-settings", handler))
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
if (typeof window === "undefined") return
|
||||
const handler = async (event: Event) => {
|
||||
const detail = (event as CustomEvent<{ url?: string; instanceId?: string }>).detail
|
||||
if (!detail || detail.instanceId !== props.instance.id || !detail.url) return
|
||||
setPreviewUrl(detail.url)
|
||||
const confirmed = await showConfirmDialog(`Preview available at ${detail.url}. Open now?`, {
|
||||
title: "Preview ready",
|
||||
confirmLabel: "Open preview",
|
||||
cancelLabel: "Later",
|
||||
})
|
||||
if (confirmed) {
|
||||
setCenterTab("preview")
|
||||
}
|
||||
}
|
||||
window.addEventListener(BUILD_PREVIEW_EVENT, handler)
|
||||
onCleanup(() => window.removeEventListener(BUILD_PREVIEW_EVENT, handler))
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
if (typeof window === "undefined") return
|
||||
window.localStorage.setItem(LEFT_DRAWER_STORAGE_KEY, sessionSidebarWidth().toString())
|
||||
@@ -449,6 +472,7 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
||||
|
||||
let sidebarActionId = 0
|
||||
const [pendingSidebarAction, setPendingSidebarAction] = createSignal<PendingSidebarAction | null>(null)
|
||||
const [sidebarRequestedTab, setSidebarRequestedTab] = createSignal<string | null>(null)
|
||||
|
||||
const triggerKeyboardEvent = (target: HTMLElement, options: { key: string; code: string; keyCode: number }) => {
|
||||
target.dispatchEvent(
|
||||
@@ -499,6 +523,9 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
||||
|
||||
const handleSidebarRequest = (action: SessionSidebarRequestAction) => {
|
||||
setPendingSidebarAction({ action, id: sidebarActionId++ })
|
||||
if (action === "show-skills") {
|
||||
setSidebarRequestedTab("skills")
|
||||
}
|
||||
if (!leftPinned() && !leftOpen()) {
|
||||
setLeftOpen(true)
|
||||
measureDrawerHost()
|
||||
@@ -902,6 +929,7 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
||||
onToggleTerminal={() => setTerminalOpen((current) => !current)}
|
||||
isTerminalOpen={terminalOpen()}
|
||||
onOpenAdvancedSettings={() => setShowAdvancedSettings(true)}
|
||||
requestedTab={sidebarRequestedTab()}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -1243,18 +1271,18 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* SOLO Mode & Auto-Approval Toggles */}
|
||||
{/* APEX PRO Mode & Auto-Approval Toggles */}
|
||||
<div class="flex items-center bg-white/5 border border-white/5 rounded-full px-1.5 py-1 space-x-1">
|
||||
<button
|
||||
onClick={() => toggleAutonomous(props.instance.id)}
|
||||
title="Autonomous Mode (SOLO): Enable autonomous AI agent operations"
|
||||
title="Autonomous Mode (APEX PRO): Enable autonomous AI agent operations"
|
||||
class={`flex items-center space-x-1.5 px-2 py-0.5 rounded-full transition-all ${getSoloState(props.instance.id).isAutonomous
|
||||
? "bg-blue-500/20 text-blue-400 border border-blue-500/30"
|
||||
: "text-zinc-500 hover:text-zinc-300"
|
||||
}`}
|
||||
>
|
||||
<Zap size={12} class={getSoloState(props.instance.id).isAutonomous ? "animate-pulse" : ""} />
|
||||
<span class="text-[9px] font-black uppercase tracking-tighter">SOLO</span>
|
||||
<span class="text-[9px] font-black uppercase tracking-tighter">APEX PRO</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => toggleAutoApproval(props.instance.id)}
|
||||
@@ -1305,7 +1333,65 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
||||
>
|
||||
<div class="flex-1 flex overflow-hidden min-h-0">
|
||||
<Show when={!isPhoneLayout()}>
|
||||
<Editor file={currentFile()} />
|
||||
<div class="flex-1 flex flex-col min-h-0 bg-[#0d0d0d]">
|
||||
<div class="h-10 glass border-b border-white/5 flex items-center justify-between px-4 shrink-0">
|
||||
<div class="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class={`px-2.5 py-1 rounded-md text-[11px] font-semibold uppercase tracking-wide border ${
|
||||
centerTab() === "code"
|
||||
? "bg-white/10 border-white/20 text-white"
|
||||
: "border-transparent text-zinc-400 hover:text-zinc-200 hover:bg-white/5"
|
||||
}`}
|
||||
onClick={() => setCenterTab("code")}
|
||||
>
|
||||
Code
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class={`px-2.5 py-1 rounded-md text-[11px] font-semibold uppercase tracking-wide border ${
|
||||
centerTab() === "preview"
|
||||
? "bg-white/10 border-white/20 text-white"
|
||||
: "border-transparent text-zinc-400 hover:text-zinc-200 hover:bg-white/5"
|
||||
}`}
|
||||
onClick={() => setCenterTab("preview")}
|
||||
disabled={!previewUrl()}
|
||||
title={previewUrl() ? previewUrl() : "Run build to enable preview"}
|
||||
>
|
||||
Preview
|
||||
</button>
|
||||
</div>
|
||||
<Show when={previewUrl()}>
|
||||
{(url) => (
|
||||
<div class="text-[10px] text-zinc-500 truncate max-w-[50%]" title={url()}>
|
||||
{url()}
|
||||
</div>
|
||||
)}
|
||||
</Show>
|
||||
</div>
|
||||
<Show when={centerTab() === "preview"} fallback={<Editor file={currentFile()} />}>
|
||||
<Show
|
||||
when={previewUrl()}
|
||||
fallback={
|
||||
<div class="flex-1 flex items-center justify-center text-zinc-500">
|
||||
<div class="text-center">
|
||||
<p>No preview available yet.</p>
|
||||
<p class="text-sm mt-2 opacity-60">Run build to detect a preview URL.</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{(url) => (
|
||||
<iframe
|
||||
class="flex-1 w-full h-full border-none bg-black"
|
||||
src={url()}
|
||||
title="App Preview"
|
||||
sandbox="allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-popups"
|
||||
/>
|
||||
)}
|
||||
</Show>
|
||||
</Show>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user