patchright-bun 1.58.1 → 1.58.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/README.md +225 -225
- package/ThirdPartyNotices.txt +5041 -5041
- package/cli.js +19 -19
- package/index.d.ts +17 -17
- package/index.js +17 -17
- package/index.mjs +18 -18
- package/jsx-runtime.js +42 -42
- package/jsx-runtime.mjs +21 -21
- package/lib/agents/agentParser.js +89 -89
- package/lib/agents/copilot-setup-steps.yml +34 -34
- package/lib/agents/generateAgents.js +348 -348
- package/lib/agents/playwright-test-coverage.prompt.md +31 -31
- package/lib/agents/playwright-test-generate.prompt.md +8 -8
- package/lib/agents/playwright-test-generator.agent.md +88 -88
- package/lib/agents/playwright-test-heal.prompt.md +6 -6
- package/lib/agents/playwright-test-healer.agent.md +55 -55
- package/lib/agents/playwright-test-plan.prompt.md +9 -9
- package/lib/agents/playwright-test-planner.agent.md +73 -73
- package/lib/common/config.js +282 -282
- package/lib/common/configLoader.js +344 -344
- package/lib/common/esmLoaderHost.js +104 -104
- package/lib/common/expectBundle.js +28 -28
- package/lib/common/expectBundleImpl.js +407 -407
- package/lib/common/fixtures.js +302 -302
- package/lib/common/globals.js +58 -58
- package/lib/common/ipc.js +60 -60
- package/lib/common/poolBuilder.js +85 -85
- package/lib/common/process.js +132 -132
- package/lib/common/suiteUtils.js +140 -140
- package/lib/common/test.js +321 -321
- package/lib/common/testLoader.js +101 -101
- package/lib/common/testType.js +298 -298
- package/lib/common/validators.js +68 -68
- package/lib/fsWatcher.js +67 -67
- package/lib/index.js +726 -726
- package/lib/internalsForTest.js +42 -42
- package/lib/isomorphic/events.js +77 -77
- package/lib/isomorphic/folders.js +30 -30
- package/lib/isomorphic/stringInternPool.js +69 -69
- package/lib/isomorphic/teleReceiver.js +521 -521
- package/lib/isomorphic/teleSuiteUpdater.js +157 -157
- package/lib/isomorphic/testServerConnection.js +225 -225
- package/lib/isomorphic/testServerInterface.js +16 -16
- package/lib/isomorphic/testTree.js +329 -329
- package/lib/isomorphic/types.d.js +16 -16
- package/lib/loader/loaderMain.js +59 -59
- package/lib/matchers/expect.js +311 -311
- package/lib/matchers/matcherHint.js +44 -44
- package/lib/matchers/matchers.js +383 -383
- package/lib/matchers/toBeTruthy.js +75 -75
- package/lib/matchers/toEqual.js +100 -100
- package/lib/matchers/toHaveURL.js +101 -101
- package/lib/matchers/toMatchAriaSnapshot.js +159 -159
- package/lib/matchers/toMatchSnapshot.js +342 -342
- package/lib/matchers/toMatchText.js +99 -99
- package/lib/mcp/browser/browserContextFactory.js +329 -329
- package/lib/mcp/browser/browserServerBackend.js +84 -84
- package/lib/mcp/browser/config.js +421 -421
- package/lib/mcp/browser/context.js +244 -244
- package/lib/mcp/browser/response.js +278 -278
- package/lib/mcp/browser/sessionLog.js +75 -75
- package/lib/mcp/browser/tab.js +343 -343
- package/lib/mcp/browser/tools/common.js +65 -65
- package/lib/mcp/browser/tools/console.js +46 -46
- package/lib/mcp/browser/tools/dialogs.js +60 -60
- package/lib/mcp/browser/tools/evaluate.js +61 -61
- package/lib/mcp/browser/tools/files.js +58 -58
- package/lib/mcp/browser/tools/form.js +63 -63
- package/lib/mcp/browser/tools/install.js +72 -72
- package/lib/mcp/browser/tools/keyboard.js +107 -107
- package/lib/mcp/browser/tools/mouse.js +107 -107
- package/lib/mcp/browser/tools/navigate.js +71 -71
- package/lib/mcp/browser/tools/network.js +63 -63
- package/lib/mcp/browser/tools/open.js +57 -57
- package/lib/mcp/browser/tools/pdf.js +49 -49
- package/lib/mcp/browser/tools/runCode.js +78 -78
- package/lib/mcp/browser/tools/screenshot.js +93 -93
- package/lib/mcp/browser/tools/snapshot.js +173 -173
- package/lib/mcp/browser/tools/tabs.js +67 -67
- package/lib/mcp/browser/tools/tool.js +47 -47
- package/lib/mcp/browser/tools/tracing.js +74 -74
- package/lib/mcp/browser/tools/utils.js +94 -94
- package/lib/mcp/browser/tools/verify.js +143 -143
- package/lib/mcp/browser/tools/wait.js +63 -63
- package/lib/mcp/browser/tools.js +84 -84
- package/lib/mcp/browser/watchdog.js +44 -44
- package/lib/mcp/config.d.js +16 -16
- package/lib/mcp/extension/cdpRelay.js +351 -351
- package/lib/mcp/extension/extensionContextFactory.js +76 -76
- package/lib/mcp/extension/protocol.js +28 -28
- package/lib/mcp/index.js +61 -61
- package/lib/mcp/log.js +35 -35
- package/lib/mcp/program.js +111 -111
- package/lib/mcp/sdk/exports.js +28 -28
- package/lib/mcp/sdk/http.js +152 -152
- package/lib/mcp/sdk/inProcessTransport.js +71 -71
- package/lib/mcp/sdk/server.js +223 -223
- package/lib/mcp/sdk/tool.js +47 -47
- package/lib/mcp/terminal/cli.js +296 -296
- package/lib/mcp/terminal/command.js +56 -56
- package/lib/mcp/terminal/commands.js +333 -333
- package/lib/mcp/terminal/daemon.js +129 -129
- package/lib/mcp/terminal/help.json +31 -31
- package/lib/mcp/terminal/helpGenerator.js +88 -88
- package/lib/mcp/terminal/socketConnection.js +80 -80
- package/lib/mcp/test/browserBackend.js +98 -98
- package/lib/mcp/test/generatorTools.js +122 -122
- package/lib/mcp/test/plannerTools.js +145 -145
- package/lib/mcp/test/seed.js +82 -82
- package/lib/mcp/test/streams.js +44 -44
- package/lib/mcp/test/testBackend.js +99 -99
- package/lib/mcp/test/testContext.js +285 -285
- package/lib/mcp/test/testTool.js +30 -30
- package/lib/mcp/test/testTools.js +108 -108
- package/lib/plugins/gitCommitInfoPlugin.js +198 -198
- package/lib/plugins/index.js +28 -28
- package/lib/plugins/webServerPlugin.js +237 -237
- package/lib/program.js +417 -417
- package/lib/reporters/base.js +634 -634
- package/lib/reporters/blob.js +138 -138
- package/lib/reporters/dot.js +99 -99
- package/lib/reporters/empty.js +32 -32
- package/lib/reporters/github.js +128 -128
- package/lib/reporters/html.js +633 -633
- package/lib/reporters/internalReporter.js +138 -138
- package/lib/reporters/json.js +254 -254
- package/lib/reporters/junit.js +232 -232
- package/lib/reporters/line.js +131 -131
- package/lib/reporters/list.js +253 -253
- package/lib/reporters/listModeReporter.js +69 -69
- package/lib/reporters/markdown.js +144 -144
- package/lib/reporters/merge.js +558 -558
- package/lib/reporters/multiplexer.js +112 -112
- package/lib/reporters/reporterV2.js +102 -102
- package/lib/reporters/teleEmitter.js +317 -317
- package/lib/reporters/versions/blobV1.js +16 -16
- package/lib/runner/dispatcher.js +530 -530
- package/lib/runner/failureTracker.js +72 -72
- package/lib/runner/lastRun.js +77 -77
- package/lib/runner/loadUtils.js +334 -334
- package/lib/runner/loaderHost.js +89 -89
- package/lib/runner/processHost.js +180 -180
- package/lib/runner/projectUtils.js +241 -241
- package/lib/runner/rebase.js +189 -189
- package/lib/runner/reporters.js +138 -138
- package/lib/runner/sigIntWatcher.js +96 -96
- package/lib/runner/storage.js +91 -91
- package/lib/runner/taskRunner.js +127 -127
- package/lib/runner/tasks.js +410 -410
- package/lib/runner/testGroups.js +125 -125
- package/lib/runner/testRunner.js +398 -398
- package/lib/runner/testServer.js +269 -269
- package/lib/runner/uiModeReporter.js +30 -30
- package/lib/runner/vcs.js +72 -72
- package/lib/runner/watchMode.js +396 -396
- package/lib/runner/workerHost.js +104 -104
- package/lib/third_party/pirates.js +62 -62
- package/lib/third_party/tsconfig-loader.js +103 -103
- package/lib/transform/babelBundle.js +46 -46
- package/lib/transform/babelBundleImpl.js +461 -461
- package/lib/transform/compilationCache.js +274 -274
- package/lib/transform/esmLoader.js +103 -103
- package/lib/transform/md.js +221 -221
- package/lib/transform/portTransport.js +67 -67
- package/lib/transform/transform.js +303 -303
- package/lib/util.js +400 -400
- package/lib/utilsBundle.js +50 -50
- package/lib/utilsBundleImpl.js +103 -103
- package/lib/worker/fixtureRunner.js +262 -262
- package/lib/worker/testInfo.js +536 -536
- package/lib/worker/testTracing.js +345 -345
- package/lib/worker/timeoutManager.js +174 -174
- package/lib/worker/util.js +31 -31
- package/lib/worker/workerMain.js +530 -530
- package/package.json +2 -2
- package/test.d.ts +18 -18
- package/test.js +24 -24
- package/test.mjs +34 -34
- package/types/test.d.ts +10251 -10251
- package/types/testReporter.d.ts +822 -822
|
@@ -1,348 +1,348 @@
|
|
|
1
|
-
"use strict";
|
|
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 __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
var generateAgents_exports = {};
|
|
30
|
-
__export(generateAgents_exports, {
|
|
31
|
-
ClaudeGenerator: () => ClaudeGenerator,
|
|
32
|
-
CopilotGenerator: () => CopilotGenerator,
|
|
33
|
-
OpencodeGenerator: () => OpencodeGenerator,
|
|
34
|
-
VSCodeGenerator: () => VSCodeGenerator
|
|
35
|
-
});
|
|
36
|
-
module.exports = __toCommonJS(generateAgents_exports);
|
|
37
|
-
var import_fs = __toESM(require("fs"));
|
|
38
|
-
var import_path = __toESM(require("path"));
|
|
39
|
-
var import_utilsBundle = require("patchright-core/lib/utilsBundle");
|
|
40
|
-
var import_utils = require("patchright-core/lib/utils");
|
|
41
|
-
var import_seed = require("../mcp/test/seed");
|
|
42
|
-
var import_agentParser = require("./agentParser");
|
|
43
|
-
async function loadAgentSpecs() {
|
|
44
|
-
const files = await import_fs.default.promises.readdir(__dirname);
|
|
45
|
-
return Promise.all(files.filter((file) => file.endsWith(".agent.md")).map((file) => (0, import_agentParser.parseAgentSpec)(import_path.default.join(__dirname, file))));
|
|
46
|
-
}
|
|
47
|
-
class ClaudeGenerator {
|
|
48
|
-
static async init(config, projectName, prompts) {
|
|
49
|
-
await initRepo(config, projectName, {
|
|
50
|
-
promptsFolder: prompts ? ".claude/prompts" : void 0
|
|
51
|
-
});
|
|
52
|
-
const agents = await loadAgentSpecs();
|
|
53
|
-
await import_fs.default.promises.mkdir(".claude/agents", { recursive: true });
|
|
54
|
-
for (const agent of agents)
|
|
55
|
-
await writeFile(`.claude/agents/${agent.name}.md`, ClaudeGenerator.agentSpec(agent), "\u{1F916}", "agent definition");
|
|
56
|
-
await writeFile(".mcp.json", JSON.stringify({
|
|
57
|
-
mcpServers: {
|
|
58
|
-
"playwright-test": {
|
|
59
|
-
command: "npx",
|
|
60
|
-
args: ["playwright", "run-test-mcp-server"]
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}, null, 2), "\u{1F527}", "mcp configuration");
|
|
64
|
-
initRepoDone();
|
|
65
|
-
}
|
|
66
|
-
static agentSpec(agent) {
|
|
67
|
-
const claudeToolMap = /* @__PURE__ */ new Map([
|
|
68
|
-
["search", ["Glob", "Grep", "Read", "LS"]],
|
|
69
|
-
["edit", ["Edit", "MultiEdit", "Write"]]
|
|
70
|
-
]);
|
|
71
|
-
function asClaudeTool(tool) {
|
|
72
|
-
const [first, second] = tool.split("/");
|
|
73
|
-
if (!second)
|
|
74
|
-
return (claudeToolMap.get(first) || [first]).join(", ");
|
|
75
|
-
return `mcp__${first}__${second}`;
|
|
76
|
-
}
|
|
77
|
-
const examples = agent.examples.length ? ` Examples: ${agent.examples.map((example) => `<example>${example}</example>`).join("")}` : "";
|
|
78
|
-
const lines = [];
|
|
79
|
-
const header = {
|
|
80
|
-
name: agent.name,
|
|
81
|
-
description: agent.description + examples,
|
|
82
|
-
tools: agent.tools.map((tool) => asClaudeTool(tool)).join(", "),
|
|
83
|
-
model: agent.model,
|
|
84
|
-
color: agent.color
|
|
85
|
-
};
|
|
86
|
-
lines.push(`---`);
|
|
87
|
-
lines.push(import_utilsBundle.yaml.stringify(header, { lineWidth: 1e5 }) + `---`);
|
|
88
|
-
lines.push("");
|
|
89
|
-
lines.push(agent.instructions);
|
|
90
|
-
return lines.join("\n");
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
class OpencodeGenerator {
|
|
94
|
-
static async init(config, projectName, prompts) {
|
|
95
|
-
await initRepo(config, projectName, {
|
|
96
|
-
defaultAgentName: "Build",
|
|
97
|
-
promptsFolder: prompts ? ".opencode/prompts" : void 0
|
|
98
|
-
});
|
|
99
|
-
const agents = await loadAgentSpecs();
|
|
100
|
-
for (const agent of agents) {
|
|
101
|
-
const prompt = [agent.instructions];
|
|
102
|
-
prompt.push("");
|
|
103
|
-
prompt.push(...agent.examples.map((example) => `<example>${example}</example>`));
|
|
104
|
-
await writeFile(`.opencode/prompts/${agent.name}.md`, prompt.join("\n"), "\u{1F916}", "agent definition");
|
|
105
|
-
}
|
|
106
|
-
await writeFile("opencode.json", OpencodeGenerator.configuration(agents), "\u{1F527}", "opencode configuration");
|
|
107
|
-
initRepoDone();
|
|
108
|
-
}
|
|
109
|
-
static configuration(agents) {
|
|
110
|
-
const opencodeToolMap = /* @__PURE__ */ new Map([
|
|
111
|
-
["search", ["ls", "glob", "grep", "read"]],
|
|
112
|
-
["edit", ["edit", "write"]]
|
|
113
|
-
]);
|
|
114
|
-
const asOpencodeTool = (tools, tool) => {
|
|
115
|
-
const [first, second] = tool.split("/");
|
|
116
|
-
if (!second) {
|
|
117
|
-
for (const tool2 of opencodeToolMap.get(first) || [first])
|
|
118
|
-
tools[tool2] = true;
|
|
119
|
-
} else {
|
|
120
|
-
tools[`${first}*${second}`] = true;
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
const result = {};
|
|
124
|
-
result["$schema"] = "https://opencode.ai/config.json";
|
|
125
|
-
result["mcp"] = {};
|
|
126
|
-
result["tools"] = {
|
|
127
|
-
"playwright*": false
|
|
128
|
-
};
|
|
129
|
-
result["agent"] = {};
|
|
130
|
-
for (const agent of agents) {
|
|
131
|
-
const tools = {};
|
|
132
|
-
result["agent"][agent.name] = {
|
|
133
|
-
description: agent.description,
|
|
134
|
-
mode: "subagent",
|
|
135
|
-
prompt: `{file:.opencode/prompts/${agent.name}.md}`,
|
|
136
|
-
tools
|
|
137
|
-
};
|
|
138
|
-
for (const tool of agent.tools)
|
|
139
|
-
asOpencodeTool(tools, tool);
|
|
140
|
-
}
|
|
141
|
-
result["mcp"]["playwright-test"] = {
|
|
142
|
-
type: "local",
|
|
143
|
-
command: ["npx", "playwright", "run-test-mcp-server"],
|
|
144
|
-
enabled: true
|
|
145
|
-
};
|
|
146
|
-
return JSON.stringify(result, null, 2);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
class CopilotGenerator {
|
|
150
|
-
static async init(config, projectName, prompts) {
|
|
151
|
-
await initRepo(config, projectName, {
|
|
152
|
-
defaultAgentName: "agent",
|
|
153
|
-
promptsFolder: prompts ? ".github/prompts" : void 0,
|
|
154
|
-
promptSuffix: "prompt"
|
|
155
|
-
});
|
|
156
|
-
const agents = await loadAgentSpecs();
|
|
157
|
-
await import_fs.default.promises.mkdir(".github/agents", { recursive: true });
|
|
158
|
-
for (const agent of agents)
|
|
159
|
-
await writeFile(`.github/agents/${agent.name}.agent.md`, CopilotGenerator.agentSpec(agent), "\u{1F916}", "agent definition");
|
|
160
|
-
await deleteFile(`.github/chatmodes/ \u{1F3AD} planner.chatmode.md`, "legacy planner chatmode");
|
|
161
|
-
await deleteFile(`.github/chatmodes/\u{1F3AD} generator.chatmode.md`, "legacy generator chatmode");
|
|
162
|
-
await deleteFile(`.github/chatmodes/\u{1F3AD} healer.chatmode.md`, "legacy healer chatmode");
|
|
163
|
-
await deleteFile(`.github/agents/ \u{1F3AD} planner.agent.md`, "legacy planner agent");
|
|
164
|
-
await deleteFile(`.github/agents/\u{1F3AD} generator.agent.md`, "legacy generator agent");
|
|
165
|
-
await deleteFile(`.github/agents/\u{1F3AD} healer.agent.md`, "legacy healer agent");
|
|
166
|
-
await VSCodeGenerator.appendToMCPJson();
|
|
167
|
-
const mcpConfig = { mcpServers: CopilotGenerator.mcpServers };
|
|
168
|
-
if (!import_fs.default.existsSync(".github/copilot-setup-steps.yml")) {
|
|
169
|
-
const yaml2 = import_fs.default.readFileSync(import_path.default.join(__dirname, "copilot-setup-steps.yml"), "utf-8");
|
|
170
|
-
await writeFile(".github/workflows/copilot-setup-steps.yml", yaml2, "\u{1F527}", "GitHub Copilot setup steps");
|
|
171
|
-
}
|
|
172
|
-
console.log("");
|
|
173
|
-
console.log("");
|
|
174
|
-
console.log(" \u{1F527} TODO: GitHub > Settings > Copilot > Coding agent > MCP configuration");
|
|
175
|
-
console.log("------------------------------------------------------------------");
|
|
176
|
-
console.log(JSON.stringify(mcpConfig, null, 2));
|
|
177
|
-
console.log("------------------------------------------------------------------");
|
|
178
|
-
initRepoDone();
|
|
179
|
-
}
|
|
180
|
-
static agentSpec(agent) {
|
|
181
|
-
const examples = agent.examples.length ? ` Examples: ${agent.examples.map((example) => `<example>${example}</example>`).join("")}` : "";
|
|
182
|
-
const lines = [];
|
|
183
|
-
const header = {
|
|
184
|
-
"name": agent.name,
|
|
185
|
-
"description": agent.description + examples,
|
|
186
|
-
"tools": agent.tools,
|
|
187
|
-
"model": "Claude Sonnet 4",
|
|
188
|
-
"mcp-servers": CopilotGenerator.mcpServers
|
|
189
|
-
};
|
|
190
|
-
lines.push(`---`);
|
|
191
|
-
lines.push(import_utilsBundle.yaml.stringify(header, { lineWidth: 1e5 }) + `---`);
|
|
192
|
-
lines.push("");
|
|
193
|
-
lines.push(agent.instructions);
|
|
194
|
-
lines.push("");
|
|
195
|
-
return lines.join("\n");
|
|
196
|
-
}
|
|
197
|
-
static {
|
|
198
|
-
this.mcpServers = {
|
|
199
|
-
"playwright-test": {
|
|
200
|
-
"type": "stdio",
|
|
201
|
-
"command": "npx",
|
|
202
|
-
"args": [
|
|
203
|
-
"playwright",
|
|
204
|
-
"run-test-mcp-server"
|
|
205
|
-
],
|
|
206
|
-
"tools": ["*"]
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
class VSCodeGenerator {
|
|
212
|
-
static async init(config, projectName) {
|
|
213
|
-
await initRepo(config, projectName, {
|
|
214
|
-
promptsFolder: void 0
|
|
215
|
-
});
|
|
216
|
-
const agents = await loadAgentSpecs();
|
|
217
|
-
const nameMap = /* @__PURE__ */ new Map([
|
|
218
|
-
["playwright-test-planner", " \u{1F3AD} planner"],
|
|
219
|
-
["playwright-test-generator", "\u{1F3AD} generator"],
|
|
220
|
-
["playwright-test-healer", "\u{1F3AD} healer"]
|
|
221
|
-
]);
|
|
222
|
-
await import_fs.default.promises.mkdir(".github/chatmodes", { recursive: true });
|
|
223
|
-
for (const agent of agents)
|
|
224
|
-
await writeFile(`.github/chatmodes/${nameMap.get(agent.name)}.chatmode.md`, VSCodeGenerator.agentSpec(agent), "\u{1F916}", "chatmode definition");
|
|
225
|
-
await VSCodeGenerator.appendToMCPJson();
|
|
226
|
-
initRepoDone();
|
|
227
|
-
}
|
|
228
|
-
static async appendToMCPJson() {
|
|
229
|
-
await import_fs.default.promises.mkdir(".vscode", { recursive: true });
|
|
230
|
-
const mcpJsonPath = ".vscode/mcp.json";
|
|
231
|
-
let mcpJson = {
|
|
232
|
-
servers: {},
|
|
233
|
-
inputs: []
|
|
234
|
-
};
|
|
235
|
-
try {
|
|
236
|
-
mcpJson = JSON.parse(import_fs.default.readFileSync(mcpJsonPath, "utf8"));
|
|
237
|
-
} catch {
|
|
238
|
-
}
|
|
239
|
-
if (!mcpJson.servers)
|
|
240
|
-
mcpJson.servers = {};
|
|
241
|
-
mcpJson.servers["playwright-test"] = {
|
|
242
|
-
type: "stdio",
|
|
243
|
-
command: "npx",
|
|
244
|
-
args: ["playwright", "run-test-mcp-server"]
|
|
245
|
-
};
|
|
246
|
-
await writeFile(mcpJsonPath, JSON.stringify(mcpJson, null, 2), "\u{1F527}", "mcp configuration");
|
|
247
|
-
}
|
|
248
|
-
static agentSpec(agent) {
|
|
249
|
-
const vscodeToolMap = /* @__PURE__ */ new Map([
|
|
250
|
-
["search", ["search/listDirectory", "search/fileSearch", "search/textSearch"]],
|
|
251
|
-
["read", ["search/readFile"]],
|
|
252
|
-
["edit", ["edit/editFiles"]],
|
|
253
|
-
["write", ["edit/createFile", "edit/createDirectory"]]
|
|
254
|
-
]);
|
|
255
|
-
const vscodeToolsOrder = ["edit/createFile", "edit/createDirectory", "edit/editFiles", "search/fileSearch", "search/textSearch", "search/listDirectory", "search/readFile"];
|
|
256
|
-
const vscodeMcpName = "playwright-test";
|
|
257
|
-
function asVscodeTool(tool) {
|
|
258
|
-
const [first, second] = tool.split("/");
|
|
259
|
-
if (second)
|
|
260
|
-
return `${vscodeMcpName}/${second}`;
|
|
261
|
-
return vscodeToolMap.get(first) || first;
|
|
262
|
-
}
|
|
263
|
-
const tools = agent.tools.map(asVscodeTool).flat().sort((a, b) => {
|
|
264
|
-
const indexA = vscodeToolsOrder.indexOf(a);
|
|
265
|
-
const indexB = vscodeToolsOrder.indexOf(b);
|
|
266
|
-
if (indexA === -1 && indexB === -1)
|
|
267
|
-
return a.localeCompare(b);
|
|
268
|
-
if (indexA === -1)
|
|
269
|
-
return 1;
|
|
270
|
-
if (indexB === -1)
|
|
271
|
-
return -1;
|
|
272
|
-
return indexA - indexB;
|
|
273
|
-
}).map((tool) => `'${tool}'`).join(", ");
|
|
274
|
-
const lines = [];
|
|
275
|
-
lines.push(`---`);
|
|
276
|
-
lines.push(`description: ${agent.description}.`);
|
|
277
|
-
lines.push(`tools: [${tools}]`);
|
|
278
|
-
lines.push(`---`);
|
|
279
|
-
lines.push("");
|
|
280
|
-
lines.push(agent.instructions);
|
|
281
|
-
for (const example of agent.examples)
|
|
282
|
-
lines.push(`<example>${example}</example>`);
|
|
283
|
-
lines.push("");
|
|
284
|
-
return lines.join("\n");
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
async function writeFile(filePath, content, icon, description) {
|
|
288
|
-
console.log(` ${icon} ${import_path.default.relative(process.cwd(), filePath)} ${import_utilsBundle.colors.dim("- " + description)}`);
|
|
289
|
-
await (0, import_utils.mkdirIfNeeded)(filePath);
|
|
290
|
-
await import_fs.default.promises.writeFile(filePath, content, "utf-8");
|
|
291
|
-
}
|
|
292
|
-
async function deleteFile(filePath, description) {
|
|
293
|
-
try {
|
|
294
|
-
if (!import_fs.default.existsSync(filePath))
|
|
295
|
-
return;
|
|
296
|
-
} catch {
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
console.log(` \u2702\uFE0F ${import_path.default.relative(process.cwd(), filePath)} ${import_utilsBundle.colors.dim("- " + description)}`);
|
|
300
|
-
await import_fs.default.promises.unlink(filePath);
|
|
301
|
-
}
|
|
302
|
-
async function initRepo(config, projectName, options) {
|
|
303
|
-
const project = (0, import_seed.seedProject)(config, projectName);
|
|
304
|
-
console.log(` \u{1F3AD} Using project "${project.project.name}" as a primary project`);
|
|
305
|
-
if (!import_fs.default.existsSync("specs")) {
|
|
306
|
-
await import_fs.default.promises.mkdir("specs");
|
|
307
|
-
await writeFile(import_path.default.join("specs", "README.md"), `# Specs
|
|
308
|
-
|
|
309
|
-
This is a directory for test plans.
|
|
310
|
-
`, "\u{1F4DD}", "directory for test plans");
|
|
311
|
-
}
|
|
312
|
-
let seedFile = await (0, import_seed.findSeedFile)(project);
|
|
313
|
-
if (!seedFile) {
|
|
314
|
-
seedFile = (0, import_seed.defaultSeedFile)(project);
|
|
315
|
-
await writeFile(seedFile, import_seed.seedFileContent, "\u{1F331}", "default environment seed file");
|
|
316
|
-
}
|
|
317
|
-
if (options.promptsFolder) {
|
|
318
|
-
await import_fs.default.promises.mkdir(options.promptsFolder, { recursive: true });
|
|
319
|
-
for (const promptFile of await import_fs.default.promises.readdir(__dirname)) {
|
|
320
|
-
if (!promptFile.endsWith(".prompt.md"))
|
|
321
|
-
continue;
|
|
322
|
-
const shortName = promptFile.replace(".prompt.md", "");
|
|
323
|
-
const fileName = options.promptSuffix ? `${shortName}.${options.promptSuffix}.md` : `${shortName}.md`;
|
|
324
|
-
const content = await loadPrompt(promptFile, {
|
|
325
|
-
defaultAgentName: "default",
|
|
326
|
-
...options,
|
|
327
|
-
seedFile: import_path.default.relative(process.cwd(), seedFile)
|
|
328
|
-
});
|
|
329
|
-
await writeFile(import_path.default.join(options.promptsFolder, fileName), content, "\u{1F4DD}", "prompt template");
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
function initRepoDone() {
|
|
334
|
-
console.log(" \u2705 Done.");
|
|
335
|
-
}
|
|
336
|
-
async function loadPrompt(file, params) {
|
|
337
|
-
const content = await import_fs.default.promises.readFile(import_path.default.join(__dirname, file), "utf-8");
|
|
338
|
-
return Object.entries(params).reduce((acc, [key, value]) => {
|
|
339
|
-
return acc.replace(new RegExp(`\\\${${key}}`, "g"), value);
|
|
340
|
-
}, content);
|
|
341
|
-
}
|
|
342
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
343
|
-
0 && (module.exports = {
|
|
344
|
-
ClaudeGenerator,
|
|
345
|
-
CopilotGenerator,
|
|
346
|
-
OpencodeGenerator,
|
|
347
|
-
VSCodeGenerator
|
|
348
|
-
});
|
|
1
|
+
"use strict";
|
|
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 __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var generateAgents_exports = {};
|
|
30
|
+
__export(generateAgents_exports, {
|
|
31
|
+
ClaudeGenerator: () => ClaudeGenerator,
|
|
32
|
+
CopilotGenerator: () => CopilotGenerator,
|
|
33
|
+
OpencodeGenerator: () => OpencodeGenerator,
|
|
34
|
+
VSCodeGenerator: () => VSCodeGenerator
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(generateAgents_exports);
|
|
37
|
+
var import_fs = __toESM(require("fs"));
|
|
38
|
+
var import_path = __toESM(require("path"));
|
|
39
|
+
var import_utilsBundle = require("patchright-bun-core/lib/utilsBundle");
|
|
40
|
+
var import_utils = require("patchright-bun-core/lib/utils");
|
|
41
|
+
var import_seed = require("../mcp/test/seed");
|
|
42
|
+
var import_agentParser = require("./agentParser");
|
|
43
|
+
async function loadAgentSpecs() {
|
|
44
|
+
const files = await import_fs.default.promises.readdir(__dirname);
|
|
45
|
+
return Promise.all(files.filter((file) => file.endsWith(".agent.md")).map((file) => (0, import_agentParser.parseAgentSpec)(import_path.default.join(__dirname, file))));
|
|
46
|
+
}
|
|
47
|
+
class ClaudeGenerator {
|
|
48
|
+
static async init(config, projectName, prompts) {
|
|
49
|
+
await initRepo(config, projectName, {
|
|
50
|
+
promptsFolder: prompts ? ".claude/prompts" : void 0
|
|
51
|
+
});
|
|
52
|
+
const agents = await loadAgentSpecs();
|
|
53
|
+
await import_fs.default.promises.mkdir(".claude/agents", { recursive: true });
|
|
54
|
+
for (const agent of agents)
|
|
55
|
+
await writeFile(`.claude/agents/${agent.name}.md`, ClaudeGenerator.agentSpec(agent), "\u{1F916}", "agent definition");
|
|
56
|
+
await writeFile(".mcp.json", JSON.stringify({
|
|
57
|
+
mcpServers: {
|
|
58
|
+
"playwright-test": {
|
|
59
|
+
command: "npx",
|
|
60
|
+
args: ["playwright", "run-test-mcp-server"]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}, null, 2), "\u{1F527}", "mcp configuration");
|
|
64
|
+
initRepoDone();
|
|
65
|
+
}
|
|
66
|
+
static agentSpec(agent) {
|
|
67
|
+
const claudeToolMap = /* @__PURE__ */ new Map([
|
|
68
|
+
["search", ["Glob", "Grep", "Read", "LS"]],
|
|
69
|
+
["edit", ["Edit", "MultiEdit", "Write"]]
|
|
70
|
+
]);
|
|
71
|
+
function asClaudeTool(tool) {
|
|
72
|
+
const [first, second] = tool.split("/");
|
|
73
|
+
if (!second)
|
|
74
|
+
return (claudeToolMap.get(first) || [first]).join(", ");
|
|
75
|
+
return `mcp__${first}__${second}`;
|
|
76
|
+
}
|
|
77
|
+
const examples = agent.examples.length ? ` Examples: ${agent.examples.map((example) => `<example>${example}</example>`).join("")}` : "";
|
|
78
|
+
const lines = [];
|
|
79
|
+
const header = {
|
|
80
|
+
name: agent.name,
|
|
81
|
+
description: agent.description + examples,
|
|
82
|
+
tools: agent.tools.map((tool) => asClaudeTool(tool)).join(", "),
|
|
83
|
+
model: agent.model,
|
|
84
|
+
color: agent.color
|
|
85
|
+
};
|
|
86
|
+
lines.push(`---`);
|
|
87
|
+
lines.push(import_utilsBundle.yaml.stringify(header, { lineWidth: 1e5 }) + `---`);
|
|
88
|
+
lines.push("");
|
|
89
|
+
lines.push(agent.instructions);
|
|
90
|
+
return lines.join("\n");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
class OpencodeGenerator {
|
|
94
|
+
static async init(config, projectName, prompts) {
|
|
95
|
+
await initRepo(config, projectName, {
|
|
96
|
+
defaultAgentName: "Build",
|
|
97
|
+
promptsFolder: prompts ? ".opencode/prompts" : void 0
|
|
98
|
+
});
|
|
99
|
+
const agents = await loadAgentSpecs();
|
|
100
|
+
for (const agent of agents) {
|
|
101
|
+
const prompt = [agent.instructions];
|
|
102
|
+
prompt.push("");
|
|
103
|
+
prompt.push(...agent.examples.map((example) => `<example>${example}</example>`));
|
|
104
|
+
await writeFile(`.opencode/prompts/${agent.name}.md`, prompt.join("\n"), "\u{1F916}", "agent definition");
|
|
105
|
+
}
|
|
106
|
+
await writeFile("opencode.json", OpencodeGenerator.configuration(agents), "\u{1F527}", "opencode configuration");
|
|
107
|
+
initRepoDone();
|
|
108
|
+
}
|
|
109
|
+
static configuration(agents) {
|
|
110
|
+
const opencodeToolMap = /* @__PURE__ */ new Map([
|
|
111
|
+
["search", ["ls", "glob", "grep", "read"]],
|
|
112
|
+
["edit", ["edit", "write"]]
|
|
113
|
+
]);
|
|
114
|
+
const asOpencodeTool = (tools, tool) => {
|
|
115
|
+
const [first, second] = tool.split("/");
|
|
116
|
+
if (!second) {
|
|
117
|
+
for (const tool2 of opencodeToolMap.get(first) || [first])
|
|
118
|
+
tools[tool2] = true;
|
|
119
|
+
} else {
|
|
120
|
+
tools[`${first}*${second}`] = true;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const result = {};
|
|
124
|
+
result["$schema"] = "https://opencode.ai/config.json";
|
|
125
|
+
result["mcp"] = {};
|
|
126
|
+
result["tools"] = {
|
|
127
|
+
"playwright*": false
|
|
128
|
+
};
|
|
129
|
+
result["agent"] = {};
|
|
130
|
+
for (const agent of agents) {
|
|
131
|
+
const tools = {};
|
|
132
|
+
result["agent"][agent.name] = {
|
|
133
|
+
description: agent.description,
|
|
134
|
+
mode: "subagent",
|
|
135
|
+
prompt: `{file:.opencode/prompts/${agent.name}.md}`,
|
|
136
|
+
tools
|
|
137
|
+
};
|
|
138
|
+
for (const tool of agent.tools)
|
|
139
|
+
asOpencodeTool(tools, tool);
|
|
140
|
+
}
|
|
141
|
+
result["mcp"]["playwright-test"] = {
|
|
142
|
+
type: "local",
|
|
143
|
+
command: ["npx", "playwright", "run-test-mcp-server"],
|
|
144
|
+
enabled: true
|
|
145
|
+
};
|
|
146
|
+
return JSON.stringify(result, null, 2);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
class CopilotGenerator {
|
|
150
|
+
static async init(config, projectName, prompts) {
|
|
151
|
+
await initRepo(config, projectName, {
|
|
152
|
+
defaultAgentName: "agent",
|
|
153
|
+
promptsFolder: prompts ? ".github/prompts" : void 0,
|
|
154
|
+
promptSuffix: "prompt"
|
|
155
|
+
});
|
|
156
|
+
const agents = await loadAgentSpecs();
|
|
157
|
+
await import_fs.default.promises.mkdir(".github/agents", { recursive: true });
|
|
158
|
+
for (const agent of agents)
|
|
159
|
+
await writeFile(`.github/agents/${agent.name}.agent.md`, CopilotGenerator.agentSpec(agent), "\u{1F916}", "agent definition");
|
|
160
|
+
await deleteFile(`.github/chatmodes/ \u{1F3AD} planner.chatmode.md`, "legacy planner chatmode");
|
|
161
|
+
await deleteFile(`.github/chatmodes/\u{1F3AD} generator.chatmode.md`, "legacy generator chatmode");
|
|
162
|
+
await deleteFile(`.github/chatmodes/\u{1F3AD} healer.chatmode.md`, "legacy healer chatmode");
|
|
163
|
+
await deleteFile(`.github/agents/ \u{1F3AD} planner.agent.md`, "legacy planner agent");
|
|
164
|
+
await deleteFile(`.github/agents/\u{1F3AD} generator.agent.md`, "legacy generator agent");
|
|
165
|
+
await deleteFile(`.github/agents/\u{1F3AD} healer.agent.md`, "legacy healer agent");
|
|
166
|
+
await VSCodeGenerator.appendToMCPJson();
|
|
167
|
+
const mcpConfig = { mcpServers: CopilotGenerator.mcpServers };
|
|
168
|
+
if (!import_fs.default.existsSync(".github/copilot-setup-steps.yml")) {
|
|
169
|
+
const yaml2 = import_fs.default.readFileSync(import_path.default.join(__dirname, "copilot-setup-steps.yml"), "utf-8");
|
|
170
|
+
await writeFile(".github/workflows/copilot-setup-steps.yml", yaml2, "\u{1F527}", "GitHub Copilot setup steps");
|
|
171
|
+
}
|
|
172
|
+
console.log("");
|
|
173
|
+
console.log("");
|
|
174
|
+
console.log(" \u{1F527} TODO: GitHub > Settings > Copilot > Coding agent > MCP configuration");
|
|
175
|
+
console.log("------------------------------------------------------------------");
|
|
176
|
+
console.log(JSON.stringify(mcpConfig, null, 2));
|
|
177
|
+
console.log("------------------------------------------------------------------");
|
|
178
|
+
initRepoDone();
|
|
179
|
+
}
|
|
180
|
+
static agentSpec(agent) {
|
|
181
|
+
const examples = agent.examples.length ? ` Examples: ${agent.examples.map((example) => `<example>${example}</example>`).join("")}` : "";
|
|
182
|
+
const lines = [];
|
|
183
|
+
const header = {
|
|
184
|
+
"name": agent.name,
|
|
185
|
+
"description": agent.description + examples,
|
|
186
|
+
"tools": agent.tools,
|
|
187
|
+
"model": "Claude Sonnet 4",
|
|
188
|
+
"mcp-servers": CopilotGenerator.mcpServers
|
|
189
|
+
};
|
|
190
|
+
lines.push(`---`);
|
|
191
|
+
lines.push(import_utilsBundle.yaml.stringify(header, { lineWidth: 1e5 }) + `---`);
|
|
192
|
+
lines.push("");
|
|
193
|
+
lines.push(agent.instructions);
|
|
194
|
+
lines.push("");
|
|
195
|
+
return lines.join("\n");
|
|
196
|
+
}
|
|
197
|
+
static {
|
|
198
|
+
this.mcpServers = {
|
|
199
|
+
"playwright-test": {
|
|
200
|
+
"type": "stdio",
|
|
201
|
+
"command": "npx",
|
|
202
|
+
"args": [
|
|
203
|
+
"playwright",
|
|
204
|
+
"run-test-mcp-server"
|
|
205
|
+
],
|
|
206
|
+
"tools": ["*"]
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
class VSCodeGenerator {
|
|
212
|
+
static async init(config, projectName) {
|
|
213
|
+
await initRepo(config, projectName, {
|
|
214
|
+
promptsFolder: void 0
|
|
215
|
+
});
|
|
216
|
+
const agents = await loadAgentSpecs();
|
|
217
|
+
const nameMap = /* @__PURE__ */ new Map([
|
|
218
|
+
["playwright-test-planner", " \u{1F3AD} planner"],
|
|
219
|
+
["playwright-test-generator", "\u{1F3AD} generator"],
|
|
220
|
+
["playwright-test-healer", "\u{1F3AD} healer"]
|
|
221
|
+
]);
|
|
222
|
+
await import_fs.default.promises.mkdir(".github/chatmodes", { recursive: true });
|
|
223
|
+
for (const agent of agents)
|
|
224
|
+
await writeFile(`.github/chatmodes/${nameMap.get(agent.name)}.chatmode.md`, VSCodeGenerator.agentSpec(agent), "\u{1F916}", "chatmode definition");
|
|
225
|
+
await VSCodeGenerator.appendToMCPJson();
|
|
226
|
+
initRepoDone();
|
|
227
|
+
}
|
|
228
|
+
static async appendToMCPJson() {
|
|
229
|
+
await import_fs.default.promises.mkdir(".vscode", { recursive: true });
|
|
230
|
+
const mcpJsonPath = ".vscode/mcp.json";
|
|
231
|
+
let mcpJson = {
|
|
232
|
+
servers: {},
|
|
233
|
+
inputs: []
|
|
234
|
+
};
|
|
235
|
+
try {
|
|
236
|
+
mcpJson = JSON.parse(import_fs.default.readFileSync(mcpJsonPath, "utf8"));
|
|
237
|
+
} catch {
|
|
238
|
+
}
|
|
239
|
+
if (!mcpJson.servers)
|
|
240
|
+
mcpJson.servers = {};
|
|
241
|
+
mcpJson.servers["playwright-test"] = {
|
|
242
|
+
type: "stdio",
|
|
243
|
+
command: "npx",
|
|
244
|
+
args: ["playwright", "run-test-mcp-server"]
|
|
245
|
+
};
|
|
246
|
+
await writeFile(mcpJsonPath, JSON.stringify(mcpJson, null, 2), "\u{1F527}", "mcp configuration");
|
|
247
|
+
}
|
|
248
|
+
static agentSpec(agent) {
|
|
249
|
+
const vscodeToolMap = /* @__PURE__ */ new Map([
|
|
250
|
+
["search", ["search/listDirectory", "search/fileSearch", "search/textSearch"]],
|
|
251
|
+
["read", ["search/readFile"]],
|
|
252
|
+
["edit", ["edit/editFiles"]],
|
|
253
|
+
["write", ["edit/createFile", "edit/createDirectory"]]
|
|
254
|
+
]);
|
|
255
|
+
const vscodeToolsOrder = ["edit/createFile", "edit/createDirectory", "edit/editFiles", "search/fileSearch", "search/textSearch", "search/listDirectory", "search/readFile"];
|
|
256
|
+
const vscodeMcpName = "playwright-test";
|
|
257
|
+
function asVscodeTool(tool) {
|
|
258
|
+
const [first, second] = tool.split("/");
|
|
259
|
+
if (second)
|
|
260
|
+
return `${vscodeMcpName}/${second}`;
|
|
261
|
+
return vscodeToolMap.get(first) || first;
|
|
262
|
+
}
|
|
263
|
+
const tools = agent.tools.map(asVscodeTool).flat().sort((a, b) => {
|
|
264
|
+
const indexA = vscodeToolsOrder.indexOf(a);
|
|
265
|
+
const indexB = vscodeToolsOrder.indexOf(b);
|
|
266
|
+
if (indexA === -1 && indexB === -1)
|
|
267
|
+
return a.localeCompare(b);
|
|
268
|
+
if (indexA === -1)
|
|
269
|
+
return 1;
|
|
270
|
+
if (indexB === -1)
|
|
271
|
+
return -1;
|
|
272
|
+
return indexA - indexB;
|
|
273
|
+
}).map((tool) => `'${tool}'`).join(", ");
|
|
274
|
+
const lines = [];
|
|
275
|
+
lines.push(`---`);
|
|
276
|
+
lines.push(`description: ${agent.description}.`);
|
|
277
|
+
lines.push(`tools: [${tools}]`);
|
|
278
|
+
lines.push(`---`);
|
|
279
|
+
lines.push("");
|
|
280
|
+
lines.push(agent.instructions);
|
|
281
|
+
for (const example of agent.examples)
|
|
282
|
+
lines.push(`<example>${example}</example>`);
|
|
283
|
+
lines.push("");
|
|
284
|
+
return lines.join("\n");
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
async function writeFile(filePath, content, icon, description) {
|
|
288
|
+
console.log(` ${icon} ${import_path.default.relative(process.cwd(), filePath)} ${import_utilsBundle.colors.dim("- " + description)}`);
|
|
289
|
+
await (0, import_utils.mkdirIfNeeded)(filePath);
|
|
290
|
+
await import_fs.default.promises.writeFile(filePath, content, "utf-8");
|
|
291
|
+
}
|
|
292
|
+
async function deleteFile(filePath, description) {
|
|
293
|
+
try {
|
|
294
|
+
if (!import_fs.default.existsSync(filePath))
|
|
295
|
+
return;
|
|
296
|
+
} catch {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
console.log(` \u2702\uFE0F ${import_path.default.relative(process.cwd(), filePath)} ${import_utilsBundle.colors.dim("- " + description)}`);
|
|
300
|
+
await import_fs.default.promises.unlink(filePath);
|
|
301
|
+
}
|
|
302
|
+
async function initRepo(config, projectName, options) {
|
|
303
|
+
const project = (0, import_seed.seedProject)(config, projectName);
|
|
304
|
+
console.log(` \u{1F3AD} Using project "${project.project.name}" as a primary project`);
|
|
305
|
+
if (!import_fs.default.existsSync("specs")) {
|
|
306
|
+
await import_fs.default.promises.mkdir("specs");
|
|
307
|
+
await writeFile(import_path.default.join("specs", "README.md"), `# Specs
|
|
308
|
+
|
|
309
|
+
This is a directory for test plans.
|
|
310
|
+
`, "\u{1F4DD}", "directory for test plans");
|
|
311
|
+
}
|
|
312
|
+
let seedFile = await (0, import_seed.findSeedFile)(project);
|
|
313
|
+
if (!seedFile) {
|
|
314
|
+
seedFile = (0, import_seed.defaultSeedFile)(project);
|
|
315
|
+
await writeFile(seedFile, import_seed.seedFileContent, "\u{1F331}", "default environment seed file");
|
|
316
|
+
}
|
|
317
|
+
if (options.promptsFolder) {
|
|
318
|
+
await import_fs.default.promises.mkdir(options.promptsFolder, { recursive: true });
|
|
319
|
+
for (const promptFile of await import_fs.default.promises.readdir(__dirname)) {
|
|
320
|
+
if (!promptFile.endsWith(".prompt.md"))
|
|
321
|
+
continue;
|
|
322
|
+
const shortName = promptFile.replace(".prompt.md", "");
|
|
323
|
+
const fileName = options.promptSuffix ? `${shortName}.${options.promptSuffix}.md` : `${shortName}.md`;
|
|
324
|
+
const content = await loadPrompt(promptFile, {
|
|
325
|
+
defaultAgentName: "default",
|
|
326
|
+
...options,
|
|
327
|
+
seedFile: import_path.default.relative(process.cwd(), seedFile)
|
|
328
|
+
});
|
|
329
|
+
await writeFile(import_path.default.join(options.promptsFolder, fileName), content, "\u{1F4DD}", "prompt template");
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function initRepoDone() {
|
|
334
|
+
console.log(" \u2705 Done.");
|
|
335
|
+
}
|
|
336
|
+
async function loadPrompt(file, params) {
|
|
337
|
+
const content = await import_fs.default.promises.readFile(import_path.default.join(__dirname, file), "utf-8");
|
|
338
|
+
return Object.entries(params).reduce((acc, [key, value]) => {
|
|
339
|
+
return acc.replace(new RegExp(`\\\${${key}}`, "g"), value);
|
|
340
|
+
}, content);
|
|
341
|
+
}
|
|
342
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
343
|
+
0 && (module.exports = {
|
|
344
|
+
ClaudeGenerator,
|
|
345
|
+
CopilotGenerator,
|
|
346
|
+
OpencodeGenerator,
|
|
347
|
+
VSCodeGenerator
|
|
348
|
+
});
|