@pi-unipi/utility 0.1.1 → 0.2.3
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 +135 -21
- package/package.json +16 -7
- package/skills/utility/SKILL.md +70 -0
- package/src/analytics/collector.ts +293 -0
- package/src/cache/ttl-cache.ts +311 -0
- package/src/commands.ts +250 -0
- package/src/diagnostics/engine.ts +298 -0
- package/src/display/capabilities.ts +200 -0
- package/src/display/width.ts +226 -0
- package/src/index.ts +283 -0
- package/src/info-screen.ts +80 -0
- package/src/lifecycle/cleanup.ts +332 -0
- package/src/lifecycle/process.ts +162 -0
- package/src/tools/batch.ts +229 -0
- package/src/tools/env.ts +134 -0
- package/src/tui/badge-settings.ts +103 -0
- package/src/tui/name-badge-state.ts +299 -0
- package/src/tui/name-badge.ts +117 -0
- package/src/tui/settings-inspector.ts +303 -0
- package/src/types.ts +257 -0
- package/commands.ts +0 -38
- package/index.ts +0 -34
package/src/types.ts
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @pi-unipi/utility — Shared types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for utility modules: lifecycle, cache, analytics,
|
|
5
|
+
* diagnostics, display, TUI, and tools.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ─── Lifecycle ───────────────────────────────────────────────────────────────
|
|
9
|
+
|
|
10
|
+
/** Cleanup function registered with the lifecycle manager */
|
|
11
|
+
export type CleanupFn = () => void | Promise<void>;
|
|
12
|
+
|
|
13
|
+
/** Process lifecycle state */
|
|
14
|
+
export type LifecycleState = "running" | "shutting_down" | "orphaned" | "error";
|
|
15
|
+
|
|
16
|
+
/** Options for ProcessLifecycle */
|
|
17
|
+
export interface ProcessLifecycleOptions {
|
|
18
|
+
/** Polling interval in ms for parent PID checks (default: 30000) */
|
|
19
|
+
pollIntervalMs?: number;
|
|
20
|
+
/** Whether to install signal handlers (default: true) */
|
|
21
|
+
handleSignals?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ─── Cache ───────────────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
/** Cache entry with metadata */
|
|
27
|
+
export interface CacheEntry<V> {
|
|
28
|
+
value: V;
|
|
29
|
+
expiresAt: number;
|
|
30
|
+
createdAt: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** TTL cache backend interface */
|
|
34
|
+
export interface CacheBackend<K, V> {
|
|
35
|
+
get(key: K): Promise<V | undefined>;
|
|
36
|
+
set(key: K, value: V, ttlMs: number): Promise<void>;
|
|
37
|
+
has(key: K): Promise<boolean>;
|
|
38
|
+
delete(key: K): Promise<boolean>;
|
|
39
|
+
cleanupExpired(): Promise<number>;
|
|
40
|
+
clear(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** TTL cache options */
|
|
44
|
+
export interface TTLCacheOptions {
|
|
45
|
+
/** Use SQLite persistence (default: false) */
|
|
46
|
+
persistent?: boolean;
|
|
47
|
+
/** SQLite DB path (default: auto) */
|
|
48
|
+
dbPath?: string;
|
|
49
|
+
/** Default TTL in ms */
|
|
50
|
+
defaultTtlMs?: number;
|
|
51
|
+
/** Max entries in memory cache */
|
|
52
|
+
maxMemoryEntries?: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ─── Analytics ───────────────────────────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
/** Analytics event types */
|
|
58
|
+
export type AnalyticsEventType =
|
|
59
|
+
| "module_load"
|
|
60
|
+
| "command_run"
|
|
61
|
+
| "tool_call"
|
|
62
|
+
| "error"
|
|
63
|
+
| "compaction"
|
|
64
|
+
| "search";
|
|
65
|
+
|
|
66
|
+
/** Single analytics event record */
|
|
67
|
+
export interface AnalyticsEvent {
|
|
68
|
+
id: string;
|
|
69
|
+
type: AnalyticsEventType;
|
|
70
|
+
timestamp: number;
|
|
71
|
+
module?: string;
|
|
72
|
+
command?: string;
|
|
73
|
+
tool?: string;
|
|
74
|
+
durationMs?: number;
|
|
75
|
+
success?: boolean;
|
|
76
|
+
metadata?: Record<string, unknown>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Daily rollup of analytics events */
|
|
80
|
+
export interface AnalyticsRollup {
|
|
81
|
+
date: string; // YYYY-MM-DD
|
|
82
|
+
events: Record<AnalyticsEventType, number>;
|
|
83
|
+
totalDurationMs: number;
|
|
84
|
+
errorCount: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Analytics collector options */
|
|
88
|
+
export interface AnalyticsOptions {
|
|
89
|
+
/** SQLite DB path */
|
|
90
|
+
dbPath?: string;
|
|
91
|
+
/** Max events before auto-rollup (default: 10000) */
|
|
92
|
+
maxEvents?: number;
|
|
93
|
+
/** Enable daily rollup (default: true) */
|
|
94
|
+
rollupEnabled?: boolean;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ─── Diagnostics ─────────────────────────────────────────────────────────────
|
|
98
|
+
|
|
99
|
+
/** Health status for a single check */
|
|
100
|
+
export type HealthStatus = "healthy" | "warning" | "error" | "unknown";
|
|
101
|
+
|
|
102
|
+
/** Result of a single diagnostic check */
|
|
103
|
+
export interface DiagnosticCheck {
|
|
104
|
+
name: string;
|
|
105
|
+
module: string;
|
|
106
|
+
status: HealthStatus;
|
|
107
|
+
message: string;
|
|
108
|
+
suggestion?: string;
|
|
109
|
+
durationMs: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Complete diagnostics report */
|
|
113
|
+
export interface DiagnosticsReport {
|
|
114
|
+
timestamp: number;
|
|
115
|
+
overall: HealthStatus;
|
|
116
|
+
checks: DiagnosticCheck[];
|
|
117
|
+
summary: {
|
|
118
|
+
healthy: number;
|
|
119
|
+
warning: number;
|
|
120
|
+
error: number;
|
|
121
|
+
unknown: number;
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Plugin for diagnostics engine */
|
|
126
|
+
export interface DiagnosticPlugin {
|
|
127
|
+
name: string;
|
|
128
|
+
module: string;
|
|
129
|
+
run(): Promise<DiagnosticCheck[]>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ─── Display ─────────────────────────────────────────────────────────────────
|
|
133
|
+
|
|
134
|
+
/** Detected terminal capabilities */
|
|
135
|
+
export interface TerminalCapabilities {
|
|
136
|
+
/** Terminal supports basic colors */
|
|
137
|
+
color: boolean;
|
|
138
|
+
/** Terminal supports 256/truecolor */
|
|
139
|
+
truecolor: boolean;
|
|
140
|
+
/** Nerd Font detected */
|
|
141
|
+
nerdFont: boolean;
|
|
142
|
+
/** Unicode support level */
|
|
143
|
+
unicode: "none" | "basic" | "full";
|
|
144
|
+
/** Terminal width in columns */
|
|
145
|
+
width: number;
|
|
146
|
+
/** Terminal height in rows */
|
|
147
|
+
height: number;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Width management options */
|
|
151
|
+
export interface WidthOptions {
|
|
152
|
+
/** Truncation indicator (default: "…") */
|
|
153
|
+
ellipsis?: string;
|
|
154
|
+
/** Whether to break words (default: false) */
|
|
155
|
+
breakWords?: boolean;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ─── TUI ─────────────────────────────────────────────────────────────────────
|
|
159
|
+
|
|
160
|
+
/** Settings schema entry */
|
|
161
|
+
export interface SettingSchema {
|
|
162
|
+
key: string;
|
|
163
|
+
type: "string" | "number" | "boolean" | "object" | "array";
|
|
164
|
+
description: string;
|
|
165
|
+
default?: unknown;
|
|
166
|
+
required?: boolean;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Settings inspector state */
|
|
170
|
+
export interface SettingsInspectorState {
|
|
171
|
+
schemas: SettingSchema[];
|
|
172
|
+
values: Record<string, unknown>;
|
|
173
|
+
selectedIndex: number;
|
|
174
|
+
searchQuery: string;
|
|
175
|
+
editMode: boolean;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ─── Tools ───────────────────────────────────────────────────────────────────
|
|
179
|
+
|
|
180
|
+
/** Single batch command entry */
|
|
181
|
+
export interface BatchCommand {
|
|
182
|
+
type: "command" | "tool" | "search";
|
|
183
|
+
name: string;
|
|
184
|
+
args?: Record<string, unknown>;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Batch execution options */
|
|
188
|
+
export interface BatchOptions {
|
|
189
|
+
/** Fail on first error (default: true) */
|
|
190
|
+
failFast?: boolean;
|
|
191
|
+
/** Timeout per command in ms (default: 30000) */
|
|
192
|
+
commandTimeoutMs?: number;
|
|
193
|
+
/** Total timeout in ms (default: 300000) */
|
|
194
|
+
totalTimeoutMs?: number;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** Result of a single batch command */
|
|
198
|
+
export interface BatchResult {
|
|
199
|
+
command: BatchCommand;
|
|
200
|
+
success: boolean;
|
|
201
|
+
result?: unknown;
|
|
202
|
+
error?: string;
|
|
203
|
+
durationMs: number;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Complete batch execution result */
|
|
207
|
+
export interface BatchReport {
|
|
208
|
+
success: boolean;
|
|
209
|
+
results: BatchResult[];
|
|
210
|
+
totalDurationMs: number;
|
|
211
|
+
rolledBack: boolean;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** Environment info returned by ctx_env */
|
|
215
|
+
export interface EnvironmentInfo {
|
|
216
|
+
nodeVersion: string;
|
|
217
|
+
piVersion: string;
|
|
218
|
+
os: string;
|
|
219
|
+
platform: string;
|
|
220
|
+
unipiModules: string[];
|
|
221
|
+
configPaths: string[];
|
|
222
|
+
extensionPaths: string[];
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ─── Cleanup ─────────────────────────────────────────────────────────────────
|
|
226
|
+
|
|
227
|
+
/** Result of a cleanup operation */
|
|
228
|
+
export interface CleanupResult {
|
|
229
|
+
/** What was cleaned */
|
|
230
|
+
category: "db" | "temp" | "session" | "cache" | "log";
|
|
231
|
+
/** Items removed */
|
|
232
|
+
removed: number;
|
|
233
|
+
/** Bytes freed (approximate) */
|
|
234
|
+
bytesFreed: number;
|
|
235
|
+
/** Paths that were cleaned */
|
|
236
|
+
paths: string[];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** Complete cleanup report */
|
|
240
|
+
export interface CleanupReport {
|
|
241
|
+
timestamp: number;
|
|
242
|
+
results: CleanupResult[];
|
|
243
|
+
totalRemoved: number;
|
|
244
|
+
totalBytesFreed: number;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** Cleanup options */
|
|
248
|
+
export interface CleanupOptions {
|
|
249
|
+
/** Max age in days for DB files (default: 14) */
|
|
250
|
+
dbMaxAgeDays?: number;
|
|
251
|
+
/** Max age in days for temp files (default: 7) */
|
|
252
|
+
tempMaxAgeDays?: number;
|
|
253
|
+
/** Max age in days for sessions (default: 30) */
|
|
254
|
+
sessionMaxAgeDays?: number;
|
|
255
|
+
/** Dry run — report only (default: false) */
|
|
256
|
+
dryRun?: boolean;
|
|
257
|
+
}
|
package/commands.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @pi-unipi/utility — Command registration
|
|
3
|
-
*
|
|
4
|
-
* Registers /unipi:continue command for clean agent continuation.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
|
|
8
|
-
import { UNIPI_PREFIX, UTILITY_COMMANDS } from "@pi-unipi/core";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Register utility commands.
|
|
12
|
-
*/
|
|
13
|
-
export function registerUtilityCommands(pi: ExtensionAPI): void {
|
|
14
|
-
pi.registerCommand(`${UNIPI_PREFIX}${UTILITY_COMMANDS.CONTINUE}`, {
|
|
15
|
-
description: "Continue the agent from where it left off without adding user context",
|
|
16
|
-
handler: async (_args: string, ctx: ExtensionContext) => {
|
|
17
|
-
if (!ctx.isIdle()) {
|
|
18
|
-
if (ctx.hasUI) {
|
|
19
|
-
ctx.ui.notify(
|
|
20
|
-
"Agent is busy. Press ESC to interrupt, then try again.",
|
|
21
|
-
"warning",
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Send custom message to trigger a turn without polluting transcript
|
|
28
|
-
pi.sendMessage(
|
|
29
|
-
{
|
|
30
|
-
customType: "unipi-continue",
|
|
31
|
-
content: "",
|
|
32
|
-
display: false,
|
|
33
|
-
},
|
|
34
|
-
{ triggerTurn: true },
|
|
35
|
-
);
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
}
|
package/index.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @pi-unipi/utility — Extension entry
|
|
3
|
-
*
|
|
4
|
-
* Provides /unipi:continue command for clean agent continuation
|
|
5
|
-
* without context pollution.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
9
|
-
import {
|
|
10
|
-
UNIPI_EVENTS,
|
|
11
|
-
MODULES,
|
|
12
|
-
UTILITY_COMMANDS,
|
|
13
|
-
emitEvent,
|
|
14
|
-
getPackageVersion,
|
|
15
|
-
} from "@pi-unipi/core";
|
|
16
|
-
import { registerUtilityCommands } from "./commands.js";
|
|
17
|
-
|
|
18
|
-
/** Package version */
|
|
19
|
-
const VERSION = getPackageVersion(new URL(".", import.meta.url).pathname);
|
|
20
|
-
|
|
21
|
-
export default function (pi: ExtensionAPI) {
|
|
22
|
-
// Register commands
|
|
23
|
-
registerUtilityCommands(pi);
|
|
24
|
-
|
|
25
|
-
// Session lifecycle — announce module
|
|
26
|
-
pi.on("session_start", async () => {
|
|
27
|
-
emitEvent(pi, UNIPI_EVENTS.MODULE_READY, {
|
|
28
|
-
name: MODULES.UTILITY,
|
|
29
|
-
version: VERSION,
|
|
30
|
-
commands: [`unipi:${UTILITY_COMMANDS.CONTINUE}`],
|
|
31
|
-
tools: [],
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
}
|