pi-ui-extend 0.1.13 → 0.1.15

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.
Files changed (92) hide show
  1. package/README.md +1 -1
  2. package/dist/app/app.d.ts +5 -0
  3. package/dist/app/app.js +82 -12
  4. package/dist/app/commands/command-controller.js +1 -0
  5. package/dist/app/commands/command-host.d.ts +3 -0
  6. package/dist/app/commands/command-model-actions.d.ts +2 -0
  7. package/dist/app/commands/command-model-actions.js +40 -4
  8. package/dist/app/commands/command-navigation-actions.js +3 -0
  9. package/dist/app/commands/command-registry.d.ts +1 -0
  10. package/dist/app/commands/command-registry.js +8 -0
  11. package/dist/app/extensions/extension-ui-controller.d.ts +16 -5
  12. package/dist/app/extensions/extension-ui-controller.js +99 -61
  13. package/dist/app/input/input-action-controller.d.ts +1 -0
  14. package/dist/app/input/input-action-controller.js +8 -2
  15. package/dist/app/logger.d.ts +25 -0
  16. package/dist/app/logger.js +90 -0
  17. package/dist/app/model/model-usage-status.js +30 -15
  18. package/dist/app/popup/menu-items-controller.d.ts +2 -0
  19. package/dist/app/popup/menu-items-controller.js +45 -6
  20. package/dist/app/popup/popup-action-controller.d.ts +2 -1
  21. package/dist/app/popup/popup-action-controller.js +7 -4
  22. package/dist/app/popup/popup-menu-controller.d.ts +36 -23
  23. package/dist/app/popup/popup-menu-controller.js +68 -322
  24. package/dist/app/rendering/conversation-entry-renderer.js +3 -3
  25. package/dist/app/rendering/conversation-viewport.d.ts +10 -2
  26. package/dist/app/rendering/conversation-viewport.js +157 -16
  27. package/dist/app/rendering/editor-panels.js +4 -2
  28. package/dist/app/rendering/popup-menu-renderer.d.ts +50 -0
  29. package/dist/app/rendering/popup-menu-renderer.js +307 -0
  30. package/dist/app/rendering/render-controller.js +5 -13
  31. package/dist/app/rendering/status-line-renderer.d.ts +1 -1
  32. package/dist/app/rendering/status-line-renderer.js +27 -24
  33. package/dist/app/rendering/toast-controller.d.ts +11 -3
  34. package/dist/app/rendering/toast-controller.js +53 -12
  35. package/dist/app/runtime.d.ts +2 -1
  36. package/dist/app/runtime.js +20 -10
  37. package/dist/app/screen/mouse-controller.d.ts +2 -2
  38. package/dist/app/screen/mouse-controller.js +27 -48
  39. package/dist/app/screen/screen-styler.d.ts +1 -1
  40. package/dist/app/screen/screen-styler.js +9 -7
  41. package/dist/app/screen/scroll-controller.d.ts +11 -9
  42. package/dist/app/screen/scroll-controller.js +50 -45
  43. package/dist/app/session/lazy-session-manager.d.ts +11 -0
  44. package/dist/app/session/lazy-session-manager.js +539 -0
  45. package/dist/app/session/pix-system-message.d.ts +16 -0
  46. package/dist/app/session/pix-system-message.js +64 -0
  47. package/dist/app/session/session-event-controller.d.ts +11 -0
  48. package/dist/app/session/session-event-controller.js +58 -2
  49. package/dist/app/session/session-history.d.ts +18 -0
  50. package/dist/app/session/session-history.js +72 -3
  51. package/dist/app/session/session-lifecycle-controller.d.ts +6 -2
  52. package/dist/app/session/session-lifecycle-controller.js +7 -2
  53. package/dist/app/session/tabs-controller.d.ts +13 -1
  54. package/dist/app/session/tabs-controller.js +248 -27
  55. package/dist/app/todo/todo-model.d.ts +3 -1
  56. package/dist/app/todo/todo-model.js +14 -2
  57. package/dist/app/types.d.ts +5 -2
  58. package/dist/app/workspace/workspace-actions-controller.d.ts +2 -0
  59. package/dist/app/workspace/workspace-actions-controller.js +12 -0
  60. package/dist/config.d.ts +5 -1
  61. package/dist/config.js +73 -25
  62. package/dist/default-pix-config.js +2 -0
  63. package/dist/schemas/pi-tools-suite-schema.d.ts +1 -0
  64. package/dist/schemas/pi-tools-suite-schema.js +1 -0
  65. package/dist/schemas/pix-schema.d.ts +2 -1
  66. package/dist/schemas/pix-schema.js +5 -4
  67. package/dist/terminal-width.d.ts +2 -0
  68. package/dist/terminal-width.js +64 -3
  69. package/external/pi-tools-suite/README.md +1 -0
  70. package/external/pi-tools-suite/src/antigravity-auth/auth-store.ts +12 -3
  71. package/external/pi-tools-suite/src/antigravity-auth/commands.ts +2 -4
  72. package/external/pi-tools-suite/src/antigravity-auth/constants.ts +2 -2
  73. package/external/pi-tools-suite/src/antigravity-auth/index.ts +8 -2
  74. package/external/pi-tools-suite/src/antigravity-auth/oauth.ts +102 -50
  75. package/external/pi-tools-suite/src/antigravity-auth/status.ts +81 -2
  76. package/external/pi-tools-suite/src/antigravity-auth/stream.ts +29 -8
  77. package/external/pi-tools-suite/src/config.ts +8 -0
  78. package/external/pi-tools-suite/src/dcp/index.ts +16 -1
  79. package/external/pi-tools-suite/src/dcp/state.ts +35 -0
  80. package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +3 -0
  81. package/external/pi-tools-suite/src/todo/index.ts +181 -11
  82. package/external/pi-tools-suite/src/todo/state/state-reducer.ts +23 -10
  83. package/external/pi-tools-suite/src/todo/todo.ts +10 -5
  84. package/external/pi-tools-suite/src/todo/tool/response-envelope.ts +33 -6
  85. package/external/pi-tools-suite/src/todo/tool/types.ts +9 -1
  86. package/external/pi-tools-suite/src/todo/view/format.ts +2 -1
  87. package/external/pi-tools-suite/src/tool-descriptions.ts +2 -1
  88. package/external/pi-tools-suite/src/usage/index.ts +5 -2
  89. package/external/pi-tools-suite/src/usage/lib/google.ts +6 -13
  90. package/package.json +1 -1
  91. package/schemas/pi-tools-suite.json +4 -0
  92. package/schemas/pix.json +6 -2
@@ -3,11 +3,15 @@ import { fuzzySearch } from "../../fuzzy.js";
3
3
  import { PI_FAVORITE_MODEL_REFS, THINKING_LEVELS } from "../constants.js";
4
4
  import { APP_ICONS } from "../icons.js";
5
5
  import { parseScopedModelRef } from "../model/model-ref.js";
6
- import { buildUserMessageJumpItems, createSessionInfoMenuItemsLoader } from "./popup-menu-controller.js";
6
+ import { buildUserMessageJumpItems, createSessionInfoMenuItemsLoader, filterUserMessageJumpItems } from "./popup-menu-controller.js";
7
7
  import { getResourceSlashCommands, getSlashCommandMatches, parseSlashInput } from "../commands/slash-commands.js";
8
+ import { isRecord } from "../guards.js";
9
+ import { renderUserMessageContent } from "../rendering/message-content.js";
10
+ import { sessionHistoryFullBranchEntries } from "../session/pix-system-message.js";
8
11
  export class AppMenuItemsController {
9
12
  host;
10
13
  resumeMenuLoaderCache;
14
+ userMessageJumpItems;
11
15
  constructor(host) {
12
16
  this.host = host;
13
17
  }
@@ -65,8 +69,7 @@ export class AppMenuItemsController {
65
69
  getThinkingMenuItems(query) {
66
70
  const session = this.host.runtime()?.session;
67
71
  const currentLevel = session?.thinkingLevel ?? "off";
68
- const availableLevels = session ? session.getAvailableThinkingLevels() : [...THINKING_LEVELS];
69
- const levels = availableLevels.includes("off") ? availableLevels : ["off", ...availableLevels];
72
+ const levels = session ? normalizeAvailableThinkingLevels(session.getAvailableThinkingLevels()) : [...THINKING_LEVELS];
70
73
  const items = levels.map((level) => ({
71
74
  value: { level, current: level === currentLevel },
72
75
  label: level,
@@ -79,18 +82,40 @@ export class AppMenuItemsController {
79
82
  return fuzzySearch(items, query).map((match) => ({
80
83
  value: match.value,
81
84
  label: `${match.value.level}${match.value.current ? ` ${APP_ICONS.check}` : ""}`,
82
- description: this.thinkingLevelDescription(match.value.level),
85
+ description: this.thinkingLevelDescription(match.value.level, levels),
83
86
  }));
84
87
  }
85
88
  getUserMessageMenuItems() {
86
89
  return [
87
90
  { value: "copy", label: "Copy message", description: "Copy the full user message" },
88
91
  { value: "fork", label: "Fork", description: "Create a new session before this message" },
92
+ { value: "fork-new-tab", label: "Fork in new tab", description: "Create a fork in a new tab" },
89
93
  { value: "undo", label: "Undo changes", description: "Revert recorded commands and cut session here" },
90
94
  ];
91
95
  }
92
96
  getUserMessageJumpMenuItems(query) {
93
- return buildUserMessageJumpItems(this.host.getEntries(), query);
97
+ return filterUserMessageJumpItems(this.userMessageJumpItems ?? buildUserMessageJumpItems(this.host.getEntries()), query);
98
+ }
99
+ async refreshUserMessageJumpMenuItems() {
100
+ const runtime = this.host.runtime();
101
+ if (!runtime) {
102
+ this.userMessageJumpItems = undefined;
103
+ return;
104
+ }
105
+ const entries = await sessionHistoryFullBranchEntries(runtime.session);
106
+ const loadedBySessionEntryId = new Map(this.host.getEntries()
107
+ .filter((entry) => entry.kind === "user" && typeof entry.sessionEntryId === "string")
108
+ .map((entry) => [entry.sessionEntryId, entry]));
109
+ const sources = entries.flatMap((entry) => {
110
+ if (entry.type !== "message" || !isRecord(entry.message) || entry.message.role !== "user")
111
+ return [];
112
+ const text = renderUserMessageContent(entry.message.content);
113
+ if (!text)
114
+ return [];
115
+ const loaded = loadedBySessionEntryId.get(entry.id);
116
+ return [{ text, ...(loaded ? { entryId: loaded.id } : {}), sessionEntryId: entry.id }];
117
+ });
118
+ this.userMessageJumpItems = buildUserMessageJumpItems(sources);
94
119
  }
95
120
  getQueueMessageMenuItems() {
96
121
  return [
@@ -163,7 +188,7 @@ export class AppMenuItemsController {
163
188
  return (refreshed ?? scoped.model);
164
189
  });
165
190
  }
166
- thinkingLevelDescription(level) {
191
+ thinkingLevelDescription(level, _availableLevels) {
167
192
  switch (level) {
168
193
  case "off":
169
194
  return "No reasoning/thinking";
@@ -180,3 +205,17 @@ export class AppMenuItemsController {
180
205
  }
181
206
  }
182
207
  }
208
+ function normalizeAvailableThinkingLevels(levels) {
209
+ const seen = new Set();
210
+ const normalized = [];
211
+ for (const level of levels ?? THINKING_LEVELS) {
212
+ if (!isAvailableThinkingLevel(level) || seen.has(level))
213
+ continue;
214
+ seen.add(level);
215
+ normalized.push(level);
216
+ }
217
+ return normalized.length > 0 ? normalized : ["off"];
218
+ }
219
+ function isAvailableThinkingLevel(value) {
220
+ return THINKING_LEVELS.includes(value);
221
+ }
@@ -3,7 +3,7 @@ import type { AppCommandController } from "../commands/command-controller.js";
3
3
  import type { AppMenuItemsController } from "./menu-items-controller.js";
4
4
  import type { AppPopupMenuController } from "./popup-menu-controller.js";
5
5
  import type { AppQueuedMessageController } from "../session/queued-message-controller.js";
6
- import type { Entry, SlashCommand } from "../types.js";
6
+ import type { Entry, SlashCommand, UserMessageJumpMenuValue } from "../types.js";
7
7
  import type { AppWorkspaceActionsController } from "../workspace/workspace-actions-controller.js";
8
8
  export type AppPopupActionControllerHost = {
9
9
  runtime(): AgentSessionRuntime | undefined;
@@ -19,6 +19,7 @@ export type AppPopupActionControllerHost = {
19
19
  bindCurrentSession(): Promise<void>;
20
20
  loadSessionHistory(): void;
21
21
  scrollToConversationEntry(entryId: string): boolean;
22
+ scrollToUserMessageJumpTarget(target: UserMessageJumpMenuValue): Promise<boolean>;
22
23
  };
23
24
  export declare class AppPopupActionController {
24
25
  private readonly host;
@@ -24,7 +24,7 @@ export class AppPopupActionController {
24
24
  if (active === "user-message")
25
25
  return await this.submitSelectedUserMessageAction();
26
26
  if (active === "user-message-jump")
27
- return this.submitSelectedUserMessageJump();
27
+ return await this.submitSelectedUserMessageJump();
28
28
  if (active === "resume")
29
29
  return await this.submitSelectedResume();
30
30
  if (active === "model")
@@ -155,6 +155,10 @@ export class AppPopupActionController {
155
155
  await this.workspaceActions.forkFromUserMessage(selected.entryId);
156
156
  return true;
157
157
  }
158
+ if (selected.value === "fork-new-tab") {
159
+ await this.workspaceActions.forkFromUserMessageInNewTab(selected.entryId);
160
+ return true;
161
+ }
158
162
  await this.workspaceActions.undoChangesFromUserMessage(selected.entryId);
159
163
  return true;
160
164
  }
@@ -165,13 +169,12 @@ export class AppPopupActionController {
165
169
  return true;
166
170
  }
167
171
  }
168
- submitSelectedUserMessageJump() {
172
+ async submitSelectedUserMessageJump() {
169
173
  const selected = this.popupMenus.selectedUserMessageJump();
170
174
  if (!selected)
171
175
  return false;
172
- const entryId = selected.entryId;
173
176
  this.popupMenus.closeUserMessageJumpMenu();
174
- if (!this.host.scrollToConversationEntry(entryId)) {
177
+ if (!await this.host.scrollToUserMessageJumpTarget(selected)) {
175
178
  this.host.showToast("User message not found", "error");
176
179
  this.host.setSessionStatus(this.host.runtime()?.session);
177
180
  return true;
@@ -1,6 +1,4 @@
1
- import { type Theme } from "../../theme.js";
2
1
  import { PopupMenu, type PopupMenuItem } from "../../ui.js";
3
- import type { ScreenStyler } from "../screen/screen-styler.js";
4
2
  import type { ActivePopupMenu, Entry, ModelMenuValue, ParsedSlashInput, PixMenuController, PixMenuItem, PixMenuOptions, PixMenuSelectOptions, PopupMenuPlacement, QueueMessageMenuValue, RenderedLine, ResumeMenuValue, SlashCommand, ThinkingMenuValue, UserMessageJumpMenuValue, UserMessageMenuValue } from "../types.js";
5
3
  import type { AgentSession, SessionInfo } from "@earendil-works/pi-coding-agent";
6
4
  type SlashCommandMenuValue = SlashCommand;
@@ -10,10 +8,34 @@ type ResumePopupMenuValue = ResumeMenuValue;
10
8
  type UserMessagePopupMenuValue = UserMessageMenuValue;
11
9
  type UserMessageJumpPopupMenuValue = UserMessageJumpMenuValue;
12
10
  type QueueMessagePopupMenuValue = QueueMessageMenuValue;
11
+ type SdkPopupMenuValue = PixMenuItem<unknown>;
12
+ type PopupMenuRendererPort = {
13
+ popupMenuWidth(columns: number): number;
14
+ popupMenuMargin(columns: number): number;
15
+ effectivePopupMenuWidth(columns: number): number;
16
+ styleOverlayLine(row: number, line: RenderedLine, width: number, activeMenu: PopupMenu<unknown>): string;
17
+ overlayPlainText(line: RenderedLine, width: number): string;
18
+ renderInlineUserMessageMenu(options: {
19
+ userContentWidth: number;
20
+ userContentLeft: number;
21
+ userLine: (text: string, entryId?: string, syntaxHighlight?: RenderedLine["syntaxHighlight"]) => RenderedLine;
22
+ }, menu: PopupMenu<UserMessagePopupMenuValue>): RenderedLine[];
23
+ renderSlashCommandMenu(width: number, menu: PopupMenu<SlashCommandMenuValue>): RenderedLine[];
24
+ renderModelMenu(width: number, menu: PopupMenu<ModelPopupMenuValue>): RenderedLine[];
25
+ renderThinkingMenu(width: number, menu: PopupMenu<ThinkingPopupMenuValue>): RenderedLine[];
26
+ renderResumeMenu(width: number, menu: PopupMenu<ResumePopupMenuValue>, state: {
27
+ directQuery: string;
28
+ allSessionsLoaded: boolean;
29
+ loadedSessionCount: number;
30
+ }): RenderedLine[];
31
+ renderUserMessageJumpMenu(width: number, menu: PopupMenu<UserMessageJumpPopupMenuValue>, directQuery: string): RenderedLine[];
32
+ renderQueueMessageMenu(width: number, menu: PopupMenu<QueueMessagePopupMenuValue>): RenderedLine[];
33
+ renderSdkMenu(width: number, menu: PopupMenu<SdkPopupMenuValue>, request: {
34
+ options: PixMenuOptions;
35
+ } | undefined, directQuery: string): RenderedLine[];
36
+ };
13
37
  export type DirectPopupMenu = Exclude<ActivePopupMenu, "slash">;
14
38
  export type AppPopupMenuControllerHost = {
15
- readonly theme: Theme;
16
- readonly screenStyler: ScreenStyler;
17
39
  readonly entries: readonly Entry[];
18
40
  readonly session: AgentSession | undefined;
19
41
  readonly resumeLoading: boolean;
@@ -37,6 +59,7 @@ export type AppPopupMenuControllerHost = {
37
59
  };
38
60
  export declare class AppPopupMenuController {
39
61
  private readonly host;
62
+ private readonly renderer;
40
63
  readonly menuController: PixMenuController;
41
64
  private readonly slashCommandMenu;
42
65
  private readonly modelMenu;
@@ -62,7 +85,7 @@ export declare class AppPopupMenuController {
62
85
  private resumeMenuAllSessionsLoaded;
63
86
  private activeUserMessageEntryId;
64
87
  private activeQueuedMessageEntryId;
65
- constructor(host: AppPopupMenuControllerHost);
88
+ constructor(host: AppPopupMenuControllerHost, renderer: PopupMenuRendererPort);
66
89
  get directMenu(): DirectPopupMenu | undefined;
67
90
  get directQuery(): string;
68
91
  setDirectMenu(menu: DirectPopupMenu | undefined): void;
@@ -95,6 +118,7 @@ export declare class AppPopupMenuController {
95
118
  closeModelSelection(): void;
96
119
  closeThinkingSelection(): void;
97
120
  closeSlashCommandSelection(): void;
121
+ closeMenusForTabSwitch(): void;
98
122
  cancelActivePopupMenu(): void;
99
123
  autocompleteSlashCommand(): void;
100
124
  autocompleteModel(): boolean;
@@ -137,19 +161,12 @@ export declare class AppPopupMenuController {
137
161
  userContentLeft: number;
138
162
  userLine: (text: string, entryId?: string, syntaxHighlight?: RenderedLine["syntaxHighlight"]) => RenderedLine;
139
163
  }): RenderedLine[];
140
- private hasPopupActionItems;
141
164
  private withoutCloseMenuItems;
142
165
  private resetPopupMenuSelection;
143
166
  private resetResumeMenuLazyState;
144
167
  private maybeGrowResumeMenuWindow;
145
168
  private updateResumeMenuLoadedState;
146
169
  private resumeMenuLoadedSessionCount;
147
- private userMessageActionForeground;
148
- private selectableItemVariant;
149
- private queueMessageItemVariant;
150
- private sdkItemVariant;
151
- private resumeMenuItemSegments;
152
- private popupMenuHeader;
153
170
  private syncModelMenu;
154
171
  private syncThinkingMenu;
155
172
  private syncResumeMenu;
@@ -160,17 +177,7 @@ export declare class AppPopupMenuController {
160
177
  private syncSlashCommandMenu;
161
178
  private closeMenusExcept;
162
179
  private getSdkMenuItems;
163
- private renderSlashCommandMenu;
164
- private renderModelMenu;
165
- private renderThinkingMenu;
166
- private renderResumeMenu;
167
- private renderUserMessageJumpMenu;
168
- private renderQueueMessageMenu;
169
- private renderSdkMenu;
170
- private popupLineForeground;
171
- private popupLineBackground;
172
180
  }
173
- export declare function formatPopupMenuHeader(title: string, width: number): string;
174
181
  export type SessionInfoMenuItemsLoader = {
175
182
  readonly total: number;
176
183
  items(limit?: number): PopupMenuItem<SessionInfo>[];
@@ -179,5 +186,11 @@ export declare function createSessionInfoMenuItemsLoader(sessions: readonly Sess
179
186
  export declare function formatSessionInfoMenuItems(sessions: readonly SessionInfo[], currentSessionFile: string | undefined, query: string, options?: {
180
187
  limit?: number;
181
188
  }): PopupMenuItem<SessionInfo>[];
182
- export declare function buildUserMessageJumpItems(entries: readonly Entry[], query: string): PopupMenuItem<UserMessageJumpMenuValue>[];
189
+ export type UserMessageJumpSourceItem = {
190
+ text: string;
191
+ entryId?: string;
192
+ sessionEntryId?: string;
193
+ };
194
+ export declare function buildUserMessageJumpItems(entries: readonly Entry[] | readonly UserMessageJumpSourceItem[]): PopupMenuItem<UserMessageJumpMenuValue>[];
195
+ export declare function filterUserMessageJumpItems(items: readonly PopupMenuItem<UserMessageJumpMenuValue>[], query: string): PopupMenuItem<UserMessageJumpMenuValue>[];
183
196
  export type { ModelPopupMenuValue, QueueMessagePopupMenuValue, ResumePopupMenuValue, SlashCommandMenuValue, ThinkingPopupMenuValue, UserMessageJumpPopupMenuValue, UserMessagePopupMenuValue, };