Merge remote-tracking branch 'upstream/dev' into perf/session-timeline-virtua
This commit is contained in:
commit
f1dba7a9b8
280 changed files with 18931 additions and 6052 deletions
|
|
@ -240,13 +240,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||
return paths
|
||||
})
|
||||
const info = createMemo(() => (params.id ? sync.session.get(params.id) : undefined))
|
||||
const status = createMemo(
|
||||
() =>
|
||||
sync.data.session_status[params.id ?? ""] ?? {
|
||||
type: "idle",
|
||||
},
|
||||
)
|
||||
const working = createMemo(() => status()?.type !== "idle")
|
||||
const working = createMemo(() => sync.data.session_working(params.id ?? ""))
|
||||
const imageAttachments = createMemo(() =>
|
||||
prompt.current().filter((part): part is ImageAttachmentPart => part.type === "image"),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -208,6 +208,10 @@ export function createChildStoreManager(input: {
|
|||
session: [],
|
||||
sessionTotal: 0,
|
||||
session_status: {},
|
||||
session_working(id: string) {
|
||||
const type = this.session_status[id]?.type
|
||||
return (type ?? "idle") !== "idle"
|
||||
},
|
||||
session_diff: {},
|
||||
todo: {},
|
||||
permission: {},
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export type State = {
|
|||
session_status: {
|
||||
[sessionID: string]: SessionStatus
|
||||
}
|
||||
session_working(id: string): boolean
|
||||
session_diff: {
|
||||
[sessionID: string]: SnapshotFileDiff[]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,9 +166,7 @@ export const SessionItem = (props: SessionItemProps): JSX.Element => {
|
|||
})
|
||||
const isWorking = createMemo(() => {
|
||||
if (hasPermissions()) return false
|
||||
// This matches how the TUI does it
|
||||
const status = sessionStore.session_status[props.session.id]
|
||||
return status?.type === "busy" || status?.type === "retry"
|
||||
return sessionStore.session_working(props.session.id)
|
||||
})
|
||||
|
||||
const tint = createMemo(() => messageAgentColor(sessionStore.message[props.session.id], sessionStore.agent))
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ export const SortableProject = (props: {
|
|||
const isWorking = createMemo(() =>
|
||||
dirs().some((directory) => {
|
||||
const [store] = globalSync.child(directory, { bootstrap: false })
|
||||
return Object.values(store.session_status).some((status) => status?.type === "busy" || status?.type === "retry")
|
||||
return Object.keys(store.session_status).some((id) => store.session_working(id))
|
||||
}),
|
||||
)
|
||||
const projectSessions = createMemo(() => sortedRootSessions(projectStore(), props.sortNow()))
|
||||
|
|
|
|||
|
|
@ -1358,10 +1358,7 @@ export default function Page() {
|
|||
return out
|
||||
})
|
||||
|
||||
const busy = (sessionID: string) => {
|
||||
// This matches how the TUI does it
|
||||
return (sync.data.session_status[sessionID] ?? { type: "idle" as const }).type !== "idle"
|
||||
}
|
||||
const busy = (sessionID: string) => sync.data.session_working(sessionID)
|
||||
|
||||
const queuedFollowups = createMemo(() => {
|
||||
const id = params.id
|
||||
|
|
|
|||
|
|
@ -57,14 +57,7 @@ export function createSessionComposerState(options?: { closeMs?: number | (() =>
|
|||
() => todos().length > 0 && todos().every((todo) => todo.status === "completed" || todo.status === "cancelled"),
|
||||
)
|
||||
|
||||
const status = createMemo(() => {
|
||||
const id = params.id
|
||||
if (!id) return idle
|
||||
return sync.data.session_status[id] ?? idle
|
||||
})
|
||||
|
||||
const busy = createMemo(() => status().type !== "idle")
|
||||
const live = createMemo(() => busy() || blocked())
|
||||
const live = createMemo(() => sync.data.session_working(params.id ?? "") || blocked())
|
||||
|
||||
const [store, setStore] = createStore({
|
||||
responding: undefined as string | undefined,
|
||||
|
|
|
|||
|
|
@ -75,8 +75,6 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
|||
import.meta.env.VITE_OPENCODE_CHANNEL !== "beta" ||
|
||||
settings.general.showFileTree()
|
||||
|
||||
const idle = { type: "idle" as const }
|
||||
const status = () => sync.data.session_status[params.id ?? ""] ?? idle
|
||||
const messages = () => {
|
||||
const id = params.id
|
||||
if (!id) return []
|
||||
|
|
@ -290,7 +288,7 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
|||
const sessionID = params.id
|
||||
if (!sessionID) return
|
||||
|
||||
if (status().type !== "idle") {
|
||||
if (sync.data.session_working(params.id ?? "")) {
|
||||
await sdk.client.session.abort({ sessionID }).catch(() => {})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,4 +128,17 @@ describe("formatServerError", () => {
|
|||
["Modelo nao encontrado: x/y", "Voce quis dizer: x/y2, x/y3", "Revise provider/model no config"].join("\n"),
|
||||
)
|
||||
})
|
||||
|
||||
test("unwraps SDK-wrapped errors from cause.body", () => {
|
||||
const body = {
|
||||
name: "ConfigInvalidError",
|
||||
data: {
|
||||
message: "Missing host",
|
||||
},
|
||||
} satisfies ConfigInvalidError
|
||||
|
||||
const wrapped = new Error("ConfigInvalidError", { cause: { body, status: 400 } })
|
||||
|
||||
expect(formatServerError(wrapped, language.t)).toBe("Arquivo de config em config invalido: Missing host")
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -26,14 +26,22 @@ function tr(translator: Translator | undefined, key: string, text: string, vars?
|
|||
}
|
||||
|
||||
export function formatServerError(error: unknown, translate?: Translator, fallback?: string) {
|
||||
if (isConfigInvalidErrorLike(error)) return parseReadableConfigInvalidError(error, translate)
|
||||
if (isProviderModelNotFoundErrorLike(error)) return parseReadableProviderModelNotFoundError(error, translate)
|
||||
const unwrapped = unwrapNamedError(error)
|
||||
if (isConfigInvalidErrorLike(unwrapped)) return parseReadableConfigInvalidError(unwrapped, translate)
|
||||
if (isProviderModelNotFoundErrorLike(unwrapped)) return parseReadableProviderModelNotFoundError(unwrapped, translate)
|
||||
if (error instanceof Error && error.message) return error.message
|
||||
if (typeof error === "string" && error) return error
|
||||
if (fallback) return fallback
|
||||
return tr(translate, "error.chain.unknown", "Unknown error")
|
||||
}
|
||||
|
||||
function unwrapNamedError(error: unknown): unknown {
|
||||
if (error instanceof Error && error.cause && typeof error.cause === "object" && "body" in error.cause) {
|
||||
return (error.cause as Record<string, unknown>).body
|
||||
}
|
||||
return error
|
||||
}
|
||||
|
||||
function isConfigInvalidErrorLike(error: unknown): error is ConfigInvalidError {
|
||||
if (typeof error !== "object" || error === null) return false
|
||||
const o = error as Record<string, unknown>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue