Skip to content

Commit b0dd0b1

Browse files
refactor(core): own composer model policy
Generated-By: PostHog Code Task-Id: c1bbe3cf-742b-4b24-bf96-d11a18b4cf22
1 parent af87228 commit b0dd0b1

5 files changed

Lines changed: 83 additions & 36 deletions

File tree

apps/mobile/src/app/task/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
DEFAULT_CLAUDE_EXECUTION_MODE,
44
getAvailableModes,
55
} from "@posthog/core/sessions/executionModes";
6+
import { resolveCloudComposerModelChange } from "@posthog/core/task-detail/composerModelPolicy";
67
import {
78
DEFAULT_GATEWAY_MODEL,
89
DEFAULT_REASONING_EFFORT,
@@ -59,7 +60,6 @@ import {
5960
getComposerModelOptions,
6061
getConfigOptionLabel,
6162
getModelConfigOption,
62-
resolveComposerModelChange,
6363
} from "@/features/tasks/composer/options";
6464
import { Pill } from "@/features/tasks/composer/Pill";
6565
import { RepositoryPickerInline } from "@/features/tasks/composer/RepositoryPickerInline";
@@ -215,7 +215,7 @@ export default function NewTaskScreen() {
215215

216216
useEffect(() => {
217217
if (!hasLiveConfig) return;
218-
const next = resolveComposerModelChange({
218+
const next = resolveCloudComposerModelChange({
219219
adapter: "claude",
220220
modelOption: modelConfigOption,
221221
requestedModel: model,
@@ -777,7 +777,7 @@ export default function NewTaskScreen() {
777777
title="Model"
778778
value={model}
779779
onChange={(value) => {
780-
const next = resolveComposerModelChange({
780+
const next = resolveCloudComposerModelChange({
781781
adapter: "claude",
782782
modelOption: modelConfigOption,
783783
requestedModel: value,

apps/mobile/src/features/tasks/composer/TaskChatComposer.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
DEFAULT_CLAUDE_EXECUTION_MODE,
44
getAvailableModes,
55
} from "@posthog/core/sessions/executionModes";
6+
import { resolveCloudComposerModelChange } from "@posthog/core/task-detail/composerModelPolicy";
67
import {
78
DEFAULT_GATEWAY_MODEL,
89
DEFAULT_REASONING_EFFORT,
@@ -59,7 +60,6 @@ import {
5960
getComposerModelOptions,
6061
getConfigOptionLabel,
6162
getModelConfigOption,
62-
resolveComposerModelChange,
6363
resolveComposerPrimaryAction,
6464
} from "./options";
6565
import { Pill } from "./Pill";
@@ -206,7 +206,7 @@ export function TaskChatComposer({
206206

207207
useEffect(() => {
208208
if (!hasLiveConfig) return;
209-
const next = resolveComposerModelChange({
209+
const next = resolveCloudComposerModelChange({
210210
adapter: "claude",
211211
modelOption: modelConfigOption,
212212
requestedModel: model,
@@ -498,7 +498,7 @@ export function TaskChatComposer({
498498
title="Model"
499499
value={model}
500500
onChange={(v) => {
501-
const next = resolveComposerModelChange({
501+
const next = resolveCloudComposerModelChange({
502502
adapter: "claude",
503503
modelOption: modelConfigOption,
504504
requestedModel: v,

apps/mobile/src/features/tasks/composer/options.ts

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import {
2-
type Adapter,
32
type CloudTaskConfigOption,
4-
DEFAULT_REASONING_EFFORT,
53
isRestrictedModelOption,
6-
isSupportedReasoningEffort,
7-
type SupportedReasoningEffort,
84
} from "@posthog/shared";
95

106
export interface MobileModelOption {
@@ -40,32 +36,6 @@ export function getConfigOptionLabel(
4036
return options.find((option) => option.value === value)?.name ?? value;
4137
}
4238

43-
export function resolveComposerModelChange({
44-
adapter,
45-
modelOption,
46-
requestedModel,
47-
reasoning,
48-
}: {
49-
adapter: Adapter;
50-
modelOption: CloudTaskConfigOption;
51-
requestedModel: string;
52-
reasoning: SupportedReasoningEffort;
53-
}): { model: string; reasoning: SupportedReasoningEffort } {
54-
const selected = modelOption.options.find(
55-
(option) => option.value === requestedModel,
56-
);
57-
const model =
58-
selected && !isRestrictedModelOption(selected._meta)
59-
? requestedModel
60-
: modelOption.currentValue;
61-
return {
62-
model,
63-
reasoning: isSupportedReasoningEffort(adapter, model, reasoning)
64-
? reasoning
65-
: DEFAULT_REASONING_EFFORT,
66-
};
67-
}
68-
6939
export type ComposerPrimaryAction =
7040
| "send"
7141
| "stop"
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import {
2+
type Adapter,
3+
type CloudTaskConfigOption,
4+
DEFAULT_GATEWAY_MODEL,
5+
restrictedModelMeta,
6+
type SupportedReasoningEffort,
7+
} from "@posthog/shared";
8+
import { expect, it } from "vitest";
9+
import { resolveCloudComposerModelChange } from "./composerModelPolicy";
10+
11+
const modelOption: CloudTaskConfigOption = {
12+
id: "model",
13+
name: "Model",
14+
type: "select",
15+
currentValue: DEFAULT_GATEWAY_MODEL,
16+
options: [
17+
{ value: DEFAULT_GATEWAY_MODEL, name: "Claude" },
18+
{ value: "restricted", name: "Restricted", _meta: restrictedModelMeta() },
19+
{ value: "gpt-5.3-codex", name: "Codex" },
20+
],
21+
category: "model",
22+
description: "Choose a model",
23+
};
24+
25+
it.each([
26+
["claude", DEFAULT_GATEWAY_MODEL, "high", DEFAULT_GATEWAY_MODEL, "high"],
27+
["claude", "restricted", "high", DEFAULT_GATEWAY_MODEL, "high"],
28+
["claude", "missing", "high", DEFAULT_GATEWAY_MODEL, "high"],
29+
["codex", "gpt-5.3-codex", "xhigh", "gpt-5.3-codex", "high"],
30+
] as const)(
31+
"resolves %s model %s with %s reasoning",
32+
(adapter, requestedModel, reasoning, expectedModel, expectedReasoning) => {
33+
expect(
34+
resolveCloudComposerModelChange({
35+
adapter: adapter as Adapter,
36+
modelOption,
37+
requestedModel,
38+
reasoning: reasoning as SupportedReasoningEffort,
39+
}),
40+
).toEqual({ model: expectedModel, reasoning: expectedReasoning });
41+
},
42+
);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import {
2+
type Adapter,
3+
type CloudTaskConfigOption,
4+
DEFAULT_REASONING_EFFORT,
5+
isRestrictedModelOption,
6+
isSupportedReasoningEffort,
7+
type SupportedReasoningEffort,
8+
} from "@posthog/shared";
9+
10+
export function resolveCloudComposerModelChange({
11+
adapter,
12+
modelOption,
13+
requestedModel,
14+
reasoning,
15+
}: {
16+
adapter: Adapter;
17+
modelOption: CloudTaskConfigOption;
18+
requestedModel: string;
19+
reasoning: SupportedReasoningEffort;
20+
}): { model: string; reasoning: SupportedReasoningEffort } {
21+
const selected = modelOption.options.find(
22+
(option) => option.value === requestedModel,
23+
);
24+
const model =
25+
selected && !isRestrictedModelOption(selected._meta)
26+
? requestedModel
27+
: modelOption.currentValue;
28+
29+
return {
30+
model,
31+
reasoning: isSupportedReasoningEffort(adapter, model, reasoning)
32+
? reasoning
33+
: DEFAULT_REASONING_EFFORT,
34+
};
35+
}

0 commit comments

Comments
 (0)