feat(app): draft prompt state (#31452)

This commit is contained in:
Brendan Allan
2026-06-09 03:56:04 +00:00
committed by GitHub
parent 79cff288a6
commit 1a08ee77c7
+19 -12
View File
@@ -1,6 +1,6 @@
import { createSimpleContext } from "@opencode-ai/ui/context" import { createSimpleContext } from "@opencode-ai/ui/context"
import { checksum } from "@opencode-ai/core/util/encode" import { checksum } from "@opencode-ai/core/util/encode"
import { useParams } from "@solidjs/router" import { useParams, useSearchParams } from "@solidjs/router"
import { batch, createMemo, createRoot, getOwner, onCleanup } from "solid-js" import { batch, createMemo, createRoot, getOwner, onCleanup } from "solid-js"
import { createStore, type SetStoreFunction } from "solid-js/store" import { createStore, type SetStoreFunction } from "solid-js/store"
import type { FileSelection } from "@/context/file" import type { FileSelection } from "@/context/file"
@@ -153,9 +153,11 @@ const MAX_PROMPT_SESSIONS = 20
type PromptSession = ReturnType<typeof createPromptSession> type PromptSession = ReturnType<typeof createPromptSession>
type Scope = { type Scope = { draftID: string } | { dir: string; id?: string }
dir: string
id?: string function scopeKey(scope: Scope) {
if ("draftID" in scope) return `draft:${scope.draftID}`
return `${scope.dir}:${scope.id ?? WORKSPACE_KEY}`
} }
type PromptCacheEntry = { type PromptCacheEntry = {
@@ -163,11 +165,15 @@ type PromptCacheEntry = {
dispose: VoidFunction dispose: VoidFunction
} }
function createPromptSession(scope: ServerScope, dir: string, id: string | undefined) { function promptTarget(serverScope: ServerScope, scope: Scope) {
const legacy = `${dir}/prompt${id ? "/" + id : ""}.v2` if ("draftID" in scope) return Persist.draft(scope.draftID, "prompt")
const legacy = `${scope.dir}/prompt${scope.id ? "/" + scope.id : ""}.v2`
return Persist.serverScoped(serverScope, scope.dir, scope.id, "prompt", [legacy])
}
function createPromptSession(serverScope: ServerScope, scope: Scope) {
const [store, setStore, _, ready] = persisted( const [store, setStore, _, ready] = persisted(
Persist.serverScoped(scope, dir, id, "prompt", [legacy]), promptTarget(serverScope, scope),
createStore<{ createStore<{
prompt: Prompt prompt: Prompt
cursor?: number cursor?: number
@@ -231,6 +237,7 @@ export const { use: usePrompt, provider: PromptProvider } = createSimpleContext(
gate: false, gate: false,
init: () => { init: () => {
const params = useParams() const params = useParams()
const [search] = useSearchParams<{ draftId?: string }>()
const serverSDK = useServerSDK() const serverSDK = useServerSDK()
const cache = new Map<string, PromptCacheEntry>() const cache = new Map<string, PromptCacheEntry>()
@@ -254,8 +261,8 @@ export const { use: usePrompt, provider: PromptProvider } = createSimpleContext(
} }
const owner = getOwner() const owner = getOwner()
const load = (dir: string, id: string | undefined) => { const load = (scope: Scope) => {
const key = `${dir}:${id ?? WORKSPACE_KEY}` const key = scopeKey(scope)
const existing = cache.get(key) const existing = cache.get(key)
if (existing) { if (existing) {
cache.delete(key) cache.delete(key)
@@ -265,7 +272,7 @@ export const { use: usePrompt, provider: PromptProvider } = createSimpleContext(
const entry = createRoot( const entry = createRoot(
(dispose) => ({ (dispose) => ({
value: createPromptSession(serverSDK.scope, dir, id), value: createPromptSession(serverSDK.scope, scope),
dispose, dispose,
}), }),
owner, owner,
@@ -276,8 +283,8 @@ export const { use: usePrompt, provider: PromptProvider } = createSimpleContext(
return entry.value return entry.value
} }
const session = createMemo(() => load(params.dir!, params.id)) const session = createMemo(() => load(search.draftId ? { draftID: search.draftId } : { dir: params.dir!, id: params.id }))
const pick = (scope?: Scope) => (scope ? load(scope.dir, scope.id) : session()) const pick = (scope?: Scope) => (scope ? load(scope) : session())
return { return {
ready: () => session().ready, ready: () => session().ready,