@lebronj/pi-suite 0.1.15 → 0.1.16

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/README.md CHANGED
@@ -15,7 +15,7 @@ pi install npm:pi-web-access
15
15
  Or use the bootstrap script to install Pi, configure the team OpenAI-compatible endpoint, install this suite, and set up Bun + qmd for memory search:
16
16
 
17
17
  ```bash
18
- curl -fsSL https://registry.npmjs.org/@lebronj/pi-suite/-/pi-suite-0.1.15.tgz | tar -xzO package/scripts/bootstrap.sh | bash
18
+ curl -fsSL https://registry.npmjs.org/@lebronj/pi-suite/-/pi-suite-0.1.16.tgz | tar -xzO package/scripts/bootstrap.sh | bash
19
19
  ```
20
20
 
21
21
  ## What Is Included
@@ -1,5 +1,5 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import { join } from "node:path";
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
3
  import { getAgentDir, type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";
4
4
 
5
5
  interface PackageEntryObject {
@@ -77,12 +77,40 @@ function requirementSatisfied(requirement: RepairRequirement, installedSources:
77
77
  return installedSources.some((source) => sourceIdentity(source) === requiredIdentity);
78
78
  }
79
79
 
80
+ function globalSettingsPath(): string {
81
+ return join(getAgentDir(), "settings.json");
82
+ }
83
+
80
84
  function readInstalledPackageSources(ctx: ExtensionContext): string[] {
81
- const globalSettings = readSettings(join(getAgentDir(), "settings.json"));
85
+ const globalSettings = readSettings(globalSettingsPath());
82
86
  const projectSettings = readSettings(join(ctx.cwd, ".pi", "settings.json"));
83
87
  return [...packageSourcesFromSettings(globalSettings), ...packageSourcesFromSettings(projectSettings)];
84
88
  }
85
89
 
90
+ function addGlobalPackageSources(sources: string[]): string[] {
91
+ const settingsPath = globalSettingsPath();
92
+ const settings = readSettings(settingsPath) ?? {};
93
+ const packages = Array.isArray(settings.packages) ? [...settings.packages] : [];
94
+ const existingSources = packageSourcesFromSettings({ packages });
95
+ const added: string[] = [];
96
+
97
+ for (const source of sources) {
98
+ const requiredIdentity = sourceIdentity(source);
99
+ const alreadyPresent = existingSources.some((existing) => sourceIdentity(existing) === requiredIdentity);
100
+ if (alreadyPresent) continue;
101
+ packages.push(source);
102
+ existingSources.push(source);
103
+ added.push(source);
104
+ }
105
+
106
+ if (added.length > 0) {
107
+ mkdirSync(dirname(settingsPath), { recursive: true });
108
+ writeFileSync(settingsPath, `${JSON.stringify({ ...settings, packages }, null, 2)}\n`, "utf8");
109
+ }
110
+
111
+ return added;
112
+ }
113
+
86
114
  function pendingRequirements(ctx: ExtensionContext): RepairRequirement[] {
87
115
  const installedSources = readInstalledPackageSources(ctx);
88
116
  return REQUIRED_PACKAGES.filter((requirement) => !requirementSatisfied(requirement, installedSources));
@@ -111,7 +139,7 @@ export default function piSuiteRepairExtension(pi: ExtensionAPI): void {
111
139
  handler: async (_args, ctx) => {
112
140
  if (!ctx.hasUI) return;
113
141
 
114
- const pending = pendingRequirements(ctx);
142
+ let pending = pendingRequirements(ctx);
115
143
  if (pending.length === 0) {
116
144
  ctx.ui.notify("pi-suite companion packages are already registered. No repair needed.", "info");
117
145
  return;
@@ -122,21 +150,42 @@ export default function piSuiteRepairExtension(pi: ExtensionAPI): void {
122
150
  "info",
123
151
  );
124
152
 
125
- const failures: string[] = [];
153
+ const installFailures: string[] = [];
126
154
  for (const requirement of pending) {
127
155
  const result = await pi.exec("pi", ["install", requirement.source], { signal: ctx.signal, timeout: 120_000 });
128
156
  if (result.code !== 0) {
129
157
  const details = (result.stderr || result.stdout || "unknown error").trim();
130
- failures.push(`${formatRequirement(requirement)}: ${details}`);
158
+ installFailures.push(`${formatRequirement(requirement)}: ${details}`);
159
+ }
160
+ }
161
+
162
+ pending = pendingRequirements(ctx);
163
+ if (pending.length > 0) {
164
+ const added = addGlobalPackageSources(pending.map((item) => item.source));
165
+ if (added.length > 0) {
166
+ ctx.ui.notify(`Registered missing companion packages in user settings: ${added.join(", ")}`, "info");
167
+ }
168
+ const updateResult = await pi.exec("pi", ["update", "--extensions"], { signal: ctx.signal, timeout: 180_000 });
169
+ if (updateResult.code !== 0) {
170
+ const details = (updateResult.stderr || updateResult.stdout || "unknown error").trim();
171
+ installFailures.push(`pi update --extensions: ${details}`);
131
172
  }
132
173
  }
133
174
 
134
- if (failures.length > 0) {
135
- ctx.ui.notify(`pi-suite repair failed: ${failures.join("; ")}`, "error");
175
+ pending = pendingRequirements(ctx);
176
+ if (pending.length > 0) {
177
+ const manualCommands = pending.map((item) => `pi install ${item.source}`).join("; ");
178
+ ctx.ui.notify(
179
+ `pi-suite repair still sees missing packages: ${pending.map((item) => item.source).join(", ")}. Run manually: ${manualCommands}`,
180
+ "error",
181
+ );
136
182
  return;
137
183
  }
138
184
 
139
- ctx.ui.notify("pi-suite companion packages are installed. Reloading Pi resources...", "info");
185
+ if (installFailures.length > 0) {
186
+ ctx.ui.notify(`pi-suite repair recovered after install issues: ${installFailures.join("; ")}`, "warning");
187
+ }
188
+ ctx.ui.notify("pi-suite companion packages are registered. Reloading Pi resources...", "info");
140
189
  await ctx.reload();
141
190
  },
142
191
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lebronj/pi-suite",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "JHP's Pi extension suite for team coding workflows",
5
5
  "type": "module",
6
6
  "keywords": [