codeep 1.2.1 → 1.2.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/dist/renderer/main.js +38 -37
- package/dist/utils/skills.js +23 -3
- package/package.json +1 -1
package/dist/renderer/main.js
CHANGED
|
@@ -501,50 +501,51 @@ async function runSkill(nameOrShortcut, args) {
|
|
|
501
501
|
const params = parseSkillArgs(args.join(' '), skill);
|
|
502
502
|
app.addMessage({ role: 'user', content: `/${skill.name}${args.length ? ' ' + args.join(' ') : ''}` });
|
|
503
503
|
trackSkillUsage(skill.name);
|
|
504
|
-
const {
|
|
504
|
+
const { spawnSync } = await import('child_process');
|
|
505
505
|
try {
|
|
506
506
|
const result = await executeSkill(skill, params, {
|
|
507
507
|
onCommand: async (cmd) => {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
508
|
+
// Use spawnSync via shell for reliable stdout+stderr capture
|
|
509
|
+
const proc = spawnSync(cmd, {
|
|
510
|
+
cwd: projectPath || process.cwd(),
|
|
511
|
+
encoding: 'utf-8',
|
|
512
|
+
timeout: 60000,
|
|
513
|
+
shell: true,
|
|
514
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
515
|
+
});
|
|
516
|
+
const stdout = (proc.stdout || '').trim();
|
|
517
|
+
const stderr = (proc.stderr || '').trim();
|
|
518
|
+
const output = stdout || stderr || '';
|
|
519
|
+
if (proc.status === 0) {
|
|
520
|
+
if (output) {
|
|
521
|
+
app.addMessage({ role: 'system', content: `\`${cmd}\`\n\`\`\`\n${output}\n\`\`\`` });
|
|
518
522
|
}
|
|
519
|
-
return
|
|
523
|
+
return output;
|
|
520
524
|
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const stdout = (error.stdout || '').trim();
|
|
525
|
-
// Git commands output progress/info to stderr even on success
|
|
526
|
-
if (error.status === 0 || stderr.includes('up-to-date') || stderr.includes('up to date') || stderr.includes('Already up to date')) {
|
|
527
|
-
const result = stdout || stderr;
|
|
528
|
-
if (result) {
|
|
529
|
-
app.addMessage({ role: 'system', content: `\`${cmd}\`\n\`\`\`\n${result}\n\`\`\`` });
|
|
530
|
-
}
|
|
531
|
-
return result;
|
|
532
|
-
}
|
|
533
|
-
const errOutput = stderr || stdout;
|
|
534
|
-
if (errOutput) {
|
|
535
|
-
app.addMessage({ role: 'system', content: `\`${cmd}\` failed:\n\`\`\`\n${errOutput}\n\`\`\`` });
|
|
536
|
-
}
|
|
537
|
-
throw new Error(errOutput || error.message || 'Command failed');
|
|
525
|
+
// Non-zero exit
|
|
526
|
+
if (output) {
|
|
527
|
+
app.addMessage({ role: 'system', content: `\`${cmd}\` failed:\n\`\`\`\n${output}\n\`\`\`` });
|
|
538
528
|
}
|
|
529
|
+
throw new Error(output || `Command exited with code ${proc.status}`);
|
|
539
530
|
},
|
|
540
|
-
onPrompt: (prompt) => {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
531
|
+
onPrompt: async (prompt) => {
|
|
532
|
+
try {
|
|
533
|
+
app.addMessage({ role: 'user', content: prompt });
|
|
534
|
+
app.startStreaming();
|
|
535
|
+
const history = app.getChatHistory();
|
|
536
|
+
const response = await chat(prompt, history, (chunk) => {
|
|
537
|
+
app.addStreamChunk(chunk);
|
|
538
|
+
}, undefined, projectContext, undefined);
|
|
539
|
+
app.endStreaming();
|
|
540
|
+
// Return the AI response text for use in subsequent steps
|
|
541
|
+
const lastMsg = app.getMessages();
|
|
542
|
+
const assistantMsg = lastMsg[lastMsg.length - 1];
|
|
543
|
+
return (assistantMsg?.role === 'assistant' ? assistantMsg.content : response || '').trim();
|
|
544
|
+
}
|
|
545
|
+
catch (err) {
|
|
546
|
+
app.endStreaming();
|
|
547
|
+
throw err;
|
|
548
|
+
}
|
|
548
549
|
},
|
|
549
550
|
onAgent: (task) => {
|
|
550
551
|
return new Promise((resolve, reject) => {
|
package/dist/utils/skills.js
CHANGED
|
@@ -20,9 +20,10 @@ const BUILT_IN_SKILLS = [
|
|
|
20
20
|
{ name: 'message', description: 'Optional commit message (skips AI generation)', required: false },
|
|
21
21
|
],
|
|
22
22
|
steps: [
|
|
23
|
-
{ type: '
|
|
23
|
+
{ type: 'command', content: 'git diff --cached --stat || git diff --stat' },
|
|
24
|
+
{ type: 'prompt', content: 'Based on this git diff, generate ONLY a conventional commit message (no explanation, no markdown). Format: type(scope): description. Types: feat, fix, docs, style, refactor, test, chore. Be concise. One line only.\n\n${_prev}' },
|
|
24
25
|
{ type: 'confirm', content: 'Commit with this message?' },
|
|
25
|
-
{ type: 'command', content: 'git add -A && git commit -m "${
|
|
26
|
+
{ type: 'command', content: 'git add -A && git commit -m "${_prev}"' },
|
|
26
27
|
{ type: 'notify', content: 'Changes committed successfully!' },
|
|
27
28
|
],
|
|
28
29
|
},
|
|
@@ -707,6 +708,23 @@ export function parseSkillArgs(args, skill) {
|
|
|
707
708
|
}
|
|
708
709
|
return result;
|
|
709
710
|
}
|
|
711
|
+
/**
|
|
712
|
+
* Sanitize text for safe use inside shell commands.
|
|
713
|
+
* Strips markdown formatting and escapes double quotes.
|
|
714
|
+
*/
|
|
715
|
+
function sanitizeForShell(text) {
|
|
716
|
+
return text
|
|
717
|
+
// Strip markdown code blocks
|
|
718
|
+
.replace(/```[\s\S]*?```/g, '')
|
|
719
|
+
// Strip inline backticks
|
|
720
|
+
.replace(/`([^`]*)`/g, '$1')
|
|
721
|
+
// Strip bold/italic markers
|
|
722
|
+
.replace(/\*{1,3}([^*]+)\*{1,3}/g, '$1')
|
|
723
|
+
// Take only the first non-empty line (commit messages should be one line)
|
|
724
|
+
.split('\n').map(l => l.trim()).filter(Boolean)[0] || text.trim()
|
|
725
|
+
// Escape double quotes for shell safety
|
|
726
|
+
.replace(/"/g, '\\"');
|
|
727
|
+
}
|
|
710
728
|
/**
|
|
711
729
|
* Interpolate parameters into skill step content
|
|
712
730
|
*/
|
|
@@ -778,7 +796,9 @@ export async function executeSkill(skill, params, callbacks) {
|
|
|
778
796
|
let lastOutput = '';
|
|
779
797
|
for (const step of skill.steps) {
|
|
780
798
|
// Interpolate params and ${_prev} into step content
|
|
781
|
-
|
|
799
|
+
// For command steps, sanitize _prev for safe shell usage
|
|
800
|
+
const sanitizedPrev = step.type === 'command' ? sanitizeForShell(lastOutput) : lastOutput;
|
|
801
|
+
const allParams = { ...params, _prev: sanitizedPrev };
|
|
782
802
|
const content = interpolateParams(step.content, allParams);
|
|
783
803
|
try {
|
|
784
804
|
let result = '';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeep",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "AI-powered coding assistant built for the terminal. Multiple LLM providers, project-aware context, and a seamless development workflow.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|