portable-agent-layer 0.24.1 → 0.24.2
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/cli/index.ts +123 -0
package/package.json
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -288,6 +288,38 @@ interface HookHealth {
|
|
|
288
288
|
lastError: string | null;
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
+
function checkClaudeHooksRegistered(): boolean {
|
|
292
|
+
const settingsPath = resolve(platform.claudeDir(), "settings.json");
|
|
293
|
+
if (!existsSync(settingsPath)) return false;
|
|
294
|
+
try {
|
|
295
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
296
|
+
const groups = settings?.hooks?.SessionStart;
|
|
297
|
+
if (!Array.isArray(groups)) return false;
|
|
298
|
+
return groups.some((g: { hooks?: { command?: string }[] }) =>
|
|
299
|
+
g?.hooks?.some((h) => h?.command?.includes("LoadContext"))
|
|
300
|
+
);
|
|
301
|
+
} catch {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function checkCursorHooksRegistered(): boolean {
|
|
307
|
+
const hooksPath = resolve(platform.cursorDir(), "hooks.json");
|
|
308
|
+
if (!existsSync(hooksPath)) return false;
|
|
309
|
+
try {
|
|
310
|
+
const data = JSON.parse(readFileSync(hooksPath, "utf-8"));
|
|
311
|
+
const hooks = data?.hooks?.sessionStart;
|
|
312
|
+
if (!Array.isArray(hooks)) return false;
|
|
313
|
+
return hooks.some((h: { command?: string }) => h?.command?.includes("LoadContext"));
|
|
314
|
+
} catch {
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function checkOpencodePluginInstalled(): boolean {
|
|
320
|
+
return existsSync(resolve(platform.opencodeDir(), "plugins", "pal-plugin.ts"));
|
|
321
|
+
}
|
|
322
|
+
|
|
291
323
|
function checkHookHealth(home: string): HookHealth {
|
|
292
324
|
const logPath = resolve(home, "memory", "state", "debug.log");
|
|
293
325
|
|
|
@@ -375,6 +407,97 @@ function doctor(silent = false): DoctorResult {
|
|
|
375
407
|
ok(`PAL home: ${home}`);
|
|
376
408
|
telosCount > 0 ? ok(`TELOS: ${telosCount} files`) : fail("TELOS: not scaffolded");
|
|
377
409
|
|
|
410
|
+
// Identity
|
|
411
|
+
const palSettingsPath = resolve(home, "memory", "pal-settings.json");
|
|
412
|
+
if (existsSync(palSettingsPath)) {
|
|
413
|
+
try {
|
|
414
|
+
const s = JSON.parse(readFileSync(palSettingsPath, "utf-8"));
|
|
415
|
+
const hasIdentity = s?.identity?.principal?.name && s?.identity?.ai?.name;
|
|
416
|
+
hasIdentity
|
|
417
|
+
? ok("Identity configured")
|
|
418
|
+
: warn("Identity — incomplete (run 'pal cli install')");
|
|
419
|
+
} catch {
|
|
420
|
+
warn("Identity — could not read pal-settings.json");
|
|
421
|
+
}
|
|
422
|
+
} else {
|
|
423
|
+
warn("Identity — pal-settings.json missing (run 'pal cli install')");
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// AGENTS.md
|
|
427
|
+
const agentsMdPath = resolve(platform.opencodeDir(), "AGENTS.md");
|
|
428
|
+
existsSync(agentsMdPath)
|
|
429
|
+
? ok("AGENTS.md present")
|
|
430
|
+
: fail("AGENTS.md — missing (run 'pal cli install')");
|
|
431
|
+
|
|
432
|
+
if (claude.available) {
|
|
433
|
+
const claudeMdPath = resolve(platform.claudeDir(), "CLAUDE.md");
|
|
434
|
+
existsSync(claudeMdPath)
|
|
435
|
+
? ok("CLAUDE.md present")
|
|
436
|
+
: fail("CLAUDE.md — missing (run 'pal cli install --claude')");
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Setup state
|
|
440
|
+
const setupPath = resolve(home, "memory", "state", "setup.json");
|
|
441
|
+
if (existsSync(setupPath)) {
|
|
442
|
+
try {
|
|
443
|
+
const setup = JSON.parse(readFileSync(setupPath, "utf-8"));
|
|
444
|
+
setup?.completed
|
|
445
|
+
? ok("TELOS setup complete")
|
|
446
|
+
: warn("TELOS setup incomplete — run 'pal cli install' or start a session");
|
|
447
|
+
} catch {
|
|
448
|
+
warn("TELOS setup — could not read setup.json");
|
|
449
|
+
}
|
|
450
|
+
} else {
|
|
451
|
+
warn("TELOS setup — setup.json missing (run 'pal cli install')");
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Skills (per installed agent)
|
|
455
|
+
const countSkillsIn = (dir: string) =>
|
|
456
|
+
existsSync(dir)
|
|
457
|
+
? readdirSync(dir).filter((f) => existsSync(resolve(dir, f, "SKILL.md"))).length
|
|
458
|
+
: 0;
|
|
459
|
+
if (claude.available) {
|
|
460
|
+
const n = countSkillsIn(resolve(platform.claudeDir(), "skills"));
|
|
461
|
+
n > 0
|
|
462
|
+
? ok(`Claude Code skills: ${n}`)
|
|
463
|
+
: warn("Claude Code skills — none found (run 'pal cli install --claude')");
|
|
464
|
+
}
|
|
465
|
+
if (opencode.available) {
|
|
466
|
+
const n = countSkillsIn(resolve(platform.agentsDir(), "skills"));
|
|
467
|
+
n > 0
|
|
468
|
+
? ok(`opencode skills: ${n}`)
|
|
469
|
+
: warn("opencode skills — none found (run 'pal cli install --opencode')");
|
|
470
|
+
}
|
|
471
|
+
if (cursor.available) {
|
|
472
|
+
const n = countSkillsIn(resolve(platform.cursorDir(), "skills"));
|
|
473
|
+
n > 0
|
|
474
|
+
? ok(`Cursor skills: ${n}`)
|
|
475
|
+
: warn("Cursor skills — none found (run 'pal cli install --cursor')");
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Dependencies
|
|
479
|
+
const nodeModulesPath = resolve(palPkg(), "node_modules");
|
|
480
|
+
existsSync(nodeModulesPath)
|
|
481
|
+
? ok("Dependencies installed")
|
|
482
|
+
: fail("Dependencies missing — run 'pal cli install'");
|
|
483
|
+
|
|
484
|
+
// Hook registration (per installed agent)
|
|
485
|
+
if (claude.available) {
|
|
486
|
+
checkClaudeHooksRegistered()
|
|
487
|
+
? ok("Claude Code hooks registered")
|
|
488
|
+
: fail("Claude Code hooks — not registered (run 'pal cli install --claude')");
|
|
489
|
+
}
|
|
490
|
+
if (opencode.available) {
|
|
491
|
+
checkOpencodePluginInstalled()
|
|
492
|
+
? ok("opencode plugin installed")
|
|
493
|
+
: fail("opencode plugin — not installed (run 'pal cli install --opencode')");
|
|
494
|
+
}
|
|
495
|
+
if (cursor.available) {
|
|
496
|
+
checkCursorHooksRegistered()
|
|
497
|
+
? ok("Cursor hooks registered")
|
|
498
|
+
: fail("Cursor hooks — not registered (run 'pal cli install --cursor')");
|
|
499
|
+
}
|
|
500
|
+
|
|
378
501
|
// API key checks
|
|
379
502
|
process.env.PAL_ANTHROPIC_API_KEY
|
|
380
503
|
? ok("PAL_ANTHROPIC_API_KEY is set")
|