@oh-my-pi/pi-coding-agent 16.1.17 → 16.1.18
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 +19 -0
- package/dist/cli.js +16753 -16738
- package/dist/types/cli/usage-cli.d.ts +14 -0
- package/dist/types/commands/token.d.ts +9 -0
- package/dist/types/extensibility/plugins/legacy-pi-bundled-registry.d.ts +7 -0
- package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +31 -27
- package/dist/types/modes/components/extensions/extension-dashboard.d.ts +26 -10
- package/dist/types/modes/components/extensions/extension-list.d.ts +13 -0
- package/package.json +12 -12
- package/scripts/build-binary.ts +9 -16
- package/src/cli/usage-cli.ts +35 -4
- package/src/commands/token.ts +54 -0
- package/src/extensibility/plugins/legacy-pi-bundled-registry.ts +40 -0
- package/src/extensibility/plugins/legacy-pi-compat.ts +240 -122
- package/src/modes/components/extensions/extension-dashboard.ts +221 -165
- package/src/modes/components/extensions/extension-list.ts +66 -33
- package/src/modes/controllers/selector-controller.ts +4 -0
|
@@ -40,6 +40,9 @@ export class ExtensionList implements Component {
|
|
|
40
40
|
#focused = false;
|
|
41
41
|
#masterSwitchProvider: string | null = null;
|
|
42
42
|
#maxVisible: number;
|
|
43
|
+
#hoveredIndex: number | null = null;
|
|
44
|
+
/** Item rows rendered in the last frame, for mouse hit-testing. */
|
|
45
|
+
#visibleCount = 0;
|
|
43
46
|
|
|
44
47
|
constructor(
|
|
45
48
|
private extensions: Extension[],
|
|
@@ -108,6 +111,7 @@ export class ExtensionList implements Component {
|
|
|
108
111
|
|
|
109
112
|
render(width: number): readonly string[] {
|
|
110
113
|
const lines: string[] = [];
|
|
114
|
+
this.#visibleCount = 0;
|
|
111
115
|
|
|
112
116
|
// Search bar
|
|
113
117
|
const searchPrefix = theme.fg("muted", "Search: ");
|
|
@@ -136,15 +140,20 @@ export class ExtensionList implements Component {
|
|
|
136
140
|
for (let i = startIdx; i < endIdx; i++) {
|
|
137
141
|
const listItem = this.#listItems[i];
|
|
138
142
|
const isSelected = this.#focused && i === this.#selectedIndex;
|
|
143
|
+
const isHovered = this.#focused && i === this.#hoveredIndex && !isSelected;
|
|
139
144
|
|
|
145
|
+
let rowStr: string;
|
|
140
146
|
if (listItem.type === "master") {
|
|
141
|
-
|
|
147
|
+
rowStr = this.#renderMasterSwitch(listItem, isSelected, rowWidth);
|
|
142
148
|
} else if (listItem.type === "kind-header") {
|
|
143
|
-
|
|
149
|
+
rowStr = this.#renderKindHeader(listItem, isSelected, rowWidth);
|
|
144
150
|
} else {
|
|
145
|
-
|
|
151
|
+
rowStr = this.#renderExtensionRow(listItem.item, isSelected, rowWidth, masterDisabled);
|
|
146
152
|
}
|
|
153
|
+
if (isHovered) rowStr = theme.bg("selectedBg", rowStr);
|
|
154
|
+
rows.push(rowStr);
|
|
147
155
|
}
|
|
156
|
+
this.#visibleCount = rows.length;
|
|
148
157
|
|
|
149
158
|
lines.push(
|
|
150
159
|
...renderScrollableList(rows, {
|
|
@@ -387,6 +396,57 @@ export class ExtensionList implements Component {
|
|
|
387
396
|
this.#scrollOffset = next.scrollOffset;
|
|
388
397
|
}
|
|
389
398
|
|
|
399
|
+
/** Toggle the selected item, or flip the provider master switch when on it. */
|
|
400
|
+
#activateSelected(): void {
|
|
401
|
+
const item = this.#listItems[this.#selectedIndex];
|
|
402
|
+
if (item?.type === "master") {
|
|
403
|
+
this.callbacks.onMasterToggle?.(item.providerId);
|
|
404
|
+
} else if (item?.type === "extension") {
|
|
405
|
+
// Only allow toggling if the provider master switch is enabled.
|
|
406
|
+
const masterDisabled = this.#masterSwitchProvider !== null && !isProviderEnabled(this.#masterSwitchProvider);
|
|
407
|
+
if (!masterDisabled) {
|
|
408
|
+
const newEnabled = item.item.state === "disabled";
|
|
409
|
+
this.callbacks.onToggle?.(item.item.id, newEnabled);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/** Highlight the row under the pointer (null clears). */
|
|
415
|
+
setHoverIndex(index: number | null): void {
|
|
416
|
+
this.#hoveredIndex = index;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Map a 0-based line within this component's render to the absolute list-item
|
|
421
|
+
* index, or null when the line is the search banner, a padding row, or outside
|
|
422
|
+
* the visible window. The first two lines are the search banner and a blank
|
|
423
|
+
* separator; item rows follow, windowed at the current scroll offset.
|
|
424
|
+
*/
|
|
425
|
+
hitTest(line: number): number | null {
|
|
426
|
+
const rowLine = line - 2;
|
|
427
|
+
if (rowLine < 0 || rowLine >= this.#visibleCount) return null;
|
|
428
|
+
const index = this.#scrollOffset + rowLine;
|
|
429
|
+
return index < this.#listItems.length ? index : null;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/** Wheel notch: move the selection (and the inspector) one row. */
|
|
433
|
+
handleWheel(delta: -1 | 1): void {
|
|
434
|
+
if (delta < 0) this.#moveSelectionUp();
|
|
435
|
+
else this.#moveSelectionDown();
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/** Click: select the row under the pointer, or activate it when already selected. */
|
|
439
|
+
handleClick(line: number): void {
|
|
440
|
+
const index = this.hitTest(line);
|
|
441
|
+
if (index === null) return;
|
|
442
|
+
if (index === this.#selectedIndex) {
|
|
443
|
+
this.#activateSelected();
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
this.#selectedIndex = index;
|
|
447
|
+
this.#notifySelectionChange();
|
|
448
|
+
}
|
|
449
|
+
|
|
390
450
|
handleInput(data: string): void {
|
|
391
451
|
// Navigation
|
|
392
452
|
if (matchesSelectUp(data) || data === "k") {
|
|
@@ -399,36 +459,9 @@ export class ExtensionList implements Component {
|
|
|
399
459
|
return;
|
|
400
460
|
}
|
|
401
461
|
|
|
402
|
-
// Space:
|
|
403
|
-
if (data === " ") {
|
|
404
|
-
|
|
405
|
-
if (item?.type === "master") {
|
|
406
|
-
this.callbacks.onMasterToggle?.(item.providerId);
|
|
407
|
-
} else if (item?.type === "extension") {
|
|
408
|
-
// Only allow toggling if master is enabled
|
|
409
|
-
const masterDisabled =
|
|
410
|
-
this.#masterSwitchProvider !== null && !isProviderEnabled(this.#masterSwitchProvider);
|
|
411
|
-
if (!masterDisabled) {
|
|
412
|
-
const newEnabled = item.item.state === "disabled";
|
|
413
|
-
this.callbacks.onToggle?.(item.item.id, newEnabled);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
return;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// Enter: Same as space - toggle selected item
|
|
420
|
-
if (matchesKey(data, "enter") || matchesKey(data, "return") || data === "\n") {
|
|
421
|
-
const item = this.#listItems[this.#selectedIndex];
|
|
422
|
-
if (item?.type === "master") {
|
|
423
|
-
this.callbacks.onMasterToggle?.(item.providerId);
|
|
424
|
-
} else if (item?.type === "extension") {
|
|
425
|
-
const masterDisabled =
|
|
426
|
-
this.#masterSwitchProvider !== null && !isProviderEnabled(this.#masterSwitchProvider);
|
|
427
|
-
if (!masterDisabled) {
|
|
428
|
-
const newEnabled = item.item.state === "disabled";
|
|
429
|
-
this.callbacks.onToggle?.(item.item.id, newEnabled);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
462
|
+
// Space or Enter: activate the selected row (toggle item / master switch)
|
|
463
|
+
if (data === " " || matchesKey(data, "enter") || matchesKey(data, "return") || data === "\n") {
|
|
464
|
+
this.#activateSelected();
|
|
432
465
|
return;
|
|
433
466
|
}
|
|
434
467
|
|
|
@@ -232,11 +232,15 @@ export class SelectorController {
|
|
|
232
232
|
*/
|
|
233
233
|
async showExtensionsDashboard(): Promise<void> {
|
|
234
234
|
const dashboard = await ExtensionDashboard.create(getProjectDir(), this.ctx.settings, this.ctx.ui.terminal.rows);
|
|
235
|
+
// Fullscreen dashboard on the alternate screen (the /settings idiom): the
|
|
236
|
+
// overlay borrows the terminal's alt buffer and enables mouse tracking for
|
|
237
|
+
// its lifetime, leaving the transcript untouched underneath.
|
|
235
238
|
const overlay = this.ctx.ui.showOverlay(dashboard, {
|
|
236
239
|
width: "100%",
|
|
237
240
|
maxHeight: "100%",
|
|
238
241
|
anchor: "top-left",
|
|
239
242
|
margin: 0,
|
|
243
|
+
fullscreen: true,
|
|
240
244
|
});
|
|
241
245
|
dashboard.onClose = () => {
|
|
242
246
|
overlay.hide();
|