pi-ui-extend 0.1.32 → 0.1.34
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 +1 -1
- package/dist/app/app.d.ts +2 -0
- package/dist/app/app.js +28 -0
- package/dist/app/commands/command-session-actions.js +29 -1
- package/dist/app/constants.d.ts +1 -1
- package/dist/app/constants.js +2 -2
- package/dist/app/icons.d.ts +4 -9
- package/dist/app/icons.js +12 -35
- package/dist/app/model/model-usage-status.d.ts +2 -1
- package/dist/app/model/model-usage-status.js +33 -25
- package/dist/app/rendering/conversation-entry-renderer.d.ts +1 -0
- package/dist/app/rendering/conversation-tool-renderer.d.ts +1 -0
- package/dist/app/rendering/conversation-tool-renderer.js +12 -18
- package/dist/app/rendering/conversation-viewport.d.ts +4 -0
- package/dist/app/rendering/conversation-viewport.js +144 -13
- package/dist/app/rendering/dcp-stats.js +42 -16
- package/dist/app/rendering/render-controller.js +4 -0
- package/dist/app/rendering/status-line-renderer.d.ts +8 -1
- package/dist/app/rendering/status-line-renderer.js +36 -1
- package/dist/app/rendering/tab-line-renderer.js +2 -2
- package/dist/app/rendering/tool-block-renderer.d.ts +1 -0
- package/dist/app/rendering/tool-block-renderer.js +37 -11
- package/dist/app/runtime.js +1 -1
- package/dist/app/screen/mouse-controller.d.ts +5 -1
- package/dist/app/screen/mouse-controller.js +16 -0
- package/dist/app/screen/scroll-controller.d.ts +20 -0
- package/dist/app/screen/scroll-controller.js +127 -10
- package/dist/app/session/lazy-session-manager.js +35 -5
- package/dist/app/session/pix-system-message.d.ts +1 -0
- package/dist/app/session/pix-system-message.js +14 -3
- package/dist/app/session/queued-message-controller.d.ts +11 -4
- package/dist/app/session/queued-message-controller.js +74 -59
- package/dist/app/session/queued-message-entries.d.ts +2 -1
- package/dist/app/session/queued-message-entries.js +12 -1
- package/dist/app/session/session-event-controller.d.ts +42 -1
- package/dist/app/session/session-event-controller.js +500 -31
- package/dist/app/session/session-history.js +23 -4
- package/dist/app/session/tabs-controller.d.ts +11 -1
- package/dist/app/session/tabs-controller.js +102 -21
- package/dist/app/types.d.ts +14 -1
- package/dist/bundled-extensions/question/contract.d.ts +25 -0
- package/dist/bundled-extensions/question/contract.js +94 -0
- package/dist/bundled-extensions/question/index.d.ts +7 -0
- package/dist/bundled-extensions/question/index.js +28 -0
- package/dist/bundled-extensions/question/render.d.ts +4 -0
- package/dist/bundled-extensions/question/render.js +27 -0
- package/dist/bundled-extensions/question/result.d.ts +6 -0
- package/dist/bundled-extensions/question/result.js +84 -0
- package/dist/bundled-extensions/question/tool-description.d.ts +7 -0
- package/dist/bundled-extensions/question/tool-description.js +11 -0
- package/dist/bundled-extensions/question/tui.d.ts +2 -0
- package/dist/bundled-extensions/question/tui.js +577 -0
- package/dist/bundled-extensions/question/types.d.ts +103 -0
- package/dist/bundled-extensions/question/types.js +1 -0
- package/dist/bundled-extensions/session-title/config.d.ts +17 -0
- package/dist/bundled-extensions/session-title/config.js +150 -0
- package/dist/bundled-extensions/session-title/index.d.ts +5 -0
- package/dist/bundled-extensions/session-title/index.js +384 -0
- package/dist/bundled-extensions/session-title/title-generation.d.ts +26 -0
- package/dist/bundled-extensions/session-title/title-generation.js +141 -0
- package/dist/bundled-extensions/terminal-bell/index.d.ts +14 -0
- package/dist/bundled-extensions/terminal-bell/index.js +491 -0
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -1
- package/dist/default-pix-config.js +2 -1
- package/dist/icon-theme.d.ts +7 -0
- package/dist/icon-theme.js +36 -0
- package/dist/schemas/pi-tools-suite-schema.d.ts +4 -0
- package/dist/schemas/pi-tools-suite-schema.js +5 -0
- package/dist/schemas/pix-schema.d.ts +1 -0
- package/dist/schemas/pix-schema.js +1 -0
- package/external/pi-tools-suite/README.md +7 -7
- package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +16 -16
- package/external/pi-tools-suite/src/async-subagents/core/state.ts +18 -4
- package/external/pi-tools-suite/src/async-subagents/core/types.ts +4 -0
- package/external/pi-tools-suite/src/async-subagents/tools/result.ts +14 -26
- package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +0 -1
- package/external/pi-tools-suite/src/dcp/config.ts +14 -14
- package/external/pi-tools-suite/src/dcp/index.ts +31 -43
- package/external/pi-tools-suite/src/dcp/state-persistence.ts +151 -0
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +25 -18
- package/external/pi-tools-suite/src/tool-descriptions.ts +34 -54
- package/package.json +3 -2
- package/schemas/pi-tools-suite.json +14 -0
- package/schemas/pix.json +7 -0
- package/extensions/question/contract.ts +0 -100
- package/extensions/question/index.ts +0 -34
- package/extensions/question/render.ts +0 -28
- package/extensions/question/result.ts +0 -86
- package/extensions/question/tool-description.ts +0 -11
- package/extensions/question/tui.ts +0 -629
- package/extensions/question/types.ts +0 -123
- package/extensions/session-title/config.ts +0 -164
- package/extensions/session-title/index.ts +0 -502
- package/extensions/terminal-bell/index.ts +0 -345
|
@@ -73,11 +73,13 @@ export class ConversationViewport {
|
|
|
73
73
|
const dynamic = this.host.isDynamicConversationBlock(entry);
|
|
74
74
|
if (!dynamic && cached?.version === version)
|
|
75
75
|
return cached;
|
|
76
|
+
const availableThinkingLevels = this.host.availableThinkingLevels?.();
|
|
76
77
|
const lines = renderConversationEntryLines(entry, width, {
|
|
77
78
|
cwd: this.host.cwd,
|
|
78
79
|
colors: this.host.colors,
|
|
79
80
|
pixConfig: this.host.pixConfig,
|
|
80
81
|
outputFilters: this.host.outputFilters,
|
|
82
|
+
...(availableThinkingLevels ? { availableThinkingLevels } : {}),
|
|
81
83
|
superCompactTools: Boolean(this.host.superCompactTools),
|
|
82
84
|
allThinkingExpanded: Boolean(this.host.allThinkingExpanded),
|
|
83
85
|
renderInlineUserMessageMenu: (userEntry, context) => this.host.renderInlineUserMessageMenu(userEntry, context),
|
|
@@ -102,6 +104,23 @@ export class ConversationViewport {
|
|
|
102
104
|
block: this.blockForEntry(entry, width),
|
|
103
105
|
}));
|
|
104
106
|
}
|
|
107
|
+
entryBlockPositionById(width, entryId) {
|
|
108
|
+
const layout = this.layoutForWidth(width);
|
|
109
|
+
const targetIndex = layout.positions.get(entryId);
|
|
110
|
+
if (targetIndex === undefined)
|
|
111
|
+
return undefined;
|
|
112
|
+
for (let index = 0; index <= targetIndex; index += 1)
|
|
113
|
+
this.ensureEntryMeasured(layout, width, index);
|
|
114
|
+
const entry = layout.entries[targetIndex];
|
|
115
|
+
if (!entry)
|
|
116
|
+
return undefined;
|
|
117
|
+
return {
|
|
118
|
+
entry,
|
|
119
|
+
offset: layout.offsets[targetIndex] ?? 0,
|
|
120
|
+
lineCount: layout.lineCounts[targetIndex] ?? 0,
|
|
121
|
+
block: this.blockForEntry(entry, width),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
105
124
|
measuredLineCountForEntries(width, entryIds) {
|
|
106
125
|
if (entryIds.length === 0)
|
|
107
126
|
return 0;
|
|
@@ -122,16 +141,21 @@ export class ConversationViewport {
|
|
|
122
141
|
const superCompactTools = Boolean(this.host.superCompactTools);
|
|
123
142
|
const allThinkingExpanded = Boolean(this.host.allThinkingExpanded);
|
|
124
143
|
let layout = this.layoutCachesByWidth.get(width);
|
|
125
|
-
if (!layout
|
|
126
|
-
|
|
127
|
-
? layout
|
|
128
|
-
: undefined;
|
|
129
|
-
layout = this.buildLayout(entries, width, superCompactTools, allThinkingExpanded, previousLayout);
|
|
144
|
+
if (!layout) {
|
|
145
|
+
layout = this.buildLayout(entries, width, superCompactTools, allThinkingExpanded);
|
|
130
146
|
this.layoutCachesByWidth.set(width, layout);
|
|
131
147
|
}
|
|
132
|
-
else {
|
|
133
|
-
this.
|
|
148
|
+
else if (this.layoutStructureChanged(layout, entries, superCompactTools, allThinkingExpanded)) {
|
|
149
|
+
const synced = this.syncLayoutStructure(layout, entries, width, superCompactTools, allThinkingExpanded);
|
|
150
|
+
if (!synced) {
|
|
151
|
+
const previousLayout = layout.superCompactTools === superCompactTools && layout.allThinkingExpanded === allThinkingExpanded
|
|
152
|
+
? layout
|
|
153
|
+
: undefined;
|
|
154
|
+
layout = this.buildLayout(entries, width, superCompactTools, allThinkingExpanded, previousLayout);
|
|
155
|
+
this.layoutCachesByWidth.set(width, layout);
|
|
156
|
+
}
|
|
134
157
|
}
|
|
158
|
+
this.refreshDirtyLayoutEntries(layout, width);
|
|
135
159
|
if (this.host.hasDynamicConversationBlock?.()) {
|
|
136
160
|
this.refreshDynamicLayoutEntries(layout, width);
|
|
137
161
|
}
|
|
@@ -173,12 +197,61 @@ export class ConversationViewport {
|
|
|
173
197
|
return previousLayout.lineCounts[previousIndex];
|
|
174
198
|
}
|
|
175
199
|
layoutStructureChanged(layout, entries, superCompactTools, allThinkingExpanded) {
|
|
176
|
-
if (layout.
|
|
200
|
+
if (layout.entryIds.length !== entries.length || layout.superCompactTools !== superCompactTools || layout.allThinkingExpanded !== allThinkingExpanded)
|
|
177
201
|
return true;
|
|
178
|
-
if (layout.
|
|
202
|
+
if (layout.entryIds.length === 0)
|
|
179
203
|
return false;
|
|
180
204
|
return layout.entryIds[0] !== entries[0]?.id || layout.entryIds[layout.entryIds.length - 1] !== entries[entries.length - 1]?.id;
|
|
181
205
|
}
|
|
206
|
+
syncLayoutStructure(layout, entries, width, superCompactTools, allThinkingExpanded) {
|
|
207
|
+
if (layout.superCompactTools !== superCompactTools || layout.allThinkingExpanded !== allThinkingExpanded)
|
|
208
|
+
return false;
|
|
209
|
+
const currentEntryIds = entries.map((entry) => entry.id);
|
|
210
|
+
const overlap = layoutOverlap(layout.entryIds, currentEntryIds);
|
|
211
|
+
if (!overlap)
|
|
212
|
+
return false;
|
|
213
|
+
const estimatedBlockLineCounts = entries.map((entry) => this.estimatedBlockLineCountForEntry(entry, width));
|
|
214
|
+
const lineCounts = [];
|
|
215
|
+
const measuredLineCounts = [];
|
|
216
|
+
const positions = new Map();
|
|
217
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
218
|
+
const entry = entries[index];
|
|
219
|
+
positions.set(entry.id, index);
|
|
220
|
+
const oldIndex = index >= overlap.currentStart && index < overlap.currentStart + overlap.length
|
|
221
|
+
? overlap.previousStart + index - overlap.currentStart
|
|
222
|
+
: undefined;
|
|
223
|
+
if (oldIndex !== undefined) {
|
|
224
|
+
lineCounts.push(layout.lineCounts[oldIndex] ?? 0);
|
|
225
|
+
measuredLineCounts.push(layout.measuredLineCounts[oldIndex] === true);
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
lineCounts.push(this.estimatedLineCountForEntry(entry, entries, index, estimatedBlockLineCounts));
|
|
229
|
+
measuredLineCounts.push(false);
|
|
230
|
+
}
|
|
231
|
+
layout.entries = entries;
|
|
232
|
+
layout.entryIds = currentEntryIds;
|
|
233
|
+
layout.lineCounts = lineCounts;
|
|
234
|
+
layout.measuredLineCounts = measuredLineCounts;
|
|
235
|
+
layout.positions = positions;
|
|
236
|
+
this.rebuildOffsets(layout);
|
|
237
|
+
const changedNextIndexes = new Set([overlap.currentStart - 1, overlap.currentStart + overlap.length - 1]);
|
|
238
|
+
for (const index of changedNextIndexes) {
|
|
239
|
+
if (index >= 0 && index < entries.length)
|
|
240
|
+
this.refreshLayoutEntry(layout, width, index, layout.measuredLineCounts[index] === true);
|
|
241
|
+
}
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
rebuildOffsets(layout) {
|
|
245
|
+
const offsets = [];
|
|
246
|
+
let totalLineCount = 0;
|
|
247
|
+
for (const lineCount of layout.lineCounts) {
|
|
248
|
+
offsets.push(totalLineCount);
|
|
249
|
+
totalLineCount += lineCount;
|
|
250
|
+
}
|
|
251
|
+
offsets.push(totalLineCount);
|
|
252
|
+
layout.offsets = offsets;
|
|
253
|
+
layout.totalLineCount = totalLineCount;
|
|
254
|
+
}
|
|
182
255
|
refreshDirtyLayoutEntries(layout, width) {
|
|
183
256
|
if (layout.dirtyEntryIds.size === 0)
|
|
184
257
|
return;
|
|
@@ -224,7 +297,7 @@ export class ConversationViewport {
|
|
|
224
297
|
const previousLineCount = layout.lineCounts[index] ?? 0;
|
|
225
298
|
const nextLineCount = measure
|
|
226
299
|
? this.measuredLineCountForEntry(entry, layout.entries, index, width)
|
|
227
|
-
: this.estimatedLineCountForEntry(entry, layout.entries, index, width);
|
|
300
|
+
: this.estimatedLineCountForEntry(entry, layout.entries, index, layout.entries.map((candidate) => this.estimatedBlockLineCountForEntry(candidate, width)));
|
|
228
301
|
layout.measuredLineCounts[index] = measure;
|
|
229
302
|
if (previousLineCount === nextLineCount)
|
|
230
303
|
return false;
|
|
@@ -240,9 +313,8 @@ export class ConversationViewport {
|
|
|
240
313
|
const block = this.blockForEntry(entry, width);
|
|
241
314
|
return this.lineCountWithGap(entry, block.lineCount, this.nextVisibleEntry(entries, index, width));
|
|
242
315
|
}
|
|
243
|
-
estimatedLineCountForEntry(entry, entries, index,
|
|
244
|
-
const blockLineCount =
|
|
245
|
-
const blockLineCounts = entries.map((candidate) => this.estimatedBlockLineCountForEntry(candidate, width));
|
|
316
|
+
estimatedLineCountForEntry(entry, entries, index, blockLineCounts) {
|
|
317
|
+
const blockLineCount = blockLineCounts[index] ?? 0;
|
|
246
318
|
return this.lineCountWithGap(entry, blockLineCount, this.nextEstimatedVisibleEntry(entries, blockLineCounts, index));
|
|
247
319
|
}
|
|
248
320
|
lineCountWithGap(entry, blockLineCount, nextEntry) {
|
|
@@ -339,6 +411,65 @@ function estimateWrappedLineCount(text, width) {
|
|
|
339
411
|
}
|
|
340
412
|
return count;
|
|
341
413
|
}
|
|
414
|
+
function layoutOverlap(previousIds, currentIds) {
|
|
415
|
+
if (currentIds.length === 0 || previousIds.length === 0)
|
|
416
|
+
return { previousStart: 0, currentStart: 0, length: 0 };
|
|
417
|
+
const candidates = [];
|
|
418
|
+
const prefixLength = commonPrefixLength(previousIds, currentIds);
|
|
419
|
+
if (prefixLength > 0)
|
|
420
|
+
candidates.push({ previousStart: 0, currentStart: 0, length: prefixLength });
|
|
421
|
+
const suffixLength = commonSuffixLength(previousIds, currentIds);
|
|
422
|
+
if (suffixLength > 0)
|
|
423
|
+
candidates.push({
|
|
424
|
+
previousStart: previousIds.length - suffixLength,
|
|
425
|
+
currentStart: currentIds.length - suffixLength,
|
|
426
|
+
length: suffixLength,
|
|
427
|
+
});
|
|
428
|
+
const suffixPrefixLength = maxSuffixPrefixOverlap(previousIds, currentIds);
|
|
429
|
+
if (suffixPrefixLength > 0)
|
|
430
|
+
candidates.push({
|
|
431
|
+
previousStart: previousIds.length - suffixPrefixLength,
|
|
432
|
+
currentStart: 0,
|
|
433
|
+
length: suffixPrefixLength,
|
|
434
|
+
});
|
|
435
|
+
const prefixSuffixLength = maxSuffixPrefixOverlap(currentIds, previousIds);
|
|
436
|
+
if (prefixSuffixLength > 0)
|
|
437
|
+
candidates.push({
|
|
438
|
+
previousStart: 0,
|
|
439
|
+
currentStart: currentIds.length - prefixSuffixLength,
|
|
440
|
+
length: prefixSuffixLength,
|
|
441
|
+
});
|
|
442
|
+
return candidates.sort((left, right) => right.length - left.length)[0];
|
|
443
|
+
}
|
|
444
|
+
function commonPrefixLength(left, right) {
|
|
445
|
+
const maxLength = Math.min(left.length, right.length);
|
|
446
|
+
let length = 0;
|
|
447
|
+
while (length < maxLength && left[length] === right[length])
|
|
448
|
+
length += 1;
|
|
449
|
+
return length;
|
|
450
|
+
}
|
|
451
|
+
function commonSuffixLength(left, right) {
|
|
452
|
+
const maxLength = Math.min(left.length, right.length);
|
|
453
|
+
let length = 0;
|
|
454
|
+
while (length < maxLength && left[left.length - length - 1] === right[right.length - length - 1])
|
|
455
|
+
length += 1;
|
|
456
|
+
return length;
|
|
457
|
+
}
|
|
458
|
+
function maxSuffixPrefixOverlap(left, right) {
|
|
459
|
+
const maxLength = Math.min(left.length, right.length);
|
|
460
|
+
for (let length = maxLength; length > 0; length -= 1) {
|
|
461
|
+
let matches = true;
|
|
462
|
+
for (let offset = 0; offset < length; offset += 1) {
|
|
463
|
+
if (left[left.length - length + offset] !== right[offset]) {
|
|
464
|
+
matches = false;
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if (matches)
|
|
469
|
+
return length;
|
|
470
|
+
}
|
|
471
|
+
return 0;
|
|
472
|
+
}
|
|
342
473
|
function estimateToolLikeLineCount(toolName, expanded, output, width, pixConfig, superCompactTools, includeStatusLine) {
|
|
343
474
|
const rule = resolveToolRule(toolName, pixConfig.toolRenderer);
|
|
344
475
|
if (rule.hidden)
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
1
3
|
import { normalizeToolName, parseArgsText } from "../../tool-renderers/utils.js";
|
|
2
4
|
const NUDGE_TYPES = ["turn", "iteration", "context-soft", "context-strong"];
|
|
3
5
|
export function formatDcpStatsToast(session) {
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
+
const latestState = resolveLatestDcpState(session);
|
|
7
|
+
const stats = collectDcpSessionStats(session, latestState);
|
|
8
|
+
const nudgeStats = collectDcpNudgeStats(session, latestState?.data);
|
|
6
9
|
const activeBlocks = stats.activeBlocks ?? 0;
|
|
7
10
|
const totalBlocks = stats.totalBlocks ?? stats.activeBlocks ?? 0;
|
|
8
11
|
const totalNudgeEvents = nudgeStats.emitted + nudgeStats.upgraded;
|
|
@@ -12,7 +15,8 @@ export function formatDcpStatsToast(session) {
|
|
|
12
15
|
` Tokens saved (estimated): ${fmt(stats.tokensSaved)}`,
|
|
13
16
|
` Total pruning operations: ${fmt(stats.totalPruneCount)}`,
|
|
14
17
|
` Compression blocks active: ${activeBlocks} / ${totalBlocks} total`,
|
|
15
|
-
|
|
18
|
+
` Manual mode: ${stats.manualMode === true ? "on" : stats.manualMode === false ? "off" : "unknown"}`,
|
|
19
|
+
` State source: ${formatStateSource(stats.stateSource)}`,
|
|
16
20
|
"",
|
|
17
21
|
"Nudge telemetry:",
|
|
18
22
|
` Sent: ${fmt(nudgeStats.emitted)} emitted, ${fmt(nudgeStats.upgraded)} upgraded`,
|
|
@@ -28,7 +32,7 @@ export function formatDcpStatsToast(session) {
|
|
|
28
32
|
];
|
|
29
33
|
return lines.join("\n");
|
|
30
34
|
}
|
|
31
|
-
function collectDcpSessionStats(session) {
|
|
35
|
+
function collectDcpSessionStats(session, latestState) {
|
|
32
36
|
const usage = session.getContextUsage();
|
|
33
37
|
const stats = {
|
|
34
38
|
runs: 0,
|
|
@@ -37,14 +41,14 @@ function collectDcpSessionStats(session) {
|
|
|
37
41
|
items: 0,
|
|
38
42
|
summaryTokens: 0,
|
|
39
43
|
prunedTools: 0,
|
|
44
|
+
stateSource: latestState?.source ?? "tool-results",
|
|
40
45
|
...(usage?.tokens != null ? { contextTokens: usage.tokens } : {}),
|
|
41
46
|
...(usage?.contextWindow != null ? { contextWindow: usage.contextWindow } : {}),
|
|
42
47
|
...(usage?.percent != null ? { contextPercent: usage.percent } : {}),
|
|
43
48
|
};
|
|
44
49
|
const branch = session.sessionManager.getBranch();
|
|
45
|
-
const latestState = latestCustomEntryData(branch, "dcp-state");
|
|
46
50
|
if (latestState)
|
|
47
|
-
applyDcpStateStats(stats, latestState);
|
|
51
|
+
applyDcpStateStats(stats, latestState.data);
|
|
48
52
|
for (const entry of branch) {
|
|
49
53
|
if (entry.type !== "message")
|
|
50
54
|
continue;
|
|
@@ -94,8 +98,10 @@ function applyDcpStateStats(stats, data) {
|
|
|
94
98
|
}
|
|
95
99
|
if (Array.isArray(data.prunedToolIds))
|
|
96
100
|
stats.prunedTools = data.prunedToolIds.length;
|
|
101
|
+
if (typeof data.manualMode === "boolean")
|
|
102
|
+
stats.manualMode = data.manualMode;
|
|
97
103
|
}
|
|
98
|
-
function collectDcpNudgeStats(session) {
|
|
104
|
+
function collectDcpNudgeStats(session, latestState) {
|
|
99
105
|
const stats = {
|
|
100
106
|
emitted: 0,
|
|
101
107
|
upgraded: 0,
|
|
@@ -105,7 +111,6 @@ function collectDcpNudgeStats(session) {
|
|
|
105
111
|
activeByType: { "turn": 0, "iteration": 0, "context-soft": 0, "context-strong": 0 },
|
|
106
112
|
};
|
|
107
113
|
const branch = session.sessionManager.getBranch();
|
|
108
|
-
const latestState = latestCustomEntryData(branch, "dcp-state");
|
|
109
114
|
if (latestState)
|
|
110
115
|
applyActiveAnchorStats(stats, latestState);
|
|
111
116
|
for (const entry of branch) {
|
|
@@ -156,19 +161,40 @@ function applyActiveAnchorStats(stats, data) {
|
|
|
156
161
|
};
|
|
157
162
|
}
|
|
158
163
|
}
|
|
164
|
+
function resolveLatestDcpState(session) {
|
|
165
|
+
const sidecar = loadSidecarDcpState(session);
|
|
166
|
+
if (sidecar)
|
|
167
|
+
return { data: sidecar, source: "sidecar" };
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
function loadSidecarDcpState(session) {
|
|
171
|
+
const sessionManager = session.sessionManager;
|
|
172
|
+
const sessionDir = sessionManager.getSessionDir?.();
|
|
173
|
+
const sessionId = sessionManager.getSessionId?.();
|
|
174
|
+
if (!sessionDir || !sessionId)
|
|
175
|
+
return undefined;
|
|
176
|
+
try {
|
|
177
|
+
const statePath = join(sessionDir, "dcp-state", safeSessionFileName(sessionId));
|
|
178
|
+
const parsed = JSON.parse(readFileSync(statePath, "utf8"));
|
|
179
|
+
return isRecord(parsed) ? parsed : undefined;
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function safeSessionFileName(sessionId) {
|
|
186
|
+
return `${sessionId.replace(/[^a-zA-Z0-9._-]/g, "_")}.json`;
|
|
187
|
+
}
|
|
188
|
+
function formatStateSource(source) {
|
|
189
|
+
if (source === "sidecar")
|
|
190
|
+
return "dcp-state sidecar";
|
|
191
|
+
return "compress tool results";
|
|
192
|
+
}
|
|
159
193
|
function customEntryData(entry, customType) {
|
|
160
194
|
if (!isRecord(entry) || entry.type !== "custom" || entry.customType !== customType)
|
|
161
195
|
return undefined;
|
|
162
196
|
return isRecord(entry.data) ? entry.data : undefined;
|
|
163
197
|
}
|
|
164
|
-
function latestCustomEntryData(entries, customType) {
|
|
165
|
-
for (let i = entries.length - 1; i >= 0; i--) {
|
|
166
|
-
const data = customEntryData(entries[i], customType);
|
|
167
|
-
if (data)
|
|
168
|
-
return data;
|
|
169
|
-
}
|
|
170
|
-
return undefined;
|
|
171
|
-
}
|
|
172
198
|
function parseToolResultText(content) {
|
|
173
199
|
const parsed = parseArgsText(textContent(content));
|
|
174
200
|
return isRecord(parsed) ? parsed : undefined;
|
|
@@ -67,6 +67,8 @@ export class AppRenderController {
|
|
|
67
67
|
this.deps.mouseController.statusUserJumpTarget = undefined;
|
|
68
68
|
this.deps.mouseController.statusThinkingExpandTarget = undefined;
|
|
69
69
|
this.deps.mouseController.statusCompactToolsTarget = undefined;
|
|
70
|
+
this.deps.mouseController.statusQuickScrollUpTarget = undefined;
|
|
71
|
+
this.deps.mouseController.statusQuickScrollDownTarget = undefined;
|
|
70
72
|
this.deps.mouseController.statusTerminalBellSoundTarget = undefined;
|
|
71
73
|
this.deps.mouseController.statusSessionTarget = undefined;
|
|
72
74
|
this.deps.mouseController.statusPromptEnhancerTarget = undefined;
|
|
@@ -289,6 +291,8 @@ export class AppRenderController {
|
|
|
289
291
|
this.deps.mouseController.statusUserJumpTarget = this.deps.statusLineRenderer.userJumpTarget?.(widgetLayout, widgetRow);
|
|
290
292
|
this.deps.mouseController.statusThinkingExpandTarget = this.deps.statusLineRenderer.thinkingExpandTarget?.(widgetLayout, widgetRow);
|
|
291
293
|
this.deps.mouseController.statusCompactToolsTarget = this.deps.statusLineRenderer.compactToolsTarget?.(widgetLayout, widgetRow);
|
|
294
|
+
this.deps.mouseController.statusQuickScrollUpTarget = this.deps.statusLineRenderer.quickScrollUpTarget?.(widgetLayout, widgetRow);
|
|
295
|
+
this.deps.mouseController.statusQuickScrollDownTarget = this.deps.statusLineRenderer.quickScrollDownTarget?.(widgetLayout, widgetRow);
|
|
292
296
|
this.deps.mouseController.statusTerminalBellSoundTarget = this.deps.statusLineRenderer.terminalBellSoundTarget?.(widgetLayout, widgetRow);
|
|
293
297
|
}
|
|
294
298
|
this.deps.mouseController.statusSessionTarget = this.deps.statusLineRenderer.sessionTarget(statusLayout.text, statusRow, statusLayout.sessionLabel, statusLayout.workspaceLabel);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentSession } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { Theme } from "../../theme.js";
|
|
3
|
-
import type { SessionActivity, StatusCompactToolsTarget, StatusContextTarget, StatusDraftQueueTarget, StatusLineLayout, StatusModelTarget, StatusModelUsageTarget, StatusPromptEnhancerTarget, StatusSessionTarget, StatusTerminalBellSoundTarget, StatusThinkingExpandTarget, StatusThinkingTarget, StatusUserJumpTarget, StatusVoiceLanguageTarget, StatusVoiceMicTarget } from "../types.js";
|
|
3
|
+
import type { SessionActivity, StatusCompactToolsTarget, StatusContextTarget, StatusDraftQueueTarget, StatusLineLayout, StatusModelTarget, StatusModelUsageTarget, StatusPromptEnhancerTarget, StatusQuickScrollTarget, StatusSessionTarget, StatusTerminalBellSoundTarget, StatusThinkingExpandTarget, StatusThinkingTarget, StatusUserJumpTarget, StatusVoiceLanguageTarget, StatusVoiceMicTarget } from "../types.js";
|
|
4
4
|
import type { ScreenStyler } from "../screen/screen-styler.js";
|
|
5
5
|
import { type ModelColorsConfig } from "../../config.js";
|
|
6
6
|
export type StatusLineRendererHost = {
|
|
@@ -26,6 +26,10 @@ export type StatusLineRendererHost = {
|
|
|
26
26
|
terminalBellSoundStatusWidgetEnabled(): boolean;
|
|
27
27
|
voiceStatusWidgetText(): string;
|
|
28
28
|
voiceStatusWidgetActive(): boolean;
|
|
29
|
+
conversationQuickScrollDirections?(): {
|
|
30
|
+
up: boolean;
|
|
31
|
+
down: boolean;
|
|
32
|
+
};
|
|
29
33
|
queueableInputActive?(): boolean;
|
|
30
34
|
userMessageJumpMenuActive?(): boolean;
|
|
31
35
|
allThinkingExpandedActive?(): boolean;
|
|
@@ -50,6 +54,8 @@ export declare class StatusLineRenderer {
|
|
|
50
54
|
draftQueueTarget(layout: StatusLineLayout, row: number): StatusDraftQueueTarget | undefined;
|
|
51
55
|
thinkingExpandTarget(layout: StatusLineLayout, row: number): StatusThinkingExpandTarget | undefined;
|
|
52
56
|
compactToolsTarget(layout: StatusLineLayout, row: number): StatusCompactToolsTarget | undefined;
|
|
57
|
+
quickScrollUpTarget(layout: StatusLineLayout, row: number): StatusQuickScrollTarget | undefined;
|
|
58
|
+
quickScrollDownTarget(layout: StatusLineLayout, row: number): StatusQuickScrollTarget | undefined;
|
|
53
59
|
terminalBellSoundTarget(layout: StatusLineLayout, row: number): StatusTerminalBellSoundTarget | undefined;
|
|
54
60
|
sessionTarget(statusText: string, row: number, label: string, workspaceLabel: string): StatusSessionTarget | undefined;
|
|
55
61
|
private segments;
|
|
@@ -65,6 +71,7 @@ export declare class StatusLineRenderer {
|
|
|
65
71
|
private pushVoiceWidgetSegment;
|
|
66
72
|
private pushWorkspaceSegments;
|
|
67
73
|
private pushModelUsageSegments;
|
|
74
|
+
private modelUsageHasWarning;
|
|
68
75
|
private modelUsageResetLength;
|
|
69
76
|
private pushSegment;
|
|
70
77
|
private pushContextBarSegments;
|
|
@@ -58,6 +58,7 @@ export class StatusLineRenderer {
|
|
|
58
58
|
widgets.push({ text, assign });
|
|
59
59
|
hasParts = true;
|
|
60
60
|
};
|
|
61
|
+
const quickScrollDirections = this.host.conversationQuickScrollDirections?.() ?? { up: false, down: false };
|
|
61
62
|
const draftQueueButton = this.draftQueueWidgetText();
|
|
62
63
|
appendWidget(draftQueueButton ? this.iconButtonText(draftQueueButton) : "", (column, text) => {
|
|
63
64
|
layout.draftQueueWidget = this.widgetLayout(column, text);
|
|
@@ -79,6 +80,12 @@ export class StatusLineRenderer {
|
|
|
79
80
|
appendWidget(this.iconButtonText(APP_ICONS.compactTools), (column, text) => {
|
|
80
81
|
layout.compactToolsWidget = this.widgetLayout(column, text);
|
|
81
82
|
});
|
|
83
|
+
appendWidget(quickScrollDirections.up ? this.iconButtonText(APP_ICONS.up) : "", (column, text) => {
|
|
84
|
+
layout.quickScrollUpWidget = this.widgetLayout(column, text);
|
|
85
|
+
});
|
|
86
|
+
appendWidget(quickScrollDirections.down ? this.iconButtonText(APP_ICONS.down) : "", (column, text) => {
|
|
87
|
+
layout.quickScrollDownWidget = this.widgetLayout(column, text);
|
|
88
|
+
});
|
|
82
89
|
const voiceWidgetText = this.host.voiceStatusWidgetText();
|
|
83
90
|
appendWidget(this.voiceBorderWidgetText(voiceWidgetText), (column, text) => {
|
|
84
91
|
layout.voiceWidget = this.voiceWidgetLayout(column, voiceWidgetText, text);
|
|
@@ -137,6 +144,8 @@ export class StatusLineRenderer {
|
|
|
137
144
|
: this.host.promptEnhancerStatusWidgetEnabled()
|
|
138
145
|
? colors.info
|
|
139
146
|
: colors.muted);
|
|
147
|
+
pushWidgetSegment(layout.quickScrollUpWidget, colors.info);
|
|
148
|
+
pushWidgetSegment(layout.quickScrollDownWidget, colors.info);
|
|
140
149
|
pushWidgetSegment(layout.userJumpWidget, this.host.userMessageJumpMenuActive?.() ? colors.info : colors.muted);
|
|
141
150
|
pushWidgetSegment(layout.terminalBellSoundWidget, this.host.terminalBellSoundStatusWidgetEnabled() ? colors.info : colors.muted);
|
|
142
151
|
pushWidgetSegment(layout.thinkingExpandWidget, this.host.allThinkingExpandedActive?.() ? colors.info : colors.muted);
|
|
@@ -252,6 +261,18 @@ export class StatusLineRenderer {
|
|
|
252
261
|
return undefined;
|
|
253
262
|
return { row, startColumn: widget.startColumn, endColumn: widget.endColumn };
|
|
254
263
|
}
|
|
264
|
+
quickScrollUpTarget(layout, row) {
|
|
265
|
+
const widget = layout.quickScrollUpWidget;
|
|
266
|
+
if (!widget)
|
|
267
|
+
return undefined;
|
|
268
|
+
return { row, startColumn: widget.startColumn, endColumn: widget.endColumn, direction: "up" };
|
|
269
|
+
}
|
|
270
|
+
quickScrollDownTarget(layout, row) {
|
|
271
|
+
const widget = layout.quickScrollDownWidget;
|
|
272
|
+
if (!widget)
|
|
273
|
+
return undefined;
|
|
274
|
+
return { row, startColumn: widget.startColumn, endColumn: widget.endColumn, direction: "down" };
|
|
275
|
+
}
|
|
255
276
|
terminalBellSoundTarget(layout, row) {
|
|
256
277
|
const widget = layout.terminalBellSoundWidget;
|
|
257
278
|
if (!widget)
|
|
@@ -470,11 +491,25 @@ export class StatusLineRenderer {
|
|
|
470
491
|
fill: color,
|
|
471
492
|
track: this.host.theme.colors.statusDotBase,
|
|
472
493
|
}, MODEL_USAGE_PROGRESS_BAR_WIDTH));
|
|
473
|
-
const
|
|
494
|
+
const defaultResetStart = barStart + MODEL_USAGE_PROGRESS_BAR_WIDTH + 1;
|
|
495
|
+
const warningStart = this.modelUsageHasWarning(modelUsageLabel, defaultResetStart - labelStart)
|
|
496
|
+
? defaultResetStart
|
|
497
|
+
: undefined;
|
|
498
|
+
const resetStart = warningStart === undefined
|
|
499
|
+
? defaultResetStart
|
|
500
|
+
: warningStart + APP_ICONS.alert.length + 1;
|
|
501
|
+
if (warningStart !== undefined) {
|
|
502
|
+
this.pushSegment(segments, warningStart, APP_ICONS.alert.length, this.host.theme.colors.warning);
|
|
503
|
+
}
|
|
474
504
|
const resetLength = this.modelUsageResetLength(modelUsageLabel, resetStart - labelStart);
|
|
475
505
|
this.pushSegment(segments, resetStart, resetLength, this.host.theme.colors.muted);
|
|
476
506
|
}
|
|
477
507
|
}
|
|
508
|
+
modelUsageHasWarning(modelUsageLabel, localStart) {
|
|
509
|
+
if (localStart < 0 || localStart >= modelUsageLabel.length)
|
|
510
|
+
return false;
|
|
511
|
+
return modelUsageLabel.startsWith(APP_ICONS.alert, localStart);
|
|
512
|
+
}
|
|
478
513
|
modelUsageResetLength(modelUsageLabel, localStart) {
|
|
479
514
|
if (localStart < 0 || localStart >= modelUsageLabel.length)
|
|
480
515
|
return 0;
|
|
@@ -197,9 +197,9 @@ export class TabLineRenderer {
|
|
|
197
197
|
return { foreground: this.host.theme.colors.error, bold: true };
|
|
198
198
|
}
|
|
199
199
|
if (tab.activity === "running" || tab.activity === "thinking") {
|
|
200
|
-
return { foreground: this.host.theme.colors.
|
|
200
|
+
return { foreground: this.host.theme.colors.warning, bold: true };
|
|
201
201
|
}
|
|
202
|
-
return { foreground: this.host.theme.colors.
|
|
202
|
+
return { foreground: this.host.theme.colors.success };
|
|
203
203
|
}
|
|
204
204
|
statusIndicatorIcon(tab) {
|
|
205
205
|
if (tab.status !== "active" && tab.attention === "terminal-bell" && tab.attentionVisible !== false) {
|
|
@@ -26,5 +26,6 @@ export type ToolBlockRenderOptions = {
|
|
|
26
26
|
backgroundOverride?: string;
|
|
27
27
|
skipHeaderBackground?: boolean;
|
|
28
28
|
showGutter?: boolean;
|
|
29
|
+
headerColorOverride?: string;
|
|
29
30
|
};
|
|
30
31
|
export declare function renderToolBlock(entry: ToolBlockEntry, rule: ResolvedToolRule, width: number, colors: Theme["colors"], options?: ToolBlockRenderOptions): RenderedLine[];
|
|
@@ -18,7 +18,7 @@ export function renderToolBlock(entry, rule, width, colors, options = {}) {
|
|
|
18
18
|
const hasLspDiagnostics = hasToolLspDiagnosticsAfterMutation(entry);
|
|
19
19
|
const expanded = entry.expanded;
|
|
20
20
|
const stateIcon = toolStatusIcon(entry);
|
|
21
|
-
const toolColor = resolveColor(rule.color, colors);
|
|
21
|
+
const toolColor = options.headerColorOverride ?? resolveColor(rule.color, colors);
|
|
22
22
|
const toolOutputColor = colors.statusForeground;
|
|
23
23
|
const headerLabel = (entry.headerLabel ?? entry.toolName).toLowerCase();
|
|
24
24
|
const bg = options.backgroundOverride;
|
|
@@ -87,18 +87,42 @@ export function renderToolBlock(entry, rule, width, colors, options = {}) {
|
|
|
87
87
|
return headerLines;
|
|
88
88
|
}
|
|
89
89
|
function renderCollapsedPreviewLines(entry, body, rule, width, target, color, colors, hasLspDiagnostics, showGutter) {
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
const preview = previewBodyText(body, rule.direction, rule.previewLines);
|
|
91
|
+
const allPreviewLines = renderToolBodyLines(preview.text, width, target, color, entry.bodyStyle, colors, undefined, entry.bodyWrap, hasLspDiagnostics, entry.bodyLineStyles, entry.preserveAnsi, showGutter, { rawLineOffset: preview.rawLineOffset, bodyEndsAfterText: !preview.omittedAfter });
|
|
92
|
+
const overflow = preview.omittedBefore || preview.omittedAfter || allPreviewLines.length > rule.previewLines;
|
|
93
|
+
if (!overflow)
|
|
94
|
+
return allPreviewLines;
|
|
95
|
+
const previewLines = rule.direction === "tail" ? allPreviewLines.slice(-rule.previewLines) : allPreviewLines.slice(0, rule.previewLines);
|
|
94
96
|
return markTruncatedPreviewLine(previewLines, rule.direction, colors.statusDotBase);
|
|
95
97
|
}
|
|
96
98
|
function collapsedInlinePreview(text, rule, preserveAnsi = false) {
|
|
97
|
-
const
|
|
99
|
+
const preview = previewBodyText(text, rule.direction, rule.previewLines);
|
|
100
|
+
const rawLines = sanitizeToolBodyText(preview.text, preserveAnsi).split("\n").map((line) => stripAnsi(line).trim()).filter(Boolean);
|
|
98
101
|
if (rawLines.length === 0)
|
|
99
102
|
return { text: "", overflow: false };
|
|
100
103
|
const selectedLines = rule.direction === "tail" ? rawLines.slice(-rule.previewLines) : rawLines.slice(0, rule.previewLines);
|
|
101
|
-
return { text: selectedLines.join(" "), overflow: rawLines.length > rule.previewLines };
|
|
104
|
+
return { text: selectedLines.join(" "), overflow: preview.omittedBefore || preview.omittedAfter || rawLines.length > rule.previewLines };
|
|
105
|
+
}
|
|
106
|
+
function previewBodyText(text, direction, previewLines) {
|
|
107
|
+
const rawLines = text.split("\n");
|
|
108
|
+
const previewRawLines = Math.max(1, previewLines + 1);
|
|
109
|
+
if (rawLines.length <= previewRawLines)
|
|
110
|
+
return { text, rawLineOffset: 0, omittedBefore: false, omittedAfter: false };
|
|
111
|
+
if (direction === "tail") {
|
|
112
|
+
const start = Math.max(0, rawLines.length - previewRawLines);
|
|
113
|
+
return {
|
|
114
|
+
text: rawLines.slice(start).join("\n"),
|
|
115
|
+
rawLineOffset: start,
|
|
116
|
+
omittedBefore: start > 0,
|
|
117
|
+
omittedAfter: false,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
text: rawLines.slice(0, previewRawLines).join("\n"),
|
|
122
|
+
rawLineOffset: 0,
|
|
123
|
+
omittedBefore: false,
|
|
124
|
+
omittedAfter: rawLines.length > previewRawLines,
|
|
125
|
+
};
|
|
102
126
|
}
|
|
103
127
|
function markTruncatedPreviewLine(lines, direction, markerColor) {
|
|
104
128
|
if (lines.length === 0)
|
|
@@ -122,7 +146,7 @@ function markTruncatedPreviewLine(lines, direction, markerColor) {
|
|
|
122
146
|
};
|
|
123
147
|
});
|
|
124
148
|
}
|
|
125
|
-
function renderToolBodyLines(text, width, target, color, style, colors, syntaxHighlight, bodyWrap = "char", hasLspDiagnostics = false, bodyLineStyles, preserveAnsi = false, showGutter = false) {
|
|
149
|
+
function renderToolBodyLines(text, width, target, color, style, colors, syntaxHighlight, bodyWrap = "char", hasLspDiagnostics = false, bodyLineStyles, preserveAnsi = false, showGutter = false, options = {}) {
|
|
126
150
|
const displayPrefix = showGutter ? toolBodyGutterPrefix() : TOOL_BODY_PREFIX;
|
|
127
151
|
const prefixWidth = stringDisplayWidth(displayPrefix);
|
|
128
152
|
const bodyWidth = Math.max(1, width - prefixWidth);
|
|
@@ -131,13 +155,15 @@ function renderToolBodyLines(text, width, target, color, style, colors, syntaxHi
|
|
|
131
155
|
const gutterSegment = showGutter
|
|
132
156
|
? { start: 0, end: 1, foreground: colors.statusDotBase }
|
|
133
157
|
: undefined;
|
|
158
|
+
const rawLineOffset = options.rawLineOffset ?? 0;
|
|
134
159
|
for (const [rawLineIndex, rawLine] of sanitizeToolBodyText(text, preserveAnsi).split("\n").entries()) {
|
|
160
|
+
const absoluteRawLineIndex = rawLineOffset + rawLineIndex;
|
|
135
161
|
const ansiLine = preserveAnsi ? ansiStyledLine(rawLine) : undefined;
|
|
136
162
|
const displayLine = ansiLine?.text ?? rawLine;
|
|
137
163
|
const diffStyle = style === "diff" ? diffLineStyle(displayLine, colors) : undefined;
|
|
138
164
|
const lspDiagnosticStyle = hasLspDiagnostics ? lspDiagnosticLineStyle(displayLine, colors) : undefined;
|
|
139
|
-
const bodyLineStyle = bodyLineStyleForLine(bodyLineStyles,
|
|
140
|
-
const lineSyntaxHighlight = syntaxHighlightForLine(syntaxHighlight,
|
|
165
|
+
const bodyLineStyle = bodyLineStyleForLine(bodyLineStyles, absoluteRawLineIndex, colors);
|
|
166
|
+
const lineSyntaxHighlight = syntaxHighlightForLine(syntaxHighlight, absoluteRawLineIndex);
|
|
141
167
|
const wrappedLines = ansiLine && !diffStyle && !lspDiagnosticStyle && !bodyLineStyle && !lineSyntaxHighlight
|
|
142
168
|
? wrapAnsiStyledDisplayLine(ansiLine, bodyWidth)
|
|
143
169
|
: wrapBodyLine(displayLine, bodyWidth).map((wrapped) => ({ text: wrapped, segments: [] }));
|
|
@@ -195,7 +221,7 @@ function renderToolBodyLines(text, width, target, color, style, colors, syntaxHi
|
|
|
195
221
|
lines.push(line);
|
|
196
222
|
}
|
|
197
223
|
}
|
|
198
|
-
if (showGutter && lines.length > 0) {
|
|
224
|
+
if (showGutter && lines.length > 0 && options.bodyEndsAfterText !== false) {
|
|
199
225
|
const lastLine = lines.at(-1);
|
|
200
226
|
if (!lastLine)
|
|
201
227
|
return lines;
|
package/dist/app/runtime.js
CHANGED
|
@@ -10,7 +10,7 @@ import { isThinkingLevel, parseModelRef, parseScopedModelRef } from "./model/mod
|
|
|
10
10
|
import { openLazySessionManager } from "./session/lazy-session-manager.js";
|
|
11
11
|
const BUNDLED_QUESTION_EXTENSION_NAME = "question";
|
|
12
12
|
const PI_TOOLS_SUITE_EXTENSION_NAME = "pi-tools-suite";
|
|
13
|
-
const BUNDLED_EXTENSIONS_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "
|
|
13
|
+
const BUNDLED_EXTENSIONS_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "..", "bundled-extensions");
|
|
14
14
|
const BUNDLED_QUESTION_EXTENSION_DIR = resolve(BUNDLED_EXTENSIONS_DIR, BUNDLED_QUESTION_EXTENSION_NAME);
|
|
15
15
|
const BUNDLED_SESSION_TITLE_EXTENSION_DIR = resolve(BUNDLED_EXTENSIONS_DIR, "session-title");
|
|
16
16
|
const BUNDLED_TERMINAL_BELL_EXTENSION_DIR = resolve(BUNDLED_EXTENSIONS_DIR, "terminal-bell");
|
|
@@ -6,7 +6,7 @@ import type { ToastEntry, ToastVariant } from "../../ui.js";
|
|
|
6
6
|
import type { AppPopupActionController } from "../popup/popup-action-controller.js";
|
|
7
7
|
import type { AppPopupMenuController } from "../popup/popup-menu-controller.js";
|
|
8
8
|
import type { AppScrollController } from "./scroll-controller.js";
|
|
9
|
-
import type { Entry, ImageClickTarget, MouseEvent, MouseSelection, StatusContextTarget, StatusCompactToolsTarget, StatusDraftQueueTarget, StatusModelTarget, StatusModelUsageTarget, StatusPromptEnhancerTarget, StatusSessionTarget, StatusTerminalBellSoundTarget, TabLineMouseTarget, StatusThinkingExpandTarget, StatusThinkingTarget, StatusUserJumpTarget, StatusVoiceLanguageTarget, StatusVoiceMicTarget } from "../types.js";
|
|
9
|
+
import type { Entry, ImageClickTarget, MouseEvent, MouseSelection, StatusContextTarget, StatusCompactToolsTarget, StatusDraftQueueTarget, StatusModelTarget, StatusModelUsageTarget, StatusPromptEnhancerTarget, StatusQuickScrollTarget, StatusSessionTarget, StatusTerminalBellSoundTarget, TabLineMouseTarget, StatusThinkingExpandTarget, StatusThinkingTarget, StatusUserJumpTarget, StatusVoiceLanguageTarget, StatusVoiceMicTarget } from "../types.js";
|
|
10
10
|
import { type RenderedLink } from "./file-links.js";
|
|
11
11
|
import type { AgentSession } from "@earendil-works/pi-coding-agent";
|
|
12
12
|
type ClickFlash = {
|
|
@@ -56,6 +56,7 @@ export type AppMouseControllerHost = {
|
|
|
56
56
|
refreshModelUsageStatus(): void | Promise<void>;
|
|
57
57
|
refreshUserMessageJumpMenuItems?(): Promise<void>;
|
|
58
58
|
queueInputFromStatus?(): void | Promise<void>;
|
|
59
|
+
scrollConversationQuick(direction: "up" | "down"): void | Promise<void>;
|
|
59
60
|
toggleAllThinkingExpanded?(): void;
|
|
60
61
|
toggleSuperCompactTools?(): void;
|
|
61
62
|
toggleTerminalBellSound?(): void;
|
|
@@ -103,6 +104,8 @@ export declare class AppMouseController {
|
|
|
103
104
|
statusDraftQueueTarget: StatusDraftQueueTarget | undefined;
|
|
104
105
|
statusThinkingExpandTarget: StatusThinkingExpandTarget | undefined;
|
|
105
106
|
statusCompactToolsTarget: StatusCompactToolsTarget | undefined;
|
|
107
|
+
statusQuickScrollUpTarget: StatusQuickScrollTarget | undefined;
|
|
108
|
+
statusQuickScrollDownTarget: StatusQuickScrollTarget | undefined;
|
|
106
109
|
statusTerminalBellSoundTarget: StatusTerminalBellSoundTarget | undefined;
|
|
107
110
|
statusSessionTarget: StatusSessionTarget | undefined;
|
|
108
111
|
statusPromptEnhancerTarget: StatusPromptEnhancerTarget | undefined;
|
|
@@ -165,6 +168,7 @@ export declare class AppMouseController {
|
|
|
165
168
|
private handleStatusPromptEnhancerClick;
|
|
166
169
|
private handleStatusVoiceMicClick;
|
|
167
170
|
private handleStatusVoiceLanguageClick;
|
|
171
|
+
private handleStatusQuickScrollClick;
|
|
168
172
|
private handleInputClick;
|
|
169
173
|
private handleExtensionInputClick;
|
|
170
174
|
private openUserMessageMenu;
|