pi-spark 0.10.0 → 0.10.1

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.
@@ -16,6 +16,9 @@ const DEFAULT_THINKING_LEVEL: ModelThinkingLevel = "medium";
16
16
  /** Maximum number of models returned per list call; byte size is unrestricted. */
17
17
  const LIST_MAX_LINES = 200;
18
18
 
19
+ /** Maximum number of model rows shown when the result is collapsed. */
20
+ const COLLAPSED_MAX_ROWS = 10;
21
+
19
22
  type ModelMetadata = Omit<Model<Api>, "headers" | "compat"> & {
20
23
  thinkingLevels: ModelThinkingLevel[];
21
24
  defaultThinkingLevel: ModelThinkingLevel;
@@ -59,6 +62,16 @@ function formatPrice(value: number): string {
59
62
  return String(parseFloat(value.toFixed(2)));
60
63
  }
61
64
 
65
+ /** Notice line describing truncation or remaining pages, shared by the text result and the TUI. */
66
+ function formatListNotice(truncated: boolean, startIndex: number, endDisplay: number, total: number): string | undefined {
67
+ const nextOffset = endDisplay + 1;
68
+
69
+ if (truncated) return `[Truncated: showing models ${startIndex + 1}-${endDisplay} of ${total}. Use offset=${nextOffset} to continue.]`;
70
+ if (endDisplay < total) return `[${total - endDisplay} more models in list. Use offset=${nextOffset} to continue.]`;
71
+
72
+ return undefined;
73
+ }
74
+
62
75
  export default function (pi: ExtensionAPI) {
63
76
  pi.on("session_start", (_event, ctx) => {
64
77
  const config = loadConfig(ctx, "models");
@@ -162,15 +175,27 @@ export default function (pi: ExtensionAPI) {
162
175
  const models = details.models ?? [];
163
176
  const total = details.total ?? models.length;
164
177
 
165
- if (models.length > 0 && expanded) {
166
- addRows(models.map((model) => toModelRow(model)));
178
+ if (models.length > 0) {
179
+ const maxRows = expanded ? models.length : Math.min(models.length, COLLAPSED_MAX_ROWS);
180
+ addRows(models.slice(0, maxRows).map((model) => toModelRow(model)));
181
+
182
+ const hiddenRows = models.length - maxRows;
183
+ if (hiddenRows > 0) container.addChild(new Text(theme.fg("dim", `... (${hiddenRows} more, ${keyText("app.tools.expand")} to expand)`), 0, 0));
167
184
  container.addChild(new Spacer(1));
168
185
  }
169
186
 
170
- const summary = total > 0 ? `${models.length !== total ? `${models.length} of ` : ""}${total} ${filtered ? "matched " : ""}model${total === 1 ? "" : "s"} listed.` : `No models ${filtered ? "matched" : "found"}.`;
171
- const truncatedHint = details.truncation?.truncated ? theme.fg("warning", " (truncated)") : "";
172
- const expandHint = models.length > 0 && !expanded ? theme.fg("dim", ` (${keyText("app.tools.expand")} to expand)`) : "";
173
- container.addChild(new Text(theme.fg("muted", summary) + truncatedHint + expandHint, 0, 0));
187
+ if (details.truncation?.truncated) {
188
+ const startIndex = context.args.offset ? Math.max(0, context.args.offset - 1) : 0;
189
+ const endDisplay = startIndex + models.length;
190
+ const notice = formatListNotice(true, startIndex, endDisplay, total);
191
+ if (notice) {
192
+ container.addChild(new Text(theme.fg("warning", notice), 0, 0));
193
+ container.addChild(new Spacer(1));
194
+ }
195
+ }
196
+
197
+ const summary = `${models.length !== total ? `${models.length} of ` : ""}${total} ${filtered ? "matched " : ""}model${total === 1 ? "" : "s"} listed.`;
198
+ container.addChild(new Text(theme.fg("muted", total > 0 ? summary : `No models ${filtered ? "matched" : "found"}.`), 0, 0));
174
199
 
175
200
  return container;
176
201
  },
@@ -200,8 +225,7 @@ export default function (pi: ExtensionAPI) {
200
225
  }
201
226
  }
202
227
 
203
- const models = ctx.modelRegistry.getAll()
204
- .map((model) => toMetadata(model, ctx.modelRegistry.hasConfiguredAuth(model)));
228
+ const models = ctx.modelRegistry.getAll().map((model) => toMetadata(model, ctx.modelRegistry.hasConfiguredAuth(model)));
205
229
  const matched = listQuery ? filter(listQuery, models) : models;
206
230
  const total = matched.length;
207
231
 
@@ -229,14 +253,10 @@ export default function (pi: ExtensionAPI) {
229
253
 
230
254
  const delivered = truncation.truncated ? selected.slice(0, truncation.outputLines) : selected;
231
255
  const endDisplay = startIndex + delivered.length;
232
- const nextOffset = endDisplay + 1;
233
256
 
234
257
  let text = truncation.content;
235
- if (truncation.truncated) {
236
- text += `\n\n[Truncated: showing models ${startIndex + 1}-${endDisplay} of ${total}. Use offset=${nextOffset} to continue.]`;
237
- } else if (endDisplay < total) {
238
- text += `\n\n[${total - endDisplay} more models in list. Use offset=${nextOffset} to continue.]`;
239
- }
258
+ const notice = formatListNotice(truncation.truncated, startIndex, endDisplay, total);
259
+ if (notice) text += `\n\n${notice}`;
240
260
 
241
261
  return {
242
262
  content: [{ type: "text", text }],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-spark",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "A small, opinionated collection of pi extensions",
5
5
  "keywords": [
6
6
  "pi-coding-agent",