pi-powerline 0.6.2 → 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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ # [0.7.0](https://github.com/jwu/pi-powerline/compare/v0.6.3...v0.7.0) (2026-05-24)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **auto-format:** update pi import package ([3d67f66](https://github.com/jwu/pi-powerline/commit/3d67f6650be48de18b90f8c4582609f691e60cd3))
7
+
8
+
9
+ ### Features
10
+
11
+ * **header:** tag path packages distinctly ([471c409](https://github.com/jwu/pi-powerline/commit/471c409457de296ff94a96812e9706938981e5aa))
12
+
13
+ ## [0.6.3](https://github.com/jwu/pi-powerline/compare/v0.6.2...v0.6.3) (2026-05-24)
14
+
15
+
16
+ ### Bug Fixes
17
+
18
+ * show auto-discovered extensions in header ([e2b187f](https://github.com/jwu/pi-powerline/commit/e2b187fdcf840c741be3be3bf8ad4c95612e9fc2))
19
+
1
20
  ## [0.6.2](https://github.com/jwu/pi-powerline/compare/v0.6.1...v0.6.2) (2026-05-22)
2
21
 
3
22
 
@@ -450,13 +450,19 @@ function resolvePackageDir(source: string, cwd: string, home = getHomeDir()): st
450
450
 
451
451
  // ── getPackages: name+version from each configured package ──
452
452
 
453
+ function getPackageScopeTag(source: string, scope: PackageSource['scope']): string {
454
+ const isPathSource = !source.startsWith('npm:');
455
+ if (scope === 'project') return isPathSource ? ' [lp]' : ' [l]';
456
+ return isPathSource ? ' [gp]' : ' [g]';
457
+ }
458
+
453
459
  function getPackages(cwd: string, home = getHomeDir()): string[] {
454
460
  const sources = readPackageSources(cwd, home);
455
461
  const results: string[] = [];
456
462
 
457
463
  for (const { source, scope } of sources) {
458
464
  const pkgDir = resolvePackageDir(source, cwd, home);
459
- const scopeTag = scope === 'project' ? ' [l]' : ' [g]';
465
+ const scopeTag = getPackageScopeTag(source, scope);
460
466
  if (!pkgDir) {
461
467
  // fallback: show npm package name or raw source
462
468
  const name = source.startsWith('npm:') ? source.slice(4) : source;
@@ -470,7 +476,7 @@ function getPackages(cwd: string, home = getHomeDir()): string[] {
470
476
  return results.sort((a, b) => a.localeCompare(b));
471
477
  }
472
478
 
473
- // ── getExtensionItems: scan .ts files from settings.json extensions dirs ──
479
+ // ── getExtensionItems: scan configured and auto-discovered extension paths ──
474
480
 
475
481
  function readExtensionSources(cwd: string, home = getHomeDir()): ExtensionSource[] {
476
482
  const projectBaseDir = join(cwd, '.pi');
@@ -490,37 +496,59 @@ function resolveSettingsSource(source: string, baseDir: string, home = getHomeDi
490
496
  : resolve(baseDir, source);
491
497
  }
492
498
 
493
- function getExtensionItems(cwd: string, home = getHomeDir()): string[] {
494
- const results: string[] = [];
495
- const seenFiles = new Set<string>();
499
+ const EXTENSION_INDEX_FILES = ['index.ts', 'index.js'];
500
+
501
+ function isExtensionFile(filePath: string): boolean {
502
+ return filePath.endsWith('.ts') || filePath.endsWith('.js');
503
+ }
496
504
 
497
- function addFile(filePath: string) {
498
- const key = resolve(filePath);
499
- if (seenFiles.has(key)) return;
500
- seenFiles.add(key);
501
- results.push(formatDisplayPath(cwd, filePath));
505
+ function safeStat(path: string) {
506
+ try {
507
+ return statSync(path);
508
+ } catch {
509
+ return undefined;
502
510
  }
511
+ }
503
512
 
504
- for (const { source, baseDir } of readExtensionSources(cwd, home)) {
505
- const resolved = resolveSettingsSource(source, baseDir, home);
513
+ function listExtensionFiles(path: string): string[] {
514
+ const s = safeStat(path);
515
+ if (!s) return [];
516
+ if (s.isFile()) return isExtensionFile(path) ? [path] : [];
517
+ if (!s.isDirectory()) return [];
506
518
 
507
- if (!existsSync(resolved)) continue;
519
+ return readdirSync(path)
520
+ .sort()
521
+ .flatMap((entry) => {
522
+ const entryPath = join(path, entry);
523
+ const entryStat = safeStat(entryPath);
524
+ if (entryStat?.isFile() && isExtensionFile(entry)) return [entryPath];
525
+ if (!entryStat?.isDirectory()) return [];
508
526
 
509
- try {
510
- const s = statSync(resolved);
511
- if (s.isDirectory()) {
512
- for (const f of readdirSync(resolved).sort()) {
513
- if (f.endsWith('.ts')) addFile(join(resolved, f));
514
- }
515
- } else {
516
- addFile(resolved);
517
- }
518
- } catch {
519
- // ignore unreadable paths
520
- }
521
- }
527
+ return EXTENSION_INDEX_FILES.map((file) => join(entryPath, file)).filter((indexPath) =>
528
+ safeStat(indexPath)?.isFile(),
529
+ );
530
+ });
531
+ }
532
+
533
+ function getExtensionItems(cwd: string, home = getHomeDir()): string[] {
534
+ const sources = [
535
+ ...readExtensionSources(cwd, home).map(({ source, baseDir }) =>
536
+ resolveSettingsSource(source, baseDir, home),
537
+ ),
538
+ join(cwd, '.pi', 'extensions'),
539
+ join(home, '.pi', 'agent', 'extensions'),
540
+ ];
541
+ const seen = new Set<string>();
522
542
 
523
- return results;
543
+ return sources
544
+ .flatMap(listExtensionFiles)
545
+ .filter((filePath) => {
546
+ const key = resolve(filePath);
547
+ if (seen.has(key)) return false;
548
+ seen.add(key);
549
+ return true;
550
+ })
551
+ .map((filePath) => formatDisplayPath(cwd, filePath));
524
552
  }
525
553
 
526
554
  function shouldShowHeaderInfo(ctx: ExtensionContext, reason: SessionStartEvent['reason']): boolean {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-powerline",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "description": "Powerline-style UI extensions for pi coding agent (custom editor, breadcrumb, footer, header)",
5
5
  "homepage": "https://github.com/jwu/pi-powerline#readme",
6
6
  "repository": {