pi-subagents-lite 1.4.1 → 1.4.3
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 +6 -5
- package/package.json +5 -4
- package/src/agents/agent-discovery.ts +1 -2
- package/src/agents/agent-manager.ts +2 -1
- package/src/agents/agent-runner.ts +2 -9
- package/src/agents/agent-status.ts +2 -2
- package/src/agents/agent-types.ts +22 -20
- package/src/agents/output-file.ts +92 -12
- package/src/agents/tool-execution.ts +11 -13
- package/src/agents/usage.ts +3 -10
- package/src/config/config-io.ts +40 -29
- package/src/config/config-store.ts +17 -19
- package/src/config/types.ts +1 -0
- package/src/events.ts +3 -1
- package/src/models/model-precedence.ts +2 -0
- package/src/spawn/spawn-coordinator.ts +41 -23
- package/src/spawn/worktree-validator.ts +10 -7
- package/src/ui/agent-widget.ts +21 -19
- package/src/ui/format.ts +3 -3
- package/src/ui/menu/helpers.ts +38 -8
- package/src/ui/menu/menu-concurrency.ts +31 -18
- package/src/ui/menu/menu-model-settings.ts +28 -23
- package/src/ui/menu/menu-running-agents.ts +2 -1
- package/src/ui/menu/menu-spawn-options.ts +5 -0
- package/src/ui/menu/menu-spawn-wizard.ts +34 -19
- package/src/ui/menu/menu-system-prompt.ts +6 -2
- package/src/ui/menu/menu-widget-settings.ts +28 -0
- package/src/ui/menu/submenus/confirm.ts +2 -1
- package/src/ui/menu/submenus/model-select.ts +5 -4
- package/src/ui/menu/wrappers/settings-list.ts +73 -105
- package/src/ui/result-viewer.ts +43 -11
- package/src/{models/model-selector.ts → ui/searchable-select.ts} +29 -29
- package/src/utils.ts +2 -0
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
13
|
-
import { SettingsList,
|
|
13
|
+
import { SettingsList, type SettingItem } from "@earendil-works/pi-tui";
|
|
14
14
|
import { getAgentConfig, getAllTypes } from "../../agents/agent-types.js";
|
|
15
|
+
import type { Theme } from "../types.js";
|
|
15
16
|
import { CONFIG_AGENT_NON_MODEL_KEYS } from "../../config/types.js";
|
|
16
|
-
import { buildSettingsListTheme,
|
|
17
|
+
import { buildSettingsListTheme, createSearchableSelect } from "./helpers.js";
|
|
17
18
|
import { createModelSelectSubmenu } from "./submenus/model-select.js";
|
|
18
19
|
import { createConfirmSubmenu } from "./submenus/confirm.js";
|
|
19
20
|
import { SettingsListWrapper } from "./wrappers/settings-list.js";
|
|
@@ -24,7 +25,7 @@ export async function showModelSettingsMenu(
|
|
|
24
25
|
modelOptions: string[],
|
|
25
26
|
): Promise<void> {
|
|
26
27
|
// Build menu items from current store state.
|
|
27
|
-
const buildItems = (store: ReturnType<typeof getStore>, theme:
|
|
28
|
+
const buildItems = (store: ReturnType<typeof getStore>, theme: Theme): SettingItem[] => {
|
|
28
29
|
const items: SettingItem[] = [];
|
|
29
30
|
|
|
30
31
|
// Shared onSelect for model override submenus: applies session/permanent/clear
|
|
@@ -71,6 +72,7 @@ export async function showModelSettingsMenu(
|
|
|
71
72
|
id: "defaultModel",
|
|
72
73
|
label: "Global default model",
|
|
73
74
|
currentValue: globalDisplayValue,
|
|
75
|
+
description: "Model used when no per-type override or frontmatter model applies.",
|
|
74
76
|
submenu: createModelSelectSubmenu({
|
|
75
77
|
modelOptions,
|
|
76
78
|
showClear: false,
|
|
@@ -105,6 +107,7 @@ export async function showModelSettingsMenu(
|
|
|
105
107
|
id: `type:${typeName}`,
|
|
106
108
|
label: typeName,
|
|
107
109
|
currentValue: `${frontmatterHint}${displayModel}`,
|
|
110
|
+
description: `Per-type model override for the ${typeName} agent type.`,
|
|
108
111
|
submenu: createModelSelectSubmenu({
|
|
109
112
|
modelOptions,
|
|
110
113
|
showClear: hasPerm,
|
|
@@ -121,26 +124,26 @@ export async function showModelSettingsMenu(
|
|
|
121
124
|
id: "overrideType",
|
|
122
125
|
label: "Override another type...",
|
|
123
126
|
currentValue: "",
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
127
|
+
description: "Add a model override for an agent type that currently inherits.",
|
|
128
|
+
submenu: (_currentValue, subDone) =>
|
|
129
|
+
createSearchableSelect(
|
|
130
|
+
nonOverridden.map(e => ({ value: e.typeName, label: e.typeName })),
|
|
131
|
+
{
|
|
132
|
+
onSelect: (typeName) => {
|
|
133
|
+
const entry = nonOverridden.find(e => e.typeName === typeName)!;
|
|
134
|
+
// Delegate to createModelSelectSubmenu for the 2-step model flow
|
|
135
|
+
const modelSubmenu = createModelSelectSubmenu({
|
|
136
|
+
modelOptions,
|
|
137
|
+
showClear: false,
|
|
138
|
+
theme,
|
|
139
|
+
onSelect: modelOverrideOnSelect(entry.typeName, entry.typeName),
|
|
140
|
+
});
|
|
141
|
+
return modelSubmenu(entry.effectiveModel, subDone);
|
|
142
|
+
},
|
|
143
|
+
onCancel: () => subDone(),
|
|
144
|
+
},
|
|
145
|
+
theme,
|
|
146
|
+
),
|
|
144
147
|
});
|
|
145
148
|
}
|
|
146
149
|
|
|
@@ -153,6 +156,7 @@ export async function showModelSettingsMenu(
|
|
|
153
156
|
id: "clearSession",
|
|
154
157
|
label: "Clear session overrides",
|
|
155
158
|
currentValue: "",
|
|
159
|
+
description: "Discard model overrides set only for this session.",
|
|
156
160
|
submenu: createConfirmSubmenu({
|
|
157
161
|
message: "Clear all session overrides?",
|
|
158
162
|
theme,
|
|
@@ -169,6 +173,7 @@ export async function showModelSettingsMenu(
|
|
|
169
173
|
id: "clearAll",
|
|
170
174
|
label: "Clear all overrides",
|
|
171
175
|
currentValue: "",
|
|
176
|
+
description: "Discard all model overrides (config and session).",
|
|
172
177
|
submenu: createConfirmSubmenu({
|
|
173
178
|
message: "Clear all model overrides?",
|
|
174
179
|
theme,
|
|
@@ -22,6 +22,7 @@ import { getDisplayName, truncateDesc } from "../format.js";
|
|
|
22
22
|
import { buildSnapshotMarkdown } from "../../prompt/context.js";
|
|
23
23
|
import { buildSelectListTheme, createDelegatingComponent } from "./helpers.js";
|
|
24
24
|
import { getManager, getStore } from "../../shell.js";
|
|
25
|
+
import type { Theme } from "../types.js";
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* Show a ResultViewer for an agent's result, error, or snapshot.
|
|
@@ -73,7 +74,7 @@ async function showResultViewer(
|
|
|
73
74
|
export function buildAgentActionsList(
|
|
74
75
|
ctx: ExtensionCommandContext,
|
|
75
76
|
record: AgentRecord,
|
|
76
|
-
theme:
|
|
77
|
+
theme: Theme,
|
|
77
78
|
done: () => void,
|
|
78
79
|
setActive: (c: import("@earendil-works/pi-tui").Component) => void,
|
|
79
80
|
onClose: () => void,
|
|
@@ -27,6 +27,7 @@ export async function showSpawnOptionsMenu(ctx: ExtensionCommandContext): Promis
|
|
|
27
27
|
label: "Force background",
|
|
28
28
|
currentValue: store.agent.forceBackground ? "ON" : "OFF",
|
|
29
29
|
values: ["ON", "OFF"],
|
|
30
|
+
description: "Spawn every agent in the background by default (no foreground wait).",
|
|
30
31
|
},
|
|
31
32
|
{
|
|
32
33
|
id: "graceTurns",
|
|
@@ -36,6 +37,7 @@ export async function showSpawnOptionsMenu(ctx: ExtensionCommandContext): Promis
|
|
|
36
37
|
store.mutate.agent.setGraceTurns(parsed);
|
|
37
38
|
ctx.ui.notify(`Grace turns set to ${parsed}`, "info");
|
|
38
39
|
}),
|
|
40
|
+
description: "Extra turns after the soft turn limit before a hard abort.",
|
|
39
41
|
},
|
|
40
42
|
{
|
|
41
43
|
id: "defaultMaxTurns",
|
|
@@ -48,18 +50,21 @@ export async function showSpawnOptionsMenu(ctx: ExtensionCommandContext): Promis
|
|
|
48
50
|
store.mutate.agent.setDefaultMaxTurns(undefined);
|
|
49
51
|
ctx.ui.notify("Default max turns cleared", "info");
|
|
50
52
|
}),
|
|
53
|
+
description: "Soft turn limit; agent is steered here, then hard-aborts after grace turns. Blank = unlimited.",
|
|
51
54
|
},
|
|
52
55
|
{
|
|
53
56
|
id: "defaultThinking",
|
|
54
57
|
label: "Default thinking level",
|
|
55
58
|
currentValue: store.agent.defaultThinking ?? "inherit",
|
|
56
59
|
values: ["off", "minimal", "low", "medium", "high", "xhigh", "inherit"],
|
|
60
|
+
description: "Thinking level applied when agent frontmatter omits one.",
|
|
57
61
|
},
|
|
58
62
|
{
|
|
59
63
|
id: "disableDefaultAgents",
|
|
60
64
|
label: "Disable default agents",
|
|
61
65
|
currentValue: store.agent.disableDefaultAgents ? "ON" : "OFF",
|
|
62
66
|
values: ["ON", "OFF"],
|
|
67
|
+
description: "Skip auto-loading built-in agent types next session; only .pi/agents types load.",
|
|
63
68
|
},
|
|
64
69
|
];
|
|
65
70
|
|
|
@@ -11,9 +11,10 @@
|
|
|
11
11
|
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
12
12
|
import { SettingsList, SelectList, type SettingItem } from "@earendil-works/pi-tui";
|
|
13
13
|
import type { ThinkingLevel } from "../../types.js";
|
|
14
|
+
import type { Theme } from "../types.js";
|
|
14
15
|
import { getAgentConfig, getAvailableTypes, resolveType, discoverNewAgents } from "../../agents/agent-types.js";
|
|
15
|
-
import { findModelInRegistry } from "../../utils.js";
|
|
16
|
-
import { buildSettingsListTheme, buildSelectListTheme } from "./helpers.js";
|
|
16
|
+
import { findModelInRegistry, VALID_THINKING_LEVELS } from "../../utils.js";
|
|
17
|
+
import { buildSettingsListTheme, buildSelectListTheme, createSearchableSelect } from "./helpers.js";
|
|
17
18
|
import { DEFAULT_GRACE_TURNS } from "../../config/config-io.js";
|
|
18
19
|
import { createModelSelectSubmenu } from "./submenus/model-select.js";
|
|
19
20
|
import { createNumericSubmenu, createInputSubmenu } from "./submenus/numeric-input.js";
|
|
@@ -120,7 +121,6 @@ async function isInGitRepo(cwd: string): Promise<boolean> {
|
|
|
120
121
|
// Spawn agent wizard
|
|
121
122
|
// ============================================================================
|
|
122
123
|
|
|
123
|
-
const THINKING_LEVELS: ThinkingLevel[] = ["off", "minimal", "low", "medium", "high", "xhigh"];
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
126
|
* Show the spawn agent flow as a multi-step wizard:
|
|
@@ -146,6 +146,7 @@ export async function showSpawnAgentMenu(
|
|
|
146
146
|
id: t,
|
|
147
147
|
label: t,
|
|
148
148
|
currentValue: t,
|
|
149
|
+
description: getAgentConfig(t)?.description ?? "Agent type",
|
|
149
150
|
submenu: (_v: string, _subDone: (value?: string) => void) => {
|
|
150
151
|
done(t);
|
|
151
152
|
return undefined as any;
|
|
@@ -214,6 +215,7 @@ export async function showSpawnAgentMenu(
|
|
|
214
215
|
id: "spawn",
|
|
215
216
|
label: "Spawn",
|
|
216
217
|
currentValue: "",
|
|
218
|
+
description: "Spawn the agent with current settings",
|
|
217
219
|
submenu: (_v, done) => {
|
|
218
220
|
const gtItem = items.find(i => i.id === "graceTurns");
|
|
219
221
|
const bgItem = items.find(i => i.id === "background");
|
|
@@ -304,6 +306,7 @@ export async function showSpawnAgentMenu(
|
|
|
304
306
|
id: "model",
|
|
305
307
|
label: "Model",
|
|
306
308
|
currentValue: displayModel,
|
|
309
|
+
description: "Override the default model for this agent",
|
|
307
310
|
submenu: createModelSelectSubmenu({
|
|
308
311
|
modelOptions,
|
|
309
312
|
showClear: false,
|
|
@@ -317,6 +320,7 @@ export async function showSpawnAgentMenu(
|
|
|
317
320
|
id: "background",
|
|
318
321
|
label: "Background",
|
|
319
322
|
currentValue: currentBackground ? "ON" : "OFF",
|
|
323
|
+
description: "Run the agent in the background",
|
|
320
324
|
values: ["ON", "OFF"],
|
|
321
325
|
},
|
|
322
326
|
...(inGitRepo
|
|
@@ -324,28 +328,33 @@ export async function showSpawnAgentMenu(
|
|
|
324
328
|
id: "worktree",
|
|
325
329
|
label: "Worktree",
|
|
326
330
|
currentValue: currentWorktreeLabel,
|
|
331
|
+
description: "Run in a linked git worktree instead of parent cwd",
|
|
327
332
|
submenu: (_v: string, done: (v?: string) => void) => {
|
|
328
333
|
const pickerItems = [
|
|
329
334
|
{ value: "Inherits parent cwd", label: "Inherits parent cwd" },
|
|
330
335
|
...worktrees.map(wt => {
|
|
331
336
|
const branchLabel = wt.isDetached ? "detached" : (wt.branch ?? "detached");
|
|
332
337
|
const truncPath = truncatePath(wt.path);
|
|
333
|
-
return { value: wt.path, label:
|
|
338
|
+
return { value: wt.path, label: truncPath, provider: branchLabel };
|
|
334
339
|
}),
|
|
335
340
|
];
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
341
|
+
return createSearchableSelect(
|
|
342
|
+
pickerItems,
|
|
343
|
+
{
|
|
344
|
+
onSelect: (value) => {
|
|
345
|
+
if (value === "Inherits parent cwd") {
|
|
346
|
+
currentWorktreePath = undefined;
|
|
347
|
+
done("Inherits parent cwd");
|
|
348
|
+
} else {
|
|
349
|
+
const wt = worktrees.find(w => w.path === value);
|
|
350
|
+
currentWorktreePath = wt?.path;
|
|
351
|
+
done(wt?.branch ?? "detached");
|
|
352
|
+
}
|
|
353
|
+
},
|
|
354
|
+
onCancel: () => done(),
|
|
355
|
+
},
|
|
356
|
+
theme,
|
|
357
|
+
);
|
|
349
358
|
},
|
|
350
359
|
} as SettingItem]
|
|
351
360
|
: []),
|
|
@@ -353,24 +362,28 @@ export async function showSpawnAgentMenu(
|
|
|
353
362
|
id: "thinkingLevel",
|
|
354
363
|
label: "Thinking level",
|
|
355
364
|
currentValue: currentThinking ?? "inherit",
|
|
356
|
-
|
|
365
|
+
description: "Set the reasoning effort level",
|
|
366
|
+
values: [...VALID_THINKING_LEVELS, "inherit"],
|
|
357
367
|
},
|
|
358
368
|
{
|
|
359
369
|
id: "maxTokens",
|
|
360
370
|
label: "Max tokens",
|
|
361
371
|
currentValue: fmtNum(currentMaxTokens),
|
|
372
|
+
description: "Maximum tokens the agent can consume",
|
|
362
373
|
submenu: createNumericSubmenu(ctx, (parsed) => { currentMaxTokens = parsed; }, () => { currentMaxTokens = undefined; }),
|
|
363
374
|
},
|
|
364
375
|
{
|
|
365
376
|
id: "maxTurns",
|
|
366
377
|
label: "Max turns",
|
|
367
378
|
currentValue: fmtNum(currentMaxTurns),
|
|
379
|
+
description: "Maximum conversation turns before hard stop",
|
|
368
380
|
submenu: createNumericSubmenu(ctx, (parsed) => { currentMaxTurns = parsed; }, () => { currentMaxTurns = undefined; }),
|
|
369
381
|
},
|
|
370
382
|
{
|
|
371
383
|
id: "graceTurns",
|
|
372
384
|
label: "Grace turns",
|
|
373
385
|
currentValue: String(currentGraceTurns),
|
|
386
|
+
description: "Extra turns after soft limit before abort",
|
|
374
387
|
submenu: createNumericSubmenu(ctx, { min: 0, default: DEFAULT_GRACE_TURNS }, (parsed) => { currentGraceTurns = parsed; }),
|
|
375
388
|
},
|
|
376
389
|
{ id: "__sep__", label: " ", currentValue: "" },
|
|
@@ -378,12 +391,14 @@ export async function showSpawnAgentMenu(
|
|
|
378
391
|
id: "description",
|
|
379
392
|
label: "Description",
|
|
380
393
|
currentValue: currentDescription,
|
|
394
|
+
description: "Short label shown in the agents list",
|
|
381
395
|
submenu: createInputSubmenu(ctx),
|
|
382
396
|
},
|
|
383
397
|
{
|
|
384
398
|
id: "prompt",
|
|
385
399
|
label: "Prompt",
|
|
386
400
|
currentValue: prompt,
|
|
401
|
+
description: "The user message sent to the agent",
|
|
387
402
|
submenu: createInputSubmenu(ctx, { required: true }),
|
|
388
403
|
}
|
|
389
404
|
];
|
|
@@ -391,7 +406,7 @@ export async function showSpawnAgentMenu(
|
|
|
391
406
|
return items;
|
|
392
407
|
};
|
|
393
408
|
|
|
394
|
-
let theme:
|
|
409
|
+
let theme: Theme;
|
|
395
410
|
let doneRef: () => void;
|
|
396
411
|
|
|
397
412
|
await ctx.ui.custom((_tui, t, _kb, done) => {
|
|
@@ -17,7 +17,7 @@ import { buildSettingsListTheme } from "./helpers.js";
|
|
|
17
17
|
import { SettingsListWrapper } from "./wrappers/settings-list.js";
|
|
18
18
|
import type { SystemPromptMode } from "../../agents/types.js";
|
|
19
19
|
import { getStore } from "../../shell.js";
|
|
20
|
-
import { CUSTOM_PROMPT_PATH } from "../../
|
|
20
|
+
import { CUSTOM_PROMPT_PATH } from "../../config/config-io.js";
|
|
21
21
|
|
|
22
22
|
export async function showSystemPromptMenu(ctx: ExtensionCommandContext): Promise<void> {
|
|
23
23
|
const store = getStore();
|
|
@@ -29,6 +29,7 @@ export async function showSystemPromptMenu(ctx: ExtensionCommandContext): Promis
|
|
|
29
29
|
label: "System prompt mode",
|
|
30
30
|
currentValue: store.agent.systemPromptMode,
|
|
31
31
|
values: ["replace", "inherit", "custom"],
|
|
32
|
+
description: "How the subagent system prompt is built: replace, inherit, or custom.",
|
|
32
33
|
},
|
|
33
34
|
];
|
|
34
35
|
|
|
@@ -39,6 +40,7 @@ export async function showSystemPromptMenu(ctx: ExtensionCommandContext): Promis
|
|
|
39
40
|
label: "Create prompt file",
|
|
40
41
|
currentValue: CUSTOM_PROMPT_PATH,
|
|
41
42
|
values: ["Create"],
|
|
43
|
+
description: `Create ${CUSTOM_PROMPT_PATH} with a starter template for custom mode.`,
|
|
42
44
|
});
|
|
43
45
|
}
|
|
44
46
|
|
|
@@ -48,24 +50,26 @@ export async function showSystemPromptMenu(ctx: ExtensionCommandContext): Promis
|
|
|
48
50
|
label: "Include AGENTS.md",
|
|
49
51
|
currentValue: store.agent.includeContextFiles ? "ON" : "OFF",
|
|
50
52
|
values: ["ON", "OFF"],
|
|
53
|
+
description: "Load project and ~/.pi/agent AGENTS.md as shared <project_context>.",
|
|
51
54
|
},
|
|
52
55
|
{
|
|
53
56
|
id: "loadSkillsImplicitly",
|
|
54
57
|
label: "Load skills implicitly",
|
|
55
58
|
currentValue: store.agent.loadSkillsImplicitly ? "ON" : "OFF",
|
|
56
59
|
values: ["ON", "OFF"],
|
|
60
|
+
description: "Give new agents all skills when frontmatter omits the field.",
|
|
57
61
|
},
|
|
58
62
|
{
|
|
59
63
|
id: "loadExtensionsImplicitly",
|
|
60
64
|
label: "Load extensions implicitly",
|
|
61
65
|
currentValue: store.agent.loadExtensionsImplicitly ? "ON" : "OFF",
|
|
62
66
|
values: ["ON", "OFF"],
|
|
67
|
+
description: "Give new agents all extensions when frontmatter omits the field.",
|
|
63
68
|
},
|
|
64
69
|
);
|
|
65
70
|
|
|
66
71
|
return items;
|
|
67
72
|
};
|
|
68
|
-
|
|
69
73
|
let items = buildItems();
|
|
70
74
|
let rebuild: ((newItems: SettingItem[]) => void) | null = null;
|
|
71
75
|
|
|
@@ -54,15 +54,29 @@ export async function showWidgetSettingsMenu(ctx: ExtensionCommandContext): Prom
|
|
|
54
54
|
store.mutate.widget.setShortcut(newValue === "ON");
|
|
55
55
|
ctx.ui.notify(`Ctrl+o shortcut ${newValue}`, "info");
|
|
56
56
|
break;
|
|
57
|
+
case "thinkingBuffer":
|
|
58
|
+
store.mutate.agent.setOutputThinkingBufferSize(newValue === "OFF" ? 0 : Number(newValue));
|
|
59
|
+
ctx.ui.notify(`Thinking buffer ${newValue}`, "info");
|
|
60
|
+
break;
|
|
57
61
|
}
|
|
58
62
|
};
|
|
59
63
|
|
|
60
64
|
await ctx.ui.custom((_tui, theme, _kb, done) => {
|
|
65
|
+
const statDescriptions: Record<string, string> = {
|
|
66
|
+
showTools: "Show tool count (🛠 ) in the widget.",
|
|
67
|
+
showTurns: "Show turn count (⟳ ) in the widget.",
|
|
68
|
+
showInput: "Show input tokens (↑) in the widget.",
|
|
69
|
+
showOutput: "Show output tokens (↓) in the widget.",
|
|
70
|
+
showContext: "Show context-fill percent (%) in the widget.",
|
|
71
|
+
showCost: "Show dollar cost ($) in the widget.",
|
|
72
|
+
showTime: "Show elapsed time in the widget.",
|
|
73
|
+
};
|
|
61
74
|
const statItems: SettingItem[] = [...statConfig.entries()].map(([id, cfg]) => ({
|
|
62
75
|
id,
|
|
63
76
|
label: cfg.label,
|
|
64
77
|
currentValue: cfg.get() ? "ON" : "OFF",
|
|
65
78
|
values: ["ON", "OFF"],
|
|
79
|
+
description: statDescriptions[id],
|
|
66
80
|
}));
|
|
67
81
|
|
|
68
82
|
const items: SettingItem[] = [
|
|
@@ -71,6 +85,7 @@ export async function showWidgetSettingsMenu(ctx: ExtensionCommandContext): Prom
|
|
|
71
85
|
label: "Force compact mode",
|
|
72
86
|
currentValue: store.agent.widgetCompact ? "ON" : "OFF",
|
|
73
87
|
values: ["ON", "OFF"],
|
|
88
|
+
description: "Force compact widget mode regardless of ctrl+o state.",
|
|
74
89
|
},
|
|
75
90
|
{
|
|
76
91
|
id: "maxLines",
|
|
@@ -80,6 +95,7 @@ export async function showWidgetSettingsMenu(ctx: ExtensionCommandContext): Prom
|
|
|
80
95
|
store.mutate.widget.setMaxLines(parsed);
|
|
81
96
|
ctx.ui.notify(`Max lines (full) set to ${parsed}`, "info");
|
|
82
97
|
}),
|
|
98
|
+
description: "Max body lines in full widget mode (excluding heading).",
|
|
83
99
|
},
|
|
84
100
|
{
|
|
85
101
|
id: "descLengthFull",
|
|
@@ -89,6 +105,7 @@ export async function showWidgetSettingsMenu(ctx: ExtensionCommandContext): Prom
|
|
|
89
105
|
store.mutate.widget.setDescLengthFull(parsed);
|
|
90
106
|
ctx.ui.notify(`Description length (full) set to ${parsed}`, "info");
|
|
91
107
|
}),
|
|
108
|
+
description: "Max description length shown in full widget mode.",
|
|
92
109
|
},
|
|
93
110
|
{
|
|
94
111
|
id: "maxLinesCompact",
|
|
@@ -98,6 +115,7 @@ export async function showWidgetSettingsMenu(ctx: ExtensionCommandContext): Prom
|
|
|
98
115
|
store.mutate.widget.setMaxLinesCompact(parsed);
|
|
99
116
|
ctx.ui.notify(`Max lines (compact) set to ${parsed}`, "info");
|
|
100
117
|
}),
|
|
118
|
+
description: "Max body lines in compact widget mode.",
|
|
101
119
|
},
|
|
102
120
|
{
|
|
103
121
|
id: "descLengthCompact",
|
|
@@ -107,12 +125,21 @@ export async function showWidgetSettingsMenu(ctx: ExtensionCommandContext): Prom
|
|
|
107
125
|
store.mutate.widget.setDescLengthCompact(parsed);
|
|
108
126
|
ctx.ui.notify(`Description length (compact) set to ${parsed}`, "info");
|
|
109
127
|
}),
|
|
128
|
+
description: "Max description length shown in compact widget mode.",
|
|
110
129
|
},
|
|
111
130
|
{
|
|
112
131
|
id: "shortcut",
|
|
113
132
|
label: "Ctrl+o shortcut",
|
|
114
133
|
currentValue: store.agent.widgetShortcut ? "ON" : "OFF",
|
|
115
134
|
values: ["ON", "OFF"],
|
|
135
|
+
description: "When ON, ctrl+o toggles compact mode; when OFF, compact is set manually.",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: "thinkingBuffer",
|
|
139
|
+
label: "Log file thinking buffer",
|
|
140
|
+
currentValue: store.agent.outputThinkingBufferSize === 0 ? "OFF" : String(store.agent.outputThinkingBufferSize),
|
|
141
|
+
values: ["OFF", "80", "200", "500", "1000"],
|
|
142
|
+
description: "Controls log file thinking buffering in chars. OFF = only at turn end, 80 = flush after 80 chars.",
|
|
116
143
|
},
|
|
117
144
|
{ id: "__sep__", label: " ", currentValue: "" },
|
|
118
145
|
{
|
|
@@ -121,6 +148,7 @@ export async function showWidgetSettingsMenu(ctx: ExtensionCommandContext): Prom
|
|
|
121
148
|
currentValue: "→",
|
|
122
149
|
submenu: (_currentValue, done2) =>
|
|
123
150
|
new SettingsList(statItems, 7, buildSettingsListTheme(theme), onChange, () => done2()),
|
|
151
|
+
description: "Toggle which usage stats appear in the widget.",
|
|
124
152
|
},
|
|
125
153
|
];
|
|
126
154
|
|
|
@@ -6,13 +6,14 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { SelectList, type Component } from "@earendil-works/pi-tui";
|
|
9
|
+
import type { Theme } from "../../types.js";
|
|
9
10
|
import { buildSelectListTheme } from "../helpers.js";
|
|
10
11
|
|
|
11
12
|
export interface ConfirmSubmenuOptions {
|
|
12
13
|
/** Message shown to the user */
|
|
13
14
|
message: string;
|
|
14
15
|
/** Theme from pi-coding-agent (fg, bold, italic) */
|
|
15
|
-
theme:
|
|
16
|
+
theme: Theme;
|
|
16
17
|
/** Called when user confirms (selects Yes) */
|
|
17
18
|
onConfirm: () => void;
|
|
18
19
|
}
|
|
@@ -2,19 +2,20 @@
|
|
|
2
2
|
* model-select-submenu.ts — 2-step model override submenu.
|
|
3
3
|
*
|
|
4
4
|
* Step 1: SelectList with override mode (session/permanent/clear)
|
|
5
|
-
* Step 2 (if session/permanent):
|
|
5
|
+
* Step 2 (if session/permanent): SearchableSelectDialog for model selection
|
|
6
6
|
*
|
|
7
7
|
* The submenu factory must be created inside ctx.ui.custom to capture the theme.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { SelectList, type Component } from "@earendil-works/pi-tui";
|
|
11
|
-
import {
|
|
11
|
+
import type { Theme } from "../../types.js";
|
|
12
|
+
import { SearchableSelectDialog, type SelectOption } from "../../../ui/searchable-select.js";
|
|
12
13
|
import { buildModelOptions, buildSelectListTheme, createDelegatingComponent } from "../helpers.js";
|
|
13
14
|
|
|
14
15
|
export interface ModelSelectSubmenuOptions {
|
|
15
16
|
modelOptions: string[];
|
|
16
17
|
showClear: boolean;
|
|
17
|
-
theme:
|
|
18
|
+
theme: Theme;
|
|
18
19
|
onSelect: (mode: "session" | "permanent" | "clear", model: string | null) => void;
|
|
19
20
|
}
|
|
20
21
|
|
|
@@ -52,7 +53,7 @@ export function createModelSelectSubmenu(
|
|
|
52
53
|
modeList.onCancel = () => done();
|
|
53
54
|
|
|
54
55
|
const modelOpts = buildModelOptions(options.modelOptions);
|
|
55
|
-
const modelSelector = new
|
|
56
|
+
const modelSelector = new SearchableSelectDialog(
|
|
56
57
|
modelOpts,
|
|
57
58
|
_currentValue === "(inherits parent)" ? null : _currentValue,
|
|
58
59
|
{
|