Files
orca/src/cli/runtime/envelope-schema.test.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

167 lines
4.9 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { RuntimeRpcEnvelopeSchema, isKeepaliveFrame } from './envelope-schema'
describe('RuntimeRpcEnvelopeSchema', () => {
it('accepts a well-formed success envelope', () => {
const parsed = RuntimeRpcEnvelopeSchema.safeParse({
id: 'req-1',
ok: true,
result: { anything: 1 },
_meta: { runtimeId: 'runtime-1' }
})
expect(parsed.success).toBe(true)
})
it('accepts and strips additive future success fields', () => {
const parsed = RuntimeRpcEnvelopeSchema.safeParse({
id: 'req-1',
ok: true,
result: { value: 1, futureResultField: true },
futureEnvelopeField: 'new',
_meta: { runtimeId: 'runtime-1', futureMetaField: 2 }
})
expect(parsed).toEqual({
success: true,
data: {
id: 'req-1',
ok: true,
result: { value: 1, futureResultField: true },
_meta: { runtimeId: 'runtime-1' }
}
})
})
it('accepts a well-formed failure envelope', () => {
const parsed = RuntimeRpcEnvelopeSchema.safeParse({
id: 'req-1',
ok: false,
error: { code: 'not_found', message: 'not_found' },
_meta: { runtimeId: 'runtime-1' }
})
expect(parsed.success).toBe(true)
})
it('accepts structured failure data for agent recovery hints', () => {
const parsed = RuntimeRpcEnvelopeSchema.safeParse({
id: 'req-1',
ok: false,
error: {
code: 'app_not_found',
message: 'app not found: Gmail',
data: {
nextSteps: ['Target the desktop browser app/window that contains Gmail.']
}
},
_meta: { runtimeId: 'runtime-1' }
})
expect(parsed.success).toBe(true)
})
it('accepts and strips additive future failure fields', () => {
const parsed = RuntimeRpcEnvelopeSchema.safeParse({
id: 'req-1',
ok: false,
futureEnvelopeField: 'new',
error: {
code: 'failed',
message: 'Nope',
data: { retryable: true },
futureErrorField: 2
},
_meta: { runtimeId: 'runtime-1', futureMetaField: 3 }
})
expect(parsed).toEqual({
success: true,
data: {
id: 'req-1',
ok: false,
error: { code: 'failed', message: 'Nope', data: { retryable: true } },
_meta: { runtimeId: 'runtime-1' }
}
})
})
it('accepts a failure envelope without _meta', () => {
// Why: the runtime may fail before it has resolved its own runtimeId, in
// which case _meta is omitted. The schema must tolerate that rather than
// rejecting a legitimate failure as an invalid frame.
const parsed = RuntimeRpcEnvelopeSchema.safeParse({
id: 'req-1',
ok: false,
error: { code: 'runtime_unavailable', message: 'runtime_unavailable' }
})
expect(parsed.success).toBe(true)
})
it('rejects a frame missing the ok discriminator', () => {
const parsed = RuntimeRpcEnvelopeSchema.safeParse({
id: 'req-1',
result: {},
_meta: { runtimeId: 'runtime-1' }
})
expect(parsed.success).toBe(false)
})
it('rejects a frame with a non-string id', () => {
const parsed = RuntimeRpcEnvelopeSchema.safeParse({
id: 123,
ok: true,
result: {},
_meta: { runtimeId: 'runtime-1' }
})
expect(parsed.success).toBe(false)
})
it('still rejects malformed known fields when future fields are present', () => {
const parsed = RuntimeRpcEnvelopeSchema.safeParse({
id: 'req-1',
ok: false,
error: { code: 500, message: 'Nope', futureErrorField: true },
futureEnvelopeField: 'new'
})
expect(parsed.success).toBe(false)
})
it('rejects a frame with unrelated fields only', () => {
const parsed = RuntimeRpcEnvelopeSchema.safeParse({ hello: 'world' })
expect(parsed.success).toBe(false)
})
it('accepts a keepalive frame', () => {
const parsed = RuntimeRpcEnvelopeSchema.safeParse({ _keepalive: true })
expect(parsed.success).toBe(true)
})
it('rejects a keepalive frame with _keepalive !== true', () => {
const parsed = RuntimeRpcEnvelopeSchema.safeParse({ _keepalive: false })
expect(parsed.success).toBe(false)
})
})
describe('isKeepaliveFrame', () => {
it('returns true for a well-formed keepalive', () => {
expect(isKeepaliveFrame({ _keepalive: true })).toBe(true)
})
it('returns false for a success envelope', () => {
expect(isKeepaliveFrame({ id: 'x', ok: true, result: {}, _meta: { runtimeId: 'r' } })).toBe(
false
)
})
it('returns false for non-object inputs', () => {
expect(isKeepaliveFrame(null)).toBe(false)
expect(isKeepaliveFrame(undefined)).toBe(false)
expect(isKeepaliveFrame('keepalive')).toBe(false)
})
it('returns false when _keepalive is not strictly true', () => {
expect(isKeepaliveFrame({ _keepalive: 1 })).toBe(false)
expect(isKeepaliveFrame({ _keepalive: 'true' })).toBe(false)
})
})