pi-advisor-flow 0.1.9 → 0.2.0
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/README.md +15 -11
- package/extensions/index.ts +17 -1
- package/package.json +25 -21
- package/src/commands.ts +346 -99
- package/src/config.ts +345 -94
- package/src/conversation.ts +199 -48
- package/src/herdr.ts +145 -30
- package/src/session-state.ts +182 -41
- package/src/tools.ts +687 -179
- package/src/ui.ts +317 -81
package/src/ui.ts
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
|
-
import { Input, Key, matchesKey, fuzzyFilter, truncateToWidth, type Component, type Focusable } from "@earendil-works/pi-tui";
|
|
2
|
-
import { Box, Text } from "@earendil-works/pi-tui";
|
|
3
1
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import {
|
|
3
|
+
type Component,
|
|
4
|
+
type Focusable,
|
|
5
|
+
fuzzyFilter,
|
|
6
|
+
Input,
|
|
7
|
+
Key,
|
|
8
|
+
matchesKey,
|
|
9
|
+
truncateToWidth,
|
|
10
|
+
} from "@earendil-works/pi-tui";
|
|
4
11
|
|
|
5
12
|
export class SearchableModelSelector implements Component, Focusable {
|
|
6
|
-
private tui: any;
|
|
7
|
-
private searchInput: Input;
|
|
8
|
-
private allOptions: string[];
|
|
13
|
+
private readonly tui: any;
|
|
14
|
+
private readonly searchInput: Input;
|
|
15
|
+
private readonly allOptions: string[];
|
|
9
16
|
private filteredOptions: string[];
|
|
10
17
|
private selectedIndex = 0;
|
|
11
|
-
private title: string;
|
|
12
|
-
private onSelect: (value: string) => void;
|
|
13
|
-
private onCancel: () => void;
|
|
14
|
-
private theme: Theme;
|
|
15
|
-
private keybindings: any;
|
|
18
|
+
private readonly title: string;
|
|
19
|
+
private readonly onSelect: (value: string) => void;
|
|
20
|
+
private readonly onCancel: () => void;
|
|
21
|
+
private readonly theme: Theme;
|
|
22
|
+
private readonly keybindings: any;
|
|
16
23
|
private _focused = false;
|
|
17
24
|
|
|
18
|
-
public get focused(): boolean {
|
|
25
|
+
public get focused(): boolean {
|
|
26
|
+
return this._focused;
|
|
27
|
+
}
|
|
19
28
|
public set focused(val: boolean) {
|
|
20
29
|
this._focused = val;
|
|
21
30
|
this.searchInput.focused = val;
|
|
@@ -41,35 +50,62 @@ export class SearchableModelSelector implements Component, Focusable {
|
|
|
41
50
|
this.filteredOptions = this.allOptions;
|
|
42
51
|
}
|
|
43
52
|
|
|
44
|
-
invalidate(): void {
|
|
53
|
+
invalidate(): void {
|
|
54
|
+
this.searchInput.invalidate();
|
|
55
|
+
}
|
|
45
56
|
|
|
46
57
|
render(width: number): string[] {
|
|
47
58
|
const lines: string[] = ["═".repeat(width)];
|
|
48
59
|
lines.push(` ${this.theme.fg("accent", this.theme.bold(this.title))}`);
|
|
49
60
|
const inputLines = this.searchInput.render(width - 12);
|
|
50
|
-
lines.push(
|
|
61
|
+
lines.push(
|
|
62
|
+
` ${this.theme.fg("accent", "Search: ")}${inputLines[0] || ""}`
|
|
63
|
+
);
|
|
51
64
|
lines.push("");
|
|
52
65
|
|
|
53
66
|
const query = this.searchInput.getValue().trim();
|
|
54
|
-
this.filteredOptions = query
|
|
55
|
-
|
|
67
|
+
this.filteredOptions = query
|
|
68
|
+
? fuzzyFilter(this.allOptions, query, (item) => item)
|
|
69
|
+
: this.allOptions;
|
|
70
|
+
this.selectedIndex = Math.min(
|
|
71
|
+
this.selectedIndex,
|
|
72
|
+
Math.max(0, this.filteredOptions.length - 1)
|
|
73
|
+
);
|
|
56
74
|
|
|
57
75
|
const maxVisible = 10;
|
|
58
76
|
const total = this.filteredOptions.length;
|
|
59
77
|
if (total === 0) {
|
|
60
|
-
lines.push(
|
|
78
|
+
lines.push(` ${this.theme.fg("muted", "No matching models found.")}`);
|
|
61
79
|
} else {
|
|
62
|
-
const startIndex = Math.max(
|
|
80
|
+
const startIndex = Math.max(
|
|
81
|
+
0,
|
|
82
|
+
Math.min(
|
|
83
|
+
this.selectedIndex - Math.floor(maxVisible / 2),
|
|
84
|
+
total - maxVisible
|
|
85
|
+
)
|
|
86
|
+
);
|
|
63
87
|
const endIndex = Math.min(startIndex + maxVisible, total);
|
|
64
88
|
for (let i = startIndex; i < endIndex; i++) {
|
|
65
89
|
const item = this.filteredOptions[i];
|
|
66
|
-
if (i === this.selectedIndex)
|
|
67
|
-
|
|
90
|
+
if (i === this.selectedIndex) {
|
|
91
|
+
lines.push(
|
|
92
|
+
` ${this.theme.fg("accent", "→ ")}${this.theme.fg("accent", item)}`
|
|
93
|
+
);
|
|
94
|
+
} else {
|
|
95
|
+
lines.push(` ${this.theme.fg("text", item)}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (total > maxVisible) {
|
|
99
|
+
lines.push(
|
|
100
|
+
" " +
|
|
101
|
+
this.theme.fg("muted", ` (${this.selectedIndex + 1}/${total})`)
|
|
102
|
+
);
|
|
68
103
|
}
|
|
69
|
-
if (total > maxVisible) lines.push(" " + this.theme.fg("muted", ` (${this.selectedIndex + 1}/${total})`));
|
|
70
104
|
}
|
|
71
105
|
lines.push("");
|
|
72
|
-
lines.push(
|
|
106
|
+
lines.push(
|
|
107
|
+
` ${this.theme.fg("muted", "Type to search · ↑↓: navigate · Enter: select · Esc: cancel")}`
|
|
108
|
+
);
|
|
73
109
|
lines.push("═".repeat(width));
|
|
74
110
|
return lines;
|
|
75
111
|
}
|
|
@@ -77,14 +113,36 @@ export class SearchableModelSelector implements Component, Focusable {
|
|
|
77
113
|
handleInput(keyData: string): void {
|
|
78
114
|
const kb = this.keybindings;
|
|
79
115
|
if (kb.matches(keyData, "tui.select.up") || keyData === "\u001b[A") {
|
|
80
|
-
if (this.filteredOptions.length > 0)
|
|
116
|
+
if (this.filteredOptions.length > 0) {
|
|
117
|
+
this.selectedIndex =
|
|
118
|
+
this.selectedIndex === 0
|
|
119
|
+
? this.filteredOptions.length - 1
|
|
120
|
+
: this.selectedIndex - 1;
|
|
121
|
+
}
|
|
81
122
|
this.tui.requestRender();
|
|
82
|
-
} else if (
|
|
83
|
-
|
|
123
|
+
} else if (
|
|
124
|
+
kb.matches(keyData, "tui.select.down") ||
|
|
125
|
+
keyData === "\u001b[B"
|
|
126
|
+
) {
|
|
127
|
+
if (this.filteredOptions.length > 0) {
|
|
128
|
+
this.selectedIndex =
|
|
129
|
+
this.selectedIndex === this.filteredOptions.length - 1
|
|
130
|
+
? 0
|
|
131
|
+
: this.selectedIndex + 1;
|
|
132
|
+
}
|
|
84
133
|
this.tui.requestRender();
|
|
85
|
-
} else if (
|
|
86
|
-
|
|
87
|
-
|
|
134
|
+
} else if (
|
|
135
|
+
kb.matches(keyData, "tui.select.confirm") ||
|
|
136
|
+
keyData === "\n" ||
|
|
137
|
+
keyData === "\r"
|
|
138
|
+
) {
|
|
139
|
+
if (this.filteredOptions.length > 0) {
|
|
140
|
+
this.onSelect(this.filteredOptions[this.selectedIndex]);
|
|
141
|
+
}
|
|
142
|
+
} else if (
|
|
143
|
+
kb.matches(keyData, "tui.select.cancel") ||
|
|
144
|
+
keyData === "\u001b"
|
|
145
|
+
) {
|
|
88
146
|
this.onCancel();
|
|
89
147
|
} else {
|
|
90
148
|
this.searchInput.handleInput(keyData);
|
|
@@ -94,50 +152,72 @@ export class SearchableModelSelector implements Component, Focusable {
|
|
|
94
152
|
}
|
|
95
153
|
}
|
|
96
154
|
|
|
97
|
-
export
|
|
155
|
+
export interface ContextPreset {
|
|
156
|
+
description: string;
|
|
157
|
+
label: string;
|
|
158
|
+
value: number;
|
|
159
|
+
}
|
|
98
160
|
|
|
99
|
-
export
|
|
161
|
+
export interface AdvisorSettings {
|
|
162
|
+
autoLoopGate?: boolean;
|
|
163
|
+
blockOnBlocked?: boolean;
|
|
164
|
+
collapseResponses: boolean;
|
|
165
|
+
completionGate: boolean;
|
|
100
166
|
contextMaxChars: number;
|
|
167
|
+
customRule?: string;
|
|
101
168
|
effort?: string;
|
|
102
|
-
planGate: boolean;
|
|
103
169
|
failureGate: boolean;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
customRule?: string;
|
|
107
|
-
blockOnBlocked?: boolean;
|
|
108
|
-
autoLoopGate?: boolean;
|
|
170
|
+
failureMode?: "block-session" | "block-tool" | "warn-and-continue";
|
|
171
|
+
herdrIntegration?: boolean;
|
|
109
172
|
loopThreshold?: number;
|
|
110
173
|
maxCallsPerSession?: number;
|
|
174
|
+
planGate: boolean;
|
|
111
175
|
sessionSummary?: boolean;
|
|
112
|
-
|
|
176
|
+
toolResultMaxBytes?: number;
|
|
177
|
+
toolResultMaxLines?: number;
|
|
178
|
+
}
|
|
113
179
|
|
|
114
180
|
export class AdvisorSettingsSelector implements Component, Focusable {
|
|
115
181
|
private selectedRow = 0;
|
|
116
182
|
private contextIndex: number;
|
|
117
183
|
private effortIndex: number;
|
|
118
|
-
private settings: AdvisorSettings;
|
|
119
|
-
private customInput = new Input();
|
|
184
|
+
private readonly settings: AdvisorSettings;
|
|
185
|
+
private readonly customInput = new Input();
|
|
120
186
|
private editingCustom = false;
|
|
121
187
|
private _focused = false;
|
|
122
188
|
|
|
123
|
-
public get focused() {
|
|
189
|
+
public get focused() {
|
|
190
|
+
return this._focused;
|
|
191
|
+
}
|
|
124
192
|
public set focused(value: boolean) {
|
|
125
193
|
this._focused = value;
|
|
126
194
|
this.customInput.focused = value && this.editingCustom;
|
|
127
195
|
}
|
|
128
196
|
|
|
129
|
-
constructor(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
197
|
+
constructor(
|
|
198
|
+
private readonly options: {
|
|
199
|
+
tui: any;
|
|
200
|
+
theme: Theme;
|
|
201
|
+
presets: ContextPreset[];
|
|
202
|
+
effortLevels: string[];
|
|
203
|
+
initial: AdvisorSettings;
|
|
204
|
+
onSave: (settings: AdvisorSettings) => void;
|
|
205
|
+
onCancel: () => void;
|
|
206
|
+
}
|
|
207
|
+
) {
|
|
138
208
|
this.settings = { ...options.initial };
|
|
139
|
-
this.contextIndex = Math.max(
|
|
140
|
-
|
|
209
|
+
this.contextIndex = Math.max(
|
|
210
|
+
0,
|
|
211
|
+
options.presets.findIndex(
|
|
212
|
+
(preset) => preset.value === this.settings.contextMaxChars
|
|
213
|
+
)
|
|
214
|
+
);
|
|
215
|
+
this.effortIndex = Math.max(
|
|
216
|
+
0,
|
|
217
|
+
options.effortLevels.indexOf(
|
|
218
|
+
this.settings.effort || "Default (Model Default)"
|
|
219
|
+
)
|
|
220
|
+
);
|
|
141
221
|
this.customInput.onSubmit = (value) => {
|
|
142
222
|
this.settings.customRule = value.trim() || undefined;
|
|
143
223
|
this.editingCustom = false;
|
|
@@ -151,46 +231,116 @@ export class AdvisorSettingsSelector implements Component, Focusable {
|
|
|
151
231
|
};
|
|
152
232
|
}
|
|
153
233
|
|
|
154
|
-
invalidate(): void {
|
|
234
|
+
invalidate(): void {
|
|
235
|
+
this.options.tui.requestRender();
|
|
236
|
+
}
|
|
155
237
|
|
|
156
|
-
private currentContext() {
|
|
238
|
+
private currentContext() {
|
|
239
|
+
return this.options.presets[this.contextIndex];
|
|
240
|
+
}
|
|
157
241
|
private row(label: string, value: string, index: number) {
|
|
158
242
|
const { theme } = this.options;
|
|
159
243
|
const prefix = index === this.selectedRow ? theme.fg("accent", "›") : " ";
|
|
160
244
|
const text = `${prefix} ${label.padEnd(28)} ${value}`;
|
|
161
|
-
return index === this.selectedRow
|
|
245
|
+
return index === this.selectedRow
|
|
246
|
+
? theme.fg("accent", theme.bold(text))
|
|
247
|
+
: theme.fg("text", text);
|
|
162
248
|
}
|
|
163
249
|
|
|
164
250
|
render(width: number): string[] {
|
|
165
251
|
const { theme, presets } = this.options;
|
|
166
252
|
const trackWidth = Math.max(24, Math.min(60, width - 4));
|
|
167
|
-
const positions = presets.map((_, index) =>
|
|
253
|
+
const positions = presets.map((_, index) =>
|
|
254
|
+
Math.round((index * (trackWidth - 1)) / Math.max(1, presets.length - 1))
|
|
255
|
+
);
|
|
168
256
|
const track = Array.from({ length: trackWidth }, () => "─");
|
|
169
257
|
track[positions[this.contextIndex]] = "▲";
|
|
170
258
|
const labels = Array.from({ length: trackWidth }, () => " ");
|
|
171
259
|
for (let index = 0; index < presets.length; index++) {
|
|
172
260
|
const label = presets[index].label;
|
|
173
|
-
const start = Math.max(
|
|
174
|
-
|
|
261
|
+
const start = Math.max(
|
|
262
|
+
0,
|
|
263
|
+
Math.min(
|
|
264
|
+
trackWidth - label.length,
|
|
265
|
+
positions[index] - Math.floor(label.length / 2)
|
|
266
|
+
)
|
|
267
|
+
);
|
|
268
|
+
for (let char = 0; char < label.length; char++) {
|
|
269
|
+
labels[start + char] = label[char];
|
|
270
|
+
}
|
|
175
271
|
}
|
|
176
272
|
const heading = `Recent history${" ".repeat(Math.max(1, trackWidth - "Recent history".length - "Full branch".length))}Full branch`;
|
|
177
|
-
const onOff = (value: boolean) => value ? "On" : "Off";
|
|
273
|
+
const onOff = (value: boolean) => (value ? "On" : "Off");
|
|
178
274
|
const rows = [
|
|
179
275
|
this.row("Context window", this.currentContext().label, 0),
|
|
180
|
-
this.row(
|
|
276
|
+
this.row(
|
|
277
|
+
"Advisor reasoning",
|
|
278
|
+
this.options.effortLevels[this.effortIndex],
|
|
279
|
+
1
|
|
280
|
+
),
|
|
181
281
|
this.row("Plan gate", onOff(this.settings.planGate), 2),
|
|
182
282
|
this.row("Failure gate", onOff(this.settings.failureGate), 3),
|
|
183
283
|
this.row("Completion gate", onOff(this.settings.completionGate), 4),
|
|
184
|
-
this.row(
|
|
284
|
+
this.row(
|
|
285
|
+
"Collapse long responses",
|
|
286
|
+
onOff(this.settings.collapseResponses),
|
|
287
|
+
5
|
|
288
|
+
),
|
|
185
289
|
this.row("Custom invocation", this.settings.customRule || "None", 6),
|
|
186
|
-
this.row(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
290
|
+
this.row(
|
|
291
|
+
"Block on critical advice",
|
|
292
|
+
onOff(this.settings.blockOnBlocked ?? true),
|
|
293
|
+
7
|
|
294
|
+
),
|
|
295
|
+
this.row(
|
|
296
|
+
"Automatic loop gate",
|
|
297
|
+
onOff(this.settings.autoLoopGate ?? true),
|
|
298
|
+
8
|
|
299
|
+
),
|
|
300
|
+
this.row(
|
|
301
|
+
"Loop threshold",
|
|
302
|
+
`After ${this.settings.loopThreshold ?? 3} repeats`,
|
|
303
|
+
9
|
|
304
|
+
),
|
|
305
|
+
this.row(
|
|
306
|
+
"Max Advisor calls/session",
|
|
307
|
+
this.settings.maxCallsPerSession === undefined
|
|
308
|
+
? "∞"
|
|
309
|
+
: String(this.settings.maxCallsPerSession),
|
|
310
|
+
10
|
|
311
|
+
),
|
|
312
|
+
this.row(
|
|
313
|
+
"Session Advisor Summary",
|
|
314
|
+
onOff(this.settings.sessionSummary ?? true),
|
|
315
|
+
11
|
|
316
|
+
),
|
|
317
|
+
this.row(
|
|
318
|
+
"Gate failure mode",
|
|
319
|
+
this.settings.failureMode ?? "block-session",
|
|
320
|
+
12
|
|
321
|
+
),
|
|
322
|
+
this.row(
|
|
323
|
+
"Herdr integration",
|
|
324
|
+
onOff(this.settings.herdrIntegration ?? true),
|
|
325
|
+
13
|
|
326
|
+
),
|
|
327
|
+
this.row(
|
|
328
|
+
"Tool result lines",
|
|
329
|
+
String(this.settings.toolResultMaxLines ?? 2000),
|
|
330
|
+
14
|
|
331
|
+
),
|
|
332
|
+
this.row(
|
|
333
|
+
"Tool result bytes",
|
|
334
|
+
String(this.settings.toolResultMaxBytes ?? 50 * 1024),
|
|
335
|
+
15
|
|
336
|
+
),
|
|
191
337
|
];
|
|
192
|
-
if (this.editingCustom)
|
|
193
|
-
|
|
338
|
+
if (this.editingCustom) {
|
|
339
|
+
rows.push(
|
|
340
|
+
` ${this.customInput.render(Math.max(10, width - 6))[0] || ""}`
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
rows.push(this.row("Save changes", "", 16));
|
|
194
344
|
return [
|
|
195
345
|
theme.fg("accent", theme.bold(" Advisor settings")),
|
|
196
346
|
"",
|
|
@@ -213,7 +363,7 @@ export class AdvisorSettingsSelector implements Component, Focusable {
|
|
|
213
363
|
if (matchesKey(keyData, Key.up)) {
|
|
214
364
|
this.selectedRow = Math.max(0, this.selectedRow - 1);
|
|
215
365
|
} else if (matchesKey(keyData, Key.down)) {
|
|
216
|
-
this.selectedRow = Math.min(
|
|
366
|
+
this.selectedRow = Math.min(16, this.selectedRow + 1);
|
|
217
367
|
} else if (matchesKey(keyData, Key.left)) {
|
|
218
368
|
this.adjust(-1);
|
|
219
369
|
} else if (matchesKey(keyData, Key.right)) {
|
|
@@ -226,32 +376,118 @@ export class AdvisorSettingsSelector implements Component, Focusable {
|
|
|
226
376
|
tui.requestRender();
|
|
227
377
|
return;
|
|
228
378
|
}
|
|
229
|
-
if (this.selectedRow ===
|
|
379
|
+
if (this.selectedRow === 16) {
|
|
380
|
+
return this.options.onSave({
|
|
381
|
+
...this.settings,
|
|
382
|
+
contextMaxChars: this.currentContext().value,
|
|
383
|
+
effort: this.options.effortLevels[this.effortIndex],
|
|
384
|
+
});
|
|
385
|
+
}
|
|
230
386
|
this.adjust(1);
|
|
231
387
|
} else if (matchesKey(keyData, Key.escape)) {
|
|
232
388
|
return this.options.onCancel();
|
|
233
|
-
} else
|
|
389
|
+
} else {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
234
392
|
tui.requestRender();
|
|
235
393
|
}
|
|
236
394
|
|
|
237
395
|
private adjust(direction: number) {
|
|
238
396
|
switch (this.selectedRow) {
|
|
239
|
-
case 0:
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
397
|
+
case 0:
|
|
398
|
+
this.contextIndex = Math.max(
|
|
399
|
+
0,
|
|
400
|
+
Math.min(
|
|
401
|
+
this.options.presets.length - 1,
|
|
402
|
+
this.contextIndex + direction
|
|
403
|
+
)
|
|
404
|
+
);
|
|
405
|
+
break;
|
|
406
|
+
case 1:
|
|
407
|
+
this.effortIndex = Math.max(
|
|
408
|
+
0,
|
|
409
|
+
Math.min(
|
|
410
|
+
this.options.effortLevels.length - 1,
|
|
411
|
+
this.effortIndex + direction
|
|
412
|
+
)
|
|
413
|
+
);
|
|
414
|
+
break;
|
|
415
|
+
case 2:
|
|
416
|
+
this.settings.planGate = !this.settings.planGate;
|
|
417
|
+
break;
|
|
418
|
+
case 3:
|
|
419
|
+
this.settings.failureGate = !this.settings.failureGate;
|
|
420
|
+
break;
|
|
421
|
+
case 4:
|
|
422
|
+
this.settings.completionGate = !this.settings.completionGate;
|
|
423
|
+
break;
|
|
424
|
+
case 5:
|
|
425
|
+
this.settings.collapseResponses = !this.settings.collapseResponses;
|
|
426
|
+
break;
|
|
427
|
+
case 7:
|
|
428
|
+
this.settings.blockOnBlocked = !(this.settings.blockOnBlocked ?? true);
|
|
429
|
+
break;
|
|
430
|
+
case 8:
|
|
431
|
+
this.settings.autoLoopGate = !(this.settings.autoLoopGate ?? true);
|
|
432
|
+
break;
|
|
433
|
+
case 9:
|
|
434
|
+
this.settings.loopThreshold = Math.max(
|
|
435
|
+
2,
|
|
436
|
+
(this.settings.loopThreshold ?? 3) + direction
|
|
437
|
+
);
|
|
438
|
+
break;
|
|
248
439
|
case 10: {
|
|
249
440
|
const values = [undefined, 0, 1, 2, 3, 5, 10, 25, 50];
|
|
250
|
-
const index = Math.max(
|
|
251
|
-
|
|
441
|
+
const index = Math.max(
|
|
442
|
+
0,
|
|
443
|
+
values.indexOf(this.settings.maxCallsPerSession)
|
|
444
|
+
);
|
|
445
|
+
this.settings.maxCallsPerSession =
|
|
446
|
+
values[Math.max(0, Math.min(values.length - 1, index + direction))];
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
case 11:
|
|
450
|
+
this.settings.sessionSummary = !(this.settings.sessionSummary ?? true);
|
|
451
|
+
break;
|
|
452
|
+
case 12: {
|
|
453
|
+
const modes: AdvisorSettings["failureMode"][] = [
|
|
454
|
+
"block-session",
|
|
455
|
+
"block-tool",
|
|
456
|
+
"warn-and-continue",
|
|
457
|
+
];
|
|
458
|
+
const index = Math.max(
|
|
459
|
+
0,
|
|
460
|
+
modes.indexOf(this.settings.failureMode ?? "block-session")
|
|
461
|
+
);
|
|
462
|
+
this.settings.failureMode =
|
|
463
|
+
modes[Math.max(0, Math.min(modes.length - 1, index + direction))];
|
|
464
|
+
break;
|
|
465
|
+
}
|
|
466
|
+
case 13:
|
|
467
|
+
this.settings.herdrIntegration = !(
|
|
468
|
+
this.settings.herdrIntegration ?? true
|
|
469
|
+
);
|
|
470
|
+
break;
|
|
471
|
+
case 14: {
|
|
472
|
+
const values = [0, 500, 1000, 2000, 5000, 10_000];
|
|
473
|
+
const index = Math.max(
|
|
474
|
+
0,
|
|
475
|
+
values.indexOf(this.settings.toolResultMaxLines ?? 2000)
|
|
476
|
+
);
|
|
477
|
+
this.settings.toolResultMaxLines =
|
|
478
|
+
values[Math.max(0, Math.min(values.length - 1, index + direction))];
|
|
479
|
+
break;
|
|
480
|
+
}
|
|
481
|
+
case 15: {
|
|
482
|
+
const values = [0, 10 * 1024, 50 * 1024, 100 * 1024, 500 * 1024];
|
|
483
|
+
const index = Math.max(
|
|
484
|
+
0,
|
|
485
|
+
values.indexOf(this.settings.toolResultMaxBytes ?? 50 * 1024)
|
|
486
|
+
);
|
|
487
|
+
this.settings.toolResultMaxBytes =
|
|
488
|
+
values[Math.max(0, Math.min(values.length - 1, index + direction))];
|
|
252
489
|
break;
|
|
253
490
|
}
|
|
254
|
-
case 11: this.settings.sessionSummary = !(this.settings.sessionSummary ?? true); break;
|
|
255
491
|
}
|
|
256
492
|
}
|
|
257
493
|
}
|