@oh-my-pi/pi-coding-agent 15.7.1 → 15.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/types/auto-thinking/classifier.d.ts +35 -0
- package/dist/types/config/settings-schema.d.ts +24 -4
- package/dist/types/edit/hashline/diff.d.ts +6 -0
- package/dist/types/modes/components/model-selector.d.ts +3 -2
- package/dist/types/modes/theme/theme.d.ts +2 -1
- package/dist/types/sdk.d.ts +2 -1
- package/dist/types/session/agent-session.d.ts +22 -9
- package/dist/types/thinking.d.ts +39 -1
- package/dist/types/tiny/device.d.ts +3 -3
- package/dist/types/tiny/models.d.ts +19 -0
- package/package.json +9 -9
- package/src/auto-thinking/classifier.ts +180 -0
- package/src/config/settings-schema.ts +24 -4
- package/src/edit/hashline/diff.ts +10 -2
- package/src/edit/streaming.ts +17 -6
- package/src/eval/__tests__/shared-executors.test.ts +32 -0
- package/src/eval/js/shared/local-module-loader.ts +75 -10
- package/src/internal-urls/docs-index.generated.ts +2 -2
- package/src/main.ts +6 -1
- package/src/modes/acp/acp-agent.ts +13 -3
- package/src/modes/components/footer.ts +10 -3
- package/src/modes/components/model-selector.ts +20 -11
- package/src/modes/components/settings-defs.ts +7 -0
- package/src/modes/components/settings-selector.ts +4 -1
- package/src/modes/components/status-line/segments.ts +13 -5
- package/src/modes/controllers/event-controller.ts +5 -1
- package/src/modes/controllers/selector-controller.ts +20 -6
- package/src/modes/theme/theme.ts +6 -0
- package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
- package/src/prompts/system/auto-thinking-difficulty.md +12 -0
- package/src/sdk.ts +25 -7
- package/src/session/agent-session.ts +193 -32
- package/src/thinking.ts +73 -1
- package/src/tiny/device.ts +4 -10
- package/src/tiny/models.ts +24 -0
|
@@ -200,9 +200,16 @@ export class FooterComponent implements Component {
|
|
|
200
200
|
// Add thinking level hint when the current model advertises supported efforts
|
|
201
201
|
let rightSide = modelName;
|
|
202
202
|
if (state.model?.thinking) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
203
|
+
if (this.session.isAutoThinking) {
|
|
204
|
+
// Pending (no turn classified yet / classifying) shows a symbol-theme
|
|
205
|
+
// question-box marker; once resolved it shows `<level>`.
|
|
206
|
+
const resolved = this.session.autoResolvedThinkingLevel();
|
|
207
|
+
rightSide = `${modelName} • ${resolved ? resolved : `${theme.thinking.autoPending} auto`}`;
|
|
208
|
+
} else {
|
|
209
|
+
const thinkingLevel = state.thinkingLevel ?? ThinkingLevel.Off;
|
|
210
|
+
if (thinkingLevel !== ThinkingLevel.Off) {
|
|
211
|
+
rightSide = `${modelName} • ${thinkingLevel}`;
|
|
212
|
+
}
|
|
206
213
|
}
|
|
207
214
|
}
|
|
208
215
|
|
|
@@ -19,7 +19,7 @@ import { resolveModelRoleValue } from "../../config/model-resolver";
|
|
|
19
19
|
import type { Settings } from "../../config/settings";
|
|
20
20
|
import { type ThemeColor, theme } from "../../modes/theme/theme";
|
|
21
21
|
import { matchesSelectDown, matchesSelectUp } from "../../modes/utils/keybinding-matchers";
|
|
22
|
-
import {
|
|
22
|
+
import { AUTO_THINKING, type ConfiguredThinkingLevel, getConfiguredThinkingLevelMetadata } from "../../thinking";
|
|
23
23
|
import { getTabBarTheme } from "../shared";
|
|
24
24
|
import { DynamicBorder } from "./dynamic-border";
|
|
25
25
|
|
|
@@ -83,10 +83,15 @@ interface ScopedModelItem {
|
|
|
83
83
|
|
|
84
84
|
interface RoleAssignment {
|
|
85
85
|
model: Model;
|
|
86
|
-
thinkingLevel:
|
|
86
|
+
thinkingLevel: ConfiguredThinkingLevel;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
type RoleSelectCallback = (
|
|
89
|
+
type RoleSelectCallback = (
|
|
90
|
+
model: Model,
|
|
91
|
+
role: string | null,
|
|
92
|
+
thinkingLevel?: ConfiguredThinkingLevel,
|
|
93
|
+
selector?: string,
|
|
94
|
+
) => void;
|
|
90
95
|
type CancelCallback = () => void;
|
|
91
96
|
interface MenuRoleAction {
|
|
92
97
|
label: string;
|
|
@@ -165,7 +170,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
165
170
|
settings: Settings,
|
|
166
171
|
modelRegistry: ModelRegistry,
|
|
167
172
|
scopedModels: ReadonlyArray<ScopedModelItem>,
|
|
168
|
-
onSelect:
|
|
173
|
+
onSelect: RoleSelectCallback,
|
|
169
174
|
onCancel: () => void,
|
|
170
175
|
options?: { temporaryOnly?: boolean; initialSearchInput?: string },
|
|
171
176
|
) {
|
|
@@ -790,7 +795,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
790
795
|
if (!tag || !assigned || !modelsAreEqual(assigned.model, item.model)) continue;
|
|
791
796
|
|
|
792
797
|
const badge = makeInvertedBadge(tag, color ?? "success");
|
|
793
|
-
const thinkingLabel =
|
|
798
|
+
const thinkingLabel = getConfiguredThinkingLevelMetadata(assigned.thinkingLevel).label;
|
|
794
799
|
roleBadgeTokens.push(`${badge} ${theme.fg("dim", `(${thinkingLabel})`)}`);
|
|
795
800
|
}
|
|
796
801
|
// Custom role badges
|
|
@@ -799,7 +804,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
799
804
|
const roleInfo = getRoleInfo(role, this.#settings);
|
|
800
805
|
const badgeLabel = roleInfo.tag ?? roleInfo.name;
|
|
801
806
|
const badge = makeInvertedBadge(badgeLabel, roleInfo.color ?? "muted");
|
|
802
|
-
const thinkingLabel =
|
|
807
|
+
const thinkingLabel = getConfiguredThinkingLevelMetadata(assigned.thinkingLevel).label;
|
|
803
808
|
roleBadgeTokens.push(`${badge} ${theme.fg("dim", `(${thinkingLabel})`)}`);
|
|
804
809
|
}
|
|
805
810
|
const badgeText = roleBadgeTokens.length > 0 ? ` ${roleBadgeTokens.join(" ")}` : "";
|
|
@@ -863,11 +868,11 @@ export class ModelSelectorComponent extends Container {
|
|
|
863
868
|
);
|
|
864
869
|
}
|
|
865
870
|
}
|
|
866
|
-
#getThinkingLevelsForModel(model: Model): ReadonlyArray<
|
|
867
|
-
return [ThinkingLevel.Inherit, ThinkingLevel.Off, ...getSupportedEfforts(model)];
|
|
871
|
+
#getThinkingLevelsForModel(model: Model): ReadonlyArray<ConfiguredThinkingLevel> {
|
|
872
|
+
return [ThinkingLevel.Inherit, ThinkingLevel.Off, AUTO_THINKING, ...getSupportedEfforts(model)];
|
|
868
873
|
}
|
|
869
874
|
|
|
870
|
-
#getCurrentRoleThinkingLevel(role: string):
|
|
875
|
+
#getCurrentRoleThinkingLevel(role: string): ConfiguredThinkingLevel {
|
|
871
876
|
return this.#roles[role]?.thinkingLevel ?? ThinkingLevel.Inherit;
|
|
872
877
|
}
|
|
873
878
|
|
|
@@ -912,7 +917,7 @@ export class ModelSelectorComponent extends Container {
|
|
|
912
917
|
const optionLines = showingThinking
|
|
913
918
|
? thinkingOptions.map((thinkingLevel, index) => {
|
|
914
919
|
const prefix = index === this.#menuSelectedIndex ? ` ${theme.nav.cursor} ` : " ";
|
|
915
|
-
const label =
|
|
920
|
+
const label = getConfiguredThinkingLevelMetadata(thinkingLevel).label;
|
|
916
921
|
return `${prefix}${label}`;
|
|
917
922
|
})
|
|
918
923
|
: this.#menuRoleActions.map((action, index) => {
|
|
@@ -1069,7 +1074,11 @@ export class ModelSelectorComponent extends Container {
|
|
|
1069
1074
|
}
|
|
1070
1075
|
}
|
|
1071
1076
|
|
|
1072
|
-
#handleSelect(
|
|
1077
|
+
#handleSelect(
|
|
1078
|
+
item: ModelItem | CanonicalModelItem,
|
|
1079
|
+
role: string | null,
|
|
1080
|
+
thinkingLevel?: ConfiguredThinkingLevel,
|
|
1081
|
+
): void {
|
|
1073
1082
|
// For temporary role, don't save to settings - just notify caller
|
|
1074
1083
|
if (role === null) {
|
|
1075
1084
|
this.#onSelectCallback(item.model, null, undefined, item.selector);
|
|
@@ -86,6 +86,13 @@ const CONDITIONS: Record<string, () => boolean> = {
|
|
|
86
86
|
return false;
|
|
87
87
|
}
|
|
88
88
|
},
|
|
89
|
+
autoThinkingActive: () => {
|
|
90
|
+
try {
|
|
91
|
+
return Settings.instance.get("defaultThinkingLevel") === "auto";
|
|
92
|
+
} catch {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
},
|
|
89
96
|
};
|
|
90
97
|
|
|
91
98
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -23,6 +23,7 @@ import type {
|
|
|
23
23
|
import { SETTING_TABS, TAB_METADATA } from "../../config/settings-schema";
|
|
24
24
|
import { getCurrentThemeName, getSelectListTheme, getSettingsListTheme, theme } from "../../modes/theme/theme";
|
|
25
25
|
import { matchesAppInterrupt } from "../../modes/utils/keybinding-matchers";
|
|
26
|
+
import { AUTO_THINKING, type ConfiguredThinkingLevel } from "../../thinking";
|
|
26
27
|
import { getTabBarTheme } from "../shared";
|
|
27
28
|
import { DynamicBorder } from "./dynamic-border";
|
|
28
29
|
import { handleInputOrEscape, PluginSettingsComponent } from "./plugin-settings";
|
|
@@ -373,7 +374,9 @@ export class SettingsSelectorComponent extends Container {
|
|
|
373
374
|
|
|
374
375
|
// Special case: inject runtime options for thinking level
|
|
375
376
|
if (def.path === "defaultThinkingLevel") {
|
|
376
|
-
|
|
377
|
+
// Prepend `auto`; the rest are the model's runtime-supported efforts.
|
|
378
|
+
const levels: ConfiguredThinkingLevel[] = [AUTO_THINKING, ...this.context.availableThinkingLevels];
|
|
379
|
+
options = levels.map(level => {
|
|
377
380
|
const baseOpt = options.find(o => o.value === level);
|
|
378
381
|
return baseOpt || { value: level, label: level };
|
|
379
382
|
});
|
|
@@ -90,11 +90,19 @@ const modelSegment: StatusLineSegment = {
|
|
|
90
90
|
|
|
91
91
|
// Add thinking level with dot separator
|
|
92
92
|
if (opts.showThinkingLevel !== false && state.model?.thinking) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
if (ctx.session.isAutoThinking) {
|
|
94
|
+
// Pending (no turn classified yet / classifying) shows a symbol-theme
|
|
95
|
+
// question-box marker; once resolved it shows `<level>`.
|
|
96
|
+
const resolved = ctx.session.autoResolvedThinkingLevel();
|
|
97
|
+
const resolvedText = resolved ? (theme.thinking[resolved as keyof typeof theme.thinking] ?? resolved) : "";
|
|
98
|
+
content += `${theme.sep.dot}${resolved ? resolvedText : `${theme.thinking.autoPending} auto`}`;
|
|
99
|
+
} else {
|
|
100
|
+
const level = state.thinkingLevel ?? ThinkingLevel.Off;
|
|
101
|
+
if (level !== ThinkingLevel.Off) {
|
|
102
|
+
const thinkingText = theme.thinking[level as keyof typeof theme.thinking];
|
|
103
|
+
if (thinkingText) {
|
|
104
|
+
content += `${theme.sep.dot}${thinkingText}`;
|
|
105
|
+
}
|
|
98
106
|
}
|
|
99
107
|
}
|
|
100
108
|
}
|
|
@@ -65,7 +65,11 @@ export class EventController {
|
|
|
65
65
|
todo_auto_clear: e => this.#handleTodoAutoClear(e),
|
|
66
66
|
irc_message: e => this.#handleIrcMessage(e),
|
|
67
67
|
notice: e => this.#handleNotice(e),
|
|
68
|
-
thinking_level_changed: async () => {
|
|
68
|
+
thinking_level_changed: async () => {
|
|
69
|
+
this.ctx.statusLine.invalidate();
|
|
70
|
+
this.ctx.updateEditorBorderColor();
|
|
71
|
+
this.ctx.ui.requestRender();
|
|
72
|
+
},
|
|
69
73
|
goal_updated: async () => {},
|
|
70
74
|
} satisfies AgentSessionEventHandlers;
|
|
71
75
|
}
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
import type { InteractiveModeContext } from "../../modes/types";
|
|
30
30
|
import { type SessionInfo, SessionManager } from "../../session/session-manager";
|
|
31
31
|
import { FileSessionStorage } from "../../session/session-storage";
|
|
32
|
+
import { AUTO_THINKING, type ConfiguredThinkingLevel } from "../../thinking";
|
|
32
33
|
import {
|
|
33
34
|
isImageProviderPreference,
|
|
34
35
|
isSearchProviderPreference,
|
|
@@ -252,7 +253,7 @@ export class SelectorController {
|
|
|
252
253
|
break;
|
|
253
254
|
case "thinkingLevel":
|
|
254
255
|
case "defaultThinkingLevel":
|
|
255
|
-
this.ctx.session.setThinkingLevel(value as
|
|
256
|
+
this.ctx.session.setThinkingLevel(value as ConfiguredThinkingLevel, true);
|
|
256
257
|
this.ctx.statusLine.invalidate();
|
|
257
258
|
this.ctx.updateEditorBorderColor();
|
|
258
259
|
break;
|
|
@@ -403,10 +404,18 @@ export class SelectorController {
|
|
|
403
404
|
this.ctx.session.modelRegistry,
|
|
404
405
|
this.ctx.session.scopedModels,
|
|
405
406
|
async (model, role, thinkingLevel, selector) => {
|
|
407
|
+
// `auto` is session-global: never baked into a per-role model value
|
|
408
|
+
// (it can't round-trip through `model:<level>`). Apply it to the session
|
|
409
|
+
// separately and persist via `defaultThinkingLevel`.
|
|
410
|
+
const isAuto = thinkingLevel === AUTO_THINKING;
|
|
411
|
+
const concreteThinking = isAuto ? undefined : thinkingLevel;
|
|
406
412
|
try {
|
|
407
413
|
if (role === null) {
|
|
408
|
-
// Temporary: update agent state but don't persist to settings
|
|
414
|
+
// Temporary: update agent state but don't persist the model to settings
|
|
409
415
|
await this.ctx.session.setModelTemporary(model);
|
|
416
|
+
if (isAuto) {
|
|
417
|
+
this.ctx.session.setThinkingLevel(AUTO_THINKING, true);
|
|
418
|
+
}
|
|
410
419
|
this.ctx.statusLine.invalidate();
|
|
411
420
|
this.ctx.updateEditorBorderColor();
|
|
412
421
|
this.ctx.showStatus(`Temporary model: ${selector ?? model.id}`);
|
|
@@ -416,10 +425,12 @@ export class SelectorController {
|
|
|
416
425
|
// Default: update agent state and persist
|
|
417
426
|
await this.ctx.session.setModel(model, role, {
|
|
418
427
|
selector,
|
|
419
|
-
thinkingLevel,
|
|
428
|
+
thinkingLevel: concreteThinking,
|
|
420
429
|
});
|
|
421
|
-
if (
|
|
422
|
-
this.ctx.session.setThinkingLevel(
|
|
430
|
+
if (isAuto) {
|
|
431
|
+
this.ctx.session.setThinkingLevel(AUTO_THINKING, true);
|
|
432
|
+
} else if (concreteThinking && concreteThinking !== ThinkingLevel.Inherit) {
|
|
433
|
+
this.ctx.session.setThinkingLevel(concreteThinking);
|
|
423
434
|
}
|
|
424
435
|
this.ctx.statusLine.invalidate();
|
|
425
436
|
this.ctx.updateEditorBorderColor();
|
|
@@ -429,8 +440,11 @@ export class SelectorController {
|
|
|
429
440
|
// Other roles (smol, slow): just update settings, not current model
|
|
430
441
|
this.ctx.settings.setModelRole(
|
|
431
442
|
role,
|
|
432
|
-
formatModelSelectorValue(selector ?? `${model.provider}/${model.id}`,
|
|
443
|
+
formatModelSelectorValue(selector ?? `${model.provider}/${model.id}`, concreteThinking),
|
|
433
444
|
);
|
|
445
|
+
if (isAuto) {
|
|
446
|
+
this.ctx.session.setThinkingLevel(AUTO_THINKING, true);
|
|
447
|
+
}
|
|
434
448
|
const roleInfo = getRoleInfo(role, settings);
|
|
435
449
|
const roleLabel = roleInfo?.name ?? role;
|
|
436
450
|
this.ctx.showStatus(`${roleLabel} model: ${selector ?? model.id}`);
|
package/src/modes/theme/theme.ts
CHANGED
|
@@ -132,6 +132,7 @@ export type SymbolKey =
|
|
|
132
132
|
| "thinking.medium"
|
|
133
133
|
| "thinking.high"
|
|
134
134
|
| "thinking.xhigh"
|
|
135
|
+
| "thinking.autoPending"
|
|
135
136
|
// Checkboxes
|
|
136
137
|
| "checkbox.checked"
|
|
137
138
|
| "checkbox.unchecked"
|
|
@@ -297,6 +298,7 @@ const UNICODE_SYMBOLS: SymbolMap = {
|
|
|
297
298
|
"thinking.medium": "◒ med",
|
|
298
299
|
"thinking.high": "◕ high",
|
|
299
300
|
"thinking.xhigh": "◉ xhigh",
|
|
301
|
+
"thinking.autoPending": "▣?",
|
|
300
302
|
// Checkboxes
|
|
301
303
|
"checkbox.checked": "☑",
|
|
302
304
|
"checkbox.unchecked": "☐",
|
|
@@ -550,6 +552,8 @@ const NERD_SYMBOLS: SymbolMap = {
|
|
|
550
552
|
"thinking.high": "\u{F111} high",
|
|
551
553
|
// pick: 🧠 xhi | alt: xhi xhi
|
|
552
554
|
"thinking.xhigh": "\u{F06D} xhi",
|
|
555
|
+
// pick: (nf-md-help_box) | alt: [?]
|
|
556
|
+
"thinking.autoPending": "\u{f078b}",
|
|
553
557
|
// Checkboxes
|
|
554
558
|
// pick: | alt:
|
|
555
559
|
"checkbox.checked": "\uf14a",
|
|
@@ -723,6 +727,7 @@ const ASCII_SYMBOLS: SymbolMap = {
|
|
|
723
727
|
"thinking.medium": "[med]",
|
|
724
728
|
"thinking.high": "[high]",
|
|
725
729
|
"thinking.xhigh": "[xhi]",
|
|
730
|
+
"thinking.autoPending": "[?]",
|
|
726
731
|
// Checkboxes
|
|
727
732
|
"checkbox.checked": "[x]",
|
|
728
733
|
"checkbox.unchecked": "[ ]",
|
|
@@ -1518,6 +1523,7 @@ export class Theme {
|
|
|
1518
1523
|
medium: this.#symbols["thinking.medium"],
|
|
1519
1524
|
high: this.#symbols["thinking.high"],
|
|
1520
1525
|
xhigh: this.#symbols["thinking.xhigh"],
|
|
1526
|
+
autoPending: this.#symbols["thinking.autoPending"],
|
|
1521
1527
|
};
|
|
1522
1528
|
}
|
|
1523
1529
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Classify the difficulty of the coding request below into one bucket, by how much reasoning it needs.
|
|
2
|
+
|
|
3
|
+
Buckets:
|
|
4
|
+
|
|
5
|
+
- trivial — obvious, mechanical, or a direct question (rename, typo, one-liner, simple lookup).
|
|
6
|
+
- moderate — a real but localized task (a small feature, a normal bug fix, explaining code).
|
|
7
|
+
- hard — deep, multi-file, ambiguous, or tricky debugging or design.
|
|
8
|
+
|
|
9
|
+
Reply with exactly one word: trivial, moderate, or hard.
|
|
10
|
+
|
|
11
|
+
Request:
|
|
12
|
+
{{prompt}}
|
|
13
|
+
|
|
14
|
+
Answer:
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
You are a difficulty classifier for a coding agent. Read the user's request and decide how much reasoning effort the agent should spend on it this turn.
|
|
2
|
+
|
|
3
|
+
Reply with exactly one word — one of: `low`, `medium`, `high`, `xhigh`. No punctuation, no explanation, no other text.
|
|
4
|
+
|
|
5
|
+
Levels:
|
|
6
|
+
|
|
7
|
+
- `low` — Trivial or mechanical. A rename, a typo, a one-line edit, a formatting tweak, a direct factual question, or a request whose solution is obvious.
|
|
8
|
+
- `medium` — A localized change that needs some reasoning. A small self-contained feature, a straightforward bug fix in one place, or explaining a moderate piece of code.
|
|
9
|
+
- `high` — A non-trivial change. Spans multiple files or callers, requires real debugging, a moderate design decision, or a refactor with several moving parts.
|
|
10
|
+
- `xhigh` — Deep or open-ended. Subtle concurrency or algorithmic problems, cross-system reasoning, ambiguous requirements, large or risky refactors, or hard root-cause debugging.
|
|
11
|
+
|
|
12
|
+
Judge the inherent difficulty of the task, not how politely or verbosely it is phrased. When torn between two levels, choose the lower one.
|
package/src/sdk.ts
CHANGED
|
@@ -112,7 +112,14 @@ import {
|
|
|
112
112
|
loadProjectContextFiles as loadContextFilesInternal,
|
|
113
113
|
} from "./system-prompt";
|
|
114
114
|
import { AgentOutputManager } from "./task/output-manager";
|
|
115
|
-
import {
|
|
115
|
+
import {
|
|
116
|
+
AUTO_THINKING,
|
|
117
|
+
type ConfiguredThinkingLevel,
|
|
118
|
+
parseThinkingLevel,
|
|
119
|
+
resolveProvisionalAutoLevel,
|
|
120
|
+
resolveThinkingLevelForModel,
|
|
121
|
+
toReasoningEffort,
|
|
122
|
+
} from "./thinking";
|
|
116
123
|
import {
|
|
117
124
|
collectDiscoverableTools,
|
|
118
125
|
type DiscoverableTool,
|
|
@@ -254,7 +261,7 @@ export interface CreateAgentSessionOptions {
|
|
|
254
261
|
* Used when model lookup is deferred because extension-provided models aren't registered yet. */
|
|
255
262
|
modelPattern?: string;
|
|
256
263
|
/** Thinking selector. Default: from settings, else unset */
|
|
257
|
-
thinkingLevel?:
|
|
264
|
+
thinkingLevel?: ConfiguredThinkingLevel;
|
|
258
265
|
/** Models available for cycling (Ctrl+P in interactive mode) */
|
|
259
266
|
scopedModels?: Array<{ model: Model; thinkingLevel?: ThinkingLevel }>;
|
|
260
267
|
|
|
@@ -1013,10 +1020,17 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1013
1020
|
if (thinkingLevel === undefined) {
|
|
1014
1021
|
thinkingLevel = settings.get("defaultThinkingLevel");
|
|
1015
1022
|
}
|
|
1023
|
+
const autoThinking = thinkingLevel === AUTO_THINKING;
|
|
1024
|
+
// Concrete level the agent/session start with. With `auto` this is the
|
|
1025
|
+
// provisional level shown until the first per-turn classification resolves;
|
|
1026
|
+
// `auto` itself stays a session-only concept handled by AgentSession.
|
|
1027
|
+
let effectiveThinkingLevel: ThinkingLevel | undefined = thinkingLevel === AUTO_THINKING ? undefined : thinkingLevel;
|
|
1016
1028
|
if (model) {
|
|
1017
1029
|
const resolvedModel = model;
|
|
1018
|
-
|
|
1019
|
-
|
|
1030
|
+
effectiveThinkingLevel = logger.time("resolveThinkingLevelForModel", () =>
|
|
1031
|
+
autoThinking
|
|
1032
|
+
? resolveProvisionalAutoLevel(resolvedModel)
|
|
1033
|
+
: resolveThinkingLevelForModel(resolvedModel, effectiveThinkingLevel),
|
|
1020
1034
|
);
|
|
1021
1035
|
// Fire-and-forget TLS+H2 handshake to the model's host so it overlaps
|
|
1022
1036
|
// with the rest of session setup (extension/skill load, tool registry,
|
|
@@ -1838,7 +1852,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1838
1852
|
initialState: {
|
|
1839
1853
|
systemPrompt,
|
|
1840
1854
|
model,
|
|
1841
|
-
thinkingLevel: toReasoningEffort(
|
|
1855
|
+
thinkingLevel: toReasoningEffort(effectiveThinkingLevel),
|
|
1842
1856
|
tools: initialTools,
|
|
1843
1857
|
},
|
|
1844
1858
|
convertToLlm: convertToLlmFinal,
|
|
@@ -1945,7 +1959,11 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1945
1959
|
if (model) {
|
|
1946
1960
|
sessionManager.appendModelChange(`${model.provider}/${model.id}`);
|
|
1947
1961
|
}
|
|
1948
|
-
|
|
1962
|
+
if (!autoThinking) {
|
|
1963
|
+
// `auto` is never written to the session log; resume reads it from the
|
|
1964
|
+
// `defaultThinkingLevel` setting instead, keeping `hasThinkingEntry` false.
|
|
1965
|
+
sessionManager.appendThinkingLevelChange(effectiveThinkingLevel);
|
|
1966
|
+
}
|
|
1949
1967
|
if (initialServiceTier) {
|
|
1950
1968
|
sessionManager.appendServiceTierChange(initialServiceTier);
|
|
1951
1969
|
}
|
|
@@ -1953,7 +1971,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1953
1971
|
|
|
1954
1972
|
session = new AgentSession({
|
|
1955
1973
|
agent,
|
|
1956
|
-
thinkingLevel,
|
|
1974
|
+
thinkingLevel: autoThinking ? AUTO_THINKING : effectiveThinkingLevel,
|
|
1957
1975
|
sessionManager,
|
|
1958
1976
|
settings,
|
|
1959
1977
|
evalKernelOwnerId,
|