mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
Check agent execution namespace types (#28370)
This commit is contained in:
@@ -8,7 +8,6 @@ src/main/runtime/orca-runtime-deliver-pending-messages.ts
|
||||
src/main/runtime/orca-runtime-automation-operations.ts
|
||||
src/main/runtime/orca-runtime-file-commands.ts
|
||||
src/main/runtime/orca-runtime-fit-override-listeners.ts
|
||||
src/main/runtime/orca-runtime-get-agent-session-execution-namespace.ts
|
||||
src/main/runtime/orca-runtime-has-exact-persisted-terminal-surface-identity.ts
|
||||
src/main/runtime/orca-runtime-linear-commands.ts
|
||||
src/main/runtime/orca-runtime-preserved-branch-cleanup.ts
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
RuntimeCreateAgentSessionResult
|
||||
} from '../../shared/agent-session-host-authority'
|
||||
import { OrcaRuntimeService } from './orca-runtime'
|
||||
import type { IPtyProvider } from '../providers/pty-provider-contract'
|
||||
|
||||
function operationId(now = Date.now()): string {
|
||||
return `${now}-0123456789abcdef0123456789abcdef`
|
||||
@@ -39,10 +40,12 @@ function terminal() {
|
||||
}
|
||||
}
|
||||
|
||||
function createRuntime(provider?: {
|
||||
supportsAgentSessionClaims?: () => boolean
|
||||
supportsAgentSessionCreateOperations?: () => boolean
|
||||
}) {
|
||||
function createRuntime(
|
||||
provider?: Pick<
|
||||
IPtyProvider,
|
||||
'supportsAgentSessionClaims' | 'supportsAgentSessionCreateOperations'
|
||||
>
|
||||
) {
|
||||
const runtime = new OrcaRuntimeService(
|
||||
{
|
||||
getSettings: () => ({
|
||||
@@ -109,6 +112,102 @@ async function fenceRemoteAgentSessionSpawn(runtime: OrcaRuntimeService) {
|
||||
return { createTerminal, failure, id }
|
||||
}
|
||||
|
||||
describe('agent-session execution namespace', () => {
|
||||
it('retains the original method owner, defaults and native async functions', () => {
|
||||
const runtime = createRuntime()
|
||||
let owner = Object.getPrototypeOf(runtime)
|
||||
while (!Object.hasOwn(owner, 'ensureAgentSession')) {
|
||||
owner = Object.getPrototypeOf(owner)
|
||||
}
|
||||
expect(owner.constructor.name).toBe('OrcaRuntimeWithGetAgentSessionExecutionNamespace')
|
||||
expect(Object.getOwnPropertyNames(owner)).toEqual([
|
||||
'constructor',
|
||||
'getAgentSessionExecutionNamespace',
|
||||
'executionOwnerSupportsAgentSessionOperation',
|
||||
'toAgentSessionOptions',
|
||||
'ensureAgentSession'
|
||||
])
|
||||
for (const [name, length, constructor] of [
|
||||
['getAgentSessionExecutionNamespace', 2, 'Function'],
|
||||
['executionOwnerSupportsAgentSessionOperation', 3, 'AsyncFunction'],
|
||||
['toAgentSessionOptions', 1, 'Function'],
|
||||
['ensureAgentSession', 1, 'AsyncFunction']
|
||||
]) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(owner, name)
|
||||
expect(descriptor?.value.length).toBe(length)
|
||||
expect(descriptor?.value.constructor.name).toBe(constructor)
|
||||
}
|
||||
})
|
||||
|
||||
it('calls the selected provider probe with its receiver and caller signal', async () => {
|
||||
const signal = new AbortController().signal
|
||||
const provider: Pick<IPtyProvider, 'supportsAgentSessionClaims'> = {
|
||||
async supportsAgentSessionClaims(options) {
|
||||
expect(this).toBe(provider)
|
||||
expect(options?.signal).toBe(signal)
|
||||
return true
|
||||
}
|
||||
}
|
||||
const runtime = createRuntime(provider)
|
||||
const createTerminal = vi.spyOn(runtime, 'createTerminal').mockResolvedValue(terminal())
|
||||
await runtime.ensureAgentSession(
|
||||
{
|
||||
kind: 'explicit',
|
||||
worktree: 'id:worktree-1',
|
||||
agent: 'codex',
|
||||
providerSession: { key: 'session_id', id: 'provider-session-1' }
|
||||
},
|
||||
{ signal }
|
||||
)
|
||||
expect(createTerminal).toHaveBeenCalledWith(
|
||||
'id:worktree-1',
|
||||
expect.objectContaining({ signal })
|
||||
)
|
||||
})
|
||||
|
||||
it('propagates probe getter failure before entering the probe failure fallback', async () => {
|
||||
const failure = new Error('probe getter failed')
|
||||
const runtime = createRuntime({
|
||||
get supportsAgentSessionClaims(): IPtyProvider['supportsAgentSessionClaims'] {
|
||||
throw failure
|
||||
}
|
||||
})
|
||||
const createTerminal = vi.spyOn(runtime, 'createTerminal').mockResolvedValue(terminal())
|
||||
await expect(
|
||||
runtime.ensureAgentSession({
|
||||
kind: 'explicit',
|
||||
worktree: 'id:worktree-1',
|
||||
agent: 'codex',
|
||||
providerSession: { key: 'session_id', id: 'provider-session-1' }
|
||||
})
|
||||
).rejects.toBe(failure)
|
||||
expect(createTerminal).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('captures the terminal callee before reading launch option getters', async () => {
|
||||
const runtime = createRuntime()
|
||||
const replacement = vi.fn(async () => terminal())
|
||||
const original = vi.spyOn(runtime, 'createTerminal').mockResolvedValue(terminal())
|
||||
const resume = {
|
||||
kind: 'explicit' as const,
|
||||
worktree: 'id:worktree-1',
|
||||
agent: 'codex' as const,
|
||||
providerSession: { key: 'session_id' as const, id: 'provider-session-1' },
|
||||
get terminalKittyKeyboardProtocol() {
|
||||
runtime.createTerminal = replacement
|
||||
return true
|
||||
}
|
||||
}
|
||||
await runtime.ensureAgentSession(resume)
|
||||
expect(original).toHaveBeenCalledOnce()
|
||||
expect(original.mock.calls[0]).toHaveLength(2)
|
||||
expect(replacement).not.toHaveBeenCalled()
|
||||
await runtime.ensureAgentSession(resume)
|
||||
expect(replacement).toHaveBeenCalledOnce()
|
||||
expect(replacement.mock.calls[0]).toHaveLength(2)
|
||||
})
|
||||
})
|
||||
|
||||
describe('agent-session create operation ledger', () => {
|
||||
it.each([true, false, undefined])(
|
||||
'forwards renderer keyboard support on create and resume: %s',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { BrowserWindow } from 'electron'
|
||||
import type { TerminalWorkspaceLaunchScope } from './runtime-legacy-worker-terminal-recovery-types'
|
||||
import { OrcaRuntimeWithGetAgentSessionExecutionNamespace } from './orca-runtime-get-agent-session-execution-namespace'
|
||||
import { OrcaRuntimeWithGetAgentSessionExecutionNamespace } from './session-construction/agent-session/get-agent-session-execution-namespace'
|
||||
import type {
|
||||
RuntimeAgentSessionRpcCaller,
|
||||
RuntimeCreateAgentSessionRequest,
|
||||
|
||||
+17
-15
@@ -1,30 +1,32 @@
|
||||
// @ts-nocheck -- mechanically split from OrcaRuntimeService; behavior is covered by AST equivalence and characterization tests.
|
||||
import { OrcaRuntimeWithResolveWorktreeRemovalTarget } from './workspaces/workspace-removal-target'
|
||||
import type { TerminalWorkspaceLaunchScope } from './runtime-legacy-worker-terminal-recovery-types'
|
||||
import type { TuiAgent } from '../../shared/tui-agent'
|
||||
import { parseWslUncPath } from '../../shared/wsl-paths'
|
||||
import { OrcaRuntimeWithResolveWorktreeRemovalTarget } from '../../workspaces/workspace-removal-target'
|
||||
import type { TerminalWorkspaceLaunchScope } from '../../runtime-legacy-worker-terminal-recovery-types'
|
||||
import type { TuiAgent } from '../../../../shared/tui-agent'
|
||||
import { parseWslUncPath } from '../../../../shared/wsl-paths'
|
||||
import type {
|
||||
AgentLaunchPreferences,
|
||||
RuntimeAgentSessionRpcCaller,
|
||||
RuntimeEnsureAgentSessionRequest,
|
||||
RuntimeEnsureAgentSessionResult
|
||||
} from '../../shared/agent-session-host-authority'
|
||||
import { canonicalizeAgentSessionIdentity } from './agent-session-claim-identity'
|
||||
import { isTuiAgentEnabled } from '../../shared/tui-agent-selection'
|
||||
import { buildAgentResumeStartupPlan } from '../../shared/tui-agent-startup'
|
||||
import { agentLaunchQuotingShell } from '../../shared/agent-launch-runtime'
|
||||
import { OrchestrationError } from './orchestration/orchestration-error'
|
||||
import { withAgentSessionAccountEnv } from './agent-session-account-env'
|
||||
} from '../../../../shared/agent-session-host-authority'
|
||||
import {
|
||||
canonicalizeAgentSessionIdentity,
|
||||
type ProviderExecutionNamespace
|
||||
} from '../../agent-session-claim-identity'
|
||||
import { isTuiAgentEnabled } from '../../../../shared/tui-agent-selection'
|
||||
import { buildAgentResumeStartupPlan } from '../../../../shared/tui-agent-startup'
|
||||
import { agentLaunchQuotingShell } from '../../../../shared/agent-launch-runtime'
|
||||
import { OrchestrationError } from '../../orchestration/orchestration-error'
|
||||
import { withAgentSessionAccountEnv } from '../../agent-session-account-env'
|
||||
import {
|
||||
resolveTuiAgentLaunchArgs,
|
||||
resolveTuiAgentLaunchEnv
|
||||
} from '../../shared/tui-agent-launch-defaults'
|
||||
} from '../../../../shared/tui-agent-launch-defaults'
|
||||
|
||||
export class OrcaRuntimeWithGetAgentSessionExecutionNamespace extends OrcaRuntimeWithResolveWorktreeRemovalTarget {
|
||||
export abstract class OrcaRuntimeWithGetAgentSessionExecutionNamespace extends OrcaRuntimeWithResolveWorktreeRemovalTarget {
|
||||
protected getAgentSessionExecutionNamespace(
|
||||
workspace: TerminalWorkspaceLaunchScope,
|
||||
agent: TuiAgent
|
||||
): { machine: string; principal: string; container: string; providerRoot: string } | null {
|
||||
): ProviderExecutionNamespace | null {
|
||||
if (workspace.connectionId) {
|
||||
// Why: SSH target ids are not execution-namespace proof. Preserve the
|
||||
// legacy launch until an attested route can safely participate in claims.
|
||||
Reference in New Issue
Block a user