pi-profile-switch 0.12.0 → 0.12.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-profile-switch",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "description": "Named profiles for Pi: reference skills, extensions, MCP servers, and tools per workflow, switched without restarting. Install: npm install -g pi-profile-switch (not pi install).",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -21,8 +21,7 @@
21
21
  * (`workspaceDir`, i.e. `getProfileSwitchDir()`).
22
22
  */
23
23
 
24
- import { createHash } from "node:crypto";
25
- import { mkdir, open, readFile, rename, rm, writeFile } from "node:fs/promises";
24
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
26
25
  import path from "node:path";
27
26
 
28
27
  import { isRecord } from "./json-file.ts";
@@ -61,9 +60,6 @@ const MAX_ANNOUNCEMENTS = 50;
61
60
  const MAX_ID_LENGTH = 128;
62
61
  const MAX_MESSAGE_LENGTH = 400;
63
62
  const MAX_ACTION_LENGTH = 200;
64
- /** A pending display claim older than this is considered abandoned (the
65
- * presenting process died mid-display) and may be reclaimed. */
66
- const CLAIM_STALE_MS = 10 * 60 * 1000;
67
63
  const HISTORY_SCHEMA_VERSION = 1;
68
64
 
69
65
  export interface NoticeSurface {
@@ -276,7 +272,7 @@ function parseNpmLatest(text: string): string {
276
272
  }
277
273
 
278
274
  // ---------------------------------------------------------------------------
279
- // Global history and exclusive display claims
275
+ // Global history
280
276
  // ---------------------------------------------------------------------------
281
277
 
282
278
  function notificationsDir(workspaceDir: string): string {
@@ -316,41 +312,6 @@ async function recordDisplayed(dir: string, key: string): Promise<void> {
316
312
  await atomicWriteJson(path.join(dir, "displayed.json"), { schemaVersion: HISTORY_SCHEMA_VERSION, keys: [...keys] });
317
313
  }
318
314
 
319
- function claimFile(dir: string, key: string): string {
320
- const digest = createHash("sha256").update(key).digest("hex");
321
- return path.join(dir, "claims", `${digest}.json`);
322
- }
323
-
324
- /** Exclusive per-key claim around synchronous presentation: concurrent
325
- * launches (same process or separate ones) cannot both display the same
326
- * notice. Abandoned claims go stale and become reclaimable. */
327
- async function tryAcquireClaim(dir: string, key: string, nowMs: number): Promise<boolean> {
328
- const file = claimFile(dir, key);
329
- await mkdir(path.dirname(file), { recursive: true });
330
- for (let attempt = 0; attempt < 2; attempt++) {
331
- try {
332
- const handle = await open(file, "wx");
333
- try {
334
- await handle.writeFile(JSON.stringify({ key, at: nowMs }));
335
- } finally {
336
- await handle.close();
337
- }
338
- return true;
339
- } catch (error) {
340
- if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
341
- const existing = await readJsonQuiet(file);
342
- const at = isRecord(existing) && typeof existing.at === "number" ? existing.at : 0;
343
- if (nowMs - at <= CLAIM_STALE_MS) return false;
344
- await rm(file, { force: true });
345
- }
346
- }
347
- return false;
348
- }
349
-
350
- async function releaseClaim(dir: string, key: string): Promise<void> {
351
- await rm(claimFile(dir, key), { force: true });
352
- }
353
-
354
315
  // ---------------------------------------------------------------------------
355
316
  // Candidate evaluation and presentation
356
317
  // ---------------------------------------------------------------------------
@@ -425,16 +386,8 @@ function report(surface: NoticeSurface, message: string): void {
425
386
  }
426
387
 
427
388
  async function present(dir: string, candidate: Candidate, surface: NoticeSurface, nowMs: number): Promise<void> {
428
- if (!(await tryAcquireClaim(dir, candidate.key, nowMs))) return;
429
- try {
430
- surface.display(candidate.message, candidate.level);
431
- await recordDisplayed(dir, candidate.key);
432
- } catch (error) {
433
- // A failed presentation releases its claim so a later launch retries.
434
- await releaseClaim(dir, candidate.key);
435
- throw error;
436
- }
437
- await releaseClaim(dir, candidate.key);
389
+ surface.display(candidate.message, candidate.level);
390
+ await recordDisplayed(dir, candidate.key);
438
391
  }
439
392
 
440
393
  // ---------------------------------------------------------------------------