-
-
Notifications
You must be signed in to change notification settings - Fork 82
Expand file tree
/
Copy pathprojectCommands.ts
More file actions
153 lines (123 loc) · 4.46 KB
/
Copy pathprojectCommands.ts
File metadata and controls
153 lines (123 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import type { Message } from 'ai';
import { generateId } from './fileUtils';
export interface ProjectCommands {
type: string;
setupCommand?: string;
startCommand?: string;
followupMessage: string;
}
interface FileContent {
content: string;
path: string;
}
export async function detectProjectCommands(files: FileContent[]): Promise<ProjectCommands> {
const hasFile = (name: string) => files.some((f) => f.path.endsWith(name));
if (hasFile('package.json')) {
const packageJsonFile = files.find((f) => f.path.endsWith('package.json'));
if (!packageJsonFile) {
return { type: '', setupCommand: '', followupMessage: '' };
}
try {
const packageJson = JSON.parse(packageJsonFile.content);
const scripts = packageJson?.scripts || {};
// Check for preferred commands in priority order
const preferredCommands = ['dev', 'start', 'preview'];
const availableCommand = preferredCommands.find((cmd) => scripts[cmd]);
if (availableCommand) {
return {
type: 'Node.js',
setupCommand: `npm install`,
startCommand: `npm run ${availableCommand}`,
followupMessage: `Found "${availableCommand}" script in package.json. Running "npm run ${availableCommand}" after installation.`,
};
}
return {
type: 'Node.js',
setupCommand: 'npm install',
followupMessage:
'Would you like me to inspect package.json to determine the available scripts for running this project?',
};
} catch (error) {
console.error('Error parsing package.json:', error);
return { type: '', setupCommand: '', followupMessage: '' };
}
}
if (hasFile('index.html')) {
return {
type: 'Static',
startCommand: 'npx --yes serve',
followupMessage: '',
};
}
return { type: '', setupCommand: '', followupMessage: '' };
}
export function createCommandsMessage(commands: ProjectCommands): Message | null {
if (!commands.setupCommand && !commands.startCommand) {
return null;
}
let commandString = '';
if (commands.setupCommand) {
commandString += `
<codinitAction type="shell">${commands.setupCommand}</codinitAction>`;
}
if (commands.startCommand) {
commandString += `
<codinitAction type="start">${commands.startCommand}</codinitAction>
`;
}
return {
role: 'assistant',
content: `
${commands.followupMessage ? `\n\n${commands.followupMessage}` : ''}
<codinitArtifact id="project-setup" title="Project Setup">
${commandString}
</codinitArtifact>`,
id: generateId(),
createdAt: new Date(),
};
}
export function escapeCodinitArtifactTags(input: string) {
// Regular expression to match codinitArtifact tags and their content
const regex = /(<codinitArtifact[^>]*>)([\s\S]*?)(<\/codinitArtifact>)/g;
return input.replace(regex, (match, openTag, content, closeTag) => {
// Escape the opening tag
const escapedOpenTag = openTag.replace(/</g, '<').replace(/>/g, '>');
// Escape the closing tag
const escapedCloseTag = closeTag.replace(/</g, '<').replace(/>/g, '>');
// Return the escaped version
return `${escapedOpenTag}${content}${escapedCloseTag}`;
});
}
export function escapeCodinitAActionTags(input: string) {
// Regular expression to match codinitArtifact tags and their content
const regex = /(<codinitAction[^>]*>)([\s\S]*?)(<\/codinitAction>)/g;
return input.replace(regex, (match, openTag, content, closeTag) => {
// Escape the opening tag
const escapedOpenTag = openTag.replace(/</g, '<').replace(/>/g, '>');
// Escape the closing tag
const escapedCloseTag = closeTag.replace(/</g, '<').replace(/>/g, '>');
// Return the escaped version
return `${escapedOpenTag}${content}${escapedCloseTag}`;
});
}
export function escapeCodinitTags(input: string) {
return escapeCodinitArtifactTags(escapeCodinitAActionTags(input));
}
// We have this seperate function to simplify the restore snapshot process in to one single artifact.
export function createCommandActionsString(commands: ProjectCommands): string {
if (!commands.setupCommand && !commands.startCommand) {
// Return empty string if no commands
return '';
}
let commandString = '';
if (commands.setupCommand) {
commandString += `
<codinitAction type="shell">${commands.setupCommand}</codinitAction>`;
}
if (commands.startCommand) {
commandString += `
<codinitAction type="start">${commands.startCommand}</codinitAction>
`;
}
return commandString;
}