@juicesharp/rpiv-args 1.13.0 → 1.14.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/args.ts +38 -68
- package/package.json +1 -1
package/args.ts
CHANGED
|
@@ -27,9 +27,8 @@
|
|
|
27
27
|
* template literal below.
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import { dirname, join, resolve } from "node:path";
|
|
30
|
+
import { readFileSync } from "node:fs";
|
|
31
|
+
import { dirname } from "node:path";
|
|
33
32
|
import {
|
|
34
33
|
type BeforeAgentStartEvent,
|
|
35
34
|
type BeforeAgentStartEventResult,
|
|
@@ -39,12 +38,9 @@ import {
|
|
|
39
38
|
type ExtensionAPI,
|
|
40
39
|
type ExtensionContext,
|
|
41
40
|
formatSize,
|
|
42
|
-
getAgentDir,
|
|
43
41
|
type InputEvent,
|
|
44
42
|
type InputEventResult,
|
|
45
|
-
loadSkills,
|
|
46
43
|
parseFrontmatter,
|
|
47
|
-
type Skill,
|
|
48
44
|
stripFrontmatter,
|
|
49
45
|
type TruncationResult,
|
|
50
46
|
truncateTail,
|
|
@@ -315,72 +311,41 @@ export function invalidateSkillIndex(): void {
|
|
|
315
311
|
skillIndex = null;
|
|
316
312
|
}
|
|
317
313
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
skillDirs.push(join(dir, ".agents", "skills"));
|
|
334
|
-
if (gitRepoRoot && dir === gitRepoRoot) break;
|
|
335
|
-
const parent = dirname(dir);
|
|
336
|
-
if (parent === dir) break;
|
|
337
|
-
dir = parent;
|
|
338
|
-
}
|
|
339
|
-
return skillDirs;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
function addExistingPath(paths: string[], seen: Set<string>, path: string): void {
|
|
343
|
-
const resolved = resolve(path);
|
|
344
|
-
if (!existsSync(resolved) || seen.has(resolved)) return;
|
|
345
|
-
seen.add(resolved);
|
|
346
|
-
paths.push(resolved);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/** Collect Pi's default skill locations in collision-precedence order. */
|
|
350
|
-
export function collectDefaultSkillPaths(cwd: string, agentDir: string): string[] {
|
|
351
|
-
const paths: string[] = [];
|
|
352
|
-
const seen = new Set<string>();
|
|
353
|
-
const userAgentsSkillsDir = join(homedir(), ".agents", "skills");
|
|
354
|
-
|
|
355
|
-
addExistingPath(paths, seen, join(resolve(cwd), ".pi", "skills"));
|
|
356
|
-
for (const dir of collectAncestorAgentsSkillDirs(cwd)) {
|
|
357
|
-
if (resolve(dir) !== resolve(userAgentsSkillsDir)) addExistingPath(paths, seen, dir);
|
|
358
|
-
}
|
|
359
|
-
addExistingPath(paths, seen, join(agentDir, "skills"));
|
|
360
|
-
addExistingPath(paths, seen, userAgentsSkillsDir);
|
|
361
|
-
|
|
362
|
-
return paths;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/** Build the name→path index by asking Pi for its default skill locations. */
|
|
366
|
-
function buildSkillIndex(): Map<string, SkillIndexEntry> {
|
|
367
|
-
const cwd = process.cwd();
|
|
368
|
-
const agentDir = getAgentDir();
|
|
369
|
-
const { skills } = loadSkills({
|
|
370
|
-
cwd,
|
|
371
|
-
agentDir,
|
|
372
|
-
skillPaths: collectDefaultSkillPaths(cwd, agentDir),
|
|
373
|
-
includeDefaults: false,
|
|
374
|
-
});
|
|
314
|
+
/**
|
|
315
|
+
* Build the name→path index from Pi's command registry. `pi.getCommands()`
|
|
316
|
+
* returns every slash command the agent can see — including skills sourced
|
|
317
|
+
* from extension package manifests (`pi.skills: [...]`), not just the
|
|
318
|
+
* filesystem-walked defaults. This is the authoritative source: whatever Pi
|
|
319
|
+
* knows about as `/skill:<name>`, this index recognizes.
|
|
320
|
+
*
|
|
321
|
+
* Critically, this fixes programmatic `sendUserMessage("/skill:<name> …")`
|
|
322
|
+
* from other extensions (e.g. the `/rpiv` workflow runner). Those calls go
|
|
323
|
+
* through `prompt({expandPromptTemplates: false})`, so Pi's built-in
|
|
324
|
+
* `_expandSkillCommand` is skipped — `rpiv-args` is the only expander on that
|
|
325
|
+
* path. If the index doesn't recognize the skill, the raw `/skill:<name> …`
|
|
326
|
+
* reaches the LLM unwrapped.
|
|
327
|
+
*/
|
|
328
|
+
function buildSkillIndex(pi: ExtensionAPI): Map<string, SkillIndexEntry> {
|
|
375
329
|
const index = new Map<string, SkillIndexEntry>();
|
|
376
|
-
for (const
|
|
377
|
-
|
|
330
|
+
for (const cmd of pi.getCommands()) {
|
|
331
|
+
if (cmd.source !== "skill") continue;
|
|
332
|
+
// Pi prefixes skill-source commands with "skill:" (agent-session.js:1699).
|
|
333
|
+
const name = cmd.name.startsWith("skill:") ? cmd.name.slice("skill:".length) : cmd.name;
|
|
334
|
+
const filePath = cmd.sourceInfo.path;
|
|
335
|
+
// `cmd.sourceInfo.baseDir` cannot be used here: for skills sourced from
|
|
336
|
+
// an extension manifest (`pi.skills: [...]`), resource-loader.js:358-362
|
|
337
|
+
// overrides `skill.sourceInfo` with the *extension package's* baseDir
|
|
338
|
+
// (e.g. `packages/rpiv-pi`), not the skill folder. Pi's own internal
|
|
339
|
+
// `Skill.baseDir` is set to `dirname(filePath)` at skills.js:214,237 —
|
|
340
|
+
// which is what `${SKILL_DIR}` substitutions in skill bodies expect.
|
|
341
|
+
const baseDir = dirname(filePath);
|
|
342
|
+
index.set(name, { name, filePath, baseDir });
|
|
378
343
|
}
|
|
379
344
|
return index;
|
|
380
345
|
}
|
|
381
346
|
|
|
382
|
-
function getSkillIndex(): Map<string, SkillIndexEntry> {
|
|
383
|
-
if (!skillIndex) skillIndex = buildSkillIndex();
|
|
347
|
+
function getSkillIndex(pi: ExtensionAPI): Map<string, SkillIndexEntry> {
|
|
348
|
+
if (!skillIndex) skillIndex = buildSkillIndex(pi);
|
|
384
349
|
return skillIndex;
|
|
385
350
|
}
|
|
386
351
|
|
|
@@ -424,7 +389,7 @@ export async function handleInput(
|
|
|
424
389
|
const skillName = spaceIndex === -1 ? text.slice(SKILL_PREFIX.length) : text.slice(SKILL_PREFIX.length, spaceIndex);
|
|
425
390
|
const argsString = spaceIndex === -1 ? "" : text.slice(spaceIndex + 1).trim();
|
|
426
391
|
|
|
427
|
-
const entry = getSkillIndex().get(skillName);
|
|
392
|
+
const entry = getSkillIndex(pi).get(skillName);
|
|
428
393
|
if (!entry) return { action: "continue" }; // unknown skill — let Pi handle it
|
|
429
394
|
|
|
430
395
|
let content: string;
|
|
@@ -484,6 +449,11 @@ export function registerArgsHandler(pi: ExtensionAPI): void {
|
|
|
484
449
|
pi.on("input", async (event, ctx) => handleInput(event, ctx, pi));
|
|
485
450
|
pi.on("before_agent_start", (event) => handleBeforeAgentStart(event));
|
|
486
451
|
pi.on("session_start", (event) => {
|
|
452
|
+
// Pi fires session_start for every session including programmatic
|
|
453
|
+
// spawns. Re-enumerating the skill set per spawn is cheap (one
|
|
454
|
+
// readdir per declared skillPath); the prior workflow-aware gate
|
|
455
|
+
// shaved that work but coupled this package to rpiv-workflow's
|
|
456
|
+
// internal Symbol. Drop the gate — correctness > microseconds.
|
|
487
457
|
if (event.reason === "reload" || event.reason === "startup") {
|
|
488
458
|
invalidateSkillIndex();
|
|
489
459
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juicesharp/rpiv-args",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "Pi extension. Shell-style $1 / $ARGUMENTS placeholders and !`cmd` / ```! shell substitution, expanded into your Pi skills at invocation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|