@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 +20 -11
- package/constants.ts +21 -0
- package/events.ts +50 -1
- package/package.json +1 -1
- package/utils.ts +30 -0
package/README.md
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
# @pi-unipi/core
|
|
2
2
|
|
|
3
|
-
Shared
|
|
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
|
-
|
|
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
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
|
*/
|