pulse-framework-cli 0.4.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/dist/commands/checkpoint.d.ts +2 -0
- package/dist/commands/checkpoint.js +129 -0
- package/dist/commands/correct.d.ts +2 -0
- package/dist/commands/correct.js +77 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +183 -0
- package/dist/commands/escalate.d.ts +2 -0
- package/dist/commands/escalate.js +226 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +570 -0
- package/dist/commands/learn.d.ts +2 -0
- package/dist/commands/learn.js +137 -0
- package/dist/commands/profile.d.ts +2 -0
- package/dist/commands/profile.js +39 -0
- package/dist/commands/reset.d.ts +2 -0
- package/dist/commands/reset.js +130 -0
- package/dist/commands/review.d.ts +2 -0
- package/dist/commands/review.js +129 -0
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.js +272 -0
- package/dist/commands/start.d.ts +2 -0
- package/dist/commands/start.js +196 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +239 -0
- package/dist/commands/watch.d.ts +2 -0
- package/dist/commands/watch.js +98 -0
- package/dist/hooks/install.d.ts +1 -0
- package/dist/hooks/install.js +89 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +40 -0
- package/dist/lib/artifacts.d.ts +7 -0
- package/dist/lib/artifacts.js +52 -0
- package/dist/lib/briefing.d.ts +77 -0
- package/dist/lib/briefing.js +231 -0
- package/dist/lib/clipboard.d.ts +9 -0
- package/dist/lib/clipboard.js +116 -0
- package/dist/lib/config.d.ts +14 -0
- package/dist/lib/config.js +167 -0
- package/dist/lib/context-export.d.ts +30 -0
- package/dist/lib/context-export.js +149 -0
- package/dist/lib/exec.d.ts +9 -0
- package/dist/lib/exec.js +23 -0
- package/dist/lib/git.d.ts +24 -0
- package/dist/lib/git.js +74 -0
- package/dist/lib/input.d.ts +15 -0
- package/dist/lib/input.js +80 -0
- package/dist/lib/notifications.d.ts +2 -0
- package/dist/lib/notifications.js +25 -0
- package/dist/lib/paths.d.ts +4 -0
- package/dist/lib/paths.js +39 -0
- package/dist/lib/prompts.d.ts +43 -0
- package/dist/lib/prompts.js +270 -0
- package/dist/lib/scanner.d.ts +37 -0
- package/dist/lib/scanner.js +413 -0
- package/dist/lib/types.d.ts +37 -0
- package/dist/lib/types.js +2 -0
- package/package.json +42 -0
- package/templates/.cursorrules +159 -0
- package/templates/AGENTS.md +198 -0
- package/templates/cursor/mcp.json +9 -0
- package/templates/cursor/pulse.mdc +144 -0
- package/templates/roles/architect.cursorrules +15 -0
- package/templates/roles/backend.cursorrules +12 -0
- package/templates/roles/frontend.cursorrules +12 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Context Export - Selective file export for escalation
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.exportFiles = exportFiles;
|
|
10
|
+
exports.autoDetectFiles = autoDetectFiles;
|
|
11
|
+
exports.renderContextExport = renderContextExport;
|
|
12
|
+
exports.renderContextExportXml = renderContextExportXml;
|
|
13
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
14
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
15
|
+
const glob_1 = require("glob");
|
|
16
|
+
const MAX_LINES_PER_FILE = 500;
|
|
17
|
+
const MAX_TOTAL_LINES = 2000;
|
|
18
|
+
/**
|
|
19
|
+
* Read and export specific files
|
|
20
|
+
*/
|
|
21
|
+
async function exportFiles(repoRoot, patterns) {
|
|
22
|
+
const files = [];
|
|
23
|
+
let totalLines = 0;
|
|
24
|
+
let truncated = false;
|
|
25
|
+
for (const pattern of patterns) {
|
|
26
|
+
// Resolve glob pattern
|
|
27
|
+
const matches = await (0, glob_1.glob)(pattern, {
|
|
28
|
+
cwd: repoRoot,
|
|
29
|
+
nodir: true,
|
|
30
|
+
ignore: ["node_modules/**", ".git/**", "dist/**", "build/**", ".pulse/**"],
|
|
31
|
+
});
|
|
32
|
+
for (const match of matches) {
|
|
33
|
+
if (totalLines >= MAX_TOTAL_LINES) {
|
|
34
|
+
truncated = true;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const fullPath = node_path_1.default.join(repoRoot, match);
|
|
39
|
+
const content = await promises_1.default.readFile(fullPath, "utf8");
|
|
40
|
+
const lines = content.split("\n").length;
|
|
41
|
+
// Truncate if too long
|
|
42
|
+
let exportContent = content;
|
|
43
|
+
if (lines > MAX_LINES_PER_FILE) {
|
|
44
|
+
const truncLines = content.split("\n").slice(0, MAX_LINES_PER_FILE);
|
|
45
|
+
exportContent = truncLines.join("\n") + `\n\n// ... truncated (${lines - MAX_LINES_PER_FILE} more lines)`;
|
|
46
|
+
truncated = true;
|
|
47
|
+
}
|
|
48
|
+
files.push({
|
|
49
|
+
path: match,
|
|
50
|
+
content: exportContent,
|
|
51
|
+
lines: Math.min(lines, MAX_LINES_PER_FILE),
|
|
52
|
+
});
|
|
53
|
+
totalLines += Math.min(lines, MAX_LINES_PER_FILE);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Skip files that can't be read
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (truncated)
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
files,
|
|
64
|
+
totalFiles: files.length,
|
|
65
|
+
totalLines,
|
|
66
|
+
truncated,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Auto-detect relevant files from git diff
|
|
71
|
+
*/
|
|
72
|
+
async function autoDetectFiles(repoRoot, diffNameStatus) {
|
|
73
|
+
const files = [];
|
|
74
|
+
for (const line of diffNameStatus.split("\n")) {
|
|
75
|
+
const trimmed = line.trim();
|
|
76
|
+
if (!trimmed)
|
|
77
|
+
continue;
|
|
78
|
+
const parts = trimmed.split(/\s+/);
|
|
79
|
+
if (parts.length < 2)
|
|
80
|
+
continue;
|
|
81
|
+
const status = parts[0];
|
|
82
|
+
const file = parts[1];
|
|
83
|
+
// Include modified and added files
|
|
84
|
+
if ((status === "M" || status === "A") && file) {
|
|
85
|
+
// Skip non-code files
|
|
86
|
+
if (isCodeFile(file)) {
|
|
87
|
+
files.push(file);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return files;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Check if file is a code file
|
|
95
|
+
*/
|
|
96
|
+
function isCodeFile(filepath) {
|
|
97
|
+
const codeExtensions = [
|
|
98
|
+
".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs",
|
|
99
|
+
".py", ".rb", ".go", ".rs", ".java", ".kt",
|
|
100
|
+
".c", ".cpp", ".h", ".hpp", ".cs",
|
|
101
|
+
".vue", ".svelte", ".astro",
|
|
102
|
+
".json", ".yaml", ".yml", ".toml",
|
|
103
|
+
".sql", ".graphql", ".gql",
|
|
104
|
+
".sh", ".bash", ".zsh",
|
|
105
|
+
".css", ".scss", ".less",
|
|
106
|
+
".html", ".xml",
|
|
107
|
+
];
|
|
108
|
+
const ext = node_path_1.default.extname(filepath).toLowerCase();
|
|
109
|
+
return codeExtensions.includes(ext);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Render context export as markdown
|
|
113
|
+
*/
|
|
114
|
+
function renderContextExport(ctx) {
|
|
115
|
+
const lines = [];
|
|
116
|
+
lines.push(`## Kontext-Export`);
|
|
117
|
+
lines.push(``);
|
|
118
|
+
lines.push(`**${ctx.totalFiles} Dateien, ~${ctx.totalLines} Zeilen**`);
|
|
119
|
+
if (ctx.truncated) {
|
|
120
|
+
lines.push(`⚠️ Truncated (Limit: ${MAX_TOTAL_LINES} Zeilen)`);
|
|
121
|
+
}
|
|
122
|
+
lines.push(``);
|
|
123
|
+
for (const file of ctx.files) {
|
|
124
|
+
const ext = node_path_1.default.extname(file.path).slice(1) || "txt";
|
|
125
|
+
lines.push(`### \`${file.path}\` (${file.lines} Zeilen)`);
|
|
126
|
+
lines.push(``);
|
|
127
|
+
lines.push("```" + ext);
|
|
128
|
+
lines.push(file.content);
|
|
129
|
+
lines.push("```");
|
|
130
|
+
lines.push(``);
|
|
131
|
+
}
|
|
132
|
+
return lines.join("\n");
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Render context export in XML-style for AI models
|
|
136
|
+
*/
|
|
137
|
+
function renderContextExportXml(ctx) {
|
|
138
|
+
const lines = [];
|
|
139
|
+
lines.push(`<context_export files="${ctx.totalFiles}" lines="${ctx.totalLines}"${ctx.truncated ? ' truncated="true"' : ''}>`);
|
|
140
|
+
lines.push(``);
|
|
141
|
+
for (const file of ctx.files) {
|
|
142
|
+
lines.push(`<file path="${file.path}" lines="${file.lines}">`);
|
|
143
|
+
lines.push(file.content);
|
|
144
|
+
lines.push(`</file>`);
|
|
145
|
+
lines.push(``);
|
|
146
|
+
}
|
|
147
|
+
lines.push(`</context_export>`);
|
|
148
|
+
return lines.join("\n");
|
|
149
|
+
}
|
package/dist/lib/exec.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.exec = exec;
|
|
4
|
+
const node_child_process_1 = require("node:child_process");
|
|
5
|
+
const node_util_1 = require("node:util");
|
|
6
|
+
const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
7
|
+
async function exec(file, args, opts) {
|
|
8
|
+
try {
|
|
9
|
+
const { stdout, stderr } = await execFileAsync(file, args, {
|
|
10
|
+
cwd: opts?.cwd,
|
|
11
|
+
env: { ...process.env, ...(opts?.env ?? {}) },
|
|
12
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
13
|
+
});
|
|
14
|
+
return { stdout: String(stdout), stderr: String(stderr), exitCode: 0 };
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
return {
|
|
18
|
+
stdout: String(err?.stdout ?? ""),
|
|
19
|
+
stderr: String(err?.stderr ?? err?.message ?? ""),
|
|
20
|
+
exitCode: Number(err?.code ?? 1),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare function gitCurrentBranch(repoRoot: string): Promise<string>;
|
|
2
|
+
export declare function gitIsMainBranch(repoRoot: string): Promise<boolean>;
|
|
3
|
+
export declare function gitCreateBranch(repoRoot: string, name: string): Promise<boolean>;
|
|
4
|
+
export declare function git(repoRoot: string, args: string[]): Promise<{
|
|
5
|
+
ok: boolean;
|
|
6
|
+
stdout: string;
|
|
7
|
+
stderr: string;
|
|
8
|
+
exitCode: number;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function gitStatusPorcelain(repoRoot: string): Promise<string>;
|
|
11
|
+
export declare function gitLogOneline(repoRoot: string, n?: number): Promise<string>;
|
|
12
|
+
export declare function gitDiffStat(repoRoot: string, opts?: {
|
|
13
|
+
staged?: boolean;
|
|
14
|
+
}): Promise<string>;
|
|
15
|
+
export declare function gitDiffNameStatus(repoRoot: string, opts?: {
|
|
16
|
+
staged?: boolean;
|
|
17
|
+
}): Promise<string>;
|
|
18
|
+
export declare function gitDiffNumstat(repoRoot: string, opts?: {
|
|
19
|
+
staged?: boolean;
|
|
20
|
+
}): Promise<string>;
|
|
21
|
+
export declare function gitDiffText(repoRoot: string, opts?: {
|
|
22
|
+
staged?: boolean;
|
|
23
|
+
maxLines?: number;
|
|
24
|
+
}): Promise<string>;
|
package/dist/lib/git.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gitCurrentBranch = gitCurrentBranch;
|
|
4
|
+
exports.gitIsMainBranch = gitIsMainBranch;
|
|
5
|
+
exports.gitCreateBranch = gitCreateBranch;
|
|
6
|
+
exports.git = git;
|
|
7
|
+
exports.gitStatusPorcelain = gitStatusPorcelain;
|
|
8
|
+
exports.gitLogOneline = gitLogOneline;
|
|
9
|
+
exports.gitDiffStat = gitDiffStat;
|
|
10
|
+
exports.gitDiffNameStatus = gitDiffNameStatus;
|
|
11
|
+
exports.gitDiffNumstat = gitDiffNumstat;
|
|
12
|
+
exports.gitDiffText = gitDiffText;
|
|
13
|
+
const exec_js_1 = require("./exec.js");
|
|
14
|
+
// ════════════════════════════════════════════════════════════════════════════
|
|
15
|
+
// Branch-Utilities
|
|
16
|
+
// ════════════════════════════════════════════════════════════════════════════
|
|
17
|
+
async function gitCurrentBranch(repoRoot) {
|
|
18
|
+
const res = await (0, exec_js_1.exec)("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: repoRoot });
|
|
19
|
+
return res.stdout.trim();
|
|
20
|
+
}
|
|
21
|
+
async function gitIsMainBranch(repoRoot) {
|
|
22
|
+
const branch = await gitCurrentBranch(repoRoot);
|
|
23
|
+
return ["main", "master", "develop", "development"].includes(branch.toLowerCase());
|
|
24
|
+
}
|
|
25
|
+
async function gitCreateBranch(repoRoot, name) {
|
|
26
|
+
const res = await (0, exec_js_1.exec)("git", ["checkout", "-b", name], { cwd: repoRoot });
|
|
27
|
+
return res.exitCode === 0;
|
|
28
|
+
}
|
|
29
|
+
async function git(repoRoot, args) {
|
|
30
|
+
const res = await (0, exec_js_1.exec)("git", args, { cwd: repoRoot });
|
|
31
|
+
return { ok: res.exitCode === 0, stdout: res.stdout, stderr: res.stderr, exitCode: res.exitCode };
|
|
32
|
+
}
|
|
33
|
+
async function gitStatusPorcelain(repoRoot) {
|
|
34
|
+
const res = await git(repoRoot, ["status", "--porcelain"]);
|
|
35
|
+
return res.stdout.trimEnd();
|
|
36
|
+
}
|
|
37
|
+
async function gitLogOneline(repoRoot, n = 5) {
|
|
38
|
+
const res = await git(repoRoot, ["log", "--oneline", `-${n}`]);
|
|
39
|
+
return res.stdout.trimEnd();
|
|
40
|
+
}
|
|
41
|
+
async function gitDiffStat(repoRoot, opts) {
|
|
42
|
+
const baseArgs = ["diff", "--stat"];
|
|
43
|
+
if (opts?.staged)
|
|
44
|
+
baseArgs.push("--staged");
|
|
45
|
+
const res = await git(repoRoot, baseArgs);
|
|
46
|
+
return res.stdout.trimEnd();
|
|
47
|
+
}
|
|
48
|
+
async function gitDiffNameStatus(repoRoot, opts) {
|
|
49
|
+
const baseArgs = ["diff", "--name-status"];
|
|
50
|
+
if (opts?.staged)
|
|
51
|
+
baseArgs.push("--staged");
|
|
52
|
+
const res = await git(repoRoot, baseArgs);
|
|
53
|
+
return res.stdout.trimEnd();
|
|
54
|
+
}
|
|
55
|
+
async function gitDiffNumstat(repoRoot, opts) {
|
|
56
|
+
const baseArgs = ["diff", "--numstat"];
|
|
57
|
+
if (opts?.staged)
|
|
58
|
+
baseArgs.push("--staged");
|
|
59
|
+
const res = await git(repoRoot, baseArgs);
|
|
60
|
+
return res.stdout.trimEnd();
|
|
61
|
+
}
|
|
62
|
+
async function gitDiffText(repoRoot, opts) {
|
|
63
|
+
const baseArgs = ["diff"];
|
|
64
|
+
if (opts?.staged)
|
|
65
|
+
baseArgs.push("--staged");
|
|
66
|
+
const res = await git(repoRoot, baseArgs);
|
|
67
|
+
if (opts?.maxLines && res.stdout) {
|
|
68
|
+
const lines = res.stdout.split("\n");
|
|
69
|
+
if (lines.length > opts.maxLines) {
|
|
70
|
+
return lines.slice(0, opts.maxLines).join("\n") + `\n\n... (truncated, ${lines.length - opts.maxLines} more lines)`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return res.stdout;
|
|
74
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt for text input with optional default value
|
|
3
|
+
*/
|
|
4
|
+
export declare function promptText(label: string, defaultValue?: string): Promise<string>;
|
|
5
|
+
/**
|
|
6
|
+
* Prompt for selection from a list of choices
|
|
7
|
+
*/
|
|
8
|
+
export declare function promptSelect(label: string, choices: Array<{
|
|
9
|
+
value: string;
|
|
10
|
+
label: string;
|
|
11
|
+
}>, defaultValue?: string): Promise<string>;
|
|
12
|
+
/**
|
|
13
|
+
* Prompt for yes/no confirmation
|
|
14
|
+
*/
|
|
15
|
+
export declare function promptConfirm(label: string, defaultYes?: boolean): Promise<boolean>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.promptText = promptText;
|
|
7
|
+
exports.promptSelect = promptSelect;
|
|
8
|
+
exports.promptConfirm = promptConfirm;
|
|
9
|
+
const promises_1 = __importDefault(require("node:readline/promises"));
|
|
10
|
+
/**
|
|
11
|
+
* Prompt for text input with optional default value
|
|
12
|
+
*/
|
|
13
|
+
async function promptText(label, defaultValue = "") {
|
|
14
|
+
const rl = promises_1.default.createInterface({ input: process.stdin, output: process.stdout });
|
|
15
|
+
try {
|
|
16
|
+
const q = defaultValue ? `${label} (default: ${defaultValue}): ` : `${label}: `;
|
|
17
|
+
const ans = await rl.question(q);
|
|
18
|
+
const v = ans.trim();
|
|
19
|
+
return v.length ? v : defaultValue;
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
rl.close();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Prompt for selection from a list of choices
|
|
27
|
+
*/
|
|
28
|
+
async function promptSelect(label, choices, defaultValue) {
|
|
29
|
+
const rl = promises_1.default.createInterface({ input: process.stdin, output: process.stdout });
|
|
30
|
+
try {
|
|
31
|
+
// eslint-disable-next-line no-console
|
|
32
|
+
console.log(`${label}:\n`);
|
|
33
|
+
choices.forEach((choice, index) => {
|
|
34
|
+
const marker = defaultValue === choice.value ? " (default)" : "";
|
|
35
|
+
// eslint-disable-next-line no-console
|
|
36
|
+
console.log(` ${index + 1}. ${choice.label}${marker}`);
|
|
37
|
+
});
|
|
38
|
+
// eslint-disable-next-line no-console
|
|
39
|
+
console.log("");
|
|
40
|
+
const ans = await rl.question("Nummer wählen: ");
|
|
41
|
+
const num = parseInt(ans.trim(), 10);
|
|
42
|
+
if (num >= 1 && num <= choices.length) {
|
|
43
|
+
const choice = choices[num - 1];
|
|
44
|
+
if (choice)
|
|
45
|
+
return choice.value;
|
|
46
|
+
}
|
|
47
|
+
// If user typed the value directly
|
|
48
|
+
const found = choices.find((c) => c.value.toLowerCase() === ans.trim().toLowerCase());
|
|
49
|
+
if (found) {
|
|
50
|
+
return found.value;
|
|
51
|
+
}
|
|
52
|
+
// Return default or first choice
|
|
53
|
+
if (defaultValue)
|
|
54
|
+
return defaultValue;
|
|
55
|
+
const first = choices[0];
|
|
56
|
+
return first ? first.value : "";
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
rl.close();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Prompt for yes/no confirmation
|
|
64
|
+
*/
|
|
65
|
+
async function promptConfirm(label, defaultYes = false) {
|
|
66
|
+
const rl = promises_1.default.createInterface({ input: process.stdin, output: process.stdout });
|
|
67
|
+
try {
|
|
68
|
+
const hint = defaultYes ? "(J/n)" : "(j/N)";
|
|
69
|
+
const ans = await rl.question(`${label} ${hint}: `);
|
|
70
|
+
const v = ans.trim().toLowerCase();
|
|
71
|
+
if (v === "j" || v === "y" || v === "ja" || v === "yes")
|
|
72
|
+
return true;
|
|
73
|
+
if (v === "n" || v === "nein" || v === "no")
|
|
74
|
+
return false;
|
|
75
|
+
return defaultYes;
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
rl.close();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.notify = notify;
|
|
7
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
8
|
+
const exec_js_1 = require("./exec.js");
|
|
9
|
+
async function notify(mode, title, message) {
|
|
10
|
+
if (mode === "terminal" || mode === "both") {
|
|
11
|
+
// eslint-disable-next-line no-console
|
|
12
|
+
console.log(`\n[PULSE] ${title}\n${message}\n`);
|
|
13
|
+
}
|
|
14
|
+
if (mode === "macos" || mode === "both") {
|
|
15
|
+
if (node_os_1.default.platform() !== "darwin")
|
|
16
|
+
return;
|
|
17
|
+
// macOS notification via osascript
|
|
18
|
+
const script = `display notification ${jsonString(message)} with title ${jsonString(title)}`;
|
|
19
|
+
await (0, exec_js_1.exec)("osascript", ["-e", script]);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function jsonString(s) {
|
|
23
|
+
// osascript expects quoted AppleScript strings; JSON string works as a safe quoted string
|
|
24
|
+
return JSON.stringify(s);
|
|
25
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.findRepoRoot = findRepoRoot;
|
|
7
|
+
exports.pulseDir = pulseDir;
|
|
8
|
+
exports.stateFile = stateFile;
|
|
9
|
+
exports.configFile = configFile;
|
|
10
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
async function findRepoRoot(startDir) {
|
|
13
|
+
let cur = node_path_1.default.resolve(startDir);
|
|
14
|
+
for (let i = 0; i < 50; i++) {
|
|
15
|
+
const gitDir = node_path_1.default.join(cur, ".git");
|
|
16
|
+
try {
|
|
17
|
+
const st = await promises_1.default.stat(gitDir);
|
|
18
|
+
if (st.isDirectory())
|
|
19
|
+
return cur;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// ignore
|
|
23
|
+
}
|
|
24
|
+
const parent = node_path_1.default.dirname(cur);
|
|
25
|
+
if (parent === cur)
|
|
26
|
+
return null;
|
|
27
|
+
cur = parent;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
function pulseDir(repoRoot) {
|
|
32
|
+
return node_path_1.default.join(repoRoot, ".pulse");
|
|
33
|
+
}
|
|
34
|
+
function stateFile(repoRoot) {
|
|
35
|
+
return node_path_1.default.join(pulseDir(repoRoot), "state.json");
|
|
36
|
+
}
|
|
37
|
+
function configFile(repoRoot) {
|
|
38
|
+
return node_path_1.default.join(repoRoot, "pulse.config.json");
|
|
39
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { PulseLayer } from "./types.js";
|
|
2
|
+
export type SixElements = {
|
|
3
|
+
role?: string;
|
|
4
|
+
context?: string;
|
|
5
|
+
input?: string;
|
|
6
|
+
action?: string;
|
|
7
|
+
output?: string;
|
|
8
|
+
examples?: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Generates a 6-Element prompt exactly as specified in the PULSE Framework.
|
|
12
|
+
* This is the core template that should be copy-pasted into AI tools.
|
|
13
|
+
*/
|
|
14
|
+
export declare function renderSixElementPrompt(layer: PulseLayer, el: SixElements): string;
|
|
15
|
+
export declare function renderIstSollPrompt(options: {
|
|
16
|
+
ist: string;
|
|
17
|
+
soll: string;
|
|
18
|
+
error?: string;
|
|
19
|
+
context?: string;
|
|
20
|
+
}): string;
|
|
21
|
+
export declare function renderEscalationPrompt(options: {
|
|
22
|
+
cursorExplanation: string;
|
|
23
|
+
errorText: string;
|
|
24
|
+
gitLog: string;
|
|
25
|
+
gitDiff: string;
|
|
26
|
+
question: string;
|
|
27
|
+
codeSnippets?: string;
|
|
28
|
+
attempts?: string[];
|
|
29
|
+
}): string;
|
|
30
|
+
export type PromptTemplate = {
|
|
31
|
+
id: string;
|
|
32
|
+
name: string;
|
|
33
|
+
description: string;
|
|
34
|
+
layer: PulseLayer;
|
|
35
|
+
defaults: Partial<SixElements>;
|
|
36
|
+
};
|
|
37
|
+
export declare const PROMPT_TEMPLATES: PromptTemplate[];
|
|
38
|
+
export declare function countProvidedElements(el: SixElements): number;
|
|
39
|
+
export declare function validateOneAction(action: string | undefined): string | null;
|
|
40
|
+
/**
|
|
41
|
+
* Get template by ID
|
|
42
|
+
*/
|
|
43
|
+
export declare function getTemplateById(id: string): PromptTemplate | undefined;
|