Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -891,21 +891,23 @@ function TaskForm({
});
}}
/>
<PickerRow
label="Model"
borderTop
value={
modelOptions.find(
(option) =>
option.selection.instanceId === draft.modelSelection?.instanceId &&
option.selection.model === draft.modelSelection?.model,
)?.label ??
draft.modelSelection?.model ??
(modelOptions.length ? "Choose model" : "No models available")
}
onPress={() => navigation.navigate("SettingsScheduledTaskModel")}
disabled={saving || dictationPending || environmentUnavailable}
/>
{draft.threadId === null ? (
<PickerRow
label="Model"
borderTop
value={
modelOptions.find(
(option) =>
option.selection.instanceId === draft.modelSelection?.instanceId &&
option.selection.model === draft.modelSelection?.model,
)?.label ??
draft.modelSelection?.model ??
(modelOptions.length ? "Choose model" : "No models available")
}
onPress={() => navigation.navigate("SettingsScheduledTaskModel")}
disabled={saving || dictationPending || environmentUnavailable}
/>
) : null}
</SettingsSection>

<SettingsSection
Expand All @@ -918,7 +920,9 @@ function TaskForm({
? "Runs continue one conversation."
: "Runs share one thread, each in a fresh session without earlier runs' context."
}${
draft.threadId === null ? " The first run starts the thread." : ""
draft.threadId === null
? " The first run starts the thread."
: " Runs use the thread's current model."
} Deleting it also deletes this task.`
}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,20 @@ describe("ScheduledTasksSettings", () => {
await expect.element(dialog.getByRole("heading", { name: "New task" })).toBeInTheDocument();
await expect.element(name).toHaveValue("My draft");
});

it("offers the model only while the task is not bound to a thread", async () => {
setup();
await using _screen = await render(<ScheduledTasksSettings taskId={task.id} />);
const dialog = page.getByRole("dialog");
const model = dialog.getByRole("button", { name: "Choose model" });
await expect
.element(dialog.getByText("Each run continues this conversation", { exact: false }))
.toBeVisible();
await expect.element(model).not.toBeInTheDocument();

await userEvent.click(dialog.getByRole("combobox", { name: "Destination" }));
await userEvent.click(page.getByRole("option", { name: "New thread each run" }));

await expect.element(model).toBeEnabled();
});
});
40 changes: 21 additions & 19 deletions apps/web/src/components/settings/ScheduledTasksSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1245,7 +1245,7 @@ function ScheduledTaskDestination({
: "The first run starts a thread with the workspace and model below. Later runs post there, each in a fresh session without earlier runs' context."
: threadMode === "continue"
? "Each run continues this conversation, in its workspace and with its current model."
: "Each run starts a fresh session in this thread, without earlier runs' context.";
: "Each run starts a fresh session in this thread, with its current model and without earlier runs' context.";
return (
<Field label="Destination" htmlFor="scheduled-task-destination">
{onThreadModeChange ? (
Expand Down Expand Up @@ -1766,24 +1766,26 @@ function ScheduledTaskEditorForm({
/>
</Field>

<Field label="Model">
<div>
<ProviderModelPicker
environmentId={environmentId}
disabled={saving || !connected}
activeInstanceId={activeInstanceId}
model={activeModel}
lockedProvider={null}
instanceEntries={instanceEntries}
modelOptionsByInstance={modelOptionsByInstance}
isComposerOwned={false}
triggerClassName={SETTINGS_PICKER_TRIGGER_CLASSNAME}
onInstanceModelChange={(instanceId, model) =>
setDraft((current) => ({ ...current, modelKey: `${instanceId}:${model}` }))
}
/>
</div>
</Field>
{draft.threadId === "" ? (
<Field label="Model">
<div>
<ProviderModelPicker
environmentId={environmentId}
disabled={saving || !connected}
activeInstanceId={activeInstanceId}
model={activeModel}
lockedProvider={null}
instanceEntries={instanceEntries}
modelOptionsByInstance={modelOptionsByInstance}
isComposerOwned={false}
triggerClassName={SETTINGS_PICKER_TRIGGER_CLASSNAME}
onInstanceModelChange={(instanceId, model) =>
setDraft((current) => ({ ...current, modelKey: `${instanceId}:${model}` }))
}
/>
</div>
</Field>
) : null}

<div className="space-y-3">
{task?.schedule.type === "interval" &&
Expand Down
3 changes: 2 additions & 1 deletion docs/user/project-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ Under **Destination**, choose where runs go. **New thread each run** keeps every
run separate. The two one-thread choices start a thread on the first run and post
later runs there: one continues the same conversation, the other starts each run
in a fresh session that doesn't see earlier runs, so the thread stays readable
without the agent's context growing. To move a one-thread task, pick another
without the agent's context growing. Once the thread exists, runs use its current
model, so the task no longer offers a model choice. To move a one-thread task, pick another
thread in its project under **Destination**. Moving such a task to another
project starts a new thread there on its next run.

Expand Down
Loading