@mrclrchtr/supi-skills 7.2.0 → 7.2.1
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-skills",
|
|
3
|
-
"version": "7.2.
|
|
3
|
+
"version": "7.2.1",
|
|
4
4
|
"description": "Scoped skill controls and skill input shortcuts for PI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"README.md"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@mrclrchtr/supi-core": "7.2.
|
|
33
|
+
"@mrclrchtr/supi-core": "7.2.1"
|
|
34
34
|
},
|
|
35
35
|
"bundledDependencies": [
|
|
36
36
|
"@mrclrchtr/supi-core"
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
type BuildSystemPromptOptions,
|
|
3
3
|
formatSkillsForPrompt,
|
|
4
4
|
} from "@earendil-works/pi-coding-agent";
|
|
5
|
+
import { recordDebugEvent, truncateDebugIdentity } from "@mrclrchtr/supi-core/debug";
|
|
5
6
|
import { resolveInvocation } from "./skill-model-invocation-config.ts";
|
|
6
7
|
|
|
7
8
|
export type { ModelInvocationState } from "./skill-model-invocation-config.ts";
|
|
@@ -12,7 +13,25 @@ export const ENABLED = "Enabled";
|
|
|
12
13
|
export const MODEL_DISABLED = "Model invocation disabled";
|
|
13
14
|
export const DISABLED = "Disabled";
|
|
14
15
|
|
|
15
|
-
/** Replace PI's
|
|
16
|
+
/** Replace PI's rendered skills section while preserving the rest of a forced prompt. */
|
|
17
|
+
function replaceStructuredSkillsSection(
|
|
18
|
+
systemPrompt: string,
|
|
19
|
+
original: string,
|
|
20
|
+
replacement: string,
|
|
21
|
+
): string | undefined {
|
|
22
|
+
const content = original.trim();
|
|
23
|
+
if (!content) return undefined;
|
|
24
|
+
const currentSection = `<skills>\n${content}\n</skills>`;
|
|
25
|
+
const start = systemPrompt.indexOf(currentSection);
|
|
26
|
+
if (start < 0 || systemPrompt.indexOf(currentSection, start + currentSection.length) >= 0) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
const replacementContent = replacement.trim();
|
|
30
|
+
const section = replacementContent ? `<skills>\n${replacementContent}\n</skills>` : "";
|
|
31
|
+
return `${systemPrompt.slice(0, start)}${section}${systemPrompt.slice(start + currentSection.length)}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Apply the effective scoped invocation state to PI's mutable prompt options. */
|
|
16
35
|
export function applyPromptOverrides({
|
|
17
36
|
options,
|
|
18
37
|
systemPrompt,
|
|
@@ -26,7 +45,12 @@ export function applyPromptOverrides({
|
|
|
26
45
|
projectTrusted: boolean;
|
|
27
46
|
homeDir?: string;
|
|
28
47
|
}): string | undefined {
|
|
29
|
-
|
|
48
|
+
const selectedTools = options.selectedTools;
|
|
49
|
+
const skillFileReadTool =
|
|
50
|
+
selectedTools === undefined
|
|
51
|
+
? "read"
|
|
52
|
+
: (["read", "bash"] as const).find((tool) => selectedTools.includes(tool));
|
|
53
|
+
if (!skillFileReadTool) return undefined;
|
|
30
54
|
const skills = options.skills ?? [];
|
|
31
55
|
const effective = skills.map((skill) => ({
|
|
32
56
|
...skill,
|
|
@@ -39,11 +63,52 @@ export function applyPromptOverrides({
|
|
|
39
63
|
homeDir,
|
|
40
64
|
}).disabled,
|
|
41
65
|
}));
|
|
42
|
-
const original = formatSkillsForPrompt(skills);
|
|
43
|
-
const replacement = formatSkillsForPrompt(effective);
|
|
66
|
+
const original = formatSkillsForPrompt(skills, skillFileReadTool);
|
|
67
|
+
const replacement = formatSkillsForPrompt(effective, skillFileReadTool);
|
|
44
68
|
if (original === replacement) return undefined;
|
|
45
|
-
|
|
46
|
-
|
|
69
|
+
|
|
70
|
+
// PI renders skills inside its structured <skills> section. Mutate the
|
|
71
|
+
// normalized options so PI can render the replacement without byte matching
|
|
72
|
+
// the already-rendered prompt.
|
|
73
|
+
if (options.forceSystemPrompt === undefined) {
|
|
74
|
+
options.skills = effective;
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const structuredPrompt = replaceStructuredSkillsSection(systemPrompt, original, replacement);
|
|
79
|
+
if (structuredPrompt !== undefined) {
|
|
80
|
+
options.skills = effective;
|
|
81
|
+
options.forceSystemPrompt = structuredPrompt;
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!original) {
|
|
86
|
+
const content = replacement.trim();
|
|
87
|
+
options.skills = effective;
|
|
88
|
+
return `${systemPrompt}${content ? `\n<skills>\n${content}\n</skills>` : ""}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
recordDebugEvent({
|
|
92
|
+
source: "supi-skills",
|
|
93
|
+
level: "warning",
|
|
94
|
+
category: "prompt-overrides",
|
|
95
|
+
message: "Could not apply skill model-invocation overrides",
|
|
96
|
+
cwd: truncateDebugIdentity(cwd),
|
|
97
|
+
data: {
|
|
98
|
+
skillCount: skills.length,
|
|
99
|
+
changedSkills: skills
|
|
100
|
+
.filter(
|
|
101
|
+
(skill, index) =>
|
|
102
|
+
skill.disableModelInvocation !== effective[index]?.disableModelInvocation,
|
|
103
|
+
)
|
|
104
|
+
.map((skill) => skill.name),
|
|
105
|
+
forceSystemPrompt: true,
|
|
106
|
+
hasSkillsSection: systemPrompt.includes("<skills>"),
|
|
107
|
+
originalLength: original.length,
|
|
108
|
+
replacementLength: replacement.length,
|
|
109
|
+
systemPromptLength: systemPrompt.length,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
47
112
|
// biome-ignore lint/suspicious/noConsole: prompt mismatch must not fail silently
|
|
48
113
|
console.warn("[supi-skills] Could not apply skill model-invocation overrides");
|
|
49
114
|
return undefined;
|