minor change

This commit is contained in:
Jinjing
2026-09-01 03:53:17 -07:00
parent cebafbe042
commit 47bb90839f
9 changed files with 249 additions and 692 deletions
+1 -1
View File
@@ -45,7 +45,7 @@ export async function persistPtyIpcSpawnCommit(ctx: PtyIpcSpawnState): Promise<{
ptyId: ctx.result.id,
isDaemonHostSpawn: ctx.isDaemonHostSpawn,
isReattach: ctx.result.isReattach === true,
pinnedByResume: ctx.codexResumeHomeSelected,
pinnedByResume: Boolean(ctx.codexResumeLaunch.codexResumeHome),
launchCodexHomePath: ctx.selectedCodexHomePath,
launchEnv: ctx.baseEnv,
target: ctx.codexSelectionTarget,
-1
View File
@@ -454,7 +454,6 @@ import {
import { isMainTerminalSideEffectAuthorityForPty } from './terminal-pane/terminal-side-effect-facts-handler'
import { appendUniqueOpenFileIds } from './terminal/unsaved-close-queue'
import { setWindowCloseRequestHandler } from './window-close-request-coordinator'
import CodexRestartChip from './CodexRestartChip'
import { AgentLaunchNotices } from './terminal-pane/AgentLaunchNotices'
import { AgentLaunchRecoveryCardContainer } from './terminal-pane/AgentLaunchRecoveryCardContainer'
import {
@@ -119,7 +119,7 @@ export function buildDashboardWorktreeLaunchOptions(
)
const preferred = state.settings?.defaultTuiAgent
result[worktreeId] =
preferred && preferred !== 'blank' && isBuiltInTuiAgent(preferred) && enabled.includes(preferred)
isTuiAgent(preferred) && enabled.some((agent) => agent === preferred)
? [preferred, ...enabled.filter((agent) => agent !== preferred)]
: enabled
}
@@ -1,38 +1,21 @@
// @vitest-environment happy-dom
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { FolderWorkspace } from '../../../../shared/folder-workspace-types'
import type { ProjectGroup } from '../../../../shared/project-group-types'
import { folderWorkspaceKey } from '../../../../shared/workspace-scope'
import type * as NewWorkspaceModule from '@/lib/new-workspace'
import type { FolderWorkspace, ProjectGroup } from '../../../../shared/types'
const mocks = vi.hoisted(() => ({
activateAndRevealFolderWorkspace: vi.fn(),
ensureAgentStartupInTerminal: vi.fn()
activateAndRevealFolderWorkspace: vi.fn()
}))
// Why: importOriginal keeps the real resolveStartupLaunchDraftText, so the
// invariant test below exercises the shipped gate instead of a copy of it.
vi.mock('@/lib/worktree-activation', async (importOriginal) => {
const actual = await importOriginal<Record<string, unknown>>()
return { ...actual, activateAndRevealFolderWorkspace: mocks.activateAndRevealFolderWorkspace }
})
vi.mock('@/lib/new-workspace', async (importOriginal) => {
const actual = await importOriginal<typeof NewWorkspaceModule>()
return {
...actual,
ensureAgentStartupInTerminal: mocks.ensureAgentStartupInTerminal
}
})
import { useAppStore } from '@/store'
import { decideInitialAgentTabViewMode } from '@/lib/native-chat-initial-view-mode'
import { resolveStartupLaunchDraftText } from '@/lib/worktree-startup-payload'
import {
getFolderWorkspaceAgentLaunchPlatform,
submitFolderWorkspaceCreate
} from './folder-workspace-composer-submit'
import { useAppStore } from '@/store'
import { submitFolderWorkspaceCreate } from './folder-workspace-composer-submit'
function makeProjectGroup(): ProjectGroup {
return {
@@ -70,7 +53,9 @@ function makeFolderWorkspace(overrides: Partial<FolderWorkspace> = {}): FolderWo
describe('submitFolderWorkspaceCreate', () => {
beforeEach(() => {
vi.clearAllMocks()
mocks.activateAndRevealFolderWorkspace.mockReturnValue({ primaryTabId: 'tab-1' })
useAppStore.setState({ nativeChatLaunchDraftByTabId: {} })
Object.assign(window, {
api: {
agentTrust: {
@@ -81,8 +66,7 @@ describe('submitFolderWorkspaceCreate', () => {
})
afterEach(() => {
mocks.activateAndRevealFolderWorkspace.mockReset()
mocks.ensureAgentStartupInTerminal.mockReset()
useAppStore.setState({ nativeChatLaunchDraftByTabId: {} })
Reflect.deleteProperty(window, 'api')
vi.restoreAllMocks()
})
@@ -103,7 +87,6 @@ describe('submitFolderWorkspaceCreate', () => {
note: '',
quickAgent: null,
autoRenameBranchFromWork: false,
agentCmdOverrides: {},
createFolderWorkspace,
onOpenChange
})
@@ -115,18 +98,14 @@ describe('submitFolderWorkspaceCreate', () => {
linkedTask: null
})
expect(onOpenChange).toHaveBeenCalledWith(false)
expect(mocks.activateAndRevealFolderWorkspace).toHaveBeenCalledWith('folder-workspace-1', {
runtimeEnvironmentId: null
})
expect(consoleError).toHaveBeenCalledWith(
'Failed to activate folder workspace after create:',
expect.any(Error)
)
})
it('marks a blank folder workspace for first-input rename when launching an agent with a note', async () => {
it('uses an identity-only host launch and marks a submitted first prompt for rename', async () => {
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace())
const onOpenChange = vi.fn()
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
@@ -136,13 +115,10 @@ describe('submitFolderWorkspaceCreate', () => {
note: 'Fix the flaky checkout flow',
quickAgent: 'codex',
autoRenameBranchFromWork: true,
agentCmdOverrides: {},
agentArgs: '--model gpt-5.4',
agentEnv: { ORCA_AGENT_PROFILE: 'review' },
launchSource: 'new_workspace_composer',
runtimeEnvironmentId: 'env-1',
createFolderWorkspace,
onOpenChange
onOpenChange: vi.fn()
})
expect(createFolderWorkspace).toHaveBeenCalledWith({
@@ -153,81 +129,74 @@ describe('submitFolderWorkspaceCreate', () => {
createdWithAgent: 'codex',
pendingFirstAgentMessageRename: true
})
expect(mocks.activateAndRevealFolderWorkspace).toHaveBeenCalledWith(
'folder-workspace-1',
expect.objectContaining({
runtimeEnvironmentId: 'env-1',
startup: expect.objectContaining({
command: expect.stringContaining('codex'),
env: { ORCA_AGENT_PROFILE: 'review' },
telemetry: expect.objectContaining({
launch_source: 'new_workspace_composer'
})
})
})
)
const startup = mocks.activateAndRevealFolderWorkspace.mock.calls[0]?.[1]?.startup
expect(startup?.command).toContain('--model')
expect(startup?.command).toContain('gpt-5.4')
expect(mocks.ensureAgentStartupInTerminal).not.toHaveBeenCalled()
expect(mocks.activateAndRevealFolderWorkspace).toHaveBeenCalledWith('folder-workspace-1', {
runtimeEnvironmentId: 'env-1',
startup: {
command: '',
launchAgent: 'codex',
agentLaunch: {
selection: { kind: 'agent', agent: 'codex' },
prompt: 'Fix the flaky checkout flow',
allowEmptyPromptLaunch: true
},
telemetry: {
launch_source: 'new_workspace_composer',
request_kind: 'new'
}
}
})
})
it('does not mark first-input rename when the folder workspace has an explicit name', async () => {
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace())
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
it.each([
{
label: 'an explicit workspace name',
name: 'Checkout polish',
lastAutoName: '',
linkedWorkItem: null,
note: 'Fix the flaky checkout flow',
quickAgent: 'codex',
autoRenameBranchFromWork: true,
agentCmdOverrides: {},
createFolderWorkspace,
onOpenChange: vi.fn()
})
expect(createFolderWorkspace).toHaveBeenCalledWith({
projectGroupId: 'group-1',
name: 'Checkout polish',
connectionId: null,
linkedTask: null,
createdWithAgent: 'codex'
})
})
it('does not mark first-input rename when a linked work item owns the folder workspace name', async () => {
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace())
const linkedWorkItem = {
provider: 'github' as const,
type: 'issue' as const,
number: 42,
title: 'Restore checkout polish',
url: 'https://github.com/stablyai/orca/issues/42',
repoId: 'repo-1'
expectedName: 'Checkout polish'
},
{
label: 'linked work-item naming',
name: '',
linkedWorkItem: {
provider: 'github' as const,
type: 'issue' as const,
number: 42,
title: 'Restore checkout polish',
url: 'https://github.com/stablyai/orca/issues/42',
repoId: 'repo-1'
},
note: 'Use the issue context',
expectedName: 'Restore checkout polish'
},
{
label: 'an empty submitted prompt',
name: '',
linkedWorkItem: null,
note: ' ',
expectedName: 'Platform workspace'
}
])('does not mark first-input rename for $label', async (input) => {
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace())
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
name: '',
name: input.name,
lastAutoName: '',
linkedWorkItem,
note: 'Use the issue context',
linkedWorkItem: input.linkedWorkItem,
note: input.note,
quickAgent: 'codex',
autoRenameBranchFromWork: true,
agentCmdOverrides: {},
createFolderWorkspace,
onOpenChange: vi.fn()
})
expect(createFolderWorkspace).toHaveBeenCalledWith({
projectGroupId: 'group-1',
name: 'Restore checkout polish',
connectionId: null,
linkedTask: linkedWorkItem,
createdWithAgent: 'codex'
})
expect(createFolderWorkspace).toHaveBeenCalledWith(
expect.not.objectContaining({ pendingFirstAgentMessageRename: true })
)
expect(createFolderWorkspace).toHaveBeenCalledWith(
expect.objectContaining({ name: input.expectedName, createdWithAgent: 'codex' })
)
})
it('creates a Jira folder workspace with its bound source context', async () => {
@@ -262,7 +231,6 @@ describe('submitFolderWorkspaceCreate', () => {
note: '',
quickAgent: null,
autoRenameBranchFromWork: true,
agentCmdOverrides: {},
createFolderWorkspace,
onOpenChange: vi.fn()
})
@@ -276,8 +244,7 @@ describe('submitFolderWorkspaceCreate', () => {
})
})
it('keeps linked Codex context out of submitted startup and pastes it as a draft', async () => {
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace())
it('launches linked context as a host-owned draft and mirrors it into native chat', async () => {
const linkedWorkItem = {
provider: 'github' as const,
type: 'pr' as const,
@@ -286,6 +253,7 @@ describe('submitFolderWorkspaceCreate', () => {
url: 'https://github.com/stablyai/orca/pull/91',
repoId: 'repo-1'
}
const draft = `Review this before starting\n\n${linkedWorkItem.url}`
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
@@ -295,54 +263,30 @@ describe('submitFolderWorkspaceCreate', () => {
note: 'Review this before starting',
quickAgent: 'codex',
autoRenameBranchFromWork: true,
agentCmdOverrides: {},
launchSource: 'new_workspace_composer',
createFolderWorkspace,
createFolderWorkspace: vi.fn(async () => makeFolderWorkspace()),
onOpenChange: vi.fn()
})
expect(createFolderWorkspace).toHaveBeenCalledWith({
projectGroupId: 'group-1',
name: 'Restore linked quick-create',
connectionId: null,
linkedTask: linkedWorkItem,
createdWithAgent: 'codex'
})
const startup = mocks.activateAndRevealFolderWorkspace.mock.calls[0]?.[1]?.startup
expect(startup?.command).toBe('codex')
expect(startup?.command).not.toContain(linkedWorkItem.url)
expect(startup?.command).not.toContain('Review this before starting')
expect(startup).toMatchObject({
command: '',
launchAgent: 'codex',
launchDraftText: draft,
agentLaunch: {
selection: { kind: 'agent', agent: 'codex' },
prompt: draft,
promptDelivery: 'draft'
}
})
expect(startup).not.toHaveProperty('draftPrompt')
expect(window.api.agentTrust?.markTrusted).toHaveBeenCalledWith({
preset: 'codex',
workspacePath: '/repo/platform/hi'
})
expect(mocks.ensureAgentStartupInTerminal).toHaveBeenCalledWith({
worktreeId: folderWorkspaceKey('folder-workspace-1'),
primaryTabId: 'tab-1',
startup: expect.objectContaining({
agent: 'codex',
launchCommand: 'codex',
followupPrompt: null,
draftPrompt: `Review this before starting\n\n${linkedWorkItem.url}`
})
})
expect(useAppStore.getState().nativeChatLaunchDraftByTabId['tab-1']?.text).toBe(draft)
})
it('pre-marks remote linked Codex folder workspaces trusted before draft paste', async () => {
const createFolderWorkspace = vi.fn(async () =>
makeFolderWorkspace({
connectionId: 'ssh-1',
folderPath: '/home/alice/platform/Trust remote folder draft'
})
)
const linkedWorkItem = {
provider: 'github' as const,
type: 'pr' as const,
number: 92,
title: 'Trust remote folder draft',
url: 'https://github.com/stablyai/orca/pull/92',
repoId: 'repo-1'
}
it('pre-marks remote folder agents trusted on the owning SSH host', async () => {
const projectGroup = {
...makeProjectGroup(),
connectionId: 'ssh-1',
@@ -351,158 +295,57 @@ describe('submitFolderWorkspaceCreate', () => {
await submitFolderWorkspaceCreate({
projectGroup,
name: '',
name: 'Remote folder',
lastAutoName: '',
linkedWorkItem,
linkedWorkItem: null,
note: '',
quickAgent: 'codex',
autoRenameBranchFromWork: false,
agentCmdOverrides: {},
isRemote: true,
createFolderWorkspace,
createFolderWorkspace: vi.fn(async () =>
makeFolderWorkspace({
connectionId: 'ssh-1',
folderPath: '/home/alice/platform/Remote folder'
})
),
onOpenChange: vi.fn()
})
expect(window.api.agentTrust?.markTrusted).toHaveBeenCalledWith({
preset: 'codex',
workspacePath: '/home/alice/platform/Trust remote folder draft',
workspacePath: '/home/alice/platform/Remote folder',
connectionId: 'ssh-1'
})
expect(mocks.ensureAgentStartupInTerminal).toHaveBeenCalledWith(
expect.objectContaining({
worktreeId: folderWorkspaceKey('folder-workspace-1'),
startup: expect.objectContaining({
agent: 'codex',
draftPrompt: linkedWorkItem.url
})
})
)
})
it('delivers non-linked follow-up prompts for agents that need stdin after launch', async () => {
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace())
it.each([
['a local WSL path', { parentPath: '\\\\wsl.localhost\\Ubuntu\\home\\alice\\platform' }],
[
'a remote Windows path',
{ connectionId: 'ssh-windows', parentPath: 'C:\\Users\\alice\\platform' }
]
])('leaves command and platform resolution to the host for %s', async (_label, overrides) => {
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
name: 'Aider followup',
projectGroup: { ...makeProjectGroup(), ...overrides },
name: 'Host-owned launch',
lastAutoName: '',
linkedWorkItem: null,
note: 'Fix the failing folder prompt flow',
quickAgent: 'aider',
note: "Use Bob's startup",
quickAgent: 'claude',
autoRenameBranchFromWork: false,
agentCmdOverrides: {},
createFolderWorkspace,
createFolderWorkspace: vi.fn(async () => makeFolderWorkspace()),
onOpenChange: vi.fn()
})
const startup = mocks.activateAndRevealFolderWorkspace.mock.calls[0]?.[1]?.startup
expect(startup?.command).toBe('aider')
expect(mocks.ensureAgentStartupInTerminal).toHaveBeenCalledWith({
worktreeId: folderWorkspaceKey('folder-workspace-1'),
primaryTabId: 'tab-1',
startup: expect.objectContaining({
agent: 'aider',
launchCommand: 'aider',
followupPrompt: 'Fix the failing folder prompt flow'
})
})
})
it('uses native draft launch for linked agents with prefill support', async () => {
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace())
const linkedWorkItem = {
provider: 'gitlab' as const,
type: 'mr' as const,
number: 17,
title: 'Review folder workspace draft',
url: 'https://gitlab.example.com/group/project/-/merge_requests/17',
repoId: 'repo-1'
}
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
name: '',
lastAutoName: '',
linkedWorkItem,
note: 'Check the migration path',
quickAgent: 'claude',
autoRenameBranchFromWork: true,
agentCmdOverrides: {},
createFolderWorkspace,
onOpenChange: vi.fn()
})
const startup = mocks.activateAndRevealFolderWorkspace.mock.calls[0]?.[1]?.startup
expect(startup?.command).toContain('claude --prefill')
expect(startup?.command).toContain('Check the migration path')
expect(startup?.command).toContain(linkedWorkItem.url)
expect(mocks.ensureAgentStartupInTerminal).not.toHaveBeenCalled()
})
it('uses native prefill for link-only Linear folder workspace drafts', async () => {
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace())
const linkedWorkItem = {
provider: 'linear' as const,
type: 'issue' as const,
number: 0,
title: 'Ship Linear source drafts',
url: 'https://linear.app/acme/issue/ENG-77/ship-linear-source-drafts',
linearIdentifier: 'ENG-77',
linkedContext: {
provider: 'linear' as const,
version: 1 as const,
renderedText: [
'Linear issue context snapshot',
'Identifier: ENG-77',
'Title: Ship Linear source drafts',
'Description:',
'Distinctive folder Linear body.'
].join('\n')
expect(mocks.activateAndRevealFolderWorkspace.mock.calls[0]?.[1]?.startup).toMatchObject({
command: '',
agentLaunch: {
selection: { kind: 'agent', agent: 'claude' },
prompt: "Use Bob's startup"
}
}
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
name: '',
lastAutoName: '',
linkedWorkItem,
note: 'User note stays above source',
quickAgent: 'claude',
autoRenameBranchFromWork: true,
agentCmdOverrides: {},
createFolderWorkspace,
onOpenChange: vi.fn()
})
expect(createFolderWorkspace).toHaveBeenCalledWith({
projectGroupId: 'group-1',
name: 'ENG-77 Ship Linear source drafts',
connectionId: null,
linkedTask: {
provider: 'linear',
type: 'issue',
number: 0,
title: 'Ship Linear source drafts',
url: 'https://linear.app/acme/issue/ENG-77/ship-linear-source-drafts',
linearIdentifier: 'ENG-77'
},
createdWithAgent: 'claude'
})
const startup = mocks.activateAndRevealFolderWorkspace.mock.calls[0]?.[1]?.startup
expect(startup?.command).toContain('claude --prefill')
expect(startup?.command).toContain('User note stays above source')
expect(startup?.command).toContain('Linked Linear issue: ENG-77')
expect(startup?.command).toContain(
'https://linear.app/acme/issue/ENG-77/ship-linear-source-drafts'
)
expect(startup?.command).not.toContain('Distinctive folder Linear body.')
expect(startup?.command).not.toContain('--- BEGIN LINKED WORK ITEM CONTEXT ---')
expect(startup?.command).not.toContain('orca linear')
expect(mocks.ensureAgentStartupInTerminal).not.toHaveBeenCalled()
})
it('keeps explicit blank linked folder creates free of agent startup and draft paste', async () => {
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace())
it('keeps explicit blank linked creates free of agent startup', async () => {
const linkedWorkItem = {
provider: 'github' as const,
type: 'issue' as const,
@@ -520,111 +363,13 @@ describe('submitFolderWorkspaceCreate', () => {
note: 'Keep this as metadata only',
quickAgent: null,
autoRenameBranchFromWork: true,
agentCmdOverrides: {},
createFolderWorkspace,
createFolderWorkspace: vi.fn(async () => makeFolderWorkspace()),
onOpenChange: vi.fn()
})
expect(createFolderWorkspace).toHaveBeenCalledWith({
projectGroupId: 'group-1',
name: 'Restore checkout polish',
connectionId: null,
linkedTask: linkedWorkItem
})
expect(mocks.activateAndRevealFolderWorkspace).toHaveBeenCalledWith('folder-workspace-1', {
runtimeEnvironmentId: null
})
expect(mocks.ensureAgentStartupInTerminal).not.toHaveBeenCalled()
})
it('does not mark first-input rename without submitted first input', async () => {
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace())
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
name: '',
lastAutoName: '',
linkedWorkItem: null,
note: ' ',
quickAgent: 'codex',
autoRenameBranchFromWork: true,
agentCmdOverrides: {},
createFolderWorkspace,
onOpenChange: vi.fn()
})
expect(createFolderWorkspace).toHaveBeenCalledWith({
projectGroupId: 'group-1',
name: 'Platform workspace',
connectionId: null,
linkedTask: null,
createdWithAgent: 'codex'
})
})
it('quotes quick-agent startup for POSIX when the folder group is a local WSL UNC path', async () => {
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace())
const projectGroup = {
...makeProjectGroup(),
parentPath: '\\\\wsl.localhost\\Ubuntu\\home\\alice\\platform'
}
expect(getFolderWorkspaceAgentLaunchPlatform(projectGroup)).toBe('linux')
await submitFolderWorkspaceCreate({
projectGroup,
name: 'WSL folder',
lastAutoName: '',
linkedWorkItem: null,
note: "Use Bob's POSIX startup",
quickAgent: 'claude',
autoRenameBranchFromWork: false,
agentCmdOverrides: {},
createFolderWorkspace,
onOpenChange: vi.fn()
})
expect(mocks.activateAndRevealFolderWorkspace).toHaveBeenCalledWith(
'folder-workspace-1',
expect.objectContaining({
startup: expect.objectContaining({
command: `claude 'Use Bob'"'"'s POSIX startup'`
})
})
)
})
it('quotes quick-agent startup for Windows when the remote folder group uses a Windows path', async () => {
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace())
const projectGroup = {
...makeProjectGroup(),
connectionId: 'ssh-windows',
parentPath: 'C:\\Users\\alice\\platform'
}
expect(getFolderWorkspaceAgentLaunchPlatform(projectGroup)).toBe('win32')
await submitFolderWorkspaceCreate({
projectGroup,
name: 'Remote Windows folder',
lastAutoName: '',
linkedWorkItem: null,
note: "Use Bob's Windows startup",
quickAgent: 'claude',
autoRenameBranchFromWork: false,
agentCmdOverrides: {},
createFolderWorkspace,
onOpenChange: vi.fn()
})
expect(mocks.activateAndRevealFolderWorkspace).toHaveBeenCalledWith(
'folder-workspace-1',
expect.objectContaining({
startup: expect.objectContaining({
command: "claude 'Use Bob''s Windows startup'"
})
})
)
})
it('preserves SSH group ownership when creating and activating a folder workspace', async () => {
@@ -634,7 +379,6 @@ describe('submitFolderWorkspaceCreate', () => {
executionHostId: 'ssh:ssh-1'
}
const createFolderWorkspace = vi.fn(async () => makeFolderWorkspace({ connectionId: 'ssh-1' }))
const onOpenChange = vi.fn()
await submitFolderWorkspaceCreate({
projectGroup,
@@ -644,11 +388,9 @@ describe('submitFolderWorkspaceCreate', () => {
note: '',
quickAgent: null,
autoRenameBranchFromWork: false,
agentCmdOverrides: {},
isRemote: true,
runtimeEnvironmentId: null,
createFolderWorkspace,
onOpenChange
onOpenChange: vi.fn()
})
expect(createFolderWorkspace).toHaveBeenCalledWith({
@@ -657,14 +399,12 @@ describe('submitFolderWorkspaceCreate', () => {
connectionId: 'ssh-1',
linkedTask: null
})
expect(onOpenChange).toHaveBeenCalledWith(false)
expect(mocks.activateAndRevealFolderWorkspace).toHaveBeenCalledWith('folder-workspace-1', {
runtimeEnvironmentId: null
})
})
it('returns false when folder workspace creation fails without returning a workspace', async () => {
const createFolderWorkspace = vi.fn(async () => null)
it('returns false when folder workspace creation fails', async () => {
const onOpenChange = vi.fn()
await expect(
@@ -676,8 +416,7 @@ describe('submitFolderWorkspaceCreate', () => {
note: '',
quickAgent: null,
autoRenameBranchFromWork: false,
agentCmdOverrides: {},
createFolderWorkspace,
createFolderWorkspace: vi.fn(async () => null),
onOpenChange
})
).resolves.toBe(false)
@@ -685,185 +424,49 @@ describe('submitFolderWorkspaceCreate', () => {
expect(onOpenChange).not.toHaveBeenCalled()
expect(mocks.activateAndRevealFolderWorkspace).not.toHaveBeenCalled()
})
})
describe('submitFolderWorkspaceCreate native-chat launch draft', () => {
const ISSUE_URL = 'https://github.com/stablyai/orca/issues/42'
const linkedIssue = {
provider: 'github' as const,
type: 'issue' as const,
number: 42,
title: 'Restore linked quick-create',
url: ISSUE_URL,
repoId: 'repo-1'
}
function seededDraftFor(tabId: string): { text: string } | undefined {
return useAppStore.getState().nativeChatLaunchDraftByTabId[tabId]
}
beforeEach(() => {
mocks.activateAndRevealFolderWorkspace.mockReturnValue({ primaryTabId: 'tab-1' })
useAppStore.setState({ nativeChatLaunchDraftByTabId: {} })
Object.assign(window, {
api: { agentTrust: { markTrusted: vi.fn().mockResolvedValue(undefined) } }
})
})
afterEach(() => {
mocks.activateAndRevealFolderWorkspace.mockReset()
mocks.ensureAgentStartupInTerminal.mockReset()
useAppStore.setState({ nativeChatLaunchDraftByTabId: {} })
Reflect.deleteProperty(window, 'api')
vi.restoreAllMocks()
})
it('mirrors a startup-paste draft into the chat composer', async () => {
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
name: '',
lastAutoName: '',
linkedWorkItem: linkedIssue,
note: '',
quickAgent: 'codex',
autoRenameBranchFromWork: false,
agentCmdOverrides: {},
createFolderWorkspace: vi.fn(async () => makeFolderWorkspace()),
onOpenChange: vi.fn()
})
expect(seededDraftFor('tab-1')?.text).toBe(ISSUE_URL)
})
it('mirrors an argv-prefill draft, which never lands in startupPlan.draftPrompt', async () => {
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
name: '',
lastAutoName: '',
linkedWorkItem: linkedIssue,
note: '',
quickAgent: 'claude',
autoRenameBranchFromWork: false,
agentCmdOverrides: {},
createFolderWorkspace: vi.fn(async () => makeFolderWorkspace()),
onOpenChange: vi.fn()
})
// The draft rides in on `--prefill`, so the plan carries no draftPrompt at
// all — keying the mirror off it would silently drop this whole branch.
const startup = mocks.activateAndRevealFolderWorkspace.mock.calls[0]?.[1]?.startup
expect(startup?.draftPrompt).toBeUndefined()
expect(startup?.command).toContain(ISSUE_URL)
expect(seededDraftFor('tab-1')?.text).toBe(ISSUE_URL)
})
it('mirrors a multi-line draft into chat', async () => {
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
name: '',
lastAutoName: '',
linkedWorkItem: linkedIssue,
note: 'Reproduce on Windows first',
quickAgent: 'codex',
autoRenameBranchFromWork: false,
agentCmdOverrides: {},
createFolderWorkspace: vi.fn(async () => makeFolderWorkspace()),
onOpenChange: vi.fn()
})
expect(mocks.ensureAgentStartupInTerminal).toHaveBeenCalledWith(
expect.objectContaining({
startup: expect.objectContaining({
draftPrompt: `Reproduce on Windows first\n\n${ISSUE_URL}`
})
})
)
expect(seededDraftFor('tab-1')?.text).toBe(`Reproduce on Windows first\n\n${ISSUE_URL}`)
})
it('does not mirror an unlinked note, which is submitted rather than drafted', async () => {
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
name: '',
lastAutoName: '',
linkedWorkItem: null,
note: 'Fix the flaky checkout flow',
quickAgent: 'codex',
autoRenameBranchFromWork: false,
agentCmdOverrides: {},
createFolderWorkspace: vi.fn(async () => makeFolderWorkspace()),
onOpenChange: vi.fn()
})
expect(seededDraftFor('tab-1')).toBeUndefined()
})
})
describe('folder-workspace draft: seeded set == chat-opening set', () => {
const ISSUE_URL = 'https://github.com/stablyai/orca/issues/42'
const linkedIssue = {
provider: 'github' as const,
type: 'issue' as const,
number: 42,
title: 'Restore linked quick-create',
url: ISSUE_URL,
repoId: 'repo-1'
}
beforeEach(() => {
mocks.activateAndRevealFolderWorkspace.mockReturnValue({ primaryTabId: 'tab-1' })
useAppStore.setState({ nativeChatLaunchDraftByTabId: {} })
Object.assign(window, {
api: { agentTrust: { markTrusted: vi.fn().mockResolvedValue(undefined) } }
})
})
afterEach(() => {
mocks.activateAndRevealFolderWorkspace.mockReset()
mocks.ensureAgentStartupInTerminal.mockReset()
useAppStore.setState({ nativeChatLaunchDraftByTabId: {} })
Reflect.deleteProperty(window, 'api')
vi.restoreAllMocks()
})
// Why: `claude` takes its draft on argv, so `startupPlan.draftPrompt` stays
// undefined; `codex` gets a startup paste and sets it. Both must reach the
// view-mode gate, and both must agree with what the composer actually holds.
it.each([
['argv-prefill', 'claude' as const, '', true],
['argv-prefill multi-line', 'claude' as const, 'Reproduce on Windows first', true],
['startup-paste', 'codex' as const, '', true],
['startup-paste multi-line', 'codex' as const, 'Reproduce on Windows first', true]
])('%s', async (_label, quickAgent, note, expectMirrored) => {
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
name: '',
lastAutoName: '',
linkedWorkItem: linkedIssue,
note,
quickAgent,
autoRenameBranchFromWork: false,
agentCmdOverrides: {},
createFolderWorkspace: vi.fn(async () => makeFolderWorkspace()),
onOpenChange: vi.fn()
})
['claude', ''],
['claude', 'Reproduce on Windows first'],
['codex', ''],
['codex', 'Reproduce on Windows first']
] as const)(
'keeps the %s linked draft mirror and initial view decision aligned',
async (agent, note) => {
const linkedWorkItem = {
provider: 'github' as const,
type: 'issue' as const,
number: 42,
title: 'Restore linked quick-create',
url: 'https://github.com/stablyai/orca/issues/42',
repoId: 'repo-1'
}
const startup = mocks.activateAndRevealFolderWorkspace.mock.calls[0]?.[1]?.startup
const seeded = useAppStore.getState().nativeChatLaunchDraftByTabId['tab-1'] != null
const draftText = resolveStartupLaunchDraftText(startup)
const opensInChat =
decideInitialAgentTabViewMode({
await submitFolderWorkspaceCreate({
projectGroup: makeProjectGroup(),
name: '',
lastAutoName: '',
linkedWorkItem,
note,
quickAgent: agent,
autoRenameBranchFromWork: false,
createFolderWorkspace: vi.fn(async () => makeFolderWorkspace()),
onOpenChange: vi.fn()
})
const startup = mocks.activateAndRevealFolderWorkspace.mock.calls[0]?.[1]?.startup
const draftText = resolveStartupLaunchDraftText(startup)
const seeded = useAppStore.getState().nativeChatLaunchDraftByTabId['tab-1']?.text
const viewMode = decideInitialAgentTabViewMode({
experimentalNativeChat: true,
openAgentTabsInChatByDefault: true,
agent: quickAgent,
...(draftText != null
? { promptDelivery: 'draft' as const, launchDraftText: draftText }
: {})
}) === 'chat'
agent,
...(draftText ? { promptDelivery: 'draft' as const, launchDraftText: draftText } : {})
})
// The draft always reaches the TUI, whichever way it is delivered.
expect(`${startup?.command ?? ''}${startup?.draftPrompt ?? ''}`).toContain(ISSUE_URL)
expect(seeded).toBe(expectMirrored)
expect(opensInChat).toBe(expectMirrored)
})
expect(draftText).toContain(linkedWorkItem.url)
expect(seeded).toBe(draftText)
expect(viewMode).toBe('chat')
}
)
})
@@ -1,5 +1,6 @@
import type { LinkedWorkItemSummary } from '@/lib/new-workspace'
import { resolveQuickCreateLinkedWorkItemPrompt } from '@/lib/linked-work-item-context'
import { seedNativeChatLaunchDraftForAgentTab } from '@/lib/agent-launch-prompt-delivery'
import {
activateAndRevealFolderWorkspace,
type WorktreeStartupPayload
@@ -73,6 +74,7 @@ function buildFolderWorkspaceStartup(args: {
command: '',
launchAgent: agent,
agentLaunch,
...(linkedDraft ? { launchDraftText: linkedDraft } : {}),
// Host overwrites agent_kind from the resolved receipt before the emit, so
// this host-resolved launch threads only the surface-owned fields.
telemetry: {
@@ -168,10 +170,17 @@ export async function submitFolderWorkspaceCreate({
: undefined
onOpenChange(false)
try {
activateAndRevealFolderWorkspace(workspace.id, {
const activation = activateAndRevealFolderWorkspace(workspace.id, {
...(startup ? { startup } : {}),
runtimeEnvironmentId
})
if (activation && activation.primaryTabId && startup?.launchDraftText && quickAgent) {
seedNativeChatLaunchDraftForAgentTab({
tabId: activation.primaryTabId,
agent: quickAgent,
text: startup.launchDraftText
})
}
} catch (error) {
// Why: creation already succeeded. Do not leave the completed create modal
// open if the follow-up reveal/startup path hits a transient issue.
@@ -201,31 +201,6 @@ describe('launchWorkItemDirect', () => {
mockApi.agentTrust.markTrusted.mockResolvedValue(undefined)
})
it('rejects invalid per-launch CLI arguments before creating a workspace', async () => {
const { launchWorkItemDirect } = await import('./launch-work-item-direct')
await expect(
launchWorkItemDirect({
repoId: 'repo-1',
launchSource: 'task_page',
openModalFallback: vi.fn(),
agentArgs: '--model "unterminated',
item: {
type: 'issue',
number: 42,
title: 'Fix invalid saved launch args',
url: 'https://github.com/acme/repo/issues/42'
}
})
).resolves.toBe(false)
expect(mocks.createWorktree).not.toHaveBeenCalled()
expect(mocks.ensureDetectedAgents).not.toHaveBeenCalled()
expect(mocks.toastError).toHaveBeenCalledWith(
'CLI arguments are invalid: Unclosed quote in command template.'
)
})
it('passes a resolved PR branch override while using a short PR identity for workspace names', async () => {
mocks.ensureDetectedAgents.mockResolvedValue([])
mocks.store.settings = {}
@@ -279,7 +254,8 @@ describe('launchWorkItemDirect', () => {
undefined,
undefined,
undefined,
'refs/remotes/origin/main'
'refs/remotes/origin/main',
undefined
)
})
@@ -335,33 +311,21 @@ describe('launchWorkItemDirect', () => {
}
})
expect(mocks.createWorktree).toHaveBeenCalledWith(
'repo-1',
'eng-42-ship-linear-parity',
undefined,
'inherit',
undefined,
'sidebar',
'Ship Linear parity',
undefined,
undefined,
undefined,
undefined,
'ENG-42',
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined
)
const createArgs = mocks.createWorktree.mock.calls[0]
expect(createArgs?.[1]).toBe('eng-42-ship-linear-parity')
expect(createArgs?.[6]).toBe('Ship Linear parity')
expect(createArgs?.[10]).toBe('codex')
expect(createArgs?.[11]).toBe('ENG-42')
expect(createArgs?.[25]).toEqual({
agentLaunch: {
selection: { kind: 'agent', agent: 'codex' },
prompt:
'Linked Linear issue: ENG-42\nhttps://linear.app/acme/issue/ENG-42/ship-linear-parity\n',
promptDelivery: 'draft',
allowEmptyPromptLaunch: true
},
agentLaunchTelemetry: { launch_source: 'task_page', request_kind: 'new' }
})
})
it('prefills a link-only Linear reference without source context', async () => {
@@ -399,35 +363,23 @@ describe('launchWorkItemDirect', () => {
'Linked Linear issue: ENG-42',
'https://linear.app/acme/issue/ENG-42/ship-linear-parity'
].join('\n')
expect(buildAgentDraftLaunchPlan).toHaveBeenCalledWith({
agent: 'claude',
draft: `${expectedDraft}\n`,
cmdOverrides: {},
agentArgs: '--dangerously-skip-permissions',
agentEnv: {},
sessionOptions: undefined,
platform: 'win32',
isRemote: false
})
expect(buildAgentStartupPlan).not.toHaveBeenCalledWith(
expect.objectContaining({
agent: 'claude',
prompt: '',
expect(mocks.createWorktree.mock.calls[0]?.[25]).toEqual({
agentLaunch: {
selection: { kind: 'agent', agent: 'claude' },
prompt: `${expectedDraft}\n`,
promptDelivery: 'draft',
allowEmptyPromptLaunch: true
})
)
},
agentLaunchTelemetry: { launch_source: 'task_page', request_kind: 'new' }
})
expect(buildAgentDraftLaunchPlan).not.toHaveBeenCalled()
expect(buildAgentStartupPlan).not.toHaveBeenCalled()
expect(mocks.activateAndRevealWorktree).toHaveBeenCalledWith(
'repo-1::/repo/worktree',
expect.objectContaining({
startup: expect.objectContaining({
command: expect.stringContaining('Linked Linear issue: ENG-42')
})
backendStartupTerminalSpawned: true
})
)
const startupCommand = mocks.activateAndRevealWorktree.mock.calls[0]?.[1]?.startup?.command
expect(startupCommand).toContain('https://linear.app/acme/issue/ENG-42/ship-linear-parity')
expect(startupCommand).not.toContain('The distinctive Linear body text is here.')
expect(startupCommand).not.toContain('--- BEGIN LINKED WORK ITEM CONTEXT ---')
expect(pasteDraftWhenAgentReady).not.toHaveBeenCalled()
})
@@ -459,12 +411,14 @@ describe('launchWorkItemDirect', () => {
createdAt: expect.any(Number)
})
expect(mocks.seedNativeChatLaunchPrompt).not.toHaveBeenCalled()
// Why: the draft is inside `--prefill`, so the plan sets no draftPrompt.
// launchDraftText is the only thing that lets the view-mode gate see a
// draft here — without it this tab opens in chat unconditionally.
const startup = mocks.activateAndRevealWorktree.mock.calls.at(-1)?.[1]?.startup
expect(startup?.draftPrompt).toBeUndefined()
expect(startup?.launchDraftText).toBe('https://github.com/acme/repo/issues/12')
expect(mocks.createWorktree.mock.calls[0]?.[25]).toMatchObject({
agentLaunch: {
selection: { kind: 'agent', agent: 'claude' },
prompt: 'https://github.com/acme/repo/issues/12',
promptDelivery: 'draft'
}
})
expect(mocks.activateAndRevealWorktree.mock.calls.at(-1)?.[1]).not.toHaveProperty('startup')
})
it('seeds the chat-composer launch draft for a multi-line Linear draft launch', async () => {
@@ -524,23 +478,17 @@ describe('launchWorkItemDirect', () => {
})
).resolves.toBe(true)
expect(buildAgentDraftLaunchPlan).not.toHaveBeenCalled()
expect(pasteDraftWhenAgentReady).toHaveBeenCalledWith(
expect.objectContaining({
tabId: 'tab-1',
content: 'Use this explicit user prompt.',
agent: 'claude',
submit: true,
forcePaste: true,
onTimeout: expect.any(Function)
})
)
expect(mocks.seedNativeChatLaunchPrompt).toHaveBeenCalledWith({
tabId: 'tab-1',
agent: 'claude',
text: 'Use this explicit user prompt.',
createdAt: expect.any(Number)
expect(mocks.createWorktree.mock.calls[0]?.[25]).toEqual({
agentLaunch: {
selection: { kind: 'agent', agent: 'claude' },
prompt: 'Use this explicit user prompt.',
allowEmptyPromptLaunch: true
},
agentLaunchTelemetry: { launch_source: 'task_page', request_kind: 'new' }
})
expect(buildAgentDraftLaunchPlan).not.toHaveBeenCalled()
expect(pasteDraftWhenAgentReady).not.toHaveBeenCalled()
expect(mocks.seedNativeChatLaunchPrompt).not.toHaveBeenCalled()
expect(mocks.seedNativeChatLaunchDraft).not.toHaveBeenCalled()
})
@@ -585,38 +533,20 @@ describe('launchWorkItemDirect', () => {
expect(mocks.store.ensureDetectedAgents).not.toHaveBeenCalled()
expect(mocks.store.ensureRemoteDetectedAgents).toHaveBeenCalledWith('ssh-1')
expect(mockApi.agentTrust.markTrusted).toHaveBeenCalledWith({
preset: 'cursor',
workspacePath: '/home/orca/repo-worktrees/issue-77',
connectionId: 'ssh-1'
})
expect(buildAgentDraftLaunchPlan).toHaveBeenCalledWith({
agent: 'cursor',
draft: 'https://github.com/acme/repo/issues/77',
cmdOverrides: {},
agentArgs: '--yolo',
agentEnv: {},
sessionOptions: undefined,
platform: 'linux',
isRemote: true
})
expect(buildAgentStartupPlan).toHaveBeenCalledWith({
agent: 'cursor',
prompt: '',
cmdOverrides: {},
agentArgs: '--yolo',
agentEnv: {},
sessionOptions: undefined,
platform: 'linux',
isRemote: true,
allowEmptyPromptLaunch: true
expect(mockApi.agentTrust.markTrusted).not.toHaveBeenCalled()
expect(buildAgentDraftLaunchPlan).not.toHaveBeenCalled()
expect(buildAgentStartupPlan).not.toHaveBeenCalled()
expect(mocks.createWorktree.mock.calls[0]?.[25]).toMatchObject({
agentLaunch: {
selection: { kind: 'agent', agent: 'cursor' },
prompt: 'https://github.com/acme/repo/issues/77',
promptDelivery: 'draft'
}
})
expect(mocks.activateAndRevealWorktree).toHaveBeenCalledWith(
'wt-ssh',
expect.objectContaining({
startup: expect.objectContaining({
draftPrompt: 'https://github.com/acme/repo/issues/77'
})
backendStartupTerminalSpawned: true
})
)
expect(pasteDraftWhenAgentReady).not.toHaveBeenCalled()
@@ -686,12 +616,13 @@ describe('launchWorkItemDirect', () => {
})
).resolves.toBe(true)
expect(mocks.activateAndRevealWorktree).toHaveBeenCalled()
const activationOptions = mocks.activateAndRevealWorktree.mock.calls.at(-1)?.[1]
expect(activationOptions.startup.command).toContain(
`command test -n "$fish_pid" && set --erase -g ORCA_PI_PREFILL; command test -z "$fish_pid" && unset ORCA_PI_PREFILL; true`
)
expect(activationOptions.startup.command).not.toContain('Remove-Item Env:ORCA_PI_PREFILL')
expect(mocks.createWorktree.mock.calls[0]?.[25]).toMatchObject({
agentLaunch: { selection: { kind: 'agent', agent: 'pi' } }
})
expect(mocks.activateAndRevealWorktree.mock.calls.at(-1)?.[1]).toMatchObject({
backendStartupTerminalSpawned: true
})
expect(mocks.activateAndRevealWorktree.mock.calls.at(-1)?.[1]).not.toHaveProperty('startup')
})
it('uses the repo SSH connection when the created worktree is not hydrated yet', async () => {
@@ -730,10 +661,10 @@ describe('launchWorkItemDirect', () => {
expect(mocks.ensureRemoteDetectedAgents).toHaveBeenCalledWith('ssh-1')
expect(mocks.ensureDetectedAgents).not.toHaveBeenCalled()
const activationOptions = mocks.activateAndRevealWorktree.mock.calls.at(-1)?.[1]
expect(activationOptions.startup.command).toContain(
`command test -n "$fish_pid" && set --erase -g ORCA_PI_PREFILL; command test -z "$fish_pid" && unset ORCA_PI_PREFILL; true`
)
expect(mocks.createWorktree.mock.calls[0]?.[25]).toMatchObject({
agentLaunch: { selection: { kind: 'agent', agent: 'pi' } }
})
expect(mocks.activateAndRevealWorktree.mock.calls.at(-1)?.[1]).not.toHaveProperty('startup')
})
it('plans direct local Windows-path launches with POSIX startup for WSL project runtime', async () => {
@@ -781,11 +712,10 @@ describe('launchWorkItemDirect', () => {
})
).resolves.toBe(true)
expect(buildAgentStartupPlan).toHaveBeenCalledWith(
expect.objectContaining({
agent: 'codex',
platform: 'linux'
})
)
expect(buildAgentStartupPlan).not.toHaveBeenCalled()
expect(mocks.createWorktree.mock.calls[0]?.[25]).toMatchObject({
agentLaunch: { selection: { kind: 'agent', agent: 'codex' } }
})
expect(mocks.activateAndRevealWorktree.mock.calls.at(-1)?.[1]).not.toHaveProperty('startup')
})
})
@@ -19,6 +19,7 @@ import type { GitPushTarget, SetupDecision, TuiAgent } from '../../../shared/typ
import { getLinearIssueWorkspaceName } from '../../../shared/workspace-name'
import { resolveGitHubWorkItemIdentity } from '@/lib/github-work-item-identity'
import { getDirectWorkItemDraftContent } from '@/lib/launch-work-item-direct-draft'
import { seedNativeChatLaunchDraftForAgentTab } from '@/lib/agent-launch-prompt-delivery'
import {
resolveDirectPrStartPoint,
resolveDirectSetupDecision
@@ -238,6 +239,16 @@ export async function launchWorkItemDirect(args: LaunchWorkItemDirectArgs): Prom
toast.error(workspaceActivationErrorMessage())
return false
}
if (activation.primaryTabId && requestedAgent && promptDelivery === 'draft') {
const draft = draftContent.trim()
if (draft) {
seedNativeChatLaunchDraftForAgentTab({
tabId: activation.primaryTabId,
agent: requestedAgent,
text: draftContent
})
}
}
} catch (error) {
const message = error instanceof Error ? error.message : 'Failed to create workspace.'
toast.error(message)
@@ -8,6 +8,7 @@ import type {
WorkspaceLinkedItem
} from '../../../shared/types'
import type { AgentLaunchSpawnRequest } from '../../../shared/agent-launch-spawn-request'
import type { AgentStartupPlan } from '@/lib/tui-agent-startup'
import type { AgentStartedTelemetry } from '@/lib/worktree-activation'
import type { TaskSourceContext, WorkspaceRunContext } from '../../../shared/task-source-context'
import type { AgentStartupPlan } from '../../../shared/tui-agent-startup'
@@ -97,6 +98,10 @@ export type WorktreeCreationRequest = {
pendingFirstAgentMessageRename: boolean
/** Post-create note persisted as the worktree comment. */
note: string
/** Legacy renderer-owned startup retained for queued pre-host-launch requests. */
startupPlan?: AgentStartupPlan | null
quickPrompt?: string
launchDraftPrompt?: string
/** Telemetry emitted renderer-side off the host's `launched` receipt (the host
* create-spawn threads no telemetry). Null for blank-shell creates. */
quickTelemetry: AgentStartedTelemetry | null
@@ -1,10 +1,10 @@
import type { TuiAgent } from './tui-agent'
import type { BuiltInTuiAgent } from './types'
// Node CLIs whose shims launch a generic script (cli.js, versioned index.js), so
// only the exact install path is an authoritative identity signal.
export const EXACT_NODE_ENTRYPOINT_IDENTITIES: readonly {
pattern: RegExp
agent: TuiAgent
agent: BuiltInTuiAgent
processName: string
}[] = [
// Why: Cursor's native Windows launcher runs a generic versioned index.js,