Files
orca/src/shared/runtime-rpc-envelope.ts
T
Jinjing 60c26af8b8 fix(linear): preserve mixed-version RPC filtering compatibility (#8192)
* fix(linear): guard mixed-version RPC filtering

* fix(linear): surface filter capability failures correctly

Prevent capability checks from pinning to rejected compatibility cache
entries, and rethrow typed attribute-filter unsupported errors from the
Linear store so TaskPage can show an upgrade message instead of an empty
filtered list.

* fix(runtime): refresh cached capability verdicts

* test(linear): mock isLinearIssueAttributeFilterUnsupportedError

Prevents the invalidation slice test from failing after the runtime
client gained this export, which was otherwise undefined in the mock.

* Fix cold-cache capability probes firing duplicate status.get calls

Coalesce concurrent status.get requests for the same environment by
publishing the in-flight probe to the compatibility cache before
awaiting it, so parallel capability checks share one RPC call. On
failure, drop the cache entry immediately since this probe always
re-fetches and must not leave a stale cached verdict.
2026-07-10 19:23:12 -07:00

87 lines
1.8 KiB
TypeScript

// Why: runtime clients can be CLI, desktop, or future non-Electron shells.
// Keeping the envelope contract here avoids making those clients import each
// other just to validate the shared RPC frame shape.
import { z } from 'zod'
// Why: clients and runtimes update independently; strip additive envelope
// fields while continuing to validate every known discriminator and field.
const MetaSuccess = z
.object({
runtimeId: z.string()
})
.strip()
const MetaFailure = z
.object({
runtimeId: z.union([z.string(), z.null()])
})
.strip()
.optional()
const Success = z
.object({
id: z.string(),
ok: z.literal(true),
result: z.unknown(),
_meta: MetaSuccess
})
.strip()
const Failure = z
.object({
id: z.string(),
ok: z.literal(false),
error: z
.object({
code: z.string(),
message: z.string(),
data: z.unknown().optional()
})
.strip(),
_meta: MetaFailure
})
.strip()
const Keepalive = z
.object({
_keepalive: z.literal(true)
})
.strip()
export const RuntimeRpcEnvelopeSchema = z.union([Success, Failure, Keepalive])
export type RuntimeRpcSuccess<TResult> = {
id: string
ok: true
result: TResult
_meta: {
runtimeId: string
}
}
export type RuntimeRpcFailure = {
id: string
ok: false
error: {
code: string
message: string
data?: unknown
}
_meta?: {
runtimeId: string | null
}
}
export type RuntimeRpcResponse<TResult> = RuntimeRpcSuccess<TResult> | RuntimeRpcFailure
export type RuntimeRpcKeepaliveFrame = z.infer<typeof Keepalive>
export function isKeepaliveFrame(frame: unknown): frame is RuntimeRpcKeepaliveFrame {
return (
typeof frame === 'object' &&
frame !== null &&
'_keepalive' in frame &&
(frame as { _keepalive: unknown })._keepalive === true
)
}