@agiflowai/aicode-toolkit 0.6.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/LICENSE +661 -0
- package/README.md +151 -0
- package/dist/cli.cjs +732 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +727 -0
- package/dist/index.cjs +17 -0
- package/dist/index.d.cts +282 -0
- package/dist/index.d.ts +282 -0
- package/dist/index.js +4 -0
- package/dist/mcp-Bdxvi2Ej.cjs +4 -0
- package/dist/mcp-BmhiAfeF.js +47 -0
- package/dist/mcp-CZIiB-6Y.js +3 -0
- package/dist/mcp-Dwt8nYQV.cjs +65 -0
- package/dist/services-DNldrNnu.js +739 -0
- package/dist/services-s1vmufE4.cjs +859 -0
- package/package.json +85 -0
|
@@ -0,0 +1,859 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
let node_path = require("node:path");
|
|
25
|
+
node_path = __toESM(node_path);
|
|
26
|
+
let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
|
|
27
|
+
__agiflowai_aicode_utils = __toESM(__agiflowai_aicode_utils);
|
|
28
|
+
let fs_extra = require("fs-extra");
|
|
29
|
+
fs_extra = __toESM(fs_extra);
|
|
30
|
+
let chalk = require("chalk");
|
|
31
|
+
chalk = __toESM(chalk);
|
|
32
|
+
let gradient_string = require("gradient-string");
|
|
33
|
+
gradient_string = __toESM(gradient_string);
|
|
34
|
+
let execa = require("execa");
|
|
35
|
+
execa = __toESM(execa);
|
|
36
|
+
let __agiflowai_coding_agent_bridge = require("@agiflowai/coding-agent-bridge");
|
|
37
|
+
__agiflowai_coding_agent_bridge = __toESM(__agiflowai_coding_agent_bridge);
|
|
38
|
+
let node_os = require("node:os");
|
|
39
|
+
node_os = __toESM(node_os);
|
|
40
|
+
|
|
41
|
+
//#region src/constants/theme.ts
|
|
42
|
+
/**
|
|
43
|
+
* Theme color constants for AICode Toolkit
|
|
44
|
+
* Defines the brand color palette used throughout the CLI
|
|
45
|
+
*/
|
|
46
|
+
const THEME = { colors: {
|
|
47
|
+
primary: {
|
|
48
|
+
default: "#10b981",
|
|
49
|
+
dark: "#059669",
|
|
50
|
+
text: "#ffffff"
|
|
51
|
+
},
|
|
52
|
+
secondary: {
|
|
53
|
+
default: "#0d9488",
|
|
54
|
+
dark: "#0f766e",
|
|
55
|
+
light: "#14b8a6",
|
|
56
|
+
text: "#ffffff"
|
|
57
|
+
},
|
|
58
|
+
accent: {
|
|
59
|
+
default: "#c44569",
|
|
60
|
+
dark: "#c44569",
|
|
61
|
+
text: "#2a0b14"
|
|
62
|
+
},
|
|
63
|
+
semantic: {
|
|
64
|
+
info: "#5fb3d4",
|
|
65
|
+
success: "#5fb368",
|
|
66
|
+
error: "#d45959",
|
|
67
|
+
alert: "#d4b359"
|
|
68
|
+
},
|
|
69
|
+
cta: {
|
|
70
|
+
from: "#10b981",
|
|
71
|
+
to: "#0d9488",
|
|
72
|
+
text: "#ffffff"
|
|
73
|
+
},
|
|
74
|
+
transparent: "rgba(0, 0, 0, 0)",
|
|
75
|
+
white: "#c4cccf",
|
|
76
|
+
black: "#424549",
|
|
77
|
+
background: {
|
|
78
|
+
dark: {
|
|
79
|
+
default: "#0f0f0f",
|
|
80
|
+
shade: "#141414",
|
|
81
|
+
dark: "#0a0a0a",
|
|
82
|
+
light: "#1a1a1a"
|
|
83
|
+
},
|
|
84
|
+
light: {
|
|
85
|
+
default: "#fff",
|
|
86
|
+
shade: "#EAEAEA",
|
|
87
|
+
dark: "#17202a",
|
|
88
|
+
light: "#EAEAEA"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
} };
|
|
92
|
+
/**
|
|
93
|
+
* Gradient colors for banner (primary green -> secondary teal)
|
|
94
|
+
*/
|
|
95
|
+
const BANNER_GRADIENT = [
|
|
96
|
+
THEME.colors.primary.default,
|
|
97
|
+
THEME.colors.primary.dark,
|
|
98
|
+
THEME.colors.secondary.default,
|
|
99
|
+
THEME.colors.secondary.dark
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/utils/banner.ts
|
|
104
|
+
/**
|
|
105
|
+
* ASCII art for AICode Toolkit - simple and highly readable design
|
|
106
|
+
* Uses clean block style with clear spacing
|
|
107
|
+
*/
|
|
108
|
+
const ASCII_ART = `
|
|
109
|
+
█████╗ ██╗ ██████╗ ██████╗ ██████╗ ███████╗
|
|
110
|
+
██╔══██╗██║██╔════╝██╔═══██╗██╔══██╗██╔════╝
|
|
111
|
+
███████║██║██║ ██║ ██║██║ ██║█████╗
|
|
112
|
+
██╔══██║██║██║ ██║ ██║██║ ██║██╔══╝
|
|
113
|
+
██║ ██║██║╚██████╗╚██████╔╝██████╔╝███████╗
|
|
114
|
+
╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
|
|
115
|
+
|
|
116
|
+
████████╗ ██████╗ ██████╗ ██╗ ██╗ ██╗██╗████████╗
|
|
117
|
+
╚══██╔══╝██╔═══██╗██╔═══██╗██║ ██║ ██╔╝██║╚══██╔══╝
|
|
118
|
+
██║ ██║ ██║██║ ██║██║ █████╔╝ ██║ ██║
|
|
119
|
+
██║ ██║ ██║██║ ██║██║ ██╔═██╗ ██║ ██║
|
|
120
|
+
██║ ╚██████╔╝╚██████╔╝███████╗██║ ██╗██║ ██║
|
|
121
|
+
╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝
|
|
122
|
+
`;
|
|
123
|
+
/**
|
|
124
|
+
* Displays the AICode Toolkit banner with gradient effect
|
|
125
|
+
* Uses gradient-string with theme colors (primary green -> secondary teal)
|
|
126
|
+
*/
|
|
127
|
+
function displayBanner() {
|
|
128
|
+
const bannerGradient = (0, gradient_string.default)(BANNER_GRADIENT);
|
|
129
|
+
console.log(bannerGradient.multiline(ASCII_ART));
|
|
130
|
+
console.log(bannerGradient(" AI-Powered Code Toolkit for Modern Development"));
|
|
131
|
+
console.log(chalk.default.dim(" v0.6.0"));
|
|
132
|
+
console.log();
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Simplified banner for compact display
|
|
136
|
+
*/
|
|
137
|
+
function displayCompactBanner() {
|
|
138
|
+
const titleGradient = (0, gradient_string.default)(BANNER_GRADIENT);
|
|
139
|
+
console.log();
|
|
140
|
+
console.log(chalk.default.bold("▸ ") + titleGradient("AICode Toolkit") + chalk.default.dim(" v0.6.0"));
|
|
141
|
+
console.log(chalk.default.dim(" AI-Powered Code Toolkit"));
|
|
142
|
+
console.log();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/utils/git.ts
|
|
147
|
+
/**
|
|
148
|
+
* Execute a git command safely using execa to prevent command injection
|
|
149
|
+
*/
|
|
150
|
+
async function execGit(args, cwd) {
|
|
151
|
+
try {
|
|
152
|
+
await (0, execa.execa)("git", args, { cwd });
|
|
153
|
+
} catch (error) {
|
|
154
|
+
const execaError = error;
|
|
155
|
+
throw new Error(`Git command failed: ${execaError.stderr || execaError.message}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Execute git init safely using execa to prevent command injection
|
|
160
|
+
*/
|
|
161
|
+
async function gitInit(projectPath) {
|
|
162
|
+
try {
|
|
163
|
+
await (0, execa.execa)("git", ["init", projectPath]);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
const execaError = error;
|
|
166
|
+
throw new Error(`Git init failed: ${execaError.stderr || execaError.message}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Find the workspace root by searching upwards for .git folder
|
|
171
|
+
* Returns null if no .git folder is found (indicating a new project setup is needed)
|
|
172
|
+
*/
|
|
173
|
+
async function findWorkspaceRoot(startPath = process.cwd()) {
|
|
174
|
+
let currentPath = node_path.default.resolve(startPath);
|
|
175
|
+
const rootPath = node_path.default.parse(currentPath).root;
|
|
176
|
+
while (true) {
|
|
177
|
+
const gitPath = node_path.default.join(currentPath, ".git");
|
|
178
|
+
if (await fs_extra.pathExists(gitPath)) return currentPath;
|
|
179
|
+
if (currentPath === rootPath) return null;
|
|
180
|
+
currentPath = node_path.default.dirname(currentPath);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Parse GitHub URL to detect if it's a subdirectory
|
|
185
|
+
* Supports formats:
|
|
186
|
+
* - https://github.com/user/repo
|
|
187
|
+
* - https://github.com/user/repo/tree/branch/path/to/dir
|
|
188
|
+
* - https://github.com/user/repo/tree/main/path/to/dir
|
|
189
|
+
*/
|
|
190
|
+
function parseGitHubUrl(url) {
|
|
191
|
+
const treeMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)$/);
|
|
192
|
+
const blobMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)\/(.+)$/);
|
|
193
|
+
const rootMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/);
|
|
194
|
+
if (treeMatch || blobMatch) {
|
|
195
|
+
const match = treeMatch || blobMatch;
|
|
196
|
+
return {
|
|
197
|
+
owner: match[1],
|
|
198
|
+
repo: match[2],
|
|
199
|
+
repoUrl: `https://github.com/${match[1]}/${match[2]}.git`,
|
|
200
|
+
branch: match[3],
|
|
201
|
+
subdirectory: match[4],
|
|
202
|
+
isSubdirectory: true
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
if (rootMatch) return {
|
|
206
|
+
owner: rootMatch[1],
|
|
207
|
+
repo: rootMatch[2],
|
|
208
|
+
repoUrl: `https://github.com/${rootMatch[1]}/${rootMatch[2]}.git`,
|
|
209
|
+
isSubdirectory: false
|
|
210
|
+
};
|
|
211
|
+
return {
|
|
212
|
+
repoUrl: url,
|
|
213
|
+
isSubdirectory: false
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Clone a subdirectory from a git repository using sparse checkout
|
|
218
|
+
*/
|
|
219
|
+
async function cloneSubdirectory(repoUrl, branch, subdirectory, targetFolder) {
|
|
220
|
+
const tempFolder = `${targetFolder}.tmp`;
|
|
221
|
+
try {
|
|
222
|
+
await execGit(["init", tempFolder]);
|
|
223
|
+
await execGit([
|
|
224
|
+
"remote",
|
|
225
|
+
"add",
|
|
226
|
+
"origin",
|
|
227
|
+
repoUrl
|
|
228
|
+
], tempFolder);
|
|
229
|
+
await execGit([
|
|
230
|
+
"config",
|
|
231
|
+
"core.sparseCheckout",
|
|
232
|
+
"true"
|
|
233
|
+
], tempFolder);
|
|
234
|
+
const sparseCheckoutFile = node_path.default.join(tempFolder, ".git", "info", "sparse-checkout");
|
|
235
|
+
await fs_extra.writeFile(sparseCheckoutFile, `${subdirectory}\n`);
|
|
236
|
+
await execGit([
|
|
237
|
+
"pull",
|
|
238
|
+
"--depth=1",
|
|
239
|
+
"origin",
|
|
240
|
+
branch
|
|
241
|
+
], tempFolder);
|
|
242
|
+
const sourceDir = node_path.default.join(tempFolder, subdirectory);
|
|
243
|
+
if (!await fs_extra.pathExists(sourceDir)) throw new Error(`Subdirectory '${subdirectory}' not found in repository at branch '${branch}'`);
|
|
244
|
+
if (await fs_extra.pathExists(targetFolder)) throw new Error(`Target folder already exists: ${targetFolder}`);
|
|
245
|
+
await fs_extra.move(sourceDir, targetFolder);
|
|
246
|
+
await fs_extra.remove(tempFolder);
|
|
247
|
+
} catch (error) {
|
|
248
|
+
if (await fs_extra.pathExists(tempFolder)) await fs_extra.remove(tempFolder);
|
|
249
|
+
throw error;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Clone entire repository
|
|
254
|
+
*/
|
|
255
|
+
async function cloneRepository(repoUrl, targetFolder) {
|
|
256
|
+
await execGit([
|
|
257
|
+
"clone",
|
|
258
|
+
repoUrl,
|
|
259
|
+
targetFolder
|
|
260
|
+
]);
|
|
261
|
+
const gitFolder = node_path.default.join(targetFolder, ".git");
|
|
262
|
+
if (await fs_extra.pathExists(gitFolder)) await fs_extra.remove(gitFolder);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Fetch directory listing from GitHub API
|
|
266
|
+
*/
|
|
267
|
+
async function fetchGitHubDirectoryContents(owner, repo, path$3, branch = "main") {
|
|
268
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path$3}?ref=${branch}`;
|
|
269
|
+
const response = await fetch(url, { headers: {
|
|
270
|
+
Accept: "application/vnd.github.v3+json",
|
|
271
|
+
"User-Agent": "scaffold-mcp"
|
|
272
|
+
} });
|
|
273
|
+
if (!response.ok) throw new Error(`Failed to fetch directory contents: ${response.statusText}`);
|
|
274
|
+
const data = await response.json();
|
|
275
|
+
if (!Array.isArray(data)) throw new Error("Expected directory but got file");
|
|
276
|
+
return data.map((item) => ({
|
|
277
|
+
name: item.name,
|
|
278
|
+
type: item.type,
|
|
279
|
+
path: item.path
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region src/services/CodingAgentService.ts
|
|
285
|
+
var CodingAgentService = class {
|
|
286
|
+
workspaceRoot;
|
|
287
|
+
constructor(workspaceRoot) {
|
|
288
|
+
this.workspaceRoot = workspaceRoot;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Detect which coding agent is enabled in the workspace
|
|
292
|
+
* Checks for Claude Code, Codex, and Gemini CLI installations
|
|
293
|
+
* @param workspaceRoot - The workspace root directory
|
|
294
|
+
* @returns Promise resolving to detected agent ID or null
|
|
295
|
+
*/
|
|
296
|
+
static async detectCodingAgent(workspaceRoot) {
|
|
297
|
+
if (await new __agiflowai_coding_agent_bridge.ClaudeCodeService({ workspaceRoot }).isEnabled()) return __agiflowai_coding_agent_bridge.CLAUDE_CODE;
|
|
298
|
+
if (await new __agiflowai_coding_agent_bridge.CodexService({ workspaceRoot }).isEnabled()) return __agiflowai_coding_agent_bridge.CODEX;
|
|
299
|
+
if (await new __agiflowai_coding_agent_bridge.GeminiCliService({ workspaceRoot }).isEnabled()) return __agiflowai_coding_agent_bridge.GEMINI_CLI;
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Get available coding agents with their descriptions
|
|
304
|
+
*/
|
|
305
|
+
static getAvailableAgents() {
|
|
306
|
+
return [
|
|
307
|
+
{
|
|
308
|
+
value: __agiflowai_coding_agent_bridge.CLAUDE_CODE,
|
|
309
|
+
name: "Claude Code",
|
|
310
|
+
description: "Anthropic Claude Code CLI agent"
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
value: __agiflowai_coding_agent_bridge.CODEX,
|
|
314
|
+
name: "Codex",
|
|
315
|
+
description: "OpenAI Codex CLI agent"
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
value: __agiflowai_coding_agent_bridge.GEMINI_CLI,
|
|
319
|
+
name: "Gemini CLI",
|
|
320
|
+
description: "Google Gemini CLI agent"
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
value: __agiflowai_coding_agent_bridge.NONE,
|
|
324
|
+
name: "Other",
|
|
325
|
+
description: "Other coding agent or skip MCP configuration"
|
|
326
|
+
}
|
|
327
|
+
];
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Setup MCP configuration for the selected coding agent
|
|
331
|
+
* @param agent - The coding agent to configure
|
|
332
|
+
*/
|
|
333
|
+
async setupMCP(agent) {
|
|
334
|
+
if (agent === __agiflowai_coding_agent_bridge.NONE) {
|
|
335
|
+
__agiflowai_aicode_utils.print.info("Skipping MCP configuration");
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
__agiflowai_aicode_utils.print.info(`\nSetting up MCP for ${agent}...`);
|
|
339
|
+
let service = null;
|
|
340
|
+
let configLocation = "";
|
|
341
|
+
let restartInstructions = "";
|
|
342
|
+
if (agent === __agiflowai_coding_agent_bridge.CLAUDE_CODE) {
|
|
343
|
+
service = new __agiflowai_coding_agent_bridge.ClaudeCodeService({ workspaceRoot: this.workspaceRoot });
|
|
344
|
+
configLocation = ".mcp.json";
|
|
345
|
+
restartInstructions = "Restart Claude Code to load the new MCP servers";
|
|
346
|
+
} else if (agent === __agiflowai_coding_agent_bridge.CODEX) {
|
|
347
|
+
service = new __agiflowai_coding_agent_bridge.CodexService({ workspaceRoot: this.workspaceRoot });
|
|
348
|
+
configLocation = "~/.codex/config.toml";
|
|
349
|
+
restartInstructions = "Restart Codex CLI to load the new MCP servers";
|
|
350
|
+
} else if (agent === __agiflowai_coding_agent_bridge.GEMINI_CLI) {
|
|
351
|
+
service = new __agiflowai_coding_agent_bridge.GeminiCliService({ workspaceRoot: this.workspaceRoot });
|
|
352
|
+
configLocation = "~/.gemini/settings.json";
|
|
353
|
+
restartInstructions = "Restart Gemini CLI to load the new MCP servers";
|
|
354
|
+
}
|
|
355
|
+
if (!service) {
|
|
356
|
+
__agiflowai_aicode_utils.print.info(`MCP configuration for ${agent} is not yet supported.`);
|
|
357
|
+
__agiflowai_aicode_utils.print.info("Please configure MCP servers manually for this coding agent.");
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
await service.updateMcpSettings({ servers: {
|
|
361
|
+
"scaffold-mcp": {
|
|
362
|
+
type: "stdio",
|
|
363
|
+
command: "npx",
|
|
364
|
+
args: [
|
|
365
|
+
"-y",
|
|
366
|
+
"@agiflowai/scaffold-mcp",
|
|
367
|
+
"mcp-serve"
|
|
368
|
+
],
|
|
369
|
+
disabled: false
|
|
370
|
+
},
|
|
371
|
+
"architect-mcp": {
|
|
372
|
+
type: "stdio",
|
|
373
|
+
command: "npx",
|
|
374
|
+
args: [
|
|
375
|
+
"-y",
|
|
376
|
+
"@agiflowai/architect-mcp",
|
|
377
|
+
"mcp-serve"
|
|
378
|
+
],
|
|
379
|
+
disabled: false
|
|
380
|
+
}
|
|
381
|
+
} });
|
|
382
|
+
__agiflowai_aicode_utils.print.success(`Added scaffold-mcp and architect-mcp to ${configLocation}`);
|
|
383
|
+
__agiflowai_aicode_utils.print.info("\nNext steps:");
|
|
384
|
+
__agiflowai_aicode_utils.print.indent(`1. ${restartInstructions}`);
|
|
385
|
+
__agiflowai_aicode_utils.print.indent("2. The scaffold-mcp and architect-mcp servers will be available");
|
|
386
|
+
__agiflowai_aicode_utils.print.success("\nMCP configuration completed!");
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
//#endregion
|
|
391
|
+
//#region src/services/NewProjectService.ts
|
|
392
|
+
const RESERVED_PROJECT_NAMES = [
|
|
393
|
+
".",
|
|
394
|
+
"..",
|
|
395
|
+
"CON",
|
|
396
|
+
"PRN",
|
|
397
|
+
"AUX",
|
|
398
|
+
"NUL",
|
|
399
|
+
"COM1",
|
|
400
|
+
"COM2",
|
|
401
|
+
"COM3",
|
|
402
|
+
"COM4",
|
|
403
|
+
"COM5",
|
|
404
|
+
"COM6",
|
|
405
|
+
"COM7",
|
|
406
|
+
"COM8",
|
|
407
|
+
"COM9",
|
|
408
|
+
"LPT1",
|
|
409
|
+
"LPT2",
|
|
410
|
+
"LPT3",
|
|
411
|
+
"LPT4",
|
|
412
|
+
"LPT5",
|
|
413
|
+
"LPT6",
|
|
414
|
+
"LPT7",
|
|
415
|
+
"LPT8",
|
|
416
|
+
"LPT9"
|
|
417
|
+
];
|
|
418
|
+
var NewProjectService = class {
|
|
419
|
+
providedName;
|
|
420
|
+
providedProjectType;
|
|
421
|
+
constructor(providedName, providedProjectType) {
|
|
422
|
+
this.providedName = providedName;
|
|
423
|
+
this.providedProjectType = providedProjectType;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Validate project name against naming rules
|
|
427
|
+
* @param value - Project name to validate
|
|
428
|
+
* @returns true if valid, error message string if invalid
|
|
429
|
+
*/
|
|
430
|
+
validateProjectName(value) {
|
|
431
|
+
const trimmed = value.trim();
|
|
432
|
+
if (!trimmed) return "Project name is required";
|
|
433
|
+
if (!/^[a-zA-Z0-9]/.test(trimmed)) return "Project name must start with a letter or number";
|
|
434
|
+
if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(trimmed)) return "Project name can only contain letters, numbers, hyphens, and underscores";
|
|
435
|
+
if (RESERVED_PROJECT_NAMES.includes(trimmed.toUpperCase())) return "Project name uses a reserved name";
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Validate project type
|
|
440
|
+
* @param projectType - Project type to validate
|
|
441
|
+
* @throws Error if invalid project type
|
|
442
|
+
*/
|
|
443
|
+
validateProjectType(projectType) {
|
|
444
|
+
if (projectType !== __agiflowai_aicode_utils.ProjectType.MONOLITH && projectType !== __agiflowai_aicode_utils.ProjectType.MONOREPO) throw new Error(`Invalid project type '${projectType}'. Must be '${__agiflowai_aicode_utils.ProjectType.MONOLITH}' or '${__agiflowai_aicode_utils.ProjectType.MONOREPO}'`);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Get the provided name from constructor
|
|
448
|
+
*/
|
|
449
|
+
getProvidedName() {
|
|
450
|
+
return this.providedName;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Get the provided project type from constructor
|
|
454
|
+
*/
|
|
455
|
+
getProvidedProjectType() {
|
|
456
|
+
return this.providedProjectType;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Create project directory atomically
|
|
460
|
+
* @param projectPath - Full path where project should be created
|
|
461
|
+
* @param projectName - Name of the project (for error messages)
|
|
462
|
+
*/
|
|
463
|
+
async createProjectDirectory(projectPath, projectName) {
|
|
464
|
+
try {
|
|
465
|
+
await fs_extra.mkdir(projectPath, { recursive: false });
|
|
466
|
+
__agiflowai_aicode_utils.print.success(`Created project directory: ${projectPath}`);
|
|
467
|
+
} catch (error) {
|
|
468
|
+
if (error.code === "EEXIST") throw new Error(`Directory '${projectName}' already exists. Please choose a different name.`);
|
|
469
|
+
throw error;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Clone an existing Git repository
|
|
474
|
+
* @param repoUrl - Repository URL to clone
|
|
475
|
+
* @param projectPath - Destination path for the cloned repository
|
|
476
|
+
*/
|
|
477
|
+
async cloneExistingRepository(repoUrl, projectPath) {
|
|
478
|
+
__agiflowai_aicode_utils.print.info("Cloning repository...");
|
|
479
|
+
try {
|
|
480
|
+
const parsed = parseGitHubUrl(repoUrl.trim());
|
|
481
|
+
if (parsed.isSubdirectory && parsed.branch && parsed.subdirectory) await cloneSubdirectory(parsed.repoUrl, parsed.branch, parsed.subdirectory, projectPath);
|
|
482
|
+
else await cloneRepository(parsed.repoUrl, projectPath);
|
|
483
|
+
__agiflowai_aicode_utils.print.success("Repository cloned successfully");
|
|
484
|
+
} catch (error) {
|
|
485
|
+
await fs_extra.remove(projectPath);
|
|
486
|
+
throw new Error(`Failed to clone repository: ${error.message}`);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Initialize a new Git repository
|
|
491
|
+
* @param projectPath - Path where git repository should be initialized
|
|
492
|
+
*/
|
|
493
|
+
async initializeGitRepository(projectPath) {
|
|
494
|
+
__agiflowai_aicode_utils.print.info("Initializing Git repository...");
|
|
495
|
+
try {
|
|
496
|
+
await gitInit(projectPath);
|
|
497
|
+
__agiflowai_aicode_utils.print.success("Git repository initialized");
|
|
498
|
+
} catch (error) {
|
|
499
|
+
__agiflowai_aicode_utils.messages.warning(`Failed to initialize Git: ${error.message}`);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Validate repository URL format
|
|
504
|
+
* @param value - Repository URL to validate
|
|
505
|
+
* @returns true if valid, error message string if invalid
|
|
506
|
+
*/
|
|
507
|
+
validateRepositoryUrl(value) {
|
|
508
|
+
if (!value.trim()) return "Repository URL is required";
|
|
509
|
+
if (!value.match(/^(https?:\/\/|git@)/)) return "Please enter a valid Git repository URL";
|
|
510
|
+
return true;
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
//#endregion
|
|
515
|
+
//#region src/services/TemplateSelectionService.ts
|
|
516
|
+
var TemplateSelectionService = class {
|
|
517
|
+
tmpDir;
|
|
518
|
+
constructor(existingTmpDir) {
|
|
519
|
+
this.tmpDir = existingTmpDir || node_path.default.join(node_os.default.tmpdir(), `aicode-templates-${Date.now()}`);
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Download templates to OS tmp directory
|
|
523
|
+
* @param repoConfig - Repository configuration
|
|
524
|
+
* @returns Path to the tmp directory containing templates
|
|
525
|
+
*/
|
|
526
|
+
async downloadTemplatesToTmp(repoConfig) {
|
|
527
|
+
__agiflowai_aicode_utils.print.info(`Downloading templates from ${repoConfig.owner}/${repoConfig.repo}...`);
|
|
528
|
+
try {
|
|
529
|
+
await fs_extra.ensureDir(this.tmpDir);
|
|
530
|
+
const contents = await fetchGitHubDirectoryContents(repoConfig.owner, repoConfig.repo, repoConfig.path, repoConfig.branch);
|
|
531
|
+
const templateDirs = contents.filter((item) => item.type === "dir");
|
|
532
|
+
const globalFiles = contents.filter((item) => item.type === "file" && item.name === "RULES.yaml");
|
|
533
|
+
if (templateDirs.length === 0) throw new Error("No templates found in repository");
|
|
534
|
+
__agiflowai_aicode_utils.print.info(`Found ${templateDirs.length} template(s), downloading...`);
|
|
535
|
+
for (const template of templateDirs) {
|
|
536
|
+
const targetFolder = node_path.default.join(this.tmpDir, template.name);
|
|
537
|
+
__agiflowai_aicode_utils.print.info(`Downloading ${template.name}...`);
|
|
538
|
+
await cloneSubdirectory(`https://github.com/${repoConfig.owner}/${repoConfig.repo}.git`, repoConfig.branch, template.path, targetFolder);
|
|
539
|
+
__agiflowai_aicode_utils.print.success(`Downloaded ${template.name}`);
|
|
540
|
+
}
|
|
541
|
+
if (globalFiles.length > 0) {
|
|
542
|
+
__agiflowai_aicode_utils.print.info("Downloading global RULES.yaml...");
|
|
543
|
+
const rulesUrl = `https://raw.githubusercontent.com/${repoConfig.owner}/${repoConfig.repo}/${repoConfig.branch}/${repoConfig.path}/RULES.yaml`;
|
|
544
|
+
const targetFile = node_path.default.join(this.tmpDir, "RULES.yaml");
|
|
545
|
+
const response = await fetch(rulesUrl);
|
|
546
|
+
if (response.ok) {
|
|
547
|
+
const content = await response.text();
|
|
548
|
+
await fs_extra.writeFile(targetFile, content, "utf-8");
|
|
549
|
+
__agiflowai_aicode_utils.print.success("Downloaded global RULES.yaml");
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
__agiflowai_aicode_utils.print.success(`\nAll templates downloaded to ${this.tmpDir}`);
|
|
553
|
+
return this.tmpDir;
|
|
554
|
+
} catch (error) {
|
|
555
|
+
await this.cleanup();
|
|
556
|
+
throw new Error(`Failed to download templates: ${error.message}`);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* List available templates in the tmp directory
|
|
561
|
+
* @returns Array of template information
|
|
562
|
+
*/
|
|
563
|
+
async listTemplates() {
|
|
564
|
+
try {
|
|
565
|
+
const entries = await fs_extra.readdir(this.tmpDir, { withFileTypes: true });
|
|
566
|
+
const templates = [];
|
|
567
|
+
for (const entry of entries) if (entry.isDirectory()) {
|
|
568
|
+
const templatePath = node_path.default.join(this.tmpDir, entry.name);
|
|
569
|
+
const description = await this.readTemplateDescription(templatePath);
|
|
570
|
+
templates.push({
|
|
571
|
+
name: entry.name,
|
|
572
|
+
path: templatePath,
|
|
573
|
+
description
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
return templates;
|
|
577
|
+
} catch (error) {
|
|
578
|
+
throw new Error(`Failed to list templates: ${error.message}`);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Copy selected templates to destination
|
|
583
|
+
* @param templateNames - Names of templates to copy
|
|
584
|
+
* @param destinationPath - Destination templates folder path
|
|
585
|
+
* @param projectType - Project type (monolith allows only single template)
|
|
586
|
+
* @param selectedMcpServers - Optional array of selected MCP servers to filter files
|
|
587
|
+
*/
|
|
588
|
+
async copyTemplates(templateNames, destinationPath, projectType, selectedMcpServers) {
|
|
589
|
+
try {
|
|
590
|
+
if (projectType === __agiflowai_aicode_utils.ProjectType.MONOLITH && templateNames.length > 1) throw new Error("Monolith projects can only use a single template");
|
|
591
|
+
await fs_extra.ensureDir(destinationPath);
|
|
592
|
+
__agiflowai_aicode_utils.print.info(`\nCopying templates to ${destinationPath}...`);
|
|
593
|
+
for (const templateName of templateNames) {
|
|
594
|
+
const sourcePath = node_path.default.join(this.tmpDir, templateName);
|
|
595
|
+
const targetPath = node_path.default.join(destinationPath, templateName);
|
|
596
|
+
if (!await fs_extra.pathExists(sourcePath)) throw new Error(`Template '${templateName}' not found in downloaded templates`);
|
|
597
|
+
if (await fs_extra.pathExists(targetPath)) {
|
|
598
|
+
__agiflowai_aicode_utils.print.info(`Skipping ${templateName} (already exists)`);
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
__agiflowai_aicode_utils.print.info(`Copying ${templateName}...`);
|
|
602
|
+
if (selectedMcpServers && selectedMcpServers.length > 0) await this.copyTemplateWithMcpFilter(sourcePath, targetPath, selectedMcpServers);
|
|
603
|
+
else await fs_extra.copy(sourcePath, targetPath);
|
|
604
|
+
__agiflowai_aicode_utils.print.success(`Copied ${templateName}`);
|
|
605
|
+
}
|
|
606
|
+
const globalRulesSource = node_path.default.join(this.tmpDir, "RULES.yaml");
|
|
607
|
+
const globalRulesTarget = node_path.default.join(destinationPath, "RULES.yaml");
|
|
608
|
+
if (await fs_extra.pathExists(globalRulesSource)) {
|
|
609
|
+
if (!await fs_extra.pathExists(globalRulesTarget)) {
|
|
610
|
+
__agiflowai_aicode_utils.print.info("Copying global RULES.yaml...");
|
|
611
|
+
await fs_extra.copy(globalRulesSource, globalRulesTarget);
|
|
612
|
+
__agiflowai_aicode_utils.print.success("Copied global RULES.yaml");
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
__agiflowai_aicode_utils.print.success("\nTemplates copied successfully!");
|
|
616
|
+
} catch (error) {
|
|
617
|
+
throw new Error(`Failed to copy templates: ${error.message}`);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Copy template files with MCP server filtering
|
|
622
|
+
* @param sourcePath - Source template path
|
|
623
|
+
* @param targetPath - Target template path
|
|
624
|
+
* @param selectedMcpServers - Selected MCP servers
|
|
625
|
+
*/
|
|
626
|
+
async copyTemplateWithMcpFilter(sourcePath, targetPath, selectedMcpServers) {
|
|
627
|
+
const { MCPServer: MCPServer$1, MCP_CONFIG_FILES: MCP_CONFIG_FILES$1 } = await Promise.resolve().then(() => require("./mcp-Bdxvi2Ej.cjs"));
|
|
628
|
+
const architectFiles = MCP_CONFIG_FILES$1[MCPServer$1.ARCHITECT];
|
|
629
|
+
const hasArchitect = selectedMcpServers.includes(MCPServer$1.ARCHITECT);
|
|
630
|
+
const hasScaffold = selectedMcpServers.includes(MCPServer$1.SCAFFOLD);
|
|
631
|
+
await fs_extra.ensureDir(targetPath);
|
|
632
|
+
const entries = await fs_extra.readdir(sourcePath, { withFileTypes: true });
|
|
633
|
+
for (const entry of entries) {
|
|
634
|
+
const entrySourcePath = node_path.default.join(sourcePath, entry.name);
|
|
635
|
+
const entryTargetPath = node_path.default.join(targetPath, entry.name);
|
|
636
|
+
const isArchitectFile = architectFiles.includes(entry.name);
|
|
637
|
+
if (hasArchitect && hasScaffold) if (entry.isDirectory()) await fs_extra.copy(entrySourcePath, entryTargetPath);
|
|
638
|
+
else await fs_extra.copy(entrySourcePath, entryTargetPath);
|
|
639
|
+
else if (hasArchitect && !hasScaffold) {
|
|
640
|
+
if (isArchitectFile) await fs_extra.copy(entrySourcePath, entryTargetPath);
|
|
641
|
+
} else if (!hasArchitect && hasScaffold) {
|
|
642
|
+
if (!isArchitectFile) if (entry.isDirectory()) await fs_extra.copy(entrySourcePath, entryTargetPath);
|
|
643
|
+
else await fs_extra.copy(entrySourcePath, entryTargetPath);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Read template description from README or scaffold.yaml
|
|
649
|
+
* @param templatePath - Path to the template directory
|
|
650
|
+
* @returns Description string or undefined
|
|
651
|
+
*/
|
|
652
|
+
async readTemplateDescription(templatePath) {
|
|
653
|
+
try {
|
|
654
|
+
const scaffoldYamlPath = node_path.default.join(templatePath, "scaffold.yaml");
|
|
655
|
+
if (await fs_extra.pathExists(scaffoldYamlPath)) {
|
|
656
|
+
const yaml = await import("js-yaml");
|
|
657
|
+
const content = await fs_extra.readFile(scaffoldYamlPath, "utf-8");
|
|
658
|
+
const scaffoldConfig = yaml.load(content);
|
|
659
|
+
if (scaffoldConfig?.description) return scaffoldConfig.description;
|
|
660
|
+
if (scaffoldConfig?.boilerplate?.[0]?.description) return scaffoldConfig.boilerplate[0].description;
|
|
661
|
+
}
|
|
662
|
+
const readmePath = node_path.default.join(templatePath, "README.md");
|
|
663
|
+
if (await fs_extra.pathExists(readmePath)) return (await fs_extra.readFile(readmePath, "utf-8")).split("\n\n")[0].substring(0, 200).trim();
|
|
664
|
+
return;
|
|
665
|
+
} catch {
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Get the tmp directory path
|
|
671
|
+
*/
|
|
672
|
+
getTmpDir() {
|
|
673
|
+
return this.tmpDir;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Clean up tmp directory
|
|
677
|
+
*/
|
|
678
|
+
async cleanup() {
|
|
679
|
+
try {
|
|
680
|
+
if (await fs_extra.pathExists(this.tmpDir)) {
|
|
681
|
+
await fs_extra.remove(this.tmpDir);
|
|
682
|
+
__agiflowai_aicode_utils.print.info("Cleaned up temporary files");
|
|
683
|
+
}
|
|
684
|
+
} catch (error) {
|
|
685
|
+
__agiflowai_aicode_utils.print.warning(`Warning: Failed to clean up tmp directory: ${error.message}`);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
|
|
690
|
+
//#endregion
|
|
691
|
+
//#region src/services/TemplatesService.ts
|
|
692
|
+
var TemplatesService = class {
|
|
693
|
+
/**
|
|
694
|
+
* Download templates from a GitHub repository with UI feedback
|
|
695
|
+
* @param templatesPath - Local path where templates should be downloaded
|
|
696
|
+
* @param repoConfig - Repository configuration (owner, repo, branch, path)
|
|
697
|
+
*/
|
|
698
|
+
async downloadTemplates(templatesPath, repoConfig) {
|
|
699
|
+
__agiflowai_aicode_utils.print.info(`Fetching templates from ${repoConfig.owner}/${repoConfig.repo}...`);
|
|
700
|
+
try {
|
|
701
|
+
const templateDirs = (await fetchGitHubDirectoryContents(repoConfig.owner, repoConfig.repo, repoConfig.path, repoConfig.branch)).filter((item) => item.type === "dir");
|
|
702
|
+
if (templateDirs.length === 0) {
|
|
703
|
+
__agiflowai_aicode_utils.messages.warning("No templates found in repository");
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
__agiflowai_aicode_utils.print.info(`Found ${templateDirs.length} template(s)`);
|
|
707
|
+
let downloaded = 0;
|
|
708
|
+
let skipped = 0;
|
|
709
|
+
for (const template of templateDirs) {
|
|
710
|
+
const targetFolder = node_path.default.join(templatesPath, template.name);
|
|
711
|
+
if (await fs_extra.pathExists(targetFolder)) {
|
|
712
|
+
__agiflowai_aicode_utils.print.info(`Skipping ${template.name} (already exists)`);
|
|
713
|
+
skipped++;
|
|
714
|
+
continue;
|
|
715
|
+
}
|
|
716
|
+
__agiflowai_aicode_utils.print.info(`Downloading ${template.name}...`);
|
|
717
|
+
await cloneSubdirectory(`https://github.com/${repoConfig.owner}/${repoConfig.repo}.git`, repoConfig.branch, template.path, targetFolder);
|
|
718
|
+
__agiflowai_aicode_utils.print.success(`Downloaded ${template.name}`);
|
|
719
|
+
downloaded++;
|
|
720
|
+
}
|
|
721
|
+
__agiflowai_aicode_utils.print.success("\nAll templates downloaded successfully!");
|
|
722
|
+
} catch (error) {
|
|
723
|
+
throw new Error(`Failed to download templates: ${error.message}`);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Initialize templates folder with README
|
|
728
|
+
* @param templatesPath - Path where templates folder should be created
|
|
729
|
+
*/
|
|
730
|
+
async initializeTemplatesFolder(templatesPath) {
|
|
731
|
+
await fs_extra.ensureDir(templatesPath);
|
|
732
|
+
await fs_extra.writeFile(node_path.default.join(templatesPath, "README.md"), `# Templates
|
|
733
|
+
|
|
734
|
+
This folder contains boilerplate templates and scaffolding methods for your projects.
|
|
735
|
+
|
|
736
|
+
## Templates
|
|
737
|
+
|
|
738
|
+
Templates are organized by framework/technology and include configuration files (\`scaffold.yaml\`) that define:
|
|
739
|
+
- Boilerplates: Full project starter templates
|
|
740
|
+
- Features: Code scaffolding methods for adding new features to existing projects
|
|
741
|
+
|
|
742
|
+
## Adding More Templates
|
|
743
|
+
|
|
744
|
+
Use the \`add\` command to add templates from remote repositories:
|
|
745
|
+
|
|
746
|
+
\`\`\`bash
|
|
747
|
+
scaffold-mcp add --name my-template --url https://github.com/user/template
|
|
748
|
+
\`\`\`
|
|
749
|
+
|
|
750
|
+
Or add templates from subdirectories:
|
|
751
|
+
|
|
752
|
+
\`\`\`bash
|
|
753
|
+
scaffold-mcp add --name nextjs-template --url https://github.com/user/repo/tree/main/templates/nextjs
|
|
754
|
+
\`\`\`
|
|
755
|
+
|
|
756
|
+
## Creating Custom Templates
|
|
757
|
+
|
|
758
|
+
Each template should have a \`scaffold.yaml\` configuration file defining:
|
|
759
|
+
- \`boilerplate\`: Array of boilerplate configurations
|
|
760
|
+
- \`features\`: Array of feature scaffold configurations
|
|
761
|
+
|
|
762
|
+
Template files use Liquid syntax for variable placeholders: \`{{ variableName }}\`
|
|
763
|
+
|
|
764
|
+
See existing templates for examples and documentation for more details.
|
|
765
|
+
`);
|
|
766
|
+
}
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
//#endregion
|
|
770
|
+
Object.defineProperty(exports, 'BANNER_GRADIENT', {
|
|
771
|
+
enumerable: true,
|
|
772
|
+
get: function () {
|
|
773
|
+
return BANNER_GRADIENT;
|
|
774
|
+
}
|
|
775
|
+
});
|
|
776
|
+
Object.defineProperty(exports, 'CodingAgentService', {
|
|
777
|
+
enumerable: true,
|
|
778
|
+
get: function () {
|
|
779
|
+
return CodingAgentService;
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
Object.defineProperty(exports, 'NewProjectService', {
|
|
783
|
+
enumerable: true,
|
|
784
|
+
get: function () {
|
|
785
|
+
return NewProjectService;
|
|
786
|
+
}
|
|
787
|
+
});
|
|
788
|
+
Object.defineProperty(exports, 'THEME', {
|
|
789
|
+
enumerable: true,
|
|
790
|
+
get: function () {
|
|
791
|
+
return THEME;
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
Object.defineProperty(exports, 'TemplateSelectionService', {
|
|
795
|
+
enumerable: true,
|
|
796
|
+
get: function () {
|
|
797
|
+
return TemplateSelectionService;
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
Object.defineProperty(exports, 'TemplatesService', {
|
|
801
|
+
enumerable: true,
|
|
802
|
+
get: function () {
|
|
803
|
+
return TemplatesService;
|
|
804
|
+
}
|
|
805
|
+
});
|
|
806
|
+
Object.defineProperty(exports, '__toESM', {
|
|
807
|
+
enumerable: true,
|
|
808
|
+
get: function () {
|
|
809
|
+
return __toESM;
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
Object.defineProperty(exports, 'cloneRepository', {
|
|
813
|
+
enumerable: true,
|
|
814
|
+
get: function () {
|
|
815
|
+
return cloneRepository;
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
Object.defineProperty(exports, 'cloneSubdirectory', {
|
|
819
|
+
enumerable: true,
|
|
820
|
+
get: function () {
|
|
821
|
+
return cloneSubdirectory;
|
|
822
|
+
}
|
|
823
|
+
});
|
|
824
|
+
Object.defineProperty(exports, 'displayBanner', {
|
|
825
|
+
enumerable: true,
|
|
826
|
+
get: function () {
|
|
827
|
+
return displayBanner;
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
Object.defineProperty(exports, 'displayCompactBanner', {
|
|
831
|
+
enumerable: true,
|
|
832
|
+
get: function () {
|
|
833
|
+
return displayCompactBanner;
|
|
834
|
+
}
|
|
835
|
+
});
|
|
836
|
+
Object.defineProperty(exports, 'fetchGitHubDirectoryContents', {
|
|
837
|
+
enumerable: true,
|
|
838
|
+
get: function () {
|
|
839
|
+
return fetchGitHubDirectoryContents;
|
|
840
|
+
}
|
|
841
|
+
});
|
|
842
|
+
Object.defineProperty(exports, 'findWorkspaceRoot', {
|
|
843
|
+
enumerable: true,
|
|
844
|
+
get: function () {
|
|
845
|
+
return findWorkspaceRoot;
|
|
846
|
+
}
|
|
847
|
+
});
|
|
848
|
+
Object.defineProperty(exports, 'gitInit', {
|
|
849
|
+
enumerable: true,
|
|
850
|
+
get: function () {
|
|
851
|
+
return gitInit;
|
|
852
|
+
}
|
|
853
|
+
});
|
|
854
|
+
Object.defineProperty(exports, 'parseGitHubUrl', {
|
|
855
|
+
enumerable: true,
|
|
856
|
+
get: function () {
|
|
857
|
+
return parseGitHubUrl;
|
|
858
|
+
}
|
|
859
|
+
});
|