@aliou/pi-dev-kit 0.6.4 → 0.7.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.
@@ -4,13 +4,11 @@ import { ToolBody, ToolCallHeader, ToolFooter } from "@aliou/pi-utils-ui";
4
4
  import type {
5
5
  AgentToolResult,
6
6
  ExtensionAPI,
7
- ExtensionContext,
8
7
  Theme,
9
- ToolRenderResultOptions,
10
- } from "@mariozechner/pi-coding-agent";
11
- import { keyHint, VERSION } from "@mariozechner/pi-coding-agent";
12
- import { Text } from "@mariozechner/pi-tui";
13
- import { type Static, Type } from "@sinclair/typebox";
8
+ } from "@earendil-works/pi-coding-agent";
9
+ import { defineTool, keyHint, VERSION } from "@earendil-works/pi-coding-agent";
10
+ import { Text } from "@earendil-works/pi-tui";
11
+ import { type Static, Type } from "typebox";
14
12
  import { findPiInstallation } from "./utils";
15
13
 
16
14
  const GITHUB_RAW_CHANGELOG_URL =
@@ -32,7 +30,7 @@ const ChangelogParamsSchema = Type.Object({
32
30
  type ChangelogParams = Static<typeof ChangelogParamsSchema>;
33
31
 
34
32
  const ChangelogVersionsParamsSchema = Type.Object({});
35
- type ChangelogVersionsParams = Record<string, never>;
33
+ type ChangelogVersionsParams = Static<typeof ChangelogVersionsParamsSchema>;
36
34
 
37
35
  // ---------------------------------------------------------------------------
38
36
  // Types
@@ -200,6 +198,23 @@ const COLLAPSED_LINES = 8;
200
198
  // Render helpers
201
199
  // ---------------------------------------------------------------------------
202
200
 
201
+ function renderChangelogCall(args: ChangelogParams, theme: Theme) {
202
+ return new ToolCallHeader(
203
+ {
204
+ toolName: "Pi Changelog",
205
+ mainArg: args.version ? `v${args.version}` : "latest",
206
+ },
207
+ theme,
208
+ );
209
+ }
210
+
211
+ function renderChangelogVersionsCall(
212
+ _args: ChangelogVersionsParams,
213
+ theme: Theme,
214
+ ) {
215
+ return new ToolCallHeader({ toolName: "Pi Changelog Versions" }, theme);
216
+ }
217
+
203
218
  function renderChangelogContent(
204
219
  content: string,
205
220
  theme: Theme,
@@ -235,250 +250,242 @@ function renderChangelogContent(
235
250
  // pi_changelog
236
251
  // ---------------------------------------------------------------------------
237
252
 
238
- export function setupChangelogTool(pi: ExtensionAPI) {
239
- pi.registerTool<typeof ChangelogParamsSchema, ChangelogDetails>({
240
- name: "pi_changelog",
241
- label: "Pi Changelog",
242
- description:
243
- "Get changelog entry for a Pi version. Returns latest by default. Use pi_changelog_versions to list all available versions.",
244
- promptSnippet: `pi_changelog version="1.2.3" // Get changelog for specific version
253
+ const changelogTool = defineTool({
254
+ name: "pi_changelog",
255
+ label: "Pi Changelog",
256
+ description:
257
+ "Get changelog entry for a Pi version. Returns latest by default. Use pi_changelog_versions to list all available versions.",
258
+ promptSnippet: `pi_changelog version="1.2.3" // Get changelog for specific version
245
259
  pi_changelog // Get latest changelog`,
246
- promptGuidelines: [
247
- "Use pi_changelog to check what's new in a Pi version",
248
- "Use pi_changelog_versions first to list available versions",
249
- "Leave version empty for pi_changelog to get the latest changelog",
250
- ],
251
-
252
- parameters: ChangelogParamsSchema,
253
-
254
- async execute(
255
- _toolCallId: string,
256
- params: ChangelogParams,
257
- _signal: AbortSignal | undefined,
258
- _onUpdate: unknown,
259
- _ctx: ExtensionContext,
260
- ): Promise<AgentToolResult<ChangelogDetails>> {
261
- // Newer than installed -> fetch from GitHub
262
- if (params.version && isNewerThanInstalled(params.version)) {
263
- const githubContent = await fetchGithubChangelog();
264
- const changelog = findChangelogEntry(githubContent, params.version);
265
-
266
- const message = `Changelog for ${changelog.version} (from GitHub)\n\n## ${changelog.version}\n\n${changelog.content}`;
267
- return {
268
- content: [{ type: "text", text: message }],
269
- details: {
270
- changelog,
271
- source: "github",
272
- },
273
- };
274
- }
275
-
276
- // Local
277
- const local = readLocalChangelog();
278
- const changelog = findChangelogEntry(local.content, params.version);
279
-
280
- const message = `Changelog for ${changelog.version}\n\n## ${changelog.version}\n\n${changelog.content}`;
260
+ promptGuidelines: [
261
+ "Use pi_changelog to check what's new in a Pi version",
262
+ "Use pi_changelog_versions first to list available versions",
263
+ "Leave version empty for pi_changelog to get the latest changelog",
264
+ ],
265
+
266
+ parameters: ChangelogParamsSchema,
267
+
268
+ async execute(
269
+ _toolCallId,
270
+ params,
271
+ _signal,
272
+ _onUpdate,
273
+ _ctx,
274
+ ): Promise<AgentToolResult<ChangelogDetails>> {
275
+ // Newer than installed -> fetch from GitHub
276
+ if (params.version && isNewerThanInstalled(params.version)) {
277
+ const githubContent = await fetchGithubChangelog();
278
+ const changelog = findChangelogEntry(githubContent, params.version);
279
+
280
+ const message = `Changelog for ${changelog.version} (from GitHub)\n\n## ${changelog.version}\n\n${changelog.content}`;
281
281
  return {
282
282
  content: [{ type: "text", text: message }],
283
283
  details: {
284
284
  changelog,
285
- source: "local",
285
+ source: "github",
286
286
  },
287
287
  };
288
- },
288
+ }
289
289
 
290
- renderCall(args: ChangelogParams, theme: Theme) {
291
- return new ToolCallHeader(
292
- {
293
- toolName: "Pi Changelog",
294
- mainArg: args.version ? `v${args.version}` : "latest",
295
- },
296
- theme,
290
+ // Local
291
+ const local = readLocalChangelog();
292
+ const changelog = findChangelogEntry(local.content, params.version);
293
+
294
+ const message = `Changelog for ${changelog.version}\n\n## ${changelog.version}\n\n${changelog.content}`;
295
+ return {
296
+ content: [{ type: "text", text: message }],
297
+ details: {
298
+ changelog,
299
+ source: "local",
300
+ },
301
+ };
302
+ },
303
+
304
+ renderCall(args, theme) {
305
+ return renderChangelogCall(args, theme);
306
+ },
307
+
308
+ renderResult(result, options, theme) {
309
+ if (options.isPartial) {
310
+ return new Text(theme.fg("dim", "Pi Changelog: loading..."), 0, 0);
311
+ }
312
+
313
+ const { details } = result;
314
+
315
+ // Check for missing expected fields to detect errors
316
+ if (!details?.changelog) {
317
+ const text = result.content[0];
318
+ return new Text(
319
+ text?.type === "text" && text.text ? text.text : "No result",
320
+ 0,
321
+ 0,
297
322
  );
298
- },
323
+ }
299
324
 
300
- renderResult(
301
- result: AgentToolResult<ChangelogDetails>,
302
- options: ToolRenderResultOptions,
303
- theme: Theme,
304
- ) {
305
- const { details } = result;
306
-
307
- // Check for missing expected fields to detect errors
308
- if (!details?.changelog) {
309
- const text = result.content[0];
310
- return new Text(
311
- text?.type === "text" && text.text ? text.text : "No result",
312
- 0,
313
- 0,
314
- );
315
- }
325
+ const fields: Array<
326
+ { label: string; value: string; showCollapsed?: boolean } | Text
327
+ > = [];
316
328
 
317
- const fields: Array<
318
- { label: string; value: string; showCollapsed?: boolean } | Text
319
- > = [];
320
-
321
- const lines: string[] = [];
322
-
323
- if (options.expanded) {
324
- // Expanded view: show full changelog content
325
- lines.push(
326
- theme.fg(
327
- "accent",
328
- theme.bold(`Version: ${details.changelog.version}`),
329
- ),
330
- "",
331
- );
332
- lines.push(...renderChangelogContent(details.changelog.content, theme));
333
- fields.push(new Text(lines.join("\n"), 0, 0));
334
- } else {
335
- // Collapsed view: show version + first few lines of changelog + expand hint
336
- lines.push(
337
- theme.fg(
338
- "accent",
339
- theme.bold(`Version: ${details.changelog.version}`),
340
- ),
341
- "",
342
- );
343
- lines.push(
344
- ...renderChangelogContent(
345
- details.changelog.content,
346
- theme,
347
- COLLAPSED_LINES,
348
- ),
349
- );
350
- lines.push(
351
- "",
352
- theme.fg("muted", `${keyHint("app.tools.expand", "to expand")}`),
353
- );
354
- fields.push(new Text(lines.join("\n"), 0, 0));
355
- }
329
+ const lines: string[] = [];
356
330
 
357
- // Footer: show source tag only
358
- const footer = new ToolFooter(theme, {
359
- items: [
360
- {
361
- label: "source",
362
- value: details.source ?? "local",
363
- tone: "accent",
364
- },
365
- ],
366
- });
367
-
368
- return new ToolBody(
369
- {
370
- fields,
371
- footer,
372
- },
373
- options,
374
- theme,
331
+ if (options.expanded) {
332
+ // Expanded view: show full changelog content
333
+ lines.push(
334
+ theme.fg("accent", theme.bold(`Version: ${details.changelog.version}`)),
335
+ "",
375
336
  );
376
- },
377
- });
378
-
379
- // -------------------------------------------------------------------------
380
- // pi_changelog_versions
381
- // -------------------------------------------------------------------------
382
-
383
- pi.registerTool<
384
- typeof ChangelogVersionsParamsSchema,
385
- ChangelogVersionsDetails
386
- >({
387
- name: "pi_changelog_versions",
388
- label: "Pi Changelog Versions",
389
- description: "List all available Pi changelog versions",
390
- promptSnippet: `pi_changelog_versions // List all available versions`,
391
-
392
- parameters: ChangelogVersionsParamsSchema,
393
-
394
- async execute(
395
- _toolCallId: string,
396
- _params: ChangelogVersionsParams,
397
- _signal: AbortSignal | undefined,
398
- _onUpdate: unknown,
399
- _ctx: ExtensionContext,
400
- ): Promise<AgentToolResult<ChangelogVersionsDetails>> {
401
- const local = readLocalChangelog();
402
- const { entries } = parseChangelogEntries(local.content);
403
-
404
- if (entries.length === 0) {
405
- throw new Error("No version entries found in changelog");
406
- }
407
-
408
- const versions = entries.map((e) => e.version);
409
- const message = `${versions.length} versions available:\n${versions.join(", ")}`;
337
+ lines.push(...renderChangelogContent(details.changelog.content, theme));
338
+ fields.push(new Text(lines.join("\n"), 0, 0));
339
+ } else {
340
+ // Collapsed view: show version + first few lines of changelog + expand hint
341
+ lines.push(
342
+ theme.fg("accent", theme.bold(`Version: ${details.changelog.version}`)),
343
+ "",
344
+ );
345
+ lines.push(
346
+ ...renderChangelogContent(
347
+ details.changelog.content,
348
+ theme,
349
+ COLLAPSED_LINES,
350
+ ),
351
+ );
352
+ lines.push(
353
+ "",
354
+ theme.fg("muted", `${keyHint("app.tools.expand", "to expand")}`),
355
+ );
356
+ fields.push(new Text(lines.join("\n"), 0, 0));
357
+ }
410
358
 
411
- return {
412
- content: [{ type: "text", text: message }],
413
- details: {
414
- versions,
415
- source: "local",
359
+ // Footer: show source tag only
360
+ const footer = new ToolFooter(theme, {
361
+ items: [
362
+ {
363
+ label: "source",
364
+ value: details.source ?? "local",
365
+ tone: "accent",
416
366
  },
417
- };
418
- },
367
+ ],
368
+ });
369
+
370
+ return new ToolBody(
371
+ {
372
+ fields,
373
+ footer,
374
+ },
375
+ options,
376
+ theme,
377
+ );
378
+ },
379
+ });
419
380
 
420
- renderCall(_args: ChangelogVersionsParams, theme: Theme) {
421
- return new ToolCallHeader({ toolName: "Pi Changelog Versions" }, theme);
422
- },
381
+ // -------------------------------------------------------------------------
382
+ // pi_changelog_versions
383
+ // -------------------------------------------------------------------------
384
+
385
+ const changelogVersionsTool = defineTool({
386
+ name: "pi_changelog_versions",
387
+ label: "Pi Changelog Versions",
388
+ description: "List all available Pi changelog versions",
389
+ promptSnippet: `pi_changelog_versions // List all available versions`,
390
+
391
+ parameters: ChangelogVersionsParamsSchema,
392
+
393
+ async execute(
394
+ _toolCallId,
395
+ _params,
396
+ _signal,
397
+ _onUpdate,
398
+ _ctx,
399
+ ): Promise<AgentToolResult<ChangelogVersionsDetails>> {
400
+ const local = readLocalChangelog();
401
+ const { entries } = parseChangelogEntries(local.content);
402
+
403
+ if (entries.length === 0) {
404
+ throw new Error("No version entries found in changelog");
405
+ }
423
406
 
424
- renderResult(
425
- result: AgentToolResult<ChangelogVersionsDetails>,
426
- options: ToolRenderResultOptions,
427
- theme: Theme,
428
- ) {
429
- const { details } = result;
430
-
431
- // Check for missing expected fields to detect errors
432
- if (!details?.versions) {
433
- const text = result.content[0];
434
- return new Text(
435
- text?.type === "text" && text.text ? text.text : "No result",
436
- 0,
437
- 0,
438
- );
439
- }
407
+ const versions = entries.map((e) => e.version);
408
+ const message = `${versions.length} versions available:\n${versions.join(", ")}`;
409
+
410
+ return {
411
+ content: [{ type: "text", text: message }],
412
+ details: {
413
+ versions,
414
+ source: "local",
415
+ },
416
+ };
417
+ },
418
+
419
+ renderCall(args, theme) {
420
+ return renderChangelogVersionsCall(args, theme);
421
+ },
422
+
423
+ renderResult(result, options, theme) {
424
+ if (options.isPartial) {
425
+ return new Text(
426
+ theme.fg("dim", "Pi Changelog Versions: loading..."),
427
+ 0,
428
+ 0,
429
+ );
430
+ }
440
431
 
441
- const fields: Array<
442
- { label: string; value: string; showCollapsed?: boolean } | Text
443
- > = [];
432
+ const { details } = result;
444
433
 
445
- const lines: string[] = [
446
- theme.fg("accent", `${details.versions.length} versions available:`),
447
- "",
448
- ];
449
- const cols = 6;
450
- const maxLen = Math.max(
451
- ...details.versions.map((version) => version.length),
434
+ // Check for missing expected fields to detect errors
435
+ if (!details?.versions) {
436
+ const text = result.content[0];
437
+ return new Text(
438
+ text?.type === "text" && text.text ? text.text : "No result",
439
+ 0,
440
+ 0,
452
441
  );
453
- const colWidth = maxLen + 2;
454
- for (let i = 0; i < details.versions.length; i += cols) {
455
- const row = details.versions
456
- .slice(i, i + cols)
457
- .map((version) => version.padEnd(colWidth))
458
- .join("");
459
- lines.push(theme.fg("dim", row));
460
- }
461
- fields.push(new Text(lines.join("\n"), 0, 0));
442
+ }
462
443
 
463
- // Footer: just show version count
464
- const footer = new ToolFooter(theme, {
465
- items: [
466
- {
467
- label: "count",
468
- value: String(details.versions.length),
469
- tone: "accent",
470
- },
471
- ],
472
- });
473
-
474
- return new ToolBody(
444
+ const fields: Array<
445
+ { label: string; value: string; showCollapsed?: boolean } | Text
446
+ > = [];
447
+
448
+ const lines: string[] = [
449
+ theme.fg("accent", `${details.versions.length} versions available:`),
450
+ "",
451
+ ];
452
+ const cols = 6;
453
+ const maxLen = Math.max(
454
+ ...details.versions.map((version) => version.length),
455
+ );
456
+ const colWidth = maxLen + 2;
457
+ for (let i = 0; i < details.versions.length; i += cols) {
458
+ const row = details.versions
459
+ .slice(i, i + cols)
460
+ .map((version) => version.padEnd(colWidth))
461
+ .join("");
462
+ lines.push(theme.fg("dim", row));
463
+ }
464
+ fields.push(new Text(lines.join("\n"), 0, 0));
465
+
466
+ // Footer: just show version count
467
+ const footer = new ToolFooter(theme, {
468
+ items: [
475
469
  {
476
- fields,
477
- footer,
470
+ label: "count",
471
+ value: String(details.versions.length),
472
+ tone: "accent",
478
473
  },
479
- options,
480
- theme,
481
- );
482
- },
483
- });
474
+ ],
475
+ });
476
+
477
+ return new ToolBody(
478
+ {
479
+ fields,
480
+ footer,
481
+ },
482
+ options,
483
+ theme,
484
+ );
485
+ },
486
+ });
487
+
488
+ export function setupChangelogTool(pi: ExtensionAPI) {
489
+ pi.registerTool(changelogTool);
490
+ pi.registerTool(changelogVersionsTool);
484
491
  }