@promptscript/cli 1.14.1 → 1.15.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/index.js +247 -74
- package/package.json +1 -1
- package/src/commands/compile.d.ts.map +1 -1
- package/src/utils/markers.d.ts +3 -10
- package/src/utils/markers.d.ts.map +1 -1
package/index.js
CHANGED
|
@@ -840,6 +840,30 @@ var init_levenshtein = __esm({
|
|
|
840
840
|
}
|
|
841
841
|
});
|
|
842
842
|
|
|
843
|
+
// packages/core/src/utils/markers.ts
|
|
844
|
+
function stripPromptScriptMarkers(content) {
|
|
845
|
+
return content.replace(new RegExp(`${HTML_MARKER}\\n*`, "g"), "").replace(new RegExp(`${YAML_MARKER}[^\\n]+\\n*`, "g"), "");
|
|
846
|
+
}
|
|
847
|
+
function isGeneratedByPromptScript(content) {
|
|
848
|
+
const head = new RegExp(`^\\s*(?:${YAML_MARKER}|${HTML_MARKER})`);
|
|
849
|
+
return content.split("\n", 5).some((line) => head.test(line));
|
|
850
|
+
}
|
|
851
|
+
function stripFrontmatterMarkerLines(frontmatter) {
|
|
852
|
+
const markerLine = new RegExp(`^\\s*${YAML_MARKER}`);
|
|
853
|
+
return frontmatter.split("\n").filter((line) => !markerLine.test(line)).join("\n");
|
|
854
|
+
}
|
|
855
|
+
function stripLeadingHtmlMarker(body) {
|
|
856
|
+
return body.replace(new RegExp(`^\\s*${HTML_MARKER}\\n*`), "");
|
|
857
|
+
}
|
|
858
|
+
var HTML_MARKER, YAML_MARKER;
|
|
859
|
+
var init_markers = __esm({
|
|
860
|
+
"packages/core/src/utils/markers.ts"() {
|
|
861
|
+
"use strict";
|
|
862
|
+
HTML_MARKER = "<!--\\s*PromptScript [^>]+-->";
|
|
863
|
+
YAML_MARKER = "#\\s*promptscript-generated:";
|
|
864
|
+
}
|
|
865
|
+
});
|
|
866
|
+
|
|
843
867
|
// packages/core/src/utils/index.ts
|
|
844
868
|
var init_utils = __esm({
|
|
845
869
|
"packages/core/src/utils/index.ts"() {
|
|
@@ -850,6 +874,7 @@ var init_utils = __esm({
|
|
|
850
874
|
init_path();
|
|
851
875
|
init_version();
|
|
852
876
|
init_levenshtein();
|
|
877
|
+
init_markers();
|
|
853
878
|
}
|
|
854
879
|
});
|
|
855
880
|
|
|
@@ -12714,6 +12739,7 @@ var init_markdown_instruction_formatter = __esm({
|
|
|
12714
12739
|
this.addSection(sections, this.project(ast, renderer));
|
|
12715
12740
|
this.addSection(sections, this.techStack(ast, renderer));
|
|
12716
12741
|
this.addSection(sections, this.architecture(ast, renderer));
|
|
12742
|
+
this.addSection(sections, this.context(ast, renderer));
|
|
12717
12743
|
this.addSection(sections, this.codeStandards(ast, renderer));
|
|
12718
12744
|
this.addSection(sections, this.gitCommits(ast, renderer));
|
|
12719
12745
|
this.addSection(sections, this.configFiles(ast, renderer));
|
|
@@ -12806,6 +12832,30 @@ var init_markdown_instruction_formatter = __esm({
|
|
|
12806
12832
|
const normalizedContent = this.normalizeMarkdownForPrettier(content);
|
|
12807
12833
|
return renderer.renderSection("Architecture", normalizedContent.trim()) + "\n";
|
|
12808
12834
|
}
|
|
12835
|
+
/**
|
|
12836
|
+
* Render @context block text content as a "## Context" section.
|
|
12837
|
+
*
|
|
12838
|
+
* The "## Architecture" subsection (with code block) is stripped because
|
|
12839
|
+
* it is already rendered separately by {@link architecture}. Remaining
|
|
12840
|
+
* "## " headings are downgraded to "### " to avoid clashing with the
|
|
12841
|
+
* formatter's own h2 section headings. When no @identity block exists,
|
|
12842
|
+
* the project() fallback already consumes the full @context text, so
|
|
12843
|
+
* this method returns null to avoid duplication.
|
|
12844
|
+
*/
|
|
12845
|
+
context(ast, renderer) {
|
|
12846
|
+
const identity = this.findBlock(ast, "identity");
|
|
12847
|
+
if (!identity) return null;
|
|
12848
|
+
const contextBlock = this.findBlock(ast, "context");
|
|
12849
|
+
if (!contextBlock) return null;
|
|
12850
|
+
const text = this.extractText(contextBlock.content);
|
|
12851
|
+
if (!text) return null;
|
|
12852
|
+
const archMatch = this.extractSectionWithCodeBlock(text, "## Architecture");
|
|
12853
|
+
const remainingText = archMatch ? text.replace(archMatch, "").trim() : text.trim();
|
|
12854
|
+
if (!remainingText) return null;
|
|
12855
|
+
const downgradedText = remainingText.replace(/^(\s*)## /gm, "$1### ");
|
|
12856
|
+
const normalizedContent = this.normalizeMarkdownForPrettier(downgradedText);
|
|
12857
|
+
return renderer.renderSection("Context", normalizedContent.trim()) + "\n";
|
|
12858
|
+
}
|
|
12809
12859
|
codeStandards(ast, renderer) {
|
|
12810
12860
|
const standards = this.findBlock(ast, "standards");
|
|
12811
12861
|
if (!standards) return null;
|
|
@@ -13844,6 +13894,8 @@ ${f.content}`
|
|
|
13844
13894
|
if (techStack) sections.push(techStack);
|
|
13845
13895
|
const architecture = this.architecture(ast, renderer);
|
|
13846
13896
|
if (architecture) sections.push(architecture);
|
|
13897
|
+
const contextSection = this.contextSection(ast, renderer);
|
|
13898
|
+
if (contextSection) sections.push(contextSection);
|
|
13847
13899
|
const codeStandards = this.codeStandards(ast, renderer);
|
|
13848
13900
|
if (codeStandards) sections.push(codeStandards);
|
|
13849
13901
|
const shortcuts = this.shortcutsSection(ast, renderer);
|
|
@@ -13954,6 +14006,19 @@ ${f.content}`
|
|
|
13954
14006
|
const content = archMatch.replace("## Architecture", "").trim();
|
|
13955
14007
|
return renderer.renderSection("architecture", this.stripAllIndent(content));
|
|
13956
14008
|
}
|
|
14009
|
+
contextSection(ast, renderer) {
|
|
14010
|
+
const identity = this.findBlock(ast, "identity");
|
|
14011
|
+
if (!identity) return null;
|
|
14012
|
+
const contextBlock = this.findBlock(ast, "context");
|
|
14013
|
+
if (!contextBlock) return null;
|
|
14014
|
+
const text = this.extractText(contextBlock.content);
|
|
14015
|
+
if (!text) return null;
|
|
14016
|
+
const archMatch = this.extractSectionWithCodeBlock(text, "## Architecture");
|
|
14017
|
+
const remainingText = archMatch ? text.replace(archMatch, "").trim() : text.trim();
|
|
14018
|
+
if (!remainingText) return null;
|
|
14019
|
+
const downgradedText = remainingText.replace(/^(\s*)## /gm, "$1### ");
|
|
14020
|
+
return renderer.renderSection("Context", this.stripAllIndent(downgradedText));
|
|
14021
|
+
}
|
|
13957
14022
|
codeStandards(ast, renderer) {
|
|
13958
14023
|
const standards = this.findBlock(ast, "standards");
|
|
13959
14024
|
if (!standards) return null;
|
|
@@ -15046,6 +15111,7 @@ ${f.content}`
|
|
|
15046
15111
|
this.addSection(sections, this.project(ast, renderer));
|
|
15047
15112
|
this.addSection(sections, this.techStack(ast, renderer));
|
|
15048
15113
|
this.addSection(sections, this.architecture(ast, renderer));
|
|
15114
|
+
this.addSection(sections, this.contextSection(ast, renderer));
|
|
15049
15115
|
this.addSection(sections, this.codeStandards(ast, renderer));
|
|
15050
15116
|
this.addSection(sections, this.gitCommits(ast, renderer));
|
|
15051
15117
|
this.addSection(sections, this.configFiles(ast, renderer));
|
|
@@ -15138,6 +15204,20 @@ ${f.content}`
|
|
|
15138
15204
|
const normalizedContent = this.normalizeMarkdownForPrettier(content);
|
|
15139
15205
|
return renderer.renderSection("Architecture", normalizedContent.trim()) + "\n";
|
|
15140
15206
|
}
|
|
15207
|
+
contextSection(ast, renderer) {
|
|
15208
|
+
const identity = this.findBlock(ast, "identity");
|
|
15209
|
+
if (!identity) return null;
|
|
15210
|
+
const contextBlock = this.findBlock(ast, "context");
|
|
15211
|
+
if (!contextBlock) return null;
|
|
15212
|
+
const text = this.extractText(contextBlock.content);
|
|
15213
|
+
if (!text) return null;
|
|
15214
|
+
const archMatch = this.extractSectionWithCodeBlock(text, "## Architecture");
|
|
15215
|
+
const remainingText = archMatch ? text.replace(archMatch, "").trim() : text.trim();
|
|
15216
|
+
if (!remainingText) return null;
|
|
15217
|
+
const downgradedText = remainingText.replace(/^(\s*)## /gm, "$1### ");
|
|
15218
|
+
const normalizedContent = this.normalizeMarkdownForPrettier(downgradedText);
|
|
15219
|
+
return renderer.renderSection("Context", normalizedContent.trim()) + "\n";
|
|
15220
|
+
}
|
|
15141
15221
|
codeStandards(ast, renderer) {
|
|
15142
15222
|
const standards = this.findBlock(ast, "standards");
|
|
15143
15223
|
if (!standards) return null;
|
|
@@ -16345,6 +16425,8 @@ ${content}`);
|
|
|
16345
16425
|
if (techStack) sections.push(techStack);
|
|
16346
16426
|
const architecture = this.architecture(ast, renderer);
|
|
16347
16427
|
if (architecture) sections.push(architecture);
|
|
16428
|
+
const contextSection = this.contextSection(ast, renderer);
|
|
16429
|
+
if (contextSection) sections.push(contextSection);
|
|
16348
16430
|
const codeStandards = this.codeStandards(ast, renderer);
|
|
16349
16431
|
if (codeStandards) sections.push(codeStandards);
|
|
16350
16432
|
const gitCommits = this.gitCommits(ast, renderer);
|
|
@@ -16672,6 +16754,21 @@ ${this.stripAllIndent(content)}`;
|
|
|
16672
16754
|
}
|
|
16673
16755
|
return null;
|
|
16674
16756
|
}
|
|
16757
|
+
contextSection(ast, _renderer) {
|
|
16758
|
+
const identity = this.findBlock(ast, "identity");
|
|
16759
|
+
if (!identity) return null;
|
|
16760
|
+
const contextBlock = this.findBlock(ast, "context");
|
|
16761
|
+
if (!contextBlock) return null;
|
|
16762
|
+
const text = this.extractText(contextBlock.content);
|
|
16763
|
+
if (!text) return null;
|
|
16764
|
+
const archMatch = this.extractSectionWithCodeBlock(text, "## Architecture");
|
|
16765
|
+
const remainingText = archMatch ? text.replace(archMatch, "").trim() : text.trim();
|
|
16766
|
+
if (!remainingText) return null;
|
|
16767
|
+
const downgradedText = remainingText.replace(/^(\s*)## /gm, "$1### ");
|
|
16768
|
+
return `## Context
|
|
16769
|
+
|
|
16770
|
+
${this.stripAllIndent(downgradedText)}`;
|
|
16771
|
+
}
|
|
16675
16772
|
/**
|
|
16676
16773
|
* Extract code standards from @standards block.
|
|
16677
16774
|
* Uses shared extractor for dynamic key iteration (parity with GitHub/Claude/Cursor).
|
|
@@ -17418,6 +17515,7 @@ ${links.join("\n")}
|
|
|
17418
17515
|
this.addSection(sections, this.project(ast, renderer));
|
|
17419
17516
|
this.addSection(sections, this.techStack(ast, renderer));
|
|
17420
17517
|
this.addSection(sections, this.architecture(ast, renderer));
|
|
17518
|
+
this.addSection(sections, this.context(ast, renderer));
|
|
17421
17519
|
this.addSection(sections, this.commands(ast, renderer));
|
|
17422
17520
|
this.addSection(sections, this.postWork(ast, renderer));
|
|
17423
17521
|
}
|
|
@@ -26768,16 +26866,22 @@ function extractReservedParams(params) {
|
|
|
26768
26866
|
const remaining = [];
|
|
26769
26867
|
let only;
|
|
26770
26868
|
let exclude;
|
|
26869
|
+
let includes;
|
|
26870
|
+
let excludes;
|
|
26771
26871
|
for (const param of params) {
|
|
26772
26872
|
if (param.name === "only" && Array.isArray(param.value)) {
|
|
26773
26873
|
only = param.value.filter((v) => typeof v === "string");
|
|
26774
26874
|
} else if (param.name === "exclude" && Array.isArray(param.value)) {
|
|
26775
26875
|
exclude = param.value.filter((v) => typeof v === "string");
|
|
26876
|
+
} else if (param.name === "includes" && Array.isArray(param.value)) {
|
|
26877
|
+
includes = param.value.filter((v) => typeof v === "string");
|
|
26878
|
+
} else if (param.name === "excludes" && Array.isArray(param.value)) {
|
|
26879
|
+
excludes = param.value.filter((v) => typeof v === "string");
|
|
26776
26880
|
} else {
|
|
26777
26881
|
remaining.push(param);
|
|
26778
26882
|
}
|
|
26779
26883
|
}
|
|
26780
|
-
return { only, exclude, remaining };
|
|
26884
|
+
return { only, exclude, includes, excludes, remaining };
|
|
26781
26885
|
}
|
|
26782
26886
|
function filterBlocks(blocks, options) {
|
|
26783
26887
|
if (options.only) {
|
|
@@ -26790,6 +26894,44 @@ function filterBlocks(blocks, options) {
|
|
|
26790
26894
|
}
|
|
26791
26895
|
return blocks;
|
|
26792
26896
|
}
|
|
26897
|
+
function filterSkillsBlock(program2, options) {
|
|
26898
|
+
if (!options.includes && !options.excludes) {
|
|
26899
|
+
return program2;
|
|
26900
|
+
}
|
|
26901
|
+
const skillsBlock = program2.blocks.find((b) => b.name === "skills");
|
|
26902
|
+
if (!skillsBlock || skillsBlock.content.type !== "ObjectContent") {
|
|
26903
|
+
return program2;
|
|
26904
|
+
}
|
|
26905
|
+
const props = skillsBlock.content.properties;
|
|
26906
|
+
const skillNames = Object.keys(props);
|
|
26907
|
+
let filteredNames;
|
|
26908
|
+
if (options.includes) {
|
|
26909
|
+
const allowSet = new Set(options.includes);
|
|
26910
|
+
filteredNames = skillNames.filter((name) => allowSet.has(name));
|
|
26911
|
+
} else {
|
|
26912
|
+
const denySet = new Set(options.excludes);
|
|
26913
|
+
filteredNames = skillNames.filter((name) => !denySet.has(name));
|
|
26914
|
+
}
|
|
26915
|
+
if (filteredNames.length === skillNames.length) {
|
|
26916
|
+
return program2;
|
|
26917
|
+
}
|
|
26918
|
+
const filteredProps = {};
|
|
26919
|
+
for (const name of filteredNames) {
|
|
26920
|
+
filteredProps[name] = deepCloneValue2(props[name]);
|
|
26921
|
+
}
|
|
26922
|
+
const newSkillsBlock = {
|
|
26923
|
+
...deepClone(skillsBlock),
|
|
26924
|
+
content: {
|
|
26925
|
+
type: "ObjectContent",
|
|
26926
|
+
properties: filteredProps,
|
|
26927
|
+
loc: skillsBlock.content.loc
|
|
26928
|
+
}
|
|
26929
|
+
};
|
|
26930
|
+
return {
|
|
26931
|
+
...program2,
|
|
26932
|
+
blocks: program2.blocks.map((b) => b.name === "skills" ? newSkillsBlock : b)
|
|
26933
|
+
};
|
|
26934
|
+
}
|
|
26793
26935
|
|
|
26794
26936
|
// packages/resolver/src/extensions.ts
|
|
26795
26937
|
init_src();
|
|
@@ -27407,7 +27549,9 @@ function parseSkillMd(content) {
|
|
|
27407
27549
|
let rawFrontmatter;
|
|
27408
27550
|
let bodyContent;
|
|
27409
27551
|
if (frontmatterStart >= 0 && frontmatterEnd > frontmatterStart) {
|
|
27410
|
-
const frontmatterLines =
|
|
27552
|
+
const frontmatterLines = stripFrontmatterMarkerLines(
|
|
27553
|
+
lines.slice(frontmatterStart + 1, frontmatterEnd).join("\n")
|
|
27554
|
+
).split("\n");
|
|
27411
27555
|
const parsed = parseFrontmatterFields(frontmatterLines);
|
|
27412
27556
|
name = parsed.name;
|
|
27413
27557
|
description = parsed.description;
|
|
@@ -27418,9 +27562,9 @@ function parseSkillMd(content) {
|
|
|
27418
27562
|
scripts = parsed.scripts;
|
|
27419
27563
|
license = parsed.license;
|
|
27420
27564
|
rawFrontmatter = frontmatterLines.join("\n");
|
|
27421
|
-
bodyContent = lines.slice(frontmatterEnd + 1).join("\n").trim();
|
|
27565
|
+
bodyContent = stripLeadingHtmlMarker(lines.slice(frontmatterEnd + 1).join("\n")).trim();
|
|
27422
27566
|
} else {
|
|
27423
|
-
bodyContent = content.trim();
|
|
27567
|
+
bodyContent = stripLeadingHtmlMarker(content).trim();
|
|
27424
27568
|
}
|
|
27425
27569
|
return {
|
|
27426
27570
|
name,
|
|
@@ -28092,6 +28236,13 @@ async function fileExists(path2) {
|
|
|
28092
28236
|
return false;
|
|
28093
28237
|
}
|
|
28094
28238
|
}
|
|
28239
|
+
async function isGeneratedOutput(filePath) {
|
|
28240
|
+
try {
|
|
28241
|
+
return isGeneratedByPromptScript(await readFile8(filePath, "utf-8"));
|
|
28242
|
+
} catch {
|
|
28243
|
+
return false;
|
|
28244
|
+
}
|
|
28245
|
+
}
|
|
28095
28246
|
async function discoverSkillDirs(basePath) {
|
|
28096
28247
|
const result = /* @__PURE__ */ new Map();
|
|
28097
28248
|
const queue = [{ dir: basePath, depth: 0 }];
|
|
@@ -28109,7 +28260,7 @@ async function discoverSkillDirs(basePath) {
|
|
|
28109
28260
|
if (!isSafeSkillName(entry.name)) continue;
|
|
28110
28261
|
const subDir = resolve9(dir, entry.name);
|
|
28111
28262
|
const skillMd = resolve9(subDir, "SKILL.md");
|
|
28112
|
-
if (await fileExists(skillMd)) {
|
|
28263
|
+
if (await fileExists(skillMd) && !await isGeneratedOutput(skillMd)) {
|
|
28113
28264
|
if (!result.has(entry.name)) {
|
|
28114
28265
|
result.set(entry.name, subDir);
|
|
28115
28266
|
}
|
|
@@ -28193,6 +28344,10 @@ async function resolveNativeSkills(ast, registryPath, sourceFile, localPath, opt
|
|
|
28193
28344
|
if (skillMdPath && await fileExists(skillMdPath)) {
|
|
28194
28345
|
try {
|
|
28195
28346
|
const rawContent = await readFile8(skillMdPath, "utf-8");
|
|
28347
|
+
if (isGeneratedByPromptScript(rawContent)) {
|
|
28348
|
+
logger.verbose(`Ignoring generated SKILL.md for skill '${skillName}': ${skillMdPath}`);
|
|
28349
|
+
continue;
|
|
28350
|
+
}
|
|
28196
28351
|
const parsed = parseSkillMd(rawContent);
|
|
28197
28352
|
const updatedSkill = { ...skillObj };
|
|
28198
28353
|
const skillArgs = extractSkillArgs(skillObj);
|
|
@@ -28323,6 +28478,10 @@ async function discoverCommandFiles(dir, logger = noopLogger2) {
|
|
|
28323
28478
|
logger.verbose(`Skipping binary command file: ${entry.name}`);
|
|
28324
28479
|
continue;
|
|
28325
28480
|
}
|
|
28481
|
+
if (isGeneratedByPromptScript(content)) {
|
|
28482
|
+
logger.verbose(`Skipping generated command file: ${entry.name}`);
|
|
28483
|
+
continue;
|
|
28484
|
+
}
|
|
28326
28485
|
commands[cmdName] = {
|
|
28327
28486
|
type: "TextContent",
|
|
28328
28487
|
value: content.trim(),
|
|
@@ -28401,8 +28560,8 @@ function parseAgentFrontmatter(content) {
|
|
|
28401
28560
|
searchFrom = idx + 1;
|
|
28402
28561
|
}
|
|
28403
28562
|
if (endIdx === -1) return null;
|
|
28404
|
-
const yamlStr = trimmed.slice(3, endIdx).trim();
|
|
28405
|
-
const body = trimmed.slice(endIdx + 3).trim();
|
|
28563
|
+
const yamlStr = stripFrontmatterMarkerLines(trimmed.slice(3, endIdx)).trim();
|
|
28564
|
+
const body = stripLeadingHtmlMarker(trimmed.slice(endIdx + 3)).trim();
|
|
28406
28565
|
const frontmatter = {};
|
|
28407
28566
|
for (const line of yamlStr.split("\n")) {
|
|
28408
28567
|
const colonIdx = line.indexOf(":");
|
|
@@ -28439,6 +28598,10 @@ async function discoverAgentFiles(dir, logger = noopLogger2) {
|
|
|
28439
28598
|
logger.verbose(`Skipping binary agent file: ${entry.name}`);
|
|
28440
28599
|
continue;
|
|
28441
28600
|
}
|
|
28601
|
+
if (isGeneratedByPromptScript(fileContent)) {
|
|
28602
|
+
logger.verbose(`Skipping generated agent file: ${entry.name}`);
|
|
28603
|
+
continue;
|
|
28604
|
+
}
|
|
28442
28605
|
const parsed = parseAgentFrontmatter(fileContent);
|
|
28443
28606
|
if (!parsed) {
|
|
28444
28607
|
logger.verbose(`Skipping agent file without frontmatter: ${entry.name}`);
|
|
@@ -29926,6 +30089,8 @@ var GitRegistry = class {
|
|
|
29926
30089
|
options.baseDir = baseDir;
|
|
29927
30090
|
}
|
|
29928
30091
|
const git = simpleGit(options);
|
|
30092
|
+
git.env("GIT_TERMINAL_PROMPT", "0");
|
|
30093
|
+
git.env("GCM_INTERACTIVE", "never");
|
|
29929
30094
|
if (this.auth?.type === "token") {
|
|
29930
30095
|
const token = this.resolveToken();
|
|
29931
30096
|
if (token) {
|
|
@@ -30098,13 +30263,13 @@ function createGitRegistry(options) {
|
|
|
30098
30263
|
return new GitRegistry(options);
|
|
30099
30264
|
}
|
|
30100
30265
|
async function validateRemoteAccess(repoUrl, ref) {
|
|
30101
|
-
const git = simpleGit();
|
|
30266
|
+
const git = simpleGit().env("GIT_TERMINAL_PROMPT", "0").env("GCM_INTERACTIVE", "never");
|
|
30102
30267
|
try {
|
|
30103
30268
|
const isCommit = ref !== void 0 && /^[0-9a-f]{40}$/i.test(ref);
|
|
30104
30269
|
if (isCommit) {
|
|
30105
30270
|
const probeDir = await fs2.mkdtemp(join7(tmpdir(), "promptscript-ref-"));
|
|
30106
30271
|
try {
|
|
30107
|
-
const probe = simpleGit(probeDir);
|
|
30272
|
+
const probe = simpleGit(probeDir).env("GIT_TERMINAL_PROMPT", "0").env("GCM_INTERACTIVE", "never");
|
|
30108
30273
|
await probe.init();
|
|
30109
30274
|
await probe.addRemote("origin", repoUrl);
|
|
30110
30275
|
await probe.fetch(["origin", ref, "--depth=1"]);
|
|
@@ -31103,7 +31268,9 @@ var Resolver = class {
|
|
|
31103
31268
|
errors.push(...imported.errors);
|
|
31104
31269
|
if (imported.ast) {
|
|
31105
31270
|
let resolvedImport = imported.ast;
|
|
31106
|
-
const { only, exclude, remaining } = extractReservedParams(
|
|
31271
|
+
const { only, exclude, includes, excludes, remaining } = extractReservedParams(
|
|
31272
|
+
use.params
|
|
31273
|
+
);
|
|
31107
31274
|
if (imported.ast.meta?.params || remaining.length > 0) {
|
|
31108
31275
|
this.logger.debug(`Binding template parameters for ${importPath}`);
|
|
31109
31276
|
try {
|
|
@@ -31134,6 +31301,12 @@ var Resolver = class {
|
|
|
31134
31301
|
blocks: filterBlocks(resolvedImport.blocks, { only, exclude })
|
|
31135
31302
|
};
|
|
31136
31303
|
}
|
|
31304
|
+
if (includes || excludes) {
|
|
31305
|
+
this.logger.debug(
|
|
31306
|
+
`Filtering skills: ${includes ? `includes=[${includes.join(",")}]` : `excludes=[${excludes.join(",")}]`}`
|
|
31307
|
+
);
|
|
31308
|
+
resolvedImport = filterSkillsBlock(resolvedImport, { includes, excludes });
|
|
31309
|
+
}
|
|
31137
31310
|
let effectiveUse = use;
|
|
31138
31311
|
const fromConfig = this.options.skillTargets?.[use.path.raw];
|
|
31139
31312
|
if (use.outputDir && fromConfig && use.outputDir !== fromConfig) {
|
|
@@ -34309,18 +34482,21 @@ var duplicateSkills = {
|
|
|
34309
34482
|
// packages/validator/src/rules/use-block-filter.ts
|
|
34310
34483
|
init_src();
|
|
34311
34484
|
var BLOCK_TYPE_SET = new Set(BLOCK_TYPES);
|
|
34312
|
-
var
|
|
34485
|
+
var RESERVED_BLOCK_PARAMS = ["only", "exclude"];
|
|
34486
|
+
var RESERVED_SKILL_PARAMS = ["includes", "excludes"];
|
|
34313
34487
|
var useBlockFilter = {
|
|
34314
34488
|
id: "PS021",
|
|
34315
34489
|
name: "use-block-filter",
|
|
34316
|
-
description: "Validate only/exclude
|
|
34490
|
+
description: "Validate only/exclude/includes/excludes filter parameters on @use directives",
|
|
34317
34491
|
defaultSeverity: "error",
|
|
34318
34492
|
validate: (ctx) => {
|
|
34319
34493
|
for (const use of ctx.ast.uses) {
|
|
34320
34494
|
if (!use.params || use.params.length === 0) continue;
|
|
34321
34495
|
const onlyParam = use.params.find((p) => p.name === "only");
|
|
34322
34496
|
const excludeParam = use.params.find((p) => p.name === "exclude");
|
|
34323
|
-
|
|
34497
|
+
const includesParam = use.params.find((p) => p.name === "includes");
|
|
34498
|
+
const excludesParam = use.params.find((p) => p.name === "excludes");
|
|
34499
|
+
if (!onlyParam && !excludeParam && !includesParam && !excludesParam) continue;
|
|
34324
34500
|
if (onlyParam && excludeParam) {
|
|
34325
34501
|
ctx.report({
|
|
34326
34502
|
message: '"only" and "exclude" are mutually exclusive in @use',
|
|
@@ -34329,7 +34505,15 @@ var useBlockFilter = {
|
|
|
34329
34505
|
});
|
|
34330
34506
|
continue;
|
|
34331
34507
|
}
|
|
34332
|
-
|
|
34508
|
+
if (includesParam && excludesParam) {
|
|
34509
|
+
ctx.report({
|
|
34510
|
+
message: '"includes" and "excludes" are mutually exclusive in @use',
|
|
34511
|
+
location: use.loc,
|
|
34512
|
+
suggestion: "Use either includes: [...] or excludes: [...], not both"
|
|
34513
|
+
});
|
|
34514
|
+
continue;
|
|
34515
|
+
}
|
|
34516
|
+
for (const paramName of RESERVED_BLOCK_PARAMS) {
|
|
34333
34517
|
const param = paramName === "only" ? onlyParam : excludeParam;
|
|
34334
34518
|
if (!param) continue;
|
|
34335
34519
|
if (!Array.isArray(param.value)) {
|
|
@@ -34358,6 +34542,25 @@ var useBlockFilter = {
|
|
|
34358
34542
|
}
|
|
34359
34543
|
}
|
|
34360
34544
|
}
|
|
34545
|
+
for (const paramName of RESERVED_SKILL_PARAMS) {
|
|
34546
|
+
const param = paramName === "includes" ? includesParam : excludesParam;
|
|
34547
|
+
if (!param) continue;
|
|
34548
|
+
if (!Array.isArray(param.value)) {
|
|
34549
|
+
ctx.report({
|
|
34550
|
+
message: `"${paramName}" expects an array, got ${typeof param.value}. Use ${paramName}: ["skillName"]`,
|
|
34551
|
+
location: param.loc ?? use.loc
|
|
34552
|
+
});
|
|
34553
|
+
continue;
|
|
34554
|
+
}
|
|
34555
|
+
if (param.value.length === 0) {
|
|
34556
|
+
ctx.report({
|
|
34557
|
+
message: paramName === "includes" ? 'Empty "includes" filter imports nothing \u2014 consider removing this @use' : 'Empty "excludes" filter has no effect \u2014 consider removing the parameter',
|
|
34558
|
+
location: param.loc ?? use.loc,
|
|
34559
|
+
severity: "warning"
|
|
34560
|
+
});
|
|
34561
|
+
continue;
|
|
34562
|
+
}
|
|
34563
|
+
}
|
|
34361
34564
|
}
|
|
34362
34565
|
}
|
|
34363
34566
|
};
|
|
@@ -36703,9 +36906,7 @@ async function resolveRegistryPath(config, options = {}) {
|
|
|
36703
36906
|
import { parse as parseYaml5 } from "yaml";
|
|
36704
36907
|
|
|
36705
36908
|
// packages/cli/src/utils/markers.ts
|
|
36706
|
-
|
|
36707
|
-
return content.replace(/<!-- PromptScript [^>]+ -->\n*/g, "").replace(/# promptscript-generated: [^\n]+\n*/g, "");
|
|
36708
|
-
}
|
|
36909
|
+
init_src();
|
|
36709
36910
|
|
|
36710
36911
|
// packages/cli/src/utils/conflict-detector.ts
|
|
36711
36912
|
init_src();
|
|
@@ -37113,13 +37314,15 @@ function resolveCompileConfigPath(projectRoot, options) {
|
|
|
37113
37314
|
}
|
|
37114
37315
|
return configPath;
|
|
37115
37316
|
}
|
|
37116
|
-
|
|
37317
|
+
function hasPromptScriptMarker(content) {
|
|
37318
|
+
const lines = content.split("\n").slice(0, 50);
|
|
37319
|
+
return lines.some((line) => PROMPTSCRIPT_MARKERS2.some((marker) => line.includes(marker)));
|
|
37320
|
+
}
|
|
37321
|
+
async function readFileOrUndefined(filePath) {
|
|
37117
37322
|
try {
|
|
37118
|
-
|
|
37119
|
-
const lines = content.split("\n").slice(0, 50);
|
|
37120
|
-
return lines.some((line) => PROMPTSCRIPT_MARKERS2.some((marker) => line.includes(marker)));
|
|
37323
|
+
return await readFile14(filePath, "utf-8");
|
|
37121
37324
|
} catch {
|
|
37122
|
-
return
|
|
37325
|
+
return void 0;
|
|
37123
37326
|
}
|
|
37124
37327
|
}
|
|
37125
37328
|
async function promptForOverwrite(filePath, services) {
|
|
@@ -37182,69 +37385,32 @@ async function writeOutputs(outputs, options, _config, services) {
|
|
|
37182
37385
|
for (const output of outputs.values()) {
|
|
37183
37386
|
const outputPath = options.output ? resolve17(options.output, output.path) : resolve17(output.path);
|
|
37184
37387
|
const fileExists3 = existsSync13(outputPath);
|
|
37388
|
+
const existingContent = fileExists3 ? await readFileOrUndefined(outputPath) : void 0;
|
|
37389
|
+
const contentMatches = existingContent !== void 0 && stripPromptScriptMarkers(existingContent) === stripPromptScriptMarkers(output.content);
|
|
37185
37390
|
if (options.dryRun) {
|
|
37186
|
-
if (fileExists3) {
|
|
37187
|
-
const isGenerated2 = await isPromptScriptGenerated3(outputPath);
|
|
37188
|
-
if (isGenerated2) {
|
|
37189
|
-
const existingContent = await readFile14(outputPath, "utf-8");
|
|
37190
|
-
const existingWithoutMarker = stripMarkers(existingContent);
|
|
37191
|
-
const newWithoutMarker = stripMarkers(output.content);
|
|
37192
|
-
if (existingWithoutMarker === newWithoutMarker) {
|
|
37193
|
-
ConsoleOutput.dryRun(`Unchanged: ${outputPath}`);
|
|
37194
|
-
result.unchanged.push(outputPath);
|
|
37195
|
-
} else {
|
|
37196
|
-
ConsoleOutput.dryRun(`Would overwrite: ${outputPath}`);
|
|
37197
|
-
result.written.push(outputPath);
|
|
37198
|
-
}
|
|
37199
|
-
} else {
|
|
37200
|
-
const existingContent = await readFile14(outputPath, "utf-8");
|
|
37201
|
-
if (existingContent === output.content) {
|
|
37202
|
-
ConsoleOutput.dryRun(`Unchanged: ${outputPath}`);
|
|
37203
|
-
result.unchanged.push(outputPath);
|
|
37204
|
-
} else {
|
|
37205
|
-
ConsoleOutput.warning(`Would conflict: ${outputPath} (not generated by PromptScript)`);
|
|
37206
|
-
result.written.push(outputPath);
|
|
37207
|
-
}
|
|
37208
|
-
}
|
|
37209
|
-
} else {
|
|
37391
|
+
if (!fileExists3) {
|
|
37210
37392
|
ConsoleOutput.dryRun(`Would write: ${outputPath}`);
|
|
37211
37393
|
result.written.push(outputPath);
|
|
37212
|
-
}
|
|
37213
|
-
|
|
37214
|
-
|
|
37215
|
-
|
|
37216
|
-
|
|
37217
|
-
|
|
37394
|
+
} else if (contentMatches) {
|
|
37395
|
+
ConsoleOutput.dryRun(`Unchanged: ${outputPath}`);
|
|
37396
|
+
result.unchanged.push(outputPath);
|
|
37397
|
+
} else if (existingContent !== void 0 && hasPromptScriptMarker(existingContent)) {
|
|
37398
|
+
ConsoleOutput.dryRun(`Would overwrite: ${outputPath}`);
|
|
37399
|
+
result.written.push(outputPath);
|
|
37400
|
+
} else {
|
|
37401
|
+
ConsoleOutput.warning(`Would conflict: ${outputPath} (not generated by PromptScript)`);
|
|
37218
37402
|
result.written.push(outputPath);
|
|
37219
37403
|
}
|
|
37220
37404
|
continue;
|
|
37221
37405
|
}
|
|
37222
|
-
|
|
37223
|
-
if (isGenerated) {
|
|
37224
|
-
const existingContent = await readFile14(outputPath, "utf-8");
|
|
37225
|
-
const existingWithoutMarker = stripMarkers(existingContent);
|
|
37226
|
-
const newWithoutMarker = stripMarkers(output.content);
|
|
37227
|
-
if (!options.force && existingWithoutMarker === newWithoutMarker) {
|
|
37228
|
-
if (output.mode !== void 0) {
|
|
37229
|
-
await chmod2(outputPath, output.mode);
|
|
37230
|
-
}
|
|
37231
|
-
ConsoleOutput.unchanged(outputPath);
|
|
37232
|
-
result.unchanged.push(outputPath);
|
|
37233
|
-
continue;
|
|
37234
|
-
}
|
|
37406
|
+
if (!fileExists3) {
|
|
37235
37407
|
if (await safeWrite(outputPath, output.content, output.mode)) {
|
|
37236
37408
|
ConsoleOutput.success(outputPath);
|
|
37237
37409
|
result.written.push(outputPath);
|
|
37238
37410
|
}
|
|
37239
37411
|
continue;
|
|
37240
37412
|
}
|
|
37241
|
-
|
|
37242
|
-
try {
|
|
37243
|
-
const existingContent = await readFile14(outputPath, "utf-8");
|
|
37244
|
-
contentMatches = existingContent === output.content;
|
|
37245
|
-
} catch {
|
|
37246
|
-
}
|
|
37247
|
-
if (!options.force && contentMatches) {
|
|
37413
|
+
if (contentMatches) {
|
|
37248
37414
|
if (output.mode !== void 0) {
|
|
37249
37415
|
await chmod2(outputPath, output.mode);
|
|
37250
37416
|
}
|
|
@@ -37252,6 +37418,13 @@ async function writeOutputs(outputs, options, _config, services) {
|
|
|
37252
37418
|
result.unchanged.push(outputPath);
|
|
37253
37419
|
continue;
|
|
37254
37420
|
}
|
|
37421
|
+
if (existingContent !== void 0 && hasPromptScriptMarker(existingContent)) {
|
|
37422
|
+
if (await safeWrite(outputPath, output.content, output.mode)) {
|
|
37423
|
+
ConsoleOutput.success(outputPath);
|
|
37424
|
+
result.written.push(outputPath);
|
|
37425
|
+
}
|
|
37426
|
+
continue;
|
|
37427
|
+
}
|
|
37255
37428
|
if (options.force || overwriteAll) {
|
|
37256
37429
|
if (await safeWrite(outputPath, output.content, output.mode)) {
|
|
37257
37430
|
ConsoleOutput.success(outputPath);
|
|
@@ -38227,8 +38400,8 @@ async function compareOutput(_name, output, _config, showFull, pager) {
|
|
|
38227
38400
|
return true;
|
|
38228
38401
|
}
|
|
38229
38402
|
const existingContent = await readFile15(outputPath, "utf-8");
|
|
38230
|
-
const existingStripped =
|
|
38231
|
-
const newStripped =
|
|
38403
|
+
const existingStripped = stripPromptScriptMarkers(existingContent);
|
|
38404
|
+
const newStripped = stripPromptScriptMarkers(newContent);
|
|
38232
38405
|
if (existingStripped === newStripped) {
|
|
38233
38406
|
pager.write(chalk2.gray(` ${outputPath} (no changes)`));
|
|
38234
38407
|
return false;
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../../../packages/cli/src/commands/compile.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAkBlD,OAAO,EAAE,KAAK,WAAW,EAAyB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../../../packages/cli/src/commands/compile.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAkBlD,OAAO,EAAE,KAAK,WAAW,EAAyB,MAAM,gBAAgB,CAAC;AAmhBzE;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,QAAQ,GAAE,WAAqC,GAC9C,OAAO,CAAC,IAAI,CAAC,CAEf"}
|
package/src/utils/markers.d.ts
CHANGED
|
@@ -2,15 +2,8 @@
|
|
|
2
2
|
* PromptScript generation marker utilities.
|
|
3
3
|
*
|
|
4
4
|
* Markers are added to compiled output files so the compiler can identify
|
|
5
|
-
* files it previously generated.
|
|
6
|
-
*
|
|
5
|
+
* files it previously generated. Stripping them before content comparison
|
|
6
|
+
* avoids false diffs from timestamp-only changes.
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
|
-
* Strip PromptScript generation markers from content for comparison purposes.
|
|
10
|
-
* This allows comparing actual content changes while ignoring timestamp updates.
|
|
11
|
-
*
|
|
12
|
-
* Regex literals are inlined to avoid stateful module-level RegExp objects
|
|
13
|
-
* with the `g` flag (which maintain a `lastIndex` cursor between calls).
|
|
14
|
-
*/
|
|
15
|
-
export declare function stripMarkers(content: string): string;
|
|
8
|
+
export { stripPromptScriptMarkers as stripMarkers } from '@promptscript/core';
|
|
16
9
|
//# sourceMappingURL=markers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../../../../../packages/cli/src/utils/markers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH
|
|
1
|
+
{"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../../../../../packages/cli/src/utils/markers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,wBAAwB,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|