fix(new-workspace): type linked URL into agent input without auto-submit

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Neil
2026-05-04 20:39:27 -07:00
co-authored by Orca
parent cee7adcd93
commit 9b9c74e158
3 changed files with 51 additions and 11 deletions
+13 -8
View File
@@ -1365,14 +1365,15 @@ export function useComposerState(options: UseComposerStateOptions): UseComposerS
...(trimmedNote ? { comment: trimmedNote } : {})
})
const quickPrompt = linkedWorkItem
? linkedWorkItem.number === 0 && trimmedNote
? trimmedNote
: renderIssueCommandTemplate(DEFAULT_ISSUE_COMMAND_TEMPLATE, {
issueNumber: parsedLinkedIssueNumber,
artifactUrl: linkedWorkItem.url
})
: ''
// Why: when a linked work item is selected in the quick flow, launch
// the agent with a blank prompt and type the URL into its input as a
// draft (no trailing Enter). This lets the user review/edit before
// sending instead of auto-executing a "Complete <url>" template.
// Falls back to the trimmed note when the linked item carries no
// number/URL (Linear typed-only entries).
const isLinearTypedOnly = linkedWorkItem?.number === 0 && Boolean(trimmedNote)
const quickPrompt = isLinearTypedOnly && trimmedNote ? trimmedNote : ''
const quickDraftPrompt = linkedWorkItem && !isLinearTypedOnly ? linkedWorkItem.url : null
const startupPlan =
agent === null
@@ -1385,6 +1386,10 @@ export function useComposerState(options: UseComposerStateOptions): UseComposerS
allowEmptyPromptLaunch: true
})
if (startupPlan && quickDraftPrompt) {
startupPlan.draftPrompt = quickDraftPrompt
}
activateAndRevealWorktree(worktree.id, {
setup: result.setup,
...(startupPlan ? { startup: { command: startupPlan.launchCommand } } : {})
+32 -3
View File
@@ -200,11 +200,13 @@ export async function ensureAgentStartupInTerminal(args: {
startup: AgentStartupPlan
}): Promise<void> {
const { worktreeId, startup } = args
if (startup.followupPrompt === null) {
const draftPrompt = startup.draftPrompt ?? null
if (startup.followupPrompt === null && draftPrompt === null) {
return
}
let promptInjected = false
let draftInjected = false
for (let attempt = 0; attempt < 30; attempt += 1) {
if (attempt > 0) {
@@ -232,10 +234,21 @@ export async function ensureAgentStartupInTerminal(args: {
if (agentOwnsForeground && !promptInjected && startup.followupPrompt) {
window.api.pty.write(ptyId, `${startup.followupPrompt}\r`)
promptInjected = true
return
}
if (agentOwnsForeground && promptInjected) {
// Why: type the draft into the live agent input WITHOUT a trailing
// carriage return. The user wants the URL pre-filled so they can edit
// before sending — appending \r would auto-submit and defeat the point.
if (agentOwnsForeground && !draftInjected && draftPrompt) {
window.api.pty.write(ptyId, draftPrompt)
draftInjected = true
}
if (
agentOwnsForeground &&
(promptInjected || startup.followupPrompt === null) &&
(draftInjected || draftPrompt === null)
) {
return
}
@@ -253,6 +266,22 @@ export async function ensureAgentStartupInTerminal(args: {
// live session instead of launching the binary a second time.
window.api.pty.write(ptyId, `${startup.followupPrompt}\r`)
promptInjected = true
}
if (
!draftInjected &&
draftPrompt &&
hasChildProcesses &&
!isShellProcess(foreground) &&
attempt >= 4
) {
window.api.pty.write(ptyId, draftPrompt)
draftInjected = true
}
if (
(promptInjected || startup.followupPrompt === null) &&
(draftInjected || draftPrompt === null)
) {
return
}
} catch {
@@ -5,6 +5,12 @@ export type AgentStartupPlan = {
launchCommand: string
expectedProcess: string
followupPrompt: string | null
/** Why: text to type into the live agent input WITHOUT submitting it (no
* trailing \r). Used by the quick-create flow to pre-fill a linked work
* item URL so the user can edit/add to it before sending. Independent from
* `followupPrompt` so the call site can choose: type-and-submit (followup)
* or type-and-leave-pending (draft). */
draftPrompt?: string | null
}
function quoteStartupArg(value: string, platform: NodeJS.Platform): string {