Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
36ef6cc
fix(ai): finalize Bedrock redacted reasoning at block end (#51999)
rekram1-node Sep 29, 2026
34a8938
fix(ai): bind Bedrock Claude thinking blocks by default (#51959)
rekram1-node Sep 29, 2026
293d60a
chore(desktop): bump electron to 44.4.5 (#52005)
Hona Sep 29, 2026
41d4a9c
fix(session-ui): render moved notice as a timeline divider (#52009)
Hona Sep 29, 2026
a604b7f
fix(ui): calm diff word highlights with @pierre/diffs 1.5.1 (#51236)
Hona Sep 29, 2026
14af33d
fix(ai): show provider error bodies when no message is recognized (#5…
rekram1-node Sep 29, 2026
ff72659
fix(desktop): give isolated dev service a fixed port (#52013)
Hona Sep 29, 2026
2aaa265
fix(ai): read provider error messages from common body layouts (#52014)
rekram1-node Sep 29, 2026
6712cc4
fix(core): turn off Workers AI thinking through the chat template (#5…
rekram1-node Sep 29, 2026
b30c4d0
fix(ai): enable explicit caching on more message protocol routes (#51…
opencode-agent[bot] Sep 29, 2026
d76f968
feat(core): tell users how to sign back in to OpenCode Console (#51847)
vimtor Sep 29, 2026
b29dab3
fix(core): drop SSO link from Console sign-in error (#52062)
vimtor Sep 29, 2026
7ef4a1a
feat(tui): show recently closed tabs in new session menu
kitlangton Sep 29, 2026
0f931d3
chore(core): refresh bundled models.dev snapshot
opencode-agent[bot] Sep 29, 2026
948047a
fix(tui): use disclosure icon for low activity errors (#52097)
opencode-agent[bot] Sep 29, 2026
3126808
fix(ai): defer Mistral thinking metadata until block end (#52008)
rekram1-node Sep 29, 2026
a565ea8
feat(cli): allow disabling the background service (#52107)
opencode-agent[bot] Sep 29, 2026
83fafda
feat(cli): continue run after rejecting a permission ask (#51968)
jlongster Sep 29, 2026
7db941a
docs(console): add GPT 6.1 Sol to model list
fwang Sep 29, 2026
c14a1f5
feat(core): preserve provider response body in session errors (#52136)
rekram1-node Sep 29, 2026
bc5ff1c
fix(cli): answer subagent asks in run and keep parallel rejections co…
jlongster Sep 29, 2026
89d37a0
fix(core): restrict database files to their owner (#52150)
rekram1-node Sep 29, 2026
b694d2b
fix(core): explain ChatGPT token-sharing errors (#52158)
rekram1-node Sep 29, 2026
16ef62c
feat(app): show ChatGPT usage limit dialog (#52153)
rekram1-node Sep 29, 2026
621a5b0
feat(app): show ChatGPT token-sharing guidance (#52160)
rekram1-node Sep 29, 2026
4d90907
feat(core): add separate ChatGPT token-sharing OAuth method (#52147)
rekram1-node Sep 29, 2026
135995d
test: stabilize V2 CI test suites (#52159)
opencode-agent[bot] Sep 29, 2026
4c33a25
feat(cli): add auth export and auth import commands (#52139)
thdxr Sep 29, 2026
0f83038
fix(core): align ChatGPT token sharing with updated partner guide (#5…
rekram1-node Sep 29, 2026
4deda18
fix(app): align ChatGPT usage copy and links (#52163)
rekram1-node Sep 29, 2026
c2a39ac
fix(core): stop promising a ChatGPT usage reset (#52168)
rekram1-node Sep 29, 2026
a2fc196
fix(stats): match document background to page theme (#52169)
opencode-agent[bot] Sep 29, 2026
8d8a7bc
sync release versions for v2.0.20
Sep 29, 2026
cb7efec
chore(sync): merge upstream v2 through v2.0.20
cursoragent Sep 29, 2026
82349b5
test: stub connection status in fork plugin fixtures
cursoragent Sep 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(core): preserve provider response body in session errors (anomal…
  • Loading branch information
rekram1-node authored Sep 29, 2026
commit c14a1f5acfa4d73ad15fb927e34810a329f0df57
35 changes: 30 additions & 5 deletions packages/client/src/effect/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,12 @@ export type SessionLogOutput =
| undefined
readonly data: {
readonly sessionID: Session.ID
readonly error: { readonly type: string; readonly message: string; readonly status?: number | undefined }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number | undefined
readonly response?: { readonly body: string } | undefined
}
}
}
| {
Expand Down Expand Up @@ -902,7 +907,12 @@ export type SessionLogOutput =
readonly data: {
readonly sessionID: Session.ID
readonly assistantMessageID: SessionMessage.ID
readonly error: { readonly type: string; readonly message: string; readonly status?: number | undefined }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number | undefined
readonly response?: { readonly body: string } | undefined
}
readonly finish?: "content-filter" | undefined
readonly rawFinish?: string | undefined
readonly providerState?: SessionMessage.ProviderState | undefined
Expand Down Expand Up @@ -1112,7 +1122,12 @@ export type SessionLogOutput =
readonly sessionID: Session.ID
readonly assistantMessageID: SessionMessage.ID
readonly id: string
readonly error: { readonly type: string; readonly message: string; readonly status?: number | undefined }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number | undefined
readonly response?: { readonly body: string } | undefined
}
readonly content?:
| readonly [
(
Expand Down Expand Up @@ -1157,7 +1172,12 @@ export type SessionLogOutput =
readonly assistantMessageID: SessionMessage.ID
readonly attempt: number
readonly at: number
readonly error: { readonly type: string; readonly message: string; readonly status?: number | undefined }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number | undefined
readonly response?: { readonly body: string } | undefined
}
}
}
| {
Expand Down Expand Up @@ -1238,7 +1258,12 @@ export type SessionLogOutput =
readonly data: {
readonly sessionID: Session.ID
readonly reason: "auto" | "manual"
readonly error: { readonly type: string; readonly message: string; readonly status?: number | undefined }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number | undefined
readonly response?: { readonly body: string } | undefined
}
readonly inputID?: SessionMessage.ID | undefined
readonly cost?: (number & Brand.Brand<"Money.USD">) | undefined
readonly tokens?:
Expand Down
86 changes: 73 additions & 13 deletions packages/client/src/promise/generated/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export type ToolTextContent = { type: "text"; text: string }

export type ToolFileContent = { type: "file"; uri: string; mime: string; name?: string | null }

export type SessionStructuredError = { type: string; message: string; status?: number }
export type SessionStructuredError = { type: string; message: string; status?: number; response?: { body: string } }

export type SessionMessageCompactionRunning = {
type: "compaction"
Expand Down Expand Up @@ -3183,7 +3183,12 @@ export type SessionImportInput = {
| {
readonly status: "error"
readonly input: { readonly [x: string]: JsonValue }
readonly error: { readonly type: string; readonly message: string; readonly status?: number }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number
readonly response?: { readonly body: string }
}
readonly content?: readonly [
(
| { readonly type: "text"; readonly text: string }
Expand Down Expand Up @@ -3220,11 +3225,21 @@ export type SessionImportInput = {
readonly reasoning: number
readonly cache: { readonly read: number; readonly write: number }
}
readonly error?: { readonly type: string; readonly message: string; readonly status?: number }
readonly error?: {
readonly type: string
readonly message: string
readonly status?: number
readonly response?: { readonly body: string }
}
readonly retry?: {
readonly attempt: number
readonly at: number
readonly error: { readonly type: string; readonly message: string; readonly status?: number }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number
readonly response?: { readonly body: string }
}
}
}
| (
Expand Down Expand Up @@ -3276,7 +3291,12 @@ export type SessionImportInput = {
readonly time: { readonly created: number }
readonly status: "failed"
readonly reason: "auto" | "manual"
readonly error: { readonly type: string; readonly message: string; readonly status?: number }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number
readonly response?: { readonly body: string }
}
readonly cost?: number
readonly tokens?: {
readonly input: number
Expand Down Expand Up @@ -3500,7 +3520,12 @@ export type SessionImportInput = {
| {
readonly status: "error"
readonly input: { readonly [x: string]: JsonValue }
readonly error: { readonly type: string; readonly message: string; readonly status?: number }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number
readonly response?: { readonly body: string }
}
readonly content?: readonly [
(
| { readonly type: "text"; readonly text: string }
Expand Down Expand Up @@ -3537,11 +3562,21 @@ export type SessionImportInput = {
readonly reasoning: number
readonly cache: { readonly read: number; readonly write: number }
}
readonly error?: { readonly type: string; readonly message: string; readonly status?: number }
readonly error?: {
readonly type: string
readonly message: string
readonly status?: number
readonly response?: { readonly body: string }
}
readonly retry?: {
readonly attempt: number
readonly at: number
readonly error: { readonly type: string; readonly message: string; readonly status?: number }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number
readonly response?: { readonly body: string }
}
}
}
| (
Expand Down Expand Up @@ -3593,7 +3628,12 @@ export type SessionImportInput = {
readonly time: { readonly created: number }
readonly status: "failed"
readonly reason: "auto" | "manual"
readonly error: { readonly type: string; readonly message: string; readonly status?: number }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number
readonly response?: { readonly body: string }
}
readonly cost?: number
readonly tokens?: {
readonly input: number
Expand Down Expand Up @@ -3817,7 +3857,12 @@ export type SessionImportInput = {
| {
readonly status: "error"
readonly input: { readonly [x: string]: JsonValue }
readonly error: { readonly type: string; readonly message: string; readonly status?: number }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number
readonly response?: { readonly body: string }
}
readonly content?: readonly [
(
| { readonly type: "text"; readonly text: string }
Expand Down Expand Up @@ -3854,11 +3899,21 @@ export type SessionImportInput = {
readonly reasoning: number
readonly cache: { readonly read: number; readonly write: number }
}
readonly error?: { readonly type: string; readonly message: string; readonly status?: number }
readonly error?: {
readonly type: string
readonly message: string
readonly status?: number
readonly response?: { readonly body: string }
}
readonly retry?: {
readonly attempt: number
readonly at: number
readonly error: { readonly type: string; readonly message: string; readonly status?: number }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number
readonly response?: { readonly body: string }
}
}
}
| (
Expand Down Expand Up @@ -3910,7 +3965,12 @@ export type SessionImportInput = {
readonly time: { readonly created: number }
readonly status: "failed"
readonly reason: "auto" | "manual"
readonly error: { readonly type: string; readonly message: string; readonly status?: number }
readonly error: {
readonly type: string
readonly message: string
readonly status?: number
readonly response?: { readonly body: string }
}
readonly cost?: number
readonly tokens?: {
readonly input: number
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/session/to-session-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,10 @@ export function toSessionError(cause: unknown): SessionError.Error {

function providerError(type: string, reason: AIError["reason"]): SessionError.Error {
const status = reason.http?.status
return { type, message: reason.message, ...(status === undefined ? {} : { status }) }
return {
type,
message: reason.message,
...(status === undefined ? {} : { status }),
...(reason.body === undefined ? {} : { response: { body: reason.body } }),
}
}
9 changes: 9 additions & 0 deletions packages/core/test/session-error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ describe("toSessionError", () => {
type: "provider.invalid-request",
message: "too large",
status: 413,
response: { body: '{"error":"context limit"}' },
})
expect(
toSessionError(
Expand All @@ -127,6 +128,14 @@ describe("toSessionError", () => {
})
})

test("preserves provider response body without HTTP status", () => {
expect(toSessionError(llm(new RateLimitError({ message: "Slow down", body: '{"error":"rate limit"}' })))).toEqual({
type: "provider.rate-limit",
message: "Slow down",
response: { body: '{"error":"rate limit"}' },
})
})

test("preserves unresolved provider endpoint errors", () => {
const error = new ModelResolver.UnresolvedProviderVariablesError({
providerID: Provider.ID.make("cloudflare-workers-ai"),
Expand Down
1 change: 1 addition & 0 deletions packages/schema/src/session-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export const Error = Schema.Struct({
type: Schema.String,
message: Schema.String,
status: Schema.Int.check(Schema.isBetween({ minimum: 100, maximum: 599 })).pipe(optional),
response: Schema.Struct({ body: Schema.String }).pipe(optional),
}).annotate({ identifier: "Session.StructuredError" })
4 changes: 4 additions & 0 deletions packages/schema/test/session-error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ describe("SessionError", () => {
test("round trips current and future error types through JSON", () => {
const values: SessionError.Error[] = [
{ type: "provider.rate-limit", message: "Slow down" },
{ type: "provider.rate-limit", message: "Slow down", status: 429, response: { body: '{"error":{}}' } },
{ type: "provider.auth", message: "Authentication failed" },
{ type: "provider.future-condition", message: "A future provider failure" },
{ type: "unknown", message: "Unexpected" },
Expand All @@ -36,6 +37,9 @@ describe("SessionError", () => {
test("rejects missing envelope fields", () => {
expect(() => Schema.decodeUnknownSync(SessionError.Error)({ type: "provider.auth" })).toThrow()
expect(() => Schema.decodeUnknownSync(SessionError.Error)({ message: "Missing type" })).toThrow()
expect(() =>
Schema.decodeUnknownSync(SessionError.Error)({ type: "provider.auth", message: "Failed", response: {} }),
).toThrow()
})
})

Expand Down