Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2b7c8f2
fix(acp): later model selectors like Cline's model become session opt…
StiensWout Oct 15, 2026
aeb6904
fix(acp): registry models keep their own option lists
StiensWout Oct 14, 2026
3981a02
fix(acp): switching Cline providers no longer carries the old provide…
StiensWout Oct 15, 2026
1923f2d
fix(acp): a saved Cline model survives a server restart
StiensWout Oct 15, 2026
289e3a9
fix(acp): a saved Cline model is never swapped for another model
StiensWout Oct 15, 2026
6a149bb
fix(acp): changing another Cline option no longer pins its current model
StiensWout Oct 15, 2026
b0712a6
fix(acp): a saved option under the model picker's ID no longer overri…
StiensWout Oct 15, 2026
19ea86d
fix(acp): reconcile secondary model options with current main
maria-rcks Oct 31, 2026
fcda222
fix(acp): preserve current test coverage after merge
maria-rcks Oct 31, 2026
809072c
fix(acp): keep tuning rejection and plan filtering scoped
maria-rcks Oct 31, 2026
efe5e35
fix(acp): merge current main into secondary model options
maria-rcks Nov 1, 2026
ce047cd
fix(acp): preserve dependent secondary model selections
maria-rcks Nov 1, 2026
e8e223d
fix(acp): preserve model options while merging main
maria-rcks Nov 1, 2026
5083ec4
fix(acp): retry dependent selections and preserve resumed options
maria-rcks Nov 1, 2026
683e754
fix(acp): preserve model option cache while merging main
maria-rcks Nov 3, 2026
53c2cd2
fix(acp): enforce mode ceiling for deferred options
maria-rcks Nov 3, 2026
4c62a70
Merge remote-tracking branch 'origin/main' into t3code/acp-secondary-…
juliusmarminge Nov 11, 2026
2fe3454
chore(acp): trim duplicate tests and redundant checks
juliusmarminge Nov 11, 2026
3bc760a
fix(acp): models that have not run keep the probed tuning options
juliusmarminge Nov 11, 2026
360e8de
fix(acp): editing an option keeps a saved model choice no descriptor …
juliusmarminge Nov 11, 2026
3e46368
fix(acp): a turn fails when the agent drops a saved later model mid-s…
juliusmarminge Nov 11, 2026
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
6 changes: 5 additions & 1 deletion apps/mobile/src/features/threads/ThreadSettingsSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,9 @@ function ThreadSettingsSessionProvider(
};

const applyOptionChange = (id: string, value: string | boolean) => {
const savedSelections = pendingModel
? pendingModel.selection.options
: props.selectedModel?.options;
const descriptor = displayedDescriptors.find((entry) => entry.id === id);
const change =
descriptor?.type === "select" && typeof value === "string"
Expand All @@ -538,6 +541,7 @@ function ThreadSettingsSessionProvider(
descriptor,
displayedPrompt,
value,
savedSelections,
)
: null;
if (descriptor?.type === "select") {
Expand All @@ -552,7 +556,7 @@ function ThreadSettingsSessionProvider(
}
const next = change
? (change.modelOptions ?? [])
: applyProviderOptionSelection(displayedDescriptors, { id, value });
: applyProviderOptionSelection(displayedDescriptors, { id, value }, savedSelections);
if (!next) {
return;
}
Expand Down
40 changes: 40 additions & 0 deletions apps/mobile/src/lib/modelOptions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,46 @@ describe("mobile model options", () => {
expect(explicitOption?.selection.options).toEqual([{ id: "serviceTier", value: "priority" }]);
});

it("keeps an ACP model's saved model choice before that model has run", () => {
const instanceId = ProviderInstanceId.make("acpRegistry_cline");
const config = {
providers: [
{
instanceId,
driver: "acpRegistry",
displayName: "Cline",
enabled: true,
installed: true,
auth: { status: "authenticated" },
models: [
{
slug: "cline-pass",
name: "ClinePass",
isCustom: false,
// Borrowed tuning options: the model choice is not described yet.
capabilities: {
optionDescriptors: [
{ id: "auto_approve", label: "Auto-approve tools", type: "boolean" },
],
},
},
],
},
],
} as unknown as ServerConfig;
const saved: ModelSelection = {
instanceId,
model: "cline-pass",
options: [
{ id: "model", value: "cline-pass/muse-spark-1.3-contributor" },
{ id: "auto_approve", value: true },
],
};

const [option] = buildModelOptions(config, saved, undefined, null);
expect(option?.selection).toEqual(saved);
});

it("limits existing threads to their provider while new tasks keep every provider", () => {
const providers = ["codex", "claudeAgent"].map((instanceId) => ({
instanceId,
Expand Down
24 changes: 18 additions & 6 deletions apps/mobile/src/lib/modelOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
import {
buildExplicitProviderOptionSelectionsFromDescriptors,
getProviderOptionDescriptors,
withUndescribedSelections,
} from "@t3tools/shared/model";
import { resolveModelShortName } from "@t3tools/client-runtime/provider-clients";

Expand Down Expand Up @@ -137,20 +138,26 @@ function isDriverDisallowed(config: T3ServerConfig | null | undefined, driver: s
function normalizeSelectionOptions(
selection: ModelSelection,
capabilities: ModelCapabilities | null,
driver: string,
): ModelSelection {
if (!capabilities) {
return selection;
}
if (!selection.options?.length) {
return { instanceId: selection.instanceId, model: selection.model };
}
const options = buildExplicitProviderOptionSelectionsFromDescriptors(
getProviderOptionDescriptors({
caps: capabilities,
selections: selection.options,
}),
const descriptors = getProviderOptionDescriptors({
caps: capabilities,
selections: selection.options,
});
const explicit = buildExplicitProviderOptionSelectionsFromDescriptors(
descriptors,
selection.options,
);
const options =
driver === "acpRegistry"
? withUndescribedSelections(descriptors, explicit, selection.options)
: explicit;
return options
? { ...selection, options }
: {
Expand Down Expand Up @@ -389,6 +396,7 @@ export function buildModelOptions(
model: model.slug,
},
model.capabilities,
provider.driver,
),
});
}
Expand All @@ -413,7 +421,11 @@ export function buildModelOptions(
selection:
existing.providerDriver === "antigravity"
? fallbackModelSelection
: normalizeSelectionOptions(fallbackModelSelection, existing.capabilities),
: normalizeSelectionOptions(
fallbackModelSelection,
existing.capabilities,
existing.providerDriver,
),
});
} else {
const provider = config?.providers.find(
Expand Down
7 changes: 5 additions & 2 deletions apps/mobile/src/lib/providerOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {
ProviderOptionSelection,
} from "@t3tools/contracts";
import {
buildProviderOptionSelectionsFromDescriptors,
buildProviderOptionSelectionsAfterChange,
getProviderOptionDescriptors,
} from "@t3tools/shared/model";

Expand All @@ -24,6 +24,7 @@ export function resolveProviderOptionDescriptors(input: {
export function applyProviderOptionSelection(
descriptors: ReadonlyArray<ProviderOptionDescriptor>,
change: ProviderOptionSelection,
savedSelections: ReadonlyArray<ProviderOptionSelection> | null | undefined,
): ReadonlyArray<ProviderOptionSelection> | null {
const descriptor = descriptors.find((candidate) => candidate.id === change.id);
if (!descriptor) {
Expand All @@ -47,5 +48,7 @@ export function applyProviderOptionSelection(
: candidate,
) as ReadonlyArray<ProviderOptionDescriptor>;

return buildProviderOptionSelectionsFromDescriptors(nextDescriptors) ?? [];
return (
buildProviderOptionSelectionsAfterChange(nextDescriptors, change.id, savedSelections) ?? []
);
}
Loading
Loading