@pellux/goodvibes-sdk 0.18.20 → 0.18.22

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 (35) hide show
  1. package/dist/_internal/platform/automation/manager-runtime-execution.d.ts +2 -0
  2. package/dist/_internal/platform/automation/manager-runtime-execution.d.ts.map +1 -1
  3. package/dist/_internal/platform/automation/manager-runtime-execution.js +18 -6
  4. package/dist/_internal/platform/automation/manager-runtime.d.ts +5 -0
  5. package/dist/_internal/platform/automation/manager-runtime.d.ts.map +1 -1
  6. package/dist/_internal/platform/automation/manager-runtime.js +6 -0
  7. package/dist/_internal/platform/core/deterministic-replay.d.ts +2 -1
  8. package/dist/_internal/platform/core/deterministic-replay.d.ts.map +1 -1
  9. package/dist/_internal/platform/core/deterministic-replay.js +11 -5
  10. package/dist/_internal/platform/core/replay-command-handler.js +1 -1
  11. package/dist/_internal/platform/plugins/api.d.ts +2 -2
  12. package/dist/_internal/platform/plugins/api.d.ts.map +1 -1
  13. package/dist/_internal/platform/plugins/loader.d.ts +2 -2
  14. package/dist/_internal/platform/plugins/loader.d.ts.map +1 -1
  15. package/dist/_internal/platform/runtime/host-ui.d.ts +59 -0
  16. package/dist/_internal/platform/runtime/host-ui.d.ts.map +1 -0
  17. package/dist/_internal/platform/runtime/host-ui.js +25 -0
  18. package/dist/_internal/platform/runtime/integration/helpers.d.ts +2 -2
  19. package/dist/_internal/platform/runtime/integration/helpers.d.ts.map +1 -1
  20. package/dist/_internal/platform/runtime/services.d.ts +5 -4
  21. package/dist/_internal/platform/runtime/services.d.ts.map +1 -1
  22. package/dist/_internal/platform/runtime/services.js +5 -6
  23. package/package.json +1 -1
  24. package/dist/_internal/platform/input/command-registry.d.ts +0 -17
  25. package/dist/_internal/platform/input/command-registry.d.ts.map +0 -1
  26. package/dist/_internal/platform/input/command-registry.js +0 -25
  27. package/dist/_internal/platform/input/keybindings.d.ts +0 -88
  28. package/dist/_internal/platform/input/keybindings.d.ts.map +0 -1
  29. package/dist/_internal/platform/input/keybindings.js +0 -206
  30. package/dist/_internal/platform/panels/panel-manager.d.ts +0 -89
  31. package/dist/_internal/platform/panels/panel-manager.d.ts.map +0 -1
  32. package/dist/_internal/platform/panels/panel-manager.js +0 -481
  33. package/dist/_internal/platform/panels/types.d.ts +0 -30
  34. package/dist/_internal/platform/panels/types.d.ts.map +0 -1
  35. package/dist/_internal/platform/panels/types.js +0 -1
@@ -1,481 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // PanelManager — central manager for panel lifecycle, navigation, and split
3
- // ---------------------------------------------------------------------------
4
- // ---------------------------------------------------------------------------
5
- // PanelManager
6
- // ---------------------------------------------------------------------------
7
- export class PanelManager {
8
- registry = [];
9
- retainedPanels = new Map();
10
- _visible = false;
11
- _splitRatio = 0.6;
12
- // Two panes for the top/bottom split within the panel area
13
- topPane = { panels: [], activeIndex: 0 };
14
- bottomPane = { panels: [], activeIndex: 0 };
15
- _focusedPane = 'top';
16
- _verticalSplitRatio = 0.5; // top gets 50% of panel height
17
- _bottomPaneVisible = false;
18
- // -------------------------------------------------------------------------
19
- // Registration
20
- // -------------------------------------------------------------------------
21
- registerType(registration) {
22
- const existing = this.registry.findIndex(r => r.id === registration.id);
23
- if (existing >= 0) {
24
- this.registry[existing] = registration;
25
- }
26
- else {
27
- this.registry.push(registration);
28
- }
29
- }
30
- getRegisteredTypes() {
31
- return [...this.registry];
32
- }
33
- getTypesByCategory() {
34
- const map = new Map();
35
- for (const reg of this.registry) {
36
- const list = map.get(reg.category) ?? [];
37
- list.push(reg);
38
- map.set(reg.category, list);
39
- }
40
- return map;
41
- }
42
- prewarmRegistered() {
43
- for (const registration of this.registry) {
44
- if (!registration.preload)
45
- continue;
46
- if (this.getPanel(registration.id) || this.retainedPanels.has(registration.id))
47
- continue;
48
- const panel = registration.factory();
49
- this.retainedPanels.set(registration.id, panel);
50
- }
51
- }
52
- // -------------------------------------------------------------------------
53
- // Panel lifecycle — operates on a specific pane (defaults to focused)
54
- // -------------------------------------------------------------------------
55
- open(panelId, pane) {
56
- const existingPane = this._findPaneOf(panelId);
57
- if (existingPane) {
58
- this._activateByIdInPane(panelId, existingPane);
59
- this._visible = true;
60
- this._focusedPane = existingPane;
61
- if (existingPane === 'bottom')
62
- this._bottomPaneVisible = true;
63
- return this._getPane(existingPane).panels[this._getPane(existingPane).activeIndex];
64
- }
65
- const targetPane = pane ?? this._focusedPane;
66
- const p = this._getPane(targetPane);
67
- const oldPanel = p.panels[p.activeIndex];
68
- if (oldPanel)
69
- oldPanel.onDeactivate();
70
- const panel = this._obtainPanel(panelId);
71
- p.panels.push(panel);
72
- p.activeIndex = p.panels.length - 1;
73
- this._visible = true;
74
- // If opening into bottom pane, also make it visible
75
- if (targetPane === 'bottom') {
76
- this._bottomPaneVisible = true;
77
- this._focusedPane = 'bottom';
78
- }
79
- else {
80
- this._focusedPane = 'top';
81
- }
82
- panel.onActivate();
83
- return panel;
84
- }
85
- close(panelId) {
86
- // Search both panes
87
- for (const which of ['top', 'bottom']) {
88
- const p = this._getPane(which);
89
- const index = p.panels.findIndex(panel => panel.id === panelId);
90
- if (index < 0)
91
- continue;
92
- const panel = p.panels[index];
93
- const wasActive = index === p.activeIndex;
94
- if (wasActive)
95
- panel.onDeactivate();
96
- if (this._shouldRetain(panelId)) {
97
- this.retainedPanels.set(panelId, panel);
98
- }
99
- else {
100
- panel.onDestroy();
101
- }
102
- p.panels.splice(index, 1);
103
- if (p.panels.length === 0) {
104
- p.activeIndex = 0;
105
- if (which === 'bottom') {
106
- this._bottomPaneVisible = false;
107
- // Move focus to top if we were focused on empty bottom
108
- if (this._focusedPane === 'bottom')
109
- this._focusedPane = 'top';
110
- }
111
- }
112
- else {
113
- p.activeIndex = Math.min(p.activeIndex, p.panels.length - 1);
114
- if (wasActive) {
115
- const newActive = p.panels[p.activeIndex];
116
- if (newActive)
117
- newActive.onActivate();
118
- }
119
- }
120
- // Hide sidebar if no panels remain in either pane
121
- if (this.topPane.panels.length === 0 && this.bottomPane.panels.length === 0) {
122
- this._visible = false;
123
- }
124
- return;
125
- }
126
- }
127
- /**
128
- * Move a panel to a specific pane. If panelId is omitted, moves the active
129
- * panel from the currently focused pane.
130
- */
131
- moveToPane(dest, panelId) {
132
- const srcPaneName = panelId
133
- ? this._findPaneOf(panelId) ?? this._focusedPane
134
- : this._focusedPane;
135
- if (srcPaneName === dest)
136
- return; // already there
137
- const dstPaneName = dest;
138
- this._moveBetweenPanes(srcPaneName, dstPaneName, panelId);
139
- }
140
- /**
141
- * Move a panel to the other pane. If panelId is omitted, moves the active
142
- * panel from the currently focused pane.
143
- */
144
- moveToOtherPane(panelId) {
145
- const srcPaneName = panelId
146
- ? this._findPaneOf(panelId) ?? this._focusedPane
147
- : this._focusedPane;
148
- const dstPaneName = srcPaneName === 'top' ? 'bottom' : 'top';
149
- this._moveBetweenPanes(srcPaneName, dstPaneName, panelId);
150
- }
151
- // -------------------------------------------------------------------------
152
- // Navigation — operates on focused pane
153
- // -------------------------------------------------------------------------
154
- nextPanel() {
155
- const p = this._getFocusedPane();
156
- if (p.panels.length === 0)
157
- return;
158
- const oldPanel = p.panels[p.activeIndex];
159
- if (oldPanel)
160
- oldPanel.onDeactivate();
161
- p.activeIndex = (p.activeIndex + 1) % p.panels.length;
162
- const newPanel = p.panels[p.activeIndex];
163
- if (newPanel)
164
- newPanel.onActivate();
165
- }
166
- nextWorkspaceTab() {
167
- this._cycleWorkspaceTab(1);
168
- }
169
- prevWorkspaceTab() {
170
- this._cycleWorkspaceTab(-1);
171
- }
172
- prevPanel() {
173
- const p = this._getFocusedPane();
174
- if (p.panels.length === 0)
175
- return;
176
- const oldPanel = p.panels[p.activeIndex];
177
- if (oldPanel)
178
- oldPanel.onDeactivate();
179
- p.activeIndex = (p.activeIndex - 1 + p.panels.length) % p.panels.length;
180
- const newPanel = p.panels[p.activeIndex];
181
- if (newPanel)
182
- newPanel.onActivate();
183
- }
184
- activateByIndex(index) {
185
- const p = this._getFocusedPane();
186
- if (index < 0 || index >= p.panels.length)
187
- return;
188
- if (index === p.activeIndex)
189
- return;
190
- const oldPanel = p.panels[p.activeIndex];
191
- if (oldPanel)
192
- oldPanel.onDeactivate();
193
- p.activeIndex = index;
194
- const newPanel = p.panels[p.activeIndex];
195
- if (newPanel)
196
- newPanel.onActivate();
197
- }
198
- activateById(panelId) {
199
- const which = this._findPaneOf(panelId);
200
- if (!which)
201
- return;
202
- this._activateByIdInPane(panelId, which);
203
- }
204
- // -------------------------------------------------------------------------
205
- // Pane focus control
206
- // -------------------------------------------------------------------------
207
- focusPane(pane) {
208
- if (pane === 'bottom' && !this._bottomPaneVisible)
209
- return;
210
- this._focusedPane = pane;
211
- }
212
- getFocusedPane() {
213
- return this._focusedPane;
214
- }
215
- /** Get the currently active (focused) panel, or null if none. */
216
- getActivePanel() {
217
- const p = this._getFocusedPane();
218
- return p.panels[p.activeIndex] ?? null;
219
- }
220
- togglePaneFocus() {
221
- if (!this._bottomPaneVisible || this.bottomPane.panels.length === 0)
222
- return;
223
- this._focusedPane = this._focusedPane === 'top' ? 'bottom' : 'top';
224
- }
225
- // -------------------------------------------------------------------------
226
- // Pane visibility
227
- // -------------------------------------------------------------------------
228
- toggleBottomPane() {
229
- if (this._bottomPaneVisible) {
230
- this._bottomPaneVisible = false;
231
- if (this._focusedPane === 'bottom')
232
- this._focusedPane = 'top';
233
- }
234
- else {
235
- this._bottomPaneVisible = true;
236
- // If bottom pane is empty, populate it
237
- if (this.bottomPane.panels.length === 0) {
238
- if (this.topPane.panels.length > 1) {
239
- // Move last panel from top to bottom
240
- const panel = this.topPane.panels.pop();
241
- if (this.topPane.activeIndex >= this.topPane.panels.length) {
242
- this.topPane.activeIndex = Math.max(0, this.topPane.panels.length - 1);
243
- }
244
- this.bottomPane.panels.push(panel);
245
- this.bottomPane.activeIndex = 0;
246
- }
247
- else {
248
- // Open a default panel in bottom pane
249
- const firstType = this.registry[0];
250
- if (firstType) {
251
- this.open(firstType.id, 'bottom');
252
- }
253
- }
254
- }
255
- this._focusedPane = 'bottom';
256
- }
257
- }
258
- isBottomPaneVisible() {
259
- return this._bottomPaneVisible && this.bottomPane.panels.length > 0;
260
- }
261
- // -------------------------------------------------------------------------
262
- // Pane state accessors
263
- // -------------------------------------------------------------------------
264
- getTopPane() {
265
- return this.topPane;
266
- }
267
- getBottomPane() {
268
- return this.bottomPane;
269
- }
270
- // -------------------------------------------------------------------------
271
- // Backward-compatible accessors (operate on focused pane)
272
- // -------------------------------------------------------------------------
273
- getOpen() {
274
- const p = this._getFocusedPane();
275
- return [...p.panels];
276
- }
277
- /**
278
- * Returns all panels across both panes (top then bottom).
279
- * Use this when you need to know if any panels exist at all.
280
- */
281
- getAllOpen() {
282
- return [...this.topPane.panels, ...this.bottomPane.panels];
283
- }
284
- getActive() {
285
- const p = this._getFocusedPane();
286
- if (p.panels.length === 0)
287
- return null;
288
- return p.panels[p.activeIndex] ?? null;
289
- }
290
- getPanel(panelId) {
291
- return this.topPane.panels.find((panel) => panel.id === panelId)
292
- ?? this.bottomPane.panels.find((panel) => panel.id === panelId)
293
- ?? null;
294
- }
295
- getPaneOf(panelId) {
296
- return this._findPaneOf(panelId);
297
- }
298
- getWorkspaceTabs() {
299
- const focusedPanelId = this.getActivePanel()?.id;
300
- const topTabs = this.topPane.panels.map((panel) => ({
301
- id: panel.id,
302
- name: panel.name,
303
- icon: panel.icon,
304
- pane: 'top',
305
- active: panel.id === focusedPanelId,
306
- focused: panel.id === focusedPanelId,
307
- }));
308
- const bottomTabs = this.bottomPane.panels.map((panel) => ({
309
- id: panel.id,
310
- name: panel.name,
311
- icon: panel.icon,
312
- pane: 'bottom',
313
- active: panel.id === focusedPanelId,
314
- focused: panel.id === focusedPanelId,
315
- }));
316
- return [...topTabs, ...bottomTabs];
317
- }
318
- activateWorkspaceIndex(index) {
319
- const tabs = this.getWorkspaceTabs();
320
- if (index < 0 || index >= tabs.length)
321
- return;
322
- const tab = tabs[index];
323
- this._focusedPane = tab.pane;
324
- if (tab.pane === 'bottom')
325
- this._bottomPaneVisible = true;
326
- this._activateByIdInPane(tab.id, tab.pane);
327
- }
328
- // -------------------------------------------------------------------------
329
- // Visibility
330
- // -------------------------------------------------------------------------
331
- toggle() {
332
- this._visible = !this._visible;
333
- // Auto-open a default panel if toggling visible with nothing open
334
- if (this._visible && this.topPane.panels.length === 0 && this.bottomPane.panels.length === 0) {
335
- const defaultPanel = this._getRegistration('panel-list') ?? this.registry[0];
336
- if (defaultPanel)
337
- this.open(defaultPanel.id);
338
- }
339
- }
340
- show() {
341
- this._visible = true;
342
- }
343
- hide() {
344
- this._visible = false;
345
- }
346
- isVisible() {
347
- return this._visible;
348
- }
349
- // -------------------------------------------------------------------------
350
- // Horizontal split control (left/right)
351
- // -------------------------------------------------------------------------
352
- getSplitRatio() {
353
- return this._splitRatio;
354
- }
355
- setSplitRatio(ratio) {
356
- this._splitRatio = Math.max(0.3, Math.min(0.85, ratio));
357
- }
358
- widenLeft() {
359
- this.setSplitRatio(this._splitRatio + 0.05);
360
- }
361
- widenRight() {
362
- this.setSplitRatio(this._splitRatio - 0.05);
363
- }
364
- getLeftWidth(totalWidth) {
365
- return Math.floor(totalWidth * this._splitRatio);
366
- }
367
- getRightWidth(totalWidth) {
368
- return totalWidth - this.getLeftWidth(totalWidth);
369
- }
370
- // -------------------------------------------------------------------------
371
- // Vertical split control (top/bottom within panel area)
372
- // -------------------------------------------------------------------------
373
- getVerticalSplitRatio() {
374
- return this._verticalSplitRatio;
375
- }
376
- setVerticalSplitRatio(ratio) {
377
- this._verticalSplitRatio = Math.max(0.2, Math.min(0.8, ratio));
378
- }
379
- // -------------------------------------------------------------------------
380
- // Cleanup
381
- // -------------------------------------------------------------------------
382
- destroyAll() {
383
- for (const panel of [...this.topPane.panels, ...this.bottomPane.panels, ...this.retainedPanels.values()]) {
384
- panel.onDestroy();
385
- }
386
- this.topPane = { panels: [], activeIndex: 0 };
387
- this.bottomPane = { panels: [], activeIndex: 0 };
388
- this.retainedPanels.clear();
389
- this.registry = [];
390
- this._focusedPane = 'top';
391
- this._bottomPaneVisible = false;
392
- this._visible = false;
393
- }
394
- // -------------------------------------------------------------------------
395
- // Private helpers
396
- // -------------------------------------------------------------------------
397
- _getPane(which) {
398
- return which === 'top' ? this.topPane : this.bottomPane;
399
- }
400
- _getFocusedPane() {
401
- return this._getPane(this._focusedPane);
402
- }
403
- _findPaneOf(panelId) {
404
- if (this.topPane.panels.some(p => p.id === panelId))
405
- return 'top';
406
- if (this.bottomPane.panels.some(p => p.id === panelId))
407
- return 'bottom';
408
- return null;
409
- }
410
- _moveBetweenPanes(srcPaneName, dstPaneName, panelId) {
411
- const src = this._getPane(srcPaneName);
412
- const dst = this._getPane(dstPaneName);
413
- const id = panelId ?? src.panels[src.activeIndex]?.id;
414
- if (!id)
415
- return;
416
- const index = src.panels.findIndex(p => p.id === id);
417
- if (index < 0)
418
- return;
419
- const panel = src.panels[index];
420
- const wasActive = index === src.activeIndex;
421
- if (wasActive)
422
- panel.onDeactivate();
423
- src.panels.splice(index, 1);
424
- src.activeIndex = Math.min(src.activeIndex, Math.max(0, src.panels.length - 1));
425
- if (wasActive && src.panels.length > 0) {
426
- src.panels[src.activeIndex]?.onActivate();
427
- }
428
- // Deactivate current active in dest
429
- const oldDstActive = dst.panels[dst.activeIndex];
430
- if (oldDstActive)
431
- oldDstActive.onDeactivate();
432
- dst.panels.push(panel);
433
- dst.activeIndex = dst.panels.length - 1;
434
- panel.onActivate();
435
- if (dstPaneName === 'bottom') {
436
- this._bottomPaneVisible = true;
437
- }
438
- this._focusedPane = dstPaneName;
439
- }
440
- _cycleWorkspaceTab(direction) {
441
- const tabs = this.getWorkspaceTabs();
442
- if (tabs.length === 0)
443
- return;
444
- const currentIndex = tabs.findIndex((tab) => tab.focused);
445
- const nextIndex = currentIndex < 0
446
- ? 0
447
- : (currentIndex + direction + tabs.length) % tabs.length;
448
- this.activateWorkspaceIndex(nextIndex);
449
- }
450
- _obtainPanel(panelId) {
451
- const retained = this.retainedPanels.get(panelId);
452
- if (retained) {
453
- this.retainedPanels.delete(panelId);
454
- return retained;
455
- }
456
- const registration = this._getRegistration(panelId);
457
- if (!registration) {
458
- throw new Error(`No panel type registered with id: ${panelId}`);
459
- }
460
- return registration.factory();
461
- }
462
- _getRegistration(panelId) {
463
- return this.registry.find((registration) => registration.id === panelId);
464
- }
465
- _shouldRetain(panelId) {
466
- return this._getRegistration(panelId)?.preload === true;
467
- }
468
- _activateByIdInPane(panelId, which) {
469
- const p = this._getPane(which);
470
- const index = p.panels.findIndex(panel => panel.id === panelId);
471
- if (index >= 0 && index !== p.activeIndex) {
472
- const oldPanel = p.panels[p.activeIndex];
473
- if (oldPanel)
474
- oldPanel.onDeactivate();
475
- p.activeIndex = index;
476
- const newPanel = p.panels[p.activeIndex];
477
- if (newPanel)
478
- newPanel.onActivate();
479
- }
480
- }
481
- }
@@ -1,30 +0,0 @@
1
- import type { Line } from '@pellux/goodvibes-sdk/platform/types/grid';
2
- import type { PanelResourceContract, PanelHealthState } from '@pellux/goodvibes-sdk/platform/runtime/perf/panel-contracts';
3
- export type PanelCategory = 'development' | 'agent' | 'monitoring' | 'session' | 'ai';
4
- export interface Panel {
5
- id: string;
6
- name: string;
7
- icon: string;
8
- category: PanelCategory;
9
- onActivate(): void;
10
- onDeactivate(): void;
11
- onDestroy(): void;
12
- render(width: number, height: number): Line[];
13
- isTransient: boolean;
14
- isPinned: boolean;
15
- needsRender: boolean;
16
- resourceContract?: Readonly<PanelResourceContract>;
17
- healthState?: Readonly<PanelHealthState>;
18
- handleInput?(key: string): boolean;
19
- }
20
- export interface PanelRegistration extends Pick<Panel, 'id' | 'name' | 'icon' | 'category'> {
21
- factory: () => Panel;
22
- description: string;
23
- /**
24
- * Instantiate this panel during bootstrap and retain the instance when it is
25
- * closed so its background data continues to accumulate before the user
26
- * actively opens the workspace.
27
- */
28
- preload?: boolean;
29
- }
30
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/panels/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,2CAA2C,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,6DAA6D,CAAC;AAE3H,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,GAAG,IAAI,CAAC;AAEtF,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,aAAa,CAAC;IAGxB,UAAU,IAAI,IAAI,CAAC;IACnB,YAAY,IAAI,IAAI,CAAC;IACrB,SAAS,IAAI,IAAI,CAAC;IAGlB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,CAAC;IAG9C,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IAGrB,gBAAgB,CAAC,EAAE,QAAQ,CAAC,qBAAqB,CAAC,CAAC;IAGnD,WAAW,CAAC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAGzC,WAAW,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACpC;AAED,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;IACzF,OAAO,EAAE,MAAM,KAAK,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
@@ -1 +0,0 @@
1
- export {};