test: reconcile low-value test removals with current main (#37997)

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
OrcaWin
2026-11-03 17:23:03 -08:00
committed by GitHub
co-authored by OrcaWin
parent 9c7fe9793e
commit 68ba160c12
43 changed files with 3 additions and 1574 deletions
-13
View File
@@ -1391,7 +1391,6 @@
"src/main/browser/sessions/browser-session-registry-startup-metadata.test.ts": 478,
"src/main/browser/sessions/browser-session-registry.persistence.test.ts": 1132,
"src/main/browser/sessions/browser-session-registry.test.ts": 883,
"src/main/browser/sessions/requests/browser-session-request-decisions.test.ts": 44,
"src/main/browser/identity/browser-session-ua-cloudflare-live.electron.test.ts": 312,
"src/main/browser/identity/browser-session-ua-wire-identity-cross-context.electron.test.ts": 7167,
"src/main/browser/identity/browser-session-ua-wire-identity.electron.test.ts": 8280,
@@ -7263,7 +7262,6 @@
"src/renderer/src/components/automations/AutomationDetail.test.tsx": 833,
"src/renderer/src/components/automations/AutomationEditorDialogFooter.test.tsx": 465,
"src/renderer/src/components/automations/AutomationEditorPromptEditor.test.tsx": 396,
"src/renderer/src/components/automations/AutomationEditorSettingsSidebar.test.tsx": 1193,
"src/renderer/src/components/automations/AutomationHostBadges.test.tsx": 561,
"src/renderer/src/components/automations/AutomationHostFilterNotice.test.tsx": 552,
"src/renderer/src/components/automations/AutomationListEmptyView.test.tsx": 419,
@@ -7347,7 +7345,6 @@
"src/renderer/src/components/automations/external-automation-list-entries.test.ts": 57,
"src/renderer/src/components/automations/external-automation-scope-gating.test.ts": 67,
"src/renderer/src/components/automations/external-automation-scope-keys.test.ts": 53,
"src/renderer/src/components/automations/external-automation-source-availability.test.ts": 205,
"src/renderer/src/components/automations/use-automation-host-catalog-readoption.test.tsx": 802,
"src/renderer/src/components/automations/use-automation-host-catalog.test.tsx": 920,
"src/renderer/src/components/automations/use-automation-list-focus-recovery.test.tsx": 229,
@@ -8783,7 +8780,6 @@
"src/renderer/src/components/settings/appearance/chat/AppearanceChatSection.test.tsx": 1633,
"src/renderer/src/components/settings/appearance/AppearancePane.test.tsx": 2066,
"src/renderer/src/components/settings/artifacts/ArtifactsSettingsPane.test.tsx": 862,
"src/renderer/src/components/settings/browser/routing/BrowserClientHostedRemoteSetting.test.tsx": 841,
"src/renderer/src/components/settings/browser/BrowserPane.search-catalog.test.tsx": 774,
"src/renderer/src/components/settings/browser/profiles/BrowserProfileRow.google-cookie-clear.test.tsx": 27636,
"src/renderer/src/components/settings/browser/BrowserSitePermissionsSetting.test.tsx": 739,
@@ -8797,7 +8793,6 @@
"src/renderer/src/components/settings/cli/install/CliSection.test.tsx": 2135,
"src/renderer/src/lib/skill-runtime-command.test.ts": 1670,
"src/renderer/src/components/settings/agents/behavior/CodexHistorySharingSetting.test.tsx": 539,
"src/renderer/src/components/settings/accounts/codex/CodexLoginLinkNotice.test.tsx": 494,
"src/renderer/src/components/settings/source-control/CommitMessageAiPane.test.tsx": 3099,
"src/renderer/src/components/settings/developer-permissions/DeveloperPermissionsPane.test.tsx": 2135,
"src/renderer/src/components/settings/virtual-machines/runtimes/EphemeralVmRuntimesSection.test.tsx": 2270,
@@ -8816,7 +8811,6 @@
"src/renderer/src/components/settings/mobile/MobilePane.test.tsx": 1581,
"src/renderer/src/components/settings/advanced/network/NodeDistMirrorDialog.test.tsx": 2412,
"src/renderer/src/components/settings/notifications/NotificationHostToggles.test.tsx": 646,
"src/renderer/src/components/settings/notifications/NotificationsPane.test.tsx": 1898,
"src/renderer/src/components/settings/orchestration/OrchestrationPane.test.tsx": 2437,
"src/renderer/src/components/settings/orchestration/OrchestrationSkillAgentCoverage.test.tsx": 320,
"src/renderer/src/components/plugins/list/PluginsSettingsSection.lifecycle.test.tsx": 5402,
@@ -9507,7 +9501,6 @@
"src/renderer/src/components/terminal-pane/TerminalPaneNativeChatPortal.test.tsx": 416,
"src/renderer/src/components/terminal-pane/TerminalPaneOverlayLayer.react185.test.tsx": 1251,
"src/renderer/src/components/terminal-pane/TerminalPaneRecoveryPortals.test.tsx": 670,
"src/renderer/src/components/terminal-pane/TerminalPaneResumeInChatButton.test.tsx": 581,
"src/renderer/src/components/terminal-pane/TerminalProcessExitOverlay.test.tsx": 481,
"src/renderer/src/components/terminal-pane/TerminalRemoteRuntimeReconnectBanner.test.tsx": 812,
"src/renderer/src/components/terminal-pane/TerminalSleepingPaneOverlay.test.tsx": 407,
@@ -9660,7 +9653,6 @@
"src/renderer/src/components/terminal-pane/pty-connection/deferred-session-reattach-startup-snapshot.test.ts": 1830,
"src/renderer/src/components/terminal-pane/pty-connection/deferred-session-reattach-wsl-distro-stopped-hold.test.ts": 2517,
"src/renderer/src/components/terminal-pane/pty-connection/disposed-spawn-retention.test.ts": 84,
"src/renderer/src/components/terminal-pane/pty-connection/empty-reattach-retire-evidence.test.ts": 63,
"src/renderer/src/components/terminal-pane/pty-connection/exited-split-pane-close.test.ts": 48,
"src/renderer/src/components/terminal-pane/pty-connection/foreground-output-budgets.test.ts": 41,
"src/renderer/src/components/terminal-pane/pty-connection/foreground-output-scan.test.ts": 92,
@@ -9687,7 +9679,6 @@
"src/renderer/src/components/terminal-pane/pty-connection/unbound-pane-spawn-recovery.test.ts": 53,
"src/renderer/src/components/terminal-pane/pty-connection/unserved-ssh-pane-bridge.test.ts": 70,
"src/renderer/src/components/terminal-pane/pty-connection/write-pty-output-idle-reset.test.ts": 157,
"src/renderer/src/components/terminal-pane/pty-connection/write-pty-output-to-xterm-startup-callback.test.ts": 116,
"src/renderer/src/components/terminal-pane/pty-dispatcher-delivery-interest.test.ts": 132,
"src/renderer/src/components/terminal-pane/pty-dispatcher-delivery-resync.test.ts": 85,
"src/renderer/src/components/terminal-pane/pty-dispatcher-pi-routing.test.ts": 1362,
@@ -10052,7 +10043,6 @@
"src/renderer/src/components/terminal/tab-type-cycle.test.ts": 60,
"src/renderer/src/components/terminal/terminal-close-incarnation.test.ts": 42,
"src/renderer/src/components/terminal/terminal-provider-snapshot-bound-pty-ids.test.ts": 1982,
"src/renderer/src/components/terminal/terminal-provider-snapshot-capability-resettlement.test.ts": 277,
"src/renderer/src/components/terminal/terminal-provider-snapshot-capability.test.ts": 68,
"src/renderer/src/components/terminal/terminal-tab-actions-unified-close.test.ts": 1831,
"src/renderer/src/components/terminal/terminal-tab-actions-unrouted-close.test.ts": 589,
@@ -10663,7 +10653,6 @@
"src/renderer/src/lib/simulator-pane-shutdown-scheduler.test.ts": 1679,
"src/renderer/src/lib/simulator-tab-layout-owner.test.ts": 2398,
"src/renderer/src/lib/simulator-tab-palette-activation.test.ts": 1903,
"src/renderer/src/lib/sleeping-agent-pane-ownership.test.ts": 66,
"src/renderer/src/lib/sleeping-agent-session-launch-windows-quoting.test.ts": 547,
"src/renderer/src/lib/smart-github-submit.test.ts": 112,
"src/renderer/src/lib/source-control-remote-error.test.ts": 340,
@@ -11650,7 +11639,6 @@
"src/shared/darwin-terminal-names-real-ps.test.ts": 42,
"src/shared/darwin-terminal-names.test.ts": 267,
"src/shared/darwin-terminal-naming-single-flight.test.ts": 69,
"src/shared/agent-launch/choices/default-agent-settings.test.ts": 31,
"src/shared/device-key-proof.test.ts": 112,
"src/shared/dictation-audio-meter.test.ts": 49,
"src/shared/dictation-transcript-spacing.test.ts": 48,
@@ -12605,7 +12593,6 @@
"src/shared/wsl-login-shell-nushell.test.ts": 66,
"src/shared/wsl-paths.test.ts": 48,
"src/shared/zcode-missing-tui.test.ts": 51,
"src/shared/zcode-orchestration-contract.test.ts": 247,
"src/shared/zod-salvage-absence.test.ts": 96,
"src/wsl-guest/agent-hook-canonical-status.test.ts": 2770,
"src/wsl-guest/agent-hook-envelope-publication.test.ts": 348,
@@ -29,33 +29,6 @@ const report = (payload: Omit<ParsedAgentStatusPayload, 'prompt'>): ParsedAgentS
})
describe('programStatusHookYieldEndsAt', () => {
it('applies when no hook row speaks for the pane', () => {
expect(programStatusHookYieldEndsAt(undefined, report({ state: 'working' }))).toBeUndefined()
expect(
programStatusHookYieldEndsAt(row({ state: 'working' }, {}, 'osc'), report({ state: 'done' }))
).toBeUndefined()
expect(
programStatusHookYieldEndsAt(
row({ state: 'done' }, { providerSessionOnly: true }),
report({ state: 'working' })
)
).toBeUndefined()
})
it('yields to a live hook row of the same agent until its hooks fall silent', () => {
const hook = row({ state: 'working', agentType: 'claude' })
expect(programStatusHookYieldEndsAt(hook, report({ state: 'done', agentType: 'claude' }))).toBe(
NOW + SILENCE
)
})
it('keeps yielding through a long silent tool call that the program agrees with', () => {
const hook = row({ state: 'working', agentType: 'claude' })
expect(
programStatusHookYieldEndsAt(hook, report({ state: 'working', agentType: 'claude' }))
).toBe(Infinity)
})
it('keeps a turn the hooks settled from a later block unless the program worked since', () => {
const hook = row({ state: 'done', agentType: 'antigravity' })
const block = report({ state: 'waiting', agentType: 'antigravity' })
@@ -104,19 +77,4 @@ describe('programStatusHookYieldEndsAt', () => {
)
}
})
it('yields to a mid-turn hook row under another app id, not to a finished one', () => {
expect(
programStatusHookYieldEndsAt(
row({ state: 'working', agentType: 'openclaude' }),
report({ state: 'done', agentType: 'claude' })
)
).toBe(NOW + SILENCE)
expect(
programStatusHookYieldEndsAt(
row({ state: 'done', agentType: 'claude' }),
report({ state: 'working', agentType: 'terraform' })
)
).toBeUndefined()
})
})
@@ -1,10 +1,6 @@
import { describe, expect, it, vi } from 'vitest'
import recordings from '../../shared/fixtures/source-control-launch-recordings.json'
import type { AgentLaunchIntent } from '../../shared/agent-launch/contracts/agent-launch-intent'
import { executeAgentLaunch } from './agent-launch-executor'
import { toAgentLaunchPreferences } from '../../shared/agent-launch/choices/agent-launch-preferences'
import { assertOpenCodeModelLaunchPreferencesAbsent } from '../opencode/opencode-model-startup-plan'
import { agentPermissionChoices } from '../../shared/agent-launch/permissions/tui-agent-permission-choice'
function harness() {
const readSettings = vi.fn(() => {
@@ -63,33 +59,6 @@ const creating: AgentLaunchIntent = {
}
describe('OpenCode model preferences on unsupported launch placements', () => {
it('keeps own selectable without projecting a meaningless permission into either terminal guard', async () => {
const sessionOptions = { permissionMode: 'own' }
const projected = toAgentLaunchPreferences(sessionOptions, 'opencode')
expect(agentPermissionChoices('opencode')).toContain('own')
expect(projected).toBeUndefined()
// Workspace creation consumes this projection through the same unchanged broad guard.
expect(() => assertOpenCodeModelLaunchPreferencesAbsent('opencode', projected)).not.toThrow()
for (const intent of [reused, creating]) {
const h = harness()
await expect(h.run({ ...intent, sessionOptions })).resolves.toBeDefined()
}
})
it('refuses the real OpenCode model readback on a reused terminal before prompt delivery', async () => {
const model = recordings.opencode.update.message.params.update.configOptions.find(
(option) => option.category === 'model'
)?.currentValue
expect(model).toBe('opencode/big-pickle')
const h = harness()
await expect(h.run({ ...reused, sessionOptions: { model } })).rejects.toMatchObject({
code: 'capability_unsupported'
})
expect(h.createTerminal).not.toHaveBeenCalled()
expect(h.createWorktree).not.toHaveBeenCalled()
expect(h.deliverPrompt).not.toHaveBeenCalled()
})
it.each([reused, creating])(
'preserves definitive refusal without creating or delivering when the route settings read throws',
async (intent) => {
@@ -19,7 +19,6 @@ vi.mock('electron', () => ({
}))
import {
AGENT_INPUT_FOCUS_GUARD_CHANNEL,
AGENT_INPUT_FOCUS_GUARD_READY_CHANNEL,
guardPaneFocusForAgentInput
} from './agent-input-focus-guard'
@@ -48,21 +47,6 @@ describe('guardPaneFocusForAgentInput', () => {
vi.useRealTimers()
})
it('resolves when the pane is ready and ends the guard once', async () => {
const { sent, renderer } = fakeRenderer(7, true)
const release = await guardPaneFocusForAgentInput(renderer, 'page-1')
release()
release()
expect(sent.map(({ channel, data }) => [channel, data.active])).toEqual([
[AGENT_INPUT_FOCUS_GUARD_CHANNEL, true],
[AGENT_INPUT_FOCUS_GUARD_CHANNEL, false]
])
expect(sent[0].data.token).toBe(sent[1].data.token)
expect(ipcListeners.get(AGENT_INPUT_FOCUS_GUARD_READY_CHANNEL)).toEqual([])
})
it('refuses the input and ends the guard when the pane never answers', async () => {
vi.useFakeTimers()
const { sent, renderer } = fakeRenderer(7, false)
@@ -121,23 +121,4 @@ describe('client host hosting identity wiring', () => {
await hostingIdentityForLaunch(mkdtempSync(join(tmpdir(), 'orca-host-wiring-')))
).not.toBe(await hostingIdentityForLaunch(mkdtempSync(join(tmpdir(), 'orca-host-wiring-'))))
})
it('attaches under the identity already stamped into the first window', async () => {
await launch(mkdtempSync(join(tmpdir(), 'orca-host-wiring-')))
// Windows receive the hosting id before pairing; the lease must reuse it.
const { getBrowserClientHostId } = await import('./browser-client-host-id')
const stamped = getBrowserClientHostId()
expect(await hostingIdentity()).toBe(stamped)
})
it('keeps hosting on a process-local identity when no profile was ever resolved', async () => {
vi.resetModules()
createHostCallbacks.length = 0
hostOptions.length = 0
const { getBrowserClientHostId } = await import('./browser-client-host-id')
expect(await hostingIdentity()).toBe(getBrowserClientHostId())
})
})
@@ -50,16 +50,6 @@ describe('browser client page metadata transport', () => {
)
})
it('refuses to publish once nothing is bound', async () => {
const transport = new BrowserClientPageMetadataTransport()
const sender = { sendPageMetadataRequest: vi.fn() }
transport.bind(sender)
transport.unbind(sender)
await expect(transport.publish(PARAMS)).rejects.toBeInstanceOf(RemoteRuntimeClientError)
expect(sender.sendPageMetadataRequest).not.toHaveBeenCalled()
})
it('leaves a replacement bound when the host it replaced unbinds', async () => {
const transport = new BrowserClientPageMetadataTransport()
const outgoing = { sendPageMetadataRequest: vi.fn() }
@@ -76,22 +66,6 @@ describe('browser client page metadata transport', () => {
})
describe('browser client page metadata routing', () => {
it('publishes through the transport of the environment that owns the page', async () => {
const owning = new BrowserClientPageMetadataTransport()
const other = new BrowserClientPageMetadataTransport()
const owningSend = vi.fn().mockResolvedValue(answered({ accepted: true }))
const otherSend = vi.fn()
owning.bind({ sendPageMetadataRequest: owningSend })
other.bind({ sendPageMetadataRequest: otherSend })
registerBrowserClientPageMetadataTransport('environment-a', owning)
registerBrowserClientPageMetadataTransport('environment-b', other)
await expect(publishBrowserClientPageMetadata('environment-a', PARAMS)).resolves.toEqual({
accepted: true
})
expect(otherSend).not.toHaveBeenCalled()
})
// Another environment detects accidental fallback to any registered transport.
it('fails a publish for an environment that hosts nothing while another one does', async () => {
const elsewhere = new BrowserClientPageMetadataTransport()
@@ -78,27 +78,4 @@ describe('declarativeNetRequest frame state', () => {
expect([1, 2].map((node) => blocked(engine, tracker, node))).toEqual([true, true])
expect(tracker.topOrigin(TAB)).toBe('https://shop.example')
})
it('tracks top origins without an engine and resolves tab ids once per document', () => {
let resolved = 0
let registered = false
const tracker = new DnrFrameTracker(() => {
resolved++
return registered ? 11 : -1
})
// A restored tab's first requests come before Orca's window lists it.
expect(tracker.tabIdFor(11)).toBe(-1)
registered = true
resolved = 0
expect([tracker.tabIdFor(11), tracker.tabIdFor(11), tracker.tabIdFor(undefined)]).toEqual([
11, 11, -1
])
expect(resolved).toBe(1)
tracker.commit(null, 11, asFrame(frame(1, 'https://a.example')), 'https://a.example/')
expect(tracker.topOrigin(11)).toBe('https://a.example')
tracker.tabIdFor(11)
expect(resolved).toBe(2)
tracker.forgetContents(11)
expect(tracker.topOrigin(11)).toBeNull()
})
})
@@ -50,12 +50,6 @@ const profileB = { name: 'b' } as unknown as Electron.Session
const focus = (window: Electron.BrowserWindow): boolean => window.emit('focus')
describe("a profile's extension windows", () => {
it('track the main window while extensions are off, so turning them on finds it', () => {
const main = new BrowserWindow()
model.trackBrowserExtensionMainWindow(main)
expect(model.getBrowserExtensionMainWindow()).toBe(main)
})
it("never include another profile's popout, in lookups or events", () => {
const main = new BrowserWindow()
model.trackBrowserExtensionMainWindow(main)
@@ -89,14 +89,6 @@ describe('Web Store download request ownership', () => {
expect(signals[0].aborted).toBe(true)
})
it('still rejects an invalid package after consuming its complete response', async () => {
const { fetcher, signals } = responseFetcher(new Response('bad'))
await expect(downloadWebStoreCrx(EXTENSION_ID, { fetcher })).rejects.toThrow('Not a CRX file')
expect(signals).toHaveLength(1)
expect(signals[0].aborted).toBe(true)
})
it('keeps an overlapping healthy icon alive until its own bytes finish', async () => {
let finishHealthy = (): void => {}
const healthyResponse = new Response(
@@ -56,18 +56,6 @@ describe('guest before-mouse-event forwarding', () => {
return mouse
}
it('reports a press into the page and steps history on a side-button release', () => {
expect(trigger(false, sideButton('mouseDown', 'back'))).not.toHaveBeenCalled()
expect(trigger(false, sideButton('mouseUp', 'back'))).not.toHaveBeenCalled()
trigger(false, sideButton('mouseUp', 'forward'))
expect(rendererSend.mock.calls).toEqual([
['ui:browserPagePointerDown', { browserPageId: 'tab-1' }],
['ui:browserHistoryNavigate', { browserPageId: 'tab-1', direction: 'back' }],
['ui:browserHistoryNavigate', { browserPageId: 'tab-1', direction: 'forward' }]
])
})
it('leaves presses an agent makes in the page to the page alone', () => {
agentInjection.active = true
try {
@@ -79,32 +67,6 @@ describe('guest before-mouse-event forwarding', () => {
expect(rendererSend).not.toHaveBeenCalled()
})
it('forwards plain wheel deltas only for an active preset', () => {
const preventDefault = trigger(true, { deltaX: 24, deltaY: 120 })
expect(preventDefault).toHaveBeenCalledTimes(1)
expect(rendererSend).toHaveBeenCalledWith('ui:scrollBrowserPage', {
browserPageId: 'tab-1',
deltaX: 24,
deltaY: 120
})
trigger(false, { deltaY: 120 })
expect(rendererSend).toHaveBeenCalledTimes(1)
})
it('ignores zero deltas and preserves ctrl-wheel zoom routing', () => {
const zeroPreventDefault = trigger(true, {})
expect(zeroPreventDefault).not.toHaveBeenCalled()
const zoomPreventDefault = trigger(true, { modifiers: ['ctrl'], deltaY: -120 })
expect(zoomPreventDefault).toHaveBeenCalledTimes(1)
expect(rendererSend).toHaveBeenLastCalledWith('ui:zoomBrowserPage', {
browserPageId: 'tab-1',
direction: 'in'
})
})
it('leaves fitting presets and host-edge wheels to the guest page', () => {
setupGuestMouseWheelZoomForwarding({
browserTabId: 'tab-1',
@@ -1,107 +0,0 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import {
answerBrowserSessionBeforeRequest,
installBrowserSessionHeadersReceived,
setBrowserSessionRequestDecider,
watchDecisionBlockedMainFrames,
type BrowserSessionRequestDecider
} from './browser-session-request-decisions'
import { setBrowserSessionWebRequestObserver } from './browser-session-web-request-observer'
type Listener = (details: unknown, callback: (response: unknown) => void) => void
function fakeSession() {
const listeners: Record<string, Listener | null> = {}
const register =
(event: string) =>
(...args: unknown[]): void => {
const listener = args.at(-1)
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the guard only registers a listener function here.
listeners[event] = typeof listener === 'function' ? (listener as Listener) : null
}
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the code under test touches only these webRequest members.
const session = {
webRequest: {
onBeforeRequest: vi.fn(register('onBeforeRequest')),
onHeadersReceived: vi.fn(register('onHeadersReceived'))
}
} as unknown as Electron.Session
const fire = (event: string, details: unknown): Promise<unknown> =>
new Promise((resolve) => listeners[event]?.(details, resolve))
return { session, fire }
}
function decider(overrides: Partial<BrowserSessionRequestDecider>): BrowserSessionRequestDecider {
return {
beforeRequest: () => null,
beforeSendHeaders: (_session, _details, headers) => headers,
headersReceived: () => null,
...overrides
}
}
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: a request carries only the fields these handlers read.
const request = {
id: 1,
url: 'https://ads.example/a.js',
method: 'GET',
resourceType: 'script',
referrer: '',
timestamp: 0,
webContentsId: 3
} as Electron.OnBeforeRequestListenerDetails
afterEach(() => setBrowserSessionRequestDecider(null))
describe('browser session request decisions', () => {
it('answers with the decision, waits for a held one, and fails open', async () => {
const { session } = fakeSession()
const answer = (): Promise<unknown> =>
new Promise((resolve) => answerBrowserSessionBeforeRequest(session, request, resolve))
await expect(answer()).resolves.toEqual({})
setBrowserSessionRequestDecider(decider({ beforeRequest: () => ({ cancel: true }) }))
await expect(answer()).resolves.toEqual({ cancel: true })
setBrowserSessionRequestDecider(
decider({ beforeRequest: async () => ({ redirectURL: 'https://safe.example/' }) })
)
await expect(answer()).resolves.toEqual({ redirectURL: 'https://safe.example/' })
vi.spyOn(console, 'warn').mockImplementation(() => {})
setBrowserSessionRequestDecider(
decider({
beforeRequest: () => {
throw new Error('boom')
}
})
)
await expect(answer()).resolves.toEqual({})
})
it('tells the guest when the decider blocks its main frame', async () => {
const { session } = fakeSession()
const blocked = vi.fn()
const stop = watchDecisionBlockedMainFrames(3, blocked)
setBrowserSessionRequestDecider(decider({ beforeRequest: async () => ({ cancel: true }) }))
const page = { ...request, resourceType: 'mainFrame', url: 'https://blocked.example/' } as const
await new Promise((resolve) => answerBrowserSessionBeforeRequest(session, page, resolve))
await new Promise((resolve) => answerBrowserSessionBeforeRequest(session, request, resolve))
expect(blocked.mock.calls).toEqual([['https://blocked.example/']])
stop()
await new Promise((resolve) => answerBrowserSessionBeforeRequest(session, page, resolve))
expect(blocked).toHaveBeenCalledOnce()
})
it('installs one onHeadersReceived that reports to observers and applies the decision', async () => {
const { session, fire } = fakeSession()
const observed = vi.fn()
setBrowserSessionWebRequestObserver(observed)
installBrowserSessionHeadersReceived(session)
installBrowserSessionHeadersReceived(session)
expect(session.webRequest.onHeadersReceived).toHaveBeenCalledOnce()
await expect(fire('onHeadersReceived', request)).resolves.toEqual({})
setBrowserSessionRequestDecider(decider({ headersReceived: () => ({ cancel: true }) }))
await expect(fire('onHeadersReceived', request)).resolves.toEqual({ cancel: true })
expect(observed).toHaveBeenCalledWith(session, 'onHeadersReceived', request)
})
})
@@ -61,17 +61,6 @@ describe('OpenCode worker model execution host', () => {
promptMode: 'submit'
})
})
it('checks only the version route for a model in a local folder', async () => {
expect(await probe(host())).toBe(true)
expect(probeOpenCodeLaunchCapabilities).toHaveBeenCalledExactlyOnceWith({
command: '/tmp/private-opencode',
agent: 'opencode',
cwd: '/tmp/folder',
env: expect.objectContaining({ OPENCODE_CONFIG_DIR: '/tmp/private-config' }),
hostIdentity: 'host-1'
})
expect(resolveOpenCodeDirectModelExecutable).not.toHaveBeenCalled()
})
it('refuses an unsafe version before model discovery or worker creation', async () => {
vi.mocked(probeOpenCodeLaunchCapabilities).mockResolvedValue({
version: '2.0.14',
@@ -1,80 +0,0 @@
// @vitest-environment happy-dom
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { AGENT_CATALOG } from '@/lib/agent-catalog'
import type { AutomationDraft } from './AutomationEditorDialog'
import { AutomationEditorSettingsSidebar } from './AutomationEditorSettingsSidebar'
// Why: only the Agent field is under test; the sibling fields own their own coverage.
vi.mock('./AutomationProjectCombobox', () => ({ default: () => null }))
vi.mock('./AutomationWorkspaceField', () => ({ AutomationWorkspaceField: () => null }))
vi.mock('./AutomationSessionField', () => ({ AutomationSessionField: () => null }))
vi.mock('./AutomationSchedulePicker', () => ({ AutomationSchedulePicker: () => null }))
vi.mock('./AutomationMissedRunGraceField', () => ({ AutomationMissedRunGraceField: () => null }))
vi.mock('./AutomationPrecheckFields', () => ({ AutomationPrecheckFields: () => null }))
vi.mock('./AutomationSetupDecisionField', () => ({ AutomationSetupDecisionField: () => null }))
vi.mock('./AutomationDestinationField', () => ({ AutomationDestinationField: () => null }))
vi.mock('./AutomationExtraAgentArgsField', () => ({ AutomationExtraAgentArgsField: () => null }))
const DRAFT: AutomationDraft = {
name: '',
prompt: '',
agentId: 'codex',
extraAgentArgs: '',
projectId: '',
workspaceMode: 'existing',
workspaceId: '',
baseBranch: '',
reuseSession: false,
precheckCommand: '',
precheckTimeoutSeconds: '30',
preset: 'weekly',
time: '09:15',
dayOfWeek: '5',
customSchedule: '',
missedRunGraceMinutes: '720',
savedSchedule: null,
scheduleWarning: null
}
function renderSidebar(onDraftChange: (updater: (d: AutomationDraft) => AutomationDraft) => void) {
return render(
<AutomationEditorSettingsSidebar
surface="terminal"
chatSupported={false}
repos={[]}
projectHostSetups={[]}
automationYamlHooksByRepoKey={{}}
getAutomationHooksCacheKey={(repoId) => repoId}
repoMap={new Map()}
worktrees={[]}
settings={null}
draft={DRAFT}
visibleAgents={AGENT_CATALOG}
pickerTriggerClassName=""
segmentedGroupClassName=""
segmentedItemClassName=""
onProjectChange={vi.fn()}
onDraftChange={onDraftChange}
onSetupDecisionTouched={vi.fn()}
/>
)
}
afterEach(cleanup)
describe('AutomationEditorSettingsSidebar agent picker', () => {
it('offers agents only, never Blank Terminal', () => {
const onDraftChange = vi.fn()
renderSidebar(onDraftChange)
fireEvent.click(screen.getByRole('combobox'))
expect(screen.queryByRole('option', { name: 'Blank Terminal' })).toBeNull()
fireEvent.click(screen.getByRole('option', { name: 'Claude' }))
expect(onDraftChange).toHaveBeenCalledTimes(1)
const updater = onDraftChange.mock.calls[0][0]
expect(updater(DRAFT).agentId).toBe('claude')
})
})
@@ -1,87 +0,0 @@
import { describe, expect, it } from 'vitest'
import type { ExternalAutomationManager } from '../../../../shared/automations-types'
import { getExternalAutomationActionDisabledMessage } from './external-automation-source-availability'
function manager(overrides: Partial<ExternalAutomationManager> = {}): ExternalAutomationManager {
return {
id: 'openclaw-local',
provider: 'openclaw',
label: 'OpenClaw',
targetLabel: 'Local Mac',
target: { type: 'local' },
status: 'unavailable',
error: null,
canManage: false,
jobs: [],
...overrides
}
}
describe('external automation action availability', () => {
it('explains disabled local automation actions when the source tool is missing', () => {
expect(
getExternalAutomationActionDisabledMessage({
manager: manager({
error: 'OpenClaw jobs were found, but the openclaw CLI is not on PATH.'
})
})
).toBe('OpenClaw jobs were found, but the openclaw CLI is not on PATH.')
})
it('explains disabled SSH automation actions before the host is connected', () => {
expect(
getExternalAutomationActionDisabledMessage({
manager: manager({
target: { type: 'ssh', connectionId: 'devbox' },
error: 'SSH target is not connected.'
}),
providerLabel: 'OpenClaw',
sshStatus: 'disconnected'
})
).toBe('Connect this SSH host before managing OpenClaw automations.')
})
it('explains disabled SSH automation actions while the host is connecting', () => {
expect(
getExternalAutomationActionDisabledMessage({
manager: manager({
target: { type: 'ssh', connectionId: 'devbox' },
error: 'SSH target is not connected.'
}),
sshStatus: 'deploying-relay'
})
).toBe('Wait for this SSH host to finish connecting.')
})
it('explains disabled SSH automation actions when the remote source tool is missing', () => {
expect(
getExternalAutomationActionDisabledMessage({
manager: manager({
target: { type: 'ssh', connectionId: 'devbox' },
error: 'OpenClaw CLI is not on the remote PATH.'
}),
sshStatus: 'connected'
})
).toBe('OpenClaw CLI is not on the remote PATH.')
})
it('keeps concrete remote source errors when SSH status is unavailable to the caller', () => {
expect(
getExternalAutomationActionDisabledMessage({
manager: manager({
target: { type: 'ssh', connectionId: 'devbox' },
error: 'OpenClaw CLI is not on the remote PATH.'
})
})
).toBe('OpenClaw CLI is not on the remote PATH.')
})
it('explains disabled actions while another automation action is running', () => {
expect(
getExternalAutomationActionDisabledMessage({
manager: manager({ canManage: true }),
actionInProgress: true
})
).toBe('Another automation action is still running.')
})
})
@@ -67,12 +67,4 @@ describe('chat tip visual lifetime', () => {
expect(vi.getTimerCount()).toBe(0)
expect(container.innerHTML).toBe(finished)
})
it('starts as a complete still with reduced motion and no timer', () => {
vi.useFakeTimers()
motion(true)
const { container } = render(<ChatUiHereFeatureTipVisual />)
expect(vi.getTimerCount()).toBe(0)
expect(container.querySelectorAll('[data-on="true"]').length).toBeGreaterThan(10)
})
})
@@ -1,87 +0,0 @@
// @vitest-environment happy-dom
import { cleanup, fireEvent, render, waitFor } from '@testing-library/react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { i18n } from '../../../../i18n/i18n'
import { CodexLoginLinkNotice } from './CodexLoginLinkNotice'
const AUTH_URL = 'https://auth.openai.com/oauth/authorize?client_id=orca&state=abc123'
type LinkListener = (url: string | null) => void
function stubApi(pendingUrl: string | null): {
listeners: LinkListener[]
writeClipboardText: ReturnType<typeof vi.fn>
openUrl: ReturnType<typeof vi.fn>
} {
const listeners: LinkListener[] = []
const writeClipboardText = vi.fn(() => Promise.resolve())
const openUrl = vi.fn(() => Promise.resolve())
Object.defineProperty(globalThis, 'api', {
configurable: true,
value: {
codexAccounts: {
getPendingLoginUrl: () => Promise.resolve(pendingUrl),
onPendingLoginUrlChanged: (listener: LinkListener) => {
listeners.push(listener)
return () => {
listeners.splice(listeners.indexOf(listener), 1)
}
}
},
ui: { writeClipboardText },
shell: { openUrl }
}
})
return { listeners, writeClipboardText, openUrl }
}
afterEach(() => {
cleanup()
Reflect.deleteProperty(globalThis, 'api')
})
describe('CodexLoginLinkNotice', () => {
beforeEach(async () => {
await i18n.changeLanguage('en')
})
it('shows the link of a login that was already running when Settings opened', async () => {
stubApi(AUTH_URL)
const { container } = render(<CodexLoginLinkNotice />)
await waitFor(() => expect(container.textContent).toContain(AUTH_URL))
})
it('copies the link and opens it in the default browser on request', async () => {
const { listeners, writeClipboardText, openUrl } = stubApi(null)
const { container } = render(<CodexLoginLinkNotice />)
await waitFor(() => expect(listeners.length).toBe(1))
listeners[0](AUTH_URL)
await waitFor(() => expect(container.textContent).toContain('Copy link'))
const button = (label: string): HTMLButtonElement => {
const found = Array.from(container.querySelectorAll('button')).find((candidate) =>
candidate.textContent?.includes(label)
)
expect(found).not.toBeUndefined()
return found!
}
fireEvent.click(button('Copy link'))
await waitFor(() => expect(writeClipboardText).toHaveBeenCalledWith(AUTH_URL))
await waitFor(() => expect(container.textContent).toContain('Copied'))
fireEvent.click(button('Open'))
expect(openUrl).toHaveBeenCalledWith(AUTH_URL)
})
it('drops the link once the login ends', async () => {
const { listeners } = stubApi(AUTH_URL)
const { container } = render(<CodexLoginLinkNotice />)
await waitFor(() => expect(container.textContent).toContain(AUTH_URL))
listeners[0](null)
await waitFor(() => expect(container.textContent).toBe(''))
})
})
@@ -1,68 +0,0 @@
// @vitest-environment happy-dom
// @vitest-environment happy-dom
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { TooltipProvider } from '../../../ui/tooltip'
import { BrowserClientHostedRemoteSetting } from './BrowserClientHostedRemoteSetting'
import { getBrowserPaneSearchEntries } from '../browser-search'
import { matchesSettingsSearch } from '../../search/settings-search'
import { getBrowserClientHostedRemoteTitle } from './browser-client-hosted-remote-copy'
import type { GlobalSettings } from '../../../../../../shared/global-settings-types'
vi.mock('../../../../store/index', () => ({
useAppStore: (selector: (state: { settingsSearchQuery: string }) => unknown) =>
selector({ settingsSearchQuery: '' })
}))
function renderSetting(
settings: Pick<GlobalSettings, 'browserClientHostedRemoteEnabled'>,
updateSettings: (updates: Partial<GlobalSettings>) => void = vi.fn()
): void {
render(
<TooltipProvider>
<BrowserClientHostedRemoteSetting settings={settings} updateSettings={updateSettings} />
</TooltipProvider>
)
}
describe('BrowserClientHostedRemoteSetting', () => {
afterEach(() => {
cleanup()
})
it('defaults to this-device rendering when the profile predates the flag', () => {
renderSetting({})
expect(screen.getByRole('radio', { name: 'This device' }).getAttribute('aria-checked')).toBe(
'true'
)
expect(screen.getByText(/new pages only/i)).toBeTruthy()
})
it('reads an explicit opt-out as server-streamed rendering', () => {
renderSetting({ browserClientHostedRemoteEnabled: false })
expect(
screen.getByRole('radio', { name: 'Server (streamed)' }).getAttribute('aria-checked')
).toBe('true')
})
it('writes the chosen placement through the global settings path', () => {
const updateSettings = vi.fn()
renderSetting({ browserClientHostedRemoteEnabled: true }, updateSettings)
fireEvent.click(screen.getByRole('radio', { name: 'Server (streamed)' }))
expect(updateSettings).toHaveBeenLastCalledWith({ browserClientHostedRemoteEnabled: false })
fireEvent.click(screen.getByRole('radio', { name: 'This device' }))
expect(updateSettings).toHaveBeenLastCalledWith({ browserClientHostedRemoteEnabled: true })
})
it('is findable from settings search by its own title', () => {
const entry = getBrowserPaneSearchEntries({ isMac: false }).find(
(candidate) => candidate.title === getBrowserClientHostedRemoteTitle()
)
expect(entry).toBeDefined()
expect(matchesSettingsSearch(getBrowserClientHostedRemoteTitle(), entry ?? [])).toBe(true)
expect(matchesSettingsSearch('placement', entry ?? [])).toBe(true)
expect(matchesSettingsSearch('new pages only', entry ?? [])).toBe(true)
expect(matchesSettingsSearch('unrelated setting query', entry ?? [])).toBe(false)
})
})
@@ -3,7 +3,6 @@
import '@testing-library/jest-dom/vitest'
import { cleanup, render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { MobilePairingQrSection } from './MobilePairingQrSection'
@@ -14,31 +13,6 @@ vi.mock('@/i18n/i18n', () => ({
afterEach(cleanup)
describe('MobilePairingQrSection', () => {
it('shows and copies the pairing URL when QR encoding fails', async () => {
const writeClipboardText = vi.fn().mockResolvedValue(undefined)
Object.defineProperty(window, 'api', {
configurable: true,
value: { ui: { writeClipboardText } }
})
render(
<MobilePairingQrSection
qrDataUrl={null}
qrError
pairingUrl="orca://pair?code=copy-fallback"
endpoint="wss://host.example/large"
qrEnlarged={false}
codeCopied={false}
onQrEnlargedChange={vi.fn()}
onCodeCopiedChange={vi.fn()}
onClearCodeCopiedTimer={vi.fn()}
/>
)
expect(screen.getByRole('alert')).toHaveTextContent('couldn’t be rendered as a QR code')
await userEvent.click(screen.getByRole('button', { name: 'Copy pairing code' }))
expect(writeClipboardText).toHaveBeenCalledWith('orca://pair?code=copy-fallback')
})
it('moves focus to the copy action when a pairing code becomes ready', () => {
const props = {
qrDataUrl: null,
@@ -1,94 +0,0 @@
import { createGlobalSettingsFixture } from '../../../../../shared/global-settings-test-fixture'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { GlobalSettings } from '../../../../../shared/global-settings-types'
import type { NotificationDispatchRequest } from '../../../../../shared/notification-settings-types'
import { sendNotificationSettingsTestNotification } from './notification-settings-copy'
const { toastError, toastMessage, toastSuccess } = vi.hoisted(() => ({
toastError: vi.fn(),
toastMessage: vi.fn(),
toastSuccess: vi.fn()
}))
vi.mock('sonner', () => ({
toast: {
error: toastError,
message: toastMessage,
success: toastSuccess
}
}))
function createSettings(): GlobalSettings {
return createGlobalSettingsFixture({
notifications: {
enabled: true,
agentTaskComplete: true,
agentNeedsInput: true,
terminalBell: true,
suppressWhenFocused: true,
customSoundId: 'system',
customSoundPath: null,
customSoundVolume: 50,
mutedNotificationSourceIds: [],
notifyHiddenWorkspaces: false
}
})
}
describe('NotificationsPane', () => {
beforeEach(() => {
toastError.mockClear()
toastMessage.mockClear()
toastSuccess.mockClear()
})
afterEach(() => {
vi.unstubAllGlobals()
})
it('uses native main-process delivery even when renderer permission is stale denied on macOS', async () => {
const notifications = {
getPermissionStatus: vi.fn(async () => ({
supported: true,
platform: 'darwin' as NodeJS.Platform,
requested: true
})),
dispatch: vi.fn(async (_args: NotificationDispatchRequest) => ({ delivered: true })),
playSound: vi.fn(),
openSystemSettings: vi.fn(),
requestPermission: vi.fn()
}
vi.stubGlobal('window', {
Notification: { permission: 'denied' },
api: {
notifications,
shell: { pickAudio: vi.fn() }
}
})
await sendNotificationSettingsTestNotification(createSettings().notifications, 50)
// Probe main-process Electron delivery; renderer permission state can remain stale after macOS settings change.
expect(notifications.dispatch).toHaveBeenCalledWith({
source: 'test',
requireDisplayConfirmation: true
})
expect(toastError).not.toHaveBeenCalled()
expect(toastSuccess).not.toHaveBeenCalled()
expect(toastMessage).toHaveBeenCalledWith(
'Test notification requested',
expect.objectContaining({
description: 'If no macOS banner appeared, enable Allow notifications for Orca.',
action: expect.objectContaining({ label: 'Open Settings' })
})
)
const toastOptions = toastMessage.mock.calls[0]?.[1] as
| { action?: { onClick?: () => void } }
| undefined
toastOptions?.action?.onClick?.()
expect(notifications.openSystemSettings).toHaveBeenCalledTimes(1)
})
})
@@ -1,86 +0,0 @@
// @vitest-environment happy-dom
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
import { TooltipProvider } from '@/components/ui/tooltip'
import { TerminalPaneResumeInChatButton } from './TerminalPaneResumeInChatButton'
import type { CliChatResumeSource } from '../tab-bar/cli-chat-resume-source'
const LOCAL_SOURCE: CliChatResumeSource = {
tabId: 'tab-1',
workspaceId: 'wt-1',
paneKey: 'tab-1:leaf',
agent: 'claude',
providerSessionId: 'provider-1',
executionHostId: 'local'
}
const mocks = vi.hoisted(() => {
const source: { current: CliChatResumeSource | null } = { current: null }
return { source, resolve: vi.fn(), run: vi.fn(), pending: false }
})
vi.mock('@/store', () => ({
useAppStore: (selector: (state: Record<string, unknown>) => unknown) => selector({})
}))
vi.mock('../tab-bar/cli-chat-resume-source', () => ({
resolveCliChatResumeSource: (_state: unknown, args: unknown) => {
mocks.resolve(args)
return mocks.source.current
}
}))
vi.mock('../tab-bar/cli-chat-resume-run', () => ({
runCliChatResume: mocks.run,
useCliChatResumePending: () => mocks.pending
}))
beforeEach(() => {
mocks.source.current = LOCAL_SOURCE
})
afterEach(cleanup)
it('dispatches the exact pane with owner-opening intent and shares pending', () => {
const { rerender } = render(
<TooltipProvider>
<TerminalPaneResumeInChatButton tabId="tab-1" worktreeId="wt-1" paneKey="tab-1:leaf" />
</TooltipProvider>
)
fireEvent.click(screen.getByRole('button', { name: 'Continue in Chat UI' }))
expect(mocks.resolve).toHaveBeenCalledWith({
tab: { id: 'tab-1', worktreeId: 'wt-1' },
paneKey: 'tab-1:leaf'
})
expect(mocks.run).toHaveBeenCalledWith(LOCAL_SOURCE, true)
mocks.pending = true
rerender(
<TooltipProvider>
<TerminalPaneResumeInChatButton tabId="tab-1" worktreeId="wt-1" paneKey="tab-1:leaf" />
</TooltipProvider>
)
expect(screen.getByRole('button').getAttribute('aria-busy')).toBe('true')
expect(screen.getByRole('button').hasAttribute('disabled')).toBe(true)
})
it('keeps an older host visible but disabled, telling the user to update it', async () => {
mocks.pending = false
mocks.run.mockClear()
mocks.source.current = {
...LOCAL_SOURCE,
executionHostId: 'runtime:server-1',
hostUpdateRequired: true
}
render(
<TooltipProvider delayDuration={0}>
<TerminalPaneResumeInChatButton tabId="tab-1" worktreeId="wt-1" paneKey="tab-1:leaf" />
</TooltipProvider>
)
const button = screen.getByRole('button', {
name: 'Continue in Chat UI. Update Orca on this host to continue in Chat UI.'
})
expect(button.hasAttribute('disabled')).toBe(true)
const trigger = button.parentElement
if (trigger) {
fireEvent.focus(trigger)
}
expect(
(await screen.findAllByText('Update Orca on this host to continue in Chat UI.')).length
).toBeGreaterThan(0)
expect(mocks.run).not.toHaveBeenCalled()
})
@@ -1,83 +0,0 @@
import { describe, expect, it } from 'vitest'
import { hasEmptyReattachRetireEvidence } from './empty-reattach-retire-evidence'
import { isHibernationDoneRecord } from '../../../../../shared/hibernation-done-record'
import type { SleepingAgentSessionRecord } from '../../../../../shared/agent-session/lifecycle/agent-session-resume'
import type { ColdRestoreAgentResumeStartup } from './fresh-spawn-types'
function note(overrides: Partial<SleepingAgentSessionRecord> = {}): SleepingAgentSessionRecord {
return {
paneKey: 'tab-1:leaf-1',
worktreeId: 'wt-1',
agent: 'codex',
providerSession: { key: 'session_id', id: 'conv-1' },
prompt: '',
state: 'done',
capturedAt: 1,
updatedAt: 1,
...overrides
}
}
function resumeStartup(
record: SleepingAgentSessionRecord | null,
useLiveEntry = false
): ColdRestoreAgentResumeStartup {
return {
command: 'codex resume conv-1',
agent: 'codex',
resumeOrigin: 'saved',
resumeProviderSession: { key: 'session_id', id: 'conv-1' },
launchConfig: { agentArgs: '', agentEnv: {} },
launchToken: 'token-1',
useLiveEntry,
hasSleepingRecord: record !== null,
sleepingRecordEntry: record ? { paneKey: record.paneKey, record } : null
}
}
const WORKTREE_SLEEP_DONE = note({ origin: 'worktree-sleep' })
describe('isHibernationDoneRecord', () => {
it.each([
['a legacy originless done note', true, note()],
['a worktree-sleep done note', true, WORKTREE_SLEEP_DONE],
['a live done note (the idle anchor of a running pane)', false, note({ origin: 'live' })],
[
'a live done note marked not interrupted',
false,
note({ origin: 'live', interrupted: false })
],
['a quit done note', false, note({ origin: 'quit' })],
[
'a worktree-sleep note still working',
false,
note({ origin: 'worktree-sleep', state: 'working' })
]
])('%s -> %s', (_label, expected, record) => {
expect(isHibernationDoneRecord(record)).toBe(expected)
})
})
describe('hasEmptyReattachRetireEvidence', () => {
it.each([
['a local pty', 'local-pty-1'],
['a local daemon session id', 'wt-1@@daemon-session-1']
])('retires %s under a hibernation done note', (_label, ptyId) => {
expect(hasEmptyReattachRetireEvidence(ptyId, resumeStartup(WORKTREE_SLEEP_DONE))).toBe(true)
})
it('never retires a remote runtime pty, whose disconnect leaves the host PTY alive', () => {
expect(
hasEmptyReattachRetireEvidence('remote:env-1@@term_1', resumeStartup(WORKTREE_SLEEP_DONE))
).toBe(false)
})
it.each([
['no resume startup', undefined],
['a startup resuming the live entry', resumeStartup(WORKTREE_SLEEP_DONE, true)],
['a startup without a sleeping note', resumeStartup(null)],
['a live done note', resumeStartup(note({ origin: 'live' }))]
])('keeps a local pty with %s', (_label, startup) => {
expect(hasEmptyReattachRetireEvidence('local-pty-1', startup)).toBe(false)
})
})
@@ -1,69 +0,0 @@
import { describe, expect, it, vi } from 'vitest'
import { bindWritePtyOutputToXterm } from './write-pty-output-to-xterm'
import { createTerminalInputEchoDelay } from './terminal-input-echo-delay'
import { TerminalIdleCursorReset } from '../terminal-idle-cursor-reset'
const writeTerminalOutput = vi.hoisted(() => vi.fn())
const forceFullViewportPresent = vi.hoisted(() => vi.fn())
vi.mock('@/lib/pane-manager/pane-terminal-output-scheduler', () => ({
writeTerminalOutput
}))
vi.mock('@/lib/pane-manager/terminal-render-pause-release', () => ({
forceFullViewportPresent
}))
vi.mock('@/lib/pane-manager/terminal-delivery-credit', () => ({
takeCurrentTerminalDeliveryCredit: vi.fn(() => undefined)
}))
function createSession(startupOnParsed: () => void) {
const terminal = {}
return {
kittyKeyboardModes: { scan: vi.fn() },
resetHiddenOutputRestoreIfPtyChanged: vi.fn(),
transport: { getPtyId: vi.fn(() => 'pty-1') },
canUseHiddenOutputSnapshot: vi.fn(() => false),
shouldSnapshotHiddenCodexOutput: false,
shouldProtectNativeWindowsSynchronizedOutput: true,
shouldApplyNativeWindowsRewriteRefresh: false,
synchronizedForegroundMarkerTail: '',
synchronizedForegroundOutputActive: true,
synchronizedForegroundFrameInteractive: false,
synchronizedForegroundInteractivePresentPending: true,
lastTerminalInputAt: 0,
inputEchoDelay: createTerminalInputEchoDelay(),
idleCursorReset: new TerminalIdleCursorReset(),
scheduleForegroundGridDriftCheck: vi.fn(),
shouldForceForegroundRenderRefresh: vi.fn(() => ({ refresh: false, inPlaceRewrite: false })),
isLatencySensitiveForegroundOutput: vi.fn(() => false),
shouldRefreshForegroundSynchronously: false,
beforeTerminalOutputWrite: undefined,
markHiddenOutputRestoreNeeded: vi.fn(),
startupTiming: {
firstWrite: vi.fn(() => ({ beforeWrite: vi.fn(), onParsed: startupOnParsed }))
},
writePtyOutputToXterm: vi.fn(),
pane: { terminal }
}
}
describe('bindWritePtyOutputToXterm startup callbacks', () => {
it('composes startup timing and synchronized-frame presentation callbacks', () => {
const startupOnParsed = vi.fn()
const session = createSession(startupOnParsed)
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the fixture supplies exactly the fields read by this isolated binding test.
bindWritePtyOutputToXterm(session as never)
session.writePtyOutputToXterm?.('\x1b[?2026hframe', true, { liveStartupBatch: true })
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the scheduler mock receives the binding's documented options object.
const options = writeTerminalOutput.mock.calls[0]?.[2] as {
onParsed?: () => void
}
options.onParsed?.()
expect(startupOnParsed).toHaveBeenCalledOnce()
expect(forceFullViewportPresent).toHaveBeenCalledWith(session.pane.terminal)
})
})
@@ -1,69 +0,0 @@
/** Unknown capabilities retain panes during outages but must be re-asked after recovery to release eviction exemptions. */
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { PTY_SESSION_ID_SEPARATOR } from '../../../../shared/pty-session-id-format'
import { isEvictionExemptTerminalPty } from '../terminal-pane/terminal-hidden-worktree-retention'
import {
clearTerminalProviderSnapshotCapabilities,
synchronizeTerminalProviderSnapshotCapabilities,
terminalProviderHasAuthoritativeSnapshot
} from './terminal-provider-snapshot-capability'
const WORKTREE_ID = 'wt-resettlement'
const PTY_ID = `${WORKTREE_ID}${PTY_SESSION_ID_SEPARATOR}session-1`
async function exhaustRetryBudget(
resolver: (ids: string[]) => Promise<{ id: string; authoritative: boolean | null }[]>,
startMs: number
): Promise<number> {
const livePtyIds = [PTY_ID]
let nowMs = startMs
// 8 attempts across the 1/2/4/8/16/30/30s ladder, plus slack iterations.
for (let attempt = 0; attempt < 12; attempt += 1) {
const retryDelayMs = await synchronizeTerminalProviderSnapshotCapabilities(
livePtyIds,
resolver,
nowMs
)
if (retryDelayMs === null) {
break
}
nowMs += retryDelayMs + 1
}
return nowMs
}
describe('terminal provider snapshot capability re-settlement', () => {
beforeEach(() => clearTerminalProviderSnapshotCapabilities())
it('keeps an unknown-capability pty exempt during the outage (safety)', async () => {
const failingResolver = vi.fn(async () => {
throw new Error('daemon unavailable')
})
await synchronizeTerminalProviderSnapshotCapabilities([PTY_ID], failingResolver, 1_000)
expect(failingResolver).toHaveBeenCalled()
expect(terminalProviderHasAuthoritativeSnapshot(PTY_ID)).toBe(false)
expect(isEvictionExemptTerminalPty(PTY_ID, WORKTREE_ID)).toBe(true)
})
it('re-consults a recovered resolver after the retry budget and clears the exemption', async () => {
const failingResolver = vi.fn(async () => {
throw new Error('daemon unavailable')
})
const settledAtMs = await exhaustRetryBudget(failingResolver, 1_000)
expect(isEvictionExemptTerminalPty(PTY_ID, WORKTREE_ID)).toBe(true)
const healthyResolver = vi.fn(async (ids: string[]) =>
ids.map((id) => ({ id, authoritative: true }))
)
// Allow slow re-ask after recovery; a fresh PTY set also models ordinary tab churn.
const recoveredAtMs = settledAtMs + 10 * 60_000
await synchronizeTerminalProviderSnapshotCapabilities([PTY_ID], healthyResolver, recoveredAtMs)
const secondPassMs = recoveredAtMs + 10 * 60_000
await synchronizeTerminalProviderSnapshotCapabilities([PTY_ID], healthyResolver, secondPassMs)
expect(healthyResolver).toHaveBeenCalled()
expect(terminalProviderHasAuthoritativeSnapshot(PTY_ID)).toBe(true)
expect(isEvictionExemptTerminalPty(PTY_ID, WORKTREE_ID)).toBe(false)
})
})
@@ -13,19 +13,6 @@ afterEach(() => {
})
describe('foreground terminal tabs', () => {
it('keeps duplicate visible terminal tab claims until every token unregisters', () => {
const unregisterFirst = registerVisibleTerminalTab('tab-visible')
const unregisterSecond = registerVisibleTerminalTab('tab-visible')
expect(getForegroundTerminalTabIds()).toEqual(['tab-visible'])
unregisterFirst()
expect(getForegroundTerminalTabIds()).toEqual(['tab-visible'])
unregisterSecond()
expect(getForegroundTerminalTabIds()).toEqual([])
})
it('refreshes last-seen when explicit foreground ids leave the combined foreground set', () => {
vi.useFakeTimers()
vi.setSystemTime(1_000)
@@ -1,63 +0,0 @@
import { describe, expect, it } from 'vitest'
import type { SleepingAgentSessionRecord } from '../../../shared/agent-session/lifecycle/agent-session-resume'
function note(overrides: Partial<SleepingAgentSessionRecord> = {}): SleepingAgentSessionRecord {
return {
paneKey: 'tab-1:leaf-1',
worktreeId: 'wt-1',
agent: 'codex',
providerSession: { key: 'session_id', id: 'conv-1' },
prompt: '',
state: 'done',
capturedAt: 1,
updatedAt: 1,
...overrides
}
}
describe('recordPaneIsOwnedByPreservedPane: a pane its host kept asleep', () => {
const layout = {
'tab-1': {
root: { type: 'leaf' as const, leafId: '11111111-1111-4111-8111-111111111111' },
activeLeafId: '11111111-1111-4111-8111-111111111111',
expandedLeafId: null
}
}
const paneKey = 'tab-1:11111111-1111-4111-8111-111111111111'
const state = {
activeWorktreeId: 'wt-other',
tabsByWorktree: { 'wt-1': [{ id: 'tab-1' }] },
ptyIdsByTabId: {},
terminalLayoutsByTabId: layout
}
it('owns its unfinished session while deferred, so a sweep does not launch it again', async () => {
const { setPaneSpawnDeferral, clearPaneSpawnDeferral } =
await import('./pane-spawn-deferral-registry')
const { recordPaneIsOwnedByPreservedPane } = await import('./sleeping-agent-pane-ownership')
const record = note({ paneKey, tabId: 'tab-1', origin: 'quit' })
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the predicate reads only these four store maps.
expect(recordPaneIsOwnedByPreservedPane(record, state as never)).toBe(false)
setPaneSpawnDeferral(paneKey, { reason: 'live_cap', resume: () => {} })
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the predicate reads only these four store maps.
expect(recordPaneIsOwnedByPreservedPane(record, state as never)).toBe(true)
clearPaneSpawnDeferral(paneKey)
})
it('owns a legacy-keyed session while its pane holds the resume until shown', async () => {
const { holdPaneResumeUntilShown, releasePaneResumeHold } =
await import('./pane-spawn-deferral-registry')
const { recordPaneIsOwnedByPreservedPane } = await import('./sleeping-agent-pane-ownership')
const record = note({ paneKey: 'tab-1:2', tabId: 'tab-1', origin: 'quit' })
const holding = (): boolean => true
const legacyState = { ...state, sleepingAgentSessionsByPaneKey: { 'tab-1:2': record } }
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the predicate reads only these five store maps.
expect(recordPaneIsOwnedByPreservedPane(record, legacyState as never)).toBe(false)
holdPaneResumeUntilShown('tab-1:2', holding)
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the predicate reads only these five store maps.
expect(recordPaneIsOwnedByPreservedPane(record, legacyState as never)).toBe(true)
releasePaneResumeHold('tab-1:2', holding)
})
})
@@ -1,21 +1,7 @@
import { describe, expect, it } from 'vitest'
import {
haveSameDisabledTuiAgents,
normalizeDisabledTuiAgents,
pickTuiAgent
} from './tui-agent-selection'
import { normalizeDisabledTuiAgents, pickTuiAgent } from './tui-agent-selection'
describe('pickTuiAgent', () => {
it('uses an installed preferred agent', () => {
expect(pickTuiAgent('codex', ['claude', 'codex'])).toBe('codex')
})
it('falls back in desktop catalog order when the preference is absent or stale', () => {
expect(pickTuiAgent(null, ['cursor', 'codex'])).toBe('codex')
expect(pickTuiAgent('gemini', ['cursor', 'codex'])).toBe('codex')
expect(pickTuiAgent(null, ['continue', 'command-code'])).toBe('command-code')
})
it('respects the explicit blank terminal preference', () => {
expect(pickTuiAgent('blank', ['cursor', 'claude'])).toBeNull()
})
@@ -34,11 +20,3 @@ describe('normalizeDisabledTuiAgents', () => {
])
})
})
describe('haveSameDisabledTuiAgents', () => {
it('compares the normalized disabled-agent sets', () => {
expect(haveSameDisabledTuiAgents(['codex', 'claude'], ['claude', 'codex'])).toBe(true)
expect(haveSameDisabledTuiAgents(['codex', 'unknown'], ['codex'])).toBe(true)
expect(haveSameDisabledTuiAgents(['codex'], ['claude'])).toBe(false)
})
})
@@ -1,14 +0,0 @@
import { describe, expect, it } from 'vitest'
import { buildDefaultAgentSettingsUpdate } from './default-agent-settings'
describe('default agent settings', () => {
it.each(['blank', 'claude', null] as const)(
'clears the retired setup-only flag for %s',
(agent) => {
expect(buildDefaultAgentSettingsUpdate(agent)).toEqual({
defaultTuiAgent: agent,
newWorkspaceSetupOnly: false
})
}
)
})
@@ -1,21 +0,0 @@
import { describe, expect, it } from 'vitest'
import { buildAgentStartupPlan } from './tui-agent-startup'
import { TUI_AGENT_CONFIG } from '../catalog/tui-agent-config'
describe('DSH first launch', () => {
it.each(['darwin', 'linux', 'win32'] as const)(
'plans the current workspace with task input deferred on %s',
(platform) => {
const plan = buildAgentStartupPlan({
agent: 'dsh',
prompt: 'Review this folder',
cmdOverrides: {},
platform
})
expect(plan?.launchCommand).toContain('dsh-tui .')
expect(plan?.launchCommand).not.toContain('Review this folder')
expect(TUI_AGENT_CONFIG.dsh.promptInjectionMode).toBe('stdin-after-start')
expect(TUI_AGENT_CONFIG.dsh.draftPasteReadySignal).toBe('dsh-composer-prompt')
}
)
})
@@ -1,61 +0,0 @@
import { describe, expect, it } from 'vitest'
import { buildAgentDraftLaunchPlan, buildAgentStartupPlan } from './tui-agent-startup'
import {
isExpectedAgentProcess,
recognizeAgentProcess
} from '../../agent-status/process/agent-process-recognition'
import { pickTuiAgent } from '../catalog/tui-agent-selection'
describe('Freebuff terminal launches', () => {
it.each(['darwin', 'linux', 'win32'] as const)(
'plans task text as a follow-up to the interactive launch on %s',
(platform) => {
const prompt = '--help\nFix "quoted" paths and $HOME handling'
const plan = buildAgentStartupPlan({
agent: 'freebuff',
prompt,
cmdOverrides: {},
platform
})
expect(plan).toMatchObject({
launchCommand: 'freebuff',
expectedProcess: 'freebuff',
followupPrompt: prompt
})
expect(
buildAgentDraftLaunchPlan({
agent: 'freebuff',
draft: prompt,
cmdOverrides: {},
platform
})
).toBeNull()
}
)
it('uses the same launch contract on SSH hosts', () => {
expect(
buildAgentStartupPlan({
agent: 'freebuff',
prompt: 'Inspect this folder',
cmdOverrides: {},
platform: 'linux',
isRemote: true
})
).toMatchObject({ launchCommand: 'freebuff', followupPrompt: 'Inspect this folder' })
})
it.each(['/usr/local/bin/freebuff', 'C:\\tools\\freebuff.exe'])(
'recognizes %s separately from Codebuff',
(processName) => {
expect(recognizeAgentProcess(processName)?.agent).toBe('freebuff')
expect(isExpectedAgentProcess(processName, 'codebuff')).toBe(false)
}
)
it('honors independent installation and disabled-agent preferences', () => {
expect(pickTuiAgent('freebuff', ['freebuff', 'codebuff'])).toBe('freebuff')
expect(pickTuiAgent(null, ['freebuff'])).toBe('freebuff')
expect(pickTuiAgent('freebuff', ['freebuff', 'codebuff'], ['freebuff'])).toBe('codebuff')
})
})
@@ -1,31 +0,0 @@
import { describe, expect, it } from 'vitest'
import { buildAgentStartupPlan } from './tui-agent-startup'
describe('Freebuff startup', () => {
it('keeps Freebuff command overrides separate from Codebuff', () => {
const cmdOverrides = { freebuff: 'freebuff --debug' }
const freebuff = buildAgentStartupPlan({
agent: 'freebuff',
prompt: '',
allowEmptyPromptLaunch: true,
cmdOverrides,
platform: 'linux',
isRemote: true
})
const codebuff = buildAgentStartupPlan({
agent: 'codebuff',
prompt: '',
allowEmptyPromptLaunch: true,
cmdOverrides,
platform: 'linux',
isRemote: true
})
expect(freebuff).toMatchObject({
launchCommand: 'freebuff --debug',
expectedProcess: 'freebuff',
followupPrompt: null
})
expect(codebuff).toMatchObject({ launchCommand: 'codebuff', expectedProcess: 'codebuff' })
})
})
@@ -3,14 +3,6 @@ import { withFreshOmpLaunch } from './omp-fresh-launch'
import { buildAgentStartupPlan } from './tui-agent-startup'
describe('OMP fresh launch intent', () => {
it.each(['omp', 'omp launch', 'omp --model provider/model', 'omp --config user.yml'])(
'%s adds the final overlay',
(command) => {
expect(withFreshOmpLaunch(command, 'posix')).toContain(
`${command} --config "$ORCA_OMP_FRESH_CONFIG"`
)
}
)
it.each([
'omp --resume id',
'omp -r id',
@@ -38,12 +30,6 @@ describe('OMP fresh launch intent', () => {
const command = 'omp --model foo&'
expect(withFreshOmpLaunch(command, shell)).toBe(command)
})
it('quotes the host config path for each Windows shell', () => {
expect(withFreshOmpLaunch('omp', 'powershell')).toContain(
'omp --config "$env:ORCA_OMP_FRESH_CONFIG"'
)
expect(withFreshOmpLaunch('omp', 'cmd')).toContain('omp --config "%~$ORCA_OMP_FRESH_CONFIG:!"')
})
it('keeps fresh intent out of saved resume command and environment', () => {
const plan = buildAgentStartupPlan({
agent: 'omp',
@@ -55,14 +41,4 @@ describe('OMP fresh launch intent', () => {
expect(JSON.stringify(plan?.launchConfig)).not.toContain('ORCA_OMP_FRESH_CONFIG')
expect(plan?.env).toBeUndefined()
})
it('requires host-owned configuration for fresh SSH launches', () => {
const plan = buildAgentStartupPlan({
agent: 'omp',
prompt: 'new task',
cmdOverrides: {},
platform: 'linux',
isRemote: true
})
expect(plan?.launchCommand).toContain('test -f "$ORCA_OMP_FRESH_CONFIG"')
})
})
@@ -1,50 +0,0 @@
import { describe, expect, it } from 'vitest'
import { buildAgentStartupPlan } from './tui-agent-startup'
import { buildAgentResumeStartupPlan } from './tui-agent-resume-startup'
describe('Qoder China launch recipe identity', () => {
it.each(['darwin', 'linux', 'win32'] as const)(
'preserves the official China executable on %s',
(platform) => {
const plan = buildAgentStartupPlan({
agent: 'qoder-cn',
prompt: 'fixture',
cmdOverrides: {},
platform
})
expect(plan?.agent).toBe('qoder-cn')
expect(plan?.launchCommand).toBe("qoderclicn --prompt-interactive 'fixture'")
expect(
buildAgentResumeStartupPlan({
agent: 'qoder-cn',
providerSession: { key: 'session_id', id: 'fixture-session' },
cmdOverrides: {},
platform
})?.launchCommand
).toBe("qoderclicn '--resume' 'fixture-session'")
}
)
it.each(['darwin', 'linux', 'win32'] as const)(
'preserves an explicitly configured shared-binary --cn recipe on %s',
(platform) => {
const cmdOverrides = { 'qoder-cn': 'qodercli --cn' }
const plan = buildAgentStartupPlan({
agent: 'qoder-cn',
prompt: 'fixture',
cmdOverrides,
platform
})
expect(plan?.agent).toBe('qoder-cn')
expect(plan?.launchCommand).toBe("qodercli --cn --prompt-interactive 'fixture'")
expect(
buildAgentResumeStartupPlan({
agent: 'qoder-cn',
providerSession: { key: 'session_id', id: 'fixture-session' },
cmdOverrides,
platform
})?.launchCommand
).toBe("qodercli --cn '--resume' 'fixture-session'")
}
)
})
@@ -1,41 +0,0 @@
/** Pin the pre-launch transport predicate to buildAgentStartupPlan’s followupPrompt verdict for every agent so table drift cannot lose prompts. */
import { describe, expect, it } from 'vitest'
import { TUI_AGENT_CONFIG } from '../catalog/tui-agent-config'
import { agentPromptRidesLaunchCommand, buildAgentStartupPlan } from './tui-agent-startup'
import type { TuiAgent } from '../catalog/tui-agent'
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the config is declared as a total record over TuiAgent, so its own keys are that union.
const ALL_AGENTS = Object.keys(TUI_AGENT_CONFIG) as TuiAgent[]
const PROMPT = 'summarize the diff'
function planFor(agent: TuiAgent) {
return buildAgentStartupPlan({
agent,
prompt: PROMPT,
cmdOverrides: {},
platform: 'darwin'
})
}
describe('the prompt-transport predicate against the plan it predicts', () => {
// An empty agent list would make the contract vacuously pass.
it('puts the prompt in the launch command exactly when it says it does', () => {
for (const agent of ALL_AGENTS) {
const plan = planFor(agent)
if (!agentPromptRidesLaunchCommand(agent)) {
// The command must not smuggle the text in some other way.
expect(plan!.launchCommand).not.toContain(PROMPT)
expect(plan!.followupPrompt).toBe(PROMPT)
continue
}
// Hermes hands long text through an env var, so the command names the variable, not the text.
const carried =
plan!.launchCommand.includes(PROMPT) ||
Object.values(plan!.env ?? {}).some((value) => value.includes(PROMPT))
expect(carried, `${agent} claims its launch command carries the prompt`).toBe(true)
}
})
})
@@ -1,43 +0,0 @@
import { describe, expect, it } from 'vitest'
import { buildAgentResumeStartupPlan } from './tui-agent-resume-startup'
const SESSION = { key: 'session_id' as const, id: '940237d9-c712-48e8-bca1-fd75fc4a8d4b' }
describe('Copilot resume startup plan', () => {
it('uses the documented joined --resume form', () => {
const plan = buildAgentResumeStartupPlan({
agent: 'copilot',
providerSession: SESSION,
cmdOverrides: {},
agentArgs: '--yolo',
platform: 'darwin'
})
expect(plan?.launchCommand).toBe(`copilot '--yolo' '--resume=${SESSION.id}'`)
})
it('quotes the resume argv for cmd.exe', () => {
const plan = buildAgentResumeStartupPlan({
agent: 'copilot',
providerSession: SESSION,
cmdOverrides: {},
agentArgs: '--yolo',
platform: 'win32',
shell: 'cmd'
})
// Why: cmd.exe treats single quotes as literal characters.
expect(plan?.launchCommand).toBe(`copilot "--yolo" "--resume=${SESSION.id}"`)
})
it('honors a command override', () => {
const plan = buildAgentResumeStartupPlan({
agent: 'copilot',
providerSession: SESSION,
cmdOverrides: { copilot: 'copilot --banner' },
platform: 'linux'
})
expect(plan?.launchCommand).toBe(`copilot --banner '--resume=${SESSION.id}'`)
})
})
@@ -2,23 +2,6 @@ import { describe, expect, it } from 'vitest'
import { buildAgentResumeStartupPlan } from './tui-agent-resume-startup'
describe('Kiro cold restore', () => {
it.each([
['darwin', 'posix', "kiro-cli chat --tui '--trust-all-tools' '--resume-id' 'session-1'"],
['linux', 'posix', "kiro-cli chat --tui '--trust-all-tools' '--resume-id' 'session-1'"],
['win32', 'powershell', "kiro-cli chat --tui '--trust-all-tools' '--resume-id' 'session-1'"],
['win32', 'cmd', 'kiro-cli chat --tui "--trust-all-tools" "--resume-id" "session-1"']
] as const)('appends only the resume selector on %s/%s', (platform, shell, expected) => {
const plan = buildAgentResumeStartupPlan({
agent: 'kiro',
providerSession: { key: 'session_id', id: 'session-1' },
cmdOverrides: {},
agentArgs: '--trust-all-tools',
platform,
shell
})
expect(plan?.launchCommand).toBe(expected)
})
it('preserves the captured engine and agent selection on a remote host', () => {
const plan = buildAgentResumeStartupPlan({
agent: 'kiro',
@@ -4,17 +4,11 @@ import './agent-resume-launch-command.spec'
import './agent-startup-plan-inputs.spec'
import './agent-startup-plan-inputs-extra-agent-args.spec'
import './automation-extra-agent-args.spec'
import './dsh-startup.spec'
import './freebuff-launch.spec'
import './freebuff-startup.spec'
import './omp-fresh-launch.spec'
import './opencode-startup-prompt.spec'
import './opencode2-resume-launch-mode.spec'
import './qoder-cn-launch-recipe.spec'
import './tui-agent-fork-startup.spec'
import '../choices/tui-agent-launch-defaults.spec'
import './tui-agent-prompt-transport.spec'
import './tui-agent-startup-copilot-resume.spec'
import './tui-agent-startup-hermes.spec'
import './tui-agent-startup-session-options.spec'
import './tui-agent-startup-shell.spec'
@@ -197,7 +197,7 @@ export function buildAgentStartupPlan(args: {
}
}
/** Predict the builder’s null-followupPrompt verdict before choosing a launch surface; derive from the same injection table and pin every agent in tui-agent-prompt-transport.spec.ts.
/** Predict the builder’s null-followupPrompt verdict before choosing a launch surface; derive from the same injection table.
* All modes except stdin-after-start carry the prompt through the launch command; Hermes may reference an env carrier instead of literal prompt argv. */
export function agentPromptRidesLaunchCommand(agent: TuiAgent): boolean {
return TUI_AGENT_CONFIG[agent].promptInjectionMode !== 'stdin-after-start'
-9
View File
@@ -30,15 +30,6 @@ describe('CodeBuddy harness', () => {
expect(rows[5]?.providerSession?.id).toBe('codebuddy-verification')
})
it.each([
'codebuddy',
'cbc',
'C:\\Tools\\codebuddy.cmd',
'node /usr/lib/node_modules/@tencent-ai/codebuddy-code/dist/codebuddy.js'
])('recognizes interactive %s', (command) => {
expect(recognizeAgentProcessFromCommandLine(command)?.agent).toBe('codebuddy')
})
it('excludes print runs and resumes the original provider session', () => {
for (const flag of ['--print', '--serve', '--acp', '--bg', '--background']) {
expect(recognizeAgentProcessFromCommandLine(`codebuddy ${flag}`)).toBeNull()
-5
View File
@@ -10,11 +10,6 @@ describe('Claude Agent Teams launch name on the launching host', () => {
expect(getTuiAgentLaunchCommand(agentTeams, 'linux')).toBe('orca claude-teams')
})
it('keeps the orca-ide rename on a Linux desktop', () => {
installFakeAppEnvironment({ getCliLauncherPath: undefined })
expect(getTuiAgentLaunchCommand(agentTeams, 'linux')).toBe('orca-ide claude-teams')
})
it('keeps the orca-ide rename for WSL under a Windows server', () => {
installFakeAppEnvironment({
getCliLauncherPath: () => 'C:\\Users\\u\\.orca\\cli\\bin\\orca.exe'
@@ -3,18 +3,6 @@ import type { TuiAgent } from './agent-launch/catalog/tui-agent'
import { requireTuiAgentConfig } from './require-tui-agent-config'
describe('requireTuiAgentConfig', () => {
it('returns the config for a known agent', () => {
expect(requireTuiAgentConfig('codex').preflightTrust).toBe('codex')
})
it('names the unknown id instead of throwing a property-of-undefined error', () => {
// A custom-agent id persisted by a branch build, read back by one without the feature.
const stale = 'custom-agent:codex:b2e1ff6f-8932-413a-9133-edffa44e0ee9' as TuiAgent
expect(() => requireTuiAgentConfig(stale)).toThrow(
`Unknown agent "${stale}". This version of Orca has no such agent — pick a different agent and try again.`
)
})
it('rejects a prototype key that Object.hasOwn keeps off the config', () => {
expect(() => requireTuiAgentConfig('toString' as TuiAgent)).toThrow(/Unknown agent "toString"/)
})
@@ -16,11 +16,6 @@ describe('agent.launch accountEnv wire compatibility', () => {
expect(parsed.accountEnv).toEqual(ACCOUNT_ENV)
})
it('leaves an older client launch unchanged on a new host', () => {
const parsed = AgentLaunch.parse(BASE)
expect(parsed).not.toHaveProperty('accountEnv')
})
it('stays outside the replay fingerprint', () => {
const withEnv = AgentLaunch.parse({ ...BASE, accountEnv: ACCOUNT_ENV })
expect(computeAgentLaunchFingerprint(withEnv)).toBe(
@@ -1,19 +1,10 @@
import { describe, expect, it } from 'vitest'
import { AgentLaunch, AgentLaunchReplay } from './agent-launch-params'
import { AgentLaunch } from './agent-launch-params'
import { computeAgentLaunchFingerprint } from '../agent-launch/contracts/agent-launch-operation'
const BASE = { agent: 'claude', target: { kind: 'existing', worktree: 'id:wt-1' } }
const OPERATION_ID = '1760000000000-0123456789abcdef0123456789abcdef'
describe('agent.launch nativeChatDefault wire compatibility', () => {
it('carries the caller default on a new host, for both launch methods', () => {
expect(AgentLaunch.parse({ ...BASE, nativeChatDefault: true }).nativeChatDefault).toBe(true)
expect(
AgentLaunchReplay.parse({ ...BASE, operationId: OPERATION_ID, nativeChatDefault: false })
.nativeChatDefault
).toBe(false)
})
it('stays outside the replay fingerprint', () => {
expect(
computeAgentLaunchFingerprint(AgentLaunch.parse({ ...BASE, nativeChatDefault: true }))
@@ -1,28 +0,0 @@
import { describe, expect, it } from 'vitest'
import { buildAgentStartupPlan } from './agent-launch/startup/tui-agent-startup'
describe('ZCode orchestration and send-to-agent contract', () => {
it('keeps the prompt out of the launch command and hands it back as a follow-up', () => {
const plan = buildAgentStartupPlan({
agent: 'zcode',
prompt: 'refactor the parser',
cmdOverrides: {},
platform: 'darwin'
})
expect(plan?.launchCommand).toBe('zcode')
expect(plan?.launchCommand).not.toContain('refactor the parser')
expect(plan?.followupPrompt).toBe('refactor the parser')
})
it('carries a mode chosen through agent args onto the launch command', () => {
const plan = buildAgentStartupPlan({
agent: 'zcode',
prompt: '',
cmdOverrides: {},
platform: 'darwin',
allowEmptyPromptLaunch: true,
agentArgs: '--mode plan'
})
expect(plan?.launchCommand).toBe("zcode '--mode' 'plan'")
})
})