@pi-unipi/core 0.1.14 → 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
@@ -1,17 +1,8 @@
1
1
  # @pi-unipi/core
2
2
 
3
- Shared utilities, event types, and constants for the [Unipi](https://github.com/Neuron-Mr-White/unipi) extension suite.
3
+ Shared infrastructure for every Unipi package. Provides constants, event types, and utility functions so packages can discover each other without tight coupling.
4
4
 
5
- ## Install
6
-
7
- ```bash
8
- pi install npm:@pi-unipi/core
9
- ```
10
-
11
- Or as part of the full suite:
12
- ```bash
13
- pi install npm:unipi
14
- ```
5
+ Other packages import from `@pi-unipi/core` to emit events, read module names, and use common file operations. Without it, each package would need its own event definitions and utilities.
15
6
 
16
7
  ## Usage
17
8
 
@@ -33,6 +24,7 @@ const safeName = sanitize("my/feature: branch");
33
24
  ## Exports
34
25
 
35
26
  ### Constants
27
+
36
28
  - `UNIPI_PREFIX` — Command prefix (`unipi:`)
37
29
  - `MODULES` — All module names
38
30
  - `WORKFLOW_COMMANDS` — Workflow command names
@@ -43,6 +35,7 @@ const safeName = sanitize("my/feature: branch");
43
35
  - `RALPH_COMPLETE_MARKER` — Loop completion marker
44
36
 
45
37
  ### Events
38
+
46
39
  - `UNIPI_EVENTS` — Event names
47
40
  - `UnipiModuleEvent` — Module ready/gone payload
48
41
  - `UnipiWorkflowEvent` — Workflow start/end payload
@@ -51,6 +44,7 @@ const safeName = sanitize("my/feature: branch");
51
44
  - `UnipiStatusRequestEvent` / `UnipiStatusResponseEvent` — Status payloads
52
45
 
53
46
  ### Utilities
47
+
54
48
  - `sanitize(name)` — Sanitize string for filenames
55
49
  - `ensureDir(path)` — Create parent directories
56
50
  - `tryDelete(path)` — Safe file deletion
@@ -69,6 +63,21 @@ const safeName = sanitize("my/feature: branch");
69
63
  - `isModuleAvailable(cwd, name)` — Check if npm module exists
70
64
  - `emitEvent(pi, name, payload)` — Safe event emission
71
65
 
66
+ ## How Packages Use Core
67
+
68
+ Every Unipi package depends on `@pi-unipi/core`. On load, each package:
69
+
70
+ 1. Imports `MODULES` to register its own name
71
+ 2. Imports `UNIPI_EVENTS` to subscribe to lifecycle events
72
+ 3. Calls `emitEvent(pi, UNIPI_EVENTS.MODULE_READY, ...)` to announce itself
73
+ 4. Uses utility functions for file I/O and path resolution
74
+
75
+ This creates a loose coupling — packages discover each other through events, not direct imports.
76
+
77
+ ## Configuration
78
+
79
+ Core has no configuration. It's a pure utility layer.
80
+
72
81
  ## License
73
82
 
74
83
  MIT
package/constants.ts CHANGED
@@ -36,6 +36,8 @@ export const MODULES = {
36
36
  MILESTONE: "@pi-unipi/milestone",
37
37
  KANBOARD: "@pi-unipi/kanboard",
38
38
  FOOTER: "@pi-unipi/footer",
39
+ UPDATER: "@pi-unipi/updater",
40
+ INPUT_SHORTCUTS: "@pi-unipi/input-shortcuts",
39
41
  } as const;
40
42
 
41
43
  /** Workflow command names */
@@ -295,10 +297,29 @@ export const MILESTONE_DIRS = {
295
297
  MILESTONES: ".unipi/docs/MILESTONES.md",
296
298
  } as const;
297
299
 
300
+ /** Updater command names */
301
+ export const UPDATER_COMMANDS = {
302
+ README: "readme",
303
+ CHANGELOG: "changelog",
304
+ UPDATER_SETTINGS: "updater-settings",
305
+ } as const;
306
+
307
+ /** Updater directory paths */
308
+ export const UPDATER_DIRS = {
309
+ CONFIG: "~/.unipi/config/updater",
310
+ CACHE: "~/.unipi/cache/updater",
311
+ } as const;
312
+
313
+ /** Input-shortcuts command names */
314
+ export const INPUT_SHORTCUTS_COMMANDS = {
315
+ STASH_SETTINGS: "stash-settings",
316
+ } as const;
317
+
298
318
  /** Footer command names */
299
319
  export const FOOTER_COMMANDS = {
300
320
  FOOTER: "footer",
301
321
  FOOTER_SETTINGS: "footer-settings",
322
+ FOOTER_HELP: "footer-help",
302
323
  } as const;
303
324
 
304
325
  /** Compactor defaults */
package/events.ts CHANGED
@@ -81,6 +81,15 @@ export const UNIPI_EVENTS = {
81
81
 
82
82
  /** Agent asked user a question (ask_user tool invoked) */
83
83
  ASK_USER_PROMPT: "unipi:ask-user:prompt",
84
+
85
+ /** Update check performed */
86
+ UPDATE_CHECK: "unipi:update:check",
87
+ /** Update available */
88
+ UPDATE_AVAILABLE: "unipi:update:available",
89
+ /** Update applied */
90
+ UPDATE_APPLIED: "unipi:update:applied",
91
+ /** Update error */
92
+ UPDATE_ERROR: "unipi:update:error",
84
93
  } as const;
85
94
 
86
95
  /** Payload for MODULE_READY / MODULE_GONE */
@@ -323,6 +332,42 @@ export interface UnipiAskUserPromptEvent {
323
332
  allowFreeform?: boolean;
324
333
  }
325
334
 
335
+ /** Payload for UPDATE_CHECK */
336
+ export interface UnipiUpdateCheckEvent {
337
+ /** Current installed version */
338
+ currentVersion: string;
339
+ /** Latest version found on npm */
340
+ latestVersion: string;
341
+ /** Whether an update is available */
342
+ updateAvailable: boolean;
343
+ /** Error if check failed */
344
+ error?: string;
345
+ }
346
+
347
+ /** Payload for UPDATE_AVAILABLE */
348
+ export interface UnipiUpdateAvailableEvent {
349
+ /** Current installed version */
350
+ currentVersion: string;
351
+ /** Latest version available */
352
+ latestVersion: string;
353
+ }
354
+
355
+ /** Payload for UPDATE_APPLIED */
356
+ export interface UnipiUpdateAppliedEvent {
357
+ /** Previous version */
358
+ previousVersion: string;
359
+ /** New version after update */
360
+ newVersion: string;
361
+ }
362
+
363
+ /** Payload for UPDATE_ERROR */
364
+ export interface UnipiUpdateErrorEvent {
365
+ /** Error message */
366
+ error: string;
367
+ /** Whether the error was from check or install */
368
+ phase: "check" | "install";
369
+ }
370
+
326
371
  /** Payload for NOTIFICATION_SENT */
327
372
  export interface UnipiNotificationSentEvent {
328
373
  /** Event type that triggered notification */
@@ -359,4 +404,8 @@ export type UnipiEventPayload =
359
404
  | UnipiUtilityLifecycleEvent
360
405
  | UnipiNotificationSentEvent
361
406
  | UnipiBadgeGenerateRequestEvent
362
- | UnipiAskUserPromptEvent;
407
+ | UnipiAskUserPromptEvent
408
+ | UnipiUpdateCheckEvent
409
+ | UnipiUpdateAvailableEvent
410
+ | UnipiUpdateAppliedEvent
411
+ | UnipiUpdateErrorEvent;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/core",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "Shared utilities, event types, and constants for Unipi extension suite",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/utils.ts CHANGED
@@ -141,6 +141,36 @@ export function getPackageVersion(packageDir: string): string {
141
141
  return pkg?.version ?? "0.0.0";
142
142
  }
143
143
 
144
+ /**
145
+ * Walk up from `startDir` to find a package.json with the given `name`.
146
+ * Returns the directory containing that package.json, or null if not found.
147
+ * Stops after `maxSteps` levels (default 10).
148
+ */
149
+ export function findPackageRoot(startDir: string, packageName: string, maxSteps = 10): string | null {
150
+ let dir = path.resolve(startDir);
151
+ for (let i = 0; i < maxSteps; i++) {
152
+ const pkgPath = path.join(dir, "package.json");
153
+ const pkg = readJson<{ name?: string }>(pkgPath);
154
+ if (pkg?.name === packageName) {
155
+ return dir;
156
+ }
157
+ const parent = path.dirname(dir);
158
+ if (parent === dir) break; // filesystem root
159
+ dir = parent;
160
+ }
161
+ return null;
162
+ }
163
+
164
+ /**
165
+ * Get the installed version of a named package by walking up from startDir.
166
+ * Returns "0.0.0" if the package cannot be found.
167
+ */
168
+ export function getInstalledPackageVersion(startDir: string, packageName: string): string {
169
+ const root = findPackageRoot(startDir, packageName);
170
+ if (!root) return "0.0.0";
171
+ return getPackageVersion(root);
172
+ }
173
+
144
174
  /**
145
175
  * Check if a module is available in node_modules.
146
176
  */