@danypops/pi-packed 0.9.0 → 0.10.0

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.
@@ -149,15 +149,16 @@ function renderDiscoverPanel(ctx: ExtensionCommandContext, natives: Natives): Pr
149
149
  },
150
150
  };
151
151
 
152
+ const border = () => new DynamicBorder((s) => theme.fg("border", s));
152
153
  const container = new Container();
153
154
  container.addChild(new Spacer(1));
154
- container.addChild(new DynamicBorder());
155
+ container.addChild(border());
155
156
  container.addChild(new Spacer(1));
156
157
  container.addChild(header);
157
158
  container.addChild(new Spacer(1));
158
159
  container.addChild(list);
159
160
  container.addChild(new Spacer(1));
160
- container.addChild(new DynamicBorder());
161
+ container.addChild(border());
161
162
 
162
163
  return {
163
164
  render: (width: number) => container.render(width),
@@ -190,15 +190,16 @@ function renderConfig(ctx: ExtensionCommandContext, data: { global: PackageResou
190
190
  },
191
191
  };
192
192
 
193
+ const border = () => new DynamicBorder((s) => theme.fg("border", s));
193
194
  const container = new Container();
194
195
  container.addChild(new Spacer(1));
195
- container.addChild(new DynamicBorder());
196
+ container.addChild(border());
196
197
  container.addChild(new Spacer(1));
197
198
  container.addChild(header);
198
199
  container.addChild(new Spacer(1));
199
200
  container.addChild(list);
200
201
  container.addChild(new Spacer(1));
201
- container.addChild(new DynamicBorder());
202
+ container.addChild(border());
202
203
 
203
204
  return {
204
205
  render: (width: number) => container.render(width),
@@ -14,7 +14,7 @@
14
14
  import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
15
15
  import { DynamicBorder, rawKeyHint } from "@earendil-works/pi-coding-agent";
16
16
  import { Container, Input, Spacer, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
17
- import { Menu, type MenuItem } from "malevich-tui-components";
17
+ import { Menu, ProgressBar, type MenuItem } from "malevich-tui-components";
18
18
  import { filterRows, mergeRows, nextMode, visibleRows } from "./model.js";
19
19
  import type { Row, ViewMode } from "./model.js";
20
20
  import type { Natives, PackageResources } from "./packed.js";
@@ -86,6 +86,57 @@ export async function applyPackageChoice(
86
86
  return "cancelled";
87
87
  }
88
88
 
89
+ interface UpdateAllResult { changed: number; failedNames: string[]; }
90
+
91
+ /** Floats a live progress bar over the still-open panel while the batch
92
+ * runs sequentially -- the lazy.nvim-style "Updating N package(s)" window,
93
+ * instead of one static toast with no visible progress until it's all
94
+ * done. Resolves on its own once the last package finishes; nothing the
95
+ * user presses closes it early. */
96
+ async function runUpdatesWithProgress(
97
+ outdated: Row[],
98
+ natives: Natives,
99
+ approved: boolean | undefined,
100
+ ctx: ExtensionCommandContext,
101
+ ): Promise<UpdateAllResult> {
102
+ return ctx.ui.custom<UpdateAllResult>(
103
+ (tui, theme, _kb, done) => {
104
+ const bar = new ProgressBar({ value: 0, max: outdated.length, label: `${outdated[0]?.name ?? ""} (1/${outdated.length})`, style: (s) => theme.fg("accent", s) });
105
+ const border = () => new DynamicBorder((s) => theme.fg("border", s));
106
+ const container = new Container();
107
+ container.addChild(new Spacer(1));
108
+ container.addChild(border());
109
+ container.addChild({ invalidate() {}, render: (_width: number) => [theme.bold("Updating packages")] });
110
+ container.addChild(new Spacer(1));
111
+ container.addChild(bar);
112
+ container.addChild(new Spacer(1));
113
+ container.addChild(border());
114
+
115
+ void (async () => {
116
+ let changed = 0;
117
+ const failedNames: string[] = [];
118
+ for (let i = 0; i < outdated.length; i++) {
119
+ const row = outdated[i]!;
120
+ bar.setLabel(`${row.name} (${i + 1}/${outdated.length})`);
121
+ tui.requestRender();
122
+ try {
123
+ const outcome = await natives.update(`npm:${row.name}`, approved);
124
+ if (outcome.reloadRequired) changed += 1;
125
+ } catch (e) {
126
+ failedNames.push(`${row.name}: ${e instanceof Error ? e.message : e}`);
127
+ }
128
+ bar.setValue(i + 1);
129
+ tui.requestRender();
130
+ }
131
+ done({ changed, failedNames });
132
+ })();
133
+
134
+ return { render: (width: number) => container.render(width), invalidate: () => container.invalidate(), handleInput() {} };
135
+ },
136
+ { overlay: true, overlayOptions: { width: 50, anchor: "center" } },
137
+ );
138
+ }
139
+
89
140
  /** U -- update every outdated row with one combined approval and one
90
141
  * reload, instead of applyPackageChoice's own per-call reload (which
91
142
  * would end the session after the first successful update). */
@@ -105,23 +156,13 @@ export async function applyUpdateAll(rows: Row[], natives: Natives, ctx: Extensi
105
156
  ctx.ui.notify(approval.message ?? "update denied", "warning");
106
157
  return "cancelled";
107
158
  }
108
- ctx.ui.notify(`Updating ${outdated.length} package(s)…`, "info");
109
- let changed = 0;
110
- let failed = 0;
111
- for (const row of outdated) {
112
- try {
113
- const outcome = await natives.update(`npm:${row.name}`, approval.approved);
114
- if (outcome.reloadRequired) changed += 1;
115
- } catch (e) {
116
- failed += 1;
117
- ctx.ui.notify(`${row.name} update failed: ${e instanceof Error ? e.message : e}`, "error");
118
- }
119
- }
159
+ const { changed, failedNames } = await runUpdatesWithProgress(outdated, natives, approval.approved, ctx);
160
+ for (const failure of failedNames) ctx.ui.notify(`update failed: ${failure}`, "error");
120
161
  if (changed === 0) {
121
- ctx.ui.notify(failed > 0 ? `No packages updated; ${failed} failed.` : "All packages already up to date.", failed > 0 ? "warning" : "info");
122
- return failed > 0 ? "cancelled" : "unchanged";
162
+ ctx.ui.notify(failedNames.length > 0 ? `No packages updated; ${failedNames.length} failed.` : "All packages already up to date.", failedNames.length > 0 ? "warning" : "info");
163
+ return failedNames.length > 0 ? "cancelled" : "unchanged";
123
164
  }
124
- ctx.ui.notify(`Updated ${changed} package(s)${failed > 0 ? `, ${failed} failed` : ""}; reloading Pi resources.`, "info");
165
+ ctx.ui.notify(`Updated ${changed} package(s)${failedNames.length > 0 ? `, ${failedNames.length} failed` : ""}; reloading Pi resources.`, "info");
125
166
  await ctx.reload();
126
167
  return "changed";
127
168
  }
@@ -329,15 +370,16 @@ function renderPanel(ctx: ExtensionCommandContext, rows: Row[]): Promise<PanelAc
329
370
  },
330
371
  };
331
372
 
373
+ const border = () => new DynamicBorder((s) => theme.fg("border", s));
332
374
  const container = new Container();
333
375
  container.addChild(new Spacer(1));
334
- container.addChild(new DynamicBorder());
376
+ container.addChild(border());
335
377
  container.addChild(new Spacer(1));
336
378
  container.addChild(header);
337
379
  container.addChild(new Spacer(1));
338
380
  container.addChild(list);
339
381
  container.addChild(new Spacer(1));
340
- container.addChild(new DynamicBorder());
382
+ container.addChild(border());
341
383
 
342
384
  return {
343
385
  render: (width: number) => container.render(width),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danypops/pi-packed",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Pi package tools, commands, profiles, and TUI for the Packed daemon",
5
5
  "type": "module",
6
6
  "keywords": ["pi-package"],