Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .opencode/command/auto-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
description: autonomous Auto-Drive continuous execution mode
---

Please execute the following task with Auto-Drive enabled.
Continuously and autonomously execute all necessary steps, code modifications, and test verifications until the entire task is 100% finished without stopping mid-way for confirmation.

Task:
$ARGUMENTS
9 changes: 9 additions & 0 deletions .opencode/command/autodrive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
description: autonomous Auto-Drive continuous execution mode
---

Please execute the following task with Auto-Drive enabled.
Continuously and autonomously execute all necessary steps, code modifications, and test verifications until the entire task is 100% finished without stopping mid-way for confirmation.

Task:
$ARGUMENTS
36 changes: 36 additions & 0 deletions packages/app/src/components/prompt-input-v2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { type ImageAttachmentPart, usePrompt } from "@/context/prompt"
import { usePlatform } from "@/context/platform"
import { useSDK } from "@/context/sdk"
import { useSync } from "@/context/sync"
import { useSettings } from "@/context/settings"
import { createSessionTabs } from "@/pages/session/helpers"
import { showToast } from "@/utils/toast"
import { PromptInputV2, type PromptInputV2Suggestion } from "@opencode-ai/session-ui/v2/prompt-input"
Expand Down Expand Up @@ -58,6 +59,7 @@ export function PromptInputV2Composer(props: PromptInputV2ComposerProps) {
variantControlVisible={!props.controller.model.loading}
attachKeybind={command.keybindParts("file.attach")}
attachShortcut={command.keybind("file.attach")}
extraControl={<PromptInputV2AutoDriveControl />}
modelControl={
<PromptInputV2ModelControl
loading={props.controller.model.loading}
Expand All @@ -78,6 +80,40 @@ export function PromptInputV2Composer(props: PromptInputV2ComposerProps) {
)
}

export function PromptInputV2AutoDriveControl() {
const settings = useSettings()
const enabled = () => settings.general.autoDrive()

return (
<TooltipV2
placement="top"
gutter={6}
value={
enabled()
? "自动领航(Auto-Drive):已开启(一轮结束检测到下一步时自动续推)"
: "自动领航(Auto-Drive):已关闭(点击开启)"
}
>
<ButtonV2
variant={enabled() ? "neutral" : "ghost-muted"}
size="normal"
style={{ height: "28px", padding: "0 8px" }}
class="min-w-0 justify-start gap-1.5 ![font-weight:440] group cursor-pointer"
data-action="prompt-auto-drive-toggle"
onClick={() => settings.general.setAutoDrive(!enabled())}
>
<span class="text-12-medium" classList={{ "text-text-primary": enabled(), "text-text-weak": !enabled() }}>
自动领航
</span>
<span
class="h-1.5 w-1.5 rounded-full transition-colors"
classList={{ "bg-icon-success-base": enabled(), "bg-icon-subtle": !enabled() }}
/>
</ButtonV2>
</TooltipV2>
)
}

export function usePromptInputV2Controller(props: PromptInputV2ControllerProps): PromptInputV2ComposerController {
const sdk = useSDK()
const sync = useSync()
Expand Down
29 changes: 29 additions & 0 deletions packages/app/src/components/settings-general.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,35 @@ export const SettingsGeneral: Component = () => {
/>
</SettingsRow>

<SettingsRow
title="自动领航(Auto-Drive)"
description="在一轮执行结束后,若模型回答包含下一步计划或询问是否继续,自动发起续推指令推进任务"
>
<div data-action="settings-auto-drive">
<Switch
checked={settings.general.autoDrive()}
onChange={(checked) => settings.general.setAutoDrive(checked)}
/>
</div>
</SettingsRow>

<Show when={settings.general.autoDrive()}>
<SettingsRow
title="续推提示词(Auto-Drive Prompt)"
description="自动接续时发送给模型的提示词内容"
>
<div class="w-72" data-action="settings-auto-drive-prompt">
<TextField
value={settings.general.autoDrivePrompt()}
onChange={(value) => settings.general.setAutoDrivePrompt(value)}
placeholder="请继续执行下一步计划。"
variant="normal"
size="small"
/>
</div>
</SettingsRow>
</Show>

<SettingsRow
title={language.t("settings.general.row.reasoningSummaries.title")}
description={language.t("settings.general.row.reasoningSummaries.description")}
Expand Down
28 changes: 28 additions & 0 deletions packages/app/src/components/settings-v2/general.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,34 @@ export const SettingsGeneralV2: Component<{

<ShellSetting controller={shell} />

<SettingsRowV2
title="自动领航(Auto-Drive)"
description="在一轮执行结束后,若模型回答包含下一步计划或询问是否继续,自动发起续推指令推进任务"
>
<div data-action="settings-auto-drive">
<Switch
checked={settings.general.autoDrive()}
onChange={(checked) => settings.general.setAutoDrive(checked)}
/>
</div>
</SettingsRowV2>

<Show when={settings.general.autoDrive()}>
<SettingsRowV2
title="续推提示词(Auto-Drive Prompt)"
description="自动接续时发送给模型的提示词内容"
>
<div class="w-72" data-action="settings-auto-drive-prompt">
<TextInputV2
value={settings.general.autoDrivePrompt()}
onInput={(event) => settings.general.setAutoDrivePrompt(event.currentTarget.value)}
placeholder="请继续执行下一步计划。"
appearance="base"
/>
</div>
</SettingsRowV2>
</Show>

<SettingsRowV2
title={language.t("settings.general.row.reasoningSummaries.title")}
description={language.t("settings.general.row.reasoningSummaries.description")}
Expand Down
32 changes: 21 additions & 11 deletions packages/app/src/context/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export interface Settings {
autoSave: boolean
releaseNotes: boolean
followup: "queue" | "steer"
autoDrive: boolean
autoDrivePrompt: string
autoDriveMaxRuns: number
showFileTree: boolean
showNavigation: boolean
showSearch: boolean
Expand Down Expand Up @@ -184,7 +187,10 @@ const defaultSettings: Settings = {
general: {
autoSave: true,
releaseNotes: true,
followup: "steer",
followup: "queue",
autoDrive: true,
autoDrivePrompt: "请继续执行下一步计划。",
autoDriveMaxRuns: 5,
showFileTree: false,
showNavigation: false,
showSearch: false,
Expand Down Expand Up @@ -350,11 +356,6 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont
root.style.setProperty("--font-family-sans", sansFontFamily(store.appearance?.sans))
})

createEffect(() => {
if (store.general?.followup !== "queue") return
setStore("general", "followup", "steer")
})

return {
ready,
get current() {
Expand All @@ -369,12 +370,21 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont
setReleaseNotes(value: boolean) {
setStore("general", "releaseNotes", value)
},
followup: withFallback(
() => (store.general?.followup === "queue" ? "steer" : store.general?.followup),
defaultSettings.general.followup,
),
followup: withFallback(() => store.general?.followup, defaultSettings.general.followup),
setFollowup(value: "queue" | "steer") {
setStore("general", "followup", value === "queue" ? "steer" : value)
setStore("general", "followup", value)
},
autoDrive: withFallback(() => store.general?.autoDrive, defaultSettings.general.autoDrive),
setAutoDrive(value: boolean) {
setStore("general", "autoDrive", value)
},
autoDrivePrompt: withFallback(() => store.general?.autoDrivePrompt, defaultSettings.general.autoDrivePrompt),
setAutoDrivePrompt(value: string) {
setStore("general", "autoDrivePrompt", value)
},
autoDriveMaxRuns: withFallback(() => store.general?.autoDriveMaxRuns, defaultSettings.general.autoDriveMaxRuns),
setAutoDriveMaxRuns(value: number) {
setStore("general", "autoDriveMaxRuns", value)
},
showFileTree,
setShowFileTree(value: boolean) {
Expand Down
4 changes: 2 additions & 2 deletions packages/app/src/utils/server-compat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ function createV1Api(input: CompatibleInput): CompatibleApi {
timeCreated: Date.now(),
type: "user",
data: { text: value.text },
delivery: value.delivery ?? "steer",
delivery: value.delivery ?? "queue",
}
},
async command(value: SessionCommandInput) {
Expand All @@ -261,7 +261,7 @@ function createV1Api(input: CompatibleInput): CompatibleApi {
timeCreated: Date.now(),
type: "user",
data: { text: `/${value.command} ${value.arguments ?? ""}`.trim() },
delivery: value.delivery ?? "steer",
delivery: value.delivery ?? "queue",
}
},
async shell(value: SessionShellInput & LegacyPrompt) {
Expand Down
15 changes: 15 additions & 0 deletions packages/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,21 @@ export class Info extends Schema.Class<Info>("Config.Info")({
plugins: ConfigPlugin.Plugins.pipe(Schema.optional).annotate({
description: "Ordered external plugin packages to load",
}),
auto_drive: Schema.Union([
Schema.Boolean,
Schema.Struct({
enabled: Schema.Boolean.pipe(Schema.optional),
prompt: Schema.String.pipe(Schema.optional),
max_runs: Schema.Number.pipe(Schema.optional),
supervisor: Schema.Boolean.pipe(Schema.optional),
memory: Schema.Boolean.pipe(Schema.optional),
contextual: Schema.Boolean.pipe(Schema.optional),
}),
])
.pipe(Schema.optional)
.annotate({
description: "Auto-Drive automatic continuation configuration",
}),
experimental: ConfigExperimental.Experimental.pipe(Schema.optional),
providers: Schema.Record(Schema.String, ConfigProvider.Info).pipe(Schema.optional),
}) {}
Expand Down
10 changes: 10 additions & 0 deletions packages/core/src/plugin/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ export const Plugin = define({
command.description = "review changes [commit|branch|pr], defaults to uncommitted"
command.subtask = true
})
draft.update("autodrive", (command) => {
command.template =
"Please execute the following task with Auto-Drive enabled. Continuously execute subsequent steps, code modifications, and test verifications until fully finished without stopping mid-way for confirmation.\n\nTask:\n$ARGUMENTS"
command.description = "autonomous Auto-Drive continuous execution mode"
})
draft.update("auto-drive", (command) => {
command.template =
"Please execute the following task with Auto-Drive enabled. Continuously execute subsequent steps, code modifications, and test verifications until fully finished without stopping mid-way for confirmation.\n\nTask:\n$ARGUMENTS"
command.description = "autonomous Auto-Drive continuous execution mode"
})
})
}),
})
Loading
Loading