@oh-my-pi/pi-utils 13.11.1 → 13.12.0
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 +1 -1
- package/src/dirs.ts +151 -67
- package/src/ptree.ts +1 -1
package/package.json
CHANGED
package/src/dirs.ts
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Uses PI_CONFIG_DIR (default ".omp") for the config root and
|
|
5
5
|
* PI_CODING_AGENT_DIR to override the agent directory.
|
|
6
|
+
*
|
|
7
|
+
* On Linux, if XDG_DATA_HOME / XDG_STATE_HOME / XDG_CACHE_HOME environment
|
|
8
|
+
* variables are set, paths are redirected to XDG-compliant locations under
|
|
9
|
+
* $XDG_*_HOME/omp/. This requires running `omp config migrate` first to
|
|
10
|
+
* move data to the new locations. No filesystem existence checks are performed
|
|
11
|
+
* — if the env var is set, omp trusts that the migration has been done.
|
|
6
12
|
*/
|
|
7
13
|
|
|
8
14
|
import * as fs from "node:fs";
|
|
@@ -23,7 +29,7 @@ export const VERSION: string = version;
|
|
|
23
29
|
export const MIN_BUN_VERSION: string = engines.bun.replace(/[^0-9.]/g, "");
|
|
24
30
|
|
|
25
31
|
// =============================================================================
|
|
26
|
-
//
|
|
32
|
+
// Project directory
|
|
27
33
|
// =============================================================================
|
|
28
34
|
|
|
29
35
|
/**
|
|
@@ -64,23 +70,117 @@ export function getConfigAgentDirName(): string {
|
|
|
64
70
|
return `${getConfigDirName()}/agent`;
|
|
65
71
|
}
|
|
66
72
|
|
|
73
|
+
// =============================================================================
|
|
74
|
+
// DirResolver — cached, XDG-aware path resolution
|
|
75
|
+
// =============================================================================
|
|
76
|
+
|
|
77
|
+
type XdgCategory = "data" | "state" | "cache";
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Resolves and caches all omp directory paths. On Linux, when XDG environment
|
|
81
|
+
* variables are set, paths are redirected under $XDG_*_HOME/omp/. A new
|
|
82
|
+
* instance is created whenever the agent directory changes, which naturally
|
|
83
|
+
* invalidates all cached paths.
|
|
84
|
+
*/
|
|
85
|
+
class DirResolver {
|
|
86
|
+
readonly configRoot: string;
|
|
87
|
+
readonly agentDir: string;
|
|
88
|
+
|
|
89
|
+
// Per-category base dirs. Without XDG, all three equal configRoot / agentDir.
|
|
90
|
+
// With XDG on Linux, they point to $XDG_*_HOME/omp/.
|
|
91
|
+
readonly #rootDirs: Record<XdgCategory, string>;
|
|
92
|
+
readonly #agentDirs: Record<XdgCategory, string>;
|
|
93
|
+
|
|
94
|
+
readonly #rootCache = new Map<string, string>();
|
|
95
|
+
readonly #agentCache = new Map<string, string>();
|
|
96
|
+
|
|
97
|
+
constructor(agentDirOverride?: string) {
|
|
98
|
+
this.configRoot = path.join(os.homedir(), getConfigDirName());
|
|
99
|
+
|
|
100
|
+
const defaultAgent = path.join(this.configRoot, "agent");
|
|
101
|
+
this.agentDir = agentDirOverride ? path.resolve(agentDirOverride) : defaultAgent;
|
|
102
|
+
const isDefault = this.agentDir === defaultAgent;
|
|
103
|
+
|
|
104
|
+
// XDG is a Linux convention. On other platforms, or for non-default
|
|
105
|
+
// profiles, all categories resolve to the legacy paths.
|
|
106
|
+
let xdgData: string | undefined;
|
|
107
|
+
let xdgState: string | undefined;
|
|
108
|
+
let xdgCache: string | undefined;
|
|
109
|
+
if (process.platform === "linux" && isDefault) {
|
|
110
|
+
const resolveIf = (envVar: string) => {
|
|
111
|
+
const value = process.env[envVar];
|
|
112
|
+
if (value) {
|
|
113
|
+
try {
|
|
114
|
+
const joined = path.join(value, APP_NAME);
|
|
115
|
+
if (fs.existsSync(joined)) {
|
|
116
|
+
return joined;
|
|
117
|
+
}
|
|
118
|
+
} catch {}
|
|
119
|
+
}
|
|
120
|
+
return undefined;
|
|
121
|
+
};
|
|
122
|
+
xdgData = resolveIf("XDG_DATA_HOME");
|
|
123
|
+
xdgState = resolveIf("XDG_STATE_HOME");
|
|
124
|
+
xdgCache = resolveIf("XDG_CACHE_HOME");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
this.#rootDirs = {
|
|
128
|
+
data: xdgData ?? this.configRoot,
|
|
129
|
+
state: xdgState ?? this.configRoot,
|
|
130
|
+
cache: xdgCache ?? this.configRoot,
|
|
131
|
+
};
|
|
132
|
+
// XDG flattens the agent/ prefix: ~/.omp/agent/sessions → $XDG_DATA_HOME/omp/sessions
|
|
133
|
+
this.#agentDirs = {
|
|
134
|
+
data: xdgData ?? this.agentDir,
|
|
135
|
+
state: xdgState ?? this.agentDir,
|
|
136
|
+
cache: xdgCache ?? this.agentDir,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Config-root subdirectory, with optional XDG override. */
|
|
141
|
+
rootSubdir(subdir: string, xdg?: XdgCategory): string {
|
|
142
|
+
const cached = this.#rootCache.get(subdir);
|
|
143
|
+
if (cached) return cached;
|
|
144
|
+
const base = xdg ? this.#rootDirs[xdg] : this.configRoot;
|
|
145
|
+
const result = path.join(base, subdir);
|
|
146
|
+
this.#rootCache.set(subdir, result);
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Agent subdirectory, with optional XDG override. */
|
|
151
|
+
agentSubdir(userAgentDir: string | undefined, subdir: string, xdg?: XdgCategory): string {
|
|
152
|
+
if (!userAgentDir || userAgentDir === this.agentDir) {
|
|
153
|
+
const cached = this.#agentCache.get(subdir);
|
|
154
|
+
if (cached) return cached;
|
|
155
|
+
const base = xdg ? this.#agentDirs[xdg] : this.agentDir;
|
|
156
|
+
const result = path.join(base, subdir);
|
|
157
|
+
this.#agentCache.set(subdir, result);
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
return path.join(userAgentDir, subdir);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let dirs = new DirResolver(process.env.PI_CODING_AGENT_DIR);
|
|
165
|
+
|
|
166
|
+
// =============================================================================
|
|
167
|
+
// Root directories
|
|
168
|
+
// =============================================================================
|
|
169
|
+
|
|
67
170
|
/** Get the config root directory (~/.omp). */
|
|
68
171
|
export function getConfigRootDir(): string {
|
|
69
|
-
return
|
|
172
|
+
return dirs.configRoot;
|
|
70
173
|
}
|
|
71
174
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
/** Set the coding agent directory. */
|
|
175
|
+
/** Set the coding agent directory. Creates a fresh resolver, invalidating all cached paths. */
|
|
75
176
|
export function setAgentDir(dir: string): void {
|
|
76
|
-
|
|
77
|
-
agentCache.clear();
|
|
177
|
+
dirs = new DirResolver(dir);
|
|
78
178
|
process.env.PI_CODING_AGENT_DIR = dir;
|
|
79
179
|
}
|
|
80
180
|
|
|
81
181
|
/** Get the agent config directory (~/.omp/agent). */
|
|
82
182
|
export function getAgentDir(): string {
|
|
83
|
-
return agentDir;
|
|
183
|
+
return dirs.agentDir;
|
|
84
184
|
}
|
|
85
185
|
|
|
86
186
|
/** Get the project-local config directory (.omp). */
|
|
@@ -88,49 +188,18 @@ export function getProjectAgentDir(cwd: string = getProjectDir()): string {
|
|
|
88
188
|
return path.join(cwd, CONFIG_DIR_NAME);
|
|
89
189
|
}
|
|
90
190
|
|
|
91
|
-
// =============================================================================
|
|
92
|
-
// Caching utilities
|
|
93
|
-
// =============================================================================
|
|
94
|
-
|
|
95
|
-
const rootCache = new Map<string, any>();
|
|
96
|
-
|
|
97
|
-
function getRootSubdir(subdir: string): string {
|
|
98
|
-
if (rootCache.has(subdir)) {
|
|
99
|
-
return rootCache.get(subdir);
|
|
100
|
-
}
|
|
101
|
-
const result = path.join(getConfigRootDir(), subdir);
|
|
102
|
-
rootCache.set(subdir, result);
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const agentCache = new Map<string, any>();
|
|
107
|
-
|
|
108
|
-
function getAgentSubdir(userAgentDir: string | undefined, subdir: string): string {
|
|
109
|
-
if (!userAgentDir || userAgentDir === agentDir) {
|
|
110
|
-
if (agentCache.has(subdir)) {
|
|
111
|
-
return agentCache.get(subdir);
|
|
112
|
-
} else {
|
|
113
|
-
const result = path.join(agentDir, subdir);
|
|
114
|
-
agentCache.set(subdir, result);
|
|
115
|
-
return result;
|
|
116
|
-
}
|
|
117
|
-
} else {
|
|
118
|
-
return path.join(userAgentDir, subdir);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
191
|
// =============================================================================
|
|
123
192
|
// Config-root subdirectories (~/.omp/*)
|
|
124
193
|
// =============================================================================
|
|
125
194
|
|
|
126
195
|
/** Get the reports directory (~/.omp/reports). */
|
|
127
196
|
export function getReportsDir(): string {
|
|
128
|
-
return
|
|
197
|
+
return dirs.rootSubdir("reports", "state");
|
|
129
198
|
}
|
|
130
199
|
|
|
131
200
|
/** Get the logs directory (~/.omp/logs). */
|
|
132
201
|
export function getLogsDir(): string {
|
|
133
|
-
return
|
|
202
|
+
return dirs.rootSubdir("logs", "state");
|
|
134
203
|
}
|
|
135
204
|
|
|
136
205
|
/** Get the path to a dated log file (~/.omp/logs/omp.YYYY-MM-DD.log). */
|
|
@@ -140,52 +209,52 @@ export function getLogPath(date = new Date()): string {
|
|
|
140
209
|
|
|
141
210
|
/** Get the plugins directory (~/.omp/plugins). */
|
|
142
211
|
export function getPluginsDir(): string {
|
|
143
|
-
return
|
|
212
|
+
return dirs.rootSubdir("plugins", "data");
|
|
144
213
|
}
|
|
145
214
|
|
|
146
215
|
/** Where npm installs packages (~/.omp/plugins/node_modules). */
|
|
147
216
|
export function getPluginsNodeModules(): string {
|
|
148
|
-
return
|
|
217
|
+
return path.join(getPluginsDir(), "node_modules");
|
|
149
218
|
}
|
|
150
219
|
|
|
151
220
|
/** Plugin manifest (~/.omp/plugins/package.json). */
|
|
152
221
|
export function getPluginsPackageJson(): string {
|
|
153
|
-
return
|
|
222
|
+
return path.join(getPluginsDir(), "package.json");
|
|
154
223
|
}
|
|
155
224
|
|
|
156
225
|
/** Plugin lock file (~/.omp/plugins/omp-plugins.lock.json). */
|
|
157
226
|
export function getPluginsLockfile(): string {
|
|
158
|
-
return
|
|
227
|
+
return path.join(getPluginsDir(), "omp-plugins.lock.json");
|
|
159
228
|
}
|
|
160
229
|
|
|
161
230
|
/** Get the remote mount directory (~/.omp/remote). */
|
|
162
231
|
export function getRemoteDir(): string {
|
|
163
|
-
return
|
|
232
|
+
return dirs.rootSubdir("remote", "data");
|
|
164
233
|
}
|
|
165
234
|
|
|
166
235
|
/** Get the SSH control socket directory (~/.omp/ssh-control). */
|
|
167
236
|
export function getSshControlDir(): string {
|
|
168
|
-
return
|
|
237
|
+
return dirs.rootSubdir("ssh-control", "state");
|
|
169
238
|
}
|
|
170
239
|
|
|
171
240
|
/** Get the remote host info directory (~/.omp/remote-host). */
|
|
172
241
|
export function getRemoteHostDir(): string {
|
|
173
|
-
return
|
|
242
|
+
return dirs.rootSubdir("remote-host", "data");
|
|
174
243
|
}
|
|
175
244
|
|
|
176
245
|
/** Get the managed Python venv directory (~/.omp/python-env). */
|
|
177
246
|
export function getPythonEnvDir(): string {
|
|
178
|
-
return
|
|
247
|
+
return dirs.rootSubdir("python-env", "data");
|
|
179
248
|
}
|
|
180
249
|
|
|
181
250
|
/** Get the puppeteer sandbox directory (~/.omp/puppeteer). */
|
|
182
251
|
export function getPuppeteerDir(): string {
|
|
183
|
-
return
|
|
252
|
+
return dirs.rootSubdir("puppeteer", "cache");
|
|
184
253
|
}
|
|
185
254
|
|
|
186
255
|
/** Get the worktree base directory (~/.omp/wt). */
|
|
187
256
|
export function getWorktreeBaseDir(): string {
|
|
188
|
-
return
|
|
257
|
+
return dirs.rootSubdir("wt", "data");
|
|
189
258
|
}
|
|
190
259
|
|
|
191
260
|
/** Get the path to a worktree directory (~/.omp/wt/<project>/<id>). */
|
|
@@ -195,17 +264,17 @@ export function getWorktreeDir(encodedProject: string, id: string): string {
|
|
|
195
264
|
|
|
196
265
|
/** Get the GPU cache path (~/.omp/gpu_cache.json). */
|
|
197
266
|
export function getGpuCachePath(): string {
|
|
198
|
-
return
|
|
267
|
+
return dirs.rootSubdir("gpu_cache.json", "cache");
|
|
199
268
|
}
|
|
200
269
|
|
|
201
270
|
/** Get the natives directory (~/.omp/natives). */
|
|
202
271
|
export function getNativesDir(): string {
|
|
203
|
-
return
|
|
272
|
+
return dirs.rootSubdir("natives", "cache");
|
|
204
273
|
}
|
|
205
274
|
|
|
206
275
|
/** Get the stats database path (~/.omp/stats.db). */
|
|
207
276
|
export function getStatsDbPath(): string {
|
|
208
|
-
return
|
|
277
|
+
return dirs.rootSubdir("stats.db", "data");
|
|
209
278
|
}
|
|
210
279
|
|
|
211
280
|
// =============================================================================
|
|
@@ -214,57 +283,72 @@ export function getStatsDbPath(): string {
|
|
|
214
283
|
|
|
215
284
|
/** Get the path to agent.db (SQLite database for settings and auth storage). */
|
|
216
285
|
export function getAgentDbPath(agentDir?: string): string {
|
|
217
|
-
return
|
|
286
|
+
return dirs.agentSubdir(agentDir, "agent.db", "data");
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** Get the path to history.db (SQLite database for session history). */
|
|
290
|
+
export function getHistoryDbPath(agentDir?: string): string {
|
|
291
|
+
return dirs.agentSubdir(agentDir, "history.db", "data");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/** Get the path to models.db (model cache database). */
|
|
295
|
+
export function getModelDbPath(agentDir?: string): string {
|
|
296
|
+
return dirs.agentSubdir(agentDir, "models.db", "data");
|
|
218
297
|
}
|
|
219
298
|
|
|
220
299
|
/** Get the sessions directory (~/.omp/agent/sessions). */
|
|
221
300
|
export function getSessionsDir(agentDir?: string): string {
|
|
222
|
-
return
|
|
301
|
+
return dirs.agentSubdir(agentDir, "sessions", "data");
|
|
223
302
|
}
|
|
224
303
|
|
|
225
304
|
/** Get the content-addressed blob store directory (~/.omp/agent/blobs). */
|
|
226
305
|
export function getBlobsDir(agentDir?: string): string {
|
|
227
|
-
return
|
|
306
|
+
return dirs.agentSubdir(agentDir, "blobs", "data");
|
|
228
307
|
}
|
|
229
308
|
|
|
230
309
|
/** Get the custom themes directory (~/.omp/agent/themes). */
|
|
231
310
|
export function getCustomThemesDir(agentDir?: string): string {
|
|
232
|
-
return
|
|
311
|
+
return dirs.agentSubdir(agentDir, "themes");
|
|
233
312
|
}
|
|
234
313
|
|
|
235
314
|
/** Get the tools directory (~/.omp/agent/tools). */
|
|
236
315
|
export function getToolsDir(agentDir?: string): string {
|
|
237
|
-
return
|
|
316
|
+
return dirs.agentSubdir(agentDir, "tools");
|
|
238
317
|
}
|
|
239
318
|
|
|
240
319
|
/** Get the slash commands directory (~/.omp/agent/commands). */
|
|
241
320
|
export function getCommandsDir(agentDir?: string): string {
|
|
242
|
-
return
|
|
321
|
+
return dirs.agentSubdir(agentDir, "commands");
|
|
243
322
|
}
|
|
244
323
|
|
|
245
324
|
/** Get the prompts directory (~/.omp/agent/prompts). */
|
|
246
325
|
export function getPromptsDir(agentDir?: string): string {
|
|
247
|
-
return
|
|
326
|
+
return dirs.agentSubdir(agentDir, "prompts");
|
|
248
327
|
}
|
|
249
328
|
|
|
250
329
|
/** Get the user-level Python modules directory (~/.omp/agent/modules). */
|
|
251
330
|
export function getAgentModulesDir(agentDir?: string): string {
|
|
252
|
-
return
|
|
331
|
+
return dirs.agentSubdir(agentDir, "modules");
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/** Get the memories directory (~/.omp/agent/memories). */
|
|
335
|
+
export function getMemoriesDir(agentDir?: string): string {
|
|
336
|
+
return dirs.agentSubdir(agentDir, "memories", "state");
|
|
253
337
|
}
|
|
254
338
|
|
|
255
|
-
/** Get the
|
|
256
|
-
export function
|
|
257
|
-
return
|
|
339
|
+
/** Get the terminal sessions directory (~/.omp/agent/terminal-sessions). */
|
|
340
|
+
export function getTerminalSessionsDir(agentDir?: string): string {
|
|
341
|
+
return dirs.agentSubdir(agentDir, "terminal-sessions", "state");
|
|
258
342
|
}
|
|
259
343
|
|
|
260
344
|
/** Get the crash log path (~/.omp/agent/omp-crash.log). */
|
|
261
345
|
export function getCrashLogPath(agentDir?: string): string {
|
|
262
|
-
return
|
|
346
|
+
return dirs.agentSubdir(agentDir, "omp-crash.log", "state");
|
|
263
347
|
}
|
|
264
348
|
|
|
265
349
|
/** Get the debug log path (~/.omp/agent/omp-debug.log). */
|
|
266
350
|
export function getDebugLogPath(agentDir?: string): string {
|
|
267
|
-
return
|
|
351
|
+
return dirs.agentSubdir(agentDir, `${APP_NAME}-debug.log`, "state");
|
|
268
352
|
}
|
|
269
353
|
|
|
270
354
|
// =============================================================================
|
package/src/ptree.ts
CHANGED