mirror of
https://github.com/stablyai/orca.git
synced 2026-10-01 00:02:10 +00:00
* 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.
87 lines
1.8 KiB
TypeScript
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
|
|
)
|
|
}
|